☰
DeepOpen 项目实战:Laya 编码器适配 CLINC150 150 类意图分类全流程复现指南
2026/9/27 6:22:48 网站建设 项目流程

【免费下载链接】deepopen

非自回归System 1决策引擎,专为结构化类型决策场景设计 DeepOpen Multilingual, non-autoregressive System 1 decision engine.

项目地址:https://gitcode.com/gh_mirrors/de/deepopen
点击查看免费下载

导读

本文是 DeepOpen 仓库中clinc150/目录的完整复现指南,核心任务是把开源 Laya 英文编码器(非自回归 System 1 决策引擎)适配为150 类固定意图分类器,并提供 R-Drop + SupCon 单模型与 Laya + DeBERTa 异构集成两条可复现路线。读完本文,你将掌握从环境搭建、数据与权重固定、CE/SupCon 基线训练、R-Drop 候选比较、冻结选择、测试导出到最终推理调用的完整命令行流程,并能理解每条命令背后的源码实现与评测边界。

1. 项目背景与技术目标

clinc150/是 DeepOpen 项目中基于 README.md 组织的独立实验目录,其总体目标一句话概括:

将 Laya 英文编码器适配为 150 类意图分类器,并提供R-Drop + SupCon 单模型与Laya + DeBERTa 异构集成两条复现路线。

主线流程为:安装 → 准备数据 → 训练基础对照 → 训练 R-Drop → 冻结并测试 → 导出推理。

完整评测成绩(官方完整 in-scope test 上的本地评测,不含 OOS 检测):

模型Test Accuracy推理编码器数
CE 基线,三种子均值97.015% ± 0.100 pp1
CE + SupCon,三种子均值97.326% ± 0.046 pp1
R-Drop + SupCon,三种子均值97.6593% ± 0.0898 pp1
验证选出的 R-Drop 单模型97.7556%1
Laya + 三个 DeBERTa-v3-large98.0222%4

表中±为种子样本标准差,pp为百分点;98.0222% 是四模型异构系统的成绩。需要强调:这些是本仓库自身历史实验的本地评测汇总,不是独立盲测,也不是正式榜单成绩,阅读时请勿将其当作对外宣称的"最强"结论。

2. 完整复现步骤

2.1 环境准备

以下命令基于Linux / WSL2 + Bash。解压或克隆仓库后,进入包含train_clinc.py的clinc150/目录,后续命令全部在该目录执行。本文按单卡顺序运行,不依赖原实验服务器的/opt/...路径,也不需要多卡并行。

硬件与软件要求:

  • 建议使用16GB 显存的 NVIDIA GPU进行单模型训练(视训练分支调整 batch);
  • GPU 需支持 CUDA 与BF16(训练配置强制使用 bfloat16 自动混合精度,见 train_clinc.py 中torch.autocast('cuda', dtype=torch.bfloat16));
  • 软件环境:Python 3.12、PyTorch 2.9.1+cu128、Transformers 4.57.6(requirements.txt 还锁定了safetensors==0.9.0rc0、tokenizers==0.23.0rc0等预发布版本,若包源缺失请见末尾常见问题);
  • 实际显存占用取决于 batch、序列长度与训练分支,单模型与 DeBERTa 集成应分别评估,原实验显卡总容量不代表最低显存要求。
# 若已位于包含 train_clinc.py 的目录,跳过下一行。 cd clinc150 python3.12 -m venv .venv source .venv/bin/activate python -m pip install torch==2.9.1 --index-url https://download.pytorch.org/whl/cu128 python -m pip install -r requirements.txt # upstream 不存在时执行;已有目录先确认固定版本。 git clone https://github.com/NandhaKishorM/laya.git upstream git -C upstream checkout 42626c348753fbb17572a813127df2278a1ec527 export CUDA_VISIBLE_DEVICES=0 export USE_TF=0 TOKENIZERS_PARALLELISM=false OMP_NUM_THREADS=8 python -m pip freeze > requirements-local.txt

环境检查:

python - <<'PY' import torch, transformers assert torch.cuda.is_available(), "未检测到 CUDA GPU" assert torch.cuda.is_bf16_supported(), "当前训练配置需要 BF16 支持" print(torch.__version__, transformers.__version__) print(torch.cuda.get_device_name(0)) PY

完成标志:打印出版本号和 GPU 名称。依赖含原实验环境的预发布版本,若包源缺失按末尾常见问题处理。

2.2 准备模型与数据

python prepare.py python verify_experiment.py

prepare.py做的事与源码完全对应(见 prepare.py):从clinc/oos-eval固定 revision 下载data_full.json,并从convaiinnovations/laya固定 revision 下载编码器配置、tokenizer 与model.safetensors,最后生成包含逐文件 SHA-256 的artifacts/manifest.json;若存在独立下载的expected_manifest.json,会逐字节校验后再使用。

对象固定版本 / 数量
英文基础模型convaiinnovations/laya@1c5edc17a7acd8701df6fc341c0d179f1c62c982
数据clinc/oos-eval@828f8093932c8fe6ca7936c3d2e52903b1c523de的data_full.json
Train / validation / test15,000 / 3,000 / 4,500
类别150,仅 in-scope

完成标志:损失性质测试通过,并生成:

data/data_full.json artifacts/base/model.safetensors artifacts/base/encoder/ artifacts/base/tokenizer/ artifacts/manifest.json artifacts/data_audit.json

关键适配点:数据审计发现,Laya 原始默认的 512-token 决策格式只保留 126 个候选标记,无法覆盖完整 150 类。因此本实验放弃原生的choice/score/noul输出接口,改为固定分类头:

文本 → Laya 编码器 → masked mean pooling → dropout → 150 类线性头

在源码中,这一结构由 train_clinc.py 的IntentModel实现:AutoModel.from_config(cfg, attn_implementation='sdpa')加载 Laya(ModernBERT 底座)编码器,load_laya_encoder用strict=True严格加载权重,前向时对last_hidden_state做非 padding token 的 masked mean pooling,再经nn.Dropout(0.1)与nn.Linear(hidden_size, 150)输出分类 logits。这是 CLINC150 专用的任务适配,不能理解为原生 Laya 全部能力的提升。

2.3 训练第一轮基础对照

先运行 CE / SupCon 各三个种子。这六组产物是第 4 步完整候选比较的前置输入,不能跳过后直接运行最终汇总脚本。

set -e for method in ce supcon; do for seed in 13 42 87; do python train_clinc.py train \ --method "$method" --seed "$seed" \ --output "artifacts/runs/${method}_${seed}" done done

train_clinc.py的默认训练参数(同时是其 argparse 默认值,见 train_clinc.py 末尾):

参数默认值说明
--epochs8训练轮数
--batch-size64第一轮支持调小(如 16),但会改变 SupCon 正负样本集合
--max-len64文本最大 token 长度
--lr2e-5编码器学习率
--contrastive-weight0.1SupCon 损失权重

分类头学习率固定为编码器的 10 倍(2e-4),优化器为 AdamW(weight_decay=0.01),10% warmup 线性衰减;SupCon 的对比温度为 0.1。训练时以(accuracy, -nll)为键保存每轮最佳 checkpoint(见train中best_key逻辑),并在训练结束后做基于验证集的候选比较(logit 温度 0.5/1.0/2.0 × 原型融合 alpha 0.0–1.0 网格搜索),写出selection.json、validation.npz与validation_search.json。

完成标志:六个 run 目录中都有selection.json、model.safetensors和validation.npz:

artifacts/runs/ ├── ce_13/ ├── ce_42/ ├── ce_87/ ├── supcon_13/ ├── supcon_42/ └── supcon_87/

所有配置与验证选择完成后,单独运行测试:

for method in ce supcon; do for seed in 13 42 87; do python train_clinc.py evaluate \ --output "artifacts/runs/${method}_${seed}" done done

完成标志:每个 run 生成test_metrics.json和test_predictions.npz。与上表 CE / SupCon 结果比较时,读取classifier_only.accuracy,不要混用原型融合后的selected指标。evaluate会额外输出排除与训练集重复文本后的干净指标,并防止同一 run 被二次评测(已有test_metrics.json会直接报错)。

只想先验证基本训练流程,可以先跑supcon + seed 13一组;要继续复现完整第二轮,请补齐其余五组。

2.4 训练 R-Drop 并完成候选比较

本步包含原实验中预先比较的权重平均、成组 SupCon 和 R-Drop 家族,最终只依据 validation accuracy / NLL 选择(test 集在development_data()中被刻意丢弃,见 round2.py)。

python verify_round2.py python round2.py diagnose python round2.py soups # 先导:两个方法各一个种子。 for method in balanced_supcon rdrop; do python round2.py train --method "$method" --seed 13 done touch artifacts/round2/SCREENING_COMPLETE # 补齐三个种子。 for method in balanced_supcon rdrop; do for seed in 42 87; do python round2.py train --method "$method" --seed "$seed" done done touch artifacts/round2/REPLICATES_COMPLETE

保留当前 Bash 的set -e,确保前置命令失败时停止,不写入完成标记。touch只能在对应训练成功结束后执行。

  • round2.py diagnose:对六组第一轮模型做验证集个体/集成诊断,输出diagnostics.json(含三个种子的混淆统计、batch=64 下期望正样本 anchor 占比等)。
  • round2.py soups:做权重平均(paired/同方法 3 种子/全部 6 种子),输出到soup_*目录。
  • round2.py train --method balanced_supcon:使用BalancedBatches采样器(150 类 × 25 个 4 样本块),确保每个 epoch 每类恰好访问一次;rdrop则用普通随机 batch。

R-Drop 对同一 batch 做两次 dropout 前向,损失组合为:

L = mean(CE₁, CE₂) + 0.1 × mean(SupCon₁, SupCon₂) + [KL(p₁ || p₂) + KL(p₂ || p₁)] / 2

它同时将编码器 dropout 调到 0.1(configure_dropout会同时改写 config 的attention_dropout/mlp_dropout/embedding_dropout以及所有nn.Dropout模块的p)。训练多一次前向,推理仍为一个编码器。成组 SupCon 和权重平均即使不优于 R-Drop,也保留作为完整候选比较的一部分。

完成标志:artifacts/round2/下有diagnostics.json,两个训练家族各有三个种子的selection.json,且SCREENING_COMPLETE、REPLICATES_COMPLETE两个完成标记存在。

2.5 冻结选择、测试和导出

python round2_finish.py freeze python round2_finish.py evaluate python round2_finish.py export

三个命令分别完成:

命令输出检查内容
freezeartifacts/round2/evaluation_freeze.json验证选中的模型、选择规则、代码 / 数据 / 权重哈希
evaluateartifacts/round2/test_summary.json完整 4,500 条 test 的结果和三种子统计
exportartifacts/round2/release_single/可独立加载的模型、tokenizer、配置和来源记录

freeze的选择规则是"验证集 accuracy 降序、NLL 升序"(源码中selection_rule字段明示);evaluate会对冻结清单内的每个模型做完整 test 推理,并补充与第一轮supcon_87的配对显著性分析(bootstrap 95% 区间与 McNemar 精确检验);export会把选中模型连同编码器配置、tokenizer、infer_clinc.py、train_clinc.py、LICENSE 一起打包成release_single/,并写入模型卡README.md与provenance.json(含权重 SHA-256)。

查看单模型结果:

python - <<'PY' import json from pathlib import Path p = Path("artifacts/round2/release_single") print("来源:", json.loads((p / "provenance.json").read_text())["source"]) print("指标:", json.loads((p / "test_metrics.json").read_text())["classifier_only"]) PY

历史验证选中了rdrop_42,测试为97.7556%(4,399 / 4,500)。本次重训必须保留本次验证选择,不能因为其他种子测试更高而换模型(test 集只用于评测,不参与选模)。

2.6 输入自己的文本

python infer_clinc.py \ --checkpoint artifacts/round2/release_single \ --text "what is my bank balance" \ --text "please book a flight to London"

完成标志:每条文本返回text、intent和probability。该模型为固定 150 类闭集分类器,不提供 OOS 拒识。部署时保存完整release_single/,不能只复制model.safetensors;推理使用本项目的 infer_clinc.py,不是 Transformers 通用分类 pipeline——它会读取config.json中的labels与max_len、selection.json的选择参数,并按inference_config.json的variant决定用纯分类头还是原型融合输出。

2.7 可选:复现 98.0222% 异构集成

先完成第 1–5 步,确保artifacts/round2/rdrop_42/下有权重、验证 logits 和测试预测。这条路线固定该历史 Laya 模型,另外训练 DeBERTa;不会自动跟随本次release_single选出其他种子。

A. 下载固定 DeBERTa 权重
python -m pip install -r requirements-hybrid.txt python prepare_hybrid.py --metadata-only python prepare_hybrid.py

脚本先从官方 Hub 获取固定 revision(microsoft/deberta-v3-large@64a8c8eab3e352a784c658aef62be1662607476f)的元数据,再下载并校验文件。成功后出现artifacts/hybrid/BASE_READY。

B. 先导验证与种子复验
python hybrid.py --seed 42 touch artifacts/hybrid/PILOT_COMPLETE python hybrid_replicates.py

最后一条命令会写入replicate_decision.json并输出yes/no。历史协议门槛是先导验证准确率超过 98.4%;只有输出yes时才继续补训:

python hybrid.py --seed 13 python hybrid.py --seed 87 touch artifacts/hybrid/TRAINING_COMPLETE

若输出no,本次运行没有满足原协议的扩展条件,应保留这一结果,不强行补训以追逐历史分数。

在源码层面,hybrid.py 中的HybridControl用AutoModel.from_pretrained(..., local_files_only=True)加载 DeBERTa-v3-large 底座,同样做 masked mean pooling + 150 类头;训练配置为 encoder LR 1e-5、head LR 1e-4、batch 16、梯度累积 4、SupCon 权重 0.1;每个 epoch 结束后在验证集上做 Laya 与 DeBERTa 概率的融合权重搜索(choose,alpha ∈ {0, 0.25, 0.5, 0.75, 1.0}),选出验证最优融合。

C. 冻结、评测与导出复验
python hybrid_finish.py freeze python hybrid_finish.py evaluate python hybrid_finish.py export python verify_hybrid_export.py python infer_hybrid.py \ --checkpoint artifacts/hybrid/release_system \ --text "what is my bank balance"

历史冻结选择为:

P = 0.5 × P(Laya rdrop_42) + [P(DeBERTa seed 13) + P(DeBERTa seed 42) + P(DeBERTa seed 87)] / 6

结果为98.0222%(4,411 / 4,500)。verify_hybrid_export.py 用导出推理接口重跑 test,历史记录的prediction_mismatches为 0;本次也应检查导出与本次冻结预测一致。

下图为异构集成先导与冻结测试两阶段的准确率对比,直观展示了 DeBERTa 单模型、验证集选优融合与固定 Laya 基准在 CLINC150 上的表现差异:

2.8 常见问题

问题处理方法
No such file或相对路径错误回到包含train_clinc.py的仓库根目录
第二轮缺少validation.npz完成第 3 步的六组训练
第二轮缺少旧模型test_predictions.npz完成第 3 步末尾的六组测试
Already frozen/Test already evaluated说明该阶段已有证据;不要删除记录强行重跑,使用新的实验目录副本
安装脚本出现/opt/...不存在本指南已提供通用命令,无需运行历史setup_remote.sh
CUDA OOM先确认显卡没有被其他任务占用。第一轮支持--batch-size 16等更小 batch;第二轮及异构脚本的 batch 在代码内固定。调整 batch 会改变 SupCon 的正负样本集合,需另记配置,不能保证复现原分数
下载失败或哈希不一致核对固定 revision 和下载是否完整,不要跳过校验
包源没有预发布依赖使用具有锁定版本的包源;若替换版本,记录新环境并重新验证,不视为原环境逐项一致
想直接推理,不想训练需要先获得完整导出权重;本仓库尚无公共微调权重下载地址

2.9 复现范围与更多资料

本指南覆盖推荐单模型的完整候选流程以及可选异构集成。第一轮冻结探针、检索、校准、第三轮蒸馏、第四轮重排器属于额外研究,不是主线运行所必需。

本文命令已对照实际脚本参数与前置产物检查;本次文档整理没有重跑 GPU 实验或验证全新机器安装。结果不保证跨硬件逐 bit 一致;多轮开发已知历史测试汇总,不能称为独立盲测或正式榜单成绩。

  • 第二轮方法说明
  • 第二轮完整结果
  • 异构集成报告
  • 第一轮详细技术报告

3. 本项目的改进点深度解析

3.1 从动态候选选择适配成固定分类

原始 Laya 的输入需要同时容纳问题、候选标签和文本。本实验审计的默认 512-token 格式仅保留 126 个候选标记,无法代表完整 150 类任务。

train_clinc.py严格加载 Laya 编码器,使用非 padding token 均值池化与 150 类线性分类头。标签不再占用输入预算,文本最大长度为 64;原始 train/validation 中最长输入分别为 39/30 token。这一步改变了模型的任务接口,是CLINC150 专用适配,不能理解为原生 Laya 全部能力的提升。

3.2 监督对比损失(SupCon)

普通 CE 学习正确标签,SupCon 同时鼓励 batch 内同类文本表示靠近:

L = CE + 0.1 × SupCon z = normalize(masked_mean(encoder(text))) 温度 = 0.1

源码中的supcon实现(见 train_clinc.py)会排除自配对与"无同类正对的 anchor"(valid = pos.sum(1) > 0),只对有效 anchor 求均值。第一轮在相同训练设置下,三种子均值从 97.015% 提高至 97.326%,平均增加 0.311 pp。原型与近邻融合没有稳定提高 test,未将其包装为必然有效的改进。

3.3 R-Drop 与编码器 dropout

第二轮将编码器 dropout 设为 0.1,并对两次随机前向加入对称 KL(symmetric_kl,即[KL(p₁‖p₂) + KL(p₂‖p₁)] / 2)。三种子测试均值为 97.6593%,相对第一轮 SupCon 增加 0.3333 pp;验证选中的单模型为 97.7556%。训练需要双前向,推理仍只需单前向。该实验同时改变 dropout 和一致性目标,未单独消融两者,不能把全部收益归因于 KL。

3.4 异构概率融合

固定 Laya,再训练三个 DeBERTa-v3-large,用验证集选择融合比例,最终系统为 98.0222%。相对推荐 Laya 单模型净多判对 12 条,代价是四个编码器的权重和前向计算。DeBERTa 分量使用不同预训练底座(hybrid.py 中microsoft/deberta-v3-large固定 revision);这是系统层面的收益,不是 Laya 单模型的结构改进。蒸馏、权重平均、成组采样和原生 top-5 重排器等后续实验也保留了未提升的结果,详见相关报告。

4. 未来可以探索的方向

以下是下一步可以验证的实验,不代表已经达到的效果:

方向建议怎么做判断是否有效
拆解 R-Drop 收益比较 SupCon、SupCon+dropout、SupCon+dropout+KL,补充等计算量对照看配对种子提升,而非只比较最佳 run
降低集成部署成本将四模型概率蒸馏到一个学生,并与等训练预算单模型比较同时报告准确率、延迟、显存和训练成本;既有蒸馏未成功,不保证提升
扩展 OOS 检测使用单独定义的 OOS 训练/验证协议和检测阈值区分 150 类准确率与 OOS 检测指标
减少候选输入限制在原生决策结构上测试完整候选或分层候选方案同时报全类别召回与最终准确率,不能仅报召回成功样本
独立泛化验证将冻结的方法迁移至 Banking77 目录 / 其他意图数据,不用新 test 调参统一报告正负结果与跨数据集差异
完善可下载产物发布完整导出权重、锁定环境、校验清单和评估入口新环境能加载模型并重算全部预测

继续开发时先冻结方法和评测规则,减少反复查看同一个测试集引入的选择偏差。

5. 源代码与相关数据

5.1 源代码清单

文件作用
prepare.py固定模型 / 数据下载与 manifest 校验
verify_experiment.py损失性质、输入预算与数据审计
train_clinc.py分类器结构、CE / SupCon、训练与第一轮评测
round2.pyR-Drop、成组采样、权重平均与验证比较
round2_finish.py选择冻结、完整 test 与导出
infer_clinc.py专用分类器推理
prepare_hybrid.py / hybrid.pyDeBERTa 下载与融合训练
hybrid_finish.py / infer_hybrid.py异构系统冻结、测试、导出和推理
verify_hybrid_export.py导出系统逐样本预测复核
requirements.txt / requirements-hybrid.txt依赖版本锁定

上游 Laya 固定在 commit42626c348753fbb17572a813127df2278a1ec527,英文 Laya 预训练模型固定在1c5edc17a7acd8701df6fc341c0d179f1c62c982,DeBERTa 固定在64a8c8eab3e352a784c658aef62be1662607476f。克隆方式:git clone https://github.com/NandhaKishorM/laya.git upstream。

5.2 相关数据

数据来源为 CLINC 官方仓库固定 revision 的data_full.json(revision828f8093932c8fe6ca7936c3d2e52903b1c523de),运行prepare.py后自动保存到data/data_full.json。

Split样本数用途
train15,000更新参数、构建训练原型或检索库
val3,000选择 epoch、温度和融合比例
test4,500冻结选择后评测
oos_*不纳入本文主任务不能将闭集结果解释为 OOS 效果

官方划分保持不变。规范化文本审计发现 train/val 重复 3 个、train/test 重复 2 个、val/test 无重复;补充结果排除与训练重复的 test 文本,主结果仍采用完整官方 test。

5.3 训练后需要保存什么

保存artifacts/manifest.json、requirements-local.txt、每个 run 的配置、验证选择、权重及逐样本预测;第二轮保留evaluation_freeze.json与test_summary.json;部署保留完整release_single/或release_system/。

代码随仓库提供,数据与基础权重由脚本下载;本仓库暂未提供公共微调权重下载地址,想直接推理需要先自行完成训练与导出流程。

【免费下载链接】deepopen

非自回归System 1决策引擎,专为结构化类型决策场景设计 DeepOpen Multilingual, non-autoregressive System 1 decision engine.

项目地址:https://gitcode.com/gh_mirrors/de/deepopen
点击查看免费下载

相关推荐

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询