Модель .tflite (преобразованная из модели keras .h5) всегда предсказывает один и тот же класс с одинаковой вероятностью - PullRequest
1 голос
/ 26 июня 2019

Я обучил модель (используя керас) подсчитывать количество поднятых пальцев.Модель работает очень хорошо (точность теста ~ 99%).Теперь я пытаюсь развернуть эту модель на грани, преобразовав сохраненную модель (файл .h5) в файл .tflite.

Используя tf.lite.TFLiteConverter.from_keras_model_file (), он преобразует и даетмне файл .tflite с этой ошибкой:

tensorflow/core/grappler/grappler_item_builder.cc:637] Init node conv2d/kernel/Assign doesn't exist in graph

Когда я загружаю этот файл tflite и пытаюсь делать прогнозы для одних и тех же входных изображений, он всегда предсказывает «НОЛЬ», который является первым классом и с вероятностью =0,003922.Остальные классы всегда равны 0,00. Я получаю те же результаты при загрузке моей модели tflite в примере приложения для классификации изображений Android из репозитория Tensorflow.

Почему эта модель tflite не работает должным образом?Я что-то упускаю во время преобразования или использую операции, которые не поддерживаются в TFlite?Пожалуйста, помогите!

До сих пор я пытался выполнить преобразования в различных версиях Tensorflow;
- 1.12
- 1.14
- tf-nightly-gpu 1.14

Все дают одинаковые результаты.

Моя модель .h5 и тестовое изображение, если вы хотите попробовать это сами!

Это код, который я использовал для преобразования модели:

import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_keras_model_file("fingers_latest.h5")
tflite_model = converter.convert()
open("fingers_latest.tflite", "wb").write(tflite_model)

Модель My keras:

nbatch = 64
IMG_SIZE = 256


def load_data():
    print("Batch size = ", nbatch, "\n")

    train_datagen = ImageDataGenerator(rescale=1. / 255, rotation_range=12., width_shift_range=0.2,
                                       height_shift_range=0.2,
                                       zoom_range=0.15, shear_range=0.2, horizontal_flip=False)

    test_datagen = ImageDataGenerator(rescale=1. / 255)

    train_gen = train_datagen.flow_from_directory('./datasets/fingers_white/train/', target_size=(IMG_SIZE, IMG_SIZE),
                                                  color_mode='rgb',
                                                  batch_size=nbatch, shuffle=True,
                                                  classes=['ZERO', 'ONE', 'TWO', 'THREE', 'FOUR', 'FIVE'],
                                                  class_mode='categorical')

    test_gen = test_datagen.flow_from_directory('./datasets/fingers_white/test/', target_size=(IMG_SIZE, IMG_SIZE),
                                                color_mode='rgb',
                                                batch_size=nbatch,
                                                classes=['ZERO', 'ONE', 'TWO', 'THREE', 'FOUR', 'FIVE'],
                                                class_mode='categorical')

    return train_gen, test_gen


def train_model(train_gen, test_gen):
    model = Sequential()
    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)))
    model.add(Dropout(0.2))
    model.add(MaxPooling2D((3, 3)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(Dropout(0.4))
    model.add(MaxPooling2D((3, 3)))
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(Dropout(0.6))
    model.add(MaxPooling2D((3, 3)))
    model.add(Conv2D(32, (3, 3), activation='relu'))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dropout(0.2))
    model.add(Dense(6, activation='softmax'))

    model.summary()

    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])

    STEP_SIZE_TRAIN = train_gen.n // train_gen.batch_size
    STEP_SIZE_TEST = test_gen.n // test_gen.batch_size
    print(STEP_SIZE_TEST, STEP_SIZE_TRAIN)

    model.fit_generator(train_gen, steps_per_epoch=STEP_SIZE_TRAIN, epochs=5, validation_data=test_gen,
                        validation_steps=STEP_SIZE_TEST, use_multiprocessing=True, workers=6)

Код, который я использую для загрузки и запуска модели .tflite:

import tensorflow as tf
import tkinter as tk
from tkinter import filedialog
import PIL
from PIL import Image
import numpy as np
import time

# DEF. PARAMETERS
img_row, img_column = 224, 224
num_channel = 3
num_batch = 1
input_mean = 127.5
input_std = 127.5
floating_model = False

path_1 = r"./models/mobilenet_v2_1.0_224.tflite"
labels_path = "./models/labels_mobilenet.txt"

def load_labels(filename):
    my_labels = []
    input_file = open(filename, 'r')
    for l in input_file:
        my_labels.append(l.strip())
    return my_labels

interpreter = tf.lite.Interpreter(path_1)
interpreter.allocate_tensors()

# obtaining the input-output shapes and types
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
print(input_details, '\n', output_details)

# file selection window for input selection
root = tk.Tk()
root.withdraw()
file_path = filedialog.askopenfilename()
input_img = Image.open(file_path)
input_img = input_img.resize((img_row, img_column))
input_img = np.expand_dims(input_img, axis=0)

input_img = (np.float32(input_img) - input_mean) / input_std

interpreter.set_tensor(input_details[0]['index'], input_img)

# running inference
interpreter.invoke()

output_data = interpreter.get_tensor(output_details[0]['index'])
results = np.squeeze(output_data)

top_k = results.argsort()[-5:][::-1]
labels = load_labels(labels_path)
for i in top_k:
    print('{0:08.6f}'.format(float(results[i] / 255.0)) + ":", labels[i])

1 Ответ

0 голосов
/ 27 июня 2019

В вашем тренировочном коде вы нормализуете изображения в диапазоне [0..1], который указан следующими строками:

train_datagen = ImageDataGenerator(rescale=1. / 255, ...)
test_datagen = ImageDataGenerator(rescale=1. / 255)

Входной диапазон преобразованной модели tflite, однако, равен [-1..1], что определяется следующими строками:

input_mean = 127.5
input_std = 127.5
input_img = (np.float32(input_img) - input_mean) / input_std

Итак, вы можете попробовать заменить вышеуказанные строки на:

input_mean = 0.
input_std = 255.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...