Open LeiWang1999 opened 3 years ago
比如我现在的graph里有一个输出channel只为1的卷积层,在进行int8量化的时候,所有的量化参数都是保存在scale_list里:
// quant_save_graph.cpp for (int ch = 0; ch < channel_num; ch++) { for (int j = 0; j < cstep; j++) { if (weight_data[ch * cstep + j] == 0 || weight_scale_list[ch] == 0) i8_weight_data[ch * cstep + j] = 0; else { float int8_data = round(weight_data[ch * cstep + j] / weight_scale_list[ch]); int8_data = int8_data > 127.f ? 127.f : int8_data; int8_data = int8_data < -127.f ? -127.f : int8_data; i8_weight_data[ch * cstep + j] = int8_t(int8_data); } } } weight_tensor->scale_list = weight_scale_list; weight_tensor->zp_list = weight_zp_list; weight_tensor->data_type = TENGINE_DT_INT8; weight_tensor->elem_size = sizeof(int8_t); // int8, signed char weight_tensor->data = i8_weight_data; weight_tensor->quant_param_num = channel_num;
Tengine现在的设计大部分都是分两块的,当output channel为1的时候,存储在scale里、其他情况都存储在scale_list里。而这里的逻辑是无论channel数为多少都会存在scale_list里,但是在量化完成之后 save_graph 阶段,这个时候量化的scale是存储在scale_list里的而不是scale,这样会导致dump成文件的时候保存了无效的值:
if (v_qtparams->v_num == 1) { TM2_QuantParam qtparam; qtparam.scale = tensor->scale; qtparam.zero_point = tensor->zero_point; v_qtparams->offsets[0] = WriteTmObject(start_ptr, cur_pos, &qtparam, sizeof(TM2_QuantParam)); } else if (v_qtparams->v_num > 1) { for (unsigned int i = 0; i < v_qtparams->v_num; i++) { TM2_QuantParam qtparam; qtparam.zero_point = tensor->zp_list[i]; qtparam.scale = tensor->scale_list[i]; v_qtparams->offsets[i] = WriteTmObject(start_ptr, cur_pos, &qtparam, sizeof(TM2_QuantParam)); } }
可以考虑在下次的时候换一波血,把scale这个机制取消了,直接用scale_list就可以。
Did this bug has already fix?
@LeiWang1999 @BUG1989 大佬们,这个问题会引起输入为灰度图的模型量化精度奔溃吗
情况说明
比如我现在的graph里有一个输出channel只为1的卷积层,在进行int8量化的时候,所有的量化参数都是保存在scale_list里:
Tengine现在的设计大部分都是分两块的,当output channel为1的时候,存储在scale里、其他情况都存储在scale_list里。而这里的逻辑是无论channel数为多少都会存在scale_list里,但是在量化完成之后 save_graph 阶段,这个时候量化的scale是存储在scale_list里的而不是scale,这样会导致dump成文件的时候保存了无效的值:
可以考虑在下次的时候换一波血,把scale这个机制取消了,直接用scale_list就可以。