天天看點

python中kmeans函數_Python—kmeans算法學習筆記

一、什麼是聚類

聚類簡單的說就是要把一個文檔集合根據文檔的相似性把文檔分成若幹類,但是究竟分成多少類,這個要取決于文檔集合裡文檔自身的性質。下面這個圖就是一個簡單的例子,我們可以把不同的文檔聚合為3類。另外聚類是典型的無指導學習,所謂無指導學習是指不需要有人幹預,無須人為文檔進行标注。

python中kmeans函數_Python—kmeans算法學習筆記

二、聚類算法:from sklearn.cluster import KMeans

def__init__(self, n_clusters=8, init='k-means++', n_init=10, max_iter=300,tol=1e-4,precompute_distances='auto',verbose=0, random_state=None, copy_x=True, n_jobs=1):

(一)輸入參數:

(1)n_clusters:要分成的簇數也是要生成的質心數

類型:整數型(int)

預設值:8

n_clusters : int, optional, default: 8

The number of clusters to form as well as the number of centroids to generate.

(2)init:初始化質心,

類型:可以是function 可以是array(random or ndarray)

預設值:采用k-means++(一種生成初始質心的算法)

kmeans++:種子點選取的第二種方法。

kmedoids(PAM,Partitioning Around Medoids)

能夠解決kmeans對噪聲敏感的問題。kmeans尋找種子點的時候計算該類中所有樣本的平均值,如果該類中具有較為明顯的離群點,會造成種子點與期望偏差過大。例如,A(1,1),B(2,2),C(3,3),D(1000,1000),顯然D點會拉動種子點向其偏移。這樣,在下一輪疊代時,将大量不該屬于該類的樣本點錯誤的劃入該類。

為了解決這個問題,kmedoids方法采取新的種子點選取方式,1)隻從樣本點中選;2)選取标準能夠提高聚類效果,例如上述的最小化J函數,或者自定義其他的代價函數。但是,kmedoids方法提高了聚類的複雜度。

init : {'k-means++', 'random' or an ndarray}

Method for initialization, defaults to 'k-means++':

'k-means++' : selects initial cluster centers for k-mean clustering in a smart way to speed up convergence. See section Notes in k_init for more details.

(3)n_init: 設定選擇質心種子次數,預設為10次。傳回質心最好的一次結果(好是指計算時長短)

類型:整數型(int)

預設值:10

目的:每一次算法運作時開始的centroid seeds是随機生成的, 這樣得到的結果也可能有好有壞. 是以要運作算法n_init次, 取其中最好的。

n_init : int, default: 10

Number of time the k-means algorithm will be run with different centroid seeds. The final results will be the best output of n_init consecutive runs in terms of inertia.

(4)max_iter:每次疊代的最大次數

類型:整型(int)

預設值:300

max_iter : int, default: 300

Maximum number of iterations of the k-means algorithm for a

single run.

(5)tol: 容忍的最小誤差,當誤差小于tol就會退出疊代(算法中會依賴資料本身)

類型:浮點型(float)

預設值:le-4(0.0001)

Relative tolerance with regards to inertia to declare convergence

(6)precompute_distances: 這個參數會在空間和時間之間做權衡,如果是True 會把整個距離矩陣都放到記憶體中,auto 會預設在資料樣本大于featurs*samples 的數量大于12e6 的時候False,False時核心實作的方法是利用Cpython 來實作的

類型:布爾型(auto,True,False)

預設值:“auto”

Precompute distances (faster but takes more memory).

'auto' : do not precompute distances if n_samples * n_clusters > 12 million. This corresponds to about 100MB overhead per job usingdouble precision.

(7)verbose:是否輸出詳細資訊

類型:布爾型(True,False)

預設值:False

verbose : boolean, optional

Verbosity mode.

(8)random_state:随機生成器的種子 ,和初始化中心有關

類型:整型或numpy(RandomState, optional)

預設值:None

random_state : integer or numpy.RandomState, optional

The generator used to initialize the centers. If an integer is given, it fixes the seed. Defaults to the global numpy random number generator.

(9)copy_x:bool 在scikit-learn 很多接口中都會有這個參數的,就是是否對輸入資料繼續copy 操作,以便不修改使用者的輸入資料。這個要了解Python 的記憶體機制才會比較清楚。

類型:布爾型(boolean, optional)

預設值:True

When pre-computing distances it is more numerically accurate to center the data first.  If copy_x is True, then the original data is not modified.  If False, the original data is modified, and put back before the function returns, but small numerical differences may be introduced by subtracting and then adding the data mean.

(10)n_jobs:使用程序的數量,與電腦的CPU有關

類型:整數型(int)

預設值:1

The number of jobs to use for the computation. This works by computing

each of the n_init runs in parallel.

If -1 all CPUs are used. If 1 is given, no parallel computing code is used at all, which is useful for debugging. For n_jobs below -1,(n_cpus + 1 + n_jobs) are used. Thus for n_jobs = -2, all CPUs but one

are used.

(二)輸出參數:

(1)label_:每個樣本對應的簇類别标簽

示例:r1 = pd.Series(model.labels_).value_counts() #統計各個類别的數目

(2)cluster_centers_:聚類中心

傳回值:array, [n_clusters, n_features]

示例:r2 = pd.DataFrame(model.cluster_centers_) #找出聚類中心

使用示例:

python中kmeans函數_Python—kmeans算法學習筆記

#-*- coding: utf-8 -*-

#使用K-Means算法聚類消費行為特征資料

import pandas as pd

#參數初始化

inputfile = '../data/consumption_data.xls' #銷量及其他屬性資料

outputfile = '../tmp/data_type.xls' #儲存結果的檔案名

k = 3 #聚類的類别

iteration = 500 #聚類最大循環次數

data = pd.read_excel(inputfile, index_col = 'Id') #讀取資料

data_zs = 1.0*(data - data.mean())/data.std() #資料标準化

from sklearn.cluster import KMeans

model = KMeans(n_clusters = k, n_jobs = 4, max_iter = iteration) #分為k類, 并發數4

model.fit(data_zs) #開始聚類

#簡單列印結果

r1 = pd.Series(model.labels_).value_counts() #統計各個類别的數目

r2 = pd.DataFrame(model.cluster_centers_) #找出聚類中心

r = pd.concat([r2, r1], axis = 1) #橫向連接配接(0是縱向), 得到聚類中心對應的類别下的數目

r.columns = list(data.columns) + [u'類别數目'] #重命名表頭

print(r)

#詳細輸出原始資料及其類别

r = pd.concat([data, pd.Series(model.labels_, index = data.index)], axis = 1) #詳細

輸出每個樣本對應的類别

r.columns = list(data.columns) + [u'聚類類别'] #重命名表頭

r.to_excel(outputfile) #儲存結果

python中kmeans函數_Python—kmeans算法學習筆記

三、聚類分析算法的評價

(一)實作目标:其目标是實作組内的對象互相之間是相似的(相關的),而不同組中的對象是不同的(不相關的)。組内的相似性越大,組間差别越大,聚類效果就越好。

(二)評價方法:

既然聚類是把一個包含若幹文檔的文檔集合分成若幹類,像上圖如果聚類算法應該把文檔集合分成3類,而不是2類或者5類,這就設計到一個如何評價聚類結果的問題。

python中kmeans函數_Python—kmeans算法學習筆記

如圖認為x代表一類文檔,o代表一類文檔,方框代表一類文檔,完美的聚類顯然是應該把各種不同的圖形放入一類,事實上我們很難找到完美的聚類方法,各種方法在實際中難免有偏差,是以我們才需要對聚類算法進行評價看我們采用的方法是不是好的算法。

(1)purity評價法:

purity方法是極為簡單的一種聚類評價方法,隻需計算正确聚類的文檔數占總文檔數的比例:

python中kmeans函數_Python—kmeans算法學習筆記

其中Ω = {ω1,ω2, . . . ,ωK}是聚類的集合ωK表示第k個聚類的集合。C = {c1, c2, . . . , cJ}是文檔集合,cJ表示第J個文檔。N表示文檔總數。

如上圖的purity = ( 3+ 4 + 5) / 17 = 0.71

其中第一類正确的有5個,第二個4個,第三個3個,總文檔數17。

purity方法的優勢是友善計算,值在0~1之間,完全錯誤的聚類方法值為0,完全正确的方法值為1。同時,purity方法的缺點也很明顯它無法對退化的聚類方法給出正确的評價,設想如果聚類算法把每篇文檔單獨聚成一類,那麼算法認為所有文檔都被正确分類,那麼purity值為1!而這顯然不是想要的結果。

(2)RI評價法:

實際上這是一種用排列組合原理來對聚類進行評價的手段,公式如下:

python中kmeans函數_Python—kmeans算法學習筆記

其中TP是指被聚在一類的兩個文檔被正确分類了,TN是隻不應該被聚在一類的兩個文檔被正确分開了,FP隻不應該放在一類的文檔被錯誤的放在了一類,FN指不應該分開的文檔被錯誤的分開了。對上圖

python中kmeans函數_Python—kmeans算法學習筆記

TP+FP = C(2,6) + C(2,6) + C(2,5) = 15 + 15 + 10 = 40

其中C(n,m)是指在m中任選n個的組合數。

TP = C(2,5) + C(2,4) + C(2,3) + C(2,2) = 20

FP = 40 - 20 = 20

同理:

TN+FN= C(1,6) * C(1,6)+ C(1,6)* C(1,5) + C(1,6)* C(1,5)=96

FN= C(1,5) * C(1,3)+ C(1,1)* C(1,4) + C(1,1)* C(1,3)+ C(1,1)* C(1,2)=24

TN=96-24=72

是以RI = ( 20 + 72) / ( 20 + 20 + 72 +24) = 0.68

(三):F值評價法

這是基于上述RI方法衍生出的一個方法,

python中kmeans函數_Python—kmeans算法學習筆記

注:p是查全率,R是查準率,當β>1時查全率更有影響,當β<1時查準率更有影響,當β=1時退化為标準的F1,詳細查閱機器學習P30

RI方法有個特點就是把準确率和召回率看得同等重要,事實上有時候我們可能需要某一特性更多一點,這時候就适合F值方法

Precision=TP/(TP+FP)

Recall=TP/(TP+FN)

F1=2×Recall×Precision/(Recall+Precision)

Precision=20/40=0.5

Recall=20/44=0.455

F1=(2*0.5*0.455)/(0.5+0.455)=0.48

四、聚類分析結果的降維可視化—TSNE

我們總喜歡能夠直覺地展示研究結果,聚類也不例外。然而,通常來說輸入的特征數是高維的(大于3維),一般難以直接以原特征對聚類結果進行展示。而TSNE提供了一種有效的資料降維方式,讓我們可以在2維或者3維的空間中展示聚類結果。

示例代碼:接上文示例代碼

python中kmeans函數_Python—kmeans算法學習筆記

#-*- coding: utf-8 -*-

#接k_means.py

from sklearn.manifold import TSNE

tsne = TSNE()

tsne.fit_transform(data_zs) #進行資料降維

tsne = pd.DataFrame(tsne.embedding_, index = data_zs.index) #轉換資料格式

import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei'] #用來正常顯示中文标簽

plt.rcParams['axes.unicode_minus'] = False #用來正常顯示負号

#不同類别用不同顔色和樣式繪圖

d = tsne[r[u'聚類類别'] == 0]

plt.plot(d[0], d[1], 'r.')

d = tsne[r[u'聚類類别'] == 1]

plt.plot(d[0], d[1], 'go')

d = tsne[r[u'聚類類别'] == 2]

plt.plot(d[0], d[1], 'b*')

plt.show()

python中kmeans函數_Python—kmeans算法學習筆記

效果圖:

python中kmeans函數_Python—kmeans算法學習筆記