无监督学习——K均值聚类(上)

近几年在机器学习领域里面,聚类是比较热门的一个词汇。它是将数据集划分成组的任务,这些组叫做。其目标是划分数据,使得一个簇内的数据点非常相似且簇内的数据点非常不同。与分类算法相似,聚类算法为每个数据点分配(或预测)一个数字,表示这个点属于哪个簇。但是,与分类算法不同的是,聚类属于无监督学习,也就是说事先并不知道数据集的标签或者说特征值分类,而分类算法是监督学习,意味着已经提前知道了数据点的所属类别。接下来,我重点介绍下聚类里面比较常用的算法——k均值聚类

K均值聚类的原理讲解

1.算法介绍

k均值聚类是最简单也最常用的聚类算法之一。它试图找到代表数据特定区域的簇中心。算法交替执行以下两个步骤:将每个数据点分配给最近的簇中心,然后将簇中心设置为所分配的所有数据点的平均值。如果簇的分配不再发生变化,那么算法结束。

2.代码讲解

用scikit-learn应用K均值相当简单。下面,我们将其应用于模拟数据make_blobs,将Kmeans实例化,并设置我们要找的簇的个数。然后对数据调用fit方法。代码如下:

from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
X,y=make_blobs(random_state=1)###生成模拟的二维数据
kmeans=KMeans(n_clusters=3)###如果不指定n_clusters,它的默认值是8
kmeans.fit(X)

PS:其中make_blobs的函数功能是生成各向同性的高斯斑点以进行聚类,感兴趣的同学可以自行百度研究下,这里就不在进行赘述了。

(1) kmeans.labels_

在算法运行期间,Kmeans为X中的每个训练数据点分配一个簇标签。我们可以在kmeans.labels_中找到这些标签,实际上kmeans.labels_就是算法结果(与kmeans.predict(X)的意义一样)
在这里插入图片描述
如上图所示,聚类算法与分类算法有些相似,每个元素都有一个分配的标签。我们与数据集的原分类对比一下:
在这里插入图片描述

两相对比可以看出,标签并不是真实的,因此标签本身并没有什么意义。算法给予你的唯一信息就是所有标签相同的数据点都是相似的。所以,我们不应该为其中一组的标签是0,另一组的标签是1赋予任何意义。

(2) kmeans.cluster_centers_

之前提到的簇中心数据被保存在kmeans.cluster_centers_属性中:
在这里插入图片描述
(3) 可视化

接下来我们将数据分类结果可视化:

import mglearn
mglearn.discrete_scatter(X[:,0],X[:,1],kmeans.labels_,markers="o")
mglearn.discrete_scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],[0,1,2],markers="*",markeredgewidth=2)

在这里插入图片描述
从上面的图像可以看出,数据被3个簇中心很好的分成了三个部分。

实际上,我们也可以使用更多或更少的簇中心:

import matplotlib.pyplot as plt
fig,axes=plt.subplots(1,2,figsize=(10,5))
kmeans=KMeans(n_clusters=2)###使用两个簇
kmeans.fit(X)
mglearn.discrete_scatter(X[:,0],X[:,1],kmeans.labels_,ax=axes[0])
kmeans=KMeans(n_clusters=5)###使用五个簇
kmeans.fit(X)
mglearn.discrete_scatter(X[:,0],X[:,1],kmeans.labels_,ax=axes[1])

在这里插入图片描述

K均值聚类的实际应用

1.数据来源

水质测试数据:https://www.kaggle.com/adityakadiwal/water-potability

在这里插入图片描述
该数据集共包含3277个数据点,并通过水质硬度,酸碱度等9个特征值,将水分成了两类。(0和1指代水的类别)

接下来,为了演示无监督学习,我们将其当作不知分类结果的数据集,并用K均值算法进行聚类。

2.数据处理

老规矩,还是先读取数据,代码如下:

import pandas as pd
import winreg
###################
real_address = winreg.OpenKey(winreg.HKEY_CURRENT_USER,r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders',)
file_address=winreg.QueryValueEx(real_address, "Desktop")[0]
file_address+='\\'
file_origin=file_address+"\\源数据-分析\\water_potability.csv"###https://www.kaggle.com/adityakadiwal/water-potability
water=pd.read_csv(file_origin)
#设立桌面绝对路径,读取源数据文件,这样将数据直接下载到桌面上就可以了,省得还要去找
###################

结果如下所示:
在这里插入图片描述
可以看到这份数据中有很多空值,为了保证数据的完整性,我们将包含空值的行全部删掉(也可以用平均数来代替):

water=water.dropna()####去掉包含空值的行
water_test=water.drop("Potability",axis=1)#####去掉分类结果
y=water["Potability"]

3.应用K均值聚类并与原结果进行比较

我们对上面已经处理好的数据集应用K均值聚类算法:

kmeans=KMeans(n_clusters=2)###对应源数据中的两个分类结果
kmeans.fit(water_test)
y_pred=kmeans.predict(water_test)

处理好之后,我们将聚类结果与源数据的分类进行差值计算。如果分类结果相同,则差值等于0,因此,通过统计差值中有多少个数值为0,来对聚类结果进行测评:

import numpy as np
y_original=np.array(y)
a=y_pred-y_original###将结果进行比较,计算两者之间的差值
len(a[a==0])/len(a)###如果分类结果相同,则等于0,所以统计差值中有多少个数值为0

结果如下所示,无监督学习的K均值聚类精度为52.8%
在这里插入图片描述

K均值的精度

我们从上面的结果可以看出来,实际应用中K均值的精度并没有很高。一是因为与监督学习中的分类器相比,K均值聚类属于无监督学习,也就是说事先并不知道分类结果,没有办法进行模型训练。二是因为即使你知道给定数据中簇的“正确”个数,k均值可能也不是总能找到它们。每个簇仅由其中心定义,这意味着每个簇都是凸形。因此,K均值只能找到相对简单的形状。K均值还假设所有簇在某种程度上具有相同的“直径”,它总是将簇之间的边界刚好画在簇中心的中间位置。

举个栗子:

from sklearn.datasets import make_moons
X,y=make_moons(n_samples=200,noise=0.05,random_state=0)
kmeans=KMeans(n_clusters=2)###使用两个簇
kmeans.fit(X)
y_pred=kmeans.predict(X)###与labels_相同,为新数据点分配簇标签
plt.scatter(X[:,0],X[:,1],c=y_pred,cmap=mglearn.cm2,s=60)
plt.scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],marker="*",c=[mglearn.cm2(0),mglearn.cm2(1)],s=100,linewidth=2)

在这里插入图片描述
对于上面的数据集,很明显,我们是希望聚类算法能够发现两个半月形,但是在这里利用K均值算法是不可能做到这一点的。

总结

本篇主要讲了关于K均值聚类的一些基础的东西,包括代码原理,实际应用以及应用中的一些局限性。限于篇幅原因,下一篇我再说一些有关K均值聚类稍微复杂一点的内容。

个人博客:https://www.yyb705.com/
欢迎大家来我的个人博客逛一逛,里面不仅有技术文,也有系列书籍的内化笔记。
有很多地方做的不是很好,欢迎网友来提出建议,也希望可以遇到些朋友来一起交流讨论。

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在MapReduce编程中,K均值聚类是一个常用的算法。在实验中可能会遇到以下问题: 1. 数据倾斜问题 在K均值聚类中,数据可能会出现倾斜,导致一些Reducer处理的数据量过大,而其他Reducer则处理很少的数据。这会导致整个程序运行效率低下。 解决办法:可以采用数据切分、数据预处理、负载均衡等方法来解决数据倾斜问题。比如可以对数据进行随机分片,或者采用局部聚类的方法进行预处理,以达到负载均衡的效果。 2. 初始中心点选择问题 K均值聚类算法中,初始中心点的选择对结果有很大的影响。如果初始中心点选择不合理,可能会导致最终的聚类结果不理想。 解决办法:可以采用随机选择、聚类采样等方法来确定初始中心点。同时,可以多次运行算法,选择最优的结果。 3. 算法收敛速度问题 K均值聚类算法需要迭代多次才能收敛,每次迭代都需要进行MapReduce操作,这会导致程序运行时间较长。 解决办法:可以采用优化算法、增加并行度等方法来提高算法收敛速度。比如可以采用Mini-Batch K-means算法来减少计算量,或者增加Reducer的数量来提高并行度。 4. 数据量过大问题 K均值聚类算法需要处理大量数据,如果数据量过大,可能会导致程序无法运行或者运行时间过长。 解决办法:可以采用数据采样、分布式存储等方法来解决数据量过大的问题。比如可以采用Hadoop分布式文件系统(HDFS)来存储数据,或者采用MapReduce框架中的Combiner函数来减少数据传输量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值