변분 오토인코더(Variational Autoencoder, VAE)는 2013년 Kingma와 Welling이 발표한 생성 모델로, 잠재변수 기반 생성 모델 계열의 출발점이 된 연구입니다. 이 글에서는 VAE의 수식이 왜 그렇게 구성되는지를 데이터 분포 정의부터 ELBO 유도, 재파라미터화 트릭까지 순서대로 정리합니다.
생성 모델과 데이터 분포
생성 모델의 목표는 데이터 분포 \(p(x)\)를 학습하는 것입니다. 256×256 RGB 이미지의 경우 \(x\)는 약 19만 6천 차원의 벡터 한 개이고, \(p(x)\)는 그 점에서의 확률밀도값입니다. 함수 \(p(\cdot)\) 자체는 가능한 모든 이미지가 위치하는 고차원 공간 위에 정의된 분포입니다.
이 분포를 고차원 공간의 산맥으로 시각화할 수 있습니다. 산이 높은 영역에는 사람 얼굴, 풍경, 동물 사진 같은 그럴듯한 이미지들이 모여 있고, 골짜기에는 노이즈에 가까운 픽셀 배열들이 있습니다. 학습된 모델의 \(p(x)\)는 이 산맥의 높이지도와 같은 역할을 합니다.
학습이 끝나면 이 분포에서 점을 샘플링하여 새 이미지를 만듭니다. 산이 높은 영역에서 자주 뽑히므로 자연스럽게 그럴듯한 이미지가 나오고, 매번 다른 점이 뽑히기 때문에 다양성이 확보됩니다. 가장 높은 점 하나만 출력한다면 매번 똑같은 이미지가 나오게 됩니다.
잠재변수 모델
잠재변수의 도입
\(p(x)\)를 픽셀 공간에서 직접 모델링하는 것은 매우 어렵습니다. 이미지의 의미 구조와 픽셀 단위 표현 사이의 간극이 너무 크기 때문입니다. VAE는 이미지 \(x\)가 어떤 저차원 잠재 코드 \(z\)로부터 생성된다고 가정합니다. \(z\)는 보통 수십에서 수백 차원의 벡터로, 표정·각도·색감 같은 추상적 정보를 압축해 담은 코드로 해석할 수 있습니다.
이렇게 두면 모델링이 두 부분으로 분리됩니다. 사전 분포 \(p(z)\)는 "어떤 잠재 코드가 자연스러운가"를, 조건부 분포 \(p_\theta(x|z)\)는 "주어진 코드로부터 이미지가 어떻게 만들어지는가"를 담당합니다. 후자는 신경망으로 학습하고, 전자는 표준 정규분포 같은 단순한 분포로 고정합니다.
Marginalization
잠재변수가 있을 때 \(p(x)\)는 결합 분포에서 \(z\)를 적분으로 지워 얻습니다.
\( p_\theta(x) = \int p_\theta(x|z) \, p(z) \, dz \)
이미지 \(x\)가 나올 확률은 모든 가능한 \(z\)에서 \(x\)가 나올 확률을 \(z\)의 확률로 가중평균한 값입니다. \(x\)가 어떤 \(z\)에서 왔는지 알 수 없으므로 모든 \(z\)에 대해 가능성을 합산해야 하고, \(z\)가 연속이라 합산이 적분으로 표현됩니다.
적분의 계산 불가능성
\(p_\theta(x|z)\)가 신경망이라 이 적분은 해석적으로 풀리지 않습니다. \(z\)가 64차원만 되어도 64중 적분이 필요한데 수치 적분도 현실적이지 않습니다. 이 적분의 계산 불가능성이 VAE 전체 설계의 출발점입니다. VAE는 적분을 직접 풀지 않고 학습 가능한 하한(ELBO)을 만들어 우회합니다.
인코더와 디코더
디코더 \(p_\theta(x|z)\)
디코더는 잠재 코드 \(z\)를 받아 이미지 \(x\)를 만들어내는 신경망입니다. 출력은 확률 분포로 정의되며 보통 가우시안으로 모델링합니다.
\( p_\theta(x|z) = \mathcal{N}(\mu_\theta(z), \, \sigma^2 I) \)
\(\mu_\theta(z)\)는 가우시안의 평균이며 이미지 공간의 한 점(한 장의 이미지)에 해당합니다. 코드 수준에서 \(\mu_\theta(z)\)는 decoder(z)의 출력입니다.
가우시안 가정 하에서 로그 우도가 어떻게 풀리는지 짚어봅니다. 평균 \(\mu\), 공분산 \(\sigma^2 I\)를 갖는 \(d\)차원 다변량 가우시안의 확률밀도함수는
\( \mathcal{N}(x; \mu, \sigma^2 I) = \frac{1}{(2\pi\sigma^2)^{d/2}} \exp\left( -\frac{1}{2\sigma^2} \|x - \mu\|^2 \right) \)
입니다. 양변에 로그를 취하면
\( \log \mathcal{N}(x; \mu, \sigma^2 I) = -\frac{d}{2} \log(2\pi\sigma^2) - \frac{1}{2\sigma^2} \|x - \mu\|^2 \)
첫 항은 \(\theta\)와 무관한 상수이므로 \(\mu = \mu_\theta(z)\)를 대입하면
\( \log p_\theta(x|z) = -\frac{1}{2\sigma^2} \| x - \mu_\theta(z) \|^2 + \text{const} \)
로그 우도를 최대화하는 것은 결국 \(\|x - \mu_\theta(z)\|^2\), 즉 MSE를 최소화하는 것과 동치입니다. VAE 손실 함수의 재구성 항은 이 가정에서 직접 유도된 결과입니다. MNIST 같은 이진 픽셀 데이터에서는 베르누이 분포로 가정해 이진 교차 엔트로피(BCE) 형태가 사용됩니다.
인코더 \(q_\phi(z|x)\)
데이터 \(x\)가 주어졌을 때 잠재 코드의 진짜 사후 분포는 다음과 같이 정의됩니다.
\( p(z|x) = \frac{p_\theta(x|z) \, p(z)}{p_\theta(x)} \)
분모에 계산 불가능한 \(p_\theta(x)\)가 들어 있어 이 분포는 직접 평가할 수 없습니다. VAE는 이를 신경망으로 근사하며, 그 근사 분포가 인코더 \(q_\phi(z|x)\)입니다. 디코더와 마찬가지로 가우시안으로 모델링합니다.
\( q_\phi(z|x) = \mathcal{N}(\mu_\phi(x), \, \sigma_\phi^2(x) I) \)
인코더 신경망은 이미지 \(x\)를 받아 두 개의 벡터 출력 \(\mu_\phi(x)\)와 \(\sigma_\phi(x)\)를 생성하며, 이 둘이 그 \(x\)에 대응하는 잠재 코드 분포의 평균과 표준편차를 정의합니다.
디코더와 인코더는 대칭 구조이며 파라미터를 분리해 표기합니다. 디코더 파라미터는 \(\theta\), 인코더 파라미터는 \(\phi\)입니다. 두 신경망은 같은 손실 함수로 동시에 학습됩니다.
ELBO: 변분 하한
핵심 항등식의 유도
계산 불가능한 \(\log p_\theta(x)\)를 직접 최대화할 수 없으므로 그것의 하한을 만들어 대신 최대화합니다. 이 하한(ELBO)은 인코더 \(q_\phi(z|x)\)와 진짜 사후 분포 \(p(z|x)\) 사이의 KL 발산을 풀어 쓰는 과정에서 자연스럽게 유도됩니다.
KL 발산의 정의는 다음과 같습니다.
\( D_{KL}(q_\phi(z|x) \| p(z|x)) = \mathbb{E}_{q_\phi(z|x)} \left[ \log \frac{q_\phi(z|x)}{p(z|x)} \right] \)
베이즈 정리에서 \(p(z|x) = p_\theta(x, z) / p_\theta(x)\)이므로, 이를 대입하면
\( D_{KL}(q_\phi(z|x) \| p(z|x)) = \mathbb{E}_{q_\phi} \left[ \log q_\phi(z|x) - \log p_\theta(x, z) + \log p_\theta(x) \right] \)
\(\log p_\theta(x)\)는 \(z\)와 무관해 기댓값 밖으로 빠집니다.
\( D_{KL}(q_\phi(z|x) \| p(z|x)) = \log p_\theta(x) - \mathbb{E}_{q_\phi} \left[ \log p_\theta(x, z) - \log q_\phi(z|x) \right] \)
\(\log p_\theta(x)\)에 대해 정리하면 다음 항등식을 얻습니다.
\( \log p_\theta(x) = \underbrace{\mathbb{E}_{q_\phi} \left[ \log p_\theta(x, z) - \log q_\phi(z|x) \right]}_{\mathcal{L}(\theta, \phi;\, x), \;\text{ELBO}} + D_{KL}(q_\phi(z|x) \| p(z|x)) \)
우변 첫 항이 ELBO(Evidence Lower Bound)이고, 둘째 항은 인코더와 진짜 사후 분포 사이의 KL 발산입니다. KL 발산은 항상 0 이상이므로 다음이 성립합니다.
\( \log p_\theta(x) \geq \mathcal{L}(\theta, \phi; x) \)
ELBO는 \(\log p_\theta(x)\)의 하한선이며, ELBO를 위로 밀어올리면 천장에 해당하는 \(\log p_\theta(x)\)도 함께 올라갑니다. 동시에 KL 항이 줄어들어 인코더 \(q_\phi\)가 진짜 사후 분포에 가까워집니다. 한 식의 최적화로 생성 모델 학습과 추론 모델 학습이 동시에 진행됩니다.
ELBO 분해
앞에서 유도한 ELBO를 다시 정리하면 학습에 실제로 쓰이는 손실 함수 형태가 나옵니다. 결합 분포를 \(p_\theta(x, z) = p_\theta(x|z) p(z)\)로 분해해 ELBO 안에 대입합니다.
\( \mathcal{L}(\theta, \phi; x) = \mathbb{E}_{q_\phi} \left[ \log p_\theta(x|z) + \log p(z) - \log q_\phi(z|x) \right] \)
두 부분으로 분리합니다.
\( \mathcal{L}(\theta, \phi; x) = \mathbb{E}_{q_\phi} \left[ \log p_\theta(x|z) \right] + \mathbb{E}_{q_\phi} \left[ \log p(z) - \log q_\phi(z|x) \right] \)
두 번째 항은 KL 발산의 정의에 의해 \(-D_{KL}(q_\phi(z|x) \| p(z))\)와 같습니다.
\( \mathbb{E}_{q_\phi} \left[ \log p(z) - \log q_\phi(z|x) \right] = -\mathbb{E}_{q_\phi} \left[ \log \frac{q_\phi(z|x)}{p(z)} \right] = -D_{KL}(q_\phi(z|x) \| p(z)) \)
정리하면 ELBO는 두 항의 합으로 표현됩니다.
\( \mathcal{L}(\theta, \phi; x) = \mathbb{E}_{q_\phi(z|x)}[\log p_\theta(x|z)] - D_{KL}(q_\phi(z|x) \| p(z)) \)
재구성 항: \(\mathbb{E}_{q_\phi(z|x)}[\log p_\theta(x|z)]\). 인코더가 \(x\)에서 \(z\)를 뽑고 디코더가 그 \(z\)로부터 \(x\)를 복원할 때의 로그 우도의 기댓값입니다. 가우시안 디코더 가정 하에서는 MSE 형태가 되며, \(x \to z \to x\) 사이클이 잘 닫히도록 만드는 역할을 합니다.
정규화 항: \(D_{KL}(q_\phi(z|x) \| p(z))\). 인코더 출력 분포가 사전 분포 \(p(z) = \mathcal{N}(0, I)\)에서 너무 벗어나지 않도록 제약합니다. 이 항이 있어야 학습 후 사전 분포에서 \(z\)를 뽑아 디코더에 넣었을 때 의미 있는 이미지가 생성됩니다.
분해 식의 KL은 항등식 우변의 KL과 다른 항을 가리킵니다. 항등식의 KL은 근사 사후 분포와 진짜 사후 분포 사이의 거리라 계산 불가능하지만, 분해 식의 KL은 근사 사후 분포와 표준 가우시안 사이의 거리이므로 두 분포가 모두 가우시안이라 적분이 해석적으로 풀립니다.
유도는 1차원 가우시안에서 시작합니다. \(q(z) = \mathcal{N}(\mu, \sigma^2)\), \(p(z) = \mathcal{N}(0, 1)\)에 대해
\( \log q(z) - \log p(z) = -\frac{1}{2} \log \sigma^2 - \frac{(z-\mu)^2}{2\sigma^2} + \frac{z^2}{2} \)
이 식의 \(q\)에 대한 기댓값을 구합니다. \(z \sim \mathcal{N}(\mu, \sigma^2)\)일 때 \(\mathbb{E}[(z-\mu)^2/\sigma^2] = 1\), \(\mathbb{E}[z^2] = \mu^2 + \sigma^2\)이므로
\( D_{KL}(q \| p) = -\frac{1}{2} \log \sigma^2 - \frac{1}{2} + \frac{\mu^2 + \sigma^2}{2} = \frac{1}{2}\left( \mu^2 + \sigma^2 - \log \sigma^2 - 1 \right) \)
대각 공분산을 가정한 \(d\)차원 가우시안에서는 각 차원이 독립이므로 차원별 KL을 단순 합산합니다.
\( D_{KL}(q_\phi(z|x) \| p(z)) = \frac{1}{2} \sum_{j=1}^{d} \left( \mu_j^2 + \sigma_j^2 - \log \sigma_j^2 - 1 \right) \)
닫힌 형태란 적분이나 샘플링 없이 인코더 출력만으로 즉시 계산되는 식을 말하며, 사전 분포를 표준 가우시안으로 잡는 가장 큰 실용적 이유입니다.
재파라미터화 트릭
샘플링과 미분 불가능성
ELBO를 계산하려면 재구성 항의 기댓값을 평가해야 합니다. 실제 학습에서는 Monte Carlo로 근사해 인코더 분포에서 \(z\)를 한 개 뽑고 그 점에서의 로그 우도를 사용합니다.
\( \mathbb{E}_{q_\phi(z|x)}[\log p_\theta(x|z)] \approx \log p_\theta(x | z), \quad z \sim q_\phi(z|x) \)
문제는 \(z\)를 뽑는 샘플링 연산 자체입니다. 샘플링은 미분 불가능한 연산이라 \(\phi\)에 대한 그래디언트가 흐를 수 없습니다. 인코더 학습이 막힙니다.
무작위성의 외부화
샘플링 과정을 결정적 부분과 무작위 부분으로 분리합니다.
\( z = \mu_\phi(x) + \sigma_\phi(x) \odot \epsilon, \quad \epsilon \sim \mathcal{N}(0, I) \)
\(\epsilon\)은 신경망 외부에서 뽑은 노이즈이며 학습 대상이 아닙니다. \(\epsilon\)이 정해지면 \(z\)는 \(\mu_\phi, \sigma_\phi\)에 대해 덧셈과 곱셈으로만 이뤄진 결정적 함수가 되어 그래디언트가 흐릅니다.
분포 관점에서도 동등합니다. \(\epsilon \sim \mathcal{N}(0, I)\)일 때 \(z = \mu + \sigma \odot \epsilon\)의 평균은 \(\mu\), 분산은 \(\sigma^2\)이며, 가우시안의 affine 변환은 가우시안이므로 \(z \sim \mathcal{N}(\mu, \sigma^2)\)이 됩니다. 샘플링 절차를 바꿨을 뿐 같은 분포에서 뽑은 결과입니다.
학습과 생성
학습 단계
한 미니배치에 대한 학습 절차는 다음과 같습니다.
1. 학습 데이터에서 미니배치 \(\{x_1, \dots, x_M\}\)을 가져옵니다.
2. 각 \(x_i\)를 인코더에 통과시켜 \(\mu_\phi(x_i), \sigma_\phi(x_i)\)를 얻습니다.
3. 재파라미터화로 \(z_i = \mu_\phi(x_i) + \sigma_\phi(x_i) \odot \epsilon_i\)를 계산합니다. \(\epsilon_i\)는 매 스텝 새로 뽑은 표준 가우시안 노이즈입니다.
4. \(z_i\)를 디코더에 통과시켜 \(\mu_\theta(z_i)\)를 얻습니다.
5. 재구성 항(MSE 또는 BCE)과 KL 항(닫힌 형태)을 더한 \(-\mathcal{L}\)을 계산합니다.
6. 역전파로 \(\theta, \phi\)를 동시에 업데이트합니다.
파이썬 의사 코드입니다.
for x in dataloader:
mu, log_var = encoder(x) # q_φ(z|x)의 파라미터
eps = torch.randn_like(mu) # ε ~ N(0, I)
z = mu + torch.exp(0.5 * log_var) * eps # 재파라미터화
x_recon = decoder(z) # μ_θ(z)
recon_loss = F.mse_loss(x_recon, x, reduction='sum')
kl_loss = -0.5 * torch.sum(1 + log_var - mu.pow(2) - log_var.exp())
loss = recon_loss + kl_loss # = -ELBO
loss.backward()
optimizer.step()
분산을 직접 출력하지 않고 \(\log \sigma^2\)을 출력하는 것은 수치 안정성을 위한 표준 관행입니다. 분산은 항상 양수여야 하지만 \(\log \sigma^2\)은 실수 전체에서 자유롭게 학습할 수 있고, exp를 통해 양수로 복원됩니다.
생성 단계
학습 후 새 이미지 생성 절차는 다음과 같습니다.
1. 사전 분포에서 잠재 코드를 뽑습니다. \(z \sim \mathcal{N}(0, I)\).
2. 디코더에 통과시켜 이미지를 얻습니다. \(x = \mu_\theta(z)\).
생성 시에는 인코더가 사용되지 않습니다. 다양성은 \(z\)를 매번 다르게 뽑는 데서 발생합니다. 이론적으로는 디코더 출력에 추가 가우시안 노이즈를 더해야 정확한 샘플링이지만, 실제로는 평균 \(\mu_\theta(z)\)를 그대로 결과 이미지로 사용하는 경우가 대부분입니다. 추가 노이즈는 이미지를 흐릿하게 만들 뿐 다양성에 거의 기여하지 않습니다.
잠재공간의 매끄러움
샘플링이 일으키는 규제 효과
학습 중 인코더는 매번 다른 \(z\)를 뽑지만 디코더는 같은 \(x\)를 복원하도록 학습됩니다. 이 메커니즘이 VAE와 일반 오토인코더의 차이를 만듭니다.
학습이 반복되면 디코더는 \(\mu_\phi(x)\) 주변의 작은 영역 전체를 같은 \(x\)로 매핑하도록 학습됩니다. 이번 스텝에는 \(z_1\), 다음 스텝에는 \(z_2\)가 들어와도 모두 같은 \(x\)로 복원해야 하므로, 디코더는 그 영역에서 매끄럽게 작동하는 함수가 됩니다.
MNIST의 "7" 이미지가 인코더를 통과해 \(\mu_\phi = (1.2, -0.5), \sigma_\phi = (0.3, 0.4)\)가 나왔다고 가정합니다. 학습 도중 다음과 같은 \(z\) 값들이 번갈아 뽑힙니다.
\( z_1 = (1.1, -0.3), \quad z_2 = (1.4, -0.7), \quad z_3 = (1.3, -0.5), \ldots \)
디코더는 이 모든 점에서 "7"을 만들도록 학습되므로, 결과적으로 \((1.2, -0.5)\) 주변의 작은 영역이 "7과 비슷한 이미지들의 영역"으로 자리잡습니다. 다른 숫자는 잠재공간의 다른 영역에 자기 자리를 차지합니다.
일반 오토인코더는 \(z\)가 한 점이라 이런 영역 개념이 없습니다. 두 점 사이를 잇는 경로는 의미 없는 잠재공간을 지나가므로 보간 시 깨진 이미지가 나옵니다. VAE의 잠재공간이 매끄럽게 구조화되어 보간과 생성이 가능한 것은 샘플링이 일으키는 국소적 규제 효과 때문입니다.
두 항의 균형
VAE 학습은 재구성 항과 KL 항의 균형점에서 멈춥니다.
재구성 항: \(z\)에 \(x\) 정보를 정확히 담도록 한다. 극단적으로는 \(\sigma_\phi(x) \to 0\)이 되어 \(z\)가 결정적인 한 점이 되고 디코더는 정확한 매핑을 학습한다.
KL 항: \(q_\phi(z|x)\)가 사전 분포 \(\mathcal{N}(0, I)\)와 비슷해지도록 한다. 극단적으로는 \(\sigma_\phi(x) \to 1, \mu_\phi(x) \to 0\)이 되어 \(z\)에 \(x\) 정보가 전혀 담기지 않게 된다.
정상적으로 학습된 VAE는 \(\sigma_\phi\)가 적당히 작지만 0은 아닌 값에서, 디코더가 그 영역에서 매끄럽게 작동하는 지점에서 균형을 이룹니다.
Posterior Collapse
균형이 KL 쪽으로 무너지는 실패 모드를 Posterior Collapse 또는 KL Vanishing이라고 부릅니다. 디코더가 너무 강력하면 \(z\) 없이도 데이터 분포를 모델링할 수 있어 \(z\)를 무시하게 되고, KL 항이 \(q_\phi\)를 사전 분포로 끌고 가서 잠재변수가 의미를 잃습니다. 결과적으로 인코더-디코더의 연결이 끊어집니다.
PixelCNN, LSTM 같은 강력한 자기회귀 디코더를 결합할 때 특히 자주 발생합니다. 실전에서는 KL annealing(KL 가중치를 0에서 시작해 점진적으로 증가), Free Bits(KL을 임계값 아래로 떨어지지 않도록 제한), 디코더 표현력 제한 등으로 대응합니다. \(\beta\)-VAE는 KL 가중치 \(\beta\)를 조절해 disentanglement와 재구성 사이의 trade-off를 명시적으로 다루는 변형입니다.
정리
VAE의 논리 흐름은 다음과 같이 요약됩니다.
1. 데이터 분포 \(p(x)\)를 직접 모델링하기 어려우므로 잠재변수 \(z\)를 도입해 \(p(x) = \int p_\theta(x|z) p(z) dz\)로 분해한다.
2. 이 적분이 계산 불가능하므로 ELBO라는 하한을 만들어 대신 최대화한다.
3. ELBO는 재구성 항과 KL 정규화 항으로 분해되어 인코더와 디코더가 동시에 학습되는 손실 함수가 된다.
4. 학습 중 필요한 \(z\) 샘플링은 재파라미터화 트릭으로 그래디언트가 흐를 수 있게 만든다.
5. 샘플링이 일으키는 부수효과로 잠재공간이 매끄럽게 구조화되며, 이것이 일반 오토인코더와 구별되는 핵심 성질이다.
VAE는 한계도 있습니다. 가우시안 가정이 표현력을 제한해 GAN이나 Diffusion model 대비 생성 이미지가 흐릿한 경향이 있고, Posterior Collapse 같은 학습 안정성 문제도 존재합니다. 그럼에도 VAE의 프레임워크는 후속 연구에 깊은 영향을 미쳤으며, Normalizing Flow VAE, Hierarchical VAE, VQ-VAE 같은 확장 모델과 Diffusion model의 일부 수식 유도까지 VAE의 변분 추론 아이디어를 공유합니다.
인코더가 \(x\)를 잠재공간의 작은 영역으로 매핑하고, 디코더가 그 영역 전체를 다시 \(x\)로 복원하도록 학습하면서, 동시에 그 영역이 표준 가우시안에서 너무 멀어지지 않도록 제약한다.