Colab으로 하루에 하나씩 딥러닝

RNN_셀 구현(SimpleRNNCell) 본문

딥러닝_코드

RNN_셀 구현(SimpleRNNCell)

Elleik 2022. 11. 27. 02:23
728x90

라이브러리 호출

import os 
os.environ['TF_CPP_MIN_LOG_LEVEL'] = "3"   # 케라스에서 발생하는 경고 메세지를 제거

import tensorflow as tf
import numpy as np
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam

값 초기화

tf.random.set_seed(22)
np.random.seed(22)
assert tf.__version__.startswith('2.')   # 텐서플로 버전이 2임을 확인

batch_size = 128
total_words = 10000
max_review_len = 80
embedding_len = 100

데이터셋 준비

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.imdb.load_data(num_words=total_words)
# IMDB 데이터셋을 내려받음
# num_words: 데이터에서 등장 빈도 순위로 몇번째에 해당하는 단어까지 사용할지 의미 -> 1~10000에 해당하는 단어만 사용

x_train = tf.keras.preprocessing.sequence.pad_sequences(x_train, maxlen=max_review_len)
x_test = tf.keras.preprocessing.sequence.pad_sequences(x_test, maxlen=max_review_len)
# 패딩(padding) 작업 실시 -> 0을 넣어서 길이가 다른 샘플들의 길이를 맞춤
# pad_sequence: 정해 준 길이보다 길이가 긴 샘플은 값을 일부 자르고, 정해 준 길이보다 길이가 짧은 샘플 값을 0으로 채움
#   첫번째 인자: 패딩을 진행할 데이터
#   maxlen: 모든 데이터에 대해 정규화할 길이

train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train))
# 넘파이 배열을 Dataset으로 변환, 변환하려는 전체 데이터를 메모리로 로딩해야 하므로 큰 용량의 메모리가 필요 -> Dataset의 from_generator를 사용하여 해결
# from_generator : 데이터를 한 번에 메모리에 로딩하는 것이 아니고, 필요할 때만 파이썬 generator를 통해 가져옴
train_data = train_data.shuffle(10000).batch(batch_size, drop_remainder=True)
# 데이터셋을 변형해 줌
# shuffle: 데이터 셋을 임의로 섞어줌
# batch : 데이터셋의 항목들을 하나의 배치로 묶어줌 / batch_size: 몇 개의 샘플로 가중치를 갱신할지 지정
# drop_remainder : 마지막 배치 크기를 무시하고 지정한 배치 크기를 사용

test_data = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_data = test_data.batch(batch_size, drop_remainder=True)

print('x_train_shape:', x_train.shape, tf.reduce_max(y_train), tf.reduce_min(y_train))
print('x_test_shape:', x_test.shape)

sample = next(iter(test_data))
print(sample[0].shape)

RNN 셀을 이용한 네트워크 생성

class RNN_Build(tf.keras.Model):
  def __init__(self, units):
    super(RNN_Build, self).__init__()

    self.state0 = [tf.zeros([batch_size, units])]
    # tf.zeros : 0으 값으로 채워진 텐서를 생성
    self.state1 = [tf.zeros([batch_size, units])]
    self.embedding = tf.keras.layers.Embedding(total_words, embedding_len, input_length=max_review_len)
    # 케라스는 텍스트 데이터에 대해 워드 임베딩을 수행하는 임베딩층 제공함
    # 임베딩층을 사용하려면 각 입력이 모두 정수로 인코딩 되어 있어야 함
    #   첫번째 인자: 텍스트 데이터의 전체 단어 집합 크기
    #   두번째 인자: 임베딩이 되고 난 후 단어의 차원
    #   input_length: 입력 데이터의 길이

    self.RNNCell0 = tf.keras.layers.SimpleRNNCell(units,dropout=0.2)
    # units: 출력 공간의 차원
    # dropout: 0과 1사이의 부동소수점
    self.RNNCell1 = tf.keras.layers.SimpleRNNCell(units, dropout=0.2)
    self.outlayer = tf.keras.layers.Dense(1)

  def call(self, inputs, training=None):
    x = inputs
    x = self.embedding(x)
    state0 = self.state0
    state1 = self.state1
    for word in tf.unstack(x, axis=1):
    # 중복된 값이 있을 때 사용하면 유용하여 그룹으로 묶은 데이터를 행렬 형태로 전환하여 연산할 때 사용
      out0, state0 = self.RNNCell0(word, state0, training)
      out1, state1 = self.RNNCell1(out0, state1, training)
    x = self.outlayer(out1)
    prob = tf.sigmoid(x)
    return prob

모델 훈련

import time
units = 64
epochs = 4
t0 = time.time()

model = RNN_Build(units)
model.compile(optimizer=tf.keras.optimizers.Adam(0.001),
              loss=tf.losses.BinaryCrossentropy(),
              metrics=['accuracy'],
              experimental_run_tf_function=False)
              # optimizer: 옵티마이저 실행 -> 학습률이 0.01인 Adam을 사용
              # loss: 손실함수 설정 -> 이진 분류로 BinaryCrossentropy를 사용
              # metics: 훈련을 모니터링하기 위한 지표를 선택 -> 정확도를 사용
              # experimental_run_tf_function: 모델을 인스턴스화하는 기능을 제공, 실제로 호출되어야 컴파일이 실행
model.fit(train_data, epochs=epochs, validation_data=test_data, validation_freq=2)
# 첫번째 인자: 입력 데이터
# epochs: 학습 데이터 반복 횟수
# validation_data: 검증 데이터
# validation_freq: 에포크마다 무조건 검증 데이터셋에 대한 계산을 수행하지 않고 적절한 간격을 두고 계산하는 것

모델 훈련을 출력한 결과


모델 평가

print("훈련 데이터셋 평가...")
(loss, accuracy) = model.evaluate(train_data, verbose=0)
# train_data: 훈련 데이터
# verbose: 얼마나 자세하게 정보를 표시할지 지정
print("loss={:.4f}, accuracy:{:.4f}%".format(loss,accuracy * 100))
print("테스트 데이터셋 평가...")
(loss, accuracy) = model.evaluate(test_data, verbose=0)
print("loss={:.4f}, accuracy: {:.4f}%".format(loss,accuracy * 100))
t1 = time.time()
print('시간:', t1-t0)

모델 평가를 출력한 결과

출처: 서지영, 『딥러닝 텐서플로 교과서』, 길벗(2022)

'딥러닝_코드' 카테고리의 다른 글

RNN_계층 구현(SimpleRNN)  (1) 2022.11.27