Kmeans中的K值確定*

2020-12-13 北京圖靈學院

上篇文章為大家介紹了我們常用的聚類算法Kmenas算法,也為大家整理了一點小案例,今天為大家繼續分享我們Kmenas算法,對Kmenas算法來說,如何確定簇數K值是一個至關重要的問題,為了解決這個問題,通常會選用探索法,即給定不同的k值下,對比某些評估指標的變動情況,進而選擇一個比較合理的k值,在這我們上篇文章給大家推薦了三種方法(簇內離差平方和拐點法,輪廓係數法和間隔統計量法),接下來我們分別看看這三種方法是如何實現的:

Kmenas算法基礎公式:

拐點法

簇內離差平方和拐點法的思想很簡單,就是在不同的k值下計算簇內離差平方和,然後通過可視化的方法找到"拐點"所對應的k值,J為Kmeans算法的目標函數,隨著簇數量的增加,簇中的樣本量會越來越少,進而導致目標函數J的值也會越來越小,通過可視化方法,重點關注的是斜率的變化,當斜率由大突然變小時,並且之後的斜率變化緩慢,則認為突然變化的點就是尋找的目標點,因為繼續隨著簇數K的增加,聚類效果不再有大的變化。

接下來我們就驗證這個方法,隨機生成三組二元正態分布數據,首先基於該數據繪製散點圖,如下代碼:

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

from sklearn.cluster import KMeans

#隨機生成三組二元正態分布隨機數

np.random.seed(1234)

mean1 = [0.5,0.5]

cov1 = [[0.3,0],[0,0.3]]

x1,y1 = np.random.multivariate_normal(mean1,cov1,1000).T

mean2 = [0,8]

cov2 = [[0.3,0],[0,0.3]]

x2,y2 = np.random.multivariate_normal(mean2,cov2,1000).T

mean3 = [8,4]

cov3 = [[1.5,0],[0,1]]

x3,y3 = np.random.multivariate_normal(mean3,cov3,1000).T

#繪製三組數據的散點圖

plt.scatter(x1,y1)

plt.scatter(x2,y2)

plt.scatter(x3,y3)

plt.show()

如上圖,虛擬出來的數據呈現出三個簇,接下來基於這個虛擬數據,使用拐點法繪製簇的個數與總的簇內離差平方和之間的折線圖,確定最終的k值,代碼如下:

#構造自定義函數,用於繪製不同的k值和對應總的簇內離差平方和的折線圖

def k_SSE(X,clusters):

#選擇連續的K種不同的值

K= range(1,clusters+1)

#構建空列表用於存儲總的簇內離差平方和

TSSE= []

for k in K:

#用於存儲各個簇內離差平方和

SSE = []

kmeans = KMeans(n_clusters=k)

kmeans.fit(X)

#返回簇標籤

labels = kmeans.labels_

#返回簇中心

centers = kmeans.cluster_centers_

#計算各簇樣本的離差平方和,並保存到列表中

for label in set(labels):

SSE.append(np.sum((X.loc[labels==label,]-centers[label,:])**2))

#計算總的簇內離差平方和

TSSE.append(np.sum(SSE))

#中文和負號正常顯示

plt.rcParams['font.sans-serif'] = 'SimHei'

plt.rcParams['axes.unicode_minus'] =False

#設置繪畫風格

plt.style.use('ggplot')

#繪製K的個數與TSSE的關係

plt.plot(K,TSSE,'b*-')

plt.xlabel('簇的個數')

plt.ylabel('簇內離差平方和之和')

#

plt.show()

#將三組數據集匯總到數據框中

X = pd.DataFrame(np.concatenate([np.array([x1,y1]),np.array([x2,y2]),np.array([x3,y3])],axis=1).T)

k_SSE(X,15)

如上圖,當簇的個數為3時,形成了一個明顯的"拐點",因為K值從1到3時,折線的斜率都比較大,但是k值為4時斜率突然就降低了很多,並且之後的簇對應的斜率都變動很小,所以,合理的k值應該為3,與虛擬數據集的三個簇相吻合。

輪廓係數法

啥都不說先上公式,該方法綜合考慮了簇的密集性和分散性兩個信息,如果數據集被分割為理想的K個簇,那麼對應的簇內樣本會很密集,而簇間樣本會狠分散。上述公式中a(i)體現了簇內的秘籍性,代表樣本i與同簇內其他樣本點距離的平均值;b(i)反映了簇間的分散性,他的計算過程是樣本i與其他非同簇樣本點距離的平均值,然後從平均值中挑選出最小值。

通過公式可知當S(i)接近於-1時,說明樣本i分配的不合理,需要將其分配到其他簇中;當S(i)近似為0時,說明樣本i落在了模糊地帶,即簇的邊界處,當S(i)近似為1時,說明樣本i的分配是合理的。

接下來我們就看看如何用輪廓係數解決我們的k取值問題,由於輪廓係數計算較複雜,所以我們直接使用sklearn中的metrics中的silhouette_score方法,需要注意的是該方法需要接受的聚類簇數必須大於等於2.代碼如下:

from sklearn import metrics

#構造自定義函數

def k_silhouette(X,clusters):

K = range(2,clusters+1)

#構建空列表,用於存儲不同簇數下的輪廓係數

S = []

for k in K:

kmeans = KMeans(n_clusters=k)

kmeans.fit(X)

labels = kmeans.labels_

#調用子模塊metrics中的silhouette_score函數,計算輪廓係數

S.append(metrics.silhouette_score(X,labels,metric='euclidean'))

#設置繪圖風格

plt.rcParams['font.sans-serif'] = 'SimHei'

plt.rcParams['axes.unicode_minus'] =False

#設置繪畫風格

plt.style.use('ggplot')

#繪製K的個數與輪廓係數的關係

plt.plot(K,S,'b*-')

plt.xlabel('簇的個數')

plt.ylabel('輪廓係數')

plt.show()

k_silhouette(X,15)

如上圖,利用之前構造的虛擬數據,繪製了不同K值下對應的輪廓係數圖,當k取值為3時輪廓係數最大,且比較接近於1,說明應該把虛擬數據聚為3類比較合理。

間隔統計法

2000年Hastie等人提出了間隔統計量法(Gap Statistic方法),該方法可以適用於任何聚類算法,公式如下:

接下來我們構造自定義函數,繪製不同K值對應的間隙統計量折線圖:

#自定義函數,計算簇內任意倆樣本之間的歐式距離Dk

def short_pair_wise_D(each_cluster):

mu = each_cluster.mean(axis=0)

Dk = sum(sum((each_cluster-mu)**2*each_cluster.shape[0]))

return Dk

#自定義函數,計算簇內的Wk值

def compute_Wk(data, classfication_result):

Wk = 0

label_set = set(classfication_result)

for label in label_set:

each_cluster = data[classfication_result == label, :]

Wk = Wk + short_pair_wise_D(each_cluster)/(2.0*each_cluster.shape[0])

return Wk

# 計算GAP統計量

def gap_statistic(X, B=10, K=range(1,11), N_init = 10):

# 將輸入數據集轉換為數組

X = np.array(X)

# 生成B組參照數據

shape = X.shape

tops = X.max(axis=0)

bots = X.min(axis=0)

dists = np.matrix(np.diag(tops-bots))

rands = np.random.random_sample(size=(B,shape[0],shape[1]))

for i in range(B):

rands[i,:,:] = rands[i,:,:]*dists+bots

# 自定義0元素的數組,用於存儲gaps、Wks和Wkbs

gaps = np.zeros(len(K))

Wks = np.zeros(len(K))

Wkbs = np.zeros((len(K),B))

# 循環不同的k值,

for idxk, k in enumerate(K):

k_means = KMeans(n_clusters=k)

k_means.fit(X)

classfication_result = k_means.labels_

# 將所有簇內的Wk存儲起來

Wks[idxk] = compute_Wk(X,classfication_result)

# 通過循環,計算每一個參照數據集下的各簇Wk值

for i in range(B):

Xb = rands[i,:,:]

k_means.fit(Xb)

classfication_result_b = k_means.labels_

Wkbs[idxk,i] = compute_Wk(Xb,classfication_result_b)

# 計算gaps、sd_ks、sk和gapDiff

gaps = (np.log(Wkbs)).mean(axis = 1) - np.log(Wks)

sd_ks = np.std(np.log(Wkbs), axis=1)

sk = sd_ks*np.sqrt(1+1.0/B)

# 用於判別最佳k的標準,當gapDiff首次為正時,對應的k即為目標值

gapDiff = gaps[:-1] - gaps[1:] + sk[1:]

#設置繪圖風格

plt.rcParams['font.sans-serif'] = 'SimHei'

plt.rcParams['axes.unicode_minus'] =False

#設置繪畫風格

plt.style.use('ggplot')

# 繪製gapDiff的條形圖

plt.bar(np.arange(len(gapDiff))+1, gapDiff, color = 'steelblue')

plt.xlabel('簇的個數')

plt.ylabel('k的選擇標準')

plt.show()

# 自定義函數的調用

gap_statistic(X)

如上圖,x軸代表了不同的簇數k,y軸代表k值選擇的判斷指標gapDiff,gapDiff首次出現正值時對應的k為3,所以對於虛擬的數據集來說,將其劃分為三個簇是比較合理的。

以上就是Kmeans算法中中簇數k的確定方法,嗯,是有點小小的難度

相關焦點

  • KMeans評估(如何選擇最佳的k)
    原文來自微信公眾號:非凡wang咖在Kmenas算法中,如何確定簇數K值是一個至關重要的問題,為了解決這個問題,通常會選用探索法,即給定不同的k值下,對比某些評估指標的變動情況,進而選擇一個比較合理的k值。
  • 改良的kmeans與K近鄰算法特性分析
    摘要:kmeans算法作為無監督算法的一種,對初始點的選擇比較敏感;而k近鄰作為一種惰性且有監督的算法,對k值和樣本間距離度量方式的選擇也會影響結果。同時很多的學者投入到對kmeans算法本身特性的研究中 [4-5],目前kmeans算法已經成為機器學習,數據挖掘等領域比較重要的方法之一。而k近鄰算法是圖像以及文本分類領域應用比較廣泛的算法之一 [6-7],對k近鄰算法而言,k值的選擇以及樣本間距離的度量方式都會影響到分類的精確度。
  • 基於matlab的RBFNN的kmeans算法研究
    最後用層次聚類算法改進的kmeans算法在matlab中預設徑向基函數神經網絡,該網絡徑向基函數的數目、徑基函數的中心和寬度以及隱含層和輸出層之間的連接權值有算法的聚類結果確定,此方法徑向基函數神經 網絡的穩定性和高效性。
  • 使用K-means 算法進行客戶分類
    在本部分中,你將理解並學習到如何實現K-Means聚類。給定一組觀測值(x1,x2,...,xn),其中每一個觀測值都是d維實數向量,K均值聚類旨在將n個觀測值劃分為k(k≤n)個集合S={S1,S2,...,Sk}以最小化聚類內的平方和,其中µi是Si中的點的平均值。保證K-Means算法收斂到局部最優。
  • 數學推導+純 Python 實現機器學習算法:Kmeans 聚類
    算法流程:def kmeans(X, k, max_iterations): centroids = centroids_init(k, X) for _ in range(max_iterations): clusters = create_clusters(centroids, k, X) prev_centroids
  • 聚類算法之Kmeans
    然而,這裡歐氏距離計算方式和求均值更新簇心實際上是綁定的,嚴格來說,正是由於歐氏距離求解方式的確定,進而導致了更新簇心時是求均值的方式。可以這麼理解假定我們記k個簇心分別為a1,a2,。。。ak,每個簇的樣本數量為N1,N2,。。。Nk。我們使用平方誤差(歐氏距離)作為目標函數,即
  • Kmeans聚類算法
    ,側重總結歸納,而分類是在「分」之前就清楚知道總共有多少類,現在要確定新的樣本到底屬於哪個類,側重預測。            distance.append(dist)         idx[i] = np.argmin(distance) #k個距離中取最小的    return idx重新計算每一簇的質心,移動質心每個樣本都有了自己所屬的簇標籤後,就可以重新計算該簇的質心,一般以該簇的算術平均值作為新的質心
  • 教程 | matlab實現kmeans聚類算法
    kmeans聚類算法是一種簡單實用的聚類算法,matlab自帶函數kmeans可直接對數據進行kmeans聚類。
  • R語言做K均值聚類的一個簡單小例子
    /這篇連結裡提到默認的nstart是1,推薦使用較大的值,以獲得一個穩定的結果。這時候直接指定k下面用鳶尾花數據集做k均值聚類df<-iris[,1:4]iris.kmeans<-kmeans(df,centers=3,nstart = 25)names(iris.kmeans)iris.kmeans結果裡存儲9個結果,可能會用到的是
  • 【源碼】Kmeans聚類算法(超快速、簡潔的設計方法)
    這是一種超快速MATLAB實現的kmeans聚類算法。
  • 機器學習之基於sklearn的KMeans聚類
    聚類算法,無監督學習的代表算法,又叫做「無監督分類」即在訓練的時候只需要特徵矩陣,不需要真實值標籤可以有效地幫助我們探索數據的自然分布一、KMeans算法的運行過程運行的流程如下:自動聚類時的質心點的每步驟變化如下:下圖中紅色
  • k均值聚類算法原理和(TensorFlow)實現(無師自通)
    我們知道,在機器學習中,有三種不同的學習模式:監督學習、無監督學習和強化學習:監督學習,也稱為有導師學習,網絡輸入包括數據和相應的輸出標籤信息。例如,在 MNIST 數據集中,手寫數字的每個圖像都有一個標籤,代表圖片中的數字值。
  • 如何使用K-Means對用戶進行分群
    算法過程從 n 個樣本數據中隨機選取 K 個對象作為初始的聚類中心(在一開始確定 K 值上,憑業務經驗劃分,所以K值的選定不一定合理);分別計算每個樣本到各個聚類中心的距離,將對象分配到距離最近的聚類中;所有對象分配完成後,重新計算 K 個聚類的中心(類似重新計算虛擬中心);與前一次計算得到的 K
  • 數據分析入門系列教程-K-Means原理
    所謂的監督學習和非監督學習的區別就是樣本中是否存在標籤,對於有標籤的樣本做分析就是監督學習,而對沒有標籤的樣本做分析就屬於非監督學習。K-Means 解決的是聚類的問題,就是把樣本根據某些特徵,按照某些中心點,聚類在一起,從而達到分類的效果。K 代表的是 K 類,Means 代表的是中心,所以該算法的本質其實就是確定 K 類的中心點,當我們找到中心點後,也就完成了聚類。
  • 機器學習之分類算法K-Means介紹與代碼分析(篇四)
    維基百科,自由的百科全書中提到K-平均算法(英文:k-means clustering)源於信號處理中的一種向量量化方法,現在則更多地作為一種聚類分析方法流行於數據挖掘領域。k均值聚類是最著名的劃分聚類算法,由於簡潔和效率使得他成為所有聚類算法中最廣泛使用的。
  • K_means聚類的matlab應用
    若您對公眾號有什麼意見或建議,請在公眾號中回復或在任意文章底部留言!本文作者:南海一號在機器學習中,我們往往會遇到很大量的數據的處理,其中有一項就是聚類,即將相似的數據聚到一起,比較基礎的就是K_means聚類算法。聚類是一種無監督學習,不需要訓練樣本有對應的標籤就可以將不同的類分開。利用的就是相同類之間的相似性以及不同類之間的差異性。
  • python之kmeans數據聚類算法
    圖3kmeans實現邏輯:需要輸入待聚類的數據和欲聚類簇數k1.隨機生成k個初始點作為質心本章通過變化k的個數,計算k取不同值時,最後的誤差多少,誤差越小,則k最準確。二 數據準備對數據進行聚類,要對測試數據進行清洗。一般代碼都是對數值型數據進行計算,所以如果測試數據是漢字或其他類型的信息,我們要對其進行量化。
  • k-means算法
    k-means算法原理K-means中心思想:事先確定常數K,常數K意味著最終的聚類類別數,首先隨機選定初始點為質心,並通過計算每一個樣本與質心之間的相似度
  • 你需要的最全面的K-means聚類指南
    第一步:選擇簇的數目kK-means的第一步是選擇簇的數目k。第二步:從數據中選擇k個隨機點作為質心接下來,我們為每個簇隨機選擇質心。假設我們想要有2個簇,所以k在這裡等於2。你還必須在確定簇的個數時查看計算成本。如果我們增加簇的數量,計算成本也會增加。因此,如果你沒有高計算資源,我的建議是選擇較少數量的簇。現在讓我們在Python中實現K-means聚類算法。我們還將看到如何使用K-means ++來初始化質心,並且還將繪製曲線以確定我們的數據集的正確簇的個數。7.
  • k-means聚類簡介
    下面例子中「選擇K」的步驟描述如何確定組的數目。集群的每個質心都是特徵值的集合,它定義所產生的組。檢查質心特徵權重可以用來定性解釋每個集群代表什麼樣的組。這可以用於確定商業假設,存在什麼類型的分組或為複雜的數據集確定未知組。一旦該算法已運行並定義分組,任何新數據可以很容易地分配到正確的組。這是一個通用算法,可以用於任何類型的分組。