> For the complete documentation index, see [llms.txt](https://soojle.gitbook.io/project/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://soojle.gitbook.io/project/undefined-2/nlp/document-similarity.md).

# 문서 유사도(Document Similarity)

## 개요

![](/files/-LpcVzuzXibW5NPvg99E)

일반적으로 사람은 문서들 간에 동일한 단어 또는 비슷한 단어가 얼마나 공통적으로 많이 사용되었는지에 의존하여 문사의 유사도를 측정한다. 머신 또한 해당 정보를 바탕으로 각 문서의 단어들을 여러 방법으로 수치화한 후, 각 벡터 간의 유사도를 측정함으로써 계산이 가능해진다.

## 코사인 유사도(Cosine Similarity)

![](/files/-LpcWIRphh2Xe57vGbAN)

코사인 유사도는 두 벡터 간의 코사인 각도를 이용하여 구할 수 있는 두 벡터의 유사도를 의미한다. 두 벡터의 방향이 **완전히 동일한 경우에는 1**, 완전히 반**대 방향의 성격을 가질 경우 -1**을 반환하게 되며, 무조건 해당 값 사이로 유사도 정보를 반환한다.

두 벡터 A, B에 대해서 코사인 유사도는 식으로 표현하면 다음과 같다.

![](/files/-LpcWh3MSZBua_MVuikS)

예를 들어 다음과 같은 행렬을 벡터로 취급하여 코사인 유사도를 계산해보면 다음과 같이 결과가 나온다.

```python
from numpy import dot
from numpy.linalg import norm
import numpy as np
def cos_sim(A, B):
       return dot(A, B)/(norm(A)*norm(B))
       
doc1=np.array([0,1,1,1])
doc2=np.array([1,0,1,1])
doc3=np.array([2,0,2,2])
print(cos_sim(doc1, doc2)) 
print(cos_sim(doc1, doc3)) 
print(cos_sim(doc2, doc3))
# 0.67
# 0.67
# 1.00
```

## **유클리드 거리(Euclidean distance)**

유클리드 거리(euclidean distance)는 다차원 공간에서 점과 점 사이의 거리를 구하는 비교적 매우 직관적인 공식이다.  두 개의 점 p와 q가 각각 **p=(p1,p2,p3,...,pn)**&#xACFC; **q=(q1,q2,q3,...,qn)**&#xC758; 좌표를 가질 때 두 점 사이의 거리를 계산하는 유클리드 거리 공식은 다음과 같다.

![](/files/-LpcXvEfgFFX_ztQ9b4A)

![](/files/-LpcY-3YPxd7TD2YIN6R)

```python
import numpy as np
def dist(x,y):   
    return np.sqrt(np.sum((x-y)**2))

doc1 = np.array((2,3,0,1))
doc2 = np.array((1,2,3,1))
doc3 = np.array((2,1,2,2))
docQ = np.array((1,1,0,1))

print(dist(doc1,docQ))
print(dist(doc2,docQ))
print(dist(doc3,docQ))
# 2.23606797749979
# 3.1622776601683795
# 2.449489742783178
```

## **자카드 유사도(Jaccard similarity)**

자카드 유사도는 벡터가 아닌 단어의 빈도수를 집합 개념으로 보고, 교집합을 통해 유사도를 측정하는 방법이다. 자카드 유사도를 구하는 함수를 J라고 하였을 때, 자카드 유사도 함수 J는 아래와 같다.

![](/files/-LpcYePkzLxWR09gov32)

```python
doc1 = "apple banana everyone like likey watch card holder"
doc2 = "apple banana coupon passport love you"

# 토큰화를 수행합니다.
tokenized_doc1 = doc1.split()
tokenized_doc2 = doc2.split()

# 토큰화 결과 출력
print(tokenized_doc1)
print(tokenized_doc2)
# ['apple', 'banana', 'everyone', 'like', 'likey', 'watch', 'card', 'holder']
# ['apple', 'banana', 'coupon', 'passport', 'love', 'you']

union = set(tokenized_doc1).union(set(tokenized_doc2))
intersection = set(tokenized_doc1).intersection(set(tokenized_doc2))
print(len(intersection)/len(union))
# 0.16666666666666666
```
