此页面从命令行工具用户的角度描述了Kaldi中的I / O机制。
有关更多代码级概述,请参见Kaldi I / O机制。
总览
非表I / O
我们首先描述“非表” I / O。这是指仅包含一个或两个对象的文件或流(例如,声学模型文件;转换矩阵),而不是由字符串索引的对象的集合。
- Kaldi文件格式默认为二进制,但是如果提供标志–binary = false,则程序将输出非二进制文件。
- 许多对象都有相应的“复制”程序,例如copy-matrix或gmm-copy,可与–binary = false标志一起使用以转换为文本形式,例如“ copy-matrix --binary = false foo.mat-” 。
- 磁盘上的文件与内存中的C ++对象(例如,浮点矩阵)之间通常存在一一对应的关系,尽管某些文件包含多个对象(例如:对于声学模型文件,通常是TransitionModel对象然后是声学模型)。
- Kaldi程序通常知道他们希望读取哪种类型的对象,而不是从流中计算出来。
- 与perl相似,文件名可以替换为-(用于标准输入/输出)或诸如“ | gzip -c> foo.gz”或“ gunzip -c foo.gz |”之类的字符串。
- 对于读取文件,我们还支持foo:1045之类的东西,这意味着文件foo中的字符偏移量1045。
- 为了引用扩展文件名的概念,通常将特殊术语“ rxfilename”用于描述要读取的流(即文件,流或标准输入)的字符串,并将“ wxfilename”用于描述字符串的描述输出流。有关更多详细信息,请参见扩展文件名:rxfilenames和wxfilenames。
为了说明上述概念,请确保$ KALDI_ROOT / src / bin在路径上,其中$ KALDI_ROOT是存储库的顶部,然后键入以下内容:
回声'[0 1]'| 复制矩阵--
它将打印出一条日志消息和一些与该矩阵相对应的二进制数据。现在尝试:
回声'[0 1]'| 复制矩阵--binary = false--
输出将如下所示:
#复制矩阵--binary = false-- 复制矩阵--binary = false-- [ 0 1] LOG(copy-matrix:main():copy-matrix.cc:68)复制到-
尽管看起来矩阵和日志消息混合在一起,但是日志消息属于标准错误,因此不会传递到管道中。为了避免看到日志消息,您可以通过在命令行中添加2> / dev / null将stderr重定向到/ dev / null。
可以使用管道或使用Kaldi I / O的文件流机制连接Kaldi程序。这是一个管道示例:
回声'[0 1]'| 复制矩阵--| 复制矩阵--binary = false--
这将以文本形式输出矩阵(第一个copy-matrix命令转换为二进制形式,第二个转换为文本形式,这毫无意义)。您可以通过以下操作以更复杂的方式完成同一件事:
复制矩阵'echo [0 1] |' '| copy-matrix --binary = false--'
这里没有理由这样做,但是当程序具有多个输入或输出,因此已经使用了stdin或stdout时,它有时会很有用。对于表尤其有用(请参阅下一节)。
表I / O
Kaldi具有特殊的I / O机制,用于处理由字符串索引的对象的集合。这样的示例是通过说话者ID索引的特征矩阵,或通过说话者ID索引的说话者自适应转换矩阵。索引集合的字符串必须为非空且无空格。有关更深入的讨论,请参见表概念。
表可能以两种形式存在:“存档”或“脚本文件”。不同之处在于,存档实际上包含数据,而脚本文件指向数据的位置。
从表中读取的程序期望一个称为“ rspecifier”的字符串,该字符串表示如何读取索引数据,而写入表中的程序期望一个称为“ wspecifier”的字符串来写入它。这些是用于指定需要脚本文件还是归档文件的字符串,以及文件位置以及各种选项。rspecifier的常见类型包括“ ark:-”,这意味着从标准输入中以存档形式读取数据,或“ scp:foo.scp”,这意味着脚本文件foo.scp表示从何处读取数据。需要牢记的几点是:
- 冒号后面的部分被解释为wxfilename或rxfilename(如Non-table I / O中一样),这意味着支持管道和标准输入/输出之类的东西。
- 表格始终只包含一种类型的对象(例如,浮点矩阵)。
- 您可能会在rspecifiers和wspecifiers上看到选项,主要是:
- 在rspecifiers中,ark,s,cs:-表示当我们从这种情况下(从标准输入中)读取时,我们期望键是按排序顺序(,s)进行的,并且我们断言它们将按排序顺序进行访问(, cs)表示我们知道程序将按排序顺序访问它们(如果不满足这些条件,程序将崩溃)。这使Kaldi可以模拟随机访问而不会占用大量内存。
- 对于不太大且不便于确保排序顺序的数据(例如,用于说话人适应的转换),省略.s,cs几乎没有什么害处。
- 通常,带有多个rspecifier的程序将迭代第一个对象中的对象(顺序访问),并在后一个对象上进行随机访问,因此第一个rspecifier通常不需要“,s,cs”。
- 在scp,p:foo.scp中,.p表示如果某些引用的文件不存在,则我们不应崩溃(对于存档,如果存档已损坏或被截断,.p可以防止崩溃。)
- 对于书写,选项,t表示文本模式,例如ark,t:-。–binary命令行选项对归档无效。
- 脚本文件格式在每一行上都是“ <key> <rspecifier | wspecifier>”,例如“ utt1 / foo / bar / utt1.mat”。rspecifier或wspecifier可以包含空格,例如“ utt1 gunzip -c /foo/bar/utt1.mat.gz |”。
- 存档格式为:<key1> <object1> <newline> <key2> <object2> <newline> ...
- 归档文件可能已被合并,它们仍然是有效的归档文件,但是请注意串联的顺序,例如,避免
“猫a / b / *。ark”
如果您需要排序的订单。 - 尽管不常用,但脚本文件可用于输出,例如,如果我们写入wspecifier scp:foo.scp,并且程序尝试写入键utt1,它将在foo.scp中查找类似于“ utt1 some_file”的行,并将其写入“ some_file”。如果没有这样的行,它将崩溃。
- 可以同时写入存档和脚本,例如ark,scp:foo.ark,foo.scp。脚本文件将以“ utt1 foo.ark:1016”这样的行写入(即,它指向档案中的字节偏移量)。当要以随机顺序或部分访问数据但您不想产生很多小文件时,这很有用。
- 可以欺骗存档机制以对单个文件进行操作。例如,
回声'[0 1]'| 复制矩阵'scp:echo foo-|' 'scp,t:echo foo-|'
这值得一点解释。首先,rspecifier“ scp:echo foo-|” 如果文件bar.scp仅包含“ foo-”行,则等效于scp:bar.scp。这告诉它从标准输入中读取由“ foo”索引的对象。类似地,对于wspecifier“ scp,t:echo foo-|”,它将“ foo”的数据写入标准输出。此技巧不应过度使用。在这种特殊情况下,这是没有必要的,因为我们已经使复制矩阵程序直接支持非表I / O,因此您可以只编写“复制矩阵--”。如果您必须过多使用此技巧,最好修改相关程序。 - 如果要从存档中仅提取一个成员,则可以对“ scp:” wspecifier使用“,p”选项,以使其仅写出该元素,而忽略scp文件中其他缺少的元素。假设您想要的键是“ foo_bar”,并且一个名为some_archive.ark的存档包含矩阵,那么您可以按以下方式提取该元素:
复制矩阵'ark:some_archive.ark''scp,t,p:echo foo_bar-|'
- 在某些情况下,档案读取代码允许有限的类型转换,例如对于矩阵,在float和double之间转换,对于晶格,则使用Lattice和CompactLattice。
表I / O(带范围)
现在可以从scp文件中指定矩阵的行范围和列范围。转储功能文件时,通常将它们表示为看起来像如下的scp文件:
utt-00001 /some/dir/feats.scp:0 utt-00002 /some/dir/feats.scp:16402 ...
您可以通过添加行和列范围来修改此scp文件,其格式类似于MATLAB(除了从零开始的索引)。因此,例如,如果将其修改为:
utt-00001 /some/dir/feats.scp:0[0:9] utt-00001 /some/dir/feats.scp:0[10:19] ...
前两行代表utt-00001的第0至9行以及第10至19行。您可以用类似的方式表示列索引:
utt-00001 /some/dir/feats.scp:0[:,0:12] utt-00001 /some/dir/feats.scp:0[:,13:25] ...
将是该文件的0到12列以及13到25列。您还可以结合使用行索引和列索引:例如,
utt-00001 /some/dir/feats.scp:0[10:19,0:12]
说话者对说话者和说话者对说话的地图。
许多Kaldi程序会使用发声到说话者和发话者到说话者的地图-称为“ utt2spk”或“ spk2utt”的文件。这些通常由命令行选项–utt2spk和–spk2utt指定。utt2spk映射具有以下格式
utt1 spk_of_utt1 utt2 spk_of_utt2 ...
并且spk2utt映射具有以下格式
spk1 utt1_of_spk1 utt2_of_spk1 utt3_of_spk1 spk2 utt1_of_spk2 utt2_of_spk2 ...
这些文件用于说话人调整,例如,查找哪个说话人对应于话语,或遍历说话人。由于大多数原因与设置Kaldi示例脚本的方式以及将数据分为多个部分的方式有关,因此重要的是要确保发话者对讲者图中的讲话者处于排序顺序(请参阅数据准备)。)。无论如何,这些文件实际上都被视为存档,因此,您将看到命令行选项,例如–utt2spk = ark:data / train / utt2spk。您将看到这些文件符合以下格式的通用存档格式:“ <key1> <data> <newline> <key2> <data> <newline>”,在这种情况下,数据为文本格式。在代码级别,utt2spk文件被视为包含字符串的表,而spk2utt文件被视为包含字符串列表的表。