Рубрики
Без рубрики

Распознавание изображений в Python с помощью TensorFlow и Keras

Автор оригинала: Dan Nelson.

Вступление

Одним из наиболее распространенных применений TensorFlow и Keras является распознавание/классификация изображений. Если вы хотите узнать, как использовать Keras для классификации или распознавания изображений, эта статья научит вас этому.

Определения

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

TensorFlow/Keras

Кредит: Кредит:

TensorFlow – это библиотека с открытым исходным кодом, созданная для Python командой Google Brain. TensorFlow компилирует множество различных алгоритмов и моделей вместе, позволяя пользователю реализовать глубокие нейронные сети для использования в таких задачах, как распознавание/классификация изображений и обработка естественного языка . TensorFlow-это мощный фреймворк, который функционирует путем реализации серии обрабатывающих узлов, каждый из которых представляет собой математическую операцию, причем вся серия узлов называется “графом”.

С точки зрения Keras , это высокоуровневый API (интерфейс прикладного программирования), который может использовать функции TensorFlow под ним (а также другие библиотеки ML, такие как Theano). Keras был разработан с учетом удобства использования и модульности в качестве своих руководящих принципов. С практической точки зрения Keras делает реализацию многих мощных, но часто сложных функций TensorFlow максимально простой, и он настроен на работу с Python без каких-либо серьезных модификаций или конфигураций.

Распознавание изображений (Классификация)

Распознавание изображений относится к задаче ввода изображения в нейронную сеть и вывода ею какой-либо метки для этого изображения. Метка, которую выводит сеть, будет соответствовать заранее определенному классу. Изображение может быть помечено несколькими классами или только одним. Если существует один класс, то часто применяется термин “распознавание”, тогда как задача распознавания нескольких классов часто называется “классификацией”.

Подмножеством классификации изображений является обнаружение объектов, когда конкретные экземпляры объектов идентифицируются как принадлежащие к определенному классу, например животные, автомобили или люди.

Извлечение признаков

Для того чтобы осуществить распознавание/классификацию изображений, нейронная сеть должна выполнить извлечение признаков . Функции-это элементы данных, которые вам небезразличны и которые будут передаваться через сеть. В конкретном случае распознавания изображений объектами являются группы пикселей, такие как ребра и точки объекта, которые сеть будет анализировать на наличие паттернов.

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

Как Нейронные сети учатся распознавать изображения

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

Извлечение Признаков С Помощью Фильтров

Кредит: Кредит:

Первый слой нейронной сети принимает все пиксели внутри изображения. После того, как все данные были введены в сеть, к изображению применяются различные фильтры, которые формируют представления различных частей изображения. Это извлечение объектов, и оно создает “карты объектов”.

Этот процесс извлечения объектов из изображения осуществляется с помощью “сверточного слоя”, а свертка-это просто формирование представления части изображения. Именно из этой концепции свертки мы получаем термин Сверточная нейронная сеть (CNN), тип нейронной сети, наиболее часто используемый в классификации/распознавании изображений.

Если вы хотите визуализировать, как работает создание карт объектов, подумайте о том, чтобы посветить фонариком на картинку в темной комнате. Когда вы проводите лучом по изображению, вы узнаете об особенностях изображения. фильтр – это то, что сеть использует для формирования представления изображения, и в этой метафоре свет от фонарика является фильтром.

Ширина луча вашего фонарика определяет, какую часть изображения вы исследуете за один раз, и нейронные сети имеют аналогичный параметр-размер фильтра. Размер фильтра влияет на то, какая часть изображения, сколько пикселей исследуется одновременно. Общий размер фильтра, используемый в CNNs, равен 3, и он охватывает как высоту, так и ширину, поэтому фильтр исследует область пикселей размером 3 х 3.

Кредит: Кредит:

В то время как размер фильтра охватывает высоту и ширину фильтра, необходимо также указать глубину фильтра.

Как 2D – изображение имеет глубину?

Цифровые изображения отображаются в виде высоты, ширины и некоторого значения RGB , определяющего цвета пикселя, поэтому отслеживаемая “глубина” – это количество цветовых каналов изображения. Полутоновые (нецветные) изображения имеют только 1 цветовой канал, в то время как цветные изображения имеют 3 канала глубины.

Все это означает, что для фильтра размера 3, примененного к полноцветному изображению, размеры этого фильтра будут равны 3 х 3 х 3. Для каждого пикселя, покрытого этим фильтром, сеть умножает значения фильтра на значения в самих пикселях, чтобы получить числовое представление этого пикселя. Затем этот процесс выполняется для всего изображения, чтобы достичь полного представления. Фильтр перемещается по остальной части изображения в соответствии с параметром, называемым “шаг”, который определяет, на сколько пикселей фильтр должен быть перемещен после того, как он вычислит значение в своем текущем положении. Обычный размер шага для CNN-2.

Конечным результатом всех этих вычислений является карта объектов. Этот процесс обычно выполняется с помощью нескольких фильтров, что помогает сохранить сложность изображения.

Функции Активации

После создания карты объектов изображения значения, представляющие изображение, передаются через функцию активации или слой активации. Функция активации принимает значения, представляющие изображение, которые находятся в линейной форме (т. Е. Просто список чисел) благодаря сверточному слою, и увеличивает их нелинейность, так как сами изображения нелинейны.

Типичная функция активации, используемая для достижения этой цели, – это Выпрямленная линейная единица (ReLU), хотя есть и некоторые другие функции активации, которые иногда используются (вы можете прочитать о них здесь ).

Объединение слоев

После того как данные активированы, они отправляются через слой объединения . Объединение “понижающих выборок” изображения означает, что оно берет информацию, которая представляет изображение, и сжимает ее, делая ее меньше. Процесс объединения делает сеть более гибкой и более искусной в распознавании объектов/изображений на основе соответствующих функций.

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

Аналогично, объединяющий слой в CNN абстрагирует ненужные части изображения, сохраняя только те части изображения, которые он считает релевантными, как это контролируется заданным размером объединяющего слоя.

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

Кредит: Кредит:

Существуют различные способы объединения значений, но чаще всего используется max pooling . Max pooling получает максимальное значение пикселей в пределах одного фильтра (в пределах одного пятна на изображении). Это отбрасывает 3/4 информации, предполагая, что используются фильтры 2 х 2.

Максимальные значения пикселей используются для учета возможных искажений изображения, а параметры/размер изображения уменьшаются для контроля за переоснащением. Существуют и другие типы пулов, такие как средний пул или суммарный пул, но они используются не так часто, потому что максимальный пул имеет тенденцию давать лучшую точность.

Сплющивание

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

Полностью Подключенный Слой

Конечные слои CNN-это плотно связанные слои, или искусственная нейронная сеть (ANN). Основная функция ANN заключается в анализе входных признаков и объединении их в различные атрибуты, которые помогут в классификации. Эти слои, по существу, формируют коллекции нейронов, которые представляют различные части рассматриваемого объекта, и коллекция нейронов может представлять висячие уши собаки или красноту яблока. Когда достаточное количество этих нейронов активируется в ответ на входное изображение, изображение классифицируется как объект.

Кредит: Кредит:

Ошибка, или разница между вычисленными значениями и ожидаемым значением в обучающем наборе, вычисляется с помощью ANN. Затем сеть подвергается обратному распространению , где вычисляется влияние данного нейрона на нейрон в следующем слое и корректируется его влияние. Это делается для оптимизации производительности модели. Затем этот процесс повторяется снова и снова. Именно так сеть обучается на данных и изучает связи между входными объектами и выходными классами.

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

Последний полностью связанный слой получит выход слоя перед ним и выдаст вероятность для каждого из классов, суммируясь к единице. Если в категории “собака” есть значение 0,75, это означает 75% – ную уверенность в том, что изображение является собакой.

Классификатор изображений теперь обучен, и изображения могут быть переданы в CNN, который теперь выведет предположение о содержании этого изображения.

Рабочий процесс Машинного Обучения

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

Подготовка данных

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

В этой статье мы будем использовать предварительно обработанный набор данных.

Создание модели

Создание нейросетевой модели предполагает выбор различных параметров и гиперпараметров. Вы должны принять решение о количестве слоев для использования в вашей модели, о том, какими будут входные и выходные размеры слоев, какие функции активации вы будете использовать, будете ли вы использовать отсев и т. Д.

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

Обучение модели

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

Выбор количества эпох для тренировки-это то, что вы почувствуете, и обычно между тренировками сохраняется вес сети, чтобы вам не нужно было начинать все сначала, как только вы достигли некоторого прогресса в обучении сети.

Оценка модели

Существует несколько этапов оценки модели. Первым шагом в оценке модели является сравнение производительности модели с набором данных validation dataset , набором данных, на котором модель не была обучена. Вы будете сравнивать производительность модели с этим набором валидации и анализировать ее производительность с помощью различных метрик.

Существуют различные метрики для определения производительности модели нейронной сети, но наиболее распространенной метрикой является “точность”, количество правильно классифицированных изображений, деленное на общее количество изображений в вашем наборе данных.

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

Наконец, вы проверите производительность сети на тестовом наборе . Этот тестовый набор-еще один набор данных, который ваша модель никогда раньше не видела.

Возможно, вам интересно:

Зачем беспокоиться о тестовом наборе? Если вы получаете представление о точности вашей модели, разве это не цель набора проверки?

Это хорошая идея, чтобы сохранить пакет данных, которые сеть никогда не видела для тестирования, потому что все настройки параметров, которые вы делаете, в сочетании с повторным тестированием на наборе проверки, могут означать, что ваша сеть изучила некоторые особенности набора проверки, которые не будут обобщаться на данные вне выборки.

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

Распознавание изображений с помощью CNN

Мы уже многое рассмотрели, и если вся эта информация была немного ошеломляющей, то наблюдение за тем, как эти понятия объединяются в выборочном классификаторе, обученном набору данных, должно сделать эти понятия более конкретными. Итак, давайте рассмотрим полный пример распознавания изображений с помощью Keras-от загрузки данных до оценки.

Кредит: Кредит:

Для начала нам понадобится набор данных для тренировки. В этом примере мы будем использовать знаменитый набор данных CIFAR-10 . CIFAR10-это большой набор данных изображений, содержащий более 60 000 изображений, представляющих 10 различных классов объектов, таких как автомобили, самолеты и автомобили.

Изображения полноцветные RGB, но они довольно маленькие, всего 32 х 32. Одна замечательная вещь в наборе данных CIFAR-10 заключается в том, что он поставляется в комплекте с Keras, поэтому его очень легко загрузить, а изображения требуют очень небольшой предварительной обработки.

Первое, что мы должны сделать, это импортировать необходимые библиотеки. Я покажу, как этот импорт используется по ходу дела , но пока знайте, что мы будем использовать Numpy и различные модули, связанные с Keras:

import numpy
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, BatchNormalization, Activation
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.constraints import maxnorm
from keras.utils import np_utils

Мы собираемся использовать здесь случайное семя, чтобы результаты, достигнутые в этой статье, могли быть воспроизведены вами, вот почему нам нужен numpy :

# Set random seed for purposes of reproducibility
seed = 21

Подготовка данных

Нам нужен еще один импорт: набор данных.

from keras.datasets import cifar10

Теперь давайте загрузим набор данных. Мы можем сделать это просто, указав, в какие переменные мы хотим загрузить данные, а затем используя функцию load_data() :

# loading in the data
     
(X_train, y_train), (X_test, y_test) = cifar10.load_data()

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

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

Таким образом, чтобы нормализовать данные, мы можем просто разделить значения изображения на 255. Для этого нам сначала нужно сделать данные типа float, так как в настоящее время они являются целыми числами. Мы можем сделать это с помощью команды astype() Numpy, а затем объявить, какой тип данных нам нужен:

# normalize the inputs from 0-255 to between 0 and 1 by dividing by 255
    
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train = X_train / 255.0
X_test = X_test / 255.0

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

Мы эффективно делаем здесь бинарную классификацию, потому что изображение либо принадлежит к одному классу, либо нет, оно не может находиться где-то посередине. Команда Numpy to_categorical() используется для однократного горячего кодирования. Вот почему мы импортировали функцию np_utils из Keras, так как она содержит to_categorical() .

Нам также нужно указать количество классов, которые находятся в наборе данных, чтобы мы знали, сколько нейронов нужно сжать до конечного слоя:

# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
class_num = y_test.shape[1]

Проектирование модели

Мы достигли той стадии, когда разрабатываем модель CNN. Первое, что нужно сделать, это определить формат, который мы хотели бы использовать для модели, Keras имеет несколько различных форматов или чертежей для построения моделей, но Sequential является наиболее часто используемым, и по этой причине мы импортировали его из Keras.

Создайте модель

model = Sequential()

Первый слой нашей модели-сверточный. Он будет принимать входные данные и запускать на них сверточные фильтры.

При реализации их в Keras мы должны указать количество каналов/фильтров, которые мы хотим (это 32 ниже), размер фильтра, который мы хотим (3 x 3 в данном случае), входную форму (при создании первого слоя) и активацию и заполнение, которые нам нужны.

Как уже упоминалось, relu является наиболее распространенной активацией, и padding='same' просто означает, что мы вообще не меняем размер изображения:

model.add(Conv2D(32, (3, 3), input_shape=X_train.shape[1:], padding='same'))
model.add(Activation('relu'))

Примечание : Вы также можете связать активации и пулы вместе, например так:

model.add(Conv2D(32, (3, 3), input_shape=(3, 32, 32), activation='relu', padding='same'))

Теперь мы сделаем слой отсева, чтобы предотвратить переоснащение, который функционирует случайным образом, устраняя некоторые соединения между слоями (0,2 означает, что он отбрасывает 20% существующих соединений):

model.add(Dropout(0.2))

Здесь мы также можем захотеть выполнить пакетную нормализацию. Пакетная нормализация нормализует входы, идущие на следующий уровень, гарантируя, что сеть всегда создает активации с тем же распределением, которое мы хотим:

model.add(BatchNormalization())

Теперь появляется еще один сверточный слой, но размер фильтра увеличивается, так что сеть может изучать более сложные представления:

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))

Вот слой объединения, как обсуждалось ранее, который помогает сделать классификатор изображений более надежным, чтобы он мог изучать соответствующие паттерны. Есть также отсев и нормализация пакетов:

model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(BatchNormalization())

Это основной поток для первой половины реализации CNN: Свертка, активация, отсев, объединение . Теперь вы можете понять, почему мы импортировали Dropout , Batch Normalization , Activation , Conv2d и MaxPooling2D .

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

Важно не иметь слишком много слоев пула, так как каждый пул отбрасывает некоторые данные. Слишком частое объединение приведет к тому, что плотно связанным слоям почти не о чем будет узнавать, когда данные достигнут их.

Точное количество слоев объединения, которые вы должны использовать, будет варьироваться в зависимости от задачи, которую вы выполняете, и это то, что вы почувствуете со временем. Поскольку изображения здесь уже такие маленькие, мы не будем объединять их больше двух раз.

Теперь вы можете повторить эти слои, чтобы дать вашей сети больше представлений для работы:

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(BatchNormalization())
    
model.add(Conv2D(128, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())

После того, как мы закончим со сверточными слоями, нам нужно Сгладить данные, поэтому мы импортировали функцию выше. Мы также добавим слой выпадения снова:

model.add(Flatten())
model.add(Dropout(0.2))

Теперь мы используем импорт Dense и создаем первый плотно связанный слой. Нам нужно указать количество нейронов в плотном слое. Обратите внимание, что число нейронов в последующих слоях уменьшается, в конечном итоге приближаясь к тому же числу нейронов, что и классы в наборе данных (в данном случае 10). Ограничение ядра может упорядочивать данные по мере их изучения-еще одна вещь, которая помогает предотвратить переобучение. Вот почему мы импортировали max norm ранее.

model.add(Dense(256, kernel_constraint=maxnorm(3)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())
    
model.add(Dense(128, kernel_constraint=maxnorm(3)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())

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

Наконец, функция активации softmax выбирает нейрон с наибольшей вероятностью в качестве своего выходного сигнала, голосуя за то, что изображение принадлежит к этому классу:

model.add(Dense(class_num))
model.add(Activation('softmax'))

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

Оптимизатор-это то, что настроит весы в вашей сети, чтобы приблизиться к точке наименьших потерь. Алгоритм Adam является одним из наиболее часто используемых оптимизаторов, поскольку он дает большую производительность при решении большинства задач:

epochs = 25
optimizer = 'adam'

Теперь давайте скомпилируем модель с выбранными нами параметрами. Давайте также определим метрику для использования.

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

Мы можем распечатать сводку модели, чтобы увидеть, как выглядит вся модель.

print(model.summary())

Распечатка резюме даст нам довольно много информации:

Results:
                
Layer (type) Output Shape Param #
=================================================================
conv2d_1 (Conv2D) (None, 32, 32, 32) 896
_________________________________________________________________
activation_1 (Activation) (None, 32, 32, 32) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 32, 32, 32) 0
_________________________________________________________________
batch_normalization_1 (Batch (None, 32, 32, 32) 128
_________________________________________________________________
conv2d_2 (Conv2D) (None, 32, 32, 64) 18496
_________________________________________________________________
activation_2 (Activation) (None, 32, 32, 64) 0
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 16, 16, 64) 0
_________________________________________________________________
dropout_2 (Dropout) (None, 16, 16, 64) 0
_________________________________________________________________
batch_normalization_2 (Batch (None, 16, 16, 64) 256
_________________________________________________________________
conv2d_3 (Conv2D) (None, 16, 16, 64) 36928
_________________________________________________________________
activation_3 (Activation) (None, 16, 16, 64) 0
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 8, 8, 64) 0
_________________________________________________________________
dropout_3 (Dropout) (None, 8, 8, 64) 0
_________________________________________________________________
batch_normalization_3 (Batch (None, 8, 8, 64) 256
_________________________________________________________________
conv2d_4 (Conv2D) (None, 8, 8, 128) 73856
_________________________________________________________________
activation_4 (Activation) (None, 8, 8, 128) 0
_________________________________________________________________
dropout_4 (Dropout) (None, 8, 8, 128) 0
_________________________________________________________________
batch_normalization_4 (Batch (None, 8, 8, 128) 512
_________________________________________________________________
flatten_1 (Flatten) (None, 8192) 0
_________________________________________________________________
dropout_5 (Dropout) (None, 8192) 0
_________________________________________________________________
dense_1 (Dense) (None, 256) 2097408
_________________________________________________________________
activation_5 (Activation) (None, 256) 0
_________________________________________________________________
dropout_6 (Dropout) (None, 256) 0
_________________________________________________________________
batch_normalization_5 (Batch (None, 256) 1024
_________________________________________________________________
dense_2 (Dense) (None, 128) 32896
_________________________________________________________________
activation_6 (Activation) (None, 128) 0
_________________________________________________________________
dropout_7 (Dropout) (None, 128) 0
_________________________________________________________________
batch_normalization_6 (Batch (None, 128) 512
_________________________________________________________________
dense_3 (Dense) (None, 10) 1290
_________________________________________________________________
activation_7 (Activation) (None, 10) 0
=================================================================
Total params: 2,264,458
Trainable params: 2,263,114
Non-trainable params: 1,344

Теперь перейдем к тренировке модели. Для этого все, что нам нужно сделать, это вызвать функцию fit() в модели и передать выбранные параметры.

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

numpy.random.seed(seed)
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs, batch_size=64)

Мы будем тренироваться на 50000 образцах и проверять достоверность на 10000 образцах.

Запуск этого фрагмента кода приведет к:

Epoch 1/25

64/50000 [..............................] - ETA: 16:57 - loss: 3.1479 - acc: 0.0938
128/50000 [..............................] - ETA: 10:12 - loss: 3.0212 - acc: 0.0938
192/50000 [..............................] - ETA: 7:57 - loss: 2.9781 - acc: 0.1250
256/50000 [..............................] - ETA: 6:48 - loss: 2.8830 - acc: 0.1484
320/50000 [..............................] - ETA: 6:07 - loss: 2.8878 - acc: 0.1469
384/50000 [..............................] - ETA: 5:40 - loss: 2.8732 - acc: 0.1458
448/50000 [..............................] - ETA: 5:20 - loss: 2.8842 - acc: 0.1406

...
...
...

49664/50000 [============================>.] - ETA: 1s - loss: 1.5160 - acc: 0.4611
49728/50000 [============================>.] - ETA: 1s - loss: 1.5157 - acc: 0.4612
49792/50000 [============================>.] - ETA: 1s - loss: 1.5153 - acc: 0.4614
49856/50000 [============================>.] - ETA: 0s - loss: 1.5147 - acc: 0.4615
49920/50000 [============================>.] - ETA: 0s - loss: 1.5144 - acc: 0.4617
49984/50000 [============================>.] - ETA: 0s - loss: 1.5141 - acc: 0.4617
50000/50000 [==============================] - 262s 5ms/step - loss: 1.5140 - acc: 0.4618 - val_loss: 1.0715 - val_acc: 0.6195

End of Epoch 1

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

Теперь мы можем оценить модель и посмотреть, как она работает. Просто вызовите model.evaluate() :

# Model evaluation
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))

И нас встречает результат:

Accuracy: 83.01%

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

Вывод

Теперь, когда вы внедрили свою первую сеть распознавания изображений в Керале, было бы неплохо поиграть с моделью и посмотреть, как изменение ее параметров влияет на ее производительность.

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

Если вы хотите поиграть с кодом или просто изучить его немного глубже, проект будет загружен на GitHub !