数据准备-- 数据部分.

举个数据准备阶段关于“数据”部分的例子,请查看任何一个示例脚本目录下的data/train目录(假设你已经运行过一遍这些脚本了)。注意:目录名字data/train本身没有什么特别的。一些被命名为其他名字的目录,如data/eval2000(为一个测试集建立的),有几乎差不多的目录结构和文件格式(说“几乎”是因为在测试集的目录下,可能含有“sgm”和“glm”文件,用于sclite评分)。我们以Switchboard数据为例,对应脚本在egs/swbd/s5下。

s5# ls data/train cmvn.scp feats.scp reco2file_and_channel segments spk2utt text utt2spk wav.scp

不是所有的文件都同等重要。如果要设置简单点,分段(segmentation)信息是不必要的(即一个文件里只有一段发音),你只需要自己创建utt2spk、text和wav.scp,segments和reco2file_and_channel是可选的,根据实际需要决定是否创建。剩下的就都交给标准脚本。

下面我们会详细描述该目录下的这些文件。首先从那些需要你手动创建的文件开始。

需要手动创建的文件

文件“text”包含每段发音的标注。

s5# head -3 data/train/text sw02001-A_000098-001156 HI UM YEAH I'D LIKE TO TALK ABOUT HOW YOU DRESS FOR WORK AND sw02001-A_001980-002131 UM-HUM sw02001-A_002736-002893 AND IS

每行的第一项是发音编号(utterance-id),可以是任意的文本字符串,但是如果在你的设置中还包含说话人信息, 你应该把说话人编号(speaker-id)作为发音编号的前缀。这对于音频文件的排序非常重要。发音编号后面跟着的 是每段发音的标注。你不用保证这里出现的每一个字都出现在你的词汇表中。词汇表之外的词会被映射到data/lang/oov.txt中。 注意:尽管在这个特别的例子中,我们用下划线分割了发音编号中的“说话人”和“发音”部分,但是通常用破折号(“-”)会更安全 一点。这是因为破折号的ASCII值更小。有人向我指出说,如果使用下划线,并且说话人编号的长度不一,在某些特殊的情况下, 如果使用标准"C"语言风格对字符串进行排序,说话人编号和对应的发音编号会被排成不同的顺序。 另外一个很重要的文件是wav.scp。在Switchboard例子中,

s5# head -3 data/train/wav.scp sw02001-A /home/dpovey/kaldi-trunk/tools/sph2pipe_v2.5/sph2pipe -f wav -p -c 1 /export/corpora3/LDC/LDC97S62/swb1/sw02001.sph | sw02001-B /home/dpovey/kaldi-trunk/tools/sph2pipe_v2.5/sph2pipe -f wav -p -c 2 /export/corpora3/LDC/LDC97S62/swb1/sw02001.sph |

这个文件的格式是

<recording-id> <extended-filename>

其中,“extended-filename”可能是一个实际的文件名,或者就像本例中所述那样,是一段提取wav格式文件的命令。 extended-filename末尾的管道符号表明,整个命令应该被解释为一个管道。等会我们会解释什么是“recording-id”, 但是首先,我们需要指出,如果“segments”文件不存在,“wav.scp”每一行的第一项就是发音编号。 在Switchboard设置中,我们有“segments”文件,所以下面我们就讨论一下这个文件。

s5# head -3 data/train/segments sw02001-A_000098-001156 sw02001-A 0.98 11.56 sw02001-A_001980-002131 sw02001-A 19.8 21.31 sw02001-A_002736-002893 sw02001-A 27.36 28.93

"segments" 文件的格式是:

<utterance-id> <recording-id> <segment-begin> <segment-end>

其中,segment-begin和segment-end以秒为单位。它们指明了一段发音在一段录音中的时间偏移量。“recording-id” 和在“wav.scp”中使用的是同一个标识字符串。再次声明一下,这只是一个任意的标识字符串,你可以随便指定。 文件"reco2file_and_channel"只是在你用NIST的sclite工具对结果进行评分(计算错误率)的时候使用:

s5# head -3 data/train/reco2file_and_channel sw02001-A sw02001 A sw02001-B sw02001 B sw02005-A sw02005 A

格式为:

<recording-id> <filename> <recording-side (A or B)>

filename通常是.sph文件的名字,当然需要去掉sph这个后缀;但是也可以是任何其他你在“stm”文件中使用的标识字符串。 “录音方”(recording side)则是一个电话对话中两方通话(A或者B)的概念。如果不是两方通话,那么为保险起见最好 使用“A”。如果你并没有“stm”文件,或者你根本不知道这些都是什么东西,那么你可能就不需要reco2file_and_channel"文件。 最后一个需要你手动创建的文件是“utt2spk”。该文件指明某一段发音是哪一个说话人发出的。

s5# head -3 data/train/utt2spk sw02001-A_000098-001156 2001-A sw02001-A_001980-002131 2001-A sw02001-A_002736-002893 2001-A

文件格式是:

<utterance-id> <speaker-id>

注意一点,说话人编号并不需要与说话人实际的名字完全一致——只需要大概能够猜出来就行。 在这种情况下,我们假定每一个说话方(电话对话的每一方)对应一个说话人。这可能不完全正确—— 有时一个说话人会把电话交给另外一个说话人,或者同一个说话人会在不同的对话中出现——但是上述假定 对我们来说也足够用了。如果你完全没有关于说话人的信息,你可以把发音编号当做说话人编号。那么 对应的文件格式就变为```

```。 在一些实例脚本中还出现了另外一个文件,它在Kaldi的识别系统的建立过程中只是偶尔使用。在Resource Management (RM)设置中该文件是这样的:

s5# head -3 ../../rm/s5/data/train/spk2gender adg0 f ahh0 m ajp0 m

这个文件根据说话人的性别,将每个说话人编号映射为“m”或者“f”。 上述所有文件都应该被排序。如果没有排序,你在运行脚本的时候就会出现错误。在 \ref io_sec_tables 中我们解释了为什么需要这样。这与(Kaldi的)I/O框架有关,归根到底是因为排序后的文件可以在一些不支持 fseek()的流中——例如,含有管道的命令——提供类似于随机存取查找的功能。需要Kaldi程序都会从其他Kaldi命令 中读取多个管道流,读入各种不同类型的对象,然后对不同输入做一些类似于“合并然后排序”的处理。既然要合并排序, 当然需要输入是经过排序的。小心确保你的shell环境变量LC_ALL定义为“C”。例如,在bash中,你需要这样做:

export LC_ALL=C

如果你不这样做,这些文件的排序方式会与C++排序字符串的方式不一样,Kaldi就会崩溃。这一点我已经再三强调过了!

如果你的数据集中包含NIST提供的测试集,其中有“stm”和“glm”文件可以用作计算WER,那么你可以直接把这些文件拷贝 到数据目录下,并分别命名为“stm”和“glm”。注意,我们把评分脚本score.sh(可以计算WER)放到local/下, 这意味着该脚本是与数据集相关的。不是所有的示例设置下的评分脚本都能识别stm和glm文件。能够使用这些文件的一个 例子在Switchboard设置里,即 egs/swbd/s5/local/score_sclite.sh。如果检测到你有stm和glm文件该脚本会被顶层的评分脚本egs/swbd/s5/local/score.sh调用。

不需要手动创建的文件

数据目录下的其他文件可以由前述你提供的文件所生成。你可以用如下的一条命令创建“spk2utt”文件( 这是一条从egs/rm/s5/local/rm_data_prep.sh中摘取的命令):

utils/utt2spk_to_spk2utt.pl data/train/utt2spk > data/train/spk2utt

这是因为utt2spk和spk2utt文件中包含的信息是一样的。spk2utt文件的格式是:

<speaker-id> <utterance-id1> <utterance-id2> ....

下面我们讲一讲feats.scp文件.

s5# head -3 data/train/feats.scp sw02001-A_000098-001156 /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/raw_mfcc_train.1.ark:24 sw02001-A_001980-002131 /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/raw_mfcc_train.1.ark:54975 sw02001-A_002736-002893 /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/raw_mfcc_train.1.ark:62762

这个文件指向已经提取好的特征——在这个例子中所使用的是MFCC。feats.scp文件的格式是:

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

每一个特征文件保存的都是Kaldi格式的矩阵。在这个例子中,矩阵的维度是13(译者注:即列数;行数则 和你的文件长度有关,标准情况下帧长20ms,帧移10ms,所以一行特征数据对应10ms的音频数据)。第一行的“extended filename”, 即/home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/raw_mfcc_train.1.ark:24,意思是,打开存档(archive)文件 /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/raw_mfcc_train.1.ark , fseek()定位到24(字节),然后开始读数据。

feats.scp 文件由如下命令创建:

steps/make_mfcc.sh --nj 20 --cmd "$train_cmd" data/train exp/make_mfcc/train $mfccdir

该句被底层的run.sh脚本调用。命令中一些shell变量的定义,请查阅对应run.sh。$mfccdir是.ark文件将被写入的目录,由用户自定义。

data/train下最后一个未讲到的文件是cmvn.scp。该文件包含了倒谱均值和方差归一化的统计量,以说话人编号为索引。 每个统计量几何都是一个矩阵,在本例中是2乘以14维。在我们的例子中,有:

s5# head -3 data/train/cmvn.scp 2001-A /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/cmvn_train.ark:7 2001-B /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/cmvn_train.ark:253 2005-A /home/dpovey/kaldi-trunk/egs/swbd/s5/mfcc/cmvn_train.ark:499

与feats.scp不同,这个scp文件是以说话人编号为索引,而不是发音编号。该文件由如下的命令创建:

steps/compute_cmvn_stats.sh data/train exp/make_mfcc/train $mfccdir

(这个例子来自 egs/swbd/s5/run.sh).

因为数据准备阶段的错误会影响后续脚本的运行,所以我们有一个脚本数据目录的文件格式是否 正确。运行:

utils/validate_data_dir.sh data/train

你可能会发现下面这个命令也很有用:

utils/fix_data_dir.sh data/train

(当然可对任何数据目录使用该命令,而不只是data/train)。该脚本会修复排序错误,并会移除那些被指明需要特征数据或标注,但是却找不到被需要的数据的那些发音(utterances)。

results matching ""

    No results matching ""