神經網路學習筆記4
神經網路
①梯度
梯度法:在學習時找到最優引數,使用梯度尋找函式最小值方法:函式取值從
梯度:表示各點處函式減少最多的方向,不一定指向最小值,但沿著方向可以最大限度減少函式的值。所以在尋找函式最小值的時候,以梯度資訊為線索決定前進方向。
學習率:在神經網路學習中,決定在一次學習中應該學習多少,以及在多大程度上更新引數
使用python實現梯度下降法
def gradient_descent(f,init_x,lr=0.01,step_num=100):
x=init_x
for i in range(setp_num):
grad=numrical_gradient(f(x),x)
x -= lr*grad
f是要進行優化的函式,init_x是初始值,lr是學習率learning rate,step_num是梯度法的重複次數
numerical_gradient(f,x)求函式的梯度,使用該計算的梯度乘以學習率得到的值更新操作,由step_num指定重複的次數。該函式還可以求函式最小值
學習率過大,會發散成一個比較大的值;學習率過小,基本上沒怎麼更新就結束。設定合適的學習率非常重要。
※神經網路的梯度
example:
對於一個2*3權重W的神經網路,損失用L表示
以一個簡單的神經網路為例,實現求梯度程式碼
實現一個名為simpleNet的類
numerical_gradient(f,x)引數是f函式,x為傳給f的引數
②學習演算法的實現
神經網路的步驟
1、mini-batch
從訓練資料中隨機選取一部分資料,稱之為mini-batch。目標是減少mini-batch的損失函式值。
2、計算梯度
為了減少mini-batch損失函式的值,需要求出各個權重引數的梯度,梯度表示損失函式的值減少最多的方向。
3、更新引數,將權重引數沿著梯度方向進行微小更新。
4、loop step 123
例項
1、實現手寫數字識別的神經網路
以2層神經網路為物件,使用mnist資料集進行學習。
權重使用符合高斯分佈的隨機數進行初始化,偏置使用0進行初始化
2、mini-batch實現
從訓練資料中隨機選擇一部分資料,使用梯度法更新引數
以minst資料集進行學習,TwoLayerNet類作為物件
設定mini-batch大小為100,每次需要從60000個訓練資料中隨機取出100個數據,然後對這包含100筆資料的mini-batch求梯度,使用隨機梯度下降法更新引數。梯度法的更新速度每更新一次,都對訓練資料計算損失函式的值,把值新增到陣列中。
可以發現,隨著學習的進行,損失函式值不斷減少。是正常的學習進行訊號,表示神經網路的權重引數正在逐漸擬合數據。
3、基於測試資料評價
必須確認是否能苟正確識別訓練資料意外的其他資料,確認是否會發生過擬合。
過擬合:訓練資料中的數字影象能正確辨別,但是不在訓練資料中的數字影象卻無法被識別。
每經過一個epoch都會記錄下訓練資料和測試資料的識別精度。
epoch:指學習中所有訓練資料均被使用過一次的更新次數
比如對於10000筆訓練資料,用大小為100筆資料的mini-batch進行學習,重複隨機梯度下降法100次,所有訓練資料都過了一遍,100次為一個epoch。
程式碼實現:
# coding: utf-8 import sys, os sys.path.append(os.pardir) # 為了匯入父目錄的檔案而進行的設定 import numpy as np import matplotlib.pyplot as plt from dataset.mnist import load_mnist from two_layer_net import TwoLayerNet # 讀入資料 (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True) #載入資料 network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10) #設定神經網路 #超引數設定 iters_num = 10000 # 適當設定迴圈的次數 train_size = x_train.shape[0] batch_size = 100 learning_rate = 0.1 train_loss_list = [] train_acc_list = [] test_acc_list = [] #平均每個epoch重複的次數 iter_per_epoch = max(train_size / batch_size, 1) for i in range(iters_num): #獲取mini-batch batch_mask = np.random.choice(train_size, batch_size) x_batch = x_train[batch_mask] t_batch = t_train[batch_mask] # 計算梯度 #grad = network.numerical_gradient(x_batch, t_batch) 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) #計算每個epoch的識別精度 if i % iter_per_epoch == 0: 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 | " + str(train_acc) + ", " + str(test_acc)) # 繪製圖形 markers = {'train': 'o', 'test': 's'} x = np.arange(len(train_acc_list)) plt.plot(x, train_acc_list, label='train acc') plt.plot(x, test_acc_list, label='test acc', linestyle='--') plt.xlabel("epochs") plt.ylabel("accuracy") plt.ylim(0, 1.0) plt.legend(loc='lower right') plt.show()
在例子中,每經過一個epoch就對所有的訓練資料和測試資料識別精度,並記錄結果。
從圖裡可以看出,隨著epoch前進,使用訓練資料和測試資料評價的識別精度都提高了。