LSTM 이해하기



LSTM이란?

Long Short-Term Memory의 약자로 길이가 긴 데이터 ( 시계열 데이터 / 언어 데이터 ) 를 잘 처리할 수 있는 순환 신경망 모델입니다.

저번 글 “RNN(Recurrent Neural Network) 이해하기” 에서 설명한 순환신경망에 게이트를 추가한 모델이죠.
lstm_img_4
사진 속에서 윗 부분은 기본 순환신경망 모델인 “RNN”, 밑 부분은 RNN에 게이트를 추가한 “LSTM”모델입니다.

RNN모델과는 다르게 ht의 값만 순환하는 것이 아닌 다른 값(기억셀 Ct라고 불림)도 순환하는 것을 알 수 있습니다.
이번 글에선 이 다른 값, 즉 기억 셀($C_{t}$)가 순환하는 과정을 살펴보고 이해할 것입니다.

LSTM Architecture

기억 셀이라고 불리는 Ct값은 과거로부터 시간 t까지에 필요한 모든 정보가 저장돼 있어, 장기적인 데이터( 길이가 긴 데이터 )에 좋은 결과를 만들어줍니다.
lstm_img_1
사진을 확대해 보면 이전 셀에서 “$C_{t-1}$”, “$h_{t-1}$” 값을 받고 “$C_{t}$”, “ht”값을 전달해주는 것을 알 수 있습니다.

LSTM이 결과를 전달하는 과정은 크게 기억셀 값($C_{t}$) / 출력 값($h_{t}$)로 두 단계로 나눌 수 있습니다. 먼저 출력 셀 단계를 이해해보겠습니다.


출력 셀 $h_{t}$

1*w8Bgd_Gk5DasRC4GI6woTg

이 부분은 시그모이드를 지난 입력값과 전단계 출력값이 더해지는 것까지 기존 RNN모델과 유사합니다.

하지만, 그 이후 하이퍼볼릭 탄젠트(tanh)를 지난 기억 셀 값과 원소 별로 곱해져서 다음 출력 값으로 전달 된다는 특징이 있습니다. 기억셀이 구해지는 과정은 밑에 설명하겠습니다.

기억 셀 $C_{t}$

[1] Forget 게이트

1*mEqR_rKsGSPnG9InYVZa0w

forget 게이트의 특징 : 불필요한 기억을 잊게 해줍니다.

  • STEP 1 : 입력 값과 전 단계 출력값을 더해준 후, 시그모이드 함수를 지납니다.
  • STEP 2 : 그 후 전 단계 기억셀 값과 원소별 곱을 해줍니다.

[2] 정보 제공 게이트

1*r1ZrAmJu2SannlyAWsoPlg

정보 제공 게이트 특징 : 새로 기억할 정보를 기억셀에 추가 해줍니다.

  • STEP 1 : 입력 값과 전 단계 출력값을 더해준 후, 하이퍼볼릭 탄젠트 함수를 지납니다.
  • STEP 2 : 그 후 입력값과 전 단계 출력값을 원소별로 곱해준 후 시그모이드 함수를 지납니다.
  • STEP 3 : STEP 1, 2 값을 원소별로 곱해주는 과정이지만, 아직 하지 않고 넘어가겠습니다.

[3] 이후, [1]과 [2]가 합쳐지는 과정

1*gw8I2P_wxF_2NQyMRztQug

  • STEP 1 : 전 단계의 기억 셀 값과 Forget 게이트가 원소별로 곱해집니다.
  • STEP 2 : 정보 제공 게이트에서 두 값을 원소 별로 곱해줍니다.
  • STEP 3: STEP 1, 2 값을 더합니다,

Backpropagation of LSTM

LSTM은 RNN과 다르게 기울기 폭발(Gradient Explosion) / 기울기 소실(Gradient Vanshing)이 자주 일어나지 않습니다. 첫번째 이유로는 LSTM의 기억 셀인 $C_{t}$는 “+”와 “원소별 곱”노드만을 거치기에 그렇습니다.

“x”노드는 행렬곱이 아닌 원소별 곱을 사용하기에 곱셈이 누적되지 않아 기울기 소실이 일어나지 않습니다.

추가적을 “x”노드는 Forget 게이트가 제어하는데, 이 게이트는 잊어야하는 원소에 대해선 기울기가 소실되고, 잊지 않아야하는 원소에 대해서는 소실되지 않습니다.

Pytorch Code

import torch
import torch.nn as nn

class LSTM(nn.Module):
  def __init__(self, input_size, hidden_size, output_size):
    super(LSTM, self).__init__()
    self.lstm_layer = nn.LSTM(input_size, hidden_size)
    self.lienar = nn.Liear(hidden_size, output_size)
  def forward(self, input,):
    out, hide = self.lstm_layer(input)
    out = self.linear()
    return out


Reference
  • https://becominghuman.ai/long-short-term-memory-part-1-3caca9889bbc
  • 밑바닥부터 시작하는 딥러닝 2 / 사이토 고키 / 한빛 미디어