한국어 금융 데이터셋 파인튜닝 챗봇 - 1

현주·2024년 12월 5일
2
post-thumbnail

한국어 금융 데이터셋 파인튜닝 챗봇

이 글에서는 Bllossom의 LLaMA 기반 한국어 언어 모델을 한국어 금융 데이터셋으로 파인튜닝한 과정을 다룬다. 자원이 한정되어있기 때문에 최적화된 파인튜닝을 위해 LoRA와 4비트 양자화 기법을 사용하여 학습했다.

훈련에 사용한 모델은 Bllossom/llama-3.2-Korean-Bllossom-3B이고, 데이터셋은 BCCard-Finance-Kor-QnA를 사용했다.

👉https://huggingface.co/Bllossom/llama-3.2-Korean-Bllossom-3B
👉https://huggingface.co/datasets/BCCard/BCCard-Finance-Kor-QnA


파인튜닝 과정

라이브러리 import

import torch
from datasets import load_dataset
from transformers import (BitsAndBytesConfig, 
                          AutoTokenizer,
                          AutoModelForCausalLM, 
                          TrainingArguments)
from peft import (LoraConfig,
                  get_peft_model, 
                  prepare_model_for_kbit_training)
from trl import SFTTrainer

base_model = 'Bllossom/llama-3.2-Korean-Bllossom-3B'
dataset = load_dataset("BCCard/BCCard-Finance-Kor-QnA", split='train')

데이터 전처리

tokenizer는 모델의 템플릿에 맞춰 데이터를 토크나이징한다(map 메서드를 사용)

def preprocess(data):
        return data.map(lambda x: {'data': tokenizer.apply_chat_template([{"role": "system", "content": x['instruction']}, {"role": "assistant", "content": x['output']}], add_generation_prompt=False, tokenize=False, return_tensors="pt")}).map(lambda samples: tokenizer(samples["data"]), batched=True)

data = preprocess(dataset)
print(data[10])

토크나이저 로드

모델과 호환되는 토크나이저를 로드하고 pad_token을 설정

tokenizer = AutoTokenizer.from_pretrained("Bllossom/llama-3.2-Korean-Bllossom-3B")
tokenizer.pad_token = tokenizer.eos_token

데이터 변환

입력 데이터(instruction, output)를 모델 학습 템플릿에 맞춰 매핑한 후 토크나이징한다

<이 단계에서 일어나는 일>
👉apply_chat_template로 시스템 메시지와 답변을 템플릿에 맞게 정리
👉토크나이저를 통해 데이터를 정수 인덱스로 변환

def preprocess(data):
    return data.map(
        lambda x: {
            'data': tokenizer.apply_chat_template(
                [{"role": "system", "content": x['instruction']},
                 {"role": "assistant", "content": x['output']}],
                add_generation_prompt=False, tokenize=False, return_tensors="pt"
            )
        }
    ).map(lambda samples: tokenizer(samples["data"]), batched=True)

train_data = preprocess(train)
test_data = preprocess(test)

양자화 설정

Bits and Bytes를 사용해 모델을 4비트 양자화로 메모리 효율을 높인다

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.float16,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4"
    )
model = AutoModelForCausalLM.from_pretrained(
    base_model,
    quantization_config = bnb_config,
    device_map = 'auto',
    low_cpu_mem_usage=True
    )

LoRA 설정

LoRA를 적용해 특정 레이어만 미세조정한다

lora_config = LoraConfig(
    r=4,
    lora_alpha=32,
    target_modules=["q_proj", "o_proj", "k_proj", "v_proj", "gate_proj", "up_proj", "down_proj"],
    lora_dropout=0.1,
    bias="none"
    )

model.gradient_checkpointing_enable()
model = prepare_model_for_kbit_training(model)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()

훈련 하이퍼파라미터 설정

training_args = TrainingArguments(
    output_dir="./results",
    overwrite_output_dir=True,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=8,
    num_train_epochs=3,
    learning_rate=2e-5,
    lr_scheduler_type="cosine",
    warmup_steps=500,
    weight_decay=0.01,
    fp16=True,
    logging_steps=50,
    save_steps=500,
    save_total_limit=2,
    dataloader_num_workers=2,
    )

SFTTrainer로 훈련 실행

SFTTrainer를 활용해 LoRA 기반 훈련을 간소화한다

trainer = SFTTrainer(
    model=model,
    train_dataset=data,
    peft_config=lora_config,
    dataset_text_field="data",
    tokenizer=tokenizer,
    args=training_args,
    max_seq_length='NONE',
    packing=False
    )

model.config.use_cache = False
trainer.train()

결론

LoRA와 4비트 양자화를 사용해 한국어 금융 데이터셋으로 한국어 모델을 효율적으로 파인튜닝 해봤다!


+추가

파인튜닝을 완료한 후 모델을 테스트해 본 결과, 답변 텍스트가 반복적으로 생성되며 최대 길이에 도달해야만 답변 생성이 멈추는 현상이 발생하였다(...) 이에 대한 원인을 찾기 위해 지속적으로 디버깅을 진행하였으며, 결국 적절한 길이에서 답변이 종료되도록 수정할 수 있었다. 디버깅 과정과 상세한 내용은 다음 글에서 다루도록 하겠다.

profile
공부하는 블로그😎

1개의 댓글

comment-user-thumbnail
2025년 5월 26일

좋은 글 잘 봤습니다 선생님!
혹시 어떤 환경에서 구현하셨는지 여쭤도 될까요?

답글 달기