人工神经网络——反向传播算法初体验(python实现)

背景

初次接触反向传播算法,根据C语言中文网的站长提供的思路,照着做一遍找一下感觉,其中链接如下

神经网络分类算法原理详解

注意

站长提供的图片有点小问题,我们更正如下

问题

根据上图所示,我们有已知

#输入层
i1=0.05
i2=0.1

#输出层
o1=0.01
o2=0.99

这个神经网络是我们假想的,我们假想从输入层[i1,i2]==>>[o1,o2]的过程是这样的

神经元h1的输入(h1 input 简写为 hi1)=w1*i1+w2*i2+b1

神经元h2的输入  (hi2)=w3*i1+w4*i2+b1

神经元h1接收到输入后,通过非线性转换函数【这里选择Sigmoid函数】变换得到神经元h1的输出

神经元h1的输出  (ho1)=1.0/(1+math.exp((-1)*神经元h1的输入))

同理

神经元h2的输出  (ho2)=1.0/(1+math.exp((-1)*神经元h2的输入))

接下来我们再把隐藏层当作输入层,输出层当作隐藏层,类比推出有关神经元o1,神经元o2的一些表达式

神经元o1的输入 (oi1)=w5*ho1+w6*ho2+b2

神经元o2的输入 (oi2)=w7*ho1+w8*ho2+b2

再经过非线性变换Sigmoid函数得到

神经元o1的输出 (oo1)=1.0/(1+math.exp((-1)*oi1))

神经元o2的输出 (oo2)=1.0/(1+math.exp((-1)*oi2))

我们将得到的神经元o1输出,神经元o2输出跟我们知道的期望值o1,o2进行比对,定义其损失函数为

损失值  ( error 简写为 eo)=((oo1-o1)^2+(oo2-o2)^2)/2

由于我们的期望值精确到小数点后两位,损失函数为平方,所以我们仅需让损失容忍度(eo_allow)调整到1e-5即可满足

学习次数 (learning_time 简写为 lt)我们限定最大为10000次

学习率 (learning_rate 简写为 lr)我们设定为0.5

依次求解代求参数

w1~w8,以及b1,b2

损失值 (eo) 的偏导数

再更新该参数,更新公式为

参数_new=参数-学习率*偏导(eo,参数)

随后进入下一轮学习

终止条件(满足其中一个即可停止训练)

1.学习次数达到上限

2.损失值达到可容忍的范围

导数

f(x)=1/(1+e^(-x))的导数是
f'(x)=f(x)*(1-f(x))

源码

import math

#参考自网址【http://c.biancheng.net/ml_alg/ann-principle.html】
#网址中图片有误,请看我博文上的图片

#输入层
i1=0.05
i2=0.1
#权值参数
w1=0.15
w2=0.2
w3=0.25
w4=0.3
w5=0.4
w6=0.45
w7=0.5
w8=0.55
#输出层标记(即期望值)
o1=0.01
o2=0.99
#偏置项参数
b1=0.35
b2=0.6

#学习率
lr=0.5
#学习周期
lt=0
max_lt=10000
#允许误差
eo_allow=1e-5

#线性转换
def linear(w_one,w_two,i_one,i_two,b):
    return w_one*i_one+w_two*i_two+b
#非线性转换
def none_linear(i):
    return 1.0/(1+math.exp(-i))

print("训练开始")
#学习周期结束前一直学习
while lt<max_lt:
    lt+=1

    #求h1和h2输入值
    hi1=linear(w1,w2,i1,i2,b1)
    hi2=linear(w3,w4,i1,i2,b1)

    #求h1和h2输出值
    ho1=none_linear(hi1)
    ho2=none_linear(hi2)

    #求o1和o2输入值
    oi1=linear(w5,w6,ho1,ho2,b2)
    oi2=linear(w7,w8,ho1,ho2,b2)

    #求o1和o2输出值
    oo1=none_linear(oi1)
    oo2=none_linear(oi2)
    
    #求当前计算总误差
    eo=(math.pow(oo1-o1,2)+math.pow(oo2-o2,2))/2
    print(f"第{lt}次训练,当前计算总误差={eo}")

    #误差已经在允许范围,退出训练
    if eo<eo_allow:
        print("误差已经在允许范围,训练结束\n")
        break

    #偏导
    d_eo_oo1=oo1-o1
    d_eo_oo2=oo2-o2

    d_oo1_oi1=oo1*(1-oo1)
    d_oo2_oi2=oo2*(1-oo2)

    d_eo_oi1=d_eo_oo1*d_oo1_oi1
    d_eo_oi2=d_eo_oo2*d_oo2_oi2

    #求w5_new
    d_oi1_w5=ho1
    d_eo_w5=d_eo_oi1*d_oi1_w5
    w5_new=w5-lr*d_eo_w5
    #求w6_new
    d_oi1_w6=ho2
    d_eo_w6=d_eo_oi1*d_oi1_w6
    w6_new=w6-lr*d_eo_w6
    #求w7_new
    d_oi2_w7=ho1
    d_eo_w7=d_eo_oi2*d_oi2_w7
    w7_new=w7-lr*d_eo_w7
    #求w8_new
    d_oi2_w8=ho2
    d_eo_w8=d_eo_oi2*d_oi2_w8
    w8_new=w8-lr*d_eo_w8
    #求b2_new
    d_oi1_b2=1
    d_oi2_b2=1
    d_eo_b2=d_eo_oi1*d_oi1_b2+d_eo_oi2*d_oi2_b2
    b2_new=b2-lr*d_eo_b2

    d_oi1_ho1=w5
    d_oi1_ho2=w6
    d_oi2_ho1=w7
    d_oi2_ho2=w8

    d_eo_ho1=d_eo_oi1*d_oi1_ho1+d_eo_oi2*d_oi2_ho1
    d_eo_ho2=d_eo_oi1*d_oi1_ho2+d_eo_oi2*d_oi2_ho2

    d_ho1_hi1=ho1*(1-ho1)
    d_ho2_hi2=ho2*(1-ho2)

    d_eo_hi1=d_eo_ho1*d_ho1_hi1
    d_eo_hi2=d_eo_ho2*d_ho2_hi2

    #求w1_new
    d_hi1_w1=i1
    d_eo_w1=d_eo_hi1*d_hi1_w1
    w1_new=w1-lr*d_eo_w1
    #求w2_new
    d_hi1_w2=i2
    d_eo_w2=d_eo_hi1*d_hi1_w2
    w2_new=w2-lr*d_eo_w2
    #求w3_new
    d_hi2_w3=i1
    d_eo_w3=d_eo_hi2*d_hi2_w3
    w3_new=w3-lr*d_eo_w3
    #求w4_new
    d_hi2_w4=i2
    d_eo_w4=d_eo_hi2*d_hi2_w4
    w4_new=w4-lr*d_eo_w4
    #求b1_new
    d_hi1_b1=1
    d_hi2_b1=1
    d_eo_b1=d_eo_hi1*d_hi1_b1+d_eo_hi2*d_hi2_b1
    b1_new=b1-lr*d_eo_b1

    #更新反向传播
    w1=w1_new
    w2=w2_new
    w3=w3_new
    w4=w4_new
    b1=b1_new
    w5=w5_new
    w6=w6_new
    w7=w7_new
    w8=w8_new
    b2=b2_new

print(f"当前计算总误差={eo}")
print(f"w1={w1}\nw2={w2}\nw3={w3}\nw4={w4}\nb1={b1}\n")
print(f"w5={w5}\nw6={w6}\nw7={w7}\nw8={w8}\nb2={b2}\n")
print(f"期望值:[{o1},{o2}],预测值:[{oo1},{oo2}]")

结果

结语

可以看到,在经过七千多次训练之后,我们找到了一组参数满足我们假想的关系,本次人工神经网络训练完成,反向传播算法体验结果良好。

补充

程序中d_{a}_{b}格式的变量表示a对b偏导

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值