如图所示,先画一个简单的神经网络,输入是一个向量(x1,x2,x3,x4)
对于每一个所有的隐藏层和输出层的节点都有:
:不同层之间节点的连接权重
:上一层节点的输出值
:该节点的输入值
:该节点的输出值
:激活函数,这里采用ReLU函数
self.activative = lambda x: np.maximum(0, x) #激活函
self.dirivative = lambda x: 1 if x > 0 else 0 #导数
例如对所有隐藏层节点5,6,7:
为了方便,可以进一步将其转换为矩阵形式:
self.u_hidden = np.dot(self.W_hidden, self.input)
self.x_hidden = self.activative(self.u_hidden)
接下来是输出层的计算:
self.u_output = np.dot(self.W_ouput, self.x_hidden)
self.y = self.activative(self.u_output)
以上就是正向的计算过程,接下来讨论误差的反向传播过程,首先来看损失函数:
,是误差,为训练数据的标记,是输出
在训练的过程中,我们需要训练的也就是各层的权重, 根据梯度下降算法:
:学习率
:的梯度
首先来推导输出层的梯度,例如:
因为变量是通过影响节点8的输入值进而再影响到误差,接下来一个一个的求解分量:
综合上式,得到以下结果:
将下标处理一下,得到公式:
,又设
为该节点的误差项,所以最终的公式为:
用矩阵表示:
self.delta_output = (self.target - self.y) * self.dirivative(self.u_output)
self.nablaW_output = np.dot(self.delta_output, np.transpose(self.x_hidden))
self.W_ouput += self.learningrate * self.nablaW_output
以上,就是输出层的公式推导及简要的代码,对于隐藏层,例如误差关于的梯度的计算同样,只不过关于误差项有些区别:
根据之前的讨论,同样另,所以:
而的计算就稍微复杂一些,因为的值对其下层的节点(8,9)都有影响,所以根据全导数公式:
综合上述公式,得到:
整理一下,最终得到公式:
详细过程如下:
temp = np.dot(np.transpose(self.delta_output), self.W_ouput) #临时变量
self.delta_hidden = self.dirivative(self.u_hidden) * np.transpose(temp)
self.nablaW_hidden = np.dot(self.delta_hidden, np.transpose(self.input))
self.W_hidden += self.learningrate * self.nablaW_hidden
至此,隐藏层的权重也更新完毕
网友评论