Je suppose que les performances n'ont pas beaucoup d'importance ici, mais je ne peux pas résister. La fonction zip() recopie complètement les deux vecteurs (plutôt une transposition matricielle, en fait) juste pour obtenir les données dans l'ordre "Pythonique". Il serait intéressant de voir l'implémentation des rouages :
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
Cela permet d'extraire les éléments un par un, comme en C, mais ne fait pas de copie de tableau en masse et fait tout ce qui est important dans une seule boucle for, et utilise une seule racine carrée.
ETA : Mise à jour de l'appel print pour être une fonction. (L'original était Python 2.7, pas 3.3. La version actuelle fonctionne sous Python 2.7 avec un fichier from __future__ import print_function
déclaration.) Le résultat est le même, dans les deux cas.
CPYthon 2.7.3 sur Core 2 Duo 3.0GHz :
>>> 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
Ainsi, la méthode non-pythonique est environ 3,6 fois plus rapide dans ce cas.