You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一TFLite分类模型在Python与Kotlin中输出结果不一致排查

问题:Keras转TFLite后Python与Android预测结果不一致

将Keras序列分类模型转为TFLite模型,用于Android人体活动识别应用(Kotlin开发)。模型接收39个浮点特征,输出22类的0/1结果,特征基于加速度计x/y/z数据转换。使用完全相同的输入特征时,Python中运行TFLite模型输出类别1,但Kotlin端输出类别4。已设置ByteBuffer为native顺序,附上两端测试代码,请求排查结果不一致的原因。

Python测试代码

# manual debugging of the Android code
test_features = np.array([15.121523, 134.00166, 118.880135, 16.775457, 7.369391, 54.307922, 2.4611068, 0.7021117, 0.5910131, -6.358347, 131.46619, 137.82454, -5.3617373, 8.590351, 73.79413, 0.5156907, 3.3576744, 0.5754766, -24.99669, -6.4506474, 18.546043, -6.7344146, 1.1799959, 1.3923903, 0.36815187, 0.14375915, 0.1254036, -14.355868, 6.9462624, 21.30213, -13.576304, 1.4869289, 2.2109578, 1.4814577, 0.051293932, 0.19250752, -0.9708634, 0.855468, -0.93450075])
test_features_reshaped = test_features.reshape(1, 39)
this_activity = activity_model.predict(test_features_reshaped)

# Load TFLite model and allocate tensors.
interpreter = tf.lite.Interpreter(model_path="MyNeuralNetModel.tflite")
interpreter.allocate_tensors()

# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

# Test model on random input data.
input_shape = input_details[0]['shape']
input_data = np.array(test_features_reshaped, dtype=np.float32)
interpreter.set_tensor(input_details[0]['index'], input_data)

interpreter.invoke()

# The function `get_tensor()` returns a copy of the tensor data.
# Use `tensor()` in order to get a pointer to the tensor.
output_data = interpreter.get_tensor(output_details[0]['index'])
print(output_data)

Kotlin测试代码

var byteBuffer: ByteBuffer = ByteBuffer.allocateDirect(4 * 39)
byteBuffer.order(ByteOrder.nativeOrder())

for ( obj in combinedFeatureObjects){
            byteBuffer = assembleByteBuffer(byteBuffer, obj.accelNormFeatures)
            byteBuffer = assembleByteBuffer(byteBuffer, obj.accelXFeatures)
            byteBuffer = assembleByteBuffer(byteBuffer, obj.accelYFeatures)
            byteBuffer = assembleByteBuffer(byteBuffer, obj.accelZFeatures)
            byteBuffer.putFloat(obj.corrxy.toFloat())
            byteBuffer.putFloat(obj.corrxz.toFloat())
            byteBuffer.putFloat(obj.corryz.toFloat())
            
            var model = MyNeuralNetModel.newInstance(context)
            val inputFeature0 = TensorBufferFloat.createFixedSize(intArrayOf(1, 39), DataType.FLOAT32)
            inputFeature0.loadBuffer(byteBuffer)
            val outputs = model.process(inputFeature0)
            val outputFeature0 = outputs.outputFeature0AsTensorBuffer.floatArray
            model.close()

            var activityNumber: Int? = 25
            for ((index, value) in outputFeature0.withIndex()) {
                   if(value > .4999f) {
                       activityNumber = index
                       break
                   } else if( value > 0) {
                       activityNumber = index * 100
                  }
            }
            if ( activityNumber == 25 ) {
                var x = 0
            }

排查关键点

  • 特征顺序一致性:核对Kotlin中assembleByteBuffer拼接的特征顺序,是否和Pythontest_features数组的顺序完全匹配,需逐位对应确认。
  • ByteBuffer状态问题:每次循环填充特征前,ByteBuffer未重置position,导致后续输入数据叠加在之前的缓冲区后,实际输入长度超过39个特征。需在填充前调用byteBuffer.rewind()或重新创建ByteBuffer。
  • 数据精度匹配:确认Kotlin中所有特征转换为Float时无精度丢失,比如corrxy等变量原始类型若为Double,转换为Float后是否和Python的float32数值一致。
  • 输出解析逻辑差异:Python取输出数组最大值对应的索引,而Kotlin先判断是否有值>0.4999,无匹配则取第一个>0的索引*100,逻辑不统一。需两端采用相同的结果解析规则,比如均取最大值对应的索引。
  • 模型文件一致性:确保Python转换的TFLite模型和Android端使用的是同一个文件,避免模型版本或参数不一致。

内容的提问来源于stack exchange,提问作者Jupiter Io

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:44:57