pytorch learning

2023-11-30

1. install

请看https://wsxk.github.io/AI_env/

2. dir/help

dir用于查看一个库中有哪些组件,help用于查看组件的具体用法

import torch
if __name__ == '__main__':
    print(dir(torch))
    print((dir(torch.cuda)))
    print(help((torch.cuda.is_available)))

当然,官方文档是最好的老师https://pytorch.org/docs/stable/nn.html

3. pytorch教程

3.1 torch.utils.tensorboard

tensorboard主要是画图用的

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

writer = SummaryWriter("logs")
image_path = "DataSet/hymenoptera_data/train/ants/0013035.jpg"
image_pil = Image.open(image_path)
image_array = np.array(image_pil)
writer.add_image("picture",image_array,1,dataformats="HWC") # tag y轴 x轴 通道(height width channel)

# for i in range(100):
#     writer.add_scalar("y=2x",2*i,i)  # y=2x曲线 y轴 x轴
writer.close()

运行完后在terminal执行tensorboard --logdir=logs --port=6007 即可在浏览器中查看,--logdir是你存放的结果的目录,即SummaryWriter填入的目录

3.2 torchvision.transforms

transforms主要是对图片进行处理,即把图片转换成tensor(张量)

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

if __name__ == "__main__":
    img_path = "DataSet/hymenoptera_data/train/ants/0013035.jpg"
    img = Image.open(img_path)
    writer = SummaryWriter("logs")

    # tensor
    tensor_trans = transforms.ToTensor()
    img_tensor = tensor_trans(img)
    writer.add_image("test", img_tensor, 0)

    # normalize (input-mean)/standard
    tensor_normal = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
    img_normal = tensor_normal.forward(img_tensor)
    writer.add_image("test", img_normal, 1)

    # Resize 改变图片大小
    tensor_resize = transforms.Resize((512, 512))
    img_resize = tensor_resize(img)
    img_resize = tensor_trans(img_resize)
    writer.add_image("test", img_resize, 2)

    # Compose 组合,流水线步骤
    tensor_compose = transforms.Compose([tensor_resize, tensor_trans, tensor_normal])
    img_compose = tensor_compose(img)
    writer.add_image("test", img_compose, 3)

    # RandomCrop: 随机裁剪
    tensor_crop = transforms.RandomCrop((100, 100))
    tensor_compose2 = transforms.Compose([tensor_trans, tensor_crop])
    for i in range(10):
        img_crop = tensor_compose2(img)
        writer.add_image("Crop", img_crop, i)

    writer.close()

3.3 torchvision.datasets

datasets主要是用于加载数据集,并且其自集成了一些数据集,下载时,你需要转换成美国服务器(目前试过cn服务器与jp服务器,没成功下载)

from torchvision.datasets import CIFAR10
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter(log_dir="logs")
dataset_transform = transforms.Compose([transforms.ToTensor()])
train_set = CIFAR10(root="./torchvision_dataset", train=True, transform=dataset_transform, download=True)
test_set = CIFAR10(root="./torchvision_dataset", train=False, transform=dataset_transform, download=True)

# print(train_set)
# print(train_set[0])
# train, target = train_set[0]
# print(train)
# print(train_set.classes[target])
# train.show()

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

3.4 torch.utils.data.DataLoader

DataLoader主要是用于加载数据集,其可以自动分批次,shuffle等

from torchvision.datasets import CIFAR10
from torchvision import transforms
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

transformers = transforms.Compose([transforms.ToTensor()])
test_dataset = CIFAR10("torchvision_dataset", train=False, transform=transformers, download=False)
# 数据集,每次取64个数据,取完数据后重新清洗数据集中的数据,只有一个线程,不舍弃最后几张数据
test_dataloader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
writer = SummaryWriter(log_dir="logs")

# img, target = test_dataset[0]
# print(img.shape)
# print(target)
step = 0
for epoch in range(2):
    step = 0
    for i in test_dataloader:
        imgs, targets = i
        writer.add_images("test {}".format(epoch), imgs, step)
        step += 1
writer.close()

3.5 torch.nn

nn主要是用于搭建神经网络,它相当于一个基本骨架,下面给一个简单的例子

from torch import nn
import torch

# 这是一个简单的神经网络
class Wsxk(nn.Module):
    def __init__(self):
        super().__init__()

    # 前向传播,即输入一个数据,输出一个数据
    def forward(self, input):
        output = input+1
        return output

wsxk = Wsxk()
x = torch.tensor(1.0)
output = wsxk(x)
print(output)

3.5.1 torch.nn.functional

torch.nn.functional是torch.nn中其他模块的底层

import torch
import torch.nn.functional as F
# 输入 5*5 的二维矩阵
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]])

# 变形,因为卷积时,需要有 batch_size , channel , height , width 四个维度
input = torch.reshape(input, [1, 1, 5, 5])
kernel = torch.reshape(kernel, [1, 1, 3, 3])

print(input)
print(kernel)

# bias是开始时的偏移,stride是步数,padding是填充的数,即5*5 -》 (5+padding)*(5+padding)
output = F.conv2d(input, kernel, bias=None, stride=1, padding=0)
print(output)

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

3.5.2 卷积层的使用

直接上代码,卷积层其实是取一个矩阵,从目标矩阵中提取数据的过程,本质上是提取重要特征

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

transformer = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
dataset = torchvision.datasets.CIFAR10(root="torchvision_dataset", train=False, transform=transformer, download=False)
data_loader = DataLoader(dataset=dataset, batch_size=64, shuffle=False, num_workers=0, drop_last=False)
writer = SummaryWriter(log_dir="logs")


class Wsxk(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = torch.nn.Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)

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


test = Wsxk()
step = 0
for data in data_loader:
    imgs, targets = data
    print(imgs.shape)
    print(targets.shape)
    output_imgs = test(imgs)
    print(output_imgs.shape)
    writer.add_images("input", imgs, step)
    # 因为输出是6个通道, tensorboard只能画出3通道的,所以需要对输出进行变形,比如 64个batch * 6通道 = 128个batch * 3通道
    output_imgs = torch.reshape(output_imgs, [-1, 3, 30, 30])
    writer.add_images("output", output_imgs, step)
    step += 1

3.5.3 池化层的使用

直接上代码,池化层的作用是减少数据量,以最大池化为例,它只会取矩阵中最大的值

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

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

transformer = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
dataset = torchvision.datasets.CIFAR10(root="torchvision_dataset", train=False, transform=transformer, download=False)
dataloader = DataLoader(dataset=dataset, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
writer = SummaryWriter(log_dir="logs")


class Wsxk(torch.nn.Module):
    def __init__(self):
        super().__init__()
        # ceil_mode=True 时,输出大小为 ceil(input_size/stride),即向上取整
        self.max_pool = torch.nn.MaxPool2d(kernel_size=3, ceil_mode= True)

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


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

3.5.4 非线性激活的使用

非线性激活的作用是,让神经网络加入非线性成分,拟合非线性的数据,比如sigmoid函数,tanh函数,relu函数等,其能增加模型的泛化能力

3.5.4.1 Relu

relu其实是取max(0,x),即取0和x中的最大值

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

transformer = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
dataset = torchvision.datasets.CIFAR10(root="torchvision_dataset", train=False, transform=transformer, download=False)
dataloader = DataLoader(dataset=dataset, batch_size=64, shuffle=False, num_workers=0, drop_last=False)
writer = SummaryWriter(log_dir="logs")


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

    def forward(self, x):
        y = self.relu1(x)
        return y


wsxk = Wsxk()
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images("origin", imgs, step)
    output = wsxk(imgs)
    writer.add_images("relu", output, step)
    step += 1
3.5.4.2 sigmoid
import torch
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
import torchvision

transformer = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
dataset = torchvision.datasets.CIFAR10(root="torchvision_dataset", train=False, transform=transformer, download=False)
dataloader = DataLoader(dataset=dataset, batch_size=64, shuffle=False, num_workers=0, drop_last=False)
writer = SummaryWriter(log_dir="logs")


class Wsxk(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.relu1 = torch.nn.ReLU(inplace=False)
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        y = self.sigmoid(x)
        return y


wsxk = Wsxk()
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images("origin_1", imgs, step)
    output = wsxk(imgs)
    writer.add_images("sigmoid_1", output, step)
    step += 1

3.5.5 线性层的使用

线性层的作用是,将输入的数据进行线性变换,即 y = wx + b

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

transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
dataset = torchvision.datasets.CIFAR10(root="torchvision_dataset", train=False, transform=transform, download=False)
dataloader = DataLoader(dataset, batch_size=64, shuffle=False, num_workers=0, drop_last=True)
writer = SummaryWriter(log_dir="logs")


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

    def forward(self, x):
        y = self.linear1(x)
        return y


wsxk = Wsxk()
for data in dataloader:
    imgs, targets = data
    # output = torch.reshape(imgs, [1, 1, 1, -1])
    output = torch.flatten(imgs)
    print(output.shape)
    output = wsxk(output)
    print(output.shape)

3.5.6 torch.nn.Sequential

torch.nn.Sequential就是把所有的层都放在一个列表中,然后按顺序执行,这样就不用一个一个写了

import torch
from torch.utils.tensorboard import SummaryWriter

class Wsxk(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = torch.nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2, dilation=1)
        self.maxpool1 = torch.nn.MaxPool2d(kernel_size=2)
        self.conv2 = torch.nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2, dilation=1)
        self.maxpool2 = torch.nn.MaxPool2d(kernel_size=2)
        self.conv3 = torch.nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2, dilation=1)
        self.maxpool3 = torch.nn.MaxPool2d(kernel_size=2)
        self.flattern = torch.nn.Flatten()
        self.linear1 = torch.nn.Linear(in_features=1024, out_features=64)
        self.linear2 = torch.nn.Linear(in_features=64, out_features=10)
        self.model1 = torch.nn.Sequential(torch.nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2, dilation=1),
                                          torch.nn.MaxPool2d(kernel_size=2),
                                          torch.nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2, dilation=1),
                                          torch.nn.MaxPool2d(kernel_size=2),
                                          torch.nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2, dilation=1),
                                          torch.nn.MaxPool2d(kernel_size=2),
                                          torch.nn.Flatten(),
                                          torch.nn.Linear(in_features=1024, out_features=64),
                                          torch.nn.Linear(in_features=64, out_features=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.flattern(x)
        # x = self.linear1(x)
        # x = self.linear2(x)
        x = self.model1(x)
        return x


writer = SummaryWriter(log_dir="logs")
wsxk = Wsxk()
print(wsxk)
input = torch.ones([64, 3, 32, 32])
output = wsxk(input)
print(output.shape)
writer.add_graph(wsxk, input)
writer.close()

4. 总结

到这里,pytorch的基本用法就已经结束了,fly bitch!