-
CycleGAN 이란?머신러닝 및 딥러닝 2021. 1. 16. 13:28
CycleGAN을 이해하기 앞서 pix2pix 에 대해서 이해가 필요하다
pix2pix
pixel to pixel은 말 그대로 하나의 픽셀을 다른 픽셀로 바꿔준다는 의미이다. 아래 이미지와 같이 흑백사진을 컬러사진으로 바꾸거나, label만 부여한 input에 대해 실제 이미지를 생성하거나, edge만 있는 input 에 대하여 완전한 output을 만들어 내는데 사용한다. 아래의 사진을 참고하면 이해하기 더 용이하다.
loss function
pix2pix의 loss function은 다음과 같다. G(x) 와 y의 차이(여기서 G(x)는 생성한 이미지를 y는 ground truth를 의미한다.), 즉 pixel level의 차이를 최소화 한것을 loss로 두고 학습을 시키면 아래와 같은 결과가 나온다. Ground Truth는 정답 이미지를 의미한다.
여기서 이상한 점이 network가 생성한 output은 상대적으로 뿌옇게 보이는 것을 확인할 수 있다. 이런 현상이 일어난 이유는 network는 어떤 색으로 칠해지는 것이 정답인지를 모르기 때문에 가장 손해를 보지 않는 중간값을 선택하기 때문이라고 한다.
충분히 결과물이 괜찮아 보이지만 사람은 충분히 Ground truth 와 output을 구분해 낼 수 있다. 여기서 중요한 intuition은 "사람이 할 수 있다면 다른 DL network가 할 수 있지 않을까?" 라는 생각이다. 즉, 사람대신 다른 NN 가 이 역할을 하자는 생각이다. pix2pix는 여기서 사람의 역할을 GAN이 대신할수 있다고 생각하였다.
그렇다면 GAN 이 무엇일까?
GAN은 적대적 생성 신경망으로 해당 모델을 생성을 담당하는 Generator 와 Ground Truth와 Generator가 생성한 결과를 구별해야하는 Discriminator로 이루어져 있다.
여기서 Generator와 Discriminator는 각각, 위조지폐범과 경찰로 생각할 수 있다. Generator는 Discriminator가 눈치챌 수 없도록 Ground Truth와 차이가 안나기 위해 노력하고 Discriminator는 Generator가 생성한 결과물을 정확히 판별하도록 노력한다.
이런 적대적인 학습이 계속 되다보면 어느순간 Discriminator는 Generator가 만든 결과물과 Ground Truth를 구별할 수 있는 확률이 50%로 수렴하게 된다. 즉, 구별 하기 어려운 상태가 된다. 정리해보면 GAN은 생성모델로서 Generator가 더 완벽히 생성해내기 위하여 Discriminator를 이용한 모델이라고 할 수 있다.
실제 예시를 들어보면 아래 GAN의 목적은 흑백사진을 컬러사진으로 만들어 내는 것이다. Generator 네트워크는 자신이 만든 결과물 G(x)로 Discriminator를 속이려고 하고 , Disciminator 네트워크는 G(x)를 구별해내려고 한다.
위의 수식은 Discriminator의 목적함수 이다. D net(discriminator net) 입장에서는 0에 가까우면 real(Ground Truth), 1에 가까우면 fake 이미지로 구별한다. 즉 G net(Generator net) 가 만들어낸 결과는 fake(1) 에 가깝게 만들고 실제 정답 이미지는 real(0)에 가깝게 만든다.
D는 어떤 이미지가 input으로 들어왔을 때, fake 인지 real 인지의 확률을 output으로 내보낸다.
위의 사진처럼 0.9 는 위 결과물이 fake일 확률이 90% 라는 의미이다. D(G(x)) 확률에 log를 씌워 optimize 한다고 했을때, log도 증가함수이기 때문에 이 확률값을 maximize 한다면, 파란색 네모박스가 되어있는 부분 D는 G(x)가 fake 이미지일 경우 1이 나오고 여기서 log1은 0이 나오기 때문에 이 값이 최대값(D(G(x)) 이 0.9 만 되더라고 음수가 나온다.)이다. 노란색 네모 박스도 같은 개념으로 생각해보면 같다.
Generator의 목적함수는 Discriminator의 반대이다. 여기서는 min을 해야한다. 왜냐하면 D(G(x))를 0으로 가깝게 하면 log D(G(x))의 값이 마이너스 무한대로 가기 때문이다.
따라서 GAN의 loss 는 아래와 같다.
여기서 중요한 점은 G와 D를 경쟁관계로 만드는 것이다. G의 loss function은 항상 고정된 것이 아니라 D를 이겨내는 목표로 학습된다는 개념이 중요하다.
그렇다면 최종적으로 pix2pix에 GAN을 입힌 형태는 어떻게 결과물이 산출 될까?
여기서 L1 loss 는 전에 보여주었던 Y-G(x)가 min이 되도록 학습했던 것을 의미한다. 여기서 GAN loss를 추가해주니 훨씬 성능이 개선 된것을 확인 할 수 있다.
pix2pix의 한계점
pix2pix는 GAN loss를 합친 목적 함수를 이용하여 성능을 높였지만 training data가 pair로 존재해야만 한다는 한계점이 존재한다. 흑백 사진을 컬러 사진으로 바꾸기 위한 training dataset은 구성하기 쉽지만, 피카소와 달리 등의 그림을 실물 이미지로 바꾸기 위한 데이터셋을 구성하기는 현실적으로 불가능하다. 따라서 이런 한계점을 극복하기 위해 cycleGAN이 등장하였다.
CycleGAN
hfgis우선 예를 들어 위사진에서 아래의 오른쪽에 있는 결과물을 보면 input으로 실제 차도 사진을 넣었을 때 원하는 결과물은 해당 사진을 image segmentation 하는 이미지를 생성하기 원하는데 GAN 만 적용한 결과를 보면 image segmentation 은 하였지만 전혀 관련 없는 것을 image segmentation 한 결과 값이 나온것을 알 수 있다. 그 밑에 예시 역시 image segmentation 한 결과값을 넣어주었는데 GAN으로 이를 출력하였을 때 전혀 입력을 고려하지 않은 관련없는 실제 차도같은 사진이 나온것을 알 수 있다. 여기서 GAN을 혼자 사용하면 안된다는 것을 직관적으로 알 수 있다.
그렇다면 왜 GAN은 이런 결과물을 나타낸 것일까? 왜냐하면 GAN 입장에서는 input을 그냥 image segmentation 한 결과 처럼 나타내면 Discriminator net은 이름 real image 라고 생각하기 때문이다. input의 특징을 다 잊어버리고 똑같은 출력을 생성하는 것을 mode collapse 라고 한다고 한다.
cycleGAN의 key object는 input을 주었을 때 해당 input을 의도한 방향으로 바꾸는데 이걸 다시 원래의 input으로 되돌릴때 변환 가능 할 수 있도록 이를 바꾸라는 것이다. 즉 아래의 사진을 보면 왼쪽이 모네의 그림이고 오른쪽에 있는 것이 모네가 그림을 그린 장소를 모네의 구도와 상관 없이 실제 사진으로 찍은 것이다. 이때 모네의 그림을 사진으로 Generator가 만들gfhiusdkjdfhjghdsiughdsiughiurehtuihralgihoirtghirhjto수 있어야 하지만 또한 사진을 모네의 그림으로 표현할 수 있어야 한다. 함수 G는 모네의 그림을 사진으로 바꾸는 함수이고 F는 사진을 du모네의 그림으로 바꿔주는 함수를 이야기 한다.
Loss 함수의 의미를 생각해보면 우선 GAN 은 G를 y로 바꾸는 즉 모네의 그림을 실제 사진으로 바꾸는 GAN에 해당하는 Loss와 F(G(x))를 하게 되면 x 즉 원래의 입력과 같아지는 것을 의도하는 것인데 F의 목표는 G를 inverse 하는 것이니까 여기서 이 둘을 더한값을 Loss 값으로 하여 이를 최소화하는 것으로 학습을 진행한다.
여기서 그림을 사진으로 바꾸는 것이든, 사진을 그림으로 바꾸는 것이든 상관없이 역함수의 개념으로 생각해보면 아래와 같은 수식으로 나타낼 수 있다. 따라서 CycleGAN은 4가지의 loss term이 함쳐진 형태라는 것을 알 수 있다.
여기서 생각을 해볼 수 있는게 그럼 생성된 결과물을 즉 왼쪽에 있는 것이 모네의 그림(정확히 얘기하면 실제그림과 CycleGAN으로 산출된 결과물)이고 오른쪽에 있는것이 실제 사진(정확히 얘기하면 실제사진과 CycleGAN으로 산출된 결과물)이라고 했을 때 이를 한번더 Cycle을 연결하면 더 좋은 결과물을 얻을 수 있지 않을까? 라는 궁금증이 떠오를텐데 저자의 답변으로는 그렇지 않다고 한다. input의 이미지가 이미 너무. 오염되었기 때문이라고.......
위의 실험은 앞서 말해던 Loss 함수가 4개로 이루어져 있는것을 알 수 있다. 입력으로는 실제 도로 사진과 사람이 실제로 labeling 한 image segmentation 이 주어졌다.
여기서 Cycle alone 은 GAN loss를 사용하지 않은 것을 이야기 하고 GAN alone은 Cycle 즉 l1 loss를 사용하지 않을 것을 보여주고 있다. GAN+forward는 앞에 Term(Lgan(G(x),y) + ||F(G(x)) - x||1 만 한것이고 GAN+backward는 뒤에만 한것을 의미한다.
실험결과에서 보이듯이 모든 loss term을 사용하여야 가장 좋은 결과를 나타내는것이라고 볼 수 있다.
여기서 중요한 점이 앞에 설명한 PIX2PIX는 pair된 데이터셋이 있어야 학습이 가능한데 CycleGAN은 완벽히 pair한 데이터가 아니어도 학습이 가능하다는 것이다. 예를 들어 설명하자면 PIX2PIX는 한강의 흑백사진을 갖고 있고 한강의 컬러사진도 있어야 학습이 가능하다는 점이고 CycleGAN은 한강의 사진을 모네가 그린 그림처럼 표현 하기 위해서는 모네의 화풍을 알 수 있는 데이터셋도 필요하고(모네의 그림의 데이터셋이면 된다.) 한강의 사진들을 담고 있는 데이터셋도 필요하다는 점이다. CycleGAN은 style Transfer의 결을 갖고 있는듯 하다.
GAN은 악명이 상당히 높다(저도 GAN을 쓰려고 했지만 상당히 발산을 잘한다고 해서 논문에는 제가 쓴 논문에는 GAN을 쓰고 싶지만 안썼습니다. TMI.....) 우선 발산을 상당히 잘하고 GAN의 loss function이 양의 방향으로 갈수록 Vanishing gradient가 발생하여 학습이 잘 안된다는 문제점이 있었는데 이를 LSGAN을 사용하여 학습을 더 용이하게 했다고 한다.
또한 GAN에 L1 loss를 넣어주면 학습이 좀 더 용이하게 된다고 한다. L1 loss가 stable guiding force 역할을 해준다고 한다. 저자의 설명으로는 큰 방향으로는 L1 loss를 통해 학습하고 작은 부분을 GAN을 이용하여 학습을 진행하는 것이라고 이해하면 된다고 한다.
한계점
1. 모양을 바꾸기 어렵다.
.
위의 사진을 보면 이해가 좀더 쉬울 듯 하다. SKT에서 발표한 DiscoGAN 같은 경우 위에 그림처럼 Generator의 구조를Encoder-decoder를 사용하였다. 이 경우 bottleneck에서 저장할 수 있는 부분이 많이 없다. 나쁘게 말하면 형태도 다 잃어버리게된다. 따라서 모양의 형태도 잘 바꿀 수 있지만 디테일한 부분을 나타내기 힘들다는 한계점이 있다. 하지만 CycleGAN 같은 경우 처음엔
U-net(encoder - decoder network 에 skip connection 만 한 것 )을 사용했다고 한다. 이 경우 skip connection 때문에 detail이 더 살아 있다고 할 수 있다 하지만 디테일을 살려야 하기 때문에 skip connection에 의존을 많이 한다고 한다. 하지만 depth가 깊지 않기 때문에 문제가 된다고 한다. 따라서 이를 타개하고자 ResNet을 사용하여서 깊이도 깊고 skip-connection도 이용하여 데이터 사진의 디테일한 부분을 다 간직할 수 있게 된다. 따라서 CycleGAN 같은 경우 결과물을 보면 형태가 잘 간직된것을 볼 수 있다. 하지만 input의 디테일한 부분을 다 갖고 있기 때문에 모양의 형태등을 바꾸는 것은 어렵다고 한다.
이건 모델의 문제라기 보다는 데이터셋의 문제라고 생각할 수 있다. CycleGAN에서 ImageNet 데이터셋을 가지고 학습을 진행하였는데 데이터셋에서 wild Horse의 경우 사람이 타고 있는 경우가 없었다. 그래서 Discriminator를 속이기 위해서는 모델내에서 사람도 얼룩형태로 되어야 속일 수 있다고 판단하고 산출한 결과라고 한다. 만약 데이터셋에서 말을 사람이 타고 있는 사진이 있었다면 잘 처리했을 것 같다고 한다.
NLP만 하다가 CV도 읽어보았는데 재미있는 부분이 많은 거같다. 더 연구 하고 싶은 분야이다
'머신러닝 및 딥러닝' 카테고리의 다른 글
Hyperparameter 튜닝은 어떻게 하는걸까? (0) 2021.01.17 Dropout 이란 무엇인가 (2) 2021.01.16 nn.Module에서 super (1) 2021.01.10 np.zeros 와 np.zeros_like 의 차이 (0) 2021.01.06 NLP 에서의 embedding size (0) 2021.01.01