Я получаю совершенно разные результаты прогнозирования при сравнении вывода нейронной сети, обученной на графическом процессоре в 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, поскольку вывод модели для монохроматических изображений одинаков.
Кто-нибудь сталкивался с подобной проблемой? Любая помощь высоко ценится!