【小白学PyTorch】4 构建模型三要素与权重初始化
文章目录:
1 模型三要素
三要素其实很简单
- 必须要继承nn.Module这个类,要让PyTorch知道这个类是一个Module
- 在__init__(self)中设置好需要的组件,比如conv,pooling,Linear,BatchNorm等等
- 最后在forward(self,x)中用定义好的组件进行组装,就像搭积木,把网络结构搭建出来,这样一个模型就定义好了
我们来看一个例子:
先看__init__(self)函数
def __init__(self):
super(Net,self).__init__()
self.conv1 = nn.Conv2d(3,6,5)
self.pool1 = nn.MaxPool2d(2,2)
self.conv2 = nn.Conv2d(6,16,5)
self.pool2 = nn.MaxPool2d(2,2)
self.fc1 = nn.Linear(16*5*5,120)
self.fc2 = nn.Linear(120,84)
self.fc3 = nn.Linear(84,10)
第一行是初始化,往后定义了一系列组件。nn.Conv2d就是一般图片处理的卷积模块,然后池化层,全连接层等等。
定义完这些定义forward函数
def forward(self,x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
x = x.view(-1,16*5*5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
x为模型的输入,第一行表示x经过conv1,然后经过激活函数relu,然后经过pool1操作
第三行表示对x进行reshape,为后面的全连接层做准备
至此,对一个模型的定义完毕,如何使用呢?
例如:
net = Net()
outputs = net(inputs)
其实net(inputs),就是类似于使用了net.forward(inputs)这个函数。
2 参数初始化
简单地说就是设定什么层用什么初始方法,初始化的方法会在torch.nn.init中
话不多说,看一个案例:
# 定义权值初始化
def initialize_weights(self):
for m in self.modules():
if isinstance(m,nn.Conv2d):
torch.nn.init.xavier_normal_(m.weight.data)
if m.bias is not None:
m.bias.data.zero_()
elif isinstance(m,nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m,nn.Linear):
torch.nn.init.normal_(m.weight.data,0,0.01)
# m.weight.data.normal_(0,0.01)
m.bias.data.zero_()
这段代码的基本流程就是,先从self.modules()中遍历每一层,然后判断更曾属于什么类型,是否是Conv2d,是否是BatchNorm2d,是否是Linear的,然后根据不同类型的层,设定不同的权值初始化方法,例如Xavier,kaiming,normal_等等。kaiming也是MSRA初始化,是何恺明大佬在微软亚洲研究院的时候,因此得名。
上面代码中用到了self.modules(),这个是什么东西呢?
# self.modules的源码
def modules(self):
for name,module in self.named_modules():
yield module
功能就是:能依次返回模型中的各层,yield是让一个函数可以像迭代器一样可以用for循环不断从里面遍历(可能说的不太明确)。
3 完整运行代码
我们用下面的例子来更深入的理解self.modules(),同时也把上面的内容都串起来(下面的代码块可以运行):
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset,DataLoader
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
torch.nn.init.xavier_normal_(m.weight.data)
if m.bias is not None:
m.bias.data.zero_()
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
torch.nn.init.normal_(m.weight.data, 0, 0.01)
# m.weight.data.normal_(0,0.01)
m.bias.data.zero_()
net = Net()
net.initialize_weights()
print(net.modules())
for m in net.modules():
print(m)
运行结果:
# 这个是print(net.modules())的输出
<generator object Module.modules at 0x0000023BDCA23258>
# 这个是第一次从net.modules()取出来的东西,是整个网络的结构
Net(
(conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
(pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
# 从net.modules()第二次开始取得东西就是每一层了
Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
Linear(in_features=400, out_features=120, bias=True)
Linear(in_features=120, out_features=84, bias=True)
Linear(in_features=84, out_features=10, bias=True)
其中呢,并不是每一层都有偏执bias的,有的卷积层可以设置成不要bias的,所以对于卷积网络参数的初始化,需要判断一下是否有bias,(不过我好像记得bias默认初始化为0?不确定,有知道的朋友可以交流)
torch.nn.init.xavier_normal(m.weight.data)
if m.bias is not None:
m.bias.data.zero_()
上面代码表示用xavier_normal方法对该层的weight初始化,并判断是否存在偏执bias,若存在,将bias初始化为0。
4 尺寸计算与参数计算
我们把上面的主函数部分改成:
net = Net()
net.initialize_weights()
layers = {}
for m in net.modules():
if isinstance(m,nn.Conv2d):
print(m)
break
这里的输出m就是:
Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
这个卷积层,就是我们设置的第一个卷积层,含义就是:输入3通道,输出6通道,卷积核\(5\times 5\),步长1,padding=0.
【问题1:输入特征图和输出特征图的尺寸计算】
之前的文章也讲过这个了,
\(output = \frac{input+2\times padding -kernel}{stride}+1\)
用代码来验证一下这个公式:
net = Net()
net.initialize_weights()
input = torch.ones((16,3,10,10))
output = net.conv1(input)
print(input.shape)
print(output.shape)
初始结果:
torch.Size([16, 3, 10, 10])
torch.Size([16, 6, 6, 6])
第一个维度上batch,第二个是通道channel,第三个和第四个是图片(特征图)的尺寸。
\(\frac{10+2\times 0-5}{1}+1=6\) 算出来的结果没毛病。
【问题2:这个卷积层中有多少的参数?】
输入通道是3通道的,输出是6通道的,卷积核是\(5\times 5\)的,所以理解为6个\(3\times 5\times 5\)的卷积核,所以不考虑bias的话,参数量是\(3\times 5\times 5\times 6=450\),考虑bais的话,就每一个卷积核再增加一个偏置值。(这是一个一般人会忽略的知识点欸)
下面用代码来验证:
net = Net()
net.initialize_weights()
for m in net.modules():
if isinstance(m,nn.Conv2d):
print(m)
print(m.weight.shape)
print(m.bias.shape)
break
输出结果是:
Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
torch.Size([6, 3, 5, 5])
torch.Size([6])
都和预料中一样。
【小白学PyTorch】4 构建模型三要素与权重初始化的更多相关文章
- 【小白学PyTorch】6 模型的构建访问遍历存储(附代码)
文章转载自微信公众号:机器学习炼丹术.欢迎大家关注,这是我的学习分享公众号,100+原创干货. 文章目录: 目录 1 模型构建函数 1.1 add_module 1.2 ModuleList 1.3 ...
- 【小白学PyTorch】20 TF2的eager模式与求导
[新闻]:机器学习炼丹术的粉丝的人工智能交流群已经建立,目前有目标检测.医学图像.时间序列等多个目标为技术学习的分群和水群唠嗑的总群,欢迎大家加炼丹兄为好友,加入炼丹协会.微信:cyx64501661 ...
- 【小白学PyTorch】18 TF2构建自定义模型
[机器学习炼丹术]的炼丹总群已经快满了,要加入的快联系炼丹兄WX:cyx645016617 参考目录: 目录 1 创建自定义网络层 2 创建一个完整的CNN 2.1 keras.Model vs ke ...
- 【小白学PyTorch】15 TF2实现一个简单的服装分类任务
[新闻]:机器学习炼丹术的粉丝的人工智能交流群已经建立,目前有目标检测.医学图像.时间序列等多个目标为技术学习的分群和水群唠嗑的总群,欢迎大家加炼丹兄为好友,加入炼丹协会.微信:cyx64501661 ...
- 【小白学PyTorch】5 torchvision预训练模型与数据集全览
文章来自:微信公众号[机器学习炼丹术].一个ai专业研究生的个人学习分享公众号 文章目录: 目录 torchvision 1 torchvision.datssets 2 torchvision.mo ...
- 【小白学PyTorch】8 实战之MNIST小试牛刀
文章来自微信公众号[机器学习炼丹术].有什么问题都可以咨询作者WX:cyx645016617.想交个朋友占一个好友位也是可以的~好友位快满了不过. 参考目录: 目录 1 探索性数据分析 1.1 数据集 ...
- 【小白学PyTorch】17 TFrec文件的创建与读取
[新闻]:机器学习炼丹术的粉丝的人工智能交流群已经建立,目前有目标检测.医学图像.时间序列等多个目标为技术学习的分群和水群唠嗑的总群,欢迎大家加炼丹兄为好友,加入炼丹协会.微信:cyx64501661 ...
- 小白学phoneGap《构建跨平台APP:phoneGap移动应用实战》连载三(通过实例来体验生命周期)
4.1.2 通过实例来亲身体验Activity的生命周期 上一小节介绍了Activity生命周期中的各个过程,本小节将以一个简单的实例来使读者亲身体验到Activity生命周期中的各个事件. 在Ec ...
- 【小白学PyTorch】19 TF2模型的存储与载入
[新闻]:机器学习炼丹术的粉丝的人工智能交流群已经建立,目前有目标检测.医学图像.时间序列等多个目标为技术学习的分群和水群唠嗑的总群,欢迎大家加炼丹兄为好友,加入炼丹协会.微信:cyx64501661 ...
随机推荐
- Pandas 数据处理 | Datetime 在 Pandas 中的一些用法!
Datatime 是 Python 中一种时间数据类型,对于不同时间格式之间的转换是比较方便的,而在 Pandas 中也同样支持 DataTime 数据机制,可以借助它实现许多有用的功能,例如 1,函 ...
- QString字符串的查找与截取实例
QString是Qt中封装的字符串类,相对于标准库里的string,使用方法有些不同,个人感觉使用qt习惯后,感觉QString更好用,下面的代码主要是针对QString的字符查找.截取做的测试: # ...
- VMware虚拟机磁盘收缩的几种方法
原文地址:http://www.cnblogs.com/5201351/p/4290401.html 根据下面转载的内容,我在VMware 12.0.0 build-2985596的ubuntu上做试 ...
- 云原生数据库mysql对共享存储分布式文件系统的接口需求分析
1. 引言 云原生数据库跟分布式mpp数据库是有差异的,虽然两者都是计算与存储分离,但是在资源的占用上有所不同.云原生数据库是shard everything架构,其依赖的存储资源.内存资源.事务资源 ...
- 2018-04-19:innodb和myisam区别
福哥答案2020-04-19:
- 【深度学习】:一门入门3D计算机视觉
一.导论 目前深度学习已经在2D计算机视觉领域取得了非凡的成果,比如使用一张图像进行目标检测,语义分割,对视频当中的物体进行目标跟踪等任务都有非常不错的效果.传统的3D计算机视觉则是基于纯立体几何来实 ...
- noip复习——快速幂
\(a ^ n \bmod p\) \(a, p, n \leq 10^9\) 最普通的二进制拆分 #define LL long long LL qpow(LL a, LL n, LL p) { L ...
- 【ZJOI 2008】 树的统计 - 树链剖分
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u ...
- powerMock和mockito使用
powerMock和mockito powermock和mockito都是做mock的框架,powermock在mockito的基础上扩展而来,支持mockito的操作(也支持别的mock框架比如ea ...
- Windows 右键 照片查看器 不见了--解决办法
桌面新建 一个文本文档,将下边复制进去,另存为命名例如为:1.reg 双击运行1.reg,点‘是’,点确认即可. Windows Registry Editor Version 5.00 ; Chan ...