7、與神經網絡學習相關的參數(SGD、adam等)

1 參數的更新

四種方法:見圖

01 隨機梯度下降法:SGD

使用參數的梯度,沿着梯度方向更新參數,並且重複這個步驟多次,從而逐漸靠近最優參數,這個過程稱爲隨機梯度下降法
 

# 源代碼

class SGD:

    def _init_(self,lr=0.01):
        self.lr=lr
        
        def update(self,params,grads):  # params,和grads是字典型變量
 # 代碼段的update(params,grads),會被反覆調用按照params['W1']、grads['W1'], 
#分別保存了權重參數和他們的梯度。
            
            for k inparams.keys():
                params(key)-=self.lr*grads[key]

              

 見圖:SGD呈之字形移動, 這是一個相當低效的路徑。 

SGD的缺陷就是,如果函數的形狀非均向,比如延伸狀,搜索的路徑就會非常抵消。

低效率的最根本原因是,梯度的方向沒有指向最小的方向。


02 Momentum  方法

Mnmentum是“動量”的意思,和物理有關。

源代碼程序實現

class Momentum:

    def _init_(self,lr=0.01,momentum=0.9):
        
        self.lr=lr
        self.momentum=momentum
        self.v=None
    def update(self,params,grads):
        if self.v is None:
            self.v={}
            for key,val in params.items():
                self.v[key]=np.zeros_like(val)
                
        for key in params.keys():
            self.v[key]=self.momentum*self.v[key]-self.lr*grads[keys]
            params[key]+=self.v[key]


            
 實例變量v會保存物體的速度,初始化時候,v中什麼都不保存,但是當第一次調用update()的時候
v會以字典型變量的形式保存與參數結構相同的數據

  和SGD相比,可以更快地朝x軸方向靠近,減弱“之”字形的變動程度。

03 AdaGrad方法

在神經網絡的學習中,學習率(數學式中記爲y)的值很重要,學習率過小,會導致學習花費過多時間,反過來
學習率過大,則回到自學習發散而不能正確進行

學習率衰減(learning rate decay)

隨着學習的進行,使學習率逐漸減小。

AdaGrad:會爲每個元素適當地調整學習率,與此同時進行學習

 

源代碼:

class AdaGrad:
    
    def _init_(self,lr=0.01):
        self.lr=lr
        self.h=None
        
    def update(self,params,grads):
        if self.h is None:
            self.h={}
            for key,val in params.items():
                self.h[key]=np.zeros_like(val)
    for key in params.keys():
        self.h[key]+=grads[key]*grads[key]
        paras[key]-=self.lr*grads[key]/(np.sqrt(self.h[key])+le-7)


        

注意:最後一行加上了微小值le-7.這是爲了防止當self.h[key]中有0的時候,
將0用做除數的情況。在很多深度學習的框架中,這個微小值也可以設定爲參數。這裏選擇固定值

04 Adam 

Momentum 參照小球在碗中滾動的物理規則進行移動,AdaGrad爲參數的每個元素適當地調整更新不發。

Adam結合了前面兩種方法的優點,有望實現參數空間的高效搜索。

Adam會設置3個參數,一個是學習率(a),另外兩個是一次momentum係數B1爲0.9,B2爲0.999
             
現在多數的研究人員都喜歡Adam               
 

2、權重初始值

01 權重初始值不能是0

 02 隱藏層激活值得選擇 

# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt


def sigmoid(x):
    return 1 / (1 + np.exp(-x))


def ReLU(x):
    return np.maximum(0, x)


def tanh(x):
    return np.tanh(x)
    
input_data = np.random.randn(1000, 100)  # 高斯分佈隨機生成1000個數據
node_num = 100  # 各隱藏層的節點(神經元)數
hidden_layer_size = 5  # 隱藏層有5層
activations = {}  # 激活值的結果保存在這裏

x = input_data

for i in range(hidden_layer_size):
    if i != 0:
        x = activations[i-1]

    # 改變初始值進行實驗!
    # w = np.random.randn(node_num, node_num) * 1
    # w = np.random.randn(node_num, node_num) * 0.01
    # w = np.random.randn(node_num, node_num) * np.sqrt(1.0 / node_num)
    w = np.random.randn(node_num, node_num) * np.sqrt(2.0 / node_num)


    a = np.dot(x, w)


    # 將激活函數的種類也改變,來進行實驗!
    z = sigmoid(a)
    # z = ReLU(a)
    # z = tanh(a)

    activations[i] = z

# 繪製直方圖
for i, a in activations.items():
    plt.subplot(1, len(activations), i+1)
    plt.title(str(i+1) + "-layer")
    if i != 0: plt.yticks([], [])
    # plt.xlim(0.1, 1)
    # plt.ylim(0, 7000)
    plt.hist(a.flatten(), 30, range=(0,1))
plt.show()

03  relu的權重初始值

總結:

當激活函數使用relu時候,權重初始值使用He初始值,當激活函數爲sigmoid或者tanh等S型曲線函數時候,初始值使用Xavier初始值。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章