问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

深度学习中权重初始化的重要性

创作时间:
作者:
@小白创作中心

深度学习中权重初始化的重要性

引用
CSDN
1.
https://m.blog.csdn.net/weixin_42255757/article/details/138348767

深度学习模型的权重初始化是一个容易被忽视但至关重要的步骤。不当的权重初始化可能导致模型训练失败或训练速度缓慢。本文将通过理论分析和实验验证,深入探讨不同权重初始化方法对模型训练的影响。

为什么需要权重初始化?

在深度学习中,权重初始化的方式对模型的训练效果有着重要影响。如果权重初始化不当,可能会导致以下问题:

  1. 梯度消失或梯度爆炸:如果权重值设置为全零或完全相同的值,在误差反向传播过程中,所有权重都会进行相同的更新,导致梯度消失或梯度爆炸。
  2. 表现力受限:如果权重初始化过于集中,会导致神经元输出趋于相同,从而限制模型的表现力。

不同权重初始化方法的比较

1. 高斯分布初始化

最简单的权重初始化方法是使用均值为0、标准差为0.01的高斯分布:

np.random.randn(10, 100) * 0.01

但是,这种初始化方法存在以下问题:

  • 当使用Sigmoid激活函数时,随着网络层数的增加,激活值会越来越集中到0和1,导致梯度消失。
  • 当使用ReLU激活函数时,如果初始化值过小,会导致神经元输出趋于相同,限制模型的表现力。

2. Xavier初始化

Xavier初始化是一种更适合Sigmoid激活函数的权重初始化方法。假设前一层的节点数是n,则初始权重使用均值为0、标准差为1/√n的高斯分布:

w = np.random.randn(node_num, node_num) * 1 / np.sqrt(n)

这种初始化方法可以保持各层激活值的分布具有适当的广度,避免梯度消失问题。

3. Kaiming初始化

对于ReLU激活函数,Kaiming初始化更为适用。Kaiming初始化在Xavier初始化的基础上,将标准差乘以√2:

w = np.random.randn(node_num, node_num) * np.sqrt(2 / node_num)

这种初始化方法可以增加ReLU激活函数的输出范围,避免梯度消失问题。

实验验证

为了验证不同初始化方法的效果,我们使用一个五层神经网络进行实验。激活函数使用Sigmoid函数,用直方图画出每层的激活值的数据分布:

import matplotlib.pyplot as plt
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
x = np.random.randn(1000, 100)  # 1000个数据,每个数据100维
node_num = 100  # 隐藏层的节点数
hidden_layer_size = 5  # 隐藏层的数量
activations = {}  # 激活值的结果
for i in range(hidden_layer_size):
    # i=0的时候先计算激活值,往后每次的输入值x都是上一次激活值结果
    if i != 0:
        x = activations[i - 1]
    w = np.random.randn(node_num, node_num) * 1  # 权重初始化
    z = np.dot(x, w)
    a = sigmoid(z)  # sigmoid函数
    activations[i] = a

高斯分布初始化(标准差为1)

可以看到,随着层数加深,越来越多的激活值集中到0和1,导致梯度消失问题。

Xavier初始化

Xavier初始化可以保持各层激活值的分布具有适当的广度,但随着层数增加,激活值会越来越靠近0。

Kaiming初始化

Kaiming初始化可以保持激活值均匀分布在0~1之间,适合通过反向传播进行学习。

实际应用中的效果对比

为了进一步验证不同初始化方法的效果,我们使用一个线性不可分数据集进行分类实验。数据集生成代码如下:

import numpy as np
import matplotlib.pyplot as plt
# 构建非线性可分数据集
def create_dataset():
    np.random.seed(1)
    m = 400  # 数据量
    N = int(m / 2)  # 每一类数据的个数
    dim = 2  # 数据维度
    X = np.zeros((m, dim))
    Y = np.zeros((m, 1), dtype='uint8')
    a = 4
    # 生成数据
    for j in range(2):
        ix = range(N * j, N * (j + 1))
        t = np.linspace(j * 3.12, (j + 1) * 3.12, N) + np.random.randn(N) * 0.2
        r = a * np.sin(4 * t) + np.random.randn(N) * 0.2
        X[ix] = np.c_[r * np.sin(t), r * np.cos(t)]
        Y[ix] = j
    X = X.T
    Y = Y.T
    return X, Y
X, Y = create_dataset()
X = X.T
Y = Y.T
print(Y.shape)
print(X.shape)
plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Paired)  # 画出数据

生成的图像如下:

我们使用一个简单的多层感知机进行分类实验,分别使用(0,0.01)的高斯分布和Xavier初始化进行权重初始化:

(0,0.01)高斯分布初始化

def initialize_parameters(n, num_hidden, m):
    # 初始化参数
    w1 = np.random.randn(num_hidden, n) * 0.01  # 从输入到隐藏层权重,随机初始化
    b1 = np.zeros((num_hidden, 1))  # 从输入到隐藏层偏置,初始化为零
    w2 = np.random.randn(m, num_hidden) * 0.01  # 从隐藏层到输出层权重,随机初始化
    b2 = np.zeros((m, 1))  # 从隐藏层到输出层权重,初始化为零
    parameters = {'w1': w1, 'w2': w2, 'b1': b1, 'b2': b2}
    return parameters

训练损失值如下:

================ 0.6931125167719424
================ 0.6929599436150587
================ 0.6928419798609118
================ 0.6927533221282552
================ 0.6926665006259728
================ 0.6925442899224475
================ 0.6923418054740101
================ 0.6919987185837877
================ 0.6914315483776486
================ 0.6905487939721282

可以看到损失值几乎不下降,无法训练。

Xavier初始化

def initialize_parameters(n, num_hidden, m):
    # 初始化参数
    w1 = np.random.randn(num_hidden, n) / np.sqrt(n)  # 从输入到隐藏层权重,Xavier初始化
    b1 = np.zeros((num_hidden, 1))  # 从输入到隐藏层偏置,初始化为零
    w2 = np.random.randn(m, num_hidden) / np.sqrt(num_hidden)  # 从隐藏层到输出层权重,Xavier初始化
    b2 = np.zeros((m, 1))  # 从隐藏层到输出层权重,初始化为零
    parameters = {'w1': w1, 'w2': w2, 'b1': b1, 'b2': b2}
    return parameters

训练损失值如下:

================ 0.7088135432785352
================ 0.6196813019938332
================ 0.5770935283638372
================ 0.5129738885023197
================ 0.46283119618617713
================ 0.4218237851915789
================ 0.3914602876997484
================ 0.3705175596789437
================ 0.354306018670427
================ 0.3409172900251636

可以看到,使用Xavier初始化后,训练损失值平稳下降,最终分类效果较好。

总结

权重初始化是深度学习中一个容易被忽视但至关重要的步骤。不同的初始化方法对模型的训练效果有着显著影响。在实际应用中,建议根据所使用的激活函数选择合适的初始化方法:

  • 对于Sigmoid激活函数,推荐使用Xavier初始化。
  • 对于ReLU激活函数,推荐使用Kaiming初始化。

虽然现代深度学习框架(如PyTorch)通常会提供默认的权重初始化方法,但在某些特殊场景下,手动选择合适的初始化方法仍然非常重要。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号