kaldi里的聚类机制
这里讲阐述在kaldi里的聚类机制和接口。
可以看Classes and functions related to clustering来了解涉及到的类和函数列表。这里不包括音素决策树聚类(看Decision tree internals和How decision trees are used in Kaldi),尽管这里介绍的类和函数是在音素聚类的代码的底层使用。
The Clusterable interface
TheClusterable类是一个从类GaussClusterable继承来的一个纯虚拟类(GaussClusterable 表示高斯统计量)。未来我们可以添加一些其他类型的从Clusterable继承的clusterable。用 Clusterable类的原因就是它允许我们使用通用的聚类算法。
Clusterable接口的核心概念就是把统计量添加到一起,和用目标函数来衡量。二个Clusterable 对象距离的概念是从分别衡量这两个对象的目标函数得来的,然后把他们添加到一起,和衡量他们的目标函数;目标函数的降低来定义距离。
我们想加进去的Clusterable类的例子在一定程度上包含从一个固定的,共享的混合高斯模型里得带的混合高斯的统计量,和离散观测量的计数(目标函数等于这个分布的否定熵,计算的数量)。
得到类型Clusterable*指针(事实上是GaussClusterable类型) 的一个例子如下:
Vector<BaseFloat> x_stats(10), x2_stats(10);
BaseFloatcount = 100.0, var_floor = 0.01;
// initialize x_stats and x2_stats e.g. as
// x_stats = 100 * mu_i, x2_stats = 100 * (mu_i*mu_i + sigma^2_i)
Clusterable *cl = new GaussClusterable(x_stats, x2_stats, var_floor, count);
Clustering algorithms
我们已经实现了许多通用的聚类算法,这些都列在Algorithms for clustering。在这些算法用的最多的数据结构就是Clusterable接口类的一个vector指针:
std::vector<Clusterable*> to_be_clustered;
vector的索引是聚类的指针的索引。
K-means and algorithms with similar interfaces
调用聚类代码的一个例子如下:
std::vector<Clusterable*> to_be_clustered;
// initialize "to_be_clustered" somehow ...
std::vector<Clusterable*> clusters;
int32num_clust = 10; // requesting 10 clusters
ClusterKMeansOptions opts; // all default.
std::vector<int32> assignments;
ClusterKMeans(to_be_clustered, num_clust, &clusters, &assignments, opts);
当聚类代码被调用时,"assignments" 将告诉你每一个item在"to_be_clustered", 每一个cluster被分配。ClusterKMeans()算法即使对大数据的points也是很有效的;更多的细节可以点击这个函数看看。
有2个算法和ClusterKMeans()有相同的接口:即ClusterBottomUp()和ClusterTopDown()。也许最有用的一个是ClusterTopDown(), 当聚类数量很大时,它比ClusterKMeans()更有效。(它做一个二次分裂,和然后又在叶子上做二次分裂等等)。它被叫做TreeCluster()。
Tree clustering algorithm
TreeCluster()函数把points 聚类成一个二叉树(每个叶子不是仅仅含有一个point,你可以特定叶子的最大数目)。这个函数是非常有用的,举例来说,当为自适应建立一个聚类树。输出格式的更多细节可以看函数的文档。快速浏览的是,在首先是叶子和最后是根结点的拓扑顺序的叶子和非叶子结点,和输出一个告诉你每一个结点的父节点是什么的vector。