From 116097627ad77f813fb3a0be60a56fb9153f6279 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Mon, 3 Apr 2017 18:09:42 +0800 Subject: [PATCH] add event_handler_plot for 03.image_classification --- 02.recognize_digits/README.en.md | 1 + 02.recognize_digits/index.en.html | 1 + 03.image_classification/README.en.md | 30 ++++++++++++++++- 03.image_classification/README.md | 31 +++++++++++++++++- .../image/train_and_test.png | Bin 0 -> 15018 bytes 03.image_classification/index.en.html | 30 ++++++++++++++++- 03.image_classification/index.html | 31 +++++++++++++++++- 7 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 03.image_classification/image/train_and_test.png diff --git a/02.recognize_digits/README.en.md b/02.recognize_digits/README.en.md index c5efb71..7423f7a 100644 --- a/02.recognize_digits/README.en.md +++ b/02.recognize_digits/README.en.md @@ -259,6 +259,7 @@ def event_handler_plot(event): ``` `event_handler` is used to plot some text data when training. + ```python lists = [] diff --git a/02.recognize_digits/index.en.html b/02.recognize_digits/index.en.html index 45c85c8..251ebb3 100644 --- a/02.recognize_digits/index.en.html +++ b/02.recognize_digits/index.en.html @@ -301,6 +301,7 @@ def event_handler_plot(event): ``` `event_handler` is used to plot some text data when training. + ```python lists = [] diff --git a/03.image_classification/README.en.md b/03.image_classification/README.en.md index 0bb0775..2c243c6 100644 --- a/03.image_classification/README.en.md +++ b/03.image_classification/README.en.md @@ -397,6 +397,34 @@ feeding={'image': 0, Callback function `event_handler` will be called during training when a pre-defined event happens. +`event_handler_plot`is used to plot a figure like below: + +![png](./image/train_and_test.png) + +```python +from paddle.v2.plot import Ploter + +train_title = "Train cost" +test_title = "Test cost" +cost_ploter = Ploter(train_title, test_title) + +step = 0 +def event_handler_plot(event): + global step + if isinstance(event, paddle.event.EndIteration): + if step % 1 == 0: + cost_ploter.append(train_title, step, event.cost) + cost_ploter.plot() + step += 1 + if isinstance(event, paddle.event.EndPass): + result = trainer.test( + reader=paddle.batch( + paddle.dataset.cifar.test10(), batch_size=128), + feeding=feeding) + cost_ploter.append(test_title, step, result.cost) +``` + +`event_handler` is used to plot some text data when training. ```python # event handler to track training and testing process @@ -422,7 +450,7 @@ Finally, we can invoke `trainer.train` to start training: trainer.train( reader=reader, num_passes=200, - event_handler=event_handler, + event_handler=event_handler_plot, feeding=feeding) ``` diff --git a/03.image_classification/README.md b/03.image_classification/README.md index e97cb33..0eea28f 100644 --- a/03.image_classification/README.md +++ b/03.image_classification/README.md @@ -389,6 +389,35 @@ feeding={'image': 0, 可以使用`event_handler`回调函数来观察训练过程,或进行测试等, 该回调函数是`trainer.train`函数里设定。 +`event_handler_plot`可以用来利用回调数据来打点画图: + +![png](./image/train_and_test.png) + +```python +from paddle.v2.plot import Ploter + +train_title = "Train cost" +test_title = "Test cost" +cost_ploter = Ploter(train_title, test_title) + +step = 0 +def event_handler_plot(event): + global step + if isinstance(event, paddle.event.EndIteration): + if step % 1 == 0: + cost_ploter.append(train_title, step, event.cost) + cost_ploter.plot() + step += 1 + if isinstance(event, paddle.event.EndPass): + result = trainer.test( + reader=paddle.batch( + paddle.dataset.cifar.test10(), batch_size=128), + feeding=feeding) + cost_ploter.append(test_title, step, result.cost) +``` + +`event_handler` 用来在训练过程中输出文本日志 + ```python # End batch and end pass event handler def event_handler(event): @@ -413,7 +442,7 @@ def event_handler(event): trainer.train( reader=reader, num_passes=200, - event_handler=event_handler, + event_handler=event_handler_plot, feeding=feeding) ``` diff --git a/03.image_classification/image/train_and_test.png b/03.image_classification/image/train_and_test.png new file mode 100644 index 0000000000000000000000000000000000000000..c6336a9a69b95dc978719ce68896e3e752e67fed GIT binary patch literal 15018 zcmc(`bySpL)GzuD-3)?sBP}4^As`?kUDAqlcXtW{h!QFi(p}Pxq;%)dAU$-~dHKGz z&OP_6Q+M4z4r>j}yu;Ib|MqY1XYWs{%JR5aP%WYr92Fh8SU zh@w16diD|jov2@{r1f^;4#JiB*)!Im8!<6g9UTvyFvp##`irzT(iktgNqI@q&n19v zQqz*S5K&XucPP3C_>c|{0pm88ri7E34ulHT@pga1baJ$SaTBgC50RQOb+)H+cPsVQ zHn#{dG08n+Vyc;*=Iz$at1|0P`YIi%t8!DV@2H}rBr7K;=i?`C3UgDGb)8AM6XNLj zudO5hV>s2u4Y;9|rKOa=zl61o&HRn35*;lqfQgA&u2-_}#{#S1EtWyOxV`la4G*X1 z<|dGxSd17iz@$?(Fo1ziPZ0}^&G-@A?%{6vRZ4bt9GO{J!sWF{^wO@bd`qa@?nyhU z?Nk8zxpt@Io9-baDo$`Qq@sS5aQ>+1==dK$q9!IZJ9~Pvd@c|>C)d~BWfE(pjfg*K z;y!bi3TMR6bpr{Rm4A*Ne1y5#QWeTnH@}jXXW-=}1YX!oJr4~HT^gey|j`zWx#J+|NNO5SrHoU5xV&+F~H`1tss!$U_HjU;t{5{Hbf?Q`Wcu}}N+wa7qUUmui!AZXe+fXboi z2u)o>L*LaN#(lDq)R=sIzF&mq4qTp&t8m-SyuhIlz-e^fmsVDe9rr;(M&@=}l?B?o zHd79-b!@g7%$tPHRv?Lgb>!s1%15vevtEiZ5Tjlv@l_ zi(M{<=+-+k{^{tL|M!v1G}S1=uD-S^Y(YCXBxJJZ=6t`SsH`RGZHfRLJv~zGqIXgM z(Yn9C|Bh*N7gEZgyIv2JiYjJr&$d{%0?DD}iYe*&yWp#n&Gab?p6-E9`UnnHHMO9T z5!KMJu$9ZBHE=AmXvy8NH(XudOfaQ(ia9tqx==|B0w;@fvg+zc1yXRMi8=mskr=}= zGwCtt96N9YP0sgbXBynt0a`vjqQu0+5@&E@T(-(NE@EwG%HJy}D|ZJ%kVlGixL}mR zm0js)aF^lt-7qpzK1=9xVr)=mLW)Wouw4EPw149^r44Oc|NE8OYV4WqLc`MwxC?$L zl$O5f_P8I&UP-=K^x*=xw8CnfX@LsabZ<{qI@0}WwW^Bmy+N_*bg7{b*kXReb08`p z7xo>Sz>YvV+iNavoacWJ50N2_ayALKsB<+aWefH_pv=s#|0Xm2*WPX@!+MqS{rjgI zL?eEj*m2}_lQ3b(Bg)LB^eijOLS(BxMOH>yG82d&d`K7llph(%vmtp=Gq_TdjxTWu zY;SKXynWjRBjYuxo!8e4_BdEjasS9}j>KG3JJ$mNRy6`Y4LY15W-5@4{jV6OO7zig zIIi?HG(xDwy-ogvVp?M^zW&OzQrXXGbL^t{=8e2A6^8~Kzx^XTp}&W3Cy5s za%yU$+msh%{QkF|&yAW$nN`wIXk!Y6o!1q9zc~a=3OxulOa3<;Kt@ds@#N%W-BxCF zx#cK5xW7b1L?-)l)e3LkbgXnl5YW)XfdISmi0CzT^UJ&JhH>?%!=yHfzZLJX==vfp z`2+hQdn2}7Q+wx}fvt^R55B+&q=4j&T4B{jMSy5_&ME>^)CkuIf%8gBsI=b^fCvcDl8G3Z(#hqMHS zsBLH&C~c`6lCGd(&+AVa<(UP-8)oi{{~ZwmX_gBzrZDa)bt?OCYo8JvGr8N}ANTeq ze+BzUNdcf$6lSSLqC)}SOjex2Dt^C-(4!Tlql18$zNOUhOtdmE5P0_NS=Gh+7u|C& zBd`$Q;+lOf><>CjU=_+`GC5|Xrm$+f{}TrBpB&)-1LgR?(ttWdlmHbv%0%BspP4Fq z+7#_~`)P}peojS};uA{+2VN3)_cxCwtNLjODRU?(67AEr4Ou>T`LH;k7zTX}7(ou5 zcd407VHN)lK{d|)4<*Lvu-8Gpl=8nt4SW+BskhHUW(wnv))DrguY{^G1xf>wSabs9 z?%Q~@_&_LB0N4OB^-rY0fAShGTILM3B$CcXQUE?H%ZBJ3o5}LUMDj$kWaa1QGt#t^ znhszOl5;SGvLKg}w{3(c$0BV(0NHhHT1u&k=!;1<58u@9!E`tF@D?ryPT^D3q1 z1h0DIkRb+GCbjQt9RN6;WD9lMur!9LQ5tvm4B6^#mxLk2S4x&xfh43$Iuaa_LMj}( zN&!3|AJP%*qpKn<=L(2^0HuxE3kM+`X$#00+6HK!)DgGgmiSnL!{|j>d%~dl8$F4DJ7jBd3LV_t;*B4PF3g#- zfDFXe_2?MmQ6!(r@{J7MEdf@+&0`GxGDL7=SBaDBlZt|duQ897Z0L_%fP-B$5#|uo1{GfNH@Yv-b zh$AS=0f0Lu-M{)-W}`)X*#yo2dnX&}eCBjpv0y*cM2ll~GSlJ?P^1PFfLh3mvh4Tc z8fM5T3P9I650s)GGSgQ=@*$32q0&|DM@WD>HG9MYUiPz483{D8s}1+dcfREp4utbN zHefg7kLm)o0X|3gEdqyfHdG1BUybyUftiQePr3o+q+EWr6oBfIrKCng8>uPP4?&I# zyxr#N`pbEb#<`mp;BIwnPi&yaCTP}P(7ou^jhHA1X_QLIIRpFF*mZ4R$o*S%z@Bg2 z!|)zN;G%KVi$altL0%MHu!OO)+%? zt(oVYA2khez6A9ggSwxs?Fw=m{OOp|)T+jroo6VBgU^nq`UlH9@!hbG;Y{sbyDeKFJpAuie zZOBqic5&zvHk59jbC`Cz%cKVTfB=muhaYIb9$siU(oBd`rlga{h4!{FUHIHgBVW2X z5F9HOa&NTmj?zvS&AJ)1^4ZE{QJGDORfcmJ7a45R(Jas+&XXf{AYfx9rL=gqTtPsbg zZxTBaH1i-XWJz3y3=ZiT%HoXnh8mc_uYEF6wFb49rrtk0=iH*PH)j%LfLL}f0b zWUwILFla3DZPM1wIHihEJ}y)Pz4)Hf_62S6oi%@2fR74p zcWkkdJXO`_1eypzk$s%WspAVtobJ&|^3xbxr^dLNE~9rAGP;3U&A`O$4^En5B39nm z0Z?sgT&K`4D25MyNu>E0VwrO;AgbbOHtsJDJl15rIAW7tb2zDRTg~3;Q&SUh*?pBtts(1E9Dv47DAQ+9tN-qSHc1k#ILnx|A&k3RH z{13hQg3KC-+2q*{61-7a;mnFYBu9-$%Pls^FY$f+XSv3}!4AumDRnK2j-sOT)QSU; zHgPHU*FjegE-O&3-l-ZcVbDuavxHoh13y2DDj46|3mV-j>$MzoSD{?qD9Ugq@+rAB zGi2yY&O)iTNd1LZmRjjrtH>KSm2AgPAb|m;@Q{n?jZ6zy+ES_?Bmb6qNNtSa&KD*h z)p39}6%CkeR4$>mjgy>&1e~@6Er*CrpH^qHx z=M`%|U&D|iq&jg+R_@+-DAX~911f&JvEIUBMEeX`SNlSY-LO&AfCblNA`1XW))LNWU~0RM(Q==wSlZqHdjrY};hS0pc9p`9!Y)<<*W%TG_B~R%Kt1mMZG2!0lH5Jm z>M}x3H}EOJaq#@_GU~`#9eme0c`Juu(y!~syfu`Zugpqtvxei3&nfT|m;ZTy00g$2jxh~S!|n<9#zl3A5CkR>}w#PQwQ=3Uf0iLLWZb4fwrPG29xa0+;Z*Ya=SJN_e0Yew_qxLvvS{z(InnL1Ko(N2 zhvDBM5s8i6=GM`W^-FD8YK3*dAEYQS82ri4o4t!V({?7qP2&(s*J&!DPy6yzMG~x8 zj#2!t1{3VSX-&+MSCnO_`@Pk#8}KA}*PN#?-Ht7UP&|LSBWgWuqc_@TLl*HS<#}1T zw+EfQmj}bSjl>(P*Ic?jy$kaIFu!4jUhLp3*~W~i;V6(GnSIeV`sAPR_sF?tleA~QQG@P4 zM|bx2f{pB%N|twmKlVP%M5-Z@k1uLmxxeZ>Kl6*mnKEyZen(Iy+p{5q(%edrs!VEi z%*=L~Ix=Tc%U1n}bpDU1&H4u#`poG_OGyGV!qM^?VR&qp^^sc0YQ15{h@=FOej0V$ zW*K>;J%Kv4k*EQWHuaOM(e947{)m+i@=_%pgqjJjUo+;NZb#+l$I-8qCnyRV{mZ8- z!|f|oCm|km4kBr~Bov@xg8+Gaq3%x-xP|tG)jm-?G*V|7-M_1C)>f8Dw7DiuxbW7^ zQPpxTG%_UUe`-eATH~4mGkL8RETZ?+;pXJCx+V~51*(|Z?x+3O|k>KzLtRe4jt zR5u*JaWKV(+j9!P|ptsruI_z_rtTrdoAnc>H4ib6iSYXrYCpww6C3F z8&37{lIg`pu;~39e`5y?^B%h%6eSu9)*SmUd8q3Mm1q-Q!b%P>AMSBe@DhbMlrnui z3YetWIwVVyasyBkRUeUy&h0$T{z8N6$&cNsjfZ=xi-1Zkk#ICoG_f_Wnay3v1Nn!% z*6Ftr$ftf3tq2ZvF5Ns3e$_nWCyCwD^G}-yc^Tu{4KbVyFe!t5^bbX4tMu`?Z^HIbzkw!TTB!Bd9qTC<9sIr`9dHiOx;X%(wS#wpt{tTXASVHNW z`1|-cJYS}NfZgW&h2g)E;-8`fj7X$dZ9=+@qJW*o3z{Jk06NM?-$$GI7>Ql$&wWBj z9}|y1f#N~aVVkEPae+iY$2Oy~kW1xtVtDS9N1UArVraOWC=Xup2iYad;(*mBz=)e3 zk`zeYo|p!^&MVi~ne2&a$CmNN?dYxjx^KZKzc$&dz`~#_-*9BLCMPG@vUnMp&Ly$n zih|G4=j!Fl^?WI;;J_AGR@h*%N-SE`jV4JtK+0$(Wj%kYxf)Co@MrB!<$G9r-{ti{ z6VJf4c^-Lo^~Tf1ORw}FX^xvI#ipG4gZIuq20hU=ycHjOFOG6Ujvw6*(ArI{O9W;; zbJe#wa2{6)sHUoIYHZ)VtEFP?;&&+R3hg}XSWBje9yYVmQOgY>_t03kaNszB0duk z1*z<-QEgdA4fDc$@J=c?Xp9Ew_Jz; z|GtGd6vfk6wMyHrUNrrUl^Zg(Q8s>Xy6qQY*}p?vF7=WC{NYHusg;ui^{HEa?X21} z{6yO-?Aw!wW=`g4EAc88!sM3YlyUbQ{H|}Ng6DP#+S6-S4j%MQ|D11|8r$|S>KbKK zEhF;NV)t%&d~2>E=f>`AU8tW}aOxOOYct#7gH$lM`ldO(EF&AKmfGo_%4G5Azx9o~ zIOQRhMOKWx^Fw-yZKZY}62iv{r_nBYX(bJu?MYx1&-+qQ}dw)q}@Bd9jm~87Fbbs_q$g@)ME^gM6 z+XSuY#wNlmHjVU_OTYAqoto?GHX*hL@ayt&4fyl_$#`?ny3@)gaa>(5zzuQ1bslv{F$N5(BproLz3 z_1#L4wp&81;FNWDqu?AWeaNk<_CjE44`r75tse)*S>?w4cCHxzVUo6BKFKo%##SRk z2MvukrP^(J)kV;Bhrb<|UZ=w?e-w-7wDMaP;bFblxJxUR_0wyk!#vy;-}(MpzpJ@1 z-rVt~_;*)Fq92#AD&A4&r_(`I4e8hF_nQ(NqiQ!RyAAh}+;h50mB#R`S}7mz8Z#tU z!9={NS>FxMZWtpthWFjZCZSxIn(^D|+5efcybvlVWjM^;ka*H&2Xqst<=$>$(Kp0J zBEDW+;kCU4ZXiv_CUWzX_M5+|x??(aICnM`Hvf`DLkv46&h0%jo>u%qgft#CR^!gf(V=>z7;c4Ipy~QSS645^W}WLa zag*dk*Q4d%hn=S98XI5~?ot?@^LKoqr(m48uIHi>N%;e=8aGbuC<_7yhOz%O;QWOAG5EwkViSzjYQRF7@y=Rx_iz z7Q0Hd=SzhC*?(1E!otXHtyg~E7UmMrjY7g&J5}jAuLis7;W9Gx+_5`%XZKsFxMB>| zMaEA(kZ!1LZmq`a!-=%*q->Aq0z!98ofrBU>bVB9HSc^Fa(y)kxjoy8jm`)s;pHU5{Mn$mJ+4QusdjNe3>Ake_W=b3Z#@P2_za$sAZ~t_M zU7OlIB)KI7G;Cws-+B>CBr$uYj&})1;_MNJLyoTZMRC6t{}8pmZHcQ9L3IaM#I+8H zbQ4-|OK3^>@5=6mMb3_}`<)$^BJ>@Li_zjZhyEBI*iHE%9;PV&fM3vtIw}%amBe#J zDUPsBD{bjzk&$VtB62s39Apr$Ssi2JlaEe!NbVLl-DW4p)mX%}q zV9i;SLeMV+o)DXK70PpUM^EPnH49`q@ZCFgKn=0YXOXiG&+Zr|H{aI6smk7t!QyrF zJ~{om-|;*+lw!~1gIpU6;^9sbZy$yyPO@rJW@XJIURF(QDqTopK>(x zt1UXITF{-csIB5yPl&UtE-^9Fi$zkxY zZ=&$>7^GWIo)U`D9P69R?y`+>r{r)!aoTrO_u!b?X^>kde&a%#5U)IkedF&{L1O0n zP#{9V>AP)FW?pM_G`WAGb=ebvPyb$MLuV1qiCf}FFMWi9%u%>!X zki4vzU{V{8of@Ee?2sp(#T(M3)KF_UX;ERZSxX@4i!>BUD%WE4vPwH!t9U z=7!(%nL4)Z>A%blo{`T<5Xv)aAVVD!@gCBU)aY#S86*M$LR=6qU`RSDNPglVimzhe zRC;~i;@m*X*G8f-?vtrv8(C^v>yv$IsA$tSV_kjuxnC5oq;rdQAcY6TumgE=>Vx-z zW!~^M6%~vNLGf#znqm0fPSGZ2bJ18AH5&hY_qS)K$p^#@6ncmd!aq(+U49j}?P?9m zPC5x+pnyT?kFyCK(FwIzY0t!~k>nLAzYZetx0)hEo)qocSuZwaWD-~7#xx|ve;HC| zve5#)xh3YD4T*z@X41QhN&C3n+$)NSOpiA;lv>PnRyQc{!8){T(Li=% zS@M*NgLnJpW9jzkRR)H$_|IjSo*@BoUmI+SSK_T$Q+qlRde1oO}s>69e3a7{K237vWk z4+fV6!!>E-}t9CG7W-RE&#pQ#BjlA>F? z!pQXyn~dOAM`hQkE-XZ_%k!bmP+vXo-#%M9CocGHlo*{`ln^H^YA!ajG`(+af>q$6 z_kGeJIOU&%s%RM`pWTm@!$XH-Z(qLOZF8j%FHXH9zbW_Se&{rshTWT{rUuBv_4~MM zpNs*mULk|bmb?P%EInxq&FT3jwr=+Z2CD>9o?J87lA)TZ#=&!JHk^R6l0C_$D}AC6PGEe_99vhMKLNsP2B8^K=)Mo&hqe=^DQFNemqG@HMp@+EI%&J zpBOPlM)IMs>06yM^GeZcI+mwggr>nSSaXW>!s*nEl3s}QM!E6!&@pw=Y&U0_9MLHW zFL9^-S-3ilbuu(w+RE8gKRnHLNv&bG`o{TQ{YAj?muCi|Rid22g31fbyY>C93_miP zN$uy@MS9mHhK;_%y2f*&9pe;+Z;;1cwT)A~HM0w`|Mt<`h^*9e-{Y*F=X&d7;?1fp z)<&$&%5}%q!|6rCbZpX8M$In*e%u%#ZS9b7xkiLfHAzhU(n0qlOO6vBd-h^OC$IgV zLjQ!|oH*W~nCmf7slN-ymvqBVwp`X{Hq2-UE?a*I_^7iWibqE;i{0O-;3&N_&d%xa z#JWUBP=XR3iUY{Ubry0Bj;eM1_t(H{>F|Js7bs5eA$9JSNCJ}lMuuDS6dp$3BJ)ax zNHoSMA)52EDYWPmcBSWFxVJr-mlI_<|9OG0h2n*yK~nK>YMeyR=t`l1((QBNCa?Y% zVlHMp*PSS9S4EUv6AiCWKAdPIo5aKA9qp%IJa5wf!49P_ZK|SqY`?jbx@;BKs(rW$Fxi8zo5V6P7}uS$6|ZRH*fm* zO_3U1Eo@&J>wIpdcrN^9*!y^Lv({_5Mtf%+4X;xTHv!n)CYQD9lHZ?`^{XiI9*em2 zP4C|IYve9_F1EfSQk@q?#p6o^mi_241My7E{|cy$4kGOeLtVz-WaPW? zsZ49cc{gkrz6A}qb#kRi&hh|gUk(Y|M0lJ>;b|kMJR#DN@Fg&Rs~kSLnpKneDRAkY zhj?86LT$-sP_^Lp^H}^m<8wgr!3zh3%4t6?f^7sw@CI>XYZ-oK@Ez2|jq)JyQq@58 zIRvyooLsgJi+lNURLeF_RXkpUF+RBo}mu zu1Vh=bueU2UNqfC5DheQzM6iy$Sy+q9-_TIlp0zT?%JUeXIR{_L}iSJcY1_fDjX%;fbh%yjko-==%AZ*P(A zo?DkTsbO5|`A*;+)|CUGms>~@96kK0Popmt5X9l%paIX9{0)-1rYrRnbW+vlzmd)g&RGR)(EmD3we(B%BAP#@T)U;Y z5yPgjcTBLzk7qVb)S52hc*i)ymfm=x8zxdj2BaC+jN3sfuw*ja1&3M-E?5u-6WRzuw4=xK zQ&N93|E#DiJ%Fc$gCWEh<@!SZjFN++heqSf@XPhel}i<^)@_d3-%RJwc8!puXA^t9 zxlT$*@&-fQBuuZe>I$jryRNS}!O-gAc$Hz&P@SrWD4r1K6P-Nwp3tD9yt8y=OoTK> zwOKBFD!n-2{ww>}zM=wvI9@Tf3+^Oi%Udqenn-22ssRD;s`yy&x_p5YtZbhuBDy>Ig$ za}s;zLWug1Uw4nbn%a1V`;^5-;#x|EslBL7vVEf5!T>2lPC+R2(#(OtJRl`xHv9|< zk2#rk)`6+KlUA=scH@t|yP@itbS6=B46y352S#EnmR$2?In+kj*)YKSK5LrTvf=Mm z8ZM3p*ZSE`LJ&lfIdglP3&0tv;_-T5GrU*Gl`|vcSTY zhE!mh%wAVE>gsAQwUtO&&YW(~jv+he$K>+f%k56D4{P-f@dxW}P8UaoXs3??K;b=& z!t1t?e8aIJE124b-@tNqy8**?dW;Lob21W`oH>!Zxn$%k;@*pAW}oO)^3xdG_xFfr zc^BO@2TWh}3L6Er29%YRe03?7o+hxRl+ep4NIAJyxjAfOy!#nDK5qHl^q3NfG3;4r z8|XOpWVauIEU{$A|0zFi-Kthkg{1}8(&f@w-N_$W&=<*+*MwrR?M%2P)e@E{ljND{ z=E=x@6KE(SpMfl=JW%B9`fA@E_I6oE<#VuZCy1m_fp@QS7>?P(*Pg;rJ(jTdQ)M+9 zdCe?W^$K5sYwwrugS1b_*GKc>5Fuoy*MEkm(c@og8wl5>*z+ZwTNJyEsS52@ycupE zNsEufs4OIjS}z^4;>dwRGK^mhaAvD<1tyeIj7uu(em*6Ub$_uLo(ACYlnc!q~L0zmXFg~z}eZ>1&KDD{MRT}XT9Yd>d|)pNNilG z_peGyJ1&)$lSD;#pM!ukALmWYv)Pwv)nPa#r=y)+y6fJKM$ zTq1ih3{Za^)io}^oKl1l_YE~@R2 zH|v4k?Fa)K^r7y3q^mtAA~%*|jC0N<7Nb&Ra;2=;PF1w{p~V?rV%Af38iKFTu00=6 zE;Cf^AZ!o?hO9=IZTvQsxt+XL3`{_HZO;+mY!d{Llsfsw)<~{6I#nYY?{HK5r7;Y*t=b6S9ukre zL+R9j?xl}ZGOGg{y3LKM%{DJ`qYO5to=UD0)!A85ME7cuU*q7B=rD+ME^RN}E1`PW z*Yi$cJ+2AcTYiO$5G|kM;%~u%-klFD%PK*+Sy%_ZGwd~@=K{U&j#!y)&~N?cMBJ9`1%TP&1TG%@+Ijv@WxL&S=>DT#T-AY611m|iW8uet38x@zVJ_X zTApGrro9=A8aId28z?^QHVH6JE(#gEQ{LHY+PxdJkGs?KW1u&1`tv~zfL>%EL@<&sE|Kzi*&rvSs0L%?5?&M$cdYuae2%XSZa z$YNK|j-3Mi`_!ppe&^|TG!wE#dIjpU`kcmgB+{u1#jt~^24_dX=RX9HFvGcT=d}L9 zWH?-6wK8hjOH*F@6*p<`!?fk{IxWqyDfGun>-2Hi*=Fz=^L7@dOg*YcqMR0Grw^s_ z#)vEmTSUQv0TJ$;ucZar`~Z$}q!c(Ch1ZVMUv~Ol-F+l)B>KZ;^+;8V@(! zA8@L(&~$(^O^4`+#HdX27s^mk{MeG(Gyk@hfg5`t4zK&t+UoPsVSx(f{F0P)sa}b6 z>!$!O`M9KZYQ|YWx)9gL`#=04P^#4kFac&zG0XBG3b2y>T(hy*`i3PBOg>CwjoBM9 zFNK|@>xc8dySeZ1;dHF`J31xMt$lcQ>+AQKNu|{LU*E?ww;cc2GW>##ObS~>#61~v zr1A{@>DK2ju>+0rqSIq)lDr&)SRRgwm@?oHWA(CpeJ_6?U!KIWs z^rq*$>rkRpRAZr@KF20HBGTv^Q5Kqe7J?wi)6w9`VuRZ^9gd4j$2(GgKgVhGKCMQq z5q>cM^poxSS{v9pAnC9a~;`=k|VSZm_lE(wA02$7$*`GjOft&?G z`afC8XYyb`D$CW0kTq+9n!xkooG-hd1l#N-sZ@HBnxYa*``5^cc!~J%$v<*TT_y+E zgp-(tr6||$TxIAJxzC$3Lnad9D(_2pWQYUpv%mBY^W!XODw+(}n?t*Cw=#$PdWURg zRpI}Z!Fm!KLd^Ie&)Z{&=Wf!;54eM`Gl^Svw7YAp0LRI!YXMt+O@|idAGP)&R#r)4 z8pFX~aR-xm-#^jsP(N?WSffrRk$Vb(#w=?B>Oq5@Y$!U{ zc0}}sw3`mz)G!6<7ibW8(i30WM`7Cfz6d*iPD>A3DOSTj1==okE@J0+sfIj^V{blyk_7n z!^yhoYFOB097H-RWwL$ei{Y>&f^)alVNkl9V^?rFY(_xI3yvhbu)2h63r)JI!qV%gPyv||_V9r^Baf+{{q zAo%v^H5N&e4c zNl{bA+kO_ekkZ#@{;3PRF^^RS|4{9iEuCx2nM9REkwB>a?^8&H!Ez;=Kdaje6F*+0 zVuEWXwUGvmh#MHE3H_f{DIAl+KUqQuo<14H6D*6P%XFsiOL!2QzmE6|<_roqk#U?z z1PTJrZ9k+hg+X;{`Utqek|8^4eK4_g2}t-EWcnUVx>M9+-;@Y`tW!WGz_ra8{s=yk zF5&)U^&gp*Z1fFCZ92ep{ak!xF60}NWC?wyILGY}DZs3Mxi}O#Jl!;u>w-E|dSX}P zvcEB?{0#n_vuOSk3qczXT_-Kq`5@|Nrcle@0aEmRQ0eUI$xRPF-AO~WW|1su>(V`sNtotG+y0zjhH=u#wBZva>lj^o?fxb$}#d|wFj8=NI1G7TNM#`PB=Pn zE|E61T-b?B@QPqGPPR(rUQ~TiS@!gY@BOSSU-4aR(^X_XIzb6jCMEscYgzoi^KU&` zWQn9?Q`UuPML%tMdHFcd&#|PBTga|6J6t5EA0!*A*bc8bu!0HDqXP7LOp=28S5MS9 z3G9;Jlzr@-7wJ53&ci~;euNw{1%3j)K$I9W*U!ZZwT~nM`*G*ZkuG0jjN-Sc9J@$~ zT=*ZSTLFtAGCebTwg5Gu^fP2qyk-BZr4iVsKDx0k9<2w$dL=lZm64B!fAw!yd&@dM)0)3e#IoY&wxa8h`;Po)8N_Y9rkDGbnMj z{{*;OrX4^=wEW>u+o-RO0w79m)y5XL$jdfB@{c=T2+GSJhaQmZPaG}B?q?q4ZHfTH zdQZ!-|HNX?;=qYgAkj!SL>Dbk$-ku@_<-}DtF*31-om3*IT15nG?z0Bh4yUpFaxgf zG%5cqXqUqAQOgOK#Epet#bahb+u{H`fQ3+cX5FxAGb^p=)>}Ami`S+H)&VYqB5Qhi4}BvyTgn8taA`m7W$sx;^+Z?xvL&g{?q$ukI_&>{Bm?N1#@u>e@4Ua?G`sI~I>%g0Z zM8AUt9500(pDRD`($ceMx7}AjKNK|0R&8Pf(vdts5nT==eWZewuGO%-xX#s?qigBx zA_K&LF`4!q3M>B!+kj6CRGKpJfiu+gNLe2J$`E1O?#CPG?|jfm6PN<{jt})rXtzKd zBW^G86zZ+aZuXsrZybS*ANp;0aoJ4Q55V3N>4EX4j}0e`nY#5|c=TAI6Sd{o>YrPU z76&~``-Ydj0ZD9O;dwF)x-_WtGYq;XbazX)?=YOOmApX#Rg(SHX9^@kW`bgm8{vyo zPdK*P>X6!u6zco)=59Rowtq^XI#Nm@XN$qbKRd@sLT1oSo(8gb83*%y*a8CgKSxzn z-w5-q8OXov(=bQwO?WVP-+hAmg0xNG%D@Bg)LvXfZ({