基于DeepDive实现从股权交易公告获取企业与企业之间存在交易关系的概率--解析篇

前言

前面实践篇基于DeepDive实现从股权交易公告获取企业与企业之间存在交易关系的概率–实践篇 已经大概地走了一波如何使用deepdive去做实体抽取,关系概率计算等操作,接下将基于deepdive的数据处理、实体抽取、特征抽取,结合示例相关文件进行解析。

1.数据处理脚本解析

前面我们第一步就是把股权交易公告数据通过执行 deepdive do articles实现公告数据导入。

articles 是deepdive的目标名,对应文件app.ddlog

具体导入数据表结构定义如下

@source
articles(
        @key
        @distributed_by
    id      text,
    @searchable
    content text
).

当前articles对象包含两个字段,分别是idcontent

实现数据导入的规则是在app.ddlogarticles的命名与当前目录的input 文件夹下需要导入的csv文件名对应
在这里插入图片描述

2. 数据标注脚本解析

通过执行 deepdive do sentences 实现公告数据标注,具体使用standfordnlp自然语言处理包。

2.1 数据标注结构定义

deepdive默认用standford nlp进行文本处理,可以返回句子的分词、lemma、pos、NER,具体看一下自然语言处理基础。

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

2.2 数据标注函数实现

这里定义函数名为nlp_markup 的函数,定义入参、返回值以及具体执行程序。

over后面定义接入参doc_idcontext,然后将返回数据rows数据结构对应定义的sentences的行数据,最后一句说明了我们这个程序文件是udf/nlp_markup.sh ,输入是tsv的一行。

function nlp_markup over (
        doc_id text,
        content text
    ) returns rows like sentences
    implementation "udf/nlp_markup.sh" handles tsv lines.

udf/nlp_markup.sh文件就是具体实现标注的程序,一般来说我们是可以不动它

set -euo pipefail
cd "$(dirname "$0")"

: ${BAZAAR_HOME:=$PWD/bazaar}

# 启动standordnlp 自然语言处理执行程序 具体在 udf/bazaar/parser/target/start 
# 启动程序由 sbt/sbt stage编译得
[[ -x "$BAZAAR_HOME"/parser/target/start ]] || {
    echo "No Bazaar/Parser set up at: $BAZAAR_HOME/parser"
    exit 2
} >&2

[[ $# -gt 0 ]] ||
    # default column order of input TSV
    set -- doc_id content

# 将数据tvs行数据转json
# start Bazaar/Parser to emit sentences TSV
tsv2json "$@" |

# 解析json数据,实现标注
"$BAZAAR_HOME"/parser/run.sh -i json -k doc_id -v content

定义完函数跟执行程序,就需要实现函数调用

sentences += nlp_markup(doc_id, content) :-
    articles(doc_id, content).

上面的+= 其实和其他语言差不多,就是对于来源是articles中的每一行的doc_idcontent 我们都调用nlp_markup 然后结果添加到sentences表中。

这一部分的函数基本都不需要进行改动,都是套路,沿着走就是了。

3.候选实体生成

首先我们再次明确的我们的目标,我们需要从这波非结构化数据里面,找到企业并且判断企业跟企业之间的关系。

我们上面以及完成数据初始化导入以及进行的数据标注,接下来我们根据标注后的数据,按照我们的规则,抽取出这段公告里面的实体也就是企业

3.1 抽取候选实体结构定义

老套路,定义实体表

@extraction
company_mention(
        @key
    # id 
    mention_id     text,
    @searchable
    # 企业名称
    mention_text   text,
    @distributed_by
    @references(relation="sentences", column="doc_id",         alias="appears_in")
    # 对应sentences表的id
    doc_id         text,
    # 对应sentences表的sentence_index
    @references(relation="sentences", column="doc_id",         alias="appears_in")
    sentence_index int,
    # 句中开始位置
    begin_index    int,
    # 句中结束位置
    end_index      int
).

3.2 抽取实体函数实现

这里的定义就是函数入参、返回值以及程序。

function map_company_mention over (
        doc_id         text,
        sentence_index int,
        tokens         text[],
        ner_tags       text[]
    ) returns rows like company_mention
    implementation "udf/map_company_mention.py" handles tsv lines.

udf/map_company_mention.py 就是核心抽取实体代码,具体逻辑就是根据 sentences里面的ner_tags,实体类型的识别,抽取类型为ORG的数据进行转换存储到company_mention里面,核心逻辑如下:

在这里插入图片描述

4. 候选实体关系抽取

前面说了,我们要判断企业跟企业之间的是否存在交易关系的概率,首先我们得建立企业与企业的集合,基于笛卡儿积。

假如有3个企业,笛卡儿积之后就会出现这样的结果:

企业1 企业2
阿里 腾讯
阿里 百度
腾讯 阿里
腾讯 百度
百度 阿里
百度 腾讯

4.1 候选实体关系结构定义

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

4.2 抽取候选关系函数

由于套路一致,讲讲核心就行

执行函数:

这里其实是基于数据库操作进行笛卡儿积,要求相关联的两个候选实体,要是在同一句话里的,不再同一句话中怎么知道他们两个有关系。而且两个名字不能一样,识别的时候也有可能一个部分识别了两个,所以开始位置也不能一样。

在这里插入图片描述

执行程序udf/map_transaction_candidate.py 主要做去重

在这里插入图片描述

一般来说,也是不用怎么改动的。

5.提取特征逻辑

这就是寻常的机器学习领域了,提取特征,利用机器学习去分类哪些是有交易关系的。

对于自然语言来说,他的特征就是上下文,就是上下文

5.1 定义特征表

@extraction
transaction_feature(
        @key
        @references(relation="has_transaction", column="p1_id", alias="has_transaction")
    p1_id   text,
    @key
    @references(relation="has_transaction", column="p1_id", alias="has_transaction")
    p2_id   text,
    @key
    feature text
).

5.2 提取特征实现

function extract_transaction_features over (
        p1_id          text,
        p2_id          text,
        p1_begin_index int,
        p1_end_index   int,
        p2_begin_index int,
        p2_end_index   int,
        doc_id         text,
        sent_index     int,
        tokens         text[],
        lemmas         text[],
        pos_tags       text[],
        ner_tags       text[],
        dep_types      text[],
        dep_tokens     int[]
    ) returns rows like transaction_feature
    implementation "udf/extract_transaction_features.py" handles tsv lines.

transaction_feature += extract_transaction_features(
    p1_id, p2_id, p1_begin_index, p1_end_index, p2_begin_index, p2_end_index,
    doc_id, sent_index, tokens, lemmas, pos_tags, ner_tags, dep_types, dep_tokens
) :-
    company_mention(p1_id, _, doc_id, sent_index, p1_begin_index, p1_end_index),
    company_mention(p2_id, _, doc_id, sent_index, p2_begin_index, p2_end_index),
    sentences(doc_id, sent_index, _, tokens, lemmas, pos_tags, ner_tags, _, dep_types, dep_tokens).

核心脚本 udf/extract_transaction_features.py,调用了ddlib库get_generic_features_relation产生了特征.

在这里插入图片描述

以其中一句为例子,1201734457_3

SELECT 	sentence_text FROM	sentences WHERE 	doc_id = '1201734457' 	AND sentence_index =3

公司拟将全资子公司山丹县芋兴粉业 有限责任公司(以下简称:芋兴粉业)100%股权、全资子公司甘肃天润 薯业有限责任公司(以下简称:天润薯业)100%股权及甘肃天润薯业有 限责任公司的全资子公司甘肃大有农业科技有限公司(以下简称:大有 科技)100%股权同价转让给甘肃亚盛薯业有限责任公司(以下简称:亚 盛薯业)。

根据我们观察 实体是甘肃大有农业科技有限公司以及甘肃天润薯业有限责任公司,他们进行了股权转让

甘肃大有农业科技有限公司实体id:1201734457_3_46_51

甘肃天润薯业有限责任公司实体id: 1201734457_3_22_27

select feature from transaction_feature where p1_id = '1201734457_3_46_51' and p2_id='1201734457_3_22_27'

总共抽取了79个特征

在这里插入图片描述

具体解析参考:https://blog.csdn.net/weixin_42001089/article/details/90749577

6. 样本打标

做过机器学习的朋友都知道,训练模型需要训练大量的标签数据进行模型迭代优化,这里示例的逻辑是导入先验数据,按照我们预先设定的规则,进行标记,产生一堆正例样本和反例样本。

6.1 导入先验数据

导入已知有交易关系的先验数据,先验数据结构如下:

transaction_dbdata(
    @key
    company1_name text,
    @key
    company2_name text
).

6.2 初始化标签表并对结合先验数据进行打标

定义标签表 transaction_label

@extraction
transaction_label(
    @key
    @references(relation="has_transaction", column="p1_id", alias="has_transaction")
    p1_id   text,
    @key
    @references(relation="has_transaction", column="p2_id", alias="has_transaction")
    p2_id   text,
    @navigable
    label   int,
    @navigable
    rule_id text
).

先验数据打标规则: 先验数据与抽选集合企业名称一致的权重为3,就是正相关比较大

在这里插入图片描述

6.3 对候选数据进行打标

核心脚本udf/supervise_transaction.py

在这里插入图片描述

这里基本就是按照定好的逻辑规则进行标注
在这里插入图片描述

通过sum计算打标结果总计获得最终标记transaction_resolve

 SELECT r0.p1_id AS column_0,
    r0.p2_id AS column_1,
    sum(r0.label) AS column_2
   FROM transaction_label r0
  GROUP BY r0.p1_id, r0.p2_id

最终标注结果如下:
在这里插入图片描述

7 变量表定义

首先定义最终存储的表格,[?]表示此表是用户模式下的变量表,即需要推到关系的表。这里我们需要推到的是企业和企业间是否存在交易关系。

has_transaction(p1_id, p2_id) = if l > 0 then TRUE
                      else if l < 0 then FALSE
                      else NULL end :- transaction_label_resolved(p1_id, p2_id, l).

8 构建因子图

8.1 因子图解释

Factor Graph 是概率图的一种,概率图有很多种,最常见的就是Bayesian Network (贝叶斯网络)和Markov Random Fields(马尔可夫随机场)。
 在概率图中,求某个变量的边缘分布是常见的问题。这问题有很多求解方法,其中之一就是可以把Bayesian Network和Markov Random Fields 转换成Facor Graph,然后用sum-product算法求解。基于Factor Graph可以用sum-product算法可以高效的求各个变量的边缘分布。

将一个具有多变量的全局函数因子分解,得到几个局部函数的乘积,以此为基础得到的一个双向图叫做因子图。
 所谓factor graph(因子图),就是对函数因子分解的表示图,一般内含两种节点,变量节点和函数节点。我们知道,一个全局函数能够分解为多个局部函数的积,因式分解就行了,这些局部函数和对应的变量就能体现在因子图上。
 在概率论及其应用中, 因子图是一个在贝叶斯推理中得到广泛应用的模型。

8.2 应用因子图获取交易概率

将每一对 has_transaction 中的实体对和特征表连接起来,通过特征因子连接,全局学习这些特征的权重 f

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

# Inference rule: Symmetry
@weight(3.0)
has_transaction(p1_id, p2_id) => has_transaction(p2_id, p1_id) :-
    transaction_candidate(p1_id, _, p2_id, _).

获取交易概率如下:

在这里插入图片描述

发布了41 篇原创文章 · 获赞 54 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_28540443/article/details/105194885