Pytorch如何快速計(jì)算余弦相似性矩陣
Pytorch計(jì)算余弦相似性矩陣
之前一直想找一個(gè)可以快速用矩陣相乘(可以直接GPU加速)計(jì)算余弦相似性矩陣的代碼,總算找到了。
代碼是在參考代碼的基礎(chǔ)上進(jìn)行了一些修改以適配自己的任務(wù)。
import torch
def calculate_cosine_similarity_matrix(h_emb, eps=1e-8):
r'''
'''
# h_emb (N, M)
# normalize
a_n = h_emb.norm(dim=1).unsqueeze(1)
a_norm = h_emb / torch.max(a_n, eps * torch.ones_like(a_n))
# cosine similarity matrix
sim_matrix = torch.einsum('bc,cd->bd', a_norm, a_norm.transpose(0,1))
return sim_matrix
if __name__ == "__main__":
x = torch.randn(100, 700)
sim_matrix = calculate_cosine_similarity_matrix(x, eps=1e-8)
# print(sim_matrix)
y = torch.zeros((100,100))
for i in range(100):
for j in range(100):
y[i,j] = torch.cosine_similarity(x[i].unsqueeze(dim=0), x[j].unsqueeze(dim=0))
print(y-sim_matrix)
輸出結(jié)果:
tensor([[ 0.0000e+00, 0.0000e+00, -1.8626e-09, ..., -1.7462e-09,
-2.2352e-08, -1.6764e-08],
[ 0.0000e+00, -2.3842e-07, -3.7253e-09, ..., -2.6077e-08,
-9.3132e-09, -1.1642e-08],
[-1.8626e-09, -3.7253e-09, 1.1325e-06, ..., -5.3551e-09,
-4.6566e-09, -1.8626e-08],
...,
[-1.7462e-09, -2.6077e-08, -5.3551e-09, ..., 5.9605e-07,
-2.4214e-08, -2.2352e-08],
[-2.2352e-08, -9.3132e-09, -4.6566e-09, ..., -2.4214e-08,
2.3842e-07, 9.3132e-10],
[-1.6764e-08, -1.1642e-08, -1.8626e-08, ..., -2.2352e-08,
9.3132e-10, 3.5763e-07]])
可以說(shuō)誤差非常小了,非常之nice。
接下來(lái)講講為什么這么寫(xiě)
首先回顧一下余弦相似性(圖源自百度百科):

其實(shí)一開(kāi)始我理解不了這個(gè)代碼為什么可以實(shí)現(xiàn)(本人比較呆)。
首先我們可以將輸入看作是一個(gè)向量而不是一個(gè)矩陣,那么
a_n = h_emb.norm(dim=1)
得到的是該向量的二范數(shù),接著用
a_norm = h_emb / torch.max(a_n, eps * torch.ones_like(a_n))
可以看作是
,至于為什么要加eps是防止0除。
現(xiàn)在你再把原來(lái)的向量看回是一個(gè)矩陣,那么最后的
sim_matrix = torch.einsum('bc,cd->bd', a_norm, a_norm.transpose(0,1))就好理解得到的是一個(gè)相似性矩陣了。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python接口測(cè)試之如何使用requests發(fā)起請(qǐng)求
這篇文章主要介紹了Python接口測(cè)試之如何使用requests發(fā)起請(qǐng)求問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
如何使Python中的print()語(yǔ)句運(yùn)行結(jié)果不換行
這篇文章主要介紹了如何使Python中的print()顯示當(dāng)前語(yǔ)句后不換行,print() 是一個(gè)常用函數(shù),但是每次,print()語(yǔ)句顯示后都會(huì)換行,本問(wèn)我們就來(lái)節(jié)日如何使print()顯示當(dāng)前語(yǔ)句后不換行,需要的朋友可以參考一下2022-03-03
python兒童學(xué)游戲編程知識(shí)點(diǎn)總結(jié)
在本文里小編給大家整理了關(guān)于python兒童學(xué)游戲編程知識(shí)點(diǎn)以及內(nèi)容總結(jié),需要的朋友們參考學(xué)習(xí)下。2019-06-06
基于Python實(shí)現(xiàn)配置熱加載的方法詳解
所謂的配置熱加載,也就是說(shuō)當(dāng)服務(wù)收到配置更新消息之后,我們不用重啟服務(wù)就可以使用最新的配置去執(zhí)行任務(wù)。本文將介紹如何用Python實(shí)現(xiàn)配置熱加載,需要的可以參考一下2022-07-07
Python解決多進(jìn)程間訪問(wèn)效率低的方法總結(jié)
這篇文章主要為大家詳細(xì)介紹了當(dāng)Python多進(jìn)程間訪問(wèn)效率低時(shí),應(yīng)該如何解決?文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-09-09
Python Pandas pandas.read_sql函數(shù)實(shí)例用法
在本篇文章里小編給大家整理的是一篇關(guān)于Python Pandas pandas.read_sql函數(shù)詳解內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。2021-06-06
Python+Selenium實(shí)現(xiàn)瀏覽器的控制操作
這篇文章主要為大家詳細(xì)介紹了Python+Selenium如何實(shí)現(xiàn)常見(jiàn)的瀏覽器控制操作,例如:瀏覽器參數(shù)設(shè)置、控制瀏覽器前進(jìn)/后退等,感興趣的可以了解一下2022-09-09

