: 가중치가 업데이트되는 과정에서 1보다 작은 값이 곱해져서 기울기가 사라지는 기울기 소멸 문제 발생
-> 해결을 위해 LSTM, GRU 같은 확장된 RNN 방식 사용
: 기울기 소멸 문제 해결을 위해 망각 게이트, 입력 게이트, 출력 게이트를 은닉층의 각 뉴런에 추가
망각 게이트
: 과거 정보를 어느 정도 기억할지 결정
입력 게이트
: 현재 정보를 기억하기 위함. 새로운 정보를 반영할지 결정.
셀
출력 게이트
: 과거 정보와 현재 데이터를 사용하여 뉴런의 출력 결정
전체 과정
: 셀을 통해서 역전파 수행. 중단없는 기울기
########## 네트워크 생성
class LSTM_Build(tf.keras.Model):
def __init__(self, units):
super(LSTM_Build, self).__init__()
self.state0 = [tf.zeros([batch_size, units]), tf.zeros([batch_size, units])]
self.state1 = [tf.zeros([batch_size, units]), tf.zeros([batch_size, units])]
self.embedding = tf.keras.layers.Embedding(total_words, embedding_len, input_length=max_review_len)
self.RNNCell0 = tf.keras.layers.LSTMCell(units, dropout=0.5) # units: 메모리 셀 개수, dropout: 전체 가중치 중 50% 값을 0으로 설정하여 사용x
self.RNNCell1 = tf.keras.layers.LSTMCell(units, dropout=0.5)
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)
# train 매개변수 추가
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 = LSTM_Build(units)
model.compile(optimizer=tf.keras.optimizers.Adam(0.001),
loss=tf.losses.BinaryCrossentropy(),
metrics=['accuracy'],
experimental_run_tf_function=False)
model.fit(train_data, epochs=epochs, validation_data=test_data, validation_freq=2)
########## 모델 평가
print("훈련 데이터셋 평가...")
(loss, accuracy) = model.evaluate(train_data, verbose=0)
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)
class LSTM_Build(tf.keras.Model):
def __init__(self, units):
super(LSTM_Build, self).__init__()
self.embedding = tf.keras.layers.Embedding(total_words, embedding_len, input_length=max_review_len)
self.rnn = tf.keras.Sequential([
tf.keras.layers.LSTM(units, dropout=0.5, return_sequences=True, unroll=True),
tf.keras.layers.LSTM(units, dropout=0.5, unroll=True)
])
self.outlayer = tf.keras.layers.Dense(1)
def call(self, inputs, training=None):
x = inputs
x = self.embedding(x)
x = self.rnn(x)
x = self.outlayer(x)
prob = tf.sigmoid(x)
return prob
########## 이후 과정 동일
LSTM(units, dropout return_sequences, unroll)
# LSTMCell: 셀 단위로 수행되므로 다수 셀을 수행하려면 for문으로 반복적 수행 필요
for word in tf.unstack(x, axis=1):
out0, state0 = self.RNNCell0(word, state0, training)
out1, state1 = self.RNNCell1(out0, state1, training)
# LSTM
x = self.rnn(x)
: 게이트 메커니즘이 적용된 RNN 프레임워크의 한 종류
: 과거 정보를 적당히 초기화시키는 목적
: 과거와 현재 정보의 최신화 비율 결정
: 현시점의 정보에 대한 후보군 계산
: 업데이트 게이트 결과와 후보군 결과 결합하여 현시점의 은닉층 계산
########## 네트워크 생성
class GRU_Build(tf.keras.Model):
def __init__(self, units):
super(GRU_Build, self).__init__()
self.state0 = [tf.zeros([batch_size, units])]
self.state1 = [tf.zeros([batch_size, units])]
self.embedding = tf.keras.layers.Embedding(total_words, embedding_len, input_length=max_review_len)
self.RNNCell0 = tf.keras.layers.GRUCell(units, dropout=0.5)
self.RNNCell1 = tf.keras.layers.GRUCell(units, dropout=0.5)
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
########## 이후 과정 동일
########## 네트워크 생성
class GRU_Build(tf.keras.Model):
def __init__(self, units):
super(GRU_Build, self).__init__()
self.embedding = tf.keras.layers.Embedding(total_words, embedding_len, input_length=max_review_len)
self.rnn = tf.keras.Sequential([
tf.keras.layers.GRU(units, dropout=0.5, return_sequences=True, unroll=True),
tf.keras.layers.GRU(units, dropout=0.5, unroll=True)
])
self.outlayer = tf.keras.layers.Dense(1)
def call(self, inputs, training=None):
x = inputs
x = self.embedding(x)
x = self.rnn(x)
x = self.outlayer(x)
prob = tf.sigmoid(x)
return prob
########## 이후 과정 동일
: 이전 시점의 데이터 뿐만 아니라, 이후 시점의 데이터도 함께 활용하여 출력 값을 예측
########## 모델 생성
import numpy as np
from tensorflow.keras.preprocessing import sequence
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Embedding, LSTM, Bidirectional
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.datasets import imdb
n_unique_words = 10000
maxlen = 200
batch_size = 128
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=n_unique_words)
x_train = sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = sequence.pad_sequences(x_test, maxlen=maxlen)
y_train = np.array(y_train)
y_test = np.array(y_test)
model = Sequential()
model.add(Embedding(n_unique_words, 128, input_length=maxlen))
model.add(Bidirectional(LSTM(64))) # LSTM에 양방향 RNN 적용
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
########## 모델 훈련
model.fit(x_train, y_train,
batch_size=batch_size,
epochs=4,
validation_data=[x_test, y_test])
model.summary()
########## 모델 평가
loss, acc = model.evaluate(x_train, y_train, batch_size=384, verbose=1)
print ('Training accuracy', model.metrics_names, acc)
print ('Training accuracy', model.metrics_names, loss)
loss, acc = model.evaluate(x_test, y_test, batch_size=384, verbose=1)
print ('Testing accuracy', model.metrics_names, acc)
print ('Testing accuracy', model.metrics_names, loss)
# train 정확도: 97%, test 정확도: 86%