前言:
聚類分析是一種非監督的機器學習算法,可以建立在無給定劃分類別的情況下,根據數據相似程度進行樣本分組的方法。它的入參是一組未被標記的樣本,根據樣本數據的距離或相似度劃分為若干組,劃分的原則是組內距離最小化,組外間距最大化。
聚類分析的算法有多種,本文只為大家介紹K-Means 算法的應用和簡單的原理。
下文將分4個模塊為大家介紹聚類分析:
聚類分析的應用場景
聚類分析的K-Means 算法原理
聚類分析代碼-輸出聚類中心
聚類分析代碼-可視化
如何得到一個好的聚類分析結果
一、聚類分析的應用場景:
聚類分析的優勢在於可以在無標籤的情況下,將客戶根據數據之間的相關性劃分成幾類,常見的應用場景如下:
客戶畫像:可以基於眾多數據,給客戶進行分層分類,以便對目前運營的產品有完善的了解,如客戶的性別、年齡、地區、職業、收入等;
精準營銷:利用貸前、貸中數據,挖掘真正有價值的客戶,並找到其需求所在,精準推送,一網打盡;
反欺詐:清洗欺詐特徵(如首逾)進行數據挖掘,找到明細有欺詐傾向客戶和正常客戶的差異。
二、K-Means 算法原理:
K-Means 算法又稱為快速聚類法,是基於最小誤差法的原則將數據劃分為預定的類別K。這種算法原理簡單且計算高效。
算法過程如下:
Scikit-learn 中的 K-Means算法使用歐式距離去度量樣本到聚類中心的距離,並把誤差平方和SSE作為度量聚類效果的目標函數,選取誤差平方和最小的分類結果作為最終的聚類結果。
歐式距離函數:
三、聚類分析代碼-輸出聚類中心
3.1. 定義聚類分析所需要的包
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport mglearnfrom sklearn.preprocessing import LabelEncoderimport warningswarnings.filterwarnings('ignore')import seaborn as snsfrom sklearn.datasets import make_blobsfrom matplotlib import pyplotplt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus']=False3.2. 生成測試聚類分析代碼需要的隨機數據
data,target=make_blobs(n_samples=100000,n_features=10,centers=10)
a = []for i in range(10): a.append('X'+str(i))data = pd.DataFrame(data)data.columns = a
pyplot.scatter(data[:,1],data[:,0],c=target);pyplot.show()3.3. 輸出聚類中心
from sklearn.cluster import KMeansk = 4 iteration = 500 model = KMeans(n_clusters = k,n_jobs = 4,max_iter = iteration)model.fit(data)r1 = pd.Series(model.labels_).value_counts()r2 = pd.DataFrame(model.cluster_centers_)r = pd.concat([r2,r1],axis=1)r.columns = list(data.columns)+[u'所屬類別數目']r聚類分析的結果輸出如下:
3.4. 給每行數據標記所屬類別
r = pd.concat([data,pd.Series(model.labels_,index=data.index)],axis=1)r.columns = list(data.columns)+[u'所屬類別數目']
四、聚類分析代碼-可視化
上述已經輸出了聚類中心並給每個客戶都打好聚類標籤了,接下來就需要使用2種可視化工具進行聚類結果的觀測:
4.1. 聚類分析可視化工具-TSNE
TSNE可以對高維數據進行降維,讓其可以在2維或3維空間中進行聚類結果的展示,通過TSNE圖像可以大致看出是不是通過聚類分析把樣本數據明細的分類出來了,即觀測聚類效果。
from sklearn.manifold import TSNEtsne = TSNE()tsne.fit_transform(data)tsne = pd.DataFrame(tsne.embedding_,index=data.index)c = ['go','r.','b*','y.'] # 定義每個分類的顏色for i in range(k): # k為分類的個數 v = tsne[r[u'類別數目'] == i] plt.plot(v[0],v[1],c[i])4.2. 特徵間的二維分布散點圖
TSNE有個缺點,處理大量數據(10萬+),會非常慢,考驗工程師的耐心,這時也可以使用兩兩特徵的散點圖。我們可以根據業務經驗選取散點圖的特徵,比如高學歷伴隨高收入,我們可以選取學歷和收入來看其散點圖是否有明顯的聚類效果,如果覺得1-2組不夠有代表性,可以多選幾組。
# 查看兩兩特徵的二維分布fig,axes = plt.subplots(1,2,figsize=(10,5))mglearn.discrete_scatter(data['X0'],data['X1'],model.labels_,ax=axes[0])mglearn.discrete_scatter(data['X1'],data['X2'],model.labels_,ax=axes[1])4.3. 單個特徵的概率密度函數
在聚類完成後,我們可以通過查看每個聚類的分布情況,判斷聚類出來的結果是否具有業務意義。
通過下面的代碼,我們將對每個聚類標籤下的特徵都畫出一張概率密度函數圖像(即如果有4個聚類中心,將有4張特徵為X1的分布圖)。
def density_plot(data,col): plt.figure(dpi=80) p = data[col].plot(kind='kde',linewidth=2,subplots=True,sharex=False,figsize=(5,5)) plt.legend() return plt for i in range(k): density_plot(data[r[u'類別數目']==i],'X1')
這時候,就需要多個特徵輔助判斷聚類結果是否有業務意義。如下例:
從上表中可以明顯觀察到月使用次數越多,客戶活躍程度越高,說明此結果在業務層面的解釋下非常好。
五、如何得到一個好的聚類分析結果
在做聚類分析的時候,我們通常會遇到以下幾個問題:
到底該聚成幾類?
樣本特徵過多,怎麼降維?
怎樣才是一個好的聚類結果?
1. 到底該聚成幾類?
首先,我們應該明確自己的業務目標,初步制定下初始分類個數,即需要將客戶劃分為幾類。比如我們做欺詐聚類,那麼可以把客戶分為2類:有欺詐傾向/無欺詐傾向;我們做營銷數據分析,可以把客戶分為優質/良好/一般/較差等。
其次,我們可以圍繞初始類別個數進行上下浮動,並挑選幾組極具有業務含義的特徵進行散點圖和概率密度分布圖的觀測,從中選取業務意義最好的分類個數。
2. 樣本特徵過多,怎麼降維?
目前,針對無監督學習的數據降維主要有主成分分析和相關性分析。
個人不推薦在聚類分析之前使用主成分分析,原因在於:學過線性代數的朋友們應該都知道,主成分分析是通過正交變化將一組相關性的特徵轉換為非線性相關的特徵,轉換後的變量叫主成分,也是特徵值對應的特徵向量。一方面,主成分分析會損失很多原始數據信息;另一方面,通過主成分分析保留下來的主成分也很難有解釋性,因為數據已經被正交變換了。
如果樣本特徵過多,且相似特徵非常多,可以使用相關性分析,刪去極相關的特徵(如相關係數>=0.8)。這樣做的好處:
一方面,降低了聚類分析循環計算量,實現便捷高效;另一方面,保留了樣本大部分的信息。
3. 怎樣才是一個好的聚類結果?
算法是死的,業務是活的,任何算法結果都要符合業務場景。在分析聚類結果的時候,我們只需要關注以下3點:
1. 在聚類分析可視化工具-TSNE上觀測聚類效果,樣本數據有明顯的分層;
2. 在特徵間的二維分布散點圖和單個特徵的概率密度函數上,和幾組特徵的業務意義相吻合;
2. 分類出來的結果有業務價值。
----END---
知乎:金融建模
微信號:cutewendan
公眾號:風控汪的數據分析之路