一、K-means算法原理
k-means算法是一種簡單的迭代型聚類算法,采用距離作為相似性指標,從而發現給定數據集中的K個類,且每個類的中心是根據類中所有值的均值得到,每個類用聚類中心來描述。對於給定的一個包含n個d維數據點的數據集X以及要分得的類別K,選取歐式距離作為相似度指標,聚類目標是使得各類的聚類平方和最小,即最小化:

結合最小二乘法和拉格朗日原理,聚類中心為對應類別中各數據點的平均值,同時為了使得算法收斂,在迭代過程中,應使最終的聚類中心盡可能的不變。
二、算法實現一般流程
K-means是一個反復迭代的過程,算法分為四個步驟:
1)選取數據空間中的K個對象作為初始中心,每個對象代表一個聚類中心;
2)對於樣本中的數據對象,根據它們與這些聚類中心的歐氏距離,按距離最近的准則將它們分到距離它們最近的聚類中心(最相似)所對應的類;
3)更新聚類中心:將每個類別中所有對象所對應的均值作為該類別的聚類中心,計算目標函數的值;
4)判斷聚類中心和目標函數的值是否發生改變,若不變,則輸出結果,若改變,則返回2)。
三、算法應用實例--鳶尾花分類問題
1.Iris數據集
Iris也稱鳶尾花卉數據集,是一類多重變量分析的數據集。數據集包含150個數據集,分為3類,每類50個數據,每個數據包含4個屬性。可通過花萼長度,花萼寬度,花瓣長度,花瓣寬度4個屬性預測鳶尾花卉屬於(Setosa,Versicolour,Virginica)三個種類中的哪一類。
代碼實現:
import math from collections import defaultdict import numpy as np
dataname = "data.txt"
def loadIRISdata(filename): data = [] with open(filename, mode="r", encoding="utf-8") as rf: for line in rf: if line == '\n': continue data.append(list(map(float, line.split(" ")))) return data
def generateCenters(data): '''求解初始聚類中心''' centers = [] '''已知維度為4''' '''分三類,取第0,50,100的三個向量作為分界''' centers.append(data[0]) centers.append(data[50]) centers.append(data[100]) return centers
def distance(a ,b): '''歐式距離''' sum = 0 for i in range(4): sq = (a[i]-b[i])*(a[i]-b[i]) sum += sq return math.sqrt(sum)
def point_avg(points): '''對維度求平均值''' new_center = [] for i in range(4): sum = 0 for p in points: sum += p[i] new_center.append(float("%.8f" % (sum/float(len(points))))) return new_center def updataCenters(data, assigments): new_means = defaultdict(list) centers = [] for assigment, point in zip(assigments, data): new_means[assigment].append(point) '''將同一類的數據進行整合''' for i in range(3): points = new_means[i] centers.append(point_avg(points)) return centers
def assignment(data, centers): assignments = [] '''對應位置顯示對應類群''' for point in data: '''遍歷所有數據''' shortest = float('inf') shortestindex = 0 for i in range(3): '''遍歷三個中心向量,與哪個類中心歐氏距離最短就將其歸為哪類''' value = distance(point, centers[i]) if value < shortest: shortest = value shortestindex = i assignments.append(shortestindex) return assignments def kmeans(data): k_data = generateCenters(data) assigments = assignment(data, k_data) old_assigments = None while assigments != old_assigments: new_centers = updataCenters(data, assigments) old_assigments = assigments assigments = assignment(data, new_centers) result = list(zip(assigments, data)) return result
def acc(result): sum = 0 all = 0 for i in range(50): if result[i][0] == 0: sum += 1 all += 1 for i in range(50): if result[i+50][0] == 1: sum += 1 all += 1 for i in range(50): if result[i+100][0] == 2: sum += 1 all += 1 print('sum:', sum, 'all:', all) return sum, all if __name__ == "__main__": data = loadIRISdata(dataname) result = kmeans(data) for i in range(3): tag = 0 print('\n') print("第%d類數據有:" % (i+1)) for tuple in range(len(result)): if(result[tuple][0] == i): print(tuple, end=' ') tag += 1 if tag > 20 : print('\n') tag = 0 #print(result) print('\n') sum, all = acc(result) print('c-means准確度為:%2f%%' % ((sum/all)*100))
運行結果:

