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中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章