K-means聚类算法

2023-05-16

K-means 是我们最常用的基于欧式距离的聚类算法,其认为两个目标的距离越近,相似度越大。

本文大致思路为:先介绍经典的牧师-村名模型来引入 K-means 算法,然后介绍算法步骤和时间复杂度,通过介绍其优缺点来引入算法的调优与改进,最后我们利用之前学的 EM 算法,对其进行收敛证明。

1. 算法

1.1. 牧师-村民模型

K-means 有一个著名的解释:牧师—村民模型:

有四个牧师去郊区布道,一开始牧师们随意选了几个布道点,并且把这几个布道点的情况公告给了郊区所有的村民,于是每个村民到离自己家最近的布道点去听课。
听课之后,大家觉得距离太远了,于是每个牧师统计了一下自己的课上所有的村民的地址,搬到了所有地址的中心地带,并且在海报上更新了自己的布道点的位置。
牧师每一次移动不可能离所有人都更近,有的人发现A牧师移动以后自己还不如去B牧师处听课更近,于是每个村民又去了离自己最近的布道点……
就这样,牧师每个礼拜更新自己的位置,村民根据自己的情况选择布道点,最终稳定了下来。

我们可以看到该牧师的目的是为了让每个村民到其最近中心点的距离和最小。

1.2. 算法步骤

所以 K-means 的算法步骤为:

  • 选择初始化的 k 个样本作为初始聚类中心a = a_1, a_2, \cdots, a_k
  • 针对数据集中每个样本x_i,计算它到 k 个聚类中心的距离并将其分到距离最小的聚类中心所对应的类中;
  • 针对每个类别a_j,重新计算它的聚类中心a_j = \frac{1}{\left | c_i \right |} \sum_{x \in c_j} x(即属于该类的所有样本的质心);
  • 重复上面 2 3 两步操作,直到达到某个中止条件(迭代次数、最小误差变化等)。

1.3. 复杂度

我们先看下伪代码:

获取数据 n 个 m 维的数据
随机生成 K 个 m 维的点
while(t)
    for(int i=0;i < n;i++)
        for(int j=0;j < k;j++)
            计算点 i 到类 j 的距离
    for(int i=0;i < k;i++)
        1. 找出所有属于自己这一类的所有数据点
        2. 把自己的坐标修改为这些数据点的中心点坐标
end

时间复杂度:O(tknm),其中,t 为迭代次数,k 为簇的数目,n 为样本点数,m 为样本点维度。

空间复杂度:O(m(n+k)),其中,k 为簇的数目,m 为样本点维度,n 为样本点数。

2. 优缺点

2.1. 优点

  • 容易理解,聚类效果不错,虽然是局部最优, 但往往局部最优就够了;
  • 处理大数据集的时候,该算法可以保证较好的伸缩性;
  • 当簇近似高斯分布的时候,效果非常不错;
  • 算法复杂度低。

2.2. 缺点

  • K 值需要人为设定,不同 K 值得到的结果不一样;
  • 对初始的簇中心敏感,不同选取方式会得到不同结果;
  • 对异常值敏感;
  • 样本只能归为一类,不适合多分类任务;
  • 不适合太离散的分类、样本类别不平衡的分类、非凸形状的分类。

3. 算法调优与改进

针对 K-means 算法的缺点,我们可以有很多种调优方式:如数据预处理(去除异常点),合理选择 K 值,高维映射等。以下将简单介绍:

3.1. 数据预处理

K-means 的本质是基于欧式距离的数据划分算法,均值和方差大的维度将对数据的聚类产生决定性影响。所以未做归一化处理和统一单位的数据是无法直接参与运算和比较的。常见的数据预处理方式有:数据归一化,数据标准化。

此外,离群点或者噪声数据会对均值产生较大的影响,导致中心偏移,因此我们还需要对数据进行异常点检测。

3.2. 合理选择K值

K 值的选取对 K-means 影响很大,这也是 K-means 最大的缺点,常见的选取 K 值的方法有:手肘法、Gap statistic 方法。

手肘法:

当 K < 3 时,曲线急速下降;当 K > 3 时,曲线趋于平稳,通过手肘法我们认为拐点 3 为 K 的最佳值。

手肘法的缺点在于需要人工看不够自动化,所以我们又有了 Gap statistic 方法,这个方法出自斯坦福大学的几个学者的论文:Estimating the number of clusters in a data set via the gap statistic

其中D_k为损失函数,这里E(logD_k)指的是logD_k的期望。这个数值通常通过蒙特卡洛模拟产生,我们在样本里所在的区域中按照均匀分布随机产生和原始样本数一样多的随机样本,并对这个随机样本做 K-Means,从而得到一个D_k 。如此往复多次,通常 20 次,我们可以得到 20 个logD_k 。对这 20 个数值求平均值,就得到了E(logD_k)的近似值。最终可以计算 Gap Statisitc。而 Gap statistic 取得最大值所对应的 K 就是最佳的 K。

由图可见,当 K=3 时,Gap(K) 取值最大,所以最佳的簇数是 K=3。

Github 上一个项目叫 gap_statistic ,可以更方便的获取建议的类簇个数。

3.3. 采用核函数

基于欧式距离的 K-means 假设了了各个数据簇的数据具有一样的的先验概率并呈现球形分布,但这种分布在实际生活中并不常见。面对非凸的数据分布形状时我们可以引入核函数来优化,这时算法又称为核 K-means 算法,是核聚类方法的一种。核聚类方法的主要思想是通过一个非线性映射,将输入空间中的数据点映射到高位的特征空间中,并在新的特征空间中进行聚类。非线性映射增加了数据点线性可分的概率,从而在经典的聚类算法失效的情况下,通过引入核函数可以达到更为准确的聚类结果。

3.4. K-means++

我们知道初始值的选取对结果的影响很大,对初始值选择的改进是很重要的一部分。在所有的改进算法中,K-means++ 最有名。

K-means++ 算法步骤如下所示:

  • 随机选取一个中心点a_1
  • 计算数据到之前 n 个聚类中心最远的距离D(x),并以一定概率\frac{D(x)^2}{\sum D(x)^2}选择新中心点a_i
  • 重复第二步。

简单的来说,就是 K-means++ 就是选择离已选中心点最远的点。这也比较符合常理,聚类中心当然是互相离得越远越好。

但是这个算法的缺点在于,难以并行化。所以 k-means II 改变取样策略,并非按照 k-means++ 那样每次遍历只取样一个样本,而是每次遍历取样 k 个,重复该取样过程log(n)次,则得到klog(n)个样本点组成的集合,然后从这些点中选取 k 个。当然一般也不需要log(n)次取样,5 次即可。

3.5. ISODATA

ISODATA 的全称是迭代自组织数据分析法。它解决了 K 的值需要预先人为的确定这一缺点。而当遇到高维度、海量的数据集时,人们往往很难准确地估计出 K 的大小。ISODATA 就是针对这个问题进行了改进,它的思想也很直观:当属于某个类别的样本数过少时把这个类别去除,当属于某个类别的样本数过多、分散程度较大时把这个类别分为两个子类别。

4. 收敛证明

我们先来看一下 K-means 算法的步骤:先随机选择初始节点,然后计算每个样本所属类别,然后通过类别再跟新初始化节点。这个过程有没有想到之前介绍的 EM 算法 。

我们需要知道的是 K-means 聚类的迭代算法实际上是 EM 算法。EM 算法解决的是在概率模型中含有无法观测的隐含变量情况下的参数估计问题。在 K-means 中的隐变量是每个类别所属类别。K-means 算法迭代步骤中的 每次确认中心点以后重新进行标记 对应 EM 算法中的 E 步 求当前参数条件下的 Expectation 。而 根据标记重新求中心点 对应 EM 算法中的 M 步 求似然函数最大化时(损失函数最小时)对应的参数

首先我们看一下损失函数的形式:

其中:

为了求极值,我们令损失函数求偏导数且等于 0:

k 是指第 k 个中心点,于是我们有:

可以看出,新的中心点就是所有该类的质心。

EM 算法的缺点就是,容易陷入局部极小值,这也是 K-means 有时会得到局部最优解的原因。

5. 开源库

5.1. sklearn

import pandas as pd
# 参数初始化
inputfile = r'F:\...\consumption_data.xls'  # 销量及其他属性数据
outputfile = r'F:\...\data_type.xls'  # 保存结果的文件名
k = 3  # 聚类的类别
iteration = 500  # 聚类最大循环次数
data = pd.read_excel(inputfile, index_col = 'Id')  # 读取数据
data_zs = 1.0*(data - data.mean())/data.std()  # 数据标准化
 
from sklearn.cluster import KMeans
model = KMeans(n_clusters = k, n_init = 4, max_iter = iteration,random_state=1234)  # 分为k类,并发数4
model.fit(data_zs)  # 开始聚类
 
# 简单打印结果
r1 = pd.Series(model.labels_).value_counts()  # 统计各个类别的数目
r2 = pd.DataFrame(model.cluster_centers_)  # 标准化数据的聚类中心
r2.columns=data.mean().index #修改r2的列,方便逆标准化计算
r_1 = pd.concat([r2*data.std()+data.mean(), r1], axis = 1) # 横向连接(0是纵向),得到聚类中心对应的类别下的数目
r_1.columns = list(data.columns) + ['类别数目']  # 重命名表头
print(r_1)
 
# 详细输出原始数据及其类别
r = pd.concat([data, pd.Series(model.labels_, index = data.index)], axis = 1)   # 详细输出每个样本对应的类别
r.columns = list(data.columns) + ['聚类类别']  # 重命名表头
# r.to_excel(outputfile)  # 保存结果
 
#同时保存两个结果到xls中
with pd.ExcelWriter(outputfile) as writer:  # doctest: +SKIP
    r_1.to_excel(writer, sheet_name='聚类中心及数目')
    r.to_excel(writer, sheet_name='原始数据聚类类别')
 
 
def density_plot(data):  # 自定义作图函数
  import matplotlib.pyplot as plt
  plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
  plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
  p = data.plot(kind='kde', linewidth = 2, subplots = True, sharex = False)
  [p[i].set_ylabel('密度') for i in range(k)]
  plt.legend()
  plt.tight_layout()
  return plt
 
pic_output = r'F:\...\分群'
# 概率密度图文件名前缀
for i in range(k):
  density_plot(data[r['聚类类别']==i]).savefig('%s%s.png' %(pic_output, i+1))

5.2. pyclustering

from pyclustering.cluster.kmeans import kmeans
from pyclustering.utils.metric import type_metric, distance_metric
 
user_function = lambda point1, point2: point1[0] + point2[0] + 2
metric = distance_metric(type_metric.USER_DEFINED, func=user_function)
 
# create K-Means algorithm with specific distance metric
start_centers = [[4.7, 5.9], [5.7, 6.5]];
kmeans_instance = kmeans(sample, start_centers, metric=metric)
 
# run cluster analysis and obtain results
kmeans_instance.process()
clusters = kmeans_instance.get_clusters()

参考文献

【机器学习】K-means(非常详细) - 知乎

K-means聚类算法-CSDN博客 

K-means聚类自定义距离计算的开源算法选择_小小她爹的博客-CSDN博客 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

K-means聚类算法 的相关文章

  • Python学习2——DBSCAN聚类算法

    一 原理 参考博文 xff1a DBSCAN聚类算法Python实现 徐奕的专栏 CSDN博客 dbscan python https blog csdn net xyisv article details 88918448 DBSCAN是
  • python DBSCAN聚类算法

    文章目录 DBSCAN聚类算法基本思想基本概念工作流程参数选择DBSCAN的优劣势 代码分析 61 61 Matplotlib Pyplot 61 61 61 61 make blobs 61 61 61 61 StandardScaler
  • 【数据挖掘】DBSCAN聚类算法(python实现)

    一 python代码 39 39 39 Author Vici date 2020 5 14 39 39 39 import math 39 39 39 Point类 xff0c 记录坐标x xff0c y和点的名字id 39 39 39
  • 【机器学习】DBSCAN聚类算法(含Python实现)

    文章目录 一 算法介绍二 例子三 Python实现3 1 例13 2 算法参数详解3 3 鸢尾花数据集 一 算法介绍 DBSCAN xff08 Density Based Spatial Clustering of Applications
  • K-means聚类算法

    K means 是我们最常用的基于欧式距离的聚类算法 xff0c 其认为两个目标的距离越近 xff0c 相似度越大 本文大致思路为 xff1a 先介绍经典的牧师 村名模型来引入 K means 算法 xff0c 然后介绍算法步骤和时间复杂度
  • DBSCAN聚类算法

    DBSCAN是一种非常著名的基于密度的聚类算法 其英文全称是 Density Based Spatial Clustering of Applications with Noise xff0c 意即 xff1a 一种基于密度 xff0c 对
  • 聚类、K-Means、例子、细节

    聚类 今天说聚类 xff0c 但是必须要先理解聚类和分类的区别 xff0c 很多业务人员在日常分析时候不是很严谨 xff0c 混为一谈 xff0c 其实二者有本质的区别 分类其实是从特定的数据中挖掘模式 xff0c 作出判断的过程 比如Gm
  • sklearn中的聚类算法K-Means

    1 1 无监督学习与聚类算法 有监督学习 的一部分 xff0c 即是说 xff0c 模型在训练的时候 xff0c 即需要特征矩阵X xff0c 也需要真实标签y 有相当一部分算法属于 无监督学习 xff0c 无监督的算法在训练的时候只需要特
  • Fuzzy C-Means Clustering(模糊C均值)

    别看了 有错的 我懒得改了 强推https www bilibili com video BV18J411a7yY t 61 591 看完你还不会那我也没办法了 算法原理 模糊c 均值聚类算法 fuzzy c means algorithm
  • SKlearn里面的K-means使用详解

    在K Means聚类算法原理中 xff0c 我们对K Means的原理做了总结 xff0c 本文我们就来讨论用scikit learn来学习K Means聚类 重点讲述如何选择合适的k值 1 K Means类概述 在scikit learn
  • 实训 wine数据集_基于wine的K-Means聚类模型研究

    摘要 xff1a 本文通过使用wine数据集来构建K Means聚类模型 xff0c 先对wine数据集的原始样本进行数据预处理 xff0c 得到预处理后的数据作为我们的新数据样本 xff0c 通过sklearn的估计器接收进行学习的数据用
  • k-均值(k-means)及Matlab动态实现

    k 均值 k means 及Matlab实现 注 1 仅适合于数值属性的数据 2 对正态分布 高斯分布 数据聚类效果最佳 1 算法思想 k means算法 也称k 均值算法 它把N个对象划分成k个簇 用簇中对象的均值表示每个簇的中心点 质心
  • 机器学习——聚类算法k-means

    机器学习 聚类算法k means 常见的聚类算法 k means算法 k 均值算法 由簇中样本的平均值来代表整个簇 文章目录 机器学习 聚类算法k means 聚类分析概述 一 k means背景 二 k means算法思想 1 k mea
  • 机器学习——聚类——密度聚类法——OPTICS

    目录 理论部分 1 1 提出背景 1 2 OPTICS算法 1 2 1 基本概念 1 2 2 算法流程 1 2 3 优点 1 2 4 缺点 1 3 其它算法 代码部分 2 1 自行实现 2 2 sklearn实现 理论部分 1 1 提出背景
  • 数据挖掘十大算法(二):K-means聚类算法原理与实现

    参考 1 机器学习 KMeans聚类 K值以及初始类簇中心点的选取 2 K Means算法的研究分析及改进 一 K means算法原理 K means算法是最常用的一种聚类算法 算法的输入为一个样本集 或者称为点集 通过该算法可以将样本进行
  • KMeans算法

    目录 一 基本概念 二 Centroid Initialization Methods 三 Mini Batch K Means 四 找寻最优的聚类数量 4 1 拐点 4 2 silhouette score 轮廓分数 五 Kmeans的优
  • Python机器学习之k-means聚类算法

    1 引言 所谓聚类 就是按照某个特定的标准将一个数据集划分成不同的多个类或者簇 使得同一个簇内的数据对象的相似性尽可能大 同时不再一个簇内的数据对象的差异性也尽可能大 聚类算法属于无监督学习算法的一种 k 均值聚类的目的是 把 n个点 可以
  • 聚类算法(二)--层次聚类法

    本文主要介绍层次聚类法的基本原理 距离计算方法 算法的优缺点 以及R语言实战 一 概述 层次聚类 Hierarchical Clustering 试图在不同层次上对数据集进行划分 从而形成树形的聚类结构 数据集的划分可采用 自底向上 的聚合
  • 层次聚类在MATLAB中实现

    层次聚类在MATLAB中实现 By Yang Liu 1 第一种方法 1 输入要聚类的数据 2 计算各个样本之间的欧氏距离 3 把距离化成矩阵 矩阵中的元素 X i j X ij Xij 表示第i个样本和第j个样
  • 分层聚类算法

    分层聚类算法 转载 看到很多地方都讲到分层聚类法 这到底是什么东东 今天来研究一下 分层聚类法是聚类算法的一种 聚类算法是数据挖掘的核心技术 把数据库中的对象分类是数据挖掘的基本操作 其准则是使属于同一类的个体间距离尽可能小 而不同类个体间

随机推荐

  • 安装CDC drivers 失败原因,记录关键点

    1 驱动版本不对 xff0c 因为CDC drivers 主要调用的是usbser sys 文件 xff0c 需要查看你的c windows system32 drivers下是否有该文件 2 驱动对了 xff0c 但是安装过程中一直提示找
  • Ubuntu 运行文件时,出现 Permission denied

    在Ubuntu下 xff0c 执行sh文件时提示下面信息 xff1a bash xx sh Permission denied 可以尝试以下方法解决 xff1a chmod 777 xx sh 执行其他类型的文件出错时 xff0c 也可以此
  • update.app格式解压工具-ROM定制开发教程

    Github分享工具地址 xff1a https github com Loren Yi update app 使用教程 xff1a 下载huawei unpack exe 到本地目录 讲华为 UPDATE APP放至同一路径 将 UPDA
  • mysql时间和本地时间相差13个小时

    原文地址 https www xiegaosheng com post view id 61 73 mysql时间和本地时间相差13个小时 作者 谢高升 发布 2017 12 15 浏览 0次 mysql时间和本地时间相差13个小时 修改l
  • 美团笔试题(2018.10.09)

    逻辑题20个要快点做 xff0c 然后30个选择考的东西比较多 编程两个 优惠券 有一个满x减的优惠券 xff0c 一共n个商品 xff0c 每个只能选择一次 xff0c 求能使用优惠券的最小价格 就是求n个数选任意几个加起来最接近x且大于
  • AndroidStudio gradle 编译发现阿里云镜像找不到对应jar包https://maven.aliyun.com/nexus/content/repositories/jcenter

    FAILURE Build completed with 4 failures 1 Task failed with an exception What went wrong Execution failed for task 39 app
  • 用PyQt5写了个音乐播放器

    首先先展示一下界面 xff08 不美观但好用 xff09 除了不能看歌词功能该有的都有 xff0c 作为本地播放器还挺好用的 xff0c 界面是用PyQt5做的 下面是源代码 xff1a span class token keyword i
  • Consul+Ocelot搭建微服务实践--IdentityServer集成

    文章目录 1 IdentityServer介绍2 建立IdentityServer2 1 安装IdentityServer42 2 定义配置中心2 2 1 定义Client2 2 2 定义ApiResource2 2 3定义Identity
  • 配置Linux内核版本在线或离线升级(回退)

    在线升级 一 查看系统内核 xff08 当前系统内核为3 10 xff09 uname r 二 确定当前主机能连外网 ping www baidu com 三 导入在线elrepo仓库公钥 rpm import https www elre
  • 深度学习相关网址

    深度学习教学网址 Unsupervised Feature Learning and Deep Learning Tutorial GitHub rasmusbergpalm DeepLearnToolbox Matlab Octave t
  • CentOS Docker安装并使用httpd镜像运行容器

    Docker 是一个开源的应用容器引擎 xff0c 基于 Go 语言 并遵从 Apache2 0 协议开源 CentOS Docker 安装 先卸载旧版本 xff0c 较旧的 Docker 版本称为 docker 或 docker engi
  • 基于神经辐射场NeRF的SLAM方法

    随着2020年NeRF 1 的横空出世 xff0c 神经辐射场方法 xff08 Neural Radiance Fields xff09 如雨后春笋般铺天盖地卷来 NeRF最初用来进行图像渲染 xff0c 即给定相机视角 xff0c 渲染出
  • 有限视角重叠和不准确外参标定下的多相机SLAM的鲁棒初始化

    1 摘要 本文提出了一种当相机只有有限的公共视野和不准确的外参标定情形下的用于多相机视觉SLAM系统的鲁棒初始化方法 有限的共同视野导致只有一些特征可以在相机之间匹配上 离线标定后 xff0c 由于振动或相机错误放置而导致的不准确的外部位姿
  • Unifying Flow, Stereo and Depth Estimation论文阅读

    1 序言 上篇文章中我们提到了一种在线标定光学防抖主摄和ToF方法 其中使用RAFT作为光流估计网络来进行密集匹配 xff0c 本文我们来介绍一种更新的光流估计算法GMFlow xff0c 其被CVPR2022接收为Oral 同时也将介绍其
  • BARF: Bundle-Adjusting Neural Radiance Fields论文阅读

    摘要 神经辐射场 NeRF 可以合成真实世界场景的全新视角的照片 xff0c 其性能优异 xff0c 因此在计算机视觉领域引起较大的兴趣 NeRF的一个限制条件是需要准确相机位姿 本文提出了集束调整神经辐射场 BARF xff0c 可以用不
  • 自动驾驶高精定位

    定位是高等级自动驾驶的基础 xff0c 但在高速NOA和城区NOA等场景中 xff0c 如何能够稳定地在各种工况下实现高精度定位将是个难题 一个常见的问题是 xff1a 高速NOA 城区NOA功能需要实现多高精度的定位 xff1f 需要多高
  • 高精度组合导航里的松耦合、紧耦合、深耦合

    高精度定位 xff0c 是自动驾驶车辆一切丰满理想实现的前提 它用于判断自动驾驶功能是否处于可激活的设计运行条件内 xff1b 它用于支撑自动驾驶车辆的全局路径规划 xff1b 它用于辅助自动驾驶车辆的变道 避障策略 不同的场景特点 不同的
  • 超像素分割

    1 超像素 超像素是把一张图片中具有相似特征的像素进行聚类 xff0c 形成一个更具有代表性的大 像素 这个新的像素可以作为其他图像处理算法的基本单位 xff0c 可以减低图像的维度和异常像素点 目前常用的超像素分割算法有SLIC SEED
  • Numpy使用问题汇总

    1 批量操作 1 1 现象 import numpy as np vec 61 np zeros 10 int indices 61 np array 0 0 vec indices 43 61 1 print vec 上面代码的输出不是
  • K-means聚类算法

    K means 是我们最常用的基于欧式距离的聚类算法 xff0c 其认为两个目标的距离越近 xff0c 相似度越大 本文大致思路为 xff1a 先介绍经典的牧师 村名模型来引入 K means 算法 xff0c 然后介绍算法步骤和时间复杂度