向量相似度评估方法

在这里插入图片描述

原文链接:向量相似度评估方法

相似度在工作中的使用可以说是相当频繁,今天就带大家介绍pytorch中四种常用的向量相似度评估思路:

  1. CosineSimilarity
  2. DotProductSimilarity
  3. BiLinearSimilarity
  4. MultiHeadedSimilarity

1 余弦相似度

余弦相似度相信大家都很熟悉了。用两个向量夹角的余弦值作为衡量两个个体间差异的大小。余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似。

import torch
import torch.nn as nn
import math

class CosineSimilarity(nn.Module):
 
    def forward(self, tensor_1, tensor_2):
        normalized_tensor_1 = tensor_1 / tensor_1.norm(dim=-1, keepdim=True)
        normalized_tensor_2 = tensor_2 / tensor_2.norm(dim=-1, keepdim=True)
        return (normalized_tensor_1 * normalized_tensor_2).sum(dim=-1)

2 DotProductSimilarity

这个相似度函数计算每对向量之间的点积,并用可选的缩放来减少输出的方差,以调整结果的输出。

class DotProductSimilarity(nn.Module):
 
    def __init__(self, scale_output=False):
        super(DotProductSimilarity, self).__init__()
        self.scale_output = scale_output
 
    def forward(self, tensor_1, tensor_2):
        result = (tensor_1 * tensor_2).sum(dim=-1)
        if self.scale_output:
            # TODO why allennlp do multiplication at here ?
            result /= math.sqrt(tensor_1.size(-1))
        return result

余弦法和点积法都是最常用的数学方法,在复杂场景下我们可以将神经网络的思路加入到计算相似度的方法中去。

3 BiLinearSimilarity

此相似度函数执行两个输入向量的双线性变换,就是加入了神经网络线性层。这个函数有一个权重矩阵“W”和一个偏差“b”,以及两个向量之间的相似度,计算公式为:
x T W y + b x^TWy+b xTWy+b

计算后可使用激活函数,默认为不激活。

class BiLinearSimilarity(nn.Module):
 
    def __init__(self, tensor_1_dim, tensor_2_dim, activation=None):
        super(BiLinearSimilarity, self).__init__()
        self.weight_matrix = nn.Parameter(torch.Tensor(tensor_1_dim, tensor_2_dim))
        self.bias = nn.Parameter(torch.Tensor(1))
        self.activation = activation
        self.reset_parameters()
 
    def reset_parameters(self):
        nn.init.xavier_uniform_(self.weight_matrix)
        self.bias.data.fill_(0)
 
    def forward(self, tensor_1, tensor_2):
        intermediate = torch.matmul(tensor_1, self.weight_matrix)
        result = (intermediate * tensor_2).sum(dim=-1) + self.bias
        if self.activation is not None:
            result = self.activation(result)
        return result

根据此思路,我们可以演变出三线性变换,计算公式为:
W T [ x , y , x ∗ y ] + b W^T[x,y,x*y]+b WT[x,y,xy]+b

只是在原基础上将各个特征及特征之间的关系都变为了输入,感兴趣的朋友们可以自行动手实现。

4 MultiHeadedSimilarity

这个相似度函数借用了transformer多“头”的思路来计算相似度。我们将输入张量投影到多个新张量中,并分别计算每个投影张量的相似度。

class MultiHeadedSimilarity(nn.Module):
 
    def __init__(self,
                 num_heads,
                 tensor_1_dim,
                 tensor_1_projected_dim=None,
                 tensor_2_dim=None,
                 tensor_2_projected_dim=None,
                 internal_similarity=DotProductSimilarity()):
        super(MultiHeadedSimilarity, self).__init__()
        self.num_heads = num_heads
        self.internal_similarity = internal_similarity
        tensor_1_projected_dim = tensor_1_projected_dim or tensor_1_dim
        tensor_2_dim = tensor_2_dim or tensor_1_dim
        tensor_2_projected_dim = tensor_2_projected_dim or tensor_2_dim
        if tensor_1_projected_dim % num_heads != 0:
            raise ValueError("Projected dimension not divisible by number of heads: %d, %d"
                             % (tensor_1_projected_dim, num_heads))
        if tensor_2_projected_dim % num_heads != 0:
            raise ValueError("Projected dimension not divisible by number of heads: %d, %d"
                             % (tensor_2_projected_dim, num_heads))
        self.tensor_1_projection = nn.Parameter(torch.Tensor(tensor_1_dim, tensor_1_projected_dim))
        self.tensor_2_projection = nn.Parameter(torch.Tensor(tensor_2_dim, tensor_2_projected_dim))
        self.reset_parameters()
 
    def reset_parameters(self):
        torch.nn.init.xavier_uniform_(self.tensor_1_projection)
        torch.nn.init.xavier_uniform_(self.tensor_2_projection)
 
    def forward(self, tensor_1, tensor_2):
        projected_tensor_1 = torch.matmul(tensor_1, self.tensor_1_projection)
        projected_tensor_2 = torch.matmul(tensor_2, self.tensor_2_projection)
 
        last_dim_size = projected_tensor_1.size(-1) // self.num_heads
        new_shape = list(projected_tensor_1.size())[:-1] + [self.num_heads, last_dim_size]
        split_tensor_1 = projected_tensor_1.view(*new_shape)
        last_dim_size = projected_tensor_2.size(-1) // self.num_heads
        new_shape = list(projected_tensor_2.size())[:-1] + [self.num_heads, last_dim_size]
        split_tensor_2 = projected_tensor_2.view(*new_shape)
 
        return self.internal_similarity(split_tensor_1, split_tensor_2)

总结

复杂的做法只是在向量的基础上进行了更多的线性变化和线性变化组合。其实我们自己完全可以根据业务场景自创计算方法,因为神经网络的好处就是在于我们可以随意自行搭建。

原文链接:向量相似度评估方法
在这里插入图片描述

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
区域感知结构相似度损失函数(Perceptual Structural Similarity Loss with Region-wise Attention)是一种改进的目标感知结构相似度损失函数,用于图像生成、风格迁移等任务中。其核心思想是在目标感知结构相似度损失的基础上,引入区域感知的注意力机制,以提高损失函数的鲁棒性和效果。下面是区域感知结构相似度损失函数的tensorflow代码实现: ``` import tensorflow as tf from tensorflow.keras.applications.vgg16 import VGG16 # 加载预训练的VGG16模型 vgg16 = VGG16(include_top=False, weights='imagenet', input_shape=(None, None, 3)) vgg16.trainable = False # 选择VGG16的某些层作为特征提取器 layers = ['block1_conv2', 'block2_conv2', 'block3_conv3', 'block4_conv3'] outputs = [vgg16.get_layer(name).output for name in layers] model = tf.keras.Model(inputs=vgg16.input, outputs=outputs) def region_aware_perceptual_structural_similarity_loss(y_true, y_pred): # 提取目标图像和生成图像的特征表示 true_features = model(y_true) pred_features = model(y_pred) # 计算每个特征图的MSE损失,并乘以对应的注意力权重 loss = 0 for true_feature, pred_feature in zip(true_features, pred_features): mse_loss = tf.keras.losses.MSE(true_feature, pred_feature) attention = region_aware_attention(true_feature, pred_feature) loss += mse_loss * attention loss /= len(true_features) return loss def region_aware_attention(x, y, kernel_size=3): # 计算特征图的均值和标准差 x_mean, x_var = tf.nn.moments(x, axes=[1, 2], keepdims=True) y_mean, y_var = tf.nn.moments(y, axes=[1, 2], keepdims=True) # 计算相似度矩阵 xy = tf.nn.conv2d(x * y, tf.ones((kernel_size, kernel_size, x.shape[-1], 1)), strides=[1, 1, 1, 1], padding='SAME') xx = tf.nn.conv2d(x ** 2, tf.ones((kernel_size, kernel_size, x.shape[-1], 1)), strides=[1, 1, 1, 1], padding='SAME') yy = tf.nn.conv2d(y ** 2, tf.ones((kernel_size, kernel_size, x.shape[-1], 1)), strides=[1, 1, 1, 1], padding='SAME') sigma = tf.sqrt(xx * yy) similarity = xy / sigma # 计算区域感知的注意力权重 max_similarity = tf.reduce_max(similarity, axis=[1, 2], keepdims=True) attention = tf.exp(similarity - max_similarity) attention *= tf.cast(attention > 1e-5, tf.float32) attention /= tf.reduce_sum(attention, axis=[1, 2], keepdims=True) return attention ``` 在上面的代码中,我们首先提取目标图像和生成图像的特征表示,然后对于每个特征图,计算其MSE损失,并乘以对应的区域感知的注意力权重。注意力权重的计算方法是先计算相似度矩阵,然后对相似度矩阵进行归一化处理,最后得到每个像素点的注意力权重。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值