Классификация и обнаружение изображений - одни из самых важных задач в области компьютерного зрения и машинного обучения. В этом блоге я тренирую модель машинного обучения для классификации различных видов одежды с использованием сверточной нейронной сети, подобной VGG (Visual Geometry Group) (Симонян и др., 2014).

Этот блог будет полезен для тех, кто имеет базовое представление о CNN и ищет практические рекомендации по их реализации с использованием Keras. Прочитав этот блог, вы будете знакомы с:

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

В архитектуре VGG все сверточные слои используют фильтры размером 3 x 3 с шагом = 1 и одинаковым заполнением, а все слои с максимальным объединением имеют размер фильтра 2 x 2 с шагом = 2. С каждым набором сверточного слоя количество фильтров удваивается, а с каждым объединяющим слоем ширина и высота изображения уменьшаются вдвое. Здесь я выполняю задачу классификации, используя меньшую модель, похожую на VGG. Я не использую полную модель VGG из-за ее громоздких размеров с большим количеством параметров (которые, как известно, есть у VGG). Хотя существует ряд других моделей, которые превзошли VGG, такие как ResNet, Inception и т. Д., VGG прост для понимания новичками и дает хорошее представление о том, как реализовать сверточные сети в целом. Если вы хотите освежить память о сверточных нейронных сетях, можете заглянуть в этот блог.

Блог разделен на четыре основных этапа, общих почти для каждой задачи классификации изображений:

  • Шаг 1: Загрузите данные (настройте рабочие каталоги, инициализируйте изображения, измените размер и выполните разделение тестовой поездкой)
  • Шаг 2. Настройте модель (расширение данных, построение модели, настройка обратных вызовов и другие гиперпараметры)
  • Шаг 3. Обучите модель (обучите и следите за прогрессом)
  • Шаг 4: Оценка и прогноз (получите отчет о классификации и спрогнозируйте ярлыки классов для новых невидимых изображений)

Набор данных был загружен с Kaggle. Хотя исходный набор данных содержит около 24 различных категорий одежды, в этот блог я включил только 8 из них. Код доступен в моем репозитории Github здесь. После загрузки набора данных вы можете организовать данные в этой структуре каталогов (вы можете сгенерировать эту структуру, перейдя в целевой каталог и используя tree --filelimit=15 в терминале).

.
├── Dataset
│   ├── black_dress [450 entries]
│   ├── black_pants [539 entries]
|   .  
|   .
│   └── white_dress [506 entries]
├── Output
├── logs
├── main.py
├── predict.py
├── train.py
└── vgg.py

Различные категории данных хранятся в папке Dataset. Каждая категория содержит ~ 450–550 записей, что дает нам сбалансированный набор данных. Обученная модель и графики потери точности будут сохранены в папке Output. Папка журналов предназначена для хранения контрольных точек для отслеживания прогресса потерь и точности в реальном времени на тензорной доске во время обучения модели.

Шаг 1. Загрузите данные

Для классификации нам нужно инициализировать наш вход X и выход Y, где X и Y - изображения и соответствующие им метки классов. В блоке кода ниже мы определяем рабочий каталог и загружаем путь ко всем изображениям из data_dir в список imagePaths. Перед загрузкой рекомендуется менять порядок входных изображений, чтобы избежать искажений в последовательности данных. Мы перебираем все пути изображения и извлекаем изображения из путей и изменяем размер (размер 64 x 64 пикселя). Изображения (вход X) и их соответствующие метки (выход Y) теперь сохраняются в списках data и labels соответственно.

Вот краткий обзор набора данных:

Мы конвертируем списки data и labels в массивы NumPy и нормализуем data для более быстрой сходимости. Для обучения модели категориальные метки должны быть преобразованы в горячие векторные кодировки. Мы используем LabelBinarizer для нескольких ярлыков, но если у вас всего две категории, вы можете использовать вместо этого LabelEncoder, который будет производить целочисленные кодировки. Закодированные имена классов сохраняются в файле pickle сериализованным способом для поиска имени класса позже во время прогнозирования.

Теперь, когда у нас есть данные (X) и их метки (Y) в правильном формате, данные разделены на обучающие и тестовые наборы (для обучения и тестирования, как следует из названия) с помощью train_test_split функция. Он принимает такие аргументы, как данные ( X ) и их метки ( Y ), test_size , определяющий коэффициент разделения, и random_state, определяющий параметр перемешивания.

Шаг 2: Настройте модель

После разделения набора данных мы дополняем наши данные, чтобы предотвратить переоснащение и улучшить обобщение, создав аналогичные изображения исходных данных, отличающиеся линейным переносом, отражением, вращением и сдвигом. Можно также искусственно добавить преобразованные изображения в набор данных, но у Keras есть класс ImageDataGenerator, который автоматически делает это в соответствии с предоставленными аргументами. Значения аргументов, таких как диапазон_ вращения, диапазон_ширин_смещения, диапазон_высоты_двига, диапазон_двига, диапазон_крупности, горизонтальное_флип, можно настроить в зависимости от набора данных. Если вы решили добавить искусственно преобразованные изображения, не забудьте сделать это только на наборе поездов, а не на тестовом наборе, потому что это вызовет утечку данных, что приведет к высокой ложной точности. Архитектуру модели VGG можно инициализировать, импортировав ее из модуля vgg.py .

Одна из очень полезных функций в Keras - это обратные вызовы, которые используются во время обучения модели для целей мониторинга, регистрации и отладки. Здесь мы используем ModelCheckpoint, TerminateOnNaN, ReduceLROnPlateau, и TensorBoard во время обучения .

  • ModelCheckpoint создает контрольные точки после каждых нескольких эпох (число, указанное аргументом period) с именем файла, содержащим значения для этой конкретной эпохи. Например: 'VGG_epoch- {epoch: 02d} _loss- {loss: .4f} _val_loss- {val_loss: .4f} .h5' будет содержать номер эпохи, потерю обучения и потерю проверки в имя файла контрольной точки.
  • TerminateOnNaN останавливает обучение, если значение потери становится равным Nan в любой момент .
  • ReduceLROnPlateau снижает скорость обучения на определенный коэффициент, когда определенное количество (здесь потеря проверки) не уменьшается с количеством эпох. Аргумент терпение определяет количество эпох, после которых скорость обучения будет снижена, если улучшения не наблюдается.
  • TensorBoard позволяет динамически визуализировать и отслеживать ход обучения. Журналы хранятся в пути к папке, заданном аргументом каталог_журнала. Чтобы открыть тензорборд, убедитесь, что тензорборд установлен. Обучение можно визуализировать, используя эту команду в терминале: tensorboard --logdir=/path_to_logs, а затем открыв localhost: 6006 в вашем браузере . Для этой конкретной структуры каталогов используйте tensorboard --logdir='./logs.

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

Шаг 3: Обучение

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

Модель обучается более 100 эпох с помощью оптимизатора Adam, начальная скорость обучения 0,0007 и размер пакета 64 в этом случае. Сначала я использовал скорость обучения 0,001, которая является параметром по умолчанию для использования Adam. Однако значения точности и потерь показали большие колебания, поэтому я снизил скорость обучения и пришел к оптимальному числу 0,0007.

Epoch 1/100
53/53 [==============================] - 109s 2s/step - loss: 1.3691 - acc: 0.5699 - val_loss: 1.2561 - val_acc: 0.7312
.
.
.
Epoch 100/100
53/53 [==============================] - 86s 2s/step - loss: 0.0825 - acc: 0.9653 - val_loss: 0.0921 - val_acc: 0.9666

Графики обучения потерь и точности показали, что уменьшение скорости обучения с помощью ReduceLROnPlateau имело существенное значение, когда потери были на плато. Модель достигла общей точности 97%.

Шаг 4: оценка и прогноз

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

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

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

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

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

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

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

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

Я также хотел бы поблагодарить Адриана Роузброка за все, что я узнал из его блогов о компьютерном зрении.

использованная литература