Пошаговое руководство по использованию Fastai

Средний индиец производит около 450 граммов мусора в среднем в день. Настоящая проблема не в количестве производимого мусора. Проблема в раздельном сборе мусора.

10–15 минут моего ежедневного времени уходит на размышления о том, как разделить мусор по разным корзинам. В противном случае это время можно было бы потратить лучше, например, быстро вздремнуть 15 минут :).

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

Что ж! кажется, мы можем научить машину делать это. К счастью, в Kaggle есть набор данных, в котором есть множество примеров о различных типах мусора. Шашанк Секар создал этот набор данных, и он доступен здесь на kaggle.

Давайте начнем

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

Подробнее об этой команде можно прочитать здесь.

%reload_ext autoreload
%autoreload 2
%matplotlib inline

Следующие строки кода — это обычные ритуалы поиска библиотеки «fastai» на вашем компьютере, а затем возврата всех функций, написанных в модулях с именами «vision» и «metric».

Подробности об импорте в python объясняются здесь.

Ой! Я упоминал, что вам потребуется установить библиотеку fastai V1, которая находится поверх Pytorch 1.0.

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

from pathlib import Path
from fastai.vision import *
from fastai.metrics import error_rate

Потребность во власти

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

Если у вас нет графического процессора, то у fastai есть очень хорошо документированные шаги здесь или здесь, которые помогут вам в этом. Вы даже можете запустить версию этого поста, которую я разместил здесь на Kaggle.

В порядке! у вас есть GPU, у вас есть ссылка на набор данных. Теперь вам нужно установить «размер партии». Чего ждать? какой размер партии?

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

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

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

Fastai дает вам размер пакета по умолчанию 64, который работает в большинстве сценариев.

Как увидеть данные

Чтобы сначала увидеть данные, вам нужно получить их с сайта, на котором они размещены. Если вы пробуете эту записную книжку на своем локальном компьютере или на облачном сервере, отличном от Kaggle, раскомментируйте следующие строки, удалив `#` в следующей строке.

#path = untar_data('https://www.kaggle.com/techsash/waste-classification-data', <destination>)

Когда вы раскомментируете предыдущий код и запустите его, метод untar_data() загрузит набор данных с указанного вами URL-адреса, а затем разархивирует файл в место назначения.

Переменная `path` даст вам представление о файловой системе, в которую загружаются ваши данные.

Подробнее о методе untar_data() можно узнать здесь.

Замените «‹destination›» на путь, по которому вы хотите сохранить загруженные данные.

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

После этого вы можете запустить приведенный ниже код, чтобы обернуть путь «../input» во встроенный в Python метод, известный как Path(), который дает вам представление файловой системы, в которой хранятся ваши данные.

Любопытные могут обратиться к документации по Python здесь, чтобы удовлетворить свою жажду узнать больше о методе Path().

path = Path('../input/waste-classification-data/dataset/DATASET');

Если вы используете kaggle, то путь к этому набору данных будет похож на путь внутри метода Path(). Если вы используете свой локальный компьютер или сервер GPU, замените путь внутри метода Path() на корневую папку набора данных.

Следующие две переменные pathTest и pathTrain содержат подпапки train и test, которые находятся внутри этого конкретного набора данных. Когда вы делаете pathTest.ls(), он отображает папки и подпапки по этому пути.

Любознательные могут сослаться на документацию по Python здесь, чтобы удовлетворить свое желание узнать больше о методе `Path()`.

pathTest = path/'TEST'
pathTrain = path/'TRAIN'
pathTest.ls()
------
Output
------
[PosixPath('../input/waste-classification-data/dataset/DATASET/TEST/O'), PosixPath('../input/waste-classification-data/dataset/DATASET/TEST/R')]

В приведенном выше выводе вы можете видеть, что это подпапки с именами «O» и «R» внутри папки «TEST». Что внутри этих папок? Следующий код может дать вам ответ.

numberOfFiles = (pathTest/'O').ls()
numberOfFiles[:5]
------
Output
------
[PosixPath('../input/waste-classification-data/dataset/DATASET/TEST/O/O_13022.jpg'),
 PosixPath('../input/waste-classification-data/dataset/DATASET/TEST/O/O_12670.jpg'),
 PosixPath('../input/waste-classification-data/dataset/DATASET/TEST/O/O_13838.jpg'),
 PosixPath('../input/waste-classification-data/dataset/DATASET/TEST/O/O_13346.jpg'),
 PosixPath('../input/waste-classification-data/dataset/DATASET/TEST/O/O_13446.jpg')]

(pathTest/’O’).ls() означает «пожалуйста, дайте мне файлы или папки по указанному пути», а numberOfFiles[:5] означает «пожалуйста, дайте мне первые 5 элементов в списке».

[:5] известен как нарезка, и больше информации об этой концепции можно прочитать в этой статье на pythonforbeginners.com.

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

Как получить данные

Имена папок «O» и «R» важны, потому что их можно назвать «метками». Глядя на эти ярлыки, вы можете узнать, какие папки содержат изображения какого типа отходов.

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

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

Помимо извлечения информации с этикетки, вам также необходимо сделать следующее →

  • Разделите данные на обучающий и проверочный наборы. Алгоритму машинного обучения требуется обучающий набор, на котором он может научиться классифицировать данные, а затем проверочный набор, на котором вы можете проверить, работает ли обученный алгоритм. ведет себя так, как ожидалось.
  • Преобразование данных. Если вы обучаете алгоритм машинного обучения только на похожих изображениях, он не сможет распознавать изображения, отличающиеся от исходных обучающих примеров, которые вы показывали ему во время цикла обучения. . Я также объяснял это в одной из моих предыдущих статей.
  • Преобразование данных в ImageDataBunch. ÏmageDataBunch — это объект Python, который сопоставляет ваши данные, выполняет две вышеуказанные операции, затем нормализует их, а затем загружает в графический процессор. Подробное объяснение находится здесь в официальной документации фастая.

Все эти вещи должны казаться вам ошеломляющими, но fastai предоставляет встроенные методы для всех этих вещей.

Посмотрите на приведенный ниже код, который выполняет все перечисленные выше действия в одной строке.

data = ImageDataBunch.from_folder(path, ds_tfms=get_transforms(), valid_pct=0.2, size=224).normalize(imagenet_stats)

В приведенном выше коде выполняет следующие действия →

  • Метод ImageDataBunch .from_folder() используется, чтобы сообщить fastai путь к данным.
  • get_transforms() переворачивает, поворачивает, обрезает данные.
  • ` – это процент обучающих данных, зарезервированных для проверки.
  • size – размер, в который конвертируются файлы изображений перед передачей в нейронную сеть
  • Наконец данные нормализуются с помощью normalize()

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

data.show_batch(rows=3, figsize=(7,6))

.classes позволяет вам просматривать классы, т. е. метки в вашем наборе данных.
.c позволяет вам просматривать количество классов.

print(data.classes)
len(data.classes),data.c
------
Output
------
['O', 'R']
(2, 2)

Время обучения

Посмотрим, что у вас есть на данный момент →

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

Теперь у вас есть все для обучения вашей нейронной сети.

Обучение нейронной сети включает в себя следующие шаги →

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

Это похоже на тонну кода, но fastai позволяет вам делать все это, используя одну строку кода, как указано ниже.

learn = cnn_learner(data, models.resnet34, metrics=error_rate)

cnn_learner() принимает на вход следующее →

  • data — это набор данных, созданный в предыдущих разделах
  • models.resnet34 — это предварительно обученная модель. Предобученная модель — это нейронная сеть, которая уже была обучена на аналогичных данных. Использование предварительно обученной модели известно как трансферное обучение, и оно значительно сокращает время обучения. Здесь — хорошая статья на сайтеwardsdatascience.com, в которой рассказывается о переносе обучения с использованием fastai.
  • metrics — После завершения обучения вам нужно будет оценить точность нейронной сети. «Метрика» поможет вам в этом.

После создания нейронной сети fit_one_cycle() запускает сеть через образцы изображений 4 раза. Это помогает сети узнать подробности об изображениях и пытается различать разные категории этих изображений. В данном случае это «О» и «Р».

learn.fit_one_cycle(4)

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

Наконец, сохраните свою модель, используя метод save().

learn.model_dir = "/kernel/output"
learn.save('stage-1', return_path=True)

Время результата

Класс ClassificationInterpretation в библиотеке fastai извлекает предсказанные изображения, сравнивает их с реальными изображениями и возвращает наиболее неправильные изображения.

Это изображения, которые вызвали недоумение в сети.

interp = ClassificationInterpretation.from_learner(learn)
losses,idxs = interp.top_losses()
len(data.valid_ds)==len(losses)==len(idxs)
interp.plot_top_losses(9, figsize=(15,11))
interp.plot_confusion_matrix(figsize=(12,12), dpi=60)
interp.most_confused(min_val=2)

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

plot_confusion_matrix() отображает матрицу прогнозов, где сеть допустила ошибку.

most_confused() дает количество классов, в которых сеть запуталась.

Потренируйся еще

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

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

Теперь попробуйте еще немного обучить модель и посмотрите, улучшит ли это точность. Для этого используйте метод `Unfreeze()`, который позволяет вам обучать основу сети.

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

learn.unfreeze()
learn.fit_one_cycle(1)

Сейчас потери значительно уменьшились. Теперь загрузите модель, используя .load(), а затем найдите скорость обучения, используя lr_find().

learn.load('stage-1');
learn.lr_find()
learn.recorder.plot()

`.recorder.plot()` отображает скорость обучения. График выше показывает скорость, с которой сеть учится уменьшать потери.

Обучите еще несколько слоев, сначала «разморозив», а затем подогнав два цикла обучения с помощью `fit_one_cycle()`. Здесь наибольшая скорость обучения между 1e-6 и 1e-4 пройдена, потому что именно тогда наклон графика скорости обучения начал становиться крутым в предыдущем разделе.

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

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

Сначала экспортируйте веса, метаданные и модель в папку на жестком диске, используя `.export()`. Это сохранит модель в виде файла с именем «export.pkl».

learn.path = Path("/kernel")
learn.export()

Ву Ху! Время предсказаний

Поздравляем! вы использовали магию фастая, чтобы успешно создать и обучить свою самую первую нейронную сеть. Теперь пришло время использовать модель.

Шаги, которые вам нужно выполнить для прогнозирования, выглядят следующим образом:

  • Для прогнозирования вам не нужен графический процессор. Так что попросите фастая не использовать gpu с этим кодом — torch.device(‘cpu’)
  • Используйте open_image(), чтобы выбрать любое изображение из папки «TEST».
  • Используйте load_learner(path) для загрузки сохраненной модели, убедитесь, что в пути существует файл «export.pkl».
  • Используйте predict(), чтобы сделать прогноз. predict() выводит три вещи: прогнозируемый класс, метку, к которой принадлежит класс, вероятность прогноза.
testImageList = ImageList.from_folder(pathTest/'O')
image = open_image(testImageList.items[0])
image

model = load_learner(learn.path)
className, label, probability = model.predict(image)
className, label, probability
-----
Output
-----
Category O, tensor(0), tensor([0.9983, 0.0017])

Вывод

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

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

Не стесняйтесь разветвлять и делиться записной книжкой для этого проекта, доступной на github, а ядро ​​kaggle доступно здесь.

Объявление

Я так рад сообщить, что мой первый курс глубокого обучения теперь доступен на Udemy. Курс доступен со скидкой 95% до полуночи 31 мая. Используйте эту ссылку, чтобы применить код скидки.