본문 바로가기
Python/Machine Learning

챕터 2 과제정리 2

by 좌우지간에 2024. 12. 31.

쇼핑몰 고객 데이터 분석 및 클러스터링 프로젝트 학습 정리

이번 쇼핑몰 고객 데이터 분석 및 클러스터링 프로젝트를 진행하면서 제가 학습하고 경험한 내용을 구체적인 코드 기반으로 정리해 보았습니다. 단순한 과정 나열이 아닌, 코드를 작성하면서 얻은 인사이트와 함께 학습 내용을 담았습니다.



1. 데이터 전처리 및 탐색

  • pandas를 활용한 데이터 로딩 및 정리: pd.read_csv('Mall_Customers.csv')를 통해 데이터를 로드하고, df.drop()으로 불필요한 컬럼을 제거했습니다. df.info()df.describe()로 데이터의 전반적인 정보를 확인하며, 수치형 데이터와 범주형 데이터의 특성을 파악했습니다.
    df = pd.read_csv('Mall_Customers.csv')
    df = df.drop(columns=['CustomerID'])
    print(df.info())
    print(df.describe())

  • 원-핫 인코딩: pd.get_dummies(df, columns=['Gender'], drop_first=True)를 사용하여 범주형 데이터인 'Gender' 컬럼을 원-핫 인코딩했습니다. drop_first=True 옵션을 통해 다중공선성 문제를 방지할 수 있다는 점을 이해했습니다. 또한, 비지도 학습에서는 범주형 변수를 원-핫 인코딩할 경우 거리 계산이 왜곡될 수 있어 수치형 변수만 사용해야 한다는 점을 배웠습니다.
    df = pd.get_dummies(df, columns=['Gender'], drop_first=True)
    df = df.drop(columns=['Gender_Male']) # 비지도 학습을 위해 제거

  • matplotlib, seaborn을 이용한 시각화: 히스토그램 (sns.histplot())과 박스플롯 (sns.boxplot())을 통해 데이터의 분포와 이상치를 확인했습니다. 이를 통해 각 변수의 특성을 파악하고, 이상치 처리가 필요할 수 있음을 인지했습니다.

    plt.figure(figsize=(20, 15))
    plotnumber = 1
    for column in df.columns:
        ax = plt.subplot(3, 5, plotnumber)
        sns.histplot(df[column], kde=True, ax=ax)
        plotnumber += 1
    plt.show()
    
    plt.figure(figsize=(20, 15))
    plotnumber = 1
    for column in df.columns:
        ax = plt.subplot(3, 5, plotnumber)
        sns.boxplot(y=df[column], ax=ax)
        plotnumber += 1
    plt.show()

* **`sklearn.preprocessing`을 이용한 스케일링**: `StandardScaler`를 사용하여 데이터를 스케일링했습니다. 클러스터링 알고리즘이 거리 기반으로 작동하기 때문에 스케일링이 필요하다는 점을 이해했습니다. ```python scaler = StandardScaler() scaled_data = scaler.fit_transform(df) scaled_df = pd.DataFrame(scaled_data, columns=df.columns) ```

### 2. 비지도 학습 (클러스터링)
  • K-means:

    • 엘보우 방법 (inertia_)을 통해 최적의 클러스터 수를 찾고, 실루엣 점수 (silhouette_score())를 통해 클러스터링 결과를 평가했습니다.

      inertia = []
      for i in range(1, 11):
          kmeans = KMeans(n_clusters=i, init='k-means++', max_iter=300, n_init=10, random_state=0)
          kmeans.fit(scaled_df)
          inertia.append(kmeans.inertia_)
      plt.plot(range(1, 11), inertia)
      plt.show()
      
      silhouette_scores = []
      for n_cluster in range(2, 11):
          kmeans = KMeans(n_clusters=n_cluster, init='k-means++', max_iter=300, n_init=10, random_state=0)
          kmeans_labels = kmeans.fit_predict(scaled_df)
          silhouette_avg = silhouette_score(scaled_df, kmeans_labels)
          silhouette_scores.append(silhouette_avg)
      plt.plot(range(2, 11), silhouette_scores)
      plt.show()
    • KMeans 모델을 학습하고, fit_predict() 메서드를 통해 각 데이터에 클러스터 라벨을 할당했습니다.

      kmeans = KMeans(n_clusters=5, init='k-means++', max_iter=300, n_init=10, random_state=0)
      kmeans_labels = kmeans.fit_predict(scaled_df)
      df['KMeans_Cluster'] = kmeans_labels

  • 계층적 군집화:

    • scipy.cluster.hierarchylinkage() 함수와 dendrogram() 함수를 사용하여 덴드로그램을 시각화했습니다. 이를 통해 클러스터 구조를 파악하고 적절한 클러스터 수를 선택하는 데 도움을 받았습니다.
    • sklearn.clusterAgglomerativeClustering 모델을 사용하여 클러스터링을 수행하고, 결과를 저장했습니다.
      plt.figure(figsize=(10, 7))
      dend = dendrogram(linkage(scaled_df, method='ward'))
      plt.show()
      

    agg_cluster = AgglomerativeClustering(n_clusters=3, linkage='ward')
    agg_labels = agg_cluster.fit_predict(scaled_df)
    df['Agg_Cluster'] = agg_labels
    ```


  • DBSCAN: DBSCAN 모델을 학습하고, 클러스터 라벨을 저장했습니다. DBSCAN은 노이즈 데이터에 대해 -1 라벨을 할당한다는 점을 인지했습니다.

    dbscan = DBSCAN(eps=0.5, min_samples=5)
    dbscan_labels = dbscan.fit_predict(scaled_df)
    df['DBSCAN_Cluster'] = dbscan_labels

  • GMM: GaussianMixture 모델을 학습하고, 클러스터 라벨을 저장했습니다. GMM은 각 클러스터가 가우시안 분포를 따른다는 점을 가정한다는 것을 이해했습니다.

    gmm = GaussianMixture(n_components=3, random_state=0)
    gmm_labels = gmm.fit_predict(scaled_df)
    df['GMM_Cluster'] = gmm_labels

  • PCA를 통한 시각화: PCA를 사용하여 고차원 데이터를 2차원으로 차원 축소하고, 산점도 (sns.scatterplot())를 통해 클러스터링 결과를 시각화했습니다. 또한, 3차원 산점도를 통해 클러스터링 결과를 추가적으로 확인했습니다.

     pca = PCA(n_components=2)
     pca_result = pca.fit_transform(scaled_df)
     df['pca_x'] = pca_result[:, 0]
     df['pca_y'] = pca_result[:, 1]
    
     sns.scatterplot(x='pca_x', y='pca_y', hue='KMeans_Cluster', palette='viridis', data=df)
     plt.show()


### 3. 클러스터별 특징 분석
  • groupby()mean()을 이용하여 각 클러스터별 평균 특징을 분석했습니다. 이를 통해 각 클러스터에 속한 고객들의 특징을 파악하고, 클러스터별 의미를 부여할 수 있었습니다.
    kmeans_cluster_summary = df.groupby('KMeans_Cluster').mean()
    print(kmeans_cluster_summary)


### 4. 지도 학습 (분류)
  • 클러스터 라벨 (KMeans_Cluster)을 목표 변수로 사용하여 지도 학습 모델을 학습했습니다.

  • train_test_split() 함수를 사용하여 데이터를 훈련 세트와 테스트 세트로 나누었습니다.

  • 로지스틱 회귀: LogisticRegression 모델을 학습하고, 테스트 세트에서 성능을 평가했습니다. classification_report()accuracy_score() 함수를 사용하여 모델 성능을 측정했습니다.

    X = df.drop(columns=['KMeans_Cluster', 'Agg_Cluster', 'DBSCAN_Cluster', 'GMM_Cluster', 'pca_x', 'pca_y','pca_z'])
    y = df['KMeans_Cluster']
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
    
    logistic_model = LogisticRegression(random_state=42, solver='liblinear')
    logistic_model.fit(X_train, y_train)
    logistic_predictions = logistic_model.predict(X_test)
    print(classification_report(y_test, logistic_predictions))
    print(accuracy_score(y_test, logistic_predictions))
  • 랜덤 포레스트: RandomForestClassifier 모델을 학습하고, 테스트 세트에서 성능을 평가했습니다.

    rf_model = RandomForestClassifier(random_state=42)
    rf_model.fit(X_train, y_train)
    rf_predictions = rf_model.predict(X_test)
    print(classification_report(y_test, rf_predictions))
    print(accuracy_score(y_test, rf_predictions))