22.03.30 GAN(Generative Adversarial Network) - Cycle GAN 공부

2022. 3. 31. 14:07카테고리 없음

 

목차

1. GAN이란 무엇일까 https://www.youtube.com/watch?v=odpjk7_tGY0 

2. CycleGAN 총정리 http://www.kwangsiklee.com/2018/03/cyclegan%EC%9D%B4-%EB%AC%B4%EC%97%87%EC%9D%B8%EC%A7%80-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90/

 

 

 

 

* GAN이란 무엇일까

Unsupervised Learning : train data의 분포를 보고 image를 생성

확률분포

이미지는 더 많은 케이스(64x64x3)가 있어서 확률분포가 어렵게 생겼을 것임.

만약 이렇게 생겼다고 한다.

안경 낀 남자

금발 여자

(실제로는 x가 고차원벡터임)

 

generative model이 하고자 하는 것

저 데이터 분포를 잘 근사하는 모델을 만드는 것(실제같은 이미지 생성)

 

GAN - 두 가지 모델 존재 (Discriminator과 Generator)

Discriminator : 진짜가 들어가면 진짜1로 구분, 가짜면 0. input은 이미지의 고차원 벡터(64x64x3), output은 1차원 0~1사이 값

Generator : 랜덤한 코드를 받아서 이미지를 생성해냈을 떄 Fake image를 만들어서 Discriminator를 속여야(1이 나오게) 한다. 따라서 Generator는 학습을 하면 할수록 진짜같은 가짜 이미지를 만들어낸다.

 

GAN의 수식 - Discriminator

D = GAN의 loss함수

log(D(x)) = D가 1일때 0, D가 0이면 -무한대

 

GAN의 수식 - Generator

Generator는 Discriminator에 가짜 이미지를 넣었을 떄 최대한 1이 나오도록 학습을 해야한다.

 

GAN 코드

Discriminator

intput : 18x18 MNIST를 1차원으로 펼침 = 784

output : 0~1 사이 값. 진짜스러운지 가짜스러운지, size 1(sigmoid 거침)

 

Generator

intput : latent code

output : 다시 이미지 생성. 18x18 = 784

 

Loss function - Binary Cross Entropy Loss

h(x) = hypothesis, y = label(실제정답)

 

Optimizer - Adam D와 G를 따로따로 구현해야함.

Data - tensor

 

실제 학습되는 코드 -Discriminator

진짜 이미지 넣으면 1을, 가짜이미지 넣으면 0을 내놓도록 학습

 

실제 학습되는 코드 - Generator

생성한 가짜이미지를 D한테 넣어줬을 떄 점점 1이 나오도록 학습

g_optimizer.step() = D는 학습안하고 G만 학습한다.

D와 G는 각각 backpropagation이 서로의 weight를 업데이트하진 않는다. D는 D것만 업데이트, G는 G것만 업데이트

전체 코드 아래에

https://github.com/yunjey/pytorch-tutorial

 

GitHub - yunjey/pytorch-tutorial: PyTorch Tutorial for Deep Learning Researchers

PyTorch Tutorial for Deep Learning Researchers. Contribute to yunjey/pytorch-tutorial development by creating an account on GitHub.

github.com

 

초반에는 D(G(z))가 0이 나오기 떄문에 빠르게 그럴듯한 이미지를 만들 시점으로 들어서도록 아래와 같이 한다.

Generator는 초반에 매우 형편없는 이미지를 만들게 된다. 그럼 D(G(z))는 0에 가까운 값을 내놓는다.

그럼 log(1-0.00001) 을 하면 안된다. 따라서 log(1-DG)가 아닌 log(DG)를 해야한다.

따라서 y에 1을 대입해서 처음엔 이렇게 하게 한다.

 

총 정리

GAN의 목표 : 실제 데이터 분포와 모델이 생성한 데이터 분포간의 차이를 줄이는 것

 

GAN의 loss 함수를 변형한 여러 GAN 모델들

1. DCGAN(Deep Convolutional GAN 2015)

- 1차원 18x18=784가 아닌 2차원 CNN을 사용

- G에서 deconvolution을 진행

- pooling layer를 사용하지 않는다. (unpooling할 떄 이상한 이미지를 만들어낼 수 있어서)

- Adam optimizer : 보통 64x64 이미지 생성할때 convolution layer를 4개 사용하여 모델을 만드는데, 저 beta1,2를 사용하면 학습이 잘 된다고 하여 저렇게 한다.

- 흥미로운 점 : latent vector를 가지고 연산을 할 수 있다. word2vec처럼

안경쓴남자 - 안경안쓴남자 + 안경안쓴여자 = 안경쓴여자

 

2. LSGAN(Least Squares GAN)

- 기존 GAN은 D를 속이기만 하면 되는데, 

- 아래서 파란 선 : 기존 GAN D의 Dicission Boundary 진짜가짜를 구분하기 위한. 0.5를 기준으로 높으면 진짜, 가짜

- 빨간 선 : LSGAN의 D의 Dicission Boundary. 분홍색 점들 : 가짜 데이터인데 완벽히 속였다. 그러나 진짜 데이터인 빨간색 점들과 먼 것을 보아 좋지않은 이미지를 생성하긴 한 것. 그러므로 완벽히 속였다 하더라도 좋지 않은 이미지일 수 있다. 그러므로 저 분홍점을 Discission Boundary에 가깝게 좀더 끌어올려서 별로인 이미지는 걸러지고 좋은 이미지만 D가 1을 내뱉도록, 확실히 속도록 하는 게 LSGAN

- 기존과 다르게 sigmoid를 없앰.

- 큰 차이점 : 기존엔 cross entropy를 썼는데, LSGAN은 least squre loss로 바꿈(L2)

기존이랑 LSGAN 둘 다 진짜이미지는 1로 가고, 가짜이미지는 0으로 가는데 차이는

D(G(z))가 만약 1보다 훨씬 큰값 = 3 등을 낸다고 해도, G(z)가 이상한 이미지 일수 있는 문제점이 있었다.

그러므로 LSGAN으로 바꾸면 1보다 크든 작든 Dicission Boundary쪽으로 밀어준다.

DCGAN보다는 좋긴 좋다. 근데 몇 개는 보다시피 이상한 것도 있음.

 

 

3. SGAN - MNIST데이터로 설명

기존과 다르게 D가 더이상 진짜가짜를 구분하지 않고 class를 구분한다. MNIST의 기본 10개 클래스에(0~9까지 숫자그림) + 가짜 클래스 1개를 추가함.

- one-hot vector : class를 나타냄 [0,0,0,1,0,0] -> 숫자3를 의미 등

- 진짜 정상적인 5를 받으면 class로 5를 내뱉고, 가짜이미지 비정상적인 걸 받으면 fake class를 내뱉음

따라서 이 GAN의 목적은 가짜 이미지를 만들어도 input으로 준 one-hot vector랑 output으로 나오는 one-hot vector가 같도록 만들어줘야한다.

그래서 반은 supervised learn이고 반은 unsupervised learn이어서 semi supervised라고 부름.( class가 있어서 training시 label(정답)이 존재해야하므로)

z벡터는 그대로 두고, class(one-hot vector)만 바꾸게 되면 예를 들어 저 보라머리 캐릭터가 있으면

z벡터는 보라머리캐릭터 생성이고, class는 저 포즈나 표정이다. 그래서 class를 바꾸면 캐릭터는 보라머리 그대로인데 포즈만 바뀌게 됨.

z가 조금변하면 캐릭터도 조금변하고, z가 많이 변하면 캐릭터도 많이 변함.

 

4. ACGAN(Auxiliary Classifier GAN 2016)

- Semi supervised GAN 이랑 비슷한데 D가 해야되는 task가 두개이다. 진짜인지 가짜인지도 구분하고, class도 구분해야 한다. 즉, 가짜임에도 불구하고 class는 2같다.라고 구분해야함.

그래서 ACGAN은 MNIST지만 class가 10개임. 가짜지만, 3 이런식으로 진짜,5 

- 그래서 SGAN은 좋은 가짜이미지를 만드는 데 특화라면, ACGAN은 Data augmentation? 좀 noise가 껴있어도 잘 만들어낸다? 

 

여태까지는 loss 함수를 바꾸거나 label을 추가한 형태였다면, 앞으로는 조금 더 확장된 GAN을 살펴보자

5. CycleGAN

- 이미지의 도메인 또는 스타일을 바꾸는 GAN, 얼룩말을 말로, 말을 얼룩말로, 여름을 겨울로

input : latent code를 받지 않고, image를 받는다

A도메인을 B도메인으로 바꾸고 싶다. (A 얼룩말 B 그냥말)

그래서 D를 학습시킬 떄는 얼룩말을 넣지 않고 그냥 말만 넣어서 학습

그러면 얼룩말을 받았을 떄 가짜이미지라고 판별할 것임.

그래서 D를 속이기 위해 얼룩말을 말로 바꾸게 된다. 그러나 속이기만 하면 되므로

꼭 저 input때의 말 자세가 아닌 뛰는 말 자세 등 말이기만 하면 되는 사진을 Generate한다.

그러므로 이 task의 목표 : 얼룩말을 말로 바꾸되, 그 자세는 유지하도록 하는 것.

그럼 모양 유지는 어떻게 하냐?

얼룩말 -> 말로 바꾸고, 그 말을 다시 얼룩말로 바꾼다.

예를 들어 저 맨왼쪽 얼룩말을 뛰고있는 말 이미지로 바꿨다. 그리고 그걸 다시 원래 얼룩말로 복원시키려면(generate하려면) 자세가 다르기 때문에 쉽지 않을 것이다(loss가 크다?) 따라서 이 작업을 잘 해내기 위해 최대한 자세가 변하지 않은 황토말 이미지를 생성하게 될 것이다.

즉, 모양은 유지하되 말색깔(도메인)만 바꾸기 위해서는 reconstruction error가 적도록, D를 속일 수 있게 하는 방향으로 학습시키면 될 것이다.

이 설명하신 분이 구현하신 코드

https://github.com/yunjey/mnist-svhn-transfer

 

GitHub - yunjey/mnist-svhn-transfer: PyTorch Implementation of CycleGAN and SSGAN for Domain Transfer (Minimal)

PyTorch Implementation of CycleGAN and SSGAN for Domain Transfer (Minimal) - GitHub - yunjey/mnist-svhn-transfer: PyTorch Implementation of CycleGAN and SSGAN for Domain Transfer (Minimal)

github.com

 

 

* CycleGAN 총정리

CycleGAN으로 할 수 있는 일

- 말<->얼룩말 변환, 대신 자세는 유지

- 여름<-> 겨울 변환

- 아이폰사진 <-> DSLR 사진 변환

- 모네그림 <-> 실제풍경

 

CycleGAN의 탄생 : pix2pix에다가 GAN을 더해서 CycleGAN을 만듦

 

pix2pix : supervised learning, input,output 이 모두 사진임, 즉 흑백사진 -> 컬러사진

 - self supervised 이다 왜냐면 label을 붙여주지 않아도 흑백/컬러 사진을 정답지로 학습시킬 수 있기 때문.

 - loss 는 |G(x)-y|

 - 또는 이렇게 건물구조도를 주면 실제 건물처럼 만들어낼 수 있음. 단 정답에 비해 뿌옇고 부조화스러움

 - 흑백-> 컬러사진도 역시 뿌옇다. 왜냐하면 loss를 막기위해 흑백이 아닌 색을 모델이 선택하는데 이때 색깔값에 대한 가이드라인이 없어 모델이 중간값을 고르는 경향이 나타난다.

따라서 pix2pix의 intuition : 사람이 보기에 output과 ground truth는 명확히 구별된다(Discriminator) 그러면 이 D를 뉴럴 네트워크가 하도록 하자! -> GAN의 탄생

 

GAN

 - 우리의 목적은 흑백사진 입력을 컬러사진으로 만드는 것, 이것이 G 네트워크

 - 여기에 D를 추가하여 G(x)가 real인지 fake인지 구별하게끔 만든다.

 - 즉 D는 fake를 구별하려 하고, G는 fake image로 D를 속여야 한다.

 

 

GAN의 수식

- D 네트워크

- real은 0에 가깝게, fake는 1에 가깝게 구별한다.

- D의 loss함수는 저 식과 같다. argmax 사용. logD(G(x))+ log(1-D(y))를 넣은 저 값. 즉 0~1사이가 나온다

- log(D(G(x))) 를 통해 G가 만들어내는 결과는 1(fake)에 가깝게 만들고,

  log(1-D(y))를 통해 실제 정답이미지의 결과는 0(real)에 가깝게 만든다.

 

- G 네트워크

 - argMin. D와 반대로

 - log(D(G(x)))를 통해 G가 만들어내는 결과는 0(real)에 가깝게 만든다

 - log(1-D(y))를 통해 실제 정답 이미지는 1(fake)에 가깝게 만든다. 즉, D를 속인다.

 

GAN 네트워크 총 수식 정의

- G의 관점에서는 D가 loss function이다.

 

개선된 pix2pix

 - pix2pix의 loss는 픽셀 level loss(y-G(x)만 사용)와 GAN의 loss를 합쳐서 개선하였다.

 

pix2pix의 한계점

 - 데이터셋을 구성하기 쉽지 않다(모네의 실제 그림과 실물 이미지를 1000장씩 구하려면?)

 

CycleGAN

 - 완전히 똑같지 않은 원하는 style의 사진을 쉽게 구할 수 있다.

 - 기존의 GAN loss를 사용하나 조금 변형해야한다. 왜냐면 기존 GAN은 2가지 한계가 있음

1. input의 특성이 무시됨 2. 같은 output으로 매몰될 여지가 있음.

- 그러므로! CycleGAN은 추가 loss를 적용. 원본 이미지로 reconstruct해봤을 때의 loss를 추가하는 것.

즉, 도메인은 바꾸되 다시 원래 그림으로 복구가능할 정도로만 바꿔라.

 

CycleGAN의 정방향 loss함수

- 기존 GAN의 loss(argmin argmax log어쩌구)는 유지한다. (=LGAN)

- 추가적으로 생긴 loss는 generation한 이미지를 reconstruction한 이미지와 원래의 x의 loss가 최소화 되어야 한다.(=F(G(x))-x)

즉 기존 GAN에서는 G만 하는데, 여기는 reconstruct작업인 F도 추가된 느낌.

 

반대방향 학습

 - 같은 맥락으로 반대 방향의 학습도 가능하다. F가 G의 역함수 개념이니 가능.

 - 모네 -> 실물의 학습이 가능하면, 실물 -> 모네로의 학습도 가능하다.

 

CycleGAN 의 최종 loss함수

 - 두 방향의 학습을 모두 합친 아래 loss 모습이 최종이 된다.

 - GAN은 두 방향의 loss를 합친다. ( 한 방향으로만 학습시켰을 떄는 결과가 좋지 않았다고 함 )

 

CycleGAN의 학습결과

- 그림-> 사진, 사진-> 그림 변환

- city scape cycleGAN을 사용했을때가 제일 잘 원본으로 돌아오고, 한 이미지로의 수렴도 일어나지 않았다.

- GTA와 실제 도로 사진으로의 reconstruction. 원본은 GTA 스샷, 정답지는 자율주행 차량 사진

- GTA <-> real street view

 

 

 

CycleGAN의 아키텍쳐

 - CycleGAN에서는 G의 아키텍쳐가 굉장히 중요함

 - 최초의 CycleGAN은 G로 U-Net을 채택하였다( 장점 : skip connection으로 디테일이 많이 간직된다. 단점 : 두 가지 컨텐츠가 비슷할 경우, skip connection을 최대한 사용하려고 하여 성능이 좋지 못함.

 - 최근 CycleGAN은 G로 ResNet을 채택하였다.( 장점 : 이미지 퀄리티가 좋음. 단점 : 메모리를 많이 사용함 ) 

 

CycleGAN의 loss함수의 변경

 - GAN으로 cross entropy를 사용하였더니 Gradient Vanishing 문제가 발생. 따라서 LSGAN을 사용

 

 

CycleGAN의 한계점

1. 모양

 - 도메인은 바꾸나 모양은 바꾸기 어려움. 사과를 오렌지로 바꾸기

2. 데이터 분포

 - 말->얼룩말에서 말 위에 사람이 타 있는 사진은 제대롣 동작하지 못했음

 - Optimization의 문제라기보다는 Dataset의 문제

 

GTA와 자율주행의 관계

 - 무인자동차의 학습 도구로 GTA 게임을 사용하기가 좋다.

 - 실사에 가까운 GTA 게임에서 Object Detection을 훈련시키고 실제 도로에서 검증한다고 한다.

 - 그러나 GTA에서 학습된 모델로 실제 환경에서 돌렸을 때 정확도가 그리 높지는 않았었는데 CycleGAN을 사용하면 

82.8%의 정확도(per-lixel accuracy)로 괜찮은 성과를 낸다.