TigerCow.Door


안녕하세요. 문범우입니다.

이번 포스팅에서는 텐서플로우의 새로운 기능인 dynamic rnn에 대해서 알아보도록 하겠습니다.


* 해당 포스트의 모든 내용은 김성훈 교수님의 '모두를 위한 딥러닝'을 바탕으로 제작되었습니다.

관련한 상세 내용은 아래 링크를 참고해주세요.

https://hunkim.github.io/ml/



1. Dynamic RNN



우리가 그동안 다루어보았던 RNN모델을 다시한번 생각해보도록 하겠습니다.

이전의 모델을 이용해서 'hello'와 같은 문자열을 다루어볼때는, 우리가 다루고자하는 문자열의 크기에 따라서 RNN을 구성하였습니다.

하지만 실제의 데이터에서는 문자열의 크기가 가변적입니다.

예를 들어, 누군가가 전달하는 문자열 데이터를 처리한다고 했을 때, 그 데이터가 항상 고정된 길이는 아닙니다. 오히려 우리가 매번 고정된 길이로 보내달라고 한다면, 우리의 모델을 사용하는 사용자 입장에서는 매우 불편한 일이 될 것입니다.


이러한 것을 다루기 위해, 기존의 방법으로는 아래와 같이, 문자열의 뒤에 padding을 붙여주었습니다.


하지만 사실상 이러한 padding을 넣어도, 각 모델에 있는 weight에 의해서 어떠한 값이 나오게 됩니다.

그리고 이렇게 나오는 값 때문에 우리의 loss함수가 헷갈려할 수 있어 결과가 좋지 않을 수도 있습니다.


그럼 이것을 어떻게 해결할까요?


텐서플로우에서는 이것을 해결하기 위해 각 문자열의 길이를 구해서 sequence_length 라는 list로 만들어서 dynamic rnn 모델을 사용합니다.

코드를 통해 확인해보도록 하겠습니다.



이때 입력은 어떠한 문자열이라고 가정합니다.

그리고 cell을 만드는 것과 다른 과정도 이전의 알아본 것과 일치합니다.

하지만 rnn을 구현할때, dynamic_rnn을 사용하며 이때 앞에서구한 sequence_length를 넣은것을 볼 수 있습니다.


그리고 이에 따른 우측의 결과를 보시면, 길이가 5인 문자열에 대해서는 올바르게 결과가 나오고, 길이가 3인 문자열에 대해서는 앞의 3개 문자열에 대해서만 값을 주고 뒤의 2개의 값은 0으로 만듭니다.

그리고 길이가 4인 문자열에 대해서도 동일하게 맨 뒤의 1개에 대해서는 값을 0으로 만들어 버립니다.


즉, 문자열이 없는 곳은 아예 값을 0으로 만들어서 우리의 Loss함수가 잘 작동하도록 합니다.


블로그 이미지

Tigercow.Door

Back-end / Python / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

이번 포스팅에서는, 그 동안 배운 RNN 내용을 통해서, RNN을 보다 wide하고 deep하게 만들어 보도록 하겠습니다.


* 해당 포스트의 모든 내용은 김성훈 교수님의 '모두를 위한 딥러닝'을 바탕으로 제작되었습니다.

관련한 상세 내용은 아래 링크를 참고해주세요.

https://hunkim.github.io/ml/



1. Long sentence


우리가 지난 번 내용을 통해 'hihello'라는 문자열에 대해 RNN을 이용하여 문자열을 예측하는 모델을 구성해 보았습니다.


그럼, 이러한 모델이 아래와 같은 긴 문장에서도 잘 작동할까요?


결과는 No. 입니다.


위와 같은 긴 문장은 우리가 그전에 만들어보았던 모델에서 제대로 작동되지 않습니다. 왜 그럴까요?

간단하게 생각해보면, 우리의 모델이 보다 wide하거나 deep하지 않기 때문입니다. 즉, 위와 같은 긴 문자열을 다루기에는 우리의 모델이 너무 작습니다.


그럼 당연히 생각해볼 문제는, 우리의 RNN 모델을 더 쌓을수는 없을까? 입니다.



2. Wide & Depp RNN


그럼 RNN 모델을 어떻게 쌓을까요?

이는 어렵지 않습니다.

기존의 코드를 크게 수정할 필요도 없습니다.



이를 Stacked RNN 이라고 하는데, 위의 코드에서 보시다 시피 이전의 코드와 같이 cell을 만드는데 그 아래에서 MultiRNNCell이라는 함수를 새롭게 사용하고 있습니다.

해당 함수를 통해 우리가 얼마나 RNN을 쌓아올릴지 손쉽게 구성할 수 있습니다.



3. Softmax layer


또한 우리가 CNN을 알아보면서 Softmax layer를 사용했던 것처럼, 우리의 RNN모델을 통해 나온 결과를 그대로 사용하지 않고 그 뒤에 Softmax layer를 붙여주면 보다 더 잘 작동할 것 입니다.



이를 위해서 위의 그림과 같이 RNN 모델에서 나오는 결과 값을 softmax 에 넣기 위해 reshape을 진행합니다. 즉, X_for_softmax 를 먼저 만들어주고 이를 softmax layer를 통과시킨후 outputs으로 펼쳐줍니다.



이를 실제로 코드로 살펴보면 위와 같습니다.

위에서 말했던 것처럼, X_for_softmax에 RNN의 outputs를 넣어주며 reshape을 하고 softmax의 w와 b를 정해줍니다.

w를 정할때 입력사이즈(hidden size), 출력사이즈(num classes), 즉 우리가 예측하고자 하는 것의 one-hotd의 크기를 넣어줍니다.

그리고 bias의 값에는 출력사이즈를 넣어줍니다.

이렇게 softmax layer를 통과시키고 나서 다시한번 reshape를 통해 결과를 펼쳐줍니다.


그리고 이러한 outputs를 우리의 sequence_loss에 넣어줍니다.

이전에는 사실, RNN의 결과로 나온 outputs를 그대로 넣었는데 그 값들은 state 값을 가지고 있기 때문에 사실상 틀린 것 입니다. 위와 같이 softmax layer를 통과시켜서 나온 output을 logits으로 넣어주어야 합니다.


그리고 마지막에는 그전과 같이 훈련을 시켜주고, 결과를 출력해주면 됩니다.

블로그 이미지

Tigercow.Door

Back-end / Python / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

이번 포스팅에서는 RNN을 이용하여 hihello를 학습시켜 보도록 하겠습니다.


* 해당 포스트의 모든 내용은 김성훈 교수님의 '모두를 위한 딥러닝'을 바탕으로 제작되었습니다.

관련한 상세 내용은 아래 링크를 참고해주세요.

https://hunkim.github.io/ml/




1. 'hihello' 학습시키기

이번에는 위와 같이 우리가 hihello 라는 문자열을 주었을 때, 각 문자에 대해 다음 문자를 예측해보도록 학습시킬 것 입니다.

이 문제가 간단해보일 수 있지만, 좀 더 자세히 살펴보면 h를 입력했을 때, 어쩔때는 i를, 어쩔 때는 e를 반환해야 합니다. 이는 RNN의 특성인, 이전 문자가 무엇이 나왔는지 알아야 값을 제대로 출력할 수 있습니다.



2. RNN basic 정리


그럼 먼저 간단히 RNN의 기본적인 내용에 대해 정리해보도록 하겠습니다.

우리가 그동한 RNN을 공부하면서 그 자체에 대해서는 간단히 여겨질 수 있으나 실제로 RNN에 어떤 값을 어떻게 넣어줘야 할지 복잡할 수 있습니다.

하나씩 살펴보겠습니다.

우리가 넣고자 하는 text는 'hihello'입니다. 그리고 그 문자에는 5개의 유니크한 문자로 존재합니다. 그리고 이 문자열을 인덱스로 표현하면,

h:0 , i:1 , e:2 , l:3 , o:4 이고 이를 one-hot 인코딩으로 나타내면 위 그림과 같습니다.


우리가 전체적으로 구성할 모델은 위와 같을 것입니다.

그럼, 이제 입력 dimension, 출력 dimension, batch size 등에 대해서 생각해보도록 하겠습니다.

그림에서 보듯이 input dimension 은 5입니다.

그리고 총 6개로 구성되기 때문에 sequence = 6 입니다.

또한 hidden 또한 5 입니다.

마지막으로 batch size는 하나의 문자이므로 1 입니다.



3. RNN 만들기


먼저 rnn cell을 만듭니다.

이때 기본적으로 BasicRNNCell 을 이용할 수도 있겠지만, 많이 사용되는 LSTM 이나 GRU를 이용할 수도 있습니다. 이때 중요한 것은 rnn_size입니다.

rnn size는 출력값으로써 5로 정해집니다.


두번째로 중요한 것은 입력입니다.

이는 위에서 알아봤던 것처럼, input dimension = 5, sequence = 6 으로 넣어주면 될 것입니다.


그럼 이를 바탕으로 데이터를 만들어 보도록 하겠습니다.


먼저 입력, x_data 로 hihell을 인덱스로써 넣어주었고 이를 one_hot encoding으로 변환하여, x_one_hot 으로 구성하였습니다.

그리고 우리가 학습하고자 하는 결과값, y_data 또한 위와 같이 구성하였습니다.


그리고 X 와 Y에 우리가 설정한 값들을 넣어줍니다.

위에서 알아본 것과 같이 sequence_length = 6 이며, input_dim = 5 입니다.

이후, cell을 만들고 이때 결과의 크기, hidden_size를 입력합니다.

또한 위에서는 initial_state를 만드는데 전부 0으로 만들었습니다.

그리고 우리가 만든 cell과 state를 이용하여 결과를 내도록 하였습니다.


이렇게 만든 모델이 얼마나 잘 맞는지 알기 위해서 loss를 구해야 합니다.

즉, cost를 구해야하는데 텐서플로우에서는 이를 쉽게할 수 있도록 sequence_loss 라는 함수를 제공합니다.


sequence_loss 함수를 활용하여 위와 같이 구성합니다.

우리의 모델을 통해 나오는 outputs를 sequence_loss의 logits으로 넣어줍니다. 이는 우리의 예측값을 넣어주는 것 입니다.

그리고 targets는 우리의 훈련값을 넣어주는 것으로써 Y를 넣어줍니다. 그리고 여기서 weights는 단순히 1인 값으로 넣어주도록 합니다.


그리고 이것을 평균을 내서 AdamOptimize로 넣어줌으로써 loss를 최소화 시켜줍니다.



그리고 학습과정은 그 동안했던 것과 유사하게 진행해줍니다.



이를 통한 결과는 위와 같습니다.

결과의 초반에 보면 예측이 아주 잘못되고 있지만 시간이 지나면서 loss가 점점떨어지고, 예측또한 잘 되는 것을 볼 수 있습니다.


블로그 이미지

Tigercow.Door

Back-end / Python / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요