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

当前回答

如果你碰巧已经在使用PyTorch,你应该使用他们的cosessimilarity实现。

假设有两个n维的numpy。ndarray, v1和v2,即它们的形状都是(n,)。以下是如何获得它们的余弦相似度:

import torch
import torch.nn as nn

cos = nn.CosineSimilarity()
cos(torch.tensor([v1]), torch.tensor([v2])).item()

或者假设有两个numpy。ndarray w1和w2,它们的形状都是(m, n)。下面给你一个余弦相似度列表,每个都是w1中的一行和w2中的相应行之间的余弦相似度:

cos(torch.tensor(w1), torch.tensor(w2)).tolist()

其他回答

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

我们可以用简单的数学公式计算余弦相似度。 Cosine_similarity = 1-(向量的点积/向量范数的积)。我们可以定义两个函数分别用于点积和范数的计算。

def dprod(a,b):
    sum=0
    for i in range(len(a)):
        sum+=a[i]*b[i]
    return sum

def norm(a):

    norm=0
    for i in range(len(a)):
    norm+=a[i]**2
    return norm**0.5

    cosine_a_b = 1-(dprod(a,b)/(norm(a)*norm(b)))

你应该试试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)

你可以使用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))

所有答案都非常适合不能使用NumPy的情况。如果可以的话,这里有另一种方法:

def cosine(x, y):
    dot_products = np.dot(x, y.T)
    norm_products = np.linalg.norm(x) * np.linalg.norm(y)
    return dot_products / (norm_products + EPSILON)

还要记住EPSILON = 1e-07,以确保组织安全。