数学建模社区-数学中国
标题:
人工神经网络——反向传播算法初体验(python实现)
[打印本页]
作者:
杨利霞
时间:
2022-9-12 18:40
标题:
人工神经网络——反向传播算法初体验(python实现)
人工神经网络——反向传播算法初体验(python实现)
: ]/ w3 p+ f3 r1 {# t4 m
% c% t! B7 N% M5 G
背景
6 Z) q4 P; B3 L/ y
初次接触反向传播算法,根据C语言中文网的站长提供的思路,照着做一遍找一下感觉,其中链接如下
$ \8 K" `* T+ G* |4 P
& E, w! j* O; B+ H# N. [
【神经网络分类算法原理详解】
; ^ [- u2 {; M* _
( I/ F0 @$ R$ J7 q5 q
注意
4 v# ]' W3 c% a; _9 P+ y
站长提供的图片有点小问题,我们更正如下
( i( x3 g+ G; U/ W- ]
1 u r Z# V" }, K9 F
) u0 A# e( T) e/ W; C8 f; i
2 g, ?- b; a/ h4 Z# _1 a
问题
; G. a/ X! `/ z/ V
根据上图所示,我们有已知
7 M+ S' u) S" J
9 c% d$ [( S$ z
#输入层
6 Y6 G6 f" [3 }
i1=0.05
7 c( ]' b# U% {9 x4 P+ k# x
i2=0.1
5 V- O X: F$ b3 R1 w0 M
1 k7 y% _5 t' I& E9 G+ e$ a9 |& |
#输出层
, a' p3 W$ _4 W* D! X6 k6 Z
o1=0.01
0 ~. v0 R- j2 N' p6 ~ P
o2=0.99
( q7 D* _4 G/ }- m' M
这个神经网络是我们假想的,我们假想从输入层[i1,i2]==>>[o1,o2]的过程是这样的
! ~* d, Z2 E" Y, W' r$ A
* a3 y4 `8 x$ E
神经元h1的输入(h1 input 简写为 hi1)=w1*i1+w2*i2+b1
% K+ J$ \; ^! h
9 E7 z+ m, U \0 B- |: p x. c
神经元h2的输入 (hi2)=w3*i1+w4*i2+b1
2 G$ K* U& v9 M! p; D! s" N2 l3 s
$ t3 @/ W9 o2 w2 S4 P7 t
神经元h1接收到输入后,通过非线性转换函数【这里选择Sigmoid函数】变换得到神经元h1的输出
- J7 s( y6 ?4 T! _2 B
2 a0 ]. S; O# N7 i
神经元h1的输出 (ho1)=1.0/(1+math.exp((-1)*神经元h1的输入))
; b; W5 B% f. a/ W" k6 L0 ~& h* U
+ Y6 H! G4 i+ R9 {
同理
: I1 b2 M* g7 P3 q, y9 d6 r
; q% `* w% @* B6 G
神经元h2的输出 (ho2)=1.0/(1+math.exp((-1)*神经元h2的输入))
, V4 a, P! }/ z
" {" x6 e( m% D9 j
接下来我们再把隐藏层当作输入层,输出层当作隐藏层,类比推出有关神经元o1,神经元o2的一些表达式
: E& | J3 c2 g" F% x8 n5 ]
' }" R2 P- t6 W' `( s, m
神经元o1的输入 (oi1)=w5*ho1+w6*ho2+b2
' s! h" s! Y4 q
( D3 v: M( {; s- @, Z
神经元o2的输入 (oi2)=w7*ho1+w8*ho2+b2
8 I- z% }3 |% f1 c; g
7 C1 K. i' k! n
再经过非线性变换Sigmoid函数得到
1 H& V- U% J1 {6 S5 b2 Z" M
2 b8 H. v1 m& a" e
神经元o1的输出 (oo1)=1.0/(1+math.exp((-1)*oi1))
9 r3 s$ G2 x$ Q# U
9 P2 u( }' m0 f+ J2 S# ]- h6 e. g
神经元o2的输出 (oo2)=1.0/(1+math.exp((-1)*oi2))
: }6 K" ^' J7 E! c3 j5 N9 X! }
+ P- p$ Q% V2 J* g: s' T
我们将得到的神经元o1输出,神经元o2输出跟我们知道的期望值o1,o2进行比对,定义其损失函数为
9 U( D1 M, Y- h$ y, X3 k
3 P( W" c# o$ @2 A4 d9 x9 Y) U/ U
损失值 ( error 简写为 eo)=((oo1-o1)^2+(oo2-o2)^2)/2
9 V( v" r3 l# T% d6 c& B
7 p1 f* S* d7 ?) L/ s& L3 ?& G
由于我们的期望值精确到小数点后两位,损失函数为平方,所以我们仅需让损失容忍度(eo_allow)调整到1e-5即可满足
' b+ F/ K$ z5 |$ z- S1 D w4 t
' c8 R Z) E0 i; A5 Z4 a
学习次数 (learning_time 简写为 lt)我们限定最大为10000次
/ f, j% o# r" C' [
' r) A3 ?% t2 t
学习率 (learning_rate 简写为 lr)我们设定为0.5
+ F% _& o7 {/ U4 y% h" Q3 t# H. W
0 R( S7 x b7 M- s3 }
依次求解代求参数
! \- C! i x2 K! ]) ^; ~! N
7 N9 y6 Q) \$ W1 T( w
w1~w8,以及b1,b2
0 x; t8 R) r( x) _ s3 p; r" }
. l7 y- u; n% b* f1 W u
跟
; y; y S: y# L
$ a7 _( C$ B2 `3 J& Y
损失值 (eo) 的偏导数
. c7 n5 `9 m. _/ o
3 R( T" R- g ?% D* y+ N1 \
再更新该参数,更新公式为
! Z1 r9 t+ O0 O: G* z; w
1 P1 D6 g, a- b G& { {' S# n
参数_new=参数-学习率*偏导(eo,参数)
* w. c3 X; H- b& V4 G
随后进入下一轮学习
/ G# t( f. T2 M. A# p$ `
" J& k( N# X+ `$ y
终止条件(满足其中一个即可停止训练)
: W1 y2 }4 h) V
1 S1 _ B+ o( Z; w& B! Y, n
1.学习次数达到上限
: Q5 G! W1 A$ P% q& A, s* C
b4 O; a6 P; F' U5 Y7 W6 p
2.损失值达到可容忍的范围
* }8 {6 q* p, h! r P% z/ |5 N
0 g. Z$ ?3 z/ _- X9 v& v1 v: q9 z
导数
* r" S8 w" w3 U6 t! K8 i; M
f(x)=1/(1+e^(-x))的导数是
+ f+ ~/ ]# j3 K, u/ K, v
f'(x)=f(x)*(1-f(x))
3 r' Q6 {$ \% p5 a2 F3 k3 u
源码
9 C6 q" ~7 n8 a/ S
import math
$ O1 |9 o/ w" R( p/ l+ `/ G8 Z
6 y$ ?; \7 e$ a& \: Y) D
#参考自网址【http://c.biancheng.net/ml_alg/ann-principle.html】
1 c; y& S0 _. o7 O- t, ?
#网址中图片有误,请看我博文上的图片
1 X) }) e3 W2 [, m
& J( S' k9 q- q4 E: p
#输入层
& R2 o- A' b6 O' ]1 |+ Z& l
i1=0.05
+ I1 q* H2 f8 [6 I
i2=0.1
0 E$ S" R! e0 [% \& e* @. m+ ?
#权值参数
" d% b2 y4 W2 E* a# M. i. ]: a
w1=0.15
# W" U9 `7 C* ~- P
w2=0.2
+ C* Y. ~# [: ~( y
w3=0.25
( [& K; t" T" X, i
w4=0.3
% t7 P9 n7 X2 h+ P
w5=0.4
6 \4 n2 u# ^$ |$ p( E, a/ r2 V
w6=0.45
" ^: j7 D/ C- D, c) J4 J' {& l% B7 k
w7=0.5
0 Q3 E. ^! z: G( b. L7 x$ S
w8=0.55
7 d% p' E$ \6 j9 J5 q5 a' T O/ }
#输出层标记(即期望值)
6 @ e& P. J4 }# N: X3 a
o1=0.01
/ Z' D7 E1 }9 }5 N: N* v, o
o2=0.99
b1 e5 t" ^% g6 v; l
#偏置项参数
6 w" X4 Y1 |3 T7 c7 h
b1=0.35
' Y5 a3 b9 }. i4 |8 M9 `
b2=0.6
2 H9 P. |3 L1 ]; h% Z& _
$ u d3 h' D" r
#学习率
/ X ` L6 Z6 {/ W& t, [3 G
lr=0.5
# @6 d9 ?4 [9 {3 s# [; H
#学习周期
7 D P; T# |+ C7 E1 }, q1 P6 d5 e# q
lt=0
: d& x, t9 P h b a
max_lt=10000
" u3 M5 U# k R. W/ b* X
#允许误差
2 `8 c0 \' j! p: f7 a' ^( Q
eo_allow=1e-5
; V! G; S) O8 {0 A# L2 W- N
- u+ l2 U$ ^$ c. |7 `# y
#线性转换
; J9 d3 L! t7 }9 W+ i
def linear(w_one,w_two,i_one,i_two,b):
+ w9 Q& {6 z9 P- C2 B# x% j
return w_one*i_one+w_two*i_two+b
* j# ~4 C% e1 m. k2 O
#非线性转换
; s# P9 d0 m. P& T6 ~$ [' u
def none_linear(i):
! i5 B, z8 c6 u9 _ B$ [
return 1.0/(1+math.exp(-i))
6 m, c* j) ?+ y7 m
% h2 V1 ^/ _* c- Z
print("训练开始")
# D; Q9 F& Z4 k. S- H
#学习周期结束前一直学习
9 k, o; b1 i. Q. e
while lt<max_lt:
+ M4 R; Z% t V: W$ ` h$ N @0 o5 j9 F
lt+=1
) h5 Z2 t5 T$ }9 p
#求h1和h2输入值
, Q l v5 } j% m
hi1=linear(w1,w2,i1,i2,b1)
7 C! F+ \+ a d |) B
hi2=linear(w3,w4,i1,i2,b1)
5 H& U" P; ?: f h4 |
#求h1和h2输出值
- B1 ], D/ X. m3 v C
ho1=none_linear(hi1)
' S- x( c- c8 d$ c1 p8 f# O
ho2=none_linear(hi2)
% u2 o: V$ z5 m4 q9 F
#求o1和o2输入值
9 x2 j, y; D5 y9 B
oi1=linear(w5,w6,ho1,ho2,b2)
* w: T& b0 {( ]9 u8 X' B: R. r
oi2=linear(w7,w8,ho1,ho2,b2)
( Y6 {4 K9 t5 v T w5 A
#求o1和o2输出值
% m7 ^; y0 ^; f9 q" V- O
oo1=none_linear(oi1)
# r: @3 A0 T0 B4 y' L
oo2=none_linear(oi2)
, u! a3 D/ S; z k. J h1 o2 d
8 b- C& J6 \+ S* s) l; T
#求当前计算总误差
4 N+ K5 {( e. T! b; y2 N5 u1 e
eo=(math.pow(oo1-o1,2)+math.pow(oo2-o2,2))/2
" x$ m9 S3 r" |6 v9 ` V
print(f"第{lt}次训练,当前计算总误差={eo}")
+ n$ I: W( _+ A n* E0 z% g! q
#误差已经在允许范围,退出训练
* {5 y& |1 @7 y. p; i3 G
if eo<eo_allow:
* f: k% b) C, s/ ?. f
print("误差已经在允许范围,训练结束\n")
# c% Z! T3 C. m! X/ H% W+ Q+ A
break
: t" w8 f- h8 g
#偏导
7 Z- q0 ]. c6 X* W! r
d_eo_oo1=oo1-o1
* A8 W9 |, u( p" x* |4 M
d_eo_oo2=oo2-o2
% ~3 V) Y# W: U3 Q5 v( }3 I' g
d_oo1_oi1=oo1*(1-oo1)
6 S# g! Y& z: X/ B( V" E% U
d_oo2_oi2=oo2*(1-oo2)
- u- E& n# R4 I' a0 r- {6 F
d_eo_oi1=d_eo_oo1*d_oo1_oi1
1 B. p5 Y- v' X9 F9 [' T
d_eo_oi2=d_eo_oo2*d_oo2_oi2
% j4 E, ^* L3 Z
#求w5_new
/ |: m5 _5 w5 k9 j& I+ N Q/ g
d_oi1_w5=ho1
% A' R" C+ @2 d1 r2 U! {0 b
d_eo_w5=d_eo_oi1*d_oi1_w5
, K* K! m* t( E
w5_new=w5-lr*d_eo_w5
& z* x/ g) V0 Z. d5 A: W4 T
#求w6_new
* Y* Z4 N. Q- ?$ G2 r; e4 c
d_oi1_w6=ho2
" [! T3 H7 A1 `+ q4 b+ f+ o' k. Y
d_eo_w6=d_eo_oi1*d_oi1_w6
! x* o& H' x+ N! a! F6 b: B
w6_new=w6-lr*d_eo_w6
# v. S# ?8 l& h2 U* [' a7 L, g! R' G
#求w7_new
# o1 v; {! z U7 Y" ]& ~
d_oi2_w7=ho1
" b& W/ n: j3 T" a, p
d_eo_w7=d_eo_oi2*d_oi2_w7
) |. Z" w6 N* u: Z8 w
w7_new=w7-lr*d_eo_w7
" y# H* v: ~, {. j( O( [
#求w8_new
5 m% L7 Y$ x7 X4 K, C; V9 l/ {
d_oi2_w8=ho2
$ D) o9 d: ]; S" n/ P% s
d_eo_w8=d_eo_oi2*d_oi2_w8
$ A$ W$ |; ?& T
w8_new=w8-lr*d_eo_w8
$ t! y( ]& F+ U/ ~& ^2 f
#求b2_new
" x; B s X" p8 G; k
d_oi1_b2=1
& x2 D- i3 r, @7 E5 R
d_oi2_b2=1
5 W5 A' q/ b2 |: R8 B
d_eo_b2=d_eo_oi1*d_oi1_b2+d_eo_oi2*d_oi2_b2
; o c/ x* ?' O6 I4 P4 Y5 Y" B [
b2_new=b2-lr*d_eo_b2
9 l+ h& g, i4 n. L' u
d_oi1_ho1=w5
( q+ N8 x; f d7 V; H' e
d_oi1_ho2=w6
$ {) f: Z a9 b5 M! N/ F! q
d_oi2_ho1=w7
7 X: t: I# ]" K: h3 y m( h
d_oi2_ho2=w8
0 M' ?$ C) h; Z, p; c% A
d_eo_ho1=d_eo_oi1*d_oi1_ho1+d_eo_oi2*d_oi2_ho1
7 ~2 D2 F0 D1 B2 S
d_eo_ho2=d_eo_oi1*d_oi1_ho2+d_eo_oi2*d_oi2_ho2
% F9 `9 q5 J& l Z% R0 C% D
d_ho1_hi1=ho1*(1-ho1)
8 _: b$ g( m3 K5 S/ k
d_ho2_hi2=ho2*(1-ho2)
: d& R! \6 s i7 F* H% `
d_eo_hi1=d_eo_ho1*d_ho1_hi1
7 m1 \/ R( M0 ~4 W) A4 m/ Y/ p, b
d_eo_hi2=d_eo_ho2*d_ho2_hi2
8 z3 b) s- q+ T7 v+ Z
#求w1_new
, |4 v3 J' f4 G3 X; {0 g
d_hi1_w1=i1
) T6 R R+ {1 S' l! ?
d_eo_w1=d_eo_hi1*d_hi1_w1
2 H' [. ~% r9 x9 F* |: ]. a
w1_new=w1-lr*d_eo_w1
6 @2 U; \% ^$ ]- t4 E8 J
#求w2_new
( i$ X: n: |0 ]" K
d_hi1_w2=i2
) l/ Z" r. [6 U4 o H( V
d_eo_w2=d_eo_hi1*d_hi1_w2
! q9 D7 p/ K1 [
w2_new=w2-lr*d_eo_w2
% b8 T. T( v8 J. j5 W
#求w3_new
( p+ Q! x% H$ c- U) u1 O: x/ w
d_hi2_w3=i1
0 ?7 o, [0 I$ e5 w P2 o$ u
d_eo_w3=d_eo_hi2*d_hi2_w3
) z2 E9 x$ }8 Q. ]! b) z2 J
w3_new=w3-lr*d_eo_w3
% P* S0 R& |# L" w9 g4 x8 V3 i4 j
#求w4_new
7 w. a5 E8 L2 U# e
d_hi2_w4=i2
8 d# D m' j3 y6 d- m
d_eo_w4=d_eo_hi2*d_hi2_w4
5 _: E/ Q! ]9 R) o% Z, F% D
w4_new=w4-lr*d_eo_w4
, L7 \6 B3 {4 l- C( ~! L" d
#求b1_new
Z; A2 G, |& Q' [2 m- d
d_hi1_b1=1
' r! Y8 ?5 j4 t; v& m2 U
d_hi2_b1=1
# v% u& N5 ~. U3 @" P2 o1 D2 }
d_eo_b1=d_eo_hi1*d_hi1_b1+d_eo_hi2*d_hi2_b1
& T5 U0 a) D6 ~5 H: P6 c
b1_new=b1-lr*d_eo_b1
4 K1 c3 n+ j$ @* V
#更新反向传播
- Z0 H% W6 e' K. o# ^8 P# p
w1=w1_new
2 t# c8 n/ K9 X2 D" ?7 B
w2=w2_new
. d4 e L8 Z7 n) n
w3=w3_new
; i f2 K$ F6 {& I+ D2 t1 z
w4=w4_new
' @, {7 y6 g$ E! A
b1=b1_new
, P' z- o. U+ ~
w5=w5_new
, n% G) Q4 K. H
w6=w6_new
" e, e! T$ t: l5 R1 e' b
w7=w7_new
- D$ ?* {5 J i7 K3 C* C, @
w8=w8_new
! h& T8 h. h+ M% ^! K
b2=b2_new
, M0 @3 r4 M2 d4 j1 H
print(f"当前计算总误差={eo}")
4 c* W% E" i/ w
print(f"w1={w1}\nw2={w2}\nw3={w3}\nw4={w4}\nb1={b1}\n")
9 q9 k9 r- {& r7 B
print(f"w5={w5}\nw6={w6}\nw7={w7}\nw8={w8}\nb2={b2}\n")
( u# r+ ^2 q) f5 }
print(f"期望值:[{o1},{o2}],预测值:[{oo1},{oo2}]")
7 U+ n- h5 [3 ^1 l ~% n
, v* K# c. c I
结果
6 f; q; i1 p. j) Z& w! [* Y
5 N- r |# N5 V
" V9 o6 [# i9 u3 v
结语
! E9 S, v: V: ]' ]% F
可以看到,在经过七千多次训练之后,我们找到了一组参数满足我们假想的关系,本次人工神经网络训练完成,反向传播算法体验结果良好。
) x; i8 u# A( A2 x0 Q5 M- z
8 ~) g: p3 }; k8 g& g, ?- u3 A& l% V
补充
: y/ o$ u1 Q; }" _
程序中d_{a}_{b}格式的变量表示a对b偏导
; i3 I7 _) Q# z" N
————————————————
/ E' |( T2 x; b3 x' p+ R
版权声明:本文为CSDN博主「冰凌呀」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
) r& o( v# D; Q% Z m, L$ N7 ~' h
原文链接:https://blog.csdn.net/qq_36694133/article/details/126667954
: j1 d) `1 ?7 y4 n6 h+ Q
' f6 X: V1 B* @- c' f
9 q& J/ {2 D& ~% V' b% k
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5