亚洲综合伊人,成人欧美一区二区三区视频不卡,欧美日韩在线高清,日韩国产午夜一区二区三区,大胆美女艺术,一级毛片毛片**毛片毛片,你瞅啥图片

您當(dāng)前的位置是:  首頁(yè) > 新聞 > 專(zhuān)家觀點(diǎn) >
 首頁(yè) > 新聞 > 專(zhuān)家觀點(diǎn) >

李理:自動(dòng)梯度求解——cs231n的notes

2016-12-16 14:20:56   作者:   來(lái)源:CTI論壇   評(píng)論:0  點(diǎn)擊:


  本系列文章面向深度學(xué)習(xí)研發(fā)者,希望通過(guò)Image Caption Generation,一個(gè)有意思的具體任務(wù),深入淺出地介紹深度學(xué)習(xí)的知識(shí)。本系列文章涉及到很多深度學(xué)習(xí)流行的模型,如CNN,RNN/LSTM,Attention等。本文為第5篇。
  作者:李理
  目前就職于環(huán)信,即時(shí)通訊云平臺(tái)和全媒體智能客服平臺(tái),在環(huán)信從事智能客服和智能機(jī)器人相關(guān)工作,致力于用深度學(xué)習(xí)來(lái)提高智能機(jī)器人的性能。
  相關(guān)文章:
  Optimization
  這一部分內(nèi)容來(lái)自:CS231n Convolutional Neural Networks for Visual Recognition
  簡(jiǎn)介
  我們的目標(biāo):x是一個(gè)向量,f(x)是一個(gè)函數(shù),它的輸入是一個(gè)向量(或者認(rèn)為是多變量的函數(shù),這個(gè)輸入向量就是自變量),輸出是一個(gè)實(shí)數(shù)值。我們需要計(jì)算的是f對(duì)每一個(gè)自變量的導(dǎo)數(shù),然后把它們排成一個(gè)向量,也就是梯度。
\
  為什么要求這個(gè)呢?前面我們也講了,我們的神經(jīng)網(wǎng)絡(luò)的損失函數(shù)最終可以看成是權(quán)重weights和bias的函數(shù),我們的目標(biāo)就是調(diào)整這些參數(shù),使得損失函數(shù)最小。
  簡(jiǎn)單的表達(dá)式和梯度的解釋
  首先我們看一個(gè)很簡(jiǎn)單的函數(shù)f(x,y)=xy,求f對(duì)x和y的偏導(dǎo)數(shù)很簡(jiǎn)單:
\
  首先來(lái)看導(dǎo)數(shù)的定義:
\
  函數(shù)在某個(gè)點(diǎn)的導(dǎo)數(shù)就是函數(shù)曲線(xiàn)在這個(gè)點(diǎn)的斜率,也就是f(x)隨x的變化率。
  比如上面的例子,當(dāng)x=4,y=-3時(shí)f(x,y)=-12,f對(duì)x的偏導(dǎo)數(shù)
\
  也就是說(shuō),如果我們固定y=4,然后給x一個(gè)很小的變化h,那么f(x,y)的變化大約是-3*h。
  因此乘法的梯度就是
\
  同樣,加法的梯度更簡(jiǎn)單:
\
  最后一個(gè)簡(jiǎn)單函數(shù)是max函數(shù):
\
  這個(gè)導(dǎo)數(shù)是ReLU(x)=max(x,0)的導(dǎo)數(shù),其實(shí)也簡(jiǎn)單,如果x>=y,那么max(x,y)=x,則導(dǎo)數(shù)是1,否則max(x,y)=0,那么對(duì)x求導(dǎo)就是0.
  復(fù)雜表達(dá)式的鏈?zhǔn)椒▌t
  接下來(lái)看一個(gè)稍微復(fù)雜一點(diǎn)的函數(shù)f(x,y,z)=(x+y)z。我們引入一個(gè)中間變量q,f=qz,q=x+y,我們可以使用鏈?zhǔn)椒▌t求f對(duì)x和y的導(dǎo)數(shù)。
\
  對(duì)y的求導(dǎo)也是類(lèi)似的。
  下面是用python代碼來(lái)求f對(duì)x和y的導(dǎo)數(shù)在某一個(gè)點(diǎn)的值。
# 設(shè)置自變量的值
x = -2; y = 5; z = -4

# “前向”計(jì)算f
q = x + y # q becomes 3
f = q * z # f becomes -12

# 從“后”往前“反向”計(jì)算
# 首先是 f = q * z
dfdz = q # 因?yàn)閐f/dz = q, 所以f對(duì)z的梯度是 3
dfdq = z # 因?yàn)閐f/dq = z, 所以f對(duì)q的梯度是 -4
# 然后 q = x + y
dfdx = 1.0 * dfdq # 因?yàn)閐q/dx = 1,所以使用鏈?zhǔn)椒▌t計(jì)算dfdx=-4
dfdy = 1.0 * dfdq # 因?yàn)閐q/dy = 1,所以使用鏈?zhǔn)椒▌t計(jì)算dfdy=-4
  我們也可以用計(jì)算圖來(lái)表示和計(jì)算:
\
  綠色的值是feed forward的結(jié)果,而紅色的值是backprop的結(jié)果。
  不過(guò)我覺(jué)得cs231n課程的這個(gè)圖沒(méi)有上面blog的清晰,原因是雖然它標(biāo)示出來(lái)了最終的梯度,但是沒(méi)有標(biāo)示出local gradient,我在下面會(huì)畫(huà)出完整的計(jì)算過(guò)程。
  反向傳播算法的直覺(jué)解釋
  我們?nèi)绻延?jì)算圖的每一個(gè)點(diǎn)看成一個(gè)“門(mén)”(或者一個(gè)模塊),或者說(shuō)一個(gè)函數(shù)。它有一個(gè)輸入(向量),也有一個(gè)輸出(標(biāo)量)。對(duì)于一個(gè)門(mén)來(lái)說(shuō)有兩個(gè)計(jì)算,首先是根據(jù)輸入,計(jì)算輸出,這個(gè)一般很容易。還有一種計(jì)算就是求輸出對(duì)每一個(gè)輸入的偏導(dǎo)數(shù),或者說(shuō)輸出對(duì)輸入向量的”局部“梯度(local gradient)。一個(gè)復(fù)雜計(jì)算圖(神經(jīng)網(wǎng)絡(luò))的計(jì)算首先就是前向計(jì)算,然后反向計(jì)算,反向計(jì)算公式可能看起來(lái)很復(fù)雜,但是如果在計(jì)算圖上其實(shí)就是簡(jiǎn)單的用local gradient乘以從后面?zhèn)鬟^(guò)來(lái)的gradient,然后加起來(lái)。
  Sigmoid模塊的例子
  接下來(lái)我們看一個(gè)更復(fù)雜的例子:
\
  這個(gè)函數(shù)是一個(gè)比較復(fù)雜的復(fù)合函數(shù),但是構(gòu)成它的基本函數(shù)是如下4個(gè)簡(jiǎn)單函數(shù):
\
  下面是用計(jì)算圖畫(huà)出這個(gè)計(jì)算過(guò)程:
\
  這個(gè)圖有4種gate,加法,乘法,指數(shù)和倒數(shù)。加法有加一個(gè)常數(shù)和兩個(gè)變量相加,乘法也是一樣。
  上圖綠色的值是前向計(jì)算的結(jié)果,而紅色的值是反向計(jì)算的結(jié)果,localgraident并沒(méi)有標(biāo)示出來(lái),所以看起來(lái)可能有些跳躍,下面我在紙上詳細(xì)的分解了其中的步驟,請(qǐng)讀者跟著下圖自己動(dòng)手計(jì)算一遍。
\
  上圖就是前向計(jì)算的過(guò)程,比較簡(jiǎn)單。
\
  第二個(gè)圖是計(jì)算local gradient,對(duì)于兩個(gè)輸入的乘法和加法,local gradient也是兩個(gè)值,local gradient的值我是放到圖的節(jié)點(diǎn)上了。
\
  第三個(gè)圖是具體計(jì)算一個(gè)乘法的local gradient的過(guò)程,因?yàn)樯蠄D可能看不清,所以單獨(dú)放大了這一步。
\
  最后計(jì)算真正的梯度,是把local gradient乘以來(lái)自上一步的gradient。不過(guò)這個(gè)例子一個(gè)節(jié)點(diǎn)只有一個(gè)輸出,如果有多個(gè)的話(huà),梯度是加起來(lái)的,可以參考1.4的
\
  上面我們看到把
\
  分解成最基本的加法,乘法,導(dǎo)數(shù)和指數(shù)函數(shù),但是我們也可以不分解這么細(xì)。之前我們也學(xué)習(xí)過(guò)了sigmoid函數(shù),那么我們可以這樣分解:
\
  σ(x)σ(x)的導(dǎo)數(shù)我們之前已經(jīng)推導(dǎo)過(guò)一次了,這里再列一下:
\
  因此我們可以把后面一長(zhǎng)串的gate”壓縮“成一個(gè)gate:
\
  我們來(lái)比較一下,之前前向計(jì)算σ(x)σ(x)需要一次乘法,一次exp,一次加法導(dǎo)數(shù);而反向計(jì)算需要分別計(jì)算這4個(gè)gate的導(dǎo)數(shù)。
  而壓縮后前向計(jì)算是一樣的,但是反向計(jì)算可以”利用“前向計(jì)算的結(jié)果
\
  這只需要一次減法和一次乘法!當(dāng)然如果不能利用前向的結(jié)果,我們?nèi)绻枰匦掠?jì)算σ(x)σ(x),那么壓縮其實(shí)沒(méi)有什么用處。能壓縮的原因在于σ函數(shù)導(dǎo)數(shù)的特殊形式。而神經(jīng)網(wǎng)絡(luò)的關(guān)鍵問(wèn)題是在訓(xùn)練,訓(xùn)練性能就取決于這些細(xì)節(jié)。如果是我們自己來(lái)實(shí)現(xiàn)反向傳播算法,我們就需要利用這樣的特性。而如果是使用工具,那么就依賴(lài)于工具的優(yōu)化水平了。
  下面我們用代碼來(lái)實(shí)現(xiàn)一下:
w = [2,-3,-3] # assume some random weights and data
x = [-1, -2]

# forward pass
dot = w[0]*x[0] + w[1]*x[1] + w[2]
f = 1.0 / (1 + math.exp(-dot)) # sigmoid function

# backward pass through the neuron (backpropagation)
ddot = (1 - f) * f # gradient on dot variable, using the sigmoid gradient derivation
dx = [w[0] * ddot, w[1] * ddot] # backprop into x
dw = [x[0] * ddot, x[1] * ddot, 1.0 * ddot] # backprop into w
# we're done! we have the gradients on the inputs to the circuit
  上面的例子用了一個(gè)小技巧,就是所謂的stagedbackpropagation,說(shuō)白了就是給中間的計(jì)算節(jié)點(diǎn)起一個(gè)名字。比如dot。為了讓大家熟悉這種技巧,下面有一個(gè)例子。
  Staged computation練習(xí)
\
  我們用代碼來(lái)計(jì)算這個(gè)函數(shù)對(duì)x和y的梯度在某一點(diǎn)的值
  前向計(jì)算
x = 3 # example values
y = -4

# forward pass
sigy = 1.0 / (1 + math.exp(-y)) # 分子上的sigmoid   #(1)
num = x + sigy # 分子                               #(2)
sigx = 1.0 / (1 + math.exp(-x)) # 分母上的sigmoid #(3)
xpy = x + y                                              #(4)
xpysqr = xpy**2                                          #(5)
den = sigx + xpysqr # 分母                        #(6)
invden = 1.0 / den                                       #(7)
f = num * invden # done!                                 #(8)
  反向計(jì)算
# backprop f = num * invden
dnum = invden # gradient on numerator                             #(8)
dinvden = num                                                     #(8)
# backprop invden = 1.0 / den 
dden = (-1.0 / (den**2)) * dinvden                                #(7)
# backprop den = sigx + xpysqr
dsigx = (1) * dden                                                #(6)
dxpysqr = (1) * dden                                              #(6)
# backprop xpysqr = xpy**2
dxpy = (2 * xpy) * dxpysqr                                        #(5)
# backprop xpy = x + y
dx = (1) * dxpy                                                   #(4)
dy = (1) * dxpy                                                   #(4)
# backprop sigx = 1.0 / (1 + math.exp(-x))
dx += ((1 - sigx) * sigx) * dsigx # Notice += !! See notes below  #(3)
# backprop num = x + sigy
dx += (1) * dnum                                                  #(2)
dsigy = (1) * dnum                                                #(2)
# backprop sigy = 1.0 / (1 + math.exp(-y))
dy += ((1 - sigy) * sigy) * dsigy                                 #(1)
# done! phew
  需要注意的兩點(diǎn):1.前向的結(jié)果都要保存下來(lái),反向的時(shí)候要用的。2.如果某個(gè)變量有多個(gè)出去的邊,第一次是等于,第二次就是+=,因?yàn)槲覀円巡煌鋈c(diǎn)的梯度加起來(lái)。
  下面我們來(lái)逐行分析反向計(jì)算:
  (8)f=num*invden
  local gradient
\
  而上面?zhèn)鬟^(guò)來(lái)的梯度是1,所以dnum=1*invden。注意變量的命名規(guī)則,df/dnum就命名為dnum【省略了df,因?yàn)槟J(rèn)我們是求f對(duì)所有變量的偏導(dǎo)數(shù)】
  同理:dinvden=num
  (7)invden=1.0/den
  local gradient是(-1.0/(den**2)),然后乘以上面來(lái)的dinvden
  (6)den=sigx+xpysqr
  這個(gè)函數(shù)有兩個(gè)變量sigx和xpysqr,所以需要計(jì)算兩個(gè)local梯度,然后乘以dden
  加法的local梯度是1,所以就是(1)*dden
  (5)xpysqr=xpy**2
  localgradient是2*xpy,再乘以dxpysqr
  (4)xpy=x+y
  還是一個(gè)加法,local gradient是1,所以dx和dy都是dxpy乘1
  (3)sigx=1.0/(1+math.exp(-x))
  這是sigmoid函數(shù),local gradient是(1-sigx)*sigx,再乘以dsigx。
  不過(guò)需要注意的是這是dx的第二次出現(xiàn),所以是+=,表示來(lái)自不同路徑反向傳播過(guò)來(lái)給x的梯度值
  (2)num=x+sigy
  還是個(gè)很簡(jiǎn)單的加法,local gradient是1.需要注意的是dx是+=,理由同上。
  (1)sigy=1.0/(1+math.exp(-y))
  最后是sigmoid(y)和前面(3)一樣的。
  請(qǐng)仔細(xì)閱讀上面反向計(jì)算的每一步代碼,確保自己理解了之后再往下閱讀。
  梯度的矩陣運(yùn)算
  前面都是對(duì)一個(gè)標(biāo)量的計(jì)算,在實(shí)際實(shí)現(xiàn)時(shí)用矩陣運(yùn)算一次計(jì)算一層的所有梯度會(huì)更加高效。因?yàn)榫仃嚦艘韵蛄亢拖蛄砍艘韵蛄慷伎梢钥闯鼍仃嚦艘跃仃嚨奶厥庑问,所以下面我們介紹矩陣乘法怎么求梯度。
  首先我們得定義什么叫矩陣對(duì)矩陣的梯度!
  我查閱了很多資料,也沒(méi)找到哪里有矩陣對(duì)矩陣的梯度的定義,如果哪位讀者知道,請(qǐng)告訴我,謝謝!唯一比較接近的是Andrew Ng的課程cs294的背景知識(shí)介紹的slides linalg的4.1節(jié)定義了gradient of Matrix,關(guān)于矩陣對(duì)矩陣的梯度我會(huì)有一個(gè)猜測(cè)性的解釋?zhuān)赡軙?huì)有問(wèn)題。
  首先介紹graiden to fmatrix
  假設(shè)f:Rm×n→R是一個(gè)函數(shù),輸入是一個(gè)m×n的實(shí)數(shù)值矩陣,輸出是一個(gè)實(shí)數(shù)。那么f對(duì)A的梯度是如下定義的:
\
  看起來(lái)定義很復(fù)雜?其實(shí)很簡(jiǎn)單,我們把f看成一個(gè)mn個(gè)自變量的函數(shù),因此我們可以求f對(duì)這mn個(gè)自變量的偏導(dǎo)數(shù),然后把它們排列成m*n的矩陣就行了。為什么要多此一舉把變量拍成矩陣把他們的偏導(dǎo)數(shù)也排成矩陣?想想我們之前的神經(jīng)網(wǎng)絡(luò)的weights矩陣,這是很自然的定義,同時(shí)我們需要計(jì)算loss對(duì)weights矩陣的每一個(gè)變量的偏導(dǎo)數(shù),寫(xiě)出這樣的形式計(jì)算起來(lái)比較方便。
  那么什么是矩陣對(duì)矩陣的梯度呢?我們先看實(shí)際神經(jīng)網(wǎng)絡(luò)的一個(gè)計(jì)算情況。對(duì)于全連接的神經(jīng)網(wǎng)絡(luò),我們有一個(gè)矩陣乘以向量D=WxD=Wx【我們這里把向量x看成矩陣】,F(xiàn)在我們需要計(jì)算loss對(duì)某一個(gè) WijWij的偏導(dǎo)數(shù),根據(jù)我們之前的計(jì)算圖, WijWij有多少條出邊,那么就有多少個(gè)要累加的梯度乘以local梯度。
  假設(shè)W是m×n的矩陣,x是n×p的矩陣,則D是m×p的矩陣
\
  根據(jù)矩陣乘法的定義
\
  我們可以計(jì)算:
\
  請(qǐng)仔細(xì)理解上面這一步,如果k≠i,則不論s是什么,WksWij不是同一個(gè)變量,所以導(dǎo)數(shù)就是0;如果k=i,sWisxsl=xjl,也就求和的下標(biāo)s取j的時(shí)候有WijWij。
  因此
\
  上面計(jì)算了loss對(duì)一個(gè)Wijj的偏導(dǎo)數(shù),如果把它寫(xiě)成矩陣形式就是:
\
  前面我們推導(dǎo)出了對(duì)Wij的偏導(dǎo)數(shù)的計(jì)算公式,下面我們把它寫(xiě)成矩陣乘法的形式并驗(yàn)證【證明】它。
\
  為什么可以寫(xiě)成這樣的形式呢?
\
  上面的推導(dǎo)似乎很復(fù)雜,但是我們只要能記住就行,記法也很簡(jiǎn)單——把矩陣都變成最特殊的11的矩陣(也就是標(biāo)量,一個(gè)實(shí)數(shù))。D=wx,這個(gè)導(dǎo)數(shù)很容易吧,對(duì)w求導(dǎo)就是local gradientx,然后乘以得到dW=dDx;同理dx=dDW。
  但是等等,剛才那個(gè)公式里還有矩陣的轉(zhuǎn)置,這個(gè)怎么記?這里有一個(gè)小技巧,就是矩陣乘法的條件,兩個(gè)矩陣能相乘他們的大小必須匹配,比如D=W x,W是m n,x是n p,也就是第二個(gè)矩陣的行數(shù)等于第一個(gè)的列數(shù)。
  現(xiàn)在我們已經(jīng)知道dW是dD”乘以“x了,dW的大小和W一樣是m n,而dD和D一樣是m p,而x是n p,那么為了得到一個(gè)mn的矩陣,唯一的辦法就是dD∗xT
  同理dx是np,dD是mp,W是m*n,唯一的乘法就是WT∗dD 
  下面是用python代碼來(lái)演示,numpy的dot就是矩陣乘法,可以用numpy.dot(A,B),也可以直接調(diào)用ndarray的dot函數(shù)——A。dot(B):
# forward pass
W = np.random.randn(5, 10)
X = np.random.randn(10, 3)
D = W.dot(X)

# now suppose we had the gradient on D from above in the circuit
dD = np.random.randn(*D.shape) # same shape as D
dW = dD.dot(X.T) #.T gives the transpose of the matrix
dX = W.T.dot(dD)
  至此,本系列文章的第5部分告一段落。在接下來(lái)的文章中,作者將為大家詳細(xì)講述關(guān)于常見(jiàn)的深度學(xué)習(xí)框架/工具的使用方法、使用自動(dòng)求導(dǎo)來(lái)實(shí)現(xiàn)多層神經(jīng)網(wǎng)絡(luò)等內(nèi)容,敬請(qǐng)期待。

專(zhuān)題

文水县| 凤阳县| 大宁县| 子长县| 平利县| 耒阳市| 崇义县| 长岛县| 县级市| 师宗县| 隆回县| 丹江口市| 黄陵县| 桂平市| 巴马| 宜昌市| 昌宁县| 南郑县| 双柏县| 临桂县| 竹溪县| 简阳市| 伊金霍洛旗| 长泰县| 中牟县| 吉木乃县| 炉霍县| 永靖县| 太湖县| 甘南县| 娄底市| 永安市| 富阳市| 正阳县| 衡阳市| 张掖市| 临潭县| 金溪县| 板桥市| 紫云| 应用必备|