数学建模社区-数学中国

标题: 人工神经网络——反向传播算法初体验(python实现) [打印本页]

作者: 杨利霞    时间: 2022-9-12 18:40
标题: 人工神经网络——反向传播算法初体验(python实现)
人工神经网络——反向传播算法初体验(python实现)7 H3 R+ j& ?0 l# K$ o+ \
  q8 u/ W2 K2 @
背景
6 M# U: U) ^' j$ i3 _) x1 p初次接触反向传播算法,根据C语言中文网的站长提供的思路,照着做一遍找一下感觉,其中链接如下
! f  S4 |+ o0 I% h7 M$ ~* f. E' q: e7 d( @0 q
【神经网络分类算法原理详解】
1 Q/ D6 |7 C) J) n0 n4 y; ^* U1 B$ r% g+ ]
注意
( E  Q8 E+ c0 a" @, u# i" ~站长提供的图片有点小问题,我们更正如下
+ r, m& X& f2 P) t
& q; J; S# I0 k8 O! y$ X, P% [% P
$ A' n- S5 z( g) u) J* y
+ Q4 [# F* F2 X7 j+ _* m& n, A/ N问题) l. R, v+ G* F5 l' P& n
根据上图所示,我们有已知
. Q; P) e" W# A) p5 L* W% V# A* a7 D* V' p4 N
#输入层4 y' q& h, D) e! r; ^; |( M
i1=0.05
. p6 G  f  d' k! t. j# Z7 vi2=0.17 B7 M6 ]1 D' }" @' @

% e# g$ S, B9 C7 [) b: n4 n#输出层
' [) R1 \5 q' o  S1 ]% Ao1=0.01
) [. U3 j1 N. `! l9 F; no2=0.99
& ?; \( G2 l6 I. w( g/ B/ t这个神经网络是我们假想的,我们假想从输入层[i1,i2]==>>[o1,o2]的过程是这样的% v/ j+ g2 |* @: n! g' w- ~, c/ x3 a
# K5 f6 m5 h! c: g0 A: {
神经元h1的输入(h1 input 简写为 hi1)=w1*i1+w2*i2+b11 d0 R# q& {* W% M4 v

  C% b5 N& F) H/ z3 _, v6 `神经元h2的输入  (hi2)=w3*i1+w4*i2+b15 U/ N& V: G. U2 q- [; d" Q* j1 {0 x

5 l( _% q! P# t7 _. w( ^神经元h1接收到输入后,通过非线性转换函数【这里选择Sigmoid函数】变换得到神经元h1的输出
0 i7 \8 X- z0 F1 T) [% B, g) b0 X3 Z- p3 c
神经元h1的输出  (ho1)=1.0/(1+math.exp((-1)*神经元h1的输入))
0 h0 Z, l( R3 W7 m0 M  W& e+ }  l! o/ m* L- a* f, w6 b# y  D6 N
同理
! `/ D6 R9 O& }# L/ I, P; n4 Z" j- H7 w- f5 ]0 a) M) @- ~' r/ {
神经元h2的输出  (ho2)=1.0/(1+math.exp((-1)*神经元h2的输入))9 g. \" t9 U& r+ P% p+ o4 A: ]7 y, k* a

4 d  Y: x. ~$ U2 }' W接下来我们再把隐藏层当作输入层,输出层当作隐藏层,类比推出有关神经元o1,神经元o2的一些表达式
1 @& q0 Q' W0 V% O* L' H  ~% n2 h( Q9 i" a2 ~% [* B% L  j
神经元o1的输入 (oi1)=w5*ho1+w6*ho2+b2; L3 c2 _5 U! Y- Q- A

5 e9 J0 z+ Z% S4 _5 F$ ^, @. |神经元o2的输入 (oi2)=w7*ho1+w8*ho2+b2& h( j2 Y) b4 A7 L- v8 ]7 {9 {

: V; [% ^& B5 ~, Z再经过非线性变换Sigmoid函数得到. p1 W! C. h$ V) Y

1 j$ q% H9 h+ F/ |& f神经元o1的输出 (oo1)=1.0/(1+math.exp((-1)*oi1))
) h4 K3 R" T" A/ S, W! b
7 r# I' ~. p$ r) x神经元o2的输出 (oo2)=1.0/(1+math.exp((-1)*oi2))
8 J9 m+ V7 r1 K0 S* n% m+ O6 P8 S& u0 y% `3 u. k5 a/ Q
我们将得到的神经元o1输出,神经元o2输出跟我们知道的期望值o1,o2进行比对,定义其损失函数为7 q& \& O( e% b! K6 }5 K( H- b

  e0 T1 l, [! E8 X! z9 V$ W; B损失值  ( error 简写为 eo)=((oo1-o1)^2+(oo2-o2)^2)/2$ S; M# ~/ x  Z8 ^
/ ^7 r' U- b2 o# E5 V
由于我们的期望值精确到小数点后两位,损失函数为平方,所以我们仅需让损失容忍度(eo_allow)调整到1e-5即可满足  I6 t' ~8 g/ Y9 U% M

- }  V' `1 x% n. [! L7 Z学习次数 (learning_time 简写为 lt)我们限定最大为10000次
( b( |/ ?+ n" N; @0 F1 `1 w0 {, G( P. m  \/ j. q& ]9 p
学习率 (learning_rate 简写为 lr)我们设定为0.5& u' _2 F) D/ P' I% L# D# D9 Q
! o8 `2 q( ?1 W3 Q% i6 z
依次求解代求参数
3 ~9 {( t) D6 c* c) ^
% M' ^% |/ U) N7 m7 P* a; Lw1~w8,以及b1,b2
  F6 K7 A% s" L3 l( s
! ?5 A8 S6 g/ F& m) n
/ s8 [: T+ H: ?% [, Y! p; A) G1 V# X5 R- N
损失值 (eo) 的偏导数
# G/ q+ g9 }- G& ?4 o& E7 T
+ V: ~4 S! S1 E/ |4 g. N3 q再更新该参数,更新公式为( I9 R5 d, F2 X: M: g6 l  q; J' t

9 a9 u1 @/ _; X; ?1 I" J; W. l5 B参数_new=参数-学习率*偏导(eo,参数)& W& I2 _; ]; A$ O/ _- X
随后进入下一轮学习2 q7 v% J; Q2 i. S, T, B$ ]9 N

3 O# W! g: D3 M  f! v% C终止条件(满足其中一个即可停止训练)" N5 D# g9 ?7 Y8 C# r

4 o% e  i% I9 x8 w4 @( f1.学习次数达到上限0 q2 E4 U9 n0 g. y" v  E- Q
. l  \' H: Z- B6 }
2.损失值达到可容忍的范围) V4 w  H) k( p" p0 \9 X+ x
" p3 y9 s* v* N9 ]; \8 o$ J. T4 s
导数
$ y. Y. [0 w( Rf(x)=1/(1+e^(-x))的导数是; l; V; r& k( ~5 {  k% M2 L
f'(x)=f(x)*(1-f(x))
4 H: Y. E, b+ t) a- \" X源码
. h4 e9 C1 N9 M7 bimport math
/ @' H0 P! q$ j& E. z: v# k: }8 A3 M' {9 b( e0 @5 }. h. o+ m* G
#参考自网址【http://c.biancheng.net/ml_alg/ann-principle.html】
4 A! `- c- ^. R- N9 F#网址中图片有误,请看我博文上的图片
9 v2 O) T9 r+ f' J* c& r% Q6 a0 s0 N$ f* ]
#输入层" _. Q& I' a( g& p, u* ~
i1=0.05
, |+ I2 `5 r# F! T- di2=0.1
7 ^; l( U1 Z: Y9 Y6 U9 T! e9 \#权值参数  s# D/ H  M0 P0 Y
w1=0.15
3 V0 l$ }+ o7 k; Ww2=0.2% ]; ^- V# t" n1 W* q1 F0 G
w3=0.25! {; {1 p; C1 ]( k5 q# T/ z
w4=0.3
4 k4 e, n1 e' O5 v6 X4 Z8 Pw5=0.4# ]' P) G3 i* V& a. s3 M
w6=0.45
+ x- x4 G: p0 pw7=0.5& ?0 E) l- P0 |
w8=0.55
3 D, n/ r+ {! g7 w#输出层标记(即期望值)
& J2 l3 k7 y( Y- S/ S, t% ~o1=0.01
. f4 l; o: i) w0 go2=0.99
$ b( b+ E: e" E#偏置项参数
7 S0 [5 u2 }) e% F9 [b1=0.35+ k! v  M! s7 `$ q2 ^) R
b2=0.6  M, r" T1 ~+ ^# E

4 ~# V$ \/ ^- q* w% }#学习率! }( Z: @" T+ `# b! m/ D
lr=0.5
! N/ Q6 r2 r5 e. \2 K0 x- L+ B* j#学习周期
7 ]" w2 F& U5 ~, Y- ~" H2 Ilt=02 w2 s' B3 f$ c- d  [9 U
max_lt=10000
$ o. X8 f2 X/ }#允许误差- c5 x! T- G( ]
eo_allow=1e-56 S. s' v9 C& I- H8 x9 T3 l  I; G
& i4 o2 t7 K6 A# B
#线性转换- p5 C/ a7 k1 B# g" Q- b+ G
def linear(w_one,w_two,i_one,i_two,b):8 F6 ~  N  D; H
    return w_one*i_one+w_two*i_two+b7 a0 c# r1 x6 L$ P
#非线性转换- K; G! L- x$ e- |
def none_linear(i):
3 Q' j& I# P! ?    return 1.0/(1+math.exp(-i))
1 n# h3 u; p5 z! m$ k3 ~/ W" c+ h1 o2 f5 a/ ?9 U& w
print("训练开始")3 h  z; R3 p8 }* v9 @
#学习周期结束前一直学习
: C2 [7 D) f  m2 x  T0 Cwhile lt<max_lt:
8 @& ^) c% ?: \( B    lt+=1( @$ c# q# Y* x5 i. t
    #求h1和h2输入值
& D! L: @" e7 @& J. z! q# _    hi1=linear(w1,w2,i1,i2,b1)' c. ^: z) E6 T
    hi2=linear(w3,w4,i1,i2,b1)
" {1 q+ S! `9 x, x6 J    #求h1和h2输出值
! V& W8 N1 s. o5 i    ho1=none_linear(hi1)4 f0 D: k, Y# G' s6 ~; N
    ho2=none_linear(hi2)
0 @1 V( z% u, H5 @+ E3 Q    #求o1和o2输入值& Q1 d0 }1 ~- \8 F; a* u  Y
    oi1=linear(w5,w6,ho1,ho2,b2)
1 }' I4 R. [  f. e- z( G    oi2=linear(w7,w8,ho1,ho2,b2)
7 S3 [" X/ ^* C0 n    #求o1和o2输出值2 }. d  @" r9 c5 @8 A! Q! Q
    oo1=none_linear(oi1)+ R7 r7 }+ |! S( \7 `* i! L
    oo2=none_linear(oi2)" P7 L# w9 a" Z
2 v2 h8 W+ e" l# Z: P; G" z) s
    #求当前计算总误差
7 O, O$ M- P! ^* w. V# J; S# ?% x! K* U+ u    eo=(math.pow(oo1-o1,2)+math.pow(oo2-o2,2))/2& D! G/ u9 J3 g1 J/ H
    print(f"第{lt}次训练,当前计算总误差={eo}")0 }- F; |4 y4 ^5 s; E. C; G
    #误差已经在允许范围,退出训练
& j7 Y- C7 u' Y0 U: r! j/ m6 j' m    if eo<eo_allow:
! ^3 m, }6 Y6 e3 |* P) R        print("误差已经在允许范围,训练结束\n"). @8 O( I" L  ^6 g
        break
1 r3 D; ?6 {5 u7 e8 M    #偏导
' a& Y+ d, _. V# Y* n    d_eo_oo1=oo1-o1
3 A# S0 c! M  ]+ x' L3 ~+ B    d_eo_oo2=oo2-o2
9 n! V! h6 @" a, h% ^3 |    d_oo1_oi1=oo1*(1-oo1)6 ]3 S: u2 M6 P' ^7 U0 I, p; L
    d_oo2_oi2=oo2*(1-oo2); P3 |3 o2 P7 I4 E% j& D* I
    d_eo_oi1=d_eo_oo1*d_oo1_oi1, h7 J3 n/ a  z1 h
    d_eo_oi2=d_eo_oo2*d_oo2_oi2
" _8 F% D( M/ {- W1 g; P+ ~    #求w5_new% F0 e' _  {" V* v: r4 A  a1 K
    d_oi1_w5=ho1
& @8 X- C3 L5 y) {" l    d_eo_w5=d_eo_oi1*d_oi1_w5
1 {1 s' K6 b2 N& n0 G' L    w5_new=w5-lr*d_eo_w5; \( j" b1 T" V% r  a! F- _, Y3 w& _
    #求w6_new+ c& o' D  {2 o
    d_oi1_w6=ho2
+ Q- H. X2 j3 U; e! M2 N. y9 p  V    d_eo_w6=d_eo_oi1*d_oi1_w6" o- E* J+ h2 ~' M0 ]- l  _$ S  s
    w6_new=w6-lr*d_eo_w6* Z+ K/ i& `$ f  x: b* E8 g
    #求w7_new
1 Z9 {3 M9 r5 t4 d    d_oi2_w7=ho1, S  |& L% R  i: u  b8 S4 _
    d_eo_w7=d_eo_oi2*d_oi2_w7
6 M: ^+ j8 ^' u' x; t$ q+ J2 o1 j    w7_new=w7-lr*d_eo_w7# R( E. W7 n) y1 z" e  }
    #求w8_new
4 d" ^% U4 V0 X' X    d_oi2_w8=ho22 m& v4 M5 q1 E
    d_eo_w8=d_eo_oi2*d_oi2_w8
/ s  o9 j5 b) u& r    w8_new=w8-lr*d_eo_w86 e2 n' i) D! F5 c3 L: Y/ I: Q
    #求b2_new- v1 F! ?3 R( d6 _% l) j& B$ b3 d
    d_oi1_b2=1
* P. N- }, E. D' M$ T* p    d_oi2_b2=1
" H8 L' h( z0 K- m# u; c    d_eo_b2=d_eo_oi1*d_oi1_b2+d_eo_oi2*d_oi2_b2
9 \) ~$ |0 z& M/ r    b2_new=b2-lr*d_eo_b2
$ ^/ h1 W9 w' U# L1 x- O    d_oi1_ho1=w5
" S$ J" C) K* |0 C    d_oi1_ho2=w6
5 }6 V4 u- T! K0 T0 Q$ a! b    d_oi2_ho1=w7- Z% d2 e8 G8 h4 a  S, `
    d_oi2_ho2=w82 A0 e) R1 h# N: I, D  G3 w
    d_eo_ho1=d_eo_oi1*d_oi1_ho1+d_eo_oi2*d_oi2_ho1' S6 X3 J. Q7 s. g! }& f7 r7 ~
    d_eo_ho2=d_eo_oi1*d_oi1_ho2+d_eo_oi2*d_oi2_ho2
/ I0 _7 B) c' i  q    d_ho1_hi1=ho1*(1-ho1)
8 a, N8 M) i7 I5 V5 `% c    d_ho2_hi2=ho2*(1-ho2)
3 \( P! g, D% t" j3 i/ t    d_eo_hi1=d_eo_ho1*d_ho1_hi1: S5 M! H$ C' {$ a8 a
    d_eo_hi2=d_eo_ho2*d_ho2_hi2
) v1 h/ f# W3 z1 u4 C. N% ?    #求w1_new
) A1 k$ {0 c# X( q/ J# p% r& C    d_hi1_w1=i1, d) |6 X$ j: S) p' e$ _) v
    d_eo_w1=d_eo_hi1*d_hi1_w1& h% `7 I$ P% [$ Z& q! ~% C# X
    w1_new=w1-lr*d_eo_w1
7 N3 _5 E! f2 B! X7 v    #求w2_new: e/ F  w. W  ^0 _. g
    d_hi1_w2=i2. O0 n8 y! T: F- n
    d_eo_w2=d_eo_hi1*d_hi1_w2! n, m% K+ [0 L$ Q
    w2_new=w2-lr*d_eo_w2
, O) b8 p  J' D1 D& t( J8 o    #求w3_new
4 k/ V+ W4 b& H    d_hi2_w3=i1
' @, T, ~: o9 D" J% g! t1 }. G    d_eo_w3=d_eo_hi2*d_hi2_w3, E5 Q" T5 p! Q+ J% }
    w3_new=w3-lr*d_eo_w32 ~( I. N" E, @0 I
    #求w4_new
3 d/ t+ @4 u4 Q0 O    d_hi2_w4=i21 t3 e' L/ O) ]' d( R/ p* u: _
    d_eo_w4=d_eo_hi2*d_hi2_w4; d) A7 B  A% r* L# m# T) u  u
    w4_new=w4-lr*d_eo_w4
+ `/ ?% a3 ?3 }3 ~" ^# c    #求b1_new
" @% r8 L# w0 J. L0 u/ }' o    d_hi1_b1=1( F* p+ J: e' E
    d_hi2_b1=1+ I. R2 H6 P3 C  w0 ~8 B' w
    d_eo_b1=d_eo_hi1*d_hi1_b1+d_eo_hi2*d_hi2_b1
0 M, r: M: e2 u( x( E    b1_new=b1-lr*d_eo_b1) A! d( O( s' K+ x1 B
    #更新反向传播
# }( z5 f) u, y  A" H' H    w1=w1_new; e! R; W1 p' P- }
    w2=w2_new
" n" `# _3 M7 X9 I% n- Z    w3=w3_new
& Y- t+ e" W# ?+ h: A. k    w4=w4_new  W: c2 `. f# H
    b1=b1_new: q; {' u: }% C& s* |. w
    w5=w5_new) q0 _7 O. G2 z8 D6 E# I$ v1 L1 U
    w6=w6_new
# ]& i/ B0 M- \    w7=w7_new8 @# Y' D  X# y) {3 d- s  `9 \0 ^
    w8=w8_new
9 l: W: L5 C3 j) D3 S! i- J6 b    b2=b2_new
- h0 X7 q& Q9 K2 ]! x2 uprint(f"当前计算总误差={eo}")! t4 Q" D0 H' x9 j
print(f"w1={w1}\nw2={w2}\nw3={w3}\nw4={w4}\nb1={b1}\n")
% J* Q  [2 Y3 e- G9 n+ ~  sprint(f"w5={w5}\nw6={w6}\nw7={w7}\nw8={w8}\nb2={b2}\n")
9 r) ~5 B0 T0 _5 ~$ qprint(f"期望值:[{o1},{o2}],预测值:[{oo1},{oo2}]"): W% `9 y7 E  ~5 j" s- L, k
) L1 n3 Y& j7 ]  R% R# z8 Q
结果8 {( O6 ^2 Q8 u2 L) G

; r. d4 J! m! r/ t. i
$ ?2 e# X  o. M结语3 e6 G# \0 e* v
可以看到,在经过七千多次训练之后,我们找到了一组参数满足我们假想的关系,本次人工神经网络训练完成,反向传播算法体验结果良好。
2 x8 R# e5 A5 P5 ?9 N
8 F% D- b7 u2 S8 j( P" N( {. a补充
$ u% M; p6 c! e/ I; |程序中d_{a}_{b}格式的变量表示a对b偏导
6 J! E, F+ l. U————————————————
% |" Z$ ?0 _( j* \) c版权声明:本文为CSDN博主「冰凌呀」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
+ Z+ N, W  A* \  e原文链接:https://blog.csdn.net/qq_36694133/article/details/126667954
8 }) y1 j# h7 f/ V8 J
' y; t: A# e8 a
$ `& G' a0 W/ s$ W3 u# Y




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5