計算兩向量的歐式距離,餘弦相似度

來自:http://www.mtcnn.com
>>> import numpy
>>> vec1=[[1,1,1],[2,2,2]]
>>> vec2=[[2,2,2],[1,1,1]]
>>> vec1=numpy.array(vec1)
>>> vec2=numpy.array(vec2)
>>> vec1
array([[1, 1, 1],
       [2, 2, 2]])
>>> vec2
array([[2, 2, 2],
       [1, 1, 1]])
>>> dist = numpy.sqrt(numpy.sum(numpy.square(vec1 - vec2)))  
>>> dist
2.4494897427831779
>>> numpy.linalg.norm(vec1-vec2)
2.4494897427831779


餘弦相似度:

>>> vec1
array([[1, 1, 1],
       [2, 2, 2]])
>>> vec2
array([[2, 2, 2],
       [1, 1, 1]])
>>> num=float(numpy.sum(vec1*vec2))
>>> num
12.0
>>> denom=numpy.linalg.norm(vec1)*numpy.linalg.norm(vec2)
>>> cos=num/denom
>>> denom
15.000000000000002
>>> cos
0.79999999999999993
>>> sim=0.5+0.5*cos
>>> sim
0.89999999999999991



兩者相同的地方,就是在機器學習中都可以用來計算相似度,但是兩者的含義有很大差別,以我的理解就是:

前者是看成座標系中兩個  ,來計算兩點之間的 距離 ;

後者是看成座標系中兩個 向量 ,來計算兩向量之間的 夾角 。

前者因爲是  ,所以一般指 位置 上的差別,即 距離 ;

後者因爲是 向量 ,所以一般指 方向 上的差別,即所成 夾角 。

如下圖所示:


數據項A和B在座標圖中當做點時,兩者相似度爲距離dist(A,B),可通過歐氏距離(也叫歐幾里得距離)公式計算:


當做向量時,兩者相似度爲cosθ,可通過餘弦公式計算:


假設||A||、||B||表示向量A、B的2範數,例如向量[1,2,3]的2範數爲:

√(1²+2²+3²) =  √14 

numpy中提供了範數的計算工具: linalg.norm()

所以計算cosθ起來非常方便(假定A、B均爲列向量):

num = float(A.T * B) #若爲行向量則 A * B.T
denom = linalg.norm(A) * linalg.norm(B)
cos = num / denom #餘弦值
sim = 0.5 + 0.5 * cos #歸一化

因爲有了linalg.norm(),歐氏距離公式實現起來更爲方便:

dist = linalg.norm(A - B)
sim = 1.0 / (1.0 + dist) #歸一化

關於歸一化:

因爲餘弦值的範圍是 [-1,+1] ,相似度計算時一般需要把值歸一化到 [0,1],一般通過如下方式:

sim = 0.5 + 0.5 * cosθ 
若在歐氏距離公式中,取值範圍會很大,一般通過如下方式歸一化:

sim = 1 / (1 +  dist ( X,Y ))


說完了原理,簡單扯下實際意義,舉個栗子吧:

例如某T恤從100塊降到了50塊(A(100,50)),某西裝從1000塊降到了500塊(B(1000,500))

那麼T恤和西裝都是降價了50%,兩者的價格變動趨勢一致,餘弦相似度爲最大值,即兩者有很高的 變化趨勢相似度

但是從商品價格本身的角度來說,兩者相差了好幾百塊的差距,歐氏距離較大,即兩者有較低的 價格相似度

人工智能社區


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