在學(xué)習(xí)斯坦福大學(xué)的 cs231遇到了不少問題,這一篇主要是來自己對于神經(jīng)網(wǎng)絡(luò)中的梯度計算和其實現(xiàn)的python代碼。
目前我所學(xué)習(xí)到的有關(guān)梯度的計算的方法有兩種,第一種是根據(jù)網(wǎng)絡(luò)的反向傳播,可以得到網(wǎng)絡(luò)輸出的導(dǎo)數(shù)dout與輸入dx,dw,db的關(guān)系(這里所說的神經(jīng)網(wǎng)絡(luò)是比較簡單的全連接神經(jīng)網(wǎng)絡(luò),激活層為sotmax或者relu等函數(shù)),這一部分將在下篇blog里進(jìn)行推導(dǎo)計算;第二種就是利用基本公式(一個點號代表求一階導(dǎo)數(shù)):
一個簡單的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示(具體的不多解釋):

下面貼出代碼:
import numpy as np
from random import randrange
def eval_numerical_gradient(f,x,verbose=True,h=0.0001):
#計算f在x的梯度,其中f是接收一個參數(shù)的函數(shù),返回一個數(shù)字,如loss
fx = f(x)
grad = np.zeros_like(x)
it = np.nditer(x,flags=['multi_index'],op_flags=['readwrite'])
#當(dāng)?shù)鷽]有結(jié)束的時候
while not it.finished:
ix = it.multi_index
oldval = x[ix]
x[ix] = oldval+h
f1 = f(x)
x[ix] = oldval-h
f2 = f(x)
grad[ix] = (f1-f2)/(2*h)
if verbose:
print(ix,grad[ix])
it.iternext()
return grad
def eval_numerical_gradient_array(f,x,df,h=1e-5):
#f為接受numpy數(shù)組并返回numpy數(shù)組的函數(shù),并求f在x的梯度
grad = np.zeros_like(x)
it = np.nditer(x,flags=['multi_index'],op_flags=['readwrite'])
while not it.finished:
ix = it.multi_index
oldval = x[ix]
x[ix] = oldval + h
pos = f(x).copy()
x[ix] = oldval - h
neg = f(x).copy()
x[ix] = oldval
grad[ix] = np.sum((pos - neg) * df) / (2 * h)
it.iternext()
return grad
上述的兩個函數(shù)都是計算導(dǎo)數(shù),其中第一個函數(shù)eval_numerical_gradient是用來計算簡單函數(shù)的導(dǎo)數(shù),第二個函數(shù)eval_numerical_gradient_array則是用來計算矩陣中對應(yīng)元素的導(dǎo)數(shù)。第一個函數(shù)好理解,現(xiàn)在來看第二個函數(shù),原理一樣,但是會發(fā)現(xiàn)在計算導(dǎo)數(shù)的時候分子多乘了一個df,這個是為什么?
#eval_numerical_gradien
grad[ix] = (f1-f2)/(2*h)
#eval_numerical_gradient_array
grad[ix] = np.sum((pos - neg) * df) / (2 * h)
下面給出矩陣求導(dǎo)的公式公式來源:https://blog.csdn.net/xiezongsheng1990/article/details/86709575
個人覺得這個公式不太好理解,接下來詳細(xì)說明矩陣對元素的求導(dǎo)
矩陣中某個元素的梯度,分為兩個方向:x和y,因此矩陣某個元素的梯度也就由兩部分相加而成。

在這個例子里,上面矩陣導(dǎo)數(shù)的公式可以簡化為:即為該元素在y1和y2方向上的導(dǎo)數(shù)和。
grad[ix] = np.sum((pos - neg) * df) / (2 * h)
在這條執(zhí)行語句中,公式中的即為元素在x和y方向上所對應(yīng)的行向量和列向量的變化,因為只有一個元素變化了
,其他元素都沒有變化,所以
,
則為
。
個人理解:
矩陣對梯度的求導(dǎo)本質(zhì)上是一個復(fù)合求導(dǎo),即矩陣先對行/列向量求導(dǎo),行/列向量最后再對該元素進(jìn)行求導(dǎo)。
下篇預(yù)告:神經(jīng)網(wǎng)絡(luò)導(dǎo)數(shù)的推導(dǎo)并計算與本篇公式所得到的導(dǎo)數(shù)之間的誤差