ML

[ML Backend 찍먹하기] #1. 간단하게 Bert모델 학습시키기(feat. Optuna)

young_3060 2025. 5. 11. 14:22
728x90

우선 모델이 필요할 것 같아서 새로 모델 빠르게 학습시켜서 저장했다.

감정분류 모델이라 데이터셋은 네이버 영화리뷰 데이터셋을 학습시켰고, 이전 프로젝트에서 거의 비슷하게 진행했기 때문에, 참고해서 했다. + 위키독스에 자세히 잘 나와있길래 거의 그대로 진행했다.

이번 토이프로젝트는 아주 간단하게만 진행할 건데, 저장한 모델을 FastAPI로 만들어서 간단한 웹사이트에서의 Backend와 소통하는것을 목표로 하고 있다.

 

(참고)

https://young3060.tistory.com/entry/NLP-BERT%EB%A1%9C-%EB%84%A4%EC%9D%B4%EB%B2%84-%EC%98%81%ED%99%94-%EB%A6%AC%EB%B7%B0-%EA%B0%90%EC%A0%95%EB%B6%84%EB%A5%98%ED%95%98%EA%B8%B0

 

[NLP] BERT로 네이버 영화 리뷰 감정분류하기

저번 포스팅에서 BERT 모델에 대해 알아봤다! 이번에는 BERT를 이용해서 네이버 영화 리뷰 데이터를 긍정, 부정 감정분류하는 실습을 해보고자한다. 여러 블로그들을 참고해보며 코드를 작성했고,

young3060.tistory.com

 

 

 

한가지 다른 부분은 Optuna를 이용해 모델 학습 최적 파라미터들을 구했다는 점정도?

모델 설계에서의 최적의 파라미터들을 구해보고 싶어서 이용해보았다.

 

 

import optuna
from tensorflow.keras.layers import Embedding, Dense, LSTM
from tensorflow.keras.models import Sequential
from tensorflow.keras.models import load_model
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.preprocessing.sequence import pad_sequences
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

def create_model(trial):
  embedding_dim = trial.suggest_categorical('embedding_dim', [64, 100, 128])
  hidden_units = trial.suggest_categorical('hidden_units', [64, 128, 256])
  dropout_rate = trial.suggest_float('dropout_rate', 0.2, 0.5)

  model = Sequential()
  model.add(Embedding(vocab_size, embedding_dim))
  model.add(LSTM(hidden_units))
  model.add(Dense(1, activation='sigmoid'))

  lr = trial.suggest_float('lr', 1e-4, 1e-2, log=True)
  model.compile(optimizer=Adam(learning_rate=lr),
                loss='binary_crossentropy',
                metrics=['accuracy'])

  return model

def objective(trial):
  model = create_model(trial)
  history = model.fit(X_train, y_train,
                      validation_data=(X_test, y_test),
                      batch_size=64,
                      epochs=5,
                      verbose=0)
  val_accuracy = history.history['val_accuracy'][-1]
  return val_accuracy

study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=5)

# 결과 출력
print("Best trial:")
trial = study.best_trial
print("  Accuracy: {}".format(trial.value))
print("  Params: ")
for key, value in trial.params.items():
    print("    {}: {}".format(key, value))

 

 

<결과>

[I 2025-05-03 14:51:22,117] A new study created in memory with name: no-name-5b951af0-f7f2-40b4-b9bf-92cd1672f74c
[I 2025-05-03 15:00:23,109] Trial 0 finished with value: 0.8436297178268433 and parameters: {'embedding_dim': 64, 'hidden_units': 64, 'dropout_rate': 0.22276440693849447, 'lr': 0.00019195254851351004}. Best is trial 0 with value: 0.8436297178268433.
[I 2025-05-03 15:16:42,874] Trial 1 finished with value: 0.8486244082450867 and parameters: {'embedding_dim': 100, 'hidden_units': 128, 'dropout_rate': 0.32267506147511477, 'lr': 0.00040506131223840697}. Best is trial 1 with value: 0.8486244082450867.
[I 2025-05-03 15:53:37,276] Trial 2 finished with value: 0.8478260636329651 and parameters: {'embedding_dim': 128, 'hidden_units': 256, 'dropout_rate': 0.2022201240027561, 'lr': 0.00016615167707407038}. Best is trial 1 with value: 0.8486244082450867.
[I 2025-05-03 16:13:40,865] Trial 3 finished with value: 0.8456767201423645 and parameters: {'embedding_dim': 128, 'hidden_units': 128, 'dropout_rate': 0.272825306594591, 'lr': 0.00020064684965132078}. Best is trial 1 with value: 0.8486244082450867.
[I 2025-05-03 16:24:02,333] Trial 4 finished with value: 0.8484811186790466 and parameters: {'embedding_dim': 100, 'hidden_units': 64, 'dropout_rate': 0.21016084517597255, 'lr': 0.00035428566687915745}. Best is trial 1 with value: 0.8486244082450867.
Best trial:
  Accuracy: 0.8486244082450867
  Params: 
    embedding_dim: 100
    hidden_units: 128
    dropout_rate: 0.32267506147511477
    lr: 0.00040506131223840697

 

 

그래서 이대로 진행했고, best_params로 모델 학습 + 저장까지 마쳤다.

 

이제 다음 포스팅에서는 간단한 웹사이트를 만들고 FastAPI로 Backend에서 처리하는 것을 진행할 것 같다.

728x90