Kaldi 介紹
Kaldi 是由 C++ 編寫的語音識別工具,其目的在於為語音識別研究者提供一個研究和使用的平台。
Kaldi 環境搭建
本文主要通過使用 Docker 和 Nvidia-docker 構建 Ubuntu 環境對 Kaldi 進行搭建。Docker 針對的是無 GPU 的環境,Nvidia-docker 針對的是需要使用 GPU 計算的環境,如果讀者機器上存在 GPU 計算資源,請使用 Nvidia-docker,使用 Nvidia 官方提供的 CUDA 鏡像,可以省去安裝 CUDA 的麻煩。Kaldi 的環境搭建分為兩部分,一部分為依賴工具安裝,另一部分為自身源碼編譯。
Docker 基礎命令
本節簡單介紹在安裝 Kaldi 過程中使用到的 Docker 基礎命令,如讀者需要更加詳細的學習 Docker ,請主動尋找相應的專業書籍、文檔學習。
本章中所用到的 Docker 命令如下:
docker pull 從 Docker Hub 中拉取鏡像
docker images 查看系統中所有 Docker 鏡像
docker run 運行 Docker 鏡像
docker exec 登陸已經運行的 Docker 鏡像 docker commit 在原有鏡像基礎上創建新鏡像 docker ps 查看鏡像是否運行
注意: 如果讀者需要使用 GPU 來進行計算,需要安裝 Nvidia-docker , 該軟件的運行命令與 Docker 的運行命令一致。Docker 與 Nvidia-docker 的安裝過程這里不做介紹。
Kaldi 環境搭建
這里假設讀者電腦已經安裝 Docker 和 Nvidia-docker ,如果未安裝,請先安裝再進行如下操作。
首先通過 Docker 獲取相應的 Ubuntu 系統。
docker pull nvidia/cuda:9.0-base-ubuntu16.04
之后啟動該鏡像,並安裝相應軟件
nvidia-docker run -itd nvidia/cuda:9.0-base-ubuntu16.04 /bin/bash 啟動鏡像並保持后台運行
nvidia-docker ps 獲取該啟動鏡像的 Container ID
nvidia-docker exec -it <Container ID> /bin/bash 進入系統 apt-get update apt-get install git vim cd /opt && git clone https://github.com/kaldi-asr/kaldi.git && cd kaldi
接下來進行 Kaldi 的第一部分安裝,第一部分主要是針對 Kaldi 依賴工具的安裝比如 Openfst、Portaudio 等。安裝步驟如下:
cd tools && extras/check_dependencies.sh
apt-get install g++ zlib1g-dev make automake autoconf bzip2 unzip wget sox libtool subversion python2.7 python3 libatlas-dev libatlas-base-dev make extras/install_irstlm.sh
Kaldi 安裝的第二部分為源碼編譯部分,這里的首要條件是第一部分正常安裝之后,第二部分才能順利完成。安裝步驟如下:
cd /opt/kaldi/src ./configure --shared make depend -j 8 make -j 8
只有以上兩部順利安裝,Kaldi 的安裝才算成功。
最后讀者可以退出終端,使用命令:
docker commit <Container ID> kaldi:latest
來構建一個可以長時間使用的 Docker 鏡像,當然讀者也可以使用作者已經做好的 Dockerfile 文件來生成 Docker 鏡像,或者直接拉取作者已經做好的 Docker 鏡像。
Kaldi 目錄介紹
本節主要對 Kaldi 的目錄進行詳細介紹。
Kaldi 一級目錄
在 Kaldi 的一級主目錄中(也就是進入 kaldi 目錄之后大家所看到的所有目錄)包括:egs、misc、scripts、src、tools、windows。
- egs :此目錄為 Kaldi 例子目錄,其中例子包含了不乏語音識別、語種識別、聲紋識別、關鍵字識別等。
- misc : 此目錄包含了一些 pdf、以及相關 docker、htk 等資源
- scripts: 此目錄只用來存放 Rnnlm,以及相應的運行腳本。
- src : 此目錄為 Kaldi 的源代碼目錄,Kaldi 的多數算法的源代碼都存放於此,其中不乏GMM、Ivector、Nnet等一系列的算法。
- tools: 此目錄主要存放 Kaldi 依賴庫的安裝腳本
- windows: 此目錄為在 Windows 平台運行所必須的腳本以及相關的執行程序。
這里只是針對性的對 egs 和 src 目錄進行介紹,其他目錄讀者可以自行了解。
Kaldi 一級目錄 Egs
Egs 目錄主要用於存放 Kaldi 的所有例程,這里會統一羅列出相關文件所包含的相關例子。
- Aishell : 此目錄為中文語音識別和聲紋識別相關例子。
- Aishell2 : 此目錄主要為中文語音識別例子,但是針對 Aishell 在腳本方面更加規整。
- ami : 此目錄主要涉及到多信道語音識別的例子。
- an4 : 此例子為 CMU 提供語音識別例子,並沒有涉及神經網絡。
- apiai_decode: 此例子為解碼器使用的例子,其中包含了如何使用預訓練模型,這里主要針對的是 Nnet3 解碼。
- aspire: 此為ASpIRE 挑戰賽的例子,其中包含了怎樣使用噪聲數據構建多條件數據的例子。
- aurora4: 此例子主要介紹 RBM 預訓練。
- babel: 此例子主要是用來訓練 KWS (Key Word Search)。
- babel_multilang: 此例子為訓練多語音 KWS。
- bentham: 手寫筆識別的例子。
- bn_music_speech : 音樂與語音區分的例子。
- callhome_diarization : 說話人分割的例子。
- callhome_etyptian: 埃及語語音識別例子。
- chime1-5 : 主要針對 CHiME 競賽開放的例子。
- cigar : 圖像分類的例子。
- commonvoice: Mozilla Common Voice 語音識別的例子。
- csj : 日語 語音識別例子。
- dihard_2018 : DiHARD Speech Diarization CHALLENGE 的例子。
- fame : 富里西語語音識別和聲紋識別的例子。
- farsdat: 主要用來聲學語音研究和語音識別的例子。
- fisher_callhome_spanish : 使用 Callhome 預料進行語音識別的例子。
- fisher_english: 英文雙聲道 8000 Hz 對話電話語音數據集的語音識別例子。
- fisher_swbd: 包含 fisher 數據集以及 swbd 數據集的語音識別例子。
- gale_arabic: 阿拉伯語語音識別例子。
- gale_mandarin: 普通話語音識別例子。
- gp: 全球電話語音識別例子(多語種語音識別例子)。
- heroico: 西班牙語音識別例子。
- houst: 普通話電話語音識別例子。
- hub4_english : 英語新聞廣播語音識別例子。
- hub4_spanish: 西班牙新聞廣播語音識別例子。
- iam: IAM 手寫筆識別例子。
- iban: 語音識別例子。
- ifnenit: 阿拉伯語手寫筆識別例子。
- librispeech: 英語語音識別例子。
- lre/lre07 : 語種識別例子。
- madcat_ar : 手寫筆識別例子。
- madcat_zh: 中文手寫筆識別例子。
- mini_librispeech: 英語語音識別例子。
- mult_en: 英語 LVCSR 例子。
- pub: RNNLM 模型構建例子。
- reverb: REVERB 挑戰賽例子。
- rimes: 法語手寫筆識別例子。
- rm: 英語語音識別例子,包含了如何進行遷移學習。
- sitw: sitw 說話人識別挑戰賽的例子。
- sprakbanken: 丹麥語語音識別例子。
- sprakbanken_swe: 瑞典語語音識別例子。
- sre08/10/16: 說話人識別的例子。
- svhn: 圖像分類的例子。
- swahili: 班圖人語 語音識別例子。
- swab: 雙聲道對電話語音識別例子。
- tedium: 英語語音識別例子。
- thchs30: 普通話語音識別例子。
- tidigits: 基礎語音識別的例子。
- timit: 主要是 GMM/HMM 語音識別例子。
- tunisian_msa: 阿拉伯語音識別例子。
- uw3:OCR 識別例子。
- voxceleb: 說話人識別例子。
- vystadial_cz: 捷克語語音識別例子。
- voxforge: 基礎語音識別例子,以及對應的在線 demo 的例子。
- vystadial_en: 英文語音識別例子。
- wsj: wsj 英文語音識別例子。
- yesno: 獨立詞語音識別例子。
- yomdle_fa/korean/russian/tamil/zh: OCR 識別例子。
- zeroth_korean: 朝鮮語語音識別例子。
注意: 雖然 Egs 中存放了大量的例子,但由於某些外部原因並不是所有例子的數據都能免費獲得。
Kaldi 一級目錄 src
src 目錄為 Kaldi 的源碼目錄,主要保存了包括 GMM、HMM 等在內的大部分 Kaldi 語音項目源代碼。這里分別對相關算法目錄進行介紹。
在 src 目錄中,有兩類文件夾,一類是算法原目錄,一類為算法組合生成bin(可執行程序)目錄。
base: Kaldi 基礎目錄,主要包括與 Kaldi 項目相關的基礎宏定義、類型定義等。 bin: Kaldi 的基礎 bin 目錄,主要是包括基礎的執行程序。例如,查看 tree 信息、矩陣拷貝等基礎操作。 cudamatrix: Kaldi 矩陣計算相關 GPU 計算目錄 matrix : Kaldi 矩陣計算相關 CPU 計算目錄 itf: Kaldi 相關的 interface hmm : Kaldi 相關隱馬爾可夫算法的代碼目錄 utils: Kaldi 相關,語音算法無關的工具目錄,例如,線程操作、io操作、文本操作等。 probe: Kaldi 相關的 exp(指數) 測試目錄 transform: Kaldi 相關的特征轉換算法目錄 fstext: Kaldi 中 fst 相關的算法基礎目錄 fstbin: Kaldi 中 fst 對應的算法執行文件夾 feat: Kaldi 相關的特征提取算法目錄 featbin: Kaldi 相關的特征提取可執行目錄 gmm: Kaldi 相關的 GMM 算法基礎目錄 gmmbin: Kaldi 相關的 GMM 算法可執行文件目錄 ivector: Kaldi 相關的 ivector 算法基礎目錄 ivectorbin: Kaldi 相關的 ivector 算法的可執行目錄,以及基於能量的 vad 執行目錄。 kws: Kaldi 相關的關鍵字搜索基礎算法目錄 kwsbin: Kaldi 相關的關鍵字搜索執行目錄 lat: Kaldi 相關的網格生成基礎算法目錄 latbin: Kaldi 相關的網格生成算法的可執行文件目錄 lm: Kaldi 自帶的語言模型基礎算法目錄 lmbin: Kaldi 相關語音模型的可執行文件目錄 nnet: Kaldi 相關的 nnet1 基礎算法實現目錄 nnetbin: Kaldi nnet1相關的算法可執行文件目錄 nnet2: Kaldi nnet2 相關的基礎算法實現目錄 nnet2bin: Kaldi nnet2 相關的算法可執行文件目錄 nnet3: Kaldi nnet3 相關基礎算法實現目錄 nnet3bin: Kaldi nnet3 相關實現算法的可執行文件目錄 online: Kaldi online1 相關解碼算法的實現目錄 onlinebin: Kaldi online1 相關解碼器算法的可執行目錄 online2: Kaldi online2 相關解碼器算法的實現目錄 online2bin: Kaldi online2 相關解碼器算法的可執行目錄 rnnlm: Kaldi rnnlm 相關的語音模型基礎算法實現目錄 rnnlmbin: Kaldi rnnlm 相關的語音模型的可執行目錄 sgmm2: Kaldi sgmm2 相關的子空間 GMM 基礎算法實現目錄 sgmm2bin: Kaldi sgmm2 相關的子空間 GMM 基礎算法可執行目錄 tfrnnlm: Kaldi 相關的 Tensorflow rnnlm 基礎算法目錄 tfrnnlmbin: Kaldi 相關的 Tensorflow rnnlm 基礎算法實現的可執行目錄
Kaldi Egs Aishell 例子黑箱運行
本節的目的在於,讓讀者在不了解 Kaldi 語音識別相關的算法的情況下,能過順利運行 Aishell 的例子,並順利獲得語音識別模型。
首先需要有幾個注意點:
- 如果需要運行神經網絡相關的算法,確保機器擁有 GPU 運算能力。
- 確保以上 Kaldi 編譯成功。
- 如果網絡下載速度有限,請離線下載相關數據集。
- 確定運行代碼機器內存和硬盤大小。
本例子完全運行需要硬盤資源為 76G,所以需要確定硬盤是否有足夠的空間。
Aishell 例子運行
為了能過順利黑箱運行 Aishell 語音識別的例子。需要對 /opt/kaldi/egs/Aishell/s5 中的 run.sh 腳本進行幾點修改。
假設 Aishell 的語音數據已經全部下載,目錄存放於 /newdata/corpus/Aishell , 那么對應的 run.sh 腳本修改如下:
同時,由於我們的數據集已經下載,故需要注釋掉與 Aishell 數據相關的下載腳本,修改如下:
由於大家機器、內存和 CPU 數量的不同,在部分腳本相對應的運行進程上也要進行部分修改,這里需要大家根據自己實際機器情況。假設運行的機器為 16G 內存,run.sh 腳本修改為,vim 打開 run.sh ,進入命令模式:
:%s/--nj 10/--nj 5/g
同時,需要修改 local/nnet3/run_ivector_common.sh
該腳本中對應的 nj 個數,修改方法如上一步。
注意: 由於在運行神經網絡計算之前會進行 ivector 計算,因此需要根據運行機器的內存情況進行重新設置。這里建議:如果運行機器內存不到32G,在此例子中 ivector 的 nj 個數設置為 1,對應之上腳本的 118 行。
最后,需要注意,如果需要進行神經網絡相關訓練操作,需要對 local/chain/run_tdnn.sh
進行修改,修改操作為將 num_jobs_initial
和 num_jobs_final
統一修改成該訓練機器所對應的 GPU 個數。修改如下圖:
最后,回到 run.sh 的目錄中,使用命令:
nohup sh run.sh &
確保 run.sh 能夠在后台運行。直至出現錯誤或者運行成功自動結束。
運行結束之后,我們可以在 exp 目錄下的對應目錄下找到對應的錯誤率,以及識別結果。例如,使用 chain 來構建的神經網絡,目錄位置如下:
exp/chain/tdnn_1a_sp/
目錄中存放的解碼所需要的大部分信息。
如何在黑箱情況下,使用獨立語音進行模型模型構建
本節假設讀者已經成功運行上一節黑箱的例子,相信大家做語音識別的初衷亦或者興趣點在於如何使用自己的語音訓練模型,那么本節的主要目的就在於告訴大家如何在 Aishell 的基礎上,使用自己的語音構建模型。
學習本節,讀者依舊不需要了解任何的 Kaldi 語音識別相關內容。此時,讀者可能會有疑問,既然是黑箱,那如何能夠使用獨立語音訓練集訓練出自己的模型呢?
其實很簡單,我們這里有兩種方法提供給大家:
方法一: 我們只需要模仿 Aishell 的數據存放規律進行存放即可。
方法二: 如果我們現有的獨立數據集有自己的規律存放,那么只需要修改針對性的修改 run.sh 中的兩個腳本即可。
方法一這里不做詳細說明,大家根據上一節使用的 Aishell 的數據方式模仿存儲即可。這里針對方法二進行示范。
再次回到 run.sh 腳本中,我們可以發現,Aishell 的數據處理邏輯主要存在於兩個子腳本中。他們分別為如圖所示:
這兩個腳本即是我們需要修改的數據處理腳本。
首先看第一個腳本: local/Aishell_prepare_dict.sh
,此腳本的作用在於處理 Aishell 語音數據集所包含的發音字典信息。由於我們使用的是我們自己的獨立數據集合,因此,我們需要通過我們自己的獨立語音數據集獲取相對應的發音詞典。對應於 Aishell 數據集中的 lexicon.txt 文件。
第二步:修改local/Aishell_data_prep.sh
腳本。該腳本主要是用來讀取訓練數據集、驗證集以及測試集相對應的語音和語音相對應文本的對應關系。
由於第一步只需要進行匹配和人工標注,這里不多贅述。這里簡單說明一下第二部分如何修改。
假設我們的語音數據集的分布為如圖所示:
同時,我們可以通過 Aishell 的數據,看出數據存放格式如下圖所示:
那么,我們只需要將我們的數據集中 session 文件夾去除掉,亦或者修改腳本中如下圖所示的代碼即可:
只需要將 49 行的 NF-1 修改為 NF-2 即可。 這樣就可以順利運行我們自己的獨立語音數據集合。
總結
本章主要介紹了 Kaldi 相關的 Docker 基礎操作,並介紹了如何正確安裝 Kaldi 以及 Kaldi 相關的目錄結構,之后介紹了黑盒運行 Aishell 的例子,最后簡單介紹了如何修改腳本來運行自己的獨立語音數據集。
本文首發於 GitChat,未經授權不得轉載,轉載需與 GitChat 聯系。