Python实现Xavier初始化
在开始之前,我们先回顾一下神经网络模型Xavier初始化的基本原理。
一、Xavier初始化基本内容
| |
|---|
| 核心目标 | 防止深度神经网络在训练初期的梯度消失和梯度爆炸问题。 |
| 核心思想 | 在训练开始时,将信号的方差维持在一个合理的范围内,使得信号能够在前向传播和反向传播中有效地流动,既不衰减太快,也不膨胀过多。为了达到这一目的我们需要使神经网络的输入方差等于其输出方差 |
| 数学原理 | 保持前向传播和反向传播的信号方差稳定,推导出权重方差应为 。 |
| 两种形式 | 均匀分布的权重分布 |
| 适用场景 | 与 Tanh 和 Sigmoid 激活函数搭配效果最佳。 |
*表述输入或输出神经元的个数
二、Xavier初始化代码实现
2.1 正态分布
defxavier_normal_init(shape):
"""
使用Xavier正态分布初始化权重矩阵
参数说明:
shape: 权重矩阵的形状,例如(输入维度, 输出维度)
数学原理:
std = sqrt(2 / (n_input + n_output))
这个公式确保每层输出的方差大致相同
返回值:
初始化后的权重矩阵
"""
# 计算输入和输出的维度
# 对于全连接层,shape[0]是输入神经元数,shape[1]是输出神经元数
n_input = shape[0] # 前一层神经元数量(输入)
n_output = shape[1] # 当前层神经元数量(输出)
# 计算Xavier初始化所需的标准差
std_dev = np.sqrt(2.0 / (n_input + n_output))
# 从正态分布中采样并乘以标准差
# np.random.randn生成标准正态分布N(0,1)的随机数
weights = np.random.randn(*shape) * std_dev
return weights
*shape 中的星号(*)是一个解包操作符。np.random.randn(*shape) * std_dev等价于weights = np.random.randn(100, 50) * std_dev 当 shape = (100, 50) 时
2.2 均匀分布
defxavier_uniform_init(shape):
"""
使用Xavier均匀分布初始化权重矩阵
参数说明:
shape: 权重矩阵的形状
数学原理:
limit = gsqrt(6 / (n_input + n_output))
权重在[-limit, limit]范围内均匀分布
返回值:
初始化后的权重矩阵
"""
# 计算输入和输出的维度
n_input = shape[0]
n_output = shape[1]
# 计算均匀分布的边界
limit = np.sqrt(6.0 / (n_input + n_output))
# 从均匀分布中采样,范围是[-limit, limit]
# np.random.uniform生成均匀分布随机数
weights = np.random.uniform(-limit, limit, size=shape)
return weights