Skip to content

taishan1994/BERT-Relation-Extraction

Repository files navigation

BERT-Relation-Extraction

使用bert进行关系三元组抽取。

模型和数据下载地址:https://cowtransfer.com/s/c5e2422d2e0b40 点击链接查看 [ BERT-Relation-Extraction ] ,或访问奶牛快传 cowtransfer.com 输入传输口令 vvf067 查看;

依赖

scikit-learn==1.1.3 
scipy==1.10.1 
seqeval==1.2.2
transformers==4.27.4
pytorch-crf==0.7.2

目录结构

--checkpoint模型和配置保存位置
--model_hub预训练模型
----chinese-bert-wwm-ext:
--------vocab.txt
--------pytorch_model.bin
--------config.json
--data存放数据
----dgre
--------ori_data原始的数据
--------ner_data处理之后的数据
------------labels.txt标签
------------train.txt训练数据
------------dev.txt测试数据
--------re_data------------labels.txt关系标签
------------train.txt训练数据
------------dev.txt测试数据
------------rels.txt该数据集没有因为实体只有两类有的话则是哪些实体之间具有关系
--config.py配置
--model.py模型
--process.py处理ori数据得到ner数据和re数据
--predict.py加载训练好的模型进行预测
--ner_main.py实体识别训练和测试
--re_main.py关系识别训练和测试

说明

使用的方法:

  • 1、利用BERT-BILSTM-CRF识别出文本里面的实体。
  • 2、根据rels之间实体对之间的关系,将可能有关系的两类实体和文本拼接后输入到模型里面进行分类。

这里以dgre数据为例。

1去https://huggingface.co/hfl/chinese-bert-wwm-ext/tree/main下载相关文件到chinese-bert-wwm-ext下2在process.py里面定义将ori_data里面的数据处理得到ner_data下的数据和re_data下的数据ner_data下数据样本是这样的--labels.txt
故障设备
故障原因
--train.txt/dev.txt
{"id": "AT0001", "text": ["6", "2", "号", "汽", "车", "故", "障", "报", "告", "综", "合", "情", "况", ":", "故", "障", "现", "象", ":", "加", "速", "后", ",", "丢", "开", "油", "门", ",", "发", "动", "机", "熄", "火", "。"], "labels": ["O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "B-故障设备", "I-故障设备", "I-故障设备", "B-故障原因", "I-故障原因", "O"]}
一行一条样本格式为BIOre_data下的数据样本是这样的--labels.txt
性能故障
部件故障
检测工具
组成
没关系
--train.txt/dev.txt
{"text": "故障原因:车轮悬架臂支座表面与车架接触面两者之间的表面接触不平整,在车辆低速急加速时,车轮悬架臂支座瞬间的推力,刚好车轮悬架臂支座表面与车架接触面接触不平整,车轮悬架臂支座表面与车架表面产生相对位移,使两者表面之间有摩擦,产生金属异响声解决方法:根据车轮悬架臂支座表面与车架接触面两者之间的表面接触不平整现象,对车轮悬架臂支座表面与车架表面进行平整化处理", "labels": ["车架接触面", "表面接触不平整", "部件故障"], "id": "1380_2"}
如果还有rels.txt则是这样的
{
    "故障设备_故障原因": ["性能故障", "部件故障", "检测工具", "组成"]
}
可参考duie/re_data下的rels.txt
也就是不同类型的实体对之间存在的关系3在config.py里面定义一些参数比如--max_seq_len句子最大长度GPU显存不够则调小--epochs训练的epoch数
--train_batch_size训练的batchsize大小GPU显存不够则调小--dev_batch_size验证的batchsize大小GPU显存不够则调小--save_step多少step保存模型
其余的可保持不变注意实体识别最大长度和关系抽取最大长度要保持一致4在ner_main.py里面修改data_name为数据集名称需要注意的是名称和data下的数据集名称保持一致最后运行python ner_main.py

5在re_main.py里面修改data_name为数据集名称需要注意的是名称和data下的数据集名称保持一致最后运行python re_main.py

5在predict.py修改data_name并加入预测数据最后运行python predict.py

DGRE数据集

max_seq_len=512
epochs=3
train_batch_size=12
dev_batch_size=12
实体识别precision    recall  f1-score   support

        故障原因       0.70      0.74      0.72       490
        故障设备       0.75      0.79      0.77       484

   micro avg       0.72      0.76      0.74       974
   macro avg       0.72      0.76      0.74       974
weighted avg       0.72      0.76      0.74       974

关系识别precision    recall  f1-score   support

        性能故障       0.96      0.87      0.91        30
        部件故障       0.89      0.99      0.94       464
        检测工具       1.00      0.67      0.80         3
          组成       0.60      0.95      0.73        19
         没关系       0.96      0.62      0.75       176

    accuracy                           0.89       692
   macro avg       0.88      0.82      0.83       692
weighted avg       0.90      0.89      0.88       692

联合预测文本>>>>>492号汽车故障报告故障现象一辆车用户用水清洗发动机后在正常行驶时突然产生铛铛异响自行熄火
实体>>>>>: {'故障原因': [('异响', 40, 41), ('熄火', 45, 46)]}
关系>>>>>: []
====================================================================================================
文本>>>>>故障现象空调制冷效果差实体>>>>>: {'故障设备': [('空调', 5, 6)], '故障原因': [('制冷效果差', 7, 11)]}
关系>>>>>: [('空调', '制冷效果差', '部件故障')]
====================================================================================================
文本>>>>>原因分析1遥控器失效或数据丢失;2ISU模块功能失效或工作不良;3系统信号有干扰导致处理方法体会1检查该车发现两把遥控器都不能工作两把遥控器同时出现故障的可能几乎是不存在的由此可以排除遥控器本身的故障2检查ISU的功能受其控制的部分全部工作正常排除了ISU系统出现故障的可能3怀疑是遥控器数据丢失用诊断仪对系统进行重新匹配发现遥控器匹配不能正常进行此时拔掉ISU模块上的电源插头使系统强制恢复出厂设置再插上插头发现系统恢复可以进行遥控操作但当车辆发动在熄火后遥控又再次失效4查看线路图发现在点火开关处安装有一钥匙行程开关当钥匙插入在点火开关内处于ON位时该开关接通向ISU发送一个信号此时遥控器不能进行控制工作当钥匙处于OFF位时开关断开遥控器恢复工作可以对门锁进行控制如果此开关出现故障也会导致遥控器不能正常工作同时该行程开关也控制天窗的自动回位功能测试天窗发现不能自动回位确认该开关出现故障
实体>>>>>: {'故障设备': [('遥控器', 7, 9), ('ISU模块', 20, 24), ('系统信号', 37, 40), ('遥控器', 66, 68), ('遥控器', 158, 160), ('遥控器', 182, 184), ('开关', 434, 435)], '故障原因': [('失效', 10, 11), ('数据', 13, 14), ('丢失', 15, 16), ('功能失效', 25, 28), ('工作不良', 30, 33), ('干扰', 42, 43), ('不能工作', 70, 73), ('数据丢失', 161, 164), ('失效', 260, 261), ('不能自动回位', 424, 429), ('故障', 438, 439)]}
关系>>>>>: [('遥控器', '失效', '部件故障'), ('遥控器', '丢失', '部件故障'), ('ISU模块', '功能失效', '部件故障'), ('ISU模块', '工作不良', '部件故障'), ('系统信号', '干扰', '部件故障'), ('遥控器', '不能工作', '部件故障'), ('遥控器', '数据丢失', '部件故障'), ('遥控器', '不能自动回位', '部件故障'), ('开关', '故障', '部件故障')]
====================================================================================================
文本>>>>>原因分析1发动机点火系统不良;2发动机系统油压不足;3喷嘴故障;4发动机缸压不足;5水温传感器故障实体>>>>>: {'故障设备': [('发动机点火系统', 7, 13), ('发动机系统', 19, 23), ('喷嘴', 31, 32), ('发动机', 38, 40), ('水温传感器', 48, 52)], '故障原因': [('不良', 14, 15), ('油压不足', 24, 27), ('故障', 33, 34), ('缸压不足', 41, 44), ('故障', 53, 54)]}
关系>>>>>: [('发动机点火系统', '不良', '部件故障'), ('发动机系统', '油压不足', '部件故障'), ('喷嘴', '故障', '部件故障'), ('发动机', '缸压不足', '部件故障'), ('水温传感器', '故障', '部件故障')]
====================================================================================================

DUIE数据集

max_seq_len:256
epochs:1
train_batch_size:12
dev_batch_size:12

实体在第1000step手动停止,关系在1500step手动停止。具体可自己调节。

实体识别precision    recall  f1-score   support

        Date       0.87      0.79      0.83      3130
      Number       0.77      0.72      0.75       877
        Text       0.70      0.63      0.66      2045
          人物       0.80      0.90      0.85     44595
          企业       0.47      0.67      0.55      3148
       企业/品牌       0.53      0.69      0.60       160
          作品       0.00      0.00      0.00        90
          国家       0.71      0.74      0.73      2241
        图书作品       0.86      0.72      0.78      4535
          地点       0.40      0.50      0.44       958
          城市       0.45      0.61      0.52       220
          奖项       0.00      0.00      0.00       529
          学校       0.64      0.86      0.74      1879
        学科专业       0.00      0.00      0.00         8
        影视作品       0.86      0.63      0.72      7900
        文学作品       0.57      0.21      0.30       188
          景点       0.44      0.36      0.40       118
          机构       0.81      0.37      0.51      2977
          歌曲       0.80      0.76      0.78      4976
          气候       0.80      0.80      0.80       132
        电视综艺       0.76      0.65      0.70      1010
         行政区       0.73      0.70      0.71       305
          语言       0.00      0.00      0.00        20
        音乐专辑       0.70      0.70      0.70      1035

   micro avg       0.77      0.79      0.78     83076
   macro avg       0.57      0.54      0.55     83076
weighted avg       0.78      0.79      0.77     83076

关系识别precision    recall  f1-score   support

         没关系       0.73      0.71      0.72      4887
        毕业院校       0.99      1.00      0.99      1372
          主角       0.80      0.21      0.33       188
        占地面积       0.95      0.95      0.95       165
        成立日期       0.99      1.00      0.99      2101
         主题曲       0.84      0.93      0.88       404
          歌手       0.86      0.85      0.85      3319
         创始人       0.90      0.91      0.91       301
          简称       0.94      0.99      0.97       651
          母亲       0.91      0.53      0.67      1145
        人口数量       0.96      1.00      0.98        85
          嘉宾       0.69      0.90      0.78       761
         代言人       0.95      0.97      0.96       129
          校长       0.98      0.96      0.97       419
        官方语言       1.00      0.72      0.84        18
        邮政编码       0.00      0.00      0.00         7
          父亲       0.78      0.86      0.82      2240
        所属专辑       0.96      0.95      0.96      1203
         主持人       0.90      0.78      0.84       619
          祖籍       0.96      0.95      0.96       256
          面积       0.91      0.91      0.91        95
          票房       0.95      0.84      0.89       289
          国籍       0.99      0.97      0.98      1925
          作者       0.92      0.96      0.94      4488
          首都       0.94      0.85      0.89        73
        所在城市       0.95      0.91      0.93       106
          作曲       0.61      0.82      0.70      1252
          导演       0.90      0.90      0.90      2736
          饰演       1.00      0.79      0.88      1185
        注册资本       0.99      1.00      1.00       280
          朝代       0.85      1.00      0.92       924
        专业代码       0.00      0.00      0.00         3
          海拔       1.00      1.00      1.00        58
         制片人       0.75      0.76      0.76       289
          气候       1.00      1.00      1.00       137
          编剧       0.80      0.64      0.71       846
        修业年限       0.00      0.00      0.00         5
          作词       0.88      0.54      0.67      1279
         董事长       0.96      0.95      0.95       966
          妻子       0.64      0.91      0.75      2473
          丈夫       1.00      0.01      0.01       759
          获奖       0.99      0.98      0.99       550
          主演       0.91      0.96      0.93      5937
                  1.00      0.98      0.99       262
        总部地点       0.96      0.99      0.98       533
         改编自       0.96      1.00      0.98       275
        上映时间       0.96      0.97      0.96      1302
        出品公司       0.95      0.98      0.97       949
          配音       0.94      0.87      0.90       490

    accuracy                           0.87     50736
   macro avg       0.85      0.81      0.81     50736
weighted avg       0.88      0.87      0.86     50736

联合预测文本>>>>>歌曲墨写你的美是由歌手冷漠演唱的一首歌曲
实体>>>>>: {'歌曲': [('墨写你的美', 3, 7)], '人物': [('冷漠', 13, 14)]}
关系>>>>>: [('墨写你的美', '冷漠', '歌手')]
====================================================================================================
文本>>>>>982阎维文回到山西隆重地迎娶了刘卫星
实体>>>>>: {'人物': [('阎维文', 5, 7), ('刘卫星', 19, 21)]}
关系>>>>>: [('阎维文', '刘卫星', '妻子'), ('刘卫星', '阎维文', '妻子')]
====================================================================================================
文本>>>>>王皃姁为还是太子的刘启生了二个儿子刘越汉景帝第11子)、刘寄汉景帝第12子实体>>>>>: {'人物': [('王皃姁', 0, 2), ('刘启', 9, 10), ('刘越', 18, 19), ('刘寄', 30, 31)]}
关系>>>>>: [('王皃姁', '刘启', '父亲'), ('王皃姁', '刘越', '父亲'), ('王皃姁', '刘寄', '父亲'), ('刘启', '王皃姁', '父亲'), ('刘启', '刘越', '父亲'), ('刘启', '刘寄', '父亲'), ('刘越', '王皃姁', '父亲'), ('刘越', '刘启', '父亲'), ('刘越', '刘寄', '父亲'), ('刘寄', '王皃姁', '父亲'), ('刘寄', '刘启', '父亲'), ('刘寄', '刘越', '父亲')]
====================================================================================================
文本>>>>>数据分析方法五种是2011年格致出版社出版的图书作者是尤恩·苏尔李
实体>>>>>: {'图书作品': [('数据分析方法五种', 0, 7)], '人物': [('尤恩·苏尔李', 29, 34)]}
关系>>>>>: [('数据分析方法五种', '尤恩·苏尔李', '作者')]
====================================================================================================
文本>>>>>视剧不可磨灭是导演潘培成执导刘蓓丁志诚李洪涛丁海峰雷娟刘赫男等联袂主演
实体>>>>>: {'影视作品': [('不可磨灭', 3, 6)], '人物': [('潘培成', 11, 13), ('刘蓓', 17, 18), ('丁志诚', 20, 22), ('李洪涛', 24, 26), ('丁海峰', 28, 30), ('雷娟', 32, 33), ('刘赫男', 35, 37)]}
关系>>>>>: [('不可磨灭', '潘培成', '导演'), ('不可磨灭', '刘蓓', '主演'), ('不可磨灭', '丁志诚', '主演'), ('不可磨灭', '李洪涛', '主演'), ('不可磨灭', '丁海峰', '主演'), ('不可磨灭', '雷娟', '主演'), ('不可磨灭', '刘赫男', '主演')]
====================================================================================================

可以看到,对于人物之间关系的识别会存在问题,这也正是补充里面所提到的。可能需要对人物之间的关系进行特别的优化。

补充

后处理很重要。在DGRE数据集中,限制了:

  • 原因必须在设备的后面。
  • 如果出现:设备1-原因1-设备2-原因2,则设备1不会考虑设备2后的所有原因了。

构建负样本很重要。虽然我们限制了哪两类实体之间有关系,但是在其内部还是有没有关系的存在,因此要构建负样本让模型知道这些实体之间没有关系。具体不同数据集可能构建的方式不大一样。

该方法还是存在一些问题

  • 不能区分两个实体之间存在多个关系。
  • 对于同类实体之间存在的关系不能有效的识别,而且不能区分主体和客体。

为了解决第二个问题,会发现关系是成对出现的,比如A是B的妻子,那么B是A的丈夫。duie数据中有四类:["丈夫","妻子","父亲","母亲"]。针对于父亲、母亲需要补充关系"儿子/女儿"。对于这种数据,需要交换sbj和obj,然后构建新的关系。在process.py中:

if spo["predicate"] in ["丈夫", "妻子", "父亲", "母亲"]:
    # 这里针对人物之间的关系转换一下
    tmp_reverse = {}
    tmp_reverse["id"] = i
    tmp_reverse["text"] = text
    if spo["predicate"] == "妻子":
        tmp_labels = [obj, sbj, "丈夫"]
    elif spo["predicate"] == "丈夫":
        tmp_labels = [obj, sbj, "妻子"]
    elif spo["predicate"] == "父亲":
        tmp_labels = [obj, sbj, "儿子/女儿"]
    elif spo["predicate"] == "母亲":
        tmp_labels = [obj, sbj, "儿子/女儿"]
    tmp_reverse["labels"] = tmp_labels
max_seq_len=256
epochs=5
train_batch_size=24
dev_batch_size=12

运行1820步后手动停止。

              precision    recall  f1-score   support

         没关系       0.92      0.92      0.92     18867
          歌手       0.86      0.88      0.87      3315
         制片人       0.94      0.67      0.78       284
          校长       0.99      0.97      0.98       419
          面积       0.90      0.93      0.91        95
        占地面积       0.96      0.94      0.95       165
        总部地点       0.97      1.00      0.98       533
          朝代       0.86      0.95      0.90       728
          作曲       0.70      0.69      0.69      1253
        邮政编码       0.00      0.00      0.00         7
        成立日期       0.98      1.00      0.99      2094
          祖籍       0.98      0.99      0.99       234
          妻子       0.81      0.78      0.79      2046
          饰演       0.98      0.86      0.92      1161
        注册资本       1.00      1.00      1.00       280
          简称       0.97      0.98      0.97       651
         创始人       0.91      0.92      0.91       281
          配音       0.92      0.95      0.94       496
        所在城市       0.98      0.86      0.91       106
                  0.96      0.99      0.97       255
          国籍       0.98      0.99      0.98      1733
        修业年限       0.00      0.00      0.00         5
          作词       0.77      0.69      0.73      1273
          嘉宾       0.78      0.83      0.81       747
         主题曲       0.86      0.91      0.89       406
        专业代码       0.00      0.00      0.00         3
         董事长       0.96      0.94      0.95       951
          编剧       0.64      0.75      0.69       855
         代言人       0.93      0.97      0.95       129
        所属专辑       0.96      0.96      0.96      1209
          海拔       1.00      1.00      1.00        58
          母亲       0.00      0.00      0.00       159
        官方语言       0.00      0.00      0.00        18
          父亲       1.00      0.01      0.01       302
        人口数量       0.92      1.00      0.96        85
         改编自       0.99      1.00      0.99       288
          丈夫       0.79      0.77      0.78      1971
        出品公司       0.97      0.97      0.97       950
          导演       0.91      0.89      0.90      2735
          票房       0.87      0.94      0.90       279
          首都       0.76      0.94      0.84        68
        上映时间       0.97      0.99      0.98      1286
          主角       0.75      0.62      0.68       188
          作者       0.94      0.91      0.93      4463
          气候       1.00      1.00      1.00       137
          主演       0.94      0.95      0.95      5898
         主持人       0.87      0.76      0.81       623
          获奖       0.97      0.99      0.98       532
        毕业院校       0.99      1.00      0.99      1331
       儿子/女儿       0.73      0.88      0.79      3824

    accuracy                           0.90     65776
   macro avg       0.82      0.80      0.80     65776
weighted avg       0.90      0.90      0.89     65776

文本>>>>>歌曲墨写你的美是由歌手冷漠演唱的一首歌曲
实体>>>>>: {'歌曲': [('墨写你的美', 3, 7)], '人物': [('冷漠', 13, 14)]}
关系>>>>>: [('墨写你的美', '冷漠', '歌手')]
====================================================================================================
文本>>>>>982阎维文回到山西隆重地迎娶了刘卫星
实体>>>>>: {'人物': [('阎维文', 5, 7), ('刘卫星', 19, 21)]}
关系>>>>>: [('阎维文', '刘卫星', '妻子'), ('刘卫星', '阎维文', '丈夫')]
====================================================================================================
文本>>>>>王皃姁为还是太子的刘启生了二个儿子刘越汉景帝第11子)、刘寄汉景帝第12子实体>>>>>: {'人物': [('王皃姁', 0, 2), ('刘启', 9, 10), ('刘越', 18, 19), ('刘寄', 30, 31)]}
关系>>>>>: [('王皃姁', '刘启', '儿子/女儿'), ('刘启', '王皃姁', '儿子/女儿'), ('刘启', '刘越', '儿子/女儿'), ('刘启', '刘寄', '儿子/女儿'), ('刘越', '王皃姁', '儿子/女儿'), ('刘越', '刘启', '儿子/女儿'), ('刘寄', '王皃姁', '儿子/女儿')]
====================================================================================================
文本>>>>>数据分析方法五种是2011年格致出版社出版的图书作者是尤恩·苏尔李
实体>>>>>: {'图书作品': [('数据分析方法五种', 0, 7)], '人物': [('尤恩·苏尔李', 29, 34)]}
关系>>>>>: [('数据分析方法五种', '尤恩·苏尔李', '作者')]
====================================================================================================
文本>>>>>视剧不可磨灭是导演潘培成执导刘蓓丁志诚李洪涛丁海峰雷娟刘赫男等联袂主演
实体>>>>>: {'影视作品': [('不可磨灭', 3, 6)], '人物': [('潘培成', 11, 13), ('刘蓓', 17, 18), ('丁志诚', 20, 22), ('李洪涛', 24, 26), ('丁海峰', 28, 30), ('雷娟', 32, 33), ('刘赫男', 35, 37)]}
关系>>>>>: [('不可磨灭', '潘培成', '导演'), ('不可磨灭', '刘蓓', '主演'), ('不可磨灭', '丁志诚', '主演'), ('不可磨灭', '李洪涛', '主演'), ('不可磨灭', '丁海峰', '主演'), ('不可磨灭', '雷娟', '主演'), ('不可磨灭', '刘赫男', '主演')]
====================================================================================================

有一定的效果,可能训练更长时间效果更好。

延申

由于这几个项目的代码结构都差不多,而且都和信息抽取相关,就一起放在这。

Releases

No releases published

Packages

No packages published

Languages