LoRA란? 대규모 언어 모델을 적은 파라미터로 미세 조정하는 원리

LoRA란? 대규모 언어 모델을 적은 파라미터로 미세 조정하는 원리#

LoRA(Low-Rank Adaptation)는 이미 학습된 모델의 가중치는 고정하고, 그 옆에 추가한 작은 행렬만 학습하는 미세 조정 기법입니다.

대규모 언어 모델을 특정 업무에 맞추고 싶다고 가정해 보겠습니다. 모든 가중치를 다시 학습하는 전체 미세 조정은 학습 대상 파라미터뿐 아니라 기울기와 옵티마이저 상태를 관리해야 합니다. 모델이 커질수록 필요한 메모리와 저장 공간도 부담이 됩니다.

LoRA는 질문을 바꿉니다.

“기존 가중치 전체를 수정하는 대신, 필요한 변화만 작은 크기로 표현할 수 있을까?”

이 변화량을 두 개의 작은 행렬로 표현하면 학습할 파라미터를 크게 줄일 수 있습니다. 원본 모델은 유지하면서 작업별로 서로 다른 LoRA 어댑터를 보관할 수도 있습니다.

이 글은 비전공자도 이해할 수 있도록 먼저 직관을 설명한 뒤, 행렬식과 실제 설정으로 이어집니다.

먼저 알아둘 용어#

용어 의미
사전 학습 모델 대량의 데이터로 이미 학습된 기본 모델
미세 조정 기존 모델을 특정 데이터나 작업에 맞게 추가 학습하는 과정
가중치 모델이 계산에 사용하는 학습된 숫자들
파라미터 학습으로 값이 조정되는 가중치 등의 요소
어댑터 기본 모델에 추가해 학습한 작은 구성 요소
랭크 행렬이 표현할 수 있는 독립적인 방향의 수를 나타내는 값
PEFT 일부 파라미터만 학습하는 효율적인 미세 조정 방법의 묶음

전체 미세 조정과 LoRA는 무엇이 다를까?#

모델의 한 계층에 가중치 행렬 W가 있다고 하겠습니다. 입력 x가 들어오면 이 계층은 가중치를 이용해 출력을 계산합니다.

원래 계층의 출력 = W가 입력 x에 적용된 결과

전체 미세 조정에서는 학습을 통해 원래 행렬 W 자체가 바뀝니다.

학습 후 가중치 = W + ΔW

여기서 ΔW는 새 작업에 맞추기 위해 필요한 가중치 변화량입니다.

LoRA에서는 W를 고정하고, 변화량을 표현하는 작은 행렬 두 개를 별도로 학습합니다.

원래 가중치 W: 고정
추가 행렬 A, B: 학습
구분 전체 미세 조정 LoRA
기본 모델의 가중치 학습 중 변경 학습 중 고정
주된 학습 대상 선택한 원본 가중치 전체 추가한 작은 행렬
작업별 결과물 변경된 모델 가중치 기본 모델에 결합할 어댑터
학습 자원 모델 크기에 따라 부담이 큼 학습 파라미터와 관련 상태를 줄일 수 있음
고려할 점 저장·학습 비용 어댑터 설정과 적용 범위에 따라 품질이 달라짐

LoRA가 기본 모델을 메모리에서 없애 준다는 뜻은 아닙니다. 기본 모델은 여전히 필요합니다. 줄어드는 것은 주로 학습할 가중치의 수와 그에 수반되는 메모리 부담입니다.

‘저랭크’는 무슨 뜻일까?#

사진을 편집한다고 상상해 보세요. 원본 사진의 모든 픽셀을 마음대로 고치는 대신, 밝기나 색조처럼 몇 개의 조정 방향만 사용해 원하는 변화를 표현하는 상황과 비슷합니다.

LoRA의 핵심 아이디어는 모델에 필요한 변화가 가중치 행렬의 모든 방향을 자유롭게 사용하지 않아도 더 적은 수의 방향으로 효과적으로 표현될 수 있다는 것입니다.

행렬에서 이와 관련된 개념이 랭크입니다. 랭크는 행렬이 표현하는 독립적인 방향의 수라고 생각할 수 있습니다.

다만 여기에는 중요한 구분이 있습니다.

  • 원래 가중치 행렬 W의 랭크가 반드시 낮다는 뜻이 아닙니다.
  • LoRA가 표현하려는 것은 추가 학습에 필요한 변화량입니다.
  • 모든 모델과 작업에서 같은 낮은 랭크가 충분하다고 보장하는 뜻도 아닙니다.

LoRA 논문은 언어 모델을 새로운 작업에 맞추는 과정에서 낮은 차원의 변화로도 좋은 결과를 얻을 수 있다는 실험적 근거를 제시했습니다. 이 관찰을 바탕으로 변화량을 작은 행렬의 곱으로 제한합니다.

LoRA의 행렬식: 큰 변화량을 작은 행렬 두 개로 표현하기#

입력 차원을 d_in, 출력 차원을 d_out이라고 하겠습니다. 기존 가중치 행렬 W의 크기는 다음과 같습니다.

W의 크기: d_out × d_in

전체 미세 조정에서는 같은 크기의 변화량 ΔW를 직접 학습할 수 있습니다.

LoRA는 변화량을 다음처럼 표현합니다.

ΔW = B × A

A의 크기: r × d_in
B의 크기: d_out × r
r: LoRA의 랭크

A와 B를 곱한 결과는 d_out × d_in 크기입니다. 따라서 원래 가중치 W에 더할 수 있습니다.

원래 출력: W × x

LoRA 적용 출력:
W × x + (α / r) × B × (A × x)

여기서 α는 LoRA가 학습한 변화의 크기를 조절하는 설정값입니다. α / r은 기본적인 LoRA 설정에서 사용하는 스케일입니다.

입력은 두 경로를 지나간다#

동작을 순서대로 풀어보면 다음과 같습니다.

  1. 입력 x가 원래 계층에 들어갑니다.
  2. 고정된 원본 가중치 W가 기본 출력을 계산합니다.
  3. 같은 입력이 작은 행렬 A를 거쳐 r차원으로 변환됩니다.
  4. 그 결과가 행렬 B를 거쳐 원래 출력 크기로 돌아옵니다.
  5. LoRA 결과에 α / r을 적용하고 기본 출력에 더합니다.

즉, 기존 모델의 출력에 새 작업에 맞춰 학습한 작은 보정값을 더하는 방식입니다.

원본 가중치 W를 학습하지 않는다는 말은, 학습 과정에서 원본 가중치의 기울기와 옵티마이저 상태를 갱신하지 않는다는 뜻입니다. 학습에 필요한 다른 중간 계산과 메모리가 모두 사라진다는 의미는 아닙니다.

파라미터는 얼마나 줄어들까?#

정사각형 행렬 하나를 단순화해 4096 × 4096이라고 가정하겠습니다.

원래 행렬의 원소 수:
4096 × 4096 = 16,777,216개

LoRA의 랭크를 r = 16으로 설정하면 추가 행렬의 원소 수는 다음과 같습니다.

A: 16 × 4096 = 65,536개
B: 4096 × 16 = 65,536개

A + B = 131,072개

이 행렬 하나의 계산 예시에서 학습하는 LoRA 행렬 원소 수는 원래 행렬 원소 수의 약 **0.78%**입니다.

그렇다고 전체 모델의 학습 파라미터가 반드시 99.2% 감소한다고 말할 수는 없습니다. 실제 비율은 어느 계층에 LoRA를 적용하는지, 각 계층의 입출력 크기가 얼마인지, 다른 모듈도 함께 학습하는지에 따라 달라집니다.

또 4096과 r=16은 계산을 보여주기 위해 선택한 값입니다. 특정 모델에서 이 설정이 최상의 품질을 낸다는 보장은 아닙니다.

학습 시작 전에는 왜 원본 모델과 같은 출력을 낼까?#

일반적인 LoRA 초기화에서는 행렬 A에 초기값을 넣고 B를 0으로 설정합니다.

B = 0
→ B × A = 0
→ LoRA가 더하는 변화량 = 0

따라서 학습을 시작하기 전에는 LoRA 경로가 기본 모델의 출력을 바꾸지 않습니다. 학습을 진행하면서 A와 B가 필요한 변화량을 표현하게 됩니다.

Hugging Face PEFT의 기본 LoRA 초기화에서는 A에 Kaiming 균등 초기화, B에 0 초기화를 사용합니다. PEFT에는 다른 초기화 옵션도 있으므로, 이 설명은 기본 설정을 기준으로 이해해야 합니다.

r, lora_alpha, lora_dropout은 어떻게 다를까?#

LoRA 설정에서 자주 만나는 값은 다음 세 가지입니다.

설정 하는 일 값을 바꾸면 주로 달라지는 것
r 작은 행렬이 사용하는 중간 차원 학습 파라미터 수와 변화 표현 능력
lora_alpha LoRA 결과의 스케일 조절 기본 출력에 더하는 보정의 크기
lora_dropout 학습 중 LoRA 경로에 드롭아웃 적용 학습 과정의 정규화 정도

r: 얼마나 넓은 변화 공간을 허용할까?#

r이 커지면 A와 B의 크기도 커집니다.

LoRA 파라미터 수 = r × d_in + d_out × r

같은 대상 계층이라면 r을 두 배로 늘릴 때 LoRA 파라미터 수도 두 배가 됩니다. 표현할 수 있는 변화의 폭은 커지지만 학습 비용과 어댑터 크기도 늘어납니다.

반대로 r이 너무 작으면 작업에 필요한 변화를 충분히 표현하지 못할 수 있습니다. 그렇다고 r이 클수록 항상 더 좋은 결과를 얻는 것도 아닙니다.

정해진 만능 값은 없습니다. 작업, 데이터, 대상 계층에 맞춰 작은 값에서 시작해 검증 결과와 메모리 사용량을 비교해야 합니다.

lora_alpha: 보정값의 크기를 어떻게 조절할까?#

기본적인 LoRA 계산에서는 학습한 결과에 α / r을 곱합니다.

예를 들어 다음 설정이라면 스케일은 2입니다.

r = 16
lora_alpha = 32

α / r = 2

다만 alpha를 두 배로 하면 모델 품질이 두 배로 좋아진다는 뜻은 아닙니다. 학습률 등 다른 설정과 함께 모델의 학습 동작에 영향을 줍니다.

또 변형 기법에 따라 스케일 방식이 달라질 수 있습니다. 여기서는 기본 LoRA의 계산식을 설명합니다.

lora_dropout: 학습 중 일부 입력을 제외하기#

드롭아웃은 학습 과정에 적용하는 정규화 방법입니다. lora_dropout=0.05는 LoRA 경로의 학습에 드롭아웃을 설정하는 예입니다.

데이터가 적다고 무조건 특정 값을 써야 하는 것은 아닙니다. 드롭아웃 사용 여부와 정도도 검증 데이터의 결과를 보고 정해야 합니다.

target_modules: 모델의 어느 부분에 LoRA를 적용할까?#

LoRA는 모델의 모든 가중치에 자동으로 같은 방식으로 적용되는 기술이 아닙니다. 어느 계층에 작은 행렬을 추가할지 선택해야 합니다.

Transformer 기반 언어 모델에서는 어텐션 계층의 투영 행렬에 적용하는 예가 많습니다. 모델 구조에 따라 다음과 같은 이름을 볼 수 있습니다.

["q_proj", "k_proj", "v_proj", "o_proj"]
  • q_proj, k_proj, v_proj: 어텐션 계산에 쓰이는 변환
  • o_proj: 어텐션 결과를 출력 쪽으로 변환

또 다음처럼 MLP 계층의 선형 변환을 대상으로 삼는 모델도 있습니다.

["gate_proj", "up_proj", "down_proj"]

하지만 이 이름이 모든 모델에서 동일하다고 가정하면 안 됩니다. 모델 아키텍처를 확인한 뒤 실제 존재하는 모듈을 지정해야 합니다.

적용 계층이 넓을수록 무조건 낭비일까?#

아닙니다. 대상 계층이 늘어나면 학습할 LoRA 파라미터도 늘어납니다. 동시에 작업에 필요한 변화 표현 능력이 높아질 수도 있습니다.

Hugging Face PEFT는 QLoRA 방식의 학습 예로 모든 선형 계층을 대상으로 지정하는 target_modules="all-linear"도 안내합니다.

target_modules="all-linear"

따라서 “어텐션 계층만 적용해야 한다” 또는 “모든 선형 계층은 항상 과적합이다”라고 단정할 수 없습니다. 메모리와 품질을 함께 측정해 선택해야 합니다.

원문의 “target_modules가 품질의 70%를 결정한다”는 수치는 확인된 보편 법칙이 아닙니다. 적용 대상을 결정하는 중요한 설정이라는 점만 유지합니다.

LoRA와 QLoRA는 무엇이 다를까?#

두 용어는 비슷하지만 해결하려는 자원 문제가 다릅니다.

LoRA는 원본 모델을 고정하고 작은 어댑터를 학습합니다.

QLoRA는 기본 모델을 낮은 비트 수로 양자화해 저장하고, 그 모델을 고정한 채 LoRA 어댑터를 학습하는 접근입니다. QLoRA 논문에서는 4비트 NF4, 이중 양자화, 메모리 사용량 급증을 관리하는 옵티마이저 등을 제시했습니다.

구분 LoRA QLoRA
기본 모델 가중치 고정 양자화된 형태로 저장하고 고정
학습 대상 LoRA 어댑터 LoRA 어댑터
핵심 목적 학습할 파라미터 축소 학습할 파라미터 축소와 기본 모델의 메모리 사용 절감
유의할 점 기본 모델을 메모리에 올려야 함 양자화 지원 환경과 학습 설정을 함께 확인해야 함

“QLoRA면 어떤 7B 모델도 8GB GPU에서 학습할 수 있다”처럼 GPU 용량을 하나로 단정할 수 없습니다. 필요한 메모리는 모델 구조, 시퀀스 길이, 배치 크기, 정밀도, 옵티마이저와 학습 환경에 따라 달라집니다.

QLoRA의 양자화 방식 자체는 별도의 문서에서 더 깊게 다루고, 여기서는 LoRA 어댑터를 학습하면서 기본 모델의 메모리 부담을 줄이는 방법이라는 관계를 기억하면 됩니다.

실무 시나리오: 특정 분야 문서에 맞춘 모델#

다음은 실제 기업의 측정 결과가 아닌 가상 시나리오입니다.

한 팀이 특정 분야의 문서를 일정한 형식으로 요약하는 모델을 만들고 싶다고 가정해 보겠습니다. 전체 미세 조정에 필요한 자원이 부담된다면 LoRA 또는 QLoRA를 검토할 수 있습니다.

작업 순서는 다음과 같습니다.

  1. 기본 모델이 현재 문서를 얼마나 정확하게 요약하는지 먼저 측정합니다.
  2. 입력 문서와 기대 출력으로 학습 데이터를 구성합니다.
  3. 일부 자료를 학습에 사용하고, 별도 자료를 평가용으로 남깁니다.
  4. 적용 계층과 r, alpha 등을 정해 어댑터를 학습합니다.
  5. 학습 전후의 정확성, 누락, 잘못된 내용 생성 여부를 비교합니다.
  6. 필요한 메모리와 응답 시간, 운영 비용을 측정합니다.

어댑터가 작다는 사실과 답변의 정확도가 높다는 사실은 다릅니다. 특정 분야의 데이터로 학습했다고 해서 관련 사실을 항상 정확히 답하거나, 근거가 없는 정보를 생성하지 않게 되는 것도 아닙니다.

특히 법률·의료·금융 등 정확성이 중요한 분야에서는 실제 이용 목적에 맞는 평가 자료와 검토 절차가 필요합니다. 비용 절감이나 지연 시간 개선 역시 학습 방식만으로 결정되지 않으며, 배포 환경과 요청량을 포함해 측정해야 합니다.

PEFT로 LoRA 설정하기#

Hugging Face의 PEFT 라이브러리에서는 LoraConfig로 설정을 정의하고 get_peft_model()로 준비된 기본 모델에 적용할 수 있습니다.

다음은 이미 로드한 언어 모델 base_model이 있다는 가정에서 LoRA를 연결하는 핵심 코드입니다.

from peft import LoraConfig, TaskType, get_peft_model

lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type=TaskType.CAUSAL_LM,
)

model = get_peft_model(base_model, lora_config)
model.print_trainable_parameters()

각 설정의 역할은 다음과 같습니다.

코드 의미
r=16 LoRA의 중간 차원을 16으로 설정
lora_alpha=32 기본 LoRA 계산에서 스케일에 사용할 값
target_modules=[...] LoRA를 추가할 계층 이름
lora_dropout=0.05 학습 중 LoRA 경로의 드롭아웃 설정
bias="none" 바이어스를 별도로 학습하지 않도록 설정
TaskType.CAUSAL_LM 다음 토큰 예측 방식의 언어 모델 작업 지정

q_proj와 v_proj는 해당 이름의 모듈이 존재하는 모델에서만 사용할 수 있는 예입니다. 모델 구조가 다르면 대상 모듈 이름도 확인해야 합니다.

model.print_trainable_parameters()는 학습 가능한 파라미터 수를 확인하는 데 유용합니다. 출력 숫자는 사용한 기본 모델, 적용 계층, 랭크에 따라 달라지므로 원문의 특정 출력값을 모든 모델에 적용할 수는 없습니다.

이 코드만 실행하면 미세 조정이 끝날까?#

아닙니다. 위 코드는 학습할 LoRA 어댑터를 모델에 적용하는 단계입니다. 실제 학습에는 다음도 필요합니다.

  • 기본 모델과 토크나이저 로드
  • 학습 데이터 준비와 형식 점검
  • 학습 설정과 옵티마이저 구성
  • 학습 실행
  • 검증 데이터 평가
  • 어댑터 저장과 추론 확인

PEFT 설정 코드가 짧다는 사실이 전체 미세 조정 작업이 세 줄로 끝난다는 뜻은 아닙니다.

학습한 어댑터는 어떻게 사용할까?#

학습을 마친 뒤에는 기본 모델과 어댑터를 별도로 유지하거나, 조건이 맞는 경우 가중치를 병합할 수 있습니다.

어댑터를 별도로 두기#

추론할 때 기본 모델에 LoRA 어댑터를 연결해 사용합니다.

기본 모델 + 작업 A용 어댑터
기본 모델 + 작업 B용 어댑터

같은 기본 모델을 바탕으로 서로 다른 작업의 어댑터를 관리하기에 편리합니다. 다만 실제 어댑터 전환 방식과 메모리 사용량은 추론 도구와 배포 구조에 따라 다릅니다.

어댑터를 기본 모델에 병합하기#

기본 LoRA에서 결합할 수 있는 가중치는 개념적으로 다음과 같습니다.

병합된 가중치 = W + (α / r) × B × A

원문의 W + B × A는 스케일 인자를 생략한 표현입니다. 실제 병합에서는 학습 설정에 맞는 스케일이 반영되어야 합니다.

PEFT에서는 지원되는 구성에서 다음 메서드를 사용할 수 있습니다.

merged_model = model.merge_and_unload()

이 메서드는 병합된 모델을 반환하므로 반환값을 받아 사용합니다. 병합 후에는 별도의 LoRA 계산 경로에 따른 추론 오버헤드를 줄일 수 있지만, 병합된 전체 모델을 저장한다면 작은 어댑터 파일만 저장하는 것보다 저장 공간이 더 필요할 수 있습니다.

또 merge_and_unload()로 만든 모델을 그대로 “언머지”하는 흐름과, 어댑터를 유지한 채 merge_adapter() 후 unmerge_adapter()를 사용하는 흐름은 다릅니다. 나중에 어댑터를 다시 전환하거나 병합을 되돌려야 한다면 사용할 메서드와 보관할 파일을 미리 정해야 합니다.

“별도 어댑터의 추론 오버헤드는 언제나 3~5%”처럼 고정된 수치를 기대해서는 안 됩니다. 하드웨어, 요청 크기, 배치, 추론 엔진에 따라 달라집니다.

LoRA 설정을 고를 때 무엇을 측정해야 할까?#

r, alpha, 적용 계층은 모두 중요하지만, 숫자를 외워 적용하는 것만으로 품질을 보장할 수는 없습니다. 다음 항목을 같은 평가 조건에서 비교해 보세요.

확인 항목 질문
작업 품질 기본 모델보다 실제 작업의 결과가 개선되었는가?
일반화 학습에 쓰지 않은 자료에서도 개선이 유지되는가?
메모리 목표 하드웨어에서 학습과 추론이 가능한가?
처리 시간 학습 시간과 실제 응답 시간이 허용 범위인가?
어댑터 크기 저장·전환 방식에 맞는가?
실패 사례 어떤 입력에서 오답, 누락, 형식 오류가 발생하는가?

처음부터 모든 설정을 동시에 바꾸면 무엇이 개선을 만들었는지 알기 어렵습니다. 기준 설정을 하나 정한 뒤 적용 계층이나 랭크 같은 항목을 비교 가능한 방식으로 조정하는 편이 좋습니다.

데이터가 많으면 반드시 높은 랭크를 사용해야 한다거나, 특정 건수 이하에서는 r=4가 충분하다는 보편적인 기준도 없습니다. 데이터의 양뿐 아니라 작업의 성격과 데이터 품질이 중요합니다.

자주 하는 오해#

“LoRA는 모델 전체를 99% 이상 압축한다”#

앞의 99.2% 계산은 특정 크기의 행렬 하나에서 전체 원소 수와 LoRA 학습 원소 수를 비교한 예입니다. 기본 모델이 99.2% 작아진다는 뜻이 아닙니다.

“원래 가중치 변화량이 언제나 정확히 저랭크다”#

LoRA는 학습할 변화를 낮은 랭크의 행렬 곱으로 제한해 표현합니다. 모든 가능한 전체 미세 조정 결과를 항상 같은 낮은 랭크로 정확하게 재현한다는 보장은 없습니다.

“LoRA만 적용하면 작은 GPU에서도 어떤 모델이든 학습할 수 있다”#

기본 모델의 가중치를 보관하고 계산할 메모리는 여전히 필요합니다. QLoRA처럼 양자화와 결합하더라도 모델 크기와 학습 설정에 따라 요구 메모리가 달라집니다.

“적용 계층이 많을수록 반드시 나쁘다”#

적용 계층이 늘면 학습 파라미터와 비용이 증가할 수 있습니다. 그 대신 특정 작업에서는 품질에 도움이 될 수 있습니다. 모델 구조와 검증 결과를 기준으로 선택해야 합니다.

“어댑터가 작으면 응답도 자동으로 빠르다”#

학습할 파라미터 수와 실제 추론 지연 시간은 다른 지표입니다. 추론은 기본 모델 계산도 수행합니다. 어댑터 병합 여부, 요청 길이, 하드웨어, 배포 엔진을 함께 봐야 합니다.

정리#

LoRA는 사전 학습 모델의 가중치를 고정하고, 필요한 변화량을 작은 행렬 두 개로 학습하는 방법입니다.

기본 모델 출력 + 작은 어댑터가 만든 보정값 = LoRA 적용 출력

이 구조를 이해하면 주요 설정의 역할도 분명해집니다.

  • r은 변화량을 표현하는 중간 차원을 정합니다.
  • lora_alpha는 기본 LoRA에서 보정값의 스케일을 조절합니다.
  • target_modules는 모델의 어느 계층에 LoRA를 적용할지 정합니다.
  • QLoRA는 양자화된 기본 모델과 LoRA 학습을 결합해 메모리 부담을 더 줄이려는 방법입니다.
  • 학습한 어댑터는 별도로 사용하거나, 지원되는 구성에서 기본 모델에 병합할 수 있습니다.

LoRA의 장점은 “아주 작은 파일 하나로 어떤 분야에서도 높은 정확도를 얻는다”는 약속이 아닙니다. 제한된 학습 자원 안에서 모델을 새로운 작업에 적응시킬 선택지를 제공한다는 데 있습니다. 적절한 설정은 목표 작업의 평가 결과와 실제 자원 사용량으로 판단해야 합니다.