Да начнется код!

Введение

В предыдущем разделе мы обсуждали Почему, что и как использовать GAN. Теперь мы будем использовать Tensorflow для кодирования простого GAN.

Вход

Мы будем обучать нашу GAN работе с базой данных MNIST.

Выход

В конце статьи вы сможете сгенерировать рукописную цифру с помощью своего обученного генератора.

Блокнот Jupyter можно найти на моем Github.

Поток данных

Пришло время создать нашу генеративно-состязательную сеть. GAN состоит из двух компонентов:

  • Дискриминатор: различайте настоящие и поддельные изображения (данные).
  • Генератор: создает поддельные изображения, чтобы обмануть дискриминатор.

Давайте посмотрим на архитектуру GAN

  • Реальное изображение Xподается на дискриминатор,D
  • Dпредсказывает, является ли он настоящим или поддельным
  • Затем с помощью случайного шума создается скрытый вектор Z.
  • Zподается в генератор, G
  • Gсоздает фальшивое изображение
  • Это поддельное изображение отправляется на дискриминатор, D
  • D определяет, является ли это изображение реальным или поддельным.

Вот как данные передаются в сети. Потеря во время обучения используется для обучения модели с использованием Gradient Decent & Back-propagation.

Методы

Мы можем провести обучение двумя способами:
 – с помощью градиентной ленты
 – с помощью функции подгонки.

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

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

Импорт данных

Давайте импортируем базу данных MNIST для нашего обучения. База данных MNIST представляет собой набор рукописных цифр. Размер каждого изображения составляет 28x28 пикселей.

Код

Нормализация

Мы нормализуем наше изображение между [-1, 1]

Код

Модель

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

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

  • Ввод: изображение 28x28 сглаживается для создания 784длинного входного вектора.
  • Активация: Leaky_relu для добавления нелинейности
  • Выходной слой: Сигмовидная активация используется для прогнозавероятности

Генератор кода

  • Входные данные: скрытый вектор размера 10.
  • Активация: Relu используется для скрытых слоев.
  • Выход: изображение 28 x 28, которое мы преобразовываем в 28 x 28 x 1.

В идеале мы должны использовать активацию tanh на выходном слое Генератора, поскольку мы нормализовали нашу модель так, чтобы она находилась между [-1, 1]. Но это привело к проблеме под названием Сбой режима из-за простоты нашей модели.

Сокращение режима — это состояние, при котором модель вместо того, чтобы фиксировать изменения в реальных данных, просто изучает наиболее распространенные символы/точки данных. Вот пример.

Функции потерь

Функция потерь, используемая в статье GAN, имеет вид

😨😱😭😭😭‼⁉

Не бегайте! Позвольте мне сделать это интуитивно понятным и рассматривать по одному термину за раз.

  • x: реальное изображение передается на дискриминатор
  • z: скрытый вектор передается в генератор
  • D: модель дискриминатора
  • G: модель генератора
  • G(z): фальшивое изображение, созданное после передачи z в G.
  • D(x): вероятность, определяемая D {0: поддельная, 1: настоящая} для реального изображения.
  • D(G(z)): вероятность, заданная D {0: подделка, 1: реальная} для поддельного изображения.
  • E: ожидание или просто усреднение потерь для партии.
  • журнал: старая школа и простой журнал.

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

Log(D(x)) будет равен 0ifD(x) = 1, т. е. реальное изображение правильно классифицировано и отрицательная бесконечность, если D(x) = 0, т.е. реальное изображение считается подделкой. Точно так же Log(1-D(G(x))) равен 0, когда дискриминатор правильно классифицирует фальшивое изображение G(x).

С другой стороны, цель Генератора — обмануть Дискриминатор. Он пытается максимизировать значение D(G(z)). Так обучаются обе модели.

Обучение

У нас есть две разные модели: Дискриминатор (D) и Генератор (G). Но нам нужно тренировать их вместе. Мы создадим пользовательскую модель (класс), чтобы объединить эти две модели под названием GAN. Он будет содержать 3 функции:

  • Конструктор: добавьте наши модели G и D
  • компилировать: добавить наш компилятор, функцию потерь и оптимизатор, используемые в обучении.
  • train_step: здесь мы рассчитываем потери и градиент, а также обратное распространение.

Код

Сохранение сгенерированного изображения

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

Код

Теперь нам нужны эти изображения каждые, скажем, 50 эпох. Для этого мы будем использовать так называемые обратные вызовы. Обратный вызов — это класс, который позволяет нам вызывать функции после каждой эпохи (среди прочих сценариев)

Код

Гипер параметры

Настройка количества эпох, размера пакета и т. д.

Код

Тренироваться

Наконец, мы можем обучить модель и сохранить ее.

Код

Полученные результаты

Это результаты после 5000эпох обучения.

На начальных этапах Генератор создает шум, но позже при обучении он начинает создавать что-то похожее на цифры.

Советы

  • Эта модель требует приличного графического процессора для быстрого обучения.
  • Если вы сталкиваетесь с нехваткой ресурсов, используйте Google Colab для запуска эксперимента, где обучение модели с текущими гиперпараметрами займет около 3 часов.
  • При использовании Google Colab просто убедитесь, что страница не простаивает слишком долго, иначе обучение прекратится
  • При необходимости уменьшите количество эпох или размер пакета.

Вот оно, народ! Теперь вы знаете, как генерировать синтетические цифры.

Приятного обучения и экспериментов!

Если у вас есть какие-либо сомнения или отзывы, пожалуйста, прокомментируйте. Или вы можете связаться со мной в LinkedInили Twitter.