数学建模社区-数学中国
标题:
人工神经网络——反向传播算法初体验(python实现)
[打印本页]
作者:
杨利霞
时间:
2022-9-12 18:40
标题:
人工神经网络——反向传播算法初体验(python实现)
人工神经网络——反向传播算法初体验(python实现)
& I; z# E$ |: \$ ]1 b9 W3 d& o2 A
6 q6 y( U4 U$ B8 v6 z; ?" o6 ]
背景
4 Q' t3 N U2 ]* {) T
初次接触反向传播算法,根据C语言中文网的站长提供的思路,照着做一遍找一下感觉,其中链接如下
- L! Q, \% R. [, g! }" R) P
! D- P' A" u! Z# P, G# A$ [
【神经网络分类算法原理详解】
; B i5 t2 W& f: {8 A
3 d# p- C& M2 t1 d
注意
& o- e0 G/ p( Z. B3 M+ \9 e& o
站长提供的图片有点小问题,我们更正如下
5 ?3 k1 N) A" R7 ]9 }
* ^. N; x& U$ {( F6 U1 l
5 O7 @ `! Z% D
$ }6 B/ u. O! b, ]# f; ]% @
问题
; `) z( {. p& U# C' @3 ^+ o4 ^/ B) Y) H
根据上图所示,我们有已知
. K! u( L& a% i2 G0 v0 Z
8 _1 g$ w6 g4 Y1 l
#输入层
( _8 l$ ^, j- r, o
i1=0.05
/ ~. L0 U6 Q, ^1 H
i2=0.1
* W z2 X$ P: x. F/ S8 R
8 Q9 W+ X# U+ V: m2 a
#输出层
9 Y6 Y, A. K6 Z* \. d6 x" \7 T
o1=0.01
9 Q, }# u/ a9 h8 A" Q
o2=0.99
2 w: L Y2 N- e+ |0 X
这个神经网络是我们假想的,我们假想从输入层[i1,i2]==>>[o1,o2]的过程是这样的
" R4 g1 p" l0 j& x9 r
, M/ j7 a, _6 [7 _$ w& W& P5 R4 Y4 e
神经元h1的输入(h1 input 简写为 hi1)=w1*i1+w2*i2+b1
( X. p6 I. W- B! z+ z+ p3 ?$ m+ q
* A* U4 S) v1 F6 o$ U5 H* U% z
神经元h2的输入 (hi2)=w3*i1+w4*i2+b1
2 ^* u5 ?3 z7 q6 D: V
' C9 d0 J, O7 R" t8 ~8 ~
神经元h1接收到输入后,通过非线性转换函数【这里选择Sigmoid函数】变换得到神经元h1的输出
6 P, ~! w2 ~8 z" ?
8 ?+ I9 `6 B$ C
神经元h1的输出 (ho1)=1.0/(1+math.exp((-1)*神经元h1的输入))
/ a) F. w3 x8 _6 [: X1 G+ z
7 X u0 v" B( z# Q2 r2 a& N' a/ ]
同理
8 {, @" o9 d. J" W3 r K" M- t2 d
; f: u' s8 V3 m' _ x* e. O, @
神经元h2的输出 (ho2)=1.0/(1+math.exp((-1)*神经元h2的输入))
2 Q, K7 q* n+ H! `, c9 }2 w" B
9 y. c) E& ^; D3 y# f8 x. o2 q
接下来我们再把隐藏层当作输入层,输出层当作隐藏层,类比推出有关神经元o1,神经元o2的一些表达式
2 L: t1 A' g0 q. R3 ^5 `
) K9 q, Z& d# P: l" x8 q
神经元o1的输入 (oi1)=w5*ho1+w6*ho2+b2
; o) s; D+ X( I- p: R/ ^
+ ]; r3 _2 b1 T8 Y
神经元o2的输入 (oi2)=w7*ho1+w8*ho2+b2
+ \- A. @" H E+ q9 E; @0 ^+ @
' M: L( J. ^9 B" _! \
再经过非线性变换Sigmoid函数得到
4 t$ Z, h! T% d$ ^, u6 y2 ?
2 L- i9 S9 }+ q! P
神经元o1的输出 (oo1)=1.0/(1+math.exp((-1)*oi1))
9 [$ v3 d/ O7 B) L1 K
" V9 |) \8 n# J% ?4 B. ^
神经元o2的输出 (oo2)=1.0/(1+math.exp((-1)*oi2))
& c) x4 H! E9 g" ^
6 e. y0 {2 [: n \5 C1 n, N0 t9 U
我们将得到的神经元o1输出,神经元o2输出跟我们知道的期望值o1,o2进行比对,定义其损失函数为
/ n+ I+ t1 i$ H* x9 D- j
+ Y* V" B, J2 b3 L) B/ I
损失值 ( error 简写为 eo)=((oo1-o1)^2+(oo2-o2)^2)/2
+ u8 V! F$ g8 B7 K& y" [, z' f. a# n
8 X V* ?) o3 u, C8 A
由于我们的期望值精确到小数点后两位,损失函数为平方,所以我们仅需让损失容忍度(eo_allow)调整到1e-5即可满足
4 B) f& m; H2 ~/ L5 t
! g% x% S, B, |% `, x
学习次数 (learning_time 简写为 lt)我们限定最大为10000次
5 b0 B4 ~1 M! a. W
- X8 e% o) p3 ^& O* ^
学习率 (learning_rate 简写为 lr)我们设定为0.5
- {5 v5 p0 \- L
4 y0 B) b8 _) N9 b
依次求解代求参数
: g+ a' y+ n1 F
& R0 b1 ^. a& R4 f! M
w1~w8,以及b1,b2
U4 { u5 y- X+ q6 k( T5 o% U
3 E: a$ M+ L$ k/ E7 @, f
跟
8 f( ~0 o1 d* z2 d7 X! y* }
7 n k* | H4 k3 ~
损失值 (eo) 的偏导数
- Z3 x' u- y* j& f6 g
$ B9 @$ r R2 E8 l# w5 L
再更新该参数,更新公式为
- h0 g' P: v* l5 z
* m6 S, N0 N# w5 Q+ v
参数_new=参数-学习率*偏导(eo,参数)
5 w5 q) F) G" U$ Z# v
随后进入下一轮学习
2 k4 s @, j5 ~4 i1 a# t9 V0 M
; y* N' I" P) Y( p, \2 f
终止条件(满足其中一个即可停止训练)
+ Z; q' b$ u! E. O5 b1 x
) a1 N2 l' y# Q; {( T/ A7 s
1.学习次数达到上限
* {- |; `+ i* L: K6 |! U
8 z1 z4 p' ~) r$ r: L2 d! Z
2.损失值达到可容忍的范围
5 n* \3 t/ Q$ `! r% J9 m& m
2 Z3 K l _" d. p
导数
, o$ L3 n# V% t7 ^! ]8 t
f(x)=1/(1+e^(-x))的导数是
0 h* |4 u( j" t* E
f'(x)=f(x)*(1-f(x))
6 X& Z$ c2 K# K4 ?% k! E
源码
* I6 X, r4 J5 n) X& @
import math
9 s6 O$ h6 t! c9 H, r
* I! W& b, N6 O3 y% ]" Z
#参考自网址【http://c.biancheng.net/ml_alg/ann-principle.html】
( e. W; h' E, s: s$ K
#网址中图片有误,请看我博文上的图片
$ J* ^( s8 `/ ^# N
* e8 O* W# g: y2 i
#输入层
/ k6 Z) J9 o4 K3 U; B @
i1=0.05
# @1 g/ _7 z- y/ \9 W" A
i2=0.1
1 b: T4 E* a$ w9 K, T3 r P: p
#权值参数
8 ]# |7 Y$ W) C7 j
w1=0.15
: u/ ?% Z6 q& d/ z
w2=0.2
, ]7 m, N0 e: O1 I4 [8 x! o3 K
w3=0.25
' W# z3 O" X+ h) |9 s) ~6 Q7 K
w4=0.3
4 }* \ d. E2 M2 E& E4 t3 o
w5=0.4
$ r- R; n5 m2 v8 _/ e8 ^
w6=0.45
6 }( ~! b) P: J5 c3 ], g" |, Q
w7=0.5
" o3 j' e! g; O1 i3 D- P' U( D
w8=0.55
/ P# z) ?4 d4 b5 Y5 i
#输出层标记(即期望值)
2 Y$ [8 v2 b+ d: @
o1=0.01
0 A% h' e! S1 e8 h$ e" f
o2=0.99
$ N5 r0 j3 t o1 t; @2 ?
#偏置项参数
! m( k- r+ \& S
b1=0.35
$ }+ `$ _7 [9 t | i
b2=0.6
' ?( C4 x" ]& M+ r% i) J
" n& H8 `# h# D; r+ K' q" k
#学习率
8 x0 A% F% v# u- G) e( C& y: [$ k
lr=0.5
, N" H0 {" |; P- l" b7 h1 z. v
#学习周期
N; _% M; A/ ]9 ?
lt=0
7 Q6 `2 n! {+ p/ A* z
max_lt=10000
/ n& Y3 A: T8 S6 h7 ?' M$ E$ J! \
#允许误差
$ G5 x2 J. l6 M/ T l. ^) m8 _
eo_allow=1e-5
6 U M9 {0 T6 o4 O+ g4 y
. Y( y1 q* L6 g+ D4 R& b0 a
#线性转换
+ m6 e2 L8 @8 J3 O8 E" ^- T8 B$ M4 j1 A1 V
def linear(w_one,w_two,i_one,i_two,b):
8 c4 P) i& b0 D
return w_one*i_one+w_two*i_two+b
/ Y7 y& ?( ~' f0 M
#非线性转换
/ H+ f5 a" s% K; C
def none_linear(i):
# Y4 Q) [& ]) E6 V* ~+ _
return 1.0/(1+math.exp(-i))
: h/ C% a& D* h: P: s7 X8 b
) G# q5 a% W, i8 s7 e* V) M6 P
print("训练开始")
1 s6 t1 C6 C/ F( y! V' W
#学习周期结束前一直学习
, d! {$ Z% y6 H4 U
while lt<max_lt:
4 d4 h2 m" W3 B4 [7 d) i1 K
lt+=1
7 l7 f8 j# D- x+ o( O# M
#求h1和h2输入值
3 R9 o. L( @; r& |3 {& m$ i
hi1=linear(w1,w2,i1,i2,b1)
3 E: i+ w: V8 T' q4 Q: h
hi2=linear(w3,w4,i1,i2,b1)
, _' r( M% K' K6 h: y& [4 Z
#求h1和h2输出值
0 w0 D, ^- Q5 B3 q1 ?* |- D
ho1=none_linear(hi1)
7 x9 g, O4 B/ A/ n
ho2=none_linear(hi2)
6 W0 ~8 ~- t6 [3 _
#求o1和o2输入值
" h* F5 z) u6 G* V, K4 u5 j' d
oi1=linear(w5,w6,ho1,ho2,b2)
; ]: Y$ k7 T! S6 A/ l
oi2=linear(w7,w8,ho1,ho2,b2)
& Q# m' \# U9 v- g9 U3 W$ b8 e
#求o1和o2输出值
: F( | b! P# x; Y. s
oo1=none_linear(oi1)
/ g8 @- j* U# f( m1 l. n
oo2=none_linear(oi2)
2 {8 D8 a9 H& `- n7 t# y
3 q' k& I6 z# o: m& D# r+ Z+ y1 y' H
#求当前计算总误差
% K# F6 U( q3 M4 z. Z9 y) j) M
eo=(math.pow(oo1-o1,2)+math.pow(oo2-o2,2))/2
4 ^+ p6 h2 ?& e# }' R
print(f"第{lt}次训练,当前计算总误差={eo}")
1 c# L, m! w7 z- F. k
#误差已经在允许范围,退出训练
1 \( O% n; y- a& z/ O
if eo<eo_allow:
( v+ H* V" z) L
print("误差已经在允许范围,训练结束\n")
% i' a1 x' f$ H5 U% y9 N
break
A8 Y3 E& l; o6 D# I
#偏导
9 T/ u, M, f% Y7 B, K
d_eo_oo1=oo1-o1
9 ?# \; F1 U# K8 C
d_eo_oo2=oo2-o2
- `* B% I" P* L$ Q" m
d_oo1_oi1=oo1*(1-oo1)
+ C1 J2 |. F0 ^2 o, P, A
d_oo2_oi2=oo2*(1-oo2)
* }7 b9 Z& P4 u1 _# J# N
d_eo_oi1=d_eo_oo1*d_oo1_oi1
/ F8 o: ^# `1 D
d_eo_oi2=d_eo_oo2*d_oo2_oi2
% u: h; K" g- Y( C4 ~: R6 C
#求w5_new
' U2 ~; r0 P' b/ t; M
d_oi1_w5=ho1
) {, z$ }& k: Q) X- q
d_eo_w5=d_eo_oi1*d_oi1_w5
% S! {" ?3 n3 Q. P X M8 l
w5_new=w5-lr*d_eo_w5
# D. r+ t1 G& _3 N7 @
#求w6_new
6 N' Q2 o& u7 _
d_oi1_w6=ho2
% Q' m, S# ?+ w1 ~2 y- j( b
d_eo_w6=d_eo_oi1*d_oi1_w6
6 p$ G' [& N' N0 F9 Q4 b1 {
w6_new=w6-lr*d_eo_w6
3 K, A0 K W4 D! s8 f
#求w7_new
: U( o3 w4 B% |+ o! y; A$ M
d_oi2_w7=ho1
, H* [' M8 x# q6 b; |3 V: l
d_eo_w7=d_eo_oi2*d_oi2_w7
& f; X6 P" Y% J0 T; x$ b. G
w7_new=w7-lr*d_eo_w7
& a9 j) r( b" ~/ S
#求w8_new
" k( @7 `7 V/ `" ?8 E# ]( }! w
d_oi2_w8=ho2
3 w% q% c7 y B( v6 C ?
d_eo_w8=d_eo_oi2*d_oi2_w8
* f7 p0 T4 r6 o% ]9 @) L# v4 ?
w8_new=w8-lr*d_eo_w8
* i$ L. O, U! I; M. r* X$ F: `
#求b2_new
: ?* h; b5 d4 Z* {( Y+ X/ K/ p
d_oi1_b2=1
+ H4 h8 I" \7 @8 A
d_oi2_b2=1
+ J( b) C4 ` Y1 n
d_eo_b2=d_eo_oi1*d_oi1_b2+d_eo_oi2*d_oi2_b2
0 G7 ~2 R9 o( `: j5 Z2 I! o! m
b2_new=b2-lr*d_eo_b2
0 l+ b5 M# U& d8 q, O$ j9 p( g/ Y
d_oi1_ho1=w5
& D5 ~: d! Z! g
d_oi1_ho2=w6
0 h2 C$ v. ?6 D" A, J5 M
d_oi2_ho1=w7
9 e0 e ]. u t( g& v- J
d_oi2_ho2=w8
) P& H/ _/ e% V2 q# N, }
d_eo_ho1=d_eo_oi1*d_oi1_ho1+d_eo_oi2*d_oi2_ho1
7 X, I+ f$ J! }
d_eo_ho2=d_eo_oi1*d_oi1_ho2+d_eo_oi2*d_oi2_ho2
$ Q( n \' [0 B. T# d# [
d_ho1_hi1=ho1*(1-ho1)
" @& D* R+ M8 W
d_ho2_hi2=ho2*(1-ho2)
/ e2 q7 [: g6 P2 W
d_eo_hi1=d_eo_ho1*d_ho1_hi1
a" U% Q0 D0 _2 o8 \+ Q
d_eo_hi2=d_eo_ho2*d_ho2_hi2
/ l% P5 i5 T6 I, t' ~
#求w1_new
' g- d. Q, ~% i, E# {; f7 C3 g9 F
d_hi1_w1=i1
- j/ s3 u. J/ W. `0 p
d_eo_w1=d_eo_hi1*d_hi1_w1
" F: G8 A# U- M
w1_new=w1-lr*d_eo_w1
0 U G3 B& E( D) S5 A* ]" G5 P& ]
#求w2_new
5 W' O! p* ]2 t" `5 }6 V
d_hi1_w2=i2
* a% @& ?+ y& W- x+ l$ X
d_eo_w2=d_eo_hi1*d_hi1_w2
T( v+ o1 ~8 n0 b: e3 X
w2_new=w2-lr*d_eo_w2
7 T+ V- v; U( t$ m' t! t6 a
#求w3_new
( r4 K2 e$ O' m; s; p
d_hi2_w3=i1
F! Z& |2 X+ |
d_eo_w3=d_eo_hi2*d_hi2_w3
/ _$ V, J% \ X6 a0 q& Z' N' Q% b7 r
w3_new=w3-lr*d_eo_w3
^" g0 e, i' i; |( l e
#求w4_new
5 g3 X/ l' K: h& C
d_hi2_w4=i2
, z- X0 k9 H3 y! n) m k4 G5 O
d_eo_w4=d_eo_hi2*d_hi2_w4
7 M" I& M' E- A/ n
w4_new=w4-lr*d_eo_w4
$ o% n/ h7 x( x, x, @1 b) ]9 a% H
#求b1_new
" S, Y) q8 k5 W5 G) C
d_hi1_b1=1
, {$ {/ y; v; m7 c2 o
d_hi2_b1=1
- w/ S" Z7 B9 X. e: ~& U
d_eo_b1=d_eo_hi1*d_hi1_b1+d_eo_hi2*d_hi2_b1
6 Q) o4 M0 E8 Y" T, X3 ~
b1_new=b1-lr*d_eo_b1
, }6 Q( Z8 g# u) Y1 i6 b/ j- f O
#更新反向传播
! _2 _+ t! m" g) @2 ?( d
w1=w1_new
( Q( n6 @3 Q4 p3 n% |
w2=w2_new
0 v% k, g4 q/ m. a4 i' K- i
w3=w3_new
2 d: d+ b( N# i& R
w4=w4_new
/ F4 V& z, x5 K. Q9 P) T- a
b1=b1_new
4 `' H8 N6 ~$ w6 \7 n
w5=w5_new
( @: @4 l! n& ^) L
w6=w6_new
' ~' E) x: C9 K: d
w7=w7_new
2 o3 s2 a/ S( D y v
w8=w8_new
8 }$ `) l" F9 j# m/ h
b2=b2_new
8 X/ P! I. X) U0 r ]
print(f"当前计算总误差={eo}")
# `0 S% B+ |2 G; [7 Z
print(f"w1={w1}\nw2={w2}\nw3={w3}\nw4={w4}\nb1={b1}\n")
; I- R- R7 l/ p4 J# }2 r* r+ P
print(f"w5={w5}\nw6={w6}\nw7={w7}\nw8={w8}\nb2={b2}\n")
) t; d' o; G9 _1 d( C3 Y8 g4 Z. R4 B
print(f"期望值:[{o1},{o2}],预测值:[{oo1},{oo2}]")
0 M( T! L* B/ Z& z* }5 ~2 p
3 W0 _% L V. K1 W6 j2 c1 Y# g
结果
6 `% A2 V" J- k( o
& B- @1 B3 T/ l4 r0 L( K
. O7 O7 r8 e/ K
结语
. ^5 N0 p& ]1 I* Y8 M2 Q* W5 V
可以看到,在经过七千多次训练之后,我们找到了一组参数满足我们假想的关系,本次人工神经网络训练完成,反向传播算法体验结果良好。
# S5 a1 M% |% w( Y# t% e; t
5 i1 f6 I0 m) G$ W
补充
( N, M. |) k) X7 n* e9 b& F
程序中d_{a}_{b}格式的变量表示a对b偏导
( Y# d( }. _7 q( ~7 W h) ~1 p+ l, B
————————————————
1 Z4 I8 }' @; G- `
版权声明:本文为CSDN博主「冰凌呀」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
/ y& T# t8 \) J# c: F: W
原文链接:https://blog.csdn.net/qq_36694133/article/details/126667954
. d$ w0 S# s# R! w' U! Z5 L
$ `% Z/ N$ z+ _2 K v
4 @, }" Y3 Z& c7 d7 T/ m$ v- i: b
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5