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

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

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

Что такое GAN и почему они полезны?

GAN — это тип глубокой нейронной сети, состоящий из двух основных компонентов: генератора и дискриминатора. Работа генератора состоит в том, чтобы создавать новые данные, которые выглядят как обучающие данные, в то время как работа дискриминатора состоит в том, чтобы отличать реальные данные от поддельных данных, сгенерированных генератором. Генератор и дискриминатор обучаются состязательным способом, что означает, что они конкурируют друг с другом. Генератор пытается обмануть дискриминатор, создавая более реалистичные данные, в то время как дискриминатор пытается поймать генератор, отвергая поддельные данные. Таким образом, обе модели улучшаются со временем, пока не достигнут равновесия, при котором генератор создает данные, неотличимые от реальных данных, и дискриминатор не может их различить.

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

Как работают GAN?

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

Процесс обучения GAN включает в себя чередование двух этапов:

  • Шаг 1: исправлен генератор и обновлен дискриминатор. В дискриминатор подается пакет реальных изображений из обучающего набора данных и пакет поддельных изображений, сгенерированных генератором. Цель дискриминатора состоит в том, чтобы правильно классифицировать каждое изображение как реальное или поддельное. Функция потерь дискриминатора измеряет, насколько хорошо он выполняет эту задачу.
  • Шаг 2.Исправлен дискриминатор и обновлен генератор. Генератор получает пакет случайных векторов шума и генерирует пакет фальшивых изображений. Цель генератора — обмануть дискриминатор, заставив его думать, что его выходной сигнал реален. Функция потерь генератора измеряет, насколько хорошо он выполняет эту задачу.

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

Каковы некоторые примеры GAN в действии?

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

  • Создание реалистичных лиц знаменитостей/людей, которых не существует. Вы можете попробовать сами, используя этот онлайн-инструмент: https://thispersondoesnotexist.com/
  • Создание реалистичных изображений произведений искусства/стилей. Вы можете попробовать сами, используя этот онлайн-инструмент: https://deepart.io/
  • Создание реалистичных изображений текста/почерка. Вы можете попробовать сами, используя этот онлайн-инструмент: https://fakewords.art/

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

Как реализовать GAN на Python?

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

Во-первых, нам нужно импортировать некоторые библиотеки и модули, которые мы будем использовать:

# Import TensorFlow and other libraries
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
import numpy as np

Далее нам нужно загрузить и предварительно обработать набор данных MNIST. Мы будем использовать только тренировочные изображения размером 28x28 пикселей в градациях серого. Мы нормализуем значения пикселей, чтобы они были между -1 и 1, и изменим их форму, чтобы они были тензорами 28x28x1.

# Load and prepare the MNIST dataset
(train_images, train_labels), (_, _) = keras.datasets.mnist.load_data()
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
train_images = (train_images - 127.5) / 127.5 # Normalize the images to [-1, 1]

Затем нам нужно определить некоторые гиперпараметры и константы, которые мы будем использовать для нашей модели:

# Define some constants
BUFFER_SIZE = 60000 # Number of images to shuffle
BATCH_SIZE = 256 # Batch size for training
NOISE_DIM = 100 # Dimension of the noise vector for the generator
NUM_EPOCHS = 50 # Number of epochs for training

Затем нам нужно создать объект набора данных TensorFlow, который позволит нам эффективно перемешивать и группировать изображения:

# Create a TensorFlow dataset object
train_dataset = tf.data.Dataset.from_tensor_slices(train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)

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

# Define the generator network
def make_generator_model():
    model = keras.Sequential()
    # Start with a dense layer that takes the noise vector as input and outputs a 7x7x256 tensor
    model.add(layers.Dense(7*7*256, use_bias=False, input_shape=(NOISE_DIM,)))
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())
    model.add(layers.Reshape((7, 7, 256)))
    # Apply a transposed convolution layer that upsamples the tensor to 14x14x128
    model.add(layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same', use_bias=False))
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())
    # Apply another transposed convolution layer that upsamples the tensor to 28x28x64
    model.add(layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=False))
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())
    # Apply a final transposed convolution layer that outputs a 28x28x1 image tensor with tanh activation
    model.add(layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=False,
                                     activation='tanh'))
    return model
#Define the discriminator network
def make_discriminator_model():
    model = keras.Sequential()
    # Start with a convolution layer that takes the image tensor as input and outputs a 14x14x64 tensor
    model.add(layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=[28, 28, 1]))
    model.add(layers.LeakyReLU())
    model.add(layers.Dropout(0.3))
    # Apply another convolution layer that outputs a 7x7x128 tensor
    model.add(layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'))
    model.add(layers.LeakyReLU())
    model.add(layers.Dropout(0.3))
    # Apply a final dense layer that outputs a scalar probability with sigmoid activation
    model.add(layers.Flatten())
    model.add(layers.Dense(1, activation='sigmoid')
    return model

Затем нам нужно создать экземпляры наших моделей генератора и дискриминатора и определить их оптимизаторы и функции потерь. Мы будем использовать бинарную кросс-энтропийную потерю для обеих моделей и оптимизатора Адама со скоростью обучения 0,0002 и бета_1 0,5.

# Create the generator and discriminator models
generator = make_generator_model()
discriminator = make_discriminator_model()

# Define the optimizers and the loss function
generator_optimizer = tf.keras.optimizers.Adam(0.0002, beta_1=0.5)
discriminator_optimizer = tf.keras.optimizers.Adam(0.0002, beta_1=0.5)
cross_entropy = tf.keras.losses.BinaryCrossentropy()

Функция потерь для дискриминатора измеряет, насколько хорошо он может различать реальные и поддельные изображения. Он сравнивает предсказания дискриминатора для реальных изображений с массивом из 1, а предсказания дискриминатора для поддельных изображений — с массивом из 0.

# Define the discriminator loss function
def discriminator_loss(real_output, fake_output):
    # Calculate the loss for real images
    real_loss = cross_entropy(tf.ones_like(real_output), real_output)
    # Calculate the loss for fake images
    fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output)
    # Return the total loss
    total_loss = real_loss + fake_loss
    return total_loss

Функция потерь для генератора измеряет, насколько хорошо он может обмануть дискриминатор. Он сравнивает прогнозы дискриминатора на поддельных изображениях с массивом из 1.

# Define the generator loss function
def generator_loss(fake_output):
    # Calculate the loss for fake images
    return cross_entropy(tf.ones_like(fake_output), fake_output)

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

# Define the training step function
@tf.function
def train_step(images):
    # Generate a batch of random noise vectors
    noise = tf.random.normal([BATCH_SIZE, NOISE_DIM])
    
    # Use tf.GradientTape to record the gradients of both models
    with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
        # Generate a batch of fake images using the generator
        generated_images = generator(noise, training=True)
        
        # Get the discriminator's predictions on real and fake images
        real_output = discriminator(images, training=True)
        fake_output = discriminator(generated_images, training=True)
        
        # Calculate the losses for both models
        gen_loss = generator_loss(fake_output)
        disc_loss = discriminator_loss(real_output, fake_output)
    
    # Get the gradients of both models
    gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)
    gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables)

    # Apply the gradients using the optimizers
    generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))
    discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))

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

# Define a helper function to generate and save images
def generate_and_save_images(model, epoch, test_input):
    # Generate a batch of images using the model
    predictions = model(test_input, training=False)
    
    # Plot the images in a 4x4 grid
    fig = plt.figure(figsize=(4,4))
    for i in range(predictions.shape[0]):
        plt.subplot(4, 4, i+1)
        plt.imshow(predictions[i, :, :, 0] * 127.5 + 127.5, cmap='gray')
        plt.axis('off')
    
    # Save the figure as an image file
    plt.savefig('image_at_epoch_{:04d}.png'.format(epoch))
    plt.show()

# Define a constant vector to use for generating images
seed = tf.random.normal([16, NOISE_DIM])

# Train the GAN model
for epoch in range(NUM_EPOCHS):
    # Loop over the batches of images
    for image_batch in train_dataset:
        # Update both models in one step
        train_step(image_batch)
    
    # Generate and save some images after each epoch
    generate_and_save_images(generator, epoch + 1, seed)

# Generate and save some final images after the last epoch
generate_and_save_images(generator, NUM_EPOCHS, seed)

Каковы плюсы и минусы GAN?

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

Плюсы:

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

Минусы:

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

Заключение

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

Спасибо за чтение, и я надеюсь, что вы узнали что-то новое!

Спасибо, что нашли время, чтобы прочитать эту историю. Если вам понравилось, выразите свою признательность, щелкнув значок хлопка столько раз, сколько пожелаете. Если вам нравится то, что я пишу, и вы хотели бы поддержать меня, вы можете стать пользователем Medium, перейдя по ссылке или угостить меня чашечкой кофе ☕️. Оставайтесь с нами, чтобы узнать больше!

Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .