Создание проекта глубокого обучения от идеи до производства

О работе, связанной с этим курсом

Работа основана на черновике фастбука Глубокое обучение программистов с fastai и PyTorch и fastai course-v4.

👉Читать главу 1 здесь.

📜Неписаные правила практики глубокого обучения

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

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

👉Никогда не переоценивайте ограничения и недооценивайте возможности глубокого обучения
Если вы переоцениваете ограничения, такие как доступность данных, постановка проблемы и т. д., тогда вы можете не применять глубокое обучение к своей проблеме. Главное — попробовать.

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

Как начать свой проект, с чего начать и как получить данные

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

Я слышу это много.
👉«Какой проект найти, чтобы я мог практиковать машинное обучение».
👉 «В моем проекте/продукте нет возможности реализовать машинное обучение».
👉 «У меня есть идея внедрить машинное обучение в свой продукт/работу, но у меня недостаточно данных».

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

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

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

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

Трансмиссия 🚂 Подход

В 2012 году Джереми Ховард вместе с Маргит Цвемер и Майком Лукидесом представили метод под названием Drivetrain Approach.

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

Итак, каков подход к трансмиссии? Будет лучше, если мы это представим.

Ниже перечислены компоненты этого подхода. папки.

👉Какие входные данные мы можем контролировать— В моем случае это будет «отличить мои фотографии от фотографий моей дочери».

👉Какие данные мы можем собирать — В моем случае это могут быть разные изображения WhatsApp, которые у меня есть, или фотографии Google, которые у меня есть.

👉Модели — Это последний шаг. Какие данные у нас есть и какие данные мы можем собрать, определяет, какую модель мы можем построить и как она будет работать. Наконец, эти модели можно объединить, чтобы получить нужный нам окончательный результат.

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

Теперь в следующих разделах мы объединим эти принципы в код.

Начнем🚴

Сначала мы сделаем некоторые общие настройки.

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

Из-за этого мне пришлось сделать следующее обходное решение.

Установите cuda версии 10.1, а затем установите дополнительные пакеты.

!pip install torch==1.6.0+cu101 torchvision==0.7.0+cu101 -f https://download.pytorch.org/whl/torch_stable.html

Сбор данных📓

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

Проект, которым мы сейчас займемся, — это детектор «Вафли» и «Мороженое». Эта система поможет нам определить, какой продукт является вафлей, а какой — мороженым.

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

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

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

Идем дальше🚴‍♂️

Вы также можете увидеть, какой тип файла есть в вашем наборе данных, используя это👇

В kaggle входной каталог, в котором хранятся ваши данные, называется «../input».

path=Path("../input")
files = get_image_files(path)
files

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

Вы заметили что-то другое в выводе выше? Список, который мы получили, также отображает количество элементов в списке. Это связано с тем, что этот «список» — не обычный список Python, а специальный class L внутри fastai, который дает обычному списку Python некоторые сверхспособности.

С классом L можно сделать что-то подобное👇

files[1,2]

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

Хорошо, давайте двигаться дальше.

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

Как мне это сделать?

Позвольте мне взять образец из результатов get_image_files().

files[1]

Обратите внимание, что родительская папка этого файла изображения имеет имя «мороженое». Это наш святой Грааль. Это то, что говорит нам, какое изображение является чем, и все, что нам нужно сделать, это взять имя этой родительской папки и указать fastai использовать его в качестве метки для нашей модели.

Функция parent_label в фасте делает именно это.

parent_label(files[1])

Видите, как это было легко.

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

В fastai есть много функций, которые помогают нам разделить данные на тестовые и обучающие наборы. Один из них — RandomSplitter(valid_pct=0.2, seed=42). Здесь «valid_pct» — это процент данных, которые мы хотим сохранить в качестве проверочного набора, а остальные будут сохранены для обучения. На данный момент забудьте о «seed», мы вернемся к этому в следующих главах.

Еще одна вещь, которую следует помнить, это то, что нейронные сети не работают, когда изображения имеют разный размер. Об этом позаботится Resize(128) . Он изменяет размеры всех изображений в квадратную форму заданного вами размера. Здесь я использовал 128*128.

Собираем все вместе

Теперь нам не нужно делать все вышеперечисленные шаги вручную. Можем положить в сумку и отдать в фастай для работы. Этот «мешок» известен как Datablock .

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

desserts = DataBlock(
    blocks=(ImageBlock, CategoryBlock), 
    get_items=get_image_files, 
    splitter=RandomSplitter(valid_pct=0.2, seed=42),
    get_y=parent_label,
    item_tfms=Resize(128))

Как использовать блок данных?🤔

Блок данных, который мы создали выше, — это просто сумка. Это скорее шаблон, который сообщает fastai, какие шаги нужно выполнить.

Эти шаги оживают, когда мы подключаем что-то, известное как «Загрузчик данных». Этот «загрузчик данных» следует шаблону (блоку данных) для загрузки данных, разбивает их на небольшие наборы, известные как пакеты, и передает их графическому процессору.

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

dataloader = desserts.dataloaders(path)

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

dataloader.valid.show_batch(max_n=4, nrows=1)

Вы заметили, что все изображения имеют одинаковый размер?

Вы помните код item_tfms=Resize(128), который мы ранее поместили в блок данных? Это позаботится об изменении размера всех изображений до 128 * 128 квадратных форм.

Почему квадратная форма? Что ж! он работает достаточно хорошо.

Есть еще одна важная вещь, которую мы еще не сделали.

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

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

Это известно как увеличение данных.

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

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

desserts=desserts.new(item_tfms=RandomResizedCrop(128,min_scale=0.3),batch_tfms=aug_transforms())

Вы заметили ключевое слово min_scale внутри RandomResizedCrop? это сообщает fastai, какая часть изображения должна быть выбрана для обрезки. Еще одна вещь, на которую стоит обратить внимание, это ключевое слово batch_tfms. Это говорит fastai применить aug_transforms ко всей партии.

С их помощью мы снова определяем наш загрузчик данных.

dataloader = desserts.dataloaders(path)

dataloader.valid.show_batch(max_n=4, nrows=1)

Смотреть! как изображения меняются сейчас из-за сделанных на них аугментаций.

Время тренироваться🤩

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

Следующие две строчки помогут нам в этом. Как и в предыдущей главе, мы будем использовать fine_tune, поскольку здесь мы используем предварительно обученную модель.

learn = cnn_learner(dataloader, resnet18, metrics=error_rate)
learn.fine_tune(4)

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

Мы можем проверить, где наша модель запуталась, с помощью следующего кода.

interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix()

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

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

interp.plot_top_losses(4, nrows=4)

Чем выше число в разделе «вероятность», тем менее уверенной была модель.

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

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

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

Есть много способов сделать это, но есть ли способ проще?

Это именно то, что мы собираемся исследовать в Главе 3.

Кстати для приквела к этой истории читайте Глава 1

Как показать свою поддержку публикации🤗

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

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

  • Если вам нравится моя работа, нажмите на эту ссылку, чтобы купить мне кофе.
  • Купите мой курс глубокого обучения в udemy. Просто нажмите на ссылку курса в примечаниях к шоу и получите потрясающую скидку на мой курс глубокого обучения.
  • Подпишитесь на мою публикацию и поделитесь ею, чтобы о ней узнало больше людей.
  • Подпишитесь и поделитесь моим подкастом SimpleAI в Google podcast или любом другом проигрывателе подкастов по вашему выбору. Не забудьте поставить ему 5 звезд.
  • Подпишитесь на мою информационную рассылку.