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

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