데이터분석-머신러닝-AI/강의 정리

[혼자 공부하는 머신러닝+딥러닝] 25강. LSTM과 GRU 셀 - 고급 순환층

bluebamus 2023. 11. 29.

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 :

https://velog.io/@katinon/%ED%98%BC%EA%B3%B5%EB%A8%B8%EC%8B%A0-%EC%88%9C%ED%99%98-%EC%8B%A0%EA%B2%BD%EB%A7%9D-LSTM-GRU-%EC%85%80

 

[혼공머신] 순환 신경망 : LSTM, GRU 셀

혼자 공부하는 머신러닝+딥러닝 책에 기반한 정리글입니다.전체 소스코드는 아래 Github 링크에서 확인할 수 있습니다.Github 링크일반적으로 기본 순환층은 긴 시퀸스를 학습하기 어렵다. 멀리 떨

velog.io

https://velog.io/@clayryu328/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D%EB%94%A5%EB%9F%AC%EB%8B%9D-11

 

[혼자 공부하는 머신러닝+딥러닝] #11 LSTM GRU

LSTM GRU 솔직히 잘...?

velog.io

 

댓글