聚类cluster

一,k均值算法

(一)自己写程序

举例,在excel中有四个点的坐标如下,表示样本集 D = ( x 1 , x 2 , x 3 , x 4 ) D=(x_1,x_2,x_3,x_4) D=(x1,x2,x3,x4)(分别对应下图中的最左边标签对应的数, x 1 = ( 2.2 , 2.3 ) . . . x_1=(2.2,2.3)... x1=(2.2,2.3)...)
在这里插入图片描述
现在将这四个点画出来

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()

在这里插入图片描述
随机选择两个样本作为初始均值向量,(机器学习西瓜书中随机选样本集中的数,而此处是随机生成范围内的数,未必是样本集中存在的 x 1 到 x 4 x_1到x_4 x1x4):
在上面得到了点的横纵坐标之后(即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])还是矩阵,是 1 × 1 1\times 1 1×1矩阵。
在这里插入图片描述
经过float之后变成浮点数。
测试一下

test = randcenters(dataSet,2)

在这里插入图片描述
所以这里得到的两个质心就是初始均值向量,即
μ 1 = ( 5.000 , 4.939 ) ; μ 2 = ( 3.924 , 6.698 ) \mu _1=(5.000,4.939);\mu_2=(3.924,6.698) μ1=(5.000,4.939);μ2=(3.924,6.698)
现在计算上面的数据集到质心的距离(欧氏距离)

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)

结果是新的聚类中心,即 μ 1 = ( 2.6 , 2.7 ) , μ 2 = ( 8.15 , 7.5 ) \mu_1=(2.6,2.7),\mu_2=(8.15,7.5) μ1=(2.6,2.7),μ2=(8.15,7.5)
在这里插入图片描述
最后输出聚类结果图片
图片分析部分不做进一步讲解,完整代码如下

#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
关于sklearn库可以参考这篇文章:https://blog.csdn.net/u014248127/article/details/78885180,
作者写得很详细
也可以初步扫一下这个:https://blog.csdn.net/Mr_Cat123/article/details/84594032

import numpy as np
import xlrd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

workbook = xlrd.open_workbook('C:/users/Lenovo/Desktop/test.xlsx')
sheet = workbook.sheet_by_name('Sheet1')

data_x = sheet.col_values(0)
data_y = sheet.col_values(1)
dataSet = np.mat([data_x,data_y]).T


dataSet_arr = np.array(dataSet)
print(dataSet_arr)
model = KMeans(n_clusters=2) #n_cluster即上面的k值,表示有多少个类

y_pred = model.fit_predict(dataSet_arr)
plt.scatter(dataSet_arr[:,0],dataSet_arr[:,1],c=y_pred)
plt.show()

这里输出的y_pred为下图
在这里插入图片描述
表示0,1是一类,2,3是一类。
结果如下
在这里插入图片描述
参考文献
1,https://www.cnblogs.com/eczhou/p/7860424.html
2,机器学习实践第十章
3,https://blog.csdn.net/u014248127/article/details/78885180

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值