В рамках моего учебного процесса, после SchoolofAI Paris и курса машинного обучения, который я организовываю для организации 19AI, я начал машинное обучение с помощью нового курса fast.ai и применил первый урок к своим собственным данным и поэкспериментировал с моими боковая сторона.

Цель этой статьи - дать быстрое первое знакомство с fast.ai и тем, как быстро создать первую модель.

Я решил использовать конкурс Kaggle Признание цветка для набора данных (более 4000 изображений 5 классов) и запустить его в Google Colab.

Сбор данных

Я сделал это старым способом, загрузив файлы и экспортировав их на Диск, прежде чем заметил, что вы можете напрямую импортировать данные из Kaggle в Google Colab… В следующий раз будет лучше.

На данный момент я только что создал файл Jupyter и папку с данными в одной подпапке.

# in order to link the content of your drive to you jupyter file
from google.colab import drive
drive.mount(‘/content/drive’)

Инициализация всего

Давайте сначала определим, где я могу найти данные:

p = pathlib.Path('./drive/My Drive/your_path/')
path = p.absolute()/'flowers'

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

path.ls()
[PosixPath('/content/drive/My Drive/your_path/flowers/rose'),  PosixPath('/content/drive/My Drive/your_path/flowers/tulip'),  PosixPath('/content/drive/My Drive/your_path/flowers/dandelion'),  PosixPath('/content/drive/My Drive/your_path/flowers/daisy'),  PosixPath('/content/drive/My Drive/your_path/flowers/sunflower'),  PosixPath('/content/drive/My Drive/your_path/flowers/models')]

Библиотека fast.ai предоставляет удобный способ получения метки в зависимости от имени папки внутри класса ImageDataBunch.

С помощью метода from_folder () мы сразу определим следующие вещи:

  1. Корень основной папки. В нашем случае: цветы.
  2. Коэффициент набора проверки. Это определение X% набора данных в качестве набора для проверки и того, что остается в качестве набора для обучения.
  3. Изменение размера импортируемых изображений, чтобы все они были одинакового размера.
  4. Используйте изменение изображения, чтобы иметь больший набор данных.
data = ImageDataBunch.from_folder(path, train = 'data', valid_pct = 0.2, size = 224, ds_tfms = get_transforms())

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

data.normalize(imagenet_stats)

Теперь, когда у нас есть все данные, давайте убедимся, что все в порядке:

Тренировочный процесс

Когда данные готовы, мы можем создать пустой CCN с помощью create_cnn (). Кроме того, мы уже можем дать параметры для его настройки. Сейчас мы определяем:

  1. Ссылка на наши предварительно обработанные данные
  2. Предварительно обученная архитектура, которую мы хотели бы, чтобы у CNN уже была
  3. Цель CNN: здесь цель - максимально снизить error_rate.
learn = create_cnn(data, models.resnet34, metrics=error_rate)

Это та часть, которой я не особо горжусь, но надеюсь, что это поможет другим не повторять ту же ошибку.

Я начал процесс обучения на 4 эпохах (эпоха - это цикл, в котором все данные проверяются один раз):

learn.model
learn.fit_one_cycle(4)

Неудивительно, что это заняло у меня слишком много времени, чтобы обработать: 4,5 мин. Действительно, я начал обрабатывать 4.000+ картинок. Четыре раза. Хорошие результаты все же.

Поэтому, прежде чем пробовать что-либо еще, я создал меньший набор данных: ~ 400 изображений.

Этот набор поможет мне настроить гиперпараметры перед тем, как начать процесс с 4000+ картинками. С этим новым набором данных я могу обрабатывать их намного быстрее. Давайте запустим lr_find, чтобы проверить кривую обучения / скорости:

Мы, несомненно, могли бы нацелиться на лучший LR, между 5e-3 и 2e-2, в конце склона.

Давайте обучим модель на этих 400 изображениях со следующим lr:

learn.fit_one_cycle(8, max_lr=slice(5e-3, 2e-2))

Давайте теперь снова проанализируем соотношение скорость обучения / потери после размораживания модели. Это поможет нам получить максимум от нашей CNN, минимизируя потери.

learn.unfreeze()
learn.lr_find()

После построения мы можем определить лучший LR: от 2e-4 до 1e-6.

learn.fit_one_cycle(8, max_lr=slice(1e-6, 1e-2))

Результат меня устраивает. Мы получили 3,2 улучшения по сравнению с исходной моделью и заканчивая точностью 91,2%.

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

94,3% точность. Не мог надеяться на лучшее с первого раза.

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

Давайте сначала проанализируем общую ошибку.

interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix(figsize=(5,5), dpi = 120)

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

Давайте теперь проверим самую высокую ошибочную классификацию.

interp.plot_top_losses(9, figsize=(15, 11))

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

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

На сегодня все кончено :-)

Следующая статья будет о скорости обучения и о том, что это такое на самом деле.

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

Также спасибо Реми за его статью, которая помогла мне сформировать мою.