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

使用 BrainScript 的层引用

CNTK预定义了许多常见的“层”,这使得编写简单网络非常简单,这些网络由分层在彼此之上的标准层组成。 层是函数对象,可以像常规的 BrainScript 函数一样使用,但保存可学习的参数,并具有传递构造参数或属性的额外配对{}

例如,这是使用 DenseLayer{} 层的简单 1 隐藏层模型的网络说明:

h = DenseLayer {1024, activation=ReLU} (features)
p = DenseLayer {9000, activation=Softmax} (h)

然后,可以使用这一条件进行训练,例如:针对跨枚举条件进行训练:

ce = CrossEntropy (labels, p)

如果网络是直接连接操作, (许多操作) ,则可以使用替代方法 Sequential() 符号:

myModel = Sequential (
    DenseLayer {1024, activation=ReLU} :
    DenseLayer {9000, activation=Softmax}
)

并像这样调用它:

p = myModel (features)

示例模型

下面显示了一个槽标记器,该标记器嵌入单词序列,使用循环 LSTM 对其进行处理,然后对每个单词进行分类:

taggingModel = Sequential (
    EmbeddingLayer {150} :      # embed into a 150-dimensional vector
    RecurrentLSTMLayer {300} :  # forward LSTM
    DenseLayer {labelDim}       # word-wise classification
)

下面是用于图像识别的简单卷积网络:

convNet = Sequential (
    # 3 layers of convolution and dimension reduction by pooling
    ConvolutionalLayer {32, (5:5), pad=true, activation=ReLU} :
    MaxPoolingLayer {(3:3), stride=(2:2)} :
    ConvolutionalLayer {32, (5:5), pad=true, activation=ReLU} :
    MaxPoolingLayer {(3:3), stride=(2:2)} :
    ConvolutionalLayer {64, (5:5), pad=true, activation=ReLU} :
    MaxPoolingLayer {(3:3), stride=(2:2)} :
    # 2 dense layers for classification
    DenseLayer {64, activation=ReLU} :
    LinearLayer {10}
)

参数共享

如果将层分配给变量并将其用于多个位置, 则会共享参数。 如果你说

lay = DenseLayer {1024, activation=Sigmoid}
h1 = lay (x)
h2 = lay (h1)  # same weights as `h1`

h1并将h2共享相同的参数,这lay()两种情况下的函数相同。 在上述情况下,这可能不是所需内容,因此请注意。 如果上述两个 lay() 调用都意味着具有不同的参数,请记住定义两个单独的实例,例如 lay1 = DenseLayer{...}lay2 = DenseLayer{...}

那么,为什么这种行为? 层允许在模型的各个部分之间共享参数。 请考虑一个 DSSM 模型,该模型处理两个输入图像,例如 doc ,与 query 同一处理链相同,并比较生成的隐藏向量:

imageToVec = Sequential (
    ConvolutionalLayer {32, (5:5), pad = true, activation = ReLU} :
    MaxPoolingLayer {(3:3), stride = (2:2)} :
    ConvolutionalLayer {64, (5:5), pad = true, activation = ReLU} :
    MaxPoolingLayer {(3:3), stride = (2:2)} :
    DenseLayer {64, activation = ReLU} :
    LinearLayer {10}
)
zDoc   = imageToVec (doc)
zQuery = imageToVec (query)  # same model as for zDoc
sim = CosDistance (zdoc, zQuery)

其中 imageToVec 是将图像转换为平面矢量的模型的一部分。 imageToVec 是一个函数对象,反过来又包含多个函数对象 (,例如) 的 ConvolutionalLayer{} 三个实例。 imageToVec 实例化 一次,此实例保存所有包含的函数对象的可学习参数。 两个 model() 调用都将在应用程序中共享这些参数,其渐变将是这两个调用的总和。

最后,请注意,如果在上面的示例中query,并且doc必须具有相同维度,因为它们通过同一函数对象进行处理,并且该函数对象的第一层有其输入维度推断为匹配这两query个维度。doc 如果维度不同,则此网络格式不正确,并且维度推理/验证将失败并显示错误消息。

实现说明

许多层是围绕基础CNTK基元的包装器,以及相应的必需可学习参数。 例如, ConvolutionalLayer{} 包装 Convolution() 基元。 使用层的优点是:

  • 层包含正确维度的可学习参数
  • 层可组合 (cf. Sequential())

DenseLayer{}、LinearLayer{}

用于创建完全连接的层的工厂函数。 DenseLayer{} 采用可选的非线性。

DenseLayer {outDim, activation=Identity, init='glorotUniform', initValueScale=1, bias=true}
LinearLayer {outDim, init='glorotUniform', initValueScale=1, bias=true}

parameters

  • outDim:此层的输出维度
  • activation DenseLayer{} (仅) :在此处传递用作激活函数的函数,例如activation=ReLU
  • init 'heNormal' | 'glorotUniform' (|...) :权重的初始化类型。 有关初始化选项的完整列表,请参阅此处
  • initValueScale:随机初始化的方差乘以
  • bias:如果为 false,则不包括偏差参数

返回值

实现所需完全连接的层的函数。 请参阅说明。

说明

使用这些工厂函数创建完全连接的层。 Use DenseLayer{} if you would like an activation function to be included, otherwise LinearLayer{}.

每个工厂函数都会创建一个函数对象,该对象包含可学习的权重矩阵,除非 bias=false存在可学习的偏差。 函数对象可以像实现以下公式之一的函数一样使用:

DenseLayer{...} (v) = activation (W * v + b)
LinearLayer{...} (v) = W * v + b

其中W是维度的权重矩阵,b是维度[outDim x (dimension of v)][outdim]的偏差,生成的值具有维度 (或张量维度) ,outDim如下所示。

Tensor 支持

如果返回的函数应用于张量排名 > 1 的输入(例如二维图像) W 将具有维度 [outDim x (first dimension of input) x (second dimension of input) x ...]

另一方面, outDim 可以是指定张量维度的向量,例如 (10:10)。 在这种情况下, W 将具有维度 [outDim[0] x outDim[1] x ... x (dimension of input)],并 b 具有张量维度 [outDim[0] x outDim[1] x ...]

CNTK的矩阵产品将解释这些额外的输出或输入维度,就像将其平展为长向量一样。 For more details on this, see the documentation of Times()

示例:

h = DenseLayer {1024, activation=Sigmoid) (v)

或者:

Layer = DenseLayer {1024, activation=Sigmoid)
h = Layer (v)

卷积Layer{}

创建具有可选非线性的卷积层。

ConvolutionalLayer {numOutputChannels, filterShape,
                    activation = Identity,
                    init = 'glorotUniform', initValueScale = 1,
                    stride = 1, pad = false, lowerPad = 0, upperPad = 0,
                    bias = true}

parameters

  • numOutputChannels: (筛选器数) 的输出通道数
  • filterShape:筛选器 的空间 范围,例如 (5:5) 2D 筛选器。 此处 包含输入通道维度。
  • activation:可选的非线性,例如 activation=ReLU
  • init 'heNormal' | 'glorotUniform' (|...) :权重的随机初始化类型。 有关随机初始化选项的完整列表,请参阅此处
  • initValueScale:随机初始化的方差乘以
  • stride:在输入上滑动筛选器时递增。 例如 (2:2) ,将维度减少 2
  • pad:如果未设置 (默认) ,则筛选器将移出输入的“有效”区域,也就是说,不使用该区域以外的值。 如果 pad 另一方面设置,筛选器将应用于所有输入位置,并且有效区域之外的值将被视为零。
  • lowerPadupperPad:显式指定填充的不同边距。 筛选器将转移到 (几乎) 以零进行扩充的有效区域。 例如 lowerPad=(1:2) ,将追加零列和两行零。 输出的维度相应地扩展。
  • bias:如果为 false,则不包括偏差参数

返回值

实现所需完全连接的层的函数。 请参阅说明。

说明

使用这些工厂函数创建卷积层。

生成的层对 N 维张量应用卷积运算。 调用方指定筛选器的空间扩展。 给定空间区 (的一组筛选器(例如 (5:5)) )与输入 (的每个位置(例如 [640 x 480]大小的图像) )相关联。 假设 () 启用 pad 填充,并且步幅为 1,这将生成同一维度 [640 x 480] () 的输出区域。

通常,许多筛选器同时应用。 numOutputChannels 指定数字,因此对于每个输入位置,将生成整个向量 numOutputChannels 。 对于上面的示例,设置为 numOutputChannels 64 会在大小调整的张量中 [640 x 480 x 64]。 最后一个轴称为 通道维度

将卷积应用于具有通道维度的输入时,每个筛选器还包含输入通道维度的向量。 例如,当将具有指定空间筛选器范围的(5:5)[640 x 480 x 3]卷积应用于大小调整的颜色图像时,每个筛选器将是[5 x 5 x 3]张量。

堆叠在一起的所有 numOutputChannels 筛选器称为 内核。 在我们的示例中,内核形状将为 [5 x 5 x 3 x 64]

下面总结了各种维度和形状之间的关系:

input shape    : [ (spatial dims)  x  (#input channels)                        ]
spatial extent : [ (filterShape)                                               ]
output shape   : [ (spatial dims)  x                     x  numOutputChannels  ]
kernel shape   : [ (filterShape)   x  (#input channels)  x  numOutputChannels  ]

在我们的示例中为:

input shape    : [ 640 x 480   x   3                          ]
spatial extent : [   5 x 5                                    ]
output shape   : [ 640 x 480   x       x   numOutputChannels  ]
kernel shape   : [   5 x 5     x   3   x   numOutputChannels  ]

填充

如果未启用填充,则输出区域将减少无法应用完整筛选器范围的边界位置。 例如,在不填充的情况下将 -extent 筛选器应用于 (5:5)图像,最外侧的 2 行和像素列将导致筛选器超出边界。 因此, ConvolutionalLayer{} 将相应地减少维度。

[640 x 480]带有(5:5)无填充的筛选器卷积的图像将留下一个[636 x 476]大小调整的输出区域。

进步

参数 stride 指定筛选器的增量。 大于 1 的步幅值将导致输出区域的子采样。 例如,筛选 [640 x 480] 具有步幅 (2:2) 的图像将导致 [320 x 240]具有填充和 [318 x 238] 不填充的调整大小的区域。

注释

此层是基元周围的 Convolution() 包装器。

筛选器内核参数的名称,如日志的验证部分所示将以结尾 .W。 维度当前 不会[ (filterShape) x (#input channels) x numOutputChannels ] 上所述显示,而是 [ numOutputChannels x ( (product over filter shape) * (#input channels) ) ]'。

示例:

c = ConvolutionalLayer {64, (3:3), pad = true, stride = (1:1), bias=false} (x)

DeconvLayer{}

创建一个反卷积层。

DeconvLayer {numOutputChannels,
             filterShape, numInputChannels,
             bias = true,
             activation = (x=>x),
             init = 'glorotUniform',
             initValueScale = 0.001,
             initBias = 0,
             stride = 1, autoPadding = false,
             lowerPad = 0, upperPad = 0,
             maxTempMemSizeInSamples = 0}

parameters

  • numOutputChannels: (筛选器数) 的输出通道数
  • filterShape:筛选器 的空间 范围,例如 (5:5) 2D 筛选器。 此处 包含输入通道维度。
  • numInputChannels:输入卷) (筛选器数的输入通道数
  • bias:如果为 false,则不包括偏差参数
  • activation:可选的非线性,例如 activation=ReLU
  • init 'heNormal' | 'glorotUniform' (|...) :权重的随机初始化类型。 有关随机初始化选项的完整列表,请参阅此处
  • initValueScale:随机初始化的方差乘以
  • initBias:偏差的初始值
  • stride:在输入上滑动筛选器时递增。 例如 (2:2) ,将维度减少 2
  • autoPadding:如果未设置 (默认) ,则筛选器将移出输入的“有效”区域,也就是说,不使用该区域以外的值。 如果 autoPadding 另一方面设置,筛选器将应用于所有输入位置,并且有效区域之外的值将被视为零。
  • lowerPadupperPad:显式指定输出卷填充的不同边距 ,即用于相应卷积层中输入的边距。 请务必将它们与卷积层相对应的设置,以实现相同的张量维度。

返回值

实现所需完全连接的层的函数。 请参阅说明。

说明

使用这些工厂函数创建一个反卷积层。

生成的层对 N 维张量应用反卷积运算。 此层是基元周围 Convolution() 包含的 deconv=true包装器。

一个用于反卷积的常用用例是重新构造图像, (此处查看,例如) 。 如果卷积采用输入 2D 接受字段区域并计算与 2D 筛选器的关联,则解积采用像素并将其分布到 2D 区域。

请考虑图像 p (.,.) ,像素位置 (x,y) 和居中 [3 x 3] 筛选器,其中以下内容 (目前没有特征映射深度维度,即单个通道) :

[ . . c
  a b .
  . . . ]

此处,b 和 c 是筛选器的权重“.”。 对应于零权重。 卷积 () 计算输出像素 q (x, y) 位置 (x, y) :

q(x,y) = b * p(x,y) + a * p(x-1,y) + c * p(x+1,y-1)

十字复数采用像素 q (x,y) ,并将其分布到大约 (x,y) 的区域。 如果使用相同的筛选器,它将对输出 r (x,y) 做出以下贡献:

r(x,y)     += b * q(x,y)
r(x-1,y)   += a * q(x,y)
r(x+1,y-1) += c * q(x,y) 

知道这同样适用于整个平面上的所有 x 和 y,我们可以为 r (x,y) 表示这一点:

r(x,y)     += b * q(x,y)
r(x,y)     += a * q(x+1,y)
r(x,y)     += c * q(x-1,y+1) 

或总计,

r(x,y) = b * q(x,y) + a * q(x+1,y) + c * q(x-1,y+1) 

这与上述卷积的形式相同,只是筛选器沿两个轴镜像。

现在,我们将功能映射引入组合中。 这很容易:而不是从输入深度到输出深度,而是走向另一个方向。

总之,卷积 (W,x) == 解卷积 (W', x) ,其中

W : [W x H x C x K]

and

W’ = W 其值重新排列为: [(W mirrored) x (H mirrored) x K x C]

即 Deconvolution () 的隐式功能是:

  • 交换两个深度维度 (转置)
  • 空间维度 (反转数据的顺序)
  • 这些卷积 ()

示例:

deconv_A = DeconvLayer {inputDim, (5:5), cMap1, lowerPad=(2:2:0), upperPad=(2:2:0)}(unpool_A)

有关详细示例并演练,请参阅 使用解压和取消池的图像自动编码器

MaxPoolingLayer{}、AveragePoolingLayer{}

工厂函数用于创建最大或平均池层。

MaxPoolingLayer {poolShape, stride = 1, pad = false, lowerPad = 0, upperPad = 0}
AveragePoolingLayer {poolShape, stride = 1, pad = false, lowerPad = 0, upperPad = 0} =

parameters

  • poolShape:要池的区域的形状,例如 (2:2)
  • stride:在输入上滑动池时递增。 例如 (2:2) ,将维度减少 2
  • pad:如果未设置 (默认) ,则池将转移到输入的“有效”区域,也就是说,不使用该区域以外的值。 如果 pad 另一方面设置,池将应用于所有输入位置,并且有效区域之外的值将被视为零。 对于平均池,平均值的计数不包括填充值。
  • lowerPadupperPad:显式指定填充的不同边距。 筛选器将转移到 (几乎) 以零进行扩充的有效区域。 例如 lowerPad=(1:2) ,将追加零列和两行零。 输出的维度相应地扩展。

返回值

实现所需池层的函数。 请参阅说明。

说明

使用此工厂函数创建池操作。 用于 MaxPoolingLayer{} 计算池区域中的值的最大值,并 AveragePoolingLayer{} 取平均值。

池操作在输入区域的位置上滑动“池窗口”,并计算相应池区域中值的最大值或平均值。

此操作在结构上与卷积非常相似,只是应用于滑动窗口的操作具有不同的性质。

有关输入维度、填充和步幅的所有注意事项都同样适用,因此请参阅 ConvolutionalLayer{} 更多详细信息。

示例:

p = MaxPoolingLayer {(3:3), stride=(2:2)} (c)

MaxUnpoolingLayer{}

创建 max-unooling 层。

MaxUnpoolingLayer {poolShape,
                   stride = 1, pad = false,
                   lowerPad = 0, upperPad = 0} 

parameters

  • poolShape:要取消池的区域形状 (输出 区域大小) ,例如 (2:2)
  • stride:在 输出上滑动池时递增。 例如 (2:2) ,将维度增加 2
  • pad:如果未 (默认) 设置,则池将转移到输出的“有效”区域,也就是说,不使用该区域以外的值。
  • lowerPadupperPad:显式指定填充的不同边距。 筛选器将假定 (几乎) 扩充的有效输出区域。

返回值

实现所需取消池层的函数。 请参阅说明。

说明

使用此工厂函数创建取消池操作。

取消池操作是池操作的反函数。 它需要两个输入:相应的池层的输出,例如 p1 ,以及其相应池层的输入,例如 r1,也。 它在其输入 p1位置上滑动“反池窗口”,并将值投影到具有相应池操作中最大值的输出区域的位置,即 in r1。 CNTK需要第二个输入r1来确定取消池操作的目标,因为CNTK不存储所谓的开关变量, (在此处查看详细信息) 。

示例:

unpool_A = MaxUnpoolingLayer {(2:2), stride=(2:2)}(deconv_B, relu_A)

有关详细示例并演练,请参阅 使用解压和取消池的图像自动编码器

EmbeddingLayer{}

EmbeddingLayer {outDim,
                init='glorotUniform', initValueScale=1,
                embeddingPath = '', transpose = false}

parameters

  • outDim:所需嵌入向量的维度
  • init 'heNormal' | 'glorotUniform' (|...) :权重的初始化类型。 有关初始化选项的完整列表,请参阅此处
  • initValueScale:随机初始化的方差乘以
  • embeddingPath:如果给定,则不会学习嵌入内容,而是从文件中加载,在训练期间不会进一步更新
  • transpose:允许加载以转置形式存储的嵌入内容

返回值

实现嵌入层的函数。 请参阅说明。

说明

“嵌入”是指通过密集连续向量表示单词或其他离散项。 此层假定输入采用单热形式。 例如,对于词汇大小为 10,000 的词汇,每个输入向量应具有维度 10,000,并且包含零,但包含 1 个位置除外。 该位置的索引是它所表示的单词或项的索引。

在CNTK中,相应的嵌入向量存储为矩阵的列。 因此,将输入词映射到其嵌入实现为矩阵产品。 为此,必须以稀疏格式存储输入向量。

有趣的事实:嵌入矩阵的渐变具有渐变向量的形式,这些矢量对于迷你批中看到的单词来说只有非零。 由于对于数十或数十万的现实词汇,绝大多数列将是零,CNTK实现具有特定的优化来表示“列稀疏”形式的渐变。

已知问题:上述列稀疏渐变形式目前不受 我们的 1 位 SGD 并行化技术支持。 请改用 块动量 技术。

示例

一个已学习的嵌入,表示词汇 87636 中的单词作为 300 维向量:

input = Input{87636, sparse=true}    # word sequence, as one-hot vector, sparse format
embEn = EmbeddingLayer{300} (input)  # embed word as a 300-dimensional continuous vector

此外 sparse=true,还应在配置块中 reader 将输入声明为稀疏。 下面是使用以下内容 CNTKTextFormatReader读取稀疏文本输入的示例:

reader = {
    readerType = "CNTKTextFormatReader"
    file = "en2fr.txt"
    randomize = true
    input = {
        input  = { alias = "E" ; dim = 87636 ;  format = "sparse" }
        labels = { alias = "F" ; dim = 98624 ;  format = "sparse" }
    }
}

如果嵌入向量已存在且应从文件中加载,则如下所示:

input = Input{87636, sparse=true}     # word sequence, as one-hot vector, sparse format
embEn = EmbeddingLayer{300, embeddingPath="embedding-en.txt", transpose=true} (w) # embedding from disk

其中,该文件 "embedding-en.txt" 应包含 87,636 个文本行,每个行包含 300 个空格分隔的数字。 由于此文件将嵌入内容保存为行而不是列, transpose=true 因此将动态转置矩阵。

RecurrentLSTMLayer{}、RecurrentLSTMLayerStack{}

工厂函数用于创建单层或多层循环 LSTM。

RecurrentLSTMLayer {outDim, cellShape = None,
                    goBackwards = false,
                    usePeepholes = false,
                    init = 'glorotUniform', initValueScale = 1,
                    enableSelfStabilization = false,
                    allowOptimizedEngine = false}
RecurrentLSTMLayerStack {layerDims,
                         cellShapes = None,
                         usePeepholes = false,
                         init = 'glorotUniform', initValueScale = 1,
                         enableSelfStabilization = false,
                         allowOptimizedEngine = false}

parameters

  • outDim RecurrentLSTMLayer{} () :网络的输出维度。 若要表示排名>1 的张量,可以是向量,例如 (40:2)
  • layerDims RecurrentLSTMLayerStack{} () :网络内部层和输出的维度数组
  • cellShape RecurrentLSTMLayer{} ( (可选) :LSTM 单元格的维度。 通常,这与 outDim a0/> 相同。 如果给出不同的值,将插入一个额外的线性投影,以便从单元格维度转换为输出。
  • cellShapes RecurrentLSTMLayerStack{} ( (可选) :表示RecurrentLSTMLayer()投影等cellShape值的数组
  • goBackwards (可选) :如果为 true,则重复周期向后运行
  • usePeepholes (可选) :如果为 true,请在 LSTM 中使用窥视孔连接
  • init 'heNormal' | 'glorotUniform' (|...) :权重的初始化类型。 有关初始化选项的完整列表,请参阅此处
  • initValueScale:随机初始化的方差乘以
  • enableSelfStabilization (可选) :如果为 true,则插入类似于“稳定器”的操作 StabilizerLayer{}
  • allowOptimizedEngine (可选的默认 false) :如果为 true,则尽可能使用 cuDNN 的优化 RNN 引擎

返回值

实现所需层的函数 () ,该函数对其输入序列应用/应用循环 LSTM。 此层 (堆栈) 将输入序列映射到相同长度的隐藏状态序列。

说明

这实现了要应用于一系列输入的循环 LSTM,采用两个变体:一个层和一个多层堆栈。 此操作会自动处理可变长度输入。 隐藏状态和单元格的初始值为 0。

将此层应用于输入序列将返回 (堆栈顶部) 循环 LSTM 的隐藏状态序列, (LSTM 的内存单元的值不会返回) 。 返回的序列的长度与输入相同。 如果仅需要最后一个状态(如序列分类或某些序列到序列方案),则仅用于 BS.Sequences.Last() 提取最后一项的隐藏状态。 (在向后重复周期中,将使用 BS.Sequences.First().)

若要创建包含的双向模型 RecurrentLSTMLayer(),请使用两个层,一个层 goBackwards=trueSplice() 两个输出在一起。 RecurrentLSTMLayerStack() 当前不支持双向模型,必须使用多个 RecurrentLSTMLayer()/Splice() 组合手动构造模型。

使用 CuDNN5 RNN 引擎

如果可能,此函数将自动使用 CuDNN5 的优化 RNN 引擎,也就是说,如果是

  • 指定的模型是由 CuDNN5 函数实现的模型
    • 无投影 (无 cellShape 参数)
    • 无窥孔连接
    • 无自我稳定
    • 不向后移动
    • 对于 RecurrentLSTMLayerStack{},所有层维度具有相同的值
  • allowOptimizedEngine=true

具体而言,CNTK需要启用allowOptimizedEngine=true。 这是因为 CuDNN5 RNN 作为需要 GPU 的CNTK基元操作实现。 但是,许多实际系统使用 GPU 进行训练,但在部署中只使用 CPU 服务器。 CuDNN5 RNN 不适合此处。 (理论上可以使用 CuDNN5 RNN 进行训练,并将其替换为在 BrainScript.) 中使用等效的显式 LSTM 实现进行部署

注释

如果 allowOptimizedEngine=true 这两个层变体是基元周围的 OptimizedRNNStack() 包装器。

示例

一个简单的文本分类器,它通过重复周期运行单词序列,然后将 LSTM 的最后 隐藏状态传递给 softmax 分类器,可以采用以下形式:

w = Input{...}                   # word sequence (one-hot vectors)
e = EmbeddingLayer {150} (w)     # embed as a 150-dimensional dense vector
h = RecurrentLSTMLayer {300} (e) # left-to-right LSTM with hidden and cell dim 300
t = BS.Sequences.Last (h)        # extract last hidden state
z = DenseLayer {10000, activation=Softmax} (t)  # softmax classifier

若要将上述示例更改为使用 CuDNN5 RNN 引擎的三层堆栈,请更改以下行:

h = RecurrentLSTMLayerStack {(300:300:300), allowOptimizedEngine=true} (e)

若要创建双向单层 LSTM (,例如,使用一半的隐藏维度与上述) 相比,请使用以下命令:

hFwd = RecurrentLSTMLayer {150} (e)
hBwd = RecurrentLSTMLayer {150, goBackwards=true} (e)
h = Splice (hFwd:hBwd)

DelayLayer{}

工厂函数用于创建延迟其输入的层。

DelayLayer {T=1, defaultHiddenActivation=0}

parameters

  • T:延迟的时间步骤数。 若要访问将来的值,请使用负值
  • defaultHiddenActivation:要用于边界处延迟帧的值

返回值

实现所需延迟操作的函数。

说明

此操作按 T 默认 1 () 的步骤延迟输入序列。 例如,将单词序列转换为重叠单词三重序列非常有用。

请考虑输入序列“b c b”,该序列应编码为一个热向量序列,如下所示:

1 0 0 0
0 1 0 1
0 0 1 0

此处,每列都是一个热向量,对应于一个单词。 DelayLayer{T=1}应用于此输入将生成以下序列:

0 1 0 0
0 0 1 0
0 0 0 1

所有令牌都延迟一个,第一个位置作为 0 向量填充。 同样,使用 DelayLayer{T=-1} (负延迟) 将授予对未来值的访问权限,并用零从右侧填充:

0 0 0 0
1 0 1 0
0 1 0 0

注释

此层是围绕基元的PastValue()FutureValue()包装器。

示例

下面演示如何将三个相邻单词堆积到三元语法向量中:

x  = ...                   # input value, e.g. a N-dimensional one-hot vector
xp = DelayLayer{} (x)      # previous value
xn = DelayLayer{T-1} (x)   # next value (negative delay)
tg = Splice (xp : x : xn)  # concatenate all into a 3N-dimensional three-hot vector

BatchNormalizationLayer{}、LayerNormalizationLayer{}、StabilizerLayer{}

工厂函数用于为批处理规范化、层规范化和自我稳定创建层。

BatchNormalizationLayer {spatialRank = 0,
                         normalizationTimeConstant = 5000,
                         initialScale = 1, epsilon = 0.00001, useCntkEngine = true}
LayerNormalizationLayer {initialScale = 1, initialBias = 0}
StabilizerLayer{}

parameters

BatchNormalizationLayer:

  • spatialRank:规范化参数在第一个 spatialRank 维度上共用。 当前允许的值为 0, (没有池) ,2 个 (池跨图像) 的所有像素位置进行池
  • normalizationTimeConstant (默认 5000) :用于计算平均值/方差统计信息以使用推理的第一级低通筛选器样本中的时间常量
  • initialScale:scale 参数的初始值
  • epsilon:计算反方差时添加到方差估计中的小值
  • useCntkEngine:如果为 true,请使用CNTK的本机实现。 如果为 false,则仅使用 cuDNN 的实现 (GPU) 。

LayerNormalizationLayer:

  • initialScale:scale 参数的初始值
  • initialBias:偏差参数的初始值

返回值

实现执行规范化操作的层的函数。

说明

BatchNormalizationLayer{} 实现论文 批处理规范化中所述的技术:通过减少内部共变移 (谢尔盖·Ioffe、克里斯蒂安·塞格迪) 来加速深度网络训练 。 它按小分量平均值/方差规范化每个微型样本的输入,并使用学习的缩放因子和偏差将其反规范化。

在推理中,批处理规范化使用长期运行的平均值/var 估计值,而不是使用 minibatch 平均值/方差。 此估计值通过低传递筛选微分量统计信息在训练期间计算。 参数可以修改 normalizationTimeConstant 低传递筛选器的时间常量。 我们建议从默认 (5000) 开始,但尝试其他值,通常按几千到几万的顺序进行试验。

LayerNormalizationLayer{} 实现 层规范化 (吉米·雷巴、杰米·瑞安·基罗斯、杰弗里·伊森·辛顿) 。 它通过将样本的所有元素中的平均值减去,然后除以样本的所有元素的标准偏差来规范化每个输入样本。

StabilizerLayer{} 实现每个自 稳定深度神经网络的自稳定器 (P. Ghahremani, J. Droppo) 。 这种简单而有效的技术将其输入与可学习标量相乘 (,但与层规范化不同,它不会首先规范化输入,也不会减去平均) 。 请注意,与提出线性标量或指数标Exp (beta)beta的原始纸张相比,我们发现,使用每秒作者建议的锐化软增强操作是有益的,这避免了指数的负值和不稳定。

注释

BatchNormalizationLayer{} 是基 BatchNormalization() 元周围的包装器。 LayerNormalizationLayer{} 并在 StabilizerLayer{} BrainScript 中直接表示。

示例

卷积网络中具有批处理规范化的典型层:

MyLayer (x, depth, initValueScale) =
{
    c = ConvolutionalLayer {depth, (5:5), pad=true, initValueScale=initValueScale} (x)
    b = BatchNormalizationLayer {spatialRank = 2} (c)    #####
    r = ReLU (b)
    p = MaxPoolingLayer {(3:3), stride = (2:2)} (r)
}.p

FeatureMVNLayer{}

工厂函数用于创建一个按平均值和标准偏差规范化特征输入的层。

FeatureMVNLayer{}

parameters

空参数列表 {}

返回值

实现执行规范化操作的层的函数。

说明

此层通过其偏差和方差规范化神经网络的输入。 通过执行训练数据的完整传递,然后保存并冻结这些值,从而提前估计这些值。 此操作将自动发生。

由于此层的参数在主训练之前在单独的传递中预计算,因此只能应用于声明为 Input{}的变量。

示例

这是用于语音声学建模的神经网络的典型起点:

features = Input{40}      # e.g. speech features
featNorm = FeatureMVNLayer{} (features)
h = DenseLayer{2048} (featNorm)
...