KBR
KBR

hi there

[LSTM] LSTM의 동작 원리 2편: Cell State와 세 개의 Gates

[LSTM] LSTM의 동작 원리 2편: Cell State와 세 개의 Gates


지난 게시물에서 LSTM 셀의 전체적인 큰 그림을 살펴봤었다.

LSTM은 기존 RNN의 단점이었던 장기 의존성(Long-Term Dependency) 문제를 해결하기 위해 장기 기억과 단기 기억을 분리해서 관리하는 구조를 가지고 있다고 했다.

이를 위해 셀 내부에는 정보의 흐름을 조절하는 3개의 게이트와 1개의 데이터 생성기가 있으며, 특히 핵심 정보를 끝까지 운반하는 Cell State(장기 기억)에 대해 알아봤다. ​

게이트를 하나씩 알아보기 전에 아주 쉬운 비유를 하자면:

💡 [아주 쉬운 비유: 시험공부를 하는 학생]
기존 RNN
벼락치기를 해서 방금 본 마지막 페이지의 내용은 기억하지만, 책 앞부분 내용은 이미 다 까먹은 상태

LSTM
요약노트 (Cell State)를 가지고 있는 학생
1. 시험에 안 나올 것 같은 내용은 지우고(Forget Gate),
2. 새로 배운 중요한 내용은 추가로 적어두고(Input Gate),
3. 문제를 풀 때 노트를 참고해서 답을 적어냄(Output Gate)



LSTM의 컨베이어 벨트: Cell State

Cell State LSTM의 Cell State ($C_t$)


LSTM 블록의 제일 위쪽에 수평으로 이어진 선이 바로 Cell State($C_t$)다.

이 길을 통해 정보가 거의 변하지 않고 쭉 흘러갈 수 있어서, 아주 오래전의 정보도 끝까지 전달될 수 있다.

  1. 정보의 통과
    • 이전 시점($C_{t-1}$)에서 넘어온 정보(기억)가 다음 시점으로 나갈 때까지 복잡한 변환 없이 직선으로 흐른다.

    • 기존 RNN은 데이터를 계속 변형시켜서 (tanh와 같은 활성화 함수를 계속 거침) 나중에는 원래 형태를 알아보기 힘들지만, LSTM의 Cell State는 가벼운 선형 연산(덧셈, 곱셈)만 거치기 때문에 정보가 변질되지 않고 그대로 흘러갈 수 있다.

    • 따라서 맨 처음에 들어왔던 중요한 정보가 먼 미래(끝부분)까지 살아남을 수 있게 된다.
      ⇒ 장기 의존성 문제 해결!

  2. 정보의 수정: 곱하기($\times$)와 더하기($+$)
    • 그림의 위쪽 라인을 보면 두 가지 연산 장치가 달려있는 걸 확인할 수 있다.

    • 곱하기(X): 정보를 얼마나 살릴지 죽일지 결정한다.
      • 0을 곱하면 → 0이 되어 정보가 완벽하게 삭제된다. (forget)
      • 1을 곱하면 → 원래 값이 그대로 유지된다. (keep)

    • 더하기(+): 새로운 정보를 추가한다.
      • 기존의 기억 흐름에, 이번 단계에서 중요하다고 판단된 새로운 기억을 얹어준다. (update)
    💡 즉, LSTM의 Cell State는 이 컨베이어 벨트 위로 지나가는 정보(기억) 상자에, 중간중간 게이트(Gate)라는 작업자들이 붙어서, **'필요없는 건 빼고(X), 새로운 건 넣는(+)'** 작업을 수행하는 공장과 같다.

그럼 여기서 생기는 질문: 중요한 정보와 필요 없는 정보를 구분하는 기준은 무엇일까?

이 판단을 위해 LSTM은 3개의 게이트(Gate) 를 사용하여 정보의 흐름을 조절한다.



3가지 게이트를 지나는 과정 (Forget Gate → Input Gate → Output Gate)

1 . 망각 게이트 (Forget Gate): 과거의 정보를 잊는 단계

망각 게이트 단계 망각 게이트 단계
  • 역할
    • 과거의 정보($C_{t-1}$) 중 필요 없는 것을 버리고, 필요한 것만 남기는 단계

  • 작동 원리
    • 이전 시점의 은닉 상태($h_{t-1}$)와 현재 시점의 입력 데이터($x_t$)로 받아서 판단한다.

    • 시그모이드($\sigma$) 함수를 통과시켜 0과 1 사이의 값을 내보낸다.
      • 0에 가까우면 → 정보 삭제
      • 1에 가까우면 → 정보 유지

    • 이 값($f_t$)은 직전 셀 상태($C_{t-1}$)와 곱하기(X) 연산되어 실제 삭제가 이뤄진다.

  • 예시 (Context Switching)
    • “그는 밥을 먹었다”라는 문장이 끝나고 새로운 문장이 시작될 때, 이전 주어(‘그’)에 대한 설명 정보 등은 잊어도 된다. 이때 망각 게이트가 낮은 값(e.g. 0.1)을 출력하여 정보를 희미하게 만든다.
    \[f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f)\]
    • $f_t$: 망각 게이트의 출력값 (0-1)
    • $h_{t-1}$: 이전 시점의 은닉 상태 (단기 기억)
    • $x_t$: 현재 시점의 입력 데이터

    💡 왜 0/1 스위치(step function; 계단함수)가 아닐까??
        ⇒ 역전파(Backpropagation)를 통한 학습 때문

    만약 0과 1만 있는 스위치(계단함수)라면?
      - 그래프가 수직이거나 평평해서 미분값이 무한대이거나 0이 된다.
      - 이렇게 되면 경사하강법을 적용할 수 없어, 모델이 '얼마나 잊어야 할지'를 학습할 수 없다.

    0-1 사이의 연속적인 값(sigmoid; 시그모이드)이라면?
      - 부드러운 곡선 형태로 미분(기울기 계산)이 가능하다.
      - 따라서 모델이 조금씩 오차를 줄여가며 최적 의 망각 비율을 스스로 학습할 수 있다.



2 . 입력 게이트 (Input -Gate): 새로운 정보를 저장하는 단계

입력 게이트 단계 입력 게이트 단계
  • 입력 게이트는 현재 들어온 정보 중 무엇을, 얼마나 Cell State(컨베이어 벨트)에 실을지를 결정하는 단계이다.

  • 이 과정에서는 Sigmoid와 Tanh 이 두 가지 함수가 협력하여 수행한다.

    a. 선별 담당(Sigmoid Layer): ‘얼마나 중요한 정보인가?’

    • 작동 원리
      • 현재 들어온 데이터($x_t$)와 이전 단기 기억($h_{t-1}$)을 보고, 각 정보의 중요도를 0-1 사이의 점수로 매긴다.

    • 단어 전체가 아니라 ‘속성(차원)별’로 판단한다.
      • 예를 들어, ‘그녀(She)‘라는 단어가 들어왔을 때, 이를 [0.9, 0.1, -0.5] 같은 벡터로 인식한다.

      • 이때 입력 게이트는 문맥을 고려해 각 속성마다 다른 점수(가중치)를 매긴다.

      • e.g. 상황에 따른 중요도 판단

        • 입력 단어: ‘그녀’ ([성별정보, 존댓말여부, 감정상태])
        • 현재 문맥: 주어를 기억해야 하는 상황
        • Sigmoid(입력 게이트)의 판단 결과: [0.99, 0.01, 0.01]
          • 첫 번째(0.99): 성별 정보(여성)은 뒤에서 대명사(‘her’)를 맞추려면 중요하니까 확실하게 저장 (1에 가까운 값)
          • 두 번째(0.01): 존댓말 정보는 지금 문맥에서 별로 중요하지 않으므로 무시 (0에 가까운 값)
          • 세 번째(0.01): 감정 상태 또한 중요하지 않으므로 무시 (0에 가까운 값)

    단어 하나에 대한 점수를 매기는 것이 아닌, 단어를 표현하는 벡터의 각 속성(차원)마다 별도로 점수(0-1)를 매기는 것

    b. 데이터 생성 담당 (Tanh Layer): ‘실제 저장할 내용은 무엇인가?’

    • 선별 담당(Sigmoid)이 문을 열라고 신호를 보내도, 정작 들어올 데이터가 없다면 소용이 없다.

    • Tanh 층은 현재 데이터($x_t$)와 이전 기억($h_{t-1}$)을 바탕으로, Cell State에 더해질 새로운 후보값($\tilde{C_t}$)을 만들어낸다.

      • 이 값은 -1 ~ 1 사이의 값을 가지며, 정보의 방향(긍정/부정, 증가/감소)을 나타낸다.

    c. 최종 입력: $\sigma$와 $tanh$의 협력

    • 두 함수의 계산이 끝났다면, 이제 두 값을 같은 위치끼리 곱한다 (중요도 X 실제 정보)
      • 0.99(중요함) * 성별 정보 = Cell State에 강하게 기록됨
      • 0.01(안중요) * 존댓말 정보 = 0에 가까워져서 거의 기록되지 않음

    • 이렇게 필터링을 거친 정보들을 Cell State(컨베이어 벨트)에 덮어씌워 장기 기억으로 만들어야 하는데,

      이 과정에 대한 자세한 설명은 아래에서…~

    💡 [여기까지 정리]
    망각 게이트(Forget Gate)를 통해 '과거에서 버릴 것'을 정하고, 입력 게이트(Input Gate)를 통해 “현재에서 취할 것”을 결정했다!
    이제 이 두 가지 정보를 가지고 실제 장기 기억 저장소(Cell State; 컨베이어 벨트)에 내용을 덮어씌워야 한다.




+) 셀 상태 업데이트(Cell State Update) 단계: 기억 갱신

업데이트 단계 셀 상태 업데이트 단계


앞서 ‘망각 게이트(forget gate)‘와 ‘입력 게이트(input gate)‘를 통해 준비를 마쳤다면, 이제 실제로 컨베이어 벨트(Cell State)에 정보(기억)을 갱신해야 한다.

이 단계는 ”과거의 기억 중 남길 것”과 ”새로운 기억 중 더할 것”을 합치는 과정이다.

  1. 업데이트 공식: 과거와 현재의 결합
\[C_t = \underbrace{(f_t \times C_{t-1})}_{\text{살아남은 과거}} + \underbrace{(i_t \times \tilde{C}_t)}_{\text{반영된 현재}}\]
  • 살아남은 과거 ($f_t \times C_{t-1}$)
    • 이전 시점의 기억($C_{t-1}$)에 망각 게이트 값($f_t$, 0~1)을 곱해서 불필요한 기억을 지운 상태
      → Forget Gate의 최종 반영값

  • 반영된 현재($i_t \times \tilde{C}_t$)
    • Tanh가 제안한 새로운 정보 후보군($\tilde{C_t}$, -1~1)에 입력 게이트의 승인 비율($i_t$, 0~1)을 곱해서, 중요하다고 선택된 정보만 남긴 상태
      → Input Gate의 최종 반영값

      • $i_t$ = Input Gate의 Sigmoid Layer의 출력값 (0 ~ 1)
      • $\tilde{C}_t$ = Input Gate의 Tanh Layer의 출력값, candidate (-1 ~ 1)

  • 최종 결과 ($C_t$)
    • 이 두 값을 더하기(+) 하여 다음 시점으로 넘겨줄 최종 셀 상태(장기 기억)를 완성한다.

    💡 곱셈이 아닌 덧셈을 하는 이유?

    1. 기울기 소실 (Vanishing Gradient) 방지
    - 일반 RNN은 곱셈을 하면서 상태를 업데이트한다. 1보다 작은 수를 계속 곱하면 값은 결국 0으로 수렴해서 사라진다. (오래된 기억이 사라지는 이유)
    - 반면, LSTM은 더하기 연산을 사용한다. 미분(역전파)할 때, 더하기 연산은 기울기를 그대로 뒤로 전달해주는 역할을 하므로 정보가 멀리까지 살아남을 수 있다.

    2. 정보의 누적 (ResNet과 유사)
    - 컴퓨터 비전의 ResNet(Residual Network)이 층을 깊게 쌓아도 학습이 잘 되는 이유는 입력을 출력에 더해주기 `SkipConnection`을 통해 입력을 출력에 더해주기 때문이다.
    - LSTM의 Cell State도 이와 유사하게 기존 기억을 덮어쓰는(overwrite)게 아니라 기존 기억 위에 정보를 얹는(add) 방식으로 작동하기 때문에 장기 기억 보존에 탁월하다.

    💡 왜 $Tanh$(-1 ~ 1)을 사용할까?

    LSTM 내부에는 두 종류의 활성화 함수가 있다
    - Sigmoid (0 ~ 1): 문을 여닫는 '게이트(비율)' 역할
    - Tanh (-1 ~ 1): 실제 데이터인 '정보(information)' 역할

    후보군 $\tilde{C}_t$을 만들 때 $Tanh$을 쓰는 이유는 정보의 방향성 때문이다.
    - 양수 (+): 정보를 강화 (e.g. 주가 상승, 긍정 감정)
    - 음수 (-): 정보를 감쇄하거나 반전 (e.g. 주가 하락, 부정 감정)
    - 0: 중립

    → 이 단계에서 만들어진 정보는 아직 확정된 게 아니기 때문에 후보군이라고 부른다.

    만약 0-1 사이의 값(Sigmoid)만 사용해서 계속 더한다면, 숫자가 줄어들지않고 무조건 커지기만 해서, 나중에는 값이 무한대로 발산할 가능성이 있다. 따라서 Tanh은 음수값을 통해 이것들을 제한한다.


  • 예시, 영화 리뷰 분석 시뮬레이션
    • LSTM이 ‘이 영화는 지루한(boring) 영화다문장을 읽었다고 가정해보자.
    • 내부적으로 3가지 속성(Index)을 추적 중이다.
      • Index 0: 재미 (Positive=1, Negative=-1)
      • Index 1: 장르-액션 (High=1, Low=0)
      • Index 2: 시제 (Future=1, Past=-1)

    Step 1) Tanh (후보군 생성) 단계

    • ‘지루한($x_t$)’이라는 단어를 보고 Tanh Layer가 의견(후보 벡터 $\tilde{C}_t$)을 낸다

      • Candidate Vector: [-0.9, -0.1, 0.0]
        • Index 0 (재미): -0.9 (아주 재미없음! 점수 깎기)
        • Index 1 (액션): -0.1 (액션이랑은 관계없지만, 약간 정적인 느낌?)
        • Index 2 (시제): 0.0 (시제랑은 상관없음)

    Step 2) Input Gate (입력 게이트) 단계

    • 동시에 Sigmoid 층이 문맥을 보고 중요도($i_t$)를 판단한다. (목표: 영화 평점 매기기)

    • Input Gate Vector: [1.0, 0.1, 0.0]

      • Index 0 (재미): 1.0 (평점에 핵심적인 정보야. 무조건 반영!)
      • Index 1 (액션): 0.1 (액션 여부는 평점에 별로 중요하지 않음)
      • Index 2 (시제): 0.0 (시제도 평점이랑 관련 없음)

    Step 3) Update (곱하기 & 더하기) 단계

    • 이제 후보군과 게이트를 곱해서 기존 기억($C_{t-1}$)에 더한다

      속성 Tanh (의견) Input Gate (필터) 최종 반영값 ($\tilde{C}_t \times i_t$) 결과
      재미 -0.9 1.0 -0.9 기존 재미 점수에서 0.9만큼 대폭 깎음
      액션 -0.1 0.1 -0.01 거의 반영 안 됨
      시제 0.0 0.0 0.0 전혀 반영 안 됨

    결과적으로 LSTM은 “지루하다”는 단어를 통해 영화의 재미 점수만 골라서 낮추는(update) 정교한 작업을 수행하게 된다.




3 . 출력 게이트 (Output Gate): 최종 결과를 내보내는 단계

입력 게이트 단계 입력 게이트 단계
  • 현재 가진 정보(장기 기억)를 바탕으로 최종 결과(단기 기억 및 출력)를 내보내는 단계이다.
    • e.g. 주어가 사람(단수/복수, 성별, etc.)이라는 것을 파악했으므로, 뒤에 올 동사도 그에 맞는 형태를 내보내도록 결정하는 역할

  • 출력 게이트는 혼자서 Output을 결정하지 않고, 방금 만든 업데이트를 마친 Cell State($C_t$)을 가져와서 사용한다.


[출력 게이트 과정 정리]

  1. Output Gate($o_t$): 지금 가진 정보 중 몇 %나 밖으로 보낼까? (sigmoid로 결정, 0~1)
  2. Cell State 변환: 방금 갱신된 장기 기억($C_t$)을 가져와서 Tanh 함수를 씌운다. (값이 너무 커지지 않도록 -1 ~ 1로 정규화 및 포장)
  3. 최종 출력 ($h_t$) 계산
    $h_t = o_t \times \tanh(C_t)$
💡 요약
출력 단계는 방금 갱신된 장기 기억($C_t$)을 Tanh으로 정규화한 뒤, 출력 게이트($o_t$)가 허락한 비율만큼만 필터링하여 Hidden State($h_t$)로 내보내는 과정이다.
이렇게 만들어진 $h_t$는 다음 시점(t+1)의 LSTM 셀로 넘어가고, 동시에 다음 층(Dense Layer)으로도 전달되어 우리가 원하는 최종 예측값이 된다.



전체 데이터 흐름 정리

LSTM 전체 데이터 흐름 정리 LSTM 전체 데이터 흐름


  1. 이전 시점의 기억 도착
    • 이전 블록에서 넘어온 단기 기억($h_{t-1}$) 과 장기 기억($C_{t-1}$)이 셀에 도착한다.
  2. 망각 결정 (Forget Gate)
    • 현재 데이터($x_t$)와 단기 기억($h_{t-1}$)을 보고, 과거 기억 중 ‘얼마나 잊을지’ 가중치($f_t$)를 정한다.
  3. 과거 필터링
    • 가져온 과거 기억($C_{t-1}$)에 망각 가중치($f_t$)를 곱해서 ‘살아남은 과거’를 만든다. (이 과정에서 기존의 원본 $C_{t-1}$은 덮어씌워진다.)
  4. 새로운 정보 승인 (Input Gate)
    • 다시 $x_t$와 $h_{t-1}$을 보고 “얼마나 저장할지” 승인 비율($i_t$)을 정하고, Tanh로 새로운 후보군($\tilde{C}_t$)을 만든 뒤 둘을 곱해 ‘반영된 현재’를 만든다.
  5. 기억 업데이트 (Cell State Update)
    • ‘살아남은 과거’와 ‘반영된 현재’를 더해 이번 시점의 최종 장기 기억 ($C_t)$을 완성한다.
  6. 최종 출력 (Output Gate)
    • 완성된 $C_t$는 다음 LSTM 블록으로 전달되고, 동시에 C_t$C_t$($o_t$)을 곱해 현재 시점의 최종 단기 기억이나 출력값 ($h_t$)을 만들어 내보낸다.

구분 명칭 역할 활성화 함수 비유
1. Gate Forget Gate 과거를 얼마나 잊을지 결정 Sigmoid (0 ~ 1) 삭제 담당 게이트
2. Gate Input Gate 입력을 얼마나 받을지 결정 Sigmoid (0 ~ 1) 입력 담당 게이트
3. Info Cell Candidate 새로 기억할 실제 내용 후보 Tanh (-1 ~ 1) 새로운 정보 덩어리
4. Gate Output Gate 결과를 얼마나 내보낼지 결정 Sigmoid (0 ~ 1) 출력 담당 게이트