Заметки о чтении бумаги CycleGAN

GAN

封面

Эта статья была впервые опубликована в моем личном блоге:X ошибок.женщины/цикл-сухой-день…

Добро пожаловать в другие статьи:xerrors.fun


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

В оригинальной статье сначала была предложена гипотеза:

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

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

Итак, автор хочет обучить отношение отображения G, которое может отображать домен X в домен G(X), эквивалентный распределению Y, но возникает проблема: нет гарантии, что такое преобразование будет соответствовать входу x и выходу y. , а также Нет возможности оптимизации; проблема здесь должна заключаться в той проблеме, с которой вы столкнетесь при использовании непарных данных; при этом в процессе обучения часто происходит «схлопывание режима»: все изображения сопоставляются с одним вывод.

Чтобы гарантировать, что каждый выход может быть связан со входом, это можно понимать как сохранение исходной «потенциальной связи», поэтому автор ввел принцип «постоянства цикла», то есть для обеспечения того, чтобы G, полученное после x проходит через отношение отображения G (x) может быть отображено обратно через другое отношение отображения F, то есть для удовлетворенияF(G(x)) = x,G(F(y))=y.

1. Связанная работа

Эта часть в основном предназначена для ознакомления с работой предшественников и их собственным пониманием, вот небольшая запись;

Автор считает, что ключ к успеху GAN лежит в понятии «состязательная потеря», и автор также предлагает свою собственную «потерю согласованности цикла», основанную на этом.

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

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

image-20201208115526873

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

Unlike the above approaches, our formulation does not rely on any task-specific, predefined similarity function between the input and output, nor do we assume that the input and output have to lie in the same low-dimensional embedding space.

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

Что касается «постоянства цикла», автор объясняет, что концепция использования транзитивности в качестве метода оптимизации имеет долгую историю и применялась во многих областях, таких как перевод и сопоставление 3D-моделей. используется согласованность цикла, Потери используются в обучении моделей, и их знания отличаются от наших тем, что их знания используют транзитивность для контроля обучения CNN.

Of these, Zhou et al. and Godard et al. are most similar to our work, as they use a cycle consistency loss as a way of using transitivity to supervise CNN training.

Среди них Чжоу и Годар и др. больше всего похожи на нашу работу, которые использовали потерю согласованности цикла как способ использовать транзитивность для контроля обучения CNN.

При этом по стечению обстоятельств появился и DualGAN:

Concurrent with our work, in these same proceedings, Yi et al. independently use a similar objective for unpaired image-to-image translation, inspired by dual learning in machine translation.

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

В то же время автор также сравнил Neural Style Transfer, Хотя результаты схожи, Cycle GAN фокусируется на сопоставлении двух наборов изображений и извлекает более продвинутые функции, помимо внешнего вида. Таким образом, модель также легче применять к другим задачам.

2. Математическая теория

Чтобы понять математические концепции здесь, главное сначала понять функцию каждой части на этой диаграмме;

image-20201208115526873

Сеть содержит две функции отображения и два дискриминатора.При обучении отношения отображения G и дискриминатора DY целевая функция выглядит следующим образом (одинаково для F и DX):

LGAN(G,DY,X,Y)=Eypdata (y)[logDY(y)]+Expdata (x)[log(1DY(G(x))]\begin{aligned} \mathcal{L}_{\mathrm{GAN}}\left(G, D_{Y}, X, Y\right) &=\mathbb{E}_{y \sim p_{\text {data }}(y)}\left[\log D_{Y}(y)\right] \\ &+\mathbb{E}_{x \sim p_{\text {data }}(x)}\left[\log \left(1-D_{Y}(G(x))\right]\right. \end{aligned}

потеря согласованности цикла потери:

Lcyc (G,F)=Expdata (x)[F(G(x))x1]+Eypdata (y)[G(F(y))y1]\begin{aligned} \mathcal{L}_{\text {cyc }}(G, F) &=\mathbb{E}_{x \sim p_{\text {data }}(x)}\left[\|F(G(x))-x\|_{1}\right] \\ &+\mathbb{E}_{y \sim p_{\text {data }}(y)}\left[\|G(F(y))-y\|_{1}\right] \end{aligned}

Объединив их вместе, можно получить целевую функцию следующим образом, гдеλ\lambdaконтролирует относительную важность этих двух целей. :

L(G,F,DX,DY)=LGAN(G,DY,X,Y)+LGAN(F,DX,Y,X)+λLcyc(G,F)\begin{aligned} \mathcal{L}\left(G, F, D_{X}, D_{Y}\right) &=\mathcal{L}_{\mathrm{GAN}}\left(G, D_{Y}, X, Y\right) \\ &+\mathcal{L}_{\mathrm{GAN}}\left(F, D_{X}, Y, X\right) \\ &+\lambda \mathcal{L}_{\mathrm{cyc}}(G, F) \end{aligned}

Весь алгоритм заключается в решении следующей формулы:

G*,F*=argminG,FmaxDx,DYL(G,F,DX,DY)G^{*}, F^{*}=\arg \min _{G, F} \max _{D_{x}, D_{Y}} \mathcal{L}\left(G, F, D_{X}, D_{Y}\right)

В дополнение к передаче стиля существует потеря идентичности функции потерь, автор обнаружил, что введение дополнительных потерь для мотивации отображения генератора может хорошо сохранить компоненты цвета между входом и выходом:

Lidentity (G,F)=Eypdata (y)[G(y)y1]+Expdata (x)[F(x)x1]\begin{aligned} & \mathcal{L}_{\text {identity }}(G, F)=\mathbb{E}_{y \sim p_{\text {data }}(y)}\left[\|G(y)-y\|_{1}\right]+\mathbb{E}_{x \sim p_{\text {data }}(x)}\left[\|F(x)-x\|_{1}\right] \end{aligned}

3. Структура сети

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

Генератор состоит из трех частей:

"кодировать-преобразовать-декодировать«Первую часть можно понимать как извлечение признаков (кодирование), которое извлекает абстрактные признаки исходного изображения, а вторую часть представляет собой преобразование, которое преобразует признаки из домена изображения A в домен изображения B, а затем восстанавливает (декодирует) в домен B. picture. Поэтому для представления модели генератора обычно используются два верхних напоминания;

Generator

Строитель

class Generator(nn.Module):
    def __init__(self, input_nc, output_nc, n_residual_blocks=9):
        super(Generator, self).__init__()

        # Initial convolution block (256x256x3 -> 256x256x64)
        ## https://zhuanlan.zhihu.com/p/66989411 详解 nn.ReflectionPad2d
        model = [   nn.ReflectionPad2d(3),
                    nn.Conv2d(input_nc, 64, 7),
                    nn.InstanceNorm2d(64),
                    nn.ReLU(inplace=True) ]

        # Downsampling, Encoding (256x256x64 -> 128x128x128 -> 64x64x256)
        ## 采用两个卷积层进行特征提取
        in_features = 64
        out_features = in_features*2
        for _ in range(2):
            model += [  nn.Conv2d(in_features, out_features, 3, stride=2, padding=1),
                        nn.InstanceNorm2d(out_features),
                        nn.ReLU(inplace=True) ]
            in_features = out_features
            out_features = in_features*2

        # Residual blocks, Transformation (64x64x256 -> 64x64x256)
        ## 添加 6 个(默认)残差模块进行风格转换
        for _ in range(n_residual_blocks):
            model += [ResidualBlock(in_features)]

        # Upsampling, Decoding (64x64x256 -> 128x128x128 -> 256x256x64)
        ## 将图像特征还原到图像域 B 上,使用两层逆卷积操作
        out_features = in_features//2
        for _ in range(2):
            model += [  nn.ConvTranspose2d(in_features, out_features, 3, stride=2, padding=1, output_padding=1),
                        nn.InstanceNorm2d(out_features),
                        nn.ReLU(inplace=True) ]
            in_features = out_features
            out_features = in_features//2

        # Output layer (2556x256x64 -> 256x256x)
        model += [  nn.ReflectionPad2d(3),
                    nn.Conv2d(64, output_nc, 7),
                    nn.Tanh() ]

        self.model = nn.Sequential(*model)

    def forward(self, x):
        return self.model(x)

остаточный модуль

class ResidualBlock(nn.Module):
    def __init__(self, in_features):
        super(ResidualBlock, self).__init__()

        conv_block = [  nn.ReflectionPad2d(1),
                        nn.Conv2d(in_features, in_features, 3),
                        nn.InstanceNorm2d(in_features),
                        nn.ReLU(inplace=True),
                        nn.ReflectionPad2d(1),
                        nn.Conv2d(in_features, in_features, 3),
                        nn.InstanceNorm2d(in_features)  ]

        self.conv_block = nn.Sequential(*conv_block)

    def forward(self, x):
        return x + self.conv_block(x)

дискриминатор

это простой классификатор

discriminator

Дискриминатор:

class Discriminator(nn.Module):
    def __init__(self, input_nc):
        super(Discriminator, self).__init__()

        # A bunch of convolutions one after another
        model = [   nn.Conv2d(input_nc, 64, 4, stride=2, padding=1),
                    nn.LeakyReLU(0.2, inplace=True) ]

        model += [  nn.Conv2d(64, 128, 4, stride=2, padding=1),
                    nn.InstanceNorm2d(128), 
                    nn.LeakyReLU(0.2, inplace=True) ]

        model += [  nn.Conv2d(128, 256, 4, stride=2, padding=1),
                    nn.InstanceNorm2d(256), 
                    nn.LeakyReLU(0.2, inplace=True) ]

        model += [  nn.Conv2d(256, 512, 4, padding=1),
                    nn.InstanceNorm2d(512), 
                    nn.LeakyReLU(0.2, inplace=True) ]

        # FCN classification layer
        model += [nn.Conv2d(512, 1, 4, padding=1)]

        self.model = nn.Sequential(*model)

    def forward(self, x):
        x =  self.model(x)
        # Average pooling and flatten
        return F.avg_pool2d(x, x.size()[2:]).view(x.size()[0], -1)

4. Тренировочный процесс

При оценке генератора используются три функции потерь: потеря GAN, потеря идентичности, потеря цикла; картинка стоит тысячи слов, мой рисунок просто фантастический!

训练生成器的过程

Из рисунка видно, что входными данными для обучения генератора являются два изображения Real A и Real B, взятые из домена A и домена B. Обучение всего генератора разделено на три части, которые являются оранжевыми областями для рассчитать потери идентичности, желтая область используется для расчета потерь цикла, а остальная часть фиолетового цвета используется для расчета потерь GAN; для 6 потерь, генерируемых двумя генераторами, накопление используется как потери генератора , а затем выполняется обратное распространение, также можно использовать следующий код, иллюстрирующий это.

Метод обучения дискриминатора:

训练判别器的过程

Код может ссылаться на удобочитаемую версию Pytorch, реализованную этим большим парнем:PyTorch-CycleGAN/blob/master/train

использованная литература

  1. Tensorflow implementation of CycleGAN - GitHub
  2. Ссылка на код: Чистая и удобочитаемая реализация CycleGAN в Pytorch - GitHub
  3. Помогите вам понять CycleGAN и легко внедрить его с помощью TensorFlow - Qubit