PEFT documentation
PaCA: 부분 연결 적응
PaCA: 부분 연결 적응
PaCA(ICLR 2025)는 학습 속도와 활성화 메모리를 목표로 하는 PEFT 방법입니다. 각 대상 사전 학습 가중치의 r개의 무작위로 선택된 입력 열(“부분 연결”)을 미세 조정합니다. 학습 가능한 매개변수는 이러한 열의 업데이트만이며, LoRA와 달리 PaCA는 추가적인 저랭크 행렬을 추가하지 않습니다.
LoRA와 같은 방법은 사전 학습된 각 레이어 옆에 작은 저랭크(low-rank) 브랜치를 실행합니다. 이 브랜치는 적은 FLOPs가 필요하지만, 사전 학습된 레이어와 순차적으로 실행되며 역전파를 위해 입력 활성화의 자체 복사본을 유지합니다. PaCA는 이 두 가지 문제를 모두 피합니다:
- 레이어당 GEMM 1회. 적응된 열은 해당 matmul 직전에 사전 학습된 가중치에 기록되고, matmul 직후에 원래대로 복원됩니다. 따라서 forward와 backward 모두 동결된 베이스 레이어와 동일하게 matmul을 한 번만 실행합니다.
- 부분 활성화. 적응된 열의 기울기는 일치하는
r개의 입력 채널에만 의존하므로, 전체 입력 대신 역전파를 위해 해당 채널만 저장됩니다.
결과 가중치의 관점에서, PaCA 어댑터는 A 행렬이 고정된 열 선택기인 랭크 r의 LoRA 어댑터와 동등합니다: W' = W + delta @ S에서 S가 r개의 열을 선택합니다. 따라서 convert_to_lora()를 통해 손실 없이 랭크 r의 LoRA 어댑터로 변환할 수 있으며, 예를 들어 LoRA 추론 스택으로 서빙하는 데 사용할 수 있습니다.
PaCA를 사용할 때:
- LoRA 수준의 정확도를 유지하면서 더 빠른 fine-tuning 단계와 더 낮은 activation memory를 원합니다. 예를 들어, 동일한 GPU에서 더 긴 시퀀스나 더 큰 batch를 처리하기 위한 경우입니다.
- base weights에 정확히 병합되는 어댑터(업데이트가 단순한 컬럼 업데이트인 경우)가 필요합니다.
현재 제약 사항:
nn.Linear레이어(양자화 선형 레이어 포함)만 지원됩니다.- PaCA는 base layer의
forward를 호출하는 대신 matmul을 직접 실행하므로, base layer에 등록된 forward hook은 호출되지 않습니다(경고 메시지가 출력됩니다). 대신 PaCA layer에 hook을 등록하세요. - Mixed adapter batches(
adapter_names인자)는 지원되지 않습니다. - sharded weights(FSDP, DeepSpeed ZeRO-3)을 사용한 학습은 아직 테스트되지 않았습니다.
torch.compile이 지원됩니다: 컴파일 시 컬럼 스왑, matmul 및 restore가 불투명한 커스텀 오프(torch.ops.peft.paca_linear_forward/_backward)로 실행되므로 컴파일러가 베이스 가중치를 복사하지 않습니다. 이를 위해torch.library.custom_op(PyTorch >= 2.4)이 필요하며, 그렇지 않으면 eager 구현이 추적됩니다.paca_alpha / r은 열 업데이트를 스케일링하므로, 사실상 학습률의 배율 역할을 합니다.- 추론을 위해 어댑터를 병합(
merge_and_unload())하세요. 병합되지 않은 forward는 여전히 모든 호출 시 컬럼을 반복적으로 교체합니다.
사용
from transformers import AutoModelForCausalLM
from peft import PacaConfig, get_peft_model
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-3B")
config = PacaConfig(r=16, paca_alpha=16, target_modules="all-linear", random_seed=0)
model = get_peft_model(model, config)
model.print_trainable_parameters()기본적으로 대상이 되는 모든 레이어는 r개의 컬럼을 무작위로 선택하여 파인튜닝합니다. 해당 논문에서는 이 방식이 가중치 노름 또는 누적 그래디언트에 따라 컬럼을 선택하는 방식과 동등한 성능을 보였습니다. 컬럼을 직접 선택하려면, 예를 들어 다른 선택 전략을 시도하거나 레이어당 다른 수의 컬럼을 사용하려면 paca_indices_pattern을 전달하세요. 그 키는 LoRA의 rank_pattern와 마찬가지로 레이어 이름 또는 정규식입니다:
config = PacaConfig(
r=16,
paca_alpha=16,
target_modules=["q_proj", "v_proj"],
paca_indices_pattern={"layers.0.self_attn.q_proj": [0, 2, 4, 6], "layers.1.self_attn.v_proj": list(range(32))},
)키와 일치하는 레이어는 주어진 열을 fine-tune하고, 나머지 대상 레이어는 r개의 무작위 열을 선택합니다. 스케일링은 모든 레이어에서 config의 r를 사용하여 paca_alpha / r로 계산되므로, paca_alpha는 모든 레이어에서 동일한 의미를 가집니다.
해당 논문의 초록은 다음과 같습니다:
이전 파라미터 효율적 파인튜닝(PEFT) 알고리즘은 전체 모델이 아닌 소수의 추가 어댑터 파라미터만 학습시킴으로써 대규모 신경망 모델의 파인튜닝에 필요한 메모리 사용량과 계산 비용을 줄입니다. 그러나 PEFT에 따른 계산 비용 감소가 반드시 학습 시간 감소로 이어지지는 않습니다. 어댑터 레이어의 계산 비용은 사전 학습된 레이어보다 훨씬 작지만, 이 두 유형의 레이어가 GPU에서 순차적으로 처리되어 상당한 지연 오버헤드가 발생한다는 것은 잘 알려진 사실입니다. LoRA와 그 변형들은 추론 시 저랭크 어댑터 행렬을 사전 학습된 가중치와 병합하여 이러한 지연 오버헤드를 피합니다. 그러나 학습 중에는 저랭크 어댑터 행렬이 지속적으로 업데이트되는 동안 사전 학습된 가중치가 동결된 상태를 유지해야 하므로 해당 레이어를 병합할 수 없습니다. 또한 LoRA와 그 변형들은 첫 번째 저랭크 어댑터 행렬이 가중치 기울기를 계산하기 위해 사전 학습된 가중치의 입력 활성화가 여전히 필요하기 때문에 활성화 메모리를 줄이지 못합니다. 이 문제를 완화하기 위해, 우리는 모델에 어댑터 레이어를 도입하는 대신 사전 학습된 가중치 내에서 무작위로 선택된 부분 연결을 파인튜닝하는 Partial Connection Adaptation(PaCA)을 제안합니다. PaCA는 어댑터 레이어와 사전 학습된 레이어의 순차적 처리로 인한 시간 오버헤드를 제거하여 학습 속도를 향상시킬 뿐만 아니라, 기울기 계산에 전체 활성화가 아닌 부분 활성화만 저장하면 되므로 활성화 메모리도 줄입니다. LoRA와 비교할 때, PaCA는 MMLU 데이터셋에서의 파인튜닝과 Oasst1 데이터셋에서의 지시 튜닝과 같은 다양한 파인튜닝 시나리오에서 유사한 정확도를 유지하면서 학습 시간을 22%, 총 메모리 사용량을 16% 줄입니다. PaCA는 양자화와도 결합할 수 있어 LLaMA3.1-70B와 같은 대규모 모델의 파인튜닝을 가능하게 합니다. 또한 PaCA는 LoRA에 비해 NVIDIA A100 GPU와 INTEL Gaudi2 HPU 모두에서 23% 더 긴 시퀀스로 학습할 수 있고 처리량을 16% 향상시킵니다.
벤치마크 개요
API
PacaConfig
클래스 peft.PacaConfig
< source >( task_type: Optional[Union[str, TaskType]] = Nonepeft_type: Optional[Union[str, PeftType]] = Noneauto_mapping: Optional[dict] = Nonepeft_version: Optional[str] = Nonebase_model_name_or_path: Optional[str] = Nonerevision: Optional[str] = Noneinference_mode: bool = Falser: int = 8paca_alpha: int = 8target_modules: list[str] | str | None = Noneexclude_modules: list[str] | str | None = Nonelayers_to_transform: list[int] | int | None = Nonelayers_pattern: list[str] | str | None = Nonerandom_seed: int | None = Nonepaca_indices_pattern: dict | None = <factory>init_weights: bool = Truemodules_to_save: list[str] | None = None )
매개변수
- r (
int, 선택 사항, 기본값8) — 각 대상 레이어에서 미세 조정되는 입력 열(부분 연결)의 수입니다.(out_features, in_features)형태의 가중에 대해, PaCA는r * out_features개의 매개변수를 학습하며, 이는 랭크가r인 LoRA 어댑터의B행렬과 동일한 수입니다.in_features를 초과할 수 없습니다. - paca_alpha (
int, 선택 사항, 기본값8) — 스케일링 계수입니다. 선택된 열의 업데이트는paca_alpha / r * delta입니다.lora_alpha와 마찬가지로, 이는 어댑터의 유효 학습률에 곱해지는 배율 역할을 합니다. - target_modules (
Union[list[str], str], 선택 사항) — PaCA로 교체할 모듈 이름의 목록 또는 모듈 이름의 정규식 표현입니다. 예를 들어,['q_proj', 'v_proj']또는'.*decoder.*(SelfAttention|EncDecAttention).*(q|v)$'입니다. 이 값이'all-linear'로 지정되면 출력 레이어를 제외한 모든 선형 모듈이 선택됩니다.nn.Linear레이어만 지원됩니다. - exclude_modules (
Union[list[str], str], 선택 사항) — 어댑터를 적용하지 않을 모듈의 이름입니다. 문자열을 전달하면 정규식 매칭이 수행됩니다. 문자열 목록을 전달하면 정확한 매칭이 수행되거나, 모듈 이름이 전달된 문자열 중 하나로 끝나는지 확인됩니다. - layers_to_transform (
Union[list[int], int], 선택 사항) — 변환할 레이어 인덱스입니다. 이 인수가 지정되면 PEFT는 해당 리스트에 지정된 레이어 인덱스만 변환합니다. 단일 정수가 전달되면 PEFT는 해당 인덱스의 레이어만 변환합니다. - layers_pattern (
Optional[Union[list[str], str]], 선택 사항) —layers_to_transform이None과 다르면만 사용되는 레이어 패턴 이름입니다. 이는 모델의nn.ModuleList를 대상으로 해야 하며, 보통'layers'또는'h'라고 불립니다. - random_seed (
int, 선택 사항, 기본값None) — 부분 연결을 선택하는 데 사용되는 시드입니다. 각 레이어는 이 시드와 레이어 이름에서 파생된 서로 다른 선택을 사용합니다.None인 경우 전역 torch 난수 생성기가 사용됩니다. 선택된 인덱스는 항상 어댑터 체크포인트에 저장되므로, 학습된 어댑터를 로드할 때 시드가 필요하지 않습니다. - paca_indices_pattern (
dict, 선택 사항) — 레이어 이름 또는 정규식 표현에서 해당 레이어에서r개의 무작위 선택 대신 fine-tuning되는 입력 열 인덱스로의 선택적 매핑입니다. 예를 들어{'^model.layers.0.self_attn.q_proj': [0, 2, 4]}와 같습니다. 이를 통해 레이어별로 서로 다른 수의 열을 사용할 수도 있습니다. 레이어의 인덱스는in_features보다 작아야 하며 고유해야 합니다. 스케일링은paca_alpha / r이며, 모든 레이어에서 이 config의r을 사용합니다. 이는 주어진 인덱스의 수와 무관합니다. 어떤 키에도 매칭되지 않는 대상 레이어는r개의 무작위로 선택된 열을 사용합니다. - init_weights (
bool, 선택 사항, 기본값True) —True인 경우, 선택된 열의 업데이트가 0으로 초기화되어 초기화 시점에 적응된 모델이 기본 모델과 동일해집니다.False로 설정하면 무작위 값으로 초기화되며, 이는 테스트 목적으로만 사용됩니다. - modules_to_save (
list[str], 선택 사항) — PaCA 레이어를 제외하고 최종 체크포인트에 학습 가능 상태로 설정되어 저장될 모듈 목록입니다. 예를 들어, 시퀀스 분류 또는 토큰 분류 작업에서 최종 레이어인classifier/score는 무작위로 초기화되므로 학습 가능 상태로 설정되고 저장되어야 합니다.
이것은 PacaModel의 구성을 저장하기 위한 구성 클래스입니다.
PaCA(Partial Connection Adaptation, https://huggingface.co/papers/2503.01905)는 각 대상 사전 학습 가중치의 r개의 무작위로 선택된 입력 열(부분 연결)을 미세 조정합니다. 학습 가능한 매개변수는 이러한 열의 업데이트뿐이며, LoRA와 달리 PaCA는 추가적인 저랭크 행렬을 도입하지 않습니다. 행렬 곱셈 직전에 적응된 열이 사전 학습 가중치로 교체되고, 행렬 곱셈 직후 즉시 원래 상태로 복원되므로 전방 전파와 역전파 모두 단일 GEMM만 실행됩니다. 또한 역전파 시에는 r개의 선택된 입력 채널만 메모리에 유지됩니다.
PacaModel
class peft.PacaModel
< source >( modelpeft_config: Union[PeftConfig, dict[str, PeftConfig]]adapter_name: strlow_cpu_mem_usage: bool = Falsestate_dict: Optional[dict[str, torch.Tensor]] = None ) → torch.nn.Module
매개변수
- model (PreTrainedModel) — 적응할 모델.
- config (PacaConfig) — PaCA 모델의 구성입니다.
- adapter_name (
str) — 어댑터의 이름이며, 기본값은"default"입니다. - low_cpu_mem_usage (
bool,optional, 기본값False) — 메타 디바이스에 빈 어댑터 가중치를 생성합니다. 로딩 프로세스를 가속하는 데 유용합니다.
반환값
torch.nn.Module
PaCA 모델.
사전 학습된 모델에서 Partial Connection Adaptation(PaCA) 모델을 생성합니다. 해당 방법은 https://huggingface.co/papers/2503.01905에 설명되어 있습니다.
예:
>>> from transformers import AutoModelForCausalLM
>>> from peft import PacaConfig, get_peft_model
>>> base_model = AutoModelForCausalLM.from_pretrained("facebook/opt-125m")
>>> config = PacaConfig(r=16, paca_alpha=16, target_modules="all-linear")
>>> model = get_peft_model(base_model, config)속성:
- model (PreTrainedModel) — 적응할 모델.
- peft_config (PacaConfig): PaCA 모델의 구성입니다.