我认为性能在这里并不重要,但我无法抗拒。zip() 函数完全重新复制两个向量(实际上更多的是矩阵转置)只是为了以“Pythonic”顺序获取数据。确定具体实施的时间会很有趣:
import math
def cosine_similarity(v1,v2):
"compute cosine similarity of v1 to v2: (v1 dot v2)/{||v1||*||v2||)"
sumxx, sumxy, sumyy = 0, 0, 0
for i in range(len(v1)):
x = v1[i]; y = v2[i]
sumxx += x*x
sumyy += y*y
sumxy += x*y
return sumxy/math.sqrt(sumxx*sumyy)
v1,v2 = [3, 45, 7, 2], [2, 54, 13, 15]
print(v1, v2, cosine_similarity(v1,v2))
Output: [3, 45, 7, 2] [2, 54, 13, 15] 0.972284251712
这经历了一次提取一个元素的类似 C 的噪音,但不进行批量数组复制,并且在单个 for 循环中完成所有重要的事情,并使用单个平方根。
ETA:将打印调用更新为函数。(原来是 Python 2.7,而不是 3.3。当前在 Python 2.7 下运行,带有一条from __future__ import print_function
语句。)无论哪种方式,输出都是相同的。
3.0GHz Core 2 Duo 上的 CPYthon 2.7.3:
>>> timeit.timeit("cosine_similarity(v1,v2)",setup="from __main__ import cosine_similarity, v1, v2")
2.4261788514654654
>>> timeit.timeit("cosine_measure(v1,v2)",setup="from __main__ import cosine_measure, v1, v2")
8.794677709375264
因此,在这种情况下,非 Python 方式的速度大约快 3.6 倍。