Глубокое обучение, Машинное обучение, Python

Классификация изображений с использованием Deep Learning и PyTorch: пример использования данных изображений цветов

Классификация изображений цветов с использованием сверточной глубокой нейронной сети с библиотекой PyTorch

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

Для этого мы будем использовать библиотеки Python PyTorch, TorchVision и PIL.

Исследование данных

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

Теперь мы увидим образец изображения цветка из папки «роза».

show_image("../data/flowers/rose/537207677_f96a0507bb.jpg")

Предварительная обработка данных

PyTorch всегда ожидает данные в виде «тензоров». Эти «тензоры» проходят между узлами нейронной сети и содержат исходные и предварительно или постобработанные данные. Короче говоря, «тензоры» аналогичны массивам «numpy».

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

Мы можем рассматривать изображение как трехмерный тензор. Каждое изображение может иметь 3 типа значений цвета пикселей - красный, зеленый и синий соответственно. Мы называем это цветовым кодированием RGB. Два других измерения - это значения в пикселях по длине и ширине.

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

  1. Изменение размера в соответствии с шаблоном. Изменение размера изображения на квадратную. В нашем случае мы изменим размер каждого изображения до изображения 64x64.
  2. Нормализация: статистическая нормализация с использованием механизма (x - среднее) / SD для каждого значения пикселя. Это помогает улучшить визуализацию, улучшить характеристики и увеличить контраст изображения.

Используя PyTorch, мы сделаем этот набор предварительной обработки

Мы также можем определить функцию для отображения набора преобразованных изображений.

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

show_transformed_image(make_grid(image))

У нас также может быть класс для индексации словаря данных

Это поможет в идентификации классов.

Построение модели

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

Слой свертки

Математически операция свертки между двумя функциями f и g определяется как

На практике, если мы рассматриваем f как тензор изображения, то g должен быть другим тензором, который может работать как «ядро свертки».

Это попиксельное суммирование умноженных значений двух тензоров.

На диаграмме ниже показано влияние операции свертки на тензор образца изображения.

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

Выход (0,0) = тензор изображения (0,0) x ядро ​​(0,0) + тензор изображения (0,1) x ядро ​​(0,1) + тензор изображения (0,2) x ядро ​​(0,2 ) + Тензор изображения (1,0) x ядро ​​(1,0) + тензор изображения (1,1) x ядро ​​(1,1) + тензор изображения (1,2) x ядро ​​(1,2) + тензор изображения ( 2,0) x ядро ​​(2,0) + тензор изображения (2,1) x ядро ​​(2,1) + тензор изображения (2,2) x ядро ​​(2,2) = 1 x 1 + 1 x 0 + 1 Икс 1 + 0 Икс 0 + 1 Икс 1 + 1 Икс 0 + 0 Икс 1 + 0 Икс 0 + 1 Икс 1 = 4

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

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

Поскольку каждое изображение следует цветовой кодировке RGB, мы применим операцию свертки для каждого цвета и, следовательно, получим три выходных тензора. Конечным результатом будет тензорное суммирование всех трех. Каждый из этих «цветовых кодов» известен как «канал» в терминологии PyTorch API.

Математически, если фильтр размера kxk применяется к изображению размером WxH, то он создает выходное изображение / тензор размера (W-k + 1) x (H-k + 1)

В нашем случае свертка создается так

self.conv1 = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=3,stride=1, padding=1)

«Out_channels» указывает, сколько фильтров нужно применить. Здесь мы применили 12 фильтров, которые дадут 12 промежуточных тензоров изображений размером 62x62. Каждое из этих изображений содержит одну уникальную особенность исходного изображения.

Для получения дополнительной информации о «Фильтрах свертки» читатели могут перейти по ссылке ниже.



Слой ReLU

«ReLU» - это функция активации, которая фиксирует нелинейность вывода другой функции. Математически это определяется как

Таким образом, он всегда возвращает положительное значение. Можно сказать, что это «позитивный фильтр». После свертки мы применим слой «ReLU».

В нашем случае ReLU создается, как показано ниже.

self.relu1 = nn.ReLU()

Максимальный уровень объединения

«Максимальный уровень объединения» обычно следует после «ReLU». «Максимальный пул» размера 2 представляет собой окно 2x2, которое пересекает выходной тензор операции «ReLU» и выбирает максимальное значение пикселя в пределах окна. Эту операцию можно пояснить на схеме ниже.

Цель слоя «Максимальный пул» - выбрать только те функции, которые имеют большое влияние и большую ценность. Это помогает уменьшить размеры элементов.

В нашем случае «Максимальный пул» создается, как показано ниже.

self.maxpool1 = nn.MaxPool2d(kernel_size=2)

Это уменьшит размер изображения на 50% (32 = 64/2).

Линейный функциональный слой

Как следует из названия, это линейная функция, которая принимает выходные данные «Max Pool» в виде сглаженного массива и выдает выходные данные в виде индексов классов. Выходное значение «Линейной функции» для прогнозируемых индексов класса будет максимальным.

В нашем случае «Линейная функция» создается, как показано ниже.

self.lf = nn.Linear(in_features=32 * 32 * 24, out_features=num_classes)

Общая архитектура модели

Мы будем применять разные слои, как показано на схеме ниже.

У нас есть два набора слоев «свертка» и «ReLU». «View» выполняет сглаживание выходных тензоров из последнего слоя «ReLU». У нас есть тензор изображения размером 64x64 в качестве входных данных, который будет уменьшен до 32x32 из-за применения «MaxPool2D» с размером ядра 2x2 (32 = 64/2).

Сначала мы разделим набор данных на тренировку и тест в соотношении 80:20.

Затем мы напишем собственный класс для наложения этих слоев, расширив «Модуль», предоставленный библиотекой PyTorch.

«__Init__» определяет каждый уровень и его параметры, тогда как функция «forward» выполняет фактические вызовы и наложение слоев. Выходные данные последнего слоя возвращаются функцией «вперед».

Модельное обучение

Нам нужен оптимизатор и функция потерь для обучения модели. Для этого мы будем использовать Adam optimizer и Cross-Entropy Loss.

from torch.optim import Adam
cnn_model = FlowerClassifierCNNModel()
optimizer = Adam(cnn_model.parameters())
loss_fn = nn.CrossEntropyLoss()

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

Мы можем написать функцию для этого

Вызов функции «loss.backward» возвращается к слоям и вычисляет потери, произошедшие во время процесса.

Мы будем использовать «epoche» из 200 для обучения модели.

train_and_build(200)

Тестирование модели и точность

Мы должны установить модель в режим eval, чтобы проверить ее точность на тестовом наборе данных.

Функция torch.max возвращает максимальное значение из выходного тензора «Линейной функции». Максимальное значение подразумевает прогнозируемую метку класса.

Функция torch.sum суммирует «1» в тензоре, который является результатом операции «И» между тензором «предсказанный» и «фактический тестовый выход». Таким образом, это суммирование дает количество правильно предсказанных изображений.

И здесь мы получаем точность

test_accuracy

Это почти 70,52%. Мы получили хорошую точность на простой модели. Эта модель может быть дополнительно доработана.

Использование модели для прогнозирования с образцом изображения

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

show_image("../data/flowers/dandelion/13920113_f03e867ea7_m.jpg")

Это изображение «Одуванчика».

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

class_index

Итак, переходя от класса к словарю индекса, как упоминалось выше, мы можем подтвердить, что это «Одуванчик». Итак, наша модель классификатора изображений работает хорошо !!

Заключение

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

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

Блокнот Jupyter для этого можно найти по ссылке ниже



Недавно я написал книгу по ML (https://twitter.com/bpbonline/status/1256146448346988546)