1. 程式人生 > >dropout原理及python實現

dropout原理及python實現

dropout原理及python實現

標籤: 神經網路 python


dropout引入

我們都知道在訓練神經網路的時候,對於神經網路來說很容易產生過擬合現象,在解決神經網路的過擬合的時候,我們可以使用正則化進行防止過擬合現象的產生,除此之外我們也可以使用dropout來防止過擬合現象。

dropout如它的名字一樣,就是在進行傳播的時候刪除一些結點,這樣的話我們就可以降低網路的複雜性,這樣的話我們的網路就不會變的過擬合了。

dropout的實現

dropout主要在於在進行網路傳播的時候隨機關閉一二寫神經元,這裡的關鍵就在於如何關閉,我們可以把神經元的輸出乘0進行關閉,因為置位0後,這個神經元就不會起到作用了。具體步驟如下:

1、建立一個維度與本層神經元數目相同的矩陣 D [ l ] D^{[l]} .
2、根據概率(keep_prob)我們把 D

[ l ] D^{[l]} 中的元素設定為0或者1.
3、把本層的啟用函式的輸出 a [
l ] a^{[l]}
D [ l ] D^{[l]} 相乘(對應元素乘)作為新的輸出。
4、把新的輸出除以keep_prob(這一步不知道原因)。
5、在進行反向傳播的時候同樣進行這樣的操作,所以要把D儲存下來,這樣才能對被關閉的神經元對應的w不進行更新。

python程式碼實現 (主要是前向傳播以及反向傳播)

# 前向傳播,需要用到一個輸入x以及所有的權重以及偏執項,都在parameters這個字典裡面儲存
# 最後返回會返回一個caches裡面包含的 是各層的a和z,a[layers]就是最終的輸出
def forward(x,parameters,keep_prob = 0.5):
    a = []
    z = []
    d = []
    caches = {}
    a.append(x)
    z.append(x)
    # 輸入層不用刪除
    d.append(np.ones(x.shape))
    layers = len(parameters)//2
    # 前面都要用sigmoid
    for i in range(1,layers):
        z_temp =parameters["w"+str(i)].dot(a[i-1]) + parameters["b"+str(i)]
        a_temp = sigmoid(z_temp)
        # 1、建立一個維度與本層神經元數目相同的矩陣$D^{[l]}$.
        d_temp = np.random.rand(z_temp.shape[0],z_temp.shape[1])
        #2、根據概率(keep_prob)我們把$D^{[l]}$中的元素設定為0或者1.
        d_temp = d_temp < keep_prob
        3、把本層的啟用函式的輸出$a^{[l]}$ 與$D^{[l]}$相乘(對應元素乘)作為新的輸出。4、除keep_prob
        a_temp = (a_temp * d_temp)/keep_prob
        z.append(z_temp)
        a.append(a_temp)
        d.append(d_temp)
        
    # 最後一層不用sigmoid,也不用dropout
    z_temp = parameters["w"+str(layers)].dot(a[layers-1]) + parameters["b"+str(layers)]
    z.append(z_temp)
    a.append(z_temp)
    d.append(np.ones(z_temp.shape))
    
    caches["z"] = z
    caches["a"] = a
    # 記得儲存起來,因為反向傳播還會使用
    caches["d"] = d
    caches["keep_prob"] = keep_prob    
    return  caches,a[layers]   
    
    
# 反向傳播,parameters裡面儲存的是所有的各層的權重以及偏執,caches裡面儲存各層的a和z
# al是經過反向傳播後最後一層的輸出,y代表真實值 
# 返回的grades代表著誤差對所有的w以及b的導數
def backward(parameters,caches,al,y):
    layers = len(parameters)//2
    grades = {}
    m = y.shape[1]
    # 假設最後一層不經歷啟用函式
    # 就是按照上面的圖片中的公式寫的
    grades["dz"+str(layers)] = al - y
    grades["dw"+str(layers)] = grades["dz"+str(layers)].dot(caches["a"][layers-1].T) /m
    grades["db"+str(layers)] = np.sum(grades["dz"+str(layers)],axis = 1,keepdims = True) /m
    # 前面全部都是sigmoid啟用
    for i in reversed(range(1,layers)):
        da_temp = parameters["w"+str(i+1)].T.dot(grades["dz"+str(i+1)])
        5、在進行反向傳播的時候同樣進行這樣的操作,所以要把D儲存下來,這樣才能對被關閉的神經元對應的w不進行更新
        # 要記得乘上對應的開關caches["d"][i],這樣就保證了關閉的神經元在反向傳播的時候仍然是關閉的
        da_temp = (caches["d"][i] * da_temp)/caches["keep_prob"]
        grades["dz"+str(i)] = da_temp * sigmoid_prime(caches["z"][i])
        grades["dw"+str(i)] = grades["dz"+str(i)].dot(caches["a"][i-1].T)/m
        grades["db"+str(i)] = np.sum(grades["dz"+str(i)],axis = 1,keepdims = True) /m
    return grades   

整個網路的其他部分程式碼可以參考:https://blog.csdn.net/qq_28888837/article/details/84296673

參考:

https://blog.csdn.net/qq_28888837/article/details/84296673
https://zhuanlan.zhihu.com/p/29592806