K-means聚类算法算法优缺点:优点:容易实现
缺点:可能收敛到局部最小值,在大规模数据集上收敛较慢
使用数据类型:数值型数据
算法思想k-means算法实际上就是通过计算不同样本间的距离来判断他们的相近关系的,相近的就会放到同一个类别中去。
1.首先我们需要选择一个k值,也就是我们希望把数据分成多少类,这里k值的选择对结果的影响很大,Ng的课说的选择方法有两种一种是elbow method,简单的说就是根据聚类的结果和k的函数关系判断k为多少的时候效果最好。另一种则是根据具体的需求确定,比如说进行衬衫尺寸的聚类你可能就会考虑分成三类(L,M,S)等
2.然后我们需要选择最初的聚类点(或者叫质心),这里的选择一般是随机选择的,代码中的是在数据范围内随机选择,另一种是随机选择数据中的点。这些点的选择会很大程度上影响到最终的结果,也就是说运气不好的话就到局部最小值去了。这里有两种处理方法,一种是多次取均值,另一种则是后面的改进算法(bisecting K-means)
3.终于我们开始进入正题了,接下来我们会把数据集中所有的点都计算下与这些质心的距离,把它们分到离它们质心最近的那一类中去。完成后我们则需要将每个簇算出平均值,用这个点作为新的质心。反复重复这两步,直到收敛我们就得到了最终的结果。
函数loadDataSet(fileName)
从文件中读取数据集
distEclud(vecA, vecB)
计算距离,这里用的是欧氏距离,当然其他合理的距离都是可以的
randCent(dataSet, k)
随机生成初始的质心,这里是虽具选取数据范围内的点
kMeans(dataSet, k, distMeas=distEclud, createCent=randCent)
kmeans算法,输入数据和k值。后面两个事可选的距离计算方式和初始质心的选择方式
show(dataSet, k, centroids, clusterAssment)
可视化结果
1#coding=utf-82fromnumpy import *34def loadDataSet(fileName):5dataMat =[]6fr =open(fileName)7forlineinfr.readlines():8curLine = line.strip().split('\t')9fltLine = map(float, curLine)10dataMat.append(fltLine)11returndataMat1213#计算两个向量的距离,用的是欧几里得距离14def distEclud(vecA, vecB):15returnsqrt(sum(power(vecA - vecB,2)))1617#随机生成初始的质心(ng的课说的初始方式是随机选K个点)18def randCent(dataSet, k):19n = shape(dataSet)[1]20centroids =mat(zeros((k,n)))21forjinrange(n):22minJ =min(dataSet[:,j])23rangeJ =float(max(array(dataSet)[:,j]) -minJ)24centroids[:,j] = minJ + rangeJ * random.rand(k,1)25returncentroids2627def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):28m = shape(dataSet)[0]29clusterAssment = mat(zeros((m,2)))#create mat to assign data points30#to a centroid, also holds SE of each point31centroids =createCent(dataSet, k)32clusterChanged =True33whileclusterChanged:34clusterChanged =False35foriinrange(m):#foreach data point assign it to the closest centroid36minDist =inf37minIndex = -138forjinrange(k):39distJI =distMeas(centroids[j,:],dataSet[i,:])40ifdistJI <minDist:41minDist = distJI; minIndex =j42ifclusterAssment[i,0] !=minIndex:43clusterChanged =True44clusterAssment[i,:] = minIndex,minDist**245PRint centroids46forcentinrange(k):#recalculate centroids47ptsInClust = dataSet[nonzero(clusterAssment[:,0].A==cent)[0]]#getall the pointinthiscluster48centroids[cent,:] = mean(ptsInClust, axis=0) #assign centroid to mean49returncentroids, clusterAssment5051def show(dataSet, k, centroids, clusterAssment):52frommatplotlib import pyplotasplt53numSamples, dim =dataSet.shape54mark = ['or','ob','og','ok','^r','+r','sr','dr','<r','pr']55foriinxrange(numSamples):56markIndex =int(clusterAssment[i,0])57plt.plot(dataSet[i,0], dataSet[i,1], mark[markIndex])58mark = ['Dr','Db','Dg','Dk','^b','+b','sb','db','<b','pb']59foriinrange(k):60plt.plot(centroids[i,0], centroids[i,1], mark[i], markersize =12)61plt.show()6263def main():64dataMat = mat(loadDataSet('testSet.txt'))65myCentroids, clustAssing= kMeans(dataMat,4)66print myCentroids67show(dataMat,4, myCentroids, clustAssing)686970if__name__ =='__main__':71main()
这里是聚类结果,还是很不错的啦
但是有时候也会收敛到局部最小值,就像下面这样,就是不幸收敛到局部最优了
机器学习笔记索引
来自为知笔记(Wiz)