Notice
Recent Posts
Recent Comments
Link
Ssul's Blog
AI Product 개발전략과 개발기 - text-generation모델 파인튜닝 본문
앞 글에서 이야기했던 우여곡절(?)을 마치고, 드디어 학습에 들어간다.
그 첫번째는 LLM을 Instruction-tuning으로 파인튜닝
이제부터는 코드와 주석 위주로 가겠다.
1. 어떤 모델을 foundation모델로 사용할 것인가?
- 한글이 잘 될것
- 될수 있으면 작을 것
이 두가지 기준을 가지고 접근했을때, 야놀자에서 나온 eeve 평이 좋아서, 우선 eeve2.8B로 작업해보고, 성능이 괜찮다 생각되면 10.8B로 진행을 하여보자
2. 초기 셋팅
# 코랩 왼쪽편에 열쇠 모양이 있다. 클릭해서 HF_TOKEN에 자신의 허깅페이스 토큰을 넣는다
from google.colab import userdata
userdata.get('HF_TOKEN')
###########################################
# 0. Huggingface login
from huggingface_hub import notebook_login
notebook_login()
# 로그인 창이 뜨면, 자신의 토큰을 입력하여 로그인 한다
##########################################
# 1-3. 모듈 다운
!pip install -q -U datasets
!pip install -q -U bitsandbytes
!pip install -q -U accelerate
!pip install -q -U peft
!pip install -q -U trl
###########################################
# 2-1. 모듈 불러오기
import os
import torch
import transformers
from datasets import load_from_disk
from transformers import (
BitsAndBytesConfig,
AutoModelForCausalLM,
AutoTokenizer,
Trainer,
TextStreamer,
pipeline
)
from peft import (
LoraConfig,
prepare_model_for_kbit_training,
get_peft_model,
get_peft_model_state_dict,
set_peft_model_state_dict,
TaskType,
PeftModel
)
from trl import SFTTrainer
3. 모델 양자화해서 가져와서 > 로라붙이기
#@title 🤗 Base model 선택하기
device = 'auto' #@param {type: "string"}
base_LLM_model = 'yanolja/EEVE-Korean-Instruct-2.8B-v1.0' #@param {type: "string"}
###########################################
# 3-1. 모델 다운로드
model = AutoModelForCausalLM.from_pretrained(
base_LLM_model,
# load_in_8bit=True, # LoRA
# torch_dtype=torch.float16,
load_in_4bit=True, # Quantization Load
device_map=device)
tokenizer = AutoTokenizer.from_pretrained(base_LLM_model)
- load_in_4bit=True를 통해서 양자화된 모델을 가져오기
이제 LoRA를 붙여 보자
###########################################
# 파인튜닝 고고
# NF4 양자화를 위한 설정
lora_config = LoraConfig(
r=4, # LoRA 가중치 행렬의 rank. 정수형이며 값이 작을수록 trainable parameter가 적어짐
lora_alpha=8, # LoRA 스케일링 팩터. 추론 시 PLM weight와 합칠 때 LoRA weight의 스케일을 일정하게 유지하기 위해 사용
lora_dropout=0.05,
target_modules=['q_proj', 'k_proj', 'v_proj', 'o_proj', 'gate_proj', 'up_proj', 'down_proj'], # LoRA를 적용할 layer. 모델 아키텍처에 따라 달라짐
bias='none', # bias 파라미터를 학습시킬지 지정. ['none', 'all', 'lora_only']
task_type=TaskType.CAUSAL_LM
)
# 양자화된 모델을 학습하기 전, 전처리를 위해 호출
model = prepare_model_for_kbit_training(model)
# LoRA 학습을 위해서는 아래와 같이 peft를 사용하여 모델을 wrapping 해주어야 함
model = get_peft_model(model, lora_config)
# 학습 파라미터 확인
model.print_trainable_parameters()
4. 데이터 셋팅하기
###########################################
# 4-1. 모듈 불러오기
import os
import torch
import transformers
import pandas as pd
from datasets import load_dataset, Dataset, concatenate_datasets
from transformers import AutoModelForCausalLM, AutoTokenizer
import pandas as pd
# CSV 파일 경로를 지정합니다.
file_path = '파일경로/spam_dataset_final.csv'
# CSV 파일을 pandas DataFrame으로 불러옵니다.
dataset = pd.read_csv(file_path)
# dataset = pd.read_csv(file_path, encoding='utf-8')
# DataFrame 출력
print(dataset)
sms에 문자 원문이 들어있다. LLM 파인 튜닝을 위해, 텍스트를 preprocessing진행하자
import re
# 텍스트 정리 함수 정의
def clean_text(text):
text = re.sub(r'\[.*?\]', '', text) # 대괄호 안의 텍스트 제거
text = re.sub(r'\(.*?\)', '', text) # 소괄호 안의 텍스트 제거
text = re.sub(r'\n', ' ', text) # 줄바꿈 문자 제거
text = re.sub(r'\s+', ' ', text) # 여러 개의 공백을 하나의 공백으로 대체
text = re.sub(r'[^가-힣a-zA-Z\s]', '', text) # 한글, 영어 알파벳, 공백을 제외한 문자 제거
return text.strip()
# 'sms' 컬럼에 정리 함수 적용
dataset['cleaned_sms'] = dataset['sms'].apply(clean_text)
from datasets import Dataset
# pandas DataFrame을 Dataset으로 변환
dataset = Dataset.from_pandas(dataset)
- cleaned_sms에 다듬어진 sms 데이터를 추가합니다
- 데이터를 dataset객체로 만듭니다
Instruction-tuning*을 위한 템플릿을 준비합니다
(사전 학습된 언어 모델(PLM)을 특정 작업에 더 적합하게 만드는 데 사용되는 기법 중 하나입니다. 이 기법은 모델에게 특정한 지시(instruction)를 제공하여 그 지시를 따라 작업을 수행하도록 조정하는 과정)
###########################################
# Instruction tuning을 위한 template 작성.
instruct_template = {
"prompt_input": "{instruction}\n\n###\n\n\n이 문자는 다음 중 어떤 문자인가?(1개만 고르시오)\n\n프로모션문자\n스팸문자\n정치선거문자\n정부문자\n개인문자\n인증문자\n\n답변:\n",
"prompt_no_input": "{instruction}\n\n###\n\n\n이 문자는 다음 중 어떤 문자인가?(1개만 고르시오)\n\n프로모션문자\n스팸문자\n정치선거문자\n정부문자\n개인문자\n인증문자\n\n답변:\n",
"response_split": "답변:\n"
}
def generate_prompt(data_point):
instruction = data_point["cleaned_sms"]
# input = data_point["input"]
label = data_point["label"]
if input:
res = instruct_template["prompt_input"].format(instruction=instruction)
else:
res = instruct_template["prompt_no_input"].format(instruction=instruction)
if label:
res = f"{res}{label}<|im_end|>" # eos_token을 마지막에 추가
data_point['text'] = res
return data_point
# 데이터셋에 프롬프트 적용
remove_column_keys = dataset.features.keys() # 기존 컬럼(instruction, output 등) 제거
dataset_cvted = dataset.shuffle().map(generate_prompt, remove_columns=remove_column_keys)
def tokenize_function(examples):
outputs = tokenizer(examples["text"], truncation=True, max_length=512)
return outputs
remove_column_keys = dataset_cvted.features.keys()
dataset_tokenized = dataset_cvted.map(tokenize_function, batched=True, remove_columns=remove_column_keys)
# dataset_tokenized 분리
dataset_dict = dataset_tokenized.train_test_split(test_size=0.2, seed=42)
dataset_train = dataset_dict['train']
dataset_test = dataset_dict['test']
5. 학습하기
# Data Collator 역할
# 각 입력 시퀀스의 input_ids(토큰) 길이를 계산하고, 가장 긴 길이를 기준으로 길이가 짧은 시퀀스에는 패딩 토큰 추가
def collate_fn(examples):
examples_batch = tokenizer.pad(examples, padding='longest', return_tensors='pt')
examples_batch['labels'] = examples_batch['input_ids'] # 모델 학습 평가를 위한 loss 계산을 위해 입력 토큰을 레이블로 사용
return examples_batch
train_args = transformers.TrainingArguments(
per_device_train_batch_size=2, # 각 디바이스당 배치 사이즈. 작을수록(1~2) 좀 더 빠르게 alignment 됨
gradient_accumulation_steps=4,
warmup_steps=1,
num_train_epochs=1,
max_steps=1000,
learning_rate=2e-4, # 학습률
bf16=True, # bf16 사용 (지원되는 하드웨어 확인 필요)
output_dir="outputs",
optim="paged_adamw_8bit", # 8비트 AdamW 옵티마이저
logging_steps=50, # 로깅 빈도
save_total_limit=3 # 저장할 체크포인트의 최대 수
)
trainer = SFTTrainer(
model=model,
train_dataset=dataset_train,
max_seq_length=512, # 최대 시퀀스 길이
args=train_args,
dataset_text_field="text",
data_collator=collate_fn
)
model.config.use_cache = False
trainer.train()
# 평가 수행
eval_results = trainer.evaluate(eval_dataset=dataset_test)
print(f"Evaluation Results: {eval_results}")
6. 파인튜닝 모델 허깅페이스에 올리기(LoRA파라미터만 올리기)
model_name = f"여러분의 허깅페이스 아이디/EEVE-Korean-2.8b_LoRA_0612"
model.push_to_hub(model_name, use_auth_token=True)
'AI & ML > 사용하기' 카테고리의 다른 글
AI Product 개발전략과 개발기 - 임베딩 Top-k전략 (0) | 2024.06.28 |
---|---|
AI Product 개발전략과 개발기 - text-classification모델 파인튜닝 (0) | 2024.06.27 |
Runpod사용하기 (0) | 2024.06.12 |
RAG가 적용된 나만의 챗봇 만들기(langchain, FastAPI, streamlit) (0) | 2024.05.09 |
[ChatGPT] OpenAI임베딩 이용해서 RAG구현(langchain,vectordb) (0) | 2024.02.23 |