Создайте CNN с нуля для классификации изображений

Введение

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

Давайте погрузимся!

Что такое набор данных CIFAR-10?

Набор данных CIFAR-10 состоит из 60000 цветных изображений 32x32 в 10 классах, по 6000 изображений в каждом классе. Есть 50000 обучающих изображений и 10000 тестовых изображений.

Набор данных разделен на пять обучающих пакетов и один тестовый пакет, каждый из которых содержит 10 000 изображений. Тестовая партия содержит ровно 1000 случайно выбранных изображений из каждого класса. Обучающие пакеты содержат оставшиеся изображения в случайном порядке, но некоторые обучающие пакеты могут содержать больше изображений из одного класса, чем из другого. Между ними обучающие пакеты содержат ровно 5000 изображений из каждого класса.

Классы полностью взаимоисключающие. Между легковым и грузовым транспортом нет пересечения. «Автомобиль» включает в себя седаны, внедорожники и тому подобное. «Грузовик» включает только большие грузовики. Ни один из них не включает пикапы.

Наборы данных Torchvision

В этой статье мы будем использовать набор данных из PyTorch. Здесь есть много других замечательных наборов данных. https://pytorch.org/docs/stable/torchvision/datasets.html

Проверка вычислительных возможностей графического процессора

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

Импорт данных

В следующем коде мы получаем набор данных от torchvision. Я указал 20 % обучающих данных, которые будут использоваться для проверки, и размер пакета из 30 изображений. Я настоятельно рекомендую вам использовать набор данных для проверки, ниже мы увидим, как он помогает в выборе правильной конфигурации сети.

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

Массив классов содержит 10 классов, присутствующих в наборе данных.

Просмотр изображения из данных тренировки🔎

Из приведенного выше примера изображения из набора обучающих данных мы можем видеть, как применяется наше преобразование RandomRotation (20).

Архитектура нейронной сети

Наша модель должна принимать изображение размером 32x32 пикселя в спектре RGB (глубина = 3) в качестве входных данных и возвращать выходные данные в виде одного из 10 классов (самолет, автомобиль, птица, кошка, олень, собака, лягушка, лошадь, корабль, грузовик).

Я создал архитектуру, как показано ниже, первый сверточный слой принимает ввод тензора изображения 32x32x3. выход первого слоя - тензор 32x32x16, после каждого слоя мы видим, что глубина увеличивается. В некоторой сетевой архитектуре вы можете увидеть слой пула между каждым сверточным слоем для уменьшения размера. Хотя слой пула помогает уменьшить размер, он также может потерять некоторые данные. поскольку наше входное изображение маленькое, я использовал слой объединения после каждых 2 сверточных слоев. после слоя объединения 2x2 мы видим, что размер тензора уменьшился до 16x16 с 32x32. Входной тензор для сверточных слоев 3 и 4 имеет размеры 16x16x32 и 16x16x64 соответственно.

Я использовал отсев 25%. Dropout помогает предотвратить переоснащение, игнорируя нейроны во время обучения. Я также создал функцию weights_init_normal для инициализации модели с нормально распределенными весами. Вам не нужно этого делать, но в более крупных моделях это может помочь быстро сойтись потерям при обучении и проверке.

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

Определить функцию потерь и оптимизатор

Я выбрал оптимизатор Adam, ознакомьтесь с другими оптимизаторами, включая SGD, здесь. Для скорости обучения установлено значение 0,001.

Обучение и проверка

Мы вызываем метод обучения с различными параметрами, такими как количество эпох, модель, загрузчики и т. д. Мы передаем изображение (данные) из набора обучающих данных (загрузчики [‘train’]) в модель. Затем рассчитайте потери и выполните обратное распространение, во время которого мы обновляем веса на основе потерь. model.eval() уведомляет все слои о том, что мы находимся в режиме eval, поэтому нормальные и выпадающие слои будут работать в режиме eval.

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

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

Из приведенного выше вывода мы видим, что модель была сохранена после эпохи 54. она имеет потерю проверки 0,54.

Хотя я запускал текущую модель до 60 эпох, ранее с другим набором гиперпараметров я мог получить аналогичную производительность в течение 15 эпох.

Постройте график потерь при обучении и проверке

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

Протестируйте модель

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

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

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

Текущий вывод показывает все 20 правильно классифицированных изображений, проверьте свои и найдите несколько неправильно классифицированных.

Мысли об улучшении модели

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

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

  • Скорость обучения
  • Эпоха
  • Выбывать
  • Размер партии
  • Добавить/удалить преобразования
  • Добавить/удалить сверточный слой
  • Изменить оптимизатор

Я люблю слышать ваши предложения / отзывы!