双线性模型(⼀)(RESCAL、LFM、DistMult)
今天开始,就要开始阅读双线性模型的⽂章了。⼤约有⼗七⼋篇⽂章,都是在综述经常见到的经典双线性模型,计划在⼋⽉中旬之前看完。虽然后⾯不会去做这类⽅法,但是作
力透纸背
为这个领域的研究者,觉得还是应该读⼀读,否则总感觉⾃⼰的知识体系是有漏洞的。
开题报告⾥对于这⼀类模型的简介:
语义匹配模型采⽤基于相似性的打分函数,通过匹配实体和关系在嵌⼊向量空间的潜在语义衡量三元组事实成⽴的可能性。该类模型的典型代表有:RESCAL[28]、
DistMult[29]、HolE[30]、ComplEx[31]、ANALOGY[32]、SEEK[50]等。RESCAL[28]⼜称双线性模型,该模型⽤向量表⽰实体,⽤矩阵表⽰关系,并通过⾃定义的打
分函数捕捉三元组的内部交互。DistMult[29]通过将RESCAL的关系矩阵限制为对⾓矩阵对其进⾏了简化。HolE(Holographic Embedding)[30]结合了RESCAL的表
⽰能⼒与DistMult的简洁⾼效,将实体和关系都表⽰为空间中的向量,并定义了头尾实体进⾏交互的循环关联操作,操作结果与关系的表⽰进⾏匹配以计算三元组得
分。ComplEx(Complex Embedding)[31]在DistMult的基础上引⼊复值嵌⼊,实体和关系的embedding不再位于实值空间⽽是复空间。此外ComplEx的三元组打分
函数并⾮对称形式,对于⾮对称关系类型的三元组可根据头尾实体的位置关系得到不同的得分,从⽽可以更好地建模⾮对称关系。ANALOGY[32]在RESCAL的基础
上进⾏扩展,以更好地建模实体和关系的推理属性。它采⽤了和RESCAL同样的双线性函数作为三元组打分函数。 SEEK(Segmented Embedding of Knowledge)
[50]针对现有模型的表⽰能⼒与复杂度不能兼顾的问题,提出轻量级的嵌⼊框架,核⼼思想是对实体和关系进⾏分段嵌⼊,并通过段间组合计算三元组得分,可以在
不增加模型复杂度的情况下获得较好的表⽰能⼒,并实现对于对称和⾮对称关系类型的处理能⼒。
⽬录
RESCAL
【paper】 A Three-Way Model for Collective Learning on Multi-Relational Data
【简介】这篇⽂章应该算是双线性模型的开⼭之作。是德国的⼀个团队发表在 ICML 2011 上的⼯作,⽐较⽼了,主要思想是三维张量分解。
模型
定义了⼀个 tensor,m 是关系数,n 是实体数,每个关系对应于 tensor 中的⼀个 slice,即⼀个矩阵,每个矩阵相当于表⽰图的邻接矩阵。位置元素为 1 代表两个实体之间存在这
种关系,为 0 表⽰不存在。
对 tensor 进⾏分解:
A是 n×r 的矩阵,表⽰每个实体的隐性表⽰(latent-component reprentation),R k是 r×r 的⾮对称矩阵,建模第 k 个属性/关系中的实体 latent component 的交互。
矩阵A和R k通过约束最⼩化问题来计算:
特别要提的是R k是⾮对称矩阵,这样可以建模⾮对称关系,在同⼀个实体作为头实体或尾实体时会得到不同的 latent component reprentation。
其中,
更具体地,
(其实贴图时可以不⽤定义⾼度)
这样的分解机制可以利⽤相关实体提供的信息进⾏表⽰,类似推荐⾥的协同过滤,这⾥称为 collective learning,举了⼀个栗⼦:
以上就是 Rescal 的核⼼思想了,后⾯有⼏个⼩节讲和其他⽅法的联系以及计算 factorization 的⽅法,没有仔细看。
实验
collective classification
该实验使⽤⾃建的政党数据集,包括 93 个实体和 3 个关系,因此构建了 93×93×5 的 tensor。政党分类效果如下。
collective 实体消歧
实体消歧可以视为 isEqual 关系的链接预测,在 Cora 数据集上进⾏了实验:
除了上述两个实验,还在 Kinships, Nations 和 UMLS 数据集上进⾏了链接预测,并在 Nations 数据集上进⾏了聚类实验。并在各个数据集上进⾏了与其他两个算法的运⾏效率
的⽐较,不再贴图了。
代码
⽂章中说 Rescal 是⽤不超过 120 ⾏的 Python/Numpy实现的,但没有给出代码。Pykg2vec 实现了 Rescal,但我没有看明⽩,实现的⽐较巧妙。因为也没有打算做这块,就不
继续花时间研究了。
class Rescal(PairwiModel):
"""
`A Three-Way Model for Collective Learning on Multi-Relational Data`_ (RESCAL) is a tensor factorization approach to knowledge reprentation learning,
which is able to perform collective learning via the latent components of the factorization.
Rescal is a latent feature model where each relation is reprented as a matrix modeling the iteraction between latent factors. It utilizes a weight matrix which specify how much the latent features of head and tail entities interact in the relati Portion of the code bad on mnick_ and `OpenKE_Rescal`_.
Args:
config (object): Model configuration parameters.
.. _mnick: /mnick/rescal.py/blob/master/rescal/rescal.py
.. _OpenKE_Rescal: /thunlp/OpenKE/blob/master/models/RESCAL.py
.. _A Three-Way Model for Collective Learning on Multi-Relational Data : www.icml-2011/papers/438_icmlpaper.pdf
"""
def __init__(lf, **kwargs):
super(Rescal, lf).__init__(lf.__class__.__name__.lower())
param_list = ["tot_entity", "tot_relation", "hidden_size", "margin"]
param_dict = lf.load_params(param_list, kwargs)
lf.__dict__.update(param_dict)
<_embeddings = NamedEmbedding("ent_embedding", lf.tot_entity, lf.hidden_size)
nn.init.xavier_uniform_(lf.ent_embeddings.weight)
nn.init.xavier_uniform_(lf.rel_matrices.weight)
lf.parameter_list = [
<_embeddings,
]
lf.loss = Criterion.pairwi_hinge
def embed(lf, h, r, t):
""" Function to get the embedding value.
Args:
h (Tensor): Head entities ids.
r (Tensor): Relation ids of the triple.
t (Tensor): Tail entity ids of the triple.
Returns:
Tensors: Returns head, relation and tail embedding Tensors.
"""
k = lf.hidden_size
<_embeddings.weight.data = lf.get_normalized__embeddings, lf.tot_entity, dim=-1)
打印机扫描仪
emb_h = lf.ent_embeddings(h)
emb_r = lf.rel_matrices(r)
emb_t = lf.ent_embeddings(t)
emb_h = emb_h.view(-1, k, 1)
emb_r = emb_r.view(-1, k, k)
emb_t = emb_t.view(-1, k, 1)
return emb_h, emb_r, emb_t
def forward(lf, h, r, t):
h_e, r_e, t_e = lf.embed(h, r, t)
# dim of h: [m, k, 1]
# r: [m, k, k]
# t: [m, k, 1]
return -torch.sum(h_e * torch.matmul(r_e, t_e), [1, 2])
@staticmethod
def get_normalized_data(embedding, num_embeddings, p=2, dim=1):
norms = (embedding.weight, p, dim).data
return embedding.weight.data.div(norms.view(num_embeddings, 1).expand_as(embedding.weight))
在 FB15k 数据集上尝试运⾏了⼀下,效果很差:
【⼩结】本⽂⽤三维张量分解进⾏三元组嵌⼊。
LFM(Latent Factor Model)
【paper】 A latent factor model for highly multi-relational data
【简介】这篇⽂章是法国的研究团队发表在 NIPS 2012 上的⽂章,还挂了 Antoine Bordes 的名字。⽂章提出了 LFM(Latent Factor Model),主要贡献有两点:⼀是定义了unigram、bigram、trigram 三种⽅式组合的三元组打分函数;⼆是将关系矩阵分解为低阶矩阵的组合,这样可以实现参数共享。其实这种⽐较⽼的论⽂的表达⽅式、⾏⽂结构跟现在的论⽂都不太⼀样,再加上时间有限,所以没有看太明⽩。但这类模型终究是要过⼀遍的,就这样吧。
模型
⽂章在 intro 部分介绍了统计关系数据建模的现存难点:
1. 频繁出现的关系类型只是⼀⼩部分(长尾现象)
2. 数据存在噪声并且不完整
3. 数据集规模有限
⽂章称 LFM 是基于概率的,明确考虑了数据的不确定性。这⾥的不确定性应该不是指的实体和关系包含语义的不确定性,只是指对三元组进⾏概率打分。
早期的论⽂中三元组表⽰都是(subject, relation, object),若三元组成⽴,写作R i(S i,O k)=1。
表⽰及打分函数
logistic 模型进⾏了如下的定义:
介绍一位名人其中,ηi k(j)是⼀个线性函数:
贡献⼀:对打分函数ηi k(j)进⾏了重新定义
贡献⼆:对关系矩阵进⾏分解
当关系数量⽐较多时,每个关系下的样本很少,容易引起过拟合。之前的模型曾经使⽤两种解决⽅法,⼀是聚类,⼆是⽤向量表⽰关系。与 RESCAL 的使⽤⼀个通⽤矩阵进⾏参数化的⽅法不同,本⽂提出的解决⽅法是将关系矩阵分解为 d 秩⼀矩阵(不知道这⾥的“⼀矩阵”是不是指对⾓矩阵){Θr}1≤r≤d。
分解的稀疏性和d≪n r可以保证不同关系的参数共享。
Loss
模型训练的⽬标是最⼤化下⾯的 likelihood:
经过推导,可以得到 log-likelihood:
上午推导了⼀下,前半部分没有对上,可能中间有近似约减消掉的项。
训练⽬标等价于最⼩化负的 log-likelihood:
祛皱美白
实验
和 RESCAL ⼀样,在 Kinships、UMLS、Nations 数据集上进⾏了实验,与 RESCAL、MRC 和 SME 三个 baline 对⽐了 AUC 和 log-likelihood。
除了进⾏关系数据建模,实验部分还学习了动词的语义表⽰。这部分没细看。
代码
没有代码。
【总结】本⽂定义了 unigram、bigram、trigram 进⾏组合的线性打分函数,并对关系矩阵进⾏分解实现参数共享。
DistMult
【paper】 Embedding entities and relations for learning and inference in knowledge bas
【简介】这篇⽂章是康奈尔⼤学和微软的研究者发表在深度学习顶会⽆冕之王 ICLR 2015 上的⼯作,⽂章提出了 DistMult。模型的改进微乎其微,就是把双线性模型的关系矩阵限制为了对⾓矩阵,然后重点是⽤ embedding-bad 的⽅法做了规则挖掘。看⽂章署名的话应该都是中国⼈,⾏⽂结构也很典型,因此看起来感觉⽐上⼀篇舒服多了,⼤部分内容基本能看懂。
Intro 与 Related Work
⽂章将 TransE 和 NTN 都归类为神经⽹络,并且 motivation 来源于这两个模型:
1. 不同的设计如何影响学习结果
2. 链接预测实验只是间接展⽰低维 embedding 的效果,关系属性如何捕捉以及如何作⽤很难解释。
⽂章贡献如下:
1. 提出通⽤框架整合现有模型
2. 链接预测实验评价
3. 挖掘逻辑规则
(看 related work 有感:第⼀点是,⼀直不知道 related work 该写什么、怎么写。我写论⽂⼀个很⼤的问题是⼀开始的引⼊总是从很⼤很宏观的⾓度,本想由浅⼊深引到⾃⼰的⼯作上,但是由于⼀开始没有聚焦,并且⼀写开就刹不住车,所以会有⼀种顾左右⽽⾔他、⽂不对题的感觉,⼩论⽂、开题报告⾥都有这个问题。这篇的 related work 就是由浅⼊深,先列出 multi-relational learning 的⼀些⽅法,然后详细介绍了 NTN,然后引到⾃⼰的规则抽取⼯作(虽然中间少了点衔接)。以后我在写 related work 也要再聚焦⼀些,多说与⾃⼰⼯作有密切关联的相关⼯作;第⼆点是 DistMult 这篇⽂章,模型本⾝的改进⼏乎没有,很鸡肋,但是它把展⽰的重点放在了规则挖掘上,这就是扬长避短的作⽤了,就像⾐服的穿搭,⾝材不好也没有关系,关键是如何凸显优势、弱化劣势。)
模型
模型部分⽂章说,呈现的是⼀个通⽤的 NN 框架,讨论了不同设计的选择,并对⽐了效果。其实都是⽐较 naive 的东西,没什么新的。
实体表⽰
实体表⽰就是⽤ “one-hot” 向量查询实体矩阵:
NTN ⽤预训练的词向量做为实体的初始表⽰。
关系表⽰
关系的表⽰通常反映在打分函数中,打分函数通常被定义为线性、双线性或⼆者组合的转换函数:
⼏个模型的关系表⽰及打分函数:
本⽂只考虑最基本的双线性打分函数:
本⽂提出了将关系矩阵M r限制为对⾓矩阵(DistMult),这样可以将双线性模型的参数量减少到与 TransE 相同。
上⾯提出的通⽤框架同样适⽤于深层语义模型和多层 NN。
参数学习
和 TransE ⼀样使⽤负采样操作构建负样本,并定义 margin-loss:
实验
链接预测
在 WN 和 FB15k 上进⾏链接预测实验。
⽐较了五个模型(按照复杂度降序排列)的效果:
1. 4个 tensor slice 的 NTN
2. Bilinear + Linear:⼀个tensor slice 的 NTN,且只有线性层
3. TransE
4. Bilinear:最基本的双线性打分函数
5. Bilinear-diag:关系矩阵限制为对⾓矩阵的双线性模型
五个模型效果如下:
NTN 最复杂,但是效果最差,相反,最简单的 DistMult 效果最好。但是⽂中也提到了,将关系矩阵限制为对⾓矩阵丧失了对⾮对称关系建模的能⼒,这是 DistMult 的缺陷。
还在不同的关系类型上对⽐了乘法(bilinear-diag,即 DistMult)和加法(TransE,DistAdd)的特征交互的效果。
显然,DistMult ⽐ DistAdd 效果要好。
此外,还试验了使⽤⾮线性的投影函数 tanh,并使⽤预训练词向量进⾏实体表⽰的初始化。在预测实体时,利⽤实体类型信息进⾏结果过滤。
规则抽取
葡萄天蛾
规则抽取是本⽂的重要⼯作。逻辑规则有很重要的意义:
1. 可⽤于推断新事实进⾏ KB 补全
2. 优化数据存储,只存储逻辑规则⽐存储事实节省空间
3. ⽀持复杂推理
4. 为推断结果提供解释
⽂中说 embedding-bad 的规则挖掘不必受 KB 规模的影响,但后⾯做实验还是只做了两跳和三跳的,
不可能不受 KB 规模的影响。
该任务的⽬的就是挖掘如下的 Horn 规则:
⽤两种⽅式建模关系的组合:关系⽤向量表⽰的⽤加法(欧式距离),⽤矩阵表⽰的⽤乘法(Frobenius 范数)。
规则挖掘算法:
挖掘结果如下,横坐标代表挖掘的数量,纵坐标代表挖掘的质量/精度,DistMult 的效果是好于 AMIE 的。
并且,bilinear 在长路径下效果更好。
代码
原⽂没有给出代码,pykg2vec 给出了 DistMult 的实现
class DistMult(PointwiModel):
"""
`EMBEDDING ENTITIES AND RELATIONS FOR LEARNING AND INFERENCE IN KNOWLEDGE BASES`_ (DistMult) is a simpler model comparing with RESCAL in that it simplifies
the weight matrix ud in RESCAL to a diagonal matrix. The scoring
function ud DistMult can capture the pairwi interactions between
the head and the tail entities. However, DistMult has limitation on modeling asymmetric relations.
Args:
config (object): Model configuration parameters.
.. _EMBEDDING ENTITIES AND RELATIONS FOR LEARNING AND INFERENCE IN KNOWLEDGE BASES:
arxiv/pdf/1412.6575.pdf
消毒柜维修"""
def __init__(lf, **kwargs):
super(DistMult, lf).__init__(lf.__class__.__name__.lower())
param_list = ["tot_entity", "tot_relation", "hidden_size", "lmbda"]
param_dict = lf.load_params(param_list, kwargs)
lf.__dict__.update(param_dict)
num_total_ent = lf.tot_entity
num_total_rel = lf.tot_relation
k = lf.hidden_size
<_embeddings = NamedEmbedding("ent_embedding", num_total_ent, k)
nn.init.xavier_uniform_(lf.ent_embeddings.weight)
nn.init.xavier_uniform_(lf.rel_embeddings.weight)
李准基身高
lf.parameter_list = [
真实美女
<_embeddings,
]
lf.loss = Criterion.pointwi_logistic
def embed(lf, h, r, t):
"""Function to get the embedding value.
Args:
h (Tensor): Head entities ids.
r (Tensor): Relation ids of the triple.
t (Tensor): Tail entity ids of the triple.
Returns:
Tensors: Returns head, relation and tail embedding Tensors.
"""
h_emb = lf.ent_embeddings(h)
r_emb = lf.rel_embeddings(r)
t_emb = lf.ent_embeddings(t)
return h_emb, r_emb, t_emb
def forward(lf, h, r, t):
h_e, r_e, t_e = lf.embed(h, r, t)
return -torch.sum(h_e*r_e*t_e, -1)
def get_reg(lf, h, r, t, reg_type="F2"):
h_e, r_e, t_e = lf.embed(h, r, t)
if reg_type.lower() == 'f2':
regul_term = an(torch.sum(h_e ** 2, -1) + torch.sum(r_e ** 2, -1) + torch.sum(t_e ** 2, -1))
elif reg_type.lower() == 'n3':
regul_term = an(torch.sum(h_e ** 3, -1) + torch.sum(r_e ** 3, -1) + torch.sum(t_e ** 3, -1))
el:
rai NotImplementedError('Unknown regularizer type: %s' % reg_type)
return lf.lmbda*regul_term
【总结】本⽂提出了 neural-embedding 的通⽤框架,并把 NTN、TransE 等模型套在框架⾥进⾏对⽐;提出了将关系矩阵限制为对⾓矩阵的 DistMult;并⽤ embedding-bad ⽅法挖掘逻辑规则。
Processing math: 100%