模型训练方法

规定:

  • 训练方法和参数初始化方法 - 图1为需要更新的参数
  • 训练方法和参数初始化方法 - 图2#card=math&code=g%28w%29)为在参数为训练方法和参数初始化方法 - 图3时计算的梯度值
  • 训练方法和参数初始化方法 - 图4为上一次的更新值(的变化)

对于模型的训练,神经网络基本都采用了梯度下降,不同方法的区别在于对于梯度下降的优化,由于梯度下降中,参数更新主要是依赖两个量:学习率和梯度,所以现有方法都是对于学习率和梯度进行了改进和优化。

首先,梯度下降按照按此步长处理的样本批次不同,分为BGD、min-BGD、SGD

对于学习率的改进,有一些是作为学习率设置,有一些是作为独特的一种优化方法,有:

  • 学习率衰减。通常都是按迭代次数,包括分段常数衰减、逆时衰减、指数衰减、自然指数衰减、余弦衰减
  • 学习率预热。指的在最初迭代时,先采用比较小的学习率,是梯度降到一定程度再恢复初始设定的学习率,提高训练稳定性。
  • 学习率周期性调整。有循环学习率(固定周期,相邻周期内学习率分别线性增加和线性减少)和带热重启的随机梯度下降(每个周期内学率进行余弦衰减,下一周期时重新初始为预先设定的值,但比上一周期的初始值小)
  • AdaGrad
  • RMSprop
  • AdaDelta

对于梯度的改进,有:

  • Momentum
  • Nesterov Accelerated Gradient

还有同时对学习率和梯度进行优化

  • Adam
  • Nadam

SGD

最普遍的随机梯度下降,对于参数的更新规则如下:

训练方法和参数初始化方法 - 图5%0A#card=math&code=w%20%3D%20w%20-%20%5Calpha%20g%28w%29%0A)

  1. optimizer = keras.optimizers.SGD(learning_rate=0.1)

momentum

在普通的梯度下降上引入动量的概念,即在梯度值上加上一部分上一次的更新值,可以更好的避免局部极值。更新规则如下:

训练方法和参数初始化方法 - 图6%0A#card=math&code=w%5Cprime%20%3D%20w%20%2B%20%5Crho%20%5CDelta%20%5C%5C%5C%5C%0Aw%20%3D%20w%5Cprime%20-%20%5Calpha%20g%28w%29%0A)

  1. optimizer = keras.optimizers.SGD(learning_rate=0.1, momentum=True)

Nesterov Accelerated Gradient, NAG

对momentum的改进,一个小变种,将momentum看作两步参数更新操作,将第一步参数的梯度用作第二步的梯度计算。更新规则如下:

训练方法和参数初始化方法 - 图7%0A#card=math&code=w%5Cprime%20%3D%20w%20%2B%20%5Crho%20%5CDelta%20%5C%5C%5C%5C%0Aw%20%3D%20w%5Cprime%20-%20%5Calpha%20g%28w%5Cprime%29%0A)

  1. optimizer = keras.optimizers.SGD(learning_rate=0.1, momentum=True, nesterov=True)

AdaGrad

全称:Adaptive Gradient Algorithm,每次迭代时自适应调整参数的学习率,借鉴了L2正则化思想,训练方法和参数初始化方法 - 图8为每个参数梯度平方的累计值。缺点是经过一定次数迭代学习率就会到很小了,如果没找到最优点,之后也很难再找到。

训练方法和参数初始化方法 - 图9%0A#card=math&code=Gt%20%3D%20%5Csum%7B%5Ctau%3D1%7D%5Et%20g%5Ctau%20%5Codot%20g%5Ctau%5C%5C%5C%5C%0Aw%20%3D%20w%20-%20%5Cfrac%7B%5Calpha%7D%7B%5Csqrt%7BG_t%20%2B%20%5Cepsilon%7D%7D%20%5Codot%20g%28w%29%0A)

  1. optimizer = keras.optimizers.Adagrad(learning_rate=0.001, initial_accuulator_value=0.1, epsilon=1e-7)

RMSprop

对AdaGrad的改进,对训练方法和参数初始化方法 - 图10的计算进行改进,从累积变为指数衰减平移,计算的是每次梯度平方的指数衰减移动平均(指数衰减平移),训练方法和参数初始化方法 - 图11为衰减率,如果下式中训练方法和参数初始化方法 - 图12位置都取1,就和AdaGrad相同,训练方法和参数初始化方法 - 图13通常取0.9:

训练方法和参数初始化方法 - 图14%20gt%20%5Codot%20g_t%5C%5C%5C%5C%5C%0Aw%20%3D%20w%20-%20%5Cfrac%7B%5Calpha%7D%7B%5Csqrt%7BG_t%20%2B%20%5Cepsilon%7D%7D%20%5Codot%20g(w)%0A#card=math&code=G_t%20%3D%20%5Cbeta%20G%7Bt-1%7D%20%2B%20%281-%5Cbeta%29%20g_t%20%5Codot%20g_t%5C%5C%5C%5C%5C%0Aw%20%3D%20w%20-%20%5Cfrac%7B%5Calpha%7D%7B%5Csqrt%7BG_t%20%2B%20%5Cepsilon%7D%7D%20%5Codot%20g%28w%29%0A)

  1. optimizer = keras.optimizers.RMSprop(learning_rate=0.001, rho=0.9, momentum=0.0, epsilon=1e-7, centered=False)

Adadelta

也是对于AdaGrad的改进,相比于AdaGrad,另外引入了对于每次参数更新差值训练方法和参数初始化方法 - 图15的指数衰减平移:

训练方法和参数初始化方法 - 图16%5CDelta%7Bt-1%7D%5Codot%20%5CDelta%7Bt-1%7D%20%5C%5C%5C%5C%0Aw%20%3D%20w%20-%20%5Cfrac%7B%5Csqrt%7B%5Chat%5CDelta%7Bt-1%7D%5E2%2B%5Cepsilon%7D%7D%7B%5Csqrt%7BG_t%20%2B%20%5Cepsilon%7D%7D%20%5Codot%20g(w)%0A#card=math&code=G_t%20%3D%20%5Csum%7B%5Ctau%20%3D1%7D%5Et%20g%5Ctau%20%5Codot%20g%5Ctau%20%5C%5C%5C%5C%0A%5Chat%20%5CDelta%7Bt-1%7D%5E2%20%3D%20%5Cbeta_1%20%5Chat%5CDelta%7Bt-2%7D%5E2%20%2B%20%281-%5Cbeta1%29%5CDelta%7Bt-1%7D%5Codot%20%5CDelta%7Bt-1%7D%20%5C%5C%5C%5C%0Aw%20%3D%20w%20-%20%5Cfrac%7B%5Csqrt%7B%5Chat%5CDelta%7Bt-1%7D%5E2%2B%5Cepsilon%7D%7D%7B%5Csqrt%7BG_t%20%2B%20%5Cepsilon%7D%7D%20%5Codot%20g%28w%29%0A)

optimizer = keras.optimizers.Adadelta(learning_rate=0.001, rho=0.95, epsilon=1e-7)

Adam

本质上就是Momentum和RMSprop的结合。一方面计算梯度平方的指数衰减平移,另一方面计算梯度的指数衰减平移,并且对于指数衰减平均计算公式进行了修正(初始时会具有较大偏差):

训练方法和参数初始化方法 - 图17g(w)%5C%5C%5C%5C%0AGt%20%3D%20%5Cbeta_2G%7Bt-1%7D%20%2B%20(1-%5Cbeta2)g(w)%5Codot%20g(w)%5C%5C%5C%5C%0A%5Chat%20M_t%20%3D%20%5Cfrac%7BM_t%7D%7B1-%5Cbeta_1%5Et%7D%5C%5C%5C%5C%0A%5Chat%20G_t%20%3D%20%5Cfrac%7BG_t%7D%7B1-%5Cbeta_2%5Et%7D%5C%5C%5C%5C%0Aw%20%3D%20w%20-%20%5Cfrac%7B%5Calpha%7D%7B%5Chat%20G_t%20%2B%20%5Cepsilon%7D%5Chat%20M_t%0A#card=math&code=M_t%20%3D%20%5Cbeta_1M%7Bt-1%7D%20%2B%20%281-%5Cbeta1%29g%28w%29%5C%5C%5C%5C%0AG_t%20%3D%20%5Cbeta_2G%7Bt-1%7D%20%2B%20%281-%5Cbeta_2%29g%28w%29%5Codot%20g%28w%29%5C%5C%5C%5C%0A%5Chat%20M_t%20%3D%20%5Cfrac%7BM_t%7D%7B1-%5Cbeta_1%5Et%7D%5C%5C%5C%5C%0A%5Chat%20G_t%20%3D%20%5Cfrac%7BG_t%7D%7B1-%5Cbeta_2%5Et%7D%5C%5C%5C%5C%0Aw%20%3D%20w%20-%20%5Cfrac%7B%5Calpha%7D%7B%5Chat%20G_t%20%2B%20%5Cepsilon%7D%5Chat%20M_t%0A)

optimizer = keras.optimizers.Adam(learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-7, amsgrad=False)

Nadam

在Adam中引入了Nsterov Accelerated Gradient。

optimizer = keras.optimizers.Nadam(learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-7)

Ftrl

用的比较少的一个优化算法,Google研究员提出的,在论文Ad Click Prediction: a View from the Trenches,基本可知其应用场景。

optimizer = keras.optimizers.Ftrl(
    learning_rate=0.001,
    learning_rate_power=-0.5,
    initial_accumulator_value=0.1,
    l1_regularization_strength=0.0,
    l2_regularization_strength=0.0,
    name="Ftrl",
    l2_shrinkage_regularization_strength=0.0,
    beta=0.0)

模型初始化方法

在keras中,每个初始化方式有两种命名放心,实现和功能都相同,一种是类似Java中的单词首字母大写,另外一种是Python中的驼峰式,单词之间用单个下划线进行分割。

RandomNormal

通过正态分布进行产生。

tf.keras.initializers.RandomNormal(mean=0, stddev=1.)
tf.keras.initializers.random_normal(mean=0, stddev=1.)

TruncatedNormal,与RandomNormal的区别是,超过两个标准差的数据将被剔除重新生成:

tf.keras.initializers.TruncatedNormal(mean=0, stddev=1.)
tf.keras.initializers.truncated_normal(mean=0, stddev=1.)

RandomUniform

通过均匀分布进行产生

tf.keras.initializers.RandomUniform(minval=-0.05, maxval=0.05, seed=None)
tf.keras.initializers.random_uniform(minval=-0.05, maxval=0.05, seed=None)

Zeros

全0初始化,最简单直接的操作了,基本只用在bias

tf.keras.initializers.Zeros()
tf.keras.initializers.zeros()

Ones

说到Zeros,就不得不说另一种很直接的方式,初始值都置为1:

tf.keras.initializers.Ones()
tf.keras.initializers.ones()

Constanct

指定一常数作为初始化参数的所有值

tf.keras.initializers.Constant(value=0)
tf.keras.initializers.constant(value=0)

GlorotNormal

也叫Xavier normal,具体实现是:

采用截断式的正态分布(TruncatedNormal),均值为0,标准差为训练方法和参数初始化方法 - 图18%7D#card=math&code=%5Csqrt%7B2%2F%28fan%7Bin%7D%2Bfan%7Bout%7D%29%7D),其中训练方法和参数初始化方法 - 图19分别是权重参数中的输入单元个数和输出单元个数

tf.keras.initializers.GlorotNormal()
tf.keras.initializers.glorot_normal()

GlorotUniform

也叫Xavier uniform,具体实现是:

采用均匀分布,上下界区间范围是训练方法和参数初始化方法 - 图20,其中训练方法和参数初始化方法 - 图21%7D#card=math&code=limit%20%3D%20%5Csqrt%7B6%2F%28fan%7Bin%7D%20%2B%20fan%7Bout%7D%29%7D)

tf.keras.initializers.GlorotUniform()
tf.keras.initializers.glorot_uniform()

HeNormal

He相对于Glorot,只是去掉了训练方法和参数初始化方法 - 图22,使得参数只与输入层有关,与输出层无关。具体实现是:

采用截断式的正态分布(TruncatedNormal),均值为0,标准差为训练方法和参数初始化方法 - 图23,其中分别是权重参数中的输入单元个数和输出单元个数

tf.keras.initializers.HeNormal()
tf.keras.initializers.he_normal()

HeUniform

具体实现是:

采用均匀分布,上下界区间范围是训练方法和参数初始化方法 - 图24,其中训练方法和参数初始化方法 - 图25

tf.keras.initializers.GlorotUniform()
tf.keras.initializers.glorot_uniform()

LecunNormal

Lecun和He,差别只在常系数值。具体实现是:

采用截断式的正态分布(TruncatedNormal),均值为0,标准差为训练方法和参数初始化方法 - 图26,其中分别是权重参数中的输入单元个数和输出单元个数

tf.keras.initializers.LecunNormal()
tf.keras.initializers.lecun_normal()

LecunUniform

具体实现是:

采用均匀分布,上下界区间范围是训练方法和参数初始化方法 - 图27,其中训练方法和参数初始化方法 - 图28

tf.keras.initializers.LecunNormal()
tf.keras.initializers.lecun_normal()

VarianceScaling

综合Glorot、He、Lecun等几大初始化方式,给了一个更加方便的调节方式。

如果是正态分布(Truncated或Unruncated),均值仍然为0,方差为训练方法和参数初始化方法 - 图29;如果是均匀分布,上下界绝对值相同,绝对值是训练方法和参数初始化方法 - 图30,其中参数通过API进行调节。keras中,Glorot、He、Lecun的几个初始化方式都是以VarianceScaling为父类实现的。

'''
scale: 缩放值
mode: fan_in, fan_out, fan_avg,分别是输入层值、输出层值、输入输出层值的均值
distribution: 选择的分布,可选值为:truncated_normal, untruncated_normal, uniform
'''
tf.keras.initializers.VarianceScaling(
scale=0.1, mode='fan_in', distribution='uniform')
tf.keras.initializers.variance_scaling(
scale=0.1, mode='fan_in', distribution='uniform')

Identity

将权重参数初始化为单位矩阵,由于形状不是方阵,只是使主对角线上元素为1(最小维度值构成的方阵为单位矩阵)

tf.keras.initializers.Identity()
tf.keras.initializers.identity()

Orthogonal

将权重参数初始化为正交矩阵,其中维数上的一侧正交(例如,如果行数少于列数,那么输出矩阵中行是正交的)

tf.keras.initializers.Orthogonal(gain=1.0, seed=None)
tf.keras.initializers.orthogonal(gain=1.0, seed=None)