信息抽取实战:三元组抽取(限定领域 vs 开放领域)(附代码)

信息抽取实战:三元组抽取

一、限定领域的三元组抽取

  本项目将会介绍在2019语言与智能技术竞赛三元组抽取比赛方面的一次尝试。由于该比赛早已结束,当时也没有参加这个比赛,因此没有测评成绩,我们也只能拿到训练集和验证集。但是,这并不耽误我们在这方面做实验。

比赛介绍

  该比赛的网址为:http://lic2019.ccf.org.cn/kg,给定schema约束集合及句子sent,其中schema定义了关系P以及其对应的主体S和客体O的类别,例如(S_TYPE:人物,P:妻子,O_TYPE:人物)、(S_TYPE:公司,P:创始人,O_TYPE:人物)等。比如下面的例子:

{
   
  "text": "九玄珠是在纵横中文网连载的一部小说,作者是龙马",
  "spo_list": [
    ["九玄珠", "连载网站", "纵横中文网"],
    ["九玄珠", "作者", "龙马"]
  ]
}

  该比赛一共提供了20多万标注质量很高的三元组,其中17万训练集,2万验证集和2万测试集,实体关系(schema)50个
  在具体介绍的思路和实战前,先介绍下本次任务的处理思路
在这里插入图片描述

  首先是对拿到的数据进行数据分析,包括统计每个句子的长度及三元组数量,每种关系的数量分布情况。接着,对数据单独走序列标注模型和关系分析模型。最后在提取三元组的时候,用Pipeline模型,先用序列标注模型预测句子中的实体,再对实体(加上句子)走关系分类模型,预测实体的关系,最后形成有效的三元组。
  接下来将逐一介绍,项目结构图如下:
在这里插入图片描述

数据分析

  我们对训练集做数据分析,训练集数据文件为train_data.json
  数据分析会统计训练集中每个句子的长度及三元组数量,还有关系的分布图,代码如下:

# -*- coding: utf-8 -*-
import json
from pprint import pprint
import pandas as pd
from collections import defaultdict
import matplotlib.pyplot as plt

plt.figure(figsize=(18, 8), dpi=100)   # 输出图片大小为1800*800
# # Mac系统设置中文字体支持
# plt.rcParams["font.family"] = 'Arial Unicode MS'
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题

# 加载数据集
def load_data(filename):
    D = []
    with open(filename, 'r', encoding='utf-8') as f:
        content = f.readlines()

    content = [_.replace(' ', '').replace('\u3000', '').replace('\xa0', '').replace('\u2003', '') for _ in content]

    for l in content:
        l = json.loads(l)
        D.append({
   
            'text': l['text'],
            'spo_list': [
                (spo['subject'], spo['predicate'], spo['object'])
                for spo in l['spo_list']
            ]
        })
    return D

filename = '../data/train_data.json'

D = load_data(filename=filename)
pprint(D)

# 创建text, text_length, spo_num的DataFrame
text_list = [_["text"] for _ in D]
spo_num = [len(_["spo_list"])for _ in D]

df = pd.DataFrame({
   "text": text_list, "spo_num": spo_num} )
df["text_length"] = df["text"].apply(lambda x: len(x))
print(df.head())
print(df.describe())

# 绘制spo_num的条形统计图
pprint(df['spo_num'].value_counts())
label_list = list(df['spo_num'].value_counts().index)
num_list = df['spo_num'].value_counts().tolist()

# 利用Matplotlib模块绘制条形图
x = range(len(num_list))
rects = plt.bar(x=x, height=num_list, width=0.6, color='blue', label="频数")
plt.ylim(0, 80000) # y轴范围
plt.ylabel("数量")
plt.xticks([index + 0.1 for index in x], label_list)
plt.xlabel("三元组数量")
plt.title("三元组频数统计图")

# 条形图的文字说明
for rect in rects:
    height = rect.get_height()
    plt.text(rect.get_x() + rect.get_width() / 2, height+1, str(height), ha="center", va="bottom")

plt.savefig('./spo_num_bar_chart.png')
plt.show()

plt.close()

# 关系统计图
plt.figure(figsize=(18, 8), dpi=100)   # 输出图片大小为1800*800
# # Mac系统设置中文字体支持
# plt.rcParams["font.family"] = 'Arial Unicode MS'
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题

# 关系统计图
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南有芙蕖

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值