自定义layer

https://www.cnblogs.com/sdu20112013/p/12132786.html一文里说了怎么写自定义的模型.本篇说怎么自定义层.

分两种:

  • 不含模型参数的layer
  • 含模型参数的layer

核心都一样,自定义一个继承自nn.Module的类,在类的forward函数里实现该layer的计算,不同的是,带参数的layer需要用到nn.Parameter

不含模型参数的layer

直接继承nn.Module

import torch
from torch import nn class CenteredLayer(nn.Module):
def __init__(self, **kwargs):
super(CenteredLayer, self).__init__(**kwargs)
def forward(self, x):
return x - x.mean() layer = CenteredLayer()
layer(torch.tensor([1, 2, 3, 4, 5], dtype=torch.float)) net = nn.Sequential(nn.Linear(8, 128), CenteredLayer())
y = net(torch.rand(4, 8))
y.mean().item()

含模型参数的layer

  • Parameter
  • ParameterList
  • ParameterDict

Parameter类其实是Tensor的子类,如果一个TensorParameter,那么它会自动被添加到模型的参数列表里。所以在自定义含模型参数的层时,我们应该将参数定义成Parameter,除了直接定义成Parameter类外,还可以使用ParameterListParameterDict分别定义参数的列表和字典。

ParameterList用法和list类似

class MyDense(nn.Module):
def __init__(self):
super(MyDense,self).__init__()
self.params = nn.ParameterList([nn.Parameter(torch.randn(4,4)) for i in range(4)])
self.params.append(nn.Parameter(torch.randn(4,1))) def forward(self,x):
for i in range(len(self.params)):
x = torch.mm(x,self.params[i])
return x net = MyDense()
print(net)

输出

MyDense(
(params): ParameterList(
(0): Parameter containing: [torch.FloatTensor of size 4x4]
(1): Parameter containing: [torch.FloatTensor of size 4x4]
(2): Parameter containing: [torch.FloatTensor of size 4x4]
(3): Parameter containing: [torch.FloatTensor of size 4x4]
(4): Parameter containing: [torch.FloatTensor of size 4x1]
)
)

ParameterDict用法和python dict类似.也可以用.keys(),.items()

class MyDictDense(nn.Module):
def __init__(self):
super(MyDictDense, self).__init__()
self.params = nn.ParameterDict({
'linear1': nn.Parameter(torch.randn(4, 4)),
'linear2': nn.Parameter(torch.randn(4, 1))
})
self.params.update({'linear3': nn.Parameter(torch.randn(4, 2))}) # 新增 def forward(self, x, choice='linear1'):
return torch.mm(x, self.params[choice]) net = MyDictDense()
print(net) print(net.params.keys(),net.params.items()) x = torch.ones(1, 4)
net(x, 'linear1')

输出

MyDictDense(
(params): ParameterDict(
(linear1): Parameter containing: [torch.FloatTensor of size 4x4]
(linear2): Parameter containing: [torch.FloatTensor of size 4x1]
(linear3): Parameter containing: [torch.FloatTensor of size 4x2]
)
)
odict_keys(['linear1', 'linear2', 'linear3']) odict_items([('linear1', Parameter containing:
tensor([[-0.2275, -1.0434, -1.6733, -1.8101],
[ 1.7530, 0.0729, -0.2314, -1.9430],
[-0.1399, 0.7093, -0.4628, -0.2244],
[-1.6363, 1.2004, 1.4415, -0.1364]], requires_grad=True)), ('linear2', Parameter containing:
tensor([[ 0.5035],
[-0.0171],
[-0.8580],
[-1.1064]], requires_grad=True)), ('linear3', Parameter containing:
tensor([[-1.2078, 0.4364],
[-0.8203, 1.7443],
[-1.7759, 2.1744],
[-0.8799, -0.1479]], requires_grad=True))])

使用自定义的layer构造模型

layer1 = MyDense()
layer2 = MyDictDense() net = nn.Sequential(layer2,layer1)
print(net)
print(net(x))

输出

Sequential(
(0): MyDictDense(
(params): ParameterDict(
(linear1): Parameter containing: [torch.FloatTensor of size 4x4]
(linear2): Parameter containing: [torch.FloatTensor of size 4x1]
(linear3): Parameter containing: [torch.FloatTensor of size 4x2]
)
)
(1): MyDense(
(params): ParameterList(
(0): Parameter containing: [torch.FloatTensor of size 4x4]
(1): Parameter containing: [torch.FloatTensor of size 4x4]
(2): Parameter containing: [torch.FloatTensor of size 4x4]
(3): Parameter containing: [torch.FloatTensor of size 4x4]
(4): Parameter containing: [torch.FloatTensor of size 4x1]
)
)
)
tensor([[-4.7566]], grad_fn=<MmBackward>)

从头学pytorch(十一):自定义层的更多相关文章

  1. 从头学pytorch(一):数据操作

    跟着Dive-into-DL-PyTorch.pdf从头开始学pytorch,夯实基础. Tensor创建 创建未初始化的tensor import torch x = torch.empty(5,3 ...

  2. 从头学pytorch(三) 线性回归

    关于什么是线性回归,不多做介绍了.可以参考我以前的博客https://www.cnblogs.com/sdu20112013/p/10186516.html 实现线性回归 分为以下几个部分: 生成数据 ...

  3. 从头学pytorch(九):模型构造

    模型构造 nn.Module nn.Module是pytorch中提供的一个类,是所有神经网络模块的基类.我们自定义的模块要继承这个基类. import torch from torch import ...

  4. 从头学pytorch(六):权重衰减

    深度学习中常常会存在过拟合现象,比如当训练数据过少时,训练得到的模型很可能在训练集上表现非常好,但是在测试集上表现不好. 应对过拟合,可以通过数据增强,增大训练集数量.我们这里先不介绍数据增强,先从模 ...

  5. 从头学pytorch(七):dropout防止过拟合

    上一篇讲了防止过拟合的一种方式,权重衰减,也即在loss上加上一部分\(\frac{\lambda}{2n} \|\boldsymbol{w}\|^2\),从而使得w不至于过大,即不过分偏向某个特征. ...

  6. 从头学pytorch(十二):模型保存和加载

    模型读取和存储 总结下来,就是几个函数 torch.load()/torch.save() 通过python的pickle完成序列化与反序列化.完成内存<-->磁盘转换. Module.s ...

  7. 从头学pytorch(十五):AlexNet

    AlexNet AlexNet是2012年提出的一个模型,并且赢得了ImageNet图像识别挑战赛的冠军.首次证明了由计算机自动学习到的特征可以超越手工设计的特征,对计算机视觉的研究有着极其重要的意义 ...

  8. 从头学pytorch(十九):批量归一化batch normalization

    批量归一化 论文地址:https://arxiv.org/abs/1502.03167 批量归一化基本上是现在模型的标配了. 说实在的,到今天我也没搞明白batch normalize能够使得模型训练 ...

  9. 从头学pytorch(二十):残差网络resnet

    残差网络ResNet resnet是何凯明大神在2015年提出的.并且获得了当年的ImageNet比赛的冠军. 残差网络具有里程碑的意义,为以后的网络设计提出了一个新的思路. googlenet的思路 ...

随机推荐

  1. @codeforces - 1214F@ Employment

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 有 m 个城市围成一个圆环,编号为 1~m. 某公司有 n 个职 ...

  2. oracle函数 round(d1[,c1])

    [功能]:给出日期d1按期间(参数c1)四舍五入后的期间的第一天日期(与数值四舍五入意思相近) [参数]:d1日期型,c1为字符型(参数),c1默认为j(即最近0点日期) [参数表]:c1对应的参数表 ...

  3. 21Hash算法以及暴雪Hash

    一:哈希表简介 哈希表是一种查找效率极高的数据结构,理想情况下哈希表插入和查找操作的时间复杂度均为O(1),任何一个数据项可以在一个与哈希表长度无关的时间内计算出一个哈希值(key),然后在常量时间内 ...

  4. @loj - 2478@「九省联考 2018」林克卡特树

    目录 @description@ @solution@ @part - 1@ @part - 2@ @accepted code@ @details@ @description@ 小 L 最近沉迷于塞 ...

  5. HZOJ 走格子

    作者的正解: 对于100%的数据:行动可以分为两种: 1. 步行,花费一个单位的时间移动到4联通的相邻格子中去. 2. 使用传送门,指定一个方向的墙的前面的一个格子,步行至最近的一个墙的面前,使用传送 ...

  6. 2018-5-28-win10-uwp-动态修改ListView元素布局

    title author date CreateTime categories win10 uwp 动态修改ListView元素布局 lindexi 2018-05-28 15:15:54 +0800 ...

  7. 解决TortoiseSVN中out of date问题的一个方法

    http://blog.csdn.net/freefalcon/article/details/645058 从去年开始,公司的代码管理从CVS转向了subvsersion,后者确实是前者的一个飞跃, ...

  8. xml path 列转行实例

    SQL Server2005提供了一个新查询语法——For XML PATH(''),这个语法有什么用呢?想象一下这样一个查询需求:有两个表,班级表A.学生表B,要查询一个班级里有哪些学生?针对这个需 ...

  9. RBF神经网络通用函数 newrb, newrbe

      RBF神经网络通用函数 newrb, newrbe 1.newrb 其中P为输入向量,T为输出向量,GOAL为均方误差的目标,SPREED为径向基的扩展速度.返回值是一个构建好的网络,用newrb ...

  10. html(三)注册页面与重定向

    注册和登陆的建立是通过界面post提交表单然后在测试界面获取提交的值,进行判断. 1.测试传来的值,是否为空,将值传回到测试界面: ("Reg.jsp?errorCode=" + ...