k-means
: 비계층 군집분석
: 특정한 임의 지점을 선택해 해당 중심에 가까운 포인트들을 선택하는 군집화 기법
- 이론
ratsgo.github.io/machine%20learning/2017/04/19/KC/
K-평균 군집화(K-means Clustering) · ratsgo's blog
이번 글에서는 K-평균 군집화(K-means Clustering)에 대해 살펴보겠습니다. (줄여서 KC라 부르겠습니다) 이번 글은 고려대 강필성 교수님과 역시 같은 대학의 김성범 교수님 강의를 정리했음을 먼저 밝
ratsgo.github.io
* cluster3_kmeans.py
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
print(make_blobs)
x, y = make_blobs(n_samples=150, n_features=2, centers=3, cluster_std = 0.5, shuffle = True, random_state=0)
print(x)
'''
[[ 2.60509732 1.22529553]
[ 0.5323772 3.31338909]
[ 0.802314 4.38196181]
[ 0.5285368 4.49723858]
[ 2.61858548 0.35769791]
[ 1.59141542 4.90497725]
...
]
'''
print(y)
# [1 0 0 0 1 0 0 1 2 0 1 2 2 ...]
plt.scatter(x[:, 0], x[:, 1], c='gray', marker='o')
plt.grid(True)
plt.show()
from sklearn.datasets import make_blobs
make_blobs(n_samples=샘플수, n_features=, centers=중심점수, cluster_std = 분산, shuffle = True, random_state=난수 seed) : blobs dataset 생성k-means
from sklearn.cluster import KMeans
kmodel = KMeans(n_clusters = 3, init='k-means++', random_state = 0).fit(x)
print(kmodel)
pred = kmodel.fit_predict(x)
print('pred:', pred)
'''
pred: [1 2 2 2 1 2 2 1 0 2 1 0 0 2 2 0 0 1 0 1 2 1 2 2 0 1 1 2 0 1 0 0 0 0 2 1 1
1 2 2 0 0 2 1 1 1 0 2 0 2 1 2 2 1 1 0 2 1 0 2 0 0 0 0 2 0 2 1 2 2 2 1 1 2
1 2 2 0 0 2 1 1 2 2 1 1 1 0 0 1 1 2 1 2 1 2 0 0 1 1 1 1 0 1 1 2 0 2 2 2 0
2 1 0 2 0 2 2 0 0 2 1 2 2 1 1 0 1 0 0 0 0 1 0 0 0 2 0 1 0 2 2 1 1 0 0 0 0
1 1]
'''
print(x[pred == 0])
'''
[[-2.12133364 2.66447408]
[-0.37494566 2.38787435]
[-1.84562253 2.71924635]
...
]
'''
print()
print(x[pred == 1])
'''
[[ 2.60509732 1.22529553]
[ 2.61858548 0.35769791]
[ 2.37533328 0.08918564]
...
]
'''
print()
print(x[pred == 2])
'''
[[ 0.5323772 3.31338909]
[ 0.802314 4.38196181]
[ 0.5285368 4.49723858]
...
]
'''
print()
from sklearn.cluster import KMeans
KMeans(n_clusters = 군집 수, init='k-means++', random_state = 난수 seed).fit(x) : kmeans
- KMeans API
scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html
sklearn.cluster.KMeans — scikit-learn 0.24.1 documentation
scikit-learn.org
plt.scatter(x[pred==0, 0], x[pred==0, 1], c = 'red', marker='o', label='cluster1')
plt.scatter(x[pred==1, 0], x[pred==1, 1], c = 'green', marker='s', label='cluster2')
plt.scatter(x[pred==2, 0], x[pred==2, 1], c = 'blue', marker='v', label='cluster3')
plt.scatter(kmodel.cluster_centers_[:, 0], kmodel.cluster_centers_[:, 1], c = 'black', marker='+', s=50, label='center')
plt.legend()
plt.grid(True)
plt.show()
# 몇개의 그룹으로 나눌지가 중요. k의 값.
# 방법 1 : elbow - 클러스터간 SSE(오차 제곱의 함, sum of squares error)의 차이를 이용해 k 개수를 알 수 있다.
plt.rc('font', family = 'malgun gothic')
def elbow(x):
sse = []
for i in range(1, 11): # KMeans 모델을 10번 실행
km = KMeans(n_clusters = i, init='k-means++', random_state = 0).fit(x)
sse.append(km.inertia_)
print(sse)
plt.plot(range(1, 11), sse, marker='o')
plt.xlabel('클러스터 수')
plt.ylabel('SSE')
plt.show()
elbow(x) # k는 3을 추천
# 방법 2 : silhoutte
'''
실루엣(silhouette) 기법
클러스터링의 품질을 정량적으로 계산해 주는 방법이다.
클러스터의 개수가 최적화되어 있으면 실루엣 계수의 값은 1에 가까운 값이 된다.
실루엣 기법은 k-means 클러스터링 기법 이외에 다른 클러스터링에도 적용이 가능하다
'''
import numpy as np
from sklearn.metrics import silhouette_samples
from matplotlib import cm
# 데이터 X와 X를 임의의 클러스터 개수로 계산한 k-means 결과인 y_km을 인자로 받아 각 클러스터에 속하는 데이터의 실루엣 계수값을 수평 막대 그래프로 그려주는 함수를 작성함.
# y_km의 고유값을 멤버로 하는 numpy 배열을 cluster_labels에 저장. y_km의 고유값 개수는 클러스터의 개수와 동일함.
def plotSilhouette(x, pred):
cluster_labels = np.unique(pred)
n_clusters = cluster_labels.shape[0] # 클러스터 개수를 n_clusters에 저장
sil_val = silhouette_samples(x, pred, metric='euclidean') # 실루엣 계수를 계산
y_ax_lower, y_ax_upper = 0, 0
yticks = []
for i, c in enumerate(cluster_labels):
# 각 클러스터에 속하는 데이터들에 대한 실루엣 값을 수평 막대 그래프로 그려주기
c_sil_value = sil_val[pred == c]
c_sil_value.sort()
y_ax_upper += len(c_sil_value)
plt.barh(range(y_ax_lower, y_ax_upper), c_sil_value, height=1.0, edgecolor='none')
yticks.append((y_ax_lower + y_ax_upper) / 2)
y_ax_lower += len(c_sil_value)
sil_avg = np.mean(sil_val) # 평균 저장
plt.axvline(sil_avg, color='red', linestyle='--') # 계산된 실루엣 계수의 평균값을 빨간 점선으로 표시
plt.yticks(yticks, cluster_labels + 1)
plt.ylabel('클러스터')
plt.xlabel('실루엣 개수')
plt.show()
'''
그래프를 보면 클러스터 1~3 에 속하는 데이터들의 실루엣 계수가 0으로 된 값이 아무것도 없으며, 실루엣 계수의 평균이 0.7 보다 크므로 잘 분류된 결과라 볼 수 있다.
'''
X, y = make_blobs(n_samples=150, n_features=2, centers=3, cluster_std=0.5, shuffle=True, random_state=0)
km = KMeans(n_clusters=3, random_state=0)
y_km = km.fit_predict(X)
plotSilhouette(X, y_km)
* cluster4.py
# 숫자 이미지 데이터에 K-평균 알고리즘 사용하기
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
import numpy as np
from sklearn.datasets import load_digits
digits = load_digits() # 64개의 특징(feature)을 가진 1797개의 표본으로 구성된 숫자 데이터
print(digits.data.shape) # (1797, 64) 64개의 특징은 8*8 이미지의 픽셀당 밝기를 나타냄
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=10, random_state=0)
clusters = kmeans.fit_predict(digits.data)
print(kmeans.cluster_centers_.shape) # (10, 64) # 64차원의 군집 10개를 얻음
# 군집중심이 어떻게 보이는지 시각화
fig, ax = plt.subplots(2, 5, figsize=(8, 3))
centers = kmeans.cluster_centers_.reshape(10, 8, 8)
for axi, center in zip(ax.flat, centers):
axi.set(xticks=[], yticks=[])
axi.imshow(center, interpolation='nearest')
plt.show() # 결과를 통해 KMeans가 레이블 없이도 1과 8을 제외하면
# 인식 가능한 숫자를 중심으로 갖는 군집을 구할 수 있다는 사실을 알 수 있다.
# k평균은 군집의 정체에 대해 모르기 때문에 0-9까지 레이블은 바뀔 수 있다.
# 이 문제는 각 학습된 군집 레이블을 그 군집 내에서 발견된 실제 레이블과 매칭해 보면 해결할 수 있다.
from scipy.stats import mode
labels = np.zeros_like(clusters)
for i in range(10):
mask = (clusters == i)
labels[mask] = mode(digits.target[mask])[0]
# 정확도 확인
from sklearn.metrics import accuracy_score
print(accuracy_score(digits.target, labels)) # 0.79354479
# 오차행렬로 시각화
from sklearn.metrics import confusion_matrix
mat = confusion_matrix(digits.target, labels)
sns.heatmap(mat.T, square=True, annot=True, fmt='d', cbar=False,
xticklabels=digits.target_names,
yticklabels=digits.target_names)
plt.xlabel('true label')
plt.ylabel('predicted label')
plt.show() # 오차의 주요 지점은 1과 8에 있다.
# 참고로 t분포 확률 알고리즘을 사용하면 분류 정확도가 높아진다.
from sklearn.manifold import TSNE
# 시간이 약간 걸림
tsne = TSNE(n_components=2, init='random', random_state=0)
digits_proj = tsne.fit_transform(digits.data)
# Compute the clusters
kmeans = KMeans(n_clusters=10, random_state=0)
clusters = kmeans.fit_predict(digits_proj)
# Permute the labels
labels = np.zeros_like(clusters)
for i in range(10):
mask = (clusters == i)
labels[mask] = mode(digits.target[mask])[0]
# Compute the accuracy
print(accuracy_score(digits.target, labels)) # 0.93266555
iris dataset으로 지도/비지도 학습 - KNN, KMEANS
* cluster5_iris.py
from sklearn.datasets import load_iris
iris_dataset = load_iris()
print(iris_dataset.keys())
# dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename'])
print(iris_dataset['data'][:3])
'''
[[5.1 3.5 1.4 0.2]
[4.9 3. 1.4 0.2]
[4.7 3.2 1.3 0.2]]
'''
print(iris_dataset['feature_names'])
# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
print(iris_dataset['target'][:3]) # [0 0 0]
print(iris_dataset['target_names']) # ['setosa' 'versicolor' 'virginica']
# train/test
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(iris_dataset['data'], iris_dataset['target'], test_size = 0.25, random_state = 42)
print(train_x.shape, test_x.shape) # (112, 4) (38, 4)
- 지도학습 : KNN
from sklearn.neighbors import KNeighborsClassifier
knnModel = KNeighborsClassifier(n_neighbors=1, weights='distance', metric = 'euclidean')
print(knnModel)
knnModel.fit(train_x, train_y)
# 모델 성능
import numpy as np
predict_label = knnModel.predict(test_x)
print('예측값 :', predict_label) # [1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1 0]
print('실제값 :', test_y) # [1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1 0]
print('test acc : {:.3f}'.format(np.mean(predict_label == test_y))) # test acc : 1.000
from sklearn import metrics
print('test acc :', metrics.accuracy_score(test_y, predict_label)) # test acc : 1.0
print()
# 새로운 값을 분류
new_input = np.array([[6.6, 5.5, 4.4, 1.1]])
print(knnModel.predict(new_input)) # [1]
print(knnModel.predict_proba(new_input)) # [[0. 1. 0.]]
dist, index = knnModel.kneighbors(new_input)
print(dist, index) # [[2.24276615]] [[3]]
print()
- 비지도학습 : K-MEANS
from sklearn.cluster import KMeans
kmeansModel = KMeans(n_clusters = 3, init='k-means++', random_state=0)
kmeansModel.fit(train_x) # feature만 참여
print(kmeansModel.labels_) # [1 1 0 0 0 1 1 0 0 2 0 2 0 2 0 1 ...
print('0 cluster : ', train_y[kmeansModel.labels_ == 0])
# 0 cluster : [2 1 1 1 2 1 1 1 1 1 2 1 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 1]
print('1 cluster : ', train_y[kmeansModel.labels_ == 1])
# 1 cluster : [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
print('2 cluster : ', train_y[kmeansModel.labels_ == 2])
# 2 cluster : [2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 2 2 2]
# 새로운 값을 분류
new_input = np.array([[6.6, 5.5, 4.4, 1.1]])
predict_cluster = kmeansModel.predict(new_input)
print(predict_cluster) # [2]
print()
# 성능 측정
predict_test_x = kmeansModel.predict(test_x)
print(predict_test_x)
np_arr = np.array(predict_test_x)
np_arr[np_arr == 0], np_arr[np_arr == 1], np_arr[np_arr == 2] = 3, 4, 5 # 임시 저장용
print(np_arr)
np_arr[np_arr == 3] = 1 # 군집3을 1로 versicolor로 변경
np_arr[np_arr == 4] = 0 # 군집4을 0로 setosa로 변경
np_arr[np_arr == 5] = 2 # 군집5을 2로 verginica로 변경
print(np_arr)
predict_label = np_arr.tolist()
print(predict_label)
print('test acc :{:.3f}'.format(np.mean(predict_label == test_y))) # test acc :0.947
ㅁ
'BACK END > Deep Learning' 카테고리의 다른 글
[딥러닝] TensorFlow 환경설정 (0) | 2021.03.22 |
---|---|
[딥러닝] DBScan (0) | 2021.03.22 |
[딥러닝] 클러스터링 (0) | 2021.03.19 |
[딥러닝] Neural Network (0) | 2021.03.19 |
[딥러닝] KNN (0) | 2021.03.18 |