文章目录

  • 1.序言
  • 2.K均值算法
    • 2.1简介
    • 2.2算法过程
  • 3.实现代码
    • 主函数
    • 导入数据集
    • 初始化聚类中心
    • 样本聚类
    • 更新聚类中心
    • 判断是否更新
    • 绘制效果图
    • 代码整合

1.序言

本人是一名刚升大二的学生,最近刚接触机器学习,当学到这些算法以后就想试试用自己现有的能力来实现他们,我选择了相对容易理解的K均值聚类算法进行实现,相信很多小伙伴也都有过这种想法,所以决定将我实现算法的过程和代码分享出来,这也是我第一次写博客,希望能给跟我一样正在学习的同学带来帮助,同时也欢迎各路前辈提出优化方案和意见。

2.K均值算法

2.1简介

k均值算法是机器学习中一个经典的分类算法,通过设立中心点,将与之最近的样本归为一类,从而达到分类的效果,再不停地利用均值计算新的中心点,反复如此,直至达到最佳的分类效果。
如图则是实现效果

2.2算法过程

想要实现一个算法,了解它的具体流程和原理是必须的,所以在实现之前先了解一下此算法是如何运行的.
第一步:初始化聚类中心在运行整个算法前,需要有一组中心点来作为最初中心点,以便在此基础上进行更新,初始化中心点可以是随机的,具体方法将在代码中讲解

第二步:根据中心点对样本进行分类计算样本与每个中心点的距离,将该样本分给离它最近的中心点那一类,当所有样本计算完后即完成了算法的第一次分类

第三步:计算新的聚类中心因为第二步已经分好了类,现在只用对每个类中的所有样本求均值,将得到的均值作为该类别新的聚类中心

第四步:比较前后聚类中心这里比较前后的聚类中心是为了了解中心点的变化情况以判断是否需要继续更新,刚开始的变化也许会很大,通过不停的重复更新,中心点的前后变化会越来越小,这里我们就可以设定一个程度,当变化程度小于我们设定的程度时,我们就可以认为当前的聚类中心不需要再更新

注:若需要更新中心点,则需要重新进行第二到第四步,直至不需要更新后方可进行第五步

第五步:绘制聚类效果图通过绘制效果图可以更直观地判断自己的的分类个数和设定程度是否合适

以上则是算法实现的大致流程,接下来就来看看用代码将如何对算法进行实现

3.实现代码

主函数

主函数的内容与2.2中的算法过程基本一致就不做过多叙述

if __name__ == '__main__':k = 3print("第一步:调用数据集")sample_data = load_data(file_path="E:\\pythonproject\\clustering-algorethm\\data")print("第二步:初始化聚类中心")old_cluster_center = initialize_cluster_center(data=sample_data, k=k)print("初始化聚类中心如下")print(old_cluster_center)print("第三步:聚类并更新中心点")center_update_pro = center_update()c = np.shape(sample_data)[1]true_center = np.mat(np.zeros((k,c)))count = 0while True:#聚类结果collect_result = center_update_pro.collect(data=sample_data, old_center=old_cluster_center, k=k)print("聚类结果如下")print(collect_result)#计算新的聚类中心new_cluster_center = center_update_pro.new_point_calculate(collect_result)#判断是否继续更新result = center_update_pro.change_judge(last_point=old_cluster_center, now_point=new_cluster_center)if result == 1:count += 1print(f"更新 {count} 次后完成更新")print("保存最终聚类中心点")true_center = new_cluster_centerprint(f"如下为最终中心点{true_center}")np.savetxt("E:\\pythonproject\\clustering-algorethm\\finish_data.txt" ,np.c_[collect_result])print(collect_result)print("绘制聚类效果图")center_update_pro.draw( sample_data,true_center, collect_result )breakelse:#新旧中心点更替old_cluster_center = new_cluster_centercount += 1print(f"更新 {count} 次")continue

导入数据集

该算法用于数据的分类,所以首先要导入准备好的数据集,本章的数据样本来源于UCI上的小麦种子数据集。

#调用数据集
def load_data(file_path):f = open(file_path)data = []for line in f.readlines():row = []lines = line.strip().split()for i in lines:row.append(float(i))data.append(row)f.close()return np.mat(data)

这里将数据集以矩阵的形式保存是为了后续能利用矩阵的运算规则更方便的进行计算

初始化聚类中心

#初始化聚类中心
def initialize_cluster_center(data , k):sum = np.shape(data)[1]my_center = np.mat(np.zeros((k,sum)))#生成零矩阵储存聚类中心信息for i in range(sum): # 遍历每一个特征,在每个特征上取一个最大值与最小值之间的随机值xmin = np.min(data[:, i])xrange = np.max(data[:, i]) - xminmy_center[:, i] = xmin*np.mat(np.ones((k,1))) + np.random.rand(k, 1) * xrangereturn my_center

初始化的方法是遍历每一个特征的所有样本,分别得到每个特征的最大值和最小值,以二者之差作为变化范围,用最小值加上一个0-1的随机值与最大值的乘积方可得到最小值与最大值之间的一个随机值来作为初始值,每个特征均如此便可成功初始化聚类中心

样本聚类

本章分类中所用距离为欧氏距离

这里将数据分为三部分拼接是为了方便在后续操作中方便分出哪些属于哪个类别

    def collect(self , data , old_center,k):#聚类m, n = np.shape(data)  # m为样本个数,n为特征个数label_1 = np.mat(np.zeros((n)))label_2 = np.mat(np.zeros((n)))label_3 = np.mat(np.zeros((n)))  # 创造三个零矩阵用于储存分类结果for i in range(m):  # 遍历样本label = 0min_distance = np.inf#初始化最小距离为正无穷for j in range(k):  # 分别计算此样本与各个中心的距离并找出最小值distance = np.power(data[i,] - old_center[j,], 2).sum()distance = math.sqrt(distance)if distance < min_distance:min_distance = distancelabel = j + 1if label == 1:label_1 = np.row_stack((label_1, data[i, :]))if label == 2:label_2 = np.row_stack((label_2, data[i, :]))if label == 3:label_3 = np.row_stack((label_3, data[i, :]))  # 根据类型填入相应矩阵# 在每个样本最后加一个类别元素,以方便计算新的聚类中心时将各组分开label_1 = np.delete(label_1, 0, axis=0)oth_1 = np.mat(np.ones((np.shape(label_1)[0],1)))label_1 = np.column_stack((label_1 , oth_1))label_2 = np.delete(label_2, 0, axis=0)oth_2 = np.mat(np.ones((np.shape(label_2)[0],1)))*2label_2 = np.column_stack((label_2 , oth_2))label_3 = np.delete(label_3, 0, axis=0)oth_3 = np.mat(np.ones((np.shape(label_3)[0],1)))*3label_3 = np.column_stack((label_3 , oth_3))label = np.row_stack((label_1, label_2, label_3))#将三个类垂直拼接为一个矩阵返回return label

更新聚类中心

获得聚类样本后便通过均值计算新的聚类中心

    def new_point_calculate(self, data):m, n = np.shape(data)label_1 = np.mat(np.zeros((n)))label_2 = np.mat(np.zeros((n)))label_3 = np.mat(np.zeros((n)))#用于放置各类样本for l in range(m):#分类放置if data[l,-1] == 1:label_1 = np.row_stack((label_1, data[l, :]))#将该样本放入对应矩阵if data[l,-1] == 2:label_2 = np.row_stack((label_2, data[l, :]))if data[l,-1] == 3:label_3 = np.row_stack((label_3, data[l, :]))#删除类别元素,恢复矩阵格式label_1 = np.delete(label_1, -1, axis=1)label_2 = np.delete(label_2, -1, axis=1)label_3 = np.delete(label_3, -1, axis=1)m1,n1 = np.shape(label_1)m2,n2 = np.shape(label_2)m3,n3 = np.shape(label_3)center_1 = np.mat(np.zeros((1,n1)))center_2 = np.mat(np.zeros((1,n2)))center_3 = np.mat(np.zeros((1,n3)))for i in range(n1):sum_1 = label_1[:,i].sum()/m1center_1[0,i] = sum_1#计算中心点1的第i个特征for i in range(n2):sum_2 = label_2[:,i].sum()/m2center_2[0,i] = sum_2for i in range(n3):sum_3 = label_3[:,i].sum()/m3center_3[0,i] = sum_3new_point = np.row_stack((center_1, center_2, center_3))return new_point

判断是否更新

本章判断更新是以前后几个中心的欧式距离的平均值来作为判断依据,可以通过更改代码中最后一个if条件来调整变化范围

    def change_judge(self, last_point, now_point):#判断是否继续更新中心m,n = np.shape(last_point)distance = 0for i in range(m):#计算第i个中心的距离distance += np.power(last_point[i,:] - now_point[i,:], 2).sum()distance += math.sqrt(distance)distance = distance/m #m个中心点前后距离差的平均值作为中心点变化的整体变化距离if distance < 0.05:#通过调整该值来设置中心点最低变化距离return 1#完成else:return 0#未完成

绘制效果图

调用matplotlib中的scatter函数进行绘制

 def draw(self,point_data, center, sub_center):Myfig = plt.figure()axes = Myfig.add_subplot(111)length = len(point_data)print(length)for a in range(length):if sub_center[a, -1] == 1:axes.scatter(point_data[a, 2], point_data[a, 3], color='m', alpha=0.4)if sub_center[a, -1] == 2:axes.scatter(point_data[a, 2], point_data[a, 3], color='b', alpha=0.4)if sub_center[a, -1] == 3:axes.scatter(point_data[a, 2], point_data[a, 3], color='g', alpha=0.4)for i in range(len(center)):axes.scatter(center[i, 2], center[i, 3], color='red', marker='p')plt.xlabel('X')plt.ylabel('Y')plt.title('kmeans-JYZ')plt.show()

代码整合

import matplotlib.pyplot as plt
import numpy as np
import math#调用数据集
def load_data(file_path):f = open(file_path)data = []for line in f.readlines():row = []lines = line.strip().split()for i in lines:row.append(float(i))data.append(row)f.close()return np.mat(data)#初始化聚类中心
def initialize_cluster_center(data , k):sum = np.shape(data)[1]my_center = np.mat(np.zeros((k,sum)))#生成零矩阵储存聚类中心信息for i in range(sum): # 遍历每一个特征,在每个特征上取一个最大值与最小值之间的随机值xmin = np.min(data[:, i])xrange = np.max(data[:, i]) - xminmy_center[:, i] = xmin*np.mat(np.ones((k,1))) + np.random.rand(k, 1) * xrangereturn my_centerclass center_update(object):#创造中心点更新类def draw(self,point_data, center, sub_center):Myfig = plt.figure()axes = Myfig.add_subplot(111)length = len(point_data)print(length)for a in range(length):if sub_center[a, -1] == 1:axes.scatter(point_data[a, 2], point_data[a, 3], color='m', alpha=0.4)if sub_center[a, -1] == 2:axes.scatter(point_data[a, 2], point_data[a, 3], color='b', alpha=0.4)if sub_center[a, -1] == 3:axes.scatter(point_data[a, 2], point_data[a, 3], color='g', alpha=0.4)for i in range(len(center)):axes.scatter(center[i, 2], center[i, 3], color='red', marker='p')plt.xlabel('X')plt.ylabel('Y')plt.title('kmeans-JYZ')plt.show()def change_judge(self, last_point, now_point):#判断是否继续更新中心m,n = np.shape(last_point)distance = 0for i in range(m):#计算第i个中心的距离distance += np.power(last_point[i,:] - now_point[i,:], 2).sum()distance += math.sqrt(distance)distance = distance/m#m个中心点前后距离差的平均值作为中心点变化的整体变化距离if distance < 0.05:#通过调整该值来设置中心点最低变化距离return 1#完成else:return 0#未完成def new_point_calculate(self, data):m, n = np.shape(data)label_1 = np.mat(np.zeros((n)))label_2 = np.mat(np.zeros((n)))label_3 = np.mat(np.zeros((n)))#用于放置各类样本for l in range(m):#分类放置if data[l,-1] == 1:label_1 = np.row_stack((label_1, data[l, :]))#将该样本放入对应矩阵if data[l,-1] == 2:label_2 = np.row_stack((label_2, data[l, :]))if data[l,-1] == 3:label_3 = np.row_stack((label_3, data[l, :]))#删除类别元素,恢复矩阵格式label_1 = np.delete(label_1, -1, axis=1)label_2 = np.delete(label_2, -1, axis=1)label_3 = np.delete(label_3, -1, axis=1)m1,n1 = np.shape(label_1)m2,n2 = np.shape(label_2)m3,n3 = np.shape(label_3)center_1 = np.mat(np.zeros((1,n1)))center_2 = np.mat(np.zeros((1,n2)))center_3 = np.mat(np.zeros((1,n3)))for i in range(n1):sum_1 = label_1[:,i].sum()/m1center_1[0,i] = sum_1#计算中心点1的第i个特征for i in range(n2):sum_2 = label_2[:,i].sum()/m2center_2[0,i] = sum_2for i in range(n3):sum_3 = label_3[:,i].sum()/m3center_3[0,i] = sum_3new_point = np.row_stack((center_1, center_2, center_3))return new_pointdef collect(self , data , old_center,k):#聚类m, n = np.shape(data)  # m为样本个数,n为特征个数label_1 = np.mat(np.zeros((n)))label_2 = np.mat(np.zeros((n)))label_3 = np.mat(np.zeros((n)))  # 创造三个零矩阵用于储存分类结果for i in range(m):  # 遍历样本label = 0min_distance = np.inf#初始化最小距离为正无穷for j in range(k):  # 分别计算此样本与各个中心的距离并找出最小值distance = np.power(data[i,] - old_center[j,], 2).sum()distance = math.sqrt(distance)if distance < min_distance:min_distance = distancelabel = j + 1if label == 1:label_1 = np.row_stack((label_1, data[i, :]))if label == 2:label_2 = np.row_stack((label_2, data[i, :]))if label == 3:label_3 = np.row_stack((label_3, data[i, :]))  # 根据类型填入相应矩阵# 在每个样本最后加一个类别元素,以方便计算新的聚类中心时将各组分开label_1 = np.delete(label_1, 0, axis=0)oth_1 = np.mat(np.ones((np.shape(label_1)[0],1)))label_1 = np.column_stack((label_1 , oth_1))label_2 = np.delete(label_2, 0, axis=0)oth_2 = np.mat(np.ones((np.shape(label_2)[0],1)))*2label_2 = np.column_stack((label_2 , oth_2))label_3 = np.delete(label_3, 0, axis=0)oth_3 = np.mat(np.ones((np.shape(label_3)[0],1)))*3label_3 = np.column_stack((label_3 , oth_3))label = np.row_stack((label_1, label_2, label_3))#将三个类垂直拼接为一个矩阵返回return labelif __name__ == '__main__':k = 3print("第一步:调用数据集")sample_data = load_data(file_path="E:\\pythonproject\\clustering-algorethm\\data")print("第二步:初始化聚类中心")old_cluster_center = initialize_cluster_center(data=sample_data, k=k)print("初始化聚类中心如下")print(old_cluster_center)print("第三步:聚类并更新中心点")center_update_pro = center_update()c = np.shape(sample_data)[1]true_center = np.mat(np.zeros((k,c)))count = 0while True:#聚类结果collect_result = center_update_pro.collect(data=sample_data, old_center=old_cluster_center, k=k)print("聚类结果如下")print(collect_result)#计算新的聚类中心new_cluster_center = center_update_pro.new_point_calculate(collect_result)#判断是否继续更新result = center_update_pro.change_judge(last_point=old_cluster_center, now_point=new_cluster_center)if result == 1:count += 1print(f"更新 {count} 次后完成更新")print("保存最终聚类中心点")true_center = new_cluster_centerprint(f"如下为最终中心点{true_center}")np.savetxt("E:\\pythonproject\\clustering-algorethm\\finish_data.txt" ,np.c_[collect_result])print(collect_result)print("绘制聚类效果图")# center_update_pro.draw(data = collect_result  , center = true_center)center_update_pro.draw( sample_data,true_center, collect_result )breakelse:#新旧中心点更替old_cluster_center = new_cluster_centercount += 1print(f"更新 {count} 次")continue

以上便是我这次实现算法的全部过程,欢迎指导。
初始化思路借鉴于 https://blog.csdn.net/weixin_41744192/article/details/113736788
绘制图像借鉴于https://blog.csdn.net/weixin_41744192/article/details/113736788

python实现机器学习算法——K均值聚类算法相关推荐

  1. python图像分割_基于K均值聚类算法的Python图像分割

    1个K均值算法 实际上,K-means算法是一种非常简单的算法,与算法思想或特定实现无关. 通过以一定方式测量样本之间的相似度,并迭代更新聚类中心,它属于无监督分类. 当聚类中心不再移动或移动差异小于 ...

  2. matlab实现k-l算法,K均值聚类算法的MATLAB实现

    K-means算法是最简单的一种聚类算法.算法的目的是使各个样本与所在类均值的误差平方和达到最小(这也是评价K-means算法最后聚类效果的评价标准) K-means聚类算法的一般步骤: 初始化.输入 ...

  3. Thinking in SQL系列之五:数据挖掘K均值聚类算法与城市分级

    原创: 牛超   2017-02-21   Mail:10867910@qq.com 引言:前一篇文章开始不再介绍简单算法,而是转到数据挖掘之旅.感谢CSDN将我前一篇机器学习C4.5决策树算法的博文 ...

  4. python(scikit-learn)实现k均值聚类算法

    k均值聚类算法原理详解 示例为链接中的例题 直接调用python机器学习的库scikit-learn中k均值算法的相关方法 from sklearn.cluster import KMeans imp ...

  5. k均值聚类算法python_K均值和其他聚类算法:Python快速入门

    k均值聚类算法python This post was originally published here 这篇文章最初发表在这里 Clustering is the grouping of obje ...

  6. 机器学习之无监督学习-K均值聚类算法

    机器学习之无监督学习-K均值聚类算法 对于无监督学习,有两类重要的应用,一个是聚类,一个是降维.我们今天主要学习聚类中的K均值聚类. 我们先看看下图,图a为原始的数据点,我们想要对图a的数据点进行分类 ...

  7. 机器学习实战-61:K均值聚类算法(K-Means)

    K均值聚类算法(K-Means) 深度学习原理与实践(开源图书)-总目录,建议收藏,告别碎片阅读! 机器学习分为监督学习.无监督学习和半监督学习(强化学习).无监督学习最常应用的场景是聚类(clust ...

  8. Python金融数据挖掘 第11章 复习思考题1 (聚类)给出一个数据集data_multivar.txt,里面有200个点坐标,在平面坐标系下可以画出它的散点图,用K均值聚类算法来训练模型,分4类。

    1.题目 给出一个数据集data_multivar.txt,里面有200个点坐标,在平面坐标系下可以画出它的散点图,如图11-12所示. data_multivar.txt 图11-12 数据集 da ...

  9. k均值聚类算法(K Means)及其实战案例

    算法说明 K均值聚类算法其实就是根据距离来看属性,近朱者赤近墨者黑.其中K表示要聚类的数量,就是说样本要被划分成几个类别.而均值则是因为需要求得每个类别的中心点,比如一维样本的中心点一般就是求这些样本 ...

  10. k均值聚类算法原理和(TensorFlow)实现

    顾名思义,k均值聚类是一种对数据进行聚类的技术,即将数据分割成指定数量的几个类,揭示数据的内在性质及规律. 我们知道,在机器学习中,有三种不同的学习模式:监督学习.无监督学习和强化学习: 监督学习,也 ...

最新文章

  1. 数据库备份到文件服务器,数据库文件备份到云服务器上
  2. ASPNET服务器控件之一
  3. linux搜索有哪些文件夹,Linux常见几个查找命令
  4. 万物皆对象java_又一次认识java(一) ---- 万物皆对象
  5. 剑指offer--重建二叉树
  6. springboot前端传参date类型后台处理方式
  7. 【MyBatis框架】mybatis和spring整合
  8. 舰船目标检测的学习笔记
  9. SCI论文降重技巧盘点 - 易智编译EaseEditing
  10. Windows10+VS2019+OpenGL安装配置详解
  11. EXCEL常用函数之统计函数
  12. MSP430F149的看门狗定时器
  13. KTV信息管理系统+点歌系统(WPF)
  14. 树莓派2使用TSL2561
  15. Java8新特性之空指针异常的克星Optional类
  16. 兼容edge、谷歌和火狐浏览器的滚动条样式纯css实现
  17. C# 数字转汉字(一二三)
  18. 谈谈一些有趣的CSS题目(九)-- 巧妙的实现 CSS 斜线
  19. 即时通登陆显示服务器失败,即时通中网页出现应用程序中的服务器错误是怎么回事...
  20. 转:Python处理音频信号实战 : 手把手教你实现音乐流派分类和特征提取

热门文章

  1. MATLAB2020b下载和安装
  2. 计算机程序设计员技能试题,计算机程序设计员试题及答案[1]
  3. vmware7序列号
  4. 漫画:什么是二分查找?(修订版)
  5. 用PPT就可以做印章?是的,超简单超逼真,教你一分钟搞定
  6. dreamweaver php网站模板,用DreamWeaver模板工具批量制作网页
  7. 模块化机房建设指导书_模块化机房建设方案解析
  8. java ftl_.ftl文件 是什么文件 freemaker
  9. python电影爬取并下载_python爬取电影并下载
  10. 爬取豆瓣电影top250