한양과학기술고등학교

에듀테크 프로젝트 대시보드

생성적 적대 신경망 (GAN)

생성적 적대 신경망 (GAN)

생성자 G vs 판별자 D · 미니맥스 게임으로 진짜 같은 가짜를 만드는 법  |  8개 봉우리 분포를 흉내내는 2D 토이 GAN

역전파로 학습하는 신경망 하나만 있으면 "정답이 있는" 분류·회귀 문제를 풀 수 있습니다. 그런데 "진짜 같은 이미지를 새로 만들어라"처럼 정답 라벨이 없는 문제는 어떻게 학습시킬까요? 2014년 이안 굿펠로우가 제안한 GAN은 신경망 두 개를 서로 경쟁시켜 이 문제를 풉니다. 생성자(Generator) G는 위조지폐범처럼 무작위 노이즈로 가짜를 찍어내고, 판별자(Discriminator) D는 감별사처럼 진짜와 가짜를 구분하려 합니다. 둘 다 점점 실력이 늘면서, G는 결국 D조차 속을 만큼 진짜 같은 샘플을 만들게 됩니다.

1. 두 신경망의 순전파 흐름

노이즈 z ~ Uniform(−1,1)²─▶ 생성자 G(z)─▶ 가짜 샘플 x_fake
실제 데이터 x_real (8-가우시안)─┐
x_real 또는 x_fake─▶ 판별자 D(x)─▶ 확률 p = P(진짜)

D는 x_real에는 1(진짜), x_fake에는 0(가짜)이라고 답하도록 학습됩니다. G는 정답 라벨이 없는 대신, D의 판단을 손실로 사용합니다 — "내가 만든 게 D를 얼마나 잘 속였는가"가 곧 G의 성적표입니다.

2. 미니맥스 목적함수

# 원논문의 적대적 게임 (Goodfellow et al., 2014)
min_G max_D  V(D,G) = E[log D(x_real)] + E[log(1 − D(G(z)))]

# D는 이 값을 최대화(진짜=1, 가짜=0 잘 맞히기)
# G는 이 값을 최소화(D가 가짜를 진짜로 착각하게 만들기)
비-포화(non-saturating) 트릭: 학습 초반 G가 형편없을 때는 D가 가짜를 너무 쉽게 잡아내 log(1−D(G(z)))의 기울기가 거의 0이 되어 G가 학습되지 않습니다(기울기 소실). 그래서 실전에서는 G의 손실을 −log D(G(z))로 바꿔 씁니다 — "D를 속이는 데 실패했다"를 최소화하는 대신 "D가 진짜라고 믿게 만들기"를 최대화하는 것으로 부호만 바꾼 것인데, 초반 기울기가 훨씬 커서 학습이 안정적입니다. 아래 데모도 이 트릭을 사용합니다.

3. 직접 학습시켜 보기 — 8개 봉우리 분포 흉내내기

파란 점은 실제 데이터(원 위에 고르게 놓인 8개 가우시안 봉우리), 분홍 점은 지금 G가 만들어낸 가짜 샘플입니다. 배경의 밝기는 판별자 D가 그 위치를 얼마나 "진짜"라고 믿는지를 나타내는 확률 히트맵입니다. 학습 시작을 누르고 분홍 점들이 8개 봉우리를 골고루 덮는지, 아니면 한두 곳에만 몰리는지(모드 붕괴) 관찰해 보세요.

실제 데이터 x_real 생성된 가짜 x_fake 배경 밝기 = D(x)의 "진짜" 확신도
0.12
8
step 0
D 손실 – · G 손실 –
D(x_real) 평균 확신도
대기 중

균형점(내쉬 균형)에서는 D가 진짜·가짜를 구분 못 해 확신도가 50% 근처로 수렴합니다. 학습률이 너무 크면 G와 D가 서로 튕겨내며 진동(불안정)하고, 점들이 한 봉우리에만 뭉치면 모드 붕괴입니다 — 그때는 새로 뽑기를 눌러보세요.

4. 왜 GAN 학습이 어려운가

문제증상완화책
기울기 소실G의 손실이 초반에 거의 안 움직임비-포화 손실(위 2번)
모드 붕괴다양한 실제 데이터 중 일부만 흉내냄미니배치 판별, unrolled GAN
훈련 불안정D·G 손실이 수렴 안 하고 진동학습률 축소, WGAN(거리 기반 손실)
균형 판단 어려움"충분히 학습됐다"를 손실만으로 알기 어려움샘플 육안 확인, FID 점수

5. 생성 모델 계열 한눈에 비교

GANVAE확산 모델(Diffusion)
학습 방식생성자·판별자 적대적 경쟁인코더·디코더 재구성 + 잠재분포 정규화노이즈를 점진적으로 제거하도록 학습
생성 속도빠름 (forward 1회)빠름 (forward 1회)느림 (수십~수천 스텝 반복)
대표 이슈모드 붕괴·불안정흐릿한 결과물느린 샘플링 속도
대표 사례StyleGAN, 딥페이크이미지 압축·표현 학습Stable Diffusion, DALL·E

6. 파이썬 의사코드 (한 스텝)

for step in range(num_steps):
    # ── ① 판별자 D 학습: 진짜=1, 가짜=0 을 구분하도록 ──
    x_real = sample_real_batch()
    z      = sample_noise_batch()
    x_fake = G(z).detach()                      # G는 이 단계에서 갱신 안 함
    loss_D = bce(D(x_real), 1) + bce(D(x_fake), 0)
    update(D, grad(loss_D, D.params))

    # ── ② 생성자 G 학습: D가 가짜를 진짜라고 믿도록 ──
    z      = sample_noise_batch()
    x_fake = G(z)
    loss_G = bce(D(x_fake), 1)              # 비-포화 트릭: 목표 라벨을 1로
    update(G, grad(loss_G, G.params))            # D는 이 단계에서 고정, 기울기만 통과
핵심 포인트: G를 학습할 때도 D의 순전파·역전파를 거쳐야 기울기가 G까지 전달됩니다. 다만 이때 D의 가중치는 갱신하지 않고, "가짜를 조금 더 진짜처럼 만들려면 입력을 어느 방향으로 옮겨야 하는가"라는 입력에 대한 기울기만 빌려서 G의 가중치를 고칩니다.

핵심 정리

  • GAN = 생성자 G(가짜 생성)와 판별자 D(진짜/가짜 구분)의 적대적 게임
  • D는 진짜 1·가짜 0 분류 손실로, G는 D를 속이는 정도를 손실로 학습
  • 초반 기울기 소실을 막기 위해 G 손실에 비-포화 트릭 사용
  • 균형점에서 D의 확신도는 50%로 수렴 — 더 이상 진짜·가짜를 구분 못 함
  • 대표 실패 사례는 모드 붕괴(다양성 손실)와 훈련 불안정
  • 딥페이크·StyleGAN 등에 쓰이며, 최근에는 확산 모델(Diffusion)이 이미지 생성의 주류로 떠오르는 중