Из-за избытка блогов на этой странице сегодня я решил добавить еще один в список. Мы будем говорить о различных терминах, таких как автоэнкодеры и вариационные автоэнкодеры, и, наконец, о реализации последнего. Итак, вы, возможно, слышали о сжатии данных, верно? Это означает не что иное, как шифрование данных в той или иной форме, которая потребляет меньше памяти и способна при необходимости восстановить почти все из них. Можем ли мы сделать это с помощью машинного обучения? Очевидно, что можем, и вот настало время поговорить об автоэнкодерах. Итак, давайте начнем с нашего нового блога.

Что такое автоэнкодер?

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

Часть кодировщика и декодера может быть чем угодно, например нейронной сетью с прямой связью, сверточной сетью или стеком LSTM или GRU в зависимости от нашего варианта использования. На приведенном выше рисунке x — это входные данные, z — сжатый вектор признаков, а x’ — регенерированные входные данные.

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

Вариационный автоэнкодер — это не что иное, как вариант архитектуры, которую мы обсуждали выше. Так чем же он отличается от обычного автоэнкодера? Да, вы правильно поняли (слово ВАРИАЦИОННЫЙ). Вариационный автоэнкодер не только изучает представление данных, но также изучает параметры распределения данных, что делает его более функциональным, чем автоэнкодер, поскольку его можно использовать для создания новых выборок из заданной области. Именно это делает вариационный автоэнкодер генеративной моделью. Архитектура модели следующая:

Поскольку вариационный автоэнкодер является вероятностной моделью, мы стремимся изучить здесь распределение скрытого пространства (представление признаков). Обычный автоэнкодер очень склонен к переоснащению, поскольку он пытается сопоставить данные в одном векторе признаков, и небольшое изменение во входных данных может сильно изменить вектор признаков. Чтобы решить эту проблему, нам нужно использовать какую-то регуляризацию, которая ограничивает изученное распределение, чтобы оно было далеко друг от друга (минимизирует ковариацию скрытых распределений). Поэтому мы предполагаем, что распределения близки к нормальному распределению (среднее значение = 0 и дисперсия = 1).

Теперь мы можем обсудить функцию потерь вариационного автоэнкодера. Он состоит из двух терминов:

  1. потеря реконструкции, которая в основном объясняет регенерацию входных данных
  2. потеря расхождения KL, которая пытается уменьшить разрыв между распределениями, полученными с помощью нормального распределения.

Потеря дивергенции KL может быть получена следующим образом:

Потери при реконструкции могут быть любыми потерями, используемыми для контролируемых алгоритмов, таких как логарифмическая потеря или среднеквадратическая потеря. Общие потери представляют собой сумму потерь реконструкции и потерь расхождения KL.

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

  1. предсказать среднее значение и дисперсию скрытого пространства
  2. выборка точки из полученного распределения в качестве вектора признаков
  3. использовать точку выборки для восстановления ввода
  4. обратное распространение потери для обновления параметров модели

Хотите создать свой собственный VAE

Теперь, когда у нас есть представление о том, что такое автоэнкодеры и вариационные автоэнкодеры, давайте реализуем вариационный автоэнкодер, используя Tensorflow и Keras:

Необходимый импорт

import tensorflow.keras as keras
import tensorflow as tf
import numpy as np
import keras.layers as L
import keras.backend as K

Класс выборки

class sampling(L.Layer):
    def __init__(self, intdim, **kwargs):
        self.intdim = intdim
        super(sampling, self).__init__(**kwargs)

    def call(self, args):
        z_mean, z_log_sigma = args
        batch_size = tf.shape(z_mean)[0]
        epsilon = K.random_normal(shape=(batch_size, self.intdim),
                                  mean=0., stddev=1)
        return z_mean + z_log_sigma * epsilon

    def compute_output_shape(self, input_shape):
        return input_shape[0]

    def get_config(self):
        config={'intdim':self.intdim}
        return config

Класс вариационного автоэнкодера

class VAutoEnc():
    def __init__(self, featurelen, intdim):
        self.vocab_len = vocab_len
        self.featurelen = feature_len
        self.intdim = intdim
        self.sample = self.sampling(self.intdim)
        self.model = self.RetGraph()


    def RetGraph(self):
        encinp = L.Input(shape=(self.featurelen,1), dtype='float64')
        
        l = L.Dense(self.intdim)(encinp)

        mean = L.Dense(self.intdim)(encinp)
        log_sigma = L.Dense(self.intdim)(encinp)

        z   = self.sample([mean, log_sigma])

        out = self.Dense(self.featurelen)(z)
        
        meansigma = L.concatenate([mean, log_sigma], name='meansigma')



        model = keras.models.Model(encinp, [z_l, meansigma])

        return model


    def recloss(self):
        def loss1(y_true, y_pred):
            reconstruct_loss = tf.keras.losses.MSE(y_pred, y_true)
            return reconstruct_loss
        return loss1

    def vaeloss(self):
        def loss2(y_true, y_pred):
            mean = y_pred[:,0:self.intdim]
            log_sigma = y_pred[:, self.intdim:]
            kl_loss = -0.5*K.mean(1+log_sigma-K.square(mean)-K.exp(log_sigma))
            return kl_loss

Код очень прост и понятен, где мы берем входной вектор размера featurelen и кодируем его в скрытый вектор длины intdim. Потери реконструкции и KL определяются отдельно. Определен другой слой выборки для выборки данных с использованием среднего значения и дисперсии распределения.

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

Первоначально опубликовано на https://spraphul.github.io 29 марта 2020 г.