Обучение контрастному представлению — подробное руководство (часть 1, основы)

Оказывается, рассказывать вещи порознь — хороший способ понять мир.

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

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

Почему это так? Краткий список проблем, от которых страдают традиционные контролируемые модели глубокого обучения:

  1. Они предполагают, что классы, наблюдаемые во время обучения, представляют собой совокупность всех возможных классов элементов данных, поэтому они не адаптируются к просмотру совершенно новых классов данных (обобщение вне выборки).
  2. Им нужны огромные объемы существующих данных для изучения полезных представлений, что в лучшем случае утомительно, а в худшем невозможно — например, когда класс встречается редко в реальном мире (проблема эффективности выборки).
  3. Их нельзя легко переобучить на новых данных без снижения производительности существующих задач (катастрофическое забывание).
  4. Они не могут ничему научиться из огромного количества неразмеченных данных, которые создаются каждый день (проблема контроля).

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

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

Во многих отношениях приведенное выше определение неудовлетворительно. На самом деле это цель большинства глубокого обучения в целом — изучение хороших функций. Однако две части этого определения служат для точного отображения важных элементов области: обучение на основе какпомеченных, так и неразмеченных данных и изучение представлений, которые широко используются. Теорема о бесплатном обеде может тут же прийти на ум опытным читателям, но существует большая пропасть между тем, чтобы быть SOTA во всех возможных задачах и быть совершенным в одной за счет всех остальных. Эта пропасть может заключать в себе подмножество хороших результатов во «всех полезных задачах» с точки зрения нашей вселенной, и поэтому ее определенно стоит искать.

С другой стороны, контрастное обучение — это скорее методология обучения моделей машинного обучения (точнее его следует называть контрастным обучением), которое оказывается чрезвычайно полезным при изучении таких надежных представлений. Область исследования репрезентативного обучения в целом обширна, и в этой статье основное внимание будет уделено глубине, а не широте, с целью понять более узкую область контрастного репрезентативного обучения посредством внедрения и прикладных тематических исследований. Хорошей стороной этого является то, что некоторые из самых мощных методов обучения репрезентации представляют собой модели с контрастным обучением (SimCLR, MoCo, SimSiam и т. д.), поэтому этот метод имеет многообещающие перспективы в его нынешнем виде.

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

  • Неравные размеры партий
  • Индивидуальная стратегия выборки
  • Несколько проходов вперед
  • Ручное управление хранилищем тензоров CPU и GPU во время обучения
  • Пользовательские крючки для тензорной доски

Основное внимание будет уделено задачам компьютерного зрения, поэтому абсолютно необходим хороший графический процессор (4 ГБ+).

Оглавление:

  1. Контрастное обучение: предыстория
  2. Что такое сходство?
  3. Загрузчики данных и стратегия выборки
  4. Архитектура модели
  5. Написание контрастного тренажера
  6. Функции убытков и майнинг образцов
  7. Оценка моделей обучения представлению

Готовая версия всего кода в этой статье доступна в этом репозитории.

Контрастное обучение: предыстория

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

Контрастные модели и методы обучения имеют долгую и разнообразную историю в области машинного обучения. Один из первых примечательных примеров, хотя и не названный точным термином «контрастное обучение», был фактически опубликован в 1993 году и использовался для задачи проверки подписи. После этого интересующей задачей стала повторная идентификация человека, а затем, в более широком смысле, обучение за несколько или один раз на наборах данных, таких как Omniglot. Тем не менее, использование также существовало во встраивании текста, с модификациями word2vec, использующими одну из самых ранних форм истинной контрастной потери. Чтобы понять эти варианты использования, нам нужно сначала понять, что позволит вам делать такая модель. Подумайте о машине, которая может принять два элемента и получить оценку сходства:

О проверке подписи легко думать таким образом, если чек утверждает, что имеет подпись от определенного лица, мы можем поместить подпись чека в машину с известной подписью этого человека и посмотреть, как выглядит сходство. Для таких задач, как это, простое вычитание изображений не работает, и даже более сложные методы сравнения патчей, такие как *, страдают от огромного разнообразия контекстов, которые содержат естественные изображения. Преимущество использования моделей глубокого обучения для этой задачи заключается в мощности представления, они могут изучать пространства признаков, в которых представлены только самые отличительные части изображений, что позволяет лучше определить сходство. Использование моделей глубокого обучения для построения таких представлений называется обучением глубокому представлению или, в зависимости от вашей школы, глубоким метрическим обучением. Таким образом, для моделей глубокого обучения (а также для многих традиционных моделей машинного обучения) рабочий процесс выглядит примерно так:

Модель глубокого обучения M преобразует элементы входных данных в векторное пространство, в котором аналогичные примеры имеют схожие векторные представления, а разные примеры имеют разные векторные представления. S здесь может соответствовать одиночному скалярному произведению или косинусному сходству — ключ в том, что векторы, извлеченные с использованием модели глубокого обучения, выделяют атрибуты, которые делают объекты похожими (или непохожими).

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

Большинство читателей, знакомых с глубоким обучением, сразу же перейдут к функции потерь — как мы можем побудить модель формировать представления с этим свойством? Ответ на удивление прост (относительно, конечно):

Это одна из самых простых формулировок потерь для контрастного обучения. В приведенном выше уравнении функция индикации Sxy равна 1, если x и y подобны, и нулю в противном случае. Поэтому, когда примеры похожи, мы пытаемся минимизировать расстояние между ними, а когда они не похожи, мы пытаемся минимизировать их расстояние от поля. Но какая, к черту, маржа?

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

Нам также нужно быть более конкретными, когда мы говорим, что два элемента «похожи» или «несходны». Для изображений мы можем сказать, что два изображения X, Y похожи, если они содержат один и тот же объект, однако это требует такого же контроля, как и простая классификация изображений (мы можем просто собрать все похожие изображения вместе и восстановить группировку классов). Так что же хорошего в контрастных моделях в ситуации, когда сходство определяется (известным) содержанием изображения?

Что ж, в некоторых случаях (например, повторная идентификация человека) мы можем знать метку класса изображения (кто на изображении), но у нас гораздо больше классов, чем примеров на класс — у нас может быть только одно или два изображения из одного класса. человека, а несколько тысяч человек в нашей базе данных. Это приводит ко многим проблемам для традиционных классификаторов, которые пытаются предсказать идентичность человека по изображению, поскольку существует очень небольшая изменчивость внутри класса (ноль в случае одного изображения), чтобы изучить отличительные признаки для предсказания класса. из. Контрастные модели путем сравнения представляют собой функции обучения, помогающие различать классы, и поэтому могут учиться как минимум на (C-1) примерах с учетом C общих классов и изображения из определенного класса. Кроме того, во время тестирования могут присутствовать классы, которых мы не видели во время обучения, и традиционный классификатор должен был бы отнести их к одному из обучающих классов. Сравнивая, контрастивная модель может оценить попарное сходство между всеми тестируемыми примерами и обнаружить новые «кластеры» похожих изображений, которые будут соответствовать новым классам.

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

Что такое сходство?

Рассмотрим следующее: если вы сфотографируете свою кошку (которая у вас определенно есть, учитывая, что вы читаете эту статью) и используете программу редактирования изображений, чтобы отразить ее по центральной линии, изменится ли это содержание изображения?

Нет, вы все равно будете утверждать, что это изображение того же кота. Аналогично, если вы немного размыли изображение или обрезали границу. Такие операции сохраняют семантику или основное содержание изображения. Исходя из определения сходства большинства людей, исходное изображение и изображение с одним из этих преобразований, сохраняющих семантику, будут считаться «похожими». Обратите внимание, что мы здесь сделали? Мы смогли создать пару похожих изображений без необходимости явно помечать содержимое или пиксели изображения меткой.

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

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

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

Загрузчики данных и стратегия выборки

Мы создадим два загрузчика данных для нашего варианта использования: один для использования помеченных данных (т. и их класс неизвестен).

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

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

Это приводит к следующему набору данных Pytorch:

Этот набор данных выводит словарь, содержащий тензор BxCxHxW для «x1» — это якорные изображения, тензор BxCxHxW для «x2 — это аналогичные (в нашем случае того же класса) примеры для x1 и тензор Bx1 для «меток» — это основной класс истины пары.

Одна хитрость заключается в том, что мы будем создавать пакеты внутри самого набора данных, поэтому, если мы передаем это в конструктор DataLoader, нам нужно указать batch_size = None. Таким образом, мы можем гарантировать, что каждая партия содержит ровно одну пару из каждого класса, и помочь предотвратить дисбаланс из-за случайной выборки. Это на самом деле станет проще в случае неконтролируемого/самоконтролируемого, так как мы просто будем считать, что каждое изображение является своим собственным классом. На данный момент размер пакета зафиксирован на C, количество классов.

«Ярлыки» здесь просто для визуализации и оценки позже.

Мы сможем повторно использовать этот класс для создания контрастных пар для любого набора данных, который организован в папки по классам (например, формат «ImageFolder» от Pytorch).

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

Архитектура модели

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

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

from torchvision import models
EMB_SIZE = 2
embedding_net = models.resnet18()
embedding_net.conv1 = nn.Conv2d(1, 64, (7,7), (2,2), (3,3))
embedding_net.fc = nn.Linear(512, EMB_SIZE)
model = embedding_net
model.train(); print()

Обратите внимание, что в дополнение к изменению выходного размера полностью подключенной головы на желаемый размер наших вложений, мы также изменяем первый сверточный слой, чтобы получать изображения с 1 каналом вместо 3 каналов (это необходимо, поскольку изображения MNIST являются 1 каналом) . Здесь мы используем EMB_SIZE = 2, чтобы упростить визуализацию вложений, однако на практике обычно устанавливаются более высокие значения, такие как 128 или 256.

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

Обучение контрастной модели

У нас есть данные, и у нас есть модель, осталось только два элемента, пока мы не сможем начать обучение: тренер и функция потерь. Тренер реализует прямой и обратный проход по модели, обновляет параметры модели и регистрирует результаты. Мы начнем с создания скелета тренера с методом обучения одной итерации (прямой проход + расчет потерь + обратный проход) и методом обучения заданного количества эпох.

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

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

x1, x2 = input
out1 = model(x1); out2 = model(x2)

Далее нам нужно извлечь элементы по отдельности из data_dict в методе train(), чтобы отправить их на текущее устройство:

## Grab an example
x1 = data_dict["x1"]; x2 = data_dict["x2]
label = data_dict["label"]
## Send it to self.device
x1 = x1.to(self.device); x2 = x2.to(self.device)
label = label.to(self.device)
x = (x1,x2)

Наконец, функция потерь (которую мы скоро напишем) будет использовать оба выходных вложения для вычисления расстояния между ними. Мы можем изменить это в методе train_iter():

## Calculate the loss(es)
loss = self.loss_function(out1, out2)

Окончательный трейнер выглядит так:

Функции потерь и негативный майнинг

Это, вероятно, один из наиболее важных компонентов контрастных методов, наряду со стратегией аугментации/выборки данных. Прежде чем мы перейдем к более глубокому концу, мы начнем с простого Margin Loss — того же, что мы видели ранее в этом посте:

Потеря маржи начинается с двух примеров данных (x, y) вместе с меткой подобия (Sxy), которая равна 1, когда (x, y) похожи, и 0 в противном случае. Убедитесь, что вы понимаете, что означает минимизация этих потерь — поскольку D(x,y) рассчитывается сетью, потери минимизируются, когда D(x,y) мало, в то время как (Sxy) равно 1 (т. е. сеть таким же образом представляет известные подобные пары). И наоборот, чтобы сеть не представляла каждый пример одинаково (явление, известное как коллапс, которое мы обсудим позже), мы также заставляем модель представлять разные примеры по-разному, говоря, что они должны быть разделены по крайней мере краевым расстоянием M .

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

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

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

Хотя это и не самый быстрый способ, мы можем сделать это, повторяя каждый индекс A последовательно N раз и повторяя индекс B по пакету N раз — это формирует массив, в котором ни один из индексов не совпадает, и затем мы можем использовать его для индексации пакетов. в одну большую партию, то есть B*(B-1)xCxHxW — это все возможные похожие и непохожие пары вместе с вектором метки B*(B-1) для подобия.

def form_pairs(inA, inB):
    
    '''
    Form pairs from two tensors of embeddings. It is assumed that the embeddings at corresponding batch positions are similar
    and all other batch positions are dissimilar 
    
    i.e inA[i] ~ inB[i] and inA[i] !~ inB[j] for all i =! j
    '''
    
    b, emb_size = inA.shape
    perms = b**2
    
    labels = [0]*perms; sim_idxs = [(0 + i*b) + i for i in range(b)]
    for idx in sim_idxs:
        labels[idx] = 1
    labels = torch.Tensor(labels)
    
    return(inA.repeat(b, 1), torch.cat([inB[i,:].repeat(b,1) for i in range(b)]), labels.type(torch.LongTensor).to(inA.device))

В результате получится следующая схема:

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

Мы реализуем методы forward_triplets() и forward_ntxent() в следующих разделах.

Теперь, когда у нас есть загрузчик данных, модель, тренер и функция потерь, мы можем начать обучение! Мы будем использовать небольшое подмножество из 3000 примеров из более крупного обучающего набора MNIST (используя SubsetRandomSampler) и посмотрим, как выглядит наша динамика обучения. Затем мы воспользуемся несколькими невидимыми примерами, чтобы визуализировать пространство встраивания. Мы будем использовать размер встраивания 32 и использовать PCA, чтобы уменьшить их до 2 измерений для визуализации. Ниже приведен учебный блокнот, в котором реализованы все функции, описанные выше, для тренировки с потерей контрастной пары:

Вот график потерь при обучении для нашего подмножества из 2000 примеров для 10 эпох:

Вот результирующие 2-мерные проекции PCA 32-мерных вложений тестового набора (объяснено 45% дисперсии):

Приблизительно из 2700 примеров (90% из 3000) мы изучили встраивания, которые показывают большое разделение между цифрами. Давайте немного углубимся в математику, чтобы выяснить, сколько примеров было фактически сравнено. Во-первых, для дискриминационных моделей (где мы предсказываем цифры напрямую) у нас было бы примерно 2700/10 = 270 примеров на цифру для изучения представления. Для сравнительного обучения каждая партия содержала один похожий пример цифры и 9 непохожих пар, то есть 10 сравнений на партию. Учитывая 270 полных партий, это означает, что каждая цифра имела 2700 сравнений, чтобы узнать представление. Это в 10 раз больше примеров, на которых основывается представление цифры, по сравнению с дискриминационными методами.

Давайте углубимся в другие функции потерь, чтобы посмотреть, можем ли мы добиться еще большего успеха. Во-первых, обратите внимание, что с Margin Loss мы устанавливаем расстояние между похожими примерами равным 0. Поскольку наша стратегия выборки требует только одного похожего примера на партию, это не так уж плохо, но со стратегией выборки со сбалансированными похожими и непохожими примерами для каждого класса похожие примеры начнут объединяться в небольшие кластеры. Мы пытаемся кодировать похожие примеры, но относимся к ним так, как будто они должны быть одним и тем же примером! Это препятствует внутриклассовой дисперсии, и нам нужно дать модели возможность размещать похожие примеры близко друг к другу, не помещая их непосредственно друг над другом (все единицы). Один из способов обойти это (и проблему установки значения поля , что само по себе сложно) заключается в применении отдельного ограничения.Вместо того, чтобы сходное расстояние равнялось 0, а разное расстояние — пределу, мы можем применить более слабое ограничение, заключающееся в том, что одинаковые расстояния меньше разнородных расстояний в пакете.

Триплетная потеря использует это ограничение:

В этой формулировке A — это (встроенная) точка данных, P — другая (встроенная) точка данных, похожая на A, а N — другая (встроенная) точка данных, отличная от A. В правильном языке сравнительного обучения они известны как якорь, положительные и отрицательные примеры.

К счастью для нас, Triplet Loss уже доступен в виде модуля Pytorch. Все, что нам нужно сделать, это добавить функцию для формирования триплетов из нашего пакета:

def form_triplets(inA, inB):
        
    '''
    Form triplets from two tensors of embeddings. It is assumed that the embeddings at corresponding batch positions are similar
    and all other batch positions are dissimilar 
    
    i.e inA[i] ~ inB[i] and inA[i] !~ inB[j] for all i =! j
    '''
    
    b, emb_size = inA.shape
    perms = b**2
    
    labels = [0]*perms; sim_idxs = [(0 + i*b) + i for i in range(b)]
    for idx in sim_idxs:
        labels[idx] = 1
    labels = torch.Tensor(labels)
        
    labels = labels.type(torch.BoolTensor).to(inA.device)
    anchors = inA.repeat(b, 1)[~labels]
    negatives = torch.cat([inB[i,:].repeat(b,1) for i in range(b)])[~labels]
    positives = inB.repeat(b, 1)[~labels]
return(anchors, positives, negatives)

затем добавьте соответствующий форвардный метод в нашу функцию потерь:

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

Вот тренировка записной книжки с Triplet Loss:

Вот кривая потерь при обучении:

Вот результирующие 2-мерные проекции PCA 32-мерных вложений тестового набора (объяснено 56% дисперсии):

Мы можем сразу заметить, что каждый из отдельных кластеров теперь более «размазан» — хотя это не сразу выглядит хорошо, это позволяет модели быть более выразительной с разделением классов. Например, если наш набор данных включает кошек и собак, у нас могут быть изображения, содержащие человека или растение на заднем плане. Таким образом, изображение кошки с человеком на заднем плане должно быть ближе к изображению собаки с человеком на заднем плане, чем, скажем, изображение морды собаки. С Margin Loss все эти изображения будут равномерно разделены на плотные кластеры с маржевым расстоянием.

В этой части мы рассмотрим еще одну функцию потерь, потерю NT-Xent (или нормализованную температурную кросс-энтропию). Эта потеря была представлена ​​в популярной статье SimCLR и основана на потере нескольких классов N-пар (представленной в этой статье). Мы попытаемся понять эту потерю, выполнив несколько последовательных шагов. Во-первых, рассмотрим (для одного примера) общую потерю перекрестной энтропии для задач классификации:

Учитывая, что y является вектором меток истинности, а y - вектором прогнозируемой вероятности по классам, это по существу сводится к отрицательному логарифму прогнозируемой вероятности для нашего интересующего класса. Это значение уменьшается по мере того, как значение yhat становится равным 1, и наоборот — потери минимизируются, когда мы предсказываем интересующий нас класс с вероятностью 1, и максимизируются, когда мы предсказываем неправильный класс с вероятностью 1.

Теперь для триплета a, p, n мультиклассовая потеря N-пары может быть записана (с использованием некоторой алгебры) как:

где ‹x, y› обозначает скалярный продукт. Обратите внимание, что, как и в случае с Triplet Loss, знаменатель будет увеличиваться по мере увеличения расстояния между вложением с положительной и отрицательной привязкой. Мы можем рассматривать расстояния аналогично вероятности потери перекрестной энтропии — мы хотели бы разделить непохожие примеры с наибольшим расстоянием. Приложив немного алгебры, мы можем переписать это следующим образом:

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

Для более подробного объяснения потери NT-Xent ознакомьтесь со следующими руководствами здесь, здесь и здесь. Реализация здесь сильно заимствует из последней ссылки.

Наша финальная функция потерь с интегрированными парами, триплетами и NT-Xent выглядит следующим образом:

и тренировочный блокнот по потере NT-Xent:

Прогресс тренировочного проигрыша:

Вот результирующие 2-мерные проекции PCA 32-мерных вложений тестового набора (объяснено 35% дисперсии):

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

Полученные вложения выглядят следующим образом и имеют самый высокий процент дисперсии, объясненный PCA: 80% — это говорит о том, что большое количество из 32 признаков коллинеарны. Мы рассмотрим этот момент подробнее в следующем разделе.

Эффекты различных функций потерь

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

Что тут происходит? Кажется, что потеря триплетов лучше всего визуально разделяет классы, но это далеко не все. Например, легко забыть, что это 2-мерные проекты 32-мерных точек, и поэтому они подвержены потере информации из-за любого используемого метода уменьшения размерности, которым в нашем случае является PCA. Ниже приводится объяснение дисперсии PCA для каждого метода:

  • Контрастные пары: 45%
  • Контрастные тройняшки: 56%
  • НТ-Зент: 35%
  • Кросс-энтропия: 80%

Представления, которые мы получаем из Triplet Loss, кажутся более подходящими для редукции с помощью PCA (по сравнению с другими контрастными потерями), что может объяснить некоторые из хороших графиков, которые мы получаем. Представления из Contrastive Pairs и NT-Xent могли бы содержать больше информации и лучше декоррелироваться в функциях, что сделало бы этот график плохим для использования в одиночку для оценки качества представления. Кроме того, есть много других вопросов, на которые эти графики не отвечают:

Какой из них лучше всего подходит для последующих задач? Генерирует ли одна из этих функций потерь пространство вложения, которое линейно разделимо в классах? Близки ли одни и те же классы в каждом из этих пространств вложений (ближайшие соседи) или места рандомизированы? Имеют ли внутриклассовые размещения семантический смысл?

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

  1. Кластерный анализ [коэффициент силуэта, индекс Рэнда, взаимная информация]
  2. Снижение размерности [PCA, T-SNE]
  3. Линейная классификация [Линейный датчик]

Измерение качества пространства для встраивания в значительной степени будет темой следующей части этой серии. Как только мы поймем, как измерять производительность, мы перейдем к более сложным темам, таким как обучение с полным самоконтролем (SimCLR, MoCo, BYOL и т. д.), эффект дополнений, интеллектуальный анализ с жесткими отрицательными значениями и декоррелирование векторов признаков. Следите за обновлениями!