<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>https://nerc.itmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Aleksei.latyshev&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="https://nerc.itmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Aleksei.latyshev&amp;*"/>
		<link rel="alternate" type="text/html" href="https://nerc.itmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Aleksei.latyshev"/>
		<updated>2026-11-12T11:13:41Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69474</id>
		<title>Вариационный автокодировщик</title>
		<link rel="alternate" type="text/html" href="https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69474"/>
				<updated>2019-01-27T23:39:40Z</updated>
		
		<summary type="html">&lt;p&gt;Aleksei.latyshev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Вариационный автокодировщик''' (англ. ''Variational Autoencoder'', ''VAE'') {{---}} это [[автокодировщик]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt; (a.k.a. генеративная модель, которая учится отображать объекты в заданное скрытое пространство (и обратно)) основанный на вариационном выводе.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Предпосылки ==&lt;br /&gt;
При попытке использования обыкновенного автокодировщика для генерации новых объектов (желательно из того же априорного распределения, что и датасет) возникает следующая проблема. Случайной величиной с каким распределением проинициализировать скрытые векторы, для того, чтобы картинка, после применения декодера, стала похожа на картинки из датасета, но при этом не совпадала ни с одной из них? Ответ на этот вопрос не ясен, в связи с тем, что обыкновенный автокодировщик не может ничего утверждать про распределение скрытого вектора и даже про его область определения. В частности, область определения может быть даже дискретной.&lt;br /&gt;
&lt;br /&gt;
Вариационный автокодировщик в свою очередь предлагает пользователю самому определить распределение скрытого вектора. &lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
'''Порождающее моделирование''' (англ. ''Generative modelling'') {{---}} область машинного обучения, имеющая дело с распределением &amp;lt;math&amp;gt;P(X)&amp;lt;/math&amp;gt;, определенном на датасете &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; из пространства (возможно многомерного) &amp;lt;math&amp;gt;\Chi&amp;lt;/math&amp;gt;. Так, например, популярные задачи генерации картинок имеют дело с огромным количеством измерений (пикселей). &lt;br /&gt;
&lt;br /&gt;
Также как и в обыкновенных кодировщиках у нас имеется скрытое вероятностное пространство &amp;lt;math&amp;gt;Z&amp;lt;/math&amp;gt; соответствующее случайной величине &amp;lt;math&amp;gt;(z, P(z))&amp;lt;/math&amp;gt; (распределенной как-нибудь фиксированно, здесь &amp;lt;math&amp;gt;\sim N(0, 1)&amp;lt;/math&amp;gt;). И мы хотим иметь декодер &amp;lt;math&amp;gt;f(z, \theta) \colon Z \times \Theta \to \Chi &amp;lt;/math&amp;gt;. При этом мы хотим найти такие &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, чтобы после разыгрывания &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; по &amp;lt;math&amp;gt;P(z)&amp;lt;/math&amp;gt; мы получили &amp;quot;что-то похожее&amp;quot; на элементы &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Вообще, для любого &amp;lt;math&amp;gt;x \in X&amp;lt;/math&amp;gt; мы хотим считать &amp;lt;math&amp;gt;P(x) = \int P(x|z; \theta)P(z)dz&amp;lt;/math&amp;gt;, здесь мы заменили &amp;lt;math&amp;gt;f(z, \theta)&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt;, чтобы явно показать зависимость между &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; и после этого применить формулу полной вероятности. Обычно &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt; около нуля почти для всех пар &amp;lt;math&amp;gt;(x, z)&amp;lt;/math&amp;gt;. Основная идея в том, что мы хотим теперь генерировать &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, который бы давали что-то около &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и только их суммировать в &amp;lt;math&amp;gt;P(x)&amp;lt;/math&amp;gt;. Для этого нам требуется ввести еще одно распределение &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;, которое будет получать &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и говорить распределение на &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; которое наиболее вероятно будет генерировать нам такой &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Теперь нам нужно как-то сделать похожими распределения &amp;lt;math&amp;gt;E_{z\sim Q}P(X|z)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;P(X)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим следующую дивергенцию Кульбака-Лейблера.&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z|X) − log P(z|X)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Распишем &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;P(X|z) * P(z) / P(X)&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z) − log P(X|z) - log P(z)] + log P(X)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Что эквивалентно:&lt;br /&gt;
:&amp;lt;math&amp;gt;logP(x) - D[Q(z)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим эту штуку для &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;, тогда:&lt;br /&gt;
:&amp;lt;math&amp;gt;logP(x) - D[Q(z|X)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z|X)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посмотрим, на это равенство. Правую часть мы можем оптимизировать градиентным спуском (пусть пока и не совсем понятно как).&lt;br /&gt;
В левой же части первое слагаемое -- то, что мы хотим максимизировать. В то же время &amp;lt;math&amp;gt;D[Q(z|X)||P(z|X)]&amp;lt;/math&amp;gt; мы хотим минимизировать. Если у нас &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt; -- достаточно сильная модель, то в какой-то модель она будет хорошо матчить &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt;, а значит их дивергенция Кульбака-Лейблера будет почти 0. А значит на это слагаемое можно забить. И стараться максимизировать правую часть. В качестве бонуса мы еще получили более &amp;quot;поддатливую&amp;quot; &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt;, вместо нее можно смотреть на &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь разберемся как оптимизировать правую часть. Сначала нужно определиться с моделью для &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;. Обычно ее берут равной &amp;lt;math&amp;gt;N(z|\mu(X, \theta), \sigma(X, \theta))&amp;lt;/math&amp;gt;. Где &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\sigma&amp;lt;/math&amp;gt; какие-то детерминированные функции на X с обучаемыми параметрами &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, которые мы впредь будем опускать). Ага, нейронки. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно проверить, что для дивергенция Кульбака-Лейблера двух нормальных распределений имеет следующий вид.&lt;br /&gt;
:&amp;lt;math&amp;gt;D_{K}[N(\mu_1, \Sigma_0)||N(\mu_1, \Sigma_0)]&amp;lt;/math&amp;gt;, KLD есть &amp;lt;math&amp;gt;\frac{1}{2} (tr(\Sigma_1^{-1}\Sigma_0) + (\mu_1 - \mu_0)^T\Sigma_1^{-1}(\mu_1 - \mu_0) - k + log(\frac{det\Sigma_1}{det\Sigma_0})) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это значит, что&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z|X)||P(z)] = D[N(\mu(X), \Sigma(X))||N(0, I)] = \frac12 (tr(\Sigma(X)) + \mu(X)^T\mu(X) - k - log(det\Sigma(X)))&amp;lt;/math&amp;gt;. &lt;br /&gt;
Теперь здесь &lt;br /&gt;
можно считать градиенты, для BackPropagation. С первым слагаемым в правой части все немного сложнее. &amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)]&amp;lt;/math&amp;gt; мы можем считать методом Монте-Карло(МК), но тогда такая штука (из-за того, что переменные спрятаны в распределении, из которого мы генерируем себе выборку, для МК) не является гладкой относительно них, а значит непонятно, как проталкивать через это градиент. Для того, чтобы все-таки можно было протолкнуть градиент, применяется так называемый reparametrization trick, который базируется на простой формуле &amp;lt;math&amp;gt;N(\Sigma(X), \mu(X)) = \mu(X) + \Sigma^{\frac12}(X) * N(0, I) &amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)] = E_{\epsilon \sim N(0, I)}[log P(X = f(\mu(X) + \Sigma^{\frac12}(X) * \epsilon), \theta)]&amp;lt;/math&amp;gt;. &lt;br /&gt;
В такой форме мы уже можем использовать BackPropagation для переменных из функций &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следующая картинка лучше поможет осознать структуру VAE и, в частности, зачем нужен (и как работает) reparametrization trick.&lt;br /&gt;
&lt;br /&gt;
На левой части диаграмма без использования reparameterization trick. &lt;br /&gt;
На правой части диаграмма с использованием reparameterization trick. &lt;br /&gt;
&lt;br /&gt;
[[Файл:VAE.PNG]]&lt;br /&gt;
&lt;br /&gt;
взято из https://arxiv.org/pdf/1606.05908.pdf&lt;br /&gt;
&lt;br /&gt;
== Пример реализации ==&lt;br /&gt;
Ниже приведена реализация частного случая VAE на языке Python с использованием библиотеки Pytorch.&lt;br /&gt;
Эта реализация работает с датасетом MNIST.&lt;br /&gt;
Размерность скрытого слоя {{---}} 2. &lt;br /&gt;
Координаты в нем считаются независимыми (из-за этого, например, матрица &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; диагональная, и формула для расчета KLD немного другая).&lt;br /&gt;
&lt;br /&gt;
 class VariationalAutoencoder(nn.Module):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super().__init__()&lt;br /&gt;
        self.mu = nn.Linear(32, 2)&lt;br /&gt;
        self.gamma = nn.Linear(32, 2)&lt;br /&gt;
        self.encoder = nn.Sequential(nn.Linear(784, 32), nn.ReLU(True))&lt;br /&gt;
        self.decoder = nn.Sequential(nn.Linear(2, 32), nn.ReLU(True), nn.Linear(32, 784), nn.Sigmoid())&lt;br /&gt;
 &lt;br /&gt;
    def forward(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        x = self.decoder(encoding)&lt;br /&gt;
        return x, mu, gamma&lt;br /&gt;
 &lt;br /&gt;
    def reparameterize(self, mu, gamma):&lt;br /&gt;
        if self.training:&lt;br /&gt;
            sigma = torch.exp(0.5*gamma)&lt;br /&gt;
            std_z = Variable(torch.from_numpy(np.random.normal(0, 1, size=sigma.size())).float())&lt;br /&gt;
            encoding = std_z.mul(sigma).add(mu)&lt;br /&gt;
            return encoding&lt;br /&gt;
        else:&lt;br /&gt;
            return mu&lt;br /&gt;
 &lt;br /&gt;
    def encode(self, x):&lt;br /&gt;
        x = self.encoder(x)&lt;br /&gt;
        mu = self.mu(x)&lt;br /&gt;
        gamma = self.gamma(x)&lt;br /&gt;
        return mu, gamma&lt;br /&gt;
  &lt;br /&gt;
    def decode(self, x):&lt;br /&gt;
        return self.decoder(x)&lt;br /&gt;
 &lt;br /&gt;
    def latent(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        return encoding&lt;br /&gt;
 &lt;br /&gt;
 def loss_function(input, output, mu, gamma, batch_size=batch_size):&lt;br /&gt;
    BCE = F.binary_cross_entropy(output, input)&lt;br /&gt;
    KLD = -0.5*torch.sum(1 + gamma - mu.pow(2) - gamma.exp())&lt;br /&gt;
    KLD /= batch_size*784&lt;br /&gt;
    return BCE + KLD&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Область применения вариационных автокодировщиков совпадает с областью применения обыкновенных автокодировщиков. А именно:&lt;br /&gt;
* Каскадное обучение глубоких сетей (хотя сейчас применяется все реже, в связи с появлением новых методов инициализации весов)&lt;br /&gt;
* Уменьшение шума в данных&lt;br /&gt;
* Уменьшение размерности данных (иногда работает лучше, чем [[метод главных компонент]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Благодаря тому, что пользователь сам устанавливает нужное распределение скрытого вектора, вариационный кодировщик хорошо подходит для генерации новых объектов (например, картинок). Для этого достаточно разыграть скрытый вектор согласно его распределению и скормить ее в декодер. Получится объект из того же распределения, что и датасет.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
*[[:Автокодировщик|Автокодировщик]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt; &lt;br /&gt;
*[[:Generative Adversarial Nets (GAN)|Порождающие состязательные сети]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
*[https://habr.com/ru/post/429276/ Вариационные автокодировщики: теория и рабочий код]&lt;br /&gt;
*[https://jaan.io/what-is-variational-autoencoder-vae-tutorial/ Tutorial - What is a variational autoencoder?]&lt;br /&gt;
*[https://towardsdatascience.com/intuitively-understanding-variational-autoencoders-1bfe67eb5daf Intuitively Understanding Variational Autoencoders]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[https://arxiv.org/abs/1606.05908 Tutorial on Variational Autoencoders]&lt;br /&gt;
*Datalore презентация Дениса Степанова&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Порождающие модели]]&lt;/div&gt;</summary>
		<author><name>Aleksei.latyshev</name></author>	</entry>

	<entry>
		<id>https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69473</id>
		<title>Вариационный автокодировщик</title>
		<link rel="alternate" type="text/html" href="https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69473"/>
				<updated>2019-01-27T23:29:32Z</updated>
		
		<summary type="html">&lt;p&gt;Aleksei.latyshev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Вариационный автокодировщик''' (англ. ''Variational Autoencoder'', ''VAE'') {{---}} это [[автокодировщик]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt; (a.k.a. генеративная модель, которая учится отображать объекты в заданное скрытое пространство (и обратно)) основанный на вариационном выводе.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Предпосылки ==&lt;br /&gt;
При попытке использования обыкновенного автокодировщика для генерации новых объектов (желательно из того же априорного распределения, что и датасет) возникает следующая проблема. Случайной величиной с каким распределением проинициализировать скрытые векторы, для того, чтобы картинка, после применения декодера, стала похожа на картинки из датасета, но при этом не совпадала ни с одной из них? Ответ на этот вопрос не ясен, в связи с тем, что обыкновенный автокодировщик не может ничего утверждать про распределение скрытого вектора и даже про его область определения. В частности, область определения может быть даже дискретной.&lt;br /&gt;
&lt;br /&gt;
Вариационный автокодировщик в свою очередь предлагает пользователю самому определить распределение скрытого вектора. &lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
'''Порождающее моделирование''' (англ. ''Generative modelling'') {{---}} область машинного обучения, имеющая дело с распределением &amp;lt;math&amp;gt;P(X)&amp;lt;/math&amp;gt;, определенном на датасете &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; из пространства (возможно многомерного) &amp;lt;math&amp;gt;\Chi&amp;lt;/math&amp;gt;. Так, например, популярные задачи генерации картинок имеют дело с огромным количеством измерений (пикселей). &lt;br /&gt;
&lt;br /&gt;
Также как и в обыкновенных кодировщиках у нас имеется скрытое вероятностное пространство &amp;lt;math&amp;gt;Z&amp;lt;/math&amp;gt; соответствующее случайной величине &amp;lt;math&amp;gt;(z, P(z))&amp;lt;/math&amp;gt; (распределенной как-нибудь фиксированно, здесь &amp;lt;math&amp;gt;~N(0, 1)&amp;lt;/math&amp;gt;). И мы хотим иметь декодер &amp;lt;math&amp;gt;f(z, \theta) \colon Z \times \Theta \to \Chi &amp;lt;/math&amp;gt;. При этом мы хотим найти такие &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, чтобы после разыгрывания &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; по &amp;lt;math&amp;gt;P(z)&amp;lt;/math&amp;gt; мы получили &amp;quot;что-то похожее&amp;quot; на элементы &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Вообще, для любого &amp;lt;math&amp;gt;x \in X&amp;lt;/math&amp;gt; мы хотим считать &amp;lt;math&amp;gt;P(x) = \int P(x|z; \theta)P(z)dz&amp;lt;/math&amp;gt;, здесь мы заменили &amp;lt;math&amp;gt;f(z, \theta)&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt;, чтобы явно показать зависимость между &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; и после этого применить формулу полной вероятности. Обычно &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt; около нуля почти для всех пар &amp;lt;math&amp;gt;(x, z)&amp;lt;/math&amp;gt;. Основная идея в том, что мы хотим теперь генерировать &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, который бы давали что-то около &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и только их суммировать в &amp;lt;math&amp;gt;P(x)&amp;lt;/math&amp;gt;. Для этого нам требуется ввести еще одно распределение &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;, которое будет получать &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и говорить распределение на &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; которое наиболее вероятно будет генерировать нам такой &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Теперь нам нужно как-то сделать похожими распределения &amp;lt;math&amp;gt;E_{z~Q}P(X|z)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;P(X)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим следующую дивергенцию Кульбака-Лейблера.&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z|X) − log P(z|X)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Распишем &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;P(X|z) * P(z) / P(X)&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z) − log P(X|z) - log P(z)] + log P(X)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Что эквивалентно:&lt;br /&gt;
:&amp;lt;math&amp;gt;logP(x) - D[Q(z)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим эту штуку для &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;, тогда:&lt;br /&gt;
:&amp;lt;math&amp;gt;logP(x) - D[Q(z|X)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z|X)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посмотрим, на это равенство. Правую часть мы можем оптимизировать градиентным спуском (пусть пока и не совсем понятно как).&lt;br /&gt;
В левой же части первое слагаемое -- то, что мы хотим максимизировать. В то же время &amp;lt;math&amp;gt;D[Q(z|X)||P(z|X)]&amp;lt;/math&amp;gt; мы хотим минимизировать. Если у нас &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt; -- достаточно сильная модель, то в какой-то модель она будет хорошо матчить &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt;, а значит их дивергенция Кульбака-Лейблера будет почти 0. А значит на это слагаемое можно забить. И стараться максимизировать правую часть. В качестве бонуса мы еще получили более &amp;quot;поддатливую&amp;quot; &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt;, вместо нее можно смотреть на &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь разберемся как оптимизировать правую часть. Сначала нужно определиться с моделью для &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;. Обычно ее берут равной &amp;lt;math&amp;gt;N(z|\mu(X, \theta), \sigma(X, \theta))&amp;lt;/math&amp;gt;. Где &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\sigma&amp;lt;/math&amp;gt; какие-то детерминированные функции на X с обучаемыми параметрами &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, которые мы впредь будем опускать). Ага, нейронки. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно проверить, что для дивергенция Кульбака-Лейблера двух нормальных распределений имеет следующий вид.&lt;br /&gt;
:&amp;lt;math&amp;gt;D_{K}[N(\mu_1, \Sigma_0)||N(\mu_1, \Sigma_0)]&amp;lt;/math&amp;gt;, KLD есть &amp;lt;math&amp;gt;\frac{1}{2} (tr(\Sigma_1^{-1}\Sigma_0) + (\mu_1 - \mu_0)^T\Sigma_1^{-1}(\mu_1 - \mu_0) - k + log(\frac{det\Sigma_1}{det\Sigma_0})) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это значит, что&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z|X)||P(z)] = D[N(\mu(X), \Sigma(X))||N(0, I)] = \frac12 (tr(\Sigma(X)) + \mu(X)^T\mu(X) - k - log(det\Sigma(X)))&amp;lt;/math&amp;gt;. &lt;br /&gt;
Теперь здесь &lt;br /&gt;
можно считать градиенты, для BackPropagation. С первым слагаемым в правой части все немного сложнее. &amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)]&amp;lt;/math&amp;gt; мы можем считать методом Монте-Карло(МК), но тогда такая штука (из-за того, что переменные спрятаны в распределении, из которого мы генерируем себе выборку, для МК) не является гладкой относительно них, а значит непонятно, как проталкивать через это градиент. Для того, чтобы все-таки можно было протолкнуть градиент, применяется так называемый reparametrization trick, который базируется на простой формуле &amp;lt;math&amp;gt;N(\Sigma(X), \mu(X)) = \mu(X) + \Sigma^{\frac12}(X) * N(0, I) &amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)] = E_{\epsilon~N(0, I)}[log P(X = f(\mu(X) + \Sigma^{\frac12}(X) * \epsilon), \theta)]&amp;lt;/math&amp;gt;. &lt;br /&gt;
В такой форме мы уже можем использовать BackPropagation для переменных из функций &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следующая картинка лучше поможет осознать структуру VAE и, в частности, зачем нужен (и как работает) reparametrization trick.&lt;br /&gt;
&lt;br /&gt;
На левой части диаграмма без использования reparameterization trick. &lt;br /&gt;
На правой части диаграмма с использованием reparameterization trick. &lt;br /&gt;
&lt;br /&gt;
[[Файл:VAE.PNG]]&lt;br /&gt;
&lt;br /&gt;
взято из https://arxiv.org/pdf/1606.05908.pdf&lt;br /&gt;
&lt;br /&gt;
== Пример реализации ==&lt;br /&gt;
Ниже приведена реализация частного случая VAE на языке Python с использованием библиотеки Pytorch.&lt;br /&gt;
Эта реализация работает с датасетом MNIST.&lt;br /&gt;
Размерность скрытого слоя {{---}} 2. &lt;br /&gt;
Координаты в нем считаются независимыми (из-за этого, например, матрица &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; диагональная, и формула для расчета KLD немного другая).&lt;br /&gt;
&lt;br /&gt;
 class VariationalAutoencoder(nn.Module):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super().__init__()&lt;br /&gt;
        self.mu = nn.Linear(32, 2)&lt;br /&gt;
        self.gamma = nn.Linear(32, 2)&lt;br /&gt;
        self.encoder = nn.Sequential(nn.Linear(784, 32), nn.ReLU(True))&lt;br /&gt;
        self.decoder = nn.Sequential(nn.Linear(2, 32), nn.ReLU(True), nn.Linear(32, 784), nn.Sigmoid())&lt;br /&gt;
 &lt;br /&gt;
    def forward(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        x = self.decoder(encoding)&lt;br /&gt;
        return x, mu, gamma&lt;br /&gt;
 &lt;br /&gt;
    def reparameterize(self, mu, gamma):&lt;br /&gt;
        if self.training:&lt;br /&gt;
            sigma = torch.exp(0.5*gamma)&lt;br /&gt;
            std_z = Variable(torch.from_numpy(np.random.normal(0, 1, size=sigma.size())).float())&lt;br /&gt;
            encoding = std_z.mul(sigma).add(mu)&lt;br /&gt;
            return encoding&lt;br /&gt;
        else:&lt;br /&gt;
            return mu&lt;br /&gt;
 &lt;br /&gt;
    def encode(self, x):&lt;br /&gt;
        x = self.encoder(x)&lt;br /&gt;
        mu = self.mu(x)&lt;br /&gt;
        gamma = self.gamma(x)&lt;br /&gt;
        return mu, gamma&lt;br /&gt;
  &lt;br /&gt;
    def decode(self, x):&lt;br /&gt;
        return self.decoder(x)&lt;br /&gt;
 &lt;br /&gt;
    def latent(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        return encoding&lt;br /&gt;
 &lt;br /&gt;
 def loss_function(input, output, mu, gamma, batch_size=batch_size):&lt;br /&gt;
    BCE = F.binary_cross_entropy(output, input)&lt;br /&gt;
    KLD = -0.5*torch.sum(1 + gamma - mu.pow(2) - gamma.exp())&lt;br /&gt;
    KLD /= batch_size*784&lt;br /&gt;
    return BCE + KLD&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Область применения вариационных автокодировщиков совпадает с областью применения обыкновенных автокодировщиков. А именно:&lt;br /&gt;
* Каскадное обучение глубоких сетей (хотя сейчас применяется все реже, в связи с появлением новых методов инициализации весов)&lt;br /&gt;
* Уменьшение шума в данных&lt;br /&gt;
* Уменьшение размерности данных (иногда работает лучше, чем [[метод главных компонент]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Благодаря тому, что пользователь сам устанавливает нужное распределение скрытого вектора, вариационный кодировщик хорошо подходит для генерации новых объектов (например, картинок). Для этого достаточно разыграть скрытый вектор согласно его распределению и скормить ее в декодер. Получится объект из того же распределения, что и датасет.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
*[[:Автокодировщик|Автокодировщик]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt; &lt;br /&gt;
*[[:Generative Adversarial Nets (GAN)|Порождающие состязательные сети]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
*[https://habr.com/ru/post/429276/ Вариационные автокодировщики: теория и рабочий код]&lt;br /&gt;
*[https://jaan.io/what-is-variational-autoencoder-vae-tutorial/ Tutorial - What is a variational autoencoder?]&lt;br /&gt;
*[https://towardsdatascience.com/intuitively-understanding-variational-autoencoders-1bfe67eb5daf Intuitively Understanding Variational Autoencoders]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[https://arxiv.org/abs/1606.05908 Tutorial on Variational Autoencoders]&lt;br /&gt;
*Datalore презентация Дениса Степанова&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Порождающие модели]]&lt;/div&gt;</summary>
		<author><name>Aleksei.latyshev</name></author>	</entry>

	<entry>
		<id>https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69470</id>
		<title>Вариационный автокодировщик</title>
		<link rel="alternate" type="text/html" href="https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69470"/>
				<updated>2019-01-27T23:23:40Z</updated>
		
		<summary type="html">&lt;p&gt;Aleksei.latyshev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Вариационный автокодировщик''' (англ. ''Variational Autoencoder'', ''VAE'') {{---}} это [[автокодировщик]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt; (a.k.a. генеративная модель, которая учится отображать объекты в заданное скрытое пространство (и обратно)) основанный на вариационном выводе.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Предпосылки ==&lt;br /&gt;
При попытке использования обыкновенного автокодировщика для генерации новых объектов (желательно из того же априорного распределения, что и датасет) возникает следующая проблема. Случайной величиной с каким распределением проинициализировать скрытые векторы, для того, чтобы картинка, после применения декодера, стала похожа на картинки из датасета, но при этом не совпадала ни с одной из них? Ответ на этот вопрос не ясен, в связи с тем, что обыкновенный автокодировщик не может ничего утверждать про распределение скрытого вектора и даже про его область определения. В частности, область определения может быть даже дискретной.&lt;br /&gt;
&lt;br /&gt;
Вариационный автокодировщик в свою очередь предлагает пользователю самому определить распределение скрытого вектора. &lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
'''Порождающее моделирование''' (англ. ''Generative modelling'') {{---}} область машинного обучения, имеющая дело с распределением &amp;lt;math&amp;gt;P(X)&amp;lt;/math&amp;gt;, определенном на датасете &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; из пространства (возможно многомерного) &amp;lt;math&amp;gt;\Chi&amp;lt;/math&amp;gt;. Так, например, популярные задачи генерации картинок имеют дело с огромным количеством измерений (пикселей). &lt;br /&gt;
&lt;br /&gt;
Также как и в обыкновенных кодировщиках у нас имеется скрытое вероятностное пространство &amp;lt;math&amp;gt;Z&amp;lt;/math&amp;gt; соответствующее случайной величине &amp;lt;math&amp;gt;(z, P(z))&amp;lt;/math&amp;gt; (распределенной как-нибудь фиксированно, здесь &amp;lt;math&amp;gt;~N(0, 1)&amp;lt;/math&amp;gt;). И мы хотим иметь декодер &amp;lt;math&amp;gt;f(z, \theta) \colon Z \times \Theta \to \Chi &amp;lt;/math&amp;gt;. При этом мы хотим найти такие &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, чтобы после разыгрывания &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; по &amp;lt;math&amp;gt;P(z)&amp;lt;/math&amp;gt; мы получили &amp;quot;что-то похожее&amp;quot; на элементы &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Вообще, мы хотим, чтобы для любого &amp;lt;math&amp;gt;x \in X&amp;lt;/math&amp;gt; мы хотим считать &amp;lt;math&amp;gt;P(x) = \int P(x|z; \theta)P(z)dz&amp;lt;/math&amp;gt; здесь мы заменили &amp;lt;math&amp;gt;f(x, \theta)&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt;, чтобы явно сделать зависимость между &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; и после этого применить формулу полной вероятности. Обычно &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt; около нуля почти для всех пар &amp;lt;math&amp;gt;(x, z)&amp;lt;/math&amp;gt;. Основная идея в том, что мы хотим теперь генерировать &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, который бы давали что-то около x и только их суммировать в &amp;lt;math&amp;gt;P(x)&amp;lt;/math&amp;gt;. Для этого нам требуется ввести еще одно распределение &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;, которое будет получать x и говорить распределение на &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; которое наиболее вероятно будет генерировать нам такой &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Теперь нам нужно как-то сделать похожими распределения &amp;lt;math&amp;gt;E_{z~Q}P(X|z)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;P(X)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим следующую дивергенцию Кульбака-Лейблера.&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z|X) − log P(z|X)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Распишем &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;P(X|z) * P(z) / P(X)&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z) − log P(X|z) - log P(z)] + log P(X)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Что эквивалентно:&lt;br /&gt;
:&amp;lt;math&amp;gt;logP(x) - D[Q(z)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим эту штуку для &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;, тогда:&lt;br /&gt;
:&amp;lt;math&amp;gt;logP(x) - D[Q(z|X)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z|X)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посмотрим, на это равенство. Правую часть мы можем оптимизировать градиентным спуском (пусть пока и не совсем понятно как).&lt;br /&gt;
В левой же части первое слагаемое -- то, что мы хотим максимизировать. В то же время &amp;lt;math&amp;gt;D[Q(z|X)||P(z|X)]&amp;lt;/math&amp;gt; мы хотим минимизировать. Если у нас &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt; -- достаточно сильная модель, то в какой-то модель она будет хорошо матчить &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt;, а значит их дивергенция Кульбака-Лейблера будет почти 0. А значит на это слагаемое можно забить. И стараться максимизировать правую часть. В качестве бонуса мы еще получили более &amp;quot;поддатливую&amp;quot; &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt;, вместо нее можно смотреть на &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь разберемся как оптимизировать правую часть. Сначала нужно определиться с моделью для &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;. Обычно ее берут равной &amp;lt;math&amp;gt;N(z|\mu(X, \theta), \sigma(X, \theta))&amp;lt;/math&amp;gt;. Где &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\sigma&amp;lt;/math&amp;gt; какие-то детерминированные функции на X с обучаемыми параметрами &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, которые мы впредь будем опускать). Ага, нейронки. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно проверить, что для дивергенция Кульбака-Лейблера двух нормальных распределений имеет следующий вид.&lt;br /&gt;
:&amp;lt;math&amp;gt;D_{K}[N(\mu_1, \Sigma_0)||N(\mu_1, \Sigma_0)]&amp;lt;/math&amp;gt;, KLD есть &amp;lt;math&amp;gt;\frac{1}{2} (tr(\Sigma_1^{-1}\Sigma_0) + (\mu_1 - \mu_0)^T\Sigma_1^{-1}(\mu_1 - \mu_0) - k + log(\frac{det\Sigma_1}{det\Sigma_0})) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это значит, что&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z|X)||P(z)] = D[N(\mu(X), \Sigma(X))||N(0, I)] = \frac12 (tr(\Sigma(X)) + \mu(X)^T\mu(X) - k - log(det\Sigma(X)))&amp;lt;/math&amp;gt;. &lt;br /&gt;
Теперь здесь &lt;br /&gt;
можно считать градиенты, для BackPropagation. С первым слагаемым в правой части все немного сложнее. &amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)]&amp;lt;/math&amp;gt; мы можем считать методом Монте-Карло(МК), но тогда такая штука (из-за того, что переменные спрятаны в распределении, из которого мы генерируем себе выборку, для МК) не является гладкой относительно них, а значит непонятно, как проталкивать через это градиент. Для того, чтобы все-таки можно было протолкнуть градиент, применяется так называемый reparametrization trick, который базируется на простой формуле &amp;lt;math&amp;gt;N(\Sigma(X), \mu(X)) = \mu(X) + \Sigma^{\frac12}(X) * N(0, I) &amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)] = E_{\epsilon~N(0, I)}[log P(X = f(\mu(X) + \Sigma^{\frac12}(X) * \epsilon), \theta)]&amp;lt;/math&amp;gt;. &lt;br /&gt;
В такой форме мы уже можем использовать BackPropagation для переменных из функций &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следующая картинка лучше поможет осознать структуру VAE и, в частности, зачем нужен (и как работает) reparametrization trick.&lt;br /&gt;
&lt;br /&gt;
На левой части диаграмма без использования reparameterization trick. &lt;br /&gt;
На правой части диаграмма с использованием reparameterization trick. &lt;br /&gt;
&lt;br /&gt;
[[Файл:VAE.PNG]]&lt;br /&gt;
&lt;br /&gt;
взято из https://arxiv.org/pdf/1606.05908.pdf&lt;br /&gt;
&lt;br /&gt;
== Пример реализации ==&lt;br /&gt;
Ниже приведена реализация частного случая VAE на языке Python с использованием библиотеки Pytorch.&lt;br /&gt;
Эта реализация работает с датасетом MNIST.&lt;br /&gt;
Размерность скрытого слоя {{---}} 2. &lt;br /&gt;
Координаты в нем считаются независимыми (из-за этого, например, матрица &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; диагональная, и формула для расчета KLD немного другая).&lt;br /&gt;
&lt;br /&gt;
 class VariationalAutoencoder(nn.Module):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super().__init__()&lt;br /&gt;
        self.mu = nn.Linear(32, 2)&lt;br /&gt;
        self.gamma = nn.Linear(32, 2)&lt;br /&gt;
        self.encoder = nn.Sequential(nn.Linear(784, 32), nn.ReLU(True))&lt;br /&gt;
        self.decoder = nn.Sequential(nn.Linear(2, 32), nn.ReLU(True), nn.Linear(32, 784), nn.Sigmoid())&lt;br /&gt;
 &lt;br /&gt;
    def forward(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        x = self.decoder(encoding)&lt;br /&gt;
        return x, mu, gamma&lt;br /&gt;
 &lt;br /&gt;
    def reparameterize(self, mu, gamma):&lt;br /&gt;
        if self.training:&lt;br /&gt;
            sigma = torch.exp(0.5*gamma)&lt;br /&gt;
            std_z = Variable(torch.from_numpy(np.random.normal(0, 1, size=sigma.size())).float())&lt;br /&gt;
            encoding = std_z.mul(sigma).add(mu)&lt;br /&gt;
            return encoding&lt;br /&gt;
        else:&lt;br /&gt;
            return mu&lt;br /&gt;
 &lt;br /&gt;
    def encode(self, x):&lt;br /&gt;
        x = self.encoder(x)&lt;br /&gt;
        mu = self.mu(x)&lt;br /&gt;
        gamma = self.gamma(x)&lt;br /&gt;
        return mu, gamma&lt;br /&gt;
  &lt;br /&gt;
    def decode(self, x):&lt;br /&gt;
        return self.decoder(x)&lt;br /&gt;
 &lt;br /&gt;
    def latent(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        return encoding&lt;br /&gt;
 &lt;br /&gt;
 def loss_function(input, output, mu, gamma, batch_size=batch_size):&lt;br /&gt;
    BCE = F.binary_cross_entropy(output, input)&lt;br /&gt;
    KLD = -0.5*torch.sum(1 + gamma - mu.pow(2) - gamma.exp())&lt;br /&gt;
    KLD /= batch_size*784&lt;br /&gt;
    return BCE + KLD&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Область применения вариационных автокодировщиков совпадает с областью применения обыкновенных автокодировщиков. А именно:&lt;br /&gt;
* Каскадное обучение глубоких сетей (хотя сейчас применяется все реже, в связи с появлением новых методов инициализации весов)&lt;br /&gt;
* Уменьшение шума в данных&lt;br /&gt;
* Уменьшение размерности данных (иногда работает лучше, чем [[метод главных компонент]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Благодаря тому, что пользователь сам устанавливает нужное распределение скрытого вектора, вариационный кодировщик хорошо подходит для генерации новых объектов (например, картинок). Для этого достаточно разыграть скрытый вектор согласно его распределению и скормить ее в декодер. Получится объект из того же распределения, что и датасет.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
*[[:Автокодировщик|Автокодировщик]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt; &lt;br /&gt;
*[[:Generative Adversarial Nets (GAN)|Порождающие состязательные сети]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
*[https://habr.com/ru/post/429276/ Вариационные автокодировщики: теория и рабочий код]&lt;br /&gt;
*[https://jaan.io/what-is-variational-autoencoder-vae-tutorial/ Tutorial - What is a variational autoencoder?]&lt;br /&gt;
*[https://towardsdatascience.com/intuitively-understanding-variational-autoencoders-1bfe67eb5daf Intuitively Understanding Variational Autoencoders]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[https://arxiv.org/abs/1606.05908 Tutorial on Variational Autoencoders]&lt;br /&gt;
*Datalore презентация Дениса Степанова&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Порождающие модели]]&lt;/div&gt;</summary>
		<author><name>Aleksei.latyshev</name></author>	</entry>

	<entry>
		<id>https://nerc.itmo.ru/wiki/index.php?title=%D0%9C%D0%B0%D1%88%D0%B8%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5&amp;diff=69467</id>
		<title>Машинное обучение</title>
		<link rel="alternate" type="text/html" href="https://nerc.itmo.ru/wiki/index.php?title=%D0%9C%D0%B0%D1%88%D0%B8%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BE%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5&amp;diff=69467"/>
				<updated>2019-01-27T23:14:10Z</updated>
		
		<summary type="html">&lt;p&gt;Aleksei.latyshev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Машинное обучение]]&lt;br /&gt;
&lt;br /&gt;
=Общие понятия=&lt;br /&gt;
*[[Общие понятия]]&lt;br /&gt;
*[[Модель алгоритма и ее выбор]]&lt;br /&gt;
*[[Переобучение]]&lt;br /&gt;
*[[Кросс-валидация]]&lt;br /&gt;
*[[Выброс]]&lt;br /&gt;
&lt;br /&gt;
=Классификация и регрессия=&lt;br /&gt;
*[[Метрический классификатор и метод ближайших соседей]]&lt;br /&gt;
*[[Нейронные сети, перцептрон]]&lt;br /&gt;
*[[Дерево решений и случайный лес]]&lt;br /&gt;
*[[Логистическая регрессия]]&lt;br /&gt;
&lt;br /&gt;
=Кластеризация=&lt;br /&gt;
*[[Кластеризация]]&lt;br /&gt;
*[[Иерархическая кластеризация]]&lt;br /&gt;
*[[Оценка качества в задаче кластеризации]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Ансамбли=&lt;br /&gt;
*[[Виды ансамблей]]&lt;br /&gt;
*[[Бустинг, AdaBoost]]&lt;br /&gt;
*[[CatBoost]]&lt;br /&gt;
&lt;br /&gt;
=Глубокое обучение=&lt;br /&gt;
*[[Глубокое обучение]]&lt;br /&gt;
*[[Настройка глубокой сети]]&lt;br /&gt;
*[[Batch-normalization]]&lt;br /&gt;
*[[Практики реализации нейронных сетей]]&lt;br /&gt;
*[[Рекуррентные нейронные сети]]&lt;br /&gt;
==Сверточные сети==&lt;br /&gt;
*[[Сверточные нейронные сети]]&lt;br /&gt;
==Порождающие модели==&lt;br /&gt;
*[[Generative Adversarial Nets (GAN)]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Вариационный автокодировщик]]&lt;br /&gt;
==Обработка естественного языка==&lt;br /&gt;
*[[Распознавание речи]]&lt;br /&gt;
*[[Обработка естественного языка]]&lt;br /&gt;
&lt;br /&gt;
=Уменьшение размерности=&lt;br /&gt;
*[[Уменьшение размерности]]&lt;br /&gt;
&lt;br /&gt;
=Обучение с подкреплением=&lt;br /&gt;
*[[Обучение с подкреплением]]&lt;br /&gt;
*[[Методы policy gradient и алгоритм асинхронного актора-критика]]&lt;br /&gt;
&lt;br /&gt;
=Примеры кода=&lt;br /&gt;
*[[Обзор библиотек для машинного обучения на Python]]&lt;br /&gt;
*[[Примеры кода на Scala]]&lt;br /&gt;
&lt;br /&gt;
=В разработке=&lt;br /&gt;
*[[Мета-обучение]]&lt;br /&gt;
*[[Оценка качества в задачах классификации и регрессии]]&lt;br /&gt;
*[[Линейная регрессия]]&lt;br /&gt;
*[[Стохастический градиентный спуск ]]&lt;br /&gt;
*[[Задача нахождения объектов на изображении]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Neural Style Transfer]]&amp;lt;tex&amp;gt;^\star&amp;lt;/tex&amp;gt;&lt;br /&gt;
*[[Долгая краткосрочная память]]&lt;br /&gt;
*[[Метод опорных векторов (SVM)]]&lt;br /&gt;
*[[Байесовская классификация]]&lt;br /&gt;
*[[EM-алгоритм]]&lt;br /&gt;
*[[Ранжирование]]&lt;br /&gt;
*[[Рекомендательные системы]]&lt;br /&gt;
*[[Настройка гиперпараметров]]&lt;br /&gt;
*[[Активное обучение]]&lt;br /&gt;
*[[Примеры кода на R]]&lt;br /&gt;
*[[Примеры кода на Java]]&lt;br /&gt;
*[[Регуляризация]]&lt;br /&gt;
*[[Обратное распространение ошибки]]&lt;br /&gt;
*[[Порождающие модели]]&lt;br /&gt;
*[[Векторное представление слов]]&lt;br /&gt;
*[[Ядра]]&lt;br /&gt;
*[[Сегментация изображений]]&lt;br /&gt;
*[[XGBoost]]&lt;br /&gt;
*[[Известные наборы данных]]&lt;/div&gt;</summary>
		<author><name>Aleksei.latyshev</name></author>	</entry>

	<entry>
		<id>https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69464</id>
		<title>Вариационный автокодировщик</title>
		<link rel="alternate" type="text/html" href="https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69464"/>
				<updated>2019-01-27T23:10:59Z</updated>
		
		<summary type="html">&lt;p&gt;Aleksei.latyshev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Вариационный автокодировщик''' (англ. ''Variational Autoencoder'', ''VAE'') {{---}} это [[автокодировщик]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt; (a.k.a. генеративная модель, которая учится отображать объекты в заданное скрытое пространство (и обратно)) основанный на вариационном выводе.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Предпосылки ==&lt;br /&gt;
При попытке использования обыкновенного автокодировщика для генерации новых объектов (желательно из того же априорного распределения, что и датасет) возникает следующая проблема. Случайной величиной с каким распределением проинициализировать скрытые векторы, для того, чтобы картинка, после применения декодера, стала похожа на картинки из датасета, но при этом не совпадала ни с одной из них? Ответ на этот вопрос не ясен, в связи с тем, что обыкновенный автокодировщик не может ничего утверждать про распределение скрытого вектора и даже про его область определения. В частности, область определения может быть даже дискретной.&lt;br /&gt;
&lt;br /&gt;
Вариационный автокодировщик в свою очередь предлагает пользователю самому определить распределение скрытого вектора. &lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
'''Порождающее моделирование''' (англ. ''Generative modelling'') {{---}} область машинного обучения, имеющая дело с распределением &amp;lt;math&amp;gt;P(X)&amp;lt;/math&amp;gt;, определенном на датасете &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; из пространства (возможно многомерного) &amp;lt;math&amp;gt;\Chi&amp;lt;/math&amp;gt;. Так, например, популярные задачи генерации картинок имеют дело с огромным количеством измерений (пикселей). &lt;br /&gt;
&lt;br /&gt;
Также как и в обыкновенных кодировщиках у нас имеется скрытое вероятностное пространство &amp;lt;math&amp;gt;Z&amp;lt;/math&amp;gt; соответствующее случайной величине &amp;lt;math&amp;gt;(z, P(z))&amp;lt;/math&amp;gt; (распределенной как-нибудь фиксированно, здесь &amp;lt;math&amp;gt;~N(0, 1)&amp;lt;/math&amp;gt;). И мы хотим иметь декодер &amp;lt;math&amp;gt;f(z, \theta) \colon Z \times \Theta \to \Chi &amp;lt;/math&amp;gt;. При этом мы хотим найти такие &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, чтобы после разыгрывания &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; по &amp;lt;math&amp;gt;P(z)&amp;lt;/math&amp;gt; мы получили &amp;quot;что-то похожее&amp;quot; на элементы &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Вообще, мы хотим, чтобы для любого &amp;lt;math&amp;gt;x \in X&amp;lt;/math&amp;gt; мы хотим считать &amp;lt;math&amp;gt;P(x) = \int P(x|z; \theta)P(z)dz&amp;lt;/math&amp;gt; здесь мы заменили &amp;lt;math&amp;gt;f(x, \theta)&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt;, чтобы явно сделать зависимость между &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; и после этого применить формулу полной вероятности. Обычно &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt; около нуля почти для всех пар &amp;lt;math&amp;gt;(x, z)&amp;lt;/math&amp;gt;. Основная идея в том, что мы хотим теперь генерировать &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt;, который бы давали что-то около x и только их суммировать в &amp;lt;math&amp;gt;P(x)&amp;lt;/math&amp;gt;. Для этого нам требуется ввести еще одно распределение &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;, которое будет получать x и говорить распределение на &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; которое наиболее вероятно будет генерировать нам такой &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;. Теперь нам нужно как-то сделать похожими распределения &amp;lt;math&amp;gt;E_{z~Q}P(X|z)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;P(X)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим следующую дивергенцию Кульбака-Лейблера.&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z|X) − log P(z|X)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Распишем &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;P(X|z) * P(z) / P(X)&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z) − log P(X|z) - log P(z)] + log P(X)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Что эквивалентно:&lt;br /&gt;
:&amp;lt;math&amp;gt;logP(x) - D[Q(z)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим эту штуку для &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;, тогда:&lt;br /&gt;
:&amp;lt;math&amp;gt;logP(x) - D[Q(z|X)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z|X)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посмотрим, на это равенство. Правую часть мы можем оптимизировать градиентным спуском (пусть пока и не совсем понятно как).&lt;br /&gt;
В левой же части первое слагаемое -- то, что мы хотим максимизировать. В то же время &amp;lt;math&amp;gt;D[Q(z|X)||P(z|X)]&amp;lt;/math&amp;gt; мы хотим минимизировать. Если у нас &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt; -- достаточно сильная модель, то в какой-то модель она будет хорошо матчить &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt;, а значит их дивергенция Кульбака-Лейблера будет почти 0. А значит на это слагаемое можно забить. И стараться максимизировать правую часть. В качестве бонуса мы еще получили более &amp;quot;поддатливую&amp;quot; &amp;lt;math&amp;gt;P(z|X)&amp;lt;/math&amp;gt;, вместо нее можно смотреть на &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь разберемся как оптимизировать правую часть. Сначала нужно определиться с моделью для &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt;. Обычно ее берут равной &amp;lt;math&amp;gt;N(z|\mu(X, \theta), \sigma(X, \theta))&amp;lt;/math&amp;gt;. Где &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\sigma&amp;lt;/math&amp;gt; какие-то детерминированные функции на X с обучаемыми параметрами &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, которые мы впредь будем опускать). Ага, нейронки. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно проверить, что для дивергенция Кульбака-Лейблера двух нормальных распределений имеет следующий вид.&lt;br /&gt;
:&amp;lt;math&amp;gt;D_{K}[N(\mu_1, \Sigma_0)||N(\mu_1, \Sigma_0)]&amp;lt;/math&amp;gt;, KLD есть &amp;lt;math&amp;gt;\frac{1}{2} (tr(\Sigma_1^{-1}\Sigma_0) + (\mu_1 - \mu_0)^T\Sigma_1^{-1}(\mu_1 - \mu_0) - k + log(\frac{det\Sigma_1}{det\Sigma_0})) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это значит, что&lt;br /&gt;
:&amp;lt;math&amp;gt;D[Q(z|X)||P(z)] = D[N(\mu(X), \Sigma(X))||N(0, I)] = \frac12 (tr(\Sigma(X)) + \mu(X)^T\mu(X) - k - log(det\Sigma(X)))&amp;lt;/math&amp;gt;. &lt;br /&gt;
Теперь здесь &lt;br /&gt;
можно считать градиенты, для BackPropagation. С первым слагаемым в правой части все немного сложнее. &amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)]&amp;lt;/math&amp;gt; мы можем считать методом Монте-Карло(МК), но тогда такая штука (из-за того, что переменные спрятаны в распределении, из которого мы генерируем себе выборку, для МК) не является гладкой относительно них, а значит непонятно, как проталкивать через это градиент. Для того, чтобы все-таки можно было протолкнуть градиент, применяется так называемый reparametrization trick, который базируется на простой формуле &amp;lt;math&amp;gt;N(\Sigma(X), \mu(X)) = \mu(X) + \Sigma^{\frac12}(X) * N(0, I) &amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)] = E_{\epsilon~N(0, I)}[log P(X = f(\mu(X) + \Sigma^{\frac12}(X) * \epsilon), \theta)]&amp;lt;/math&amp;gt;. &lt;br /&gt;
В такой форме мы уже можем использовать BackPropagation для переменных из функций &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следующая картинка лучше поможет осознать структуру VAE и, в частности, зачем нужен (и как работает) reparametrization trick.&lt;br /&gt;
&lt;br /&gt;
На левой части диаграмма без использования reparameterization trick. &lt;br /&gt;
На правой части диаграмма с использованием reparameterization trick. &lt;br /&gt;
&lt;br /&gt;
[[Файл:VAE.PNG]]&lt;br /&gt;
&lt;br /&gt;
взято из https://arxiv.org/pdf/1606.05908.pdf&lt;br /&gt;
&lt;br /&gt;
== Пример реализации ==&lt;br /&gt;
Ниже приведена реализация частного случая VAE на языке Python с использованием библиотеки Pytorch.&lt;br /&gt;
Эта реализация работает с датасетом MNIST.&lt;br /&gt;
Размерность скрытого слоя {{---}} 2. &lt;br /&gt;
Координаты в нем считаются независимыми (из-за этого, например, матрица &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; диагональная, и формула для расчета KLD немного другая).&lt;br /&gt;
&lt;br /&gt;
 class VariationalAutoencoder(nn.Module):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super().__init__()&lt;br /&gt;
        self.mu = nn.Linear(32, 2)&lt;br /&gt;
        self.gamma = nn.Linear(32, 2)&lt;br /&gt;
        self.encoder = nn.Sequential(nn.Linear(784, 32), nn.ReLU(True))&lt;br /&gt;
        self.decoder = nn.Sequential(nn.Linear(2, 32), nn.ReLU(True), nn.Linear(32, 784), nn.Sigmoid())&lt;br /&gt;
 &lt;br /&gt;
    def forward(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        x = self.decoder(encoding)&lt;br /&gt;
        return x, mu, gamma&lt;br /&gt;
 &lt;br /&gt;
    def reparameterize(self, mu, gamma):&lt;br /&gt;
        if self.training:&lt;br /&gt;
            sigma = torch.exp(0.5*gamma)&lt;br /&gt;
            std_z = Variable(torch.from_numpy(np.random.normal(0, 1, size=sigma.size())).float())&lt;br /&gt;
            encoding = std_z.mul(sigma).add(mu)&lt;br /&gt;
            return encoding&lt;br /&gt;
        else:&lt;br /&gt;
            return mu&lt;br /&gt;
 &lt;br /&gt;
    def encode(self, x):&lt;br /&gt;
        x = self.encoder(x)&lt;br /&gt;
        mu = self.mu(x)&lt;br /&gt;
        gamma = self.gamma(x)&lt;br /&gt;
        return mu, gamma&lt;br /&gt;
  &lt;br /&gt;
    def decode(self, x):&lt;br /&gt;
        return self.decoder(x)&lt;br /&gt;
 &lt;br /&gt;
    def latent(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        return encoding&lt;br /&gt;
 &lt;br /&gt;
 def loss_function(input, output, mu, gamma, batch_size=batch_size):&lt;br /&gt;
    BCE = F.binary_cross_entropy(output, input)&lt;br /&gt;
    KLD = -0.5*torch.sum(1 + gamma - mu.pow(2) - gamma.exp())&lt;br /&gt;
    KLD /= batch_size*784&lt;br /&gt;
    return BCE + KLD&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Область применения вариационных автокодировщиков совпадает с областью применения обыкновенных автокодировщиков. А именно:&lt;br /&gt;
* Каскадное обучение глубоких сетей (хотя сейчас применяется все реже, в связи с появлением новых методов инициализации весов)&lt;br /&gt;
* Уменьшение шума в данных&lt;br /&gt;
* Уменьшение размерности данных (иногда работает лучше, чем [[метод главных компонент]]&amp;lt;sup&amp;gt;[на 27.01.19 не создан]&amp;lt;/sup&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Благодаря тому, что пользователь сам устанавливает нужное распределение скрытого вектора, вариационный кодировщик хорошо подходит для генерации новых объектов (например, картинок). Для этого достаточно разыграть скрытый вектор согласно его распределению и скормить ее в декодер. Получится объект из того же распределения, что и датасет.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
*[[:Автокодировщик|Автокодировщик]]&lt;br /&gt;
*[[:Generative Adversarial Nets (GAN)|Порождающие состязательные сети]]&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
*[https://habr.com/ru/post/429276/ Вариационные автокодировщики: теория и рабочий код]&lt;br /&gt;
*[https://jaan.io/what-is-variational-autoencoder-vae-tutorial/ Tutorial - What is a variational autoencoder?]&lt;br /&gt;
*[https://towardsdatascience.com/intuitively-understanding-variational-autoencoders-1bfe67eb5daf Intuitively Understanding Variational Autoencoders]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[https://arxiv.org/abs/1606.05908 Tutorial on Variational Autoencoders]&lt;br /&gt;
*Datalore презентация Дениса Степанова&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Порождающие модели]]&lt;/div&gt;</summary>
		<author><name>Aleksei.latyshev</name></author>	</entry>

	<entry>
		<id>https://nerc.itmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:VAE.PNG&amp;diff=69461</id>
		<title>Файл:VAE.PNG</title>
		<link rel="alternate" type="text/html" href="https://nerc.itmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:VAE.PNG&amp;diff=69461"/>
				<updated>2019-01-27T22:14:11Z</updated>
		
		<summary type="html">&lt;p&gt;Aleksei.latyshev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Aleksei.latyshev</name></author>	</entry>

	<entry>
		<id>https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69460</id>
		<title>Вариационный автокодировщик</title>
		<link rel="alternate" type="text/html" href="https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69460"/>
				<updated>2019-01-27T22:12:11Z</updated>
		
		<summary type="html">&lt;p&gt;Aleksei.latyshev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Вариационный автокодировщик''' (англ. ''Variational Autoencoder'', ''VAE'') {{---}} это [[автокодировщик]] (a.k.a. генеративная модель, которая учится отображать объекты в заданное скрытое пространство (и обратно)) основанный на вариационном выводе.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Предпосылки ==&lt;br /&gt;
При попытке использования обыкновенного автокодировщика для генерации новых объектов (желательно из того же априорного распределения, что и датасет) возникает следующая проблема. Случайной величиной с каким распределением проинициализировать скрытые векторы, для того, чтобы картинка, после применения декодера, стала похожа на картинки из датасета, но при этом не совпадала ни с одной из них? Ответ на этот вопрос не ясен, в связи с тем, что обыкновенный автокодировщик не может ничего утверждать про распределение скрытого вектора и даже про его область определения. В частности, область определения может быть даже дискретной.&lt;br /&gt;
&lt;br /&gt;
Вариационный автокодировщик в свою очередь предлагает пользователю самому определить распределение скрытого вектора. &lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
'''Генеративное моделирование''' (англ. ''Generative modelling'') {{---}} область машинного обучения, имеющая дело с распределением P(X), определенном на датасете X из пространства (возможно многомерного) &amp;lt;math&amp;gt;\Chi&amp;lt;/math&amp;gt;. Так, например, популярные задачи генерации картинок имеют дело с огромным количеством измерений (пикселей). &lt;br /&gt;
&lt;br /&gt;
Также как и в обыкновенных кодировщиках у нас имеется скрытое вероятностное пространство Z соответствующее случайной величине (z, P(z))(распределенной как-нибудь фиксированно, здесь ~N(0, 1)). И мы хотим иметь декодер &amp;lt;math&amp;gt;f(z, \theta) \colon Z \times \Theta \to \Chi &amp;lt;/math&amp;gt;. При этом мы хотим найти такие &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, чтобы после разыгрывания z по P(z) мы получили &amp;lt;&amp;lt;что-то похожее&amp;gt;&amp;gt; на элементы X. &lt;br /&gt;
Вообще, мы хотим, чтобы для любого &amp;lt;math&amp;gt;x \in X&amp;lt;/math&amp;gt; мы хотим считать &amp;lt;math&amp;gt;P(x) = \int P(x|z; \theta)P(z)dz&amp;lt;/math&amp;gt; здесь мы заменили &amp;lt;math&amp;gt;f(x, \theta)&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt;, чтобы явно сделать зависимость между x и z и после этого применить формулу полной вероятности. Обычно &amp;lt;math&amp;gt;P(x|z; \theta)&amp;lt;/math&amp;gt; около нуля почти для всех пар (x, z). Основная идея в том, что мы хотим теперь генерировать z, который бы давали что-то около x и только их суммировать в P(x). Для этого нам требуется ввести еще одно распределение Q(z|X), которое будет получать x и говорить распределение на z которое наиболее вероятно будет генерировать нам такой x. Теперь нам нужно как-то сделать похожими распределения &amp;lt;math&amp;gt;E_{z~Q}P(X|z)&amp;lt;/math&amp;gt; и P(X). Рассмотрим следующую дивергенцию Кульбака-Лейблера &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z|X) − log P(z|X)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Распишем P(z|X) как P(X|z) * P(z) / P(X):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D[Q(z)||P(z|X)] = E_{z∼Q} [log Q(z) − log P(X|z) - log P(z)] + log P(X)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Что эквивалентно:&lt;br /&gt;
&amp;lt;math&amp;gt;logP(x) - D[Q(z)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим эту штуку для Q(z|X), тогда:&lt;br /&gt;
&amp;lt;math&amp;gt;logP(x) - D[Q(z|X)||P(z|X)] = E_{z∼Q}[log P(X|z)] - D[Q(z|X)||P(z)]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Посмотрим, на это равенство. Правую часть мы можем оптимизировать градиентным спуском (пусть пока и не совсем понятно как).&lt;br /&gt;
В левой же части первое слагаемое -- то, что мы хотим максимизировать. В то же время &amp;lt;math&amp;gt;D [Q(z|X)||P(z|X)]&amp;lt;/math&amp;gt; мы хотим минимизировать. Если у нас Q(z|X) -- достаточно сильная модель, то в какой-то модель она будет хорошо матчить P(z|X), а значит их дивергенция Кульбака Лейблера будет почти 0. А значит на это слагаемое можно забить. И стараться максимизировать правую часть. В качестве бонуса мы еще получили более &amp;quot;поддатливую&amp;quot; P(z|X), вместо нее можно смотреть на Q(z|X).&lt;br /&gt;
&lt;br /&gt;
Теперь разберемся как оптимизировать правую часть. Сначала нужно определиться с &amp;lt;math&amp;gt;Q(z|X)&amp;lt;/math&amp;gt; обычно ее берут равной &amp;lt;math&amp;gt;N(z|\mu(X, \theta), \sigma(X, \theta))&amp;lt;/math&amp;gt;. Где &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\sigma&amp;lt;/math&amp;gt; какие-то детерминированные функции на X с обучаемыми параметрами &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, которые мы впредь будем опускать (ага, нейронки)). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно проверить, что для двух нормальных распределений с параметрами &amp;lt;math&amp;gt;D_{KL}[N(\mu_1, \Sigma_0)||N(\mu_1, \Sigma_0)]&amp;lt;/math&amp;gt;, KLD есть &amp;lt;math&amp;gt;\frac{1}{2} (tr(\Sigma_1^{-1}\Sigma_0) + (\mu_1 - \mu_0)^T\Sigma_1^{-1}(\mu_1 - \mu_0) - k + log(\frac{det\Sigma_1}{det\Sigma_0})) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Это значит, что &amp;lt;math&amp;gt;D[Q(z|X)||P(z)] = D[N(\mu(X), \Sigma(X))||N(0, I)] = \frac12 (tr(\Sigma(X)) + \mu(X)^T\mu(X) - k - log(det\Sigma(X)))&amp;lt;/math&amp;gt;. Теперь здесь можно считать градиенты, для BackProp-a. С первым слагаемым в правой части, все немного сложнее. E_{z∼Q}[log P(X|z)] мы можем считать методом монте-карло(МК), но тогда такая штука (из-за того, что переменные спрятаны в распределении, из которого мы генерируем себе выборку, для МК) не является гладкой, относительно их, а значит непонятно как проталкивать через это градиент. Для того, чтобы все-таки можно было протолкнуть градиент, применяется так называемый reparametrization trick, который базируется на простой формуле &amp;lt;math&amp;gt;N(\Sigma(X), \mu(X)) = \mu(X) + \Sigma^{\frac12}(X) * N(0, I) &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;E_{z∼Q}[log P(X|z)] = E_{\epsilon~N(0, I)}[log P(X = f(\mu(X) + \Sigma^{\frac12}(X) * \epsilon), \theta)]&amp;lt;/math&amp;gt;. В такой форме мы уже можем использовать BackPropagation для переменных из функций &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mu&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следующая картинка лучше поможет осознать структуру VAE и, в частности, зачем нужен (и как работает) reparametrization trick. &lt;br /&gt;
&lt;br /&gt;
== Пример реализации ==&lt;br /&gt;
Ниже приведена реализация частного случая VAE на языке Python с использованием библиотеки Pytorch.&lt;br /&gt;
Эта реализация работает с датасетом MNIST.&lt;br /&gt;
Размерность скрытого слоя {{---}} 2. &lt;br /&gt;
Координаты в нем считаются независимыми (из-за этого, например, матрица &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; диагональная, и формула для расчета KLD немного другая).&lt;br /&gt;
&lt;br /&gt;
 class VariationalAutoencoder(nn.Module):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super().__init__()&lt;br /&gt;
        self.mu = nn.Linear(32, 2)&lt;br /&gt;
        self.gamma = nn.Linear(32, 2)&lt;br /&gt;
        self.encoder = nn.Sequential(nn.Linear(784, 32), nn.ReLU(True))&lt;br /&gt;
        self.decoder = nn.Sequential(nn.Linear(2, 32), nn.ReLU(True), nn.Linear(32, 784), nn.Sigmoid())&lt;br /&gt;
 &lt;br /&gt;
    def forward(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        x = self.decoder(encoding)&lt;br /&gt;
        return x, mu, gamma&lt;br /&gt;
 &lt;br /&gt;
    def reparameterize(self, mu, gamma):&lt;br /&gt;
        if self.training:&lt;br /&gt;
            sigma = torch.exp(0.5*gamma)&lt;br /&gt;
            std_z = Variable(torch.from_numpy(np.random.normal(0, 1, size=sigma.size())).float())&lt;br /&gt;
            encoding = std_z.mul(sigma).add(mu)&lt;br /&gt;
            return encoding&lt;br /&gt;
        else:&lt;br /&gt;
            return mu&lt;br /&gt;
 &lt;br /&gt;
    def encode(self, x):&lt;br /&gt;
        x = self.encoder(x)&lt;br /&gt;
        mu = self.mu(x)&lt;br /&gt;
        gamma = self.gamma(x)&lt;br /&gt;
        return mu, gamma&lt;br /&gt;
  &lt;br /&gt;
    def decode(self, x):&lt;br /&gt;
        return self.decoder(x)&lt;br /&gt;
 &lt;br /&gt;
    def latent(self, x):&lt;br /&gt;
        mu, gamma = self.encode(x)&lt;br /&gt;
        encoding = self.reparameterize(mu, gamma)&lt;br /&gt;
        return encoding&lt;br /&gt;
 &lt;br /&gt;
 def loss_function(input, output, mu, gamma, batch_size=batch_size):&lt;br /&gt;
    BCE = F.binary_cross_entropy(output, input)&lt;br /&gt;
    KLD = -0.5*torch.sum(1 + gamma - mu.pow(2) - gamma.exp())&lt;br /&gt;
    KLD /= batch_size*784&lt;br /&gt;
    return BCE + KLD&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Область применения вариационных автокодировщиков совпадает с областью применения обыкновенных автокодировщиков. А именно:&lt;br /&gt;
* Каскадное обучение глубоких сетей (хотя сейчас применяется все реже, в связи с появлением новых методов инициализации весов)&lt;br /&gt;
* Уменьшение шума в данных&lt;br /&gt;
* Уменьшение размерности данных (иногда работает лучше, чем [[метод главных компонент]])&lt;br /&gt;
&lt;br /&gt;
Благодаря тому, что пользователь сам устанавливает нужное распределение скрытого вектора, вариационный кодировщик хорошо подходит для генерации новых объектов (например, картинок). Для этого достаточно разыграть скрытый вектор согласно его распределению и скормить ее в декодер. Получится объект из того же распределения, что и датасет.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;/div&gt;</summary>
		<author><name>Aleksei.latyshev</name></author>	</entry>

	<entry>
		<id>https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69401</id>
		<title>Вариационный автокодировщик</title>
		<link rel="alternate" type="text/html" href="https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69401"/>
				<updated>2019-01-25T23:13:21Z</updated>
		
		<summary type="html">&lt;p&gt;Aleksei.latyshev: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Вариационный автокодировщик''' (англ. ''Variational Autoencoder'', ''VAE'') {{---}} это [[автокодировщик]] (a.k.a. генеративная модель, которая учится отображать объекты в заданное скрытое пространство (и обратно)) основанный на вариационном выводе.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Предпосылки ==&lt;br /&gt;
При попытке использования обыкновенного автокодировщика для генерации новых объектов (желательно из того же априорного распределения, что и датасет) возникает следующая проблема. Случайной величиной с каким распределением проинициализировать скрытые векторы, для того, чтобы картинка, после применения декодера, стала похожа на картинки из датасета, но при этом не совпадала ни с одной из них? Ответ на этот вопрос не ясен, в связи с тем, что обыкновенный автокодировщик не может ничего утверждать про распределение скрытого вектора и даже про его область определения. В частности, область определения может быть даже дискретной.&lt;br /&gt;
&lt;br /&gt;
Вариационный автокодировщик в свою очередь предлагает пользователю самому определить распределение скрытого вектора. &lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
'''Генеративное моделирование''' (англ. ''Generative modelling'') {{---}} область машинного обучения, имеющая дело с распределением P(X), определенном на датасете X из пространства (возможно многомерного) &amp;lt;math&amp;gt;\Chi&amp;lt;/math&amp;gt;. Так, например, популярные задачи генерации картинок имеют дело с огромным количеством измерений (пикселей). &lt;br /&gt;
&lt;br /&gt;
Также как и в обыкновенных кодировщиках у нас имеется скрытое вероятностное пространство Z соответствующее случайной величине (z, P(z))(распределенной как-нибудь фиксированно, здесь ~N(0, 1)). И мы хотим иметь декодер &amp;lt;math&amp;gt;f(z, \theta) \colon Z \times \Theta \to \Chi &amp;lt;/math&amp;gt;. При этом мы хотим найти такие &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, чтобы после разыгрывания z по P(z) мы получили &amp;lt;&amp;lt;что-то похожее&amp;gt;&amp;gt; на элементы X.&lt;br /&gt;
TODO:&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Область применения вариационных автокодировщиков совпадает с областью применения обыкновенных автокодировщиков. А именно:&lt;br /&gt;
* Каскадное обучение глубоких сетей (хотя сейчас применяется все реже, в связи с появлением новых методов инициализации случайными весами)&lt;br /&gt;
* Уменьшение шума в данных&lt;br /&gt;
* Уменьшение размерности данных (иногда работает лучше, чем [[метод главных компонент]])&lt;br /&gt;
&lt;br /&gt;
Благодаря тому, что пользователь сам устанавливает нужное распределение скрытого вектора, вариационный кодировщик хорошо подходит для генерации новых объектов (например, картинок). Для этого достаточно разыграть скрытый вектор согласно его распределению и скормить ее в декодер. Получится объект из того же распределения, что и датасет.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;/div&gt;</summary>
		<author><name>Aleksei.latyshev</name></author>	</entry>

	<entry>
		<id>https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69383</id>
		<title>Вариационный автокодировщик</title>
		<link rel="alternate" type="text/html" href="https://nerc.itmo.ru/wiki/index.php?title=%D0%92%D0%B0%D1%80%D0%B8%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA&amp;diff=69383"/>
				<updated>2019-01-25T22:52:36Z</updated>
		
		<summary type="html">&lt;p&gt;Aleksei.latyshev: Новая страница: «'''Вариационный автокодировщик''' (англ. ''Variational Autoencoder'', ''VAE'') {{---}} это автокодировщик (a.k.…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Вариационный автокодировщик''' (англ. ''Variational Autoencoder'', ''VAE'') {{---}} это [[автокодировщик]] (a.k.a. генеративная модель, которая учится отображать объекты в заданное скрытое пространство (и обратно)) основанный на вариационном выводе.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Предпосылки ==&lt;br /&gt;
При попытке использования обыкновенного автокодировщика для генерации новых объектов (желательно из того же априорного распределения, что и датасет) возникает следующая проблема. Случайной величиной с каким распределением проинициализировать скрытые векторы, для того, чтобы картинка, после применения декодера, стала похожа на картинки из датасета, но при этом не совпадала ни с одной из них? Ответ на этот вопрос не ясен, в связи с тем, что обыкновенный автокодировщик не может ничего утверждать про распределение скрытого вектора и даже про его область определения. В частности, область определения может быть даже дискретной.&lt;br /&gt;
&lt;br /&gt;
Вариационный автокодировщик в свою очередь предлагает пользователю самому определить распределение скрытого вектора. &lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
'''Генеративное моделирование''' (англ. ''Generative modelling'') {{---}} область машинного обучения, имеющая дело с распределением P(X), определенном на датасете X из пространства (возможно многомерного) &amp;lt;math&amp;gt;\Chi&amp;lt;/math&amp;gt;. Так, например, популярные задачи генерации картинок имеют дело с огромным количеством измерений (пикселей). &lt;br /&gt;
&lt;br /&gt;
Также как и в обыкновенных кодировщиках у нас имеется скрытое вероятностное пространство Z соответствующее случайной величине (z, P(z))(распределенной как-нибудь фиксированно, здесь ~N(0, 1)). И мы хотим иметь декодер &amp;lt;math&amp;gt;f(z, \theta) \colon Z \times \Theta \to \Chi &amp;lt;/math&amp;gt;. При этом мы хотим найти такие &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, чтобы после разыгрывания z по P(z) мы получили &amp;lt;&amp;lt;что-то похожее&amp;gt;&amp;gt; на элементы X.&lt;br /&gt;
TODO:&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Область применения вариационных автокодировщиков совпадает с областью применения обыкновенных автокодировщиков. А именно:&lt;br /&gt;
* Каскадное обучение глубоких сетей (хотя сейчас применяется все реже, в связи с появлением новых методов инициализации случайными весами)&lt;br /&gt;
* Уменьшение шума в данных&lt;br /&gt;
* Уменьшение размерности данных (иногда работает лучше, чем [[метод главных компонент]])&lt;br /&gt;
&lt;br /&gt;
Благодаря тому, что пользователь сам устанавливает нужное распределение скрытого вектора, вариационный кодировщик хорошо подходит для генерации новых объектов (например, картинок). Для этого достаточно разыграть скрытый вектор согласно его распределению и скормить ее в декодер. Получится объект из того же распределения, что и датасет.&lt;/div&gt;</summary>
		<author><name>Aleksei.latyshev</name></author>	</entry>

	</feed>