IQ Lab
← all posts
AI 2026.04.28 · 11 min read Advanced

LSTM은 어떻게 기억하는가 — CEC에서 GRU까지

Vanishing gradient의 근본 원인부터 Constant Error Carousel의 수학적 증명, forget bias 초기화의 결정적 효과, GRU의 단순화까지 — LSTM 설계 철학의 전체 흐름을 추적한다.


Plain RNN의 gradient는 시간을 거슬러 올라갈수록 지수적으로 사라진다. Hochreiter & Schmidhuber 1997은 이 문제의 근본 원인이 곱셈적 Jacobian 누적이라는 것을 진단했고, 그 해법으로 LSTM을 설계했다. 왜 additive update가 vanishing을 막는가? 그리고 이 원리가 GRU와 현대 아키텍처로 어떻게 이어지는가?

Plain RNN의 문제 — 곱이 쌓인다

BPTT에서 TT step을 거슬러 올라가는 gradient는 다음 형태를 띤다.

hTh0=t=1TWhhdiag(σ(zt))\frac{\partial h_T}{\partial h_0} = \prod_{t=1}^{T} W_{hh}^\top \,\mathrm{diag}(\sigma'(z_t))

각 step마다 WhhW_{hh}의 spectral radius ρ\rho가 곱해진다. ρ<1\rho < 1이면 gradient는 ρT\rho^T로 지수 감쇠하고, ρ>1\rho > 1이면 폭발한다. ρ=1\rho = 1은 이론적으로 균형점이지만 학습으로 유지하기 불가능에 가깝다.

핵심 통찰은 단순하다. 곱셈적 누적이 문제라면, 덧셈적 누적으로 바꾸면 된다.

LSTM의 cell state update는 다음과 같다.

ct=ftct1+itc~tc_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t

이 수식의 핵심은 ct1c_{t-1}직접 더해진다는 점이다. ftf_t, iti_t, c~t\tilde{c}_t는 모두 ht1h_{t-1}xtx_t의 함수이지 ct1c_{t-1}을 직접 참조하지 않는다.

정리 1 · CEC — Direct Partial Derivative

LSTM cell update ct=ftct1+itc~tc_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t에서 ct1c_{t-1}에 대한 direct partial derivative는 다음과 같다.

ctct1direct=ft\frac{\partial c_t}{\partial c_{t-1}}\bigg|_{\text{direct}} = f_t

(element-wise scalar)

▷ 증명

ft=σ(Wf[ht1;xt]+bf)f_t = \sigma(W_f [h_{t-1}; x_t] + b_f), iti_t, c~t\tilde{c}_t는 모두 ht1h_{t-1}xtx_t만을 직접 참조한다. ct1c_{t-1}에 직접 의존하는 항은 ftct1f_t \odot c_{t-1}뿐이다. 따라서 (ftct1)/ct1=ft\partial(f_t \odot c_{t-1})/\partial c_{t-1} = f_t이고, 나머지 항의 direct partial은 0이다. \square

Chain rule을 TT step에 적용하면 cell path의 gradient는 matrix product가 아닌 element-wise scalar product로 단순화된다.

cTc0cell path=t=1Tft\frac{\partial c_T}{\partial c_0}\bigg|_{\text{cell path}} = \prod_{t=1}^{T} f_t

ft1f_t \approx 1이면 이 곱도 1\approx 1이다. Hochreiter는 이것을 **Constant Error Carousel(CEC)**이라 불렀다 — 정보가 carousel처럼 cell 안을 순환하며 보존된다.

Plain RNN과의 차이는 극단적이다. ρ=0.9\rho = 0.9, σ=0.5\sigma' = 0.5인 plain RNN은 100 step 후 gradient가 (0.45)1001035(0.45)^{100} \approx 10^{-35}로 사라진다. f=0.99f = 0.99인 LSTM cell은 같은 시점에 0.991000.370.99^{100} \approx 0.37을 유지한다.

4개의 Gate — 왜 이 형태인가

순수한 additive update ct=ct1+Wxtc_t = c_{t-1} + W x_t는 CEC를 만족하지만 세 가지 문제를 갖는다. 모든 입력이 무조건 누적되고, 오래된 정보를 지울 수 없으며, cell이 unbounded하게 성장한다.

LSTM은 sigmoid gate 3개로 이를 해결한다.

ft=σ(Wf[ht1;xt]+bf)forget: 이전 cell 보존?it=σ(Wi[ht1;xt]+bi)input: 새 정보 받아들임?c~t=tanh(Wc[ht1;xt]+bc)candidate: 어떤 새 정보?ot=σ(Wo[ht1;xt]+bo)output: cell의 어느 부분 노출?ct=ftct1+itc~tht=ottanh(ct)\begin{aligned} f_t &= \sigma(W_f [h_{t-1}; x_t] + b_f) & \text{forget: 이전 cell 보존?} \\ i_t &= \sigma(W_i [h_{t-1}; x_t] + b_i) & \text{input: 새 정보 받아들임?} \\ \tilde{c}_t &= \tanh(W_c [h_{t-1}; x_t] + b_c) & \text{candidate: 어떤 새 정보?} \\ o_t &= \sigma(W_o [h_{t-1}; x_t] + b_o) & \text{output: cell의 어느 부분 노출?} \\ c_t &= f_t \odot c_{t-1} + i_t \odot \tilde{c}_t \\ h_t &= o_t \odot \tanh(c_t) \end{aligned}

sigmoid는 [0,1][0, 1]으로 “양(degree)“을 제어하고, tanh는 [1,1][-1, 1]로 “값(value)“을 표현한다. 정보의 선택과 내용이 분리된다.

Greff et al. 2017의 대규모 ablation 실험은 이 구조가 놀랍도록 robust함을 보인다. NIG(no input gate)와 NOG(no output gate)만이 큰 성능 손실을 유발했고, 나머지 변형(peephole, coupled gates 등)은 모두 marginal했다.

트레이드오프

Vanilla LSTM은 RNN 대비 4배의 파라미터 (4H(D+H+1)4H(D+H+1))를 요구한다. 이 비용은 long-range dependency 학습 능력으로 돌아온다. 단, cell state path만 vanishing이 해결되고 hidden path는 여전히 취약하다는 점, 그리고 sequential 처리로 GPU 병렬화가 제한된다는 점은 명확한 한계다.

Forget Bias = 1 — 학습의 cold start를 막다

CEC의 수학이 옳더라도 학습이 시작되는 시점이 critical하다. PyTorch의 기본값은 bf=0b_f = 0으로, 이때 ftσ(0)=0.5f_t \approx \sigma(0) = 0.5다. 100 step 후 initial gradient는 0.510010300.5^{100} \approx 10^{-30} — float32 정밀도의 한계(10810^{-8})를 훨씬 밑돌아 학습이 사실상 멈춘다.

bf=1b_f = 1로 설정하면 초기 ftσ(1)=0.73f_t \approx \sigma(1) = 0.73이 되고, 같은 100 step에서 gradient는 0.7310010130.73^{100} \approx 10^{-13}으로 측정 가능한 수준을 유지한다. 비율은 1.4610010171.46^{100} \approx 10^{17}배다.

Jozefowicz et al. 2015는 이 단순한 변경이 T=200T = 200 Adding Problem에서 학습 가능 여부를 binary하게 결정함을 보였다. PyTorch에서 적용하는 방법은 다음과 같다.

def set_forget_bias(lstm, value=1.0):
    for layer in range(lstm.num_layers):
        bias_ih = getattr(lstm, f'bias_ih_l{layer}')
        bias_hh = getattr(lstm, f'bias_hh_l{layer}')
        H = bias_ih.size(0) // 4
        with torch.no_grad():
            bias_ih[H:2*H].fill_(value)
            bias_hh[H:2*H].fill_(0.0)

PyTorch의 LSTM bias 순서는 [i, f, g, o]이므로 forget gate는 인덱스 H:2H에 해당한다.

GRU — 같은 정신, 더 단순한 형태

Cho et al. 2014의 GRU는 LSTM의 핵심 정신을 2개의 gate로 압축한다.

zt=σ(Wz[ht1;xt]+bz)rt=σ(Wr[ht1;xt]+br)h~t=tanh(W[rtht1;xt]+b)ht=(1zt)ht1+zth~t\begin{aligned} z_t &= \sigma(W_z [h_{t-1}; x_t] + b_z) \\ r_t &= \sigma(W_r [h_{t-1}; x_t] + b_r) \\ \tilde{h}_t &= \tanh(W [r_t \odot h_{t-1}; x_t] + b) \\ h_t &= (1 - z_t) \odot h_{t-1} + z_t \odot \tilde{h}_t \end{aligned}

update gate ztz_t는 LSTM의 forget gate와 input gate를 coupled한 형태다 — ft=1ztf_t = 1 - z_t, it=zti_t = z_t에 해당한다. cell state와 hidden state의 분리도 없앴다.

cell path의 direct gradient는 ht/ht1direct=1zt\partial h_t / \partial h_{t-1}|_{\text{direct}} = 1 - z_t로, LSTM의 ftf_t와 정확히 대응한다. CEC의 원리가 동일하게 적용된다.

파라미터는 LSTM의 75%(3H(D+H+1)3H(D+H+1))이고, Chung et al. 2014의 체계적 비교에서 폴리포닉 음악 모델링 등 여러 task에서 동등한 성능을 보였다. universal 우열은 없고 task에 따라 선택이 달라진다.

정리

  • Plain RNN의 vanishing은 Jacobian의 matrix product 누적이 근본 원인이다.
  • LSTM의 cell update는 이를 element-wise scalar product로 바꾼다. ct/ct1=ft\partial c_t / \partial c_{t-1} = f_t — CEC의 핵심.
  • ft1f_t \approx 1이 되도록 forget bias = 1로 초기화하면 cold start를 막고 long-range gradient를 학습 초기부터 살린다.
  • GRU는 같은 additive update 철학을 2개의 gate로 구현하며, 파라미터를 25% 절약한다.

LSTM의 모든 설계 결정은 하나의 원칙으로 수렴한다 — 곱셈을 덧셈으로 바꿔 gradient를 시간 축에서 보존하라. ResNet의 residual connection, Transformer의 layer-wise additive update, Mamba의 selective SSM까지, 이 원칙의 변주가 현대 아키텍처 전반에 흐른다.

REF
Hochreiter, S. & Schmidhuber, J. · 1997 · Long Short-Term Memory · Neural Computation
REF
Jozefowicz, R., Zaremba, W. & Sutskever, I. · 2015 · An Empirical Exploration of Recurrent Network Architectures · ICML