多读书多实践,勤思考善领悟

从零开始学习知识图谱 之 五.电影知识图谱构建 5.基于Deepdive非结构化文本关系抽取

本文于1592天之前发表,文中内容可能已经过时。

一. 简介

前面完成了针对结构化数据和半结构化数据的知识抽取工作,本节我们进行基于Deepdive框架的非结构化文本关系抽取。所采用的文本来自于百度百科的人物介绍。本次实战基于OpenKG上的支持中文的deepdive:斯坦福大学的开源知识抽取工具(三元组抽取),我们基于此,抽取电影领域的演员-电影关系。

deepdive是由斯坦福大学InfoLab实验室开发的一个开源知识抽取系统。它通过弱监督学习,从非结构化的文本中抽取结构化的关系数据 。本项目CNDeepdive修改了自然语言处理的model包,使它支持中文,并提供中文tutorial。

DeepDive项目处于维护模式,并且不再处于主动开发状态。用户社区保持活跃,但是原始项目成员不能再承诺令人兴奋的新功能/改进或响应请求。有关最新研究,请参阅Snorkel项目Ce Zhang的项目

本教程的项目代码放在github上,下载地址为《从零开始学习知识图谱》项目源代码

二. 环境准备

1. 操作系统

支持操作系统:macOS、Linux、Docker容器。Linux安装可以参考VirtualBox虚拟机安装UbuntuVirtualBox虚拟机安装CentOS8进行安装。

deepdive在高版本Linux下的支持并不好,虽然笔者修改安装代码最终也装上了,但是不建议新手来处理。所以推荐Ubuntu 16.04的版本。 Ubuntu 16.04下载地址,安装Ubuntu主机可参考文章VirtualBox虚拟机安装Ubuntu注意不要安装python3,使用Ubuntu自带的

2. 安装JDK

1) 设置下载目录

1
2
3
[root@ubuntu-mmm CNdeepdive]# cd /usr/local/
[root@ubuntu-mmm local]# mkdir jdk/
[root@ubuntu-mmm local]# cd jdk/

2) 下载JDK

1
2
3
4
5
6
7
8
9
[root@ubuntu-mmm jdk]# wget https://download.oracle.com/otn/java/jdk/8u221-b11/230deb18db3e4014bb8e3e8324f81b43/jdk-8u221-linux-x64.tar.gz?AuthParam=1570778301_521350e291b71079469aa571d925a2ec
--2019-10-11 14:04:37-- https://download.oracle.com/otn/java/jdk/8u221-b11/230deb18db3e4014bb8e3e8324f81b43/jdk-8u221-linux-x64.tar.gz?AuthParam=1570778301_521350e291b71079469aa571d925a2ec
正在解析主机 download.oracle.com (download.oracle.com)... 23.195.255.150
正在连接 download.oracle.com (download.oracle.com)|23.195.255.150|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:195094741 (186M) [application/x-gzip]
正在保存至: “jdk-8u221-linux-x64.tar.gz?AuthParam=1570778301_521350e291b71079469aa571d925a2ec”

r.gz?AuthParam=1570778301_521350e291b7107 5%[===>

3) 解压

使用tar -zxvf 文件名进行解压。

1
[root@ubuntu-mmm jdk]# tar -zxvf jdk-8u221-linux-x64.tar.gz

4) 配置环境变量

1
[root@ubuntu-mmm jdk]# vi /etc/profile

将如下配置添加至文件中,然后保存退出。

1
2
3
4
#java
export JAVA_HOME=/usr/local/jdk/jdk1.8.0_221
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib

执行命令,使文件修改后立即生效

1
[root@ubuntu-mmm jdk]# source /etc/profile

5) 验证

1
2
3
4
5
[root@ubuntu-mmm jdk]# java -version

java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)

3. 安装Deepdive

1)下载Deepdive安装包 CNDeepdive

2)修改install.sh,否则出现报错,无法安装

1
2
# 修改前 tar xzvf "$tarball" -C "$PREFIX"
tar zvf "$tarball" -C "$PREFIX"

3)运行install.sh,先选择【1 】安装deepdive,然后选择【6】 安装postgresql。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@ubuntu-mmm CNdeepdive]# cd /usr/local/CNdeepdive
[root@ubuntu-mmm CNdeepdive]# bash install.sh
#运行install.sh 分别选择【1 】安装deepdive,选择【6】 安装postgresql。
正在处理用于 dbus (1.10.6-1ubuntu3.3) 的触发器 ...
正在处理用于 ca-certificates (20170717~16.04.1) 的触发器 ...
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...

done.
done.
+ sudo localedef -i en_US -f UTF-8 en_US.UTF-8
## Finished installation for _deepdive_runtime_deps
## Finished installation for deepdive
......
+ trap 'rm -f /tmp/pg_hba.conf.ixUUNdF' EXIT
+ echo 'host all all 127.0.0.1/32 trust'
+ echo 'host all all ::1/128 trust'
+ sudo cat /etc/postgresql/9.5/main/pg_hba.conf
+ sudo tee /etc/postgresql/9.5/main/pg_hba.conf
+ sudo service postgresql restart
++ rm -f /tmp/pg_hba.conf.ixUUNdF
## Finished installation for postgres
......

4)配置环境变量,deepdive的可执⾏⽂件⼀般安装在~/local/bin⽂件夹下。 在~/.bashrc 文件的末尾添加下面的内容:

1
2
3
4
5
6
7
[root@ubuntu-mmm CNdeepdive]# vi ~/.bashrc
#添加如下内容
#除了root,其他在/home/(username)/local/bin其中的(username)要替换成你当前登录的用户名
export PATH="/root/local/bin:$PATH"

#来使我们的修改生效。
[root@ubuntu-mmm CNdeepdive]# source ~/.bashrc

5)然后执行下面的命令,安装自然语言处理的部分 。

1
2
3
4
root@ubuntu-mmm:/usr/local/CNdeepdive# bash nlp_setup.sh

Install Dependency.
Denpendency Already Installed.

好的,到这里Deepdive就已经安装完成了 。

6)打开终端执行deepdive我们可以看到Deepdive的版本信息和命令参数的Help。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
root@ubuntu-mmm:/usr/local/CNdeepdive# deepdive
# DeepDive (v0.8.0-79-g28a58de)
# Usage: deepdive COMMAND [ARG]...

# To enable bash completion for deepdive commands, run:
source $(deepdive whereis installed etc/deepdive_bash_completion.sh)

No COMMAND given

# Available COMMANDs are:
deepdive check # Checks errors in compiled DeepDive app
deepdive compile # Compiles DeepDive source code into executables under run/
deepdive compute # Runs a UDF using a computer against the database
deepdive create # Creates a table/view in the database
deepdive db # Exposes lower level database operations provided by the driver
deepdive do # Runs necessary processes to get something done
deepdive done # Checks whether given targets are all done
deepdive env # Runs commands inside DeepDive's environment
deepdive help # Shows help
deepdive initdb # (DEPRECATED) Initializes the underlying database for the DeepDive application
deepdive load # Loads a given relation's data
deepdive mark # Marks state of something to do
deepdive model # Supports working with the statistical inference model
deepdive plan # Shows execution plan for given targets
deepdive query # Runs a DDlog query against the database for the DeepDive application
deepdive redo # Runs processes after marking them as 'todo'
deepdive run # Runs the current DeepDive app end-to-end
deepdive sql # Runs a SQL query against the database for the DeepDive application
deepdive unload # Unloads a given relation's data
deepdive version # show deepdive's version and build information
deepdive whereis # Finds absolute paths to files in the app or DeepDive installation

安装也可以参考文档Deepdive 实战-从下载到跑路

三. 项目框架搭建

1. 建立postgresql的数据库movie

数据库管理工具推荐

Navicat Premium,是一套数据库开发工具,让你从单一应用程序中同时连接 MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite 数据库。Navicat系列破解工具链接:https://pan.baidu.com/s/1KmH2aaESpjozQaxr2C7D2A

可以使用它来管理PostgreSQL数据库,Navicat连接PostgreSQL,PostgreSQL需要进行如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
1. 通过find / -name  postgresql.conf 和 find / -name pg_hba.conf 找到这两个文件

2. 设置外网访问:

     1)修改配置文件 postgresql.conf
           listen_addresses = '*'
     2)修改pg_hba.conf       在原来的host下面新加一行
           # IPv4 local connections:
           host    all             all             127.0.0.1/32            trust
           host    all             all             0.0.0.0/0               password

3. 重新启动服务:service postgresql restart

在这里我们不使用navicat,可以不安装。

1) 创建数据库movie

运行 sudo -u postgres createdb 建立数据库movie

1
root@ubuntu-mmm:CNdeepdive# sudo -u postgres createdb movie

如果要删除数据,可以使用下面命令

1
root@ubuntu-mmm:CNdeepdive# sudo -u postgres dropdb movie

2) 验证数据库是否创建成功

首先运行sudo -i -u postgres 进入到postgresql账户

1
root@ubuntu-mmm:/usr/local/CNdeepdive# sudo -i -u postgres

输入psql进入到postgresql命令界面

1
2
3
4
5
postgres@ubuntu-mmm:~$ psql
psql (9.5.19)
Type "help" for help.

postgres=#

查看数据库列表

1
2
3
4
5
6
7
8
9
10
11
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
movie | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
postgres | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
template0 | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)

修改PostgreSQL登录密码:

1
2
3
postgres=# ALTER USER postgres WITH PASSWORD 'postgres';

ALTER ROLE

输入\q退出psql。

1
postgres-# \q

3) 返回自己的程序目录

运行’’’su yourusername’’’ 回到自己的程序目录。

1
postgres@ubuntu-mmm:~$ su root

2. 项目框架搭建

1)创建项⽬⽂件夹

这部分的数据和代码以及程序都在前面我们解压后的CNdeepdive/transaction中,你可以把这个目录复制到你喜欢的地方(比如~/Projects/transaction 这个位置),然后再新建一个目录,可以叫做transaction2 我们后面的所有工作都是在这个transaction2目录中进行的,后面简称它为项目目录。

运行命令:

1
2
3
root@ubuntu-mmm:/var/lib/postgresql# cd /usr/local/CNdeepdive
root@ubuntu-mmm:/usr/local/CNdeepdive# mkdir transaction2/
root@ubuntu-mmm:/usr/local/CNdeepdive# cd transaction2

2)建⽴数据库配置⽂件db.url

建⽴⾃⼰的项⽬⽂件夹transaction2,之前已在postgresql中为项⽬建⽴数据库movie,现要在项⽬⽂件夹下建⽴数据库配置⽂件:
运行命令:

1
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# echo "postgresql://localhost:5432/movie" >db.url

命令说明:

echo “postgresql://$USER@$HOSTNAME:5432/db_name” >db.url

#$符号是shell中用来表示变量的,所以这个蓝色部分大概就是 用户名@主机名:。。。。

#db_name 我们这个项目的数据库名,也可以自定义。

3)创建项⽬⽂件

在deepdive内建立输入数据文件夹 input,用户定义函数文件夹udf,用户配置文件app.ddlog,模型配置文件deepdive.conf。

为了调用 stanford_nlp 进行文本处理,将下载的CNdeepdive 文件夹中的transaction/udf/bazzar复制到自己的 udf 文件夹下,并在udf/bazzar/parser/ 目录下运行 sbt/sbt stage 进行编译。编译完成后会在 target 中生成可执行文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2/udf/bazaar/parser# chmod 777 sbt/sbt
#获得执行权限
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2/udf/bazaar/parser# sbt/sbt stage

Getting org.scala-sbt sbt 0.13.8 ...
:: retrieving :: org.scala-sbt#boot-app
confs: [default]
52 artifacts copied, 0 already retrieved (17674kB/165ms)
Getting Scala 2.10.4 (for sbt)...
:: retrieving :: org.scala-sbt#boot-scala
confs: [default]
5 artifacts copied, 0 already retrieved (24459kB/108ms)
[info] Loading project definition from /usr/local/CNdeepdive/transaction2/udf/bazaar/parser/project/project
[info] Updating {file:/usr/local/CNdeepdive/transaction2/udf/bazaar/parser/project/project/}parser-build-build...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Loading project definition from /usr/local/CNdeepdive/transaction2/udf/bazaar/parser/project
[info] Updating {file:/usr/local/CNdeepdive/transaction2/udf/bazaar/parser/project/}parser-build...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Set current project to deepdive-nlp-parser (in build file:/usr/local/CNdeepdive/transaction2/udf/bazaar/parser/)
[info] Updating {file:/usr/local/CNdeepdive/transaction2/udf/bazaar/parser/}parser...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[warn] Scala version was updated by one of library dependencies:
[warn] * org.scala-lang:scala-library:(2.10.3, 2.10.4, 2.10.2, 2.10.0) -> 2.10.5
[warn] To force scalaVersion, add the following:
[warn] ivyScala := ivyScala.value map { _.copy(overrideScalaVersion = true) }
[warn] Run 'evicted' to see detailed eviction warnings
[info] Compiling 6 Scala sources to /usr/local/CNdeepdive/transaction2/udf/bazaar/parser/target/scala-2.10/classes...
[info] Wrote start script for mainClass := Some(com.clearcut.nlp.Main) to /usr/local/CNdeepdive/transaction2/udf/bazaar/parser/target/start
[success] Total time: 18 s, completed 2019-10-15 16:10:54

三. 数据准备

1. 先验数据导入

为了对样本进行打标,我们需要一定的先验数据,它包含确定的演员-电影关系对。我们直接从结构化数据的数据库中抽取出演员和对应的代表作作为先验数据。

1) actor_movie.txt文件

用MySQL Workbench导出工具把actor_to_movie表的数据导出到actor_movie.txt文件,也可以通过百度云(提取码:xgof)直接下载该文件。这一步在先前的windows环境下完成。数据格式如下:

1
2
3
4
5
#actor_id movie_id
900 1
10426 9
9412 11
8792 25

2) 获取 actor_movie_dbdata.csv 文件

您可以通过脚本 udf/get_actor_movie.py 获取 input/actor_movie_dbdata.csv 文件,也可以通过百度云(提取码:jyxo)直接下载该文件。这一步在先前的windows环境下完成

1
2
3
C:\my\Python\python.exe C:/d/mmm/pycharm/deepdive/udf/get_actor_movie.py

Process finished with exit code 0

3) app.ddlog 中定义相应的数据表

获取该文件后,我们需要将其导入到数据库中以进行处理。首先我们在app.ddlog 中定义相应的数据表,文件内容如下:

1
2
3
4
5
6
7
@source
actor_movie_dbdata(
@key
actor_name text,
@key
movie_name text
).

4) 编译及生成数据表

而后通过命令行编译及生成数据表

a. 行编译操作,也就是在项目目录执行下面的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive compile

2019-10-16 15:25:51.779111 ‘run/LATEST.COMPILE’ -> ‘20191016/152551.724661396’
2019-10-16 15:25:51.784188 ‘run/RUNNING.COMPILE’ -> ‘20191016/152551.724661396’
2019-10-16 15:25:51.784488 Parsing DeepDive application (/usr/local/CNdeepdive/transaction2) to generate:
2019-10-16 15:25:51.784700 run/compiled/schema.json
2019-10-16 15:25:51.784902 from app.ddlog
2019-10-16 15:25:52.230712 run/compiled/deepdive.conf
2019-10-16 15:25:52.230760 from app.ddlog
2019-10-16 15:25:52.739134 from deepdive.conf
2019-10-16 15:25:52.740832 run/compiled/deepdive.conf.json
2019-10-16 15:25:53.062665 Performing sanity checks on run/compiled/deepdive.conf.json:
2019-10-16 15:25:53.090525 checking if input_extractors_well_defined
2019-10-16 15:25:53.090609 checking if input_schema_wellformed
2019-10-16 15:25:53.090621 Normalizing and adding built-in processes to the data flow to compile:
2019-10-16 15:25:53.090631 run/compiled/config-0.00-init_objects.json
2019-10-16 15:25:53.101117 run/compiled/config-0.01-parse_calibration.json
2019-10-16 15:25:53.108870 run/compiled/config-0.01-parse_schema.json
2019-10-16 15:25:53.126399 run/compiled/config-0.51-add_init_app.json
2019-10-16 15:25:53.132111 run/compiled/config-0.52-input_loader.json
2019-10-16 15:25:53.144006 run/compiled/config-1.00-qualified_names.json
2019-10-16 15:25:53.158387 run/compiled/config-1.01-parse_inference_rules.json
2019-10-16 15:25:53.185708 run/compiled/config-2.01-grounding.json
2019-10-16 15:25:53.287285 run/compiled/config-2.02-learning_inference.json
2019-10-16 15:25:53.303617 run/compiled/config-2.03-calibration_plots.json
2019-10-16 15:25:53.314917 run/compiled/config-9.98-ensure_init_app.json
2019-10-16 15:25:53.324952 run/compiled/config-9.99-dependencies.json
2019-10-16 15:25:53.336073 run/compiled/config.json
2019-10-16 15:25:53.337028 Validating run/compiled/config.json:
2019-10-16 15:25:53.382982 checking if compiled_base_relations_have_input_data
2019-10-16 15:25:53.383035 checking if compiled_dependencies_correct
2019-10-16 15:25:53.383047 checking if compiled_input_output_well_defined
2019-10-16 15:25:53.383056 checking if compiled_output_uniquely_defined
2019-10-16 15:25:53.383064 Compiling executable code into:
2019-10-16 15:25:53.383073 run/compiled/code-cmd_extractor.json
2019-10-16 15:25:53.401750 run/compiled/code-dataflow_dot.json
2019-10-16 15:25:53.417009 run/compiled/code-Makefile.json
2019-10-16 15:25:53.435906 run/compiled/code-sql_extractor.json
2019-10-16 15:25:53.447180 run/compiled/code-tsv_extractor.json
2019-10-16 15:25:53.461059 Generating files:
2019-10-16 15:25:53.471287 run/process/init/app/run.sh
2019-10-16 15:25:53.478829 run/process/init/relation/actor_movie_dbdata/run.sh
2019-10-16 15:25:53.482429 run/dataflow.dot
2019-10-16 15:25:53.484349 run/Makefile
2019-10-16 15:25:53.541030 run/dataflow.svg
2019-10-16 15:25:53.543347 (file:///usr/local/CNdeepdive/transaction2/run/dataflow.svg)
2019-10-16 15:25:53.544398 ‘run/compiled’ -> ‘20191016/152551.724661396’

b. 编译完成后,我们要执行deepdive do db

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive do actor_movie_dbdata

# on ubuntu-mmm: deepdive do actor_movie_dbdata
# run/20191016/152600.104675031/plan.sh
# execution plan for data/actor_movie_dbdata

## process/init/app ##########################################################
# Done: N/A
process/init/app/run.sh
mark_done process/init/app
##############################################################################


## process/init/relation/actor_movie_dbdata ##################################
# Done: N/A
process/init/relation/actor_movie_dbdata/run.sh
mark_done process/init/relation/actor_movie_dbdata
##############################################################################


## data/actor_movie_dbdata ###################################################
# Done: N/A
# no-op
mark_done data/actor_movie_dbdata
##############################################################################

这里do 后面应该和我们app.ddlog 中的名字相同,和input 文件夹中的文件名也相同,他们三个应该都是一致的。他会把input文件中的对应的文件导入postgresql数据库中。注意这个语句执行后,他会进入一个类似vi的界面让你审查他自动生成的处理代码是不是正确,这时候输入:wq 就可以保存并退出,继续执行后面的步骤。运行结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2019-10-16 15:36:50.793180 
2019-10-16 15:36:50.793341 : ## process/init/app ##########################################################
2019-10-16 15:36:50.793549 : # Done: 2019-10-16T15:31:00+0800 (5m 42s ago)
2019-10-16 15:36:50.793734 : process/init/app/run.sh
2019-10-16 15:36:50.793938 : mark_done process/init/app
2019-10-16 15:36:50.795712 : ##############################################################################
2019-10-16 15:36:50.795906
2019-10-16 15:36:50.796165
2019-10-16 15:36:50.796308 ## process/init/relation/actor_movie_dbdata ##################################
2019-10-16 15:36:50.796550 # Done: N/A
2019-10-16 15:36:50.796758 process/init/relation/actor_movie_dbdata/run.sh
2019-10-16 15:36:50.797006 ++ dirname process/init/relation/actor_movie_dbdata/run.sh
2019-10-16 15:36:50.797202 + cd process/init/relation/actor_movie_dbdata
2019-10-16 15:36:50.797407 + export DEEPDIVE_CURRENT_PROCESS_NAME=process/init/relation/actor_movie_dbdata
2019-10-16 15:36:50.797677 + DEEPDIVE_CURRENT_PROCESS_NAME=process/init/relation/actor_movie_dbdata
2019-10-16 15:36:50.797987 + deepdive create table actor_movie_dbdata
2019-10-16 15:36:50.885518 CREATE TABLE
2019-10-16 15:36:50.886898 + deepdive load actor_movie_dbdata
loading actor_movie_dbdata: 0:00:00 179KiB [ 816MiB/s] ([ 816MiB/s])r_movie_dbdata.csv (csv format)
loading actor_movie_dbdata: 0:00:00 5.94k [ 123k/s] ([ 123k/s])
2019-10-16 15:36:50.996248 COPY 5943
2019-10-16 15:36:50.998965 mark_done process/init/relation/actor_movie_dbdata
2019-10-16 15:36:51.003297 ##############################################################################
2019-10-16 15:36:51.003373
2019-10-16 15:36:51.003386
2019-10-16 15:36:51.003397 ## data/actor_movie_dbdata ###################################################
2019-10-16 15:36:51.003408 # Done: N/A
2019-10-16 15:36:51.003436 # no-op
2019-10-16 15:36:51.003467 mark_done data/actor_movie_dbdata
2019-10-16 15:36:51.006529 ##############################################################################
2019-10-16 15:36:51.006568
2019-10-16 15:36:51.006580
‘run/FINISHED’ -> ‘20191016/153642.492053809

c. 执行完成后,可以执行下面代码在数据库中查询,看看是不是成功导入了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive query '?- actor_movie_dbdata(actor_name, _).'

actor_name
--------------------------------------------------------------------------
周星驰
周星驰
Stephen Chow
Stephen Chow
周星驰
周星驰
Stephen Chow
Stephen Chow
周星驰
周星驰
Stephen Chow
Stephen Chow
周星驰
周星驰
Stephen Chow
Stephen Chow
车保罗
车保罗
Paul Che
Paul Che
张学友
张学友
Jacky Cheung
Jacky Cheung
章子怡
Zhang Ziyi
章子怡
Zhang Ziyi
章子怡

2. 待抽取文章的导入

1) 爬取数据

为了获取到大量的电影和演员相关文章,我们直接套用之前的半结构化数据爬虫来获取非结构文本articles.txt。 这一步在先前的windows环境下完成

cmd中执行命令:scrapy crawl 项目名

1
2
3
4
PS C:\d\mmm\pycharm\deepdive\udf\baidu_baike\baidu_baike> scrapy crawl baidu
2019-10-16 16:06:06 [scrapy.utils.log] INFO: Scrapy 1.7.3 started (bot: baidu_baike)
2019-10-16 16:06:06 [scrapy.utils.log] INFO: Versions: lxml 4.4.1.0, libxml2 2.9.5, cssselect 1.1.0, parsel 1.5.2, w3lib 1.21.0, Twisted 19.7.0, Python 3.7.4 (tags/v3.7.4:e09359112e, Jul 8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)], pyOpenSSL 19.0.0 (OpenSSL 1.1.1c 28 May 2019), cryptography 2.7, Platform Windows-10-10.0.18362-SP0
2019-10-16 16:06:06 [scrapy.crawler] INFO: Overridden settings: {'BOT_NAME': 'baidu_baike', 'NEWSPIDER_MODULE': 'baidu_baike.spiders', 'SPIDER_MODULES': ['baidu_baike.spiders'], 'USER_AGENT': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}

2) 数据转换

接下来为了将其导入到数据库中,需要将其转换为csv格式,这里可以使用程序 udf/trans.py 进行转换。再更改名成input/articles.csv即可。 这一步在先前的windows环境下完成

1
2
3
C:\my\Python\python.exe C:/d/mmm/pycharm/deepdive/udf/trans.py

Process finished with exit code 0

3) app.ddlog 中定义相应的数据表

在 app.ddlog 中建立相应的 articles 表:

1
2
3
4
5
@source
articles(
id text,
content text
).

4) 编译及生成数据表

因为下面的 stanford_nlp 进行句法分析时速度特别的慢,因此我抽取出 articles.csv 的头10 行进行实验。
a. 执行 ‘’’ deepdive do articles ‘’’ 将文章导入到 postgresql中

1
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive compile && deepdive do articles

b. 验证是否成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive query '?- articles(id, _).'
id
----
0
1
2
3
4
5
6
7
8
9
10
(11 rows)

四. 文本处理

1. 用 stanford_nlp 模块进行文本处理

deepdive 默认采⽤standfor nlp进⾏⽂本处理。输⼊⽂本数据,nlp模块将以句子为单位,返回每句的分词、lemma、pos、NER和句法分析的结果,为后续特征抽取做准备。我们将这些结果存入sentences表中。

1) app.ddlog 中定义相应的数据表

首先在 app.ddlog 中建立 sentences 表:

1
2
3
4
5
6
7
8
9
10
11
12
13
@source
sentences(
doc_id text,
sentence_index int,
sentences_text text,
tokens text[],
lemmas text[],
pos_tags text[],
ner_tags text[],
doc_offsets int[],
dep_types text[],
dep_tokens int[]
).

2) app.ddlog 中定义相应的函数

而后定义NLP 处理的函数 nlp_markup 来调用自定义的脚本 udf/nlp_markup.sh 进行文本处理。 我们需要对数据处理的方法,deepdive只是个框架,具体要怎么处理需要我们告诉他。所以我们要定义函数来处理articles让他变成sentences。

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

说明:

function用来定义函数,后面nlp_markup 是函数名 over后面接的是参数表。
returns 说明了函数返回的形式,返回就像我们前面定义的sentences那样的一行。
最后一句说明了我们这个程序文件是udf/nlp_markup.sh ,输入是tsv的一行。

3) app.ddlog 中定义相应的函数调用

使用如下语法调用 nlp_markup 函数,将函数的输出存储到sentences 表中:

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

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

4) 编写 nlp_markup.sh

udf/nlp_markup.sh 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env bash
# A shell script that runs Bazaar/Parser over documents passed as input TSV lines
#
# $ deepdive env udf/nlp_markup.sh doc_id _ _ content _
##
set -euo pipefail
cd "$(dirname "$0")"

: ${BAZAAR_HOME:=$PWD/bazaar}
[[ -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

# convert input tsv lines into JSON lines for Bazaar/Parser


# start Bazaar/Parser to emit sentences TSV
tsv2json "$@" |
"$BAZAAR_HOME"/parser/run.sh -i json -k doc_id -v content

说明:

所有#开头的(除了#!)都是普通注释
参数的用法(

  • $0:调用文件使用的文件名,带有前面的路径,
  • $1-∞:传给脚本的各个参数,
  • $@,$*:这两个都表示传入的所有参数,
  • $#:表示传入参数的个数)
    第一行指定了脚本的执行程序
    第六行指定了一些程序的错误处理方式等(详见Shell相关文档)
    第七行改变当前目录到nlp_markup.py 所在目录,也就是udf 目录
    第九行设置了一个变量BAZZER_HOME 他的值是bazaar 的路径
    第10-13行执行/parser/target/start 文件,如果有错会不正常退出,并提示
    第15-17行检查输入参数的正确性,看参数个数是不是大于0个,如果没有参数,自己设定参数名
    第23-24行把全部输入的参数用tsv2json 工具转换成json 格式,然后在执行parser/run.sh 并以刚才的json 作为参数输入。

4) 编译及生成数据表

a. 编译并执行deepdive compile && deepdive do sentences 生成 sentences 表。
预告:运行很慢,耐心等待

1
2
3
4
5
6
7
8
9
10
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# chmod 777 udf/bazaar/parser/run.sh
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# chmod 777 udf/nlp_markup.sh

root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive compile && deepdive do sentences

loading dd_tmp_sentences: 0:00:31 0 B [ 0 B/s] ([ 0 B/s])2019-10-17 10:01:41.117623 Reading POS tagger model from edu/stanford/nlp/models/pos-tagger/chinese-distsim/chinese-distsim.tagger ... done [2.1 sec].
2019-10-17 10:01:41.118162 Adding annotator lemma
loading dd_tmp_sentences: 0:00:42 0 B [ 0 B/s] ([ 0 B/s])2019-10-17 10:01:52.480759 Loading classifier from edu/stanford/nlp/models/ner/chinese.misc.distsim.crf.ser.gz ... done [11.3 sec].
loading dd_tmp_sentences: 0:00:43 0 B [ 0 B/s] ([ 0 B/s])2019-10-17 10:01:53.716363 Loading parser from serialized file edu/stanford/nlp/models/lexparser/chineseloading dd_tmp_sentences: 0:00:44 0 B [ 0 B/s] ([ 0 B/s])2019-10-17 10:01:53.943866 Parsing document 0...
......

b. 您可以通过以下命令来查询生成的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive query '
doc_id, index, tokens, ner_tags | 5
?- sentences(doc_id, index, text, tokens, lemmas, pos_tags, ner_tags, _, _, _).
'

doc_id | index | tokens | ner_tags
--------+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------
0 | 1 | {周星驰,,,1962年,6月,22日,生,于,香港,,,祖籍,浙江,宁波,,,中国,香港,演员,、,导演,、,编剧,、,制作人,、,商人,,,毕业于,无线,电视,艺员,训练班,。} | {PERSON,O,MISC,MISC,MISC,O,O,GPE,O,O,GPE,GPE,O,GPE,GPE,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O}
0 | 2 | {1980年,成为,丽的,电视台,的,特约,演员,,,从而,进入,演艺圈,。} | {O,O,O,O,O,O,O,O,O,O,O,O}
0 | 3 | {1981年,出演,个人,首部,电视剧,《,IQ,成熟,时,》,。} | {O,O,O,O,O,O,MISC,MISC,MISC,O,O}
0 | 4 | {1988年,将,演艺,事业,的,重心,转向,大,银幕,,,并,于,同,年,出演,电影,处女,作,《,捕,风,汉子,》,。} | {O,O,O,O,O,O,O,O,O,O,O,O,MISC,MISC,O,O,O,O,O,MISC,MISC,MISC,O,O}
0 | 5 | {1990年,凭借,喜剧片,《,一,本,漫画,闯,天涯,》,确立,其,无厘头,的,表演,风格,(,1,),;,同年,,,因其,主演,的,喜剧,动作片,《,赌圣,》,打破,香港,地区,票房,纪录,而,获得,关注,(,2,),。} | {O,O,O,O,MISC,MISC,MISC,MISC,MISC,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,MISC,O,O,GPE,O,O,O,O,O,O,O,O,O,O}
(5 rows)

五. 实体抽取及候选实体对的生成

本部分包含两步:

  • 获取候选实体
    • 获取演员候选实体
    • 获取电影候选实体
  • 生成候选实体对,即演员-电影实体对

1.候选实体的生成

1) app.ddlog 中定义相应的数据表

首先介绍演员候选实体的生成。首先我们在app.ddlog 中定义实体数据表:

1
2
3
4
5
6
7
8
9
@extraction
actor_mention(
mention_id text,
mention_text text,
doc_id text,
sentences_index int,
begin_index int,
end_index int
).

该表包含了实体的id、内容、所在文本的id、所在句子的索引、起始和终止位置索引。

2) app.ddlog 中定义相应的函数

而后继续定义实体抽取函数:

1
2
3
4
5
6
7
8
function map_actor_mention over(
doc_id text,
sentence_index int,
tokens text[],
pos_tags text[],
ner_tags text[]
) returns rows like actor_mention
implementation "udf/map_actor_mention.py" handles tsv lines.

其中 udf/map_actor_mention.py 脚本遍历数据库中的句子,找到连续的NER标记为PERSON 且 POS 标记为NR的序列,再对其做过滤整合处理,返回候选实体。

3) app.ddlog 中定义相应的函数调用

最后我们在 app.ddlog 中调用函数,将 函数的输出存储到 actor_mention 表中。

1
2
3
4
actor_mention += map_actor_mention(
doc_id, sentence_index, tokens, pos_tags, ner_tags
) :-
sentences(doc_id, sentence_index, _, tokens, _, pos_tags, ner_tags, _, _, _).

4) 编译及生成数据表

现在我们可以编译并执行得到 actor_mention 表了。

1
2
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# chmod 777 udf/map_actor_mention.py
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive compile && deepdive do actor_mention

5) 生成电影类的实体表

同理可以得到电影类的实体表 movie_mention :

a. 在app.ddlog 中定义相应的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@extraction
movie_mention(
mention_id text,
mention_text text,
doc_id text,
sentences_index int,
begin_index int,
end_index int
).

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

movie_mention += map_movie_mention(
doc_id, sentence_index, tokens, pos_tags, ner_tags
) :-
sentences(doc_id, sentence_index, _, tokens, _, pos_tags, ner_tags, _, _, _).

b. 编译并执行

1
2
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# chmod 777 udf/map_movie_mention.py
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive compile && deepdive do movie_mention

c. 查询看一下得到的实体:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive query '
mention_id, mention_text, doc_id | 5
?- movie_mention(mention_id, mention_text, doc_id, _, _, _).
'

mention_id | mention_text | doc_id
------------+--------------+--------
0_5_28_28 | 赌圣 | 0
0_7_6_6 | 大话西游 | 0
0_7_11_11 | 华语 | 0
0_8_6_6 | 喜剧 | 0
0_9_4_4 | 少林足球 | 0
(5 rows)

2. 生成候选实体对

1) app.ddlog 中定义相应的数据表

这一步我们要生成候选实体对,首先定义数据表如下:

1
2
3
4
5
6
7
@extraction
play_candidate(
p1_id text,
p1_name text,
p2_id text,
p2_name text
).

2) app.ddlog 中定义相应的统计每个句⼦的实体数

包含实体1/2 的id 和内容。接下来统计每个句子的实体数量以限制同一句内出现过多实体:

1
2
3
num_entity(doc_id, sentence_index, COUNT(p) + COUNT(q)) :-
actor_mention(p, _, doc_id, sentence_index, _, _),
movie_mention(q, _, doc_id, sentence_index, _, _).

3) app.ddlog 中定义相应的函数

而后定义过滤函数:

1
2
3
4
5
6
7
function map_play_candidate over (
p1_id text,
p1_name text,
p2_id text,
p2_name text
) returns rows like play_candidate
implementation "udf/map_play_candidate.py" handles tsv lines.

该函数内您可以定义一些规则对候选实体对进行筛选。

4) app.ddlog 中定义相应的函数调用

接下来调用上述函数并结合一些规则对实体对进行进一步的筛选,将筛选结果存储到 play_candidate 数据表中:

1
2
3
4
5
6
7
play_candidate += map_play_candidate(p1, p1_name, p2, p2_name) :-
num_entity(same_doc, same_sentence, num_e),
actor_mention(p1, p1_name, same_doc, same_sentence, p1_begin, _),
movie_mention(p2, p2_name, same_doc, same_sentence, p2_begin, _),
num_e < 5,
p1_name != p2_name,
p1_begin != p2_begin.

5) 编译及生成数据表

a. 编译并执行得到候选实体对表:

1
2
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# chmod 777 udf/map_play_candidate.py
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive compile && deepdive do play_candidate

b. 查询一下看看结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive query '
p1_text, p2_text | 5
?- play_candidate(_, p1_text, _, p2_text).
'

p1_text | p2_text
--------------+----------
周星驰 | 滕王阁序
周星驰 | 北斗
龙炳基 | 北斗
赵子龙 | 生命
郑佩佩 | 审死官
(5 rows)

六. 数据处理

1. 特征抽取

现在我们要用deeodive自带的 ddlib 库抽选实体对的文本特征。

1) app.ddlog 中定义相应的数据表

首先定义特征表:

1
2
3
4
5
6
@extraction
play_feature(
p1_id text,
p2_id text,
feature text
).

该特征是实体对间一系列文本特征的集合。

2) app.ddlog 中定义相应的函数

而后我们定义特征提取函数得到各种 POS/NER/次序列的窗口特征等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function extract_play_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 play_feature
implementation "udf/extract_play_features.py" handles tsv lines.

3) app.ddlog 中定义相应的函数调用

而后调用该函数:

1
2
3
4
5
6
7
play_feature += extract_play_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
) :-
actor_mention(p1_id, _, doc_id, sent_index, p1_begin_index, p1_end_index),
movie_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).

4) 编译及生成数据表

a. 编译并执行:

预告:运行很慢,耐心等待……

1
2
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# chmod 777 udf/extract_play_features.py
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive compile && deepdive do play_feature

b. 查询看一下特征:

1
2
3
4
5
6
7
8
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive query '| 5 ?- play_feature(_, _, feature).'

IS_INVERTED
INV_WORD_SEQ_[》 是 2006年 上映 的 一 部 宫廷 悲剧 电影 , 该 片 根据 莎士比亚 名剧 《 哈姆雷特 》 改编 , 由 冯小刚 导演 , 主要 演员 有 章子怡 、 葛优 、 吴彦祖 、]
INV_LEMMA_SEQ_[》 是 2006年 上映 的 一 部 宫廷 悲剧 电影 , 该 片 根据 莎士比亚 名剧 《 哈姆雷特 》 改编 , 由 冯小刚 导演 , 主要 演员 有 章子怡 、 葛优 、 吴彦祖 、]
INV_NER_SEQ_[O O MISC O O O O O O O O O O O O O O MISC O O O O PERSON O O O O O PERSON O PERSON O PERSON O]
INV_POS_SEQ_[PU VC NT VV DEC CD M NN NN NN PU DT NN P NR NN PU NR PU VV PU P NR NN PU JJ NN VE NR PU NR PU NR PU]
(5 rows)

2. 有监督数据处理

1) app.ddlog 中定义相应的数据表

首先在 app.ddlog 中定义 play_label 表存放有监督数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
@extraction             
play_label(
@key
@references(relation="has_play", column="p1_id", alias="has_play")
p1_id text,
@key
@references(relation="has_play", column="p2_id", alias="has_play")
p2_id text,
@navigable
label int,
@navigable
rule_id text
).

rule_id 表示相关性的规则名称,label 为正值表示正相关,负值表示负相关。绝对值越大,相关性越大。

2) app.ddlog 中定义,初始化定义

初始化定义,复制 play_candidate 表,label 初始化为0,rule_id 为 NULL:

1
paly_label(p1, p2, 0, NULL) :- play_candidate(p1, _, p2, _).

2) app.ddlog 中定义,导入

接下来将最开始导入的有监督数据表 actor_movie_dbdata 导入到 play_label 中,并赋予权重3:

1
2
3
4
play_label(p1, p2, 3, "from_dbdata") :-
play_candidate(p1, p1_name, p2, p2_name),
actor_movie_dbdata(n1, n2),
[lower(n1) = lower(p1_name), lower(n2) = lower(p2_name)].

3. 预标记

接下来定义一些逻辑规则对文本进行预标记

1) app.ddlog 中定义相应的数据表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function supervise over (      
p1_id text, p1_begin int, p1_end int,
p2_id text, p2_begin int, p2_end int,
doc_id text,
doc_id text,
sentence_index int,
sentence_text text,
tokens text[],
lemmas text[],
pos_tags text[],
ner_tags text[],
dep_types text[],
dep_tokens int[]
) returns (p1_id text, p2_id text, label int, rule_id text)
implementation "udf/supervise_play.py" handles tsv lines.

程序 udf/supervise_play.py 里通过一些指定的规则如 出演这种特征来进行预标记。给出label和rule_id的值。

2) app.ddlog 中定义相应的函数调用

接下来调用标记函数,将规则抽到的数据写到play_label 表中:

1
2
3
4
5
6
7
8
9
10
11
12
play_label += supervise(
p1_id, p1_begin, p1_end,
p2_id, p2_begin, p2_end,
doc_id, sentence_index, sentence_text,
tokens, lemmas, pos_tags, ner_tags, dep_types, dep_tokens_indexes
) :-
play_candidate(p1_id, _, p2_id, _),
actor_mention(p1_id, p1_text, doc_id, sentence_index, p1_begin, p1_end),
movie_mention(p2_id, p2_text, _, _, p2_begin, p2_end),
sentences( doc_id, sentence_index, sentence_text,
tokens, lemmas, pos_tags, ner_tags, _, dep_types, dep_tokens_indexes
).

3) app.ddlog 中定义,最终标记

由于不同的规则可能覆盖了相同的实体对,因此利用 vote方法进行综合给出最终标记:

1
2
play_label_resolved(p1_id, p2_id, SUM(vote)) :-
play_label(p1_id, p2_id, vote, rule_id).

4) 编译及生成数据表

最后编译并执行:

1
2
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# chmod 777 udf/supervise_play.py
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive compile && deepdive do play_label_resolved

4. 变量表定义

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

1) app.ddlog 中定义相应的数据表

1
2
3
4
5
@extraction
has_play?(
p1_id text,
p2_id text
).

2) app.ddlog 中定义,写入已知的变量

根据打标结果,写入已知的变量:

1
2
3
4
has_play(p1_id, p2_id) = if l > 0 then TRUE
else if l < 0 then FALSE
else NULL end :-
play_label_resolved(p1_id, p2_id, l).

3) 编译及生成数据表

此时表中部分变量的label 已知,成为了先验变量。编译并执行:

1
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive compile && deepdive do has_play

5. 构建因子图

1) app.ddlog 中定义相应的,指定特征

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

1
2
3
4
@weight(f)
has_play(p1_id, p2_id) :-
play_candidate(p1_id, _, p2_id, _),
play_feature(p1_id, p2_id, f).

2) 编译及生成数据表

a. 编译并生成最终的概率模型:

1
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive compile && deepdive do probabilities

b. 就完成了我们的推断,现在查询我们预测的演员-电影间的交易关系概率:

1
2
3
4
5
6
7
8
9
10
root@ubuntu-mmm:/usr/local/CNdeepdive/transaction2# deepdive sql "SELECT p1_id, p2_id, expectation FROM has_play_label_inference ORDER BY random() LIMIT 5"

p1_id | p2_id | expectation
------------+------------+-------------
6_38_20_20 | 6_38_44_44 | 0.926
0_30_36_36 | 0_30_57_57 | 0.082
0_39_83_83 | 0_39_94_95 | 0.214
6_21_7_8 | 6_21_43_43 | 0.003
5_66_0_0 | 5_66_20_21 | 0.008
(5 rows)

六. 参考

  1. deepdive python3 环境下多种实体关系抽取流程

  2. 支持中文的deepdive:斯坦福大学的开源知识抽取工具(三元组抽取)