GAN(Generative Adversarial Network)을 활용하여 이미지 증폭을 시키는 모델을 구현하려면 다음과 같이 코드를 작성할 수 있습니다. 아래 코드는 간단한 GAN을 사용하여 MNIST 숫자 데이터를 생성하는 예시입니다. 이 코드를 참고하여 이미지 데이터를 증폭시키는 GAN 모델을 구현하실 수 있습니다.
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
# Device configuration
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# Hyperparameters
latent_size = 64
hidden_size = 256
image_size = 784
num_epochs = 100
batch_size = 100
learning_rate = 0.0002
# MNIST dataset
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=(0.5,), std=(0.5,))
])
mnist_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transform, download=True)
data_loader = DataLoader(dataset=mnist_dataset, batch_size=batch_size, shuffle=True)
# Generator model
class Generator(nn.Module):
def __init__(self):
super(Generator, self).__init__()
self.model = nn.Sequential(
nn.Linear(latent_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, image_size),
nn.Tanh()
)
def forward(self, x):
return self.model(x)
# Discriminator model
class Discriminator(nn.Module):
def __init__(self):
super(Discriminator, self).__init__()
self.model = nn.Sequential(
nn.Linear(image_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, 1),
nn.Sigmoid()
)
def forward(self, x):
return self.model(x)
# Initialize models and optimizers
generator = Generator().to(device)
discriminator = Discriminator().to(device)
criterion = nn.BCELoss()
optimizer_g = torch.optim.Adam(generator.parameters(), lr=learning_rate)
optimizer_d = torch.optim.Adam(discriminator.parameters(), lr=learning_rate)
# Training
total_step = len(data_loader)
for epoch in range(num_epochs):
for i, (images, _) in enumerate(data_loader):
images = images.reshape(-1, image_size).to(device)
real_labels = torch.ones(batch_size, 1).to(device)
fake_labels = torch.zeros(batch_size, 1).to(device)
# Train discriminator
outputs = discriminator(images)
d_loss_real = criterion(outputs, real_labels)
real_score = outputs
z = torch.randn(batch_size, latent_size).to(device)
fake_images = generator(z)
outputs = discriminator(fake_images.detach())
d_loss_fake = criterion(outputs, fake_labels)
fake_score = outputs
d_loss = d_loss_real + d_loss_fake
optimizer_d.zero_grad()
d_loss.backward()
optimizer_d.step()
# Train generator
z = torch.randn(batch_size, latent_size).to(device)
fake_images = generator(z)
outputs = discriminator(fake_images)
g_loss = criterion(outputs, real_labels)
optimizer_g.zero_grad()
g_loss.backward()
optimizer_g.step()
if (i+1) % 200 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{total_step}], '
f'D_loss: {d_loss.item():.4f}, G_loss: {g_loss.item():.4f}, '
f'D(x): {real_score.mean().item():.2f}, D(G(z)): {fake_score.mean().item():.2f}')
# Generate sample images
with torch.no_grad():
z = torch.randn(batch_size, latent_size).to(device)
fake_images = generator(z)
fake_images = fake_images.reshape(-1, 1, 28, 28)
torchvision.utils.save_image(fake_images, f'gan_samples_{epoch+1}.png', normalize=True)
# Save models
torch.save(generator.state_dict(), 'generator.ckpt')
torch.save(discriminator.state_dict(), 'discriminator.ckpt')
# Hyperparameters
latent_size = 64 # 잠재 벡터의 크기
hidden_size = 256 # 은닉층의 크기
image_size = 784 # 이미지 크기
num_epochs = 100 # 훈련 에포크 수
batch_size = 100 # 배치 크기
learning_rate = 0.0002 # 학습률
답변 )
하이퍼파라미터(Hyperparameter)는 모델을 훈련할 때 사용되는 설정 값으로, 모델의 구조나 학습 프로세스를 제어하고 조정하는 데 사용됩니다. 하이퍼파라미터는 사람이 직접 지정해야 하며, 모델 자체의 파라미터(가중치 및 편향)와는 달리 자동으로 학습되지 않습니다. 이러한 하이퍼파라미터의 조정은 모델의 성능과 수렴 속도에 큰 영향을 미칩니다.
아래에서 코드에서 사용된 각 하이퍼파라미터에 대해 설명해보겠습니다:
latent_size
(잠재 벡터의 크기):
hidden_size
(은닉층의 크기):
image_size
(이미지 크기):
num_epochs
(훈련 에포크 수):
batch_size
(배치 크기):
learning_rate
(학습률):
이러한 하이퍼파라미터들은 모델의 성능과 학습의 안정성에 영향을 미치기 때문에 조심스럽게 조정하는 것이 중요합니다. 실험을 통해 최적의 값을 찾는 것이 일반적인 접근 방법입니다.
MNIST는 손글씨 숫자 이미지 데이터셋으로, 0부터 9까지의 숫자가 각각의 클래스로 지정되어 있는 데이터셋입니다. torchvision 라이브러리는 여러 데이터셋과 트랜스폼(transform) 기능을 제공하여 데이터를 효율적으로 불러오고 전처리할 수 있습니다.
아래는 주어진 코드에서 사용된 transform
에 대한 설명입니다:
transform = transforms.Compose([
transforms.ToTensor(), # 이미지를 PyTorch 텐서로 변환
transforms.Normalize(mean=(0.5,), std=(0.5,)) # 이미지의 픽셀 값을 정규화
])
transforms.ToTensor()
:
transforms.Normalize(mean=(0.5,), std=(0.5,))
:
-1
에서 1
사이로 데이터를 조정하고자 하기 때문에 0.5
로 설정되었습니다.이렇게 transform
을 정의하여 데이터셋을 전처리하면, 데이터를 로드할 때마다 이미지가 텐서로 변환되고 정규화되어 모델 학습에 적합한 형태로 준비됩니다.
torchvision.datasets.MNIST
및 DataLoader
를 사용하여 MNIST 데이터셋을 로드하고 데이터를 미니배치로 나누는 과정.
mnist_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transform, download=True)
data_loader = DataLoader(dataset=mnist_dataset, batch_size=batch_size, shuffle=True)
torchvision.datasets.MNIST
:
torchvision.datasets
모듈은 다양한 이미지 데이터셋을 제공합니다.MNIST
클래스는 MNIST 데이터셋을 로드하기 위한 클래스입니다.root
: 데이터셋이 저장될 디렉토리 경로를 지정합니다. 여기에서는 ./data
디렉토리에 저장됩니다.train
: 데이터셋의 훈련용 데이터를 사용할지 여부를 지정합니다.transform
: 이미지 데이터에 적용할 전처리 트랜스폼을 지정합니다. 위에서 설명한 대로 ToTensor
와 Normalize
트랜스폼이 적용됩니다.download
: 데이터셋이 로컬에 없는 경우, 인터넷에서 데이터셋을 다운로드할지 여부를 지정합니다.DataLoader
:
DataLoader
는 데이터셋을 미니배치로 나누어주는 유틸리티 클래스입니다.dataset
: 데이터셋 객체를 지정합니다. 위에서 로드한 mnist_dataset
을 사용합니다.batch_size
: 한 번에 로드되는 미니배치의 크기를 지정합니다.shuffle
: 데이터를 섞을지 여부를 지정합니다. 훈련 과정에서 데이터를 무작위로 섞는 것이 도움이 됩니다.이렇게 작성된 코드는 mnist_dataset
을 data_loader
로 미니배치 단위로 분할하여 사용할 수 있게 준비합니다. data_loader
는 반복 가능한 객체이며, 반복문을 사용하여 각 스텝마다 미니배치를 얻을 수 있습니다. 데이터셋을 미니배치로 나누어 효율적으로 모델을 학습시키거나 평가하는 데 사용됩니다.
# Generator model
# 생성자 신경망은 Generator라는 클래스로 정의되며, nn.Module을 상속받습니다.
# 이 생성자는 두 개의 선형 레이어, ReLU 활성화 함수, 그리고 최종적으로 Tanh 활성화 함수로 구성되어 있습니다.
# Tanh 함수를 사용하여 픽셀 값이 -1에서 1 사이에 있도록 합니다.
class Generator(nn.Module):
def __init__(self):
super(Generator, self).__init__()
self.model = nn.Sequential(
nn.Linear(latent_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, image_size),
nn.Tanh()
)
def forward(self, x):
return self.model(x)
클래스 정의 (class Generator(nn.Module):
):
nn.Module
클래스를 상속받아 정의됩니다.nn.Module
을 상속받는 것으로 PyTorch에서 모델을 정의하고 학습하기 위한 기본적인 틀을 생성합니다.__init__
메서드:
super(Generator, self).__init__()
은 부모 클래스의 초기화 메서드를 호출하는 코드로, 상속받은 클래스의 초기화를 수행합니다.신경망 구성 (self.model = nn.Sequential(...)
):
nn.Sequential
객체가 있습니다.nn.Sequential
은 여러 개의 레이어를 순차적으로 쌓아서 신경망을 구성할 수 있게 해주는 컨테이너입니다.nn.Linear(latent_size, hidden_size)
:
latent_size
)와 은닉층 크기(hidden_size
)를 연결하는 선형 레이어입니다.nn.ReLU()
:
nn.Linear(hidden_size, image_size)
:
image_size
)로 변환하는 선형 레이어입니다.nn.Tanh()
:
forward
메서드:
x
를 self.model
에 전달하여 생성된 이미지를 반환합니다.이렇게 생성자 신경망은 잠재 벡터를 입력으로 받아 이미지를 생성하는 역할을 수행합니다. GAN의 생성자는 무작위 잠재 벡터를 입력으로 받아 현실적인 이미지처럼 보이는 가짜 이미지를 생성하는 능력을 가집니다.
생성자 신경망의 구조를 그림으로 표현하면 아래와 같습니다. 이 구조는 코드에서 정의한 대로, 두 개의 선형 레이어와 활성화 함수로 구성되어 있습니다.
Generator (
(model): Sequential (
(0): Linear(in_features=64, out_features=256, bias=True)
(1): ReLU()
(2): Linear(in_features=256, out_features=784, bias=True)
(3): Tanh()
)
)
위의 그림에서 in_features
는 입력 특성의 수를 나타내며, out_features
는 출력 특성의 수를 나타냅니다. 생성자의 구조는 다음과 같이 설명할 수 있습니다:
첫 번째 선형 레이어 (Linear(in_features=64, out_features=256, bias=True)
):
in_features
)는 잠재 벡터의 크기인 64입니다.out_features
)는 은닉층의 크기인 256입니다.ReLU 활성화 함수:
두 번째 선형 레이어 (Linear(in_features=256, out_features=784, bias=True)
):
in_features
)는 은닉층의 크기인 256입니다.out_features
)는 이미지의 크기인 784입니다.Tanh 활성화 함수:
이 구조를 이해하면, 생성자가 어떻게 잠재 벡터를 입력으로 받아 실제 이미지와 유사한 이미지를 생성하는지 이해할 수 있을 것입니다.
이 코드는 생성자와 마찬가지로 nn.Module
을 상속받아 정의되며, 두 개의 선형 레이어와 활성화 함수로 구성되어 있습니다.
class Discriminator(nn.Module):
def __init__(self):
super(Discriminator, self).__init__()
self.model = nn.Sequential(
nn.Linear(image_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, 1),
nn.Sigmoid()
)
def forward(self, x):
return self.model(x)
클래스 정의 (class Discriminator(nn.Module):
):
nn.Module
클래스를 상속받아 정의됩니다.nn.Module
을 상속받는 것으로 PyTorch에서 모델을 정의하고 학습하기 위한 기본적인 틀을 생성합니다.__init__
메서드:
super(Discriminator, self).__init__()
은 부모 클래스의 초기화 메서드를 호출하는 코드로, 상속받은 클래스의 초기화를 수행합니다.신경망 구성 (self.model = nn.Sequential(...)
):
nn.Sequential
객체가 있습니다.nn.Sequential
은 여러 개의 레이어를 순차적으로 쌓아서 신경망을 구성할 수 있게 해주는 컨테이너입니다.nn.Linear(image_size, hidden_size)
:
image_size
)와 은닉층 크기(hidden_size
)를 연결하는 선형 레이어입니다.nn.ReLU()
:
nn.Linear(hidden_size, 1)
:
nn.Sigmoid()
:
forward
메서드:
x
를 self.model
에 전달하여 식별자의 출력을 반환합니다.이렇게 식별자 신경망은 입력된 데이터가 진짜 데이터일 확률을 추정하는 역할을 수행합니다. GAN에서 식별자는 생성된 이미지와 실제 이미지를 구분하는 역할을 담당하며, 이를 통해 생성자를 더 나은 이미지를 생성하도록 학습시키는 경쟁 관계가 형성됩니다.
생성자 신경망과 마찬가지로 식별자 신경망의 구조를 그림으로 표현하면 아래와 같습니다. 이 구조는 코드에서 정의한 대로, 두 개의 선형 레이어와 활성화 함수로 구성되어 있습니다.
Discriminator (
(model): Sequential (
(0): Linear(in_features=784, out_features=256, bias=True)
(1): ReLU()
(2): Linear(in_features=256, out_features=1, bias=True)
(3): Sigmoid()
)
)
위의 그림에서 in_features
는 입력 특성의 수를 나타내며, out_features
는 출력 특성의 수를 나타냅니다. 식별자의 구조는 다음과 같이 설명할 수 있습니다:
첫 번째 선형 레이어 (Linear(in_features=784, out_features=256, bias=True)
):
in_features
)는 이미지의 크기인 784입니다.out_features
)는 은닉층의 크기인 256입니다.ReLU 활성화 함수:
두 번째 선형 레이어 (Linear(in_features=256, out_features=1, bias=True)
):
in_features
)는 은닉층의 크기인 256입니다.out_features
)는 1로서, 하나의 출력 뉴런을 가진 선형 레이어입니다.Sigmoid 활성화 함수:
이 구조를 이해하면, 식별자가 어떻게 입력된 이미지를 진짜 데이터와 가짜 데이터로 구분하려고 하는지 이해할 수 있을 것입니다. GAN의 식별자는 이진 분류 문제로써, 입력 데이터가 진짜 데이터인지 가짜 데이터인지를 확률로 예측하는 역할을 합니다.
# Initialize models and optimizers
# 생성자와 식별자의 인스턴스를 생성하고, 선택한 장치(CPU 또는 GPU)로 이동시킵니다.
# 손실 함수(nn.BCELoss)와 옵티마이저(Adam)를 생성자와 식별자 각각에 대해 정의합니다.
generator = Generator().to(device)
discriminator = Discriminator().to(device)
criterion = nn.BCELoss()
optimizer_g = torch.optim.Adam(generator.parameters(), lr=learning_rate)
optimizer_d = torch.optim.Adam(discriminator.parameters(), lr=learning_rate)
생성자와 식별자 인스턴스 생성:
Generator()
와 Discriminator()
클래스를 호출하여 생성자와 식별자의 인스턴스를 생성합니다.장치 이동 (to(device)
):
.to(device)
를 사용하여 모델과 관련된 모든 요소를 지정한 장치로 이동시킵니다.손실 함수 (nn.BCELoss()
):
옵티마이저 설정 (torch.optim.Adam
):
generator.parameters()
와 discriminator.parameters()
는 각 모델의 학습 가능한 파라미터들을 가져옵니다.lr=learning_rate
는 학습률(learning rate)로, 옵티마이저가 모델 파라미터를 업데이트할 때 사용되는 스텝 크기를 결정합니다.이렇게 설정된 생성자와 식별자의 인스턴스, 손실 함수, 그리고 옵티마이저는 GAN 학습 과정에서 사용되며, 생성자와 식별자 모두가 경쟁 관계를 통해 서로를 학습하게 됩니다.
전체 코드 :
# Training
# 지정된 에포크 수만큼 훈련 루프가 실행됩니다. 각 에포크마다 루프는 데이터셋 배치를 반복하게 됩니다.
total_step = len(data_loader)
for epoch in range(num_epochs):
for i, (images, _) in enumerate(data_loader):
images = images.reshape(-1, image_size).to(device)
real_labels = torch.ones(batch_size, 1).to(device)
fake_labels = torch.zeros(batch_size, 1).to(device)
# Train discriminator
# 식별자는 실제 이미지와 생성된 이미지를 구별하도록 훈련됩니다.
# 실제 이미지는 식별자를 통과하고 실제 레이블(1)에 대한 손실이 계산됩니다.
# 생성자에 의해 생성된 가짜 이미지는 생성자를 통과한 후 그래디언트를 분리하여 가짜 레이블(0)에 대한 손실이 계산됩니다.
# 전체 식별자 손실은 이 두 손실의 합입니다.
outputs = discriminator(images)
d_loss_real = criterion(outputs, real_labels)
real_score = outputs
z = torch.randn(batch_size, latent_size).to(device)
fake_images = generator(z)
outputs = discriminator(fake_images.detach())
d_loss_fake = criterion(outputs, fake_labels)
fake_score = outputs
d_loss = d_loss_real + d_loss_fake
optimizer_d.zero_grad()
d_loss.backward()
optimizer_d.step()
# Train generator
# 생성자는 식별자를 속이는 이미지를 생성하기 위해 훈련됩니다.
# 무작위 잠재 벡터가 생성되고 생성자의 입력으로 사용됩니다.
# 생성된 이미지는 식별자를 통과하며, 생성자 손실은 실제 레이블(1)에 대한 손실로 계산됩니다.
z = torch.randn(batch_size, latent_size).to(device)
fake_images = generator(z)
outputs = discriminator(fake_images)
g_loss = criterion(outputs, real_labels)
optimizer_g.zero_grad()
g_loss.backward()
optimizer_g.step()
# 그래디언트가 계산되고 그것들을 사용하여 식별자와 생성자 매개변수를 업데이트합니다. 이를 위해 각각의 옵티마이저를 사용합니다.
# 진행 상황 출력: 코드는 훈련 진행 상황을 지정된 간격마다 출력합니다.
if (i+1) % 200 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{total_step}], '
f'D_loss: {d_loss.item():.4f}, G_loss: {g_loss.item():.4f}, '
f'D(x): {real_score.mean().item():.2f}, D(G(z)): {fake_score.mean().item():.2f}')
# Generate sample images
# 각 에포크 후에 생성자는 일괄적인 생성된 이미지를 만듭니다. 이 이미지는 모양을 조정하고 PNG 이미지로 저장됩니다.
with torch.no_grad():
z = torch.randn(batch_size, latent_size).to(device)
fake_images = generator(z)
fake_images = fake_images.reshape(-1, 1, 28, 28)
torchvision.utils.save_image(fake_images, f'gan_samples_{epoch+1}.png', normalize=True)
total_step = len(data_loader)
for epoch in range(num_epochs):
for i, (images, _) in enumerate(data_loader):
images = images.reshape(-1, image_size).to(device)
real_labels = torch.ones(batch_size, 1).to(device)
fake_labels = torch.zeros(batch_size, 1).to(device)
total_step
설정:
total_step
은 전체 데이터셋을 몇 번의 배치로 나누어 훈련할 것인지를 나타냅니다.len(data_loader)
를 사용하여 데이터로더에서 제공되는 총 배치 개수를 계산하여 설정합니다.에포크 루프 (for epoch in range(num_epochs):
):
num_epochs
)만큼 에포크 루프가 실행됩니다.배치 루프 (for i, (images, _) in enumerate(data_loader):
):
data_loader
에서 데이터 배치를 순회하며 반복합니다.enumerate(data_loader)
는 데이터로더에서 배치와 그에 해당하는 인덱스를 함께 제공합니다.이미지 변환과 장치 이동:
-1, image_size
모양으로 변환합니다.-1
차원은 이미지 개수를 유지하고, image_size
차원은 이미지 데이터의 차원을 펼쳐주는 역할을 합니다..to(device)
를 사용하여 이미지 데이터를 지정한 장치(CPU 또는 GPU)로 이동시킵니다.레이블 생성과 장치 이동:
torch.ones(batch_size, 1)
은 batch_size
개수의 1로 이루어진 실제 레이블을 생성합니다.torch.zeros(batch_size, 1)
은 batch_size
개수의 0으로 이루어진 가짜 레이블을 생성합니다.이렇게 위의 코드 블록은 에포크와 배치 루프를 반복하면서 이미지 데이터를 변환하고 장치로 이동시키며 실제 레이블과 가짜 레이블을 생성하는 과정을 수행합니다. 이는 GAN의 훈련 과정에서 식별자와 생성자를 학습시키기 위해 필요한 준비 작업입니다.
# Train discriminator
# 식별자는 실제 이미지와 생성된 이미지를 구별하도록 훈련됩니다.
# 실제 이미지는 식별자를 통과하고 실제 레이블(1)에 대한 손실이 계산됩니다.
# 생성자에 의해 생성된 가짜 이미지는 생성자를 통과한 후 그래디언트를 분리하여 가짜 레이블(0)에 대한 손실이 계산됩니다.
# 전체 식별자 손실은 이 두 손실의 합입니다.
outputs = discriminator(images)
d_loss_real = criterion(outputs, real_labels)
real_score = outputs
z = torch.randn(batch_size, latent_size).to(device)
fake_images = generator(z)
outputs = discriminator(fake_images.detach())
d_loss_fake = criterion(outputs, fake_labels)
fake_score = outputs
d_loss = d_loss_real + d_loss_fake
optimizer_d.zero_grad()
d_loss.backward()
optimizer_d.step()
위 코드 블록은 GAN의 학습 중에서 식별자(discriminator)를 훈련하는 부분을 나타냅니다. 식별자는 진짜 이미지와 가짜 이미지를 구별하도록 학습됩니다. 이때 식별자의 목표는 진짜 이미지에는 높은 확률을, 가짜 이미지에는 낮은 확률을 할당하여 구별하는 것입니다.
outputs = discriminator(images)
:
images
를 식별자에 입력하고, 식별자의 출력을 계산합니다.d_loss_real = criterion(outputs, real_labels)
:
real_labels
와 식별자의 출력 outputs
사이의 손실을 계산합니다.real_score = outputs
:
real_score
에 저장합니다.z = torch.randn(batch_size, latent_size).to(device)
:
z
를 생성합니다. 이 벡터는 생성자에 입력으로 사용됩니다.latent_size
는 잠재 벡터의 차원을 나타냅니다.fake_images = generator(z)
:
z
를 입력으로 주어 가짜 이미지 fake_images
를 생성합니다.outputs = discriminator(fake_images.detach())
:
fake_images
를 식별자에 입력하고, 식별자의 출력을 계산합니다..detach()
를 사용하여 생성자의 그래디언트를 분리합니다. 이는 생성자의 업데이트를 방지하고, 식별자만을 업데이트하는 데 사용됩니다.d_loss_fake = criterion(outputs, fake_labels)
:
fake_labels
와 식별자의 출력 outputs
사이의 손실을 계산합니다.fake_score = outputs
:
fake_score
에 저장합니다.d_loss = d_loss_real + d_loss_fake
:
optimizer_d.zero_grad()
, d_loss.backward()
, optimizer_d.step()
:
d_loss
에 대한 역전파를 수행합니다.이렇게 실제 이미지와 가짜 이미지를 사용하여 식별자를 훈련하게 되면, 식별자는 실제 이미지와 가짜 이미지를 잘 구별할 수 있는 능력을 향상시키게 됩니다.
# Train generator
# 생성자는 식별자를 속이는 이미지를 생성하기 위해 훈련됩니다.
# 무작위 잠재 벡터가 생성되고 생성자의 입력으로 사용됩니다.
# 생성된 이미지는 식별자를 통과하며, 생성자 손실은 실제 레이블(1)에 대한 손실로 계산됩니다.
z = torch.randn(batch_size, latent_size).to(device)
fake_images = generator(z)
outputs = discriminator(fake_images)
g_loss = criterion(outputs, real_labels)
optimizer_g.zero_grad()
g_loss.backward()
optimizer_g.step()
위 코드 블록은 GAN의 학습 중에서 생성자(generator)를 훈련하는 부분을 나타냅니다. 생성자의 목표는 실제 데이터처럼 보이는 가짜 이미지를 생성하여 식별자를 속이는 것입니다.
z = torch.randn(batch_size, latent_size).to(device)
:
z
를 생성합니다. 이 벡터는 생성자의 입력으로 사용됩니다.latent_size
는 잠재 벡터의 차원을 나타냅니다.fake_images = generator(z)
:
z
를 입력으로 주어 가짜 이미지 fake_images
를 생성합니다.outputs = discriminator(fake_images)
:
fake_images
를 식별자에 입력하고, 식별자의 출력을 계산합니다.g_loss = criterion(outputs, real_labels)
:
outputs
와 실제 레이블 real_labels
사이의 손실을 계산합니다.optimizer_g.zero_grad()
, g_loss.backward()
, optimizer_g.step()
:
g_loss
에 대한 역전파를 수행합니다.생성자는 실제 이미지를 보다 잘 모방할 수 있도록 학습됩니다. 이렇게 생성자와 식별자가 서로를 경쟁적으로 학습하면서, 생성자는 더 실제와 유사한 이미지를 생성하고, 식별자는 그 구별 능력을 향상시키는 방향으로 학습이 진행됩니다. 이런 학습의 상호 작용을 통해 GAN은 점차적으로 실제와 유사한 이미지를 생성하도록 생성자를 조정하게 됩니다.
# 진행 상황 출력: 코드는 훈련 진행 상황을 지정된 간격마다 출력합니다.
if (i+1) % 200 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{total_step}], '
f'D_loss: {d_loss.item():.4f}, G_loss: {g_loss.item():.4f}, '
f'D(x): {real_score.mean().item():.2f}, D(G(z)): {fake_score.mean().item():.2f}')
위 코드 블록은 학습 중에 생성자와 식별자의 손실 및 예측 확률 등 학습 진행 상황을 주기적으로 출력하는 부분입니다. 이는 학습 과정을 모니터링하고 학습 진행 상황을 파악하는데 도움을 줍니다.
(i+1) % 200 == 0
:
i
에 대해 200 배치마다 아래의 출력을 실행합니다.f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{total_step}], '
:
f'D_loss: {d_loss.item():.4f}, G_loss: {g_loss.item():.4f}, '
:
D_loss
)과 생성자 손실(G_loss
)을 출력합니다. 손실 값은 소수점 4자리까지 출력됩니다.f'D(x): {real_score.mean().item():.2f}, D(G(z)): {fake_score.mean().item():.2f}'
:
D(x)
는 실제 이미지에 대한 식별자의 평균 예측 확률을 출력합니다. 이 값은 실제 이미지가 얼마나 실제로 인식되는지를 나타냅니다.D(G(z))
는 생성된 이미지에 대한 식별자의 평균 예측 확률을 출력합니다. 이 값은 생성자가 얼마나 실제 이미지와 유사한 이미지를 생성하는지를 나타냅니다.이러한 출력을 통해 학습이 진행되는 동안 식별자와 생성자의 손실 및 예측 확률 등의 변화를 실시간으로 모니터링할 수 있습니다. 학습이 진행됨에 따라 손실이 감소하고, 생성된 이미지가 실제와 유사해지는지 확인할 수 있습니다.
# Generate sample images
# 각 에포크 후에 생성자는 일괄적인 생성된 이미지를 만듭니다. 이 이미지는 모양을 조정하고 PNG 이미지로 저장됩니다.
with torch.no_grad():
z = torch.randn(batch_size, latent_size).to(device)
fake_images = generator(z)
fake_images = fake_images.reshape(-1, 1, 28, 28)
torchvision.utils.save_image(fake_images, f'gan_samples_{epoch+1}.png', normalize=True)
위 코드 블록은 각 에포크가 끝난 후 생성자를 사용하여 가짜 이미지를 생성하고, 이를 이미지 파일로 저장하는 부분을 나타냅니다.
with torch.no_grad():
:
z = torch.randn(batch_size, latent_size).to(device)
:
z
를 생성합니다. 이 벡터는 생성자에 입력으로 주어 가짜 이미지를 생성합니다.latent_size
는 잠재 벡터의 차원을 나타냅니다.fake_images = generator(z)
:
z
를 입력으로 주어 가짜 이미지 fake_images
를 생성합니다.fake_images = fake_images.reshape(-1, 1, 28, 28)
:
fake_images
의 모양을 변경합니다. 일반적으로 생성된 이미지는 일렬로 나열되어 있으므로 이를 28x28 크기의 이미지로 변환합니다.-1
은 나머지 차원을 자동으로 계산하라는 의미입니다. 따라서 배치 크기와 이미지 차원에 따라 알맞게 모양이 조정됩니다.torchvision.utils.save_image(fake_images, f'gan_samples_{epoch+1}.png', normalize=True)
:
fake_images
를 PNG 이미지 파일로 저장합니다.f'gan_samples_{epoch+1}.png'
은 파일 이름으로, 에포크 번호를 포함하여 저장됩니다.normalize=True
는 이미지를 정규화하여 [0, 1] 범위로 변환하여 저장하도록 지정합니다.이렇게 생성자가 생성한 가짜 이미지를 각 에포크가 끝난 후 저장함으로써, 학습 중에 생성자가 어떤 이미지를 생성하고 있는지를 확인할 수 있습니다. 생성된 이미지들이 에포크마다 어떻게 변화하는지를 시각적으로 관찰하여 모델의 진행 상황을 평가하거나 문제를 해결할 수 있습니다.
# Save models
# 훈련 후에 생성자와 식별자 모델의 매개변수 상태를 torch.save를 사용하여 체크포인트 파일로 저장합니다.
torch.save(generator.state_dict(), 'generator.ckpt')
torch.save(discriminator.state_dict(), 'discriminator.ckpt')
위 코드 블록은 학습이 완료된 후 생성자와 식별자 모델의 매개변수 상태를 저장하는 부분입니다. 이렇게 저장된 매개변수 상태를 나중에 로드하여 모델을 재사용하거나 이어서 학습하는데 사용할 수 있습니다.
torch.save(generator.state_dict(), 'generator.ckpt')
:
'generator.ckpt'
라는 파일로 저장합니다.generator.state_dict()
는 생성자 모델의 매개변수들을 딕셔너리 형태로 가져옵니다.torch.save(discriminator.state_dict(), 'discriminator.ckpt')
:
'discriminator.ckpt'
라는 파일로 저장합니다.discriminator.state_dict()
는 식별자 모델의 매개변수들을 딕셔너리 형태로 가져옵니다.이렇게 매개변수 상태를 파일로 저장하면, 이후에 모델을 재구성하거나 다른 프로젝트에서 모델을 사용할 때 유용합니다. 저장된 체크포인트 파일을 로드하여 모델의 매개변수를 설정하면, 해당 모델을 저장한 시점의 상태로 모델을 복구할 수 있습니다.
딥러닝에 대해 열심히 공부하셨군요👍