- 推理引擎
- 大模型
【免费下载链接】FlexGen
Running large language models on a single GPU for throughput-oriented scenarios.
导读
本文介绍如何基于 Hugging Face Transformers 生态,使用 HANS(Heuristic Analysis for NLI Systems)数据集对自然语言推理(NLI)模型进行对抗性评估。HANS 专门用于检测模型是否在依赖词汇重叠、子序列、句法成分等表层启发式线索,而非真正理解蕴含关系。读完本文,你将掌握完整的评估流水线:从获取 HANS 数据集、用 GLUE 脚本训练 NLI 模型,到运行run_hans.py生成预测文件、再通过 HANS 官方评分脚本按三类启发式分别统计 entailed / non-entailed 准确率,并能读懂示例结果揭示的模型脆弱性。本指南以仓库中的 README.md 为骨架,结合 run_hans.py 与 utils_hans.py 源码展开。
HANS:为什么需要对抗性评估
常规 GLUE 评测(如 MNLI 的 dev 集准确率)衡量的是模型在标准分布上的表现。然而,已有研究(McCoy et al., 2019,见 arXiv:1902.01007)指出,很多 NLI 模型"作弊":它们并非真正理解句子的蕴含关系,而是利用训练数据中的统计捷径。HANS 数据集正是为暴露这一缺陷而设计,它构造了三种启发式陷阱:
- 词汇重叠(lexical overlap):前提与假设共享大量词汇,模型易误判为蕴含;
- 子序列(subsequence):假设恰好是前提的连续子串,模型易直接判蕴含;
- 句法成分(constituent):假设与前提的某个句法成分相同,模型易被误导。
HANS 对每种启发式同时提供entailed(真蕴含)与non-entailed(假蕴含)两类样例。若模型依赖启发式而非语义,其 non-entailed 准确率会远低于 entailed 准确率——这正是对抗性评估的核心诊断信号。本指南对应的示例由 Nafise Sadat Moosavi 提供,被收录于仓库的 research_projects 目录。
环境准备与依赖
运行评估脚本前需要安装 Transformers 及相关依赖。仓库中 requirements.txt 明确锁定transformers == 3.5.1。由于run_hans.py基于较老的 Trainer API(使用HfArgumentParser、TrainingArguments),建议在兼容该版本的 Python 3.6+ 环境中执行:
pip install transformers==3.5.1此外脚本运行依赖torch、numpy、tqdm、filelock(用于缓存文件的跨进程锁),请一并安装:
pip install torch numpy tqdm filelock获取 HANS 数据集
HANS 数据集由 Tom McCoy 提供,可从其官方仓库下载。下载解压后,目录中应包含以下两个核心文件:
heuristics_train_set.txt:训练集,带标签(run_hans.py支持do_train时使用);heuristics_evaluation_set.txt:评估集,即对抗性评测所用数据。
从源码 utils_hans.py 可以看到,HansProcessor正是读取这两个文件构造样例:
def get_train_examples(self, data_dir): return self._create_examples(self._read_tsv(os.path.join(data_dir, "heuristics_train_set.txt")), "train") def get_dev_examples(self, data_dir): return self._create_examples(self._read_tsv(os.path.join(data_dir, "heuristics_evaluation_set.txt")), "dev")因此,命令行中的--data_dir $HANS_DIR必须指向包含上述两个.txt文件的目录。
获取经过 NLI 训练的模型
HANS 评估针对的是已经过 NLI 任务训练的模型。README 建议使用run_glue.py在 MNLI 上训练模型(例如 BERT-base),训练产物即模型目录路径$MODEL_PATH。仓库中的 legacy/pytorch-lightning/run_glue.py 即为此类训练脚本的示例(使用glue_processors、glue_tasks_num_labels等 API 完成 GLUE 任务处理)。
模型目录需包含pytorch_model.bin(或 TF 权重)、config.json与词表文件,run_hans.py通过AutoConfig/AutoTokenizer/AutoModelForSequenceClassification加载。需要注意run_hans.py的版本差异:--model_name_or_path若指向含.ckpt的路径,源码会以from_tf=True加载 TF 权重(见 run_hans.py)。
运行对抗性评估:run_hans.py 完整指南
命令行参数
README 给出的核心命令如下:
export HANS_DIR=path-to-hans export MODEL_TYPE=type-of-the-model-e.g.-bert-roberta-xlnet-etc export MODEL_PATH=path-to-the-model-directory-that-is-trained-on-NLI-e.g.-by-using-run_glue.py python run_hans.py \ --task_name hans \ --model_type $MODEL_TYPE \ --do_eval \ --data_dir $HANS_DIR \ --model_name_or_path $MODEL_PATH \ --max_seq_length 128 \ --output_dir $MODEL_PATH参数说明如下:
| 参数 | 取值示例 | 含义 |
|---|---|---|
--task_name | hans | 任务名,必须为hans(源码hans_tasks_num_labels = {"hans": 3}仅注册了该任务) |
--model_type | bert/roberta/xlnet等 | 模型类型,决定 tokenizer 行为 |
--do_eval | 无值 | 触发评估模式,生成预测文件 |
--data_dir | HANS 数据集目录 | 需包含heuristics_evaluation_set.txt等文件 |
--model_name_or_path | 模型目录或 HF 模型 ID | 被评估的 NLI 模型 |
--max_seq_length | 128 | 序列最大长度,超长截断、不足补齐 |
--output_dir | 模型目录 | 预测结果输出位置 |
三类参数对象与可选参数
run_hans.py通过HfArgumentParser同时解析三组参数(见 run_hans.py):
- ModelArguments:
--config_name、--tokenizer_name、--cache_dir,用于指定与模型不同的配置/分词器或下载缓存位置; - DataTrainingArguments:
--task_name、--data_dir、--max_seq_length(默认 128)、--overwrite_cache; - TrainingArguments(Transformers 内置):
--do_train、--do_eval、--per_device_eval_batch_size、--seed、--local_rank(分布式)、--fp16、--overwrite_output_dir等。README 示例仅用默认 batch size 与 seed;若要复现示例结果,注意保持 seed 一致。
由于--output_dir同时是模型目录,且评估模式不触发"目录非空"校验(该校验仅在do_train时生效,见 run_hans.py),直接复用模型目录输出是安全的。
数据加载与特征化细节
评估数据由HansDataset加载(utils_hans.py),关键逻辑:
- 缓存:特征会被缓存为
cached_dev_<Tokenizer类名>_<max_seq_length>_hans文件,使用FileLock保证分布式下仅单进程构建、其余进程复用缓存;可用--overwrite_cache强制重建; - RoBERTa 标签修正:对 RoBERTa / XLM-R / BART 系列,源码会交换 label 1 与 label 2(
# HACK(label indices are swapped in RoBERTa pretrained model),见 utils_hans.py); - 标签体系:
HansProcessor.get_labels()返回["contradiction", "entailment", "neutral"],其中 HANS 评估将contradiction与neutral归并为 non-entailment(label 0),entailment为 label 1(见 utils_hans.py); - pairID 保留:TSV 中第 8 列是样例编号,前缀
ex会被剥离并转为整数,作为预测结果与黄金标签对齐的键(见 utils_hans.py)。
预测输出与结果文件
评估完成后,trainer.predict(eval_dataset)得到 logits,经np.argmax(..., axis=1)取预测类别,随后写入$MODEL_PATH/hans_predictions.txt(见 run_hans.py),格式为:
pairID,gold_label ex1,entailment ex2,contradiction ...随后使用 HANS 数据集官方提供的评分脚本hans/evaluate_heur_output.py(需从 HANS 仓库获取)对该文件进行评估,即:
python hans/evaluate_heur_output.py --output_dir $MODEL_PATH或按该脚本的接口传入hans_predictions.txt路径与评估集路径。
示例结果解读:BERT-base 的脆弱性
README 给出了一个参考结果:使用 batch size 8、随机种子 42 在 MNLI 上训练的 BERT-base 模型,在 HANS 上的表现如下:
Heuristic entailed results: lexical_overlap: 0.9702 subsequence: 0.9942 constituent: 0.9962 Heuristic non-entailed results: lexical_overlap: 0.199 subsequence: 0.0396 constituent: 0.118这是对抗性评估最有说服力的证据:
- entailed 准确率极高(0.97~0.99):模型面对真蕴含样例时几乎全对,说明它非常擅长"找证据";
- non-entailed 准确率极低(0.04~0.20):当样例满足启发式特征但语义上并不蕴含时,模型几乎全部误判为蕴含。
两者之间巨大的落差说明:该模型在 MNLI 上虽表现良好,却严重依赖表层启发式线索而非真正的语义推理,是典型的"表面线索投机者"。若你的模型在 HANS 上 non-entailed 准确率明显更高,说明其推理能力更稳健。需要强调的是,该结果是特定配置(batch size 8、seed 42)下的参考值,并非所有 BERT-base 模型的普适结论,不同训练配置会得到不同数字。
进阶扩展:结合评估脚本进行分布外诊断
run_hans.py还支持训练模式(--do_train),可在 HANS 训练集上继续微调并保存模型与 tokenizer(run_hans.py)。常见进阶用法包括:
- 多模型对比:对 BERT、RoBERTa、XLNet 等不同架构分别运行
run_hans.py --do_eval,对比各类启发式的 non-entailed 准确率,定位最稳健的架构; - 训练干预实验:在 NLI 训练中引入对抗样本、数据增强或去偏正则,再回到 HANS 验证改进效果;
- 参数敏感性:调整
--max_seq_length(默认 128,HANS 样例普遍较短,128 足够)、--per_device_eval_batch_size、--seed,观察结果稳定性; - 与 GLUE 指标对照:将 MNLI dev 准确率与 HANS 得分对照,展示"标准评测高分 ≠ 鲁棒推理"的差异。
小结
本文完整梳理了基于 HANS 的 NLI 对抗性评估流程:获取数据集 → 用run_glue.py训练 NLI 模型 → 运行run_hans.py --do_eval生成hans_predictions.txt→ 用 HANS 官方evaluate_heur_output.py按三类启发式统计 entailed / non-entailed 准确率。源码层面的关键实现(标签修正、pairID 对齐、缓存与多进程锁、RoBERTa 标签交换)均在 run_hans.py 与 utils_hans.py 中得到印证。对抗性评估是检验 NLI 模型真实推理能力、避免"高分低能"的重要工具,建议将其纳入模型发布的常规评测流程。
- 推理引擎
- 大模型
【免费下载链接】FlexGen
Running large language models on a single GPU for throughput-oriented scenarios.
相关推荐
ParlAI Bot Adversarial Dialogue 任务实战:基于冒犯性标注的对抗性对话安全数据集与评估体系
ParlAI Bot Adversarial Dialogue 任务实战:基于冒犯性标注的对抗性对话安全数据集与评估体系 导读 Bot Adversarial
NLP人工智能深度学习如何在Elm项目中快速集成elm-charts?5分钟上手教程
如何在Elm项目中快速集成elm charts?5分钟上手教程 想要在Elm应用中快速创建漂亮的SVG图表吗?elm charts是你的完美选择!这个强大的El
人工智能NLPEmbedding微调机器学习《开源大模型食用指南》实战:基于 transformers 与 peft 对 Phi-4 进行 LoRA 微调
《开源大模型食用指南》实战:基于 transformers 与 peft 对 Phi 4 进行 LoRA 微调 Phi 4 是微软开源的 14B 参数级大语言模
教程大模型本地部署微调
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考