model.predict () - Модель с точностью, близкой к 1, предсказывает неправильные классы - PullRequest
3 голосов
/ 03 августа 2020

Я создал модель для распознавания автомобильных номеров. Вот он:

def create_model(input_shape = (224, 224, 3)):
    input_img = Input(shape=input_shape)
    model = efnB0_model (input_img)
    model = GlobalAveragePooling2D(name='avg_pool')(model)
    model = Dropout(0.2)(model)
    backbone = model

    branches = []
    for i in range(7):
            branches.append(backbone)
            branches[i] = Dense(360, name="branch_"+str(i)+"_Dense_360")(branches[i])
            branches[i] = BatchNormalization()(branches[i])
            branches[i] = Activation("relu") (branches[i])
            branches[i] = Dropout(0.2)(branches[i])
                       
            branches[i] = Dense(35, activation = "softmax", name="branch_"+str(i)+"_output")(branches[i])
        
    output = Concatenate(axis=1)(branches)
    output = Reshape((7, 35))(output)
    model = Model(input_img, output)

    return model

Я использовал этот DataGenerator:

import tensorflow.keras as keras
from skimage.io import imread
from skimage.transform import resize
import numpy as np
import math

class DataGenerator(Sequence):

    def __init__(self, x_set, y_set, batch_size):
        self.x, self.y = x_set, y_set
        self.batch_size = batch_size

    def __len__(self):
        return math.ceil(len(self.x) / self.batch_size)

    def __getitem__(self, idx):
        batch_x = self.x[idx*self.batch_size : (idx + 1)*self.batch_size]
        batch_x = np.array([resize(imread(file_name), (224, 224)) for file_name in batch_x])
        batch_x = batch_x * 1./255
        batch_y = self.y[idx*self.batch_size : (idx + 1)*self.batch_size]
        batch_y = np.array(batch_y)

        return batch_x, batch_y

Поэтому я закодировал каждый номерной знак (длина 7 символов и 35 возможных символов для каждой позиции с использованием этого код:

#One Hot Encoding der Labels, Zielarray hat eine Shape von (7,35)
from numpy import argmax
# define input string

def my_onehot_encoded(label):
    # define universe of possible input values
    characters = '0123456789ABCDEFGHIJKLMNPQRSTUVWXYZ'
    # define a mapping of chars to integers
    char_to_int = dict((c, i) for i, c in enumerate(characters))
    int_to_char = dict((i, c) for i, c in enumerate(characters))
    # integer encode input data
    integer_encoded = [char_to_int[char] for char in label]
    # one hot encode
    onehot_encoded = list()
    for value in integer_encoded:
        character = [0 for _ in range(len(characters))]
        character[value] = 1
        onehot_encoded.append(character)

    return onehot_encoded

Для лицензии с меткой «7CT2498» я получаю следующий вывод с однократным кодированием:

[[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

Теперь при запуске созданной мной модели на 10 эпох 10.000 обучающих данных и 3.000 данных проверки. Я получил точность обучения 0,9969 и точность проверки 0,9798, так что неплохо.

Но теперь я попытался предсказать номерной знак с помощью этой модели (изображение взято из тот же набор данных, что и мои данные для обучения и проверки).

Я использовал этот код:

model = keras.models.load_model(
    "/path/to/model.h5", compile=True)
opt = keras.optimizers.Adam(learning_rate=0.0001)
model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=["accuracy"])
img = cv2.imread('/path/to/image.png')
img = cv2.resize(img,(224,224))
img = np.reshape(img,[1,224,224,3])

classes = model.predict(img)

print(classes)

И я получил только один правильно предсказанный класс. Что-то не так с моим кодом?

Ответы [ 2 ]

3 голосов
/ 07 августа 2020

После просмотра кода, который вы мне прислали, кажется, что вы использовали skimage для предварительной обработки при подборе модели и opencv при выполнении прогноза. После использования того же кода предварительной обработки он отлично работает:

from skimage.io import imread
from skimage.transform import resize
import numpy as np
import math

img = imread('path/to/image')
img = resize(img,(224,224))
img = img*1./255
img = np.reshape(img,[1,224,224,3])

classes = model.predict(img)

print(classes)
0 голосов
/ 07 августа 2020

Похоже, ваша модель сильно переоснащается ... Возможно, вы захотите немного изучить эту проблему .. Еще один момент, для распознавания номерных знаков вы можете выбрать другой подход. Вы можете использовать следующие: -

  1. Детектор пластин OpenCV
  2. Классификатор изображений
  3. (не рекомендуется) Pytesseract

С уважением, InfinityS

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