42. TensorFlow에서 RNN 구현하기 (lab 12)


김성훈 교수님 동영상 정리는 이번이 마지막이다. 아마존 웹서비스를 사용하는 동영상이 더 있지만, 시기적으로 적절치 않아서 생략했다.


이번 동영상에서 구현할 RNN 모델이다. character 기반의 language model로 "hello"가 입력일 때의 결과를 예측하는 초간단, 초단순 RNN이다.


RNN에서 거쳐야 할 작업 중의 첫 번째다. 기본 cell을 비롯해서 이전 동영상에서 언급됐던 LSTM과 GRU cell을 사용할 수도 있다. 그림에 있는 rnn_size에 들어가는 값은 output layer의 크기가 된다.


이전 그림에 언급했던 것처럼 output layer의 크기인 4를 전달하고 있다. 동영상에 나오는 코드는 최신 버전에서 살짝 동작하지 않는다. tensorflow 사용법이 조금 바뀌었다. 그림에 나오는 사이트에 가면 동작하는 코드를 볼 수 있다. (소스코드 보기)


전체 코드에서 가장 중요하다고 말씀하신 X_split 변수에 대해 설명한다. 그림 아래에 위치한 값이 X_split을 의미한다. 1행 4열의 Tensor 객체를 4개 갖고 있는 리스트이다. 입력으로 들어오는 값이 h, e, l, o 중의 하나를 가리키고, 가리키는 방식으로 one-hot encoding을 사용하기 때문에 1행 4열이 된다.

그림 위쪽은 출력 결과이다. 결과 또한 one-hot encoding으로 나오기 때문에 1행 4열이다. 입력과 출력 모두 time-step size는 4개로 동일하다. 글자 4개를 한 번에 전달해서 결과로 4개를 돌려 받는다는 뜻이다. 입력과 출력의 갯수는 당연히 다를 수 있다. 1대N, N대N, N대1 등의 모델에 들어간 숫자를 보면 알 수 있다.


vocabulary는 데이터에 포함된 unique한 문자를 의미한다. word 기반이 된다면 unique한 단어가 될 것이다. 4개의 글자 중에서 하나를 가리키는 방식으로 특정 인덱스의 숫자만 1로 만든다(one-hot encoding). 1행 4열을 하나로 관리해야 하니까, x_data는 4행 4열의 2차원 배열이 된다. np는 numpy의 약자.


코드 순서와 그림에 배치된 layer 순서가 일치한다. rnn_cell은 output layer, state는 hidden layer, X_split은 input layer에 해당한다.

rnn.rnn은 0.9 버전에서 tf.nn.rnn으로 바뀌었다. RNN에서 가장 중요한 것은 자신의 상태를 매번 바꾸어 나가면서 매번 예측을 하는 것이었다. 여기서 보면 rnn 함수 호출로 예측에 해당하는 outputs와 새로운 상태인 state가 반환되는 것을 알 수 있다.


코드만 놓고 본다면, 전체 소스코드에서 이 부분이 가장 어렵다. logits는 y에 해당하는 예측값, targets는 정답을 갖고 있는 label, weights는 말 그대로 weight.

logits는 1x4로 구성된 배열이기 때문에 2차원 배열이어야 하고, targets는 각각에 대한 정답을 담고 있기 때문에 1차원 배열, weights 또한 입력에 대해 계산되는 값이기 때문에 1차원 배열이 된다.

sequence_loss_by_example 함수는 이들 배열을 한 번에 받아서 loss(erorr)를 한 번에 계산해 준다. 4개의 입력이 있었으니까, 이들을 모아서 최종 cost를 계산하고 optimizer가 가장 작은 cost를 찾는다. 이전 동영상에 나왔던 RMSPropOptimizer 함수를 사용하고 있다. sequence_loss_by_example 함수는 파이썬의 리스트를 매개변수로 받기 때문에 logits 등을 []로 감쌌다.


학습해서 중간 결과를 보여주는 코드는 이전과 유사하다. 다만 예측 결과로 나온 result는 문자에 대한 인덱스를 갖고 있는 리스트라서 해당 인덱스가 어떤 문자인지 검사하기 위해서 리스트 컴프리헨션(comprehension)을 사용하고 있다. 이 코드는 char_rdic[result[0]]과 같은 형태로 바꿀 수 있지만, 바꾸면 코드가 훨씬 길어진다. 출력이 4개니까.


전체 소스코드. 주석을 제거하면 얼마 안 된다고 교수님께서 강조하셨다. 말씀하신 것처럼 직접 입력해 보면 얼마 걸리지 않을 정도로 짧다.


이전 코드에서 100번 반복하기 때문에 출력 결과는 많이 생략되어 있다. 어찌 됐든 스스로 정답을 찾아가는 모습이 신기하다. 다만 착각하면 안 되는 것이, 이번 모델은 "hello"에 최적화되어 있어서 다른 문자열에 대해서는 동작하지 않는다.


RNN을 여러 층으로 쌓을 수 있고, 쌓는 방법 또한 무지하게 간단하다. 훨씬 복잡한 모델이 나타난다면 사용해야 할 방법이다.


셰익스피어를 학습하면 셰익스피어가 될 수 있다. 실제 만들어진 글을 보면 셰익스피어의 향기가 물씬 풍긴다. 이 부분에 대한 소스 코드는 없지만, 관련 글이 있는 곳은 찾았다. (셰익스피어 보기)


리눅스 소스코드를 학습하면, 프로그래밍도 가능하다고 한다. 이번 내용은 셰익스피어와 같은 사이트에 있다.


N대N 모델의 소스코드가 있는 곳이다. sherjilozair이 만든 코드를 교수님께서 수정하셨다고 했다.

원본 코드  https://github.com/sherjilozair/char-rnn-tensorflow
수정 코드  https://github.com/hunkim/word-rnn-tensorflow


교수님께서 시를 쓰는 모델을 만드셨다. 페이지에 들어가면 몇 가지 문장을 선택하라고 한다. 말이 되거나 좋아보이는 것을 선택하면, 그 내용으로 학습해서 신춘문예에 내신다고 한다. 직접 좋아하는 시를 입력해서 학습시킬 수도 있다. (신춘문예 2017 후보 시봇)

시봇 알고리즘에 기여하고 싶거나 소스코드가 보고 싶다면 아래 링크로 간다.

  https://github.com/DeepLearningProjects/poem-bot


N대1 모델의 소스코드가 있는 곳의 주소다. (07_lstm.py) mnist 손글씨 이미지를 LSTM 모델을 사용해서 분류하는 코드를 볼 수 있다. 그런데, 이곳은 이전 동영상에서 다운 받아야 한다고 알려준 적이 있는 곳이다.


RNN으로 할 수 있는 다양한 영역을 보여준다. 프로그래머가 아닌 일반인들이 훨씬 좋아할 만한 주제들이다.


다음 동영상에 대해 간단하게 설명하셨다. 아마존 웹서비스를 사용해서 머신러닝을 할 수 있다고.