본문 바로가기
AI Deep Learning

딥러닝의 새로운 지평: 초심자를 위한 Low-Rank Adaptation (LoRA) 완벽 가이드 4편

by AI디코더 2025. 6. 16.

제4장: 실전! PyTorch와 Hugging Face로 LoRA 구현하기

 

이론적 원리를 이해했다면, 이제 직접 코드를 통해 LoRA를 구현해 볼 차례입니다. 다행히도 Hugging Face의 PEFT 라이브러리 덕분에 복잡한 수학적 구현 없이도 몇 줄의 코드만으로 LoRA를 손쉽게 적용할 수 있습니다. 이 장에서는 PyTorch와 PEFT를 사용하여 모델을 미세조정하는 전체 과정을 단계별로 안내합니다.

 

4.1. 핵심 도구: Hugging Face PEFT 라이브러리

 

Hugging Face의 PEFT(Parameter-Efficient Fine-Tuning) 라이브러리는 LoRA를 비롯한 다양한 PEFT 기법을 transformers 모델에 손쉽게 적용할 수 있도록 설계된 표준 도구입니다.23 이 라이브러리를 사용하면 개발자는 LoRA의 내부 구현에 신경 쓸 필요 없이, 하이퍼파라미터 설정과 훈련 로직에만 집중할 수 있습니다.

 

4.2. LoraConfig: LoRA 훈련의 청사진

 

LoRA 훈련을 시작하기 전에, 어떤 방식으로 LoRA를 적용할지 정의하는 설정 객체를 만들어야 합니다. 이것이 바로 LoraConfig입니다.26

LoraConfig는 LoRA 훈련의 모든 세부 사항을 담고 있는 청사진과 같습니다. 주요 하이퍼파라미터와 그 역할은 다음과 같습니다.

파라미터 (Parameter) 설명 (Description) 일반적인 값 (Typical Range) 선택 가이드 및 고려사항 (Selection Guide & Considerations)
r LoRA 어댑터의 순위(rank). 낮을수록 파라미터 수가 적어지지만 표현력이 제한될 수 있음.28 4, 8, 16, 32, 64, 128 8 또는 16으로 시작하는 것이 일반적. 복잡한 작업이나 큰 데이터셋일수록 높은 값을 고려할 수 있으나, 너무 높으면 과적합(overfitting) 위험이 있음.29
lora_alpha LoRA 가중치의 스케일링 팩터. 학습된 가중치의 영향력을 조절함.28 16, 32, 64 r의 1배 또는 2배로 설정하는 것이 일반적인 관행.29 lora_alpha / r이 최종 스케일링 값이 됨. alpha를 고정하고 학습률(learning rate)을 먼저 튜닝하는 것이 더 효과적일 수 있음.31
target_modules LoRA를 적용할 모델 내 모듈(레이어)의 이름. 보통 트랜스포머의 어텐션 관련 레이어(q_proj, v_proj 등)를 지정함.26 ["q_proj", "v_proj"] 등 일반적으로 모든 선형 레이어(all-linear)에 적용하면 성능이 향상되지만, 메모리 사용량이 증가함. 어텐션 관련 레이어에만 적용하는 것이 효율과 성능의 좋은 절충안임.29
lora_dropout LoRA 레이어에 적용할 드롭아웃 확률. 과적합을 방지하는 데 도움을 줌.28 0.05, 0.1 데이터가 적거나 과적합이 우려될 때 0.1과 같은 값을 사용. Unsloth와 같은 최적화 라이브러리는 0으로 설정 시 더 빠른 학습을 지원하기도 함.29
bias 편향(bias) 파라미터를 학습할지 여부. none, all, lora_only 중 선택.26 "none" "none"으로 설정하면 편향을 학습하지 않아 파라미터 효율성이 가장 높고 과적합 방지에 유리함. "lora_only"는 LoRA 레이어의 편향만 학습.29
task_type 모델이 수행할 작업의 유형. (예: TaskType.CAUSAL_LM for Causal LM).27 TaskType.SEQ_2_SEQ_LM, TaskType.CAUSAL_LM 모델 아키텍처와 수행하려는 작업에 맞게 정확히 지정해야 함.

 

4.3. 코드 실습: 단계별 모델 미세조정

 

이제 실제 코드를 통해 google/flan-t5-small 모델을 미세조정하는 과정을 살펴보겠습니다.

(1) 환경 설정 및 라이브러리 임포트

먼저 필요한 라이브러리를 설치하고 임포트합니다.

 

Python



# 필요한 라이브러리 설치
#!pip install transformers datasets peft torch accelerate bitsandbytes

import torch
from datasets import load_dataset
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, TrainingArguments, Trainer
from peft import LoraConfig, get_peft_model, TaskType

# 모델 ID와 데이터셋 ID 정의
model_id = "google/flan-t5-small"
dataset_id = "samsum"

(2) 기본 모델 및 토크나이저 로드

Hugging Face Hub에서 사전 훈련된 모델과 해당 토크나이저를 로드합니다.

 

Python



# 토크나이저와 모델 로드
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSeq2SeqLM.from_pretrained(model_id)

(3) LoraConfig 생성

위의 가이드 표를 참고하여 LoraConfig 객체를 생성합니다. 여기서는 r=16, lora_alpha=32로 설정해 보겠습니다.

 

Python



# LoRA 설정 정의
lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q", "v"],  # T5 모델의 어텐션 레이어 이름
    lora_dropout=0.1,
    bias="none",
    task_type=TaskType.SEQ_2_SEQ_LM
)

(4) get_peft_model로 PEFT 모델 생성

get_peft_model 함수를 사용하여 기본 모델에 LoRA 설정을 적용합니다. 이 함수는 모델을 'in-place'로, 즉 원본 모델 객체 자체를 수정하여 PEFT 모델로 변환합니다.27

 

Python



# 기본 모델에 LoRA 적용
peft_model = get_peft_model(model, lora_config)

(5) 학습 가능한 파라미터 확인

print_trainable_parameters() 헬퍼 함수를 호출하여 LoRA가 얼마나 효율적인지 직접 눈으로 확인합니다. 전체 파라미터 중 극히 일부만 학습 대상이 된 것을 볼 수 있습니다.

 

Python



# 학습 가능한 파라미터 수 출력
peft_model.print_trainable_parameters()
# 출력 예시: trainable params: 491520 |
| all params: 77433600 |
| trainable%: 0.6348133340929519

(6) 데이터 준비 및 Trainer 실행

데이터셋을 로드하고 토큰화한 후, Hugging Face Trainer를 사용하여 훈련을 시작합니다. Trainer는 훈련 루프의 복잡한 부분을 자동화해 줍니다.

 

Python



# 데이터셋 로드 및 전처리 (간략화된 예시)
dataset = load_dataset(dataset_id)
#... (데이터 토큰화 과정 생략)...

# 훈련 인자 설정
training_args = TrainingArguments(
    output_dir="./flan-t5-small-lora-samsum",
    learning_rate=1e-3,
    per_device_train_batch_size=8,
    num_train_epochs=3,
    weight_decay=0.01,
    evaluation_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True,
)

# Trainer 생성 및 훈련 시작
trainer = Trainer(
    model=peft_model,
    args=training_args,
    train_dataset=tokenized_dataset["train"],
    eval_dataset=tokenized_dataset["test"],
    #... (data_collator 등 추가 설정)
)

trainer.train()

 

4.4. 어댑터 저장, 로드, 그리고 병합

 

훈련이 완료된 후에는 학습된 LoRA 어댑터를 관리하고 활용해야 합니다.

  • 어댑터 저장: 훈련된 경량 어댑터는 save_pretrained 메서드로 간단히 저장할 수 있습니다. 저장되는 파일은 adapter_model.bin과 adapter_config.json 뿐이며, 용량이 매우 작습니다.27
    Python
    peft_model.save_pretrained("./my-flan-t5-lora-adapter")

  • 추론을 위한 어댑터 로드: 나중에 추론을 위해 어댑터를 사용하려면, 먼저 원본 기본 모델을 로드한 다음, PeftModel.from_pretrained를 사용하여 저장된 어댑터 가중치를 그 위에 적용합니다.27
    get_peft_model은 훈련을 위해 모델을 준비하는 함수이고, PeftModel.from_pretrained는 이미 훈련된 어댑터를 로드하는 함수라는 목적의 차이를 이해하는 것이 중요합니다.33
    Python
    from peft import PeftModel

    # 기본 모델 다시 로드
    base_model = AutoModelForSeq2SeqLM.from_pretrained(model_id)
    # 저장된 어댑터 로드
    inference_model = PeftModel.from_pretrained(base_model, "./my-flan-t5-lora-adapter")

  • 배포를 위한 병합: 실제 서비스에 배포할 때는 merge_and_unload() 메서드를 사용하는 것이 매우 유용합니다. 이 메서드는 LoRA 어댑터 가중치를 기본 모델의 가중치에 완전히 통합하여, PEFT 라이브러리 의존성 없이 순수한 transformers 모델처럼 사용할 수 있는 단일 모델을 만듭니다. 이렇게 병합된 모델은 추론 시 추가 지연 시간이 전혀 없습니다.34
    Python
    merged_model = peft_model.merge_and_unload()
    # 이제 merged_model은 LoRA 가중치가 합쳐진 일반 transformers 모델입니다.
    # 별도의 파일로 저장하여 배포할 수 있습니다.
    merged_model.save_pretrained("./my-flan-t5-merged-model")

이처럼 PEFT 라이브러리는 LoRA의 복잡한 과정을 추상화하여, 개발자가 단 몇 줄의 코드로 강력한 미세조정 기술을 활용할 수 있도록 지원합니다.



반응형

댓글