The current state of the PEFT docs is not one of structure and I was constantly annoyed that whenever I wanted to change something there were several places that needed touching and they all felt disconnected. So this is my attempt at structuring the docs. Some of these ideas are quite old (discussed in 01/2025) but are still valid. I've removed most of the code guides without replacement. That's not ideal, I think we should have code examples but I'm think they should be method-focused. Maybe one general example of a training workflow is sufficient because most methods follow the same scheme. All details from the method guides (prompting, lora, oft/boft, etc.) are now integrated into the respective method pages instead. I would have hesitated to do this if these guides would have integrated information about the adapters but they didn't. I think it makes a lot more sense to have one place for each method to gather examples/tips/recommendations and that is now the `package_refernce/<method>` page. This page now also hosts a small space that shows the MetaMathQA (and potentially other) benchmark results highlighted for that method. I've moved the LoRA initializations to `package_reference/lora#Initialization` and converted the init methods to `<hfoption>`-tags. This collapses them to a list but may reduce searchability through the document - at least firefox is not able to search 'through' the option tabs. This also doesn't make them appear in the ToC and people specifically searching for, say, PiSSA won't find it directly. I think that's OK though, since the search is able to locate it. The quicktour is a bit more detailed about what happens under the hood (quick doesn't have to mean simplistic) and includes some new visualizations. I hope that we can integrate more visualizations in the future where it makes sense. * Remove PEFT method space + front page buttons The space was not that useful anymore since most methods are compatible with most models. The front page buttons are, at least temporarily, with the exception of the quicktour and method overview buttons. I like the visuals but there should only be elements that are useful. --------- Co-authored-by: Benjamin Bossan <BenjaminBossan@users.noreply.github.com> Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>
7.0 KiB
PSOFT
PSOFT is an Orthogonal Fine-Tuning (OFT)-based parameter-efficient fine-tuning method that preserves the geometric relationships of pre-trained weight column vectors while achieving a balanced trade-off between performance and multi-dimensional efficiency, including parameter count, memory usage, and computational cost. By restricting orthogonal transformations to a low-rank principal subspace derived from pre-trained weights, PSOFT bridges the gap between LoRA and OFT, providing both theoretical guarantees and practical adaptability. Its effectiveness is validated through extensive evaluations on diverse benchmarks, including GLUE, VTAB-1K, GSM8K, MATH, and commonsense reasoning benchmarks.
- Only
nn.Linearlayers are supported. - Quantized layers are not supported.
The abstract from the paper is:
Driven by the rapid growth of model parameters, parameter-efficient fine-tuning (PEFT) has become essential for adapting large models to diverse downstream tasks under constrained computational resources. Within this paradigm, orthogonal fine-tuning and its variants preserve semantic representations of pre-trained models, but struggle to achieve both expressiveness and efficiency in terms of parameter counts, memory, and computation. To overcome this limitation, we propose efficient Orthogonal Fine-Tuning with Principal Subspace adaptation (PSOFT), which confines orthogonal transformations to the principal subspace of pre-trained weights. Specifically, PSOFT constructs this subspace via matrix decomposition to enable compatible transformations, establishes a theoretical condition that strictly maintains the geometry of this subspace for essential semantic preservation, and introduces efficient tunable vectors that gradually relax orthogonality during training to enhance adaptability. Extensive experiments on 35 NLP and CV tasks across four representative models demonstrate that PSOFT offers a practical and scalable solution to simultaneously achieve semantic preservation, expressiveness, and multi-dimensional efficiency in PEFT.
How PSOFT Works
PSOFT decomposes each weight matrix W_{pre} into W_{pri} and W_{res} using SVD:
W_{\text{pre}} = U S V^\top
The principal subspace W_{\text{pri}} = U_r S_r V_r^\top = AB is constructed from the top-r singular components:
W_{\text{pre}} = W_{\text{pri}} + W_{\text{res}} = AB + W_{\text{res}},
W_{\text{ps-tuned}} = ARB + W_{\text{res}}. (PSOFT-SO: PSOFT with strict orthogonality)
W_{\text{ps-tuned}} = A \, \mathrm{diag}(\alpha) \, R \, \mathrm{diag}(\beta) \, B + W_{\text{res}}. (PSOFT-RO: PSOFT with relaxed orthogonality)
During training, A, B, and W_{\text{res}} are frozen, and only R (or R with \alpha and \beta) is trainable.
For compatibility with the PEFT framework (which expects additive weight updates), PSOFT is implemented in the following additive form:
W_{\text{ps-tuned}} = W_{\text{pre}} + A (R - I_r) B
Trainable Parameters
After applying PSOFT:
- The original model weights (
A,B, andW_{\text{res}}) are frozen. - Only the orthogonal matrix
R(and optionally\alpha,\beta) are trainable. - No additional bias parameters are introduced.
Basic Usage
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)
Configuration Options
Different Mode
(PSOFT-SO: PSOFT with strict orthogonality)
config = PsoftConfig(psoft_orth=True,psoft_mag_a=False,psoft_mag_b=False)
(PSOFT-RO: PSOFT with relaxed orthogonality)
config = PsoftConfig(psoft_orth=True,psoft_mag_a=True,psoft_mag_b=True)
Best Practices
- Rank Choice: Smaller ranks (e.g.,
32–128) are suitable for simpler tasks, while larger ranks (e.g.,64–256) provide greater expressiveness for more complex tasks at the cost of increased parameters and computation. - Scaling Factor: The scaling factor is typically set to
rin PSOFT. - Learning Rate: Use standard learning rates (e.g.,
1e-4to5e-3) for stable training. - SVD Initialization: The
lowrankoption is more memory- and compute-efficient thanfull, making it more suitable for large models. - Cayley–Neumann Approximation: When the rank is large, enabling the Cayley–Neumann approximation can significantly improve computational efficiency, while the benefit is less pronounced for small ranks. In practice, a small number of Neumann series terms (typically
5) usually provides a good balance between accuracy and efficiency.
Benchmark overview
API
PsoftConfig
autodoc tuners.psoft.config.PsoftConfig
PsoftModel
autodoc tuners.psoft.model.PsoftModel