TensorFlow Lite int8量化运算细节及核心疑问咨询
TensorFlow Lite int8线性运算量化全流程解析
核心量化逻辑回顾
int8量化的本质是通过**缩放因子(S)和零点(Z)**将浮点数映射到整数域,彻底规避推理时的浮点运算。对于线性运算Y = WX + b,浮点数与量化整数的映射关系为:
- 浮点数:
X = S_x(q_x - Z_x),W = S_w(q_w - Z_w),b = S_b(q_b - Z_b),Y = S_y(q_y - Z_y) - 其中
S是浮点数缩放因子,Z是整数零点(使浮点数0对应整数Z),q_*是量化后的整数(int8)
将上述关系代入Y=WX+b推导后,得到量化整数的运算公式:
q_y = M * (q_w*q_x - Z_x*q_w + q_b) + Z_y
其中M = S_w*S_x / S_y,为适配纯整数运算,TFLite将M近似为定点数形式M0 * 2^(-n)(M0为int32,n为右移位数)。
参数M的具体作用
M是缩放比例转换系数,核心作用是将中间整数运算结果的缩放比例对齐到输出的缩放比例:
- 中间项
q_w*q_x - Z_x*q_w + q_b对应的浮点数是WX + b(即Y的浮点数),其缩放比例为S_w*S_x - 输出量化值
q_y对应的浮点数缩放比例为S_y - 通过
M = S_w*S_x / S_y可将中间结果的缩放比例转换为输出的缩放比例,确保最终q_y反量化回浮点数时与原始Y一致。
用定点数M0*2^(-n)近似M,是为了将乘法+除法运算转换为整数乘法+算术右移,完全规避浮点操作,适配低功耗硬件的整数计算单元。
位宽转换的完整步骤
你关注的int64到int8的转换流程,是推理阶段的关键操作,每一步细节如下:
- 计算中间int32值:
temp = q_w*q_x - Z_x*q_w + q_bq_w(int8)和q_x(int8)相乘得到int32(避免溢出),加上预计算好的-Z_x*q_w + q_b(int32,离线预计算后存储在模型中),结果为int32。
- int32转int64乘法:
temp64 = (int64)temp * M0- 两个int32相乘的最大值为
(2^31-1)^2,超出int32范围,必须用int64存储防止溢出。
- 两个int32相乘的最大值为
- 算术右移n位:
shifted = temp64 >> n- 采用带符号的算术右移(保留符号位),实现
*2^(-n)的除法操作,将结果缩放至接近输出int8的范围。
- 采用带符号的算术右移(保留符号位),实现
- 加上零点Z_y:
final_temp = shifted + (int64)Z_y- Z_y(int32)先扩展为int64,与shifted相加,确保无溢出。
- 钳位并转int8:
- 将
final_temp限制在int8的合法范围[-128, 127]:小于-128则设为-128,大于127则设为127,其余保持原值。 - 最后将钳位后的int64值强制转换为int8类型,得到最终量化输出
q_y。
- 将
完整量化推理流程(离线+在线)
离线预计算阶段(模型转换时完成)
- 统计输入X、权重W、输出Y的浮点数分布,计算各自的缩放因子
S_x, S_w, S_y和零点Z_x, Z_w, Z_y(偏置的缩放因子S_b = S_w*S_x,零点Z_b=0)。 - 计算
M = S_w*S_x / S_y,通过定点数近似算法找到最优的M0(int32)和n(右移位数),最小化近似误差。 - 预计算
-Z_x*q_w + q_b(int32),存储到量化后的模型文件中。 - 将W、X、Y分别量化为int8的
q_w, q_x, q_y(推理时输入q_x由浮点数X量化得到)。
在线推理阶段(运行时执行)
- 读取量化输入
q_x(int8)和预存储的q_w(int8)、预计算项(int32)、M0(int32)、n、Z_y(int32)。 - 按上述位宽转换步骤执行运算,得到
q_y(int8)。 - 若需要输出浮点数,通过
Y = S_y(q_y - Z_y)反量化得到。
内容的提问来源于stack exchange,提问作者jangho an
相关产品推荐
相关产品推荐

