−1과 +1 두 점이 반반인 데이터에 표준편차 σ = 2인 노이즈를 섞고, 트위디 공식이 알려 주는 평균 위치로 한 번에 뛰어 보면 대부분 두 점 사이 데이터가 없는 구간에 떨어진다. 노이즈가 클 때는 원래 점이 −1인지 +1인지 모르니 평균이 한가운데로 가기 때문이다. 노이즈를 조금 걷어 내고 그만큼만 움직이고, 다시 조금 걷어 내고 움직이는 여러 스텝이 필요하다. 그 스텝들은 노이즈를 쌓던 순방향 SDE를 시간을 거꾸로 돌린 것이어야 할 텐데, 순방향 SDE를 거꾸로 풀 수 있을까? 거꾸로 돌리려면 무엇이 더 있어야 할까?
역방향 SDE
1982년 브라이언 앤더슨(Brian Anderson)은 순방향 확산 SDE를 시간에 대해 되감는 역방향 SDE를 보였다. 시간 T(노이즈가 가장 큰 때)에서 0(데이터)으로 거슬러 가며 다음을 풀면, 매 순간의 분포가 순방향의 pt와 정확히 같다.
dt가 음수라는 것을 놓치면 안 된다. −g²∇log pt dt 는 실제로는 +g² × (스코어) × |dt|, 다시 말해 스코어 방향으로의 이동이다. 이동 폭 g²|dt|는 한 스텝에서 걷히는 노이즈 분산이고, 여기에 순방향과 같은 크기 g의 노이즈 항 g dW̄(바람)가 더해진다.
데이터가 −1 과 +1 두 점(반반)일 때 시간 축(가로, 왼쪽 t = 0 이 데이터, 오른쪽이 노이즈가 가장 큰 t = T)을 따라 그린 점들의 길. 위: 순방향 SDE 로 데이터에서 출발한 길이 비틀거리며 퍼진다. 가운데: 역방향 SDE 로 t = T 의 노이즈에서 출발한 길이 비틀거리며 두 점으로 돌아온다. 아래: 확률 플로우 ODE 의 길은 매끈하고, 같은 출발점이면 늘 같은 도착점에 닿는다
역방향 SDE의 노이즈 항(바람)
역방향 SDE의 샘플(참가자)은 스코어(레이더) 방향으로 걸으면서 노이즈 항 g dW̄(바람)에 비틀거린다. 이 노이즈 항을 그냥 없애 버리면 어떻게 될까.
스코어 항의 계수 g²는 그대로 두고 노이즈 항만 끄면, 모든 샘플이 필요 이상으로 끌려간다. 샘플들은 가운데 가까이 있는 봉우리 몇 개에 몰리고 각 봉우리 안에서도 한 점으로 뭉치는데, 바로 아래 위젯의 세 번째 단추(「SDE에서 노이즈 항만 끔」)가 그 결과다. 위젯에서는 일곱 봉우리 가운데 한가운데 봉우리에 51%가, 점과 스텝을 더 많이 쓴 이 절의 파이썬에서는 64%가 몰린다(참 비중은 12%).
직접 움직여 보기
불러오는 중…
그런데 노이즈 항을 끄면서 스코어 항의 계수를 g²에서 ½g²로 절반으로 줄이는 다른 방법이 있다.
dx=[f(x,t)−21g(t)2∇xlogpt(x)]dt
xfg(t)∇xlogpt샘플의위치순방향의표류항순방향의확산계수노이즈레벨t의스코어
확률 플로우 ODE(probability flow ODE. ODE는 상미분방정식, ordinary differential equation)다(송(Yang Song) 외, 2021). 무작위가 전혀 없는 결정론적 식인데도, 매 순간의 분포가 역방향 SDE와 똑같이 pt다. 노이즈 항이 하던 "퍼뜨리는 일"을 스코어 항 계수의 줄어든 절반이 대신 해 주기 때문이다. 포커-플랑크 방정식(점들의 분포가 시간에 따라 어떻게 흐르는지 적은 식)으로 보면 구조가 보인다. 노이즈 항이 밀도를 바꾸는 양 ½g²∇²pt는 ½g²∇·(pt ∇log pt)와 같은 식이다. 그러니 노이즈로 퍼지는 일은, 점들을 속도 −½g²∇log pt로, 다시 말해 밀도가 높은 곳에서 낮은 곳으로 미는 흐름과 분포에 똑같은 변화를 준다. 그래서 노이즈 항을 끄고 그 흐름을 대신 이동에 넣으면 분포는 바뀌지 않으며, 스코어 항의 계수 g²에서 퍼짐을 대신하는 ½g²을 빼고 나면 ½g²가 남는다. DDIM(denoising diffusion implicit model, 디노이징 디퓨전 암묵적 모델, 송(Jiaming Song) 외 2020)이라는 빠른 샘플러가 이 ODE를 시간을 잘게 끊어 푸는(이산화) 한 방식이다.
그러면 다양성은 어디서 오는가. ODE에서는 출발점이 도착점을 완전히 정하므로, 다양성은 출발점, 다시 말해 t = T 에서 넓게 흩어진 초기 노이즈에서 온다. 수천 개의 샘플이 서로 다른 곳에서 출발하니 서로 다른 봉우리에, 올바른 비율로 도착한다. 역방향 SDE의 노이즈 항은 다양성의 원천이 아니라, 같은 분포에 이르는 또 하나의 이동 방식이다.
“다양성은 초기 노이즈의 흩어짐에서 오고, 역방향 SDE의 노이즈 항은 그 위에 얹을 수 있는 선택이다.”
파이썬
import numpy as np
mu = np.array([[-2.5, -1.5], [1.5, -2.0], [-1.0, 2.0], [2.5, 1.5],
[0.0, 0.0], [-2.0, 0.5], [1.0, -0.5]])
w = np.array([.18, .14, .16, .14, .12, .13, .13]); s0 = 0.4
def score(x, var): # 노이즈를 더한 혼합의 스코어 (봉우리 분산 s0²+σ²)
d = mu[None] - x[:, None]
lg = np.log(w) - (d**2).sum(-1) / (2 * var)
g = np.exp(lg - lg.max(1, keepdims=True)); g /= g.sum(1, keepdims=True)
return (g[..., None] * d).sum(1) / var
def walk(rule, n=4000, N=500, smax=8.0, smin=0.01, seed=1):
r = np.random.default_rng(seed)
x = r.normal(size=(n, 2)) * np.sqrt(smax**2 + s0**2) # 출발: 노이즈가 가장 큰 σ_max 의 점
sig = np.geomspace(smax, smin, N + 1)
for i in range(N):
d = sig[i]**2 - sig[i + 1]**2 # 이번 스텝에 걷히는 노이즈 분산 (g² dt)
sc = score(x, s0**2 + sig[i]**2)
if rule == "SDE": x = x + d * sc + np.sqrt(d) * r.normal(size=x.shape)
if rule == "ODE": x = x + 0.5 * d * sc
if rule == "바람만 끔": x = x + d * sc
k = np.argmin(((x[:, None] - mu[None])**2).sum(-1), 1)
frac = np.bincount(k, minlength=7) / n
spread = np.sqrt(((x - mu[k])**2).sum(1).mean() / 2)
return frac, spread
print("참 비중 ", w)
for rule in ["SDE", "ODE", "바람만 끔"]:
f, sp = walk(rule)
print(f"{rule:8s}", f.round(2), f"퍼짐 {sp:.2f}", f"총변동 {0.5 * abs(f - w).sum():.3f}")
# 참 비중 [0.18 0.14 0.16 0.14 0.12 0.13 0.13]
# SDE [0.17 0.14 0.17 0.15 0.12 0.12 0.13] 퍼짐 0.39 총변동 0.017
# ODE [0.17 0.15 0.16 0.14 0.13 0.12 0.13] 퍼짐 0.39 총변동 0.019
# 바람만 끔 [0.01 0. 0.02 0. 0.64 0.13 0.2 ] 퍼짐 0.24 총변동 0.586
SDE와 ODE는 봉우리 비율도, 봉우리 안의 퍼짐(참값 0.4)도 맞추지만, 노이즈 항만 끈 역방향 SDE(「바람만 끔」)는 비율과 퍼짐을 둘 다 틀린다. 총변동은 두 비율 표의 차이 절댓값을 더해 반으로 나눈 값이고, 0이면 두 표가 똑같다.
이 절의 결론
“역방향 SDE에 필요한 새 재료는 스코어 하나다. 노이즈 항을 끄고 스코어 항의 계수를 절반으로 줄이면 결정론적인 확률 플로우 ODE가 되고, 그래도 매 순간의 분포는 같다. 다양성은 초기 노이즈에서 온다.”
문제 9. 노이즈 항이 없는 역방향 과정은 무너지는가
데이터 N(0, 1)에 표류 없이 노이즈를 쌓아 pt = N(0, 1 + t)가 되게 했다(f = 0, g² = 1). 확률 플로우 ODE를 t = 3에서 0까지 거꾸로 풀면, N(0, 4)에서 뽑은 출발점은 어떤 분포로 가는가?
시간 축 위의 확률 플로우 ODE 문제. t = 3에서 N(0, 4)로 흩어진 출발점들이 노이즈 항 없이 t = 0까지 거꾸로 간다. 도착 분포는 비워 두었다
함께 풀기
이서연
f = 0, g² = 1이고 데이터가 N(0, 1)이니까 스코어는 −x예요. dx/dt = −½ × (−x) = x/2라서, t = 3에서 0으로 오면 x(0) = x(3) × e−3/2이에요. 표준편차가 2 × 0.223 = 0.446, 분산 0.199예요. 데이터보다 훨씬 좁아요. 역시 노이즈 항이 없으면 쪼그라드나 봐요.
선생님
그 스코어는 몇 시의 분포 pt에서 구한 거예요?
이서연
아… 데이터 분포 p₀요. 문제 5(노이즈를 더한 정규분포)에서 한 실수를 또 했어요. 시각 t의 분포는 N(0, 1 + t)라서 스코어가 −x/(1 + t)예요.
선생님
민준 학생, 그 스코어로 확률 플로우 ODE를 써 봐요.
김민준
f = 0, g² = 1이니까 dx/dt = −½ ∇log pt(x) = x / (2(1 + t))예요. 풀면 x(t) ∝ √(1 + t)네요. t = 3에서 0으로 오면 x(0) = x(3) × √(1/4) = x(3)/2예요.
김민준
N(0, 4)를 반으로 줄이면 N(0, 1)이에요. 무너지지 않아요. 노이즈 없이도 정확히 데이터 분포로 가요.
선생님
랑주뱅에서 노이즈를 끈 것과 뭐가 달라요?
김민준
랑주뱅은 분포 p가 하나로 고정돼 있어서 노이즈를 끄면 모두 꼭대기로 가요. 확률 플로우 ODE는 따라가는 분포 pt가 매 순간 바뀌고, 스코어 항의 계수도 절반이에요. 출발점이 N(0, 4)로 흩어져 있으니까 그 흩어짐이 그대로 줄어들 뿐 사라지지 않아요.
김민준
발표 순서 정할 때 제비뽑기를 한 번 하고 나면 그 뒤는 정해진 규칙대로만 가도 되잖아요. 무작위는 처음 한 번이면 충분한 거예요. 제비뽑기가 초기 노이즈, 정해진 규칙이 ODE고요.
선생님
좋은 비유예요. "노이즈를 끄면 무너진다"는 고정된 분포 위의 랑주뱅에 대한 말이에요. 디퓨전의 역방향에는 노이즈 없는 길이 따로 있어요.
문제 10. 거꾸로 도는 OU (킬러)
표류가 있는 순방향 과정 가운데 가장 단순한 오른슈타인–울렌벡(OU, Ornstein–Uhlenbeck) 과정(원점 쪽으로 끌리면서 흔들리는 과정) dx = −x dt + √2 dW를 쓰고, 데이터는 x₀ ~ N(3, 0.5²)이다. (가) pt의 평균과 분산을 구하라. t = 5에서 pt는 무엇에 가까운가? (나) 역방향 SDE를 쓰고, 거꾸로 센 시간 τ(그리스 문자 타우) = T − t로 바꿔 시뮬레이션할 식을 적어라. (다) x5 ~ N(0, 1)에서 출발해 거꾸로 풀어, 데이터 분포가 복원되는지 확인하라.
OU 과정의 시간 축. t = 0의 데이터 N(3, 0.5²)이 순방향 dx = −x dt + √2 dW로 t = 5까지 가고, 역방향은 t = 5의 N(0, 1)에서 출발한다. 중간의 분포와 역방향 식은 비워 두었다
함께 풀기
이서연
(가)는 선형이라 쉬워요. 평균은 3e−t, 분산은 0.25e−2t + (1 − e−2t)예요. t = 5면 평균 0.020, 분산 0.99997이라 거의 N(0, 1)이에요.