K-means 실습

동동·2026년 4월 3일

deeplearning

목록 보기
2/2

K-means

앞선 KNN은 라벨이 있는 상태에서 새로운 데이터의 위치를 찾는 분류 모델이었다.

K-means는 라벨이 없는 상태에서 데이터를 정해진 개수의 군집으로 나누는 비지도학습 알고리즘이다.

작동 방식은 다음과 같다.

1. 초기화: 데이터 공간에 K개의 centroid를 무작위로 배치

2. 군집 할당: 모든 데이터 포인트는 가장 가까운 중심점을 찾아 해당 그룹으로 소속됨

3. 중심점 업데이트: 각 그룹에 속한 데이터들의 산술 평균 위치를 계산하여, 중심점을 그 위치로 이동시킴

4. 반복: 중심점의 위치가 더 이상 변하지 않거나 정해진 반복 횟수에 도달할 때까지 2,3번 과정을 반복

코드 예시

import numpy as np
import cv2
import matplotlib.pyplot as plt
# load image
img =  cv2.imread('MRI.png') # Reads an image into BGR Format

img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)   #load image with RGB format
img_size = img.shape
print(img_size)

# Display original image
plt.imshow(img)
plt.title("Original Image")
plt.show()
# Reshape data

all_pixels  = img.reshape((-1,3)).astype(float)
print(all_pixels.shape)
# Run k-means clustering
from sklearn.cluster import KMeans

K = 4       # Number of clusters

km_model = KMeans(n_clusters=K)
km_model.fit(all_pixels)
# Learned Centroids
centers = km_model.cluster_centers_
print(centers) # In RGB Format
# Display different cluster segments
segmented_img = km_model.labels_    # Clustering Result
segmented_img = segmented_img.reshape(img_size[0], img_size[1])
plt.imshow(segmented_img)
plt.title("k-Means Clustering")
plt.show()
# display different segments separately

for k in range(K):
    plt.imshow(img*(segmented_img == k)[...,None])
    plt.title('Cluster ' + str(k))
    plt.show()

내가 작성한 코드

# L2 distance
def L2_distance(x, y):
    return np.sqrt( np.sum((x - y)**2, axis=1) )
# My k-means implementation

def my_kMeans(all_data, num_clusters):

    num_data, data_dim = all_data.shape # data size

    # Centroid and cluster initialization
    # centroids = np.random.rand(num_clusters, data_dim) * 256.                 # Random coordinate initialization
    centroids = all_data[np.random.randint(num_data, size = num_clusters),:]    # Random sample initialization
    clusters = (-1)*np.ones(num_data)     # initialize all the clusters with -1

    max_iteration = 20
    for iter in range(max_iteration):
        # save current cluster
        current_clusters = clusters.copy()

        # update cluster
        for k in range(num_data):
            data = all_data[k]  # each data
            # For each data, find the distance from the centroids
            dist = L2_distance(centroids, data)

            # find minimum distance (index) & save
            ########### Implement your code here ######################
            clusters[k] = np.argmin(dist) # dist 배열에 담긴 거리들 중 가장 작은 값(최단 거리)의 인덱스(클러스터 번호)를 저장합니다.

        # update the centroids
        for m in range(num_clusters):
            cluster_map = (clusters == m)
            num_samples_in_cluster = cluster_map.sum()

            # find the average of the cluster samples
            ########### Implement your code here ######################
            centroids[m] = np.mean(all_data[cluster_map], axis=0) # 할당된 데이터가 하나라도 있는 경우, 클러스터에 속한 데이터들의 축 0(axis=0)을 기준으로 평균(mean)을 구해 업데이트합니다.



        # We stop when the clusters does not change
        if np.sqrt(((current_clusters - clusters)**2).sum()) < 1e-20:
            break

    return clusters, centroids
# Run your kMeans

K = 4

labels, cent = my_kMeans(all_pixels, K)
# Display the segmentation results
seg_img = labels.reshape(img_size[0], img_size[1])
plt.imshow(seg_img)
plt.title("My k-Means Clustering")
plt.show()
for k in range(K):
    plt.imshow(img*(seg_img == k)[...,None])
    plt.title('Cluster ' + str(k))
    plt.show()

0개의 댓글