tf.lite.Interpreter.set_tensor无法正确识别uint8输入张量问题
这个问题不是TensorFlow Lite的bug,是配置细节和数值转换逻辑有误导致的,具体解决步骤如下:
1. 类型矛盾报错的原因
你设置target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]时,该算子集默认要求所有算子的输入输出为int8类型,你后续设置的inference_input_type=tf.uint8仅修改了模型元数据里的dtype字段,没有改变内部的类型校验逻辑,所以才会出现get_input_details显示要求uint8,但实际运行校验要求int8的矛盾。
2. 转int8输入后结果错误的原因
你直接将uint8的图像数据强制转换为int8类型,会导致数值溢出:比如uint8的128转换为int8会变成-128,完全破坏了输入数据的分布,所以推理结果全部错误。你需要按照量化参数做正确的数值偏移:
因为你的输入量化参数为scale=1.0, zero_point=0,正确的转换逻辑为:
# uint8输入转符合模型要求的int8输入 img_array_int8 = (img_array.astype(np.int32) - 128).astype(np.int8)
将转换后的img_array_int8传入模型即可得到正确的推理结果。
3. 直接使用uint8输入的修改方案
如果你不想做输入类型转换,可以修改量化配置的算子集,增加默认的TFLITE_BUILTINS支持,让你设置的uint8输入输出配置生效:
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8, tf.lite.OpsSet.TFLITE_BUILTINS]
重新量化后的模型就可以直接传入uint8的图像数据,不需要额外转换。
4. 输出结果说明
你观察到输出总和接近256属于正常现象:sigmoid的浮点输出范围为[0,1],量化到uint8时会映射到[0,255],如果你的6个输出原本总和为1,量化后每个值乘255再取整,总和自然会接近255/256,少量误差是量化舍入导致的,不影响模型效果。
内容的提问来源于stack exchange,提问作者Brad

