PEFT documentation
PSOFT
PSOFT
PSOFT는 직교 미세 조정(Orthogonal Fine-Tuning, OFT) 기반의 매개변수 효율적 미세 조정 방법입니다. 사전 학습된 가중치 열 벡터의 기하학적 관계를 보존하면서, 매개변수 수, 메모리 사용량, 계산 비용 등 다차원적 효율성과 성능 사이의 균형 잡힌 트레이드오프를 달성합니다. PSOFT는 직교 변환을 사전 학습된 가중치에서 유도된 저랭크 주성분 부분공간으로 제한하여 LoRA와 OFT 사이의 격차를 해소하며, 이론적 보장과 실용적 적응성을 모두 제공합니다. 그 효과는 GLUE, VTAB-1K, GSM8K, MATH, 상식 추론 벤치마크를 포함한 다양한 벤치마크에 대한 광범위한 평가를 통해 검증되었습니다.
nn.Linear레이어만 지원됩니다.- 양자화 레이어는 지원되지 않습니다.
해당 논문의 초록은 다음과 같습니다:
모델 파라미터의 급속한 성장에 힘입어, 제한된 계산 자원 내에서 대규모 모델을 다양한 다운스트림 작업에 적응시키기 위한 파라미터 효율적 파인튜닝(PEFT)이 필수적이 되었습니다. 이 패러다임 내에서 직교 파인튜닝(orthogonal fine-tuning)과 그 변형들은 사전 학습 모델의 의미 표현을 보존하지만, 파라미터 수, 메모리, 계산 측면에서 표현력과 효율성을 동시에 달성하는 데 어려움을 겪고 있습니다. 이러한 한계를 극복하기 위해, 우리는 사전 학습 가중치의 주성분 부분공간(principal subspace)으로 직교 변환을 제한하는 효율적 직교 파인튜닝 with Principal Subspace adaptation(PSOFT)을 제안합니다. 구체적으로 PSOFT는 행렬 분해를 통해 호환 가능한 변환을 가능하게 하는 이 부분공간을 구성하고, 필수적인 의미 보존을 위해 이 부분공간 기하학을 엄격하게 유지하는 이론적 조건을 확립하며, 학습 중 직교성을 점진적으로 완화하여 적응력을 향상시키는 효율적 튜너블 벡터를 도입합니다. 4개의 대표 모델에 걸친 35개의 NLP 및 CV 작업에 대한 광범위한 실험은 PSOFT가 PEFT에서 의미 보존, 표현력, 다차원 효율성을 동시에 달성하는 실용적이고 확장 가능한 솔루션을 제공함을 보여줍니다.
PSOFT 작동 방식
PSOFT는 각 가중치 행렬 을(를) 과(와) SVD를 사용하여:
주요 부분공간 는 상위 $r$개의 특이 성분으로 구성됩니다:
(PSOFT-SO: 엄격한 직교성을 가진 PSOFT
(PSOFT-RO: 이직성(orthogonality)을 완화한 PSOFT
학습 중에 $A$, $B$, 그리고 은 고정되고, 오직 (또는 을 사용하는 만 학습 가능합니다.
PEFT 프레임워크(가산적 가중치 업데이트를 기대함)와의 호환성을 위해, PSOFT는 다음과 같은 가산 형태로 구현됩니다:
학습 가능한 매개변수
PSOFT 적용 후:
- 원래 모델 가중치($A$, $B$, $W_{\text{res}}$)는 고정됩니다.
- 직교 행렬만 (그리고 선택적으로 $\alpha$, $\beta$)만 학습 가능합니다.
- 추가 편향 매개변수는 도입되지 않습니다.
기본 사용법
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PsoftConfig, get_peft_model
# Load base model
model_id = "facebook/opt-125m"
model = AutoModelForCausalLM.from_pretrained(model_id)
# Configure PSOFT
config = PsoftConfig(
r=32, # the dimension of trainable matrix R,
psoft_alpha=32, # scaling factor (typically set to r in PSOFT),
target_modules=["q_proj", "v_proj"], # target attention projection layers
ab_svd_init="psoft_init", # principal subspace initialization
psoft_svd="full", # SVD method
psoft_orth=True, # enable orthogonal R (Cayley parameterization)
psoft_mag_a=True, # enable tunable vector alpha
psoft_mag_b=True, # enable tunable vector beta
use_cayley_neumann=False, # disable Cayley–Neumann approximation
num_cayley_neumann_terms=5, # number of Neumann series terms
cayley_neumann_eps=None, # improve numerical stability
)
# Apply PSOFT
model = get_peft_model(model, config)
model.train()
tokenizer = AutoTokenizer.from_pretrained(model_id)
tokenizer.pad_token = tokenizer.eos_token
# Train
inputs = tokenizer("Hello world", return_tensors="pt", padding=True)
loss = model(**inputs, labels=inputs["input_ids"]).loss
loss.backward()
trainable = [p for p in model.parameters() if p.requires_grad]
optimizer = torch.optim.AdamW(trainable, lr=5e-4)
optimizer.step()
optimizer.zero_grad(set_to_none=True)구성 옵션
다른 모드
(PSOFT-SO: 엄격한 직교성을 가진 PSOFT)
config = PsoftConfig(psoft_orth=True,psoft_mag_a=False,psoft_mag_b=False)(PSOFT-RO: 이직성(orthogonality)을 완화한 PSOFT)
config = PsoftConfig(psoft_orth=True,psoft_mag_a=True,psoft_mag_b=True)최적의 관행
- 랭크 선택: 더 작은 랭크(예:
32–128)는 단순한 작업에 적합하며, 더 큰 랭크(예:64–256)는 매개변수와 계산량이 증가하는 대가로 더 복잡한 작업에 대한 표현력을 높여 줍니다. - Scaling Factor: 스케일링 팩터는 일반적으로 PSOFT에서 다음과 같이 설정됩니다.
- 학습률: 안정적인 학습을 위해 표준 학습률(예:
1e-4에서5e-3)을 사용하세요. - SVD 초기화:
lowrank옵션은full보다 메모리와 계산 효율성이 높아 대규모 모델에 더 적합합니다. - Cayley–Neumann Approximation: 랭크가 큰 경우, Cayley–Neumann 근사를 활성화하면 계산 효율성을 크게 향상시킬 수 있지만, 랭크가 작은 경우에는 그 이점이 덜 두드러집니다. 실무에서는 Neumann series 항의 개수를 소수로(일반적으로
5) 설정하면 정확도와 효율성 사이의 좋은 균형을 제공합니다.
벤치마크 개요
API
PsoftConfig
class peft.PsoftConfig
< 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 = 32target_modules: Optional[Union[list[str], str]] = Noneexclude_modules: Optional[Union[list[str], str]] = Nonepsoft_alpha: int = 32psoft_dropout: float = 0.0fan_in_fan_out: bool = Falseab_svd_init: Literal['psoft_init', 'pissa_init'] = 'psoft_init'psoft_svd: Literal['full', 'lowrank'] = 'full'psoft_svd_lowrank_niter: int = 10random_seed: int = 0psoft_orth: bool = Truepsoft_mag_b: bool = Truepsoft_mag_a: bool = Trueuse_cayley_neumann: bool = Falsenum_cayley_neumann_terms: int = 5cayley_neumann_eps: Optional[float] = Nonemodules_to_save: Optional[list[str]] = Noneinit_weights: bool = Truelayers_to_transform: Optional[Union[list[int], int]] = Nonelayers_pattern: Optional[Union[list[str], str]] = None )
매개변수
- r (
int) — 기본값은 32입니다. PSOFT 랭크(r)는 r*r 변환 R을 통해 어댑터 용량을 제어합니다. 간단한 작업에는 일반적으로 32-128의 작은 랭크가 충분하며, 더 복잡한 작업은 64-256을 사용하면 표현력이 높아지지만 추가적인 매개변수와 계산 비용이 발생합니다. 경험적으로 검증된 설정은 논문을 참고하세요: https://openreview.net/forum?id=FSHrinMArK. - target_modules (
Optional[Union[List[str], str]]) — 어댑터를 적용할 모듈의 이름입니다. 이 값이 지정되면 지정된 이름을 가진 모듈만 교체됩니다. 문자열을 전달하면 정규식 매칭이 수행됩니다. 문자열 목록을 전달하면 정확한 매칭이 수행되거나, 모듈 이름이 전달된 문자열 중 하나로 끝나는지 확인됩니다. 이 값이 ‘all-linear’로 지정되면 모든 linear/Conv1D 모듈이 선택됩니다(모델이 PreTrainedModel인 경우 출력 레이어는 제외). 이 값이 지정되지 않으면 모델 아키텍처에 따라 모듈이 선택됩니다. 아키텍처가 알려지지 않은 경우 오류가 발생하며, 이 경우 대상 모듈을 수동으로 지정해야 합니다. - exclude_modules (
Optional[Union[List[str], str]]) — 어댑터를 적용하지 않을 모듈의 이름입니다. 문자열을 전달하면 정규식 매칭이 수행됩니다. 문자열 목록을 전달하면 정확한 매칭이 수행되거나, 모듈 이름이 전달된 문자열 중 하나로 끝나는지 확인됩니다. - psoft_alpha (
int) — 기본값은 32입니다. PSOFT 스케일링 계수를 제어합니다. LoRA alpha와 동일한 의미를 가집니다. - psoft_dropout (
float) — 기본값은 0.0입니다. PSOFT 경로에 적용되는 Dropout입니다. LoRA dropout과 동일한 의미를 가집니다. - fan_in_fan_out (
bool) — 교체할 레이어가 가중치를 (fan_in, fan_out) 형태로 저장하는 경우 True로 설정합니다. 예를 들어, gpt-2는 가중치를 (fan_in, fan_out) 형태로 저장하는Conv1D를 사용하므로 이 값을True로 설정해야 합니다. - ab_svd_init (
Literal["psoft_init", "pissa_init"]) — 기본값은 ‘psoft_init’입니다. PSOFT에서 주 부분공간을 구성하는 데 사용되는 A와 B의 초기화 전략입니다. ‘psoft_init’: 행 직교 A를 사용하는 SVD 기반 초기화로, 엄격한 직교성을 보장합니다(PSOFT). ‘pissa_init’: 대칭인 A와 B를 사용하는 SVD 기반 초기화(표준 PiSSA). - psoft_svd (
Literal["full", "lowrank"]) — 기본값은 ‘full’입니다. 초기화에 사용할 SVD 백엔드: ‘full’은 torch.linalg.svd를, ‘lowrank’는 torch.svd_lowrank를 사용합니다. - psoft_svd_lowrank_niter (
int) — psoft_svd=‘lowrank’일 때만 사용됩니다. 기본값은 10입니다. psoft_svd=‘lowrank’일 때 torch.svd_lowrank에서 사용되는 power iteration의 횟수입니다. - psoft_orth (
bool) — 기본값은 ‘True’입니다. True인 경우, Cayley parameterization을 통해 R이 직교 행렬이 되도록 제약하여 사전 학습된 가중치 벡터의 열 사이의 기하학적 관계를 보존합니다. False인 경우, R은 직교성 제약이 없는 자유 행렬입니다. - psoft_mag_b (
bool) — 기본값은 ‘True’입니다. True인 경우, R의 ‘output’ 측에서 대각 스칼링 벡터를 학습합니다. 사전 학습된 기하 구조에 약간의 왜곡을 유발하면서 작업 적응력을 높이기 위해 psoft_mag_a와 함께 사용되는 경우가 많습니다. - psoft_mag_a (
bool) — 기본값은 ‘True’입니다. True인 경우, R의 ‘input’ 측에서 대각 스칼링 벡터를 학습합니다. 사전 학습된 기하 구조에 약간의 왜곡을 유발하면서 작업 적응력을 높이기 위해 psoft_mag_b와 함께 사용되는 경우가 많습니다. - use_cayley_neumann (
bool) — 기본값은 ‘False’입니다. PSOFT의 Cayley-Neumann 형식을 사용할지 여부를 지정합니다. 계산 효율성을 높이기 위해 True로 설정할 수 있지만, 직교성에 대한 근사 오차가 커지는 비용이 발생합니다. - num_cayley_neumann_terms (
int) — 기본값은 5입니다. use_cayley_neumann=True일 때만 사용됩니다. 사용할 Cayley-Neumann 항의 수입니다. 값이 높을수록 직교성에 대한 근사 오차가 줄어듭니다. - cayley_neumann_eps (
optional[float]) — 기본값은 ‘None’입니다. use_cayley_neumann=True일 때만 사용됩니다. Cayley-Neumann 근사법에서 생성자 행렬 Q에 대한 선택적 Frobenius-노름 상한입니다. None(기본값)인 경우 리스케일링이 적용되지 않습니다. (0, 1) 범위의 값(예: 0.9)으로 설정된 경우, ||Q||_F가 임계값을 초과할 때마다 수치적 안정성을 높이기 위해 Q가 리스케일링됩니다. 자세한 내용은 https://spherelab.ai/oftv2/를 참조하세요. - init_weights (
bool) — 기본값은 ‘True’입니다. PSOFT 레이어의 가중치를 기본 초기화 방식으로 초기화할지 여부를 지정합니다. 정확히 무엇을 하는지 알고 있는 경우를 제외하고는 이 설정을 변경하지 마세요. - modules_to_save (
List[str]) — 어댑터 레이어를 제외한 최종 체크포인트에 학습 가능 상태로 설정되고 저장될 모듈 목록. - layers_to_transform (
Union[List[int], int]) — 변환할 레이어의 인덱스입니다. 정수 목록을 전달하면 이 목록에 지정된 레이어 인덱스에 어댑터를 적용합니다. 단일 정수를 전달하면 해당 인덱스의 레이어에 변환을 적용합니다. - layers_pattern (
Optional[Union[List[str], str]]) —layers_to_transform가None과 다르면만 사용되는 레이어 패턴 이름입니다. 이는 모델의nn.ModuleList를 대상으로 해야 하며, 보통'layers'또는'h'라고 불립니다.
PSOFT(Principal Subspace Adaptation을 활용한 효율적인 직교 미세 조정)에 대한 설정입니다.
PSOFT는 저랭크 행렬 A와 B 사이에 r*r 직교 변환 R을 삽입하여 저랭크 업데이트를 ΔW = B @ (R-I) @ A로 수행합니다. 학습 대상은 R(및 선택적 튜너블 벡터)뿐이며, A와 B는 psoft_init (SVD 기반, 행 직교 A)으로 초기화된 후 고정됩니다.
PsoftModel
class peft.PsoftModel
< source >( modelpeft_config: Union[PeftConfig, dict[str, PeftConfig]]adapter_name: strlow_cpu_mem_usage: bool = Falsestate_dict: Optional[dict[str, torch.Tensor]] = None )
PSOFT(Principal Subspace Adaptation을 활용한 효율적인 직교 미세 조정) 모델.
저항 A와 B 사이에 r*r 직교(또는 스케일링) 변환 R을 삽입합니다: ΔW = B @ (R-I) @ A. A/B를 SVD에서 초기화하고 동결한 뒤 R(및 선택적 크기 벡터)만 학습하려면 ab_svd_init="psoft_init"을 사용하세요.