Генеративные ИИ-движки — Часть II

Подробное погружение в генеративные компоненты GenAI

Индекс

Парадигмы генеративной модели

  • Вариационные автоэнкодеры (VAE)
  • Генеративно-состязательные сети (GAN)
  • авторегрессия
  • Нормализация моделей потока
  • Модели на основе энергии
  • Диффузионные модели

Другие парадигмы GenAI

Заключение

Парадигмы генеративной модели

В пространстве генеративной модели существует огромное количество творчества. Я имею в виду не то, что генерируют модели, а существующие архитектуры моделей, увлекательную науку, поддерживающую теорию, и умные реализации. Честно говоря, это что-то вроде Дикого Запада с точки зрения причин, почему тот или иной модельный подход работает. Это область активных исследований, созревшая для научно обоснованных, но острых и новых подходов. Давайте углубимся в некоторые из текущих парадигм модели GenAI.

1. Вариационные автоэнкодеры (ВАЭ)

"бумага"

VAE — это вероятностные модели, которые пытаются взять сложное пространство распределения и сопоставить его с простым пространством распределения с нормальным единичным распределением. Из нормального распределения очень легко делать выборки. VAE состоят из двух основных компонентов: кодера и декодера. Архитектура кодировщика-декодера может быть любым примитивом нейронной сети (плотным, CNN и т. д.). Кодер отображает входные данные в скрытое пространство меньшей размерности, а декодер восстанавливает исходные данные из представления скрытого пространства.

На рисунке ниже показан пример архитектуры VAE. Обратите внимание, что кодировщик выводит множество нормальных распределений (μ и σ). Каждое распределение представляет собой особенность изображения. Например, первое распределение может представлять, насколько солнечна сцена на изображении, второе распределение может представлять высоту горы и так далее.

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

Генеративным двигателем VAE является скрытое пространство (узкое место μ и σ) и методология выборки.

На практике это помогает математике, если мы предположим, что сеть фактически выводит журнал дисперсии. Ниже приведен пример выходных данных кодировщика (μ и log(var)), для скрытого пространства размера n (количество распределений).

n = 5 #number of distributions
x = layers.Flatten()(x) # x is output from encoder
mean = layers.Dense(n)(x) # layer computes the mean vector 
log_var = layers.Dense(n)(x) # layer computes log variance vector 
sampled_vector = Sampling()([mean, log_var]) # sample from distribution 

По соглашению скрытые векторы обозначаются буквой z. Для выборки из среднего значения и log(var) уровень выборки использует случайный множитель эпсилон для имитации случайной выборки. Этот механизм также является уловкой репараметризации, которая позволяет градиентному потоку во время обратного распространения (ознакомьтесь с документом OG). Результат — это просто выборка из нормального распределения.

class Sampling(layers.Layer):
  def call(self, inputs):
          z_mean, z_log_var = inputs
          batch = tf.shape(z_mean)[0]
          dim = tf.shape(z_mean)[1]
          epsilon = tf.random.normal(shape=(batch, dim))
          return z_mean + tf.exp(0.5 * z_log_var) * epsilon

2. Генеративно-состязательные сети (GAN):

бумага, керасовые условные GAN

GAN состоят из двух нейронных сетей: генератора и дискриминатора. Генератор нацелен на создание реалистичных семплов и работает очень похоже на декодер в VAE. Ввод в генератор аналогичен вводу дискретизированного вектора в декодер в VAE. Дискриминатор пытается различать настоящие и сгенерированные (фальшивые) образцы и работает очень похоже на кодировщик в автоэнкодере, но выдает 0 или 1. Эти сети участвуют в процессе конкурентного обучения, где цель генератора — обмануть дискриминатор. и дискриминатор улучшает свою способность различать настоящие и поддельные образцы. Благодаря этому состязательному обучению GAN могут генерировать очень убедительные результаты, такие как фотореалистичные изображения или реалистичный текст.

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

random_latent_vectors = tf.random.normal(shape=(batch_size, latent_dim))

Случайный вектор похож на пластилин для детей, это отправная точка для генератора, чтобы построить что-то интересное, соответствующее реальности (данные для обучения).

3. Авторегрессия

RNN и LSTM, PixelNet, Transformers, GPT

Авторегрессионные модели — это статистические модели, которые предсказывают вероятность следующего элемента в последовательности на основе всех предыдущих элементов. Вектор вероятности - это размер словарного запаса. Например, в предложении «Золотой эль летом ___» авторегрессионная модель может предсказать слово «день» как наиболее вероятное слово на пустом месте. Чтобы сделать его авторегрессивным, модель затем передаст всю строку в качестве входных данных для следующей итерации, чтобы предсказать следующее слово, а затем следующее и т. д.

По умолчанию авторегрессионные модели на самом деле являются детерминированными (негенеративными). Чтобы выбрать правильное слово, модель выбирает наиболее вероятное слово на основе всех предыдущих слов.

Чтобы сделать эти модели генеративными, был добавлен метод выборки для выборки из полного словаря слов. GPT (генеративные предварительно обученные преобразователи) используют температурный параметр для управления степенью стохастичности (случайности) в модели. Во всех предыдущих случаях, которые мы видели до сих пор, выборка обычно выполняется с нормальным распределением. Для авторегрессионного генеративного случая выборка выполняется с предопределенными вероятностями на основе выходных данных модели. Чтобы предсказать следующее слово в приведенном ниже предложении, модель выводит вектор вероятностей, равный размеру полного словаря. Допустим, словарный запас состоит всего из 3 слов ["день", "ночь", "луна"] со следующими вероятностями [0,3, 0,1, 0,05]. Со слоем выборки модель будет вести себя следующим образом:

«Золотой эль на летнем ___» — модель предсказывает «день» в 30% случаев, «ночь» в 10% случаев и «луну» в 5% случаев.

Параметр температуры управляет стохастичностью вывода (0 = детерминированный, 1 = стохастический / случайный / генеративный).

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

Генеративным механизмом для авторегрессионных моделей является методология выборки поверх архитектуры детерминированной модели.

def sample_probabilities(vocab_probs, temperature):
  vocab_probs= vocab_probs** (1 / temperature)
  vocab_probs= vocab_probs/ np.sum(vocab_probs)
  return np.random.choice(len(vocab_probs), p=vocab_probs), vocab_probs

4. Нормализация моделей потока

Norm Flow UvA, RealNVP, GLOW, FFJORD

Подобно VAE, модели нормализующего потока (NFM) также пытаются сопоставить сложные распределения исходных данных (комплексное вероятностное пространство) p (x) с нормальным единичным распределением в скрытом пространстве p (z). С нормальными единичными распределениями очень легко работать и делать выборки. Основная задача состоит в том, чтобы найти отображение обратно в исходное пространство данных. VAE сопоставляются с исходным распределением данных q(x|z), близким приближением к p(x|z), но не с истинным распределением вероятностей. Модель нормализующего потока использует несколько приемов линейной алгебры, чтобы сделать функцию отображения p(z|x) обратимой, поэтому она может отображать p(x) в p(z), а затем производить выборку из p(z) и находить соответствующие точки в p(x) с обратной функцией p(x|z) (не приближение). Как и в примере с VAE, каждая скрытая пространственная гауссова (нормальное распределение) представляет собой характеристику исходных данных (уровень солнца, высота горы и т. д.).

f(x) -> латентные_векторы и в обратном направлении f’(латентные_векторы) -> х

Нормализация моделей потоков интересна для изучения. Связующие слои являются ключевым компонентом NFM и требуют глубокого изучения для полного объяснения. В этом блоге основное внимание уделяется генеративным аспектам текущих генеративных моделей. В будущем я могу попробовать это в своем собственном руководстве по NFM, но сейчас, пожалуйста, обратитесь к Учебнику UvA для более подробного ознакомления.

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

RealNVP — это одна из реализаций NFM. Обычное скрытое пространство инициализируется с помощью переменной distribution в приведенном ниже примере кода. Он используется в функции log_loss для вычисления логарифмической вероятности, которая просто измеряет, насколько далеко от нормального распределения находится текущий прогноз. Во время обучения потери вычисляются повторно, пока модель не начнет предсказывать значения, очень похожие на нормальное распределение.

distribution = tfp.distributions.MultivariateNormalDiag(
            loc=[0.0, 0.0], scale_diag=[1.0, 1.0]
        )

При выводе, когда вызывается model.predict(), модель RealNVP за кулисами запускает функцию call(x) с обратным направлением (направление = 1). Модель генерирует новые данные, начиная с нормальных распределений, преобразуя нормальные распределения в течение ряда шагов, пока они не будут отображены обратно в исходное пространство данных.

samples = model.distribution.sample(3000)
x, _ = model.predict(samples)

Код взят из реализации Keras RealNVP.

class RealNVP(keras.Model):
    def __init__(self, num_coupling_layers):
        super().__init__()

        self.num_coupling_layers = num_coupling_layers

        # Distribution of the latent space.
        self.distribution = tfp.distributions.MultivariateNormalDiag(
            loc=[0.0, 0.0], scale_diag=[1.0, 1.0]
        )
        self.masks = np.array(
            [[0, 1], [1, 0]] * (num_coupling_layers // 2), dtype="float32"
        )
        self.loss_tracker = keras.metrics.Mean(name="loss")
        self.layers_list = [Coupling(2) for i in range(num_coupling_layers)]

    @property
    def metrics(self):
        """List of the model's metrics.

        We make sure the loss tracker is listed as part of `model.metrics`
        so that `fit()` and `evaluate()` are able to `reset()` the loss tracker
        at the start of each epoch and at the start of an `evaluate()` call.
        """
        return [self.loss_tracker]

    def call(self, x, training=True):
        log_det_inv = 0
        direction = 1
        if training:
            direction = -1
        for i in range(self.num_coupling_layers)[::direction]:
            x_masked = x * self.masks[i]
            reversed_mask = 1 - self.masks[i]
            s, t = self.layers_list[i](x_masked)
            s *= reversed_mask
            t *= reversed_mask
            gate = (direction - 1) / 2
            x = (
                reversed_mask
                * (x * tf.exp(direction * s) + direction * t * tf.exp(gate * s))
                + x_masked
            )
            log_det_inv += gate * tf.reduce_sum(s, [1])

        return x, log_det_inv

    # Log likelihood of the normal distribution plus the log determinant of the jacobian.

    def log_loss(self, x):
        y, logdet = self(x)
        log_likelihood = self.distribution.log_prob(y) + logdet
        return -tf.reduce_mean(log_likelihood)

    def train_step(self, data):
        with tf.GradientTape() as tape:

            loss = self.log_loss(data)

        g = tape.gradient(loss, self.trainable_variables)
        self.optimizer.apply_gradients(zip(g, self.trainable_variables))
        self.loss_tracker.update_state(loss)

        return {"loss": self.loss_tracker.result()}

    def test_step(self, data):
        loss = self.log_loss(data)
        self.loss_tracker.update_state(loss)

        return {"loss": self.loss_tracker.result()}

Модели на основе энергии

Документ о моделях на основе энергии, Модели на основе энергии UvA, Контрастная дивергенция, Учебник Яна Лекуна

Модели на основе энергии (EBM) используют контрастное расхождение во время обучения, чтобы неявно оценить плотность базовых данных, в то время как модели VAE и Normalizing Flow изучают плотность данных явно. EBM лучше всего понять на примерах, потому что модели EBM используют энергию как аналогию подобия. EBM обучены выдавать низкие баллы за вероятные наблюдения, подумайте о стабильных системах с низким энергопотреблением. Сеть обучена выдавать высокие баллы за маловероятные наблюдения, подумайте о нестабильных системах с возбужденным энергетическим состоянием. В термодинамике системы предпочитают стабильное состояние, которое обычно означает низкоэнергетическое состояние. Высокоэнергетические состояния означают повышенную волатильность и неопределенность.

Вероятные и маловероятные наблюдения представляют собой специальность сети. Например, если сеть научится классифицировать изображения кошек, вероятное наблюдение = изображение кошки. С точки зрения вероятности энергия низка, когда p(x) = 1, вероятность того, что на картинке изображена кошка, и высока, когда p(x) = 0.

Запомнить

низкая энергия = стабильная система = вероятные наблюдения = высокая вероятность

высокая энергия = нестабильная система = маловероятные наблюдения = низкая вероятность

Алгоритм EBM для примера классификации изображения кошки:

Обучение

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

Контрастная потеря увеличивает оценку энергии между различными наблюдениями за счет обновления весов сети. Форма функции энергии регулируется таким образом, чтобы вероятные наблюдения имели более низкую энергию, а маловероятные наблюдения имели более высокую энергию.

Вывод

  1. Подайте изображение случайного шума в модель, уровень энергии/оценка будет очень высоким при первом проходе.
  2. Вычислите градиенты относительно пикселей изображения и обновите значение каждого пикселя в направлении уменьшения энергетического состояния. Обратите внимание, что это стохастический градиентный спуск во время вывода, он относится не к весу модели, а к каждому пикселю.
  3. Продолжайте обновлять изображение до тех пор, пока энергетическое состояние не станет низким, после чего изображение будет напоминать изображение кошки.

Во время вывода кривая изученной функции (веса модели) фиксируется, а значения x обновляются, чтобы снизить значение энергии.

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

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

# model input at inference - random noise image 
input_images = np.random.uniform(size = (10, 32, 32, 1)) * 2 - 1

Динамика Ланжевена — это алгоритм, который снижает уровень энергии ввода в течение ряда шагов до тех пор, пока удовлетворительные результаты не создадут новый набор изображений.

def langevin_sampler(model, images, steps, step_size):
    for _ in range(steps): 
        # add small amount of noise to the image 
        images+= tf.random.normal(images.shape, mean = 0, stddev = 0.005) 
        images= tf.clip_by_value(images, -1.0, 1.0)
        with tf.GradientTape() as tape:
            tape.watch(images)
            out_score = -model(images) 
        grads = tape.gradient(out_score, images) 
        grads = tf.clip_by_value(grads, -0.03, 0.03)
        images+= -step_size * grads 
        images= tf.clip_by_value(images, -1.0, 1.0)
    return images

Диффузионные модели

Keras Tutorial, бумага, обзор

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

В моделях диффузии есть два шага:

  1. График шума: при заданном входном изображении график шума добавляет шум в течение нескольких шагов, пока изображение не станет просто шумом, без информации. На данный момент глубокое обучение не реализовано, только конвейер преобразования данных. Изображения в каждой точке повреждения сохраняются для обучения.

2. Моделирование: архитектура U-Net берет зашумленное изображение и прогнозирует шум в изображении. Таким образом, шум может быть удален для следующего шага.

Мне нравится думать об этом следующим образом: представьте, что вы видите темную тень вдали, это может быть любое количество узнаваемых вещей, медведь или, может быть, пень. Чем ближе вы подходите к размытому объекту, тем более четким он становится, пока не становится ясно, что это просто старая шина.

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

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

Генеративный механизм, лежащий в основе диффузионных моделей, — это исходный ввод случайного шума, а дополнительный шум добавляется к прогнозам модели для повышения общей стохастичности модели. Способность U-Net медленно формировать случайный шум в форму, затем в объект, а затем в очень детализированный реалистично выглядящий объект.

Keras tutorial содержит красивый набор чистого кода и отличные примеры. Я буду использовать код из статьи Denoising and Diffusion, чтобы лучше выделить генеративные части модели. Бумажный код — это исследовательский код — запутанный и трудный для понимания, но он делает свою работу. Параметр self.num_timesteps определяет, сколько шагов распространения выполняется при выводе. Чем больше количество шагов диффузии, тем больше шагов снижения шума применяется к исходному шумовому изображению, тем чище будет конечный результат.

  def p_sample_loop(self, denoise_fn, *, shape, noise_fn=tf.random_normal):
    """
    Generate samples
    """
    assert isinstance(shape, (tuple, list))
    i_0 = tf.constant(self.num_timesteps - 1, dtype=tf.int32)
    
    # initial full noise image 
    img_0 = noise_fn(shape=shape, dtype=tf.float32)
    _, img_final = tf.while_loop(
      cond=lambda i_, _: tf.greater_equal(i_, 0),
      body=lambda i_, img_: [
        i_ - 1,
        self.p_sample(
          denoise_fn=denoise_fn, x=img_, t=tf.fill([shape[0]], i_), noise_fn=noise_fn, return_pred_xstart=False)
      ],
      loop_vars=[i_0, img_0],
      shape_invariants=[i_0.shape, img_0.shape],
      back_prop=False
    )
    assert img_final.shape == shape
    return img_final

Функция p_sample фактически выполняет подавление шума, поэтому давайте рассмотрим ее далее. Функция p_sample включает параметр t, который добавляет дополнительный шум к прогнозируемому шуму модели, что в целом добавляет стохастичности модели и может привести к более уникальным/новым результатам.

  def p_sample(self, denoise_fn, *, x, t, noise_fn, clip_denoised=True, return_pred_xstart: bool):
    """
    Sample from the model
    """
    model_mean, _, model_log_variance, pred_xstart = self.p_mean_variance(
      denoise_fn, x=x, t=t, clip_denoised=clip_denoised, return_pred_xstart=True)
    noise = noise_fn(shape=x.shape, dtype=x.dtype)
    assert noise.shape == x.shape
    # no noise when t == 0
    nonzero_mask = tf.reshape(1 - tf.cast(tf.equal(t, 0), tf.float32), [x.shape[0]] + [1] * (len(x.shape) - 1))
    sample = model_mean + nonzero_mask * tf.exp(0.5 * model_log_variance) * noise
    assert sample.shape == pred_xstart.shape
    return (sample, pred_xstart) if return_pred_xstart else sample

Другие парадигмы GenAI

Я рассмотрел несколько фундаментальных архитектур моделей, но будьте уверены, что на этом они не заканчиваются. Область AI/ML действительно развивается так быстро, что невозможно идти в ногу со всем последним и лучшим. Если у вас есть какие-то крутые модели архитектур/парадигм, которыми вы можете поделиться, или, возможно, вы хотите увидеть подробное объяснение в блоге, пожалуйста, оставьте примечание в комментариях.

На данный момент вот несколько более новых существующих архитектур в качестве почетных упоминаний: парадигма неавторегрессионной модели FlowSeq, низкое сопоставление с непрерывными нормализующими потоками (CNF), архитектура прогнозирования совместного внедрения (I-JEPA),

Заключение

Генеративный ИИ представляет собой захватывающий рубеж в области искусственного интеллекта, позволяя машинам проявлять творческий подход и создавать контент, выходящий за рамки простых прогнозов. Сила генеративных моделей заключается в функциональности и атрибутах модели:

Функциональность:

  1. Представление: модели учатся представлять сложные базовые распределения данных и структуры со скрытыми пространствами, весами моделей и распределениями вероятностей.
  2. Выборка: реализации модели включают методологии выборки, которые могут выбирать из изученных представлений исходных данных и создавать новые выходные данные, которые напоминают исходные данные.
  3. Стохастичность: реализации модели вводят стохастичность (случайность/шум) в выходные данные модели или промежуточные этапы генерации данных, чтобы привнести новизну в выходные данные и улучшить обучение.

Атрибуты:

  1. Новинка: выходные данные должны быть уникальными, новыми и оригинальными.
  2. Сходство: выходные данные модели должны напоминать обучающие данные.
  3. Организация элементов: генеративные модели организуют темы, элементы и функции по-новому, что соответствует желаемой функциональности модели.