#BP神经网络简单python实现
BP神经网络的算法推导详见前面的文章:BP神经网络算法推导
##样例示意图
假设输入层有3个神经元,隐藏层有4个神经元,输出层有1个神经元,如图所示:
##样例参数说明
如图所示,隐藏层的结果(输出)为 Y → = X → × V i j \overrightarrow{Y} = \overrightarrow{X} \times V_{ij} Y=X×Vij:
{ y 0 = x 0 V 00 + x 1 V 10 + x 2 V 20 y 1 = x 0 V 01 + x 1 V 11 + x 2 V 21 y 2 = x 0 V 02 + x 1 V 12 + x 2 V 22 y 3 = x 0 V 03 + x 1 V 13 + x 2 V 23 \left\{ \begin{aligned} y_{0}=x_{0}V_{00}+x_{1}V_{10}+x_{2}V_{20} \\ y_{1}=x_{0}V_{01}+x_{1}V_{11}+x_{2}V_{21} \\ y_{2}=x_{0}V_{02}+x_{1}V_{12}+x_{2}V_{22} \\ y_{3}=x_{0}V_{03}+x_{1}V_{13}+x_{2}V_{23} \end{aligned} \right. ⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧y0=x0V00+x1V10+x2V20y1=x0V01+x1V11+x2V21y2=x0V02+x1V12+x2V22y3=x0V03+x1V13+x2V23
以向量形式表示出来:
( y 0 → y 1 → y 2 → y 3 → ) 4 × 4 = ( x 0 → x 1 → x 2 → ) 4 × 3 ( V 00 V 01 V 02 V 03 V 10 V 11 V 12 V 13 V 20 V 21 V 22 V 23 ) 3 × 4 \Big(\overrightarrow{y_{0}} \overrightarrow{y_{1}} \overrightarrow{y_{2}} \overrightarrow{y_{3}} \Big)_{4\times 4} = \Big(\overrightarrow{x_{0}} \overrightarrow{x_{1}} \overrightarrow{x_{2}} \Big)_{4\times 3} \left( \begin{matrix} V_{00} & V_{01} & V_{02} & V_{03} \\ V_{10} & V_{11} & V_{12} & V_{13} \\ V_{20} & V_{21} & V_{22} & V_{23} \end{matrix} \right)_{3\times 4} (y0y1y2y3)4×4=(x0x1x2)4×3⎝⎛V00V10V20V01V11V21V02V12V22V03V13V23⎠⎞3×4
输出层的结果为 O → = Y → × W j k \overrightarrow{O} = \overrightarrow{Y} \times W_{jk} O=Y×Wjk:
O → 4 × 1 = ( y 0 → y 1 → y 2 → y 3 → ) 4 × 4 × ( W 0 W 1 W 2 W 3 ) 4 × 1 \overrightarrow{O}_{4\times 1} =\Big(\overrightarrow{y_{0}} \overrightarrow{y_{1}} \overrightarrow{y_{2}} \overrightarrow{y_{3}} \Big)_{4\times 4} \times \left( \begin{matrix} W_{0} \\ W_{1} \\ W_{2} \\ W_{3} \end{matrix} \right)_{4\times 1} O4×1=(y0y1y2y3)4×4×⎝⎜⎜⎛W0W1W2W3⎠⎟⎟⎞4×1
因为本例子使用3层BP神经网络解决异或问题,则输入为00,01,10,11,期望得到的输出为0,1,1,0,如下所示:
( X 0 X 1 X 2 d e s i r e 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 0 ) \left( \begin{matrix} X_{0} & X_{1} & X_{2} & d_{esire}\\ 1 & 0 & 0 & 0\\ 1 & 0 & 1 & 1\\ 1 & 1 & 0 & 1\\ 1 & 1 & 1 & 0 \end{matrix} \right) ⎝⎜⎜⎜⎜⎛X01111X10011X20101desire0110⎠⎟⎟⎟⎟⎞
##代码实现
#导入numpy包(用python实现的科学计算包)
import numpy as np
#输入数据X,异或问题的输入00,01,10,11,加上X0,组成4x3的输入矩阵
X = np.array([[1,0,0],
[1,0,1],
[1,1,0],
[1,1,1]])
#期望输出Desire,根据输入对应的期望输出为0,1,1,0
D = np.array([[0,1,1,0]])
#权值初始化,取值范围-1到1
V = np.random.random((3,4))*2-1
W = np.random.random((4,1))*2-1
#打印权值V的初始值
print(V)
#打印权值W的初始值
print(W)
#学习率Learning Rate设置,学习率太大迭代次数少了,但是不够准确,学习率太小会导致迭代次数过高还无法得到较好结果,这里将学习率设置为0.11
lr = 0.11
#定义sigmoid转移函数,取值范围为(0,1)
def sigmoid(x):
return 1/(1+np.exp(-x))
#定义sigmoid函数的导数
def dsigmoid(x):
return x*(1-x)
#定义权值更新函数
def update():
global X,D,V,W,lr #X为输入,D为期望输出,V为输入层到隐藏层的权值,W为隐藏层到输出层的权值,lr为学习率
Y = sigmoid(np.dot(X,V))#隐藏层输出(4x4)
O = sigmoid(np.dot(Y,W))#输出层实际输出(4x1)
#误差信号O_delta及Y_delta
O_delta = (D.T - O)*dsigmoid(O)
Y_delta = O_delta.dot(W.T)*dsigmoid(Y)
#权值的改变值
W_C = lr*Y.T.dot(O_delta)
V_C = lr*X.T.dot(Y_delta)
#更新权值
W = W + W_C
V = V + V_C
#迭代20000次,进行权值更新,每个500次打印一下误差,观察误差的变化过程,误差求法为理想输出-实际输出,求绝对值后取均值。
for i in range(20000):
update()#更新权值
if i%500==0:
Y = sigmoid(np.dot(X,V))#隐藏层输出(4,4)
O = sigmoid(np.dot(Y,W))#输出层输出(4,1)
print('Error:',np.mean(np.abs(D.T-O)))
#打印最终输出值Output
Y = sigmoid(np.dot(X,V))#隐藏层输出(4,4)
O = sigmoid(np.dot(Y,W))#输出层输出(4,1)
print(O)
#定义一个函数,将最终的输出用0和1来表示
def judge(x):
if x>=0.5:
return 1
else:
return 0
#利用map函数将输出O传入judge函数中
for i in map(judge,O):
print(i)
欢迎访问我的个人简介
http://www.wyfshu.xyz
Email:[email protected]
2018-01-16