[基本功]pytorch基本操作教程

文章目录

  • 数据加载
    • Dataset
    • Dataloader
  • 可视化——TensorBoard
  • Transform
    • ToTensor
    • Nomalize
    • Resize
    • RandomCrop
  • torch.nn:神经网络的基本架构
    • Module:所有神经网络的基本类
    • Convolution Layers
    • Pooling Layers
    • 非线性激活
    • 正则化层
    • Recurrent Layers
    • Transformer Layers
    • Linear Layers
    • Dropout Layers
    • Sparse Layers
    • Distance Functions
    • Loss Functions
  • torch.nn.Sequential
  • 搭建实战
  • 损失函数
  • 反向传播
  • 优化器torch.optim
  • 现有网络模型的修改与使用
  • 模型的保存与读取
  • 完整的模型训练套路
  • 使用GPU训练
  • 完整的模型使用套路

数据加载

  • Dataset:提供一种方式去获取数据及其label
  • 如何获取每一个数据及其label
  • 告诉我们总共有多少数据
  • Dataloader:为后面的网络提供不同的数据形式

Dataset

简介:所有数据集都应该继承Dataset,所有子类都应该重写__getitem__(对每个数据获取label),可以重写_len_(获取数据长度)

举例1:

输入:蚂蚁的照片;label:ants

(蚂蚁的照片放在名为ants的文件夹中)

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

img,label = ants_dataset[0]
img.show()

举例2:

有文件夹ants_image和ants_label,ants_image存储蚂蚁的图片,ants_label存储蚂蚁的标签(和图片同样个数的txt文件,文件名为图片名,文件内容为标签)。当标签复杂时常用这种方式。

Dataloader

from torch.utils.data import DataLoader
from torch.utils,tensorboard import SummaryWriter
import torchvision
"""
dataset:要加载的数据集
batch_size:每次取多少
shuffle:True表示每次将数据集打乱
sampler
batch_sampler
num_workers:采用多进程进行加载
drop_last:采样除不尽是否舍去最后余下的样本
"""

test_data = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor()) #自带数据集

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

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

writer = SummaryWriter("logs")

for epoch in range(2):
    step = 0
    for data in data_loader:
        imgs,target = data
        writer.add_image("Epoch:{}".format(epoch),imgs,step)
        step += 1
    
writer.close()

可视化——TensorBoard

举例:绘制 y=x 的图像

from torch.utils.tensorboard import SummaryWriter #直接向log_dir写入文件,可被TensorBoard解析

writer = SummaryWriter("logs") #将对应的事件文件存储到logs文件夹中

# writer.add_image(tag标题,img_tensor图片[torch.Tensor/numpy.array/string],global_step) 添加图片
# writer.add_scaler(tag标题,scaler_value储存的数值y,global_step记录的步x) 添加标量

# y = x
for i in range(100):
    writer.add_scaler("y=x",i,i)

writer.close()
#————————————以上已经建立好事件文件,下面是如何打开————————————————

#在Terminal中输入 tensorboard --logdir=logs --port=6007,点击端口网址即可从浏览器打开图片
#port指定端口,可不指定

举例:绘制图片

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

writer = SummaryWriter("logs")

image_path = "dataset/train/ants/0013035.jpg"
img_PIL = Image.open(image_path)
img_array = np.array(img_PIL)

writer.add_image("test",img_array,1,dataformats='HWC')

writer.close()

Transform

常用类:

ToTensor:转换成tensor数据类型

Compose:中心裁剪并返回tensor数据类型

ToPILImage:把tensor或ndarray转换成PIL Image

Nomalize:输入tensor图片,均值,标准差,将其标准化

Resize:把PIL Image转换成给定尺寸,如果只有一个参数则match小的那条边进行等比缩放

RandomCrop:随机裁剪

ToTensor

from torchvision import transforms # ToTensor,resize等,对图片进行变换
from torch.utils.tensorboard import SummaryWriter

image_path = "dataset/train/ants/0013035.jpg"
img = Image.open(img_path)

writer = SummaryWriter("logs")

tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)

writer.add_image("Tensor_img",tensor_img)

writer.close()

Nomalize

trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5]) #三个通道,均值标准差都为0.5
# (input - 0.5) / 0.5 = 2 * input - 1
# input [0,1]
# result [-1,1]
img_norm = trans_norm(img_tensor)

Resize

trans_resize = transforms.Resize((512,512))
img_resize = trans_resize(img)

#Compose+resize
trans_resize_2 = transforms.Resize(512)
#Compose参数为列表,元素为transforms类型
trans_compose = transforms.Compose([trans_resize_2,trans_totensor])
img_resize_2 = trans_compose(img)

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)

torch.nn:神经网络的基本架构

Containers:容器,骨架

Convolution Layers:卷积层

Pooling Layers:池化层

Padding Layers

Non-linear Activations:非线性激活

Normalization Layers:正则化层

Module:所有神经网络的基本类

举例1:

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        self.conv1 = nn.Conv2d(1,20,5)
        self.conv2 = nn.Conv2d(20,20,5)
        
    def forward(self,x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))

举例2:

from torch import nn
import torch

class test(nn.Module):
    def __init__(self):
        super(test,self).__init__()
        
    def forward(self,input):
        output = input + 1
        return output
    
test_model = test()
x = torch.tensor(1.0)
output = test_model(x)

Convolution Layers

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)) #(batch_size,通道数,数据维度)
kernel = torch.reshape(kernel,(1,1,3,3))

output = F.conv2d(input,kernel,stride=1) #stride:步长;padding:在输入数据的周围进行补零填充
print(output)

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("../data",train=False,transform=torchvision.transforms.ToTensor(),
                                      download=True)
dataloader = DataLoader(dataset,batch_size=64)

class mymodule(nn.Module):
    def __init__(self):
        super(mymodule,self).__init__()
        self.conv1 = Conv2d(3,6,3,stride=1,padding=0) #输入3通道,输出6层,3*3的核
        
    def forward(self,x):
        x = self.conv1(x)
        return x
    
mymo = mymodule()

writer = SummaryWriter("../logs")
step = 0
for data in dataloader:
    imgs,targets = data
    output = mymo(imgs)
    #print(output.shape)
    writer.add_images("input",imgs,step)
    output = torch.reshape(output,(-1,3,30,30))
    writer.add_images("output",output,step)
    
    step += 1

Pooling Layers

torch.nn.MaxPool2d:

(默认步长为kernel_size)

(ceil_mode为True表示不足核大小时仍取;否则不取)

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

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

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

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

dataloader = DataLoader(dataset,batch_size=64)
writer = SummaryWriter("../logs_maxpool")
step = 0
for imgs,targets in dataloader:
    writer.add_images("input",imgs,step)
    output = mymo(imgs)
    writer.add_images("output",output,step)
    step += 1
    
writer.close()

非线性激活

torch.nn.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))

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

torch.nn.sigmoid:

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

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

class mymodule(nn.Module):
    def __init__(self):
        super(mymodule,self).__init__()
        self.relu1 = ReLU()
        self.sigmoid1 = Sigmoid()
        
    def forward(self,input):
        output = self.sigmoid1(input)
        return output
    
mymo = mymodule()
writer = SummaryWriter("../logs_relu")
step = 0
for imgs,targets in dataloader:
    writer.add_images("input",imgs,global_step=step)
    output = mymo(imgs)
    writer.add_images("output",output,step)
    step += 1
    
writer.close()

正则化层

torch.nn.BatchNorm2d:

m = nn.BatchNorm2d(100,affine=False) #100是特征数,对应通道数
input = torch.randn(20,100,35,45)
output = m(input)

Recurrent Layers

nn.RNNBase

nn.RNN

nn.LSTM

nn.GRU

nn.RNNCell

nn.LSTMCell

nn.GRUCell

Transformer Layers

nn.Transformer

nn.TransformerEncoder

nn.TransformerDecoder

nn.TransformerEncoderLayer

nn.TransformerDecoderLayer

Linear Layers

nn.Linear

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

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

class mymodule(nn.Module):
    def __init__(self):
        super(mymodule,self).__init__()
        self.linear1 = Linear(196608,10) #输入特征数,输出特征数
        
    def forward(self,input):
        output = self.linear1(input)
        return output
    
mymo = mymodule()

for imgs,targets in dataloader:
    output = torch.reshape(imgs,(1,1,1,-1))
    #等价于
    #output = torch.flatten(imgs)
    output = mymo(output)

Dropout Layers

是什么:训练时,将input tensor中的一些元素随机变为0(概率为p),以防止过拟合

Sparse Layers

nn.Embedding

Distance Functions

是什么:计算两值间的相似度/距离

Loss Functions

torch.nn.Sequential

例:

model = nn.Sequential(
		nn.Conv2d(1,20,5),
    	nn.ReLU(),
    	nn.Conv2d(20,64,5),
    	nn.ReLU()
)

搭建实战

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

class mymodule(nn.Module):
    def __init__(self):
        super(mymodule,self).__init__()
        self.conv1 = Conv2d(3,32,5,padding=2) #in_channel,out_channel,kernel
        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)
        #法2
        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.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)
        
        #法2
        x = self.model1(x)
        
        return x
    
mymo = mymodule()
#检查代码合规性
input = torch.ones((64,3,32,32))
output = mymo(input)

writer = SummaryWriter("../logs_seq")
writer.add_graph(mymo,input) #展现网络层
writer.close()

损失函数

nn.L1Loss()

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() #可设置reduction='sum'
result = loss(inputs,targets)

nn.MSELoss()

loss_mse = MSELoss()
result_mse = loss_mse(inputs,targets)

nn.CrossEntropyLoss()

  • 要求input(N,C):N=batch_size,C=类别数
  • 要求targets(N)
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)

反向传播

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

class mymodule(nn.Module):
    def __init__(self):
        super(mymodule,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
    
dataset = torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=64)

mymo = mymodule()

loss = nn.CrossEntropyLoss()

for imgs,targets in dataloader:
    outputs = mymo(imgs)
    result_loss = loss(outputs,targets)
    result_loss.backward() #可以得到梯度

优化器torch.optim

optim.SGD:随机梯度下降

optim.Adam

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

class mymodule(nn.Module):
    def __init__(self):
        super(mymodule,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
    
dataset = torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=64)

mymo = mymodule()

loss = nn.CrossEntropyLoss()

optim = torch.optim.SGD(mymo.parameters(),lr=0.01)

for epoch in range(20):
    running_loss = 0.0
    for imgs,targets in dataloader:
        outputs = mymo(imgs)
        result_loss = loss(outputs,targets)
        optim.zero_grad()
        result_loss.backward() #可以得到梯度
        optim.step()
        running_loss += result_loss
    print(running_loss)

现有网络模型的修改与使用

import torchvision
from torch import nn

vgg_false = torchvision.models.vgg16(pretrained=False)
vgg_true = torchvision.models.vgg16(pretrained=True)

print(vgg16_true)

#添加层
vgg16_true.classifier.add_module('add_linear',nn.Linear(1000,10))

#修改层
vgg16_false.classifier[6] = nn.Linear(4096,10)

模型的保存与读取

import torch
import torchvision

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

#保存方式一:保存模型与参数
torch.save(vgg16,"vgg16_method1.pth")

#对应的加载方式
model = torch.load("vgg16_method1.pth")

#以上方法存在陷阱,当前若无该模型的类class,无法正确加载,需要import

#保存方式二:保存模型的参数[官方推荐]
torch.save(vgg16.state_dict(),"vgg16_method2.pth")

#对应的加载方式
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))

完整的模型训练套路

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

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

train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))

train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)

class mymodule(nn.Module):
    def __init__(self):
        super(mymodule,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(1024,64),
            nn.Linear(64,10)
        )
    
    def forward(self,x):
        x = self.model(x)
        return x
#创建网络模型
mymo = mymodule()
"""
⭐
if torch.cuda.is_available():
	mymo = mymo.cuda()
"""

#损失函数
loss_fn = nn.CrossEntropyLoss()
"""
⭐
if torch.cuda.is_available():
	loss_fn = loss_fn.cuda()
"""


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

#设置训练网络的一些参数
total_train_step = 0
total_test_step = 0
epoch = 10

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

start_time = time.time()

for i in range(epoch):
    print("-----------第{}轮训练开始-----------".format(i+1))
    
    mymo.train() #和eval()同,有dropout层或batchnorm层时才有实际作用
    for imgs,targets in train_dataloader:
        """
		⭐
		if torch.cuda.is_available():
        	imgs = imgs.cuda()
        	targets = targets.cuda()
		"""
        outputs = mymo(imgs)
        loss = loss_fn(outputs,targets)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        total_train_step += 1
        if total_train_step % 100 == 0:
            end_time = time.time()
            print(end_time - start_time)
        	print("训练次数:{},Loss:{}".format(total_train_step,loss.item())) #item可以将tensor转化成真实数字
            writer.add_scaler("train_loss",loss.item(),total_train_step)
    
    #测试步骤开始
    mymo.eval()
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():
        for imgs,targets in test_dataloader:
        	"""
            ⭐
            if torch.cuda.is_available():
                imgs = imgs.cuda()
                targets = targets.cuda()
            """
            outputs = mymo(imgs)
            loss = loss_fn(outputs,targets)
            total_test_loss += loss.item()
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy += accuracy
            
    print("整体测试集上的Loss:{}".format(total_test_loss))
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
    writer.add_scaler("test_loss",total_test_loss,total_test_step)
    writer.add_scaler("test_accuracy",total_accuracy/test_data_size,total_test_step)
    total_test_step += 1
    
    torch.save(mymo,"mymo_{}.pth".format(i))
    print("模型已保存")
    
writer.close()

如何计算误分类率:

import torch

outputs = torch.tensor([[0.1,0.2],
                        [0.3,0.4]])

print(outputs.argmax(1)) #1表示横向最值,0表示纵向最值
preds = outputs.argmax(1)
targets = torch.tensor([0,1])

print((preds==targets).sum())

使用GPU训练

方法1:

对网络模型、数据(输入,标注)、损失函数调用它们的.cuda()【见#12⭐部分】

方法2:

.to(device)

device = torch.device(“cpu”) or torch.device(“cuda”) or torch.device(“cuda:0”)

以#12的代码为例

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

"""
⭐定义训练的设备
device = torch.device("cpu")
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
"""

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

train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))

train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)

class mymodule(nn.Module):
    def __init__(self):
        super(mymodule,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(1024,64),
            nn.Linear(64,10)
        )
    
    def forward(self,x):
        x = self.model(x)
        return x
#创建网络模型
mymo = mymodule()
"""
⭐
mymo = mymo.to(device)
"""

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

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

#设置训练网络的一些参数
total_train_step = 0
total_test_step = 0
epoch = 10

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

start_time = time.time()

for i in range(epoch):
    print("-----------第{}轮训练开始-----------".format(i+1))
    
    mymo.train() #和eval()同,有dropout层或batchnorm层时才有实际作用
    for imgs,targets in train_dataloader:

        """
		⭐
		imgs = imgs.to(device)
		targets = targets.to(device)
		"""
        
        outputs = mymo(imgs)
        loss = loss_fn(outputs,targets)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        total_train_step += 1
        if total_train_step % 100 == 0:
            end_time = time.time()
            print(end_time - start_time)
        	print("训练次数:{},Loss:{}".format(total_train_step,loss.item())) #item可以将tensor转化成真实数字
            writer.add_scaler("train_loss",loss.item(),total_train_step)
    
    #测试步骤开始
    mymo.eval()
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():
        for imgs,targets in test_dataloader:
            """
			⭐
			imgs = imgs.to(device)
			targets = targets.to(device)
			"""
            outputs = mymo(imgs)
            loss = loss_fn(outputs,targets)
            total_test_loss += loss.item()
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy += accuracy
            
    print("整体测试集上的Loss:{}".format(total_test_loss))
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
    writer.add_scaler("test_loss",total_test_loss,total_test_step)
    writer.add_scaler("test_accuracy",total_accuracy/test_data_size,total_test_step)
    total_test_step += 1
    
    torch.save(mymo,"mymo_{}.pth".format(i))
    print("模型已保存")
    
writer.close()

完整的模型使用套路

  • 利用已经训练好的模型,给它提供输入
from PIL import Image
import torchvision
from torch import nn
import torch

image_path = "../imgs/dog.png"
image = Image.open(image_path)
print(image)

#PNG是四个通道,除了RGB的三通道外还有透明度通道。如果图片本来就为三通道,则该操作不做改变
image = image.convert("RGB")

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

image = transform(image)
print(image.shape) #3*32*32

"""
此处拷贝mymodule类
"""
class mymodule(nn.Module):
    def __init__(self):
        super(mymodule,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(1024,64),
            nn.Linear(64,10)
        )
    
    def forward(self,x):
        x = self.model(x)
        return x
    
model = torch.load("mymo_0.pth")
#如果是在GPU上训练的模型,现在在cpu上使用,需要加参数:
#model = torch.load("mymo_29_gpu.pth",map_location=torch.devive("gpu"))
print(model)

image = torch.reshape(image,(1,3,32,32))
model.eval()
with torch.no_grad():
	output = model(image)
print(output.argmax(1))

你可能感兴趣的:(基本功&经典方法,pytorch,深度学习,机器学习)