앞서 다루었던 DNN과 CNN은 입력층에서 출력층 방향으로 연산이 전개되는 피드포워드 방식의딥러닝 모형이었다면 순환 신경망 (Recurrent Neural Network, RNN)은 은닉층의 뉴런이 순환 고리를 통해 이전의 정보가 재입력되는 순환구조 형태의 딥러닝이다. 즉, 순환 신경망은 은닉층의 노드에서 나온 결과값을 출력층 방향으로 보내면서 동시에 다시 은닉층 노드의 입력으로 보낸다.
[그림 1] 순환 신경망의 구조
[그림 1]의 왼쪽 그림은 은닉층을 하나의 박스로 취급하여 단순화시킨 것이고, 오른쪽 그림은 이를 시간의 흐름 (Time Step)에 따라 펼쳐서 표현한 RNN의 구조이다. RNN의 은닉층에는 순환 뉴런 (Recurrent Neuron)이 존재하는데, 순환 뉴런은 각 타임 스텝 t마다 입력 벡터 xt와 이전 타임 스텝의 출력 벡터인 yt-1을 입력으로 받는다. 이에 따라 가중치도 입력 벡터에 대한 가중치와 이전 타임 스텝의 출력 가중치를 가진다. 이 순환 뉴런은 각 시점에 걸쳐 과거의 값을 기억하는 메모리 역할을 수행하므로 메모리 셀 (Memory Cell) 또는 간단히 셀이라고 한다.
RNN은 고정 길이 입력이 아니라 임의 길이를 가진 시퀀스 (Sequence) 단위로 입력과 출력을 처리하며, 음성 인식, 손글씨 인식, 제스처 인식과 같이 시간에 따라 연속성을 가지는 데이터 혹은 길이가 가변적인 데이터를 학습 및 처리하는 작업에 적합하다.
RNN은 입력과 출력의 길이를 다르게 설계할 수 있으므로 다양한 용도로 사용할 수 있다. 아래 그림은 입력과 출력의 길이에 따라서 달라지는 RNN의 다양한 형태를 보여준다.
[그림 2] 입출력 길이에 따른 RNN 구조
- 일 대 다 구조: 하나의 입력만 받아서 다수의 결과값을 출력하는 구조로 하나의 이미지 입력에 대해서 사진의 제목을 출력하는 이미지 캡셔닝 (Image Captioning)과 같은 주제에 활용될 수 있다.
- 다 대 일 구조: 여러 개의 입력 데이터를 고려하여 하나의 결과값을 도출하는 구조로 입력 문서가 긍정적인지 부정적인지를 판별하는 감성 분류 또는 스팸 메일 분류 등에 활용할 수 있다.
- 다 대 대 구조: 여러 개의 입력 데이터를 통해 여러 개의 결과값을 도출하는 구조로 주식 가격이나 시계열 데이터 예측에 사용될 수 있으며, 문장 번역이나 하나의 단어가 입력된 후 그다음에 오게 될 단어를 예측하는 언어 인식과 같은 정보처리에 적합하다.
실습은 가상의 리뷰 데이터를 가지고 감성 분석(분류)를 해보겠다.
모형 학습 및 예측
#1. 모듈 및 함수 불러오기
from keras.layers import Embedding, SimpleRNN
#2. 모형 생성
model = Sequential()
model.add(Embedding(10000, 128))
model.add(SimpleRNN(128, activation='tanh'))
model.add(Dense(1, activation='sigmoid'))
#3. 모형 학습 과정 설정
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
#4. 모형 학습 및 예측
history = model.fit(X_train, Y_train, epochs=5, batch_size=300)
Y_classes = model.predict_classes(X_test, verbose=0)
print("평가용 데이터 세트에 대한 예측 클래스\n", Y_classes[:5])
▶ 1. RNN 모형을 구축하기 위한 keras.layers 모듈의 SimpleRNN 함수와 Embedding 함수를 임포트한다. 각 함수에 대한 설명은 다음과 같다,
- SimpleRNN( ): 기본적인 RNN 모형을 생성하기 위한 함수
- Embedding( ): 단어를 벡터로 표현하는 방법 중 하나인 워드 임베딩 (Word Embedding)을 수행하는 층을 생성하는 함수이다. 워드 임베딩은 정수로 인코딩된 텍스트 데이터를 입력받아 사용자가 설정한 특정 차원의 실수값으로 이루어진 밀집 벡터 (Dense Vector)를 만든다. 즉, 임베딩층은 정수를 입력으로 받아 이 정수에 연관된 벡터를 반환하는데, 보통 벡터의 크기는 128, 256, 512를 주로 사용하며, 다루는 단어의 수가 특별히 많을 경우 1,024를 사용하기도 한다.
▶ 2. Sequential( ) 함수를 통해 생성한 모형에 층을 순서대로 추가한다. Embedding 함수는 총 단어의 수(단어의 최대 정수 인덱스에 1을 더한 값)와 출력 벡터의 크기를 인자로 가지는데, 여기에서는 총 단어의 수는 10000으로, 벡터의 크기는 128로 지정했다. 그리고, SimpleRNN( ) 함수로 tanh 활성화 함수를 갖는 순환층을, Dense( ) 함수로 시그모이드 활성화 함수를 갖는 출력층을 추가하였다.
▶ 3. 구축하고자 하는 모형은 이진 분류(부정적/긍정적)를 수행하는 모형이므로 손실 함수로 ‘binary_crossentropy'를 설정하였다.
모형 평가
train_score = model.evaluate(X_train, Y_train, verbose=0)
test_score = model.evaluate(X_test, Y_test, verbose=0)
print("학습용 데이터 세트 오차와 정확도: {:.3f}, {:.3f}".format(train_score[0], train_score[1]))
print("평가용 데이터 세트 오차와 정확도: {:.3f}, {:.3f}".format(test_score[0], test_score[1]))
This post was written based on what I read and studied the book below.
http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9791195511747
댓글