{"id":13595419,"url":"https://github.com/WuHuRestaurant/xf_event_extraction2020Top1","last_synced_at":"2025-04-09T13:32:00.420Z","repository":{"id":43054891,"uuid":"300111366","full_name":"WuHuRestaurant/xf_event_extraction2020Top1","owner":"WuHuRestaurant","description":"科大讯飞2020事件抽取挑战赛第一名解决方案\u0026完整事件抽取系统","archived":false,"fork":false,"pushed_at":"2020-12-29T10:23:02.000Z","size":10015,"stargazers_count":536,"open_issues_count":9,"forks_count":123,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-11-06T18:43:53.088Z","etag":null,"topics":["competition","events-extraction","pytorch"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WuHuRestaurant.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-01T01:59:19.000Z","updated_at":"2024-09-11T09:18:11.000Z","dependencies_parsed_at":"2022-08-24T11:30:44.997Z","dependency_job_id":null,"html_url":"https://github.com/WuHuRestaurant/xf_event_extraction2020Top1","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WuHuRestaurant%2Fxf_event_extraction2020Top1","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WuHuRestaurant%2Fxf_event_extraction2020Top1/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WuHuRestaurant%2Fxf_event_extraction2020Top1/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WuHuRestaurant%2Fxf_event_extraction2020Top1/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WuHuRestaurant","download_url":"https://codeload.github.com/WuHuRestaurant/xf_event_extraction2020Top1/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248049340,"owners_count":21039204,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["competition","events-extraction","pytorch"],"created_at":"2024-08-01T16:01:49.658Z","updated_at":"2025-04-09T13:31:56.963Z","avatar_url":"https://github.com/WuHuRestaurant.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# XF-Event-Extraction\n## 天池中医药NER冠军方案已经开源，欢迎star\n\n项目链接：https://github.com/z814081807/DeepNER\n\n2020\n科大讯飞事件抽取挑战赛\n\n比赛链接：http://challenge.xfyun.cn/topic/info?type=hotspot\n\n\n结果:\n| Name     | Score |  Rank|Team member| \n| :--------|:------|:----|:----------|\n|我是蛋糕王 | 0.73859| 1   |https://github.com/WuHuRestaurant\u003cbr\u003ehttps://github.com/aker218|\n\n\n事件抽取系统，包含触发词（trigger），事件论元（role），事件属性（attribution）的抽取。基于 pytorch 的 pipeline 解决方案。\n\n## 主要思路\n\n将任务分割为**触发词抽取**，**论元抽取**，**属性抽取**。具体而言是论元和属性的抽取结果依赖于**触发词**，因此只有一步误差传播。**因 time loc 并非每个句子中都存在，并且分布较为稀疏，因此将 time \u0026 loc 与 sub \u0026 obj 的抽取分开（role1 提取 sub \u0026 obj；role2 提取 time \u0026 loc）**\n\n模型先进行**触发词提取**，由于复赛数据集的特殊性，模型限制抽取的事件仅有一个，**如果抽取出多个触发词，选择 logits 最大的 trigger 作为该句子的触发词**，如果没有抽取触发词，筛选整个句子的 logits，取 argmax 来获取触发词；\n\n然后根据触发词抽取模型抽取的触发词，分别输入到 role1 \u0026 role2 \u0026 attribution 模型中，进行后序的论元提取和属性分类；四种模型都是基于 Roberta-wwm 进行实验，加入了不同的特征。\n\n最后将识别的结果进行整合，得到提交文件。\n\n### pipeline 思路如下：\n\u003cdiv align=center\u003e\u003cimg width=\"400\" height=\"300\" alt=\"pipeline\" src=\"./imgs/pipeline.png\"/\u003e\u003c/div\u003e\n\n### trigger 提取器：\ntrigger 提取采用的特征是**远程监督 trigger**，把所有标注数据当做一个知识库，对当前文本进行匹配。注：在训练时，需要排除自身的label，我们采用的是KFold的训练集 distant trigger 构造，即将训练集分成K份，用前K-1份的所有label当做后一份的知识库，构造训练数据的distant trigger；test 时候采用所有 trigger。\n在测试时若出现预测为空，选取 distant trigger logits 最大的解码输出 trigger。\n具体模型如下：\n\u003cdiv align=center\u003e\u003cimg width=\"400\" height=\"300\" alt=\"trigger\" src=\"./imgs/trigger.png\"/\u003e\u003c/div\u003e\n\n### role 提取器：\nrole 采用的特征是**trigger的相对距离**，然后采用了苏神的 **Conditional Layer Norm** 来让整个句子融入 trigger 信息，同样采用 Span 解码的方式。由于数据中 subject/object 分布相似，同时与 time/loc 分布相差很大，我们进一步进行了优化，将前两者和后两者的抽取分开，防止 time/loc 的数据对 subject/object 的 logits 稀疏化。\n\u003cdiv align=center\u003e\u003cimg width=\"400\" height=\"300\" alt=\"role\" src=\"./imgs/role.png\"/\u003e\u003c/div\u003e\n\n### attribution 分类器：\nattribution 分类器并没有进行特殊优化，采用了一个**动态窗口**的方法，我们认为某一 trigger 的 tense \u0026 polarity 只与其附近的语境有关，因此我们设定了一个窗口，对该窗口内进行 pooling 操作，然后利用 pooling 后的 logits 进行多任务学习，同时分类出 tense 和 polarity。因属性数据类别不均及其严重，最后我们用 ERNIE 模型做了一个10折交叉验证，有较大的提升。\n\u003cdiv align=center\u003e\u003cimg width=\"400\" height=\"300\" alt=\"attribution\" src=\"./imgs/attribution.png\"/\u003e\u003c/div\u003e\n\n### 数据增强：\n本次比赛主要的上分点在于数据增强的工作，初赛和复赛数据的分布差别极大，一起训练反而会导致结果下降。因此我们做了一个初赛数据筛选的工作，筛选出与复赛数据分布相近的数据进行增量训练。主要流程详见PPT中**基于标签验证的数据增强部分**。\n\n## 项目运行主要环境\n\n运行系统：\n\n```python\nUbuntu 18.04.4\n```\n\n---\n\npython:\n\n```python\npython3.7\n```\n\n----\n\npython 运行环境，可以通过以下代码完成依赖包安装：\n\n```python\npip install -r requirements.txt\n```\n\n```python\ntransformers==2.10.0\npytorch_crf==0.7.2\nnumpy==1.16.4\ntorch==1.5.1+cu101\ntqdm==4.46.1\nscikit_learn==0.23.2\ntorchcrf==1.1.0\n```\n\nCUDA:\n\n```python\nCUDA Version: 10.2  Driver 440.100 GPU：Tesla V100 (32G) * 2\n```\n\n## 项目目录说明\n\n```shell\nxf_ee\n├── data                                    # 数据文件夹\n│   ├── final                               # 复赛数据(处理过的)\n│   │   ├── mid_data                        # 中间数据 （词典等）\n│   │   ├── preliminary_clean               # 清洗后的初赛数据\n│   │   └── raw_data                        # 复赛经过初步清洗后的 raw_data\n│   └── preliminary                         # 初赛数据（略）\n│\n├── out                                     # 存放训练的模型\n│   ├── final                               # 复赛各个单模型（trigger/role/attribution）\n│   └── stack                               # 十折交叉验证的 attribution 模型\n│\n├── script/final                            # 放训练 / 评估 / 测试 的脚本\n│   ├── train.sh                            \n│   ├── dev.sh                     \n│   └── test.sh                \n│\n├── src_final\n│   ├── features_analysis                   # 数据分析\n│   │   └── images                          # 分析时画得一些图 \n│   ├── preprocess                       \n│   │   ├── convert_raw_data.py             # 处理转换原始数据\n│   │   ├── convert_raw_data_preliminary.py     # 转换初赛数据为复赛格式并处理\n│   │   └── processor.py                    # 转换数据为 Bert 模型的输入\n│   ├── utils                      \n│   │   ├── attack_train_utils.py           # 对抗训练 FGM / PGD\n│   │   ├── dataset_utils.py                # torch Dataset\n│   │   ├── evaluator.py                    # 模型评估\n│   │   ├── functions_utils.py              # 跨文件调用的一些 functions\n│   │   ├── model_utils.py                  # 四个任务的 models\n│   │   ├── options.py                      # 命令行参数\n│   |   └── trainer.py                      # 训练器\n|\n├── 答辩PPT                                 # 决赛PPT\n├── dev.py                                  # 用于模型评估\n├── ensemble_predict.py                     # 用百度 ERNIE 模型对 attribution 十折交叉验证\n├── predict_preliminary.py                  # 对初赛数据进行清洗\n├── readme.md                               # ...\n├── test.py                                 # pipeline 预测复赛数据 （包含 ensemble）\n└── train.py                                # 模型训练\n```\n\n## 使用说明\n\n### 数据转换\n\n数据转换部分只提供代码和已经转换好的数据，具体操作在 **src_final/preprocess**中的 convert_raw_data中，包含对初赛/复赛数据的清洗和转换。\n\n### 训练阶段\n\n```shell\nbash ./script/final/train.sh\n```\n\n注：**脚本中指定的 BERT_DIR 指BERT所在文件夹，BERT采用的是哈工大的全词覆盖wwm模型，下载地址 https://github.com/ymcui/Chinese-BERT-wwm ，自行下载并制定对应文件夹，并将 vocab.txt 中的两个 unused 改成 [INV] 和 [BLANK]（详见 processor 代码中的 fine_grade_tokenize）**\n\n**如果设备显存不够，自行调整 train_batch_size，脚本中的 batch_size（32）在上述环境中占用显存为16G**\n\n**最终训练的结果是每一个 epoch 下存一次，线下评估结果在 eval_metric.txt 下，保留最优线下结果作为训练结果，其余删掉即可**\n\n可更改的公共参数有\n\n```\nlr: bert 模块的学习率\nother_lr: 除了bert模块外的其他学习率（差分学习率）\nweight_decay：...\nattack_train： 'pgd' / 'fgm' / '' 对抗训练 fgm 训练速度慢一倍, pgd 慢两倍，但是效果都有提升\nswa_start: 滑动权重平均开始的epoch\n```\n\n##### trigger提取模型训练 （TASK_TYPE=“trigger”）\n\n可更改的参数有\n\n```python\nuse_distant_trigger: 是否使用复赛数据构造的远程监督库中的 trigger 信息\n```\n\n##### role 提取模型训练 （TASK_TYPE=“role1/role2”）\n\n可更改的参数有\n\n```python\nuse_trigger_distance: 是否使用句子中的其他词到 trigger 的距离这一个特征\n```\n\n**attribution 分类模型训练 （TASK_TYPE=“attribution”）**\n\n未使用其他特征\n\n\n\n**MODE=“stack”** 时候对 attribution 任务进行十折交叉验证，换用百度 ERNIE1.0 模型作为预训练模型\n\n### 验证阶段\n\n```shell\nbash ./script/final/dev.sh\n```\n\n主要的参数有三个：\n\n* TASK_TYPE：需要验证任务的 type\n* start/end threshold ：trigger / role1 model 需要进行调整的阈值\n* dev_dir: 需要验证的模型的文件夹\n\n### 测试阶段\n\n```shell\nbash ./script/final/test.sh\n```\n\n利用训练最优的四个单模型进行 pipeline 式的预测 sentences.json 文件，获取最终的 submit 文件，\n\n其中 **submit_{version},json** 为四个单模型的结果， **submit_{version}_ensemble_,json** 为单模型 + attribution 交叉验证后的结果。\n\n四个任务 model 的上级文件夹必须指定，同时文件夹名称应包含模型的参数特征。\n\n* **trigger_ckpt_dir**：              trigger 所在的文件夹\n* **role1_ckpt_dir**：                 role1 所在的文件夹\n* **role2_ckpt_dir：**                 role2 所在的文件夹\n* **attribution_ckpt_dir：**    attribution所在的文件夹\n\n## 测试效果 \n\n|     classification      |    score    |\n| :---------------------: | :---------: |\n|     submit_v1.json      |   0.73684   |\n| submit_v1_ensemble.json | **0.73859** |\n\n### 各阶段提升\n\u003cdiv align=center\u003e\u003cimg width=\"500\" height=\"250\" alt=\"res\" src=\"./imgs/res.png\"/\u003e\u003c/div\u003e\n\n---\n### 数据增强\n\n\n在我们的训练过程中，实际使用了组委会提供的初赛(经过清洗和转换)+复赛数据进行训练，在项目内部提供了清洗完毕的初赛数据；具体清洗流程如下所示：\n\n* 只使用复赛数据train得到trigger抽取模型和role1抽取模型(需指定model的上级文件夹)\n\n    **trigger_simple_ckpt_dir**：             单独复赛数据train trigger 所在的文件夹\n    **role1_simple_ckpt_dir**：               单独复赛数据train role1 所在的文件夹\n* 使用predict_prelimiary.py调用train好的trigger model 和role1 model 预测初赛数据的trigger和sub/ob\n\n```python\npython predict_preliminary.py --dev_dir_trigger trigger_simple_ckpt_dir  --dev_dir_role role1_simple_ckpt_dir\n```\n* 运行src_final/preprocess下的convert_raw_data_preliminary.py\n```python\npython convert_raw_data_preliminary.py\n```\n* 运行src_final/preprocess下的convert_raw_data.py 即完成了初赛数据的清洗\n```python\npython convert_raw_data.py\n```\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FWuHuRestaurant%2Fxf_event_extraction2020Top1","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FWuHuRestaurant%2Fxf_event_extraction2020Top1","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FWuHuRestaurant%2Fxf_event_extraction2020Top1/lists"}