관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

순환 신경망(RNN) 2 - 순환 신경망의 활용 : 임베딩, 양방향 RNN, 스태킹 RNN, 순환 드롭아웃 본문

인공지능/딥러닝

순환 신경망(RNN) 2 - 순환 신경망의 활용 : 임베딩, 양방향 RNN, 스태킹 RNN, 순환 드롭아웃

huenuri 2024. 12. 18. 13:34

앞에서 simpleRNN, LSTM, GRU 순환 신경망 구조에 대해 간단하게 알아보았다. 이제 예제를 통해 순환 신경망을 활용하는 방법을 알아보자.


 

 

 

 

1. 임베딩

컴퓨터는 우리가 사용하는 한글, 영어 등을 그대로 이해하지 못한다. 컴퓨터가 이해하는 벡터로 변경해야 하는데 그것을 임베딩(Embedding)이라고 말한다. 임베딩이 잘 될수록 모델의 성능 또한 높아지고 훈련도 잘되기 때문에 임베딩과 관련된 여러 가지 방법들이 개발되어 왔다.

크게는 단어 수준의 임베딩(Word2Vec, FastText)과 문장 수준의 임베딩(Elmo, Bert, GPT 등)으로 구분할 수 있다. 단어 수준의 임베딩은 동음이의어를 구별할 수 없지만, 문장 수준의 임베딩은 사람처럼 문장의 맥락을 보고 이를 파악할 수 있다.

단어 수준의 임베딩을 위해 단어, 음절, 형태소 등으로 나누고 이를 수치로 변환한다. 가장 간단한 벡터 변환 방법은 원핫(one-hot) 인코딩이다.

 

이 방법은 매우 간단하지만 단어가 많아질수록 벡터의 공간이 커지고 비효율이 발생하는 문제가 있다. 원핫 인코딩은 행렬 값이 대부분 '0'인 희소행렬(sparse matrix)이라고도 부른다. 엄청난 크기의 희소행렬은 메모리 낭비가 심하고, 또한 원핫 인코딩은 단어와 단어의 유사도를 알기 어렵다는 한계가 있다.

 

 

 

반대로 단어를 밀집행렬로 표현할 수도 있는데, 이때 행렬은 0이 아닌 실수값으로 채워진다. 밀집행렬 형태는 단어와 단어의 유사도를 알 수 있고, 자원의 낭비가 작다는 장점이 있다. 텐서플로(케라스)에서는 임베딩 레이어를 제공하고 있는데, 희소행렬이 아닌 밀집행렬로 구현되어 있다.

 

 

 

 

임베딩 레이어에는 두 가지 파라미터 값이 필요하다. 첫 번째는 입력 차원(단어의 총 수)이고 두 번째는 임베딩 차원이다. 다음 [그림 5-14]에서 N개의 입력 차원을 3차원 임베딩 공간으로 매핑하는 것을 확인할 수 있다. 즉, N개의 단어로 구성된 문장을 3개의 원소를 갖는 벡터로 변환하는 개념이다.

다음 예제에서는 tensorflow.keras.layers로부터 임베딩 레이어를 가져와서 사용한다. 임의의 4개의 숫자 12, 8, 15, 20을 임베딩 레이어에 통과시키면 각각 원소 3개를 가진 벡터로 변환되어 밀집행렬로 정리되는 것을 알 수 있다.

 


 

 

 

 

 

임베딩 레이어는 input_dim, output_dim, input_length 파라미터가 있다. input_dim은 단어 사전의 크기이고, output_dim은 출력 벡의 크기를 말한다. 여기서는 3을 지정했다.

 

임베딩 레이어를 모델에 적용해보자. 일반적으ㄹ도 자연어 처리 모델에서는 데이터를 입력하는 부분에 임베딩 레이어를 활용한다. 또한 모델에 따라 입력 길이(input_length)를 설정해야 할 수도 있고 그렇지 않을 수도 있다.

 

 

 

 

책에서도 역시 오래된 버전이라 그런지 최신 버전의 코드를 반영하지 못해서 수정했는데 계속 틀리고 있다. input 대신 Input 클래스를 사용해야 한다.

 

 

 

 

 

 

다음과 같이 라이브러리를 미리 호출해 활용할 수도 있다. 

 

하지만 오류가 뜨고 있다. 이건 앞에서 했던 방식으로 하면 코드 오류가 뜬다. 이처럼 수정했다. 여러 번 수정 끝에 이처럼 수정했다. 여기서 중요한 것은 Input 클래스를 import 해야 사용할 수 있다는 것이다.

 

 

 


 

 

 

 

 

2. 양방향(Birdrectional) RNN

자연어 데이터의 경우 순서대로 데이터를 처리하고, 역순으로 처리할 경우 더 좋은 성능을 발휘하기도 한다. [그림 5-15]는 (a) 순차적인 RNN 구조와 (b) 양방향 RNN 구조를 보여주고 있다.
텐서플로에서는 tensorflow.keras.layers에 양방향 레이어(Bidirectional)를 제공하고 있고 RNN 레이어를 감싸면 쉽게 양방향 RNN을 만들 수 있다.

 

[그림 5-15] Structure Overview

  • (a) 단방향 RNN : 입력이 순차적으로 왼쪽에서 오른쪽으로만 흐름
  • (b) 양방향 RNN : 입력이 양방향으로 처리되며, 순방향과 역방향 모두 반영

 

 

 

다음 빈칸에 알맞은 단어는 무엇일까? 영화, 친구, 텐서플로 창시자 등 다양한 단어를 생각할 수 있다. 왜 그렇게 생각할 수 있을까? 앞에 나온 “나는”이란 단어만 가지고는 예측할 수 없지만 뒤에 나오는 “보고싶다”라는 단어를 바탕으로 다양한 단어를 추측할 수 있기 때문이다.

 

문장에서 다음 단어를 예측하기 위해서 앞에 있는 단어뿐 아니라 뒤에 있는 단어도 매우 중요하기에 양방향 RNN은 자연어에서 주로 활용되는 방법이다.


 

 

 

 

코드를 이처럼 수정했다. 

 

 

 

 

모델의 summary() 결과에서 LSTM과 같이 유닛의 개수는 32로 지정해서 모델을 만들었지만 유닛의 개수가 64개가 된다. 순방향과 역방향으로 각각 LSTM 모델이 만들어졌기 때문이다.


 

 

 

 

3. 스태킹 RNN

Dense 레이어처럼 RNN 레이어 또는 양방향 RNN을 여러 층으로 쌓아서 모델을 만들 수 있다. 이때 중요한 점은 다른 레이어처럼 쌓기만 하면 에러가 발생한다. 기본적으로 RNN은 마지막 상태 값만 출력하기 때문이다. [그림 5-17]에서 보듯, 마지막 출력(④)을 제외하고는 ①~③ 출력은 무시한다.

 

 

 


 

 

 

 

 

책 코드로 하면 아무것도 출력되지 않는다. 입력 크기를 명시하지 않았기 때문이다.


 

 

 

 

 

4. 순환 드롭아웃

내장 RNN은 기본적으로 텐서플로 레이어에서 제공하는 유용한 기능인 dropout 외에 recurrent-dropout을 제공하고 있다. dropout은 입력에 대한 드롭아웃 비율이고, recurrent-dropout은 순환 상태의 드롭아웃 비율을 뜻한다. 모두 0과 1 사시의 부동 소수점이고 과대 적합을 방지하기 위해 내장된 기능이다.


 

 

 

 

학습을 마치고

1시까지는 다 마치고 싶었는데 코드 오류가 많아서 수정하느라 시간이 좀 지체되었다. 그래도 실습을 진행하며 RNN의 입력층과 출력층 등의 구조에 대해 파악해볼 수 있었다. 그리고 어떻게 하면 오류가 나지 않는지도. 경고 표시로 된 것도 없도록 수정하고 싶어서 힘들지만 이렇게 작성했다.

다음 장에서는 자연어 처리에 대해서 배우게 되는데 조금 쉬었다가 해볼 생각이다.