Вычисление евклидовой нормы в Pytorch. Проблемы понимания реализации

1

Я видел еще один поток StackOverflow, рассказывающий о различных реализациях для вычисления евклидовой нормы, и у меня возникают проблемы с тем, почему/как работает конкретная реализация.

Код найден в реализации метрики MMD: https://github.com/josipd/torch-two-sample/blob/master/torch_two_sample/statistics_diff.py

Вот несколько исходных шаблонов:

import torch
sample_1, sample_2 = torch.ones((10,2)), torch.zeros((10,2))

Затем следующая часть - это то, где мы берем код выше. Я не уверен, что образцы объединяются вместе.

sample_12 = torch.cat((sample_1, sample_2), 0)
distances = pdist(sample_12, sample_12, norm=2)

и затем передаются в функцию pdist:

def pdist(sample_1, sample_2, norm=2, eps=1e-5):
    r"""Compute the matrix of all squared pairwise distances.
    Arguments
    ---------
    sample_1 : torch.Tensor or Variable
        The first sample, should be of shape ''(n_1, d)''.
    sample_2 : torch.Tensor or Variable
        The second sample, should be of shape ''(n_2, d)''.
    norm : float
        The l_p norm to be used.
    Returns
    -------
    torch.Tensor or Variable
        Matrix of shape (n_1, n_2). The [i, j]-th entry is equal to
        ''|| sample_1[i, :] - sample_2[j, :] ||_p''."""

здесь мы добираемся до мяса расчета

    n_1, n_2 = sample_1.size(0), sample_2.size(0)
    norm = float(norm)
    if norm == 2.:
        norms_1 = torch.sum(sample_1**2, dim=1, keepdim=True)
        norms_2 = torch.sum(sample_2**2, dim=1, keepdim=True)
        norms = (norms_1.expand(n_1, n_2) +
             norms_2.transpose(0, 1).expand(n_1, n_2))
        distances_squared = norms - 2 * sample_1.mm(sample_2.t())
        return torch.sqrt(eps + torch.abs(distances_squared))

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

Теги:
pytorch
euclidean-distance

1 ответ

2
Лучший ответ

Пройдите через этот блок кода шаг за шагом. Определение евклидова расстояния, т.е. Норма Л2,

Изображение 174551

Рассмотрим простейший случай. У нас есть два образца,

Изображение 174551

Образец a имеет два вектора [a00, a01] и [a10, a11]. То же самое для образца b. Пусть сначала вычислим norm

n1, n2 = a.size(0), b.size(0)  # here both n1 and n2 have the value 2
norm1 = torch.sum(a**2, dim=1)
norm2 = torch.sum(b**2, dim=1)

Теперь мы получаем

Изображение 174551

Затем у нас есть norms_1.expand(n_1, n_2) и norms_2.transpose(0, 1).expand(n_1, n_2)

Изображение 174551

Заметим, что b транспонируется. Сумма двух дает norm

Изображение 174551

sample_1.mm(sample_2.t()), что умножение двух матриц.

Изображение 174551

Поэтому после операции

distances_squared = norms - 2 * sample_1.mm(sample_2.t())

ты получаешь

Изображение 174551

В конце концов, последний шаг принимает квадратный корень от каждого элемента в матрице.

  • 0
    Спасибо тебе большое за это. Это одна из самых полезных поломок, которые я когда-либо видел :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню