实体嵌入Entity Embedding及代码实现

实体嵌入

英文是Entity Embedding。我们希望深度学习能够处理结构化数据。在处理类别特征时,常用办法包括独热编码、顺序编码等。在NLP任务处理中,词和文章的表示都得益于嵌入。我们同样可以将这个思想在结构化数据领域加以运用。

原理

假设 N N N表示分箱的数量, M M M表示嵌入的维度, B B B表示训练时候的批量尺寸。我们用 x ∈ R B ∗ 1 x \in R^{B*1} xRB1代表输入数据, E ∈ R N ∗ M E \in R^{N*M} ERNM表示嵌入矩阵, c ∈ R N ∗ 1 c \in R^{N*1} cRN1表示分箱的向量中心。我们的权重。下标中 i i i表示数据的序号, j j j表示分箱的序号。
W i j = s o f t m a x ( 1 ∣ x i − c j ∣ + ϵ ) W_{ij} = softmax(\frac 1 {|x_i - c_j| + \epsilon}) Wij=softmax(xicj+ϵ1)
我们最后生成的嵌入矩阵可以表示为 V ∈ R B ∗ N V \in R^{B*N} VRBN
V i = ∑ j = 1 N W i j E j V = W E V_i = \sum_{j=1}^N W_{ij} E_j \\\\ V = WE Vi=j=1NWijEjV=WE

代码实现

我们借助pytorch构建实体嵌入层。

import torch
import torch.nn as nn
import torch.nn.functional as F

class EntityEmbeddingLayer(nn.Module):
    def __init__(self, num_level, emdedding_dim, centroid):
        super(EntityEmbeddingLayer, self).__init__()
        self.embedding = nn.Embedding(num_level, embedding_dim)
        self.centroid = torch.tensor(centroid).detach_().unsqueeze(1)
    
    def forward(self, x): 
        """
        x: size of (batch_size, 1)
        """
        eps = 1e-7
        x = x.unsqueeze(1)
        d = 1.0/((x-self.centroid).abs()+eps)
        w = F.softmax(d.squeeze(2), 1)
        v = torch.mm(w, self.embedding.weight)
        return v

适用场景

深度学习处理结构化数据。

优点

  1. 嵌入向量稠密,非稀疏
  2. 容易计算类别距离
  3. 方便可视化

缺点

  1. 暂无

Reference

  • NLP实战高手课,第三章,王然,极客时间
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一个示例代码。不过在此之前,请问您是否已经安装了相应的Python库,如`numpy`和`pandas`等? 以下是一个简单的示例代码: ```python import numpy as np import pandas as pd class TransH: def __init__(self, entity_num, relation_num, dim, margin, learning_rate): self.entity_num = entity_num self.relation_num = relation_num self.dim = dim self.margin = margin self.learning_rate = learning_rate self.entity_embedding = np.random.uniform(-6 / np.sqrt(dim), 6 / np.sqrt(dim), (entity_num, dim)) self.relation_embedding = np.random.uniform(-6 / np.sqrt(dim), 6 / np.sqrt(dim), (relation_num, dim)) self.relation_normal_vector = np.random.uniform(-6 / np.sqrt(dim), 6 / np.sqrt(dim), (relation_num, dim)) def l2_norm(self, tensor): return np.sqrt(np.sum(np.square(tensor))) def transfer(self, e, norm): return e - np.dot(e, norm) / norm * norm / self.l2_norm(norm) def calc(self, head, relation, tail): head = self.entity_embedding[head] relation = self.relation_embedding[relation] tail = self.entity_embedding[tail] head = self.transfer(head, self.relation_normal_vector[relation]) tail = self.transfer(tail, self.relation_normal_vector[relation]) score = np.sum(np.abs(head + relation - tail), axis=-1) return score def train(self, triplets): for triplet in triplets: head, relation, tail = triplet score = self.calc(head, relation, tail) if score + self.margin > 0: positive_sample = 1 negative_sample = 0 head_gradient = self.relation_normal_vector[relation] / self.l2_norm(self.relation_normal_vector[relation]) tail_gradient = - self.relation_normal_vector[relation] / self.l2_norm(self.relation_normal_vector[relation]) relation_gradient = self.transfer(self.entity_embedding[head], self.relation_normal_vector[relation]) - self.transfer(self.entity_embedding[tail], self.relation_normal_vector[relation]) else: positive_sample = 0 negative_sample = 1 head_gradient = - self.relation_normal_vector[relation] / self.l2_norm(self.relation_normal_vector[relation]) tail_gradient = self.relation_normal_vector[relation] / self.l2_norm(self.relation_normal_vector[relation]) relation_gradient = self.transfer(self.entity_embedding[tail], self.relation_normal_vector[relation]) - self.transfer(self.entity_embedding[head], self.relation_normal_vector[relation]) self.entity_embedding[head] -= self.learning_rate * (positive_sample * head_gradient + negative_sample * head_gradient) self.entity_embedding[tail] -= self.learning_rate * (positive_sample * tail_gradient + negative_sample * tail_gradient) self.relation_embedding[relation] -= self.learning_rate * (positive_sample * relation_gradient + negative_sample * relation_gradient) def save_embedding(self, entity_file, relation_file): entity_df = pd.DataFrame(self.entity_embedding) relation_df = pd.DataFrame(self.relation_embedding) entity_df.to_csv(entity_file, index=False, header=False, sep='\t') relation_df.to_csv(relation_file, index=False, header=False, sep='\t') ``` 这里的`TransH`类实现了TransH模型,包括了初始化、计算、训练和保存嵌入向量等方法。您可以根据需要进行修改和扩展。`train`方法需要输入三元组数组,其中每个三元组包括头实体id、关系id和尾实体id。`save_embedding`方法可以将学习到的实体和关系的嵌入向量保存到文件中。 希望这个示例代码对您有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值