본문 바로가기
알고리즘

자연어처리 - cos유사도, Word2Vec, Doc2Vec

by 육빔 2024. 3. 20.
728x90
반응형

cos유사도

 

서로의 벡터를 계산하는 공식. 선대시간에 신나게 했었다.

같을수록 1에 가까우며 다르면 0에 가깝다.

 

tf, tf-idf

 

먼저 제공된 데이터로 단어장을 만든 후

각 단어의 빈도수를 체크하여 나온 값을 문장들의 벡터를 생성한다. 여기서 idf는 너무 자주나오는 단어는 변별성이 없다고 판단하여 감소키니는 차이가 있다.

코사인 유사도 공식

import numpy as np
from numpy import dot
from numpy.linalg import norm
import pandas as pd

# Cosine Simiarity
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('문서 1과 문서2의 유사도 :',cos_sim(doc1, doc2))
print('문서 1과 문서3의 유사도 :',cos_sim(doc1, doc3))
print('문서 2와 문서3의 유사도 :',cos_sim(doc2, doc3))
  • CountVectorizer:
    • 문서 집합에서 단어 토큰을 생성하고 각 단어의 수를 세어 BOW 인코딩 벡터를 만든다.
  • TfidfVectorizer:
    • CountVectorizer와 비슷하지만 TF-IDF 방식으로 단어의 가중치를 조정한 BOW 인코딩 벡터를 만든다.

 

실제 텍스트 문장 벡터로 표현하기 - 단순 TF 이용

TEXT = ['banana apple apple eggplant', 
        'orange carrot banana eggplant', 
        'apple carrot banana banana', 
        'orange banana grape'
]
# CountVectorizer 이용하기
from sklearn.feature_extraction.text import CountVectorizer # frequency based DTM
tf_vectorizer = CountVectorizer(min_df=2, max_df=0.8, ngram_range=(1,1))
tf_features = tf_vectorizer.fit_transform(TEXT)

 

  • ngram_range : (min_n, max_n) 튜플
  • n-그램 범위
  • max_df : 정수 또는 [0.0, 1.0] 사이의 실수. 디폴트 1
  • 단어장에 포함되기 위한 최대 빈도
  • min_df : 정수 또는 [0.0, 1.0] 사이의 실수. 디폴트 1
  • 단어장에 포함되기 위한 최소 빈도
# 단어들의 이름 확인하기
feature_names = tf_vectorizer.get_feature_names_out()
print(feature_names)
#['apple' 'carrot' 'eggplant' 'orange']

 

단어장에 등록 완료

 

# 벡터화 된 문서 확인
features = np.array(tf_features.todense())
features

array([[2, 0, 1, 0],
            [0, 1, 1, 1],
            [1, 1, 0, 0],
            [0, 0, 0, 1]])

이런식으로 확인이 가능하다.

 

# Cosine 유사도 계산
print('문서 0과 문서1의 유사도 :',cos_sim(features[0], features[1]))
print('문서 1과 문서2의 유사도 :',cos_sim(features[1], features[2]))
print('문서 2와 문서3의 유사도 :',cos_sim(features[2], features[3]))

 

위에서 진행한 것처럼 똑같이 계산이 가능하다.

 

 

이번엔 실제 텍스트 문장 벡터로 표현하기 - TF-idf 이용

from sklearn.feature_extraction.text import TfidfVectorizer # tf-idf based DTM
tfidf_vectorizer = TfidfVectorizer(min_df=2, max_df=0.8, ngram_range=(1,1))
tfidf_features = tfidf_vectorizer.fit_transform(TEXT)

 

진행과정은 위와 일치한다.

 

여기서 tf-idf가 뭔지 잘 모르겠으면 이 강의가 맛집이다.

https://www.youtube.com/watch?v=meEchvkdB1U

 

 

Word2Vec

 

우리는 스무고개를 할때 동물인지, 식물인지, 사물인지 먼저 판단한 다음에 세부사항으로 그와 유사한 단어를 찍어 맞춘다. [동물, 식물, 사물] 먼저 벡터를 분리한 후 그 차이를 계산하는 다차원 벡터를 생성하는 알고리즘이다. 

 

아래는 단어를 예측하는 2가지 방식이다. 

  • CBOW (Continuous Bag of Words): 주변 단어들을 사용하여 타겟 단어를 예측합니다. 이 방식은 주변 단어들의 정보를 합하여 타겟 단어의 출현 확률을 최대화하는 방향으로 학습합니다.
  • Skip-gram: 타겟 단어로부터 주변 단어들을 예측합니다. 이 방식은 타겟 단어를 기반으로 주변 단어들의 출현 확률을 최대화하는 방향으로 학습합니다.
from gensim.models import Word2Vec
model_sg_n10 = Word2Vec(reviews, window=3, min_count=3, vector_size=100, sg=1, negative=10)

 

위는 Word2Vec을 학습시키는 코드로 설명을 하자면


제공된 reviews 데이터로 학습을 시키고,

앞과 뒤에서 각각 3개의 단어를 문맥으로 고려,

적어도 3번은 나와야되고,

100차원 벡터로 표현할거고,

Skip-gram 알고리즘을 사용할거고(문맥 단어 예측),

네거티브 샘플링을 사용할 것(쓰는 이유: 부정적 단어를 업데이트하여 큰 데이터셋에서 자주 사용)

으로 설명할 수 있을 것 같다.

 

model_sg_n10.wv.similarity('이정재', '이범수')

 

유사도를 측정해주는 메서드

 

model_sg_n10.wv.most_similar('이정재',topn=10)

 

비슷한 단어 10개 추출해주는 메서드

 

만약 시각화로 관련된 것을 보고 싶으면 차원 축소를 사용해서 봐야된다. 뭐 당연한 말이지만 사람은 3차원까지 밖에 못보니까.. 갑자기 여러차원을 볼 수 있으면 시간차원도.. 상대성이론.. 주저리주저리..

# t-SNE를 사용하여 2차원으로 축소
tsne = TSNE(n_components=2, random_state=0)
word_vectors_2d = tsne.fit_transform(word_vectors_np)

 

이럴땐 t-SNE (manifold기법)을 사용하여 축소 후 시각화를 시키면 된다.

 

 

Doc2Vec

 

Word2Vec과 비슷하나 단어뿐만 아니라 문서의 문맥도 함께 고려하여 벡터를 학습한다. 문서 ID를 사용하여 Vector값을 이동시킨다.

사용법은 똑같다.

# doc2vec 학습이 가능한 형태로 변형
from gensim.models.doc2vec import TaggedDocument
tagged_docs = [TaggedDocument(doc, tags=[i]) for i, doc in enumerate(preprocessed_reviews) if doc != None]

 

728x90
반응형