RNN 실습 1
- IMDB 데이터셋을 활용
- LSTM 모델 활용
- 리뷰 감성분류, 긍정/부정으로 이진 분류 라벨링
- IMDB 데이터는 훈련데이터와 테스트 데이터를 5:5 비율로 제공
- 라이브러리 불러오기
import tensorflow as tf
from tensorflow.keras import layers, Sequential
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.datasets import imdb
from tensorflow.keras.preprocessing.sequence import pad_sequences
- IMDB 데이터셋 불러오기
def load_data(num_words, max_len):
(X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=num_words)
X_train = pad_sequences(X_train, maxlen=max_len)
X_test = pad_sequences(X_test, maxlen=max_len)
return X_train, X_test, y_train, y_test
- LSTM 모델 구축
layers.Embedding: max_words에서 embedding_size로 각 문장을 구성하는 벡터의 크기를 줄이는 임베딩 레이어 추가
input_dim: 어휘의 크기, 즉 최대 정수 인덱스 + 1
output_dim: 임베딩의 차수
def build_lstm_model(num_words, embedding_len):
model = Sequential()
model.add(layers.Embedding(input_dim = num_words, output_dim=embedding_len))
model.add(layers.LSTM(16))
model.add(layers.Dense(1, activation='sigmoid'))
return model
- LSTM hidden state 크기: 16
- 출력층은 긍정/부정 중 하나의 값으로 출력되기에, 노드의 개수는 1
- 출력층 활성화 함수는 로지스틱 회귀를 위해 시그모이드 함수 설정
- 모델 학습
def run_model(model, X_train, X_test, y_train, y_test, epochs=5):
optimizer = Adam(learning_rate=0.001)
loss='binary_crossentropy'
model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])
hist = model.fit(X_train, y_train, batch_size=128, epochs=epochs, shuffle=True, verbose=2)
test_loss, test_acc = model.evaluate(X_test, y_test, verbose=0)
print()
print("테스트 loss: {:.5f}, 테스트 정확도: {:.3f}%".format(test_loss, test_acc * 100))
return optimizer, hist
- 전체 코드 실행
def main():
tf.random.set_seed(2022)
num_words = 6000
max_len = 130
embedding_len = 100
X_train, X_test, y_train, y_test = load_data(num_words, max_len)
model = build_lstm_model(num_words, embedding_len)
run_model(model, X_train, X_test, y_train, y_test)
if __name__ == "__main__":
main()
- load_data(num_words: 등장 빈도 순위 -> 단어 집합 크기, max_len: 리뷰 최대 길이)
- X_train 개수: 25000
- X_train 리뷰 길이: 130
- 임베딩 차원: 100
RNN 실습 2
- 캐글의 아마존 식품 리뷰 데이터 셋을 활용
- RNN, LSTM, GRU 모델 활용
- 평점 분류, 라벨링 1~5까지로
https://www.kaggle.com/datasets/snap/amazon-fine-food-reviews
- 라이브러리 불러오기
import tensorflow as tf
from tensorflow.keras import layers, Sequential
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.optimizers import Adam
from sklearn.model_selection import train_test_split
- 데이터셋 불러오기
def load_data(max_len):
data = pd.read_csv("./review_score.csv")
X = data['Review']
y = data['Score']
y = y - 1 # 값을 1~5에서 0~4로 변경
tokenizer = Tokenizer()
tokenizer.fit_on_texts(X)
X = tokenizer.texts_to_sequences(X)
# 전체 단어 중에서 가장 큰 숫자로 mapping된 단어의 숫자
max_features = max([max(_in) for _in in X]) + 1
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
X_train = pad_sequences(X_train, maxlen=max_len)
X_test = pad_sequences(X_test, maxlen=max_len)
return X_train, X_test, y_train, y_test, max_features
- 문자열로 되어있는 데이터 -> tokenizer 및 시퀀스로 변환
- 학습 데이터 80% / 테스트 데이터 20%로 분리
- 모든 문장이 가장 긴 문장의 단어 개수와 일치하도록 패딩 추가
- Simple RNN 모델
def build_rnn_model(max_features, embedding_size):
model = Sequential()
model.add(layers.Embedding(input_dim=max_features, output_dim=embedding_size))
model.add(layers.SimpleRNN(32))
model.add(layers.Dense(5, activation='softmax'))
return model
- 은닉층에 SimpleRNN layer 추가
- 출력 값이 1~5라서 출력 노드의 개수는 5 & 활성화함수는 softmax
- LSTM 모델
def build_lstm_model(max_features, embedding_size):
model = Sequential()
model.add(layers.Embedding(input_dim=max_features, output_dim=embedding_size))
model.add(layers.LSTM(32))
model.add(layers.Dense(5, activation='softmax'))
return model
- 은닉층에 LSTM layer 추가
- 출력 값이 1~5라서 출력 노드의 개수는 5 & 활성화함수는 softmax
- GRU 모델
def build_gru_model(max_features, embedding_size):
model = Sequential()
model.add(layers.Embedding(input_dim=max_features, output_dim=embedding_size))
model.add(layers.GRU(32))
model.add(layers.Dense(5, activation='softmax'))
return model
- 은닉층에 GRU layer 추가
- 출력 값이 1~5라서 출력 노드의 개수는 5 & 활성화함수는 softmax
- 모델 학습
def run_model(model, X_train, X_test, y_train, y_test, epochs=10):
optimizer = Adam(learning_rate=0.001)
loss = 'sparse_categorical_crossentropy'
model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])
hist = model.fit(X_train, y_train, batch_size=256, epochs=epochs, shuffle=True, verbose=2)
test_loss, test_acc = model.evaluate(X_test, y_test, verbose=0)
return test_loss, test_acc, optimizer, hist
- 다중 분류 문제이기 때문에 손실함수는 sparse_categorical_crossentropy
- 전체 코드 실행
def main():
tf.random.set_seed(2022)
max_len = 150
embedding_size = 128
X_train, X_test, y_train, y_test, max_features = load_data(max_len)
rnn_model = build_rnn_model(max_features, embedding_size)
lstm_model = build_lstm_model(max_features, embedding_size)
gru_model = build_gru_model(max_features, embedding_size)
rnn_test_loss, rnn_test_acc, _, _ = run_model(rnn_model, X_train, X_test, y_train, y_test)
lstm_test_loss, lstm_test_acc, _, _ = run_model(lstm_model, X_train, X_test, y_train, y_test)
gru_test_loss, gru_test_acc, _, _ = run_model(gru_model, X_train, X_test, y_train, y_test)
print()
print("=" * 20, "모델 별 Test Loss와 정확도", "=" * 20)
print("[RNN ] 테스트 Loss: {:.5f}, 테스트 Accuracy: {:.3f}%".format(rnn_test_loss, rnn_test_acc * 100))
print("[LSTM] 테스트 Loss: {:.5f}, 테스트 Accuracy: {:.3f}%".format(lstm_test_loss, lstm_test_acc * 100))
print("[GRU ] 테스트 Loss: {:.5f}, 테스트 Accuracy: {:.3f}%".format(gru_test_loss, gru_test_acc * 100))
if __name__ == "__main__":
main()
- 모델 학습 결과
- LSTM > GRU > RNN 순으로 정확도가 높게 나옴
- 간단한 실습으로 은닉층의 개수를 한 개씩만 설정하여 정확도 낮음
참고자료
반응형
'IT Study > ML & DL' 카테고리의 다른 글
[CNN] OpenCV 실습 | 이미지 조각 순서변경, 프리윗 필터, 회선처리 (1) | 2023.12.31 |
---|---|
[DL/NLP] RNN 실습 (with. nsmc data) (1) | 2023.12.23 |
[DL/NLP] Word2Vec - CBOW & Skip-Gram 방식 (1) | 2023.12.23 |
[DL/CNN] CNN 실습 (with. MNIST data) (0) | 2023.12.22 |