介紹一些compose算法,以及這部分的代碼實現。算法
原理部分參考: 走進語音識別中的 WFST(二)spa
能夠看下示例圖:.net
咱們先來看一下 Composition 的效果,圖(a)和圖(b)Composition 後生成了圖(c),從這麼簡單的效果圖咱們大體能夠看出來其實這個操做就是找出知足下面這個條件的轉移:第一個 WFST 的某個轉移上的輸出標籤等於第二個 WFST 的某個轉移上的輸入標籤,而後把這些轉移上的 label 和 weight 分別進行操做: code
固然上面的大白話確定是不嚴謹、不徹底正確的,下面咱們將結合下僞代碼來介紹正確的生成方式。須要注意的是,這裏是一個 epsilon-free 的算法,即第一個 WFST 的任意轉移上的輸出 label 不能爲空(εε)而且第二個 WFST 的任意轉移上的輸入 label 也不能爲空(εε)。xml
下圖作了個流程的示範,筆寫比較方便一點。其實只要認真看懂了上面的僞代碼這邊就能夠跳過不看了。blog
下面在代碼裏驗證一下剛剛的例子:get
$ cat A.fst 0 1 a b 0.1 0 2 b a 0.2 1 3 a a 0.4 1 1 c a 0.3 2 3 b b 0.5 3 0.6 $ cat B.fst 0 1 b c 0.3 1 2 a b 0.4 2 2 a b 0.6 2 0.7 $ cat words.txt a 1 b 2 c 3
#注意,符號表不能有0 fstcompile --isymbols=words.txt --osymbols=words.txt A.fst|fstarcsort --sort_type=olabel > A.bfst fstcompile --isymbols=words.txt --osymbols=words.txt B.fst|fstarcsort --sort_type=ilabel > B.bfst fstprint A.bfst >A.fst.txt fstprint B.bfst >B.fst.txt fsttablecompose A.bfst B.bfst | fstarcsort > C.bfst #fstcompose A.bfst B.bfst >C.bfst #兩個之間結果是同樣的 fstprint C.bfst > C.fst fstdraw --width=25 --height=20 --isymbols=words.txt --osymbols=words.txt C.bfst > Cfst.dot #畫出dot圖 fstdraw --width=25 --height=20 --isymbols=words.txt --osymbols=words.txt A.bfst > Afst.dot fstdraw --width=25 --height=20 --isymbols=words.txt --osymbols=words.txt B.bfst > Bfst.dot dot -Tpng Afst.dot > A.png #畫png圖 dot -Tpng Bfst.dot > B.png dot -Tpng Cfst.dot > C.png
這裏已經個人註釋裏面了,符號表words.txt裏是不能有0的,能夠試一下,有0結果就會錯了,猜想是fst默認0是終止吧,儘可能咱們不用0吧。it
咱們來看下生成的最終的png圖,和例子是同樣的。io
A: table
B:
C: