import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.datasets import imdb
from tensorflow.keras.preprocessing.sequence import pad_sequences # 다양한 리뷰 텍스트의 길이를 동일하도록 잘라주는 모듈
import matplotlib.pyplot as plt
# 1. IMDB 데이터 로드
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=10000) # 가장 많이 등장하는 단어 1만 개를 정수 형태로 갖고오게끔
print(x_train)
2. 시퀀스 패딩
max_len = 200 # 모든 리뷰 길이를 200 단어로 길이를 통일
x_train = pad_sequences(x_train, maxlen=max_len)
x_test = pad_sequences(x_test, maxlen=max_len)
3. 텍스트 분류 모델 정의
model = models.Sequential([
layers.Embedding(input_dim=10000, output_dim=32, input_length=max_len),
# 정수 인덱스를 32차원으로 임베딩(단어를 하나하나 input 해줌) 벡터로 변환 후 단어의 의미를 벡터 공간에 넣어줌
# input_dim == 단어 사전의 크기(10,000), output_dim == 임베딩 차원수(32개)를 의미
layers.LSTM(32),
#LSTM 레이어는 문장 안에서 순서 정보를 학습
# 문맥(context)을 고려해서 감정의 특징을 더 정확하게 학습 가능하게 함
layers.Dense(1, activation='sigmoid')
# 출력층은 하나의 노드이고, 0~1 사이 확률을 반환하게 되므로 sigmoid 활성화를 사용함
# 0.5 기준으로 긍정/부정을 판별해주는 코드임
])
4. 모델 컴파일
model.compile(
optimizer='adam', # 성능이 좋아서 많이 사용되는 옵티마이저
loss='binary_crossentropy', # 0 or 1 분류 문제이므로 binary crossentropy 손실 함수 사용
metrics=['accuracy'] # 학습 성능을 accuracy(정확도) 기준으로 평가
)
5. 모델 학습
history = model.fit(
x_train, y_train, # 학습 데이터 (입력 문자 + 정답 라벨)
epochs = 3, # 전체 데이터를 3번 반복 학습
batch_size = 64, # 한 번에 64개의 리뷰를 읽고 가중치 업데이트
validation_split=0.2 # 학습 데이터의 20%를 검증용으로 사용해서 과적합 여부 평가
)
6. 모델 평가
acc = model.evaluate(x_test, y_test)[1] # 테스트 set으로만 모델 평가하고 accuracy를 계산
print("Test Accuracy: ", acc) # 최종 테스트 정확도 출력
7. 예측 수행
pred = model.predict(x_test[:5]) # 테스트 데이터 중 앞 5개 리뷰에 대해 예측 수행
print("예측 확률: ", pred) # 각 리뷰가 긍정일 확률(0~1 사이값)을 출력
print("예측 결과: ", (pred > 0.5).astype(int)) # 확률 값이 0.5 보다 크면 긍정(1), 작으면 부정(0)으로 바꿔서 최종 예측 레이블을 만듦
8. 학습 과정 시각화(Loss와 Accuracy 그래프)
8-1 Loss 그래프
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1) # 1행 2열 중 첫 번째 그래프 사용
plt.plot(history.history['loss'], label='Train Loss') # 학습에 대한 손실값을 그래프로 표현
plt.plot(history.history['val_loss'], label='Validation Loss') # 검증에 대한 손실값을 그래프로 표현
plt.title("Loss Curve (Binary Crossentropy)")
plt.xlabel("Epoch") # X축은 Epoch(학습 반복 횟수)
plt.ylabel("Loss") # Y축은 손실값(MSE)
plt.legend() # 범례 표시
plt.tight_layout()
plt.show()
그래프 해석: 과적합이 되었다는 것을 알 수 있어요.(다만, 학습은 잘 됐어요) => 데이터부터 처음부터 다 뜯어봐야 할 거 같아요. 😣
8-2 Accuracy 그래프
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1) # 1행 2열 중 첫 번째 그래프 사용
plt.plot(history.history['accuracy'], label='Train accuracy') # 학습 정확도을 그래프로 표현
plt.plot(history.history['val_accuracy'], label='Validation accuracy') # 검증에 대한 정확도를 그래프로 표현
plt.title("accuracy Curve")
plt.xlabel("Epoch") # X축은 Epoch(학습 반복 횟수)
plt.ylabel("accuracy") # Y축은 학습 정확도
plt.legend() # 범례 표시
plt.tight_layout()
plt.show()
학습은 잘 됐지만 검증 데이터가 올라갔다가 떨어졌다가 해요 --> test 데이터와 train 데이터의 성격을 분석 후 다시 학습 필요할 것 같아요 🤔 epochs 횟수를 더 높이거나 스케일링을 바꿔보거나 하면 결과가 달라질 수도요?? 🤔
8-3 예측 결과 그래프
pred_probs = pred_probs[:3] # 앞에서 3개만 사용
plt.figure(figsize=(7, 4))
plt.bar([1, 2, 3], pred_probs) # 1, 2, 3번째 데이터를 가지고 확률 계산
plt.axhline(0.5, color='red', linestyle='--')
plt.xticks([1, 2, 3], ['Review 1', 'Review 2', 'Review 3'])
plt.ylim(0, 1) # Y축의 숫자 범위를 0~1로 설정하여 표현하도록 함
plt.title("Sentiment Prediction Probability (0=부정, 1=긍정)")
plt.ylabel("Probability")
plt.show()
어쨌든 Review 2번째가 긍정적이었고 1, 3번째는 부정적이었다는 결과를 확인할 수 있어요 🤔 부정적인 단어가 더 많이 작성되었나봐요 🤔