머신러닝(군집)

짬그브·2025년 3월 20일

k-평균 군집

군집(clustering)은 데이터 셋을 클러스터(cluster)라는 그룹으로 나누는 작업이다.

한 클러스터 안의 데이터 포인트끼리는 매우 비슷하고 다른 클러스터의 데이터 포인트와는 구분되도록 데이터를 나누는 것이 목표이다.

분류 알고리즘과 비슷하게 군집 알고리즘은 각 데이터 포인터가 어느 클러스터에 속하는지 할당 또는 예측한다.

군집의 종류 : k-평균 군집, 병합 군집, DBSCAN

k-평균(k-mean) 군집은 간단하고 널리 사용하는 군집 알고리즘이다.
k-평균 알고리즘은 데이터의 어떤 영역을 대표하는 클러스터중심(cluster center)를 찾는 것이다.
k-평균 알고리즘은 두 단계를 반복적으로 수행한다.
1. 데이터 포인트를 가장 가까운 클러스터 중심에 할당한다.
2. 클러스터에 할당된 데이터 포인트의 평균으로 클러스터 중심을 다시 지정한다.

rom sklearn.datasets import load_iris
import matplotlib.pyplot as plt

data = load_iris()
print(data.target)
print(data.target_names)

x = data.data
plt.figure(figsize=(9,4))
plt.subplot(121)
plt.scatter(x[:,2],x[:,3], c='k', marker='.')
plt.xlabel('Petal length', fontsize=14)
plt.ylabel('Petal width', fontsize=14)

y = data.target

plt.subplot(122)
plt.plot(x[y==0, 2], x[y==0,3], 'yo', label='iris setosa')
plt.plot(x[y==1, 2], x[y==1,3], 'bs', label='iris versicolor')
plt.plot(x[y==2, 2], x[y==2,3], 'g^', label='iris virginca')
plt.xlabel('Petal Length', fontsize=14)
plt.legend(loc='best')
plt.tick_params(labelleft=False)
plt.show()


mglearn 모듈 install

import matplotlib.pyplot as plt
import mglearn
mglearn.plots.plot_kmeans_algorithm()
plt.show()

from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np

#############################################################
blob_centers = np.array(
    [[0.2,2.3],
     [-1.5, 2.3],
     [-2.8, 1.8],
     [-2.8, 2.8],
     [-2.8, 1.3]]
)
blob_std = np.array([0.4, 0.3, 0.1, 0.1, 0.1])
x,y = make_blobs(n_samples=2000, centers=blob_centers,
                 cluster_std=blob_std, random_state=7)

def plot_clusters(x, y=None):
    plt.scatter(x[:,0], x[:,1], c=y, s=1)
    plt.xlabel('x')
    plt.xlabel('y')

plt.figure(figsize=(8,4))
plot_clusters(x)
plt.show()

from sklearn.cluster import KMeans

k = 5
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(x)
y_pred = kmeans.predict(x)
print(y_pred)
print(kmeans.cluster_centers_)
print()
print(blob_centers)
print(kmeans.labels_)

x_new = np.array([[0,2],[3,2],[-3,3],[3,2.5]])
print(kmeans.predict(x_new))

[2 2 4 ... 1 4 2]
[[-0.066884    2.10378803]
 [-2.79290307  2.79641063]
 [-2.80214068  1.55162671]
 [-1.47468607  2.28399066]
 [ 0.47042841  2.41380533]]

[[ 0.2  2.3]
 [-1.5  2.3]
 [-2.8  1.8]
 [-2.8  2.8]
 [-2.8  1.3]]
[2 2 4 ... 1 4 2]
[0 4 1 4]

from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np

#############################################################
blob_centers = np.array(
    [[0.2,2.3],
     [-1.5, 2.3],
     [-2.8, 1.8],
     [-2.8, 2.8],
     [-2.8, 1.3]]
)
blob_std = np.array([0.4, 0.3, 0.1, 0.1, 0.1])
x,y = make_blobs(n_samples=2000, centers=blob_centers,
                 cluster_std=blob_std, random_state=7)

def plot_clusters(x, y=None):
    plt.scatter(x[:,0], x[:,1], c=y, s=1)
    plt.xlabel('x')
    plt.xlabel('y')

plt.figure(figsize=(8,4))
plot_clusters(x)
plt.show()

from sklearn.cluster import KMeans

k = 5
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(x)
y_pred = kmeans.predict(x)
print(y_pred)
print(kmeans.cluster_centers_)
print()
print(blob_centers)
print(kmeans.labels_)

x_new = np.array([[0,2],[3,2],[-3,3],[3,2.5]])
print(kmeans.predict(x_new))

#############################################################

def plot_data(X):
    plt.plot(X[:, 0], X[:, 1], 'k.', markersize=2)

def plot_centroids(centroids, weights=None, circle_color='w', cross_color='k'):
    if weights is not None:
        centroids = centroids[weights > weights.max() / 10]
    plt.scatter(centroids[:, 0], centroids[:, 1],
                marker='o', s=35, linewidths=8,
                color=circle_color, zorder=10, alpha=0.9)
    plt.scatter(centroids[:, 0], centroids[:, 1],
                marker='x', s=2, linewidths=12,
                color=cross_color, zorder=11, alpha=1)

def plot_decision_boundaries(clusterer, X, resolution=1000, show_centroids=True,
                             show_xlabels=True, show_ylabels=True):
    mins = X.min(axis=0) - 0.1
    maxs = X.max(axis=0) + 0.1
    xx, yy = np.meshgrid(np.linspace(mins[0], maxs[0], resolution),
                         np.linspace(mins[1], maxs[1], resolution))
    Z = clusterer.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)

    plt.contourf(Z, extent=(mins[0], maxs[0], mins[1], maxs[1]),
                cmap="Pastel2")
    plt.contour(Z, extent=(mins[0], maxs[0], mins[1], maxs[1]),
                linewidths=1, colors='k')
    plot_data(X)
    if show_centroids:
        plot_centroids(clusterer.cluster_centers_)

    if show_xlabels:
        plt.xlabel("$x_1$", fontsize=14)
    else:
        plt.tick_params(labelbottom=False)
    if show_ylabels:
        plt.ylabel("$x_2$", fontsize=14, rotation=0)
    else:
        plt.tick_params(labelleft=False)

plt.figure(figsize=(8, 4))
plot_decision_boundaries(kmeans, x)
plt.show()


#k-평균 알고리즘

#############################################################

kmeans_iter1 = KMeans(n_clusters=5, init='random', n_init=1,
                      max_iter=1, random_state=0)
kmeans_iter2 = KMeans(n_clusters=5, init='random', n_init=1,
                      max_iter=2, random_state=0)
kmeans_iter3 = KMeans(n_clusters=5, init='random', n_init=1,
                      max_iter=3, random_state=0)

kmeans_iter1.fit(x)
kmeans_iter2.fit(x)
kmeans_iter3.fit(x)



#############################################################

plt.figure(figsize=(10, 8))

plt.subplot(321)
plot_data(x)
plot_centroids(kmeans_iter1.cluster_centers_, circle_color='r', cross_color='w')
plt.ylabel("$x_2$", fontsize=14, rotation=0)
plt.tick_params(labelbottom=False)
plt.title("Update the centroids (initially randomly)", fontsize=14)

plt.subplot(322)
plot_decision_boundaries(kmeans_iter1, x, show_xlabels=False, show_ylabels=False)
plt.title("Label the instances", fontsize=14)

plt.subplot(323)
plot_decision_boundaries(kmeans_iter1, x, show_centroids=False, show_xlabels=False)
plot_centroids(kmeans_iter2.cluster_centers_)

plt.subplot(324)
plot_decision_boundaries(kmeans_iter2, x, show_xlabels=False, show_ylabels=False)

plt.subplot(325)
plot_decision_boundaries(kmeans_iter2, x, show_centroids=False)
plot_centroids(kmeans_iter3.cluster_centers_)

plt.subplot(326)
plot_decision_boundaries(kmeans_iter3, x, show_ylabels=False)

plt.show()



kmeans_per_k = [KMeans(n_clusters=k, random_state=42).fit(x) for k in range(1,10)]
inertias = [model.inertia_ for model in kmeans_per_k]

plt.figure(figsize=(7,4))
plt.plot(range(1,10), inertias, 'bo-')
plt.xlabel('K', fontsize=14)
plt.ylabel('Inertia', fontsize=14)
plt.annotate('Elbow',
             xy=(4, inertias[3]),
             xytext=(0.55, 0.55),
             fontsize=16,
             textcoords='figure fraction',
             arrowprops=dict(facecolor='black',shrink=0.1))
plt.show()

from sklearn.metrics import silhouette_score

print(silhouette_score(x, kmeans.labels_))
silhouette_scores = [silhouette_score(x, model.labels_)for model in kmeans_per_k[1:]]
plt.figure(figsize=(7,3))
plt.plot(range(2,10), silhouette_scores, 'bo-')
plt.xlabel('K', fontsize=14)
plt.ylabel('Silhouette score', fontsize=14)
plt.show()

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.DataFrame(columns=['height', 'weight'])
df.loc[0] = [185,60]
df.loc[1] = [180,60]
df.loc[2] = [185,70]
df.loc[3] = [165,63]
df.loc[4] = [155,68]
df.loc[5] = [170,75]
df.loc[6] = [175,80]


import seaborn as sns
from sklearn.cluster import KMeans


data_point = df.values
kmeans = KMeans(n_clusters=3).fit(data_point)
print(kmeans.cluster_centers_)
df['cluster_id'] = kmeans.labels_
print(df)

sns.lmplot(x='height', y='weight',
           data=df, fit_reg=False,
           scatter_kws={'s':200},
           hue='cluster_id')
plt.show()

from matplotlib.image import imread
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

image = imread('ladybug.png')
print(image.shape)

x = image.reshape(-1,3)
print(x.shape)
kmeans = KMeans(n_clusters=8, random_state=42).fit(x)
segment_img = kmeans.cluster_centers_[kmeans.labels_]
segment_img = segment_img.reshape(image.shape)

segment_imgs = []

n_colors = [10, 8, 6, 4, 2]
for n_clusters in n_colors:
    kmeans = KMeans(n_clusters=n_clusters, random_state=42).fit(x)
    segment_img = kmeans.cluster_centers_[kmeans.labels_]
    segment_imgs.append(segment_img.reshape(image.shape))

plt.figure(figsize=(8,4))
plt.subplot(231)
plt.imshow(image)
plt.title('Original image')
plt.axis('off')

for idx, n_clusters in enumerate(n_colors):
    plt.subplot(232 + idx)
    plt.imshow(segment_imgs[idx])
    plt.title(f'{n_clusters} colors')
    plt.axis('off')


plt.show()

(533, 800, 3)
(426400, 3)

병합 군집

병합 군집(agglomerative clustering) 은 시작할 때 각 포인트를 하나의 클러스터로 지정하고, 그 다음 특정 종료 조건을 만족할 때까지 가장 비슷한 두 클러스터를 합친다.

scikit-learn의 병합 군집 옵션은 아래와 같다.
ward : 기본으로 설정되어 있으며, 조건은 모든 클러스터내의 분산을 가장 작게 증가시키는 두 클러스터를 합친다. 그래서 크기가 비교적 비슷한 클러스터가 만들어진다.
average : 클러스터 포인트 사이의 평균 거리가 가장 짧은 두 클러스터를 합친다.
complete : 클러스터 포인트 사이의 최대 거리가 가장 짧은 두 클러스터를 합친다.

scikit-learn의 병합 군집 종료 조건은 클러스터 개수로 지정한다.

import matplotlib.pyplot as plt
import mglearn

mglearn.plots.plot_agglomerative_algorithm()
plt.show()

DBSCAN

DBSCAN ( density-based spatial clustering of applications with noise) 은 특성 공간에서 데이터가 많이 붐비는 포인트를 찾는다. 이런 지역을 특성 공간의 밀집 지역(dense region) 이라고 한다.
DBSCAN의 아이디어는 데이터의 밀집 지역을 한 클러스터로 구성하며 비교적 비어있는 지역을 경계로 다른 클러스터와 구분하는 것이다.
DBSCAN에는 두개의 매개변수(min_samples, eps)가 있다.
한 데이터 포인터에서 eps 거리 안에 데이터가 min_samples 개수만큼 들어있으면 이 데이터 포인터를 핵심 샘플(P) 로 분류한다.
eps보다 가까운 핵심 샘플은 DBSCAN에 의해 동일한 클러스터로 합쳐진다.

DBSCAN은 시작할 때 무작위로 포인트를 선택한다.
포인트에서 eps 거리 안의 모든 포인터를 찾는다. 만약 eps 거리 안에 있는 포인트 수가 min_samples 보다 적으면 그 포인트는 어떤 클래스에도 속하지 않는 noise로 레이블 한다.
eps 거리 안에 있는 포인트 수가 min_samples보다 많은 포인트가 있다면 그 포인트는 핵심 샘플로 레이블하고 새로운 클러스터 레이블을 할당한다.
그런 다음 그 포인트(eps 거리안의) 의 모든 이웃을 확인하고, 만약 어떤 클러스터에도 아직 할당되지 않았다면 현재 클러스터에 할당한다. 그리고 eps 거리 안에 있으면 이웃이 핵심 샘플이면 그 포인트의 이웃을 차례로 방문하여 동일한 클러스터로 합친다. 이 과정을 eps 거리 안에 더 이상 핵심 샘플이 없을 때가지 진행한다.


from sklearn.datasets import make_moons
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt
import numpy as np


def plot_dbscan(dbscan, X, size, show_xlabels=True, show_ylabels=True):
    core_mask = np.zeros_like(dbscan.labels_, dtype=bool)
    core_mask[dbscan.core_sample_indices_] = True
    anomalies_mask = dbscan.labels_ == -1
    non_core_mask = ~(core_mask | anomalies_mask)

    cores = dbscan.components_
    anomalies = X[anomalies_mask]
    non_cores = X[non_core_mask]

    plt.scatter(cores[:, 0], cores[:, 1],
                c=dbscan.labels_[core_mask], marker='o', s=size, cmap="Paired")
    plt.scatter(cores[:, 0], cores[:, 1], marker='*', s=20, c=dbscan.labels_[core_mask])
    plt.scatter(non_cores[:, 0], non_cores[:, 1], c=dbscan.labels_[non_core_mask], marker=".")
    if show_xlabels:
        plt.xlabel("$x_1$", fontsize=14)
    else:
        plt.tick_params(labelbottom=False)
    if show_ylabels:
        plt.ylabel("$x_2$", fontsize=14, rotation=0)
    else:
        plt.tick_params(labelleft=False)
    plt.title("eps={:.2f}, min_samples={}".format(dbscan.eps, dbscan.min_samples), fontsize=14)


#############################################################
X,y = make_moons(n_samples=1000, noise=0.05, random_state=42)
dbscan = DBSCAN(eps=0.05, min_samples=5)
dbscan.fit(X)
print(dbscan.labels_[:10])

dbscan2 = DBSCAN(eps=0.2, min_samples=5)
dbscan2.fit(X)
print(dbscan2.labels_[:10])

plt.figure(figsize=(9,4))
plt.subplot(121)
plot_dbscan(dbscan, X, size=100)
plt.subplot(122)
plot_dbscan(dbscan2, X, size=600, show_ylabels=False)
plt.show()



#############################################################







[ 0  2 -1 -1  1  0  0  0  2  5]
[0 0 0 0 1 0 0 0 0 1]

from sklearn.metrics.cluster import adjusted_rand_score
from sklearn.datasets import make_moons
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans, AgglomerativeClustering, DBSCAN
import mglearn
import matplotlib.pyplot as plt
import numpy as np


x, y = make_moons(n_samples=200, noise=0.05, random_state=0)

scaler = StandardScaler()
scaler.fit(x)
x_scaled = scaler.transform(x)

fig, axes = plt.subplots(1,4,figsize=(15,3), subplot_kw={'xticks':[],'yticks':[]})
algorithms = [KMeans(n_clusters=2),AgglomerativeClustering(n_clusters=2), DBSCAN()]

np.random.seed(0)
random_clusters = np.random.randint(low=0, high=2, size=len(x))
axes[0].scatter(x_scaled[:,0], x_scaled[:,1], c= random_clusters, cmap=mglearn.cm3, s=60, edgecolors='black')
axes[0].set_title(f'random-allocation - ARI : {adjusted_rand_score(y, random_clusters):.2f}')

for ax, algorithm in zip(axes[1:], algorithms):
    clusters = algorithm.fit_predict(x_scaled)
    ax.scatter(x_scaled[:,0], x_scaled[:,1], c=clusters, cmap=mglearn.cm3, s=60, edgecolor='k')
    ax.set_title(f'{algorithm.__class__.__name__} - ARI : {adjusted_rand_score(y, clusters):.2f}')
plt.show()

profile
+AI to AI+

0개의 댓글