聚類分析在客戶細分中極為重要。有三類比較常見的聚類模型笼痛,K-mean聚類、層次(系統(tǒng))聚類琅拌、最大期望EM算法缨伊。在聚類模型建立過程中,一個比較關(guān)鍵的問題是如何評價聚類結(jié)果如何财忽,會用一些指標來評價倘核。
.
文章目錄
@[toc]
一、scikit-learn中的Kmeans介紹
1即彪、相關(guān)理論
2紧唱、主函數(shù)KMeans
3活尊、簡單案例一
4、案例二
5漏益、案例四——Kmeans的后續(xù)分析
二蛹锰、大數(shù)據(jù)量下的Mini-Batch-KMeans算法
主函數(shù) :
三、sklearn中的cluster進行kmeans聚類
四绰疤、分類變量聚類方法的K-modes與K-prototype
延伸一:數(shù)據(jù)如何做標準化
延伸二:Kmeans可視化案例
延伸三:模型保存
延伸四:HDBSCAN與Kmeans的聚類的一些紀要
一铜犬、scikit-learn中的Kmeans介紹
scikit-learn 是一個基于Python的Machine Learning模塊,里面給出了很多Machine
Learning相關(guān)的算法實現(xiàn)轻庆,其中就包括K-Means算法癣猾。
官網(wǎng)scikit-learn案例地址:http://scikit-learn.org/stable/modules/clustering.html#k-means
部分來自:scikit-learn 源碼解讀之Kmeans——簡單算法復(fù)雜的說
各個聚類的性能對比:
優(yōu)點:
原理簡單
速度快
對大數(shù)據(jù)集有比較好的伸縮性
缺點:
需要指定聚類 數(shù)量K
對異常值敏感
對初始值敏感
1
2
3
4
5
6
7
8
9
10
11
1、相關(guān)理論
參考:K-means算法及文本聚類實踐
(1)中心點的選擇
k-meams算法的能夠保證收斂余爆,但不能保證收斂于全局最優(yōu)點纷宇,當初始中心點選取不好時,只能達到局部最優(yōu)點蛾方,整個聚類的效果也會比較差像捶。可以采用以下方法:k-means中心點
選擇彼此距離盡可能遠的那些點作為中心點桩砰;
先采用層次進行初步聚類輸出k個簇拓春,以簇的中心點的作為k-means的中心點的輸入。
多次隨機選擇中心點訓(xùn)練k-means亚隅,選擇效果最好的聚類結(jié)果
(2)k值的選取
k-means的誤差函數(shù)有一個很大缺陷硼莽,就是隨著簇的個數(shù)增加,誤差函數(shù)趨近于0枢步,最極端的情況是每個記錄各為一個單獨的簇沉删,此時數(shù)據(jù)記錄的誤差為0,但是這樣聚類結(jié)果并不是我們想要的醉途,可以引入結(jié)構(gòu)風(fēng)險對模型的復(fù)雜度進行懲罰:
λλ是平衡訓(xùn)練誤差與簇的個數(shù)的參數(shù)矾瑰,但是現(xiàn)在的問題又變成了如何選取λλ了,有研究[參考文獻1]指出隘擎,在數(shù)據(jù)集滿足高斯分布時殴穴,λ=2mλ=2m,其中m是向量的維度货葬。
另一種方法是按遞增的順序嘗試不同的k值采幌,同時畫出其對應(yīng)的誤差值,通過尋求拐點來找到一個較好的k值震桶,詳情見下面的文本聚類的例子休傍。
2、主函數(shù)KMeans
參考博客:python之sklearn學(xué)習(xí)筆記
來看看主函數(shù)KMeans:
sklearn.cluster.KMeans(n_clusters=8,
init='k-means++',
n_init=10,
max_iter=300,
tol=0.0001,
precompute_distances='auto',
verbose=0,
random_state=None,
copy_x=True,
n_jobs=1,
algorithm='auto'
)
1
2
3
4
5
6
7
8
9
10
11
12
參數(shù)的意義:
n_clusters:簇的個數(shù)蹲姐,即你想聚成幾類
init: 初始簇中心的獲取方法
n_init: 獲取初始簇中心的更迭次數(shù)磨取,為了彌補初始質(zhì)心的影響人柿,算法默認會初始10次質(zhì)心,實現(xiàn)算法忙厌,然后返回最好的結(jié)果凫岖。
max_iter: 最大迭代次數(shù)(因為kmeans算法的實現(xiàn)需要迭代)
tol: 容忍度,即kmeans運行準則收斂的條件
precompute_distances:是否需要提前計算距離逢净,這個參數(shù)會在空間和時間之間做權(quán)衡哥放,如果是True 會把整個距離矩陣都放到內(nèi)存中,auto 會默認在數(shù)據(jù)樣本大于featurs*samples 的數(shù)量大于12e6 的時候False,False 時核心實現(xiàn)的方法是利用Cpython 來實現(xiàn)的
verbose: 冗長模式(不太懂是啥意思爹土,反正一般不去改默認值)
random_state: 隨機生成簇中心的狀態(tài)條件甥雕。
copy_x: 對是否修改數(shù)據(jù)的一個標記,如果True胀茵,即復(fù)制了就不會修改數(shù)據(jù)犀农。bool 在scikit-learn 很多接口中都會有這個參數(shù)的,就是是否對輸入數(shù)據(jù)繼續(xù)copy 操作宰掉,以便不修改用戶的輸入數(shù)據(jù)。這個要理解Python 的內(nèi)存機制才會比較清楚赁濒。
n_jobs: 并行設(shè)置
algorithm: kmeans的實現(xiàn)算法轨奄,有:‘a(chǎn)uto’, ‘full’, ‘elkan’, 其中 'full’表示用EM方式實現(xiàn)
雖然有很多參數(shù),但是都已經(jīng)給出了默認值拒炎。所以我們一般不需要去傳入這些參數(shù),參數(shù)的挪拟。可以根據(jù)實際需要來調(diào)用击你。
3玉组、簡單案例一
參考博客:python之sklearn學(xué)習(xí)筆記
本案例說明了,KMeans分析的一些類如何調(diào)取與什么意義丁侄。
import numpy as np
from sklearn.cluster import KMeans
data = np.random.rand(100, 3) #生成一個隨機數(shù)據(jù)惯雳,樣本大小為100, 特征數(shù)為3
假如我要構(gòu)造一個聚類數(shù)為3的聚類器
estimator = KMeans(n_clusters=3)#構(gòu)造聚類器
estimator.fit(data)#聚類
label_pred = estimator.labels_ #獲取聚類標簽
centroids = estimator.cluster_centers_ #獲取聚類中心
inertia = estimator.inertia_ # 獲取聚類準則的總和
1
2
3
4
5
6
7
8
9
10
estimator初始化Kmeans聚類;estimator.fit聚類內(nèi)容擬合鸿摇;
estimator.label_聚類標簽石景,這是一種方式,還有一種是predict拙吉;estimator.cluster_centers_聚類中心均值向量矩陣
estimator.inertia_代表聚類中心均值向量的總和
4潮孽、案例二
案例來源于:使用scikit-learn進行KMeans文本聚類
from sklearn.cluster import KMeans
num_clusters = 3
km_cluster = KMeans(n_clusters=num_clusters, max_iter=300, n_init=40,
init='k-means++',n_jobs=-1)
返回各自文本的所被分配到的類索引
result = km_cluster.fit_predict(tfidf_matrix)
print "Predicting result: ", result
1
2
3
4
5
6
7
8
9
10
km_cluster是KMeans初始化,其中用init的初始值選擇算法用’k-means++’筷黔;
km_cluster.fit_predict相當于兩個動作的合并:km_cluster.fit(data)+km_cluster.predict(data)往史,可以一次性得到聚類預(yù)測之后的標簽,免去了中間過程佛舱。
n_clusters: 指定K的值
max_iter: 對于單次初始值計算的最大迭代次數(shù)
n_init: 重新選擇初始值的次數(shù)
init: 制定初始值選擇的算法
n_jobs: 進程個數(shù)椎例,為-1的時候是指默認跑滿CPU
注意挨决,這個對于單個初始值的計算始終只會使用單進程計算,
并行計算只是針對與不同初始值的計算粟矿。比如n_init=10凰棉,n_jobs=40,
服務(wù)器上面有20個CPU可以開40個進程,最終只會開10個進程
其中:
km_cluster.labels_
km_cluster.predict(data)
1
2
這是兩種聚類結(jié)果標簽輸出的方式,結(jié)果貌似都一樣陌粹。都需要先km_cluster.fit(data)撒犀,然后再調(diào)用。
5掏秩、案例四——Kmeans的后續(xù)分析
Kmeans算法之后的一些分析或舞,參考來源:用Python實現(xiàn)文檔聚類
from sklearn.cluster import KMeans
num_clusters = 5
km = KMeans(n_clusters=num_clusters)
%time km.fit(tfidf_matrix)
clusters = km.labels_.tolist()
1
2
3
4
5
6
7
8
9
10
分為五類,同時用%time來測定運行時間蒙幻,把分類標簽labels格式變?yōu)閘ist映凳。
(1)模型保存與載入
from sklearn.externals import joblib
注釋語句用來存儲你的模型
joblib.dump(km, 'doc_cluster.pkl')
km = joblib.load('doc_cluster.pkl')
clusters = km.labels_.tolist()
1
2
3
4
5
6
(2)聚類類別統(tǒng)計
frame = pd.DataFrame(films, index = [clusters] , columns = ['rank', 'title', 'cluster', 'genre'])
frame['cluster'].value_counts()
1
2
(3)質(zhì)心均值向量計算組內(nèi)平方和
選擇更靠近質(zhì)心的點,其中 km.cluster_centers_代表著一個 (聚類個數(shù)*維度數(shù))邮破,也就是不同聚類诈豌、不同維度的均值。
該指標可以知道:
一個類別之中的抒和,那些點更靠近質(zhì)心矫渔;
整個類別組內(nèi)平方和。
類別內(nèi)的組內(nèi)平方和要參考以下公式:
通過公式可以看出:
質(zhì)心均值向量每一行數(shù)值-每一行均值(相當于均值的均值)
注意是平方摧莽。其中庙洼,n代表樣本量,k是聚類數(shù)量(譬如聚類5)
其中镊辕,整篇的組內(nèi)平方和可以通過來獲得總量:
km.inertia_
1
.
公眾號“素質(zhì)云筆記”定期更新博客內(nèi)容:
二油够、大數(shù)據(jù)量下的Mini-Batch-KMeans算法
部分內(nèi)容參考來源:scikit-learn學(xué)習(xí)之K-means聚類算法與 Mini Batch K-Means算法
當數(shù)據(jù)量很大的時候,Kmeans 顯然還是很弱的征懈,會比較耗費內(nèi)存速度也會收到很大影響石咬。scikit-learn 提供了MiniBatchKMeans算法,大致思想就是對數(shù)據(jù)進行抽樣卖哎,每次不使用所有的數(shù)據(jù)來計算碌补,這就會導(dǎo)致準確率的損失。
MiniBatchKmeans 繼承自Kmeans 因為MiniBathcKmeans 本質(zhì)上還利用了Kmeans 的思想.從構(gòu)造方法和文檔大致能看到這些參數(shù)的含義棉饶,了解了這些參數(shù)會對使用的時候有很大的幫助厦章。batch_size 是每次選取的用于計算的數(shù)據(jù)的樣本量,默認為100.
Mini Batch K-Means算法是K-Means算法的變種照藻,采用小批量的數(shù)據(jù)子集減小計算時間袜啃,同時仍試圖優(yōu)化目標函數(shù),這里所謂的小批量是指每次訓(xùn)練算法時所隨機抽取的數(shù)據(jù)子集幸缕,采用這些隨機產(chǎn)生的子集進行訓(xùn)練算法群发,大大減小了計算時間晰韵,與其他算法相比,減少了k-均值的收斂時間熟妓,小批量k-均值產(chǎn)生的結(jié)果雪猪,一般只略差于標準算法。
該算法的迭代步驟有兩步:
1:從數(shù)據(jù)集中隨機抽取一些數(shù)據(jù)形成小批量起愈,把他們分配給最近的質(zhì)心
2:更新質(zhì)心
與K均值算法相比只恨,數(shù)據(jù)的更新是在每一個小的樣本集上。對于每一個小批量抬虽,通過計算平均值得到更新質(zhì)心官觅,并把小批量里的數(shù)據(jù)分配給該質(zhì)心,隨著迭代次數(shù)的增加阐污,這些質(zhì)心的變化是逐漸減小的休涤,直到質(zhì)心穩(wěn)定或者達到指定的迭代次數(shù),停止計算
Mini Batch K-Means比K-Means有更快的 收斂速度笛辟,但同時也降低了聚類的效果功氨,但是在實際項目中卻表現(xiàn)得不明顯
一張k-means和mini batch k-means的實際效果對比圖
來看一下 MiniBatchKMeans的python實現(xiàn):
官網(wǎng)鏈接、案例一則鏈接
主函數(shù) :
MiniBatchKMeans(n_clusters=8, init=’k-means++’, max_iter=100, batch_size=100, verbose=0, compute_labels=True, random_state=None,
tol=0.0, max_no_improvement=10, init_size=None, n_init=3, reassignment_ratio=0.01)
1
2
相關(guān)參數(shù)解釋(來自博客:用scikit-learn學(xué)習(xí)K-Means聚類):
random_state: 隨機生成簇中心的狀態(tài)條件,譬如設(shè)置random_state = 9
tol: 容忍度手幢,即kmeans運行準則收斂的條件
max_no_improvement:即連續(xù)多少個Mini Batch沒有改善聚類效果的話疑故,就停止算法,
和reassignment_ratio弯菊, max_iter一樣是為了控制算法運行時間的。默認是10.一般用默認值就足夠了踱阿。
batch_size:即用來跑Mini Batch
KMeans算法的采樣集的大小管钳,默認是100.如果發(fā)現(xiàn)數(shù)據(jù)集的類別較多或者噪音點較多,需要增加這個值以達到較好的聚類效果软舌。
reassignment_ratio:
某個類別質(zhì)心被重新賦值的最大次數(shù)比例才漆,這個和max_iter一樣是為了控制算法運行時間的。這個比例是占樣本總數(shù)的比例佛点,
乘以樣本總數(shù)就得到了每個類別質(zhì)心可以重新賦值的次數(shù)醇滥。如果取值較高的話算法收斂時間可能會增加,尤其是那些暫時擁有樣本數(shù)較少的質(zhì)心超营。
默認是0.01鸳玩。如果數(shù)據(jù)量不是超大的話,比如1w以下演闭,建議使用默認值不跟。 如果數(shù)據(jù)量超過1w,類別又比較多米碰,可能需要適當減少這個比例值窝革。
具體要根據(jù)訓(xùn)練集來決定购城。
import time
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import MiniBatchKMeans, KMeans
from sklearn.metrics.pairwise import pairwise_distances_argmin
from sklearn.datasets.samples_generator import make_blobs
獲取數(shù)據(jù)
np.random.seed(0)
batch_size = 45
centers = [[1, 1], [-1, -1], [1, -1]]
n_clusters = len(centers)
X, labels_true = make_blobs(n_samples=3000, centers=centers, cluster_std=0.7)
kmeans
Compute clustering with Means
k_means = KMeans(init='k-means++', n_clusters=3, n_init=10)
t0 = time.time()
k_means.fit(X)
t_batch = time.time() - t0
MiniBatchKMeans
mbk = MiniBatchKMeans(init='k-means++', n_clusters=3, batch_size=batch_size,
n_init=10, max_no_improvement=10, verbose=0)
t0 = time.time()
mbk.fit(X)
t_mini_batch = time.time() - t0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
內(nèi)容跟kmeans很像,只是一般多加一個參數(shù)虐译,batch_size瘪板。
.
三、sklearn中的cluster進行kmeans聚類
參考博客:python之sklearn學(xué)習(xí)筆記
import numpy as np
from sklearn import cluster
data = np.random.rand(100, 3) #生成一個隨機數(shù)據(jù)漆诽,樣本大小為100, 特征數(shù)為3
k = 3 # 假如我要聚類為3個clusters
[centroid, label, inertia] = cluster.k_means(data, k)
1
2
3
4
5
四磷账、分類變量聚類方法的K-modes與K-prototype
K-prototype與K-modes
K-modes是K-means用在非數(shù)值集合上的一種方法,將原本K-means使用的歐式距離替換成字符間的漢明距離嘁圈。
用去分類變量
K-prototype是K-means與K-modes的一種集合形式肛炮,適用于數(shù)值類型與字符類型集合的數(shù)據(jù)。
度量具有混合屬性的方法是蚪腐,數(shù)值屬性采用K-means方法得到P1箭昵,分類屬性采用K-modes方法P2,那么D=P1+a*P2回季,a是權(quán)重家制。如果覺得分類屬性重要,則增加a泡一,否則減少a颤殴,a=0時即只有數(shù)值屬性
更新一個簇的中心的方法,方法是結(jié)合K-means與K-modes的更新鼻忠。
code實現(xiàn)可參考:nicodv/kmodes
公眾號“素質(zhì)云筆記”定期更新博客內(nèi)容:
.
延伸一:數(shù)據(jù)如何做標準化
data_zs = 1.0*(data - data.mean())/data.std() #數(shù)據(jù)標準化
1
.
延伸二:Kmeans可視化案例
來源于博客:使用python-sklearn-機器學(xué)習(xí)框架針對140W個點進行kmeans基于密度聚類劃分
from sklearn.cluster import KMeans
from sklearn.externals import joblib
import numpy
import time
import matplotlib.pyplot as plt
if name == 'main':
## step 1: 加載數(shù)據(jù)
print "step 1: load data..."
dataSet = []
fileIn = open('./data.txt')
for line in fileIn.readlines():
lineArr = line.strip().split(' ')
dataSet.append([float(lineArr[0]), float(lineArr[1])])
#設(shè)定不同k值以運算
for k in range(2,10):
clf = KMeans(n_clusters=k) #設(shè)定k :!L0痢!K芙俊3合馈!B癯辍哨啃!這里就是調(diào)用KMeans算法
s = clf.fit(dataSet) #加載數(shù)據(jù)集合
numSamples = len(dataSet)
centroids = clf.labels_
print centroids,type(centroids) #顯示中心點
print clf.inertia_ #顯示聚類效果
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
#畫出所有樣例點 屬于同一分類的繪制同樣的顏色
for i in xrange(numSamples):
#markIndex = int(clusterAssment[i, 0])
plt.plot(dataSet[i][0], dataSet[i][1], mark[clf.labels_[i]]) #mark[markIndex])
mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '<b', 'pb']
# 畫出質(zhì)點,用特殊圖型
centroids = clf.cluster_centers_
for i in range(k):
plt.plot(centroids[i][0], centroids[i][1], mark[i], markersize = 12)
#print centroids[i, 0], centroids[i, 1]
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
延伸三:模型保存
from sklearn.externals import joblib
joblib.dump(km_cluster, "/..../train_model.m")
km_cluster = joblib.load(".../train_model.m")
kmeans_SSE.labels_
1
2
3
4
延伸四:HDBSCAN與Kmeans的聚類的一些紀要
如果輸入數(shù)據(jù)的變量類型不同写妥,部分是數(shù)值型(numerical)拳球,部分是分類變量(categorical),需要做特別處理珍特。
方法1是將分類變量轉(zhuǎn)化為數(shù)值型醇坝,但缺點在于如果使用獨熱編碼(one hot encoding)可能會導(dǎo)致數(shù)據(jù)維度大幅度上升,如果使用標簽編碼(label encoding)無法很好的處理數(shù)據(jù)中的順序(order)。方法2是對于數(shù)值型變量和分類變量分開處理呼猪,并將結(jié)果結(jié)合起來画畅,具體可以參考Python的實現(xiàn)[1],如K-mode和K-prototype宋距。
輸出結(jié)果非固定轴踱,多次運行結(jié)果可能不同。
首先要意識到K-means中是有隨機性的谚赎,從初始化到收斂結(jié)果往往不同淫僻。一種看法是強行固定隨機性,比如設(shè)定sklearn中的random state為固定值壶唤。另一種看法是雳灵,如果你的K均值結(jié)果總在大幅度變化,比如不同簇中的數(shù)據(jù)量在多次運行中變化很大闸盔,那么K均值不適合你的數(shù)據(jù)悯辙,不要試圖穩(wěn)定結(jié)果 [2]
運行效率與性能之間的取舍。
但數(shù)據(jù)量上升到一定程度時迎吵,如>10萬條數(shù)據(jù)躲撰,那么很多算法都不能使用。最近讀到的一篇對比不同算法性能隨數(shù)據(jù)量的變化很有意思 [Benchmarking Performance and Scaling of Python Clustering Algorithms]击费。在作者的數(shù)據(jù)集上拢蛋,當數(shù)據(jù)量超過一定程度時僅K均值和HDBSCAN可用。
因此不難看出蔫巩,K均值算法最大的優(yōu)點就是運行速度快谆棱,能夠處理的數(shù)據(jù)量大,且易于理解圆仔。但缺點也很明顯垃瞧,就是算法性能有限,在高維上可能不是最佳選項荧缘。
一個比較粗淺的結(jié)論是,在數(shù)據(jù)量不大時拦宣,可以優(yōu)先嘗試其他算法截粗。當數(shù)據(jù)量過大時,可以試試HDBSCAN鸵隧。僅當數(shù)據(jù)量巨大绸罗,且無法降維或者降低數(shù)量時,再嘗試使用K均值豆瘫。
一個顯著的問題信號是珊蟀,如果多次運行K均值的結(jié)果都有很大差異,那么有很高的概率K均值不適合當前數(shù)據(jù),要對結(jié)果謹慎的分析育灸。
此外無監(jiān)督聚類的評估往往不易腻窒,基本都是基于使用者的主觀設(shè)計,如sklearn中提供的Silhouette Coefficient和 Calinski-Harabaz Index [5]磅崭。更多關(guān)于無監(jiān)督學(xué)習(xí)如何評估可以參考 [微調(diào):一個無監(jiān)督學(xué)習(xí)算法儿子,如何判斷其好壞呢?]。
參考:如何正確使用「K均值聚類」砸喻?
原文:https://blog.csdn.net/sinat_26917383/article/details/70240628