[리뷰] GAN 첫걸음



한빛미디어 출판사의 "GAN 첫걸음(타리크 라시드, 고락윤 저)"를 읽고 작성한 리뷰입니다.

표지


GAN(Generative Adversarial Network, 생성적 적대 신경망)은 서로 경쟁하는 두 개의 신경망(생성자, 판별자)으로 구현된다. 생성자는 새로운 데이터를 생성하며, 판별자는 가짜와 실제를 구별한다. 생성자와 판별자는 서로 이기려는 경쟁을 지속하는데 위조범이 그럴듯한 모조품을 만들면 판별자가 잡아내는 식의 경쟁이다.

말이 쉽지 GAN을 배우려고 책을 펴면 이상한 것들을 새로 배워야 한다. 오토인코더 부터 시작해서 G와 D가 팽팽하게 서로 당기고 있는 이상한 긴 수식, Likelihood에서 부터 각종 확률과 분포 등등..

반면 이 책은 GAN을 처음 접하거나 어려워 포기했던 이들에게 제 격인 책인 것 같다. 내 기억이 맞다면 오토 인코더라는 말은 한마디도 안나왔다. 대표적으로 눈에 띄는 장점을 정리하면 다음과 같다.

  • GAN의 핵심을 3단계로 정리하고 예제로 구현하는 부분은 그 어느 책보다도 전달력이 뛰어났다.

  • 반드시 필요한 것만 간추려 알려주고 있어 완급 조절이 훌륭한 책이다.

  • 계보(AE, VAE, GAN, DCGAN, MMGAN, NSGAN, WGAN, WGAN-GP, ProGAN, SGAN, CGAN, CycleGAN, RGAN, SAGAN, BigGAN에 이르는…) 흐름이 아닌 모드 붕괴, 경사하강법 등 문제 인식에 초점을` 맞춘 접근법이 마음에 들었다.

  • 난이도는 쉬운 반면, 다루는 깊이는 논쟁이 되고 있는 연구까지 다루고 있다.

  • 아마도 GAN, 딥러닝, PyTorch 셋 다 몰라도 이 책이라면 무난히 GAN의 세계에 입성할 수 있을 것 같다. 정말 쉽다.

간단한 장점만으로는 설명이 부족한 것 같아 전체적인 구성 및 책을 읽으며 인상깊었던 핵심 내용들을 위주로 아래와 같이 정리해 보았다.


  • 파트 1 : 준비과정
    먼저 PyTorch와 Colab의 기초를 배운다. Define By Run 방식의 계산 그래프를 토대로 자동 미분을 실습하는 과정을 통해 PyTorch의 활용법과 직관적인 장점을 느낄 수 있다.

    다음으로 MNIST 손글씨 분류 신경망을 만들어 본다. Pandas와 Matplotlib으로 MNIST 데이터가 어떻게 생겼는지 열어본 후, 기본적인 네트워크를 구성한다. 오차를 정의하는 손실함수, 가중치 학습 방법인 옵티마이저, train() 함수 등을 만들며 신경망의 기본을 다진다.

    이어서 만든 모델의 성능을 단계적으로 아래와 같이 향상시킨다.

    • 손실함수 : MSE -> BCE
    • 활성화함수 : Sigmoid -> LeakyReLU
    • 옵티마이저 : SGD -> Adam
    • 정규화 적용 : LayerNorm()
      위 단계를 거쳐 모델의 성능을 87%에서 97%까지 끌어올리는데, 딥러닝의 성능 개선을 위한 일반적인 방법을 핵심만 잘 간추리고 있다.

    다음으로 CUDA는 어떻게 활용하는지, 성능은 얼마나 향상되는지 측정해본다.

    • Vectorization : Python(for) -> Numpy(행렬) / 1500배 성능 향상
    • CUDA : Numpy(CPU) -> CUDA(GPU) / 150배 성능 향상

    파트1은 정리하자면 딥러닝과 PyTorch의 기본을 복습하는 장이다. 이미 둘을 잘 알고 있다면 건너 뛰어도 무방하다.

    하지만 스스로 딥러닝이 부족하다고 느껴진다면 반드시 꼼꼼하게 익히고 넘어가야 한다. 판별자가 딥러닝 모델과 거의 유사하기 때문이다. 판별자도 제대로 만들기 어렵다면 더욱 까다로운 생성자 혹은 판별자와 생성자 간 통신을 이해하기 어려울 것이다.

    GAN을 배우고 처음으로 맞닥드렸던 난관이 모드 붕괴였는데 아마 대부분 공통적으로 겪는 현상이 아닌가 싶다. 뒤에 이를 해결하기 위해서 딥러닝의 성능 개선 방법을 미리 익혀두는 것은 필수이며, 이를 확실히 알기 위해서는 딥러닝의 기초가 필수다. 또 이를 위해 PyTorch이나 Colab 실습 환경 사용법을 숙지해야 함은 말할 필요도 없다.

    이처럼 큰 집을 만들기 위해 초보자들도 쉽게 따라할 수 있도록 벽돌을 아래부터 하나씩 차곡차곡 쌓아올리는 구성이 인상적이었다.


  • 파트2 : GAN의 핵심
    먼저 GAN의 핵심 개념을 살펴보자.
    • MNIST 신경망이 아무 그림이나 Input으로 받아 0 ~ 9(10개)를 Output으로 내보내는 과정은 정보가 줄어드는 압축이라고 볼 수 있다. 이를 뒤집어 10개의 숫자를 입력하여 어떤 그림이 나오도록 확대하면 이미지를 만들어 낼 수 있을 것이다. 원핫 인코딩 벡터가 그 예인데, 대신 평균적인 같은 결과만 나온다는 것이 문제이다. 3을 넣으면 항상 똑같이 생긴 3 모양의 그림이 나오는 셈이다.

    • 여기에서 착안된 구조가 GAN이다. 책에서는 GAN의 핵심을 다음과 같이 3단계로 잘 정리하고 있다.

      • 1단계 : 실제 데이터로 판별기 학습. 레이블은 True(1). 1단계_107p

      • 2단계 : 생성기가 만든 데이터로 판별기 학습. 레이블은 False(0). 2단계_108p

      • 3단계 : 생성기 생성 및 훈련. 생성기의 결과를 판별기가 판단 후 오차 역전파법으로 생성기 가중치 업데이트. 단, 판별자의 가중치는 업데이트 하지 않음. 3단계_108p

    이어서 3개의 예제를 실습한다. 코드 구현을 통해 핵심 개념을 파악할 수 있음은 물론, GAN에서 겪게 되는 어려움인 모드 붕괴 등의 해결책을 익힐 수 있다.

    • 1010패턴
      [1,0,1,0]의 데이터를 입력받아 동일한 [1,0,1,0]을 생성하는 심플한 GAN을 만들어 본다.(엄밀히 1은 0.8 ~ 1.0의 임의의 수치를, 0은 0.0 ~ 0.2의 임의 수치를 의미한다.)

      비슷한 결과를 만들어내는 이 작업이 무슨 의미가 있냐 할 수 있겠지만 군더더기를 다 걷어냄으로써 핵심만 볼 수 있는 효과가 있는 매력적인 예제이다. 위의 3단계 핵심 개념에 맞춰 구현한 소스 코드는 아래와 같다. PyTorch답게 직관적이다.

          # 1단계 : 판별기 훈련(참 데이터)
          D.train(generate_real(), torch.FloatTensor([1.0]))
          # 2단계 : 판별기 훈련(거짓(생성기) 데이터)
          # D가 훈련되지 않도록 detach()로 계산 그래프에서 떼어내므로 자동 미분 불가
          # 생성기 인자가 0.5이므로 [1,0,1,0] 패턴은 등장하기 어렵다
          D.train(G.forward(torch.FloatTensor([0.5])).detach(), torch.FloarTensor([0.0]))
          # 3단계 : 생성기 훈련
          # D의 오차가 전달되어 G의 가중치를 갱신
          G.train(D, torch.FloatTensor([0.5]), torch.FloatTensor([1.0]))
      

      이 예제에서 또 하나의 눈여겨볼 점은 손실 그래프를 그리면 0.25 값이 나온다는 사실이다. G의 인자로 활용된 0.5가 평균제곱(MSE)되어 0.25가 되었기 때문이다.

    • MNIST
      이 예제의 핵심은 모드 붕괴이다. 아래 그림과 같이 생성기가 하나 혹은 일부 클래스만 만들게 되는 현상으로 아직도 연구가 진행중이다.

      모드붕괴_146p

      생성기가 판별기 성능을 앞선 후, 실제에 결과가 가깝게 나오는 꿀 지점을 발견하여 그 이미지를 계속 만들어 낸다는 것이 이를 설명하는 그럴듯한 이론이다.

      예제에서는 손실함수 및 활성화함수 변경, 정규화, 생성기 입력을 정규화 하고 늘리는 방법 등을 통해 모드 붕괴를 개선한다.

      또 눈여겨 볼 점은 G와 D의 균형점에서 BCELoss()의 값이 0.693 정도의 값으로 수렴하는 것이 이상적임을 설명해준다. 이는 이진 교차 엔트로피에서 예상되는 손실 ln(2)의 값으로 부록 “이상적인 손실값” 부분에서 보다 심도 있게 다룬다.

      더불어 입력 시드를 더할 경우 이미지가 겹쳐 보이는(예를 들면 : 3모양 + 5모양 = 겹치면 8 모양) 현상이 나타나지만, 뺄 경우 직관적으로 예측이 불가능한 결과를 보이는 연구도 언급한다.

      이처럼 난이도는 쉬운 반면 다루는 깊이는 논쟁이 되고 있는 연구에 이르고 있어 이 또한 책의 장점이라 할 수 있겠다.

    • 얼굴이미지 생성
      이 예제의 핵심은 RGB, HDF5, CUDA 활용이다. 그리고 드디어 Likelihood의 개념이 등장하기 시작한다. (재미있는 것은 저자분이 예제마다 운이 좋게도 테슬라 T4를 얻었다고 자랑하신다. 아무래도 코랩 Pro나 유료 서비스를 이용하시는 것 같은데 은근 귀여우심..ㅎㅎ)

      얼굴_189p


  • 파트3 : 합성곱과 조건부 GAN
    이 파트에서는 GAN의 품질을 조금 더 높힐 수 있는 방법들을 다룬다. CNN을 활용하는 DCGAN, 메모리 공간복잡도 측정법, GELU 활성화 함수가 소개된다.

    특히, CNN의 구조를 직관적으로 잘 설명하고 있고 - 왠만한 딥러닝만 집중으로 다루는 책보다 훨씬 낫다 - 부록에서는 CNN 네트워크 설계 방법과 관련된 Tip을 다루고 있다. 예전에 들었던 앤드루 응 교수님의 코세라 대표 강의 Deep Learning Specialization보다도 핵심을 더 잘 요약했다고 생각한다. 부록_264p

    CNN의 적용한 결과 위 얼굴이미지 예제에 비해 윤곽선이 또렸해 졌음을 확인할 수 있다. CNN적용_222p

    이어서 조건부 GAN 파트에서는 레이블과 Input 관계를 학습하는 것에 초점을 맞춰 특정 레이블에만 조건부로 집중하여 품질을 향상시켜 본다.

    마지막으로 부록에서는 위에 언급한 것들을 제외하고도 GAN의 우도 학습이나, f = xy 같은 심플한 함수로 불안정한 학습과 경사학습법의 한계를 다룬다. GAN의 심화 단계로 넘어가기 위한 필수 개념들을 심플하게 잘 전달하고 있다. 부록_268p


끝으로 대부분의 기술서들과 달리 열정만 있으면 실력이 없어도 익힐 수 있는 차별화된 장점을 갖춘 멋진 책이라는 점을 강조하며 리뷰를 마친다.







© 2019.04. by theorydb

Powered by theorydb