【Basic】K-means 聚类算法

K-means 聚类算法属于无监督学习,即数据没有“标准答案”。

业界也逐渐开始探索将有监督学习和无监督学习结合在一起,首先通过聚类等无监督学习的算法处理数据,通过各种假设和结合聚类结果来给数据打标签然后再把这些数据输送给有监督学习来进行建模训练,使得未经人工标注的数据,也能起到提高有监督学习模型预测准确度的效果。这种集两家之长的方法称为半监督学习是当前机器学习研究的热点之一。

K-means 算法的重点概念:

  • 聚类问题
  • 簇(cluster)
  • 质心
  • 多数表决

簇(cluster)

在聚类问题中,“簇”(Cluster)是一个处于核心位置的概念,只要涉及聚类问题,“簇”就一定会出现。“簇”这个字并不太常见,也许初见会被吓一跳,请放心,这是个很简单的词儿样本数据集通过聚类算法最终会聚成一个个“类”,这些类在机器学习的中文术语里就称为"簇”。

聚类面临的问题

1. 应该汇聚成多少个簇?

样本数据点经过聚类之后会形成多少个簇,事先是未知的。而选择不同的簇个数,可能会产生不同的聚类结果。

不同的聚类算法采取了不同的思路,主要分为划分法、层次法、密度法和网格法,不过解决思路概括起来无非两种,一种是预先设定有多少个簇,另一种则是其在聚类的过程中形成。
划分法是最简单、最容易实现的聚类算法,所谓划分,就是预先假设待聚类的n个数据将能划分为K个区域(K小于或等于n),即聚类后形成K个簇,在这个假设基础上 再采取各种手段完成聚类,也就是采取第一种解决思路。 K-means算法就是一种具有代表性的典型划分法。
K-means 中的“K”就是聚K个类的意思。

2. 怎样量化相似?

找质心

怎样找质心?

假设聚类问题的样本数据也能找出K个中心点,就能同样以该点为中心、以距离为度量划出范围来,将同一范围内的数据样本点作为一个簇,也就可以实现聚类的效果了。

可最大的问题是没有这个中心点。虽然同样是多数表决,但 K-means算法表决的是聚类问题,是“咱们是不是同一个簇”,即大家都是待判别,并没有任何一个样本数据点可以作为中心点,后面似乎也就无从谈起了。

随机选取就是 K-means 算法初始化多个质心的全部内容,也就是在数据集中随机选取 K 个点作为质心。

假设现在我们通过K个质心得到了K个簇,现在需要做的是怎样让这K个簇形成新的质心。做法有很多, K-means 算法选择了最简单的一种:求平均。每个簇都有若干数据点,求出这些数据点的坐标值均值,就得到了新质心的坐标值。

这其实也是一种变相的多数表决。根据全体拥有表决权的数据点的坐标来共同决定 新的质心在哪里,而表决权则由簇决定在 K-means聚类的过程中会多次经历质心计算, 数据点归属于哪个簇可能会频繁变动,所以,同一个数据点可能在这一轮与一群样本点 进行簇A的质心计算,在下一轮就与另一群样本点进行簇B的质心计算。这也是该算法与KNN算法较为不同的地方。

K-means 聚类算法的聚类过程,可以看成是不断寻找簇的质心的过程,这个过程从随机设定K个质心开始,直到找到K个真正质心为止:

  1. 初始化质心并聚为 K 个簇。首先可以确信的是,无论产生过程如何,既然现在有了K个质心,对于其他数据点来说,根据其距离哪个质心近就归为哪个簇的办法,可以聚成K个簇。但请注意,这只是第一步,并不是最后完成聚类的结果。
  2. 重新选取质心。对于聚成的K个簇,需要重新选取质心。这里运用了多数表决原则,根据一个簇内所有样本点各自的维度值来求均值,得到该簇的新的坐标值。
  3. 生成新的质心。其实即重复,对于根据均值计算得到的K个新质心,重复第一步中离哪个质心近就归为哪个簇的过程,再次将全部样本点聚成K个簇。经过不断重复,当质心不再变化后,完成聚类。

总结一下其实就是首先逐个计算数据集点到K个质心的距离,根据距离的远近,将数据集点分别划归距离最近的质心,也就是根据距离质心的远近完成一次聚类,形成K个类;然后就是选取新质心,这其实是一次对聚类内的所有数据点进行求均值计算。重复上述两个过程,也就是生成新质心后重新进行聚类,然后根据聚类结果再次生成新质心。一直重复这个过程,聚类就结束了。

K-means 算法的数学解析

找质心过程的本质

一言以蔽之,就是让簇内样本点到达各自质心的距离的总和最小能够满足这个“最小”的K个质心,就是我们要找的质心。这样一表述,要找的目标就具体多了。下面我们使用数学的语言进行描述,也许会更加明了清晰。

距离的度量

对于 K-means 的数学表达式还有另一种解释将距离看成是簇内数据样本点与质心的平方误差,平方误差越小,说明簇内数据样本点围绕质心越紧,通过最小化平方误差,也就找到了数据样本点最“扎实”的K个簇。

K- means 具体步骤

K-means 算法是一种无监督的聚类算法,与之前算法最大的区别在于输入只有样本特征值向量,而不再具有类别标记Y,输出则为具有分类功能的模型,能够根据输入的特征值预测分类结果。

  1. 随机选取K个对象,以它们为质心。
  2. 计算数据集到质心的距离。
  3. 将对象划归(根据距离哪个质心最近)。
  4. 以本类内所有对象的均值重新计算质心,完成后进行第二步。
  5. 类不再变化后停止。

K - means 的 Python 实现

在 Scikit–Lean机器学习库中,最近邻模型算法族都在cluster类库下,当前版本共有10个类。聚类算法看似都是想把对象聚成K个类,但方法却似百花齐放,具有代表性的几个类如下:

  • KMeans类:这个类就是本文介绍的K -means-聚类算法。MiniBatchKMeans类:这是k- -means算法的变体,使用mini- -batch(小批量)来减少一次聚类所需的计算时间。mini-batch也是深度学习常使用的方法。
  • DBSCAN类:使用 DBSCAN聚类算法, DBSCAN算法的主要思想是将聚类的类视为被低密度区域分隔的高密度区域。
  • MeanShift类:使用 MeanShift聚类算法 MeanShift算法的主要方法是以任意点作为质心的起点,根据距离均值将质心不断往高密度的地方移动,也即所谓均值漂移,当不满足漂移条件后说明密度已经达到最高,就可以划分成簇。
  • AffinityPropagation类:使用 Affinity Propagation聚类算法,简称AP算法,聚类过程是一个“不断合并同类项”的过程,用类似于归纳法的思想方法完成聚类这种方法被称为“层次聚类”。
%matplotlib inline

import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans

# 使用 make_blobs 生成聚类测试数据集
n_samples = 1500
X, y = make_blobs(n_samples=n_samples)

# 进行聚类
y_pred = KMeans(n_clusters=3).fit_predict(X)

plt.scatter(X[:, 0], X[:, 1], c=y_pred)

在这里插入图片描述
需要特别说明的是,这里的pred和分类算法中的pred不同,不应该理解成是对类别的预测,而应该作为“聚类后得到的簇的编号”来理解,本段代码中y_pred的值其实是每个样本对应的簇的编号,实际值如下:

array([0, 0, 1, ..., 0, 0, 0])

K-means 优缺点

K-means算法原理简单,实现容易,能够很快地实现部署;聚类过程中只涉及求均值运算,不需要进行其他太复杂的运算,执行效率较高,而且往往能取得较好的聚类效果。因此遇到聚类问题,不妨首先选择使用kmeans算法,可能一上来就把问题给解决了,而且原理也容易说清楚。

虽然简单不是缺点,但 K-means 算法当然还是存在缺点的,最明显的问题就是需要先验地设置“K”,也就是根据外部经验人为地设置聚类的簇的个数。同时,由于需要求均值,这就要求数据集的维度属性类型应该是数值类型。此外,K-means算法使用随机选择的方法初始化质心,不同的随机选择可能对最终的聚类结果产生明显影响,增加了不可控因素。最后,“K–means”中的“means”也会带来一些原生的问题,如果数据集中出现一些孤立点,也就是远离其他数据集点的数据点时,会对聚类结果产生非常明显的扰动。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
K-means聚类算法的C++实现可以参考以下代码: ```cpp #pragma once #ifndef K_MEANS_H #define K_MEANS_H #include <vector> using namespace std; struct Tuple { float x; float y; float z; }; class K_means { private: vector<Tuple> basic_data; int mean_number; vector<vector<Tuple>> result_data; vector<Tuple> means; vector<float> mea_square_error; public: K_means(vector<Tuple> basic_data, int mean_number) : result_data(mean_number), mea_square_error(mean_number) { this->basic_data = basic_data; this->mean_number = mean_number; } void get_fina_result_data(); private: float get_distxyz(Tuple tuple1, Tuple tuple2); void prime_k_meansbase(); void get_k_means(); void get_basemean(); void get_new_k_means(); void get_k_mean_erro(); }; #endif ``` 通过这个头文件定义了K_means类和相关的数据结构Tuple。K_means类包含了计算最后聚类结果的方法get_fina_result_data(),以及一些私有方法用于初始化和计算聚类过程。 下面是具体的测试代码: ```cpp #include <iostream> #include <vector> #include "k_means.h" using namespace std; void test() { vector<Tuple> basic_data_test; Tuple temp_data; int x = 0, y = 0, z = 0; int k; // 分类数量 int n; // 样本数量 cout << "请输入类别数量:" << endl; cin >> k; cout << "请输入数据量:" << endl; cin >> n; for (int i = 0; i < n; i++) { cout << "请输入x, y, z:" << endl; cin >> x >> y >> z; temp_data.x = x; temp_data.y = y; temp_data.z = z; basic_data_test.push_back(temp_data); } K_means a(basic_data_test, k); a.get_fina_result_data(); } int main() { test(); } ``` 这段测试代码首先获取用户输入的分类数量k和数据量n,然后循环读取用户输入的样本数据,并创建K_means对象进行聚类。最后调用get_fina_result_data()方法获取最终的聚类结果。 这就是一个简单的K-means聚类算法的C++实现。您可以根据自己的需求进行修改和扩展。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [机器学习--C++实现 K-Means聚类demo](https://blog.csdn.net/qq_52816511/article/details/124411829)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值