当前位置: 首页 > article >正文

PyTorch-基础(CUDA、Dataset、transforms、卷积神经网络、VGG16)

PyTorch-基础

环境准备

CUDA Toolkit安装(核显跳过此步骤)

CUDA Toolkit是NVIDIA的开发工具,里面提供了各种工具、如编译器、调试器和库

首先通过NVIDIA控制面板查看本机显卡驱动对应的CUDA版本,如何去下载对应版本的Toolkit工具,本人下载的是Toolkit 12.2

下载地址:https://developer.nvidia.com/cuda-toolkit-archive

在这里插入图片描述

下载完毕后打开cuda_12.2.2_windows_network.exe,这里会让你指定一个临时目录这个目录用于存放临时文件的,安装Toolkit 成功后会自动卸载

注意临时目录不要和安装目录指定相同位置,假如指定了相同位置后面是无法安装的

在这里插入图片描述

选择路径时可以切换到自定义的安装路径

路径最好和工具中一致,参考路径D:\NVIDIA CUDA\NVIDIA GPU Computing Toolkit\CUDA\v版本号

在这里插入图片描述

安装完后后我们需要添加CUDA环境变量

在这里插入图片描述

在这里插入图片描述

安装完毕后通过nvcc -V测试是否安装成功

在这里插入图片描述

CUDNN安装(核显跳过此步骤)

Cudnn是NVIDIA提供的一个深度神经网络加速库,它包含了一系列高性能的基本函数和算法,用于加速深度学习任务的计算,它可以与Cuda一起使用,提供了针对深度学习任务的高效实现。

下载地址:https://developer.nvidia.com/cudnn-downloads

选择对应CUDA版本下载,这里下载压缩包

在这里插入图片描述

下载完毕后将压缩包解压,将解压内容直接复制粘贴到CUDA安装目录下,本人安装目录是D:\NVIDIA CUDA\NVIDIA GPU Computing Toolkit\CUDA\v12.1

在这里插入图片描述

粘贴完毕后打开命令行执行nvidia-smi看到如下内容表示安装成功

在这里插入图片描述

Anaconda创建虚拟环境

#创建一个名为pytorch,python版本3.8的虚拟环境
conda create -n pytroch2.3.0 python=3.8
#切换到当前环境
conda activate pytroch2.3.0
#查看本机支持的CUDA版本(核显跳过)
nvidia-smi
#安装pytorch
#官网https://pytorch.org/get-started/locally/
#下载对应CUDA版本的pytorch(独显电脑执行该命令)
#如果与下载很慢,可以分开下载
conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia
#下载对应CUDA版本的pytorch(核显电脑执行该命令)
conda install pytorch torchvision torchaudio cpuonly -c pytorch

测试PyTroch

在包都安装完毕后执行如下命令没有任何报错表示安装成功

#进入python命令行
python
#引入torch
import torch
#测试cuda(核显返回False,独显返回True)
torch.cuda.is_available()

编辑器选择

在开发过程中需要使用到2款编辑器,分别是PyCharm和Jupyter

PyCharm

PyCharm:https://www.jetbrains.com.cn/pycharm/download/

安装完毕后再PyCharm中Settings中找到Python Interpreter并且选择Add Interpreter将Conda添加进来,这样项目就可以选择指定Conda的环境运行

在这里插入图片描述

Jupyter

安装Anaconda时会顺便安装了Jupyter,但是Jupyter默认是Base环境,接下来我们需要在前面创建好的pytroch2.3.0环境下安装Jupyter

#切换到pytroch2.3.0
conda activate pytroch2.3.0
#安装Jupyter
conda install nb_conda
#安装完毕,
jupyter notebook

启动成功后创建一个文件,切换环境,执行测试代码

在这里插入图片描述

常用类库

Dataset

Pytroch提供Dataset用于存放数据集,使用方式很简单编写一个类继承Dataset,实现init、getitem、len方法即可简单使用Dataset,以下就是一个Dataset的简单使用

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, item):
        img_name = self.img_path[item]
        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 = 'E:\\Python-Project\\Torch-Demo\\dataset\\train'
#蚂蚁数据集
ants_label_dir = 'ants_image'
ants_dataset = MyData(root_dir,ants_label_dir)
#蜜蜂数据集
bees_label_dir = 'bees_image'
bees_dataset = MyData(root_dir,bees_label_dir)
#合并2个数据集
train_dataset = ants_dataset + bees_dataset

transforms

transforms是神经网络中一个非常重要的库,它提供了将数据转换为Tensor类型数据,Tensor包装了神经网络的数据参数如数据网络的数据格式、梯度、梯度方法等,并且transforms包含了很多操作数据的库可以对Tensor数据进行各种修改

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

writer = SummaryWriter('logs')

img_path = "data/train/ants_image/0013035.jpg"
img = Image.open(img_path)
#将图片转换为tensor类型
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("ToTensor", img_tensor)

#对tensor进行进行归一化,减少不同图片的色彩的差值,提升训练效果
#规划的计算公式 output[channel] = (input[channel] - mean[channel]) / std[channel]
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize", img_norm)

#对PIL图片大小修改
trans_resize = transforms.Resize((512, 512))
img_resize = trans_resize(img)
img_resize = trans_totensor(img_resize)
writer.add_image("Resize", img_resize)

#对PIL图片进行整体缩放
trans_resize_2 = transforms.Resize(512)
trans_compose = transforms.Compose([trans_resize_2,trans_totensor])
img_resize_2 = trans_compose(img)
writer.add_image("Resize", img_resize_2,1)

#对PIL图片进行随机裁剪
trans_random = transforms.RandomCrop((128,128))
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()

tensorboard

tensorboard提供训练可视化工具,通过图标的方式可以跟踪实验中不同阶段下的指标用于对比

依赖安装
#安装tensorboard可视化工具
conda install tensorboard
启动tensorboard
#--logdir 指定读取的文件目录
#--port 指定服务启动的端口
tensorboard --logdir=logs --port=6007
简单使用案例

以下创建1个函数y=2x,并且将内容输出到tensorboard

from torch.utils.tensorboard import SummaryWriter
#指定日志生成的目录
writer = SummaryWriter("logs")
#往writer写入数据
#参数1:图表名称
#参数2:Y轴值
#参数3:X轴值
for i in range(100):
    writer.add_scalar("y=2x", 2 * i, i)
#关闭流
writer.close()

在项目目录下使用tensorboard --logdir=logs启动tensorboard

常见问题:

多次重复执行时刷新tensorboard会发现图标很乱,解决方法有2种:

1、将logs下文件生成重新代码重新启动tensorboard

2、每次执行都创建一个新的logs文件,将图标写入新logs文件下

在这里插入图片描述

Dataset下载与转换

结合Dataset和Transforms对数据集进行下载并且转换,PyTorch提供了一些用于练习的数据集可以通过Dataset进行下载,一下就是一个案例

import torchvision
from torch.utils.tensorboard import SummaryWriter

#定义一个转换操作,对dataset中的数据集进行操作
dataset_transform = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor(),
])

#训练数据集,CIFAR10是PyTorch提供的一个数据集,会自动去下载
#https://www.cs.toronto.edu/~kriz/cifar.html
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)

#使用tensorboard显示数据集合,显示前面10张
writer = SummaryWriter("p10")
for i in range(10):
    img,target = test_set[i]
    writer.add_image("test_set",img,i)

writer.close()

DataLoader

Dataset是数据集,那么需要获取数据集的数据那么就需要用到DataLoader,DataLoader可以将数据集安装指定规则分批、打乱后重新组合成一批一批的数据

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

#测试数据集
test_data = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
#加载数据集,batch_size=4每获取4张数据为一组,shuffle=True乱序获取
#加载完毕后元组(图片集合,标签集合)
test_loader = DataLoader(dataset=test_data,batch_size=4,shuffle=True,num_workers=0,drop_last=False)

#打印Dataloader
writer = SummaryWriter("dataloder")
step = 0
for data in test_loader:
    imgs,targets = data
    writer.add_images("test_data",imgs,step)
    step = step + 1
writer.close()

使用tensorboard --logdir=dataloder在控制台查看加载好的数据集

在这里插入图片描述

神经网络

PyTorch封装了很多神经网络的类库,文档地址 https://pytorch.org/docs/stable/nn.html

卷积神经网络(NN)

卷积层

卷积神经网络具体的计算过程可以参考:https://github.com/vdumoulin/conv_arithmetic/blob/master/README.md

在这里插入图片描述

结合上图与参考地址中的动图案例可以总结出在计算过程中有几个重要参数:

  1. 输入(二维数组)
  2. 卷积核每次计算后移动的步长(stride)
  3. 是否对图像边填充,而增加图像大小(padding)
  4. 输出(二维数组)
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))
kernel = torch.reshape(kernel,(1,1,3,3))
#使用卷积核对图像进行卷积,卷积和在图像中滑动的步长1,可获得一个3X3输出
output = F.conv2d(input,kernel,stride=1,padding=0)
print(output)

#使用卷积核对图像进行卷积,卷积和在图像中滑动的步长2,可获得一个3X3输出
output2 = F.conv2d(input,kernel,stride=2,padding=0)
print(output2)

#使用卷积核对图像进行卷积,卷积和在图像中滑动的步长1,对图像外面填充一圈0的数据图像将变成7X7,可获得一个5X5输出
# [0, 0, 0, 0, 0, 0, 0]
# [0, 1, 2, 0, 3, 1, 0]
# [0, 0, 1, 2, 3, 1, 0]
# [0, 1, 2, 1, 0, 0, 0]
# [0, 5, 2, 3, 1, 1, 0]
# [0, 2, 1, 0, 1, 1, 0]
# [0, 0, 0, 0, 0, 0, 0]
output3 = F.conv2d(input,kernel,stride=1,padding=1)
print(output3)

案例

将PyTorch测试数据集CIFAR10下载下来,利用Conv2d对数据集中的图片进行卷积,卷积核大小为3x3,步长为1,输出6通道

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

#使用测试集训练,以为训练集合数据太多了
dataset = torchvision.datasets.CIFAR10(root='./dataset', train=False, transform=torchvision.transforms.ToTensor(),download=True)
#加载数据
dataloader = DataLoader(dataset,batch_size=64)
#定义一个训练模型
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        #定义一个的卷积方法
        #参数1:输入3个通道的数据(图片又RBG 3个通道组成)
        #参数2:输出为6个通道的数据(进行6次卷积计算结果集堆叠在一起)
        #参数3:卷积核大小3X3
        #参数4:卷积核每次计算后移动步长1
        #参数5:不对图像边进行填充
        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

my_model = MyModel()

writer = SummaryWriter('./logs_conv2d')
step = 0
#计算DataLoader中的每一组数据
for data in dataloader:
    imgs,targets = data
    output = my_model(imgs)
    #torch.Size([64, 3, 32, 32])
    # print(imgs.shape)
    #torch.Size([64, 6, 30, 30])
    # print(output.shape)
    writer.add_images("input",imgs,step)
    #由于6个通道在tensorboard无法显示,强行转换为3个通道,参数1填写-1会根据后面的数自动推算
    output = torch.reshape(output,(-1,3,30,30))
    writer.add_images("output",output,step)
    step = step + 1

writer.close()
最大池化核心层

最大池化的目的是将图像中的特质保留将图像缩小,比如一张5x5的图片池化后变成2x2的这样可以缩小图片提高计算过程

最大池化核,在每一片被池化核覆盖的区域内获取一个最大的值作为结果写入到结果集中,默认没获取完后池化核移动步长等于池化核大小

  1. Ceil_model=True:池化核覆盖区域超出图像范围时也要获取最大值
  2. Ceil_model=False:只获取池化核覆盖区域在图像范围内的最大值,超出范围的值丢弃

在这里插入图片描述

案例

将PyTorch测试数据集CIFAR10下载下来,对数据集进行池化

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(root='./dataset', train=False, download=True, transform=torchvision.transforms.ToTensor())
#加载数据
dataloader = DataLoader(dataset,batch_size=64)
#定义一个训练模型
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        #定义最大池化的规则
        #参数1:池化核3x3
        #参数2:磁化核溢出部分是否保留
        self.maxpool1 = MaxPool2d(kernel_size=3,ceil_mode=False)

    def forward(self, input):
        #对数据进行池化
        output = self.maxpool1(input)
        return output

my_model = MyModel()

writer = SummaryWriter('./logs_maxpool')
step = 0
#计算DataLoader中的每一组数据
for data in dataloader:
    imgs,targets = data
    writer.add_images("input",imgs,step)
    output = my_model(imgs)
    writer.add_images("output",output,step)
    step += 1

writer.close()
非线性激活

默认的图像都是线性的训练出来的模型就很死版,对数据集进行非线性集合后训练模型可以训练出符合各种曲线各种特征的模型

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(root='./dataset', train=False, download=True, transform=torchvision.transforms.ToTensor())
#加载数据
dataloader = DataLoader(dataset,batch_size=64)
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        #最简单的非线性激活,把数据中负数变为0(图像场景下不明显)
        self.relu1 = ReLU()
        #Sigmoid函数计算,输出值介于0-1之间
        self.sigmoid1 = Sigmoid()

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

my_model = MyModel()

writer = SummaryWriter('./logs_relu')
step = 0
#计算DataLoader中的每一组数据
for data in dataloader:
    imgs,targets = data
    output = my_model(imgs)
    writer.add_images("input",imgs,step)
    writer.add_images("output",output,step)
    step = step + 1

writer.close()

网络模型搭建

PyTorch中的模型

PyTorch中提供了很多以实现的模型有的时候直接使用PyTorch的模型就可完成我们的需求,不需要直接去编写模型,官方文档中包含了完整的实例,例如图像处理模型地址如下:https://pytorch.org/vision/stable/models.html#classification

基于VGG16修改模型

在很多的需求的实现过程都拿vgg16作为前置的模型,在vgg16的基础上进行修改,以下就是基于vgg16模型修改适应CIFAR10数据集

import torchvision.datasets
from torch import nn

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

#获取一个已经训练过的vgg16模型,这会下载一个包
vgg16_true = torchvision.models.vgg16(pretrained=True)
#获取一个没有训练过的vgg16模型
vgg16_false = torchvision.models.vgg16(pretrained=False)
#打印vgg16模型
print(vgg16_true)

#vgg16默认是输出1000个结果,CIFAR10数据集结果只有10类,让vgg16模型适应CIFAR10,操作方式有2种
#1. 在vgg16基础上添加一层线性层
vgg16_true.classifier.add_module("add_linear", nn.Linear(1000, 10))
print(vgg16_true)
#2. 直接修改第六层的逻辑
vgg16_false.classifier[6] = nn.Linear(4096, 10)
print(vgg16_false)

模型的保存与加载

import torch
import torchvision

#获取一个没有训练过的vgg16模型
vgg16 = torchvision.models.vgg16(pretrained=False)
#保存方式1:保存模型结构+参数文件
torch.save(vgg16,"vgg16_method1.pth")
#保存方式2:保存模型的参数(官方推荐)
torch.save(vgg16.state_dict(),"vgg16_method2.pth")

#加载模型结构+参数文件(方式1加载时要有该网络模型的对象才能加载成功)
model = torch.load("vgg16_method1.pth")
print(model)
#加载模型的参数(官方推荐)
dict = torch.load("vgg16_method2.pth")
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(dict)
print(model)

CIFAR10分类模型案例

编写一段网络模型对CIFAR10中的数据集进行分类,最后输入一张图片得到分类,模型的搭建流程图像

在这里插入图片描述

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

from model import *
#定义训练的设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#准备数据集
train_data = torchvision.datasets.CIFAR10(root='./dataset', train=True, download=True,transform=torchvision.transforms.ToTensor())
test_data = torchvision.datasets.CIFAR10(root='./dataset', train=False, download=True,transform=torchvision.transforms.ToTensor())

#获得数据集的长度
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)
test_dataloader = DataLoader(test_data, batch_size=64)

#创建网络模型
my_model = MyModel()
my_model = my_model.to(device)  #使用GPU训练
#损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device) #使用GPU训练
#优化器
learning_rate = 0.001
optimizer = torch.optim.SGD(my_model.parameters(), learning_rate)

#设置训练网络的参数
total_train_step = 0 #训练的次数
total_test_step = 0  #测试的测试
epochs = 10          #训练轮数

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

for i in range(epochs):
    print("--------------------第{}轮训练开始--------------------".format(i+1))
    #训练集数据
    my_model.train()
    for data in train_dataloader:
        imgs,targets = data
        imgs = imgs.to(device) #使用GPU训练
        targets = targets.to(device) #使用GPU训练
        outputs = my_model(imgs)
        #计算损失函数
        loss = loss_fn(outputs, targets)
        #使用优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        #记录训练次数
        total_train_step += 1
        if total_train_step % 100 == 0: #每逢100才打印
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss",loss.item(),total_train_step)
    #测试步骤开始
    my_model.eval()
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs,targets = data
            imgs = imgs.to(device)  # 使用GPU训练
            targets = targets.to(device)  # 使用GPU训练
            outputs = my_model(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss += loss.item()
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy += accuracy.item()
    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 += 1
    #保存每一轮的训练结果
    torch.save(my_model,"./pth/my_model_{}.pth".format(i))
    print("模型已保存")

writer.close()

编写测试程序加载训练好的模型,识别

在这里插入图片描述


http://www.kler.cn/a/556018.html

相关文章:

  • 去中心化协作智能生态系统设计
  • 对学习编程语言的一些理解
  • 如何为自己的 PDF 文件添加密码?在线加密 PDF 文件其实更简单
  • 【弹性计算】虚拟化技术
  • Visual studio 2022 将打开文件的方式由单击改为双击
  • python入门 函数
  • Word文档中插入的图片不能完整显示
  • 传输与接入(无线)问答题及答案-2(25题)
  • 【react18】如何使用useReducer和useContext来实现一个todoList功能
  • 低代码与开发框架的一些整合[2]
  • 清影2.0(AI视频生成)技术浅析(四):计算机视觉(CV)
  • ArcGIS Pro挖填方计算指南:全面解析与实施步骤
  • python 3.6.8支持的Django版本是多少?
  • 2025 新版Android Studio创建Java语言项目
  • Python爬虫实战:从零到一构建数据采集系统
  • pycharm将当前项目上传到github
  • 自己安装一台DeepSeek的服务器
  • MySQL 中慢查询的优化方案
  • 在mfc中使用自定义三维向量类和计算多个三维向量的平均值
  • 基于深度重塑的航拍目标检测增强网络