传送门: https://www.cnblogs.com/greentomlee/p/12314064.html
github: Leezhen2014: https://github.com/Leezhen2014/python_deep_learning
我们已经可以实现一些简单的节点(比如, 加法,乘法等),以及 激活函数;
并且已经知道了 backward() 函数的实现的方法:只要计算偏导数即可,将偏导数公式的实现放到 对应节点的backward函数中即可;
在本章中会介绍一些复杂的层,比如affine, Softmax-with-Loss ; 本章比较考验数学功底、对梯度求导的理解、对计算图的理解;
话不多说,开始....
Affine 层其实是全连接层,Affine的名字来源于斯坦福的C231, 网上也很多实现: https://blog.csdn.net/achcxchca/article/details/80959735
Affine(仿射)的意思可以理解为前面一层中的每一个神经元都连接到当前层中的每一个神经元,加入仿射层输出的形状和数值都有所改变,这点类似于图像处理的仿射变换。在许多情况下,这是神经网络的「标准」层。仿射层通常被加在卷积神经网络或循环神经网络做出最终预测前的输出的顶层。
PS: Affine层的输出X是需要考虑到输入是以单个数据为对象的,还是以多个输入为对象的。
Forward的计算图:
Backward计算图:
1 class Affine: 2 def __init__(self, W, b): 3 self.W = W 4 self.b = b 5 6 self.x = None 7 self.original_x_shape = None 8 # 计算微分 9 self.dW = None 10 self.db = None 11 12 def forward(self, x): 13 # 为了支持支持张量的计算,将x先做形状修改 相当于transOp 14 self.original_x_shape = x.shape 15 x = x.reshape(x.shape[0], -1) 16 17 # out = w*x+b 18 self.x = x 19 out = np.dot(self.x, self.W) + self.b 20 21 return out 22 23 def backward(self, dout): 24 25 dx = np.dot(dout, self.W.T) 26 self.dW = np.dot(self.x.T, dout) 27 self.db = np.sum(dout, axis=0) 28 29 # 将dx形状trans回去(张量支持) 30 dx = dx.reshape(*self.original_x_shape) 31 return dx