深度学习 —参数初始化以及损失函数
文章目录
- 深度学习 ---参数初始化以及损失函数
- 一,参数初始化
- 1.1 固定值初始化
- 1.1.1 全0初始化
- 1.1.2 全1初始化
- 1.3 任意常数初始化
- 1.2 随机初始化
一,参数初始化
神经网络的参数初始化是训练深度学习模型的关键步骤之一。初始化参数(通常是权重和偏置)会对模型的训练速度、收敛性以及最终的性能产生重要影响。
1.1 固定值初始化
固定值初始化是指在神经网络训练开始时,将所有权重或偏置初始化为一个特定的常数值。这种初始化方法虽然简单,但在实际深度学习应用中通常并不推荐。
1.1.1 全0初始化
方面 | 内容 |
---|---|
方法 | 将所有权重初始化为零。 |
缺点 | 1. 对称性破坏:每个神经元在每一层中都会执行相同的计算,模型无法学习。 2. 权重更新一致:在反向传播时,所有神经元会收到相同的梯度,导致权重更新完全一致。 3. 降低表达能力:同一层的神经元会保持相同的功能,极大降低模型的表达能力。 |
应用场景 | 通常不用来初始化权重,但可以用来初始化偏置。 |
对称性问题 | - 现象:同一层的所有神经元具有完全相同的初始权重和偏置。 - 后果:在反向传播时,所有神经元会收到相同的梯度,导致权重更新完全一致;无论训练多久,同一层的神经元本质上会保持相同的功能(相当于“一个神经元”的多个副本),极大降低模型的表达能力。 |
import torch
import torch.nn as nndef test004():linear = nn.Linear(in_features=6, out_features=4)nn.init.zeros_(linear.weight)print(linear.weight)if __name__ == "__main__":test004()
1.1.2 全1初始化
全1初始化会导致网络中每个神经元接收到相同的输入信号,进而输出相同的值,这就无法进行学习和收敛。所以全1初始化只是一个理论上的初始化方法,但在实际神经网络的训练中并不适用
import torch
import torch.nn as nndef test003():linear = nn.Linear(in_features=6, out_features=4)nn.init.ones_(linear.weight)print(linear.weight)if __name__ == "__main__":test003()
1.3 任意常数初始化
将所有参数初始化为某个非零的常数(如 0.1,-1 等)。虽然不同于全0和全1,但这种方法依然不能避免对称性破坏的问题
import torch
import torch.nn as nndef test002():linear = nn.Linear(in_features=6, out_features=4)nn.init.constant_(linear.weight, 0.63)print(linear.weight)passif __name__ == "__main__":test002()
1.2 随机初始化
方面 | 内容 |
---|---|
方法 | 使用随机数生成器为每个权重分配一个随机值。通常从某个分布(如正态分布或均匀分布)中采样。例如: - 均匀分布:从 [−a,a][-a, a][−a,a] 中随机采样,其中 aaa 是一个小的常数。 - 正态分布:从均值为0、标准差为 σ\sigmaσ 的正态分布中采样。 |
优点 | 1. 打破对称性:每个神经元的初始权重不同,避免了所有神经元执行相同计算的问题。 2. 加速收敛:随机初始化可以避免梯度消失或梯度爆炸的问题,使训练过程更加稳定。 3. 提高模型表达能力:不同的初始权重使得每个神经元能够学习不同的特征,增强了模型的表达能力。 |
缺点 | 1. 选择合适的范围:如果随机初始化的范围过大或过小,可能会导致训练不稳定或收敛缓慢。例如,范围过大可能导致梯度爆炸,范围过小可能导致梯度消失。 2. 需要调整超参数:需要选择合适的分布和范围,这可能需要一些实验和调优。 |
应用场景 | 适用于大多数神经网络的权重初始化,尤其是深层网络。正态分布和均匀分布是最常用的初始化方法。 |
注意事项 | 1. 小范围初始化:通常选择较小的随机范围,例如 [−0.01,0.01][-0.01, 0.01][−0.01,0.01] 或标准差为0.01的正态分布。 2. 根据网络深度调整:对于较深的网络,可能需要更小的初始化范围,以避免梯度消失或爆炸。 3. 结合激活函数:不同的激活函数可能需要不同的初始化策略。例如,ReLU 激活函数通常需要使用 He 初始化(正态分布,标准差为 2/n\sqrt{2/n}2/n),而 Sigmoid 或 Tanh 激活函数通常使用 Xavier 初始化(均匀分布或正态分布,范围根据输入和输出维度调整)。 |
def test01():model =nn.Linear(8,1)print(model.weight)#均匀分步初始化nn.init.normal_(model.weight,mean=0,std=0.01)print(model.weight)#正态分布初始化# 均值为0,标准差为0.01nn.init.normal_(model.weight,mean=0,std=0.01)print(model.weight)
if __name__ == '__main__':test01()