本节及后续章节将介绍深度学习中的几种聚类算法,所选方法都在Sklearn库中聚类模块有具体实现。本节为上篇,将介绍几种相对基础的聚类算法,包括K-均值算法和均值漂移算法。
目录
聚类(Clustering)是机器学习中的一类无监督学习方法。它是按照某个特定标准(如距离)把一个数据集分割成不同的类或簇(cluster),使得同一个簇内的数据对象的相似性尽可能大,同时不在同一个簇中的数据对象的差异性也尽可能地大。也即聚类后同一类的数据尽可能聚集到一起,不同类数据尽量分离。
按照策略不同,传统的聚类方法主要可以分为三类:划分式聚类方法(Partition-based Methods)、基于密度的聚类方法(Density-based methods)和层次化聚类方法(Hierarchical Methods)等。
除此之外,还有一些高级的方法,如谱聚类(Spectral Clustering ):其主要思想是把所有的数据看做空间中的点,这些点之间可以用边连接起来。距离较远的两个点之间的边权重值较低,而距离较近的两个点之间的边权重值较高,通过对所有数据点组成的图进行切图,让切图后不同的子图间边权重和尽可能的低,而子图内的边权重和尽可能的高,从而达到聚类的目的。
在Sklearn的cluster(聚类)子模块中,提供了上述几种典型的聚类算法,具体函数名称见下表:
上表列出的是Sklearn实现的几种主要聚类算法,在sklearn_cluster子库中,一共实现了12种聚类方法,官网用表格的形式列出了方法对比。下图是官网给出的使用不同算法对不同种类分别的数据进行聚类的结果对比图,每种算法的性能特点可见一斑。
K均值是一种非常基础的划分式聚类算法,它的主要思想是:在给定K值(与类的数目对应)和K个初始类簇中心点的前提下,把每个样本点分到离其最近的类簇中心点所代表的类簇中,所有点分配完毕之后,根据一个类簇内的所有点重新计算该类簇的中心点,然后再迭代的进行分配点和更新类簇中心点的步骤,直至类簇中心点的变化很小,或者达到指定的迭代次数。
参考周志华老师的《机器学习》一书中有关K均值的算法流程。如下图所示:
从流程来看K均值算法计算步骤包括两个核心步骤:一是计算每一个样本点到类簇中心的距离;二是根据类簇内的各点计算新的簇类中心。简单而言,就是如何计算各样本点与类心的距离,以及如何根据分类结果更新类心。
在SKlearn中,使用sklearn.cluster.KMeans函数,实现K均值算法。
以下是该函数的声明:
看一下histogram函数的声明:
class sklearn.cluster.KMeans(n_clusters=8, *, init='k-means++', n_init='auto', max_iter=300, tol=0.0001, verbose=0, random_state=None, copy_x=True, algorithm='lloyd')
部分参数说明:
- image:输入图像。
- nbins:用于计算直方图的bin的数目。
- source_range:待补充。
- normalize:待补充 。
- channel_axis:待补充。
返回值:
- hist:灰度直方图的数值,数组类型。如果通道数不止一个,则hist是二维数组。
- cluster_centers:Coordinates of cluster centers. If the algorithm stops before fully converging (see tol and max_iter), these will not be consistent with labels_.
- labels:Labels of each point
- inertia:Sum of squared distances of samples to their closest cluster center, weighted by the sample weights if provided.
- n_iter:Number of iterations run.
- n_features_in:Number of features seen during fit.
- feature_names_in_:Names of features seen during fit. Defined only when X has feature names that are all strings.
本节将介绍如何使用Kmean函数实现对IRIS数据集的聚类。
- import matplotlib.pyplot as plt
-
- import mpl_toolkits.mplot3d # noqa: F401
- import numpy as np
-
- from sklearn import datasets
- from sklearn.cluster import KMeans
-
- np.random.seed(5)
-
- iris = datasets.load_iris()
- X = iris.data
- y = iris.target
-
- estimators = [
- ("k_means_iris_8", KMeans(n_clusters=8)),
- ("k_means_iris_3", KMeans(n_clusters=3)),
- ("k_means_iris_bad_init", KMeans(n_clusters=3, n_init=1, init="random")),
- ]
-
- fig = plt.figure(figsize=(10, 8))
- titles = ["8 clusters", "3 clusters", "3 clusters, bad initialization"]
- for idx, ((name, est), title) in enumerate(zip(estimators, titles)):
- ax = fig.add_subplot(2, 2, idx + 1, projection="3d", elev=48, azim=134)
- est.fit(X)
- labels = est.labels_
-
- ax.scatter(X[:, 3], X[:, 0], X[:, 2], c=labels.astype(float), edgecolor="k")
-
- ax.xaxis.set_ticklabels([])
- ax.yaxis.set_ticklabels([])
- ax.zaxis.set_ticklabels([])
- ax.set_xlabel("Petal width")
- ax.set_ylabel("Sepal length")
- ax.set_zlabel("Petal length")
- ax.set_title(title)
-
- # Plot the ground truth
- ax = fig.add_subplot(2, 2, 4, projection="3d", elev=48, azim=134)
-
- for name, label in [("Setosa", 0), ("Versicolour", 1), ("Virginica", 2)]:
- ax.text3D(
- X[y == label, 3].mean(),
- X[y == label, 0].mean(),
- X[y == label, 2].mean() + 2,
- name,
- horizontalalignment="center",
- bbox=dict(alpha=0.2, edgecolor="w", facecolor="w"),
- )
-
- ax.scatter(X[:, 3], X[:, 0], X[:, 2], c=y, edgecolor="k")
-
- ax.xaxis.set_ticklabels([])
- ax.yaxis.set_ticklabels([])
- ax.zaxis.set_ticklabels([])
- ax.set_xlabel("Petal width")
- ax.set_ylabel("Sepal length")
- ax.set_zlabel("Petal length")
- ax.set_title("Ground Truth")
-
- plt.subplots_adjust(wspace=0.25, hspace=0.25)
- plt.show()
K-means Clustering — scikit-learn 1.5.0 documentation
K均值算法比较简单,但有几个方面需要注意。