Android TensorFlow Lite解释器:如何解决“ DataType错误:无法解析java.lang.Float的DataType”

时间:2019-01-17 11:58:56

标签: java android tensorflow tensorflow-lite

运行TFLite解释器时,输入包含浮点数的ByteBuffer作为输入,应用程序将引发异常:

“数据类型错误:无法解析java.lang.Float的数据类型”

模型本身是在Keras上训练的,然后转换为TF,然后转换为TFLite。

为了进行转换,我使用了TF(1.5.0版)toco转换器。

toco的输入参数:

toco --input_file = converted.pb --output_file = model.tflite --input_format = TENSORFLOW_GRAPHDEF --input_shape = 1,224,224,3 --input_array = main_input --output_array = main_output / Sigmoid --inference_type = FLOAT --output_format = TFLITE --input_type = FLOAT

我还手动创建了一个float [] [] [] [] []数组,代替了ByteBuffer,该数组的尺寸应作为模型的输入:[1,224,224,3]

导致与ByteBuffer相同的错误。

请注意,我将浮点数除以255,以获得[0,1]范围内的像素值。

import org.tensorflow.lite.Interpreter;
import java.nio.ByteBuffer;


public Interpreter tflite;

tflite = new Interpreter(loadModelFile(Test_TFLite.this,modelFile));

ByteBuffer bytebuffer_float = convertBitmapToByteBuffer_float(image, 1, 
    224, 3);

float out = 0;

tflite.run(bytebuffer_float,out);


private ByteBuffer convertBitmapToByteBuffer_float(Bitmap bitmap, int 
    BATCH_SIZE, int inputSize, int PIXEL_SIZE) {
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4 * BATCH_SIZE * 
    inputSize * inputSize * PIXEL_SIZE); //float_size = 4 bytes
        byteBuffer.order(ByteOrder.nativeOrder());
        int[] intValues = new int[inputSize * inputSize];
        bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, 
    bitmap.getWidth(), bitmap.getHeight());
        int pixel = 0;
        for (int i = 0; i < inputSize; ++i) {
            for (int j = 0; j < inputSize; ++j) { 
                final int val = intValues[pixel++];


                byteBuffer.putFloat( ((val >> 16) & 0xFF)* (1.f/255.f)); 
                byteBuffer.putFloat( ((val >> 8) & 0xFF)* (1.f/255.f)); 
                byteBuffer.putFloat( (val & 0xFF)* (1.f/255.f)); 
            }
        }
        return byteBuffer;
    }

我希望将单个浮点值在[0,1]范围内作为输出。由于解释器抛出异常,因此没有实际输出。

“数据类型错误:无法解析java.lang.Float的数据类型”

1 个答案:

答案 0 :(得分:1)

我自己从未使用过TF-Lite用于Java。 但是,根据docstflite.run()的两个参数都必须是张量。但是对于output参数,您只传递了一个float。因此,我很确定这是您错误“无法解析java.lang.Float的数据类型”的根本原因。

注意:同样根据文档,原始ByteBuffer以及支持的数据类型(floatintlong,{{1 }})受支持。因此,您的两种方法byteByteBuffer都应该起作用。您只需对输出执行相同的操作。