From 0f69cb55da844b5e852f622690720b8506033ca0 Mon Sep 17 00:00:00 2001 From: Avanti Shrikumar Date: Sun, 23 Oct 2016 01:40:36 -0700 Subject: [PATCH 01/19] pos through dense in, and works Former-commit-id: 7313f9f55eac61c2527ea4fb875c7d7a0aecead7 [formerly 93da2cd57bdaf7157ae264f547cd555f35ff0224] Former-commit-id: ff724dfe28fbd44a1737b086a6299ee64377b337 --- deeplift/blobs/activations.py | 3 ++- deeplift/blobs/core.py | 17 +++++++++++------ deeplift/conversion/keras_conversion.py | 3 ++- deeplift/util.py | 2 +- ...nt smoothening windows on KS statistic.xlsx | Bin 0 -> 53061 bytes ...on score distributions.ipynb.REMOVED.git-id | 2 +- tutorial/DeepLIFT tutorial.ipynb | 6 ++++++ 7 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 examples/study_score_distributions/tal_gata/Effect of different smoothening windows on KS statistic.xlsx create mode 100644 tutorial/DeepLIFT tutorial.ipynb diff --git a/deeplift/blobs/activations.py b/deeplift/blobs/activations.py index 454c49b..1e994b3 100644 --- a/deeplift/blobs/activations.py +++ b/deeplift/blobs/activations.py @@ -69,7 +69,8 @@ def _get_mxts_increments_for_inputs(self): else: #all the other ones here are of the form: # scale_factor*self.get_mxts() - if (self.mxts_mode == MxtsMode.DeepLIFT): + if (self.mxts_mode == MxtsMode.DeepLIFT + or self.mxts_mode==MxtsMode.PosThroughDenseDeepLIFT): scale_factor = self._deeplift_get_scale_factor() elif (self.mxts_mode == MxtsMode.GuidedBackpropDeepLIFT): deeplift_scale_factor = self._deeplift_get_scale_factor() diff --git a/deeplift/blobs/core.py b/deeplift/blobs/core.py index fdac833..6f5e027 100644 --- a/deeplift/blobs/core.py +++ b/deeplift/blobs/core.py @@ -15,10 +15,11 @@ ScoringMode = deeplift.util.enum(OneAndZeros="OneAndZeros", SoftmaxPreActivation="SoftmaxPreActivation") MxtsMode = deeplift.util.enum(Gradient="Gradient", DeepLIFT="DeepLIFT", - DeconvNet="DeconvNet", - GuidedBackprop="GuidedBackprop", - GuidedBackpropDeepLIFT=\ - "GuidedBackpropDeepLIFT") + DeconvNet="DeconvNet", + GuidedBackprop="GuidedBackprop", + GuidedBackpropDeepLIFT=\ + "GuidedBackpropDeepLIFT", + PosThroughDenseDeepLIFT="PosThroughDenseDeepLIFT") ActivationNames = deeplift.util.enum(sigmoid="sigmoid", hard_sigmoid="hard_sigmoid", tanh="tanh", @@ -461,10 +462,11 @@ def _get_mxts_increments_for_inputs(self): class Dense(SingleInputMixin, OneDimOutputMixin, Node): - def __init__(self, W, b, **kwargs): + def __init__(self, W, b, mxts_mode, **kwargs): super(Dense, self).__init__(**kwargs) self.W = W self.b = b + self.mxts_mode = mxts_mode def get_yaml_compatible_object_kwargs(self): kwargs_dict = super(Dense, self).\ @@ -480,7 +482,10 @@ def _build_activation_vars(self, input_act_vars): return B.dot(input_act_vars, self.W) + self.b def _get_mxts_increments_for_inputs(self): - return B.dot(self.get_mxts(),self.W.T) + if (self.mxts_mode == MxtsMode.PosThroughDenseDeepLIFT): + return B.dot(self.get_mxts()*(self.get_mxts()>0.0),self.W.T) + else: + return B.dot(self.get_mxts(),self.W.T) class BatchNormalization(SingleInputMixin, Node): diff --git a/deeplift/conversion/keras_conversion.py b/deeplift/conversion/keras_conversion.py index 084dc0b..3b70659 100644 --- a/deeplift/conversion/keras_conversion.py +++ b/deeplift/conversion/keras_conversion.py @@ -134,7 +134,8 @@ def dense_conversion(layer, name, verbose, else "")+name, verbose=verbose, W=layer.get_weights()[0], - b=layer.get_weights()[1])] + b=layer.get_weights()[1], + mxts_mode=mxts_mode)] to_return.extend(converted_activation) return to_return diff --git a/deeplift/util.py b/deeplift/util.py index 561cdb6..57710d5 100644 --- a/deeplift/util.py +++ b/deeplift/util.py @@ -261,7 +261,7 @@ def get_smoothen_function(window_size): #we will trim off the value from the front of the output later on padding = int(window_size/2) new_dims = [inp_tensor.shape[0], inp_tensor.shape[1]+2*padding] - padded_inp = B.zeros_like(inp_tensor) + padded_inp = B.zeros(new_dims) #fill the middle region with the original input padded_inp = B.set_subtensor( padded_inp[:,padding:(inp_tensor.shape[1]+padding)], diff --git a/examples/study_score_distributions/tal_gata/Effect of different smoothening windows on KS statistic.xlsx b/examples/study_score_distributions/tal_gata/Effect of different smoothening windows on KS statistic.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..37f466e84070369466f79db97a2f2c19b9c53bda GIT binary patch literal 53061 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
    62mCMJKV7s;GD)r*%RF=>+D6z#iQ32VJx1A> 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�QbNQ?P`_Q|rG=mWsps}84X=f8a{?FL zkaTD&7O&jJNnez%rPLKr+fjy+>Z(FfOLurcZkjE1{s-doibpV@%2sFB3_)L+8{VBo zZWto#4T(@(<^uvlF|f~}C6P`6r1I2E_}~#<7P>UO=;v=E^x+?PICC{Gd4d%8XKbAJW6gKLnmy4Z>}J{i?Y+_Mca-}d z)Ha?8sNHAo{5I#}PkLtxJ-6Szwj-?*5rcjkfL>9n<0y>-m@uJ%e_DrMQYR51yE-__ z8>j)iwmJQo24tJ{+~_j0Uyv4Qcj zisdpF|-h(x*IYr0}W?0v)fG)B0I=ikHy4O;O>7}U9 z5Gw#^ziEftd4?8)+vfGi8(=r%ECob;FWJz7?e+*ql+7UB-7xnp*QGt_kg7dp`V95K zb1oP0qfaGKnMR<^C9=gE_uPRwQGAv;7W2UFKCZZG<|)zpd_%(X`nz8@U3#DHlAA$3 zcE{y#jo!v=^>EESvMjuqfr1Jq)&RUDd{`qsBd+=mi37dS!Whix(^~7a!%hqCzW#wY zSx>8W&@wkYH9+BfNZcKGCP*6Cx$V(iQIngioqTS>^-Zm8C*4N|x6V1k@iT*3`lN>H z+G{pEij1whO@wuFe0G>}fk$Tl^x-zBm%X#g&FpagvZZo+Pi0lzip98Ji@DuEm)LjA zx-Q7M<3vr~2(h+S)yWm6d>K1aE#F9b;Ogk|3;VNm*#Sz3B7{t#8X(M!TM0uUim1Me zF#HU<%UCV8xL#(u6!?==KU`Q*F}b881l`+k=3vFM0OAIyd488&ScY}kbQCF+|IoGgHzWxl+?d0eLRTd%xYaQ9kF}NMYh@jt zZg=n1Ua2n#bF6wC6wz>*G(FcQ&1esqr{lfrBPMvh1%Bz*Xb$>s0+Xf&}^bnC`%UpL%0+f}5aIZ;|73&d+2 z#Qi*_(qy;926R>$Ir0>$?fsFFG2+@jy9eHuA~!C7(2AexS>OMKqmv)mrmZ9OdoH-p z`#>0jn5Dzac{PgVeLf(6B4#_XWC5s=aKLqgVMWV+Q7-bI>)-cA^19I0#fXUN(z^`nd!h+EvU(s8%#) zz#s5^JK3^){MjJgLmrRTF`XY2KAW41X?;eq$#{ggCmz!R@S?dC)RtblmkgPjhZm6| zKT~5y{O<)fIW2M9%F0G2zkcisnpr9pI&xOBLyK+mgUCqcN`T1Nkg%j>24BwWo)`D@N#Nhd?*ZP!NC3mPN!hU>$PD0J0( zo1DBW+U35(@>=52=QM<4^e9HgNoMS2igQH_^`}s~9DGbG{XU;hG!BZ`Yksx&a!eI1 zCvc}-be2X??8REPJZ*!X;}K(anK~P zF*fx4(%)A*i$`X1P0V>|c6Ak6Gj*WB@P@d$;b=`SC!Lq3&U49hYv5B0(_kShOoT@& z_sFOyvL9m~RB~-Y!v~>q`%bjr2(H z5DllMa8FiMcF4)`rZeXLR(EHN!60Wuocc6dOFD5pbtGM?A5;i$heJsj#ibYX6 z*8QbEjNOdM^07|AsQ}xoPP+#}}a$G4(Cb#I;RQ-iOfwAxw3#fggz0WvU@f zBu1$Lsu$y)fw&Of3%%AQf)$HuOFvKjkmx0S*>_NnC3^+w$Dh2YU34}^x7|X%=dogS1@&_7YCPa=I~;r7bNoqdL2If z)Q=g2r^3ESqc^XaHB$plyhYsUf+{hHpnb}u#{+lg+NC-URHIgSVW+^qduWa`GU+Yh zGk!?LnN5N%Wa5xOJqM{z$_pAy2{9RK+Q!n+_VYQVQGD5O_K*6UY3p3X2=K8O{_hh| z78p+eRJr3vaND4k7OBeU-?>nEmC3i(xUd^Gxy>YOgP@oka*pE<9haQQaO3lVl@EOZ z*2I7jsW-*7UjS@Kz@Pcg#jM*Ea5;5}ZiT)cJ*zKP)V!M1czpAS0 zXkx-4&`PZEi*tQKBLwtt3A$}#7P-IF)(qDDQ@x`3X{XBaS7DSri4zD}D|bIWH6w}I4Kf-OUb429{a=0sOavk*8g z9M-`bG2R5Q#9diLBtND|xdTd-5lvoE%W0CAhMDwU zU_yRFTCC*aFK~vLvbov)vMxjV5r|z%gfz#OAWe@tuys(((wiP`7tgIDF>7I}R8(+E zrn)~qlE0j#H`2lawF2SyGIN2gPyXsI4`drC9qMA_c1(q@DEwcC0XqDL78h>oljGB!`fb%_#UW$o8ho6(wd9}rbhKJ6Tv zSvo-9C8KT#AJgOmxI1J;=jOWE0F{K8FYcc4o5JOX+y6DsYq(Qgk2oMlCO?H9ikT+d z7fL2sc1^X7zORR&Pumv&JX(szZ3XPEQ>gO5m9W64h2JA>;5H>UjqV>6z1^rQ(w6Tk z8~D@HwQ)59hHqe@gBm|Xh8${?mo<9_wlg#{0zq~rZs#Fc0n^j@f^VTIlmM#xIS$NF z!yZivOzLakCSFEvatk~VcHVaDfL@>05XHa%F~zV@n&k&T#lSc5m>Lg?kzM>e;|) z+gUU9DO(HQ-rQEfPf_JlG89_-b4WaeTR$|WF&z7??hhU0=2An@nJa&Dr$YHNN*`q2ik8l@Qc&x`_9W#w*>k>^ zoLa-Y1X;;Zb$O_gkZT;;(Gj22mRL?H+1YBO+BR4N@%@{aUBk?J55eW}F@PsFH|c0& zYh8e*KKQfJ7(07D+kAq0IA>`r4{-IElVlbqEi;wwK%2^Tk6?sDQq+Bd1UQ{^sIN3}iN`$C$YaV1nlO%oTfBy4V||1&3V90u)Aj$y#S>Y0&q ze|euYcpv0DeV&%K#S4o zi@|$f!4p$v+dok^$oH#?2-fb8VQuJ?kDecU{mr+JgXeN6=YI{1K~TlW#EmqmA{p=y zXSgzt0m7SnjGVQW{>$K-f{D@Np8PPmP<=9BFqQ5?iW)!jxw1~%ewZ{|<39@B_9pwm zI>^Iy-qy<+!!nzNz%9sVfSr6P8h?vzDA*DayrsLknjaz1hQn8?ZB-=YK@jq#V10K9 zS$o_0-ZkWM_~JwqIm&bG5k_al8Mg!RepeAQN@NAe2in(i`BnMUKU1#ktQn!602v5}S(IH=TwVJ~7*>B<8;{?^z>(}Q}nhvHsU z58AMfknYq26}HI-v}{rMHJ&B!!mrMTmd_A@d!`vd!M}DF{`2;@TBq_1j6)MAa+{^e z3g$+PU^5H>7|^XJD1ogwn{I}=(i`O5z&bFg_*B(a+PyyUmYE!=W^%ew8m|I`h$3HFe>cosULfe*G=g5Zje;3;H!9bhd z;xEA80Wq2T{<5ESY;UV2G4`emc-)~_cH7T{YySJC2o)tK+z7UW(m*G9Zo2Y-9K9AY zC4i|f+3EOIl`&K;Na72k%9v%)rxTJ;c&pRT0be*Fk0w=W{mT7ovRcPDMyc1TyyUaK zUtb5g`_%KgE4Tf=78Y5!g0U^kp&tmjFa=AIH=$NS0VPNaag!)Xm9$~0N38_Au5@xK zyHoH&9vE-_D?Xh&W9uRImO)jF=Ax#>x3hNK%>f@3zaxJPs76%A^c^s=t8@bFO3LZ3 z07X^IlzFfJqELJj#d){(kN&$9!@qa-EWt*@zclA?*j>+cu@|@JY|le{uaFrm9p^0{ zR|Z08xWjL6@iwBE9v-B}078+oN6V;=Cs&x9!*I-K2_R;EQ6`+5VCx2SJx(Z|s2NaN zRYFe9c}>|1^QX>a9c>%<7>Zab6AKW~x$zhFXx%fAeoI5Z)NoEkEE9KMHoI+LI%scu zvtV~$^{lA!vUQr#tDy5aXJn*@X$6Df(FkP<(4{ndCPH1|RGMnA_hG8ITPBzd4 z*e&|=dU4hfXdSHI#O(T!<_27<%(^OGkqv>%4$6JCOr2?*Wk1|mdM;2m(>DrJ{rjU! zZVXF~_1i3bl6-zo;^QOK=7`U7X9>WFq8)yl(j2nTGBYW14(s}ez8gH#yO1wj0~NYR zHI)%iYzh4spi$b;brTa~yL-ex|3F_JdLwj^oFeSTP~>4b-w1utBg;idE?#B;bggJD zIjOWLcxV)Hg@@V%f3?%Q5Vj_js~^@mxT^e<1u?=^ql^SoP= zrDQn89g?;%H6h3UXry(jaoZtjP&XHYlF~v%!(9puwhXReT)?H~&~uyvcIk_8RiAFo zR(*NYx9v^{pp2UdNXYjwic9`O(+lpD1naPt!|v#J7J`~GN;UWzFh&4|!DEP41`^ItfHXo?9bCb_e_ zU~$kod6w0cNln1Y|uxp@5uoUY{GG1RlCeUZ`Bbu@R;-Uz{N zZhwqRM@Q4XfNsuRMXzVcotIns7ciM8p(t^oK5(2PLvN<#%Xsa}?A1_e+tnp%3uiqo zwH2=;hqTM+gco;TkB9?YKPBE1$7yC_&lN$j{*ETLe2ZUts=tJKJI^g2{jx>d^_2W# zxl;yCn|`#navWcqo24`cbV$8j$D!at8>+GL5_q_*C>$n0bD`Li&t8D*NsFRji2fLB z`ow=FJ2mY~<%5BfFGn70zHK0+(4EJuK{}6mi^aE7c@^TaMWQyrOm&`do5VbKb3HxT9uHOA65naI6V%RHB zflSd*G{;~{fzt%5n?UloRgx{=LoU>$@1t&nyhQ9xbi-m=&9}hR<3P+}8pAx;e>&jd zbfFP+!6C4s>55Cn${s%D0fAQk$MpE-V4IbPDvP&MYz^wXx4tN#4*fPx@C-x;1B*BL z=2j`3=oNLvjc&n))(Mue)h!28%K3KLr}TN`Y?lG)DSc~_SgL zEqFt^e}!srNh%72Y3QkkvOpTAU7+5>c@K0Yg#g@vig8YgY7O{gY6(?Lp~3wHTfW+< zVenR08eV4EUCA)Rr_PTGO#8n$lsxl3p+1Y&gu+BM!{m$JT1T!F+Je6x2|Ql6BZL*u zaHg9vmwc$@@h5dew3-`^09vseMqLy)6ZD4o=Eh0UoJ_p7O3O(^g$~V=9H_bhv_+Zi zqL?hbWnGE2t!j>cG_5l*V3ZS?w+@aHH|W0&4)6kQmM1(!#4%^pCWuHHVSG?5)K_9s zoAcoIMY*+_7S)Uid3ZpU6?L*#3Dd6nG{Ql`22<f{T6kt|;hGL-ev4=~5$v&f>FnLE$B?d~0;RI1IW?0Wcqk5t`o;~Q;m zDqaebCM&6rX|==w0ZN#NHH%&`mci*>b4|*#$1ps5NP&br-}grfc0%`FW>EI`O>n)u z<39d-hVOf*1Tm>vYuXg|Z6YOY!V|kg9zTbmpBDnvtj8pVLGS!d8L%J~2~&d|o=U#h z{Fb-)Z@zZ}7_*WnD3p6;yrszR(mk8P)%*GSGPX|FxOBa@UGgJO8-ZC*uqXO>U05u| z`CaY4O<(_Q&k4Cp*nZcu2>B;Nk2ZJ~v}y~VPhb$%MvR$)+^$(y>bdboyjFNlE?dV~ z5es#|9QCk$`>FbjWxta!EX(sA*xrvl<}ejzv@|-9Q;0TU-2XUo77@JiNVT=}9$ePu z@m_k_V%i2_c$dkP!BRq5a&C*%U?xwHUkn+`tE8XrN&fbFs!ibgqGd#Z3_%8o|xD5U8L z{vG!vwKAeQueJJ*+EH$H${ieg^~YhqdnaOlAJkq|)^zBu#2OcmE?FLE_KS)ll9il@U>F zYb=w(yzK=d6nOqXJb1Xh1?9{~{Y;VuFz?qqs7QbGK1UEH~ZyFWi@w)0~qpyKSS%T+Ur zJU^d6&2M)6lJiAoXBkc_`F!`N(6ZqfVNLc}8E6sM#O?JJwT_u&_=D86XqQHqr{i4- z{}wpx@i-z*l~xXQ_<+y(&+dA=AM586qU4)C@Pz$^)8p#G6*df~VaC}lUF#qxMI7MN zg3(g$fjN&w=hcPl_!lL7ud-Iztktm|<*94cq`Y5~T8D2}6_J*_I^-QA70a_%HjVQO zRWor%UZNzQXx~(H`Yu?q=?aJHY_J)tG(*|ceAir{&{(PbJ2_C@oMgy!IU_51(Gw>EdBLai}4^%fIHC zK*gaVWceOMJ%X!JoPL@GH4*C@(;*aw`{B4LbYzs_<%6^5f3Q4#T}V- z7o+qf^K*LPOUG^Iy*g&Rs*d(=iFfg_4(y0DQ%@FxPM>?F8umjmn6>oP)TB6O#+PV{ zQ;SoudVik83+&2HD336Sp#OC5rAJV&(#z=YrQBN%f&SP%)W?Ce7!Kd_u}uJS*kLzf zlJ7Awcf$xybqutp+}wJ+bxwSk3!LVOSO#!l-d8n4Jr_37I910)jD+LxH9(Lm>p`pB zW#+yOAHRyMIRAn3M*z!i$?`d3F=#i@l-Y7xKAID}Y2PNk%O{OK?g^OY`S$wjKN77y z)_0e)fBIeHOF$xaP%h2DnN1dMhbR>AZu|HMtlkh@5Kda3l@gBihgiY}&_?^1MjCQea&?i@3E`09Pfswbld3<&X8 zzo>n?oi)K8Y8Gsyl`U(zLmPx^BVpnahCBcPTV@+z>kMp_~&jSY|1eSet zFS2FY6WT>DZS|8(T@rg}sXBRwifv|mR1K4++NtU?a+I#)&^<$dgLB@Jx&qC!kjE2F za?EJ_A)xTi;|Sk4o$K+%(@V@7n0eu#@({e7ooHG3k;}w zb!DlxO6+Z6AqX_xKwrApR1xqNc6(U$*+y4*qduL0s|2NGSPST0B@NFpcGiZYd86&c z#Zx_(LM2xH(aSF9BInhnRJyrs4+j0e+VFpR32|CA2>X2ce@**=sE_22H%7N>{PbP- z+3tV;vUwt|LR_mZlM7RIl`-9Q-oEfNqBBg4-`1JVWOz*}gTfvW{b%AH;m}E~LLjqY zDmSh$yA;Yj^AxCSXcAOB32$IDRlJ?bbq+0jcqP#kx4oNg4$L(FKa~yOCw6zuu1_(1MtCWtjuv18v>>GDASq2R&MotdIuxlol9BP7I z=Q#eUHi6m&`hETfW`qPNe1>x0GIorPS-uKOyw_@ER6x$(e0u3F*JKqhLg3WG(93Oh zatdC{YHql>w|ydu;M*JRMO`D^%4&@baD8K#=z5--#n7vP3LYu3dCM=K(htA5gSC1f zS}B;&HLHyXHqB@+msR0g(`4>4iNmLqx=F0Z3QMDIdrt4`UBg3r5anW-5K9D}Cknj2tLkcxHxbawjcRn*qPCG>hy)`Ypy*JZ*0#a?Pe`bIV} zU-*zxMhSV+c{wb`1QCzE@d11cFq4y;a+8PO(P9s8tZT@5Qd3798dx?t6l9xy!TQE@ zU@(Q+0CGgE>#(N5om81{ zPb5SZ1DV6QDNLT-$9|=!O|Ut{ET*~m1ZKH8DYv66g{psgta1j1ZDYm8ZKht7qlzu- zFx3Ji#Fl%sG?Hhv6!9Qhyv$l#mWk5|>Y$RVXzA!RBund&pr~e(E~N$UBx%?N9pTmK znBcfHw)u3)3yHWwTYL-ATuI*wpfeeE&EyA4jc$7UBWN4`7SqI{r*admM5$lhS?y`W zoiOOdI@pyx8Htcg4)=A0MJXCb1~cE-d|0M5jv{`W4BiGfJ_B6jg=`?u9g2BC!;7v8 zEPIrPilIQaLAp*fVPg>OyolI%V?qS8&RAE6`m&e@GjVoRX1PYcm&}%|{3(x3ITVM0 zeSx0^$Qw9Ay7NC4s-0ars05wthy$~IS6o^2kBK;PB1^bhun&4fyRq!ggZylz zvldn4ML)LgM-T&hNg$5AtGy4(2O3*psg(gQmN0G`*vwedhxL+i%!9hZ9uTU@&e?)? z@X#ZpC2o=CJGPM>rV8t-J(jCc5>q}5hh;)k=}7qNuFA6!8|f}!W&Ka2wa<=qKJkwJ zqrGgmXrIG`+v<~dbrbQq>>-xIXXP1V7mXm}!90e{j~>*6vz}U4O^fw`(&Tfugd0`* zBXn!%j@*9b#zF=&-Ptl5)NgmfxxnbEi#6ef)QC$=Z}9BRg9R)TerZ^;tN{ITu>n`#-aMo9)(-#UjB~h@))Rwj`+rXMktUYHv z-L;o1W#KnqH&-yaVPNv|1ly3l2K>`mG#xvp{`@~sn;K-d=+ooiwYh4`(-(bQv`&!w z6+7DxF)0JRGg`}4MQAN(P~o)lTwtoS%xH7k1$woqoEjxKBRU?0t6lBo12n~_V32yV zavlR&@nF^6o?>Pg?N$IS0uLP*pcp;8;jWDNaC>r=#ZeHM#`muxYn4D8zrx>L= zm*|bK0SN(ox{2F9G;M-=L6Og81hi$yTm#!qDG&BD&`M{}ueHkzDwBDLT)o=Iqyj5AxWJuH+0x1h{0)dbG42)PTI zDyH=;uwYtkBOf_Fq}n=-*HTjD+7ZjmIROLLWh;TFC45hy1OCA>uPn3==&i~w+A&s8 zLCZK=xPV!3F;cyxM36NEedoA63tQF`wW8!Y zrx-H!pW@X9rM-_QXbwsDHmuxOg8;RyWq6qPKt6(Vs;Tl^pUQcNevoN0U1-&V+fLsL zII*xEptT=xRUGq3muN}x|-oH4+@9%E~Is!xClp!s>f01xwIXvD~r5y~8B?QBbZ z@NPIUE;bpr8p>}`sjpR;04lC)9p! zd^9L1FQJvbUOb&Y>njD)hTciQYxbDnm04qZe;}%HCO;6p*29SJE{eY)FK}O* zVEe$x%R+-X&;d5X-pEUB*7oybpY4hMOJ&xTFyZauN7yv2XlN2UHPl~6WihMYb&_Q? z2f{|j+T!pWpD7IaiC4wsOB5(?l)|$8et|W8|1;=X87bHxU*^Cs)PSDBzro@*5RKG> zejvnC6WUg%fygRgmQo!vV(Zkh(VrIL*T+pbsa1d$*E6hgy`I)ztIIlIrY<9-3SnSB zeC`HpPgPlwnCls6+MB_)U}qsjl(CWc+p68L#V=OOQL|(LBi;c1wqQ4D%n~fiuhL=MHeeYJbrsV~!6lpk8b^%U4oXv%yN4J0oW~w5WiE}CKbelp zR&^{iB3=Q4Y>-G?DZ?I;b8a!$FJw8r#2M80VI2TJUml20q|$di4Ctg@bIM@sn05|j zr6V({u~8t7+=$U0@(+TJw2yPvP42BU5&H!@f|R-oslJWc6YPR5z^ z?CAY6Ka2Y$s*=s=M!>v!8=G08ZS9YkQeh^ghAId8c4&0m+g(OkycsGHY^PC=0(b>e zoQ0SX8mcx!VZl)BgtlKBLwB(5g-t0$m@toA%O}cMtA8LaML7H2qFcyEwLCz2oGJwd zr<)QryLdt^fh#R`oSlTz4JWSWhg8$>twKEk2FjOn`AmJRZn@I87V?rK(bHpldsX@{ z(8<^X&SpTYR4;pTwgifAR_Ue;w2W-53&1CFnQ1wMxGY8B%1nBG#w)bz z7huRnrLVMuvWw~GdP_mgo3b808jw#Yo-|14=N)GCRA>}$Ru|;BL2TJS^OW6fUxJv& zsIaBNIg6d;kyba0vXF0=uu_TQ0D4V?uiGZ6F?|;pH8I#iNOJy^DbR*Ky;NCttG3LH zS-_lk3qD0?ZcjxjPxQ=7#$iqfr{2wOmYUM7<-}D}17F8FuLQNH} z{R>7S%d4T-K%r!QWM&;#(;J>QziB?LnB~QdFIu{QFq6JyU1!!=iKxR96L7m9D<`a` zNoANUzBy-_fd((K00mQ%_AgW+#v9CWXZN)TFasFIe%e>2k=HmYb>a|kwV)E_;xhkbAaQs<$cmsbpr3^M3 zFDcIO$rJfMKYH;(GM*E5ySGDJuekb8?>@tn;jv8?nwNaGA?nn|iAVwJ9W7sx2bBX$ zWa=7PhD=kGV7X&}i$>0%P3Bqf?_so!StU661H{A_?MRqwYkO7%u>$J=Y%MLfjaoJt zXCD_--#A{M{?pRC0YxI(=N;V;ijq}DH7_>c?mRhg`LcX-WeJ(JiPq(Fxc;6fc-#GM z_s7tUudA7kV@CShz4j*WtXX}{=cVfr$XK-D%B9G(1?M;QgqZ{tb2kEco&M8t@2noH z7XvX5n1Ry>0(1b2`GLSW;h~=ggx{SL4QR$9^*bTaxV$%Y&OjV7){MC{sfL%W282rJ z9c<{E2>5|`KaKcMjWv`NPf#q?Lhv~%BXD&m+$vE*F4GpM8y>(YQskI{4JZ4gVcHs= zp?8rvLAj;S_y>Y*%2t|@iOK?a9>D+i56obYlA|q5=Lc$?d3WviR+(gzN&VBcdxu7I zJG5rI?mjeSb@W`m=Vng)|KVo;Wx;0boA4IAn2mY3BlCT`yvyKVNety2K31nT`c6_k zr14wgu8?nzd&Tu$h!{3-gGN-*BbmVED(2T1*l6~D_P2vlOZNM1Msrllvmb~*+PH7y ziAmqluM_vf+?%y17KH@rzP^38*%DA>ZBK?*VbD0G_$=NgUE}8Y&#!9650XzjNOY$D z@6Q_ffBwPG==4HuV3sW+qJj>DI(JcJu2;kTxj_M^{VgQbn>V%F&KzDoqh5dL!q1{z zt5XoL^R*9W>Q9fm2g}si?x1GNKlT@4NHqGn14f7TAmO03ep$03e6Fm1aGaMndw$q% zd&;H<*JAB2KQKIv_=-$sZsHORl&7HrAYWE?i=jOP&3Fv(edK6VLWT@;d){`RICuvz zR{nry(Uw;`BOUgwM{OI7_C5wNMZ>M{dHbYC?ws*hoqN?NV><%%?Fk$UKlO6xF6A^{ z0K|+hc{|;ZEN_;v)HpjJ%1ui%8>eC1IUpTkA z$PC}Y9&Ufh-t;*{2nbpBqeiAMvzsKVzlRjFQkc3p11T-FJy?HW0kZ+B5TQ0nRND{9 z;^*|H1ty>+t32FfR**)eM>m~+LvjAxdd0{IF%>;GY|-K@6x%wm52FW_#@W{T5-I?I#? zVPQa^%O}VeBdIkEE=gC zU=m@_Q}Yxc9mdOy!F3)c#~*Cl$RyK#J5tFWPR>km*FC(U`1FM}XBz%QOyfEyx|Y^M za9zE6Dfb7$_Az4FiG`oEmNAw3(?n%`k^1K`EbJrZz)cxIC}(~hPDIwiu<8u~95|YB zCGgCE2*iK6i29$sRZ4hN);hn8gAoi<{k1TRS4(nEJFL+Q!+3oWiKYGj&}$>N>+&}J zro;Kaxx@eaGWQeKjzE3GGr@<;WLz|mLn}J6qc_IL@^aSdyM+BSQ?W1`GJLxu;MCiVO5x$G>sAn!D9RJ00 z{ihITXY1c;_GZgY!K>7)`^Tpd-ye<-iU=vfwK!Lp44Nt>fcN}CO_oPi$Ur5s zg`hV?jMxK7+pY>6c_^2DN>L$U^I6(9uWNJ{VC>7XwMF`pj^0mJt$hwhMWSPXP55k9vL}B5qMGJWu)9 z67K*ErbXuhCHF>|m!@*Z%=_UeB?a9O{42tbO^uux20uxl8el@tn- z8p5#Ikk(U5Y>%I;^okn4n(vGX<{Q6?LR!^He z;;D@LqDM`}&>Mcz9Ad13C>1m(#cfCmeqC-=?SjpgdtsP`b2IlP6R4otKj&MA0W}k? zwa^v0RD5UJDc8BK29B38^3Xot1iM#}CLi05DA`XNMiB`+;1id?TT!E*f@8oK>?Z!_ zKXz&&d=TA;Fb*$ss$hQI@gG&kZXV9D_oC__(9XC;u;o@UpnAN+(wiu<*&MQLr^x!{ zf=lvnW>5K+hIGWVP==|80{|wS3FP++zw5zs1H5L1lUj1N(sF^S`sF{f2bQTztDrLY z?oIGU-T9x>2LvOkM8Ph2p;TYEG&zbm3?@Ig(fJT6K7GKZQ`UI~p?T7ii$Lt(&W00a zkX5VijGSY9G@7M%2L=Y!{6tF+j|hSa#&H+U_tl-_g=!(pR{6OEB*HD_|IOX;|NEEF z<%fhnw1t;*VD}5EPDD{8?0vo$vH#-kC(gASH9S`(!r_DVWXw7!+}uLU5w;fY{PS8c zx_|rn?E{g2S!8p!hMu^*J#0f(_PIOobPnYXg>-%mNKom=@qQq-{b!`#f8#-*f!q;h zw{a^T@}8C|)7%U{fc1ZG8mYf8cX&>F`^dIv`n>O1r+=TB{`P@}O^iby+^MeK9K4&C z+N?6XHHF#{Wtyb_?*Sfs{5}Wx_ymD^lz&3=`%G^lc3EDQap{Z7jHY^JFWu;|5Ap~+{B7R#@Fto5 z)S#DHE^}TtDe~=NBqYQ_nCqGfq1nWf~n#2VX4gdL5drCJ)?^VgY0cA zb;clbBR1jjbXp!Qt?dOdUAM-z!Y4QEFf8U%4I&1)F4ij;xX1g{OpXLpwdL^O>NP!VMZ4XD2&*WX1^73bz6Uqp68iSfso| zx_ah!sKJMYjMz&{A~Z?9RMk~sPA}UPSGe)K3}>@ows=n$)#mBXnmxfAgfIFXf~cpO zBzARyogRmP(<@_HaXn36?nPaD*mW6q|7wrEe$W{&i-33bzqEy>rR$Y=BjR@auT`Q8 z;74@=d6QYU*xKYW{)kwsswx`^SE)m-K%?9#bKU^F%^Oc3ix+YFP&3f}YaRD_|9rmJ zUvqrpQfRMK4$m7%qwkA)hCRT9$%`c~MZSx5lhX;rGAwllr>cJ--cHE7R$NEBHADW_ z&S;8>Mhrv*Q30V|VE2(`+@dXh>bP)OM9Tus$F zGm|rH*q%!1%Hjut`r_QhhC_Y10lCS1^HL+)j_10FgwS!qcRf11)#nFbEU;_ zfHxcm^QJdaAyc`Pm^EZ2&rMS4g$wo!!thFc91ZYhUsw9WBT$0Tx`9MdROz&_$%o_* z$t@&DeKF5D`_A)aSLL3Jz~_;a!oX{8xIF-~Svu@~97d@?p}hU}Jkw|rr{AaCwR|dK zY{#Gj%RD$jg$8-aI7?0o#Y+(b7-f%h>R*+FJ9C;{O+|veJq{TowzwX-P}TR>J9yAf z3(=)W6Si`QY;l@&d@Y356rU=dF&X2L0T3IA%PHKE>&fejoSi>V{_bTiI<&#d;ZKj9 zncuIh{{E}=@8Rkbo#YAQmn#;Bp)mOYpsP(koUs)$Ty|D6prl>k?GEXBnwKIQ{Fo1n zH0PKYa)$n*vCj0;55-=KuWkvgO}3}t9j|mTuTiOP=;B=IDwQ!!(+60*RUCA5U`%?l zkIA*;Y6p|5D0TVF^-#vCrssdyTXY0QO9o>9Smpb(^qIXHU$w+ZMdjFG%P3W<}V3IOShDIt0Fu^KsGCctDuMWqi+1ihKVmmwpT*(~Q+Aa6Q zY(s61HP6`SO7s3BnWgp!#T?`-fO8^yKYa9dA4Pol1jWm)Pk8U{3m|;JCog<|n^5xo zuC1TQr?|@}IqyK`_^0}v>RkfN2zp(R(golp!iMDO!o5(oJPS@%?oiq3zDoZ7GWQ|~ zBUU-}RdY8-|MQ^_<&{CuHs9N3dgiZ;iup$NicxRq?>Zt`O8$6P8e3a{rXQ~BnX{iE zq9E&*vAsOWC&9OiPgBLiJ8svS|6S9*{Ne&Puvy&;{pG{1CfrF_QN0G@*d-&|r}zng zoUmbxz6WS;{edur)ZH2rj%tUR20u;NGTLIRIuRlzhd`c-7Mjzwh2N1$AqlhCM)oEwC>auUg~jhPFFP6O17 zElCO_a#}Mm*EtpD@R3&O)q@`vo6o46EUOGtx;{%}XXeTIL2LS6$DAs+UzBex6Kf&j zoZ1uIUkcR)Ml_b(_hGSgy8PigDD22H3FV?7&uccet@mee;>=+hEgEMaq5C|c!DD1gAIjqs(8s~=yq*it z>2i`YqgGZ?fLXSq#I`h~4#y-*xEMoPixzqfbXC>jG2rks#UW^$S0XYhL)=ALK0pB4 z#f2KMR|VfUcPW~nMjL(~aSx`R88fmK;cd&O60R5desl+^O4TWkci{2su7?q|M>lay zV@JQBCch594ac4yE3?2z$z0`-1dA|VPop_w>SXkXte`015w z6CYjnYFry5C*Ba~kOS%(Iw!$E+DJPC!IEp-FDG4HFC6NnU2Kz_1{Ar>Pp=#91qDUK z{w}6OfB5zicN2^irLx@k)Kyar4((~mku{PD@NjW?bMbe=c-vrBMx%x5dUFUcYXf1eu-moakch_eg^F$4O3u^CPoR@TEt($FphFhe zwBMex&u6fxkFlF%f?_Agc5zKF^c1UlMji(}s__pTMZ^}OpnPf-9cC@E9@AZ6AfSbK zD;N#f!nub}sT7s-Ra*w(nS2>S<1^6jK|`Y*Wu&<5%A8)(-R6YwZLoCfh=st|DS&<| zF_x_*15r(&soW`%9xv6e!QV8WLHlH%lE3gRWbyYYmU{`Z6%=Xhi{G_gm5tQ?;S!qm^I{QF z4T_P^FpZVRGDIevoAxXCmcrfai4tDo+-Gk5_XW6DgX<)5fwe3*o!IJIyKU$I`j&&M zC)XP>#o1c-lov=LP(Hj~gXn?Dj8hMkYXMgBLY0MR?@V59I{iG>nxa+%5^fFmhXCw! zrJutv6xE#L%uZj(>VeKqse)N$?-G(1R`)xgt-PM`?<26}vnxgOFswmTt1~64?IQ_| z=%#>6YhIn466F_UMvnx4fv4xxz&ecCNV=5_l)X9^55~$n54Mc79X*~qz9{V9QaG0A zJcCScxO$zVBqzzcu4AzJ59m(a@F3Wcmdn>niu$-!Ks z!w0CU78aGhpvnteyx?%x^i+_pke+;2o8cv_yMz5R{iAhb{QtB*bVPec!Jrfb*Zju6 zLbmeGsFnuab^BQzI7Sh`;Iv0}6_312+*f}a=`vqvTKUuIkH~ZPw-sznxNEorp8H+E zYsRPKD5UFuBMcD&3kPLab05N5#Jiu`O>Fzz-2lZ4@&r;V+-V!-+@LrBlj5-A+(881 zWIxUyaWzuB9{zSb-RQcx8;&Ie*%?arawz23APzZ`cbtu@jk|{{tAz7i@Ar!UC(Slg zav^2xntyUXSNuVo_5thTsUH&e1@XOI1pC5}pF7}4#)3QqY7ud#za&+WhTr^;_P)d) z%C`M`Bq`gFt%y;QWUFkY$wVPZw(Q1`WSOQRWH5%Z6G|~5RJJTbWldwmSSm@j!N@YB zvNKbbE5_XK)%`rb=YF31_q>0>`(B@qnYljZJg#$_^El7r_#WRQt-=|YvPFhiB9*Dm zkJ9Xz#-j1bgBr zDy+_UHLeOShiNe#vjT&eKbz5CYo1Em&T(Lw)IJ@hN-o@-3DbSiyoc;jj`E?%5G|t} z2X1_g+fdCh&nXW*b2|R~7LfoM!QB~Z&z62`AwS_*%a+ez=Eyc_IlOYj1UK&j>MyV_ z5d*yWnmR`qNa=PN5n_NG*}6iv-?9CAZ>+5(BwV^Rjn5acox}GOuLT6MrfolSBpDgx zcgaaSW2Y-KN=)W`i+y`teAlec`eKCqcxIYe_i)kN zn9*g<-eD_#&45aDGb?-cIBe&5B7ZFBOfqyWBNZuY&+3BTZsd_YqQal~(-76T!qbLF z*Mp2^c*PqN(m}?oiTEJol~L=LY@PMA1vvCjVuhPC3P;d;$-Xe>e36dnC@(>WW!~2I zpD>}P#F0Xa^}8geI^Ie}GC))w$AXp9p&Kb&D=T+)vObP%%CL<4>}#MTB_ox>=#iRr z-jP;1EVuj9cXeg!+aT-g%-V(v$_1%Q+$R#W7S*G5g8%W%xCpSn0v#zqs#sA!)uCTk z@B~L}X%?+9UryYJOzMdt>o8AWVy?FnWVju#X`mU3v7@gR>DF5^xH5xTX}Ct|!_XN* z^y@|tA=zdjLXSGD`O<*Kgry}f66pBZE`^Y|3XFQneJ`DoGdFEuA-9+u8<6d!$<&&{ z`XUbK&xw&P{+zj$KWt-y!H{Dh^Q#RM!BK$9NQ++`g+hJl%Xcc^S{POjqiDUYThQ{w z?dwHoOTIaMQ|d@94pS?4;X^pK8s~XA?LxzwB=liszt?f+Cked6+N2O9N)lH))T&pp zEFB-xp`$8#Wz-iZ`rz}gsPv;JI!|^(kTe4&L&kiQxaH77(3SwW3N}Xd;ZJ&1;Hsz_ zUK0sA_B_Okz3NprNZ$v8w^dZAE$n7~jpP5&BEi$z!WWyC>|Y0`ldV|9qm!Gym^=xWQcxU z*@-6Y5jf};N@~b1N#sd*5bC0^5&KFknN%5t3heP zvmoX#XU%-)p``GJ#XjbDrtcYePn#AV%0{&I@Bxw5^81n}*RleOaaz<{bno^EFj~lj z98~V`S&b|l66iq!In$mEpY>LXp-8{UX5Ub%!F{jx^}sxl(j*a}u6VEB8=9n`I-uwo z(#dTmA6f*I6sbC)b@L?iE&GGtSjKrfx&#j`;$Z>$PJX4&1c4wY86U6BV;WE7hN3tT zlj>MIc2g%c0k6)q@OBx*;EkuE8DM;&1B#-5uQzByz;S$Twit!%@=j51U6VmRZ*XLe z7Lx-Yvj&qQ)h*fI-$=*6)%UrHHDzmqG^&Y52P)2FI9#gRcBUjl#K4{O^YAH`?>nO4 z%`FBn!222gGP|RBazb##lC83v15_E;u)pV)jREIyQ&!b%jn@YWlHA?~6u(|-ZG=9x zP5;Y1-;DsaZh`lXqL8)HXHL&~@6rtRadrb9EaKZ{VYpeL`K0DHoEB=JlCulM@-Tk@ zA+G&+Ly-Hn)iS)a^1)OD3Rz1V|5GbUC#h?wGY1c5TI^Wcc-s-QiW}g)0Dck1J3YkR zZK)g!?iH+(jaaFB-C3{;RlFZZ;dPSeR zH=`#VefgD-%;d$lGWz^+T=Dj)<^-9d)Z4yHn6%3b{d>xkh4^J4&4cO1LdA2i!BVf8 zr&Y+uBFfziCv%nCiBh`sIFe7MesEo7omAf^rPN-5s6e_@3TvH;;3X(_vEohR?O4r; zL8txDJ(9z?A3dG+>z0K;7($pnT1nASx2{yfpDdcS&(_T^YPt2| z5yi1|qjCs7?HOJM==5Nu0fz+L@N$%#_KE5{K8=X>Ei=63c) z*Rh&6f>mMhT9aSKHOL;ev`C^M8cO6`n3uTF6XQr<)5ry2vz1tcr&M47g0>< zM7SAyW4?{M2k>COv3c+|PkX46uxG|i9r#s=Kf3k!I#&wtG^WANx^q>UScIJLKz3J~ z%-t?Dqlve*Swcs(M{x9Qqj#*f?7Y87*ZHk{#AE@87{gm`9(TkCHGlzH3>YuRg{65n zn3ul|v17K;0Q3L~{Epd?Up;*jl^k|r0B=@>8|qj`Y+nY+T881$8uyu+;*r--GX!M| zhqe;y2R3AO6#r`!p(Rp0(wo7GW|%I7GO_yrG(#>Mm!z2>uQfmp@h;_9_dNlRTK3$J z;JG_-M?7;vobIQ;a@2x_2EAfZr0Z8+5xuIZS28z)JNmHhkZ;Xi$q3*uh{UM@BL9%P%WYcwu?&8$jt&hHonDIk@} zY|6c!C$nobd7a+8b@PVw^|Q1yh#Sv&?>B&^?w_VBpfJ<6$c<1i`6aG%QIdfWMF(;Y zg3;iU%0Oue$AC?HQwh2vzkrDeiax#ZtmJ5b(2qN6m5T_*VRAnQ5vZF{j>~IbdNNQ& zA~(rT+ci~h+CTO7Eg6e4XHhg0n}y&fH?{EcAZ5w;k$#fFZe#F>4O-X4!6!@1TFr1F zY|SV*jB!f%NQZ^2?GN%<=5umjnOOyWwlOtpTZ+22LnF-wu_zd11*~gq5!PTw{1W<3ex%qv*Vf=J^X(5`kkpH z@+F;yl|TuC5^F_t#-ZP5-64ple;nZLs7DD=wD$vAQ&{2V4rt;ArJ8{f!b#fzXC_1m z60;9D2Uu9@I{S1ZP-6Sr_dG}E)-xhSC&oI9=VTbwFW5K7y0GDq8YNg!{wE_GVHy^G zYV+`n%ycYS6%)c*HIPHYq;!x+3=fSi$K-9#=ZY?i_^cCq%_`=?FePojf-G)zFuyaL zRbj#(H3ZF{WBj3oE0Mos$)KCY6%YDE3ms~Ben^86v(cU7r`eukfI~|Ft^*;BR~#^q z@|F40SefCTzmseo3VOr2N@+~Kwy@l>TE>gizE*W-^L)Y12&PyCpiEs07_QMPukDd*CpsGsr3Pz?OpNt_JP-rBZ}rzCM+(eP3GgE^ z{F0~;H&Fn|7JMr&vz4$iUlk)$pA5HPmAC6}O@sMziu~juAW)g3RmnjB)eN0vhc^Qt z;h)Z@s)$lxiW)YQ6x7T|?`Aw&R;#T7Oi5Q>yzJE;IdgibHCs6$sES_2EJ=6@SeMV_ zLBZocEY4XRZ=5>S5-@A9pKTefGm*GaSricB>BZa&cTh|BC1`yP>QbHG65ji*AFFVW z>Wf96{>1OUTQK+p*Y zquC%!5_4<@bzX+i?CYe&ftwME%pJ`U5zn1b&K6#!kXtaBnyR~z`w0BpKA1>NGv7G= zD0{o}*hCCL&W}jh&l+zAnd^2qx_}PSH*DeD8kN)e@z?P_M0sTvfi!ISQQv7`w&levMK-S@>ByP4Ek0 zAVfdEji=OSNRSN&F^&CRV+|@d%mVG$`&Bl}g#kwr^roNm))p#pbj?Aaftw2ya=~ z9$4V29d^1+UKKI&)?!UHy5PL=aF!1*m7quXNZ3CJH)aKbr(*sGZF&3p;U|kY!mP|v zCdjSw3UHx<0844Mss)>tg26R!I&cjTtWL@)!#aKVxjS*yNUMtAPSrC+-2`G|a45dqQY7@%h{XT)Z9e>>KtD zve!VcZ)GLqcUqx$7>X2d3XIR>Z&S4tnkOi+<#Skcgk*{oDrrI#u2c-hWQ6S*n6BBp zkyARS+jvlX=QpvO)7zM`k(nnd)-ZIQ$v|8=wHkCwoMY4CS!q_Zl^%NZCBPy?Il6+2 zz&kx)+TUs39Yj)g9a@dxH;hwF(L%9^t@+S7khVdOEnixJ^Xof(;FIHk^Te3%JycZ0 zgEGzm06Y16lQf^nLa+52mZNe_!Y5>adHXnZT_}j*;Vv1XBbjoBylr*p!y8T4Mjw;qx$r$E>S$SVcZhp@^~pYf!WZS$|`*xWk?tPugH@A2e@~g3(mLr>M zWxcgc-i+%6_-!}>JGp4HY|f@+O;v3NSa{$!?VPiC&-b`* zSQI~+RjDb!xdeE!mYL_AHHr#Nr$EOIVB6taWX43^TwG~q8^n5&gilxYZGee7A~Bl? zdivq?sji=y+76dNqJp4&dK!aJ#7v`?`Bbc6EE$~(V=T%hQ^+~>He1$e5bnW*0Y<^F z#74cgx`CR*I-w3!x_y2X=X7H){G|GK4IRywc@^M3Sso<4!!V|NPdVhz6H_ zHsY&a^gX|DPA2uKZ;9KO<1Cm8V&xk5hoG-lUG?rrpWL{)tLJ$q7bhO?yAow!1UOAu z%HYocrpzXDJJw=+tbq<-(?e~XNFa+<;vA-QqH&gIhk}wLPywvi=A_j~aomp|jth8e z?(7H&rXPQ zti2{xyT#k-{BcV`DVHWLu@BuZ1-4zQX&kCmN5YZCbJ@f@OF>;ts%>;vTObmZ_l0*3 zDl7;tDk;t41R3-=tY00EVB~Md>#*yiS3$T*-qA*yj;!Y1IWR!5M*RXzY;>#}isu1Et#8W4NkzQH?RQOWL~syq?*f{W_9D zEoX!liGe>)s+qY%bAy**u{&}qqQW{mNs(_sdOI=PD3d}e zmGMv5*A?Epe$}^XK8kk84!6*< zeto{81oCSX1)}*+LGNUvz)%5>{!nli65HmioUnp1f~Dk%gY2dHNVjGw59O{SbObG|R z&4bp~Wlk{-o-)C-MeOn0m2>eO`q+e^`7HP@Xf$5AYBrOwW9WL-4Mfe?!KLW|5teY)HjF3%>;h6#&gYJ;E2|jSKBN{+iwQY4nl&jxd)_m1 z4J=2dnK$mUsBM~4(3-iDi*GFVy7}48ZycD_rSVfUZ&~}w z>?#BLTfi-bepjo^El|D4pn#>#PCBW!J{FE(Y+2fqF^ZO~^+fH&B^{H7+B)mCT%%LL zwVRiQiyM5z&cMr^*qUi%L zg6~Vdu$qC^Odf<~H-L~*WNWr9%WkD)0PenQe+sCY zu=$hWmgS(XwFb`ud-S5nvISsx!+IDEj6W;4&ZZ4ne%3x^j#O;jP+s$n=4c6iq2o|S zeQG7?V^Ibfpe5%W0FH;z#N9|1%oyC@bVEG4Hk|=6j+sXVc$%m&L_eLQdv>_@a=vGS zW=!M8#LtoFg&)1zvzbP&y3+|qUT9qAeGDS9=O?|}Ee>=UgPi1Cg>e_(?EJNkjF19! zh@03@P_9|cn7K*bvKd=12JZO;NH$MjKS$Gv5Vw*clwWU5O)2+twwvqm2oJy>-hsw@ zY~?mH4uQ~%83Q@osO2D-@gk&+up97}N-KArp};_Q65Ot6##!TK5h5liZ4aooUF*3Y zS+r!|!hErrMlwat+$2)ueNk6P*g9mVfd;pGfrR9~0R8@(38E&o8Vs~8{-&(;|QBY%S_XqR3sFS0Xa)fSOdEo&L zzxQO%U0tsHP;f&nXu#XURRSisyP;xZEd_MomY}8>@Rnnam7d=aGLU=GU$c{=Q;x1D zz>wk~<3LMsL~6(QcF5oWm?G#SJuQK($Mhvg;~Ht;DBf}t2Xns2!K{d9SS>GE!kmq& zC`@f6-%Osy3s!srlOa zFjN?u)Xp3z>ccG8{L(?fkPnR5>Z!?0kfpDkyZ3=BYc00IoRKE!GH(DQ+VoW{74|!y zyD}*q$q3a=Lw8UVfq7w~o z(kuZ6+94X7SX-}#XLcGK>|&oLNAAdd=A=^Huk8ajlS)HlPOqqX)>{u)eBQ1%erzi< zSXh}V4{HE?*^>CvjPo}19x9D;lr5Qho8*#$%jBz1 zEF4^QDc|h2TlzLot9XlNa2W3gK#MsRG=e4_=fG?QmQlT+85HVQUk%K+t!E2&Bo{Vu z=x({NJDLUxJ(K8D5&Bd1gOv-$#CY{_+NS-W=F^}z1K4Yid8@#U@uKe}@`$jB3K_wC zFZ0ulwtDWEVWH@YIcG4TN5|%B&;iG(hibP&6#Q?!(bVQ?N8#PJa&_?7Nu6g%QspyyNG7MrUf3c76(1Wf1Sp)}T6q`@dTgE^Mjlr!$0o6mq|< z3%l+KUJ1LE!D!lhy{2kMK6F+Fxs^rJej})U<@>T#BV;OA*k$d~z#?7+8_e3A+U5!d ze0PKuM_11N0g)sem>E|?dNN@nrgv+*T{>j++E2kGfHdUL{+hT?7<8L6rL>ej+kw%v zY^?6TQHj~d+gC|A$=O9=XU0!;o3`YO)mn-IZnRU8!on_X`f=q?aDI0~SH5-(dJ7NofYvXI*z71WawmkKbF~|`L2=zC`dWfFSpqu*dg6nO%;KWT> zYw?9WjAg0!23du^G;uQtnUhIo7&XQn(}cPgm7d;rUt#Sqg*U9s1bEtTAaG$}nE{nW z=Zk`=tCl-xZb#SD@ z31Pd{d-|5+Zr7?C(N$w1B@Ap5su~+jk#ORO_7e8tmQZn0$HrTv<|})P-cHH+dVI7GP@auG3!h z!?n+Y1##-k1fFsb>g!`E4sx;1vPL_7NkEqcTb@|)3cc|#?CMdV&9|BL$PE{6XenD6 z&k#nprxncV$t!_jpeu{wNE!&zb6GUCdfjB-;J)(-h)MCJ%0qzLp!Wl3+qqWHg-6?g zCyEJ4Al{mt_lATXYLu(IjeZWqw-Yo#5+t&9DJeAr1RU9ABmJa(OMLZ%i}Oobgh^y8 zFrVs(l{xQr3CIq}P6!0DAM!lF4Xe!$f#k?RK!7j=g1fHi>Em%TDDWR|$2D-6>kCd} z*il{4NZ5-%TEu^7E9j~uKD#=gvRhg`sTghL9X{N3#=M4Pyjv&fQzv&r4sq4&QU)J# zvu6AG12&yg?4=OI{Z5Cf<*q9?ySyGG`!N_QKMs*E7-u?+#;(t=j`k1dXeZh2RXx`( zJ7jTH-~OmDMYa)i$^W?4SnWPYyTzJY8Om6Ecm?GJcM)*9EgSyBOCO;rL6m&%oOGe(`i~I58wBx1Q;=<9YV+?iGBpq{X4R)iIf8^4cH27Ma z{5573>~f{R4f&;2R94BGYKQ9-sS#>MOz8;OXW)X%RhinQ(yBr(k=^aBsC6nRix8@$ ztbbK-SyV&U!Fy<$2&Cm)_+kf0-nDw6rW?-_rp>`j$MJhzR2hyQR^^58WNqtqyH|S| zeR5PafFz5>wMh1aU700o#OMONF)*_3sD$A@$<&*_*?+br-K*^SIUZm1-k# z1#-;)6n|HLXxaZ6dWj_`vYV{rjZZxjW^gcRk)|GIiWTRs3$(J^Mo-6}WTORo6KEy%UJc+pJ*u zx)j|CjSHeCDao4rf{Jn^`C)ypD2m3>KU7?OE-+6N6GVXonX5rB@cT|`r(C(i5ml7g z{Uq8T;nb{dg3kqUBkDWL1Nuk4#EDx>Jvw*TtW}{f=wh&}qqfD{FA8n@_qRM>(rtTk zYX7la+hqE#UTzfDJ>MS{v;Q94upqO>gMU_ZVNK;x>if@2%8+3h_3C?-Hu z&fD44VA0e>T(;v8kRW>e!gY+O&P(g00}=-=aQ1&aH74iKdvNWx`JKa|A`a~yM$Znj zrV@5|Hio+z`%9eT+3)jsB+OOv;E6N0(;^Tu{bN%{SUW`m_VLsU7d5Lm{JOQ?KlQsl z4ttv;?)_t%8pZhIhTD%l71Dozua4nhxe?# z9GwDnYT0`v>DYqhJK#pKV)@}Vh556D4%6@ijoDF6k$pT2xOCqh>hg?JnPT~Hr*+J> zJ<%qKFBHp9+!bwki#a24Hfcs}cCmchiGpALL9zMAW>YJ!T-?cLe)t~nC@8IBazQ3q z@Yv(x_`W|9D_(U4_s$3yR*Q!a@m=K$yvsxV3po>y%6GnQEzfj2zAC7SJpF2@nfW7m z%fYp{@vGkv^V7eQx5AJtJ8lR{Qf`juB2?;o;%4HDf& zZe;BJf*md*E?Dlb`nmF5@!@__&Xd;p@o$6dH+5>I=1sH03c%!tq=|C02mjn$Sm4r! z7dym}lTSa9CT>deAP;kM&GoG6clfB%+CyKGuA|Bd2cb>*x;b(6tBzlfA`{a#jlL1< z`5bA3i0vxQ@%T{Bu+1 z1i&OgW(g~4CClYcn#6x#Nz0>SLU_m7HyRmwqSJrypWD3nbNjjOa>2@_6Co|A(YQ4P zyirlkpGkq43hT!$AHLC6YG{|&2WdI^u@X=(rD_Tp}pY^wx>5iUHZo#ypaFY zvg4flI0NuMr2npEwf>=HT|g}>K>)SvK9D0!W}bcmW_GlNBx`Ul8w?h|0mUpGar-n9@gkmtJ?o z45{@H)n50$oE2EU>cZ3XdtuQXM7L1&z8Z>gb zx+5d6v=Y>^KL$+|wdfXEp`l9r`d$wh8p!Jv#n@{@)tbKc$~Z`aylamJo0wzsB?H(e zahR2!;?ZQkqd7&z|LI+?li{K+UMz(t{_ex?UuXL5^KenBT%DBcdCl}SRom>`Bv7QSCL%~JULlBaHU%N()-C^70Mwdgd?+2vA6Qb4pU%>Zz&u)$P$6S2RYSR@RdS}T_Uxk*JQST7fNzUzU(JrCO!(s9;8O5=Rrr#?Qdjxu=|_i*Fo^tzdz**R|sz7u!P!f0&~eHI3W zGMy(@wn6XTTQSqi(rM&fU<`NOA5tFsIy{_mM|5DF-uqSNs+q*5^_jCq7OYVljAGwa zWM`U90<7=;Nd44#E|NKKw6k{B3aS=xF!-Has*S$uw`-|4?F!X5_E$QaXL9p01{H~J z4IhrV@&1&qyyIYgwV^C_^rwG@H1(3&k8SQ5CKkG3`0O&k;}lMg+k zWGE54wa|al?u?OU5*}JHTU+?8?9B4_reVeV6J3YZ9ey3#bzfS1j&E~tsL#^eo*-&^ zusC3QWJI6bs{?tK(Zl@J(05$3_esNBmhlx|K3cyzZnkmkm9xF3t4_p-LrOCmB`I6! z*SiLHmE0~bd|>u%hk|8zZ_PK0Liz zeXYyx#eAX>Y;(q4uRq$0|pht{5rgRC&pjZy*Kl$wU(Y%cg;7-6ek(0L z4z6Mwn)c{J_dd@fR}2CO4@>(vvE^N|ymCsJF%+5ExQwDqC zrd`65q+Pc)&kS@Ks5`U_p7)9;z4gE24<`8NnovhtGegCSk8S@RwJS2Ivaid_ZC=W-NetAt-CZkk z%XI?_xji3sVqI13&3m#o9!OT69mzuZ|LXpwsv$lW!v|k-ZglQxzxDd#uLGNOJHAVc z7puognmUFGmg!eNE=@GbPpBA5cPp^l17OOd>U9!Y+UO7_=8^ACxh;D_RFF zr?p?p|6NTbDcIPa;=O(;(DbN|`n%ITzqRe+Tv3Gafpy55&G`bk6Y^B;S5u?Zt*1-%Ls~#fq(K4)tFbfRc1 zx;_K7Z8glkJX=rQ>Fa0vr1eo(FJk>kN80<7XTst&pWnuABY}z=VH&lgd*q{2+^3JU zZF&7pVf(^DmATlfnR9;6EdsX=%kbMgf6vlpJ+0=yF)yyR2OGmFTRlDI)bb|QV9Uly zIFuWCrlw2VRKf2C(m%NKwK=y>B#6TU5kdLahV*#=NG*pOmAAb56*dr`>=%wSxuLfn z55hitX;O9FPkntUm?z#qZ}npaE!$4YGkXqYXgmOesJ~6;&***Jc=@>MAc#l$de!Zs z?5D| zYF&o#XbUyCed&@@$sgPPo4y^geSGvD4+J913xSA2cJf@sdRpDY`Uh%y`1}9XwF=L+ z^BjHx0l)G8_Vqa30y}zCC~lc|4JI@udlGp}=yt`k^QTr`T;WN-y`SjJngo^tM zLuqyQJ4SBNQ(&5I2G5?~faYq3y_>o6yzQoS(zZJ(wSt=$;L8-Z2r<6&UA63EXOvQ- znD&vJC%PvOz55CgtlR0Bn0c5~cy83l+rMS;ZSJA(pF~SSH9h-J2(I^1f<@1}5x;rw z;=f~cHX>tOxczIx+-#%;nD4{@KO!g2iw-8HhtNcuZ4f7O6g%RQls%D85-@E47n2!} zyCec{v{1ZEO_4`VS`N}=plJE0vQuIY;nD+&k31q|r;hs#_LuRSACsOTu(wqiv-=f< z+%sk@ZXFWk6?vty*E9d#E3Vj2)jCMbg;(xJQW>tN(#BHUQn!g{#74JlZ%r|8%T+d}6WsPxp z@bo+E#A*-U>bsnegriRNhZde1_;POud9#j>HM)(feXvyeW4@yJ>#wp^EI1AS_pXs@ zY*1za&d~sHj*I>KEcV3S^!oqP_^+St-E<_jRbfx;GI0T+{l($J{KtcsZUg4v#mt#k zULo7vG8_-{a5mNpNVhb?UYehnjyN$b{OjwJG9P~0duQncq1_U##}<-!j|8@;)W5}Jx=Q5w z-AsPgX5^5r=ypn9seYGq5+QgBbwRYJQ=t|bB@>*5FLpp6;(zt|KR>yg#oh?=x)FrB9O~~Ci2OY(t<3*ZK*Yz(dBUK8 zF>o3S{)d1baCt`E^tv9Xsqy>u?*;E>w%_;(7H9+u%KS$`Vel*kS}OlhHUxVUeFcj} z|91}E{SP^3cKs>m-zEIL65hZSsG~d0h9us`00V{_hh0Zg2QY!ZynPlJKYX;qMaua|iWTc?jfY`@c2h spZlr5m;O)9_3x!mfWM`Gb;JMYF)MREaB=yq+aVD0hu?Sq2Lz^acmMzZ literal 0 HcmV?d00001 diff --git a/examples/study_score_distributions/tal_gata/TAL-GATA simulation score distributions.ipynb.REMOVED.git-id b/examples/study_score_distributions/tal_gata/TAL-GATA simulation score distributions.ipynb.REMOVED.git-id index 184a6fd..287114e 100644 --- a/examples/study_score_distributions/tal_gata/TAL-GATA simulation score distributions.ipynb.REMOVED.git-id +++ b/examples/study_score_distributions/tal_gata/TAL-GATA simulation score distributions.ipynb.REMOVED.git-id @@ -1 +1 @@ -9f1412b9f201b59efb7ac09c23707d948decaaab \ No newline at end of file +b56af922f89fc65faedabdb77562ddd639826c30 \ No newline at end of file diff --git a/tutorial/DeepLIFT tutorial.ipynb b/tutorial/DeepLIFT tutorial.ipynb new file mode 100644 index 0000000..286dcb3 --- /dev/null +++ b/tutorial/DeepLIFT tutorial.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 0 +} From 04d58bfb0a32cbfc9969754cd26307061ddff3cf Mon Sep 17 00:00:00 2001 From: Avanti Shrikumar Date: Mon, 24 Oct 2016 08:21:34 -0700 Subject: [PATCH 02/19] continuing to explore the talgata case Former-commit-id: 0f4fc608b36de5547a4f904925477f960c1787a9 [formerly c9f9afc6e1211ac3ef0132b7fbbb93952cd0940a] Former-commit-id: b2a83325b2cc4eb857f976e6f8442ce3385acab5 --- deeplift/blobs/activations.py | 5 +- deeplift/blobs/core.py | 30 +++- ...00 Using Larger Model.ipynb.REMOVED.git-id | 1 + ...TA sleuth example 500.ipynb.REMOVED.git-id | 1 + .../TAL-GATA tutorial.ipynb.REMOVED.git-id | 1 + ...model_khP5H_modelWeights.h5.REMOVED.git-id | 1 + .../record_7_model_khP5H_modelYaml.yaml | 155 ++++++++++++++++++ ...t smoothening windows on KS statistic.xlsx | Bin 0 -> 171 bytes 8 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 examples/study_score_distributions/tal_gata/TAL-GATA sleuth example 500 Using Larger Model.ipynb.REMOVED.git-id create mode 100644 examples/study_score_distributions/tal_gata/TAL-GATA sleuth example 500.ipynb.REMOVED.git-id create mode 100644 examples/study_score_distributions/tal_gata/TAL-GATA tutorial.ipynb.REMOVED.git-id create mode 100644 examples/study_score_distributions/tal_gata/record_7_model_khP5H_modelWeights.h5.REMOVED.git-id create mode 100644 examples/study_score_distributions/tal_gata/record_7_model_khP5H_modelYaml.yaml create mode 100644 examples/study_score_distributions/tal_gata/~$Effect of different smoothening windows on KS statistic.xlsx diff --git a/deeplift/blobs/activations.py b/deeplift/blobs/activations.py index 1e994b3..d955d70 100644 --- a/deeplift/blobs/activations.py +++ b/deeplift/blobs/activations.py @@ -69,8 +69,9 @@ def _get_mxts_increments_for_inputs(self): else: #all the other ones here are of the form: # scale_factor*self.get_mxts() - if (self.mxts_mode == MxtsMode.DeepLIFT - or self.mxts_mode==MxtsMode.PosThroughDenseDeepLIFT): + if (self.mxts_mode==MxtsMode.DeepLIFT + or self.mxts_mode==MxtsMode.PosThroughDenseDeepLIFT + or self.mxts_mode==MxtsMode.CounterBalanceDenseDeepLIFT): scale_factor = self._deeplift_get_scale_factor() elif (self.mxts_mode == MxtsMode.GuidedBackpropDeepLIFT): deeplift_scale_factor = self._deeplift_get_scale_factor() diff --git a/deeplift/blobs/core.py b/deeplift/blobs/core.py index 6f5e027..e3f7394 100644 --- a/deeplift/blobs/core.py +++ b/deeplift/blobs/core.py @@ -19,7 +19,10 @@ GuidedBackprop="GuidedBackprop", GuidedBackpropDeepLIFT=\ "GuidedBackpropDeepLIFT", - PosThroughDenseDeepLIFT="PosThroughDenseDeepLIFT") + PosThroughDenseDeepLIFT=\ + "PosThroughDenseDeepLIFT", + CounterBalanceDenseDeepLIFT=\ + "CounterBalanceDenseDeepLIFT") ActivationNames = deeplift.util.enum(sigmoid="sigmoid", hard_sigmoid="hard_sigmoid", tanh="tanh", @@ -484,6 +487,31 @@ def _build_activation_vars(self, input_act_vars): def _get_mxts_increments_for_inputs(self): if (self.mxts_mode == MxtsMode.PosThroughDenseDeepLIFT): return B.dot(self.get_mxts()*(self.get_mxts()>0.0),self.W.T) + elif (self.mxts_mode == MxtsMode.CounterBalanceDenseDeepLIFT): + #self.W has dims input x output + #fwd_contribs has dims batch x output x input + fwd_contribs = self._get_input_activation_vars()[:,None,:]\ + *self.W.T[None,:,:] + #total_pos_contribs and total_neg_contribs have dim batch x output + total_pos_contribs = B.sum(fwd_contribs*(fwd_contribs>0), axis=-1) + total_neg_contribs = B.abs(B.sum(fwd_contribs*(fwd_contribs<0), + axis=-1)) + #if output diff-from-def is positive but there are some neg + #contribs, temper positive by some portion of the neg + #to_distribute has dims batch x output + to_distribute = B.minimum(total_neg_contribs,total_pos_contribs)\ + *(1.0-(B.minimum(total_neg_contribs,total_pos_contribs)/ + pseudocount_near_zero(B.maximum(total_neg_contribs,total_pos_contribs)))) + #total_pos_contribs_new has dims batch x output + total_pos_contribs_new = total_pos_contribs - to_distribute + total_neg_contribs_new = total_neg_contribs - to_distribute + #positive_rescale has dims batch x output + positive_rescale = total_pos_contribs_new/pseudocount_near_zero(total_pos_contribs) + negative_rescale = total_neg_contribs_new/pseudocount_near_zero(total_neg_contribs) + #new_Wt has dims batch x output x input + new_Wt = self.W.T[None,:,:]*(fwd_contribs>0)*positive_rescale[:,:,None] + new_Wt += self.W.T[None,:,:]*(fwd_contribs<0)*negative_rescale[:,:,None] + return B.sum(self.get_mxts()[:,:,None]*new_Wt[:,:,:],axis=1) else: return B.dot(self.get_mxts(),self.W.T) diff --git a/examples/study_score_distributions/tal_gata/TAL-GATA sleuth example 500 Using Larger Model.ipynb.REMOVED.git-id b/examples/study_score_distributions/tal_gata/TAL-GATA sleuth example 500 Using Larger Model.ipynb.REMOVED.git-id new file mode 100644 index 0000000..c9acb43 --- /dev/null +++ b/examples/study_score_distributions/tal_gata/TAL-GATA sleuth example 500 Using Larger Model.ipynb.REMOVED.git-id @@ -0,0 +1 @@ +f184ec2efbb66e138e4899c5837532560df610a4 \ No newline at end of file diff --git a/examples/study_score_distributions/tal_gata/TAL-GATA sleuth example 500.ipynb.REMOVED.git-id b/examples/study_score_distributions/tal_gata/TAL-GATA sleuth example 500.ipynb.REMOVED.git-id new file mode 100644 index 0000000..22de699 --- /dev/null +++ b/examples/study_score_distributions/tal_gata/TAL-GATA sleuth example 500.ipynb.REMOVED.git-id @@ -0,0 +1 @@ +3c581908b7bfdf8d0ff42124e6edfef92b54d43c \ No newline at end of file diff --git a/examples/study_score_distributions/tal_gata/TAL-GATA tutorial.ipynb.REMOVED.git-id b/examples/study_score_distributions/tal_gata/TAL-GATA tutorial.ipynb.REMOVED.git-id new file mode 100644 index 0000000..2979abb --- /dev/null +++ b/examples/study_score_distributions/tal_gata/TAL-GATA tutorial.ipynb.REMOVED.git-id @@ -0,0 +1 @@ +72fd394241c363b42a9be3d21889787a03ee95e3 \ No newline at end of file diff --git a/examples/study_score_distributions/tal_gata/record_7_model_khP5H_modelWeights.h5.REMOVED.git-id b/examples/study_score_distributions/tal_gata/record_7_model_khP5H_modelWeights.h5.REMOVED.git-id new file mode 100644 index 0000000..b894472 --- /dev/null +++ b/examples/study_score_distributions/tal_gata/record_7_model_khP5H_modelWeights.h5.REMOVED.git-id @@ -0,0 +1 @@ +6f0db47c76d87f258fe75c1b0e3d4f616b6dff45 \ No newline at end of file diff --git a/examples/study_score_distributions/tal_gata/record_7_model_khP5H_modelYaml.yaml b/examples/study_score_distributions/tal_gata/record_7_model_khP5H_modelYaml.yaml new file mode 100644 index 0000000..9014b30 --- /dev/null +++ b/examples/study_score_distributions/tal_gata/record_7_model_khP5H_modelYaml.yaml @@ -0,0 +1,155 @@ +input_config: +- dtype: float + input_shape: [1, 4, 200] + name: sequence +input_order: [sequence] +loss: {output: binary_crossentropy} +name: Graph +node_config: +- concat_axis: -1 + create_output: false + dot_axes: -1 + input: sequence + inputs: &id001 [] + merge_mode: concat + name: conv1 +- concat_axis: -1 + create_output: false + dot_axes: -1 + input: conv1 + inputs: *id001 + merge_mode: concat + name: conv1_act +- concat_axis: -1 + create_output: false + dot_axes: -1 + input: conv1_act + inputs: *id001 + merge_mode: concat + name: conv2 +- concat_axis: -1 + create_output: false + dot_axes: -1 + input: conv2 + inputs: *id001 + merge_mode: concat + name: conv2_act +- concat_axis: -1 + create_output: false + dot_axes: -1 + input: conv2 + inputs: *id001 + merge_mode: concat + name: max_pool +- concat_axis: -1 + create_output: false + dot_axes: -1 + input: max_pool + inputs: *id001 + merge_mode: concat + name: flatten +- concat_axis: -1 + create_output: false + dot_axes: -1 + input: flatten + inputs: *id001 + merge_mode: concat + name: dense1 +- concat_axis: -1 + create_output: false + dot_axes: -1 + input: dense1 + inputs: *id001 + merge_mode: concat + name: dense1_act +- concat_axis: -1 + create_output: false + dot_axes: -1 + input: dense1_act + inputs: *id001 + merge_mode: concat + name: output_preact +- concat_axis: -1 + create_output: false + dot_axes: -1 + input: output_preact + inputs: *id001 + merge_mode: concat + name: output_act +nodes: + conv1: + W_constraint: null + W_learning_rate_multiplier: null + W_regularizer: null + activation: linear + activity_regularizer: null + b_constraint: null + b_learning_rate_multiplier: null + b_regularizer: null + border_mode: valid + cache_enabled: true + custom_name: conv1 + dim_ordering: th + init: glorot_uniform + name: Convolution2D + nb_col: 11 + nb_filter: 51 + nb_row: 4 + subsample: &id002 !!python/tuple [1, 1] + trainable: true + conv1_act: {activation: relu, cache_enabled: true, custom_name: conv1_act, name: Activation, + trainable: true} + conv2: + W_constraint: null + W_learning_rate_multiplier: null + W_regularizer: null + activation: linear + activity_regularizer: null + b_constraint: null + b_learning_rate_multiplier: null + b_regularizer: null + border_mode: valid + cache_enabled: true + custom_name: conv2 + dim_ordering: th + init: glorot_uniform + name: Convolution2D + nb_col: 11 + nb_filter: 49 + nb_row: 1 + subsample: *id002 + trainable: true + conv2_act: {activation: relu, cache_enabled: true, custom_name: conv2_act, name: Activation, + trainable: true} + dense1: {W_constraint: null, W_learning_rate_multiplier: null, W_regularizer: null, + activation: linear, activity_regularizer: null, b_constraint: null, b_learning_rate_multiplier: null, + b_regularizer: null, cache_enabled: true, custom_name: dense1, init: glorot_uniform, + input_dim: null, name: Dense, output_dim: 5, trainable: true} + dense1_act: {activation: relu, cache_enabled: true, custom_name: dense1_act, name: Activation, + trainable: true} + flatten: {cache_enabled: true, custom_name: flatten, name: Flatten, trainable: true} + max_pool: + border_mode: valid + cache_enabled: true + custom_name: max_pool + dim_ordering: th + name: AveragePooling2D + pool_size: !!python/tuple [1, 180] + strides: !!python/tuple [1, 1] + trainable: true + output_act: {activation: sigmoid, cache_enabled: true, custom_name: output_act, + name: Activation, trainable: true} + output_preact: {W_constraint: null, W_learning_rate_multiplier: null, W_regularizer: null, + activation: linear, activity_regularizer: null, b_constraint: null, b_learning_rate_multiplier: null, + b_regularizer: null, cache_enabled: true, custom_name: output_preact, init: glorot_uniform, + input_dim: null, name: Dense, output_dim: 3, trainable: true} +optimizer: {beta_1: 0.8999999761581421, beta_2: 0.9990000128746033, epsilon: 1.0e-08, + lr: 0.0010000000474974513, name: Adam} +output_config: +- concat_axis: -1 + dot_axes: -1 + input: output_act + inputs: [] + merge_mode: concat + name: output +output_order: [output] diff --git a/examples/study_score_distributions/tal_gata/~$Effect of different smoothening windows on KS statistic.xlsx b/examples/study_score_distributions/tal_gata/~$Effect of different smoothening windows on KS statistic.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..0fec4a672bdd8ff0ea208f10ea1b6592c68ac844 GIT binary patch literal 171 zcmWe|EKAHQ$y5l=D9X$(%}p#)APNXDI5LzmBr@bNlrUs6C@=&wWH1x~S=kJw47ot@ PBA^)cV2%UF)cczN%EuV( literal 0 HcmV?d00001 From c28068fed4cb93cf158342e360fb02d45ad12173 Mon Sep 17 00:00:00 2001 From: Avanti Shrikumar Date: Mon, 24 Oct 2016 08:28:41 -0700 Subject: [PATCH 03/19] deleted the thing that wasn't a tutorial Former-commit-id: 32cc2c0575f8d92ded69f69fd87c001f5617e7ee [formerly c441c9715fe5af4367224aee900bb3b061413e39] Former-commit-id: 373a2b2df76c3c9eaf9f13895f5526960f816674 --- tutorial/DeepLIFT tutorial.ipynb | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 tutorial/DeepLIFT tutorial.ipynb diff --git a/tutorial/DeepLIFT tutorial.ipynb b/tutorial/DeepLIFT tutorial.ipynb deleted file mode 100644 index 286dcb3..0000000 --- a/tutorial/DeepLIFT tutorial.ipynb +++ /dev/null @@ -1,6 +0,0 @@ -{ - "cells": [], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 0 -} From ac5de6591d59848890c792470bee4b62087cf05c Mon Sep 17 00:00:00 2001 From: AvantiShri Date: Tue, 25 Oct 2016 14:03:55 -0700 Subject: [PATCH 04/19] misc updates and added a cross corr func Former-commit-id: 2ddcf2e84dc7e12859efcf587fe40b700cf7df60 [formerly 2f716fd27b27b5edf8b55747b66958f38ac2eeb5] Former-commit-id: bfa9da497d7b13adc091a4bfc9ebbb5b992d08a8 --- deeplift/blobs/core.py | 9 ++++--- deeplift/util.py | 33 +++++++++++++++++++++++++- deeplift/visualization/viz_sequence.py | 2 +- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/deeplift/blobs/core.py b/deeplift/blobs/core.py index e3f7394..b730c94 100644 --- a/deeplift/blobs/core.py +++ b/deeplift/blobs/core.py @@ -499,9 +499,12 @@ def _get_mxts_increments_for_inputs(self): #if output diff-from-def is positive but there are some neg #contribs, temper positive by some portion of the neg #to_distribute has dims batch x output - to_distribute = B.minimum(total_neg_contribs,total_pos_contribs)\ - *(1.0-(B.minimum(total_neg_contribs,total_pos_contribs)/ - pseudocount_near_zero(B.maximum(total_neg_contribs,total_pos_contribs)))) + to_distribute =\ + B.maximum( + (total_neg_contribs*(total_neg_contribs < total_pos_contribs) + - B.maximum(self._get_default_activation_vars(),0)),0.0)\ + *(1.0-((total_neg_contribs)/ + pseudocount_near_zero(total_pos_contribs))) #total_pos_contribs_new has dims batch x output total_pos_contribs_new = total_pos_contribs - to_distribute total_neg_contribs_new = total_neg_contribs - to_distribute diff --git a/deeplift/util.py b/deeplift/util.py index 57710d5..b3697e5 100644 --- a/deeplift/util.py +++ b/deeplift/util.py @@ -244,6 +244,37 @@ def format_json_dump(json_data, indent=2): return json.dumps(jsonData, indent=indent, separators=(',', ': ')) +def get_cross_corr_function(filters): + from deeplift import backend as B + + if (len(filters.shape)==3): + filters = filters[:,None,:,:] + assert filters.shape[1]==1 #input channels=1 + assert filters.shape[2]==4 #acgt + + #set up the convolution. Note that convolutions reverse things + filters = np.array(filters[:,:,::-1,::-1]).astype("float32") + input_var = B.tensor_with_dims(num_dims=4, name="input") + conv_out = B.conv2d(inp=input_var, + filters=filters, + border_mode="valid", + subsample=(1,1)) + compiled_func = B.function(inputs=[input_var], outputs=conv_out) + + def cross_corr(regions_to_scan, batch_size, progress_update=None): + assert len(regions_to_scan.shape)==4 + assert regions_to_scan.shape[1]==1 #input channels=1 + assert regions_to_scan.shape[2]==4 #acgt + #run function in batches + conv_results = np.array(deeplift.util.run_function_in_batches( + func=compiled_func, + input_data_list=[regions_to_scan], + batch_size=batch_size, + progress_update=progress_update)) + return conv_results + return cross_corr + + def get_smoothen_function(window_size): """ Returns a function for smoothening inputs with a window @@ -289,7 +320,7 @@ def get_smoothen_function(window_size): averaged_padded_inp = averaged_padded_inp[:,0,0,:] smoothen_func = B.function([inp_tensor], averaged_padded_inp) - def smoothen(inp, batch_size, progress_update): + def smoothen(inp, batch_size, progress_update=None): return run_function_in_batches( func=smoothen_func, input_data_list=[inp], diff --git a/deeplift/visualization/viz_sequence.py b/deeplift/visualization/viz_sequence.py index 910826a..20b22f6 100644 --- a/deeplift/visualization/viz_sequence.py +++ b/deeplift/visualization/viz_sequence.py @@ -99,7 +99,7 @@ def plot_weights_given_ax(ax, array, #the highlight dict should be the color for color in highlight: for start_pos, end_pos in highlight[color]: - assert start_pos > 0.0 and end_pos <= array.shape[1] + assert start_pos >= 0.0 and end_pos <= array.shape[1] min_depth = np.min(depths_at_positions[start_pos:end_pos]) max_height = np.max(heights_at_positions[start_pos:end_pos]) ax.add_patch( From 0942c322183b77a4a200063244608c8c82d9c208 Mon Sep 17 00:00:00 2001 From: Avanti Shrikumar Date: Tue, 25 Oct 2016 14:04:43 -0700 Subject: [PATCH 05/19] added a no padding option to smoothing Former-commit-id: a67dadb4b45c44f8dac00e1313fe6a46445cd9f2 [formerly 45255f244bfa9455c51c9eb1f8ef3a8dbaf39008] Former-commit-id: af645446ca27886e28680fab811a77f15ab2f513 --- deeplift/util.py | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/deeplift/util.py b/deeplift/util.py index 57710d5..bb9b6ea 100644 --- a/deeplift/util.py +++ b/deeplift/util.py @@ -244,7 +244,7 @@ def format_json_dump(json_data, indent=2): return json.dumps(jsonData, indent=indent, separators=(',', ': ')) -def get_smoothen_function(window_size): +def get_smoothen_function(window_size, same_size_return=True): """ Returns a function for smoothening inputs with a window of size window_size. @@ -255,25 +255,29 @@ def get_smoothen_function(window_size): from deeplift import backend as B inp_tensor = B.tensor_with_dims(2, "inp_tensor") - #do padding so that the output will have the same size as the input - #remember, the output will have length of input length - (window_size-1) - #so, we're going to pad with int(window_size/2), and for even window_size - #we will trim off the value from the front of the output later on - padding = int(window_size/2) - new_dims = [inp_tensor.shape[0], inp_tensor.shape[1]+2*padding] - padded_inp = B.zeros(new_dims) - #fill the middle region with the original input - padded_inp = B.set_subtensor( - padded_inp[:,padding:(inp_tensor.shape[1]+padding)], - inp_tensor) - #duplicate the left end for padding - padded_inp = B.set_subtensor(padded_inp[:,0:padding], - inp_tensor[:,0:padding]) - #duplicate the right end for padding - padded_inp = B.set_subtensor( - padded_inp[:,(inp_tensor.shape[1]+padding):], - inp_tensor[:,(inp_tensor.shape[1]-padding):]) - padded_inp = padded_inp[:,None,None,:] + if (same_size_return): + #do padding so that the output will have the same size as the input + #remember, the output will have length of input length - (window_size-1) + #so, we're going to pad with int(window_size/2), and for even window_size + #we will trim off the value from the front of the output later on + padding = int(window_size/2) + new_dims = [inp_tensor.shape[0], inp_tensor.shape[1]+2*padding] + padded_inp = B.zeros(new_dims) + #fill the middle region with the original input + padded_inp = B.set_subtensor( + padded_inp[:,padding:(inp_tensor.shape[1]+padding)], + inp_tensor) + #duplicate the left end for padding + padded_inp = B.set_subtensor(padded_inp[:,0:padding], + inp_tensor[:,0:padding]) + #duplicate the right end for padding + padded_inp = B.set_subtensor( + padded_inp[:,(inp_tensor.shape[1]+padding):], + inp_tensor[:,(inp_tensor.shape[1]-padding):]) + padded_inp = padded_inp[:,None,None,:] + else: + padded_inp = inp + averaged_padded_inp = B.pool2d( inp=padded_inp, pool_size=(1,window_size), @@ -284,8 +288,9 @@ def get_smoothen_function(window_size): #if window_size is even, then we have an extra value in the output, #so kick off the value from the front - if (window_size%2==0): + if (window_size%2==0 and same_size_return): averaged_padded_inp = averaged_padded_inp[:,:,:,1:] + averaged_padded_inp = averaged_padded_inp[:,0,0,:] smoothen_func = B.function([inp_tensor], averaged_padded_inp) From 524824bb6569b5a79f5f1dd5b2d1f9f738d320f2 Mon Sep 17 00:00:00 2001 From: AvantiShri Date: Tue, 25 Oct 2016 14:23:01 -0700 Subject: [PATCH 06/19] bugfixes Former-commit-id: 2562fc150d8f567b31fb855168a0d2c6dee1224d [formerly 9a4cec0ab354f9e98eef97446a1c1b2fa884f8ab] Former-commit-id: cb52ba3c667396ffe30858fd2efece5926c2b6ca --- deeplift/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deeplift/util.py b/deeplift/util.py index eebf689..69e047a 100644 --- a/deeplift/util.py +++ b/deeplift/util.py @@ -305,9 +305,9 @@ def get_smoothen_function(window_size, same_size_return=True): padded_inp = B.set_subtensor( padded_inp[:,(inp_tensor.shape[1]+padding):], inp_tensor[:,(inp_tensor.shape[1]-padding):]) - padded_inp = padded_inp[:,None,None,:] else: - padded_inp = inp + padded_inp = inp_tensor + padded_inp = padded_inp[:,None,None,:] averaged_padded_inp = B.pool2d( inp=padded_inp, From fa8164d0d1b5588190fa31ad5e3e0c764ab11e87 Mon Sep 17 00:00:00 2001 From: AvantiShri Date: Tue, 25 Oct 2016 14:54:20 -0700 Subject: [PATCH 07/19] added a topN scores function Former-commit-id: e1febf5fa6777f6e880473fb45eef5807cc22284 [formerly 840c28c10b9e6baf1941e9fe5a8a01260df262b9] Former-commit-id: e4781f122937b7b64db987e30c26611e28b99845 --- deeplift/util.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/deeplift/util.py b/deeplift/util.py index 69e047a..4cec794 100644 --- a/deeplift/util.py +++ b/deeplift/util.py @@ -333,3 +333,26 @@ def smoothen(inp, batch_size, progress_update=None): progress_update=progress_update) return smoothen + + +def get_top_N_scores_per_region( + scores, N, exclude_hits_within_window): + scores = scores.copy() + assert len(scores.shape)==2, scores.shape + if (N==1): + return np.max(scores, axis=1)[:,None] + else: + top_n_scores = [] + top_n_indices = [] + for i in range(scores.shape[0]): + top_n_scores_for_region=[] + top_n_indices_for_region=[] + for n in range(N): + max_idx = np.argmax(scores[i]) + top_n_scores_for_region.append(scores[i][max_idx]) + top_n_indices_for_region.append(max_idx) + scores[i][max_idx-exclude_hits_within_window: + max_idx+exclude_hits_within_window-1] = -np.inf + top_n_scores.append(top_n_scores_for_region) + top_n_indices.append(top_n_indices_for_region) + return np.array(top_n_scores), np.array(top_n_indices) From 1ed1b8b5c0150943a481bd082e13e50f51436317 Mon Sep 17 00:00:00 2001 From: Avanti Shrikumar Date: Sun, 30 Oct 2016 13:25:20 -0400 Subject: [PATCH 08/19] refactor for dense mxts in progress Former-commit-id: ad60fc3f3fbf20a44925874bacebceb6f7a2d635 [formerly 2ebe87a65f8af01c1ed68cc87de788926ab8e0b4] Former-commit-id: 036071d5509aebf196e31198818281f8efe16660 --- deeplift/backend/theano_backend.py | 2 +- deeplift/blobs/activations.py | 24 +++---- deeplift/blobs/core.py | 46 ++++++------ deeplift/conversion/keras_conversion.py | 67 +++++++++++------- ...t smoothening windows on KS statistic.xlsx | Bin 53061 -> 53072 bytes ...t smoothening windows on KS statistic.xlsx | Bin 171 -> 0 bytes tests/blobs/test_activation.py | 15 ++-- tests/blobs/test_batchnorm.py | 8 ++- tests/blobs/test_concat.py | 12 ++-- tests/blobs/test_conv2d.py | 20 +++--- tests/blobs/test_dense.py | 4 +- tests/blobs/test_maxmerge.py | 12 ++-- tests/blobs/test_maxout.py | 7 +- tests/blobs/test_pooling.py | 15 ++-- tests/conversion/test_convolutional_model.py | 2 +- tests/conversion/test_load_batchnorm.py | 10 ++- 16 files changed, 138 insertions(+), 106 deletions(-) delete mode 100644 examples/study_score_distributions/tal_gata/~$Effect of different smoothening windows on KS statistic.xlsx diff --git a/deeplift/backend/theano_backend.py b/deeplift/backend/theano_backend.py index 87a0a8b..4c4d6bb 100644 --- a/deeplift/backend/theano_backend.py +++ b/deeplift/backend/theano_backend.py @@ -62,7 +62,7 @@ def sum(x, axis): def ones_like(x): - return T.ones_like(x) + return T.ones_like(x, dtype=theano.config.floatX) def zeros_like(x): diff --git a/deeplift/blobs/activations.py b/deeplift/blobs/activations.py index d955d70..3395986 100644 --- a/deeplift/blobs/activations.py +++ b/deeplift/blobs/activations.py @@ -12,15 +12,14 @@ class Activation(SingleInputMixin, OneDimOutputMixin, Node): #if you tried to call its functions for a layer that was #not actually one dimensional) - def __init__(self, mxts_mode, - **kwargs): - self.mxts_mode = mxts_mode + def __init__(self, nonlinear_mxts_mode, **kwargs): + self.nonlinear_mxts_mode = nonlinear_mxts_mode super(Activation, self).__init__(**kwargs) def get_yaml_compatible_object_kwargs(self): kwargs_dict = super(Activation, self).\ get_yaml_compatible_object_kwargs() - kwargs_dict['mxts_mode'] = self.mxts_mode + kwargs_dict['nonlinear_mxts_mode'] = self.nonlinear_mxts_mode return kwargs_dict def _compute_shape(self, input_shape): @@ -63,27 +62,26 @@ def _gradients_get_scale_factor(self): self._get_input_activation_vars()) def _get_mxts_increments_for_inputs(self): - if (self.mxts_mode == MxtsMode.DeconvNet): + if (self.nonlinear_mxts_mode==NonlinearMxtsMode.DeconvNet): #apply the given nonlinearity in reverse mxts = self._build_activation_vars(self.get_mxts()) else: #all the other ones here are of the form: # scale_factor*self.get_mxts() - if (self.mxts_mode==MxtsMode.DeepLIFT - or self.mxts_mode==MxtsMode.PosThroughDenseDeepLIFT - or self.mxts_mode==MxtsMode.CounterBalanceDenseDeepLIFT): + if (self.nonlinear_mxts_mode==NonlinearMxtsMode.DeepLIFT): scale_factor = self._deeplift_get_scale_factor() - elif (self.mxts_mode == MxtsMode.GuidedBackpropDeepLIFT): + elif (self.nonlinear_mxts_mode== + NonlinearMxtsMode.GuidedBackpropDeepLIFT): deeplift_scale_factor = self._deeplift_get_scale_factor() scale_factor = deeplift_scale_factor*(self.get_mxts() > 0) - elif (self.mxts_mode == MxtsMode.Gradient): + elif (self.nonlinear_mxts_mode==NonlinearMxtsMode.Gradient): scale_factor = self._gradients_get_scale_factor() - elif (self.mxts_mode == MxtsMode.GuidedBackprop): + elif (self.nonlinear_mxts_mode==NonlinearMxtsMode.GuidedBackprop): scale_factor = self._gradients_get_scale_factor()\ *(self.get_mxts() > 0) else: - raise RuntimeError("Unsupported mxts_mode: " - +str(self.mxts_mode)) + raise RuntimeError("Unsupported nonlinear_mxts_mode: " + +str(self.nonlinear_mxts_mode)) orig_mxts = scale_factor*self.get_mxts() return orig_mxts return mxts diff --git a/deeplift/blobs/core.py b/deeplift/blobs/core.py index b730c94..f2a203a 100644 --- a/deeplift/blobs/core.py +++ b/deeplift/blobs/core.py @@ -14,15 +14,16 @@ ScoringMode = deeplift.util.enum(OneAndZeros="OneAndZeros", SoftmaxPreActivation="SoftmaxPreActivation") -MxtsMode = deeplift.util.enum(Gradient="Gradient", DeepLIFT="DeepLIFT", - DeconvNet="DeconvNet", - GuidedBackprop="GuidedBackprop", - GuidedBackpropDeepLIFT=\ - "GuidedBackpropDeepLIFT", - PosThroughDenseDeepLIFT=\ - "PosThroughDenseDeepLIFT", - CounterBalanceDenseDeepLIFT=\ - "CounterBalanceDenseDeepLIFT") +NonlinearMxtsMode = deeplift.util.enum( + Gradient="Gradient", + DeepLIFT="DeepLIFT", + DeconvNet="DeconvNet", + GuidedBackprop="GuidedBackprop", + GuidedBackpropDeepLIFT="GuidedBackpropDeepLIFT") +DenseMxtsMode = deeplift.util.enum( + Linear="Linear", + PosOnly="PosOnly", + Counterbalance="Counterbalance") ActivationNames = deeplift.util.enum(sigmoid="sigmoid", hard_sigmoid="hard_sigmoid", tanh="tanh", @@ -214,20 +215,20 @@ def _build_fwd_pass_vars(self): self._mxts = B.zeros_like(self.get_activation_vars()) -class Input_FixedDefault(Input): +class Input_FixedReference(Input): - def __init__(self, default=0.0, **kwargs): - super(Input_FixedDefault, self).__init__(**kwargs) - self.default = default + def __init__(self, reference=0.0, **kwargs): + super(Input_FixedReference, self).__init__(**kwargs) + self.reference = reference def get_yaml_compatible_object_kwargs(self): - kwargs_dict = super(Input_FixedDefault, self).\ + kwargs_dict = super(Input_FixedReference, self).\ get_yaml_compatible_object_kwargs() - kwargs_dict['default'] = self.default + kwargs_dict['reference'] = self.reference return kwargs_dict def _build_default_activation_vars(self): - return B.ones_like(self._activation_vars)*self.default + return B.ones_like(self._activation_vars)*self.reference class Node(Blob): @@ -465,11 +466,11 @@ def _get_mxts_increments_for_inputs(self): class Dense(SingleInputMixin, OneDimOutputMixin, Node): - def __init__(self, W, b, mxts_mode, **kwargs): + def __init__(self, W, b, dense_mxts_mode, **kwargs): super(Dense, self).__init__(**kwargs) self.W = W self.b = b - self.mxts_mode = mxts_mode + self.dense_mxts_mode = dense_mxts_mode def get_yaml_compatible_object_kwargs(self): kwargs_dict = super(Dense, self).\ @@ -485,9 +486,9 @@ def _build_activation_vars(self, input_act_vars): return B.dot(input_act_vars, self.W) + self.b def _get_mxts_increments_for_inputs(self): - if (self.mxts_mode == MxtsMode.PosThroughDenseDeepLIFT): + if (self.dense_mxts_mode == DenseMxtsMode.PosOnly): return B.dot(self.get_mxts()*(self.get_mxts()>0.0),self.W.T) - elif (self.mxts_mode == MxtsMode.CounterBalanceDenseDeepLIFT): + elif (self.dense_mxts_mode == DenseMxtsMode.Counterbalance): #self.W has dims input x output #fwd_contribs has dims batch x output x input fwd_contribs = self._get_input_activation_vars()[:,None,:]\ @@ -515,8 +516,11 @@ def _get_mxts_increments_for_inputs(self): new_Wt = self.W.T[None,:,:]*(fwd_contribs>0)*positive_rescale[:,:,None] new_Wt += self.W.T[None,:,:]*(fwd_contribs<0)*negative_rescale[:,:,None] return B.sum(self.get_mxts()[:,:,None]*new_Wt[:,:,:],axis=1) - else: + elif (self.dense_mxts_mode == DenseMxtsMode.Linear): return B.dot(self.get_mxts(),self.W.T) + else: + raise RuntimeError("Unsupported mxts mode: " + +str(self.dense_mxts_mode)) class BatchNormalization(SingleInputMixin, Node): diff --git a/deeplift/conversion/keras_conversion.py b/deeplift/conversion/keras_conversion.py index 3b70659..eec220e 100644 --- a/deeplift/conversion/keras_conversion.py +++ b/deeplift/conversion/keras_conversion.py @@ -6,7 +6,8 @@ from collections import OrderedDict import deeplift from deeplift import models, blobs -from deeplift.blobs import MxtsMode, MaxPoolDeepLiftMode +from deeplift.blobs import NonlinearMxtsMode,\ + DenseMxtsMode, MaxPoolDeepLiftMode import deeplift.util from deeplift.backend import PoolMode, BorderMode import numpy as np @@ -61,10 +62,11 @@ def batchnorm_conversion(layer, name, verbose, **kwargs): def conv2d_conversion(layer, name, verbose, - mxts_mode, **kwargs): - #mxts_mode only used for activation + nonlinear_mxts_mode, **kwargs): + #nonlinear_mxts_mode only used for activation converted_activation = activation_conversion( - layer, name, verbose, mxts_mode=mxts_mode) + layer, name, verbose, + nonlinear_mxts_mode=nonlinear_mxts_mode) to_return = [blobs.Conv2D( name=("preact_" if len(converted_activation) > 0 else "")+name, @@ -125,17 +127,17 @@ def flatten_conversion(layer, name, verbose, **kwargs): def dense_conversion(layer, name, verbose, - mxts_mode, **kwargs): + dense_mxts_mode, nonlinear_mxts_mode, **kwargs): converted_activation = activation_conversion( layer, name=name, verbose=verbose, - mxts_mode=mxts_mode) + nonlinear_mxts_mode=nonlinear_mxts_mode) to_return = [blobs.Dense( name=("preact_" if len(converted_activation) > 0 else "")+name, verbose=verbose, W=layer.get_weights()[0], b=layer.get_weights()[1], - mxts_mode=mxts_mode)] + dense_mxts_mode=dense_mxts_mode)] to_return.extend(converted_activation) return to_return @@ -144,33 +146,39 @@ def linear_conversion(**kwargs): return [] -def prelu_conversion(layer, name, verbose, mxts_mode, **kwargs): +def prelu_conversion(layer, name, verbose, nonlinear_mxts_mode, **kwargs): return [blobs.PReLU(alpha=layer.get_weights()[0], - name=name, verbose=verbose, mxts_mode=mxts_mode)] + name=name, verbose=verbose, + nonlinear_mxts_mode=nonlinear_mxts_mode)] -def relu_conversion(layer, name, verbose, mxts_mode): - return [blobs.ReLU(name=name, verbose=verbose, mxts_mode=mxts_mode)] +def relu_conversion(layer, name, verbose, nonlinear_mxts_mode): + return [blobs.ReLU(name=name, verbose=verbose, + nonlinear_mxts_mode=nonlinear_mxts_mode)] -def sigmoid_conversion(layer, name, verbose, mxts_mode): +def sigmoid_conversion(layer, name, verbose, nonlinear_mxts_mode): return [blobs.Sigmoid(name=name, verbose=verbose, - mxts_mode=mxts_mode)] + nonlinear_mxts_mode=nonlinear_mxts_mode)] -def softmax_conversion(layer, name, verbose, mxts_mode): - return [blobs.Softmax(name=name, verbose=verbose, mxts_mode=mxts_mode)] +def softmax_conversion(layer, name, verbose, + nonlinear_mxts_mode): + return [blobs.Softmax(name=name, verbose=verbose, + nonlinear_mxts_mode=nonlinear_mxts_mode)] -def activation_conversion(layer, name, verbose, mxts_mode, **kwargs): +def activation_conversion(layer, name, verbose, nonlinear_mxts_mode, **kwargs): activation = layer.get_config()[KerasKeys.activation] return activation_to_conversion_function[activation]( layer=layer, name=name, verbose=verbose, - mxts_mode=mxts_mode) + nonlinear_mxts_mode=nonlinear_mxts_mode) def sequential_container_conversion(layer, name, verbose, - mxts_mode, maxpool_deeplift_mode, + nonlinear_mxts_mode, + dense_mxts_mode, + maxpool_deeplift_mode, converted_layers=None): if (converted_layers is None): converted_layers = [] @@ -185,7 +193,8 @@ def sequential_container_conversion(layer, name, verbose, name=(name_prefix+"-" if name_prefix != "" else "")+str(layer_idx), verbose=verbose, - mxts_mode=mxts_mode, + nonlinear_mxts_mode=nonlinear_mxts_mode, + dense_mxts_mode=dense_mxts_mode, maxpool_deeplift_mode=maxpool_deeplift_mode)) return converted_layers @@ -216,9 +225,10 @@ def sequential_container_conversion(layer, name, verbose, def convert_sequential_model(model, num_dims=None, - mxts_mode=MxtsMode.DeepLIFT, - default=0.0, + nonlinear_mxts_mode=NonlinearMxtsMode.DeepLIFT, + reference=0.0, verbose=True, + dense_mxts_mode=DenseMxtsMode.Linear, maxpool_deeplift_mode=default_maxpool_deeplift_mode): converted_layers = [] if (model.layers[0].input_shape is not None): @@ -233,7 +243,7 @@ def convert_sequential_model(model, num_dims=None, else: input_shape = None converted_layers.append( - blobs.Input_FixedDefault(default=default, + blobs.Input_FixedReference(reference=reference, num_dims=num_dims, shape=input_shape, name="input")) @@ -242,7 +252,8 @@ def convert_sequential_model(model, num_dims=None, #but whatever converted_layers = sequential_container_conversion( layer=model, name="", verbose=verbose, - mxts_mode=mxts_mode, + nonlinear_mxts_mode=nonlinear_mxts_mode, + dense_mxts_mode=dense_mxts_mode, maxpool_deeplift_mode=maxpool_deeplift_mode, converted_layers=converted_layers) deeplift.util.connect_list_of_layers(converted_layers) @@ -251,11 +262,12 @@ def convert_sequential_model(model, num_dims=None, def convert_graph_model(model, - mxts_mode=MxtsMode.DeepLIFT, + nonlinear_mxts_mode=NonlinearMxtsMode.DeepLIFT, verbose=True, + dense_mxts_mode=DenseMxtsMode.Linear, maxpool_deeplift_mode=default_maxpool_deeplift_mode, auto_build_outputs=True, - default=0.0): + reference=0.0): name_to_blob = OrderedDict() keras_layer_to_deeplift_blobs = OrderedDict() keras_non_input_layers = [] @@ -269,7 +281,7 @@ def convert_graph_model(model, assert input_shape[0] is None #for the batch axis deeplift_input_layer =\ blobs.Input_FixedDefault( - default=default, + reference=reference, shape=input_shape, num_dims=None, name=keras_input_layer_name) @@ -285,7 +297,8 @@ def convert_graph_model(model, deeplift_layers = conversion_function( layer=layer, name=layer_name, verbose=verbose, - mxts_mode=mxts_mode, + nonlinear_mxts_mode=nonlinear_mxts_mode, + dense_mxts_mode=dense_mxts_mode, maxpool_deeplift_mode=maxpool_deeplift_mode) deeplift.util.connect_list_of_layers(deeplift_layers) keras_layer_to_deeplift_blobs[id(layer)] = deeplift_layers diff --git a/examples/study_score_distributions/tal_gata/Effect of different smoothening windows on KS statistic.xlsx b/examples/study_score_distributions/tal_gata/Effect of different smoothening windows on KS statistic.xlsx index 37f466e84070369466f79db97a2f2c19b9c53bda..1a9a5a6f405fff98f2d4f2ef865fcd75803eced5 100644 GIT binary patch delta 7505 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 MPLJF^^q&s@57l2C!2kdN diff --git a/examples/study_score_distributions/tal_gata/~$Effect of different smoothening windows on KS statistic.xlsx b/examples/study_score_distributions/tal_gata/~$Effect of different smoothening windows on KS statistic.xlsx deleted file mode 100644 index 0fec4a672bdd8ff0ea208f10ea1b6592c68ac844..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 171 zcmWe|EKAHQ$y5l=D9X$(%}p#)APNXDI5LzmBr@bNlrUs6C@=&wWH1x~S=kJw47ot@ PBA^)cV2%UF)cczN%EuV( diff --git a/tests/blobs/test_activation.py b/tests/blobs/test_activation.py index 36dcd9f..a988e75 100644 --- a/tests/blobs/test_activation.py +++ b/tests/blobs/test_activation.py @@ -7,21 +7,24 @@ import os import numpy as np import deeplift.blobs as blobs +from deeplift.blobs import DenseMxtsMode import theano class TestActivations(unittest.TestCase): def setUp(self): - self.input_layer = blobs.Input_FixedDefault( - default=0.0, + self.input_layer = blobs.Input_FixedReference( + reference=0.0, num_dims=None, shape=(None,4)) self.w1 = [1.0, 2.0, 3.0, 4.0] self.w2 = [-1.0, -2.0, -3.0, -4.0] W = np.array([self.w1, self.w2]).T b = np.array([-1.0, 1.0]) - self.dense_layer = blobs.Dense(W=W, b=b) + self.dense_layer = blobs.Dense( + W=W, b=b, + dense_mxts_mode=DenseMxtsMode.Linear) self.dense_layer.set_inputs(self.input_layer) self.inp = [[1.0, 1.0, 1.0, 1.0], [2.0, 2.0, 2.0, 2.0]] @@ -54,7 +57,8 @@ def set_up_prediction_func_and_deeplift_func(self, out_layer): return fprop_results, bprop_results_each_task def test_relu_deeplift(self): - out_layer = blobs.ReLU(mxts_mode=blobs.MxtsMode.DeepLIFT) + out_layer = blobs.ReLU( + nonlinear_mxts_mode=blobs.NonlinearMxtsMode.DeepLIFT) fprop_results, bprop_results_each_task =\ self.set_up_prediction_func_and_deeplift_func(out_layer) self.assertListEqual(fprop_results, @@ -73,7 +77,8 @@ def test_relu_deeplift(self): (-1.0/-20.0)*np.array(self.w2)])) def test_relu_gradient(self): - out_layer = blobs.ReLU(mxts_mode=blobs.MxtsMode.Gradient) + out_layer = blobs.ReLU( + nonlinear_mxts_mode=blobs.NonlinearMxtsMode.Gradient) fprop_results, bprop_results_each_task =\ self.set_up_prediction_func_and_deeplift_func(out_layer) diff --git a/tests/blobs/test_batchnorm.py b/tests/blobs/test_batchnorm.py index 5e93a72..91e0075 100644 --- a/tests/blobs/test_batchnorm.py +++ b/tests/blobs/test_batchnorm.py @@ -7,21 +7,23 @@ import os import numpy as np import deeplift.blobs as blobs +from deeplift.blobs import DenseMxtsMode import theano class TestBatchNormalization(unittest.TestCase): def setUp(self): - self.input_layer = blobs.Input_FixedDefault( - default=0.0, + self.input_layer = blobs.Input_FixedReference( + reference=0.0, num_dims=None, shape=(None,4)) self.w1 = [1.0, 2.0, 3.0, 4.0] self.w2 = [-1.0, -2.0, -3.0, -4.0] W = np.array([self.w1, self.w2]).T b = np.array([-1.0, 1.0]) - self.dense_layer = blobs.Dense(W=W, b=b) + self.dense_layer = blobs.Dense(W=W, b=b, + dense_mxts_mode=DenseMxtsMode.Linear) self.dense_layer.set_inputs(self.input_layer) self.dense_layer.build_fwd_pass_vars() self.dense_layer.set_scoring_mode(blobs.ScoringMode.OneAndZeros) diff --git a/tests/blobs/test_concat.py b/tests/blobs/test_concat.py index 4ed10c5..25dd290 100644 --- a/tests/blobs/test_concat.py +++ b/tests/blobs/test_concat.py @@ -7,25 +7,27 @@ import os import numpy as np import deeplift.blobs as blobs +from deeplift.blobs import DenseMxtsMode import theano class TestConcat(unittest.TestCase): def setUp(self): - self.input_layer1 = blobs.Input_FixedDefault( - default=0.0, + self.input_layer1 = blobs.Input_FixedReference( + reference=0.0, num_dims=None, shape=(None,1,1,1)) - self.input_layer2 = blobs.Input_FixedDefault( - default=0.0, + self.input_layer2 = blobs.Input_FixedReference( + reference=0.0, num_dims=None, shape=(None,1,1,1)) self.concat_layer = blobs.Concat(axis=1) self.concat_layer.set_inputs([self.input_layer1, self.input_layer2]) self.flatten_layer = blobs.Flatten() self.flatten_layer.set_inputs(self.concat_layer) - self.dense_layer = blobs.Dense(W=np.array([([1,2])]).T, b=[1]) + self.dense_layer = blobs.Dense( + W=np.array([([1,2])]).T, b=[1], dense_mxts_mode=DenseMxtsMode.Linear) self.dense_layer.set_inputs(self.flatten_layer) self.dense_layer.build_fwd_pass_vars() diff --git a/tests/blobs/test_conv2d.py b/tests/blobs/test_conv2d.py index 9b4d7ba..eea02b9 100644 --- a/tests/blobs/test_conv2d.py +++ b/tests/blobs/test_conv2d.py @@ -7,6 +7,7 @@ import os import numpy as np import deeplift.blobs as blobs +from deeplift.blobs import DenseMxtsMode import deeplift.backend as B import theano @@ -16,12 +17,12 @@ class TestConv(unittest.TestCase): def setUp(self): #theano convolutional ordering assumed here...would need to #swap axes for tensorflow - self.input_layer = blobs.Input_FixedDefault( - default=0.0, + self.input_layer = blobs.Input_FixedReference( + reference=np.array([0.0,0.0,0.0,0.0])[:,None].astype("float32"), num_dims=None, shape=(None,2,4,4)) - self.w1 = np.arange(8).reshape(2,2,2)[:,::-1,::-1] - self.w2 = -np.arange(8).reshape(2,2,2)[:,::-1,::-1] + self.w1 = np.arange(8).reshape(2,2,2)[:,::-1,::-1].astype("float32") + self.w2 = -np.arange(8).reshape(2,2,2)[:,::-1,::-1].astype("float32") self.conv_W = np.array([self.w1, self.w2]).astype("float32") self.conv_b = np.array([-1.0, 1.0]).astype("float32") @@ -34,10 +35,11 @@ def create_small_net_with_conv_layer(self, conv_layer, self.flatten_layer.set_inputs(self.conv_layer) self.dense_layer = blobs.Dense( - W=np.array([([1]*outputs_per_channel) - +([-1]*outputs_per_channel)]) - .astype("float32").T, - b=np.array([1]).astype("float32")) + W=(np.array([([1.0]*outputs_per_channel) + +([-1.0]*outputs_per_channel)]).T) + .astype("float32"), + b=np.array([1]).astype("float32"), + dense_mxts_mode=DenseMxtsMode.Linear) self.dense_layer.set_inputs(self.flatten_layer) self.dense_layer.build_fwd_pass_vars() @@ -46,7 +48,7 @@ def create_small_net_with_conv_layer(self, conv_layer, self.dense_layer.set_active() self.input_layer.update_mxts() - self.inp = np.arange(64).reshape((2,2,4,4)) + self.inp = np.arange(64).reshape((2,2,4,4)).astype("float32") def test_fprop(self): diff --git a/tests/blobs/test_dense.py b/tests/blobs/test_dense.py index e8770cf..f4c2765 100644 --- a/tests/blobs/test_dense.py +++ b/tests/blobs/test_dense.py @@ -13,8 +13,8 @@ class TestDense(unittest.TestCase): def setUp(self): - self.input_layer = blobs.Input_FixedDefault( - default=0.0, + self.input_layer = blobs.Input_FixedReference( + reference=0.0, num_dims=None, shape=(None,4)) self.w1 = [1.0, 2.0, 3.0, 4.0] diff --git a/tests/blobs/test_maxmerge.py b/tests/blobs/test_maxmerge.py index 74ea901..ff6850c 100644 --- a/tests/blobs/test_maxmerge.py +++ b/tests/blobs/test_maxmerge.py @@ -13,16 +13,16 @@ class TestMaxMerge(unittest.TestCase): def setUp(self): - self.input_layer1 = blobs.Input_FixedDefault( - default=1.0, + self.input_layer1 = blobs.Input_FixedReference( + reference=1.0, num_dims=None, shape=(None,2,1,3)) - self.input_layer2 = blobs.Input_FixedDefault( - default=0.0, + self.input_layer2 = blobs.Input_FixedReference( + reference=0.0, num_dims=None, shape=(None,2,1,3)) - self.input_layer3 = blobs.Input_FixedDefault( - default=-1.0, + self.input_layer3 = blobs.Input_FixedReference( + reference=-1.0, num_dims=None, shape=(None,2,1,3)) self.merge_layer = blobs.MaxMerge(axis=1, temp=1) diff --git a/tests/blobs/test_maxout.py b/tests/blobs/test_maxout.py index c611850..84e38d8 100644 --- a/tests/blobs/test_maxout.py +++ b/tests/blobs/test_maxout.py @@ -13,9 +13,10 @@ class TestMaxout(unittest.TestCase): def setUp(self): - self.input_layer = blobs.Input_FixedDefault(default=-2, - num_dims=None, - shape=(None,2)) + self.input_layer = blobs.Input_FixedReference( + reference=-2, + num_dims=None, + shape=(None,2)) W = np.array([[[-1.0, 0.0], [-1.0, 0.0], [-1.0, 0.0], diff --git a/tests/blobs/test_pooling.py b/tests/blobs/test_pooling.py index 9dcbdab..60a169f 100644 --- a/tests/blobs/test_pooling.py +++ b/tests/blobs/test_pooling.py @@ -7,6 +7,7 @@ import os import numpy as np import deeplift.blobs as blobs +from deeplift.blobs import MxtsMode from deeplift.blobs import MaxPoolDeepLiftMode import deeplift.backend as B import theano @@ -17,7 +18,7 @@ class TestPool(unittest.TestCase): def setUp(self): #theano dimensional ordering assumed here...would need to swap #axes for tensorflow - self.default_inps=np.array([[[ + self.reference_inps=np.array([[[ [0,0,2,3], [0,1,0,0], [0,5,4,0], @@ -44,8 +45,8 @@ def setUp(self): [1,2,5,1], [8,7,6,1], [7,1,9,10]]]]) - self.input_layer = blobs.Input_FixedDefault( - default=self.default_inps, + self.input_layer = blobs.Input_FixedReference( + reference=self.reference_inps, num_dims=None, shape=(None,2,4,4)) @@ -82,8 +83,8 @@ def test_fprop_maxpool(self): func = theano.function([self.input_layer.get_activation_vars()], self.pool_layer.get_activation_vars(), allow_input_downcast=True) - np.testing.assert_almost_equal(func([self.default_inps[0], - self.default_inps[0]-1]), + np.testing.assert_almost_equal(func([self.reference_inps[0], + self.reference_inps[0]-1]), np.array( [[[[1,2,3], [5,5,4], @@ -110,8 +111,8 @@ def test_fprop_avgpool(self): func = theano.function([self.input_layer.get_activation_vars()], self.pool_layer.get_activation_vars(), allow_input_downcast=True) - np.testing.assert_almost_equal(func([self.default_inps[0], - self.default_inps[0]-1]), + np.testing.assert_almost_equal(func([self.reference_inps[0], + self.reference_inps[0]-1]), 0.25*np.array( [[[[ 1, 3, 5], [ 6,10, 4], diff --git a/tests/conversion/test_convolutional_model.py b/tests/conversion/test_convolutional_model.py index a92abc9..111635c 100644 --- a/tests/conversion/test_convolutional_model.py +++ b/tests/conversion/test_convolutional_model.py @@ -8,7 +8,7 @@ import numpy as np from deeplift.conversion import keras_conversion as kc import deeplift.blobs as blobs -from deeplift.blobs import MxtsMode +from deeplift.blobs import NonlinearMxtsMode import theano import keras from keras import models diff --git a/tests/conversion/test_load_batchnorm.py b/tests/conversion/test_load_batchnorm.py index 4c38163..1cd63c5 100644 --- a/tests/conversion/test_load_batchnorm.py +++ b/tests/conversion/test_load_batchnorm.py @@ -8,6 +8,7 @@ import numpy as np from deeplift.conversion import keras_conversion as kc import deeplift.blobs as blobs +from deeplift.blobs import DenseMxtsMode import theano import keras from keras import models @@ -69,8 +70,8 @@ def setUp(self): def prepare_batch_norm_deeplift_model(self, axis): - self.input_layer = blobs.Input_FixedDefault( - default=0.0, + self.input_layer = blobs.Input_FixedReference( + reference=0.0, num_dims=None, shape=(None,2,2,2)) self.batch_norm_layer = blobs.BatchNormalization( @@ -83,7 +84,10 @@ def prepare_batch_norm_deeplift_model(self, axis): self.batch_norm_layer.set_inputs(self.input_layer) self.flatten_layer = blobs.Flatten() self.flatten_layer.set_inputs(self.batch_norm_layer) - self.dense_layer = blobs.Dense(W=np.ones((1,8)).T, b=np.zeros(1)) + self.dense_layer = blobs.Dense( + W=np.ones((1,8)).T, + b=np.zeros(1), + dense_mxts_mode=DenseMxtsMode.Linear) self.dense_layer.set_inputs(self.flatten_layer) self.dense_layer.build_fwd_pass_vars() self.dense_layer.set_scoring_mode(blobs.ScoringMode.OneAndZeros) From 71bb695d4fbcef12a0f698b9992c3793c523ce72 Mon Sep 17 00:00:00 2001 From: Avanti Shrikumar Date: Sun, 30 Oct 2016 14:03:27 -0400 Subject: [PATCH 09/19] tests passing and public example updated Former-commit-id: 534b397550d1e6194df194681d3183e3cfde2f00 [formerly f20642525410add744971b30f7dd8d92feb69d67] Former-commit-id: 45c0b97b4297df9d354d0f1ebfdd89e1869658b3 --- deeplift/backend/theano_backend.py | 9 ++++++--- deeplift/conversion/keras_conversion.py | 2 +- .../tal_gata/TAL-GATA simulation.ipynb.REMOVED.git-id | 2 +- tests/blobs/test_dense.py | 4 +++- tests/blobs/test_maxmerge.py | 4 +++- tests/blobs/test_pooling.py | 5 +++-- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/deeplift/backend/theano_backend.py b/deeplift/backend/theano_backend.py index 4c4d6bb..1ab1558 100644 --- a/deeplift/backend/theano_backend.py +++ b/deeplift/backend/theano_backend.py @@ -132,7 +132,7 @@ def abs(inp): def conv2d(inp, filters, border_mode, subsample): - + inp = T.cast(inp, dtype=theano.config.floatX) if (border_mode==BorderMode.same): #'half' kernel width padding results in outputs of the same #dimensions as input @@ -140,19 +140,22 @@ def conv2d(inp, filters, border_mode, subsample): assert filters.shape[2]%2 == 1 and filter_shape[3]%2 == 1,\ "haven't handled even filter shapes for border mode 'half'" return T.nnet.conv2d(input=inp, - filters=theano.shared(value=filters), + filters=T.cast(theano.shared(value=filters), + dtype=theano.config.floatX), border_mode=border_mode, subsample=subsample, filter_shape=filters.shape) def conv2d_grad(out_grad, conv_in, filters, border_mode, subsample): + out_grad=T.cast(out_grad, dtype=theano.config.floatX) conv_op = T.nnet.conv.ConvOp(output_mode=border_mode, dx=subsample[0], dy=subsample[1]) inverse_conv2d = conv_op.grad( (conv_in, - T.as_tensor_variable(filters)), + T.cast(T.as_tensor_variable(filters), + dtype=theano.config.floatX)), (out_grad,)) #grad returns d_input and d_filters; we just care about #the first diff --git a/deeplift/conversion/keras_conversion.py b/deeplift/conversion/keras_conversion.py index eec220e..2297907 100644 --- a/deeplift/conversion/keras_conversion.py +++ b/deeplift/conversion/keras_conversion.py @@ -280,7 +280,7 @@ def convert_graph_model(model, input_shape = [None]+[x for x in input_shape] assert input_shape[0] is None #for the batch axis deeplift_input_layer =\ - blobs.Input_FixedDefault( + blobs.Input_FixedReference( reference=reference, shape=input_shape, num_dims=None, diff --git a/examples/public/tal_gata/TAL-GATA simulation.ipynb.REMOVED.git-id b/examples/public/tal_gata/TAL-GATA simulation.ipynb.REMOVED.git-id index f504287..14fc7e2 100644 --- a/examples/public/tal_gata/TAL-GATA simulation.ipynb.REMOVED.git-id +++ b/examples/public/tal_gata/TAL-GATA simulation.ipynb.REMOVED.git-id @@ -1 +1 @@ -05d70639ae6f40402a39a0b6e974a6fc4a333c87 \ No newline at end of file +05a12dae678e4ea4bb78ecb769fdf88d1b53032f \ No newline at end of file diff --git a/tests/blobs/test_dense.py b/tests/blobs/test_dense.py index f4c2765..31538de 100644 --- a/tests/blobs/test_dense.py +++ b/tests/blobs/test_dense.py @@ -7,6 +7,7 @@ import os import numpy as np import deeplift.blobs as blobs +from deeplift.blobs import DenseMxtsMode import theano @@ -21,7 +22,8 @@ def setUp(self): self.w2 = [-1.0, -2.0, -3.0, -4.0] W = np.array([self.w1, self.w2]).T b = np.array([-1.0, 1.0]) - self.dense_layer = blobs.Dense(W=W, b=b) + self.dense_layer = blobs.Dense(W=W, b=b, + dense_mxts_mode=DenseMxtsMode.Linear) self.dense_layer.set_inputs(self.input_layer) self.dense_layer.build_fwd_pass_vars() self.dense_layer.set_scoring_mode(blobs.ScoringMode.OneAndZeros) diff --git a/tests/blobs/test_maxmerge.py b/tests/blobs/test_maxmerge.py index ff6850c..8068162 100644 --- a/tests/blobs/test_maxmerge.py +++ b/tests/blobs/test_maxmerge.py @@ -7,6 +7,7 @@ import os import numpy as np import deeplift.blobs as blobs +from deeplift.blobs import DenseMxtsMode import theano @@ -30,7 +31,8 @@ def setUp(self): [self.input_layer1, self.input_layer2, self.input_layer3]) self.flatten_layer = blobs.Flatten() self.flatten_layer.set_inputs(self.merge_layer) - self.dense_layer = blobs.Dense(W=np.array([([1,6])]).T, b=[1]) + self.dense_layer = blobs.Dense(W=np.array([([1,6])]).T, b=[1], + dense_mxts_mode=DenseMxtsMode.Linear) self.dense_layer.set_inputs(self.flatten_layer) self.dense_layer.build_fwd_pass_vars() diff --git a/tests/blobs/test_pooling.py b/tests/blobs/test_pooling.py index 60a169f..e46e93a 100644 --- a/tests/blobs/test_pooling.py +++ b/tests/blobs/test_pooling.py @@ -7,7 +7,7 @@ import os import numpy as np import deeplift.blobs as blobs -from deeplift.blobs import MxtsMode +from deeplift.blobs import DenseMxtsMode from deeplift.blobs import MaxPoolDeepLiftMode import deeplift.backend as B import theano @@ -62,7 +62,8 @@ def create_small_net_with_pool_layer(self, pool_layer, W=np.array([([2]*outputs_per_channel) +([3]*outputs_per_channel)]) .astype("float32").T, - b=np.array([1]).astype("float32")) + b=np.array([1]).astype("float32"), + dense_mxts_mode=DenseMxtsMode.Linear) self.dense_layer.set_inputs(self.flatten_layer) self.dense_layer.build_fwd_pass_vars() From 81aac5178ee029a7b2350fdc88b71f52bacee5fb Mon Sep 17 00:00:00 2001 From: Avanti Shrikumar Date: Sun, 30 Oct 2016 18:46:33 -0400 Subject: [PATCH 10/19] Now the reference is an additional input argument Former-commit-id: 3efc00e68de4166d02a40d46e89e75ce101b636a [formerly 3034f9e4a00c7af88af2d85a92ef79345df0dc49] Former-commit-id: 73e8a5bf0555e376602071fbb792e0cf81218bd0 --- README.md | 5 +- deeplift/backend/theano_backend.py | 4 +- deeplift/blobs/core.py | 19 +------ deeplift/conversion/keras_conversion.py | 16 ++---- deeplift/models.py | 16 ++++-- .../TAL-GATA simulation.ipynb.REMOVED.git-id | 2 +- tests/blobs/test_activation.py | 23 ++++---- tests/blobs/test_batchnorm.py | 52 ------------------- tests/blobs/test_concat.py | 34 ++++++------ tests/blobs/test_conv2d.py | 30 +++++------ tests/blobs/test_dense.py | 25 ++++----- tests/blobs/test_maxmerge.py | 37 +++++++------ tests/blobs/test_maxout.py | 41 +++++++-------- tests/blobs/test_pooling.py | 49 +++++++++-------- tests/conversion/test_load_batchnorm.py | 28 +++++----- 15 files changed, 161 insertions(+), 220 deletions(-) delete mode 100644 tests/blobs/test_batchnorm.py diff --git a/README.md b/README.md index eaccf68..62dbab3 100644 --- a/README.md +++ b/README.md @@ -134,10 +134,11 @@ Here are the steps necessary to implement the backward pass, which is where the 4. Compile the importance score computation function with ```python - deeplift.backend.function([input_layer.get_activation_vars()...], + deeplift.backend.function([input_layer.get_activation_vars()..., + input_layer._get_default_activation_vars()...], blob_to_find_scores_for.get_target_contrib_vars()) ``` - - The first argument represents the inputs to the function and should be a list of one symbolic tensor for each input layer (this was explained under the instructions for compiling the forward pass). + - The first argument represents the inputs to the function and should be a list of one symbolic tensor for the activations of each input layer (as for the forward pass), followed by a list of one symbolic tensor for the references of each input layer - The second argument represents the output of the function. In the example above, it is a single tensor containing the importance scores of a single blob, but it can also be a list of tensors if you wish to compute the scores for multiple blobs at once. - Instead of `get_target_contrib_vars()` which returns the importance scores (in the case of `MxtsMode.DeepLIFT`, these are called "contribution scores"), you can use `get_mxts()` to get the multipliers. 5. Now you are ready to call the function to find the importance scores. diff --git a/deeplift/backend/theano_backend.py b/deeplift/backend/theano_backend.py index 1ab1558..3018cf5 100644 --- a/deeplift/backend/theano_backend.py +++ b/deeplift/backend/theano_backend.py @@ -79,7 +79,9 @@ def set_subtensor(subtensor, amnt): def function(inputs, outputs, **kwargs): return theano.function(inputs, outputs, - allow_input_downcast=True, **kwargs) + allow_input_downcast=True, + on_unused_input='ignore', + **kwargs) def tensor_with_dims(num_dims, name): diff --git a/deeplift/blobs/core.py b/deeplift/blobs/core.py index f2a203a..310dc1c 100644 --- a/deeplift/blobs/core.py +++ b/deeplift/blobs/core.py @@ -201,7 +201,8 @@ def get_activation_vars(self): return self._activation_vars def _build_default_activation_vars(self): - raise NotImplementedError() + return B.tensor_with_dims(self._num_dims, + name="ref_"+str(self.get_name())) def get_yaml_compatible_object_kwargs(self): kwargs_dict = super(Input,self).get_yaml_compatible_object_kwargs() @@ -215,22 +216,6 @@ def _build_fwd_pass_vars(self): self._mxts = B.zeros_like(self.get_activation_vars()) -class Input_FixedReference(Input): - - def __init__(self, reference=0.0, **kwargs): - super(Input_FixedReference, self).__init__(**kwargs) - self.reference = reference - - def get_yaml_compatible_object_kwargs(self): - kwargs_dict = super(Input_FixedReference, self).\ - get_yaml_compatible_object_kwargs() - kwargs_dict['reference'] = self.reference - return kwargs_dict - - def _build_default_activation_vars(self): - return B.ones_like(self._activation_vars)*self.reference - - class Node(Blob): def __init__(self, **kwargs): diff --git a/deeplift/conversion/keras_conversion.py b/deeplift/conversion/keras_conversion.py index 2297907..3717d5e 100644 --- a/deeplift/conversion/keras_conversion.py +++ b/deeplift/conversion/keras_conversion.py @@ -226,7 +226,6 @@ def sequential_container_conversion(layer, name, verbose, def convert_sequential_model(model, num_dims=None, nonlinear_mxts_mode=NonlinearMxtsMode.DeepLIFT, - reference=0.0, verbose=True, dense_mxts_mode=DenseMxtsMode.Linear, maxpool_deeplift_mode=default_maxpool_deeplift_mode): @@ -243,10 +242,7 @@ def convert_sequential_model(model, num_dims=None, else: input_shape = None converted_layers.append( - blobs.Input_FixedReference(reference=reference, - num_dims=num_dims, - shape=input_shape, - name="input")) + blobs.Input(num_dims=num_dims, shape=input_shape, name="input")) #converted_layers is actually mutated to be extended with the #additional layers so the assignment is not strictly necessary, #but whatever @@ -266,8 +262,7 @@ def convert_graph_model(model, verbose=True, dense_mxts_mode=DenseMxtsMode.Linear, maxpool_deeplift_mode=default_maxpool_deeplift_mode, - auto_build_outputs=True, - reference=0.0): + auto_build_outputs=True): name_to_blob = OrderedDict() keras_layer_to_deeplift_blobs = OrderedDict() keras_non_input_layers = [] @@ -280,11 +275,8 @@ def convert_graph_model(model, input_shape = [None]+[x for x in input_shape] assert input_shape[0] is None #for the batch axis deeplift_input_layer =\ - blobs.Input_FixedReference( - reference=reference, - shape=input_shape, - num_dims=None, - name=keras_input_layer_name) + blobs.Input(shape=input_shape, num_dims=None, + name=keras_input_layer_name) name_to_blob[keras_input_layer_name] = deeplift_input_layer keras_layer_to_deeplift_blobs[id(keras_input_layer)] =\ [deeplift_input_layer] diff --git a/deeplift/models.py b/deeplift/models.py index 9117e38..f2f80dd 100644 --- a/deeplift/models.py +++ b/deeplift/models.py @@ -42,9 +42,19 @@ def _get_func(self, find_scores_layer, if (slice_objects is not None): output_symbolic_vars = output_symbolic_vars[slice_objects] core_function = B.function([input_layer.get_activation_vars() + for input_layer in input_layers]+ + [input_layer._get_default_activation_vars() for input_layer in input_layers], - output_symbolic_vars) - def func(task_idx, input_data_list, batch_size, progress_update): + output_symbolic_vars) + def func(task_idx, input_data_list, + batch_size, progress_update, + input_references_list=None): + if (input_references_list is None): + input_references_list = [0.0 for x in input_data_list] + input_references_list = [ + np.ones_like(input_data)*reference + for (input_data, reference) in + zip(input_data_list, input_references_list)] #WARNING: this is not thread-safe. Do not try to #parallelize or you can end up with multiple target_layers #active at once @@ -52,7 +62,7 @@ def func(task_idx, input_data_list, batch_size, progress_update): target_layer.update_task_index(task_idx) to_return = deeplift.util.run_function_in_batches( func = core_function, - input_data_list = input_data_list, + input_data_list = input_data_list+input_references_list, batch_size = batch_size, progress_update = progress_update) target_layer.set_inactive() diff --git a/examples/public/tal_gata/TAL-GATA simulation.ipynb.REMOVED.git-id b/examples/public/tal_gata/TAL-GATA simulation.ipynb.REMOVED.git-id index 14fc7e2..03d0c99 100644 --- a/examples/public/tal_gata/TAL-GATA simulation.ipynb.REMOVED.git-id +++ b/examples/public/tal_gata/TAL-GATA simulation.ipynb.REMOVED.git-id @@ -1 +1 @@ -05a12dae678e4ea4bb78ecb769fdf88d1b53032f \ No newline at end of file +4afb455c130a959e3727903eb2573a2209509703 \ No newline at end of file diff --git a/tests/blobs/test_activation.py b/tests/blobs/test_activation.py index a988e75..c17c1a5 100644 --- a/tests/blobs/test_activation.py +++ b/tests/blobs/test_activation.py @@ -8,16 +8,15 @@ import numpy as np import deeplift.blobs as blobs from deeplift.blobs import DenseMxtsMode +from deeplift import backend as B import theano class TestActivations(unittest.TestCase): def setUp(self): - self.input_layer = blobs.Input_FixedReference( - reference=0.0, - num_dims=None, - shape=(None,4)) + self.input_layer = blobs.Input(num_dims=None, + shape=(None,4)) self.w1 = [1.0, 2.0, 3.0, 4.0] self.w2 = [-1.0, -2.0, -3.0, -4.0] W = np.array([self.w1, self.w2]).T @@ -38,19 +37,19 @@ def set_up_prediction_func_and_deeplift_func(self, out_layer): out_layer.set_active() self.input_layer.update_mxts() - fprop_func = theano.function([self.input_layer.get_activation_vars()], - out_layer.get_activation_vars(), - allow_input_downcast=True) + fprop_func = B.function([self.input_layer.get_activation_vars()], + out_layer.get_activation_vars()) fprop_results = [list(x) for x in fprop_func(self.inp)] - bprop_func = theano.function( - [self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) + bprop_func = B.function( + [self.input_layer.get_activation_vars(), + self.input_layer._get_default_activation_vars()], + self.input_layer.get_mxts()) bprop_results_each_task = [] for task_idx in range(len(fprop_results[0])): out_layer.update_task_index(task_index=task_idx) - bprop_results_task = [list(x) for x in bprop_func(self.inp)] + bprop_results_task = [list(x) for x in bprop_func( + self.inp, np.zeros_like(self.inp))] bprop_results_each_task.append(bprop_results_task) out_layer.set_inactive() diff --git a/tests/blobs/test_batchnorm.py b/tests/blobs/test_batchnorm.py deleted file mode 100644 index 91e0075..0000000 --- a/tests/blobs/test_batchnorm.py +++ /dev/null @@ -1,52 +0,0 @@ -from __future__ import division -from __future__ import print_function -from __future__ import absolute_import -import unittest -from unittest import skip -import sys -import os -import numpy as np -import deeplift.blobs as blobs -from deeplift.blobs import DenseMxtsMode -import theano - - -class TestBatchNormalization(unittest.TestCase): - - def setUp(self): - self.input_layer = blobs.Input_FixedReference( - reference=0.0, - num_dims=None, - shape=(None,4)) - self.w1 = [1.0, 2.0, 3.0, 4.0] - self.w2 = [-1.0, -2.0, -3.0, -4.0] - W = np.array([self.w1, self.w2]).T - b = np.array([-1.0, 1.0]) - self.dense_layer = blobs.Dense(W=W, b=b, - dense_mxts_mode=DenseMxtsMode.Linear) - self.dense_layer.set_inputs(self.input_layer) - self.dense_layer.build_fwd_pass_vars() - self.dense_layer.set_scoring_mode(blobs.ScoringMode.OneAndZeros) - self.dense_layer.set_active() - self.input_layer.update_mxts() - self.inp = [[1.0, 1.0, 1.0, 1.0], - [2.0, 2.0, 2.0, 2.0]] - - def test_dense_fprop(self): - func = theano.function([self.input_layer.get_activation_vars()], - self.dense_layer.get_activation_vars(), - allow_input_downcast=True) - self.assertListEqual([list(x) for x in func(self.inp)], - [[9.0,-9.0], [19.0, -19.0]]) - - def test_dense_backprop(self): - func = theano.function([self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) - self.dense_layer.update_task_index(task_index=0) - self.assertListEqual([list(x) for x in func(self.inp)], - [self.w1, self.w1]) - self.dense_layer.update_task_index(task_index=1) - self.assertListEqual([list(x) for x in func(self.inp)], - [self.w2, self.w2]) - diff --git a/tests/blobs/test_concat.py b/tests/blobs/test_concat.py index 25dd290..adb9dca 100644 --- a/tests/blobs/test_concat.py +++ b/tests/blobs/test_concat.py @@ -8,20 +8,15 @@ import numpy as np import deeplift.blobs as blobs from deeplift.blobs import DenseMxtsMode +from deeplift import backend as B import theano class TestConcat(unittest.TestCase): def setUp(self): - self.input_layer1 = blobs.Input_FixedReference( - reference=0.0, - num_dims=None, - shape=(None,1,1,1)) - self.input_layer2 = blobs.Input_FixedReference( - reference=0.0, - num_dims=None, - shape=(None,1,1,1)) + self.input_layer1 = blobs.Input(num_dims=None, shape=(None,1,1,1)) + self.input_layer2 = blobs.Input(num_dims=None, shape=(None,1,1,1)) self.concat_layer = blobs.Concat(axis=1) self.concat_layer.set_inputs([self.input_layer1, self.input_layer2]) self.flatten_layer = blobs.Flatten() @@ -42,22 +37,27 @@ def setUp(self): self.inp2 = np.arange(2).reshape((2,1,1,1))+1 def test_concat(self): - func = theano.function([self.input_layer1.get_activation_vars(), + func = B.function([self.input_layer1.get_activation_vars(), self.input_layer2.get_activation_vars()], - self.concat_layer.get_activation_vars(), - allow_input_downcast=True) + self.concat_layer.get_activation_vars()) np.testing.assert_allclose(func(self.inp1, self.inp2), np.array([[[[1]],[[1]]],[[[2]],[[2]]]])) def test_concat_backprop(self): - func = theano.function([self.input_layer1.get_activation_vars(), - self.input_layer2.get_activation_vars()], - #self.concat_layer.get_mxts(), - [self.input_layer1.get_mxts(), - self.input_layer2.get_mxts()], - allow_input_downcast=True) + func = B.function([ + self.input_layer1.get_activation_vars(), + self.input_layer2.get_activation_vars()], + #self.concat_layer.get_mxts(), + [self.input_layer1.get_mxts(), + self.input_layer2.get_mxts()], + ) print(func(self.inp1, self.inp2)) self.dense_layer.update_task_index(task_index=0) np.testing.assert_allclose(func(self.inp1, self.inp2), [np.array([[[[1]]],[[[1]]]]), np.array([[[[2]]],[[[2]]]])]) + + def test_concat_backprop2(self): + func = B.function([self.flatten_layer.get_activation_vars()], + self.flatten_layer.get_mxts(), + ) diff --git a/tests/blobs/test_conv2d.py b/tests/blobs/test_conv2d.py index eea02b9..d8a5df3 100644 --- a/tests/blobs/test_conv2d.py +++ b/tests/blobs/test_conv2d.py @@ -9,7 +9,6 @@ import deeplift.blobs as blobs from deeplift.blobs import DenseMxtsMode import deeplift.backend as B -import theano class TestConv(unittest.TestCase): @@ -17,8 +16,7 @@ class TestConv(unittest.TestCase): def setUp(self): #theano convolutional ordering assumed here...would need to #swap axes for tensorflow - self.input_layer = blobs.Input_FixedReference( - reference=np.array([0.0,0.0,0.0,0.0])[:,None].astype("float32"), + self.input_layer = blobs.Input( num_dims=None, shape=(None,2,4,4)) self.w1 = np.arange(8).reshape(2,2,2)[:,::-1,::-1].astype("float32") @@ -58,9 +56,8 @@ def test_fprop(self): self.create_small_net_with_conv_layer(conv_layer, outputs_per_channel=9) - func = theano.function([self.input_layer.get_activation_vars()], - self.conv_layer.get_activation_vars(), - allow_input_downcast=True) + func = B.function([self.input_layer.get_activation_vars()], + self.conv_layer.get_activation_vars()) np.testing.assert_almost_equal(func(self.inp), np.array( [[[[439, 467, 495], @@ -84,10 +81,10 @@ def test_dense_backprop(self): outputs_per_channel=9) self.dense_layer.update_task_index(task_index=0) - func = theano.function([self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) - np.testing.assert_almost_equal(func(self.inp), + func = B.function([self.input_layer.get_activation_vars(), + self.input_layer._get_default_activation_vars()], + self.input_layer.get_mxts()) + np.testing.assert_almost_equal(func(self.inp, np.zeros_like(self.inp)), np.array( [[[[ 0, 2, 2, 2], [ 4, 12, 12, 8], @@ -118,9 +115,8 @@ def test_fprop_stride(self): self.create_small_net_with_conv_layer(conv_layer, outputs_per_channel=9) - func = theano.function([self.input_layer.get_activation_vars()], - self.conv_layer.get_activation_vars(), - allow_input_downcast=True) + func = B.function([self.input_layer.get_activation_vars()], + self.conv_layer.get_activation_vars()) np.testing.assert_almost_equal(func(self.inp), np.array( [[[[ 439, 495], @@ -145,10 +141,10 @@ def test_dense_backprop_stride(self): outputs_per_channel=4) self.dense_layer.update_task_index(task_index=0) - func = theano.function([self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) - np.testing.assert_almost_equal(func(self.inp), + func = B.function([self.input_layer.get_activation_vars(), + self.input_layer._get_default_activation_vars()], + self.input_layer.get_mxts()) + np.testing.assert_almost_equal(func(self.inp, np.zeros_like(self.inp)), np.array( [[[[ 0, 2, 0, 2], [ 4, 6, 4, 6], diff --git a/tests/blobs/test_dense.py b/tests/blobs/test_dense.py index 31538de..9fdfeb6 100644 --- a/tests/blobs/test_dense.py +++ b/tests/blobs/test_dense.py @@ -7,6 +7,7 @@ import os import numpy as np import deeplift.blobs as blobs +from deeplift import backend as B from deeplift.blobs import DenseMxtsMode import theano @@ -14,10 +15,8 @@ class TestDense(unittest.TestCase): def setUp(self): - self.input_layer = blobs.Input_FixedReference( - reference=0.0, - num_dims=None, - shape=(None,4)) + self.input_layer = blobs.Input(num_dims=None, + shape=(None,4)) self.w1 = [1.0, 2.0, 3.0, 4.0] self.w2 = [-1.0, -2.0, -3.0, -4.0] W = np.array([self.w1, self.w2]).T @@ -33,20 +32,22 @@ def setUp(self): [2.0, 2.0, 2.0, 2.0]] def test_dense_fprop(self): - func = theano.function([self.input_layer.get_activation_vars()], - self.dense_layer.get_activation_vars(), - allow_input_downcast=True) + func = B.function([self.input_layer.get_activation_vars()], + self.dense_layer.get_activation_vars()) self.assertListEqual([list(x) for x in func(self.inp)], [[9.0,-9.0], [19.0, -19.0]]) + @skip def test_dense_backprop(self): - func = theano.function([self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) + func = B.function([self.input_layer.get_activation_vars(), + self.input_layer._get_default_activation_vars()], + self.input_layer.get_mxts()) self.dense_layer.update_task_index(task_index=0) - self.assertListEqual([list(x) for x in func(self.inp)], + self.assertListEqual([list(x) for x in func( + self.inp, np.zeros_like(self.inp))], [self.w1, self.w1]) self.dense_layer.update_task_index(task_index=1) - self.assertListEqual([list(x) for x in func(self.inp)], + self.assertListEqual([list(x) for x in func(self.inp, + np.zeros_like(self.inp))], [self.w2, self.w2]) diff --git a/tests/blobs/test_maxmerge.py b/tests/blobs/test_maxmerge.py index 8068162..a0214af 100644 --- a/tests/blobs/test_maxmerge.py +++ b/tests/blobs/test_maxmerge.py @@ -14,16 +14,13 @@ class TestMaxMerge(unittest.TestCase): def setUp(self): - self.input_layer1 = blobs.Input_FixedReference( - reference=1.0, + self.input_layer1 = blobs.Input( num_dims=None, shape=(None,2,1,3)) - self.input_layer2 = blobs.Input_FixedReference( - reference=0.0, + self.input_layer2 = blobs.Input( num_dims=None, shape=(None,2,1,3)) - self.input_layer3 = blobs.Input_FixedReference( - reference=-1.0, + self.input_layer3 = blobs.Input( num_dims=None, shape=(None,2,1,3)) self.merge_layer = blobs.MaxMerge(axis=1, temp=1) @@ -62,14 +59,21 @@ def test_fprop(self): rtol=10**-6) def test_backprop_contribs(self): - func = theano.function([self.input_layer1.get_activation_vars(), - self.input_layer2.get_activation_vars(), - self.input_layer3.get_activation_vars()], - [self.input_layer1.get_target_contrib_vars(), - self.input_layer2.get_target_contrib_vars(), - self.input_layer3.get_target_contrib_vars()], + func = theano.function([ + self.input_layer1.get_activation_vars(), + self.input_layer2.get_activation_vars(), + self.input_layer3.get_activation_vars(), + self.input_layer1._get_default_activation_vars(), + self.input_layer2._get_default_activation_vars(), + self.input_layer3._get_default_activation_vars()], + [self.input_layer1.get_target_contrib_vars(), + self.input_layer2.get_target_contrib_vars(), + self.input_layer3.get_target_contrib_vars()], allow_input_downcast=True) - print(func(self.inp1, self.inp2, self.inp3)) + print(func(self.inp1, self.inp2, self.inp3, + np.ones_like(self.inp1)*1.0, + np.ones_like(self.inp2)*0.0, + np.ones_like(self.inp3)*-1.0)) self.dense_layer.update_task_index(task_index=0) soln = np.array( [[np.array([[[0.0, @@ -91,5 +95,8 @@ def test_backprop_contribs(self): 0.5, 0.0]]])]*2]) print(soln) - np.testing.assert_allclose(func(self.inp1, self.inp2, self.inp3), - soln, rtol=10**-6) + np.testing.assert_allclose(func(self.inp1, self.inp2, self.inp3, + np.ones_like(self.inp1)*1.0, + np.ones_like(self.inp2)*0.0, + np.ones_like(self.inp3)*-1.0), + soln, rtol=10**-6) diff --git a/tests/blobs/test_maxout.py b/tests/blobs/test_maxout.py index 84e38d8..c4c4d87 100644 --- a/tests/blobs/test_maxout.py +++ b/tests/blobs/test_maxout.py @@ -7,16 +7,14 @@ import os import numpy as np import deeplift.blobs as blobs +from deeplift import backend as B import theano class TestMaxout(unittest.TestCase): def setUp(self): - self.input_layer = blobs.Input_FixedReference( - reference=-2, - num_dims=None, - shape=(None,2)) + self.input_layer = blobs.Input(num_dims=None, shape=(None,2)) W = np.array([[[-1.0, 0.0], [-1.0, 0.0], [-1.0, 0.0], @@ -47,9 +45,8 @@ def setUp(self): self.input_layer.update_mxts() def test_maxout_fprop(self): - func = theano.function([self.input_layer.get_activation_vars()], - self.maxout_layer.get_activation_vars(), - allow_input_downcast=True) + func = B.function([self.input_layer.get_activation_vars()], + self.maxout_layer.get_activation_vars()) self.assertListEqual([list(x) for x in func([[-2.0,-2.0], [-1.0,-1.0], [ 0.5, 0.5], @@ -57,17 +54,19 @@ def test_maxout_fprop(self): [[2.0,2.0], [1.0,1.0], [1.0,1.0], [4.0,4.0]]) + @skip def test_diff_from_default(self): - func = theano.function([self.input_layer.get_activation_vars()], - self.input_layer._get_diff_from_default_vars()) + func = B.function([self.input_layer.get_activation_vars()], + self.input_layer._get_diff_from_default_vars()) self.assertListEqual([list(x) for x in func([[-2.0,-2.0], [-1.0,-1.0], [ 0.5, 0.5], [ 2.0, 2.0]])], [[0.0,0.0], [1.0,1.0], [2.5,2.5], [4.0,4.0]]) + @skip def test_time_spent_per_feature(self): - func = theano.function([self.input_layer.get_activation_vars()], + func = B.function([self.input_layer.get_activation_vars()], self.maxout_layer\ ._debug_time_spent_per_feature) time_spent_per_feature = func([[-2.0,-2.0],[-1.0,-1.0], @@ -102,7 +101,7 @@ def test_time_spent_per_feature(self): @skip def test_weighted_ws(self): - func = theano.function([self.input_layer.get_activation_vars()], + func = B.function([self.input_layer.get_activation_vars()], self.maxout_layer\ ._debug_weighted_ws) weighted_ws = func([[-2.0,-2.0],[-1.0,-1.0], @@ -111,20 +110,18 @@ def test_weighted_ws(self): assert False def test_maxout_backprop(self): - func = theano.function([self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) + func = B.function([self.input_layer.get_activation_vars(), + self.input_layer._get_default_activation_vars()], + self.input_layer.get_mxts()) + inp = [[-2.0,-2.0], + [-1.0,-1.0], + [ 0.5, 0.5], + [ 2.0, 2.0]] self.maxout_layer.update_task_index(task_index=0) - self.assertListEqual([list(x) for x in func([[-2.0,-2.0], - [-1.0,-1.0], - [ 0.5, 0.5], - [ 2.0, 2.0]])], + self.assertListEqual([list(x) for x in func(inp,np.ones_like(inp)*-2)], [[-1.0,0.0], [-1.0,0.0], [ -1.0,0.6], [-0.625,1.125]]) self.maxout_layer.update_task_index(task_index=1) - self.assertListEqual([list(x) for x in func([[-2.0,-2.0], - [-1.0,-1.0], - [ 0.5, 0.5], - [ 2.0, 2.0]])], + self.assertListEqual([list(x) for x in func(inp,np.ones_like(inp)*-2)], [[0.0,-1.0], [0.0,-1.0], [0,-0.4], [0.75,-0.25]]) diff --git a/tests/blobs/test_pooling.py b/tests/blobs/test_pooling.py index e46e93a..f39af80 100644 --- a/tests/blobs/test_pooling.py +++ b/tests/blobs/test_pooling.py @@ -45,8 +45,7 @@ def setUp(self): [1,2,5,1], [8,7,6,1], [7,1,9,10]]]]) - self.input_layer = blobs.Input_FixedReference( - reference=self.reference_inps, + self.input_layer = blobs.Input( num_dims=None, shape=(None,2,4,4)) @@ -81,9 +80,8 @@ def test_fprop_maxpool(self): self.create_small_net_with_pool_layer(pool_layer, outputs_per_channel=9) - func = theano.function([self.input_layer.get_activation_vars()], - self.pool_layer.get_activation_vars(), - allow_input_downcast=True) + func = B.function([self.input_layer.get_activation_vars()], + self.pool_layer.get_activation_vars()) np.testing.assert_almost_equal(func([self.reference_inps[0], self.reference_inps[0]-1]), np.array( @@ -109,9 +107,8 @@ def test_fprop_avgpool(self): self.create_small_net_with_pool_layer(pool_layer, outputs_per_channel=9) - func = theano.function([self.input_layer.get_activation_vars()], - self.pool_layer.get_activation_vars(), - allow_input_downcast=True) + func = B.function([self.input_layer.get_activation_vars()], + self.pool_layer.get_activation_vars()) np.testing.assert_almost_equal(func([self.reference_inps[0], self.reference_inps[0]-1]), 0.25*np.array( @@ -138,11 +135,13 @@ def test_backprop_maxpool_gradients(self): outputs_per_channel=9) self.dense_layer.update_task_index(task_index=0) - func = theano.function([self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) - print(func(self.backprop_test_inps)) - np.testing.assert_almost_equal(func(self.backprop_test_inps), + func = B.function([ + self.input_layer.get_activation_vars(), + self.input_layer._get_default_activation_vars()], + self.input_layer.get_mxts()) + np.testing.assert_almost_equal( + func(self.backprop_test_inps, + np.ones_like(self.backprop_test_inps)*self.reference_inps), np.array( [[np.array([[1, 0, 0, 0], [0, 0, 2, 0], @@ -171,11 +170,14 @@ def test_backprop_maxpool_scaled_contribs(self): outputs_per_channel=9) self.dense_layer.update_task_index(task_index=0) - func = theano.function([self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) - print(func(self.backprop_test_inps)) - np.testing.assert_almost_equal(func(self.backprop_test_inps), + func = B.function([self.input_layer.get_activation_vars(), + self.input_layer._get_default_activation_vars()], + self.input_layer.get_mxts()) + print(func(self.backprop_test_inps, + np.ones_like(self.backprop_test_inps)*self.reference_inps)) + np.testing.assert_almost_equal(func( + self.backprop_test_inps, + np.ones_like(self.backprop_test_inps)*self.reference_inps), np.array( [[np.array([[0.5, 0, 0, 0], [0, 0, 2./4 + 1./4, 0], @@ -203,15 +205,16 @@ def test_backprop_avgpool(self): outputs_per_channel=9) self.dense_layer.update_task_index(task_index=0) - func = theano.function([self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) - print(func(self.backprop_test_inps)) + func = B.function([self.input_layer.get_activation_vars(), + self.input_layer._get_default_activation_vars()], + self.input_layer.get_mxts()) avg_pool_grads = np.array([[1, 2, 2, 1], [2, 4, 4, 2], [2, 4, 4, 2], [1, 2, 2, 1]]).astype("float32") - np.testing.assert_almost_equal(func(self.backprop_test_inps), + np.testing.assert_almost_equal(func( + self.backprop_test_inps, + np.ones_like(self.backprop_test_inps)*self.reference_inps), np.array( [[avg_pool_grads*2*0.25, avg_pool_grads*3*0.25], diff --git a/tests/conversion/test_load_batchnorm.py b/tests/conversion/test_load_batchnorm.py index 1cd63c5..1d57dd3 100644 --- a/tests/conversion/test_load_batchnorm.py +++ b/tests/conversion/test_load_batchnorm.py @@ -70,10 +70,7 @@ def setUp(self): def prepare_batch_norm_deeplift_model(self, axis): - self.input_layer = blobs.Input_FixedReference( - reference=0.0, - num_dims=None, - shape=(None,2,2,2)) + self.input_layer = blobs.Input(num_dims=None, shape=(None,2,2,2)) self.batch_norm_layer = blobs.BatchNormalization( gamma=self.gamma, beta=self.beta, @@ -135,12 +132,13 @@ def test_batch_norm_positive_axis_fwd_prop(self): def test_batch_norm_positive_axis_backprop(self): self.prepare_batch_norm_deeplift_model(axis=self.axis) deeplift_multipliers_func = theano.function( - [self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) - np.testing.assert_almost_equal(deeplift_multipliers_func(self.inp), - self.grad_func(self.inp), - decimal=6) + [self.input_layer.get_activation_vars(), + self.input_layer._get_default_activation_vars()], + self.input_layer.get_mxts(), + allow_input_downcast=True) + np.testing.assert_almost_equal( + deeplift_multipliers_func(self.inp, np.zeros_like(self.inp)), + self.grad_func(self.inp), decimal=6) def test_batch_norm_negative_axis_fwd_prop(self): @@ -157,9 +155,11 @@ def test_batch_norm_negative_axis_fwd_prop(self): def test_batch_norm_negative_axis_backprop(self): self.prepare_batch_norm_deeplift_model(axis=self.axis-4) deeplift_multipliers_func = theano.function( - [self.input_layer.get_activation_vars()], - self.input_layer.get_mxts(), - allow_input_downcast=True) - np.testing.assert_almost_equal(deeplift_multipliers_func(self.inp), + [self.input_layer.get_activation_vars(), + self.input_layer._get_default_activation_vars()], + self.input_layer.get_mxts(), + allow_input_downcast=True) + np.testing.assert_almost_equal(deeplift_multipliers_func( + self.inp, np.zeros_like(self.inp)), self.grad_func(self.inp), decimal=6) From 9d7ca5be814c7b8c0c029c0b9d096458163f7c1f Mon Sep 17 00:00:00 2001 From: Avanti Shrikumar Date: Sun, 30 Oct 2016 19:07:27 -0400 Subject: [PATCH 11/19] renamed default to reference Former-commit-id: b16a3b2bb1106e89a8758eb685e790d542c03c9d [formerly 2f446ed493dc868875083fae8d24f7278a104675] Former-commit-id: a0f450907a4b129eb887d83b99026b881c8601df --- deeplift/blobs/activations.py | 12 +- deeplift/blobs/convolution.py | 4 +- deeplift/blobs/core.py | 62 ++-- deeplift/blobs/maxout.py | 18 +- deeplift/blobs/rnn.py | 16 +- deeplift/models.py | 2 +- .../public/tal_gata/TAL-GATA simulation.ipynb | 319 ++++++++++++++++++ .../TAL-GATA simulation.ipynb.REMOVED.git-id | 1 - tests/blobs/test_activation.py | 2 +- tests/blobs/test_conv2d.py | 4 +- tests/blobs/test_dense.py | 2 +- tests/blobs/test_maxmerge.py | 6 +- tests/blobs/test_maxout.py | 6 +- tests/blobs/test_pooling.py | 6 +- tests/conversion/test_load_batchnorm.py | 4 +- 15 files changed, 391 insertions(+), 73 deletions(-) create mode 100644 examples/public/tal_gata/TAL-GATA simulation.ipynb delete mode 100644 examples/public/tal_gata/TAL-GATA simulation.ipynb.REMOVED.git-id diff --git a/deeplift/blobs/activations.py b/deeplift/blobs/activations.py index 3395986..c7a57b3 100644 --- a/deeplift/blobs/activations.py +++ b/deeplift/blobs/activations.py @@ -28,7 +28,7 @@ def _compute_shape(self, input_shape): def _build_fwd_pass_vars(self): super(Activation, self)._build_fwd_pass_vars() self._gradient_at_default_activation =\ - self._get_gradient_at_activation(self._get_default_activation_vars()) + self._get_gradient_at_activation(self.get_reference_vars()) def _get_gradient_at_default_activation_var(self): return self._gradient_at_default_activation @@ -37,13 +37,13 @@ def _build_activation_vars(self, input_act_vars): raise NotImplementedError() def _deeplift_get_scale_factor(self): - input_diff_from_default = self._get_input_diff_from_default_vars() - near_zero_contrib_mask = (B.abs(input_diff_from_default)\ + input_diff_from_reference = self._get_input_diff_from_reference_vars() + near_zero_contrib_mask = (B.abs(input_diff_from_reference)\ < NEAR_ZERO_THRESHOLD) far_from_zero_contrib_mask = 1-(1*near_zero_contrib_mask) #the pseudocount is to avoid division-by-zero for the ones that #we won't use anyway - pc_diff_from_default = input_diff_from_default +\ + pc_diff_from_reference = input_diff_from_reference +\ (1*near_zero_contrib_mask) #when total contrib is near zero, #the scale factor is 1 (gradient; piecewise linear). Otherwise, @@ -53,8 +53,8 @@ def _deeplift_get_scale_factor(self): scale_factor = near_zero_contrib_mask*\ self._get_gradient_at_default_activation_var() +\ (far_from_zero_contrib_mask*\ - (self._get_diff_from_default_vars()/ - pc_diff_from_default)) + (self._get_diff_from_reference_vars()/ + pc_diff_from_reference)) return scale_factor def _gradients_get_scale_factor(self): diff --git a/deeplift/blobs/convolution.py b/deeplift/blobs/convolution.py index 253eac6..54556c0 100644 --- a/deeplift/blobs/convolution.py +++ b/deeplift/blobs/convolution.py @@ -181,9 +181,9 @@ def _get_mxts_increments_for_inputs(self): elif (self.maxpool_deeplift_mode== MaxPoolDeepLiftMode.scaled_gradient): grad_times_diff_def = self._get_input_grad_given_outgrad( - out_grad=self.get_mxts()*self._get_diff_from_default_vars()) + out_grad=self.get_mxts()*self._get_diff_from_reference_vars()) pcd_input_diff_default = (pseudocount_near_zero( - self._get_input_diff_from_default_vars())) + self._get_input_diff_from_reference_vars())) return grad_times_diff_def/pcd_input_diff_default else: raise RuntimeError("Unsupported maxpool_deeplift_mode: "+ diff --git a/deeplift/blobs/core.py b/deeplift/blobs/core.py index 310dc1c..2a2804d 100644 --- a/deeplift/blobs/core.py +++ b/deeplift/blobs/core.py @@ -80,36 +80,36 @@ def get_activation_vars(self): self._layer_needs_to_be_built_message() return self._activation_vars - def _build_default_activation_vars(self): + def _build_reference_vars(self): raise NotImplementedError() - def _build_diff_from_default_vars(self): + def _build_diff_from_reference_vars(self): """ instantiate theano vars whose value is the difference between - the activation and the default activaiton + the activation and the reference activation """ - return self.get_activation_vars() - self._get_default_activation_vars() + return self.get_activation_vars() - self.get_reference_vars() def _build_target_contrib_vars(self): """ the contrib to the target is mxts*(Ax - Ax0) """ - return self.get_mxts()*self._get_diff_from_default_vars() + return self.get_mxts()*self._get_diff_from_reference_vars() - def _get_diff_from_default_vars(self): + def _get_diff_from_reference_vars(self): """ return the theano vars representing the difference between - the activation and the default activation + the activation and the reference activation """ - return self._diff_from_default_vars + return self._diff_from_reference_vars - def _get_default_activation_vars(self): + def get_reference_vars(self): """ get the activation that corresponds to zero contrib """ - if (hasattr(self, '_default_activation_vars')==False): - raise RuntimeError("_default_activation_vars is unset") - return self._default_activation_vars + if (hasattr(self, '_reference_vars')==False): + raise RuntimeError("_reference_vars is unset") + return self._reference_vars def _increment_mxts(self, increment_var): """ @@ -200,7 +200,7 @@ def __init__(self, num_dims, shape, **kwargs): def get_activation_vars(self): return self._activation_vars - def _build_default_activation_vars(self): + def _build_reference_vars(self): return B.tensor_with_dims(self._num_dims, name="ref_"+str(self.get_name())) @@ -211,8 +211,8 @@ def get_yaml_compatible_object_kwargs(self): return kwargs_dict def _build_fwd_pass_vars(self): - self._default_activation_vars = self._build_default_activation_vars() - self._diff_from_default_vars = self._build_diff_from_default_vars() + self._reference_vars = self._build_reference_vars() + self._diff_from_reference_vars = self._build_diff_from_reference_vars() self._mxts = B.zeros_like(self.get_activation_vars()) @@ -247,13 +247,13 @@ def _get_input_activation_vars(self): return self._call_function_on_blobs_within_inputs( 'get_activation_vars') - def _get_input_default_activation_vars(self): + def _get_input_reference_vars(self): return self._call_function_on_blobs_within_inputs( - '_get_default_activation_vars') + 'get_reference_vars') - def _get_input_diff_from_default_vars(self): + def _get_input_diff_from_reference_vars(self): return self._call_function_on_blobs_within_inputs( - '_get_diff_from_default_vars') + '_get_diff_from_reference_vars') def _get_input_shape(self): return self._call_function_on_blobs_within_inputs('get_shape') @@ -282,11 +282,11 @@ def _build_fwd_pass_vars(self): self._activation_vars =\ self._build_activation_vars( self._get_input_activation_vars()) - self._default_activation_vars =\ - self._build_default_activation_vars() - self._diff_from_default_vars =\ - self._build_diff_from_default_vars() - self._mxts = B.zeros_like(self._get_default_activation_vars()) + self._reference_vars =\ + self._build_reference_vars() + self._diff_from_reference_vars =\ + self._build_diff_from_reference_vars() + self._mxts = B.zeros_like(self.get_reference_vars()) def _compute_shape(self, input_shape): """ @@ -301,9 +301,9 @@ def _build_activation_vars(self, input_act_vars): """ raise NotImplementedError() - def _build_default_activation_vars(self): + def _build_reference_vars(self): return self._build_activation_vars( - self._get_input_default_activation_vars()) + self._get_input_reference_vars()) def _update_mxts_for_inputs(self): """ @@ -488,7 +488,7 @@ def _get_mxts_increments_for_inputs(self): to_distribute =\ B.maximum( (total_neg_contribs*(total_neg_contribs < total_pos_contribs) - - B.maximum(self._get_default_activation_vars(),0)),0.0)\ + - B.maximum(self.get_reference_vars(),0)),0.0)\ *(1.0-((total_neg_contribs)/ pseudocount_near_zero(total_pos_contribs))) #total_pos_contribs_new has dims batch x output @@ -652,7 +652,7 @@ def _build_activation_vars(self, input_act_vars): return B.maximum_over_list(the_list=input_act_vars) def _get_mxts_increments_for_inputs(self): - refs = self._get_input_default_activation_vars() + refs = self._get_input_reference_vars() inp_acts = self._get_input_activation_vars() output = self.get_activation_vars() #1(a): Compute max(ref s.t. ref < output, -inf if ref >= output) @@ -682,7 +682,7 @@ def _get_mxts_increments_for_inputs(self): max_neg_ride = B.maximum_over_list(negative_rides_arr) max_pos_ride = B.maximum_over_list(positive_rides_arr) #allocate total negative and positive importance according to ratio of max ride lengths - out_diff_def = self._get_diff_from_default_vars() + out_diff_def = self._get_diff_from_reference_vars() #distribute importance for individual pos and neg rides according to some function exp_pos_rides_arr = [B.exp(pos_rides/self.temp)-1 for pos_rides in positive_rides_arr] @@ -700,10 +700,10 @@ def _get_mxts_increments_for_inputs(self): contrib_neg_rides_arr = [((-exp_neg_rides*max_neg_ride)/ sum_exp_neg_rides) for exp_neg_rides in exp_neg_rides_arr] - #compute multipliers as ratio of contrib to inp diff-from-default + #compute multipliers as ratio of contrib to inp diff-from-reference pcd_inp_diff_def_arr = [pseudocount_near_zero(inp_diff_def) for inp_diff_def in - self._get_input_diff_from_default_vars()] + self._get_input_diff_from_reference_vars()] multipliers_arr = [(contrib_pos_rides+contrib_neg_rides)/ pcd_inp_diff_def for (contrib_pos_rides, diff --git a/deeplift/blobs/maxout.py b/deeplift/blobs/maxout.py index 6d20eaf..17c277a 100644 --- a/deeplift/blobs/maxout.py +++ b/deeplift/blobs/maxout.py @@ -80,7 +80,7 @@ def _get_actual_active_gradients(self): def _get_weighted_active_gradients(self): """ intuition for calculation: take the vector in the direction - of change ('input_diff_from_default') and find the 'theta' + of change ('input_diff_from_reference') and find the 'theta' representing where along this vector two planes intersect. Also find pairs of planes where the former is increasing faster than the latter along the direction of @@ -109,11 +109,11 @@ def _get_weighted_active_gradients(self): #get gradients ("features") weighted by how much they #'dominate' on a vector #from the default value of the input to the actual input value - #input_diff_from_default has dimensions: batch x num_inputs - inp_diff_from_default = self._get_input_diff_from_default_vars() + #input_diff_from_reference has dimensions: batch x num_inputs + inp_diff_from_reference = self._get_input_diff_from_reference_vars() #compute differences in each feature activation at default - #_get_input_default_activation_vars() has dims: batch x num_inputs + #_get_input_reference_vars() has dims: batch x num_inputs #W_differences has dims: # num_features x num_features x num_inputs x num_outputs #b_differences has dims: @@ -121,24 +121,24 @@ def _get_weighted_active_gradients(self): #feature_diff_at_default therefore has dims: # batch x num_features x num_features x num_outputs feature_diff_at_default =\ - B.dot(self._get_input_default_activation_vars() + B.dot(self._get_input_reference_vars() , self.W_differences)\ + self.b_differences self._debug_feature_diff_at_default = feature_diff_at_default #dot product with unit vector in the difference-from-default dir #change_vec_projection has dim batch x - #inp_diff_from_default has dims: batch x num_inputs + #inp_diff_from_reference has dims: batch x num_inputs #W_differences has dims: # num_features x num_features x num_inputs x num_outputs #change_vec_projection therefore has dims: # batch x num_features x num_features x num_outputs - inp_diff_from_default_pc = inp_diff_from_default +\ + inp_diff_from_reference_pc = inp_diff_from_reference +\ (NEAR_ZERO_THRESHOLD* - (B.sum(B.abs(inp_diff_from_default) + (B.sum(B.abs(inp_diff_from_reference) ,axis=1)