Интерпретатор Android TensorFlow Lite: как исправить «Ошибка типа данных: не удается разрешить тип данных java.lang.Float» - PullRequest
0 голосов
/ 17 января 2019

При запуске интерпретатора TFLite, передающего в качестве входных данных ByteBuffer, содержащий числа с плавающей точкой, приложение выдает исключение:

«Ошибка типа данных: невозможно разрешить тип данных java.lang.Float»

Сама модель была обучена на Керасе, затем преобразована в TF, а затем в TFLite.

Для конвертации я использовал токо-конвертер TF (версия 1.5.0).

Входные параметры для toco:

toco --input_file = convert.pb --output_file = model.tflite --input_format = TENSORFLOW_GRAPHDEF --input_shape = 1,224,224,3 --input_array = main_input --output_array = main_output / Sigmoid --inferenceoutputOput для типа FLO = TFLITE --input_type = FLOAT

Вместо ByteBuffer я также вручную создал массив float [] [] [] [] с размерами, ожидаемыми в качестве входных данных для модели: [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 голосов
/ 17 января 2019

Я никогда не использовал TF-Lite для Java. Но, согласно документам , оба аргумента tflite.run() должны быть тензорами. Но для аргумента output вы передаете только один float. Итак, я уверен, что это основная причина вашей ошибки "не удается разрешить тип данных java.lang.Float".

Примечание: также в соответствии с документами поддерживаются необработанные ByteBuffer с, а также многомерные массивы поддерживаемых типов данных (float, int, long, byte). Итак, оба ваших подхода ByteBuffer и float[][][][] должны работать. Вы должны сделать то же самое для вывода.

...