Всем привет, я бы хотел вам кое‑что рассказать. Когда я однажды наткнулся на тему, связанную с self‑supervised learning, меня удивила мысль о том, что для обучения нейросети, оказывается, не совсем обязательная разметка. Удивительная идея, которая, как кажется на первый взгляд, ломает все, что я знал об обучении нейросетей.
Сегодня я бы хотел углубиться в эту тему и рассказать про методы обучения таких моделей. Статья будет полезна для тех, кто уже знаком с нейросетями и хочет узнать, как можно их обучать без разметки. Сегодня мы пройдемся по таким темам:
И ответить на главный вопрос: «А чему учить, если ты сам ничего не знаешь?»
В конце статьи я приложил ссылку на Colab ноутбук с реализацией каждого метода, примерами работы и парой вещей, не упомянутых тут.
Немножко теории
Эту часть я оформлю в небольшой справочник для создания академического налета и чтобы было удобно освежить знания.
Эмбеддинг — представление некого объекта (изображения, текста и тому подобное) в виде вектора в многомерном пространстве. В идеальном случае, эмбеддинги похожих объектов лежат очень близко, а непохожих — далеко.
Self‑supervised обучение — обучение, при котором у модели (а иногда и у нас) отсутствует какая‑либо разметка данных, в таком случае, основная цель модели — с��здание информативных представлений (эмбеддингов) для объектов.
Cosine similarity — она же косинусная схожесть. Метрика, показывающая схожесть направлений векторов. Находится в пределах [-1; 1], где:
1 — Полное сходство(вектора направлены в одном направлении)
0 — Вектора перпендикулярны
-1 — Вектора противоположны по направлению
Contrastive learning или "Свой, среди чужих".
Якоря, моря и Triplet Loss.
Triplet Loss — является одним из ранних и достаточно простых способов обучения представлений, но к self‑supervised обучению он не относится, потому что для его использования все‑таки необходима разметка данных.
Triplet loss основан на тройках примеров из данных:
Якорь (Anchor) — тот, с кем мы сравниваем (своего рода главный)
Positive — Объект того же класса, что и якорь (мы должны быть с ним близки)
Negative — Тот, от кого мы должны быть подальше.
В этих тройках и кроется наша функция и, по‑совместительству, задача модели:
Сделай так, чтобы якорь и позитивный пример были как можно ближе, а негативный — как можно дальше

Страшно? Сейчас все поясню.
— евклидово расстояние от якоря до позитивного примера.
— расстояние от якоря до негативного примера.
— абстрактный минимальный отступ между позитивным и негативным примерами(его так же называют margin).
Triplet loss равен 0 тогда, когда расстояния от якоря до негатива больше, чем расстояние до позитива, то есть
А отступ там откуда взялся? Зачем он тут?
Скажу честно, этот вопрос я задал себе, когда впервые увидел эту функцию, чтобы на него ответить представим, что отступ нам приснился и его нет, тогда, кажется, что и так все круто, но давайте попробуем «сжульничать» и найти способ всегда получать 0.
Если попробовать подобрать числа, то мы выйдем на то, что если оба расстояния будут 0, то и функция будет давать 0. А ч��о это значит? Значит все 3 эмбеддинга находятся в одной точке, что нас категорически не устраивает, но функция показывает 0, получается, мы выполнили задачу минимизации функции, схитрив.
И именно так и поступает нейросеть при обучении, она понимает, что ей проще сместить все эмбеддинги в 1 точку, вместо обучения правильных представлений. Такое явление называется коллапсом эмбеддингов и он является одной из главных проблем в контрастном self‑supervised обучении.
Небольшое дополнение
Выше я упоминал, что Triplet loss — чисто supervised метод, но, на самом деле, существуют его адаптации, не требующие разметки, в них берутся 2 аугментации(якорь и позитив) какого‑то элемента и аугментация другого случайного элемента из набора данных.
Как найти своего среди чужих? NT-Xent Loss
Собственно, разметки нет от слова совсем. Вариантов у нас тут немного. Единственное, что мы знаем наверняка — элемент n похож на элемент n, как бы это странно не звучало. И да, такой информации вполне достаточно(почти). Так как мы имеем в распоряжении единственный верный позитивный пример, то единственный наш вариант — аугментации, то есть видоизменения оригинала с целью получения «соседа», а именно — второго позитивного примера(на практике делают 2 аугментации оригинала, сам оригинал при обучении не используют).
Как нам заставить модель учиться? Для этого надо поставить задачу немного иначе:
Создай такие эмбеддинги, чтобы вероятность найти для первой аугментации(якоря в каком‑то смысле) его «соседа», то есть вторую аугментацию среди всех эмбеддингов была максимальной.

Такая логика задается вот такой пугающей, на первый взгляд, формулой:
Что тут происходит? Сначала разберем кто тут кто.
— косинусная схожесть 2 эмбеддингов
— функция экспоненты
— параметр, называемый температурой
Теперь по порядку.
— Получаем некое число, показывающее схожесть 2 аугментаций исходного объекта, чтобы его вычислить мы считаем схожесть и делим ее на
— параметр, регулирующий то, насколько сильно модель должна быть уверена в 2ом соседе, чтобы получить низкий лосс. Чем температура выше, тем проще ей получить низкий лосс и тем более «халатно» она будет работать, но если
сделать низким, модель начнет запоминать шум в данных, а не обобщать их, поэтому нужно что‑то среднее (обычно ставят 0.1). Прогоняем схожесть через экспоненту и получаем ее уже в виде некого числа.
N — число примеров в батче. Почему 2N? — потому что у нас для каждого примера 2 аугментации(2 позитива).
— Считаем по аналогии схожесть якоря с всеми
остальными эмбеддингами (включая 2ю аугментацию, но не включая самого себя), получаем своего рода числовой аналог схожести якоря с всеми эмбеддингами в батче.
— Т.к. дробь всегда будет < 1, то с помощью логарифма мы приводим вероятность в функцию, которую уже можно минимизировать (при уменьшении логарифма вероятность будет наоборот увеличиваться)
Важное замечание — суммирование в знаменателе происходит не по всем примерам, а только по батчу, поэтому эффективность оригинального метода очень зависела от размера батча, но на данный момент существуют способы обойти требование большого батча и использовать маленький батч.
Self-prediction, или же: "Угадай, что спрятано"
Рассмотрим второй вариант того, как можно заставить модель создавать устойчивые и богатые информацией признаки изображения или текста. Тут у нас тоже нету никаких меток и единственный верный вариант — мы сами.
Подход self‑prediction несколько иной. Вместо того, чтобы учить модель «искать своего среди чужих» мы научим ее восстанавливать потерянную часть объекта. Логика проста — если мы сможем по какой‑то части, например, изображения понять что на ней изображено и восстановить, то тогда мы понимаем что в целом находится на изображении.
Цель: взять объект, намеренно убрать случайную часть и после научить модель восстанавливать потерянный кусочек
Рассмотрим пример self‑supervised обучения для создания текстовых эмбеддингов (подобие BERT):

Общей формулы так таковой тут нет, потому что для каждой модальности и модели она разные, но задача для всех моделей одинакова — восстановленная часть должна быть максимально близка к оригиналу. В Colab ноутбуке вы можете посмотреть пример реализации self‑prediction метода для изображений.
Важное архитектурное замечание: для получения эмбеддингов обычно берут выход одного из последних скрытых слоев.
Что же по итогу?
В заключении я бы хотел добавить, что описанные тут методы являются уже скорее устаревающими, но все еще активно используются. Я не стал включать сюда разбор таких способов, как DINO, который сейчас является SOTA в мире self‑supervised learning, но он ближе к скорее развитию названных технологий, возможно, я когда‑то сделаю подробный разбор этой идеи, потому что она полна идей и интересных решений.
А все‑таки — чему учить модель, если мы ничего не знаем?
Ответ прост — мы можем научить модель не выдавать определенный результат при некоторых входных данных, а понимать данные. И, как показывает практика, даже для supervised обучения, где уже есть разметка претрейн модели self‑supervised методом дает улучшение результатов и ускорение обучения.
В остальном, надеюсь статья была полезна и интересна, она для меня первая, поэтому я открыт к конструктивной критике и дополнениям.
Ссылка на ноутбук с кодом и демонстрацией работы каждого описанного метода — Google Colab
Всем пока и, надеюсь, до встречи :-)
