Векторизовать scipy.stats.norm.logpdf

Вопрос или проблема

Я пытаюсь обучить байесовскую нейронную сеть, и в какой-то момент мне нужно вычислить логарифмическую вероятность для некоторых данных в соответствии с многомерным диагональным нормальным распределением с параметрами (mu, sigma).
У меня есть 2 проблемы:

  1. Я не знаю размер значений заранее (учтите, что я гарантирую, что ‘values’, ‘mu’ и ‘rho’ имеют одинаковый размер, но они могут быть как 1D, так и 2D, что заставляет меня использовать некрасивое выражение if. В идеале я бы просто перебирал элементы независимо от размера тензора.

  2. Это очень медленно. Я не вижу, как можно векторизовать logpdf способом numpy, так как передача значений, mu и sigma напрямую в norm.logpdf кажется неявно создает ковариационную матрицу (которая слишком велика и вызывает сбой программы).

    from scipy.stats import norm
    
    ...
    
    mu = self.mu.detach().numpy()
    sigma = np.log(1 + np.exp(self.rho.detach().numpy()))
    vals = values.detach().numpy()
    log_likelihood_val = 0
    if len(values.size()) == 2:
        for i in range(values.size()[0]):
            for j in range(values.size()[1]):
                log_likelihood_val += norm.logpdf(vals[i,j], loc=mu[i,j], scale=sigma[i,j])
    else:
        for i in range(values.size()[0]):
            log_likelihood_val += norm.logpdf(vals[i], loc=mu[i], scale=sigma[i])
    return torch.tensor(log_likelihood_val)
    

Как мне реализовать это по-другому?

Я просто в конечном итоге определил свою собственную функцию logpdf, чтобы она легко векторизировалась, что решило обе проблемы сразу:

def log_likelihood(self, values: torch.Tensor) -> torch.Tensor:
    def logpdf(x, mu, sigma):
        return -(((x - mu)/sigma)**2)/2 - torch.log(np.sqrt(2*np.pi) * sigma)

    sigma = torch.log(1 + torch.exp(self.rho))
    log_likelihood_val = torch.sum(logpdf(values, self.mu, sigma))
    return log_likelihood_val

Надеюсь, это поможет кому-то.

Ответ или решение

Теория

При обучении байесовской нейронной сети (БНС) часто требуется вычислить логарифм правдоподобия для набора данных в соответствии с многомерным гауссовским распределением с диагональной ковариационной матрицей. Обычно параметры такого распределения описываются векторами среднего (mu) и стандартного отклонения (sigma). Однако функция scipy.stats.norm.logpdf из библиотеки SciPy изначально предназначена для работы с одномерными распределениями, что может создать трудности при попытке векторизации данных, особенно в многомерных случаях.

Пример

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

Применение

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

[ \log(\text{pdf}(x | \mu, \sigma)) = -\frac{(x – \mu)^2}{2\sigma^2} – \log(\sqrt{2\pi}\sigma) ]

Пример кода:

def log_likelihood(self, values: torch.Tensor) -> torch.Tensor:
    def logpdf(x, mu, sigma):
        return -(((x - mu) / sigma) ** 2) / 2 - torch.log(np.sqrt(2 * np.pi) * sigma)

    sigma = torch.log(1 + torch.exp(self.rho))
    log_likelihood_val = torch.sum(logpdf(values, self.mu, sigma))
    return log_likelihood_val

Заключение

Данный подход позволяет значительно упростить код и улучшить его производительность за счет векторизации расчётов с использованием тензоров PyTorch. Это решение не только устраняет необходимость в условных конструкциях, таких как if-операторы для различных измерений, но и значительно оптимизирует вычисления линейной алгебры в многомерных случаях, что особенно актуально в контексте обучения байесовских нейронных сетей с большим объемом данных.

Оцените материал
Добавить комментарий

Капча загружается...