你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

BrainScript CNTK文本格式读取器

本页从 BrainScript 的角度记录 CNTKTextFormatReader,但 Python 用户也可以通过阅读本文档来学习 -- 概念、参数和模式都是相同的。

CNTKTextFormatReader (稍后只需 CTF 读取器) 即可使用根据以下规范设置格式的输入文本数据。 它支持以下主要功能:

  • 每个文件 (输入) 多个输入流
  • 稀疏和密集输入
  • 可变长度序列

CNTK文本格式 (CTF)

输入文件中的每一行都包含一个用于一个或多个输入的示例。 由于 (显式或隐式) 每个行也附加到序列,因此它定义一个或多个 <序列、输入、样本> 关系。 每个输入行的格式必须如下所示:

[Sequence_Id](Sample or Comment)+

where

Sample=|Input_Name (Value )*

Comment=|# some content

  • 每行以序列 ID 开头,并包含一个或多个示例 (,换而言之,每行都是) 的无序样本集合。
  • 序列 ID 是一个数字。 可以省略它,在这种情况下,行号将用作序列 ID。
  • 每个示例实际上是一个键值配对由输入名称组成,相应的值向量 (映射到更高维度) 作为网络本身的一部分完成。
  • 每个示例都以管道符号开头, (|) 后跟输入名称 (没有空格) ,后跟空格分隔符,然后是值列表。
  • 每个值是稀疏输入的数字或索引前缀的数字。
  • 制表符和空格都可以互换用作分隔符。
  • 批注以管道开头,后跟哈希符号: |#然后是实际内容 (正文) 批注。 正文可以包含任何字符,但是需要通过将哈希符号追加到正文中的管道符号来转义, (请参阅以下示例) 。 批注正文一直持续到行尾或下一个未转义管道,以先行为准。

简单示例

此示例基于最小一组参数和格式选项。

若要使用 CTF 读取器,readerType请在CNTK配置的读取器部分中设置:CNTKTextFormatReader

...
reader = [
    readerType = "CNTKTextFormatReader"
    file = "c:\mydata\SampleInput.txt" # See the second example for Linux path example

    # IMPORTANT!
    # All inputs are grouped within "input" sub-section.
    input = [
        A = [
            dim = 5
            format = "dense"
        ]
        B = [
            dim = 1000000
            format = "sparse"
        ]
        C = [
            dim = 1
            format = "dense"
        ]
    ]
]
# the rest of the cntk config ...

(本文档中此片段和其他 NDL 示例仅reader显示一节,省略CNTK配置的其余部分;有关指向一组完整示例网络和相应数据集)

CTF 读取器需要以下一组参数:

  • file - 包含数据集的文件的路径。
  • input- 定义输入名称 (A标识的输入的子节, BC并在上面的示例中) 。 在每个输入中,必须指定以下必需参数:
    • format - 指定输入类型。 dense必须是或sparse
    • dim - 为 密集 输入指定输入值向量 (的维度,这直接对应于每个样本中的值数,对于 稀疏 ,这表示) 可能索引值范围的上限。

与上述读取器配置对应的输入数据应如下所示:

|B 100:3 123:4 |C 8 |A 0 1 2 3 4 |# a CTF comment
|# another comment |A 0 1.1 22 0.3 54 |C 123917 |B 1134:1.911 13331:0.014
|C -0.001 |# a comment with an escaped pipe: '|#' |A 3.9 1.11 121.2 99.13 0.04 |B 999:0.001 918918:-9.19

请注意以下有关输入格式的信息:

  • |Input_Name 标识每个输入示例的开头。 此元素是必需的,后跟对应值向量。
  • 密集向量只是浮点值的列表;稀疏向量是元组的列表 index:value
  • 输入向量) 以及 输入 分隔符之间 (输入) 之间,选项卡和空格都允许作为值分隔符 (。
  • ) 下面的扩展示例中介绍了每个单独的行构成长度为 1 (“Real”可变长度序列的“序列”。
  • 每个输入标识符只能在单个行上显示一次, (每行要求每个输入转换为 一个样本) 。
  • 在概念上,行内输入样本的顺序并不重要 (,每行都是键值对的无序集合)
  • 每个格式良好的线条必须以“换行符” \n 或“回车符、换行符” \r\n 符号结尾。

扩展示例

此示例包含所有可能的配置参数,并显示各种输入格式选项。 有关此示例中使用的配置参数的完整说明,请参阅 下表

...
precision="double"

reader = [
    readerType = "CNTKTextFormatReader"
    file = "/home/mydata/SampleInput.txt" # See the first example for Windows style path example
    randomize = true
    randomizationWindow = 30
    skipSequenceIds = false
    maxErrors = 100
    traceLevel = 2

    chunkSizeInBytes = 1024

    keepDataInMemory = true
    frameMode = false

    input = [
        Some_very_long_input_name = [
            alias = "a"
            dim = 3
            format = "dense"
        ]
        Some_other_also_very_long_input_name = [
            alias = "b"
            dim = 2
            format = "dense"
        ]
    ]
]
# the rest of the cntk config ...

使用复合读取器,如下所示:

reader = {
        verbosity = 0 ;
        randomize = true;
        randomizationWindow=30
        deserializers = ({
            type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
            file = "/home/mydata/SampleInput.txt" # See the first example for Windows style path example
            maxErrors = 100
            skipSequenceIds = false
            traceLevel = 2
            input = {
                qu1fea = {alias = "qui"; dim = 95589; format = "sparse"}
                qu2fea = {alias = "quj"; dim = 95589; format = "sparse"}
                pairweight = {alias = "wij"; dim = 1; format = "dense"}
            }
        })
    }

然后,相应的输入文件可以大致如下所示:

100 |a 1 2 3 |b 100 200
100 |a 4 5 6 |b 101 201
100 |b 102983 14532 |a 7 8 9
100 |a 7 8 9
200 |b 300 400 |a 10 20 30
333 |b 500 100
333 |b 600 -900
400 |a 1 2 3 |b 100 200
|a 4 5 6 |b 101 201
|a 4 5 6 |b 101 201
500 |a 1 2 3 |b 100 200

以上示例中讨论的所有选项仍在此处应用。 除此之外,我们引入了两个附加功能:

输入名称别名

输入名称可以任意长,因此在整个输入文件中重复这些名称可能没有空间效率。 为了缓解这种情况,数据集可以使用“别名”而不是完整的输入名称。 然后,需要在每个输入子节中指定别名。 在我们的示例中,数据集使用别名,这些b别名a分别映射到读取器配置部分中的“Some_very_long_input_name”和“Some_other_also_very_long_input_name”。

序列 ID

如前所述,输入文件中的每一行表示一个 序列 ,其中包含每个输入的单个样本。 但是,如果行以非负数为前缀,则数字用作相应的 序列 ID。共享相同序列 ID 的所有后续行将合并在一起,成为同一序列的一部分。 因此,对 N 行重复相同的数字前缀可以生成多样本序列,每个输入包含 1 到 N 个样本。 省略第二行和以下行的序列前缀具有相同的效果。 因此,上面的示例数据集定义了 ID100200、和 333400500五个序列

将读取器节中的参数设置为 skipSequenceIdstrue 强制读取器忽略数据集中的所有显式序列 ID,并将单独的行视为单个序列。 此外,省略数据集中第一行的序列 ID 具有相同的效果 -- 将忽略所有后续序列 ID,将被视为单个序列的行,如以下示例所示:

|a 1 2 3 |b 100 200
100 |a 4 5 6 |b 101 201
200 |b 102983 14532 |a 7 8 9

使用序列时要考虑的一些最终事项:

  • 序列 ID 必须是唯一的。
  • ID 前缀只能针对连续行重复。
  • 行 (的序列长度(即,共享相同 ID 前缀的行数) 不能超过样本的最大输入长度, (此序列中输入) 中的样本数。

例如,以下数据集 无效

100 |a 1 2 3 |b 100 200
200 |a 4 5 6 |b 101 201
100 |b 102983 14532 |a 7 8 9

123 |a 1 2 3 |b 100 200
456 |a 4 5 6
456 |b 101 201

几个Real-World示例

  • 分类:每行都包含一个示例,其中包含一个标签和特征。 不需要序列 ID,因为每一行都是其自己的长度 1 的“序列”。
|class 23:1 |features 2 3 4 5 6
|class 13:1 |features 1 2 0 2 3
...
  • DSSM:每行都包含源目标文档配对,通过一袋单词表示,编码为稀疏向量。
|src 12:1 23:1 345:2 45001:1    |tgt 233:1 766:2 234:1
|src 123:1 56:1 10324:1 18001:3 |tgt 233:1 2344:2 8889:1 2234:1 253434:1
  • 部分语音标记:序列将每个元素映射到相应的标签。 序列垂直对齐 (每行一个单词 + 标记) 。
0 |word 234:1 |tag 12:1
0 |word 123:1 |tag 10:1
0 |word 123:1 |tag 13:1
1 |word 234:1 |tag 12:1
1 |word 123:1 |tag 10:1
...
  • 序列分类:映射到单个标签的序列。 序列垂直对齐;“class”标签可以出现在具有相同 sequenceId 的任何行中。

注意

目前,行数不能超过最长序列的长度。 这意味着标签不能单独出现在行上。 这是将来将解除的实现细节。

0 |word 234:1 |class 3:1
0 |word 123:1
0 |word 890:1
1 |word 11:1 |class 2:1
1 |word 344:1
  • 序列到序列:将源序列映射到目标序列。 这两个序列垂直对齐,在最简单的情况下,只是在另一个之后打印。 它们通过具有相同的总体“序列 ID” (联接,在这种情况下,) 成为“工作单元 ID”。

注意

目前,行数不能超过最长序列的长度。 这意味着序列必须水平对齐。 这是将来将解除的实现细节。

0 |sourceWord 234:1  |targetWord 344:1
0 |sourceWord 123:1  |targetWord 456:1
0 |sourceWord 123:1  |targetWord 2222:1
0 |sourceWord 11:1
1 |sourceWord 123:1
...
  • Learning排名:“序列”表示查询,每个示例都有一个带有手标分级的文档。 在这种情况下,“序列”只是一个多集, (在学习到排名损失函数的上下文中) 没有排序。
0 |rating 4 |features 23 35 0 0 0 21 2345 0 0 0 0 0
0 |rating 2 |features 0 123 0 22 44 44 290 22 22 22 33 0
0 |rating 1 |features 0 0 0 0 0 0 1 0 0 0 0 0
1 |rating 1 |features 34 56 0 0 0 45 1312 0 0 0 0 0
1 |rating 0 |features 45 45 0 0 0 12 335 0 0 0 0 0
2 |rating 0 |features 0 0 0 0 0 0 22 0 0 0 0 0
...

配置参数

参数 说明
precision 指定输入值的浮点精度 (doublefloat) 。 可选,默认值为 float.

reader 部分

参数 说明
readerType 指定一个受支持的CNTK读取器来加载 (, CNTKTextFormatReader 例如) 。 “必需”。
file 包含输入数据集 (Windows或 Linux 样式) 的文件的路径。 “必需”。
randomize 指定输入是否应随机化 (truefalse) 。 可选,默认值为 true.
randomizationSeed 当输入数据重新随机化) 时,初始随机化种子值 (递增。 可选,默认值为 0.
randomizationWindow 指定随机化窗口的大小 (正整数) (,即随机化范围) 。 此参数会影响数据集一次驻留在内存中的多少。 可选,具体取决于 sampleBasedRandomizationWindow 值,默认值为样本中整个数据集的大小 (,即,当 (区块大小等于 32MB) 时,整个数据集) ) 随机化输入,或 4GB 的磁盘空间值(即 128 区块大小等于 32MB) )。 This parameter is ignored when randomize is false.
sampleBasedRandomizationWindow 如果 true,随机化窗口的大小将解释为一定数量的样本,否则为多个区块。 可选,默认值为 false. Similarly to randomizationWindow, this parameter is ignored, when randomize is false.
skipSequenceIds 如果 true,读取器将忽略输入文件中的序列 ID,将每个单独的行解释为大小为 1 的独立序列, (查看序列 ID) 部分可选,默认值为 false.
maxErrors 应引发异常的输入错误数。 可选,默认为 0,这意味着第一个格式不正确的值将触发异常。
traceLevel 输出详细级别。 0 - 仅显示错误; 1 - 显示错误和警告; 2 - 显示所有输出。 可选,默认值为 1.
chunkSizeInBytes 单个读取操作中要从磁盘读取的连续字节数。 可选,默认为 33554432 (32MB) 。
keepDataInMemory 如果 true,整个数据集将缓存在内存中。 可选,默认值为 false.
frameMode true 指示读取器使用针对仅包含单个样本) 的帧 (序列优化的打包方法。 可选,默认值为 false.
cacheIndex 指定在预处理阶段生成的元数据是否应写入磁盘,并在可用 (truefalse 时从磁盘加载,) 。 可选,默认值为 false. 有关更多详细信息,请参阅下面的部分。 CNTK版本 2.1 中的新增功能。
索引缓存

注意

CNTK版本 2.1 中的新增功能。

索引缓存允许以 2-3 倍) 显著 (减少启动时间,尤其是在处理大型输入文件时。 将 cacheIndex 标志设置为 true 指示读取器将索引元数据写入磁盘, (与输入文件相同的目录,) 缓存文件不可用,或者如果缓存文件) 早于输入文件 (过时。 编写是尽力的,在单独的线程上执行,以不影响读取器性能。 如果缓存文件存在且是最新的,则读取器将不再浏览输入文件以生成索引,而是从缓存文件加载索引。 请注意,某些读取器配置参数对索引 (有直接影响,不同的值 frameMode 可能会导致具有不同序列数的索引) 。 因此,读取器可以忽略缓存文件,其配置不同于生成缓存的配置。 若要查看缓存的完整优势,不应在后续重新运行时修改配置。

input 子节

input 将多个单独的输入组合在一起,每个输入都有一个适当标记的配置子部分。 下面介绍的所有参数都特定于与特定输入关联的 输入名称 子节。

参数 说明
alias 用于标识数据集中的输入的替代简写名称 (字符串) 。 可选
format 指定输入类型 (densesparse) 。 “必需”。
dim 维度 (输入 (值的正整数) ,即样本中 密集 输入的输入值数、 稀疏 输入) 的索引范围的上限。 “必需”。
definesMBSize 标志 (默认 false) ,指示是否应在来自此特定流的样本中计算小块大小 (可选)。

你将在CNTK存储库中找到完整的网络定义相应的数据集示例。 在那里,还可以找到使用 CNTKTextFormat 读取器的 端到端测试