두 숫자 목록 간의 코사인 유사성
두 목록 사이 의 코사인 유사성 을 계산해야합니다. 예를 들어 목록 1은 이고 목록 2는 입니다. numpy 또는 통계 모듈 과 같은 것을 사용할 수 없습니다 . 나는 공통 모듈 (수학 등)을 사용해야한다 (그리고 소비되는 시간을 줄이기 위해 가능한 한 최소한의 모듈).dataSetI
dataSetII
하자 말은 dataSetI
있다 [3, 45, 7, 2]
하고 dataSetII
있다 [2, 54, 13, 15]
. 목록의 길이는 항상 동일합니다.
물론 코사인 유사성은 0과 1 사이 이며 ,이를 위해를 사용하여 세 번째 또는 네 번째 십진수로 반올림됩니다 format(round(cosine, 3))
.
도와 주셔서 미리 감사드립니다.
SciPy 를 시도해보십시오 . 예를 들어 "적분을 수치 적으로 계산하고 미분 방정식, 최적화 및 희소 행렬을 해결하는 루틴"과 같은 유용한 과학 루틴이 많이 있습니다. 수 처리를 위해 초고속 최적화 NumPy를 사용합니다. 설치는 여기 를 참조 하십시오 .
spatial.distance.cosine은 유사성이 아니라 거리를 계산합니다 . 따라서 유사성 을 얻으려면 1에서 값을 빼야합니다 .
from scipy import spatial
dataSetI = [3, 45, 7, 2]
dataSetII = [2, 54, 13, 15]
result = 1 - spatial.distance.cosine(dataSetI, dataSetII)
numpy
만 기반으로 다른 버전
from numpy import dot
from numpy.linalg import norm
cos_sim = dot(a, b)/(norm(a)*norm(b))
cosine_similarity
함수 양식 문서를 사용할 수 있습니다.sklearn.metrics.pairwise
In [23]: from sklearn.metrics.pairwise import cosine_similarity
In [24]: cosine_similarity([[1, 0, -1]], [[-1,-1, 0]])
Out[24]: array([[-0.5]])
나는 여기서 성능이 그다지 중요하지 않다고 생각하지만 저항 할 수는 없다. 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 : 인쇄 호출을 함수로 업데이트했습니다. (원본은 3.3이 아니라 Python 2.7이었습니다. 현재는 from __future__ import print_function
명령문을 사용하여 Python 2.7에서 실행됩니다 .) 출력은 어느 쪽이든 동일합니다.
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
따라서이 경우 비 파이썬 방식은 약 3.6 배 더 빠릅니다.
I did a benchmark based on several answers in the question and the following snippet is believed to be the best choice:
def dot_product2(v1, v2):
return sum(map(operator.mul, v1, v2))
def vector_cos5(v1, v2):
prod = dot_product2(v1, v2)
len1 = math.sqrt(dot_product2(v1, v1))
len2 = math.sqrt(dot_product2(v2, v2))
return prod / (len1 * len2)
The result makes me surprised that the implementation based on scipy
is not the fastest one. I profiled and find that cosine in scipy takes a lot of time to cast a vector from python list to numpy array.
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)
You can round it after computing:
cosine = format(round(cosine_measure(v1, v2), 3))
If you want it really short, you can use this one-liner:
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)))
without using any imports
math.sqrt(x)
can be replaced with
x** .5
without using numpy.dot() you have to create your own dot function using list comprehension:
def dot(A,B):
return (sum(a*b for a,b in zip(A,B)))
and then its just a simple matter of applying the cosine similarity formula:
def cosine_similarity(a,b):
return dot(a,b) / ( (dot(a,a) **.5) * (dot(b,b) ** .5) )
You can do this in Python using simple function:
def get_cosine(text1, text2):
vec1 = text1
vec2 = text2
intersection = set(vec1.keys()) & set(vec2.keys())
numerator = sum([vec1[x] * vec2[x] for x in intersection])
sum1 = sum([vec1[x]**2 for x in vec1.keys()])
sum2 = sum([vec2[x]**2 for x in vec2.keys()])
denominator = math.sqrt(sum1) * math.sqrt(sum2)
if not denominator:
return 0.0
else:
return round(float(numerator) / denominator, 3)
dataSet1 = [3, 45, 7, 2]
dataSet2 = [2, 54, 13, 15]
get_cosine(dataSet1, dataSet2)
Using numpy compare one list of numbers to multiple lists(matrix):
def cosine_similarity(vector,matrix):
return ( np.sum(vector*matrix,axis=1) / ( np.sqrt(np.sum(matrix**2,axis=1)) * np.sqrt(np.sum(vector**2)) ) )[::-1]
You can use this simple function to calculate the cosine similarity:
def cosine_similarity(a, b):
return sum([i*j for i,j in zip(a, b)])/(math.sqrt(sum([i*i for i in a]))* math.sqrt(sum([i*i for i in b])))
If you happen to be using PyTorch already, you should go with their CosineSimilarity implementation.
Suppose you have two n
-dimensional numpy.ndarray
s, v1
and v2
, i.e. their shapes are both (n,)
. Here's how you get their cosine similarity:
import torch
import torch.nn as nn
cos = nn.CosineSimilarity()
cos(torch.tensor([v1]), torch.tensor([v2])).item()
Or suppose you have two numpy.ndarray
s w1
and w2
, whose shapes are both (m, n)
. The following gets you a list of cosine similarities, each being the cosine similarity between a row in w1
and the corresponding row in w2
:
cos(torch.tensor(w1), torch.tensor(w2)).tolist()
참고URL : https://stackoverflow.com/questions/18424228/cosine-similarity-between-2-number-lists
'code' 카테고리의 다른 글
IntelliJ가 특정 파일을 올바르게 인식하지 못하고 대신 텍스트 파일로 멈춤 (0) | 2020.08.29 |
---|---|
WinForms 응용 프로그램에 명령 줄 인수를 어떻게 전달합니까? (0) | 2020.08.29 |
프로젝트 ': app'의 종속성 'com.android.support:support-annotations'와 충돌합니다. (0) | 2020.08.29 |
javascript / Node.js에서 시간을 어떻게 얻습니까? (0) | 2020.08.29 |
URL에서 .html을 제거하는 방법? (0) | 2020.08.29 |