[ DEVOCEAN] LLM OT LIAMA2 한국어 파인튜닝

Gandalf_Song
11 min readMay 8, 2024

--

머리말

스터디 전까지 스터디 그룹원들은 각자 하고 싶은 모델을 선택하여 한국어 학습 파인튜닝과 쿼로라를 진행했다.

윈도우에서의 BitsAndBytes GPU버전 미지원과 코랩의 T4 GPU와의 사투(GPU가 모자르면 다양한 에러와 라이브러이 오류를 만나게 된다) 끝에 코랩의 A100 GPU로 한번에 해결했다.

100개 정도만 학습해서 그런지 결과물은 도중에 끊겼다는게 아쉽다.

해당 모델을 파인튜닝해보면서 느낀건 적어도 24gb정도되는 그래픽카드가 있어야 수월할 것 같다라는 것이다.

서버의 경우에는 메모리가 부족하거나 cpu가 견디지 못하면 OOM 또는 timeout | badgateway 같은 일들이 벌어지는데

이 LLM의 경우 불러와서 메모리에 적재를 그때그때 해서 그런지 라이브러리 에러가 정말 많이 났다. (대부분 뭐가 없다 | 뭐가 불러오지 못했다)
이 경우가 아니면 gpu oom이 발생되었다.

추론의 경우에는 윈도우 | 맥 상관없이 돌 것같은데 쿼로라로 불러오고 트레이닝 하는 것은 리눅스 말고는 답이 없는 상태인것 같다.

아직 까지 밑 라이브러리 함수들을 완벽히 이해하지는 못했지만, 해당 것은 앞으로 스터디 학습이 진행되니 공부할 예정이다.

필수 라이브러리 설치

!pip3 install -q -U transformers==4.38.2
!pip3 install -q -U datasets==2.18.0
!pip3 install -q -U bitsandbytes==0.42.0
!pip3 install -q -U peft==0.9.0
!pip3 install -q -U trl==0.7.11
!pip3 install -q -U accelerate==0.27.2

상수 선언

HUGGING_TOKKEN = "토큰"
BASE_MODEL = "meta-llama/Llama-2-7b-hf"
DATASET = "daekeun-ml/naver-news-summarization-ko"
OUT_MODEL = "llama2-2b-sum-ko"
FINETUNE_MODEL_DIR = './llama2-2b-sum-ko'

필수 객체 로드

from huggingface_hub import login, notebook_login

class HuggingFaceNotebookLogin:
def __init__(self, toekn ):
self.token = toekn
def login(self):
print("Logging in...")
login(self.token)
#notebook_login()
from datasets import load_dataset
class DataSetter:
def __init__(self, dataset_name):
self.dataset_name = dataset_name
self.dataset = self.load_dataset()
def load_dataset(self):
return load_dataset(self.dataset_name)
def get_dataset(self):
return self.dataset
def generate_prompt(example):
prompt_list = []
for i in range(len(example['document'])):
prompt_list.append(
f"""<|begin_of_text|><|start_header_id|>user<|end_header_id|>다음 글을 요약해주세요:
{example['document'][i]}<|eot_id|><|start_header_id|>assistant<|end_header_id|>
{example['summary'][i]}<|eot_id|>"""
)
return prompt_list
import torch
from transformers import BitsAndBytesConfig
from peft import LoraConfig

class LoraCfg:
def __init__(self):
self.r = 8
self.lora_alpha = 8
self.lora_dropout = 0.05
self.target_modules = ["q_proj", "o_proj", "k_proj", "v_proj", "gate_proj", "up_proj", "down_proj"]
self.bias="none",
self.task_type="CAUSAL_LM",
def get_config(self):
return LoraConfig(r=self.r,lora_alpha=self.lora_alpha,lora_dropout=self.lora_dropout,target_modules=self.target_modules,task_type=self.task_type)
class BabCfg:
def __init__(self):
self.load_in_4bit = True
self.bnb_4bit_quant_type = "nf4"
self.bnb_4bit_compute_dtype = torch.float16
def get_config(self):
return BitsAndBytesConfig(load_in_4bit=self.load_in_4bit,bnb_4bit_quant_type=self.bnb_4bit_quant_type,bnb_4bit_compute_dtype=self.bnb_4bit_compute_dtype)

허깅페이스 로그인 (토큰버전) \ 쿼로라 \ 모델 로드 \ 학습

from os import pipe
import torch
from datasets import Dataset, load_dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig, pipeline, TrainingArguments
from peft import PeftModel
from trl import SFTTrainer

HuggingFaceNotebookLogin(HUGGING_TOKKEN).login()
print("Logged in successfully!")
data_set = DataSetter(DATASET).get_dataset()
print("Loaded dataset successfully!")
# Set up the model
model = AutoModelForCausalLM.from_pretrained(BASE_MODEL, device_map="auto", quantization_config=BabCfg().get_config())
print("Set up the model successfully!")
# Set up the training arguments
trainer = SFTTrainer(
model=model,
train_dataset=data_set['train'],
max_seq_length=512,
args=TrainingArguments(
output_dir="outputs",
# num_train_epochs = 1,
max_steps=100,
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
optim="paged_adamw_8bit",
warmup_steps=0.03,
learning_rate=2e-4,
fp16=True,
logging_steps=100,
push_to_hub=False,
report_to='none',
),
peft_config=LoraCfg().get_config(),
formatting_func=generate_prompt,
)
# Train the model
trainer.train()
print("Trained the model successfully!")

모델 저장

ADAPTER_MODEL = "lora_adapter"
trainer.model.save_pretrained(ADAPTER_MODEL)
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, low_cpu_mem_usage=True, weight="right")
model = model.merge_and_unload()
model.save_pretrained(OUT_MODEL)
print("Saved the model successfully!")

모델 로드 \ 모델 추론

def generate_prompts_sentence(example):
prompt = f"""<|begin_of_text|><|start_header_id|>user<|end_header_id|>다음 글을 요약해주세요:
{example['document']}<|eot_id|><|start_header_id|>assistant<|end_header_id|>
{example['summary']}<|eot_id|>"""
return prompt
def app(dataset):
finetune_model = AutoModelForCausalLM.from_pretrained(FINETUNE_MODEL_DIR, quantization_config=bnb_config, device_map={"":0})
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, add_special_tokens=True)
print("Set up the model successfully!")
pipe_finetuned = pipeline("text-generation", model=BASE_MODEL, tokenizer=tokenizer, max_new_tokens=512)
print("Set up the pipeline successfully!")
doc = dataset['test']['document'][2]
pipe_finetuned = pipeline("text-generation", model=finetune_model, tokenizer=tokenizer, max_new_tokens=512)
outputs = pipe_finetuned(
generate_prompts_sentence(dataset['test'][2]),
do_sample=True,
temperature=0.2,
top_k=50,
top_p=0.95,
add_special_tokens=True
)
print(outputs[0]['generated_text'][len(generate_prompts_sentence(dataset['test'][2])):])
app(data_set)
OUTPUT
뉴욕 증권거래소 NYSE 에서 다우존스 산업평균지수는 전장보다 253.88포인트 0.82% 하락한 30 775.43으로 거래를 마쳤다. S P500지수는 전장보다 33.45포인트 0.88% 하락한 3 785.38을 기술주 중심의 나스닥 지수는 전장보다 149.16포인트 1.33% 하락한 11 028.74로 장을 마감했다. 올해 상반기 마지막 거래일인 이날 뉴욕 증시 3대 지수는 모두 크게 저조한 실적을 기록했다. S P500의 경우 연초 기준으로 21.08% 하락했는데 이는 52년 전인 1970년 상반기 이후 가장 낮은 수준이다. 분기 기준으로 보면 다우와 S P500은 지난 2020년 1분기 이후 최악의 분기 실적이다. 홈리치 버그의 최고투자책임자 스테파니 �

--

--