余弦相似度-矩陣比向量計(jì)算性能比較

背景

比如在推薦系統(tǒng)亲雪,通過算法計(jì)算出數(shù)據(jù)在返回向量時(shí),就需要比較向量之間的距離,來判斷相似度品擎。 比如用tfidf計(jì)算兩個(gè)文件之間的相似度。調(diào)用機(jī)器學(xué)習(xí)庫會(huì)返回兩個(gè)文件對(duì)應(yīng)的關(guān)鍵詞向量备徐,需要計(jì)算兩個(gè)向量之間的距離來判斷兩個(gè)文本的相似度萄传。

在實(shí)際應(yīng)用中可能是上千或上萬個(gè)文檔。我們可能需要指定一篇文檔與其他文檔的相似度蜜猾,按分?jǐn)?shù)從高到低排序秀菱,選出關(guān)聯(lián)最強(qiáng)的文檔作為推薦

先給出結(jié)論

矩陣計(jì)算性能要遠(yuǎn)遠(yuǎn)大于向量計(jì)算
以下實(shí)例均采用pyhon演示

向量表示方法

密集向量與稀疏向量
給定向量 (0.5,0,1)
密集向量表示方法 [0.5,0,1]
稀疏向量表示方法 (3,[0,2]蹭睡,[0.5,1])第一個(gè)數(shù)字3 表示向量維度3衍菱,[0,2]表示向量在0,和2上有數(shù)據(jù)肩豁,[0.5,1] 表示數(shù)據(jù)并且與[0,2]對(duì)應(yīng)脊串。也就是說0,5在0號(hào)位,2在二號(hào)位清钥。未表示出來的位置的數(shù)值是0

向量初始化方法

from pyspark.ml.linalg import SparseVector
SparseVector(3, [0,2], [0.5,1])

矩陣表示方法

矩陣有很多種表示方法 這里只介紹csr_matrix表示方法
用網(wǎng)上的一個(gè)圖來說明


image.png

圖左邊Matrix 是一個(gè)常規(guī)表示矩陣
圖右邊csr表示矩陣琼锋。
csr矩陣表示法中 只表示矩陣的非0數(shù)值及位置,在矩陣中0值較多的情況下能節(jié)約空間祟昭。
values 表示矩陣中的非0數(shù)值缕坎。
row indices 表示列標(biāo):row indices數(shù)組的第一個(gè)位置的值表示values第一個(gè)數(shù)值列標(biāo),row indices數(shù)組的第二個(gè)位置的值表示values第二個(gè)數(shù)值列標(biāo) 依次類推
column indices 表示行標(biāo) :column indices數(shù)組的第一個(gè)位置的值表示values第一個(gè)數(shù)值行標(biāo) 篡悟,column indices數(shù)組的第二個(gè)位置的值表示values第二個(gè)數(shù)值行標(biāo) 依次類推
對(duì)數(shù)值1 行標(biāo)為0谜叹,列標(biāo)也為0 所以矩陣00位置就是1
同理數(shù)值7 行標(biāo)1 列標(biāo)為0 所以矩陣的01位置就是7

from scipy.sparse import csr_matrix
mat = csr_matrix((data, (row_ind, col_ind)), shape=(M, N))

例如

from scipy.sparse import csr_matrix
mat = csr_matrix(([1,2,3,4], ([0,0,1,1],[0,1,0,1])), shape=(2, 2))
# mat.toarray() 結(jié)果:
array([[1, 2],
       [3, 4]], dtype=int64)

shape=(2,2) 表示 2x2的矩陣

SparseVector 向量轉(zhuǎn)csr_matrix 矩陣

當(dāng)然不會(huì)一個(gè)向量轉(zhuǎn)成矩陣 肯定是一組向量轉(zhuǎn)矩陣

# 假如有一組向量
vertor_list = []
data = []
row_ind = []
col_ind = []
M = len(vertor_list)
N = 0

for i, v in enumerate(vertor_list):
    N = v.size # 向量的維度 也就是矩陣的列數(shù) 所有向量的維度應(yīng)該一致
    row_ind.extend(N * [i]) # 列下表 每一行來說列下標(biāo)一致 并且都是 偏移量i
    col_ind.extend(v.indices) # 行下標(biāo) 與向量的行下標(biāo)一致
    data.extend(v.values)

mat = csr_matrix((data, (row_ind, col_ind)), shape=(M, N))

這組向量中的維度一定要一致匾寝,比如都是2維向量。假如一組向量有些是2維向量有些是3維向量荷腊,不僅數(shù)據(jù)轉(zhuǎn)換會(huì)出錯(cuò) 并且二維向量與三維向量算相似度也沒有意義

上述代碼是把一組向量轉(zhuǎn)成矩陣的方法 比如
(0,1)
(0很钓,2)
(1董栽,2)
轉(zhuǎn)成矩陣后:
[[0,1],
[0,2],
[1,2]]

如何用矩陣來代替向量的點(diǎn)乘呢锭碳?

比如有一組向量
(0,1)
(0推汽,2)
(1歹撒,2)
現(xiàn)有向量(1,1)分別于這組向量計(jì)算點(diǎn)乘
(1,1) * (0,1) = 1 * 0 + 1 * 1
(1,1) * (0,2) = 1 * 0 + 1 * 2
(1,1) * (1,2) = 1 * 1 + 1 * 2
實(shí)際上這就是矩陣

[1,1] * [[0,0,1]
           [1,2,2]]

而矩陣

 [[0,0,1]
  [1,2,2]]

正好是矩陣

[[0,1],
[0,2],
[1,2]]

的轉(zhuǎn)置
好了 基礎(chǔ)知識(shí)介紹完畢 下面開始完成的測試代碼了

測試代碼

from pyspark.ml.linalg import SparseVector
import random
from scipy.sparse import csr_matrix
import time
# num 表示生產(chǎn)多少組向量暖夭,v表示向量的維度
def build_data(num, v):
  vertor_list = []
  for i in range(num):
    data = [random.random() for i in range(v)]
    verctor = SparseVector(v, [i for i in range(v)], data)
    vertor_list.append(verctor)

  data = []
  row_ind = []
  col_ind = []
  M = len(vertor_list)
  N = 0

  for i, v in enumerate(vertor_list):
    N = v.size
    row_ind.extend(N * [i])
    col_ind.extend(v.indices)
    data.extend(v.values)

  mat = csr_matrix((data, (row_ind, col_ind)), shape=(M, N))

  return vertor_list, mat

# 性能比較
v1_list, mat1 = build_data(100, 200)
v2_list, mat2 = build_data(2, 200)

result = []
start = time.time() * 1000
for v2 in v2_list:
  for v1 in v1_list:
    result.append(v2.dot(v1))
end = time.time() * 1000
print('向量計(jì)算耗時(shí):' + str(end - start))

start = time.time() * 1000
a = mat2.dot(mat1.T)
end = time.time() * 1000
print('矩陣計(jì)算耗時(shí):' + str(end - start))

一組比較結(jié)果

向量計(jì)算耗時(shí):10.74658203125
矩陣計(jì)算耗時(shí):0.9091796875

另一組比較

v1_list, mat1 = build_data(5000, 200)
v2_list, mat2 = build_data(500, 200)

向量計(jì)算耗時(shí):152447.44384765625
矩陣計(jì)算耗時(shí):1628.77685546875

5000個(gè)數(shù)據(jù)200維向量在任何公司都不能有這么小的數(shù)據(jù)量 直接向量點(diǎn)成要2.5分鐘,而矩陣相乘只需要1.6秒邪码。直接向量點(diǎn)成不僅僅是效率低闭专。而是一個(gè)不能接受的超長時(shí)間

余弦相似度說明

假如有向量A,B |A|=向量A的摸 |B|=向量B的摸
cos(A,B) = A * B / (|A|*|B|)
當(dāng)|A| = 1 切 |B| = 1時(shí) 有 cos(A,B) = A * B
所以在求的向量時(shí) 先對(duì)向量進(jìn)行正則化 正則化后向量的摸為1,向量的點(diǎn)乘即可代表向量的余弦值

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末萤彩,一起剝皮案震驚了整個(gè)濱河市斧拍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖予权,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浪册,死亡現(xiàn)場離奇詭異,居然都是意外死亡笆环,警方通過查閱死者的電腦和手機(jī)厚者,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門账忘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熙宇,“玉大人烫止,你說我怎么就攤上這事烈拒」泖ⅲ” “怎么了赊时?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長诞吱。 經(jīng)常有香客問我,道長竭缝,這世上最難降的妖魔是什么房维? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任抬纸,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘阿趁。我一直安慰自己,他們只是感情好脖阵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布皂股。 她就那樣靜靜地躺著,像睡著了一般命黔。 火紅的嫁衣襯著肌膚如雪呜呐。 梳的紋絲不亂的頭發(fā)上悍募,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天搜立,我揣著相機(jī)與錄音以躯,去河邊找鬼。 笑死址晕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的顿锰。 我是一名探鬼主播硼控,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼牢撼!你這毒婦竟也來了匙隔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤熏版,失蹤者是張志新(化名)和其女友劉穎纷责,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撼短,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡再膳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了曲横。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喂柒。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胳喷,到底是詐尸還是另有隱情湃番,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布吭露,位于F島的核電站吠撮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏讲竿。R本人自食惡果不足惜泥兰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望题禀。 院中可真熱鬧鞋诗,春花似錦、人聲如沸迈嘹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秀仲。三九已至融痛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間神僵,已是汗流浹背雁刷。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留保礼,地道東北人沛励。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像炮障,于是被迫代替她去往敵國和親目派。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355