你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
BrainScript 和 Python:了解和扩展读者
从版本 1.5 开始,CNTK 正从整体读取器设计转向更可组合的模型,使你可以指定和撰写不同格式的输入数据。
以前,每个读取器都负责数据读取的不同方面,包括但不限于:
- 将数据从外部存储反序列化到内存中表示形式
- 整个料库的随机化
- (输入序列/样本的不同转换,例如裁剪或缩放图像)
- (帧、序列或截断的 BPTT) 为不同模式创建小型巴切,其布局可由 GPU 使用
- 预提取小块和 IO 区块级别
在版本 1.5 中,上述功能的主要部分被分解,并移动到核心 CNTK,以便在不同的读取器之间共享。 此版本还引入了两种可以扩展的主要抽象,以支持新的数据格式:
- 反序列化程序 - 负责将外部存储输入反序列化为内存中序列
- 转换 - 它将输入序列转换为输出序列
在接下来的部分中,我们将更详细地讨论这些抽象。
在 Python 中配置读取器 (微型批处理源)
本部分提供了一些示例,介绍了如何在 Python 中配置复合读取器 (即 MinibatchSource) 。
下面的示例改编自 AlexNet_ImageNet_Distributed.py,它显示了 与 Transforms 部分中的 AlexNet 读取器等效的 Python。
import cntk.io
mean_file = ...
map_file = ...
# model dimensions
image_height = 227
image_width = 227
num_channels = 3 # RGB
num_classes = 1000
transforms = [
ImageDeserializer.crop(crop_type='randomside',
side_ratio=0.88671875,
jitter_type='uniratio'),
ImageDeserializer.scale(width=image_width,
height=image_height,
channels=num_channels,
interpolations='linear'),
ImageDeserializer.mean(mean_file)
]
reader = MinibatchSource(
ImageDeserializer(map_file, StreamDefs(
# first column in map file is referred to as 'image'
features = StreamDef(field='image', transforms=transforms),
# and second as 'label'
labels = StreamDef(field='label', shape=num_classes))))
下面的示例 (改编自 A2_RunCntk_py3.py) 演示了如何将多个反序列化器组合在一起。
n_rois = 100
n_classes = 17
rois_dim = 4 * n_rois
label_dim = n_classes * n_rois
map_file = ...
roi_file = ...
label_file = ...
# read images
scale = ImageDeserializer.scale(width=1000,
height=1000,
channels=3,
scale_mode="pad",
pad_value=114,
interpolations='linear')
image_source = ImageDeserializer(map_file)
image_source.ignore_labels()
image_source.map_features('features', [scale])
# read rois and labels
roi_source = CTFDeserializer(roi_file)
roi_source.map_input('rois', dim=rois_dim, format="dense")
label_source = CTFDeserializer(label_file)
label_source.map_input('roiLabels', dim=label_dim, format="dense")
# define a composite reader
reader = MinibatchSource([image_source, roi_source, label_source])
...
# define mapping from reader streams to network inputs
input_map = {
image_input: reader.streams.features,
roi_input: reader.streams.rois,
label_input: reader.streams.roiLabels
}
BrainScript
反序列化程序
让我们从端到端 LSTM/FullUtterance 测试中查看 HTKMLFReader 的以下配置片段, (此处的完整配置) :
...
# Old reader config. For illustration only.
reader = [
readerType = "HTKMLFReader"
readMethod = "blockRandomize"
nbruttsineachrecurrentiter = 32
randomize = "auto"
verbosity = 0
features = [
dim = 363
type = "real"
scpFile = "$DataDir$/glob_0000.scp"
]
labels = [
mlfFile = "$DataDir$/glob_0000.mlf"
labelMappingFile = "$DataDir$/state.list"
labelDim = 132
labelType = "category"
]
]
此配置片段声明一个读取器,该读取器生成两个具有名称和"features"
"labels"
名称的数据流。 它采用输入两种类型的文件:
- HTK 分析中已知的功能文件列表,该文件
scp
(“script”文件) - 称为
mlf
文件 (“主标签文件”的标签文件)
在上述配置片段中,没有定义反序列化方式 scp
或 mlf
格式的显式实体。
所有内容都封装在 HTKMLFReader 配置中。
因此,如果需要同时公开其他不同数据格式 scp
的输入流, mlf
则需要更改 HTKMLFReader 并添加支持。
为了提高可组合性和重用性,同一输入 的新 配置显式定义反序列化器和它们生成的输入流:
reader = [
verbosity = 0
randomize = true
# A list of deserializers the reader uses.
deserializers = (
[
# Type of deserializer, in this case the one that knows
# how to deserialize HTK feature files.
type = "HTKFeatureDeserializer"
# Module (.dll or .so) where this deserializer is implemented
module = "HTKDeserializers"
# Description of input streams the deserializer provides,
# can be one or many, depending on a particular
# deserializer implementation
# For HTKFeatureDeserializer, just one stream can be described.
input = [
# Description of input stream to feed the Input node named "features"
features = [
dim = 363
scpFile = "$DataDir$/glob_0000.scp"
]
]
]:
[
# Type of deserializer, in this case the one
# that knows how to deserialize mlf files.
type = "HTKMLFDeserializer"
module = "HTKDeserializers"
# Description of input streams the deserializer provides,
# For HTKMLFDeserializer, just one stream can be described.
input = [
# Description of input stream to feed the Input node named "labels"
labels = [
dim = 132
mlfFile = "$DataDir$/glob_0000.mlf"
labelMappingFile = "$DataDir$/state.list"
# whether phone boundary information should be encoded
# set to true in CTC-type training
phoneBoundaries=false
]
]
]
)
]
由htk
反序列化程序生成的mlf
序列根据其逻辑键 (组合在一起,这是唯一标识语音话语的字符串,并且同时存在于scp
mlf
文件) 中。
如果需要另一个不同格式的流,只需将相应的反序列化程序添加到配置 (HTK 功能和 HTK MLF 反序列化程序就不可能立即公开每个) 的多个输入流。
注意
目前,支持旧读取器配置和新读取器配置。 当读取器配置中使用“反序列化程序”键时,读取器类型将隐式设置为“CompositeDataReader”。 若要确保可以在 Windows 上加载 CompositeDataReader 模块, Cntk.Composite.dll
应位于 CNTK 可执行文件所在的同一目录中。 Cntk.Composite.so
Linux 上应位于lib
与包含 CNTK 可执行文件的文件夹并排bin
所在的文件夹中。
目前 CNTK 支持以下反序列化程序:
反序列化程序类型 | 模块 | 描述 |
---|---|---|
HTKFeatureDeserializer | HTKDeserializers | HTK 功能文件的反序列化程序 |
HTKMLFDeserializer | HTKDeserializers | HTK MLF 文件的反序列化程序 |
ImageDeserializer | ImageReader | 编码为纯文件或 zip 存档中的图像的反序列化程序。 |
Base64ImageDeserializer | ImageReader | 映射文件中编码为 base64 字符串的图像的反序列化程序。 |
CNTKTextFormatDeserializer | CNTKTextFormatReader | CNTK 文本文件的反序列化程序 |
CNTKBinaryFormatDeserializer | CNTKBinaryReader | CNTK 二进制格式化文件的反序列化程序 |
有关配置参数的完整说明,请参阅 下表 。
转换
转换是一个简单的抽象,采用序列作为输入,在序列中执行样本的一些转换,并返回输出序列。 转换的典型示例是图像的不同转换,例如裁剪、缩放或转置。 可以根据输入配置转换。
让我们看看如何将转换应用到输入 (配置从 Tests/EndToEndTests/Image/AlexNet 测试) :
deserializers = ([
type = "ImageDeserializer"
module = "ImageReader"
# Map file which maps images to labels
file = "$ConfigDir$/train_map.txt"
# Description of input streams
input = [
# Description of input stream to feed the Input node named "features"
features = [
transforms = (
[
type = "Crop"
# Possible values: Center, RandomSide, RandomArea, Multiview10. Default: Center
cropType = "RandomSide"
# Crop scale side ratio.
sideRatio = 0.875
# Crop scale ratio jitter type
jitterType = "UniRatio"
]:[
type = "Scale"
width = 224
height = 224
channels = 3
# Interpolation to use when scaling image to width x height size.
interpolations = "linear"
]:[
type = "Mean"
# Stores mean values for each pixel in OpenCV matrix XML format.
meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
]:[
# Changes the image layout from HWC to CHW
type = "Transpose"
]
)
]
# Description of input stream to feed the Input node named "labels"
labels = [
labelDim = 1000
]
]
]
])
在此配置中,四个转换应用于输入流 features
。
最初,图像数据反序列化程序生成由 HWC 表示形式的单个图像组成的序列。
之后,将按顺序排列的转换列表应用于图像:首先是 裁剪 转换,后跟 Scale 和 Mean。
最后一个转换是转 置 ,用于将图像布局从 HWC 更改为 CHW。
目前已实现以下转换。 有关其详细说明,请参阅 ImageReader。
转换类型 | 模块 |
---|---|
Crop | ImageReader |
缩放 | ImageReader |
Color | ImageReader |
平均值 | ImageReader |
转置 | ImageReader |
新的读取者配置格式说明
用于编写多个数据反序列化器的读取器配置部分如下所示:
reader = [
randomize = true|false
verbosity = 0|1|2
...
deserializers = (
[<deserializerConfiguration1>]:
[<deserializerConfiguration2>]:
...
[<deserializerConfigurationN>]
)
]
每个反序列化程序配置都指定为:
[
module = "<readerModuleName>" # Name of the external module (.dll or .so) where this particular deserializer is implemented
type = "<deserializerType>" # The type of the deserializer
# There could be more deserializer-specific options in this section
# Date deserializer input - describes a set of streams this deserializer produces.
# It can be one (as in HTK) or many (as in CNTKTextFormat)
input = [
# Replace 'InputNameN' by the name of the corresponding input node in the network.
InputName1 = [<inputConfiguration>]
InputName2 = [<inputConfiguration>]
...
]
]
输入配置包含输入特定的选项,以及(可选)应用于输入的转换有序列表:
[
# Per-input data deserializer-specific options
# Optionally a pipeline of transformations, to be implemented by data deserializer's reader module:
transforms = (
[<transformationConfiguration1>]:
[<transformationConfiguration2>]:
...
[<transformationConfigurationN>]
)
]
转换配置标识转换类型和任何特定于转换的选项:
[
type = "<transformName>"
# Transform-specific options
]
配置选项
常规读取器配置
参数 | 说明 |
---|---|
verbosity |
详细级别 (0 、 1 2 ) 控制不同组件的诊断输出, (Randomizer、Deserializer、Bundler 等) 可选,默认为 0 a0/>。 |
randomize |
指定是否应随机化输入 ( true , false ) 。 随机化方法与 HTKMLFReader 的 blockRandomize 相同。 可选,默认值为 true . |
randomizationSeed |
当输入数据重新随机化) 时,初始随机化种子值 (递增。 可选,默认值为 0 . |
randomizationWindow |
指定随机化窗口的大小 (正整数) (,即随机化范围) 。 此参数会影响数据集一次驻留在内存中的多少。 (可选)默认为样本或区块中 整个数据集 的大小 (,具体取决于 sampleBasedRandomizationWindow 值) 。 但是,如果其中一个反序列化器未CNTKTextFormatDeserializer sampleBasedRandomizationWindow 显式设置为true ,randomizationWindow 则默认为128 (,这是大约 4GB 磁盘空间的区块) 。 如果 randomize 为 false ,则忽略此参数。 |
sampleBasedRandomizationWindow |
如果 true ,随机化窗口的大小将解释为一定数量的样本,否则解释为多个区块。 可选,默认为true CNTKTextFormatDeserializer 在反序列化程序列表中不存在,否则为false 不存在。 与randomizationWindow 此参数类似,当为 false a0/> 时randomize ,将忽略此参数。 |
truncationLength |
指定 BPTT (正整数) 样本中的截断长度。 仅当为 true 时truncated ,才必需,否则将被忽略。 |
multiThreadedDeserialization |
指定在从反序列化器 (收集小包序列时,是否应使用多个线程,true false ) 。 可选。 |
frameMode |
指定是否应在帧或序列级别随机化并返回数据。 当 true 输入序列拆分为帧时。 可选。 这两者frameMode 都不能同时设置为true 。truncated |
truncated |
启用 true 通过时间截断的反向传播 (BPTT) 。 可选。 这两者frameMode 都不能同时设置为true 。truncated |
useNumericSequenceKeys |
序列键用于关联不同反序列化程序之间的序列。 对于某些反序列化程序, (例如 HTK 和 MLF) 序列键是任意字符串。 存储它们需要在大型库上占用大量内存。 如果确定序列键是数值,请将此参数设置为 true,在这种情况下,所有字符串键将转换为减少内存压力的整数。 可选,默认值 false 。 |
hashSequenceKeys |
出于上述内存原因,还可以通过将此参数设置为 true 来对字符串键进行哈希处理。 请仅将其用于支持字符串序列键 (HTK、MLF) 的反序列化程序。 可选,默认值 false 。 |
cacheIndex |
指定在预处理阶段生成的元数据是否应写入磁盘,并在可用 (true 时从磁盘加载, false ) 。 可选,默认为 false . 有关详细信息,请参阅下面的部分。 CNTK 版本 2.1 中的新增功能。 |
索引缓存
注意
CNTK 版本 2.1 中的新增功能。
索引缓存允许大幅 (2-3 倍,) 减少启动时间,尤其是在处理大型输入文件时。 将 cacheIndex
标志 true
设置为指示读取器将索引元数据写入磁盘 (与输入文件相同的目录,) 缓存文件不可用,或者缓存文件 (早于输入文件) 。 写入是尽最大努力的,在单独的线程上执行,以便不影响读取器性能。 如果缓存文件存在并且是最新的,则读取器将不再浏览输入文件以生成索引,而是从缓存文件加载索引。 请注意,某些读取器配置参数对索引 (有直接影响,不同的值 frameMode
可能会导致索引具有不同序列数) 。 因此,读取器可以忽略缓存文件,其配置不同于生成缓存的配置。 若要查看缓存的完整优势,不应在后续重新运行时修改配置。
cacheIndex
对 ImageDeserializer 和 CNTKBinaryFormatDeserializer 没有影响,因为前者不为输入数据编制索引,而后来的索引信息嵌入格式本身。
常规反序列化程序配置
参数 | 说明 |
---|---|
module |
指定实现数据反序列化器的读取器模块名称。 “必需”。 |
type |
指定给定读取器模块公开的数据反序列化程序名称。 “必需”。 |
常规转换配置
参数 | 说明 |
---|---|
type |
指定由实现数据反序列化器的读取器模块公开的转换名称。 “必需”。 |
HTKFeatureDeserializer 选项
参数 | 说明 |
---|---|
scpFile |
要处理的 SCP 文件的路径列表。 这些文件应为 HTK 兼容文件,并且必须以“存档”格式指定。 使用存档的详细信息在 HTKMLF 读取器中介绍。 “必需”。 |
dim |
一个整数,指定具有所需上下文窗口的完整特征向量维度。1必需 |
contextWindow |
可以指定为正整数对或单个正整数 (在这种情况下,它将同一个数字解释为重复两次) 的对。 指定示例中上下文窗口) 对 (第一个和第二个整数的左右大小。 可选,默认为 1 . |
prefixPathInSCP |
要应用于 SCP 文件中指定的路径的前缀字符串。 可选。 |
例如 ,如果具有 72 维特征 (24 维筛选器库特征加上增量和增量系数) 并且网络旨在处理 11 帧的上下文窗口,则指定的维度应为 792。
HTKMLFDeserializer 选项
参数 | 说明 |
---|---|
mlfFile |
HTK 样式 mlf 文件的路径,其中包含文件 () 中指定的 scp 所有言语的标签。 如果未mlfFileList 指定,则为必需。 |
mlfFileList |
HTK 样式 mlf 文件 () 的路径数组,其中包含文件 (s) 中指定的 scp 所有话语的标签。 如果未mlfFile 指定,则为必需。 |
dim |
标签集的总基数 (正整数) 。 “必需”。 |
labelMappingFile |
文件的路径,其中列出了文件中显示的 mlf 所有标签,每行一行。 “必需”。 |
labelDim 可用作 dim 的同义词。
CNTKTextFormatDeserializer 选项
可用于 CNTKTextFormatReader 的相同选项
ImageDeserializer 选项
file
:一个简单的文本文件,其中每行都包含逻辑序列键、图像文件 ((例如 JPEG、PNG ) 等)和基于 0 的标签之间的制表符分隔映射。
有关详细信息,请参阅 ImageReader。
Base64ImageDeserializer 选项
此反序列化程序支持可用于 ImageDeserializer 的相同选项。 唯一的区别在于映射文件的格式:
file
:一个简单的文本文件,其中每行包含逻辑序列键之间的制表符分隔映射 (可选,可以省略) 、基于 0 的类别标签和 base 64 编码的图像文件 (,例如 JPEG、PNG 等) 。
配置和测试示例
你将在 CNTK 存储库中找到完整的网络定义和相应的数据集示例。 你还将在此处找到使用反序列化器的单元和端到端测试,即
- https://github.com/Microsoft/CNTK/tree/release/latest/Tests/EndToEndTests/Speech/HTKDeserializers/LSTM/FullUtterance
- https://github.com/Microsoft/CNTK/tree/release/latest/Tests/EndToEndTests/Image/AlexNet
- https://github.com/Microsoft/CNTK/tree/release/latest/Tests/UnitTests/ReaderTests/Config/ImageAndTextReaderSimple_Config.cntk
- https://github.com/Microsoft/CNTK/tree/release/latest/Tests/UnitTests/ReaderTests/Config/CNTKTextFormatReader/dense.cntk