Deep Learning through deep learning

#3 DCGAN (Generative Adversarial Networks) - CelebA, 자체 제작 데이터셋 실습 본문

ML&DL/GAN

#3 DCGAN (Generative Adversarial Networks) - CelebA, 자체 제작 데이터셋 실습

NeuroN 2023. 8. 2. 16:40

GAN 에 대한 기본적인 훈련을 마쳤으니 이제는 좀 더 안정적이고 고품질의 이미지를 생성해보자.

사실상 이전의 모델은 돌려봤다는 느낌뿐이지 이게 이미지인지 그저 픽셀인지 긴가민가하다.

이 글의 전체적인 내용은 #2 이전 글의 GAN 모델의 이미지 품질 및 안정성 향상을 위한 Convolution Neural Network (CNN) 모델 구조 변경이다.

이전 코드와 데이터셋을 그대로 사용하면서 몇 가지 수정할 부분만 추가할 예정이다.


Coding DCGAN

CelebA 얼굴이미지 데이터 (이미지 데이터 형식)를 활용한 DCGAN

더보기

1. 기존의 코드에서 몇 가지 수정을 거치면 된다.

class Discriminator(nn.Module):
  def __init__(self):
    super().__init__()

    self.model = nn.Sequential(
        # (1,3,128,128) 형태
        nn.Conv2d(3,256,kernel_size=8,stride=2), 
        # 단색이므로 1, 커널크기 8, 보폭 2
        nn.BatchNorm2d(256),
        nn.GELU(),
        nn.Conv2d(256,256,kernel_size=8,stride=2),
        nn.BatchNorm2d(256),
        nn.GELU(),

        nn.Conv2d(256,3,kernel_size=8,stride=2),
        nn.GELU(),

        View(3*10*10), 
        nn.Linear(3*10*10,1),
        nn.Sigmoid())

    self.loss_function = nn.BCELoss()
    self.optimiser = torch.optim.Adam(self.parameters(), lr = 0.0001)
    self.counter = 0
    self.progress = []
    pass
  
  def forward(self, inputs):
    return self.model(inputs)

  def train(self,inputs,targets):
    outputs = self.forward(inputs)
    loss = self.loss_function(outputs,targets)
    self.counter +=1
    if(self.counter%10==0):
      self.progress.append(loss.item())
      pass
    if(self.counter%10000==0):
      print("counter = ",self.counter)
      pass
    
    self.optimiser.zero_grad()
    loss.backward()
    self.optimiser.step()
    pass
  
  def plot_progress(self):
    df = pandas.DataFrame(self.progress, columns=['loss'])
    df.plot(ylim=(0,1.0), figsize=(16,8), alpha=0.1, marker='.', grid=True, yticks=(0,0.25,0.5,1.0,5.0))
    pass

> Discriminator 판별기의 변경된 코드이다.

model 부분에서 기존의 MLP 구조를 CNN 구조로 바꾼다. 이미지 처리에 있어 CNN 구조가 월등히 좋기 때문이며, 이때 단색인 경우 1, 컬러인 경우 3 이다.

class Generator(nn.Module):
  def __init__(self):
    super().__init__()

    self.model = nn.Sequential(
        nn.Linear(100,3*11*11),
        nn.GELU(),
        # 4차원으로 형태 변환
        View((1,3,11,11)), 
        # (1,3,128,128) 형태
        nn.ConvTranspose2d(3,256,kernel_size=8,stride=2), 
        # 컬러이므로 3, 커널크기 8, 보폭 2
        nn.BatchNorm2d(256),
        nn.GELU(),
        nn.ConvTranspose2d(256,256,kernel_size=8,stride=2),
        nn.BatchNorm2d(256),
        nn.GELU(),

        nn.ConvTranspose2d(256,3,kernel_size=8,stride=2,padding=1),
        nn.BatchNorm2d(3),
        
        nn.Sigmoid())

    self.optimiser = torch.optim.Adam(self.parameters(), lr = 0.0001)
    self.counter = 0
    self.progress = []
    pass
  
  def forward(self, inputs):
    return self.model(inputs)

  def train(self,D,inputs,targets):
    g_output = self.forward(inputs)
    d_output = D.forward(g_output)
    loss = D.loss_function(d_output,targets)
    self.counter +=1
    if(self.counter%10==0):
      self.progress.append(loss.item())
      pass
    
    self.optimiser.zero_grad()
    loss.backward()
    self.optimiser.step()
    pass
    
  def plot_progress(self):
    df = pandas.DataFrame(self.progress, columns=['loss'])
    df.plot(ylim=(0,1.0), figsize=(16,8), alpha=0.1, marker='.', grid=True, yticks=(0,0.25,0.5,1.0,5.0))
    pass

> Generator 생성기의 변경된 코드이다.

마찬가지로 MLP 구조를 CNN 으로 변경하였다.

 

2. 위의 D,G 두 함수만을 변경하여 훈련에 들어간다.

1번의 학습 뿐인 결과에도 이전의 결과와는 차원이 다른 고품질의 이미지가 생성된다.

직접 제작한 데이터셋 (이미지 데이터 형식)을 활용한 DCGAN

사실 설명할게 없다. #2에서 말했듯이 이미지 데이터셋 폴더를 만들어 이미지를 zip으로 압축한 후 사용하면 된다. 모델 저장 및 불러오기를 잊지 말자.


else

이번에는 간단한 GAN 성능향상을 위한 DCGAN에 대해 다루었다. WGAN, WGAN-GP, LSGAN 에 대해서도 다룰 예정이지만, 먼저 빠르게 목표에 달성하고자 이쯤에서 '순수한 이미지 생성' 은 마치고자 한다.

이후 '조건부 이미지 생성'  CGAN 에 대한 글을 다룰 예정이며, 드디어 우리는 이미지만 찍어내는 알고리즘이 아닌 내가 원하는 이미지를 찍어내기 위해 다른 접근 방법을 시도해볼 것이다.