我想计算两个列表之间的余弦相似度,比如说,列表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))

当前回答

你应该试试SciPy。它有一堆有用的科学例程,例如,“用于数值计算积分、求解微分方程、优化和稀疏矩阵的例程。”它使用超高速优化的NumPy进行数字处理。请参见此处安装。

注意,space .distance.cos计算距离,而不是相似度。所以,你必须用1减去这个值才能得到相似度。

from scipy import spatial

dataSetI = [3, 45, 7, 2]
dataSetII = [2, 54, 13, 15]
result = 1 - spatial.distance.cosine(dataSetI, dataSetII)

其他回答

import math
from itertools import izip

def dot_product(v1, v2):
    return sum(map(lambda x: x[0] * x[1], izip(v1, v2)))

def cosine_measure(v1, v2):
    prod = dot_product(v1, v2)
    len1 = math.sqrt(dot_product(v1, v1))
    len2 = math.sqrt(dot_product(v2, v2))
    return prod / (len1 * len2)

你可以在计算后四舍五入:

cosine = format(round(cosine_measure(v1, v2), 3))

如果你想让它真的很短,你可以使用下面的一行代码:

from math import sqrt
from itertools import izip

def cosine_measure(v1, v2):
    return (lambda (x, y, z): x / sqrt(y * z))(reduce(lambda x, y: (x[0] + y[0] * y[1], x[1] + y[0]**2, x[2] + y[1]**2), izip(v1, v2), (0, 0, 0)))

你应该试试SciPy。它有一堆有用的科学例程,例如,“用于数值计算积分、求解微分方程、优化和稀疏矩阵的例程。”它使用超高速优化的NumPy进行数字处理。请参见此处安装。

注意,space .distance.cos计算距离,而不是相似度。所以,你必须用1减去这个值才能得到相似度。

from scipy import spatial

dataSetI = [3, 45, 7, 2]
dataSetII = [2, 54, 13, 15]
result = 1 - spatial.distance.cosine(dataSetI, dataSetII)

另一个版本,如果你有一个场景,你有一个向量列表和一个查询向量,你想要计算查询向量与列表中所有向量的余弦相似度,你可以用下面的方式一次性完成:

>>> import numpy as np

>>> A      # list of vectors, shape -> m x n
array([[ 3, 45,  7,  2],
       [ 1, 23,  3,  4]])

>>> B      # query vector, shape -> 1 x n
array([ 2, 54, 13, 15])

>>> similarity_scores = A.dot(B)/ (np.linalg.norm(A, axis=1) * np.linalg.norm(B))

>>> similarity_scores
array([0.97228425, 0.99026919])

不使用任何导入

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) )

你可以在Python中使用简单的函数来实现:

def get_cosine(text1, text2):
  vec1 = text1
  vec2 = text2
  intersection = set(vec1.keys()) & set(vec2.keys())
  numerator = sum([vec1[x] * vec2[x] for x in intersection])
  sum1 = sum([vec1[x]**2 for x in vec1.keys()])
  sum2 = sum([vec2[x]**2 for x in vec2.keys()])
  denominator = math.sqrt(sum1) * math.sqrt(sum2)
  if not denominator:
     return 0.0
  else:
     return round(float(numerator) / denominator, 3)
dataSet1 = [3, 45, 7, 2]
dataSet2 = [2, 54, 13, 15]
get_cosine(dataSet1, dataSet2)