『PyTorch』第四弹_通过LeNet初识pytorch神经网络_上
总结一下相关概念:
- torch.Tensor - 一个近似多维数组的数据结构
- autograd.Variable - 改变Tensor并且记录下来操作的历史记录。和Tensor拥有相同的API,以及backward()的一些API。同时包含着和张量相关的梯度
- nn.Module - 神经网络模块,便捷的数据封装,能够将运算移往GPU,还包括一些输入输出的东西
- nn.Parameter - 一种变量(Variable),当将任何值赋予Module时自动注册为一个参数
- autograd.Function - 实现了使用自动求导方法的前馈和后馈的定义。每个Variable的操作都会生成至少一个独立的Function节点,与生成了Variable的函数相连之后记录下操作历史
导入库:
1 2 3 4 5 6 7 8 | # Author : Hellcat # Time : 2018/2/10 import torch as t import torch.nn as nn import torch.optim as optim import torch.nn.functional as F from torch.autograd import Variable |
torch.nn:网络层
torch.nn.functional:激活函数、池化函数归于此模块
pytorch中的网络层是class,而tensorflow
print(t.nn.Conv2d)
<class 'torch.nn.modules.conv.Conv2d'>
print(tf.nn.conv2d)
<function conv2d at 0x000001A33CC44510>
网络主体:
net网络要使用class并继承父类才行,因而有一些自带的方法
net.parameters():返回全部的参数值,迭代器
net.named_parameters():返回参数名称和值,迭代器
net.参数名:就是参数变量,Variable,可以直接查看data和grad等等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | class Net(nn.Module): def __init__( self ): # nn.Module子类的函数必须在构造函数中执行父类的构造函数 # 等价于nn.Model.__init__(self) super (Net, self ).__init__() # 输入1通道,输出6通道,卷积核5*5 self .conv1 = nn.Conv2d( 1 , 6 , 5 ) # 定义卷积层:输入6张特征图,输出16张特征图,卷积核5x5 self .conv2 = nn.Conv2d( 6 , 16 , 5 ) # 定义全连接层:线性连接(y = Wx + b),16*5*5个节点连接到120个节点上 self .fc1 = nn.Linear( 16 * 5 * 5 , 120 ) # 定义全连接层:线性连接(y = Wx + b),120个节点连接到84个节点上 self .fc2 = nn.Linear( 120 , 84 ) # 定义全连接层:线性连接(y = Wx + b),84个节点连接到10个节点上 self .fc3 = nn.Linear( 84 , 10 ) # 定义向前传播函数,并自动生成向后传播函数(autograd) def forward( self ,x): # 输入x->conv1->relu->2x2窗口的最大池化->更新到x x = F.max_pool2d(F.relu( self .conv1(x)),( 2 , 2 )) # 输入x->conv2->relu->2x2窗口的最大池化->更新到x x = F.max_pool2d(F.relu( self .conv2(x)), 2 ) # view函数将张量x变形成一维向量形式,总特征数不变,为全连接层做准备 x = x.view(x.size()[ 0 ], - 1 ) # 输入x->fc1->relu,更新到x x = F.relu( self .fc1(x)) # 输入x->fc2->relu,更新到x x = F.relu( self .fc2(x)) # 输入x->fc3,更新到x x = self .fc3(x) return x if __name__ = = "__main__" : net = Net() |
展示网络参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # #########查看参数######### print (net) """ Net( (conv1): Conv2d (1, 6, kernel_size=(5, 5), stride=(1, 1)) (conv2): Conv2d (6, 16, kernel_size=(5, 5), stride=(1, 1)) (fc1): Linear(in_features=400, out_features=120) (fc2): Linear(in_features=120, out_features=84) (fc3): Linear(in_features=84, out_features=10) ) """ # 返回参数值:顺序和下面的named一致 params = list (net.parameters()) print ( len (params)) """ 10 """ # net.named_parameters(): ((参数名称,参数属性),……) for name, parameters in net.named_parameters(): print (name, ":" , parameters.size()) """ conv1.weight : torch.Size([6, 1, 5, 5]) conv1.bias : torch.Size([6]) conv2.weight : torch.Size([16, 6, 5, 5]) conv2.bias : torch.Size([16]) fc1.weight : torch.Size([120, 400]) fc1.bias : torch.Size([120]) fc2.weight : torch.Size([84, 120]) fc2.bias : torch.Size([84]) fc3.weight : torch.Size([10, 84]) fc3.bias : torch.Size([10]) """ |
模拟单次向前&向后传播:
1 2 3 4 5 6 7 8 9 10 11 | # #########网络传播过程模拟######### # 输入如果没有batch数,则少一维度,Tensor,unsqueeze()可以为张量扩维 input_ = Variable(t.randn( 1 , 1 , 32 , 32 )) out = net(input_) print (out.size()) """ torch.Size([1, 10]) """ # net.zero_grad() # 输出值为10个标量(一个向量),所以需要指定每个标量梯度的权重 # out.backward(t.ones(1,10)) |
注意: torch.nn 只接受小批量的数据
整个torch.nn包只接受那种小批量样本的数据,而非单个样本。 例如,nn.Conv2d能够结构一个四维的TensornSamples x nChannels x Height x Width。
如果你拿的是单个样本,使用input.unsqueeze(0)来加一个假维度就可以了。
维度是[batch,channel,height,width]。
Loss函数构建
1 2 3 4 5 6 7 8 9 10 11 | # #########Loss设计######### target = Variable(t.arange( 0 , 10 )) # Loss需要先实例化,然后是callable的实例 loss_fn = nn.MSELoss() # 均方误差 loss = loss_fn(out, target) print (loss) net.zero_grad() print ( "反向传播之前:" , net.conv1.bias.grad) loss.backward() print ( "反向传播之后:" , net.conv1.bias.grad) |
反向传播之前: None
反向传播之后: Variable containing:
-0.1330
-0.0888
-0.0101
-0.0186
0.0462
0.0317
[torch.FloatTensor of size 6]
优化器构建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # #########优化器设计######### print (net.parameters()) """ <generator object Module.parameters at 0x0000021B525BE888> """ # 初始化优化器 optimizer = optim.SGD(net.parameters(), lr = 0.01 ) optimizer.zero_grad() # 效果等同net.zero_grad() output = net(input_) loss = loss_fn(output, target) loss.backward() print ( "反向传播之前:" , net.conv1.bias.data) optimizer.step() print ( "反向传播之后:" , net.conv1.bias.data) |
反向传播之前:
-0.1702
0.1192
0.1349
0.1307
-0.0141
-0.0558
[torch.FloatTensor of size 6]
反向传播之后:
-0.1689
0.1201
0.1350
0.1309
-0.0146
-0.0561
[torch.FloatTensor of size 6]
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 上周热点回顾(1.20-1.26)
· 【译】.NET 升级助手现在支持升级到集中式包管理