【Python機器學習實戰】無監督學習之PCA和K-Means二連擊

簡介

無監督學習着重於發現數據本身的分佈特點。與監督學習不同,無監督學習不需要對數據進行標記。

從功能上來看,無監督學習模型可以用於發現數據的“羣落”(聚類),同時也可以尋找“離羣”的樣本,另外,對於特徵維度非常高的數據樣本,我們同樣可以通過無監督的學習對數據進行降維(PCA),保留最具有區分性的低維度特徵。這些都是在海量數據處理中非常實用的技術。

K均值(K-means)算法

K均值算法是數據聚類中最經典,也相對容易理解的模型。算法執行可以分層一下四個階段:

  • 隨機佈設K個特徵空間內的點作爲初始的聚類中心;
  • 對每個數據的特徵向量,從K個聚類中心中選擇距離最近的一個,並把改數據標記爲從屬於這個聚類中心;
  • 在所有的數據都被標記過聚類中心後,根據這些數據被分配的類簇,重新對K個聚類中心做計算;
  • 如果一輪下來,所有的數據點從屬的聚類中心與上一次的分配的類簇沒有變化,那麼迭代就可以停止,否則回到第二步繼續循環。

主成分分析PCA

使用PCA進行降維的目的有兩個:

  • 在實際項目中經常會有特徵維度非常之高的訓練樣本,而往往又無法藉助自己的領域知識人工地構建有效特徵;
  • 在數據表現方面,我們無法用肉眼觀測超過三個維度的特徵,因此數據降維爲數據的可視化提供了可能性。

問題引出

本文將繼續使用對手寫數字進行分類的數據,關於數據的相關內容可以參考我的另外一篇博客:sklearn實例-用支持向量機分類器(SVC)識別手寫字體

代碼實例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import adjusted_rand_score, classification_report
from sklearn.decomposition import PCA
from sklearn.svm import LinearSVC

digits_train = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/'
                           'optdigits/optdigits.tra', header=None)
digits_test = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/'
                           'optdigits/optdigits.tes', header=None)

X_train = digits_train[np.arange(64)]
y_train = digits_train[64]
X_test = digits_test[np.arange(64)]
y_test = digits_test[64]

#------------------直接用K均值進行聚類--------------------
kmeans = KMeans(n_clusters=10)
kmeans.fit(X_train, y_train)
y_pred = kmeans.predict(X_test)
print('使用ARI指標計算評估聚類性能:', adjusted_rand_score(y_test, y_pred)) #與Accuracy類似


#------------------使用PCA壓縮數據至二維並可視化--------------------
#初始化PCA,並將64維的數據壓縮至2維
estimator = PCA(n_components=2)
X_pca = estimator.fit_transform(X_train)

#定義一個能夠將二維分類結果可視化的函數
def plot_pca_scatter():
    colors = ['black', 'blue', 'purple', 'yellow', 'white', 'red', 'lime', 'cyan', 'orange', 'gray']
    for i in  range(len(colors)):
        px = X_pca[:, 0][y_train.values == i]
        py = X_pca[:, 1][y_train.values == i]
        plt.scatter(px, py, color=colors[i])

    plt.legend(np.arange(10).astype(str))
    plt.xlabel('First Principle Component')
    plt.ylabel('Second Priciple Component')
    plt.show()

#調用該函數並將結果可視化
plot_pca_scatter()

#------------------PCA+線性SVC與SVC對比--------------------
#導入基於線性核函數的支持向量機分類器,並進行擬合
svc = LinearSVC()
svc.fit(X_train, y_train)
y_pred = svc.predict(X_test)

#用PCA將64維數據壓縮至20維
estimator_new = PCA(n_components=20)
pca_X_train = estimator_new.fit_transform(X_train)
pca_X_test = estimator_new.fit_transform(X_test)

#再使用默認配置初始化LinearSVC,對壓縮過的20維數據進行建模並作出預測
pca_svc = LinearSVC()
pca_svc.fit(X_train, y_train)
y_pca_pred = pca_svc.predict(X_test)

#對比兩者的性能
print('The Accuracy of SVC:', svc.score(X_test, y_test))
print('The Accuracy of SVC after PCA:', pca_svc.score(X_test, y_test))

輸出結果:

使用ARI指標計算評估聚類性能: 0.6632289468987028

The Accuracy of SVC: 0.9187534780189204
The Accuracy of SVC after PCA: 0.9287701725097385

在這裏插入圖片描述

小結

對於聚類算法,評估其性能可以考慮以下兩種方式:①對於有標籤的數據集,可以和上述代碼一樣採用Adjusted Rand Index(ARI),ARI指標計算方式與計算準確性(Accuracy)類似;②如果用於評估的數據沒有所屬類別,那麼可以使用輪廓係數(Silhouette Coefficient)來度量聚類結果的質量,其取值爲[-1, 1],數值越大表示聚類效果越好。

  • K-Means所採用的迭代式算法簡單實用,但是缺陷在於容易收斂到局部最優解,還有必須預先設定簇的數量
  • 可以通過“肘部”觀察法用於粗略預估相對合理的類簇個數。因爲K-Means模型最終期望所有數據點到其所屬的類簇距離的平方和趨於穩定,因此可以繪製一條曲線,x軸爲k的大小,y軸爲所有數據到其所屬簇距離的平方和,然後找到肘部。
  • 對比PCA前後的SVC分類性能,可以發現兩者差別並不大,大概失去了2%左右的預測準確性,但是卻降低了68.75%的維度。
  • 經過大量實踐證明,相較於損失少部分模型性能,維度壓縮能節省大量用於模型訓練的時間,使得PCA帶來的模型綜合效率變得更爲划算。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章