BP神经网络求解异或算法
一、BP神经网络
BP算法包括信号的前向传播和误差的反向传播两个过程。即计算误差输出时按从输入到输出的方向进行,而调整权值和阈值则从输出到输入的方向进行。
正向传播时,输入信号通过隐含层作用于输出节点,经过非线性变换,产生输出信号,若实际输出与期望输出不相符,则转入误差的反向传播过程。
误差反传是将输出误差通过隐含层向输入层逐层反传,并将误差分摊给各层所有单元,以从各层获得的误差信号作为调整各单元权值的依据。通过调整输入节点与隐层节点的联接强度和隐层节点与输出节点的联接强度以及阈值,使误差沿梯度方向下降,经过反复学习训练,确定与最小误差相对应的网络参数(权值和阈值),训练即告停止。此时经过训练的神经网络即能对类似样本的输入信息,自行处理输出误差最小的经过非线形转换的信息
下面以单隐藏层为例,进行输出值的公式推导,其结构示意图如下:
在实际实验过程中我们会依据预测输出值
o
1
o_1
o1与实际输出值的误差或者自定义学习率,对前面计算过程中的
W
11
W_{11}
W11
W
21
W_{21}
W21
V
11
V_{11}
V11
V
12
V_{12}
V12
V
21
V_{21}
V21 以及
V
22
V_{22}
V22进行新的值的计算。
二、激活函数
在神经元中,输入的 inputs 通过加权,求和后,还被作用了一个函数,这个函数就是激活函数。引入激活函数是为了增加神经网络模型的非线性。没有激活函数的每层都相当于矩阵相乘。就算你叠加了若干层之后,无非还是个矩阵相乘
如图所示,如果没有激活函数
f
f
f的值就是
x
1
x_1
x1
x
2
x2
x2与相关系数矩阵的乘积之和,是线性的,对于非线性函数的预测不能很好地体现。
针对这种情况我们引入了激活函数,激活函数是非线性函数,常见的激活函数如下:
(1)Sigmoid函数
Sigmoid函数是一个在生物学中常见的S型函数,也称为S型生长曲线。在信息科学中,由于其单增以及反函数单增等性质,Sigmoid函数常被用作神经网络的阈值函数,将变量映射到0,1之间,公式如下:
f
(
x
)
=
1
1
+
e
−
x
f(x)= \frac{1}{1+e^{-x}}
f(x)=1+e−x1
(2)Tanh函数
Tanh是双曲函数中的一个,Tanh()为双曲正切。在数学中,双曲正切“Tanh”是由基本双曲函数双曲正弦和双曲余弦推导而来。公式如下:
f
(
x
)
=
e
x
−
e
−
x
e
x
+
e
−
x
f(x)= \frac{e^x-e^{-x}}{e^x+e^{-x}}
f(x)=ex+e−xex−e−x
(3)ReLU函数
Relu激活函数(The Rectified Linear Unit),用于隐层神经元输出。公式如下:
f
(
x
)
=
m
a
x
(
0
,
x
)
f(x)=max(0,x)
f(x)=max(0,x)
三、异或求解
该方法中,我采用的RELU函数作为激活函数,程序代码如下:
import numpy as np
def com(x, deriv = False):
if(deriv == True):
return x*(1-x)
else:
return 1/(1+np.exp(-x))
#输入数据
x = np.array([[0,0],[0,1],[1,0],[1,1]])
#输出数据
y = np.array([[0],[1],[1],[0]])
#定义学习率
#learning_rate = 1e-6
#卷积计算权重初始值随机化
w1 = 2*np.random.random((2,4))-1
w2 = 2*np.random.random((4,2))-1
w3 = 2*np.random.random((2,1))-1
for i in range(20000):
#根据初始权重得到隐藏层数据
h1 = com(np.dot(x,w1))
#矩阵中小于0的数据为0,大于0的数据不改变
h_relu = np.maximum(h1, 0)
h2 = com(np.dot(h_relu,w2))
h3 = com(np.dot(h2,w3))
#误差
h3_loss = y - h3
h3_grad = h3_loss*com(h3,deriv = True)
h2_loss = h3_grad.dot(w3.T)
h2_grad = h2_loss*com(h2,deriv = True)
h1_loss = h2_grad.dot(w2.T)
h1_grad = h1_loss*com(h1,deriv = True)
w3 += h2.T.dot(h3_grad)
w2 += h1.T.dot(h2_grad)
w1 += x.T.dot(h1_grad)
print("out after training")
print(h3)
得到程序运行结果如下:
由输出结果可知,预测结果比较符合实际。