误差逆传播算法(BP神经网络)
BP神经网络是一种按误差反向传播(简称误差反传)训练的多层前馈网络,其算法称为BP算法,它的基本思想是梯度下降法,利用梯度搜索技术,以期使网络的实际输出值和期望输出值的误差均方差为最小。
基本BP算法包括信号的前向传播和误差的反向传播两个过程。即计算误差输出时按从输入到输出的方向进行,而调整权值和阈值则从输出到输入的方向进行。
下面让我们从数学原理上来看一下BP算法是怎样工作的。
我们给定训练集输入示例有d个属性,输出是一个l维的实值向量,转换成如下图所示的前馈神经网络的输入输出的形式,该神经网络拥有d个输入神经元、l个输出神经元以及q个隐藏神经元。
对于上图中的神经网络我们需要确定输入层到隐层的d*q个权值、隐层到输出层的q*l个权值、q个隐层神经元的阈值、l个输出层神经元的阈值,一共则是(d+l+1)*q+l个参数需要确定。
和之前的参数更新方式一样,我们对于任意参数v的更新方式可以表示为如下的形式:
我们在前面假设神经元内都是sigmoid函数,并且sigmoid函数有一个很重要的导数性质如下:
因此我们可以根据式(1)(2)得到如下的式子
我们把式子(5)(6)带入(4)式再带入(3)式可以得到如下的参数更新公式:
类似的我们也可以得到其他参数的更新公式:
以上便是我们BP算法的推导过程,在整个过程中我们先通过输出层得到误差,再从误差入手进行反向传播更新参数就OK了。
注:通常我们把学习率设置为0.1,学习率控制着算法的每一轮迭代时的更新步长,若太大则容易震荡,太小则收敛速度又会过慢,有时我们会在不同的网络层之间设定不同的学习率。
下面给出BP神经算法的简单代码实现(带有隐层的神经网络):
import numpy as np def nonlin(x, deriv=False): if deriv == True: # 如果deriv=True我们就进行求导 return x * (1 - x) else: # 返回sigmoid函数 return 1 / (1 + np.exp(-x)) # 给定输入输出 x = np.array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]]) y = np.array([[0, 1, 1, 0]]).T # 均值与标准差 mu, sigma = 0, 0.1 w0 = np.random.normal(mu, sigma, (3, 5)) w1 = np.random.normal(mu, sigma, (5, 1)) # 定义迭代次数 iter_size = 1000 # 定义学习率 lr = 1 for i in range(iter_size): # 输入层 L0 = x # 隐藏层(输入层和隐藏层间权重为w0) L1 = nonlin(L0.dot(w0)) # 输出层(隐藏层和输出层间权重为w1) L2 = nonlin(L1.dot(w1)) # 损失函数 L2_loss = L2 - y # 输出层的导数 L2_delta = L2_loss * nonlin(L2, True) # 隐藏层到输出层的梯度 grad1 = L1.T.dot(L2_delta) # 隐藏层到输出层参数更新 w1 -= grad1 * lr # L1对L2_loss贡献了多少,反过来传梯度时就要乘以这个权重 L1_loss = L2_delta.dot(w1.T) # 隐藏层的导数 L1_delta = L1_loss * nonlin(L1, True) # 输入层到隐藏层的梯度 grad0 = L0.T.dot(L1_delta) # 输入层到隐藏层的参数更新 w0 -= grad0 * lr print(L2)