코사인 유사도를 구하는 식은 다음과 같다.
먼저 단순한 문장부터 해 보자.
import numpy as np
# 형태소 종류 5개 중 각각의 문장이 가진 형태소 종류 카운트
def v(V, D):
for value in ['파란','하얀','하늘','구름','파도']:
if value in D:
V.append(D[value])
else:
V.append(0)
return V
# 코사인 유사도 구하기
def sim(a,b):
return a@b/(np.linalg.norm(a) * np.linalg.norm(b))
# 문장에서 형태소를 분리한다
A = '파란 하늘 파란 파도'
B = '파란 하늘 하얀 파도'
C = '하얀 구름 파란 하늘'
LA = A.split()
LB = B.split()
LC = C.split()
DA = {word:LA.count(word) for word in LA}
DB = {word:LB.count(word) for word in LB}
DC = {word:LC.count(word) for word in LC}
VA=[]
VB=[]
VC=[]
va=np.array(v(VA,DA))
vb=np.array(v(VB,DB))
vc=np.array(v(VC,DC))
print(sim(va,vb)) # 0.8164965809277261
print(sim(va,vc)) # 0.6123724356957946
print(sim(vb,vc)) # 0.75
결과를 확인해보면 문장 A와 문장 B가 유사하다는걸 알 수 있다.
이번엔 실제 문장에서 형태소를 분리한 뒤 유사도를 구해보자.
from konlpy.tag import *
import numpy as np
# 형태소 종류 중 각각의 문장이 가진 형태소 종류 카운트
def make_vec(feature,data):
v = []
for f in feature:
cnt =0
for word in data:
if word == f:
cnt += 1
v.append(cnt)
return np.array(v)
# 코사인 유사도 구하기
def sim(a,b):
return a@b/(np.linalg.norm(a) * np.linalg.norm(b))
okt = Okt()
# input에서 형태소 분리
A = okt.nouns(input()) # 내 이름은 코난, 탐정이죠
B = okt.nouns(input()) # 내 이름은 유난, 떨고있죠
C = okt.nouns(input()) # 으하하하
print(A) # ['내', '이름', '코난', '탐정']
print(B) # ['내', '이름', '유난']
print(C) # ['하하']
feature = set(A+B+C)
va = make_vec(feature,A)
vb = make_vec(feature,B)
vc = make_vec(feature,C)
print('va & vb', sim(va,vb)) # va & vb 0.5773502691896258
print('vb & vc', sim(vb,vc)) # vb & vc 0.0
print('va & vc', sim(va,vc)) # va & vc 0.0
문장 A와 B는 유사하지만, B와 C, C와 A는 유사하지 않음을 결과로 알 수 있다.