포스트

Learning Rates for LoRA Variants

LoRA variation method들의 learning rate에 따른 성능 차이

Learning Rates for LoRA Variants

LoRA variation method들을 직접 reproduce하면서 계속 의아했던 점이 있습니다.

LoRA를 기반으로 후속 method를 제안했다면 당연히 기존 LoRA보다 좋은 성능을 보여야 할 것 같았습니다. 실제로 각 논문도 대부분 vanilla LoRA 대비 성능 향상을 핵심 결과로 제시합니다. 그런데 막상 여러 method를 동일한 환경에서 비교해 보면 benchmark에 따라서는 오히려 가장 단순한 LoRA가 더 좋은 경우가 적지 않았습니다.

처음에는 LoRA variation들이 보고하는 향상이 대개 약 1%p 안팎이므로, seed나 data order에 따른 실험 오차일 수도 있다고 생각했습니다. 하지만 LoRA, DoRA, rsLoRA, PiSSA, AdaLoRA, ABBA 등을 동일한 hyperparameter setting에서 비교했을 때, LoRA가 다른 method들을 큰 차이로 앞서는 경우도 있었습니다.

처음에는 구현이 잘못되었다고 생각했습니다. 그래서 여러 조건에서 실험을 반복하고 hyperparameter search도 진행했습니다. 그 과정에서 알게 된 사실은 단순합니다. 동일한 hyperparameter를 사용하는 것이 항상 공정한 비교는 아니며, 특히 LoRA 계열 method마다 적합한 learning rate 범위가 다를 수 있다는 것입니다.

이 글에서는 제가 겪은 PiSSA reproduction 문제를 중심으로, LoRA variation을 비교할 때 무엇을 같게 두어야 하고 무엇을 고려해야 하는지 공유하고자 합니다.

1. LoRA에 대한 기본적인 지식

pretrained model의 한 linear layer가 다음 weight를 가진다고 하겠습니다.

\[W_0 \in \mathbb{R}^{d_{\text{out}} \times d_{\text{in}}}\]

Full fine-tuning은 $W_0$ 전체를 학습합니다. 반면 LoRA는 $W_0$를 freeze하고, 학습해야 할 변화량 $\Delta W$만 두 개의 작은 행렬로 표현합니다.

\[W' = W_0 + \Delta W\] \[\Delta W = \gamma_r BA\] \[A \in \mathbb{R}^{r \times d_{\text{in}}}, \qquad B \in \mathbb{R}^{d_{\text{out}} \times r}\]

$r$은 LoRA의 rank입니다. 일반적으로 $r \ll \min(d_{\text{in}}, d_{\text{out}})$이므로, 학습되는 parameter 수는 $r(d_{\text{in}} + d_{\text{out}})$입니다.

Full fine-tuning에서 필요한 $d_{\text{in}}d_{\text{out}}$ 개와 비교하면 매우 작은 값입니다.

vanilla LoRA에서 scaling factor는 보통 다음과 같습니다.

\[\gamma_r = \frac{\alpha}{r}\]

따라서 LoRA의 학습 거동은 rank와 learning rate만으로 결정되지 않습니다. lora_alpha, initialization, target module, optimizer, scheduler도 실제 update의 크기와 방향에 영향을 줍니다.

2. 하이퍼파라미터 중에서 rank만큼은 함부로 다르게 세팅하면 안 되는 이유

LoRA variation을 비교할 때 각 method에 가장 잘 맞는 learning rate를 따로 찾는 것은 필요합니다. 반면 primary comparison에서 method마다 rank까지 임의로 다르게 선택하면 method 자체의 효과를 분리하기 어려워집니다.

2.1 Rank는 단순한 학습 설정이 아니라 model capacity다

LoRA update는 다음 조건을 만족합니다.

\[\operatorname{rank}(\Delta W) \le r\]

rank를 높이면 표현할 수 있는 update subspace가 넓어집니다. 동시에 trainable parameter 수와 training memory, 연산량도 증가합니다. 예를 들어 method A를 $r=8$, method B를 $r=64$로 비교해 B가 더 좋은 결과를 얻었다면, 그것이 algorithm의 장점인지 8배 더 큰 rank budget의 효과인지 분리하기 어렵습니다.

따라서 첫 번째 head-to-head comparison에서는 다음 항목을 통제해야 합니다.

동일한 base model과 checkpoint

동일한 dataset split과 preprocessing

동일한 target modules

동일한 training sample 수와 optimizer step 수

동일하거나 대응되는 rank budget

가능한 한 유사한 trainable-parameter 수

그 후 별도의 실험에서 각 method가 rank 증가에 따라 어떻게 scaling되는지를 비교하는 것이 좋습니다.

2.2 하지만 같은 숫자의 rank가 항상 공정한 것은 아니다

여기에는 중요한 예외가 있습니다. 서로 다른 구조를 사용하는 method에서는 r=32라는 표기만 같게 두어도 실제 parameter budget이 다를 수 있습니다.

LoRA, PiSSA, rsLoRA는 같은 adapter 구조를 사용하므로 target modules까지 같다면 동일 rank 비교가 비교적 명확합니다. DoRA는 magnitude parameter가 추가되므로 정확한 trainable-parameter 수도 함께 보고해야 합니다. AdaLoRA는 학습 도중 rank를 재분배하므로 initial rank보다 최종 target budget과 rank-allocation schedule을 맞추는 것이 중요합니다.

ABBA는 더 분명한 예외입니다. ABBA의 update는 다음과 같이 두 low-rank product의 element-wise product로 구성됩니다.

\[\Delta W = s(B_1A_1) \odot (B_2A_2)\]

이때 trainable parameter 수는

\[(r_1+r_2)(d_{\text{in}}+d_{\text{out}})\]

입니다. ABBA 논문은 LoRA의 rank $r$과 parameter 수를 맞추기 위해 $r_1=r_2=r/2$로 설정합니다. 따라서 LoRA의 $r=32$와 ABBA의 두 내부 rank를 각각 32로 놓는다면, nominal rank 표기는 같아 보여도 ABBA가 약 2배의 adapter parameter를 사용하게 됩니다.

결국 공정성의 핵심은 모든 configuration file에 같은 r을 복사하는 것이 아닙니다.

구조가 같은 method에는 동일 rank를 사용하고, 구조가 다른 method에는 동일한 최종 parameter budget을 대응시켜야 합니다.

3. 제가 겪은 문제: PiSSA가 GSM8K와 MATH에서 LoRA를 이기지 못했다

PiSSA는 vanilla LoRA와 동일한 low-rank architecture를 사용하지만 initialization을 바꿉니다. pretrained weight를 SVD하면 $W_0 = U\Sigma V^\top$로 표현할 수 있습니다.

PiSSA는 큰 singular value에 대응하는 top-$r$ singular components로 adapter를 initialize하고 나머지를 frozen residual weight에 둡니다.

단순화하면 아래 식과 같이 나타낼 수 있습니다.

\[W_0 = W_{\text{res}} + B_0A_0\]

따라서 학습 시작 시점의 전체 weight는 원래 $W_0$와 같지만 LoRA와 달리 principal subspace를 처음부터 학습하게 됩니다. PiSSA는 이러한 initialization이 더 빠른 convergence와 높은 최종 성능으로 이어진다고 주장합니다.

저도 처음에는 PiSSA가 적어도 LoRA보다 낮은 성능을 보이지는 않을 것이라고 예상했습니다. 다른 benchmark에서는 결과가 괜찮았지만, GSM8K와 MATH에서는 여러 번 반복해도 PiSSA가 LoRA를 넘지 못했습니다. 경우에 따라서는 작은 오차라고 보기 어려울 정도로 차이가 벌어졌습니다.

그래서 자연스럽게 제 구현이 틀렸을 가능성부터 확인했습니다.

SVD initialization이 올바르게 적용되었는지, $W_{\text{res}}$를 정확히 구성했는지, adapter merge 또는 save/load 과정에서 weight가 달라지지 않았는지, prompt template과 answer extraction이 원 논문과 같은지, GSM8K와 MATH의 evaluation setting이 동일한지, random seed와 data order가 어느 정도 영향을 미치는지 등을 확인했습니다.

이 항목들을 확인하는 것은 필요합니다. 하지만 구현에 문제가 없더라도 PiSSA가 계속 밀릴 수 있는 또 다른 이유가 있었습니다. LoRA에 맞는 learning rate를 PiSSA에도 그대로 사용하고 있었기 때문입니다.

동일한 learning rate로 실험하는 것이 공정하다고 생각했지만, 실제로는 그렇지 않았습니다. 그래서 논문마다 최적화된 learning rate를 찾아보기 시작했고, ICLR 2026 workshop 논문 중에 이와 관련된 조사를 한 논문을 찾았습니다.

Learning Rate Matters: Vanilla LoRA May Suffice for LLM Fine-tuning

text

해당 논문의 Figure 1을 보면, 논문마다 최적의 learning rate가 다르고 그때마다 최적의 accuracy가 다르게 나온다는 것을 알 수 있습니다. 제가 눈여겨본 점은 LoRA가 특정 learning rate에서 다른 method들을 이겼을 뿐만 아니라, 다른 method들이 각자의 최적 learning rate에서 기록한 accuracy보다도 더 높은 성능을 보였다는 것입니다.

결론: learning rate 선정은 매우 중요합니다. 이 설정 하나로 성능이 좌우될 수 있다면, 가장 단순하면서도 효율적인 LoRA가 실무에서 널리 사용되는 이유를 이해할 수 있습니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.