为什么要进行初始化

首先假设有一个两层全连接网络,第一层的第一个节点值为 \(H_{11}= \sum_{i=0}^n X_i*W_{1i}\),

这个时候,方差为 \(D(H_{11}) = \sum_{i=0}^n D(X_i) * D(W_{1i})\), 这个时候,输入\(X_i\)一般会做归一化,那么其方差为1,而权重W如果不进行归一化的话,H的方差就会变得很大,然后多层累计,下一次的输入会越来越大,使得网络不好收敛,如果权重W进行了初始化,使得其方差保持在1/n附近,那么方差H则会收敛在1附近,从而使得网络变得更好优化。 很多初始化都是使用的这个原理,控制每一层的输出,使其保持在一定的范围内。

一些常见初始化方法

Xavier

Xavier初始化也是类似的原理, 假设输入X 以及做了归一化,其方差为1 ,那么Xavier所希望的就是上述公式D(H) 保持在1左右,那么就可以得到公式

\[H_{layer1} = \sum_{i=0}^n D(X_i) * D(W_{1i})=n_1 *D(W) = 1 \\ H_{layer2} =\sum_{i=0}^n D(X_i) * D(W_{1i}) = n_2 *D(W) = 1
\]

其中n1 和 n2 为网络层的输入输出节点数量,一般情况下,输入输出是不一样的,为了均衡考虑,可以做一个平均操作,于是变得到 \(D(W) = \frac{2}{n_1+n_2}\)

这个时候,我们假设 W服从均匀分布 \(U[-a, a]\), 那么在这个条件下,

\[D(W) = \frac{(-a-a)^2}{12} = \frac{a^2}{3}
\]

推出\(a = \frac{\sqrt{6}}{\sqrt{n_1+n_2+1}}\),从而得到:

\[W \sim U[-\frac{\sqrt{6}}{\sqrt{n_1+n_2+1}},\frac{\sqrt{6}}{\sqrt{n_1+n_2+1}}]
\]

这样就可以得到Xavier初始化,在pytorch中使用Xavier初始化方式如下,值得注意的是,Xavier对于sigmoid和tanh比较好,对于其他的可能效果就不是那么好了

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

Kaiming

Kaiming 初始化比较适合ReLU激活函数,其原理也跟上述差不多,也是希望将权重的方差保持在一定的范围内,使得正反向传播的值得到有效的控制,在kaiming初始化中,主要将权重的方差设置为 \(D(w) = \frac{2}{ni}\),由于考虑到ReLU激活函数,将方差调整为\(D(w)= \frac{2}{(1+a^2)*n_i}\), 这里的a是ReLU的斜率。

在pytorch中使用Kaiming初始化

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


LSTM初始化

LSTM中,公式和参数值的设定如下所示

在LSTM中,由于很多门控的权重尺寸是一样的,所以可以使用如下方法进行初始化

def _init_lstm(self, weight):
for w in weight.chunk(4, 0):
init.xavier_uniform(w) self._init_lstm(self.lstm.weight_ih_l0)
self._init_lstm(self.lstm.weight_hh_l0)
self.lstm.bias_ih_l0.data.zero_()
self.lstm.bias_hh_l0.data.zero_()

Embedding进行初始化

self.embedding = nn.Embedding(embedding_tokens, embedding_features, padding_idx=0)
init.xavier_uniform(self.embedding.weight)

其他通用初始化方法

遍历初始化

for name, param in net.named_parameters():
if 'weight' in name:
init.normal_(param, mean=0, std=0.01)
print(name, param.data) for name, param in net.named_parameters():
if 'bias' in name:
init.constant_(param, val=0)
print(name, param.data) ## 通过instance 初始化
for m in self.children():
if isinstance(m, nn.Linear):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, -100)
# 也可以判断是否为conv2d,使用相应的初始化方式
elif isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight.item(), 1)
nn.init.constant_(m.bias.item(), 0)

直接使用pytorch内置初始化

from torch.nn import init 

init.normal_(net[0].weight, mean=0, std=0.01) 

init.constant_(net[0].bias, val=0)

自带初始化方法中,会自动消除梯度反向传播,但是手动情况下必须自己设定

def no_grad_uniform(tensor, a, b):

  with torch.no_grad():

    return tensor.uniform_(a, b)

使用apply进行初始化

批量初始化方法,注意net里面的apply函数,可以作用网络的所有module

def weights_init(m):                                               # 1

  classname = m.__class__.__name__                             # 2

  if classname.find('Conv') != -1:                               # 3

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

  elif classname.find('BatchNorm') != -1:                        # 5

    nn.init.normal_(m.weight.data, 1.0, 0.02)                  # 6

    nn.init.constant_(m.bias.data, 0)                          # 7 

net.apply(weights_init)

Pytorch系列:(七)模型初始化的更多相关文章

  1. 计算广告CTR预估系列(七)--Facebook经典模型LR+GBDT理论与实践

    计算广告CTR预估系列(七)--Facebook经典模型LR+GBDT理论与实践 2018年06月13日 16:38:11 轻春 阅读数 6004更多 分类专栏: 机器学习 机器学习荐货情报局   版 ...

  2. Alamofire源码解读系列(七)之网络监控(NetworkReachabilityManager)

    Alamofire源码解读系列(七)之网络监控(NetworkReachabilityManager) 本篇主要讲解iOS开发中的网络监控 前言 在开发中,有时候我们需要获取这些信息: 手机是否联网 ...

  3. [Asp.net MVC]Asp.net MVC5系列——在模型中添加验证规则

    目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5 ...

  4. WCF编程系列(七)信道及信道工厂

    WCF编程系列(七)信道及信道工厂   信道及信道栈 前面已经提及过,WCF中客户端与服务端的交互都是通过消息来进行的.消息从客户端传送到服务端会经过多个处理动作,在WCF编程模型中,这些动作是按层 ...

  5. Asp.net MVC]Asp.net MVC5系列——在模型中添加

    目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5 ...

  6. iOS流布局UICollectionView系列七——三维中的球型布局

      摘要: 类似标签云的球状布局,也类似与魔方的3D布局 iOS流布局UICollectionView系列七——三维中的球型布局 一.引言 通过6篇的博客,从平面上最简单的规则摆放的布局,到不规则的瀑 ...

  7. [源码解析] PyTorch分布式(6) -------- DistributedDataParallel -- 初始化&store

    [源码解析] PyTorch分布式(6) ---DistributedDataParallel -- 初始化&store 目录 [源码解析] PyTorch分布式(6) ---Distribu ...

  8. Keil MDK STM32系列(七) STM32F4基于HAL的PWM和定时器

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  9. SQL Server 2008空间数据应用系列七:基于Bing Maps(Silverlight) 的空间数据展现

    原文:SQL Server 2008空间数据应用系列七:基于Bing Maps(Silverlight) 的空间数据展现 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft ...

随机推荐

  1. Bind DNS服务——转发与区域记录更新

    Linux基础服务--Bind DNS服务 Part4 转发与区域记录更新 一个DNS服务器不可能保存所有的区域记录,所以我们一般都会将其他的区域纪录转发到其他的服务器上进行解析. Bind9提供了全 ...

  2. Nebula 基于 ElasticSearch 的全文搜索引擎的文本搜索

    本文首发于 Nebula Graph 公众号 NebulaGraphCommunity,Follow 看大厂图数据库技术实践. 1 背景 Nebula 2.0 中已经支持了基于外部全文搜索引擎的文本查 ...

  3. 【NX二次开发】判断部件是否已修改(判断部件是否需要保存)UF_PART_is_modified();

    判断部件是否已修改(判断部件是否需要保存)UF_PART_is_modified(); 注意:函数需要输入原型,不要输入事例.事例转原型:UF_ASSEM_ask_prototype_of_occ() ...

  4. 生成树协议(STP)

    一.交换网络环路的产生 1.广播风暴的形成 2.多帧复制 3.MAC地址表紊乱 二.STP简介 STP-Spanning Tree Protocol(生成树协议) 逻辑上断开环路,防止广播风暴的产生 ...

  5. 基于websocket vue 聊天demo 解决方案

    基于websocket vue 聊天demo 解决方案 demo 背景 电商后台管理的客服 相关技术 vuex axios vue websocket 聊天几种模型 一对一模型 一对一 消息只一个客户 ...

  6. SpringCloud Alibaba实战(8:使用OpenFeign服务调用)

    源码地址:https://gitee.com/fighter3/eshop-project.git 持续更新中-- 在上一个章节,我们已经成功地将服务注册到了Nacos注册中心,实现了服务注册和服务发 ...

  7. 每日三道面试题,通往自由的道路4——JVM篇

    茫茫人海千千万万,感谢这一秒你看到这里.希望我的面试题系列能对你的有所帮助!共勉! 愿你在未来的日子,保持热爱,奔赴山海! 每日三道面试题,成就更好自我 昨天既然你有讲到字符串常量池是吧,那这样吧 1 ...

  8. 在 raspberry pi pico 上体验 MicroPython

    raspberry pi pico 官方提供 2 种开发方式,其中一种是使用 python3 开发,树莓派提供了 MicroPython 固件,把这个固件烧录进去,就可以 在 pico 上跑 pyth ...

  9. 基于C#的多边形冲突检测

    之前在项目上碰到了一个多边形冲突检测的问题,经百度.bing.google,发现目前已有的方案,要么是场景覆盖不全,要么是通过第三方类库实现(而这些第三方类库几乎是无法逆向反编译的),而项目中禁止使用 ...

  10. C#调用JAVA(二)调用方法

    上期我们创建了jar包并放到了unity中,那么我们继续 如果您还没有看上一期请先看上一期,这是链接 C#调用JAVA(一)制作jar包 - 执著GodShadow - 博客园 (cnblogs.co ...