数学建模社区-数学中国

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

作者: 杨利霞    时间: 2022-9-12 18:40
标题: 人工神经网络——反向传播算法初体验(python实现)
人工神经网络——反向传播算法初体验(python实现)
( p# l6 q6 d/ B0 s6 M% b# T. |) I# u. ?4 ]
背景/ d6 ~/ J& a# H# O& b! s
初次接触反向传播算法,根据C语言中文网的站长提供的思路,照着做一遍找一下感觉,其中链接如下+ q" Y! d* q5 k+ l

" _3 V' L3 W4 h) H【神经网络分类算法原理详解】8 M* M8 n: c8 W9 |! E  W1 u
9 j  q/ s$ C8 }5 a
注意
3 Q1 I, {4 f7 G站长提供的图片有点小问题,我们更正如下
3 M+ m* y. m& G* s4 g& s9 h
' Q6 q8 k( G3 D: K  l
1 i+ M" i: ^5 ]
5 M9 m! n. v0 h3 M- s) N) h问题
1 ~, u! H+ t) W$ M: q& o; y根据上图所示,我们有已知
$ c. a1 b1 I9 j0 h4 O' x- O5 U4 q% w3 i. S5 ]$ g# N' o
#输入层. S% a8 b) p4 Q. V, D
i1=0.050 h7 q% V3 y0 n1 B/ a7 j
i2=0.1
0 w& a( T, l' N: e6 r9 @2 |0 q: p! f. O! q
#输出层
4 D5 @  `3 U5 e( \  @o1=0.01# K- X) J8 i8 i, }" j: G
o2=0.99
1 i5 z& T6 s$ t: s1 @/ }. F8 ^4 I这个神经网络是我们假想的,我们假想从输入层[i1,i2]==>>[o1,o2]的过程是这样的
3 }  [! l6 o- O1 o' a  w6 E. m( W3 F$ p' @7 J
神经元h1的输入(h1 input 简写为 hi1)=w1*i1+w2*i2+b13 A( a7 P) S5 K9 \$ A% P
, Q. ^+ A. T; a, h7 t
神经元h2的输入  (hi2)=w3*i1+w4*i2+b16 @) v% q& @" p; i2 \
  n: G- t0 q9 P& u) t$ w! K( z
神经元h1接收到输入后,通过非线性转换函数【这里选择Sigmoid函数】变换得到神经元h1的输出: w$ a# m8 B$ p$ ]/ c. Y3 V+ ~
$ T1 d: X$ a& }! a: `: X! q5 z
神经元h1的输出  (ho1)=1.0/(1+math.exp((-1)*神经元h1的输入))+ d6 `2 }) J8 l
' O  `# ^  x% V) I  z0 c
同理, c; c3 Q! v" C1 }( O- e" M$ G) e2 q: k
0 a" u; }8 r7 W, }! d$ w- Y/ C
神经元h2的输出  (ho2)=1.0/(1+math.exp((-1)*神经元h2的输入))# S% L; N2 P4 F/ Y; \$ ~1 r( p7 w  f

% H/ u1 x; A! ]( M$ P4 x接下来我们再把隐藏层当作输入层,输出层当作隐藏层,类比推出有关神经元o1,神经元o2的一些表达式" Q) U, ~8 ^1 z
- G1 H* H! B& j% R
神经元o1的输入 (oi1)=w5*ho1+w6*ho2+b2
6 G. f, U: P% D3 k9 X, v# |! d) x: u5 Q3 j, L
神经元o2的输入 (oi2)=w7*ho1+w8*ho2+b2
! D; d- s( m' R; G! p
* M7 E( k4 S. Y- G再经过非线性变换Sigmoid函数得到3 ^7 d) v. I4 S- o

$ J- s) Q  W/ H  E神经元o1的输出 (oo1)=1.0/(1+math.exp((-1)*oi1))* X) o; M$ n0 a& a1 _

+ _+ o6 T/ T. Y% ?- k0 O神经元o2的输出 (oo2)=1.0/(1+math.exp((-1)*oi2))
( k. C- a3 u. |
) Q1 w! C' t6 h0 H我们将得到的神经元o1输出,神经元o2输出跟我们知道的期望值o1,o2进行比对,定义其损失函数为
' U* I3 H  N$ m8 t/ {" U
- r) g7 A; c, m/ k损失值  ( error 简写为 eo)=((oo1-o1)^2+(oo2-o2)^2)/2
2 f' R  f& o" D, K# b
7 Q) Q* F5 \6 V* I9 A: e* e由于我们的期望值精确到小数点后两位,损失函数为平方,所以我们仅需让损失容忍度(eo_allow)调整到1e-5即可满足
  X" ?0 H4 r) j( O8 e! n7 B* {# b/ }  r( E. {3 A( W
学习次数 (learning_time 简写为 lt)我们限定最大为10000次
& J1 C  h1 x0 U0 |
, A) A" K9 u; j1 O学习率 (learning_rate 简写为 lr)我们设定为0.5
, g  f8 @. Y  A9 ?! K8 Z. R, p- s9 Y
依次求解代求参数, x& e# d4 M1 n8 Z7 k' N
& P6 z! Q. p6 W. p+ O- D$ s  P1 q
w1~w8,以及b1,b2  C+ ]; J$ y7 P+ p% G" N* H5 b
* b0 m( R/ i& }2 L! \( |: F

! u: ~/ w8 f& h& q0 D) P/ ]; I9 t* x
7 V$ Z/ s. l) B0 Q损失值 (eo) 的偏导数
4 M! ~0 }6 V( @, \( C: ~3 v  ]" A0 {7 F; x9 |) h) |
再更新该参数,更新公式为
7 o* v* K2 S4 C) f0 N. g2 e# R1 d8 ]! I- g% f* U7 ]( b
参数_new=参数-学习率*偏导(eo,参数), d4 a+ Z% l2 d. g
随后进入下一轮学习
- {! r  t- f7 @3 C, p. ^
( K( I! F7 z& Z& w5 Z: i4 e  o终止条件(满足其中一个即可停止训练)
* ~; k4 o7 B  F
  e4 i3 o- X4 h( y- b1.学习次数达到上限
3 b; t- e6 w1 y$ `7 @5 R
+ R: ]. `+ j! ^2.损失值达到可容忍的范围
% ^- Q8 w$ ~5 c$ w) i  w/ A/ O2 F- D0 c/ i& H, {
导数
: S$ V! h$ L3 Zf(x)=1/(1+e^(-x))的导数是
9 z6 L& I8 N8 q' w+ g% Hf'(x)=f(x)*(1-f(x))
5 X1 x: v) v6 o& H% |源码
; Q2 c3 d( E3 y/ j( p4 c' v5 u6 Nimport math5 d  \3 f- B# f

7 U, a! B% x+ `: Y! ~7 G#参考自网址【http://c.biancheng.net/ml_alg/ann-principle.html】& W' M1 a/ b4 `1 p
#网址中图片有误,请看我博文上的图片
3 `! ]; M' ?! O0 @! d0 t: z. U/ e, R: u; j$ S2 j
#输入层- ^& I! h% R, |3 M% {
i1=0.05: H! R( [- Q* _  F0 j
i2=0.13 t$ |8 S. J3 x1 n$ i0 E1 D
#权值参数5 F4 ]- S6 Z0 ^+ T
w1=0.153 E, Z5 _# d' \4 R
w2=0.2
+ ]& j  L- V( H$ Y( Y, }w3=0.25
; y! d! E) _' I7 @- Xw4=0.3
* f0 O3 Y8 M0 V; @2 _" }0 Sw5=0.4
1 _0 j) l& o8 x5 ^; B- \* T; Cw6=0.453 [* Y2 g" E; T& Z: y7 x8 w
w7=0.5
4 T* b( J- D4 N  S2 t/ x' w) Qw8=0.55  J+ O% G& Q2 }: p% u; @
#输出层标记(即期望值)
6 C& i! G5 e& _! `$ i- Oo1=0.01
% t" v$ c0 g+ Q# Jo2=0.99
+ M4 b9 r" g4 f, m; h4 b#偏置项参数! L( `6 x. v; ^
b1=0.355 D+ P5 F: ^& p* i3 [# T; I- q
b2=0.6
1 Z1 d. s1 q8 u. [5 ]3 }  D8 }5 R5 ~4 P) M3 C% p! v
#学习率+ Q5 k, p2 L% @; V
lr=0.5! p4 o1 L. d* D
#学习周期# Z6 ~; s' h! P$ U0 {
lt=0
/ [; z$ K( M! wmax_lt=10000& h) r* n9 a  r4 U! B- c( i: R
#允许误差0 v. z5 \3 k# p
eo_allow=1e-56 n0 l+ h) ~* i& Z. a* `

) @8 h* _0 q! ^3 t#线性转换$ Z* c1 k/ o! \/ X2 M+ B
def linear(w_one,w_two,i_one,i_two,b):
; c1 q; G' S9 t6 ~; o    return w_one*i_one+w_two*i_two+b9 q# u9 J2 }' t" g
#非线性转换% ^. Y% f, f! I% }8 h
def none_linear(i):, N. x. z/ Y( ]* t, N" [5 t$ c, e8 g
    return 1.0/(1+math.exp(-i))
8 @6 [& \# D" I0 I- _5 T8 N: g1 _  k: \. q' x, M! C
print("训练开始")7 s/ `: q3 J* B1 i; a2 ]0 L
#学习周期结束前一直学习
  W# Q* p/ d) o/ Q+ rwhile lt<max_lt:- h; g9 u9 ]# y9 c7 |6 q( X
    lt+=1" S" ?" H' i& d: k* v( O
    #求h1和h2输入值
+ r  E  x$ c" q$ r; h1 q$ y    hi1=linear(w1,w2,i1,i2,b1)* ~% u! p) }/ [% r& o- d
    hi2=linear(w3,w4,i1,i2,b1)& ?$ V/ q/ ^) |) e8 W! L
    #求h1和h2输出值8 |1 Q7 W) i4 F; C
    ho1=none_linear(hi1)  r$ \  P8 x) r0 S9 u
    ho2=none_linear(hi2)
* b: k- a3 x2 C$ \& T    #求o1和o2输入值1 M- [/ E' {$ l, X1 E$ x0 U
    oi1=linear(w5,w6,ho1,ho2,b2)- k" V- h  w" B' X* F; ?% T
    oi2=linear(w7,w8,ho1,ho2,b2)
8 S# \; O# D) X8 A# H, y    #求o1和o2输出值2 [  p% ?# A5 @
    oo1=none_linear(oi1)
+ l9 K7 a" r9 i) U4 V( g7 h/ M: P/ G    oo2=none_linear(oi2)* {$ D# M8 k0 k! r  N
7 T! w6 O- ]- n, K' t
    #求当前计算总误差
& D" t, [: R& C( r    eo=(math.pow(oo1-o1,2)+math.pow(oo2-o2,2))/2
. \% q5 h$ F$ n" b& w6 K) Q7 r    print(f"第{lt}次训练,当前计算总误差={eo}")
' i2 M1 {1 F( a& a+ Y7 l) P2 z) X0 I    #误差已经在允许范围,退出训练
7 ]1 k2 x3 S! P* `' I% o! l    if eo<eo_allow:1 O8 ?  J! D3 w  f; G
        print("误差已经在允许范围,训练结束\n")
, v& V1 g8 {* j* Q: {% @) i        break
% [. \8 l, a3 Y    #偏导  ]7 ^+ [# C' [8 G* O1 ]
    d_eo_oo1=oo1-o13 q+ L& G, Z3 @( _9 W9 b" i
    d_eo_oo2=oo2-o2
9 \9 S8 |/ s+ L- v$ |9 F* D8 q. |    d_oo1_oi1=oo1*(1-oo1)( P  s1 T& A5 r3 Q% \$ S
    d_oo2_oi2=oo2*(1-oo2)
' l) D" t: q; N1 z, ~. d* S, a    d_eo_oi1=d_eo_oo1*d_oo1_oi1
7 s; J; E! c5 q7 v4 d    d_eo_oi2=d_eo_oo2*d_oo2_oi2
8 ]9 Q3 x9 _% Q    #求w5_new3 ^. H. R( y1 l5 q+ p6 h% H
    d_oi1_w5=ho1
- a3 m; Q% U! k" e; f/ H    d_eo_w5=d_eo_oi1*d_oi1_w5- `& {$ _- E9 V: w! u! w8 q
    w5_new=w5-lr*d_eo_w5
2 S% j0 X  w: }# ?8 A$ U/ @    #求w6_new, P5 ^, Z$ G; w) k% V
    d_oi1_w6=ho2  k2 a) q4 V' p/ o- ^. |
    d_eo_w6=d_eo_oi1*d_oi1_w6
: p$ W  y# ~8 H  G/ [    w6_new=w6-lr*d_eo_w6( x1 z+ e/ N: E. n" i
    #求w7_new: z$ ~) W0 U1 C. o9 Z2 s3 C
    d_oi2_w7=ho1; L4 F1 o9 ?1 L4 ^/ f* \
    d_eo_w7=d_eo_oi2*d_oi2_w78 }/ X/ m7 f8 G0 n9 F6 ?/ l+ ]
    w7_new=w7-lr*d_eo_w7$ z, m. L; k' T3 J, E
    #求w8_new
, T' v7 K" @( L& |0 l$ }( L    d_oi2_w8=ho2) p# U+ I1 }& Z  u" Q9 {! v
    d_eo_w8=d_eo_oi2*d_oi2_w8+ B0 {  c3 ~! G' \8 M
    w8_new=w8-lr*d_eo_w8
/ A0 [" H1 N( P4 p; k+ {+ p: u: E    #求b2_new
/ J) F! h3 m( m) R    d_oi1_b2=1
! y( j  }& E/ U7 {! K    d_oi2_b2=18 U7 `+ n- h) f
    d_eo_b2=d_eo_oi1*d_oi1_b2+d_eo_oi2*d_oi2_b2
9 t% [; l" O; I: U* h    b2_new=b2-lr*d_eo_b2; h3 A) j1 F4 x
    d_oi1_ho1=w5. V" @3 }9 o6 T2 i% z" F/ z- t9 Y
    d_oi1_ho2=w6
1 }# C: [$ w4 \, g! r3 v- q0 J    d_oi2_ho1=w7! y$ s/ X0 d1 m2 s5 C7 t$ W0 \" Y, F1 p
    d_oi2_ho2=w88 Z% C2 h% g/ [" L, g
    d_eo_ho1=d_eo_oi1*d_oi1_ho1+d_eo_oi2*d_oi2_ho1
' P( C, R. k* [. q8 p3 \. _2 n* r    d_eo_ho2=d_eo_oi1*d_oi1_ho2+d_eo_oi2*d_oi2_ho2* \2 R7 D- k( f! M9 L7 g" W9 r  v
    d_ho1_hi1=ho1*(1-ho1)
: `8 N$ q' E8 ?4 r8 w, [3 R( E9 C    d_ho2_hi2=ho2*(1-ho2)$ m& v! u7 V) n$ O
    d_eo_hi1=d_eo_ho1*d_ho1_hi1
' W" w! G, {- L1 D' `! ^/ d" j    d_eo_hi2=d_eo_ho2*d_ho2_hi2
- Q6 I. Y# k6 A    #求w1_new5 q% Q2 M9 P' {7 C6 c
    d_hi1_w1=i14 ?  T/ e& i6 G5 `
    d_eo_w1=d_eo_hi1*d_hi1_w1
& e  [& J+ \# E: g- ^. c    w1_new=w1-lr*d_eo_w1
2 m+ ~$ E" s& r$ e    #求w2_new
4 K4 `; X  B6 e0 Y+ a    d_hi1_w2=i24 K# O, D$ \! v, l8 X& y7 [3 t7 S
    d_eo_w2=d_eo_hi1*d_hi1_w2
) B# E/ F. w7 q' i    w2_new=w2-lr*d_eo_w23 j' e3 {7 s/ C, _/ H: m
    #求w3_new9 ~& X5 r% X0 J8 F$ w- `# \; J, ]
    d_hi2_w3=i19 t9 l: V; M$ L- B$ m8 C& p+ `& v4 s
    d_eo_w3=d_eo_hi2*d_hi2_w3% o5 c& o5 W5 |6 J: s3 B
    w3_new=w3-lr*d_eo_w3+ ~# _1 p$ ^3 y4 b4 ?1 T. w) @
    #求w4_new8 D3 K3 s, p: o  A) r' V4 \
    d_hi2_w4=i2+ x( ]% ]  l9 K  `" s
    d_eo_w4=d_eo_hi2*d_hi2_w44 |9 x( @0 `+ R* ]" S
    w4_new=w4-lr*d_eo_w4
5 E0 c3 C1 D1 T; L* @# G    #求b1_new1 i" P4 p) F! O! x8 {2 J; o; I+ k
    d_hi1_b1=1# f7 V$ F+ ?$ W
    d_hi2_b1=1, ~7 I" ^, {4 n' {8 q3 y/ `
    d_eo_b1=d_eo_hi1*d_hi1_b1+d_eo_hi2*d_hi2_b17 ^* y) n8 |8 m& k, b8 ]
    b1_new=b1-lr*d_eo_b1
/ g+ w. @& p) p7 z) q2 T- Q! b6 p; q" h    #更新反向传播
- L7 R* {0 N; H# _8 d' Z" F    w1=w1_new1 w3 S  q# F% t: u  r' L
    w2=w2_new) x$ c; {* R; S+ B/ @
    w3=w3_new
' M8 h; F( X* }$ S7 S0 |2 E0 D    w4=w4_new
, P+ Z  N% [2 j& m" h: k& m, m& u    b1=b1_new
& H, A2 T: l" G/ ?    w5=w5_new
8 W0 h: s+ U! l# @    w6=w6_new
4 L0 k# ^9 y- k1 c: U! B    w7=w7_new- w. I4 W7 k* Q# C
    w8=w8_new# l+ k8 J# c( p% N& S
    b2=b2_new% T) \% O& O- x" Q! r5 q3 K
print(f"当前计算总误差={eo}")2 C1 y: U# M4 ^* {- ~9 ]6 a$ p
print(f"w1={w1}\nw2={w2}\nw3={w3}\nw4={w4}\nb1={b1}\n")
% `% M  {5 T- g4 g3 m" gprint(f"w5={w5}\nw6={w6}\nw7={w7}\nw8={w8}\nb2={b2}\n")% R' {2 x. m- @; l. K
print(f"期望值:[{o1},{o2}],预测值:[{oo1},{oo2}]")
5 F0 Y6 m- F" D6 q' E7 E( P' r- O# v3 p. ]2 P* X" [- i$ i
结果
% A$ |! O' k- D' ?" M8 m# R  E
8 p0 c* Z! j9 _( N6 ~& ^) i: W) n( H* \6 J7 j
结语
0 M$ I- g) i6 C可以看到,在经过七千多次训练之后,我们找到了一组参数满足我们假想的关系,本次人工神经网络训练完成,反向传播算法体验结果良好。
2 h: z; l9 Q! I0 x
. {$ }3 w1 c6 ~8 }! a6 m  r8 |补充
+ g; A* G, F  [4 V4 x程序中d_{a}_{b}格式的变量表示a对b偏导
4 r3 R: X/ Y$ @& c- m3 }+ T% z————————————————" T' ~' j0 Z# [/ T& V
版权声明:本文为CSDN博主「冰凌呀」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。# j' z* Z; z! N& i# i; ]
原文链接:https://blog.csdn.net/qq_36694133/article/details/1266679544 W. G- y  X! h, w9 k& n

. [9 R; `- O* b( ~/ k/ l( f& \4 M0 F& U: Z2 Q8 L4 s# e2 H





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