Kaldi 中CMVN處理過程

2021-10-02 00:27:22 字數 3308 閱讀 9165

author: xin pan

date: 2020.01.03

因為一直好奇cmvn(cepstral mean and variance normalization,倒譜均值方差歸一化)是怎麼處理的,正好在伺服器安上了gdb就跟著單步除錯了一下。

先看下kaldi官網對於cmvn的解釋,以下內容來自compute-cmvn-stats這個工具的usage

如果你做了逐句的cmvn就沒必要做逐說話人的fmllr(因為你將會在不同的offset上做fmllr)。因此這個情況下的說話人資訊怎麼用呢?這個情況下你就應該讓說話人的id(speaker-ids)等於語句id(utterance-ids)。說話人的資訊不用等於真正說話的人的數量,這個就是你想要適應的層次。

這次實驗的時候我是用aishell 1 的train set 進行的。使用的完整命令如下:

compute-cmvn-stats --spk2utt=ark:data/train/spk2utt scp:data/train/feats.scp ark,scp:/home/panxin/kaldi/egs/aishell/s5/mfcc/cmvn_train.ark,/home/panxin/kaldi/egs/aishell/s5/mfcc/cmvn_train.scp
這次的train特徵是16維的mfcc。

feat-to-dim scp:data/train/feats.scp - 

16

假設我的spk2utt檔案是這樣的

s0002 bac009s0002w0122 bac009s0002w0123 bac009s0002w0124
feats.scp是這樣的

bac009s0002w0122 mfcc_noise/raw_mfcc_pitch_train.1.ark:17

bac009s0002w0123 mfcc_noise/raw_mfcc_pitch_train.1.ark:9751

bac009s0002w0124 mfcc_noise/raw_mfcc_pitch_train.1.ark:16077

那現在我們進入compute-cmvn-stats.cc的main去看一看,其中對源**有部分刪減

int

main

(int argc,

char

*ar**)

const matrix

&feats = feat_reader.

value

(utt)

;//feats儲存的是 utt這個音訊的特徵值,實實在在的值if(

!is_init)if(

!(utt, feats,

&weights_reader,

&stats)

)else}if

(stats.

numrows()

==0)else}}

else

writer.

write

(feat_reader.

key(

), stats)

; num_done++;}

}}elseif(

!(utt, feats,

&weights_reader,

&stats)

)else

} matrix<

float

>

stats_float

(stats)

;writekaldiobject

(stats_float, wxfilename, binary)

; kaldi_log <<

"wrote global cmvn stats to "

<<

printablewxfilename

(wxfilename);}

kaldi_log <<

"done accumulating cmvn stats for "

<< num_done

<<

" utterances; "

<< num_err <<

" had errors."

;return

(num_done !=0?

0:1)

;}catch

(const std::exception &e)

}

bool

(std::string utt,

const matrixbase

&feats,

randomaccessbasefloatvectorreader *weights_reader,

matrix<

double

>

*cmvn_stats)

else

const vector

&weights = weights_reader-

>

value

(utt);if

(weights.

dim(

)!= feats.

numrows()

)acccmvnstats

(feats,

&weights, cmvn_stats)

;return

true;}

}

在$kaldi_home/src/transform/cmvn.cc中定義了initcmvnstats以及acccmvnstats這兩個函式

void

initcmvnstats

(int32 dim, matrix<

double

>

*stats)

void

acccmvnstats

(const vectorbase

&feats, basefloat weight, matrixbase<

double

>

*stats)

}void

acccmvnstats

(const matrixbase

&feats,

const vectorbase

*weights,

matrixbase<

double

>

*stats)

for(int32 i =

0; i < num_frames; i++

)}

Hadoop中mapReduce處理過程詳解

為了說明這個問題,我們使用wordcount的處理過程來進行演示,演示圖如下所示 分析上圖 1.輸入分片 input split 在進行map計算之前,mapreduce會根據輸入檔案計算輸入分片 input split 每個輸入分片 input split 針對乙個map任務,輸入分片 input...

spring mvc 中 請求處理過程

spring mvc 中 請求處理過程 url初始化過程 override public void dowith method method throws illegalargumentexception,illegalacces ception reflectionutils.user decla...

USB host處理過程

在usbh core.c中有乙個函式usbh process 這個函式很重要,main 函式每迴圈一次,它就執行一次,它處理所有usb核心狀態的變化,typedef enum host state 根據這個當前狀態 phost gstate 處於以上哪個狀態的不同,做出不同的處理過程。其中最重要的要...