机器学习之聚类算法k-means

来源:互联网 发布:怎样关闭136端口 xp 编辑:程序博客网 时间:2024/06/04 19:09

一、目的意义

内容包括:

1)问题描述:k-means聚类算法的研究,此算法主要对二维数据点进行聚类。

二、算法阐述(占20%

---输入:期望得到的簇的数目kn个对象的二维数据D

---输出:k个簇的集合。

 

算法步骤:

1)输入kn个二维数据对象

     2)随机选择k个对象作为初始的簇的质心

3repeat

4)计算每个对象与各个簇的质心的距离,将对象划分到距离     其最近的簇

5)重新计算每个簇的质心并更新

6until所有分类下标都等于最小下标,算法停止

7)输出这k个簇的集合。

三、算法实现(占30%

 []:以下代码为算法的主要代码

命名为k_means.py的文件,此文件下的代码为:

from numpy import *import matplotlib.pyplot as plt#计算欧氏距离def euclDistance(vector1, vector2):   return sqrt(sum(power(vector2 - vector1, 2)))    #初始化质心,采用随机产生质心def initCentroids(dataSet, k):    numSamples, dim = dataSet.shape    #numSamples = 80    #dim = 2        centroids = mat(zeros((k, dim)))    #[[ 0.  0.]    # [ 0.  0.]    # [ 0.  0.]    # [ 0.  0.]]    for i in range(k):        index = int(random.uniform(0, numSamples)) #产生随机数,如果随机数产生相等了,如22,40,22,13,那么显示的聚类将减少,因为有个聚类的结果始终为空        #print(index)        centroids[i, :] = dataSet[index, :]    #print(centroids)    return centroids#centroids#[[-2.123337  2.943366]# [ 2.046259  2.735279]# [-2.967647  2.848696]# [ 3.542056  2.778832]]    #centroids, clusterAssment = k_means.kmeans(dataSet, k)    #k-meansdef kmeans(dataSet, k):    numSamples = dataSet.shape[0]  #计算行数用0,计算列数用1, numSamples=80    clusterAssment = mat(zeros((numSamples, 2))) #80*2的零矩阵    clusterChanged = True    centroids = initCentroids(dataSet, k) #初始化质心    while clusterChanged:        clusterChanged = False        for i in range(numSamples):  #循环80行            minDist = 100000.0  #假设当前的这个距离最小            minIndex = 0                        for j in range(k): # 求出每一行距离最小的下标,最小下标即是每个点所属类别                distance = euclDistance(centroids[j],dataSet[i])                if distance < minDist:                    minDist = distance                    minIndex = j            if clusterAssment[i, 0] != minIndex: #对象的下标不等于最小下标,直到所有对象下标都等于最小下标,算法停止。                clusterChange = True                clusterAssment[i, :] = minIndex, minDist**2                #print(clusterAssment[i, :])                #[[ 2.          2.32363089]]                #[[ 1.          0.14270381]]                #[[ 3.          9.63189586]]    for j in range(k):  #将同一个簇的点放在一起        pointsInCluster = dataSet[nonzero(clusterAssment[:, 0] == j)[0]]        #print(pointsInCluster)        #print(nonzero(clusterAssment[:, 0] == j))        #(array([ 3, 27, 51, 71, 79]), array([0, 0, 0, 0, 0]))        centroids[j, :] =mean(pointsInCluster, axis = 0) #计算每一列的均值,得出每个簇的质心        #print(centroids) #[[ 1.09078155 -3.17263173]                         # [ 2.6265299   3.10868015]                         # [ 4.589752   -1.575316  ]                         # [-3.03458403  0.53734279]]    return centroids, clusterAssmentdef 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         ## 画出所有样例点 属于同一分类的绘制同样的颜色       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']        #画出质心    for i in range(k):        plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 12)        plt.show()                         命名为test_kmeans.py的文件,此文件下的代码为:
import matplotlibmatplotlib.use('Tkagg')   #要想绘图成功,必须加上这两句,也可修改matplotlib的配置文件,                          #则不用这两句from numpy import *       #numpy 是python的函数库,import matplotlib.pyplot as pltimport k_means  ##处理数据,dataSet为嵌套列表[[1.658985, 4.285136], [-3.453687, 3.424321],.....]print("loading data...")dataSet = []  fileIn = open('testSet.txt')  for line in fileIn.readlines():        lineArr = line.strip().split()    #['1.658985', '4.285136']    #['-3.453687', '3.424321']    dataSet.append([float(lineArr[0]), float(lineArr[1])])#dataSet   嵌套列表print("clustering..."  )dataSet = mat(dataSet)  ####转成80*2的矩阵k = 4centroids, clusterAssment = k_means.kmeans(dataSet, k)  print("show the result...")k_means.showCluster(dataSet, k, centroids, clusterAssment) 


测试数据文件,文件名为testSet.txt
1.658985    4.285136  
-3.453687   3.424321  
4.838138    -1.151539  
-5.379713   -3.362104  
0.972564    2.924086  
-3.567919   1.531611  
0.450614    -3.302219  
-3.487105   -1.724432  
2.668759    1.594842  
-3.156485   3.191137  
3.165506    -3.999838  
-2.786837   -3.099354  
4.208187    2.984927  
-2.123337   2.943366  
0.704199    -0.479481  
-0.392370   -3.963704  
2.831667    1.574018  
-0.790153   3.343144  
2.943496    -3.357075  
-3.195883   -2.283926  
2.336445    2.875106  
-1.786345   2.554248  
2.190101    -1.906020  
-3.403367   -2.778288  
1.778124    3.880832  
-1.688346   2.230267  
2.592976    -2.054368  
-4.007257   -3.207066  
2.257734    3.387564  
-2.679011   0.785119  
0.939512    -4.023563  
-3.674424   -2.261084  
2.046259    2.735279  
-3.189470   1.780269  
4.372646    -0.822248  
-2.579316   -3.497576  
1.889034    5.190400  
-0.798747   2.185588  
2.836520    -2.658556  
-3.837877   -3.253815  
2.096701    3.886007  
-2.709034   2.923887  
3.367037    -3.184789  
-2.121479   -4.232586  
2.329546    3.179764  
-3.284816   3.273099  
3.091414    -3.815232  
-3.762093   -2.432191  
3.542056    2.778832  
-1.736822   4.241041  
2.127073    -2.983680  
-4.323818   -3.938116  
3.792121    5.135768  
-4.786473   3.358547  
2.624081    -3.260715  
-4.009299   -2.978115  
2.493525    1.963710  
-2.513661   2.642162  
1.864375    -3.176309  
-3.171184   -3.572452  
2.894220    2.489128  
-2.562539   2.884438  
3.491078    -3.947487  
-2.565729   -2.012114  
3.332948    3.983102  
-1.616805   3.573188  
2.280615    -2.559444  
-2.651229   -3.103198  
2.321395    3.154987  
-1.685703   2.939697  
3.031012    -3.620252  
-4.599622   -2.185829  
4.196223    1.126677  
-2.133863   3.093686  
4.668892    -2.562705  
-2.793241   -2.149706  
2.884105    3.043438  
-2.967647   2.848696  
4.479332    -1.764772  
-4.905566   -2.911070

四、结果分析(占30%


 

图片解释:算法输出了四个簇,此次聚类结果比较不错,四个较大的点为质心,

 

图片解释:此次聚类算法明显不如人意,这也是此算法的缺点,易达到局部最优。


 

图片解释;我们希望的算法聚类个数是4,这里只有3个聚类,出现这也的原因是:簇的四个初始质心是随机选取的,有可能随机到同一个数,如(22,13,33,22),这样导致有一个簇始终为空,不过出现这种情况的概率还是很小的,这也是此算法最糟糕的结果。


 

 

 

五、总结(占15%

我们知道,任何算法都有它自身的优点与缺点,通过很多次的实验结果验证,我更加深刻理解了k-means的优点与缺点。

优点:k-means算法是聚类问题的经典算法,该算法简单快速。对于大数据量的数据,有相对较高的算法效率,它的伸缩性很高,常常以局部最优来结束算法。当簇是密集的,圆形的,团状的,而且簇与簇之前的区别明显时,它的聚类效果较好。

缺点:要求用户必须事先给出要生成的簇的数目k,这就好比世上先有鸡还是先有蛋的问题,这也是此算法无法避免的缺点。次算法对于初始值很敏感,对于不同的初始值,聚类的结果往往不同。对于噪声数据和孤立点数据非常敏感,少量的该数据能够对平均值产生巨大的影响。

这个算法也即将应用到一个平台上,对于这个算法的透侧研究,也将有助于我开发此软件,我知道,通过此次算法的研究,我已经学到了很多有用的东西。