2021 CCF BDCI 全国信息检索挑战杯(CCIR-Cup)智能人机交互自然语言理解赛道第二名参赛解决方案

Overview

2021 CCF BDCI 全国信息检索挑战杯(CCIR-Cup) 智能人机交互自然语言理解赛道第二名解决方案

比赛网址: CCIR-Cup-智能人机交互自然语言理解

1.依赖环境:

  • python==3.8
  • torch==1.7.1+cu110
  • numpy==1.19.2
  • transformers==4.5.1
  • scikit_learn==1.0
  • seqeval==1.2.2
  • tqdm==4.50.2
  • CUDA==11.0

2.解决方案

1.数据预处理部分

1.首先对任务进行明确,赛题任务是意图识别与槽填充,在观察训练数据之后,发现槽填充任务可分解为两类任务来做:一类是标准槽填充任务,即槽值可在当前对话句子当中完全匹配到;另一类是非标准槽填充(自拟的名字),即槽值不可在当前对话句子中找到或者完全匹配。对于非标准槽填充任务,把它当作另一种分类任务来解决。所以,我就把比赛任务当作三个子任务来进行,分别是意图识别、标准槽填充和非标准槽填充(分类任务)。

2.对于标准槽填充而言,有些槽标签在大部分训练数据中都是可完全匹配的,但是仍然存在少量不完全匹配槽标签,例如:句中出现的是港片、韩剧、美剧、内地、英文、中文等词汇时,对应的槽值标注却是香港、韩国、美国、大陆、英语、华语等。对于这一类数据,若将其当作非标准槽填充任务显得不太合理,解决方案是:提前准备好一个特殊词汇的映射字典 region_dic.json,在处理训练数据的时候,如果碰到了有的槽值出现在特殊词汇字典中,则对其进行槽标注的时候需要先进行转换。

3.然后用 ernie 的 Tokenizer 将对话句子按字切分,可能存在 ##后缀 和 [UNK] 的情况,将切分好的句子作为原始输入,对于标准槽填充任务,按 BIO 的方式进行标注。观察训练数据后发现,标准槽填充任务中存在少量的嵌套命名实体,例如:

{
"NLU07301": {
    "text": "西安WE比赛的视频帮我找一下",
    "intent": "Video-Play",
    "slots": {
      "name": "西安WE比赛的视频",
      "region": "西安"
    }
  }
}

对于这种少量嵌套的例子,我并没有涉及特殊的网络结构来解决,而是使用了一种简单的方式:首先将每条训练数据的 slots 下的所有槽值的长度按从大到小排列,然后在对其进行序列标注的时候按槽的先后顺序进行标注,比如上面的例子的标注方式为:

首先是 "name" 这个槽标签:

B-name I-name I-name I-name I-name I-name I-name I-name I-name O O O O O

然后是 "region" 这个槽标签:

B-region I-region I-name I-name I-name I-name I-name I-name I-name O O O O O

"region" 标注完成后将 B-name I-name 这两个tag给覆盖掉了。

最后,对于这种嵌套实体,模型就按照这种标注方式去训练;在解码的时候,按照一定的匹配规则识别出"name" 和 "region"这两个槽标签,后面的实验中表明使用这种标注方式能够有效的识别出测试集数据中存在的嵌套实体。

4.手动纠正部分,训练数据中存在一些数据有着明显的标注错误。例如:NLU00400 的 "artist": "银临,河图",正确的标注应该为 "artist": ["银临",""河图"];"query_type":"汽车票查询" 和 "query_type":"汽车票",这两个明显就是一样的,故将其统一,再比如:

{
  "NLU04386": {
    "text": "明天早上7:20你会不会通知我带洗衣液",
    "intent": "Alarm-Update",
    "slots": {
      "datetime_date": "明天",
      "notes": "带洗衣液",
      "datetime_time": "早上7"
    }
  }
}

"datetime_time":"早上7" 标注错误,正确标注应该为"datetime_time": "早上7:20",且类似这种的错误在"Alarm-Update"这个意图中大量存在。如果不进行纠正,则对模型的训练会造成很大的影响。

5.对于非标准槽填充部分,统计出了四种槽标签:command、index、play_mode 和 query_type,将这四类槽标签的槽值当作类别,一共有29种类别,如:

音量调节
查询状态
汽车票查询
穿衣指数
紫外线指数
...
None

None表示不存在这一类值。然后对其进行类似意图识别那样做分类。

6.对于域外检测任务:在 a 榜阶段,我在 LCQMC 数据集中选择了1000条左右数据作为 Other 数据的来源;在 b 榜阶段,我把 a 榜阶段预测出的 intent 为 Other 的数据加上 LCQMC数据集中选择出500条数据一起作为训练集的 intent 为 Other 类进行训练。

7.对于小样本检测任务:发现意图为 Audio-Play 和 TVProgram_Play 的这两个意图是小样本数据,在原始训练集中分别为50条。解决方法:对小样本意图数据进行数据增强,使其数量接近基本任务数据的1000条左右,具体做法:分别对 Audio-Play 和TVProgram_Play这两个意图进行增强,举例来说,对于 Audio-Play 而言,其可能的槽标签有

8.在模型输出后,进行一步后处理操作:对模型预测结果进行纠正,即把不属于某一类intent的槽值删除,首先统计出训练数据中的意图和槽标签之间的关系:

{
  "FilmTele-Play": ["name", "tag", "artist", "region", "play_setting", "age"],
  "Audio-Play": ["language", "artist", "tag", "name", "play_setting"],
  "Radio-Listen": ["name", "channel", "frequency", "artist"],
  "TVProgram-Play": ["name", "channel", "datetime_date", "datetime_time"],
  "Travel-Query": ["query_type", "datetime_date", "departure", "destination", "datetime_time"],
  "Music-Play": ["language", "artist", "album", "instrument", "song", "play_mode", "age"],
  "HomeAppliance-Control": ["command", "appliance", "details"],
  "Calendar-Query": ["datetime_date"],
  "Alarm-Update": ["notes", "datetime_date", "datetime_time"],
  "Video-Play": ["name", "datetime_date", "region", "datetime_time"],
  "Weather-Query": ["datetime_date", "type", "city", "index", "datetime_time"],
  "Other": []
}

就可以发现意图只能包含特定的标签,某些标签不可能出现在其它意图中
举例来说:比如我在一条测试数据中预测出其intent = FilmTele-Play, 然后其槽值预测中出现了"notes"这个槽标签,这与我之前统计的哪些槽标签只出现在哪些意图中不符合(即训练数据中FileTele-Play这个意图不可能出现"notes"这个槽标签),所以该函数就把"notes"这个槽位和槽值删除掉。

"Audio-Play": ["language", "artist", "tag", "name", "play_setting"], 一共五类,分别在训练数据中统计出各个槽标签可能出现的槽值有哪些,比如 "language": ["日语", "英语", "法语", "俄语", "西班牙语", "华语", "韩语", "德语", "藏语"] ,language 有这些可选项,当然也可以自己随便添加几个合适的选项。得到了一个这种字典后,对于每一条原训练数据中意图为 Audio-Play 的数据进行扩充,每一条扩充20条新数据,具体扩充方式:对于原数据而言,如果某一个槽标签出现,则在该槽标签对应的标签候选项中随机选择一个替换它,对原数据存在的每一个槽标签都进行这种操作,这样就增加了一条”新数据“,经过实验验证,小样本数据扩充前后,线上得分提升了两个点,证明这种方式还是效果不错的。
9.在a榜阶段,训练数据包括三部分:原始训练数据 + 小样本意图扩充数据 + LCQMC数据集(1000条)当作域外数据;在b榜阶段,训练数据除了和a榜相同的部分外,还把模型在a榜测试集上的输出当作a榜测试集的标注,再将这些数据也添加到训练数据中进行训练,然后再去预测b榜测试集,所以b榜阶段的最终使用的训练集有13119条。

2.模型算法部分

此次比赛我一共使用了三个模型进行训练,最后的结果 result.json 由三个模型的投票表决产生。

1.JointErine 模型

思路参照:BERT for Joint Intent Classification and Slot Filling

预训练模型并没有使用中文版 bert base,而是使用的是百度的中文版 ernie-1.0 base,三个任务进行联合训练。意图识别和非标准槽填充使用 erine 模型的输出分别连接一个全连接层进行分类;标准槽填充得到 erine 的输出后,再将其输入到 CRF 层,erine预训练模型与CRF层采用不同的学习率,erine 的学习率是5e-5,CRF层的学习率是5e-2

2.InteractModel_1 模型

思路参照:A CO-INTERACTIVE TRANSFORMER FOR JOINT SLOT FILLING AND INTENT DETECTION

仍然是三个任务联合训练,不同的是,意图识别和标准槽填充部分进行了一层交互,非标准槽填充未与上述二个任务进行交互,而是把预训练模型的输出 pooled_output 直接输入到全连接层中进行分类。

交互层部分:

首先使用中文版 ernie-1.0 base 预训练模型作为主体部分: $$ 对于输入的序列{x_1,x_2,...,x_n}(n是token的数量),输入到中文版ernie-1.0模型之后得到输出H = {h_1, h_2, ..., h_n} $$ 然后是意图和标准槽填充的交互层,这个模型中使用了一层交互层:

标签注意力层

image-20210929212611984

协同交互注意力层

image-20210929212740433

前馈神经网络层

image-20210929212830068

解码器层部分

image-20210929213002909

3.InteractModel_3模型

InteractModel_3 模型结构类似于上述讲解的 InteractModel_1 ,唯一的区别就是 InteractModel_3 的意图识别和标准槽填充部分使用了三层的交互。
镜像复现说明请查看 ccir/image/README.md

3.项目目录结构

ccir
|-- data                                                —— 数据文件夹
|   |-- code                                            —— 包含所有代码文件夹
|   |   |-- __init__.py
|   |   |-- model                                       —— 与网络模型相关文件夹
|   |   |   |-- __init__.py
|   |   |   |-- InteractModel_1.py                      —— InteractModel_1 网络模型
|   |   |   |-- InteractModel_3.py                      —— InteractModel_3 网络模型
|   |   |   |-- JointBertModel.py                       —— JointBertModel 网络模型
|   |   |   |-- __pycache__
|   |   |   |   |-- __init__.cpython-38.pyc
|   |   |   |   |-- InteractModel_1.cpython-38.pyc
|   |   |   |   |-- InteractModel_3.cpython-38.pyc
|   |   |   |   |-- JointBertModel.cpython-38.pyc
|   |   |   |   `-- torchcrf.cpython-38.pyc
|   |   |   `-- torchcrf.py                             —— CRF层网络模型
|   |   |-- predict                                     —— 包含推理代码的文件夹
|   |   |   |-- __init__.py     
|   |   |   |-- integration.py                          —— 负责将三个模型的结果进行投票输出成最后的结果result.json
|   |   |   |-- post_process.py                         —— 对模型的结果进行后处理的代码
|   |   |   |-- __pycache__
|   |   |   |   |-- __init__.cpython-38.pyc
|   |   |   |   |-- post_process.cpython-38.pyc
|   |   |   |   |-- test_dataset.cpython-38.pyc
|   |   |   |   `-- test_utils.cpython-38.pyc
|   |   |   |-- run_interact1.py                        —— 对线上训练的InteractModel_1模型进行推理
|   |   |   |-- run_interact3.py                        —— 对线上训练的InteractModel_3模型进行推理
|   |   |   |-- run_JointBert.py                        —— 对线上训练的JointBert模型进行推理
|   |   |   |-- run_trained_interact1.py                —— 对本地训练的InteractModel_1模型进行推理
|   |   |   |-- run_trained_interact3.py                —— 对本地训练的InteractModel_3模型进行推理
|   |   |   |-- run_trained_JointBert.py                —— 对本地训练的JointBert模型进行推理
|   |   |   |-- test_dataset.py                         —— 构建测试集dataset
|   |   |   `-- test_utils.py                           —— 测试集的工具类函数
|   |   |-- __pycache__
|   |   |   `-- __init__.cpython-38.pyc
|   |   |-- preprocess                                  —— 数据预处理代码
|   |   |   |-- __init__.py     
|   |   |   |-- analysis.py                             —— 分析训练数据,哪些意图包含哪些标签
|   |   |   |-- extend_audio_sample.py                  —— 用于扩充意图为”Audio-Play“的小样本数据
|   |   |   |-- extend_tv_sample.py                     —— 用于扩充意图为”TVProgram-Play“的小样本数据
|   |   |   |-- extract_intent_sample.py                —— 在训练数据中提取特定意图的数据
|   |   |   |-- generate_intent.py                      —— 对训练数据和验证集数据提取意图
|   |   |   |-- process_other.py                        —— 处理域外数据
|   |   |   |-- process_rawdata.py                      —— 处理原始训练数据和验证集数据
|   |   |   |-- rectify.py                              —— 对意图为”Alarm-Update“的训练数据进行纠正
|   |   |   |-- slot_sorted.py                          —— 对槽填充的标注按槽值从大到小进行排序
|   |   |   |-- split_train_dev.py                      —— 将原始训练数据按8: 2划分
|   |   `-- scripts
|   |       |-- build_vocab.py                          —— 构建词典,加载词汇表
|   |       |-- config_Interact1.py                     —— InteractModel_1的配置文件(参数设置)
|   |       |-- config_Interact3.py                     —— InteractModel_3的配置文件(参数设置)
|   |       |-- config_jointBert.py                     —— JointBert的配置文件(参数设置)
|   |       |-- dataset.py                              —— 构建训练集dataset
|   |       |-- __init__.py
|   |       |-- __pycache__
|   |       |   |-- build_vocab.cpython-38.pyc
|   |       |   |-- config_Interact1.cpython-38.pyc
|   |       |   |-- config_Interact3.cpython-38.pyc
|   |       |   |-- config_jointBert.cpython-38.pyc
|   |       |   |-- dataset.cpython-38.pyc
|   |       |   |-- __init__.cpython-38.pyc
|   |       |   `-- utils.cpython-38.pyc
|   |       |-- train_interact1.py                      —— InteractModel_1的主函数训练代码
|   |       |-- train_interact3.py                      —— InteractModel_3的主函数训练代码
|   |       |-- train_jointBert.py                      —— JointBert的主函数训练代码
|   |       `-- utils.py                                —— 训练阶段的工具类函数(train、valid等)
|   |-- __init__.py
|   |-- prediction_result                               —— 模型推理结果result.json的保存文件夹
|   |-- __pycache__
|   |   `-- __init__.cpython-38.pyc
|   |-- raw_data                                        —— 原始训练集文件夹
|   `-- user_data                                       —— 用户数据文件夹
|       |-- common_data                                 —— 训练和验证时使用的公共文件夹
|       |   |-- intent_label.txt                        —— 包含11类意图的txt文件
|       |   |-- intent_slot_mapping.json                —— 意图与槽标签对应关系的字典
|       |   |-- region_dic.json                         —— 用于帮助训练集槽标注的映射字典
|       |   |-- slot_label.txt                          —— 标准槽标签
|       |   `-- slot_none_vocab.txt                     —— 非标准槽标签
|       |-- dev_data
|       |   |-- dev_intent_label.txt                    —— 验证集数据的意图
|       |   |-- dev_seq_in.txt                          —— 验证集数据的原始句子分词输入
|       |   |-- dev_seq_out.txt                         —— 验证集数据的序列标注
|       |   `-- dev_slot_none.txt                       —— 验证集数据的非标准槽填充分类标签
|       |-- output_model                                —— 保存训练过程中间的模型文件夹
|       |   |-- InteractModel_1                         —— InteractModel_1文件夹(线上训练的模型保存在该文件夹下)
|       |   |   `-- trained_model                       —— 保存本地训练好的模型的文件夹
|       |   |       `-- Interact1_model_best.pth.tar    —— 本地训练好的InteractModel_1模型
|       |   |-- InteractModel_3                         —— InteractModel_3文件夹(线上训练的模型保存在该文件夹下)
|       |   |   `-- trained_model
|       |   |       `-- Interact3_model_best.pth.tar    —— 本地训练好的InteractModel_3模型
|       |   `-- JointBert                               —— JointBert文件夹(线上训练的模型保存在该文件夹下)
|       |       `-- trained_model
|       |           `-- bert_model_best.pth.tar         —— 本地训练好的JointBert模型
|       |-- pretrained_model                            —— 预训练模型文件夹
|       |   `-- ernie                                   —— ernie
|       |       |-- config.json
|       |       |-- pytorch_model.bin
|       |       |-- special_tokens_map.json
|       |       |-- tokenizer_config.json
|       |       `-- vocab.txt
|       |-- test_data                                   —— 测试集文件夹
|       |   |-- test_B_final_text.json                  —— 测试集原始json文件
|       |   `-- test_seq_in_B.txt                       —— 经过Tokenizer分词后的测试集文件
|       |-- tmp_result                                  —— 保存单个模型输出结果
|       `-- train_data                                  —— 训练集文件夹
|           |-- train_intent_label.txt                  —— 训练集数据的意图
|           |-- train_seq_in.txt                        —— 验证集数据的原始句子分词输入
|           |-- train_seq_out.txt                       —— 验证集数据的序列标注
|           `-- train_slot_none.txt                     —— 验证集数据的非标准槽填充分类标签
|-- image                                               —— 镜像相关文件夹
|   |-- readme_images                                   —— 存放赛题解决方案和算法介绍的README文档的图片
|   |-- ccir-image.tar                                  —— 镜像文件
|   |-- README.md                                       —— 关于复现具体操作的REDAME文档
|   |-- run_infer.sh                                    —— 使用本地训练的模型进行线上推理的脚本
|   `-- run.sh                                          —— 进行线上训练和推理的脚本
`-- README.md                                           —— 赛题整体的解决方案和算法介绍的README文档
Owner
JinXiang
自然语言处理
JinXiang
Anomaly detection analysis and labeling tool, specifically for multiple time series (one time series per category)

taganomaly Anomaly detection labeling tool, specifically for multiple time series (one time series per category). Taganomaly is a tool for creating la

Microsoft 272 Dec 17, 2022
Official implementation of CATs: Cost Aggregation Transformers for Visual Correspondence NeurIPS'21

CATs: Cost Aggregation Transformers for Visual Correspondence NeurIPS'21 For more information, check out the paper on [arXiv]. Training with different

Sunghwan Hong 120 Jan 04, 2023
Source code for our CVPR 2019 paper - PPGNet: Learning Point-Pair Graph for Line Segment Detection

PPGNet: Learning Point-Pair Graph for Line Segment Detection PyTorch implementation of our CVPR 2019 paper: PPGNet: Learning Point-Pair Graph for Line

SVIP Lab 170 Oct 25, 2022
Image Super-Resolution by Neural Texture Transfer

SRNTT: Image Super-Resolution by Neural Texture Transfer Tensorflow implementation of the paper Image Super-Resolution by Neural Texture Transfer acce

Zhifei Zhang 413 Nov 30, 2022
Semi-supervised Implicit Scene Completion from Sparse LiDAR

Semi-supervised Implicit Scene Completion from Sparse LiDAR Paper Created by Pengfei Li, Yongliang Shi, Tianyu Liu, Hao Zhao, Guyue Zhou and YA-QIN ZH

114 Nov 30, 2022
SPTAG: A library for fast approximate nearest neighbor search

SPTAG: A library for fast approximate nearest neighbor search SPTAG SPTAG (Space Partition Tree And Graph) is a library for large scale vector approxi

Microsoft 4.3k Jan 01, 2023
A method that utilized Generative Adversarial Network (GAN) to interpret the black-box deep image classifier models by PyTorch.

A method that utilized Generative Adversarial Network (GAN) to interpret the black-box deep image classifier models by PyTorch.

Yunxia Zhao 3 Dec 29, 2022
This repo is duplication of jwyang/faster-rcnn.pytorch

Faster RCNN Pytorch This repo is duplication of jwyang/faster-rcnn.pytorch C/C++ code are removed and easier to study. Python 3.8.5 Ubuntu 20.04.1 LTS

Kim Jihwan 1 Jan 14, 2022
[CVPR 2022 Oral] Rethinking Minimal Sufficient Representation in Contrastive Learning

Rethinking Minimal Sufficient Representation in Contrastive Learning PyTorch implementation of Rethinking Minimal Sufficient Representation in Contras

36 Nov 23, 2022
Codebase for testing whether hidden states of neural networks encode discrete structures.

structural-probes Codebase for testing whether hidden states of neural networks encode discrete structures. Based on the paper A Structural Probe for

John Hewitt 349 Dec 17, 2022
A simple, fast, and efficient object detector without FPN

You Only Look One-level Feature (YOLOF), CVPR2021 A simple, fast, and efficient object detector without FPN. This repo provides an implementation for

789 Jan 09, 2023
Fast SHAP value computation for interpreting tree-based models

FastTreeSHAP FastTreeSHAP package is built based on the paper Fast TreeSHAP: Accelerating SHAP Value Computation for Trees published in NeurIPS 2021 X

LinkedIn 369 Jan 04, 2023
Code for the Paper: Alexandra Lindt and Emiel Hoogeboom.

Discrete Denoising Flows This repository contains the code for the experiments presented in the paper Discrete Denoising Flows [1]. To give a short ov

Alexandra Lindt 3 Oct 09, 2022
Subdivision-based Mesh Convolutional Networks

Subdivision-based Mesh Convolutional Networks The official implementation of SubdivNet in our paper, Subdivion-based Mesh Convolutional Networks Requi

Zheng-Ning Liu 181 Dec 28, 2022
Implementation for NeurIPS 2021 Submission: SparseFed

READ THIS FIRST This repo is an anonymized version of an existing repository of GitHub, for the AIStats 2021 submission: SparseFed: Mitigating Model P

2 Jun 15, 2022
Reading Group @mila-iqia on Computational Optimal Transport for Machine Learning Applications

Computational Optimal Transport for Machine Learning Reading Group Over the last few years, optimal transport (OT) has quickly become a central topic

Ali Harakeh 11 Aug 26, 2022
the code used for the preprint Embedding-based Instance Segmentation of Microscopy Images.

EmbedSeg Introduction This repository hosts the version of the code used for the preprint Embedding-based Instance Segmentation of Microscopy Images.

JugLab 88 Dec 25, 2022
A Domain-Agnostic Benchmark for Self-Supervised Learning

DABS: A Domain Agnostic Benchmark for Self-Supervised Learning This repository contains the code for DABS, a benchmark for domain-agnostic self-superv

Alex Tamkin 81 Dec 09, 2022
DGCNN - Dynamic Graph CNN for Learning on Point Clouds

DGCNN is the author's re-implementation of Dynamic Graph CNN, which achieves state-of-the-art performance on point-cloud-related high-level tasks including category classification, semantic segmentat

Wang, Yue 1.3k Dec 26, 2022
Computer Vision is an elective course of MSAI, SCSE, NTU, Singapore

[AI6122] Computer Vision is an elective course of MSAI, SCSE, NTU, Singapore. The repository corresponds to the AI6122 of Semester 1, AY2021-2022, starting from 08/2021. The instructor of this course

HT. Li 5 Sep 12, 2022