TransH嵌入模型详细介绍及每一步骤的python实现代码
时间: 2024-03-08 07:49:52 浏览: 119
TransH嵌入模型是一种基于知识图谱的实体关系表示学习模型,它是在TransE模型的基础上发展而来的。下面是TransH嵌入模型的详细介绍及每一步骤的Python实现代码。
1. 模型介绍
TransH模型的主要思想是为每个关系定义一个超平面,将实体映射到该超平面上。这个超平面被称为关系空间,实体被映射到该空间中的一个点上。在关系空间中,实体之间的距离可以通过两个实体在该超平面上的投影点之间的欧氏距离来计算。TransH模型的目标是最小化实体和关系之间的距离,并将其映射到关系空间中。
2. 数据处理
在实现TransH模型之前,需要对原始数据进行处理。假设原始数据包含三元组(head,relation,tail),其中head和tail表示实体,relation表示实体之间的关系。首先,需要将每个实体和关系映射到一个唯一的数字ID上。然后,将三元组表示为数字ID的形式。最后,将数据分为三部分:训练集、验证集和测试集。
以下是Python代码实现:
```python
import numpy as np
# 将实体和关系映射到数字ID
def get_entity_id(entity_list):
entity_id = {}
for entity in entity_list:
if entity not in entity_id:
entity_id[entity] = len(entity_id)
return entity_id
def get_relation_id(relation_list):
relation_id = {}
for relation in relation_list:
if relation not in relation_id:
relation_id[relation] = len(relation_id)
return relation_id
# 将三元组表示为数字ID的形式
def get_triple(triple_list, entity_id, relation_id):
triple = []
for triple_str in triple_list:
head, relation, tail = triple_str.strip().split('\t')
triple.append((entity_id[head], relation_id[relation], entity_id[tail]))
return np.array(triple)
# 将数据分为训练集、验证集和测试集
def split_data(triple, ratio=(0.7, 0.2, 0.1)):
train_ratio, valid_ratio, test_ratio = ratio
train_size = int(len(triple) * train_ratio)
valid_size = int(len(triple) * valid_ratio)
test_size = len(triple) - train_size - valid_size
train_triple = triple[:train_size]
valid_triple = triple[train_size:train_size+valid_size]
test_triple = triple[train_size+valid_size:]
return train_triple, valid_triple, test_triple
```
3. 模型训练
TransH模型的训练分为两个步骤:第一步是训练TransE模型,第二步是在TransE模型的基础上训练TransH模型。
3.1 训练TransE模型
TransE模型的目标是最小化三元组中实体和关系之间的距离。具体来说,对于三元组(h,r,t),TransE模型的目标是最小化以下损失函数:
$ L = \sum_{(h,r,t) \in S} max(0, \gamma + d(h+r,t) - d(h,r,t)) $
其中,S表示训练集,d表示欧氏距离,$\gamma$表示边界值,$d(h+r,t)$表示实体h与关系r的和向量与实体t的向量之间的欧氏距离,$d(h,r,t)$表示实体h、关系r和实体t之间的欧氏距离。
以下是Python代码实现:
```python
import torch
import torch.nn as nn
import torch.nn.functional as F
class TransE(nn.Module):
def __init__(self, n_entity, n_relation, embedding_dim):
super(TransE, self).__init__()
self.entity_embedding = nn.Embedding(n_entity, embedding_dim)
self.relation_embedding = nn.Embedding(n_relation, embedding_dim)
def forward(self, head, relation, tail):
head_embedding = self.entity_embedding(head)
relation_embedding = self.relation_embedding(relation)
tail_embedding = self.entity_embedding(tail)
score = torch.norm(head_embedding + relation_embedding - tail_embedding, p=2, dim=1)
return score
def loss(self, score, margin=1.0):
return torch.mean(F.relu(margin + score))
def predict(self, head, relation):
head_embedding = self.entity_embedding(head)
relation_embedding = self.relation_embedding(relation)
tail_embedding = head_embedding + relation_embedding
return tail_embedding
```
3.2 训练TransH模型
在TransE模型的基础上,TransH模型为每个关系定义一个超平面,将实体映射到该超平面上。具体来说,在TransH模型中,每个关系r都有一个超平面$W_r$,该超平面由一个法向量$w_r$和一个点$p_r$确定。实体h和t在关系空间中的投影点分别为$h_r$和$t_r$。对于三元组(h,r,t),TransH模型的目标是最小化以下损失函数:
$ L = \sum_{(h,r,t) \in S} max(0, \gamma + d(h_r + w_r,t_r) - d(h_r,t_r) + d(h+r,t) - d(h,t)) $
其中,S表示训练集,$\gamma$表示边界值,$d(h_r + w_r,t_r)$表示实体h和关系r的超平面投影点的和向量与实体t的超平面投影点之间的欧氏距离,$d(h_r,t_r)$表示实体h和实体t在关系r的超平面上的投影点之间的欧氏距离,$d(h+r,t)$表示实体h与关系r的和向量与实体t的向量之间的欧氏距离,$d(h,t)$表示实体h和实体t之间的欧氏距离。
以下是Python代码实现:
```python
class TransH(nn.Module):
def __init__(self, n_entity, n_relation, embedding_dim):
super(TransH, self).__init__()
self.entity_embedding = nn.Embedding(n_entity, embedding_dim)
self.relation_embedding = nn.Embedding(n_relation, embedding_dim)
self.relation_hyperplane_normal = nn.Embedding(n_relation, embedding_dim)
self.relation_hyperplane_point = nn.Embedding(n_relation, embedding_dim)
def forward(self, head, relation, tail):
head_embedding = self.entity_embedding(head)
relation_embedding = self.relation_embedding(relation)
tail_embedding = self.entity_embedding(tail)
relation_hyperplane_normal = self.relation_hyperplane_normal(relation)
relation_hyperplane_point = self.relation_hyperplane_point(relation)
head_projection = head_embedding - torch.sum(head_embedding * relation_hyperplane_normal, dim=1, keepdims=True) * relation_hyperplane_normal
tail_projection = tail_embedding - torch.sum(tail_embedding * relation_hyperplane_normal, dim=1, keepdims=True) * relation_hyperplane_normal
relation_hyperplane_projection = relation_embedding - torch.sum(relation_embedding * relation_hyperplane_normal, dim=1, keepdims=True) * relation_hyperplane_normal
score = torch.norm(head_projection + relation_hyperplane_projection - tail_projection, p=2, dim=1)
return score
def loss(self, score, margin=1.0):
return torch.mean(F.relu(margin + score))
def predict(self, head, relation):
head_embedding = self.entity_embedding(head)
relation_embedding = self.relation_embedding(relation)
relation_hyperplane_normal = self.relation_hyperplane_normal(relation)
relation_hyperplane_point = self.relation_hyperplane_point(relation)
head_projection = head_embedding - torch.sum(head_embedding * relation_hyperplane_normal, dim=1, keepdims=True) * relation_hyperplane_normal
relation_hyperplane_projection = relation_embedding - torch.sum(relation_embedding * relation_hyperplane_normal, dim=1, keepdims=True) * relation_hyperplane_normal
tail_embedding = head_projection + relation_hyperplane_projection
return tail_embedding
```
4. 模型评估
模型评估的主要目标是计算模型的预测准确率。具体来说,需要计算模型在验证集和测试集上的平均准确率(Mean Average Precision,MAP)和平均逆排名(Mean Reciprocal Rank,MRR)。
以下是Python代码实现:
```python
def evaluate(model, triple, entity_id, relation_id, device):
with torch.no_grad():
hits10 = 0
hits1 = 0
ranks = []
for head, relation, tail in triple:
head = torch.tensor([head], dtype=torch.long).to(device)
relation = torch.tensor([relation], dtype=torch.long).to(device)
tail = torch.tensor([tail], dtype=torch.long).to(device)
all_entity = torch.tensor(list(entity_id.values()), dtype=torch.long).to(device)
all_entity = all_entity.unsqueeze(0).repeat(len(entity_id), 1)
score = model(head, relation, all_entity)
_, indices = torch.sort(score)
indices = indices.cpu().numpy().tolist()[0]
rank = indices.index(tail.item()) + 1
ranks.append(rank)
if rank <= 10:
hits10 += 1
if rank == 1:
hits1 += 1
mrr = np.mean([1/rank for rank in ranks])
map = 0
for i, rank in enumerate(ranks):
if rank <= 10:
map += (i+1) / hits10
map /= len(ranks)
return hits10/len(triple), hits1/len(triple), mrr, map
```
以上就是TransH嵌入模型的详细介绍及每一步骤的Python实现代码。
阅读全文