Deep Learning GAN using PyTorch, Changed Art Exhibition

In recent years, the development of artificial intelligence (AI) and deep learning has had a significant impact on various fields. In particular, Generative Adversarial Networks (GANs) have brought revolutionary changes in the field of image generation. We have now entered an era where we can create entirely new artworks through GANs and showcase these works through exhibitions. In this article, we will take a detailed look at the process of implementing GANs using PyTorch and exhibiting the generated artworks.

Overview of GAN

GANs consist of two networks: a Generator and a Discriminator. The Generator takes random noise as input and attempts to generate images that look real, while the Discriminator determines whether the input image is real or generated. The two networks are in a competitive relationship, which leads to the generation of increasingly realistic images over time.

Structure of GAN

  • Generator (G): A network that takes a random noise vector as input and generates images. During the GAN training process, the Generator continuously learns to produce images that are difficult for the Discriminator to identify.
  • Discriminator (D): A network that takes images as input and determines whether the image is part of the actual dataset or generated by the Generator. The Discriminator also evolves to make increasingly accurate judgments through learning.

Implementing GAN with PyTorch

Now, we will define the Generator and Discriminator to implement GANs using PyTorch. In this example, we will build a simple image generation model.

Installing Required Libraries

!pip install torch torchvision matplotlib

Preparing the Dataset

We will train our GAN using the MNIST dataset, which consists of handwritten digit images from 0 to 9. We will load the data using the code below.


import torch
from torchvision import datasets, transforms

# Download and prepare MNIST dataset
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
    

Building the Generator and Discriminator Models

We will now define the Generator and Discriminator models. We will use a simple fully connected neural network, where the Generator takes random noise vectors as input and generates images.


import torch.nn as nn

# Define Generator model
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(100, 256),
            nn.ReLU(),
            nn.Linear(256, 512),
            nn.ReLU(),
            nn.Linear(512, 1024),
            nn.ReLU(),
            nn.Linear(1024, 784),
            nn.Tanh()  # MNIST is normalized to [-1, 1].
        )

    def forward(self, z):
        return self.model(z).view(-1, 1, 28, 28)  # Resizing to 28x28 image

# Define Discriminator model
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(784, 512),
            nn.LeakyReLU(0.2),
            nn.Linear(512, 256),
            nn.LeakyReLU(0.2),
            nn.Linear(256, 1),
            nn.Sigmoid()  # Outputs probability between 0 and 1
        )

    def forward(self, img):
        return self.model(img.view(-1, 784))  # Resizing to 784 vector
    

Training the Model

To train the model, we will define the loss function and optimization technique. The Generator aims for minimal loss, while the Discriminator is trained with the assumption that a larger loss indicates incorrect judgments.


import torch.optim as optim

# Initialize models
generator = Generator()
discriminator = Discriminator()

# Define loss function and optimization technique
criterion = nn.BCELoss()  # Binary Cross Entropy Loss
optimizer_G = optim.Adam(generator.parameters(), lr=0.0002, betas=(0.5, 0.999))
optimizer_D = optim.Adam(discriminator.parameters(), lr=0.0002, betas=(0.5, 0.999))

# Training loop
num_epochs = 50
for epoch in range(num_epochs):
    for i, (imgs, _) in enumerate(train_loader):
        # Set real images and labels
        real_imgs = imgs
        real_labels = torch.ones(imgs.size(0), 1)  # Real image label: 1
        fake_labels = torch.zeros(imgs.size(0), 1)  # Fake image label: 0

        # Train Discriminator
        optimizer_D.zero_grad()
        outputs = discriminator(real_imgs)
        d_loss_real = criterion(outputs, real_labels)
        d_loss_real.backward()

        z = torch.randn(imgs.size(0), 100)  # Sampling noise vector
        fake_imgs = generator(z)
        outputs = discriminator(fake_imgs.detach())
        d_loss_fake = criterion(outputs, fake_labels)
        d_loss_fake.backward()
        optimizer_D.step()

        # Train Generator
        optimizer_G.zero_grad()
        outputs = discriminator(fake_imgs)
        g_loss = criterion(outputs, real_labels)  # The Generator aims to have fake images judged as real
        g_loss.backward()
        optimizer_G.step()

    print(f'Epoch [{epoch+1}/{num_epochs}], d_loss: {d_loss_real.item() + d_loss_fake.item():.4f}, g_loss: {g_loss.item():.4f}')
    

Visualizing the Results

After training the model, we will save and visualize the generated images.


import matplotlib.pyplot as plt

# Function to generate and visualize images
def show_generated_images(generator, num_images=25):
    z = torch.randn(num_images, 100)
    generated_images = generator(z).detach().numpy()
    generated_images = (generated_images + 1) / 2  # Convert to [0, 1]

    fig, axes = plt.subplots(5, 5, figsize=(10, 10))
    for i, ax in enumerate(axes.flatten()):
        ax.imshow(generated_images[i][0], cmap='gray')
        ax.axis('off')
    plt.tight_layout()
    plt.show()

show_generated_images(generator)
    

Revised Art Exhibitions and the Use of GANs

Now, let’s look at how to exhibit artworks generated by GANs. The exhibitions provide visitors with an opportunity to experience the intersection of AI and art, going beyond mere appreciation of the artwork.

Themes and Structure of AI Art Exhibitions

AI-based art exhibitions can consist of the following elements:

  • Generated Works: Displaying various artworks generated through GANs. Each piece includes an explanation of how AI generated the image.
  • Workshops: Providing workshops where visitors can create their own AI artworks, offering direct experience with AI technology.
  • Discussion Sessions: Facilitating deeper understanding through discussions with experts about the relationship between AI and art.

Planning and Executing the Exhibition

When planning the exhibition, the following steps should be taken:

  1. Setting Objectives: Clearly defining the goals and themes of the exhibition.
  2. Selecting Venue: Choosing a location convenient for visitors to access.
  3. Selecting Works: Choosing various works generated through GANs for exhibition.
  4. Promotion Strategy: Promoting the exhibition through social media, posters, and websites.
  5. Operation and Feedback: Collecting feedback from visitors during the exhibition for future reference.

Conclusion

The implementation of GANs using PyTorch and hosting a revised art exhibition is an exciting example of the intersection of AI and art. The advancement of GANs provides artists with new creative tools, while offering visitors a chance to experience art in entirely new ways. As AI advances, the boundaries of art are expanding, and we can expect even more innovations in future exhibitions.