DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

PEFT 报 Target modules not found,LoRA 应该挂到哪一层

先读取真实模块名称,再区分 target_modules 的字符串正则与列表匹配。说明模型结构、层筛选和训练参数验收,避免套用其他模型的 q_proj 名称。

调用 get_peft_model() 时出现 Target modules ... not found in the base model,训练尚未开始。常见情况是复制了另一种模型的 q_proj、v_proj,或者把正则表达式放进了列表。

本文按 PEFT 0.17.0 的 LoRA 配置规则说明。模块名称属于模型实现,不能只根据“都是语言模型”判断。旧版本配置也应对照实际安装版本核查。

先看模型里到底有哪些模块

对已经加载的基础模型 model,列出名称与类型:

for name, module in model.named_modules():
    print(name, type(module).__name__)

这里不会打印权重内容。检查的是将被注入适配器的子模块,不是 named_parameters() 中以 .weight 结尾的参数名。

有的注意力实现把 Q、K、V 合在 query_key_value,有的拆成 q_proj、k_proj、v_proj。某个名字在另一份模型中有效,不代表当前模型也存在。先找到真实目标,再确认其类型能被当前 LoRA 实现支持;名称匹配成功但层类型不受支持,是后续另一种错误。

包装器和模型版本还会改变完整路径。自定义架构、替换层或加载了不同模型类时,应检查实际对象,不能仅看配置文件写着哪一种模型家族。

字符串与列表不是同一种匹配

PEFT 0.17.0 中,target_modules 传字符串时按正则匹配完整模块名;传列表时,检查完整名称相等或模块路径以点加该项结尾。列表中的内容不作为逐项正则。

假设前一步已确认目标名称以 query_key_value 结尾,匹配这类模块可用:

from peft import LoraConfig, TaskType, get_peft_model

config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    r=8,
    lora_alpha=16,
    target_modules=["query_key_value"],
)
adapted = get_peft_model(model, config)

r 和 lora_alpha 在这里仅是示例配置,需要按实际训练方案确定。这个目标名只适用于已确认具有相应模块的模型。

若业务确实需要用正则筛选完整路径,使用单个字符串,并先观察它会匹配哪些名字:

import re

pattern = r".*\.1\..*query_key_value"
matched = [
    name for name, _ in model.named_modules()
    if re.fullmatch(pattern, name)
]
print(matched)

这里的模式示意“路径中某个点分数字为 1”的筛选,不保证等同于业务定义的第一层;真实路径里可能有多个数字层级。核对输出后,才把 pattern 作为字符串传给 target_modules。写成 [pattern] 会改成列表匹配,常常找不到任何目标。

不要为了消除错误扩大到所有层

target_modules="all-linear" 在该版本可选择线性层与 Conv1D;对 PreTrainedModel 会排除输出层。它会改变适配器覆盖范围、训练参数数量及保存结果,不能作为任何目标名错误的统一替代。

如果还配置了 layers_to_transform、layers_pattern、exclude_modules 或 modules_to_save,也要核对筛选与排除条件。目标名存在,但层筛选没有匹配到索引,仍可能无法注入。正则预览只是名称检查,不完整模拟这些额外规则。

已经保存的适配器配置还应与原基础模型匹配。不要随意改目标名后加载旧适配器,再用忽略缺失权重的方式声称加载成功;保留原配置和权重,必要时建立新的训练输出目录。

注入成功后检查哪些参数会训练

在注入前记录预期模块列表。成功构建 adapted 后,可用下面的诊断片段核对训练范围:

adapted.print_trainable_parameters()
for name, parameter in adapted.named_parameters():
    if parameter.requires_grad:
        print(name, tuple(parameter.shape))

确认预期 LoRA 参数存在,基础层与额外可训练模块的状态符合方案,再进行受控的前向与反向检查。只有错误消失还不够:匹配范围过窄、意外选中了另一组层,同样可能让模型能启动但训练目标变了。