[pytorch入门] 6. 神经网络

news2024/12/24 8:04:39

基本介绍

  • torch.nn:
    在这里插入图片描述
    • Containers:基本骨架
    • Convolution Layers: 卷积层
    • Pooling layers:池化层
    • Non-linear Activations (weighted sum, nonlinearity):非线性激活
    • Normalization Layers:正则化层

Containers类

介绍

containers相对重要的一个类,主要给神经网络定义了一些骨架、一些结构,后面那些类都是要向骨架中填充的东西
里面有6个模块,其中module模块是里面最重要的一个模块
在这里插入图片描述
一般自己定义类,然后继承nn.module
里面一定要写的两个函数:__init__()和forward函数(前向传播)

from torch import nn
import torch
class Test(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self,input):
        output = input+1
        return output

test = Test()
# print(test.forward(1))
x = torch.tensor(1)
print(test(x))

Sequential 序列

将网络序列放到sequential里面,这样就可以调用一个模块连续使用自己定义的网络
这样会让代码更加简洁易懂

model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )

# Using Sequential with OrderedDict. This is functionally the
# same as the above code
model = nn.Sequential(OrderedDict([
          ('conv1', nn.Conv2d(1,20,5)),
          ('relu1', nn.ReLU()),
          ('conv2', nn.Conv2d(20,64,5)),
          ('relu2', nn.ReLU())
        ]))

在下节实战中进行实例演示

Convolution 卷积

基础理解

import torch
import torch.nn.functional as F

input = torch.tensor([[1,2,0,3,1],
                      [0,1,2,3,1],
                      [1,2,1,0,0],
                      [5,2,3,1,1],
                      [2,1,0,1,1]])
kernel = torch.tensor([
                        [1,2,1],
                        [0,1,0],
                        [2,1,0]
                    ])

# output = torch.nn.Conv2d(input)
# print(input.shape)
# print(kernel.shape)  # 目前不符合Con2d的尺寸要求,需要进行尺寸变换

input = torch.reshape(input, (1,1,5,5))  # 1个通道,1个样本,5行5列
kernel = torch.reshape(kernel, (1,1,3,3))  # 1个通道,1个样本,3行3列

print(input.shape)
print(kernel.shape)

# 之后进行卷积操作
output1 = F.conv2d(input, kernel, stride=1, padding=0) # stride步长,padding在输入图像的四周进行填充
print(output1)

output2 = F.conv2d(input, kernel, stride=2) # stride步长,padding填充
print(output2)

output3 = F.conv2d(input, kernel, stride=1, padding=1) # stride步长,padding在输入图像的四周进行填充
print(output3)   # 会发现比padding=0时大了一圈,因为padding=1时,会在输入图像的四周填充一圈0

output4 = F.conv2d(input, kernel, stride=1, padding=2) # stride步长,padding在输入图像的四周进行填充
print(output4)   # 会发现比padding=1时大了一圈,因为padding=2时,会在输入图像的四周填充两圈0

在这里插入图片描述

参数概念

def torch.nn.Conv2d(in_channels, out_channels, kernel_size,
 stride=1, padding=0, dilation=1, groups=1, bias=True, 
 padding_mode='zeros', device=None, dtype=None)

# in_channels:int,输入通道
# out_channels :int,输出通道
# kernel_size :int或元祖,卷积核的大小
# stride:int or tuple, optional。横向纵向的步径大小 默认为1
# padding (int, tuple or str, optional) 是否需要在输入图像的边缘进行填充,默认为0 不填充
# padding_mode (str, optional) – 'zeros', 'reflect', 'replicate' or 'circular' 控制如何填充,Default: 'zeros'即全部填充为0
# dilation (int or tuple, optional) – Spacing between kernel elements. Default: 1 卷积核之间的距离,一般为空洞卷积,不常用
# groups (int, optional) – Number of blocked connections from input channels to output channels. Default: 1
# bias (bool, optional) – If True, adds a learnable bias to the output. Default: True

实际上不需要自己写卷积核,他是会自己在输入图像中采样获得,只需要定义卷积核大小即可

使用

import torch
import torchvision
from torch.utils.data import DataLoader
from torch import nn
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10("./dataset",train = False, transform=torchvision.transforms.ToTensor(),download=True)

dataloader = DataLoader(dataset, batch_size=64, shuffle=True)

# 搭建简单神经网络
class Test(nn.Module):
    def __init__(self):
        super(Test,self).__init__()
        self.conv1 = nn.Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)

    def forward(self,x):
        x = self.conv1(x)
        return x
    
net = Test()


writer = SummaryWriter('logs')
step = 0
for data in dataloader:    # 一次性取出一个batch_size的数据,daaloader的使用见前面文章
    imgs, targets = data
    output = net(imgs)
    print(imgs.shape)
    print(output.shape)
    # print(output)
    print('-------')
    writer.add_images("input", imgs, step)

    # 但是这里output的shape是[64,6,30,30],6个通道没办法显示
    # 因此需要对output进行处理,使其变成[64,3,30,30]
    # 比较简单的方案是6个通道直接切开,变成两个bitch,每个bitch有3个通道(不是很严谨)
    # 当不知道batch_size的大小时,可以使用-1来代替,他会根据后面的数据直接计算
    output = torch.reshape(output,(-1,3,30,30))
    writer.add_images("output", output, step)
    step = step+1

在这里插入图片描述

辨析:nn 与 nn.functional

上面卷积操作的两个代码中,一个用的torch.nn.functional中的conv2d,一个用的torch.nn中的conv2d
nn 与 nn.functional有很多相同的函数,同时也有很多差异

相同点

  • 实际功能相同,即nn.Conv2d和nn.functional.conv2d 都是进行卷积,nn.Dropout 和nn.functional.dropout都是进行dropout等
  • 运行效率近乎相同

不同点

  • nn.functional.xxx是函数接口,而nn.XXX是nn.functional.xxx的类封装,并且nn.xxx都集成于同一个祖先nn.Module。这一点导致了nn.XXX除了具有nn.functional.xxx的功能之外,内部附带了nn.Module相关的属性和方法,例如train(), eval(),load_state_dict, state_dict 等。
  • 两者的调用方式不同
    • nn.xxx需要先实例化并传入参数,然后以函数调用的方式调用实例化的对象并传入输入数据

      input = img
      conv = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, padding=1)  # 实例化
      out = conv(input) # 以函数调用的方式调用实例化的对象并传入输入数据
      
    • nn.functional.xxx同时传入输入数据和weight、bias等其他参数

      weight = torch.rand(64,3,3,3)
      bias = torch.rand(64)
      out = nn.functional.conv2d(inputs, weight, bias, padding=1) # 调用函数的同时传入数据与参数
      
  • nn.Xxx继承于nn.Module, 能够很好的与nn.Sequential结合使用, 而nn.functional.xxx无法与nn.Sequential结合使用。
    fm_layer = nn.Sequential(
                nn.Conv2d(3, 64, kernel_size=3, padding=1),
                nn.BatchNorm2d(num_features=64),
                nn.ReLU(),
                nn.MaxPool2d(kernel_size=2),
                nn.Dropout(0.2)
      
    
  • nn.xxx不需要自己定义和管理weight,而functional.xxx需要自己定义weight,每次调用的时候都需要手动传入weight,不利于代码复用
    • 使用nn.xxx定义一个CNN
      class CNN(nn.Module):
          def __init__(self):
              super(CNN, self).__init__()
              
              self.cnn1 = nn.Conv2d(in_channels=1,  out_channels=16, kernel_size=5,padding=0)
              self.relu1 = nn.ReLU()
              self.maxpool1 = nn.MaxPool2d(kernel_size=2)
              
              self.cnn2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=5,  padding=0)
              self.relu2 = nn.ReLU()
              self.maxpool2 = nn.MaxPool2d(kernel_size=2)
              
              self.linear1 = nn.Linear(4 * 4 * 32, 10)
              
          def forward(self, x):
              x = x.view(x.size(0), -1)
              out = self.maxpool1(self.relu1(self.cnn1(x)))
              out = self.maxpool2(self.relu2(self.cnn2(out)))
              out = self.linear1(out.view(x.size(0), -1))
              return out
      
    • 用nn.function.xxx的写法
      class CNN(nn.Module):
          
          
          def __init__(self):
              super(CNN, self).__init__()
              
              self.cnn1_weight = nn.Parameter(torch.rand(16, 1, 5, 5))
              self.bias1_weight = nn.Parameter(torch.rand(16))
              
              self.cnn2_weight = nn.Parameter(torch.rand(32, 16, 5, 5))
              self.bias2_weight = nn.Parameter(torch.rand(32))
              
              self.linear1_weight = nn.Parameter(torch.rand(4 * 4 * 32, 10))
              self.bias3_weight = nn.Parameter(torch.rand(10))
              
          def forward(self, x):
              x = x.view(x.size(0), -1)
              out = F.conv2d(x, self.cnn1_weight, self.bias1_weight)
              out = F.relu(out)
              out = F.max_pool2d(out)
              
              out = F.conv2d(x, self.cnn2_weight, self.bias2_weight)
              out = F.relu(out)
              out = F.max_pool2d(out)
              
              out = F.linear(x, self.linear1_weight, self.bias3_weight)
              return out
      

选择

根据问题的复杂度和个人风格喜好决定
一般在能使用nn.xxx的情况下尽量使用,因为这样更能显示出网络间的层次关系,也更加纯粹

在nn.xxx不能满足功能需求时可以使用nn.functional.xxx,因为nn.functional.xxx更接近底层,更灵活

  • pytorch官方推荐:具有学习参数的(例如,conv2d, linear, batch_norm)采用nn.Xxx方式,没有学习参数的(例如,maxpool, loss func, activation func)等根据个人选择使用nn.functional.xxx或者nn.Xxx方式。

最大池化

介绍

池化的目的是保存主要内容的同时减少数据大小

用的比较多的为MaxPool2d,取kernel覆盖范围中最大的值输出

def MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=Flse,ceil_mode=False)
  • kernel_size:采样窗口大小
  • stride:步幅,注意这里默认值不一样了,卷积层为1,这里为kernel_size的大小
  • padding:填充值
  • dilation:kernel中每个格子中间是否存在间隔,一般不对其进行设置,有间隔时也称为空洞卷积
  • ceil_mode:设置为True时使用ceil模式,设置为False时使用floor模式
    • ceil模式:kernel覆盖不足时(边界越界时),保留获取的数值
    • floor模式:kernel覆盖不足时,不保留获取的数值

使用方法

import torch
from torch import nn
input = torch.tensor([[1,2,0,3,1],
                      [0,1,2,3,1],
                      [1,2,1,0,0],
                      [5,2,3,1,1],
                      [2,1,0,1,1]],
                    #   dtype=torch.float32  # 如果报错时,可以尝试加上这一行
                      )

input = torch.reshape(input,(1,1,5,5)) # 使之满足输入要求

class Test(nn.Module):
    def __init__(self):
        super(Test,self).__init__()
        self.maxpool = nn.MaxPool2d(kernel_size=3,padding=0,ceil_mode=False)

    def forward(self,input):
        output = self.maxpool(input)
        return output

net = Test()
output = net(input)
print(output)

实例

import torch
from torch import nn
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter


dataset = torchvision.datasets.CIFAR10('./dataset',train=False,transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=4)

class Test(nn.Module):
    def __init__(self):
        super(Test,self).__init__()
        self.maxpool = nn.MaxPool2d(kernel_size=3,padding=0,ceil_mode=False)

    def forward(self,input):
        output = self.maxpool(input)
        return output

net = Test()
writer = SummaryWriter('logs')
step = 0

for data in dataloader:
    imgs, targets = data
    writer.add_images('input',imgs, step)
    output = net(imgs)   # 池化不会改变channel的数量,因此不需要reshape
    writer.add_images('output',output, step)
    step = step+1
writer.close()

非线性激活

官方文档有很多非线性函数,这里举几个例子

ReLU

在这里插入图片描述
ReLU有一个参数inplace:用于指明是否修改原值

  • inplace=True:没有返回值,直接修改原值
  • inplace=False:不修改原值,有结果作为返回值返回
from torch import nn
import torch

class Test(nn.Module):
    def __init__(self):
        super(Test, self).__init__()
        self.relu1 = nn.ReLU(inplace=False)

    def forward(self, input):
        output = self.relu1(input)
        return output

net = Test()

input = torch.tensor([[1,2,0,-3,1],
                      [0,1,-2,3,1],
                      [1,2,1,0,0],
                      [-5,2,3,1,1],
                      [-2,1,0,1,1]])

output = net(input)
print(output)

在这里插入图片描述

Sigmod

ReLU对图像的处理不明显,这里用sigmod举例
在这里插入图片描述

from torch import nn
import torch
from torch.utils.tensorboard import SummaryWriter
import torchvision
from torch.utils.data import DataLoader

dataset = torchvision.datasets.CIFAR10('./dataset',train=False,transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset=dataset, batch_size=64)

class Test(nn.Module):
    def __init__(self):
        super(Test, self).__init__()
        self.sigmoid1 = nn.Sigmoid()

    def forward(self, input):
        output = self.sigmoid1(input)
        return output

net = Test()
writer = SummaryWriter('logs')
step=0
for data in dataloader:
    imgs, targets = data
    writer.add_images('input',imgs,step)
    output = net(imgs)
    writer.add_images('output',output,step)
    step = step+1
writer.close()


Linear Layers:线性层

在这里插入图片描述
比较常见的这种图实际上就是由线性层一个一个搭建出来的

def torch.nn.Linear(in_features, out_features, bias=True, device=None, dtype=None

参数中的in_features指的就是上面输入层数据的个数(即d),out_features即为输出层个数(前半部分的输出层为中间的隐藏层),bias=True时,计算会加上偏置b

# 例:将图片(如5*5)展开成一行(如1*25),经过线性层转换为x个

import torchvision
import torch
from torch import nn
from torch.utils.data import DataLoader


datasets = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(datasets, batch_size=64)

class Test(nn.Module):
    def __init__(self):
        super(Test, self).__init__()
        self.liner1 = nn.Linear(196608,10)
    
    def forward(self, input):
        output = self.liner1(input)
        return output

net = Test()

for data in dataloader:
    imgs, targets = data
    print("原始大小:",imgs.shape) 

    # output = torch.reshape(imgs,(1,1,1,-1)) # 将imgs展开成一行 输出效果见第一张图
    # 这里也可以直接用torch.flatten(imgs)来展开
    output = torch.flatten(imgs)  # 输出效果见第二张图
    print("转化为一维", output.shape)  # 先用这个来看一下展开后的大小,这是决定了线性层的输入大小
    # break
    
    output2 = net(output)
    print("线性层转化后", output2.shape)
    break

使用reshape:
在这里插入图片描述
使用torch.flatten:
在这里插入图片描述

其它层

Normalization 正则化层: 采用正则化的话会提高神经网络的训练速度
Recurrent Layers:一些特定的网络结构,含有RNN、LSTM等
Transformer Layers:已经写好的特定结构,与上面类似
Dropout Layers:也是在特定网络中才需要
Distance Functions:计算两个层之间的误差
Loss Functions:计算loss

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1408089.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

边缘计算及相关产品历史发展

边缘计算及相关产品历史发展 背景边缘计算的历史CDN(Content Delivery Network)Cloudlet雾计算MEC(Multi-Access Edge Computing,MEC) 边缘计算的现状云计算厂商硬件厂商软件基金会 背景 最近,公司部分业务…

基于springboot+vue的社区医院信息平台系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究背景…

阿赵UE学习笔记——解决UE资源不能正常显示缩略图的问题

阿赵UE学习笔记目录 大家好,我是阿赵。   这里分享一个虚幻引擎使用小技巧。在使用虚幻引擎的过程中,经常会遇到有些资源在重新打开项目的时候,会看不到缩略图,而是显示默认资源的图标: 这个时候,第一种…

应用app的服务器如何增加高并发

增强服务器的高并发能力是现代网络应用非常关键的需求。面对用户数量的不断增长和数据量的膨胀,服务器必须能够处理大量并发请求。以下是一些提高服务器高并发能力的常用方法和具体实施细节: 优化服务器和操作系统配置 服务器和操作系统的默认配置不一定…

快速上手的AI工具-文心一言绘画达人

前言 大家好,现在AI技术的发展,它已经渗透到我们生活的各个层面。对于普通人来说,理解并有效利用AI技术不仅能增强个人竞争力,还能在日常生活中带来便利。无论是提高工作效率,还是优化日常任务,AI工具都可…

【模拟通信】AM、FM等的调制解调

调制相关的概念 调制:控制载波的参数,使载波参数随调制信号的规律变化 已调信号:受调载波,含有调制信号的全部特征 调制的作用: 提高发射效率多路复用,提高信道利用率提高系统抗干扰能力 两种调制方式 线性调制&a…

网络协议与攻击模拟_08DHCP协议

技术学习要了解某项技术能干什么?它的详细内容?发展走向? 一、DHCP协议 1、DHCP基本概念 dhcp动态主机配置协议,广泛应用于局域网内部 主要是为客户机提供TCP/IP 参数(IP地址、子网掩码、网关、DNS等)…

STL第四讲

第四讲 万用Hash Function 左侧的是设计为类并重载调用运算符,右侧是一般函数的形势; 但是右侧形势在创建容器时更麻烦; 具体例子: 第三种形势:struct hash 偏特化形式 tuple 自C03引入; 关于源码解读的…

Linux服务器系统修改SSH端口教程

修改端口号是通过修改SSH的配置文件实现的,在服务器终端先激活root用户,然后输入: vim /etc/ssh/sshd_config找到#Port 22这个位置 键盘按i进入编辑模式 删除掉Port 22前面的#,然后键盘按一下回车键(如果没有#可不必…

软件产品为什么要测试才能上线?测试可以发现所有bug吗?

在现如今信息时代,软件产品已经成为人们生活中不可或缺的一部分。无论是在工作中还是在娱乐休闲时,我们都需要依赖各种软件来完成各种任务。然而,你是否注意到了身边的软件产品都是经过严格的测试才能上线的呢?那么为什么软件产品必须要经过…

JS之歌词滚动案例

让我为大家带来一个歌词滚动的案例吧&#xff01; 详细的介绍都在代码块中 我很希望大家可以自己动手尝试一下&#xff0c;如果需要晴天的mp3音频文件可以私信我 上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset&quo…

【开源】基于JAVA语言的图书管理系统

目录 一、 系统介绍二、 功能模块2.1 登录注册模块2.1 图书馆模块2.2 图书类型模块2.3 图书模块2.4 图书借阅模块2.5 公告模块 三、 源码解析3.1 图书馆模块设计3.2 图书类型模块设计3.3 图书模块设计3.4 图书借阅模块设计3.5 公告模块设计 四、 免责说明 一、 系统介绍 图书管…

和硕拿下AI Pin代工大单公司 | 百能云芯

和硕公司近日成功中标AI Pin代工大单&#xff0c;AI Pin被认为是继iPhone之后的下一个划时代产品&#xff0c;吸引了全球科技圈的广泛关注。和硕公司对此表示&#xff0c;他们不会只专注于单一客户&#xff0c;而是期望在下半年有更多新品上市&#xff0c;为公司带来丰硕的业绩…

《Linux高性能服务器编程》笔记06

Linux高性能服务器编程 本文是读书笔记&#xff0c;如有侵权&#xff0c;请联系删除。 参考 Linux高性能服务器编程源码: https://github.com/raichen/LinuxServerCodes 豆瓣: Linux高性能服务器编程 文章目录 Linux高性能服务器编程第13章 多进程编程13.1 fork 系统调用13…

空调设计软件工程师考虑点

空调设计软件工程师考虑点 看如的下边有输入压力P&#xff0c;单位不同&#xff0c;MPG是相对压力&#xff0c;Kpa是绝对压力。绝对压力比相对压力大一个大气压&#xff0c;即100kpa。 海立压缩机直接给转速值就行。CAN数据格式&#xff0c;Motoral高位在前&#xff0c;Intel高…

函数栈帧的创建与销毁【此一篇,足以让卿彻底扫盲】

一、函数栈帧要解决的问题 刚接触编程语言的的我们&#xff0c;想必都会存在这些问题&#xff1a; Ⅰ 局部变量不初始化&#xff0c;为什么是随机值&#xff1b; Ⅱ 形参与实参的关系&#xff1b; Ⅲ 函数是如何被调用&#xff0c;以及开辟相对应的空间的&#xff1b; Ⅳ…

MySQL数据库的锁机制

目录 一、引言 二、锁的类型及作用 2.1 行级锁 2.2 间隙锁与临键锁 2.3 共享锁与排他锁 2.4 意向锁 2.5 表级锁 2.6 元数据锁 三、锁的管理与优化 3.1 合理设置事务隔离级别 3.2 避免长事务 3.3 索引优化 3.4 明确锁定范围 3.5 避免不必要的全表扫描 四、实战分…

SpringBoot+beetl idea热更新解决方案

SpringBootbeetl idea热更新解决方案 第一在application中开启&#xff1a; beetl:resource-auto-check: true #热加载beetl模板&#xff0c;开发时候用第二在application中开启&#xff1a; devtools: 这个部分专门用于配置Spring Boot DevTools的相关参数。DevTools…

基于springboot+vue的“衣依”服装销售平台系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究背景…

【latex】在Overleaf的IEEE会议模板中,快速插入参考文献

【LaTeX】在Overleaf的IEEE会议模板中&#xff0c;快速插入参考文献 写在最前面第一步&#xff1a;在文献检索网站导出引用文献的bib文件第二步&#xff1a;编辑overleaf模版方法二&#xff1a;EduBirdie生成参考文献&#xff08;补充&#xff09;使用LaTeX在Overleaf的IEEE会议…