本文介紹關(guān)于GoogLeNet的續(xù)作响鹃,習(xí)慣稱為inception v2犬性,如下:
- [v2] Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift凉翻,top5 error 4.8%
這篇文章做出的貢獻(xiàn)不是一般的大,它提出了Batch Normalization(BN),以至于網(wǎng)上關(guān)于它的介紹鋪天蓋地,但中文優(yōu)秀原創(chuàng)沒幾個耙蔑,都是轉(zhuǎn)載來轉(zhuǎn)載去,挑幾個好的比如:這個障斋、這個纵潦、這個徐鹤。我之前也寫過一個談?wù)凾ensorflow的Batch Normalization垃环,講了講BN在Tensorflow中的實現(xiàn)。
前人關(guān)于BN介紹的已經(jīng)太詳細(xì)了返敬,我就不再重復(fù)的了遂庄。本文就是想講一講BN的反向傳播,BN需要調(diào)節(jié)的參數(shù)有兩個劲赠,γ 和 β涛目,反向傳播的計算方式就是下面這張圖:
又是令人作嘔的公式。
幾乎所有介紹BN的文章都把這部分略過了凛澎,估計是怕講不清楚霹肝,或者作者根本就不明白也不想深究。BN的理念很好理解塑煎,它的優(yōu)良效果也很好理解沫换,可BN的訓(xùn)練到底是怎么回事?怎么反向傳播最铁?Szegedy在論文原文里也只是一句話帶過了:
During training we need to backpropagate the gradient of loss ? through this transformation, as well as compute the gradients with respect to the parameters of the BN transform. We use chain rule...
上面那一坨公式對于深度學(xué)習(xí)的老鳥們應(yīng)該不會構(gòu)成理解障礙讯赏,但對于接觸不久的人群垮兑,簡直就是天書!鑒于此漱挎,參考xiaia的cs231n_2016_winter作業(yè)系枪,捋一捋BN的反向傳播到底是怎么實現(xiàn)的,好有個直觀理解磕谅。
下面的介紹基于cs231n_2016_winter/assignment2的全連接網(wǎng)絡(luò)私爷,隱藏層5個,每個100個神經(jīng)元(hidden_dims = [100, 100, 100, 100, 100])膊夹,激活函數(shù)ReLU当犯,每個隱藏層激活函數(shù)前都加了BN層,輸出層是softmax-10割疾,optimizer是adam嚎卫。
Batch Normalization反向傳播實現(xiàn)
根據(jù)上面那一坨公式,寫出來的代碼是這樣子的:
def batchnorm_backward(dout, cache):
"""
Backward pass for batch normalization.
For this implementation, you should write out a computation graph for
batch normalization on paper and propagate gradients backward through
intermediate nodes.
Inputs:
- dout: Upstream derivatives, of shape (N, D)
- cache: Variable of intermediates from batchnorm_forward.
Returns a tuple of:
- dx: Gradient with respect to inputs x, of shape (N, D)
- dgamma: Gradient with respect to scale parameter gamma, of shape (D,)
- dbeta: Gradient with respect to shift parameter beta, of shape (D,)
"""
dx, dgamma, dbeta = None, None, None
x, gamma, beta, var, miu, x_hat, eps = cache
m = len(x)
dx_hat = dout * gamma
dvar = np.sum(dx_hat * (x-miu), axis=0) * -0.5 * (var + eps) ** (-1.5)
dmiu = np.sum(dx_hat * (-1) / np.sqrt(var+eps), axis=0) + dvar * np.mean(-2 * (x - miu), axis=0)
dx = dx_hat / np.sqrt(var + eps) + dvar * 2 * (x - miu) / m + dmiu / m
dgamma = np.sum(dout * x_hat, axis=0)
dbeta = np.sum(dout, axis=0)
return dx, dgamma, dbeta
Tensorflow的源碼里應(yīng)該也會有相應(yīng)的實現(xiàn)宏榕,以后我再找找看拓诸。
上面的batchnorm_backward函數(shù)就是BN反向傳播的python實現(xiàn)版本,僅僅是把公式改寫成了python語言而已麻昼,這篇博文對代碼做了一些解釋奠支,可以參考,這里不再贅述抚芦。
問題就來了倍谜,dout是個什么東西?作為函數(shù)的輸入叉抡,它怎么來的尔崔?我再翻一翻源碼,找到了這個函數(shù):
def softmax_loss(x, y):
"""
Computes the loss and gradient for softmax classification.
Inputs:
- x: Input data, of shape (N, C) where x[i, j] is the score for the jth class
for the ith input.
- y: Vector of labels, of shape (N,) where y[i] is the label for x[i] and
0 <= y[i] < C
Returns a tuple of:
- loss: Scalar giving the loss
- dx: Gradient of the loss with respect to x
"""
probs = np.exp(x - np.max(x, axis=1, keepdims=True))
probs /= np.sum(probs, axis=1, keepdims=True)
N = x.shape[0]
loss = -np.sum(np.log(probs[np.arange(N), y])) / N
dx = probs.copy()
dx[np.arange(N), y] -= 1
dx /= N
return loss, dx
softmax_loss用來計算最后softmax層的loss和gradient褥民,函數(shù)返回兩個值季春,一個是loss,一個是dx(gradient)消返,這個dx就是dout的源頭载弄!也是反向傳播的最最最開始的地方!它是這么得來的:
dx = probs.copy()
dx[np.arange(N), y] -= 1
注:其中probs是softmax的輸出結(jié)果撵颊。
上面的程序代碼是如此的簡潔宇攻!讓人完全蒙圈!逼得我重溫了一下反向傳播算法倡勇,輸出層的殘差是這么算的:
代碼里的f'(z)去哪兒了逞刷???或者這種計算方式是softmax獨有亲桥?深深的感覺到了自己基礎(chǔ)知識的薄弱洛心。我又查閱了Neural Networks and Deep Learning,終于找到了题篷,其中的公式 (84) 是 softmax 層的殘差計算方法词身,如下:
可是作者讓讀者自己推倒公式!又蒙圈了番枚,有興趣的可以自己推倒試一試法严。
簡而言之,dx就是最后一層的gradient葫笼,這個dx要一層一層的反向傳播回去深啤,不同層的反向傳播計算方式也不同,比如ReLU的反向傳播計算是這樣的:
def relu_backward(dout, cache):
"""
Computes the backward pass for a layer of rectified linear units (ReLUs).
Input:
- dout: Upstream derivatives, of any shape
- cache: Input x, of same shape as dout
Returns:
- dx: Gradient with respect to x
"""
dx, x = None, cache
dx = dout
dx[x <= 0] = 0
return dx
當(dāng)然還有 dropout_backward路星、affine_backward(全連層) 還有上面的 batchnorm_backward 計算函數(shù)溯街,不再一一列舉。反向傳播其實就是把gradient作為輸入洋丐,按照前向傳播相反的方向再計算一遍而已呈昔。
總的來講,加入BN層的反向傳播沒有發(fā)生根本的改變友绝,只是多了一個反向計算過程(batchnorm_backward函數(shù))而已堤尾,上述網(wǎng)絡(luò)的最后幾層的前向和反向傳播示意圖如下:
圖也畫了,代碼也給了迁客,公式還是沒明白郭宝,不深究了。
總之掷漱,加入BN層的網(wǎng)絡(luò)粘室,反向傳播的時候也相應(yīng)的多了BN-back,其中的dgamma切威、dbeta會根據(jù)反向傳播的gradient(或者叫殘差)計算出來育特,再利用 optimizer 更新 γ 和 β。