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。