전에는 DCGAN을 구현해보았다. 이번에는 이미지를 생성하는 것의 씨가 되는 잠재변수 z와 생성되는 이미지, 그리고 이미지의 인식 결과에 대해서 깊이 파보는 시간을 가진다. 코드는 Github를 참고하길 바란다.
1. 생성모델
mnist이미지를 바탕으로 생성 모델에 대해 생각해보자. mnist는 2차원의 이미지 데이터이지만, 실제로는 가로 28픽셀, 세로 28픽셀, 총 784픽셀의 각각에 화소값이 입력되어 있다. 즉, 2차원 이미지이지만, 784차원의 데이터로 취급되므로 주의해야한다.
그럼, 이 784차원의 캔버스에 이미지를 생성하는 의미를 생각해보자. 하나의 이미지 데이터 img는 784개 값의 나열로 나타낼 수 있다. 즉, i번째의 픽셀 값 xi라고 한다면 아래의 식과 같이 표현할 수 있다.
그런데, 생성모델 Pgen이란 각 픽셀 값이 임의의 값을 취했을 때의 동시확률분포(joint probability)를 구하는 것과 같다. 즉,
그러면, 예를 들어 각 픽셀이 전부 0이 될때의 확률이라던가, 전부 1이 될 때의 확률이라던가, 더욱 중간에 가까운 값이라던가, 784차원의 모든 값의 분포에 대해서 확률을 구하는 것이 된다. 즉, 전부 x분포에 대한 밀도 분포를 알 수 있게 된다. 확률밀도분포를 알게 될 때의 가장 큰 메리트는, 그 확률 밀도를 기본으로 데이터를 인공적으로 생성할 수 있는 것이다.
주사위를 예로 들어 이해하기 쉽게 설명해보도록 하겠다. 어떤 주사위를 굴리는 현상을 관측했을 때, 다수의 시행의 결과, 주사위의 눈이 나태나는 1차원 변수 x의 값은 1, 2, 3, 4, 5, 6 중 하나를 취하게 되며, 그 확률이 전부 동일한 것을 알 수 있다. 이 경우, x의 확률밀도분포는
위의 식과 같이 된다. 한번 생성 모델이 정해지면, 확률밀도분포로부터 x의 값을 샘플링하는 것이 가능하다. 확률분포에 따라 주사위를 굴리는 것이 좋다.
2. GAN의 생성모델
이러한 확률밀도분포 P(x)를 뉴럴 네트워크로 근사하게 구현하자고 하는 것이 GAN의 generator의 사고 방식이다. 잠재변수 z가 전달되었을 때, z의 조건부 활률 분포 D(x|z)를 구한다. 구한 확률분포로부터 샘플링을 실시하여 x 즉 이미지를 생성한다.
사실 generator는 잠재변수로부터 이미지 데이터의 확률밀도분산이 아닌 이미지 데이터 자체를 직접 축력하는 함수이다. 본래 확률분포로부터 샘플링할 때는 그 분포에 따른 흔들림을 가진 확률론적인 값을 생성한다. 그러나, generator의 경우에 같은 z로부터는 항상 (결정론적으로) 같은 값이 출력된다.
생성 이미지의 흔들림은, z를 난수로부터 결정하여 재현한다는 사고방식일까? 논문에서 언급되고 있는 확률 밀도 함수와 구현상의 결정론적인 함수의 이론적 관계성은 그다지 알려져 있지 않다. 아는 분이 계시다면 알려주길 바란다.
아무튼 잠재변수 z로부터 이미지를 생성하는 것을 그림을 표현하면 아래와 같다.
잠재변수 공간상 z의 어떤 값에 대해, 정해진 이미지가 출력된다. 여기서는 그림으로 표시하기 위해 z를 차원으로 하고 있다. 랜덤으로 샘플링한 각 z로부터 대응하는 이미지가 생성되고 있는 그림이다.
또한 임의의 두 점 간을 연속적으로 변화를 시키는 것으로, 생성한 이미지도 연속적으로 변화될 수 있다.
3. 잠재공간의 차원
그럼 discriminator를 좌절시킬정도로 진짜에 가까운 데이터를 생성하기 위해서는 z의 차원을 어느정도로 설정하는 것이 좋을까? 데이터의 차원(784) 정도는 필요할까? 아마 그렇지는 않을 것이다. 기껏해야 10종류의 숫자를 표시하는 것으로 mnist데이터의 분포는 이것보다 낮은 차원으로 집약되어 있을 것이다.
만약 화소를 가로 세로 2배로한 minit 데이터가 있을 때, 2*2*784 = 3136차원의 잠재변수가 필요하다고 생각되지는 않는다. 해상도가 커져도, 그곳에 집약된 정보량은 기본적으로 변하지 않는다.
이것으로 실제로 z의 차원을 변화시켜, 각각의 생성 이미지를 살펴보자. 난수는 고정하여, 각 iteration마다 같은 z로부터 이미지를 출력해보았다.
(※ 그림의 epoch라고 적혀있으나, 실제는 iteration으로 표기 실수이다. )
먼저 z_dim = 100부터
깔끔한 이미지가 생성되고 있다. 난수는 고정되어 있으므로 3000 iteration정도부터 z의 맵핑이 수렴되어, 각 칸에 똑같은 숫자가 계속 생성되고 있다. 4가 9가 되거나, 3이 8이되는 미세한 흔들림이 있다.
z의 차원은 조금씩 작게해보았다.
다음은 z_dim = 50이다.
이미지의 퀄리티 자체는 z_dim =100과 큰 변화가 없으나, iteration을 거쳐도 각 칸에서 생성되는 숫자가 정해져 있다는 느낌은 들지 않는다. 숫자가 휙휙 바뀌고 있으며, 흔들림이 없는 느낌이다. 학습마다에 generator함수가 바꿔 쓰여있어, z의 맵핑이 수렴되지 않는듯한 느낌이다. 또한, 잘 보면 5x5의 25칸 중에 같은 이미지가 많은 느낌이 든다.
다음은 z =10이다.
안정적으로 생성되고 있다. 100보다 이미지 품질이 깨끗한지도 모르겠다.
z = 2
z_dim = 50에서 봣던 현상이 현저하다. 휙휙 이미지가 바뀌고 있으며, 3이라면 3뿐이라던가 명백히 같은 이미지가 생성되고 있다.
z=1
z_dim = 2와 동일하다. 이미지 자체는 깔끔하지만, 여기까지 왔을 때 훈련 데이터의 분포를 재현하는 듯한 생성 모델을 학습한다고 얘기하는 것보다는 단순히 훈련 데이터를 모방하고 있다고 생각할 수 있다.
이것은 모드 붕괴(mode collapse)라고 부르는 현상으로, generator의 학습에 실패하여, 훈련 데이터의 (종종 다봉성의) 분포 전체를 표현하지 않고 훈련 데이터의 최빈값(mode)만을 학습하고 있다. 전 국민의 기대에 응하는 능력이 아닌, 다수파를 위한 정책을 만드는 듯한 느낌이다.
z_dim = 2, 1의 경우에는, 잠재변수의 차원이 충분하지 않아 generator가 훈련 데이터의 분산을 제대로 표현하지 못하고 고육지책으로 특정의 이미지를 집중하는 것으로 discriminator을 속일 대안을 만들고 있다고 말할 수 있다.
z_dim = 50의 경우도 모드 붕괴 현상을 볼 수 있었다. z_dim= 10에서는 이미지 생성에 성공하고 있으므로, 차원이 부족하다는 이유는 없다고 할 수 있다. 아마도, generator과 discriminator의 학습관계의 균형이 적당하지 않고, generator의 출력이 특정의 분포에 집중하고 있는 것으로 생각된다. 이로 인해 GAN의 파라미터 튜닝이 어려운 하나의 원인이라고 생각한다.
각 차원 수의 생성 모델에서, 99000 iteration후에 10000샘플 생성시켰을 때의 각 숫자의 빈도를 픽토그램으로 표현하면 아래의 그림과 같다. 그렇다고 해도, 실제로 어떤 숫자를 GAN가 만드는지에 대해서 알 수 없으므로, 그 대신에 숫자를 식별하는 모델을 CNN_classifier로써 구성하여 (keras의 example에 있는 것을 그대로 추가하였다), 그 식별 결과를 이용하였다. 따라서, 어디까지나 CNN_classifier가 생각한 픽토그램이다. 이것을 보아도 샘플링을 모조리 생성하고 있는 것은 z_dim = 100, 10일 경우라는 것을 알 수 있다.
그럼, 모처럼 GAN로 샘플을 생성하고 싶은데 모드 봉괴에 의해 생성 샘플이 한쪽으로 치우치는 것을 피하고 싶을 것이다. 모드 붕괴가 일어나고 있는가, 혹은 일어나지 않고 있는가를 확인하는 것은 어떻게 하면 좋을까? PC에 붙어서 생성되는 샘플을 계속 보는 것도 힘든 일이며, 시각화되지 않은 샘플은 사용할 수 없다. 생성 데이터를 보지않고, 학습시 손실함수로부터 학습이 잘 되고 있는지를 판단하는 것은 가능할까? 이것은 WGAN와 관련이 있다.
4. 정리
dcgan보다 높은 화질의 이미지를 생성하는 것에 성공해도, 모드 붕괴에 의해 원하던 결과를 출력하지 못하는 문제가 발생하고 있다는 것을 알 수 있다.
5. 과제
- 생성결과를 확인하지 않고, 학습의 옳고 그림을 판별하는 방법
- 모드 붕괴가 일어나지 않는 방법
참고자료
https://qiita.com/triwave33/items/a5b3007d31d28bc445c2
'IT > AI\ML' 카테고리의 다른 글
[python] 교차검증(cross validation/クロスバリデーション/交差検証)과 그 방법들 (0) | 2020.05.19 |
---|---|
GAN ; WGAN & WGAN-gp (0) | 2020.05.01 |
[논문] GAN ; CycleGAN (Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks) (2) | 2020.04.30 |
[python] GAN; cGAN(conditional GAN) (2) | 2020.04.30 |
[python] PCA와 ICA의 개요와 차이점 (2) | 2020.04.30 |