K-Means是一种聚类算法,与之前提到的朴素贝叶斯等算法不同,它属于无监督学习。无监督学习是什么意思呢?简单来说,之前的算法中我们是利用特征 x 和类别 y 来进行训练、分类的,而无监督学习是指不需要我们提供具体的类别 y ,而让数据自己聚在一起,形成 k 个簇,以实现分类的目的。
具体方法是通过对给定的样本进行划分,分为 k 个簇,使得簇内的点尽量紧密的连在一起,而簇间的距离尽量大,评判的标准就是通过欧氏距离。
主要包括两个步骤(首先初始化 k 个质心):
分别计算样本点与各个质心的距离,来判断样本归属于哪个簇;
寻找得到的簇的新质心,并更新。
重复循环上述两步,直到平均距离最小,即找到了最佳的质心以及簇的分类。
接下来看看如何通过程序来实现。首先需要用到sklearn中的方法来生成一些用来测试的数据——make_blobs。
sklearn.datasets.make_blobs(n_samples=100, n_features=2,centers=3, cluster_std=1.0, center_box=(-10.0, 10.0), shuffle=True, random_state=None)[source]
n_samples是待生成的样本的总数
n_features是每个样本的特征数
centers表示类别数
cluster_std表示每个类别的方差
在 jupyter notebook 中通过 shift + tab 组合键可以看到其中的参数,默认为100个样本,两个特征,三个中心点等等。
import matplotlib.pyplot as plt
import sklearn.datasets as datasets
X,y = datasets.make_blobs()
plt.scatter(X[:,0], X[:,1], c=y)
因为在生成数据的时候就是默认三个中心,所以分三类是最优的,然而在拿到未知的数据时并不清楚分几簇才是最好的,下面先实现一下分类,再说明如何选择 k 值最好。
from sklearn.cluster import KMeans
kmeans = KMeans(3)
kmeans.fit(X)
y_ = kmeans.predict(X)
print(y_)
[out] [2 1 2 0 0 0 2 0 1 1 1 1 2 1 1 2 0 1 2 1 0 2 0 2 1 1 2 0 2 0 1 1 0 1 2 0 0
1 2 2 0 1 2 1 2 0 2 0 2 2 0 1 2 0 0 1 1 1 2 0 2 1 1 2 1 0 0 0 0 2 0 2 0 2
0 1 0 2 0 0 2 1 0 0 2 2 1 2 1 2 1 2 1 0 1 2 2 1 1 0]
同之前算法类似,先创建对象,然后将样本进行训练,不同之处在于 K-Means是无监督学习,不需要传入目标值。上面暂时先设置分三类,得到结果分别用数字打标签。下面通过图像看一下分类是否成功:
可以看到,通过简单的调库,就将样本进行分类了。那么解决了分类问题,下面说一下如何选择簇的个数。
举个栗子,取 k 为4时,如上图所示的分类结果显然他将之前的分类中一个簇又进行的拆分,明显有些多余了。然而,当我们拿到数据时,尤其是特征较多的时候,我们根本无法一眼看出来怎么分是合适的。在之前的算法中,可以根据准确率来判断,对于无监督学习,显然没有那些条件。不过它也有自己的评价指标——轮廓系数(sklearn.metrics.silhouette_score)。
除去默认参数,最主要的参数只有两个,分别是样本和标签。通过这个轮廓系数来分别计算不同分类个数的值。轮廓系数取值范围为[-1,1],取值越接近1则说明聚类性能越好,相反,取值越接近-1则说明聚类性能越差。
测试得到结果为:k=2时,轮廓系数为0.79;k=3时,轮廓系数为0.81;k=4时,轮廓系数为0.70;k=5时,轮廓系数为0.55。
由此可以得到,k 取3时,聚类效果最好,以后对真实数据进行处理就可以通过这样的方式来找最合适的初始值。当然,还有一个要注意的,同一组数据可能会根据不同特征被划分为不同的结果,聚类出来的结果可能并不是全局最优的,保险起见,可以多试几次,找到最佳的分类结果。
往期推荐
python解释器到底是什么?
爬虫 | urllib入门+糗事百科实战
Python骚操作!教你学会装饰器!
【机器学习】K-近邻算法(KNN)
python数据分析与挖掘 | 挖掘建模