深入浅出TinyML 21:INT8量化改变了模型中的哪些数据?

📅 发布时间:2026/8/31 4:02:05
深入浅出TinyML 21:INT8量化改变了模型中的哪些数据?
把模型文件标记为INT8并不能证明整个推理链都在执行整数计算。权重、输入、输出和中间激活可能采用不同数据类型某些量化方式仍需要浮点输入或浮点内核。MCU部署最常关注全整数量化权重和激活使用整数表示输入输出也具有明确Scale与Zero Point。是否获得速度收益还取决于运行时和目标处理器的优化内核。检查量化模型时要逐项确认权重、输入、输出、中间激活和算子内核的数据类型。完成本篇后你应该能够说明INT8量化对权重、激活、输入输出和算子内核的改变。计算FP32与INT8张量的存储差异并识别饱和。运行一个整数全连接层比较反量化输出与浮点基线。INT8用-128到127共256个整数格子近似一段浮点范围。模型仍在做同类数学运算但数值表示和内核发生改变。图1全整数量化涉及输入、权重、中间激活和输出映射一、先把核心关系连起来权重量化主要减少模型存储FP32权重通常每个占4字节INT8权重每个占1字节。仅权重量化可以显著缩小权重部分但推理时可能将权重还原为浮点输入和激活仍为浮点。因此文件变小不等于整数内核已经生效。需要查看模型张量类型和目标运行时执行路径。中间激活决定整数计算能否贯穿网络全整数量化为每个激活张量保存量化参数算子在整数域完成乘加、偏置和重缩放。乘法结果通常在更宽的累加类型中保存再映射到下一层int8范围。某个算子缺少整数实现时转换器可能失败或模型中出现浮点回退。MCU项目应明确禁止意外浮点算子。表1常见量化方案的差异方案数据类型路径MCU意义仅权重量化权重INT8输入和激活通常FP32主要减小文件动态范围量化权重INT8激活由运行时动态处理需确认运行时支持全整数量化权重、输入和激活均使用整数路径适合整数内核与MCU部署二、输入输出契约随量化改变int8输入需要把预处理后的实数按照Scale和Zero Point量化。模型输出也要反量化或在整数域重新计算业务阈值。量化参数来自部署模型而非训练脚本中的经验常量。模型更新后输入输出Scale可能变化固件必须读取或同步新参数。Python要求转换器只生成全整数INT8算子import tensorflow as tfconverter tf.lite.TFLiteConverter.from_saved_model(saved_model)converter.optimizations [tf.lite.Optimize.DEFAULT]converter.representative_dataset representative_datasetconverter.target_spec.supported_ops [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]converter.inference_input_type tf.int8converter.inference_output_type tf.int8tflite_model converter.convert()三、收益要在目标固件上闭环量化前后统一比较测试集指标、模型文件、最终Flash、Arena、推理时间和能量。模型文件缩小约四倍只是权重层面的理论关系元数据和运行时代码不会按同比例缩小。Cortex-M上的速度收益依赖CMSIS-NN等优化内核、算子形状和编译配置。板端测量是最终证据。整数推理仍要表达实数尺度量化张量由整数数组、scale和zero point共同表达。整数q对应实数r≈scale×(q-zero_point)。权重、输入、每层激活和输出可以拥有不同scale卷积累加通常使用int32以容纳多个int8乘积。一次整数全连接先计算 (qx-zx)×(qw-zw) 的int32累加再结合输入、权重和输出尺度做requantize最后限制到int8范围。高效内核把乘尺度转换成整数乘法与移位避免每个元素执行浮点除法。只有权重量化时模型文件可能变小输入和激活仍为浮点MCU未必获得完整整数加速。全整数模型要求算子路径都支持INT8并把输入输出类型明确设为int8。r scale×(q-zero_point)int32累加acc Σ(qx-zx)(qw-zw)再按 (Sx×Sw)/Sy 映射到输出整数。量化误差集中在舍入、裁剪和异常范围实数落到有限网格时发生舍入超出校准范围时被裁剪到-128或127。少量极端值把scale拉大会让大多数常见值只使用少数整数码校准范围过窄又会在现场饱和。比较FP32与INT8不能只看模型字节。要在同一独立测试集上比较混淆矩阵统计输入与关键激活的饱和比例并在目标板测Flash、Arena和延迟。输入契约也改变。固件写入int8张量前要使用模型实际scale与zero point直接把原始传感器整数截成int8会破坏物理尺度。输出分数需要反量化后再应用阈值或把阈值预先映射到同一整数域。INT8链路中的数值对象对象常用类型检查输入int8量化参数范围与饱和权重int8/per-channel每通道scale累加int32溢出与偏置尺度输出int8或int16反量化与阈值动手逐项执行一个INT8全连接层脚本先计算浮点输出再分别量化输入和两行权重执行int32累加并反量化。它省略高效内核的定点requantize但完整展示误差来自哪里。实验环境与输入Python 3标准库。保存为 int8_dense.py 并运行。参数为教学示例不代表某个已训练模型。按顺序完成实验运行并比较float与dequant输出。打印输入和权重整数码。把输入2.4改为20观察饱和及误差。缩小输入scale比较分辨率与范围冲突。可直接运行量化、int32累加与反量化def q8(value, scale, zero0):return max(-128, min(127, round(value/scale)zero))x [0.35, -0.80, 1.20, 2.40]w [[0.50, -0.25, 0.10, 0.35],[-0.40, 0.70, -0.20, 0.15]]bias [0.05, -0.10]sx, sw 0.02, [0.005, 0.006]float_y [sum(a*b for a, b in zip(x, row))bias[i]for i, row in enumerate(w)]qx [q8(v, sx) for v in x]dequant_y []for i, row in enumerate(w):qw [q8(v, sw[i]) for v in row]acc sum(a*b for a, b in zip(qx, qw))# 偏置在真实整数模型中按 sx*sw[i] 量化为int32restored acc*sx*sw[i] bias[i]dequant_y.append(restored)print(row, i, qx, qx, qw, qw, acc, acc)print(float :, float_y)print(int8-fp:, dequant_y)print(error :, [b-a for a, b in zip(float_y, dequant_y)])先读懂代码中的关键路径qx与每行qw使用不同scale复现输入per-tensor、权重per-channel。乘积先累加为宽整数再乘Sx×Sw恢复实数。偏置保留浮点只为教学真实模型按Sx×Sw量化为int32。输入超过scale覆盖范围时q8裁剪信息不可恢复。你应该观察到什么反量化输出接近浮点输出但不完全相等。累加值超出int8范围却安全保存在Python整数对应MCU的int32累加。极端输入被裁剪后误差明显增加。成功标准能用scale和zero point完成量化与反量化。能区分权重量化和全整数推理。效果、资源和饱和统计同时验收。失败时从哪里查起INT8输出异常现象原因检查输出全为边界值输入缩放或校准范围错统计q-128/127比例分类索引正确但分数怪输出未反量化读取输出scale/zp模型仍含浮点算子转换未限制INT8集合检查算子列表和I/O dtype理解这段手工计算后再阅读CMSIS-NN或TFLM内核中的乘法器、移位和饱和会更容易。把实验迁移到真实MCU项目TFLM固件直接向int8输入张量写码量化前先执行完整物理量和标准化链。记录-128与127占比现场饱和增多时触发输入漂移。输出若用于阈值可以反量化到浮点也可以把阈值转换为整数码两种方式必须使用输出张量自己的scale与zero point。整数内核的最终输出还会经历定点乘法器、右移、舍入和饱和。手工浮点恢复用于理解尺度若要逐码复现TFLM需要从模型量化参数生成与内核相同的定点乘法器并用边界向量验证。还要检查类别阈值位于哪个数值域。若验证集阈值是浮点概率固件使用整数输出时先按输出scale映射并对阈值前后一个整数码做边界测试。整数模型的测试向量要覆盖零点附近、正负最大常见值和饱和边界。对每条向量同时保存浮点输入、量化输入、浮点输出和整数输出才能区分模型误差与固件量化错误。模型文件缩小比例与固件Flash缩小比例通常不同因为运行时和业务代码不随权重位宽等比例变化。资源报告应把两者分栏。把结果再向前推进一步计算600元素FP32与INT8输入张量的字节差异。说明为什么偏置常用int32。为真实输入增加饱和比例日志。收束INT8量化可能只改变权重也可以贯穿输入、激活和输出。MCU项目需要明确使用全整数链路并以模型检查和板端测量验证。参考资料Google AI Edge构建并转换微控制器模型Google AI Edgetf.lite APIArm CMSIS-NN 官方文档