ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 11. RNN(Recurrent Neural Network)
    general ML, DL, NLP/딥러닝 2022. 6. 28. 18:08

    *본 게시물은 22-1학기 연세대학교 일반대학원 딥러닝을이용한비정형데이터분석(이상엽 교수님) 수업 내용을 정리한 것입니다.

     

    1. 개요

      RNN(Recurrent Neural Network)은 모형이라기보다는 층(layer)이라 할 수 있습니다. 따라서 Feed Forward Neural Network의 은닉층 하나로 생각할 수 있으며, 이 RNN이라는 은닉층이 순차적으로 여러번 반복 적용됩니다. 

    정확히는 RNN은 순차적으로 입력되는 데이터, 즉 시퀀스(sequence) 데이터에 대해 매번 반복적으로(=순환적으로) 적용되는 방식으로 작동합니다. 

    1) 시퀀스 데이터(sequence data)

      시퀀스 데이터란, 순서를 가지고 연속적으로 나열되어있는 데이터를 말합니다. 주로 텍스트(단어 시퀀스), 비디오(이미지 시퀀스) 데이터를 시퀀스 데이터라 부르며, RNN은 특히 텍스트 데이터를 다루는 데에 적합합니다. 

    2) 텍스트

      텍스트를 다룰 때에는 어떤 단어가 어떤 순서로 언제 사용되었는지가 중요 정보가 되며, task를 수행할 때 주요하게 작용합니다. 이러한 텍스트에 대해 RNN은 1. 단어의 순서 2. 단어간 관계정보를 얻는데 매우 용이합니다. 즉, 텍스트가 가진 정보를 추출하기에 적합합니다. 

    3) 감성분석(sentiment analysis)

      갑자기 감성분석이라니 당황스러우셨겠지만  RNN을 사용해 감성분석을 수행할 수 있습니다. 감성분석은 텍스트 분류 task로 문서의 감성을 파악해야 합니다. 감성을 파악하기 위해서는 여러 정보가 필요한데, 단순한 단어 출현 빈도 정보보다는 단어들이 어떤 순서로 사용되었는지, 다른 단어들과 어떠한 관계를 가지고 있는지가 훨씬 감성분석에 도움이 되는 정보입니다. 빈도에는 순서나 관계와 같은 정보가 누락되어 있기 때문입니다. 이에 따라 RNN을 사용하여 감성분석도 가능합니다. 

     

    2. RNN의 작동 방식 

      RNN이 어떻게 작동하는지를 알려면 텍스트 데이터(말뭉치, 코퍼스, 문서...)가 RNN에 어떻게 입력되는지를 먼저 알아야 합니다. 다음과 같이 요약할 수 있습니다. 

    문서(단어)를 저차원(원소 약 100~300개) 벡터로 표현 = 문서를 100~300차원 임베딩 벡터로 표현

    ⇒ RNN에 텍스트를 입력하려면 텍스트를 먼저 임베딩 벡터로 변환
    *벡터: 여러 숫자들을 일렬로 배열한 것, 하나의 숫자는 '원소'가 되며 벡터는 원소 여러 개를 가짐
    *벡터는 기하학적 의미를 지님: 공간상 하나의 점(POINT)
       -공간은 또 차원을 가지며, 축 개수에 따라 차원이 달라짐
    *벡터 내 원소 개수 = 벡터의 차원

    여기서도 컴퓨터는 숫자밖에 모르는 바보임이 드러납니다(...) 아무튼 이 포스트에서는 문서가 100차원으로 표현되었다고 가정합니다. 아래와 같이 변환된 상태인 것입니다. 벡터 변환시 가지게 된 원소의 값도 학습을 통해 찾은 최적의 값이라 부를 수 있습니다. 

    0.13 -5.98 .....이러한 원소(숫자)의 개수는 단어 당 100개(단어 당 100차원)..... 1.34
    영화 -1.11 7.12 0.76
    되게 2.35 4.76 -0.04
    재밌었어 6.21 2.11 -3.21

      위에서도 언급했듯이 텍스트데이터는 시퀀스데이터입니다. 때문에 RNN에는 단어별 임베딩 벡터 순서대로 들어간다고(그->영화->되게->재밌었어) 생각하면 됩니다. 한 단어 임베딩 해치우고, 그 다음 단어 임베딩 해치우고 이런 식인 것입니다(...)ㅋㅋㅋ

     

    좀 더 구조적으로 time step 0에서의 RNN을 수행한다고 가정하겠습니다.

    RNN의 입력층 입력노드는 임베딩 벡터의 원소의 수, 즉 임베딩 벡터 차원과 개수가 같습니다(입력 노드 수 = 임베딩 벡터 원소(차원) 수). 각 입력노드는 첫 번째 단어('그') 임베딩 벡터의 각 원소 값을 각각 받습니다. 그림에서는 벡터의 원소 수(차원)가 100이기 때문에 100개의 임베딩 값이 입력 노드에 들어갔다고 가정합니다. RNN의 은닉노드 개수는 사용자 마음대로입니다. 이 RNN 모델에서는 은닉노드를 모든 레이어에서 j개 썼다고 가정하겠습니다. 

    time step 0에서의 RNN층: time step 0이기에 H0이 됩니다. 편향은 일단 생각하지 않습니다.

      입력층과 첫번째 RNN 은닉층 사이를 보면 화살표들이 있습니다. 이 화살표들은 각각의 가중치를 가지기 때문에, 입력 노드와 은닉 노드 사이 unique한 가중치 개수100*j개가 됩니다. 입력노드에 들어온 단어 임베딩 값과 가중치를 곱한 결과인 z1....zj는 활성화 함수를 거쳐 f(z1)....f(zj)가 되는데, 그림에 따르면 f(z1)은 h0,1에, f(zj)는 h0,j에 대응합니다. 낱개의 h0,1 , h0,j는 히든 스테이트(hidden state)라 부릅니다. 이렇게 RNN층을 거쳐 나온 모든 히든 스테이트를 나열하면 히든 스테이트 벡터(hidden state vector) h0가 됩니다. 히든 스테이트 벡터의 원소 수는 은닉 노드 수와 동일합니다.

    RNN 입력 노드 수 단어 임베딩 벡터 원소 수(차원)
    RNN 은닉 노드 수 사용자 마음대로 정의
    입력 노드~은닉 노드 사이 가중치 개수 입력 노드 수*은닉 노드 수
    히든 스테이트 벡터 원소 수(차원) 해당 RNN층 은닉 노드 수

     

      다음은 time step 1입니다. 위 그림과는 달리 입력이 2개로 나누어져 있는 것을 확인할 수 있습니다. time step 1의 입력은 두 번째 단어 '영화'의 임베딩 벡터와 이전 time step 0에서 생성된 히든스테이트 벡터 h0입니다. time step 1의 입력층에서는 단어 임베딩 벡터, time step 1의 RNN 은닉층에는 time step 0의 히든 스테이트 벡터h0이 입력됩니다. 즉 두 번째 단어 임베딩 벡터는 time step 1의 입력층으로, 이전 time step 0의 히든 스테이트 벡터 h0은 바로 RNN 은닉층에 갑니다.

    위에서는 설명하지 않았지만 실은 time step 0에서도 히든 스테이트 정보가 0으로 들어옵니다. 과정에서는 생략하였습니다.

     

    이를 풀어서 그려보면 아래 그림과 같습니다. 

    이상엽 교수님 수업자료입니다.

     결론적으로 RNN의 입력은 이전 time step의 히든 스테이트 벡터 & 단어 임베딩 벡터라 생각하면 됩니다. 이러한 과정을 마지막 단어 임베딩 벡터가 RNN에 입력되어 통과할 때까지 계속 반복합니다.

    마지막 히든 스테이트 벡터 ht-1이 생성되면, 이 ht-1는 바로 출력층의 입력이 됩니다. 이 마지막 히든 스테이트 벡터는 원소의 개수를 j개 가지고 있습니다(앞에서 계속 은닉 노드의 수는 j라고 가정하고 있습니다). 때문에 출력층은 j+1(편향)개의 원소를 받게 됩니다. 만일 이진분류라면 (j+1)*2개의 파라미터가 생성되며, 이를 토대로 확률 예측이 이루어집니다. 

     

      여기까지만 보면 RNN은 꽤 괜찮은 모형같습니다. 앞에 등장한 단어의 정보를 모두 가지고 있을 뿐더러 단어의 순서, 관계 정보 등을 반영하여 학습할 수 있기 때문입니다. 그러나 RNN의 히든 스테이트 벡터는 바로 직전 단어의 정보를 가장 많이 가지고 있고 이전에 등장한 단어로 갈수록 정보가 점점 적어집니다. 때문에 시퀀스 길이가 지나치게 길어지면 정보 소실이 일어나고 맙니다. 

     

    3. 심화 RNN

    RNN에서 이전 타임 스텝의 정보는 이전 타임 스텝의 히든 스테이트 벡터를 통해 넘어갔었습니다. 히든 스테이트 벡터는 이전부터 앞부분에 있는 단어들의 정보가 존재하는 상태이기는 하나, RNN이 진행될수록 앞부분에 있는 단어들의 정보가 점점 희미해집니다. 

    이상엽 교수님 수업자료입니다. plain RNN

      즉 이전 타임 스텝 히든 스테이트 벡터 하나만 넘기게 될 경우, 실질적으로 문장에서 중요한 정보를 가진 앞부분의 단어 정보가 제대로 전달되지 않을 수도 있다는 것입니다. 이를 해결하기 위해 h0부터 hT-1까지 매 타임 스텝의 모든 히든 스테이트 벡터를 넘기는 방법도 존재합니다. 

    모든 히든 스테이트 벡터를 다 사용하면 어떻게 될까요?

    모든 히든 스테이트 벡터를 사용하는 방법은 크게 2가지입니다.

     

    (1) 이어붙이기(concatenation)

    차원의 크기가 j, 타임 스텝 수는 t인 RNN이 있다고 가정합니다. 그렇다면 히든스테이트 벡터는 총 t개가 됩니다. 차원의 크기가 j로 모두 같으므로 이 히든 스테이트 벡터를 계속 옆으로 이어붙이면 j차원이 t개 있는 셈이므로 원소 수(차원)가 j*t인 히든스테이트 벡터가 완성됩니다. 이는 단순한 flatten을 통해 가능합니다. 

    (2) 평균(mean)

    이름에서도 알 수 있듯이 각 히든 스테이트 벡터 원소들을 다 더한 후 t개만큼 나누는 방법입니다. 원소 수(차원)는 j개로 유지되고, 원소 값만 달라집니다.

     

     

    (3) StackedRNN

    하지만 위의 방법들은 제법 심심합니다 ~_~ㅋㅋㅋ 보편적으로는 RNN의 한계를 개선하기 위해 RNN을 여러 층 쓰는 StackedRNN을 사용합니다. 

      첫 번째 층(RNN1)은 위에서 해왔던 RNN과 똑같이 동작합니다. 시퀀스 데이터의 단어 임베딩 벡터를 입력받아 RNN을 수행합니다. 두 번째 층(RNN2) 역시 RNN1과 마찬가지로 시퀀스 데이터를 입력받는데, 이때 입력받는 것은 첫 번째 층으로부터 전달된, 시퀀스 형태의 히든 스테이트 벡터입니다. 시퀀스 형태로 RNN1로부터 히든 스테이트 벡터를 전달받기 위해서는 return_sequences를 True로 두어야 합니다.  

    좀 더 깔끔히 나타내면 아래와 같습니다. 먼저 등장한 RNN1은 SimpleRNN으로, 64차원을 가집니다. 이때 인자에 return_sequence가 True이므로, 아래 등장하는 RNN2에 64차원의 시퀀스 히든 스테이트 벡터가 전달됩니다. 

     

    하지만 그럼에도 RNN의 단점이 완전히 개선되지는 않습니다. 이에 따라 나중에는 LSTM, GRU와 같이 RNN을 기반으로 몇 가지 장치를 더 추가한 모형들이 등장하게 됩니다. 

    'general ML, DL, NLP > 딥러닝' 카테고리의 다른 글

    13. CNN을 이용한 text 분류  (0) 2022.06.28
    12. LSTM(Long Short-Term Memory)  (0) 2022.06.28
    10. 이미지 분류 사전학습모형  (0) 2022.04.21
    9. CNN 코드 - cats & dogs  (0) 2022.04.21
    8. CNN 코드 - MNIST, Cifar-10  (0) 2022.04.21

    댓글

Designed by Tistory.