Опубликовано с моего сайта

Разработка набора данных

В этом проекте я буду делать классификатор изображений. Мои предыдущие попытки какое-то время назад, насколько я помню, не сработали. Чтобы немного изменить его, я буду использовать фреймворк Pytorch. Вместо TensorFlow. Так как это будет мой первый опыт использования Pytorch. Я буду брать учебник, прежде чем я начну свой проект. Проект представляет собой классификатор, который выявляет разницу между бутилированным чаем улун и бутилированным зеленым чаем.

Учебник, который я использовал, назывался 60-минутный блиц от PyTorch. (Хотя это заняло у меня более 60 минут). Набрав учебник, я привык использовать Pytorch. Так я начал продвигаться по проекту. Так как это будет классификатор изображений. Мне нужно было получить много изображений в моем наборе данных. Сначала наткнулся на статью среднего размера. Который использовал хороший скребок. Но даже после нескольких правок это не сработало.

Поэтому я перешел к использованию Bing для поиска изображений. У Bing есть API изображений, который вы можете использовать. Что упрощает сбор изображений по сравнению с Google. Я использовал эту статью из pyimagesearch. Сначала у меня было несколько проблем с API. Поскольку конечные точки, предоставленные мне Microsoft, не подходят для этого руководства. После осмотра и нескольких правок я смог заставить его работать.

Но просмотр папки с изображениями дал мне следующее:

Просмотрев код, я заметил, что программа не создает новые изображения. Но изменил изображения на «000000». Это произошло из-за того, что не был скопирован последний раздел кода из сообщения в блоге. Который обновил переменную счетчика.

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

После этого я получил чай улун, используя термин «бутылочный чай улун».

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

Это потому, что мы хотим, чтобы классификатор работал с напитками в бутылках. Так что листья не актуальны. Какими бы вкусными они ни были.

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

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

После того, как я сделал это с обоими наборами данных. Я был готов перейти к созданию модели. Так что пошел в Google Collab и импортировал Pytorch.

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

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

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

Разработка модели

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

shape ‘[-1, 400]’ is invalid for input of size 179776

Я смог решить эту проблему, изменив размеры ядра на 2 x 2. И изменил карты функций на 64.

self.fc1 = nn.Linear(64 * 2 * 2, 120)
x = x.view(-1, 64 * 2 * 2)

Сразу после этого я попал в другую ошибку:

ValueError: Expected input batch_size (3025) to match target batch_size (4).

Это было исправлено путем повторного изменения формы переменной x.

x = x.view(-1, 64 * 55 * 55)

Используя этот форумный пост.

Потом еще одна ошибка 😩.

RuntimeError: size mismatch, m1: [4 x 193600], m2: [256 x 120] at /pytorch/aten/src/TH/generic/THTensorMath.cpp:41

Это было исправлено путем повторного изменения линейного слоя.

self.fc1 = nn.Linear(64 * 55 * 55, 120)

Блин, я не знал, что один плотный слой может доставить мне столько головной боли.

После тренировки. Мне нужно было протестировать модель. Я не делал тестовую папку перед изготовлением модели. (ошибка новичка). Я сделал это быстро, используя первые 5 изображений каждого класса. Это плохо. Это может загрязнить данные. И привести к переоснащению. Но мне нужно было посмотреть, работала ли модель в то время.

Я хотел построить одно из изображений в тестовой папке. Поэтому я позаимствовал код из учебника. Это привело к ошибке. Но исправил это, изменив диапазон на единицу. Вместо 5. Это потому, что у моей модели всего 2 этикетки. (тензор[0] и тензор[1]) Не 4.

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

if i % 10 == 0:
   print('[%d, %d] loss: %.5f' %
       (epoch + 1, i + 1, running_loss / 10))
   running_loss = 0.0

Как мы видим, потери очень велики.

Когда я тестировал модель в тестовой папке, это дало мне следующее:

Это означает, что это в лучшем случае угадывание. Позже я обнаружил, что это произошло потому, что каждое изображение было выбрано как зеленый чай. С 5 изображениями с этикеткой зеленого чая. Это приводит к тому, что он оказывается правильным в 50% случаев.

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

Отладка модели

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

Первое, что сказал автор, — начать с простой задачи, которая, как известно, работает с вашим типом данных. Хотя я думал, что использую простую модель, предназначенную для работы с данными изображений. Поскольку я заимствовал модель из учебника Pytorch. Но это не сработало. Поэтому выбрал более простую форму модели. Который я нашел из учебника TensorFlow. Который имел только 3 сверточных слоя. И два плотных слоя. Мне пришлось изменить окончательные параметры слоя, так как они выдавали мне ошибки. Поскольку он был разработан для 10 целей в виду. Вместо 2. После этого я возился с гиперпараметрами. При этом я смог довести точность тестовых изображений до 80% 😀.

Accuracy of the network on the 10 test images: 80 %
10
8

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

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

Чтобы реструктурировать его, я сделал это в следующем стиле:

При вызове тестового и обучающего набора данных по отдельности.

train_dataset = ImageFolder(root='data/train')
test_dataset  = ImageFolder(root='data/test')

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

Accuracy of the network on the 10 test images: 70 %
10
7

Поскольку это не было значительным уменьшением, модель узнала кое-что о зеленом чае и чае улун.

Используя код из учебника Pytorch, я хотел проанализировать его еще больше:

Accuracy of Green_tea_test : 80 %
Accuracy of oolong_tea_test : 60 %

Составление прогнозов

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

for i, t, p, in zip(img_list, truth_label, predicted_label):
  one_merge_dict = {'image': i, 'truth_label': t, 'predicted_label':    p}
  merge_list.append(one_merge_dict)
print(merge_list)

С первой попытки у меня получилось следующее:

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

Теперь я могу начать отделять изображения от правильного к неправильному.

Я смог сделать это, используя небольшой оператор if

Я хотел избавиться от пробелов, поэтому решил изменить прорисовку изображений.

ax = plt.subplot(1, 4, i + 1)
fig = plt.figure(figsize=(15,15))

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

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