# LICS2021 MRC
## 1. 项目&任务介绍
本项目基于官方给定的baseline([**DuReader-Checklist-BASELINE**](https://github.com/PaddlePaddle/Research/tree/master/NLP/DuReader-Checklist-BASELINE))进行二次改造,对整个代码框架做了简单的重构,对核心网络结构添加了注释,解耦了数据读取的模块,并添加了阈值确认的功能,一些小的细节也做了改进。最终的B榜的排名为31名。
本次任务为[2021语言与智能技术竞赛](http://lic2021.ccf.org.cn/):机器阅读理解任务,机器阅读理解 (Machine Reading Comprehension) 是指让机器阅读文本,然后回答和阅读内容相关的问题。
具体的,给定一个问题q,一段篇章p及其标题t,参赛系统需要根据篇章内容,判断该篇章p中是否包含给定问题的答案,如果是,则给出该问题的答案a;否则输出“无答案”。数据集中的每个样本,是一个四元组(q、p、t和a),例如:
```
问题 ( q ): 番石榴汁热量
篇章 ( p ): 番石榴性温,味甜、酸、涩…,最重要的是番石榴所含的脂肪热量较低,一个番石榴所含的脂肪约0.9克重或84卡路里。比起苹果,番石榴所含有的脂肪少38%,卡路里少42%。
标题 ( t ): 番石榴汁的热量 - 妈妈网百科
参考答案 ( a ): [‘一个番石榴所含的脂肪约0.9克重或84卡路里’]
问题 ( q ): 云南文山市多少人口?
篇章 ( p ): 云南省下辖8个市、8个少数民族自治州,面积39万平方千米,总人口4596万人,云南汉族人口为3062.9万人,占云南省总人口的66.63%…
标题 ( t ): 云南总人口数多少人,2019年云南人口数量统计(最新)
参考答案 ( a ): [‘无答案’]
```
## 2. 数据
### 2.1 数据概览
本次竞赛数据集共包含约8.6K问题,其中包括3K训练集,1.1K开发集和4.5K测试集。其中开发集包含1K领域内样本以及少量checklist样本。
在json中的存储逻辑如下,一个数据集文件,比如说train.json或者dev.json是一个大的json串,其中包含一个key,`data`,对应的value是一个list;list中的每个value均为一个dict(往往仅有一个value),dict中包含两个key,分别为`paragraphs`和`title`(这里的title往往为空字符串);在`paragraphs`中,是一个list,这里存放真正的数据样本,相当于路这个list的长度对应于数据量的多少;在list中的每个value均为一个dict,会包含如下三部分的key,
- context
对应的内容,往往是一个较长的字符串
- title
标题,即context的标题,往往是一个较短的字符串
- qas
对应的问&答内容,这部分是一个list,其中每个值代表一个问题的实体结构,用dict存储。
- id
问题的唯一id
- question
问题,字符串
- type
识别是否是in-domain或者为checklist的数据类型(名词、短语、推理等等),是一个可以枚举的字符串
- answers
答案,是一个list,其中每个值均代表一个答案的实体,用dict存储,包含两个key,
- text
回答内容,字符串
- answer_start
答案的起始位置(从零开始),如果为-1,则表示没有答案,即此时text的value必然为空字符串。
- is_impossible
True或者False,如果为True,表示存在答案(answers中至少有一个不为空的答案),如果为False,则answers中无答案。
> 该字段的解释目前是自己理解得到的,官网未给出明确的解释。
目前为止,已经梳理清楚整体的数据存储结构,为了加深理解这里将上面的字段含义做了一个类比,如下,
其中起始的key,`data`将他理解为**一本书**,显然一本书中会包含**多篇课文**,每篇课文均为独立的实体,所以其value应该是一个list;
接下来是为**课文**实体,往往一篇课文是有两部分组成,即一个标题`title`和多个段落`paragraphs`;
显然**一篇课文**中会包含**多个段落**,每个段落均为独立的实体,所以其value应该是一个list;
接下来是**段落**实体(对应于一个数据样本),在一个段落中,至少会包含它的内容`context`,它的标题`title`以及对应的问答`qas`。
显然在**一个段落**中会包含**多个问答**,每个问答均为独立的实体,所以其value应该是一个list;
接下来是**问答**实体,每个问答实体中,均为包含问题`question`,它的类型`type`,它的唯一表示`id`和它的答案(可能会有多个)。
以一个具体的数据json存储格式(两个样本)展示如下:
```json
{
"data": [
{
"paragraphs": [
{
"context": "高铁和动车上是可以充电的,充电插头就在座位下边或者是前边。高铁动车上的充电插座排布与车型新旧有关。有些车座位是每排座位两个电源插座,有些新型车比如说“复兴号”是每两个座位有一个电源。祝旅途愉快!",
"qas": [
{
"question": "高铁站可以充电吗",
"type": "vocab_noun",
"id": "ebbe3fc466f0f04177b8a64d2ee0de69",
"answers": [
{
"text": "",
"answer_start": -1
}
],
"is_impossible": true
}
],
"title": "高铁和动车上能充电吗? - 知乎"
},
{
"context": "【皋】字读音既可读gāo,又可读háo。读作gāo时,字义有三种意思,水边的高地或岸;沼泽,湖泊;姓氏。读作háo时,有号呼;呼告的意思。皋读作háo时... 全文",
"qas": [
{
"question": "皋怎么读",
"type": "in-domain",
"id": "e3ffa587bba2478191e357cd9a56d10b",
"answers": [
{
"text": "既可读gāo,又可读háo",
"answer_start": 6
}
],
"is_impossible": false
}
],
"title": "皋怎么读 - 懂得"
},
}
]
}
```
### 2.2 数据分布
训练数据量共3000,类型均为in-domain,
**context长度**的分布占比,
```
count 1404.000000
mean 211.985755
std 158.369534
min 50.000000
25% 112.000000
50% 152.000000
75% 251.250000
max 988.000000
```
有答案的占比为46.8%,有答案的的**答案长度**分布,
```
count 1404.000000
mean 44.738604
std 66.828911
min 1.000000
25% 5.000000
50% 15.000000
75% 62.250000
max 522.000000
```
### 2.3 数据ID化
本部分主要介绍如何将上面的九个不同的数据格式转化为模型可接受的数据格式。
- 样本的归一化
原始的数据整体为一个大的json结构体,不利于传统意义的上的训练样本的区分,该部分主要将整个json结构进行解析为单个的训练样本。定义**一个训练样本**为如下的结构,
- `id`
一个训练样本的id
- `title`
字符串类型,多部分为空
- `context`
字符串类型,context文本
- `question`
字符串类型,代表一个问题文本
- `answers`
数组类型,每个元素为一个json结构体,包括`text`和`answer_start`,基本均为一个