k均值聚类 注释

试编程实现k均值聚类算法,设置三组不同的初始中心点,在西瓜数据集4.0上进行实验比较

代码全是《机器学习》上的,只是将其整合到了一起,能够运行手写体识别。
内容大部分进行了注释,可能有些注释不够精准或者不容理解,见谅!

代码:

import numpy as np #用来调整数组和矩阵
import matplotlib as mpl #用来设置字体和正负号
import matplotlib.pyplot as plt #画图框
import warnings #用来设置警告

dataMat= [[0.697, 0.460],[0.774, 0.376],[0.634, 0.264],[0.608, 0.318],\
        [0.556, 0.215],[0.430, 0.237],[0.481, 0.149],[0.437, 0.211],\
        [0.666, 0.091],[0.243, 0.267],[0.245, 0.057],[0.343, 0.099],\
        [0.639, 0.161],[0.657, 0.198],[0.360, 0.370],[0.593, 0.042],\
        [0.719, 0.103],[0.359, 0.188],[0.339, 0.241],[0.282, 0.257],\
        [0.748, 0.232],[0.714, 0.346],[0.483, 0.312],[0.478, 0.437],\
        [0.525, 0.369],[0.751, 0.489],[0.532, 0.472],[0.473, 0.376],\
        [0.725, 0.445],[0.446, 0.459]]  #输入数据

def distEclud(vecA, vecB): #计算距离
    return np.sqrt(np.sum(np.power(vecA - vecB, 2)))

def randCent(dataSet, k): #构建质心
    warnings.simplefilter("ignore")  #将警告忽略掉
    n = np.shape(dataSet)[1] #记录矩阵的宽度
    centroids = np.mat(np.zeros((k, n))) #生成一个矩阵用来存放质心
    for j in range(n): 
        minJ = min (dataSet[:,j])
        rangeJ = float(max(dataSet[:, j]) - minJ) #确定随机点再数据集内
        centroids[:, j] = minJ + rangeJ * np.random.rand(k, 1) # 构建簇质心
    return centroids
  
def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    m = np.shape(dataSet)[0] # 矩阵行数
    clusterAssment = np.mat(np.zeros((m, 2))) #记录簇索引和误差
    centroids = createCent(dataSet, k) #质心
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDist = np.inf #设置一个无穷大值
            minIndex = -1 #用来标记分类情况
            for j in range(k):
                distJI = distMeas(centroids[j, :], dataSet[i, :]) #距离,开始对数据点进行分类
                if distJI < minDist:
                    minDist = distJI
                    minIndex = j
                    
            if clusterAssment[i, 0] != minIndex:#如果此点在分类结果簇中的簇索引值与计算所得的最小簇索引值不等
                clusterChanged = True
            clusterAssment[i, :] = minIndex, minDist**2#更新簇分配结果矩阵中该点对应的簇索引和最小距离
        for cent in range(k):
            ptsInClust = dataSet[np.nonzero(clusterAssment[:, 0].A == cent)[0]]]#获取簇分配结果矩阵中属于当前cent簇的所有索引列表,并对应到数据集中的点,全部取出放入新的列表
            centroids[cent, :] = np.mean(ptsInClust, axis=0) #对得到的列表按列取均值,作为该簇的最新的质心放入簇质心列表
    return centroids, clusterAssment

def testKmeans(k):
    global dataMat
    dataMat = np.mat(dataMat)
    myCentroids, clustAssing = kMeans(dataMat, k)
    print ('myCentroids:\n', myCentroids)
    mpl.rcParams['font.sans-serif'] = [u'SimHei'] # 指定显示字体
    mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像中负号'-'显示为方块的问题
    plt.figure(1, facecolor='white') # 创建一个新图形, 背景色设置为白色
plt.scatter(np.array(myCentroids[:, 0]), np.array(myCentroids[:, 1]), marker='+', alpha=1, s=150) #绘制质心
    for cent in range(k): #开始绘制西瓜数据的点
        xing=['o','v','^','1','2','3','*','s','+','D','x'] #设置形状
        ptsInClust = dataMat[np.nonzero(clustAssing[:, 0].A == cent)[0]]
        plt.scatter(np.array(ptsInClust[:, 0]), np.array(ptsInClust[:, 1]), marker=xing[cent], alpha=1) #设置画点时的形状
    plt.show()

if __name__=='__main__':
  k_numy=int(input("请输入质心数:"))
  testKmeans(k_numy)  #画图

运行结果

质心为6:
在这里插入图片描述
质心为5:
在这里插入图片描述
质心为3:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值