kaldi中的hmm-topology介紹
kaldi中的hmm-topology介紹
kaldi中是對音素進行建模,使用HMM模型。一般情況下每個音素有3個狀態,每個狀態有2個弧。靜音音素sil可能有5個狀態,且每個狀態可能不止2個弧。
kaldi中音素的HMM模型的topo檔案,一般是由指令碼utils/gen_topo.pl生成。一個示例如下:
<Topology>
<TopologyEntry>
<ForPhones> 1 2 3 4 5 6 7 8 </ForPhones>
<State> 0 <PdfClass> 0
<Transition> 0 0.5
<Transition> 1 0.5
</State>
<State> 1 <PdfClass> 1
<Transition> 1 0.5
<Transition> 2 0.5
</State>
<State> 2 <PdfClass> 2
<Transition> 2 0.5
<Transition> 3 0.5
</State>
<State> 3
</State>
</TopologyEntry>
</Topology>
上面的示例topo檔案,描述了音素1、2、3、4、5、6、7和8這8個音素的拓撲結構。它們這8個音素的拓撲結構是一模一樣的,都是3個狀態,序號為0到2;最後一個3狀態是結束狀態,或叫“非發射狀態”。
hmm-topology.h檔案中定義了類HmmTopology,用來表示所有音素的topo結構。這個類是比較簡單和形象的。這裡給出類的定義。
注意:這裡對原始碼進行了修改,以方面閱讀和理解
class HmmTopology {
public:
/// A structure defined inside HmmTopology to represent a HMM state.
struct HmmState {
int32 forward_pdf_class;
int32 self_loop_pdf_class;
std::vector<std::pair<int32, BaseFloat> > transitions;
HmmState(): forward_pdf_class(-1), self_loop_pdf_class(-1) { }
HmmState(int32 i): forward_pdf_class(i), self_loop_pdf_class(i) { }
};
/// TopologyEntry is a typedef that represents the topology of
/// a single (prototype) state.
typedef std::vector<HmmState> TopologyEntry;
void Read(std::istream &is, bool binary);
void Write(std::ostream &os, bool binary) const;
/// Returns the topology entry (i.e. vector of HmmState) for this phone;
/// will throw exception if phone not covered by the topology.
const TopologyEntry &TopologyForPhone(int32 phone) const{
return entries_[phone2idx_[phone]];
}
HmmTopology() {}
private:
std::vector<int32> phones_; // list of all phones we have topology for. Sorted, uniq. no epsilon (zero) phone.
std::vector<int32> phone2idx_; // map from phones to indexes into the entries vector (or -1 for not present).
std::vector<TopologyEntry> entries_;
};
可以看出來,這個類其實是很簡單的。
音素的HMM結構,在被指定之後,在後面的訓練或者解碼過程中,都不會再改變。所以這裡也只要理解成員變數的意義,能看懂最基本的讀和寫函式已經基本的使用就可以了。
HmmTopology的成員變數很少,只有3個。phones_存放了音素,phone2idx是個索引表,根據這個索引表,能找到音素的拓撲結構。通過閱讀上面的TopologyForPhone函式可以清楚看出其作用。entries_存放了具體的拓撲結構。就像上面的例子一樣,8個音素的拓撲結構是一模一樣的,所以entries_中,只要存放一份拓撲結構就可以了,這個是所有音素共享的。
如果用一個圖來表示上面例子中的topo在類中的樣子,可以看下圖。
幾個問題的說明:
1、為什麼HmmState中的pdf_class有兩個。
在早先版本的kaldi中,是隻有一個pdf_class的。後來為了支援更復雜的一些hmm結構,就設計為了兩個pdf_class。不過,對於一般的情況,跑普通的gmm-hmm模型,跑tdnn等,完全不用擔心。這兩個pdf_class的值是完全一樣的。
2、HmmState中的transitions中,給出了下一跳的概率,這個值會隨著訓練而不斷更新嗎?
不會。這個概率值只在初始化的時候使用一次,今後不再使用。訓練生成的新的轉移概率,會儲存在transition-model中。
---------------------
作者:shzyiwai
來源:CSDN
原文:https://blog.csdn.net/u013677156/article/details/79133123
版權宣告:本文為博主原創文章,轉載請附上博文連結!