K-means(K-均值)算法

K-means(k-均值,也记为kmeans)是聚类算法中的一种,由于其原理简单,可解释强,实现方便,收敛速度快,在数据挖掘、聚类分析、数据聚类、模式识别、金融风控、数据科学、智能营销和数据运营等领域有着广泛的应用。

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

一、K-means基础

1.1牧师-村民模型

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

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

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

1.2聚类

什么是聚类?

通俗说,聚类是将一堆数据划分成到不同的组中。

聚类(Clustering)的通俗定义:将一堆数据划分到不同的组中。一种无监督学习,其产生的类别是未知的。

聚类的学术定义:把一个数据对象的集合划分成簇(子集),使簇内对象彼此相似,簇间对象不相似的过程。

1.3聚类分类

在聚类算法中,常用的是 K-means 和 DBSCAN,但本文聚焦 K-means 。

HMM即隐马尔可夫模型(HiddenMarkovModel)在语音识别、机器翻译、中文分词、命名实体识别、词性标注、基因识别等领域有广泛的使用。

1.4基于划分的聚类算法

学术性的定义:按照某种目标将数据划分成若干个组,划分的结果是使目标函数值最大化(或最小化)。

通俗性的定义:根据样本特征的相似度或距离远近,将其划分为若干个类。

1.4.1相似度

什么是相似度?即两个对象的相似程度。

相似度的原理
原理代表
基于距离的度量距离小,相似度大欧氏距离
基于夹角的度量夹角小,相似度大余弦相似度

1.4.2距离

什么是距离?即两点的距离。

二、K-means原理

K-means,其中K是指类的数量,means是指均值。

2.1K-means原理

K-means是基于样本集合划分的聚类算法,是一种无监督学习。

K-means的思想:

  • 将样本集合划分为k个子集,构成k个类;
  • 将n个样本分到k个类中,每个样本到其所属类的中心距离最小。

K-means的假设:一个样本只属于一个类,或者类的交集为空集。

K-means是怎么判断类别的,又是怎么判断相似的?

 

通过K-means算法原理,可知K-means的本质是物以类聚。

2.2K-means算法

 K-means 的算法步骤为:

  1. 选择初始化的 k 个样本作为初始聚类中心 a = a_{1},a_{2},...a_{k}
  2. 针对数据集中每个样本 x_{i} 计算它到 k 个聚类中心的距离并将其分到距离最小的聚类中心所对应的类中;
  3. 针对每个类别a_{j},重新计算它的聚类中心 a_{j} = \frac{1}{|c_{j}|}\sum _{x\in c_{j}}x(即属于该类的所有样本的质心);
  4. 重复上面 2 3 两步操作,直到达到某个中止条件(迭代次数、最小误差变化等)。

K-means聚类算法的主要步骤:

  • 第一步:初始化聚类中心:随机选取k个样本作为初始的聚类中心。(k需要提前确定)
  • 第二步:给聚类中心分配样本:计算每个样本与各个聚类中心之间的距离,把每个样本分配给距离它最近的聚类中心(初始中心的选择影响聚类结果)
  • 第三步:移动聚类中心 :新的聚类中心移动到这个聚类所有样本的平均值处(可能存在空簇)
  • 第四步:停止移动:重复第2步,直到聚类中心不再移动为止

注意:K-means算法采用的是迭代的方法,得到局部最优解

2.2.1. K-means如何确定 K 值?

K-means 常常根据 SSE 和轮廓系数确定 K 值。

方法一:尝试不同k值:多选取几个k值,对比聚类效果,选择最优的k值。

方法二:结合业务特点:假定想要把文章分为兵乒球,篮球,综合三个类型,就设定k=3。

方法三:根据SSE和轮廓系数:SSE越小,聚类效果越好;轮廓系数越大,聚类效果越好。

2.2.2. K-means如何选取初始中心点?

K-means选择不同的初始中心,会得到不同的聚类结果。

K-means 常使用 K-means++ 方法确定初始中心点。

K-means++:选择初始的聚类中心之间的相互距离要尽可能的远

二分K-means:选择误差最大的类,进行二分分裂。

2.2.3. K-means如何处理空簇?

聚类中心没有被分配到样本,常常将其删除。

空簇问题:K-means中计划聚成20类,结果才聚成19类,1类为空。

空簇原因:聚类中心没有被分配到样本。

解决办法

  • 法一:其他簇心的均值点
  • 法二:删除空族
  • 法三:最远离聚类中心的点

2.3. K- means特征工程

类别特征、大数值特征都不适用于 K-means 聚类。

原因:K-means是基于距离的,而类别没有距离。

k-means对异常值明显,比如年龄、金额等。

2.4. K- means评估

什么样的 K-means 聚类才是好的 K-means 聚类?

实际应用中,常常把 SSE(Sum of Squared Errors,误差平方和) 与轮廓系数(Silhouette Coefficient)结合使用,评估聚类模型的效果。

SSE:误差平方和(Sum of Squared Errors)最小,聚类效果最好。

轮廓系数(Silhouette Coefficient):轮廓系数越大,聚类效果越好。

2.4.1. SSE

SSE越小,聚类效果越好。

2.4.2. 轮廓系数

轮廓系数越大,聚类效果越好。

2.5复杂度

先看下伪代码:

获取数据 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 为样本点数。

三、K-means应用

3.1K-means的python实现

# -*- coding:utf-8 -*-
import numpy as np
from matplotlib import pyplotclass K_Means(object):# k是分组数;tolerance‘中心点误差’;max_iter是迭代次数def __init__(self, k=2, tolerance=0.0001, max_iter=300):self.k_ = kself.tolerance_ = toleranceself.max_iter_ = max_iterdef fit(self, data):self.centers_ = {}for i in range(self.k_):self.centers_[i] = data[i]for i in range(self.max_iter_):self.clf_ = {}for i in range(self.k_):self.clf_[i] = []# print("质点:",self.centers_)for feature in data:# distances = [np.linalg.norm(feature-self.centers[center]) for center in self.centers]distances = []for center in self.centers_:# 欧拉距离# np.sqrt(np.sum((features-self.centers_[center])**2))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 = Truefor 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 = Falseif optimized:breakdef predict(self, p_data):distances = [np.linalg.norm(p_data - self.centers_[center]) for center in self.centers_]index = distances.index(min(distances))return indexif __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)print(k_means.centers_)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(predict)pyplot.scatter(feature[0], feature[1], c=('r' if cat == 0 else 'b'), marker='x')pyplot.show()

 运行结果如下:

{0: array([1.16666667, 1.46666667]), 1: array([7.33333333, 9.        ])}

 

备注:*是两组数据的”中心点”;x是预测点分组。

3.2K-means的Sklearn实现

import numpy as np
from sklearn.cluster import KMeans
from matplotlib import pyplotif __name__ == '__main__':x = np.array([[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6], [9, 11]])# 把上面数据点分为两组(非监督学习)
clf = KMeans(n_clusters=2)
clf.fit(x)  # 分组centers = clf.cluster_centers_  # 两组数据点的中心点
labels = clf.labels_  # 每个数据点所属分组
print(centers)
print(labels)for i in range(len(labels)):pyplot.scatter(x[i][0], x[i][1], c=('r' if labels[i] == 0 else 'b'))
pyplot.scatter(centers[:, 0], centers[:, 1], marker='*', s=100)# 预测
predict = [[2, 1], [6, 9]]
label = clf.predict(predict)
for i in range(len(label)):pyplot.scatter(predict[i][0], predict[i][1], c=('r' if label[i] == 0 else 'b'), marker='x')pyplot.show()

运行结果如下:

[[7.33333333 9.        ][1.16666667 1.46666667]]
[1 1 0 0 1 0]

备注:*是两组数据的”中心点”;x是预测点分组。

 3.3. 用户聚类分群

数据集:titanic.xls(泰坦尼克号遇难者与幸存者名单)

titanic.xls的数据集获取地址:

titanic.xls

任务:基于除survived字段外的数据,使用k-means对用户进行分组(生/死)

聚类的用户分群常用在早期,尝试进行用户探索。实际落地常常结合用户标签,或者用户画像进行用户分群。

用户聚类分群的python代码如下:

# -*- coding:utf-8 -*-
import numpy as np
from sklearn.cluster import KMeans
from sklearn import preprocessing
import pandas as pd# 加载数据
df = pd.read_excel('titanic.xls')
df.drop(['body', 'name', 'ticket'], 1, inplace=True)
df.fillna(0, inplace=True)  # 把NaN替换为0# 把字符串映射为数字,例如{female:1, male:0}
df_map = {}
cols = df.columns.values
for col in cols:if df[col].dtype != np.int64 and df[col].dtype != np.float64:temp = {}x = 0for ele in set(df[col].values.tolist()):if ele not in temp:temp[ele] = xx += 1df_map[df[col].name] = tempdf[col] = list(map(lambda val: temp[val], df[col]))# 将每一列特征标准化为标准正太分布
x = np.array(df.drop(['survived'], 1).astype(float))
x = preprocessing.scale(x)
clf = KMeans(n_clusters=2)
clf.fit(x)# 计算分组准确率
y = np.array(df['survived'])
correct = 0
for i in range(len(x)):predict_data = np.array(x[i].astype(float))predict_data = predict_data.reshape(-1, len(predict_data))predict = clf.predict(predict_data)if predict[0] == y[i]:correct += 1print(correct * 1.0 / len(x))

执行结果:

第一次执行:0.6974789915966386
第二次执行:0.3017570664629488

注意:结果出现很大波动,原因是它随机分配组(生:0,死:1)(生:1,死:0)。

四、K-means总结

4.1K-means的优缺点

4.1.1优点

  • 容易理解,聚类效果不错,虽然是局部最优, 但往往局部最优就够了;
  • 原理简单,实现方便,收敛速度快;
  • 处理大数据集的时候,该算法可以保证较好的伸缩性;
  • 当簇近似高斯分布的时候,效果非常不错;
  • 算法复杂度低;
  • 聚类效果较优;
  • 模型的可解释性较强;
  • 调参只需要调类数k 。

4.1.2 缺点

  • K 值需要人为设定,不同 K 值得到的结果不一样,k的选取不好把握;
  • 对初始的簇中心敏感,不同选取方式会得到不同结果;
  • 对异常值敏感;
  • 样本只能归为一类,不适合多分类任务;
  • 不适合太离散的分类、样本类别不平衡的分类、非凸形状的分类;
  • 如果数据的类型不平衡,则聚类效果不佳
  • 采用的是迭代的方法,得到局部最优解
  • 对于噪音和异常点比较敏感

什么是凸集 (convex set)?

凸集 (convex set)

欧几里得空间的一个子集,其中任意两点之间的连线仍完全落在该子集内。例如,下面的两个图形都是凸集:

所以,凸的数据集,即数据集的样本呈现凸集分布。

相反,下面的两个图形都不是凸集:

 

所以,不是凸的数据集,即是数据集的样本呈现的不是凸集分布。

4.2K-means的改进

针对K-means缺点,K-means有许多改进算法,如数据预处理(去除异常点),合理选择 K 值,高维映射等。

K-means改进
缺点改进
1、k的选取不好把握ISODATA
2、对初始聚类中心敏感k-means++
3、对于不是凸的数据集比较难以收敛DESCAN
4、如果数据的类型不平衡,则聚类效果不佳CUSBoost
5、采用的是迭代的方法,得到局部最优解二分K-means
6、对于噪音和异常点比较敏感K-Mediods

【机器学习】K-means(非常详细) - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/78798251

Kmeans++聚类算法原理与实现 - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/152286357

4.3聚类和分类的区别

聚类和分类的区别是什么呢?

最大区别是:聚类是无监督的;分类是有监督学习。

其中机器学习的分类按输出类别(标签)不同,可以分为二分类(Binary Classification)、多分类(Multi-Class Classification)、多标签分类(Multi-Label Classification)。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我和云栖有个约会

云栖大会&#xff1a;聚焦创新&#xff0c;驱动未来 2009年&#xff0c;一场地方网站峰会在中国掀起了技术的浪潮。随着时间的推移&#xff0c;这场峰会逐渐演变成了全球领先的科技盛会——云栖大会。回首历史&#xff0c;云栖大会不仅是中国云计算产业发展的见证者&#xff0c…

高效分割分段视频:提升您的视频剪辑能力

在数字媒体时代&#xff0c;视频剪辑已经成为一项重要的技能。无论是制作个人影片、广告还是其他类型的视频内容&#xff0c;掌握高效的视频剪辑技巧都是必不可少的。本文将介绍如何引用云炫AI智剪高效地分割和分段视频&#xff0c;以提升您的视频剪辑能力。以下是详细的操作步…

2023-11-01 LeetCode每日一题(参加会议的最多员工数)

2023-11-01每日一题 一、题目编号 2127. 参加会议的最多员工数二、题目链接 点击跳转到题目位置 三、题目描述 一个公司准备组织一场会议&#xff0c;邀请名单上有 n 位员工。公司准备了一张 圆形 的桌子&#xff0c;可以坐下 任意数目 的员工。 员工编号为 0 到 n - 1 。…

appium操控微信小程序的坑

appium操控微信小程序的坑 打不开启动页面driver的context只有NATIVE_APP小程序上元素找不到 我打算使用appium操控微信小程序&#xff0c;只要能够获取到小程序的页面元素就算成功。下面都是我遇到的问题。 打不开启动页面 以下是我的appium的配置参数和代码&#xff1a; de…

基于Taro + React 实现微信小程序半圆滑块组件、半圆进度条、弧形进度条、半圆滑行轨道(附源码)

效果&#xff1a; 功能点&#xff1a; 1、四个档位 2、可点击加减切换档位 3、可以点击区域切换档位 4、可以滑动切换档位 目的&#xff1a; 给大家提供一些实现思路&#xff0c;找了一圈&#xff0c;一些文章基本不能直接用&#xff0c;错漏百出&#xff0c;代码还藏着掖…

Kubernetes - Ingress HTTP 升级 HTTPS 配置解决方案(新版本v1.21+)

之前我们讲解过 Kubernetes - Ingress HTTP 搭建解决方案&#xff0c;并分别提供了旧版本和新版本。如果连 HTTP 都没搞明白的可以先去过一下这两篇 Kubernetes - Ingress HTTP 负载搭建部署解决方案_放羊的牧码的博客-CSDN博客Kubernetes - Ingress HTTP 负载搭建部署解决方案…

SpringMVC Day 07 : 表单验证

前言 表单验证在Web开发中是非常常见和重要的一部分&#xff0c;它用于确保用户提交的数据符合预期的规则和限制。 通过表单验证&#xff0c;我们可以有效地捕获并处理用户输入中的错误或不正确的数据&#xff0c;从而提高应用程序的数据质量和用户体验。在本教程中&#xff…

Thread

Thread 线程启动线程第一种创建线程线程的第二种创建方式使用匿名内部类完成线程的两种创建 Thread API线程的优先级线程提供的静态方法守护线程用户线程和守护线程的区别体现在进程结束时 多线并发安全问题同步块 线程 启动线程 启动线程:调用线程的start方法,而不是直接调用…

lua-resty-request库写入爬虫ip实现数据抓取

根据提供的引用内容&#xff0c;正确的库名称应该是lua-resty-http&#xff0c;而不是lua-resty-request。使用lua-resty-http库可以方便地进行爬虫&#xff0c;需要先安装OpenResty和lua-resty-http库&#xff0c;并将其引入到Lua脚本中。然后&#xff0c;可以使用lua-resty-h…

【网络协议】聊聊http协议

当我们输入www.baidu.com的时候&#xff0c;其实是先将baidu.com的域名进行DNS解析&#xff0c;转换成对应的ip地址&#xff0c;然后开始进行基于TCP构建三次握手的连接&#xff0c;目前使用的是1.1 默认是开启了keep-Alive。可以在多次请求中进行连接复用。 HTTP 请求的构建…

【k8s】pod详解

一、Pod介绍 1、Pod的基础概念 Pod是kubernetes中最小的资源管理组件&#xff0c;Pod也是最小化运行容器化应用的资源对象&#xff0c;一个pod代表着集群中运行的一个进程。kubernetes中其它大多数组件都是围绕着pod来进行支持和扩展pod功能的。 例如&#xff0c;用于管理po…

计算机基础知识41

前端 # 前端是所有跟用户直接打交道 比如&#xff1a;PC页面、手机页面、汽车显示屏&#xff0c;肉眼可以看见的 # 后端&#xff1a;一堆代码&#xff0c;用户不能够直接看到&#xff0c;不直接与用户打交道 常见的后端&#xff1a;Python、Java、Go等 # 学了前端就可以做全栈…

算法题:二叉树的层序遍历

层序遍历&#xff0c;看似简单&#xff0c;实则陷阱很多&#xff0c;怪不得该题目被认定为中等难度题。此处运用了迭代求解法。&#xff08;完整题目附在了最后&#xff09; # Definition for a binary tree node. class TreeNode:def __init__(self, val0, leftNone, rightNon…

Vectrosity 插件使用

1 下载 https://download.csdn.net/download/moonlightpeng/88490704?spm1001.2014.3001.5503 2 使用&#xff0c;目前在2020.3.3上测试可以 导入时选5.6 再导入demo

FlinkCDC系列:通过skipped.operations参数选择性处理新增、更新、删除数据

在flinkCDC源数据配置&#xff0c;通过debezium.skipped.operations参数控制&#xff0c;配置需要过滤的 oplog 操作。操作包括 c 表示插入&#xff0c;u 表示更新&#xff0c;d 表示删除。默认情况下&#xff0c;不跳过任何操作&#xff0c;以逗号分隔。配置多个操作&#xff…

四、[mysql]索引优化-1

目录 前言一、场景举例1.联合索引第一个字段用范围查询不走索引(分情况&#xff09;2.强制走指定索引3.覆盖索引优化4.in和or在表数据量比较大的情况会走索引&#xff0c;在表记录不多的情况下会选择全表扫描5.like 后% 一般情况都会走索引(索引下推) 二、Mysql如何选择合适的索…

(三)上市企业实施IPD成功案例分享之——五菱

2022年对汽车产业而言是极为不平凡的一年。这一年&#xff0c;企业受到疫情反复、芯片短缺、原材料价格上涨等负面因素影响&#xff0c;汽车产业的变革持续加速。面对变革与挑战&#xff0c;五菱汽车仍逆势交出一份超出市场预期的成绩单。上半年&#xff0c;五菱发布2022年财报…

2023年【熔化焊接与热切割】考试题及熔化焊接与热切割模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年【熔化焊接与热切割】考试题及熔化焊接与热切割模拟考试&#xff0c;包含熔化焊接与热切割考试题答案和解析及熔化焊接与热切割模拟考试练习。安全生产模拟考试一点通结合国家熔化焊接与热切割考试最新大纲及熔…

ASO优化之如何制作Google Play的长短描述

应用的描述以及标题和图标是元数据中最关键的元素&#xff0c;可以影响用户是否决定下载我们的应用程序。简短描述的长度限制为80个字符&#xff0c;它提供了更多的有关应用背景信息的机会。 1、简短描述帮助用户快速了解我们应用。 确保内容丰富的同时&#xff0c;保持简洁和…

Redis与Mysql的数据一致性(双写一致性)

双写一致性&#xff1a;当修改了数据库的数据也要同时的更新缓存的数据&#xff0c;使缓存和数据库的数据要保持一致。 一般是在写数据的时候添加延迟双删的策略 先删缓存 再修改数据 延迟一段时间后再次删除缓存 这种方式其实不是很靠谱 一致性要求高 共享锁&#xff1a;读…