From ab9e3392855651b3ff622fb0efe034c840f58c44 Mon Sep 17 00:00:00 2001 From: z1069614715 <1069614715@qq.com> Date: Thu, 9 Feb 2023 19:24:25 +0800 Subject: [PATCH] v1.5 --- README.md | 15 ++++++--- model/__pycache__/__init__.cpython-38.pyc | Bin 482 -> 479 bytes model/__pycache__/convnext.cpython-38.pyc | Bin 9323 -> 9320 bytes model/__pycache__/cspnet.cpython-38.pyc | Bin 27163 -> 27160 bytes model/__pycache__/densenet.cpython-38.pyc | Bin 12416 -> 12413 bytes model/__pycache__/dpn.cpython-38.pyc | Bin 9911 -> 9908 bytes .../__pycache__/efficientnetv2.cpython-38.pyc | Bin 31851 -> 31852 bytes model/__pycache__/ghostnet.cpython-38.pyc | Bin 7899 -> 7896 bytes model/__pycache__/mnasnet.cpython-38.pyc | Bin 10663 -> 10660 bytes model/__pycache__/mobilenetv2.cpython-38.pyc | Bin 7648 -> 7645 bytes model/__pycache__/mobilenetv3.cpython-38.pyc | Bin 10891 -> 10888 bytes model/__pycache__/repghost.cpython-38.pyc | Bin 14224 -> 14221 bytes model/__pycache__/repvgg.cpython-38.pyc | Bin 12997 -> 12994 bytes model/__pycache__/resnest.cpython-38.pyc | Bin 13947 -> 13944 bytes model/__pycache__/resnet.cpython-38.pyc | Bin 13873 -> 13870 bytes model/__pycache__/sequencer.cpython-38.pyc | Bin 15308 -> 15305 bytes model/__pycache__/shufflenetv2.cpython-38.pyc | Bin 8967 -> 8964 bytes model/__pycache__/vgg.cpython-38.pyc | Bin 9327 -> 9324 bytes model/__pycache__/vovnet.cpython-38.pyc | Bin 7733 -> 7730 bytes model/efficientnetv2.py | 2 +- predict.py | 16 ++++++++-- utils/__pycache__/__init__.cpython-38.pyc | Bin 140 -> 137 bytes utils/__pycache__/utils.cpython-38.pyc | Bin 34789 -> 34887 bytes utils/__pycache__/utils_aug.cpython-38.pyc | Bin 6324 -> 6321 bytes utils/__pycache__/utils_model.cpython-38.pyc | Bin 3077 -> 3090 bytes utils/utils.py | 15 +++++---- utils/utils_model.py | 30 +++++++++--------- 27 files changed, 48 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index d070aad..8280d8a 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ image classifier implement in pytoch. - **简单的安装过程** 1. 安装好pytorch, torchvision(pytorch==1.12.0+ torchvision==0.13.0+) 可以在[pytorch](https://pytorch.org/get-started/previous-versions/)官网找到对应的命令进行安装. - 2. pip install -r requirements.txt + 2. pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple - **人性化的设定** 1. 大部分可视化数据(混淆矩阵,tsne,每个类别的指标)都会以csv或者log的格式保存到本地,方便后期美工图像. @@ -245,7 +245,7 @@ image classifier implement in pytoch. 是否采用测试阶段的数据增强. - **cam_visual** default: False - 是否进行热力图可视化. + 是否进行热力图可视化.(目前只支持在cpu上进行可视化热力图) - **cam_type** type: string, default: GradCAMPlusPlus, choices: ['GradCAM', 'HiResCAM', 'ScoreCAM', 'GradCAMPlusPlus', 'AblationCAM', 'XGradCAM', 'EigenCAM', 'FullGrad'] 热力图可视化的类型. @@ -533,7 +533,7 @@ image classifier implement in pytoch. 1. 在predict.py中的--cam_type参数,可以选择各种各样的热力图计算方法,如果遇到这个效果不好可以进行更换,当然效果不好除了跟热力图的计算方法有关系之外还有是你选择的层. 2. 在第一点中说到的层,热力图可视化需要选择层进行计算,这个是在predict.py中的cam_visual方法定义中进行定义. - 例如这样 cam_model = cam_visual(model, test_transform, DEVICE, model.cam_layer(), opt) 这个model.cam_layer()就是选择的层,默认就是卷积特征的最后一个block,这个可以在model文件夹中的每个模型文件中的模型进行修改. + 例如这样 cam_model = cam_visual(model, test_transform, DEVICE, model.cam_layer(), opt) 这个model.cam_layer()就是选择的层,默认就是卷积特征的最后一个layer,这个可以在model文件夹中的每个模型文件中的模型进行修改. 13. 关于类别平衡的问题. @@ -679,4 +679,11 @@ image classifier implement in pytoch. 1. predict.py支持检测灰度图,其读取后会检测是否为RGB通道,不是的话会进行转换. 2. 更新readme.md. -3. 修复一些bug. \ No newline at end of file +3. 修复一些bug. + +### pytorch-classifier v1.5 更新日志 + +1. 更新readme.md +2. 修改predict.py中的读取模型方式. +3. 修复predict.py中批量预测保存图片时候的内存溢出问题. +4. 修复predict.py中热力图可视化的报错问题,但是目前只支持cpu状态下可视化热力图. \ No newline at end of file diff --git a/model/__pycache__/__init__.cpython-38.pyc b/model/__pycache__/__init__.cpython-38.pyc index 177d5b3d08713780a783e58340ebb6b9b3581fb6..24c9f6a631554cedfd8c11c62200415a1a0f77a5 100644 GIT binary patch delta 30 kcmaFFe4m*+l$V!_0SM$$pKRnVVr13RPf0A9+{zdW0CZvp^8f$< delta 33 ncmcc5{D_%5l$V!_0SIRJb!_A=V&pK?&&?~*FHV`<#252EEf=KJbn-b7iOmxvA2PGmfcO=Y%Vm4m+Cj{g$((XGR2xCeS`bkQBAS3i zNKrG030BkrV)aaBlizGN0myvW03sL|K?Dlji>`DtO5}@jQ9>UqR0-U$R0#E z0EtWnHXsXZL_J8X8bshQ;)TLyDUd6QCV_~_AYuxT$YkIEvKl9ERSXeq00|;%pDd*$ zE!7DURR$4VAfg*Y09_99nZJ@3=X4-5M3b?ock&{o7RI8<>dNtqos-*@4H(-e?@-TbFVFe^6Pvj8Y{8%J_i7{ugiFgrX{^sT4 z0*pY;4hd7ye2}UL5D^U`gh52wWG2a6#+=OslK+_5szD;OlnfZCHMMe2VMI9iu${?Z>M09}&pnpLA^-=QToCaiu fXfhV{OrEdQ!dN(2MLC|aV{(hK0b|?bt;(ALyPtN8 diff --git a/model/__pycache__/cspnet.cpython-38.pyc b/model/__pycache__/cspnet.cpython-38.pyc index aa6c3d8d8df7a0bd4c6600b388795a467eab7283..5ffa9a1796f9e1b446ddaf955390d0295e79b466 100644 GIT binary patch delta 33 ncmbPzg>l9eM($8vUM>b8kV}2Ck^3`0tB!t3V##JU0nsP`rA`T0 delta 36 qcmbPng>m*3M($8vUM>b8SRK;2k^3`0hrWJpUWtBj%4TK((I^1PKnj=u diff --git a/model/__pycache__/densenet.cpython-38.pyc b/model/__pycache__/densenet.cpython-38.pyc index 448ea6bf3e79b981baf871b54132cd22404d527a..b65e6a043f2164c14cd79b0776612d8982b21b68 100644 GIT binary patch delta 31 lcmZoj{F}fX%FD~e00eTWPd0KJu(RsvrzDnac4oKL1OSDO2pa$Z delta 34 ocmeyH(2&R-%FD~e00hMmog29g*f|XKbMs2{i&Hi`u-j?^0HOg2CjbBd diff --git a/model/__pycache__/dpn.cpython-38.pyc b/model/__pycache__/dpn.cpython-38.pyc index 29301039edb0a5e4ea7943182c6bd02766bcf6ab..1a16282f0d548b423d4516d72f4a7d60eb2074ee 100644 GIT binary patch delta 31 lcmdn)yTz9~l$V!_0SM$$pKRoQ&&sN)pORRznTc(y0sx552*&^b delta 34 ocmdnuyWN*Nl$V!_0SNS?IyZ8^XXVh*&&?~*FHYI~pLMGO0Hjh1kN^Mx diff --git a/model/__pycache__/efficientnetv2.cpython-38.pyc b/model/__pycache__/efficientnetv2.cpython-38.pyc index 3e9a487f520bf35047b968a972aafb8dbb9d85f5..0c089b8f2b75c8f0736cd51e0967f244142d8a30 100644 GIT binary patch delta 2035 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 DUHT88 delta 52 zcmca>{lJ<#l$V!_0SL77J2!H7v2d8^=jN5@7pH8V#S$vPdyC6CKd;QmFDTU~^w#7* GG7kZeoe_8d diff --git a/model/__pycache__/mobilenetv3.cpython-38.pyc b/model/__pycache__/mobilenetv3.cpython-38.pyc index d37248acede99d28f5a894aecd58a874e990aad4..7a9164bde80a813c8559aa352f3d10ce2e188664 100644 GIT binary patch delta 31 lcmeAU?Fi)#<>lpK00OzxCmXqMv$7iMrzDnae#bgj1ptE_2}%F} delta 34 ocmeAO?GEJ*<>lpK00PB=&W+r+SvgGfbMs2{i&HkgW}T}70Gc=o8~^|S diff --git a/model/__pycache__/repghost.cpython-38.pyc b/model/__pycache__/repghost.cpython-38.pyc index 741c13cfab0f4d85b8216a7388e40cee67e95eed..12a0f534b20bed65d31da7758848057006e1c09b 100644 GIT binary patch delta 31 lcmbP`-kf2#o*$ delta 34 ocmey7^E-z-l$V!_0SI=MbZ+F9Waco?&&?~*FHYI4$?R_o0J)P1`v3p{ diff --git a/model/__pycache__/resnet.cpython-38.pyc b/model/__pycache__/resnet.cpython-38.pyc index 72c7996cc960b688f06e7a4f8e7f37f085bda556..4fe41a9a957f546e6a8148c84728aaab8a315554 100644 GIT binary patch delta 31 lcmdm(vo41_l$V!_0SM$$pKRn7WoOmVPf0Ah($ diff --git a/model/__pycache__/sequencer.cpython-38.pyc b/model/__pycache__/sequencer.cpython-38.pyc index 6e0729ce27d45e0b424624c79b00c6674c2655ce..05443506e7fa533457030a0c75610fe27508b5d3 100644 GIT binary patch delta 31 lcmX?8ezKf9l$V!_0SM$$pKRn-Vqw+SPf0AlpK00OzxCmXrrSy+wqQxZ!y7qLv00|0h!2ps?b delta 34 ocmZp1Yj@)g<>lpK00M{d&W+shEF7l#xp^h}#VMQfS*FSX0FJx~6#xJL diff --git a/model/__pycache__/vgg.cpython-38.pyc b/model/__pycache__/vgg.cpython-38.pyc index be54e01fc4f3e110c1ffab74129a67120ea53808..6e3fee56d4056ae4e75aa310ca9562000d85ad80 100644 GIT binary patch delta 31 lcmaFw@y3HYl$V!_0SM$$pKRpb#m=g!pORRz`7HY)832_z39kSE delta 34 ocmaFk@!o?wl$V!_0SGcDb#CO|#m=FlpPN^rU!1b}6#F6>0JeGx>i_@% diff --git a/model/__pycache__/vovnet.cpython-38.pyc b/model/__pycache__/vovnet.cpython-38.pyc index 61e939ea8194a78c63390290e3f8ff7ddb9ad5ab..06f25de71edc2cc285ab587a4b54d0df8d45c4f2 100644 GIT binary patch delta 31 lcmdmLv&n`#l$V!_0SM$$pKRn#W?|LQPf0Al$V!_0SM;J?A*wm%)+6spPN^rU!1bJm}S2t0HVhV1ONa4 diff --git a/model/efficientnetv2.py b/model/efficientnetv2.py index acdbc76..addf4b5 100644 --- a/model/efficientnetv2.py +++ b/model/efficientnetv2.py @@ -383,7 +383,7 @@ def forward_features(self, x, need_fea=False): return x def cam_layer(self): - return self.features[-1] + return self.features[-5:] def switch_to_deploy(self): new_block = [] diff --git a/predict.py b/predict.py index 98ef390..f7eecac 100644 --- a/predict.py +++ b/predict.py @@ -6,8 +6,10 @@ os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" import matplotlib.pyplot as plt import numpy as np +from copy import deepcopy from utils import utils_aug from utils.utils import predict_single_image, cam_visual, dict_to_PrettyTable, select_device, model_fuse +from utils.utils_model import select_model def set_seed(seed): random.seed(seed) @@ -27,6 +29,7 @@ def parse_opt(): parser.add_argument('--device', type=str, default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu') opt = parser.parse_known_args()[0] + if not os.path.exists(os.path.join(opt.save_path, 'best.pt')): raise Exception('best.pt not found. please check your --save_path folder') ckpt = torch.load(os.path.join(opt.save_path, 'best.pt')) @@ -34,8 +37,13 @@ def parse_opt(): if opt.half and DEVICE.type == 'cpu': raise Exception('half inference only supported GPU.') if opt.half and opt.cam_visual: + raise Exception('cam visual only supported cpu. please set device=cpu.') + if (opt.device != 'cpu') and opt.cam_visual: raise Exception('cam visual only supported FP32.') - model = ckpt['model'].float() + with open(opt.label_path) as f: + CLASS_NUM = len(f.readlines()) + model = select_model(ckpt['model'].name, CLASS_NUM) + model.load_state_dict(ckpt['model'].float().state_dict(), strict=False) model_fuse(model) model = (model.half() if opt.half else model) model.to(DEVICE) @@ -59,7 +67,7 @@ def parse_opt(): opt, DEVICE, model, test_transform, label = parse_opt() if opt.cam_visual: - cam_model = cam_visual(model, test_transform, DEVICE, model.cam_layer(), opt) + cam_model = cam_visual(model, test_transform, DEVICE, opt) if os.path.isdir(opt.source): save_path = os.path.join(opt.save_path, 'predict', datetime.datetime.strftime(datetime.datetime.now(),'%Y_%m_%d_%H_%M_%S')) @@ -71,7 +79,7 @@ def parse_opt(): plt.figure(figsize=(6, 6)) if opt.cam_visual: - cam_output = cam_model(os.path.join(opt.source, file), pred) + cam_output = cam_model(os.path.join(opt.source, file)) plt.imshow(cam_output) else: plt.imshow(plt.imread(os.path.join(opt.source, file))) @@ -79,6 +87,8 @@ def parse_opt(): plt.title('predict label:{}\npredict probability:{:.4f}'.format(label[pred], float(pred_result[pred]))) plt.tight_layout() plt.savefig(os.path.join(save_path, file)) + plt.clf() + plt.close() with open(os.path.join(save_path, 'result.csv'), 'w+') as f: f.write('img_path,pred_class,pred_class_probability\n') diff --git a/utils/__pycache__/__init__.cpython-38.pyc b/utils/__pycache__/__init__.cpython-38.pyc index 935f6cd527c41f85cf2294993f1a7bdfdef68aeb..b4c7fcc4ef8acc74a5c2dbc82b6513bfce71e71a 100644 GIT binary patch delta 28 icmeBS>}2E)<>lpK00OzxClk4CSoQQ%5=$of+X4VlCI*uL delta 31 lcmeBV>|x{%<>lpK0D`$|J0^15a2V?6=9TCdr%d#*1pseZ2ps?b diff --git a/utils/__pycache__/utils.cpython-38.pyc b/utils/__pycache__/utils.cpython-38.pyc index 67a88268fb00739ffcab6bf383767d5336a1970f..a73cf7d2ba722557f9ed79ca785d47ae142ab40f 100644 GIT binary patch delta 10873 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 delta 10949 zcmaJ{34B!5)t~!jO(qEeLX7OPhy#%w5oMLFAcS3T1Rs;RFJZ!L-uEUXAuv{`V!yi7 z+tt=K*#4xnYSpN9L#?&7?e|lmYCnA~t=1}9ty*hqf3?eZ{^uo`kdJ=JZ_eCzmvhcN z_ndRjId7i1*?8k7qjF1SWx0?39=iMbr2c&6C{cUwlqNB8h#Z=}I5R&!U-+a?)}$9? z7RDEHdsup2W>I_*wQKd0Vv@g3PS$@Aw*L|-^-iO$`1Q}l7t6!)_Jh9o68SCpZTh}M zekkvdM-GbkQu!TulzNuQ@5=Ad_wtoKd8fSVpika)z=*Gqcgycn?@D=(yw|F2`Bcj) zd0$gNcFX%|?P~dee2_*jl|PUV(f1l!`>=e3);>aO*V5CY^09+OpL~oS8{{$hI89n7 zpO8<|_j>t5`4oL`kbjm>%O4ZEjq)e*8S2?2KaxL_Kc}9}@-OmP`5d*j5VGgxaYB9E zGFn8-Wi4AB0_#gT5L0?h6OyqaSSENf5 zu9Ux$zou_fo|M0#@163u@>Tjy$k*iW=(|zAE`LwoNm~Afe3J;iNvkD2osw_S(_8dp z$&ck9Y{G&cESe|sC}*u6EdTXdfc?u}O7OOJn_ zIxUlRrrAf0v$n=RVv$e8^NG zM(R~VR}Xst6C)~-m3d2L)T6*KN`GhQrV#^?Wm0X0yeSh-;x1iVGv0XCr~kEMWcSvZ z8sJI~8!leZ*9}WXfl+}ib&vkbusOAi@)({UC*TG^OFgR>*X~*VBXpDlWjdFTmU2Z( zJ%v7Dx}wGPr!vjnc1nAy&Zl#Z>8M01Yc?jF; ze*k!kK+I6gcp#l?wg>VTVg6|3C7Nk3Cg2mbMun&n`qJU^jB=rmw~YMO?ZZWtAwVIm z%uJ$9eWLFf(LSMqx)}HW!D^bRY|1gsfBW>>k-KJ&B(yQZElbFjg6)`TrK)M^QK4#q z;q;SJ!>F%ZpBnjU5zEw{0YE$!n0M^WDh`qW@=qYm0Ni?P{*T36p zSLb7nXzIrWyOOBAE4Rl?=CVzx=4txGxQSwR_s8Sj5H&C|H`qkda1_*wbns36!GtCC zbl3QrsRMtD6+L*G=Z2D2*0GfO4tgdLi237s$Hb9hzV4W~U_sn3^QqX#l5x8JOe*X8 z(^l3EC2XfXPmJ1yjDkmT!&z%jqAg{s-viqz{n5lZ;-sE@?$}ikqS()F2MPh(iB-5p zGUJAm>4a@tHai8kESpoAL^{=Bu?tWaYklst>F)vk2LPvQnLCWl9daqysa%$9*-@#s zrTW8jXNawO!lVx-!efw7;MN8%j?7OdGL15^Fs|pF*HD}UmM0L1mAn3qRG#*mrvsGi zbb1aiow6O0NFuMMVs_uQ+~6LSa;#WbZAAYj064jL*mjheP>SS^ZJKd^GGnS)7$2~e z^M~o(iX{ud8sC;BWLqt7!vs$5&dRFYSQT8Vn0@ri;r?K(kn0_}lJY=Hdq^_8J z&QxY*0G&`Wkv5Z=oxmGmywgQ3{i~e5V)C)b{nSO)cTA6+GH3SR=)tY@y!~!zrgOGU z-j|)611hJZRYteHqA)xR-kn_e<^lpZxLHvMv%ebjJ`snZoS^{8+| z%CZaTo;`WNz$+u&g{(UPisRTlJIEU!GiA)NwkF9#P=xU{TzvpPJDb z@6!cOO-_QwK3eF8GZxu%(sC<$8obNi10S%gM3kAtX1=7qGV}4`Xy7YNX7nuRYr!0A zW;ac716FGy?O8jhtLq5#(qc`3H1I`W!sSo$ji_t7r_KJz7!4QI5iB@O=U*5TZp6wab261}R@;DS z0_o%GIi4=6z32hIM~!%e=X#Wt&nbsB)T7F@_S3`%^pkVvdEVqX$m(Xov}l652{?dH zeIDQzfD)5f_@HjSu&W4m`94rrQ!5^Ea`1SGcC{4)NdSma!Haob{X9IL?m=0jRRRNi zK$Fpe^H%j};eg`Nb*+|yoR=(Js-V|O6R3-qtzUncxi*zlxp>*;^&7pW`hxz(yx~(I zM|C%?j#c&30Y3DPft^E9R)mfE^?B!sS-Rq)(be~0i1*67zE59t(Fk#ezU-o{#+QUX zv2&#U?~A5wW}oC&F(ToHZHuBJM|rgTu1L6|QOyMP(h+;=-{XjKdFMqM?s39&%y7cD zb~jvnhnO7?G|)ZRz)LC0!)dx=w<}r)A}gCu;j-11R||iw&s%VDh@;DqI!kW?2#<_U`yp%$*YV*@9p~S1&fPNXt!)V zf=&xz!<88NCO`!Mk_|UVJ4t0!7dlD^!yDIb%Bx&neVh8-K?y0%{t@c!)JxYTNAf|= zkzCR28jV@?b>P_oP$4D~93Z~IBxr|}-ejr>6kPr6!fE1u{m+G_cYTG`16nSMjsJ@$ zfqTI~kdhg@L;V1F`(f1gEE-n*A$78?`HX6z9)%w}OTWA5+)6&+An#H=sK+dxIJ>lz zTYR8pw0q06+q21!fha^&eUxdG3-tu3z0lpZIPDkB`i-Uaz2}2$Y09z*Q<#8Y4^MLE zV>a4T{TU=&>NY}CqdS)EU1n0Nf#SwHftZCK+H7U*oKkn7XDxxF9-cErJd9|hp0|9- zB#*Eg%oZ|~VEr76OIu^d0HUMx;pMTVY=BG=U$UfKk8=~ z4N49a!yK2+xIjIvD_4x3z;?|d!Hwod8WYLgdlE`|x9x*K@t9t>V%V%B7!Iw?$pVGN z<*YSOKAUZeRnU!EnY`0ZUN^bRiVaau=`XJsHNwkXGp^w@(WlWB4u{5hTfMKJUooa; zzz&ZSnSW|y<%U6Mox1g__>=w8nDEyMJ~4 z9ApM`dY&yXUp;53zDjs0_Gr0Sqxf1JivDMSXf?IGLAn`Z!xSuucjHEyR3hn6$gO??1fjgLno@1*6)Z5CN%WEq zj;!BOPKsjt-=JS8^%b#(FwDYJl*67WjyS~9Y0+w>wC=UUBX63z;P>k zu&Du2*gw!`Q1zrA@2nEM`A=wcJq@z2p_{`W@vBd|x2!K0Vv^pupZraJ5vb@Z=?Hb3w^Cplpc#$S3 zdh+6Z8v0njxA~kgPoW2T*b#B;tTi>CZSH9$?N&8OPu((xq};G2J)1oQ#6+ zeIiyC`c9YcUj5#d=|y-`H$=|cu_Wb(2;gll0C>UF+=rLHHD=a5lakkEK#tpor(b!i0Br9Dng)Mcr_dm2e7l zM0{#Iu?b5!uN_1=M^14#ZgNr_fRy4DJ!?!nQ2|l5dD4Kzdoo~Y@L5(ydkzzGcj?&H zDa9H(%Vdx^?)@vH20lyaW1|A-__{==@37bx>@+%q2Sk@4#bMFq@AOk&s578uJAsy9 zSLm=$&F&0!g%A6(MrUYW$O&{s4*PDB!snEAhFZ!G2x;s#)E8(@ls*-}(pf}<5Y_m& zD?nZ73HE%44vQx0BQn%aq${y#UpQOgJxg)6Z(n$;Z;o$+Z=-LUucMlXR&|DHma#9g z)t4PDeE3H%eFk-g4-0SXa$<6u&#B(t8R;5)*mpp5Mw(EB4mWs;DImSlMTA>J;Wna+ zug?v+WreJLRl%|-Ai@pZnmxSwwsMXBZZVtJCvpPu3*Intsn z;16wR4r|JV)FA!vnZ8axLD3l`XgL1PU`ybDaDttJWE^M~PN*dey^!Jt%qx>VlDg4A zew=q&=_C~SYBQZ^r|5$!61JuH$3w+(bvCi5h65mgRfn+22slIBqbkwI(U2F^(5PF6 zQI2!TPx8&gmuU&n=ss*Lnm+k(R(>10VF+ zxain+ptAl$zAgh6)8&T>cLfglT1d&SH=IzXaX>VS>xC0OWVA$jtYrIjzU#zwMw4Iq zW#C|>=#(8Yy2@b}2gEW`*L{I(HKB+eG7bqDy1{6s9;c$KvNHhv?y3TjeL-hXS2Z1k zzone)A?Q@J4DR$393sOv7&0=#M@H)F8tT+^hB||?OqSn34AOB#`x!x!B-d`MAhMF&t*Iw9U}lrBE=ndn=Wj>z$?k0L!%U? zJxjgKAmDp7w|H|*#KUyprfP1a$fwWFyrUlmd~9Z{1ZUG4&m*&KaiIGo`j{IIv7%Ji zBfo5A>EoH4KiN97oGV30V&2fxcGR5(ji=y(^@BYw-;6?EzGIg6c4-0#a}0p$!I$aD zuAwzPy7B5nxltv?>3esKt^X_ydix!qOrvPUO<2`aS_rFA-T&ONOo-3vOU#uaE+o9G zZ!*^wM*+oA0PxSLh2k5_PYIY;r!JSNrY1{K8N%{*&k-pn?Wj+=AurQaW4)hAb*aJGNIeU`{wJr*}n^rFd0&es96M8-a~YC28~+yl2cj)Q>XIR`BZvk5l_$ z$WLF~c#fEvIL_x4@{+PL9~c8U*LzR@0@9 zT*&OXKyCKT6j89y*vYV_{TQeQG6x@(+?B{?t+f4fFo)L^K2nI$6cSM=bbJ2`~gqK2agabJ2gDP;>Q-SJ&zB*0|mrn-iBKdZRUWI&XQv9-}Fn%LnPS zm3{>n=|fqznor-lvthV?!8&URoE!yk=yOA)Vw66ri|JvYz@pOXLw1tJdyy^dp3)RE z=GDw)G|D>;UjxFMNi%-8$(E-DC%|$ri9r_ z>jkMV7I_C{9ty_DOtE6G1RgePxI1?+$(6HoR8;cxZq`w|sQ)ycP}PY0GqzNH<~cy3 z>U_fbK6v6lTyJO@w|y}PEdikAKsbiJOKA?WDw#`~rdM?af__N(^m(_7Xy7&a^rSk0 zV0lC>>VCeZ!9NJL)e&x_Xk==hO6|Hn>rm2uI6HeT=eXFP=eD4%uAk;~M0vKAZB9{m zYN*B)3U<2Ldnr3nSL7DXU?mc2Bhe(czyUqy=a51_4w<>zs4u4X=9U%NLSg4_k8k5Z zfUSQzw$|sNygDaW9p^H}erxC@mgR*}eU3q`rPXdUm(8}RLKcOlk|T*%ugdngU%fD2 zc`hH`QTyrxe1yl7^`4u7dd?)p>{08!=gRWXIjD7rbV5kmQ z-a>1rPFz)2gs!-ijj1du%_f!cs1C!o94G#Pru>Wx+^}q?>?M_?mw7pQyV&N$YP~y* zJs->FA!33zqqc%T1A(~Tp?dTNYSDXmk2|gmgnM@iN3cXCG2aA805k$T18k?CvTINc z@^r7ks`ZcVc`9p+;iG^s;|3L^2(eGC111*QWnBmgqnMN{I7Gzugu;S)8dz9bd|WI+mgNqkNJ}FW zkLS|~y1Lms!c@y622HP!xE;u=me6}ys^8?Yo*r>Ja3xsXNg!TswOPpmy`gKJ$$^0y zPXv1%2kt3)4@bPmgDEiQ3fn8|;E1ZdpA4|{uBVyP_3_q+CbIzM5bECA%^5B`h4D}6 z`}Ww=Gu}+B@}g@F)6e*0ge*;M(CgZ!Z93fvdAPkP}TOy~BHiB173I1D#zWm{8xJ**HExi-R&4B84Mtk1$-~^8C)ah45@dJr6Z_58dqLaO=2!%6OyA@;xS-2;D zor=^p7Ip*Vi(2WIS?}+kGOBc@ypIZaTKt@%)oje>^xWbCakDNI?@BMFrEVG7(;80s z)OSJWdjOvYpAcnFtQa5CXi>~&nT*QI5Y+-qI-QofjQVb-9IPiOtDq=|-wj;WedE3WL4~9@+A4q1Knd87G#ZfKgQ&5emKJz8)c#$POPM8k_0+1?JGt z&+7M}{yZj#6*R`GPhGxP3)K;Jr>%s_dcQyeuNSFHF&+A>9_NJw=yzZ?sr4lAatS~y zz%-1|>qC{?H8q)TX<=2A`juEfw83+HRcYbDc5t)-q zNfrf&UR_Y(j-#rGlcJa7i9)j)MbGg-zCD>yqk$9GqN)VlZnPc-coyJ8fO4=J1(*%6 zkw83nNxDEKx~=F)0^|Vl0NzW`FQIuW!2JM^0z3i0_4bF+;=mcDW;eWy0%zn>pP)Ys zMo|A!BLR@7acZJwqIChlTmS^Oio-cXMxG1WXZU8*TU$Is+xQ6ksbQZ|xRLo@RJ@QV X`s`cuJ=ad}{@t}}gcz)+9jg0ZaQ`RQ diff --git a/utils/__pycache__/utils_aug.cpython-38.pyc b/utils/__pycache__/utils_aug.cpython-38.pyc index 15166b0fa299fd5fb53b136c406312b9f035f97d..f2238e33f59d2664fd97199e6f804190c04993f9 100644 GIT binary patch delta 760 zcmZwEOKTHR6bEqcFu9#cnwXf$qa!I;)EJS(Bvh!NU6j-sh16n%j*m3YCiT(ucBI8x zDUIUFf*cV10)mP{iMxIRp@Qq|6j5+h5W%JQKUoySf%$RrKXY#G-1(5+PJ4=8ulsx@~H(ay0fwY5=xM$U^2 zz13oDj6Q0IO>5w8Yqef0t%@XCDR3I3X(<|{fSzR&l+$yAqX>s23717L^h+#9U-cdT zB;pHT3S6Xj?i|Z^f4MglRv_EkVR`!FJt8+@`o`HbS-z~yw|osYN56e9>5Cqsjlo)2 zT*i0-;7^1Ju29ThJTZgvD)^^elvxM)HOYe{rTod6gf6Zl(m@Q&f}_9!H^5DBOOjA~ zx-H7Bd!@y;EkcN=K?yh;DUcbMVil?e-tY#}d3i8KH-1R4kn{T(!s8&`Z@&-5Sd(^x zQ9h2~JpBwl_Eu41!PiVQoul0{;=G2mPCLd)PYdN5Sf@QB8p6Occ`tK`#@wnF5LJqW zK94l<5Z=4TZ?BZa{BnPz`^VOzgW>0sPx07-B*Dc9>N`LIZSVvvNfL^1mJ|q_RrZ%! zqwnE{=^XOI|FqYs5gB8ToDFZv{wsO+H>_x?rixAa6d97={zqi?R0i`CAP4eb4pbyP UzF1kPS8ajUmScNHggVjmU!Z`dZ~y=R delta 807 zcmZwEO=}ZD7zc1CZnnEg6O%S+YHE=BR#&7UttnP0LZuRj)>=rbRY>!)X|{EfI$3S( zsWnAfq6c|SegV;nhY}BhegVJ2Ab3#lBviq>^WPo>abbUX_CGV3XJ_|P?^6C;AmBSB zug`Cv?D_qQHj=b!PO?$%3@Dd8VbN83;N*G15ndE)f+}i}r8}QglQBU_ZGw%Ft)D*ue8M21WH39e8qxOs^%Nkx+%O?t!y?$mu)r8a=yt^m^A`M!3FxM^iohCWf_{( zr@Aj9JSs7~f=JJ@EPc^GgsvgJ4yM5k+VxGbna;j%!^3iPKhR<`^gA#pTZ;uRvpJd% zj>^0ptgt2e6@0;N($gc4qO(|=1K5Gb!92x7xwE%WE`WcA@5ro${H|numGAJDlLY0)q6;7oJ{9r zPlH9>=hFz!fT4roH@%7DHCc+omc1lcRj@Uo*oDT5U^RXPb0+C~?^eJF3gYiN4XWEEyw9Yk&pl`9;=hJx1fGn5+OQ0$dYQ4B@mK^S$)VACtMjQR9 EKZm}$eE639Lo)YM4P}iRc2c645O21riGx zfP9U`FIibw4fRtJOD2EhbYT24*@)|jFcS}x6r&uY6uS^3A0rPCvN29p=T2c}_Vb(E H!(9mg=58H_ delta 95 zcmbOv(JH|k%FD~e00f`>I+Cj=@*ZHEv+*1^t3Zk90r3mGP`7RfCB%F4oF xqMw^rqFi