知识图谱表示学习 TransH: Knowledge Graph Embedding by Translating on Hyperplanes

知识图谱表示学习 TransH: Knowledge Graph Embedding by Translating on Hyperplanes

表示学习是深度学习的基础,将数据用更有效的方式表达出来,才能让深度学习发挥出更强大的作用。表示学习避免了手动提取数据特征的繁琐,允许计算机学习特征的同时,也学习如何提取特征。尽管举例基于翻译(translation)的知识图谱表示学习已经过去了五六年的时间,但是仍不可忽略其重要意义。本文聚焦于TransH模型。

1. 摘要和引言

TransE模型简单有效的方法,在链接预测达到了state-of-the-art的效果。但在知识图谱中,关系的属性在嵌入时也应当被考虑,如一对多,多对一,和多对多的关系。本文注意到TransE不能很好地处理这些类型的关系。有些模型可以保留不同类别的关系,但是牺牲了处理的效率。为了达到一个效率和模型能力的权衡,本文提出了TransH。利用一对多,多对一的关系,本文提出了一个简单的技巧,可以帮助减少负采样过程中假负例的出现概率。

在TransH中,每一个关系使用两个向量来刻画,其中一个单位向量 w r w_r wr用来表示超平面,另外一个向h量 d r d_r dr用来将向量投影到此超平面。

2. 相关工作

(1)TransE详情请点击

(2)非结构化表示 Unstructured:将不同实体用嵌入方式表示,得分函数为 ∣ ∣ h − t ∣ ∣ ||h-t|| ht。显然这种方式不能区分不同的关系。

(3)距离模型 Distant Model:将头实体和尾实体用两个不同的矩阵 W r h W_{rh} Wrh W r t W_{rt} Wrt投影,相似程度用 W r h h W_{rh}h Wrhh W r t t W_{rt}t Wrtt L 1 L_1 L1距离来度量。此模型不能很好捕捉实体和关系的相关性。

(4)双线性模型 Bilinear Model:模型认为实体之间是二阶相关的,用 h t W r t h^tW_rt htWrt来建模。

(5)单层网络模型 Single Layer Model:使用神经网络的非线性变换,将 h , t h, t h,t作为输入,并加以非线性层,最后用线性单元计算得分 u r f ( W r h h + W r t t + b r ) u_r f(W_{rh}h+W_{rt}t+b_r) urf(Wrhh+Wrtt+br)

(6)神经张量网络 Neural Tensor Network:在此篇文章中的神经张量网络之后加入了非线性单元。

3. TransH

为了克服TransE在对一对多,多对一和多对多的关系上的不足,我们提出了一种针对不同关系的分布式表示方法,TransH。如图所示,对于一个关系 r r r,设置一个关系翻译向量 d r d_r dr,在关系所在的超平面 w r w_r wr中( w r w_r wr是单位向量),而不是在整个嵌入表示的空间中。具体而言,对于一个三元组 ( h , r , t ) (h, r, t) (h,r,t) h , t h, t h,t的嵌入表示首先投影到超平面 w r w_r wr, 他们的投影分别是 h ⊥ , t ⊥ h_{\perp}, t_{\perp} h,t。假定在超平面内,关系满足向量加法,即 h ⊥ + r = t ⊥ h_{\perp} + r = t_{\perp} h+r=t,那么误差即为 ∣ ∣ h ⊥ + d r − t ⊥ ∣ ∣ 2 2 ||h_{\perp} + d_{r} - t_{\perp}||_2^2 h+drt22。约束 ∣ ∣ w r ∣ ∣ 2 = 1 ||w_r||_2=1 wr2=1,那么
h ⊥ = h − w r T h w r t ⊥ = t − w r T t w r h_{\perp}=h-w_r^Thw_r \\ t_{\perp}=t-w_r^Ttw_r h=hwrThwrt=twrTtwr
最终得分函数为
f r ( h , t ) = ∣ ∣ ( h − w r T h w r ) + d r − ( t − w r T t w r ) ∣ ∣ 2 2 f_r(h, t) = ||(h-w_r^Thw_r)+d_r-(t-w^T_rtw_r)||_2^2 fr(h,t)=(hwrThwr)+dr(twrTtwr)22

在这里插入图片描述

上述为TransH的基本模型,除此之外,还有一定的约束条件,如下
∀ e ∈ E , ∣ ∣ e ∣ ∣ 2 ≤ 1 ∀ r ∈ R . ∣ w r T d r ∣ / ∣ ∣ d r ∣ ∣ 2 ≤ ϵ ∀ r ∈ R , ∣ ∣ w r ∣ ∣ 2 = 1 \forall e \in E, ||e||_2 \le 1 \\ \forall r \in R. |w_r^Td_r|/||d_r||_2 \le \epsilon \\ \forall r \in R, ||w_r||_2 = 1 eE,e21rR.wrTdr/dr2ϵrR,wr2=1
含义分别为

  1. 所有实体为的L2范数小于等于1,避免模型通过调整实体嵌入表示的大小,来达到目的。
  2. 对于每个关系平面的法向量,和平面上的翻译向量,要满足相互垂直。
  3. 每个关系平面的法向量应该为单位向量。

在考虑到上述的约束之后,损失函数为
L = ∑ ( h , r , t ) ∈ △ ∑ ( h ′ , r ′ , t ′ ) ∈ △ ′ [ f r ( h , t ) + γ − f r ′ ( h ′ , t ′ ) ] + C { ∑ e ∈ E [ ∣ ∣ e ∣ ∣ 2 2 − 1 ] + ∑ r ∈ R [ ( w r T d r ) 2 ∣ ∣ d r ∣ ∣ 2 2 − ϵ 2 ] } L = \sum_{(h,r,t)\in\triangle} \sum_{(h',r',t')\in \triangle'}[f_r(h, t) + \gamma - f_{r'}(h', t')] + C\{\sum_{e\in E}[||e||_2^2-1] + \sum_{r\in R}[\frac{(w_r^Td_r)^2}{||d_r||^2_2} - \epsilon^2]\} L=(h,r,t)(h,r,t)[fr(h,t)+γfr(h,t)]+C{eE[e221]+rR[dr22(wrTdr)2ϵ2]}
C C C为超参数,用于调节约束的重要程度。

在训练时,仍然使用了负采样的技术。但由于一对多,多对一和多对多的关系关系存在,若随机采样作为负样本,则很容易出现假负例,影响训练效果。本文提出了一种依据概率进行选取的方法,在构造负样本的时候,对于一对多的关系更倾向于替换头实体,而对于多对一的关系更倾向于替换尾实体。

首先需要统计两个数值,平均每个头实体链接的尾实体数目,记作 t p h tph tph;平均每个尾实体链接的头实体数目,记作 h p t hpt hpt。对于一个样本 ( h , r , t ) (h,r,t) (h,r,t),以 t p h t p h + h p t \frac{tph}{tph+hpt} tph+hpttph的概率替换头实体,以 h p t t p h + h p t \frac{hpt}{tph+hpt} tph+hpthpt的概率替换尾实体。

4. 实验

选择了三个实验来验证模型的效果,并分别计算了 m e a n   r a n k mean\ rank mean rank h i t @ 10 hit@10 hit@10。其具体计算和含义可参照此处

(1)链接预测(同TransE)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AFEfIesJ-1593179897190)(C:\Users\pengw\AppData\Roaming\Typora\typora-user-images\image-20200626213519676.png)]

此外,也给出了对于不同关系TransH和TransE的对比。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tVzVOESw-1593179897191)(C:\Users\pengw\AppData\Roaming\Typora\typora-user-images\image-20200626215512108.png)]

(2)三元组分类

判断一个给定的三元组为正确或错误,或者说头实体和尾实体是否存在给定的关系。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fvznXzNq-1593179897194)(C:\Users\pengw\AppData\Roaming\Typora\typora-user-images\image-20200626215431890.png)]

(3)文本关系提取

文本关系提取是扩充知识图谱的重要方式。通过知识图谱的嵌入表示,不需要任何额外的文本内容,就能够对候选实事进行评分。此处选取了数据集中最普及的50条断言,数据集被分为两部分,一部分作为训练,另一部分作为测试。通过AUC来对模型进行评价,与X轴和Y轴围成的面积越大越好。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zjxkKgPH-1593179897197)(C:\Users\pengw\AppData\Roaming\Typora\typora-user-images\image-20200626215554637.png)]

5. 结论

本文提出了TransH,一种用于知识图谱嵌入的新的方法。TransH克服了TransE在一对多,多对一和多对多关系上表现的不足。实验证明在链接预测,三元组分类和文本关系提取三个任务上,和TransE相比均有提升。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Python将Neo4j的知识图谱转换为嵌入向量的示例代码,利用的是TransH方法: ```python from py2neo import Graph import numpy as np import torch from torch.utils.data import Dataset, DataLoader # Neo4j数据库连接信息 uri = "bolt://localhost:7687" user = "neo4j" password = "password" # TransH嵌入向量设置 embedding_dim = 50 # 嵌入向量维度 margin = 1.0 # 损失函数中的边界值 learning_rate = 0.01 # 学习率 num_epochs = 100 # 迭代次数 # Neo4j数据库操作 class Neo4jDB: def __init__(self, uri, user, password): self.graph = Graph(uri, auth=(user, password)) def close(self): self.graph.close() def get_all_triples(self): query = """ MATCH (h)-[r]->(t) RETURN id(h) AS h_id, id(t) AS t_id, type(r) AS r_type """ result = self.graph.run(query) triples = [(row["h_id"], row["t_id"], row["r_type"]) for row in result] return triples # TransH嵌入向量模型 class TransHModel(torch.nn.Module): def __init__(self, num_entities, num_relations, embedding_dim): super(TransHModel, self).__init__() self.num_entities = num_entities self.num_relations = num_relations self.embedding_dim = embedding_dim # 实体、关系、嵌入向量初始化 self.entity_embedding = torch.nn.Embedding(num_entities, embedding_dim) self.relation_embedding = torch.nn.Embedding(num_relations, embedding_dim) self.normal_vector = torch.nn.Embedding(num_relations, embedding_dim) # 参数初始化 torch.nn.init.xavier_uniform_(self.entity_embedding.weight.data) torch.nn.init.xavier_uniform_(self.relation_embedding.weight.data) torch.nn.init.xavier_uniform_(self.normal_vector.weight.data) def forward(self, head, tail, relation): # 获取实体、关系、嵌入向量 entity_emb = self.entity_embedding(torch.LongTensor(range(self.num_entities)).to(device)) relation_emb = self.relation_embedding(torch.LongTensor(range(self.num_relations)).to(device)) normal_vector_emb = self.normal_vector(torch.LongTensor(range(self.num_relations)).to(device)) # 计算头实体和尾实体在关系空间中的表示 head_emb = torch.index_select(entity_emb, 0, head) tail_emb = torch.index_select(entity_emb, 0, tail) relation_emb = torch.index_select(relation_emb, 0, relation) normal_vector_emb = torch.index_select(normal_vector_emb, 0, relation) head_proj = head_emb - torch.sum(head_emb * normal_vector_emb, dim=1, keepdim=True) * normal_vector_emb tail_proj = tail_emb - torch.sum(tail_emb * normal_vector_emb, dim=1, keepdim=True) * normal_vector_emb # 计算距离和损失 distance = torch.norm(head_proj + relation_emb - tail_proj, p=2, dim=1) loss = torch.mean(torch.relu(distance - margin)) return loss # 数据集类 class TripleDataset(Dataset): def __init__(self, triples, num_entities, num_relations): self.triples = triples self.num_entities = num_entities self.num_relations = num_relations def __len__(self): return len(self.triples) def __getitem__(self, idx): head, tail, relation = self.triples[idx] return head, tail, relation # 加载数据集 db = Neo4jDB(uri, user, password) triples = db.get_all_triples() num_entities = len(set([triple[0] for triple in triples] + [triple[1] for triple in triples])) num_relations = len(set([triple[2] for triple in triples])) train_dataset = TripleDataset(triples, num_entities, num_relations) train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True) # 模型和优化器 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = TransHModel(num_entities, num_relations, embedding_dim).to(device) optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) # 模型训练 for epoch in range(num_epochs): total_loss = 0.0 for batch_idx, (head, tail, relation) in enumerate(train_loader): head, tail, relation = head.to(device), tail.to(device), relation.to(device) optimizer.zero_grad() loss = model(head, tail, relation) loss.backward() optimizer.step() total_loss += loss.item() print("Epoch {}, Loss {:.4f}".format(epoch+1, total_loss/len(train_loader))) # 提取嵌入向量 entity_emb = model.entity_embedding(torch.LongTensor(range(num_entities)).to(device)).cpu().detach().numpy() relation_emb = model.relation_embedding(torch.LongTensor(range(num_relations)).to(device)).cpu().detach().numpy() normal_vector_emb = model.normal_vector(torch.LongTensor(range(num_relations)).to(device)).cpu().detach().numpy() # 保存嵌入向量 np.save("entity_embedding.npy", entity_emb) np.save("relation_embedding.npy", relation_emb) np.save("normal_vector_embedding.npy", normal_vector_emb) # 关闭数据库连接 db.close() ``` 其中,`Neo4jDB`类封装了Neo4j数据库的连接和操作,其中`get_all_triples`方法用于获取所有三元组数据。`TransHModel`类定义了TransH模型的架构和前向传播过程,其中包括实体、关系和嵌入向量的初始化、距离计算和损失计算。`TripleDataset`类定义了数据集的格式和获取方式。 在代码中,首先通过`get_all_triples`方法获取所有三元组数据,并根据实体和关系的数量初始化模型。然后使用PyTorch的`DataLoader`将三元组数据转换为批次,并在循环中使用`model`计算损失并更新参数。在训练完成后,通过`model`提取实体、关系和嵌入向量,并保存到文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值