你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
- 执行分层训练?
- 使用多任务目标进行训练?
- 在图像上训练回归模型?
- 训练多标签分类器?
- 按顺序开始对建模进行排序?
- 训练 DSSM (或卷积-DSSM) 模型?
- 使用解码和取消池训练图像自动编码器?
- 使用快速 R-CNN 进行对象检测?
层明智训练
若要执行按层训练,只需在配置文件中使用多个“命令”,其中每个命令的类型为 action=train。
command = TrainLayer1:TrainLayer2:TrainLayer3:EndToEndTrain:Test:Output
TrainLayer1= [
action = train
...
]
TrainLayer2= [
action = train
...
]
...
使用多任务目标进行训练
只需将组合条件定义为 BrainScript 表达式,可以通过指定这些 evaluationNodes条件来监视所有单个任务损失。
task1loss = CrossEntropyWithSoftMax(prediction,label)
task2loss = SquareError(reconstruction,input)
mtloss = task1loss + Constant(0.3) .* task2loss
criterionNodes = (mtloss)
evaluationNodes = (task1loss:task2loss)
在图像上训练回归模型
下面介绍如何使用 CNTK 预测输入图像的一个或多个浮点值。 示例用例是预测给定图像中对象的边界框,例如 (x、y、w、h) 。 你也可以想到,仅仅通过查看汽车 (的图像来预测汽车的价格实际上会很有趣) 。 在这里,我们使用一个非常简单的示例来训练网络来预测图像的平均 RGB 值, (规范化为 [0, 1]) 。 但是,相同的步骤适用于其他用例。 这些步骤包括:
- 将图像和地面真相回归标签定义为网络输入
- 定义一个网络,用于预测与回归标签匹配的值数 w.r.t。
- 定义一个损失函数,该函数将预测值与基本事实进行比较
- 调整 .cntk 配置文件中的读取器部分以读取图像和回归标签
下面介绍了如何执行此操作。 示例 /图像/回归/RegrSimple_CIFAR10.cntk 的“示例”文件夹中包含完整的配置文件。 该文件夹还包含用于下载图像数据的脚本,并生成用于训练和测试的回归地面真相。
1-3) 定义输入、网络和丢失函数:
BrainScriptNetworkBuilder = [
imageShape = 32:32:3
featScale = Constant(1/256)
labelDim = 3
model (features) = {
featNorm = Scale(features, featScale)
h1 = LinearLayer {100, init="gaussian", initValueScale=1.5} (featNorm)
ol = LinearLayer {labelDim, init="gaussian", initValueScale=1.5} (h1)
}.ol
# inputs
features = Input {imageShape}
regrLabels = Input {labelDim}
# apply model to features
ol = model (features)
# define regression loss
# rmse = sqrt(SquareError(regrLabels, ol) / labelDim)
sqerr = SquareError (regrLabels, ol)
rmse = Sqrt (Constant(1/labelDim).* sqerr)
featureNodes = (features)
labelNodes = (regrLabels)
criterionNodes = (rmse)
evaluationNodes = (rmse)
OutputNodes = (ol)
]
- 使用 ImageReader 和 CNTKTextFormatReader 定义复合读取器:
reader = {
verbosity = 0 ; randomize = true
deserializers = ({
type = "ImageDeserializer" ; module = "ImageReader"
file = "$dataDir$/cifar-10-batches-py/train_map.txt"
input = {
features = { transforms = (
{ type = "Scale" ; width = 32 ; height = 32 ; channels = 3 ; interpolations = "linear" } :
{ type = "Transpose" }
)}
ignored = { labelDim = 10 }
}
} : {
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = "$dataDir$/cifar-10-batches-py/train_regrLabels.txt"
input = {
regrLabels = { dim = 3 ; format = "dense" }
}
})
}
读取器是一个复合读取器,它使用 ImageReader 读取图像和 CNTKTextFormatReader 读取回归地面真实标签。 它通过使用) 定义一组反序列化程序 ({...} : {...} ,并分配上述网络中定义的输入, (cf. 特征和重新生成) 来执行此操作。
有关完整配置文件和该文件夹中对应的自述文件,请参阅 示例/图像/杂项/CIFAR-10/06_RegressionSimple.cntk 。
训练多标签分类器
对于多标签分类,应避免使用 CrossEntropy,因为它只能处理总和为 1 的输入向量。 明智的替代方法是使用逻辑损失函数的总和,每个输出一个
...
probabilities = DenseLayer {outputSize, activation=Sigmoid} (hidden)
logisticLoss = Logistic (multiLabels, probabilities)
trainingCriterion = (logisticLoss)
...
除了损失本身之外,你可能还希望监视其他指标,例如错误预测的数量。 此表达式没有内置表达式,但可以表示为
...
hammingLoss (y, p) = ReduceSum (y != (p > 0.5))
hl = hammingLoss(multiLabels,probabilities)
evaluationNodes = (hl)
...
这计算 y[i] 与 p[i]>0.5 意见不一的次数。
按顺序开始对建模进行排序
此 动手实验室 介绍开始序列处理的主要成分,如 CNTK 文本格式,以及如何将读取器配置为使用各种输入序列的短别名。 grapheme 到 phoneme (G2P) 示例演示了实际的序列到序列任务。
序列到序列建模的一个重要问题是如何使用束搜索解码测试数据。 可以在配置中完成此操作,其中顶级操作为“write”。 解码需要搜索最可能的输出序列。 CNTK 有 一个梁搜索 解码器,而你可以像这样调用
BrainScriptNetworkBuilder = (BS.Seq2Seq.BeamSearchSequenceDecoderFrom (
BS.Network.Load (decodeModelPath), beamSize))
并将使用指定的梁大小执行梁搜索。 对于 1 的梁大小,有专门的贪婪解码器
BrainScriptNetworkBuilder = (BS.Seq2Seq.GreedySequenceDecoderFrom (
BS.Network.Load (decodeModelPath)))
这两个解码器对网络都有特定要求,如 G2P 示例所示
训练 DSSM (或卷积 DSSM) 模型
DSSM (或深度语义相似性模型) 是在源目标文本对上训练的 DNN 模型,用于学习相关源文本和目标文本对更近的地方的短文本嵌入空间。 模型的文本输入由其预先计算的三元报哈希表示, (见, 黄等 人) 。 对于 C-DSSM,三元语法哈希按单词计算,然后按照文本中单词发生的顺序进行串联。 这两个模型的输入大小固定。 如果考虑 50K 三元语法,则对应于源和目标文本的 DSSM 输入将为长度为 50K 的矢量。 对于 C-DSSM,矢量的长度为 50K x n,其中第一个 n-1 字向量是串联的,第 n 个向量包含对应于文本中所有剩余单词的向量之和。 如果文本中的单词少于 n 个,则向量其余部分将填充为零。 若要使用图像绘制类比,可以将 C-DSSM 的文本输入视为采用格式存储 [C x H x W] 尺寸 10x1 和 50K 通道的图像。
此示例演示如何使用 CNTKTextFormatReader 训练 DSSM /C-DSSM 模型。 数据应包含 2 个功能 (源文本和目标文本) 和 1 个标签 (始终设置为定型数据中的值 1,因为它仅包含正样本 - 在训练期间,负目标示例由随机采样) 生成。 下面是读取器配置,
reader = {
verbosity = 0
randomize = true
deserializers = ({
type = "CNTKTextFormatDeserializer"
module = "CNTKTextFormatReader"
file = "data.txt"
input = {
Q = { dim = 500000; format = "sparse" }
D = { dim = 500000; format = "sparse" }
L = { dim = 1; format = "dense" }
}
})
}
输入数据的示例,
|L 1 |Q 482:1 761:1 1832:1 2117:1 12370:1 17131:1 17854:1 24976:1 27676:1 28055:1 28177:1 29507:1|D 482:1 761:1 1832:1 2117:1 12370:1 17131:1 17854:1 24976:1 27676:1 28055:1 28177:1 29507:1
|L 1 |Q 149:1 153:1 595:1 671:1 675:1 1110:1 1517:1 2077:1 2114:1 5533:1 5662:1 6886:1 6901:1 7294:1 12846:1 13033:1 16614:1 19425:1 22015:1 24839:1 24994:1 26196:1 26358:1 27565:1|D 149:1 153:1 595:1 671:1 675:1 1110:1 1517:1 2077:1 2114:1 5533:1 5662:1 6886:1 6901:1 7294:1 12846:1 13033:1 16614:1 19425:1 22015:1 24839:1 24994:1 26196:1 26358:1 27565:1
|L 1 |Q 187:1 2294:1 2800:1 6920:1|D 187:1 2294:1 2800:1 6920:1
最后是网络定义,
BrainScriptNetworkBuilder = {
# Constants scalars
isConvolutional = true
numWords = (if isConvolutional then 10 else 1)
numTrigramsPerWord = 50000
numHiddenNodes = 300
wordWindowSize = 3
numWindows = numWords - wordWindowSize + 1
numNeg = 50
# Constant tensors
CONST_GAMMA = Constant(10)
CONST_SHIFT = Constant(1)
CONST_NEG = Constant(numNeg)
CONST_PAD_NEG = Constant(0, rows=numNeg, cols=1)
CONST_PAD_POS = Constant(1, rows=1, cols=1)
CONST_PAD = Splice(CONST_PAD_POS : CONST_PAD_NEG, axis=1)
# Inputs
Q = Input(500000)
D = Input(500000)
L = Input(1)
qr = if isConvolutional
then TransposeDimensions(ReshapeDimension(Q, 1, numTrigramsPerWord:1:numWords), 1, 3)
else Slice(0, numTrigramsPerWord, Q, axis=1)
dr = if isConvolutional
then TransposeDimensions(ReshapeDimension(D, 1, numTrigramsPerWord:1:numWords), 1, 3)
else Slice(0, numTrigramsPerWord, D, axis=1)
qdssm = Sequential (
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
qcdssm = Sequential (
ConvolutionalLayer {numHiddenNodes, (wordWindowSize:1), pad=false, activation=Tanh} :
MaxPoolingLayer {(numWindows:1), stride=(1:1)} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
ddssm = Sequential (
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
dcdssm = Sequential (
ConvolutionalLayer {numHiddenNodes, (wordWindowSize:1), pad=false, activation=Tanh} :
MaxPoolingLayer {(numWindows:1), stride=(1:1)} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
qembed = if isConvolutional
then qcdssm
else qdssm
dembed = if isConvolutional
then dcdssm
else ddssm
qf = qembed(qr)
df = dembed(dr)
lf = Times(CONST_PAD, L)
c = CosDistanceWithNegativeSamples(qf, df, CONST_SHIFT, CONST_NEG)
s = Slice(0, 1, c, axis=1, tag="output")
ce = CrossEntropyWithSoftmax(lf, Scale(CONST_GAMMA, c), tag="criterion")
}
注意:
- 虽然 C-DSSM 的性能一直优于 DSSM,但它也会训练速度较慢 (有时速度高达 5-10 倍) 。 因此,在某些情况下,通过对更多数据 (或更多纪元) 进行训练,可能会从 DSSM 在同一训练时间获得更好的性能。
- 原始 DSSM/C-DSSM 在查询和文档标题对上进行了训练。 但是,可以通过训练其他类型的数据(例如 会话查询对 或 查询前缀后缀对)来了解短文本之间的其他关系。
使用反卷积和取消池训练图像自动编码器
此处有说明。
使用快速 R CNN 训练对象检测
此处有说明。