본문 바로가기
Study

[NLP] 3. Cluster Analysis

by Hwanin99 2024. 8. 19.

군집 분석이란 유사성을 기반으로 군집을 분류하고 군집에 따라 유형 별 특징을 분석하는 기법이다.

  • 텍스트에 대한 군집 분석에서는 군집으로 묶여진 텍스트들끼리 최대한 유사하고 다른 군집으로 묶여진 텍스트들과는 최대한 유사하지 않도록 분류한다.

1. 텍스트 유사도

  • 텍스트 쌍에 대한 자카드 유사도와 코사인 유사도를 계산한다.

Jaccard Similarity

  • 두 텍스트 문서 사이에 공통된 용어의 수와 해당 텍스트에 존재하는 총 고유 용어 수의 비율을 사용한다.

자카드 유사도

 

from nltk import word_tokenize
from nltk.stem import WordNetLemmatizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

def jaccard_similarity(d1,d2):
  lemmatizer = WordNetLemmatizer()
  
  words1 = [lemmatizer.lemmatize(word.lower()) for word in word_tokenize(d1)]
  words2 = [lemmatizer.lemmatize(word.lower()) for word in word_tokenize(d2)]

  inter = len(set(words1).intersection(set(words2)))
  union = len(set(words1).union(set(words2)))

  return inter/union

d1 = 'Think like a man of action and act like man of thought.'
d2 = 'Try not to become a man of success but rather try to become a man of value.'
d3 = 'Give me liberty, of give me death'

print(jaccard_similarity(d1,d2))
print(jaccard_similarity(d1,d3))
print(jaccard_similarity(d2,d3))
----------------------------------------------------------------------------------
0.2222222222222222
0.06666666666666667
0.058823529411764705

Cosine Similarity

  • 벡터 표현 사이의 각도에 대한 코사인 값을 사용한다.
    • BoW와 TF-IDF 행렬은 텍스트에 대한 벡터 표현으로 활용이 가능하다.

코사인 유사도

 

tiv = TfidfVectorizer()
corpus = [d1,d2,d3]

tfidf = tiv.fit_transform(corpus).todense()

print(cosine_similarity(tfidf[0],tfidf[1]))
print(cosine_similarity(tfidf[0],tfidf[2]))
print(cosine_similarity(tfidf[1],tfidf[2]))
-------------------------------------------
[[0.22861951]]
[[0.06083323]]
[[0.04765587]]

2. Word2Vec 생성

  • Word2Vec이란 워드 임베딩 종류 중 하나이며, 단어를 벡터로 변환하는 것이다.
    • 단어를 벡터로 변환해야 유사도 계산이 가능하기에 사용한다.

분산 표현

  • 비슷한 위치에 등장하는 단어들은 비슷한 의미를 가진다.
    • one-hot encoding → [0, 0, 1, 0, 0]
    • Word2Vec → [0.5, 0.3, 0.6, 0.2, 0.1]

Word2Vec의 원리

from gensim.models import Word2Vec
from sklearn.manifold import TSNE
from matplotlib import font_manager as fm
from matplotlib import rc
  • Word2Vec 모델을 생성한다.
  • gensim의 Word2Vec은 선언과 동시에 학습을 해 단어 벡터들을 생성한다.
word2vec = Word2Vec(reviews,min_count=5)
word2vec.most_similar('영화')
----------------------------------------
[('마음', 0.9530888795852661),
 ('작품', 0.9518659114837646),
 ('표현', 0.9510675668716431),
 ('듯', 0.9501262903213501),
 ('잔잔', 0.9475257396697998),
 ('빛', 0.9405984282493591),
 ('따뜻', 0.9391463398933411),
 ('이야기', 0.9380040168762207),
 ('행복', 0.9371881484985352),
 ('며', 0.9370923042297363)]

3. T-SNE를 이용한 단어 벡터 시각화

tsne = TSNE(n_components=2)

vocab = word2vec.wv.vocab
similarity = word2vec[vocab]

transform_similarity = tsne.fit_transform(similarity)
df = pd.DataFrame(transform_similarity,index=vocab,columns=['x','y'])
df[0:10]
---------------------------------------------------------------------
        	 x	         y
어릴	28.295990	-8.357121
  때	 51.076187	 34.401684
  보	 53.763302	 35.310375
  고	 54.834187	 34.524097
지금	53.737076	32.965286
다시	54.376877	34.094414
봐도	55.836914	32.453102
재밌	61.529640	28.628321
어요	61.958828	27.494741
ㅋㅋ	64.159485	26.294779

 

import seaborn as sns
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')

sns.lmplot('x','y',data = df,fit_reg = False,size = 6)

plt.show()

T-SNE를 이용한 시각화


4. Scikit-learn, Scipy를 이용한 계층적 군집화

  • 계층적 군집화란 개별 개체들을 유사한 개체나 그룹과 통합해 군집화를 수행하는 알고리즘이다.
    • 비계층적 군집화와는 달리 군집 수를 지정하지 않아도 군집화를 할 수 있는 것이 장점이다.
    • 계층적 군집화는 모든 개체 간 거리나 유사도가 미리 계산되어 있어야만 하며, 계산 복잡도도 비계층적 군집화보다 크다.

Scikit-learn

  • 비계층적 군집화의 일종인 agglomerativeClustering(병합 군집)을 이용하여 계층적 군집화를 실습한다.
  • 병합 군집은 각 개체들을 클러스터로 간주하며, 종료 조건을 만족할 때 까지 가장 비슷한 두 클러스터들을 합치며 진행한다.

 

  • 병합 군집의 종료 조건에는 3가지를 지정 가능하다.
    • Ward
      • 모든 클러스터 내의 분산을 가장 적게 증가시키는 두 클러스터를 합친다.(기본값)
    • Average
      • 클러스터 간 평균 거리가 가장 짧은 두 클러스터를 합친다.
    • Complete
      • 클러스터 간 최대 거리가 가장 짧은 두 클러스터를 합친다.

Ward

from sklearn.cluster import AgglomerativeClustering

ward = AgglomerativeClustering(n_clusters=6,linkage='ward')
predict = ward.fit_predict(df)

results = df
results['predict'] = predict

sns.lmplot('x','y',data = results,fit_reg = False,size = 6,hue = 'predict') #hue는 색깔구분
plt.show()

Ward

Average

avg=AgglomerativeClustering(n_clusters=6,linkage='average')
predict=avg.fit_predict(df)

results=df
results['predict']=predict

sns.lmplot('x','y',data=results,fit_reg=False,size=6,hue='predict')
plt.show()

Average

Complete

compl=AgglomerativeClustering(n_clusters=6,linkage='complete')
predict=compl.fit_predict(df)

results=df
results['predict']=predict

sns.lmplot('x','y',data=results,fit_reg=False,size=6,hue='predict')
plt.show()

Complete


Scipy

  • pdist를 이용한 각 단어 간 유클리디안 거리를 계산한다.
from scipy.spatial.distance import pdist,squareform
from scipy.cluster.hierarchy import linkage,dendrogram

distmatrix = pdist(df,metric = 'euclidean')
row_dist = pd.DataFrame(squareform(distmatrix))

 

  • 각 단어 간 유클리디안 거리를 이용한 군집 분석 및 덴드로그램 시각화
row_clusters = linkage(distmatrix,method = 'complete')

plt.figure(figsize = (20,10))
dendrogram(row_clusters,
           leaf_rotation = 50,
           leaf_font_size = 7)
plt.show()

유클리디안 거리를 이용한 군집 분석 덴드로그램

 

  • Word2Vec을 이용한 군집 분석 및 덴드로그램 시각화
mergins = linkage(df,method = 'complete')

plt.figure(figsize = (20,10))
dendrogram(mergins,
           leaf_rotation = 50,
           leaf_font_size = 7)
plt.show()

Word2Vec을 이용한 군집 분석 덴드로그램


5. Scikit-learn을 이용한 비계층적 군집화

  • 비계층적 군집화는 나눌 클러스터 개수를 지정해 각 개체가 어느 클러스터에 속하는 지를 결정한다.
    • 계층적 군집화보다 계산 복잡도가 작기 때문에 대량의 데이터에 유리하나, 클러스터 개수에 따라 군집화 성능이 크게 좌우되기 때문에 조정이 필요하다.

 

  • 대표적인 비계층적 군집화 알고리즘인 k-means를 사용해 실습한다.


Cluster 3개

from sklearn.cluster import KMeans

kmeans = KMeans(n_clusters = 3)
predict = kmeans.fit_predict(df)

results = df
results['predict'] = predict

sns.lmplot('x','y',data = results,fit_reg = False,size = 6,hue = 'predict')
plt.show()

 

Cluster 3개에 대해 k-means를 사용해 시각화


Cluster 6개

kmeans = KMeans(n_clusters = 6)
predict = kmeans.fit_predict(df)

results = df
results['predict'] = predict

sns.lmplot('x','y',data = results,fit_reg = False,size = 6,hue = 'predict')
plt.show()

Cluster 6개에 대해 k-means를 사용해 시각화

'Study' 카테고리의 다른 글

[NLP] 6. Topic Modeling  (0) 2024.08.21
[NLP] 5. Semantic Network Analysis  (0) 2024.08.20
[NLP] 4. Document Classification  (0) 2024.08.20
[NLP] 2. Keyword Analysis  (1) 2024.08.19
[NLP] 1. National Language Processing  (0) 2024.08.19