파이토치를 활용한 GAN 딥러닝, 미술 전시회

서론

GAN(Generative Adversarial Network)은 생성 모델의 일종으로, 두 개의 신경망이 상호작용하여 새로운 데이터를 생성하는 방법입니다. GAN은 주로 이미지 생성, 텍스트 생성, 음악 생성 등 다양한 분야에서 활용됩니다. 본 글에서는 파이토치(PyTorch) 라이브러리를 활용하여 GAN을 구현하고, 이를 통해 미술 전시회에서 사용할 수 있는 예술 작품을 생성하는 과정을 상세히 설명하겠습니다.

1. GAN의 기본 개념

GAN은 두 개의 모델, 즉 생성자(Generator)와 판별자(Discriminator)로 구성됩니다. 생성자는 무작위 입력을 바탕으로 데이터를 생성하며, 판별자는 주어진 데이터가 실제 데이터인지 생성된 데이터인지를 판별합니다. GAN의 학습 과정은 다음과 같습니다.

  1. 생성자는 무작위 노이즈를 입력받아 가짜 이미지를 생성합니다.
  2. 판별자는 생성된 이미지와 실제 이미지를 비교합니다.
  3. 판별자가 가짜 이미지를 실제 이미지로 잘못 판단할수록 생성자는 더 나은 이미지를 생성하도록 학습합니다.

이 과정은 생성자가 너무 가벼운 가짜 이미지를 생성할 수 없도록 판별자가 점점 더 정교해지는 모습을 만들어냅니다.

2. 파이토치 설치하기

GAN을 구현하기 위해 먼저 파이토치를 설치해야 합니다. 다음의 명령어를 통해 설치할 수 있습니다.

    
    pip install torch torchvision
    
    

3. 데이터 준비

미술 작품 이미지를 생성하기 위해서는 데이터셋이 필요합니다. 이번 실습에서는 CIFAR-10 데이터셋을 사용하겠습니다. 이 데이터셋은 10가지 클래스의 이미지로 구성되어 있으며, 그림 미술과 관련된 데이터셋을 구축할 수 있습니다. 파이토치 내장 함수를 사용해 손쉽게 사용할 수 있습니다.

3.1 CIFAR-10 데이터셋

    
    import torchvision.transforms as transforms
    import torchvision.datasets as datasets
    from torch.utils.data import DataLoader

    # 데이터 전처리
    transform = transforms.Compose([
        transforms.Resize(64),
        transforms.CenterCrop(64),
        transforms.ToTensor(),
        transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]),
    ])

    # CIFAR-10 데이터셋 로드
    dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
    dataloader = DataLoader(dataset, batch_size=128, shuffle=True, num_workers=2)
    
    

4. GAN 모델 구현하기

GAN 모델은 두 개의 신경망을 사용하여 생성자와 판별자를 정의해야 합니다. 생성자는 임의의 노이즈를 기반으로 이미지를 생성하고, 판별자는 이미지의 진위를 판별합니다.

4.1 생성자 모델

    
    import torch
    import torch.nn as nn

    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, 3*64*64),
                nn.Tanh(),
            )

        def forward(self, z):
            z = self.model(z)
            return z.view(-1, 3, 64, 64)
    
    

4.2 판별자 모델

    
    class Discriminator(nn.Module):
        def __init__(self):
            super(Discriminator, self).__init__()
            self.model = nn.Sequential(
                nn.Linear(3*64*64, 512),
                nn.LeakyReLU(0.2),
                nn.Linear(512, 256),
                nn.LeakyReLU(0.2),
                nn.Linear(256, 1),
                nn.Sigmoid(),
            )

        def forward(self, img):
            img = img.view(-1, 3*64*64)
            return self.model(img)
    
    

5. 손실 함수와 옵티마이저 설정하기

GAN의 학습을 위해 손실 함수와 옵티마이저를 설정해야 합니다. 일반적으로 이진 교차 엔트로피 손실(Binary Cross Entropy Loss)을 사용하며, Adam 최적화를 사용할 수 있습니다.

    
    import torch.optim as optim

    generator = Generator()
    discriminator = Discriminator()

    criterion = nn.BCELoss()
    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))
    
    

6. GAN 훈련하기

GAN의 훈련 과정은 생성자와 판별자가 번갈아 가며 학습하는 방식입니다. 아래의 코드는 GAN을 훈련하기 위한 주 루프를 나타냅니다.

    
    import numpy as np
    import matplotlib.pyplot as plt

    def train_gan(num_epochs):
        for epoch in range(num_epochs):
            for i, (imgs, _) in enumerate(dataloader):
                # 진짜 이미지 레이블: 1
                real_labels = torch.ones(imgs.size(0), 1)
                # 가짜 이미지 레이블: 0
                fake_labels = torch.zeros(imgs.size(0), 1)

                # 판별자 학습
                optimizer_D.zero_grad()
                outputs = discriminator(imgs)
                d_loss_real = criterion(outputs, real_labels)
                d_loss_real.backward()

                z = torch.randn(imgs.size(0), 100)
                fake_images = generator(z)
                outputs = discriminator(fake_images.detach())
                d_loss_fake = criterion(outputs, fake_labels)
                d_loss_fake.backward()

                optimizer_D.step()
                d_loss = d_loss_real + d_loss_fake

                # 생성자 학습
                optimizer_G.zero_grad()
                outputs = discriminator(fake_images)
                g_loss = criterion(outputs, real_labels)
                g_loss.backward()
                optimizer_G.step()

                if (i % 100 == 0):
                    print(f'Epoch [{epoch}/{num_epochs}], Step [{i}/{len(dataloader)}], d_loss: {d_loss.item()}, g_loss: {g_loss.item()}')

    train_gan(num_epochs=20)
    
    

7. 결과 시각화하기

모델 훈련이 끝나면 생성된 이미지를 시각화할 수 있습니다. 아래의 코드는 생성된 이미지를 저장하고 시각화하는 과정입니다.

    
    def plot_generated_images(num_images):
        z = torch.randn(num_images, 100)
        generated_images = generator(z).detach().numpy()
        generated_images = (generated_images + 1) / 2  # (-1, 1) -> (0, 1)
        
        fig, axes = plt.subplots(1, num_images, figsize=(15, 5))
        for i in range(num_images):
            axes[i].imshow(generated_images[i].transpose(1, 2, 0))
            axes[i].axis('off')
        plt.show()

    plot_generated_images(10)
    
    

8. 결론

본 글에서는 파이토치를 활용한 GAN 딥러닝의 기본 개념 및 구현 과정을 살펴보았습니다. GAN을 사용하여 미술 작품과 같은 새로운 이미지를 생성할 수 있으며, 이를 미술 전시회와 같은 행사에 활용할 수 있습니다. 앞으로 GAN 기술은 더욱 발전할 것으로 기대되며, 다양한 조형적 가능성을 제공할 것입니다.

9. 추가 자료

아래는 GAN 및 관련 주제에 대한 추가 자료입니다.