자연어 처리 - 텍스트 유사도
텍스트 유사도
코사인 유사도(Cos)
가장 많이 사용되는 기법
- 백터 내적
import numpy as np
from numpy import dot
from numpy.linalg import norm
# 코사인 세타를 구하는 함수
def cos_sim(A, B):
return dot(A, B)/(norm(A)*norm(B)) # norm(A): 벡터 A의 길이
문서 1: 나는 치킨 좋아요
문서 2: 나는 피자 좋아요
문서 3: 나는 피자 좋아요 나는 피자 좋아요
나는 치킨 피자 좋아요
문서 1: 1 1 0 1
문서 2: 1 0 1 1
문서 3: 2 0 2 2
doc1 = np.array([1,1,0,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)) # 각도, 방향이 같으므로 두 문서의 유사도는 100%이다.
0.6666666666666667
0.6666666666666667
1.0000000000000002
sklearn - cosine_similarity
from sklearn.metrics.pairwise import cosine_similarity
print(cosine_similarity([doc1], [doc2]))
print(cosine_similarity([doc1], [doc3]))
print(cosine_similarity([doc2], [doc3]))
[[0.66666667]]
[[0.66666667]]
[[1.]]
유클리드 거리
유클리디언 유사도(Euclidean Distance)
말의 어조, 억양에 대해서는 의미가 있으나 일반적으로 잘 사용하지 않는다.
- 두 점 사이의 거리 공식
def eu_dist(A, B):
return np.sqrt(np.sum((A-B)**2))
print(eu_dist(doc1, doc2))
print(eu_dist(doc1, doc3))
print(eu_dist(doc2, doc3)) # 각도가 아니라 거리이므로 강도의 차이가 있다.
1.4142135623730951
2.6457513110645907
1.7320508075688772
sklearn - euclidean_distances
from sklearn.metrics.pairwise import euclidean_distances
print(euclidean_distances([doc1], [doc2]))
print(euclidean_distances([doc1], [doc3]))
print(euclidean_distances([doc2], [doc3]))
[[1.41421356]]
[[2.64575131]]
[[1.73205081]]
맨해튼 유사도
Manhattan Similarity
정수 처리가 필요한 경우 사용한다.
from sklearn.metrics.pairwise import manhattan_distances
print(manhattan_distances([doc1], [doc2]))
print(manhattan_distances([doc1], [doc3]))
print(manhattan_distances([doc2], [doc3]))
[[2.]]
[[5.]]
[[3.]]
자카드 유사도
Jaccard Similarity
공통된 단어가 얼마나 있는지 나타낸다.
- \[J(A, B) = \frac{\vert{A∩B}\vert}{\vert{A∪B}\vert}\]
doc1 = '나는 치킨 좋아요'
doc2 = '나는 피자 좋아요'
doc3 = '나는 피자 좋아요 나는 피자 좋아요'
token_doc1 = doc1.split()
token_doc2 = doc2.split()
token_doc3 = doc3.split()
# 합집합
union = set(token_doc1).union(set(token_doc2))
# 교집합
intsec = set(token_doc1).intersection(set(token_doc2))
union, intsec
({'나는', '좋아요', '치킨', '피자'}, {'나는', '좋아요'})
len(intsec)/len(union)
0.5
print(len(set(token_doc1).intersection(set(token_doc2)))/len(set(token_doc1).union(set(token_doc2))))
print(len(set(token_doc1).intersection(set(token_doc3)))/len(set(token_doc1).union(set(token_doc3))))
print(len(set(token_doc2).intersection(set(token_doc3)))/len(set(token_doc2).union(set(token_doc3))))
0.5
0.5
1.0
댓글남기기