cs231_n4.1_反向传播

1. 反向传播是利用链式法则递归计算表达式梯度的方法。

2. 反向传播的直观理解:反向传播是一个优美的局部过程。在整个计算线路图中,每个门单元都会得到一些输入并立即计算两个东西:这个门的输出值,和其输出值关于输入值的局部梯度。链式法则指出,门单元应该将回传的梯度乘以它对其的输入的局部梯度,从而得到整个网络的输出对该门单元的每个输入值的梯度。

3. 模块化:Sigmoid例子        

    任何可微分的函数(加/减/乘方等)都可以看做门,可以将多个门组合成一个门,也可以根据需要将一个函数分拆成多个门。现在看看一个表达式:

   

    整个计算线路如下:

   

     sigmoid函数关于其输入的求导是可以简化的:

   

4. 分段反向传播:假设有如下函数,计算其梯度

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 # 搞定!                                		  #(8)


#反向传播,回传,好绕啊,要细心看o
# 回传 f = num * invden
dnum = invden # 分子的梯度                                         #(8)
dinvden = num                                                     #(8)
# 回传 invden = 1.0 / den 
dden = (-1.0 / (den**2)) * dinvden                                #(7)
# 回传 den = sigx + xpysqr
dsigx = (1) * dden                                                #(6)
dxpysqr = (1) * dden                                              #(6)
# 回传 xpysqr = xpy**2
dxpy = (2 * xpy) * dxpysqr                                        #(5)
# 回传 xpy = x + y
dx = (1) * dxpy                                                   #(4)
dy = (1) * dxpy                                                   #(4)
# 回传 sigx = 1.0 / (1 + math.exp(-x))
dx += ((1 - sigx) * sigx) * dsigx # Notice += !! See notes below  #(3)
# 回传 num = x + sigy
dx += (1) * dnum                                                  #(2)
dsigy = (1) * dnum                                                #(2)
# 回传 sigy = 1.0 / (1 + math.exp(-y))
dy += ((1 - sigy) * sigy) * dsigy                                 #(1)
# 完成! 嗷~~

5. 用向量化操作计算梯度

# 前向传播
W = np.random.randn(5, 10)
X = np.random.randn(10, 3)
D = W.dot(X)

# 假设我们得到了D的梯度
dD = np.random.randn(*D.shape) # 和D一样的尺寸,注意:*表示的是将调用的多个参数放入元组
dW = dD.dot(X.T) #.T就是对矩阵进行转置
dX = W.T.dot(dD)

提示:要分析维度!注意不需要去记忆dW和dX的表达,因为它们很容易通过维度推导出来。例如,权重的梯度dW的尺寸肯定和权重矩阵W的尺寸是一样的,而这又是由X和dD的矩阵乘法决定的(在上面的例子中X和W都是数字不是矩阵)。总有一个方式是能够让维度之间能够对的上的。例如,X的尺寸是 [10x3],dD的尺寸是 [5x3],如果你想要dW和W的尺寸是 [5x10],那就要dD.dot(X.T)

转载自:https://blog.csdn.net/kingsure001/article/details/107913006

猜你喜欢

转载自blog.csdn.net/jialibang/article/details/109033489
今日推荐