对机器学习一直很有兴趣,这段时间一直在看这方面的资料,今天记录下自己对K-means算法的学习,主要是研究了下zouxy09大神的文章。文章中有不足不妥的地方欢迎提醒交流,多谢!
关于k-means的理论知识,可以参考9神的文章,当然谷歌百度上也有很多。推荐都看看,集多家之所长,会让自己收获的更多。我这里就不再赘述了【懒癌一个】
执行流程
确定分类簇数k,可通过查看散点分布
随机选取质心点矩阵
对数据集中每个点进行迭代,计算每个点与各质心点的距离,选取距离数据点最近的质心点簇作为自己的类簇
直到数据集中所有数据点的类别不变为止
可视化分类点
执行结果
数据集是引用9神文章中的测试数据
开始读取数据 绘制散点图
可以看出图片中的散点分布大致成4或则5类,这里我设置的类簇数为4。 以下是执行分类计算的代码执行结果
调用开始进行数据聚类 开始质心选取 初始化质点点完成
[[-1.786345 2.554248] [ 3.367037 -3.184789] [ 2.884105 3.043438] [-3.284816 3.273099]] 开始分类 第1轮更新质点完成
[[-2.93239418 -0.59719121] [ 2.21588922 -2.88365904] [ 2.6265299 3.10868015] [-3.29756333 2.80177833]]
第2轮更新质点完成
[[-3.4967025 -2.70989515] [ 2.65077367 -2.79019029] [ 2.6265299 3.10868015] [-2.45009747 2.89275747]]
第3轮更新质点完成
[[-3.53973889 -2.89384326] [ 2.65077367 -2.79019029] [ 2.6265299 3.10868015] [-2.46154315 2.78737555]]
第4轮更新质点完成
[[-3.53973889 -2.89384326] [ 2.65077367 -2.79019029] [ 2.6265299 3.10868015] [-2.46154315 2.78737555]]
已完成数据分类 开始绘图
总共迭代了四轮,其实可以看出第四轮迭代后的质心矩阵与第三轮的质心矩阵一致,也就是实际上迭代了3轮,就已经分好类。看着结果还不错。
分类代码 以下是参考zouxy09大神的代码,我这里做了一些改动
# -*- coding:utf-8 -*- from numpy import * import matplotlib.pyplot as plt class Kmeans(): def __init__(self,dataSet,k): self.dataSet = dataSet self.k = k #质点数 self.numSamples = dataSet.shape[0] #矩阵的行数 self.dim = dataSet.shape[1] #矩阵的列数 self.signData = mat(zeros((self.numSamples,2))) #标签矩阵 #计算欧氏距离 def euclDistance(self,vector1,vector2): return sqrt(sum(power(vector1 - vector2 ,2))) def dataCount(self): print u"开始质心选取" # centroids = zeros((self.k,self.dim)) tem = [int(random.uniform(0,self.numSamples)) for i in xrange(self.k)] centroids = self.dataSet[tem] print u'初始化质点点完成\n' print centroids clusterChanged = True print u"开始分类" count = 0 while clusterChanged: clusterChanged = False for i in xrange(self.numSamples): minDist = 1000000000 index = 0 for j in xrange(self.k): distance = self.euclDistance(centroids[j,:],self.dataSet[i,:]) if distance < minDist: minDist = distance index = j #检查标签 if self.signData[i,0] != index: clusterChanged = True self.signData[i,:] = index,minDist**2 #更新质点 for i in range(self.k): pointsInCluster = self.dataSet[nonzero(self.signData[:,0].A==i)[0]] centroids[i,:] = mean(pointsInCluster,axis=0) count +=1 print u"第{}轮更新质点完成\n".format(count) print centroids print '*'*200 #分隔 print u"已完成数据分类" print u'开始绘图' if self.dim !=2: print u"无法绘制2纬图" return 1 mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr'] #设置绘图颜色 if k > len(mark): print u"选择的类别数太大,请重新确认类别数" return 1 for i in xrange(self.numSamples): markIndex = int(self.signData[i,0]) plt.plot(self.dataSet[i,0],self.dataSet[i,1],mark[markIndex]) #绘制分类图形 mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '<b', 'pb'] #设置质心绘图颜色 for i in range(self.k): plt.plot(centroids[i,0],centroids[i,1],mark[i],markersize=12) plt.show() if __name__=='__main__': print u'开始读取数据' dataSet = [] with open('D:/datajl.txt') as files: for line in files.readlines(): line = line.strip().split(',') # print line,type(line) dataSet.append([float(line[0]),float(line[1])]) dataSet = mat(dataSet) print u'绘制散点图' for x in xrange(dataSet.shape[0]): plt.plot(dataSet[x,0],dataSet[x,1],'ob') plt.show() k = 4 print u'开始进行数据聚类' Kmeans = Kmeans(dataSet,k) Kmeans.dataCount()任何算法都有其弊端,关于kmeans的缺点,还是参考zouxy09的文章吧,我就不误导了。
衷心感谢所有在互联网上分享自己技术文章的前辈们!
最后希望对看到此处的你有所帮助【微笑】
