需要全部代码请点赞关注收藏后评论留言私信~~~
误差反向传播学习算法
用神经网络来完成机器学习任务,先要设计好网络结构S,然后用训练样本去学习网络中的连接系数和阈值系数,即网络参数S,最后才能用来对测试样本进行预测。
在研究早期,没有适合多层神经网络的有效的参数学习方法是长期困扰该领域研究者的关键问题,以致于人们对人工神经网络的前途产生了怀疑,导致该领域的研究进入了低谷期。直到1986年,以Rumelhart和McCelland为首的小组发表了误差反向传播(Error Back Propagation,BP)算法,该问题才得以解决,多层神经网络从此得到快速发展。
采用BP算法来学习的、无反馈的、同层节点无连接的、多层结构的前馈神经网络称为BP神经网络。
逻辑代数中的异或运算时非线性的,它不能由单个神经元来模拟,下面用模拟异或运算的神经网络为例来说明BP学习过程
样本:
网络结构:
要学习的参数:
BP学习算法可分为前向传播预测与反向传播学习两个过程。
为了方便求导,隐层和输出层的激励函数采用Sigmoid函数:
Sigmoid函数的导数为:
前向传播预测过程
设网络各参数初值为:
取第一个训练样本(0,0),第1隐层的输出:
用l^(1)和l^(2)表示标签值,采用各标签值的均方误差MSE作为总误差,并将总误差依次展开至输入层:
可见,总误差E是各层参数变量的函数,因此学习的目的就是通过调整各参数变量的值,使E最小。可采用梯度下降法求解。
第一个训练样本的标签值为(0,1),因此,输出产生的误差分别为0.743和−0.236。总误差:E=1/2∑_i=1^2▒(z^(i)−l^(i))^2=0.304 输出层节点的参数更新,以节点1的w_2^(1,1)和θ_2^(1)为例详细讨论。
先求偏导∂E/∂w_2^(1,1):∂E/∂w_2^(1,1)=∂E/∂y_2^(1)∙∂y_2^(1)/∂w_2^(1,1)=∂[1/2∑_i=1^2▒(y_2^(i)−l^(i))^2]/∂y_2^(1)∙∂y_2^(1)/∂w_2^(1,1)=(y_2^(1)−l^(1))∙∂y_2^(1)/∂w_2^(1,1)
式中括号(y_2^(1)−l^(1))是输出层节点1的校对误差,记为E_2^1,即E_2^1=y_2^(1)−l^(1)=0.743。因此∂E/∂w_2^(1,1)可视为该节点的校对误差乘以该节点输出对待更新参数变量的偏导:∂E/∂w_2^(1,1)=E_2^1∙∂y_2^(1)/∂w_2^(1,1)
后面求导过程过于繁杂 此处省略不表
以上给出了输入第一个训练样本后,网络的前向预测和反向学习过程。可将样本依次输入网络进行训练。一般要进行多轮训练。
运行输出结果如下
经过2000轮训练,每轮平均值总误差由0.32降维0.008
最后一轮的四个输出与相应标签值对比为下 预测输出十分接近实际标签值
部分代码如下
for j in range(2000):
print("\n\n轮:", j)
E = 0.0
for i in range(4):
print("样本:", i)
print("实例:", XX[i])
print("标签", L[i])
### 前向传播预测
# 计算第1隐层的输出
Y1[0] = y_1_1(W1, theta1, XX[i])
Y1[1] = y_1_2(W1, theta1, XX[i])
#print("第1隐层的输出:", Y1)
# 计算第2隐层的输出
Y2[0] = y_2_1(W2, theta2, Y1)
Y2[1] = y_2_2(W2, theta2, Y1)
print("第2隐层的输出:", Y2)
### 后向传播误差
# 计算第2隐层的校对误差
E2[0] = Y2[0] - L[i][0]
E2[1] = Y2[1] - L[i][1]
E += 0.5*(E2[0]*E2[0]+E2[1]*E2[1])
#print("总误差", E)
#print("第2隐层的校对误差", E2)
# 计算第1隐层的校对误差
E1[0] = E2[0]*Y2[0]*(1 - Y2[0])*W2[0,0] + E2[1]*Y2[1]*(1 - Y2[1])*W2[0,1]
E1[1] = E2[0]*Y2[0]*(1 - Y2[0])*W2[1,0] + E2[1]*Y2[1]*(1 - Y2[1])*W2[1,1]
#print("第1隐层的校对误差", E1)
### 更新系数
# 更新第2隐层的系数
W2[0,0] = W2[0,0] - a*E2[0]*Y2[0]*(1 - Y2[0])*Y1[0]
W2[1,0] = W2[1,0] - a*E2[0]*Y2[0]*(1 - Y2[0])*Y1[1]
theta2[0] = theta2[0] - a*E2[0]*Y2[0]*(1 - Y2[0])
W2[0,1] = W2[0,1] - a*E2[1]*Y2[1]*(1 - Y2[1])*Y1[0]
W2[1,1] = W2[1,1] - a*E2[1]*Y2[1]*(1 - Y2[1])*Y1[1]
theta2[1] = theta2[1] - a*E2[1]*Y2[1]*(1 - Y2[1])
#print("第2隐层的连接系数", W2)
#print("第2隐层的阈值系数", theta2)
# 更新第1隐层的系数
W1[0,0] = W1[0,0] - a*E1[0]*Y1[0]*(1 - Y1[0])*XX[i][0]
W1[1,0] = W1[1,0] - a*E1[0]*Y1[0]*(1 - Y1[0])*XX[i][1]
theta1[0] = theta1[0] - a*E1[0]*Y1[0]*(1 - Y1[0])
W1[0,1] = W1[0,1] - a*E1[1]*Y1[1]*(1 - Y1[1])*XX[i][0]
W1[1,1] = W1[1,1] - a*E1[1]*Y1[1]*(1 - Y1[1])*XX[i][1]
theta1[1] = theta1[1] - a*E1[1]*Y1[1]*(1 - Y1[1])
#print("第1隐层的连接系数", W1)
#print("第1隐层的阈值系数", theta1)
print("平均总误差" + str(E/4.0))
下面用深度学习框架Tensorflow来模拟异或运算
训练过程如下
当采用(2,2,2)全连接层神经网络时,训练2000轮时,误差约为0.19,四个标签对应的输出为:
[0.43767142,0.56202793]→[0.,1.],
[0.5493321,0.45261452]→[1.,0.],
[0.575727,0.42299467]→[1.,0.],
[0.43716326,0.5625658 ]→[ 0.,1.]。
如果增加隐层的数量,将有效提高模拟效果,将隐层节点数量增加到4个,误差降到约0.16。
部分代码如下
import tensorflow as tf
import numpy as np
# 样本实例
XX = np.array([[0.0,0.0],
[0.0,1.0],
[1.0,0.0],
[1.0,1.0]])
# 样本标签
L = np.array([[0.0,1.0],
[1.0,0.0],
[1.0,0.0],
[0.0,1.0]])
tf_model = tf.keras.Sequential([
tf.keras.layers.Dense(2, activation='sigmoid', input_shape=(2,), kernel_initializer='random_uniform', bias_initializer='zeros'),
tf.keras.layers.Dense(2, activation='sigmoid', kernel_initializer='random_uniform', bias_initializer='zeros')
])
tf_model.compile(optimiaer=tf.keras.optimizers.SGD(), loss=tf.keras.losses.mean_squared_error, metrics=['accuracy'])
tf_model.summary()
tf_model.fit(XX, L, batch_size=4, epochs=2000, verbose=1)
tf_model.evaluate(XX, L)
创作不易 觉得有帮助请点赞关注收藏~~~