深度学习:语音识别技术实践
上QQ阅读APP看书,第一时间看更新

1.6 构建一个简单的ASR

本节将数据分为训练和测试集,建立一个ASR系统,对其进行训练、测试并获得一些解码结果。在kaldi-trunk/egs目录中创建一个digits文件夹,把所有与项目相关的文件等都放在这里。

假设想要建立一个基于自己的音频数据的ASR系统,需要100个文件的数据集,文件格式为.wav,每个文件包含3个以英文记录的口语数字。这些音频文件中的每一个以可识别的方式命名(例如,“1_5_6.wav”,相应的语音句子是“一、五、六”),并且在特定记录会话期间放置在表示特定说话者可识别的文件夹中。可能有一种情况——同一人的录音在两个不同的质量/噪声环境中,这时要将它们放在单独的文件夹中。总结一下,示范数据集如下所述:


10个不同的说话者(ASR系统必须在不同的说话者上进行训练和测试,所以说话者越多越好)。

每位说话者说10句话。

100个句子/话语(100个*.wav文件中放置在与特定说话者有关的10个文件夹中,每个文件夹中有10个* .wav文件)。

300个词(0~9的数字)。

每个句子/话语由3个词组成。


无论第一个数据集是什么,请根据具体情况调整。小心大数据集和复杂的语法,从简单的开始,在这种情况下只包含数字的句子比较不错。

找到kaldi-trunk/egs/digits目录并创建digits_audio文件夹,在kaldi-trunk/egs/digits/ digits_audio中再创建两个文件夹——test和train。选择一个说话者来表示测试数据集,使用该说话者的“speakerID”作为kaldi-trunk/egs/digits/digits_audio/test目录中另一个新文件夹的名称,然后把所有与该人有关的音频文件放在一起;将其余(9个说话者)放入train文件夹,这将是训练数据集。

1. 音频数据

准备音频数据。必须创建一些文本文件,用来允许Kaldi系统与音频数据打交道。在此部分(及语言数据部分)创建的每个文件都可以被视为具有一定数量的字符串(每个字符串占一个独立行)的文本文件。这些字符串需要排序,如果遇到任何排序问题,可以使用Kaldi脚本检查(utils/validate_ data_dir.sh)和修复(utils/fix_data_dir.sh)数据顺序。并且为了信息,utils目录将在工具附件部分被附加到用户的项目。

在kaldi-trunk/egs/digits目录中创建test和train子文件夹后,在每个子文件夹中创建以下文件(在test和train子文件夹中以同样的方式命名文件,只不过是与之前创建的两个不同的数据集相关)。

(1)spk2gender

该文件记录说话者的性别。如同我们假设的,“speakerID”是每个说话者的唯一名称(在这种情况下,它也是一个“recordingID”)。在这个例子中,有5名女性和5名男性说话者(f=女性,m=男性)。

模式:<speakerID> <gender>

例如:

    cristine f
    dad m
    josh m
    july f
    #...

(2)wav.scp

该文件用相关的音频文件连接每个发言(在特定记录会话期间由一个人说的句子)。如果坚持这里的命名方法,utteranceID只不过是speakerID(说话者的文件夹名称)附带了*.wav文件名,而没有'.wav'结尾(看下面的例子)。

模式:<uterranceID> <full_path_to_audio_file>

例如:

    dad_4_4_2 /home/{user}/kaldi-trunk/egs/digits/digits_audio/train/dad/4_4_2.wav
    july_1_2_5 /home/{user}/kaldi-trunk/egs/digits/digits_audio/train/july/1_2_5.wav
    july_6_8_3 /home/{user}/kaldi-trunk/egs/digits/digits_audio/train/july/6_8_3.wav
    #...

(3)text

该文件包含与其文本转录匹配的每个发言。

模式:<uterranceID> <text_transcription>

例如:

    dad 4 4 2 four four two
    july 1 2 5 one two five
    july 6 8 3 six eight three
    #...

(4)utt2spk

该文件告诉ASR系统发言属于哪个特定的说话者。

模式:<uterranceID> <speakerID>

例如:

    dad 4 4 2 dad
    july 1 2 5 july
    july 6 8 3 july
    #...

(5)corpus.txt

该文件目录略有不同。在kaldi-trunk/egs/digits/data中创建一个文件夹local,在kaldi-trunk/egs/digits/data/local中创建一个文件corpus.txt,该文件应该包含可能发生在ASR系统中的每一个话语转录(在我们的情况下,是100行100个音频文件)。

模式:<text_transcription>

例如:

    one two five
    six eight three
    four four two
    #...

2. 语言数据

下面涉及的语言建模文件,也需要将其视为“必须完成”。现在展示的是一个理想的例子。

在kaldi-trunk/egs/digits/data/local目录中创建一个文件夹dict,在kaldi-trunk/egs/ digits/data/local/dict中创建以下文件。

(1)lexicon.txt

该文件包含字典中的每个单词及其电话录音(取自/egs/voxforge)。

模式:<word> <phone 1> <phone 2>…

例如:

    !SIL sil
    <UNK> spn
    eight ey t
    five f ay v
    four f ao r
    nine n ay n
    one hh w ah n
    one w ah n
    seven s eh v ah n
    six s ih k s
    three th r iy
    two t uw
    zero z ih r ow
    zero z iy r ow

(2)nonsilence_phones.txt

该文件列出了项目中存在的非静止的音素。

模式:<phone>

    ah
    ao
    ay
    eh
    ey
    f
    hh
    ih
    iy
    k
    n
    ow
    r
    s
    t
    th
    uw
    w
    v
    z

(3)silence_phones.txt

该文件列出了静止的音素。

模式:<phone>

    sil
    spn

(4)optional_silence.txt

该文件列出了可选的静止音素。

模式:<phone>

    sil

下面添加在示例性脚本中广泛使用的必需的Kaldi工具。

从kaldi-trunk/egs/wsj/s5目录中复制两个文件夹(和全部内容)——utils和steps,并将它们放在kaldi-trunk/egs/digits目录中。同时,还可以创建到这些目录的链接,可以在kaldi-trunk/egs/voxforge/s5中找到这样的链接。

打分脚本可帮助获得解码结果,从kaldi-trunk/egs/voxforge/s5/local目录中将脚本score.sh复制到项目中的相似位置(kaldi-trunk/egs/digits/local)。此外,还需要安装在这个示例中使用的语言建模工具包——SRI语言建模(SRILM)工具包。有关详细的安装说明,请访问kaldi-trunk/tools/install_srilm.sh(阅读里面所有的注释)。因为SRILM是一款商用收费的软件,所以没有自动下载的脚本。下载srilm-1.7.2.tar.gz并重命名为srilm.tgz后,运行install_srilm.sh。

    mv ./srilm-1.7.2.tar.gz  ./srilm.tgz
    ./install_srilm.sh

在kaldi-trunk/egs/digits中创建一个文件夹conf,在该文件夹内部创建以下两个文件(对于解码和mfcc特征提取过程中的一些配置修改,取自/egs/voxforge)。

(1)decode.config

    first beam=10.0
    beam=13.0
    lattice_beam=6.0

(2)mfcc.conf

    --use-energy=false

最后一项工作是准备运行脚本来创建ASR系统。

以下这两种方法足以在仅使用数字词典和小训练数据集的情况下显示解码结果的显著差异。


MONO:单声道训练。

TRI1:简单的三音素训练。


在kaldi-trunk/egs/digits目录中创建以下3个脚本。

(1)cmd.sh

    #设置本地系统任务(本地CPU无须外部群集)
    export train cmd=run.pl
    export decode_cmd=run.pl

(2)path.sh

    #定义Kaldi根目录
    export KALDI ROOT='pwd'/../..
    #设置路径以包含有用的工具
    export PATH=$PWD/utils/:$KALDI_ROOT/src/bin:$KALDI_ROOT/tools/openfst/
bin:$KALDI_ROOT/src/fstbin/:$KALDI_ROOT/src/gmmbin/:$KALDI_ROOT/src/featbin/
:$KALDI_ROOT/src/lmbin/:$KALDI_ROOT/src/sgmm2bin/:$KALDI_ROOT/src/fgmmbin/
:$KALDI_ROOT/src/latbin/:$PWD:$PATH
    #定义音频数据路径
    export DATA ROOT="/home/{user}/kaldi-trunk/egs/digits/digits_audio"
    #启用SRILM
    source $KALDI_ROOT/tools/env.sh
    #为了数据能够正确排序所需的变量
    export LC_ALL=C

(3)run.sh

现在要做的就是运行run.sh脚本。终端的日志能提示你如何处理可能遇到的错误。

除了在终端窗口中会注意到某些解码结果外,进入新创建的kaldi-trunk/egs/digits/ exp,可能会注意到该exp文件夹中有同样目录结构的mono和tri1结果。如果切换到mono/decode目录,在这里可能会找到结果文件(以wer_ {number}方式命名)。解码过程的日志可以在日志文件夹(同一目录)中找到。

在成功安装Kaldi后,可运行一些示例脚本(如Yesno、Voxforge、LibriSpeech,它们相对容易,有免费的音频/语言数据可供下载)。