您的位置:首页 > 其它

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

2017-06-03 20:35 281 查看
一、目的意义

内容包括:

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

二、算法阐述(占20%)

---输入:期望得到的簇的数目k,n个对象的二维数据D。

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

 

算法步骤:

(1)输入k及n个二维数据对象

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

(3)repeat

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

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

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

(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-means
def 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  #假
4000
设当前的这个距离最小
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, 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

## 画出所有样例点 属于同一分类的绘制同样的颜色
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 matplotlib
matplotlib.use('Tkagg')   #要想绘图成功,必须加上这两句,也可修改matplotlib的配置文件,
#则不用这两句
from numpy import *       #numpy 是python的函数库,
import matplotlib.pyplot as plt
import 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 = 4
centroids, 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,这就好比世上先有鸡还是先有蛋的问题,这也是此算法无法避免的缺点。次算法对于初始值很敏感,对于不同的初始值,聚类的结果往往不同。对于噪声数据和孤立点数据非常敏感,少量的该数据能够对平均值产生巨大的影响。

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

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息