https://www.youtube.com/watch?v=YJSHBQj8zbU&list=PL7ZVZgsnLwEEoHQAElEPg7l7T6nt25I3N&index=3
군집 분석(Cluster Analysis)
- 군집 분석은 데이터의 특성에 따라 유사한 것끼리 묶음
- 유사성을 기반으로 군집을 분류하고, 군집에 따라 유형별 특징을 분석하는 기법
- 텍스트에 대한 군집 분석에서는 군집으로 묶여진 텍스트들끼리는 최대한 유사하고, 다른 군집으로 묶여진 텍스트들과는 최대한 유사하지 않도록 분류
텍스트 유사도
- 텍스트 쌍에 대한 자카드 유사도와 코사인 유사도 계산
- 자카드 유사도(Jaccard Similarity): 두 텍스트 문서 사이에 공통된 용어의 수와 해당 텍스트에 존재하는 총 고유 용어 수의 비율을 사용
- 코사인 유사도(Cosine Similarity): 백터 표현 사이의 각도에 대한 코사인 값을 사용. BoW와 TF-IDF 행렬은 텍스트에 대한 백터 표현으로 활용 가능
import nltk
from nltk.metrics.distance import jaro_similarity
nltk.download('punkt')
nltk.download('wordnet')
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()
# 단어 뽑아서 lemmatize, list로
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 of value."
d3 = "Give me liberty, or give me death."
print(jaccard_similarity(d1, d2)) # 0.2222222222222222
print(jaccard_similarity(d1, d3)) # 0.0625
print(jaccard_similarity(d2, d3)) # 0.05555555555555555
# 코사인유사도의 경우 벡터로 계산하기 때문에
# tf-idf vectorizer를 사용한 뒤 코사인유사도 계산해야 함.
tiv = TfidfVectorizer()
corpus = [d1, d2, d3]
tfidf = tiv.fit_transform(corpus).todense()
print(cosine_similarity(tfidf[0], tfidf[1])) # [[0.21078354]]
print(cosine_similarity(tfidf[0], tfidf[2])) # [[0.]]
print(cosine_similarity(tfidf[1], tfidf[2])) # [[0.]]
한국어 형태소 분석기 사용 : konlpy, mecab
-> 이건 지난 영상에서 이미 설치했으니 패스. 윈도우에서 mecab은 eunjeon으로 설치하면 됩니다!
데이터 전처리
import urllib.request
raw = urllib.request.urlopen("https://raw.githubusercontent.com/e9t/nsmc/master/ratings.txt").readlines()
print(raw[:5])
raw = [x.decode() for x in raw[1:10000]]
reviews = []
for i in raw:
reviews.append(i.split("\t")[1])
print(reviews[:5])
#['어릴때보고 지금다시봐도 재밌어요ㅋㅋ', '디자인을 배우는 학생으로, 외국디자이너와 그들이 일군 전통을 통해 발
#전해가는 문화산업이 부러웠는데. 사실 우리나라에서도 그 어려운시절에 끝까지 열정을 지킨 노라노 같은 전통이있어
# 저와 같은 사람들이 꿈을 꾸고 이뤄나갈 수 있다는 것에 감사합니다.', '폴리스스토리 시리즈는 1부터 뉴까지 버릴
#께 하나도 없음.. 최고.', '와.. 연기가 진짜 개쩔구나.. 지루할거라고 생각했는데 몰입해서 봤다.. 그래 이런게 진
#짜 영화지', '안개 자욱한 밤하늘에 떠 있는 초승달 같은 영화.']
# 형태소 분석
from eunjeon import Mecab
tagger = Mecab()
reviews = [tagger.morphs(x) for x in reviews]
print(reviews[:5][0]) # ['어릴', '때', '보', '고', '지금', '다시', '봐도', '재밌', '어요', 'ㅋㅋ']
Word2Vec
from gensim.models import Word2Vec
from sklearn.manifold import TSNE
from matplotlib import font_manager as fm
from matplotlib import rc
word2vec = Word2Vec(reviews, min_count=5)
word2vec
word2vec.wv.most_similar("영화") # <gensim.models.word2vec.Word2Vec object at 0x00000266B7AF0A90>
# [('듯', 0.9414538145065308), ('작품', 0.9384720921516418), ('마음', 0.9210805892944336), ('이야기', 0.9041269421577454), ('잔잔', 0.8972564339637756), ('모습', 0.8951208591461182), ('느낌', 0.8920300006866455), ('가슴', 0.8907313346862793), ('며', 0.8872851133346558), ('따뜻', 0.8859601020812988)]
t-sne를 이용한 단어 벡터 시각화
tsne = TSNE(n_components=2) # 2차원으로 만들겠다
tsne
vocab = word2vec.wv.key_to_index
similarity = word2vec.wv[vocab]
similarity
# 보기 편하게 데이터프레임으로 변환
import pandas as pd
transform_similarity = tsne.fit_transform(similarity) # similarity를 2차원으로
df = pd.DataFrame(transform_similarity, index=vocab, columns=["x", "y"])
df[0:10]
import seaborn as sns
import matplotlib.pyplot as plt
plt.style.use("seaborn-white")
sns.lmplot("x", "y", data=df, fit_reg=False, size=8)
plt.show()
Scikit-learn, Scipy를 이용한 계층적 군집화
CodeText
- 계층적 군집화란 개별 개체들을 유사한 개체나 그룹과 통합해 군집화를 수행하는 알고리즘
- 비계층적 군집화와는 달리 군집 수를 지정하지 않아도 군집화를 할 수 있는 것이 장점
- 계층적 군집화는 모든 개체간 거리나 유사도가 미리 계산되어 있어야만 하며, 계산복잡도도 비계층적 군집화보다 큼
Scikit-learn
- 비계층적 군집화의 일종인 agglomerativeClustering(병합 군집)을 이용, 계층적 군집화 실습
- 병합 군집은 각 개체들을 클러스터로 간주, 종료 조건을 만족할 때 까지 가장 비슷한 두 클러스터들을 합치며 진행
- 병합 군집의 종료 조건에는 3가지를 지정 가능
- ward - 모든 클러스터 내의 분산을 가장 적게 증가시키는 두 클러스터를 합침(기본값)
- average - 클러스터간 평균 거리가 가장 짧은 두 클러스터를 합침
- complete - 클러스터간 최대 거리가 가장 짧은 두 클러스터를 합침
- scikit-learn 사용 예제에서는 종료 조건 간의 차이를 비교
from sklearn.cluster import AgglomerativeClustering
# ward 방법
ward = AgglomerativeClustering(n_clusters=6, linkage='ward')
predict = ward.fit_predict(df)
predict
results = df
results['predict'] = predict
results[0:10] # 어떤 클러스터에 속하는지 보여줌
sns.lmplot("x", "y", data=results, fit_reg=False, size=8, hue="predict")
plt.show()
# avg 방법
avg = AgglomerativeClustering(n_clusters=6, linkage="average")
predict = avg.fit_predict(df)
predict
results = df
results['predict'] = predict
results[0:10] # 어떤 클러스터에 속하는지 보여줌
sns.lmplot("x", "y", data=results, fit_reg=False, size=8, hue="predict")
plt.show()
# complete 방법
compl = AgglomerativeClustering(n_clusters=6, linkage="complete")
predict = compl.fit_predict(df)
predict
results = df
results['predict'] = predict
results[0:10] # 어떤 클러스터에 속하는지 보여줌
sns.lmplot("x", "y", data=results, fit_reg=False, size=8, hue="predict")
plt.show()
Scipy
- scipy를 이용한 거리 사용과 word2vec 사용을 비교
- 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_dist
- 각 단어간 유클리디안 거리를 이용한 군집 분석 및 덴드로그램 시각화
row_clusters = linkage(distmatrix, method="complete")
plt.figure(figsize=(20,10))
dendrogram(row_clusters, leaf_rotation=50, leaf_font_size=7)
plt.show()
- word2vec을 이용한 군집 분석 및 덴드로그램 시각화
mergings = linkage(df, method="complete")
plt.figure(figsize=(20,10))
dendrogram(mergings, leaf_rotation=50, leaf_font_size=7)
plt.show()
Scikit-learn을 이용한 비계층적 군집화
- 비계층적 군집화는 나눌 클러스터 개수를 지정해 각 개체가 어느 클러스터에 속하는 지를 결정
- 계층적 군집화보다 계산 복잡도가 작기 때문에 대량의 데이터에 유리하나, 클러스터 개수에 따라 군집화 성능이 크게 좌우되기 때문에 조정이 필요
- 대표적인 비계층적 군집화 알고리즘인 kmeans를 사용해 실습
- 클러스터 개수 3개
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3)
predict = kmeans.fit_predict(df)
predict
results = df
results['predict'] = predict
results[0:10]
sns.lmplot("x", "y", data = results, fit_reg = False, size = 6, hue = "predict")
plt.show()
- 클러스터 개수 6개
kmeans = KMeans(n_clusters=6)
predict = kmeans.fit_predict(df)
predict
results = df
results['predict'] = predict
results[0:10]
sns.lmplot("x", "y", data = results, fit_reg = False, size = 6, hue = "predict")
plt.show()
'Computer > ML·DL·NLP' 카테고리의 다른 글
[이수안컴퓨터연구소] 의미 연결망 분석 Semantic Network Analysis (0) | 2021.08.07 |
---|---|
[이수안컴퓨터연구소] 문서 분류 Document Classification (0) | 2021.08.07 |
[이수안컴퓨터연구소] 키워드 분석 Keyword Analysis (0) | 2021.08.04 |
[이수안컴퓨터연구소] 자연어 처리 Natural Language Processing 기초 2 한국어 NLP (Feat. Windows에서 Mecab 사용하기!) (0) | 2021.07.28 |
[이수안컴퓨터연구소] 자연어 처리 Natural Language Processing 기초 1 (영어 NLP) (0) | 2021.07.28 |
댓글