Deepseek R1 QLoRA 파인튜닝
사용 개념
Deepseek-R1-Distill-Llama-8B
이 블로그 글은 Deepseek-R1-Distill-Llama-8B를 4비트 양자화와 LoRA를 활용해 파인튜닝하고 허깅페이스에 모델을 호스팅하는 것까지를 설명한다.
코드 리뷰를 위해 파인튜닝하였는데, 그 코드를 변형하여 포스팅한다.
Deepseek-R1-Distill-Llama-8B모델은 딥시크 R1을 경량화한 모델로 8B크기라서 쓸만한 편이다.
양자화
모델을 그냥 파인튜닝(FP32)하면 메모리가 상당히 많이 필요하다. 이를 위해 모델의 가중치를 낮은 비트 정밀도로 변경하는 것을 양자화라 하는데 아래로 내려갈수록 성능이 떨어질 우려는 있지만 리소스 사용량과 속도 면에서 좋다.
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
load_in_4bit=True, #4비트 양자화
device_map="auto"
)
LoRA
모델 전체 업데이트가 아니라 특정 가중치만 학습하는 것이다. 전체 모델을 건드리는 것은 매우매우 거대한 작업이다...실제 필요한 작업에 비해 사이즈가 너무 크다. 따라서 일부 레이어만 변화를 주는 것.
코드에서는 q_proj, v_proj, k_proj같은 레이어에만 적용하고 있는 것이다. 이러면 메모리를 많이 절약할 수 있다.
Unsloth 라이브러리
LoRA 파인튜닝을 최적화하는 라이브러리다. 위의 양자화와 LoRA기법, 그러니까 QLoRA를 위해 사용하는 라이브러리다. 장점은 뭐 이렇다고 한다.
트랜스포머보다 개별 모델에 최적화
수동 그래디언트 계산(파이토치 Autograd는 LoRA에서 최적화가 좀 별로일수도...)
WandB
MLops 툴이다. 머신러닝계의 데이터독 가입하면 키를 받을 수 있는데 키를 등록하고
wandb.login(key="wandb키")
#프로젝트명은 알아서
wandb.init(project="Finetuning-Deepseek-R1", job_type="training")
이런식으로 등록하고 WandB 웹에 접속해서 모니터링할 수 있다.
코드
하단 코드는 코랩 T4 GPU면 충분하다.
필요한 라이브러리 설치
!pip install transformers datasets bitsandbytes huggingface-hub accelerate
!pip install --upgrade --force-reinstall --no-cache-dir git+https://github.com/unslothai/unsloth.git
!pip install wandb
!pip install unsloth_zoo
!pip install xformers
허깅페이스와 wandb로그인
from huggingface_hub import login
import wandb
hf_token = "HF토큰"
login(hf_token)
wandb.login(key="wandb키")
#프로젝트명은 알아서
wandb.init(project="Finetuning-Deepseek-R1", job_type="training")
데이터셋, 모델 로딩
from datasets import load_dataset
dataset = load_dataset("사용자명/데이터셋", split="필요한만큼")
prompt_style = """아래는 코드와 해당 코드에 대한 리뷰 요청이다.
코드를 검토하고 3~4줄의 간단한 코드 리뷰를 제공하라.
### 코드:
{}
### 코드 리뷰:
{}
"""
def format_prompt(example):
code = example['prompt']
review = example['response']
return{"text": prompt_style.format(code, reviw)}
dataset = dataset.map(format_prompt)
모델 로드하기
from unsloth import FastLanguageModel
# 모델 로드 (4-bit 양자화 활성화)
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/DeepSeek-R1-Distill-Llama-8B",
max_seq_length=2048,
load_in_4bit=True,
token=hf_token
)
LoRA
model = FastLanguageModel.get_peft_model(
model=model,
r=16,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
lora_alpha=16,
lora_dropout=0,
)
훈련하기
from transformers import TrainingArguments
from trl import SFTTrainer
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset,
dataset_text_field="text",
args=TrainingArguments(
per_device_train_batch_size=4,
gradient_accumulation_steps=2,
max_steps=100,
warmup_steps=10,
learning_rate=2e-4,
fp16=True,
logging_steps=10,
output_dir="outputs",
),
)
trainer.train()
모델 저장 후 호스팅
model.save_pretrained("저장경로")
tokenizer.save_pretrained("저장경로")
NEW_REPO_NAME = "호스팅 경로"
model.push_to_hub(NEW_REPO_NAME)
tokenizer.push_to_hub(NEW_REPO_NAME)

