[머신러닝] 비지도학습 알고리즘

yeji·2024년 11월 21일
0

Python

목록 보기
25/36

군집화

K-Means Clustering

  • 순서 : K개 군집수 설정 -> 임의 중심 선정 -> 해당 중심점과 거리가 가까운 데이터 그룹화 -> 데이터 무게 중심으로 중심점 이동 -> 다시 거리가 가까운 데이터 그룹화(반복)
  • 일반적이고 적용하기 쉽지만 거리 기반으로 가까움을 측정하기 때문에 차원이 많을수록 정확도가 떨어짐
  • 반복 횟수가 많을수록 처리 시간이 느려짐
  • 몇개의 군집(K)을 선정할지 주관적이고, 평균을 이용하기에 이상치에 취약함
  • 라이브러리 : sklearn.cluster.KMeans
    • 함수 입력 값
      • n_cluster : 군집화 개수
      • max_iter : 최대 반복 횟수
    • 메소드
      • labels_ : 각 데이터 포인트가 속한 군집 중심점 레이블
      • cluster_centers : 각 군집 중심점의 좌표

평가지표

  • 비지도학습 특성상 답이 없어 평가가 쉽지 않지만, 군집화가 잘되어 있다는 것은 다른 군집간의 거리는 떨어져 있고 동일한 군집끼리는 가까이 있다는 것을 의미함
  • 실루엣 분석 : 각 군집간의 거리가 얼마나 효율적으로 분리되어 있는지 측정
    • 1로 갈수록 잘 군집화 되어 있고 -1에 가까울수록 잘못 군집화 되어 있음
  • 실루엣 값이 높고 개별 군집의 평균 값의 편차가 크지 않아야 좋은 군집화
  • 라이브러리 : 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_df2 = iris_df[['sepal_length','sepal_width','petal_length','petal_width']]

# KMean
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters = 3, init = 'k-means++', max_iter = 300, random_state= 42)
kmeans.fit(iris_df2)

# 답과 비교를 위해 분석 결과 컬럼으로 추가
iris_df2['target'] = iris_df['species']
iris_df2['cluster'] = kmeans.labels_

# 시각화를 통해 정답과 비교
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()

RFM

  • 다양한 기준으로 고객을 분류하는 기법
  • Recency : 가장 최근 구입일에서 오늘까지의 시간
  • Frequency : 상품 구매 횟수
  • Monetary value : 총 구매 금액
# 라이브러리
!pip install openpyxl

# 데이터 가져오기
retail_df = pd.read_excel('/Users/t2023-m0092/Desktop/J/Python/강의/강의_머신러닝/실습코드/Online Retail.xlsx')
retail_df.head(3)
retail_df.info()
retail_df.isnull().sum()

# 데이터 EDA
retail_df.info()
retail_df.isnull().sum()
retail_df.describe(include = 'all')

# 데이터 전처리 - customerID 결측치 삭제
cond_cust = (retail_df['CustomerID'].notnull())
retail_df[cond_cust].isnull().sum()

# 데이터 전처리 - invoice가 C로 시작하는 것 삭제
cond_invo = (retail_df['InvoiceNo'].astype(str).str[0] != 'C')
retail_df[cond_invo].head(3)

# 데이터 전처리 - quantity, unitprice가 음수인 것 삭제
cond_minus = (retail_df['Quantity'] >0 ) & (retail_df['UnitPrice'] >0)
retail_df[cond_minus].head(3)

# 데이터 전처리 적용
retail_df_2 = retail_df[cond_cust & cond_invo & cond_minus]
retail_df_2.info()

# 데이터 전처리 - country 영국만 선택
cond_uk = (retail_df_2['Country'] =='United Kingdom')
retail_df_2 = retail_df_2[cond_uk]

# 데이터 전처리 - 수량&가격 곱해서 총 구매금액 컬럼 추가
retail_df_2['Amt'] = retail_df_2['Quantity'] * retail_df_2['UnitPrice']
retail_df_2['Amt'] = retail_df_2['Amt'].astype('int')

# 데이터 전처리 - customerid 중복 제거
retail_df_2[['CustomerID']].drop_duplicates()

# 데이터 전처리 - 전체 데이터 중 가장 최근 날짜 기준으로 구매 날짜 빼고 +1
# 추후 CustomerID 기준으로 Priod의 최소의 Priod를 구하면 그것이 Recency

retail_df_2['Period'] = (dt.datetime(2011,12,10) - retail_df_2['InvoiceDate']).apply(lambda x: x.days+1)

# 피벗 보기
rfm_df = retail_df_2.groupby('CustomerID').agg({
    'Period' : 'min',
    'InvoiceNo' : 'count',
    'Amt' : 'sum'
})

# 컬럼명 변경
rfm_df.columns = ['Recency','Frequency','Monetary']

# 데이터 정규화
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_features = sc.fit_transform(rfm_df[['Recency','Frequency','Monetary']])

# 평가
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)

# 군집 확인
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)
profile
👋🏻

0개의 댓글