当前位置:   article > 正文

机器学习 k-means算法python实现_k均值算法的散点图python

k均值算法的散点图python

(一).算法概念

K-Means算法是一种聚类分析(cluster analysis)的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法。

它的基本思想是,通过迭代寻找K个簇(Cluster)的一种划分方案,使得聚类结果对应的损失函数最小。其中,损失函数可以定义为各个样本距离所属簇中心点的误差平方和:


(二).具体步骤 

通过迭代不断的划分簇和更新聚类中心,直到每个点与其聚类中心的距离之和最小,停止迭代。要预先知道聚类簇的个数num,和初始化聚类中心centre。聚类簇的个数一般已知。而初始化聚类中心的值是随机初始化的。

选择K个点作为初始质心  
repeat  
    将每个点指派到最近的质心,形成K个簇  
    重新计算每个簇的质心  
until 簇不发生变化或达到最大迭代次数  

 其中,距离的计算可以选取欧式距离或曼哈顿距离等等。


 (三).代码实现

1.自定义数据集:

sklearn.datasets.make_classification官网详解:http://sklearn.datasets.make_classification

  1. # 202011000106
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. from sklearn import datasets
  5. # 产生多类单标签数据集,为每个类分配一个或多个正态分布的点集,为测试聚类算法而使用的
  6. # 数据集:
  7. x, y = datasets.make_classification(n_samples=200, # 默认样本个数是100
  8. n_features=2, # 产生的默认特征 n_features 是两种,01
  9. n_informative=2, # 信息特征的数量
  10. n_redundant=0, # 冗余特征的数量
  11. n_repeated=0,
  12. n_classes=3, n_clusters_per_class=1, # 有三个类,每个类有一簇
  13. # 剩余都是默认值
  14. weights=None, flip_y=0.01, class_sep=1.0, hypercube=True, shift=0.0, scale=1.0,
  15. shuffle=True, random_state=0)
  16. # 返回值:xarray of shape [n_samples, n_features]是生成的样本;yarray of shape [n_samples]是每个样本的类成员的整数标签。
  17. plt.scatter(x[:, 0], x[:, 1], c=y)
  18. # 绘制散点图
  19. plt.show()

 生成的散点图如下:

 2.方法实现

  1. def kmeans(datas, num, threshold, maximum):
  2. # datas:输入数据;
  3. # num:聚类个数;
  4. # threshold:阈值;
  5. # maximum:最大迭代次数
  6. # result:最后聚类的结果
  7. result = np.zeros(len(datas))
  8. # 初始化result,np.zeros返回来一个给定形状和类型的用0填充的数组,即一个由2000组成的一维数组
  9. # centre:聚类中心
  10. centre = np.random.random((num, len(datas[0])))
  11. # 返回一个num行2列的浮点数,浮点数都是从0-1之间随机取值,维度是2
  12. for i in np.arange(0, maximum):
  13. # 聚类:
  14. result = classify(datas, centre)
  15. # 对于每一次聚类求中心点:
  16. centre1 = centralization(datas, result, centre)
  17. # 欧氏距离:
  18. dis = distance(centre, centre1)
  19. if dis < 0:
  20. break
  21. centre = centre1
  22. print(centre.shape)
  23. return result
更新聚类归属:
  1. def classify(datas, centre):
  2. d = np.zeros((len(datas), len(centre)))
  3. # 输出结果:
  4. # len(datas)=200; len(centre))=num(聚类个数),即d是一个200*num的数组
  5. for i in np.arange(0, len(datas)):
  6. # 一共200个点,每一个点就都要经过聚类
  7. for j in np.arange(0, len(centre)):
  8. # @矩阵乘法:
  9. d[i][j] = (datas[i] - centre[j]) @ (datas[i] - centre[j])
  10. # 样本和各个质心的距离
  11. result = np.argmin(d, axis=1)
  12. # 返回向量中的最小值的索引,可以按行返回或者按列返回,axis=1按行取最小值,即取得距离哪一个类的距离最近
  13. return result
求和阈值比较的那个数字:
  1. def distance(datas, centre):
  2. d = np.zeros((len(datas), len(centre)))
  3. # 和上面一样
  4. for i in np.arange(0, len(datas)):
  5. for j in np.arange(0, len(centre)):
  6. d[i][j] = (datas[i] - centre[j]) @ (datas[i] - centre[j])
  7. return np.sqrt(np.sum(d))
  8. # np.sqrt返回一个非负平方根;np.sum对d里面的元素求和
更新聚类中心,返回一个新的聚类中心:
  1. def centralization(datas, result, centre):
  2. centre = np.zeros(centre.shape)
  3. # centre.shape输出结果为(3,2),即生成一个3*2的数组
  4. for i, n in zip(result, np.arange(0, len(result))):
  5. # 用序列解包同时遍历多个序列
  6. # https://www.cnblogs.com/Apy-0816/p/11100248.html
  7. centre[i] = centre[i] + datas[n]
  8. for i in np.arange(0, len(centre)):
  9. a = np.sum(result == i)
  10. centre[i] = centre[i] / a
  11. # 更新聚类中心
  12. return centre
  1. result = kmeans(x, 3, 2, 50)
  2. # 输入数据
  3. print(result)
  4. # 打印
  5. plt.scatter(x[:, 0], x[:, 1], c=result)
  6. plt.show()
  7. # 输出

 (四).运行结果


 (五).实验问题

一开始运行的时候,发现如下报错:

 经过查找,发现是使用np.zeros()错误,是因为zeros()的第一个参数是决定数组的规格的,而第二参数是决定数据类型的,改正后的正确代码如下:

d = np.zeros((len(datas), len(centre)))

即添加双重括号即可解决。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/529923
推荐阅读
相关标签
  

闽ICP备14008679号