Little Mound pytorch 연구 노트

  Pytorch 강화 학습을 시작하려면 Pytorch 과정을 찾아보세요. B사이트에서 가장 많이 플레이한 코스는 샤오투두 코스 입니다. 전체적으로 내용이 매우 디테일하다는 느낌이 들지만 기대와는 다릅니다. RL 코스가 아닌 DL 코스이기는 하지만, pytorch 사용 아주 좋습니다. 이 블로그는 전체 학습 과정을 요약합니다.
  참고: 이 노트에 사용된 데이터 세트는 모두 CIFAR10이며 다운로드가 비교적 간단합니다~, 아래부터 시작

데이터 읽기

  읽기 전 데이터 준비가 필요하며, CIFAR10의 경우 오프라인으로 다운로드 가능합니다.(URL: https://download.pytorch.org/tutorial/hymenoptera_data.zip ) 다운로드 후 데이터세트 폴더에 저장하세요. 구조는 다음과 같습니다:
여기에 이미지 설명을 삽입하세요.
  다음은 이미지를 읽는 것입니다. 초기 판독은 PIL을 통해 이루어지며 나중에 dataloader로 대체됩니다. 가장 중요한 것은 클래스를 정의하고 두 개의 매개변수를 전달하는 것입니다. 예는 다음과 같습니다.

  read_data.py

# function:使用PIL完成数据的读取,可查看
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)
        img.show()
        label = self.label_dir
        return img, label

    def __len__(self):
        return len(self.img_path)

root_dir = "dataset/train"
ants_label_dir = "ants"
ants_datasets = MyData(root_dir, ants_label_dir)
ants_datasets.__getitem__(0)   # 输入查看图片编号即可
print(len(ants_datasets))

텐서보드 사용

  Tensorboard는 사진을 보거나 데이터를 분석하는 데 사용할 수 있는 시각화 도구입니다.
  먼저 설치에 대해 이야기해 보겠습니다. 설치 중에 두 가지 오류가 보고되었습니다.

报错:ModuleNotFoundError: No module named 'tensorboard'
解决:pip install tensorboard -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com

报错:ModuleNotFoundError: No module named 'six'
解决:pip install six -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com

  지침:

  1. 기본 템플릿에 따라 프레임워크를 작성합니다.
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter("logs")   # 这个logs是生成日志文件的文件夹名,可随意更换
writer.add_image()	   # 添加一张图像,第一个参数是tag,第二个是数据本身,第三个是编号
wirter.add_images()	# 添加多张图像,第一个是tag,第二个是数据本身,第三个是编号
writer.add_scalar()    # 添加数值 第一个参数是tag, 再后是先y后x, 例如:writer.add_scalar("y=2x", 2*i, i)  
writer.add_graph(tudui, input)   # 查看网络结构,tudui是模型,input是模型输入
writer.close()

  코드를 실행하면 로그 폴더에 이벤트 파일이 생성됩니다.
여기에 이미지 설명을 삽입하세요.

  2. 터미널에서 tensorboard --logdir=logs를 사용합니다.

여기에 이미지 설명을 삽입하세요.

  3. 다음을 보려면 localhost 링크를 클릭하십시오.

여기에 이미지 설명을 삽입하세요.
  네트워크 구조를 볼 수도 있습니다.

  

test_tb.py

# function:展示tensorboard的使用
from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image

writer = SummaryWriter("logs")

# add_image使用
image_path = "dataset/train/ants/5650366_e22b7e1065.jpg"
image_path1 = "dataset/train/ants/6240329_72c01e663e.jpg"
img_PIL = Image.open(image_path)
img_array = np.array(img_PIL)
img_PIL1 = Image.open(image_path1)
img_array1 = np.array(img_PIL1)
writer.add_image("image", img_array, 1, dataformats='HWC')   # 这个通道顺序需要改,tensorboard默认使用的是tensor结构,但这个读的是PIL结构
writer.add_image("image", img_array1, 2, dataformats='HWC')

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

변환 사용

  Transforms는 데이터 유형을 변환하는 데 사용되며, pytorch에서 사용되는 대부분의 데이터 형식은 Tensor입니다. Transfroms는 도구를 직접 제공합니다.

  변환_learn.py

# function:展示transforms的基本使用格式
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
import numpy as np

writer = SummaryWriter("logs")

# python用法 → tensor数据类型
# 通过transform.ToTensor看两个问题
    # 1. transform如何使用
    # 2. 为什么需要Tensor
image_path = "dataset/train/ants/522163566_fec115ca66.jpg"
# PILTensor()
img = Image.open(image_path)
tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)

writer.add_image("image", tensor_img, 1)
writer.close()

  유용한_변형.py

  몇 가지 일반적인 변환이 있습니다. 사용 방법을 기억할 수 있습니다: ToTensor(Tensor 유형으로 변환), Normalize(정규화), Resize(데이터 모양 조정), Compose(여러 변환을 함께 통합), RandomCrop(무작위 자르기) 데이터), 다음과 같이 사용하세요:

# function:展示部分常见transfroms,包括:ToTensor(转换为Tensor类型),Normalize(做正则化),Resize(调整数据shape),Compose(将多个transfroms整合在一起),RandomCrop(随机裁剪数据)
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

writer = SummaryWriter("logs")
img = Image.open("dataset/train/ants/5650366_e22b7e1065.jpg")

# ToTensor
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)

# Normalize
trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)

# Resize
# 输入序列(512, 512)或者数值(512, 会生成方阵)
trans_resize = transforms.Resize((512, 512))
img_resize = trans_resize(img)
img_resize = trans_totensor(img_resize)

# Compose
# PILPIL → tensor
trans_resize_2 = transforms.Resize(512)
trans_compose = transforms.Compose([trans_resize_2, trans_totensor])
img_resize_2 = trans_compose(img)

# RandomCrop——随机裁剪
trans_ramdom = transforms.RandomCrop(128)
trans_compose_2 = transforms.Compose([trans_ramdom, trans_totensor])
for i in range(10):
    img_crop = trans_compose_2(img)
    writer.add_image("RandomCrop", img_crop, i)

writer.add_image("ToTensor", img_tensor, 1)
writer.add_image("Norm", img_norm, 2)
writer.add_image("Resize", img_resize, 3)
writer.add_image("Compose", img_resize_2, 4)
writer.close()

  데이터세트_변형.py

  주로 데이터 추출을 위해 dataLoader를 사용하여 시작하는데, 이미지 데이터가 직접 PIL 형식이기 때문에 데이터로더 중에 변환이 수행되어야 합니다. 데이터 세트는 torchversion:
    torchversion: 기본 데이터 세트인
    torchvision: 데이터 세트를 다운로드할 수 있습니다. 데이터 세트
    torchvision: dataloader를 다운로드합니다. 다운로드할 특정 데이터를 선택
  하고 다음과 같이 사용합니다.

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

# # ====torchvision.datasets使用====
# 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)
#
# writer = SummaryWriter("dataset_transformer")
# for i in range(10):
#     img, target = train_set[i]
#     writer.add_image("test_set", img, i)
# writer.close()

# # ====torchvision.DataLoader使用====
test_data = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor()]))
test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)

img, target = test_data[0]
print(img.shape)
print(target)

step = 0
writer = SummaryWriter("dataloader")
for data in test_loader:
    imgs, targets = data
    writer.add_images("dataloader", imgs, step) # 注意:批量添加的时候使用add_images函数
    step = step + 1
writer.close()

torch.nn은 다음을 사용합니다.

  torch.nn은 신경망(neural network)을 위해 pytorch에서 제공하는 관련 연산 지원입니다.구체적인 내용이 많지만 일반적으로 사용되는 몇 가지만 설명합니다.

  전환 2D

  컨볼루션 작업 구현(구체적으로 컨볼루션이 무엇인지, 동영상에서 자세히 설명)을 위해 여기에 템플릿을 남겨두겠습니다.

  nn_conv2d.py
# torch.nn 的卷积conv2d 实例
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

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

tudui = Tudui()
step = 0
writter = SummaryWriter("logs_conv2d")
for data in dataLoader:
    imgs, targets = data
    output = tudui(imgs)
    writter.add_images("input", imgs, step)
    output = torch.reshape(output, [-1, 3, 30, 30])
    writter.add_images("output", output, step)
    step = step + 1

  nn.module의 기본 사용

  위의 Tudui 클래스는 nn.module을 상속합니다. 실제로 이것은 pytorch 전체의 신경망의 상위 클래스입니다. 간단한 템플릿을 남기고 사용 시 상속만 하면 됩니다.

  nn_module.py
# function:nn.module的基本使用
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)
output = tudui(x)
print(output)

  maxpool.py

    최대 풀링과 컨볼루션의 차이점은
    컨볼루션은 컨볼루션 커널을 사용하여 계산을 수행하고 차원 불변
    컨볼루션은 컨볼루션 커널을 사용하여 최대값을 계산한다는 점입니다. 차원 불변
  최대 풀링은 다음과 같이 구현됩니다.

# function:torch.nn 最大池化maxpool示例
import torch
import torchvision
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

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

input = torch.tensor([[1, 2, 0, 3, 1],
                      [0, 1, 2, 3, 1],
                      [1, 2, 1, 0, 0],
                      [5, 2, 5, 1, 1],
                      [2, 1, 0, 1, 2]
                      ], 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__()
        # ceil_mode为True,保留边框部分()
        # ceil_mode为False,不保留边框部分()
        self.maxpool = MaxPool2d(kernel_size=3, ceil_mode=False)

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

writer = SummaryWriter("log_maxpool")
tudui = Tudui()
output = tudui(input)
step = 0
for data in dataLoader:
    imgs, targets = data
    writer.add_images("intput", imgs, step)
    output = tudui(imgs)
    writer.add_images("output", output, step)
    step = step + 1
writer.close()

  선형.py

  선형화 구현:

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

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

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.Linear = Linear(196608, 10)
    def forward(self, input):
        output = self.Linear(input)
        return output

tudui = Tudui()
for data in dataLoader:
    imgs, targets = data
    print(imgs.shape)
    output = torch.flatten(imgs)
    print(output.shape)
    output = tudui(output)
    print(output.shape)

  손실

  손실(Loss)은 손실 함수입니다. Pytorch는 직접 사용할 수 있는 몇 가지 기능을 제공합니다. 여기에 예를 들어 보겠습니다.

  nn_loss.py
# function:损失函数使用示例
import torch
from torch.nn import L1Loss
from torch import nn

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

# L1直接损失
loss = L1Loss()
result = loss(inputs, targets)

# 均方差损失
loss_mse = nn.MSELoss()
result_mes = loss_mse(inputs, targets)

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

  최적의

  최적화 프로그램 사용을 위한 템플릿이 있습니다:

        optim.zero_grad()        # 1.设置梯度为0
        result_loss.backward()   # 2.计算梯度,进行反向传播
        optim.step()             # 3.进行梯度更新,调整权重参数(降低loss)

  예는 다음과 같습니다:

  nn_optimal.py
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, Linear, Sequential
from torch.nn import MaxPool2d
from torch.nn import Flatten
from torch.utils.data import DataLoader, dataloader
from nn_loss import loss

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model = 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, input):
        x = self.model(input)
        return x

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

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()        # 1.设置梯度为0
        result_loss.backward()   # 2.计算梯度,进行反向传播
        optim.step()             # 3.进行梯度更新,调整权重参数(降低loss)
        running_loss = running_loss + result_loss
    print(running_loss)

  relu.py

  비선형성(선형성이 좋지 않음)을 도입합니다. 예는 다음과 같습니다.

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

input = torch.tensor([[1, 0.5],
                      [-1, 3]])
input = torch.reshape(input, (-1, 1, 2, 2))
print(input)

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

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.relu = ReLU()
    def forward(self, input):
        output = self.relu(input)
        return output
writer = SummaryWriter("logs_relu")
tudui = Tudui()
output = tudui(input)
step = 0
for data in dataLoader:
    imgs, targets = data
    writer.add_images("input", imgs, step)
    output = tudui(imgs)
    writer.add_images("output", output, step)
    step = step + 1
writer.close()

print(output)

  순차.py

  전통적인 방식으로 모델을 작성하려면 앞으로 구조를 한 겹씩 작성해야 합니다. Sequential은 모델에서 직접 정의할 수 있으며 예는 다음과 같습니다.

## 传统方式:自己写模型
# import torch
# from torch import nn
# from torch.nn import Conv2d, Linear, Sequential
# from torch.nn import MaxPool2d
# from torch.nn import Flatten
#
# 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, input):
#         x = self.conv1(input)
#         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()
# input = torch.ones((64, 3, 32, 32))
# output = tudui(input)
# print(output.shape)

## 使用Sequential写模型
import torch
from torch import nn
from torch.nn import Conv2d, Linear, Sequential
from torch.nn import MaxPool2d
from torch.nn import Flatten
from torch.utils.tensorboard import SummaryWriter


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model = 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, input):
        x = self.model(input)
        return x

writer = SummaryWriter("logs_sequential")
tudui = Tudui()
input = torch.ones((64, 3, 32, 32))
output = tudui(input)
writer.add_graph(tudui, input)
writer.close()
print(output.shape)

전체 모델 훈련

  train_cpu.py

  예는 다음과 같습니다:

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

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


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

# 搭建神经网络
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(),
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10))
    def forward(self, input):
        x = self.model(input)
        return x

### 测试模型正确性
# if __name__ == '__main__':
#     tudui = Tudui()
#     input = torch.ones((64, 3, 32, 32))
#     output = tudui(input)
#     print(output.shape)

# 创建网络模型
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
writter = SummaryWriter("logs_train")

total_test_step = 0
for i in range(10):
    print("-----第{}轮训练开始----".format(i+1))
    # 训练步骤开始
    tudui.train()   #特定层:Dropout
    for data in train_dataloader:
        # 1. 数据导入
        imgs, targets = data
        # 2. 模型导入
        outputs = tudui(imgs)
        # 3. loss计算
        loss = loss_fn(outputs, targets)
        # 4. 优化器优化模型
        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()))  #loss.item()相当于取值
            writter.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))
    writter.add_scalar("test_loss", loss.item(), total_test_step)
    writter.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("模型已保存!")
writter.close()

  train_gpu.py

  예는 다음과 같습니다:

# 与CPU的区别:在网络模型、数据、损失函数上增加cuda()

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

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


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

# 搭建神经网络
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(),
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10))
    def forward(self, input):
        x = self.model(input)
        return x

### 测试模型正确性
# if __name__ == '__main__':
#     tudui = Tudui()
#     input = torch.ones((64, 3, 32, 32))
#     output = tudui(input)
#     print(output.shape)

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

# 损失函数
loss_fn = nn.CrossEntropyLoss()
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
writter = SummaryWriter("logs_train")

total_test_step = 0
for i in range(10):
    print("-----第{}轮训练开始----".format(i+1))
    # 训练步骤开始
    tudui.train()   #特定层:Dropout
    for data in train_dataloader:
        # 1. 数据导入
        imgs, targets = data
        imgs = imgs.cuda()
        targets = targets.cuda()
        # 2. 模型导入
        outputs = tudui(imgs)
        # 3. loss计算
        loss = loss_fn(outputs, targets)
        # 4. 优化器优化模型
        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()))  #loss.item()相当于取值
            writter.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.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))
    writter.add_scalar("test_loss", loss.item(), total_test_step)
    writter.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("模型已保存!")
writter.close()

모델 저장

  model_save.py

  예는 다음과 같습니다:

# function:训练模型的保存
import torch
import torchvision

vgg16 = torchvision.models.vgg16(pretrained=False)

# 保存方式1
torch.save(vgg16, "vgg16_method1.pth")

# 保存方式2(官方推荐)
torch.save(vgg16.state_dict(), "vgg16_method2.pth")

모델 로딩

  모델_로더

  예는 다음과 같습니다:

# function:现有模型加载

import torch
import torchvision

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

vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
# model = torch.load("vgg16_method2.pth")  # 直接是字典权重
print(model)

모델 사용법

  model_use.py

  예는 다음과 같습니다:

# function:自找图片,验证train.py训练的模型准确性
import torch
import  torchvision
from PIL import Image
from torch import nn

image_path = "dog.png"
image = Image.open(image_path)

transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)), torchvision.transforms.ToTensor()])

image = transform(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(),
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10))
    def forward(self, input):
        x = self.model(input)
        return x

model = torch.load("tudui_9.pth")
image = torch.reshape(image, (1, 3, 32, 32))
image = image.cuda()
model.eval()
with torch.no_grad():
    output = model(image)
print(output.argmax(1))

사전 모델 사용

  premodel_use.py

  예는 다음과 같습니다:

# function:使用现有网络对现有数据集进行训练
import torchvision
from torch import nn

vgg16_false = torchvision.models.vgg16(pretrained=False)
vgg16_true = torchvision.models.vgg16(pretrained=True)
print(vgg16_true)

train_data = torchvision.datasets.CIFAR10("./dataset", train=True, download=True, transform=torchvision.transforms.ToTensor())
# CIFAR10最终的输出结果是10类,所以必须按照原来的增加一层
vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))
print(vgg16_true)

# CIFAR10最终的输出结果是10类,也可以在原来基础上做改动
vgg16_false.classifier[6] = nn.Linear(4096, 10)
print(vgg16_false)

  위는 pytorch의 기본에 대한 간략한 이해입니다. 학습은 계속 진행 중입니다. 계속해서 좋은 작업을 하세요~

추천

출처blog.csdn.net/gls_nuaa/article/details/132889816