ASR神经网络实战

kaldi语音识别理论与实践课程学习。

之前学习了基于GMM-HMM的传统语音识别:GMM-HMM 其中也包含Kaldi架构的简介,语音数据的预处理,特征提取等过程。 今天学习基于神经网络的语音识别。

神经网络训练脚本

以TDNN为例。

Kaldi中大部分的例子egs里,都提供了训练thnn的recipe。

不同recipes的内容可能有所差异,但大体都能分为3个部分。

神经网络config可以简单理解为一张图,Kaldi网络就是从这张图初始化得到的。

参数设置

stage:控制脚本运行起始位置的参数。 nnet3_affix:训练好的神经网络存放名字后缀 train_stage:如果训到第50轮断了,就把该值设置成50,就可以从第50轮开始,而不需要从头开始

common_egs_dir和remove_egs后续会再说。

再下来 . ./的是配置环境变量。其中: utils/parse_options.sh 实现了基于shell脚本的“ --key value”的传参方式, 例如:

./run_tdnn.sh --stage 0 --gmm tri4b \

--nnet3_affix data_aug

注意: 只有定义在utils/parse_options.sh之前的参数允许以该方式传参, 图中的[dir, gmm_dir, ali_dir, graph_dir]等不能以此方式传参。

神经网络config

num_target:神经网络维度,tree的叶子节点数。 下面是个TDNN的网络结构。tdnn1,2,3只是名字,不代表是第一层、第二层等,你也可以写成a,b,c。(-1,0,2)代表context的左一右二。 configs是一组配置。可以理解为就是神经网络的画像,整体结构和内部节点之间的关系。网络初始化的时候就要按config里的定义初始化。 为了便于理解config,Kaldi提供了一个config解析器,即xconfig_to_configs。

生成以下文件: { final.config; init.config; init.raw; network.config; ref.config; ref.raw; vars; xconfig; xconfig.expanded.1; xconfig.expanded.2 }

可分为四类:

xconfig: 比原始的config增加了一些定义。expend2是对1的进一步解析。

init: 注意:是只和输入相关的节点,不是初始化后的整个网络。

init.config 只包含两个节点,input node和output node

init.raw 从init.config初始化得到的, 需要init.config的目的是得到输入数据的维度相关的信息,以便于训练后面的LDA,这是一个训练的小技巧。

ref 是reference的简称。顾名思义是个参考的config。 lda矩阵是”假“的(随机初始化的):还没有对输入数据进行遍历,还没有统计 ref.raw就是从ref.config得到的完整模型,为了给kaldi提供一个参考,供kaldi遍历,能够计算出整个模型的context。

final var,全程variable,存储模型上下文信息 这个左右context是根据左右context是根据ref.raw计算出来的。

final.config 训练的神经网咯就是由它初始化得到的。 被解析成更小的单元 component node

那component和component node之间是什么关系? 就是面向对象里的 类 component和 对象 component node的关系。

比如下面,

处了刚才例子中的TDNN模型中的relu-batchnorm组件,kaldi还有哪些组件呢? xconfig_parser支持的组件都在这个文件里: kaldi/egs/steps/libs/nnet3/xconfig/parser.py

这些组件可以分为以下几类:

Basic layer Activation & Normalization Recurrent layer Convolution layer Attention layer

这些组件按情况组在一起,可以DIY自己的网络。

下面介绍常见的网络模型。

Kaldi中的常见的神经网络

TDNN

一个简单的TDNN 看一下它的final.config Append:拼接 offset:相对于当前位置的偏移,-3向历史时刻偏移3时刻,+3向未来。

一个稍微复杂的TDNN

除了拼接,实现加的操作sum 直接把tdnn3的0时刻接到tdnn5 scale对某个层的输出放大、缩小

CNN

一个简单的CNN

用了conv-relu-batchnorm的组件 height就是FBank的维数,time-offset就是卷积核kernel的大小 代码里描述的就是一个3 *3 的卷积核 这样的组件解析出的final.config: 大多数参数和之前的一样,多了个height-subsample-out,指高度上的降采样率,因为输入高度height-in和输出高度height-out都是40,所以没有降采样,所以这里等于1。 另一个要注意的,num_filters_out=64,所以后面跟的component要有 block-dim=64,不然初始化模型时候会报错。

注:这里为了方面给大家看,里面有 /的换行符号,实际中kaldi是不允许有的。

LSTM

一个简单的LSTM 就多了个lstm-layer 和 cell,delay=3就是三次循环

先回归一下LSTM的网络结构: 输入xt,,历史信息rt ,输出yt。细胞核Ct

看下final-config: 因为比较复杂,下图删除了DNN的部分 下面看看component和LSTM的公式是怎么联系起来的? 比如,以输入门为例 it 可以从图中看到有三个输入箭头, Wix和Wir对应上面代码的第一部分(前三行) Wic对应第二部分(中间三行),向后偏移3个时刻 第三部分就是激活函数

再看个细胞核Ct的计算过程: ElementwiseProduct就是点乘。

总结以下:

上面学习了如何使用Xconfig提供的组件搭建TDNN等这些网络,从component中看和公式的对应关系。等熟练了这些,就可以自己DIY网络结构。

神经网络训练流程

如何使用定义好的神经网络进行训练? 先看一个标准DNN训练的脚本: feat-cmvn-opts:是否对参数归一化 训练前后期的jobs数,和学习率lrate,还可以用以前的egs,需不需要删掉,每多少步保存,是否用GPU,需要的文件地址,训练结束后模型存储位置 stage:描述控制训练流程 那标准的训练流程包含哪些步骤呢? init初始化stage不控制

egs:表示examples,训练使用的样例。把输入数据和标签换了一种方便读取的格式,整合在一起生成的文件。LDA:一般放在神经网络第一层 计算LDA变换矩阵与pre softmax矩阵就是训练的小技巧,一般数据集小的时候用到,数据量大的时候不用(此时对数据规整起不到太大作用,甚至有反作用)stage=50,从50轮开始继续训练

一个重要的步骤egs: stage=-4 这个目录下会生成四组文件

exp/$dir/egs

egs相关文件 egs.{n}.ark:训练数据易于读写的,有利于训练的形式 {t,v}_diagnostic.egs:计算模型在训练集t上的loss和验证集v上的loss combine.egs:训练结束后,用来合并多个模型的egs辅助文件 tree:输出节点的个数,从而确定egs的标签的上限 ali_special.scp和{t,v}_uttlist用来辅助生成{t,v}_diagnostic.egsinfo 总共有多少egs,多少帧等信息

egs内部的具体信息:

参数信息: 左右context,每个egs中有8帧语音,每个大的egs里有383176个egs,特征维度feat_num,num_frames用来训练的羽音帧数,num_archives最后生成的egs个数 egs内部: 每个大的egs里有383176个小的egs,下面看小的egs,是kaldi读取输入输出数据的最小单元。从上面的参数知,这个小的egs里有8帧有效帧,但下图中的input是40,是包含了context的(19+13+8) 整个训练的结果 final.raw只有神经网络的参数 final.mdl是在.raw的基础上增加了些信息 Priors:先验向量 单纯的神经网络只是计算出来后验概率,再结合TransitionModel和priors计算似然分数,才能得到声学模型 final.mdl是声学模型,final.raw只是神经网络模型

相关阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。