Подтвердить что ты не робот

Признание мниста с использованием кера

Как я могу обучить модель распознавать пять чисел на одном изображении. Код выглядит следующим образом:

from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dropout, Dense, Input
from keras.models import Model, Sequential

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
             activation='relu',
             input_shape=(28, 140, 1)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dropout(0.5))

Здесь должен быть цикл для распознавания каждого числа на картинке, но я не знаю, как это реализовать.

model.add(Dense(11, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
          optimizer=keras.optimizers.Adadelta(),
          metrics=['accuracy'])

model.fit(X_train, y_train,
      batch_size=1000,
      epochs=8,
      verbose=1,
      validation_data=(X_valid, y_valid))

Изображение комбинированного числа mnist выглядит следующим образом:

combined numbers in one picture

4b9b3361

Ответ 1

Я предлагаю два возможных подхода:

Случай 1 - Изображения хорошо структурированы.

В приведенном вами примере это действительно так, поэтому, если ваши данные выглядят в указанной вами ссылке, я предлагаю этот подход.

В приведенной вами ссылке каждое изображение в основном состоит из 5 28-х пиксельных изображений, сложенных вместе. В этом случае я предлагаю разрезать изображения (то есть вырезать каждое изображение на 5 частей) и обучать вашу модель, как с обычными данными MNIST (например, используя предоставленный вами код). Затем, когда вы хотите применить свою модель для классификации новых данных, просто отрежьте каждое новое изображение на 5 частей. Классифицируйте каждую из этих 5 штук с помощью своей модели, а затем просто напишите эти 5 чисел рядом с другим в качестве вывода.

так относительно этого предложения:

Здесь должен быть цикл для распознавания каждого числа на картинке, но Я не знаю, как это реализовать.

вам не нужен цикл for. Просто сократите свои цифры.

Случай 2. Изображения не очень хорошо структурированы.

В этом случае каждое изображение помечено 5 номерами. Поэтому каждая строка в y_train и y_valid) будет представлять собой 0,1-вектор с 55 элементами. Первые 11 записей - это горячая кодировка первого числа, а вторая 11 записей - это горячая кодировка второго номера и так далее. Поэтому каждая строка в y_train будет иметь 5 записей, равных 1, а остальные равны 0.

Кроме того, вместо использования активации softmax на выходном уровне и потери categorical_crossentropy используйте функцию активации сигмоида и потерю "binary_crossentropy" (см. дальнейшее обсуждение причин здесь и здесь)

Подводя итог, замените это:

model.add(Dense(11, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
          optimizer=keras.optimizers.Adadelta(),
          metrics=['accuracy'])

с этим:

model.add(Dense(55, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
          optimizer=keras.optimizers.Adadelta())

Ответ 2

Поскольку у вас уже есть очень хорошее поведение, все, что вам нужно сделать, это расширить количество классов в вашей модели.

Вы можете использовать 5 раз 11 классов вместо использования только 11 классов.

Первые 11 классов идентифицируют первое число, следующие 11 классов идентифицируют второе число и так далее. В общей сложности 55 классов, 11 классов для каждой позиции на изображении.

Итак, короче:

  • X_training будет полным изображением, как показано в ссылке, в форме (28,140) или (140,28), в зависимости от того, какие методы вы используете для загрузки изображений.
  • Y_training будет 55-элементным вектором, shape (55,), указывая, какие числа находятся в каждом квадранте.

Пример: для первого изображения с 9,7,5,4,10 вы создадите Y_training со следующими позициями, содержащими значение 1:

  • Y_training[9] = 1
  • Y_training[18] = 1 #(18=7+11)
  • Y_training[27] = 1 #(27=5+22)
  • Y_training[37] = 1 #(37=4+33)
  • Y_training[54] = 1 #(54=10+44)

Создайте свои слои модели так, как вы хотите, почти так же, как и обычная модель MNIST, а это означает: нет необходимости пытаться использовать петли или что-то в этом роде.

Но это, вероятно, должно быть немного больше, чем раньше.

Вы больше не сможете использовать categorical_crossentropy, у вас будет 5 правильных классов для каждого изображения, а не только 1. Если вы используете "сигмоидные" активации в конце, binary_crossentropy должна быть хорошей заменой,

Убедитесь, что ваш последний слой соответствует 55-элементному вектору, например, Dense(55).

Ответ 3

Эта проблема была решена Янном Лекуном в 90-х годах. Вы можете найти демо и документы на своем сайте.

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

Очень общее решение, которое может обрабатывать переменное число чисел и разных шкал и позиций, заключается в построении модели, которая может предсказать ограничивающие поля чисел и выполнить классификацию на них. В недавней истории таких моделей с R-CNN, Fast-RCNN и Faster-RCNN.

Вы можете найти реализацию Python для Faster-RCNN на github.

Ответ 4

Классическая работа в этой области 'Многозначное распознавание номеров из изображений улиц с использованием глубоких сверточных нейронных сетей

Модель Keras (функциональная, а не последовательная):

inputs = Input(shape=(28, 140, 1), name="input")
x = inputs
x = Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(28, 140, 1))(x)
x = Conv2D(64, (3, 3), activation='relu')(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Dropout(0.25)(x)
x = Flatten()(x)
x = Dropout(0.5)(x)
digit1 = Dense(10, activation='softmax', name='digit1')(x)
digit2 = Dense(10, activation='softmax', name='digit2')(x)
digit3 = Dense(10, activation='softmax', name='digit3')(x)
digit4 = Dense(10, activation='softmax', name='digit4')(x)
digit5 = Dense(10, activation='softmax', name='digit5')(x)
predictions = [digit1,digit2,digit3,digit4,digit5]
model = Model(inputs=inputs, outputs=predictions)
model.compile(optimizer=Adam(), metrics=['accuracy'], oss='categorical_crossentropy')

PS Вы можете использовать 11 классов для 10 цифр и пустого пространства.

Ответ 5

Советую вам следовать Практическое глубокое обучение для кодеров, потрясающее MOOC Джереми Говарда.

В ресурсах части 1 вы найдете этот ноутбук, в котором подробно описывается процедура обучения CNN на MNIST dataset с использованием Keras.

Я мог бы попытаться воспроизвести его и показать вам, как это сделать, но вы узнаете гораздо больше, следуя MOOC...


Обратите внимание, что Изучите TensorFlow и глубокое обучение без Ph.D. от Martin Görner также отлично, и покажет вам, как использовать нейронные сети с MNIST (1-го видео) и более (3H видео).

Но это основное внимание уделяется TensorFlow API, а не Keras. Во всяком случае, это высококачественный контент, поэтому стоит потратить время.