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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从yesno模型入门kaldi语音识别

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

yesno模型

?

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

kaldi官網工具大全http://kaldi-asr.org/doc/tools.html

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

執行 run.sh入口程序

?

# 數據處理階段

?

?

. 訓練和測試數據預處理階段

執行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把樣本集一半數據共30個用作訓練文件名列表存在 data/local/waves.train,另一半共30個識別測試文件名列表存到data/local/waves.test。

?

3.create_yesno_wav_scp.pl腳本把waves.test文件進行標注存到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進行標注存到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進行標注到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進行標注到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 目錄創建一個文件lm_tg.arpa內容:

\data\

ngram 1=4

?

\1-grams:

-1 NO

-1 YES

-99 <s>

-1 </s>

?

\end\

?

8. 從WSJ樣本復制階段

?

8.1.創建目錄data/train_yesno 和data/test_yesno

?

8.2. 把data/local/test_yesno_wav.scp 復制到data/test_yesno/wav.scp

把data/local/train_yesno_wav.scp 復制到data/train_yesno/wav.scp

?

8.3.把data/local/train_yesno.txt 復制到 data/train_yesno/text

把data/local/test_yesno .txt 復制到 data/test_yesno/text

?

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

?

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 轉換成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

?

此時目錄結構如下:

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>

?

. 字典預處理階段

執行local/prepare_dict.sh

?

1. 創建詞典目錄data/local/dict 和 復制文件:input/lexicon_nosil.txt 到data/local/dict/lexicon_words.txt ; input/lexicon.txt 到data/local/dict/lexicon.txt

lexicon_words.txt內容:

YES Y

NO N

?

lexicon.txt 內容:

<SIL> SIL

YES Y

NO N

?

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

Y

N

?

3. data/local/dict/silence_phones.txt 和 data/local/dict/optional_silence.txt 內容:

SIL

?

此時目錄結構如下:

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

?

. 執行命令

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

?

1. 調用這個腳本處理傳入的參數

. utils/parse_options.sh

?

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

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

?

1.2 最后左移兩個參數,參數列表變為:

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. 執行不啟動新的shell執行腳本 設置環境變量

. ./path.sh

執行 腳本 設置環境變量 KALDI_ROOT和 PATH

kaldi/tools/env.sh

?

4. 執行命令檢測詞典文件內容是否正確

utils/validate_dict_dir.pl $srcdir

?

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

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

(通過 check_lexicon_pair函數 檢查詞典是否成對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是否為普通文件,不是普通文件則執行該指令

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

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

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

?

6.命令 復制文件 內容:

cp $srcdir/lexiconp.txt $tmpdir/

lexiconp.txt內容:

<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文件內容:

SIL

Y

N

?

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

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

phone_map.txt內容:

SIL SIL

Y Y

N N

創建目錄 data/lang/phones 一系列音素的集合

mkdir -p $dir/phones

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

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

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

?

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

sets.txt 內容:

SIL

Y

N

?

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

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

?

roots.txt內容:

shared split SIL

shared split Y

shared split Nlex_ndisambig

?

?

7. 下面命令其中|代表管道,執行 utils/apply_map.pl 傳到腳本的第一個值 $tmpdir 第二個值是$srcdir/silence_phones.txt 的內容,然后把腳本運行的結果傳給后并輸出到文件中屬于標準輸入<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 內容:

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 內容:

Y

N

?

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

?

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

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

?

optional_silence.txt內容:

SIL

?

context_indep.txt內容:

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文件每行第一個字段 并且排序去除重復 增加幾個字段 并且編號 輸出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 內容:

<SIL> 1.0 SIL

YES 1.0 Y

NO 1.0 N

?

words.txt 內容:

<eps> 0

<SIL> 1

NO 2

YES 3

#0 4

<s> 5

</s> 6

?

10. 如果沒有使用詞-位置-依賴音素(word-position-dependent phones)的方法我們使用格詞對齊(lattice word alignment)的方法,并且創建$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

?

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

cat $tmpdir/align_lexicon.txt | \

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

?

11. # 通過腳本命令創建 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

?

到這里代碼輸出結果為:

<SIL> <SIL> 1

<eps> <eps> 1

NO NO 3

YES YES 2

?

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

經過后半段代碼輸出為:

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;

?

其中命令對概率是通過對數處理,比如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`

?

執行這句話shell輸出下面的結果:

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

?

整個命令創建L.fst文件用于訓練是silence 概率,內容:

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,其打印結果,一行一般有5列。一行對應一個弧。第一列和第二列,表示這個弧的起始狀態和終止狀態。第三列和第四列,表示輸入和輸出。第五列是權重。

使用下面命令生成一個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有限狀態機,FST 與FSM最主要的區別在于FST在完成狀態轉移的同時產生一個輸出)語音這里是以音素輸入,詞輸出結果。

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

初始狀態0狀態到1狀態: 輸入 音素<eps>和 SIL 權重都是0.69315 輸出都是 SIL 靜音

從1狀態到2狀態:3:2/0.69315 輸入音素 N輸出詞No 權重0.69315

2:3/0.69315 輸入音素 Y輸出詞Yes 權重0.69315

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

從狀態1到狀態1:3:2/0.69315 輸入音素 N輸出詞No 權重0.69315

2:3/0.69315 輸入音素 Y輸出詞Yes 權重0.69315

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

狀態1是終止狀態 ,結束時候可以得到該輸出語句的權重總和。

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

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

2.3. Composition 應該是進行模型組合運算


?

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

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

?

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

oov.txt 內容只有一行 : <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文件 內容:#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. 使用同樣的方法創建這個矩陣文件

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` #結果 : silphonelist=1

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

?

16. 生成一個拓撲文件,允許控制這個 non-silence HMMs和 silence HMMs 的狀態數

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

?

topo內容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也是一個發音詞典,除了L.fst的內容,還包括#1, #2這種消除岐義的符號,#0是一個自環,具體可以看Disambiguation symbols說明:

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

使用fstprint命令得到內容:

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狀態圖:

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;

?

處理之后目錄結構圖:

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

?

?

. 執行命令 local/prepare_lm.sh 準備語言模型用于測試

LMlanguage model)在data/lang_test_tg 目錄

1. 命令arpa2fst是一個KaldiC++ 程序。該程序將ARPA格式的語言模型轉換為一個加權有限狀態轉換器(實際上是一個接收器)

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

?

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

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

words.txt內容:

<eps> 0

<SIL> 1

NO 2

YES 3

#0 4

<s> 5

</s> 6

?

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

(詞組前面的數字:概率,詞組后面的數據,回退權值)

yesno的模型input/task.arpabo

\data\

ngram 1=4


?

\1-grams:

-1 NO

-1 YES

-99 <s>

-1 </s>

\end\


?

通過arpa2fst轉換的G.fst 通過fstprint函數可以看到結果:

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,其打印結果,一行一般有5列。一行對應一個弧。第一列和第二列,表示這個弧的起始狀態和終止狀態。第三列和第四列,表示輸入和輸出。第五列是權重。

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

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

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

fstisstochastic data/lang_test_tg/G.fst

輸出結果: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執行以下三條指令

train_yesno 為例

. 命令

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

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

主要為了創建feats.scp文件

?

1. 創建目錄/home/wenlong/wenlong_GIT/kaldi/egs/yesno/s5/mfcc exp/make_mfcc/train_yesno

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

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

4. 該腳本檢測data目錄中數據是否正常

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目錄執行else之后的語句,顯示提示steps/make_mfcc.sh: [info]: no segments file exists: assuming wav.scp indexed by utterance.

?

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

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;

?

參數列表:

  • 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

    ?

    其中該語句根據cpu核心數量設置并行任務數;

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

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

    ?

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

    使用fseek()定位到24字節位置讀取內容。

    ?

    ?

    下面這段代碼利用Kaldicompute-mfcc-feats工具計算梅爾倒譜頻率特征,然后利用copy-feats工具的參數—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

    ?

    查看前幾行數據內容:

    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內容拷貝到 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 內容格式:

    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

    ?

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

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

    ?

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

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

    三. 在data/train_yesno 和data/test_yesno 創建兩個目錄 .back 然后把需要的文件復制過來

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

    utils/fix_data_dir.sh data/$x

    ?

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


    ?

    <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 訓練

    發現一個文檔在訓練階段講解比較詳細

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

    ?

    執行代碼該語句進行單音素訓練

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

    --totgauss 400 \

    data/train_yesno data/lang exp/mono0a

    ?

    $data 對應參數 data/train_yesno ;

    $lang 對應參數 data/lang;

    $dir 對應參數 exp/mono0a;

    ?

    nj根據參數--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++代碼執行可以得到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">代碼執行時傳入的數據文件類型,其中</span></code><code><span style="color:#000000">ark</span></code><code><span style="color:#000000">是二進制文件。</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文件都可以看成是數據表。這種格式有如下特點:

    <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>和“可擴展文件名”讓</code><code>Kaldi</code><code>去找數據</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>.ark</code><code>格式可能是文本</code><code>/</code><code>二進制,”</code><code>t”</code><code>參數表示文本,默認是二進制。格式:</code><code>key</code><code>的</code><code>id</code><code>,空格,目標數據。</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>代碼可以順序或隨機訪問</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>通過隨機訪問來讀取</code><code>.ark</code><code>文件可能是無效的,因為代碼可能必須將對象緩存在內存中。</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>為了有效地隨機訪問</code><code>.ark</code><code>文件,您可以使用“</code><code>ark</code><code>,</code><code>scp”</code><code>寫入機制(例如用于將</code><code>mfcc</code><code>功能寫入磁盤)來寫出相應的腳本文件。 然后,通過</code><code>scp</code><code>文件訪問它。</code></span> <code><span style="color:#0000ff">? </span></code><span style="color:#0000ff"><code>在檔案上進行隨機訪問時,避免代碼必須緩存一堆內容的另一種方法是告知代碼歸檔歸檔并按排序順序調用(例如“</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) 二進制.

    • "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) 進行排序

    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中執行并且記錄日志(百度沒有搜到相關語法,只知道|是管道)這里是使用運行C++程序工具

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

    # 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 拓撲圖

    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 把參數傳到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'

    ?

    執行完成會在日志輸出以下結果

    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

    ?

    參考官方文檔相關: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;

    ?

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

    ?

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

    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循環中使用gmm-acc-stats-ali(GMM訓練累積狀態)和gmm-est工具進行訓練,并且按照 realign_iters="1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 23 26 29 32 35 38";這些次數時候使用gmm-align-compiled工具重新對齊數據

    ?

    # Graph compilation

    . 該腳本創建一個完整的可擴展的解碼圖HCLG

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

    ?

    描繪了所有語言模型G,發聲詞典(lexicon)L,上下文依賴(context-dependecy)C,還有我們模型HMM的結構H,輸出結果是有限狀態轉換器(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 這篇文檔關于HCLG知識

    ?

    ?

    1. 初始化參數表

    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部分內容

    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 代表上下文相關音素窗的寬度,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 };

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

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

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

    單音素:

    vector<int32> ctx_window = { 15 };

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

    3. 四個變量對應的值:

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

    clg_tmp=$clg.$$

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

    ilabels_tmp=$ilabels.$$ #$$代表當前進程的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文件,在后面腳本中為了節省空間把它刪除

    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"> 生成從 轉移ids(transition-ids)到上下文音素依賴的H 轉移器,無自環[使用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工具進行fst的組合,確定化,去除符號,去除空轉移,最小化,是否隨機?

    (還得好好學習以下fst相關知識)

    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 增加自環

    ?

    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 官網內容:

    #數據準備階段

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

    數據集一般是這樣:

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

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

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

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

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

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

    二. 聲學數據

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

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

    1. spk2gender

    該文件是說話人和說話人的性別的對應關系(f=female,m=male)

    pattern:<speakerID><gender>

    2. wav.scp

    發言人與音頻文件的對應關系

    pattern:<utteranceID><full_path_to_audio_file>

    3. text

    包含每個發音人匹配的文本標音

    pattern:<utteranceID><text_transcription>

    4. utt2spk

    每個發音人表述內容對應的說話人

    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文件夾下創建的一個子文件夾local,在里面創建一個文件corpus.txt 每行代表一個音頻文件的標音 pattern:<text_transcription> 三. 語言數據 是語言模型文件相關的,主要是在data/local目錄下創建dict子目錄,該目錄有以下的文件:</span>

    1. lexicon.txt

    包含每個詞的音素的標音

    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 獲得解碼結果

    六. 配置文件

    創建一個文件夾conf創建下面2個文件

    1. decode.config

    first_beam=10.0

    beam=13.0

    lattice_beam=6.0

    2.mfcc.conf

    --use-energu=false

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

    ?

    附錄2 Kaldi I/O機制

    (由于調用C++程序對參數不太理解,查了資料需要學習這個機制)

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

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

    . Non-table I/O

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

    1. kaldi文件默認是2進制的,如果flag –binary=false輸出則是非2進制

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

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

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

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

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

    例如 echo '[ 0 1 ]' | copy-matrix --binary=false - - 其中 | 代表管道把輸出變為下面的輸入

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

    二. Table I/O

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

    ?

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

    ?

    "rspecifier" 程序從表中讀,告訴我們如何讀一個索引的數據

    "wspecifier"程序把數據寫入表中

    rspecifiers的共同的類型是"ark:-", 從標準輸入中作為一個archive讀取數據,或是"scp:foo.scp",代表從script文件foo.scp讀取數據

    ?

    • 對于 rspecifiers的 ark,s,cs:- 代表我們從標準輸入讀已經排序的keys (,s) 我們認為他們將按順序被讀取, (,cs)意味著我們知道程序將 按順序訪問他們(如果條件不滿足,程序將會崩潰),好處就是可以隨機訪問而不會浪費大量的內存。

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

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

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

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


    ?

    附錄3 Kaldi常用工具

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

    kaldi官網工具大全http://kaldi-asr.org/doc/tools.html


    ?

    附錄4 FSTFinite State Transducer)總結:

    一般使用的是WFSTWeightd Finite 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)

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

    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 加權接收器

    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.

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


    ?


    ?

    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.

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


    ?


    ?

    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.

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


    ?


    ?

    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結構的音素,這個標簽沿著一個完整路徑指定音素的發音分布的合法字符串。

    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.

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

    2.2. Weighted Transducers 加權轉換器

    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

    我們不用接收器而用有限狀態轉換器表示在自動語音識別(ASR)遇到的n-gram 語法,發音詞典,上下文依賴規范,HMM拓撲結構,詞,音素或者HMM分段(HMM segmentations),點陣和n-best輸出列表。這個轉換器代表對于組合模型和優化他們提供一般的方法,主導了簡單而又靈活的ASR解碼器的設計。

    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.

    加權有限狀態轉換器和加權接收器特別的相似,就是多了一個輸入標簽,輸出標簽和每個轉換的權重。

    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。通過給每個轉換相同的輸入輸出標簽使得圖2(a)和圖1(a)表示相同的語言模型。雖然沒有增加新信息,但是這給了我們使用處理接收器和轉換器一致性的便利方法。

    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)表示一個作為一個在詞典中從音素串到詞的映射的簡單的發音詞典,在這個例子中data和dew,用概率表示選擇發音的最大死然度。沿著從開始狀態到終止狀態的一個特殊權重的詞串能夠讀取出來轉換的一個音素串。與一個發音一致的詞是通過這個轉換消耗第一個發音的音素的輸出。這個轉換消耗剩余音素不會有更多符號輸出,表示通過null符號#作為轉換的結果符號。一般來說,一個 ε符號標記了一個轉換沒有消耗輸入,一個 ε符號的輸出標簽標記的一個轉換不會產生輸出。


    ?


    ?


    ?


    ?

    圖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.

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

    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.

    優勢是轉換器能夠保存兩個表示級別的相對關系,例如音素和詞之間或者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.

    準確的說,一個轉換器指定字符串之間的二元關系:當有一個在轉換器從一個初始到終止狀態的路徑,第一個字符串作為這條路經輸入標簽順序和第二個字符串作為這條路經的輸出標簽順序。一般來說,這是一個關系而不是一個函數,因為相同的輸入字符串可能沿著兩條不同路徑被轉換成不同的字符串。對于權重轉換器每隊字符串都與權重相關聯。

    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.

    用這個加權轉換器的操作去組合,優化,查找,修剪。每個操作實現一個單一的,明確定義的函數,這個函數已經在有理冪級數數學理論中建立起來。許多操作都是對非加權接收器的經典算法進行加權轉換概括處理。

    2.3. Composition 應該是進行模型組合運算

    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.

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

    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.

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


    ?

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

    不能寫出有限個互不相交的開區間的并,不是半環。

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


    ?


    ?


    ?


    ?


    ?


    ?


    ?


    ?


    ?


    ?


    ?


    ?

    總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。