[Tensorflow] 5. 순환신경망(RNN, Recurrent Neural Network)

2023. 8. 21. 00:29·AI/Deep Learning

안녕하세요! 오랜만에 돌아온 딥러닝 포스팅입니다.

최근에 알약 인식을 위한 프로젝트를 진행하고 있어서 딥러닝 관련 서적을 많이 찾아보게 되는데요..

이번에도 공부하면서 심플하게 풀어내고자 작성하게 되었습니다.

 

순환신경망(RNN)은 주식과 같은 시계열 데이터나 문장과 같은 자연어 데이터와 같이 순서가 있는 데이터를 입력으로 받으며 동일 네트워크 구조를 이용하여 변화하는 입력에 대한 출력을 학습하는 방식입니다. 또한 순환신경망의 구조는 아래와 같이 표현할 수 있으며 기존과 다르게 $x_{t-1}$의 데이터를 사용하여 얻은 값인 $h_{t-1}$이 다음 출력값($h_t$)을 계산하기 위해 $x_{t}$와 함께 전달되고 있는 모습을 보입니다.

출처 : https://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/Recurrent_neural_network_unfold.svg/1600px-Recurrent_neural_network_unfold.svg.png

 

 

이제 SimpleRNN, LSTM, GRU 레이어를 통해 대표적인 순환신경망의 3가지 종류에 대해서 간단하게 알아봅시다.

 

이미지 출처 : https://miro.medium.com/max/1400/1*HRuDxU1i4JNu-Ywt88LnaQ.png

 

 

이미지 출처 : https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/LSTM_Cell.svg/1200px-LSTM_Cell.svg.png

 

 

이미지 출처 : https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Gated_Recurrent_Unit%2C_base_type.svg/2880px-Gated_Recurrent_Unit%2C_base_type.svg.png

 

이것으로 개념은 간단하게 알아보았고 책에서 소개한 곱셈 문제를 통해 세 레이어를 사용한 모델을 학습시키려고 합니다.

우선 곱셈문제에 대해 간단하게 소개하자면 랜덤으로 실수 100개를 만들고 그 중 임의의 2개를 실수를 곱한 값을 정답으로 하는 문제입니다. 참고로 모델을 학습시키기 위해 100개의 실수 [0.2, 0.5, ..., 0.2]와 두 개의 1이 있는 마킹 데이터 [0,1, ..., 0]을  입력합니다.

# SimpleRNN, LSTM, GRU 실습
# 곱셈 문제 : 100개의 실수중 2개의 실수를 뽑아 곱한 결과를 맞추는 문제
x = list()
y = list()
for i in range(3000) :
    lst = np.random.uniform(low=0, high=1, size=100)   # 0~1 사이 난수 100개 생성
    index = np.random.choice(100, 2, replace=False)    # 0~100 사이 정수 2개 추출
    zeros = np.zeros(100)                              # [0, 0, ..., 0]
    zeros[index] = 1                                   # 2개의 인덱스에 해당되는 값을 1로
    x.append(np.array(list(zip(zeros,lst))))           
    y.append(np.prod(lst[index]))                      # 2개의 실수를 곱한 값을 y에 저장
    
x = np.array(x)
y = np.array(y)

 

x와 y를 생성하여 저장했으면 본격적으로 모델을 생성하겠습니다.

각 모델은 SimpleRNN, LSTM, GRU 레이어를 사용하여 만들었으며 순환신경망 2겹을 쌓았습니다.

# SimpleRNN
model_simplernn = tf.keras.Sequential([
    tf.keras.layers.SimpleRNN(units=30, return_sequences=True, input_shape=[100,2]),
    tf.keras.layers.SimpleRNN(units=30),
    tf.keras.layers.Dense(1)])
# LSTM
model_lstm = tf.keras.Sequential([
    tf.keras.layers.LSTM(units=30, return_sequences=True, input_shape=[100,2]),
    tf.keras.layers.LSTM(units=30),
    tf.keras.layers.Dense(1)])
# GRU
model_gru = tf.keras.Sequential([
    tf.keras.layers.GRU(units=30, return_sequences=True, input_shape=[100,2]),
    tf.keras.layers.GRU(units=30),
    tf.keras.layers.Dense(1)])

model_simplernn.compile(optimizer=tf.keras.optimizers.Adam(),
              loss = tf.keras.losses.mean_squared_error)
model_lstm.compile(optimizer=tf.keras.optimizers.Adam(),
              loss = tf.keras.losses.mean_squared_error)
model_gru.compile(optimizer=tf.keras.optimizers.Adam(),
              loss = tf.keras.losses.mean_squared_error)

model_simplernn.summary()
model_lstm.summary()
model_gru.summary()

  • 제일 복잡한 구조인 LSTM 레이어로 구축한 모델의 파라미터 개수가 11311개로 GRU레이어로 구축한모델(8671개), SimpleRNN레이어로 구축한모델(2851개)보다 많은 것을 알 수 있습니다.
  • 정답 데이터인 y는 하나의 실수로 이루어져 있으므로 마지막 층인 Dense 레이어에서 유닛이 1개입니다.
  • 손실함수는 MSE를 사용하였습니다.

 

모델을 구축했으니 데이터셋을 이용해서 학습하는 코드입니다. 참고로 간단한 데이터 셋임에도 상당한 소요시간을 보입니다

history_simplernn = model_simplernn.fit(x, y, epochs=50, validation_split=0.35)
history_lstm = model_lstm.fit(x, y, epochs=50, validation_split=0.35)
history_gru = model_gru.fit(x, y, epochs=50, validation_split=0.35)

압도적인 학습 시간... 코랩으로 돌리세요..!

 

마지막으로 학습하면서 생긴 손실과 정확도를 시각화하는 코드입니다.

import matplotlib.pyplot as plt
plt.figure(figsize=(14,4))
plt.subplot(1,3,1)
plt.plot(history_simplernn.history["loss"], "b-", label="loss")
plt.plot(history_simplernn.history["val_loss"], "r--", label="val_loss")
plt.xlabel("Epoch")
plt.title("SimpleRNN Loss")
plt.ylim(0,0.1)
plt.legend()

plt.subplot(1,3,2)
plt.plot(history_lstm.history["loss"], "b-", label="loss")
plt.plot(history_lstm.history["val_loss"], "r--", label="val_loss")
plt.xlabel("Epoch")
plt.title("LSTM Loss")
plt.ylim(0,0.1)
plt.legend()

plt.subplot(1,3,3)
plt.plot(history_gru.history["loss"], "b-", label="loss")
plt.plot(history_gru.history["val_loss"], "r--", label="val_loss")
plt.xlabel("Epoch")
plt.title("GRU Loss")
plt.ylim(0,0.1)
plt.legend()

plt.show()

  • GRU와 LSTM으로 구축한 모델에서 성과가 뛰어납니다!

 

끝으로 지금까지 알아본 3가지 레이어를 다음과 같이 정리하였습니다.

 

저작자표시 비영리 변경금지 (새창열림)

'AI > Deep Learning' 카테고리의 다른 글

[Tensorflow] 4. Convolutional Neural Network (CNN)  (0) 2023.08.11
[밑시딥1] 챕터 5~8 요약  (0) 2023.03.26
[밑시딥1] 챕터 1~4 요약  (0) 2023.03.26
[Tensorflow] 3. 분류 (Classification)  (0) 2023.01.07
[Tensorflow] 2-1 Regression with Boston housing datasets  (0) 2023.01.07
'AI/Deep Learning' 카테고리의 다른 글
  • [Tensorflow] 4. Convolutional Neural Network (CNN)
  • [밑시딥1] 챕터 5~8 요약
  • [밑시딥1] 챕터 1~4 요약
  • [Tensorflow] 3. 분류 (Classification)
임파카
임파카
[ML & Statistics] 모바일 버전에서 수식 오류가 있어 PC 환경에서 접속하는 것을 권장합니다.
  • 임파카
    무기의 스탯(Stat)
    임파카
  • 전체
    오늘
    어제
    • Study (149)
      • Data Science (44)
        • Modeling (18)
        • Manipulation (21)
        • Visualization (4)
      • Statistics (59)
        • Mathmetical Statistics (53)
        • Categorical DA (1)
      • Web Programming (17)
      • AI (26)
        • Machine Learning (16)
        • Deep Learning (10)
      • 활동 및 프로젝트 (3)
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
임파카
[Tensorflow] 5. 순환신경망(RNN, Recurrent Neural Network)
상단으로

티스토리툴바