【免费下载链接】deepopen
非自回归System 1决策引擎,专为结构化类型决策场景设计 DeepOpen Multilingual, non-autoregressive System 1 decision engine.
导读
本文是 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 pp | 1 |
| CE + SupCon,三种子均值 | 97.326% ± 0.046 pp | 1 |
| R-Drop + SupCon,三种子均值 | 97.6593% ± 0.0898 pp | 1 |
| 验证选出的 R-Drop 单模型 | 97.7556% | 1 |
| Laya + 三个 DeBERTa-v3-large | 98.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.pyprepare.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 / test | 15,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 donetrain_clinc.py的默认训练参数(同时是其 argparse 默认值,见 train_clinc.py 末尾):
| 参数 | 默认值 | 说明 |
|---|---|---|
--epochs | 8 | 训练轮数 |
--batch-size | 64 | 第一轮支持调小(如 16),但会改变 SupCon 正负样本集合 |
--max-len | 64 | 文本最大 token 长度 |
--lr | 2e-5 | 编码器学习率 |
--contrastive-weight | 0.1 | SupCon 损失权重 |
分类头学习率固定为编码器的 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三个命令分别完成:
| 命令 | 输出 | 检查内容 |
|---|---|---|
freeze | artifacts/round2/evaluation_freeze.json | 验证选中的模型、选择规则、代码 / 数据 / 权重哈希 |
evaluate | artifacts/round2/test_summary.json | 完整 4,500 条 test 的结果和三种子统计 |
export | artifacts/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.py | R-Drop、成组采样、权重平均与验证比较 |
| round2_finish.py | 选择冻结、完整 test 与导出 |
| infer_clinc.py | 专用分类器推理 |
| prepare_hybrid.py / hybrid.py | DeBERTa 下载与融合训练 |
| 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 | 样本数 | 用途 |
|---|---|---|
| train | 15,000 | 更新参数、构建训练原型或检索库 |
| val | 3,000 | 选择 epoch、温度和融合比例 |
| test | 4,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.
相关推荐
DeepOpen Laya + DeBERTa 异构编码器概率融合:CLINC150 混合系统实验方案与实现解析
DeepOpen Laya + DeBERTa 异构编码器概率融合:CLINC150 混合系统实验方案与实现解析 导读 本文完整解析 DeepOpen 项目在
Laya源码解读:双向编码器+决策头如何实现单步前向传播分类
Laya源码解读:双向编码器+决策头如何实现单步前向传播分类 Laya 是一个多语言、非自回归的 System 1 决策引擎:核心是一个双向编码器(Modern
人工智能NLP强化学习如何用SillyTavern轻松打造你的专属AI对话助手?简单三步实现智能自动化
如何用SillyTavern轻松打造你的专属AI对话助手?简单三步实现智能自动化 还在为重复的AI对话设置而烦恼吗?SillyTavern让你告别繁琐操作,只需
人工智能AI 应用交互助手前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考