비선형 인코더는 PCA의 평평한 부분공간이 설명하기 어려운 휘어진 데이터를 압축할 수 있다. 그렇다고 우리가 원하는 개념을 저절로 찾아 주지는 않는다. 이번 강의는 같은 관측값에 PCA, 오토인코더(autoencoder), 변분 오토인코더(VAE)를 학습시켜 두 사실을 함께 확인한다.

2D 평면에서 점들이 구부러진 띠 위에 있다고 하자. 직선 하나에 투영하면 띠를 따라 멀리 떨어진 두 구간이 겹칠 수 있다. 비선형 인코더는 굽은 띠를 따라 좌표를 부여하고, 디코더는 그 좌표를 다시 띠 위의 관측으로 바꿀 수 있다. 개선의 이유는 함수의 모양이 유연해졌기 때문이다. 생물학이나 이야기의 의미를 자동으로 이해했기 때문은 아니다.

준비와 90분 구성

PCA의 복원과 연쇄법칙을 복습하고, 신경망 층과 경사 하강법의 역할을 알고 오자. 휘어진 예제 15분, 오토인코더 20분, VAE의 확률 25분, 실습 20분, 표현 진단 10분으로 진행한다. 제출물은 복원 성능과 의미 해석을 별도로 적은 비교표다.

공통 환경과 실습 묶음을 준비한다. lesson03.py에 CPU로 실행하는 두 PyTorch 모델이 모두 들어 있다. 모델 가중치나 데이터는 다운로드하지 않는다.

두 방향의 함수를 함께 학습한다

인코더는 $z=f_\phi(x)$를 만들고 디코더는 $\hat x=g_\theta(z)$를 복원한다. 이번 모델은 24개 관측 좌표를 두 숫자로 줄였다가 다시 24개로 되돌린다.

$$ x\xrightarrow{f_\phi}z\xrightarrow{g_\theta}\hat x, \qquad \min_{\phi,\theta}\frac1n\sum_i\|x_i-g_\theta(f_\phi(x_i))\|_2^2. $$

실습의 인코더와 디코더에는 각각 유닛 32개의 은닉층과 Tanh가 있다. 디코더 마지막 출력은 선형이다. 표준화한 특징은 음수가 될 수 있으므로, 출력을 $[0,1]$로 제한하는 sigmoid는 이 데이터에 맞지 않는다. 이미지 예제에서 본 활성함수를 그대로 가져오기보다 관측값의 범위와 손실을 맞춰야 한다.

적절한 용량의 선형 오토인코더가 제곱 오차의 최적점에 도달하면 PCA 부분공간을 나타낼 수 있다. 다만 잠재 축 자체가 PCA 축과 일치할 필요는 없다. 비선형성은 가능한 복원의 범위를 넓히면서 초기값 의존성, 과적합, 최적화 선택도 함께 가져온다. Hinton과 Salakhutdinov의 원래 연구 자료는 역사적 출발점을 제공한다. 여기의 작은 모델은 그 학습 절차를 재현하는 모델이 아니라 원리를 보는 실습이다.

복원에 도움이 되는 정보가 관심 있는 상태와 같다고 보장되지는 않는다. 발화자 정체성이 복원을 쉽게 한다면 모델은 이야기 진행보다 정체성을 우선할 수 있다. 복원 목적식은 우리가 해석 가능성이나 인과적 상태를 원한다는 사실을 알지 못한다.

VAE는 하나의 코드 대신 분포를 만든다

잡음 섞인 한 관측을 여러 상태가 설명할 수 있다고 하자. VAE 인코더는 점 하나 대신 다음과 같은 분포를 출력한다.

$$ q_\phi(z\mid x)=\mathcal N\!\left(\mu_\phi(x), \operatorname{diag}(\sigma_\phi^2(x))\right). $$

사전분포는 $p(z)=\mathcal N(0,I)$, 관측 모델은 $p_\theta(x\mid z)$로 둔다. 실습의 관측 모델은 디코더 출력을 평균으로 하고 표준편차 $s=0.3$을 고정한 가우시안이다. 단위는 표준화한 특징의 단위다. 네트워크의 logvar는 잠재 분포의 분산 로그다. 관측 잡음 $s$와 같은 변수가 아니다.

VAE가 최대화하는 증거 하한(ELBO)은 다음과 같다.

$$ \mathcal L(x)=\mathbb E_{q_\phi(z\mid x)}[\log p_\theta(x\mid z)] -D_{\mathrm{KL}}\!\left(q_\phi(z\mid x)\|p(z)\right) \leq\log p_\theta(x). $$

첫 항은 관측을 잘 설명하도록 유도한다. 둘째 항은 인코더 분포가 사전분포에서 벗어나는 데 비용을 준다. KL 발산은 “복잡한 그림”에 임의로 벌점을 주는 수가 아니라 두 분포를 비교하는 양이다.

왜 하한인지도 짧게 확인할 수 있다.

$$ \log p_\theta(x)=\mathcal L(x)+D_{\mathrm{KL}}(q_\phi(z\mid x)\|p_\theta(z\mid x)). $$

뒤의 KL은 음수가 아니므로 ELBO는 로그 우도보다 작거나 같다. 차이는 근사 사후분포와 모델의 사후분포가 얼마나 다른지다. Kingma와 Welling의 원 논문이 이 목적식과 학습 방법을 제시한다.

대각 가우시안과 표준정규 사전분포의 KL은 직접 계산된다.

$$ D_{\mathrm{KL}}=\frac12\sum_j \left(\mu_j^2+\exp(\ell_j)-1-\ell_j\right),\qquad\ell_j=\log\sigma_j^2. $$

$\mu=0$, $\ell=0$을 넣어 보자. 인코더 분포와 사전분포가 같으므로 KL이 0이다. 학습 전에도 할 수 있는 간단한 수학 검산이다.

무작위 샘플을 거쳐도 미분하려면

$\epsilon\sim\mathcal N(0,I)$를 뽑고 다음처럼 쓴다.

$$ z=\mu+\exp(\ell/2)\odot\epsilon. $$

무작위성은 $\epsilon$에 두고, 네트워크 출력에서 샘플까지는 미분 가능한 연산으로 연결한다. 이것이 재매개변수화(reparameterization)다. 전체 코드는 학습할 때 이 샘플을 디코더에 넣는다. 매 관측의 최소화 목적은 매개변수와 무관한 상수를 빼면

$$ \frac{\|x-\hat x\|^2}{2s^2}+D_{\mathrm{KL}} $$

이다. 특징 방향으로 합한 뒤 관측 방향으로 평균한다는 점을 확인하자. 한 항만 특징 평균을 내고 다른 항은 합하면 두 항의 상대적 가중치가 달라진다. 실습은 관측 잡음을 고정한 일반 ELBO를 사용한다. 별도 설명 없이 KL 가중치를 바꾸는 beta-VAE가 아니다. 물론 $s$의 선택 자체가 복원과 사전분포 사이의 균형에 영향을 준다.

세 모델을 실행하고 읽는다

압축을 푼 디렉터리에서 다음 코드를 실행한다.

from common import make_dataset
from lesson03 import train_models

data = make_dataset()
embeddings, metrics = train_models(data, epochs=300)
for name, value in metrics.items():
    print(name, value)

그림은 python lesson03.py --output outputs로 저장한다. 전체 파일에는 두 모델 정의, 정확한 손실, 고정 시드, 학습 세션만 사용하는 표준화가 들어 있다. 평가 세션은 가중치와 전처리를 바꾸지 않는다. 전체 학습 데이터를 한 번에 사용하는 작은 반복문으로 연산을 쉽게 읽게 했다. 실제 학습에서는 미니배치와 검증 기반 종료를 많이 사용한다.

PCA, 오토인코더, VAE 사후평균이 만든 평가 세션 좌표.

세 그림 모두 평가 관측을 기록 시간으로 색칠했다. 시간과 z_true는 학습 입력이 아니다. VAE 그림은 사후평균을 표시한다. 코드의 vae_mean_decode_test_mse도 $\mu(x)$를 디코더에 넣은 복원 오차다. ELBO에 들어가는 샘플 기반 기대 복원 오차와 같은 수치가 아니다. 이를 같다고 보고하면 불확실성의 의미가 흐려진다.

MSE가 작은 것은 하나의 결과이며 상태 표현의 최종 순위가 아니다. 가까운 시퀀스 단계가 가까이 남는지, 새로운 세션의 분기 정보를 읽어 낼 수 있는지, 관심 없는 메타데이터가 표현을 지배하는지 별도로 점검한다. 평가 결과를 보며 구조를 계속 고쳤다면 최종 보고에는 새로 숨겨 둔 평가 집합이 필요하다.

바이오와 캐릭터 대화에 적용하기

유전자 카운트에는 가우시안 제곱 오차가 맞지 않을 수 있다. 카운트에 맞는 우도와 라이브러리 크기 처리 등이 중요하다. 이번 합성 데이터가 연속값인 이유는 관측 모델을 단순하게 맞추기 위해서다. 잠재 그림이 예쁘다는 것만으로 세포 정체성과 발달 순서가 검증되지는 않는다.

대화에서는 사전학습 임베딩을 복원한다면 그 임베딩이 이미 담은 정보를 보존하는 것이다. 문맥 창에서 빠진 사건은 복원 목적만으로 되살릴 수 없다. 미래 턴이나 결과 예측으로 표현을 평가하되, 예측 시점에 이용 가능한 정보만 사용하고 사용자와 캐릭터가 달라질 때도 점검한다.

잠재 샘플링은 이야기 불확실성이 보정되었다는 뜻도 아니다. 분포가 달라지면 VAE도 틀릴 수 있고, 매끈한 사전분포가 모든 중간 상태의 의미를 보장하지 않는다. 추가 가정 없이 비지도 축을 의미 요인으로 유일하게 정하기 어렵다는 점은 Locatello 등의 연구와 연결된다.

연습과 해설

  1. 병목을 없애 보자. 잠재 차원을 24로 늘리면 학습 MSE가 낮아져도 상태 발견이 좋아졌다고 할 수 없는 이유는? 해설: 관측과 잡음을 그대로 복사할 공간이 늘어났다. 복원뿐 아니라 새로운 세션에서의 후속 과제를 점검해야 한다.
  2. KL을 손으로 구하라. 한 좌표에서 $\mu=1$, $\sigma^2=1$일 때 표준정규분포까지의 KL은? 정답: $1/2$다. $\mu=0$, $\sigma^2=1$이면 0이다.
  3. 관측 잡음을 바꿔라. 검증 집합에서 $s=0.15$와 $s=0.6$을 비교한다. 힌트: 작은 $s$는 복원 오차에 더 큰 가중치를 준다. MSE와 KL을 함께 적되 어느 하나도 의미적 유용성 자체는 아니라는 점을 설명한다.

다음 강의에서는 각 관측을 복원하는 대신 휘어진 공간의 이웃 관계를 보존하는 문제로 이동한다.