한국어 텍스트 감정분류 모델(KoBERT)

MD(Model Description)

label2id = {
    "공포": 0,
    "놀람": 1,
    "분노": 2,
    "슬픔": 3,
    "중립": 4,
    "행복": 5,
    "혐오": 6,
}

메인 모델

monologg/kobert모델의 사전 학습된 KoBERT 모델을 미세조정하였습니다(fine tunning)

구성

# Tokenizer
!git clone https://github.com/monologg/KoBERT-Transformers.git

from kobert_transformers.tokenization_kobert import KoBertTokenizer

#Default Settings
tokenizer = KoBertTokenizer.from_pretrained("monologg/kobert")
model = BertForSequenceClassification.from_pretrained("monologg/kobert")

#Datasets Preprocessing
import json 

with open('/content/train_datasets.json', 'r', encoding='utf-8') as files:
  train_dataset = json.load(files)

with open('/content/test_datasets.json', 'r', encoding='utf-8') as files_t:
  val_dataset = json.load(files_t)


from datasets import Dataset

# 리스트 데이터를 Hugging Face Dataset으로 변환
train_dataset = Dataset.from_list(train_dataset)
val_dataset = Dataset.from_list(val_dataset)


# 토큰화 함수 정의
def tokenize_function(examples):
    return tokenizer(
        examples['Sentence'],  # 텍스트 필드 이름
        padding='max_length',
        truncation=True,
        max_length=128
    )

train_dataset = train_dataset.map(tokenize_function, batched=True)
val_dataset = val_dataset.map(tokenize_function, batched=True)

# 불필요한 컬럼 제거
train_dataset = train_dataset.remove_columns(['Sentence'])
val_dataset = val_dataset.remove_columns(['Sentence'])

# 데이터셋 포맷 지정 (PyTorch tensors)
train_dataset.set_format('torch')
val_dataset.set_format('torch')

Model Config Settings

model.config
BertConfig {
  "_attn_implementation_autoset": true,
  "_name_or_path": "monologg/kobert",
  "architectures": [
    "BertModel"
  ],
  "attention_probs_dropout_prob": 0.1,
  "classifier_dropout": null,
  "hidden_act": "gelu",
  "hidden_dropout_prob": 0.1,
  "hidden_size": 768,
  "id2label": {
    "0": "LABEL_0",
    "1": "LABEL_1",
    "2": "LABEL_2",
    "3": "LABEL_3",
    "4": "LABEL_4"
  },
  "initializer_range": 0.02,
  "intermediate_size": 3072,
  "label2id": {
    "LABEL_0": 0,
    "LABEL_1": 1,
    "LABEL_2": 2,
    "LABEL_3": 3,
    "LABEL_4": 4
  },
  "layer_norm_eps": 1e-12,
  "max_position_embeddings": 512,
  "model_type": "bert",
  "num_attention_heads": 12,
  "num_hidden_layers": 12,
  "pad_token_id": 1,
  "position_embedding_type": "absolute",
  "transformers_version": "4.47.0",
  "type_vocab_size": 2,
  "use_cache": true,
  "vocab_size": 8002
}
  • 라벨이 5개 밖에 없는 것을 확인할 수 있습니다.

Configuration Settings

from transformers import BertConfig, BertForSequenceClassification, AutoTokenizer
import torch

# 감정별 라벨 매핑
label2id = {
    "공포": 0,
    "놀람": 1,
    "분노": 2,
    "슬픔": 3,
    "중립": 4,
    "행복": 5,
    "혐오": 6,
}

id2label = {v: k for k, v in label2id.items()}

# BertConfig에 라벨 매핑 추가
config = BertConfig.from_pretrained(
    "monologg/kobert",
    num_labels=7,
    id2label=id2label,
    label2id=label2id
)

model = BertForSequenceClassification.from_pretrained("monologg/kobert", config=config)
tokenizer = KoBertTokenizer.from_pretrained("monologg/kobert")
  • 사실은 num_labels=7을 할 필요가 없습니다.
  • 세팅 이후에 model.config로 세팅값을 확인해보면 7가지 레이블 값이 입력된 것을 확인 할 수 있습니다.

Detail Configuration

설정 항목
학습률 2e-5
학습 배치사이즈 64
평가 배치사이즈 1
평가 지표 F1 Score (Macro)
FP16 사용 여부 True

평가지표

Epoch Training Loss Validation Loss F1 Macro Precision Macro Recall Macro
1 No log 1.273796 0.496522 0.509767 0.506992
2 1.478500 1.216168 0.532564 0.534552 0.537554
3 1.155800 1.216068 0.536442 0.537659 0.539811
4 0.996200 1.235898 0.536210 0.537586 0.541298
5 0.901000 1.248866 0.540000 0.539427 0.543429
  • f1-score기반으로 평가, → 0.54 성능이 그렇게 좋진 못합니다
  • batch_size, Learning_Rate등의 하이퍼 파라미터를 조정할 필요가 보여집니다.(최소 10에포크 이상)
  • T4기준 배치사이즈는 64VRAM 4G 정도 차지하므로 더욱 늘려도 상관 없을듯 합니다.

최종 훈련코드

training_args = TrainingArguments(
    output_dir='./results',
    learning_rate=2e-5,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,
    num_train_epochs=10,
    eval_strategy="epoch",
    save_strategy="epoch",
    metric_for_best_model="f1_macro",
    load_best_model_at_end=True
)

Inference

model = BertForSequenceClassification.from_pretrained('./result/pp')
tokenizer = KoBertTokenizer.from_pretrained('./result/pp')


# GPU 사용 여부 확인 및 디바이스 설정
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
model.to(device)  # 모델을 디바이스로 이동
model.eval()

# 2. 입력 데이터 준비
texts = [
    "오늘 정말 기분이 좋다 ㅎㅎ!",
    "왜 이렇게 힘든 일이 많지? ㅠㅠ",
    "정말 화가 난다!",
    "평범한 하루였어.",
    "너무 재밌다 ㅋㅋㅋ!",
]

# 3. 토큰화 및 입력 형식 변환
def preprocess_and_tokenize(texts, tokenizer, max_length=128):
    inputs = tokenizer(
        texts,
        padding=True,  # 배치 크기에 맞게 패딩
        truncation=True,  # 최대 길이 초과 시 자름
        max_length=max_length,
        return_tensors="pt",  # PyTorch 텐서 반환
    )
    return inputs

inputs = preprocess_and_tokenize(texts, tokenizer)

# 입력 데이터를 GPU로 이동
inputs = {key: val.to(device) for key, val in inputs.items()}



# 4. 인퍼런스 수행
with torch.no_grad():
    outputs = model(**inputs)
    logits = outputs.logits
    predictions = torch.argmax(logits, dim=-1).cpu().numpy()


# 예측 결과 매핑
predicted_labels = [id2label[pred] for pred in predictions]

# 6. 결과 출력
for text, label in zip(texts, predicted_labels):
    print(f"Input: {text}")
    print(f"Predicted Label: {label}\n")
Downloads last month
20
Safetensors
Model size
92.2M params
Tensor type
F32
·
Inference Examples
This model does not have enough activity to be deployed to Inference API (serverless) yet. Increase its social visibility and check back later, or deploy to Inference Endpoints (dedicated) instead.

Model tree for UICHEOL-HWANG/kobert

Base model

monologg/kobert
Finetuned
(7)
this model