Nie sądzę, żeby wydajność miała tu duże znaczenie, ale nie mogę się oprzeć. Funkcja zip () całkowicie ponownie kopiuje oba wektory (właściwie to raczej transpozycja macierzy) tylko po to, aby uzyskać dane w „Pythonowej” kolejności. Byłoby ciekawie zaplanować wdrożenie nakrętek i śrub:
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
Przechodzi przez szum podobny do C podczas wyodrębniania elementów pojedynczo, ale nie powoduje masowego kopiowania tablicy i wykonuje wszystko, co ważne w pojedynczej pętli for, i wykorzystuje pojedynczy pierwiastek kwadratowy.
ETA: Zaktualizowano wywołanie drukowania, aby było funkcją. (Oryginał to Python 2.7, a nie 3.3. Bieżący działa pod Pythonem 2.7 z rozszerzeniemfrom __future__ import print_function
instrukcją.) Dane wyjściowe są takie same, tak czy inaczej.
CPYthon 2.7.3 na 3,0 GHz Core 2 Duo:
>>> 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
Tak więc w tym przypadku sposób niepytoniczny jest około 3,6 razy szybszy.