BIRCH算法简介

BIRCH算法的全称是Balanced Iterative Reducing and Clustering using Hierarchies,它使用聚类特征来表示一个簇,使用聚类特征树(CF-树)来表示聚类的层次结构,算法思路也是“自底向上”的。

解决了Agglomerative算法不能撤销先前步骤的工作的缺陷

CF-树只存储原始数据的特征信息,并不需要存储原始数据信息,内存开销上更优

BIRCH算法只需要遍历一遍原始数据,而Agglomerative算法在每次迭代都需要遍历一遍数据,所以BIRCH在性能也优于Agglomerative

BIRCH是一种增量聚类方法,针对每一个点的聚类决策都是基于当前已经处理过的数据点,而不是全局的数据点。支持对流数据的聚类,BIRCH一开始并不需要所有的数据

BIRCH算法原理

BIRCH算法中引入了两个概念:聚类特征和聚类特征树,以下分别介绍。

聚类特征(CF)

CF是BIRCH增量聚类算法的核心,CF树中得节点都是由CF组成,一个CF是一个三元组,这个三元组就代表了簇的所有信息。给定N个d维的数据点$\{x_1,x_2,…,x_n\}$,CF定义如下:CF =(N,LS,SS)。其中,N是子类中节点的数目,LS是N个节点的线性和,SS是N个节点的平方和。

CF有个特性,即可以求和,具体说明如下:CF1=(n1,LS1,SS1),CF2=(n2,LS2,SS2),则CF1+CF2=(n1+n2, LS1+LS2, SS1+SS2)。假设簇C1中有三个数据点:(2,3),(4,5),(5,6),则CF1={3,(2+4+5,3+5+6),(2^2+4^2+5^2,3^2+5^2+6^2)}={3,(11,14),(45,70)},同样的,簇C2的CF2={4,(40,42),(100,101)},那么,由簇C1和簇C2合并而来的簇C3的聚类特征CF3计算如下:CF3={3+4,(11+40,14+42),(45+100,70+101)}={7,(51,56),(145,171)}

另外在介绍两个概念:簇的质心和簇的半径。假如一个簇中包含n个数据点:$X_i, i=1,2,3…n$,则质心$X_0$和半径R计算公式如下:

$$X_0=\frac{\sum_{i=1}^{n}X_i}{n}$$

$$R = \sqrt{\frac{\sum_{i=1}^{n}(X_i-X_0)^2}{n}}$$

其中,簇半径表示簇中所有点到簇质心的平均距离。CF中存储的是簇中所有数据点的特性的统计和,所以当我们把一个数据点加入某个簇的时候,那么这个数据点的详细特征,例如属性值,就丢失了,由于这个特征,BIRCH聚类可以在很大程度上对数据集进行压缩。

聚类特征树(CF tree)

CF tree的结构类似于一棵B-树,它有两个参数:内部节点平衡因子B,叶节点平衡因子L,簇半径阈值T。树中每个节点最多包含B个孩子节点,记为$({CF}_i,{CHILD}_i)$,1<=i<=B,${CF}_i$是这个节点中的第i个聚类特征,${CHILD}_i$指向节点的第i个孩子节点,对应于这个节点的第i个聚类特征。例如,一棵高度为3,B为2,L为3的一棵CF树的例子如图所示:

聚类特征树CF Tree的生成

一棵CF树是一个数据集的压缩表示,叶子节点的每一个输入都代表一个簇C,簇C中包含若干个数据点,并且原始数据集中越密集的区域,簇C中包含的数据点越多,越稀疏的区域,簇C中包含的数据点越少,簇C的半径小于等于T。随着数据点的加入,CF树被动态的构建,插入过程有点类似于B-树。加入算法表示如下:

(1)从根节点开始,自上而下选择最近的孩子节点

(2)到达叶子节点后,检查最近的元组CFi能否吸收此数据点

是,更新CF值

否,是否可以添加一个新的元组

是,添加一个新的元组

否则,分裂最远的一对元组,作为种子,按最近距离重新分配其它元组

(3)更新每个非叶节点的CF信息,如果分裂节点,在父节点中插入新的元组,检查分裂,直到root

下面我们看看怎么生成CF Tree。我们先定义好CF Tree的参数: 即内部节点的最大CF数B, 叶子节点的最大CF数L, 叶节点每个CF的最大样本半径阈值T。

在最开始的时候,CF Tree是空的,没有任何样本,我们从训练集读入第一个样本点,将它放入一个新的CF三元组A,这个三元组的N=1,将这个新的CF放入根节点,此时的CF Tree如下图:

现在我们继续读入第二个样本点,我们发现这个样本点和第一个样本点A,在半径为T的超球体范围内,也就是说,他们属于一个CF,我们将第二个点也加入CF A,此时需要更新A的三元组的值。此时A的三元组中N=2。此时的CF Tree如下图:

此时来了第三个节点,结果我们发现这个节点不能融入刚才前面的节点形成的超球体内,也就是说,我们需要一个新的CF三元组B,来容纳这个新的值。此时根节点有两个CF三元组A和B,此时的CF Tree如下图:

当来到第四个样本点的时候,我们发现和B在半径小于T的超球体,这样更新后的CF Tree如下图:

那个什么时候CF Tree的节点需要分裂呢?假设我们现在的CF Tree 如下图, 叶子节点LN1有三个CF, LN2和LN3各有两个CF。我们的叶子节点的最大CF数L=3。此时一个新的样本点来了,我们发现它离LN1节点最近,因此开始判断它是否在sc1,sc2,sc3这3个CF对应的超球体之内,但是很不幸,它不在,因此它需要建立一个新的CF,即sc8来容纳它。问题是我们的L=3,也就是说LN1的CF个数已经达到最大值了,不能再创建新的CF了,怎么办?此时就要将LN1叶子节点一分为二了。

将LN1里所有CF元组中,找到两个最远的CF做这两个新叶子节点的种子CF,然后将LN1节点里所有CF sc1, sc2, sc3,以及新样本点的新元组sc8划分到两个新的叶子节点上。将LN1节点划分后的CF Tree如下图:

如果我们的内部节点的最大CF数B=3,则此时叶子节点一分为二会导致根节点的最大CF数超了,也就是说,我们的根节点现在也要分裂,分裂的方法和叶子节点分裂一样,分裂后的CF Tree如下图:

有了上面这一系列的图,相信大家对于CF Tree的插入就没有什么问题了,总结下CF Tree的插入:

从根节点向下寻找和新样本距离最近的叶子节点和叶子节点里最近的CF节点

如果新样本加入后,这个CF节点对应的超球体半径仍然满足小于阈值T,则更新路径上所有的CF三元组,插入结束。否则转入3.

如果当前叶子节点的CF节点个数小于阈值L,则创建一个新的CF节点,放入新样本,将新的CF节点放入这个叶子节点,更新路径上所有的CF三元组,插入结束。否则转入4。

4.将当前叶子节点划分为两个新叶子节点,选择旧叶子节点中所有CF元组里超球体距离最远的两个CF元组,分布作为两个新叶子节点的第一个CF节点。将其他元组和新样本元组按照距离远近原则放入对应的叶子节点。依次向上检查父节点是否也要分裂,如果需要按和叶子节点分裂方式相同。

对于上图所示的CF-树,假设现在添加一个新的簇$CF_12$,这个簇距离$CF_8$最近,但是不满足被吸收的条件($CF_8$和$CF_12$之间的距离大于了阈值),加入过程如下:

用$CF_8$跟$CF_1$和$CF_2$比较距离,发现离$CF_1$更近,找到$CF_1$的子节点$CF_3$和$CF_4$

同步骤1,找到$CF_3$的子节点,发现为叶子节点4:$\{CF_6,CF_7,CF_8\}$

尝试把$CF_12$加入到叶子节点4,此时节点4的数量为4,超过了我们设定的L值3,所以现在需要分离节点4,将$CF_8$和$CF_12$分到一个新的叶子节点,然后剩下$CF_6$和$CF_7$

同时在节点2中加入一个新的非叶子节点,此时节点2的数量为3,大于我们设定的B值2,进一步拆分节点2为两个新的非叶子节点

同步骤4,知道所有的节点都满足CF-树种B=2,L=3的约束

更新所有CF节点对应的特征值,得到如下的新CF-树:

BIRCH算法流程

上面讲了半天的CF Tree,终于我们可以步入正题BIRCH算法,其实将所有的训练集样本建立了CF Tree,一个基本的BIRCH算法就完成了,对应的输出就是若干个CF节点,每个节点里的样本点就是一个聚类的簇。也就是说BIRCH算法的主要过程,就是建立CF Tree的过程。当然,真实的BIRCH算法除了建立CF Tree来聚类,其实还有一些可选的算法步骤的,现在我们就来看看 BIRCH算法的流程:

将所有的样本依次读入,在内存中建立一颗CF Tree, 建立的方法参考上一节。

(可选)将第一步建立的CF Tree进行筛选,去除一些异常CF节点,这些节点一般里面的样本点很少。对于一些超球体距离非常近的元组进行合并

(可选)利用其它的一些聚类算法比如K-Means对所有的CF元组进行聚类,得到一颗比较好的CF Tree.这一步的主要目的是消除由于样本读入顺序导致的不合理的树结构,以及一些由于节点CF个数限制导致的树结构分裂。

(可选)利用第三步生成的CF Tree的所有CF节点的质心,作为初始质心点,对所有的样本点按距离远近进行聚类。这样进一步减少了由于CF Tree的一些限制导致的聚类不合理的情况。

从上面可以看出,BIRCH算法的关键就是步骤1,也就是CF Tree的生成,其他步骤都是为了优化最后的聚类结果。

BIRCH算法的主流程如下:

BIRCH算法小结

BIRCH算法可以不用输入类别数K值,这点和K-Means,Mini Batch K-Means不同。如果不输入K值,则最后的CF元组的组数即为最终的K,否则会按照输入的K值对CF元组按距离大小进行合并。一般来说,BIRCH算法适用于样本量较大的情况,这点和Mini Batch K-Means类似,但是BIRCH适用于类别数比较大的情况,而Mini Batch K-Means一般用于类别数适中或者较少的时候。BIRCH除了聚类还可以额外做一些异常点检测和数据初步按类别规约的预处理。但是如果数据特征的维度非常大,比如大于20,则BIRCH不太适合,此时Mini Batch K-Means的表现较好。对于调参,BIRCH要比K-Means,Mini Batch K-Means复杂,因为它需要对CF Tree的几个关键的参数进行调参,这几个参数对CF Tree的最终形式影响很大。

BIRCH算法的主要优点有:

节省内存。叶子节点放在磁盘分区上,非叶子节点仅仅是存储了一个CF值,外加 指向父节点和孩子节点的指针。

速度快。合并两个两簇只需要两个类簇的CF元组直接相加即可,计算两个簇的距 离只需要用到(N,LS,SS)这三个值。

一遍扫描数据库即可建立CF Tree。

可识别噪声点。建立好CF Tree后把那些包含数据点少的MinCluster当作outlier。

由于CF Tree是高度平衡的,所以在树上进行插入或查找操作很快。

BIRCH算法的主要缺点有:

结果依赖于数据点的插入顺序。本属于同一个簇的点可能由于插入顺序相差很远 而分到不同的簇中,即使同一个点在不同的时刻被插入,也会被分到不同的簇中。

对非球状的簇聚类效果不好。这取决于簇直径和簇间距离的计算方法。

对高维数据聚类效果不好。

由于每个节点只能包含一定数目的子节点,最后得出来的簇可能和自然簇相差很 大。BIRCH适合于需要产生大量的子簇的场景,但在整个过程中算法一旦中断, 一切必须从头再来。

局部性导致了BIRCH的聚类效果欠佳。当一个新数据点要插入时,它只跟很少一部分簇进行了相似性(通过计算簇间距离)比较,高效率不一定带来好效果。

在scikit-learn中使用BIRCH

在scikit-learn中,BIRCH类实现了基于特征树CF Tree的聚类。因此要使用BIRCH来聚类,关键是对CF Tree结构参数的处理。在CF Tree中,几个关键的参数为内部节点的最大CF数B, 叶子节点的最大CF数L, 叶节点每个CF的最大样本半径阈值T。这三个参数定了,CF Tree的结构也基本确定了,最后的聚类效果也基本确定。可以说BIRCH的调参就是调试B,L和T。至于类别数K,此时反而是可选的,不输入K,则BIRCH会对CF Tree里各叶子节点CF中样本的情况自己决定类别数K值,如果输入K值,则BIRCH会CF Tree里各叶子节点CF进行合并,直到类别数为K。

class sklearn.cluster.Birch(*, threshold=0.5, branching_factor=50, n_clusters=3, compute_labels=True, copy=True)

参入参数:

threshold:即叶节点每个CF的最大样本半径阈值T,它决定了每个CF里所有样本形成的超球体的半径阈值。一般来说threshold越小,则CF Tree的建立阶段的规模会越大,即BIRCH算法第一阶段所花的时间和内存会越多。但是选择多大以达到聚类效果则需要通过调参决定。默认值是5.如果样本的方差较大,则一般需要增大这个默认值。

branching_factor:即CF Tree内部节点的最大CF数B,以及叶子节点的最大CF数L。这里scikit-learn对这两个参数进行了统一取值。也就是说,branching_factor决定了CF Tree里所有节点的最大CF数。默认是50。如果样本量非常大,比如大于10万,则一般需要增大这个默认值。选择多大的branching_factor以达到聚类效果则需要通过和threshold一起调参决定

n_clusters:即类别数K,在BIRCH算法是可选的,如果类别数非常多,我们也没有先验知识,则一般输入None,此时BIRCH算法第4阶段不会运行。但是如果我们有类别的先验知识,则推荐输入这个可选的类别值。默认是3,即最终聚为3类。

compute_labels:布尔值,表示是否标示类别输出,默认是True。一般使用默认值挺好,这样可以看到聚类效果。

实例代码:

from sklearn.datasets import make_blobs

from sklearn.cluster import Birch

import matplotlib.pyplot as plt

# 生成样本点

centers = [[1, 1], [-1, -1], [1, -1]]

X, labels = make_blobs(n_samples=750, centers=centers,

cluster_std=0.4, random_state=0)

clustering = Birch(n_clusters=3).fit(X)

plt.figure(figsize=(10, 8))

plt.scatter(X[:, 0], X[:, 1], c=clustering.labels_, cmap='prism')

plt.show()

参考链接:

birch聚类 java_层次聚类改进算法之BIRCH相关推荐

  1. 聚类之层次聚类、基于划分的聚类(…

    5.聚类之层次聚类.基于划分的聚类(k-means).基于密度的聚类.基于模型的聚类 目录(?)[-] 1.      一层次聚类 1.      层次聚类的原理及分类 2.      层次聚类的流程 ...

  2. 说话人聚类--谱聚类和层次聚类

    谱聚类和层次聚类 在讯飞实习了一个月了,做了点说话人聚类的工作,现在总结一下主要用到的谱聚类和层次聚类. 层次聚类 在层次聚类这块,我主要学习了 凝聚型层次聚类和 BIRCH方法,主要参考的博客有 [ ...

  3. KMEANS均值聚类和层次聚类:亚洲国家地区生活幸福质量异同可视化分析和选择最佳聚类数...

    阅读全文:http://tecdat.cn/?p=24198 <世界幸福报告>是可持续发展解决方案网络的年度报告,该报告使用盖洛普世界民意调查的调查结果研究了150多个国家/地区的生活质量 ...

  4. 使用MATLAB进行K-means聚类和层次聚类

    1.分别使用k-means聚类和层次聚类,将以下八个点分为3个类簇.A1=(2,10),A2=(2,5),A3=(8,4),A4=(5,8),A5=(7,5), A6=(6,4), A7=(1,2), ...

  5. 聚类(2)——层次聚类 Hierarchical Clustering

    聚类系列: 聚类(序)----监督学习与无监督学习 聚类(1)----混合高斯模型 Gaussian Mixture Model 聚类(2)----层次聚类 Hierarchical Clusteri ...

  6. 【R】【密度聚类、层次聚类、期望最大化聚类】

    文章目录 1.对数据集进行加载.预处理集可视化 1.1 加载数据集 1.2 数据预处理 1.3 将样本点进行可视化 2.密度聚类(DBSCAN 算法) 2.1 加载程序包 2.2 设置聚类参数阈值并可 ...

  7. 【机器学习】聚类【Ⅴ】密度聚类与层次聚类

    主要来自周志华<机器学习>一书,数学推导主要来自简书博主"形式运算"的原创博客,包含自己的理解. 有任何的书写错误.排版错误.概念错误等,希望大家包含指正. 由于字数限 ...

  8. Python计算机视觉编程第六章——图像聚类(K-means聚类,DBSCAN聚类,层次聚类,谱聚类,PCA主成分分析)

    Python计算机视觉编程 图像聚类 (一)K-means 聚类 1.1 SciPy 聚类包 1.2 图像聚类 1.1 在主成分上可视化图像 1.1 像素聚类 (二)层次聚类 (三)谱聚类 图像聚类 ...

  9. 【视频】KMEANS均值聚类和层次聚类:R语言分析生活幸福指数可视化|数据分享...

    原文链接:http://tecdat.cn/?p=24198 聚类是将总体或数据点划分为多个组的任务,以使同一组中的数据点与同一组中的其他数据点更相似,而与其他组中的数据点不相似.它基本上是基于它们之 ...

最新文章

  1. C++的STL栈实现队列
  2. 最难忘的一天----一周年记
  3. Html5 History API解析
  4. BlockChain:《Blockchain Gate》听课笔记——以POW机制为例阐述共识机制的激励相容设计
  5. 求最短路径——BFS、Dijkstra、Prim算法对比
  6. 计算机计算各科及格率,某两个班数学考试成绩如下,要求计算分析指标,用..._投资分析考试_帮考网...
  7. linux bash文件,linux之bash配置文件
  8. pandas(七) -- 数据分组
  9. 腾讯,字节,阿里,小米,京东大厂Offer拿到手软!绝对干货
  10. delphi中richedit中光标如何定位到最后_嵌入式开发之Linux系统中Vi编辑器的使用
  11. 构建入门Restful Web服务
  12. exec调用oracle,exec 和 call 用法详解
  13. java 动态执行代码_java中动态执行一段代码
  14. 化验室计算机分级管理,[欧盟法规] 欧盟受控实验室之《计算机化系统验证》摒弃了GAMP5的分类? (1之3)...
  15. SPTD和虚拟光驱 以后装机我再也不带酒精52%了
  16. Flask后端实践 连载十三 Flask输出Excel报表
  17. Windows下使用bat脚本批量创建文件夹
  18. linux mint能用安卓,如何在Ubuntu和Linux Mint上安装Android Studio
  19. 基于ART-PI SPI驱动W25Q128
  20. Java方法的分类及使用

热门文章

  1. c语言sprintf函数 long,基于C语言sprintf函数的深入理解
  2. 流量易得情怀难守?董宇辉爆火用半年,新东方“暴雷”只需一周?
  3. mysql数据库如何做缓存_MySql数据库缓存
  4. Qt终端输入qtcreator打不开IDE,点击图标是可以打开的
  5. android权限工具,Android权限扫描工具
  6. D - 人见人爱A+B(有关进制问题)
  7. element-plus table表格换行变色以及部分el自带样式的修改
  8. vim使用技巧之查找字符串
  9. 哪些耳机音质不错?比苹果耳机音质好的耳机推荐
  10. jsonpath:从庞大的接口返回结果(返回结果为字典类型)中取字段值