9-3 LSTM과 GRU셀
<주요 내용>
LSTM 셀: 타임스텝이 긴 데이터를 효과적으로 학습하기 위해 고안된 순환층, '입력 게이트, 삭제 게이트, 출력 게이트' 역할을 하는 작은셀이 포함되어 있음
LSTM 셀은 은닉 상태(Hidden state) 외에 셀 상태를 출력함, 셀 상태는 다음 층으로 전달되지 않으며 현재 셀에서만 순환됨
GRU 셀: LSTM 셀의 간소화 버전이지만, 못지않은 성능을 냄
LSTM 구조 (Long Short-Term Memory)
LSTM 셀을 사용한 순환층 클래스
입력과 가중치를 곱하고 절편을 더해 활성화 함수를 통과시키는 구조를 여러개 가지고 있음. 계산 결과를 다음 타임스텝에 재사용
1. 은닉 상태
입력과 이전 타임스텍의 은닉 상태를 가중치에 곱한 후 활성화 함수를 통과시켜 다음 은닉 상태를 만듦
기본 순환층과 달리 시그모이드 활성화 함수 사용
tanh 활성화 함수를 통과한 어떤 값과 곱해져서 은닉 상태를 만듦
2. 셀 상태 cell state
은닉상태와 달리 셀 상태는 다음 층으로 전달 되지않고 LSTM 셀에서 순환만 되는 값
<셀상태와 은닉상태>
1. 입력, h 상태를 가중치 wf 에 곱한 다음 시그모이드 함수를 통과 시킴.
2. 이전 타임 스텝의 c 상태와 곱하여 새로운 c 상태를 만듦
3. 이 c 상태가 오른쪽에서 tanh 함수를 통과하여 새로운 h 상태를 만듦
LSTM 은 작은 셀을 여러 개 포함하고 있는 큰 셀
입력과 은닉상태에 곱해지는 wo wf 가 다름( 서로 다른 기능을 위해 훈련)
<2개의 작은 셀이 더 추가되어 셀 상태를 만듦>
입력과 은닉 상태를 각지 다른 가중치에 곱한 다음, 하나는 시그모이드 다른 하나는 tanh 함수 통과
두 결과를 곱한 후 이전 셀 상태와 더함
<최종적인 다음 셀 상태>
삭제 게이트 : 셀 상태에 있는 정보를 제거하는 역할을 함
입력 게이트 : 새로운 정보를 셀 상태에 추가
출력 게이트 : 이 셀 상태가 다음 은닉 상태로 출력
하지만, 케라스에는 이미 LSTM 클래스가 준비되어있음(계산할 필요 없음)
LSTM 신경망 훈련하기
IMDB 리뷰 데이터를 로드하고 훈련 세트와 검증 세트로 나눔
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)
케라스의 pad_sequences() 함수로 각 샘플의 길이를 100에 맞추고 부족할 때는 패딩을 추가
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 셀을 사용한 순환층 만들기. SimpleRNN -> LSTM 클래스
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'))
모델 컴파일하고 훈련
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])
기본 순환층 보다 LSTM이 과대적합을 억제하면서 훈련 잘 수행함
경우에 따라서 과대적합을 더 강하게 제어하기 위해 드롭아웃 적용을 할 수 있음
순환층에 드롭아웃 적용하기
완전 연결 신경망과 합성곱 신경망은 Dropout 클래스를 사용함
순환층은 자체적으로 드롭아웃 기능 제공
(dropout 매개변수; 셀의 입력에 드롭아웃을 적용, recurrent_dropout 매개변수;순환되는 은닉상테에 드롭아웃 적용)
LSTM 클래스에 dropout 매개변수를 0.3으로 지정하여 30%의 입력을 드롭아웃
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'))
모델을 이전과 동일한 조건으로 훈련
rmsprop = keras.optimizers.RMSprop(learning_rate=1e-4)
model2.compile(optimizer=rmsprop, loss='binary_crossentropy',
metrics=['accuracy'])
checkpoint_cb = keras.callbacks.ModelCheckpoint('best-dropout-model.h5',
save_best_only=True)
early_stopping_cb = keras.callbacks.EarlyStopping(patience=3,
restore_best_weights=True)
history = model2.fit(train_seq, train_target, epochs=100, batch_size=64,
validation_data=(val_seq, val_target),
callbacks=[checkpoint_cb, early_stopping_cb])
dropout의 적용으로 훈련 손실과 검증 손실 간의 차이가 좁혀짐
2개의 층을 연결하기
순환층 연결할 때 주의할 점
순환층의 은닉 상태는 샘플의 마지막 타임스텝에 대한 은닉상태만 다음 층으로 전달
순환층을 쌓게 되면 모든 순환 층에 순차 데이터가 필요
앞쪽의 순환층이 모든 타임 스텝에 대한 은닉 상태를 출력해야함
오직 마지막 순환층만 마지막 타임스텝의 은닉상태를 출력해야함
-> 케라스에서 마지막을 제외한 다른 모든 순환층에서 return_sequences 매개변수를 True 로 지정
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'))
첫 번째 LSTM 층이 모든 타임스텝(100개)의 은닉 상태를 출력하기 때문에 출력 크기가(None,100,8)로 표시
이에 반해 두 번째 LSTM 층의 출력 크기는 마지막 타임스텝의 은닉 상태만 출력하기 때문에 (None,8).
과대적합을 제어하면서 손실을 최대한 낮춤.
GRU 구조 (Gated Recurrent Unit)
LSTM 을 간소화한 버전
이 셀은 LSTM 처럼 셀 상태를 계산하지 않고 은닉 상태 하나만 포함하고 있음
3개의 셀 중 2개는 시그모이드 활성화 함수를 사용하고 다른 하나는 tanh 활성화 함수 사용
삭제 게이트 : 맨 왼쪽에서 wz를 사용하는 셀의 출력이 은닉 상태에 바로 곱해짐
입력 되는 정보 제어:똑같은 출력을 1에서 뺀 다음에 가장 오른쪽 wg 를 사용하는 셀의 출력에 곱함
은닉 상태의 정보를 제어: 가운데 wr을 사용하는 셀에서 출력된 값은 wg 셀이 사용할 은닉 상태의 정보 제어
GRU 셀은 LSTM 보다 가중치가 적어서 계산량이 적지만 좋은 성능
GRU 신경망 훈련하기
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'))
입력에 곱하는 가중치는 16x 8 = 128
은닉 상태에 곱하는 가중치는 8 x 8 = 64
뉴런마다 절편이 하나씩이므로 128+64+8 = 200
작은 셀이 3개이므로 총 600개의 모델 파라미터가 필요
하지만, summary()의 출력은 624
바뀐점 : 은닉 상태가 먼저 가중치와 곱해진 다음 가운데 셀의 출력과 곱해짐.
ws ( 입력과 은닉 상태에 곱해지는 가중치를 별도 표시) -> wx 와 wh 로 나눔
따라서 나우어서 계산하면 작은 셀마다 하나씩 절편이 추가되어 24개의 모델 파라이터가 추가됨
따라서, 624개
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])
드롭 아웃을 사용하지 않아서, 훈련 손실과 검증 손실 사이에 차이가 있지만 훈련 과정이 잘 수렴되고 있음
'공부 > Deep Learning' 카테고리의 다른 글
[Paper Review] Noise2Noise: Learning image restoration without clean data (0) | 2024.03.17 |
---|---|
[Paper Review] Attention is all you need (3) | 2024.02.28 |
혼자 공부하는 머신러닝 + 딥러닝 8장 (2) | 2023.11.19 |
혼자 공부하는 머신러닝 + 딥러닝 7장 (1) | 2023.11.12 |
혼자공부하는 머신러닝 + 딥러닝 5장 (0) | 2023.10.28 |