군집 분석이란 유사성을 기반으로 군집을 분류하고 군집에 따라 유형 별 특징을 분석하는 기법이다.
- 텍스트에 대한 군집 분석에서는 군집으로 묶여진 텍스트들끼리 최대한 유사하고 다른 군집으로 묶여진 텍스트들과는 최대한 유사하지 않도록 분류한다.
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()
4. Scikit-learn, Scipy를 이용한 계층적 군집화
- 계층적 군집화란 개별 개체들을 유사한 개체나 그룹과 통합해 군집화를 수행하는 알고리즘이다.
- 비계층적 군집화와는 달리 군집 수를 지정하지 않아도 군집화를 할 수 있는 것이 장점이다.
- 계층적 군집화는 모든 개체 간 거리나 유사도가 미리 계산되어 있어야만 하며, 계산 복잡도도 비계층적 군집화보다 크다.
Scikit-learn
- 비계층적 군집화의 일종인 agglomerativeClustering(병합 군집)을 이용하여 계층적 군집화를 실습한다.
- 병합 군집은 각 개체들을 클러스터로 간주하며, 종료 조건을 만족할 때 까지 가장 비슷한 두 클러스터들을 합치며 진행한다.
- 병합 군집의 종료 조건에는 3가지를 지정 가능하다.
- Ward
- 모든 클러스터 내의 분산을 가장 적게 증가시키는 두 클러스터를 합친다.(기본값)
- Average
- 클러스터 간 평균 거리가 가장 짧은 두 클러스터를 합친다.
- Complete
- 클러스터 간 최대 거리가 가장 짧은 두 클러스터를 합친다.
- Ward
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()
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()
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()
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()
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 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()
'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 |