steps/nnet3/train_dnn.py
--l2-regularize-factor
影响模型参数的l2正则化强度的因子。要进行l2正则化,主要方法是在配置文件中使用'l2-regularize'进行配置。l2正则化因子将乘以组件中的l2正则化值,并且可用于通过模型平均化以校正与并行化带来的影响。 (float,默认值= 1)
src/nnet3/nnet-utils.cc:2030
void ApplyL2Regularization(const Nnet &nnet, BaseFloat l2_regularize_scale, Nnet *delta_nnet) { /*...*/
//nnet是更新前的神经网络
const Component *src_component_in = nnet.GetComponent(c);
//delta_nnet是进行更新后的神经网络
UpdatableComponent *dest_component =
dynamic_cast<UpdatableComponent*>(delta_nnet->
GetComponent(c));
//delta_nnet->c -= 2.0 * l2_regularize_scale * alpha * eta * nnet.c
// alpha为L2正则化常数
// eta为学习率
// nnet.c为该nnet的component(应该是权重)
// l2_regularize来自于L2Regularization(),该函数返回UpdatableComponent中的L2正则化常量(通常由配置文件设定)。
// 根据steps/libs/nnet3/xconfig/basic_layers.py:471
// 可以xconfig中指定l2-regularize(默认为0.0)
// 一般通过ApplyL2Regularization()而非组件层的代码读取该常量。ApplyL2Regularization(),声明于nnet-utils.h(训练工作流的一部分)。
BaseFloat scale = -2.0 * l2_regularize_scale * lrate * l2_regularize;
// nnet3/nnet-simple-component.cc:1027
// linear_params_.AddMat(alpha, other->linear_params_);
// bias_params_.AddVec(alpha, other->bias_params_);
/*...*/}
//输出的统计数值
CuVector<double> value_sum_;
//非线性(神经元)的微分的统计数值(只适用于以向量元素为单位的非线性,不适用于Softmax)
CuVector<double> deriv_sum_;
//objective derivative function sum square
//目标函数微分的平方和,用于诊断
CuVector<double> oderiv_sumsq_;
//oderiv_sumsq_中stats数量
double oderiv_count_;
对于神经网络中的每个可更新组件c,假设它在组件中设定了l2正则化常量alpha(请参阅UpdatableComponent::L2Regularization())和学习率eta,那么此函数为(伪代码):
对求W偏导:
可以发现L2正则化项对b的更新没有影响,但是对于w的更新有影响:
delta_nnet-> c -= 2.0 * l2_regularize_scale * alpha * eta * nnet.c
nnet.c即w;
eta为学习率
因子-1.0(-=,减等于)是为了最大化正则化项;
因子2.0来自参数平方的导数。该函数使用了"l2_regularize_scale"因子,请参阅下面的说明。
注意:由于与自然梯度的相互作用,Kaldi的L2正则化是普通方法的近似。问题在于普通梯度乘以经过近似化、平滑化、比例缩放的Fisher矩阵的逆,但是l2梯度不是。这意味着我们正在优化的不是常规的"目标函数 + L2正则化项"这种形式,我们可以将其视为"常规目标函数 + L2正则化项 × Fisher矩阵" ,前提是 参数变化量不受到Fisher矩阵缩放的影响,所以这不会影响L2的整体强度,只会影响是方向(direction-wise)权重。实际上,在大的Fisher矩阵的变换方向上,相对于梯度,L2项的贡献将更大。这可能并不理想,但如果没有实验就很难判断。无论如何,L2的影响足够小,并且Fisher矩阵根据identity进行了充分的平滑,我怀疑这会产生很大的差别。
要为nnet3设定L2正则化,可以调用nnet3/xconfig_to_configs.py: