基於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, _).

獲取交易概率如下:

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章