前言
在上篇《 Python 机器学习实战 —— 无监督学习(上)》介绍了数据集变换中最常见的 PCA 主成分分析、NMF 非负矩阵分解等无监督模型,举例说明使用使用非监督模型对多维度特征数据集进行降维的意义及实用方法。对 MDS 多维标度法、LLE 局部线性嵌入法、Isomap 保距映射法、t-SNE 分布邻域嵌入算法等 ML 流形学习模型的基础使用方法进行讲解。
本文将对聚类算法进行讲解,聚类算法就是将数据集划分成组的任务,这些组叫成簇,同一个簇内的数据点特征非常相似,不同簇内的数据点特征区别很大,这点与监督学习中的分类算法很类似,运行完成后系统会为同一簇内的数据分配同一个数字,不同簇的数字都不一样。常见的聚类模型有 KMeans、DBSCAN、GMM 、Agglomerative 等,下面将一一介绍。
目录
四、KMeans 均值聚类
4.1 KMeans 的基本原理
KMeans 均值聚类是最简单最常用的聚类算法之一,它会尝试找到代表数据区域的簇中心,并保存在 cluster_centers 属性中。再把每个数据点分配给最接近的簇中心,并把每个簇中心设置为所分配数据点的平均值。当簇中心的值根据模型运算设置不再发生变化时,算法结束。
构造函数
1 class KMeans(TransformerMixin, ClusterMixin, BaseEstimator): 2 @_deprecate_positional_args 3 def __init__(self, n_clusters=8, *, init='k-means++', n_init=10, 4 max_iter=300, tol=1e-4, precompute_distances='deprecated', 5 verbose=0, random_state=None, copy_x=True, 6 n_jobs='deprecated', algorithm='auto'):
- n_clusters:int 类型,默认为8,代表生成簇中心数目
- init:选择 {’k-means++’, ‘random ’} 之一, 或者传递一个ndarray向量,代表初始化方式,默认值为 ‘k-means++’。‘k-means++’ 用一种特殊的方法选定初始聚类中发,可加速迭代过程的收敛;‘random’ 随机从训练数据中选取初始质心。如果传递的是一个ndarray,则应该形如 (n_clusters, n_features) 并给出初始质心。
- n_init:int 类型,默认值为10,用不同的聚类中心初始化值运行算法的次数,最终解是在 inertia 意义下选出的最优结果。
- max_iter: int 类型,默认值为 300 ,代表模型优化的最大迭代数。
- tol:float类型,默认值为 1e-4 ,代表求解方法精度
- precompute_distances: 可选值 {‘auto’,True,False }, 代表预计算距离,计算速度更快但占用更多内存。‘auto’:如果 样本数乘以聚类数大于 12million 的话则不预计算距离;True:总是预先计算距离;False:永远不预先计算距离。’ deprecated ‘ 旧版本使用,新版已丢弃。
- verbose: int 类型,默认为 0,详细程度。
- random_state:默认值为None 随机数种子,推荐设置一个任意整数,同一个随机值,模型可以复现
- copy_x: bool 类型,默认值True。当 precomputing distances 生效时,将数据中心化会得到更准确的结果。如果把此参数值设为True,则原始数据不会被改变。如果是False,则会直接在原始数据上做修改并在函数返回值时将其还原。但是在计算过程中由于有对数据均值的加减运算,数据返回后,原始数据和计算前可能会有细小差别。
- n_jobs:int 类型,默认为 None, CPU 并行数。内部原理是同时进行n_init指定次数的计算时,若值为 -1,则用所有的CPU进行运算。若值为1,则不进行并行运算。若值小于-1,则用到的CPU数为(n_cpus + 1 + n_jobs)。因此如果 n_jobs值为-2,则用到的CPU数为总CPU数减1。’ deprecated ‘ 旧版本使用,新版已丢弃。
- algorithm: str 类型,{ auto,full,elkan } 三选一。full就是一般意义上的K-Means算法; elkan是使用的elkan K-Means算法; auto则会根据数据值是否是稀疏的(稀疏一般指是有大量缺失值),来决定如何选择full 和 elkan。如果数据是稠密的,就选择elkan K-means,否则就使用普通的Kmeans算法。
常用参数
- cluster_centers_: 代表簇中心 ,训练后簇中心都会被保存在此属性中
- labels_:返回数据点所属的簇标志,与 predict 方法返回值相同
4.2 KMeans 的应用场景
下面先用简单的 make_blobs 数据集了解 KMeans 的基础使用方式,KMeans 模型在分别把簇中心设置为 3 和 5,观察一下数据的变化。注意测试数据集中默认为 3 类,然而 KMeans 是无监督学习模型,不会使用数据集给出的结果进行分类,而是按照 n_clusters 的设置进行分类。这是 KMeans 模型的优点也可以说是缺点,虽然没有受数据集类型的限制,然而在运行前必须先设置簇的数量。实事上在现实场景中,很多数据事先是无法确定簇数量的。
1 def kmean_test(n): 2 #生成数据集 3 X, y = datasets.make_blobs(n_samples=100, n_features=2, random_state=1) 4 #使用KMeans模型,3个簇中心 5 kmean=KMeans(n_clusters=n) 6 model=kmean.fit_predict(X) 7 #显示运算结果 8 plt.scatter(X[:,0],X[:,1],s=50,c=model,marker='^') 9 plt.xlabel('feature0') 10 plt.ylabel('feature1') 11 #显示簇中心 12 center=kmean.cluster_centers_ 13 plt.scatter(center[:,0],center[:,1],s=200,color='red',marker='.') 14 #显示簇边界 15 radii=[cdist(X[model==i],[center]).max() for i,center in enumerate(center)] 16 for c,r in zip(center,radii): 17 axes.add_patch(plt.Circle(c,r,alpha=0.3,zorder=1)) 18 plt.show() 19 20 if __name__=='__main__': 21 kmean_test(3) 22 kmean_test(5)
3 簇中心运行结果
5 簇中心运行结果
下面例子尝试利用 digits 数据集,通过 KMeans 训练,再查看一下分辨手写数字的准确率,可见单凭 KMeans 模型已经可以分辨手写数字的准确率到达将近80% 。
1 def kmean_test(): 2 # 输入测试数据 3 digits=datasets.load_digits() 4 #使用KMeans模型,10个簇中心 5 kmean=KMeans(10) 6 #训练数据 7 model=kmean.fit_predict(digits.data) 8 #计算匹配度 9 labels=np.zeros_like(model) 10 for i in range(10): 11 mask=(model==i) 12 labels[mask]=mode(digits.target[mask])[0] 13 #计算准确率 14 acc=accuracy_score(digits.target,labels) 15 print(acc)
运行结果
还记得在上一篇文章《 Python 机器学习实战 —— 无监督学习(上)》介绍 ML 流形学习中曾经提过, t-SNE 模型是一个非线性嵌入算法,特别擅长保留簇中的数据点。在此尝试把 KMeans 与 t-SNE 相结合一起使用,有意想不到的效果。
运行后可以发现末经过调试的算法,准确率已经可以达到 94% 以上。可见,只要适当地运用无监督学习,也能够精准地实现数据的分类。
1 def kmean_test(): 2 # 输入测试数据 3 digits=datasets.load_digits() 4 #使用t-SNE 模型进行训练 5 tsne=TSNE() 6 model0=tsne.fit_transform(digits.data) 7 #使用KMeans模型进行训练 8 kmean=KMeans(10) 9 model1=kmean.fit_predict(model0) 10 #计算匹配度 11 labels=np.zeros_like(model1) 12 for i in range(10): 13 mask=(model1==i) 14 labels[mask]=mode(digits.target[mask])[0]