MACHINE LEARNING/Machine Learning Library

ML(머신러닝) : K-Means Clustering 개념 정리 (K-Means++ 알고리즘, sklearn.cluster, KMeans 활용)

신강희 2024. 4. 24. 12:28
728x90

< K-Means Clustering >

- K-Means Clustering은 비지도 학습 알고리즘 중 하나로, 데이터를 여러 개의 클러스터로 그룹화하는 데 사용된다.

- 이 알고리즘의 목표는 데이터 포인트들을 그룹 내에서 가능한 작은 거리의 합계로 클러스터링하는 것!

 

# 이전까지 작성한 Classification(분류)에 KNN, SVM, Decision Tree, Logistic regression

# Prediction(예측)에 regression(회귀) 은 모두 Supervised Learnig 

# Clustering은 모두 Unsupervised Learning 이다.

 

k 개의 그룹을 만든다. 즉, 비슷한 특징을 갖는 것들끼리 묶는것

다음을 두개, 세개, 네개 그룹 등등 원하는 그룹으로 만들 수 있다.

 

알고리즘

또다시 중심에 직교하는 선을 긋고, 자신의 영역안에 있는 것들을 자신의 색으로 바꾼다.

 

중심을 이동해서, 영역을 나눴는데, 나눈 영역안에 다른 카테고리가 더이상 나타나지 않으면, 끝낸다.

 

< Random Initialization Trap >

- 클러스터링 알고리즘에서 발생할 수 있는 문제

- 이 문제는 K-Means 알고리즘이 초기 중심의 무작위 선택에 따라 결과가 크게 달라질 수 있다는 것을 의미한다.

 

다음과 같은 데이터 분포가 있다고 치자.

우리가 원하는 클러스터링 그룹화는, 아래와 같은 것이다.

원치 않는 그룹화가 되어버렸다!

위와 같은 문제는 해결한것이, K-Means++ 알고리즘이다.

 

< Choosing the right number of clusters >

몇개로 분류할지는 어떻게 결정하는가? K의 갯수를 정하는 방법

within-cluster sums of squares

센터가 원소들과의 거리가 멀수록 값이 커진다. 따라서 최소값에 가까워지는 갯수를 뽑되, 갯수가 너무 많아지면 차별성이 없어진다.

 

# 사람 팔꿈치처럼 확 꺾인다고 하여 엘보우 메소드라고 한다.

 

< 에제를 통하여 코딩해 보자 >

import pandas as pd

 

df = pd.read_csv('../data/Mall_Customers.csv')

 

# 원하는 그룹(비슷한 사람들끼리) 을 만들어야 한다. => 클러스터링

df.isna().sum()

CustomerID                0
Genre                     0
Age                       0
Annual Income (k$)        0
Spending Score (1-100)    0
dtype: int64

 

# 클러스터링(Unsupervised) 은 y 그룹을 만들어 달라고 요청하는거기 때문에 X만 생성

X = df.loc[ : , 'Genre' : 'Spending Score (1-100)' ]

 

# 문자열 데이터가 있으므로 인코딩

X['Genre'].nunique()

2

 

from sklearn.preprocessing import LabelEncoder

 

encoder = LabelEncoder()

encoder.fit_transform(X['Genre'])

array([1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1,
       0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
       0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1,
       0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0,
       0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1,
       1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1,
       0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,
       0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0,
       1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
       1, 1])

 

# 스펠링 순으로 순서를 매기기 때문에 0이 Female 1이 Male
sorted(X['Genre'].unique())

['Female', 'Male']

 

# 인코딩한 데이터를 Genre 컬럼 값으로 넣기

X['Genre'] = encoder.fit_transform(X['Genre'])

ㄴ 변환된것 확인

 

# K-Means는 피쳐스케일링을 안해도 된다. 어차피 이 데이터를 가지고 평균을 구하는거기 때문에
# 한다고 문제가 되진 않지만 구지 필요가 없다

# 컬럼이 4개이므로 차트로 그릴수 없다. 차트로 그릴수 있는 최대 갯수는 3개 x,y,z 4개 이상은 불가능 하다.

 

# KMeans 인공지능 생성

from sklearn.cluster import KMeans

 

# 인공지능 이름은 kmeans () 파라미터 안에 그룹수를 정해줘야 하는데 아직 적합한 수를 못구했으므로 임의로 적는다. 지금은 3개
kmeans = KMeans(n_clusters= 3, random_state= 10)

 

# 학습 fit 와 예측 predict를 한꺼번에 실행
y_pred = kmeans.fit_predict(X)

 

y_pred

array([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, 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, 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, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2, 1,
       2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
       2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
       2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
       2, 1])

 

# 구한 그룹정보를 원본 데이터에 넣어준다.
df['Group'] = y_pred

 

# 그룹1인 그룹사람들에게 푸시보낼거다. 이 그룹 데이터 가져와라

df.loc[df['Group'] == 1 , ]

 

## 그룹수를 바꾸면서 적합한 그룹수를 다시 알아보자
# 반복문을 사용하여 1~10개까지 그룹수를 넣어본다.
# wcss라는 임의의 비어있는 리스트를 만들어줘서 해당 반복문 결과를 리스트에 저장시킨다.

wcss = []
for i in range(1, 10+1) :
    kmeans = KMeans(n_clusters=i, random_state= 10)
    kmeans.fit(X)
    wcss.append(kmeans.inertia_)

 

# 경고문은 무시하여도 된다.

 

wcss

[308862.06,
 212889.442455243,
 143391.59236035674,
 104414.67534220166,
 75399.61541401484,
 58348.64136331505,
 51167.19736842105,
 45324.85021951262,
 40811.455768566826,
 37141.48254409704]

 

# 시각화 해보자

import matplotlib.pyplot as plt

 

plt.plot(wcss)

plt.show()

 

# 대략 5개일때부터 변화가 없으므로, 그룹수를 5개로 하여 다시 학습 후 예측

kmeans = KMeans(n_clusters= 5, random_state= 1)

y_pred = kmeans.fit_predict(X)

 

# 원본데이터에 예측값을 컬럼으로 넣어 눈으로 비교해보자.df['Group'] = y_pred

 

# 각 그룹별로 확인해보고 싶을때.

# 나눈 갯수대로 해당 값만 불러와서 확인 할수 있다.

 

df.loc[df['Group'] == 0 , ]

df.loc[df['Group'] == 4 , ]

 

다음 게시글로 계속

반응형