《機器學習實戰》之K-均值聚類演算法的python實現

來源:互聯網
上載者:User

標籤:k-均值聚類演算法   機器學習實戰   python   

《機器學習實戰》之K-均值聚類演算法的python實現

最近的項目是關於“基於資料採礦的電路故障分析”,項目基本上都是師兄們在做,我只是在研究關於項目中用到的如下幾種演算法:二分均值聚類、最近鄰分類、基於規則的分類器以及支援向量機。基於項目的保密性(其實也沒有什麼保密的,但是怕以後老闆看到我寫的這篇博文,所以,你懂的),這裡就不介紹“基於資料採礦的電路故障分析”的思路了。

廢話不多說了,開始正題哈。

基本K-均值聚類演算法

基本K均值演算法的基本思路為:首先選擇K個初始質心(集合中所有點度量值的均值), K值為期望得到簇的個數,大小由使用者指定;將每個點指派到最近的質心,點與點之間的距離通過兩點對應的度量值差的絕對值進行度量,然後根據指派到簇的點,更新每個簇的質心,重複指派和更新,直到簇不再發生變化,或者滿足終止條件。

其虛擬碼如下:

建立k個點作為初始的質心點(隨機播放)
當任意一個點的簇分配結果發生改變時
            對資料集中的每一個資料點
                        對每一個質心
                              計算質心與資料點的距離
                        將資料點分配到距離最近的簇
           對每一個簇,計算簇中所有點的均值,並將均值作為質心

python實現代碼如下:注釋基本上寫的相當相當詳細,由於自己還是python的初學者,覺得注釋過多不方便看,還請大家諒解,有錯誤希望大家指正。
用到的庫有numpymatplotlib,直接通過如下命令安裝即可。

pip install numpy
pip install matplotlib

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)))  #求這兩個矩陣的距離,vector1、2均為矩陣# init centroids with random samples  #在樣本集中隨機選取k個樣本點作為初始質心def initCentroids(dataSet, k):      numSamples, dim = dataSet.shape   #矩陣的行數、列數     centroids = zeros((k, dim))         #感覺要不要你都可以    for i in range(k):          index = int(random.uniform(0, numSamples))  #隨機產生一個浮點數,然後將其轉化為int型        centroids[i, :] = dataSet[index, :]      return centroids  # k-means cluster #dataSet為一個矩陣#k為將dataSet矩陣中的樣本分成k個類 def kmeans(dataSet, k):      numSamples = dataSet.shape[0]  #讀取矩陣dataSet的第一維度長度,即獲得有多少個樣本資料    # 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)))  #得到一個N*2的零矩陣    clusterChanged = True      ## step 1: init centroids      centroids = initCentroids(dataSet, k)  #在樣本集中隨機選取k個樣本點作為初始質心    while clusterChanged:          clusterChanged = False          ## for each sample          for i in range(numSamples):  #range            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             #k個簇裡面與第i個樣本距離最小的的標號和距離儲存在clusterAssment中            #若所有的樣本不在變化,則退出while迴圈            if clusterAssment[i, 0] != minIndex:                  clusterChanged = True                  clusterAssment[i, :] = minIndex, minDist**2  #兩個**表示的是minDist的平方        ## step 4: update centroids          for j in range(k):              #clusterAssment[:,0].A==j是找出矩陣clusterAssment中第一列元素中等於j的行的下標,返回的是一個以array的列表,第一個array為等於j的下標            pointsInCluster = dataSet[nonzero(clusterAssment[:, 0].A == j)[0]] #將dataSet矩陣中相對應的樣本提取出來             centroids[j, :] = mean(pointsInCluster, axis = 0)  #計算標註為j的所有樣本的平均值    print (‘Congratulations, cluster complete!‘)      return centroids, clusterAssment  # show your cluster only available with 2-D data #centroids為k個類別,其中儲存著每個類別的質心#clusterAssment為樣本的標記,第一列為此樣本的類別號,第二列為到此類別質心的距離 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! ")          return 1     # draw all samples      for i in range(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.py

from numpy import *  import time  import matplotlib.pyplot as plt import KMeans## step 1: load data  print ("step 1: load data..." ) dataSet = []   #列表,用來表示,列表中的每個元素也是一個二維的列表;這個二維列表就是一個樣本,樣本中包含有我們的屬性值和類別號。#與我們所熟悉的矩陣類似,最終我們將獲得N*2的矩陣,fileIn = open("D:/xuepython/testSet.txt")  #是正斜杠for line in fileIn.readlines():     temp=[]    lineArr = line.strip().split(‘\t‘)  #line.strip()把末尾的‘\n‘去掉    temp.append(float(lineArr[0]))    temp.append(float(lineArr[1]))    dataSet.append(temp)    #dataSet.append([float(lineArr[0]), float(lineArr[1])])#上面的三條語句可以有這條語句代替  fileIn.close()  ## step 2: clustering...  print ("step 2: clustering..."  )dataSet = mat(dataSet)  #mat()函數是Numpy中的庫函數,將數組轉化為矩陣k = 4  centroids, clusterAssment = KMeans.kmeans(dataSet, k)  #調用KMeans檔案中定義的kmeans方法。## step 3: show the result  print ("step 3: show the result..."  )KMeans.showCluster(dataSet, k, centroids, clusterAssment)

運行結果圖如下:

上面是出現的兩種聚類的結果。由於基本K均值聚類演算法質心選擇的隨機性,其聚類的結果一般比較隨機,一般不會很理想,最終結果往往出現自然簇無法區分的情況,為避免此問題,本文採用二分K均值聚類演算法

二分K-均值聚類的python的實現將在下篇博文給出。

完整代碼和測試所用的資料可以在這裡擷取,還是希望大家從串連擷取源碼,因為從網頁上copy的代碼會出現沒有縮排的情況,需要大家添加縮排,比較麻煩,當你遇到IndentationError:unindent does not match any outer indentation level這樣的錯誤的時候,就是縮排引起的錯誤,可以看這篇博文,這篇博文給予瞭解決方法。

除了參考了《機器學習實戰》這本書之外,還參考了如下部落格,這篇部落格基本上也是參考了《機器學習實戰》這本書,在此,感謝作者。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

《機器學習實戰》之K-均值聚類演算法的python實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.