k-meas非監督聚類分析


實驗名稱: k-meas非監督聚類分析

 

一、實驗目的和要求

目的:

  1. 加深對非監督學習的理解和認識
  2. 掌握聚類方法K-Means算法的設計方法

 

要求:

    根據聚類數據,采用k-Means聚類方法畫出聚類中心

二、實驗環境、內容和方法

環境:windows 7,python2.6 ,Eclipse,Pydev

內容:

1)   非監督學習的理論基礎  

2)   動態聚類分析的思想和理論依據 

3)   聚類算法的評價指標

 

三、實驗基本原理

K-means算法是很典型的基於距離的聚類算法,采用距離作為相似性的評價指標,即認為兩個對象的距離越近,其相似度就越大。該算法認為簇是由距離靠近的對象組成的,因此把得到緊湊且獨立的簇作為最終目標。

我們以一個二維的例子來說明下聚類的目的。如下圖左所示,假設我們的n個樣本點分布在圖中所示的二維空間。從數據點的大致形狀可以看出它們大致聚為三個cluster,其中兩個緊湊一些,剩下那個松散一些。我們的目的是為這些數據分組,以便能區分出屬於不同的簇的數據,如果按照分組給它們標上不同的顏色,就是像下圖右邊的圖那樣:

如果人可以看到像上圖那樣的數據分布,就可以輕松進行聚類。但我們怎么教會計算機按照我們的思維去做同樣的事情呢?這里就可以使用k-means算法。

 

 

算法過程如下:

1)從N個文檔隨機選取K個文檔作為質心

2)對剩余的每個文檔測量其到每個質心的距離,並把它歸到最近的質心的類

3)重新計算已經得到的各個類的質心

4)迭代2~3步直至新的質心與原質心相等或小於指定閾值,算法結束

具體如下:

輸入:k, data[n];

(1) 選擇k個初始中心點,例如c[0]=data[0],…c[k-1]=data[k-1];

(2) 對於data[0]….data[n],分別與c[0]…c[k-1]比較,假定與c[i]差值最少,就標記為i;

(3) 對於所有標記為i點,重新計算c[i]={ 所有標記為i的data[j]之和}/標記為i的個數;

(4) 重復(2)(3),直到所有c[i]值的變化小於給定閾值

 

 

k-means算法是一種很常見的聚類算法,它的基本思想是:通過迭代尋找k個聚類的一種划分方案,使得用這k個聚類的均值來代表相應各類樣本時所得的總體誤差最小。

k-means算法的基礎是最小誤差平方和准則。其代價函數是:

式中,μc(i)表示第i個聚類的均值。我們希望代價函數最小,直觀的來說,各類內的樣本越相似,其與該類均值間的誤差平方越小,對所有類所得到的誤差平方求和,即可驗證分為k類時,各聚類是否是最優的。

上式的代價函數無法用解析的方法最小化,只能有迭代的方法。k-means算法是將樣本聚類成 k個簇(cluster),其中k是用戶給定的,其求解過程非常直觀簡單,具體算法描述如下:

1、隨機選取 k個聚類質心點

2、重復下面過程直到收斂 {

對於每一個樣例 i,計算其應該屬於的類:

對於每一個類 j,重新計算該類的質心:

}

下圖展示了對n個樣本點進行K-means聚類的效果,這里k取2。

其偽代碼如下:

********************************************************************

創建k個點作為初始的質心點(隨機選擇)

當任意一個點的簇分配結果發生改變時

對數據集中的每一個數據點

對每一個質心

計算質心與數據點的距離

將數據點分配到距離最近的簇

對每一個簇,計算簇中所有點的均值,並將均值作為質心

********************************************************************

 

 

四、實驗過程描述

k-means算法比較簡單,但也有幾個比較大的缺點:

(1)k值的選擇是用戶指定的,不同的k得到的結果會有挺大的不同,如下圖所示,左邊是k=3的結果,這個就太稀疏了,藍色的那個簇其實是可以再划分成兩個簇的。而右圖是k=5的結果,可以看到紅色菱形和藍色菱形這兩個簇應該是可以合並成一個簇的:

(2)對k個初始質心的選擇比較敏感,容易陷入局部最小值。例如,我們上面的算法運行的時候,有可能會得到不同的結果,如下面這兩種情況。K-means也是收斂了,只是收斂到了局部最小值:

(3)存在局限性,如下面這種非球狀的數據分布就搞不定了:

(4)數據庫比較大的時候,收斂會比較慢。

k-means老早就出現在江湖了。所以以上的這些不足也被世人的目光敏銳的捕捉到,並融入世人的智慧進行了某種程度上的改良。例如問題(1)對k的選擇可以先用一些算法分析數據的分布,如重心和密度等,然后選擇合適的k。而對問題(2),有人提出了另一個成為二分k均值(bisecting k-means)算法,它對初始的k個質心的選擇就不太敏感。

 

五、實驗結果

 

六、附錄代碼

 

Kmeans.py:

 

from numpy import *

import time

import matplotlib.pyplot as plt

 

 

# calculate Euclidean distance

def euclDistance(vector1, vector2):

    return sqrt(sum(power(vector2 - vector1, 2)))

 

# init centroids with random samples

def initCentroids(dataSet, k):

    numSamples, dim = dataSet.shape

    centroids = zeros((k, dim))

    for i in range(k):

        index = int(random.uniform(0, numSamples))

        centroids[i, :] = dataSet[index, :]

    return centroids

 

# k-means cluster

def kmeans(dataSet, k):

    numSamples = dataSet.shape[0]

    # first column stores which cluster this sample belongs to,

    # second column stores the error between this sample and its centroid

    clusterAssment = mat(zeros((numSamples, 2)))

    clusterChanged = True

 

    ## step 1: init centroids

    centroids = initCentroids(dataSet, k)

 

    while clusterChanged:

        clusterChanged = False

        ## for each sample

        for i in xrange(numSamples):

            minDist = 100000.0

            minIndex = 0

            ## for each centroid

            ## step 2: find the centroid who is closest

            for j in range(k):

                distance = euclDistance(centroids[j, :], dataSet[i, :])

                if distance < minDist:

                    minDist = distance

                    minIndex = j

            

            ## step 3: update its cluster

            if clusterAssment[i, 0] != minIndex:

                clusterChanged = True

                clusterAssment[i, :] = minIndex, minDist**2

 

        ## step 4: update centroids

        for j in range(k):

            pointsInCluster = dataSet[nonzero(clusterAssment[:, 0].A == j)[0]]

            centroids[j, :] = mean(pointsInCluster, axis = 0)

 

    print 'Congratulations, cluster complete!'

    return centroids, clusterAssment

 

# show your cluster only available with 2-D data

def showCluster(dataSet, k, centroids, clusterAssment):

    numSamples, dim = dataSet.shape

    if dim != 2:

        print "Sorry! I can not draw because the dimension of your data is not 2!"

        return 1

 

    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']

    if k > len(mark):

        print "Sorry! Your k is too large! please contact Zouxy"

        return 1

 

    # draw all samples

    for i in xrange(numSamples):

        markIndex = int(clusterAssment[i, 0])

        plt.plot(dataSet[i, 0], dataSet[i, 1], mark[markIndex])

 

    mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '<b', 'pb']

    # draw the centroids

    for i in range(k):

        plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 12)

 

    plt.show()

      

      

      

      

      

      

      

 

 

Test_kmeans.py:

 

 

from numpy import *

import time

import matplotlib.pyplot as plt

 

import kmeans

 

from kmeans import kmeans,showCluster

 

## step 1: load data

print "step 1: load data..."

dataSet = []

fileIn = open('F:\code\python\k-means-2014-5-8/testSet.txt')

for line in fileIn.readlines():

    lineArr = line.strip().split('\t')

    dataSet.append([float(lineArr[0]), float(lineArr[1])])

 

## step 2: clustering...

print "step 2: clustering..."

dataSet = mat(dataSet)

k = 4

centroids, clusterAssment = kmeans(dataSet, k)

 

## step 3: show the result

print "step 3: show the result..."

showCluster(dataSet, k, centroids, clusterAssment)

 

 

數據點:testSet.txt

1.658985    4.285136

-3.453687    3.424321

4.838138    -1.151539

-5.379713    -3.362104

0.972564    2.924086

-3.567919    1.531611

0.450614    -3.302219

-3.487105    -1.724432

2.668759    1.594842

-3.156485    3.191137

3.165506    -3.999838

-2.786837    -3.099354

4.208187    2.984927

-2.123337    2.943366

0.704199    -0.479481

-0.392370    -3.963704

2.831667    1.574018

-0.790153    3.343144

2.943496    -3.357075

-3.195883    -2.283926

2.336445    2.875106

-1.786345    2.554248

2.190101    -1.906020

-3.403367    -2.778288

1.778124    3.880832

-1.688346    2.230267

2.592976    -2.054368

-4.007257    -3.207066

2.257734    3.387564

-2.679011    0.785119

0.939512    -4.023563

-3.674424    -2.261084

2.046259    2.735279

-3.189470    1.780269

4.372646    -0.822248

-2.579316    -3.497576

1.889034    5.190400

-0.798747    2.185588

2.836520    -2.658556

-3.837877    -3.253815

2.096701    3.886007

-2.709034    2.923887

3.367037    -3.184789

-2.121479    -4.232586

2.329546    3.179764

-3.284816    3.273099

3.091414    -3.815232

-3.762093    -2.432191

3.542056    2.778832

-1.736822    4.241041

2.127073    -2.983680

-4.323818    -3.938116

3.792121    5.135768

-4.786473    3.358547

2.624081    -3.260715

-4.009299    -2.978115

2.493525    1.963710

-2.513661    2.642162

1.864375    -3.176309

-3.171184    -3.572452

2.894220    2.489128

-2.562539    2.884438

3.491078    -3.947487

-2.565729    -2.012114

3.332948    3.983102

-1.616805    3.573188

2.280615    -2.559444

-2.651229    -3.103198

2.321395    3.154987

-1.685703    2.939697

3.031012    -3.620252

-4.599622    -2.185829

4.196223    1.126677

-2.133863    3.093686

4.668892    -2.562705

-2.793241    -2.149706

2.884105    3.043438

-2.967647    2.848696

4.479332    -1.764772

-4.905566    -2.911070


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM