PyTorch入门

首先要安装好Anaconda(以前就已经安装好,所以在这里不多加赘述)

有序的管理环境

在很多项目中,需要使用不用版本的环境,比如这个项目需要使用pytorch0.4,另一个项目需要用到pytorch1.0,如果卸载了0.4版本,转而安装了1.0版本。那么下一次再需要用到0.4版本,就还得卸载1.0版本。而Anaconda集成的conda包就能够解决这个问题,它可以创造出两个屋子,相互隔离,一个屋子放0.4版本,另一个屋子放1.0版本,需要使用哪个屋子,就进哪个屋子工作。

首先使用conda指令创建一个屋子,叫做pytorch,指令如下:

conda create -n pytorch python=3.9

conda是指使用conda包,create是创建的意思,-n是指后面的名字是屋子的名字,pytorch是屋子的名字(可以更改成自己喜欢的),python=3.9是指创建的屋子是python3.9版本的。

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_libtorch和pytorch版本

01.安装PyTorch

(1)进入官网https://pytorch.org/并在首页向下找到如下页面进行选择

  • 第一行推荐选择稳定版本
  • 第二行根据系统性进行选择
  • 第三行windows系统选择conda并且要有anaconda,linux系统选择pip
  • 第四行根据自己情况选择,我使用的是python3.9版本
  • 第五行要先知道自己是GPU还是集显或者没有显卡,我这里是3060所以选择第一个,如果是集显或者没有显卡,要选择cpu
  • 前面五行选择的结果给出第六行的安装指令,将其复制

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_python_02

(2)打开anaconda的命令提示行前面已经创建了pytorch的环境,在此处输入conda activate pytorch再把上面的第六行的命令粘贴进来,这里11.6版本安装失败,我又改成了11.7版本

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_libtorch和pytorch版本_03

(3)检验版本是否安装成功,先输入python之后再输入import torch,如果没有报错则证明,已经安装成功

(4)下载好pytorch之后,在pycharm官网下载ppycharm编译器并导入pytorch环境,在python console中输入import torch若什么都不显示再输入torch.cuda.is_available()若显示True则环境配置成功

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_卷积_04

(5)在pytorch环境中安装jupyter

先在anaconda的小黑框里面输入conda activate pytorch,之后再安装一个包输入conda install nb_conda,python3.9版本的使用conda install nb_conda_kernels命令符。安装完成之后输入jupyter notebook,后打开网页版的jupyter

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_神经网络_05

再输入import torch,按住shift+enter则跳转到下一个代码块,运行了代码块前面会有数字,再输入torch.cuda.is_available()

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_神经网络_06

在运行jupyter的时候不要关闭anaconda的小黑框,否则会断开链接

02.python学习中的两大法宝函数

dir( ):打开看见内部有什么

help( ):说明书

比如要打开pytorch工具箱里面有什么就是:

  • dir(pytorch)==>会输出函数1、函数2、函数3、函数4
  • 继续探索函数里面有什么就是dir(pytorch.函数3)==>会输出a、b、c
  • 之后想要查看道具如何使用则可以使用help(pytorch.函数3.a)==>会输出想要查看的内容的使用方法

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_python_07

03.pytorch加载数据

pytorch里面涉及到如何读取数据一般涉及到两个类DatasetDataloader

假设数据是一堆垃圾,我们需要在其中提取到有用的数据,也就是加入我们需要的都是可回收垃圾这一类,我们就需要把可回收垃圾这一大类别全都提取出来。其中在对数据处理的过程中:

Dataset是提供一种方式去获取数据及其label

  • 如何获取每一个数据及其label
  • 告诉我们总共有多少数据

Dataloader是为后面的网络提供不同的数据格式

03.Transforms的用法

tensor的数据类型

通过transforms.ToTensor去看两个问题

  • transforms该如何使用(python)
  • Tensor数据类型相较于普通的数据类型有什么区别,为什么需要使用Tensor的数据类型

官方给出的Transforms的源代码中,关于ToTensor的函数解释是,将一个PIL或者numpy类型的图片转化成Tensor类型的函数

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_深度学习_08

transforms该如何使用(python)

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_神经网络_09

可以简单理解为,transforms是一个工具箱,我们根据这个工具箱打造一个属于自己的工具(类的实例化),再用这个自己的工具来把输入的图片进行加工,之后再得出我们想要的结果

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_神经网络_10

常见的Transforms

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_神经网络_11

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

writer = SummaryWriter("../logs")

img_path = "../data/images/ali.jpg"
img = Image.open(img_path)
print(img)

# ToTensor的使用
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("ToTensor",img_tensor)



# Normalize的使用
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([1,1.5,2],[5,5,3])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalsize",img_norm,1)


# Resize的使用
print(img.size)
trans_resize = transforms.Resize((512,512))
img_resize = trans_resize(img)
print(img_resize )
img_resize_totensor = trans_totensor(img_resize)
writer.add_image("ReSize",img_resize_totensor,0)


# Compose--resize的用法
# 不改变长和宽的大小关系,进行等比缩放
trans_resize_2 = transforms.Resize(512)
# transforms.Compose的两个参数,第一个是改变图片的大小,第二个是转换图片类型为tensor类型
# 如果调换位置,也就是先转换成tensor类型之后再传入resize会发现参数类型不匹配,resize需要传入img类型,所以前一个函数的和第二个函数数之间的参数传递需要对应
trans_compose = transforms.Compose([trans_resize_2,trans_totensor])
img_resize_2 = trans_compose(img)
writer.add_image("ReSize",img_resize_2,1)


# RandomCrop
trans_random = transforms.RandomCrop(512)
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()

04.torchvision中数据集的使用

在pytorch的官网上https://pytorch.org/的Docs有torchvision的介绍,介绍了关于pytorch提供的数据集的API文档,新版的pytorch在左上角的Search Docs选择0.9.0版本即可

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_卷积_12

我们选择CIFAR的数据集进行试验,其中有50000张训练图片和10000张测试图片,常见的dataset的使用如下

import torchvision

train_set = torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True)
test_set = torchvision.datasets.CIFAR10(root="./dataset",train=False,download=True)


print(test_set[0])
print(test_set.classes)

img,target = test_set[0]
print(img)
print(target)
print(test_set.classes[target])
img.show()

如果要进行pytorch进行使用,则应该用transforms进行转化成tensor数据类型

import torchvision
from torch.utils.tensorboard import SummaryWriter

dataset_transform = torchvision.transforms.Compose([
#     先进行数据类型的转化
    torchvision.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])

# 之后可以再用tensorboard进行一下显示
writer = SummaryWriter("p10")
for i in range(10):
    img,target = test_set[i]
    writer.add_image("dataset",img,i)

writer.close()

之后再打开下方的Ter'minal输入tensorboard --logdir="p10(此文件夹的相对路径)"

05.DataLoader的使用

前面用到的dataset可以理解为作用是告诉程序,我们所用到的数据集是在什么位置,dataloader可以理解为一个加载器,可以把数据加载到神经网络当中,dataloader每次是从dataset之中取数据,每次取多少数据和每次怎么取数据决定权再dataloader的参数之中——

在官网中找到关于dataloader的使用方法,其中参数,batch_size表示的是要抓取的数据大小。shuffle表示两次抓取过程中数据的顺序是否有被打乱,如果是true就是两次顺序不一样,如果是false就是两次没被打乱。num_workers 表示加载数据时使用的是单进程还是多进程进行加载,默认情况是0,0表示采用主进程进行加载(num_worker再windows上使用大于0时总是会出错,要注意!!)drop_last表示当取数据取不尽时,剩下的数据是舍去还是继续取走

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())

test_loader = DataLoader(dataset=test_data,batch_size=64,shuffle=True,num_workers=0,drop_last=False)

# 测试数据集中的第一张图片级target
img,target = test_data[0]
print(img.shape)
print(target)

writer = SummaryWriter("dataloader")
step = 0
for data in test_loader:
    imgs,targets = data
    # print(imgs.shape)
    # print(targets)
    # 由于是多个图片,所以使用的是add_images而不是image
    writer.add_images("dataloader_data",imgs,step)
    step += 1

writer.close()

生成文件用tensorboard打开时可能会出错

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_python_13

此时问题可能是端口被占用导致的,将默认的6006端口改成8008或者其他端口即可

tensorboard --logdir=learn/dataloader --host=127.0.0.1 --port=8008

06.神经网络的基本骨架-nn.Module的使用

在pytorch的官网给出的Docs找到torch.nn的文档,其中containers直译是容器,在这里是给神经网络定义了一些骨架和结构,只需要往这些结构之中添加一些不同的内容,就可以组成神经网络。后面的一些就是往这个骨架中填充的一些东西,convolution layers(卷积层),pooling layers(池化层),Non-linear Activations (weighted sum, nonlinearity)(非线性激活),Normalization Layers(智能化层)等等,这些共同组成神经网络中的核心操作部分

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_深度学习_14

在containers中一共有六个模块,其中Module模块是我们最常用的模块,它用来给所有的神经网络提供一个基本的骨架。我们搭建的神经网络,都必须从这个类之中进行继承

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_卷积_15

import torch
from torch import nn


class Nn_module(nn.module):
    def __int__(self):
        super().__init__()


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


nn_module = Nn_module()
x = torch.tensor(1.0)
output = nn_module(x)
print(output)

07.卷积操作

在pytorch官网的Docs中,torch.nn的convolution layers(卷积层)中一些很重要的内容,其中最重要的是nn.Conv1d和nn.Conv2d,分别表示一维和二维。对于卷积的原理,参考另一篇笔记

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_libtorch和pytorch版本_16

神经网络需要设置的参数介绍。其中需要输入的函数input需要四个参数,普通的矩阵的shape只有两个参数,此时就需要pytorch给提供的一个尺寸变换函数,reshape

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_python_17

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_神经网络_18

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]])

# 尺寸只有矩阵的高和宽,但是输入到神经网络中的要求是尺寸需要有四个参数
# 采用reshape函数进行改变尺寸
input = torch.reshape(input,(1 ,1 ,5 ,5))
kernel = torch.reshape(kernel,(1,1,3,3))
print(input.shape)
print(kernel.shape)

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

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

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

当参数中stride是1的时候移动的时候就会移动一个步径,所以输出的是3*3的矩阵,如果stride是2的时候,那么输出的矩阵就会是一个2*2的矩阵

还有一个重要的参数是padding,它可以决定是否可以在矩阵的周边进行填充,填充的内容可以进行设置

08.神经网络-卷积层

conv2d参数介绍

  • in_channels:输入图片的通道数,一般彩色图片的通道数是3个
  • out_channels:通过卷积之后产生的输出通道数是多少
  • kernel_size:可以是个数,也可以是元组,表示卷积核的一个大小
  • stride:表示卷积核在卷积过程中横向和纵向的步幅的大小
  • padding:表示在卷积过程中,是否需要在卷积图像的边缘进行填充
  • padding_mode:控制padding以一个什么样的方式进行填充,一般是zeros,把填充的内容都设为0
  • dilation:定义在卷积过程中核之间的距离
  • groups:一般设置成1
  • bias:一般设置为true,设置一个偏置

https://github.com/vdumoulin/conv_arithmetic/blob/master/README.md为不同参数设置的图像演示

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_python_19

out_channels是2的时候,可能会有两个不同的卷积核对一个in_channels是1的图像进行卷积,能得到两个输出,这样out_channels的值就是2

libtorch和pytorch版本 pytorch0.4和pytorch1.0的区别_神经网络_20

对图像进行卷积并显示在tensorboard上面

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

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

dataloader = DataLoader(dataset,batch_size=64)

class Nnmodule(nn.Module):
    def __init__(self):
        super(Nnmodule, 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


nnmodule = Nnmodule()
print(nnmodule)

writer = SummaryWriter("conv2d")

step = 0
for data in dataloader:
    imgs,targets = data
    output = nnmodule(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])
    # add_images不能显示6个out_channels的图片,所以可以用reshape改变一下
    # 第一个参数不知道是多少的时候,先写-1,这样会根据后面参数再进行计算
    output = torch.reshape(output,(-1,3,30,30))
    writer.add_images("output",output,step)
    step += 1

writer.close()

经典模型vgg16