누군가 매우 간단한 그래픽 방식으로 코사인 유사성의 예를 제시 할 수 있습니까?
여기에 벡터를 (목록 또는 무언가로) 보여준 다음 수학을해서 어떻게 작동하는지 볼 수 있습니까?나는 초보자입니다.
다음은 비교할 두 가지 매우 짧은 텍스트입니다.
-
Julie loves me more than Linda loves me
-
Jane likes me more than Julie loves me
우리는 순전히 단어 수와 단어 순서를 무시하면서이 텍스트들이 얼마나 비슷한 지 알고 싶습니다. 우리는 두 텍스트에서 단어 목록을 만드는 것으로 시작합니다.
me Julie loves Linda than more likes Jane
이제 각 단어에 각 단어가 나타나는 횟수를 계산합니다.
me 2 2
Jane 0 1
Julie 1 1
Linda 1 0
likes 0 1
loves 2 1
more 1 1
than 1 1
우리는 단어 자체에 관심이 없습니다. 우리는이 두 개의 수직 벡터 수에만 관심이 있습니다. 예를 들어, 각 텍스트에는 'me'의 두 인스턴스가 있습니다. 우리는이 두 벡터의 한 함수, 즉 그 사이의 각도 코사인을 계산하여이 두 텍스트가 서로 얼마나 가까운지를 결정하려고합니다.두 벡터는 다음과 같습니다.
a: [2, 0, 1, 1, 0, 2, 1, 1]
b: [2, 1, 1, 0, 1, 1, 1, 1]
그들 사이의 각도의 코사인은 약 0.822입니다.이 벡터는 8 차원입니다. 코사인 유사성을 사용한다는 장점은 인간 능력을 넘어서는 질문을 시각화 할 수있는 것으로 변환한다는 것입니다. 이 경우, 이것을 0도 또는 완벽한 일치로부터 '거리'인 약 35 도의 각도로 생각할 수 있습니다.
코사인 유사성이 어떻게 계산 되는지 (계산에 사용 된 특정 연산 )보다는 "
왜
"코사인 유사성이 작동하는지 (유사성에 대한 좋은 표시를 제공하는 이유)에 대한 통찰력을 얻는 데 더 관심이 있다고 생각합니다 . 후자에 관심이 있다면,이 게시물에서 Daniel이 표시 한 참조 및 관련 SO Question을 참조하십시오 .방법과 이유를 설명하기 위해 처음에는 문제를 단순화하고 2 차원에서만 작동하는 것이 유용합니다. 일단 이것을 2D로 가져 오면 3 차원으로 생각하기가 더 쉽고 물론 더 많은 차원에서 상상하기가 더 어렵지만, 선형 대수를 사용하여 숫자 계산을 수행하고 용어로 생각하는 데 도움을 줄 수 있습니다 우리가 이것을 그릴 수는 없지만 n 차원의 선 / 벡터 / "평면"/ "구"의 집합.따라서
두 가지 차원에서
: 텍스트 유사성과 관련하여 이것은 "London"과 "Paris"라는 두 가지 용어에 중점을두고 각 단어가 몇 번이나 나오는지를 계산합니다. 우리가 비교하고자하는 두 문서. 이것은 각 문서마다 xy 평면의 한 점을 제공합니다. 예를 들어, Doc1이 파리를 한 번, 런던을 네 번 가졌다면, (1,4) 지점이이 문서를 제시 할 것입니다 (문서에 대한이 작은 평가와 관련하여). 또는 벡터 측면에서 말하면이 Doc1 문서는 원점에서 (1,4)로가는 화살표입니다. 이 이미지를 염두에두고 두 문서가 유사하다는 것이 무슨 의미이며 이것이 벡터와 어떤 관련이 있는지 생각해 봅시다.매우 유사한 문서 (이 제한된 차원 세트와 관련하여)는 파리에 대한 참조 수가 동일하거나 런던에 대한 참조 수가 동일하거나 이러한 참조의 비율이 동일 할 수 있습니다. 파리에 대한 2 개의 참조, 런던에 대한 8 개의 참조를 가진 문서 Doc2도 매우 유사하지만, 더 긴 텍스트 또는 도시 이름에 대해 더 반복적이지만 동일한 비율로만 가능합니다. 어쩌면 두 문서 모두 런던에 대한 가이드 일뿐입니다. 파리에 대한 참조 만 전달합니다 (그리고 그 도시가 얼마나 냉담한지 ;-)이제 덜 유사한 문서에도 두 도시에 대한 참조가 포함될 수 있지만 비율은 다릅니다. 아마도 Doc2는 파리를 한 번만, 런던을 일곱 번만 인용했을 것입니다.
우리의 xy 평면으로 돌아가서
, 우리가이 가상의 문서를 그리면, 그것들이 매우 유사 할 때, 그들의 벡터는 겹치며 (일부 벡터는 더 길어질 수 있지만) 공통성이 떨어지기 시작하면서이 벡터들은 갈라지기 시작합니다. 그들 사이에 더 넓은 각도를 갖도록
벡터들 사이의 각도
를 측정함으로써 , 우리는 그들의 유사성에 대한 좋은 아이디어를 얻을 수 있고, 이 각도 의
코사인
을 취함으로써, 일을 더 쉽게 만들 수 있습니다. 우리가 무엇을 어떻게 설명 하느냐에 따라 이러한 유사성. 각도가 작을수록 코사인 값이 커지고 (1에 가까워짐) 유사성이 높아집니다.Doc1이 파리 만 인용하고 Doc2가 런던 만 인용한다면, 문서는 전혀 공통점이 없습니다. Doc1은 x 축에 벡터, y 축에 Doc2, 각도 90도, 코사인 0을 갖습니다.이 경우 우리는이 문서들이 서로 직교한다고 말할 것입니다.
치수 추가
:
작은 각도 (또는 큰 코사인)로 표현 된 유사성에 대한 직관적 인 느낌으로 이제 "Amsterdam"이라는 단어를 혼합하여 3 차원으로 사물을 상상할 수 있습니다. 각각에 대한 참조는 특정 방향으로 진행되는 벡터를 가지며,이 방향이 파리와 런던을 각각 3 회 인용하지만 암스테르담 등을 인용하지 않는 문서와 비교하는 방법을 볼 수 있습니다. 10 개 또는 100 개 도시를위한 공간. 그리기는 어렵지만 개념화하기는 쉽습니다.
수식 자체에 대해 몇 마디
말함으로써 마무리하겠습니다 . 내가 말했듯이, 다른 참조는 계산에 대한 좋은 정보를 제공합니다.두 가지 차원에서 처음입니다. 두 벡터 사이의 각도의 코사인 공식은 삼각 차이 (각도 a와 각도 b)에서 파생됩니다.
cos(a - b) = (cos(a) * cos(b)) + (sin (a) * sin(b))
이 공식은 내적 제품 공식과 매우 유사합니다.
Vect1 . Vect2 = (x1 * x2) + (y1 * y2)
여기서
cos(a)
받는 대응
x
값 값, 제 벡터 등 유일한 문제는,이 인 , 등을 정확하게하지 그리고 이들 값은 단위 원에 판독해야위한 값. 이 벡터의 길이의 곱으로 나눔으로써 상기 : 수식 차기의 분모는 곳이다 및 좌표가 정규화가된다.
sin(a)
y
x
y
cos
sin
x
y
다음은 C #으로 구현 한 것입니다.
using System;
namespace CosineSimilarity
{
class Program
{
static void Main()
{
int[] vecA = {1, 2, 3, 4, 5};
int[] vecB = {6, 7, 7, 9, 10};
var cosSimilarity = CalculateCosineSimilarity(vecA, vecB);
Console.WriteLine(cosSimilarity);
Console.Read();
}
private static double CalculateCosineSimilarity(int[] vecA, int[] vecB)
{
var dotProduct = DotProduct(vecA, vecB);
var magnitudeOfA = Magnitude(vecA);
var magnitudeOfB = Magnitude(vecB);
return dotProduct/(magnitudeOfA*magnitudeOfB);
}
private static double DotProduct(int[] vecA, int[] vecB)
{
// I'm not validating inputs here for simplicity.
double dotProduct = 0;
for (var i = 0; i < vecA.Length; i++)
{
dotProduct += (vecA[i] * vecB[i]);
}
return dotProduct;
}
// Magnitude of the vector is the square root of the dot product of the vector with itself.
private static double Magnitude(int[] vector)
{
return Math.Sqrt(DotProduct(vector, vector));
}
}
}
간단하게하기 위해 벡터 a와 b를 줄입니다.
Let :
a : [1, 1, 0]
b : [1, 0, 1]
그런 다음 코사인 유사성 (Theta) :
(Theta) = (1*1 + 1*0 + 0*1)/sqrt((1^2 + 1^2))* sqrt((1^2 + 1^2)) = 1/2 = 0.5
cos 0.5의 역수는 60 도입니다.
이 파이썬 코드는 알고리즘을 구현하려는 빠르고 더러운 시도입니다.
import math
from collections import Counter
def build_vector(iterable1, iterable2):
counter1 = Counter(iterable1)
counter2 = Counter(iterable2)
all_items = set(counter1.keys()).union(set(counter2.keys()))
vector1 = [counter1[k] for k in all_items]
vector2 = [counter2[k] for k in all_items]
return vector1, vector2
def cosim(v1, v2):
dot_product = sum(n1 * n2 for n1, n2 in zip(v1, v2) )
magnitude1 = math.sqrt(sum(n ** 2 for n in v1))
magnitude2 = math.sqrt(sum(n ** 2 for n in v2))
return dot_product / (magnitude1 * magnitude2)
l1 = "Julie loves me more than Linda loves me".split()
l2 = "Jane likes me more than Julie loves me or".split()
v1, v2 = build_vector(l1, l2)
print(cosim(v1, v2))
@Bill Bell 예제를 사용하여 [R]
a = c(2,1,0,2,0,1,1,1)
b = c(2,1,1,1,1,0,1,1)
d = (a %*% b) / (sqrt(sum(a^2)) * sqrt(sum(b^2)))
또는 crossprod () 메소드의 성능을 활용합니다.
e = crossprod(a, b) / (sqrt(crossprod(a, a)) * sqrt(crossprod(b, b)))
이것은
Python
코사인 유사성을 구현 하는 간단한 코드입니다.
from scipy import linalg, mat, dot
import numpy as np
In [12]: matrix = mat( [[2, 1, 0, 2, 0, 1, 1, 1],[2, 1, 1, 1, 1, 0, 1, 1]] )
In [13]: matrix
Out[13]:
matrix([[2, 1, 0, 2, 0, 1, 1, 1],
[2, 1, 1, 1, 1, 0, 1, 1]])
In [14]: dot(matrix[0],matrix[1].T)/np.linalg.norm(matrix[0])/np.linalg.norm(matrix[1])
Out[14]: matrix([[ 0.82158384]])
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
*
* @author Xiao Ma
* mail : 409791952@qq.com
*
*/
public class SimilarityUtil {
public static double consineTextSimilarity(String[] left, String[] right) {
Map<String, Integer> leftWordCountMap = new HashMap<String, Integer>();
Map<String, Integer> rightWordCountMap = new HashMap<String, Integer>();
Set<String> uniqueSet = new HashSet<String>();
Integer temp = null;
for (String leftWord : left) {
temp = leftWordCountMap.get(leftWord);
if (temp == null) {
leftWordCountMap.put(leftWord, 1);
uniqueSet.add(leftWord);
} else {
leftWordCountMap.put(leftWord, temp + 1);
}
}
for (String rightWord : right) {
temp = rightWordCountMap.get(rightWord);
if (temp == null) {
rightWordCountMap.put(rightWord, 1);
uniqueSet.add(rightWord);
} else {
rightWordCountMap.put(rightWord, temp + 1);
}
}
int[] leftVector = new int[uniqueSet.size()];
int[] rightVector = new int[uniqueSet.size()];
int index = 0;
Integer tempCount = 0;
for (String uniqueWord : uniqueSet) {
tempCount = leftWordCountMap.get(uniqueWord);
leftVector[index] = tempCount == null ? 0 : tempCount;
tempCount = rightWordCountMap.get(uniqueWord);
rightVector[index] = tempCount == null ? 0 : tempCount;
index++;
}
return consineVectorSimilarity(leftVector, rightVector);
}
/**
* The resulting similarity ranges from −1 meaning exactly opposite, to 1
* meaning exactly the same, with 0 usually indicating independence, and
* in-between values indicating intermediate similarity or dissimilarity.
*
* For text matching, the attribute vectors A and B are usually the term
* frequency vectors of the documents. The cosine similarity can be seen as
* a method of normalizing document length during comparison.
*
* In the case of information retrieval, the cosine similarity of two
* documents will range from 0 to 1, since the term frequencies (tf-idf
* weights) cannot be negative. The angle between two term frequency vectors
* cannot be greater than 90°.
*
* @param leftVector
* @param rightVector
* @return
*/
private static double consineVectorSimilarity(int[] leftVector,
int[] rightVector) {
if (leftVector.length != rightVector.length)
return 1;
double dotProduct = 0;
double leftNorm = 0;
double rightNorm = 0;
for (int i = 0; i < leftVector.length; i++) {
dotProduct += leftVector[i] * rightVector[i];
leftNorm += leftVector[i] * leftVector[i];
rightNorm += rightVector[i] * rightVector[i];
}
double result = dotProduct
/ (Math.sqrt(leftNorm) * Math.sqrt(rightNorm));
return result;
}
public static void main(String[] args) {
String left[] = { "Julie", "loves", "me", "more", "than", "Linda",
"loves", "me" };
String right[] = { "Jane", "likes", "me", "more", "than", "Julie",
"loves", "me" };
System.out.println(consineTextSimilarity(left,right));
}
}
코사인 유사성을 계산하는 간단한 Java 코드
/**
* Method to calculate cosine similarity of vectors
* 1 - exactly similar (angle between them is 0)
* 0 - orthogonal vectors (angle between them is 90)
* @param vector1 - vector in the form [a1, a2, a3, ..... an]
* @param vector2 - vector in the form [b1, b2, b3, ..... bn]
* @return - the cosine similarity of vectors (ranges from 0 to 1)
*/
private double cosineSimilarity(List<Double> vector1, List<Double> vector2) {
double dotProduct = 0.0;
double normA = 0.0;
double normB = 0.0;
for (int i = 0; i < vector1.size(); i++) {
dotProduct += vector1.get(i) * vector2.get(i);
normA += Math.pow(vector1.get(i), 2);
normB += Math.pow(vector2.get(i), 2);
}
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}
두 벡터 A와 B는 2D 공간 또는 3D 공간에 존재하며, 이들 벡터 사이의 각도는 cos 유사성입니다. 각도가 더 크면 (최대 180도에 도달 할 수 있음) Cos 180 = -1이고 최소 각도는 0 도입니다. cos 0 = 1은 벡터가 서로 정렬되어 벡터가 유사 함을 의미합니다.
cos 90=0 (which is sufficient to conclude that the vectors A and B are not similar at all and since distance cant be negative, the cosine values will lie from 0 to 1. Hence, more angle implies implies reducing similarity (visualising also it makes sense)
'programing' 카테고리의 다른 글
특성을 사용하여 특정 작업에 대해 ASP.NET MVC에서 캐싱 방지 (0) | 2020.05.15 |
---|---|
Node.js에서 객체 복제 (0) | 2020.05.15 |
파일 중간에 특정 줄을 표시하는 빠른 유닉스 명령? (0) | 2020.05.15 |
명령 줄의 숭고한 텍스트 (0) | 2020.05.15 |
안드로이드 4.3 블루투스 저에너지 불안정 (0) | 2020.05.15 |