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을 이용하여 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

댓글을 달아 주세요


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

이번 포스팅에서는 텐서플로우를 이용한 기본적인 RNN모델에 대해서 알아보도록 하겠습니다.


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

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

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



1. RNN



우리가 이전, 이론에서 알아보았듯이 RNN 모델에서는 아웃풋이 다시금 영향을 주게 됩니다.

위에서 왼쪽과 같은 것을 cell이라고 표현하는데, 즉 cell의 아웃풋이 다시 cell에 영향을 주게 됩니다. 그리고 이것이 기존의 Neural Network과 큰 다른점 입니다.

그런데, 이것을 실제로 어떻게 구현할까요?

생각보다 의외로, 텐서플로우에서 쉽게 구현이 가능합니다.


텐서플로우에서 RNN을 구현할때, 크게 두가지 단계로 나눠볼 수 있습니다.

첫번째는 다음과 같은 코드입니다.


1
cell = tf.contrib.rnn.BasicLSTMCell(num_units=hidden_size, state_is_tuple=True)
cs


우선 위에서 말한 Cell을 만듭니다. 이때 cell은 어떤 형태인지 정할 수 있습니다. 기본적으로 위의 사진과 같이 RNN형태도 있으며 위의 코드와 같이 LSTM과 같은 형태도 있습니다.

그리고 이렇게 cell을 만들때 가장 중요한 점은, cell의 아웃풋(출력)의 크기가 얼마일지 정하는 것입니다. 이를 위의 사진 및 코드에서 볼 수 있듯이 num_units라고 하기도 하며 hidden_size라고 하기도 합니다.


그리고 두번째로, 방금 만든 cell을 실제로 구동하여 입력에 대한 출력값을 뽑아냅니다.


1
outputs, _states = tf.nn.dynamic_rnn(cell, X, initial_state=initial_state, dtype=tf.float32)
cs


이를 하기 위해 일반적으로 dynamic_rnn을 사용합니다.

이 함수를 이용하여 우리가 만들어준 cell을 넘겨주고 우리가 원하는 입력데이터를 넘겨줍니다. 

그럼 이 함수는 두개의 출력을 반환하는데, 하나는 결과 값인 outputs이며 하나는 해당 states의 값 입니다.

states값은 우리가 직접적으로 사용할 일은 별로 없고 일반적으로 outputs을 이용하게 됩니다.


이렇게 두단계로 나뉘게 된 이유는 여러가지가 있을텐데, 그 중 가장 중요한 이유중 하나는 cell을 만드는 단계와 cell을 이용하여 구동하는 단계를 나눠줌으로써 우리가 원하는 cell의 형태를 자유롭게 바꾸어가면서 모델을 구동할 수 있는 것 입니다.



2. Input&Output Data



이제 우리가 구현할 모델에 대한 입력 데이터를 살펴보도록 하겠습니다.

여기서는 우리가 문자열 데이터를 다루게 될 텐데, 이를 벡터로 다루기 가장 좋은 방법 중 하나가 one-hot encoding 입니다. 즉 위의 사진과 같이 알파벳을 표현합니다.


실제로, 김성훈 교수님 github에서는 아래와 같이 one-hot encoding을 이용하여 입력 데이터를 설정하였습니다.


1
2
3
4
5
6
7
x_data = [[010233]]   # hihell
x_one_hot = [[[10000],   # h 0
              [01000],   # i 1
              [10000],   # h 0
              [00100],   # e 2
              [00010],   # l 3
              [00010]]]  # l 3
cs


그럼 이에 따른 Output data의 dimension은 어떻게 될까요?

이는, 여러분이 정해주기 나름입니다.


우리가 cell을 만들때 hidden size를 정한다고 했습니다. output data의 dimension은 우리가 정한 hidden size에 따라 결정됩니다.

즉, input data의 dimension이 어떻든 간에 상관없이 output data의 dimension은 hidden size로 결정됩니다.


실제로 따로 training 없이, 단지 input data와 output data를 확인하기 위한 코드는 아래와 같습니다.

먼저, output data의 dimension을 결정할 hidden size를 결정하였습니다.

그리고 input data에 맞춰서 cell을 만들었습니다.

이후, input data를 만드는데 위에서는 dimension = 4 인 input data를 만들었습니다.

그리고 이를 구동하고 outputs를 출력해보면 우리가 hidden size를 2로 설정한 것과 같이 2개의 값이 나왔습니다.



실제로 cell의 shape을 확인해보면 위 그림의 왼쪽에 나온 것처럼, 3개의 숫자를 가지고 있습니다. 이때 맨마지막 값은 dimension으로써 우리가 hidden size를 통해 결정된다는 것을 알았습니다.


그럼 나머지 두개의 숫자는 무엇을 의미할까요?


먼저, 가운데에 있는 숫자는 sequence_length를 의미합니다.

우리가 사용하는 RNN의 가장 큰 장점은 우리가 시리즈 데이터를 받을 수 있는 것입니다. 즉, 우리가 받을 시리즈 데이터가 몇개인지를 의미하는 것이 sequence length로써 cell shape의 두번째에 위치하는 값입니다.

이는 우리가 입력데이터를 설정할때 주는 값으로 설정이 됩니다. 그리고 아웃풋데이터도 이를 따라가게 됩니다.



이를 포함한 코드를 살펴보면, 위와 같습니다.

여기서 x_data 를 설정한 코드를 보시면, [h, e, l, l, o] 라고 작성한 것처럼 직접 변수를 이용하여 sequence data를 넣어주고, 그 길이가 sequence length로 설정됩니다.

그리고 나머지는 위에서 확인했던 것과 같습니다.

모델을 구동시켜 나온 output를 확인해보면 그 sequence length 또한 5인것을 확인할 수 있습니다.


그럼 마지막으로, celld의 shape에서 첫번째 숫자가 의미하는 것을 알아보도록 하겠습니다.



우리가 학습을 시킬때, 한줄씩, 문자열 하나씩 학습시키기는 것은 너무나 비효율적입니다. 이를 효율적으로 하기 위해서는 한번에 여러개의 문자열을 학습시키는 것입니다. 이때 한번에 몇개의 문자열을 학습시킬 것인지 정하는 것을 batch size라고 하며 이것이 shape에서 첫번째 값이 의미하는 것 입니다.


위의 그림처럼 batch size를 3으로 함으로써 한번에 3개의 문자열을 입력하여 훈련하도록 합니다.


이또한 코드를 통해서 한번 더 확인해보도록 하겠습니다.



위와 같이 x_data를 설정할때 문자열을 3개 넣음으로써 batch_size가 3으로 설정된다는 것을 알 수 있습니다.

그리고 이에 맞춰서 결과에서 또한 3개의 output이 나오는 것을 볼 수 있습니다.


블로그 이미지

Tigercow.Door

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

댓글을 달아 주세요


안녕하세요.

이번 포스팅에서는 Neural Network에서도 가장 재밌고, 꽃이라고 하는 Recurrent Neural Network(RNN)에 대해서 알아보도록 하겠습니다.


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

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

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




1. Sequence(or Series) Data


우리가 사용하는 데이터들 중에서는 sequence data들이 매우 많이 있습니다.

예를 들어, 우리가 이야기하는 자연어에서도 단순히 하나의 단어에 대해서만 이해해서 전체적인 이해를 할 수 있는 것이 아니라, 그전에 이야기했던 단어들을 모두 이해해야 합니다. 이러한 데이터를 sequence data라고 합니다.


이전의 NN이나 CNN등 에서는 하나의 입력, x에 대해서 출력 y를 나타내는 간단한 형태였기 때문에 시리즈 데이터인, x0, x1, ..., xt등의 데이터를 처리하기 힘들었습니다.


그래서 이러한 시리즈 데이터를 처리하기 위해서 다음과 같은 모델이 고안되었습니다.



즉, 입력값에 대해서 현재의 state가 다음의 state에 영향을 미치는 것입니다.

이를 좀 더 펼쳐서 살펴보면 다음과 같습니다.


실제로는 우측과 같이 구현되는데, 위에서 언급한 바와 같이, x0 를 통해 계산된 것이 x1이 계산될때 영향을 미칩니다.

이러한 모델은 시리즈 데이터들을 다루는데 매우 효과적입니다.



2. Recurrent Neural Network


즉, 이러한 모델을 RNN(Recurrent Neural Network)라고 합니다.

이러한 모델은 어떻게 계산하는 것일까요?


RNN에서는 state라는 개념이 존재하는데, state를 계산하기 위해, 그 전에 있던 old state가 사용되고 입력값 x가 사용됩니다.

그리고 여기서 사용되는 함수, f는 전체적으로 동일합니다.


좀 더 구체적으로 값을 계산하는 방법에 대해서 알아보겠습니다.

가장 기초적으로는 Vanilla RNN입니다.


우리가 그동안 다뤘던 WX 와 같은 형태처럼, 입력값 h_(t-1)에 대해서 W_(hh)*h_(t-1)로 계산되고, x_t에 대해서는 W_(xh)*x_t와 같이 계산됩니다. 그리고 sigmoid와 비슷한 tanh에 두 값을 더해서 넣어줍니다.

그리고 결과값 yt에 대해서는 W_(hy)*h_t로 계산합니다.

이때 y가 몇개의 벡터로 나올 것인가는 우리가 설정하는 W에 따라서 결정됩니다.



3. Recurrent Networks



위에서 알아본 RNN은 매우 다양하게 활용될 수 있습니다.

위의 그림을 보시면, 첫번째는 우리가 그동안 다루었던 단순한 Neural Network같은 것으로부터 시작해, Image Captioning에서 이용되는 one to many 형태도 있으며, Sentiment Classification으로써 여러개의 단어를 통해 감정을 예측하는 등으로 활용되는 many to one, 그리고 many to many의 형태가 있습니다.


블로그 이미지

Tigercow.Door

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

댓글을 달아 주세요