CoolFace
Modelpublic

UICHEOL-HWANG/kobert

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes11downloads
Model Card

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

MD(Model Description)

  • 7가지 감정범주:
python
label2id = {
    "공포": 0,
    "놀람": 1,
    "분노": 2,
    "슬픔": 3,
    "중립": 4,
    "행복": 5,
    "혐오": 6,
}

메인 모델

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

구성

python
# 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

python
model.config
bash
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

python
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

평가지표

EpochTraining LossValidation LossF1 MacroPrecision MacroRecall Macro
1No log1.2737960.4965220.5097670.506992
21.4785001.2161680.5325640.5345520.537554
31.1558001.2160680.5364420.5376590.539811
40.9962001.2358980.5362100.5375860.541298
50.9010001.2488660.5400000.5394270.543429
  • f1-score기반으로 평가, → 0.54 성능이 그렇게 좋진 못합니다
  • batch_size, Learning_Rate등의 하이퍼 파라미터를 조정할 필요가 보여집니다.(최소 10에포크 이상)
  • T4기준 배치사이즈는 64VRAM 4G 정도 차지하므로 더욱 늘려도 상관 없을듯 합니다.

최종 훈련코드

python
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

python
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")