PEFT란?
최근 대형 언어 모델 (LLM: Large Language Model)의 성능이 비약적으로 향상되면서, 다양한 분야에서 이를 활용해 특정 태스크에 맞춰 모델을 미세조정하는 시도가 이어지고 있다. 그러나 대형 언어 모델의 파라미터 수가 수십, 수천 억개에 달하면서, 전체 파라미터를 모두 업데이트하는 전통적인 미세조정(Fine-Tuning) 방식은 막대한 계산 비용과 메모리 사용 문제를 야기한다.
이에 따라, 학습해야 할 파라미터 수를 크게 줄이는 동시에 성능 저하를 최소화하는 파라미터 효율화 미세조정(PEFT, Parameter-Efficient Fine-Tuning) 기법이 각광받고 있다. PEFT 방법들은 모델의 일부 모듈만을 학습하거나 추가 파라미터를 최소한으로 도입해, 기존 모델의 대규모 파라미터는 고정(freeze) 상태로 두는 방식을 취한다.
PEFT 기본 아이디어
PEFT는 크게 다음과 같은 아이디어를 바탕으로 한다.
- 추가 계층(Adapters)나 테이블(Prompt Embeddings)만 학습: 기존 모델의 핵심 파라미터는 동결(Freeze)하고, 적은 양의 추가 모듈(예: Adapter, Prefix, LoRA 등)을 삽입하여 해당 모듈 파라미터만 학습한다.
- 미세조정 범위 최소화: 모델 전역을 학습하는 대신, 특정 부분(예: 주로 Transformer의 Feed-Forward Layer나 Attention에 들어가는 일부 매트릭스)만을 선별적으로 업데이트하여 계산량을 절감한다.
이러한 기법으로는 Adapter, Prefix Tuning, Prompt Tuning, 그리고 LoRA 등이 대표적이다.
LoRA (Low-Rank Adaptation)
LoRA(Hu et al., 2021)는 Transformer 구조에서 가장 큰 비중을 차지하는 가중치 행렬(W)에 대해 저차원 보강(Low-Rank Decomposition)을 적용함으로써, 적은 수의 학습 가능한 파라미터만 추가하여 효율적인 미세조정을 가능케 하는 방법이다.
- 기존 모델 전체를 학습하면 메모리와 연산량이 급증한다.
- LoRA는 저랭크(low-rank) 기반으로 업데이트를 수행하기 때문에, 추가되는 파라미터 수가 상대적으로 매우 적다.
LoRA에서는 Transformer의 Self-Attention에 포함된 가중치 행렬 W를 학습할 때, 이 행렬에 직접 기울기를 전파하지 않고, 다음과 같은 추가 항을 도입한다
\( \mathbf{W} = \mathbf{W}_0 + \Delta \mathbf{W} \)
여기서 $\Delta \mathbf{W}$를 저랭크 행렬의 곱으로 근사한다:
\( \Delta \mathbf{W} = \mathbf{B} \mathbf{A} \quad,\quad \mathbf{B} \in \mathbb{R}^{d \times r}, \quad \mathbf{A} \in \mathbb{R}^{r \times k} \)
- r은 랭크(rank)로, 일반적으로 r << min(d,k)로 설정한다.
- 학습 과정에서 B와 만 업데이트하고, W0의 가중치 행렬은 고정(Freeze) 상태로 둔다.
- 따라서 학습해야 할 파라미터 수가 d⋅r+r⋅k로 상당히 감소한다.
LoRA 방식의 학습 과정은 다음과 같다.
- 초기화: $\mathbf{B}$는 영행렬(0)로 초기화하고, $\mathbf{A}$는 random gaussian 분포로 세팅한다.
따라서 학습 시작 때 BA 값은 zero이다. - Forward Propagation: 입력 $\mathbf{x} $가 들어올 때, 모델 내에서 $\mathbf{W}_0 \mathbf{x} $에 $\mathbf{B}\mathbf{A}\mathbf{x} $를 더해 최종 출력을 얻는다.
- Backward Propagation: $\mathbf{W}_0$에 대한 기울기는 계산하지 않고(freeze 됐기 때문), $\mathbf{B}$와 $\mathbf{A}$만 업데이트한다.
이를 통해 훈련에 필요한 파라미터와 GPU 메모리 사용량을 크게 절감할 수 있다.
또한 Production 단계에서 모델을 배포할 때도 LoRA는 굉장히 유용하다.
$ \mathbf{W} = \mathbf{W}_0 + \mathbf{B} \mathbf{A} $ 이기 때문에 원래의 $ W_0 $으로 복구시키기 위해 단지 BA를 subtract하고, 또다른 LoRA weight인 $ \mathbf{B}' \mathbf{A}' $를 더해주면 다른 downstream task로 쉽고 빠르게, "very little memory overhead"로 전환할 수 있다.
GPT-3을 통째로 Fine-Tuning 하는 것 보다 LoRA 방식을 사용하면 trainable parameter 수도 엄청나게 감소하고 성능도 비등한 것을 확인할 수 있다.
최근 sLLM을 이용한 서비스 개발을 하는 경우 이렇게 LoRA처럼 PEFT 방식으로 학습하거나 Prompt Engineering을 통해 NLP 모듈을 개발하고 있다. 다음 포스팅에서 실제 코드 예제로 두 방식을 비교해보도록 하겠다.
'AI, 머신러닝' 카테고리의 다른 글
[Spark] 빅데이터 분산처리를 위한 PySpark 설치와 PostgreSQL 연결하고 세션 생성하기. (1) | 2025.02.02 |
---|---|
RAG 시스템 강화하기 - LangChain으로 Multi-Query, Reranker 적용한 증권 뉴스 RAG 구현 (1) | 2025.01.30 |
네이버 증권뉴스 크롤링으로 RAG 데이터셋 만들기 (python, BeautifulSoup4) (0) | 2025.01.30 |
RAG 시스템 강화하기 - Multi-Query, Self-Query, Reranker 알아보기 (0) | 2025.01.29 |
OpenAI API와 LangChain으로 만드는 고성능 RAG 시스템 구현하기 (0) | 2025.01.28 |