数据文件:
链接:https://pan.baidu.com/s/1E0Hkj1ORxu-1zT6J2VAd0g
提取码:ckwr
机器学习kmeans算法用代码实现:
#!/user/bin/env python3
# -*- coding: utf-8 -*-
# @Author : Crystal
import numpy as np
import matplotlib.pyplot as plt
dataSet = np.genfromtxt('testSet1.txt')
x_data = dataSet[:,0]
y_data = dataSet[:,1]
plt.scatter(x_data,y_data)
print(dataSet.shape)
'''
上述过程的伪代码表示如下:
(1)创建k个点作为起始质心(初始化质心)
(2)当任意一个点的簇分配结果发生改变时
对数据集中的每个数据点
对每个质心
计算质心与数据点之间的距离
将数据点分配到距其最近的簇
对每一个簇,计算簇中所有点的均值并将均值作为质心
'''
k = 4
def eduDistance(vector1, vector2):
# print(sum(((vector1 - vector2) ** 2)))
return np.sqrt(sum((vector1 - vector2) ** 2))
# (1)初始化质心
def initCentroids(data, k):
#获取行数及列数
numSamples, dim = data.shape
# k个质心,因为是存放质心的数据,所有列数和样本点的列数一样
#生成一个四行二列的数组
centroids = np.zeros((k, dim))
# print(centroids)
# 随机生成k个质心
for i in range(k):
#随机生成一个存在的索引,通过随机的索引选取随机的值作为质心
index = int(np.random.uniform(0, numSamples))
centroids[i] = data[index]
print('cen:',centroids)
return centroids
# (2)计算每个样本点到簇中心的举例
def kmeans(data, k):
# 计算样本点的个数
#索引0,及数据的行数,即数据个数
numSamples = data.shape[0]
# 定于簇分配结果矩阵,第一列保存样本点属于那个簇,第二列保存样本点和当前所属簇的误差
#生成临时矩阵,用于存放误差
clusterData = np.array(np.zeros((numSamples, 2)))
# print(clusterData)
# 决定簇质心是否发生改变的量
clusterChanged = True
# 初始化质心
#获取生成质心函数返回的对象
centroids = initCentroids(data, k)
l = 0
while clusterChanged: # 当=true才会执行
clusterChanged = False
for i in range(numSamples): # 遍历所有的样本点;(选择先遍历所有的质心会比较麻烦)
# 最小距离
minDist = 100000
# 定义样本所属的簇
minIndex = 0
# print('minDist',minDist)
# 循环计算每一个质心与该样本点的距离
for j in range(k):
distance = eduDistance(data[i], centroids[j])
# 如果计算的距离小于最小距离,则更换最小距离和所属的簇
# 如果计算的距离小于最小距离,则证明该行数据距离第j个质心更近
if distance < minDist:
minDist = distance
clusterData[i, 1] = minDist
# 更换样本所属的簇
minIndex = j
# clusterData[i,0] = minIndex#这两行代码不能写在这里,写在这里的化会陷入死循环
# clusterChanged = True
# print(clusterData[i,0])
# print(minIndex)
#寻找了最小距离之后,需要更换样本点所属的质心
if clusterData[i, 0] != minIndex:
clusterChanged = True
clusterData[i, 0] = minIndex
# 更换质心
for j in range(k):
# 获取第j个簇所有样本所在的索引
cluster_index = np.nonzero(clusterData[:, 0] == j)
# print(cluster_index)
# 第j个簇所有的样本点
pointInCluster = data[cluster_index]
# 计算质心
# print('22:',centroids[j, :])
#将质心更换为所属簇样本点的平均值
centroids[j, :] = np.mean(pointInCluster, axis=0)
# print('33:',centroids[j, :])
print('cen2:',centroids)
#不断更换质心,直至所有样本点的所属簇与最小距离对应的簇相同
#后将这些簇样本点的平均值作为最后的质心
return centroids, clusterData
def showCluster(data, k, centroids, clusterData):
numSamples, dim = data.shape
if dim != 2:
print("dimension of your data is not 2!")
return 1
# 用不同类别展示各个颜色
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', ', 'pr']
if k > len(mark):
print("your k is too large!")
return 1
# 画样本点
for i in range(numSamples):
markIndex = int(clusterData[i, 0])
plt.plot(data[i, 0], data[i, 1], mark[markIndex])
# 用不同颜色形状来表示各个质心
mark = ['+r', '+b', '+g', '+k', '^b', '+b', 'sb', 'db', ', 'pb']
for i in range(k):
plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize=60)
plt.show()
centroids, clusterData = kmeans(dataSet, k)
#判断是否正常执行
if np.isnan(centroids).any():
print('Error')
else:
print('cluster complete')
showCluster(dataSet, k, centroids, clusterData)