将两个embedding信息进行融合最常见的方式就是加法,因为按照onehot的形式去考虑,加法能够映射出当前embedding的唯一组合形式(虽然无法看出序列关系)。有时也需要将加法替换为加权相加,增加一组权重参数辅助融合,做法如下:
代码实现是先把两个张量拼接,然后再通过线性层计算权重,然后再去softmax
import torch
import torch.nn.functional as F
# 创建两个嵌入向量
embedding1 = torch.tensor([[1.0, 2.0, 3.0], [1.,2.,3.], [0.,0.,0.]])
embedding2 = torch.tensor([[4.0, 5.0, 6.0], [1.,2.,3.], [0.,0.,0.]])
# 定义线性层来计算注意力权重
attention_layer = torch.nn.Linear(embedding1.size(1), 1, bias=False)
# 将两个嵌入向量连接起来
concatenated_embeddings = torch.cat((embedding1.unsqueeze(1), embedding2.unsqueeze(1)), dim=1)
# 计算注意力权重
attention_scores = attention_layer(concatenated_embeddings)
attention_weights = F.softmax(attention_scores, dim=1)
# 计算加权和
fused_embedding = torch.sum(attention_weights * concatenated_embeddings, dim=1)
# 打印融合后的嵌入向量
print("Fused Embedding:", fused_embedding)
里面线性层的定义最好在初始化函数定义,这个实现方式用到了batch forward的技巧。
element-wise的注意力计算方法(常用的线性注意力计算方法):
import torch
import torch.nn.functional as F
# 创建两个嵌入向量
embedding1 = torch.tensor([[1.0, 2.0, 3.0], [1.,2.,3.], [0.,0.,0.]])
embedding2 = torch.tensor([[4.0, 5.0, 6.0], [1.,2.,3.], [0.,0.,0.]])
# 定义线性层来计算注意力权重,这里的out size不是1
attention_layer = torch.nn.Linear(embedding1.size(1), embedding1.size(1), bias=False)
# 将两个嵌入向量连接起来
concatenated_embeddings = torch.cat((embedding1.unsqueeze(1), embedding2.unsqueeze(1)), dim=1)
# 计算注意力权重
attention_scores = attention_layer(concatenated_embeddings)
attention_weights = F.softmax(attention_scores, dim=1)
# 计算加权和
fused_embedding = torch.sum(attention_weights * concatenated_embeddings, dim=1)
# 打印融合后的嵌入向量
print("Fused Embedding:", fused_embedding)