카테고리 없음

2025.12.16 TIL (본캠프, 42일차)

D:Connect 2025. 12. 16. 21:19

오늘은 어제 배운 클러스터링을 실습하였다.

어제 배운 개념들이 실제로 어떻게 작동하는지 눈으로 확인할 수 있었다.

 

코드 한 줄 한 줄의 의미가 중요하지만, 처음이기에 외우는것보다 나는 각 단계가 어떤 의미인지 이해하려고 했다.

 

데이터 준비

먼저 필요한 라이브러리들을 import했다.

표준화, PCA, K-Means, 시각화 등 어제 배운 모든 기법들이 라이브러리로 준비되어 있었다.(복붙이 아니라 직접 입력하는게 핵심)

신기했던 건 yellowbrick이라는 라이브러리인데, 이건 K값을 자동으로 추천해주는 Elbow Method를 구현하는 것이였다.

 

데이터를 로드한 후, 먼저 결측치를 확인했다. 이제 이건 기본이다.

 

비지도학습에서는 피처 선택이 중요하다

클러스터링에 사용할 컬럼을 지정하는 부분이 있었다:

feature_names=['customer_zip_code_prefix','price','shipping_charges','payment_sequential','payment_value']

 

어제 강의에서 "컬럼이 가지는 개념적 의미는 무엇인지?"를 물었던 이유가 여기였다.

무작정 모든 컬럼을 쓰는 게 아니라, 분석 목적에 맞는 컬럼을 선택해야 한다는 뜻이다.

 

비지도 학습 전처리 과정

 

표준화

StandardScaler를 사용했다. 어제 배운 내용 그대로다:

scale_df = StandardScaler().fit_transform(base_df1)

fit_transform을 한 번에 한다. fit은 평균과 표준편차를 계산하고, transform은 그것을 적용한다.

 

PCA로 차원 축소

pca = PCA(n_components=3)
pca.fit(scale_df)
pca.explained_variance_ratio_.sum()

3개의 주성분을 설정했을 때, 전체 분산의 몇 %를 설명하는지 확인한다.

튜터는 이 값이 높을수록 좋다고 했다. 예를 들어 0.85가 나오면 "5개 컬럼의 85%를 3개로 설명한다"는 뜻이다.

 

그리고 실제로 PCA를 적용해서 변환된 데이터를 얻는다:

pca_df = pca.fit_transform(scale_df)

이제 원본 5개 컬럼이 3개 주성분(PC1, PC2, PC3)으로 축소되었다.

 

다음 단계는 최적의 K값 찾기

Elbow Method

visualizer = KElbowVisualizer(model, k=(3,12))
visualizer.fit(pca_df) 
visualizer.show()

K 범위를 3부터 12까지 설정하고, 각 K에서의 성능을 시각화한다.

산점도가 팍 꺾이는 지점이 Elbow Point다. 거기가 추천 K값이다.

 

Distance Map

intercluster_distance(MiniBatchKMeans(5, random_state=42), pca_df)

K=5일 때 각 클러스터 간 거리를 히트맵으로 본다.

색이 밝을수록 거리가 멀다.

대칭 구조로 나타나고, 대각선은 자기 자신과의 거리(0)이므로 검은색이다.

어제 강의에서 "이는 참고치일 뿐이다"라고 했던 이유가 이제 이해된다. 히트맵이 실행할 때마다 약간 달라질 수 있기 때문이다.

 

(핵심) 클러스터링 실행

K-Means 적용

kmeans = KMeans(n_clusters=5, random_state=42, init='random')
kmeans.fit(pca_df)
labels = kmeans.labels_

K=5로 정하고 K-Means를 실행한다.

random_state=42는 재현성을 위해 랜덤 시드를 고정하는 것이다. 그래야 같은 결과가 나온다.

실행되면 각 데이터 포인트에 0부터 4까지의 클러스터 번호가 할당된다.

 

결과 확인

base_df.groupby(['Cluster'])['customer_id'].count().reset_index()

각 클러스터에 몇 개의 고객이 속하는지 확인한다.

혹시 한 클러스터에 대부분의 고객이 몰려있다면 문제가 있다는 신호다.

 

시각화 통해 확인

2D 산점도

sns.scatterplot(data = kmeans_df, x = 'PC1', y='PC2', hue='Cluster',palette = 'Set3')

PCA의 첫 두 주성분으로 2차원에 시각화한다.

색으로 구분된 5개 클러스터가 명확히 분리되어 보인다. 만약 섞여있다면 K값이나 피처를 다시 조정해야 한다.

 

3D 산점도

fig = plt.figure(figsize=(12,10))
ax = plt.subplot(111, projection='3d')
ax.scatter(x, y, z, s=60, c=kmeans_df["Cluster"], marker='*', alpha = 0.7, cmap = 'Pastel1')

모든 3개 주성분을 3차원으로 본다. 2D보다 더 많은 정보를 담을 수 있다. 별 모양 마커를 사용해서 보기 좋게 표현했다.

 

레이더 차트 (가장 인상적)

레이더 차트는 각 클러스터의 특성을 한눈에 비교할 수 있다.

각 축이 하나의 컬럼을 나타내고, 클러스터별로 다르게 칠해진 영역이 나타난다.

 
angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
angles += angles[:1]

360도를 균등하게 나눈다. num_vars가 5이면 72도씩 간격을 둔다.

실제로 레이더 차트를 보니 각 클러스터의 특징이 명확했다:

  • Cluster 0: 이 영역이 크다
  • Cluster 1: 저 영역이 크다
  • ...

이것이 바로 "인사이트"다. 각 클러스터가 어떤 특징을 가지고 있는지 한눈에 알 수 있다.

 

 

하루를 마무리하며....

 

"아, 이게 데이터분석이구나"

어제까지는 개념만 배웠는데, 오늘 직접 코드를 짜면서 느꼈다. 클러스터링은:

  1. 데이터를 준비하고
  2. 여러 기법으로 최적값을 찾아서
  3. 알고리즘을 실행하고
  4. 결과를 시각화해서
  5. 비즈니스 인사이트를 도출하는

전체 과정이다.

기술은 도구일 뿐이고, 진짜 중요한 건 "이 결과가 의미 있는가?"를 판단하는 것이다.

놀랐던 건 코드가 생각보다 간단하다는 것이다.

특히 PCA, K-Means, 시각화까지 한 파일에서 모두 처리할 수 있다는 게 신기했다.

 

레이더 차트를 봤을 때 깨달았다. 숫자만 봐서는 알 수 없는 패턴이 한눈에 보인다.

  • 2D 산점도: 클러스터가 잘 분리되었는지 확인
  • 3D 산점도: 더 많은 정보를 담음
  • 레이더 차트: 각 클러스터의 특성 비교

코드를 보면서 각 파라미터의 의미를 생각해봤다:

  • n_components=3: 몇 개의 주성분을 만들 것인가? (차원 축소 정도)
  • n_clusters=5: 몇 개의 클러스터로 나눌 것인가?
  • random_state=42: 재현성을 위한 랜덤 시드
  • init='random': 초기 중심점을 어떻게 설정할 것인가?

모든 게 선택이고, 이 선택들이 결과에 영향을 미친다.

 

오늘 새롭게 알게된 사실은 "정답이 없는 데이터에서 정답을 찾아내는" 그것이 데이터분석가의 일이다.