DL) RNN , LSTM

2022. 7. 12. 03:26ML_DL/DL

언어 모델 (Language Model)에 대해서 알아보자.

언어 모델이란?

문장과 같은 단어 시퀸스에서 각 단어의 확률을 계산하는 모델이다.

(Word2Vec도 여러 가지 언어 모델 중 하나이다. CBOW 같은 경우 주변 단어 정보로 타겟 단어의 확률을 할당하였다.)

 

근데 신경망은 비교적 최근 기술인데 그러면 그 이전에는 어떻게 자연어처리를 하였을까?

 

통계적 언어 모델(Statistical Language Model, SLM)

단어의 등장 횟수를 바탕으로 조건부 확률을 계산하였다.

 

ex) I'm a student 라는 문장이 등장할 확률을 구해보자.

먼저 식으로 나타내면 다음과 같다.

P("I","am","a","student") = P("I") X P("am" | "I") X P("a" | "I", "am") X P("student" | "I","am","a")

 

총 말뭉치의 문장이 1000개 이고 그 중 "I"로 시작하는 문장이 100개이면,

P("I") = 100/1000 = 1/10,

"I"로 시작하는 100개의 문장 중 바로 다음에 "am"이 등장하는 문장이 50개인 경우는 다음과 같다.

P("am"| "I")  = 50/100 = 1/2

 

위와 같이 구해서 모두 곱해주면 문장이 등장할 확률을 구할 수 있고 이것이 SLM의 방식이었다.

 

SLM으로는 부족한거였나? 요즘은 다 신경망 쓰던데?

SLM은 치명적인 문제점이 하나 있다. 바로 희소성 문제이다.

예를 들어 일상적으로 사용하는 "1 days", "2 days",... 와 같은 표현이 있고"8 days"는 없었다면, 해당 말뭉치를 이용한 통계적 언어 모델은 "8 days"를 표현하는 문장을 만들어 낼 수 없다. 

 

왜 그럴까?

위에서 등장 횟수를 바탕으로 조건부 확률을 계산한 것을 보면 쉽게 알 수 있다.

등장 횟수를 바탕으로 구하기에 한 번도 사용되지 않은 "8 days"는 나타날 확률이 0이다.

즉, 말뭉치에 조합된 표현이 없었으므로 만들어 낼 수 없다. 라는 것이 희소 문제라 부른다.

 

통계적 언어모델에서 이런 문제를 해결하기 위해 제시된 3가지를 알아보자.

 

N-gram 

N-gram이 뭔지 부터 알아보자

연속하는 2개 이상의 단어, 즉 단어 시퀸스를 벡터화 하는 방법이다. ( 기존에는 단어 한 개씩 벡터화를 진행하였다.)

다음은 N이 1 ~ 3 인 경우를 나타낸다.

N=1) I, love, you, so , much 

N=2) I love, love you, you so , so much 

N=3) I love you, love you so, you so much

 

근데 얘가 어떻게 희소 문제를 해결 할 수 있을까?

헷갈릴 수 있으나, 희소 문제는 I am a math 라는 표현과 math teacher 라는 표현이 있었다고 가정해도,

i am a math teacher라는 문장을 만들 수 없다.

 

그럼 Bi-gram, Tri-gram의 수식을 한 번 보자.(Bi-gram 는 N=2, Tri-gram 는 N=3인 경우 이다)

 

P( X(i) | X1,X2,...,X(i-1) ) ~= P( X(i) | X(i-1) ) => Bi-gram

P( X(i) | X1,X2,...,X(i-1) ) ~= P( X(i) | X(i-1),X(i-2) ) => Tri-gram

 

이 식들이 어떻게 유사할 수 있을까? (어떻게 위 식을 변형 시킨거지?)

마르코프 가정(Markov assumption)

: 특정 시점에서 어떤 상태의 확률은 최근 상태에만 의존하다

X(i)의 확률은 그 이전에 있는 몇 개의 토큰만으로도 추론이 가능하다.

아래 이미지는 마르코프 가정을 이미지화 한 것이다.

 각 원(토큰)들이 영향을 받는 갯수를 토대로 차수를 알 수 있다. (혹은 그 반대로도 생각 가능하다)

위 이미지는 T개의 토큰으로 구성된 문장이 나타날 확률을 보여준다.

pi 라고 불리는 저 기호는 i=1 ~ i=T 까지의 곱을 의미한다.

 

(sigma는 덧셈이었으나 , 해당 기호는 곱셈이라고 생각하면 된다.)

 

그러면 N-gram 사용하면 이제 희소 문제는 걱정이 없겠구나?

사실 N-gram에서도 문제점이 발생한다. 장기 의존성 문제라 불리는 것인데, 이는 근접한 토큰을 통해서 학습하기 때문에, 맨 앞부분이 맨 뒷부분(타겟)에 대해서 매우 중요한 표현일 경우에 오류가 발생한다.(예시)

 

맨 뒷부분(타겟)에 대해서는 맨 앞과의 관계를 고려하는 것이 아닌 맨 뒷부분으로 부터 몇 개 정도의 토큰의 빈도수를 토대로 학습을 하기 때문이다.

 

이를 장기 의존성 문제라하고 이를 해결하기 위해 의존성 분석이라는 방법을 이용한다.

의존성 분석이라는 방법에는 Shift reduce parsingTransition-based-ModelGraph-based-Model 이 있는데 이는 본 글에서는 다루지 않겠다.

 

추가로 N이 6~7정도로 늘리면서 장기 의존성 문제를 해결하고자 하면 또 다시 희소 문제가 발생한다.

 

게다가 사실 Bi-gram 의 경우에서도 희소성 문제는 여전히 발생한다. 

빈번하게 사용될 만한 단어가 아니라면(말뭉치에 없을 경우) 자연스러운 문장임에도 등장 확률은 0이 될 수 있기 때문이다. 

 

그러면 어떻게 해야할까?

 

N-gram 모델에서 발생하는 희소성 문제를 보안하고자 스무딩(Smoothing), backoff 등의 방법이 사용된다.

 

Smoothing(스무딩)

말뭉치에 존재하지 않는 표현에 대해 확률 값을 0이 아닌 다른 값으로 만들어 주는 작업이다.

스무딩에도 여러가지 방법이 있지만 , 그 중 add-k smoothing 을 보려고 한다.

Add-k smoothing 이란 N-gram의 모든 count에 대해서 k만큼 더 해줌으로 희소 문제를 해결하고자 하였다.

 

Back off (사실 큰 범위에서는 스무딩의 일종이라고 봐도 무방하다)

기본적인 개념은 N-gram으로 사용하고 있는데 희소문제가 발생하면 그보다 하나 낮은 N-1 -gram으로 확률을 계산하여 희소 문제를 해결하고자 하는 방법이다. 다만 예를 들어 Tri-gram 중 희소문제가 발생하여 Bi-gram을 통해 확률 계산을 하여 해당 갑을 인가하면 전체 확률의 합이 1을 넘어갈 수 있는데 이 때 적절한 값을 곱해 보정해주게 된다. 

 

이는 smoothing의 discount라는 개념을 이용한 것이다. 위 적절한 값이란 distribution function alpha를 곱해서 확률 값을 주게 된다. (물론 기존 N-gram에서 나온 확률값이 있다면 해당 값을 그대로 사용한다)

 

그러면 신경망에서는 희소 문제는 상관 없나요?

신경망 언어 모델에서는 횟수 기반이 아닌 word2Vec 이나 fastText등 출력 값인 임베딩 벡터를 사용한다. 

그말인 즉슨 의미적 문법적으로 유사한 단어라면 충분히 만들어 낼 수 있다는 것이다. (임베딩 벡터란 것이 의미를 내포하기 때문에)

 

신경망 언어 모델인 RNN (Recurrent Neural Netwokr)를 보자

RNN은 연속형 데이터를 처리하기 위해 고안된 신경망이다. 

연속형 데이터?

순서에 따라서 단위의 의미가 달라지는 데이터를 의미한다. (Sequential한 데이터)

 

RNN의 POS tagging 구조

RNN의 감정분석 모델 구조

RNN 구조의 특징 

좀 더 자세하게 보자

 

기존 딥러닝 구조와는 다르게 본인의 은닉층으로 다시 돌아가는 선을 볼 수 있는데 이와 같은 특징을 갖기에 순환 신경망이라는 이름이 붙여지게 되었다.

 

하나 주의해야할 점이 있는데, 저기서 W(hx) , b(h)등은 모두 같은 형태임을 염두해야한다. 즉 각각 다른 가중치가 아닌 하나의 변수에 내부 원소들이 동일하게 들어가 있는 것이다. 

 

그림을 이해하기 위해서 t 라는 부분을 잘 보아야한다. t는 시간의 흐름을 내포한다. 즉 t=1 일때 에서 t=2 로 진행하는 과정인데 이는 다시 말하자면 현재 t는 t-1에 대한 결과에 영향을 받고 있다는 의미이다.

 

시점에 대해서 좀 더 자세히 이해하기 일련의 과정을 그림으로 표현하면 다음과 같다.

 

 

다양한 RNN의 구조

one to many : 1개의 벡터 -> sequential한 벡터를 반환 : 이미지를 설명하는 "이미지 캡셔닝"

many to one : Sentiment analysis

many to many(1) : sequence to sequence 구조 : "기계 번역" ( 모두 입력 받은 이후 출력 )

many to many(2) : (입력과 동시에 출력한다, 형태는 input/output 둘 다 sequence) : "비디오를 프레임별로 분류"

 

장점과 단점

RNN은 이론적으로는 매우 긴 길이의 Sequential data도 처리가 가능합니다.

 

다만 몇 가지 단점이 있는데, 

병렬화(paralleiztion) 불가능

GPU가 발전해서 딥러닝이 큰 성과를 보였는데 이 중심에는 병렬화 기능이 있으나 , RNN의 경우 데이터를 순차적으로 받아야 하기 때문에 이러한 GPU연산을 사용함에 있어서 큰 장점이 없다.

 

기울기 폭팔, 기울기 소실의 문제점 (Exploding Gradient, Vanishing Gradient)

기울기의 문제는 결국 활성화 함수의 미분의 형태에 의해서 발생하게 된다. 

다음은 단순 RNN에서 활성화 함수인 tanh의 미분화 그래프이다.

 

우리는 수많은 은닉층을 통과하면서 역전파 과정이 이루어지는 것을 알고있다. 

역전파의 과정에서는 활성화 함수의 미분값을 전달하게 되는데 위 그래프를 보면 최댓값이 1 ,  x=(-4,4) 을 갖는 것을 볼 수 있다 . 수 많은 은닉층을 통과한다는 것은 미분값이 수 많이 곱해진다는 의미인데 미분값이 1 이하의 경우 1 이상의 경우에 따라서 역전파의 정보가 과하게 혹은 미약하게 전달이 되게 된다. 

 

시퀀스 앞쪽에 있는 벡터에 대해서 1이하의 경우 역전파의 정보가 거의 전달되지 않고 기울기 1이상의 대해서는 너무 과하게 전달된다. 

 

이를 기울기 소실과 기울기폭발이라고 부른다. 

 

* 기울기 폭발은 사실 가중치행렬의 연속적인 곱이 주된 원인이므로, 위에서 tanh 의 미분값이 1을 안넘는데? 하고 고민할 필요는 없다.

 

기울기 정보의 크기를 어떻게 잘 조절하면 되는거 아닌가? 

그러한 아이디어를 토대로 등장한 것이 앞으로 다루게 될 장단기 기억망(Long-Short Term Memory, LSTM) 이다.

그럼 이 LSTM의 구조를 보고 어떻게 기울기 정보의 크기를 조절할 수 있는지 알아보자

 

 

위 그림에서 기존에는 보지 못했던 Gate들이 생성된 것을 볼 수 있다. 

먼저 각 Gate가 하는 역할을 알아보자 

 

Forget Gate는 이전 state의 값을 받아오고, 현재 state의 입력값과 같이 Sigmoid 함수를 통과하게 된다.

Sigmoid를 통과한 값은 0~1 사이 값을 갖게 되고 이는 확률로 볼 수 있다. 이를 곱 연산을 통하면 결국

이전 state의 C 값에 대해서 값을 어느정도 조정하게 된다. 이는 다시 말해 과거 정보를 얼마나 유지할지 의미힌다.

 

Input Gate는 새로 들어온 입력과 이전 state에 대해서 계산을 진행하여 C값에 대해 덧셈을 해준다.

이는 새로 입력된 정보를 얼만큼 활용할지를 의미한다.

 

Output Gate는 조정된 C값과 이전 정보, 새로운 입력에 대해서 출력 정보를 얼마만큼 넘겨줄지를 정하게 된다.

 

즉 앞, 뒷쪽 시퀸스의 정보의 비중을 새로 생긴 cell-state인 C값을 통해서 결정할 수 있게 된 것이다.

위 그림에서는 가장 위에 있는 선이 cell-state이다.

LSTM은 구조적으로 너무 무겁기에 학습 파라미터가 너무 많다는 단점이 있다. 

이를 해결하고자 LSTM을 구조적으로 단순화시킨 GRU (Gated Recurrent Unit)이 나왔다.

 

기울기 문제를 해결한 방법의 핵심은 곱연산에 있어서 아다마르 곱을 사용한 것에 있으며, 각기 다른 가중치 행렬이다.

 

 

GRU의 구조

기존 LSTM과 달라진 점이 몇 가지 보인다.

 

먼저 cell-state 와 Output Gate가 사라진 것을 볼 수 있다.

우리는 앞서 cell-state를 통해서 정보의 비중을 조정했는데,  GRU에서는 h(t)가 그 역할도 수행을 하고 있다.

 

Output Gate에서 했던 출력 값 조정을 위해 GRU에서는 r(t)를 이용하게 되었고, 매 time-step에서 h(t)를 출력하게 되었다.

 

그러면 추가로 생긴 z(t)는 어떤 역할을 할까? z(t)의 값에 따라 Forget/Input Gate를 활성화 시킬 수 있다.

극단적인 z(t) =1 , z(t) =0 의 부분을 보자.

1인 경우 Forget Gate가 활성화 되며, 0인 경우 Input Gate가 활성화 되는 것을 볼 수 있다.

 

Quiz) 

 

A = z(t)*h^(t)

 


Reference

https://www.youtube.com/channel/UCxP77kNgVfiiG6CXZ5WMuAQ

 

Minsuk Heo 허민석

Tutorial for Computer Science

www.youtube.com

https://dgkim5360.tistory.com/entry/understanding-long-short-term-memory-lstm-kr

 

Long Short-Term Memory (LSTM) 이해하기

이 글은 Christopher Olah가 2015년 8월에 쓴 글을 우리 말로 번역한 것이다. Recurrent neural network의 개념을 쉽게 설명했고, 그 중 획기적인 모델인 LSTM을 이론적으로 이해할 수 있도록 좋은 그림과 함께

dgkim5360.tistory.com

 

'ML_DL > DL' 카테고리의 다른 글

DL) CNN  (0) 2022.07.15
DL) RNN 구조와 Attention  (0) 2022.07.12
DL) 단어의 분산 표현(Distributed Representation)  (0) 2022.07.11
DL) Natural Language Processing (자연어 처리)  (0) 2022.07.08
DL) Hyperparameters  (0) 2022.07.06