배경과 문제의식
대규모 언어모델의 일반적인 활용 방식은 대규모 데이터로 사전학습한 모델을 특정 downstream task에 맞게 fine-tuning하는 것이다. 그러나 모델 규모가 커질수록 모든 파라미터를 업데이트하는 full fine-tuning은 점점 비현실적인 방법이 된다. 예를 들어 GPT-3 175B와 같은 모델을 task마다 별도로 fine-tuning하면, 각 task마다 1,750억 개 규모의 파라미터를 가진 모델 복사본을 저장하고 배포해야 한다. 이는 저장 비용, GPU 메모리, 배포 비용, task switching 측면에서 매우 비효율적이다.
기존에도 parameter-efficient tuning을 위한 adapter, prefix tuning, prompt tuning 등의 방법이 제안되었다. 하지만 adapter는 Transformer block 사이에 추가 layer를 삽입하기 때문에 추론 시 계산 경로가 길어지고 inference latency가 증가할 수 있다. Prefix tuning 계열은 입력 앞에 학습 가능한 token을 추가하기 때문에 모델이 실제 task 입력에 사용할 수 있는 sequence length를 줄이는 문제가 있다. 또한 이러한 방법들은 효율성은 높지만 full fine-tuning 수준의 성능을 항상 안정적으로 따라가지 못하는 trade-off가 존재한다.
LoRA는 이 문제를 해결하기 위해 “downstream task에 적응할 때 필요한 weight 변화량은 전체 고차원 공간이 아니라 낮은 intrinsic rank를 가질 수 있다”는 가정에서 출발한다. 즉, 사전학습된 모델 전체를 다시 학습하는 것이 아니라, task adaptation에 필요한 작은 변화 방향만 학습해도 충분할 수 있다고 본다.
핵심 아이디어
“규모가 큰 전체 파라미터 공간에서 실제 Task 성능을 좋게 만드는 변화 방향은 이후 작은 저차원 공간 안에 있을 수 있다.”
LoRA의 핵심 아이디어 위의 가정에서 시작되어 pre-trained weight를 고정하고, weight의 변화량만 low-rank decomposition으로 학습하는 것이다.
변화 행렬 델타 W이 사실 몇 개의 중요한 방향으로만 이루어져 있다고 보고 B A로 분해하여, 학습할 파라미터를 대폭 줄이는 아이디어이다. 해당 방법은 아래 예시를 참고해보자.

아키텍처 구조

LoRA는 특정 neural network layer, 특히 Transformer의 dense projection matrix에 적용된다. Transformer self-attention에는 일반적으로 Query, Key, Value, Output projection matrix가 존재한다.
논문에서는 주로 attention module의 (W_q)와 (W_v)에 LoRA를 적용한다. 즉 기존 Transformer 구조 전체를 바꾸는 것이 아니라, attention projection weight 옆에 low-rank update branch를 병렬로 추가하는 방식이다.
구조적으로 보면 입력 (x)는 두 경로로 흐른다. 하나는 기존 pre-trained weight (W_0)를 통과하는 경로이고, 다른 하나는 LoRA의 (A), (B)를 통과하는 경로이다. (A)는 입력을 작은 rank 차원 (r)로 압축하고, (B)는 이를 다시 원래 출력 차원으로 확장한다. 두 결과를 더해 최종 출력 (h)를 만든다.
학습 초기에는 (A)를 Gaussian distribution으로 초기화하고, (B)는 0으로 초기화한다. 따라서 학습 시작 시점에는 (BA = 0)이므로 기존 pre-trained model의 출력이 변하지 않는다. 이후 학습이 진행되면서 (A), (B)만 업데이트되어 task-specific한 변화량을 학습한다.
이 방식은 기존 Transformer 구조를 크게 변경하지 않으며, 학습해야 하는 파라미터 수와 optimizer state 저장 비용을 크게 줄인다. 또한 inference 시에는 (W_0 + BA)로 merge할 수 있어 별도의 추가 layer 없이 동작한다.
직관적 이해
LoRA는 “거대한 모델 전체를 새로 고치는 것”이 아니라 “기존 모델이 이미 알고 있는 지식 중 특정 task에 필요한 방향만 살짝 조정하는 것”으로 이해할 수 있다.
Full fine-tuning은 모델의 모든 weight를 자유롭게 업데이트한다. 이는 마치 책 전체를 다시 쓰는 것과 같다. 반면 LoRA는 책 전체를 다시 쓰지 않고, 특정 task에 필요한 몇 개의 중요한 부분에 얇은 메모지를 붙여 보정하는 방식에 가깝다. 기존 pre-trained model은 이미 방대한 언어 지식과 feature를 가지고 있으므로, downstream task에서는 그 지식을 완전히 새로 학습하기보다 특정 feature를 더 강조하거나 약간 방향을 조정하는 것만으로도 충분할 수 있다.
수학적으로 보면 full fine-tuning은 델타 W라는 큰 변화 행렬 전체를 학습한다. 하지만 LoRA는 이 변화 행렬이 사실 몇 개의 중요한 방향으로만 이루어져 있다고 보고, 이를 (BA)라는 low-rank 형태로 제한한다. 여기서 rank (r)은 모델이 weight를 수정할 수 있는 중요한 변화 방향의 수라고 이해할 수 있다.
논문 후반의 분석에서도 LoRA의 델타 W는 완전히 새로운 feature를 만드는 것이 아니라, pre-trained weight (W)에 이미 존재하지만 충분히 강조되지 않았던 task-specific feature 방향을 증폭하는 역할을 한다고 해석한다. 즉 LoRA는 “모델을 새로 배우게 하는 것”보다는 “기존 모델 안에 있는 유용한 능력을 task에 맞게 켜주는 것”에 가깝다.
한계
LoRA에도 한계는 존재한다. 첫째, 서로 다른 task의 LoRA module을 하나의 batch에서 동시에 처리하기 어렵다. LoRA는 task별로 다른 (A), (B)를 학습한다. inference latency를 없애기 위해 (W = W_0 + BA)로 merge하면 task마다 서로 다른 weight가 만들어진다.
따라서 하나의 batch 안에 서로 다른 task의 입력이 섞여 있을 경우, 각 sample마다 다른 merged weight를 사용해야 하므로 단일 forward pass로 처리하기 어렵다. 이를 해결하려면 merge하지 않고 sample별로 다른 LoRA module을 동적으로 선택해야 하지만, 이 경우 추가 계산이 발생해 LoRA의 “no additional inference latency” 장점이 약해질 수 있다.
둘째, LoRA의 성능은 어떤 weight matrix에 적용하느냐에 영향을 받는다. 논문에서는 주로 attention의 (W_q), (W_v)에 적용했을 때 좋은 결과를 보였지만, 모든 task와 모델에서 이 선택이 항상 최적인 것은 아니다. 어떤 layer와 어떤 projection에 LoRA를 적용할지에 대한 원리적인 기준은 아직 완전히 확립되지 않았다.
셋째, rank (r)의 선택이 중요하다. 작은 (r)은 파라미터 효율성이 높지만 표현력이 제한될 수 있고, 큰 (r)은 표현력은 높아지지만 LoRA의 효율성이 줄어든다. 논문에서는 매우 작은 rank로도 좋은 성능을 보였지만, downstream task가 사전학습 분포와 크게 다르거나 더 복잡한 변화를 요구하는 경우에는 작은 rank만으로 충분하지 않을 수 있다.
넷째, LoRA는 pre-trained model이 이미 충분히 좋은 feature를 가지고 있다는 전제에 강하게 의존한다. 만약 downstream task가 pre-training에서 거의 학습되지 않은 도메인이나 언어, 특수한 지식을 요구한다면, 기존 feature를 조금 보정하는 것만으로는 한계가 있을 수 있다.
마지막으로, LoRA는 fine-tuning의 작동 원리를 완전히 설명한 방법은 아니다. 논문 역시 pre-training에서 학습된 feature가 downstream task에서 어떻게 변환되고 활용되는지, 그리고 어떤 weight update가 왜 low-rank로 충분한지에 대해서는 추가 연구가 필요하다고 언급한다.