본문 바로가기

개발/NLP Trends

Weekly NLP #05 Review : 얘랑 나랑 얼마나 비슷해?

※ 본 블로그 포스트는 박지호님의 "Weekly NLP" 내용을 채용하여 개인공부를 기록한 포스트입니다.
원작자의 허가를 맡았으며 불법적인 공유가 아님을 미리 알립니다.

 

여러분은 어떤 사람과 얼마나 비슷한지 숫자로 표현할 수 있으신가요?
"친구 A보다 B가 나와 좀 더 비슷한 거 같아.." 라는 어찌어찌 할 수 있을거 같은데, 아무래도 절대적인 숫자를 생각해내기는 것은 조금 애매한 것 같죠?

하지만 지난 2주 동안 배운 vector는 다릅니다! 명확하게 2개의 vector 간의 거리를 계산하는 방법을 배워봅시다. 그리고 지난 주 배운 Word Embedding을 예시로 왜 거리가 중요한 지 알아보겠습니다.

NLP에서 Vector의 역할은?

이전에 소개한 Bag-of-Word (BoW) vector 또는 tf-idf vector는 문장을 단어의 빈도수를 계산하여 N차원의 column vector로 표현한 것을 배웠습니다. 여기서 N은 전체 단어 (vocabulary)의 수수자라 단어가 많을수록 커진다고 했죠.

전에 나온 Word Embedding은 각 단어들을 GloVe나 skipgram 같은 알고리즘으로 각 단어들을 비교적 작은 100차원, 300차원 등의 vector로 줄여서 만들수 있었죠.

핵심은 문장, 문서, 그리고 단어를 숫자들로 이루어진 vector로 만들어 N차원의 공간의 하나의 점으로 바꾸어 표현한다는 것 입니다.

2차원으로 줄여서 표현한 word embedding space., 출처 : https://jiho-ml.com/weekly-nlp-5/

두 개의 vector 사이의 거리를 재보자 : Euclideian Distance

$$distance(A, B) = \sqrt{(a_1 - b_1)^2 + (a_2 - b_2)^2 + \cdots + (a_n - b_n)^2}$$

2차원에서 두 점 사이의 거리를 재는것, 중학교 때 배우셨죠? 그걸 N차원으로 확대해봅시다.
개념적으로 보아 두 점 사이에 줄을 긋고, 그 줄의 길이를 계산하는 것입니다.

2D에서 euclidean distance, 출처 : https://jiho-ml.com/weekly-nlp-5/

두 개의 vector 사이의 각을 재보자 ; Cosine Similarity

$Cosine\,Similarity$는 두 개의 vector들 사이의 각도를 계산합니다. 그렇기 때문에 크기(magnitude)는 무시되고, 방향의 차이만 계산됩니다.

$$similarity = cos(\theta) = \frac{A \cdot B}{\|A\| \|B\|} = \frac{\sum_{i=1}^{n}A_iB_i}{\sqrt{\sum_{i=1}^{n}A_i^2}\sqrt{\sum_{i=1}^{n}B_i^2}}$$

위 수식을 풀어서 이해하면, 만약 vector A와 vector B가:

  • 같은 방향(0도)이라면 1,
  • 완전히 반대 방향(180도)이라면 -1,
  • 서로 독립적(90도)이라면 0.

$cosine\,distance$는 $cosine\,similarity$랑 같은 걸 그냥 뒤집어서 생각한겁니다.

$Cosine\,Distance = 1-Cosine\,Similarity$

만약 vector A와 vector B가:

  • 같은 방향(0도)이라면 0,
  • 완전히 반대 방향(180도)이라면 2,
  • 서로 독립적(90도)이라면 1

그래서 뭘 쓰라고요?

NLP문제에서는 cosine similarity가 주로 쓰입니다. 왜냐면 vector를 단어의 빈도수(frequency)로 계산하는 경우가 많기 때문입니다. 어느 단어가 몇 번 등장하냐는 글 길이에 영향을 많이 받고, 데이터 안 모든 글이 같은 단어 수를 가지기는 힘듭니다.

예를 들어, 어느 긴 글에 "bank"라는 단어가 100번 등장하고, 어느 짧은 글에는 20번 등장한다 했을 때, 이 두 글이 경제라는 비슷한 주제라는 것을 알아내려면, 절대적 거리를 계산하는 euclidean distance보다는 각도를 계산하는 cosine similarity를 쓰는게 더 적합할 것 입니다. 다만 항상 정답이 될 수 없기 때문에 본인이 계산하려는 vector의 수학적인 성격을 잘 파악해서 결정하는 것이 중요합니다.

A와 B의 euclidean distance와 cosine similarity, 출처 : https://jiho-ml.com/weekly-nlp-5/

이처럼 cosine distance는 vector들 간의 유사성을 계산하기 위해 쓰입니다.
Word2Vec 뿐만 아니라 Document Embedding, Item2Vec 등 다양한 모델과 데이터에 활용될 수 있습니다.


5번째 포스팅을 시작해보겠습니다!
오늘 더 자세히 공부해볼 것은 벡터의 유사도(Vector Similarity) 입니다!
기계가 문서의 유사도를 구할 때 문서들 간에 동일한 단어 또는 비슷한 단어가 얼마나 공통적으로 많이 사용되었는지에 의존합니다. 즉, 유사도의 성능은 단어들을 어떤 방법으로 수치화하여 표현했는지, 문서 간의 단어들의 차이를 어떤 방법으로 계산했는지에 따라 달라지게 됩니다.

1. 코사인 유사도 (Cosine Similarity)

두 벡타 간의 코사인 각도를 이용하여 구할 수 있는 벡터의 유사도를 의미한다. 두 벡터의 방향이 완전히 동일한 경우에는 1의 값을 가지고, 90도의 각을 이루면 0의 값, 180도로 반대의 방향을 가지면 -1의 값을 가지게 된다. 즉, -1 이상 1이하의 값을 가지며 값이 1에 가까울수록 유사도가 높다고 판단할 수 있다. 직관적으로 이해하자면 두 벡터가 가르키는 방향이 얼마나 유사한지를 의미한다.

$$similarity = cos(\theta) = \frac{A \cdot B}{\|A\| \|B\|} = \frac{\sum_{i=1}^{n}A_iB_i}{\sqrt{\sum_{i=1}^{n}(A_i)^2}\sqrt{\sum_{i=1}^{n}(B_i)^2}}$$

출처 : https://codong.tistory.com/35

방향이 얼마나 유사한지를 판단하는 것을 두 벡터 사이의 각도를 구하는 것으로 접근했다. 왼쪽 그림은 두 벡터 a, b의 스칼라곱($A \cdot B$)을 표현한 그림이다. 오른쪽 그림을 통해 $\theta$값이 작아지면 자연스럽게 $cos \theta$의 값이 1에 가까워 짐을 알 수 있다. 

1-1. Norm

스칼라곱 공식을 살펴보면 $A \cdot B = cos \theta \| A \| \| B \|$ 인데, $\|A\|$ 를 norm 이라고 한다.
쉽게 얘기하면 절댓값을 말하고, 어떤 값의 크기를 계산하여 비교가 가능하게끔 하는 함수로 이해하면 된다. 

1-2. L1 Norm (Manhattan Distance)

L1 Norm은 2개의 벡터를 빼고 절댓값을 취한 뒤 합한것을 말한다.
예를 들어 $ x=(1,2,3), y=(-1,2,4)\;then\;d(x,y)=|1-(-1)|+|2-2|+|3-4|=2+0+1=3$ 이다.

1-3. L2 Norm (Euclidean Distance)

L2 Norm은 2개의 벡터 각 원소를 빼고 제곱한 뒤 합치고 루트 씌운것을 말한다.
예를 들어 $x=(1,2,3), y=(-1,2,4)\;then\;d(x,y)=\sqrt{(4+0+1)} = \sqrt{5}$ 이다.

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)) #문서1과 문서2의 코사인 유사도, 0.67
print(cos_sim(doc1, doc3)) #문서1과 문서3의 코사인 유사도, 0.67
print(cos_sim(doc2, doc3)) #문서2과 문서3의 코사인 유사도, 1.00

위 코드는 코사인 유사도의 예시코드인데 요놈이 크기보다 방향으로 유사도를 따진다!

2. 유클리드 거리 (Euclidean Distance)

유클리드 거리는 문서 유사도를 구할 때 타 유사도만큼 유용한 방법은 아니다.
다차원 공간에서 2개의 점 p와 q가 각각 $p=(p_1, p_2, p_3, \cdots, p_n)$과 $q=(q_1, q_2, q_3, \cdots, q_n)$의 좌표를 가질 때 두 점 사이의 거리를 계산하는 유클리드 거리 공식은 아래와 같다.

$$\sqrt{(q_1-p_1)^2+(q_2-p_2)^2+\cdots+(q_n-p_n)^2} = \sqrt{\sum_{i=1}^{n}(q_i-p_i)^2}$$

다차원 공간이라 복잡해 보이지만, 2차원 공간이라고 한다면 단순히 피타고라스 정리라고 생각해도 무방한 것 같다.

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, doc2)) # 2.236
print(dist(doc2, docQ)) # 3.162
print(dist(doc3, docQ)) # 2.449

3주차때 공부했던 L1, L2 Norm을 포함해서 한번에 정리해보았다.

 

출처 : https://jiho-ml.com/weekly-nlp-5/

 

Week 5 - 얘랑 나랑 얼마나 비슷해?

여러분은 어떤 사람과 얼마나 비슷한지 숫자로 표현할 수 있으신가요? "친구 A보다 B가 나와 좀 더 비슷한거 같아.." 라는 어찌어찌 할 수 있을거 같은데, 아무래도 절대적인 숫자를 생각해내기는

jiho-ml.com