采用deepdive的上市公司关系抽取

时间: 2023-07-11 admin 互联网

采用deepdive的上市公司关系抽取

采用deepdive的上市公司关系抽取

准备

项目目标
在此设项目中,我们的目标是接受一组非结构化(或结构化)输入,并使用提取的输出填充关系数据库表,以及表示DeepDive对提取的置信度的每个提取的边际概率。更正式地说,我们编写一个DeepDive应用程序,根据指定的模式提取关系及其组成实体或属性的提及; 这项任务通常被称为关系提取。因此,我们将通过一个示例场景,我们希望从新闻文章中提取两个公司以及之间的关系。

DeepDive
DeepDive是一个从非结构化数据中提取价值的系统。DeepDive通过从非结构化信息(文本文档)创建结构化数据(SQL表)并将这些数据与现有结构化数据库集成,帮助将黑暗数据变为现实。
在上市公司关系抽取项目中,使用DeepDive从非结构化的上市公司公告信息中提取出结构化的公司实体间的三元组关系。

安装DeepDive
打开终端并运行:bash <(curl -fsSL git.io/getdeepdive)
选择deepdive
配置环境变量,deepdive的可执行文件一般安装在~/local/bin文件夹下。
~/.bash_profile下添加如下内容并保存:

export PATH="/root/local/bin:$PATH"

然后执行source ~/.bash_profile设置环境变量。

声明要预测的内容
在DeepDive我们想要预测的是一个名为DDlog的语言中的随机变量,存储在一个文件中:app.ddlog
在app.ddlog中声明:
#预测一对提及的公司实体之间是否表示有相关关系

    has_relation?(p1_id text,p2_id text ).

其中p1_id和p2_id的格式如下:1201900355_1_24_29,第一个”1201900355”是初始数据公告articles表中对应的id;”1”是该公司实体在公告中的句子的索引,”1”表示第一个句子;”24_29”表示公司在文章中的位置索引,24是开始位置,29是结束位置。

设置数据库
打开终端并运行:bash <(curl -fsSL git.io/getdeepdive) postgres 安装postgres数据库

打开终端并运行:echo “postgresql://$USER@$HOSTNAME:5432/db_name” >db.url建立数据库配置文件,其中db_name是数据库名字

数据获取

爬虫目标
在本实验中,我们实验的目的是从非结构化文本中提取出公司以及公司之间的关系。实验的数据源来源于巨潮资讯网主页的信息披露部分的深市主板上金融行业的交易公告。因此爬虫的目标是获取巨潮资讯网上的深市主板上金融行业的交易公告。

数据源
本次数据使用了巨潮资讯网上() 上市公司的深市主板上的上市公司的金融行业的交易公告信息。从巨潮网上查看控制台中的network发现巨潮资讯网在公告信息这一模块是通过post请求加参数来发送request,因此只要构建一个和巨潮网相同的请求的参数列表即可。然后将返回的url链接存入csv文件,通过csv文件保存的pdf文件的链接地址,通过python的pdfminer库将pdf文件下载存储为一个txt文件。

爬虫
公告新闻是通过post请求加参数来发送request,因此只要构建一个和巨潮网相同的请求的参数列表即可

query = {   'stock': '','searchkey': '','plate': szmb,'category': category_jy_szsh,'trade': '','column': 'szmb','columnTitle': '历史公告查询','pageNum': page_num,'pageSize’: 50,'tabName': 'fulltext','sortName': '','sortType': '','limit': '','showTitle': ‘’,'seDate': '2017-01-01 ~ 2017-10-23',}

PDF转CSV
从巨潮信息网上下载的上市公司公告数据是用PDF格式保存的,而DeepDive工具要使用的数据源是CSV格式的文件,因此需要将下载的PDF文件融合形成一个CSV文件。在PDF转CSV文件时使用了pdfminer库和csv库,其中pdfminer是一种从PDF文档中提取信息的工具,csv库用来读写CSV文件。

数据初始化
在用DeepDive处理原始文本时,由于原始文本中出现了一些简称之类的词,nlp语言里面并没有处理此类情况的方法,所以会造成公司实体识别不准确的情况,会降低程序处理结果的正确性,因此在将文本导入DeepDive之前对文本进行了预处理操作。
针对公告信息中大部分采用简称的方式来表示公司,所以采用了哈工大研发的ltp工具来进行公告中公司实体的识别,通过设置API参数中的pattern=ner&format=plain识别出公司名称并返回,然后用正则表达式匹配公告中的***公司(以下简称“***”)提取出公司和相应的简称之间的对应关系,然后用全称替换掉公告中的简称来进行原始文本的初始化。

数据处理

加载原始输入数据
准备待抽取的文章(示例使用上市公司公告),命名为articles.csv,放在input文件夹下。
在app.ddlog中建立对应的articles表的格式:

articles(id		text,     #文章的idcontent	text      #文章的内容
).

将aiticles.csv文件加载到数据库的articles表格中。

添加NLP标记
采用standford nlp进行文本处理。根据输入文本数据,nlp模块将以句子为单位,返回每句的分词、lemma、pos、NER和句法分析的结果。
在app.ddlog中建立对应的sentences表的格式:

    sentences(doc_id         text,       #doc_id表示的是articles表中公告对应的idsentence_index int,   # sentence_index表示的是公司所在的句子在文章中对应的索引sentence_text  text,   # sentence_text表示的是公司所在的句子的内容tokens         text[],     #tokens的结构如下:1: “证券”,其中1是分词的索引,“证券”是分词的内容lemmas         text[],   # lemmas与pos_tag、ner_tags、dep_types和tokens的结构是一样的,表示词元pos_tags       text[],    #pos_tags表示的是句子的词性ner_tags       text[],	    #ner_tags表示的是实体类型的识别,如果是公司则表示为“ORG”doc_offsets    int[],    #doc_offsets表示的是每个分词在文章中的开始位置的索引dep_types      text[],  #dep_types表示的是每个分词的句法结构dep_tokens     int[]       ).

提取提及的公司实体
在app.ddlog中定义实体数据表:

    company_mention(mention_id     text,      #mention_id的格式和has_relation中p1_text的格式相同mention_text   text,     #保存公司的名称doc_id         text,	      #保存文章的索引sentence_index int,      #保存公司所在句子的索引begin_index    int,	      #保存公司实体的开始位置的索引end_index      int          #保存公司实体结束位置的索引).

在map_company_mention.py脚本中遍历每个数据库中的句子,找出连续的NER标记为ORG的序列,再做其它过滤处理,其它脚本也要复制过去。这个脚本是一个生成函数,用yield语句返回输出行,将提及到的公司信息保存到数据库的company_mention表中。

提取可能有关系的公司实体对
在app.ddlog中定义实体数据表:

 transaction_candidate(p1_id   text,p1_name text,p2_id   text,p2_name text).

在map_transaction_candidate.py程序中遍历每个数据库中的句子,找出每个句子中的公司实体,将公司实体两两组成实体对,过滤掉两个相同实体组成的实体对,并将实体对的数据保存到数据库的transaction_candidate表中。

提取候选实体对的文本特征
在app.ddlog中定义实体数据表:

  transaction_feature(p1_id   text,p2_id   text,feature text
).

这里的目标是通过一组属性或特征来表示每个候选公司对提及的关键方面,然后让机器学习模型了解每个特征与我们的决策变量相关的程度。
函数调用extract_transaction_features.py来抽取特征,这里调用了DeepDive自带的ddlib库,得到各种POS/NER/词序列的窗口特征。

数据和规则的远程监督

样本打标
在app.ddlog中定义transaction_label表,存储监督数据:

transaction_label(p1_id   text,p2_id   text,label   int,rule_id text
).

其中rule_id代表在标记决定相关性的规则名称。label为正值表示正相关,负值表示负相关。绝对值越大,相关性越大。初始化定义,复制 transaction_candidate表到transaction_label中,label均定义为零。

数据的监督
在app.ddlog中定义实体数据表:

transaction_dbdata(company1_name text,company2_name text
).

通过匹配有交易的股票代码对和代码-公司对,过滤出存在交易关系的公司对,存入transaction_dbdata.csv中。将实体对保存到数据库的transaction_dbdata数据表中。
通过匹配transaction_dbdata数据表中的数据和transaction_label表中的数据,如果公司实体对在transaction_dbdata数据表中出现了,则将该实体对标记为真,将rule_id标记为“from_dbdata”。

规则的监督
函数调用supervise_transaction.py,在脚本中定义规则名称和所占的权重定义,程序将所有的候选公司实体对与定义好的规则相匹配,如果侯选实体对的规则与定义好的规则相同,则将label设置为程序中定义好的规则名称,然后将规则和权重保存到transaction_dbdata 表中。一部分规则和权重定义如下:
1.在句子中提及相隔太远的候选公司实体对被标记为假并且设置规则为“far_apart” ;
2. 如果句子实体对中包括了一些特殊字符的候选公司实体标记为假并且设置规则为“中间有特殊符号”;
3.有公司实体对中间有其他公司的候选实体对被标记为假并且设置规则为“third_company_between”;
4.在实体对中间的语句中提及“子公司”,“简称”,“购买”等词的候选实体对标记为真并且设置规则为“A子公司B”。
5.在实体对中间的语句中提及“无关联关系”的候选实体对标记为假并且设置规则为“AB无关联关系”;
6.在实体中间出现了“对”,“向”,后面出现了“投资”等词则将候选公司对标记为真并且设置规则为“A投资B”。

标签冲突的解决
不同的规则可能覆盖了相同的实体对,从而给出不同甚至相反的label。在postsql数据库中建立transaction_label_resolved表,统一实体对间的label。利用label求和,在多条规则和知识库标记的结果中,为每对实体做vote。

学习和推理

定义变量表
变量表是最终存储的数据的表格,其中(?)表示此表是用户模式下的变量表,即需要推导关系的表。这里我们预测的是公司间是否存在交易关系。
在app.ddlog中定义变量表:

 has_transaction?(p1_id text,p2_id text).

指定特征
将每个has_spouse变量连接到相应的spouse_candidate行的特征,通过DeepDive从我们远程监督的数据中学习这些特征的权重。

在app.ddlog中定义:

has_transaction(p1_id, p2_id) :-transaction_candidate(p1_id, _, p2_id, _),transaction_feature(p1_id, p2_id, f).

进行学习和推理
通过DeepDive将基于数据库中的数据对模型进行基础研究,了解权重,推断模型中变量的期望或边际概率,然后将它们加载回数据库,得到has_transaction变量推断的概率。