Kaldi(一)
Kaldi
Kaldi是一個(gè)語音識(shí)別的工具包。它由Daniel Povey于2009年創(chuàng)建。
Daniel Povey,Johns Hopkins University副教授。
個(gè)人主頁:
http://danielpovey.com/
官網(wǎng):
https://github.com/kaldi-asr/kaldi
文檔:
http://kaldi-asr.org/doc/
此外,Daniel的主頁上也有一些教程:
http://danielpovey.com/kaldi-lectures.html
數(shù)據(jù):
http://www.openslr.org/
這是Daniel Povey為了Kaldi中的示例所創(chuàng)建的資源網(wǎng)站。它還有個(gè)國內(nèi)的鏡像:
http://cn-mirror.openslr.org/
參考:
https://www.eleanorchodroff.com/tutorial/kaldi/kaldi-intro.html
這是Eleanor Chodroff寫的kaldi指南。
Eleanor Chodroff,New York University本科(2012)+Johns Hopkins University碩博(2014,2017)。現(xiàn)為Northwestern University博士后。
https://blog.csdn.net/wbgxx333
一個(gè)語音識(shí)別+Kaldi的blog。這個(gè)博主還寫了一個(gè)《kaldi資料歸納和總結(jié)》的文章,可加入博主的QQ群,在群文件中獲得。
http://jrmeyer.github.io/asr/2016/12/15/DNN-AM-Kaldi.html
How to Train a Deep Neural Net Acoustic Model with Kaldi
編譯
1.檢查依賴。
cd tools extras/check_dependencies.sh根據(jù)提示,缺什么就裝什么。
2.編譯tools文件夾
make -j 4
3.編譯src文件夾
cd ../src sudo apt install libatlas-base-dev ./configure --shared make depend -j 4 make -j 4運(yùn)行示例
示例放在egs文件夾下,目前已經(jīng)有很多示例了。這里以thchs30為例進(jìn)行介紹。這里主要參考了下文:
https://blog.csdn.net/shichaog/article/details/73655628
kaldi在線中文識(shí)別系統(tǒng)搭建
thchs30下有個(gè)s5文件夾。Daniel教程中提到,在原來的老示例中還有s1、s2這樣的文件夾,因此這個(gè)5姑且可以看成版本號(hào)吧。
**Kaldi只是一個(gè)工具包,而非框架。**因此,它并不能直接運(yùn)行,而只能被別人調(diào)用。
在示例中,一般是通過run.sh對(duì)Kaldi的功能進(jìn)行調(diào)用。
1.下載數(shù)據(jù)
http://cn-mirror.openslr.org/18/
2.修改cmd.sh。
export train_cmd=run.pl export decode_cmd="run.pl --mem 4G" export mkgraph_cmd="run.pl --mem 8G" export cuda_cmd="run.pl --gpu 1" #export train_cmd=queue.pl #export decode_cmd="queue.pl --mem 4G" #export mkgraph_cmd="queue.pl --mem 8G" #export cuda_cmd="queue.pl --gpu 1"3.修改run.sh中的數(shù)據(jù)路徑,并運(yùn)行之。
不成功的探險(xiǎn)
上文中被替換的queue.pl實(shí)際上是run.pl的分布式計(jì)算版本,用到了SLURM等技術(shù)。
sudo apt install slurm-wlm-torque slurm-wlm-doc
SLURM和Torque都是job scheduler。他們的官網(wǎng)分別是:
https://slurm.schedmd.com/
http://www.adaptivecomputing.com/products/open-source/torque/
3.在瀏覽器中運(yùn)行/usr/share/doc/slurm-wlm-doc/html/configurator.html以生成slurm.conf文件,然后把該文件保存到/etc/slurm-llnl下。
但是遺憾的是,由于我填的不對(duì),最終沒有走通這條路。
LLNL是Lawrence Livermore National Laboratory的簡(jiǎn)稱,它上面有幾篇文章不錯(cuò):
https://computing.llnl.gov/tutorials/parallel_comp/
Introduction to Parallel Computing
https://computing.llnl.gov/tutorials/linux_clusters/
Linux Clusters Overview
目錄結(jié)構(gòu)
kaldi的調(diào)用層次可分為三級(jí):
1.腳本。包括shell腳本和perl腳本。主要在egs/wsj文件夾下。
2.工具。一些可執(zhí)行文件。在src/XXXbin文件夾下。
3.算法實(shí)現(xiàn)。在src/XXX文件夾下。
工具和算法實(shí)現(xiàn)基本都是C/C++寫的。外部工具在tools文件夾下,主要是openfst、sctk、sph2pipe。
術(shù)語
LM:language model
KWS:Keyword Search
CMVN:cepstral mean and variance
G2P:Grapheme-to-Phoneme
WSJ:Wall Street Journal
OpenFst
OpenFst是一個(gè)構(gòu)造、合并、優(yōu)化和搜索加權(quán)有限狀態(tài)機(jī)FST的庫。
官網(wǎng):
http://www.openfst.org/
SCTK
Speech Recognition Scoring Toolkit是NIST(National Institute of Standards and Technology, 美國國家標(biāo)準(zhǔn)與技術(shù)協(xié)會(huì))提出的一套工具集。
官網(wǎng):
https://github.com/usnistgov/SCTK
以下網(wǎng)頁包含了SCTK支持的幾種數(shù)據(jù)格式:trn, txt, stm, ctm。這在Kaldi中用的比較多。
http://www1.icsi.berkeley.edu/Speech/docs/sctk-1.2/infmts.htm
sph2pipe
Kaldi里的音頻默認(rèn)是16k采樣率,16bits,單通道。如果是其他參數(shù),需要根據(jù)配置來修改。此外,kaldi數(shù)據(jù)處理部分還有個(gè)音量跟語速的腳本,這部分在kaldi里通過sox來實(shí)現(xiàn)的。
Kaldi里有很大一部分?jǐn)?shù)據(jù)是LDC的,比如timit,rm,wsj等。它們雖然是wave的格式,但其實(shí)不是真正的wav格式,其實(shí)是nist的SPHERE格式,kaldi里通過sph2pipe這個(gè)來把格式轉(zhuǎn)成真正的wave格式。
如果有人要在windows下看這些音頻,可以在linux下通過sph2pipe轉(zhuǎn)換下,或者有個(gè)叫voicebox的matlab程序里有個(gè)readsph的程序來轉(zhuǎn)下。
此外,kaldi里librispeech其實(shí)是FLAC格式,這是一個(gè)無損的格式,也需要通過flac命令來轉(zhuǎn)成wave來處理。
官網(wǎng):
https://www.ldc.upenn.edu/language-resources/tools/sphere-conversion-tools
SRILM
SRILM - The SRI Language Modeling Toolkit是由SRI International提出的一套工具集,主要用于創(chuàng)建和使用統(tǒng)計(jì)語言模型。
官網(wǎng):
http://www.speech.sri.com/projects/srilm/
SRI International是一家非營利的研究機(jī)構(gòu),創(chuàng)建于1946年。SRI是Stanford Research Institute的縮寫。
thchs30中的lm文件(例如lm_phone/phone.3gram.lm)就是由SRILM生成的。
參考:
http://www.52nlp.cn/language-model-training-tools-srilm-details
語言模型訓(xùn)練工具SRILM詳解
命令行粗解
kaldi的命令行腳本之所以不好讀,主要在于它有一套自己的語法。
head -1 $featdir/raw_mfcc_train.1.scp | copy-feats scp:- ark:- | copy-feats ark:- ark,t:- | head
上面是一個(gè)典型的kaldi腳本的片段。可以看出kaldi命令是一個(gè)典型的pipeline結(jié)構(gòu),用|作為命令間的分隔符,這和一般的Linux shell是一致的。比較讓人困惑的是scp和ark。
.ark(archive)是數(shù)據(jù)文件,可以是text或binary(默認(rèn))格式。
.scp(script)是描述文件,記錄對(duì)應(yīng)ark的路徑,它是text-only的格式的。
.scp相當(dāng)于C語言的指針,而.ark相當(dāng)于指針指向的內(nèi)容。
ark,t:-中的t是IO描述符,IO描述符分為讀和寫兩大類,t是讀描述符,表示text。
而-是文件描述符,-表示標(biāo)準(zhǔn)輸入輸出設(shè)備。它也可以是其他命令的輸出,例如:
ark:gunzip -c $srcdir/fsts.JOB.gz
thchs30之run.sh粗解
1.數(shù)據(jù)準(zhǔn)備。
最好是那種標(biāo)注了發(fā)音開始和結(jié)束時(shí)間的語料。但不幸的是,絕大多數(shù)開源語料都不滿足該條件,必須由算法搞定發(fā)音和標(biāo)簽的時(shí)間對(duì)齊問題。
如果要做聲紋識(shí)別的話,則語料中還必須有speaker ID。
2.訓(xùn)練monophone模型。
monophone是指那種不包含前后音節(jié)的上下文無關(guān)的音節(jié)模型。它也是后面構(gòu)建更復(fù)雜的上下文相關(guān)音節(jié)模型的基礎(chǔ)。
3.強(qiáng)制對(duì)齊(Forced Alignment)。
使用steps/align_si.sh。這里一般使用Viterbi training算法替代傳統(tǒng)的Baum-Welch算法。前者的計(jì)算效率更高,但精度不如后者。對(duì)齊操作可以有效提升標(biāo)簽和語音的吻合度,為后續(xù)訓(xùn)練提供便利。
論文:
《Comparative Study of the Baum-Welch and Viterbi Training Algorithms Applied to Read and Spontaneous Speech Recognition》
《Comparative Analysis of Viterbi Training and Maximum Likelihood Estimation for HMMs》
4.用上一步的結(jié)果,訓(xùn)練tri1模型(三因素訓(xùn)練)。
這一步很關(guān)鍵,整個(gè)thchs30的訓(xùn)練流程,都是用粗糙模型,訓(xùn)練更精細(xì)的模型。
5.訓(xùn)練tri2模型(LDA-MLLT特征變換)。
6.訓(xùn)練tri3模型(Speaker Adapted Training,SAT)。主要用到了fMLLR算法。這一步之后的強(qiáng)制對(duì)齊使用steps/align_fmllr.sh。
7.訓(xùn)練tri4模型。這一步不再有feature-space的變換,而是對(duì)之前特征的綜合,比如使用GMM算法。
8.訓(xùn)練DNN模型。
9.被噪聲干擾的語音可以使用基于深度自動(dòng)編碼器(DAE)的噪聲消除方法。這一步是可選的。
參考:
https://blog.csdn.net/Anymake_ren/article/details/52275412
kaldi中文語音識(shí)別thchs30模型訓(xùn)練代碼功能和配置參數(shù)解讀
https://blog.csdn.net/snowdroptulip/article/details/78943748
運(yùn)行thchs30
數(shù)據(jù)格式
text
utt_id WORD1 WORD2 WORD3 WORD4 ...
110236_20091006_82330_F_0001 I'M WORRIED ABOUT THAT 110236_20091006_82330_F_0002 AT LEAST NOW WE HAVE THE BENEFIT 110236_20091006_82330_F_0003 DID YOU EVER GO ON STRIKEsegments
utt_id file_id start_time end_time
110236_20091006_82330_F_001 110236_20091006_82330_F 0.0 3.44 110236_20091006_82330_F_002 110236_20091006_82330_F 4.60 8.54 110236_20091006_82330_F_003 110236_20091006_82330_F 9.45 12.05 110236_20091006_82330_F_004 110236_20091006_82330_F 13.29 16.13wav.scp
file_id path/file
110236_20091006_82330_F path/110236_20091006_82330_F.wav 111138_20091215_82636_F path/111138_20091215_82636_F.wav 111138_20091217_82636_F path/111138_20091217_82636_F.wavutt2spk
utt_id spkr_id
110236_20091006_82330_F_0001 110236 110236_20091006_82330_F_0002 110236 110236_20091006_82330_F_0003 110236spk2utt
spkr_id utt_id1 utt_id2 utt_id3
lexicon.txt
lexicon.txt就是發(fā)聲詞典。
WORD W ER D LEXICON L EH K S IH K AH NARPA文件格式
SRILM生成的lm文件是ARPA文件格式。
\data\ ngram 1=64000 ngram 2=522530 ngram 3=173445\1-grams: -5.24036 'cause -0.2084827 -4.675221 'em -0.221857 -4.989297 'n -0.05809768 -5.365303 'til -0.1855581這個(gè)文件的頭部比較好懂,不解釋。
1-grams部分中每一條包括了3項(xiàng),其中第二項(xiàng)顯然是條目文本本身。
第一項(xiàng)表示ngram的條件概率,即P(wordN∣word1,word2,…,wordN?1)P(word_N \mid word_1,word_2,\dots,word_{N-1})P(wordN?∣word1?,word2?,…,wordN?1?)。
第三項(xiàng)表示回退(backoff)概率。
下面我們舉例說明條件概率和回退概率的用法。
假設(shè)arpa的最高元是3元,則句子ABCDEF發(fā)生的概率為:
P(ABCDEF)=P(A)?P(B∣A)?P(C∣AB)?P(D∣BC)?P(E∣CD)?(F∣DE)P(ABCDEF)=P(A)*P(B\mid A)*P(C\mid AB)*P(D\mid BC)*P(E\mid CD)*(F\mid DE)P(ABCDEF)=P(A)?P(B∣A)?P(C∣AB)?P(D∣BC)?P(E∣CD)?(F∣DE)
其中,P(A)通過訪問arpa中的1-grams項(xiàng)獲得,P(B∣A)P(B\mid A)P(B∣A)通過訪問2-grams項(xiàng)獲得,其他的概率通過訪問3-grams項(xiàng)獲得。
P(A)的計(jì)算直接找對(duì)應(yīng)A的文法項(xiàng)獲得概率即可。如果2-grams中存在“A B”項(xiàng),P(B∣A)P(B\mid A)P(B∣A)的概率也很容易獲得,但是如果“A B”詞組在2-grams中不存在,我們就需要利用回退概率計(jì)算P(B∣A)P(B\mid A)P(B∣A),計(jì)算公式為P(B∣A)=α(A)?P(B)P(B\mid A)=\alpha(A)*P(B)P(B∣A)=α(A)?P(B),其中的α(A)\alpha(A)α(A)就表示A的回退概率。
總結(jié)
- 上一篇: 数学狂想曲(十)——复变函数, 平稳离散
- 下一篇: Machine Learning之Pyt