Adapter
모델 레이어 사이에 삽입되는 작은 학습 모듈
모델 레이어 사이에 삽입되는 작은 학습 모듈
Adapter는 사전 학습된 대규모 모델을 효율적으로 특정 태스크에 적응시키기 위해 Transformer 레이어 사이에 삽입되는 작은 학습 모듈입니다. 원본 모델의 파라미터는 고정(freeze)하고 Adapter만 학습하므로, 전체 fine-tuning 대비 0.5~4%의 파라미터만 업데이트하면서도 유사한 성능을 달성합니다.
2019년 Google Research의 논문 "Parameter-Efficient Transfer Learning for NLP"에서 처음 제안되었습니다. 이후 PEFT(Parameter-Efficient Fine-Tuning)의 핵심 기법으로 발전하였으며, LoRA, Prefix Tuning 등 다양한 변형 기법의 기반이 되었습니다.
Adapter의 구조는 다운프로젝션(down-projection), 비선형 활성화, 업프로젝션(up-projection)으로 구성된 보틀넥(bottleneck) 형태입니다. 예를 들어 768차원 입력을 64차원으로 줄였다가 다시 768차원으로 복원합니다. 이 보틀넥 차원이 Adapter의 용량을 결정하며, 일반적으로 원래 차원의 1~10%를 사용합니다.
다국어/다도메인 서비스에서 하나의 기본 모델에 여러 Adapter를 태스크별로 교체하며 사용할 수 있습니다. 의료, 법률, 금융 등 도메인별 Adapter를 준비해두면 추론 시 필요한 Adapter만 로드하여 빠르게 전환할 수 있어, 다양한 전문 분야를 커버하는 서비스 구축에 효과적입니다.
from transformers import AutoModelForSequenceClassification
from peft import get_peft_model, LoraConfig, TaskType
# 기본 모델 로드
model_name = "bert-base-uncased"
model = AutoModelForSequenceClassification.from_pretrained(
model_name, num_labels=2
)
# LoRA (Low-Rank Adaptation) 설정 - Adapter의 인기 변형
lora_config = LoraConfig(
task_type=TaskType.SEQ_CLS,
r=8, # 보틀넥 차원 (rank)
lora_alpha=32, # 스케일링 팩터
lora_dropout=0.1, # 드롭아웃
target_modules=["query", "value"] # 적용할 레이어
)
# Adapter가 적용된 PEFT 모델 생성
peft_model = get_peft_model(model, lora_config)
# 학습 가능한 파라미터 확인
trainable_params = sum(p.numel() for p in peft_model.parameters() if p.requires_grad)
total_params = sum(p.numel() for p in peft_model.parameters())
print(f"학습 파라미터: {trainable_params:,} / {total_params:,}")
print(f"학습 비율: {100 * trainable_params / total_params:.2f}%")
# 학습 후 Adapter만 저장
peft_model.save_pretrained("./my_adapter")
# 다른 태스크용 Adapter 로드하여 교체
from peft import PeftModel
base_model = AutoModelForSequenceClassification.from_pretrained(model_name)
medical_model = PeftModel.from_pretrained(base_model, "./medical_adapter")
legal_model = PeftModel.from_pretrained(base_model, "./legal_adapter")
"각 고객사별로 full fine-tuning하면 모델 저장 비용이 너무 커요. Adapter 방식으로 가면 기본 모델 하나에 고객별 Adapter만 따로 저장할 수 있어서, 저장 공간을 90% 이상 줄일 수 있습니다."
"Adapter와 LoRA의 차이점을 설명해주세요. Adapter는 레이어 사이에 새로운 모듈을 추가하는 방식이고, LoRA는 기존 가중치에 저차원 행렬을 더하는 방식입니다. LoRA가 추론 시 오버헤드 없이 병합 가능해서 더 많이 쓰입니다."
"7B 모델 전체 fine-tuning에 A100 80GB 4장이 필요한데, LoRA 쓰면 24GB GPU 1장으로도 가능해요. 학습 시간도 3분의 1로 줄어들고요."
rank가 너무 작으면 표현력이 부족하고, 너무 크면 효율성이 떨어집니다. 일반적으로 r=4~16으로 시작하여 태스크 복잡도에 따라 조정하세요. 복잡한 태스크에서는 r=64까지 필요할 수 있습니다.
모든 레이어에 Adapter를 적용하면 파라미터가 늘어납니다. Attention의 Query/Value에만 적용해도 대부분 충분하며, 태스크에 따라 FFN 레이어 추가를 고려하세요.
Adapter는 특정 기본 모델에 종속됩니다. 기본 모델이 업데이트되면 기존 Adapter가 동작하지 않을 수 있으니, 기본 모델 버전을 함께 기록하세요.