딥러닝 프레임워크/생성형 AI

GAN(Generative Adversarial Network)

Zoo_10th 2024. 4. 22.

1. GAN 이란?

GAN(Generative Adversarial Network)은 생성적 적대 신경망으로, 2014년 Ian Goodfellow와 그의 동료들에 의해 처음 제안된 딥러닝 모델이다. GAN은 두 개의 신경망, 즉 생성자(Generator)와 구분자(Discriminator)가 서로 경쟁하면서 학습하는 구조를 가지고 있다.

1-2. 목적

GAN의 목적은 진짜와 구별할 수 없는 가짜 데이터를 생성하는 것이다. 생성자는 실제 데이터와 구분자를 속이기 위해 점차 실제 데이터와 비슷한 데이터를 생성하게 되고, 구분자는 진짜와 가짜를 구별하는 데 점차 능숙해진다.

1-3. 기본 원리

GAN의 기본 원리는 두 개의 신경망인 생성자와 구분자를 상호 경쟁시키는 것이다.

 - 생성자는 주어진 랜덤 노이즈 벡터를 받아 실제 데이터와 비슷한 데이터를 생성한다.

 - 구분자는 실제 데이터와 생성자가 만든 데이터를 구별하여 진짜와 가짜를 판별한다.

 - 생성자는 구분자를 속이기 위해 생성한 데이터를 실제 데이터처럼 만들어야 하며, 구분자는 가능한 한 정확하게 구별하려고 한다.

 - 이 경쟁적인 학습 과정을 통해 생성자는 실제 데이터와 구별할 수 없는 데이터를 생성하게 된다.

2. 손실 함수

2-1. 생성자 손실 함수 (Generator Loss)

 - 생성자의 목표는 구분자를 속이는 것이다. 생성자가 만들어낸 가짜 데이터의 구분자 출력을 1에 가깝게 만드는 것이 목표이다. 이를 위해서는 생성된 데이터와 구분자의 출력값의 차이를 최소화해야 한다. 보통은 실제 데이터 대신에 생성자가 만든 데이터를 입력으로 넣어 구분자의 출력을 얻고, 그 출력에 대한 손실을 계산한다. 이 손실을 최소화하면 생성자는 더 실제 데이터와 유사한 데이터를 생성하도록 학습된다.

2-2. 구분자 손실 함수 (Discriminator Loss)

 - 구분자의 목표는 생성된 가짜 데이터와 실제 데이터를 구별하는 것이다. 따라서 구분자는 가짜 데이터에 대해서는 0에 가깝게, 실제 데이터에 대해서는 1에 가깝게 출력하도록 학습된다. 이를 위해 가짜 데이터와 실제 데이터의 구분자의 출력값 차이를 최대화한다. 즉, 구분자의 목표는 정확한 구별을 하기 위해 손실을 최대화하는 것이다.

2-3. 학습 과정

1) 생성자는 랜덤한 노이즈 벡터를 입력받아 가짜 데이터를 생성한다.

2) 생성된 가짜 데이터와 실제 데이터가 구분자에 의해 평가된다.

3) 생성자의 손실 함수를 최소화하도록 생성자의 가중치를 업데이트하고, 구분자의 손실 함수를 최대화하도록 구분자의 가중치를 업데이트한다.

4) 이러한 과정을 반복하면서 생성자는 실제 데이터와 구별할 수 없는 가짜 데이터를 생성하게 되고, 구분자는 점차 더 정확하게 구별하게 된다.

3. GAN Architecture

3-1. Vanilla GAN (기본 GAN)

Vanilla GAN은 GAN의 기본 형태로, 생성자와 구분자로 구성된다. 생성자는 랜덤한 노이즈 벡터를 입력으로 받아 이미지를 생성하고, 구분자는 실제 이미지와 생성자가 생성한 이미지를 구별한다. 이 두 네트워크는 서로 경쟁하며 학습하게 되고, 생성자는 실제 이미지와 유사한 이미지를 생성하도록, 구분자는 진짜와 가짜를 더 잘 구별하도록 학습된다.

3-2. DCGAN (Deep Convolutional GAN)

DCGAN은 합성곱 신경망을 사용하여 GAN을 개선한 것이다. 이미지 생성 및 구분을 위해 CNN을 사용함으로써 더 안정적이고 고품질의 이미지를 생성할 수 있게 되었다. DCGAN은 합성곱 층과 전치 합성곱 층을 사용하여 이미지를 처리하고 생성한다.

3-3. CGAN (Conditional GAN)

CGAN은 Vanilla GAN의 확장으로, 생성자와 구분자에 추가적인 조건 정보가 주어진다. 이 조건 정보는 생성자가 원하는 특정한 이미지를 생성하도록 돕는다. 예를 들어, 특정 숫자를 생성하도록 조건을 주면, 해당 숫자에 대한 이미지를 생성하게 된다.

3-4. CycleGAN

CycleGAN은 두 도메인 간의 이미지를 변환하는 데 사용된다. 주로 스타일 변환에 활용되며, 한 도메인의 이미지를 다른 도메인의 이미지로 변환하고, 다시 원래 도메인으로 변환함으로써 일종의 순환성을 가지게 된다.

3-5. Progressive GAN

Progressive GAN은 해상도를 단계적으로 키워가며 생성자와 구분자를 훈련시키는 방법이다. 처음에는 낮은 해상도에서 시작하여 점차 높은 해상도로 이미지를 생성하도록 한다. 이러한 방식으로 고해상도 이미지를 생성할 수 있으며, 더 높은 품질의 이미지를 얻을 수 있다.

4. GAN 활용 사례 (기술동향, 트렌드)

4-1. 이미지 생성

https://openai.com/dall-e-2

 

DALL·E 2

DALL·E 2 is an AI system that can create realistic images and art from a description in natural language.

openai.com

GAN은 이미지 생성 분야에서 큰 성과를 보여주고 있다. 특히, StyleGAN과 같은 모델은 실제같은 고품질 이미지를 생성하여 예술 작품, 캐릭터, 풍경 등 다양한 영역에서 활용된다.

4-2. 이미지 편집

4-3. 이미지 해상도 향상

GFPGAN

​ GAN을 사용하여 저해상도 이미지를 고해상도로 업스케일링하는 기술이 발전하고 있다. 이를 통해 이미지의 세부 정보를 더 정확하게 복원하고 높은 해상도의 이미지를 얻을 수 있다.

5. GAN의 한계와 트렌드

5-1. 모드 붕괴 (Mode Collapse)

GAN에서 생성자가 다양한 결과를 생성하지 않고 특정한 이미지만을 생성하는 현상을 모드 붕괴라고 한다. 이로 인해 GAN이 다양한 결과물을 생성하지 못하고 특정 부류의 이미지만을 생성하는 문제가 발생할 수 있다.

5-2. 학습 불안정성

GAN은 생성자와 구분자 간의 경쟁적 학습을 기반으로 하기 때문에 학습이 불안정할 수 있다. 초반에는 생성자가 아직 학습되지 않았기 때문에 구분자가 쉽게 가짜를 식별하며, 이로 인해 생성자가 더 나은 결과를 얻기 어려워지는 현상이 발생할 수 있다.

5-3. 과적합

GAN은 데이터의 분포를 학습하기 때문에 충분한 양의 다양한 데이터가 필요하다. 데이터가 제한적일 경우 과적합 문제가 발생할 수 있으며, 이로 인해 생성된 이미지의 다양성과 품질이 저하될 수 있다.

5-4. 트렌드: Self-Supervised Learning과의 통합

Self-Supervised Learning은 레이블이 없는 데이터를 활용하여 모델을 학습하는 방법으로, GAN과 통합하여 레이블 없는 데이터를 기반으로 생성 및 학습을 진행하는 방향으로 연구가 진행되고 있다. 이를 통해 더 나은 생성 결과와 학습의 안정성을 도모하고 있다.

5-5. 트렌드: Few-Shot Learning 및 메타 학습

Few-Shot Learning 및 메타 학습은 작은 데이터셋에서도 빠르게 학습하고 새로운 작업에 적용할 수 있는 능력을 갖는 모델을 개발하는 방향으로 연구가 진행되고 있다. GAN과 통합하여 작은 데이터셋에서도 효과적으로 이미지 생성 및 변환 작업을 수행하는 연구들이 진행 중이다.

6. MNIST GAN 실습

6-1. 라이브러리 준비

6-2. 데이터셋 로딩 및 준비

1) 데이터 로드

MNIST 데이터셋을 불러오고, 학습에 사용할 훈련 이미지(train_images)와 레이블(train_labels)을 가져온다.

2) 이미지 정규화

 - MNIST 이미지 데이터를 [-1, 1] 범위로 정규화한다. 정규화는 이미지의 각 픽셀 값을 [-1, 1] 사이로 스케일링하여 학습을 안정화시키고 최적화를 돕는다.

3) 데이터셋 파라미터 설정

 - BUFFER_SIZE: 데이터를 섞기 위한 버퍼의 크기로, 60,000으로 설정하였다. 데이터를 섞음으로써 학습 시 모델이 특정 패턴에 치우치지 않도록 도움을 준다.

 - BATCH_SIZE: 한 번에 학습할 배치의 크기로, 256으로 설정하였다.

4) 데이터 배치 생성 및 섞기

 - tf.data.Dataset.from_tensor_slices(train_images): 이미지 데이터를 tf.data.Dataset 형태로 변환하여 데이터셋을 생성한다.

 - shuffle(BUFFER_SIZE): 데이터셋을 섞는데 사용되며, BUFFER_SIZE만큼의 버퍼를 사용하여 데이터를 랜덤하게 섞는다.

 - batch(BATCH_SIZE): 배치 크기에 따라 데이터셋을 배치로 나눈다. 각 배치는 BATCH_SIZE만큼의 이미지를 포함한다.

6-3. 모델 만들기

1) 생성자

생성자는 시드값 (seed; 랜덤한 잡음)으로부터 이미지를 생성하기 위해, tf.keras.layers.Conv2DTranspose (업샘플링) 층을 이용한다. 처음 Dense층은 이 시드값을 인풋으로 받습니다. 그 다음 원하는 사이즈 28x28x1의 이미지가 나오도록 업샘플링을 여러번 한다. tanh를 사용하는 마지막 층을 제외한 나머지 각 층마다 활성함수로 tf.keras.layers.LeakyReLU을 사용하고 있다.

① Dense 레이어를 통해 100차원의 랜덤 노이즈를 받아 7x7x256 차원으로 변환한다.

② 이후 Reshape 레이어로 3D 텐서로 변환하여 CNN 레이어들을 통해 업샘플링을 수행한다.

③ Conv2DTranspose 레이어를 통해 업샘플링을 수행하고, BatchNormalization 및 LeakyReLU 활성화 함수를 사용하여 출력을 준비한다.

④ 마지막 레이어에서는 28x28x1 크기의 이미지를 생성하며, tanh 활성화 함수를 사용하여 이미지를 생성한다.

2) 감별자

감별자는 합성곱 신경망(Convolutional Neural Network, CNN) 기반의 이미지 분류기이다.

① 첫 번째 Conv2D 레이어: 5x5 필터를 사용하여 64개의 채널로 특징을 추출하고, 2 strides로 다운샘플링한다.

② LeakyReLU 활성화 함수를 사용하여 비선형성을 추가하고, 과적합을 방지하기 위해 Dropout을 적용한다.

③ 두 번째 Conv2D 레이어: 5x5 필터를 사용하여 128개의 채널로 특징을 추출하고, 2 strides로 다운샘플링한다.

④ Flatten 레이어를 사용하여 1D 벡터로 펼친다.

⑤ 마지막 Dense 레이어에서 1개의 출력 유닛을 사용하여 이진 분류를 수행한다. 이 출력은 진짜 이미지인지 가짜 이미지인지를 나타낸다.

3) 손실함수와 옵티마이저 정의

4) 감별자 손실함수

메서드는 감별자가 가짜 이미지에서 얼마나 진짜 이미지를 잘 판별하는지 수치화한다. 진짜 이미지에 대한 감별자의 예측과 1로 이루어진 행렬을 비교하고, 가짜 (생성된) 이미지에 대한 감별자의 예측과 0으로 이루어진 행렬을 비교한다.

 - real_output: 감별자에게 진짜 이미지를 입력했을 때의 출력값 (진짜 이미지에 대한 판별 결과)

 - fake_output: 감별자에게 가짜 이미지를 입력했을 때의 출력값 (가짜 이미지에 대한 판별 결과)

 - cross_entropy: 크로스 엔트로피 손실 함수로, 각 이미지의 손실을 계산하는데 사용된다.

 - real_loss: 진짜 이미지에 대한 손실로, 진짜 이미지를 실제로 진짜로 분류하도록 한다.

 - fake_loss: 가짜 이미지에 대한 손실로, 가짜 이미지를 가짜로 분류하도록 한다.

 - total_loss: 총 손실로, 진짜 이미지 손실과 가짜 이미지 손실을 합한 값입니다. 이것이 감별자의 최종 손실로 사용된다.

5) 생성자 손실함수

생성자의 손실함수는 감별자를 얼마나 잘 속였는지에 대해 수치화를 한다. 직관적으로 생성자가 원활히 수행되고 있다면, 감별자는 가짜 이미지를 진짜 (또는 1)로 분류를 할 것이다. 여기서 우리는 생성된 이미지에 대한 감별자의 결정을 1로 이루어진 행렬과 비교를 할 것이다.

 - fake_output: 생성자가 생성한 가짜 이미지를 감별자에 입력했을 때의 출력값 (가짜 이미지에 대한 판별 결과)

 - cross_entropy: 크로스 엔트로피 손실 함수로, 각 이미지의 손실을 계산하는데 사용된다.

 - generator_loss: 생성자의 손실로, 감별자가 가짜 이미지를 진짜로 판별하도록 만드는 손실을 나타낸다. 생성자는 이 손실을 최소화하여 가짜 이미지를 진짜처럼 만들려고 노력한다.

6) 체크포인트 저장

 - checkpoint_dir: 체크포인트 파일들을 저장할 디렉토리 경로를 지정한다.

 - checkpoint_prefix: 체크포인트 파일들의 접두사로, 이를 활용하여 체크포인트 파일들의 이름을 지정한다.

 - tf.train.Checkpoint: 텐서플로우에서 제공하는 체크포인트 관리 클래스로, 특정 변수들의 상태를 저장하고, 나중에 불러와서 사용할 수 있도록 한다. 여기서는 생성자, 감별자, 그리고 optimizer들의 상태를 저장한다.

7) 훈련 루프 정의하기

 - EPOCHS: 총 에폭 수로, 전체 학습 데이터셋을 몇 번 반복할 것인지를 결정한다.

 - noise_dim: 생성자에 입력될 랜덤 노이즈 벡터의 차원이다. 이 차원은 생성자가 얼마나 다양한 이미지를 생성할 수 있는지에 영향을 미친다.

 - num_examples_to_generate: 시각화를 위해 생성할 이미지의 수를 나타낸다.

 - seed: 생성자에 입력할 초기 랜덤 노이즈 벡터로, 이미지 생성의 기초가 되는 값들이다. 특정 랜덤 시드를 사용하여 이미지를 생성하면, 같은 시드를 사용하여 학습 중간에 이미지를 생성하여 진행 상황을 시각적으로 확인할 수 있다.

훈련 루프는 생성자가 입력으로 랜덤시드를 받는 것으로부터 시작된다. 그 시드값을 사용하여 이미지를 생성한다. 감별자를 사용하여 (훈련 세트에서 갖고온) 진짜 이미지와 (생성자가 생성해낸) 가짜이미지를 분류한다. 각 모델의 손실을 계산하고, 그래디언트 (gradients)를 사용해 생성자와 감별자를 업데이트한다.(학습 단계를 정의하는 train_step 함수에 @tf.function 데코레이터를 사용하여 TensorFlow의 그래프 모드로 컴파일하는 부분이다.)

 - @tf.function: TensorFlow에서 제공하는 데코레이터로, 해당 함수를 TensorFlow의 그래프 모드로 컴파일하여 성능을 향상시킨다.

 - train_step: 학습 단계를 정의하는 함수로, 주어진 이미지에 대해 생성자와 감별자를 업데이트하고 손실을 계산하여 그래디언트를 적용한다.

 - tf.GradientTape: 그래디언트를 계산하기 위한 TensorFlow의 컨텍스트 관리자이다. 생성자와 감별자의 그래디언트를 계산하기 위해 사용된다.

8) 이미지 생성 및 저장

 - generate_and_save_images: 생성자를 사용하여 입력된 랜덤 노이즈 벡터로부터 이미지를 생성하고, 이를 플롯하여 저장한다.

 - model: 사용할 생성자 모델이다.

 - epoch: 현재 에폭(epoch)의 번호로, 저장된 이미지의 파일 이름에 사용된다.

 - test_input: 생성자에 입력할 랜덤 노이즈 벡터로, 이미지를 생성하는 데 사용된다.

 - 생성된 이미지들은 4x4 그리드로 표시되며, 각 이미지의 픽셀 값은 [-1, 1] 범위로 되돌려진 후 시각화된다. 결과 이미지는 파일로 저장된다.

9) GIF 생성

728x90

댓글