我想计算两个列表之间的余弦相似度,比如说,列表1是dataSetI,列表2是dataSetII。
假设dataSetI是[3,45,7,2],dataSetII是[2,54,13,15]。列表的长度总是相等的。我想将余弦相似度报告为0到1之间的数。
dataSetI = [3, 45, 7, 2]
dataSetII = [2, 54, 13, 15]
def cosine_similarity(list1, list2):
# How to?
pass
print(cosine_similarity(dataSetI, dataSetII))
不使用任何导入
math.sqrt (x)
可以用
x * * 5
如果不使用numpy.dot(),您必须使用列表理解创建自己的dot函数:
def dot(A,B):
return (sum(a*b for a,b in zip(A,B)))
然后它只是一个应用余弦相似度公式的简单问题:
def cosine_similarity(a,b):
return dot(a,b) / ( (dot(a,a) **.5) * (dot(b,b) ** .5) )
这里有一个实现,也适用于矩阵。它的行为完全像sklearn余弦相似度:
def cosine_similarity(a, b):
return np.divide(
np.dot(a, b.T),
np.linalg.norm(
a,
axis=1,
keepdims=True
)
@ # matrix multiplication
np.linalg.norm(
b,
axis=1,
keepdims=True
).T
)
符号@代表矩阵乘法。看到
“at”(@)符号在Python中有什么作用?
你可以使用SciPy(最简单的方法):
from scipy import spatial
dataSetI = [3, 45, 7, 2]
dataSetII = [2, 54, 13, 15]
print(1 - spatial.distance.cosine(dataSetI, dataSetII))
注意,space .distance.cos()给出了一个不相似度(距离)值,因此要获得相似度,需要从1中减去该值。
另一种解决方法是自己编写函数,甚至考虑不同长度的列表的可能性:
def cosineSimilarity(v1, v2):
scalarProduct = moduloV1 = moduloV2 = 0
if len(v1) > len(v2):
v2.extend(0 for _ in range(len(v1) - len(v2)))
else:
v2.extend(0 for _ in range(len(v2) - len(v1)))
for i in range(len(v1)):
scalarProduct += v1[i] * v2[i]
moduloV1 += v1[i] * v1[i]
moduloV2 += v2[i] * v2[i]
return round(scalarProduct/(math.sqrt(moduloV1) * math.sqrt(moduloV2)), 3)
dataSetI = [3, 45, 7, 2]
dataSetII = [2, 54, 13, 15]
print(cosineSimilarity(dataSetI, dataSetII))