標籤:k-均值聚類演算法 機器學習實戰 python
《機器學習實戰》之K-均值聚類演算法的python實現
最近的項目是關於“基於資料採礦的電路故障分析”,項目基本上都是師兄們在做,我只是在研究關於項目中用到的如下幾種演算法:二分均值聚類、最近鄰分類、基於規則的分類器以及支援向量機。基於項目的保密性(其實也沒有什麼保密的,但是怕以後老闆看到我寫的這篇博文,所以,你懂的),這裡就不介紹“基於資料採礦的電路故障分析”的思路了。
廢話不多說了,開始正題哈。
基本K-均值聚類演算法
基本K均值演算法的基本思路為:首先選擇K個初始質心(集合中所有點度量值的均值), K值為期望得到簇的個數,大小由使用者指定;將每個點指派到最近的質心,點與點之間的距離通過兩點對應的度量值差的絕對值進行度量,然後根據指派到簇的點,更新每個簇的質心,重複指派和更新,直到簇不再發生變化,或者滿足終止條件。
其虛擬碼如下:
建立k個點作為初始的質心點(隨機播放)
當任意一個點的簇分配結果發生改變時
對資料集中的每一個資料點
對每一個質心
計算質心與資料點的距離
將資料點分配到距離最近的簇
對每一個簇,計算簇中所有點的均值,並將均值作為質心
python實現代碼如下:注釋基本上寫的相當相當詳細,由於自己還是python的初學者,覺得注釋過多不方便看,還請大家諒解,有錯誤希望大家指正。
用到的庫有numpy和matplotlib,直接通過如下命令安裝即可。
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實現