聚类cluster
一,k均值算法
(一)自己写程序
举例,在excel中有四个点的坐标如下,表示样本集 (分别对应下图中的最左边标签对应的数,)
现在将这四个点画出来
import numpy as np
import xlrd
import matplotlib.pyplot as plt
workbook = xlrd.open_workbook('C:/users/Lenovo/Desktop/test.xlsx')
sheet = workbook.sheet_by_name('Sheet1')
dot_x = sheet.col_values(0)
dot_y = sheet.col_values(1)
plt.scatter(dot_x,dot_y)
plt.show()
随机选择两个样本作为初始均值向量,(机器学习西瓜书中随机选样本集中的数,而此处是随机生成范围内的数,未必是样本集中存在的):
在上面得到了点的横纵坐标之后(即dot_x,dot_y),现在组合成数据集(注意dot_x,dot_y)都是行矢量,所以组成矩阵数据集后要转置
dot_x = sheet.col_values(0)
dot_y = sheet.col_values(1)
dataSet = np.mat([dot_x,dot_y]).T
现在开始随机生成聚类中心
def randcenters(dataSet,k): #输入数据集和k
n = np.shape(dataSet)[1] #查看k有多少列,实际上就是点的坐标的维度,比如两维x,y
centroids = np.matrix(np.zeros((k,n))) #zeros得到的是数组,一定要变成矩阵,否则centroids[:,0]并不表示第一列
for J in range(n):
rangeJ = float(max(dataSet[:,J])-min(dataSet[:,J])) #求出范围,注意 A
centroids[:,J] = min(dataSet[:,J]) + rangeJ*np.random.rand(k,1) #生成聚类中心
return centroids
上面中注意“A”部分:rangeJ=float…, 此处float一定不能少,因为max(dataSet[:,J])还是矩阵,是矩阵。
经过float之后变成浮点数。
测试一下
test = randcenters(dataSet,2)
所以这里得到的两个质心就是初始均值向量,即
现在计算上面的数据集到质心的距离(欧氏距离)
def distEclud(vecA,vecB): #输入的是数组,不能用list形式
return np.sqrt(sum(np.power(vecA-vecB,2)))
开始着手聚类算法:
def kMeans(dataSet,k): #不妨以k=2举例
m = np.shape(dataSet)[0] #显示数据集的个数,即有多少个数据需要处理
ClustDist = np.mat(np.zeros((m,2))) #聚类最小距离的索引值和此距离。第一列放索引值,第二列放最小距离
clustercents = randcenters(dataSet,k) #调用生成随机聚类
clusterChanged = True
while clusterChanged: #用while进行迭代
clusterChanged = False # 设置初始为False
# 计算每个数据与随机初始得到的质心的距离,比如假设只有两个质心,即k=2,那么找到每个数据分别到这两个
# 点的距离,并保留距离小的那个。比如x1到质心Cent1和质心Cent2的距离分别为l1和l2,且l1<l2.那么
# 就保留l1并记下l1的位置(索引)
for i in range(m):
distlist = [distEclud(clustercents[j,:],dataSet[i,:]) for j in range(k)] #计算每个数据与随机质心间的距离
minDist = min(distlist) #找到最小距离
minIndex = distlist.index(minDist) #最小距离对应的索引值
if ClustDist[i,0] != minIndex: #找到了一个新的聚类中心,因为是for i in...循环,只要数据集中有一个新中心就变True
clusterChanged = True
ClustDist[i,:] = minIndex,minDist #放置找到的新的最小距离
for cent in range(k): #假设k=2,即两个聚类中心
dInx = np.nonzero(ClustDist[:,0].A == cent)[0]
ptsInClust = dataSet[dInx] #选择数据中的数
clustercents[cent,:] = np.mean(ptsInClust,axis=0)
return clustercents, ClustDist
完整代码如下:
def randcenters(dataSet,k): #输入数据集和k
n = np.shape(dataSet)[1] #查看k有多少列,实际上就是点的坐标的维度,比如两维x,y
centroids = np.matrix(np.zeros((k,n))) #zeros得到的是数组,一定要变成矩阵,否则centroids[:,0]并不表示第一列
for J in range(n):
rangeJ = float(max(dataSet[:,J])-min(dataSet[:,J])) #求出范围,注意 A
centroids[:,J] = min(dataSet[:,J]) + rangeJ*np.random.rand(k,1) #生成聚类中心
return centroids
def distEclud(vecA,vecB):
return np.sqrt(sum(np.power(vecA-vecB,2)))
def kMeans(dataSet,k): #不妨以k=2举例
m = np.shape(dataSet)[0] #显示数据集的个数,即有多少个数据需要处理
ClustDist = np.mat(np.zeros((m,2))) #聚类最小距离的索引值和此距离。第一列放索引值,第二列放最小距离
clustercents = randcenters(dataSet,k) #调用生成随机聚类
clusterChanged = True
while clusterChanged: #用while进行迭代
clusterChanged = False # 设置初始为False
# 计算每个数据与随机初始得到的质心的距离,比如假设只有两个质心,即k=2,那么找到每个数据分别到这两个
# 点的距离,并保留距离小的那个。比如x1到质心Cent1和质心Cent2的距离分别为l1和l2,且l1<l2.那么
# 就保留l1并记下l1的位置(索引)
for i in range(m):
distlist = [distEclud(clustercents[j,:],dataSet[i,:]) for j in range(k)] #计算每个数据与随机质心间的距离
minDist = min(distlist) #找到最小距离
minIndex = distlist.index(minDist) #最小距离对应的索引值
if ClustDist[i,0] != minIndex: #找到了一个新的聚类中心,因为是for i in...循环,只要数据集中有一个新中心就变True
clusterChanged = True
ClustDist[i,:] = minIndex,minDist #放置找到的新的最小距离
for cent in range(k): #假设k=2,即两个聚类中心
dInx = np.nonzero(ClustDist[:,0].A == cent)[0]
ptsInClust = dataSet[dInx] #选择数据中的数
clustercents[cent,:] = np.mean(ptsInClust,axis=0)
return clustercents, ClustDist
workbook = xlrd.open_workbook('C:/users/Lenovo/Desktop/test.xlsx')
sheet = workbook.sheet_by_name('Sheet1')
dot_x = sheet.col_values(0)
dot_y = sheet.col_values(1)
dataSet = np.mat([dot_x,dot_y]).T
k = 2
clustercents,ClustDist = kMeans(dataSet,k)
print(clustercents)
结果是新的聚类中心,即
最后输出聚类结果图片
图片分析部分不做进一步讲解,完整代码如下
#from numpy import *
import numpy as np
import xlrd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
#随机生成聚类中心
def randcenters(dataSet,k): #输入数据集和k
n = np.shape(dataSet)[1] #查看k有多少列,实际上就是点的坐标的维度,比如两维x,y
centroids = np.matrix(np.zeros((k,n))) #zeros得到的是数组,一定要变成矩阵,否则centroids[:,0]并不表示第一列
for J in range(n):
rangeJ = float(max(dataSet[:,J])-min(dataSet[:,J])) #求出范围,注意 A
centroids[:,J] = min(dataSet[:,J]) + rangeJ*np.random.rand(k,1) #生成聚类中心
return centroids
def distEclud(vecA,vecB):
return np.sqrt(sum(np.power(vecA-vecB,2)))
def kMeans(dataSet,k): #不妨以k=2举例
m = np.shape(dataSet)[0] #显示数据集的个数,即有多少个数据需要处理
ClustDist = np.mat(np.zeros((m,2))) #聚类最小距离的索引值和此距离。第一列放索引值,第二列放最小距离
clustercents = randcenters(dataSet,k) #调用生成随机聚类
clusterChanged = True
while clusterChanged: #用while进行迭代
clusterChanged = False # 设置初始为False
# 计算每个数据与随机初始得到的质心的距离,比如假设只有两个质心,即k=2,那么找到每个数据分别到这两个
# 点的距离,并保留距离小的那个。比如x1到质心Cent1和质心Cent2的距离分别为l1和l2,且l1<l2.那么
# 就保留l1并记下l1的位置(索引)
for i in range(m):
distlist = [distEclud(clustercents[j,:],dataSet[i,:]) for j in range(k)] #计算每个数据与随机质心间的距离
minDist = min(distlist) #找到最小距离
minIndex = distlist.index(minDist) #最小距离对应的索引值
if ClustDist[i,0] != minIndex: #找到了一个新的聚类中心,因为是for i in...循环,只要数据集中有一个新中心就变True
clusterChanged = True
ClustDist[i,:] = minIndex,minDist #放置找到的新的最小距离
for cent in range(k): #假设k=2,即两个聚类中心
dInx = np.nonzero(ClustDist[:,0].A == cent)[0]
ptsInClust = dataSet[dInx] #选择数据中的数
clustercents[cent,:] = np.mean(ptsInClust,axis=0)
return clustercents, ClustDist
def color_cluster(dataindx, dataSet, plt):
datalen = len(dataindx)
for indx in range(datalen):
if int(dataindx[indx]) == 0:
plt.scatter(dataSet[indx, 0], dataSet[indx, 1], c='blue', marker='o')
elif int(dataindx[indx]) == 1:
plt.scatter(dataSet[indx, 0], dataSet[indx, 1], c='green', marker='o')
elif int(dataindx[indx]) == 2:
plt.scatter(dataSet[indx, 0], dataSet[indx, 1], c='red', marker='o')
elif int(dataindx[indx]) == 3:
plt.scatter(dataSet[indx, 0], dataSet[indx, 1], c='cyan', marker='o')
def drawScatter(plt, mydata, size=20, color='blue', mrkr='o'):
plt.scatter(mydata.T[0].tolist(), mydata.T[1].tolist(), s=size, c=color, marker=mrkr)
workbook = xlrd.open_workbook('C:/users/Lenovo/Desktop/test.xlsx')
sheet = workbook.sheet_by_name('Sheet1')
dot_x = sheet.col_values(0)
dot_y = sheet.col_values(1)
dataSet = np.mat([dot_x,dot_y]).T
k = 2
clustercents,ClustDist = kMeans(dataSet,k)
print(clustercents)
color_cluster(ClustDist[:, 0:1], dataSet, plt)
drawScatter(plt,clustercents,color='red',mrkr='D')
聚类中心
聚类结果
(二)调用现有库(待续…)
关于sklearn库可以参考这篇文章:https://blog.****.net/u014248127/article/details/78885180,
作者写得很详细
参考文献
1,https://www.cnblogs.com/eczhou/p/7860424.html
2,机器学习实践第十章
3,https://blog.****.net/u014248127/article/details/78885180