Другой прогноз: Keras против Android + DL4J

Я получаю совершенно разные результаты прогнозирования при сравнении вывода нейронной сети, обученной на графическом процессоре в Python (3.5.5) + Keras (версия 2.0.8), с выводом той же нейронной сети на Android (API 24) с использованием DL4J. (1.0.0-бета2).

Было бы очень полезно, если бы кто-то поделился своим опытом решения этой проблемы, спасибо!

Импорт модели в Android

Нейронная сеть была преобразована в формат DL4J путем импорта с помощью:

MultiLayerNetwork model = KerasModelImport.importKerasSequentialModelAndWeights(SIMPLE_MLP, false)

и сохраняя его с помощью DL4Js ModelSerializer.

Модель импортируется в приложение Android с помощью метода DL4J restoreMultiLayerNetwork().

Вывод модели

Нейронная сеть предназначена для прогнозирования изображений фиксированной входной формы: фиксированная высота, ширина, 3 канала.

Конвейер предварительной обработки изображений в Android:

Изображение загружается как входной поток с устройства и сохраняется в INDarray:

AndroidNativeImageLoader loader = new AndroidNativeImageLoader(100, 100, 3);

InputStream  inputStream_bitmap = getContentResolver().openInputStream(uri);
INDArray indarray1 = loader.asMatrix(inputStream_bitmap);

AndroidNativeImageLoader() загружает и повторно масштабирует изображение.

INDarray 'indarray1' масштабируется, чтобы содержать значения в диапазоне [0,1]:

indarray1 = indarray1.divi(255);

INDarray передается по сети для вычисления вывода:

INDArray output = model.output(indarray1);

Конвейер предварительной обработки изображений в Python:

from keras.preprocessing import image
from keras.utils import np_utils
import numpy as np

img = image.load_img(img_path, target_size=(100, 100))
img = image.img_to_array(img)
img = np.expand_dims(img, axis=0)
img = img.astype('float32')/255

output = model.predict(img)

Проблема:

Прогноз с использованием Python и Keras значительно отличается от прогноза в Android с использованием DL4J. Выход представляет собой массив из 2 значений, каждое из которых представляет собой число с плавающей запятой в [0,1]. Разница в предсказании для обычного изображения .bmp, сделанного камерой, составляет до 0,99 на элемент этого выходного массива.

Проведенные тесты:

При использовании монохроматического изображения .bmp (только красного или только синего, только зеленого или полностью белого) результаты предсказания практически одинаковы для обеих сред. Они отличаются только на 10e-3, что можно объяснить обучением на GPU и применением на CPU.

Вывод: На данный момент я считаю, что предварительная обработка изображений на Android выполняется иначе, чем на Python, поскольку вывод модели для монохроматических изображений одинаков.

Кто-нибудь сталкивался с подобной проблемой? Любая помощь высоко ценится!


person Moritz    schedule 26.09.2018    source источник
comment
Не могли бы вы сообщить о проблеме: github.com/deeplearning4j/deeplearning4j/issues с дополнительной информацией, и мы можно посмотреть на разницу? Спасибо!   -  person Adam Gibson    schedule 26.09.2018


Ответы (1)


DL4J и Android используют BGR вместо RGB. Поэтому необходимо выполнить преобразование цветового формата.

Престижность переходит к @saudet из этого поста на Github:

https://github.com/deeplearning4j/deeplearning4j/issues/6495

NativeImageLoader необходимо загрузить с этим преобразованием:

loader = new NativeImageLoader(100, 100, 3, new ColorConversionTransform(COLOR_BGR2RGB));
person Moritz    schedule 28.09.2018