聚類是一種無監督的學習,它將相似的物件歸到同乙個簇中,聚類方法幾乎可以應用於所有物件,簇內的物件越相似,聚類的效果越好,本文主要介紹k-均值聚類的演算法,之所以稱之為k-均值是因為它可以發現k個不同的簇,並且每個簇的中心採用簇中所含的值的均值計算而成
k-均值是發現給定資料集的k個簇的演算法,簇個數是由使用者給定的,每乙個簇通過質心(centroid),即簇中所有店的中心來描述。
k-均值演算法的工作流程是這樣的,首先,隨機確定k個初始點作為質心。然後將資料集中的每個點分配到乙個簇中,具體來說,為每個點找其最近的質心,並將其分配給質心所對應的簇,這一步完成後,每個簇的質心更新為該簇所有點的平均值。
上述過程的偽**表示如下:
建立k個作為起始質心(通常是隨機選擇)
當任意乙個點的簇分配結果發生改變時
對資料集中的每個資料點
對每個質心
計算質心與資料點之間的距離
將資料點分配到距離其最近的簇
對每乙個簇,計算簇中所有點的均值並將均值作為質心
收集資料:使用任意方法
準備資料:需要資料型資料來計算距離,也可以將標稱型資料對映為二值型資料再用於距離計算。
分析資料:使用任意方法。
訓練演算法:不適用於無監督學習,即無監督學習沒有訓練過程。
測試演算法:應用聚類演算法,觀察結果。可以使用量化的誤差指標如誤差平方和來評價演算法的結果。
使用演算法:可以用於所希望的任何應用,通常情況下,簇質心可以代表整個簇的資料來做出決策
上面提到的「最近」質心的說法,意味著需要進行某種距離計算,可以選擇任意距離度量方法。這裡我們選擇利用歐式距離進行度量。資料集上的k-均值演算法的效能會受到所選距離計算方法的影響。下面給出k-均值演算法的**實現,首先建立乙個名為kmeans.py的檔案,然後將下面程式清單中的**新增到檔案中。
首先我們需要k-均值聚類演算法的支援函式,第乙個函式loaddataset(),它將原始資料文字檔案讀入到列表中,文字檔案每一行為tab分隔的浮點數,每乙個列表會被新增到datamat中,最後返回datamat,這種格式可以很容易將很多值封裝到矩陣中。
def loaddataset(filename):
datamat=
fr=open(filename)
for line in fr.readlines():
curline=line.strip().split('\t')
fltline=map(float,curline)
return datamat
我們首先使用testset.txt檔案中的實驗資料,其中資料儲存格式是這樣的
下乙個函式disteclud()計算兩個向量的歐式距離
def disteclud(veca,vecb):
return sqrt(sum(power(veca-vecb,2)))
最後乙個函式是randcent(),該函式為給定資料集構造乙個包含k個隨機質心的集合。隨機質心必須要在整個資料集的邊界之內,這個可以通過找到資料集的每一維的最小和最大值來完成。然後生成0到1.0之間的隨機數並可以通過取值範圍和最小值,以確保隨機點在資料的邊界之內
def kmeans(dataset,k,distmeas=disteclud,createcent=randcent):
m=shape(dataset)[0]
clusterassment=mat(zeros((m,2)))
centroids=createcent(dataset,k)
clusterchanged=true
while clusterchanged:
clusterchanged=false
for i in range(m):
mindist=inf;minindex=-1
for j in range(k):
distji=distmeas(centroids[j,:],dataset[i,:])
if distjikmeans()函式接受4個輸入引數,只有資料集及簇的數目是必選引數,而用來計算距離和建立初始質心的函式都是可選的,kmeans()一開始確定資料集中資料點的總數,然後建立乙個矩陣來儲存每個簇的分配結果。簇分配結果矩陣clusterassment包含兩列:一列紀錄簇索引值,第二列儲存誤差。這裡的誤差是指當前點到簇質心的距離。
按照上述方式(即計算之心-分配-重新計算)反覆迭代,知道所有資料點的簇分配結果不再改變為止
下圖給出兩個聚類結果的示意圖,下面的圖是乙個由於質心隨機初始化導致k-均值演算法效果不好的乙個例子,上面的圖是乙個包含三個簇的資料集上執行k-均值演算法之後的結果,但是點的簇分配結果值沒有那麼準確,k-均值演算法收斂單聚類效果較差的原因是,k-均值演算法收斂到了區域性最小值,而非全域性最小值。
為克服k-均值演算法收斂於區域性最小值的問題,有人提出了另乙個稱為二分k-均值的演算法,該演算法首先將所有點作為乙個簇,然後將該簇一分為二,之後選擇其中乙個簇繼續進行劃分,選擇哪乙個簇進行劃分取決於對其劃分是否可以最大程度降低sse的值,上述基於sse的劃分過程不斷重複,知道得到使用者指定的簇數目為止
二分k-均值演算法的偽**形式如下:
將所有點看成乙個簇
當簇數目小於k時
對於每乙個簇
計算總誤差
在給定的簇上面進行k-均值聚類(k=2)
計算將該簇一分為二之後的總誤差
選擇使得誤差最小的那個簇進行劃分操作
def bikmeans(dataset,k,distmeas=disteclud):
m=shape(dataset)[0]
clusterassment=mat(zeros((m,2)))
centroid0=mean(dataset,axis=0).tolist()[0]
centlist=[centroid0]
for j in range(m):
clusterassment[j,1]=distmeas(mat(centroid0),dataset[j,:])**2
while(len(centlist)該函式首先建立乙個矩陣來儲存資料集中的每個點的簇分配結果及平方誤差,然後計算整個資料集的質心,並使用乙個列表來保留所有的質心。得到上述質心之後,可以遍歷資料集中所有點來計算每個點到質心的誤差值.這些誤差值將會在後面用到。
接下來程式進入while迴圈,該迴圈會不停對簇進行劃分,知道得到想要的簇數目為止。可以通過考察簇列表的值來獲得當前簇的數目。然後遍歷所有的簇來決定最佳的簇進行劃分。為此需要比較劃分前後的sse。一開始將最小sse設為無窮,然後遍歷簇列表centlist中的每乙個簇。對每個簇,將該簇中的所有點看成乙個小的資料集ptsincurrcluster。將ptsincurrcluster輸入到函式kmeans()中進行處理(k=2)。 k-均值演算法會生成兩個(簇),同時給出每個簇的誤差值,這些誤差與剩餘資料集的誤差之後作為本次劃分的誤差,如果該劃分的sse值最小,則本次劃分被儲存。一旦決定了要劃分的簇,接下來執行實際劃分操作,只需要將要劃分的簇中所有點的簇分配結果進行修改即可。當使用kmeans()函式並制定簇數字2時,會得到兩個編號為0和1的結果簇。需要將這些簇編號修改為劃分簇及新加簇的編號,該過程可以通過兩個陣列過濾器來完成,最後,新的簇分配結果被更新,新的質心會被新增到centlist中。
當while迴圈結束時,同kmeans()函式一樣,函式返回質心列表和簇分配結果。
下面我們利用乙個較難的資料集testset.txt2來測試二分k-均值演算法。
我們可以看到聚類結果比普通k-均值準確很多
k均值聚類演算法
輸入 簇的數目k和包含n個物件的資料庫。輸出 k個簇,使平方誤差準則最小。演算法步驟 1.為每個聚類確定乙個初始聚類中心,這樣就有k 個初始聚類中心。2.將樣本集中的樣本按照最小距離原則分配到最鄰近聚類 3.使用每個聚類中的樣本均值作為新的聚類中心。4.重複步驟2.3直到聚類中心不再變化。5.結束,...
K 均值聚類演算法
from numpy import 建立元組 dataset 與我們所熟悉的矩陣類似,最終我們將獲得n 2的矩陣,filein open home zengxl pycharmprojects test3 機器學習實戰 ch10 testset.txt 是正斜槓 for line in filein...
K 均值聚類演算法
k means演算法是最簡單的一種聚類演算法。演算法的目的是使各個樣本與所在類均值的誤差平方和達到最小 這也是評價k means演算法最後聚類效果的評價標準 k means聚類演算法的一般步驟 初始化。輸入基因表達矩陣作為物件集x,輸入指定聚類類數n,並在x中隨機選取n個物件作為初始聚類中心。設定迭...