숫자 2개(x, y)짜리 데이터를 숫자 1개(z)로 압축했다가 다시 되살려요 — 정보를 가장 덜 잃는 압축 방향을 AI가 스스로 찾아내는 걸 지켜보세요.
● 청록 점 = 원본 데이터 · — 파란 직선 = 잠재 축 (z가 사는 곳) · ● 파란 작은 점 = 복원된 점 x̂ · ┈ 빨간 점선 = 압축하면서 잃어버린 정보 · ✚ = 데이터 중심 m · ⭐ = z로 새로 만든 점. 빨간 점선이 전부 짧아지는 축의 방향을 찾는 게 목표예요.
복원 오차는 빨간 점선 길이 제곱의 평균이에요. 보존된 분산은 데이터의 퍼짐 중 축 방향으로 살아남은 비율 — 오차가 줄면 이 값이 100%에 가까워져요.
디코딩 결과: x̂ = (5.00, 5.00) — 잠재 공간의 숫자 하나로 새 데이터를 만들어냈어요!
import torch
import torch.nn as nn
# 인코더: 784차원(28×28 이미지)을 32차원 잠재 벡터로 압축
encoder = nn.Sequential(
nn.Linear(784, 128), nn.ReLU(),
nn.Linear(128, 32), # z: 숫자 32개
)
# 디코더: 32차원 z를 다시 784차원 이미지로 복원
decoder = nn.Sequential(
nn.Linear(32, 128), nn.ReLU(),
nn.Linear(128, 784), nn.Sigmoid(),
)
params = list(encoder.parameters()) + list(decoder.parameters())
optimizer = torch.optim.Adam(params, lr=1e-3)
loss_fn = nn.MSELoss() # 손실 = 원본과 복원본의 차이
for epoch in range(10):
for x, _ in train_loader: # 라벨은 안 써요 (비지도 학습!)
x = x.view(-1, 784)
z = encoder(x) # 압축
x_hat = decoder(z) # 복원
loss = loss_fn(x_hat, x) # 원본과 얼마나 같아졌나?
optimizer.zero_grad()
loss.backward()
optimizer.step()