ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DCGAN 논문 리뷰(Deep Convolutional Generative Adversarial Networks)
    논문 리뷰 2024. 7. 19. 12:47

    오늘은 GAN 논문에 이어 DCGAN 논문 리뷰를 해보고자 한다. 

     

    논문의 이론보다는 테크니컬한 부분을 많이 다루고 있는 논문이라고 생각된다. GAN이 아무래도 학습하기 어려운 모델이라서 그런지 초기 세팅 등에 대한 팁을 많이 제공하고 있다.

    (누가 봐도 학습하느라 저자들이 엄청 고생한거 같은 논문이다..ㅋㅋㅋㅋ)

     

     

    꽤나 오래된 논문이라서 과거 논문들과의 비교는 생략하고, 이 논문에서 도입한 3가지 CNN 구조에 대해 소개하겠다.

     

    1. pooling 대신에 strided convolution을 사용하자. 

    2. convolutional feature의 가장 윗 부분에서 fully connected layers를 제거하자. 자세한 구조는 Fig. 1에서 제안하고 있다. 

    DCGAN에서 제안한 구조에서는 4개의 fractionally-strided convolutions를 이용해 upsampling을 한다. 이 부분은 나중에 코드에서 보겠지만 ConvTranspose2d로 구현된다.

    3. Batch Normalization을 사용하자. 

    + ReLU activation은 generator에(output에는 Tanh), leaky rectified activation은 discriminator에 사용하자.

     

    정리해서 DCGAN의 초기 세팅에 대해 정리하면 다음과 같다.

     

    논문의 결과는 생략하고 파이토치 사이트에 있는 코드를 뜯어보려고 한다.

    한국어로 번역된 페이지로 살펴보자.( DCGAN 튜토리얼 — 파이토치 한국어 튜토리얼 (PyTorch tutorials in Korean))

     

    생성자와 판별자를 구분해보면 사용된 activation function이 다르다는 것을 알 수 있다. 또한 생성자는 upsampling을 위해 ConvTranspose2d를 사용하는 반면, 판별자는 downsampling을 위해 Conv2d를 사용하는 것을 알 수 있다.

     

    (아래 글은 모두 튜토리얼에서 그대로 가져온 글입니다!!)

     

    Part 1 - 구분자의 학습

    구분자의 목적은 주어진 입력값이 진짜인지 가짜인지 판별하는 것임을 상기합시다. Goodfellow의 말을 빌리자면, 구분자는 “변화도(gradient)를 상승(ascending)시키며 훈련”하게 됩니다. 실전적으로 얘기하면, 𝑙𝑜𝑔(𝐷(𝑥))+𝑙𝑜𝑔(1−𝐷(𝐺(𝑧))) 를 최대화시키는 것과 같습니다. ganhacks 에서 미니 배치(mini-batch)를 분리하여 사용한 개념을 가져와서, 우리 역시 두가지 스텝으로 분리해 계산을 해보겠습니다. 먼저, 진짜 데이터들로만 이루어진 배치를 만들어 𝐷 에 통과시킵니다. 그 출력값으로 (𝑙𝑜𝑔(𝐷(𝑥))의 손실값을 계산하고, 역전파 과정에서의 변화도들을 계산합니다. 여기까지가 첫번째 스텝입니다. 두번째 스텝에서는, 오로지 가짜 데이터들로만 이루어진 배치를 만들어 𝐷 에 통과시키고, 그 출력값으로 (𝑙𝑜𝑔(1−𝐷(𝐺(𝑧))의 손실값을 계산해 역전파 변화도를 구하면 됩니다. 이때 두가지 스텝에서 나오는 변화도들은 축적(accumulate) 시켜야 합니다. 변화도까지 구했으니, 이제 옵티마이저를 사용해야겠죠. 파이토치의 함수를 호출해주면 알아서 변화도가 적용될겁니다.

     

    진짜 데이터로만 이루어진 배치를 통과시키고, 가짜 데이터로만 이루어진 배치를 통과시킨다.(섞지 않는다!)

     

    Part 2 - 생성자의 학습

    오리지널 GAN 논문에 명시되어 있듯, 생성자는 𝑙𝑜𝑔(1−𝐷(𝐺(𝑧)))을 최소화시키는 방향으로 학습합니다. 하지만 이 방식은 충분한 변화도를 제공하지 못함을 Goodfellow가 보여줬습니다. 특히 학습초기에는 더욱 문제를 일으키죠. 이를 해결하기 위해 𝑙𝑜𝑔(𝐷(𝐺(𝑧)))를 최대화 하는 방식으로 바꿔서 학습을 하겠습니다. 코드에서 구현하기 위해서는 Part 1에서 한대로 구분자를 이용해 생성자의 출력값을 판별해주고, 진짜 라벨값을 이용해 G의 손실값을 구해줍니다. 그러면 구해진 손실값으로 변화도를 구하고, 최종적으로는 옵티마이저를 이용해 G의 가중치들을 업데이트시켜주면 됩니다. 언뜻 볼때는, 생성자가 만들어낸 가짜 이미지에 진짜 라벨을 사용하는것이 직관적으로 위배가 될테지만, 이렇게 라벨을 바꿈으로써 𝑙𝑜𝑔(𝑥)라는 BCELoss 의 일부분을 사용할 수 있게 합니다 (앞서 우리는 BCELoss에서 라벨을 이용해 원하는 로그 계산 요소를 고를 수 있음을 알아봤습니다).

    • Loss_D - 진짜 데이터와 가짜 데이터들 모두에서 구해진 손실값. (𝑙𝑜𝑔(𝐷(𝑥))+𝑙𝑜𝑔(1−𝐷(𝐺(𝑧)))
    • Loss_G - 생성자의 손실값. 𝑙𝑜𝑔(𝐷(𝐺(𝑧)))

    '논문 리뷰' 카테고리의 다른 글

    GAN 논문리뷰(Generative Adversarial Nets)  (0) 2024.07.18

    댓글

Designed by Tistory.