Реализация бумаги VQ-VAE-2 - PullRequest
1 голос
/ 27 марта 2020

Я пытаюсь создать двухэтапный VQ-VAE-2 + PixelCNN, как показано в документе: «Создание разнообразных высококачественных изображений с VQ-VAE-2» (https://arxiv.org/pdf/1906.00446.pdf). У меня есть 3 вопроса реализации:

  1. В документе упоминается:

    Мы разрешаем каждому уровню в иерархии отдельно зависеть от пикселей.

Я понимаю, что второе скрытое пространство в VQ-VAE-2 должно быть обусловлено конкатенацией 1-го скрытого пространства и уменьшенной выборкой версии изображения. Это правильно?

В статье «Генерация условного изображения с помощью декодеров PixelCNN» (https://papers.nips.cc/paper/6527-conditional-image-generation-with-pixelcnn-decoders.pdf) говорится:

h - это горячее кодирование, которое определяет класс, что эквивалентно добавлению класса зависимое смещение на каждом слое.

Насколько я понимаю, условие вводится как одномерный тензор, который вводится в смещение посредством свертки. Теперь для двухэтапного условного PixelCNN необходимо ограничить вектор класса, а также скрытый код предыдущего этапа. Возможность, которую я вижу, состоит в том, чтобы добавить их и скормить трехмерный тензор. Кто-нибудь видит другой способ сделать это?

Потери и оптимизация не меняются в 2 этапа. Каждый просто добавляет потерю каждой стадии в окончательную потерю, которая оптимизирована. Это правильно?

1 Ответ

0 голосов
/ 01 апреля 2020

Обсуждая с одним из авторов статьи, я получил ответы на все эти вопросы и поделился ими ниже.

Вопрос 1

Это правильно, но понижающая дискретизация изображения реализована с использованием пошаговой свертки, а не непараметрического изменения c. Это может быть воспринято как часть архитектуры кодера примерно так (число после каждой переменной указывает их пространственное затемнение, например, h64 равно [B, 64, 64, D] и т. Д.).

   h128 = Relu(Conv2D(image256, stride=(2, 2)))
   h64 = Relu(Conv2D(h128, stride=(2, 2)))
   h64 = ResNet(h64)

Теперь для получения h32 и q32 мы можем сделать:

   h32 = Relu(Conv2D(h64,  stride=(2, 2)))
   h32 = ResNet(h32)
   q32 = Quantize(h32)

Таким образом, градиенты перетекают обратно к изображению, и, следовательно, мы имеем зависимость между h32 и image256.

Везде, где вы можете использовать свертку 1x1, чтобы отрегулировать размер последнего измерения (слои объектов), использовать пошаговую свертку для понижающей дискретизации и пошаговую транспонированную свертку для повышающей дискретизации пространственных измерений. Таким образом, для этого примера квантования нижнего слоя, вам нужно сначала увеличить дискретизацию q32 до 64x64, объединить его с h64 и передать результат в квантователь. Для дополнительной выразительной силы мы вставили остаточный стек между ними. Выглядит это так:

    hq32 = ResNet(Conv2D(q32, (1, 1)))
    hq64 = Conv2DTranspose(hq32, stride=(2, 2))
    h64 = Conv2D(concat([h64, hq64]), (1, 1))
    q64 = Quantize(h64)

Вопрос 2

В оригинальной статье PixelCNN также описано, как использовать пространственное кондиционирование с использованием сверток. Сглаживание и добавление к встраиванию классов как глобальному условию не очень хорошая идея. Вам нужно применить транспонированную свертку, чтобы выровнять пространственные измерения, затем свертку 1x1, чтобы сопоставить размерность объекта со скрытыми повторениями pixelcnn, а затем добавить его.

Вопрос 3

Это хорошая идея тренировать их отдельно. Помимо изоляции потерь et c. и возможность настраивать соответствующие скорости обучения для каждого этапа, вы также сможете использовать полный объем памяти вашего GPU / TPU для каждого этапа. Эти приоры работают лучше и лучше в большем масштабе, поэтому не стоит отрицать, что это так.

...