天天看點

深度學習入門(三)建構簡單的兩層神經網絡

25天看完了吳恩達的機器學習以及《深度學習入門》和《tensorflow實戰》兩本書,吳恩達的學習課程隻學了理論知識,另外兩本書的代碼自己敲了一遍,感覺過的太快,趁着跑cGAN的時間把兩本書的知識點總結下,然後繼續深度學習的課程。歡迎小夥伴一起學習~

另外,本文先把架構搭好,後續會一直補充細節和知識點。

最後,本文參考的書是《深度學習入門》齋藤康毅著,十分推薦初學者使用。

​​本文的代碼位址​​

神經網絡學習的全貌圖

  1. 從訓練資料随機抽取一部分資料
  2. 帶入模型計算梯度
  3. 根據梯度更新參數
  4. 重複步驟1,2,3

兩層神經網絡實作

首先定義兩層神經網絡的類并初始化變量,類中包含了計算損失、準确率、梯度更新等函數。

這裡儲存參數使用的字典形式,建構的神經層使用的OrderDict,目的是儲存神經層的順序

class TwoLayerNet:
    def __init__(self, input_size, hidden_size, output_size, weight_init_std = 0.01):
        #初始化權重
        self.params = {}
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b2'] = np.zeros(output_size)
        #生成層
        self.layers = OrderedDict()
        self.layers['Affinel1'] = Affine(self.params['W1'], self.params['b1'])
        self.layers['Relu'] = Relu()
        self.layers['Affinel2'] = Affine(self.params['W2'], self.params['b2'])
        self.lastlayer = SoftmaxWithLoss()      

定義了預測函數、計算損失和準确率,前面提到,我們把每一神經層子產品化為一個類,類中主要包含了前向傳播forward()和反向傳播backward()

這裡主要用到全連接配接層和relu層兩個類,在文末給出代碼

def predict(self, x):
        for layer in self.layers.values(): #values需要有括号
            x = layer.forward(x)  # 調用forward計算前向傳播結果
        return x

    def loss(self, x, t):
        y = self.predict(x)
        return self.lastlayer.forward(y, t)

    def accuracy(self, x, t):
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        if t.ndim != 1:
            t = np.argmax(t, axis=1)
        accuracy = np.sum(y==t) / float(t.shape[0])
        return accuracy      

接下來是根據損失來計算梯度,反向傳播backward()

def gradient(self, x, t):
        # forward
        self.loss(x, t)
        # backward
        dout = 1
        dout = self.lastLayer.backward(dout)
        layers = list(self.layers.values())
        layers.reverse()
        for layer in layers:
            dout = layer.backward(dout)
        grads = {}
        grads['W1'], grads['b1'] = self.layers['Affine1'].dW, self.layers['Affine1'].db
        grads['W2'], grads['b2'] = self.layers['Affine2'].dW, self.layers['Affine2'].db
        return grads      
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True) # 這裡的load_mnist是導入資料的腳本

network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10) # 定義模型

iters_num = 1000 # 疊代的最大數目
train_size = x_train.shape[0]  # 訓練集的大小
batch_size = 100 # 每一個batch的大小
learning_rate = 0.1 #學習率

train_loss_list = []
train_acc_list = []
test_acc_list = []

iter_per_epoch = max(train_size / batch_size, 1) #一個epoch(紀元)的疊代次數

for i in range(iters_num):
    batch_mask = np.random.choice(train_size, batch_size) #随機抽取batch_size個資料的編号
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]

    grad = network.gradient(x_batch, t_batch) # 調用梯度計算函數

    for key in ('W1', 'b1', 'W2', 'b2'):  # 梯度更新
        network.params[key] -= learning_rate * grad[key]

    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)

    if i % iter_per_epoch: # 一個epoch後,計算訓練集和測試集的準确率
        train_acc = network.accuracy(x_train, t_train)
        test_acc = network.accuracy(x_test, t_test)
        train_acc_list.append(train_acc)
        test_acc_list.append(test_acc)
        print(train_acc, test_acc)      

繼續閱讀