[혼자 공부하는 머신러닝+딥러닝] 25강. LSTM과 GRU 셀 - 고급 순환층
https://www.youtube.com/watch?v=ub8S29bF6rk&list=PLJN246lAkhQjoU0C4v8FgtbjOIXxSs_4Q&index=25
- 개요
- 단어의 길이가 길수록 즉 시퀀스가 길수록 순환되는 은닉 상태에 담기게 되는 정보들은 점점 희석된다.
- 때문에 멀리 떨어져 있는 단어 정보는 점차 인식하기 어려운 상태가 된다.
- 일반적으로 기본 순환층은 긴 시퀀스를 학습하기 어렵다.
- 이러한 문제를 해결하기 위해 고급 순환층인 LSTM과 GRU 셀이 발명되었다.
- LSTM (Long Short Term Memory)
- 단기 메모리를 오래 기억하기 위해 고안되었다.
- 입력과 가중치를 곱하고 절편을 더해 활성화 함수를 통과시키는 구조를 여러 개 가지고 있고, 이런 계산 결과는 다음 타임스텝에 재사용 된다.
- 셀의 구성을 알아보자
- 하나의 셀 내부에는 4개의 작은 셀들(Wf, Wi, Wj, Wo)과 은닉 상태, 셀 상태 총 2가지 상태가 순환된다.
- 모든 작은 셀들에는 동일한 입력과 순환 상태가 전달된다.
- 작은 셀들은 셀 상태에 정의되어 있는 게이트에 연결되어 있다.
- 셀 상태에는 총 3개의 게이트가 있으며 각 역할은 다음과 같다.
- 삭제 게이트 : Wf는 시그모이드를 통과하여 통과하여 이전 타임스텝의 셀 상태와 곱해져 새로운 셀 상태를 만드는 데 기여한다.
- 입력 게이트 : Wi (시그모이드), Wj (tanh) 를 통과한 두 셀의 출력이 곱해져 이전 타임스텝의 셀 상태와 더해져 새로운 셀 상태를 최종적으로 만든다.
- 출력 게이트 : 은닉상태를 만들기 위해 tanh를 통과해서 Wo (시그모이드) 의 출력에 사용된다.
- LSTM 신경망
- 이전 강의에서의 SimpleRNN대신 LSTM을 사용한다.
from tensorflow.keras.datasets import imdb
from sklearn.model_selection import train_test_split
(train_input, train_target), (test_input, test_target) = imdb.load_data(
num_words=500)
train_input, val_input, train_target, val_target = train_test_split(
train_input, train_target, test_size=0.2, random_state=42)
from tensorflow.keras.preprocessing.sequence import pad_sequences
train_seq = pad_sequences(train_input, maxlen=100)
val_seq = pad_sequences(val_input, maxlen=100)
- LSTM 신경망 만들기
- (16개 인풋 x 8개 뉴런 + 8 순환 x 8 뉴런 + 8절편) x 4개의 작은 셀
- 총 800개의 가중치
from tensorflow import keras
model = keras.Sequential()
model.add(keras.layers.Embedding(500, 16, input_length=100))
model.add(keras.layers.LSTM(8))
model.add(keras.layers.Dense(1, activation='sigmoid'))
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) (None, 100, 16) 8000
lstm (LSTM) (None, 8) 800
dense (Dense) (None, 1) 9
=================================================================
Total params: 8809 (34.41 KB)
Trainable params: 8809 (34.41 KB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
- 학습 하기
- RMSprop의 학습률을 0.0001로 조정하고 배치 크기는 64개, 에포크는 100으로 정의한다.
- 체크포인트와 저기 종료도 포함한다.
- 80%의 정확도
rmsprop = keras.optimizers.RMSprop(learning_rate=1e-4)
model.compile(optimizer=rmsprop, loss='binary_crossentropy',
metrics=['accuracy'])
checkpoint_cb = keras.callbacks.ModelCheckpoint('best-lstm-model.h5',
save_best_only=True)
early_stopping_cb = keras.callbacks.EarlyStopping(patience=3,
restore_best_weights=True)
history = model.fit(train_seq, train_target, epochs=100, batch_size=64,
validation_data=(val_seq, val_target),
callbacks=[checkpoint_cb, early_stopping_cb])
- 그래프 그리기
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'val'])
plt.show()
- 순환 층에 드롭아웃 적용하기
- 과대 적합을 막기 위한 작업 추가
- dropout 매개변수는 은닉상태의 비율을 지정하고 순환되는 셀 상태의 드롭아웃 매개변수는 따로 있다.
- 모델 학습 코드는 동일 하다 정확도 80%, 아주 미미하게 성능이 상승되었다.
model2 = keras.Sequential()
model2.add(keras.layers.Embedding(500, 16, input_length=100))
model2.add(keras.layers.LSTM(8, dropout=0.3))
model2.add(keras.layers.Dense(1, activation='sigmoid'))
- 2개의 층 연결하기
- return_sequences=True 로 정의하여 모든 타임스텝의 은닉상태를 출력해야 한다.
- 모델 학습 코드는 동일 하다 정확도 79%
model3 = keras.Sequential()
model3.add(keras.layers.Embedding(500, 16, input_length=100))
model3.add(keras.layers.LSTM(8, dropout=0.3, return_sequences=True))
model3.add(keras.layers.LSTM(8, dropout=0.3))
model3.add(keras.layers.Dense(1, activation='sigmoid'))
model3.summary()
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_2 (Embedding) (None, 100, 16) 8000
lstm_2 (LSTM) (None, 100, 8) 800
lstm_3 (LSTM) (None, 8) 544
dense_2 (Dense) (None, 1) 9
=================================================================
Total params: 9353 (36.54 KB)
Trainable params: 9353 (36.54 KB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
- GRU 셀
- LSTM의 간소화 버전으로 cell 상태가 없다.
- 일반적으로 설명시 사용되는 이미지는 왼쪽이고 실제 텐서플로우에서 구현된 상태는 오른쪽이다.
- 왼쪽 이미지에서 Wz에서 Wg의 출력과 결합되기 전 1에서 Wz의 출력 값을 뺀 다음 Wg의 출력과 곱해진다.
- 왼쪽 이미지에서 Wr은 Wg에 주입되는 은닉상태의 양을 조절, 변경, 제어한다고 보면 된다.
- 오른쪽 이미지에서 Wg였던 셀에서 분리된 Wh가 은닉상태에 미리 곱해지고 Wr 출력과 다시 곱해져 G 셀에 들어간다.
- 오른쪽 이미지에서 Wg였던 셀에서 분리된 Wx는 입력과 곱해져 G셀에 들어간다.
- 오른쪽 이미지 처럼 Wg 셀 내용을 떨어뜨려 놨을 때의 변화는 Wh와 h가 곱해질 때 절편이 사용되고 Wx와 입력이 곱해질 때 절편이 또 필요해져서 선형 방적식이 따로 존재하게 되는 셈이 된다. (절편이 늘어나는 효과가 생긴다)
- 이렇게 설명을 별개로 하는 이유는 코드로 구현할 경우 모델 파라미터 개수를 확인하면 실재로 달라지기 때문이다.
- GRU 셀 신경망 훈련하기
- 클래스만 변경하면 된다
- LSTM처럼 셀 상태를 계산하지 않고 은닉상태 하나만 포함한다.
- GRU 셀은 LSTM보다 가중치가 적기 때문에 계산량이 적지만 LSTM과 비교해 좋은 성능을 만들어 낸다.
- 16 (입력 수) x 8 (뉴런 수) + 8 (은닉 상태) x 8 (뉴런 수) + 8 (뉴런) + 8 (가중치) x 3 (작은 뉴런?)
model4 = keras.Sequential()
model4.add(keras.layers.Embedding(500, 16, input_length=100))
model4.add(keras.layers.GRU(8))
model4.add(keras.layers.Dense(1, activation='sigmoid'))
model4.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_3 (Embedding) (None, 100, 16) 8000
gru (GRU) (None, 8) 624
dense_3 (Dense) (None, 1) 9
=================================================================
Total params: 8633 (33.72 KB)
Trainable params: 8633 (33.72 KB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
- 모델 학습하기
- 정확도는 79%이다
rmsprop = keras.optimizers.RMSprop(learning_rate=1e-4)
model4.compile(optimizer=rmsprop, loss='binary_crossentropy',
metrics=['accuracy'])
checkpoint_cb = keras.callbacks.ModelCheckpoint('best-gru-model.h5',
save_best_only=True)
early_stopping_cb = keras.callbacks.EarlyStopping(patience=3,
restore_best_weights=True)
history = model4.fit(train_seq, train_target, epochs=100, batch_size=64,
validation_data=(val_seq, val_target),
callbacks=[checkpoint_cb, early_stopping_cb])
- 그래프 그리기
- 드롭아웃을 사용하면 검증 손실에 더 좋은 결과를 만들 수 있을 것이다.
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'val'])
plt.show()
- 검증하기
test_seq = pad_sequences(test_input, maxlen=100)
rnn_model = keras.models.load_model('best-2rnn-model.h5')
rnn_model.evaluate(test_seq, test_target)
782/782 [==============================] - 6s 7ms/step - loss: 0.4346 - accuracy: 0.7975
[0.434622585773468, 0.7974799871444702]
- reference :
'데이터분석-머신러닝-AI > 강의 정리' 카테고리의 다른 글
[혼자 공부하는 머신러닝+딥러닝] 24강. 순환 신경망으로 IMDB 리뷰 분류하기 - 영화 리뷰 감상평을 분류해보자 (0) | 2023.11.29 |
---|---|
[혼자 공부하는 머신러닝+딥러닝] 23강. 순차 데이터와 순환 신경망 - 자연어 처리를 위한 신경망 (1) | 2023.11.28 |
[혼자 공부하는 머신러닝+딥러닝] 22강. 합성곱 신경망의 시각화 - 가중치, 특성치 시각화 (1) | 2023.11.27 |
[혼자 공부하는 머신러닝+딥러닝] 21강. 합성곱 신경망을 사용한 이미지 분류 - 패션 mnist를 이용한 분류 코딩 학습 (0) | 2023.11.26 |
[혼자 공부하는 머신러닝+딥러닝] 20강. 합성곱 신경망의 개념과 동작 원리 배우기 - 2차원 이미지를 그대로 학습 해보자! (2) | 2023.11.26 |
댓글