DL/Computer Vision

[Computer Vision] GAN(Generative Adversarial Nets) 논문 리뷰 및 구현 (2)

moonzoo 2023. 1. 17. 14:37

이전글 ) GAN 논문 리뷰

 

[DL-Papers] GAN(Generative Adversarial Nets) 논문 리뷰 및 구현 (1)

지금까지 논문 스터디 학회 활동과 개인적으로 정리했던 논문들을 하나씩 올려보려고합니다. 과거에 정리한 글을 올리면서 잊어버렸던 내용을 상기시키면서 조금씩 부족한 부분을 최대한 수정

mz-moonzoo.tistory.com

GAN 요약

G: Generative model

  • GAN은 생성모델로 이미지, 음성, sequentail data등 원하는 형태의 데이터를 만드는 모델이다.
  • Discriminative model을 상대로 완벽하게 속이고자 한다. -> training data의 분포를 모사함

D: Discriminative model

  • 실제 데이터와 생성 모델이 만들어낸 데이터를 구별
  • sample 데이터가 G로부터 나온 데이터가 아닌 실제 training data로부터 나온 데이터일 확률을 추정
 
이 논문에서 adversarial nets 프레임워크의 컨셉은 ‘경쟁’으로, Discriminative model은 sample data가 G model이 생성한 sample data인지, 실제 training data 분포인지 판별하는 것을 학습한다.

 

코드 구현

GAN을 구현하고 학습 데이터 셋은 MNIST데이터셋을 통해서 새로운 MNIST를 만들어보려 한다.

 

Libary Import

신경망을 만들기 위해 여기서는 torch를 사용했고 데이터셋, 아키텍처 모델, 이미지 변환 기능으로 구성되어 있는 패키지인 torchvision을 improt 했다.

 

Load Dataset

학습해서 생성할 데이터셋인 MNIST 데이터를 불러오도록 한다.

샘플 이미지를 확인하면 잘 불러온 것을 확인할 수 있다. 다음으로 데이터로더 함수를 사용해 데이터 로더를 생성했다.

데이터 로더의 batch_size를 32로 해줬기 때문에 아래 체크에서 보면 x.shape가 [32, 1, 28, 28]이 나오게 된다.

 

모델 구축하기

Generator

먼저, 우리는 G에게 줄 Random Noise를 생성하게 된다. 이 Noise는 G가 Fake Image를 만들 재료로 쓰이게 된다.

_fc_layer을 보면  Linear -> Batchnorm -> LeakyReLU로 layers 반환한다. 그럼 이제 self.model을 보도록 하겠다.

 

우선 self._fc_layer(self.nz,128,noralize=False)로 노이즈 레이어를 추가해줬다.

다음은 self._fc_layer(128,256) 128은 입력값으로 벡터 latent size를 넣어줬다. * 64,128,256 여기선 128

마지막 nn.Linear(1024,int(np.prod(self.img_size)))로 출력하고자하는 이미지 사이즈가 28*28이므로 마지막 layer에서 view를 이용해 shape을 맞춰준다.

마지막으로 Tanh() 함수를 사용해 출력되는 값을 -1~1 사이로 맞춰준다.

그리고 마지막으로 MNIST 픽셀 범위도 -1~1로 맞춰주면 판별 조건이 모두 갖춰진다.

 

Discriminator

판별자는 생성자에 비해 비교적으로 간단하다.

우선 입력값으로 nn.Linear(784,512)을 받아 생성자에서 생성한 이미지를 받아준다.

그렇게 Linear -> LeakyReLU -> Linear -> Sigmoid로 구성된다.

판별자는 어떠한 데이터가 진짜인지 가짜인지 판단해야 하므로 한 개의 확률값을 만들어내야만 한다.

따라서 마지막에는 출력값을 1개의 값으로 만들어주고 이를 0~1 사이의 확률값으로 만들어주기 위해 sigmoid를 사용

 

Pytorch forward()는 모델이 학습데이터 x를 입력 받아서 forward propagation을 진행시키는 함수이다.
반드시 forward라는 이름의 함수여야 한다.

 

학습하기

 

가중치 초기화

  • 가중치 초기화(weight initialization)는 딥러닝 학습의 어려움을 극복하기 위한 방법 중 하나이다.
  • 초기값을 올바르게 설정하는 것이 이유
    optimization에서 어떤 초기값에서 출발하느냐에 따라 local minimum, global minimum에 빠지느냐가 결정되기 때문에 아무리 좋은 optimizer를 사용하여도 초기값을 잘못 설정하면 global minimum으로 수렴하기가 상당히 어렵다
  • 하지만 딥러닝 모델은 거대한 feature space를 가지고 있기 때문에 올바른 초기값을 설정하는 것은 어렵다
  • forward에서는 전달되는 값이 너무 커지거나 작아지지 않게, backward에서는 grdadient vanishing/exploding이 일어나지 않게 weight를 적절히 초기화하는 것이 중요하지만 이는 정해진 규칙이 없으며 휴리스틱하게 설정해야 함.

 

neuron의 가중치를 기반으로 error를 결정하기 때문이고, 정확한 모델을 얻으려면 작은 error를 필요로 하기 때문에 가중치의 초깃값 설정이 중요하다.

 

파라미터 세팅

 

마지막 레이어가 노드수가 1개일 경우에는 보통 Binary Classification을 할때 사용될수가 있는데

이럴경우 BCELoss를 사용하기도 한다. 

BCELoss함수를 사용할 경우에는 먼저 마지막 레이어의 값이 0~1로 조정을 해줘야하기 때문에

단순하게 마지막 레이어를 nn.Linear로 할때 out of range 에러가 뜬다.

따라서 BCELoss함수를 쓸땐 마지막 레이어를 시그모이드함수를 적용시켜줘야 한다.

 

이 구현에선 BCELoss 사용

 

학습 시작

loss_real = loss_func(out_real, yb_real)) (진짜 이미지에 대한 Loss) 

loss_fake = criterion(out_real,yb_fake))(가짜 이미지에 대한 Loss)를 구해서 평균을 구하고, backward해준다.

Generator의 목표는 lossG를 구하고 backward

간단히 구현한 모델이라 그런지 성능이 그렇게 좋지는 않은것 같지만 크게보면 loss가 떨어지는 것을 볼 수 있다

 

가짜 이미지 시각화

생각보다 알아볼 수 있는 이미지가 생성된 것을 확인할 수 있다.

 

후기

이렇게 간단한 GAN 구현까지 마치도록 하겠습니다. 이 논문이 발표된 2014년 이후에 계속해서 여러 GAN논문이 나왔는데 확인 해봤는데 다음 글에서는 CycleGAN에 대해 다뤄보도록 하겠습니다.