GPT와 함께하는 클러스터링 정리

1. 클러스터와 클러스터링

클러스터는 데이터 분석에서 서로 비슷한 특성을 가진 데이터 포인트들의 묶음을 의미한다.
클러스터링은 이러한 묶음을 자동으로 찾아내는 과정이며, 비지도 학습의 대표적인 방법 중 하나이다.

비지도 학습은 정답 레이블 없이 데이터 자체의 구조를 파악하는 학습 방식이다.
따라서 클러스터링은 다음과 같은 상황에서 자주 사용된다.

  • 고객 세분화
  • 구매 패턴 분석
  • 이상 탐지 전처리
  • 이미지 군집화
  • 문서 주제 분리

좋은 클러스터는 일반적으로 다음 특징을 가진다.

  • 같은 클러스터 내부의 데이터는 서로 가깝다.
  • 다른 클러스터와는 충분히 구분된다.

대표적인 클러스터링 알고리즘은 다음과 같다.

  • K-Means
  • 계층적 클러스터링
  • DBSCAN

이 실습에서는 그중에서도 가장 대표적인 K-Means를 중심으로 진행한다.


2. 실습 전체 흐름

이 실습의 전체 흐름은 다음과 같다.

가상 데이터 생성
↓
데이터프레임 변환
↓
산점도로 데이터 구조 확인
↓
K-Means 군집화 적용
↓
군집 수를 바꿔가며 결과 비교
↓
inertia 확인
↓
여러 k에 대한 inertia 수집
↓
엘보우 메서드로 적절한 k 탐색

3. make_blobs()

개요

make_blobs()는 군집 구조가 있는 가상 데이터를 생성하는 함수이다.
클러스터링 실습에서는 실제 데이터 대신 군집이 잘 드러나는 인공 데이터를 만들기 위해 자주 사용한다.

이 함수는 지정한 개수의 중심점을 기준으로 데이터를 퍼뜨려 생성한다.
따라서 K-Means 같은 알고리즘이 어떻게 동작하는지 시각적으로 이해하기 좋다.


실습 코드

from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=100, centers=4, random_state=2026)

코드 해석

  • n_samples=100
    전체 샘플 수를 100개로 지정한다.
  • centers=4
    중심점을 4개로 두어 4개의 군집 구조를 가진 데이터를 만든다.
  • random_state=2026
    실행할 때마다 같은 데이터가 생성되도록 난수를 고정한다.

여기서 반환되는 값은 다음과 같다.

  • X: 실제 좌표 데이터
  • y: 각 샘플이 어느 중심에서 생성되었는지 나타내는 정답 그룹

클러스터링은 비지도 학습이므로 학습 시 y를 사용하지 않지만,
실습에서는 데이터가 실제로 어떤 구조인지 확인하는 참고용으로 사용할 수 있다.


반환값

X → numpy.ndarray
y → numpy.ndarray

ai가 추천하는 심화 예제

X, y = make_blobs(n_samples=200, centers=3, random_state=42)

print(X.shape)
print(y.shape)

# 결과
# (200, 2)
# (200,)

4. 데이터 직접 확인: X 와 y

개요

생성된 X와 y를 직접 출력하면,
X는 좌표값 배열, y는 각 점의 원래 그룹 번호라는 것을 확인할 수 있다.


실습 코드

X
y

해석

  • X의 각 행은 하나의 데이터 포인트이다.
  • 기본적으로 2차원 좌표 형태이므로 시각화가 쉽다.
  • y는 각 데이터가 어느 중심점에서 생성되었는지를 의미한다.

이때 y는 어디까지나 가상 데이터 생성 시 붙은 정답용 정보이며,
K-Means는 이 값을 모르고 X만 보고 스스로 군집을 나눈다.


5. pandas.DataFrame()

개요

K-Means는 NumPy 배열로도 바로 학습할 수 있지만,
시각화나 후속 조작을 더 편하게 하기 위해 DataFrame으로 변환하는 경우가 많다.

실습에서는 X를 DataFrame으로 바꿔 두 개의 컬럼을 가진 표 형태로 다룬다.


실습 코드

import pandas as pd
import seaborn as sns
X = pd.DataFrame(X)
X

주요 역할

  • 배열 데이터를 표 형태로 변환
  • 열 단위 접근을 쉽게 만듦
  • Seaborn 시각화와의 궁합 개선

반환값

pandas.DataFrame

ai가 추천하는 심화 예제

X_df = pd.DataFrame(X, columns=["feature_1", "feature_2"])

print(X_df.head())

# 결과
# 두 개의 feature 컬럼을 가진 데이터프레임 출력

6. sns.scatterplot()

개요

scatterplot()은 2차원 데이터를 점으로 시각화하는 함수이다.
클러스터링에서는 산점도가 매우 중요하다.
데이터가 실제로 몇 개 정도의 그룹으로 나뉘어 보이는지 눈으로 먼저 확인할 수 있기 때문이다.


실습 코드

sns.scatterplot(x=X[0], y=X[1], hue=y)

해석

  • x=X[0]
    첫 번째 좌표를 x축으로 사용한다.
  • y=X[1]
    두 번째 좌표를 y축으로 사용한다.
  • hue=y
    원래 생성된 그룹 번호를 색상으로 구분해서 보여준다.

이 그래프를 통해, 데이터가 실제로 4개의 중심 주변에 모여 있다는 점을 직관적으로 확인할 수 있다.


주요 역할

  • 데이터 구조 시각화
  • 군집이 얼마나 잘 분리되는지 확인
  • 실제 정답 그룹 분포 확인

반환값

matplotlib.axes.Axes

ai가 추천하는 심화 예제

sns.scatterplot(x=X_df["feature_1"], y=X_df["feature_2"])

# 결과
# 색 구분 없이 전체 데이터 분포만 시각화

7. K-Means 개요

K-Means는 데이터를 K개의 클러스터로 나누는 대표적인 비지도 학습 알고리즘이다.

동작 방식은 다음과 같다.

  1. 처음에 K개의 중심점 centroid를 정한다.
  2. 각 데이터 포인트를 가장 가까운 중심점에 할당한다.
  3. 각 클러스터의 평균 위치를 새로운 중심점으로 계산한다.
  4. 중심점이 더 이상 크게 바뀌지 않을 때까지 반복한다.

핵심 아이디어는 단순하다.

  • 같은 군집 안의 점들은 중심에 가깝게 모이게 하고
  • 서로 다른 군집은 자연스럽게 분리되도록 만든다.

장점은 다음과 같다.

  • 알고리즘이 단순하고 빠르다.
  • 대규모 데이터에도 비교적 잘 동작한다.
  • 직관적으로 이해하기 쉽다.

단점도 있다.

  • 군집 수 K를 미리 정해야 한다.
  • 구형 또는 볼록 형태 군집에 유리하다.
  • 이상치나 노이즈에 민감할 수 있다.
  • 초기 중심점에 따라 결과가 달라질 수 있다.

8. KMeans(), fit(), predict()

개요

KMeans()는 K-Means 모델 객체를 생성하고,
fit()은 데이터로 모델을 학습시키며,
predict()는 각 데이터가 어느 군집에 속하는지 예측한다.


실습 코드

from sklearn.cluster import KMeans

km = KMeans(n_clusters=4)
km.fit(X)
pred = km.predict(X)

sns.scatterplot(x=X[0], y=X[1], hue=pred)

코드 해석

  • n_clusters=4
    군집 개수를 4개로 지정한다.
  • fit(X)
    데이터를 바탕으로 중심점을 찾는다.
  • predict(X)
    각 데이터가 어느 군집에 속하는지 레이블을 반환한다.

여기서 pred는 0, 1, 2, 3 같은 군집 번호 배열이다.
이 번호는 원래 y와 숫자가 꼭 일치할 필요는 없다.
클러스터링에서는 번호 자체보다 어떤 점들이 함께 묶였는지가 중요하다.


반환값

  • KMeans() → 모델 객체
  • fit() → self
  • predict() → numpy.ndarray

ai가 추천하는 심화 예제

km = KMeans(n_clusters=3, random_state=42)
km.fit(X)
pred = km.predict(X)

print(pred[:10])

# 결과
# 앞 10개 샘플의 군집 번호 출력

9. 군집 수를 바꿔보기: n_clusters=5

개요

클러스터링에서 가장 중요한 결정 중 하나는 군집 수 K를 몇 개로 둘 것인가이다.
실습에서는 원래 데이터가 4개 군집 구조로 생성되었지만,
의도적으로 K를 5로 바꿔 군집화를 다시 수행한다.


실습 코드

km = KMeans(n_clusters=5)
km.fit(X)
pred = km.predict(X)

sns.scatterplot(x=X[0], y=X[1], hue=pred)

해석

K를 5로 주면 알고리즘은 어떻게든 5개로 나누려고 하기 때문에,
원래 하나의 자연스러운 군집이 둘로 쪼개지거나
군집 경계가 어색하게 형성될 수 있다.

이 과정을 통해 다음 사실을 배울 수 있다.

  • K-Means는 반드시 지정한 K개로 나눈다.
  • 따라서 K를 잘못 정하면 결과도 어색해질 수 있다.
  • 적절한 K를 찾는 과정이 필요하다.

10. inertia_

개요

inertia_는 KMeans 모델이 계산한 관성값을 의미한다.
관성은 각 데이터 포인트와 자신이 속한 클러스터 중심점 사이 거리의 제곱합이다.

즉, 같은 군집 안의 점들이 중심에 얼마나 밀집되어 있는지를 수치화한 값이다.

수식 느낌으로 쓰면 다음과 같이 볼 수 있다.

[
Inertia = \sum_{i=1}^{n} |x_i - \mu_{c_i}|^2
]

여기서

  • (x_i): 데이터 포인트
  • (\mu_{c_i}): 해당 포인트가 속한 클러스터 중심

실습 코드

km.inertia_

해석

관성값이 작을수록 군집 내부가 더 촘촘하게 모여 있다는 뜻이다.
즉, 일반적으로는 관성값이 낮을수록 더 좋은 군집화처럼 보인다.

하지만 주의할 점이 있다.

  • K가 커질수록 inertia는 거의 항상 감소한다.
  • 극단적으로 K를 데이터 개수만큼 늘리면 inertia는 매우 작아질 수 있다.
  • 따라서 inertia만 보고 최적 K를 바로 결정할 수는 없다.

이 때문에 엘보우 메서드 같은 추가적인 해석이 필요하다.


반환값

float

ai가 추천하는 심화 예제

km = KMeans(n_clusters=4, random_state=42)
km.fit(X)

print(km.inertia_)

# 결과
# 현재 K에 대한 관성값 출력

11. 여러 K에 대한 inertia 수집

개요

적절한 군집 수를 찾기 위해서는 여러 K에 대해 inertia를 비교해야 한다.
실습에서는 K를 2부터 10까지 바꿔가며 관성값을 저장한다.


실습 코드

inertia_list = []

for i in range(2, 11):
    km = KMeans(n_clusters=i)
    km.fit(X)
    inertia_list.append(km.inertia_)

inertia_list

코드 해석

  • range(2, 11)
    K를 2, 3, ..., 10까지 순회한다.
  • 각 K마다 KMeans를 새로 만들고 fit() 한다.
  • 학습 후 inertia_를 리스트에 저장한다.

이렇게 하면 K 변화에 따른 관성값 변화를 한눈에 볼 수 있는 준비가 된다.


주요 역할

  • 군집 수 후보별 성능 비교
  • 엘보우 메서드 입력 데이터 생성
  • K 변화에 따른 응집도 변화 확인

ai가 추천하는 심화 예제

inertia_list = []

for k in range(2, 8):
    km = KMeans(n_clusters=k, random_state=42)
    km.fit(X)
    inertia_list.append(km.inertia_)

print(inertia_list)

# 결과
# K=2~7에 대한 관성값 리스트 출력

12. sns.lineplot()

개요

lineplot()은 연속적인 값의 변화를 선 그래프로 시각화하는 함수이다.
여기서는 K에 따라 inertia가 어떻게 변하는지 확인하는 용도로 사용된다.


실습 코드

sns.lineplot(x=range(2, 11), y=inertia_list)

해석

x축은 군집 수 K,
y축은 각 K에서의 inertia 값이다.

일반적으로 K가 증가할수록 inertia는 감소한다.
하지만 어느 시점 이후부터는 감소 폭이 크게 줄어들 수 있다.
이 지점을 찾는 것이 바로 엘보우 메서드의 핵심이다.


반환값

matplotlib.axes.Axes

ai가 추천하는 심화 예제

sns.lineplot(x=list(range(2, 8)), y=inertia_list)

# 결과
# K와 관성값 관계를 선 그래프로 출력

13. 엘보우 메서드

개요

엘보우 메서드는 적절한 군집 수 K를 결정하기 위한 대표적인 방법이다.

기본 아이디어는 단순하다.

  • K를 늘릴수록 inertia는 줄어든다.
  • 하지만 어느 순간부터 감소 폭이 급격히 줄어든다.
  • 그 지점이 마치 팔꿈치처럼 꺾여 보인다고 해서 elbow point라고 부른다.
  • 그 K를 적절한 군집 수 후보로 본다.

즉,
군집 수를 늘리는 데 따른 이득이 확연히 줄어드는 시점을 찾는 방식이다.


해석 포인트

예를 들어 K를 늘릴 때 inertia가 다음처럼 감소한다고 하자.

  • K=2 → 크게 감소
  • K=3 → 크게 감소
  • K=4 → 꽤 감소
  • K=5 이후 → 감소 폭이 작음

이 경우 K=4 부근이 적절한 군집 수 후보가 될 가능성이 높다.

이 실습에서는 원래 make_blobs에서 centers=4로 데이터를 만들었기 때문에,
엘보우도 대체로 4 근처에서 나타날 가능성이 높다.


주의할 점

엘보우 메서드는 직관적이지만 항상 명확한 꺾임이 보이는 것은 아니다.
따라서 실제 문제에서는 다음 지표를 함께 쓰기도 한다.

  • 실루엣 점수
  • Davies-Bouldin score
  • Calinski-Harabasz score

14. 실습에서 사용된 핵심 메서드 요약

메서드 / 속성역할

make_blobs() 군집 구조를 가진 가상 데이터 생성
pandas.DataFrame() 배열 데이터를 표 형태로 변환
sns.scatterplot() 데이터 분포와 군집 결과 시각화
KMeans() K-Means 모델 생성
fit() 중심점 학습
predict() 군집 번호 예측
inertia_ 군집 내부 응집도 측정
sns.lineplot() K와 inertia 관계 시각화

15. 실습 전체 코드 흐름 요약

make_blobs()
↓
X, y 생성
↓
DataFrame 변환
↓
scatterplot() 으로 데이터 구조 확인
↓
KMeans(n_clusters=4)
↓
fit()
↓
predict()
↓
scatterplot() 으로 군집 결과 확인
↓
KMeans(n_clusters=5)
↓
fit()
↓
predict()
↓
군집 수 변화에 따른 결과 비교
↓
inertia_ 확인
↓
여러 K에 대해 inertia 수집
↓
lineplot() 으로 inertia 시각화
↓
엘보우 메서드로 적절한 K 탐색

16. 최종 정리

데이터 생성

  • make_blobs를 사용해 군집 구조가 있는 2차원 가상 데이터를 만든다.

시각화

  • scatterplot으로 데이터가 어떻게 모여 있는지 확인한다.
  • 원래 그룹과 예측된 군집을 각각 시각화한다.

K-Means 적용

  • 지정한 K에 따라 데이터를 군집으로 나눈다.
  • fit으로 중심점을 학습하고 predict로 군집 레이블을 얻는다.

군집 수 비교

  • K를 4와 5로 바꿔 결과를 비교한다.
  • K를 잘못 지정하면 군집이 부자연스럽게 나뉠 수 있음을 확인한다.

관성과 엘보우 메서드

  • inertia_를 통해 군집 내부 응집도를 수치화한다.
  • 여러 K에 대한 inertia를 선 그래프로 그리고
  • elbow point를 통해 적절한 군집 수를 탐색한다.