본문 바로가기
2/[ Machine Learning ]

[GAN] 오토인코더와 GAN을 사용한 표현 학습과 생성적 학습

by Kieran_Han 2021. 1. 26.

SOURCE: Hands-On Machine Learning with Scikit-Learn, Keras & TensorFlow

 

Autoencoder: 어떤 지도 없이도(Label되어 있지 않은 Train Data를 사용해서) Latent Representation 또는 Coding이라 부르는 Input Data의 밀집 표현을 학습할 수 있는 인공 신경망

    - 일반적으로 입력보다 훨씬 낮은 차원을 가지므로 Autoencoder가 차원 축소, 특히 시각화에 유용하게 사용됨

    - 강력한 추출기처럼 작동하므로 DNN의 비지도 사전훈련에 사용 가능

    - Train Data와 매우 비슷한 새로운 data 생성 가능 → Generative Model(생성 모델), but 생성된 이미지가 흐릿하고 실제 이미지 같지는 않다.

 

Autoencoder와 GAN은 모두 비지도 학습이며, 둘 다 밀집 표현을 학습하고 생성 모델로 사용 가능

Autoencoder

    - 단순히 입력을 출력으로 복사하는 방법 학습

    - 다양한 방법으로 네트워크에 제약을 가해 작업을 어렵게 만듬 → 단순히 입력을 출력으로 바로 복사하지 못하도록 막고 data를 효율적으로 표현하는 방법을 배우게 만듬

    - 코딩은 일정 제약 조건하에서 Identity function을 학습하려는 autoencoder의 노력으로 생겨난 부산물

GAN

    - 신경망 2개로 구성

    - Generator는 Train data와 비슷하게 보이는 data 생성

    - Discriminator는 가짜 data와 진짜 data를 구별

    - 위 두 구조는 신경망이 훈련하는 동안 생성자와 판별자가 서로 경쟁 → Adversarial Training

 

1. 효율적인 데이터 표현

 

보통 긴 Sequence를 기억하기 어렵기 때문에 패턴을 찾는 것이 유용 → 훈련하는 동안 autoencoder에 제약을 가해서 data에 있는 패턴을 찾아 활용 → 효율적인 정보 저장

 

Autoencoder는 항상 두 부분으로 구성

    - Encoder(= Recognition Network): 입력을 내부 표현으로 바꿈

    - Decoder(= Generative Network): 내부 표현을 출력으로 바꿈

    - 출력층의 뉴런 수가 입력 개수와 동일하다는 것을 제외하면 대게 Autoencoder는 다층 퍼셉트론과 같은 구조

    - Autoencoder가 입력을 재구성하기 때문에 출력을 종종 Reconstruction(재구성)이라고 부름

    - 비용 함수는 Reconstruction과 입력이 다를 때 모델에 벌점을 부과하는 Reconstruction loss를 포함

 

2. 과소완전 선형 Autoencoder로 PCA 수행

 

Autoencoder가 선형 활성화 함수만 사용하고 비용 함수가 평균 제곱 오차(MSE)라면, 이는 결국 PCA(주성분 분석)를 수행하는 것

    - Autoencoder를 Encoder와 Decoder 두 개 components로 구성, 둘 다 하나의 Dense 층을 가진 일반적인 Sequential model, Autoencoder는 Incoder 다음에 Decoder가 뒤따르는 Sequential Model

    - Autoencoder의 Output 개수가 Input의 개수와 동일

    - 단순한 PCA를 수행하기 위해서는 Activation Function를 사용하지 않으며(모든 뉴런이 Linear), Loss Function은 MSE

 

위 Model을 간단한 3D Dataset에 훈련 후 동일한 Dataset을 Encoding함 → 2D로 투영

    - 동일한 Dataset X_train이 Input과 Target에도 사용됨

    - Autoencoder는 PCA처럼 data에 있는 분산이 가능한 많이 보존되도록 data를 투영할 최상의 2D 평면을 찾음

 

3. Stacked Autoencoder

 

Autoencoder는 Hidden Layer를 여러 개 가질 수 있다, 이를 Stacked Autoencoder(or Deep Autoencoder)라고 한다

Hidden Layer를 많이 만들면 Encoder가 너무 강력해서 Train Data를 완벽하게 재구성하겠지만 이 과정에서 유용한 data 표현을 학습하지 못하며, 새로운 sample에 일반화가 어렵다

Stacked Autoencoder의 구조는 전형적으로 가운데 Hidden Layer를 기준으로 대칭이다

 

3.1 Keras를 사용하여 Stacked Autoencoder 구현

일반적인 심층 MLP와 매우 비슷하게 Stacked Autoencoder 구현 가능

    - Fashion MNIST Dataset에서 SELU Activation Function을 사용해 Stacked Autoencoder 생성

    - Autoencoder Model을 Encoder와 Decoder 두 개 Submodel로 나눔

    - Encoder는 28×28 Pixel의 흑백 이미지를 받아 그 다음 각 이미지를 784 크기의 vector로 표현하기 위해 펼침

    - 이 vector를 크기가 점점 줄어드는 Dense 층 두 개에 통과시키고 두 층은 모두 SELU Activation Function을 사용

    - 각 Input 이미지에 대해 encoder는 크기가 30인 vector를 출력

    - decoder는 크기가 30인 coding을 받아 크기가 점점 커지는 Dense 층 두 개에 통과시키고 최종 vector를 28×28 배열로 변경하여 decoder의 output이 encoder의 input과 동일한 크기가 되도록 만듦

    - Stacked Autoencoder를 컴파일할 때 mse 대신 이진 크로스 엔트로피 손실을 사용 → 재구성 작업을 다중 레이블 이진 분류 문제로 다룸 → 각 필섹의 강도는 픽셀이 검정일 확률 → 이런 식으로 문제 정의 시, 모델이 더 빠르게 수렴하는 경향이 있음

    - X_train을 Input과 Target으로 사용해 model을 훈련함

 

3.2 Reconstruction 시각화

Autoencoder가 적절히 훈련되었는지 확인하기 위해 Input과 Output을 비교 → Input과 Output의 차이가 크지 않아야함

    - 재구성된 이미지를 식별할 수는 있지만 정보를 조금 잃었지만, 정보가 너무 많으면 data에서 어떤 유익한 패턴을 학습하지 못하고 완벽한 재구성 이미지를 만들기 때문에 위와 같이 해야함

 

3.3 Fashion MNIST Dataset 시각화

Autoencoder는 Sample과 Feature가 많은 대용량 dataset을 다룰 수 있어서 Autoencoder를 적절한 수준으로 차원을 축소한 후 다른 차원 축소 알고리즘을 사용해 시각화 가능

Fashion MNIST dataset을 Autoencoder의 encoder model을 사용해 차원을 30으로 줄이고, t-SNE 알고리즘을 구현한 Scikit-learn으로 시각화하기 위해 2차원으로 차원 축소를 진행

 

3.4 Stacked Autoencoder를 사용한 비지도 사전훈련

레이블된 Train Data가 많지 않은 복잡한 지도 학습 문제를 다룰 때, 비슷한 문제를 학습한 신경망의 하위층을 재사용하는 것 또한 한 방법 → 저수준의 Feature를 학습할 필요가 없어 적은 Train Data를 사용해 고성능 Model Train 가능 = 기존의 네트워크에서 학습한 Feature 감지 기능 재사용한 것

비슷하게 레이블되지 않은 대량의 Dataset이 있다면 먼저 전체 data를 사용해 Stacked Autoencoder를 훈련 그 다음 Autoencoder의 하위층을 재사용해 신경망을 만들고 레이블된 data를 사용해 Train

분류기를 Train할 때 레이블된 Train Data가 많지 않으면 사전훈련된 층을 동결하는 것도 가능

모든 Train data를 사용해 Autoencoder를 Train하고, Encoder Layer를 재사용하여 새로운 신경망을 만듦

 

3.5 Autoencoder Train Technique - 가중치 묶기

위 그림처럼 Autoencoder가 완벽하게 대칭일 땐 Decoder의 가중치와 Encoder의 가중치를 묶는 것이 일반적인 방법

→ Model에 있는 가중치의 수를 절반으로 줄여서 Train 속도를 높이고 Overfitting의 위험 줄임

    - Keras의 사용자 정의 Layer를 만들어 Layer 간에 가중치를 묶음

    - 일반적인 Dense Layer와 비슷하지만 다른 Dense Layer의 전치된 가중치를 사용함

    - 편향 Vector는 독자적으로 사용

    - 이전과 비슷하게 새로운 Stacked Encoder를 만들고 이 Decoder의 Dense Layer는 Encoder Layer과 묶여 있음

 

3.6 Training one Autoencoder at a Time

한 번에 전체 Autoencoder를 Train하는 것보다 그림처럼 Autoencoder 하나를 Train하고 이를 쌓아올려서 한 개의 Stacked Autoencoder를 만들 수 있음

Train Step 1에서 1st Autoencoder는 Input을 재구성하도록 학습

→ 이 Autoencoder를 사용해 전체 Train Set를 encoder하여 새 Train Set를 생성

→ 이 새로운 Train Set에서 2nd Autoencoder를 Train

→ 모든 Autoencoder를 사용해 전체 네트워크를 만듦

이러한 방법으로 더 많은 Autoencoder를 Train해서 Deep Stacked Autoencoder 생성

 

4 Convolutional Autoencoder

 

이미지를 다룰 경우 Autoencoder 성능 좋지 않음

→ CNN이 밀집 네트워크보다 훨씬 맞기에 이미지에 대한 Autoencoder를 만들려면 Convolutional Autoencoder를 만듦

Encoder는 Convolutional Layer와 Pooling Layer로 구성된 일반적인 CNN

Encoder는 전형적으로 Input에서 공간 방향의 차원을 줄이고 깊이를 늘림

Deconder는 거꾸로 동작해야 한다(이미지의 스케일을 늘리고 깊이를 원본 차원으로 되돌려야 함)

→ 이를 위해 전치 Convolutional Layer를 사용

    - Fashion MNIST DataSet에 대한 Convolutional Autoencoder

 

5. Recurrent Autoencoder

 

비지도 학습이나 차원 축소를 위해 시계열이나 텍스트와 같은 Sequence에 대한 Autoencoder를 만들려면 Recurrent Autoencoder가 밀집 네트워크보다 나음

Encoder는 일반적으로 Input Sequence를 하나의 vector로 압축하는 Sequence-to-Vector RNN

Decoder는 반대로 Vector-to-Sequence RNN

    - 위 Recurrent Encoder는 Time Step마다 28차원을 갖는 어떤 길이의 Sequence로 처리 가능

    → 각 이미지를 행의 Sequence로 간주하여 Fashion MNIST 이미지를 처리 가능

    - 각 Time Step마다 Input Vector를 주입하기 위해 Decoder의 첫 번째 층에 RepeatVector 층을 사용함

 

Autoencoder가 흥미로운 Feature를 train하도록 강제하기 위해 coding Layer의 크기를 제한하여 Undercomplete로 만듦

Input 크기만큼 또는 Input보다 큰 coding layer를 두어 Overcomplete Autoencoder 또한 가능

 

6. Stacked Denoising Autoencoder

 

Autoencoder가 유용한 Feature를 학습하도록 강제하는 다른 방법은 Input에 잡음을 추가하고, 잡음이 없는 원본 Input을 복원하도록 Train하는 것

잡음은 Input에 추가된 순수한 Gaussian 잡음이거나 Dropout처럼 무작위로 Input을 꺼서 발생 가능

 

    - Encoder Input에 적용한 Dropout Layer이 있는 (or 대신 Gaussian Noise Layer를 사용한) 일반적인 Stacked Autoencoder이다

    - Dropout Layer를 Train하는 동안에만 활성화 됨(Gaussian Noise Layer 또한 같음)

 

    - 픽셀 절반을 꺼서 만든 잡음 섞인 이미지와 Dropout 기반의 Denoising Autoencoder로 재구성한 이미지

    - Denoising Autoencoder를 data 시각화나 비지도 사전훈련을 위해 사용할 뿐 아니라 간단하고 효율적으로 이미지에서 잡음을 제거하는 데 사용 가능

 

7. Sparse Autoencoder

 

좋은 Feature를 추출하도록 만드는 다른 제약의 방식은 Sparsity(희소)

→ 비용 함수에 적절한 항을 추가하여 Autoencoder가 Coding Layer에서 활성화되는 뉴런 수를 감소시키도록 만듦

e.g. Coding Layer에서 5% 뉴런만 활성화되도록 강제하면, Autoencoder가 적은 수의 활성화된 뉴런을 조합하여 Input을 표현해야 함 → Coding Layer의 각 뉴런은 유용한 Feature를 표현하게 됨

    - 간단한 방법은 Coding Layer에 Sigmoid Activation Function을 사용하고 큰 Coding Layer을 사용하는 것

    - Coding Layer Activation 값에 l₁ 규제 추가

    - ActivityRegularization Layer는 Input을 그대로 반환하면서 훈련 손실에 입력의 절대값 합 더함

    - ActivityRegularization Layer를 제거하고 이전 층에서 activity_regularizer = keras.regularizers.l1(1e-3)로 지정해도 동일

    - 이 규제는 신경망이 0에 가까운 코딩을 만들도록 유도하지만 입력을 올바르게 재구성하지 못하면 벌칙을 받기 때문에 0이 아닌 값이 조금 출력되어야 함

    - l₂ 노름 대신 l₁ 노름을 사용하면 신경망이 입력 이미지에서 불필요한 것을 제거하고 가장 중요한 코딩을 보전하도록 만듦

 

더 나은 결과를 내는 다른 방법은 훈련 반복마다 coding layer의 실제 희소 정도를 측정하고 측정된 희소 정도가 Target 희소 정도와 다르면 model에 벌칙을 부과하는 것

→ 전체 훈련 배치에 대해 코딩 층에 있는 각 뉴런의 평균적인 활성화를 계산

→ 배치 크기가 너무 작지 않으면, 평균값이 정확하지 않을 것

 

각 뉴런에 대한 평균 활성화 정도를 알면 비용 함수에 Sparsity Loss를 추가하여 너무 활성화되거나 충분히 활성화되지 않은 뉴런에 벌칙 가함

e.g. 한 뉴런의 평균 활성화가 0.3이고 목표 희소 정도가 0.1이라면, 이 뉴런은 덜 활성화되도록 규제해야 함

간단한 방법은 비용 함수에 제곱 오차 (0.3-0.1)²을 추가하는 것

또는 그림과 같이 강한 Gradient를 가진 Kullback-Leibler Divergence를 사용하는 것

 

Coding Layer의 각 뉴런에 대해 희소 손실을 계산했다면, 이 손실들을 모두 합해서 비용 함수의 결과에 더하고

희소 손실과 재구성 손실의 상대적 중요도를 제어하기 위해 Sparsity Loss에 희소 가중치 Hyperparameter를 곱함

이 가중치가 너무 크면 model이 목표 희소에 가깝게 되겠지만 input을 적절히 재구성하지 못해서 쓸모없는 model이 될 수 있음

반대로 가중치가 너무 작으면  model이 희소 목표를 거의 무시할 것이므로 어떤 흥미로운 Feature도 학습 못함

    - KL 발산 규제를 적용하기 위해 사용자 정의 규제 생성

    - Coding Layer의 Activation에 KLDivergenceRegularizer를 적용해 Sparsity Autoencoder 생성

 

8. Variational Autoencoder(변이형 오코인코더)

 

    1. Variational Autoencoder = Probabilistic Autoencoder(확률적 변이인코더)이다

    → 훈련이 끝난 후에도 출력이 부분적으로 우연에 의해 결정됨(이와 반대로, Denoising Autoencoder는 훈련 시에만 무작위성 사용)

    2. Generative Autoencoder라는 점이 중요. 마치 훈련 세트에서 Sampling 된 것 같은 새로운 Sample 생성 가능

 

이런 두 속성이 Variational Autoencoder를 RBM과 유사하게 만들지만, 훈련이 더 쉽고 샘플링 과정이 훨씬 빠름

Variational Autoencoder는 효율적인 근사 베이즈 추론 방법인 Variational Bayesian inference(변분 베이즈 추론)를 수행

위 그림처럼 Variational Autoencoder는 Autoencoder의 기본 구조인 Encoder와 그 뒤를 따르는 Decoder가 있다

다른 점은 주어진 input에 대한 Coding을 바로 만드는 대신, Encoder는 평균 코딩μ와 표준편차σ를 만든다

실제 코딩은 평균이 μ이고 표준편차가 σ인 Gaussian 분포에서 랜덤하게 Sampling된다

그 후 디코더가 Sampling된 Coding을 보통처럼 Decoding해서 훈련 샘플을 닮은 최종 출력을 만든다

 

Variational Autoencoder는 Input이 매우 복잡한 분포를 가지더라도 간단한 Gaussian 분포에서 Sampling된 것처럼 보이는 Coding을 만드는 경향이 있다

훈련하는 동안 비용 함수가 coding을 Gaussian Sample들의 군집처럼 보이도록 Coding Space 안으로 점진적으로 이동시키고 훈련이 끝난 뒤 새로운 sample을 매우 쉽게 생성할 수 있고, Gaussian 분포에서 랜덤한 Coding을 Sampling해 Decoding하면 된다

 

비용 함수는

    1. Autoencoder가 Input을 재생산하도록 만드는 일반적인 재구성 손실

    2. 단순한 Gaussian 분포에서 샘플된 것 같은 코딩을 가지도록 Autoencoder를 강제하는 Latent Loss

 

잠재손실에는

    1. 목표 분포(Gaussian 분포)와 실제 코딩 분포 사이의 KL 발산을 사용

    2. 코딩 층으로 전달될 수 있는 정보 양을 제한하는(Autoencoder가 유용한 Feature를 학습하게 만드는) Gaussian Noise 때문에 Sparcity Encoder 보다 수식이 복잡

    - Fashion MNIST DataSet에서 Variational Autoencoder를 만들었다

    - μ와 ν가 주어졌을 때 코딩을 샘플링하는 사용자 정의 층이 필요

    - 이 Sampling 층은 두 입력 mean(μ)과 log_var(ν)를 받는다

    - 이 model은 완전히 순차적이지 않기 때문에 함수형 API를 사용해 encoder를 생성

 

    - coding_mean(μ)과 codings_log_var(ν)를 출력하는 두 Dense Layer가 동일한 input(즉, 두 번째 Dense Layer의 출력)을 사용 → codings_mean과 codings_log_var를 출력

    - 실제로 사용하는 것은 마지막 출력(codings)이다

 

    - 지금까지 만들었던 여러 Decoder와 사실상 동일하게 Layer를 단순히 쌓아서 Decoder는 함수형 API 대신 Sequential API를 사용

 

    - 배치에 있는 각 Sample의 잠재 손실을 계산(마지막 축을 기준으로 더함)

    - 배치에 있는 모든 Sample의 평균 순실을 계산하고 재구성 손실에 비례해 적절한 크기가 되도록 784로 나눔

    - 실제 Variational Autoencoder의 재구성 손실은 픽셀마다 재구성 오차의 합이지만, Keras가 Binary_crossentropy 손실을 계산할 때 합이 아니라 784개의 픽셀의 평균을 계산 → 따라서 필요한 것보다 재구성 손실이 784배 작음

    - 평균이 아니라 합을 계산하는 사용자 정의 손실 함수를 정의할 수 있지만 잠재 손실을 784로 나누는 것이 더 간단(최종 손실은 원래보다 784배 작아질 것. 이는 더 큰 학습률을 사용해야 한다는 것을 의미)

 

8.1 Fashion MNIST Image 생성

Variational Autoencoder를 사용해 이미지를 생성할 것이며, Gaussian 분포에서 랜덤한 코딩을 Sampling하여 Decoding하는 것이 전부이다

    - Variational Autoencoder는 Sematic Interpolation 수행 가능(두 이미지가 겹쳐 보이는 것)

 

9 Generative Adversarial Networks (GAN)

 

이 아이디어는 신경망을 서로 겨루게 하고 경쟁을 통해 신경망을 향상하는 것을 기대한다

생성자

    - 랜덤한 분포(일반적으로 Gaussian 분포)를 Input으로 받고 이미지와 같은 data를 출력

    - 랜덤한 input은 생성할 이미지의 잠재 표현(코딩)으로 가정

    - 생성자는 Variational Autoencoder의 Decoder와 같은 기능을 제공

    - 같은 방식으로 새로운 이미지를 생성 가능(Guassian Noise를 주입하여 완전히 새로운 이미지를 출력)

 

판별자

    - 생성자에서 얻은 가짜 이미지나 훈련 세트에서 추출한 진짜 이미지를 입력으로 받아 입력된 이미지가 가짜인지 진짜인지 구분

 

훈련하는 동안 생성자와 판별자의 목표는 반대

판별자는 진짜 이미지와 가짜 이미지를 구분하고 생성자는 판별자를 속일 만큼 진짜 같은 이미지를 생성

GAN은 다른 목표를 가진 두 네트워크로 구성되므로 일반적인 신경망처럼 훈련 불가능

 

각 훈련 반복은 두 단계로 이뤄짐

    1. 판별자를 훈련. 훈련세트에서 실제 이미지 배치를 샘플링하고 생성자에서 생성한 동일한 수의 가짜 이미지를 합침

    - 가짜 이미지의 레이블은 0으로 세팅하고 진짜 이미지는 1로 세팅

    - 판별자는 이진 크로스 엔트로피를 사용해 한 스텝 동안 이렇게 레이블된 배치로 훈련

    - 1단계에서는 역전파를 판별자의 가중치만 최적화함

 

    2. 생성자를 훈련. 먼저 생성자를 사용해 다른 가짜 이미지 배치 생성

    - 다시 판별자를 사용해 이미지가 진짜인지 가짜인지 판별

    - 배치에 진짜 이미지를 추가하지 않고 레이블을 모두 1(진짜)로 세팅

    - 다른 말로 하면 생성자가 판별자가 진짜라고 (잘못) 믿을 이미지를 생성해야 함

    - 이 단계 동안에는 판별자의 가중치를 동결하는 것이 중요

    → 역전파는 생성자의 가중치에만 영향을 미침

 

    - 생성자와 판별자 생성

    - 생성자는 오토인코더의 디코더와 비슷

    - 판별자는 일반적인 이진분류기(이미지를 입력으로 받고 하나의 유닛과 Sigmoid 활성화 함수를 사용한 Dense 층으로 끝)

    - 각 훈련 반복의 두 번째 단계에서 생성자와 판별자가 연결된 전체 GAN 모델 필요

 

    - Model들을 compile

    - 판별자는 이진 분류기이므로 자연스럽게 이진 크로스 엔트로피 손실을 사용

    - 생성자는 GAN 모델을 통해서만 훈련되기 때문에 따로 compile할 필요 없음

    - GAN 모델도 이진 분류기이므로 이진 크로스 엔트로피 손실을 사용

    - 중요한 점: 두 번째 단계에서 판별자를 훈련하면 안됨 → GAN 모델 컴파일하기 전에 판별자가 훈련되지 않도록 설정 필요

 

    - 훈련이 일반적인 반복이 아니기 때문에 fit() method 사용 불가 대신 사용자 정의 훈련 반복문 생성

    - 먼저 이미지를 순회하는 Dataset 생성

 

    1 단계

    - Gaussian Noise를 생성자에 주입하여 가짜 이미지 생성

    - 이와 동일한 개수의 진짜 이미지를 합쳐서 배치 완성

    - 타깃 y1은 가짜 이미지일 경우 0이고 진짜 이미지는 1로 설정

    - 이 배치에서 판별자를 훈련

    - 판별자의 trainable 속성을 True로 지정

    - 이는 trainable이 model이 compile 될 때 True 였지만 현재는 False일 때(or 반대) Keras가 출력하는 경고를 제거

 

    2 단계

    - GAN에 Gaussian Noise 주입

    - 생서자가 먼저 가짜 이미지를 생성하고 판별자가 이 이미지가 가짜인지 진짜인지 추측

    - 판별자가 가짜 이미지를 진짜로 믿게 만들고 싶게 타깃 y2를 1로 지정

    - 경고를 피하기 위해 trainable 속성을 False로 지정

 

9.1 GAN 훈련의 어려움

1. 훈련 과정에서 생성자와 판별자는 끊임없이 서로 앞서려고 노력함 → Nash Equilibrium이라 부르는 상태에 도달

    - 다른 플레이어가 전략을 수정하지 않을 것이므로 어떤 플레이어도 자신의 전략을 수정하지 않는 상태

 

2. Mode Collapse

    - 생성자의 출력 다양성이 줄어듦

    - GAN은 몇 개의 클래스 사이를 오가다가 어떤 클래스에서도 좋은 결과를 만들지 못함

 

3. 생성자와 판별자가 지속적으로 서로에게 영향을 주기 때문에 파라미터 변동이 크고 불안정해질 수 있다

 

9.2 Deep Convolutioanl GAN (DCGAN)

1. 판별자에 있는 Pooling 층을 스트라이드 합성곱으로 바꾸고 생성자에 있는 Pooling 층은 전치 합성곱을 바꿈

2. 생성자와 판별자에 배치 정규화를 사용 (생성자의 출력층과 판별자의 입력층은 제외)

3. 층을 깊게 쌓기 위해 완전 연결 은닉층을 제거

4. tanh 함수를 사용해야 하는 출력층을 제외하고 생성자의 모든 층을 ReLU 활성화 함수를 사용

5. 판별자의 모든 층은 LeakyReLU 활성화 함수를 사용

 

    - 생성자는 크기 100의 코딩을 받아 7*7*128차원으로 투영하고 이 결과를 7*7*128크기의 텐서로 바꿈

    - 이 텐서는 배치 정규화를 거쳐 스트라이드가 2인 전치 합성곱 층에 주입

    - 7*7에서 14*14로 업샘플링되고 깊이는 128에서 64로 감소

    - 이 결과 다시 배치 정규화 층을 지나서 스트라이드가 2인 다른 전치 합성곱 층에 주입

    - 14*14에서 28*28로 업샘플링되고 깊이는 64에서 1로 감소

    - 이 층은 tanh 활성화 함수를 사용하므로 출력 범위가 -1에서 1 사이

    - 이 때문에 이 GAN을 훈련하기 전에 훈련 세트를 동일한 범위로 스케일 조정 필요

    - 또한, 크기를 바꾸고 채널 차원 추가 필요

 

    - 판별자는 이진 분류를 위한 일반적인 CNN과 매우 비슷

    - 이미지를 다운샘플링하기 위해 최대 풀링 층을 사용하지 않고 스트라이드 합성곱을 사용

 

하지만 DCGAN은 완벽하지 않다

매우 큰 이미지를 생성하면 국부적으로는 특징이 구분되지만 전반적으로는 일관성 없는 이미지를 얻을 가능성이 높다

 

9.3 ProGAN

훈련 초기에 작은 이미지를 생성하고 점진적으로 생서자와 판별자에 합성곱 층을 추가해 갈수록 큰 이미지를 만드는 방법

이는 Stacked Autoencoder를 층별로 훈련하는 것과 비슷. 이전에 훈련된 층은 그대로 훈련 가능하도록 두고 생성자의 끝과 판별자의 시작 부분에 층을 추가

 

4 × 4에서 8 × 8 로 크게하려면 기존 합성곱 층에 업샘플링 층을 추가

이 층에서 출력한 8 × 8 크기 특성 맵은 새로운 합성곱 층으로 주입. 이 층 다음에 새로운 출력 합성곱 층이 뒤따름

이 층은 일반적인 합성곱 층으로 필요한 컬러 채널 수로 줄이기 위해 크기가 1인 커널을 사용

새로운 합성곱 층이 추가될 때 훈련된 첫 번째 층의 가중치를 일ㅎ지 않기 위해 원래 출력층과 새로운 출력층의 가중치 합을 최종 출력으로 만듦

새로운 출력층의 가중치는 α이고 원래 출력층의 가중치는 1-α이다 (α는 0에서 1까지 서서히 증가)

 

MiniBatch 표준편차 층

판별자의 마지막 층 근처에 추가

입력에 있는 모든 위치에 대해 모든 채널과 배치의 모든 샘플에 걸쳐 표준편차를 계산

→ S = tf.math.reduce_std(inputs, axis = [0, -1]))

이 표준편차는 모든 픽셀에 대해 평균하여 하나의 값을 얻음

→ v = tf.reduce_mean(S)

마지막으로 추가적인 특성 맵이 배치의 모든 샘플에 추가되고 계산된 이 값으로 채워짐

→ tf.concat([inputs, tf.fill([batch_size, height, width, 1], v)], axis = -1))

생성자가 만든 이미지에 다양성이 부족하면 판별자의 특성 맵 간의 표준편차가 작을 것이므로

따라서 판별자는 이 통계를 쉽게 얻을 수 있고 다양성이 아주 적은 이미지를 만드는 생성자에게 속을 가능성이 줄어듦

→ 생성자가 조금 더 다양한 출력을 만들도록 유도하고 모드 붕괴의 위험 감소

 

동일한 학습 속도

He 초기화 대신 평균이 0이고 표준편차가 1인 Gaussian 분포를 사용해 모든 가중치를 초기화

하지만 층이 실행될 때마다 He 초기화에 있는 동일한 인자로 가중치의 스켈일 낮춤

가중치를 √(2/n_inputs)로 나눔 (n_inputs = 층의 입력 개수)

가중치 초기화에서 스케일을 맞추지 않고 모델의 한 부분으로 가중치를 조정함으로써 훈련 내내 모든 파라미터의 Dynamic Range를 동일하게 만듦

→ 모든 가중치가 동일한 속도로 학습됨 → 훈련 속도와 안정성 향상

 

픽셀별 정규화 층

생성자의 합성곱 층 뒤에 추가

이 층은 동일한 이미지의 동일 위치에 있는 모든 활성화를 채널에 대해 정규화 (활성화의 제곱 평균의 제곱근으로 나눔)

→ input / tf.sqrt(tf.reduce_mean(tf.square(X), axis = -1, keepdims = True) + 1e-8)

*1e-8을 더해주는 것은 0으로 나누는 것 방지

이 기법은 생성자와 판별자 사이의 과도한 경쟁으로 활성화 값이 폭주되는 것을 막음

 

9.4 StyleGAN

Style Transfer 기법을 사용해 생성된 이미지가 훈련된 이미지와 같은 다양한 크기의 국부적인 구조를 갖도록 만듦

이는 생성된 이미지의 품질을 크게 높여줌

판별자와 손실함수는 그대로 두고 생성자만 변경, 네트워크 두 개로 구성

 

Mapping 네트워크

8개의 MLP가 잠재표현 z(코딩)를 vector w로 mapping한다

이 vector는 여러 affine transformation('A'라고 표시된 활성화 함수가 없는 Dense 층)으로 전달되어 vector 여러 개 생성

이 vector는 미세한 텍스처부터 고수준 특성까지 각기 다른 수준에서 생성된 이미지의 스타일을 제어

→ Mapping 네트워크는 코딩을 여러 스타일 vector로 매핑

 

합성 네트워크

이미지 생성을 책임짐

일정하게 학습된 입력을 받음 (훈련이 끝난 후에 입력이 일정해지고 훈련하는 동안에는 역전파에 의해 계속 바뀜)

앞에서와 같이 이 입력을 합성곱 여러 개와 업샘플링 층에 통과시킴

But,

    1. 입력과 활성화 함수 전에 있는 모든 합성곱 층의 출력에 잡음이 조금 섞임

    2. 잡음이 섞인 다음에 적응적 인스턴스 정규화(AdaIN) 층이 뒤 따름

각 특성 맵을 독립적으로 (특성 맵의 평균을 빼고 표준편차로 나누어) 표준화한 다음 스타일 Vector를 사용해 각 특성 맵의 스케일과 이동을 결정 (Style vector에는 특성 맵마다 하나의 스케일과 하나의 편향이 포함됨)

코딩에 독립적으로 Noise를 추가하는 것이 매우 중요

추가된 Noise를 사용하여 이미지의 각 부분에 정확한 양의 무작위성을 추가할 수 있음

 

추가된 Noise는 각 수준마다 다르다

Noise 입력은 하나의 특성 맵을 채우는 Gaussian Noise로 구성되며 모든 특성 맵으로 브로드캐스팅 된다

그 후, 추가되기 전에 학습된 특성별 스케일링 인자로 조정됨

 

마지막으로 StyleGAN은 일정 비율의 이미지를 두 개의 다른 코딩으로 생성하는 Mixing Regularization이라 불리는 기법을 사용

구체적으로 코딩 c1과 c2가 매핑 네트워크를 통과하여 두 style vector w1과 w2를 만듦

그다음 합성 네트워크가 천 번째 단계에서 스타일 w1으로 나머지 단계에서는 스타일 w2를 바탕으로 이미지를 생성

변경되는 단계는 랜덤하게 선택됨 → 네트워크가 인접한 수준의 스타일이 상관관계를 가진다고 가정하지 못하도록 막음

→ 각 style vector가 생성된 이미지에 있는 제한된 개수의 속성에만 영향을 미치는 styleGAN의 국지성을 촉진시킴

 

사전훈련된 StyleGAN keras model

http://bit.ly/nvidia-stylegan 

 

NVlabs/stylegan

StyleGAN - Official TensorFlow Implementation. Contribute to NVlabs/stylegan development by creating an account on GitHub.

github.com

http://bit.ly/nvidia-stylegan2 

 

NVlabs/stylegan2

StyleGAN2 - Official TensorFlow Implementation. Contribute to NVlabs/stylegan2 development by creating an account on GitHub.

github.com