SGD配置块控制这CNTK里面的SGD(随机梯度下降)算法,如果你对其他的工具包熟悉,可以学习下面的内容
minibatch size在CNTK中是怎么定义的?
如何把第三方的工具包里面的学习率和momentum等参数转化到CNTK里?
SGD的结构和默认值如下:
SGD = {
# Training process control
modelPath = ...
trainCriterionNodeName = ...
evalCriterionNodeName = ...
maxEpochs = ...
epochSize = 0
minibatchSize = 256
truncated = false
dropoutRate = 0
maxTempMemSizeInSamplesForCNN = 0
keepCheckPointFiles = false
disableWkInBatchNormal = false
# Learning rate and momentum control
learningRatesPerSample = ...
learningRatesPerMB = ...
minLearningRatePerSample = ...
momentumAsTimeConstant = ...
momentumPerMB = ...
useNAG = false
autoAdjust = {
autoAdjustLR = "none" # | "searchBeforeEpoch" | "adjustAfterEpoch"
autoAdjustMinibatch = false
# for autoAdjustLR = "adjustAfterEpoch":
reduceLearnRateIfImproveLessThan = 0
learnRateDecreaseFactor = 0.618
increaseLearnRateIfImproveMoreThan = (infinity)
learnRateIncreaseFactor = 1.382
loadBestModel = true
learnRateAdjustInterval = 1
useCVSetControlLRIfCVExists = true
useEvalCriterionControlLR = false
# for autoAdjustLR = "searchBeforeEpoch":
numMiniBatch4LRSearch = 500
numPrevLearnRates = 5
numBestSearchEpoch = 1
# for autoAdjustMinibatch = true:
numMiniBatch4LRSearch = 500
minibatchSizeTuningFrequency = 1
minibatchSizeTuningMax = 1048576
minibatchSearchCriterionErrorMargin = 1
}
parallelTrain = {
parallelizationMethod = "none" # | "dataParallelSGD" | "blockMomentumSGD" | "modelAveragingSGD"
parallelizationStartEpoch = 1
distributedMBReading = false
syncPerfStats = 0
# for parallelizationMethod = "dataParallelSGD"
dataParallelSGD =
{
gradientBits = (8*sizeof(precision)) # | 1 | 2
useBufferedAsyncGradientAggregation= false
}
# for parallelizationMethod = "blockMomentumSGD"
blockMomentumSGD = {
blockSize = (120000 * #workers)
blockMomentumAsTimeConstant = (-blockSize / log(1 - 1/#workers))
resetSGDMomentum = true;
useNesterovMomentum = true;
blockLearningRate = 1.0
}
# for parallelizationMethod = "modelAveragingSGD"
modelAveragingSGD = {
blockSize = (40000 * #workers)
}
}
# Gradient control
gradientClippingWithTruncation = true
clippingThresholdPerSample = (infinity)
L2RegWeight = 0
L1RegWeight = 0
gaussianNoiseInjectStd = 0
gradUpdateType = "" # "" | "adagrad" | "rmsProp" | "fsAdaGrad"
# for gradUpdateType = "adaGrad" or "rmsProp":
normWithAveMultiplier = true
# for gradUpdateType = "rmsProp":
rms_wgt_inc = 1.2
rms_wgt_dec = 0.75
rms_wgt_max = 10.0
rms_wgt_min = 0.1
rms_gamma = 0.99
# Information display
traceLevel = 0
firstMBsToShowResult = 10
numMBsToShowResult = 10
numMBsToCUDAProfile = 0
# Precompute
useAllDataForPreComputedNode = true
# Gradient check
gradientCheck = false
sigFigs = 6
}
参数
训练过程控制
trainCriterionNodeName
:训练标准节点的名称,如果没有配置的话,会使用默认值。evalCriterionNodeName
:评估标准节点的名称,如果没有配置的话,会使用默认值。epochSize
: 每一次迭代的样本个数,CNTK每次迭代取出epochSize
个样本之后,会做如下处理:o 保存一个检查点模型,也是训练也是从这里开始的.
o 较差验证
o 学习率控制
ominibatch
自减
当epochSize
设置成0的时候,表明使用整个数据集,即epochSize
等于实际数据集的大小,在处理较小的数据集的时候,一般会这么做。当处理大数据集的时候,会使用检查点来配合epochSize
的设置,例如:假如为了防止断电或是断网引起的计算数据丢失,我们可以设置每30分钟创建一个检查点,来保证计算数据的丢失最大不会超过30分钟(断电后,可以从上一个检查点恢复),这时候我们可以通过设置epochSize
的大小为计算30分钟时处理的个数来完成。
注意:像minibatchSize
,如果input是由一些列有顺序的样本组成,例如一个句子的文本,epochSize
代表着具体独立的条目数(每个单词),而不是序列的个数(句子)。keepCheckPointFiles
:当一次新的迭代开始,是否需要将检查点文件保存下来,值有true和false(默认)。disableWkInBatchNormal
:当SGD更新时,是否将权重衰减项进行批量归一化,值有true和false(默认)。maxEpochs
:需要迭代的次数。minibatchSize
:每次迭代从样本中取的个数(minibatch
),默认值是256.这个值还可以根据迭代次数来指定不同的值,例如:128*2:1024,代表头两次迭代取128个样本,后面剩下的迭代都取1024个样本。在CNTK中Minibatch
是被定义成在模型更新之间,取的样本个数。这个定义在并行处理时仍然有效(例如:
sizek
个工作站,每个工作站一次迭代取Minibatch
个样本)。在变长的input中,
/kMinibatch
指的是序列中的具体个数,而不是序列的个数。SGD将会去适合在Minibatch
中的样本数里,尽量多的序列。如果中途给定了几个input。SGD将会把它放到当前minibatch
里,知道总数超出minibatchsize
。dropoutRate
:指训练过程中的输出节点的丢弃率。默认是0.0
,0.5*10:0.2
代表前10次迭代使用的输出节点丢弃率为0.5,其他的迭代使用0.2。maxTempMemSizeInSamplesForCNN:在打包和解包输入样本数据时使用的最大内存。默认是0,代表需要多少就用多少。在使用GUP时可以控制内存溢出。
学习率和momentum的控制
CNTK指定学习率和momentum的方式不同与其他工具包。详细说明
learningRatesPerSample
:每一次迭代处理一个样本时计算梯度的学习率参数,这个梯度可用于更新网络模型。0.025*10:0.00625
代表前10条的样本迭代的学习率使用0.025
,其他的迭代都使用0.00625
。learningRatesPerMB
:设置学习率的另一种方式,每次迭代处理minibatchsize
个样本之后,更新一次学习率。这种方式与其他工具包的指定方式一致。在并行处理中,learningRatesPerMB
会被转化成learningRatesPerSample
,最终还是以learningRatesPerSample
的方式来处理。minLearningRatePerSample
:每样本学习率的最小值。当实际的学习率小于这个最小值的时候,标志计算过程结束。当动态调整学习率被启动时,可以用这个值来控制训练提前结束。默认值是1e-9
.momentumAsTimeConstant
:梯度变化在每一个时间常数的momentum
。momentum
的作用是加快收敛速度的,一般加入之前的梯度来修改更新梯度步长。时间常数是指梯度下降到原来的1/e=37%所用的时间。在这里,这个时间等同于这个时间内处理的样本的个数。其他工具包里经常会将momentum
当成每次minibatch
的权重(例如0.9).可以使用momentumAsTimeConstant = -minibatchSize / ln (momentumPerMB)
来进行转化。20000*10:2500
代表前10次时间常数迭代的momentum
为20000
,剩下的为2500
。momentumPerMB
:momentum设置的另一个方式,与其他的工具包表述一样。例如:0.9代表前一个梯度将以0.9的权重来返回。与其他工具包不同的是CNTK仍然使用unit-gain滤波器,新的梯度将会被乘以(1-momentumPerMB)
,本质上,也会被转化成mentumAsTimeConstant = -minibatchSize / ln (momentumPerMB)
。autoAdjust
:自动调整学习率。默认是(“”)
意思是不自动调整。还可以设置一下等值:autoAdjustLR
:使用自动学习率调整算法,AdjustAfterEpoch
(每次迭代之后,检查训练标准,决定是否调整学习率)SearchBeforeEpoch
(每次迭代之前,通过一小部分的训练集来搜索学习率)。- 当使用
AdjustAfterEpoch
时:
reduceLearnRateIfImproveLessThan
:如果改进值小于这个值,就减小学习率。默认0learnRateDecreaseFactor
:学习率下降因子。默认0.618increaseLearnRateIfImproveMoreThan
:如果改进值大于这个值,增加学习率。默认是1#INF
(infinity) 意味着永远部增加。learnRateIncreaseFactor
:学习率增加因子,默认是1.382
loadBestModel
:如果当前模型效率降低,是否要加载最好的模型。值有true(默认)和falselearnRateAdjustInterval
:应用学习率调整检查的频度。默认是1。代表每次迭代调整检查一次。如果是大于1(n),就代表n次迭代调整检查一次useEvalCriterionControlLR
:使用评价标准来替代训练标准来更新学习率。默认是false
- 当使用
SearchBeforeEpoch
时:
numMiniBatch4LRSearch
:使用搜索学习率的minibatches 的数量,默认值是500,通常为一次迭代总数的10-20%。numPrevLearnRate
:搜索范围,默认值是5,表示是5条。numBestSearchEpoch
:从几次迭代里面来找最好的学习率。默认值为1
- 当使用
AdaptiveMinibatchSizing
时:
numMiniBatch4LRSearch
:与numMiniBatch4LRSearch里的意识一致,这个两个字段共享。autoAdjustMinibatch
:minibatch
自动调整,默认值false。当为true时,将在用户指定minibatch
完成过后,下一次的迭代才开始进行自动调整。例如:minibatchSize=256:1024
,在头两次的迭代minibatch
为256和1024.之后的迭代minibatch
开始自动调整。minibatchSizeTuningFrequency
:每跳过几次迭代之后,再开始动态调整minibatch
,默认值是1minibatchSizeTuningMax
:允许自动调整的最大值。默认是1048576
梯度控制
gradientClippingWithTruncation
:是否要截断梯度,来防止梯度爆炸,默认是true。如果是false,将要使用代价更高的剪辑标准来替代。clippingThresholdPerSample
:每个样本的裁剪阈值。默认值是1 # INF意味无穷(关闭剪辑)L2RegWeight
:默认0,每个样本的l2正则权重值。L1RegWeight
:默认0,每个样本的l1正则权重值。gradUpdateType
:梯度更新类型。None ,AdaGrad,RmsProp- 当
gradUpdateType
为AdaGrad或RmsProp时可以使用下面的参数来控制gradupdate的行为: -
normWithAveMultiplier
:通过 AdaGrad/RmsProp算法使用适用与梯度的平均乘数来标准化梯度。默认true
当
gradUpdateType
的值为RmsProp时有如下参数:rms_wgt_inc
:学习率测量的乘法增量,默认是1.2rms_wgt_dec
:学习率测量的乘法减量,默认是0.75rms_wgt_max
:允许学习率测量的最大值,越接近1,学习率的调整就越稳定也越慢,默认是10rms_wgt_min
:允许学习率测量的最小值,越接近1,学习率的调整就越稳定也越慢,默认是0.1rms_gamma
:学习率测量的乘法增量,用于估计方差平均移动的平滑因子,值越小s,忘记前面信息的速度就越快。默认是0.99gaussianNoiseInjectStd
:用AdaGrad的方法时,增加的高斯噪声的标准偏差。默认是0
信息显示- traceLevel:0(默认),1. 表示输出信息的级别。
- numMBsToShowResult:显示训练过程中每多少个minibatches进行统计。默认10
梯度检查 - gradientCheck:是否使用梯度检查器。默认false。当使用梯度检查器时,需要使用大于sequence 长度的minibatch ,来提供给用于训练RNNs的被截断的backpropagation through time (BPTT) 算法,并且还要使用更小的学习率,以防止数值问题所造成的分歧。此外,精度应设置为double。
描述
SGD 块中的缺省设置项,将被设为默认值。
没有指定的参数也都为默认值
cntk中的minibatch size是什么?
CNTK中minibatchSize
参数的定义非常特殊:它是指更新模型样本的个数,这里的样本是指通过系统输入进来的向量或张量。例如,在图片识别中,一张图片就是一个样本。
重点强调一下,在处理连续的数据中,样本就是连续序列中的一项,因此,在CNTK中minibatchSize 并不是指多少个序列,而是可以指跨序列的个体的数量总和。CNTK原生支持可变长度的序列,在同样的minibatch中可以适应高度不同长度的序列而不需要使用类似bucketing这样的方法。连同指定每样本学习率的CNTK概念(而不是minibatch),任何长度序列中的每一项都会产生同样的梯度,导致统一收敛。(一些其他的工具会把minibatch 定义成为序列的数量,这就是问题,尤其是梯度被定义成为minibatch 的平均值而不是minibatch 的总和,因为每次从序列中获取数据的大小或是步长所生成的梯度与序列的长度成反比,CNTK的方法可以避免这个问题)
当使用了多个Input{}
,所有的input的序列长度不可能全部相同,例如,在给每一个序列单独的一个序列分类标签的问题中,使用控制样本的最大数量来输入。
尽管我们清晰的定义了minibatchSize 为更新模型过程中使用的样本个数。还有两个例外:
- 序列数据:可变长的序列不能一般的概括成minibatch size,在这种情况下,在一个minibatch size之内会将尽可能多的序列包装起来。(有一个例外:如果下一个序列的随机语料库超过了minibatch size,minibatch将成为这个序列的一部分)
- 数据并行:这里的minibatch size是一个近似值,因为基于块的随机算法不能够保证每一个工作站收到完全精确的相同样本数量。
所有上述的情况也适用于epochsize。
从其他工具中转化learning-rate和momentum 参数
CNTK的模型更新公式与其他的工具集和语法不同。参数是在不可知的minibatch size的方式下被指定。CNTK在训练中自动修改minibatch size,这在文本数据并行训练中很重要。在一个不可知的方式指定learning-rate和momentum避免了依赖于minibatch size变化时调整这些值的复杂性。
下面是CNTK模型更新中使用 momentum 参数在SGD中的公式:
G(t) = (1-mu) sum { g(t-minibatchSize+1) ... g(t) } + mu * G(t-minibatchSize)
mu = exp (-minibatchSize/momentumAsTimeConstant)
M(t) = M(t-minibatchSize) + learningRatePerSample G(t)
- G(t):t样本的平滑惯性梯度
- g(t’):在t’时样本的原梯度
- M(t):t样本之后所使用的模型
- t:minibatchSize的步长增量
(注意:当使用可变长度的序列,由于序列长度在minibatch一般不与minibathsize完全相等。minibathsize会略有波动) - momentum 过滤器G(t)是unit-gain,伴随时间所分发的每个样本的梯度总和是1.
- 学习率是被指定到每样本的,而不是w.r.t. 所有样本的平均值。
用于其它工具包和神经网络文章的规范往往是这样:
G'(t) = average { g(t-minibatchSize+1) ... g(t) } + mu * G'(t-minibatchSize)
M(t) = M(t-minibatchSize) + eta G'(t)
- G’:定义梯度为除去(1-mu)的每minibatch的平均值
- mu:momentum参数,例如0.9,应用于每mimibatch的non-unit-gain IIR过滤器
- eta:mimibatch平均值梯度的学习率
可以使用如下公式来将上述参数映射到CNTK的参数中:
learningRatePerSample = eta / minibatchSize / (1-mu)
momentumAsTimeConstant = -minibatchSize / ln (mu)
还可以使用如下方法来映射到learningRatePerMB 和momentumPerMB(注意:learningRatePerSample不需要/ (1-mu)):
learningRatePerSample = learningRatePerMB / minibatchSize
momentumAsTimeConstant = -minibatchSize / ln (momentumPerMB)
例如:
使用并行处理和自动minibatch标定的配置项 ImageHandsOn tutorial
SGD = {
epochSize = 50000
maxEpochs = 160 ; minibatchSize = 128
learningRatesPerSample = 0.0078125*80:0.00078125*40:0.000078125
momentumAsTimeConstant = 1200
L2RegWeight = 0.0001
firstMBsToShowResult = 10 ; numMBsToShowResult = 500
parallelTrain = {
parallelizationMethod = "dataParallelSGD"
parallelizationStartEpoch = 1
distributedMBReading = true
dataParallelSGD = { gradientBits = 2 }
}
autoAdjust = {
autoAdjustMinibatch = true # enable automatic growing of minibatch size
minibatchSizeTuningFrequency = 10 # try to enlarge after this many epochs
numMiniBatch4LRSearch = 200
minibatchSizeTuningMax = 15000 # out of memory above this
}
}