Узнайте, как создать свою собственную полууправляемую модель с нуля в PyTorch

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

В этом руководстве:

  • Вы узнаете, что такое обучение с учителем, без учителя, частично и без учителя.
  • Пройдите пошагово по коду PyTorch для BYOL - полу-контролируемого метода обучения, который вы можете реализовать и запустить самостоятельно в Google Colab - ни облако, ни графический процессор не требуется!
  • Вы изучите основную теорию BYOL - метода обучения с полу-контролируемым обучением.

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

Что такое полу-контролируемое обучение и зачем оно нам?

В целом методы машинного обучения можно разделить на три категории:

  • контролируемое обучение
  • обучение без учителя
  • обучение с подкреплением

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

При контролируемом обучении наши данные состоят из помеченных объектов. Задача модели машинного обучения состоит в том, чтобы научиться назначать метки (или значения) объектам.

Примеры:
1) В больнице есть показания ЭКГ, которые помечены кодом ICD-10. На основе показаний ЭКГ мы хотим автоматически поставить предварительный диагноз пациенту.
2) У банка есть данные о кредиторах - их финансовое положение, сколько они владеют, платят ли они вовремя и т. Д. Банк хочет оценить, сколько еще деньги они могут кому-то одолжить.

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

Пример: мы можем поручить компьютеру кластеризовать изображения по 10 категориям, не уточняя, что означают эти категории (k-означает кластеризацию).

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

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

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

Пример. Предположим, у нас есть большой набор данных с изображениями без пометки. Мы хотим научиться извлекать из этих изображений некоторые полезные функции, которые могут помочь нам в других задачах (например, распознавание кошек / собак). Мы произвольно применяем 9 различных искажений к изображениям (или не искажаем их, поэтому существует 10 вариантов). Затем мы поручаем модели определить, какое искажение (если таковое имеется) было применено. Мы надеемся, что эта модель научится извлекать особи, которые затем можно будет повторно использовать в другом месте (например, для распознавания кошек / собак).

STL-10 - эталонный набор данных для полу-контролируемого обучения

Прежде чем мы перейдем к методам, давайте посмотрим на набор данных, который мы будем использовать. Набор данных STL-10 был создан исследователями из Стэнфордского университета и вдохновлен CIFAR-10, о котором вы, возможно, слышали. STL-10 состоит из 100 000 изображений без меток, 5 000 изображений с метками для обучения и 8 000 изображений для тестирования. Изображения равномерно распределены по десяти классам.

Откройте Google Colab и создайте новый ноутбук со средой GPU. Во-первых, для удобства смонтируйте Google Диск. STL-10 довольно тяжелый, и повторная загрузка его каждый раз при запуске среды может быть неудобной. Запустите приведенный ниже код в ячейку и следуйте инструкциям.

Затем создайте папку для набора данных STL-10.

Загрузите набор данных STL-10. Как видите, здесь мы также определяем трансформацию. Мы делаем это потому, что по умолчанию все изображения являются объектами изображений PIL, что не очень удобно для нейронных сетей. Поэтому мы преобразуем их в тензоры.

Мы также должны определить DataLoaders для этих наборов данных. Попробуйте сделать это сами! Заполните недостающие части кода.

Здорово! Как видите, размер пакета установлен на 128 - это значение было получено мной экспериментально как значение, которое не вызывает сбоев в среде Google Colab, но вы можете свободно экспериментировать.

Получите контролируемый базовый уровень

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

Загрузите свой собственный скрытый

Bootstrap your own latent (BYOL) - это самоконтролируемый метод репрезентативного обучения, который был впервые опубликован в январе 2020 года, а затем представлен на ведущей научной конференции - NeroNIPS 2020. Мы реализуем этот метод.

Грубый обзор

У BYOL есть две сети - онлайн и целевая. Они учатся друг у друга. Мы берем изображение и выполняем на нем два разных увеличения (t и t ’). Одно расширенное изображение (v) помещается в онлайн-сеть, а второе расширенное изображение (v ’) передается в целевую сеть.

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

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

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

Онлайн-сеть учится «быстро» у целевой сети, а целевая сеть «учится» у онлайн-сети. Онлайн-сеть старается быть как можно ближе к выходу целевой сети.

Интуиция, лежащая в основе этого механизма, заключается в том, что выходные данные этих двух сетей должны быть похожими - обе они получают одни и те же изображения, но с разными дополнениями. Если у нас есть изображение кошки, независимо от того, как мы его предварительно обрабатываем (в некоторой разумной степени), это все равно фотография кошки. Онлайн-сеть изучает проекцию целевой сети для тех же объектов, но с разной «экспозицией» на изображении.

В самом конце часть онлайн-сети (кодировщик, ) будет извлечена и использована для контролируемого обучения.

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

Контрастное обучение

Также стоит отметить, что эта архитектура является примером контрастного обучения. Контрастное обучение - это метод, с помощью которого мы пытаемся получить представления (вложения) похожих объектов как можно более похожими, но представления различных изображений как можно более разными. Вы можете узнать больше в этом посте на Medium. Существенное отличие BYOL в том, что этот метод не имеет отрицательных пар. Благодаря этому усовершенствованию он стал легче для вычислений и, следовательно, может быть продемонстрирован в бесплатной среде Google Colab.



Аугментации

Как упоминалось ранее, на изображение выполняются два разных увеличения. Чтобы быть более конкретным, мы пробуем два преобразования из двух разных распределений t ~ Τ и t ’~ Τ’. Статья, опубликованная в протоколах NIPS, не развивает эти дополнения, но препринт, опубликованный на arXiv, делает.

Если вы хотите быть в курсе самых современных методов, вы должны уметь читать научные статьи. Поэтому я рекомендую вам взглянуть на Раздел B (стр. 16–17) предпечатной версии и реализовать недостающий код функций. Некоторые значения не взяты из статьи в связи с отсутствием информации. Документация для torchvision.transforms должна быть полезной.

Каркас архитектуры BYOL

Давайте снова посмотрим на рисунок 1.

Итак, у нас есть изображения (набор данных STL-10) и дополнения. А как насчет остальных? Кодировщиком (f) может быть любая сеть, которая преобразует данные изображения в функции (представление), например, resnet18. Проекция (g) отвечает за создание меньших представлений из выходных данных сети представления (кодировщика). Слой предсказания делает псевдопрогнозы на основе проекций.

Обратите внимание, что эта архитектура асимметрична. Авторы предполагают, что это предотвращает свертывание решений (например, вывод одного и того же вектора для каждого изображения даст MSE = 0). Следовательно, слой прогнозирования должен иметь одинаковые входные и выходные размеры, чтобы вычислять MSE между выходными данными целевой сети проекции и сетью онлайн-прогнозирования.

Реализация проектора

Как видно выше, BYOL.mlp должен возвращать проектор и предсказатель. Тогда давай сделаем это. Предварительная печать в разделе 3.3 Подробности реализации гласит:

[…] Представление y проецируется в меньшее пространство многослойным персептроном (MLP) gθ, и аналогично для целевой проекции gξ. Этот MLP состоит из линейного слоя с размером вывода 4096, за которым следует пакетная нормализация, выпрямленные линейные единицы (ReLU) и последний линейный слой с размером вывода 256.

Это означает:

Модель примерки

Мы разделим модель подбора для немаркированных данных на четыре этапа:

  • Обучить (подогнать) модель на немаркированных данных
  • Подтвердить на данных о поездах без ярлыков
  • Подтвердить данные проверки (метки будут опущены)
  • Распечатать результаты

Все вышеперечисленные шаги будут повторены epochs раз.

Прямое и обратное распространение

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

Затем нам нужно перебрать пакеты, возвращаемые DataLoader, и поместить их в GPU.

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

Мы запускаем обратное распространение тензора потерь…

… И обновить параметры целевой сети.

Перейдем к методу forward. Во-первых, нам нужно дополнить изображения двумя разными функциями увеличения. Мы используем torch.no_grad(), поскольку не хотим выполнять обратное распространение через эти преобразования. Два изображения с различными расширениями сохраняются в переменных v и v_prime.

Изображение v передается в онлайн-сеть, которая возвращает псевдопрогноз. Обратите внимание, что мы не используем здесь torch.no_grad(), так как мы будем выполнять обратный проход по этой сети. Изображение v_prime передается в целевую сеть с torch.no_grad(). Оба выхода normalize d и…

… И на этих выходных данных рассчитывается среднеквадратичная ошибка (или, скорее, квадратная ошибка суммы, поскольку мы устанавливаем sum уменьшение __init__).

В документе также говорится, что:

Мы симметризуем потери […], отдельно передавая v 'в онлайн-сеть и v в целевую сеть для вычисления [потери].

В приведенном ниже коде представлена ​​эта симметричная потеря.

Теперь осталось обновить целевую сеть. Помните self.tau, определенный в __init__? Это параметр распада. Параметры ξ целевой сети обновляются на i -м шаге с параметрами θ онлайн-сети:

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

И это последний код для класса BYOL, который также включает процесс проверки и код для запуска обучения. Мы будем проводить обучение с самоконтролем только в течение одной эпохи, поскольку обычно это занимает один час в Google Colab. Вы можете изменить train_loss = self.validate(train_dl) на train_loss = 0, чтобы сократить время.

Последний уровень resnet18 заменяется слоем Identity - с этим мы получим функции, извлеченные этой сетью, вместо прогнозов для 1000 классов.

Полу-контролируемое обучение

А теперь давайте объединим обучение с учителем с обучением с учителем. Прежде всего, мы извлекаем онлайн-кодировщик () из класса BYOL и создаем копию. Поскольку мы хотим предсказать десять классов, мы заменим последний слой Identity на Linear. Если вы собираетесь заморозить кодирующую часть сети, вы можете сделать это, раскомментировав код.

Результаты

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

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

Выводы

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

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

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