kaldi nnet模型的decode流程解析


前言

前面的文章中讲过nnet3模型的线上解码流程,本文用的是nnet模型,又称nnet1,之前虽然讲过nnet3,但并没有对nnet系列模型进行说明,具体细节以后的文章中会讲到,简单概括一下就是,nnet1-3是目前kaldi中神经网络3个版本的实现,其中nnet1只能单GPU训练,而nnet2和nnet3支持多GPU并行训练。本文不用kaldi的online解码程序,唯一的区别就是线上解码的程序中集成了特征提取的部分,本文会基于中文语音数据集thchs30, 将特征提取这一部分剥离出来,并且更加细致深入地对解码脚本进行分析。


1、特征提取

1-1 filter bank特征计算

我们准备1个音频文件,采用40维的 filter bank 作为音频特征,如果打开 steps/make_fbank.sh这个脚本看一下的话(egs/thchs30/s5目录下), 会发现在kaldi中用的是 compute-fbank-feats 对filter bank特征值进行计算,程序如下所示:

cmvndir=data/cmvn
fbank_config=conf/fbank.conf
logdir=data/log
write_num_frames_opt="--write-num-frames=ark,t:$logdir/utt2num_frames"
write_utt2dur_opt="--write-utt2dur=ark,t:$logdir/utt2dur_opt"
compute-fbank-feats $write_utt2dur_opt --verbose=2 \
	--config=$fbank_config scp,p:data/wav.scp ark:- | \
	copy-feats $write_num_frames_opt ark:- ark,scp:data/raw_fbank.ark,data/raw_fbank.scp

我们将音频文件保存在 data/ 目录下并且命名为kaldiAudio.wav,对应的 wav.scp 文件就要写成:

kaldiAudio 绝对路径/data/kaldiAudio.wav

kaldi的处理脚本中是对音频文件按照utterance进行切片分割的(有助于提高精度),这里我们直接识别整个音频文件。fbank.conf中只设置了特征维度,–num-mel-bins=40,最后通过 copy-feats 程序将生成特征保存为二进制格式的特征值数据文件和文本可读的索引文件, 并且可以看到这是kaldi中经典的管道处理方式.。

data/ 目录下可以看到 raw_fbank.arkraw_fbank.scp,同样用 copy-feats 将数据转换为可读格式:

copy-feats ark:data/raw_fbank.ark ark,t:data/raw_fbank.txt

如下所示:

kaldiAudio  [
  8.004622 7.31894 8.03226 7.958833 7.955966 6.58563 8.797564 10.36797 10.24033 8.992172 9.952239 10.88897 9.673435 9.61389 10.71609 11.70178 10.77474 10.99115 10.87134 11.76409 11.64323 11.56577 11.01871 11.95526 11.79006 11.24747 12.42347 12.41098 12.58917 12.24361 12.18508 12.28606 12.86248 12.61785 12.69271 13.56598 12.89132 13.61957 13.60456 13.77276 
  6.146434 6.513846 6.958009 8.8211 8.080534 8.134282 7.915387 9.522163 8.873638 8.051316 8.937432 10.523 10.11279 10.12092 9.892173 9.687159 10.78549 10.76351 10.32943 9.95922 10.57875 10.86678 11.50387 11.36076 11.73355 11.79521 12.17509 12.91764 12.60885 12.69566 12.86338 13.0166 13.08658 13.39682 13.2829 13.3754 12.61703 13.31254 13.48593 13.20711 
  ...
  ...
    13.324 9.921647 9.136233 9.102282 8.616577 8.006015 9.04313 10.45946 10.39699 9.469311 9.850446 10.45423 10.16977 10.00985 9.99722 10.68876 10.11563 11.50137 10.48171 11.14089 10.6063 11.74318 11.68 11.54663 12.37438 12.52746 11.81949 11.84163 12.21267 12.9073 13.00435 13.2382 13.38783 12.42131 13.41655 13.60514 13.88391 14.06045 13.20792 13.10941 
  13.13926 9.507677 8.957983 9.091571 9.459952 8.951037 10.08002 10.3803 9.276938 9.746222 10.12829 10.31635 10.4552 10.88429 10.53327 11.45724 10.74167 11.32559 10.12712 11.33259 11.51689 10.89203 11.53752 11.97547 12.75158 12.92514 11.95726 13.27353 12.81323 12.54143 12.90975 13.18728 13.50072 12.78029 12.81061 12.90424 13.50287 13.87549 13.14325 12.738 ]

这是一个 [961, 40] 大小的特征矩阵,每一帧是40维的mel bins, 同时可以直接看到 raw_fbank.scp 中的内容,标识出特征数据所在的地址:

kaldiAudio data/raw_fbank.ark:11

kaldi中更多地会用这个索引文件来寻找特征数据,而不是直接读取二进制数据文件,特别是在 utterance 片段很多的时候,scp 格式的文件看起来就很简洁。

1-2 cmvn处理

cmvn 的全称是 cepstral mean and variance normalization,即倒谱均值方差归一化,归一化的目的是将输入的声学特征进行规整,使其符合正态分布,即均值为0向量,方差为单位矩阵。一般来说需要在某个范围内统计声学特征的均值和方差才能对某一段音频特征做归一化,比如kaldi中的全局归一化和说话人归一化 ,这里我们将问题简化,直接用这个音频特征自身的均值和方差来做归一化,这样就使得归一化之后的特征数据完全符合标准正态分布,然而实际上需要预先保存统计出来的均值和方差,用这个来对新的声学特征进行归一化。

先是通过 compute-cmvn-stats 计算cmvn系数,和特征数据一样,保存为ark和scp两种格式:

compute-cmvn-stats --spk2utt=ark:data/spk2utt scp:data/raw_fbank.scp \
	ark,scp:$cmvndir/cmvn.ark,$cmvndir/cmvn.scp

注意这里的spk2utt 文件,因为我们只有1个音频文件并且没有分割utterance 所以直接写成:

kaldiAudio kaldiAudio

最后是用 apply-cmvn-stats 生成归一化之后的声学特征:

cmvn_opts=
[ -e conf/cmvn_opts ] && cmvn_opts=$(cat conf/cmvn_opts)
feats="ark:copy-feats scp:data/raw_fbank.scp ark:- |"
[ -n "$cmvn_opts" ] && feats="$feats apply-cmvn $cmvn_opts --utt2spk=ark:data/utt2spk scp:$cmvndir/cmvn.scp ark:- ark:- |"

cmvn_opt中可以设置是否要对均值或者方差进行归一化,比如:

--norm-means=true --norm-vars=true

上面的代码执行后是将归一化之后的特征数据保存到feats变量中,我们可以放到终端执行并且指定保存的文件:

copy-feats scp:data/raw_fbank.scp ark:- \
 apply-cmvn --norm-means=true --norm-vars=true --utt2spk=ark:data/utt2spk scp:data/cmvn/cmvn.scp ark:- ark,t:data/cmvn_fbank.txt

之后就可以得到归一化之后的声学特征,打开后可以看到:

kaldiAudio  [
  -2.945327 -4.432829 -4.891563 -6.017329 -6.394454 -7.954942 -5.846905 -4.548752 -4.575329 -5.965943 -5.038093 -4.159336 -5.277455 -5.402295 -4.277543 -3.291182 -4.083419 -4.154355 -4.581059 -3.956977 -4.382272 -4.637384 -5.267299 -4.41099 -4.630136 -5.321544 -4.581518 -4.747177 -4.242865 -4.045171 -3.914935 -3.847886 -3.271742 -3.330802 -3.203338 -2.247759 -2.762707 -1.752607 -1.485643 -1.248099 
  -4.803515 -5.237923 -5.965814 -5.155062 -6.269886 -6.40629 -6.729082 -5.39456 -5.942019 -6.906799 -6.052899 -4.5253 -4.8381 -4.89526 -5.101463 -5.305805 -4.072673 -4.381994 -5.122971 -5.761846 -5.446749 -5.336382 -4.782134 -5.00549 -4.686643 -4.773796 -4.829899 -4.240518 -4.223187 -3.593121 -3.236631 -3.117339 -3.047639 -2.551827 -2.613138 -2.438336 -3.036993 -2.059637 -1.604279 -1.813745 
  -3.164258 -4.986865 -6.443318 -7.051134 -5.034025 -4.849117 -5.197085 -5.361386 -6.520294 -5.632722 -6.252649 -6.538762 -5.427609 -4.564577 -5.093193 -5.449993 -4.458255 -5.078162 -4.052905 -5.238842 -5.000014 -4.418169 -4.482397 -4.260475 -4.065145 -4.241971 -4.977835 -5.077936 -3.977766 -3.11266 -3.051807 -2.947707 -3.260707 -3.160501 -3.255517 -2.362335 -2.273935 -1.733366 -1.257235 -1.075335 
  ...
  ...
    2.374046 -1.830122 -3.78759 -4.87388 -5.733843 -6.534557 -5.601338 -4.45726 -4.418662 -5.488805 -5.139886 -4.594078 -4.781122 -5.006334 -4.996416 -4.304202 -4.742531 -3.644134 -4.970686 -4.580172 -5.419206 -4.45998 -4.606003 -4.819622 -4.045813 -4.041549 -5.185492 -5.31653 -4.619369 -3.38148 -3.095663 -2.895741 -2.746391 -3.527337 -2.479492 -2.208601 -1.770117 -1.311731 -1.882283 -1.911449 
  2.18931 -2.244092 -3.96584 -4.884591 -4.890468 -5.589535 -4.564451 -4.536425 -5.538718 -5.211894 -4.862037 -4.731953 -4.495687 -4.131897 -4.460361 -3.535728 -4.116488 -3.819917 -5.32528 -4.388479 -4.508615 -5.311132 -4.748485 -4.390786 -3.66861 -3.643873 -5.047722 -3.884631 -4.018808 -3.747348 -3.190265 -2.946657 -2.633502 -3.168358 -3.085437 -2.909503 -2.151148 -1.496687 -1.946952 -2.282863 ]

我们来计算一下归一化之后声学特征的均值向量和协方差矩阵:

可以看到均值向量是1个零向量,但协方差矩阵并不是单位矩阵,虽然对角线上,每一维的特征的方差都是1,但他们并不是相互独立的,所以其他位置的数值不为0。

目前为止我们得到了用来解码的40维归一化声学特征。

1-3 拼帧

splicing 或者拼帧是一种特征变换技术,即在一定的窗长内,将前后若干帧拼成一帧特征。虽然本文暂时不想过多涉及DNN的训练部分,但拼帧的实现是在训练脚本 steps/nnet/train.sh 中完成的,所以这里也要单独讲一下,训练脚本中 splice 被设置为5,因此拼帧时会将 t t t时刻一帧, t − 1 t-1 t1

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值