한국어 텍스트 감정분류 모델(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
109
Safetensors
Model size
92.2M params
Tensor type
F32
·
Inference Providers NEW
This model is not currently available via any of the supported Inference Providers.

Model tree for UICHEOL-HWANG/kobert

Base model

monologg/kobert
Finetuned
(7)
this model