news 2026/9/20 18:51:47

PEFT 中 PSOFT 微调实战:主元子空间上的高效正交微调(PsoftConfig 详解与 LLaMA 训练示例)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PEFT 中 PSOFT 微调实战:主元子空间上的高效正交微调(PsoftConfig 详解与 LLaMA 训练示例)

PEFT 中 PSOFT 微调实战:主元子空间上的高效正交微调(PsoftConfig 详解与 LLaMA 训练示例)

【免费下载链接】peft🤗 PEFT: State-of-the-art Parameter-Efficient Fine-Tuning.项目地址: https://gitcode.com/gh_mirrors/pe/peft

本文围绕 PEFT 仓库中 PSOFT(Principal Subspace adaptation Orthogonal Fine-Tuning,主元子空间正交微调)的官方示例 examples/psoft_finetuning/README.md 展开,讲清楚 PSOFT 的核心思想(把 LoRA 的低秩结构与 OFT 的正交性约束结合)、PsoftConfig全部关键参数的语义与默认值,并给出从 125M 小模型快速上手到 LLaMA-3.2-3B 完整训练的复现路径。读完本文,你可以直接复制仓库中的训练脚本完成一次 PSOFT 微调,并理解底层 A/B 分解缓存、Cayley 参数化与 Cayley–Neumann 近似的实现细节。

1. PSOFT 是什么:介于 LoRA 与 OFT 之间的正交微调

PSOFT 的目标是在保持 OFT(Orthogonal Fine-Tuning)核心原则——保留预训练权重列向量之间的几何关系——的同时,在参数、计算与内存三个维度上取得均衡。与依赖稀疏化设计的 OFT 变体(如 OFTv2、BOFT、GOFT)不同,PSOFT 从"低秩主元子空间"的视角出发,把正交变换限制在预训练权重的 top-r 主元子空间内,从而在 LoRA 与 OFT 之间架起桥梁。官方文档页 PSOFT 参考文档 还给出了它在 GLUE、VTAB-1K、GSM8K、MATH 及常识推理等基准上的有效性说明。

具体做法是:对权重矩阵做 SVD,$W_{\text{pre}} = U S V^\top$,取 top-r 奇异分量构造主元子空间 $W_{\text{pri}} = U_r S_r V_r^\top = AB$,于是

$$W_{\text{pre}} = AB + W_{\text{res}}$$

训练中冻结 $A$、$B$ 与残差 $W_{\text{res}}$,只训练中间的 $R$(以及可选的幅值向量 $\alpha$、$\beta$)。文档页区分两种模式:

  • PSOFT-SO(严格正交):$W_{\text{ps-tuned}} = A R B + W_{\text{res}}$;
  • PSOFT-RO(放松正交):$W_{\text{ps-tuned}} = A, \mathrm{diag}(\alpha), R, \mathrm{diag}(\beta), B + W_{\text{res}}$,两个低维可调向量在训练中逐步放松正交约束以提升任务适应性。

为兼容 PEFT 框架"加法式权重更新"的约定,实现层面采用等价形式:

$$W_{\text{ps-tuned}} = W_{\text{pre}} + A (R - I_r) B$$

这一实现细节可以从源码直接验证:layer.py 中Linear.get_delta_weight计算的就是B @ (R - I) @ A * scaling。仓库对 PSOFT 的适用边界有两条明确限制:仅支持nn.Linear不支持量化层(见 model.py 的dispatch_default与 layer.py 中对权重的 dtype 检查)。

2. 快速上手:四行配置接入 PSOFT

以下是最小可运行流程(继承自 README 的 Quick Start 章节),使用 TRL 的SFTTrainer在 IMDB 数据上训练:

import torch from peft import PsoftConfig, get_peft_model from transformers import AutoTokenizer, AutoModelForCausalLM from trl import SFTConfig, SFTTrainer from datasets import load_dataset model_name = "facebook/opt-125m" model = AutoModelForCausalLM.from_pretrained(model_name) tokenizer = AutoTokenizer.from_pretrained(model_name) tokenizer.pad_token_id = tokenizer.eos_token_id psoft_config = PsoftConfig( r=32, psoft_alpha=32, ) peft_model = get_peft_model(model, psoft_config) peft_model.print_trainable_parameters() dataset = load_dataset("imdb", split="train[:1%]") training_args = SFTConfig(dataset_text_field="text", max_length=128) trainer = SFTTrainer( model=peft_model, args=training_args, train_dataset=dataset, processing_class=tokenizer, ) trainer.train() peft_model.save_pretrained("psoft-opt-125m")

关键点说明:

  • PsoftConfig在 config.py 中定义,__post_init__会把peft_type固定为PeftType.PSOFT,并做一系列参数合法性校验(r > 0、初始化方式与 SVD 后端枚举、Cayley–Neumann 参数范围等);
  • 默认r=32psoft_alpha=32,二者相等使缩放因子scaling = psoft_alpha / r = 1,与文档"缩放因子通常设为 r"的最佳实践一致(scaling的计算见 layer.py 的update_layer);
  • 只传rpsoft_alpha时,其余参数走默认值:ab_svd_init="psoft_init"psoft_svd="full"psoft_orth=Truepsoft_mag_a/b=True,即默认开启"放松正交"(RO)模式。

完整参数与文档化配置示例

PSOFT 参考文档 给出了带完整注释的配置写法,覆盖了所有核心开关:

config = PsoftConfig( r=32, # 可训练矩阵 R 的维度 psoft_alpha=32, # 缩放因子(通常设为 r) target_modules=["q_proj", "v_proj"], # 目标注意力投影层 ab_svd_init="psoft_init", # 主元子空间初始化 psoft_svd="full", # SVD 方法 psoft_orth=True, # 启用正交 R(Cayley 参数化) psoft_mag_a=True, # 启用可调向量 alpha psoft_mag_b=True, # 启用可调向量 beta use_cayley_neumann=False, # 关闭 Cayley–Neumann 近似 num_cayley_neumann_terms=5, # Neumann 级数项数 cayley_neumann_eps=None, # 数值稳定性阈值 )

结合 config.py 的字段定义,各参数语义与默认值如下:

参数默认值说明
r32正交变换 R 的维度,决定适配器容量;建议 32–128(简单任务)或 64–256(复杂任务)
psoft_alpha32缩放因子,语义同 LoRA alpha;scaling = psoft_alpha / r
psoft_dropout0.0作用在 A 路径上的 Dropout
ab_svd_init"psoft_init""psoft_init":A 行正交的非对称 SVD 初始化(严格正交,PSOFT 默认);"pissa_init":A/B 对称分解(标准 PiSSA 风格)
psoft_svd"full""full"torch.linalg.svd"lowrank"torch.svd_lowrank
psoft_svd_lowrank_niter10psoft_svd="lowrank"时生效的幂迭代次数
random_seed0psoft_svd="lowrank"时用于固定随机投影,保证保存/加载后结果可复现
psoft_orthTrueTrue 时 R 经 Cayley 参数化保持正交;False 时 R 为自由矩阵
psoft_mag_a/psoft_mag_bTrue / True在 R 的输入/输出侧各学一个对角缩放向量(RO 模式的 α、β)
use_cayley_neumannFalse用 Neumann 级数代替矩阵求逆,提升大 rank 下的计算效率
num_cayley_neumann_terms5use_cayley_neumann=True时生效,项数越多正交近似误差越小
cayley_neumann_epsNone对生成矩阵 Q 的 Frobenius 范数上界;设为 (0,1) 内的值(如 0.9)会在范数超限时对 Q 重缩放
fan_in_fan_outFalse被替换层以 (fan_in, fan_out) 存储权重时置 True
layers_to_transform/layers_patternNone限定作用层;与字符串形式的target_modules(正则)互斥,__post_init__中会直接抛错

这些校验并非纸面约束,tests/test_initialization.py 中有对应测试逐一验证:例如psoft_svd="full"却修改了psoft_svd_lowrank_niter会触发 UserWarning,use_cayley_neumann=Truenum_cayley_neumann_terms<=0cayley_neumann_eps不在 (0,1) 会直接抛出 ValueError。

3. 底层实现:正交层如何构造 R,A/B 如何初始化

3.1 OrthLayer:用 r(r-1)/2 个参数表示 r×r 正交矩阵

可训练的核心是 layer.py 中的OrthLayer。当psoft_orth=True时,它并不直接存储完整的 r×r 矩阵,而是只存一个上三角向量(r*(r-1)//2个参数),由_skew_symmetric还原为反对称矩阵 Q,再经Cayley 变换$R = (I+Q)(I-Q)^{-1}$ 得到正交矩阵——这就是"通过 Cayley 参数化保证 R 正交"的来源,权重置零即对应 $R=I$(初始时更新量为零,训练从预训练模型无损出发)。

两种求 R 的路径:

  • 精确路径use_cayley_neumann=False):调用torch.linalg.solve(I-Q, I+Q, left=False),半精度下会自动升 fp32 求解;
  • Cayley–Neumann 近似路径use_cayley_neumann=True):用级数 $R \approx I + 2(Q + Q^2 + \cdots + Q^{t-1}) + Q^t$ 代替求逆,num_cayley_neumann_terms控制截断项数 t;cayley_neumann_eps非 None 时会先把 $|Q|_F$ 投影到该上界以内,改善数值稳定性(源码注释说明该思路借鉴自 OFT v2 的 Cayley/Neumann 参数化)。

随后get_matrix按开关把vector_b(按行缩放)与vector_a(按列缩放)乘到 R 上,即 RO 模式的 α/β。reset_parameters中:正交模式权重清零,非正交模式初始化为单位阵,两个幅值向量一律初始化为 1(初始恒等)。

3.2 A/B 缓存:主元子空间分解与两种初始化

update_layer会先检查r <= min(in_features, out_features),然后调用_build_psoft_ab_cache_buffers(见 layer.py)构建 A、B 缓存:

  1. 把基座权重转成 fp32 并取 (out, in) 布局(若基座权重不是 float32/float16/bfloat16 会抛 TypeError,这正是"不支持量化层"的落点);
  2. psoft_svd选择后端:fulltorch.linalg.svd取前 r 个奇异分量;lowranktorch.svd_lowrank,并在torch.random.fork_rng内用random_seed播种,保证随机投影确定性(因为torch.svd_lowrank不接受 generator 参数,且必须覆盖 SVD 实际运行的设备);
  3. ab_svd_init组装:
    • psoft_initA = U_h[:r](行正交),B = V_r @ diag(Sr / scaling),把缩放吸进 B;
    • pissa_init:取sqrt(Sr_scaled)A = diag(s)@U_hB = V_r@diag(s),得到对称 A/B(无严格正交约束的 PiSSA 风格)。

A、B 存入BufferDict缓存并冻结,训练只更新psoft_R。前向传播(Linear.forward)的增量计算为xa = x @ A.Txr = R(xa)delta_y = (xr - xa) @ B.T * scaling,再与基座输出相加——这正是加法式形式 $W_{pre} + A(R-I)B$ 的逐元素实现。

3.3 合并与 LoRA 转换

Linear.merge/unmerge基于get_delta_weight把 $\Delta W$ 加减回基座权重,支持safe_merge(合并后检测 NaN)。此外supports_lora_conversion返回 True,即 PSOFT 适配器可转换为 LoRA 形式使用。

4. 完整训练:LLaMA-3.2-3B 上的复现命令

仓库提供了带完整参数解析的训练脚本 psoft_finetuning.py,其ScriptArguments继承SFTConfig,把上述 PSOFT 参数全部暴露为命令行参数,并额外处理了数据侧逻辑:数据集若没有text列,可用--dataset_field "[input, output]"自动拼成### USER: ...\n### ASSISTANT: ...的 SFT 文本。脚本开头还有一道防御性检查:只接受bf16/fp16/fp32三种精度,从源头杜绝误加载量化模型。

README 中给出的 LLaMA-3.2-3B 命令可直接复制运行:

python psoft_finetuning.py \ --base_model_name_or_path meta-llama/Llama-3.2-3B \ --output_dir ./outputs/psoft-llama3.2-3b-imdb \ --data_path imdb \ --dataset_split "train[:1%]" \ --max_length 128 \ --num_train_epochs 1 \ --per_device_train_batch_size 1 \ --gradient_accumulation_steps 8 \ --learning_rate 5e-4 \ --bits bf16 \ --r 128 \ --psoft_alpha 128 \ --target_modules q_proj v_proj

要点:r=128psoft_alpha=128成对出现(scaling=1);目标模块限定为q_projv_proj(脚本默认值也是这两个);bits=bf16指定 bf16 精度加载基座,device_map="auto"自动分片。训练结束后,适配器与 tokenizer 会保存到output_dir/psoft_ft下。

脚本中各 PSOFT 相关参数的默认值与 config.py 保持一致:ab_svd_init="psoft_init"psoft_svd="full"psoft_orth=Truepsoft_mag_a/b=Trueuse_cayley_neumann=Falsenum_cayley_neumann_terms=5psoft_svd_lowrank_niter默认为 None,仅在用户显式设置(通常配合--psoft_svd lowrank)时才传入配置。

5. 官方最佳实践与适用建议

以下五条 Best Practices 完整继承自 README,并结合源码给出对应落点:

  1. 秩的选择(Rank Choice):较小秩(32–128)适合简单任务;较大秩(64–256)表达力更强,但参数与计算开销同步上升。r直接决定 R 的规模(OFT 参数个数为 $r(r-1)/2$),也受r <= min(in, out)约束。
  2. 缩放因子(Scaling Factor)psoft_alpha通常设为 r,使scaling = psoft_alpha / r = 1
  3. 学习率(Learning Rate):使用常规学习率区间(如1e-45e-3)即可获得稳定训练(LLaMA 示例用的5e-4落在此区间);
  4. SVD 初始化(SVD Initialization)lowrank后端比full更省内存与算力,更适合大模型。注意lowrank结果依赖随机投影,仓库通过random_seed参数(默认 0)保证保存的适配器在重新加载后可复现输出;
  5. Cayley–Neumann 近似:秩较大时开启use_cayley_neumann=True可显著提升计算效率(免去 r×r 求逆),小秩时收益有限;Neumann 级数项数取 5(默认值)通常能在精度与效率间取得平衡。需要更强数值稳定性时可设置cayley_neumann_eps(如 0.9)。

6. 验证、测试与基准结果

仓库内有多处可交叉验证 PSOFT 行为的证据:

  • 配置校验测试:tests/test_initialization.py 覆盖了非法参数(terms 非正、eps 越界、niter/eps 在不适用场景下的告警)以及配置构造;
  • 模型级测试:tests/test_custom_models.py 中包含{"target_modules": ["lin0"], "r": 4, "psoft_alpha": 4, "psoft_svd": "lowrank", "psoft_svd_lowrank_niter": 10}use_cayley_neumann=True等多种 PSOFT 配置的组合测试;
  • 方法对比基准:仓库 method_comparison/MetaMathQA 目录下有 PSOFT 在 LLaMA-3.2-3B 上的实测记录,如 psoft--llama-3.2-3B-default.json 与 psoft--llama-3.2-3B-fast.json(后者对应"fast"变体,可对照本文的低秩/Cayley–Neumann 效率选项);
  • 架构映射:从 constants.py 看,TRANSFORMERS_MODELS_TO_PSOFT_TARGET_MODULES_MAPPING直接复用了 LoRA 的模型-目标模块映射,因此未显式指定target_modules时,PSOFT 会按已知架构自动选择目标层,未知架构则报错要求手动指定。

7. 引用信息

如在使用 PSOFT 时引用该方法,可参考 README 中的 BibTeX 信息:

@inproceedings{wu2026efficient, title={Efficient Orthogonal Fine-Tuning with Principal Subspace Adaptation}, author={Wu, Fei and Hu, Jia and Min, Geyong and Wang, Shiqiang}, booktitle={The Fourteenth International Conference on Learning Representations}, year={2026} }

小结:PSOFT 用"SVD 主元子空间 + 冻结 A/B + 可训练小尺寸正交 R(可选 α/β 放松)"的组合,把 OFT 的正交语义保留与 LoRA 式的低参数量结合起来。实操上记住三件事即可:默认配置(r=32, psoft_alpha=32, psoft_orth=True, mag_a/b=True)适合快速实验;大模型把psoft_svd切到lowrank;大 rank 时打开use_cayley_neumann。注意其仅支持nn.Linear且不支持量化基座这两条硬边界。

【免费下载链接】peft🤗 PEFT: State-of-the-art Parameter-Efficient Fine-Tuning.项目地址: https://gitcode.com/gh_mirrors/pe/peft

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 18:51:21

UDEC离散元数值模拟实战指南:从建模到调试全流程解析

简介&#xff1a;通用离散元程序是岩土工程中常用的数值模拟软件&#xff0c;这份中文指导说明&#xff08;详尽版&#xff09;是一份面向初学者的权威教程&#xff0c;旨在帮助快速理解离散元建模思路与模拟过程。资源为单个DOC文档&#xff0c;大小1.88MB&#xff0c;内容从软…

作者头像 李华
网站建设 2026/9/20 18:48:26

docx模板批量生成与形式审查:职称申报论文自动化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 18:47:19

端到端数采链路中的边缘数据处理流水线设计与实操

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 18:47:04

Furion内置定时任务实战:从ISchedule到动态调度

简介&#xff1a;面向.NET开发者的Furion内置定时任务学习资源&#xff0c;聚焦框架基于Hangfire封装的定时任务模块&#xff0c;帮助读者快速掌握在真实项目中注册、调度与监控后台任务的方法。资源包共12个文件&#xff0c;以7个C#源码文件为主&#xff0c;配合JSON配置、项目…

作者头像 李华
网站建设 2026/9/20 18:45:38

Gurobi学术版安装全指南:30分钟跑通model.optimize()

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 18:44:07

Java SSM老年人健康饮食管理系统:从需求分析到答辩全流程解析

简介&#xff1a;面向Java SSM框架课程设计与毕业设计编写的完整毕业论文文档&#xff0c;以“老年人健康饮食管理系统”为题&#xff0c;围绕需求分析、系统设计、功能实现进行系统阐述。文档可分为绪论、相关技术、需求分析、总体设计、功能设计、数据库设计、系统实现等章节…

作者头像 李华