日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从yesno模型入门kaldi语音识别

發(fā)布時間:2023/12/31 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从yesno模型入门kaldi语音识别 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

yesno模型

?

kaldi常用工具 http://blog.csdn.net/zjm750617105/article/details/52548798

kaldi官網(wǎng)工具大全http://kaldi-asr.org/doc/tools.html

yesno孤立詞識別kaldi腳本http://www.cnblogs.com/welen/p/7485151.html

執(zhí)行 run.sh入口程序

?

# 數(shù)據(jù)處理階段

?

?

. 訓(xùn)練和測試數(shù)據(jù)預(yù)處理階段

執(zhí)行local/prepare_data.sh waves_yesno

?

1. 是把waves_yeno目錄下的文件名全部保存到waves_all.list中.

ls -1 $waves_dir > data/local/waves_all.list

?

2.使用perl腳本create_yesno_waves_test_train.pl把樣本集一半數(shù)據(jù)共30個用作訓(xùn)練文件名列表存在 data/local/waves.train,另一半共30個識別測試文件名列表存到data/local/waves.test。

?

3.create_yesno_wav_scp.pl腳本把waves.test文件進(jìn)行標(biāo)注存到data/local/test_yesno_wav.scp,格式:

1_0_0_0_0_0_0_0 waves_yesno/1_0_0_0_0_0_0_0.wav

1_0_0_0_0_0_0_1 waves_yesno/1_0_0_0_0_0_0_1.wav

..

?

4.create_yesno_wav_scp.pl腳本把waves.train進(jìn)行標(biāo)注存到data/local/train_yesno_wav.scp,格式:

0_0_0_0_1_1_1_1 waves_yesno/0_0_0_0_1_1_1_1.wav

0_0_0_1_0_0_0_1 waves_yesno/0_0_0_1_0_0_0_1.wav

?

?

5.create_yesno_txt.pl腳本把waves.test進(jìn)行標(biāo)注到data/local/test_yesno.txt,格式:

1_0_0_0_0_0_0_0 YES NO NO NO NO NO NO NO

1_0_0_0_0_0_0_1 YES NO NO NO NO NO NO YES

?

6.create_yesno_txt.pl腳本把waves.train進(jìn)行標(biāo)注到data/local/train_yesno.txt,格式:

0_0_0_0_1_1_1_1 NO NO NO NO YES YES YES YES

0_0_0_1_0_0_0_1 NO NO NO YES NO NO NO YES

?

7. data/local 目錄創(chuàng)建一個文件lm_tg.arpa內(nèi)容:

\data\

ngram 1=4

?

\1-grams:

-1 NO

-1 YES

-99 <s>

-1 </s>

?

\end\

?

8. 從WSJ樣本復(fù)制階段

?

8.1.創(chuàng)建目錄data/train_yesno 和data/test_yesno

?

8.2. 把data/local/test_yesno_wav.scp 復(fù)制到data/test_yesno/wav.scp

把data/local/train_yesno_wav.scp 復(fù)制到data/train_yesno/wav.scp

?

8.3.把data/local/train_yesno.txt 復(fù)制到 data/train_yesno/text

把data/local/test_yesno .txt 復(fù)制到 data/test_yesno/text

?

8.4.通過awk文本處理工具處理text文本 輸出到 data/train_yesno/utt2spk文件 和 data/test_yesno/utt2spk文件,這個兩個文件分別是發(fā)音和人對應(yīng)關(guān)系,以及人和其發(fā)音 id的對應(yīng)關(guān)系.由于只有一個人的發(fā)音,所以這里都用global來表示發(fā)音.格式:

?

1_0_0_0_0_0_0_0 global

1_0_0_0_0_0_0_1 global

1_0_0_0_0_0_1_1 global

...

?

?

8.5.通過 utils/utt2spk_to_spk2utt.pl 腳本 把 utt2spk 轉(zhuǎn)換成spk2utt 格式:

global 1_0_0_0_0_0_0_0 1_0_0_0_0_0_0_1 1_0_0_0_0_0_1_1 1_0_0_0_1_0_0_1 1_0_0_1_0_1_1_1 1_0_1_0_1_0_0_1 1_0_1_1_0_1_1_1 1_0_1_1_1_0_1_0 1_0_1_1_1_1_0_1 1_1_0_0_0_0_0_1 1_1_0_0_0_1_1_1 1_1_0_0_1_0_1_0 1_1_0_0_1_0_1_1 1_1_0_0_1_1_1_0 1_1_0_1_0_1_0_0 1_1_0_1_0_1_1_0 1_1_0_1_1_0_0_1 1_1_0_1_1_0_1_1 1_1_0_1_1_1_1_0 1_1_1_0_0_0_0_1 1_1_1_0_0_1_0_1 1_1_1_0_0_1_1_1 1_1_1_0_1_0_1_0 1_1_1_0_1_0_1_1 1_1_1_1_0_0_1_0 1_1_1_1_0_1_0_0 1_1_1_1_1_0_0_0 1_1_1_1_1_1_0_0 1_1_1_1_1_1_1_1

?

此時目錄結(jié)構(gòu)如下:

data

├───local

<span style="color:#00000a"><code>│ ├───</code><code>waves.train</code> <code>│ ├───</code><code>waves.test</code> <code>│ ├───</code><code>test_yesno_wav.scp</code> <code>│ ├───</code><code>train_yesno_wav.scp</code></span>

│ ├───test_yesno.txt

│ ├───test_yesno.txt

<span style="color:#00000a"><code>│ ├───</code><code>lm_tg.arpa</code> <code>│ └───</code><code>waves_all.list </code> <code>├───</code><code>train_yesno</code> <code>│ ├───</code><code>text</code> <code>│ ├───</code><code>utt2spk</code> <code>│ ├───</code><code>spk2utt</code> <code>│ └───</code><code>wav.scp</code> <code>├───</code><code>test_yesno</code> <code>│ ├───</code><code>text</code> <code>│ ├───</code><code>utt2spk</code> <code>│ ├───</code><code>spk2utt</code> <code>│ └───</code><code>wav.scp </code> </span>

?

. 字典預(yù)處理階段

執(zhí)行local/prepare_dict.sh

?

1. 創(chuàng)建詞典目錄data/local/dict 和 復(fù)制文件:input/lexicon_nosil.txt 到data/local/dict/lexicon_words.txt ; input/lexicon.txt 到data/local/dict/lexicon.txt

lexicon_words.txt內(nèi)容:

YES Y

NO N

?

lexicon.txt 內(nèi)容:

<SIL> SIL

YES Y

NO N

?

2. cat input/phones.txt | grep -v SIL > data/local/dict/nonsilence_phones.txt 使用反轉(zhuǎn)查找(排除)文件中SIL 并且存到另一個文件 nonsilence_phones.txt 內(nèi)容:

Y

N

?

3. data/local/dict/silence_phones.txt 和 data/local/dict/optional_silence.txt 內(nèi)容:

SIL

?

此時目錄結(jié)構(gòu)如下:

<span style="color:#00000a"><code>data</code></span>

├───local

<span style="color:#00000a"><code>│ └───</code><code>dict</code> <code>│ ├───</code><code>lexicon_words.txt</code> <code>│ ├───</code><code>lexicon.txt</code> <code>│ ├───</code><code>nonsilence_phones.txt</code></span>

│ ├───silence_phones.txt

<span style="color:#00000a"><code>│ └───</code><code>optional_silence.txt</code></span>

?

. 執(zhí)行命令

utils/prepare_lang.sh --position-dependent-phones false data/local/dict "<SIL>" data/local/lang data/lang

?

1. 調(diào)用這個腳本處理傳入的參數(shù)

. utils/parse_options.sh

?

1.1 把傳入的—position-dependent-phones處理 成 position_dependent_phones 然后通過之后的代碼把第二個參數(shù)false賦值給他

name=`echo "$1" | sed s/^--// | sed s/-/_/g`

?

1.2 最后左移兩個參數(shù),參數(shù)列表變?yōu)?#xff1a;

utils/prepare_lang.sh data/local/dict "<SIL>" data/local/lang data/lang

?

2. 四個變量,方便閱讀代碼

srcdir=$1 #data/local/dict

oov_word=$2 #<SIL>

tmpdir=$3 #data/local/lang

dir=$4 #data/lang

?

3. 執(zhí)行不啟動新的shell執(zhí)行腳本 設(shè)置環(huán)境變量

. ./path.sh

執(zhí)行 腳本 設(shè)置環(huán)境變量 KALDI_ROOT和 PATH

kaldi/tools/env.sh

?

4. 執(zhí)行命令檢測詞典文件內(nèi)容是否正確

utils/validate_dict_dir.pl $srcdir

?

檢測silence_phones.txt optional_silence.txt nonsilence_phones.txt 等文件格式是否正確 (主要是匹配應(yīng)該沒有\(zhòng)r \n,是否為文件是空的,或是phones的結(jié)尾不應(yīng)該是 _B, _E, _S 或 _I 這些容易混淆的符號,內(nèi)容是否重復(fù))

(檢查silence_phones.txt, nonsilence_phones.txt內(nèi)容互斥)

(通過 check_lexicon_pair函數(shù) 檢查詞典是否成對lexicon.txt lexiconp.txt )

檢測data/loacal/dict/extra_questions.txt 不存在 輸出"--> data/loacal/dict/extra_questions.txt is empty (this is OK)\n"

?

5. 檢查文件$srcdir/lexicon.txt是否為普通文件,不是普通文件則執(zhí)行該指令

perl -ape 's/ (\S+\s+)\S+\s+(.+)/$1$2/;' < $srcdir/lexiconp.txt > $srcdir/lexicon.txt || exit 1;

這個perl -ape 命令 應(yīng)該是-a -p -e ,后面是字符匹配替換,$1代碼第一個括號$2代 表第二個括號內(nèi)容,\S+ 多個非空格 \s+ 多個空格 .+ 匹配一次或多次任何字符。

(注:本代碼為普通不執(zhí)行后面代碼)。

?

6.命令 復(fù)制文件 內(nèi)容:

cp $srcdir/lexiconp.txt $tmpdir/

lexiconp.txt內(nèi)容:

<SIL> 1.0 SIL

YES 1.0 Y

NO 1.0 N

?

命令讀取兩個文件合并到phones文件,

cat $srcdir/silence_phones.txt $srcdir/nonsilence_phones.txt | \

awk '{for(n=1;n<=NF;n++) print $n; }' > $tmpdir/phones

data/local/lang/phones文件內(nèi)容:

SIL

Y

N

?

命令 作用是把兩個文件列合并到新文件

paste -d' ' $tmpdir/phones $tmpdir/phones > $tmpdir/phone_map.txt

phone_map.txt內(nèi)容:

SIL SIL

Y Y

N N

創(chuàng)建目錄 data/lang/phones 一系列音素的集合

mkdir -p $dir/phones

方文檔:phones目錄下包含許多不同的音素集的信息,每個文件都有三種形式,擴(kuò)展名為.csl, .int 和 .txt是相同信息的三種不同格式。這些文件可以用這個腳本"utils/prepare_lang.sh"創(chuàng)建。

命令主要 apply_map.pl腳本作用讀入 phone_map.txt文件每行兩個數(shù)據(jù)段用hash映射鍵值對存儲,然后讀入$srcdir/{,non}silence_phones.txt數(shù)據(jù),用此數(shù)據(jù)作為鍵取之前hash的值并輸出到sets.txt文件,在之后生成的.int文件是音素集合

cat $srcdir/{,non}silence_phones.txt | utils/apply_map.pl $tmpdir/phone_map.txt > $dir/phones/sets.txt

?

不同的silence 音素?fù)碛胁煌?GMMs. [注意: 這里所有的"shared split" 意思是對于所有狀態(tài)我們可能擁有一個GMM,或者我們能夠分割狀態(tài)。因為他們是上下文-依賴音素(context-independent phones),他們看不到上下文context](來源:prepare_lang.sh注釋)

sets.txt 內(nèi)容:

SIL

Y

N

?

命令生成的這個roots文件讓所有silence音素共享同一個概率密度函數(shù)。

cat $dir/phones/sets.txt | awk '{print "shared", "split", $0;}' > $dir/phones/roots.txt

?

roots.txt內(nèi)容:

shared split SIL

shared split Y

shared split Nlex_ndisambig

?

?

7. 下面命令其中|代表管道,執(zhí)行 utils/apply_map.pl 傳到腳本的第一個值 $tmpdir 第二個值是$srcdir/silence_phones.txt 的內(nèi)容,然后把腳本運行的結(jié)果傳給后并輸出到文件中屬于標(biāo)準(zhǔn)輸入<STDIN>讀取;整個指令目的是 匹配兩個文件相同的字符輸出到新文件

cat $srcdir/silence_phones.txt | utils/apply_map.pl $tmpdir/phone_map.txt | \

awk '{for(n=1;n<=NF;n++) print $n;}' > $dir/phones/silence.txt

?

silence.txt 內(nèi)容:

SIL

?

8.命令生成nonsilence.txt文件

cat $srcdir/nonsilence_phones.txt | utils/apply_map.pl $tmpdir/phone_map.txt | \

awk '{for(n=1;n<=NF;n++) print $n;}' > $dir/phones/nonsilence.txt

?

nonsilence.txt 內(nèi)容:

Y

N

?

之后用下面兩個命令把文件復(fù)制到指定目錄

?

cp $srcdir/optional_silence.txt $dir/phones/optional_silence.txt

cp $dir/phones/silence.txt $dir/phones/context_indep.txt

?

optional_silence.txt內(nèi)容:

SIL

?

context_indep.txt內(nèi)容:

SIL

?

9. 下面命令生成data/lang/phones.txt文件

echo "<eps>" | cat - $dir/phones/{silence,nonsilence,disambig}.txt | \

awk '{n=NR-1; print $1, n;}' > $dir/phones.txt

?

下面代碼處理 lexiconp.txt文件每行第一個字段 并且排序去除重復(fù) 增加幾個字段 并且編號 輸出words.txt ,如果失敗則退出。

cat $tmpdir/lexiconp.txt | awk '{print $1}' | sort | uniq | awk '

BEGIN {

print "<eps> 0";

}

{

if ($1 == "<s>") {

print "<s> is in the vocabulary!" | "cat 1>&2"

exit 1;

}

if ($1 == "</s>") {

print "</s> is in the vocabulary!" | "cat 1>&2"

exit 1;cat $tmpdir/lexiconp.txt | awk '{print $1}' | sort | uniq | awk '

BEGIN {

print "<eps> 0";

}

{

if ($1 == "<s>") {

print "<s> is in the vocabulary!" | "cat 1>&2"

exit 1;

}

if ($1 == "</s>") {

print "<

}

printf("%s %d\n", $1, NR);

}

END {

printf("#0 %d\n", NR+1);

printf("<s> %d\n", NR+2);

printf("</s> %d\n", NR+3);

}' > $dir/words.txt || exit 1;

?

lexiconp.txt 內(nèi)容:

<SIL> 1.0 SIL

YES 1.0 Y

NO 1.0 N

?

words.txt 內(nèi)容:

<eps> 0

<SIL> 1

NO 2

YES 3

#0 4

<s> 5

</s> 6

?

10. 如果沒有使用詞-位置-依賴音素(word-position-dependent phones)的方法我們使用格詞對齊(lattice word alignment)的方法,并且創(chuàng)建$dir/phones/align_lexicon.{txt,int} 文件。

silphone=`cat $srcdir/optional_silence.txt` || exit 1; #silphone=SIL

?

# 首先從詞典移除概率通過正則匹配方法

perl -ape 's/(\S+\s+)\S+\s+(.+)/$1$2/;' <$tmpdir/lexiconp.txt >$tmpdir/align_lexicon.txt

?

# 然后增加一行"<eps> $silphone"

[ ! -z "$silphone" ] && echo "<eps> $silphone" >> $tmpdir/align_lexicon.txt

?

#讀文件內(nèi)容,把原文件的每行第一個字段字符多輸出一遍

cat $tmpdir/align_lexicon.txt | \

perl -ane '@A = split; print $A[0], " ", join(" ", @A), "\n";' | sort | uniq > $dir/phones/align_lexicon.txt

?

11. # 通過腳本命令創(chuàng)建 phones/align_lexicon.int 矩陣

cat $dir/phones/align_lexicon.txt | utils/sym2int.pl -f 3- $dir/phones.txt | \

utils/sym2int.pl -f 1-2 $dir/words.txt > $dir/phones/align_lexicon.int

?

其中腳本中的 $sym2int{$A[0]} = $A[1] + 0; #把從phones.txt讀出來的每行兩個分別 以鍵值存到hash中phones/align_lexicon.int

cat $dir/phones/align_lexicon.txt | utils/sym2int.pl -f 3- $dir/phones.txt

?

到這里代碼輸出結(jié)果為:

<SIL> <SIL> 1

<eps> <eps> 1

NO NO 3

YES YES 2

?

(過程是通過map把存儲鍵值,然后從另一個文件align_lexicon.txt 取第三列數(shù)據(jù)找到value值 替換結(jié)果)

經(jīng)過后半段代碼輸出為:

1 1 1

0 0 1

2 2 3

3 3 2

?

(過程同上)

?

這段代碼命令是為了生成data/lang/L.fst :

utils/make_lexicon_fst.pl --pron-probs $tmpdir/lexiconp.txt $sil_prob $silphone | \

fstcompile --isymbols=$dir/phones.txt --osymbols=$dir/words.txt \

--keep_isymbols=false --keep_osymbols=false | \

fstarcsort --sort_type=olabel > $dir/L.fst || exit 1;

?

其中命令對概率是通過對數(shù)處理,比如ln(0.5)= 0.693147180559945

utils/make_lexicon_fst.pl --pron-probs data/local/lang/lexiconp.txt 0.5 `cat data/local/dict/optional_silence.txt`

?

執(zhí)行這句話shell輸出下面的結(jié)果:

0 1 <eps> <eps> 0.693147180559945

0 1 SIL <eps> 0.693147180559945

2 1 SIL <eps>

1 1 SIL <SIL>

1 1 Y YES 0.693147180559945

1 2 Y YES 0.693147180559945

1 1 N NO 0.693147180559945

1 2 N NO 0.693147180559945

1 0

?

<eps> 0 SIL 1

?

整個命令創(chuàng)建L.fst文件用于訓(xùn)練是silence 概率,內(nèi)容:

root@wenlong:/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5# fstprint data/lang/L.fst

0 1 0 0 0.693147182

0 1 1 0 0.693147182

1 1 1 1

1 1 3 2 0.693147182

1 2 3 2 0.693147182

1 1 2 3 0.693147182

1 2 2 3 0.693147182

1

2 1 1 0

?

對于fst,其打印結(jié)果,一行一般有5列。一行對應(yīng)一個弧。第一列和第二列,表示這個弧的起始狀態(tài)和終止?fàn)顟B(tài)。第三列和第四列,表示輸入和輸出。第五列是權(quán)重。

使用下面命令生成一個PDF文件,如下圖所示

fstdraw data/lang_test_tg/L.fst | dot -Tps | ps2pdf – L.pdf

?


?

FSTFinite State Transducer)說明:

(L, see "Speech Recognition with Weighted Finite-State Transducers" by Mohri, Pereira and Riley, in Springer Handbook on SpeechProcessing and Speech Communication, 2008)

(之前以為是FSM有限狀態(tài)機(jī),FST 與FSM最主要的區(qū)別在于FST在完成狀態(tài)轉(zhuǎn)移的同時產(chǎn)生一個輸出)語音這里是以音素輸入,詞輸出結(jié)果。

個人理解拿L.fst為例,詞: NO 2,YES 3,<eps> 0,<SIL> 1 音素:<eps> 0 , SIL 1,N 3,Y 2

初始狀態(tài)0狀態(tài)到1狀態(tài): 輸入 音素<eps>和 SIL 權(quán)重都是0.69315 輸出都是 SIL 靜音

從1狀態(tài)到2狀態(tài):3:2/0.69315 輸入音素 N輸出詞No 權(quán)重0.69315

2:3/0.69315 輸入音素 Y輸出詞Yes 權(quán)重0.69315

從狀態(tài)2運行后必然回到狀態(tài)1:1:0 輸入 音素<eps> 輸出是 SIL

從狀態(tài)1到狀態(tài)1:3:2/0.69315 輸入音素 N輸出詞No 權(quán)重0.69315

2:3/0.69315 輸入音素 Y輸出詞Yes 權(quán)重0.69315

1:1 輸入 音素SIL 輸出是 SIL

狀態(tài)1是終止?fàn)顟B(tài) ,結(jié)束時候可以得到該輸出語句的權(quán)重總和。

(還沒看到權(quán)重是直接加還是像概率那樣累乘,以后完善,那種決策樹算法和它有沒有關(guān)系呢?)

2017年10月11日更新:權(quán)重的這個運算在下文WFST中有所說明

2.3. Composition 應(yīng)該是進(jìn)行模型組合運算


?

下面這段是從別處看來的fst說明,下面這段話好像是自己打上的放百度里也沒有找到出處

初始狀態(tài)是0.這僅僅有一個初始狀態(tài),最終狀態(tài)是2權(quán)重是3.5。任何非初始最終權(quán)重的 狀態(tài)都是一個最終的狀態(tài)。從狀態(tài)0到1輸入標(biāo)簽a輸出標(biāo)簽x權(quán)重0.5的arc (或轉(zhuǎn)移)。這個FST 有限狀態(tài)轉(zhuǎn)換器中ac到xz的權(quán)重是6.5(arc的總和加上最終權(quán)重)。

?

12. 在訓(xùn)練期間這個文件 oov.txt 包含了我們將要映射詞匯表之外的發(fā)音詞,并通過上面的方法生成oov.int 矩陣文件。

oov.txt 內(nèi)容只有一行 : <SIL>

?

echo "$oov_word" > $dir/oov.txt || exit 1;

cat $dir/oov.txt | utils/sym2int.pl $dir/words.txt >$dir/oov.int || exit 1;

?

生成 wdisambig.txt文件 內(nèi)容:#0

echo '#0' >$dir/phones/wdisambig.txt

?

13. 同樣生成矩陣文件

utils/sym2int.pl $dir/phones.txt <$dir/phones/wdisambig.txt>$dir/phones/wdisambig_phones.int

utils/sym2int.pl $dir/words.txt <$dir/phones/wdisambig.txt >$dir/phones/wdisambig_words.int

?

?

14. 使用同樣的方法創(chuàng)建這個矩陣文件

for f in silence nonsilence optional_silence disambig context_indep; do

utils/sym2int.pl $dir/phones.txt <$dir/phones/$f.txt >$dir/phones/$f.int

utils/sym2int.pl $dir/phones.txt <$dir/phones/$f.txt | \

awk '{printf(":%d", $1);} END{printf "\n"}' | sed s/:// > $dir/phones/$f.csl || exit 1;

done

?

for x in sets extra_questions; do

utils/sym2int.pl $dir/phones.txt <$dir/phones/$x.txt > $dir/phones/$x.int || exit 1;

done

?

utils/sym2int.pl -f 3- $dir/phones.txt <$dir/phones/roots.txt \

> $dir/phones/roots.int || exit 1;

?

if [ -f $dir/phones/word_boundary.txt ]; then

utils/sym2int.pl -f 1 $dir/phones.txt <$dir/phones/word_boundary.txt \

> $dir/phones/word_boundary.int || exit 1;

fifor f in silence nonsilence optional_silence disambig context_indep; do

utils/sym2int.pl $dir/phones.txt <$dir/phones/$f.txt >$dir/phones/$f.int

utils/sym2int.pl $dir/phones.txt <$dir/phones/$f.txt | \

awk '{printf(":%d", $1);} END{printf "\n"}' | sed s/:// > $dir/phones/$f.csl || exit 1;

done

?

for x in sets extra_questions; do

utils/sym2int.pl $dir/phones.txt <$dir/phones/$x.txt > $dir/phones/$x.int || exit 1;

done

?

utils/sym2int.pl -f 3- $dir/phones.txt <$dir/phones/roots.txt \

> $dir/phones/roots.int || exit 1;

?

if [ -f $dir/phones/word_boundary.txt ]; then

utils/sym2int.pl -f 1 $dir/phones.txt <$dir/phones/word_boundary.txt \

> $dir/phones

?

15.

silphonelist=`cat $dir/phones/silence.csl` #結(jié)果 : silphonelist=1

nonsilphonelist=`cat $dir/phones/nonsilence.csl` #結(jié)果: nonsilphonelist= 2:3

?

16. 生成一個拓?fù)湮募?#xff0c;允許控制這個 non-silence HMMs和 silence HMMs 的狀態(tài)數(shù)

utils/gen_topo.pl $num_nonsil_states $num_sil_states $nonsilphonelist $silphonelist >data/lang/topo

?

topo內(nèi)容1表示silcense,2是Y ,3是N:

<Topology>

<TopologyEntry>

<ForPhones>

2 3

</ForPhones>

<State> 0 <PdfClass> 0 <Transition> 0 0.75 <Transition> 1 0.25 </State>

<State> 1 <PdfClass> 1 <Transition> 1 0.75 <Transition> 2 0.25 </State>

<State> 2 <PdfClass> 2 <Transition> 2 0.75 <Transition> 3 0.25 </State>

<State> 3 </State>

</TopologyEntry>

<TopologyEntry>

<ForPhones>

1

</ForPhones>

<State> 0 <PdfClass> 0 <Transition> 0 0.25 <Transition> 1 0.25 <Transition> 2 0.25 <Transition> 3 0.25 </State>

<State> 1 <PdfClass> 1 <Transition> 1 0.25 <Transition> 2 0.25 <Transition> 3 0.25 <Transition> 4 0.25 </State>

<State> 2 <PdfClass> 2 <Transition> 1 0.25 <Transition> 2 0.25 <Transition> 3 0.25 <Transition> 4 0.25 </State>

<State> 3 <PdfClass> 3 <Transition> 1 0.25 <Transition> 2 0.25 <Transition> 3 0.25 <Transition> 4 0.25 </State>

<State> 4 <PdfClass> 4 <Transition> 4 0.75 <Transition> 5 0.25 </State>

<State> 5 </State>

</TopologyEntry>

</Topology>

?

17. 生成 L_disambig.fst文件

utils/make_lexicon_fst.pl --pron-probs $tmpdir/lexiconp_disambig.txt $sil_prob $silphone '#'$ndisambig | \

fstcompile --isymbols=$dir/phones.txt --osymbols=$dir/words.txt \

--keep_isymbols=false --keep_osymbols=false | \

fstaddselfloops $dir/phones/wdisambig_phones.int $dir/phones/wdisambig_words.int | \

fstarcsort --sort_type=olabel > $dir/L_disambig.fst || exit 1;

L_disambig.fst也是一個發(fā)音詞典,除了L.fst的內(nèi)容,還包括#1, #2這種消除岐義的符號,#0是一個自環(huán),具體可以看Disambiguation symbols說明:

http://kaldi-asr.org/doc/graph.html#graph_disambig

使用fstprint命令得到內(nèi)容:

root@wenlong:/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5# fstprint data/lang_test_tg/L_disambig.fst

0 1 0 0 0.693147182

0 2 1 0 0.693147182

1 1 1 1

1 1 3 2 0.693147182

1 3 3 2 0.693147182

1 1 2 3 0.693147182

1 3 2 3 0.693147182

1 1 4 4

1

2 1 5 0

3 2 1 0

?

?

使用命令得到FST狀態(tài)圖:

fstdraw data/lang_test_tg/L_disambig.fst | dot -Tps | ps2pdf - L_disambig.pdf

?

?

18. 通過該語句驗證目錄以及文件

! utils/validate_lang.pl $dir && echo "$(basename $0): error validating output" && exit 1;

?

處理之后目錄結(jié)構(gòu)圖:

<span style="color:#00000a"><code>data</code></span>

├───lang

<span style="color:#00000a"><code>│ └───</code><code>phones</code> <code>│ ├───</code><code>align_lexicon.txt</code> <code>│ ├───</code><code>align_lexicon.int</code> <code>│ ├───</code><code>context_indep.txt</code> <code>│ ├───</code><code>context_indep.int</code> <code>│ ├───</code><code>disambig.txt</code> <code>│ ├───</code><code>disambig.int</code> <code>│ ├───</code><code>extra_questions.txt</code> <code>│ ├───</code><code>extra_questions.int</code> <code>│ ├───</code><code>nonsilence.txt</code> <code>│ ├───</code><code>nonsilence.int</code> <code>│ ├───</code><code>optional_silence.txt</code> <code>│ ├───</code><code>optional_silence.int</code> <code>│ ├───</code><code>roots.txt</code> <code>│ ├───</code><code>roots.int</code> <code>│ ├───</code><code>sets.txt</code> <code>│ ├───</code><code>sets.int</code> <code>│ ├───</code><code>silence.txt</code> <code>│ ├───</code><code>silence.int</code> <code>│ ├───</code><code>wdisambig.txt</code> <code>│ ├───</code><code>wdisambig_phones.int</code> <code>│ ├───</code><code>wdisambig_words.int</code> </span>

?

?

. 執(zhí)行命令 local/prepare_lm.sh 準(zhǔn)備語言模型用于測試

LMlanguage model)在data/lang_test_tg 目錄

1. 命令arpa2fst是一個KaldiC++ 程序。該程序?qū)?/span>ARPA格式的語言模型轉(zhuǎn)換為一個加權(quán)有限狀態(tài)轉(zhuǎn)換器(實際上是一個接收器)

arpa2fst --disambig-symbol=#0 --read-symbol-table=$test/words.txt input/task.arpabo $test/G.fst

?

--disambig-symbol=#0 用于輸入側(cè)的回退鏈接,去除 <s> </s>

--read-symbol-table=$test/words.txt 使用已存在的符號列表,默認(rèn)是“”。

words.txt內(nèi)容:

<eps> 0

<SIL> 1

NO 2

YES 3

#0 4

<s> 5

</s> 6

?

ARPA是常用的語言模型存儲格式, 由主要由兩部分構(gòu)成。模型文件頭和模型文件體構(gòu)成。

(詞組前面的數(shù)字:概率,詞組后面的數(shù)據(jù),回退權(quán)值)

yesno的模型input/task.arpabo

\data\

ngram 1=4


?

\1-grams:

-1 NO

-1 YES

-99 <s>

-1 </s>

\end\


?

通過arpa2fst轉(zhuǎn)換的G.fst 通過fstprint函數(shù)可以看到結(jié)果:

root@wenlong:/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5# fstprint data/lang_test_tg/G.fst

0 0 2 2 2.30258512

0 0 3 3 2.30258512

0 2.30258512


?

對于fst,其打印結(jié)果,一行一般有5列。一行對應(yīng)一個弧。第一列和第二列,表示這個弧的起始狀態(tài)和終止?fàn)顟B(tài)。第三列和第四列,表示輸入和輸出。第五列是權(quán)重。

fstdraw data/lang_test_tg/G.fst | dot -Tps | ps2pdf – G.pdf

該命令生成一個PDF文件,如下圖所示

使用C++工具驗證生成的G.fst文件

fstisstochastic data/lang_test_tg/G.fst

輸出結(jié)果:1.20397 1.20397

?

# Create the lexicon FST with disambiguation symbols, and put it in lang_test.

# There is an extra step where we create a loop to "pass through" the

# disambiguation symbols from G.fst.

?

# 特征提取階段

$x分別對與train_yesnotest_yesno執(zhí)行以下三條指令

train_yesno 為例

. 命令

steps/make_mfcc.sh --nj 1 data/$x exp/make_mfcc/$x mfcc

其中—nj 1 表示并行任務(wù)的數(shù)量,data/$x 訓(xùn)練所在目錄,exp/make_mfcc/$x記錄make_mfcc的執(zhí)行logmfcc 特征輸出目錄

主要為了創(chuàng)建feats.scp文件

?

1. 創(chuàng)建目錄/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc exp/make_mfcc/train_yesno

2. 如果data/train_yesno/feats.scp是普通文件,創(chuàng)建目錄data/train_yesno/.backup并把此scp 文件移動到/.backup目錄下

3. 判斷兩個文件是否是普通文件data/train_yesno/wav.scp conf/mfcc.conf,沒有則退出

4. 該腳本檢測data目錄中數(shù)據(jù)是否正常

utils/validate_data_dir.sh --no-text --no-feats data/train_yesno

?

5. 該腳本除非mfcc/storage/ 存在否則沒用

utils/create_data_link.pl $mfccdir/raw_mfcc_$name.$n.ark

?

6.由于沒有data/train_yesno/segments目錄執(zhí)行else之后的語句,顯示提示steps/make_mfcc.sh: [info]: no segments file exists: assuming wav.scp indexed by utterance.

?

執(zhí)行命令但是由于第二個參數(shù)文件不存在,好像也沒什么用

utils/split_scp.pl $scp $split_scps || exit 1;

#$scp= data/train_yesno/wav.scp $split_scps=exp/make_mfcc/train_yesno/wav_train_yesno.1.scp

?

?

7.

run.pl JOB=1:$nj $logdir/make_mfcc_${name}.JOB.log \

compute-mfcc-feats $vtln_opts --verbose=2 --config=$mfcc_config \

scp,p:$logdir/wav_${name}.JOB.scp ark:- \| \

copy-feats $write_num_frames_opt --compress=$compress ark:- \

ark,scp:$mfccdir/raw_mfcc_$name.JOB.ark,$mfccdir/raw_mfcc_$name.JOB.scp \

|| exit 1;

?

參數(shù)列表:

  • JOB=1:1

  • exp/make_mfcc/train_yesno/make_mfcc_train_yesno.JOB.log

  • compute-mfcc-feats

  • --verbose=2

  • --config=conf/mfcc.conf

  • scp,p:exp/make_mfcc/train_yesno/wav_train_yesno.JOB.scp

  • ark:-

  • |

  • copy-feats

  • --compress=true

  • ark:-

  • ark,scp:/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc/raw_mfcc_train_yesno.JOB.ark,/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc/raw_mfcc_train_yesno.JOB.scp

  • ?

    $jobname = $1; #JOB

    $jobstart = $2; #1

    $jobend = $3; #1

    ?

    其中該語句根據(jù)cpu核心數(shù)量設(shè)置并行任務(wù)數(shù);

    elsif (open(P, "</proc/cpuinfo")) { # Linux

    while (<P>) { if (m/^processor/) { $max_jobs_run++; } }

    ?

    核心就是執(zhí)行該代碼把shell日志存到exp/make_mfcc/$x目錄下的.log文件 并生成 raw_mfcc_train_yesno.1.ark raw_mfcc_train_yesno.1.scp raw_mfcc_train_yesno.1.scp 存放的是發(fā)音id 和 對應(yīng)的總特征文件.ark中語音對應(yīng)的字節(jié)偏移,官方文檔說fseek() to position24, and read the data that's there.

    使用fseek()定位到24字節(jié)位置讀取內(nèi)容。

    ?

    ?

    下面這段代碼利用Kaldicompute-mfcc-feats工具計算梅爾倒譜頻率特征,然后利用copy-feats工具的參數(shù)—compress=true 壓縮處理存儲為兩個文件類型arkscp

    compute-mfcc-feats --verbose=2 --config=conf/mfcc.conf scp,p:exp/make_mfcc/train_yesno/wav_train_yesno.1.scp ark:- | copy-feats --compress=true ark:- ark,scp:/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc/raw_mfcc_train_yesno.1.ark,/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc/raw_mfcc_train_yesno.1.scp

    ?

    查看前幾行數(shù)據(jù)內(nèi)容:

    root@wenlong:/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5# copy-feats ark:mfcc/raw_mfcc_train_yesno.1.ark ark,t:- | head

    copy-feats ark:mfcc/raw_mfcc_train_yesno.1.ark ark,t:-

    0_0_0_0_1_1_1_1 [

    48.97441 -14.08838 -0.1344408 4.717922 21.6918 -0.2593708 -8.379625 8.9065 4.354931 17.00239 0.8865671 9.878274 2.105978

    53.68612 -10.14593 -1.394655 -2.119211 13.08846 6.172102 8.67521 19.2422 0.4617066 5.210238 3.242958 2.333473 -0.5913677

    55.30577 -10.3102 2.783288 6.130808 18.00465 0.1580257 -5.36183 5.867401 6.992276 3.769728 0.3255215 4.97998 6.144587

    56.4837 -16.38814 -2.418081 8.250138 5.304474 5.584198 -14.83413 2.809654 10.13197 19.37797 -4.723887 2.218409 4.529143

    59.04967 -6.238421 -3.889256 -4.782247 1.989491 8.229766 -3.262494 -3.118021 -2.301227 12.84513 -23.23007 4.634783 -2.480992

    61.0052 -5.754351 -2.929794 -1.887643 9.401306 6.466054 3.297932 5.754842 6.992276 13.73597 -2.704123 -3.764996 -11.14875

    61.16816 -6.399778 -4.081148 -1.308722 0.9340172 1.201521 1.067387 3.180134 5.485222 14.03292 -2.367496 -0.4280972 4.259902

    61.98296 -7.206563 -1.714476 2.512154 2.200584 6.760006 -7.461166 -3.488502 2.219936 8.297047 -3.826214 9.39221 -4.559578

    60.51632 -6.722493 -2.482045 -1.656075 4.485107 2.662413 -7.067541 10.36977 5.485222 6.650749 -2.591914 6.718862 -3.89821

    ?

    8. 這段代碼把raw_mfcc_test_yesno.1.scp raw_mfcc_train_yesno.1.scp內(nèi)容拷貝到 train_yesno/feats.scp test_yesno/feats.scp

    for n in $(seq $nj); do

    cat $mfccdir/raw_mfcc_$name.$n.scp || exit 1;

    done > $data/feats.scp || exit 1

    ?

    feats.scp 內(nèi)容格式:

    0_0_0_0_1_1_1_1 /home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc/raw_mfcc_train_yesno.1.ark:16

    0_0_0_1_0_0_0_1 /home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc/raw_mfcc_train_yesno.1.ark:8386

    0_0_0_1_0_1_1_0 /home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc/raw_mfcc_train_yesno.1.ark:17289

    0_0_1_0_0_0_1_0 /home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc/raw_mfcc_train_yesno.1.ark:25347

    0_0_1_0_0_1_1_0 /home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc/raw_mfcc_train_yesno.1.ark:33353

    ……

    ?

    ?

    二.

    steps/compute_cmvn_stats.sh data/$x exp/make_mfcc/$x mfcc

    ?

    創(chuàng)建文件cmvn.scp包含計算每個說話人的(cmvn)倒譜頻率均值和方差歸一化的統(tǒng)計量,以說話人編號為索引。內(nèi)容如下:

    global /home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc/cmvn_train_yesno.ark:7

    ?

    只有一條是因為是只有一個人發(fā)音所以用global就可以了

    與 feats.scp 不同,這個 scp 文件是以說話人編號為索引,而不是發(fā)音編號。

    三. 在data/train_yesno 和data/test_yesno 創(chuàng)建兩個目錄 .back 然后把需要的文件復(fù)制過來

    包括cmvn.scp feats.scp spk2utt text utt2spk wav.scp

    utils/fix_data_dir.sh data/$x

    ?

    文檔中指出“(當(dāng)然可對任何數(shù)據(jù)目錄使用該命令,而不只是 data/train)。該腳本會修復(fù)排序錯誤,并會移除那些缺失發(fā)聲人(utterances)的數(shù)據(jù)包括特征數(shù)據(jù)或標(biāo)注。”


    ?

    <span style="color:#00000a"><code>mfcc</code><code>目錄</code></span>

    ├───cmvn_test_yesno.ark

    <span style="color:#00000a"><code>├───</code><code>cmvn_train_yesno.ark</code> <code>├───</code><code>cmvn_train_yesno.ark </code> <code>├───</code><code>raw_mfcc_test_yesno.1.ark </code> <code>├───</code><code>raw_mfcc_train_yesno.1.ark</code> <code>├───</code><code>cmvn_test_yesno.scp </code> <code>├───</code><code>cmvn_train_yesno.scp </code> <code>├───</code><code>raw_mfcc_test_yesno.1.scp </code> <code>├───</code><code>raw_mfcc_train_yesno.1.scp</code> </span>

    # Mono 訓(xùn)練

    發(fā)現(xiàn)一個文檔在訓(xùn)練階段講解比較詳細(xì)

    http://blog.csdn.net/duishengchen/article/details/52575926

    ?

    執(zhí)行代碼該語句進(jìn)行單音素訓(xùn)練

    steps/train_mono.sh --nj 1 --cmd "$train_cmd" \

    --totgauss 400 \

    data/train_yesno data/lang exp/mono0a

    ?

    $data 對應(yīng)參數(shù) data/train_yesno ;

    $lang 對應(yīng)參數(shù) data/lang;

    $dir 對應(yīng)參數(shù) exp/mono0a;

    ?

    nj根據(jù)參數(shù)--nj 1 確定)

    sdata=$data/split$nj

    ?

    其中 exp/mono0a/log 存放日志文件

    1. 命令

    example_feats=”ark,s,cs:apply-cmvn --utt2spk=ark:data/train_yesno/split1/1/utt2spk scp:data/train_yesno/split1/1/cmvn.scp scp:data/train_yesno/split1/1/feats.scp ark:- | add-deltas ark:- ark:- |”

    feat_dim=`feat-to-dim "$example_feats" – 2>/dev/null`

    ?

    #C++代碼執(zhí)行可以得到mfcc的特征維度,feat_dim這里mfcc39

    <span style="color:#00000a"><code><span style="color:#000000">前綴</span></code><code><span style="color:#000000">"scp:" </span></code><code><span style="color:#000000">或 </span></code><code><span style="color:#000000">"ark:"</span></code><code><span style="color:#000000">代表文件后綴名的格式,目的告訴</span></code><code><span style="color:#000000">C++</span></code><code><span style="color:#000000">代碼執(zhí)行時傳入的數(shù)據(jù)文件類型,其中</span></code><code><span style="color:#000000">ark</span></code><code><span style="color:#000000">是二進(jìn)制文件。</span></code> <code><span style="color:#000000">從一個博客了解下面人容:</span></code> <code><span style="color:#000000">博客地址:</span></code><code><span style="color:#000000">http://blog.csdn.net/llearner/article/details/77543337</span></code></span>

    .scp.ark文件都可以看成是數(shù)據(jù)表。這種格式有如下特點:

    <span style="color:#00000a"><code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>.scp</code><code>格式是純文本格式,一行有</code><code>key</code><code>的</code><code>id</code><code>和“可擴(kuò)展文件名”讓</code><code>Kaldi</code><code>去找數(shù)據(jù)</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>.ark</code><code>格式可能是文本</code><code>/</code><code>二進(jìn)制,”</code><code>t”</code><code>參數(shù)表示文本,默認(rèn)是二進(jìn)制。格式:</code><code>key</code><code>的</code><code>id</code><code>,空格,目標(biāo)數(shù)據(jù)。</code></span><span style="color:#0000ff">12</span></span>

    .scp和.ark文件幾個通用的點:

    <span style="color:#00000a"><code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>指定讀表的字符串叫</code><code>rspecifier;</code><code>比如 </code><code>"ark:gunzip -c my/dir/foo.ark.gz|".</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>指定寫表的字符串叫 </code><code>wspecifier;</code><code>比如 </code><code>"ark,t:foo.ark".</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>.ark</code><code>文件可以共同連接起來,仍然是有效的</code><code>ark</code><code>文件(沒有中心索引)</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>代碼可以順序或隨機(jī)訪問</code><code>.scp</code><code>和</code><code>.ark</code><code>文件。用戶級代碼只需要知道它是迭代還是查找,不需要知道訪問的是哪種類型文件。</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>Kaldi</code><code>不會在</code><code>.ark</code><code>文件中表示對象類型;需要提前知道對象類型。</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>.ark</code><code>和</code><code>.scp</code><code>文件不包含混合類型</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>通過隨機(jī)訪問來讀取</code><code>.ark</code><code>文件可能是無效的,因為代碼可能必須將對象緩存在內(nèi)存中。</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>為了有效地隨機(jī)訪問</code><code>.ark</code><code>文件,您可以使用“</code><code>ark</code><code>,</code><code>scp”</code><code>寫入機(jī)制(例如用于將</code><code>mfcc</code><code>功能寫入磁盤)來寫出相應(yīng)的腳本文件。 然后,通過</code><code>scp</code><code>文件訪問它。</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>在檔案上進(jìn)行隨機(jī)訪問時,避免代碼必須緩存一堆內(nèi)容的另一種方法是告知代碼歸檔歸檔并按排序順序調(diào)用(例如“</code><code>ark</code><code>,</code><code>s</code><code>,</code><code>cs</code><code>: </code><code>- ”</code><code>))</code></span></span>


    ?

    <span style="color:#00000a"><code><span style="color:#0000ff">更多信息看 </span></code><code><span style="color:#0000ff"><a data-cke-saved-href="http://www.kaldi-asr.org/doc/io.html" href="http://www.kaldi-asr.org/doc/io.html">Kaldi I/O mechanisms</a>.(</span></code><code><span style="color:#0000ff">下文有簡單介紹</span></code><code><span style="color:#0000ff">) </span></code> <span style="color:#00000a">wspecifiers</span></span>
    • "t" (text) text 模式.

    • "b" (binary) 二進(jìn)制.

    • "f" (flush) 每次寫操作都刷新流

    • "nf" (no-flush) 每次寫操作都不刷新流

    • "p" (permissive) 寬松模式, 對于scp文件 缺少一些東西,這個 "p"不會寫入文件,也不會報告錯誤

    例如:

    <span style="color:#00000a"> "ark,t,f:data/my.ark""ark,scp,t,f:data/my.ark,|gzip -c > data/my.scp.gz"</span>

    rspecifiers

    • "o" (once)

    • "p" (permissive)

    • "s" (sorted)key按照排序后的字符串讀取

    • "cs" (called-sorted) 進(jìn)行排序

    2. 命令是混合高斯模型初始化過程和生成一個決策樹,$cmd就是run.pl

    $cmd JOB=1 $dir/log/init.log \

    gmm-init-mono $shared_phones_opt "--train-feats=$feats subset-feats --n=10 ark:- ark:-|" $lang/topo $feat_dim \

    $dir/0.mdl $dir/tree || exit 1;

    run.pl中下面這段代碼:

    open(B, "|bash") || die "run.pl: Error opening shell command";

    print B "( " . $cmd . ") 2>>$logfile >> $logfile";

    close(B);

    個人理解是使得$cmd命令直接通過管道在shell中執(zhí)行并且記錄日志(百度沒有搜到相關(guān)語法,只知道|是管道)這里是使用運行C++程序工具

    從日志可以得到字符替換后的命令參數(shù)其中

    # gmm-init-mono C++程序

    --shared-phones="$lang/phones/sets.int" 之前生成的音素的集合

    "--train-feats=ark,s,cs:apply-cmvn --utt2spk=ark:data/train_yesno/split1/1/utt2spk scp:data/train_yesno/split1/1/cmvn.scp scp:data/train_yesno/split1/1/feats.scp ark:- | add-deltas ark:- ark:- | subset-feats --n=10 ark:- ark:-|"

    data/lang/topo 拓?fù)鋱D

    39 梅爾倒譜頻率39

    ?

    ?

    輸出:exp/mono0a/0.mdl 生成的模型可以使用gmm-info查看概要信息:

    root@wenlong:/yesno/s5# gmm-info --print-args=false ./exp/mono0a/0.mdl

    number of phones 3

    number of pdfs 11

    number of transition-ids 30

    number of transition-states 11

    feature dimension 39

    number of gaussians 11

    ?

    輸出:exp/mono0a/tree 決策樹

    root@wenlong:/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5# tree-info $tree

    tree-info exp/mono0a/tree

    num-pdfs 11

    context-width 1

    central-position 0

    ?

    決策樹是如何在 kaldi 中使用的官方文檔:

    http://kaldi-asr.org/doc/tree_externals.html

    <span style="color:#00000a"><code>使用命令查看</code><code>phone </code><code>樹</code></span>
    <span style="color:#00000a"><code>draw-tree data/lang/phones.txt exp/mono0a/tree | dot -Tps -Gsize=7,11 | ps2pdf - ./tree.pdf</code></span>
    <span style="color:#00000a"><img data-cke-saved-src="https://img-blog.csdnimg.cn/2022010704134354462.png" src="https://img-blog.csdnimg.cn/2022010704134354462.png" data-cke-saved-name="圖像5" name="圖像5" data-cke-upload-id="5" data-widget="uploadimage" width="643" height="274" /></span>

    ?

    C++工具draw-tree

    http://www.kaldi-asr.org/doc/draw-tree_8cc.html

    "輸出一個決策樹"

    使用幫助:

    "Usage: draw-tree [options] <phone-symbols> <tree>\n"

    "e.g.: draw-tree phones.txt tree | dot -Gsize=8,10.5 -Tps | ps2pdf - tree.pdf\n"

    ?

    run.pl 把參數(shù)傳到shell中運行了以下C++工具

    gmm-init-mono --shared-phones=data/lang/phones/sets.int '--train-feats=ark,s,cs:apply-cmvn --utt2spk=ark:data/train_yesno/split1/1/utt2spk scp:data/train_yesno/split1/1/cmvn.scp scp:data/train_yesno/split1/1/feats.scp ark:- | add-deltas ark:- ark:- | subset-feats --n=10 ark:- ark:-|' data/lang/topo 39 exp/mono0a/0.mdl exp/mono0a/tree

    ?

    subset-feats --n=10 ark:- ark:-

    ?

    add-deltas ark:- ark:-

    ?

    apply-cmvn --utt2spk=ark:data/train_yesno/split1/1/utt2spk scp:data/train_yesno/split1/1/cmvn.scp scp:data/train_yesno/split1/1/feats.scp ark:-

    ?

    3. 命令

    echo "$0: Compiling training graphs"

    $cmd JOB=1:$nj $dir/log/compile_graphs.JOB.log \

    compile-train-graphs --read-disambig-syms=$lang/phones/disambig.int $dir/tree $dir/0.mdl $lang/L.fst \

    "ark:sym2int.pl --map-oov $oov_sym -f 2- $lang/words.txt < $sdata/JOB/text|" \

    "ark:|gzip -c >$dir/fsts.JOB.gz" || exit 1;

    ?

    #其中$cmdrun.pl腳本 JOB=1:$nj是并行處理 $dir/log/compile_graphs.JOB.log 是記錄日志

    ?

    compile-train-graphs --read-disambig-syms=data/lang/phones/disambig.int exp/mono0a/tree exp/mono0a/0.mdl data/lang/L.fst 'ark:sym2int.pl --map-oov 1 -f 2- data/lang/words.txt < data/train_yesno/split1/1/text|' 'ark:|gzip -c >exp/mono0a/fsts.1.gz'

    ?

    執(zhí)行完成會在日志輸出以下結(jié)果

    LOG (compile-train-graphs[5.2.130~1-1771a]:main():compile-train-graphs.cc:147) compile-train-graphs: succeeded for 31 graphs, failed for 0

    ?

    參考官方文檔相關(guān):Decoding-graph creation recipe (training time)

    http://kaldi-asr.org/doc/graph_recipe_train.html

    4. 命令

    echo "$0: Aligning data equally (pass 0)"

    $cmd JOB=1:$nj $dir/log/align.0.JOB.log \

    align-equal-compiled "ark:gunzip -c $dir/fsts.JOB.gz|" "$feats" ark,t:- \| \

    gmm-acc-stats-ali --binary=true $dir/0.mdl "$feats" ark:- \

    $dir/0.JOB.acc || exit 1;

    ?

    運行原理類似上一個命令,執(zhí)行 align-equal-compiled程序把結(jié)果利用管道當(dāng)成輸出執(zhí)行第二個程序 gmm-acc-stats-ali

    ?

    5. gmm-est工具是基于GMM的最大似然重估聲學(xué)模型

    gmm-est --min-gaussian-occupancy=3 --mix-up=$numgauss --power=$power \

    $dir/0.mdl "gmm-sum-accs - $dir/0.*.acc|" $dir/1.mdl 2> $dir/log/update.0.log || exit 1;

    ?

    ?

    6. 在while循環(huán)中使用gmm-acc-stats-ali(GMM訓(xùn)練累積狀態(tài))和gmm-est工具進(jìn)行訓(xùn)練,并且按照 realign_iters="1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 23 26 29 32 35 38";這些次數(shù)時候使用gmm-align-compiled工具重新對齊數(shù)據(jù)

    ?

    # Graph compilation

    . 該腳本創(chuàng)建一個完整的可擴(kuò)展的解碼圖HCLG

    utils/mkgraph.sh data/lang_test_tg exp/mono0a exp/mono0a/graph_tgpr

    ?

    描繪了所有語言模型G,發(fā)聲詞典(lexicon)L,上下文依賴(context-dependecy)C,還有我們模型HMM的結(jié)構(gòu)H,輸出結(jié)果是有限狀態(tài)轉(zhuǎn)換器(FST),在輸出中有word-ids,pdf-ids(有求解GMM的indexes),具體過程查看官方文檔Decoding-graph creation recipe (test time)

    http://kaldi-asr.org/doc/graph_recipe_test.html

    http://blog.csdn.net/quhediegooo/article/details/70037062 這篇文檔關(guān)于HCLG知識

    ?

    ?

    1. 初始化參數(shù)表

    lang=$1 # data/lang_test_tg

    tree=$2/tree #exp/mono0a/tree

    model=$2/final.mdl #exp/mono0a/final.mdl

    dir=$3 #exp/mono0a/graph_tgpr

    ?

    mkdir -p $dir

    ?

    2. 上下文音素窗(Phonetic context windows)

    具體參考官方文檔 How decision trees are used in Kaldi 中的Phonetic context windows部分內(nèi)容

    http://kaldi-asr.org/doc/tree_externals.html

    N=$(tree-info $tree | grep "context-width" | cut -d' ' -f2) || { echo "Error when getting context-width"; exit 1; } #N=1

    P=$(tree-info $tree | grep "central-position" | cut -d' ' -f2) || { echo "Error when getting central-position"; exit 1; } #P=0

    ?

    N 代表上下文相關(guān)音素窗的寬度,P 表示指定中心音素。

    Name in code

    Name in command-line arguments

    Value (triphone)

    Value (monophone)

    N

    –context-width=?

    3

    1

    P

    –central-position=?

    1

    0

    ?

    三音素:

    // probably not valid C++

    vector<int32> ctx_window = { 12, 15, 21 };

    假設(shè) N=3P=1,這個就代表音素15有一個右邊的上下文21和左邊的上下文12

    vector<int32> ctx_window = { 12, 15, 0 };

    表示音素15有一個左上下文和沒有右上下文,在決策樹代碼里為了方便,我們不把后續(xù)符號放在這些上下文窗中,我們直接給其賦0

    單音素:

    vector<int32> ctx_window = { 15 };

    所以單音素系統(tǒng)是上下文相關(guān)系統(tǒng)的一個特殊情況,窗的大小 N=1和一個不做任何事情的樹。

    3. 四個變量對應(yīng)的值:

    clg=$lang/tmp/CLG_${N}_${P}.fst

    clg_tmp=$clg.$$

    ilabels=$lang/tmp/ilabels_${N}_${P}

    ilabels_tmp=$ilabels.$$ #$$代表當(dāng)前進(jìn)程的id號

    ?

    clg = data/lang_test_tg/tmp/CLG_1_0.fst

    clg_tmp = data/lang_test_tg/tmp/CLG_1_0.fst.5129

    ilabels = data/lang_test_tg/tmp/ilabels_1_0

    ilabels_tmp =data/lang_test_tg/tmp/ilabels_1_0.5129

    4.生成一個exp/mono0a/graph_tgpr/Ha.fst文件,在后面腳本中為了節(jié)省空間把它刪除

    if [[ ! -s $dir/Ha.fst || $dir/Ha.fst -ot $model \

    || $dir/Ha.fst -ot $lang/tmp/ilabels_${N}_${P} ]]; then

    make-h-transducer --disambig-syms-out=$dir/disambig_tid.int \

    --transition-scale=$tscale $lang/tmp/ilabels_${N}_${P} $tree $model \

    > $dir/Ha.fst.$$ || exit 1;

    mv $dir/Ha.fst.$$ $dir/Ha.fst

    fi

    ?

    kaldi工具 make-h-transducer

    <span style="color:#00000a"> 生成從 轉(zhuǎn)移ids(transition-ids)到上下文音素依賴的H 轉(zhuǎn)移器,無自環(huán)[使用add-self-loops增加]Usage: make-h-transducer <ilabel-info-file> <tree-file> <transition-gmm/acoustic-model> [<H-fst-out>] e.g.: make-h-transducer ilabel_info 1.tree 1.mdl > H.fst </span>

    ?

    ?

    5. 使用kaldi工具進(jìn)行fst的組合,確定化,去除符號,去除空轉(zhuǎn)移,最小化,是否隨機(jī)?

    (還得好好學(xué)習(xí)以下fst相關(guān)知識)

    fsttablecompose $dir/Ha.fst "$clg" | fstdeterminizestar --use-log=true \

    | fstrmsymbols $dir/disambig_tid.int | fstrmepslocal | \

    fstminimizeencoded > $dir/HCLGa.fst.$$ || exit 1;

    mv $dir/HCLGa.fst.$$ $dir/HCLGa.fst

    fstisstochastic $dir/HCLGa.fst || echo "HCLGa is not stochastic"

    ?

    該實例shell輸出信息:

    fsttablecompose exp/mono0a/graph_tgpr/Ha.fst data/lang_test_tg/tmp/CLG_1_0.fst

    fstdeterminizestar --use-log=true

    fstrmsymbols exp/mono0a/graph_tgpr/disambig_tid.int

    fstrmepslocal

    fstminimizeencoded

    fstisstochastic exp/mono0a/graph_tgpr/HCLGa.fst

    0.5342 -0.000299216

    HCLGa is not stochastic

    ?

    6. 使用工具add-self-loops 增加自環(huán)

    ?

    add-self-loops --self-loop-scale=$loopscale --reorder=true \

    $model < $dir/HCLGa.fst | fstconvert --fst_type=const > $dir/HCLG.fst.$$ || exit 1;

    ?

    # Decoding

    ?

    ?

    ?

    附錄1 Kaldi for Dummies tutorial 官網(wǎng)內(nèi)容:

    #數(shù)據(jù)準(zhǔn)備階段

    一. 語音數(shù)據(jù):文件格式是.wav,每個文件包含幾個英文單詞,文件名對應(yīng)格式例如(1_5_6.wav.到“one,five,six”)

    數(shù)據(jù)集一般是這樣:

    1. 10和不同的說話人(ASR自動語音識別必須在不同的人訓(xùn)練和測試,人越多效果越好)

    2. 每個人說10個不同的句子。

    3. 100個*.wav文件放入10個文件夾,每個文件夾10個*.wav文件

    4. 300個詞(從數(shù)字0到9)

    5. 每個句子/話語由3個詞組成。

    一般在egs文件夾下構(gòu)建自己的訓(xùn)練測試項目文件夾,比如MyAudio文件夾在它下面創(chuàng)建兩個文件夾train和test選取一個人以人名命名的文件夾放到test文件夾用于測試,剩下9個人分別創(chuàng)建9個文件夾放到train中用于訓(xùn)練

    二. 聲學(xué)數(shù)據(jù)

    創(chuàng)建一些test文件(每個string一行對應(yīng)數(shù)字)必須是有序的,使用utils/validate_data_dir.sh驗證數(shù)據(jù),使用fix_data_dir.sh腳本修復(fù)存在的錯誤

    在MyAudio文件夾下創(chuàng)建data文件夾,然后創(chuàng)建train和test兩個子文件夾,在每個文件夾都有下列文件:

    1. spk2gender

    該文件是說話人和說話人的性別的對應(yīng)關(guān)系(f=female,m=male)

    pattern:<speakerID><gender>

    2. wav.scp

    發(fā)言人與音頻文件的對應(yīng)關(guān)系

    pattern:<utteranceID><full_path_to_audio_file>

    3. text

    包含每個發(fā)音人匹配的文本標(biāo)音

    pattern:<utteranceID><text_transcription>

    4. utt2spk

    每個發(fā)音人表述內(nèi)容對應(yīng)的說話人

    Pattern: <uterranceID> <speakerID>

    <span style="color:#00000a"> dad_4_4_2 dadjuly_1_2_5 julyjuly_6_8_3 july# and so on… 5. corpus.txt data文件夾下創(chuàng)建的一個子文件夾local,在里面創(chuàng)建一個文件corpus.txt 每行代表一個音頻文件的標(biāo)音 pattern:<text_transcription> 三. 語言數(shù)據(jù) 是語言模型文件相關(guān)的,主要是在data/local目錄下創(chuàng)建dict子目錄,該目錄有以下的文件:</span>

    1. lexicon.txt

    包含每個詞的音素的標(biāo)音

    pattern: <word> < phone1> <phone2>

    eight ey t

    five f ay v

    four f ao r

    # and so on…

    2. nonsilence_phones.txt

    該文件把非靜音音素放入一個列表

    pattern:<phone>

    ah

    ao

    ay

    # and so on…

    3. silence_phones.txt

    靜音音素

    pattern:<phone>

    sil

    spn

    4. optional_silence.txt

    可選的silence音素

    pattern : <phone>

    sil

    四. 工具腳本主要放在utils和steps中

    五.評分腳本在local/score.sh 獲得解碼結(jié)果

    六. 配置文件

    創(chuàng)建一個文件夾conf創(chuàng)建下面2個文件

    1. decode.config

    first_beam=10.0

    beam=13.0

    lattice_beam=6.0

    2.mfcc.conf

    --use-energu=false

    一般來說,訓(xùn)練主要是MONO但音素訓(xùn)練,簡單三音素訓(xùn)練兩種方式。

    ?

    附錄2 Kaldi I/O機(jī)制

    (由于調(diào)用C++程序?qū)?shù)不太理解,查了資料需要學(xué)習(xí)這個機(jī)制)

    I/O機(jī)制代碼級別官方文檔:http://www.kaldi-asr.org/doc/io.html

    命令行的I/O機(jī)制:http://www.kaldi-asr.org/doc/io_tut.html

    . Non-table I/O

    所涉及的文件或者流僅僅包含一到兩個對象(聲學(xué)模型文件,變換矩陣

    1. kaldi文件默認(rèn)是2進(jìn)制的,如果flag –binary=false輸出則是非2進(jìn)制

    2. 有許多符合 "copy" 程序, e.g. copy-matrix gmm-copy, 可以使用 –binary=false 這個標(biāo)志轉(zhuǎn)換成text格式, e.g. "copy-matrix --binary=false foo.mat -".

    3.磁盤上的文件應(yīng)該和內(nèi)存中的C++的object對象一致,e.g. a matrix of floats,盡管一些文件比這個object對象多(對于聲學(xué)模型文件有 TransitionModel object 和一個聲學(xué)模型)

    4. kaldi程序需要知道它要讀的文件的類型,而不是從流中讀出類型。(PS:所以要加scp:)

    5. 同樣地,對于perl一個文件名能夠被 - 所替換或是一個例如"|gzip -c >foo.gz" or "gunzip -c foo.gz|" 的string

    6. 對于讀文件,也支持如 “foo:1045” 表示從 foo 文件偏移 1045 個字節(jié)開始讀取。

    例如 echo '[ 0 1 ]' | copy-matrix --binary=false - - 其中 | 代表管道把輸出變?yōu)橄旅娴妮斎?/span>

    或是這樣:echo '[ 0 1 ]|' 'copy-matrix - - | copy-matrix --binary=false - -' 傳入兩個參數(shù)得到一樣效果

    二. Table I/O

    處理strings字符串索引的數(shù)據(jù)集合,比如通過utterance-ids索引的特征矩陣或是通過speaker-ids索引的speaker-adaptation 變化矩陣,strings必須非空。

    ?

    一個表可能存在兩種格式:一個是 "archive" 或是 "script ".不同是 archive包含真實的數(shù)據(jù),script文件定位一個數(shù)據(jù)的位置。

    ?

    "rspecifier" 程序從表中讀,告訴我們?nèi)绾巫x一個索引的數(shù)據(jù)

    "wspecifier"程序把數(shù)據(jù)寫入表中

    rspecifiers的共同的類型是"ark:-", 從標(biāo)準(zhǔn)輸入中作為一個archive讀取數(shù)據(jù),或是"scp:foo.scp",代表從script文件foo.scp讀取數(shù)據(jù)

    ?

    • 對于 rspecifiers的 ark,s,cs:- 代表我們從標(biāo)準(zhǔn)輸入讀已經(jīng)排序的keys (,s) 我們認(rèn)為他們將按順序被讀取, (,cs)意味著我們知道程序?qū)?按順序訪問他們(如果條件不滿足,程序?qū)罎?#xff09;,好處就是可以隨機(jī)訪問而不會浪費大量的內(nèi)存。

    • 對于數(shù)據(jù)不是很大還有不方便確保順序 (e.g. transforms for speaker adaptation), 省略,s,cs.幾乎沒有壞處

    • 通常程序會采用多個 rspecifiers 的對于第一個通常不需要",s,cs"

    • 對于scp,p:foo.scp, 這個 ,p 意味著如果這些引用的文件不存在則我們不應(yīng)該讓程序崩潰 (對于archives,如果這個 archive 損壞和截斷p 將阻止崩潰.)

    • 對于寫數(shù)據(jù)這個選項 ,t 意味著text模式, e.g. in ark,t:-. 這個 –binary 命令行選項將不會影響到這個archives.


    ?

    附錄3 Kaldi常用工具

    參考kaldi常用工具 http://blog.csdn.net/zjm750617105/article/details/52548798

    kaldi官網(wǎng)工具大全http://kaldi-asr.org/doc/tools.html


    ?

    附錄4 FSTFinite State Transducer)總結(jié):

    一般使用的是WFSTWeightd Finite State Transducer)加權(quán)有限狀態(tài)轉(zhuǎn)換器

    看了那篇論文挑選一些重點(L, see "Speech Recognition with Weighted Finite-State Transducers" by Mohri, Pereira and Riley, in Springer Handbook on SpeechProcessing and Speech Communication, 2008)

    (沒看完,以后有時間再看它,先看腳本了)

    OpenFst資源:OpenFst website

    http://www.openfst.org/twiki/bin/view/FST/WebHome

    一篇中文博客講解WFST中epsilon removal和determinization操作

    http://blog.csdn.net/l_b_yuan/article/details/50954425

    2.1. Weighted Acceptors 加權(quán)接收器

    A finite-state transducer is a finite automaton whose state transitions are labeled with both input and output symbols. Therefore, a path through the transducer encodes a mapping from an input symbol sequence, or string, to an output string. A weighted transducer puts weights on transitions in addition to the input and output symbols. Weights may encode probabilities, durations, penalties, or any other quantity that accumulates along paths to compute the overall weight of mapping an input string to an out-put string. Weighted transducers are thus a natural choice to represent the probabilistic finite-state models prevalent in speech processing.

    一個有限狀態(tài)轉(zhuǎn)義器是一個有限狀態(tài)機(jī),他的轉(zhuǎn)義轉(zhuǎn)換是用輸入輸出符號標(biāo)記。因此,一個路徑通過轉(zhuǎn)換器編碼一個從輸入序列或字符串到輸出符號的映射。權(quán)重轉(zhuǎn)換器除了輸入輸出符號外還把權(quán)重放到轉(zhuǎn)移過程上。權(quán)重可能是編碼概率,持續(xù)時間,懲罰因子或是其他沿著路徑計算全部輸入字符串到輸出字符串的映射權(quán)重的積累量。權(quán)重轉(zhuǎn)換器因此也是代表流行在語音處理方面概率有限狀態(tài)模型的一個自然選擇。


    ?


    ?

    1 (a)

    The automaton in Figure 1(a) is a toy finite-state language model. The legal word strings are specified by the words along each complete path, and their probabilities by the product of the corresponding transition probabilities.

    這個圖是一個微不足道的有限狀態(tài)語言模型。合法詞字符串被沿著每個完整路徑的詞所指定,他們的概率和通過符合轉(zhuǎn)移概率的乘積得到。


    ?


    ?

    1 (b)

    The automaton in Figure 1(b) gives the possible pro-nunciations of one word, data, used in the language model. Each legal pronunciation is the phone strings along a complete path, and its probability is given by the product of the corresponding transition probabil-ities.

    這個圖的自動機(jī)給了一個詞,數(shù)據(jù)在語言模型的發(fā)音可能。每個合法的發(fā)音是沿著完整路徑的音素串,它的可能性也是通過符合轉(zhuǎn)移概率的乘積取得。


    ?


    ?

    1(c)

    Finally, the automaton in Figure 1(c) encodes a typical left-to-right, three-distribution-HMM struc-ture for one phone, with the labels along a complete path specifying legal strings of acoustic distributions for that phone.

    這個圖編碼了一個典型的從左到右,三分布(音素)HMM結(jié)構(gòu)的音素,這個標(biāo)簽沿著一個完整路徑指定音素的發(fā)音分布的合法字符串。

    These automata consist of a set of states, an ini-tial state, a set of final states (with final weights), and a set of transitions between states. Each transition has a source state, a destination state, a label and a weight. Such automata are called weighted finite-state acceptors (WFSA), since they accept or recog-nize each string that can be read along a path from the start state to a final state. Each accepted string is assigned a weight, namely the accumulated weights along accepting paths for that string, including final weights. An acceptor as a whole represents a set of strings, namely those that it accepts. As a weighted acceptor, it also associates to each accepted string the accumulated weights of their accepting paths.

    這些自動機(jī)由一組狀態(tài)組成,一個初始狀態(tài),一組終止?fàn)顟B(tài)(終止權(quán)重)和一組轉(zhuǎn)臺之間的轉(zhuǎn)移。每個轉(zhuǎn)移都有一個來源狀態(tài)一個目標(biāo)狀態(tài),一個標(biāo)簽和一個權(quán)重組成。這樣的自動機(jī)成為加權(quán)有限狀態(tài)轉(zhuǎn)換器(WFST),因為他們能夠沿著從開始狀態(tài)到終止?fàn)顟B(tài)的一條路徑讀取到接收或識別的每個字符串。每個接收的字符串分配一個權(quán)重,也就是沿著接收路徑字符串的累積權(quán)重,包括最終的權(quán)重。(我在想上面的概率是乘,這里的權(quán)重不知道是加還是乘或是什么?)作為一個整體代表一組字符串的接收器,即那些它接收的。作為一個加權(quán)的接收器,它還將每個接受的字符串與其接受路徑的累積權(quán)重相關(guān)聯(lián)。

    2.2. Weighted Transducers 加權(quán)轉(zhuǎn)換器

    Our approach uses finite-state transducers, rather than acceptors, to represent the n-gram grammars, pronunciation dictionaries, context-dependency specifications, HMM topology, word, phone or HMM segmentations, lattices and n-best output lists encountered in ASR. The transducer representation provides general methods for combining models and optimizing them, leading to both simple and flexible ASR decoder design

    我們不用接收器而用有限狀態(tài)轉(zhuǎn)換器表示在自動語音識別(ASR)遇到的n-gram 語法,發(fā)音詞典,上下文依賴規(guī)范,HMM拓?fù)浣Y(jié)構(gòu),詞,音素或者HMM分段(HMM segmentations),點陣和n-best輸出列表。這個轉(zhuǎn)換器代表對于組合模型和優(yōu)化他們提供一般的方法,主導(dǎo)了簡單而又靈活的ASR解碼器的設(shè)計。

    A weighted finite-state transducer (WFST) is quite similar to a weighted acceptor except that it has an input label, an output label and a weight on each of its transitions.

    加權(quán)有限狀態(tài)轉(zhuǎn)換器和加權(quán)接收器特別的相似,就是多了一個輸入標(biāo)簽,輸出標(biāo)簽和每個轉(zhuǎn)換的權(quán)重。

    The examples in Figure 2 encode (a superset of) the information in the WFSAs of Fig-ure 1(a)-(b) as WFSTs. Figure 2(a) represents the same language model as Figure 1(a) by giving each transition identical input and output labels. This adds no new information, but is a convenient way we use often to treat acceptors and transducers uniformly.

    圖2將圖1的WFSA的信息編碼成為WFST。通過給每個轉(zhuǎn)換相同的輸入輸出標(biāo)簽使得圖2(a)和圖1(a)表示相同的語言模型。雖然沒有增加新信息,但是這給了我們使用處理接收器和轉(zhuǎn)換器一致性的便利方法。

    2 (a)

    Figure 2(b) represents a toy pronunciation lexi-con as a mapping from phone strings to words in the lexicon, in this example data and dew, with probabilities representing the likelihoods of alternative pronunciations. It transduces a phone string that can be read along a path from the start state to a final state to a word string with a particular weight. The word corresponding to a pronunciation is out-put by the transition that consumes the first phone for that pronunciation. The transitions that consume the remaining phones output no further symbols, indicated by the null symbol ε as the transition’s output label. In general, an ε input label marks a transition that consumes no input, and an # output label marks a transition that produces no output.

    圖2(b)表示一個作為一個在詞典中從音素串到詞的映射的簡單的發(fā)音詞典,在這個例子中data和dew,用概率表示選擇發(fā)音的最大死然度。沿著從開始狀態(tài)到終止?fàn)顟B(tài)的一個特殊權(quán)重的詞串能夠讀取出來轉(zhuǎn)換的一個音素串。與一個發(fā)音一致的詞是通過這個轉(zhuǎn)換消耗第一個發(fā)音的音素的輸出。這個轉(zhuǎn)換消耗剩余音素不會有更多符號輸出,表示通過null符號#作為轉(zhuǎn)換的結(jié)果符號。一般來說,一個 ε符號標(biāo)記了一個轉(zhuǎn)換沒有消耗輸入,一個 ε符號的輸出標(biāo)簽標(biāo)記的一個轉(zhuǎn)換不會產(chǎn)生輸出。


    ?


    ?


    ?


    ?

    圖2 (b)

    This transducer has more information than the WFSA in Figure 1(b). Since words are encoded by the output label, it is possible to combine the pronunciation transducers for more than one word without losing word identity.Similarly, HMM structures of the form given in Figure 1(c) can be combined into a single transducer that preserves phone model identity.

    通過輸出標(biāo)簽編碼的詞可以組合更多詞的發(fā)音轉(zhuǎn)換器而不會丟失詞的獨一性。同樣圖1(c)這種格式的HMM結(jié)構(gòu)也能組合這種單獨轉(zhuǎn)換器保存音素模型的獨一性。

    This illustrates the key advantage of a transducer over an acceptor: the transducer can

    represent a rela-tionship between two levels of representation, for in-stance between phones and words or between HMMs and context-independent phones.

    優(yōu)勢是轉(zhuǎn)換器能夠保存兩個表示級別的相對關(guān)系,例如音素和詞之間或者HMM和上下文依賴音素之間。

    More precisely, a transducer specifies a binary relation between strings: two strings are in the relation when there is a path from an initial to a final state in the transducer that has the first string as the sequence of input labels along the path, and the second string as the sequence of output labels along the path (� symbols are left out in both input and output). In general, this is a relation rather than a function since the same input string might be transduced to different strings along two distinct paths. For a weighted transducer, each string pair is also associated with a weight.

    準(zhǔn)確的說,一個轉(zhuǎn)換器指定字符串之間的二元關(guān)系:當(dāng)有一個在轉(zhuǎn)換器從一個初始到終止?fàn)顟B(tài)的路徑,第一個字符串作為這條路經(jīng)輸入標(biāo)簽順序和第二個字符串作為這條路經(jīng)的輸出標(biāo)簽順序。一般來說,這是一個關(guān)系而不是一個函數(shù),因為相同的輸入字符串可能沿著兩條不同路徑被轉(zhuǎn)換成不同的字符串。對于權(quán)重轉(zhuǎn)換器每隊字符串都與權(quán)重相關(guān)聯(lián)。

    We rely on a common set of weighted transducer operations to combine,optimize, search and prune them [Mohri et al., 2000]. Each operation implements a single, well-defined function that has its foundations in the mathematical theory of rational power series [Salomaa and Soittola, 1978, Bers-tel and Reutenauer, 1988,Kuich and Salomaa, 1986]. Many of those operations are the weighted transducer generalizations of classical algorithms for un-weighted acceptors.

    用這個加權(quán)轉(zhuǎn)換器的操作去組合,優(yōu)化,查找,修剪。每個操作實現(xiàn)一個單一的,明確定義的函數(shù),這個函數(shù)已經(jīng)在有理冪級數(shù)數(shù)學(xué)理論中建立起來。許多操作都是對非加權(quán)接收器的經(jīng)典算法進(jìn)行加權(quán)轉(zhuǎn)換概括處理。

    2.3. Composition 應(yīng)該是進(jìn)行模型組合運算

    Composition is the transducer operation for combining different levels of representation. For instance, a pronunciation lexicon can be composed with a word-level grammar to produce a phone-to-word transducer whose word strings are restricted to the grammar. A variety of ASR transducer com-bination techniques, both context-independent and context-dependent, are conveniently and efficiently implemented with composition.

    轉(zhuǎn)換器運算----組合是結(jié)合不同級別的表示。例如一個發(fā)聲詞典能夠與詞級別的語法結(jié)合產(chǎn)生一個音素到詞的轉(zhuǎn)換器,這個轉(zhuǎn)換器的詞串被語法約束。不同的ASR轉(zhuǎn)換器結(jié)合技術(shù)(包括上下文不依賴和上下文依賴)既便利又效率的組合實現(xiàn)。

    As previously noted, a transducer represents a bi-nary relation between strings. The composition of two transducers represents their relational composi-tion. In particular, the composition T = T 1 ? T 2 of two transducers T 1 and T 2 has exactly one path mapping string u to string w for each pair of paths, the first in T 1 mapping u to some string v and the sec-ond in T 2 mapping v to w. The weight of a path in T is computed from the weights of the two corre-sponding paths in T 1 and T 2 with the same operation that computes the weight of a path from the weights of its transitions. If the transition weights represent probabilities, that operation is the product. If instead the weights represent log probabilities or negative log probabilities as is common in ASR for numerical stability, the operation is the sum. More generally, the weight operations for a weighted transducer can be specified by a semiring [Salomaa and Soittola, 1978, Berstel and Reutenauer, 1988, Kuich and Salomaa, 1986],as discussed in more detail in Section 3.

    正如之前指出,一個轉(zhuǎn)換器表示一個字符串的二元關(guān)系。這兩個轉(zhuǎn)換器的組合表示了他們的關(guān)系。特別是這個組合T = T 1 ? T 2,兩個轉(zhuǎn)換器T1和T2有一個正確的路徑映射每條路徑上的字符u和字符w ,第一步在T1映射字符u到字符v然后在第二步T2映射v到w。在T 的這個路徑權(quán)重是從T1和T2相同操作兩個符合路徑的權(quán)重計算的,這相同的操作從其轉(zhuǎn)換權(quán)重計算路徑的權(quán)重。如果這個權(quán)重表示為概率,這個運算就是乘積。如果在ASR中這個權(quán)重?fù)Q作表示log概率或者負(fù)log概率作為數(shù)字的穩(wěn)定性,那么運算就是和的形式。一般來說對于權(quán)重轉(zhuǎn)換器的權(quán)重運算能夠通過一個半環(huán)所指定。(需要學(xué)習(xí)下群和半環(huán))


    ?

    例如,取B=(0,3),A=(1,2),則B-A=(0,1]U[2,3)

    不能寫出有限個互不相交的開區(qū)間的并,不是半環(huán)。

    例如:取B=[0,3),A=[1,2),則B-A=[0,1)U[2,3)是兩個半開區(qū)間的并是半環(huán)。


    ?


    ?


    ?


    ?


    ?


    ?


    ?


    ?


    ?


    ?


    ?


    ?

    總結(jié)

    以上是生活随笔為你收集整理的从yesno模型入门kaldi语音识别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。