지수족

브레그만 발산: 접선이 만드는 높이 차

앞 절에서, θ와 η를 서로 다른 분포에서 가져오면 펜헬–영 부등식의 두 변이 달라진다고 했다. 두 변의 차이 F(θ) + F*(η) − θ·η 는 볼록한 곡선과 접선 사이의 높이 차다. 한편 분포 사이의 차이를 재는 비대칭의 양으로 우리는 KL 발산을 알고 있는데, 두 변의 차이와 KL 발산은 혹시 같은 것 아닐까?

절벽 위의 판자: 왜 비대칭인가

볼록한 절벽 위 한 지점에 서서, 그 지점의 접선 기울기대로 곧은 판자를 쭉 뻗는다. 판자는 어디서나 실제 절벽보다 아래에 있다(볼록하니까). 판자를 댄 지점에서 판자와 절벽의 높이 차는 0이고 멀어질수록 커지는데, 이 "절벽과 판자 사이의 높이 차"가 브레그만 발산이다. 판자를 어디에 댔느냐에 따라 값이 달라서 비대칭이다.

베르누이의 로그정규화자 F(θ) = log(1 + eᶿ) 를 절벽으로 보고, θ′ = −1 에 판자(접선 기울기가 η′ = 0.269인 그 점의 접선)를 댔다. 판자는 어디서나 절벽 아래에 있고, θ = 2 에서 절벽과 판자의 높이 차는 1.01 이다. 이 높이 차가 브레그만 발산이다
베르누이의 로그정규화자 F(θ) = log(1 + eᶿ) 를 절벽으로 보고, θ′ = −1 에 판자(접선 기울기가 η′ = 0.269인 그 점의 접선)를 댔다. 판자는 어디서나 절벽 아래에 있고, θ = 2 에서 절벽과 판자의 높이 차는 1.01 이다. 이 높이 차가 브레그만 발산이다

이 높이 차를 계산 도구로 처음 쓴 사람은 소련의 수학자 레프 브레그만(Lev Bregman)이다. 1967년 그는 여러 볼록 집합이 함께 가진 점(제약 여러 개를 한꺼번에 만족하는 점)을 찾는 방법을 다뤘다. 이미 쓰이던 방법은 집합마다 돌아가며 가장 가까운 점으로 수선을 내려 옮겨 가는 것이었는데, 여기서 「가깝다」는 보통의 거리로만 쟀다. 브레그만은 가까움을 볼록함수 하나로 만든 이 높이 차로 재도 같은 방법이 통하도록 넓혔다. 대칭이 아니어서 거리라 부르기는 어렵지만, 번갈아 사영하는 데는 충분했다.

KL = 브레그만 발산

BF(θ:θ′)=F(θ)−F(θ′)−∇F(θ′)⋅(θ−θ′)\textcolor{#c2398a}{B_F}(\textcolor{#3b7de0}{\theta} : \textcolor{#3b7de0}{\theta}') = \textcolor{#7d8a3a}{F}(\textcolor{#3b7de0}{\theta}) - \textcolor{#7d8a3a}{F}(\textcolor{#3b7de0}{\theta}') - \nabla \textcolor{#7d8a3a}{F}(\textcolor{#3b7de0}{\theta}') \cdot (\textcolor{#3b7de0}{\theta} - \textcolor{#3b7de0}{\theta}')
BF브레그만 발산 (판자는 둘째 인수 θ′ 에 댄다)θ높이 차를 재는 점θ′판자(접선)를 댄 점F로그정규화자 (볼록함수)\begin{array}{ll} \textcolor{#c2398a}{B_F} & \text{브레그만 발산 (판자는 둘째 인수 } \theta' \text{ 에 댄다)} \\ \textcolor{#3b7de0}{\theta} & \text{높이 차를 재는 점} \\ \textcolor{#3b7de0}{\theta}' & \text{판자(접선)를 댄 점} \\ \textcolor{#7d8a3a}{F} & \text{로그정규화자 (볼록함수)} \end{array}

KL을 지수족 골격으로 풀면 이 모양이 그대로 나온다. log pθ₁ − log pθ₂ = (θ₁ − θ₂)·t(x) − F(θ₁) + F(θ₂) 이고(캐리어는 상쇄된다), pθ₁ 아래에서 평균 내면 t(x) 자리에 η₁이 들어간다.

KL(pθ1 ∥ pθ2)=F(θ2)−F(θ1)−η1⋅(θ2−θ1)=BF(θ2:θ1)=BF∗(η1:η2)\textcolor{#c2398a}{\mathrm{KL}}(\textcolor{#7f8f10}{p}_{\textcolor{#3b7de0}{\theta}_1} \,\|\, \textcolor{#7f8f10}{p}_{\textcolor{#3b7de0}{\theta}_2}) = \textcolor{#7d8a3a}{F}(\textcolor{#3b7de0}{\theta}_2) - \textcolor{#7d8a3a}{F}(\textcolor{#3b7de0}{\theta}_1) - \textcolor{#e0504a}{\eta}_1 \cdot (\textcolor{#3b7de0}{\theta}_2 - \textcolor{#3b7de0}{\theta}_1) = \textcolor{#c2398a}{B_F}(\textcolor{#3b7de0}{\theta}_2 : \textcolor{#3b7de0}{\theta}_1) = \textcolor{#c2398a}{B_{F^*}}(\textcolor{#e0504a}{\eta}_1 : \textcolor{#e0504a}{\eta}_2)
KLKL 발산pθ1, pθ2같은 가족의 두 분포θ1, θ2두 분포의 자연 파라미터η1, η2두 분포의 기댓값 파라미터, η1=∇F(θ1)F로그정규화자BF, BF∗F 와 F∗ 로 만든 브레그만 발산\begin{array}{ll} \textcolor{#c2398a}{\mathrm{KL}} & \text{KL 발산} \\ \textcolor{#7f8f10}{p}_{\textcolor{#3b7de0}{\theta}_1},\ \textcolor{#7f8f10}{p}_{\textcolor{#3b7de0}{\theta}_2} & \text{같은 가족의 두 분포} \\ \textcolor{#3b7de0}{\theta}_1,\ \textcolor{#3b7de0}{\theta}_2 & \text{두 분포의 자연 파라미터} \\ \textcolor{#e0504a}{\eta}_1,\ \textcolor{#e0504a}{\eta}_2 & \text{두 분포의 기댓값 파라미터, } \eta_1 = \nabla F(\theta_1) \\ \textcolor{#7d8a3a}{F} & \text{로그정규화자} \\ \textcolor{#c2398a}{B_F},\ \textcolor{#c2398a}{B_{F^*}} & F \text{ 와 } F^* \text{ 로 만든 브레그만 발산} \end{array}

KL 발산의 두 인수 순서에 주의하라. KL(pθ₁ ‖ pθ₂) 에서 판자는 앞의 분포 θ₁ 에 대고, 높이 차는 뒤의 θ₂ 에서 잰다. θ 좌표로는 BF(θ₂ : θ₁)로 순서가 뒤집히지만, η 좌표로 쓰면 BF*(η₁ : η₂)로 순서가 바뀌지 않는다. 헷갈리면 숫자로 확인한다: θ₁ = 0.5, θ₂ = −1 인 두 베르누이에서 KL(p₁‖p₂) = 0.2729, KL(p₂‖p₁) = 0.2574 이다. BF(θ₂ : θ₁) = 0.2729, BF(θ₁ : θ₂) = 0.2574. 순서를 거꾸로 쓰면 다른 방향의 KL이 나온다.

직접 움직여 보기

불러오는 중…

ML에서: 고정된 판자와 움직이는 모델

학습은 크로스 엔트로피를 줄이는 과정이고, 크로스 엔트로피를 줄이는 것은 KL(현실 ‖ 모델)을 줄이는 것과 같다. 현실의 분포가 가족의 한 명 pθ* 이고 모델이 qθ 라면, 판자는 현실의 θ* 에 고정되어 있다. 학습은 모델의 θ를 옮겨, 그 고정된 판자와 곡선 사이의 높이 차 BF(θ : θ*) 를 줄여 가는 일이다.

파이썬

import numpy as np

F = lambda t: np.log1p(np.exp(t))                  # 베르누이의 로그정규화자
dF = lambda t: 1 / (1 + np.exp(-t))                # η = 시그모이드(θ)
B = lambda a, b: F(a) - F(b) - dF(b) * (a - b)     # B_F(a : b), 판자는 b 에
kl = lambda p, q: p * np.log(p / q) + (1 - p) * np.log((1 - p) / (1 - q))
Fs = lambda e: e * np.log(e) + (1 - e) * np.log(1 - e)
BFs = lambda e1, e2: Fs(e1) - Fs(e2) - np.log(e2 / (1 - e2)) * (e1 - e2)   # ∇F*(η) = θ

t1, t2 = 0.5, -1.0
p1, p2 = dF(t1), dF(t2)
print(f"KL(p1‖p2) = {kl(p1, p2):.4f}   B_F(θ2:θ1) = {B(t2, t1):.4f}   B_F*(η1:η2) = {BFs(p1, p2):.4f}")
print(f"KL(p2‖p1) = {kl(p2, p1):.4f}   B_F(θ1:θ2) = {B(t1, t2):.4f}")

for t in [0.0, 5.0]:
    print(f"θ = {t}: θ 를 0.1 옮긴 KL = {kl(dF(t), dF(t + 0.1)):.3e}   F''(θ) = {dF(t) * (1 - dF(t)):.4f}")
# KL(p1‖p2) = 0.2729   B_F(θ2:θ1) = 0.2729   B_F*(η1:η2) = 0.2729
# KL(p2‖p1) = 0.2574   B_F(θ1:θ2) = 0.2574
# θ = 0.0: θ 를 0.1 옮긴 KL = 1.249e-03   F''(θ) = 0.2500
# θ = 5.0: θ 를 0.1 옮긴 KL = 3.217e-05   F''(θ) = 0.0066

θ의 한 칸은 곳곳에서 크기가 다르다

θ를 0.1만큼 바꾸는 것이 어디서나 같은 크기의 변화를 만드는가? 방금 파이썬 출력이 답한다. 베르누이에서 θ = 0 에서 θ를 0.1 옮기면 KL이 1.25 × 10⁻³ 인데, θ = 5 에서 같은 0.1을 옮기면 3.2 × 10⁻⁵ 로, 약 39배 차이가 난다. F를 두 번 미분한 값 F″(θ)가 곳곳에서 다르기 때문인데, 그렇다면 θ 좌표의 한 칸은 곳곳에서 다른 크기의 변화다.

이 절의 결론

“KL 발산은 '로그정규화자와 그 접선 사이의 높이 차’였다. KL 발산의 비대칭, 볼록함수의 접선과 르장드르 변환, 지수족의 θ 좌표, 이 세 가지가 여기서 하나로 합류한다.”

문제 14. 오늘의 속도로 10년 뒤를 내다보면

연 5% 복리 적금에 1,000만 원을 넣었을 때 n년 뒤 잔고는 1000 × 1.05ⁿ 만 원이고, 이 곡선은 볼록하다. (가) 지금 잔고가 늘어나는 속도(한 해에 약 48.8만 원)로 곧게 10년을 늘여 내다보면 실제 잔고보다 얼마나 모자라는가? (나) 거꾸로, 10년 뒤 잔고가 늘어나는 속도로 곧게 지금까지 되짚어 계산하면 실제 1,000만 원보다 얼마나 모자라는가? 두 값은 같은가?

연 5% 복리 잔고 1000 × 1.05ⁿ 만 원의 곡선과, 곧게 늘여 볼 두 자리(지금과 10년 뒤)(sources/07-지수족/problems_figs.py)
연 5% 복리 잔고 1000 × 1.05ⁿ 만 원의 곡선과, 곧게 늘여 볼 두 자리(지금과 10년 뒤)(sources/07-지수족/problems_figs.py)

함께 풀기

김민준 M01
김민준

(가)는 1000 + 48.8 × 10 = 1488만 원, 실제는 1628.9만 원이라 141만 원 모자라요. (나)도 같은 10년이니까 똑같이 141만 원 모자라겠죠.

선생님 T01
선생님

10년 뒤에는 한 해에 얼마씩 늘고 있어요?

김민준 M04
김민준

1628.9 × 0.0488 = 79.5만 원이요. 그 속도로 10년을 되짚으면 1628.9 − 795 = 834만 원이라 166만 원 모자라요. 141이 아니네요.

이서연 S01
이서연

곡선이 뒤로 갈수록 가팔라지니까, 가파른 쪽에서 그은 접선이 더 크게 빗나가. 곡선이 볼록하니까 어느 쪽에 긋든 접선은 곡선 아래에 있어서 모자라기만 하고.

선생님 T01
선생님

위의 판자 이야기로 말하면요?

이서연 S01
이서연

판자를 지금에 대고 10년 뒤에서 높이 차를 잰 게 (가), 판자를 10년 뒤에 대고 지금에서 잰 게 (나)예요. 같은 두 점인데 141 대 166. 판자를 어디에 대느냐에 따라 값이 다른 비대칭이 이거예요.

문제 15. 푸아송에서 판자는 어디에 대나 (킬러)

(가) 지수족에서 KL(pθ₁ ‖ pθ₂) = BF*(η₁ : η₂) 를 증명하라. KL = BF(θ₂ : θ₁) 은 위에서 보인 것을 써도 된다. (나) λ₁ = 2, λ₂ = 5 인 두 푸아송에서 KL의 두 방향, BF(θ₂ : θ₁), BF*(η₁ : η₂)를 수치로 구해 맞춰 보라. 푸아송은 F(θ) = eᶿ, η = λ 다.

푸아송의 로그정규화자 F(θ) = eᶿ 와 두 점 θ₁ = log 2(λ₁ = 2), θ₂ = log 5(λ₂ = 5)(sources/07-지수족/problems_figs.py)
푸아송의 로그정규화자 F(θ) = eᶿ 와 두 점 θ₁ = log 2(λ₁ = 2), θ₂ = log 5(λ₂ = 5)(sources/07-지수족/problems_figs.py)

함께 풀기

김민준 M05
김민준

수치부터 했어요. KL(p₁‖p₂) = 2 log(2/5) + 5 − 2 = 1.167, 반대 방향은 1.581 이에요. BF(θ₂ : θ₁) = exp(θ₂) − exp(θ₁) − exp(θ₁)(θ₂ − θ₁) = 5 − 2 − 2 log 2.5 = 1.167. 여기까진 맞아요. 그런데 BF*(η₁ : η₂)는 0.186 이 나와요. 1.167 과 여섯 배 넘게 차이 나요. 수치 오차일까요?

선생님 T01
선생님

그 코드는 몇 자리까지 정확해요?

김민준 M01
김민준

로그랑 지수 몇 번이니까 10⁻¹⁵ 쯤이요. 여섯 배는… 수치 오차가 아니에요. 식이 틀렸어요.

선생님 T01
선생님

F*는 어디서 가져왔어요?

김민준 M01
김민준

F*는 음의 엔트로피라고 했으니까, 푸아송 확률로 −H를 x = 0부터 199까지 직접 더해 만들었어요.

이서연 S06
이서연

잠깐, 음의 엔트로피는 캐리어가 0일 때 얘기 아니었어? 푸아송은 캐리어 −log x! 가 있잖아. 그럼 F*(η) = −H − E[k(x)] 일 거야.

선생님 T01
선생님

캐리어 항까지 더하기가 번거로우면, F*를 확실하게 얻는 다른 길은요?

이서연 S01
이서연

정의에서요. F(θ) = eᶿ 를 손으로 르장드르 변환하면… η log η − η 예요. 민준아, 그걸로 해 봐.

김민준 M01
김민준

(2 log 2 − 2) − (5 log 5 − 5) − log 5 × (2 − 5) = 1.167. 세 개가 같아요. −H로 만든 함수에는 E[log x!] 라는 굽은 항이 더 섞여서, 판자와의 높이 차가 달라졌던 거예요.

선생님 T01
선생님

서연 학생, 증명은요?

이서연 S01
이서연

첫 번째 등호는 위에서 본 대로 판자가 θ₁에 있는 BF(θ₂ : θ₁)이에요.

이서연 S05
이서연

두 번째가 막혀요. BF*(η₁ : η₂) = F*(η₁) − F*(η₂) − ∇F*(η₂)·(η₁ − η₂) 인데, ∇F*(η₂) 를 뭘로 바꿔야 할지 모르겠어요. F* 는 엔트로피에 캐리어 항을 더한 거니까 그걸 η로 미분해야 하나요?

선생님 T01
선생님

앞 절에서 르장드르 짝의 그래디언트 역함수가 무엇이라고 했죠?

이서연 S01
이서연

(F′)⁻¹ = (F*)′ … θ 에서 F 의 그래디언트가 η 면, η 에서 F* 의 그래디언트는 θ 예요.

이서연 S09
이서연

그러면 ∇F*(η₂) = θ₂ 예요. 엔트로피를 미분할 필요가 없었어요.

선생님 T01
선생님

남은 F*(η₁), F*(η₂) 는요?

이서연 S01
이서연

르장드르 변환의 정의로 바꿔 볼게요. F*(η) = θ·η − F(θ) 도 넣으면 θ₁·η₁ − F(θ₁) − θ₂·η₂ + F(θ₂) − θ₂·(η₁ − η₂) = F(θ₂) − F(θ₁) − η₁·(θ₂ − θ₁). 첫 번째 줄이랑 똑같아요.

김민준 M01
김민준

근데 판자 대는 자리가 바뀌었네?

이서연 S01
이서연

응. θ 좌표에서는 판자를 θ₁ 에 대고 θ₂ 에서 재는데, η 좌표에서는 판자를 η₂ 에 대고 η₁ 에서 재. 좌표를 바꾸면 판자를 대는 인수와 높이 차를 재는 인수가 뒤집혀.

선생님 T13
선생님

이 장에서 가져갈 건 이거예요. KL 은 로그정규화자의 접선 높이 차이고, θ 로 쓰면 순서가 뒤집히고 η 로 쓰면 순서가 안 바뀌어요. 그 사이를 잇는 게 르장드르 짝의 성질 하나, 그래디언트의 역함수는 쌍대의 그래디언트라는 사실이었어요.

이서연 S01
이서연

선형대수에서 전치행렬로 옮기면 곱의 순서가 뒤집히던 것 같아요. (AB)ᵀ = BᵀAᵀ. 쌍대로 건너가면 순서가 뒤집히는 게 규칙처럼 느껴져요.

문제 16. 확신한 예제는 왜 잘 움직이지 않나

로짓 하나로 앞면 확률을 내는 이진 분류 모델이 있다. 위 파이썬 출력에서 로짓을 0.1 옮기면 로짓 0 근처에서는 KL이 1.25 × 10⁻³, 로짓 5 근처에서는 3.2 × 10⁻⁵ 로, 약 39배 차이가 났다. (가) 로짓 5 에서 KL 1.25 × 10⁻³ 을 만들려면 로짓을 얼마나 옮겨야 하는가? (나) 그때 앞면 확률은 얼마나 바뀌는가? 로짓 0 에서 0.1 옮길 때와 견줘라.

로짓 θ와 앞면 확률을 잇는 시그모이드 곡선. 로짓 0에서 0.1 옮긴 구간과, 물음의 자리인 로짓 5(sources/07-지수족/problems_figs.py)
로짓 θ와 앞면 확률을 잇는 시그모이드 곡선. 로짓 0에서 0.1 옮긴 구간과, 물음의 자리인 로짓 5(sources/07-지수족/problems_figs.py)

함께 풀기

김민준 M01
김민준

39배 차이니까 0.1 × 39 = 3.9 만큼 옮기면 돼요.

선생님 T01
선생님

로짓을 조금 옮길 때 KL은 옮긴 양의 몇 제곱에 비례하죠?

김민준 M08
김민준

브레그만 발산은 곡선과 판자의 높이 차니까… 작은 변화 δ(델타)에서는 ½ F″ δ², 제곱이에요. 그럼 39배를 채우는 변화는 √39 ≈ 6.2배, 0.1 × 6.2 = 0.62 쯤이요.

이서연 S01
이서연

그건 작은 변화에서 쓰는 근사잖아. 0.62 도 작은 걸까?

김민준 M01
김민준

그럼 근사 없이 풀어 볼게. 로짓을 올릴 때 0.682, 내릴 때 0.557 이야.

이서연 S01
이서연

방향마다 다르네. 곡선이 한쪽으로 기울어 있어서 그런가 봐. 제곱으로 근사한 0.62 는 그 사이고.

선생님 T01
선생님

(나)는요?

김민준 M01
김민준

로짓 0 에서 0.1 옮기면 확률이 0.500 에서 0.525 로 0.025 바뀌어요. 로짓 5 에서 0.682 옮기면 0.9933 에서 0.9966 으로 0.0033 바뀌고요. KL은 같은데 확률 변화는 일곱 분의 일도 안 돼요.

이서연 S08
이서연

확률이 1 에 붙어 있을수록 작은 변화도 KL로는 크게 쳐지는 거네요. 거꾸로 말하면, 모델이 이미 0.993 으로 확신한 예제는 같은 크기의 로짓 업데이트로는 분포가 거의 안 움직여요.

선생님 T01
선생님

그래요. θ 좌표의 한 칸이 곳곳에서 다른 크기라서, 학습률 하나로는 모든 곳의 스텝을 고르게 맞출 수 없어요. 곳마다 변화를 재는 기준을 달리 대야 하지 않을까 하는 물음이 여기서 남아요.