首页 > 科技 > 第34集 python机器学习:凝聚聚类

第34集 python机器学习:凝聚聚类

凝聚聚类:凝聚聚类是指许多基于相同原则构建的聚类算法。这一原则是:算法首先声明每个点是自己的簇,然后合并两个最相似的簇,直到满足某种停止条件为止。

scikit-learn中实现的停止准则是簇的个数,因此相似簇被合并,直到仅剩下指定的簇个数。还有一些链接准则,规定如何度量“最相似簇”,这种度量法则总是定义在两个现有的簇中间。

scikit-learn中实现了以下三种选项:

ward:默认选项,ward挑选两个簇来合并,使得所有簇中的方差增加最小,这样通常会得到大小差不多相等的簇。

average:average链接将簇中所有点之间平均距离最小的两个簇进行合并

complete:complete链接(也成为了最大链接)将簇中点之间最大距离最小的两个簇合并。

其中,ward适用于大多数数据,不过如果初中的成员个数非常不同(比如其中的一个簇要比另外其他所有簇大得多),那么使用average和complete的效果可能会更好。

mglearn.plots.plot_agglomerative_algorithm()

运行后显示聚类算法的基本过程:


凝聚聚类用迭代的方法合并两个最接近的簇

从上图的运行结果可知,簇的合并在最开始,每个点自成一簇。然后在每一个步骤中,相距最近的两个簇被合并。在前四个步骤中,选出两个单点簇合并使其变为两个点簇。然后继续扩张,合并到三个点簇、4个点簇等等,直到最终达到我们制定的只剩下三个簇为止。

下面我们来看凝聚聚类对我们以前使用到的make_blobs这个数据集使用简单的三类簇数据效果如何,这里由于凝聚算法不能对新数据点做出预测,故而没有predict方法,所以我们该用fit_predict方法。代码如下:

from sklearn.cluster import AgglomerativeClustering

x, y = make_blobs(random_state=1)

agg = AgglomerativeClustering(n_clusters=3)

assignment = agg.fit_predict(x)

mglearn.discrete_scatter(x[:, 0], x[:, 1], assignment)

plt.xlabel("feature 0 value")

plt.ylabel("feature 1 value")

运行后结果如下图:


使用3个簇的凝聚聚类的簇分配

正如所料,算法完美的完成了聚类。虽然凝聚聚类的scikit-learn实现需要你指定希望算法找到的簇个数,但凝聚聚类方法为选择正确的个数提供了一些帮助。下面我们来看一下有哪些帮助:

1、 层次凝聚与树状图

凝聚聚类生成了所谓的层次凝聚,聚类过程迭代进行,每个点都从一个单点变为属于最终的某个簇,每个中间步骤都提供了数据的一种聚类(簇的个数也不相同)。有时候,同时查看所有可能的聚类是有帮助的,下面这个例子有助于我们深入了解每个簇如何分解为较小的簇:

mglearn.plots.plot_agglomerative()

运行结果如下:


凝聚聚类生成的层次化的簇分配(用线表示),以及带有编号的数据点

尽管这种可视化为层次聚类提供了非常详细的视图,但它依赖于数据的二维性质,因此不能用于二维以上的数据集,但是我们却可以利用树状图来处理多维数据。

不过,目前scikit-learn没有绘制树状图的功能,但是我们可以利用Scipy轻松生成树状图。Scipy的凝聚类算法接口与scikit-learn稍有不同,Scipy提供了一个函数,接受数据组x并计算一个链接数组,他对层次聚类的相似度进行编码,然后我们可以将这个链接数组提供给Scipy的dendrogram函数来绘制树状图。

from sklearn.cluster import AgglomerativeClustering

#从scipy中导入dendrogram函数和ward函聚类数

from scipy.cluster.hierarchy import dendrogram, ward

x, y = make_blobs(random_state=0, n_samples=12)

#将ward聚类应用于数组x

#scipy的ward函数返回一个数组,指定执行凝聚聚类时跨越的距离

linkage_array = ward(x)

#现在为包含粗之间距离的linkage_array绘制树状图

dendrogram(linkage_array)

#在树中标记划分成两个簇或三个簇的位置

ax = plt.gca()

bounds = ax.get_xbound()

ax.plot(bounds, [7.25, 7.25], '--', c='k')

ax.plot(bounds, [4, 4], '--', c='k')

ax.text(bounds[1], 7.25, 'two cluster', va='center', fontdict={'size': 15})

ax.text(bounds[1], 4, 'three cluster', va='center', fontdict={'size': 15})

plt.xlabel("sample index")

plt.ylabel("cluster distance")

运行后对应结果如下:


聚类树状图(用线表示划分成两个簇和三个簇)

树状图在底部显示数据点(编号从0-11),然后这些点(表示单点簇)作为叶节点给每一棵树没合并两个簇就添加一个新的父节点(从下往上看),图中的Y轴不仅说明凝聚算法中何时合并,每个分支的长度还表示被合并簇之前的距离。这里最长的分支标记为“three cluster”(三个簇)的虚线表示,它们是最长分支,这表示从三个簇到两个簇的过程中合并了一些距离非常远的点,由途中可以看出,将剩下的两个簇合并为一个簇也需要跨越相对较大的距离。

不幸的是,凝聚聚类仍然无法分离想two_moons数据集这样复杂的形状,下面我们将学习另一种算法——DBSCAN来解决这个问题。


本文来自投稿,不代表本人立场,如若转载,请注明出处:http://www.souzhinan.com/kj/257758.html