聚類分析

  聚類常用於數據探索或挖掘前期,在沒有做先驗經驗的背景下做的探索性分析,也適用於樣本量較大情況下的數據預處理工作。例如針對企業整體的用戶特徵,在未得到相關只是或經驗之前先根據數據本身特點進行用戶分羣,然後針對不同羣體做進一步分析;例如對連續數據做離散化,便於後續做分類分析應用。

  常用的聚類算法分爲基於劃分,層次,密度,網格,統計學,模型等類型的算法,典型算法包括K均值(經典的聚類算法),DBSCAN,兩步聚類,BIRCH,譜聚類等。

  聚類分析能解決的問題包括:數據集可以分位幾類,每個類別有多少樣本量,不同類別中各個變量的強弱關係如何,不同類別的典型特徵是什麼等;除了劃分類別外,聚類還能用於基於類別劃分的其他應用,例如圖片壓縮等。但是,聚類無法提供明確的行動指向,聚類結果更多是爲後期挖掘和分析工作提供預處理和參考,無法回答“爲什麼”和“怎麼辦”的問題。

數據異常對聚類結果的影響

  K均值(K-Means)是聚類中最常用的方法之一,它基於點與點距離的相似度來計算最佳類別歸屬,但K均值在應用之前一定要注意兩種數據異常:

  1. 數據的異常值。數據中的異常值能明顯改變不同點之間的距離相似度,並且這種影響是非常顯著的。因此基於距離相似度的判別模式下,異常值的處理必不可少。
  2. 數據的異常量綱。不同的維度和變量之間,如果存在數值規模或量綱的差異,那麼在做距離之前需要先將變量歸一化或標準化。例如跳出率的數值分佈區間是[0,1],訂單金額可能是[0,10 000 000],而訂單數量則是[0,1000],如果沒有歸一化或標準化操作,那麼相似度將主要受訂單金額的影響。

超大數據量時應該放棄K均值算法

  K均值在算法穩定性,效率和準確率(相對於真實標籤的判別)上表現非常好,並且在應對大量數據時依然如此。它的算法時間複雜度上界爲O(nkt),其中n是樣本量,k是劃分的聚類數,t是迭代次數。當聚類數和迭代次數不變時,K均值的算法消耗時間只跟樣本量有關,因此會呈線性增長趨勢。

應對高維數據的聚類

  在做高位數據聚類時,傳統的在低維空間通用的聚類方法運用到高維度空間時,通常不能取得令人滿意的聚類效果,這主要表現在聚類計算耗時太長,聚類結果相對於真實標籤分類的準確性和穩定性都大大降低。問什麼在高維空間下聚類會出現這種問題呢?

  • 在面對高維數據時,基於距離的相似度計算效率極低;
  • 高維空間的大量屬性特徵使得在所有維上存在簇的可能性非常低;
  • 由於稀疏性及近鄰特性,基於距離的相似度幾乎爲0,導致高維的空間中很難存在數據簇。

在應對高維數據的聚類主要有2種方法:降維,子空間聚類。

  • 降維是應對高維數據的有效辦法,通過特徵選擇法維度轉化法將高維空間降低或映射到低維空間,直接解決了高維問題。
  • 子空間聚類算法是在高維數據空間中對傳統聚類算法的一種擴展,其思路是選取與給定簇密切相關的維,然後在對應的子空間進行聚類。比如譜聚類就是一種子空間聚類方法。由於選擇相關維的方法以及評估子空間的方法需要自定義,因此這種方法對操作者的要求較高。

如何選擇聚類分析算法

聚類算法有幾十種之多,聚類算法的選擇,主要參考以下因素:

  • 如果數據集是高維度的,那麼選擇譜聚類,它是子空間劃分的一種。
  • 如果數據量爲中小規模,例如在100W條以內,那麼K均值將是比較好的選擇;如果數據量超過100W條,那麼可以考慮使用Mini Batch KMeans。
  • 如果數據集中有噪點(離羣點),那麼使用基於密度DBSCAN可以有效應對這個問題。
  • 如果追求更高的分類準確度,那麼選擇譜聚類將比K均值準確度更好。

Python 聚類分析

import numpy as np 
import matplotlib.pyplot as plt


# 數據準備
raw_data = np.loadtxt('/Users/nxcjh/learn/python-yunying/python_book/chapter4/cluster.txt') # 導入數據文件
X = raw_data[:, :-1] # 分割要聚類的數據
y_true = raw_data[:, -1] 

print(X)

[[ 0.58057881  0.43199283]
 [ 1.70562094  1.16006288]
 [ 0.8016818  -0.51336891]
 ...
 [-0.75715533 -1.41926816]
 [-0.34736103 -0.84889633]
 [ 0.61103884 -0.46151157]]

訓練聚類模型

訓練聚類模型。先設置聚類數量爲3,並建立聚類模型對象,然後通過fit方法訓練模型,通過predict方法做聚類應用得到原始訓練集的聚類標籤集y_pre(也可以在應用fit方法後直接從聚類對象的labels_屬性獲得訓練集的聚類標籤);從得到的聚類模型中,通過其cluster_centers_ 屬性和inertia_屬性得到各類別中心以及樣本距離最近的聚類中心的總和。

from sklearn.cluster import KMeans # 導入Sklearn聚類模塊

n_clusters = 3 # 設置聚類數量
model_kmeans = KMeans(n_clusters=n_clusters, random_state=0) # 建立聚類模型對象

知識點:將算法保存到硬盤

Python 內置標準庫cPickle是實現這一過程的有效方法庫。cPickle可以將任意一種類型的Python將對象進行序列化/持久化操作,算法模型對象也不例外。cPickle的主要應用方法是dump和load。

  • dump: 將Python對象序列化保存到本地的文件
  • load: 從本地文件讀取Python對象並恢復實例對象

注意:在python3中使用pickle,python2中使用cPickle

import pickle
pickle.dump(model_kmeans, open("my_model_object.pkl","wb"))
model_kmeans2 = pickle.load(open("my_model_object.pkl","rb"))

model_kmeans2.fit(X) # 訓練聚類模型
y_pre = model_kmeans2.predict(X) # 預測聚類模型
print(y_pre)
[1 1 2 0 2 0 1 1 0 0 0 1 2 1 2 1 0 2 2 2 2 2 1 2 1 0 0 1 1 0 0 2 2 2 0 0 2
 0 1 2 2 2 1 1 2 2 2 1 1 0 0 1 1 1 0 2 0 2 1 0 1 0 1 1 0 2 2 2 1 1 1 0 1 1
 0 1 1 2 1 1 1 0 2 1 2 0 0 1 0 1 2 0 0 1 1 1 2 0 0 1 2 1 1 0 2 1 0 2 1 1 2
 1 2 1 2 2 0 0 1 1 2 2 1 1 0 1 1 1 2 1 1 0 2 2 1 2 0 1 2 1 0 2 2 1 2 2 2 1
 2 1 1 0 1 1 0 0 2 1 1 1 1 1 2 2 1 1 0 0 1 0 2 2 1 2 0 1 0 1 1 1 0 0 0 2 0
 1 0 0 2 0 1 2 0 1 0 0 0 1 2 0 2 1 2 0 2 1 1 2 1 1 1 1 1 1 2 2 0 2 0 1 0 1
 1 1 2 2 2 0 1 2 0 0 2 2 1 0 2 2 1 1 2 2 1 2 2 0 2 2 2 1 0 1 2 2 2 1 2 0 0
 1 2 2 2 0 1 2 2 2 2 2 0 0 1 0 0 1 1 0 0 1 2 0 2 0 1 2 2 0 0 1 1 0 1 2 2 0
 0 2 1 1 0 1 1 1 2 1 2 1 2 0 2 0 1 0 1 0 0 1 2 0 2 2 1 0 0 0 2 0 1 0 1 0 1
 2 1 2 2 0 0 1 0 1 2 2 1 2 0 2 2 1 1 1 1 2 2 2 2 2 2 1 2 1 0 2 2 0 1 2 0 2
 1 2 2 1 2 2 2 2 2 2 0 2 0 0 2 0 1 2 2 2 0 2 0 0 1 2 1 0 0 1 2 0 2 1 1 0 1
 0 0 0 0 0 2 1 2 0 1 1 0 2 2 2 1 2 1 2 2 0 2 2 2 0 1 0 1 1 1 0 0 1 0 0 2 0
 1 0 1 1 1 2 0 2 2 2 0 1 0 1 1 1 1 1 1 0 1 2 1 1 1 2 2 2 2 2 2 0 0 2 0 0 1
 0 1 2 1 0 0 0 2 1 2 1 2 2 0 0 0 0 1 1 1 0 2 0 0 1 0 2 0 2 0 1 1 2 1 1 2 0
 1 0 1 0 0 0 0 0 2 2 0 1 2 0 0 1 1 1 0 1 2 2 0 1 2 1 2 2 2 1 2 0 1 1 1 2 0
 0 1 1 0 2 0 2 2 2 1 0 2 0 0 0 1 0 1 1 0 2 2 0 1 1 1 2 2 1 2 1 2 1 0 0 2 0
 2 2 0 0 1 0 1 2 2 1 0 1 2 2 1 0 0 0 1 1 1 0 2 2 0 2 2 2 0 1 2 2 2 0 2 1 1
 0 0 0 0 0 0 1 2 1 1 1 2 2 2 1 0 1 2 2 1 0 2 1 2 2 0 1 0 1 0 0 2 1 2 0 0 1
 0 2 0 2 1 0 2 1 1 1 0 0 1 2 2 1 2 2 0 0 1 1 0 2 0 1 1 2 0 2 1 0 0 2 2 1 1
 1 0 0 2 1 0 1 2 0 0 2 0 2 0 1 2 1 0 0 1 1 2 1 1 1 0 0 1 2 2 0 0 2 0 2 0 1
 1 0 0 0 1 0 0 0 1 0 1 2 2 0 0 2 2 1 0 0 0 2 1 0 1 0 1 2 2 0 0 1 2 2 1 0 2
 2 1 0 2 1 2 2 1 2 1 2 2 0 0 0 0 2 2 1 1 2 1 1 1 0 1 0 2 1 0 2 1 2 1 2 0 2
 0 1 0 1 1 1 0 2 2 0 0 1 0 0 0 0 0 0 0 2 0 2 0 2 2 0 1 0 2 1 2 1 2 1 2 0 2
 1 2 1 2 2 2 0 2 0 0 0 0 2 0 0 1 1 0 0 2 1 1 0 2 0 1 2 0 2 2 1 1 1 1 0 2 1
 1 0 0 1 0 2 2 1 2 1 0 2 0 1 1 2 0 1 2 0 1 0 1 1 1 1 0 1 2 0 1 0 2 0 0 0 0
 0 1 1 2 0 0 0 1 2 0 1 2 2 2 0 1 0 2 2 2 2 1 2 0 1 2 0 0 0 0 0 0 1 0 0 0 0
 2 0 2 2 2 2 2 2 0 2 1 0 0 2 2 2 2 0 2 0 2 0 2 1 1 2 1 2 1 1 1 2 2 0 0 0 0
 2]

模型效果指標評估

from sklearn import metrics # 導入sklearn效果評估模塊

n_samples, n_features = X.shape # 總樣本量,總特徵數
print ('samples: %d \t features: %d' % (n_samples, n_features))  # 打印輸出樣本量和特徵數量

samples: 1000 	 features: 2

評估指標1: inertias

inertias是K均值模型對象的屬性,表示樣本距離最近的聚類中心的總和,它是作爲在沒有真實分類結果標籤下的非監督式評估指標。該值越小越好,值越小證明樣本在類間的分佈越集中,即類內的距離越小。

inertias = model_kmeans.inertia_  # 樣本距離最近的聚類中心的總和
print(inertias)
300.1262936093466

評估指標2: adjusted_rand_s:,調整後的蘭德指數(Adjusted Rand Index)

蘭德指數通過考慮在預測和真實聚類中在相同或不同聚類中分配的所有樣本對和計數對來計算兩個聚類之間的相似性度量。調整後的蘭德指數通過對蘭德指數的調整得到獨立於樣本量和類別的接近於0的值,其取值範圍爲[-1,1],負數代表結果不好,越接近於1越好,意味着聚類結果與真實情況越吻合。

adjusted_rand_s = metrics.adjusted_rand_score(y_true, y_pre)  # 調整後的蘭德指數
print(adjusted_rand_s)
0.9642890803276076

評估指標3: mutual_info_s,互信息(Mutual Information, MI)

互信息是一個隨機變量中包含的關於另一個隨機變量的信息量,在這裏指的是相同數據的兩個標籤之間的相似度的量度,結果是非負值。

mutual_info_s = metrics.mutual_info_score(y_true, y_pre)  # 互信息
print(mutual_info_s)
1.0310595406681184

評估指標4: adjusted_mutual_info_s,調整後的互信息(Adjusted Mutual Information, AMI)

調整後的互信息是對互信息評分的調整得分。它考慮到對於具有更大數量的聚類羣,通常MI較高,而不管實際上是否有更多的信息共享,它通過調整聚類羣的概率來糾正這種影響。當兩個聚類集相同(即完全匹配)時,AMI返回值爲1;隨機分區(獨立標籤)平均預期AMI約爲0,也可能爲負數。

adjusted_mutual_info_s = metrics.adjusted_mutual_info_score(y_true, y_pre)  # 調整後的互信息
print(adjusted_mutual_info_s)
0.938399249349474


/anaconda3/lib/python3.6/site-packages/sklearn/metrics/cluster/supervised.py:732: FutureWarning: The behavior of AMI will change in version 0.22. To match the behavior of 'v_measure_score', AMI will use average_method='arithmetic' by default.
  FutureWarning)

評估指標5: homogeneity_s,同質化得分(Homogeneity)

如果所有的聚類都只包含屬於單個類的成員的數據點,則聚類結果將滿足同質性。其取值範圍[0,1]值越大意味着聚類結果與真實情況越吻合。

homogeneity_s = metrics.homogeneity_score(y_true, y_pre)  # 同質化得分
print(homogeneity_s)
0.9385116928897981

評估指標6: comleteness_s,完整性得分(Completeness)

如果作爲給定類的成員的所有數據點是相同集羣的元素,則聚類結果滿足完整性。其取值範圍[0,1]值越大意味着聚類結果與真實情況越吻合。

completeness_s = metrics.completeness_score(y_true, y_pre)  # 完整性得分
print(completeness_s)
0.9385372785555511

評估指標7: v_measure_s,V-measure得分

它是同質化和完整性之間的諧波平均值,v=2*(均勻性 * 完整性)/(均勻性 + 完整性)。其取值範圍[0,1],值越大意味着聚類結果與真實情況越吻合。

v_measure_s = metrics.v_measure_score(y_true, y_pre)  # V-measure得分
print(v_measure_s)
0.938524485548298

評估指標8: silhouette_s,輪廓係數(Silhouette)

它用來計算所有樣本的平均輪廓係數,使用平均羣內距離和每個樣本的平均最近簇羣距離來計算,它是一種非監督式評估指標。其最高值爲1,最差值爲-1,0附近的值表示重疊的聚類,負值通常表示已被分配到錯誤的集羣。

silhouette_s = metrics.silhouette_score(X, y_pre, metric='euclidean')  # 平均輪廓係數
print(silhouette_s)
0.6342086134083013

評估指標9: calinski_harabaz_s,Calinski和Harabaz得分

該分數定義爲羣內離散與簇間離散的比值,它是一種非監督式評估指標。

calinski_harabaz_s = metrics.calinski_harabaz_score(X, y_pre)  # Calinski和Harabaz得分
print(calinski_harabaz_s)
2860.8215946947635

模型效果可視化

centers= model_kmeans.cluster_centers_ # 各類別中心
colors = ['#4EACC5', '#FF9C34', '#4E9A06']  # 設置不同類別的顏色
plt.figure() # 建立畫布
for i in range(n_clusters):  # 循環讀類別
    index_sets = np.where(y_pre == i)  # 找到相同類的索引集合
    cluster = X[index_sets]  # 將相同類的數據劃分爲一個聚類子集
    plt.scatter(cluster[:, 0], cluster[:, 1], c=colors[i], marker='.')  # 展示聚類子集內的樣本點
    plt.plot(centers[i][0], centers[i][1], 'o', markerfacecolor=colors[i], markeredgecolor='k',
             markersize=6)  # 展示各聚類子集的中心
plt.show() # 展示圖像

    

在這裏插入圖片描述

模型應用

new_X = [[1,3.6]]
cluster_label = model_kmeans.predict(new_X)
print('cluster of new data point is:  %d' % cluster_label)
cluster of new data point is:  1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章