KMeans案例

KMeans聚类基于python有两种实现方式,一种是手动写算法实现聚类,另一种是采用写好的算法自动实现聚类,下面针对两种方法进行代码实现

一、数据准备  文件 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

二、python代码实现

1、手动写算法实现聚类, KMeansOnHand.py代码如下:

  1 # encoding:utf-8
  2 
  3 import numpy as np
  4 """
  5 手动实现聚类
  6 """
  7 
  8 # 将每行数据放入一个数组内列表,返回一个二维列表
  9 
 10 def loadDataSet(fileName):
 11     # 创建空列表
 12     dataMat = []
 13     fr = open(fileName, "rb")
 14     for line in fr.readlines():
 15         # 按照制表符切割每行,返回一个列表list
 16         curLine = line.decode("utf-8").strip().split('\t')
 17         # 将切分后的每个列表中的元素,以float形式返回,map()内置函数,返回一个map object【注意,在python2.7版本中map直接返回list】,这里需要再包装个list
 18         fltLine = list(map(float, curLine))  # 通过map(float, curLine)将列表内的每一个数据转换为float类型,然后放入list中
 19         dataMat.append(fltLine)
 20     return dataMat
 21 
 22 
 23 # 两点欧式距离
 24 def distEclud(vecA, vecB):
 25     # np.power(x1,x2)  对x1中的每个元素求x2次方,不会改变x1。
 26     return np.sqrt(np.sum(np.power(vecA - vecB, 2)))
 27 
 28 
 29 # 随机找到3个中心点的位置坐标,返回一个3*2的矩阵
 30 def randCent(dataSet, k):
 31     # 返回dataSet列数,2列
 32     n = np.shape(dataSet)[1]
 33     '''
 34         centerids是一个3*2的矩阵,用于存储三个中心点的坐标
 35     '''
 36     centerids = np.mat(np.zeros((k, n)))
 37     for j in range(n):
 38         # 统计所有行每一列的最小值
 39         minJ = min(dataSet[:, j])
 40         # 所有行每列最大值与最小值的差值
 41         rangeJ = float(max(dataSet[:, j]) - minJ)
 42         # np.random.rand(k,1) 产生k行1列的数组,里面的数据是0~1的浮点型 随机数。
 43         array2 = minJ + rangeJ * np.random.rand(k, 1)
 44         # 转换成k*1矩阵 赋值给centerids
 45         # centerids[:, j] = np.mat(array2)
 46         centerids[:, j] = array2
 47     return centerids
 48 
 49 
 50 def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
 51     # 计算矩阵所有 行数  m=80
 52     m = np.shape(dataSet)[0]
 53     # zeros((m,2)) 创建一个80行,2列的二维数组
 54     # numpy.mat 将二维数组转换成矩阵  【类别号,当前点到类别号中心点的距离】
 55     clusterAssment = np.mat(np.zeros((m, 2)))
 56     # createCent找到K个随机中心点坐标
 57     centerids = createCent(dataSet, k)
 58     #     print centerids
 59     clusterChanged = True
 60     while clusterChanged:
 61         clusterChanged = False
 62         # 遍历80个数据到每个中心点的距离
 63         for i in range(m):
 64             # np.inf float的最大值,无穷大
 65             minDist = np.inf
 66             # 当前点属于的类别号
 67             minIndex = -1
 68             # 每个样本点到三个中心点的距离
 69             for j in range(k):
 70                 # x = centerids[j,:]
 71                 # print x
 72                 # 返回两点距离的值 centerids[j, :]是三个中心点,dataSet[i, :]是样本中的每个点
 73                 distJI = distMeas(centerids[j, :], dataSet[i, :])
 74                 if distJI < minDist:
 75                     # 当前最小距离的值
 76                     minDist = distJI
 77                     # 当前最小值属于哪个聚类
 78                     minIndex = j
 79             # 有与上次迭代计算的当前点的类别不相同的点
 80             if clusterAssment[i, 0] != minIndex:
 81                 clusterChanged = True
 82             # 将当前点的类别号和最小距离 赋值给clusterAssment的一行
 83             clusterAssment[i, :] = minIndex, minDist
 84         for cent in range(k):
 85             # array = clusterAssment[:,0].A==cent
 86             # result = np.nonzero(clusterAssment[:,0].A==cent)[0]
 87             # clusterAssment[:,0].A 将0列 也就是类别号转换成数组
 88             # clusterAssment[:,0].A==cent 返回的是一列,列中各个元素是 True或者False,True代表的是当前遍历的cent类别
 89             # np.nonzero(clusterAssment[:,0].A==cent)  返回数组中值不为False的元素对应的行号下标数组 和列号下标数组
 90             # currNewCenter 取出的是对应是当前遍历cent类别的 所有行数据组成的一个矩阵
 91             currNewCenter = dataSet[np.nonzero(clusterAssment[:, 0].A == cent)[0]]  # clusterAssment[:, 0].A是将clusterAssment[:, 0]转成array数组,[:, 0]表示对所有的行取第一列
 92             # numpy.mean 计算矩阵的均值,axis=0计算每列的均值,axis=1计算每行的均值。
 93             # 这里是每经过一次while计算都会重新找到各个类别中中心点坐标的位置  ,axis = 0 是各个列求均值
 94             centerids[cent, :] = np.mean(currNewCenter, axis=0)
 95             # 返回 【 当前三个中心点的坐标】 【每个点的类别号,和到当前中心点的最小距离】
 96     return centerids, clusterAssment
 97 
 98 if __name__ == '__main__':
 99     # numpy.mat 将数据转换成80*2的矩阵
100     dataMat = np.mat(loadDataSet('./testSet.txt'))
101     k = 3
102     # centerids 三个中心点的坐标。clusterAssment 每个点的类别号|到当前中心点的最小距离
103     centerids, clusterAssment = kMeans(dataMat, k, distMeas=distEclud, createCent=randCent)
104     print(centerids)
105     print(clusterAssment)

运行结果:

[[-2.46154315  2.78737555]
 [ 2.87916148  2.54065409]
 [-0.68321373 -2.968607  ]]
[[1.         2.12886068]
 [0.         1.17900336]
 [1.         4.17969841]
 [2.         4.71295505]
 [1.         1.94477093]
 [0.         1.67362246]
 [2.         1.18188929]
 [2.         3.06753609]
 [1.         0.96893225]
 [0.         0.80372102]
 [2.         3.98448001]
 [2.         2.10768253]
 [1.         1.40131626]
 [0.         0.37244653]
 [2.         2.84967758]
 [2.         1.03672953]
 [1.         0.96780218]
 [0.         1.76136981]
 [2.         3.64745539]
 [2.         2.60428396]
 [1.         0.63749452]
 [0.         0.71431155]
 [2.         3.06349942]
 [2.         2.7268031 ]
 [1.         1.73446256]
 [0.         0.95299726]
 [2.         3.40136033]
 [2.         3.33258554]
 [1.         1.05044206]
 [0.         2.01403167]
 [2.         1.93550277]
 [2.         3.07374815]
 [1.         0.85533934]
 [0.         1.24263474]
 [1.         3.67962042]
 [2.         1.96850502]
 [1.         2.82869331]
 [0.         1.76834366]
 [2.         3.53336343]
 [2.         3.16752963]
 [1.         1.55634792]
 [0.         0.28264306]
 [2.         4.05601598]
 [2.         1.91474539]
 [1.         0.84293455]
 [0.         0.95587941]
 [2.         3.86840903]
 [2.         3.12525834]
 [1.         0.70438474]
 [0.         1.62430415]
 [2.         2.81032715]
 [2.         3.76748552]
 [1.         2.75102005]
 [0.         2.39406258]
 [2.         3.3201695 ]
 [2.         3.32609886]
 [1.         0.69395963]
 [0.         0.154283  ]
 [2.         2.55604156]
 [2.         2.56020016]
 [1.         0.05368144]
 [0.         0.14007598]
 [2.         4.28753047]
 [2.         2.11157349]
 [1.         1.51214357]
 [0.         1.15372603]
 [2.         2.99193835]
 [2.         1.97261219]
 [1.         0.82976405]
 [0.         0.79065148]
 [2.         3.77095664]
 [2.         3.99386969]
 [1.         1.93235148]
 [0.         0.44855365]
 [2.         5.3674754 ]
 [2.         2.26336341]
 [1.         0.50280822]
 [0.         0.50980516]
 [1.         4.59317314]
 [2.         4.22274427]]

2、采用写好的算法自动实现聚类,KMeansByScikitlearn.py代码如下:

  1 # encoding:utf-8
  2 
  3 import numpy as np
  4 """
  5 手动实现聚类
  6 """
  7 
  8 # 将每行数据放入一个数组内列表,返回一个二维列表
  9 
 10 def loadDataSet(fileName):
 11     # 创建空列表
 12     dataMat = []
 13     fr = open(fileName, "rb")
 14     for line in fr.readlines():
 15         # 按照制表符切割每行,返回一个列表list
 16         curLine = line.decode("utf-8").strip().split('\t')
 17         # 将切分后的每个列表中的元素,以float形式返回,map()内置函数,返回一个map object【注意,在python2.7版本中map直接返回list】,这里需要再包装个list
 18         fltLine = list(map(float, curLine))  # 通过map(float, curLine)将列表内的每一个数据转换为float类型,然后放入list中
 19         dataMat.append(fltLine)
 20     return dataMat
 21 
 22 
 23 # 两点欧式距离
 24 def distEclud(vecA, vecB):
 25     # np.power(x1,x2)  对x1中的每个元素求x2次方,不会改变x1。
 26     return np.sqrt(np.sum(np.power(vecA - vecB, 2)))
 27 
 28 
 29 # 随机找到3个中心点的位置坐标,返回一个3*2的矩阵
 30 def randCent(dataSet, k):
 31     # 返回dataSet列数,2列
 32     n = np.shape(dataSet)[1]
 33     '''
 34         centerids是一个3*2的矩阵,用于存储三个中心点的坐标
 35     '''
 36     centerids = np.mat(np.zeros((k, n)))
 37     for j in range(n):
 38         # 统计所有行每一列的最小值
 39         minJ = min(dataSet[:, j])
 40         # 所有行每列最大值与最小值的差值
 41         rangeJ = float(max(dataSet[:, j]) - minJ)
 42         # np.random.rand(k,1) 产生k行1列的数组,里面的数据是0~1的浮点型 随机数。
 43         array2 = minJ + rangeJ * np.random.rand(k, 1)
 44         # 转换成k*1矩阵 赋值给centerids
 45         # centerids[:, j] = np.mat(array2)
 46         centerids[:, j] = array2
 47     return centerids
 48 
 49 
 50 def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
 51     # 计算矩阵所有 行数  m=80
 52     m = np.shape(dataSet)[0]
 53     # zeros((m,2)) 创建一个80行,2列的二维数组
 54     # numpy.mat 将二维数组转换成矩阵  【类别号,当前点到类别号中心点的距离】
 55     clusterAssment = np.mat(np.zeros((m, 2)))
 56     # createCent找到K个随机中心点坐标
 57     centerids = createCent(dataSet, k)
 58     #     print centerids
 59     clusterChanged = True
 60     while clusterChanged:
 61         clusterChanged = False
 62         # 遍历80个数据到每个中心点的距离
 63         for i in range(m):
 64             # np.inf float的最大值,无穷大
 65             minDist = np.inf
 66             # 当前点属于的类别号
 67             minIndex = -1
 68             # 每个样本点到三个中心点的距离
 69             for j in range(k):
 70                 # x = centerids[j,:]
 71                 # print x
 72                 # 返回两点距离的值 centerids[j, :]是三个中心点,dataSet[i, :]是样本中的每个点
 73                 distJI = distMeas(centerids[j, :], dataSet[i, :])
 74                 if distJI < minDist:
 75                     # 当前最小距离的值
 76                     minDist = distJI
 77                     # 当前最小值属于哪个聚类
 78                     minIndex = j
 79             # 有与上次迭代计算的当前点的类别不相同的点
 80             if clusterAssment[i, 0] != minIndex:
 81                 clusterChanged = True
 82             # 将当前点的类别号和最小距离 赋值给clusterAssment的一行
 83             clusterAssment[i, :] = minIndex, minDist
 84         for cent in range(k):
 85             # array = clusterAssment[:,0].A==cent
 86             # result = np.nonzero(clusterAssment[:,0].A==cent)[0]
 87             # clusterAssment[:,0].A 将0列 也就是类别号转换成数组
 88             # clusterAssment[:,0].A==cent 返回的是一列,列中各个元素是 True或者False,True代表的是当前遍历的cent类别
 89             # np.nonzero(clusterAssment[:,0].A==cent)  返回数组中值不为False的元素对应的行号下标数组 和列号下标数组
 90             # currNewCenter 取出的是对应是当前遍历cent类别的 所有行数据组成的一个矩阵
 91             currNewCenter = dataSet[np.nonzero(clusterAssment[:, 0].A == cent)[0]]  # clusterAssment[:, 0].A是将clusterAssment[:, 0]转成array数组,[:, 0]表示对所有的行取第一列
 92             # numpy.mean 计算矩阵的均值,axis=0计算每列的均值,axis=1计算每行的均值。
 93             # 这里是每经过一次while计算都会重新找到各个类别中中心点坐标的位置  ,axis = 0 是各个列求均值
 94             centerids[cent, :] = np.mean(currNewCenter, axis=0)
 95             # 返回 【 当前三个中心点的坐标】 【每个点的类别号,和到当前中心点的最小距离】
 96     return centerids, clusterAssment
 97 
 98 if __name__ == '__main__':
 99     # numpy.mat 将数据转换成80*2的矩阵
100     dataMat = np.mat(loadDataSet('./testSet.txt'))
101     k = 3
102     # centerids 三个中心点的坐标。clusterAssment 每个点的类别号|到当前中心点的最小距离
103     centerids, clusterAssment = kMeans(dataMat, k, distMeas=distEclud, createCent=randCent)
104     print(centerids)
105     print(clusterAssment)

运行结果:

x= [[-5.19811282e+00  6.41869316e-01]
 [-5.75229538e+00  4.18627111e-01]
 [-1.08448984e+01 -7.55352273e+00]
 ...
 [ 1.36105255e+00 -9.07491863e-01]
 [-3.54141108e-01  7.12241630e-01]
 [ 1.88577252e+00  1.41185693e-03]] <class 'numpy.ndarray'> y= [1 1 0 ... 2 2 2] <class 'numpy.ndarray'>
y_pred :  [2 2 1 ... 0 0 0]
dataArray type = <class 'numpy.ndarray'>

图形绘制效果:

 

posted @ 2021-03-09 21:29  大数据程序员  阅读(1020)  评论(0编辑  收藏  举报