(New)进阶任务:模型可解释性-实例证据分析
任务简介
模型的预测一般情况下是黑盒的,我们不知道模型为什么预测出这个结果,所以我们需要可信分析的输出结果帮助用户理解模型做出这种判断的机制(模型可解释性),诊断模型的问题所在并提出优化方案(可信增强工具)。实例级证据分析旨在从训练数据中找出对当前预测起重要作用的若干条实例数据。开发者基于实例级证据可对训练数据中的问题进行分析,如识别训练集中的脏数据、识别数据稀疏等。
快速开始
代码结构
任务位于/wenxin_appzoo/tasks/text_classification目录下,是分类任务的一个进阶使用,目录结构如下:
.
├── data
│ ├── analysis_data ## 可信分析(实例分析、特征分析)的demo数据
│ │ ├── example_analysis ## 实例分析
│ │ │ └── demo.txt
│ │ └── feature_analysis ## 特征分析
│ │ └── demo.txt
......
│ ├── dict
│ │ ├── sentencepiece.bpe.model
│ │ └── vocab.txt
......
│ ├── predict_data
│ │ └── infer.txt
│ ├── test_data
│ │ └── test.txt
│ ├── train_data
│ │ └── train.txt
......
├── data_set_reader
│ ......
├── ernie_doc_infer_server.py
├── ernie_run_infer_server.py
├── examples
│ ├── cls_ernie_fc_ch_data_distribution_correct.json ## 获取数据集样本分布情况任务对应的配置文件
│ ├── cls_ernie_fc_ch_example_analysis.json ## 实例分析任务的配置文件
│ ├── cls_ernie_fc_ch_feature_analysis.json ## 特征分析任务的配置文件
│ ├── cls_ernie_fc_ch_find_dirty_data.json ## 筛选脏数据任务的配置文件
│ ├── cls_ernie_fc_ch_infer.json
│ ├── cls_ernie_fc_ch_infer_with_active_learning.json
│ ├── cls_ernie_fc_ch_infer_with_iflytek.json
│ ├── cls_ernie_fc_ch.json
│ ......
├── find_dirty_data.py ## 基于实例分析的结果查找脏数据的脚本
├── inference
│ ......
├── model
│ ├── base_cls.py
│ ├── ernie_classification.py
│ ......
├── reader
│ ......
├── run_balance_data.py ## 均衡训练集数据分布的脚本
├── run_data_distribution_correct.py ## 获取数据集样本分布情况的脚本
├── run_example_analysis.py ## 运行实例分析的启动脚本
├── run_features_analysis.py ## 运行特征分析的启动脚本
├── ......
├── trainer
│ ......
└── trust_analysis
├── gradient_similarity_wenxin.py ## 基于梯度相似度的实例分析脚本
├── integrated_gradients_wenxin.py ## 基于积分梯度的特征分析脚本
└── respresenter_point_wenxin.py ## 基于表示点方法的实例分析脚本
准备工作
在进行模型实例分析之前,首先需要训练出一个可预测的模型,本次文心套件中仅提供在文本分类任务上的实例分析功能,所以用户首先需要在分类任务中训练出一个模型,这里以ERNIE 3.0 Base模型举例。
模型准备
预训练模型均存放于wenxin_appzoo/wenxin_appzoo/models_hub文件夹下,进入文件夹下,执行sh download_ernie_3.0_base_ch.sh 即可下载ERNIE 3.0 Base模型的模型参数、字典、网络配置文件。
训练准备
数据准备可以参考:V2.1.0准备工作 训练配置文件如下(examples/cls_ernie_fc_ch.json):
{
"dataset_reader": {
"train_reader": {
"name": "train_reader", ## 训练、验证、测试各自基于不同的数据集,数据格式也可能不一样,可以在json中配置不同的reader,此处为训练集的reader。
"type": "BasicDataSetReader", ## 采用BasicDataSetReader,其封装了常见的读取tsv、txt文件、组batch等操作。
"fields": [## 域(field)是文心的高阶封装,对于同一个样本存在不同域的时候,不同域有单独的数据类型(文本、数值、整型、浮点型)、单独的词表(vocabulary)等,可以根据不同域进行语义表示,如文本转id等操作,field_reader是实现这些操作的类。
{
"name": "text_a", ## 文本分类任务的第一个特征域,命名为"text_a"。
"data_type": "string",
"reader": {
"type": "ErnieTextFieldReader"
},
"tokenizer": {
"type": "FullTokenizer", ## 指定text_a分词器,除ernie-tiny模型之外,其余基本上都固定为FullTokenizer分词器。
"split_char": " ",
"unk_token": "[UNK]"
},
"need_convert": true,
"vocab_path": "../../models_hub/ernie_3.0_base_ch_dir/vocab.txt", ## 词表地址
"max_seq_len": 512,
"truncation_type": 0,
"padding_id": 0
},
{
"name": "label",
"data_type": "int",
"reader": {
"type": "ScalarFieldReader"
},
"tokenizer": null,
"need_convert": false,
"vocab_path": "",
"max_seq_len": 1,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
}
],
"config": {
"data_path": "./data/train_data", ## 数据路径。
"shuffle": true,
"batch_size": 8,
"epoch": 10,
"sampling_rate": 1.0,
"need_data_distribute": true,
"need_generate_examples": false
}
},
"test_reader": { ## 此处为测试集的reader。
"name": "test_reader",
"type": "BasicDataSetReader",
"fields": [
{
"name": "text_a",
"data_type": "string",
"reader": {
"type": "ErnieTextFieldReader"
},
"tokenizer": {
"type": "FullTokenizer",
"split_char": " ",
"unk_token": "[UNK]"
},
"need_convert": true,
"vocab_path": "../../models_hub/ernie_3.0_base_ch_dir/vocab.txt",
"max_seq_len": 512,
"truncation_type": 0,
"padding_id": 0
},
{
"name": "label",
"data_type": "int",
"need_convert": false,
"reader": {
"type": "ScalarFieldReader"
},
"tokenizer": null,
"vocab_path": "",
"max_seq_len": 1,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
}
],
"config": {
"data_path": "./data/test_data",
"shuffle": false,
"batch_size": 8,
"epoch": 1,
"sampling_rate": 1.0,
"need_data_distribute": false,
"need_generate_examples": false
}
}
},
"model": {
"type": "ErnieClassification",
"is_dygraph": 1,
"optimization": { ## 优化器设置,文心ERNIE推荐的默认设置。
"learning_rate": 2e-05,
"use_lr_decay": true,
"warmup_steps": 0,
"warmup_proportion": 0.1,
"weight_decay": 0.01,
"use_dynamic_loss_scaling": false,
"init_loss_scaling": 128,
"incr_every_n_steps": 100,
"decr_every_n_nan_or_inf": 2,
"incr_ratio": 2.0,
"decr_ratio": 0.8
},
"embedding": {
"config_path": "../../models_hub/ernie_3.0_base_ch_dir/ernie_config.json"
},
"num_labels": 2
},
"trainer": {
"type": "CustomDynamicTrainer",
"PADDLE_PLACE_TYPE": "gpu",
"PADDLE_IS_FLEET": 0, ## 是否启用fleetrun运行,多卡运行时必须使用fleetrun,单卡时即可以使用fleetrun启动也可以直接python启动
"train_log_step": 10,
"use_amp": true,
"is_eval_dev": 0,
"is_eval_test": 1,
"eval_step": 100,
"save_model_step": 200,
"load_parameters": "",
"load_checkpoint": "",
"pre_train_model": [
{
"name": "ernie_3.0_base_ch",
"params_path": "../../models_hub/ernie_3.0_base_ch_dir/params"
}
],
"output_path": "./output/cls_ernie_3.0_base_fc_ch_dy",
"extra_param": {
"meta":{
"job_type": "text_classification"
}
}
}
}
开始训练
# 进入指定任务的目录
cd wenxin_appzoo/wenxin_appzoo/tasks/text_classification
# 单卡训练,如果fleetrun设置为0,则使用下面命令
python ./run_trainer.py --param_path "./examples/cls_ernie_fc_ch.json"
# 单卡训练,如果fleetrun设置为1,则使用下面的命令
fleetrun --log_dir log ./run_trainer.py --param_path "./examples/cls_ernie_fc_ch.json" 1>log/lanch.log 2>&1
# 多卡训练,fleetrun必须设置为1,使用下面的命令
fleetrun --log_dir log ./run_trainer.py --param_path "./examples/cls_ernie_fc_ch.json" 1>log/lanch.log 2>&1
- 通过上述脚本调用json文件开启训练
- 训练阶段日志文件于log文件夹下,workerlog.N 保存了第N张卡的log日志内容,如遇到程序报错可以通过查看不同卡的workerlog.N定位到有效的报错信息。
- 训练模型保存于./output/cls_ernie_3.0_base_fc_ch_dy文件夹下,保存好的模型,我们选择checkpoints文件进行下一步的操作。
开始实例分析
实例分析是对训练集数据和测试集数据进行分析,逐个对测试集中的数据进行评估分析,选出训练集中哪些样本对当前测试集数据的结果是正向支持,哪些是负向支持。所需要的数据格式如下所示:
选择珠江花园的原因就是方便,有电动扶梯直接到达海边,周围餐馆、食廊、商场、超市、摊位一应俱全。酒店装修一般,但还算整洁。 1
15.4寸笔记本的键盘确实爽,基本跟台式机差不多了,蛮喜欢数字小键盘,输数字特方便,样子也很美观,做工也相当不错 1
房间太小。其他的都一般。。。。。。。。。 0
运行脚本配置如下(examples/cls_ernie_fc_ch_example_analysis.json)
{
"dataset_reader": {
"train_reader": {
"name": "train_reader", ## 配置训练集
"type": "BasicDataSetReader",
"fields": [
{
"name": "text_a",
"data_type": "string",
"reader": {
"type": "ErnieTextFieldReader"
},
"tokenizer": {
"type": "FullTokenizer",
"split_char": " ",
"unk_token": "[UNK]"
},
"need_convert": true,
"vocab_path": "../../models_hub/ernie_3.0_base_ch_dir/vocab.txt",
"max_seq_len": 512,
"truncation_type": 0,
"padding_id": 0
},
{
"name": "label",
"data_type": "int",
"reader": {
"type": "ScalarFieldReader"
},
"tokenizer": null,
"need_convert": false,
"vocab_path": "",
"max_seq_len": 1,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
}
],
"config": {
"data_path": "./data/train_data",
"shuffle": false, ## shuffle必须是false
"batch_size": 1, ## batch_size必须是1
"epoch": 1, ## 必须是1
"sampling_rate": 1.0,
"need_data_distribute": false,
"need_generate_examples": false ## 必须是false
}
},
"test_reader": { ## 配置测试集
"name": "test_reader",
"type": "BasicDataSetReader",
"fields": [
{
"name": "text_a",
"data_type": "string",
"reader": {
"type": "ErnieTextFieldReader"
},
"tokenizer": {
"type": "FullTokenizer",
"split_char": " ",
"unk_token": "[UNK]"
},
"need_convert": true,
"vocab_path": "../../models_hub/ernie_3.0_base_ch_dir/vocab.txt",
"max_seq_len": 512,
"truncation_type": 0,
"padding_id": 0
},
{
"name": "label",
"data_type": "int",
"need_convert": false,
"reader": {
"type": "ScalarFieldReader"
},
"tokenizer": null,
"vocab_path": "",
"max_seq_len": 1,
"truncation_type": 0,
"padding_id": 0,
"embedding": null
}
],
"config": {
"data_path": "./data/analysis_data/example_analysis",
"shuffle": false, ## shuffle必须是false
"batch_size": 1, ## batch_size必须是1
"epoch": 1, ## 必须是1
"sampling_rate": 1.0,
"need_data_distribute": false, ## 必须是false
"need_generate_examples": true ## 必须是true
}
}
},
"model": {
"type": "ErnieClassification",
"is_dygraph": 1,
"optimization": {
"learning_rate": 2e-05,
"use_lr_decay": false, ## 必须是false
"warmup_steps": 0,
"warmup_proportion": 0.1,
"weight_decay": 0.01,
"use_dynamic_loss_scaling": false,
"init_loss_scaling": 128,
"incr_every_n_steps": 100,
"decr_every_n_nan_or_inf": 2,
"incr_ratio": 2.0,
"decr_ratio": 0.8
},
"embedding": {
"config_path": "../../models_hub/ernie_3.0_base_ch_dir/ernie_config.json"
},
"num_labels": 2
},
"trainer": {
"type": "CustomDynamicTrainer",
"PADDLE_PLACE_TYPE": "gpu",
"PADDLE_IS_FLEET": 0,
"train_log_step": 10,
"use_amp": true,
"is_eval_dev": 0,
"is_eval_test": 1,
"eval_step": 100,
"save_model_step": 200,
"load_parameters": "./output/cls_ernie_3.0_base_fc_ch_dy/save_checkpoints/checkpoints_step_501/", ## 上一部训练出的模型checkpoints文件
"load_checkpoint": "",
"pre_train_model": [],
"output_path": "./output/analysis_result.txt", ## 分析结果最终保存的地址
"interpret_type": "GradientSimilarity", ## 采用哪种方式进行分析,可选:RepresenterPoint(表示点方法)、GradientSimilarity(基于梯度相似度的方法)
"extra_param": {
"meta":{
"job_type": "text_classification"
}
}
}
}
开始运行:
# 使用当前目录下的run_example_analysis.py 脚本进行实例分析
python run_example_analysis.py --param_path=./examples/cls_ernie_fc_ch_example_analysis.json
# 运行完成后,结果将保存在./output/analysis_result.txt中。
分析结果如下所示: 第一行为测试集样本,行末最后一列数字为模型预测结果。examples with positive influence表示对当前结果起到正向影响的训练集中的top3 样本,examples with positive influence表示对当前结果起到负向影响的训练集中的top3 样本。
text:这个 宾馆 比较 陈旧 了 , 特价 的 房间 也 很一般 。 总体来说 一般 1 1
examples with positive influence
Example(text_a='看到 很多 评价 都 很高 , 结果 期待 也 高 了 些 , 没有 想象 的 好看 , 外观 一般 , 缺乏 质感 , 毕竟 这个 价位 嘛 。', label='1') 0.9305076599121094
Example(text_a='服务 : 整体 勉强 有 4星级 水平 问题 : 硬件 水平 偏低 , 房间 隔音 效果 差 , 门 薄 墙 薄 , 结账 时间 偏 长 , 早餐 质量 偏低 , 不过 在 该 地段 , 也 没有 比 这
家 更好 地 宾馆 供选择 .', label='1') 0.9046429991722107
Example(text_a='总体 感觉 不错 , 美中不足 的 是 房 与 房 之间 隔音 效果 不太 好 , 还有 房价 感觉 稍 高 。', label='1') 0.8945478796958923
examples with negative influence
Example(text_a='第一次 在 当当 网上 买 书 , 很方便 , 很 实惠 ! 孩子 一 收到 书 , 就 爱不释手 地 读 起来 , 是 一套 好书 , 在 开心 快乐 地 儿童 故事 中 让 孩子 学会 做 一
个 有 个性 、 有 爱心 、 乐于助人 的 孩子 。', label='0') 0.9305076599121094
Example(text_a='卡梅拉 是 之 勇敢 的 小鸡 简单 而 执着我喜欢 哦 ~ 同事 的 小 宝宝 也 很喜欢 ~ 还有 我 将 给 我 男朋友 听 的 也 很 投入 ~', label='0') 0.9046429991722107
Example(text_a='这本书 虽然 内容 不 多 , 但是 插图 很大 , 很 生动 和 形象 , 里面 的 故事 都是 小孩子 碰到 过 的 事情 , 并且 很 有 启发性 , 我 女儿 看 了 以后 很喜欢 , 而且 碰到 术 中 类似 的 事情 , 她 会 说 “ 大卫 , 不 可以 ” , 呵呵 , 看来 是 受到 潜移默化 的 影响 了 , 总的来说 , 个人 感觉 这本书 不错 , 难怪 是 获 过 大奖 的 书 。', label='0') 0.8945478796958923
text:怀着 十分 激动 的 心情 放映 , 可是 看着 看着 发现 , 在 放映 完毕 后 , 出现 一集米 老鼠 的 动画片 ! 开始 还 怀疑 是不是 赠送 的 个别 现象 , 可是 后来 发现 每张 DVD 后面 都 有 ! 真 不知道 生产商 怎么 想 的 , 我 想 看 的 是 猫 和 老鼠 , 不是 米老鼠 ! 如果 厂家 是 想 赠送 的 话 , 那 就 全套 米老鼠 和 唐老鸭 都 赠送 , 只 在 每张 DVD 后面 添加 一集 算什么 ? ? 简直 是 画蛇添足 ! ! 0 0
examples with positive influence
Example(text_a='< 色 , 戒 > 是 一本 挂羊头 卖 狗肉 的 书 , 本来 买 回家 准备 过 足读 小说 瘾 , 结果 是 一本 短篇集 . 网上 购物 有 缺陷 , 因为 我们 不能 动手 去 翻 要 买 的 >书 , 买者 应该 对其 进行 必要 的 , 一目了然 的 说明 , 哪 怕 加 一句 ? 短篇集 ? , 读者 也 不会 对 到手 的 书 如此 失望 , 啊 . . . . . . . 受骗 了', label='0') 0.9882171750068665
Example(text_a='这个 宾馆 太 差 了 , 厕所 感觉 不 消毒 , 而且 房间 里面 任何 吃 的 东西 都 没有 , 连 水 都 没有 , 电视 而且 都 不 清楚 , 门 还 不用 , 马桶 的 水 要 等 半个小时 在 按 才 可以 下去 , 如果 不是 车 坏 了 别 的 酒店 都 满 了 , 我 是 实在 不 想 选 这个 酒店 , 宾馆 服务 人员 态度 不好 , 这', label='0') 0.9857099056243896
Example(text_a='给 朋友 订 的 , 原来 计划 2天 , 结果 入住 遭遇 使得 第二天 改 到 凯悦 了 , 1 ) 送 朋友 入住 , 所有 的 车位 都 上锁 , 只 好找 别 的 收费 的 , 其实 在 同一 个
院子 里 2 ) 办理 入住 时 竟 说 没 查 到 有 订房 , 不知 是 携程 还是 酒店 的 原因 3 ) 房间 的 床上 竟然 有 一条 很 长 的 血迹 , 恶心 4 ) 所以 要求 换 一个 房间 , 被 很
不 客气 的 告知 只此 一间 , 感觉 给 我 房间 是 给 我 很大 的 恩惠 和 施舍 了 5 ) 竟然 没有 热水 洗澡 , 朋友 强烈 要求 以后 不要 再 订 这家 酒店 了', label='0') 0.9856864213943481
examples with negative influence
Example(text_a='另外 说一句 , 书 中 的 故事 也 适合 给 低 段 儿童 朗读', label='1') 0.9882171750068665
Example(text_a='入住 的 时候 礼宾 在 哪里 ? 房间 里 的 花盆 特别 象 90年代初期 的 田园 花盆 , 极为 难看 . 更可怕 的 是 入住 的 时候 门口 不管 客人 , 照常 做大 范围 清洁 .', label='1') 0.9857099056243896
Example(text_a='今天 才 知道 这 书 还有 第6卷 , 真 有点 郁闷 : 为什么 同一 套书 有 两种 版本 呢 ? 当当网 是不是 该 跟 出版社 商量 商量 , 单独 出 个 第6卷 , 让 我们 的 孩子 >不会 有所 遗憾 。', label='1') 0.9856864213943481
text:还 稍微 重 了 点 , 可能 是 硬盘 大 的 原故 , 还要 再 轻 半斤 就好 了 。 其他 要 进一步 验证 。 贴 的 几种 膜 气泡 较多 , 用 不 了 多久 就要 更换 了 , 屏幕 膜 稍 好 点 , 但 比 没有 要强 多 了 。 建议 配 赠 几张 膜 让 用 用户 自己 贴 。 0 0
examples with positive influence
Example(text_a='客观 来说 , 只是 自身 的 一点 经验 加上 收集 的 功夫 堆积 出来 的 . 专业性 和 系统性 不够 , 里面 的 所谓 经验 方法 还 需要 进一步 考证 .', label='0') 0.9857235550880432