上周数据挖掘选修课老师要求我们自己尝试写一个反向传播的模型出来,我在CSDN上找了关于C++实现简单方向传播算法的相关内容,并结合老师课上内容成功实现了简单的反向传播神经网络,以此记录。
神经网络
- 神经网络最早是由心理学家和神经学家提出的,旨在寻求开发和测试神经的计算模拟;
- 神经网络是一组连接的输入/输出单元, 其中每个连接都与一个权相关联;
- 在学习阶段, 通过调整神经网络的权, 使得能够预测输入样本的正确类标记。
反向传播算法
误差反向传播算法简称反向传播算法(Back Propagation)。使用反向传播算法的多层感知器又称为 BP 神经网络。后向传播算法是在多层前馈(multilayer feed-forward)神经网络上学习的。一个多层前馈神经网络的模型如下图所示:
- 训练样本 X = { x 1 , x 2 , . . . , x i } X =\{x_1 ,x_2 ,..., x_i\} X={x1,x2,...,xi}馈入输入层.每层之间存在加权连接; 其中, w i j w_{ij} wij表示由某层的单元j到前一层的单元 i i i的权;
- 隐藏层的数量是任意的, 实践中通常只用一层
- 输出层发布给定样本的网络预测
- 包含n个隐藏层的网络称作n+1层神经网络
- 网络是全连接的, 如果每个单元都向下一层的每个单元提供输入
- 给定足够多的隐藏单元, 线性阈值函数的多层前馈神经网络可以逼近任何函数
基本思想:
- 将训练集数据输入到神经网络的输入层,经过隐藏层,最后达到输出层并输出结果,这就是前向传播过程。
- 由于神经网络的输出结果与实际结果有误差,则计算估计值与实际值之间的误差,并将 该误差从输出层向隐藏层反向传播,直至传播到输入层;
- 在反向传播的过程中,根据误差调整各种参数的值(相连神经元的权重),使得总损失 函数减小。
- 迭代上述三个步骤(即对数据进行反复训练),直到满足停止准则。
步骤解释
- 初始化权:网络的权被初始化为很小的随机数 (例如, 由-1.0到1.0, 或由-0.5到0.5), 每个单元有一个偏置,
也类似地初始化为小随机数; - 每个样本
X
X
X按以下步骤处理:
- 向前传播输入;
- 后向传播误差;
- 重复以上两步,直至终止条件满足。
测试问题
典型非线性问题XOR测试,即异或问题:两数相同时结果为0;两数不同时结果为1。
输入 | 输入 | 输出 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
前向传播
前向传播是将输入结点将由训练集获取到的输入值经过一系列操作依次从隐含层传递给输出层:
第
j
j
j层结点的当前值
V
a
l
u
e
j
Value_j
Valuej是:
V
a
l
u
e
j
=
s
i
g
n
o
d
(
∑
i
W
e
i
g
h
t
i
j
V
a
l
u
e
i
+
θ
j
)
Value_j = signod(\sum_i{Weight_{ij}Value_i +\theta_j})
Valuej=signod(i∑WeightijValuei+θj)
- W e i g h t i j Weight_{ij} Weightij是由上一层的单元 i i i到单元 j j j的连接的权重;
- V a l u e i Value_i Valuei是上一层的单元i的当前值;
- θ j \theta_j θj 是单元 j j j的偏差(偏置值,用来改变单元的活性);
- s i g m o d ( ) sigmod() sigmod()函数是激活函数的一种,又称挤压函数,可以将一个较大的输入值域映射到较小的区间 [ 0 , 1 ] [0,1] [0,1]里, s i g m o d ( ) sigmod() sigmod()的表达式如下: f ( x ) = 1 1 + e − x f(x) = \frac{1}{1+e^{-x}} f(x)=1+e−x1。
所以,一个隐含或输出单元
j
j
j的当前值是将前一层的当前值与对应的权重相乘以形成加权和,将加权和加到与单元
j
j
j想联的偏置值上,最后通过激活函数得到单元
j
j
j的当前值。
反向传播
我们通过前向传播会得到输出节点的预测值,这个预测值和测试集中输出结点的正确输出值是存在一定的误差,反向传播就是从输出层依次沿着隐含层、输入层传播这个误差,并更新每个结点的权值和反映网络预测误差的偏置值。
输出单元
j
j
j的误差
E
r
r
j
Err_j
Errj通过下式计算:
E
r
r
j
=
V
a
l
u
e
j
(
1
−
V
a
l
u
e
j
)
(
R
i
g
h
t
O
u
t
j
−
V
a
l
u
e
j
)
Err_j=Value_j(1-Value_j)(RightOut_j - Value_j)
Errj=Valuej(1−Valuej)(RightOutj−Valuej)
其中:
- V a l u e j Value_j Valuej是单元 j j j的当前值;
- R i g h t O u t j RightOut_j RightOutj是训练集中给出的正确输出值;
- V a l u e j ( 1 − V a l u e j ) Value_j(1-Value_j) Valuej(1−Valuej)是激活函数 s i g m o d ( ) sigmod() sigmod()的导数。
隐含单元
j
j
j的误差
E
r
r
j
Err_j
Errj通过下式计算:
E
r
r
j
=
V
a
l
u
e
j
(
1
−
V
a
l
u
e
j
)
∑
k
W
e
i
g
h
t
j
k
E
r
r
k
Err_j=Value_j(1-Value_j)\sum_k{Weight_{jk}{Err_k}}
Errj=Valuej(1−Valuej)k∑WeightjkErrk
其中,
- W e i g h t j k Weight_{jk} Weightjk是由下一较高层中单元 k k k到单元j的连接权;
- E r r k Err_k Errk单元 k k k的误差
更新权值:
Δ W e i g h t i j = l ∗ E r r j ∗ V a l u e j W e i g h t i j = W e i g h t i j + Δ W e i g h t i j \Delta Weight_{ij} = l \ast Err_j \ast Value_j \\ Weight_{ij} = Weight_{ij} + \Delta Weight_{ij} ΔWeightij=l∗Errj∗ValuejWeightij=Weightij+ΔWeightij
其中,
- Δ W e i g h t i j \Delta Weight_{ij} ΔWeightij是 W e i g h t i j Weight_{ij} Weightij的改变;
- 变量
l
l
l是学习率,通常取0和1之间的值;
- 学习率帮助避免陷入判定空间的局部最小
- 学习率调整规则:将学习率设置为 1 / t 1/t 1/t,其中 t t t是对训练样本迭代的次数。
更新偏置值:
Δ θ j = l ∗ E r r j θ j = θ j + Δ θ j \Delta \theta_j = l \ast Err_j \\ \theta_j = \theta_j + \Delta \theta_j Δθj=l∗Errjθj=θj+Δθj
其中, Δ θ j \Delta \theta_j Δθj是偏置值 θ j \theta_j θj的改变。
实例更新&周期更新
- 实例更新(case update):每处理一个样本就更新权值和偏置值;
- 周期更新(epoch update):处理完训练集中的所有样本之后再更新权值和偏置值。
终止条件
- 前一周期所有的 Δ W e i g h t i j \Delta Weight_{ij} ΔWeightij都小于某个指定的阈值;
- 前一周期未正确分类的样本百分百小于某个阈值;
- 超过预先指定的周期数(实践中,权值收敛可能需要数十万个周期)。