DC-GAN: потеря дискриминатора увеличивается, а потеря генератора падает

Я не могу сказать, связана ли эта ошибка с технической ошибкой или гиперпараметрами, но потери дискриминатора моего DC-GAN начинаются с низкого уровня и постепенно повышаются, замедляясь около 8, в то время как потери в моем генераторе значительно снижаются. Я закончил это примерно на 60 000 эпох. Как ни странно, точность дискриминатора колеблется в районе 20-50%. Есть ли у кого-нибудь предложения по устранению проблемы? Любая помощь приветствуется.

Важная информация

  • Формат данных: 472 файлов 320x224 цветных PNG.
  • Оптимизатор: Adam(0.0002, 0.5)
  • Потеря: двоичная кросс-энтропия

Изображение, созданное после 50 000+ эпох: (Предполагается, что кроссовки на белом фоне)

введите здесь описание изображения

Модель дискриминатора:

    def build_discriminator(self):

        img_shape = (self.img_size[0], self.img_size[1], self.channels)

        model = Sequential()

        model.add(Conv2D(32, kernel_size=self.kernel_size, strides=2, input_shape=img_shape, padding="same"))  # 192x256 -> 96x128
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.25))

        model.add(Conv2D(64, kernel_size=self.kernel_size, strides=2, padding="same"))  # 96x128 -> 48x64
        model.add(ZeroPadding2D(padding=((0, 1), (0, 1))))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.25))
        model.add(BatchNormalization(momentum=0.8))

        model.add(Conv2D(128, kernel_size=self.kernel_size, strides=2, padding="same"))  # 48x64 -> 24x32
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.25))
        model.add(BatchNormalization(momentum=0.8))

        model.add(Conv2D(256, kernel_size=self.kernel_size, strides=1, padding="same"))  # 24x32 -> 12x16
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.25))

        model.add(Conv2D(512, kernel_size=self.kernel_size, strides=1, padding="same"))  # 12x16 -> 6x8
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(0.25))

        model.add(Flatten())
        model.add(Dense(1, activation='sigmoid'))

        model.summary()

        img = Input(shape=img_shape)
        validity = model(img)

        return Model(img, validity)

Модель генератора:

    def build_generator(self):

        noise_shape = (100,)

        model = Sequential()
        model.add(
            Dense(self.starting_filters * (self.img_size[0] // (2 ** self.upsample_layers))  *  (self.img_size[1] // (2 ** self.upsample_layers)),
                  activation="relu", input_shape=noise_shape))
        model.add(Reshape(((self.img_size[0] // (2 ** self.upsample_layers)),
                           (self.img_size[1] // (2 ** self.upsample_layers)),
                           self.starting_filters)))
        model.add(BatchNormalization(momentum=0.8))

        model.add(UpSampling2D())  # 6x8 -> 12x16
        model.add(Conv2D(1024, kernel_size=self.kernel_size, padding="same"))
        model.add(Activation("relu"))
        model.add(BatchNormalization(momentum=0.8))

        model.add(UpSampling2D())  # 12x16 -> 24x32
        model.add(Conv2D(512, kernel_size=self.kernel_size, padding="same"))
        model.add(Activation("relu"))
        model.add(BatchNormalization(momentum=0.8))

        model.add(UpSampling2D())  # 24x32 -> 48x64
        model.add(Conv2D(256, kernel_size=self.kernel_size, padding="same"))
        model.add(Activation("relu"))
        model.add(BatchNormalization(momentum=0.8))

        model.add(UpSampling2D())  # 48x64 -> 96x128
        model.add(Conv2D(128, kernel_size=self.kernel_size, padding="same"))
        model.add(Activation("relu"))
        model.add(BatchNormalization(momentum=0.8))

        model.add(UpSampling2D())  # 96x128 -> 192x256
        model.add(Conv2D(64, kernel_size=self.kernel_size, padding="same"))
        model.add(Activation("relu"))
        model.add(BatchNormalization(momentum=0.8))

        model.add(Conv2D(32, kernel_size=self.kernel_size, padding="same"))
        model.add(Activation("relu"))
        model.add(BatchNormalization(momentum=0.8))

        model.add(Conv2D(self.channels, kernel_size=self.kernel_size, padding="same"))
        model.add(Activation("tanh"))

        model.summary()

        noise = Input(shape=noise_shape)
        img = model(noise)

        return Model(noise, img)

person Riley Fitzpatrick    schedule 15.08.2019    source источник


Ответы (2)


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

person ivallesp    schedule 15.08.2019
comment
Имеет смысл. Я поменяю это и посмотрю, что будет. - person Riley Fitzpatrick; 15.08.2019
comment
Если вы считаете, что мне удалось вам помочь, выберите мое сообщение в качестве принятого ответа: D - person ivallesp; 16.08.2019
comment
Итак, я сбалансировал параметры и стал лучше балансировать между генератором и дискриминатором. Однако изображения выглядят почти так же, как и были. Единственное заметное отличие - более сплошные цвета по сравнению с тонкими цветами на первых изображениях. Любые идеи? - person Riley Fitzpatrick; 16.08.2019
comment
Да! DC-GAN - очень устаревшая модель. Часто это не просто сходится. Я бы попробовал, например, хотя бы с WGAN-GP - person ivallesp; 16.08.2019
comment
Итак, я понял, что когда я тестировал свои изменения, я не позволял им работать достаточно долго. Независимо от того, насколько я уменьшаю размер сети генератора, дискриминатор все равно имеет ужасные потери. Помогло бы увеличение размера дискриминаторной сети? Он уже довольно большой - person Riley Fitzpatrick; 16.08.2019

Я думаю, вы используете свой собственный набор данных. Если нет, подумайте об использовании того же гиперпараметра, что и в документе DCGAN, и сначала воспроизведите их результаты. Затем используйте эту сеть для своего набора данных. Известно, что DCGAN, особенно с кросс-энтропийной потерей, очень сложны и чрезвычайно чувствительны к гиперпараметрам для запуска (см. https://arxiv.org/abs/1711.10337). Особенно, если вы не ограничили свой дискриминатор какими-либо штрафами за градиент (штраф за градиент или спектральная норма).

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

person Thomas Pinetz    schedule 16.08.2019