小言_互联网的博客

kaldi aishell2数据集训练以及生成文件详细分析(步骤+部分代码解释)

487人阅读  评论(0)

kaldi aishell2数据集训练(步骤+部分代码解释)

aishell2是希尔贝壳在kaldi上开源的一套1000小时的数据集,大概有100万句话,由于工程上的需要,我没有下载该数据集,而是用的自己的数据,需要的可以在官网上下载。
首先进入aishell/s5下:
conf:存放mfcc、decode等操作的配置文件。

data:存放训练、测试的数据以及音素表。原生的data目录下什么都没有,需要根据准备文件的脚本来进行自己创建。

首先根据当前目录下的run.sh,一上来就看到:

首先要自己设置训练集、验证集以及测试集的存放地址,然后是设置nj数:

nj即number job,表示多线程工作,其值貌似和GPU的个数以及核数有关,也就是说不能设置得太大,不然电脑配置跟不上;其次在run脚本中的nj是传给了训练gmm和dnn,它会将训练数据分割成nj个部分进行处理,所以你的训练集中的文件夹个数至少不能小于该nj数,不然怎么分割啊。

然后是该脚本的第一步stage1:执行local/prepare_all.sh,该shell脚本旨在对数据进行处理前做准备工作,由prepare_all.sh中的内容:

于是打开local/prepare_dict.sh,该脚本会提供一个下载大词典的程序,如果只是跑个流程,可以执行这一步,会自动生成aishell2数据集的词典,但具体我没试过,因为数据不一样,所以从一开始我就使用自己做的词典。
词典的格式为:

word phone1 phone2 ... phoneN

所以如果要使用自己的词典,则需要在data下创建一个local文件夹,在local下还要创建一个dict文件夹,然后将词典lexcion.txt放入dict下才可以成功执行准备音素相关文件的步骤,执行完local/prepare_dict.sh得到以下文件:

这些文件的具体作用这里就不做分析了,可以自己打开各个txt看就能明白。其中音素表的准备及其重要,一定要包含语料中所有出现过的词。如果是中文,大多发音都可以按照拼音来完成,但也有一些特例,比如w要用vv代替,可以参考清华30小时数据集thchs30中使用的一个很大的中文词典,然后英文词典组合可以参考voxforge数据集中的大词典。(需要的我可以私发给你)

然后看prepare_all的第二步:
查看prepare_data:

可知需要手动准备trans.txt和wav.scp。

其中trans.txt是数据集中所有wav所对应的文本的总和,其组成结构为:

	 utt	sentense

utt为话语标注,通常情况下即对应wav的名字,其内容一般涵盖了说话人信息,例如:Y1_023就表示Y1这个speaker说的023句话。然后sentense很明显就是该wav的文本,utt和sentense之间用制表符隔开,句子中的单词或词组用空格隔开。

wav.scp的结构为:

	utt		wav_dir

wav_dir指明了当前wav的地址,可以说绝对或者相对的,utt和wav_dir之间同样以制表符隔开。

对训练集、验证集、测试集各自生成对应的trans.txt和wav.scp,到此为止,需要手动生成的文件就准备完了,相对于aishell1和其他数据集的前期准备要简单很多。

local:一般存放本数据集常用的脚本,包括run中的prepare_all.sh,run_gmm.sh,run_tdnn.sh
step、utils:包含数据处理和网络训练等脚本
cmd.sh:

配置单机和多机器训练的脚本,单机跑的话需要将train_cmd、decode_cmd、mkgraph_cmd都设置为’run.pl’:

path.sh:配置各种工具的环境的脚本,包括openfst、srilm还有tools下的环境生效都放在里面。

部分脚本以及生成的文件分析

以下训练中只使用了训练集和测试集,没有使用验证集,所以只有train和test
1.local/prepare_data.sh
首先来看看该脚本会生成的文件:data/train、data/test

以train文件为例,其目录下为:

spk2utt和utt2spk不用解释,即说话人和话语的对应关系,text为经过分词后的trans.txt,第一次使用需要安装jieba分词工具。

同时会在data/local下生成同样的train和test文件夹,其中包括生成前面4个文件的中间临时文件。

2.utils/prepare_lang.sh
该脚本会在data下生成一个lang文件夹,里面包含了语言信息:

L.fst:字典的fst结构
L_disambig.fst:包含了为消除歧义而引入的符号的L.fst,如#1,#2以及字环而引入的#0
phones.txt:词典中所有出现的音素
oov.txtoov.int:txt中包含unknown的词,int里为2个字节
topo:音素的拓扑文件,其中包含了转移概率、转移路径、id等重要信息。
words.txt:包含所有词典中出现的词以及对应的id
phones:文件夹中包含了词与音素的对其结果、特殊词的音素等等音素的信息,具体的没研究过。

同时在data/local下也会生成一个同名的lang文件夹,里面包含一些临时文件。

3.local/train_lms.sh:训练语言模型的脚本
kaldi中默认使用自带的生成语言模型的程序,不过也提供了通过srilm工具来生成语言模型的方法,在该脚本中均有体现,如果要使用srilm可以执行tools下的对应install.sh直接下载,但通常会出错,具体的不叙述了,因为我用的自带的。需要注意的是,使用该脚本,训练数据必须不小于10000,不然会报错,或者你非要使用小数据进行训练,则要改/kaldi-master/tools/kaldi_lm/train_lm.sh,将heldout_sent的值改小即可,但很明显小数据一般不会有好的效果。
执行该脚本生成data/local/lm,其中包括以下文件:

3gram-mincount:包含了困惑率和训练lm的配置文件等
text.no_oov:将text中所有词典没有出现过的词用代替
word_map:对词典中的每个词用不同的字符对应

由于词比较多,用普通的字符或者单词不能映射完,所以出现了这种类似乱码的情况,只需明白它是一直对应关系就行。
train.gz:包含一个train文件,将训练的每一句文本的每一个词都用word_map中的对应字符来表示:

word.count:统计词典中的词在训练集中出现的个数
wordlist.mapped:word_map中所用的字符
unigram.counts:也是统计词个数,但是加了点东西,导致每个词的个数都比word.count中的个数多,看了下脚本跟SIL有关,但一时半会没搞清楚,望大佬指点。

4.run_gmm.sh
这个脚本包含了mfcc特征提取,均值方差归一化:

mono、tri1,tri2,tri3训练分别是train_mono.sh,train_deltas.sh和train_lda_mllt.sh,train_mono.sh是训练单音素模型,train_deltas.sh是训练三音素模型,train_lda_mllt.sh是对特征使用LDA和MLLT进行变换,训练加入LDA和MLLT的三音素模型;其中tri1和tri2都用train_deltas.sh进行训练,只是改变了初始高斯数和总高斯数,还可以加入自适应的三音素模型train_sat.sh,效果挺好的。
所有模型训练完后都通过utils/mkgraph.sh生成HCLG.fst:一个包含词典、语言、HMM、上下文关系的最终解码网格。

再通过steps/decode.sh进行解码得到错误率文件,最后如果要进行下一个模型的训练,还需要对数据进行强制对齐:

对齐后的结果被用于下一个模型的训练。具体的对齐原理我不是太清楚,只知道要尽量将HMM状态与对应帧对齐,这样才能更好的对音素建模。

5.run_tdnn.sh
run脚本中的最后一步,也是最重要的一步,其训练一个chain模型,与一般的dnn-hmm模型不同,它不需要事先训练一个交叉熵准则的DNN模型,而是直接使用对HMM-HMM模型的对齐结果作为输入。训练chain模型需要安装CUDA使用gpu,具体安装步骤上网查吧。
首先是参数的初始化:

其中我觉得比较重要的有num_epochs,表示做完一个完整的迭代过程的次数;然后是初始学习率和最终学习率,不知道怎么设的建议都设小点;然后是minibatch_size:随机梯度下降的批量大小,需要是2的幂。
增加了改变音高的utils/data/perturb_data_dir_volume.sh:

相当于增加了数据量,同样地要提取mfcc特征和归一化,然后是提取ivector特征,这是一个超矢量,具体的不详细介绍了,通常用于说话人识别,这里加入该步骤可以增加特征的差异性,但对识别效果貌似提升不大。

接下来第7步:

将GMM-HMM的对齐结果作为lattice用于chain训练,免去鉴别性训练中需要提前生成lattice的步骤,所以叫LF-MMI(lattice free)

然后是stage8和9

这两步是为了使topo结构中每个音素对应一个状态,这样更容易对音素进行建模。然后利用topo生成状态树。
stage 10是将训练的神经网络的结构写入配置文件,包括神经网络的层数,激活函数以及神经元个数,这一部分的结构我不是特别的清楚,包括append、层后接着组件的意义还有name的命名都不太懂,希望有大佬能给我讲解下,非常感谢。

stage11就开始训练啦,把需要的参数传进去就行了,最后会生成final.mdl就是最终的声学模型。然后就是生成HCLG.fst和decode步骤,和前面GMM-HMM的步骤类似,只是使用的脚本不同。

chain模型的识别效果还是非常不错的,当然还是要基于大数据,大家可以尝试下。本文皆是自己训练后的一点小小的总结,也算是个备忘录吧,文中有任何错误的地方欢迎各位大佬指出,我会积极改正,渴望从各位大佬身上学到更多的知识,大家一起共同进步!


转载:https://blog.csdn.net/qq_37601846/article/details/100922463
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场