Android Tensorflow Lite模型推理的精度非常低

Android Tensorflow Lite模型推理的精度非常低,android,tensorflow,keras,tensorflow-lite,Android,Tensorflow,Keras,Tensorflow Lite,我想创建一个预测年龄和性别的模型,并将其集成到android应用程序中 我在Ubuntu 16上,使用Python 3.6、Tensorflow 1.13.1和Keras 2.2.4 首先,我用IMDB数据集训练不同的模型:从keras和我自己编写的VGG。 对于这两个MobileNet,我使用imagenet权重来初始化模型 准确率相当高,性别的准确率超过90% 培训结束后,我尝试了几种在tflite中转换模型的方法: 直接从.h5文件转换的三种方式: 我首先将模型转换为tf图,如中所述

我想创建一个预测年龄和性别的模型,并将其集成到android应用程序中

我在Ubuntu 16上,使用Python 3.6、Tensorflow 1.13.1和Keras 2.2.4

首先,我用IMDB数据集训练不同的模型:从keras和我自己编写的VGG。 对于这两个MobileNet,我使用imagenet权重来初始化模型

准确率相当高,性别的准确率超过90%

培训结束后,我尝试了几种在tflite中转换模型的方法:

  • 直接从.h5文件转换的三种方式:
  • 我首先将模型转换为tf图,如中所述
在转换之前,我还尝试使用这行代码:

tf.keras.backend.set_learning_phase(0)
最后,我在Android Studio中加载.tflite文件:

private ByteBuffer convertBitmapToByteBuffer(Bitmap bitmap) {
        int SIZE_IMAGE = 96;
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4*1*SIZE_IMAGE*SIZE_IMAGE*3);
        byteBuffer.order(ByteOrder.nativeOrder());
        int[] pixels = new int[SIZE_IMAGE * SIZE_IMAGE];
        bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
        int pixel = 0;
        for(int i=0; i < SIZE_IMAGE; i++){
            for(int j=0; j<SIZE_IMAGE;j++){
                final int val = pixels[pixel++];
                byteBuffer.putFloat((float) (((val >> 16) & 0xFF)/255));
                byteBuffer.putFloat((float) (((val >> 8) & 0xFF)/255));
                byteBuffer.putFloat((float) ((val & 0xFF)/255));

            }
        }    

public String recognizeImage(Bitmap bitmap) {
        ByteBuffer byteBuffer = convertBitmapToByteBuffer(bitmap);
        Map<Integer, Object> cnnOutputs = new HashMap<>();
        float[][] gender=new float[1][2];
        cnnOutputs.put(0,gender);
        float[][]age=new float[1][21];
        cnnOutputs.put(1,age);
        Object[] inputs = {byteBuffer};
        interpreter.runForMultipleInputsOutputs(inputs, cnnOutputs);
        String result = convertToResults(gender[0], age[0]);
        return result;
    }
private ByteBuffer convertBitmapToByteBuffer(位图){
int SIZE_IMAGE=96;
ByteBuffer ByteBuffer=ByteBuffer.allocateDirect(4*1*SIZE\u IMAGE*SIZE\u IMAGE*3);
byteBuffer.order(ByteOrder.nativeOrder());
int[]像素=新int[SIZE_图像*SIZE_图像];
getPixels(像素,0,bitmap.getWidth(),0,0,bitmap.getWidth(),bitmap.getHeight());
整数像素=0;
对于(int i=0;i16)&0xFF)/255);
byteBuffer.putFloat((float)((val>>8)和0xFF)/255);
byteBuffer.putFloat((float)((val&0xFF)/255));
}
}    
公共字符串识别图像(位图){
ByteBuffer ByteBuffer=convertBitmapToByteBuffer(位图);
Map cnnOutputs=newhashmap();
浮动[]性别=新浮动[1][2];
cnnOutputs.put(0,性别);
浮动[]年龄=新浮动[1][21];
cnnOutputs.put(1,年龄);
对象[]输入={byteBuffer};
runForMultipleInputsOutputs(输入,cnnOutputs);
字符串结果=转换结果(性别[0],年龄[0]);
返回结果;
}
在最终推断过程中,无论使用何种模型,精度都很低。要么口译员预测的结果总是完全相同,要么预测的年龄变化不大,但预测的性别总是“女性”

我该怎么办


提前谢谢

尝试使用keras模型和tflite模型处理一个输入数据并比较推断结果。可能输出不匹配。你可以从那里调试

converter = tf.contrib.lite.TocoConverter.from_keras_model_file(model_to_convert)
tflite_model = converter.convert()
open(model_converted, "wb").write(tflite_model)
tf.keras.backend.set_learning_phase(0)
private ByteBuffer convertBitmapToByteBuffer(Bitmap bitmap) {
        int SIZE_IMAGE = 96;
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4*1*SIZE_IMAGE*SIZE_IMAGE*3);
        byteBuffer.order(ByteOrder.nativeOrder());
        int[] pixels = new int[SIZE_IMAGE * SIZE_IMAGE];
        bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
        int pixel = 0;
        for(int i=0; i < SIZE_IMAGE; i++){
            for(int j=0; j<SIZE_IMAGE;j++){
                final int val = pixels[pixel++];
                byteBuffer.putFloat((float) (((val >> 16) & 0xFF)/255));
                byteBuffer.putFloat((float) (((val >> 8) & 0xFF)/255));
                byteBuffer.putFloat((float) ((val & 0xFF)/255));

            }
        }    

public String recognizeImage(Bitmap bitmap) {
        ByteBuffer byteBuffer = convertBitmapToByteBuffer(bitmap);
        Map<Integer, Object> cnnOutputs = new HashMap<>();
        float[][] gender=new float[1][2];
        cnnOutputs.put(0,gender);
        float[][]age=new float[1][21];
        cnnOutputs.put(1,age);
        Object[] inputs = {byteBuffer};
        interpreter.runForMultipleInputsOutputs(inputs, cnnOutputs);
        String result = convertToResults(gender[0], age[0]);
        return result;
    }