4. Actor-Critic — 비평가를 곁에 두다

GAE: 둘 사이를 λ로 잇는다

MC는 치우침이 없는 대신 분산이 크고, TD는 분산이 작은 대신 비평가가 틀린 만큼 치우친다. 학습은 응답마다, 토큰마다 이 추정을 되풀이하므로 어느 쪽 오류를 받아들일지는 매번 따라오는 선택이다. 둘 중 하나만 골라야 할까? 가까운 미래는 실제 결과를 보고 먼 미래만 비평가에 맡기는 중간은 없을까?

역사: 버클리의 절충

이 중간을 손잡이 하나로 만든 것이 UC 버클리의 존 슐먼(John Schulman)과 동료들(모리츠 Philipp Moritz, 레빈 Sergey Levine, 조던 Michael Jordan, 아빌 Pieter Abbeel)이 2016년 ICLR에 발표한 GAE다. 그들이 겨냥한 것은 시뮬레이션 속 로봇이었다. 두 다리·네 다리 로봇이 관절에 주는 힘만으로 달리게 하고, 누운 자세에서 일어서게 하는 일이다. 정책 그래디언트로 이런 일을 배우려면 샘플이 너무 많이 든다는 것이 큰 걸림돌이었고, 그들은 가치함수로 분산을 크게 줄이는 대신 치우침을 조금 받아들이는 쪽을 골랐다. 두 다리 로봇이 달리기를 배우는 데 든 시뮬레이션 경험은 실제 시간으로 1~2주 분량이었다. 같은 슐먼이 이듬해 내놓은 PPO(비평가를 쓰는 정책 그래디언트의 대표 방법)와 짝을 이루며, GAE는 언어모델 RLHF의 기본 부품이 됐다.

λ로 더하는 TD 오차

GAE(Generalized Advantage Estimation)는 두 극단 사이를 연속적으로 잇는다. TD 오차를 앞으로 쭉 더하되, 멀어질수록 λ\textcolor{#993600}{\lambda}(람다)배씩 줄인다.

A^tGAE(γ,λ)=∑l=0T−t−1(γλ)l δt+l(재귀로: A^t=δt+γλ A^t+1)\textcolor{#8e44ad}{\hat A_t^{\text{GAE}(\gamma, \lambda)}} = \sum_{l=0}^{\textcolor{#915a08}{T}-t-1} (\textcolor{#536020}{\gamma}\textcolor{#993600}{\lambda})^l\, \textcolor{#8e44ad}{\delta_{t+l}} \qquad \Big(\text{재귀로: } \textcolor{#8e44ad}{\hat A_t} = \textcolor{#8e44ad}{\delta_t} + \textcolor{#536020}{\gamma}\textcolor{#993600}{\lambda}\, \textcolor{#8e44ad}{\hat A_{t+1}}\Big)
A^tGAE 어드밴티지δt+ll걸음 뒤의 TD 오차λ0이면 TD(비평가를 믿음), 1이면 몬테카를로(결과를 기다림)γ할인율 \small\begin{array}{ll} \textcolor{#8e44ad}{\hat A_t} & \text{GAE 어드밴티지} \\ \textcolor{#8e44ad}{\delta_{t+l}} & \text{}l\text{걸음 뒤의 TD 오차} \\ \textcolor{#993600}{\lambda} & \text{0이면 TD(비평가를 믿음), 1이면 몬테카를로(결과를 기다림)} \\ \textcolor{#536020}{\gamma} & \text{할인율} \end{array}

중간의 λ\textcolor{#993600}{\lambda}는 "가까운 미래는 실제 결과를 보고, 먼 미래는 비평가를 믿는다"는 절충이다.

l걸음 뒤의 TD 오차에 곱하는 무게 (γ = 1) λ = 0 TD: 바로 다음 오차만 λ = 0.5 λ = 0.9 λ = 1 몬테카를로: 끝까지 똑같이 0 1 2 3 4 5 6 7 8 9 l : 몇 걸음 뒤의 TD 오차인가

위젯에서 해볼 것:

ML에서: 언어모델의 기본값

GAE를 처음 내놓은 논문도 λ\textcolor{#993600}{\lambda} 를 0부터 1까지 바꿔 가며 수레 위 막대 세우기를 배우게 해 보았다. 가장 빨리 배운 것은 양 끝이 아니라 0.92~0.98 사이였다. 언어모델 RLHF의 흔한 기본값도 γ=1\textcolor{#536020}{\gamma} = 1, λ=0.95\textcolor{#993600}{\lambda} = 0.95다. 보상이 응답 끝에 한 번만 오므로 할인할 이유가 없고, λ\textcolor{#993600}{\lambda} 는 1 쪽에 두어 학습 초기의 부정확한 비평가에 덜 기댄다. 비평가를 학습할 때의 목표값도 보통 이 GAE 어드밴티지에 가치를 더한 G^t=A^t+Vϕ(st)\textcolor{#0033ff}{\hat G_t} = \textcolor{#8e44ad}{\hat A_t} + \textcolor{#00897b}{V_\phi}(\textcolor{#0093b8}{s_t})(λ\textcolor{#993600}{\lambda}-리턴: GAE로 섞어 만든 '앞으로 받을 점수’의 추정)를 쓴다. 비평가를 학습하는 제곱 손실 ∑t(Vϕ(st)−G^t)2\sum_t \big(\textcolor{#00897b}{V_\phi}(\textcolor{#0093b8}{s_t}) - \textcolor{#0033ff}{\hat G_t}\big)^2 의 목표값 G^t\textcolor{#0033ff}{\hat G_t} 가 바로 이것이다.

문제 5 — 망원경처럼 접히는 합

γ=1\textcolor{#536020}{\gamma} = 1, λ=1\textcolor{#993600}{\lambda} = 1일 때 GAE가 R−V(st)\textcolor{#d9670b}{R} - \textcolor{#00897b}{V}(\textcolor{#0093b8}{s_t})가 됨을 보이시오. 정답 응답(R = 1, 풀이가 나아가며 가치가 0.45 → 0.70 → 0.80 → 0.95)의 첫 토큰 "10 × 3"으로 수치를 확인하시오. 위젯의 「문제 5 값」 단추로 같은 설정을 불러와 수치판의 “10×3” 값과 답을 견주어 보라.

김민준 (자신만만)
김민준
코드로 해봤어요. λ=1이면 δ를 전부 더하는 거니까, 첫 토큰부터 끝까지 δ를 더하면… 0.55가 나와요. R − V(s₀) = 1 − 0.45 = 0.55랑 같네요.
선생님 (평상)
선생님
식으로도 보일 수 있어요?
김민준 (평상)
김민준
더하면 V(s₁) − V(s₀) + V(s₂) − V(s₁) + … 이렇게 가운데가 지워지고, 마지막에 V(s_T) − V(s₀)이 남아요. 그러니까 V(s_T) − V(s₀)… 어? R이 어디 갔지?
이서연 (평상)
이서연
마지막 δ에는 보상 r이 들어 있잖아. 그리고 V(s_T)는 응답이 끝난 뒤의 상태라서, 더 받을 보상이 없으니까 0이야.
김민준 (당황)
김민준
아, 종료 상태 가치를 0으로 안 두고 비평가 출력을 그대로 넣었어요. 코드에서는 마지막에 R을 따로 더해서 우연히 맞았네요.
선생님 (평상)
선생님
실무 코드에서 아주 흔한 버그예요. 응답이 최대 길이에서 잘렸을 때는 “끝난” 게 아니라 “중단된” 거라 V(s_T)를 0으로 두면 안 되고요. 그래서 잘린 응답은 끝난 응답과 따로 처리해야 해요.
김민준 (평상)
김민준
보고서 쓸 때 마감 시간 되어서 멈춘 거랑, 다 쓰고 끝낸 거랑 채점이 다른 거네요.

정리 ∑lδt+l=∑lrt+l+V(sT)−V(st)=R−V(st)\sum_{l} \textcolor{#8e44ad}{\delta_{t+l}} = \sum_{l} \textcolor{#d9670b}{r_{t+l}} + \textcolor{#00897b}{V}(\textcolor{#0093b8}{s_T}) - \textcolor{#00897b}{V}(\textcolor{#0093b8}{s_t}) = \textcolor{#d9670b}{R} - \textcolor{#00897b}{V}(\textcolor{#0093b8}{s_t}) (V(sT)=0\textcolor{#00897b}{V}(\textcolor{#0093b8}{s_T}) = 0, 종료 상태). 첫 토큰: 1−0.45=0.551 - 0.45 = 0.55. 길이 제한으로 잘린 응답은 종료가 아니므로 이 처리가 달라진다.