파이토치를 활용한 GAN 딥러닝, 질문-대답 생성기

최근 몇 년간 인공지능(AI) 기술이 급격히 발전하면서, 자연어 처리(NLP) 분야도 크게 향상되었습니다. 특히 Generative Adversarial Networks(GAN)은 새로운 데이터 샘플을 만들기 위해 사용되는 강력한 기법입니다. 본 포스트에서는 PyTorch를 이용한 GAN 구현 방법과 질문-대답 생성기를 만드는 과정을 다뤄보겠습니다.

1. GAN의 개요

Generative Adversarial Networks(GAN)는 Ian Goodfellow가 2014년에 발표한 기계 학습 프레임워크로, 두 개의 신경망인 생성자(Generator)와 판별자(Discriminator)가 서로 경쟁하는 방식으로 훈련됩니다.

  • 생성자(Generator): 가짜 데이터를 생성하는 역할을 합니다. 랜덤 노이즈를 입력으로 받아서 실제 데이터와 유사한 샘플을 생성합니다.
  • 판별자(Discriminator): 주어진 데이터가 실제 데이터인지 생성자가 만든 가짜 데이터인지를 판단하는 역할을 맡고 있습니다.

이 두 네트워크는 각각의 목표를 달성하기 위해 서로 경쟁하며, 결국 생성자는 더욱 정교한 데이터를 생성하게 되고, 판별자는 이를 더욱 정확하게 구분하려고 하게 됩니다.

2. GAN의 수학적 원리

GAN의 훈련 과정은 두 가지 네트워크의 손실함수를 정의하여 최적화하는 과정입니다. 각 네트워크는 다음과 같은 목적 함수를 가지고 있습니다:

        L(D) = -E[log(D(x))] - E[log(1 - D(G(z)))]
        L(G) = -E[log(D(G(z)))]
    

여기서:

  • D(x): 판별자가 진짜 데이터 x를 올바르게 분류할 확률
  • G(z): 생성자가 랜덤 벡터 z를 입력받아 생성한 가짜 데이터
  • E[…]: 기대값

3. 질문-대답 생성기 개요

GAN 모델을 사용하여 자연어 처리에서 질문-답변 생성기를 구현할 수 있습니다. 이 시스템은 주어진 문맥에 대한 질문과 그에 대한 대답을 생성하는 모델을 목표로 합니다.

이제 우리는 GAN의 기본 구조를 사용하여 질문-대답 생성기를 어떻게 만들 수 있는지 살펴보겠습니다.

4. PyTorch 환경 설정

우선, PyTorch 라이브러리를 설치해야 합니다. 아래의 명령어로 PyTorch를 설치할 수 있습니다.

pip install torch torchvision

5. 데이터셋 준비

질문-답변 생성기를 만들기 위해, 먼저 데이터셋을 준비해야 합니다. 이 예제에서는 간단한 공개 데이터셋을 활용할 것입니다. 질문과 답변이 쌍으로 구성된 데이터를 사용합니다.

데이터셋 예시:

  • 질문: “파이썬은 무엇인가요?”
  • 답변: “파이썬은 고급 프로그래밍 언어입니다.”
  • 질문: “딥러닝이란 무엇인가요?”
  • 답변: “딥러닝은 인공 신경망을 기반으로 한 기계 학습 기법입니다.”

6. GAN 모델 구현

이제 GAN 아키텍처를 정의해 보겠습니다. 생성자는 질문을 입력받아 답변을 생성하고, 판별자는 생성된 답변이 실제 데이터인지 판별합니다.

6.1 생성자 (Generator) 구현


import torch
import torch.nn as nn

class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.net = nn.Sequential(
            nn.Linear(100, 128),
            nn.ReLU(),
            nn.Linear(128, 256),
            nn.ReLU(),
            nn.Linear(256, 512),
            nn.ReLU(),
            nn.Linear(512, 1024),
            nn.ReLU(),
            nn.Linear(1024, 2048),
            nn.ReLU(),
            nn.Linear(2048, 1)  # Output layer: 1 for solidity of generated answer
        )
        
    def forward(self, z):
        return self.net(z)
    

6.2 판별자 (Discriminator) 구현


class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.net = nn.Sequential(
            nn.Linear(1, 512),
            nn.ReLU(),
            nn.Linear(512, 256),
            nn.ReLU(),
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Linear(128, 1),
            nn.Sigmoid()  # Output layer: probability (0 or 1)
        )
        
    def forward(self, x):
        return self.net(x)
    

7. GAN 훈련 과정

이제 GAN 모델을 훈련시킬 준비가 되었습니다. 훈련 데이터로 질문-답변 쌍을 사용하고, 생성자는 랜덤 노이즈를 입력으로 받아 답변을 생성하고, 판별자는 진짜 답변과 생성된 답변을 판별합니다.


import torch.optim as optim

# Hyperparameters
num_epochs = 100
batch_size = 64
learning_rate = 0.0002

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

# Loss and Optimizers
criterion = nn.BCELoss()
optimizer_G = optim.Adam(generator.parameters(), lr=learning_rate)
optimizer_D = optim.Adam(discriminator.parameters(), lr=learning_rate)

for epoch in range(num_epochs):
    for i, (questions, answers) in enumerate(dataloader):
        # Generate random noise
        z = torch.randn(batch_size, 100)

        # Generate fake answers
        fake_answers = generator(z)

        # Create labels
        real_labels = torch.ones(batch_size, 1)
        fake_labels = torch.zeros(batch_size, 1)

        # Train Discriminator
        optimizer_D.zero_grad()
        outputs = discriminator(real_answers)
        d_loss_real = criterion(outputs, real_labels)
        
        outputs = discriminator(fake_answers.detach())
        d_loss_fake = criterion(outputs, fake_labels)
        d_loss = d_loss_real + d_loss_fake
        d_loss.backward()
        optimizer_D.step()

        # Train Generator
        optimizer_G.zero_grad()
        outputs = discriminator(fake_answers)
        g_loss = criterion(outputs, real_labels)
        g_loss.backward()
        optimizer_G.step()

    if (epoch + 1) % 10 == 0:
        print(f'Epoch [{epoch + 1}/{num_epochs}], d_loss: {d_loss.item()}, g_loss: {g_loss.item()}')
    

8. 결과 및 성능 평가

훈련이 완료되면, 생성자는 조건부 확률 분포를 학습하므로 주어진 질문에 대한 아답돈을 생성할 수 있습니다. 결과를 평가하기 위해, 생성된 텍스트를 현실의 질문-답변과 비교해야 합니다. NLU의 평가 지표인 BLEU 점수와 같은 다양한 메트릭을 사용할 수 있습니다.

9. 결론

이번 포스트에서는 PyTorch를 사용하여 GAN 기반의 질문-답변 생성기를 구현하는 방법에 대해 살펴보았습니다. GAN은 우리가 현실 세계에서 심플한 데이터 쌍을 생성하는 데 강력한 도구입니다. 앞으로도 GAN을 더욱 발전시키고, 다양한 애플리케이션에 적용할 수 있는 방법을 연구해 나가는 것이 중요합니다.

10. 참고자료