目录
1.1.1 tf.keras.initializers.VarianceScaling
1.2.1 tf.keras.layers.LeakyReLU
2.1.1 tf.keras.models.clone_model
tf.keras.callbacks.LearningRateScheduler
tf.keras.callbacks.ReduceLROnPlateau
4.1.1 tf.keras.regularizers.L1
4.1.2 tf.keras.regularizers.L1L2
4.1.3 tf.keras.regularizers.L2
4.3.1 tf.keras.constraints.MaxNorm
在实际模型训练中,可能遇到以下问题:
- 梯度消失:随着算法向下传播到较低层,梯度通常会越来越小,低层的连接权重几乎不变导致模型的无法收敛到一个很好的解
- 梯度爆炸:某些情况下(可能出现在递归神经网络中)梯度会越来越大,各层会产生较大的更新权重,直到算法发散
- 没有足够的训练数据
- 训练缓慢
- 参数过大造成过拟合
一、梯度消失与梯度爆炸
1.1 Glorot 和 He 初始化
针对梯度不稳定问题,Glorot 提出希望信号流动过程既不消失也不饱和,使得每层的输出方差等于其输入的方差,除非每层的输入和输出神经元数量相等,否则无法很好的保证。对此提出了 Xavier 初始化或者 Glorot 初始化来初始化每层的连接权重。
Glorot 初始化(激活函数采用逻辑函数)
正态分布,均值为0,方差
或 -r 和 +r 之间的均匀分布,其中
其中
使用 Glorot 初始化可以大大加快训练速度。用 代替
就成为 LeCun 初始化。各种激活函数的初始化参数见下表:
| 初始化 | 激活函数 | |
|---|---|---|
| Glorot | None、tanh、逻辑、softmax | |
| He | ReLU 和变体 | |
| LeCun | SELU |
默认情况下,Keras 使用具有均匀分布的 Glorot 初始化,但可以在创建层时可以通过设置 kernel_initializer 参数来更改初始化方式。
import tensorflow as tf
tf.keras.layers.Dense(10, activation='relu', kernel_initilizer='he_noraml')
如果想使用均匀分布但是基于 的 He 初始化,则可以通过 Variance Scaling 初始化。
he_avg_init = tf.keras.initializers.VarianceScalling(scale=2, mode='fan_avg', distribution='uniform')
tf.keras.layers.Dense(10, activation='sigmoid', kernel_initilizer=he_avg_init)
1.1.1 tf.keras.initializers.VarianceScaling
tf.keras.initializers.VarianceScaling(
scale=1.0, mode='fan_in', distribution='truncated_normal',
seed=None
)
| 参数 | 注释 |
|---|---|
| scale | 缩放因子 |
| mode | fan_in、fan_out、fan_avg 之一 |
| distribution | 要使用的随机分布。“truncated_normal”、“untruncated_normal”和“uniform”之一。 |
| 其它 | 见 tf.keras.initializers.VarianceScaling | TensorFlow Core v2.6.0 |
1.2 非饱和激活函数
梯度不稳定的一个原因就是由于激活函数选择不当;ReLU 激活函数由于对正值不饱和并且计算速度很快,所以表现要比逻辑函数好很多。但它存在神经元”死亡“问题,特别是在较大的学习率下,神经元权重调整时,输入的加权为负数,此时神经元就会死亡,只会继续输出0,因为 ReLU 激活函数的输入为负时梯度为 0。
通过对 ReLU 函数进行一些改动得到 LeakyRelU 函数,公式见下:
超参数 α 定义函数”泄露“程度,它时 z < 0 时函数的斜率,一般设置为 0.01,这就确保了神经元不会死亡但会陷入长时间的昏迷。同时也有观点认为将 α 设置为 0.2 (大泄露)会有更好的性能。也可以在训练中随机选择 α ,在测试过程将其固定为平均值,会有不错的表现。
也可以将 α 参数化得到 PReLU ,即在反向传播中修改,PReLU 在大型图像数据集的性能较优,但在小规模数据集上存在过拟合的风险。
LeakyReLU 的变体 ELU(指数线性单位)具有更好的性能:更短的训练时时间、更好的测试结果,其定义如下:
ELU 激活函数在 z 取负值时单元的平均输出接近 0 从而缓解梯度消失问题,超参数 α 定义了当 z 为较大负数时 ELU 逼近的值,一般设置为 1 ,并且 z 为负数时梯度不为 0 , 避免了神经元死亡问题;如果 α = 1 ,则函数在所有位置均平滑,有助于加速梯度下降。ELU 的计算速度较慢,但是会在训练过程具有更快的收敛速度。
SELU (可扩展的 ELU)激活函数是 ELU 的变体,如果构建一个仅由密集层堆叠组成的神经网络,并且所有隐藏层均使用 SELU 激活函数,则该网络是自归一化的,即每层的输出倾向于在训练过程中保留平均值 0 和标准差 1 ,从而解决了梯度不稳定的问题;就结果而言 SELU 大大优于其它激活函数。神经网络自归一化的条件如下:
- 输入特征必须标准化 (平均值是0,标准差是1)
- 隐藏层参数必须使用 LeCun 正态初始化
- 网络架构必须顺序
- 所有层都是密集层
激活函数的选择建议如下:
- 通常 SELU > ELU > leakyReLU (及变体) > ReLU > tanh > logistic
- 如果架构不能自归一化,则 ELU 性能可能优于 SELU
- 如果关注运行时的延迟, leaky RELU 可能会是更好的选择
- 如果不想调整其它的参数就可以使用 Keras 的默认参数值
- 如果有空闲时间和计算能力则可以使用交叉验证来评估其他激活函数(比如过拟合则可以使用 RReLU,训练集很大则可以使用 PReLU)
- 如果将速度放在首位,ReLU 仍可能是最好的选择
使用 LeakyReLu 、PReLU激活函数的代码参考如下:
model = tf.keras.models.Sequential([
# 其他层
tf.keras.layers.LeakyReLU(alpha=0.2) # leaky ReLU
tf.keras.layers.PReLU() # PReLU
# 其它层
])
使用 SELU 时,在创建层时设置 activation="selu" 和 kernel_initializer="lecun_normal":
tf.keras.layers.Dense(10, activation="selu", kernel_initializer="lecun_normal")
1.2.1 tf.keras.layers.LeakyReLU
tf.keras.layers.LeakyReLU(
alpha=0.3, **kwargs
)


6428

被折叠的 条评论
为什么被折叠?



