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)講講為什么這么寫
首先回顧一下余弦相似性(圖源自百度百科):
其實(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圖像運(yùn)算之圖像灰度直方圖對(duì)比詳解
本篇文章將結(jié)合直方圖分別對(duì)比圖像灰度變換前后的變化,方便大家更清晰地理解灰度變換和閾值變換,文中的示例代碼講解詳細(xì),需要的可以參考一下2022-08-08對(duì)Python中for復(fù)合語(yǔ)句的使用示例講解
今天小編就為大家分享一篇對(duì)Python中for復(fù)合語(yǔ)句的使用示例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-11-11Python機(jī)器學(xué)習(xí)庫(kù)scikit-learn入門開(kāi)發(fā)示例
scikit-learn是一個(gè)開(kāi)源Python語(yǔ)言機(jī)器學(xué)習(xí)工具包,它涵蓋了幾乎所有主流機(jī)器學(xué)習(xí)算法的實(shí)現(xiàn),并且提供了一致的調(diào)用接口。它基于Numpy和scipy等Python數(shù)值計(jì)算庫(kù),提供了高效的算法實(shí)現(xiàn)2022-07-07Python調(diào)用API接口實(shí)現(xiàn)人臉識(shí)別
本文主要介紹了Python調(diào)用API接口實(shí)現(xiàn)人臉識(shí)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02Python設(shè)置matplotlib.plot的坐標(biāo)軸刻度間隔以及刻度范圍
這篇文章主要介紹了Python設(shè)置matplotlib.plot的坐標(biāo)軸刻度間隔以及刻度范圍,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06python實(shí)現(xiàn)盲盒抽獎(jiǎng)功能(減庫(kù)存)
本文主要介紹了python實(shí)現(xiàn)盲盒抽獎(jiǎng)功能,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09Python pandas dataframe之重命名相同列名
這篇文章主要介紹了Python pandas dataframe之重命名相同列名方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09淺談selenium如何應(yīng)對(duì)網(wǎng)頁(yè)內(nèi)容需要鼠標(biāo)滾動(dòng)加載的問(wèn)題
這篇文章主要介紹了淺談selenium如何應(yīng)對(duì)網(wǎng)頁(yè)內(nèi)容需要鼠標(biāo)滾動(dòng)加載的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03