链接:
论文题目:OneEE: A One-Stage Framework for Fast Overlapping and Nested Event Extraction
code:https://github.com/cao-hu/oneee
paper:https://arxiv.org/abs/2209.02693v1
论文题目:CasEE: A Joint Learning Framework with Cascade Decoding for Overlapping Event Extraction
code:https://arxiv.org/abs/2107.01583v1
paper:https://github.com/JiaweiSheng/CasEE
官网:https://aclanthology.org/2021.findings-acl.14/
OneEE比CasEE效果更好
OneEE环境:
CUDA Version: 11.4
Python 3.8.20
torch 2.0.0
transformers 4.45.2
CasEE环境:
torch 2.0.0
transformers 4.45.2
引言:事件抽取理论和本项目的目标
1.分清定义,这四项代表什么
| TEST Final | F1 | Precision | Recall |
+------------+--------+-----------+--------+
| Trigger I | 0.8870 | 0.8888 | 0.8853 |
| Trigger C | 0.7877 | 0.7648 | 0.8120 |
| Argument I | 0.7561 | 0.7169 | 0.7998 |
| Argument C | 0.7255 | 0.7184 | 0.7327 |
+------------+--------+-----------+--------+
分别代表触发词识别(Trigger Identification) ,触发词分类 (Trigger Classification)
论元识别(Argument Identification),论元分类 (Argument Classification)
2.定义如下:
Trigger I (Trigger Identification):
这表示 触发词识别 的性能评估。触发词通常是指在事件抽取中表示某个特定事件发生的关键字。
Trigger C (Trigger Classification):
这表示 触发词分类 的性能评估。除了识别是否为触发词之外,还可能涉及触发词的具体类型分类(例如,时间、地点、事件类型等)。
Argument I (Argument Identification):
这表示 论元识别 的性能评估。在事件抽取中,论元是与触发词相关的实体或信息(例如,事件的参与者、地点、时间等)。
Argument C (Argument Classification):
这表示 论元分类 的性能评估。在识别出论元之后,还需要对其进行分类(例如,作为事件的“参与者”或“时间”等)。
!!!事件抽取:包括事件检测(对应触发词识别+分类)和论元分析(对应论元识别+分类)。
3.目标:
去除论元分析模块(也就是论元识别和论元分类),然后测试三个数据集 DuEE,FewFC,ACE2005三个数据集上中文事件检测的指标(只保留事件检测的模块,不保留论元分析的模块,因为论元分析会对事件检测有影响)
一、casEE三个数据集笔记和成功经验
运行CasEE_ace2005时候去除了2000之后的几百个数据,然后20epoch之后全是0,说明不能去除那么多数据,可能把几个触发词类别给删除了,然后结果就为0了,而删除一行就没有问题。这里经过pre_cascading.py处理后,数据就是会出现id一样的,但是他们的触发词类型(type)和词元(arg)是不一样的。所以这种情况是正确的。pre_cascading.py文件的功能,将原始数据集转换为occur标签的数据集,有多个事件的多条id会重复,但是标签不一样,也就是出现多条数据是正常的,标签是有多个
1.自定义数据集运行步骤:
1.首先将CasEEWithDuee_deleteArgument/pre-cascading.py中的type改为自己的数据集的事件(利用脚本《提取事件类型填写到pre-cascading.py》处理后将结果粘贴到pre-cascading.py中)
2.把自己的数据集目录改为data(先通过eventtype2event.py转换格式到跟fewfc中的data格式一样),再创建cascading_sampled目录,运行python pre-cascading.py在cascading_sampled目录下生成三个occur标签的数据
3.对于自定义的数据集,还要在utils/predict_without_oracle.py中将ARG_LEN_DICT改为自己数据集的参数(key是ty_args.json,值估计是通过bert中对应的。是最大截断长度。)
4.然后运行主程序即可python -u main.py --output_model_path ./models_save/model.bin --do_train True --do_eval True --do_test True > logs/model.log
5.出问题可以调试看看数据集问题还是代码问题
2.报错的问题:
注意:转换event_type的时候,要把arg后面那个加上[],没有的话会报错 args_roled_spans = [item['span'] for item in event['args'][arg_role]]
这个错误。(通过eventtype2event.py脚本修复)
修改完后报错 File "/home/user/jie/myStudy/CasEE/CasEEWithDuee_deleteArgument/utils/data_loader.py", line 40, in <listcomp>
tmp = [args_id[a] for a in args]
KeyError: '时间'
解决方法:shared_args_list.json中没有更新为duee的,更新即可
>>CasEE爆错#KeyError: 'collateral'
解决方法:在utils/predict_without_oracle.py里面需要修改第五行的ARG_LEN_DICT为自己数据集的参数,值应该是args里面出现的次数也许
参数这样设置,可以只运行test部分(来测试test的问题):/home/user/jie/myStudy/CasEE/CasEEWithDuee_deleteArgument/main.py --output_model_path ./models_save/model.bin --do_train False --do_eval False --do_test True > logs/model.log
casEE和oneEE中参数,注意batch-size都为8
parser.add_argument("--batch_size", type=int, default=8, help="Batch_size.")
parser.add_argument("--epochs_num", type=int, default=20, help="Number of epochs.")
注意用下面这个命令将输出逐步追加到log中:python -u main.py --output_model_path ./models_save/model.bin --do_train True --do_eval True --do_test True > logs/model.log
二、OneEE三个数据集笔记
data下面的fewfc中的newtrain比train多了1000多条数据,看了第一条数据两者格式一样
launch中这样设置可以直接调试当前文件,不用频繁更改文件了 "program": "${file}",
1.main.py中需要修改自己数据集的参数,使用的是默认参数 parser.add_argument('--config', type=str, default='./config/ace2005.json')
2./home/user/jie/myStudy/CasEE/OneEE_ace2005_deleteArgument/config/ace2005.json中 "dataset": "ace2005",也需要修改为自己的数据集
3./home/user/jie/myStudy/CasEE/OneEE_ace2005_deleteArgument/data_loader.py下面三个数据集文件夹,with open("./data/{}/new_train.json"
看loss在降低那就是正常的。
duee和fewfc数据集在oneee训练慢的话可以考虑train_dev_test用一个数据
duee的test比最后一个 TEST 19低的原因要么是模型泛化不行,要么就是自己没有保存好最好模型使用最好模型来测试
新的casEE文件运行需要修改的地方:
在data_loader中np.bool需要改为np.bool_
在根目录下放入bert-base-chinese
报错:Target sizes: [2, 887]. Tensor sizes: [1, 512]
解决方法:加入最大长度限制就ok,在OneEE_ace2005_deleteArgument/data_loader.py中的process_bert修改即可。
三、最终结果:
casEE在fewfc、duee、ace2005数据集上运行成功,OneEE在fewfc上运行成功,但是oneEE在duee和ace2005有问题,效果不好。
尝试了将train.dev.test数据合并,然后再复制到train.dev.test中,运行还是效果不好。表现为recall特别低,准确率正常但是浮动大。
其他四种就正常。
如duee:(初始结果,合并数据集到三文件)结果都类似下面这样:
| Train 3 | Loss | Tri F1 |
+---------+--------+--------+
| Label | 0.2086 | 0.0096 |
/home/user/jie/myStudy/CasEE/OneEE_duee_deleteArgument/data/duee2fewfc现在这个测试一下将训练集改为dev+test试一下效果
四、其他一些问题:
fewfc:使用的是这个数据集,代码里带的也是这个数据集
duee : 使用的是train、dev、但是test里面的数据只有id和event,无法转换trigger等标签,故这里使用dev代替test.
ace2005:这个是师兄发的的数据集,经处理之后(里面会有不少空值),都可以用
在CasEE中,需要额外生成ty_args.json和share_args_list.json(这个是ty_args.json经过值去重得到的)
在oneEE中,只需要额外生成ty_args.json(从train中得到trigger标签以及后面的多个触发词)
注意地方:ty_args.json中的事件必须都出现在train.json中,不然会报错找不到一些标签,也就是在data_loader.py中报错键错误。
在CasEE的param文件中记得改为对应数据集FewFC,duee和ace2005(目前duee和ace2005没有改)
漏洞: parser.add_argument("--data_path", type=str, default='datasets/FewFC', help="Path of the dataset.")
parser.add_argument("--test_path", type=str, default='datasets/FewFC/data/test.json', help="Path of the testset.")
服务器环境:casEE用的是jie_py3.8,oneEE是jie_oneEE
这个是dev复制变成test数据集. OneEE_epoch20_ace2005_12-25_10-41-20_true.txt
>>>>>>>>>>>>>>>>>>>>>>>>>>>问题:
注意casEE运行之前还有一步cascading
!!!错误地方:还有data_loader中的 os.chdir('/home/user/jie/myStudy/CasEE/CasEE') 后面这个CasEE需要换成具体项目
目前发现:oneEE和casEE处理的数据格式不一样,OneEE有一句"event_type": "投资"在最后确定多个事件中的一个事件。
而casEE在cascading_sampled数据集中,content后面用"occur": ["股份股权转让", "投资"], "type": "投资",这个来确定事件类型。occur会发生多个事件,type是确定的唯一事件类型。
易错地方:CasEE中python cascading.py需要提前创建目录./datasets/FewFC/cascading_sampled,才能生成三个文件train,test,dev.json
1.如果不做事件抽取只做事件检测,下面数据集中哪些信息用不到?
数据如下:{"id": "5442c0f0df93bc52d791d7dc5885b22f", "content": "今年4月,有知情人士表示该公司还在探索收购其规模最小的中国合资伙伴江淮汽车的股份。", "events": [{"type": "投资", "trigger": {"span": [19, 21], "word": "收购"}, "args": {"date": [{"span": [0, 4], "word": "今年4月"}], "obj": [{"span": [33, 37], "word": "江淮汽车"}]}}], "event_type": "投资"}
事件参数如:
"trigger": {"span": [19, 21], "word": "收购"}
"args": {"date": [{"span": [0, 4], "word": "今年4月"}], "obj": [{"span": [33, 37], "word": "江淮汽车"}]}}
这些信息对于事件检测任务是多余的。事件检测只关心是否检测到“投资”类型的事件,而不需要知道触发词的具体位置或相关的时间、对象等详细信息。
"event_type" 字段:该字段指示事件类型(例如“投资”),这部分信息在事件检测时是用不到的,因为事件检测的目标是通过文本内容检测出是否发生了某种类型的事件,而不需要提前知道事件类型。
SourceURL:file:///home/jie/桌面/个人的研究工作/师兄相关/2024.12.25报错记录.doc
2.目前oneEE_ace_2005_deleteArgument这个问题是准确率的问题,如下所示:
+-----------+--------+-----------+--------+
| EVAL 19 | F1 | Precision | Recall |
+-----------+--------+-----------+--------+
| Trigger I | 0.0583 | 0.8333 | 0.0302 |
| Trigger C | 0.0583 | 0.8333 | 0.0302 |
+-----------+--------+-----------+--------+
2024-12-24 23:56:46 - INFO:
+-----------+--------+-----------+--------+
| TEST 19 | F1 | Precision | Recall |
+-----------+--------+-----------+--------+
| Trigger I | 0.0364 | 0.8571 | 0.0186 |
| Trigger C | 0.0060 | 0.1429 | 0.0031 |
+-----------+--------+-----------+--------+
2024-12-24 23:56:46 - INFO: Best DEV F1: 0.0587
2024-12-24 23:56:46 - INFO: Best TEST F1: 0.0152
2024-12-24 23:56:52 - INFO:
+------------+--------+-----------+--------+
| TEST Final | F1 | Precision | Recall |
+------------+--------+-----------+--------+
| Trigger I | 0.0305 | 1.0000 | 0.0155 |
| Trigger C | 0.0000 | 0.0000 | 0.0000 |
解决方法:数据集确实也是处理过的。看训练集上的损失和F1分数都很高,但在验证集和测试集上的F1分数却很低,尤其是Trigger C的F1分数为0。这表明模型在训练集上表现良好,但在验证集和测试集上表现不佳,可能存在过拟合问题。(2024.12.25)
修改参数:
"batch_size": 2,
"learning_rate": 1e-3,
改为
"batch_size": 8,
"learning_rate": 1e-5,
结果是下面这个更差,上面那个效果也差
后面觉得应该是OneEE不适配这个任务
3.oneee_ace2005问题
使用参数:
"batch_size": 32,
也是报内存溢出,所以batch-size越小越不占显存。该方法不习惯。
之前跑了epoch=2的时候移除,现在设置batch-size=1试一试
尝试成功,也可以在device中修改显卡id,换个别的显卡用。
尝试1:
现在将oneEE_ACE2005中的dev复制到test,看看还会不会出现准确的为0的情况。
结果:还可以,还是部分有0
猜测:忽上忽下可能跟epoch>2就更新model.pt有关,使用了不太好的模型,可以换成5
尝试2:
将epoch》2改为》5,test还是用原本的test,然后把这一句取消注释了 trainer.load("model.pt")(本来就没有注释)
结果:效果比较差如下所示
+------------+--------+-----------+--------+
| TEST Final | F1 | Precision | Recall |
+------------+--------+-----------+--------+
| Trigger I | 0.0245 | 1.0000 | 0.0124 |
| Trigger C | 0.0000 | 0.0000 | 0.0000 |
+------------+--------+-----------+--------+
4.发现oneEE和casEE中的fewfc格式不一样
开始处理casEE中数据duee和ace2005数据
- casEE中初始fewfc数据需要经过pre_cascading.py处理成带occur的数据,代码中会加载这个标签(casEE中初始fewfc数据中的data也要保留,同时创建空的cascading_sampled文件夹)
- 删除ace2005中的有一个下标错误,这里看运行到2000后面才错,直接删除train.json后面所有运行成功。
发现casee正确的代码里面pre_cascading.py确实会把数据重复几条
{"id": "cd9f1b2792dd4b4b7fee112c5b27a811", "content": "记者查询同花顺数据发现,东旭系东旭集团股票持有东旭光电5.63亿股
{"id": "cd9f1b2792dd4b4b7fee112c5b27a811", "content": "记者查询同花顺数据发现,东旭系东旭集团股票持有东旭光电5.63亿股
5.jie_notes.txt中记录
目前已完成(2024.12.26):
oneee casEE(服务器)
fewfc true true
duee true(效果不好) true
ace2005 true 效果不好) true
两个程序的位置:
本地运行的是OneEE base
服务器运行的是casEE jie_py3.8
服务器也又运行了OneEE 用的jie_OneEE环境
##1.oneEE比caseEE效果要好
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>oneEE
测试时:batch-size =2(最终用2),epoch=1 ,"bert_name": "bert-base-chinese" 。
原始:batch-size=8,epoch=20 , "bert_name": "./bert-base-chinese",
测试数据可以用cascading_sampled_100大概100条数据来测试
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>casEE
casEE运行命令:
1.数据预处理:生成用于训练的级联采样数据,实现框架的级联学习策略(已生成于/dataset/FewFC/cascading_sampled):
python pre_cascading.py
2.训练/开发/测试模型(base) jie@dell:~/桌面/周阅微相关/CasEE/CasEE$
python -u main.py --output_model_path ./models_save/model.bin --do_train True --do_eval True --do_test True > logs/model.log
超参数记录在 中/utils/params.py。我们采用bert-base-chinese作为预训练语言模型。为了扩展,您还可以尝试其他超参数以获得更好的性能。
batch-size越大,则train_step按倍数越少,所以要尽量大,但是显存占用也会变更大,有可能会显存溢出。
问题:在CasEE中,100、500数据都会是让结果为0,
解决方法
解决方法:让epoch》=2就可以输出正确结果