知识图谱嵌入技术实践和资料

1,414 阅读8分钟

「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战

师傅领进门

【ECAI 2020.09.04】Knowledge Graph Embeddings: From Theory to Practice www.bilibili.com/video/BV17z…

image.png

1. KGE理论

1.1 引言

  • KG相关介绍
  • CWA和OWA的介绍:封闭世界假设和开放世界假设
  • KG在ML上的主要任务:连接预测/三元组分类(重点)、协同结点分类/链接聚类、实体匹配
  • 重点介绍【连接预测(信息搜索任务 - 排序任务) 、 三元组分类(分类任务 - 二分类任务)】
  • 传统模式下的关系学习方法:基于规则约束、基于图模型(CRF、PRM、RMN、RDN)缺点是受限于KG的大小方法都不可微,模型能力有限。
  • 借鉴表示学习思想,基于图表示学习的关系学习方法:Node Representation(PRA、LINE、DeepWalk、node2vec)、Graph Neural Networks(GNNs、GCNs、Graph Attention Networks)、Knowledge Graph Embeddings (TransE、DistMult、ComplEX、ConvE)
  • 简单看一下KGE的经历

1.2 KGE model

  • 整体框架(优化器、排序层、评分函数、损失函数、负采样)
  • 评分函数
    • Translation-based Scoring Functions {TransE、RotatE} 平移模型
    • Factorization-based Scoring Functions {RESCAL、DistMult、ComplEx(复数空间)} 分解模型
    • Deeper Scoring Functions (ConvE、ConvKB) 深度模型
    • Other Recent Models(HolE、SimplE、QuatE、MurP、...)
  • 损失函数
    • 对间隔 - 合页损失函数 Hing Loss (源于SVM的软间隔)
    • 负采样 - 似然函数/交叉熵
    • 二元交叉熵
    • 自对抗损失函数
    • ...
  • 正则化方法
    • L1、L2、L3
    • Dropout(ConvE)
  • 初始化方法
    • Random(Uniform、Normal) 使用不同的分布函数初始化
    • Glorot
  • 负采样
    • Local ClosedWorld Assumption 局部世界封闭假设
    • 其假定关系是唯一的,选择不同s和o作为不正确(退化)的对象。
    • 方式: Uniform sampling(随机) 、 Completeset(全集) 、1-n scoring(batch)
  • 训练步骤和优化器
    • 优化器:SGD(Adam、...)
    • Reciprocal Triples 逆向三元组
  • 模型选择
    • 网格搜索
    • 随机搜索
    • 准搜索 + 贝叶斯

1.3 评估和评测

  • Evaluation Metrics
    • Mean Rank (MR) 越小越好
    • Mean Reciprocal Rank (MRR) 越大越好
    • Hits@N 越大越好
  • Benchmark Datasets
    • FB15K - 237
    • WNI18RR
    • YAGO3-10
  • SOTA Results
    • ...

1.4 高级KGE主题

  • Calibration 校准
    • 主应用于在对模型可解释性要求较高的场景,如药物发现、蛋白质预测、金融风控
  • Multimodal Knowledge Graphs 多模态知识图谱
  • Temporal Knowledge Graphs 时序知识图谱
  • Uncertain Knowledge Graphs 不确定知识图谱
  • Robustness 稳健性 (安全方向、对抗扰动)
  • KGE & Neuro-Symbolic Reasoning KGE&神经符号推理
    • Neural Theorem Provers (NTP) 神经定理证明器
    • Analogical Reasoning 类比推理
  • Answering Complex Queries 回答复杂问题 (Query2vec 使用盒型Embeddings)

1.5 未来研究导向

  • MORE EXPRESSIVE MODELS 更强表现力的模型
  • SUPPORT FOR MULTIMODALITY 支持多模态
  • ROBUSTNESS & INTERPRETABILITY 稳健性和可解释性
  • BETTER BENCHMARKS 更好的基准
  • BEYOND LINK PREDICTION 超越现有的链接预测的现状
  • NEURO-SYMBOLIC INTEGRATION 神经符号融合

2. KGE应用

  • Pharmaceutical Industry
  • Human Resources
  • Products
  • Food & Beverage

3. KGE相关软件依赖库介绍

  • OpenKE
  • AmpliGraph
  • DGL-KE

4. KGE实践

使用软件:AmpliGraph python环境:python3.7 >= 3.7 深度学习环境:tensorflow >= 1.15.2

5.TransE实战代码

TransE是KGE的开山之作(2013年),其借鉴了word2vec论文中“语义平移不变形”的思想,将平移不变性转移到三元组<s,p,o>中,通过||h+r-t||==0来确定关系和向量化知识图谱表示。后续很多KGE模型都是在TrasnE的基础上进行改善。

TransE的缺点是无法解决一对多、多对多的关系。

如何理解一对一,一对多,多对多?b站有个up解释的非常好。链接

  • 如果只简单考虑 h+r==t 那么 司马懿的几个小妾 的向量会很相近 ,会出现张夫人等于伏夫人的情况。
  • 自反关系 (曹操 - 欣赏 - 曹操)那么欣赏就为0了,当(曹操 欣赏 司马懿)就等价于 曹操 等于司马懿,当然在真实迭代下不会如此,因为真实环境下类似(曹操 欣赏 司马懿)的例子占大多数,所以 (曹操 - 欣赏 - 曹操)会被当成噪声处理影响模型效果。

方法一 lightKG

lightKG简介

  • lightKG是一个基于Pytorch和torchtext的知识图谱深度学习框架,涵盖知识图谱领域的一些简单算法,具有轻量、简单等特点,适合知识图谱领域的初学者。github地址
  • 使用时,先从lightKG导入算法模型,创建对应的模型对象,然后调用模型对象的train方法训练模型,并保存训练好的模型;在测试时,先加载训练好的模型,然后进行测试,以x目录下的模型Y为例:
from lightkg.x import Y  # 导入算法模型
Ymodel = Y()  # 创建模型对象
Ymodel.train(...)  # 训练模型和保存
Ymodel.load(...)  # 加载训练好的模型
Ymodel.test(...)  # 测试模型
  • 方法概述:

TransE将关系看成实体间的转移,即:如果三元组(头实体,关系,尾实体)成立,头实体向量h与关系向量r的和与尾实体向量t相近,否则远离。

任务描述

  • 知识图谱中的知识通常以(头实体,关系,尾实体)的三元组形式表达。
  • 链接预测旨在给定三元组中的任意两个元素,预测第三个元素,即(?,关系,尾实体),(头实体,关系,?)和(头实体,?,尾实体),其中?表示待预测的元素,分别称为头实体预测,尾实体预测和关系预测。
  • 数据集: 来自github的链接预测数据集,可以从这里下载。每行有三个字段,用“,”分隔,分别表示头实体,关系和尾实体,数据样例如下:
科学,包涵,自然、社会、思维等领域
科学,外文名,science
科学,拼音,kē xué
科学,中文名,科学
科学,解释,发现、积累的真理的运用与实践

所需依赖

测试环境 Python 3.6.8 Pytorch 1.4.0
# 所需依赖---
torchtext>=0.4.0
tqdm>=4.28.1
torch>=1.0.0
pytorch_crf>=0.7.0
scikit_learn>=0.20.2
networkx>=2.2
revtok
jieba
regex
---------------
# 运行前需要按如下方式安装lightKG库 
!pip install -i https://pypi.douban.com/simple/ lightKG。

TransE训练

基于上述转移假设,TransE设计三元组的得分函数为:
f(h,r,t)=h+rtL1/L2f(h,r,t)=-{||\mathbf h +\mathbf r-\mathbf t ||}_{L_1/L_2}

即用L1L_1L2L_2范数衡量距离(本教程采用L1L_1范数)。得分函数用于衡量三元组有效的可能性,得分越高,三元组越可能有效。因此,正例三元组的得分高,负例三元组的得分低。由于关系数量相对较少,负例只通过替换头实体或尾实体得到。

基于上述原则建模知识图谱中的正例三元组及其对应的负例三元组,类似支持向量机,最小化基于Margin的损失,使正例的得分比负例的得分至少高一个 Margin γ\gamma,即:

L=(h,r,t) (h,r,t)max(0,f(h,r,t)+γf(h,r,t))L=\sum_{\left(h,r,t \right) \in \bigtriangleup}\ {\sum_{\left(h',r,t' \right) \in \bigtriangleup'}{\max \left(0, f\left(h, r, t \right) + \gamma-f\left(h', r, t' \right) \right)}}

其中,\bigtriangleup为知识图谱中的正例三元组集合,\bigtriangleup'为基于\bigtriangleup,通过替换其中正例三元组的头实体或尾实体得到的负例三元组集。最小化该损失得到实体和关系的向量表示。

# 查看数据集
import pandas as pd
train = pd.read_csv('datasets/train.sample.csv',header=None)
train.head(20)

import os
from lightkg.krl import KRL
from lightkg.krl.config import DEFAULT_CONFIG
# 修改epoch,默认1000
DEFAULT_CONFIG['epoch']=10
# 数据路径
dataset_path = 'datasets/train.sample.csv'
model_type = 'TransE'
# 初始化实例
krl = KRL()
if not os.path.exists('./temp/models'):
    os.makedirs('./temp/models')
# 训练
krl.train(dataset_path,
          model_type=model_type,
          dev_path=dataset_path,
          save_path='./temp/models/LP_{}'.format(model_type))

预测

# 读取 模型
krl.load(save_path='./temp/models/LP_{}'.format(model_type), model_type=model_type)
krl.test(dataset_path)

读取模型后调用对应的predict_head、predict_tail、predict_rel 即可预测头尾实体或关系。

# 打印函数
def topk_print(l,name):
    print("{}预测:".format(name))
    for i in l:
        print(i)
    print()
        
# 头实体预测
head_pred = krl.predict_head(rel='外文名', tail='science', topk=3)
# 尾实体预测
tail_pred = krl.predict_tail(head='科学', rel='外文名', topk=3)
# 关系预测
relation_pred = krl.predict_rel(head='科学', tail='science', topk=3)

print("三元组:科学 - 外文名 - science \n")
topk_print(head_pred,"头实体")
topk_print(tail_pred,"尾实体")
topk_print(relation_pred,"关系")

方法二 AmpliGraph

ECAI 2020 给出很好的视频讲解和jupyter notebook指导

注意:ampligraph 需要tensorflow1.14.0及以上版本

ECAI_2020_KGE_Tutorial_Hands_on_Session.ipynb

方法三 dgl-ke (命令行训练)

dgl-ke是亚马逊出品的KGE工具,依赖dgl框架,dgl现已适配pytorch、mxnet、tensorflow深度学习框架,但目前dgl-ke只适配pytorch,且仅可在Ubuntu或maxOS系统上通过命令行执行,可以再colab训练,反正只是拿一个Embedding。

# 使用colab加载dgl-ke训练KGE
# 使用命令行创建data文件夹,手动或者request获取文件
# 参考https://github.com/MaastrichtU-IDS/KGRulEm/blob/7a696485f9506ba6af886b6cc86658a5fa6c696b/embeddings/Train_embeddings.ipynb
!mkdir my_task

# 处理自定义文件
import os
import numpy as np
import pandas as pd

triples_path = "./data/freebase-237-merged-and-remapped.csv"
df = pd.read_csv(triples_path, names=['sub', 'pred', 'obj'])
triples = df.values.tolist()
print(len(triples))
# Please make sure the output directory exist.
seed = np.arange(num_triples)
np.random.seed(666)
np.random.shuffle(seed)
train_cnt = int(num_triples * 0.9)
valid_cnt = int(num_triples * 0.05)
train_set = seed[:train_cnt]
train_set = train_set.tolist()
valid_set = seed[train_cnt:train_cnt+valid_cnt].tolist()
test_set = seed[train_cnt+valid_cnt:].tolist()

with open("./data/FB15K237_train.tsv", 'w+') as f:
    for idx in train_set:
        f.writelines("{}\t{}\t{}\n".format(triples[idx][0], triples[idx][1], triples[idx][2]))
        
with open("./data/FB15K237_valid.tsv", 'w+') as f:
    for idx in valid_set:
        f.writelines("{}\t{}\t{}\n".format(triples[idx][0], triples[idx][1], triples[idx][2]))

with open("./data/FB15K237_test.tsv", 'w+') as f:
    for idx in test_set:
        f.writelines("{}\t{}\t{}\n".format(triples[idx][0], triples[idx][1], triples[idx][2]))

# 使用命令行
!DGLBACKEND=pytorch dglke_train --dataset FB15K237 --data_path ./data --data_files FB15K237_train.tsv FB15K237_valid.tsv FB15K237_test.tsv --format 'raw_udd_hrt' --model_name TransE_l2 --dataset FB15K237 --batch_size 1000 \
--neg_sample_size 200 --hidden_dim 400 --gamma 19.9 --lr 0.25 --max_step 500 --log_interval 100 \
--batch_size_eval 16 -adv --regularization_coef 1.00E-09 --test --num_thread 1 --num_proc 8

其他代码实现参考资料

[1] TransE论文详解及代码复现
[2] transE知识图谱补全,FB15K-237数据集(python实现)
[3] 浅析知识图谱嵌入技术的基本代码思想
[4] [KG笔记]十、知识图谱嵌入(KG Embedding)

NLP萌新,才疏学浅,有错误或者不完善的地方,请批评指正!!