Вопрос или проблема
Я пытаюсь понять алгоритм Байес по обратному распространению из статьи Неопределенность весов в нейронных сетях, идея заключается в том, чтобы создать нейронную сеть, в которой каждый вес имеет собственное распределение вероятностей. Я понимаю теорию, но не понимаю, как обновлять среднее и дисперсию в процессе обучения. Я нашел код на Pytorch, который просто делает следующее:
class BayesianLinear(nn.Module):
def __init__(self, in_features, out_features):
(...)
# Параметры весов
self.weight_mu = nn.Parameter(torch.Tensor(out_features, in_features).uniform_(-0.2, 0.2))
self.weight_rho = nn.Parameter(torch.Tensor(out_features, in_features).uniform_(-5,-4))
self.weight = Gaussian(self.weight_mu, self.weight_rho)
Как оптимизатор знает, как обновлять му (среднее) и роу (дисперсию)? Это функция Parameter позволяет это сделать? Или это происходит где-то в коде? (с этой точки зрения это выглядит как обычная нейронная сеть!).
PyTorch запоминает граф вычислений. Это означает, что для каждого значения, которое вы получаете после прямого прохода, он запоминает, какую операцию вы применили, и для всех базовых операций знает, как вычислять градиенты. Поэтому в PyTorch оптимизация предоставляется бесплатно — по крайней мере, для обычных нейронных сетей. Метод nn.Parameter
специально указывает отслеживать градиенты и изменять их во время оптимизации.
Этот подход хорошо работает в данном конкретном случае, но есть два не совсем обычных шага в байесовском обратном распространении:
- Для каждого нейрона мы выбираем веса. Технически, мы начинаем с выборки из $N(0, 1)$, а затем применяем обучаемые параметры. Конкретные значения, которые мы получаем из $N(0, 1)$, являются чем-то вроде дополнительных входов и для некоторых операций изменяют градиенты.
- Потеря обычно зависит только от выходов и истинных меток, но для термина KL вам нужно вычислить значение в замкнутой форме на основе самих весов. Вам, вероятно, придется явно собирать термин потерь KL из каждого слоя.
Все остальное должно обрабатываться нормально в pytorch
Ответ или решение
Вопрос об обновлении среднего и дисперсии весов в контексте алгоритма «Bayes by Backprop» (или «Байесовская обратная пропагация») представляет собой важную тему, поскольку это является ключевым моментом для реализации неопределенности в нейронных сетях. Рассмотрим детали того, как обновление происходит на практике.
Основы алгоритма Bayes by Backprop
Алгоритм Bayes by Backprop предполагает, что каждый вес в нейронной сети обладает собственной вероятностной моделью, а не фиксированным значением. Это означает, что в ходе обучения мы не просто обновляем веса, как в традиционных нейронных сетях, а обновляем параметры распределения вероятностей, задающих эти веса. В частности, мы обновляем среднее (μ) и логарифм дисперсии (ρ) для каждого веса.
Обновление весов с использованием PyTorch
В приведенном вами примере кода на PyTorch используется класс BayesianLinear
, который определяет слой с неопределенными весами. Параметры weights (μ и ρ) выделяются с помощью метода nn.Parameter
, который делает эти переменные «обучаемыми», то есть их значения будут обновляться в процессе оптимизации.
class BayesianLinear(nn.Module):
def __init__(self, in_features, out_features):
super(BayesianLinear, self).__init__()
self.weight_mu = nn.Parameter(torch.Tensor(out_features, in_features).uniform_(-0.2, 0.2)) # Среднее
self.weight_rho = nn.Parameter(torch.Tensor(out_features, in_features).uniform_(-5, -4)) # Логарифм дисперсии
self.weight = Gaussian(self.weight_mu, self.weight_rho) # Веса как распределение
# В процессе обратного распространения ошибки, PyTorch отслеживает все операции
Как происходит обновление μ и ρ?
1. Градиенты и вычислительный граф
PyTorch автоматически создает вычислительный граф во время прямого прохода. Этот граф содержит информацию о функциях, примененных к параметрам, что позволяет PyTorch легко вычислять градиенты. Таким образом, при вызове оптимизатора, который вы укажете (например, SGD или Adam), он будет знать, как обновить характеристики weight_mu
и weight_rho
на основе градиентов, полученных во время обратного прохода.
2. Метод потерь
Поскольку в байесовской модели вы не просто минимизируете функцию потерь (например, MSE), но и добавляете термин KL-дивергенции для учета неопределенности, необходимо, чтобы эта часть отразилась в вашем методе потерь. KL-дивергенция измеряет расхождение между вашим текущим апостериорным распределением и prior распределением (например, стандартным нормальным распределением).
kl_divergence = ...
loss = original_loss + kl_divergence
Заключение
Таким образом, обновление среднего и дисперсии весов в нейронной сети при использовании метода «Bayes by Backprop» осуществляется путем оптимизации параметров weight_mu
и weight_rho
с помощью стандартных методов градиентного спуска. PyTorch предоставляет мощные инструменты для автоматического отслеживания и вычисления градиентов, что позволяет сосредоточиться на реализации самого алгоритма. При этом важным аспектом является правильное построение функции потерь, которая учитывает как ошибку предсказания, так и неопределенность, связанную с весами.
С учетом всех вышеизложенных моментов, алгоритм Bayes by Backprop становится мощным инструментом для интеграции неопределенности в современную нейронную сеть, что открывает новые горизонты в области машинного обучения и глубокого обучения.