파이토치를 활용한 GAN 딥러닝, RNN 훈련 데이터 수집

인공지능과 머신러닝의 발전은 우리가 생활하고 있는 모든 분야에 혁신을 가져왔습니다. 그 중에서도 GAN(Generative Adversarial Networks)과 RNN(Recurrent Neural Networks)은 매우 강력한 딥러닝 기법으로 주목받고 있습니다.
이 글에서는 파이토치(PyTorch)를 활용하여 GAN 모델을 구현하고, RNN의 훈련 데이터 수집 방법에 대해 자세히 다루겠습니다.

1. GAN이란?

GAN은 두 개의 신경망(Generator와 Discriminator)이 서로 경쟁하여 학습하는 방식입니다.
제너레이터(Generator)는 현실과 유사한 데이터를 생성하고, 판별기(Discriminator)는 이 데이터가 진짜인지 가짜인지를 판단합니다.
GAN은 이미지 생성, 비디오 생성, 음악 생성 등 다양한 분야에서 활용되고 있습니다.

2. GAN의 구조

GAN은 두 부분으로 나뉘어 있습니다:

  • Generator: 주어진 랜덤 벡터를 기반으로 새로운 데이터를 생성합니다.
  • Discriminator: 진짜 데이터와 제너레이터에서 생성된 가짜 데이터를 구별합니다.

두 네트워크는 서로의 성능을 향상시키기 위해 경쟁하며, 이 과정을 통해 더 높은 품질의 데이터를 생성하게 됩니다.

3. GAN의 학습 과정

GAN의 학습 과정은 일반적으로 다음 단계를 포함합니다:

  • (1) 랜덤 노이즈를 생성하고 제너레이터에 입력합니다.
  • (2) 제너레이터는 가짜 데이터를 생성합니다.
  • (3) 판별기는 진짜 데이터와 가짜 데이터를 받아 각각에 대한 예측 값을 출력합니다.
  • (4) GAN은 판별기의 출력을 바탕으로 제너레이터의 가중치를 업데이트합니다.
  • (5) 학습이 완료될 때까지 이 과정을 반복합니다.

4. GAN의 파이토치 구현

환경 설정

먼저, 파이토치 라이브러리를 설치해야 합니다. 아래의 명령어를 실행하여 설치하세요.

pip install torch torchvision

파이토치를 활용한 GAN 코드 예제

아래는 간단한 GAN의 구현 예제입니다. MNIST 데이터셋을 사용하여 손글씨 숫자를 생성하는 모델을 만들어 보겠습니다.


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

# 하이퍼파라미터
latent_size = 64
batch_size = 100
learning_rate = 0.0002
num_epochs = 200

# 데이터셋 로드
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

mnist = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
data_loader = DataLoader(dataset=mnist, batch_size=batch_size, shuffle=True)

# 생성자 클래스 정의
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.main = nn.Sequential(
            nn.Linear(latent_size, 256),
            nn.ReLU(True),
            nn.Linear(256, 512),
            nn.ReLU(True),
            nn.Linear(512, 1024),
            nn.ReLU(True),
            nn.Linear(1024, 784),
            nn.Tanh()
        )

    def forward(self, x):
        return self.main(x)

# 판별자 클래스 정의
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.main = nn.Sequential(
            nn.Linear(784, 1024),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(1024, 512),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(512, 256),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(256, 1),
            nn.Sigmoid()
        )

    def forward(self, x):
        return self.main(x)

generator = Generator().cuda()
discriminator = Discriminator().cuda()

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, (images, _) in enumerate(data_loader):
        # 진짜 데이터 레이블
        real_images = images.view(-1, 28*28).cuda()
        real_labels = torch.ones(batch_size, 1).cuda()
        # 가짜 데이터 레이블
        noise = torch.randn(batch_size, latent_size).cuda()
        fake_images = generator(noise)
        fake_labels = torch.zeros(batch_size, 1).cuda()

        # 판별기 학습
        optimizer_D.zero_grad()
        outputs_real = discriminator(real_images)
        outputs_fake = discriminator(fake_images.detach())
        loss_D_real = criterion(outputs_real, real_labels)
        loss_D_fake = criterion(outputs_fake, fake_labels)
        loss_D = loss_D_real + loss_D_fake
        loss_D.backward()
        optimizer_D.step()

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

    print(f"Epoch [{epoch+1}/{num_epochs}], Loss D: {loss_D.item()}, Loss G: {loss_G.item()}")
    if (epoch+1) % 10 == 0:
        # 결과 저장 코드 추가 가능
        pass
    

5. RNN(Recurrent Neural Network) 소개

RNN은 순서가 있는 데이터, 즉 시퀀스 데이터를 처리하는 데 적합한 신경망 구조입니다. 예를 들어, 텍스트, 음악, 시간 데이터와 같은 형태의 데이터가 이에 해당합니다.
RNN은 이전 상태를 기억하고 이를 기반으로 현재 상태를 업데이트하여 데이터를 처리하는 방식으로 작동합니다.

RNN의 구조

RNN은 다음과 같은 구성 요소로 이루어져 있습니다:

  • 입력층: 모델의 첫 번째 층으로, 시퀀스 데이터를 입력받습니다.
  • 은닉층: 이전 상태를 기억하고 현재 입력을 결합하여 출력을 생성합니다.
  • 출력층: 최종 출력을 생성하는 층입니다.

6. RNN의 훈련 데이터 수집

RNN을 훈련시키기 위해서는 적절한 훈련 데이터가 필요합니다. 여기서는 텍스트 데이터를 수집하고 전처리하는 과정을 설명하겠습니다.

6.1 데이터 수집

RNN의 훈련에 사용할 수 있는 데이터는 다양합니다. 예를 들어, 영화 리뷰, 소설, 뉴스 기사 등 여러 형태의 텍스트 데이터가 가능합니다.
웹 스크래핑 도구(예: BeautifulSoup)를 사용하여 데이터를 수집할 수 있습니다.


import requests
from bs4 import BeautifulSoup

url = 'https://example.com/articles'  # 원하는 URL로 변경
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')

articles = []
for item in soup.find_all('article'):
    title = item.find('h2').text
    content = item.find('p').text
    articles.append(f"{title}\n{content}")

with open('data.txt', 'w', encoding='utf-8') as f:
    for article in articles:
        f.write(article + "\n\n")
    

6.2 데이터 전처리

수집한 데이터는 RNN 모델의 입력으로 사용하기 전, 전처리 과정을 거쳐야 합니다. 일반적인 전처리 과정은 다음과 같습니다:

  • 소문자화
  • 특수문자 및 숫자 제거
  • 불용어 제거

import re
import nltk
from nltk.corpus import stopwords

# nltk의 불용어 목록 다운로드
nltk.download('stopwords')
stop_words = set(stopwords.words('english'))

def preprocess_text(text):
    # 소문자화
    text = text.lower()
    # 특수문자 및 숫자 제거
    text = re.sub(r'[^a-z\s]', '', text)
    # 불용어 제거
    text = ' '.join([word for word in text.split() if word not in stop_words])
    return text

# 전처리 적용
preprocessed_articles = [preprocess_text(article) for article in articles]
    

7. RNN 모델 구현 예제

환경 설정

pip install torch torchvision nltk

파이토치를 활용한 RNN 코드 예제

아래는 간단한 RNN 모델의 구현 예제입니다. word embedding을 사용하여 텍스트 데이터를 처리합니다.


import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader

# RNN 모델 정의
class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(RNN, self).__init__()
        self.embedding = nn.Embedding(input_size, hidden_size)
        self.rnn = nn.RNN(hidden_size, hidden_size)
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        x = self.embedding(x)
        output, hidden = self.rnn(x)
        output = self.fc(output[-1])
        return output

# 훈련 데이터셋 생성
class TextDataset(Dataset):
    def __init__(self, texts, labels):
        self.texts = texts
        self.labels = labels

    def __len__(self):
        return len(self.labels)

    def __getitem__(self, idx):
        return torch.tensor(self.texts[idx]), torch.tensor(self.labels[idx])

# 하이퍼파라미터 설정
input_size = 1000  # 단어 수
hidden_size = 128
output_size = 2  # 분류할 클래스 수 (예: 긍정/부정)
num_epochs = 20
learning_rate = 0.001

# 데이터 로드 및 전처리
# 여기서는 가상의 데이터로 대체합니다.
texts = [...]  # 전처리된 텍스트 데이터
labels = [...]  # 해당 클래스 레이블

dataset = TextDataset(texts, labels)
data_loader = DataLoader(dataset, batch_size=32, shuffle=True)

# 모델 초기화
model = RNN(input_size, hidden_size, output_size)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# 훈련 시작
for epoch in range(num_epochs):
    for texts, labels in data_loader:
        optimizer.zero_grad()
        outputs = model(texts)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item()}")
    

8. 마무리

이번 글에서는 파이토치를 활용하여 GAN 및 RNN의 기본 원리와 구현 예제를 학습하였습니다.
GAN을 사용하여 이미지 데이터를 생성하고, RNN의 경우 텍스트 데이터를 처리하는 과정을 살펴보았습니다.
이러한 기술들은 앞으로도 계속 발전하여 더 많은 분야에서 활용될 것입니다.
여러분도 이러한 기술들을 활용하여 새로운 프로젝트를 시작해 보시기 바랍니다.