Привет, Хабр!

Недавно пообщался с коллегами о вариационном автоэнкодере и выяснилось что многие даже работающие в Deep Learning знают о вариационном выводе (Variational Inference) и в частности Нижней вариационной границе только по наслышке и не до конца понимают что это такое.
В этой статье я хочу подробно разобрать эти вопросы. Кому интересено, прошу под кат — будет очень интересно.

Что такое вариационный вывод?


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

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

Зачем же нам это нужно? Разве нельзя напрямую оптимизировать функцию потерь? Эти методы нам необходимы когда напрямую получить несмещенную оценку градиента невозможно (либо эта оценка обладает очень высокой дисперсией). Например наша модель задает $p(z)$ и $p(x/z)$, а нам необходимо вычислить $p(x) = \int(p(z)p(x/z)dz)$. Это как раз, то для чего разрабатывался вариационный автоэнкодер.

Что такое Нижняя вариационная граница (Variational Lower Bound)?


Представим, что у нас есть функция $f(x)$. Нижняя граница на эту функцию будет любая функция $g(x)$, удовлетворяющая уравнению:

$g(x) <= f(x)$


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

$\delta=max{f(x)} - max{g(x)}$


Достаточно очевидно, что невязка всегда положительна. Чем меньше невязка — тем лучше.

Вот пример нижней границы с нулевой невязкой:
image
А вот пример с небольшой, но положительной невязкой:
image
И наконец, достаточно большая невязка:
image

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

Вариационный автоэнкодер


Сейчас мы разберем пример очень хорошей нижней вариационной границы с потенциально нулевой невязкой (ниже будет понятно почему) — это Вариационный автоэнкодер (Variational Autoencoder).

Наша задача построить генеративную модель и обучить ее методом максимального правдоподобия. Модель будет иметь следующий вид:

$q(x) = \int{q(z)q_\theta(x|z) dz}$


где $q(x)$ — плотность вероятности генерируемых семплов, $z$ — латентные переменные, $q(z)$ — плотность вероятности латентной переменной (зачастую некая простая — например многомерное гауссовское распределение с нулевым матожиданием и единичной дисперсией — в общем что-то из чего мы можем легко семплировать), $q_\theta(x|z)$ — условная плотность семплов при заданном значении латентных переменных, в вариационном автоэнкодере выбирается гауссовское с мат ожиданием и дисперсией зависящими от z.

Зачем нам может понадобиться представлять плотность данных в таком сложном виде? Ответ прост — данные имеют очень сложную функцию плотности и мы просто технически не можем построить модель такой плотности напрямую. Мы надеемся что эту сложную плотность можно хорошо аппроксимировать с помощью двух более простых плотностей $q(z)$ и $q_\theta(x|z)$.

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

$I=\int{p(x)log(q(x))dx}$


где $p(x)$ — плотность вероятности данных. Основная проблема в том, что плотность $q(x)$ (при достаточно гибких моделях) не удается представить аналитически, а соответственно обучать модель.

Используем формулу Байеса и перепишем нашу функцию в следующем виде:

$I = \int{p(x)log(\frac{q(z)q(x|z)}{q(z|x)})dx}$


К сожалению, $q(z/x)$ все также сложно посчитать (невозможно взять интеграл аналитически). Но во-первых заметим что выражение под логарифмом не зависит от z, значит можно взять математическое ожидание от логарифма по z от любого распределения и это не изменит значения функции и под знаком логарифма умножить и поделить на это же распределение (формально мы имеем лишь одно условие — данное распределение нигде не должно обращаться в нуль). В итоге мы получим:

$I = \int{p(x)dx\int{\phi(z|x)log(\frac{q(z)q(x|z)}{\phi(z|x)})}} + \int{p(x)dx\int{\phi(z|x)log(\frac{\phi(z|x)}{q(z|x)})}}$


заметим что во-первых второе слагаемое — KL дивергенция (а значит всегда положительна):

$I = \int{p(x)dx\int{\phi(z|x)log(\frac{q(z)q(x|z)}{\phi(z|x)})}} + \int{p(x)KL[\phi(z|x)||q(z|x))]dx}$


и во-вторых $I$ не зависит ни от $q(z|x)$ ни от $\phi(z|x)$. Отсюда следует что,

$I >= \int{p(x)dx\int{\phi(z|x)log(\frac{q(z)q(x|z)}{\phi(z|x)})}}=VLB$


где $VLB$ — нижняя вариационная граница (Variational Lower Bound) и достигает своего максимума когда $KL[\phi(z|x)||q(z|x))]=0$ — т.е распределения совпадают.

Положительность и равенство нулю тогда и только тогда когда распределения совпадают KL-дивергенции доказываются именно вариационными методами — отсюда и название вариационная граница.

Хочу заметить, что использование вариационной нижней границы дает несколько преимуществ. Во-первых дает нам возможность оптимизировать функцию потерь градиентными методами (попробуйте сделать это когда интеграл аналитически не берется) и во-вторых приближает обратное распределение $q(z|x)$ распределением $\phi(z|x)$ — т.е мы можем не только семплировать данные, но и семплировать латентные переменны. К сожалению, главный недостаток — при недостаточно гибкой модели обратного распределения, т.е когда семейство $\phi(z|x)$ не содержит $q(z|x)$ — невязка будет положительной и равной:

$\delta=\int{p(x)\underset{\phi(z|x)}{min}(KL[\phi(z|x) || q(z|x)])dx}$


а это означает что максимум нижней границы и функции потерь скорее всего не совпадают. Кстати, вариационный автоэнкодер примененный для генерации картинок генерирует слишком смазанные изображения, думаю это как раз из-за выбора слишком бедного семейства $\phi(z|x)$.

Пример не очень хорошей нижней границы


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

Итак, мы будем рассматривать точно такую же генеративную модель как и в случае вариационного автоэнкодера:

$q(x) = \int{q(z)q_\theta(x|z) dz}$


обучать будем все тем же методом максимального правдоподобия:

$I=\int{p(x)log(q(x))dx}$


Мы все так же надеемся, что $q(x|z)$ будет намного «проще» чем $q(x)$.
Только теперь распишем $I$ немного по-другому:

$I=\int{p(x)log(\int{q(z)q_\theta(x|z) dz})dx}$


используя формулу Дженсена (Jensen) получим:

$I>=\int{p(x)q(z)log(q_\theta(x|z))dxdz} = VLB$


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

$\delta=\int{p(x)log(q(x))dx}-\int{p(x)q(z)log(q_\theta(x|z))dxdz}$


откуда (применив формулу Ьайеса два раза):

$\delta=\int{p(x)q(z)log(\frac{q(x)}{q(x|z)})dxdz}=\int{p(x)q(z)log(\frac{q(z)}{q(z|x)})dxdz}$


легко заметить, что:

$\delta=\int{p(x)KL[q(z)||q(z|x)]dx}$


Давайте посмотрим что будет если мы будем увеличивать нижнюю границу — невязка будет уменьшаться. При достаточно гибкой модели:

$KL[q(z)||q(z|x)]\rightarrow0 $


казалось бы все отлично — нижняя граница обладает потенциально нулевой невязкой и при достаточно гибкой модели $q(x|z)$ все должно работать. Да это действительно так, только внимательные читатели могут заметить что нулевая невязка достигается когда $x$ и $z$ являются независимыми случайными величинами!!! и для хорошего результата «сложность» распределения $q(x|z)$ должна быть ничуть не меньше чем $q(x)$. Т.е нижняя граница не дает нам никаких преимуществ.

Выводы


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

Надеюсь это было хоть немного полезно и интересно.

Комментарии (1)


  1. BelerafonL
    20.10.2019 09:51
    +1

    Спасибо за статью, тема нужная, но, к сожалению, я ничего не понял. Нет связи формул с обычной подачей материала про машинное обучение, нет примеров и пояснений что есть что. Я вот знаю архитектуру вариационного автоэнкодера, ну типа две нейросети и распределение p(z) посередине. А что есть что в формулах? У вас вводится p(x), q(x), p(x/z), фи(z/x) и нигде не сказано, что вот это вот и апроксимирует кодировщик автоэнкодера, а то вот это аппроксимирует декодер, а вот это вот наша лосс функция.
    Я вот даже не понял отсылки к тому, что автоэнкодер генерирует смазанные картинки. В курсах по машинному обучению учат, что это происходит из-за лосса попиксельной близости, где декодер генерирует некое усредненное изображение, которое пытается одновременно удовлетворять всем примерам обучающей выборки. Но как эту интуицию увидеть в «бедности семейства фи(z/x)» я не понял.
    Наверное, математические статьи не для меня, но, думаю, я не один здесь такой. Просьба объяснять чуть более «на пальцах», если можно, с примерами.