官术网_书友最值得收藏!

2.4 一個(gè)簡單的示例

本節(jié)將展示一個(gè)語音識別的示例:YesNo。這個(gè)示例的功能很有限,只能識別Yes和No兩個(gè)單詞。示例雖然簡單,卻“麻雀雖小,五臟俱全”。讀者通過學(xué)習(xí)這個(gè)示例,可以了解創(chuàng)建語音識別系統(tǒng)的基本流程。當(dāng)理解了這個(gè)示例后,讀者將會(huì)發(fā)現(xiàn),自己借助Kaldi也能夠搭建一個(gè)簡單的語音識別系統(tǒng)。

2.4.1 運(yùn)行run.sh

這個(gè)示例無需修改就可以直接運(yùn)行,包括數(shù)據(jù)的下載和整理、模型的訓(xùn)練、識別率的測試。所有腳本都在目錄egs/yesno下。

首先我們來看一下這個(gè)目錄的結(jié)構(gòu):

可以看到,這個(gè)示例由若干Shell腳本、Perl腳本和一些文本文件構(gòu)成。看到這么多文件,讀者可能會(huì)不知從何入手。其實(shí),Kaldi的所有示例,無論由多少個(gè)文件構(gòu)成,都是以run.sh為入口的。各示例中的其他腳本和可執(zhí)行程序,都是被run.sh直接或間接調(diào)用的。所以,直接執(zhí)行run.sh就可以運(yùn)行這個(gè)示例了。

我們暫且不理會(huì)這個(gè)示例背后的原理,先看看執(zhí)行結(jié)果。如果Kaldi被正確安裝,那么運(yùn)行run.sh后,屏幕上首先輸出的信息是:

上面的信息很容易理解,腳本從OpenSLR網(wǎng)站下載了一個(gè)名為waves_yesno.tar.gz的壓縮包,這個(gè)壓縮包就是這個(gè)示例所用的音頻數(shù)據(jù)。

OpenSLR是Kaldi社區(qū)建立的一個(gè)用于存儲(chǔ)語音和語言資源的網(wǎng)站,網(wǎng)站上提供了大量英語、漢語、西班牙語等語料,可以免費(fèi)下載,可用于訓(xùn)練語音識別、語音合成、說話人識別等模型。

接下來屏幕顯示了許多信息,這些信息對于不熟悉語音識別的讀者來說很難理解。讀者如果看不懂這些信息,可以暫時(shí)不用理會(huì)。

這個(gè)示例的數(shù)據(jù)集規(guī)模非常小,在普通硬件配置的計(jì)算機(jī)上,大約一兩分鐘,整個(gè)腳本就運(yùn)行完畢了。

輸出信息的最后一行是:

這就是測試結(jié)果了:WER為0.00。也就是說,總共測試了232個(gè)詞,全部識別正確。

2.4.2 腳本解析

本節(jié)將解析剛才運(yùn)行過的run.sh,幫助讀者理解這個(gè)腳本所做的事情。

1)腳本的前兩行設(shè)置了train_cmd和decode_cmd兩個(gè)變量:

這兩個(gè)變量在后面會(huì)用到,比如后面的:

以及

Kaldi的很多腳本,比如這個(gè)示例中要用到的steps/train_mono.sh和steps/decode.sh,都允許設(shè)置cmd參數(shù)。在本例中,cmd參數(shù)被設(shè)置成了utils/run.pl。

utils/run.pl這個(gè)Perl腳本的作用是多任務(wù)地執(zhí)行某個(gè)程序。這是一個(gè)非常方便的工具,是可以獨(dú)立于Kaldi之外使用的。這里用一個(gè)示例展示其用法:

上面的命令同時(shí)執(zhí)行了8個(gè)echo命令,并把屏幕顯示輸出分別寫入/tmp/log.[1-8].txt這8個(gè)文本文件中。我們打開其中一個(gè)文件看一下:

可以看到,各個(gè)進(jìn)程被分別執(zhí)行,并將輸出信息寫入了不同的日志文件中。

Kaldi工具包中提供了utils/run.pl、utils/queue.pl和utils/slurm.pl作為cmd的可選工具,它們的命令行接口相同,任務(wù)所需的內(nèi)存大小等選項(xiàng)也相同,不同之處在于run.pl在本地并行地執(zhí)行命令,而queue.pl和slurm.pl把命令提交到計(jì)算集群上執(zhí)行。

執(zhí)行任務(wù)分發(fā)的Perl腳本名及其選項(xiàng)拼接在一起,作為cmd參數(shù)傳入Kaldi的腳本中,然后Kaldi腳本使用cmd參數(shù)傳入的Perl腳本來并行地執(zhí)行程序。如果需要,讀者也可以編寫自己的任務(wù)分發(fā)腳本作為cmd的參數(shù)。

2)設(shè)置cmd參數(shù)后,腳本從OpenSLR網(wǎng)站下載數(shù)據(jù)并解壓。

waves_yesno.tar.gz壓縮包被解壓后,除一個(gè)README文件外,就是很多WAV文件了。通常來說,用于訓(xùn)練語音識別模型的數(shù)據(jù),除音頻外,還需要有音頻對應(yīng)的文本。這個(gè)數(shù)據(jù)集由于情況簡單,只包含YES和NO兩個(gè)單詞,因此這個(gè)數(shù)據(jù)集的提供者直接把文本標(biāo)注寫到了文件名中,用1代表YES,用0代表NO。比如,1_0_1_0_1_0_0_1.wav這個(gè)文件,其對應(yīng)的文本就是:

接下來,需要對數(shù)據(jù)進(jìn)行整理。數(shù)據(jù)整理有兩個(gè)目的,其一是把數(shù)據(jù)規(guī)范成Kaldi規(guī)定的數(shù)據(jù)文件夾格式,其二是劃分訓(xùn)練集和測試集。run.sh中整理數(shù)據(jù)的腳本是:

執(zhí)行這行腳本后,將生成data/train_yesno目錄和data/test_yesno目錄,分別作為這個(gè)示例的訓(xùn)練集和測試集。兩個(gè)目錄的結(jié)構(gòu)完全相同:

生成的這兩個(gè)目錄使用的是Kaldi的標(biāo)準(zhǔn)數(shù)據(jù)文件夾格式,我們查看一下這些文件的前幾行:

每個(gè)句子都被指定了一個(gè)唯一的ID。wav.scp文件記錄每個(gè)ID的音頻文件路徑,text文件記錄每個(gè)ID的文本內(nèi)容,spk2utt文件和utt2spk文件記錄每個(gè)ID的說話人信息,本例中統(tǒng)一為global。

3)除下載數(shù)據(jù)外,還有一些資源需要手動(dòng)準(zhǔn)備。在這個(gè)示例中,這些資源已經(jīng)由貢獻(xiàn)者準(zhǔn)備好了,在input路徑下。

首先是發(fā)音詞典lexicon.txt:

lexicon.txt文件給出了YES、NO和<SIL>這三個(gè)單詞的音素序列,其中<SIL>是一個(gè)特殊單詞,表示靜音。這里由于任務(wù)簡單,每個(gè)單詞都只用一個(gè)音素表示。lexicon_nosil.txt文件和lexicon.txt文件的內(nèi)容相同,只是去掉了<SIL>行。

phones.txt文件給出了這個(gè)示例的音素集:

其實(shí)phones.txt文件也可以從lexicon.txt文件中將所有音素去重得到。

task.arpabo是語言模型。本例中的語言模型不必訓(xùn)練,直接手工書寫即可:

上面的語言模型定義了識別空間:只可能是Yes和No這兩個(gè)單詞,并且這兩個(gè)單詞出現(xiàn)的概率相同。關(guān)于語言模型的知識將在本書第5章中詳細(xì)介紹。

4)數(shù)據(jù)文件夾生成后,就可以根據(jù)其中的文本信息,以及事先準(zhǔn)備好的發(fā)音詞典等文件,生成語言文件夾了。腳本如下:

前兩行腳本讀取input的資源文件,生成data/lang目錄。這個(gè)目錄是Kaldi標(biāo)準(zhǔn)的語言文件夾,存儲(chǔ)了待識別語言的單詞集、音素集等信息。第三行腳本把語言模型構(gòu)建成圖的形式,其細(xì)節(jié)將在本書第5章中介紹。

5)接下來是定義聲學(xué)特征,這是訓(xùn)練聲學(xué)模型的前提,腳本如下:

腳本執(zhí)行完畢后,train_yesno目錄和test_yesno目錄下將分別生成feats.scp文件,里面記錄了每個(gè)ID的聲學(xué)特征存儲(chǔ)位置。

6)下面是聲學(xué)模型訓(xùn)練和測試階段。由于這個(gè)示例的任務(wù)比較簡單,因此只需訓(xùn)練最簡單的聲學(xué)模型,腳本如下:

腳本執(zhí)行完畢后,聲學(xué)模型被存儲(chǔ)在exp/mono0a目錄下。至此,模型訓(xùn)練完畢,進(jìn)入測試識別階段。識別的過程也被稱作解碼,解碼前需要構(gòu)建狀態(tài)圖:

本書將在第5章中詳細(xì)講解為何需要構(gòu)建狀態(tài)圖及構(gòu)建狀態(tài)圖的原理。構(gòu)建狀態(tài)圖完畢后,調(diào)用Kaldi的解碼器解碼:

現(xiàn)在識別結(jié)果已經(jīng)輸出到exp/mono0a/decode_test_yes下面了。我們看一下識別結(jié)果:

這里我們只查看了exp/mono0a/decode_test_yes下的scoring_kaldi/penalty_0.0/10.txt文件。實(shí)際上,這個(gè)腳本輸出了很多類似的識別結(jié)果文件,這些文件的區(qū)別是使用了不同的解碼參數(shù),其WER有微小的差異。

run.sh運(yùn)行的最后,是尋找最好的解碼器調(diào)參結(jié)果并輸出:

最終找到了最好的結(jié)果:scoring_kaldi/penalty_0.0/7.txt,WER為0.0%。

以上是對YesNo這個(gè)示例較頂層的介紹。YesNo示例是一個(gè)很好的用來入門的示例,但其聲學(xué)模型訓(xùn)練過于簡單,只訓(xùn)練了單音素的GMM模型,同時(shí)這個(gè)示例的發(fā)音詞典的設(shè)置也不具備一般性。

從第3章起,本書主要使用Librispeech作為示例,這個(gè)示例是一個(gè)通用英文識別任務(wù),使用近千小時(shí)的訓(xùn)練數(shù)據(jù),是一個(gè)可以真正使用的語音識別系統(tǒng)。第3章~第6章將通過Librispeech示例,詳細(xì)地介紹語音識別系統(tǒng)的模型訓(xùn)練及解碼的流程與原理。有了YesNo示例作為基礎(chǔ),相信讀者能夠更容易地理解其他更復(fù)雜的示例流程及其背后的原理。

主站蜘蛛池模板: 嘉义市| 宁明县| 林口县| 贵阳市| 榆树市| 当涂县| 吉水县| 永顺县| 新宁县| 瑞金市| 潢川县| 遂平县| 进贤县| 阿荣旗| 聂拉木县| 乌兰县| 柯坪县| 大新县| 双牌县| 清水河县| 泾源县| 潍坊市| 东城区| 江北区| 霍山县| 墨竹工卡县| 浠水县| 宜川县| 兴宁市| 共和县| 海门市| 石门县| 荔波县| 新兴县| 察隅县| 二手房| 嘉善县| 兖州市| 南澳县| 八宿县| 福贡县|