Pytorch相似度的計算(二)

本文章中的相似度計算方法摘抄自:BiMPM
1 帶權重的cosine相似度計算
這個方法與傳統的cosine相似度計算方法不同之處就是爲輸入的兩個向量增加了一個權重,可以通過訓練權重來調節向量,獲得更加精確的相似度。
**加粗樣式**

import torch
import torch.nn as nn
class CosineSimilarityWithW(nn.Module):
    def __init__(self):
        super(CosineSimilarityWithW,self).__init__()
        self.l=1
        self.hidden_size=30
        for i in range(1, 9):#源代碼中就是這樣寫的,我就直接搬過來用了,改爲2也是可以的
            setattr(self, f'mp_w{i}',
                    nn.Parameter(torch.rand(self.l, self.hidden_size)))
        self.reset_parameters()

    def reset_parameters(self):
        for i in range(1, 9):
            w = getattr(self, f'mp_w{i}')
            nn.init.kaiming_normal(w)
    def mp_matching_func(self,v1, v2, w):
        """
        :param v1: (batch, seq_len, hidden_size)
        :param v2: (batch, seq_len, hidden_size) or (batch, hidden_size)
        :param w: (l, hidden_size)
        :return: (batch, l)
        """
        seq_len = v1.size(1)

        # Trick for large memory requirement
        """
        if len(v2.size()) == 2:
            v2 = torch.stack([v2] * seq_len, dim=1)
        m = []
        for i in range(self.l):
            # v1: (batch, seq_len, hidden_size)
            # v2: (batch, seq_len, hidden_size)
            # w: (1, 1, hidden_size)
            # -> (batch, seq_len)
            m.append(F.cosine_similarity(w[i].view(1, 1, -1) * v1, w[i].view(1, 1, -1) * v2, dim=2))
        # list of (batch, seq_len) -> (batch, seq_len, l)
        m = torch.stack(m, dim=2)
        """

        # (1, 1, hidden_size, l)
        w = w.transpose(1, 0).unsqueeze(0).unsqueeze(0)
        # (batch, seq_len, hidden_size, l)
        v1 = w * torch.stack([v1] * self.l, dim=3)
        print(v1.size())
        if len(v2.size()) == 3:
            v2 = w * torch.stack([v2] * self.l, dim=3)
        else:
            v2 = w * torch.stack([torch.stack([v2] * seq_len, dim=1)] * self.l, dim=3)

        m = torch.cosine_similarity(v1, v2, dim=2)

        return m
#隨機生成向量
tensor_1=torch.randn((5,6,30))
print(tensor_1.size())
tensor_2=torch.randn((5,4,30))
hidden=30
#聲明cosine
cos=CosineSimilarityWithW()
#聲明一個雙向lstm
lstm=nn.LSTM(30,hidden,bidirectional=True,batch_first=True)
tensor_1,_=lstm(tensor_1)
tensor_2,_=lstm(tensor_2)
#通過torch.split把雙向的lstm的輸出,劃分爲單向的,f是前,b是後
tensor_1_fw,tensor_1_bw=torch.split(tensor_1,hidden,dim=-1)
tensor_2_fw,tensor_2_bw=torch.split(tensor_2,hidden,dim=-1)
print(tensor_1_fw.size())
print(tensor_2_fw.size())
#計算的時候,計算各種方向的,第二參數就是取lstm輸出的最後一個狀態的值
mv_p_full_fw = cos.mp_matching_func(tensor_1_fw, tensor_2_fw[:, -1, :], cos.mp_w1)
mv_p_full_bw = cos.mp_matching_func(tensor_1_bw, tensor_2_bw[:, 0, :], cos.mp_w2)
mv_h_full_fw = cos.mp_matching_func(tensor_2_fw, tensor_1_fw[:, -1, :], cos.mp_w1)
mv_h_full_bw = cos.mp_matching_func(tensor_2_bw, tensor_1_bw[:, 0, :], cos.mp_w2)
print(mv_p_full_fw.size())
print(mv_h_full_bw.size())

輸出如下:
具體的效果還沒有嘗試,這個隨機出來的值,輸出之後也沒什麼用,所以就輸出一些size。

torch.Size([5, 6, 30])
test.py:17: UserWarning: nn.init.kaiming_normal is now deprecated in favor of nn.init.kaiming_normal_.
  nn.init.kaiming_normal(w)
torch.Size([5, 6, 30])
torch.Size([5, 4, 30])
torch.Size([5, 6, 30, 1])
torch.Size([5, 6, 30, 1])
torch.Size([5, 4, 30, 1])
torch.Size([5, 4, 30, 1])
torch.Size([5, 6, 1])
torch.Size([5, 4, 1])

2 基於餘弦相似度的向量極值計算
看論文裏的,改到pytorch裏面。

import torch
import torch.nn as nn
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
class VectorExtrema(nn.Module):

    def forward(self,emb_1,emb_2):
        print("1size",emb_1.size())
        print("2size",emb_2.size())
        emb_1,emb_2=emb_1.numpy(),emb_2.numpy()
        cos_similarity=cosine_similarity(emb_1,emb_2)
        print("cos_similarity",cos_similarity)
        cos_similarity = np.max(cos_similarity, axis=0).mean()
        print("after( max mean): ",cos_similarity)
        return torch.from_numpy(np.array(cos_similarity) )
ve=VectorExtrema()

emb_1=torch.randn(size=(2,3))
emb_2=torch.randn(size=(2,3))
print(emb_1)
print(emb_2)
v=ve(emb_1,emb_2)
print("common cos:",torch.cosine_similarity(emb_1,emb_2))
tensor([[ 0.3011,  0.0058,  0.5957],
        [ 0.6495, -0.0936, -0.4076]])
tensor([[ 1.9169,  1.3727,  1.9278],
        [-0.0489,  0.8407, -2.1308]])
1size torch.Size([2, 3])
2size torch.Size([2, 3])
cos_similarity [[ 0.85275286 -0.83639467]
 [ 0.14057721  0.42835093]]
after( max mean):  0.6405519
common cos: tensor([0.8528, 0.4284])

這裏其實就會把前面cosine_similary中的計算出來的值進行相加,換成了選取其中的一個最大值。sklearn裏面的cosine_similary就是隻做了除整合以外的工作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章