Llama-3.2-1B-Instruction 모델 파인튜닝하기
Llama 모델이란?
먼저, Llama 모델에 대해 간단히 소개하겠습니다.
Llama(Large Language Model Meta AI)는 Meta AI에서 개발한 대규모 언어 모델입니다.
OpenAI의 GPT 시리즈와 마찬가지로 트랜스포머 아키텍처를 기반으로 하며, 다양한 크기와 성능을 제공합니다.
이 포스팅에서 다룰 Llama-3.2-1B-Instruction 모델은 약 10억 개의 파라미터를 가진 모델로, sLLM에 해당하는 아주 작은 파라미터를 가지고 있지만, 특정 태스크에서는 뛰어난 성능을 보여주는 모델입니다.
한국어 QA 튜닝 방법
한국어 QA 시스템의 발전은 국내 AI 산업에서 매우 중요한 부분을 차지합니다.
검색 엔진, 고객 서비스 챗봇, 교육용 AI 등 다양한 분야에서 활용될 수 있기 때문입니다.
하지만 대부분의 대형 언어 모델들이 영어를 중심으로 학습되어 있어, 한국어 처리에는 아직 개선의 여지가 많습니다.
또한 QA와 같은 정해진 작은 단위의 태스크를 70B 이상의 대형 모델로 돌리기에는 GPU와 같은 하드웨어 비용의 이슈가 많이 생깁니다.
저는 이를 가벼운 크기의 언어 모델인 1B 모델로 해결하고자 합니다.
LoRA(Low-Rank Adaptation) 기법을 사용해 1B 모델을 한국어 QA 데이터셋으로 파인튜닝할 예정입니다.
(*LoRA는 대규모 모델을 파인튜닝할 때 메모리와 계산 자원을 크게 절약하면서도 효율적으로 성능을 향상시킬 수 있는 방법입니다.)
LoRA를 통해 얻어낸 새로운 웨이트를 기존 1B 모델과 병합함으로써, 한국어 QA 태스크를 더 잘 수행할 수 있도록 만들 계획입니다.
이를 통해, 기존 모델의 성능을 유지하면서도 특정 도메인에 맞춘 최적의 성능을 기대할 수 있습니다.
데이터셋 가공
데이터셋은 한국어 QA 데이터를 담고있는 KorQuAD/squad_kor_v1를 사용했습니다. 데이터셋 바로가기
KorQuAD/squad_kor_v1 · Datasets at Hugging Face
운전 구간 내의 모든 역에 정차한다. 덴노지 역 및 히네노 역 등에시 시발하여 오토리 역·히네노 역·이즈미스나가와 역·와카야마 역 간에 운전되고 있다. 쓰루가오카 역, 스기모토초 역, 우에
huggingface.co
이 데이터셋은 크게 질문(question), 문맥(context), 정답(answers) 세 파트로 구성되어있습니다.
LLM 모델에게도 동일하게 Q-C-A 순서로 프롬프트를 짜고, 이 데이터를 학습하라고 다음과 같이 알려줄 수 있습니다.
answer의 경우 여러개가 들어가있을 수 있어서 iteration을 통해 값을 꺼내서 변환해주는 과정이 추가됩니다.
from datasets import load_dataset
def formatting_prompts_func(examples):
eos_token = '<|end_of_text|>' # Llama 모델의 eos token
korQuAD_prompt = """ # 학습시킬 Prompt의 형태
### Question:
{}
### Context:
{}
### Answer:
{}
"""
#데이터셋에서 원하는 컬럼을 가져와 instruction, input, output으로 매핑
instructions = examples["question"]
inputs = examples["context"]
outputs = [item['text'][0] for item in examples["answers"]]
texts = []
#데이터 뒤에 eos_token을붙여서 최종 데이터 가공
for instruction, input, output in zip(instructions, inputs, outputs):
text = korQuAD_prompt.format(instruction, input, output) + eos_token
texts.append(text)
return {"text": texts}
이렇게 포매팅함수를 만들고나면 다음과 같은 코드를 통해 Dataset을 변환할 수 있습니다.
dataset = load_dataset("KorQuAD/squad_kor_v1", split = "train")
dataset = dataset.map(
formatting_prompts_func,
batched=True,
)
print(dataset[:1])
{'id': ['6566495-0-0'], 'title': ['파우스트_서곡'], 'context': ['1839년 바그너는 괴테의 파우스트을 처음 읽고 그 내용에 마음이 끌려 이를 소재로 해서 하나의 교
향곡을 쓰려는 뜻을 갖는다. 이 시기 바그너는 1838년에 빛 독촉으로 산전수전을 다 걲은 상황이라 좌절과 실망에 가득했으며 메피스토펠레스를 만나는 파우스트의 심경
에 공감했다고 한다. 또한 파리에서 아브네크의 지휘로 파리 음악원 관현악단이 연주하는 베토벤의 교향곡 9번을 듣고 깊은 감명을 받았는데, 이것이 이듬해 1월에 파우
스트의 서곡으로 쓰여진 이 작품에 조금이라도 영향을 끼쳤으리라는 것은 의심할 여지가 없다. 여기의 라단조 조성의 경우에도 그의 전기에 적혀 있는 것처럼 단순한 정
신적 피로나 실의가 반영된 것이 아니라 베토벤의 합창교향곡 조성의 영향을 받은 것을 볼 수 있다. 그렇게 교향곡 작곡을 1839년부터 40년에 걸쳐 파리에서 착수했으나
1악장을 쓴 뒤에 중단했다. 또한 작품의 완성과 동시에 그는 이 서곡(1악장)을 파리 음악원의 연주회에서 연주할 파트보까지 준비하였으나, 실제로는 이루어지지는 않
았다. 결국 초연은 4년 반이 지난 후에 드레스덴에서 연주되었고 재연도 이루어졌지만, 이후에 그대로 방치되고 말았다. 그 사이에 그는 리엔치와 방황하는 네덜란드인
을 완성하고 탄호이저에도 착수하는 등 분주한 시간을 보냈는데, 그런 바쁜 생활이 이 곡을 잊게 한 것이 아닌가 하는 의견도 있다.'], 'question': ['바그너는 괴테의
파우스트를 읽고 무엇을 쓰고자 했는가?'], 'answers': [{'text': ['교향곡'], 'answer_start': [54]}], 'text': ['\n ### Question:\n 바그너는 괴테의
파우스트를 읽고 무엇을 쓰고자 했는가?\n\n ### Context:\n 1839년 바그너는 괴테의 파우스트을 처음 읽고 그 내용에 마음이 끌려 이를 소재로 해서 하
나의 교향곡을 쓰려는 뜻을 갖는다. 이 시기 바그너는 1838년에 빛 독촉으로 산전수전을 다 걲은 상황이라 좌절과 실망에 가득했으며 메피스토펠레스를 만나는 파우스트
의 심경에 공감했다고 한다. 또한 파리에서 아브네크의 지휘로 파리 음악원 관현악단이 연주하는 베토벤의 교향곡 9번을 듣고 깊은 감명을 받았는데, 이것이 이듬해 1월
에 파우스트의 서곡으로 쓰여진 이 작품에 조금이라도 영향을 끼쳤으리라는 것은 의심할 여지가 없다. 여기의 라단조 조성의 경우에도 그의 전기에 적혀 있는 것처럼 단
순한 정신적 피로나 실의가 반영된 것이 아니라 베토벤의 합창교향곡 조성의 영향을 받은 것을 볼 수 있다. 그렇게 교향곡 작곡을 1839년부터 40년에 걸쳐 파리에서 착
수했으나 1악장을 쓴 뒤에 중단했다. 또한 작품의 완성과 동시에 그는 이 서곡(1악장)을 파리 음악원의 연주회에서 연주할 파트보까지 준비하였으나, 실제로는 이루어지
지는 않았다. 결국 초연은 4년 반이 지난 후에 드레스덴에서 연주되었고 재연도 이루어졌지만, 이후에 그대로 방치되고 말았다. 그 사이에 그는 리엔치와 방황하는 네덜
란드인을 완성하고 탄호이저에도 착수하는 등 분주한 시간을 보냈는데, 그런 바쁜 생활이 이 곡을 잊게 한 것이 아닌가 하는 의견도 있다.\n\n ### Answer:\n
교향곡\n <|end_of_text|>']}
파인튜닝
파인튜닝을 위해서는 transformer, peft, trl 등의 라이브러리가 필요합니다.
$pip install transformer trl peft
설치가 완료되면 다음과 같이 라이브러리를 추가해줍니다.
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
Trainer,
TrainingArguments
)
import torch
from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model
from trl import SFTTrainer
PEFT는 parameter-efficient fine tuning의 약자로 LLM이 기존에 가지고있던 대부분의 파라미터를 프리징하고, 일부의 파라미터만을 업데이트해 모델을 튜닝하는 방식을 말합니다. 기존의 거대한 크기의 베이스라인 모델은 건드리지않고, 아주 작은 크기의 어댑터 체크포인트만을 출력하기때문에 용량 관리에도 적합합니다.
관련 라이브러리 import가 끝나면 다음과 같이 meta-llama의 huggingface 레포지토리에서 모델을 내려받고 불러옵니다.
이 작업 전에는 해당 레포지토리에서 권한을 취득해야하며, huggingface 토큰을 받아 로그인하는 작업이 포함될 수 있습니다.
model_path = "meta-llama/Llama-3.2-1B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.bfloat16,
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained(
model_path
)
tokenizer.pad_token = '<|end_of_text|>'
model = prepare_model_for_kbit_training(model) #Quantization이 수행된 모델로 준비
이후 LoRA 파라미터를 설정하고 모델에 LoRA를 적용합니다.
# LoRA 설정
lora_config = LoraConfig(
r=16,
lora_alpha=16,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj", "gate_proj", "down_proj", "up_proj"],
lora_dropout=0.01,
bias="none",
task_type="CAUSAL_LM",
)
# # LoRA 적용
model = get_peft_model(model, lora_config)
각 하이퍼 파라미터를 간략하게 설명한 내용은 다음과 같습니다.
1) r : 어댑터 파라미터의 차원 갯수, 기본값은 8, r값이 증가하면 LoRA 학습 과정에서 업데이트해야하는 매개변수가 증가
2) lora_alpha: 어댑터의 스케일링 값, 어댑터에서 나온 output에 곱해지는 값으로 기본값은 8
3) lora_dropout: LoRA 레이어의 드롭아웃 확률을 의미하며, 기본값은 0, 드롭아웃은 과적합을 줄이기 위해 무작위로 뉴런을 선택해 생략하는 방식
4) target_modules: LoRA 학습에서 모델 아키텍쳐 중 타게팅할 모듈 리스트, 많은 모듈을 타게팅하면 훈련 시간이 증가, 주로 transformer의 어텐션 블록만 타게팅함
5) bias: LoRA 바이아스 유형, 기본값은 None
마지막으로 Training Arguments를 정의하고, SFTTrainer를 이용해 LoRA 학습을 수행합니다.
training_params = TrainingArguments(
output_dir="/results",
num_train_epochs=5, # 기본값은 3
per_device_train_batch_size=1, # 기본값은 8
gradient_accumulation_steps=1, # 기본값 1
optim="paged_adamw_32bit",
save_steps=10000,
logging_steps=25,
learning_rate=2e-4,
weight_decay=0.001,
fp16=False,
bf16=False,
max_grad_norm=0.3,
max_steps=-1,
warmup_ratio=0.03,
group_by_length=True,
lr_scheduler_type="constant",
)
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
peft_config=lora_config,
dataset_text_field="text",
max_seq_length=None, # 256, 512 등으로 수정할 수 있음.
tokenizer=tokenizer,
args=training_params,
packing=False,
)
trainer.train()
ADAPTER_MODEL = "lora_adapter"
trainer.model.save_pretrained(ADAPTER_MODEL)
본인의 GPU 환경에 따라 배치 사이즈와 gradient_accumulation_steps 조정을 통해 학습에 대한 하이퍼 파라미터 튜닝이 가능하며, 저는 아주 작은 단위인 배치1로 학습을 진행했습니다.
학습은 총 5epoch를 돌렸으며 RTX4090*3EA로 총 30시간정도 소요되었습니다.
r값과 target module을 줄이면 더 빠른 시간에 학습이 되겠지만 현재는 성능 테스트를 위해 위와 같이 파라미터를 설정했습니다.
최종적으로 나온 어댑터를 결합해 인퍼런스해보고싶으시다면 다음과 같은 코드를 사용할 수 있습니다.
BASE_MODEL = "meta-llama/Llama-3.2-1B-Instruct"
ADAPTER_MODEL = "lora_adapter"
TARGET_MODEL = 'models/Llama-3.2-1B-Instruct-finetuned'
model = AutoModelForCausalLM.from_pretrained(BASE_MODEL, device_map='auto', torch_dtype=torch.float16)
model = PeftModel.from_pretrained(model, ADAPTER_MODEL, device_map='auto', torch_dtype=torch.float16)
model = model.merge_and_unload()
인퍼런스 테스트
테스트는 총 3가지 질문을 통해 진행했습니다.
Question | Context | Answer | 정답 여부 |
순천향대학교의 위치는? | 순천향대학교는 충청남도 아산시 신창면 순천향로에 위치한 사립 종합대학교입니다. 순천향대학교에는 1983년 공과대학이 설립되었습니다. |
충청남도 아산시 신창면 순천향로 | O |
아이브의 리더는 누구야? | 아이브(IVE)는 대한민국의 스타쉽 엔터테인먼트 소속의 6인조 걸그룹으로, 2021년 12월 1일에 데뷔했습니다. 그룹 이름인 'IVE'는 "I HAVE"에서 유래했으며, "내가 가진 것을 당당하게 보여주겠다"는 의미를 담고 있습니다. 데뷔와 동시에 큰 인기를 끌며 빠르게 주목받는 그룹 중 하나로 자리 잡았습니다. 멤버 구성: 안유진 (리더), 가을, 레이, 장원영, 리즈, 이서 주요 활동 및 히트곡: ELEVEN (2021년): 데뷔곡으로, 세련된 퍼포먼스와 멜로디로 많은 사랑을 받았습니다. LOVE DIVE (2022년): 중독성 있는 멜로디와 매혹적인 콘셉트로 큰 인기를 얻으며 음악방송에서 다수의 1위를 차지했습니다. After LIKE (2022년): 'LOVE DIVE'에 이어 히트를 친 곡으로, 아이브의 개성을 더 확고히 하는 곡이었습니다. 아이브는 독특한 콘셉트와 뛰어난 무대 퍼포먼스로 국내외 팬들에게 사랑받고 있으며, 각 멤버들 역시 개별적인 매력을 발산하며 활발히 활동하고 있습니다. 장원영과 안유진은 데뷔 전부터 아이즈원 활동을 통해 주목받았으며, 이후 아이브로서도 성공적인 활동을 이어가고 있습니다. |
안유진 | O |
아이브 데뷔곡 알려줘 | ELEVEN | O |
마치며
이 프로젝트는 어떻게하면 효과적으로 QA만을 수행하는 sLLM을 구축할 수 있을까 고민하던 차에 Llama-3.2가 공개되고 1B 모델을 확인하자마자 시작한 프로젝트입니다.
기존 8B 모델을 이용해 해당 Task를 수행하는 모델을 고민했었지만 이번 기회를 통해 더 작은 모델로도 가능하다는 것을 확인할 수 있었으며 온디바이스 AI나 경량화가 필요한 필드에 충분히 사용가능할 것으로 생각합니다.
관련 내용은 제 huggingface repository에 올려두었습니다. 바로가기
NakJun/Llama-3.2-1B-Instruct-korQuAD-v1 · Hugging Face
Llama-3.2-1B-Instruct-korQuAD-v1 이 모델은 Llama-3.2-1B-Instruct를 기반으로 한국어 질의응답 태스크에 대해 파인튜닝된 모델입니다. 모델 설명 기본 모델: Llama-3.2-1B-Instruct 학습 데이터셋: KorQuAD v1.0 학습 방
huggingface.co
감사합니다.