엔트로피 Entropy 기반 군집 평가
군집결과의 엔트로피를 측정하여 군집평가에 사용
엔트로피 값이 낮을수록 안정적이고 변화가 적어 좋은 군집으로 평가한다
군집평가 실습
1. 필요한 패키지, 라이브러리, 데이터 불러오기
from __future__ import print_function
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
from pandas import DataFrame
from scipy.stats import entropy
from math import log, e
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
import pandas as pd
import math
import timeit
X = np.array([[2, 0], [3, 0], [4, 0], [10, 0], [11, 0], [12, 0],[20, 0], [25, 0], [30, 0]])
plt.scatter(X[:, 0], X[:, 1], s=100)
plt.show()
2. 군집 모델 생성하기
model1 = KMeans(n_clusters = 2, init = np.array([[3,0], [4,0]]), n_init = 1, max_iter =1, random_state = 1 ).fit(X)
c0, c1 = model1.cluster_centers_
print(model1.labels_)
print(c0, c1)
print(abs(model1.score(X)))
model2 = KMeans(n_clusters = 2, init = np.array([[2.5,0], [16,0]]), n_init = 1, max_iter =1, random_state = 1 ).fit(X)
c0, c1 = model2.cluster_centers_
print(model2.labels_)
print(c0, c1)
print(abs(model2.score(X)))
3. 분리도 구하기
def separation(model):
total_mean = np.mean(X[:,0])
mean1 = np.mean(X[model.labels_==0,0])
mean2 = np.mean(X[model.labels_==1,0])
count1 = np.count_nonzero(X[model.labels_==0,0])
count2 = np.count_nonzero(X[model.labels_==1,0])
separation_value = count1*(total_mean - mean1)**2 + count2*(total_mean - mean2)**2
print(separation_value)
separation(model1)
separation(model2)
4. 유사도 매트릭스 구하기
list=[]
def s_matrix(model):
for i in range(0,np.count_nonzero(X)):
list.append([])
for j in range(0, np.count_nonzero(X)):
if model.labels_[i]==model.labels_[j]:
list[i].append(1)
else:
list[i].append(0)
s_matrix(model1)
list
s_matrix(model2)
list
5. 엔트로피 구하기
def entropy(labels):
n_labels = len(labels)
counts = np.bincount(labels)
probs = counts[np.nonzero(counts)] / n_labels
n_classes = len(probs)
return - np.sum(probs*np.log(probs)) / np.log(n_classes)
entropy(model1.labels_)
entropy(model2.labels_)
군집 비교
- Cohesion(SSE) / Separation: 값이 작을수록 군집의 비율이 잘 분리됨
- 유사도 매트릭스: 1 상자의 영역이 작을수록 군집의 비율이 잘 분리됨
- Entropy: 값이 작을수록 군집의 비율이 잘 분리됨
군집비교 실습
1. 다양한 모델 생성
# 1회차
model1 = KMeans(n_clusters = 2, init = np.array([[3,0], [4,0]]), n_init = 1, max_iter =1, random_state = 1 ).fit(X)
c1, c1 = model1.cluster_centers_
print(model1.labels_)
print(c0, c1)
# 2회차
model2 = KMeans(n_clusters=2, init=np.array([[3,0],[4,0]]), n_init=1, max_iter=2).fit(X)
c0, c1 = model2.cluster_centers_
print(model2.labels_)
print(c0, c1)
# 10회차
model10 = KMeans(n_clusters = 2, init = np.array([[3,0], [4,0]]), n_init = 1, max_iter =10, random_state = 1 ).fit(X)
c0, c1 = model10.cluster_centers_
print(model10.labels_)
print(c0, c1)
# 군집이 3개인 경우
model3 = KMeans(n_clusters=3, init='random', n_init=10, max_iter=100).fit(X)
c0, c1 = model3.cluster_centers_
print(model3.labels_)
print(c0, c1)
2. 모델 비교
# SSE 비교
model1.inertia_, model2.inertia_, model10.inertia_, model3.inertia_
# Separation 비교
separation(model1), separation(model2), separation(model10), separation(model3)
# Matrix 비교
list = []
s_matrix(model1)
list
list = []
s_matrix(mode2)
list
list = []
s_matrix(model10)
list
list = []
s_matrix(model3)
list
# Entropy 비교
entropy(model1.labels_), entropy(model2.labels_),entropy(model10.labels_), entropy(model3.labels_)
Internal Measures: SSE
클러스터링 방법이나 외부조건과 관계없이 분석 결과 자체 정보만으로 클러스터의 우수성을 평가할 수 있다. 두 개 이상의 클러스터링 분석 결과를 비교하거나 다른 클러스터링 방법의 결과를 서로 비교하는데 좋은 기준이 된다.
SSE의 감소가 클 때의 k를 구하면 좋은 군집의 수 k를 찾을 수 있다. 즉, SSE의 감소폭이 줄어들기 직전의 k를 가장 좋은 k로 본다. 수학적으로 정확한 k값을 구할 수는 없다.
SSE로 k 찾기 실습
ks = range(1, 10)
SSE = []
for k in ks:
model = KMeans(n_clusters=k) #init을 지정하지 않으면 클러스터의 중심
model.fit(X)
SSE.append(model.inertia_) #inertia_: 클러스터별 SSE 저장
plt.plot(ks, SSE, '-o')
plt.xlabel('number of clusters, k')
plt.ylabel('SSE')
plt.xticks(ks)
2차원 데이터
초기 중심값 갱신 n_init과 최대 반복 횟수 max_iter가 늘어나면 더 좋은 군집을 찾을 가능성이 높다(SSE 값의 개선)
군집을 여러 개로 나누는 경우 더 좋은 군집을 찾을 가능성이 높다
3차원 이상의 데이터는 시각화가 어려우므로 특정 축을 기준으로 시각화하기 등의 방법을 이용한다
1. 2차원 데이터 X 만들고 살펴보기
X = np.array([[7,5], [5,7], [7,7], [4,4], [4,6], [1,4],
[0,0], [2,2], [8,7], [6,8], [5,5], [3,7]])
plt.scatter(X[:,0], X[:,1], s=100)
plt.show()
2. 군집을 2개로 나누는 경우
model2 = KMeans(n_clusters=2, init='random', n_init=100, max_iter=10000, random_state=1).fit(X)
c0, c1 =model2.cluster_centers_
c0, c1
def plot_cluster2(model, c0, c1):
plt.scatter(X[model.labels_==0,0],
X[model.labels_==0,1], s=100, marker='v', c='r')
plt.scatter(X[model.labels_==1,0],
X[model.labels_==1,1], s=100, marker='^', c='b')
plt.scatter(c0[0], c0[1], s=200, c='r')
plt.scatter(c1[0], c1[1], s=200, c='b')
plt.show()
plot_cluster2(model2, c0, c1)
3. 군집을 3개로 나누는 경우
model3 = KMeans(n_clusters=3, init='random', n_init=100, max_iter=10000, random_state=1).fit(X)
c0, c1, c2 =model3.cluster_centers_
c0, c1, c2
def plot_cluster3(model, c0, c1, c2):
plt.scatter(X[model.labels_==0,0],
X[model.labels_==0,1], s=100, marker='v', c='r')
plt.scatter(X[model.labels_==1,0],
X[model.labels_==1,1], s=100, marker='^', c='b')
plt.scatter(X[model.labels_==2,0],
X[model.labels_==2,1], s=100, marker='^', c='g')
plt.scatter(c0[0], c0[1], s=200, c='r')
plt.scatter(c1[0], c1[1], s=200, c='b')
plt.scatter(c2[0], c2[1], s=200, c='g')
plt.show()
plot_cluster3(model3, c0, c1, c2)
4. 군집을 4개로 나누는 경우
model4 = KMeans(n_clusters=4, init='random', n_init=100, max_iter=10000, random_state=1).fit(X)
c0, c1, c2, c3 =model4.cluster_centers_
c0, c1, c2, c3
def plot_cluster4(model, c0, c1, c2, c3):
plt.scatter(X[model.labels_==0,0],
X[model.labels_==0,1], s=100, marker='v', c='r')
plt.scatter(X[model.labels_==1,0],
X[model.labels_==1,1], s=100, marker='^', c='b')
plt.scatter(X[model.labels_==2,0],
X[model.labels_==2,1], s=100, marker='^', c='g')
plt.scatter(X[model.labels_==3,0],
X[model.labels_==3,1], s=100, marker='v', c='y')
plt.scatter(c0[0], c0[1], s=200, c='r')
plt.scatter(c1[0], c1[1], s=200, c='b')
plt.scatter(c2[0], c2[1], s=200, c='g')
plt.scatter(c3[0], c3[1], s=200, c='y')
plt.show()
plot_cluster4(model4, c0, c1, c2, c3)
5. 최적 k 찾기: k=4 선택
ks = range(1,10)
SSE = []
for k in ks:
model = KMeans(n_clusters=k)
model.fit(X)
SSE.append(model.inertia_)
print(SSE)
plt.plot(ks, SSE, '-o')
plt.xlabel('number of clusters, k')
plt.ylabel('SSE')
plt.xticks(ks)
6. Separation 비교하기: 군집3이 더 적절한 모델
# 군집2
def separation2(model):
total_mean = np.mean(X[:,0])
mean1 = np.mean(X[model.labels_==0,0])
mean2 = np.mean(X[model.labels_==1,0])
count1 = np.count_nonzero(model.labels_==0)
count2 = np.count_nonzero(model.labels_==1)
separation_value = count1*(total_mean - mean1)**2 + count2*(total_mean - mean2)**2
print(separation_value)
# 군집3
def separation3(model):
total_mean = np.mean(X[:,0])
mean1 = np.mean(X[model.labels_==0,0])
mean2 = np.mean(X[model.labels_==1,0])
mean3 = np.mean(X[model.labels_==2,0])
count1 = np.count_nonzero(model.labels_==0)
count2 = np.count_nonzero(model.labels_==1)
count3 = np.count_nonzero(model.labels_==2)
separation_value = count1*(total_mean - mean1)**2 + count2*(total_mean - mean2)**2 + count3*(total_mean - mean3)**2
print(separation_value)
# 군집4
def separation4(model):
total_mean = np.mean(X[:,0])
mean1 = np.mean(X[model.labels_==0,0])
mean2 = np.mean(X[model.labels_==1,0])
mean3 = np.mean(X[model.labels_==2,0])
mean4 = np.mean(X[model.labels_==3,0])
count1 = np.count_nonzero(model.labels_==0)
count2 = np.count_nonzero(model.labels_==1)
count3 = np.count_nonzero(model.labels_==2)
count4 = np.count_nonzero(model.labels_==3)
separation_value = count1*(total_mean - mean1)**2 + count2*(total_mean - mean2)**2 + count3*(total_mean - mean3)**2 + count4*(total_mean - mean4)**2
print(separation_value)
separation2(model2), separation3(model3), separation4(model4)
7. Matrix 비교하기
list=[]
def s_matrix(model):
for i in range(0,len(X)):
list.append([])
for j in range(0, len(X)):
if model.labels_[i]==model.labels_[j]:
list[i].append(1)
else:
list[i].append(0)
s_matrix(model2)
list
list=[]
s_matrix(model3)
list
list=[]
s_matrix(model4)
list
8. Entropy 비교하기
def entropy(labels):
n_labels = len(labels)
counts = np.bincount(labels)
probs = counts[np.nonzero(counts)] / n_labels
n_classes = len(probs)
return - np.sum(probs*np.log(probs)) / np.log(n_classes)
entropy(model2.labels_), entropy(model3.labels_), entropy(model4.labels_)
K-Means 장단점
장점
- 상대적 효율성
- 주로 local optimum 클러스터 군집을 찾는다. The Global Optimum 군집의 경우, 다수의 초기 seed 선택이나 진화적 seed 선택 등과 같은 개선 기법이 필요하다.
단점
- 중심값을 구할 수 있는 경우에만 적용가능하고, 아이템 형식의 데이터 등은 적용하기 어렵다
- k, the Number of Clusters가 적절히 정의되어야한다
- 잡음데이터나 이상치데이터에 영향을 받는다
- 임의 모양의 클러스터 군집을 찾는데 적합하지 않다
K-Means의 한계점
- 군집들이 다양성을 가지는 경우 효율적이지 못하다 - 군집의 크기, 군집의 밀도, 비원형 형태의 군집
- K-means 이상치를 포함한 데이터 처리에 부적합하다
→ 많은 수의 작은 군집들을 1차적으로 탐색한 뒤, 2차적으로 큰 군집을 찾는 과정을 수행한다 (Hierarchical Clustering)
DBSCAN, GRID, Optic, 등의 수단도 존재
실습) Iris 데이터 군집분석
'데이터 청년 캠퍼스 > SQL | 군집분석 | 소셜분석' 카테고리의 다른 글
[소셜분석] 베이지안 감정 분류 모델, 소셜분석 파싱 실습 (1) | 2022.07.14 |
---|---|
[소셜분석] Word Cloud 실습 - 앨리스, 스타워즈, 헌법 (0) | 2022.07.14 |
[소셜분석] 윈도우) Anaconda3(Python), JAVA, KoNLPy 라이브러리 설치 (0) | 2022.07.14 |
[소셜분석] 자연어 분석 KoNLPy 라이브러리 설치 및 실습 (0) | 2022.07.13 |
[군집분석] K-Means 군집 분석 알고리즘 (0) | 2022.07.11 |