cs231n'18: Course Note 4

Backpropagation, Intuitions

Backprop和chain rule,就是用求解微分时的链式法则,将复杂算式的微分计算,一步步分解成小的node,然后用这些基本的node层层叠加,最后得到微分结果。通常做法是先画出computation graph,然后再stage by stage的计算grads,基本的公式是:

                 down_diff = local_diff * up_diff

其中up_diff是从上一层block传递下来的,local_diff要通过计算得到,并且和输入值有关,两者相乘传递给下一层的block。道理很简单,但是具体代码写起来会遇到各种问题,到时候再见招拆招吧。

Patterns in backward flow

add gate

up_diff不做任何改变均匀的传向两个分支。

max gate

up_diff传向输入值大的一个分支,另一个分支为0

multiply gate

up_diff与输入值相乘后传向另外一个分支。需要注意的是,这里有一个switch的动作,即一个分支的grad与另外一个分支的输入成正比。所以一个分支的输入如果过大的话,会导致另外一个分支的grad很大,造成梯度爆炸。

具体的,score = wx,x是training data,通常是已知的不变的,所以不会计算对x的grad,只计算对w的grad dw d w 。如果输入数据x很大的话,那么由于w和x要相乘,那么会造成 dw d w 很大,这样的后果就是,要么梯度会爆炸,要么要大大降低learning rate,使得学习变慢。所以我们要对原始的输入数据进行预处理,减去均值;同时这也是BN层会加速训练的原因之一。

sigmoid gate

ddxσ(x) =(1σ(x))σ(x) d d x σ ( x )   = ( 1 − σ ( x ) ) ⋅ σ ( x )

Gradients for vectorized operations

这又是个头疼的地方,首先要记住的一点是,stage到score,不要妄图直接计算 dW d W , 先算 dScore d S c o r e ,然后通过 维度分析 来计算 dW d W 。例如,X是(N, D),W是(D, C),那么Score = X.dot(W)是(N, C)。根据 维度分析

dWdX=X.T.dot(dScore)=dScore.dot(W.T) d W = X . T . d o t ( d S c o r e ) d X = d S c o r e . d o t ( W . T )

这样可以省去很多麻烦。

如果实在避免不了计算对vector的grad,那么就要项note里说的,先写出对vector中每一项的grad,然后再去general成vector形式,这里常用到的公式是视频里板书的那个:

fX=ifqiqiX ∂ f ∂ X = ∑ i ∂ f ∂ q i ⋅ ∂ q i ∂ X ,

这里要注意的是写代码时np.sum()要对哪个axis进行。

此处有作业

Assignment 1: two_layer_net

难点在于grads的计算,这里详细的把推导过程写写,然后总结出一套简单的算法,以后再用时直接用这套算法就行,省得再去想一遍推导过程。代码在neural_network里。

这个两层的NN是先经过(W1, b1),然后ReLU一下,在经过(W2, b2)得到score,然后score再经过softmax,得到最后的Loss。它的forward很简单:

layer1_out = X.dot(W1) + b1
relu_out = np.maximum(0, layer1_out)
scores = relu_out.dot(W2) + b2

得到score后,再经过softmax得到Loss:

stable_scores = scores - np.max(scores, axis=1, keepdims=True)
correct_score = stable_scores[np.arange(N), y]

loss = -np.sum(np.log(np.exp(correct_score) / np.sum(np.exp(stable_scores), axis=1)))
loss = loss/N + reg * np.sum(W1 * W1) + reg * np.sum(W2 * W2)

下一步就是计算对W1, b1, W2, b2的grad了。

首先一定要牢记的是,上来不要妄图直接计算 dW d W 或者是 db d b ,一定要先从XW+b的结果score下手。所以,这里先算Loss对score的grad,在softmax一节已经详细讲过了:

Dscores = np.exp(stable_scores) / np.sum(np.exp(stable_scores), axis=1, keepdims=True)
Dscores[np.arange(N), y] -= 1
Dscores = Dscores / N

需要注意的一个细节是最后一步的除以N,在这里除了的话,后面可以不用再除,以防后面计算的时候忘记。然后就要计算 dW2 d W 2 db2 d b 2 。这里详细的讲一下Y = XW+b如何算grads。

Y = X.dot(W) + b梯度的计算

首先这里的已知量是(X, W, b, Y, dY = Ly ∂ L ∂ y ),要求出 dW d W db d b 。其中

y (N, C)形如:

y11y21yn1y12y22...yn2............y1cy2cync [ y 11 y 12 . . . y 1 c y 21 y 22 . . . y 2 c . . . . . . y n 1 y n 2 . . . y n c ]

X (N, D)形如:
x11x21xn1x12x22...xn2............x1dx2dxnd [ x 11 x 12 . . . x 1 d x 21 x 22 . . . x 2 d . . . . . . x n 1 x n 2 . . . x n d ]

W (D, C)形如
w11w21wd1w12w22...wd2............w1cw2cwdc [ w 11 w 12 . . . w 1 c w 21 w 22 . . . w 2 c . . . . . . w d 1 w d 2 . . . w d c ]

b (1, C)形如:
[b1,b2,...,bc] [ b 1 , b 2 , . . . , b c ]

dY (N, C) 形如:
dy11dy21dyn1dy12dy22...dyn2............dy1cdy2cdync [ d y 11 d y 12 . . . d y 1 c d y 21 d y 22 . . . d y 2 c . . . . . . d y n 1 d y n 2 . . . d y n c ]

Y = X.dot(W) + b形如:
y11y21yn1y12y22...yn2............y1cy2cync=x11x21xn1x12x22...xn2............x1dx2dxndw11w21wd1w12w22...wd2............w1cw2cwdc+[b1,b2,...,bc] [ y 11 y 12 . . . y 1 c y 21 y 22 . . . y 2 c . . . . . . y n 1 y n 2 . . . y n c ] = [ x 11 x 12 . . . x 1 d x 21 x 22 . . . x 2 d . . . . . . x n 1 x n 2 . . . x n d ] ∗ [ w 11 w 12 . . . w 1 c w 21 w 22 . . . w 2 c . . . . . . w d 1 w d 2 . . . w d c ] + [ b 1 , b 2 , . . . , b c ]

db d b 的推导

首先求 db d b 的第一项 db1 d b 1

db1=Lb1=Lyyb1=ijLyijyijb1 d b 1 = ∂ L ∂ b 1 = ∂ L ∂ y ⋅ ∂ y ∂ b 1 = ∑ i ∑ j ∂ L ∂ y i j ⋅ ∂ y i j ∂ b 1

还记得视频中板书的那个公式么,在这里用到了。
yij y i j 展开:
y11y12yij=x11w11+x12w21+...+x1dwd1+b1=x11w12+x12w22+...+x1dwd2+b2......=xi1w1j+xi2w2j+...+xidwdj+bj y 11 = x 11 w 11 + x 12 w 21 + . . . + x 1 d w d 1 + b 1 y 12 = x 11 w 12 + x 12 w 22 + . . . + x 1 d w d 2 + b 2 . . . . . . y i j = x i 1 w 1 j + x i 2 w 2 j + . . . + x i d w d j + b j

由此可以看出, b1 b 1 仅与 yi1 y i 1 有关,同样, bj b j 仅与 yij y i j 有关,并且 yijbj=1 ∂ y i j ∂ b j = 1 那么:
dbj=iLyijyijbj=i=1Ndyij d b j = ∑ i ∂ L ∂ y i j ⋅ ∂ y i j ∂ b j = ∑ i = 1 N d y i j

就是将 dy d y 的第一列所有行相加。同理, dbj d b j 就是将 dy d y 第j列所有行相加。而 dy d y 为(N, C), 由此计算出的 dbj d b j 为 (1, C),正好是b的shape。

grads['b2'] = np.sum(Dscores, axis=0)

这里用 维度分析 更好解释,正因为 dy d y 为(N, C),而b (1, C)只能与 dy d y 有关,所以只能沿着axis=0相加得到。详细的推导摆在这里,以后再遇到按 维度分析 的方式直接用就行了。

这里再插一句,从 db1=Ni=1dyi1 d b 1 = ∑ i = 1 N d y i 1 来看, 的下标是从 i i 从1到N,这说明 b1 的grad是由 这一batch中所有sample 的第一个feature所决定的。

dW d W 的推导

同样以 dw11 d w 11 为例

dw11=Lw11=Lyyw11=ijLyijyijw11 d w 11 = ∂ L ∂ w 11 = ∂ L ∂ y ⋅ ∂ y ∂ w 11 = ∑ i ∑ j ∂ L ∂ y i j ⋅ ∂ y i j ∂ w 11

从y的展开式来看, w11 w 11 仅与 yi1 y i 1 有关,而 yi1w11=xi1 ∂ y i 1 ∂ w 11 = x i 1 ,所以:
dw11=ijLyijyijw11=i=1Nxi1dyi1 d w 11 = ∑ i ∑ j ∂ L ∂ y i j ⋅ ∂ y i j ∂ w 11 = ∑ i = 1 N x i 1 ⋅ d y i 1

推广到一般,可得:
dwpq=ijLyijyijwpq=i=1Nxipdyiq, d w p q = ∑ i ∑ j ∂ L ∂ y i j ⋅ ∂ y i j ∂ w p q = ∑ i = 1 N x i p ⋅ d y i q ,

写成矩阵相乘形式为:
dw=dw11dw21dwd1dw12dw22...dwd2............dw1cdw2cdwdc=x11x21xn1x12x22...xn2............x1dx2dxndTdy11dy21dyn1dy12dy22...dyn2............dy1cdy2cdync d w = [ d w 11 d w 12 . . . d w 1 c d w 21 d w 22 . . . d w 2 c . . . . . . d w d 1 d w d 2 . . . d w d c ] = [ x 11 x 12 . . . x 1 d x 21 x 22 . . . x 2 d . . . . . . x n 1 x n 2 . . . x n d ] T ∗ [ d y 11 d y 12 . . . d y 1 c d y 21 d y 22 . . . d y 2 c . . . . . . d y n 1 d y n 2 . . . d y n c ]

再用 维度分析 解释一下,X形如(N, D),dY形如(N, C), dW d W 与W相同形如(D, C),所以 dW=X.T.dot(dY) d W = X . T . d o t ( d Y ) ,与公式推导得到的结果一致。

grads['W2'] = relu_out.T.dot(Dscores) + 2 * reg * W2

这里再插一句,从 dw11=Ni=1xi1dyi1 d w 11 = ∑ i = 1 N x i 1 ⋅ d y i 1 来看, 的下标是从 i i 从1到N,这说明 w11 的grad是由 这一batch中所有sample 的第一个feature所决定的。

dX d X 的推导

既然写了,就把它写全吧。

dx11=Lx11=Lyyx11=ijLyijyijx11 d x 11 = ∂ L ∂ x 11 = ∂ L ∂ y ⋅ ∂ y ∂ x 11 = ∑ i ∑ j ∂ L ∂ y i j ⋅ ∂ y i j ∂ x 11

x11 x 11 仅与 y1j y 1 j 有关,且 y1jx11=w1j ∂ y 1 j ∂ x 11 = w 1 j ,所以
dx11=ijLyijyijx11=j=1Cw1jdy1j d x 11 = ∑ i ∑ j ∂ L ∂ y i j ⋅ ∂ y i j ∂ x 11 = ∑ j = 1 C w 1 j ⋅ d y 1 j

推广到一般:
dxpq=ijLyijyijxpq=j=1Cdypjwqj d x p q = ∑ i ∑ j ∂ L ∂ y i j ⋅ ∂ y i j ∂ x p q = ∑ j = 1 C d y p j ⋅ w q j

其矩阵相乘形式为:
dx=dx11dx21dxd1dx12dx22...dxd2............dx1cdx2cdxdc=dy11dy21dyn1dy12dy22...dyn2............dy1cdy2cdyncw11w21wd1w12w22...wd2............w1cw2cwdcT d x = [ d x 11 d x 12 . . . d x 1 c d x 21 d x 22 . . . d x 2 c . . . . . . d x d 1 d x d 2 . . . d x d c ] = [ d y 11 d y 12 . . . d y 1 c d y 21 d y 22 . . . d y 2 c . . . . . . d y n 1 d y n 2 . . . d y n c ] ∗ [ w 11 w 12 . . . w 1 c w 21 w 22 . . . w 2 c . . . . . . w d 1 w d 2 . . . w d c ] T

维度分析 解释一下,W形如(D, C),X形如(N, D),dY形如(N, C), dX d X 与X相同形如(N, D),所以 dX=dY.dot(W.T) d X = d Y . d o t ( W . T ) ,与公式推导得到的结果一致。

Drelu_out = Dscores.dot(W2.T)
一些小的细节
ReLU梯度的计算
Dlayer1_out = Drelu_out * (layer1_out > 0)
grad_check函数
for param_name in grads:
    f = lambda W: net.loss(X, y, reg=0.05)[0]
    param_grad_num = eval_numerical_gradient(f, net.params[param_name], verbose=False)

这里注意lambda函数最后的那个 [0]

    f = lambda W: net.loss(X, y, reg=0.05)[0]

因为net.loss函数的返回值是两个:

def loss(self, X, y=None, reg=0.0):
  ...
  return loss, grads

这个[0]表示在计算f(x)的时候,只考虑返回值的第一个,即loss。

Inline Question

Now that you have trained a Neural Network classifier, you may find that your testing accuracy is much lower than the training accuracy. In what ways can we decrease this gap? Select all that apply.

Train on a larger dataset.

Add more hidden units.

Increase the regularization strength.

None of the above.

增加dataset通常来讲可以;增加hidden可能会行,但不一定,因为反而会更加overfit;增大reg strength也可以减小overfit。上述所有措施都是可能,但不能保证一定行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值