PyTorch 基础 : 神经网络包nn和优化器optm

torch.nn是专门为神经网络设计的模块化接口。nn构建于 Autograd之上,可用来定义和运行神经网络。
这里我们主要介绍几个一些常用的类

约定:torch.nn 我们为了方便使用,会为他设置别名为nn,本章除nn以外还有其他的命名约定

# 首先要引入相关的包
import torch
# 引入torch.nn并指定别名
import torch.nn as nn
#打印一下版本
torch.__version__
'1.0.0'

除了nn别名以外,我们还引用了nn.functional,这个包中包含了神经网络中使用的一些常用函数,这些函数的特点是,不具有可学习的参数(如ReLU,pool,DropOut等),这些函数可以放在构造函数中,也可以不放,但是这里建议不放。

一般情况下我们会将nn.functional 设置为大写的F,这样缩写方便调用

import torch.nn.functional as F

定义一个网络

PyTorch中已经为我们准备好了现成的网络模型,只要继承nn.Module,并实现它的forward方法,PyTorch会根据autograd,自动实现backward函数,在forward函数中可使用任何tensor支持的函数,还可以使用if、for循环、print、log等Python语法,写法和标准的Python写法一致。

class Net(nn.Module):
def __init__(self):
# nn.Module子类的函数必须在构造函数中执行父类的构造函数
super(Net, self).__init__() # 卷积层 '1'表示输入图片为单通道, '6'表示输出通道数,'3'表示卷积核为3*3
self.conv1 = nn.Conv2d(1, 6, 3)
#线性层,输入1350个特征,输出10个特征
self.fc1 = nn.Linear(1350, 10) #这里的1350是如何计算的呢?这就要看后面的forward函数
#正向传播
def forward(self, x):
print(x.size()) # 结果:[1, 1, 32, 32]
# 卷积 -> 激活 -> 池化
x = self.conv1(x) #根据卷积的尺寸计算公式,计算结果是30,具体计算公式后面第二章第四节 卷积神经网络 有详细介绍。
x = F.relu(x)
print(x.size()) # 结果:[1, 6, 30, 30]
x = F.max_pool2d(x, (2, 2)) #我们使用池化层,计算结果是15
x = F.relu(x)
print(x.size()) # 结果:[1, 6, 15, 15]
# reshape,‘-1’表示自适应
#这里做的就是压扁的操作 就是把后面的[1, 6, 15, 15]压扁,变为 [1, 1350]
x = x.view(x.size()[0], -1)
print(x.size()) # 这里就是fc1层的的输入1350
x = self.fc1(x)
return x net = Net()
print(net)
Net(
(conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1))
(fc1): Linear(in_features=1350, out_features=10, bias=True)
)

网络的可学习参数通过net.parameters()返回

for parameters in net.parameters():
print(parameters)
Parameter containing:
tensor([[[[ 0.2745, 0.2594, 0.0171],
[ 0.0429, 0.3013, -0.0208],
[ 0.1459, -0.3223, 0.1797]]],

        [[[ 0.1847,  0.0227, -0.1919],
[-0.0210, -0.1336, -0.2176],
[-0.2164, -0.1244, -0.2428]]],

        [[[ 0.1042, -0.0055, -0.2171],
[ 0.3306, -0.2808, 0.2058],
[ 0.2492, 0.2971, 0.2277]]],

        [[[ 0.2134, -0.0644, -0.3044],
[ 0.0040, 0.0828, -0.2093],
[ 0.0204, 0.1065, 0.1168]]],

        [[[ 0.1651, -0.2244,  0.3072],
[-0.2301, 0.2443, -0.2340],
[ 0.0685, 0.1026, 0.1754]]],

        [[[ 0.1691, -0.0790,  0.2617],
[ 0.1956, 0.1477, 0.0877],
[ 0.0538, -0.3091, 0.2030]]]], requires_grad=True)
Parameter containing:
tensor([ 0.2355, 0.2949, -0.1283, -0.0848, 0.2027, -0.3331],
requires_grad=True)
Parameter containing:
tensor([[ 2.0555e-02, -2.1445e-02, -1.7981e-02, ..., -2.3864e-02,
8.5149e-03, -6.2071e-04],
[-1.1755e-02, 1.0010e-02, 2.1978e-02, ..., 1.8433e-02,
7.1362e-03, -4.0951e-03],
[ 1.6187e-02, 2.1623e-02, 1.1840e-02, ..., 5.7059e-03,
-2.7165e-02, 1.3463e-03],
...,
[-3.2552e-03, 1.7277e-02, -1.4907e-02, ..., 7.4232e-03,
-2.7188e-02, -4.6431e-03],
[-1.9786e-02, -3.7382e-03, 1.2259e-02, ..., 3.2471e-03,
-1.2375e-02, -1.6372e-02],
[-8.2350e-03, 4.1301e-03, -1.9192e-03, ..., -2.3119e-05,
2.0167e-03, 1.9528e-02]], requires_grad=True)
Parameter containing:
tensor([ 0.0162, -0.0146, -0.0218, 0.0212, -0.0119, -0.0142, -0.0079, 0.0171,
0.0205, 0.0164], requires_grad=True)

net.named_parameters可同时返回可学习的参数及名称。

for name,parameters in net.named_parameters():
print(name,':',parameters.size())
conv1.weight : torch.Size([6, 1, 3, 3])
conv1.bias : torch.Size([6])
fc1.weight : torch.Size([10, 1350])
fc1.bias : torch.Size([10])

forward函数的输入和输出都是Tensor

input = torch.randn(1, 1, 32, 32) # 这里的对应前面fforward的输入是32
out = net(input)
out.size()
torch.Size([1, 1, 32, 32])
torch.Size([1, 6, 30, 30])
torch.Size([1, 6, 15, 15])
torch.Size([1, 1350]) torch.Size([1, 10])
input.size()
torch.Size([1, 1, 32, 32])

在反向传播前,先要将所有参数的梯度清零

net.zero_grad()
out.backward(torch.ones(1,10)) # 反向传播的实现是PyTorch自动实现的,我们只要调用这个函数即可

注意:torch.nn只支持mini-batches,不支持一次只输入一个样本,即一次必须是一个batch。

也就是说,就算我们输入一个样本,也会对样本进行分批,所以,所有的输入都会增加一个维度,我们对比下刚才的input,nn中定义为3维,但是我们人工创建时多增加了一个维度,变为了4维,最前面的1即为batch-size

损失函数

在nn中PyTorch还预制了常用的损失函数,下面我们用MSELoss用来计算均方误差

y = torch.arange(0,10).view(1,10).float()
criterion = nn.MSELoss()
loss = criterion(out, y)
#loss是个scalar,我们可以直接用item获取到他的python类型的数值
print(loss.item())
28.92203712463379

优化器

在反向传播计算完所有参数的梯度后,还需要使用优化方法来更新网络的权重和参数,例如随机梯度下降法(SGD)的更新策略如下:

weight = weight - learning_rate * gradient

在torch.optim中实现大多数的优化方法,例如RMSProp、Adam、SGD等,下面我们使用SGD做个简单的样例

import torch.optim
out = net(input) # 这里调用的时候会打印出我们在forword函数中打印的x的大小
criterion = nn.MSELoss()
loss = criterion(out, y)
#新建一个优化器,SGD只需要要调整的参数和学习率
optimizer = torch.optim.SGD(net.parameters(), lr = 0.01)
# 先梯度清零(与net.zero_grad()效果一样)
optimizer.zero_grad()
loss.backward() #更新参数
optimizer.step()
torch.Size([1, 1, 32, 32])
torch.Size([1, 6, 30, 30])
torch.Size([1, 6, 15, 15])
torch.Size([1, 1350])

这样,神经网络的数据的一个完整的传播就已经通过PyTorch实现了,下面一章将介绍PyTorch提供的数据加载和处理工具,使用这些工具可以方便的处理所需要的数据。

看完这节,大家可能对神经网络模型里面的一些参数的计算方式还有疑惑,这部分会在第二章 第四节 卷积神经网络有详细介绍,并且在第三章 第二节 MNIST数据集手写数字识别的实践代码中有详细的注释说明。


[Pytorch框架] 2.1.3 神经网络包nn和优化器optm的更多相关文章

  1. 【小知识】神经网络中的SGD优化器和MSE损失函数

    今天来讲下之前发的一篇极其简单的搭建网络的博客里的一些细节 (前文传送门) 之前的那个文章中,用Pytorch搭建优化器的代码如下: # 设置优化器 optimzer = torch.optim.SG ...

  2. [源码解析] PyTorch分布式优化器(2)----数据并行优化器

    [源码解析] PyTorch分布式优化器(2)----数据并行优化器 目录 [源码解析] PyTorch分布式优化器(2)----数据并行优化器 0x00 摘要 0x01 前文回顾 0x02 DP 之 ...

  3. 深度学习框架PyTorch一书的学习-第四章-神经网络工具箱nn

    参考https://github.com/chenyuntc/pytorch-book/tree/v1.0 希望大家直接到上面的网址去查看代码,下面是本人的笔记 本章介绍的nn模块是构建与autogr ...

  4. 手写数字识别 卷积神经网络 Pytorch框架实现

    MNIST 手写数字识别 卷积神经网络 Pytorch框架 谨此纪念刚入门的我在卷积神经网络上面的摸爬滚打 说明 下面代码是使用pytorch来实现的LeNet,可以正常运行测试,自己添加了一些注释, ...

  5. 小白学习之pytorch框架(1)-torch.nn.Module+squeeze(unsqueeze)

    我学习pytorch框架不是从框架开始,从代码中看不懂的pytorch代码开始的 可能由于是小白的原因,个人不喜欢一些一下子粘贴老多行代码的博主或者一些弄了一堆概念,导致我更迷惑还增加了畏惧的情绪(个 ...

  6. 小白学习之pytorch框架(3)-模型训练三要素+torch.nn.Linear()

    模型训练的三要素:数据处理.损失函数.优化算法    数据处理(模块torch.utils.data) 从线性回归的的简洁实现-初始化模型参数(模块torch.nn.init)开始 from torc ...

  7. python日记:用pytorch搭建一个简单的神经网络

    最近在学习pytorch框架,给大家分享一个最最最最基本的用pytorch搭建神经网络并且训练的方法.本人是第一次写这种分享文章,希望对初学pytorch的朋友有所帮助! 一.任务 首先说下我们要搭建 ...

  8. PyTorch框架+Python 3面向对象编程学习笔记

    一.CNN情感分类中的面向对象部分 sparse.py super(Embedding, self).__init__() 表示需要父类初始化,即要运行父类的_init_(),如果没有这个,则要自定义 ...

  9. 全面解析Pytorch框架下模型存储,加载以及冻结

    最近在做试验中遇到了一些深度网络模型加载以及存储的问题,因此整理了一份比较全面的在 PyTorch 框架下有关模型的问题.首先咱们先定义一个网络来进行后续的分析: 1.本文通用的网络模型 import ...

  10. SSH框架应用中常用Jar包用途介绍

    struts2需要的几个jar包:1)xwork-core-2.1.62)struts2-core-2.1.83)ognl-2.7.34)freemarker-2.3.155)commons-io-1 ...

随机推荐

  1. JavaScript for in循环,for of循环

    一.JavaScript for/in 语句循环遍历对象的属性 var person={fname:"Bill",lname:"Gates",age:56}; ...

  2. FIR滤波器的设计

    FIR数字滤波器的设计 线性相位FIR滤波器的特点 单位冲激响应:\(h(n),0\leq n\leq N-1\) 系统函数:\(H(z)=\sum_{n=0}^{N-1}h(n)z^{-n}\) 零 ...

  3. gstreamer样例

    #!/bin/bash xrandr -s 0 --output DSI-1 xrandr -s 0 --output HDMI-1 xrandr --fb 1024x600 --output DSI ...

  4. [.Net]Framwork WebAPI添加接口请求监控

    思路: 通过重写 ActionFilterAttribute 拦截Action的请求及返回信息,实现对接口请求的监听. 最终效果如下: 全局启用需配置如下: 局部启用需配置如下: 源码如下: 1 // ...

  5. element中表格中对其解决方法:

    element中表格中对其解决方法: 一开始错位的表格的样式:​ 发现我们设置的align="center"居中没人用  后面是操作列里的按钮影响了它   直接把align里的属性 ...

  6. 实验五:开源控制器实践——POX

    基本要求 1.tcpdump 验证Hub模块 h1 ping h2的tcpdump抓包结果截图 h1 ping h3的tcpdump抓包结果截图 2.tcpdump 验证Switch模块 h1 pin ...

  7. 手写 Java HashMap 核心源码

    手写 Java HashMap 核心源码 手写 Java HashMap 核心源码 上一章手写 LinkedList 核心源码,本章我们来手写 Java HashMap 的核心源码. 我们来先了解一下 ...

  8. Liunx下tomcat安装配置

    1.在LIUNX下下载tomcat.wget apache-tomcat-7.0.41.tar.gz 2.在安装目录下解压. tar -zxvf apache-tomcat-7.0.41.tar.gz ...

  9. luac编译命令

    luac -o out.lua 1.lua 可以不要后缀 luac -o out 1.lua

  10. 2.C/C++的const

    1.C语言的const修饰的变量都有空间 2.C语言的const修饰的全局变量具有外部链接属性 3.C++语言的const修饰的变量有时有空间,有时没有空间(发生常量折叠,且没有对变量进行取址操作) ...