이전 포스팅에서 RNN의 기본 구조와 교재의 예시를 통해 이해하고자 하였지만... 뭔가 직관적으로 이해하기가 힘들어 진도를 빼지 못하고 있었다... 정말 운 좋게 정리를 잘 해놓아주신 분의 글을 발견하였다..! RNN의 기본 구조, 입력값과 출력값 등에 대해서 다시 한 번 공부해봐야겠다..ㅠ
RNN Tensorflow + Keras
이번 포스팅은 Tensorflow의 keras를 이용하여 RNN의 다양한 구조를 구현해보는 것이 목표입니다. RNN에는 크게 세 가지 방법이 있는데 simple RNN, LSTM, GRU가 있습니다. 이번 실습은 simple RNN을 이용하여 ma
yjjo.tistory.com
텐서플로와 케라스를 활용하여 RNN을 구현할 때 입력 데이터의 구조에 대해서 궁금했었다. 책에서는 이전 층의 출력과 해당 층에서의 입력값이라고만 해놔서 이해하기가 어려웠는데
기본적인 입력 데이터의 구조는 (batch size, time_steps, input_length) 이다.
참고하는 포스팅에서는 시퀀스 - 투 - 벡터, 시퀀스 - 투 - 시퀀스와 같은 용어를 Many와 One으로 표현하셨다.
그러니까 시퀀스 - 투 - 벡터 모델은 Many - to - One 과 같다고 생각하면 될 것 같다.
여기서 many와 one은 입력 데이터의 타임 스텝과 관련이 있는데 many - to - one 모델은 입력 데이터의 타임 스텝이 1보다 크고, 출력 데이터의 타임 스텝이 1이라는 것을 의미한다. (시퀀스 - 투 - 벡터)
그렇다면 간단한 예시를 통해 RNN을 이해해보자.
Many - to - One 구조
입력 데이터의 형태 (batch size, time steps, input length), t > 1
출력 데이터의 형태 (batch size, 1, 1)
[1, 2, 3] -> [4]
[2, 3, 4] -> [5]
[3, 4, 5] -> [6] 처럼 다음에 등장할 숫자를 맞추는 many - to - one 을 구현해보겠다.
( [1, 2, 3] 이 many, [4] 가 one 이 아니다!!! 3개의 벡터 행렬 (many)를 활용하여 출력으로 하나의 [4, 5, 6] 행렬을 예측하기 때문에 many to one 구조인 것이다!)
이제 이 모델을 시각적으로 확인해보자.
각 타임 스텝마다 하나의 값만 존재하므로 단변량 시계열이다.
(아! 해당 예제를 보면 time step 1 ,2 ,3 이 각각 다른 층이 아니고 한 층을 시간의 순서에 따라서 진행되는 과정을 펼쳐서 나타낸 것이다. 그래서 아래 실습과정에서 층이 하나밖에 없는 것이다. (출력층 제외))
이번엔 이 모델에 사용될 기본 데이터를 준비해보자.
x = 학습 데이터
y = 검증 데이터
그 다음 SimpleRNN이나 LSTM, GRU 등 RNN을 사용하여 모델을 만들어보자.
은닉 유닛이 100개인 하나의 SimpleRNN 층과 해당 층에서 출력된 100개의 노드를 하나로 묶어주기 위한 Dense(1) 층을 설정하였다. 이어서 손실 함수로는 mean squared error과 adam 옵티마이저를 사용하였다.
그다음 학습 데이터 x를 적용시켜보고 테스트 데이터를 넣어 7이 나오는지 확인해보자.
참고한 포스팅에서는 input_shape = [3,1] 로 지정하셨는데 순환 신경망은 어떠한 길이의 타임 스텝도 처리할 수 있기 때문에 나는 [None, 1] 로 설정하였다. (실제로 참고 포스팅의 결과와 비슷하다.)
(결과에 대해서,,, 입력 데이터도 적고 최적화된 구조도 아니라 결과가 좋지는 않다! (그래도 반올림하면 456이 나오긴 한다) 구조 파악용으로만 참고하자.)
이번엔 층의 수를 추가해서 다시 한 번 진행해보자.
return_sequences는 이전 포스팅에서도 설명하였지만 해당 층에서 출력을 할 것인지를 설정하는 파라미터이다.
디폴트 값으로는 return_sequences=False (2D로 출력) 이며 해당 경우에는 마지막에서만 output를 출력한다.
해당 예에서는 첫 번째 RNN 층에서는 모든 타임 스텝에 대하여 출력값을 허용 (return_sequences= True) 하여 다음 층에 입력값으로 사용하기 위해 사용되었지만 다음 층에서는 지정하지 않아 결국 벡터 형태로 출력될 수 있는 것이다.
(만약 시퀀스 형태로 출력하기 위해서는 모든 층에 대하여 return_sequences = True를 지정해주고 마지막 출력층에서 TimeDistributed 로 감싸줘야 한다.)
큰 차이는 없지만 그래도 매우 미세하게 향상되었다.
Many - to - Many 구조
Many - to - Many 의 입력 데이터와 출력 데이터의 형태는 모두
(batch_size, time_steps, length) , time_steps > 1 이다.
[1, 2, 3] -> [2, 3, 4]
[2, 3, 4] -> [3, 4, 5]
[3, 4, 5] -> [4, 5, 6] 처럼 다음에 등장할 숫자들을 맞추는 Many - to - Many 구조를 구현해보겠다.
마찬가지로 기본 데이터를 준비한다.
시퀀스 - 투 - 시퀀스, 즉 many - to - many 구조는 이전의 구조와는 다르게 return_sequences와 TimeDistributed가 추가되었다.
전자는 위에 설명하였으니...
TimeDistributed 함수는 각 타임 스텝에서 출력된 아웃풋을 내부에 선언해준 레이어와 연결시켜주는 역할을 한다. 그러므로 위의 그림에서 return_sequences =True로 지정하였으므로 각 타임 스텝에서 [2, 3, 4] , [3, 4, 5], [4, 5, 6] 이 각각 출력이 되는데 이 아웃풋 값들을 선언한 Dense(1)에 연결시켜 각각의 출력값들에 적용시킨다. (이를 효율적으로 하기 위하여 각 타임 스텝을 별개의 샘플처럼 다루도록 입력의 크기를 바꾸어 준다. ex. [배치 크기, 타임 스텝, 입력 차원] --> [배치 크기 x 타임 스텝, 입력 차원] 으로 변환
즉, TimeDistributed 함수를 사용함으로써 모든 셀의 아웃풋을 사용한다는 의미가 된다. (xx -투 - 시퀀스 모델을 만들기 위해서 해당 함수를 사용해야 하는 것 같다.)
이번에도 모델을 만들어 정확도를 확인해보자
마찬가지로 한 층 더 쌓아보았다.
비슷한 결과이지만 이는 데이터가 적고 모델이 적합하지 않기 때문에 발생한 것이다. 보통 심층 RNN이 단층보다 정확도가 높으므로 참고하자.
다시 한 번 꿀같은 포스팅 너무 감사드립니다... :)
'핸즈온머신러닝&딥러닝' 카테고리의 다른 글
RNN과 어텐션을 사용한 자연어 처리 1 (0) | 2021.05.02 |
---|---|
RNN과 CNN을 사용해 시퀀스 처리하기 2 (0) | 2021.04.30 |
RNN과 CNN을 사용해 시퀀스 처리하기 1 (+내용추가) (0) | 2021.04.26 |
합성곱 신경망을 사용한 컴퓨터 비전 4 (0) | 2021.04.20 |
합성곱 신경망을 사용한 컴퓨터 비전 3 (0) | 2021.04.15 |