1. 程式人生 > >深度學習入門(三)構建簡單的兩層神經網路

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

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)

至此,我們的簡易的使用反向傳播演算法的兩層神經網路搭建和訓練就完成啦~