kaldi入门详解——aishell步骤解释

kaildi讲解

kaldi是一个开源的语音识别工具箱,是基于c++、perl、shell编写的,可以在windows和unix 平台上编译。

教程网页:http://www.kaldi-asr.org/doc/ 里面可以查阅语音/说话人识别实现过程、kaldi的数据结构、命令的使用说明等。还有网上的dan的ppt。

kaldi下载:https://github.com/kaldi-asr/kaldi。

语音识别基础知识快速入门

英文:《Speech and Language Processing》第9、10章。

中文入门方式可以看《语音信号处理》韩纪庆(编)的语音识别章节;或者《模式分类》这本书的部分章节。

kaldi安装

简要说明:(运行环境centos7、ubuntu16.4、macos 10.13都能安装成功)
0. 安装前你需要对你的 linux 进行配置,需要安装的软件apt-get、subversion、automake、autoconf、libtool、g++、zlib、libatal、wget,如何安装见《kaldi的全部资料_v0.7(未完成版本).pdf》。

  1. git clone https://github.com/kaldi-asr/kaldi.git 选择某个路径,下载kaldi。

  2. 在命令行cd到kaldi路径下,cd到tool目录下,在命令行分别输入:

    make -j nproc

    extras/install_irstlm.sh

install_irstlm.sh是安装语言模型。
3. make 完后,在src目录下:在命令行分别输入:

./configure

make depend

make

make阶段是编译阶段,将下载的包编译为可执行文件,耗时较长,耐心等待。

ubuntu安装遇到问题最少,centos和macos上安装都会出现一些问题,得手动解决。

遇到过的error和解决方法:

  1. make过程中,openfst-1.6.7.tar.gz没有解压完全,因此自动又解压一遍,生成openfst-1.6.7.tar.gz.1,因此要把原openfst-1.6.7.tar.gz删掉(rm openfst-1.6.7.tar.gz),openfst-1.6.7.tar.gz.1重命名为openfst-1.6.7.tar.gz(mv openfst-1.6.7.tar.gz.1 openfst-1.6.7.tar.gz)。再次make(不需要手动解压)。

  2. sudo make仍出现permission denied造成error。把文件夹的用户改成使用者。比如我的用户名叫work,chown -R work kaldi

  3. 如果多次make都遇到error,建议先make clean把编译过的全删掉,再重新装。

kaldi各文件解释

  • /egs:不同语料例子的执行脚本文件
  • /tools:存放asr过程中用到的库
  • /src:存放实际执行的c++算法

以aishell为例的ASR过程

命令行到kaldi路径下,输入

cd egs/aishell/s5

首先改cmd的配置:

vim cmd.sh

改为:

export train_cmd=run.pl         #"queue.pl --mem 2G"
export decode_cmd="run.pl --mem 4G"    #"queue.pl --mem 4G"
export mkgraph_cmd="run.pl --mem 8G"   #"queue.pl --mem 8G"
export cuda_cmd="run.pl --gpu 1"

原文件的queue是基于集群的,这里我们用本机/服务器跑,因此改为run.sh。

:wq保存后,输入:

vim run.sh

看见data=/export/a05/xna/data改成想存放语料的路径,返回后,新建对应的文件夹。之后输入

./run.sh

就开始进行asr过程了。强烈建议逐行运行,运行当前行时,把其他暂时注释调,这样清楚看见每个阶段的过程。

过程简单说来就是:

  • 语料数据准备 下载语料库到本地/服务器的文件夹
  • 数据关系,词典、语言文件(text, wav.scp, utt2pk, spk2utt)准备,训练集、测试集、验证集准备
  • 单音素(或者其他模型)训练和解码
  • 构建解码图
  • 解码查看结果

run.sh详细解释:

这里是简单的介绍,具体细节可以参考kaldi入门详解 aishell2步骤解释(二)

vim run.sh

查看run.sh脚本,这里逐行解释:

下载并解压aishell 178小时语料库,(音频和lexicon词典):

local/download_and_untar.sh $data $data_url data_aishell || exit 1;
local/download_and_untar.sh $data $data_url resource_aishell || exit 1;

准备词典:

local/aishell_prepare_dict.sh $data/resource_aishell || exit 1;

准备数据。分成test、dev、train集。:

local/aishell_data_prep.sh $data/data_aishell/wav $data/data_aishell/transcript || exit 1;

词典、语言文件准备,生成对应的数据关系:

Phone Sets, questions, L compilation
utils/prepare_lang.sh --position-dependent-phones false data/local/dict \
    "" data/local/lang data/lang || exit 1;

其中,数据关系保存在/data里,文件解释如下:

  • spk2gender 包含说话人的性别信息
  • spk2utt 包含说话人编号和说话人的语音编号的信息
  • text 包含语音和语音编号之间的关系
  • utt2spk 语音编号和说话人编号之间的关系
  • wav.scp 包含了原始语音的路径信息等

提取MFCC特征:

# Now make MFCC plus pitch features.
# mfccdir should be some place with a largish disk where you
# want to store MFCC features.
mfccdir=mfcc
for x in train dev test; do
  steps/make_mfcc_pitch.sh --cmd "$train_cmd" --nj 10 data/$x exp/make_mfcc/$x $mfccdir || exit 1;
  steps/compute_cmvn_stats.sh data/$x exp/make_mfcc/$x $mfccdir || exit 1;
  utils/fix_data_dir.sh data/$x || exit 1;
done

分为两步,先通过steps/make_mfcc.sh提取MFCC特征,再通过steps/compute_cmvn_stats.sh计算倒谱均值和方差归一化。

生成了两个文件夹:mfcc 和 exp/make_mfcc,其中 mfcc 里主要保存了提取的特征,而 exp/make_mfcc 里保存了日志,即 .log 文件。

在 steps/make_mfcc.sh 里用到的最主要的命令就是 compute-mfcc-feats 和 copy-feats,其在 src 里编译好的。

mfcc 目录里主要是 .ark 和 .scp 文件,其中 .scp 文件里的内容是语音段和特征对应,而真正的特征保存在 .ark 文件里。用下面的命令可以看清楚

copy-feats ark:mfcc/raw_mfcc_train.1.ark ark,t:-

单音素训练:

steps/train_mono.sh --cmd "$train_cmd" --nj 10 \
    data/train data/lang exp/mono || exit 1;    

之后会在 exp 文件夹下产生一个 mono 的目录,里面以 .mdl 结尾的就保存了模型的参数。使用下面的命令可以查看模型的内容。

$ gmm-copy --binary=false exp/mono/0.mdl - | less

构建单音素解码图:

# Monophone decoding
utils/mkgraph.sh data/lang_test exp/mono exp/mono/graph || exit 1;

mkgraph.sh主要生成了HCLG.fstwords.txt这两个重要的文件,后续识别主要利用了三个文件,分别是final.mdlHCLG.fstwords.txt

解码:分别针对开发集和测试集解码

steps/decode.sh --cmd "$decode_cmd" --config conf/decode.config --nj 10 \
  exp/mono/graph data/dev exp/mono/decode_dev
steps/decode.sh --cmd "$decode_cmd" --config conf/decode.config --nj 10 \
  exp/mono/graph data/test exp/mono/decode_test

解码的日志会保存在 exp/mono/decode_dev/log 和 exp/mono/decode_test/log 里。

Veterbi 对齐

# Get alignments from monophone system.
steps/align_si.sh --cmd "$train_cmd" --nj 10 \
  data/train data/lang exp/mono exp/mono_ali || exit 1;

之后就是和训练单音素一样,进行其他模型的训练解码,生成声学模型和语言模型,保存在/exp中。

查看结果:

输入下面的命令来查看结果

# getting results (see RESULTS file)
for x in exp/*/decode_test; do [ -d $x ] && grep WER $x/cer_* | utils/best_wer.sh; done 2>/dev/null

总结:aishell的/s5/run.sh文件运行了gmm+hmm hybrid模型以及dnn+hmm hybrid模型。

  • 首先用标准的13维MFCC加上一阶和二阶导数训练单音素GMM系统,采用倒谱均值归一化(CMN)来降低通道效应。然后基于具有由LDA和MLLT变换的特征的单音系统构造三音GMM系统,最后的GMM系统用于为随后的DNN训练生成状态对齐。
  • 基于GMM系统提供的对齐来训练DNN系统,特征是40维FBank,并且相邻的帧由11帧窗口(每侧5个窗口)连接。连接的特征被LDA转换,其中维度降低到200。然后应用全局均值和方差归一化以获得DNN输入。DNN架构由4个隐藏层组成,每个层由1200个单元组成,输出层由3386个单元组成。 基线DNN模型用交叉熵的标准训练。 使用随机梯度下降(SGD)算法来执行优化。 将迷你批量大小设定为256,初始学习率设定为0.008。
  • 被噪声干扰的语音可以使用基于深度自动编码器(DAE)的噪声消除方法。DAE是自动编码器(AE)的一种特殊实现,通过在模型训练中对输入特征引入随机破坏。已经表明,该模型学习低维度特征的能力非常强大,并且可以用于恢复被噪声破坏的信号。在实践中,DAE被用作前端管道的特定组件。输入是11维Fbank特征(在均值归一化之后),输出是对应于中心帧的噪声消除特征。然后对输出进行LDA变换,提取全局标准化的常规Fbank特征,然后送到DNN声学模型(用纯净语音进行训练)。
  1. train_mono.sh 用来训练单音子隐马尔科夫模型,一共进行40次迭代,每两次迭代进行一次对齐操作
  2. train_deltas.sh 用来训练与上下文相关的三音子模型
  3. train_lda_mllt.sh 用来进行线性判别分析和最大似然线性转换
  4. train_sat.sh 用来训练发音人自适应,基于特征空间最大似然线性回归
  5. nnet3/run_dnn.sh 用nnet3来训练DNN,包括xent和MPE
  6. 用chain训练DNN

结果

aishell训练模型的词错误率wer和字错误率cer如下:

%WER 44.23 [ 28499 / 64428, 1821 ins, 4610 del, 22068 sub ] exp/mono/decode_test/wer_13_0.0
%WER 29.67 [ 19113 / 64428, 1567 ins, 2934 del, 14612 sub ] exp/tri1/decode_test/wer_14_0.5
%WER 29.24 [ 18841 / 64428, 1557 ins, 2813 del, 14471 sub ] exp/tri2/decode_test/wer_15_0.5
%WER 27.38 [ 17640 / 64428, 1764 ins, 2267 del, 13609 sub ] exp/tri3a/decode_test/wer_16_0.0
%WER 23.44 [ 15102 / 64428, 1468 ins, 2110 del, 11524 sub ] exp/tri4a/decode_test/wer_15_0.5
%WER 21.76 [ 14017 / 64428, 1383 ins, 1954 del, 10680 sub ] exp/tri5a/decode_test/wer_16_0.5
%WER 17.43 [ 11233 / 64428, 1077 ins, 1675 del, 8481 sub ] exp/nnet3/tdnn_sp/decode_test/wer_16_0.5
%WER 15.96 [ 10281 / 64428, 919 ins, 1672 del, 7690 sub ] exp/chain/tdnn_1a_sp/decode_test/wer_12_0.5

%CER 34.13 [ 35757 / 104765, 783 ins, 3765 del, 31209 sub ] exp/mono/decode_test/cer_11_0.0
%CER 19.56 [ 20496 / 104765, 910 ins, 1436 del, 18150 sub ] exp/tri1/decode_test/cer_13_0.5
%CER 19.16 [ 20073 / 104765, 989 ins, 1211 del, 17873 sub ] exp/tri2/decode_test/cer_13_0.5
%CER 17.24 [ 18060 / 104765, 780 ins, 1024 del, 16256 sub ] exp/tri3a/decode_test/cer_13_0.5
%CER 13.58 [ 14227 / 104765, 640 ins, 716 del, 12871 sub ] exp/tri4a/decode_test/cer_14_0.5
%CER 12.22 [ 12803 / 104765, 668 ins, 565 del, 11570 sub ] exp/tri5a/decode_test/cer_14_0.5
%CER 8.44 [ 8838 / 104765, 331 ins, 510 del, 7997 sub ] exp/nnet3/tdnn_sp/decode_test/cer_14_0.5
%CER 7.37 [ 7722 / 104765, 303 ins, 581 del, 6838 sub ] exp/chain/tdnn_1a_sp/decode_test/cer_11_1.0

参考资料:
1.解读thchs30/s5/run.sh的主要步骤:https://blog.csdn.net/BBZZ2/article/details/72884979
2.kaldi的语音识别数据timit例子详解:https://blog.csdn.net/DanyHgc/article/details/75222517

你可能感兴趣的:(kaldi)