contents
summary
반면 비지도 학습이란 답(Y)을 알려주지 않고 데이터 간 유사성을 이용해서 답(Y)을 지정하는 방법.
머신러닝 개요
sklearn.cluster.KMeans
n_cluster
: 군집화 갯수max_iter
: 최대 반복 횟수labels_
: 각 데이터 포인트가 속한 군집 중심점 레이블cluster_centers
: 각 군집 중심점의 좌표*군집평가 지표
☑️ 실루엣 계수
:비지도 학습 특성 상 답이 없이 때문에 그 평가를 하긴 쉽지 않다. 다만, 군집화가 잘되어 있다는 것은 다른 군집간의 거리는 떨어져 있고 동일한 군집끼리는 가까이 있다는 것을 의미.
:이를 정량화 하기 위해 실루엣 분석(silhouette analysis)이란 간 군집 간의 거리가 얼마나 효율적으로 분리되어 있는지 측정.
sklearn.metrics.sihouette_score
: 전제 데이터의 실루엣 계수 평균 값 반환X
: 데이터 세트labels
: 레이블metrics
: 측정 기준 기본은 euclidean
➕실습
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
iris_df = sns.load_dataset('iris')
iris_df.head(3)
iris_df.info()
sns.scatterplot(data = iris_df, x = 'sepal_length', y = 'sepal_width')
sns.scatterplot(data = iris_df, x = 'sepal_length', y = 'sepal_width', hue = 'species')
iris_df2 = iris_df[['sepal_length','sepal_width','petal_length','petal_width']]
iris_df2.head(3)
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters = 3, init = 'k-means++', max_iter = 300, random_state= 42)
kmeans.fit(iris_df2)
kmeans.labels_
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2,
2, 2, 2, 0, 0, 2, 2, 2, 2, 0, 2, 0, 2, 0, 2, 2, 0, 0, 2, 2, 2, 2,
2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 0])
iris_df2['target'] = iris_df['species']
iris_df2['cluster'] = kmeans.labels_
iris_df2
plt.figure(figsize = (12,6))
plt.subplot(1,2,1)
sns.scatterplot(data = iris_df2, x = 'sepal_length', y = 'sepal_width', hue = 'target')
plt.title('Original')
plt.subplot(1,2,2)
sns.scatterplot(data = iris_df2, x = 'sepal_length', y = 'sepal_width', hue = 'cluster', palette= 'viridis')
plt.title('Clustering')
plt.show()
retail_df.head()
InvoiceNO
: 6자리의 주문번호(취소된 주문은 c 로 시작)StockCode
: 5자리의 제품 코드Description
: 제품 이름(설명)Quantity
: 주문 수량InvoiceDate
: 주문 일자, 날짜 자료형UnitPrice
: 제품 단가CustomerID
: 5자리의 고객 번호Country
: 국가명retail_df.describe(include = 'all')
cond1 = retail_df['Quantity']< 0
retail_df[cond1]
3) 데이터전처리
- customerID
결측치 삭제
- InvoiceNo
, UniPrice
, Quantity
데이터확인 및 삭제
- 영국데이터만 취함
데이터 전처리전략
# 조건1: customerID 결측치인것은 삭제
# 조건2: Invoice가 C로 시작하거나, quantity가 음수이거나, unitprice가 음수인것은 모두 삭제
cond_cust = (retail_df['CustomerID'].notnull())
retail_df[cond_cust].isnull().sum()
cond_invo = (retail_df['InvoiceNo'].astype(str).str[0] != 'C')
retail_df[cond_invo].head(3)
cond_minus = (retail_df['Quantity'] >0 ) & (retail_df['UnitPrice'] >0)
retail_df[cond_minus].head(3)
#영국인것만
cond_uk = (retail_df_2['Country'] =='United Kingdom')
retail_df_2 = retail_df_2[cond_uk]
retail_df_2
4) RFM 기반 데이터 가공
- 날짜 데이터 가공
- 최종목표
import datetime as dt
# 2011.12.10일 기준으로 각 날짜를 빼고 + 1
# 추후 CustomerID 기준으로 Priod의 최소의 Priod를 구하면 그것이 Recency
# 1번사람 100일전, 20일전, 5일전
retail_df_2['Period'] = (dt.datetime(2011,12,10) - retail_df_2['InvoiceDate']).apply(lambda x: x.days+1)
retail_df_2.head(3)
rfm_df = retail_df_2.groupby('CustomerID').agg({
'Period' : 'min',
'InvoiceNo' : 'count',
'Amt' : 'sum'
})
rfm_df
rfm_df.columns = ['Recency','Frequency','Monetary']
sns.histplot(rfm_df['Recency'])
StandardScaler
적용# 데이터정규화
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_features = sc.fit_transform(rfm_df[['Recency','Frequency','Monetary']])
5) 고객 세그멘테이션
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
kmeans = KMeans(n_clusters = 3, random_state = 42)
labels = kmeans.fit_predict(X_features)
rfm_df['label'] = labels
silhouette_score(X_features, labels)
0.592575402996014
from kmeans_visaul import visualize_silhouette
visualize_silhouette([2,3,4,5,6], X_features)
+추가 전처리
#log 스케일을 통한 추가전처리
import numpy as np
rfm_df['Recency_log'] = np.log1p(rfm_df['Recency'])
rfm_df['Frequency_log'] = np.log1p(rfm_df['Frequency'])
rfm_df['Monetary_log'] = np.log1p(rfm_df['Monetary'])
X_features2 = rfm_df[['Recency_log','Frequency_log','Monetary_log']]
sc2 = StandardScaler()
X_features2_sc = sc2.fit_transform(X_features2)
visualize_silhouette([2,3,4,5,6], X_features2_sc)
6) 평가
insight
0.592575402996014 실루엣 계수의 수치가 나쁘지 않지만 시각화를 확인해보는 것이 좋다.
군집이 5개이면, 가장 높은 실루엣 계수를 보이지만, 5개의 굽집이 제대로 보이지 않고 한쪽에 몰려있는 것을 확인할 수 있다.
그래서 추가적인 전처리를 해주고,
결과를 보면 다군집이 잘 보이게 된다. 하지만 실루엣 계수가 낮아진것을 확인할 수 있다.
각 데이터에 대해 실루엣 계수를 구한 후 평균을 내면 전체 데이터의 실루엣 스코어를 구할 수 있다. 일반적으로 이 값이 크면(1에 가까우면) 군집화가 어느정도 잘 되었다고 판단하는데, 단순히 값이 크다고 해서 군집화가 잘 됐다고 판단할 수는 없다.
전체 실루엣 스코어와 더불어 개별 군집의 평균값의 편차가 크지 않은 경우에만 전체 군집화 성능이 좋다고 판단할 가능성이 생긴다. 개별 군집의 실루엣 스코어가 전체 실루엣 스코어와 크게 다르지 않아야 된다는 뜻이다. 전체 실루엣 스코어가 클지라도 개별 군집의 실루엣 스코어가 들쭉날쭉하다면 군집화가 잘되었다고 할 수 없다는 의미.
군집마다의 실루엣 스코어를 구해보고, 시각화도 해보는 등 여러 검정을 거쳐야 군집화의 성능을 정확하게 판단할 수 있다!