K-means算法

news2024/11/15 22:49:54

文章目录

  • 1. K-means算法简介
  • 2. K-means算法原理
    • 2.1 算法具体步骤
    • 2.2 k取值方法
      • 2.2.1 手肘法
      • 2.2.2 轮廓系数法
    • 2.3 K-means++
    • 2.4 算法终止条件
  • 3. K-means算法特点
  • 4. K-means算法应用场景
  • 5. K-means算法的Python应用
    • 5.1 K-means算法的Python实现
    • 5.2 sklearn.cluster.Kmeans函数的应用
  • 6. 源码仓库地址

1. K-means算法简介

K-means算法是一种聚类算法,所谓聚类,即根据相似性原则,将具有较高相似度的数据对象划分至同一类簇,将具有较高相异度的数据对象划分至不同类簇。聚类与分类最大的区别在于,聚类过程为无监督过程,即待处理数据对象没有任何先验知识,而分类过程为有监督过程,即存在有先验知识的训练数据集。

2. K-means算法原理

K-means算法解决的问题是,在事先不知道如何分类的情况下(即无监督),让程序根据距离的远近,把N个对象(局部)最优的划分为k个类。它是无监督算法中比较常见的一种算法,原理比较简单易懂。本质是通过循环,不断迭代类中心点,计算各个对象到新的类中心点的距离并根据距离最近的原则重新归类,当类内距离最小、类间距离最大时,即可停止迭代(使用中,常常会限定迭代次数,防止陷入死循环。当达到预先设定得循环次数或类中心点不再发生变化时,最后一次迭代得到的结果,即为最终聚类结果)。

2.1 算法具体步骤

算法具体步骤如下:
第一步:指定聚类类数k(此处涉及k的选择方法);
第二步:选定初始化聚类中心。随机或指定k个对象,作为初始化聚类中心(此处随机选的方法可以升级,以达到更好的聚类效果,比如kmeans++聚类算法);
第三步:得到初始化聚类结果。计算每个对象到k个聚类中心的距离,把每个对象分配给离它最近的聚类中心所代表的类别中,全部分配完毕即得到初始化聚类结果,聚类中心连同分配给它的对象作为一类;
第四步:重新计算聚类中心。得到初始化聚类结果后,重新计算每类的类中心点(计算均值),得到新的聚类中心;
第五步:迭代循环,得到最终聚类结果。重复第三步和第四步,直到满足迭代终止条件。

2.2 k取值方法

结合书本中理论和在实际业务中遇到的情况,总结出以下几点k值的选择方法供参考:
1、如果实际业务中,数据维度不超过三维,可先通过画散点图的方法大致确定聚类数目。
2、工作中,结合业务方需求背景或经验,可敲定聚类数目。如,做用户的RFM模型(k=3)、判断是否为作弊用户(k=2)等。
3、实际业务中做探索性分析时,没有经验等做参考,可使用肘方法(elbow method)确定分类数。此处结合第一部分提到的误差平方和最小来一起理解。要使误差平方和变小,一种方法就是增加类数,这样有助于降低每个类的类内误差平方和,从而降低整体的误差平方和。但若类数太多,一是归类后解释困难,另一个降低类内误差平方和的边际效应可能下降(即增加类数k,误差平方和降低的不显著)。此时,k取误差平方和关于k的曲线的拐点。
4、交叉验证方法。将N个对象分为m个部分,用m-1个部分建立聚类模型,并用剩下的一部分检验聚类质量。
5、轮廓系数法。计算k取不同值时的轮廓系数,选择轮廓系数较接近1的分类数。

下面具体介绍手肘法轮廓系数法

2.2.1 手肘法

核心公式:SSE(sum of the squared errors,误差平方和)

在这里插入图片描述

其中,Ci是第i个簇;x是Ci中的样本点;mi是Ci的质心(Ci中所有样本的均值);SSE是所有样本的聚类误差,代表了聚类效果的好坏。

随着聚类数k的增大,样本划分会更加精细,每个簇的聚合程度会逐渐提高,那么误差平方和SSE自然会逐渐变小。当k小于真实聚类数时,由于k的增大会大幅增加每个簇的聚合程度,故SSE的下降幅度会很大,而当k到达真实聚类数时,再增加k所得到的聚合程度回报会迅速变小,所以SSE的下降幅度会骤减,然后随着k值的继续增大而趋于平缓,也就是说SSE和k的关系图是一个手肘的形状,而这个肘部对应的k值就是数据的真实聚类数。

在这里插入图片描述

显然,肘部对于的k值为4,梯度最大,下降最快,故对于这个数据集的聚类而言,最佳聚类数应该选4。

2.2.2 轮廓系数法

具体方法如下:
1)计算样本i到同簇其他样本的平均距离ai。ai越小,说明样本i越应该被聚类到该簇。将ai称为样本i的簇内不相似度。簇C中所有样本的均值称为簇C的簇不相似度。
2)计算样本i到其他某簇Cj的所有样本的平均距离bij,称为样本i与簇Cj的不相似度。定义为样本i的簇间不相似度:在这里插入图片描述
,bi越大,说明样本i越不属于其他簇。
3)根据样本i的簇内不相似度ai和簇间不相似度bi,定义样本i的轮廓系数。

在这里插入图片描述

轮廓系数范围在[-1,1]之间。该值越大,越合理。si接近1,则说明样本i聚类合理;接近-1,则说明样本i更应该分类到另外的簇;若si近似为0,则说明样本i在两个簇的边界上。

所有样本的si的均值称为聚类结果的轮廓系数,是该聚类是否合理、有效的度量。使用轮廓系数(silhouette coefficient)来确定,选择使系数较大所对应的k值。

2.3 K-means++

我们知道初始值的选取对结果的影响很大,对初始值选择的改进是很重要的一部分。在所有的改进算法中,K-means++最有名。K-means++算法步骤如下所示:(1)随机选取一个中心点a1
(2)计算数据到之前n个聚类中心最远的距离D(x),并以一定概率在这里插入图片描述
选择新中心点ai
(3)重复第二步。

简单的来说,K-means++就是选择离已选中心点最远的点。这也比较符合常理,聚类中心当然是互相离得越远越好。但是这个算法的缺点在于,难以并行化。所以k-meansII改变取样策略,并非按照k-means++那样每次遍历只取样一个样本,而是每次遍历取样k个,重复该取样过程log(n)次,则得到klog(n)个样本点组成的集合,然后从这些点中选取k个。当然一般也不需要log(n)次取样,5次即可。

2.4 算法终止条件

终止条件一般为以下几类:
a、达到预先设定的迭代次数,如20次。
b、类中心点不再发生变化或没有对象被分配给新的类。
c、误差平方和最小,误差平方和公式:在这里插入图片描述
,其中Xi代表被分到第i类的对象集合,μc(i)代表第i个聚类的均值(即类中心),c可以理解为迭代这个步骤,因为c随着迭代而发生变化,所以也是个变量。

在实际编程实现算法时,a常配合着c(误差平方和最小化)一起使用,由于使误差平方和最小有时会陷入死循环或迭代多步类中心变化不大,因此常会限制迭代次数。

3. K-means算法特点

优点:
1)容易理解,聚类效果不错,虽然是局部最优,但往往局部最优就够了。
2)处理大数据集的时候,该算法可以保证较好的伸缩性。
3)当簇近似高斯分布的时候,效果非常不错。
4)算法复杂度低。
5)主要需要调参的参数仅仅是簇数k。

缺点:
1)K值的选取不好把握。
2)结果的好坏依赖于初始类中心的选择。
3)算法常陷入局部最优,更换初始聚类中心后,新的聚类结果可能效果更优。
4)对孤立点敏感,如数据集存在异常突出点,会影响聚类效果。
5)不适合太离散的分类、样本类别不平衡的分类、非凸形状的分类。

4. K-means算法应用场景

1、隐含类别的数据较为平衡的情况,如隐含类别的数据量差别较大,则聚类的效果就较差。
2、数据最好是凸数据,即隐含类别间的差异越大,则聚类效果越好,因为中心点不再变化所需要的迭代次数较少,比较容易收敛。
3、一般作为数据预处理,或者用于辅助分类贴标签使用,因为在已经经过分类的数据上再进行聚类,准确度会非常高。

5. K-means算法的Python应用

5.1 K-means算法的Python实现

以一系列二维点作为原始数据,通过K-means算法来预测新的点属于哪一类。测试代码如下:

# -*- coding:utf-8 -*-
import random

import numpy as np
from matplotlib import pyplot


class K_Means(object):
    # k是分组数;tolerance'中心点误差';max_iter是迭代次数
    def __init__(self, k=2, tolerance=0.0001, max_iter=300):
        self.k_ = k
        self.tolerance_ = tolerance
        self.max_iter_ = max_iter

    def fit(self, data):
        self.centers_ = {}
        for i in range(self.k_):
            self.centers_[i] = data[random.randint(0,len(data))]
        # print('center', self.centers_)
        for i in range(self.max_iter_):
            self.clf_ = {} #用于装归属到每个类中的点[k,len(data)]
            for i in range(self.k_):
                self.clf_[i] = []
            # print("质点:",self.centers_)
            for feature in data:
                distances = [] #装中心点到每个点的距离[k]
                for center in self.centers_:
                    # 欧拉距离
                    distances.append(np.linalg.norm(feature - self.centers_[center]))
                classification = distances.index(min(distances))
                self.clf_[classification].append(feature)

            # print("分组情况:",self.clf_)
            prev_centers = dict(self.centers_)

            for c in self.clf_:
                self.centers_[c] = np.average(self.clf_[c], axis=0)

            # '中心点'是否在误差范围
            optimized = True
            for center in self.centers_:
                org_centers = prev_centers[center]
                cur_centers = self.centers_[center]
                if np.sum((cur_centers - org_centers) / org_centers * 100.0) > self.tolerance_:
                    optimized = False
            if optimized:
                break

    def predict(self, p_data):
        distances = [np.linalg.norm(p_data - self.centers_[center]) for center in self.centers_]
        index = distances.index(min(distances))
        return index


if __name__ == '__main__':
    x = np.array([[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6], [9, 11]])
    k_means = K_Means(k=2)
    k_means.fit(x)
    for center in k_means.centers_:
        pyplot.scatter(k_means.centers_[center][0], k_means.centers_[center][1], marker='*', s=150)

    for cat in k_means.clf_:
        for point in k_means.clf_[cat]:
            pyplot.scatter(point[0], point[1], c=('r' if cat == 0 else 'b'))

    predict = [[2, 1], [6, 9]]
    for feature in predict:
        cat = k_means.predict(feature)
        pyplot.scatter(feature[0], feature[1], c=('r' if cat == 0 else 'b'), marker='x')

    pyplot.show()
 

效果如下:

在这里插入图片描述

上图可见,所有点被分成了两类(圆点):红色和蓝色,预测的点(×)被正确分到了所属类别。

5.2 sklearn.cluster.Kmeans函数的应用

sklearn库使用sklearn.cluster.KMeans函数来实现K-Means算法,其函数原型如下:

sklearn.cluster.KMeans(n_clusters=8,*,init='k-means++', n_init=10,max_iter=300,tol=0.0001,precompute_distances='deprecated',verbose=0,random_state=None,copy_x=True,n_jobs='deprecated',algorithm='auto')

参数说明:

n_clusters:int, default=8,簇的个数,即你想聚成几类。

init:{‘k-means++’, ‘random’, ndarray, callable}, default=’k-means++’,初始簇中心的获取方法,‘k-means ++’:以一种聪明的方式为k-mean聚类选择初始聚类中心,以加快收敛速度。有关更多详细信息,请参见k_init中的注释部分。‘random’:n_clusters从初始质心的数据中随机选择观察(行)。如果传递了ndarray,则其形状应为(n_clusters,n_features),并给出初始中心。如果传递了callable,则应使用参数X,n_clusters和随机状态并返回初始化。

n_init:int, default=10,获取初始簇中心的更迭次数,k均值算法将在不同质心种子下运行的次数。

max_iter:int, default=300,最大迭代次数(因为kmeans算法的实现需要迭代),单次运行的k均值算法的最大迭代次数。

tol:float, default=1e-4,容忍度,即kmeans运行准则收敛的条件,关于Frobenius范数的相对容差,该范数表示两个连续迭代的聚类中心的差异,以声明收敛。

precompute_distances:{‘auto’, True, False}, default=‘auto’,是否需要提前计算距离,这个参数会在空间和时间之间做权衡,如果是True 会把整个距离矩阵都放到内存中,auto 会默认在数据样本大于featurs*samples 的数量大于12e6 的时候False,False 时核心实现的方法是利用Cpython 来实现的。

verbose:int, default=0,冗长模式(不太懂是啥意思,反正一般不去改默认值)。

random_state:int, RandomState instance, default=None,确定质心初始化的随机数生成。使用整数使随机性具有确定性。

copy_x:bool, default=True, 对是否修改数据的一个标记,如果True,即复制了就不会修改数据。bool 在scikit-learn 很多接口中都会有这个参数的,就是是否对输入数据继续copy 操作,以便不修改用户的输入数据。这个要理解Python 的内存机制才会比较清楚。

n_job:sint, default=None,并行设置。

algorithm:{‘auto’, ‘full’, ‘elkan’}, default=‘auto’,kmeans的实现算法,经典的EM风格算法是’full’的。通过使用三角形不等式,‘elkan’变异对于定义良好的聚类的数据更有效。但是,由于分配了额外的形状数组(n_samples,n_clusters),因此需要更多的内存。目前,‘auto’(保持向后兼容性)选择’elkan’,但为了更好的启发式,将来可能会更改。

测试代码如下:

# 导入可视化工具包
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd

X=load_iris().data
clf = KMeans(n_clusters=3,random_state=0)
clf.fit(X)
label = clf.predict(X)

# 颜色和标签列表
colors_list = ['red', 'blue', 'green']
labels_list = ['1','2','3']
x=X
for i in range(3):
    plt.scatter(x[label==i,0], x[label== i,1], s=100,c=colors_list[i],label=labels_list[i])
    
# 聚类中心点
plt.scatter(clf.cluster_centers_[:,0],clf.cluster_centers_[:,1], s=300,c='black',label='Centroids')

plt.legend()
plt.xlabel('Annual Income (k$)')
plt.ylabel('Spending Score (1-100)')
plt.show()
 

效果如下:

在这里插入图片描述

6. 源码仓库地址

🌼 图像处理、机器学习的常用算法汇总

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/657209.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】timerfd——定时器

文章目录 前言认识 timerfdAPI timerfdAPI clock 官方示例简单使用epoll实现 前言 在 Linux 系统编程中,使用 timerfd 实现定时器功能是一种更加可靠、高效、灵活的方式。本文是对 timerfd 的简单使用,不涉及太过深入知识,熟练掌握几个常用 …

该死的科斯定理和三条保命原则

* * * 原创:刘教链 * * * 号外:今天在“刘教链”公众号次条发表了《内参:美联储下半年加息时间表和路径》,一号两文无法直接链接,请大家点击公众号卡片进入文章列表打开阅读。星球会员可以直接打开知识星球或discord …

企业级微服务架构实战项目--xx优选3-mq+nacos+es实现上下架

一 nacosmqes实现上下架 1.1 架构图 1.2 工程结构 1.3 核心代码流程 1.3.1 请求product模块 2.修改数据库,推送rabbitmq中 1.3.2 rabbitmq的工具类 1.3.3 search模块中rabbit客户端订阅信息 1.监听器监听信息 2.调用相应的上下架方法 2.1 调用product模块&…

c#网编实验五--WCF和TCP消息通信实验

分别编写服务端和客户端程序,利用基于WCF的TCP技术,实现在线聊天功能,完成在线用户列表管理,消息发送、接收的功能。 在同一个解决方案中,分别编写服务端程序和客户端程序,利用TCP实现简单的群聊功能。 具…

【领域驱动设计专题】一文带领你透视DDD领域驱动模型的本质和设计原理分析指南(构建领域知识)

一文带领你透视DDD领域驱动模型的本质和设计原理分析指南 前提介绍传统的软件设计方案瀑布设计方法敏捷方法学敏捷方法学的问题和局限性 构建领域知识认识和了解领域内容实体模型介绍分析飞行计划路线(route)路线(route) 领域专家进行交流,相互交换知识挖掘出关键的…

一台服务器最大能支持多少条 TCP 连接

一、一台服务器最大能打开的文件数 1、限制参数 我们知道在Linux中一切皆文件,那么一台服务器最大能打开多少个文件呢?Linux上能打开的最大文件数量受三个参数影响,分别是: fs.file-max (系统级别参数)&a…

npm发布自己的包

按照上面流程操作

基于Echarts构建停车场数据可视化大屏

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

XSS—存储型xss

xss >跨站脚本攻击>前端代码注入>用户输入的数据会被当做前端代码执行。 原理:使用者提交的XSS代码被存储到服务器上的数据库里或页面或某个上传文件里,导致用户访问页面展示的内容时直接触发xss代码。 输入内容后直接在下方回显,回…

【Python 随练】今天是哪一天?

题目: 输入某年某月某日,判断这一天是这一年的第几天? 简介: 在本篇博客中,我们将使用Python代码解决一个日期相关的问题:如何确定某一天是给定年份的第几天。我们将提供问题的解析,并给出一…

领导看了给你加薪!python +ddt+excel 一招鲜,接口自动化测试轻松搞定,测试报告惊艳四座!

“ 接口自动化测试是指通过编写代码或使用工具,模拟用户发送请求,验证接口是否符合设计规范和功能需求的过程。” 如何用 python ddtexcel 实现接口自动化测试 接口自动化测试可以提高测试效率和质量,节省测试成本和时间,保证测试…

使用PyTorch执行特征提取和微调的迁移学习来进行图像分类

使用PyTorch执行特征提取和微调的迁移学习来进行图像分类 1. 效果图2 项目结构3 什么是迁移学习4 如何使用PyTorch进行迁移学习?5 花朵数据集源码train_feature_extraction.pyfine_tune.pyinference.py 参考 这篇博客将介绍如何使用PyTorch深度学习库执行图像分类的…

U盘重装系统Win10详细步骤和方法

当前超多的用户都在使用Win10系统,有些用户想使用U盘来重装一下Win10系统,但不知道具体怎么操作,其实操作起来难度不会很大,可以按照以下小编给大家分享的U盘重装系统Win10详细步骤和方法,就能轻松顺利完成U盘重装系统…

Jetson TX2 NX的GPIO引脚使用方式

Jetson TX2 NX是一款高性能的嵌入式AI计算平台,其中引脚的设计和使用对于开发人员来说非常重要。在本文中,我们将会介绍Jetson TX2 NX的引脚并说明其功能和使用方式。 官方文档官方文档 引脚概述 Jetson TX2 NX具有许多不同类型的引脚,包…

C++ 类的构造函数和析构函数

目录 类的构造函数和析构函数构造函数声明构造函数定义构造函数使用构造函数默认构造函数 析构函数析构函数的声明析构函数的定义 改进Stock类(加入构造函数和析构函数) 类的构造函数和析构函数 构造函数 常规的初始化语法不适用类的初始化 例如: int a 10;//整…

Deepin20.9 安装Mysql

文章目录 mysql下载查看 mysql 状态卸载卸载mysql:清理残留数据检查是否删除完毕 mysql Deepin 安装 下载 从网上下载 https://dev.mysql.com/get/mysql-apt-config_0.8.23-1_all.deb 安装 mysql-apt-config 下载文件名: mysql-apt-config_0.8.23-1_all.deb …

PoseiSwap IDO 即将开启,一览 $POSE 经济模型

以太坊创始人 Vitalik Buterin 曾在今年以太坊黑山大会上,进行了以“以太坊的三个技术挑战:扩容、隐私和用户安全”为主题的演讲,阐明了具有隐私性、可扩展性和安全性的且易访问的区块链生态将是行业发展趋势,或许重复造轮子正在变…

【探索 Kubernetes|作业管理篇 系列 10】Pod 健康检查和恢复机制

前言 大家好,我是秋意零。 上一篇中介绍了,Pod 的服务对象,从而对 Pod 有了更深的理解; 今天的主题是 Pod 健康检查和恢复机制,我们将结束 Pod 的内容。 最近搞了一个扣扣群,旨在技术交流、博客互助&am…

图像中提取文本

将从此图像中提取文本。我使用得是 PyCharm,您随意编辑器或IDE 1、下载所需得库和exe文件: tesseract-ocr 可执行exe文件下载后,安装时无需指定安装目录。 http://jaist.dl.sourceforge.net/project/tesseract-ocr-alt/tesseract-ocr-setup-3…

代码随想录二刷day25 | 回溯 之 216.组合总和III 17.电话号码的字母组合

216.组合总和III 题目链接 解题思路: 选取过程如图: 图中,可以看出,只有最后取到集合(1,3)和为4 符合条件。 递归三部曲 确定递归函数参数 和77. 组合 一样,依然需要一维数组path…