Реализация мягкой потери ближайшего соседа в PyTorch

Использование алгоритма мягкой потери ближайшего соседа в PyTorch

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

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

Обучение представлений – это задача обучения глубокой нейронной сети наиболее важным признакам в заданном наборе данных. Это обычно неявная задача, выполняемая в рамках обучения с учителем, и является ключевым фактором успеха глубокого обучения (Krizhevsky et al., 2012; He et al., 2016; Simonyan et al., 2014). Другими словами, обучение представлений автоматизирует процесс извлечения признаков. С помощью этого мы можем использовать изученные представления для последующих задач, таких как классификация, регрессия и синтез.

Рисунок 1. Иллюстрация из SNNL (Frosst et al., 2019). Посредством минимизации потери мягкого ближайшего соседа минимизируются расстояния между точками данных, похожими на класс (как показано цветом), в то время как расстояния между точками данных, принадлежащими разным классам, увеличиваются.

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

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

Для интеграции структуры окрестности в представления были предложены методы изучения многообразия, такие как локальные линейные вложения или LLE (Roweis & Saul, 2000), анализ компонент окрестности или NCA (Hinton et al., 2004) и t-стохастическое вложение соседей или t-SNE (Maaten & Hinton, 2008).

Однако упомянутые выше методы изучения многообразия имеют свои недостатки. Например, LLE и NCA кодируют линейные вложения вместо нелинейных. В то же время вложения t-SNE дают различные структуры в зависимости от используемых гиперпараметров.

Чтобы избежать таких недостатков, мы можем использовать улучшенный алгоритм NCA, который называется мягкой потерей ближайшего соседа или SNNL (Salakhutdinov & Hinton, 2007; Frosst et al., 2019). SNNL улучшает алгоритм NCA, вводя нелинейность, и он вычисляется для каждого скрытого слоя нейронной сети, а не только для последнего кодирующего слоя. Эта функция потери используется для оптимизации взаимного расположения точек в наборе данных.

В этом контексте запутанность определяется как то, насколько близки друг к другу данные точки класса по сравнению с данными точками разных классов. Низкая запутанность означает, что данные точки класса, похожие друг на друга, намного ближе друг к другу, чем данные точки разных классов (см. Рисунок 1). Иметь такой набор данных значительно облегчит выполнение последующих задач с еще более высокой производительностью. Frosst et al. (2019) расширили цель SNNL, введя температурный коэффициент T. Таким образом, у нас есть следующая конечная функция потерь,

Рисунок 2. Функция потерь мягкого ближайшего соседа. Рисунок автора.

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

Рисунок 3. Формула косинусного расстояния. Рисунок автора.

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

Метрика расстояния

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

Рисунок 4. Первый шаг в вычислении SNNL - вычисление метрики расстояния для точек входных данных. Рисунок автора.

Для нашей реализации мы используем косинусную метрику расстояния (Рисунок 3) для более стабильных вычислений. На данный момент давайте игнорировать указанные подмножества ij и ik на рисунке выше и просто сосредоточимся на вычислении косинусного расстояния между нашими точками входных данных. Мы выполняем это с помощью следующего кода PyTorch:

normalized_a = torch.nn.functional.normalize(features, dim=1, p=2)normalized_b = torch.nn.functional.normalize(features, dim=1, p=2)normalized_b = torch.conj(normalized_b).Tproduct = torch.matmul(normalized_a, normalized_b)distance_matrix = torch.sub(torch.tensor(1.0), product)

В приведенном выше отрывке кода мы сначала нормализуем исходные признаки ввода в строках 1 и 2, используя евклидову норму. Затем в строке 3 мы получаем сопряженно-транспонированное значение второго набора нормализованных признаков ввода. Мы вычисляем сопряженно-транспонированное значение для учета комплексных векторов. В строках 4 и 5 мы вычисляем косинусную похожесть и расстояние между признаками ввода.

Конкретно рассмотрим следующий набор признаков:

tensor([[ 1.0999, -0.9438,  0.7996, -0.4247],        [ 1.2150, -0.2953,  0.0417, -1.2913],        [ 1.3218,  0.4214, -0.1541,  0.0961],        [-0.7253,  1.1685, -0.1070,  1.3683]])

Используя определенную выше метрику расстояния, мы получаем следующую матрицу расстояний:

tensor([[ 0.0000e+00,  2.8502e-01,  6.2687e-01,  1.7732e+00],        [ 2.8502e-01,  0.0000e+00,  4.6293e-01,  1.8581e+00],        [ 6.2687e-01,  4.6293e-01, -1.1921e-07,  1.1171e+00],        [ 1.7732e+00,  1.8581e+00,  1.1171e+00, -1.1921e-07]])

Вероятность выборки

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

Рисунок 5. Второй шаг - вычисление вероятности выборки точек на основе их расстояний. Рисунок автора.

Мы можем вычислить это с помощью следующего кода:

pairwise_distance_matrix = torch.exp(    -(distance_matrix / temperature)) - torch.eye(features.shape[0]).to(model.device)

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

Перед вычитанием torch.eye(features.shape[0]) (также известный как диагональная матрица), тензор представлялся следующим образом,

tensor([[1.0000, 0.7520, 0.5343, 0.1698],        [0.7520, 1.0000, 0.6294, 0.1560],        [0.5343, 0.6294, 1.0000, 0.3272],        [0.1698, 0.1560, 0.3272, 1.0000]])

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

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

pick_probability = pairwise_distance_matrix / (    torch.sum(pairwise_distance_matrix, 1).view(-1, 1)    + stability_epsilon)

Вероятность выборки с маскировкой

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

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

Сначала мы должны получить парную матрицу из векторов меток:

masking_matrix = torch.squeeze(    torch.eq(labels, labels.unsqueeze(1)).float())

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

masked_pick_probability = pick_probability * masking_matrix

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

summed_masked_pick_probability = torch.sum(masked_pick_probability, dim=1)

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

snnl = torch.mean(    -torch.log(summed_masked_pick_probability + stability_epsilon)

Теперь мы можем объединить эти компоненты в функции прямого прохода (forward pass), чтобы вычислить мягкую потерю ближайших соседей для всех слоев глубокой нейронной сети,

def forward(    self,    model: torch.nn.Module,    features: torch.Tensor,    labels: torch.Tensor,    outputs: torch.Tensor,    epoch: int,) -> Tuple:    if self.use_annealing:        self.temperature = 1.0 / ((1.0 + epoch) ** 0.55)    primary_loss = self.primary_criterion(        outputs, features if self.unsupervised else labels    )    activations = self.compute_activations(model=model, features=features)    layers_snnl = []    for key, value in activations.items():        value = value[:, : self.code_units]        distance_matrix = self.pairwise_cosine_distance(features=value)        pairwise_distance_matrix = self.normalize_distance_matrix(            features=value, distance_matrix=distance_matrix        )        pick_probability = self.compute_sampling_probability(            pairwise_distance_matrix        )        summed_masked_pick_probability = self.mask_sampling_probability(            labels, pick_probability        )        snnl = torch.mean(            -torch.log(self.stability_epsilon + summed_masked_pick_probability)        )        layers_snnl.append(snnl)        snn_loss = torch.stack(layers_snnl).sum()    train_loss = torch.add(primary_loss, torch.mul(self.factor, snn_loss))    return train_loss, primary_loss, snn_loss

Визуализация разделимых представлений

Мы обучили автоэнкодер с помощью функции потерь “мягкое ближайшее соседство” и визуализировали его изученные разделимые представления. Автоэнкодер содержал (x-500-500-2000-d-2000-500-500-x) узлов и обучался на небольшом помеченном подмножестве наборов данных MNIST, Fashion-MNIST и EMNIST-Balanced. Это симулирует дефицит помеченных примеров, так как автоэнкодеры являются безнадзорными моделями.

Рисунок 7. 3D-визуализация сравнения первоначального представления и разделяемого латентного представления трех наборов данных. Для достижения этой визуализации представления были закодированы с использованием t-SNE с perplexity = 50 и скоростью обучения = 10, оптимизированы за 5000 итераций. Рисунок автора.

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

Заключительные замечания

В этой статье мы исследовали функцию потерь “мягкое ближайшее соседство” и способы ее реализации в PyTorch.

Функция потерь “мягкое ближайшее соседство” впервые была представлена в работе Салахутдинова и Хинтона (2007), где она использовалась для подсчета потери на латентном кодовом (узком месте) представлении автоэнкодера, а затем это представление использовалось для классификации kNN.

Дальнейшую разработку функции потерь “мягкое ближайшее соседство” осуществили Фросст, Паперно и Хинтон (2019), которые представили множитель температуры и вычисление потери на всех слоях нейронной сети.

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

Полная реализация кода доступна на GitLab.

Литература

  • Agarap, Abien Fred и Arnulfo P. Azcarraga. “Улучшение производительности кластеризации k-средних с использованием разделимых внутренних представлений.” Международная совместная конференция по нейронным сетям (IJCNN) 2020. IEEE, 2020.
  • Chapelle, Olivier, Bernhard Scholkopf и Alexander Zien. “Полусверхнадзорное обучение (chapelle, o. et al., eds.; 2006)[book reviews].” IEEE Transactions on Neural Networks 20.3 (2009): 542–542.
  • Frosst, Nicholas, Nicolas Papernot и Geoffrey Hinton. “Анализ и улучшение представлений с использованием функции потерь “мягкое ближайшее соседство”.” Международная конференция по машинному обучению. PMLR, 2019.
  • Goldberger, Jacob и др. “Анализ компонентов окружающей среды.” Продвижение в нейронных информационных системах. 2005.
  • He, Kaiming и др. “Глубокое остаточное обучение для распознавания изображений.” Процедуры конференции IEEE по компьютерному зрению и распознаванию образов. 2016.
  • Hinton, G., и др. “Анализ компонентов окружающей среды.” Proc. NIPS. 2004.
  • Krizhevsky, Alex, Ilya Sutskever и Geoffrey E. Hinton. “Классификация ImageNet с помощью глубоких сверточных нейронных сетей.” Продвижение в нейронных информационных системах 25 (2012).
  • Roweis, Sam T. и Lawrence K. Saul. “Нелинейное снижение размерности с использованием метода локального линейного вложения.” наука 290.5500 (2000): 2323–2326.
  • Salakhutdinov, Ruslan и Geoff Hinton. “Обучение нелинейного вложения путем сохранения структуры классов в соседстве.” Искусственный интеллект и статистика. 2007.
  • Simonyan, Karen и Andrew Zisserman. “Очень глубокие сверточные сети для распознавания изображений в крупном масштабе.” предварительная версия arXiv arXiv:1409.1556 (2014).
  • Van der Maaten, Laurens, и Geoffrey Hinton. “Визуализация данных с использованием t-SNE.” Журнал машинного обучения 9.11 (2008).