1. Clusters
* 유사한 특성을 가진 개체들의 집합
* 고객 분류, 유전자 분석, 이미지 분할
- import
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn.datasets import make_blobs
|
- make_blobs 함수 : 가상 데이터를 생성
X, y = make_blobs(n_samples=100, centers=3, random_state=2024)
|
|
- x : 샘플 데이터의 좌표
X = pd.DataFrame(X)
X
|
- y: 각 데이터 포인트가 속하는 클러스터 레이블을 나타내는 1차원 배열
y
|
array([0, 2, 1, 0, 2, 0, 0, 1, 0, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 1, 0, 2, 2, 1, 2, 2, 1, 2, 2, 0, 2, 2, 1, 2, 1, 2, 1, 1, 1, 0, 0, 2, 1, 1, 0, 1, 1, 0, 0, 0, 2, 1, 2, 1, 0, 2, 0, 2, 1, 0, 2, 2, 2, 1, 0, 2, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 2, 1, 2, 1, 0, 1, 2, 1, 0, 0, 2, 2, 1, 1, 2, 1, 2, 1, 0, 1, 0, 1, 0]) |
⬛ KMeans 클러스터링을 하지 않은 경우 ( hue = y ) _ 실제값
- 2차원 데이터셋의 산점도를 그리기 ( random_state=2024 )
sns.scatterplot(x=X[0], y=X[1], hue=y)
|
hue = y:
|
|
- random_state=2024 -> random_state=2023 으로 변경하고 다시 생성
이 섞임이 적절하다고 판단해 2023으로 진행
sns.scatterplot(x=X[0], y=X[1], hue=y)
|
⬛ KMeans 클러스터링을 한 경우 ( hue = pred ) _ 예측값
- n_clusters = 3 인 경우
from sklearn.cluster import KMeans
km = KMeans(n_clusters=3)
km.fit(X)
pred=km.predict(X)
sns.scatterplot(x=X[0], y=X[1], hue=pred)
|
|
- n_clusters = 5 인 경우
from sklearn.cluster import KMeans
km = KMeans(n_clusters=5)
km.fit(X)
pred=km.predict(X)
sns.scatterplot(x=X[0], y=X[1], hue=pred)
|
- Inertia (관성): KMeans 알고리즘에서 관성은 각 데이터 포인트와 그것이 속한 클러스터 중심점 간의 거리 제곱합,
클러스터의 응집도를 측정하는 지표
# 평가값: 하나의 클러스터안에 중심점으로부터 각각의 데이터 거리를 합한 값의 평균
km.inertia_
|
161.15478072681793 |
값의 의미:
|
- 각 K에 대한 inertia 값을 계산하고 리스트에 저장 ( 클러스터 개수(K)
inertia 값의 변화, 적절한 클러스터 개수를 결정하는 데 도움을 줍니다.
inertia_list = []
for i in range(2, 11):
km = KMeans(n_clusters=i)
km.fit(X)
inertia_list.append(km.inertia_)
inertia_list
|
|
[1578.856698952461, 222.7636237762, 192.9939401435695, 161.0432695929017, 132.08269283797623, 110.36480652885867, 91.26636887566491, 81.14561909030127, 72.47155026760123] |
- 엘보우 메서드(Elbow Method)
K-Means 클러스터링에서 적절한 클러스터 개수(K)를 결정하는 시각적인 방법을 구현
클러스터 개수(K)에 따른 inertia 값의 변화를 시각적으로 확인
sns.lineplot(x=range(2, 11), y=inertia_list) # 엘보우 메서드
|
2. Marketing 데이터셋 살펴보기
- 데이터 가져오기
mkt_df = pd.read_csv('/content/drive/MyDrive/1. KDT/6. 머신러닝 딥러닝/데이터/marketing.csv')
mkt_df
|
- 정보보기
mkt_df.info()
|
* ID: 고객 아이디 * Year_Birth: 출생 연도 * Education: 학력 * Marital_Status: 결혼 여부 * Income: 소득 * Kidhome: 어린이 수 * Teenhome: 청소년 수 * Dt_Customer: 고객 등록일 * Recency: 마지막 구매일로부터 경과일 * MntWines: 와인 구매액 * MntFruits: 과일 구매액 * MntMeatProducts: 육류 구매액 * MntFishProducts: 어류 구매액 * MntSweetProducts: 단맛 제품 구매액 * MntGoldProds: 골드 제품 구매액 * NumDealsPurchases: 할인 행사 구매 수 * NumWebPurchases: 웹에서 구매 수 * NumCatalogPurchases: 카탈로그에서 구매 수 * NumStorePurchases: 매장에서의 구매 수 * NumWebVisitsMonth: 월별 웹 방문 수 * Complain: 불만 여부 |
- 필요없는 행 삭제
mkt_df.drop('ID', axis=1, inplace=True)
mkt_df.describe()
|
- [ Year_Birth ] 열을 기준으로 오름차순으로 정렬
mkt_df.sort_values('Year_Birth')
|
- [ Income ] 열을 기준으로 내림차순으로 정렬
mkt_df.sort_values('Income', ascending=False)
|
- [ Income ] 열의 값이 666666인 행을 제거한 후 결과를 mkt_df에 다시 저장
# mkt_df = mkt_df[mkt_df['income'] < 200000] NaN이 저장되지 않음
mkt_df = mkt_df[mkt_df['Income'] != 666666]
mkt_df.sort_values('Income', ascending=False)
|
- NaN 값 확인
mkt_df.isna().mean()
|
- 결측값(NA, NaN)을 제거
mkt_df = mkt_df.dropna()
mkt_df.isna().mean()
|
- [ DT_Customer ] 고객 등록일이 object 타입
mkt_df.info()
|
- [ Dt_Customer ] 고객등록일을 datetime 타입으로 변환
mkt_df['Dt_Customer'] = pd.to_datetime(mkt_df['Dt_Customer'], format='%d-%m-%Y')
mkt_df.info()
|
- 마지막으로 가입한 사람을 기준으로 가입 날짜(달)를 구하는 작업
# 마지막으로 가입된 사람을 기준으로 가입 날짜(달) 구하기
mkt_df['pass_month'] = (mkt_df['Dt_Customer'].max().year * 12 + mkt_df['Dt_Customer'].max().month) - (mkt_df['Dt_Customer'].dt.year * 12 + mkt_df['Dt_Customer'].dt.month)
mkt_df.head()
|
|
|
- [ Dt_Customer ] 고객등록일 삭제
mkt_df.drop('Dt_Customer', axis=1, inplace=True)
mkt_df.head()
|
- 충성고객 알아보기
여러 열의 값을 합산하여 [ Total_mnt ] 를 생성
# mkt_df['Total_mnt'] = 와인, 과일, 육류, 어류, 단맛, 골드 합하기
mkt_df['Total_mnt'] = mkt_df[['MntWines', 'MntFruits', 'MntMeatProducts', 'MntFishProducts', 'MntSweetProducts', 'MntGoldProds']].sum(axis=1)
mkt_df.head()
|
- [ Children ] 파생변수 생성 = [ Kidhome ] + [ Teenhome ]
- [ Kidhome ] + [ Teenhome ] 행 삭제
mkt_df.info()
mkt_df['Children'] = mkt_df[['Kidhome', 'Teenhome']].sum(axis=1)
mkt_df['Children'] = mkt_df[['Kidhome', 'Teenhome']].sum(axis=1)
mkt_df.head()
mkt_df.drop(['Kidhome', 'Teenhome'],axis=1,inplace=True)
|
- [ Education ] 고유값 확인
mkt_df['Education'].value_counts() |
- [ Marital_Status ] 결혼여부 값들의 빈도
mkt_df['Marital_Status'].value_counts()
|
- [ Marital_Status ] 결혼여부의 특정 값들을 다른 값으로 치환, 각 값들의 빈도 확인
mkt_df['Marital_Status'] = mkt_df['Marital_Status'].replace({ 'Married':'Partner',
'Together':'Partner',
'Single':'Single',
'Divorced':'Single',
'Widow':'Single',
'Alone':'Single',
'Absurd':'Single',
'YOLO':'Single'})
mkt_df['Marital_Status'].value_counts()
|
- [ Education ] , [ Marital_Status ] 문자형 데이터 (원핫인코딩 가능)
mkt_df.info()
|
- [ Education ] , [ Marital_Status ] 원핫인코딩
mkt_df = pd.get_dummies(mkt_df,columns=['Education','Marital_Status'])
mkt_df.head()
|
- 데이터를 표준화(Standardization)
StandardScaler는 데이터를 평균이 0이고 표준편차가 1인 데이터로 변환해주는 기능을 제공
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit_transform(mkt_df)
|
ss = StandardScaler()StandardScaler 클래스의 인스턴스를 생성하여 ss라는 변수에 할당이 인스턴스를 사용하여 데이터를 표준화할 준비 ss.fit_transform(mkt_df)StandardScaler 객체(ss)의 fit_transform 메서드를 호출하여 데이터를 표준화
|
- StandardScaler 객체(ss)를 사용하여 mkt_df 데이터프레임의 모든 열을 표준화
pd.DataFrame(ss.fit_transform(mkt_df))
|
|
|
- mkt_df 데이터프레임의 모든 열을 표준화, 그 결과를 새로운 데이터프레임으로 생성하여 ss_df에 저장
ss_df = pd.DataFrame(ss.fit_transform(mkt_df),columns=mkt_df.columns)
ss_df
|
3. KMeans
* k개의 중심점을 찍은 후에 중심점에서 각 접간의 거리의 합이 가장 최소가 되는 중심점 k의 위치를 찾고,
이 중심점에서 가까운 점들을 중심점으로 묶는 알고리즘
* k개의 클라스터의 수는 정해줘야 함
- 각 경우의 클러스터(2~10) 내 제곱합(inertia)을 계산
(데이터 포인트가 해당 클러스터의 중심에 얼마나 가까이 있는지)
inertia_list =[]
for i in range(2,11):
km = KMeans(n_clusters=i,random_state=10)
km.fit(ss_df)
inertia_list.append(km.inertia_)
|
- 각 클러스터 개수에 따른 제곱합(inertia)
inertia_list
|
[42895.856234544146, 39808.76012368429, 37612.35981391132, 36117.28280437582, 34082.90546728393, 32068.210471119026, 30933.637059149678, 29408.708100372387, 28483.55451230912] |
- 클러스터 개수 (2~10) 변화에 따른 클러스터 내 제곱합(inertia)의 변화
sns.lineplot(x=range(2, 11), y=inertia_list)
|
4. 실루엣 스코어
* 군집화의 품질을 평가하는 지표로,
각 데이터 포인트가 자신이 속한 군집과 얼마나 잘 맞는지, 그리고 다른 군집과 얼마나 잘 구분되는지를 측정
* -1 에서 +1 사이의 값을 가지며, 값이 크수록 군집화의 품질이 높음을 나타냄
- 각 클러스터 개수에 대해 K-means 클러스터링을 수행
클러스터링 결과의 실루엣 점수(silhouette score)를 계산
from sklearn.metrics import silhouette_score
score =[]
for i in range(2, 11):
km = KMeans(n_clusters=i, random_state=2024)
km.fit(ss_df)
pred = km.predict(ss_df)
score.append(silhouette_score(ss_df, pred))
|
from sklearn.metrics import silhouette_score
score = []
for i in range(2, 11):
km = KMeans(n_clusters=i, random_state=2024)
km.fit(ss_df)
pred = km.predict(ss_df)
score.append(silhouette_score(ss_df, pred))
|
- seaborn 라이브러리를 사용하여 클러스터링 성능 점수의 변화를 시각화
sns.lineplot(x=range(2,11),y=score)
|
* 처음으로 올라온 지점이 나누기 좋은 지점 |
- 4개의 클러스터로 나누기 위해 K-means 클러스터링 모델을 학습
km =KMeans(n_clusters=4,random_state=2024)
km.fit(ss_df)
|
- K-means 클러스터링 모델을 사용하여 표준화된 데이터 프레임 ss_df의 각 데이터 포인트가
어떤 클러스터에 속하는지 예측하고, 예측된 클러스터 레이블을 출력
pred=km.predict(ss_df)
pred
|
array([2, 1, 2, ..., 2, 3, 1], dtype=int32) ------------------------------------------------- 해당 데이터 포인트가 속하는 클러스터의 번호(0, 1, 2, 3 중 하나)를 의미 |
- [ label ] 열 생성한 후 pred 배열의 값을 할당
pred 배열: 각 데이터 포인트가 속하는 클러스터를 나타내는 레이블 배열
mkt_df['label']=pred
mkt_df
|
- 나눠진 고객정보 보기
mkt_df 데이터프레임의 [ label ] 열의 각 클러스터 레이블의 개수를 세어서 출력
mkt_df['label'].value_counts()
|
'AI > 머신러닝' 카테고리의 다른 글
14. 계층적 군집화(HC) | 고객층 분석 (0) | 2024.10.07 |
---|---|
13. 나이브 베이즈 분류기 모델 (0) | 2024.06.18 |
11. 다양한 모델 성능비교 | Air Quality UCI (0) | 2024.06.17 |
10. lightGBM | Credit (0) | 2024.06.13 |
09. 랜덤 포레스트 (Random Forest) | Hotel (0) | 2024.06.12 |