利用Python實(shí)現(xiàn)K-Means聚類的方法實(shí)例(案例:用戶分類)
K-Means聚類算法介紹
K-Means又稱為K均值聚類算法,屬于聚類算法中的一種,而聚類算法在機(jī)器學(xué)習(xí)算法中屬于無(wú)監(jiān)督學(xué)習(xí),在業(yè)務(wù)中常常會(huì)結(jié)合實(shí)際需求與業(yè)務(wù)邏輯理解來(lái)完成建模;
無(wú)監(jiān)督學(xué)習(xí):訓(xùn)練時(shí)只需要特征矩陣X,不需要標(biāo)簽;
K-Means聚類算法基礎(chǔ)原理
K-Means聚類算法是聚類算法家族中的典型代表,同時(shí)也是最簡(jiǎn)單的算法,接下來(lái)為大家簡(jiǎn)單地介紹聚類算法基本原理:
將一組存在N個(gè)樣本的特征矩陣X劃分為K個(gè)無(wú)交集的簇,每一個(gè)簇中含有多個(gè)數(shù)據(jù),每一個(gè)數(shù)據(jù)代表著一個(gè)樣本,在同一個(gè)簇中的數(shù)據(jù)即被算法認(rèn)為是同一類;
- N:假設(shè)為樣本數(shù)量;
- K:假設(shè)為聚類簇的數(shù)量;
- 簇:類似于集合,也可以通俗地理解成一個(gè)小組,不同小組等于不同分類;
而一個(gè)簇中的所有數(shù)據(jù)的均值,被稱為這個(gè)簇的質(zhì)心,質(zhì)心的維度與特征矩陣X的維度相同,如特征矩陣X是三維數(shù)據(jù)集,質(zhì)心也就是一個(gè)三維的坐標(biāo),如此類推至更高維度;
K-Means聚類算法實(shí)現(xiàn)流程
步驟一:隨機(jī)在N個(gè)樣本中抽取K個(gè)作為初始的質(zhì)心;
步驟二:開始遍歷除開質(zhì)心外的所有樣本點(diǎn),將其分配至距離它們最近的質(zhì)心,每一個(gè)質(zhì)心以及被分配至其下的樣本點(diǎn)視為一個(gè)簇(或者說(shuō)一個(gè)分類),這樣便完成了一次聚類;
步驟三:對(duì)于每一個(gè)簇,重新計(jì)算簇內(nèi)所有樣本點(diǎn)的平均值,取結(jié)果為新的質(zhì)心;
步驟四:比對(duì)舊的質(zhì)心與新的質(zhì)心是否再發(fā)生變化,若發(fā)生變化,按照新的質(zhì)心從步驟二開始重復(fù),若沒(méi)發(fā)生變化,聚類完成;
關(guān)鍵要點(diǎn):不斷地為樣本點(diǎn)尋找質(zhì)心,然后更新質(zhì)心,直至質(zhì)心不再變化;
開始做一個(gè)簡(jiǎn)單的聚類
環(huán)境說(shuō)明:本文實(shí)際案例中使用Jupyter環(huán)境下運(yùn)行(安裝與使用可自行百度);
數(shù)據(jù)導(dǎo)入
做數(shù)據(jù)分析前,首先第一步是導(dǎo)入數(shù)據(jù),可以利用pandas內(nèi)的read_csv函數(shù)來(lái)導(dǎo)入數(shù)據(jù);
首先,導(dǎo)入所需要用到的類,并使用read_csv函數(shù)導(dǎo)入案例數(shù)據(jù):
import numpy as np import pandas as pd data = pd.read_csv(r'D:\Machine_learning\KMeans\client_data.csv') # 使用pandas中的read_csv函數(shù)導(dǎo)入數(shù)據(jù)集后,默認(rèn)格式為DataFrame # 直接查看當(dāng)前數(shù)據(jù)集長(zhǎng)什么樣子 data.head()
數(shù)據(jù)打開后會(huì)發(fā)現(xiàn)大概長(zhǎng)這樣:
交易額 成交單量 最近交易時(shí)間
0 76584.92 294 64
1 94581.00 232 1
2 51037.60 133 1
3 43836.00 98 1
4 88032.00 95 2
# 若表頭項(xiàng)為中文時(shí),可能出現(xiàn)亂碼情況,請(qǐng)自行百度解決,或直接修改為英文;
數(shù)據(jù)探索
先探索數(shù)據(jù)類型:
# 探索數(shù)據(jù)類型 data.info() # 輸出結(jié)果: <class 'pandas.core.frame.DataFrame'> RangeIndex: 8011 entries, 0 to 8010 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 交易額 8011 non-null float64 1 成交單量 8011 non-null int64 2 最近交易時(shí)間 8011 non-null int64 dtypes: float64(1), int64(2) memory usage: 187.9 KB
- 共8011個(gè)數(shù)據(jù)樣本,3個(gè)維度列(2個(gè)整數(shù)、1個(gè)浮點(diǎn)數(shù)),且無(wú)缺失數(shù)據(jù);
- 數(shù)據(jù)背景:從三個(gè)維度獲取所有用戶交易180天內(nèi)交易數(shù)據(jù)(數(shù)據(jù)獲取、清洗規(guī)則在此不作詳細(xì)說(shuō)明);
- 第一列:索引(read_csv函數(shù)導(dǎo)入數(shù)據(jù)時(shí)會(huì)自動(dòng)生成索引,若數(shù)據(jù)集本身自帶索引,可設(shè)置參數(shù)index_=0,代表數(shù)據(jù)集中第一列為索引);
- 第二列:180天內(nèi)交易額,浮點(diǎn)數(shù);
- 第三列:180天內(nèi)成交單量,整數(shù);
- 第四列:最近成交訂單的日期與當(dāng)前日期差,整數(shù)(180內(nèi)無(wú)數(shù)據(jù)按照180運(yùn)算);
由于sklearn中K-Means聚類算法僅支持二維數(shù)組運(yùn)算,所以要先將數(shù)據(jù)集轉(zhuǎn)化為二維數(shù)組:
data = np.array(data,type(float)) # 查看數(shù)據(jù)集 data —————————————————————————————————————————————————— # 輸出結(jié)果: array([[76584.92, 294.0, 64.0], [94581.0, 232.0, 1.0], [51037.6, 133.0, 1.0], ..., [0.0, 0.0, 180.0], [0.0, 0.0, 180.0], [0.0, 0.0, 180.0]], dtype=object)
查看數(shù)組結(jié)構(gòu):
# 查看數(shù)組結(jié)構(gòu) data.shape ? —————————————————————————————————————————————————— # 輸出結(jié)果: (8011, 3)
開始聚類
數(shù)據(jù)集導(dǎo)入完成后,現(xiàn)在調(diào)用sklearn完成簡(jiǎn)單的聚類:
from sklearn.cluster import KMeans X = data # 實(shí)例化K-Means算法模型,先使用5個(gè)簇嘗試聚類 cluster = KMeans(n_clusters=5, random_state=0) # 使用數(shù)據(jù)集X進(jìn)行訓(xùn)練 cluster = cluster.fit(X) # 調(diào)用屬性labels_,查看聚類結(jié)果 cluster.labels_ —————————————————————————————————————————————————— # 輸出結(jié)果: array([4, 4, 1, ..., 0, 0, 0])
- 參數(shù)n_clusters:
設(shè)定聚類的目標(biāo)簇?cái)?shù)量,本次聚類先用5個(gè)簇嘗試; - 參數(shù)random_state:
設(shè)定隨機(jī)數(shù)種子,若不設(shè)定則每次聚類時(shí)都會(huì)使用不同的隨機(jī)質(zhì)心; - 接口fit():
使用數(shù)據(jù)集對(duì)模型進(jìn)行訓(xùn)練; - 屬性labels_:
查看訓(xùn)練后,每一樣本的預(yù)測(cè)分類結(jié)果;
查看輸出結(jié)果
查看輸出結(jié)果的數(shù)組結(jié)構(gòu):
# 查看預(yù)測(cè)結(jié)果的數(shù)據(jù)結(jié)構(gòu) cluster.labels_.shape —————————————————————————————————————————————————— # 輸出結(jié)果: (8011,)
分類結(jié)果的數(shù)組結(jié)構(gòu)為(8011,),剛好對(duì)應(yīng)著8011個(gè)樣本的預(yù)測(cè)分類結(jié)果;
再次確認(rèn)目標(biāo)分類結(jié)果只有5類,可以使用numpy中的unique()函數(shù)實(shí)現(xiàn):
# 查看數(shù)組中存在的類別(對(duì)一維數(shù)組去重) np.unique(cluster.labels_) ———————————————————————————————————————— # 輸出結(jié)果: array([0, 1, 2, 3, 4])
輸出結(jié)果0~4中分別代表著5個(gè)不同的分類;
查看預(yù)測(cè)結(jié)果中每一分類的數(shù)量:
# 查看每一分類結(jié)果的數(shù)量 pd.value_counts(cluster.labels_) —————————————————————————————————————————— 0 7068 2 688 4 198 1 38 3 19 dtype: int64
分類為0的數(shù)據(jù)占比較大(約88%),這部分?jǐn)?shù)據(jù)數(shù)據(jù)實(shí)際行業(yè)應(yīng)用中的長(zhǎng)尾數(shù)據(jù),這類用戶對(duì)平臺(tái)幾乎沒(méi)有任何價(jià)值貢獻(xiàn);
聚類質(zhì)心
聚類質(zhì)心代表每一個(gè)分類簇的中心,某種意義上講,質(zhì)心坐標(biāo)可以代表著這一個(gè)簇的普遍特征,質(zhì)心可以通過(guò)調(diào)用屬性cluster_centers_來(lái)查看:
# 查看質(zhì)心 cluster.cluster_centers_ —————————————————————————————————————————————————————————— # 輸出結(jié)果: array([[3.40713759e+02, 7.43350311e-01, 1.48025750e+02], [4.30125087e+04, 4.70000000e+01, 2.03947368e+01], [6.06497324e+03, 9.37354651e+00, 3.55159884e+01], [7.57037853e+04, 7.84736842e+01, 1.52631579e+01], [1.80933537e+04, 2.34040404e+01, 1.49444444e+01]])
輸出結(jié)果中分別對(duì)應(yīng)著0~4五種分類的普遍數(shù)據(jù)特征;
K-Means聚類算法的評(píng)估指標(biāo)
當(dāng)我們完成聚類建模后,怎么知道聚類的效果好不好,這時(shí)我們便需要「評(píng)估指標(biāo)」來(lái)評(píng)價(jià)模型的優(yōu)劣,并根據(jù)此來(lái)調(diào)整參數(shù);
對(duì)于聚類算法的評(píng)估指標(biāo),從大方向上區(qū)分為兩種:真實(shí)標(biāo)簽已知與真實(shí)標(biāo)簽未知;
真實(shí)標(biāo)簽已知
即我們對(duì)于每一個(gè)樣本的標(biāo)簽Y都是已知的,但是這種情況在實(shí)際的業(yè)務(wù)中幾乎是不存在的,若標(biāo)簽已知,使用分類算法(如隨機(jī)森林、SVM等)在各個(gè)方面來(lái)說(shuō)都會(huì)更加合適;
- 調(diào)整蘭德系數(shù):
在sklearn中的類為sklearn.metrics.adjusted_rand_score(y_true, y_pred)
y_true:代表測(cè)試集中一個(gè)樣本的真實(shí)標(biāo)簽;
y_pred:使用測(cè)試集中樣本調(diào)用預(yù)測(cè)接口的預(yù)測(cè)結(jié)果(上文中使用的cluster.labels_);
調(diào)整蘭德系數(shù)的取值在[-1,1]:數(shù)值越接近1越好,大于0時(shí)聚類效果較為優(yōu)秀,小于0時(shí)代表簇內(nèi)差異巨大甚至相互獨(dú)立,模型幾乎不可用;
由于案例數(shù)據(jù)集中真實(shí)標(biāo)簽是未知的,故不在此展示;
真實(shí)標(biāo)簽未知
即我們對(duì)每一個(gè)樣本的標(biāo)簽Y都是未知的,我們事先不知道每一個(gè)樣本是屬于什么分類,這種情況才是符合我們實(shí)際業(yè)務(wù)中真實(shí)使用聚類算法的場(chǎng)景;
- 輪廓系數(shù)系數(shù):
在sklearn中的類為:
返回輪廓系數(shù)的均值:sklearn.metrics.silhouette_score(X, y_pred);
返回?cái)?shù)據(jù)集中每個(gè)樣本自身的輪廓系數(shù):sklearn.metrics.silhouette_sample(X, y_pred);
輪廓系數(shù)的取值在(-1,1):
對(duì)于某一樣本點(diǎn)來(lái)說(shuō),當(dāng)值越接近1時(shí)就代表自身與所在的簇中其他樣本越相似,并且與其他簇中的樣本不相似,而當(dāng)值越接近-1時(shí)則代表與上述內(nèi)容相反;綜述,輪廓系數(shù)越接近1越好,負(fù)數(shù)則表示聚類效果非常差;
那接下來(lái)看看輪廓系數(shù)在剛才的聚類中效果如何:
# 導(dǎo)入輪廓系數(shù)所需要的庫(kù) from sklearn.metrics import silhouette_score from sklearn.metrics import silhouette_samples # 查看輪廓系數(shù)均值 silhouette_score(X,cluster.labels_) —————————————————————————————————————————————————— # 輸出結(jié)果 0.8398497410297728 —————————————————————————————————————————————————— # 查看每一樣本輪廓系數(shù) silhouette_samples(X,cluster.labels_) —————————————————————————————————————————————————— # 輸出結(jié)果 array([0.94301872, 0.94301872, 0.94301872, ..., 0.64706719, 0.60820687, 0.58272791]) —————————————————————————————————————————————————— # 查看樣本輪廓系數(shù)結(jié)果的數(shù)組結(jié)構(gòu) silhouette_samples(X,cluster.labels_).shape —————————————————————————————————————————————————— # 輸出結(jié)果 (8011,)
本次聚類的輪廓系數(shù)為0.84,表示聚類效果良好;
樣本輪廓系數(shù)的數(shù)據(jù)結(jié)構(gòu)可以看出:數(shù)組中每一個(gè)輸出結(jié)果對(duì)應(yīng)著每一個(gè)樣本的輪廓系數(shù),共8011個(gè);
- 卡林斯基-哈拉巴斯指數(shù):
sklearn中的類:sklearn.metrics.calinski_haabasz_score (X, y_pred);
卡林斯基-哈拉巴斯指數(shù)的數(shù)值無(wú)上限,且對(duì)于模型效果來(lái)說(shuō)越高越好,而由于無(wú)上限的特性,導(dǎo)致只能用作對(duì)比,而無(wú)法快速知曉模型效果是否好;
可以看看輪廓系數(shù)在剛才的聚類中效果如何:
# 調(diào)用所需要的類 from sklearn.metrics import calinski_harabasz_score calinski_harabasz_score(X,cluster.labels_) ——————————————————————————————————————————————————————— # 輸出結(jié)果 31777.971149699857
輸出的結(jié)果為31778,那究竟效果如何?因?yàn)闆](méi)有對(duì)照組,所以無(wú)法得知,如果有興趣的小伙伴可以在調(diào)整參數(shù)的時(shí)候使用對(duì)照組試試效果;
實(shí)用案例:基于輪廓系數(shù)來(lái)選擇最佳的n_clusters
需要繪制輪廓系數(shù)分布圖,先導(dǎo)入所需用到的庫(kù):
import matplotlib.pyplot as plt import matplotlib.cm as cm
繪制輪廓系數(shù)分布圖
使用for循環(huán)分別對(duì)2~8個(gè)簇的情況畫出輪廓系數(shù)分布圖:
for n_clusters in [2,3,4,5,6,7,8]: n_clusters = n_clusters # 設(shè)置畫布 fig, ax1 = plt.subplots(1) # 設(shè)置畫布尺寸 fig.set_size_inches(18, 7) # 設(shè)置畫布X軸 ax1.set_xlim([-0.1, 1]) # 設(shè)置畫布Y軸:X.shape[0]代表著柱狀的寬度,(n_clusters + 1) * 10代表著柱與柱之間的間隔 ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10]) # 模型實(shí)例化 clusterer = KMeans(n_clusters=n_clusters, random_state=100) # 開始訓(xùn)練模型 clusterer = clusterer.fit(X) # 提取訓(xùn)練結(jié)果中的預(yù)測(cè)標(biāo)簽 cluster_labels = clusterer.labels_ # 提取訓(xùn)練結(jié)果中的輪廓系數(shù)均值 silhouette_avg = silhouette_score(X, cluster_labels) # 打印出當(dāng)前的簇?cái)?shù)與輪廓系數(shù)均值 print("簇?cái)?shù)為", n_clusters, ",輪廓系數(shù)均值為", silhouette_avg) # 提取每一個(gè)樣本的輪廓系數(shù) sample_silhouette_values = silhouette_samples(X, cluster_labels) # 設(shè)置Y軸的起始坐標(biāo) y_lower = 10 # 添加一個(gè)循環(huán),把每一個(gè)樣本的輪廓系數(shù)畫在圖中 for i in range(n_clusters): # 提取第i個(gè)簇下的所有樣本輪廓系數(shù) ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i] # 對(duì)樣本的輪廓系數(shù)進(jìn)行排序(降序) ith_cluster_silhouette_values.sort() # 設(shè)置當(dāng)前簇的柱狀寬度(使用樣本數(shù)量)以便于設(shè)置下一個(gè)簇的起始坐標(biāo) size_cluster_i = ith_cluster_silhouette_values.shape[0] # 設(shè)置Y軸第i個(gè)簇的起始坐標(biāo) y_upper = y_lower + size_cluster_i # 設(shè)置顏色 color = cm.nipy_spectral(float(i)/n_clusters) # 畫圖 ax1.fill_betweenx(np.arange(y_lower, y_upper) ,ith_cluster_silhouette_values ,facecolor=color ,alpha=0.7 ) ax1.text(-0.05 , y_lower + 0.5 * size_cluster_i , str(i)) y_lower = y_upper + 10 # 設(shè)置圖的標(biāo)題 ax1.set_title("The silhouette plot for the various clusters.") ax1.set_xlabel("The silhouette coefficient values") ax1.set_ylabel("Cluster label") # 添加輪廓系數(shù)均值線,使用虛線 ax1.axvline(x=silhouette_avg, color="red", linestyle="--") ax1.set_yticks([]) ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1]) plt.show()
結(jié)果對(duì)比
輸出結(jié)果:
簇?cái)?shù)為 2 ,輪廓系數(shù)均值為 0.9348704011138467:
簇?cái)?shù)為 3 ,輪廓系數(shù)均值為 0.8889120986545176:
簇?cái)?shù)為 4 ,輪廓系數(shù)均值為 0.8432045328349393:
簇?cái)?shù)為 5 ,輪廓系數(shù)均值為 0.8397653971050274:
簇?cái)?shù)為 6 ,輪廓系數(shù)均值為 0.8217141668609508:
簇?cái)?shù)為 7 ,輪廓系數(shù)均值為 0.7995236853252528:
簇?cái)?shù)為 8 ,輪廓系數(shù)均值為 0.7995236853252528:
從本次的輸出結(jié)果中可知,當(dāng)簇?cái)?shù)量為2時(shí),會(huì)存在最大的輪廓系數(shù)均值,是否簇?cái)?shù)量為2就是最佳的參數(shù)呢?
答案必須是否定的,我們可以通過(guò)輪廓系數(shù)分部圖看到,基本上每一個(gè)圖內(nèi)都會(huì)有一片面積很大的塊,這就是長(zhǎng)尾數(shù)據(jù)帶來(lái)的,因?yàn)樗麄兓径技性谝粋€(gè)點(diǎn)上,所以導(dǎo)致整體輪廓系數(shù)均值“被平均”得很大,這樣的狀況也是很多實(shí)際業(yè)務(wù)數(shù)據(jù)中常常會(huì)碰到的;
優(yōu)化方案選擇
既然由于長(zhǎng)尾數(shù)據(jù)對(duì)輪廓系數(shù)帶來(lái)較大偏差,那咱們的思路可以把長(zhǎng)尾數(shù)據(jù)剔除掉,僅計(jì)算非長(zhǎng)尾數(shù)據(jù)(數(shù)據(jù)分析需要在不同的具體場(chǎng)景下有不同的思路,以下僅是一種思路舉例);
當(dāng)簇?cái)?shù)量為3時(shí):
# 實(shí)例化,訓(xùn)練模型 n_clusters = 3 clusterer = KMeans(n_clusters=n_clusters, random_state=100) clusterer = clusterer.fit(X) # 查看訓(xùn)練結(jié)果 pd.value_counts(clusterer.labels_) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 0 7599 1 362 2 50 dtype: int64
長(zhǎng)尾數(shù)據(jù)所在的簇為0,計(jì)算非長(zhǎng)尾數(shù)據(jù)的輪廓系數(shù)均值:
cluster_labels = clusterer.labels_ print(np.average(silhouette_samples(X, cluster_labels)[cluster_labels != 0])) —————————————————————————————————————————————————————————————————————————————— # 輸出結(jié)果 0.4909204497858037
當(dāng)簇?cái)?shù)量為4時(shí):
# 實(shí)例化,訓(xùn)練,并查看結(jié)果分布 n_clusters = 4 clusterer = KMeans(n_clusters=n_clusters, random_state=100) clusterer = clusterer.fit(X) pd.value_counts(clusterer.labels_) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 0 7125 3 663 2 179 1 44 dtype: int64 ———————————————————————————————————————————————————————————— # 計(jì)算非長(zhǎng)尾數(shù)據(jù)的輪廓系數(shù)均值 cluster_labels = clusterer.labels_ print(np.average(silhouette_samples(X, cluster_labels)[cluster_labels != 0])) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 0.4766824917258095
當(dāng)簇?cái)?shù)量為5時(shí):
# 實(shí)例化,訓(xùn)練,并查看結(jié)果分布 n_clusters = 5 clusterer = KMeans(n_clusters=n_clusters, random_state=100) clusterer = clusterer.fit(X) pd.value_counts(clusterer.labels_) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 2 7065 0 691 3 198 1 38 4 19 dtype: int64 ———————————————————————————————————————————————————————————— # 計(jì)算非長(zhǎng)尾數(shù)據(jù)的輪廓系數(shù)均值 cluster_labels = clusterer.labels_ print(np.average(silhouette_samples(X, cluster_labels)[cluster_labels != 2])) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 0.49228555254491085
當(dāng)簇?cái)?shù)量為6時(shí):
# 實(shí)例化,訓(xùn)練,并查看結(jié)果分布 n_clusters = 6 clusterer = KMeans(n_clusters=n_clusters, random_state=100) clusterer = clusterer.fit(X) pd.value_counts(clusterer.labels_) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 0 6806 5 799 3 252 2 99 1 36 4 19 dtype: int64 ———————————————————————————————————————————————————————————— # 計(jì)算非長(zhǎng)尾數(shù)據(jù)的輪廓系數(shù)均值 cluster_labels = clusterer.labels_ print(np.average(silhouette_samples(X, cluster_labels)[cluster_labels != 0])) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 0.5043196493336838
當(dāng)簇?cái)?shù)量為7時(shí):
# 實(shí)例化,訓(xùn)練,并查看結(jié)果分布 n_clusters = 7 clusterer = KMeans(n_clusters=n_clusters, random_state=100) clusterer = clusterer.fit(X) pd.value_counts(clusterer.labels_) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 0 6374 5 931 6 387 2 188 1 76 4 36 3 19 dtype: int64 ———————————————————————————————————————————————————————————— # 計(jì)算非長(zhǎng)尾數(shù)據(jù)的輪廓系數(shù)均值 cluster_labels = clusterer.labels_ print(np.average(silhouette_samples(X, cluster_labels)[cluster_labels != 0])) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 0.501667625921486
當(dāng)簇?cái)?shù)量為8時(shí):
# 實(shí)例化,訓(xùn)練,并查看結(jié)果分布 n_clusters = 8 clusterer = KMeans(n_clusters=n_clusters, random_state=100) clusterer = clusterer.fit(X) pd.value_counts(clusterer.labels_) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 0 6411 5 927 4 372 2 172 6 74 1 32 7 13 3 10 dtype: int64 ———————————————————————————————————————————————————————————— # 計(jì)算非長(zhǎng)尾數(shù)據(jù)的輪廓系數(shù)均值 cluster_labels = clusterer.labels_ print(np.average(silhouette_samples(X, cluster_labels)[cluster_labels != 0])) ———————————————————————————————————————————————————————————— # 輸出結(jié)果 0.4974116370311323
對(duì)比上述結(jié)果,當(dāng)n_clusters=6時(shí),輪廓系數(shù)均值存在最大值0.5043;
這時(shí)查看質(zhì)心的坐標(biāo):
# 設(shè)置參數(shù)n_clusters=6再次訓(xùn)練模型 n_clusters = 6 clusterer = KMeans(n_clusters=n_clusters, random_state=100) clusterer = clusterer.fit(X) # 使用屬性cluster_centers_查看質(zhì)心坐標(biāo) clusterer.cluster_centers_ —————————————————————————————————————————————————————————————— # 輸出結(jié)果 array([[2.50559675e+02, 5.95944755e-01, 1.51620923e+02], [4.36372269e+04, 4.83333333e+01, 2.06111111e+01], [2.23257222e+04, 2.73232323e+01, 1.72020202e+01], [1.15493973e+04, 1.65515873e+01, 1.95833333e+01], [7.57037853e+04, 7.84736842e+01, 1.52631579e+01], [4.25642288e+03, 6.82227785e+00, 4.39336671e+01]]) —————————————————————————————————————————————————————————————— # 查看聚類結(jié)果分布 pd.value_counts(clusterer.labels_) —————————————————————————————————————————————————————————————— # 輸出結(jié)果 0 6806 5 799 3 252 2 99 1 36 4 19 dtype: int64 —————————————————————————————————————————————————————————————— # 聚類結(jié)果分布以百分比形式顯示 pd.value_counts(clusterer.labels_,normalize=True) —————————————————————————————————————————————————————————————— # 輸出結(jié)果 0 0.849582 5 0.099738 3 0.031457 2 0.012358 1 0.004494 4 0.002372 dtype: float64
從結(jié)果可得(數(shù)據(jù)結(jié)果為科學(xué)計(jì)數(shù)法),6個(gè)類別客戶的畫像特征分別對(duì)應(yīng)著:
- 分類0——6806位——占比85%:
交易額:251元,平均單量:0.6單,最近交易時(shí)間:152天前; - 分類1——36位——占比0.4%:
交易額:43637元,平均單量:48單,最近交易時(shí)間:21天前; - 分類2——99位——占比1.2%:
交易額:22325元,平均單量:27單,最近交易時(shí)間:17天前; - 分類3——252位——占比3.1%:
交易額:11549元,平均單量:17單,最近交易時(shí)間:20天前; - 分類4——19位——占比0.2%:
交易額:75703元,平均單量:78單,最近交易時(shí)間:15天前; - 分類5——799位——占比10%:
交易額:4256元,平均單量:7單,最近交易時(shí)間:44天前;
到此這篇關(guān)于利用Python實(shí)現(xiàn)K-Means聚類的文章就介紹到這了,更多相關(guān)Python實(shí)現(xiàn)K-Means聚類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Pytorch通過(guò)保存為ONNX模型轉(zhuǎn)TensorRT5的實(shí)現(xiàn)
這篇文章主要介紹了Pytorch通過(guò)保存為ONNX模型轉(zhuǎn)TensorRT5的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05python分布式庫(kù)celery處理大規(guī)模的任務(wù)并行化
Python中的分布式任務(wù)隊(duì)列時(shí),Celery是一個(gè)備受推崇的工具,它是一個(gè)功能強(qiáng)大的分布式系統(tǒng),可用于處理大規(guī)模的任務(wù)并行化,本文將介紹Celery的基本概念、用法和示例代碼,幫助讀者更好地了解和使用這個(gè)庫(kù)2024-01-01Python實(shí)現(xiàn)全角半角轉(zhuǎn)換的方法
這篇文章主要介紹了Python實(shí)現(xiàn)全角半角轉(zhuǎn)換的方法,很實(shí)用的方法,需要的朋友可以參考下2014-08-08vscode寫python時(shí)的代碼錯(cuò)誤提醒和自動(dòng)格式化的方法
這篇文章主要介紹了vscode寫python時(shí)的代碼錯(cuò)誤提醒和自動(dòng)格式化的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05如何用scheduler實(shí)現(xiàn)learning-rate學(xué)習(xí)率動(dòng)態(tài)變化
這篇文章主要介紹了如何用scheduler實(shí)現(xiàn)learning-rate學(xué)習(xí)率動(dòng)態(tài)變化問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09