Kaldi样例实战

一.前提条件

  在kaldi目录下的子目录kaldi/egs/目录下保存着资源管理示例脚本。查看该目录中的README.txt文件,尤其是查看资源管理部分,它提到 与语料库相对应的LDC目录号。这可以从LDC获取数据。

  

  

  进入rm目录,浏览README.txt文件查看整体结构,进入s5子目录,在s5目录中,列出并浏览RESULTS文件,以便对其中的内容有所了解。其中最重要的文件是run.sh。注意,run.sh不能直接执行,必须手动执行文件中的一系列命令。

  

  

二.资料准备

  首先,需要配置作业,如果没有安装GridEngine【分布式资源管理工具】,或者是使用较小的数据集进行实验,可以在shell上执行以下命令:

  

  如果安装了GridEngine,则应将queue.pl文件与指定GridEngine驻留位置的参数一起使用。在这种情况下,执行以下命令【参数-q是示例,在实际应用中替换为GridEngine详细信息】:

  train_cmd=" queue.pl -q all.q@a*.clsp.jhu.edu"
  encode_cmd="queue.pl -q all.q@[ah]*.clsp.jhu.edu"

  下一步是从rm语料库中创建测试和训练集。为此,执行以下命令【假设要测试的数据在./export/LDC/LDC2019S20/rm_comp/下,此数据可以去KALDI下载,需要付费】

  

  命令:./local/rm_data_prep.sh /export/LDC/LDC2019S20/rm_comp/

  执行成功后,会在当前目录下创建data的新目录。这个新目录包含三种主要的文件夹类型:

    ·local:包含当前数据的字典。

    ·train:从语料库中分割出来的用于训练的数据。

    ·test_*:从语料库中分割出来的数据,用于测试。

  

  在数据目录下执行下面的命令:

  cd local/dict
  head lexicon.txt
  head nonsilence_phones.txt
  head silence_phones.txt

  使用这些命令可以大致了解通用数据准备过程的输出。应该意识到,并非所有的这些文件都是本地Kaldi格式,即,并非所有文件都可以被Kaldi的C++程序读取,部分还需要使用Kaldi之前使用OpenFST工具进行处理。

    lexicon.txt:词典

    *silence*.txt:这些文件包含有关电话静音已经保持静音的信息。

  在train目录下,执行以下命令:

  head text
  head spk2gender
  head spk2utt
  head utt2spk
  head wav.scp

  ·text:该文件包含发声和发声ID之间的映射,这些映射将由Kaldi使用。该文件将转换为整数格式,但仍然是文本文件,单词将被替换为整数。

  ·spk2gender:该文件包含说话人及其性别之间的映射。这将充当参与培训的唯一用户列表。

  .spk2utt:这是说话者标识符与说话者相关的所有话语标识符之间的映射。

  .utt2spk:这是发话ID与相应说话者标识符之间的一对一映射。

  ·wav.scp-Kaldi程序在进行特征提取时实际上直接读取该文件。再次查看该文件,它被解析成一组键值对,其中键是每一行的第一个字符串。该值是一种“扩展文件名”。请注意,尽管我们使用扩展名.scp,但从HTK的角度来看,它不是脚本文件。

  train文件夹和test_*文件夹的结构相同。但是,train数据的大小明显大于test_*数据。可以通过返回数据目录并执行以下命令来验证这一点,该命令将给出训练集和测试集的字数:wc train/text test_feb89/text

  下一步是创建Kaldi使用的原始语言文件。在大多数情况下,这些文件将是整数格式的文本文件。确保返回到s5目录,并执行以下命令:

    utils/prepare_lang.sh data/local/dict '!SIL' data/local/lang data/lang

  这将在本地文件夹中创建一个名为lang的新文件夹,其中将包含描述所用语言的FST。看一下脚本。它将以data/创建的某些文件转化为Kaldi读取的规范形式。该脚本在data/lang/目录中创建其输出。该脚本创建的前两个文件称为words.txt和phones.txt【都在data/lang/下】。这些是OpenFst格式的符号表,表示从字符串到整数再到整数的映射。查看这些文件,它们很重要并且会经常使用。

  查看后缀为.csl的文件【在data/lang/phones中】,这些分别是冒号分隔的非静音和静音电话的整数ID列表。有时需要它们作为程序命令行上的选项,以及其它目的。

  查看phone.txt【在data/lang/中】,该文件是电话符号表,还处理标准FST中使用的"消歧符号"。这些符号通常称为#1,#2等。其中符号#0用来替换语言模型中的epsilon转换。

  文件L.fst是FST格式的编译词典。要查看其中包含哪种信息,可以执行以下操作:

    fstprint --isymbols=data/lang/phones.txt --osymbols=data/lang/words.txt data/lang/L.fst | head

  如果bash找不到命令fstprint,则需要将OpenFST的安装路径添加到PATH环境变量中。只需要运行脚本path.sh即可:

    ../path.sh

  下一步是使用在上一步中创建的文件来创建描述该语言语法的FST。为此,返回目录s5并执行以下命令:

    ./local/rm_prepare_gtammar.sh

  如果成功,则应该返回消息"成功为RM准备语法"。将在/data/lang中创建一个名为G.fst的新文件。

三.特征提取

  1.提取训练功能   

export featdir=/my/disk/rm_mfccdir
# make sure featdir exists and is somewhere you can write.
# can be local if you want.
mkdir $featdir
for x in test_mar87 test_oct87 test_feb89 test_oct89 test_feb91 test_sep92 train; do \
  steps/make_mfcc.sh --nj 8 --cmd "run.pl" data/$x exp/make_mfcc/$x $featdir; \
  steps/compute_cmvn_stats.sh data/$x exp/make_mfcc/$x $featdir; \
done

  运行这些作业,它们并行使用多个CPU,可以根据计算机的CPU数量更改-nj选项【指定要运行的作业数量】。查看文件exp /make_mfcc/train/make_mfcc.1.log以查看创建MFCC程序的日志输出。

  2.核心概念

  表的概念是基础脚本和归档文件。表格基本上是一组有序的项目,由唯一的字符串索引。Table并不是真正的C++对象,因为有单独的C++对象来访问数据,具体取决于我们是编写、迭代还是进行随机访问。类型的示例数据如下: 

BaseFloatMatrixWriter
RandomAccessBaseFloatMatrixReader
SequentialBaseFloatMatrixReader

  这些类型都是实际为模板类的typedef。脚本【.scp】文件或存档【.ark】文件都被视为数据表。格式如下:

    ·脚本格式是纯文本格式,其中包含带有键的行,然后是扩展文件名,该文件名告诉Kaldi在哪里可以找到数据。

    ·存档格式可以是文本或二进制。格式为键+空格+对象数据。

  有关脚本和档案的一些一般要点:

    ·指定如何读取表的字符串称为rspecifier。例如:ark:gunzip -c my/dir/foo.ark.gz|

    ·指定如何编写表的字符串称为wspecifier。例如:ark,t:foo.ark

    ·归档可以串联在一起,仍然是有效的归档。

    ·该代码可以顺序或通过随机访问读取脚本和存档。用户级代码仅知道它是在迭代还是在进行查找。它不知道它是在访问脚本还是存档。

    ·Kaldi不会尝试在归档文件中表示对象类型。必须提前知道对象类型。

    ·归档文件和脚本文件不能包含类型的混合。

    ·由于代码可能必须将对象缓存在内存中,因此通过随机访问读取档案可能会导致内存效率低下。

    ·为了有效地随机访问档案,可以使用ark,scp写入机制来写入相应的脚步文件。然后通过scp文件访问它。

    ·避免对文档进行随机访问时内存中缓存了大量数据。

    ·对代码文档进行排序并且按照顺序进行调用。

    ·读写档案的类型以Holder类型为模板,该类型知道如何读取和写入相关对象。

posted @ 2020-01-13 14:39  云山之巅  阅读(1385)  评论(0编辑  收藏  举报