TensorFlow Lite模型与输出数组形状不兼容问题求助
这个错误的核心原因是你的Keras模型输出形状和Android代码里定义的数组形状不匹配,咱们拆解问题并给出两种可行的解决方案:
问题根源分析
你的Keras模型最后一层是Dense(1)搭配sigmoid激活函数,这是二分类任务中单输出的设计:输出的单个值代表其中一类的概率(比如正类),另一类的概率就是1 - 输出值。此时模型的输出张量形状是[1, 1]。
但你在Android代码里定义了float[][] labelProbArray = new float[1][2],期望模型输出[1, 2]的形状(两个类别的概率分别对应数组的两个元素),这就导致了张量复制时的形状不匹配错误。
解决方案1:修改Keras模型,输出[1,2]形状的结果
如果你希望模型直接输出两个类别的概率,可以调整模型的输出层和训练配置:
修改模型最后几层:
将原有的输出层替换为Dense(2)搭配softmax激活函数,这样模型会直接输出两个类别的概率分布:# 替换原有的Dense(1)和Activation('sigmoid') model.add(Dense(2)) model.add(Activation('softmax'))调整损失函数和生成器配置:
- 编译模型时,损失函数改为
categorical_crossentropy:model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) - 训练和验证生成器的
class_mode改为'categorical':train_generator = train_datagen.flow_from_directory( # 其他参数不变 class_mode='categorical') validation_generator = test_datagen.flow_from_directory( # 其他参数不变 class_mode='categorical')
- 编译模型时,损失函数改为
重新训练并转换模型:
重新运行训练代码,得到新的.h5模型后,再用你的转换代码生成TFLite模型。此时模型的输出形状就是[1,2],和Android中定义的labelProbArray形状匹配,调用tflite.run(imgData, labelProbArray)就不会报错了。
解决方案2:不修改模型,调整Android代码适配[1,1]的输出
如果不想重新训练模型,可以直接修改Android代码来适配单输出的结果:
调整输出数组的形状:
把labelProbArray改成对应[1,1]的形状:private float[][] labelProbArray = new float[1][1]; // 匹配模型输出形状计算两个类别的概率:
运行模型后,从labelProbArray中获取正类的概率,再计算负类的概率:tflite.run(imgData, labelProbArray); float positiveProb = labelProbArray[0][0]; float negativeProb = 1.0f - positiveProb; // 此时positiveProb是正类概率,negativeProb是负类概率获取预测类别:
通过比较两个概率的大小来确定预测类别:int predictedClass = positiveProb > 0.5f ? 1 : 0;
内容的提问来源于stack exchange,提问作者MRDJR97

