反向传播(back propagation)_神经网络中的运用
反向传播(back propagation)其实是梯度下降的延伸, 当神经网络超过2层的时候, 需要求解中间层的误差项
就需要用到反向传播了. 本文将通过简单的例子, 讲解反向传播在神经网络中的运用.
上一篇博文: 梯度下降_神经网络中的运用 通过简单的2层神经网络,对梯度下降进行了讲解.当明白了梯度下降之后, 就可以进一步了解它的延伸:反向传播(back propagation)了.
基础知识
为了便于理解, 我们依然用简单的3层网络来讲解, 比如下面的网络. 输入单元被标注为 ,隐藏层节点是 .
在梯度下降博文中我们研究的是只有一个输出节点网络,代码也很直观。但是现在我们有多个输入单元和多个隐藏单元,它们的权重需要有两个索引 ,其中 表示输入单元, 表示隐藏单元。比如: 就表示 到 的权重.
权重被储存在矩阵中,由 来索引。矩阵中的每一行对应从同一个输入节点发出的权重,每一列对应传入同一个隐藏节点的权重。这里我们有三个输入节点,两个隐藏节点,权重矩阵表示为:
从上图中我们可以得到隐藏节点
的输入:
由此类推, 所以对每一个隐藏层节点
,其计算公式为:
其矩阵运算直观展示如下:
有了上面的基础知识后, 就可以介绍反向传播到底怎么工作的了.
反向传播
如何让多层神经网络学习呢?我们已了解了使用梯度下降来更新权重,反向传播算法则是它的一个延伸。以一个两层神经网络为例,可以使用链式法则计算输入层-隐藏层间权重的误差。
要使用梯度下降法更新隐藏层的权重,你需要知道各隐藏层节点的误差对最终输出的影响。每层的输出是由两层间的权重决定的,两层之间产生的误差,按权重缩放后在网络中向前传播, 这就是反向传播。既然我们知道输出误差,便可以用权重来反向传播到隐藏层。
例如,输出节点的误差是:
,则隐藏节点的误差既为输出误差
乘以输出层-隐藏层间的权重
,即
.
隐藏节点的误差项
=隐藏节点的误差
, 结果如下公式所示:
然后,梯度下降与上一篇博文: 梯度下降_神经网络中的运用 中的梯度下降相同,只是误差项
变为新的误差项
:
如果神经网络有很多层,道理也是一样的,从输出层逐渐向里反向传播就好了.逐一得到个层的误差项,然后采用梯度下降的方法跟新对应层的权重就好了.
来个实例
import numpy as np
#定义sigmoid函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
x = np.array([0.5, 0.1, -0.2]) #定义输入.x1,x2,x3
target = 0.6 #定义输出
learnrate = 0.5 #学习率
weights_input_hidden = np.array([[0.5, -0.6], #初始化输入层到中间层的权重wij
[0.1, -0.2],
[0.1, 0.7]])
weights_hidden_output = np.array([0.1, -0.3]) #初始化中间层到输出层的权重wj
## 前向传播
hidden_layer_input = np.dot(x, weights_input_hidden) #中间层的输入hj
hidden_layer_output = sigmoid(hidden_layer_input) #中间层的输出f(hj)
output_layer_in = np.dot(hidden_layer_output, weights_hidden_output) #输出层的输入oj
output = sigmoid(output_layer_in) #输出层的输出f(oj)
## 反向传播
error = target - output #输出层的误差
output_error_term = error * output * (1 - output) #输出层的误差项
hidden_error_term = np.dot(output_error_term, weights_hidden_output) * \
hidden_layer_output * (1 - hidden_layer_output) #中间层误差项
#中间层到输出层的权重更新步长
delta_w_h_o = learnrate * output_error_term * hidden_layer_output
#输入层到中间层的权重更新步长
delta_w_i_h = learnrate * hidden_error_term * x[:, None]
print('中间层到输出层的权重更新步长:')
print(delta_w_h_o)
print('输入层到中间层的权重更新步长:')
print(delta_w_i_h)
中间层到输出层的权重更新步长:
[0.00804047 0.00555918]
输入层到中间层的权重更新步长:
[[ 1.77005547e-04 -5.11178506e-04]
[ 3.54011093e-05 -1.02235701e-04]
[-7.08022187e-05 2.04471402e-04]]