You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ncnn2int8.cpp 44 kB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175
  1. // BUG1989 is pleased to support the open source community by supporting ncnn available.
  2. //
  3. // Copyright (C) 2019 BUG1989. All rights reserved.
  4. //
  5. // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // https://opensource.org/licenses/BSD-3-Clause
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed
  11. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  12. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  13. // specific language governing permissions and limitations under the License.
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <limits.h>
  17. #include <math.h>
  18. #include <assert.h>
  19. #include <fstream>
  20. #include <vector>
  21. #include <set>
  22. #include <limits>
  23. #include <map>
  24. #include <algorithm>
  25. // ncnn public header
  26. #include "net.h"
  27. #include "layer.h"
  28. #include "layer_type.h"
  29. // ncnn private header
  30. #include "layer/batchnorm.h"
  31. #include "layer/bias.h"
  32. #include "layer/binaryop.h"
  33. #include "layer/clip.h"
  34. #include "layer/concat.h"
  35. #include "layer/convolution.h"
  36. #include "layer/convolutiondepthwise.h"
  37. #include "layer/crop.h"
  38. #include "layer/deconvolution.h"
  39. #include "layer/deconvolutiondepthwise.h"
  40. #include "layer/detectionoutput.h"
  41. #include "layer/dropout.h"
  42. #include "layer/eltwise.h"
  43. #include "layer/elu.h"
  44. #include "layer/exp.h"
  45. #include "layer/flatten.h"
  46. #include "layer/innerproduct.h"
  47. #include "layer/input.h"
  48. #include "layer/instancenorm.h"
  49. #include "layer/interp.h"
  50. #include "layer/log.h"
  51. #include "layer/lrn.h"
  52. #include "layer/mvn.h"
  53. #include "layer/normalize.h"
  54. #include "layer/padding.h"
  55. #include "layer/permute.h"
  56. #include "layer/pooling.h"
  57. #include "layer/power.h"
  58. #include "layer/prelu.h"
  59. #include "layer/priorbox.h"
  60. #include "layer/proposal.h"
  61. #include "layer/psroipooling.h"
  62. #include "layer/quantize.h"
  63. #include "layer/reduction.h"
  64. #include "layer/relu.h"
  65. #include "layer/reorg.h"
  66. #include "layer/requantize.h"
  67. #include "layer/reshape.h"
  68. #include "layer/roialign.h"
  69. #include "layer/roipooling.h"
  70. #include "layer/scale.h"
  71. #include "layer/slice.h"
  72. #include "layer/shufflechannel.h"
  73. #include "layer/softmax.h"
  74. #include "layer/threshold.h"
  75. #include "layer/unaryop.h"
  76. #include "layer/yolodetectionoutput.h"
  77. #include "layer/yolov3detectionoutput.h"
  78. static bool read_int8scale_table(const char* filepath, std::map<std::string, std::vector<float> >& blob_int8scale_table, std::map<std::string, std::vector<float> >& weight_int8scale_table)
  79. {
  80. blob_int8scale_table.clear();
  81. weight_int8scale_table.clear();
  82. FILE* fp = fopen(filepath, "rb");
  83. if (!fp)
  84. {
  85. fprintf(stderr, "fopen %s failed\n", filepath);
  86. return false;
  87. }
  88. bool in_scale_vector = false;
  89. std::string keystr;
  90. std::vector<float> scales;
  91. while (!feof(fp))
  92. {
  93. char key[256];
  94. int nscan = fscanf(fp, "%255s", key);
  95. if (nscan != 1)
  96. {
  97. break;
  98. }
  99. if (in_scale_vector)
  100. {
  101. float scale = 1.f;
  102. int nscan = sscanf(key, "%f", &scale);
  103. if (nscan == 1)
  104. {
  105. scales.push_back(scale);
  106. continue;
  107. }
  108. else
  109. {
  110. // XYZ_param_N pattern
  111. if (strstr(keystr.c_str(), "_param_"))
  112. {
  113. weight_int8scale_table[ keystr ] = scales;
  114. }
  115. else
  116. {
  117. blob_int8scale_table[ keystr ] = scales;
  118. }
  119. keystr.clear();
  120. scales.clear();
  121. in_scale_vector = false;
  122. }
  123. }
  124. if (!in_scale_vector)
  125. {
  126. keystr = key;
  127. in_scale_vector = true;
  128. }
  129. }
  130. if (in_scale_vector)
  131. {
  132. // XYZ_param_N pattern
  133. if (strstr(keystr.c_str(), "_param_"))
  134. {
  135. weight_int8scale_table[ keystr ] = scales;
  136. }
  137. else
  138. {
  139. blob_int8scale_table[ keystr ] = scales;
  140. }
  141. }
  142. fclose(fp);
  143. return true;
  144. }
  145. class NetQuantize : public ncnn::Net
  146. {
  147. public:
  148. // 0=fp32 1=fp16 2=int8
  149. int storage_type;
  150. std::map<std::string, std::vector<float> > blob_int8scale_table;
  151. std::map<std::string, std::vector<float> > weight_int8scale_table;
  152. public:
  153. int quantize_convolution();
  154. int quantize_convolutiondepthwise();
  155. int quantize_innerproduct();
  156. public:
  157. int fprintf_param_int_array(int id, const ncnn::Mat& m, FILE* pp);
  158. int fprintf_param_float_array(int id, const ncnn::Mat& m, FILE* pp);
  159. int fwrite_weight_tag_data(int tag, const ncnn::Mat& data, FILE* bp);
  160. int fwrite_weight_data(const ncnn::Mat& data, FILE* bp);
  161. int save(const char* parampath, const char* binpath);
  162. };
  163. int NetQuantize::quantize_convolution()
  164. {
  165. const int layer_count = layers.size();
  166. for (int i=0; i<layer_count; i++)
  167. {
  168. // find convoultion layer
  169. if (layers[i]->type != "Convolution")
  170. continue;
  171. // find convolution layer
  172. std::map<std::string, std::vector<float> >::iterator iter_data = blob_int8scale_table.find(layers[i]->name);
  173. if (iter_data == blob_int8scale_table.end())
  174. continue;
  175. char key[256];
  176. sprintf(key, "%s_param_0", layers[i]->name.c_str());
  177. std::map<std::string, std::vector<float> >::iterator iter = weight_int8scale_table.find(key);
  178. if (iter == weight_int8scale_table.end())
  179. {
  180. fprintf(stderr, "this layer need to be quantized, but no scale param!\n");
  181. return -1;
  182. }
  183. // Convolution - quantize weight from fp32 to int8
  184. ncnn::Convolution* convolution = (ncnn::Convolution*)layers[i];
  185. std::vector<float> weight_data_int8_scales = iter->second;
  186. fprintf(stderr, "quantize_convolution %s\n", convolution->name.c_str());
  187. {
  188. ncnn::Mat int8_weight_data(convolution->weight_data_size, (size_t)1u);
  189. if (int8_weight_data.empty())
  190. return -100;
  191. const int weight_data_size_output = convolution->weight_data_size / convolution->num_output;
  192. // quantize weight to int8
  193. for (int n=0; n<convolution->num_output; n++)
  194. {
  195. ncnn::Layer* op = ncnn::create_layer(ncnn::LayerType::Quantize);
  196. ncnn::ParamDict pd;
  197. pd.set(0, weight_data_int8_scales[n]);// scale
  198. op->load_param(pd);
  199. ncnn::Option opt;
  200. opt.blob_allocator = int8_weight_data.allocator;
  201. const ncnn::Mat weight_data_n = convolution->weight_data.range(weight_data_size_output * n, weight_data_size_output);
  202. ncnn::Mat int8_weight_data_n = int8_weight_data.range(weight_data_size_output * n, weight_data_size_output);
  203. op->forward(weight_data_n, int8_weight_data_n, opt);
  204. delete op;
  205. }
  206. convolution->weight_data = int8_weight_data;
  207. }
  208. convolution->int8_scale_term = 2;
  209. }
  210. return 0;
  211. }
  212. int NetQuantize::quantize_convolutiondepthwise()
  213. {
  214. const int layer_count = layers.size();
  215. for (int i=0; i<layer_count; i++)
  216. {
  217. // find convoultion layer
  218. if (layers[i]->type != "ConvolutionDepthWise")
  219. continue;
  220. // find convolutiondepthwise layer
  221. std::map<std::string, std::vector<float> >::iterator iter_data = blob_int8scale_table.find(layers[i]->name);
  222. if (iter_data == blob_int8scale_table.end())
  223. continue;
  224. char key[256];
  225. sprintf(key, "%s_param_0", layers[i]->name.c_str());
  226. std::map<std::string, std::vector<float> >::iterator iter = weight_int8scale_table.find(key);
  227. if (iter == weight_int8scale_table.end())
  228. {
  229. fprintf(stderr, "this layer need to be quantized, but no scale param!\n");
  230. return -1;
  231. }
  232. // Convolution - quantize weight from fp32 to int8
  233. ncnn::ConvolutionDepthWise* convdw = (ncnn::ConvolutionDepthWise*)layers[i];
  234. std::vector<float> weight_data_int8_scales = iter->second;
  235. fprintf(stderr, "quantize_convolution %s\n", convdw->name.c_str());
  236. {
  237. ncnn::Mat int8_weight_data(convdw->weight_data_size, (size_t)1u);
  238. if (int8_weight_data.empty())
  239. return -100;
  240. const int weight_data_size_output = convdw->weight_data_size / convdw->group;
  241. // quantize weight to int8
  242. for (int n=0; n<convdw->group; n++)
  243. {
  244. ncnn::Layer* op = ncnn::create_layer(ncnn::LayerType::Quantize);
  245. ncnn::ParamDict pd;
  246. pd.set(0, weight_data_int8_scales[n]);// scale
  247. op->load_param(pd);
  248. ncnn::Option opt;
  249. opt.blob_allocator = int8_weight_data.allocator;
  250. const ncnn::Mat weight_data_n = convdw->weight_data.range(weight_data_size_output * n, weight_data_size_output);
  251. ncnn::Mat int8_weight_data_n = int8_weight_data.range(weight_data_size_output * n, weight_data_size_output);
  252. op->forward(weight_data_n, int8_weight_data_n, opt);
  253. delete op;
  254. }
  255. convdw->weight_data = int8_weight_data;
  256. }
  257. convdw->int8_scale_term = 1;
  258. }
  259. return 0;
  260. }
  261. int NetQuantize::quantize_innerproduct()
  262. {
  263. const int layer_count = layers.size();
  264. for (int i=0; i<layer_count; i++)
  265. {
  266. // find convoultion layer
  267. if (layers[i]->type != "InnerProduct")
  268. continue;
  269. // find InnerProduct layer
  270. std::map<std::string, std::vector<float> >::iterator iter_data = blob_int8scale_table.find(layers[i]->name);
  271. if (iter_data == blob_int8scale_table.end())
  272. continue;
  273. char key[256];
  274. sprintf(key, "%s_param_0", layers[i]->name.c_str());
  275. std::map<std::string, std::vector<float> >::iterator iter = weight_int8scale_table.find(key);
  276. if (iter == weight_int8scale_table.end())
  277. {
  278. fprintf(stderr, "this layer need to be quantized, but no scale param!\n");
  279. return -1;
  280. }
  281. // InnerProduct - quantize weight from fp32 to int8
  282. ncnn::InnerProduct* fc = (ncnn::InnerProduct*)layers[i];
  283. std::vector<float> weight_data_int8_scales = iter->second;
  284. fprintf(stderr, "quantize_convolution %s\n", fc->name.c_str());
  285. {
  286. ncnn::Mat int8_weight_data(fc->weight_data_size, (size_t)1u);
  287. if (int8_weight_data.empty())
  288. return -100;
  289. const int weight_data_size_output = fc->weight_data_size / fc->num_output;
  290. // quantize weight to int8
  291. for (int n=0; n<fc->num_output; n++)
  292. {
  293. ncnn::Layer* op = ncnn::create_layer(ncnn::LayerType::Quantize);
  294. ncnn::ParamDict pd;
  295. pd.set(0, weight_data_int8_scales[n]);// scale
  296. op->load_param(pd);
  297. ncnn::Option opt;
  298. opt.blob_allocator = int8_weight_data.allocator;
  299. const ncnn::Mat weight_data_n = fc->weight_data.range(weight_data_size_output * n, weight_data_size_output);
  300. ncnn::Mat int8_weight_data_n = int8_weight_data.range(weight_data_size_output * n, weight_data_size_output);
  301. op->forward(weight_data_n, int8_weight_data_n, opt);
  302. delete op;
  303. }
  304. fc->weight_data = int8_weight_data;
  305. }
  306. fc->int8_scale_term = 2;
  307. }
  308. return 0;
  309. }
  310. int NetQuantize::fprintf_param_int_array(int id, const ncnn::Mat& m, FILE* pp)
  311. {
  312. const int count = m.w;
  313. const int* ptr = m;
  314. fprintf(pp, " -%d=%d", 23300 + id, count);
  315. for (int i=0; i<count; i++)
  316. {
  317. fprintf(pp, ",%d", ptr[i]);
  318. }
  319. return 0;
  320. }
  321. int NetQuantize::fprintf_param_float_array(int id, const ncnn::Mat& m, FILE* pp)
  322. {
  323. const int count = m.w;
  324. const float* ptr = m;
  325. fprintf(pp, " -%d=%d", 23300 + id, count);
  326. for (int i=0; i<count; i++)
  327. {
  328. fprintf(pp, ",%f", ptr[i]);
  329. }
  330. return 0;
  331. }
  332. static inline size_t alignSize(size_t sz, int n)
  333. {
  334. return (sz + n-1) & -n;
  335. }
  336. int NetQuantize::fwrite_weight_tag_data(int tag, const ncnn::Mat& data, FILE* bp)
  337. {
  338. int p0 = ftell(bp);
  339. ncnn::Mat data_flattened = data.reshape(data.w * data.h * data.c);
  340. if (data.elemsize == 1)
  341. tag = 0x000D4B38; // int8 magic
  342. fwrite(&tag, sizeof(int), 1, bp);
  343. fwrite(data_flattened.data, data_flattened.elemsize, data_flattened.w, bp);
  344. // padding to 32bit align
  345. int nwrite = ftell(bp) - p0;
  346. int nalign = alignSize(nwrite, 4);
  347. unsigned char padding[4] = {0x00, 0x00, 0x00, 0x00};
  348. fwrite(padding, sizeof(unsigned char), nalign - nwrite, bp);
  349. return 0;
  350. }
  351. int NetQuantize::fwrite_weight_data(const ncnn::Mat& data, FILE* bp)
  352. {
  353. int p0 = ftell(bp);
  354. ncnn::Mat data_flattened = data.reshape(data.w * data.h * data.c);
  355. fwrite(data_flattened.data, data_flattened.elemsize, data_flattened.w, bp);
  356. // padding to 32bit align
  357. int nwrite = ftell(bp) - p0;
  358. int nalign = alignSize(nwrite, 4);
  359. unsigned char padding[4] = {0x00, 0x00, 0x00, 0x00};
  360. fwrite(padding, sizeof(unsigned char), nalign - nwrite, bp);
  361. return 0;
  362. }
  363. int NetQuantize::save(const char* parampath, const char* binpath)
  364. {
  365. FILE* pp = fopen(parampath, "wb");
  366. FILE* bp = fopen(binpath, "wb");
  367. fprintf(pp, "7767517\n");
  368. const int layer_count = layers.size();
  369. int layer_count_fused = 0;
  370. std::set<std::string> blob_names;
  371. for (int i=0; i<layer_count; i++)
  372. {
  373. const ncnn::Layer* layer = layers[i];
  374. if (layer->type == "ncnnfused")
  375. continue;
  376. layer_count_fused++;
  377. int bottom_count = layer->bottoms.size();
  378. for (int j=0; j<bottom_count; j++)
  379. {
  380. int bottom_blob_index = layer->bottoms[j];
  381. blob_names.insert(blobs[bottom_blob_index].name);
  382. }
  383. int top_count = layer->tops.size();
  384. for (int j=0; j<top_count; j++)
  385. {
  386. int top_blob_index = layer->tops[j];
  387. blob_names.insert(blobs[top_blob_index].name);
  388. }
  389. }
  390. int blob_count_fused = blob_names.size();
  391. fprintf(pp, "%d %d\n", layer_count_fused, blob_count_fused);
  392. for (int i=0; i<layer_count; i++)
  393. {
  394. const ncnn::Layer* layer = layers[i];
  395. if (layer->type == "ncnnfused")
  396. continue;
  397. int bottom_count = layer->bottoms.size();
  398. int top_count = layer->tops.size();
  399. fprintf(pp, "%-24s %-24s %d %d", layer->type.c_str(), layer->name.c_str(), bottom_count, top_count);
  400. for (int j=0; j<bottom_count; j++)
  401. {
  402. int bottom_blob_index = layer->bottoms[j];
  403. fprintf(pp, " %s", blobs[bottom_blob_index].name.c_str());
  404. }
  405. for (int j=0; j<top_count; j++)
  406. {
  407. int top_blob_index = layer->tops[j];
  408. fprintf(pp, " %s", blobs[top_blob_index].name.c_str());
  409. }
  410. ncnn::Layer* layer_default = ncnn::create_layer(layer->typeindex);
  411. ncnn::ParamDict pd;
  412. layer_default->load_param(pd);
  413. #define fprintf_param_value(format, phase) \
  414. { if (op->phase != op_default->phase) fprintf(pp, format, op->phase); }
  415. if (layer->type == "BatchNorm")
  416. {
  417. ncnn::BatchNorm* op = (ncnn::BatchNorm*)layer;
  418. ncnn::BatchNorm* op_default = (ncnn::BatchNorm*)layer_default;
  419. fprintf_param_value(" 0=%d", channels)
  420. fprintf_param_value(" 1=%f", eps)
  421. fwrite_weight_data(op->slope_data, bp);
  422. fwrite_weight_data(op->mean_data, bp);
  423. fwrite_weight_data(op->var_data, bp);
  424. fwrite_weight_data(op->bias_data, bp);
  425. }
  426. else if (layer->type == "Bias")
  427. {
  428. ncnn::Bias* op = (ncnn::Bias*)layer;
  429. ncnn::Bias* op_default = (ncnn::Bias*)layer_default;
  430. fprintf_param_value(" 0=%d", bias_data_size)
  431. fwrite_weight_data(op->bias_data, bp);
  432. }
  433. else if (layer->type == "BinaryOp")
  434. {
  435. ncnn::BinaryOp* op = (ncnn::BinaryOp*)layer;
  436. ncnn::BinaryOp* op_default = (ncnn::BinaryOp*)layer_default;
  437. fprintf_param_value(" 0=%d", op_type)
  438. fprintf_param_value(" 1=%d", with_scalar)
  439. fprintf_param_value(" 2=%f", b)
  440. }
  441. else if (layer->type == "Clip")
  442. {
  443. ncnn::Clip* op = (ncnn::Clip*)layer;
  444. ncnn::Clip* op_default = (ncnn::Clip*)layer_default;
  445. fprintf_param_value(" 0=%f", min)
  446. fprintf_param_value(" 1=%f", max)
  447. }
  448. else if (layer->type == "Concat")
  449. {
  450. ncnn::Concat* op = (ncnn::Concat*)layer;
  451. ncnn::Concat* op_default = (ncnn::Concat*)layer_default;
  452. fprintf_param_value(" 0=%d", axis)
  453. }
  454. else if (layer->type == "Convolution")
  455. {
  456. ncnn::Convolution* op = (ncnn::Convolution*)layer;
  457. ncnn::Convolution* op_default = (ncnn::Convolution*)layer_default;
  458. fprintf_param_value(" 0=%d", num_output)
  459. fprintf_param_value(" 1=%d", kernel_w)
  460. { if (op->kernel_h != op->kernel_w) fprintf(pp, " 11=%d", op->kernel_h); }
  461. fprintf_param_value(" 2=%d", dilation_w)
  462. { if (op->dilation_h != op->dilation_w) fprintf(pp, " 12=%d", op->dilation_h); }
  463. fprintf_param_value(" 3=%d", stride_w)
  464. { if (op->stride_h != op->stride_w) fprintf(pp, " 13=%d", op->stride_h); }
  465. fprintf_param_value(" 4=%d", pad_left)
  466. { if (op->pad_top != op->pad_left) fprintf(pp, " 14=%d", op->pad_top); }
  467. { if (op->pad_right != op->pad_left) fprintf(pp, " 15=%d", op->pad_right); }
  468. { if (op->pad_bottom != op->pad_top) fprintf(pp, " 16=%d", op->pad_bottom); }
  469. fprintf_param_value(" 5=%d", bias_term)
  470. fprintf_param_value(" 6=%d", weight_data_size)
  471. fprintf_param_value(" 8=%d", int8_scale_term)
  472. fprintf_param_value(" 9=%d", activation_type)
  473. { if (!op->activation_params.empty()) fprintf_param_float_array(10, op->activation_params, pp); }
  474. fwrite_weight_tag_data(0, op->weight_data, bp);
  475. fwrite_weight_data(op->bias_data, bp);
  476. // write int8_scale data
  477. if (op->int8_scale_term)
  478. {
  479. std::vector<float> weight_int8scale;
  480. std::vector<float> blob_int8scale;
  481. char key[256];
  482. sprintf(key, "%s_param_0", layer->name.c_str());
  483. if (weight_int8scale_table.find(std::string(key)) != weight_int8scale_table.end())
  484. {
  485. weight_int8scale = weight_int8scale_table[std::string(key)];
  486. }
  487. if (blob_int8scale_table.find(layer->name) != blob_int8scale_table.end())
  488. {
  489. blob_int8scale = blob_int8scale_table[layer->name];
  490. }
  491. // write int8_scale data
  492. fwrite(weight_int8scale.data(), sizeof(float), weight_int8scale.size(), bp);
  493. fwrite(blob_int8scale.data(), sizeof(float), blob_int8scale.size(), bp);
  494. }
  495. }
  496. else if (layer->type == "ConvolutionDepthWise")
  497. {
  498. ncnn::ConvolutionDepthWise* op = (ncnn::ConvolutionDepthWise*)layer;
  499. ncnn::ConvolutionDepthWise* op_default = (ncnn::ConvolutionDepthWise*)layer_default;
  500. fprintf_param_value(" 0=%d", num_output)
  501. fprintf_param_value(" 1=%d", kernel_w)
  502. { if (op->kernel_h != op->kernel_w) fprintf(pp, " 11=%d", op->kernel_h); }
  503. fprintf_param_value(" 2=%d", dilation_w)
  504. { if (op->dilation_h != op->dilation_w) fprintf(pp, " 12=%d", op->dilation_h); }
  505. fprintf_param_value(" 3=%d", stride_w)
  506. { if (op->stride_h != op->stride_w) fprintf(pp, " 13=%d", op->stride_h); }
  507. fprintf_param_value(" 4=%d", pad_left)
  508. { if (op->pad_top != op->pad_left) fprintf(pp, " 14=%d", op->pad_top); }
  509. { if (op->pad_right != op->pad_left) fprintf(pp, " 15=%d", op->pad_right); }
  510. { if (op->pad_bottom != op->pad_top) fprintf(pp, " 16=%d", op->pad_bottom); }
  511. fprintf_param_value(" 5=%d", bias_term)
  512. fprintf_param_value(" 6=%d", weight_data_size)
  513. fprintf_param_value(" 7=%d", group)
  514. fprintf_param_value(" 8=%d", int8_scale_term)
  515. fprintf_param_value(" 9=%d", activation_type)
  516. { if (!op->activation_params.empty()) fprintf_param_float_array(10, op->activation_params, pp); }
  517. fwrite_weight_tag_data(0, op->weight_data, bp);
  518. fwrite_weight_data(op->bias_data, bp);
  519. // write int8_scale data
  520. if (op->int8_scale_term)
  521. {
  522. std::vector<float> weight_int8scale;
  523. std::vector<float> blob_int8scale;
  524. char key[256];
  525. sprintf(key, "%s_param_0", layer->name.c_str());
  526. if (weight_int8scale_table.find(std::string(key)) != weight_int8scale_table.end())
  527. {
  528. weight_int8scale = weight_int8scale_table[std::string(key)];
  529. }
  530. if (blob_int8scale_table.find(layer->name) != blob_int8scale_table.end())
  531. {
  532. blob_int8scale = blob_int8scale_table[layer->name];
  533. }
  534. // write int8_scale data
  535. fwrite(weight_int8scale.data(), sizeof(float), weight_int8scale.size(), bp);
  536. fwrite(blob_int8scale.data(), sizeof(float), blob_int8scale.size(), bp);
  537. }
  538. }
  539. else if (layer->type == "Crop")
  540. {
  541. ncnn::Crop* op = (ncnn::Crop*)layer;
  542. ncnn::Crop* op_default = (ncnn::Crop*)layer_default;
  543. fprintf_param_value(" 0=%d", woffset)
  544. fprintf_param_value(" 1=%d", hoffset)
  545. fprintf_param_value(" 2=%d", coffset)
  546. fprintf_param_value(" 3=%d", outw)
  547. fprintf_param_value(" 4=%d", outh)
  548. fprintf_param_value(" 5=%d", outc)
  549. }
  550. else if (layer->type == "Deconvolution")
  551. {
  552. ncnn::Deconvolution* op = (ncnn::Deconvolution*)layer;
  553. ncnn::Deconvolution* op_default = (ncnn::Deconvolution*)layer_default;
  554. fprintf_param_value(" 0=%d", num_output)
  555. fprintf_param_value(" 1=%d", kernel_w)
  556. { if (op->kernel_h != op->kernel_w) fprintf(pp, " 11=%d", op->kernel_h); }
  557. fprintf_param_value(" 2=%d", dilation_w)
  558. { if (op->dilation_h != op->dilation_w) fprintf(pp, " 12=%d", op->dilation_h); }
  559. fprintf_param_value(" 3=%d", stride_w)
  560. { if (op->stride_h != op->stride_w) fprintf(pp, " 13=%d", op->stride_h); }
  561. fprintf_param_value(" 4=%d", pad_left)
  562. { if (op->pad_top != op->pad_left) fprintf(pp, " 14=%d", op->pad_top); }
  563. { if (op->pad_right != op->pad_left) fprintf(pp, " 15=%d", op->pad_right); }
  564. { if (op->pad_bottom != op->pad_top) fprintf(pp, " 16=%d", op->pad_bottom); }
  565. fprintf_param_value(" 5=%d", bias_term)
  566. fprintf_param_value(" 6=%d", weight_data_size)
  567. fprintf_param_value(" 9=%d", activation_type)
  568. { if (!op->activation_params.empty()) fprintf_param_float_array(10, op->activation_params, pp); }
  569. fwrite_weight_tag_data(0, op->weight_data, bp);
  570. fwrite_weight_data(op->bias_data, bp);
  571. }
  572. else if (layer->type == "DeconvolutionDepthWise")
  573. {
  574. ncnn::DeconvolutionDepthWise* op = (ncnn::DeconvolutionDepthWise*)layer;
  575. ncnn::DeconvolutionDepthWise* op_default = (ncnn::DeconvolutionDepthWise*)layer_default;
  576. fprintf_param_value(" 0=%d", num_output)
  577. fprintf_param_value(" 1=%d", kernel_w)
  578. { if (op->kernel_h != op->kernel_w) fprintf(pp, " 11=%d", op->kernel_h); }
  579. fprintf_param_value(" 2=%d", dilation_w)
  580. { if (op->dilation_h != op->dilation_w) fprintf(pp, " 12=%d", op->dilation_h); }
  581. fprintf_param_value(" 3=%d", stride_w)
  582. { if (op->stride_h != op->stride_w) fprintf(pp, " 13=%d", op->stride_h); }
  583. fprintf_param_value(" 4=%d", pad_left)
  584. { if (op->pad_top != op->pad_left) fprintf(pp, " 14=%d", op->pad_top); }
  585. { if (op->pad_right != op->pad_left) fprintf(pp, " 15=%d", op->pad_right); }
  586. { if (op->pad_bottom != op->pad_top) fprintf(pp, " 16=%d", op->pad_bottom); }
  587. fprintf_param_value(" 5=%d", bias_term)
  588. fprintf_param_value(" 6=%d", weight_data_size)
  589. fprintf_param_value(" 7=%d", group)
  590. fprintf_param_value(" 9=%d", activation_type)
  591. { if (!op->activation_params.empty()) fprintf_param_float_array(10, op->activation_params, pp); }
  592. fwrite_weight_tag_data(0, op->weight_data, bp);
  593. fwrite_weight_data(op->bias_data, bp);
  594. }
  595. else if (layer->type == "DetectionOutput")
  596. {
  597. ncnn::DetectionOutput* op = (ncnn::DetectionOutput*)layer;
  598. ncnn::DetectionOutput* op_default = (ncnn::DetectionOutput*)layer_default;
  599. fprintf_param_value(" 0=%d", num_class)
  600. fprintf_param_value(" 1=%f", nms_threshold)
  601. fprintf_param_value(" 2=%d", nms_top_k)
  602. fprintf_param_value(" 3=%d", keep_top_k)
  603. fprintf_param_value(" 4=%f", confidence_threshold)
  604. fprintf_param_value(" 5=%f", variances[0])
  605. fprintf_param_value(" 6=%f", variances[1])
  606. fprintf_param_value(" 7=%f", variances[2])
  607. fprintf_param_value(" 8=%f", variances[3])
  608. }
  609. else if (layer->type == "Dropout")
  610. {
  611. ncnn::Dropout* op = (ncnn::Dropout*)layer;
  612. ncnn::Dropout* op_default = (ncnn::Dropout*)layer_default;
  613. fprintf_param_value(" 0=%f", scale)
  614. }
  615. else if (layer->type == "Eltwise")
  616. {
  617. ncnn::Eltwise* op = (ncnn::Eltwise*)layer;
  618. ncnn::Eltwise* op_default = (ncnn::Eltwise*)layer_default;
  619. fprintf_param_value(" 0=%d", op_type)
  620. { if (!op->coeffs.empty()) fprintf_param_float_array(1, op->coeffs, pp); }
  621. }
  622. else if (layer->type == "ELU")
  623. {
  624. ncnn::ELU* op = (ncnn::ELU*)layer;
  625. ncnn::ELU* op_default = (ncnn::ELU*)layer_default;
  626. fprintf_param_value(" 0=%f", alpha)
  627. }
  628. else if (layer->type == "Exp")
  629. {
  630. ncnn::Exp* op = (ncnn::Exp*)layer;
  631. ncnn::Exp* op_default = (ncnn::Exp*)layer_default;
  632. fprintf_param_value(" 0=%f", base)
  633. fprintf_param_value(" 1=%f", scale)
  634. fprintf_param_value(" 2=%f", shift)
  635. }
  636. else if (layer->type == "InnerProduct")
  637. {
  638. ncnn::InnerProduct* op = (ncnn::InnerProduct*)layer;
  639. ncnn::InnerProduct* op_default = (ncnn::InnerProduct*)layer_default;
  640. fprintf_param_value(" 0=%d", num_output)
  641. fprintf_param_value(" 1=%d", bias_term)
  642. fprintf_param_value(" 2=%d", weight_data_size)
  643. fprintf_param_value(" 8=%d", int8_scale_term)
  644. fprintf_param_value(" 9=%d", activation_type)
  645. { if (!op->activation_params.empty()) fprintf_param_float_array(10, op->activation_params, pp); }
  646. fwrite_weight_tag_data(0, op->weight_data, bp);
  647. fwrite_weight_data(op->bias_data, bp);
  648. // write int8_scale data
  649. if (op->int8_scale_term)
  650. {
  651. std::vector<float> weight_int8scale;
  652. std::vector<float> blob_int8scale;
  653. char key[256];
  654. sprintf(key, "%s_param_0", layer->name.c_str());
  655. if (weight_int8scale_table.find(std::string(key)) != weight_int8scale_table.end())
  656. {
  657. weight_int8scale = weight_int8scale_table[std::string(key)];
  658. }
  659. if (blob_int8scale_table.find(layer->name) != blob_int8scale_table.end())
  660. {
  661. blob_int8scale = blob_int8scale_table[layer->name];
  662. }
  663. // write int8_scale data
  664. fwrite(weight_int8scale.data(), sizeof(float), weight_int8scale.size(), bp);
  665. fwrite(blob_int8scale.data(), sizeof(float), blob_int8scale.size(), bp);
  666. }
  667. }
  668. else if (layer->type == "Input")
  669. {
  670. ncnn::Input* op = (ncnn::Input*)layer;
  671. ncnn::Input* op_default = (ncnn::Input*)layer_default;
  672. fprintf_param_value(" 0=%d", w)
  673. fprintf_param_value(" 1=%d", h)
  674. fprintf_param_value(" 2=%d", c)
  675. }
  676. else if (layer->type == "InstanceNorm")
  677. {
  678. ncnn::InstanceNorm* op = (ncnn::InstanceNorm*)layer;
  679. ncnn::InstanceNorm* op_default = (ncnn::InstanceNorm*)layer_default;
  680. fprintf_param_value(" 0=%d", channels)
  681. fprintf_param_value(" 1=%f", eps)
  682. }
  683. else if (layer->type == "Interp")
  684. {
  685. ncnn::Interp* op = (ncnn::Interp*)layer;
  686. ncnn::Interp* op_default = (ncnn::Interp*)layer_default;
  687. fprintf_param_value(" 0=%d", resize_type)
  688. fprintf_param_value(" 1=%f", height_scale)
  689. fprintf_param_value(" 2=%f", width_scale)
  690. fprintf_param_value(" 3=%d", output_height)
  691. fprintf_param_value(" 4=%d", output_width)
  692. }
  693. else if (layer->type == "Log")
  694. {
  695. ncnn::Log* op = (ncnn::Log*)layer;
  696. ncnn::Log* op_default = (ncnn::Log*)layer_default;
  697. fprintf_param_value(" 0=%f", base)
  698. fprintf_param_value(" 1=%f", scale)
  699. fprintf_param_value(" 2=%f", shift)
  700. }
  701. else if (layer->type == "LRN")
  702. {
  703. ncnn::LRN* op = (ncnn::LRN*)layer;
  704. ncnn::LRN* op_default = (ncnn::LRN*)layer_default;
  705. fprintf_param_value(" 0=%d", region_type)
  706. fprintf_param_value(" 1=%d", local_size)
  707. fprintf_param_value(" 2=%f", alpha)
  708. fprintf_param_value(" 3=%f", beta)
  709. fprintf_param_value(" 4=%f", bias)
  710. }
  711. else if (layer->type == "MVN")
  712. {
  713. ncnn::MVN* op = (ncnn::MVN*)layer;
  714. ncnn::MVN* op_default = (ncnn::MVN*)layer_default;
  715. fprintf_param_value(" 0=%d", normalize_variance)
  716. fprintf_param_value(" 1=%d", across_channels)
  717. fprintf_param_value(" 2=%f", eps)
  718. }
  719. else if (layer->type == "Normalize")
  720. {
  721. ncnn::Normalize* op = (ncnn::Normalize*)layer;
  722. ncnn::Normalize* op_default = (ncnn::Normalize*)layer_default;
  723. fprintf_param_value(" 0=%d", across_spatial)
  724. fprintf_param_value(" 1=%d", channel_shared)
  725. fprintf_param_value(" 2=%f", eps)
  726. fprintf_param_value(" 3=%d", scale_data_size)
  727. fprintf_param_value(" 4=%d", across_channel)
  728. fwrite_weight_data(op->scale_data, bp);
  729. }
  730. else if (layer->type == "Padding")
  731. {
  732. ncnn::Padding* op = (ncnn::Padding*)layer;
  733. ncnn::Padding* op_default = (ncnn::Padding*)layer_default;
  734. fprintf_param_value(" 0=%d", top)
  735. fprintf_param_value(" 1=%d", bottom)
  736. fprintf_param_value(" 2=%d", left)
  737. fprintf_param_value(" 3=%d", right)
  738. fprintf_param_value(" 4=%d", type)
  739. fprintf_param_value(" 5=%f", value)
  740. }
  741. else if (layer->type == "Permute")
  742. {
  743. ncnn::Permute* op = (ncnn::Permute*)layer;
  744. ncnn::Permute* op_default = (ncnn::Permute*)layer_default;
  745. fprintf_param_value(" 0=%d", order_type)
  746. }
  747. else if (layer->type == "Pooling")
  748. {
  749. ncnn::Pooling* op = (ncnn::Pooling*)layer;
  750. ncnn::Pooling* op_default = (ncnn::Pooling*)layer_default;
  751. fprintf_param_value(" 0=%d", pooling_type)
  752. fprintf_param_value(" 1=%d", kernel_w)
  753. { if (op->kernel_h != op->kernel_w) fprintf(pp, " 11=%d", op->kernel_h); }
  754. fprintf_param_value(" 2=%d", stride_w)
  755. { if (op->stride_h != op->stride_w) fprintf(pp, " 12=%d", op->stride_h); }
  756. fprintf_param_value(" 3=%d", pad_left)
  757. { if (op->pad_top != op->pad_left) fprintf(pp, " 13=%d", op->pad_top); }
  758. { if (op->pad_right != op->pad_left) fprintf(pp, " 14=%d", op->pad_right); }
  759. { if (op->pad_bottom != op->pad_top) fprintf(pp, " 15=%d", op->pad_bottom); }
  760. fprintf_param_value(" 4=%d", global_pooling)
  761. fprintf_param_value(" 5=%d", pad_mode)
  762. }
  763. else if (layer->type == "Power")
  764. {
  765. ncnn::Power* op = (ncnn::Power*)layer;
  766. ncnn::Power* op_default = (ncnn::Power*)layer_default;
  767. fprintf_param_value(" 0=%f", power)
  768. fprintf_param_value(" 1=%f", scale)
  769. fprintf_param_value(" 2=%f", shift)
  770. }
  771. else if (layer->type == "PReLU")
  772. {
  773. ncnn::PReLU* op = (ncnn::PReLU*)layer;
  774. ncnn::PReLU* op_default = (ncnn::PReLU*)layer_default;
  775. fprintf_param_value(" 0=%d", num_slope)
  776. fwrite_weight_data(op->slope_data, bp);
  777. }
  778. else if (layer->type == "PriorBox")
  779. {
  780. ncnn::PriorBox* op = (ncnn::PriorBox*)layer;
  781. ncnn::PriorBox* op_default = (ncnn::PriorBox*)layer_default;
  782. { if (!op->min_sizes.empty()) fprintf_param_float_array(0, op->min_sizes, pp); }
  783. { if (!op->max_sizes.empty()) fprintf_param_float_array(1, op->max_sizes, pp); }
  784. { if (!op->aspect_ratios.empty()) fprintf_param_float_array(2, op->aspect_ratios, pp); }
  785. fprintf_param_value(" 3=%f", variances[0])
  786. fprintf_param_value(" 4=%f", variances[1])
  787. fprintf_param_value(" 5=%f", variances[2])
  788. fprintf_param_value(" 6=%f", variances[3])
  789. fprintf_param_value(" 7=%d", flip)
  790. fprintf_param_value(" 8=%d", clip)
  791. fprintf_param_value(" 9=%d", image_width)
  792. fprintf_param_value(" 10=%d", image_height)
  793. fprintf_param_value(" 11=%f", step_width)
  794. fprintf_param_value(" 12=%f", step_height)
  795. fprintf_param_value(" 13=%f", offset)
  796. }
  797. else if (layer->type == "Proposal")
  798. {
  799. ncnn::Proposal* op = (ncnn::Proposal*)layer;
  800. ncnn::Proposal* op_default = (ncnn::Proposal*)layer_default;
  801. fprintf_param_value(" 0=%d", feat_stride)
  802. fprintf_param_value(" 1=%d", base_size)
  803. fprintf_param_value(" 2=%d", pre_nms_topN)
  804. fprintf_param_value(" 3=%d", after_nms_topN)
  805. fprintf_param_value(" 4=%f", nms_thresh)
  806. fprintf_param_value(" 5=%d", min_size)
  807. }
  808. else if (layer->type == "PSROIPooling")
  809. {
  810. ncnn::PSROIPooling* op = (ncnn::PSROIPooling*)layer;
  811. ncnn::PSROIPooling* op_default = (ncnn::PSROIPooling*)layer_default;
  812. fprintf_param_value(" 0=%d", pooled_width)
  813. fprintf_param_value(" 1=%d", pooled_height)
  814. fprintf_param_value(" 2=%f", spatial_scale)
  815. fprintf_param_value(" 3=%d", output_dim)
  816. }
  817. else if (layer->type == "Quantize")
  818. {
  819. ncnn::Quantize* op = (ncnn::Quantize*)layer;
  820. ncnn::Quantize* op_default = (ncnn::Quantize*)layer_default;
  821. fprintf_param_value(" 0=%f", scale)
  822. }
  823. else if (layer->type == "Reduction")
  824. {
  825. ncnn::Reduction* op = (ncnn::Reduction*)layer;
  826. ncnn::Reduction* op_default = (ncnn::Reduction*)layer_default;
  827. fprintf_param_value(" 0=%d", operation)
  828. fprintf_param_value(" 1=%d", reduce_all)
  829. fprintf_param_value(" 2=%f", coeff)
  830. }
  831. else if (layer->type == "ReLU")
  832. {
  833. ncnn::ReLU* op = (ncnn::ReLU*)layer;
  834. ncnn::ReLU* op_default = (ncnn::ReLU*)layer_default;
  835. fprintf_param_value(" 0=%f", slope)
  836. }
  837. else if (layer->type == "Reorg")
  838. {
  839. ncnn::Reorg* op = (ncnn::Reorg*)layer;
  840. ncnn::Reorg* op_default = (ncnn::Reorg*)layer_default;
  841. fprintf_param_value(" 0=%d", stride)
  842. }
  843. else if (layer->type == "Requantize")
  844. {
  845. ncnn::Requantize* op = (ncnn::Requantize*)layer;
  846. ncnn::Requantize* op_default = (ncnn::Requantize*)layer_default;
  847. fprintf_param_value(" 0=%f", scale_in)
  848. fprintf_param_value(" 1=%f", scale_out)
  849. fprintf_param_value(" 2=%d", bias_term)
  850. fprintf_param_value(" 3=%d", bias_data_size)
  851. fprintf_param_value(" 4=%d", fusion_relu)
  852. }
  853. else if (layer->type == "Reshape")
  854. {
  855. ncnn::Reshape* op = (ncnn::Reshape*)layer;
  856. ncnn::Reshape* op_default = (ncnn::Reshape*)layer_default;
  857. fprintf_param_value(" 0=%d", w)
  858. fprintf_param_value(" 1=%d", h)
  859. fprintf_param_value(" 2=%d", c)
  860. fprintf_param_value(" 3=%d", permute)
  861. }
  862. else if (layer->type == "ROIAlign")
  863. {
  864. ncnn::ROIAlign* op = (ncnn::ROIAlign*)layer;
  865. ncnn::ROIAlign* op_default = (ncnn::ROIAlign*)layer_default;
  866. fprintf_param_value(" 0=%d", pooled_width)
  867. fprintf_param_value(" 1=%d", pooled_height)
  868. fprintf_param_value(" 2=%f", spatial_scale)
  869. }
  870. else if (layer->type == "ROIPooling")
  871. {
  872. ncnn::ROIPooling* op = (ncnn::ROIPooling*)layer;
  873. ncnn::ROIPooling* op_default = (ncnn::ROIPooling*)layer_default;
  874. fprintf_param_value(" 0=%d", pooled_width)
  875. fprintf_param_value(" 1=%d", pooled_height)
  876. fprintf_param_value(" 2=%f", spatial_scale)
  877. }
  878. else if (layer->type == "Scale")
  879. {
  880. ncnn::Scale* op = (ncnn::Scale*)layer;
  881. ncnn::Scale* op_default = (ncnn::Scale*)layer_default;
  882. fprintf_param_value(" 0=%d", scale_data_size)
  883. fprintf_param_value(" 1=%d", bias_term)
  884. fwrite_weight_data(op->scale_data, bp);
  885. fwrite_weight_data(op->bias_data, bp);
  886. }
  887. else if (layer->type == "ShuffleChannel")
  888. {
  889. ncnn::ShuffleChannel* op = (ncnn::ShuffleChannel*)layer;
  890. ncnn::ShuffleChannel* op_default = (ncnn::ShuffleChannel*)layer_default;
  891. fprintf_param_value(" 0=%d", group)
  892. }
  893. else if (layer->type == "Slice")
  894. {
  895. ncnn::Slice* op = (ncnn::Slice*)layer;
  896. ncnn::Slice* op_default = (ncnn::Slice*)layer_default;
  897. { if (!op->slices.empty()) fprintf_param_int_array(0, op->slices, pp); }
  898. fprintf_param_value(" 1=%d", axis)
  899. }
  900. else if (layer->type == "Softmax")
  901. {
  902. ncnn::Softmax* op = (ncnn::Softmax*)layer;
  903. ncnn::Softmax* op_default = (ncnn::Softmax*)layer_default;
  904. fprintf_param_value(" 0=%d", axis)
  905. // HACK
  906. if (op->axis != 0)
  907. {
  908. int fixbug0 = 1;
  909. fprintf(pp, " 1=%d", fixbug0);
  910. }
  911. }
  912. else if (layer->type == "Threshold")
  913. {
  914. ncnn::Threshold* op = (ncnn::Threshold*)layer;
  915. ncnn::Threshold* op_default = (ncnn::Threshold*)layer_default;
  916. fprintf_param_value(" 0=%f", threshold)
  917. }
  918. else if (layer->type == "UnaryOp")
  919. {
  920. ncnn::UnaryOp* op = (ncnn::UnaryOp*)layer;
  921. ncnn::UnaryOp* op_default = (ncnn::UnaryOp*)layer_default;
  922. fprintf_param_value(" 0=%d", op_type)
  923. }
  924. else if (layer->type == "YoloDetectionOutput")
  925. {
  926. ncnn::YoloDetectionOutput* op = (ncnn::YoloDetectionOutput*)layer;
  927. ncnn::YoloDetectionOutput* op_default = (ncnn::YoloDetectionOutput*)layer_default;
  928. fprintf_param_value(" 0=%d", num_class)
  929. fprintf_param_value(" 1=%d", num_box)
  930. fprintf_param_value(" 2=%f", confidence_threshold)
  931. fprintf_param_value(" 3=%f", nms_threshold)
  932. { if (!op->biases.empty()) fprintf_param_float_array(4, op->biases, pp); }
  933. }
  934. else if (layer->type == "Yolov3DetectionOutput")
  935. {
  936. ncnn::Yolov3DetectionOutput* op = (ncnn::Yolov3DetectionOutput*)layer;
  937. ncnn::Yolov3DetectionOutput* op_default = (ncnn::Yolov3DetectionOutput*)layer_default;
  938. fprintf_param_value(" 0=%d", num_class)
  939. fprintf_param_value(" 1=%d", num_box)
  940. fprintf_param_value(" 2=%f", confidence_threshold)
  941. fprintf_param_value(" 3=%f", nms_threshold)
  942. { if (!op->biases.empty()) fprintf_param_float_array(4, op->biases, pp); }
  943. { if (!op->mask.empty()) fprintf_param_int_array(5, op->mask, pp); }
  944. { if (!op->anchors_scale.empty()) fprintf_param_float_array(6, op->anchors_scale, pp); }
  945. }
  946. #undef fprintf_param_value
  947. fprintf(pp, "\n");
  948. delete layer_default;
  949. }
  950. fclose(pp);
  951. fclose(bp);
  952. return 0;
  953. }
  954. int main(int argc, char** argv)
  955. {
  956. if (argc != 6)
  957. {
  958. fprintf(stderr, "usage: %s [inparam] [inbin] [outparam] [outbin] [calibration table]\n", argv[0]);
  959. return -1;
  960. }
  961. const char* inparam = argv[1];
  962. const char* inbin = argv[2];
  963. const char* outparam = argv[3];
  964. const char* outbin = argv[4];
  965. const char* int8scale_table_path = argv[5];
  966. NetQuantize quantizer;
  967. // parse the calibration scale table
  968. if (int8scale_table_path)
  969. {
  970. bool s2 = read_int8scale_table(int8scale_table_path, quantizer.blob_int8scale_table, quantizer.weight_int8scale_table);
  971. if (!s2)
  972. {
  973. fprintf(stderr, "read_int8scale_table failed\n");
  974. return -1;
  975. }
  976. }
  977. quantizer.load_param(inparam);
  978. quantizer.load_model(inbin);
  979. quantizer.quantize_convolution();
  980. quantizer.quantize_convolutiondepthwise();
  981. quantizer.quantize_innerproduct();
  982. quantizer.save(outparam, outbin);
  983. return 0;
  984. }