我写了一个方法来计算两个数组之间的余弦距离:
def cosine_distance(a, b):
if len(a) != len(b):
return False
numerator = 0
denoma = 0
denomb = 0
for i in range(len(a)):
numerator += a[i]*b[i]
denoma += abs(a[i])**2
denomb += abs(b[i])**2
result = 1 - numerator / (sqrt(denoma)*sqrt(denomb))
return result
Run Code Online (Sandbox Code Playgroud)
在大型阵列上运行它可能会非常慢.这个方法的优化版本会运行得更快吗?
更新:我已经尝试了迄今为止的所有建议,包括scipy.这是要击败的版本,结合迈克和史蒂夫的建议:
def cosine_distance(a, b):
if len(a) != len(b):
raise ValueError, "a and b must be same length" #Steve
numerator = 0
denoma = 0
denomb = 0
for i in range(len(a)): #Mike's optimizations:
ai = a[i] #only calculate …Run Code Online (Sandbox Code Playgroud) 试图模仿Excel的SUMPRODUCT功能:
SUMPRODUCT(v1, v2, ..., vN) =
v1[0]*v2[0]*...*vN[0] + v1[1]*v2[1]*...*vN[1] + ... + v1[n]*v2[n]*...*vN[n]
Run Code Online (Sandbox Code Playgroud)
其中n是每个向量中元素的数量.
这类似于点积,但对于多个向量.我阅读了常规点积的非常详细的讨论,但我不知道如何将它干净地扩展到多个向量.作为参考,我正在复制那里提出的优化代码,我将其(通常)移植到Python 3.BTW,对于dot产品,最后一种方法仍然在P3K中获胜.
def d0(v1,v2):
"""
d0 is Nominal approach:
multiply/add in a loop
"""
out = 0
for k in range(len(v1)):
out += v1[k] * v2[k]
return out
def d1(v1,v2):
"""
d1 uses a map
"""
return sum(map(mul,v1,v2))
def d3(v1,v2):
"""
d3 uses a starmap (itertools) to apply the mul operator on an zipped (v1,v2)
"""
return sum(starmap(mul,zip(v1,v2)))
Run Code Online (Sandbox Code Playgroud)