手寫softmax cross entropy的反向傳播推導過程以及反向傳播代碼。

如圖,共兩部分,softmax一部分,cross-entropy一部分,a1、a2、a3是輸入,y1、y2、y3是softmax的輸出,t1、t2、t3是label,圖中右側輸出Loss=cross entropy,輸入gradient=1。

正向傳播和反向傳播基本規則(可以參考cs231n的教程):

正向就是正常運算,沒什麼說的,正向的多對一操作,求和,正向的一對多,每一條線都傳播同樣的值。關於匯聚和分散的原則,正向反向一樣。

反向傳播操作:

加法,grad_c=1,c=a+b,則grad_a=grad_b=grad_c。

乘法,grad_c=1,c=a×b,則grad_a=grad_c*b和grad_b=grad_c*a。

log、取導數等,都按正常導數就好了,需要注意反向傳播求導過程的一個特點,y = w*x,dy/dw=x,所以想反向傳播去更新網絡參數w,前向傳播過程是需要保留這個x的,x指每一箇中間操作(例如圖中的exp(a1)、y1、t1logy1等等),不特指輸入數據x,所以關於神經網絡的內存佔用量等計算都少不了這些考量。

神經網絡兩大內存佔用:前向傳播的緩存,網絡自身的參數。

 

參考圖:

 

 

參考實現:

前向傳播的loss並沒有直接被後向傳播使用,直接使用前邊推導出的結果(y-t)作爲梯度。。

 

關於if-else,我剛開始也看蒙了,剛開始我以爲ifelse是爲了應對髒數據的容錯,後來測了一下,代碼是跑不通的。
所以這段代碼的意思是,如果size相等,說明你的label是onehot形式的,如果size不相等,說明你的label是index形式的,onehot直接相減就是誤差,index實際是按label去取數據,如果一樣,取出來就是1,就是誤差0(公式裏有個-1),如果label不一樣,就是誤差“2”,爲什麼,因爲這個錯誤的y沒被t指向,所以沒減1,且t指向的那個0被減1,所以是-1和+1兩個誤差,因爲這兩個誤差分屬於兩個index,也就是兩個分類,所以雖然-1++1=0,但是誤差不是0,onehot學的是分佈。

demo:

import numpy as np

a = np.array([
    [0,1,0,0],
    [0,0,0,1],
    [1,0,0,0],
])
t = np.array([
    [0,1,0,0],
    [0,0,1,0],
    [1,0,0,0],
])
t2 = np.array([1,2,0])
t3 = np.array([1,3,0])

print(a)
a[np.arange(3),t2] -= 1
a = a/3
print(a)
print(sum(a))

t是one-hot形式的target,t2、t3代表非one-hot形式的target,t2對應t,a相應的有一個數據不正確,會得到如下結果。

如果使用t3,結果就是全0。

[[0 1 0 0]
 [0 0 0 1]
 [1 0 0 0]]
[[ 0.          0.          0.          0.        ]
 [ 0.          0.         -0.33333333  0.33333333]
 [ 0.          0.          0.          0.        ]]
[ 0.          0.         -0.33333333  0.33333333]

 

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