全连接层: 权值初始化

梯度消失与爆炸的由来

一般来说全连接网络的结构示意图如上:

我们先来看w2的梯度:

可以看到,梯度的值严重依赖于中间层的输出值。因此,我们必须控制这种输出的范围。 才能够让我们各个层的标准差处于正常范围。


Xavier 初始化

方差一致性:保持数据尺度维持在恰当的范围,通常方差为1.

激活函数:饱和函数,如Sigmoid,Tanh


同时考虑了前向传播和反向传播的数据尺度问题。最后我们得到权值的方差应该为:

D ( W ) = 2 n i + n i + 1 D(W) = \frac{2}{n_i+n_{i+1}} D(W)=ni+ni+12

其中, n i n_i ni表示输入神经元的个数, n i + 1 n_{i+1} ni+1表示输出神经元的个数。


通常情况下:Xavier采用均匀分布。如果它满足的分布如下:

可以得出如上的D(W)。

即,我们需要让

D ( W ) = 2 n i + n i + 1 = a 2 3 D(W)= \frac{2}{n_i+n_{i+1}} = \frac{a^2}{3} D(W)=ni+ni+12=3a2

可以得到: a = 6 n i + n i + 1 a = \frac{\sqrt{6}}{\sqrt{n_i+n_{i+1}}} a=ni+ni+1 6


非饱和激活函数

由于非饱和激活函数ReLU的使用,Xavier的方法不再适用。

KaiMing 初始化

为了解决非饱和激活函数下,Xiaver的初始化方法不再适用的问题,何恺明提出了新的初始化方法。

  • 同样遵循方差一致性原则
    保持数据尺度维持在一个恰当的范围,通常方差为1.

这种方法适用于ReLU函数及其变种函数。
在这类激活函数下,可以推导出:
D ( W ) = 2 n i D(W) = \frac{2}{n_i} D(W)=ni2

对于ReLU的变种(即负半轴具有一定斜率)的情况下:

D ( W ) = 2 ( 1 + a 2 ) × n i D(W)=\frac{2}{(1 + a^2)\times n_i} D(W)=(1+a2)×ni2

其中,a即为负半轴的斜率。

结合以上,权值的标准差为:

s t d ( W ) = 2 ( 1 + a 2 ) × n i std(W) = \sqrt{\frac{2}{(1+a^2)\times n_i}} std(W)=(1+a2)×ni2

好的,现在根据这个公式对权值进行初始化。再次观察网络层的输出范围:


nn.init.normal_(m.weight.data, std=np.sqrt(2 / self.neural_num))

以上,就是利用我的推导得出的标准差,对W进行0均值,std为 2 神 经 元 个 数 \sqrt{\frac{2}{神经元个数}} 2 的初始化。在这种情况下,我们查看输出:



layer:0, std:0.826629638671875
layer:1, std:0.8786815404891968
layer:2, std:0.9134422540664673
layer:3, std:0.8892471194267273

...

可以看到,恺明法的初始化是可以让各个层的输出值的std大约在1附近。

Pytorch中提供了恺明初始化的方法,使用的代码如下:

                nn.init.kaiming_normal_(m.weight.data)

以上。

Pytorch 提供的10种初始化方法

  • Xavier : 均匀分布
  • Xavier : 正态分布
  • KaiMing : 均匀分布
  • KaiMing : 正态分布
  • 均匀分布
  • 正态分布
  • 常数分布
  • 正交矩阵初始化
  • 单位矩阵初始化
  • 稀疏矩阵初始化

  • 日期: 2020年5月19日
  • email: lhypersonmail@163.com
  • 来源: DeepShare 学习笔记
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
您好,根据您的要求,以下是所需的MATLAB代码: %% 数据集生成 input = [0 0 1 1; 0 1 0 1; 1 1 1 1]; % 输入层数据 output = [0 1 1 0]; % 输出层数据 [l, w] = size(input); % 获取样本数和维数 %% 网络参数初始化 wh1 = rand(5, l); % 第一个隐藏层权值矩阵 bh1 = rand(5, 1); % 第一个隐藏层偏置量 wh2 = rand(4, 5); % 第二个隐藏层权值矩阵 bh2 = rand(4, 1); % 第二个隐藏层偏置量 wo = rand(1, 4); % 输出层权值矩阵 bo = rand(1, 1); % 输出层偏置量 %% 训练参数设置 alpha = 0.1; % 学习率 iteration = 10000; % 迭代次数 %% 网络训练 for i = 1 : iteration %% 前向传播 zh1 = wh1 * input + bh1; % 第一个隐藏层输入 ah1 = max(zh1, 0); % 第一个隐藏层激活 zh2 = wh2 * ah1 + bh2; % 第二个隐藏层输入 ah2 = max(zh2, 0); % 第二个隐藏层激活 zo = wo * ah2 + bo; % 输出层输入 ao = max(zo, 0); % 输出层激活 %% 计算误差 error = 0.5 * sum((output - ao) .^ 2); %% 反向传播 deltao = (ao - output) .* (zo > 0); % 输出层误差 deltah2 = (wo' * deltao) .* (zh2 > 0); % 第二个隐藏层误差 deltah1 = (wh2' * deltah2) .* (zh1 > 0); % 第一个隐藏层误差 %% 更新权值和偏置量 wo = wo - alpha * deltao * ah2'; % 输出层权值更新 bo = bo - alpha * sum(deltao, 2); % 输出层偏置量更新 wh2 = wh2 - alpha * deltah2 * ah1'; % 第二个隐藏层权值更新 bh2 = bh2 - alpha * sum(deltah2, 2); % 第二个隐藏层偏置量更新 wh1 = wh1 - alpha * deltah1 * input'; % 第一个隐藏层权值更新 bh1 = bh1 - alpha * sum(deltah1, 2); % 第一个隐藏层偏置量更新 %% 输出每一层最终权值矩阵和偏置量 if mod(i, 1000) == 0 fprintf('第 %d 次迭代:\n', i); disp(['wh1 = ', num2str(wh1)]); disp(['bh1 = ', num2str(bh1)]); disp(['wh2 = ', num2str(wh2)]); disp(['bh2 = ', num2str(bh2)]); disp(['wo = ', num2str(wo)]); disp(['bo = ', num2str(bo)]); fprintf('误差:%.4f\n', error); end end %% 测试代码 test_input = [1 0 0 1; 0 1 1 0; 1 0 1 0]; % 测试数据 test_output = [0 1 1 0]; % 测试标签 test_ah1 = max(wh1 * test_input + bh1, 0); % 第一个隐藏层测试结果 test_ah2 = max(wh2 * test_ah1 + bh2, 0); % 第二个隐藏层测试结果 test_ao = max(wo * test_ah2 + bo, 0); % 输出层测试结果 fprintf('测试误差:%.4f\n', 0.5 * sum((test_output - test_ao) .^ 2));

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

古承风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值