首页 > 其他分享 >PyTorch深度学习快速入门(中)

PyTorch深度学习快速入门(中)

时间:2024-07-29 20:57:18浏览次数:16  
标签:入门 nn output self torch PyTorch 深度 import input

PyTorch深度学习快速入门(中)

一、Containers(神经网络的基本骨架)

(一)Module 的使用

在这里插入图片描述
在这里插入图片描述

import torch
from torch import nn

class Li(nn.Module):
	def __init__(self):
		super().__init__()

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

li = Li() # 用模板创建出了一个神经网络
x = torch.tensor(1.0)  # 创建一个标量张量,其值为 1.0
# 张量是python中各种维度数据形式的统称,0维就是一个数,1维是数组,2维是矩阵,3维是空间矩阵
output = li(x)
print(output)  # 输出本来是2.0,但系统会自动忽略后面无意义的0,输出2.

(二)Sequential 的使用<搭建小实战>

Sequential 的作用:让代码更加简洁

在这里插入图片描述

# 卷积核通道数 == 输入图像的通道数
# 这是因为卷积操作是逐通道进行的,然后(可选地)通过某种方式(如求和或加权和)将各通道的结果合并
# 输出通道数 == 卷积核个数
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter


class Li(nn.Module):
	def __init__(self):
		super().__init__()
		# 法一:奇数卷积核把中心格子对准图片第一个格子,卷积核在格子外有两层就padding=2
		# 法二:如果前后尺寸不变,padding=(kernelsize-1)/2,kernelsize为卷积核(过滤器)的尺寸

		# self.conv1 = Conv2d(3,32,5,padding=2)
		# self.maxpool1 = MaxPool2d(2)
		# self.conv2 = Conv2d(32,32,5,padding=2)
		# self.maxpool2 = MaxPool2d(2)
		# self.conv3 = Conv2d(32,64,5,padding=2)
		# self.maxpool3 = MaxPool2d(2)
		# self.flatten = Flatten() # 实质上用1x1的kernel做卷积(全卷积网络)
		# self.linear1 = Linear(1024,64)
		# self.linear2 = Linear(64,10)

		self.model1 = Sequential(
			# 输出32通道是因为发生了32次卷积,输出大小不变是因为有填充边
			# kernel的内容不一样可以理解为不同的特征抓取 --> 一个核会产生一个channel
			# 层数多是为了获取更多的特征而不是偏向某一特征,深度深(在模型不退化的前提下) --> 能提取高级、复杂的特征
			Conv2d(3,32,5,padding=2),
			MaxPool2d(2),
			Conv2d(32, 32, 5, padding=2),
			MaxPool2d(2),
			Conv2d(32, 64, 5, padding=2),
			MaxPool2d(2),
			Flatten(),
			Linear(1024, 64),
			Linear(64, 10)
			# 最后一个线性层的输出往往会经过一个softmax激活函数,以将每个元素转化成表示概率的值
		)

	def forward(self,x):
		# x = self.conv1(x)
		# x = self.maxpool1(x)
		# x = self.conv2(x)
		# x = self.maxpool2(x)
		# x = self.conv3(x)
		# x = self.maxpool3(x)
		# x = self.flatten(x)
		# x = self.linear1(x)
		# x = self.linear2(x)

		x = self.model1(x)
		return x

li = Li()
print(li)
# 检验网络的书写是否正确,不写就算网络结构写错了,也不会报错
input = torch.ones((64,3,32,32))

# 可视化方式 1
output = li(input)
print(output.shape)
# 可视化方式 2
writer = SummaryWriter("./logs_seq")
writer.add_graph(li,input)
writer.close()

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


二、Convolution Layers(卷积层)

在这里插入图片描述

(一)torch.nn.functional 中 conv2d 的使用

在这里插入图片描述

import torch
import torch.nn.functional as F

# Tensor可以传入 size/具体数值/其他的 tensor 来构建一个 tensor
# tensor只能传入数据(可根据所传进行 dtype 设置)
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]])

# 卷积核一开始的大小是自己设置的,卷积核上的每一个位置相当于权重 w,其具体值正是需要学习的
kernel = torch.tensor([[1,2,1],
                       [0,1,0],
                       [2,1,0]])

# 只取一个样本->batch_size(样本数量)==1  二维矩阵->channel(图像的通道数)==1
# 4维:[图片数,图层数,宽,高]
input = torch.reshape(input,(1,1,5,5))
kernel = torch.reshape(kernel,(1,1,3,3))

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

output1 = F.conv2d(input,kernel,stride=1)
print(output1)

output2 = F.conv2d(input,kernel,stride=2)
print(output2)

# padding   
# eg.把 5x5填充成 6x6(用0填充),5x5的边缘数据可以多用几次,以平均利用数据,更好的保留边缘特征,
# 防止某些像素点被多次进行特征提取,导致某些点的作用过于放大了
output3 = F.conv2d(input,kernel,stride=1,padding=1)
print(output3)

在这里插入图片描述

(二)torch.nn 中 Conv2d 的使用

在这里插入图片描述
在这里插入图片描述

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

# "./data.txt"存在当前目录
# "../data.txt"存在上一级目录
dataset = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=64)

# 卷积核个数 == 输出通道数
class Li(nn.Module):
	def __init__(self):
		super().__init__()
		self.conv1 = Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)

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

li = Li()

writer = SummaryWriter("./logs")
step = 0
for data in dataloader:
	imgs,targets = data
	output = li(imgs)
	print(imgs.shape)
	print(output.shape)
	# torch.Size([64, 3, 32, 32])
	writer.add_images("input",imgs,step)
	# torch.Size([64, 6, 30, 30])
	# 直接输不出来 channel=6 的图 --> reshape一下,拼接图片数
	output = torch.reshape(output,(-1,3,30,30)) # -1是一个占位符,表示让Pytorch自动计算该维度的大小
	writer.add_images("output",output,step)
	step = step + 1

在这里插入图片描述

在这里插入图片描述


三、Pooling layers(池化层)

(一)池化层的介绍

在这里插入图片描述

(1)池化层的特点

  1. 没有需要学习的参数
  2. 通道数保持不变
  3. 对微小位置的变化具有鲁棒性
  4. 使用某一位置的相邻输出的总体统计特征来代替网络在该位置的输出。本质是降采样,可以大幅减少网络的参数

(2)最大池化的目的

  1. 保留输入的重要特征,但同时减小数据量,减小计算压力
  2. 防止过拟合

(3)卷积和池化的区别

卷积:提取特征 <----> 池化:降低特征数据量

(二)MaxPool2d 的使用

在这里插入图片描述

import torch
from torch import nn
from torch.nn import MaxPool2d

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)  
# dtype即datatype,不加这一句会报错:"max_pool2d" not implemented for 'Long'
# float类型和 float6 4类型是一样的,都需要 64个 bits,而 float32 只需要 32个 bits
input = torch.reshape(input,(-1,1,5,5))
print(input.shape)

class Li(nn.Module):
	def __init__(self):
		super().__init__()
		# 池化中默认的 stride 和卷积核一个大小
		# dilatioon(膨胀):空洞卷积
		# ceil_mode:True(核部分覆盖->保留)、False(核部分覆盖->舍弃),默认为 False
		self.maxpool1 = MaxPool2d(kernel_size=3,ceil_mode=False)

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

li = Li()
output = li(input)
print(output)

在这里插入图片描述

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

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

class Li(nn.Module):
	def __init__(self):
		super().__init__()
		self.maxpool1 = MaxPool2d(kernel_size=3,ceil_mode=False)

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

li = Li()

writer = SummaryWriter("logs_maxpool")

step = 0
for data in dataloader:
	imgs,targets = data
	writer.add_images("input",imgs,step)
	output = li(imgs)
	writer.add_images("output",output,step)
	step = step + 1

writer.close()

在这里插入图片描述


四、Non-linear Activations(非线性激活)

(一)非线性激活的目的

激活后就变弯了,弯曲线可以拟合十分复杂的曲线,提高泛化能力

(二)ReLU 与 Sigmoid 的使用

import torch
from torch import nn
from torch.nn import ReLU

input = torch.tensor([[1,-0.5],
                      [-1,3]]) # 有负值的原因:梯度下降,反向传播
input = torch.reshape(input,(-1,1,2,2))
print(input.shape)

class Li(nn.Module):
	def __init__(self):
		super().__init__()
		# inplace(在不在原来的位置替换)
		# ==True:会更改传入的数据(更改器方法),反之不会更改原数据(访问器方法),默认是 False
		self.relu1 = ReLU()

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

li = Li()
output = li(input)
print(output)

在这里插入图片描述

import torchvision
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

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

class Li(nn.Module):
	def __init__(self):
		super().__init__()
		self.relu1 = ReLU()
		# 三个通道的取值都是 0 ~ 255,用 ReLU 等于没有变化,用 Sigmoid 才能映射到 0 ~ 1 的区间
		self.sigmoid1 = Sigmoid()

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

li = Li()

writer = SummaryWriter("./logs_relu")  # Alt+回车:导入库
step = 0
for data in dataloader:
	imgs,targets = data
	writer.add_images("input",imgs,global_step=step)
	output = li(imgs)
	writer.add_images("output",output,global_step=step)
	step = step + 1

writer.close()

在这里插入图片描述


五、Linear Layers(线性层)及其他层

(一)其他层简介

(二)Linear Layers(线性层/全连接层)— Linear 的使用


在这里插入图片描述

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

dataset = torchvision.datasets.CIFAR10("./dataset",train=False,
									   transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=64,drop_last=True)
# 舍弃掉最后一组不满足数量的批次,不然会报错: mat1 and mat2 shapes cannot be multiplied (1x49152 and 196608x10)

class Li(nn.Module):
	def __init__(self):
		super().__init__()
		self.linear1 = Linear(196608,10)

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

li = Li()

for data in dataloader:
	imgs,targets = data
	print(imgs.shape)
	# output = torch.reshape(imgs,(1,1,1,-1))  # [1,1,1,196608]
	output = torch.flatten(imgs) # 摊平 -> 才可作为全连接的输入
	print(output.shape)
	output = li(output)
	print(output.shape)

# regulation(正则化):用于惩罚较高复杂度的拟合函数,防止过拟合,加速训练
# normalization(标准化/归一化)
# Embedding(嵌入层):存 NPL 中 token 向量

在这里插入图片描述
现在我们会自己去搭建一个网络模型了,但有的时候,我们还可以用Pytorch给我们提供的一些网络模型
在这里插入图片描述


六、损失函数&反向传播

(一)损失函数的作用&与反向传播的联系

(1)损失函数

  1. 计算实际输出和目标之间的差距
  2. 为我们更新输出提供一定的依据(反向传播),即有了损失,才能计算梯度,进而才能更新参数,趋向最优

(2)反向传播

反向传播是用来计算梯度的,给神经网络中每一个需要调优的参数,即给卷积层中每一个卷积核,设置一个梯度,根据梯度来更新参数,实现 Loss 最小化
因为是从 loss 开始推导参数,和网络的顺序相反,所以叫反向传播,梯度的理解可以直接当成“斜率”
在这里插入图片描述

(二)L1Loss、MSELoss、CrossEntropyLoss损失函数的使用

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

# 注:计算机 log 默认以 e 为底,计算器 log 默认以 10 为底
import torch
from torch import nn
from torch.nn import L1Loss, MSELoss

inputs = torch.tensor([1,2,3],dtype=torch.float32)
targets = torch.tensor([1,2,5],dtype=torch.float32)
# tensor 产生时会自带维度,reshape 是为了保证维度符合你想使用函数的特定要求
inputs = torch.reshape(inputs,(1,1,1,3))
targets = torch.reshape(targets,(1,1,1,3))

loss = L1Loss(reduction='sum')
result = loss(inputs,targets)

# mean squared error (均方误差)
loss_mse = MSELoss()
result_mse = loss_mse(inputs,targets)

print(result)
print(result_mse)

# 这里不是概率,只是一个评估分数,后续要经过 softmax (正则化)(激活层) 之后,输出的才是概率,加起来才为 1
x = torch.tensor([0.1,0.2,0.3])
# 代表 x 中需要计算元素 loss 的位置(要计算损失函数的类别),又 batch size==1,这里就没再指定了
y = torch.tensor([1])
x = torch.reshape(x,(1,3))  # (batch size,number of classes)
loss_cross = nn.CrossEntropyLoss()
result_cross = loss_cross(x,y)
print(result_cross)

# 神经网络的两大类主题:回归分类,一般 mse 用于回归,crossentroy 用于分类
# 每个优化器会对应一个优化函数,不同优化函数对应不同损失函数

在这里插入图片描述

(三)如何在之前写的神经网络中用到损失函数&反向传播

在这里插入图片描述

import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

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

class Li(nn.Module):
	def __init__(self):
		super().__init__()
		self.model1 = Sequential(
			Conv2d(3,32,5,padding=2),
			MaxPool2d(2),
			Conv2d(32, 32, 5, padding=2),
			MaxPool2d(2),
			Conv2d(32, 64, 5, padding=2),
			MaxPool2d(2),
			Flatten(),
			Linear(1024, 64),
			Linear(64, 10)
		)

	def forward(self,x):
		x = self.model1(x)
		return x

loss = nn.CrossEntropyLoss()
li = Li()
for data in dataloader:
	imgs,targets = data
	outputs = li(imgs)
	# 可以先看一下 outputs 和 targets 长什么样,看选择什么样的损失函数
	# print(outputs)
	# print(targets)
	result_loss = loss(outputs,targets)
	# print(result_loss)
	result_loss.backward()
	# outputs 是由卷积核计算出来的,result_loss 是由 outputs 计算的,所以 result_loss 是卷积核中的参数的一个函数

在这里插入图片描述


七、优化器

(一)官方文档解读

在这里插入图片描述
在这里插入图片描述

(二)如何在之前写的神经网络中用到优化器

import torch
import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

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

class Li(nn.Module):
	def __init__(self):
		super().__init__()
		self.model1 = Sequential(
			Conv2d(3,32,5,padding=2),
			MaxPool2d(2),
			Conv2d(32, 32, 5, padding=2),
			MaxPool2d(2),
			Conv2d(32, 64, 5, padding=2),
			MaxPool2d(2),
			Flatten(),
			Linear(1024, 64),
			Linear(64, 10)
		)

	def forward(self,x):
		x = self.model1(x)
		return x

loss = nn.CrossEntropyLoss()
li = Li()
# lr(learning rate):
# 大 -> 训练的模型很不稳定(一开始)
# 小 -> 模型训练的慢(学到后面),如过后面还用大,模型直接跑过极小值点了
optim = torch.optim.SGD(li.parameters(),lr=0.01)
# 一般要对数据进行多轮学习
for epoch in range(20):
	# 关注每一轮中整体的 loss
	running_loss = 0.0
	for data in dataloader:
		imgs,targets = data
		output = li(imgs)
		result_loss = loss(output,targets)

		optim.zero_grad() # 要清零,上一次计算的梯度对这一次的梯度是没用的,梯度每次计算都会累积,会越来越大
		result_loss.backward()  # 计算每个参数对应的梯度
		optim.step() # 对权重的每个参数进行更新调优
		running_loss = running_loss + result_loss
	print(running_loss)

在这里插入图片描述
在这里插入图片描述


标签:入门,nn,output,self,torch,PyTorch,深度,import,input
From: https://blog.csdn.net/wanchen_Gabby/article/details/140756231

相关文章

  • 深度模型中的优化 - 参数初始化策略篇
    序言在深度模型优化中,参数初始化策略是决定模型性能与训练效率的重要基石。恰当的初始化不仅能加速模型的收敛过程,还能有效缓解梯度消失与爆炸等问题,从而提升模型的泛化能力。随着深度学习技术的飞速发展,研究者们不断探索与提出各类参数初始化方法,旨在针对不同模型结构和数......
  • 阿里云天池——零基础入门数据挖掘 - 二手车交易价格预测
    赛题数据见官网:零基础入门数据挖掘-二手车交易价格预测_学习赛_天池大赛-阿里云天池的赛制(aliyun.com)因为本人第一次接触神经网络的深度学习,在此就将教学代码逐框解析1.1导入用于数据处理、模型训练、数据加载以及可视化的Python库%matplotlibinlinefromsklearn.m......
  • Redis快速入门
    一、简介redis为非关系型数据库,将数据以key-value(键值对)的形式存入内存基于内存存储,读写性能更高存储热点信息(短时间内存储大量数据)企业应用广泛官网Redis-TheReal-timeDataPlatform中文网Redis中文网二、下载与安装下载地址https://github.com/microsoftarc......
  • unity游戏源码和配套教程:三维的美好场景,完全免费和开源,教程完整详细,适合初学者入门
    源码(含配套教程)在夸克网盘(完全免费,完全开源,完整详细):夸克网盘分享夸克网盘是夸克推出的一款云服务产品,功能包括云存储、高清看剧、文件在线解压、PDF一键转换等。通过夸克网盘可随时随地管理和使用照片、文档、手机资料,目前支持Android、iOS、PC、iPad。https://pan.quark.cn/s/......
  • 深度学习与图像识别day5(机器学习基础)
    线性问题主要处理回归问题,回归问题即预测一个连续问题的数值。计算决定系数(R-squared,也称为R²或系数决定)是衡量回归模型预测准确性的一个常用指标。R-squared值越接近1,表示模型的预测性能越好;如果R-squared值为0,则表示模型只是简单地预测了目标变量的平均值;如果R-squared值为负,......
  • React 的 KeepAlive 实战指南:深度解析组件缓存机制
    Vue的Keep-Alive组件是用于缓存组件的高阶组件,可以有效地提高应用性能。它能够使组件在切换时仍能保留原有的状态信息,并且有专门的生命周期方便去做额外的处理。该组件在很多场景非常有用,比如:·tabs缓存页面·分步表单·路由缓存在Vue中,通过KeepAlive包裹内的组件......
  • 如何用3个月零基础入门网络安全?_网络安全零基础怎么学习
    前言写这篇教程的初衷是很多朋友都想了解如何入门/转行网络安全,实现自己的“黑客梦”。文章的宗旨是:1.指出一些自学的误区2.提供客观可行的学习表3.推荐我认为适合小白学习的资源.大佬绕道哈!→点击获取网络安全资料·攻略←一、自学网络安全学习的误区和陷阱1.不要......
  • 网络安全入门教程(非常详细)从零基础入门到精通,看完这一篇就够了。
    学前感言:1.这是一条坚持的道路,三分钟的热情可以放弃往下看了.2.多练多想,不要离开了教程什么都不会了.最好看完教程自己独立完成技术方面的开发.3.有时多google,baidu,我们往往都遇不到好心的大神,谁会无聊天天给你做解答.4.遇到实在搞不懂的,可以先放放,以后再来解决.基......
  • 《最新出炉》系列入门篇-Python+Playwright自动化测试-57- 上传文件 - 番外篇
    1.简介前边的三篇文章基本上对文件上传的知识介绍和讲解的差不多了,今天主要是来分享宏哥在文件上传的实际操作中发现的一个问题:input控件和非input控件的上传API对其都可以上传成功。废话不多说直接进入正题。2.项目实战宏哥之前在讲解和分享Java+selenium系列时,将其划分为非in......
  • 网页开发入门系列 1:开发工具准备
    网页开发入门系列1:开发工具准备文本编辑器我们需要一个文本编辑器来编辑源代码,需要注意的是编辑对象是纯文本,可以理解为txt文本文件,像MicrosoftWord这样的高级字处理软件不适合编辑代码。Vim、GNUEmacs、Windows记事本等软件都是符合要求的文本编辑器。不过前两者学习难......