From 29433f768f5a1655459be36bb9e1ab3fe385e206 Mon Sep 17 00:00:00 2001 From: ahoni <aurelie.saulq@proton.me> Date: Sun, 2 Mar 2025 19:19:39 +0100 Subject: [PATCH] change modnef model and template --- modneflib/modnef/modnef_torch/__init__.py | 1 + .../__pycache__/__init__.cpython-310.pyc | Bin 334 -> 390 bytes .../__pycache__/model.cpython-310.pyc | Bin 8805 -> 5519 bytes .../__pycache__/trainer.cpython-310.pyc | Bin 7766 -> 7841 bytes modneflib/modnef/modnef_torch/model.py | 229 ++---------- .../modnef/modnef_torch/model_builder.py | 327 ++++++++++++++++++ .../modnef_torch_neuron.cpython-310.pyc | Bin 3439 -> 3957 bytes .../__pycache__/blif.cpython-310.pyc | Bin 9185 -> 9297 bytes .../__pycache__/rblif.cpython-310.pyc | Bin 9614 -> 9737 bytes .../modnef_neurons/blif_model/blif.py | 8 +- .../modnef_neurons/blif_model/rblif.py | 8 +- .../modnef_neurons/modnef_torch_neuron.py | 26 +- .../__pycache__/rslif.cpython-310.pyc | Bin 10053 -> 10176 bytes .../__pycache__/slif.cpython-310.pyc | Bin 9774 -> 9886 bytes .../modnef_neurons/slif_model/rslif.py | 8 +- .../modnef_neurons/slif_model/slif.py | 8 +- .../__pycache__/rshiftlif.cpython-310.pyc | Bin 10261 -> 10384 bytes .../__pycache__/shiftlif.cpython-310.pyc | Bin 9784 -> 9896 bytes .../modnef_neurons/srlif_model/rshiftlif.py | 8 +- .../modnef_neurons/srlif_model/shiftlif.py | 8 +- modneflib/modnef/modnef_torch/trainer.py | 8 +- modneflib/modnef/quantizer/quantizer.py | 2 +- modneflib/modnef/templates/evaluation.py | 98 ++++++ modneflib/modnef/templates/main.py | 29 -- .../modnef/templates/model_template.json | 81 +++++ modneflib/modnef/templates/run_lib.py | 211 +++++++++++ .../modnef/templates/template_model.json | 134 ------- modneflib/modnef/templates/train.py | 62 ++++ 28 files changed, 880 insertions(+), 376 deletions(-) create mode 100644 modneflib/modnef/modnef_torch/model_builder.py create mode 100644 modneflib/modnef/templates/evaluation.py delete mode 100644 modneflib/modnef/templates/main.py create mode 100644 modneflib/modnef/templates/model_template.json create mode 100644 modneflib/modnef/templates/run_lib.py delete mode 100644 modneflib/modnef/templates/template_model.json create mode 100644 modneflib/modnef/templates/train.py diff --git a/modneflib/modnef/modnef_torch/__init__.py b/modneflib/modnef/modnef_torch/__init__.py index c9c0455..d61cdd5 100644 --- a/modneflib/modnef/modnef_torch/__init__.py +++ b/modneflib/modnef/modnef_torch/__init__.py @@ -1,4 +1,5 @@ from .modnef_neurons import * +from .model_builder import ModNEFModelBuilder from .model import ModNEFModel from .trainer import ModNEFTrainer from .executor import ModNEFExecutor \ No newline at end of file diff --git a/modneflib/modnef/modnef_torch/__pycache__/__init__.cpython-310.pyc b/modneflib/modnef/modnef_torch/__pycache__/__init__.cpython-310.pyc index 9f4f447a3ea926f1f09a8bb926113c80fe26a5ed..fb5f930237a51ae64b29d117c9107ba84b67fbc0 100644 GIT binary patch delta 185 zcmX@d)W*!4&&$ijz`(%pu;@torir|=j5ZUs4GbAlSaaBOIiffi8B*AS88q2nGBPkQ zXfobn)Y4?UCFGl*;^*q-o1c=J<5ZfNlag9AG0P;J^A=xjeo9_yT6|t=X;FS&@h#q5 zkdpW$h?*j11_p*(tYEPs77&}gq$n{nFSV$M6~yC6tw>ESEy*t`Vq;)nSjkYt!@$5$ U#53_>A|J?!91J{+ASl2H05a<{7ytkO delta 130 zcmZo;KF7qH&&$ijz`($;*m+NS%S2vTMuUmk2K=nS44P~&85tNDG#PI(YEA4hab~~8 zmz$rGmzoxzms(nspI3Z~H8(#cHK&M~fq~%`dr47ZW?pJh5etaNky??OTw0P}RK&`_ ez_5~`2xLVO*JN?VL>>+X1_llW9!4HU0Y(4~QXt>} diff --git a/modneflib/modnef/modnef_torch/__pycache__/model.cpython-310.pyc b/modneflib/modnef/modnef_torch/__pycache__/model.cpython-310.pyc index 94eb020d8c00c284144907451213f356d271c90b..980e74db9a47de5f660f7f5c0d7efaab3cda51b7 100644 GIT binary patch delta 2146 zcmaFr(yy(Z&&$ijz`(#zP<13-M3{l$F^GeVSr`}?92giFiW4SkyU8==az}A9GPpCO zu%)oKFr=`jvSsl!Ge_~JFa<Mca%|kh&&bbsi^n%V#n08vFSWENKX39sMk&Ug$&yUc z_3aF4j43QBtSuZ-tSRy!%_$tIY-ubhoGDx_tWoSK3Sd4{3Qr1e3u_cdied_Xia-lv z6laQHickwf6jzFHibxAX6nBbfidYLn6i<qHibM-T6mN=Tic||j6km!`ifoEp3u6?2 zI|B<tlt3_prt&Rrh;w{5?`FEhY|n_~I}n?Rfq{V;<Us`n28I%bW`+ff3mF(0QW$F( z;+eoCa|%-pLp%%Ei_DYd*w=}>`DwD=Vl6H$NG-a>5g(tKmst`Ye@kNWZVpL#zO;h$ z#Q4;*#GLrFoW%57Y$-*VWvN9g8E>%^r{<(h&f<)zXJ=qwum{=6!N9=4#lyzL#>B-` zB?5J4eoAVN9?aBaRwVbbF)%QIA_VMSHwFfV8s-{?c!nC58ishr8ioZ-3mIG(Vg+ki zOPFg|OIVtjill2;7qHeaFJxq7s9{~eR>K5h)faM=us1VganvxTF!nMAGiWmTX)@ko z$<0qm)#NM!IqDV*$Q!rVbMsS5b5e_Mab*@~<`tJD<|U^Vfn0D)I3uwrr981HH9obt zBr`X$Br`wn7H4s4Nqk{xVqQrR$f>tjONtUR^EBCtco-NMiUb)L7;do^mL}HcmE7Wh z=`Ruj2{Yyv@q*Owg9rhT2zz`ySa&ceoIoOMOl*uiOk9j0$kf2cR3(fWUSQQBU|WhL z7#J9mL7@Z-JP;e?BxjImQXng97_t~@7;BhP7*iNin0i@)88n%zG$uQ+N=?>d<*8Rt za9hcOFsw)t<S>xFm5jH9<B@EJI#ZJw;YqOdMPRRh36SfH#2FYE;u#niK7$gR5Nnkn zk{Nnnx4R{Sq#!QVU|;}o;7$hF403S_BPh<0Ts*muReW**zlceZ49JDD3=9mKOc1Al z0s+kxw^%?4GaaN-o`Hd3@&$fFMz+aJ0xBX|Oeqk^oWcSQ4Av^G$quYylLG`qW!yr* zrfV`6feMQvP+%6xfox(f;+fnaAg>PgCYS*E^%f^6@qqI{9w@v)zTjfzVHBEtLO@j& zl<7bs;HW_O3v4}O3NzSpmdRec8hTJ`i$I<#;s!YyYz3GA*;6FSz`#%r5(j(cBd_A* zO@gs{AUED(P0q<LPQ|9{77th|9+EHXC)*1pu&iXP+BAtxZ1PT_`N5o^)W;hS_Ci{I zQF&rf$}NH7{In8qYKMxfgoN=ep3J<0(vtY%g3RpHV)VdfhbnI0d`$QZBkRlm|NsA= zJYCev?-naq+b!nA)S_FAnYS3@(Y3Ob<i{tb7OesWA0Gn)gAgMNlMtf-BM&3fe-`E{ zP2|KgSxzjFk!x~+n7rXFww%Pu)S}`d6HurafPBJMlA2eXUv!JTAhjsBv?LXl8?`|y zEGO?3Q>zCDD3}0;ss;lC!)%bnARY%l7Z(R33lj&E1S21#1XGnHvehV|gp_<CsTUN} zpjiG4if&NR+Qe9-&cMI`%0hnmC7!tjIjOm+dG#f!DXv9D`9(!qAUA;>0wzHA7ilsu zFdTs88#ewb8D#s>qs8wQqh2zoe1ha6NNEXkMv*Hh$ucI&Gcqu6DJUo?xTof&7A2NU zE@cy)Tp|09vj|kAYO)mZOr9mLAB-L)>?Qf}Wf>_smq3p6U|?WCEr6i1noJ=fnv8Cm zj75qd+nD`|JVENg9Kp$D3VPteADnw`u_Wc^=YR`_B2eX1qykb2O4CJZAeIh@07V8k z42pa~vB?`BpPZ9eT%4SmlM|1eYQUu@IKV&^1}Iw<OEEAoa4@hi^62o0i0}w-aItf6 za&QQ8aBzrls0s-cffQ=;6$MUqQVeFh#gvy<WH5P-qOm8WfM@ds7yV#WNI?OQm|Gk+ dkjlXh6u!kEt63O?xOf;j7&#bu7<m}Qm;h@m(dPgF literal 8805 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 MN;VM8_DhTl0D7ez-v9sr diff --git a/modneflib/modnef/modnef_torch/__pycache__/trainer.cpython-310.pyc b/modneflib/modnef/modnef_torch/__pycache__/trainer.cpython-310.pyc index 244dc9429332508edd71083bd2fc0446d3427800..18e25f81bcf3e35df0c64461da7b3606c3a31ae7 100644 GIT binary patch delta 1503 zcmca+v(T0=pO=@5fq{WxZt;<HHl>MtGK_f>wSCmtQ#f<Db9th87#UI+Q<!piqxjqz zQn*sMTNqNfo0+2cQ<#DoG<h~o(q<GE^36~2b9M90Pf5*jD$UGENiEvEi?NTno~eeh znX!f;o;i=X229s5r7&hQ6)BdmWU*$k)i7i+FJNEDkiwM0oWjz}T*DC0k;h!a1fpx0 z!7BAiI2Uj&WT;_?=gwoU0jc1wVFAmym9S*-EZ|+pP-I`ivVbpzbs=LO3z)^W5M&o$ z9-9O*w}!QbA)dd6t%f09VDo)e5hfnNTP!7&1*t_G3=9mDf3b%!@=o^Wuuv3WU|=W` z1rZV;LJCAkg9sT028NXkMRJo@a6~hjZD!%@U}BV-+{-O)0+wcFU|_h#nVMIcn_84u zl3D~Z=N4;8QDSD^EvAzEB9KA1*ozBGQ&X!_iv%a%;8tLinEaDlol$hMB9A(w>|{?K zSw_{#={%OoCLsId;DkKLXkM^U@rLoK1^LMt8JiFDFtIQ?Pd+A~&uB6En}A6Y$igBI zkR~k<0kW@155xjF?-px8QD$CAkt0aJ0AwCVVsdh6QDSmsksyf6Qk+<pdW);LB(Wql zJ|#1`qzL3+O`#%LkPZtF;Xb)XaJr!-NHu$6a&mlGVos4YhzBw%z9hA{qzKi`MVbr@ z3^ON(2&FUXP2MA9#h5bryU;$4I<7kII-WY-&0B@l8QBy;Mk`N#B%)NW&cML%^8f$; z|20L5K#nc~g=vunNCCo2Ajd-jm$|q!w@4r40Jg-U^xVXXTTH2ix7f=vQ_JHMi;E0F zGAzZJRjEa$AS28`ggJ-+dziJjBr!Sr7JE@@aYkZ6s-{3uJ=m-6AQj+X3<I%3L8h=L z=NA>FCYRh|Ey*uQ%qda@$yk91kpGKpKrCAjVFx1YL0Z`IOG^q$OKx!%6s3ZKGc^S* zaBlI%#}}36#lxcECIbrtL$TRpHZdJ`CMHHEMi$1&#$u|Bo|_}ZVi-Bx7#J8dnTrG_ z?-kcFLUX7$$X1X;i@;7siv*CY*knnGXvVC~r4s6lE-<4&&J@l_EJ`U)EJ}?}EiTE- zO)SaG&nwCSnU@P9(2OczU|=w2WMC-D+x$Q>h^d|rqy}spD<n!d(+biP<5NK?1DyUq zAq_T8lM|AVz@b|VvY9)jD6=fJD83-EBm<IcK@Kf~d*c>&PGWIMd`fCrW^yWe*ztnx z;e>@<z~o&rcAB7aOq0d0$ccf0A*9F|6kv=+o)9V@L@^Z=f*f2lSy9&5MghbGX9rL! z1v|0`>;jM{iz+~}2;YNQpln#g$-uxMI(dSuyrC_ZET1fxuPIPe1M(6_Nq$jshF)G? zkr<d;oR<d{DPjVdCOG+ltWwr3-ds>Q8J`3xD2v!ZQsAr$Du-^d=9T6aR2G5LD#$7% pkHg(?i^C>2KczG$)sB&YfuUH0fq{XAfrpESk%N&33ON{sm;vpyUFiS- delta 1438 zcmZ2zd(DO~pO=@5fq{YHvgd*H9>s}#GK@(RwSA-+Q<!qNqj=mIQaDq%S{PEenwg?_ zQ<#DoG`Tm<(`MX!pRt>{p0S3pnX!f;o+*#H229s5r7&hQ6)Bc5XR&0l)-Yr-Enr*7 zkiwM0oWjz}T*DC0p2u9n1fpx0!7BAiI2Ld&WT;_?=gMQQ0jc1sVFAmyl`v;<FW_0o zP-I`iynr`_bs=LO3z)^W5M&o`9-9O*w}!QbA)c>>t%f0<e={SS2ot-&EtZnXg4D^1 z93hN6lgl_P6!{q#7>YzdggA(h1QAjoLYjerVI@P6?Bw$t(Tt{>wK+SOd_b~Q>^}L$ z#R^smzt{|HjP;DtG{uX+8dw<^7;bT<=9T8A7A2OX7J*E@#adF7n3;ErsU*J$r1=(m zabam{YE^2Hz~ukj3XI~D6?oJcMJ9Xjs58n;F5r=6RGHkzW2tNma)B(IkOLXb3pOg= zFg~>)KRF|P^D7=E7DlJZZw2%j%_qwWn$&|VEOG~F(gYD8`-*fyERgeVu@)3%=9LsV zfCThG=5Zt@Czlo_CRY{-fVeEhiDjv`xQa^>OH$)gGLuV+Kp~(hR3rn^VGbhPK<Wg_ z5_2+B5=%1k^L+9XQ&Nj=vFCxEH2H#Hm7xVl343C4a(r20PLUOe2eK!=B(=Dt2-QPH z8Vn2!GbUFHr8BBcek^3gm@rvRc;DtH!s?7{3Lxv0CJTxx)vGZuFueT#|NnnY5kxo_ zse=?Cyb1CUB*2-AOLL3#K=!gF7NzGVR@`DrExg5EmYG@}pIBUE0Fq%T&a6r;G65N3 z3L?xv1UL{_i%Sxdvv08%r50x-7Nlwl6zPM#5Ar!AXhT72LqMjmC+8Oxr6!l$VlBxp zNz5ry0m)cSz9TAQaf>a#w4|W4<Q8W^Q7R}bQ&Z49e~T|ZzNj=W9u@~T7#J9e4JMn4 z=`c1-&Ja^&^w``d7Q@Kl%D}*&$y~%g`IESo5t>uHKo)|WQUrDsTIhmg1t$ARL^Eb? zUL~Q<=mIke<aXhV#G;h)#G=&r)Z&uNTySg_WrNJi0TF0M<ufoa=rS@e6y<Ifl?r02 z=LM+&8^;O>bk4Mb^u+j7P?UpH9Vjfp#%Xdwk`Fliia<7VrxazDr542(B$i}ALKNiC zBDgnhapxo!m&B)}mSrZVq6Zo;*d9(;pm|MxFJq_42?`<>zamEl28NI#ClHUZ$OA&< zfheY;0+53XCx^)z+sK2M;7kBYeqcuyfn5OdWKlUt7U6p^3zYeaI2afhL?$1Vm6x^P zlI4>H^ELU3szF}jD9JBM&d|%tD-xZ|C@0J)Fj-ViDFhrcMeHC2ta+um1(ikMv<5N= p$y;z6ZgJS;=BJeAq}nlpl7bKe0|N^K4;K$32O|#{axe-p0|2cgQNI8H diff --git a/modneflib/modnef/modnef_torch/model.py b/modneflib/modnef/modnef_torch/model.py index 71d346c..8eaf453 100644 --- a/modneflib/modnef/modnef_torch/model.py +++ b/modneflib/modnef/modnef_torch/model.py @@ -13,17 +13,7 @@ import torch.nn as nn import torch from modnef.arch_builder import * from modnef.modnef_driver import load_driver_from_yaml -from math import ceil, log - -neuron_model = { - "blif" : mn.BLIF, - "rblif" : mn.RBLIF, - "slif" : mn.SLIF, - "rslif" : mn.RSLIF, - "shiftlif" : mn.ShiftLIF, - "rshiftlif" : mn.RShiftLIF -} - +from modnef.modnef_torch.modnef_neurons import ModNEFNeuron class ModNEFModel(nn.Module): """ @@ -70,10 +60,7 @@ class ModNEFModel(nn.Module): Generate VHDL file of model """ - def __init__(self, - configuration, - spike_grad - ): + def __init__(self): """ Initialize class @@ -87,107 +74,38 @@ class ModNEFModel(nn.Module): super().__init__() - self.name = "MySNN" - - self.layers = nn.ModuleDict() - - self.__hardware_estimation_flag = False - - self.__fpga_eval_flag = False + self.hardware_estimation_flag = False - self.mem = {} - self.spk = {} - - self.__input_size = -1 - self.__num_class = -1 - - self.configuration = configuration + self.fpga_eval_flag = False self.driver = None - self.hardware_description = { - "clock_name" : "clock", - "clock_freq" : 125_000_000, - "baud_rate" : 921_600, - "txd" : "uart_txd", - "rxd" : "uart_rxd", - "queue_read_depth" : 4096, - "queue_write_depth" : 1024 - } - - self.build(configuration=configuration, spike_grad=spike_grad) - - def build(self, configuration, spike_grad): - """ - Build layers of model (call during initialization) - - Parameters - ---------- - configuration : dict - model configuraiton dictionnary - spike_grade : function - surrogate gradient - """ - - for key in configuration: - - if key == "name": - self.name = configuration[key] - elif key == "input": - self.__input_size = configuration[key] - elif key=="num_class": - self.__num_class = configuration[key] - elif key=="hardware": - for k in configuration[key]: - self.hardware_description[k] = configuration[key][k] - else: - layer_name = key - - self.mem[layer_name] = None - self.spk[layer_name] = None - - layer_config = configuration[key] - - layer_model = layer_config["model"].lower() - - if layer_model in neuron_model.keys(): - self.layers[layer_name] = neuron_model[layer_model].from_dict(layer_config, spike_grad) - else: - print(f"{layer_model} is unknow") - + def __train(self, mode, quant, hardware, fpga): - def hardware_estimation(self): - """ - Set hardware estimation flag - """ + self.hardware_estimation_flag = hardware + self.fpga = fpga - self.eval() - self.__hardware_estimation_flag = True - for layer in self.layers: - self.layers[layer].hardware_estimation_flag = True - self.layers[layer].quantize() + for m in self.modules(): + if isinstance(m, ModNEFNeuron): + m.hardware_estimation(hardware) + m.set_quant(quant) - def train(self, mode : bool = True): + return super().train(mode=mode) + + def train(self, mode : bool = True, quant : bool = True): """ Set neuron model for trainning """ - - self.__hardware_estimation_flag = False - self.__fpga_eval_flag = False - for layer in self.layers: - self.layers[layer].hardware_estimation_flag = False - return super().train(mode=mode) - def eval(self): + return self.__train(mode=mode, quant=quant, hardware=False, fpga=False) + + + def eval(self, quant : bool = False): """ Set neuron model for evaluation """ - self.__hardware_estimation_flag = False - self.__fpga_eval_flag = False - for layer in self.layers: - self.layers[layer].hardware_estimation_flag = False - return super().eval() + return self.__train(mode=False, quant=quant, hardware=False, fpga=False) def fpga_eval(self, board_path, driver_config = "./driver.yml"): """ @@ -196,17 +114,15 @@ class ModNEFModel(nn.Module): if self.driver==None: self.driver = load_driver_from_yaml(driver_config, board_path) - self.eval() - self.__fpga_eval_flag=True - - - def init_mem(self): + return self.__train(mode=False, quant=False, hardware=False, fpga=True) + + def hardware_estimation(self): """ - Initialize layers memory + Set hardware estimation flag """ + + return self.__train(mode=False, quant=True, hardware=True, fpga=False) - for layer in self.layers: - self.spk[layer], self.mem[layer] = self.layers[layer].reset_mem() def close_driver(self): """ @@ -231,12 +147,12 @@ class ModNEFModel(nn.Module): output_spike, output_mem """ - if self.__fpga_eval_flag: - return self.__fpga_forward(input_spikes) + if self.fpga_eval_flag: + return self._fpga_forward(input_spikes) else: - return self.__computer_forward(input_spikes) + return self.software_forward(input_spikes) - def __fpga_forward(self, input_spikes): + def _fpga_forward(self, input_spikes): """ Transmit input spike to FPGA @@ -273,7 +189,7 @@ class ModNEFModel(nn.Module): return torch.tensor(batch_result).permute(1, 0, 2), None - def __computer_forward(self, input_spikes): + def software_forward(self, input_spikes): """ Run layers upate @@ -288,51 +204,8 @@ class ModNEFModel(nn.Module): output_spike, output_mem """ - self.init_mem() - - batch_size = input_spikes.shape[0] - n_steps = input_spikes.shape[1] - - spk_rec = [] - mem_rec = [] - - if self.__hardware_estimation_flag: - spike_count = torch.zeros((batch_size), device=input_spikes.device) - - for step in range(n_steps): - last_layer = None - x = input_spikes[:,step].reshape(batch_size, -1) - - if self.__hardware_estimation_flag: - spike_count += torch.sum(x, dim=1) - - for layer in self.layers: - if last_layer==None: - self.spk[layer], self.mem[layer] = self.layers[layer](input_=x, spk=self.spk[layer], mem=self.mem[layer]) - else: - self.spk[layer], self.mem[layer] = self.layers[layer](input_=self.spk[last_layer], spk=self.spk[layer], mem=self.mem[layer]) - last_layer = layer - - spk_rec.append(self.spk[last_layer]) - mem_rec.append(self.mem[last_layer]) - - if self.__hardware_estimation_flag: - self.hardware_description["queue_read_depth"] = int(max(self.hardware_description["queue_read_depth"], torch.max(spike_count).item())) - self.hardware_description["queue_write_depth"] = int(max(self.hardware_description["queue_write_depth"], (n_steps+len(self.layers))*self.__num_class)) + raise NotImplementedError() - return torch.stack(spk_rec, dim=0), torch.stack(mem_rec, dim=0) - - def set_layer_hardware(self, config): - """ - Set hardware description to all layers - - Parameters - ---------- - config: dict - hardware configuration - """ - for k in config: - self.layers[k].set_hardware(config[k]) def to_vhdl(self, file_name=None, output_path = ".", driver_config_path = "./driver.yml"): """ @@ -349,42 +222,4 @@ class ModNEFModel(nn.Module): driver configuration file """ - if file_name==None: - file_name = f"{output_path}/{self.name}.vhd" - - builder = ModNEFBuilder(self.name, self.__input_size, self.__num_class) - - self.hardware_description["queue_read_depth"] += ceil(log(self.hardware_description["queue_read_depth"])/log(256)) - self.hardware_description["queue_write_depth"] += ceil(log(self.hardware_description["queue_write_depth"])/log(256)) - - self.hardware_description["queue_read_depth"] = 2**(ceil(log(self.hardware_description["queue_read_depth"])/log(2))) - self.hardware_description["queue_write_depth"] = 2**(ceil(log(self.hardware_description["queue_write_depth"])/log(2))) - - - uart = Uart_XStep( - name="uart", - input_layer_size=self.__input_size, - output_layer_size=self.__num_class, - clk_freq=self.hardware_description["clock_freq"], - baud_rate=self.hardware_description["baud_rate"], - queue_read_depth=self.hardware_description["queue_read_depth"], - queue_write_depth=self.hardware_description["queue_write_depth"], - tx_name=self.hardware_description["txd"], - rx_name=self.hardware_description["rxd"] - ) - - builder.add_module(uart) - builder.set_io(uart) - - last_module = uart - - for layer in self.layers: - module = self.layers[layer].get_builder_module(layer, output_path) - builder.add_module(module) - builder.add_link(last_module, module) - last_module = module - - builder.add_link(last_module, uart) - - builder.get_driver_yaml(f"{output_path}/{driver_config_path}") - builder.to_vhdl(file_name, self.hardware_description["clock_name"]) \ No newline at end of file + raise NotImplementedError() \ No newline at end of file diff --git a/modneflib/modnef/modnef_torch/model_builder.py b/modneflib/modnef/modnef_torch/model_builder.py new file mode 100644 index 0000000..8e50060 --- /dev/null +++ b/modneflib/modnef/modnef_torch/model_builder.py @@ -0,0 +1,327 @@ +""" +File name: model +Author: Aurélie Saulquin +Version: 0.1.0 +License: GPL-3.0-or-later +Contact: aurelie.saulquin@univ-lille.fr +Dependencies: torch, snntorch, modnef.archbuilder, modnef_torch_neuron +Descriptions: ModNEF SNN Model +""" + +import modnef.modnef_torch.modnef_neurons as mn +import torch.nn as nn +import torch +from modnef.arch_builder import * +from modnef.modnef_driver import load_driver_from_yaml +from math import ceil, log +from snntorch.surrogate import fast_sigmoid +import json +from modnef.modnef_torch.model import ModNEFModel + +neuron_model = { + "blif" : mn.BLIF, + "rblif" : mn.RBLIF, + "slif" : mn.SLIF, + "rslif" : mn.RSLIF, + "shiftlif" : mn.ShiftLIF, + "rshiftlif" : mn.RShiftLIF +} + + +class ModNEFModelBuilder(ModNEFModel): + """ + ModNEF snntorhch model + + Attributes + ---------- + name : str + name of model + layers : torch.nn.ModuleDict + layers of model + mem : dict + membrane votlage memory of all layers + spk : dict + output spikes of all layers + configuration : dict + model configuration dictionary + driver : ModNEFDriver + ModNEF FPGA Driver + hardware_description : Dict + hardware description for VHDL generation + + Methods + ------- + build(configuration, spike_grad) + Build layers of model (call during initialization) + hardware_estimation() + Set hardware estimation flag + train() + Set neuron model for trainning + eval() + Set neuron model for evaluating + fpga_eval() + Set neuron model FPGA evaluation + init_mem() + Initialize layers memory + close_driver() + Close FPGA driver + forward(input_spikes) + Run layers upate + set_layer_hardware(config) + Set hardware description to all layers + to_vhdl() + Generate VHDL file of model + """ + + def __init__(self, + configuration, + spike_grad = fast_sigmoid(slope=25) + ): + """ + Initialize class + + Parameters + ---------- + configuration : dict + model configuraiton dictionnary + spike_grade : function + surrogate gradient + """ + + super().__init__() + + self.name = "MySNN" + + self.layers = nn.ModuleDict() + + self.mem = {} + self.spk = {} + + self.__input_size = -1 + self.__num_class = -1 + + if type(configuration) != dict: + configuration = json.load(open(configuration, 'r')) + + self.configuration = configuration + + + self.hardware_description = { + "clock_name" : "clock", + "clock_freq" : 125_000_000, + "baud_rate" : 921_600, + "txd" : "uart_txd", + "rxd" : "uart_rxd", + "queue_read_depth" : 4096, + "queue_write_depth" : 1024 + } + + self.build(configuration=self.configuration, spike_grad=spike_grad) + + def build(self, configuration, spike_grad): + """ + Build layers of model (call during initialization) + + Parameters + ---------- + configuration : dict + model configuraiton dictionnary + spike_grade : function + surrogate gradient + """ + + for key in configuration: + + if key == "name": + self.name = configuration[key] + elif key == "input": + self.__input_size = configuration[key] + elif key=="num_class": + self.__num_class = configuration[key] + elif key=="hardware": + for k in configuration[key]: + self.hardware_description[k] = configuration[key][k] + else: + layer_name = key + + self.mem[layer_name] = None + self.spk[layer_name] = None + + layer_config = configuration[key] + + layer_model = layer_config["model"].lower() + + if layer_model in neuron_model.keys(): + self.layers[layer_name] = neuron_model[layer_model].from_dict(layer_config, spike_grad) + else: + print(f"{layer_model} is unknow") + + + def init_mem(self): + """ + Initialize layers memory + """ + + for layer in self.layers: + self.spk[layer], self.mem[layer] = self.layers[layer].reset_mem() + + def close_driver(self): + """ + Close FPGA driver + """ + + if self.driver != None: + self.driver.close() + + def fpga_forward(self, input_spikes): + """ + Transmit input spike to FPGA + + Parameters + ---------- + input_spikes : Tensor + input spikes + + Returns + ------- + tuple of tensor + output_spike, None + """ + + def to_aer(input): + input = input.reshape(-1).to(torch.int32) + + aer = [] + for i in range(input.shape[0]): + for _ in range(input[i]): + aer.append(i) + + return aer + + if self.driver == None: + raise Exception("please open fpga driver before") + + batch_result = [] + + for sample in input_spikes: + sample_res = self.driver.run_sample(sample, to_aer, True, len(self.layers)) + batch_result.append([sample_res]) + + return torch.tensor(batch_result).permute(1, 0, 2), None + + + def software_forward(self, input_spikes): + """ + Run layers upate + + Parameters + ---------- + input_spikes : Tensor + input spikes + + Returns + ------- + tuple of tensor + output_spike, output_mem + """ + + self.init_mem() + + batch_size = input_spikes.shape[0] + n_steps = input_spikes.shape[1] + + spk_rec = [] + mem_rec = [] + + if self.hardware_estimation_flag: + spike_count = torch.zeros((batch_size), device=input_spikes.device) + + for step in range(n_steps): + last_layer = None + x = input_spikes[:,step].reshape(batch_size, -1) + + if self.hardware_estimation_flag: + spike_count += torch.sum(x, dim=1) + + for layer in self.layers: + if last_layer==None: + self.spk[layer], self.mem[layer] = self.layers[layer](input_=x, spk=self.spk[layer], mem=self.mem[layer]) + else: + self.spk[layer], self.mem[layer] = self.layers[layer](input_=self.spk[last_layer], spk=self.spk[layer], mem=self.mem[layer]) + last_layer = layer + + spk_rec.append(self.spk[last_layer]) + mem_rec.append(self.mem[last_layer]) + + if self.hardware_estimation_flag: + self.hardware_description["queue_read_depth"] = int(max(self.hardware_description["queue_read_depth"], torch.max(spike_count).item())) + self.hardware_description["queue_write_depth"] = int(max(self.hardware_description["queue_write_depth"], (n_steps+len(self.layers))*self.__num_class)) + + return torch.stack(spk_rec, dim=0), torch.stack(mem_rec, dim=0) + + def set_layer_hardware(self, config): + """ + Set hardware description to all layers + + Parameters + ---------- + config: dict + hardware configuration + """ + for k in config: + self.layers[k].set_hardware(config[k]) + + def to_vhdl(self, file_name=None, output_path = ".", driver_config_path = "./driver.yml"): + """ + Generate VHDL file of model + + Parameters + ---------- + file_name = None : str + VHDL file name + if default, file name is model name + output_path = "." : str + output file path + driver_config_path = "./driver.yml" : str + driver configuration file + """ + + if file_name==None: + file_name = f"{output_path}/{self.name}.vhd" + + builder = ModNEFBuilder(self.name, self.__input_size, self.__num_class) + + self.hardware_description["queue_read_depth"] += ceil(log(self.hardware_description["queue_read_depth"])/log(256)) + self.hardware_description["queue_write_depth"] += ceil(log(self.hardware_description["queue_write_depth"])/log(256)) + + self.hardware_description["queue_read_depth"] = 2**(ceil(log(self.hardware_description["queue_read_depth"])/log(2))) + self.hardware_description["queue_write_depth"] = 2**(ceil(log(self.hardware_description["queue_write_depth"])/log(2))) + + + uart = Uart_XStep( + name="uart", + input_layer_size=self.__input_size, + output_layer_size=self.__num_class, + clk_freq=self.hardware_description["clock_freq"], + baud_rate=self.hardware_description["baud_rate"], + queue_read_depth=self.hardware_description["queue_read_depth"], + queue_write_depth=self.hardware_description["queue_write_depth"], + tx_name=self.hardware_description["txd"], + rx_name=self.hardware_description["rxd"] + ) + + builder.add_module(uart) + builder.set_io(uart) + + last_module = uart + + for layer in self.layers: + module = self.layers[layer].get_builder_module(layer, output_path) + builder.add_module(module) + builder.add_link(last_module, module) + last_module = module + + builder.add_link(last_module, uart) + + builder.get_driver_yaml(f"{output_path}/{driver_config_path}") + builder.to_vhdl(file_name, self.hardware_description["clock_name"]) \ No newline at end of file diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/__pycache__/modnef_torch_neuron.cpython-310.pyc b/modneflib/modnef/modnef_torch/modnef_neurons/__pycache__/modnef_torch_neuron.cpython-310.pyc index c3dbe4e4212a44871a1e6d5e960688f70786b897..895a5aacc1efbab760c5e04db68a67bb7652872b 100644 GIT binary patch delta 1225 zcmaDa^;M29pO=@5fq{XczU@f52G2&m8H|h_lb17E2c>dlai=k*@TBmzFh=pD$foe6 z@V78V@utY82&4$MFh=pE$fXFU@~4QT@~5$+h^C0Outo`_h^GpsF{MbPNVc#<38hG- zNVhOV38%;eGib_hmSEb(6y(9cz>vaN!w?T48B3TJFqbebU@2kBVqM6X#kLS6$Brh- z0T$)VWT;_?=c)mz;7(x(X3%8vbJOIREX69#Ay`<Nm{*cnHCc<bm{DZ%Jl1M99tH*m zHpa=aY>TBt7#J9ez=S9R1H&!Ow4(gn_>|1#5{t>V*lZZZCyTQu>PRp!Fsx)O5{9cq zXyAvMo*G}Cnwg$a;xKs$yAz}M<mc>WdLV5@vRE_;!!;Eo7A5AUmZTOHdr$V}(1~$N zW(I{h6oc4|3=9m;ATz`n7#K7es}^u6C@3fdLj07fP+XapSWuFgtN^iIAu%sSAuqMG zC_hgjqp~2iNEczl<V~C^^(iHl1*r<Q3MKhP$r*Z?c_qe13RVhWQLw=Z3Sb4L#i<G@ zrA3)}=?YM{CYEI8=Yf?Jf&8V(3=WQ4Txt15$*J*~d6^}*Si#0XLK6`}98d#NgBTbX zIE$G;Vb4`1I(Y-TXnit>2lXrihz-IZ-xh<C9ymG~z|qO*r^#5v35o_Lh`lVi`6;RB zR&f@mmc)ati(_D509(bySS9A0pW^50<_8WHJ-Cu&CI%yz)eK<ELBS2ST!w*x0b+R# zV-Zgc!ve+{#)XWG3@MDkljm_*%P<vjfMP@qM5urWuy4VH=;RL^5`rlp>p^PRSXr3( z7+L;L7Uqm(6rY^S`Nk3{^ole=nzcX#STmRar$eFi)ROq5(#)Kc)S~#@{FKt1)V#@) zxTYBjfl>h^?2B|jDV8xCJrsCAUd%`=N-0k)N^O`N$vsm?7i0ytl*j|J2d1_Iq)L9W z9FHQGn<itC2FNOr$!<KB^<p5KxRY}di;HtpOEU6Pia<eBBnQ%<03txqb&D08oQjk| z0^qPw2Wew2E-5O~28l_72z?M?03yJ?MGzo=7qKxgFo1-Lr5G3(I2c$M`6QUQx#Sr+ q*g3cb*tvMP*hIMagm^f>3N<;3Oh5*4O=jjb698#L4vNX1ylMcZ0Sb!% delta 781 zcmew=_g;!GpO=@5fq{Wxjmm-a46coQGZ-0jCNF2SHcR1YVTj^Nkx1c7<xb&G<xXQs z5l9hiVU6NR5lZDvV@eTD5ouwG;!6=t5o=+H;!hC|X3&(}Y{ImS$;XL-fgy#lh9RDz zgmD2=3F89h62>f+g^XFO3qhi6Xrk<3QI1T88ishz8juRE6oz01O(s7#P43AytkRRS zSTh)fCtqf*W&t^NatPaEDPaZ%h9WQ_!oa|Ai!-e#KQ}%lGr7ckvLL$+qu69W_Cy_V z1_p+ej736lwFnLTg{6skC7D&J@#U$R=@}*VlW(&-F^Wx=<1o_$X)BV!qDdI8sUWc^ zF*mg&wW!!@aubJ+dNLy@6rmWzW@2DqaAsg&DCT2eV5nipV&DOJZ*mQnwH0F#2gq!! z7GxwArIaTYrN*Zgmt^K9mSpDV1%gZg8OO&u`43klquAsy?l+boH)=9Nyru*)P8mdi z{RbvQK%pX(o>~&0RGOKSl3Em>o1apelNvF(nrE7!AOiyfOt&gXC1W-uFcErric?GC zVa~~#?8G}$M-5~JHfQsI?18B*0;!Ul%+9CCUZe=JM_{rMpJlx$$QthCoW$bd+|-hc z{FEYTkV07yArB%HKnj?PONxqAKwK#hp#dT^K?K-g2m<82A~psF1`wlIjDdlHgMo#S uPlAbyi;;t!gPVh0gq=@_hXbrelcPwN6=VqKWKMoF0fZ@FmdIp(el-AP>!Dfz diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/__pycache__/blif.cpython-310.pyc b/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/__pycache__/blif.cpython-310.pyc index db3f256ec621749ba0f90484169a3275e89add61..0da4515400f65ec51a49a88e508075b209f54f51 100644 GIT binary patch delta 654 zcmaFpe$j(BpO=@5fq{WxMd*?AO&fWQnHbkhc4YG6R!R{_5o}?M;!aVXJdH_DFGV_) zFN;5oDMcnlwuLcDD3vWmE=9hDp_wsCIF&6$Aw?0)7D-_aX3$jG{DEnMpf`Wfv=WvD z0w7$&xIkbbLk&X~1BhP8RKt)Z2qNPJOIQ{Nfp87u0wJghp@j?}xh!E2882MJus~$< zYY{s}M$ySyVrm?Mg{6skC7D%|<HgJ;2Z%{-o+`%9tQf?=z@RBwq|U&=P~-t3ycrl6 zZZRh&6&Lw{xL%X@N|tj6f|wwsMLwJDrFs|{6E>fbj%HLz0g0!A2vrb~03!H7ge!>P z0}*MHH!2EGj+3>IbxURj1sN2B*dXl8z`#&!#lXN&!&uA)@@W=hF&~It0P-z!7Ry3L zMur-O1*|npP!=16mBLuV5YL{%6wIK>T(w~GSvJ|pUu2sn%gS<@V{=vp$T689!Ug1I z<|1B@N4e7Si;`30GxIV_iqgR@ohio$j#?fr0Y)w+E=I1+>*Sgk8Iv~~Dg-g=<$w&x z1rd25A|FI>f(T0xVFx12L4+-cD4e`eQGqdc@+Czh#(>GJN^u7MAUm0hONxq;K?*>c zZn0+Ol^7cpA>5Y@k}3ufC6gyBxe5yiFbQ%oGI8=T7J;nN6e_Bi{8}lBF=n!x@@xPn C1(kCE delta 562 zcmccU@z9+&pO=@5fq{Wxzukd!@r}I3OpL20J2H83E2apf2(~arai=Ivp2no7lggLH zpT?LXog&l17$ua-mLi)X*TT@u7$uy_mLi{`0A`D%Fb6YeDsTS8v_a6Dy=Ynq%L0B7 zu3=ojzmTDZA&UV-FJ!7=$PxgN@d70*3j{&9hH-%)RE6L|29R8q5QvNys$p0ly!ow& z9V4U2WF0ZJ$rHsSC#Q(%ZeA_M#;h2~z`&p>TBOdvz)<7@BD@$F7;Z5qCKVTXgSeiP zFG-ej2Y{F$rA6MGL!^2b8RIuUl#XUpNd}3hfCyC(5f38xL4+%a-~$n<lNFVOCl|}w zTO>1qf(eR2Y-R=q24@BahGGc@28J4j1q?Ne3mF+fEJg?`g)x{xlW8)q+#-HIO{SuB zka-y(0&J)#M`3AVUP)$EY7ip>Loo{j0|OTq-)1@aCXo9UDg-g=Wq}lDgNPgukqaU? zL4+lUumch1Ai@?z<WE*qQee!S?4)GG=s&qsDbBzT92UhTMMX&<1t3kgSTplVjE#`o sk_nP31QA7(nU!6I`2?7Fxfq!^`522pR%r?ql}(OTj$(|SyiIvF0PNy?ga7~l diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/__pycache__/rblif.cpython-310.pyc b/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/__pycache__/rblif.cpython-310.pyc index 54b42d98c6799fa9d9b1117e5317ff4c885c47a4..ce3b0d27934dac2dfcd67a029307b2f42181b0e5 100644 GIT binary patch delta 619 zcmeD4?)2fy=jG*MU|?Wa6nZ3mspdvLdnU#;ll_>yxRp`_QUqHVqqtL)Cog8w(@T*~ z<;&tvV@i=pk!@j&5=v!DkxP+pVQ6NI5>91HQAkk)vqe&vgBdhcHveV1C*&<qw6la| zfglLiFfI^W$WX(O#Q>rgGSx6-34zFXp%Rt_!XRA3xIh@HLU<tqNG?kRM8=EMFf0(= ztR`m1$S5{BRos?Cu&^{SuOzc-@<wsh$&17#H(wPuU{(xeU|`S`E7D|OU?}ne5xxuz z47ZpQlZuP{KwO{6YSN9|As{A5X_4RNP15Tb8Iw0B$!0QYrh~*YK!h5INCpw=Ac7x6 zc!CH%5Rp0gi(Ig_TQV~!(4ZK^W?^7paAsg&D0X0AV5ng%W&?ROi?LX6a<q)3EL#oJ zLPkc08iobz5LOCf4MRLf3R5tHCiCQa`9*Faewv&`(jXgfx+EJUn*$;|Kwf1o;stq- zD=oh$IW;~rFSDd5YqEiYA~-&IxWpK_n7A0ZHb*ElGcp!!zM~k-D3A}*TmT{pK}6AH zdu3V1lF6~k3XC<A>y(WdgC}oNjxz`Xnaf;UQdE=%Qf3X}vS#L$7#kHK+>i&7DgzPa llO0rCg#`qd1i2WQIQbZhI6=-6Dyp75L&b|Re)40L)c`@)jY|Lk delta 511 zcmeD5>GS5x=jG*MU|?X7v_FvkUSlJlJrm=q$$m^;+=?jzDS|DGQQRp?lNU4T>7?>y z@uxASNT<lOFh&WbvZctT$h9yuGe!xgvZctUD1g}_Da^qPn#!C1Gu;#N<|^7*!m>aB zgliZV2rOi%VaQ?t(F>Vs7_tOGWV~Pr%K{+~u3=mt1XUrlkO3r@B@80tg=-iVh-}sn zvtwiwot!RiJNcrx<m7GQ(wkq4>oY5cFfcG^iWO-xFfbH(fCwK328LVAiAlvpz96pm zWNYb0?qCoTq_oI)^Kt3*jEqT}%Vjee1=2v`=^#Q4L?liAASc0?F_}|7*dmz;6e>^* zVly)^FgP<XFceELFfi0GEMTZ%T*$}>VlhHkDU87knoN`T$}i&g(_|{j0-2Z%A~Ggl zP!*ZHQ-PPAg@J*Ai;HjbWrb!&#=OnpO2Lc*xgaHZAR-?`6inWwEX!Cl`G&FrW5wj3 z%EpXAlXX?%3<AOaDlRE1N(Cvi260(4^Gb}3kZj5UNtJ+z(#gA3T!r}rn0UDunK=0v Wi#S06B~(;7Sy<JJF>Z34>S_S9%z5Vk diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/blif.py b/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/blif.py index 5398751..653e417 100644 --- a/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/blif.py +++ b/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/blif.py @@ -239,7 +239,7 @@ class BLIF(Leaky, ModNEFNeuron): if not self.mem.shape == input_.shape: self.mem = torch.zeros_like(input_, device=self.mem.device) - if self.hardware_estimation_flag: + if self.quantization_flag: input_.data = self.quantizer(input_.data, True) self.mem.data = self.quantizer(self.mem.data, True) @@ -335,7 +335,7 @@ class BLIF(Leaky, ModNEFNeuron): self.threshold.data = self.quantizer(self.threshold.data, True, dtype) self.beta.data = self.quantizer(self.beta.data, True, dtype) - def quantize(self, dtype=torch.int32): + def quantize(self, force_init=False, dtype=torch.int32): """ Quantize synaptic weight and neuron hyper-parameters @@ -345,8 +345,12 @@ class BLIF(Leaky, ModNEFNeuron): type use during quantization """ + if force_init or not self.quantizer.is_initialize: + self.quantizer.init_from_weight(self.fc.weight) + self.quantize_weight(dtype) self.quantize_parameters(dtype) + self.quantization_flag = True @classmethod def detach_hidden(cls): diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/rblif.py b/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/rblif.py index 96c150c..4476356 100644 --- a/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/rblif.py +++ b/modneflib/modnef/modnef_torch/modnef_neurons/blif_model/rblif.py @@ -253,7 +253,7 @@ class RBLIF(Leaky, ModNEFNeuron): rec = self.reccurent(self.spk) - if self.hardware_estimation_flag: + if self.quantization_flag: self.mem.data = self.quantizer(self.mem.data, True) input_.data = self.quantizer(input_.data, True) rec.data = self.quantizer(rec.data, True) @@ -350,7 +350,7 @@ class RBLIF(Leaky, ModNEFNeuron): self.threshold.data = self.quantizer(self.threshold.data, True, dtype) self.beta.data = self.quantizer(self.beta.data, True, dtype) - def quantize(self, dtype=torch.int32): + def quantize(self, force_init=False, dtype=torch.int32): """ Quantize synaptic weight and neuron hyper-parameters @@ -359,9 +359,13 @@ class RBLIF(Leaky, ModNEFNeuron): dtype = torch.int32 : dtype type use during quantization """ + + if force_init or not self.quantizer.is_initialize: + self.quantizer.init_from_weight(self.fc.weight, self.reccurent.weight) self.quantize_weight(dtype) self.quantize_parameters(dtype) + self.quantization_flag = True @classmethod def detach_hidden(cls): diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/modnef_torch_neuron.py b/modneflib/modnef/modnef_torch/modnef_neurons/modnef_torch_neuron.py index c394271..dbfb48a 100644 --- a/modneflib/modnef/modnef_torch/modnef_neurons/modnef_torch_neuron.py +++ b/modneflib/modnef/modnef_torch/modnef_neurons/modnef_torch_neuron.py @@ -44,6 +44,7 @@ class ModNEFNeuron(): def __init__(self, quantizer : Quantizer): self.hardware_estimation_flag = False + self.quantization_flag = False self.val_min = torch.as_tensor(torch.finfo(torch.float32).max) self.val_max = torch.as_tensor(torch.finfo(torch.float32).min) @@ -78,12 +79,33 @@ class ModNEFNeuron(): raise NotImplementedError() - def hardware_estimation(self): + def quantize(self, force_init=False, dtype=torch.int32): + """ + Quantize synaptic weight and neuron hyper-parameters + + Parameters + ---------- + dtype = torch.int32 : dtype + type use during quantization + """ + + raise NotImplementedError() + + def set_quant(self, mode=False): + self.quantization_flag = mode + + # if mode: + # self.quantize(False) + + def hardware_estimation(self, mode = False): """ Toggle hardware estimation calculation """ - self.hardware_estimation_flag = not self.hardware_estimation_flag + self.hardware_estimation_flag = mode + + if mode: + self.set_quant(mode) def get_builder_module(self, module_name : str, output_path : str = "."): """ diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/__pycache__/rslif.cpython-310.pyc b/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/__pycache__/rslif.cpython-310.pyc index 1c2bb1928e74bd03a4756bfe3f1dd202bdc63a1c..c689156476790470b9b7d39d1f684d72cbc014cc 100644 GIT binary patch delta 730 zcmX@=cfg-7pO=@5fq{WxR_Kv*ADxYS!Ay*6CMPj@aVw_qrwFt#MscSoP2SF=r<Wp? z%9q8T#*`wRBGbYcC6vmRBAX)D!qChZC7jBZBA=oFW{adS2Qz3YZx&>35U%GdYAaz` zzz@PTj0^Y|GSo0+F@WfWOf?Ky0w6M8poC?CAPCnmE)ayO5M0OrlFJeTk?}$xT{R3@ z!V(NM4Dk##3=2d+A`2O77~&ag7_vZER2pP9rvyVSD@d+}AxkWqfo*|!2}_p5W-;*y zMn=iW`4UbXf`z4tc_o=ulMhIUPTn9Pz4@9%6SHC*0|SGmc#$Ck14B^&hzMd}V7SGc zm{eR84B`e(u9Ruxjs-D6N{fOwbIG<bGUiO4C}+=@v-zT252IWG0|P^dpC)&aG)P$y zh$sdTdLSZaa<zgIW69(~QQ^rO6<iYCl9@q)4#glg3j+g#GXn!du>%7GLk(jw8^{}3 zjKzW=dI2c7n6p@F7_wNiSQaudf&zi9hG`)qn8glZrGNs2BZVoLL6dp1uHquM5I;>$ z?9KtXNgqU%frxSt;Rgx><|1B@&$-g_i;`30GxIV_ib_F_mgazlTWTpI14A(=#qe;6 zF>*0+F>-BYQ)*^pY}?$W9L^|E1v07{MAU$Y+Q}bPWEty0M)2_zr52}_#Ajrtq@?Ce zm~5bG%osB{MK#VK8e}DNaY<28K1h!Sh|8LpS7K~bgm7LZNU9M;G)?}b>MATC#3abY b$i&IVSOjv7rf^Z)WG^)@#*E2R)iwYC$D6Eo delta 611 zcmX@$f7FjJpO=@5fq{YHko|%5Y1$k4f|(dsO-^F+;#NrEPZ4NgjN(pFoV=Y$PbZZx zi$9GqMJh$Qg)vGfl`TakMYe^ZnK4Q@l`TasMIOu+Nns9V&{Wzi%-kSc&t243!m@x5 zgliZV@GWGhVaQ?t(F>Vs7_#_5WITTf%K`xqu3=mt097HdkO3r@B?uzp1wp!M7_x*U z7-|^e8EP072!lixGS)D}GuAL<fv|`)$ZSpthFVsTTn$5(Xf^}e0<jX7Eb+|};t`CD z5|axhoF-qCkm8bNU|_h#l9E`GxcQYtGqYkW0|SGmc#$Ck14EG?hzJBJU`|XbE(!v1 z119&$v~kCPm>{J^L7U}e+ZY+MCohw;XUyLGOs<DfE}wycA;eFUy9i`>Q6Wfe5s1(O z5!sU`C@3)&Po5|uJo%V{i&ZicD7>K<#Aaq-U~pz&U?`SgU;z1#p@wlGBO{2#2w|l# z1~X_fRV|n-Cnr0(OR<^XPm`&r6l8W8h=3TKro_k2!oa}5#l^R|QK^}cv1v1_N;soH z1xQIHh^PV))su5nWf^P1u9>UK%h)q{wW={=^yK@haRyOfpBI-D73G1HYJj+`nRz9~ vMo6}mgQV&~M8o7<HCJIiAtqifMkY=^#v)Kc(iARgnS4~ui!pt&fcgdi@vxBX diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/__pycache__/slif.cpython-310.pyc b/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/__pycache__/slif.cpython-310.pyc index b2b7a8f662dd25e520f374167f6a5c09dda32334..56a8d34cf4cbbbb57ba5f63a00f4e82af30ca69b 100644 GIT binary patch delta 716 zcmZ4IGtZYdpO=@5fq{Wxa_Eut>l=AJm>Abg4rB7-R!ref5olqI;!aVTyqZZ*FGVVq zFN;5oDMdO(riC#|D3vWmHbt(5p_wsCIF&6$K1Bh{7D-_aX3$jL%*xCnT+dUKRl>4> z7ldmV7w|4*sA0%r0MQGXY8bNkKx8~$3CjY05Uycdzz<cyzmNeWmn8rq;{`yvY8bKv zB^YWL;u&ff76^ev7Bbc{*D%*GWC=@y%;lC~sAU0(*Dz#>WHT%fEn#8G65HG*7RJaZ zKKY@z8i!zEX<}YUX4Pad33aJk5*dj_DdmYpsqv}BC7HR2C7Jno@o71U>6>jOLYNh! z85kHe#ftP97#NEDKtuoo1H&!m#H8Y)KoHk|@+RpT?kErwq_ik-v!zTjBV*>|xw6KL znVT=l)-lTEGB7ZN_-S$#NrRN-frxw%p$j51C+Et`G8RnkmJf?{OJ)W|0ThGSAneS* zz))<(z`#($Sj-0USr%h4ABbK63O(j5mW7OrpwM8gVS=*QAgmO|8isiG6sBMXP3Ecv zlWW;!CtD~qJBIjaa$t7~$UQ|Mq8LPYfxOOK#0&B;S6Y5ia%y~LUS>&A;p9^air~b; z!zIAT#l*$PwfU1m6C-2w=2E3FMu9Sr=5i2G0U|0V-&U4ote*T+S%I;2vXqJuW8`FC zl{kY4kh#poB}GL!AZ6+xE^B69iLp@;!VRS$sag<GH~E9A_~cJ2dcp!iOhR0YOq_g- WMW7U`DO}Vv*;v(!F?DjC>IMJ{0jsqD delta 621 zcmbQ|yUvF<pO=@5fq{WR(&0e5%|>1iCdO5h!<f9d6;k+91X>uQxKk7-uV&KIN#)Dp zPh(7xN|A11j1o#^OOZ*DZDD9;j1o>|OOZ>F2eU;|n1dNKl{T|8vk2F-7iE>OEZ_m* z8pZ`Y3mIw{vKT=0LZ%vqEM5>9&s)N>fDeRg7#HwCRq!oj0Lf+XgUEP(kgghrECC6I z8isg=8ioaeAd!WPwahilH4Iro(jarWB^YX1K;ktFS;E;23q(p-n6gAS_lSitGKx)p zEUv~ck&#%GQl40p8lPHRl9@YMP(pokkVFWxViW@dgQi%KJ_7?okr#;YXJBBs#hjQ_ zToeG}`b|DAUBev-VuF+w1#I?{NoHisn7m2Wm@#AXGub*un;ZrPh7dnZt|DoWvRn|6 z2O@MqL<WeE0TJFHLKZ~Gfe3yOkw1BXe3(Tt6DSU#7{q2~U|?`&U|=YgU|;}wnxTeq zAtNJ*#Ry@gFa|SdGEELtSj6wA$y8JbGOGwg<WDwHRAgsiU|`_l;@h00*u=<KzWJ$A z7^6T5NV*h6l!1uy$=)imjFpo!RTLN-CwHkBF-A<@s}g4r4)%X>Nl{TYNSQi_%bJ;2 zVr+zDOEE~Q8bs7gPEZq{oTREJ%qPUe$HmCR$;Vg(N>ZA_MGcb|t9mh}On#@j0RRi- Bjo$zO diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/rslif.py b/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/rslif.py index cdbbc04..fd5b994 100644 --- a/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/rslif.py +++ b/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/rslif.py @@ -267,7 +267,7 @@ class RSLIF(LIF, ModNEFNeuron): rec_input = self.reccurent(self.spk) - if self.hardware_estimation_flag: + if self.quantization_flag: input_.data = self.quantizer(input_.data, True) rec_input.data = self.quantizer(rec_input.data, True) self.mem = self.quantizer(self.mem.data, True) @@ -370,7 +370,7 @@ class RSLIF(LIF, ModNEFNeuron): self.v_rest.data = self.quantizer(self.v_rest.data, True, dtype) self.threshold.data = self.quantizer(self.threshold, True, dtype) - def quantize(self, dtype=torch.int32): + def quantize(self, force_init=False, dtype=torch.int32): """ Quantize synaptic weight and neuron hyper-parameters @@ -379,9 +379,13 @@ class RSLIF(LIF, ModNEFNeuron): dtype = torch.int32 : dtype type use during quantization """ + + if force_init or not self.quantizer.is_initialize: + self.quantizer.init_from_weight(self.fc.weight, self.reccurent.weight) self.quantize_weight(dtype) self.quantize_parameters(dtype) + self.quantization_flag = True @classmethod def detach_hidden(cls): diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/slif.py b/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/slif.py index 71e3ac1..a7b89eb 100644 --- a/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/slif.py +++ b/modneflib/modnef/modnef_torch/modnef_neurons/slif_model/slif.py @@ -256,7 +256,7 @@ class SLIF(LIF, ModNEFNeuron): if not self.mem.shape == input_.shape: self.mem = torch.ones_like(input_)*self.v_rest - if self.hardware_estimation_flag: + if self.quantization_flag: input_.data = self.quantizer(input_.data, True) self.mem.data = self.quantizer(self.mem.data, True) @@ -358,7 +358,7 @@ class SLIF(LIF, ModNEFNeuron): self.v_rest.data = self.quantizer(self.v_rest.data, True, dtype) self.threshold.data = self.quantizer(self.threshold, True, dtype) - def quantize(self, dtype=torch.int32): + def quantize(self, force_init=False, dtype=torch.int32): """ Quantize synaptic weight and neuron hyper-parameters @@ -368,8 +368,12 @@ class SLIF(LIF, ModNEFNeuron): type use during quantization """ + if force_init or not self.quantizer.is_initialize: + self.quantizer.init_from_weight(self.fc.weight) + self.quantize_weight(dtype) self.quantize_parameters(dtype) + self.quantization_flag = True @classmethod diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/__pycache__/rshiftlif.cpython-310.pyc b/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/__pycache__/rshiftlif.cpython-310.pyc index b895a0cb0c7fb3bd699e0fddcc66c8e3c6011f4b..fc3997c992141b7289ae5141eb50036c7311aa12 100644 GIT binary patch delta 690 zcmbOlFd>jPpO=@5fq{YHVCa$be;av|m>9QAE?^4cR!I>`5pH3O;z?1Re3nU1FGV($ zKT9BuDMc<tzJ)PLIF&6$Aw{u;p_wsCB$X{iDMcB~7ENIeX3$jItj@e!#9Odve+kP1 zArP)%Tp+ZNp@t!g0Yooks$s|y29fc?B`ga>K)8l+fe2KE$U+8?T$U(^j2Eq8SRl4p zSHg~wQG9Zaq%DVFVQFGsNoLjL9g-G|5|afvgjwU$auU-wzn6?;R*Yw0V9*pR(qmv? zC<*});S3B6x0n-?ii;vZ+_1@+vaQ^4ASOs@QN-q-vK@?!d6S#u?HThnACgaFG%sRc zU<mQk<Sdc}DJuaHr658ZMC5@89S|W1B7#7K0Ej4?9IqIj=$6b33Qs5ou~`@x7@Qdx z7>XSj7#M08i`hWIki}Rm2%;B&f`U1VrG_DkHH&2-6C*<n!veM%riF}P7CVHM!dSx) z&ym6u%%I6U`JLh-HzHhD0di9%hzJA)33CxYC?L4f@{5vF<1_OzONz=T&sS0eM?Vjj z7$X-G7bDl^<4Wy}j4hk}Rl*tdYCxK6K|~#hs0R_C#8PArV!40_TMz;ATv6lXE2;{N zeUrbcnlr{u)>TV3hymHhTwGFAR0vW9(sYY8Gq1$hs0iV<YLHYjh-jI7K+RoPK!8b* bi;;<wkFf}3m8Nh}$7CsWFUG9Nsp=a51U{ZY delta 551 zcmbObI5mJbpO=@5fq{Xc!{I=>$41^HCdN&Z3z&kql~aULgj*P+cv4g*pJme1N#)NH zNMlTqO_6J1j1o>|OOa1eXkln(j1oy@OHoWw0<%R^n1dNKRX1xg?-udqD%xMdvOo}o zYZw;@E@Y@-$YKD|3z=#dvV=fnyif_t0$~uYVO$^#RUy2P0VJ0t0wUu@Y8V!XZq}Eu zV`LPYoF{2J`L(3v<h_!5n^~nIm=)s~7#K9giu4#57>WWxL>L1D!!72-q~fA*5I1yk zoop+2EQkqGS`@ySPp*TJF?aHGd3(m(&DZ7A7|jbA7#KqQG&zf8LCT6jL<xw{1`)X+ zLI*?$f`}jxApjyuCzmLOTO~7r!VZc-Y-R=q24@BahGGc@28J4j1q?Ne3mF+fEJg?` zg)x{xlc{RKWPW+s$=*uM{C=8DMdct9D?mi)WD#XWb`}N(1}-kX%}&bgjEoJNPpO16 z3RHolt3gB!h^U=xs3yx;KiOYRfw60HftopE%;Xhn$p+Ej04OdgDk=aevj=fmGxJJ} vjgV}q1W7f5h^EQb>h8jP0!+MIj7*$-j76ZtpebC`HhHSL7h~q+2kILDqLP06 diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/__pycache__/shiftlif.cpython-310.pyc b/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/__pycache__/shiftlif.cpython-310.pyc index 51207de58951388697859e3db0354711ffcf5ca0..70eb665a7242039cc59cb7aeb23a76d5ccffe1f7 100644 GIT binary patch delta 674 zcmdntv%;4*pO=@5fq{YHV(5|dQyY21m>9QAPGJh-R!I>`5pH3O;z?1Re2_^`FGV($ zKT9BuDMc<tzJ)PLIF&6$Aw{u;p_wsCB$X{iDMcB~7ENIeX3$jIEX~|2?9E@au!LoS z00`GGE)ZDAP{WYL0HPN%)i7iUg2;Hm5|#x*AY8+^KnSWrXdwegE=w3h#tYXlED+iJ zS<H@+QFOAAgawCSVQFGsNoLjLN(m!LiHyXel=8%))cDlmlFZ!1lFa<P__UnF^v$az z1eq0M7#J8dMT>M87#NCzKtw151H&!m#H8Y)Fc3Fn@*U}F?r0Dbq_ik(bCOIdBV*R& z6SBsPS)2dJMlc%XF)%QM_-S$!$%2&SgNOnUp#>tcK!hNO2mlcRAfj+`n|xTTTQV~! zV4)bq24QCg28LoQ1_p*2#$q;5cw{ja^MU9EpfF+1Vp+(@$WX(ufVGAR%3_1CQW$F( z;@MM}f*CZKs}@Xlkd>Xhf?alUfI^xhe#aGqoKylL{6T@iT*MCw0<N_DqU6;0%)HE! zqN2%16%@hAfQL(fk&B6ok!$l?g*HaUlFcPbVT=OhAk7sZq7p<@O}?cp%UCn{hq3}= z-DF7>GsdXN0V>G`ksx!Ki%W`%azV;$L0s0%yb@!hB7_^tKvH!eqJHvY6?b6)0VY8% bMkY=^#v)KU)D$jio@}e?#h5m^Lv;fHxzM5z delta 552 zcmZ4CyTgY!pO=@5fq{X+x9LE-_D0??CdN&ZQ<#Fdl~aULgj*P+cv4g*A7s+gN#)NH zNMlTqO_6J1j1o>|OOa1eXkln(j1oy@OHoWw0<%R^n1dNKRX58r_X>M+7A-7cS-=m% zHH-`R7c$f^WHEr~g-kUJSppz3UZ8|!fglLiFfI^;st{br0FuiR0+I1TH4F=cH-8ng zV`LPWY$9R7FOiX0lv18plp3E}T#}hPxkSQf^8pC~X2oa*1_n*hA{_<>h9Z9u5yHU0 zaEm!HskkT<#0{SOQM#Ht3d95{EehRSE|bd0m^t~btTAKeW<j|KMx$H?28IwnO^za2 zkg_}wkq;uYKtv{p5CjncAVL5{6il8iA7+uv1PVeZ2C<nL7#N%x7#NBr7#J987#1+p zFfL?d1hE()tQ5vz22G~PJ_?KY{WO`1ia=%+gNTC3`ihF|EDQ_`TwHvcV-?#N84ET) zQ3_)eC<RHEfrxStQ8C#|MV7H@a)ycmW7XtN6*I=j$p=)D4I;q4E-oo5$^j{}1#ww3 y^Gb}3kZdUdN!5Ue+R4GH?!tTmOuSr-Oq_g-MWEE6DO}Vzd9A7!W9sA|sv7|FK!IEU diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/rshiftlif.py b/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/rshiftlif.py index 85eba37..1def1cd 100644 --- a/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/rshiftlif.py +++ b/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/rshiftlif.py @@ -268,7 +268,7 @@ class RShiftLIF(LIF, ModNEFNeuron): rec_input = self.reccurent(self.spk) - if self.hardware_estimation_flag: + if self.quantization_flag: self.mem.data = self.quantizer(self.mem.data, True) input_.data = self.quantizer(input_.data, True) rec_input.data = self.quantizer(rec_input.data, True) @@ -368,7 +368,7 @@ class RShiftLIF(LIF, ModNEFNeuron): self.threshold.data = self.quantizer(self.threshold.data, True, dtype) self.beta.data = self.quantizer(self.beta.data, True, dtype) - def quantize(self, dtype=torch.int32): + def quantize(self, force_init=False, dtype=torch.int32): """ Quantize synaptic weight and neuron hyper-parameters @@ -377,9 +377,13 @@ class RShiftLIF(LIF, ModNEFNeuron): dtype = torch.int32 : dtype type use during quantization """ + + if force_init or not self.quantizer.is_initialize: + self.quantizer.init_from_weight(self.fc.weight, self.reccurent.weight) self.quantize_weight(dtype) self.quantize_parameters(dtype) + self.quantization_flag = True @classmethod def detach_hidden(cls): diff --git a/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/shiftlif.py b/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/shiftlif.py index 621a360..c798c99 100644 --- a/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/shiftlif.py +++ b/modneflib/modnef/modnef_torch/modnef_neurons/srlif_model/shiftlif.py @@ -256,7 +256,7 @@ class ShiftLIF(LIF, ModNEFNeuron): self.reset = self.mem_reset(self.mem) - if self.hardware_estimation_flag: + if self.quantization_flag: self.mem.data = self.quantizer(self.mem.data, True) input_.data = self.quantizer(input_.data, True) @@ -352,7 +352,7 @@ class ShiftLIF(LIF, ModNEFNeuron): self.threshold.data = self.quantizer(self.threshold.data, True, dtype) self.beta.data = self.quantizer(self.beta.data, True, dtype) - def quantize(self, dtype=torch.int32): + def quantize(self, force_init=False, dtype=torch.int32): """ Quantize synaptic weight and neuron hyper-parameters @@ -361,9 +361,13 @@ class ShiftLIF(LIF, ModNEFNeuron): dtype = torch.int32 : dtype type use during quantization """ + + if force_init or not self.quantizer.is_initialize: + self.quantizer.init_from_weight(self.fc.weight) self.quantize_weight(dtype) self.quantize_parameters(dtype) + self.quantization_flag = True @classmethod def detach_hidden(cls): diff --git a/modneflib/modnef/modnef_torch/trainer.py b/modneflib/modnef/modnef_torch/trainer.py index 244b6bd..7fb4704 100644 --- a/modneflib/modnef/modnef_torch/trainer.py +++ b/modneflib/modnef/modnef_torch/trainer.py @@ -13,6 +13,7 @@ from snntorch import surrogate import torch spike_grad = surrogate.fast_sigmoid(slope=25) from tqdm import tqdm +from .model_builder import ModNEFModelBuilder from .model import ModNEFModel import numpy as np @@ -77,7 +78,7 @@ class ModNEFTrainer(): """ if type(model) != ModNEFModel: - self.model = ModNEFModel(model) + self.model = ModNEFModelBuilder(model) else: self.model = model @@ -262,6 +263,11 @@ class ModNEFTrainer(): if self.verbose: loader.set_postfix_str(f"Accuracy : {np.mean(correct/total*100):0<3.2f}") + del data + del target + del spk_rec + del mem_rec + y_true = torch.stack(y_true).reshape(-1) y_pred = torch.stack(y_pred).reshape(-1) diff --git a/modneflib/modnef/quantizer/quantizer.py b/modneflib/modnef/quantizer/quantizer.py index 275ca29..898ec98 100644 --- a/modneflib/modnef/quantizer/quantizer.py +++ b/modneflib/modnef/quantizer/quantizer.py @@ -86,7 +86,7 @@ class Quantizer(): raise NotImplementedError() - def __call__(self, data, unscale=False, dtype=torch.int32): + def __call__(self, data, unscale=False, dtype=torch.int16): """ Call quantization function diff --git a/modneflib/modnef/templates/evaluation.py b/modneflib/modnef/templates/evaluation.py new file mode 100644 index 0000000..40d7147 --- /dev/null +++ b/modneflib/modnef/templates/evaluation.py @@ -0,0 +1,98 @@ +import tonic +from torch.utils.data import DataLoader +from modnef.modnef_torch import ModNEFModelBuilder +import os +from snntorch.surrogate import fast_sigmoid +from run_lib import * +import sys + +if __name__ == "__main__": + + """Experience name""" + exp_name = "Evaluation" + + """Model definition""" + model_path = "model_template.json" + best_model_name = "best_model" + + model = ModNEFModelBuilder(model_path, spike_grad=fast_sigmoid(slope=25)) + + model.load_state_dict(torch.load(best_model_name)) + + + """Kind of run + eval : full precision evaluation + qeval : quantized evaluation + heval : hardware estimation evaluation + feval : FPGA eval + """ + + kind = sys.argv[1] + + """Device definition""" + device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") + + """Evaluation variable definition""" + verbose = True + save_conf_matrix = False + output_path = "." + + """Output variable definition""" + acc = 0.0 + y_true = None + y_pred = None + save_conf_matrix = False + conf_matrix_file = "confusion_matrix.png" + conf_matrix_classes = [str(i) for i in range(10)] + + """DataSet Definition""" + dataset_path = f"{os.environ['HOME']}/datasets" + + # data set definition, change to your dataset + sensor_size = tonic.datasets.NMNIST.sensor_size + frame_transform = tonic.transforms.ToFrame(sensor_size=sensor_size, n_time_bins=10) + + test_set = tonic.datasets.NMNIST(save_to=dataset_path, train=False, transform=frame_transform) + + # batch loader + batch_size = 64 + + testLoader = DataLoader(test_set, batch_size=batch_size, shuffle=True, drop_last = True, collate_fn = tonic.collation.PadTensors(batch_first=True)) + + if kind == "eval": + acc, y_pred, y_true = evaluation( + model=model, + testLoader=testLoader, + name=exp_name, + device=device, + verbose=verbose + ) + elif kind == "qeval": + # TODO + raise NotImplementedError() + elif kind == "heval": + acc, y_pred, y_true = hardware_estimation( + model=model, + testLoader=testLoader, + name=exp_name, + device=device, + verbose=verbose + ) + elif kind == "feval": + acc, y_pred, y_true = fpga_evaluation( + model=model, + testLoader=testLoader, + name=exp_name, + verbose=verbose + ) + else: + print(f"{kind} not supported") + exit(-1) + + if save_conf_matrix: + confusion_matrix( + y_true=y_true, + y_pred=y_pred, + file_name=conf_matrix_file, + classes=conf_matrix_classes + ) \ No newline at end of file diff --git a/modneflib/modnef/templates/main.py b/modneflib/modnef/templates/main.py deleted file mode 100644 index 88f2812..0000000 --- a/modneflib/modnef/templates/main.py +++ /dev/null @@ -1,29 +0,0 @@ - -import tonic -from torch.utils.data import DataLoader -import sys -import os -from modnef.modnef_torch import ModNEFExecutor - -if __name__ == "__main__": - - # dataset path - dataset_path = f"{os.environ['HOME']}/datasets" - - # data set definition, change to your dataset - sensor_size = tonic.datasets.NMNIST.sensor_size - frame_transform = tonic.transforms.ToFrame(sensor_size=sensor_size, n_time_bins=10) - - train_set = tonic.datasets.NMNIST(save_to=dataset_path, train=True, transform=frame_transform) - test_set = tonic.datasets.NMNIST(save_to=dataset_path, train=False, transform=frame_transform) - - # batch loader - batch_size = 64 - trainloader = DataLoader(train_set, batch_size=batch_size, shuffle=True, drop_last = True, collate_fn = tonic.collation.PadTensors(batch_first=True)) - testloader = DataLoader(test_set, batch_size=batch_size, shuffle=True, drop_last = True, collate_fn = tonic.collation.PadTensors(batch_first=True)) - - # execution variable - model_path = sys.argv[1] - exe_command = sys.argv[2:] - - ModNEFExecutor(model_path, exe_command, testloader, trainloader) \ No newline at end of file diff --git a/modneflib/modnef/templates/model_template.json b/modneflib/modnef/templates/model_template.json new file mode 100644 index 0000000..31fd483 --- /dev/null +++ b/modneflib/modnef/templates/model_template.json @@ -0,0 +1,81 @@ +{ + "name" : "blif_model", + + "input" : 2312, + "num_class" : 10, + + "slif_layer" : { + "model" : "slif", + "in_features" : 2312, + "neurons" : 128, + "threshold" : 0.8, + "leak" : 0.015, + "min" : 0.0, + "rest" : 0.0, + "quantizer" : { + "kind" : "MinMaxQuantizer", + "parameters" : { + "bitwidth" : 8, + "signed" : null + } + }, + "hardware" : { + "strategy" : "Sequential", + "mem_init_file" : null, + "variable_size" : -1 + } + }, + + "shiftlif_layer" : { + "model" : "shiftlif", + "in_features" : 128, + "neurons" : 64, + "beta" : 0.875, + "threshold" : 0.8, + "reset_mechanism" : "subtract", + "quantizer" : { + "kind" : "DynamicScaleFactorQuantizer", + "parameters" : { + "bitwidth" : 8, + "signed" : null + } + }, + "hardware" : { + "strategy" : "Parallel", + "mem_init_file" : null, + "variable_size" : -1 + } + }, + + "blif_layer" : { + "model" : "blif", + "in_features" : 64, + "neurons" : 10, + "beta" : 0.9, + "threshold" : 0.8, + "reset_mechanism" : "subtract", + "quantizer" : { + "kind" : "FixedPointQuantizer", + "parameters" : { + "bitwidth" : 8, + "fixed_point" : -1, + "signed" : null + } + }, + "hardware" : { + "strategy" : "Parallel", + "mem_init_file" : null, + "variable_size" : -1 + } + }, + + "hardware" : { + "clock_name" : "clock", + "clock_freq" : 125000000, + "baud_rate" : 921600, + "txd" : "uart_txd", + "rxd" : "uart_rxd", + "queue_read_depth" : 4096, + "queue_write_depth" : 1024 + } +} diff --git a/modneflib/modnef/templates/run_lib.py b/modneflib/modnef/templates/run_lib.py new file mode 100644 index 0000000..38bec42 --- /dev/null +++ b/modneflib/modnef/templates/run_lib.py @@ -0,0 +1,211 @@ +import torch.nn as nn +from snntorch import surrogate +import torch +spike_grad = surrogate.fast_sigmoid(slope=25) +from tqdm import tqdm +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt +from sklearn.metrics import confusion_matrix +import seaborn as sns + + +def train_1_epoch(model, trainLoader, optimizer, loss, device, verbose): + epoch_loss = [] + + if verbose: + bar_format = "{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}{postfix}]" + loader = tqdm(trainLoader, desc="Train", bar_format=bar_format) + else: + loader = trainLoader + + for _, (data, target) in enumerate(loader): + model.train() + data = data.to(device) + data = data.squeeze(0) + target = target.to(device) + + spk_rec, mem_rec = model(data) + + loss_val = torch.zeros((1), dtype=torch.float, device=device) + + for step in range(data.shape[1]): + loss_val += loss(mem_rec[step], target) + + epoch_loss.append(loss_val.item()) + + model.zero_grad() + loss_val.backward() + optimizer.step() + + if verbose: + loader.set_postfix_str(f"Loss : {np.mean(epoch_loss):0<3.2f}") + + + return np.mean(epoch_loss) + +def train(model, trainLoader, testLoader, optimizer, loss, device=torch.device("cpu"), validationLoader=None, n_epoch=10, best_model_name="best_model", verbose=True, save_plot=False, save_history=False, output_path="."): + avg_loss_history = [] + acc_test_history = [] + acc_val_history = [] + + + best_acc = 0 + + model = model.to(device) + + for epoch in range(n_epoch): + if verbose: + print(f"---------- Epoch : {epoch} ----------") + + epoch_loss = train_1_epoch(model=model, trainLoader=trainLoader, optimizer=optimizer, loss=loss, device=device, verbose=verbose) + avg_loss_history.append(epoch_loss) + + if validationLoader!=None: + acc_val, _, _ = evaluation(model=model, testLoader=validationLoader, name="Validation", verbose=verbose, device=device) + acc_val_history.append(acc_val) + + acc_test, _, _ = evaluation(model=model, testLoader=testLoader, name="Test", verbose=verbose, device=device) + acc_test_history.append(acc_test) + + if best_model_name!="" and acc_test>best_acc: + torch.save(model.state_dict(), best_model_name) + best_acc = acc_test + + if save_history: + np.save(f"{output_path}/loss.npy", np.array(avg_loss_history)) + np.save(f"{output_path}/acc_test.npy", np.array(acc_test_history)) + + if len(acc_val_history)!=0: + np.save(f"{output_path}/acc_validation.npy", np.array(acc_val_history)) + + if save_plot: + plt.figure() # Create a new figure + plt.plot([i for i in range(n_epoch)], avg_loss_history) + plt.title('Average Loss') + plt.xlabel("Epoch") + plt.ylabel("Loss") + plt.savefig(f"{output_path}/loss.png") + + plt.figure() + if len(acc_val_history)!=0: + plt.plot([i for i in range(n_epoch)], acc_val_history, label="Validation") + plt.plot([i for i in range(n_epoch)], acc_test_history, label="Test") + plt.scatter([acc_test_history.index(best_acc)], [best_acc], label="Best Accuracy") + plt.legend() + plt.title("Accuracy") + plt.xlabel("Epoch") + plt.ylabel("Accuracy") + plt.savefig(f"{output_path}/accuracy.png") + + return avg_loss_history, acc_val_history, acc_test_history, best_acc + +def __run_accuracy(model, testLoader, name, verbose, device): + """ + Run inference + + Parameters + ---------- + testLoader + test dataset loader + name : str + name of inference + + Returns + ------- + (float, list, list) + accuracy + predicted class + true class + """ + + y_true = [] + y_pred = [] + correct = 0 + total = 0 + + if verbose: + bar_format = "{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}{postfix}]" + loader = tqdm(testLoader, desc=name, bar_format=bar_format) + else: + loader = testLoader + + + for _, (data, target) in enumerate(loader): + + data = data.to(device) + target = target.to(device) + + y_true.append(target) + + spk_rec, mem_rec = model(data) + + output = (spk_rec.sum(dim=0))/data.shape[1] + predicted = output.argmax(dim=1).to(device) + correct += predicted.eq(target.view_as(predicted)).sum().item() + y_pred.append(predicted) + total += target.size(0) + + if verbose: + loader.set_postfix_str(f"Accuracy : {np.mean(correct/total*100):0<3.2f}") + + del data + del target + del spk_rec + del mem_rec + + y_true = torch.stack(y_true).reshape(-1) + y_pred = torch.stack(y_pred).reshape(-1) + + + return (correct/total), y_pred, y_true + +def evaluation(model, testLoader, name="Evaluation", device=torch.device("cpu"), verbose=False): + accuracy = 0 + y_pred = [] + y_true = [] + + model = model.to(device) + + model.eval() + + accuracy, y_pred, y_true = __run_accuracy(model=model, testLoader=testLoader, name=name, verbose=verbose, device=device) + + return accuracy, y_pred, y_true + +def hardware_estimation(model, testLoader, name="Hardware Estimation", device=torch.device("cpu"), verbose=False): + accuracy = 0 + y_pred = [] + y_true = [] + + model = model.to(device) + + model.hardware_estimation() + + accuracy, y_pred, y_true = __run_accuracy(model=model, testLoader=testLoader, name=name, verbose=verbose, device=device) + + return accuracy, y_pred, y_true + + +def fpga_evaluation(model, testLoader, name="FPGA Evaluation", verbose=False): + accuracy = 0 + y_pred = [] + y_true = [] + + device = torch.device("cpu") + + model = model.to(device) + + model.hardware_estimation() + + accuracy, y_pred, y_true = __run_accuracy(model=model, testLoader=testLoader, name=name, verbose=verbose, device=device) + + return accuracy, y_pred, y_true + +def confusion_matrix(y_true, y_pred, file_name, classes): + cm = confusion_matrix(y_true, y_pred) + df_cm = pd.DataFrame(cm / np.sum(cm, axis=1)[:, None], index = [i for i in classes], columns = [i for i in classes]) + plt.figure() + sns.heatmap(df_cm, annot=True) + plt.title(f"Evaluation Confusion Matrix") + plt.savefig(file_name) \ No newline at end of file diff --git a/modneflib/modnef/templates/template_model.json b/modneflib/modnef/templates/template_model.json deleted file mode 100644 index 83681fc..0000000 --- a/modneflib/modnef/templates/template_model.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "exp_name" : "template", - - "model": { - "name" : "blif_model", - - "input" : 2312, - "num_class" : 10, - - "slif_layer" : { - "model" : "slif", - "in_features" : 2312, - "neurons" : 128, - "threshold" : 0.8, - "leak" : 0.015, - "min" : 0.0, - "rest" : 0.0, - "quantizer" : { - "kind" : "MinMaxQuantizer", - "parameters" : { - "bitwidth" : 8, - "signed" : null - } - }, - "hardware" : { - "strategy" : "Sequential", - "mem_init_file" : null, - "variable_size" : -1 - } - }, - - "shiftlif_layer" : { - "model" : "shiftlif", - "in_features" : 128, - "neurons" : 64, - "beta" : 0.875, - "threshold" : 0.8, - "reset_mechanism" : "subtract", - "quantizer" : { - "kind" : "DynamicScaleFactorQuantizer", - "parameters" : { - "bitwidth" : 8, - "signed" : null - } - }, - "hardware" : { - "strategy" : "Parallel", - "mem_init_file" : null, - "variable_size" : -1 - } - }, - - "blif_layer" : { - "model" : "blif", - "in_features" : 64, - "neurons" : 10, - "beta" : 0.9, - "threshold" : 0.8, - "reset_mechanism" : "subtract", - "quantizer" : { - "kind" : "FixedPointQuantizer", - "parameters" : { - "bitwidth" : 8, - "fixed_point" : -1, - "signed" : null - } - }, - "hardware" : { - "strategy" : "Parallel", - "mem_init_file" : null, - "variable_size" : -1 - } - }, - - "hardware" : { - "clock_name" : "clock", - "clock_freq" : 125000000, - "baud_rate" : 921600, - "txd" : "uart_txd", - "rxd" : "uart_rxd", - "queue_read_depth" : 4096, - "queue_write_depth" : 1024 - } - }, - - "optimizer" : { - "lr" : 1e-4, - "betas" : [0.9, 0.99] - }, - - "best_model" : "best_my_model", - - "verbose" : true, - - "device" : "auto", - - "train" : { - "name" : "Train", - "n_epoch" : 5, - "save_best_model" : true, - "save_history" : true, - "plot" : true - }, - - "eval" : { - "name" : "Evaluation", - "use_best_model" : true, - "conf_matrix" : true - }, - - "hardware_estimation" : { - "name" : "Hardware Estimation", - "use_best_model" : true, - "conf_matrix" : true - }, - - "vhdl" : { - "use_best_model" : false, - "driver_config" : "driver.yml", - "file_name" : null - }, - - "fpga" : { - "name" : "FPGA Evaluation", - "driver_config" : "driver.yml", - "board_path" : "board path here", - "conf_matrix" : true - }, - - "confusion_matrix" : { - "class" : ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] - } - -} \ No newline at end of file diff --git a/modneflib/modnef/templates/train.py b/modneflib/modnef/templates/train.py new file mode 100644 index 0000000..3a5bc0c --- /dev/null +++ b/modneflib/modnef/templates/train.py @@ -0,0 +1,62 @@ +import tonic +from torch.utils.data import DataLoader +from modnef.modnef_torch import ModNEFModelBuilder +import os +from snntorch.surrogate import fast_sigmoid +from run_lib import * + +if __name__ == "__main__": + + """Model definition""" + model_path = "model_template.json" + model = ModNEFModelBuilder(model_path, spike_grad=fast_sigmoid(slope=25)) + + """Optimizer""" + optimizer = torch.optim.Adam(model.parameters(), lr=1e-4, betas=(0.9, 0.999)) + + """Loss""" + loss = torch.nn.CrossEntropyLoss() + + """Device definition""" + device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu") + + """Train variable definition""" + n_epoch = 10 + best_model_name = "best_model" + verbose = True + save_plot = False + save_history = False + output_path = "." + + """DataSet Definition""" + dataset_path = f"{os.environ['HOME']}/datasets" + + # data set definition, change to your dataset + sensor_size = tonic.datasets.NMNIST.sensor_size + frame_transform = tonic.transforms.ToFrame(sensor_size=sensor_size, n_time_bins=10) + + train_set = tonic.datasets.NMNIST(save_to=dataset_path, train=True, transform=frame_transform) + test_set = tonic.datasets.NMNIST(save_to=dataset_path, train=False, transform=frame_transform) + + # batch loader + batch_size = 64 + + trainLoader = DataLoader(train_set, batch_size=batch_size, shuffle=True, drop_last = True, collate_fn = tonic.collation.PadTensors(batch_first=True)) + testLoader = DataLoader(test_set, batch_size=batch_size, shuffle=True, drop_last = True, collate_fn = tonic.collation.PadTensors(batch_first=True)) + validationLoader = None + + train( + model=model, + trainLoader=trainLoader, + testLoader=testLoader, + validationLoader=validationLoader, + optimizer=optimizer, + loss=loss, + device=device, + n_epoch=n_epoch, + best_model_name=best_model_name, + verbose=verbose, + save_plot=save_plot, + save_history=save_history, + output_path=output_path + ) \ No newline at end of file -- GitLab