上篇(飛槳paddlespeech 語(yǔ)音喚醒初探)初探了paddlespeech下的語(yǔ)音喚醒方案,通過(guò)調(diào)試也搞清楚了里面的細(xì)節(jié)。因?yàn)槭莗ython 下的,不能直接部署,要想在嵌入式上部署需要有C下的推理實(shí)現(xiàn),于是我就在C下把這個(gè)方案的部署實(shí)現(xiàn)了。需要說(shuō)明的是目前完成的是浮點(diǎn)實(shí)現(xiàn),真正部署時(shí)要用的是定點(diǎn)實(shí)現(xiàn),后面要做的是從浮點(diǎn)到定點(diǎn)的轉(zhuǎn)換。浮點(diǎn)實(shí)現(xiàn)也做了兩個(gè)版本。一是跟python下的實(shí)現(xiàn)完全一致的版本,做這個(gè)版本的目的是方便與python版本的結(jié)果比較,確保每個(gè)模塊的實(shí)現(xiàn)完全正確。二是將模型中的卷積層和對(duì)應(yīng)的batchNormal(BN)層合并為一個(gè)卷積層的版本,將卷積層和對(duì)應(yīng)的BN層合并為一個(gè)卷積層一是可以減少參數(shù)的個(gè)數(shù),二是可以減少運(yùn)算量(BN里有求方差等運(yùn)算)。做定點(diǎn)化時(shí)也是要基于這個(gè)版本來(lái)做的。下面就講講我是怎么做C下的實(shí)現(xiàn)的。
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-417160.html
語(yǔ)音喚醒的推理過(guò)程如下圖所示:
從上圖可以看出主要分兩步,一是做特征提取,二是做模型推理。將提取出來(lái)的特征值作為模型的輸入,推理后得到模型的輸出,從而給出是否是關(guān)鍵詞的結(jié)果。
?
1,? 特征提取
特征提取的步驟如下圖所示:
做這一步時(shí)主要基于兩份開(kāi)源的代碼: FFT 和 MFCC。Fbank是MFCC的一部分,因此需要對(duì)代碼進(jìn)行裁剪。做時(shí)從分幀開(kāi)始到得到特征值,每一步處理都要跟python下的保持完全一致,如分幀時(shí)用的是什么窗,用的是能量譜還是對(duì)數(shù)譜等。調(diào)試時(shí)基于一個(gè)具體的WAV文件來(lái)調(diào)。每一步執(zhí)行后python下有一個(gè)輸出,在C下也有一個(gè)輸出,要確保這兩個(gè)輸出在誤差允許范圍內(nèi)保持一致,否則就是C的實(shí)現(xiàn)有問(wèn)題。經(jīng)過(guò)調(diào)試后特征提取部分就完成了,python下的結(jié)果和C下的結(jié)果保持小數(shù)點(diǎn)后面前四位相同,誤差還是非常小的。
?
2,? 模型推理
模型推理可以分為如下幾個(gè)步驟:在Python下獲取模型參數(shù)并保存進(jìn)文件給C實(shí)現(xiàn)用,跟python完全一致的浮點(diǎn)實(shí)現(xiàn),將卷積層和對(duì)應(yīng)的BN層合并為一個(gè)卷積層的浮點(diǎn)實(shí)現(xiàn)。
2.1 模型參數(shù)獲取
在paddlespeech下先用API獲取每層的參數(shù),代碼大致如下:
然后將每層的參數(shù)按事先規(guī)定的格式保存在一個(gè)文件里,供C實(shí)現(xiàn)去解析參數(shù)。我用的參數(shù)保存格式如下:
即參數(shù)一層一層的放。在每一層里,先是層名,然后是weight參數(shù)的個(gè)數(shù)和bias參數(shù)的個(gè)數(shù),最后是weight和bias具體的參數(shù)值。在C中就根據(jù)這個(gè)規(guī)則去解析從而得到每一層的參數(shù)。
2.2 跟python推理完全一致的浮點(diǎn)實(shí)現(xiàn)
模型的框圖如下:
主要有PreProcess/DTCNStack等模塊。先實(shí)現(xiàn)模型用到的神經(jīng)網(wǎng)絡(luò)里的基本單元,有depthwise_conv1d/pointwise_conv1d/relu/batch_normal/sigmoid等。再將這些基本單元組成pre_process模塊來(lái)調(diào)試。依舊是用調(diào)試特征提取時(shí)的方法來(lái)調(diào),確保每一步的輸出跟python下的在誤差允許范圍內(nèi)保持一致。PreProcess模塊調(diào)好后再來(lái)調(diào)DTCNStack等模塊,最終形成一個(gè)完整的推理實(shí)現(xiàn)。下圖給出了我調(diào)試時(shí)用的wav的最終每幀的在python下和C下的后驗(yàn)概率(有多個(gè)值,限于長(zhǎng)度,這里只截取了部分),可以看出python下和C下的結(jié)果是保持一致的。
2.3將卷積層和對(duì)應(yīng)的BN層合并為一個(gè)卷積層的浮點(diǎn)實(shí)現(xiàn)
為了減少參數(shù)個(gè)數(shù)和運(yùn)算量,可以將將卷積層和對(duì)應(yīng)的BN層合并為一個(gè)卷積層。具體原理如下:
對(duì)于C實(shí)現(xiàn)來(lái)說(shuō),只要把banch_normal()函數(shù)去掉就可以了。但是在保存參數(shù)時(shí)卷積層的參數(shù)要根據(jù)上面的公式做個(gè)換算,同時(shí)把BN層的去掉。下圖是做最后linear以及后驗(yàn)概率運(yùn)算時(shí)有沒(méi)有BN層的結(jié)果(有多個(gè)值,限于長(zhǎng)度,這里只截取了部分)。
從上兩圖看出將卷積層和BN層合并為一層對(duì)最終結(jié)果的影響是非常小的,但是省掉了2.5K的參數(shù)以及原先BN層要做的運(yùn)算量。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-417160.html
?
到了這里,關(guān)于飛槳paddlespeech語(yǔ)音喚醒推理C實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!