Kaldi 模型训练与测试流程

先决条件

要学习Kaldi 有一些先决条件要具备

  • Linux:
    Kalid本身是在Linux下开发和测试运行的,虽然官方给了在Windows下用VS编译运行的方法,但我没有成功,坑比较多,除非你对Windows VS很熟,否则建议直接在Linux下搞。

  • C++: Kaldi所有相关算法的实现都是用C做的,如果要用Kaldi做自己的产品,C是必须会的。

  • 机器学习已经入门:搞Kaldi机器学习基本的东西要知道,不然,你都不知道你在干什么。

目录结构

首先介绍一下运行Kaldi项目的目录结构

|-- cmd.sh // 运行配置目录,设置Kaldi运行的环境变量,例如使用什么类型的队列
|-- conf  // 配置文件目录,mfcc、等参数的配置
|-- data  // Kaldi运行所产生的数据
|-- exp  // Kaldi每一步训练的模型数据及测试数据
|-- local  //存放run.sh 中调用的脚本工具,需要自己写
|-- mfcc  // mfcc数据
|-- path.sh //将Kaldi 工具和库目录添加到PATH
|-- run.sh // top层脚本,运行该脚本训练数据和测试, 需要自己写
|-- steps // kaldi 脚本工具, 复制到工程目录下
|-- tools // kaldi 脚本工具, 复制到工程目录下
`-- utils // kaldi 脚本工具, 复制到工程目录下

运行脚本

run.sh为总的运行脚本


语料准备

要做训练首先要有语料

Kaildi默认只支持wav格式的文件,为了方便,我们将为每个wav文件建立一个相同文件名的txt文件,在其放置标记后的内容,并做分词(why?)。

开放的语料主要的thchs30和aishell

词典准备

词典准备需要下面五个文件

  • lexicon.txt
  • extra_questions.txt
  • nonsilence_phones.txt
  • optional_silence.txt
  • silence_phones.txt

local/tinet_prepare_dict.sh 是准备词典的,只需要提供lexicon.txt,该脚本就会将其他文件也自动生成。

调用

local/tinet_prepare_dict.sh $data/resource_aishell

脚本将会在data/local/dict文件夹下创建这五个文件。

需要我们创建的文件

有些文需要我们自己去创建,这些文件是Kaldi训练模型所需要的。
在data目录下创建train、test 文件夹,并在每个文件夹创建如下文件

  • wav.scp
  • utt2spk.scp
  • spk2utt.scp
  • text
  • word.txt

wav.scp

文件格式如下所示:

<recording-id> <extended-filename>

wav.scp文件的目的就是给每个录音文件指定一个唯一ID。

完成后会在data目录下创建两个文件夹 train、test

MFCC

下面要计算wav的mfcc

在data目录下创建文件夹mfcc,并将train、test目录拷贝过来

接下来分别创建train和test的mfcc。

steps/make_mfcc.sh --nj $n --cmd "$train_cmd" data/mfcc/train exp/make_mfcc/train mfcc/train

steps/make_mfcc.sh --nj $n --cmd "$train_cmd" data/mfcc/test exp/make_mfcc/test mfcc/test

make_mfcc.sh的使用如下所示:

./steps/make_mfcc.sh 
Usage: ./steps/make_mfcc.sh [options] <data-dir> [<log-dir> [<mfcc-dir>] ]
e.g.: ./steps/make_mfcc.sh data/train exp/make_mfcc/train mfcc
Note: <log-dir> defaults to <data-dir>/log, and <mfccdir> defaults to <data-dir>/data
Options: 
  --mfcc-config <config-file>                      # config passed to compute-mfcc-feats 
  --nj <nj>                                        # number of parallel jobs
  --cmd (utils/run.pl|utils/queue.pl <queue opts>) # how to run jobs.
  --write-utt2num-frames <true|false>     # If true, write utt2num_frames file.

data/mfcc/train 为数据目录,exp/make_mfcc/train 为日志目录,mfcc/train是计算出的mfcc。

make_mfcc.sh 会在data/mfcc/{train,test} 创建feats.scp文件,内容如下所示:

000000 /lab/kaldi/kaldi_lab/mfcc/train/raw_mfcc_train.1.ark:7
000001 /lab/kaldi/kaldi_lab/mfcc/train/raw_mfcc_train.1.ark:3376
000002 /lab/kaldi/kaldi_lab/mfcc/train/raw_mfcc_train.1.ark:5705

这个文建指向了很多我们提取到的特征的原文件,而这也正是我们在一些脚本使用的。该文件的格式是

<utterance-id> <extended-filename-of-features>

其中 000000 /lab/kaldi/kaldi_lab/mfcc/train/raw_mfcc_train.1.ark:7
表示从这个文件的第7个位置开始读(使用 fseek() 函数)。

cmvn

cmvn.scp 保存了倒谱归一化均值和方差(cepstral mean and variance normalization)的统计信息.

<speaker-id> <extended-filename-of-cmvn>

compute_cmvn_stats.sh 命令如下所示


compute_cmvn_stats.shsteps/

Usage: steps/compute_cmvn_stats.sh [options] <data-dir> [<log-dir> [<cmvn-dir>] ]
e.g.: steps/compute_cmvn_stats.sh data/train exp/make_mfcc/train mfcc
Note: <log-dir> defaults to <data-dir>/log, and <cmvn-dir> defaults to <data-dir>/data
Options:
 --fake          gives you fake cmvn stats that do no normalization.
 --two-channel   is for two-channel telephone data, there must be no segments 
                 file and reco2file_and_channel must be present.  It will take
                 only frames that are louder than the other channel.
 --fake-dims <n1:n2>  Generate stats that won't cause normalization for these
                  dimensions (e.g. 13:14:15)

compute_cmvn_stats.sh 在数据目录下创建cmvn.scp

该文件格式是

<speaker-id> <extended-filename-of-cmvn>