Tensorflow: несовместимые формы для модели tflite и выходного массива - PullRequest
0 голосов
/ 19 марта 2019

Я следую довольно простому учебнику по tf.keras, чтобы создать классификатор двоичных изображений.Затем я преобразовал готовую модель в файл .tflite, который я пытаюсь включить в приложение для Android.

Создание кода Последовательная модель tf.keras.

import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras.layers import Activation, Dropout, Flatten, Dense
from tensorflow.keras import backend as K
from tensorflow.keras.callbacks import TensorBoard, ReduceLROnPlateau
from sklearn.utils import class_weight
import numpy as np


# dimensions of our images.====================================================================================================
img_width, img_height = 200, 200

train_data_dir = 'augmentedImg/200/training_data'#=============================================================================
validation_data_dir = 'augmentedImg/200/validation_data'#=============================================================================
nb_train_samples = 9009
nb_validation_samples = 2252
epochs = 100
batch_size = 32

layer_size = 64

if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height)
else:
    input_shape = (img_width, img_height, 3)

model = Sequential()
model.add(Conv2D(layer_size, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(layer_size, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(layer_size, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(layer_size, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())

#model.add(Dropout(0.5))

model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    rotation_range=90,
    width_shift_range=0.1,
    height_shift_range=0.1,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True
    )

test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    color_mode='grayscale',
    batch_size=batch_size,
    class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    color_mode='grayscale',
    batch_size=batch_size,
    class_mode='binary')

class_weights = class_weight.compute_class_weight(
               'balanced',
                np.unique(train_generator.classes), 
                train_generator.classes)

model.fit_generator(
    train_generator,
    class_weight=class_weights,
    steps_per_epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples# // batch_size,
    #callbacks=[tensorboard, reduce_lr]
    )

model.save_weights('model.h5')
print("End of program")

Преобразование кода в tflitemodel:

import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_keras_model_file("models/1Data_aug_200x200.h5")
tflite_model = converter.convert()
open("models/convertedModels/1Data_aug_200x200.tflite", "wb").write(tflite_model)

Затем я вызываю 'run' для модели, передавая ByteBuffer (изображение, которое нужно классифицировать) и выходной массив.

Выходной массив:

private float[][] labelProbArray = new float[1][numLabels]; //numLabels=2

Однако, когда я звоню tflite.run(imgData, labelProbArray);, я получаю сообщение об ошибке.

java.lang.IllegalArgumentException: Cannot copy between a TensorFlowLite tensor with shape [1, 1] and a Java object with shape [1, 2].

Должен ли тензор также иметь форму [1,2]?Или есть альтернатива, где я могу просто получить предсказанный класс и вернуть вероятность?

...