1. 程式人生 > 實用技巧 >神經網路學習筆記4

神經網路學習筆記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

return x

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的引數

這裡引數x取net.W,定義一個計算損失函式的新函式f,把新定義的函式傳給numerical_gradient(f,x)


②學習演算法的實現

神經網路的步驟
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前進,使用訓練資料和測試資料評價的識別精度都提高了。