【机器学习】—— K-means聚类算法原理详解 以及 二维、三维数据的K-means聚类Python实现_kmeans三维聚类python-程序员宅基地

技术标签: 机器学习  机器学习笔记  kmeans算法  

一、K-Means聚类算法原理过程

K-means算法的目的概述:K-means聚类算法是比较流行的无监督学习算法,输入无标签的数据,然后将数据聚类成不同的组

我们下面先看看K-means算法的一般过程:
【Step1】:随机初始化K个聚类中心 μ 1 , μ 2 , μ 3 , . . . μ K μ_1, μ_2, μ_3,...μ_K μ1,μ2,μ3,...μK
【Step2】:接下来,重复以下步骤
在这里插入图片描述
下面,我们通过图更加深刻地理解K-means算法的执行过程:
在这里插入图片描述

1.1 K-means聚类的一些细节

1.1.1 样本 x ( i ) x^{(i)} x(i)与中心点 μ k μ_k μk距离的衡量

我们一般用下面的式子来考虑样本 x ( i ) x(i) x(i)与中心点 μ k μ_k μk距离: ∣ ∣ x ( i ) − μ k ∣ ∣ 2 ||x^{(i)} - μ_k||^2 x(i)μk2
而我们就是需要找到令 ∣ ∣ x ( i ) − μ k ∣ ∣ 2 ||x^{(i)} - μ_k||^2 x(i)μk2最小的k值,也即是这个样本 x ( i ) x^{(i)} x(i)所属于的类的中心点

1.1.2 K-means聚类算法的应用场合

对于一些能够肉眼很明显地分辨出几个簇的数据,用K-means聚类算法当然是相当不错的,像上图的情况,但是对于一些数据分离不佳的情况,我们依然是可以用K-means聚类算法来进行分类的。

像下面这个服装经营商的例子:假设我们收集了不同人群的身高和体重,这些数据通常是密密麻麻,难以一眼分辨分离情况的,但是我们依然可以使用K-means聚类

比如说,我们需要设计S、M、L三种尺码的衣服,但是需要预计生产的数量,我们可以用K-means聚类算法把数据分成下面三种:

这样就可以很好地指导我们生产服装的数量

1.1.3 K-means聚类算法的优化目标

想要搞清楚为什么经过有限次数的迭代之后,算法就可以把数据进行分类?那么我们就需要明白算法的优化目标,以及算法是如何优化这个目标的。

而很明显,算法是想让每一样本离它所属的类的中心点的距离比距其他类的中心点的距离都近

我们用函数可以这样表达: J ( c ( 1 ) , . . . , c ( m ) , μ 1 , μ 2 , . . . μ K ) = 1 m ∑ i = 1 m ∣ ∣ x ( i ) − μ c ( i ) ∣ ∣ 2 J(c^{(1)}, ...,c^{(m)}, μ_1, μ_2,...μ_K) = \frac{1}{m}\sum_{i=1}^m||x^{(i)} - μ_{c^{(i)}}||^2 J(c(1),...,c(m),μ1,μ2,...μK)=m1i=1mx(i)μc(i)2
其中,对 c ( m ) c^{(m)} c(m)我需要解释一下: c ( m ) c^{(m)} c(m)就是第m个样本所属的类的中心点的下标k
下面,我们就来看看算法是什么时候偷偷优化了这个函数吧:

大家请翻到前面看看K-means聚类算法的算法步骤:
在这里插入图片描述

1.1.4 随机初始化的要点

还记得我们在算法过程里面的第一步吗:随机选取K个点作为初始化的簇中心点。但是实际上我们并不这样做,我们一般我在样本里面选K个点,让它们作为初始化的簇中心点

但是大家记得一件事情:就是我们的算法有可能会陷入局部最优的情况,也就是说同一个数据集可能会出现很多不同的分类情况,像下面的例子:
在这里插入图片描述
这三种情况都可以满足算法终止的条件,但是有些并不是最好的,遇到这种情况:当K值不大的时候(比如说3,4,5),那么我们可以考虑多次运行程序以求得一个较好的分类

1.1.5 类的数量K的选取

方法一是“肘部法则”,不过并不推荐,这里简单一下:肘部法则就是在使用K-means聚类算法时,我们多选择几个K值,用算法分别试一下这些K值,然后做出优化函数J的曲线,如果曲线长这样:
在这里插入图片描述
那很棒,我们就选取J函数的拐点,也就是上图K = 3的地方作为分类数。因为这样的图形酷似人的手臂,拐点是肘关节,因此叫“肘部法则”
但是,常常事与愿违,我们有时候得到的优化函数曲线可能很平滑,让人根本无法看出拐点emmmm

事实上,K值的选择还是取决于你的实际目的。在用K-means算法时,要好好想想自己用这个算法是要去干嘛的?我所选取的分类数能不能为我后续的工作服务。就像上面服装厂家的例子,如果只能生产S、M、L三种尺码衣服,那么很明显就分成3类好了,分成5类6类7类显然是不合理的

二、二维,三维数据K-means算法的Python实现

先上完整代码:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # 空间三维画图
import random

def K_means(data, K):
  """
  程序说明:
  本函数实现二维和三维数据的K_means聚类算法
  data:输入的数据,维度(m, 2)或者(m, 3)
  K:表示希望分出来的类数
  """
  num = np.shape(data)[0]

  cls = np.zeros([num], np.int)
  
  random_array = np.random.random(size = k)
  random_array = np.floor(random_array*num)
  rarray = random_array.astype(int)
  print('数据集中随机索引', rarray)

  center_point = data[rarray]
  print('初始化随机中心点', center_point)

  change = True  #change表示簇中心是否有过改变,又改变了就需要继续循环程序,没改变则终止程序
  while change:
    for i in range(num):
      temp = data[i] - center_point   #此句执行之后得到的是两个数或三个数:x-x_0,y-y_0或x-x_0, y-y_0, z-z_0
      temp = np.square(temp)          #得到(x-x_0)^2等
      distance = np.sum(temp,axis=1)  #按行相加,得到第i个样本与所有center point的距离
      cls[i] = np.argmin(distance)    #取得与该样本距离最近的center point的下标

    change = False
    for i in range(k):
      # 找到属于该类的所有样本
      club = data[cls==i]
      newcenter = np.mean(club, axis=0)  #按列求和,计算出新的中心点
      ss = np.abs(center_point[i]-newcenter) # 如果新旧center的差距很小,看做他们相等,否则更新之。run置true,再来一次循环
      if np.sum(ss, axis=0) > 1e-4:
          center_point[i] = newcenter
          change = True

  print('K-means done!')
  return center_point, cls

"""
补充一点说明:我们下面左图的代码show_picture函数需要用到的cls,
其实就是一个[1, num]的矩阵,里面的元素就是对应第i个样本所属聚类中心的下标
放在第一个for循环的后面:cls[i] = np.argmin(distance)
因为如果第一个for循环得到的聚类已经是最终结果,那么它也不会执行后面的中心点更新的代码了
"""
def show_picture(data, center_point, cls, k):
  num,dim = data.shape
  color = ['r','g','b','c','y','m','k']
  if dim == 2:
    for i in range(num):
      mark = int(cls[i])
      plt.plot(data[i,0],data[i,1],color[mark]+'o')

    #下面把中心点单独标记出来:
    for i in range(k):
      plt.plot(center_point[i,0],center_point[i,1],color[i]+'x')

  elif dim == 3:
    ax = plt.subplot(111,projection ='3d')
    for i in range(num):
      mark = int(cls[i])
      ax.scatter(data[i,0],data[i,1],data[i,2],c=color[mark])

    for i in range(k):
      ax.scatter(center_point[i,0],center_point[i,1],center_point[i,2],c=color[i],marker='x')
  plt.show()

k=6 ##分类个数
z_MF = []
yl_OSNR = []
pn = np.random.normal(0, 10, 6400)

for i in range(6400):
  index_y = random.uniform(15,30) 
  index_z = random.randint(0,3)
  z_MF.append(index_z)
  yl_OSNR.append(index_y)

pn = pn[:, np.newaxis] 
#print(pn)

y = np.array(yl_OSNR)
y = y[:,np.newaxis]
#print(y)

z_MF = np.array(z_MF)
z = z_MF[:,np.newaxis]

temp = np.hstack((pn, y))
#data = np.hstack((temp, z))
#print(data.shape)
center_point,  cls = K_means(temp, k)

show_picture(temp, center_point, cls, k)

下面给大家看看效果:
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44586473/article/details/104158302

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签