LLM 파인튜닝 양자화 파이프라인

seongyun·2025년 6월 1일

Neural Network

목록 보기
8/8

이번 주부터 드디어 기다리고 기다리던 프로젝트를 시작한다.
지금은 팀 구성이 완료되었고 팀 구성원들의 포지션을 배치 후 이제는 앞으로 어떻게 진행해야 될지에 대해 더 구체화시켜야 할 타이밍이라고 생각한다.
자 그럼 이제부터 앞으로의 진행 파이프라인을 간략하게 소개하는 시간을 가져보도록 하겠다.

사전 준비

  • EC2 인스턴스: g4dn.xlarge 또는 g5.xlarge (T4 GPU)
  • OS: Ubuntu 22.04
  • CUDA/cuDNN: CUDA 12.1
  • Python: >= 3.10
  • PyTorch: 2.2+ (CUDA 12.1/12.2 지원)
  • Transformers: Transformers >= 4.40
  • Accelerate, bitsandbytes, peft, transformers, datasets 등 필요

전체 파이프라인 개요

1. EC2 환경 세팅 및 의존성 설치
2. DeepSeek Coder 6.7B 모델 다운로드 및 로드
3. 학습용 데이터 전처리
4. PEFT 기반 파인튜닝 (LoRA/QLoRA)
5. 체크포인트 저장 및 평가
6. 양자화 (int4, int8)
7. 추론 파이프라인 구축 및 테스트

DeepSeek Coder 6.7B 모델 로드

from transformers import AutoTokenizer, AutoModelForCausalLM

model_name = "deepseek-ai/deepseek-coder-6.7b-instruct"

tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    trust_remote_code=True,
    device_map="auto",
    load_in_8bit=True,  # 또는 4bit for QLoRA
)

QLoRA 기반 파인튜닝

from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model
from transformers import TrainingArguments, Trainer

model = prepare_model_for_kbit_training(model)

lora_config = LoraConfig(
    r=8,
    lora_alpha=16,
    target_modules=["q_proj", "v_proj"],  # DeepSeek에 맞게 수정 필요
    lora_dropout=0.1,
    bias="none",
    task_type="CAUSAL_LM"
)
model = get_peft_model(model, lora_config)

training_args = TrainingArguments(
    output_dir="./results",
    per_device_train_batch_size=2,
    gradient_accumulation_steps=8,
    num_train_epochs=3,
    fp16=True,
    logging_steps=10,
    save_steps=500,
    save_total_limit=2,
    evaluation_strategy="no"
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset["train"]
)

trainer.train()

체크포인트 저장 및 평가

model.save_pretrained("./finetuned")
tokenizer.save_pretrained("./finetuned")

→ 추론 검증용 스크립트에서 예시 질문 넣고 결과 확인.

양자화 (GPTQ or bitsandbytes int4)

# 이미 QLoRA면 4bit 상태 → GPTQ 양자화로 변환 시 Huggingface Optimum 사용 가능
from transformers import AutoModelForCausalLM, AutoTokenizer
from optimum.gptq import quantize_model

model = AutoModelForCausalLM.from_pretrained("./finetuned")
quantized_model = quantize_model(model, quantization_config={"bits": 4})
quantized_model.save_pretrained("./quantized")

auto-gptq, ggml, gguf 등으로 변환 → 추론 성능 위주 최적화 가능

추론 파이프라인 테스트

from transformers import pipeline

pipe = pipeline("text-generation", model="./quantized", tokenizer="./quantized", device=0)
output = pipe("function to reverse a string in python:", max_new_tokens=100)
print(output[0]["generated_text"])

디렉토리 구조

llm_pipeline/
│
├── bootstrap.sh              # EC2 초기 셋업
├── preprocess.py             # 데이터 전처리
├── train.py                  # QLoRA 파인튜닝
├── quantize.py               # 양자화
├── infer.py                  # 추론 테스트
├── data/
│   └── your_data.jsonl
└── output/
    ├── finetuned/
    └── quantized/

최적의 파인튜닝 및 양자화 전략: QLoRA

QLoRA (Quantized Low-Rank Adaptation)는 다음과 같은 특징을 갖는다:

  • 4-bit NF4 양자화: 모델 가중치를 4-bit로 양자화하여 메모리 사용을 최소화한다.

  • LoRA 어댑터: 모델의 핵심 가중치는 동결하고, 적은 수의 파라미터만 학습하여 효율적인 파인튜닝을 수행한다.

  • Double Quantization: 양자화된 가중치에 추가 양자화를 적용하여 메모리 사용을 더욱 줄인다.

  • Paged Optimizers: 메모리 사용량을 관리하여 학습 중 메모리 초과를 방지한다.

이러한 기법들은 T4 GPU와 같은 제한된 자원에서도 대규모 언어 모델의 파인튜닝과 양자화를 가능하게 한다.

구성 요소

모델 및 토크나이저 로드:

from transformers import AutoTokenizer, AutoModelForCausalLM

model_id = "deepseek-ai/deepseek-coder-6.7b-instruct"

tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    device_map="auto",
    load_in_4bit=True,
    trust_remote_code=True
)

LoRA 설정 및 모델 준비:

from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training

model = prepare_model_for_kbit_training(model)

lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM"
)

model = get_peft_model(model, lora_config)

학습 설정 및 실행:

from transformers import TrainingArguments, Trainer

training_args = TrainingArguments(
    output_dir="./output",
    per_device_train_batch_size=1,
    gradient_accumulation_steps=8,
    num_train_epochs=3,
    fp16=True,
    save_total_limit=1,
    logging_steps=10,
    save_strategy="epoch",
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized["train"]
)

trainer.train()

모델 저장 및 추론 테스트:

model.save_pretrained("./finetuned")
tokenizer.save_pretrained("./finetuned")

from transformers import pipeline
pipe = pipeline("text-generation", model="./finetuned", tokenizer="./finetuned", device=0)
print(pipe("def reverse_string(s):", max_new_tokens=64)[0]['generated_text'])

자 이제 위의 예시 내용을 참고해서 본 내용을 진행하도록 하겠다.

목표 기반 고려사항

항목고려 이유
LLM 모델DeepSeek Coder 6.7B (코드 전용, instruction-tuned)
용도VSCode extension AI assistant
GPU 자원T4 (16GB)
CUDA12.1
요구사항짧은 응답시간, 문맥 유지력, 높은 정확도
핵심 기술QLoRA + 코드 전용 학습 데이터 + 컨텍스트 창 고려

전략 요약 (코드 어시스턴트 특화 관점)

1. 모델 아키텍처 선정 및 사전 준비

  • DeepSeek Coder 6.7B Instruct 기반 활용
  • chat 형태보다 completion-style 예측을 우선 고려 (→ prompt → 코드 구조)

2. 파인튜닝 전략: QLoRA + 코드 형식 데이터

데이터 구조(json)

{
  "prompt": "### Python function to calculate factorial:\ndef factorial(n):",
  "completion": "\n    if n == 0:\n        return 1\n    return n * factorial(n - 1)"
}
  • 인라인 주석 및 함수 설명 포함
  • Github 또는 StackOverflow 기반 데이터셋 (CodeSearchNet, BigCode 등) 활용 권장
  • 실제 VSCode 사용 시나리오 반영

토크나이저 주의

  • Tab (\t) 또는 space indentation 일관성 유지 필요
  • 불필요한 escape 제거 (ex. \n → \n)

하이퍼파라미터 (T4 최적화)

항목설정값
batch size1 (gradient accumulation 8~16)
fp16True
4-bit 양자화NF4, double quantization
LoRA r16
LoRA alpha32
Target modulesq_proj, v_proj, k_proj, o_proj

3. 추론 품질 테스트 시나리오

테스트 예시 프롬프트

# Write a Python function to check if a number is prime.

측정 기준

  • 정확도 (정답률)
  • 생성 속도 (응답 시간)
  • indentation 및 포맷 오류 여부
  • VSCode 플러그인 연결 시 실시간 대응 가능성

4. 양자화 (QLoRA 기반이면 추가 양자화 불필요)

하지만 추론 속도를 위한 GGUF or GPTQ 포맷 변환 고려 가능:

  • inference server (llama.cpp, exllama, vllm) 연동 목적

5. 최종 목표: VSCode 확장과 연결

  • 추론 API 서버 구축 (FastAPI, gRPC 등)
  • VSCode extension → 추론 서버 호출
  • context-aware prompt + streaming 응답 구성 (예: 사용자 입력 중간에 실시간 응답)

전체 구조 정리

단계기술/방법
모델deepseek-ai/deepseek-coder-6.7b-instruct
파인튜닝QLoRA (4bit) + LoRA r=16
양자화이미 4bit + double quantization 포함 (추가 X)
데이터코드 생성 특화, prompt-completion 형식
최적화gradient_accumulation_steps로 배치 증가
APIFastAPI + VSCode 연결 or REST call

이렇게 진행을 하니 궁금한 점이 하나 있어서 더 찾아본 내용이 있다.

양자화 사용 유/무에 대한 결론

이미 load_in_4bit=True로 로드한 DeepSeek Coder 6.7B 모델이라면,
추가적인 "양자화 작업"은 필요 없다.
즉, 추론을 위한 양자화는 이미 끝난 상태이다.

Hugging Face + bitsandbytes 환경에서의 load_in_4bit=True 의미

AutoModelForCausalLM.from_pretrained(
    model_id,
    load_in_4bit=True,  # <= 이게 바로 "양자화된 상태로 로드"를 의미함
    quantization_config=...,  # NF4, double quantization 설정
)
  • 이 옵션은 bitsandbytes 라이브러리를 통해 모델을 4비트 양자화 상태로 메모리에 불러오는 것이다.
  • 즉, 이미 로딩하는 순간부터 모델은 int4 타입으로 적재된다.
  • 사용되는 대표 기술들:
    - NF4 (Normal Float 4): 높은 정밀도 유지
    - Double Quantization: 두 단계로 양자화하여 메모리 효율 극대화

"양자화"라는 단어의 오해 정리

구분설명당신의 경우
파인튜닝 시 양자화 (QLoRA)학습 시 모델을 4비트로 불러와 적은 메모리로 훈련✅ 적용 중
추론 시 양자화 (GPTQ, GGUF)추론 속도/배포 목적, 더욱 경량화된 포맷 변환❌ 선택 사항 (추가만 가능)

T4 환경 기준 결론

항목상태필요 여부
load_in_4bit=True✔️ 설정됨필수
QLoRA 방식✔️ T4에 최적필수
추가 GPTQ 양자화❌ 안 해도 됨선택 (속도 최적화 원할 경우)
추론 속도 향상 목적의 GGUF❌ 안 해도 됨llama.cpp 환경에서만 필요

요약

  • 이미 4비트로 로드된 모델은 양자화된 것이므로, T4에서 파인튜닝 + 추론 모두 OK.
  • 추가 양자화는 추론 속도/배포를 더 줄이려는 특수 목적이 있는 경우만 고려하면 된다.

이번 주는 여기까지 앞으로의 프로젝트 화이팅...

0개의 댓글