【Pytorch入门】小土堆PyTorch入门教程完整学习笔记(详细笔记并附练习代码 ipynb文件)

news2024/9/23 15:45:14

小土堆PyTorch入门教程笔记

在这里插入图片描述

最近在观看PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】顺便做点笔记,方便回看,同时也希望记录的笔记能够帮助到更多在入门的小伙伴~
【注】仅记录个人觉得重要的知识,部分内容可能有遗漏

  1. 判断pytorch是否安装好,GPU是否可供pytorch使用,无报错即成功
import torch
torch.cuda.is_available()

在这里插入图片描述
2. 添加环境变量的作用:告诉系统在执行程序或者其他操作时应该如何工作
在命令行使用该命令时,无需切换到程序所在路径
3. nb_conda是jupyter notebook的扩展,可在jupyter notebook中直接使用conda环境,允许在notebook的界面中创建、管理、切换conda环境,而无需通过命令行

#安装命令如下
conda install nb_conda
  1. 使用本地已下载好的包进行安装
conda install --use-local 包名.tar.bz2
  1. Python的内置函数dir()
    dir()函数,打开工具箱。用于列出一个对象的所有属性和方法。它返回一个包含对象所有属性和方法名称的列表。如果不传入参数,则返回当前作用域中所有可用的名称
#示例 查看pytorch
dir(torch)

在这里插入图片描述
可以更加具体详细的查看

dir(torch.cuda)

在这里插入图片描述

dir(torch.cuda.is_available) #注意torch.cuda.is_available后没有括号

在这里插入图片描述

返回的结果是一个函数对象的属性列表
python 里 前后各有双下划线 __函数名__是什么?
在 Python 中,魔术属性(Magic Attributes)也称为特殊属性(Special Attributes)也称为魔法方法、双下划线方法(Double Underscore Methods),是以双下划线 __ 开头和结尾的特殊命名方式,用于实现对象的特殊行为和操作,不允许被修改

  1. Python的内置函数help(),查看官方解释文档
    help()函数,查看说明书。用于获取对象、模块、函数、关键字等的帮助信息。当传入对象时,它会显示该对象的帮助文档。如果没有传入任何参数,则会进入交互式帮助模式。
help(torch.cuda.is_available)

在这里插入图片描述
在 IPython 中,当输入 object?? 时,它会尝试显示该对象的源代码
在这里插入图片描述

  1. Pycharm 按shift + 回车 会跳转至下一行的行首

  2. 在Pycharm的Python Console中也可 以任意行为块 输入多行时 按shift + 回车
    在这里插入图片描述

  3. Pytorch读取数据的两个类 Dataset和DataLoader

from torch.utils.data import Dataset
help(Dataset)
Dataset??

Dataset将数据和label进行组织编号0 1 2 3……,使得可以根据编号读取数据;需获取每一个数据及其label以及数据总数 ,要实现 len() 方法和 getitem() 方法。
len() 方法返回数据集的样本数量;
getitem() 方法根据给定的索引返回对应的数据样本;

DataLoader对数据进行打包将数据集划分为小批量,按batchsize送入网络模型;可以接收一个 Dataset 对象作为输入,并根据指定的批量大小、是否打乱数据、是否使用多线程等参数,来构建一个用于数据加载的迭代器

Jupter Notebook从星号*变为数字代表运行结束
在这里插入图片描述

  1. Dataset类代码实战
    通过继承Dataset类class MyData(Dataset),实现__len__和__getitem__方法,可以自定义自己的数据集类以适应不同的数据源和格式
    蚂蚁蜜蜂/练手数据集:链接: https://pan.baidu.com/s/1jZoTmoFzaTLWh4lKBHVbEA 密码: 5suq
from torch.utils.data import Dataset
from PIL import Image
import os

class MyData(Dataset):
    def __init__(self, root_dir, label_dir):
        self.root_dir = root_dir
        self.label_dir = label_dir
        self.path = os.path.join(self.root_dir, self.label_dir)
        self.img_path = os.listdir(self.path)
        
    def __getitem__(self, idx):
        img_name = self.img_path[idx]
        img_item_path = os.path.join(self.root_dir, self.label_dir,img_name)
        img = Image.open(img_item_path)
        label = self.label_dir
        return img,label
    
    def __len__(self):
        return len(self.img_path)
        
root_dir = "蚂蚁蜜蜂数据集\\dataset\\train"
ants_label_dir = "ants"
ants_dataset = MyData(root_dir, ants_label_dir)
print(ants_dataset)
print(ants_dataset[0] )  # 根据重写的getitem返回 img与 label
img, label = ants_dataset[0] 
img.show()
bees_label_dir = "bees"
bees_dataset = MyData(root_dir, bees_label_dir)
img, label = bees_dataset[0] 
img.show()

train_dataset =ants_dataset + bees_dataset #两个数据集的拼接 未改变顺序,ants在前 bees在后
print(len(ants_dataset))
print(len(bees_dataset))
print(len(train_dataset))

在这里插入图片描述

  1. Tensorboard的使用
    add_saclar用于在TensorBoard中添加标量数据。该方法可以用来添加训练过程中的损失值、准确率等指标,以便于在TensorBoard中进行可视化和比较
    在这里插入图片描述
    tag(字符串):用于标识添加的标量数据的名称或标签。在TensorBoard中,这个标签将用作图表的标题。
    scalar_value(数值):要记录的标量数据的值。这可以是损失值、准确率等。
    global_step(整数,可选):表示记录的步数或迭代次数。这个参数对于在TensorBoard中显示随时间变化的数据非常有用。例如,在训练神经网络时,您可以将当前的迭代次数传递给global_step,以便在TensorBoard中可视化损失值、准确率等随着训练步数的变化而变化的曲线。
    walltime(时间戳,可选):表示记录的时间。如果不指定,则默认使用当前时间

  2. 使用tensorboard绘制 y = x 的函数

from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter("logs") # 日志文件存储位置
for i in range(100):
    writer.add_scalar("y = x", i, i) #前一个i是y 后一个i是横坐标
writer.close()

在对应位置已生成事件文件
在这里插入图片描述

  1. 打开日志文件
    在这里插入图片描述
    在anaconda激活已安装tensorboard的环境并进入日志文件所在位置,使用如下命令
tensorboard --logdir=logs  #logs是上面指定在writer = SummaryWriter("logs")中指定的文件夹名,日志文件存储在此文件中

在这里插入图片描述
出现如下的情况即为成功,在浏览器中打开显示的url http://localhost:6006/
在这里插入图片描述
另一种方式:直接输入完整的日志文件所在路径
在这里插入图片描述

在这里插入图片描述

可通过tensorboard --logdir==logs --port=XXXX 指定端口号
  1. 当未改变图像标题,重复修改y值 如writer.add_scalar(“y = x”, i, i),writer.add_scalar(“y = x”, 2i, i),writer.add_scalar(“y = x”, 3i, i),会导致新绘制会包含之前绘制的图像
    在这里插入图片描述
    解决方法:删除所有log文件,重新执行程序,再在tensorboard中查看
    在这里插入图片描述

  2. add_image()的使用
    老方法,先使用help看一下方法说明

from torch.utils.tensorboard import SummaryWriter
help(SummaryWriter.add_image)

在这里插入图片描述
注意:add_image的参数img_tensor类型需为torch.Tensor, numpy.array, or string/blobname
在这里插入图片描述
而通过PIL中的Image读取图像其对应的类型是<class ‘PIL.JpegImagePlugin.JpegImageFile’>
在这里插入图片描述

  1. 利用numpy.array()对PIL的图像进行转换
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
img_path = "C:\\Users\\Sen\\Desktop\\pytorch\\Pytorch教程\\data\\train\\ants_image\\0013035.jpg"
img = Image.open(img_path)
print(type(img))
import numpy as np
img_array = np.array(img)
print(type(img_array))

在这里插入图片描述

  1. 使用numpy.array()转图像并进行writer.add_image()
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
import numpy as np

writer = SummaryWriter("logs") # 日志文件存储位置
img_path = "C:\\Users\\Sen\\Desktop\\pytorch\\Pytorch教程\\data\\train\\ants_image\\0013035.jpg"
img = Image.open(img_path)
print(type(img))
img_array = np.array(img)
print(type(img_array))
print(img_array.shape)
writer.add_image("Img Test", img_array, 1)
writer.close()

会发现有如下报错
在这里插入图片描述
问题原因:图像形状默认为 :math:`(3, H, W),而上面通过打印发现形状为(512, 768, 3),需对通道参数进行转换
使用 dataformats=‘HWC’
在这里插入图片描述

from torch.utils.tensorboard import SummaryWriter
from PIL import Image
import numpy as np

writer = SummaryWriter("logs") # 日志文件存储位置
img_path = "C:\\Users\\Sen\\Desktop\\pytorch\\Pytorch教程\\data\\train\\ants_image\\0013035.jpg"
img = Image.open(img_path)
print(type(img))
img_array = np.array(img)
print(type(img_array))
print(img_array.shape)
writer.add_image("Img Test", img_array, 1, dataformats="HWC")
writer.close()

在这里插入图片描述
无报错,运行tensorboard进行查看
在这里插入图片描述

  1. Pytorch中的Transforms
    用于对图像进行预处理和数据增强操作,如调整图像大小、中心裁剪、随机裁剪、随机水平翻转、归一化、将 PIL 图像转换为 Tensor 等等
from torchvision import transforms

在这里插入图片描述

使用transforms的ToTensor()进行图片类型的转化

from torchvision import transforms
from PIL import Image
img_path = "C:\\Users\\Sen\\Desktop\\pytorch\\Pytorch教程\\data\\train\\bees_image\\16838648_415acd9e3f.jpg"
img = Image.open(img_path)
print(type(img))
tensor_trans = transforms.ToTensor() # transforms.ToTensor() 这一步相当于实例化 返回totensor的对象
tensor_img = tensor_trans(img)
print(type(tensor_img))

在这里插入图片描述

  1. Pycharm中查看包的结构 快捷键Alt + 7
    在这里插入图片描述
    Pycharm 查看需传入的参数ctrl+P
    在这里插入图片描述

  2. Python的__call__ 方法
    在 Python 中,__call__ 是一个特殊方法(也称为魔术方法或双下划线方法),用于使对象可以像函数一样被调用。当你在一个对象上调用 obj() 时,Python 解释器会查找该对象的__call__ 方法并调用它

class MyClass:
    def __init__(self, value):
        self.value = value
    
    def __call__(self, x):
        return self.value + x

obj = MyClass(10)
result = obj(5)  # 调用了 __call__ 方法
print(result)  # 输出: 15

在 Python 中,__call__ 是一个特殊方法(也称为魔术方法或双下划线方法),用于使对象可以像函数一样被调用。当你在一个对象上调用 obj() 时,Python 解释器会查找该对象的 __call__ 方法并调用它。

class MyClass:
    def __init__(self, value):
        self.value = value
    
    def __call__(self, x):
        return self.value + x

obj = MyClass(10)
result = obj(5)  # 调用了 __call__ 方法
print(result)  # 输出: 15

在上面的示例中,MyClass 类实现了__call__方法,因此创建的 obj 实例可以像函数一样被调用。在调用 obj(5) 时,实际上会调用 obj.__call__(5),返回的结果是 self.value + x 的计算结果,即 10 + 5 = 15。

__call__方法的灵活性使得对象可以像函数一样被使用,这在某些情况下非常有用,例如实现可调用的对象或者定制对象的行为。
查看transforms的源代码,发现其实现了__call__方法
所以tensor_trans = transforms.ToTensor() ,tensor_img = tensor_trans(img)直接传入img调用了其中的__call__方法
在这里插入图片描述

  1. tensor数据类型
    神经网络专用的数据类型,包含了许多神经网络需要的参数,使用Python Console查看tensor_img的参数
    在这里插入图片描述

  2. opencv 使用cv2.imread()读取的图像数据类型是numpy.ndarray
    在这里插入图片描述

  3. 使用add_image()添加tensor类型的图像到日志文件中 通过tensorboard展示

from torch.utils.tensorboard import SummaryWriter
from PIL import Image
from torchvision import transforms

writer = SummaryWriter("logs") # 日志文件存储位置
img_path = "C:\\Users\\Sen\\Desktop\\pytorch\\Pytorch教程\\data\\train\\bees_image\\16838648_415acd9e3f.jpg"
img = Image.open(img_path)
tensor_trans = transforms.ToTensor() 
tensor_img = tensor_trans(img)
writer.add_image("Tensor_img",tensor_img)
writer.close()
  1. 常见的transforms
    使用Normalize对图像进行归一化,对每个通道进行归一化:(输入值–均值)/ 标准差
    在这里插入图片描述
    假设三个通道的均值和标准差都为0.5
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
from torchvision import transforms

writer = SummaryWriter("logs") # 日志文件存储位置
img_path = "C:\\Users\\Sen\\Desktop\\pytorch\\Pytorch教程\\data\\train\\bees_image\\16838648_415acd9e3f.jpg"
img = Image.open(img_path)
tensor_trans = transforms.ToTensor() 
tensor_img = tensor_trans(img)
trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
img_norm = trans_norm(tensor_img)
print(tensor_img[0][0][0])
print(img_norm[0][0][0])
writer.add_image("Normalize",img_norm)
writer.close()

在这里插入图片描述

  1. transform.Resize()的使用
    注意图片数据类型,通过Image.open读取的是PIL类型的
    transform.Resize() 可以处理 PIL 图像对象,也可以处理张量类型的数据
from PIL import Image
from torchvision import transforms
img_path = "C:\\Users\\Sen\\Desktop\\pytorch\\Pytorch教程\\data\\train\\bees_image\\16838648_415acd9e3f.jpg"
img = Image.open(img_path)
print("图片原始大小,读取为PIL类型",img.size)
trans_resize = transforms.Resize((512,512))
img_resize = trans_resize(img)
print("对PIL类型进行Resize",img_resize)
tensor_trans = transforms.ToTensor() 
img_resize = tensor_trans(img_resize)
print("将PIL Reszie的图片转换为Tensor",img_resize)
trans_resize2 = transforms.Resize((256,256))
img_resize = trans_resize(img_resize)
print("对tensor类型的数据进行Resize",img_resize)

在这里插入图片描述

  1. 利用Compose进行resize
    Compose用于组合多个图像转换(transform)操作。通过 Compose,可以创建一个转换流程,这个流程可以按顺序执行多个图像处理操作,这些操作可以包括缩放、裁剪、归一化等,其需要的参数是一个列表,其元素类型是transforms类型。
    格式Compose([transforms参数1,transforms参数2,…])
from PIL import Image
from torchvision import transforms
img_path = "C:\\Users\\Sen\\Desktop\\pytorch\\Pytorch教程\\data\\train\\bees_image\\16838648_415acd9e3f.jpg"
img = Image.open(img_path)
print(img)
trans_resize2 = transforms.Resize(512)
trans_totensor = transforms.ToTensor() 
trans_compose = transforms.Compose([trans_resize2,trans_totensor])
img_resize_2 = trans_compose(img)
print(img_resize_2)

在这里插入图片描述

  1. 随机裁剪RandomCrop

RandomCrop 是 PyTorch 中用于图像数据增强(data augmentation)的函数之一,它可以在图像或张量的随机位置裁剪出指定大小的区域
transforms.RandomCrop((128, 128))会随机在输入图像中裁剪出大小为 128x128 的区域,并返回裁剪后的图像对象

from PIL import Image
from torchvision import transforms
help(transforms.RandomCrop)

在这里插入图片描述

from torch.utils.tensorboard import SummaryWriter
from PIL import Image
from torchvision import transforms

writer = SummaryWriter("logs") # 日志文件存储位置
img_path = "C:\\Users\\Sen\\Desktop\\pytorch\\Pytorch教程\\data\\train\\bees_image\\16838648_415acd9e3f.jpg"
img = Image.open(img_path)
print(img)
trans_random = transforms.RandomCrop(30)
trans_totensor = transforms.ToTensor() 
trans_compose_2 = transforms.Compose([trans_random,trans_totensor])
for i in range(10):
    img_crop = trans_compose_2(img)
    writer.add_image("RandomCrop",img_crop,i)
    
writer.close()

裁剪的结果如下
在这里插入图片描述

当随机裁剪的大小大于图像输入时会报类似这种错误
在这里插入图片描述

  1. torchvision.datasets的使用
import torchvision
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter("logs") # 日志文件存储位置
dataset_transform = transforms.Compose([
    transforms.ToTensor() 
])
train_set = torchvision.datasets.CIFAR10(root="./dataset", train=True,transform=dataset_transform, download=True)
test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False,transform=dataset_transform, download=True)
print(test_set[0])
img, target = test_set[0]  # target对应类的编号 对应cat
print(img)
print(target)
print(test_set.classes[target])

for i in range(10):
    img, target = test_set[i]
    writer.add_image("torchvision",img,i)

在这里插入图片描述

  1. DataLoader的使用
    在这里插入图片描述
    drop_last=True 表示如果最后一个批次的样本数量小于批次大小,则丢弃该批次;而 drop_last=False 则表示保留最后一个不完整的批次
import torchvision
from torchvision import transforms
from torch.utils.data import DataLoader
dataset_transform = transforms.Compose([
    transforms.ToTensor() 
])
test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False,transform=dataset_transform, download=True)
test_loader = DataLoader(dataset=test_set, batch_size=4, shuffle=True, num_workers=0, drop_last=False)
img, target = test_set[0]
print("单个img:",img.shape)
print("单个target:",target)

for data in test_loader:
    imgs,targets = data
    print(imgs.shape)
    print(targets)

在这里插入图片描述

import torchvision
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter
from torch.utils.data import DataLoader
dataset_transform = transforms.Compose([
    transforms.ToTensor() 
])
test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False,transform=dataset_transform, download=True)
test_loader = DataLoader(dataset=test_set, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
img, target = test_set[0]
print("单个img:",img.shape)
print("单个target:",target)

writer = SummaryWriter("logs") # 日志文件存储位置
step = 0
for data in test_loader:
    imgs,targets = data
    writer.add_images("test_data",imgs,step)
    step = step + 1

writer.close()

在这里插入图片描述
使用shuffle参数进行打乱

import torchvision
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter
from torch.utils.data import DataLoader
dataset_transform = transforms.Compose([
    transforms.ToTensor() 
])
test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False,transform=dataset_transform, download=True)
test_loader = DataLoader(dataset=test_set, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
img, target = test_set[0]
print("单个img:",img.shape)
print("单个target:",target)

writer = SummaryWriter("logs") # 日志文件存储位置
for epoch in range(2):
    step = 0
    for data in test_loader:
        imgs,targets = data
        writer.add_images("Epoch:{}".format(epoch),imgs,step)
        step = step + 1

writer.close()

在这里插入图片描述

  1. 神经网络的基本骨架nn.Module的使用
    常用的的包torch.nn
    神经网络的基类Module,定义的模型都需要集成该类nn.Module
    自己定义的模型需要实现__init__和forward函数
import torch
from torch import nn
class Tudui(nn.Module):
    def __init__(self):
        super().__init__()
        
    def forward(self, input):
        output = input +1
        return output
tudui = Tudui()
x = torch.tensor(1.0)
myout = tudui(x)
print(myout)

在这里插入图片描述
代码的执行流程可通过Pycharm进行debug 使用Step into My Code进行查看

在这里插入图片描述
tudui = Tudui()进行类的实例化首先会调用__init__函数,然后执行 super().__init__()
当调用一个 nn.Module 的实例时,例如 tudui(x),PyTorch 会自动触发该实例的 forward 方法。这是因为 nn.Module 类在 Python 中被视为一个可调用对象,这是通过在 nn.Module 类中实现特殊方法__call__()来实现的。

__call__ 方法在 nn.Module 中被定义为调用 forward 方法的包装器,像函数一样调用一个 nn.Module 实例时,实际上是在执行 forward 方法,并将传入的参数(在这个例子中是 x)作为输入传递给 forward 方法

  1. 卷积操作
    理论讲解请看P17 讲的很清晰
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    以上是torch.nn.functional.conv2d的参数要求
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]])
input  = torch.reshape(input,(1,1,5,5)) # 变换input维度使其满足torch.nn.functional.conv2d的参数要求
kernel = torch.reshape(kernel,(1,1,3,3))
print(input.shape)
print(kernel.shape)

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

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

  1. 卷积层的使用
    在这里插入图片描述
    卷积操作可视化链接
    在这里插入图片描述
    在这里插入图片描述
    dilation是空洞卷积,默认值是1
    在这里插入图片描述

在这里插入图片描述
out_channels是指经过卷积核之后输出的特征图的通道数
个人补充内容,请理解以下两个式子:
输入特征图的通道数 = 卷积核的通道数
输出特征图的通道数 = 卷积核的个数
解释:卷积核的通道数一定和输入的通道数相等,输入对应的每个通道与卷积核对应的每个通道进行计算再求和得到 一个通道的卷积输出;而输出特征图的通道数与卷积核的个数相关,有多少个卷积核最终就有多少个输出通道
如果理解不够清晰,请看下图
在这里插入图片描述

  1. 卷积练习代码
import torch
import torchvision
from torch.utils.data import DataLoader
from torch import nn
from torch.nn import Conv2d
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)

#搭建网络
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__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
    
writer = SummaryWriter("logs") # 日志文件存储位置    
tudui = Tudui()
print(tudui)

step = 0
for data in dataloader:
    imgs, targets = data
    output = tudui(imgs)
    print("原图像的形状",imgs.shape)
    print("卷积之后图像的形状",output.shape)
    writer.add_images("input",imgs,step)
    # 卷积之后图像的形状 torch.Size([64, 6, 30, 30])是6个通道的 而add_images只能接收3通道的输入    
    output = torch.reshape(output, (-1, 3, 30, 30))#不严谨操作 ---对output进行reshape 增大batchsize的数量 减少通道数
    writer.add_images("Conv_output",output,step) 
    step = step + 1
writer.close()

在这里插入图片描述
卷积之后图像的形状 torch.Size([64, 6, 30, 30])是6个通道的 而add_images只能接收3通道的输入 ,如果不对output进行reshape 增大batchsize的数量 减少通道数,会报以下错误
在这里插入图片描述
tensorboard的输出结果:
在这里插入图片描述

  1. 最大池化层 保留输入的特征,同时减少数据量 加快训练速度
    在这里插入图片描述
    在这里插入图片描述
    最大池化层的步长默认大小为kernel_size
    ceil_mode ceil向上取整,floor向下取整
    在这里插入图片描述
    ceil 允许有出界部分;floor 不允许
    ceil_mode =True时 为ceil
    在这里插入图片描述

在这里插入图片描述
池化层有三个特点:1.没有需要学习的参数;2.通道数保持不变;3.对微小位置的变化具有鲁棒性

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)
input = torch.reshape(input,(-1,1,5,5))
print(input.shape)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.maxpool1 = MaxPool2d(kernel_size=3,ceil_mode=True)
    
    def forward(self,input):
        output = self.maxpool1(input)
        return output
    
tudui = Tudui()
output = tudui(input)
print(output)

在这里插入图片描述

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)
input = torch.reshape(input,(-1,1,5,5))
print(input.shape)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.maxpool1 = MaxPool2d(kernel_size=3,ceil_mode=False)
    
    def forward(self,input):
        output = self.maxpool1(input)
        return output
    
tudui = Tudui()
output = tudui(input)
print(output)

在这里插入图片描述
与手动计算的最大池化一致
在这里插入图片描述

import torch
import torchvision
from torch.utils.data import DataLoader
from torch import nn
from torch.utils.tensorboard import SummaryWriter 
from torch.nn import MaxPool2d
dataset = torchvision.datasets.CIFAR10("./dataset",train= False, transform =torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=64)

#搭建网络
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.maxpool1 = MaxPool2d(kernel_size=3,ceil_mode=False)
    
    def forward(self,input):
        output = self.maxpool1(input)
        return output
    
    
writer = SummaryWriter("logs") # 日志文件存储位置    
tudui = Tudui()
print(tudui)

step = 0
for data in dataloader:
    imgs, targets = data
    output = tudui(imgs)
    print("原图像的形状",imgs.shape)
    print("池化之后图像的形状",output.shape)
    writer.add_images("maxpool_input",imgs,step)
    writer.add_images("maxpool_output",output,step) 
    step = step + 1
writer.close()

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

  1. 非线性激活层:引入非线性的特性,使得神经网络具有更强的表达能力和适应能力
    在这里插入图片描述
    inplace参数的含义:为True时对原输入进行激活函数的计算,计算结果赋给原输入;为False时,返回对原输入进行激活函数的计算的结果,原输入不发生改变,保留原始数据,默认为False
    在这里插入图片描述
    ReLU的使用
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)) #增加一个batchsize维
print(input.shape)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.relu1 = ReLU()
        
    def forward(self, input):
        output = self.relu1(input)
        return output

tudui = Tudui()
output = tudui(input)
print(output)            

在这里插入图片描述
Sigmoid的使用

import torch
import torchvision
from torch.utils.data import DataLoader
from torch import nn
from torch.utils.tensorboard import SummaryWriter 
from torch.nn import Sigmoid
dataset = torchvision.datasets.CIFAR10("./dataset",train= False, transform =torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=64)

#搭建网络
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.sigmoid1 = Sigmoid()
    
    def forward(self,input):
        output = self.sigmoid1(input)
        return output
    
    
writer = SummaryWriter("logs") # 日志文件存储位置    
tudui = Tudui()
print(tudui)

step = 0
for data in dataloader:
    imgs, targets = data
    output = tudui(imgs)
    writer.add_images("before_activate",imgs,step)
    writer.add_images("after_activate",output,step) 
    step = step + 1
writer.close()

在这里插入图片描述

  1. 线性层(全连接层)及其他层介绍
    在这里插入图片描述
    在这里插入图片描述
import torch
import torchvision
from torch.utils.data import DataLoader
from torch import nn
from torch.utils.tensorboard import SummaryWriter 
from torch.nn import Linear
dataset = torchvision.datasets.CIFAR10("./dataset",train= False, transform =torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=64, drop_last=True)

#搭建网络
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.linear1 = Linear(196608,10)
    
    def forward(self,input):
        output = self.linear1(input)
        return output
    
       
tudui = Tudui()
print(tudui)


for data in dataloader:
    imgs, targets = data
    print("原尺寸", imgs.shape) #【64,3,32,32】
    output = torch.reshape(imgs,(1, 1, 1, -1)) # reshape后 变为【1,1,1,196608】
    print("reshape后尺寸",output.shape)
    output = tudui(output)
    print("全连接层输出尺寸",output.shape)


在这里插入图片描述

  1. flatten层:将输入张量扁平化(flatten)的函数。它将输入张量沿着指定的维度范围进行扁平化处理,并返回一个一维张量作为结果
    在这里插入图片描述
    input: 输入张量,即要进行扁平化操作的张量。
    start_dim: 指定开始扁平化的维度。默认为0,即从第0维开始扁平化。
    end_dim: 指定结束扁平化的维度(包含在内)。默认为-1,即扁平化至最后一维。
t = torch.tensor([[[1, 2],
                   [3, 4]],
                  [[5, 6],
                   [7, 8]]])
torch.flatten(t)
torch.flatten(t, start_dim=1)

在这里插入图片描述

import torch
import torchvision
from torch.utils.data import DataLoader
from torch import nn
from torch import flatten
from torch.utils.tensorboard import SummaryWriter 
from torch.nn import Linear
dataset = torchvision.datasets.CIFAR10("./dataset",train= False, transform =torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=64, drop_last=True)

#搭建网络
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        self.linear1 = Linear(196608,10)
    
    def forward(self,input):
        output = self.linear1(input)
        return output
    
       
tudui = Tudui()
print(tudui)


for data in dataloader:
    imgs, targets = data
    print("原尺寸", imgs.shape) #【64,3,32,32】
    output = flatten(imgs)
    print("flatten后尺寸",output.shape)
    output = tudui(output)
    print("全连接层输出尺寸",output.shape)


在这里插入图片描述

  1. 网络搭建以及Sequential的使用
    顺序容器,可以按照添加的顺序依次执行包含的各个模块,torch.nn.Sequential提供了一种简单的方式来构建神经网络模型,代码十分简洁。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    各层输入输出顺序如下图所示
    在这里插入图片描述

搭建上图中的网络,各层的padding和stride需要手动计算一下在这里插入图片描述
最后两步的线性层中略有省略,在此补充
在这里插入图片描述

#未使用sequential
from torch import nn
from torch.nn import Module
from torch.nn import Conv2d
from torch.nn import MaxPool2d,Flatten,Linear
import torch

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__init__()
        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()
        self.linear1 = Linear(1024,64)
        self.linear2 = Linear(64, 10)
        
    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)
        return x
        
tudui = Tudui()
print(tudui)

input = torch.ones((64, 3, 32, 32))
output = tudui(input)
print(output.shape)

搭建网络并构造3*32*32的数据输入网络,检验网络各层输入输出的正确性
在这里插入图片描述
使用Sequential并使用tensorboard添加计算图

from torch import nn
from torch.nn import Module
from torch.nn import Conv2d
from torch.nn import MaxPool2d,Flatten,Linear, Sequential
import torch
from torch.utils.tensorboard import SummaryWriter 

#使用sequential
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__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
    
writer = SummaryWriter("logs") # 日志文件存储位置  
writer.add_graph(tudui, input)
tudui = Tudui()
print(tudui)

input = torch.ones((64, 3, 32, 32))
output = tudui(input)
print(output.shape)
writer.close()

在这里插入图片描述
在tensorboard中打开,点击GRAPHS
writer.add_graph(模型, 可选参数–模型的输入数据)是 TensorBoardX 库中用于将模型结构添加到 TensorBoard 中的函数。它可以将 PyTorch 模型的计算图可视化,方便查看模型的层次结构和数据流动
在这里插入图片描述
点击Tudui可查看详细结构
在这里插入图片描述

  1. torch.nn中的损失函数
    损失函数(Loss Function)用于衡量模型的预测输出与实际标签之间的差异或者误差,损失越小越好,根据loss调整参数(反向传播),更新输出,减小损失
    在这里插入图片描述
    在这里插入图片描述
import torch
from torch.nn import L1Loss

inputs = torch.tensor([1,2,3],dtype=torch.float32)
targets = torch.tensor([1,2,5],dtype=torch.float32)

inputs = torch.reshape(inputs, (1,1,1,3))
targets = torch.reshape(targets, (1,1,1,3))
loss = L1Loss()
result = loss(inputs,targets)
print(result)

loss2 = L1Loss(reduction='sum')
result2 =loss2(inputs,targets)
print(result2)

在这里插入图片描述
在这里插入图片描述
均方损失
在这里插入图片描述

import torch
from torch.nn import L1Loss,MSELoss

inputs = torch.tensor([1,2,3],dtype=torch.float32)
targets = torch.tensor([1,2,5],dtype=torch.float32)

inputs = torch.reshape(inputs, (1,1,1,3))
targets = torch.reshape(targets, (1,1,1,3))
loss = L1Loss()
result = loss(inputs,targets)
print(result)

loss2 = L1Loss(reduction='sum')
result2 =loss2(inputs,targets)
print(result2)

mse_loss = MSELoss()
mse_result = mse_loss(inputs,targets)
print(mse_result)

在这里插入图片描述

  1. 分类问题常用损失:torch.nn.CrossEntropyLoss交叉熵损失函数
    交叉熵损失函数(Cross-Entropy Loss Function)是在分类问题中经常使用的一种损失函数,特别是在多分类问题中。它衡量了模型输出的概率分布与真实标签之间的差异,通过最小化交叉熵损失来调整模型参数,使得模型更好地适应分类任务。
    在这里插入图片描述
    当分类预测正确时,损失要比较小;上式两项,左边的项相比右边的项应较大
    在这里插入图片描述
    在这里插入图片描述
import torch
from torch.nn import CrossEntropyLoss

x = torch.tensor([0.1, 0.2, 0.3])
y = torch.tensor([1])
x = torch.reshape(x,(1,3))
loss_cross = CrossEntropyLoss()
result_cross = loss_cross(x, y )
print(result_cross)

在这里插入图片描述
在这里插入图片描述
loss function的使用应根据需求,选定好损失函数后,按损失函数要求的维度(形状)输入

  1. 使用前面搭建的网络结合CrossEntropyLoss计算损失
from torch import nn
from torch.nn import Module
from torch.nn import Conv2d
from torch.nn import MaxPool2d,Flatten,Linear, Sequential
import torch
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(), download=True)
dataloader = DataLoader(dataset, batch_size=1, drop_last=True)

#使用sequential
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__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()
tudui = Tudui()
for data in dataloader:
    imgs, targets = data
    outputs = tudui(imgs)
#     print(outputs)
#     print(targets)
    result_loss = loss(outputs, targets)
    print(result_loss)
    
    

在这里插入图片描述

关于outputs和targets的维度匹配的问题
在你提供的代码中,outputs 和 targets 的维度能够匹配上,这是因为在构建 Tudui 类时,你没有对输入图片进行展平(Flatten),因此输入的图片在经过 Sequential 中的各个层时,维度会保持在图片数据的维度上(例如 [batch_size, channels, height, width]),并且在经过最后一个线性层时会自动展平为 [batch_size, num_classes] 的形状,其中 num_classes 是输出的类别数量。
让我们具体分析一下:
输入的图片 imgs 的维度为 [batch_size, channels, height, width],例如 [1, 3, 32, 32](假设 batch size 为 1,图像大小为 32x32,并且有 3 个通道)。
在 Tudui 类中,通过 Sequential 定义了模型结构,但没有对输入图片进行展平操作,因此保持了输入图片的维度。
经过 Sequential 中的各个层之后,最后一个线性层的输出会自动展平为 [batch_size, num_classes] 的形状,其中 num_classes 是输出的类别数量(这里是 10,因为 CIFAR-10 数据集有 10 个类别)。
因此,在计算损失时,outputs 的维度为 [batch_size, num_classes],与 targets 的维度 [batch_size] 是匹配的,因为交叉熵损失函数 nn.CrossEntropyLoss() 会自动处理这种情况,它期望 outputs 的形状是 [batch_size, num_classes],并且 targets 的形状是 [batch_size],它会自动将 targets 进行 one-hot 编码并计算交叉熵损失。

  1. 反向传播
    张量梯度的属性:grad
    自动求导(Autograd): 在张量上进行操作时,PyTorch 会自动跟踪操作并构建计算图,可以使用 .backward() 方法(反向传播)计算梯度,然后通过 .grad 属性获取梯度值。
    在pycharm中对该行打断点,可以看到具体的梯度值
    在这里插入图片描述
from torch import nn
from torch.nn import Module
from torch.nn import Conv2d
from torch.nn import MaxPool2d,Flatten,Linear, Sequential
import torch
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(), download=True)
dataloader = DataLoader(dataset, batch_size=1, drop_last=True)

#使用sequential
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__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()
tudui = Tudui()
for data in dataloader:
    imgs, targets = data
    outputs = tudui(imgs)
    result_loss = loss(outputs, targets)
    result_loss.backward()
    print(result_loss)
    
    

当未使用.backward()时,grad属性会一直为None
在这里插入图片描述
这里还未使用优化器,结合优化器可以对参数进行优化,降低loss

  1. 优化器的使用torch.optim
    在深度学习中,optimizer.zero_grad()是一个非常重要的操作,它的含义是将模型参数的梯度清零。
    在训练神经网络时,通常采用反向传播算法(Backpropagation)来计算损失函数关于模型参数的梯度,并利用优化器(optimizer)来更新模型参数以最小化损失函数。在每次反向传播计算梯度后,梯度信息会被累积在对应的参数张量(tensor)中。如果不清零梯度,在下一次计算梯度时,这些梯度将会被新计算的梯度累加,导致梯度信息错误。
    optimizer.zero_grad()的作用如下:
    在这里插入图片描述

先进行optimizer.zero_grad()再进行计算loss,进行反向传播loss.backward()之后再进行optim.step()
optim.step()是优化器对象(如SGD、Adam等)的一个方法,用于根据计算得到的梯度更新模型的参数
在这里插入图片描述

for data in dataloader循环完相当于对数据进行了一轮的学习(看了一遍),在这个for循环中用这次看到的数据更新网络参数,对下一次看到的数据影响不大,因为只对整个数据看了一遍,这时的loss变化不大

from torch import nn
from torch.nn import Module
from torch.nn import Conv2d
from torch.nn import MaxPool2d,Flatten,Linear, Sequential
import torch
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(), download=True)
dataloader = DataLoader(dataset, batch_size=1, drop_last=True)

#使用sequential
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__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()
tudui = Tudui()
optim = torch.optim.SGD(tudui.parameters(), lr=0.01, )

for data in dataloader:
    imgs, targets = data
    outputs = tudui(imgs)
    result_loss = loss(outputs, targets)
    optim.zero_grad()
    result_loss.backward()
    optim.step()
    print(result_loss)

在这里插入图片描述
因此需要引入epoch,对数据多扫几遍

for data in dataloader循环:
这个循环通常用于遍历数据集中的每个批次(batch)数据。
dataloader是一个用于批次化处理数据的工具,它会将数据集按照指定的批次大小分割,并提供数据加载的迭代器。
在每次迭代中,for data in dataloader会从数据加载器中获取一个批次的数据,然后你可以对这个批次的数据进行前向传播、计算损失、反向传播和参数更新等操作。
这个循环通常嵌套在训练循环中,用于处理每个训练批次的数据。

for epoch in range(X)循环:
这个循环用于控制整个训练过程的迭代次数,其中X代表训练的总轮数(epochs)。
一个epoch表示将数据集中的所有样本都用于训练一次,通常情况下,训练过程会重复多个epoch以便模型能够更好地学习数据的特征。
在每个epoch循环中,你会执行多次for data in dataloader循环,每次处理一个批次的数据,并进行前向传播、损失计算、反向传播和参数更新等训练步骤。
一般来说,训练过程会在每个epoch结束时进行模型评估,例如计算验证集上的准确率或损失,以便监控模型的训练情况和避免过拟合。

综上所述,for data in dataloader循环用于处理单个批次的数据,而for epoch in range(X)循环用于控制整个训练过程的迭代次数,确保模型能够在整个数据集上进行多次学习和优化。在实际的训练过程中,这两个循环通常会结合使用,以完成模型的训练任务。

from torch import nn
from torch.nn import Module
from torch.nn import Conv2d
from torch.nn import MaxPool2d,Flatten,Linear, Sequential
import torch
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(), download=True)
dataloader = DataLoader(dataset, batch_size=1, drop_last=True)

#使用sequential
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui,self).__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()
tudui = Tudui()
optim = torch.optim.SGD(tudui.parameters(), lr=0.01, )
for epoch in range(20):
    running_loss = 0.0
    for data in dataloader:
        imgs, targets = data
        outputs = tudui(imgs)
        result_loss = loss(outputs, targets)
        optim.zero_grad()
        result_loss.backward()
        optim.step()
        running_loss = running_loss +result_loss # running_loss相当于扫一遍全部数据的loss总和
    print(running_loss)
        

【注】:运行会比较慢,执行几个epoch看下loss的变化情况即可
在这里插入图片描述

  1. 使用pytorch提供的网络模型VGG16
    在这里插入图片描述

在这里插入图片描述
以上是博主2024年3月官网截图,vgg16的调用方法已经发生改变,与小土堆视频中的调用方法发生改变,不再有参数pretrained而是变成了参数weights
我使用的是torch 1.11.0版本,支持参数pretrained

import torchvision

vgg16_false = torchvision.models.vgg16(pretrained=False) #pretrained=False仅加载网络模型,无参数

vgg16_true = torchvision.models.vgg16(pretrained=True) #pretrained=True加载网络模型,并从网络中下载在数据集上训练好的参数
print(vgg16_true)

在这里插入图片描述
权重会被下载到这个文件夹中C:\Users\用户名.cache\torch\hub\checkpoints
在这里插入图片描述
有下载问题的可以使用我下载好的文件,放置在对应文件路径下即可

链接:https://pan.baidu.com/s/1DqR9GK1VJBJgWUqTCUQXWA 提取码:cfjx

可通过以下命令torch.hub.set_dir('新路径')来设置自定义的缓存文件夹路径

import torchvision.models as models

# 设置自定义缓存文件夹路径
torch.hub.set_dir('/path/to/custom/cache/dir/')
# 加载预训练的VGG16模型
vgg16 = models.vgg16(pretrained=True)
  1. 修改VGG网络(对1000类进行分类) 在网络最后添加一个线性层 在CIFAR10上(对10类)进行分类
    使用add_module()方法
import torchvision
import torch.nn as nn
vgg16_true = torchvision.models.vgg16(pretrained=True) #pretrained=True加载网络模型,并从网络中下载在数据集上训练好的参数
dataset = torchvision.datasets.CIFAR10("./dataset",train= False, transform =torchvision.transforms.ToTensor(), download=True)
vgg16_true.add_module('add_linear', nn.Linear(1000,10))
print(vgg16_true)

在这里插入图片描述
将添加的线性层加在classifier中

import torchvision
import torch.nn as nn
vgg16_true = torchvision.models.vgg16(pretrained=True) #pretrained=True加载网络模型,并从网络中下载在数据集上训练好的参数
dataset = torchvision.datasets.CIFAR10("./dataset",train= False, transform =torchvision.transforms.ToTensor(), download=True)
vgg16_true.classifier.add_module('add_linear', nn.Linear(1000,10))
print(vgg16_true)

在这里插入图片描述

不添加层,仅修改vgg原有网络

import torchvision
import torch.nn as nn
vgg16_true = torchvision.models.vgg16(pretrained=True) #pretrained=True加载网络模型,并从网络中下载在数据集上训练好的参数
print("修改前",vgg16_true)
dataset = torchvision.datasets.CIFAR10("./dataset",train= False, transform =torchvision.transforms.ToTensor(), download=True)
vgg16_true.classifier[6] = nn.Linear(4096,10)
print("修改后",vgg16_true)

在这里插入图片描述

在这里插入图片描述

  1. 模型的保存与读取
    两种保存方式:
    torch.save(vgg16,"vgg16_method1.pth")保存模型结构及模型参数
    torch.save(vgg16.state_dict(),"vgg16_method2.pth")仅保存模型参数存为字典,不保存模型结构(官方推荐)
import torchvision
import torch
vgg16 = torchvision.models.vgg16(pretrained=False)
# 保存方式1--保存模型结构及模型参数
torch.save(vgg16,"vgg16_method1.pth")

# 保存方式2--仅保存模型参数存为字典,不保存模型结构(官方推荐)
torch.save(vgg16.state_dict(),"vgg16_method2.pth")

在这里插入图片描述

两种读取方式:
model = torch.load("vgg16_method1.pth") 加载模型结构 + 参数方式
vgg16 = torchvision.models.vgg16(pretrained=False) vgg16.load_state_dict(torch.load("vgg16_method2.pth")) 为方式2创建模型结构并加载参数的完整写法

import torch
import torchvision
# 保存方式1对应的加载模型结构 + 参数方式
model = torch.load("vgg16_method1.pth")
print(model)

# 保存方式2对应的加载模型参数方式
model2 = torch.load("vgg16_method2.pth") #加载的是字典
print(model2)

vgg16 = torchvision.models.vgg16(pretrained=False) #为方式2创建模型结构并加载参数的完整写法
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
print(vgg16)

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

  1. 方式1 torch.load(“vgg16_method1.pth”)存在的问题
    保存模型+参数
import torch
from torch import nn
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size= 3)
    def forward(self, x):
        x = self.conv1(x)
        return x
    
tudui = Tudui()
torch.save(tudui,"tudui_method1.pth")

读取模型及参数

import torch

model = torch.load("tudui_method1.pth")
print(model)

亲测在jupyter notebook中不会报错
在这里插入图片描述
而在pycharm中会报AttributeError: Can't get attribute 'Tudui' on <module '__main__' from 'D:/DongShouRL/pytorch/nn_load.py'>
在这里插入图片描述
个人猜测:原因应该是在一个jupyter notebook是能够找到Tudui这个类的,而在Pycharm中上述读取和保存在两个文件中,导致找不到Tudui这个类,故报上述错误

解决方法:①要么在读取的文件中把模型的定义复制过来

import torch
import torch.nn as nn
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

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

model = torch.load("tudui_method1.pth")
print(model)

在这里插入图片描述
②导入对应的类使用from nn_save import Tudui

import torch
import torch.nn as nn
from nn_save import  Tudui

# class Tudui(nn.Module):
#     def __init__(self):
#         super(Tudui, self).__init__()
#         self.conv1 = nn.Conv2d(3, 64, kernel_size=3)
#
#     def forward(self, x):
#         x = self.conv1(x)
#         return x

model = torch.load("tudui_method1.pth")
print(model)
  1. print格式化输出字符串
    print函数的format是一种格式化输出字符串的方法,用来插入变量值或格式化输出字符串的样式
    将{}的地方替换为变量值
name = "Alice"
age = 30
print("My name is {} and I am {} years old.".format(name, age))
  1. 搭建后面要用的神经网络
# model.py
from torch import nn
import torch
# 搭建神经网络
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3, 32, 5, 1, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, padding=2),
            nn.MaxPool2d(2),
            nn.Flatten(),  # 展平后的序列长度为 64*4*4=1024
            nn.Linear(1024, 64),
            nn.Linear(64, 10)
        )

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


if __name__ == '__main__':
    tudui = Tudui()
    input = torch.ones((64, 3, 32, 32))
    output = tudui(input)
    print(output.shape)

构造输入,测试网络搭建是否正确
在这里插入图片描述

如果在其他文件中import报错
在这里插入图片描述
将文件所在目录Mark Directory as Sources Root
在这里插入图片描述

  1. item()函数
    item()函数用于从只包含单个元素的张量中提取Python数值,将张量转换为标量值
import torch

# 创建一个只包含一个元素的张量
tensor = torch.tensor([3.14])

# 使用item()函数获取张量的数值
value = tensor.item()

print("Value extracted using item():", value)
print("Type of extracted value:", type(value))

在这里插入图片描述

  1. torch.no_grad()
    在推理或评估模型时使用torch.no_grad(),表明当前计算不需要反向传播,使用之后,强制后边的内容不进行计算图的构建
    with 语句是 Python 中的一个语法结构,用于包裹代码块的执行,并确保在代码块执行完毕后,能够自动执行一些清理工作。

  2. 完整的模型训练与测试套路

from torch.utils.tensorboard import SummaryWriter

from model import *
import torchvision
import torch.nn as nn
from torch.utils.data import DataLoader
# 准备数据集
train_data = torchvision.datasets.CIFAR10("../dataset",train=True, transform=torchvision.transforms.ToTensor(),
                                         download=True)
test_data = torchvision.datasets.CIFAR10("../dataset",train=False, transform=torchvision.transforms.ToTensor(),
                                         download=True)
# len()获取数据集长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))

# 利用dataloader加载数据集
train_dataloader = DataLoader(train_data, batch_size=64, drop_last=True)
test_dataloader = DataLoader(test_data, batch_size=64, drop_last=True)

#创建网络模型
tudui = Tudui()

# 损失函数
loss_fn = nn.CrossEntropyLoss()

# 优化器
learning_rate = 1e-2
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)

# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0

# 记录测试的次数
total_test_step = 0

# 训练的轮数
epoch = 10

# 添加tensorboard
writer = SummaryWriter("../logs_train")

for i in range(epoch):
    print("-------------第 {} 轮训练开始------------".format(i+1))
    #训练步骤开始
    for data in train_dataloader:
        imgs, targets = data
        output = tudui(imgs)
        loss = loss_fn(output, targets)

        #优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step = total_train_step + 1
        if total_train_step % 100 ==0:
            print("训练次数:{}, Loss:{}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss",loss.item(), total_train_step)

    # 测试步骤开始
    total_test_loss = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs, targets = data
            outputs = tudui(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss = total_test_loss + loss.item()
    print("整体测试集上的Loss:{}".format(total_test_loss))
    writer.add_scalar("test_loss",total_test_loss, total_test_step)
    total_test_step = total_test_step + 1

    torch.save(tudui, "tudui_{}.pth".format(i))
    print("模型已保存")
writer.close()

在这里插入图片描述

  1. 分类问题计算正确率的方法
    在这里插入图片描述
    argmax 是一个数学和编程中常用的术语,它表示找到一个函数或数组中最大值的索引或位置。在 PyTorch 中,torch.argmax 是一个函数,用于返回输入张量(Tensor)中最大值的索引。
    在这里插入图片描述
    在这里插入图片描述
import torch

outputs = torch.tensor([[0.1, 0.2],
                        [0.3, 0.4]])
print(outputs.argmax(1))
preds = outputs.argmax(1)
targets = torch.tensor([0,1])
print(preds == targets)
print((preds == targets).sum())

在这里插入图片描述

  1. 补充正确率代码
from torch.utils.tensorboard import SummaryWriter

from model import *
import torchvision
import torch.nn as nn
from torch.utils.data import DataLoader
# 准备数据集
train_data = torchvision.datasets.CIFAR10("../dataset",train=True, transform=torchvision.transforms.ToTensor(),
                                         download=True)
test_data = torchvision.datasets.CIFAR10("../dataset",train=False, transform=torchvision.transforms.ToTensor(),
                                         download=True)
# len()获取数据集长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))

# 利用dataloader加载数据集
train_dataloader = DataLoader(train_data, batch_size=64, drop_last=True)
test_dataloader = DataLoader(test_data, batch_size=64, drop_last=True)

#创建网络模型
tudui = Tudui()

# 损失函数
loss_fn = nn.CrossEntropyLoss()

# 优化器
learning_rate = 1e-2
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)

# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0

# 记录测试的次数
total_test_step = 0

# 训练的轮数
epoch = 10

# 添加tensorboard
writer = SummaryWriter("../logs_train")

for i in range(epoch):
    print("-------------第 {} 轮训练开始------------".format(i+1))
    #训练步骤开始
    tudui.train()
    for data in train_dataloader:
        imgs, targets = data
        output = tudui(imgs)
        loss = loss_fn(output, targets)

        #优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step = total_train_step + 1
        if total_train_step % 100 ==0:
            print("训练次数:{}, Loss:{}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss",loss.item(), total_train_step)

    # 测试步骤开始
    tudui.eval()
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs, targets = data
            outputs = tudui(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss = total_test_loss + loss.item()
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy = total_accuracy + accuracy
    print("整体测试集上的Loss:{}".format(total_test_loss))
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
    writer.add_scalar("test_loss",total_test_loss, total_test_step)
    writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
    total_test_step = total_test_step + 1

    torch.save(tudui, "tudui_{}.pth".format(i))
    print("模型已保存")
writer.close()
  1. model.train()和model.eval()
    model.train()开启训练模式,模型会跟踪所有层的梯度,以便在优化器(如 torch.optim.SGD 或 torch.optim.Adam)进行梯度下降时更新模型的权重。此外,train() 方法还会将模型中的某些层(如 BatchNorm 和 Dropout)设置为训练行为。

BatchNorm 层:对于包含 BatchNorm(批量归一化)层的模型,model.train() 确保在训练过程中使用每一批数据来计算层的运行均值和方差。这些运行统计量用于归一化网络的激活值,有助于提高训练的稳定性和性能。

Dropout 层:对于包含 Dropout 层的模型,model.train() 在训练过程中随机选择一部分网络连接进行训练,即“丢弃”一部分神经元的输出。这样做可以防止网络过拟合,因为每次训练时只有一部分神经元被激活,从而增加了模型的泛化能力。
在这里插入图片描述
model.eval():开启评估模式,在评估模式下,模型不会跟踪梯度,这有助于减少内存消耗并提高计算效率。此外,eval() 方法还会将模型中的某些层(如 BatchNorm 和 Dropout)设置为评估行为,这意味着它们的行为会根据固定的参数进行调整,而不是根据训练数据。
在评估模式(model.eval())下,BatchNorm 层会使用在训练过程中学习到的均值和方差,而不是使用当前批次的数据。
在评估模式下,Dropout 层会被禁用,所有的神经元都会保留其输出,确保评估时的确定性。

在这里插入图片描述
当网络中有这些Dropout、BatchNorm 层时,一定要调用model.train()和model.eval()当网络不含这些层时,不进行调用也可以

  1. 使用GPU进行训练方式1 xx = xx.cuda()
    在这里插入图片描述
    训练数据和测试数据都要.cuda()
from torch.utils.tensorboard import SummaryWriter

import torch
import torchvision
import torch.nn as nn
from torch.utils.data import DataLoader
# 准备数据集
train_data = torchvision.datasets.CIFAR10("../dataset",train=True, transform=torchvision.transforms.ToTensor(),
                                         download=True)
test_data = torchvision.datasets.CIFAR10("../dataset",train=False, transform=torchvision.transforms.ToTensor(),
                                         download=True)
# len()获取数据集长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))

# 利用dataloader加载数据集
train_dataloader = DataLoader(train_data, batch_size=64, drop_last=True)
test_dataloader = DataLoader(test_data, batch_size=64, drop_last=True)

#创建网络模型
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),  # 展平后的序列长度为 64*4*4=1024
            nn.Linear(1024, 64),
            nn.Linear(64, 10)

        )

    def forward(self, x):
        x = self.model(x)
        return x
    
tudui = Tudui()
if torch.cuda.is_available():
    tudui = tudui.cuda()

# 损失函数
loss_fn = nn.CrossEntropyLoss()
if torch.cuda.is_available():
    loss_fn = loss_fn.cuda()
# 优化器
learning_rate = 1e-2
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)

# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0

# 记录测试的次数
total_test_step = 0

# 训练的轮数
epoch = 10

# 添加tensorboard
writer = SummaryWriter("../logs_train")

for i in range(epoch):
    print("-------------第 {} 轮训练开始------------".format(i+1))
    #训练步骤开始
    tudui.train()
    for data in train_dataloader:
        imgs, targets = data
        if torch.cuda.is_available():
            imgs = imgs.cuda()
            targets = targets.cuda()
        output = tudui(imgs)
        loss = loss_fn(output, targets)

        #优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step = total_train_step + 1
        if total_train_step % 100 ==0:
            print("训练次数:{}, Loss:{}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss",loss.item(), total_train_step)

    # 测试步骤开始
    tudui.eval()
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs, targets = data
            if torch.cuda.is_available():
                imgs = imgs.cuda()
                targets = targets.cuda()
            outputs = tudui(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss = total_test_loss + loss.item()
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy = total_accuracy + accuracy
    print("整体测试集上的Loss:{}".format(total_test_loss))
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
    writer.add_scalar("test_loss",total_test_loss, total_test_step)
    writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
    total_test_step = total_test_step + 1

    torch.save(tudui, "tudui_{}.pth".format(i))
    print("模型已保存")
writer.close()

  1. 在jupyter notebook中运行shell命令
!命令

在这里插入图片描述

  1. 使用GPU进行训练方式2(更常用) xx = xx.to(device)
    在这里插入图片描述
from torch.utils.tensorboard import SummaryWriter

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

# 定义训练的设备
device =  torch.device("cuda")
# 准备数据集
train_data = torchvision.datasets.CIFAR10("./dataset",train=True, transform=torchvision.transforms.ToTensor(),
                                         download=True)
test_data = torchvision.datasets.CIFAR10("./dataset",train=False, transform=torchvision.transforms.ToTensor(),
                                         download=True)
# len()获取数据集长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))

# 利用dataloader加载数据集
train_dataloader = DataLoader(train_data, batch_size=64, drop_last=True)
test_dataloader = DataLoader(test_data, batch_size=64, drop_last=True)

#创建网络模型
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),  # 展平后的序列长度为 64*4*4=1024
            nn.Linear(1024, 64),
            nn.Linear(64, 10)

        )

    def forward(self, x):
        x = self.model(x)
        return x
    
tudui = Tudui()
tudui = tudui.to(device)

# 损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device)

# 优化器
learning_rate = 1e-2
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)

# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0

# 记录测试的次数
total_test_step = 0

# 训练的轮数
epoch = 10

# 添加tensorboard
writer = SummaryWriter("../logs_train")

for i in range(epoch):
    print("-------------第 {} 轮训练开始------------".format(i+1))
    #训练步骤开始
    tudui.train()
    for data in train_dataloader:
        imgs, targets = data

        imgs = imgs.to(device)
        targets = targets.to(device)
        output = tudui(imgs)
        loss = loss_fn(output, targets)

        #优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_train_step = total_train_step + 1
        if total_train_step % 100 ==0:
            print("训练次数:{}, Loss:{}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss",loss.item(), total_train_step)

    # 测试步骤开始
    tudui.eval()
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs, targets = data
            imgs = imgs.to(device)
            targets = targets.to(device)
            outputs = tudui(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss = total_test_loss + loss.item()
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy = total_accuracy + accuracy
    print("整体测试集上的Loss:{}".format(total_test_loss))
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
    writer.add_scalar("test_loss",total_test_loss, total_test_step)
    writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
    total_test_step = total_test_step + 1

    torch.save(tudui, "tudui_{}.pth".format(i))
    print("模型已保存")
writer.close()

更便捷的写法

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
  1. 【注】:前面讲的两种在GPU训练方法,其实只有数据和标签(imgs和targets)需要进行 数据 = 数据.cuda() 或者 数据 = 数据.to(device)
    模型和损失函数可以直接model.to() ,model.cuda() ,loss.to(),loss.cuda()而无需赋值
    在这里插入图片描述
    在这里插入图片描述

  2. 利用已经训练好的模型 提供输入进行验证

import torchvision
from PIL import Image

image_path = "./dog.png"
image = Image.open(image_path)
print(image)
image = image.convert('RGB')
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),
                                            torchvision.transforms.ToTensor()
                                           ])
image = transform(image)
print(image)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),  # 展平后的序列长度为 64*4*4=1024
            nn.Linear(1024, 64),
            nn.Linear(64, 10)

        )

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

model = torch.load("tudui_0.pth",map_location=torch.device("cuda"))
print(model)
image = torch.reshape(image,(1,3,32,32))
model.eval()
with torch.no_grad():
    image = image.to("cuda")
    output = model(image)
print(output)
print(output.argmax(1))
  1. 使用gpu训练保存的模型在cpu上使用
model = torch.load("XXXX.pth",map_location= torch.device("cpu"))

map_location=torch.device("cpu") 是在使用 PyTorch 的 torch.load 函数加载模型或张量时的一个参数,它用于指定加载数据的目标设备。当你使用这个参数时,你告诉 PyTorch 将加载的数据映射到 CPU 上,而不是默认的 CUDA 设备(如果你的系统上有 GPU)。

  1. 运行python文件传入参数
python XXX.py --参数名 值

在这里插入图片描述

  1. 练习代码文件

链接:https://pan.baidu.com/s/1323fpWQiv0UrMS4vHGbN8g
提取码:m0c4

完结撒花!在此,感谢小土堆制作的视频教程与阅读这篇博客的你~

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

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

相关文章

Java项目:79 springboot海滨体育馆管理系统的设计与实现

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 体育馆管理系统主要实现了管理员功能模块和学生功能模块两大部分 管理员功能模块&#xff1a; 管理员登录后可对系统进行全面管理操作&#…

android安卓看书APP课设

一、引言 随着移动设备的普及和网络的发展&#xff0c;手机阅读成为了现代人获取知识和娱乐的重要途径之一。为了满足用户的阅读需求&#xff0c;我们设计并开发了一款安卓看书APP。本文将介绍该APP的设计理念、功能特点以及技术实现。 二、功能描述 1. 主页底部导航栏 为了…

免费|Python|【需求响应】一种新的需求响应机制DR-VCG研究

目录 1 主要内容 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序对应文章《Contract Design for Energy Demand Response》&#xff0c;电力系统需求响应&#xff08;DR&#xff09;用来调节用户对电能的需求&#xff0c;即在预测的需求高于电能供应时&#xff0c;希…

rtthread studio 基于bsp生成代码stm32l475正点原子潘多拉,以及硬件配置

1、基于bsp生成代码 rtthread studio 很强大的一个功能就是可以根据芯片或者bsp 生成驱动代码&#xff0c;而且rtthread内核 已经集成到了代码中&#xff01;&#xff01;只需要关注于如何使用硬件和设备完成我们想要的功能就可以&#xff1b; 它的官网文档也特别详细&#x…

银行监管报送系统介绍(十二):非居民金融账户涉税信息报送

国家税务总局、财政部、中国人民银行、中国银行业监督管理委员会、中国证券监督管理委员会、国家金融监督管理总局2017年5月9日发布、2017年7月1日起施行的《非居民金融账户涉税信息尽职调查管理办法》。 一、《管理办法》出台的背景是什么&#xff1f;   受二十国集团&…

算法---动态规划练习-8(打家劫舍2)

打家劫舍2 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址&#xff1a;点这里 2. 讲解算法原理 首先&#xff0c;给定一个非负整数数组 nums&#xff0c;其中 nums[i] 表示第 i 家的财物价值。 定义两个辅助数组 f 和 g&#xff0c;长度都为 n&#xff08;n 是…

Java智慧工地源码 智慧工地的价值体现 开发一套智慧工地系统需要多少钱

智慧工地是智慧地球理念在工程领域的行业具现&#xff0c;是一种崭新的工程全生命周期管理理念。它运用信息化手段&#xff0c;通过三维设计平台对工程项目进行精确设计和施工模拟&#xff0c;围绕施工过程管理&#xff0c;建立互联协同、智能生产、科学管理的施工项目信息化生…

亲身体验!人工智能对话无障碍 —— BRClient 使用指南

01 概述 BRClient 这个名字来源于“Bedrock Client”的简称&#xff0c;寓意是为用户提供一个坚实的基础。BRClient 作为一个开源的桌面应用&#xff0c;为用户提供了友好的图形界面&#xff0c;让每个人都能够轻松访问和使用 Claude 3 的强大功能。用户可以自定义 Claude 3 的…

2024 ccfcsp认证打卡 2023 03 01 田地丈量

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner in new Scanner(System.in);int n in.nextInt(); // 输入 n&#xff0c;表示矩形的数量int a in.nextInt(); // 输入 a&#xff0c;表示整个区域的长度int b in.nextInt()…

Web Components初探

组件化&#xff0c;标签语义化&#xff0c;是前端发展的趋势。现在流行的组件化框架有React、Vue等&#xff0c;标签语义化在H5中添加的article、dialog等。 Web Components 就是类似的一套技术&#xff0c;允许您创建可重用的定制元素&#xff0c;并且在您的web应用中使用它们…

python外网下载指定库导入内网的方法

前提&#xff1a;保持内网python版本和外网python版本一致 1.外网电脑上新建一个空文件夹&#xff0c;用于存放下载下来的库&#xff0c;cmd窗口中输入命令pip install 库名 -target下载的库存放的路径&#xff0c;则会将对应库下载到指定文件夹下 2.将该文件夹下内容拷贝内网…

Git_常用命令+代码冲突解决方案

文章目录 基本命令的使用查看git的当前版本初始化配置设置用户名及邮箱设置仓库的认证方式查看当前配置 创建仓库从远程服务器克隆仓库创建本地仓库 添加和提交文件工作区域和文件状态工作区域文件状态 查看文件状态及分支信息查看暂存区的内容添加文件提交文件查看提交日志回退…

贝锐蒲公英虚拟DMZ:工业设备异地组网,解决网段冲突难题

虚拟DMZ 产品/技术的原理传统DMZ&#xff1a; DMZ中文名称为“隔离区”&#xff0c;也称“非军事化区”&#xff1b;它是为解决安装防火墙后外部网络不能访问内部网络服务器的问题。网关DMZ功能开启后&#xff0c; 将内网的一台服务器完全暴露在外网&#xff08;内网某个IP绑…

Redis入门到实战-第二十二弹

Redis实战热身Sentinel篇 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的&#xff08;采用BSD许可证&#xff09;&#xff0c;用作数据库、缓存、消息代理和流处理引擎的内存…

C++基础之重载,重写和隐藏(十八)

一.重载 定义&#xff1a;发生在统一作用域中&#xff0c;函数名称相同&#xff0c;但是参数列表不同&#xff08;包括参数的个数&#xff0c;参数类型&#xff0c;参数顺序&#xff09;。 #include <iostream>using std::cout; using std::endl;int add(int a,int b) …

【Diffusers库】第四篇 训练一个扩散模型(Unconditional)

目录 写在前面的话下载数据模型配置文件加载数据创建一个UNet2DModel创建一个调度器训练模型完整版代码&#xff1a; 写在前面的话 这是我们研发的用于 消费决策的AI助理 &#xff0c;我们会持续优化&#xff0c;欢迎体验与反馈。微信扫描二维码&#xff0c;添加即可。   官方…

2024通信展会|中国国际信息通信展览会|北京通信展

2024通信展会|中国国际信息通信展览会|北京通信展 2024年中国信息通信展将于2024年9月25-27日在北京.国家会议中心举办&#xff0c;展会将为我们带来无尽的惊喜和机遇。让我们一起期待这场盛大的科技盛会&#xff01; 2024年中国国际信息通信展览会&#xff08;简称&#xff1…

【分类评估指标,精确率,召回率,】from sklearn.metrics import classification_report

from&#xff1a; https://zhuanlan.zhihu.com/p/368196647 多分类 from sklearn.metrics import classification_report y_true [0, 1, 2, 2, 2] y_pred [0, 0, 2, 2, 1] target_names [class 0, class 1, class 2] # print(classification_report(y_true, y_pred, targe…

基于Transformer的医学图像分类研究

医学图像分类目前面临的挑战 医学图像分类需要研究人员同时具备医学图像分析和数字图像的知识背景。由于图像尺度、数据格式和数据类别分布的影响&#xff0c;现有的模型方法&#xff0c;如传统的机器学习的识别方法和基于深度卷积神经网络的方法&#xff0c;取得的识别准确度…

linux 环境安装配置

安装java17 1.下载安装包 wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz 2.解压到自定义目录/usr/local/java mkdir /usr/local/java tar zxvf jdk-17_linux-x64_bin.tar.gz -C /usr/local/java 3.配置环境变量 echo export PATH$PATH:/…