关于相似度计算方法的python实现
参考
欧氏距离,曼哈顿距离:计算两个向量间的相似程度,值越小,相似度越高
高斯距离(标准化欧氏距离):计算两个向量间的相似程度,值越大,相似度越高
余弦相似度:取值范围是[-1,1],相同两个向量的之间的相似度为cos(0°)=1,方向上正相关;cos(180°) = -1,方向上负相关。
**pearson系数:**用于研究不同变量(n个变量)两两间的相关程度,相关性矩阵(n x n)中的取值范围[-1,1], 正相关则>0,负相关则<0,无关则=0)
Note:
- 欧式距离的数值受到维度的影响,余弦相似度在高维的情况下也依然保持低维完全相同时相似度为1等性质。
- 欧式距离体现的是距离上的绝对差异,余弦距离体现的是方向上的相对差异
import unittest
import numpy as np
import math
'''参考 https://www.cnblogs.com/chenpeng9/articles/4605577.html,https://blog.csdn.net/qq_32350131/article/details/104567014'''
'''欧几里得距离(越小相似度越高)'''
def euclidean(p,q):
'''
:param p: list
:param q: list
:return:
'''
if(len(p) != len(q)):
raise Exception("feature length must be the same")
p,q = np.array(p),np.array(q)
d1 = np.sqrt(np.sum(np.square(p - q)))
return d1
'''pearson系数(用于研究不同变量(n)间的相似程度,相关性矩阵(n x n)中的取值范围[-1,1], 正相关则>0,负相关则<0,无关则=0)'''
def pearson(p,q):
if (len(p) != len(q)):
raise Exception("feature length must be the same")
my_rho = np.corrcoef(p, q)
return my_rho
'''曼哈顿距离'''
def manhattan(p,q):
'''
:param p: list
:param q: list
:return:
'''
if (len(p) != len(q)):
raise Exception("feature length must be the same")
p, q = np.array(p), np.array(q)
dist = np.linalg.norm(p - q, ord=1)
return dist
'''高斯距离(指数距离,或者标准化欧式距离),需要先计算欧式距离'''
def exponent_distance(p,q,y):
'''
:param p: list
:param q: list
:param y: 缩放因子
:return:
'''
p, q = np.array(p), np.array(q)
d = euclidean(p,q)
d1 = np.exp(-y * d)
return d1
'''余弦相似度(取值范围是[-1,1],主要用于研究两个向量在方向上的相似度,两个相同向量之间的相似度为: cos(0) = 1)'''
def cosine(p,q):
if (len(p) != len(q)):
raise Exception("feature length must be the same")
d = np.dot(p, q) / (np.linalg.norm(p) * np.linalg.norm(q))
return d
'''策略1: 通过标准化欧式距离计算两向量的绝对距离,通过余弦相似度计算两向量的方向相似度'''
def cal_simliarity_cosine_divide_euclidean(p,q):
'''
:param p: list
:param q: list
:param y: 缩放因子
:return: 欧式距离,余弦相似度
'''
return abs(cosine(p,q)) / euclidean(p,q)
'''对所有距离进行汇总'''
def cal_simliarity(mode,p,q,y):
'''
:param mode: EXPONENT_DISTANCE,EUCLIDEAN,COSINE, EUCLIDEAN_COSINE
:param p: list
:param q: list
:param y: 缩放因子
:return: 相似度取值
'''
if(mode == "EXPONENT_DISTANCE"):
return exponent_distance(p,q,y)
elif(mode == "EUCLIDEAN"):
return euclidean(p,q)
elif(mode == "COSINE"):
return cosine(p,q)
elif(mode=="EUCLIDEAN_COSINE"):
return cal_simliarity_cosine_divide_euclidean(p,q)
else:
raise Exception("Please enter the correct mode name...")
class MyTest(unittest.TestCase):
def test_euclidean(self):
p = [1,0]
q = [5,3]
sim = euclidean(p,q)
print(sim)
def test_manhattan(self):
p = [1,0]
q = [5,3]
sim = manhattan(p,q)
print(sim)
def test_pearson(self):
p = [1,0]
q = [5,3]
sim = pearson(p,q)
print(sim)
def test_cosine(self):
p = [1, 0]
q = [5, 3]
sim = cosine(p, q)
print(sim)
def test_exponent_distance(self):
p = [1, 0]
q = [5, 3]
sim = exponent_distance(p, q, y=1)
print(math.pow(math.e,(-5)))
print(sim)
q1 = [2,3]
sim = exponent_distance(p, q1, y=1)
print(sim)
|