9 분 소요

03 한국어 자연어 처리 및 문장 유사도

1. 한국어 자연어 처리

  • 한국어에서 단어의 기준은 명확하지 않다.
  • 단어는 의미적 기능을 하는 부분과 문법적인 기능을 하는 부분의 조합으로 구성되었다.

    image

  • 의미적: 엘리스, 먹 ⇒ 중요한 정보이다.
  • 문법적: 는, 가, 에게, 다, 었다, 는다 ⇒ 중요한 정보가 아니다.

    ⇒ 한국어 자연어 처리에서는 단어의 의미적 기능과 문법적인 기능을 구분하는 것이 중요하다.

2. KoNLPy

형태소 분석이란 주어진 텍스트를 단어의 원형 형태로 분리해주는 작업이다.

image

KoNLPy는 여러 한국어 형태소 사전을 기반으로 한국어 단어를 추출해주는 파이썬 라이브러리이다.

형태소 사전 패키지

KoNLPy에서 아래의 한국어 형태소 사전 패키지들을 사용할 수 있다.

  • Mecab
  • 한나눔
  • 꼬꼬마
  • Komoran
  • Open Korean Text

각 형태소 사전별 형태소 표기 방법과 기준의 차이가 존재한다.

각 형태소 분석기 호출 방식

image

  • Hannanum()
  • Kkma()
  • Komoran(userdict=경로)
  • Mecab()
  • Okt()

꼬꼬마를 통해서 전처리해보기

image

  • sent: 두 개의 문장으로 구성된 텍스트가 주어졌다.
  • kkma.nouns(sent): sent 안의 명사들을 추출해준다.
  • kkma.pos(sent): 원형을 분리해주고 각각의 형태소 정보를 제공해준다.
    • NNG: 명사
  • kkma.sentences(sent): 문장을 구분해서 리스트로 반환해준다.

Okt를 통해서 전처리해보기

image

  • okt.pos(sent, stem=True): True이면 stemming을 해주고 원형 형태로 반환한다.

코드 실습

# 경고문을 무시합니다.
import warnings
warnings.filterwarnings(action='ignore')

import pandas as pd
from konlpy.tag import Kkma, Okt

# sts-train.tsv 파일에 저장되어 있는 KorSTS 데이터셋을 불러옵니다.
sent = pd.read_table("sts-train.tsv", delimiter='\t', header=0)['sentence1']

# sent 변수에 저장된 첫 5개 문장을 확인해봅니다.
print("sent[:5]", sent[:5])

# 꼬꼬마 형태소 사전을 이용해서 sent 내 문장의 명사를 nouns 리스트에 저장하세요.
nouns = []
kkma = Kkma()

for s in sent:
    nouns += kkma.nouns(s)
# 명사의 종류를 확인해봅니다.
print("set(nouns)", set(nouns))

# Open Korean Text 형태소 사전을 이용해서 sent 내 형태소 분석 결과를 pos_results 리스트에 저장하세요.
pos_results = []
okt = Okt()

for s in sent:
    pos_results.append(okt.pos(s))
# 분석 결과를 확인해봅니다.
print("pos_results", pos_results)

# stemming 기반 형태소 분석이 적용된 sent의 두 번째 문장을 stem_pos_results 리스트에 저장하세요.
stem_pos_results = []
stem_pos_results = okt.pos(sent[1], stem=True)
print("stem_pos_results", stem_pos_results)

>> 실습 결과
sent[:5] 0             비행기가 이륙하고 있다.
1      남자가  플루트를 연주하고 있다.
2     남자가 피자에 치즈를 뿌려놓고 있다.
3           남자가 체스를 하고 있다.
4         남자가 첼로를 연주하고 있다.
Name: sentence1, dtype: object
set(nouns) {'드럼', '자전거', '여자', '위', '등에', '보드', '판다', '사자', '체스', '얼굴', '독수리', '누군가', '소년', '공', '캥거루', '껍질', '양파', '튀김', '남', '아기', '막대기', '자가', '추', '생선', '여성', '연주', '감자', '사람', '기타', '동상', '새끼', '기계식', '빵', '기름', '플루트', '스케이트', '냄비', '아이', '노래', '장', '토마토', '새우', '호랑이', '소녀', '조각', '눈', '이드', '토끼', '팬', '후추', '담배', '피자', '천장', '북극곰', '아래', '돼지고기', '연', '스케이트보드', '피아노', '종이', '후', '말', '글', '고양이', '키보드', '황소', '일렉트릭', '비행기', '치즈', '개가', '첼로', '베이컨', '도로', '남자', '이륙', '남자가'}
pos_results [[('비행기', 'Noun'), ('가', 'Josa'), ('이륙', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('남자', 'Noun'), ('가', 'Josa'), ('큰', 'Verb'), ('플루트', 'Noun'), ('를', 'Josa'), ('연주', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('남자', 'Noun'), ('가', 'Josa'), ('피자', 'Noun'), ('에', 'Josa'), ('치즈', 'Noun'), ('를', 'Josa'), ('뿌려놓고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('세', 'Noun'), ('남자', 'Noun'), ('가', 'Josa'), ('체스', 'Noun'), ('를', 'Josa'), ('하고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('남자', 'Noun'), ('가', 'Josa'), ('첼로', 'Noun'), ('를', 'Josa'), ('연주', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('몇몇', 'Noun'), ('남자', 'Noun'), ('들', 'Suffix'), ('이', 'Josa'), ('싸우고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('담배', 'Noun'), ('를', 'Josa'), ('피우고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('피아노', 'Noun'), ('를', 'Josa'), ('치고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('남자', 'Noun'), ('가', 'Josa'), ('기타', 'Noun'), ('를', 'Josa'), ('치고', 'Josa'), ('노래', 'Noun'), ('를', 'Josa'), ('부르고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('사람', 'Noun'), ('이', 'Josa'), ('고양이', 'Noun'), ('를', 'Josa'), ('천장', 'Noun'), ('에', 'Josa'), ('던지고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('그', 'Noun'), ('남자', 'Noun'), ('는', 'Josa'), ('다른', 'Noun'), ('남자', 'Noun'), ('를', 'Josa'), ('막대기', 'Noun'), ('로', 'Josa'), ('때렸다', 'Verb'), ('.', 'Punctuation')], [('한', 'Verb'), ('여성', 'Noun'), ('이', 'Josa'), ('아기', 'Noun'), ('를', 'Josa'), ('안아서', 'Verb'), ('캥거루', 'Noun'), ('를', 'Josa'), ('안는다', 'Verb'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('플루트', 'Noun'), ('를', 'Josa'), ('연주', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('사람', 'Noun'), ('이', 'Josa'), ('종이', 'Noun'), ('한', 'Verb'), ('장', 'Noun'), ('을', 'Josa'), ('접고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('남자', 'Noun'), ('가', 'Josa'), ('도로', 'Noun'), ('를', 'Josa'), ('달리', 'Noun'), ('고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('개', 'Noun'), ('가', 'Josa'), ('베이컨', 'Noun'), ('을', 'Josa'), ('등', 'Noun'), ('에서', 'Josa'), ('떼려고', 'Verb'), ('하고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('북극곰', 'Noun'), ('이', 'Josa'), ('눈', 'Noun'), ('위', 'Noun'), ('에서', 'Josa'), ('미끄러지고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('여자', 'Noun'), ('가', 'Josa'), ('글', 'Noun'), ('을', 'Josa'), ('쓰고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('고양이', 'Noun'), ('가', 'Josa'), ('아기', 'Noun'), ('의', 'Josa'), ('얼굴', 'Noun'), ('을', 'Josa'), ('문지르고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('말', 'Noun'), ('을', 'Josa'), ('타고', 'Noun'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('남자', 'Noun'), ('가', 'Josa'), ('냄비', 'Noun'), ('에', 'Josa'), ('기름', 'Noun'), ('을', 'Josa'), ('부어', 'Noun'), ('넣는다', 'Verb'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('기타', 'Noun'), ('를', 'Josa'), ('치고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('판다', 'Noun'), ('가', 'Josa'), ('슬라이드', 'Noun'), ('아래', 'Noun'), ('로', 'Josa'), ('미끄러져', 'Verb'), ('내려간다', 'Verb'), ('.', 'Punctuation')], [('여자', 'Noun'), ('가', 'Josa'), ('뭔가', 'Noun'), ('를', 'Josa'), ('먹고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('여자', 'Noun'), ('가', 'Josa'), ('감자', 'Noun'), ('껍질', 'Noun'), ('을', 'Josa'), ('벗긴다', 'Verb'), ('.', 'Punctuation')], [('그', 'Noun'), ('소년', 'Noun'), ('은', 'Josa'), ('자전거', 'Noun'), ('에서', 'Josa'), ('떨어졌다', 'Verb'), ('.', 'Punctuation')], [('여자', 'Noun'), ('가', 'Josa'), ('플루트', 'Noun'), ('를', 'Josa'), ('연주', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('토끼', 'Noun'), ('가', 'Josa'), ('독수리', 'Noun'), ('에게서', 'Josa'), ('뛰고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('여자', 'Noun'), ('가', 'Josa'), ('빵', 'Noun'), ('을', 'Josa'), ('곁들인', 'Verb'), ('돼지고기', 'Noun'), ('를', 'Josa'), ('튀기고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('소녀', 'Noun'), ('가', 'Josa'), ('연', 'Noun'), ('을', 'Josa'), ('날리고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('남자', 'Noun'), ('가', 'Josa'), ('기계', 'Noun'), ('식', 'Suffix'), ('황소', 'Noun'), ('를', 'Josa'), ('타고', 'Noun'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('기타', 'Noun'), ('를', 'Josa'), ('연주', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('여성', 'Noun'), ('이', 'Josa'), ('다른', 'Noun'), ('여성', 'Noun'), ('들', 'Suffix'), ('과', 'Josa'), ('춤추고', 'Verb'), ('노래', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('빵', 'Noun'), ('을', 'Josa'), ('자르고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('팬', 'Noun'), ('에', 'Josa'), ('기름', 'Noun'), ('을', 'Josa'), ('부어', 'Noun'), ('넣고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('사자', 'Noun'), ('가', 'Josa'), ('사람', 'Noun'), ('들', 'Suffix'), ('과', 'Josa'), ('놀고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('개', 'Noun'), ('가', 'Josa'), ('스케이트보드', 'Noun'), ('를', 'Josa'), ('탄다', 'Verb'), ('.', 'Punctuation')], [('누군가', 'Noun'), ('가', 'Josa'), ('동상', 'Noun'), ('을', 'Josa'), ('조각', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('여성', 'Noun'), ('이', 'Josa'), ('양파', 'Noun'), ('를', 'Josa'), ('자르고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('여자', 'Noun'), ('는', 'Josa'), ('새우', 'Noun'), ('껍질', 'Noun'), ('을', 'Josa'), ('벗긴다', 'Verb'), ('.', 'Punctuation')], [('한', 'Verb'), ('여성', 'Noun'), ('이', 'Josa'), ('생선', 'Noun'), ('튀김', 'Noun'), ('을', 'Josa'), ('하고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('여성', 'Noun'), ('이', 'Josa'), ('일', 'Modifier'), ('렉', 'Noun'), ('트릭', 'Noun'), ('기타', 'Noun'), ('를', 'Josa'), ('연주', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('새끼', 'Noun'), ('호랑이', 'Noun'), ('가', 'Josa'), ('공', 'Noun'), ('을', 'Josa'), ('가지', 'Noun'), ('고', 'Josa'), ('놀고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('사람', 'Noun'), ('이', 'Josa'), ('토마토', 'Noun'), ('를', 'Josa'), ('자르고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('사람', 'Noun'), ('이', 'Josa'), ('양파', 'Noun'), ('를', 'Josa'), ('잘랐다', 'Verb'), ('.', 'Punctuation')], [('한', 'Verb'), ('남자', 'Noun'), ('가', 'Josa'), ('피아노', 'Noun'), ('를', 'Josa'), ('치고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('여성', 'Noun'), ('이', 'Josa'), ('플루트', 'Noun'), ('를', 'Josa'), ('연주', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('감자', 'Noun'), ('를', 'Josa'), ('자르고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('아이', 'Noun'), ('가', 'Josa'), ('기타', 'Noun'), ('를', 'Josa'), ('치고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('한', 'Verb'), ('소년', 'Noun'), ('이', 'Josa'), ('기타', 'Noun'), ('를', 'Josa'), ('치고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('기타', 'Noun'), ('를', 'Josa'), ('치고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('어린', 'Verb'), ('소년', 'Noun'), ('이', 'Josa'), ('키', 'Noun'), ('보드', 'Noun'), ('를', 'Josa'), ('연주', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('기타', 'Noun'), ('를', 'Josa'), ('치고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('개', 'Noun'), ('가', 'Josa'), ('아기', 'Noun'), ('를', 'Josa'), ('핥는다', 'Verb'), ('.', 'Punctuation')], [('한', 'Verb'), ('여성', 'Noun'), ('이', 'Josa'), ('양파', 'Noun'), ('를', 'Josa'), ('자르고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('기타', 'Noun'), ('를', 'Josa'), ('치고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('여자', 'Noun'), ('가', 'Josa'), ('후추', 'Noun'), ('를', 'Josa'), ('썰고', 'Verb'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('남자', 'Noun'), ('가', 'Josa'), ('드럼', 'Noun'), ('을', 'Josa'), ('치고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')], [('여자', 'Noun'), ('가', 'Josa'), ('말', 'Noun'), ('을', 'Josa'), ('탄다', 'Verb'), ('.', 'Punctuation')]]
stem_pos_results [('하다', 'Verb'), ('남자', 'Noun'), ('가', 'Josa'), ('크다', 'Verb'), ('플루트', 'Noun'), ('를', 'Josa'), ('연주', 'Noun'), ('하고', 'Josa'), ('있다', 'Adjective'), ('.', 'Punctuation')]

3. soynlp

  • 사전 기반의 단어 처리의 경우(KoNLPy), 미등록 단어 문제가 발생할 수 있음
  • soynlp는 학습 데이터 내 자주 발생하는 패턴을 기반으로 단어의 경계선을 구분해준다.

    image

가정

  1. 단어는 연속으로 등장하는 글자의 조합이며 글자 간 연관성이 높다.
  2. 한국어의 어절은 좌-우(의미적 기능-문법적 기능) 구조로 2등분 할 수 있다.

soynlp를 통해서 한국어 전처리해보기

image

  • DoublespaceLineCorpus(학습데이터의 경로): 저장되어있는 대량의 학습데이터 지정하여 학습할 수 있는 데이터로 변환해준다.
  • LRNounExtractor_v2() noun.extractor.train_extract(train_data) : 학습데이터에서 명사로 추정되는 단어를 반환한다.
  • WordExtractor() word_extractor.train_extract(train_data) : 모든 단어를 토큰화하여 리스트로 반환한다.

코드 실습

# 신문 기사를 학습 데이터로 사용하여 명사 목록을 학습한 뒤, 주어진 문장에서 명사를 추출

from soynlp.utils import DoublespaceLineCorpus
from soynlp.noun import LRNounExtractor_v2

sent = '트와이스 아이오아이 좋아여 tt가 저번에 1위 했었죠?'

# 학습에 사용할 데이터가 train_data에 저장되어 있습니다.
corpus_path = 'articles.txt'
train_data = DoublespaceLineCorpus(corpus_path)
print("학습 문서의 개수: %d" %(len(train_data)))

# LRNounExtractor_v2 객체를 이용해 train_data에서 명사로 추정되는 단어를 nouns 변수에 저장하세요.
noun_extr = LRNounExtractor_v2()
nouns = noun_extr.train_extract(train_data)

# 생성된 명사의 개수를 확인해봅니다.
print("len(nouns)", len(nouns))

# 생성된 명사 목록을 사용해서 sent에 주어진 문장에서 명사를 sent_nouns 리스트에 저장하세요.
sent_nouns = []
for word in sent.split():
    if word in nouns:
        sent_nouns.append(word)

print("sent_nouns", sent_nouns)

>> 실행 결과
학습 문서의 개수: 30091
len(nouns) 90643
sent_nouns ['트와이스', '아이오아이', '1위']

4. 문장 유사도

문장 간 유사도는 공통된 단어 혹은 의미를 기반으로 계산한다.

자카드 지수

자카드 지수는 문장 간 공통된 단어의 비율로 문장 간 유사도를 정의한다.

image

image

자카드 지수는 문장 간 유사도를 0 ~ 1 사이로 정의한다.

장점: 쉽고 간편하다.

단점: 단어를 기준으로 문장 유사도를 비교했기 때문에 의미적인 내용을 잘 부여할 수 없어 유사도의 의미가 정확하게 나오질 않을 수 있다.

코사인 유사도

코사인 유사도는 문장 벡터 간의 각도를 기반으로 계산한다.

image

image

벡터 간의 각도는 벡터 간 내적을 사용해서 계산한다.

장점: 코사인 유사도는 고차원의 공간에서 벡터 간의 유사성을 잘 보존하는 장점이 있다.

코드 실습 - 자카드 지수

import nltk

sent_1 = "오늘 중부지방을 중심으로 소나기가 예상됩니다"
sent_2 = "오늘 전국이 맑은 날씨가 예상됩니다"

def cal_jaccard_sim(sent1, sent2):
    # 각 문장을 토큰화 후 set 타입으로 변환하세요.
    words_sent1 = set(sent1.split())
    words_sent2 = set(sent2.split())

    # 공통된 단어의 개수를 intersection 변수에 저장하세요.
    intersection = words_sent1.intersection(words_sent2)
    
    # 두 문장 내 발생하는 모든 단어의 개수를 union 변수에 저장하세요.
    union = words_sent1.union(words_sent2)

    # intersection과 union을 사용하여 자카드 지수를 계산하고 float 타입으로 반환하세요.
    return float(len(intersection) / len(union))

# cal_jaccard_sim() 함수 실행 결과를 확인합니다.
print("cal_jaccard_sim(sent_1, sent_2)", cal_jaccard_sim(sent_1, sent_2))

# nltk의 jaccard_distance() 함수를 이용해 자카드 유사도를 계산하세요.
nltk_jaccard_sim = 1 - nltk.jaccard_distance(set(sent_1.split()), set(sent_2.split()))

# 직접 정의한 함수와 결과가 같은지 비교합니다.
print("nltk_jaccard_sim", nltk_jaccard_sim)

>> 실행 결과
cal_jaccard_sim(sent_1, sent_2) 0.25
nltk_jaccard_sim 0.25

코드 실습 - 코사인 유사도

from numpy import sqrt, dot
from scipy.spatial import distance
from sklearn.metrics import pairwise

sent_1 = [0.3, 0.2, 0.2133, 0.3891, 0.8852, 0.586, 1.244, 0.777, 0.882]
sent_2 = [0.03, 0.223, 0.1, 0.4, 2.931, 0.122, 0.5934, 0.8472, 0.54]
sent_3 = [0.13, 0.83, 0.827, 0.92, 0.1, 0.32, 0.28, 0.34, 0]

def cal_cosine_sim(v1, v2):
    # 벡터 v1, v2 간 코사인 유사도를 계산 후 반환하세요.
    top = dot(v1, v2)
    size1 = sqrt(dot(v1, v1))
    size2 = sqrt(dot(v2, v2))
    return top / (size1 * size2)

# 정의한 코사인 유도 계산 함수를 확인합니다.
print("cal_cosine_sim(sent_1, sent_2)", cal_cosine_sim(sent_1, sent_2))

# scipy의 distance.cosine() 함수를 이용한 코사인 유사도를 계산하세요.
scipy_cosine_sim = 1 - distance.cosine(sent_1, sent_2)

# scipy를 이용해 계산한 코사인 유사도를 확인합니다.
print("scipy_cosine_sim", scipy_cosine_sim)

# scikit-learn의 pairwise.cosine_similarity() 함수를 이용한 코사인 유사도를 계산하세요.
all_sent = [sent_1] + [sent_2] + [sent_3]
scikit_learn_cosine_sim  = pairwise.cosine_similarity(all_sent) # 조합 가능한 모든 벡터들의 쌍을 계산

# scikit-learn을 이용해 계산한 코사인 유사도를 확인합니다.
print("scikit_learn_cosine_sim", scikit_learn_cosine_sim)

>> 실행 결과
cal_cosine_sim(sent_1, sent_2) 0.713722489605211
scipy_cosine_sim 0.7137224896052109
scikit_learn_cosine_sim [[1.         0.71372249 0.4876509 ]
 [0.71372249 1.         0.2801926 ]
 [0.4876509  0.2801926  1.        ]]

댓글남기기