如圖,共兩部分,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]