Pytorch基础之模型训练

313 阅读3分钟
参与拿奖:本文已参与「新人创作礼」活动,一起开启掘金创作之路
PS:完整代码文末自取

1.训练准备

1.1 导入相关包

import torch
from torch import nn
import torchvision
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter
from time import time

1.2 加载数据集

# 数据集
train_data = torchvision.datasets.CIFAR10('./data/05 data', train=True, transform=transforms.ToTensor(), download=True)
test_data = torchvision.datasets.CIFAR10('./data/05 data', train=False, transform=transforms.ToTensor(), download=True)

print("train_data's length: {}".format(len(train_data)))
print("test_data's length: {}".format(len(test_data)))

# 利用dataloader加载数据
from torch.utils.data import DataLoader

train_data = DataLoader(train_data
                        , batch_size=64  # 每次抽取数据的大小
                        , shuffle=False  # 是否打乱顺序
                        )
test_data = DataLoader(test_data
                       , batch_size=64
                       , shuffle=False)

1.3 搭建神经网络

# 搭建神经网络
class myNet(nn.Module):
    def __init__(self):
        super(myNet, 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()  # 64x4x4
            , nn.Linear(64 * 4 * 4, 64)
            , nn.Linear(64, 10)
        )

    def forward(self, x):
        output = self.model(x)
        return output

1.4 参数初始化

# 网络实例化
mynet = myNet()

# 损失
loss_fn = nn.CrossEntropyLoss()

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

# 设置训练网络参数
total_train_step = 0  # 训练与测试次数
total_test_step = 0

epoch = 3  # 训练轮数

1.5 训练

# 使用tensorboard绘制图像
writer = SummaryWriter("myNet")

# 训练步骤
for i in range(epoch):
    print("..................train's round %d............" % (i + 1))
    begin = time()
    mynet.train()  # 启动训练模式
    for data in train_data:
        imgs, targets = data
        outputs = mynet(imgs)
        loss = loss_fn(outputs, targets)  # 损失

        optimizer.zero_grad()  # 初始化梯度(调优)
        loss.backward()  # 反向传播
        optimizer.step()

        total_train_step += 1
        if total_train_step % 100 == 0:  # 每1训练00次打印一次
            print(time() - begin)
            print("train round {},Loss {}".format(total_train_step, loss))
            writer.add_scalar("train_loss", loss.item(), total_train_step)

1.6 测试

# 测试步骤
mynet.eval()  # 启动调试模式
total_test_loss = 0  # 测试的损失
total_accuracy = 0
with torch.no_grad():
    for data in test_data:
        imgs, targets = data
        outputs = mynet(imgs)
        loss = loss_fn(outputs, targets)  # 损失
        total_test_loss += loss.item()
        accuracy = (outputs.argmax(1) == targets).sum()  # 预判正确
        total_accuracy += accuracy
print('total test accuracy {}'.format(total_accuracy / len(test_data)))  # 测试正确率
print("total test loss {}".format(total_test_loss))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
total_test_step += 1

# 保存每次的模型
torch.save(mynet, "./data/05 data/myNet/model_%d.pth" % i)  # 保存模型

image.png

image.png

2.使用GPU进行训练

2.1 训练准备

进入conda虚拟环境 ,在终端使用 nvidia-smi 查看cuda版本
使用.to(divice),torch.divice("cuda")

2.2 完整代码

# 可以通过 from model import* 导入上述模型
import torch
from torch import nn
import torchvision
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter
from time import time

print(torch.__version__,torch.cuda.is_available())


# 数据集
train_data=torchvision.datasets.CIFAR10('./data/05 data',train=True,transform=transforms.ToTensor(),download=True)
test_data=torchvision.datasets.CIFAR10('./data/05 data',train=False,transform=transforms.ToTensor(),download=True)

print("train_data's length: {}" .format(len(train_data)))
print("test_data's length: {}".format(len(test_data)))




# 利用dataloader加载数据
from torch.utils.data import DataLoader
train_data=DataLoader(train_data
                      ,batch_size=64 #每次抽取数据的大小
                      ,shuffle=False #是否打乱顺序
                     )
test_data=DataLoader(test_data
                     ,batch_size=64
                     ,shuffle=False)



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

# 网络实例化
mynet=myNet()
if torch.cuda.is_available():
    mynet=mynet.cuda() #将模型转入cuda



# 损失
loss_fn=nn.CrossEntropyLoss()
loss_fn=loss_fn.cuda()



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

# 设置训练网络参数
total_train_step=0 # 训练与测试次数
total_test_step=0

epoch=3 # 训练轮数



# 使用tensorboard绘制图像
writer=SummaryWriter("myNet")

# 训练步骤
for i in range(epoch):
    print("..................train's round %d............"%(i+1))
    begin=time()
    mynet.train() #启动训练模式
    for data in train_data:
        imgs,targets=data
        if torch.cuda.is_available():
            imgs=imgs.cuda()
            targets=targets.cuda()
        outputs=mynet(imgs)
        loss=loss_fn(outputs,targets) #损失
        
        optimizer.zero_grad() #初始化梯度(调优)
        loss.backward() #反向传播
        optimizer.step()
        
        total_train_step+=1
        if total_train_step%100==0: #每1训练00次打印一次
            print(time()-begin)
            print("train round {},Loss {}".format(total_train_step,loss))
            writer.add_scalar("train_loss",loss.item(),total_train_step)
        
    
    # 测试步骤
    mynet.eval() # 启动调试模式
    total_test_loss=0 #测试的损失
    total_accuracy=0
    with torch.no_grad():
        for data in test_data:
            imgs,targets=data
            if torch.cuda.is_available():
                imgs=imgs.cuda()
                targets=targets.cuda()
            outputs=mynet(imgs)
            loss=loss_fn(outputs,targets) #损失
            total_test_loss+=loss.item() 
            accuracy=(outputs.argmax(1)==targets).sum() #预判正确
            total_accuracy+=accuracy
    print('total test accuracy {}'.format(total_accuracy/len(test_data))) #测试正确率
    print("total test loss {}".format(total_test_loss))
    writer.add_scalar("test_loss",total_test_loss,total_test_step)
    total_test_step+=1
    
    # 保存每次的模型
    torch.save(mynet,"./data/05 data/myNet/model_%d.pth"%i) #保存模型
    
writer.close()

image.png

3.模型验证套路


import torch
from PIL import Image

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

from torchvision import transforms
transform=transforms.Compose([transforms.Resize((32,32)),transforms.ToTensor()])
image=transform(image)
print(image.shape)


# 搭建神经网络
class myNet(nn.Module):
    def __init__(self):
        super(myNet,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() # 64x4x4
            ,nn.Linear(64*4*4,64)
            ,nn.Linear(64,10)
        )
    def forward(self,x):
        output=self.model(x)
        return output
    
# 使用第一种方法加载模型
model=torch.load("./data/05 data/myNet/model_1.pth")
image=torch.reshape(image,(-1,3,32,32))

# 在CPU上加载GPU训练的模型
model=torch.load("./data/05 data/myNet/model_1.pth",map_location=torch.device("cpu")) 

model.eval()
with torch.no_grad():
    output=model(image)
    
print(output)
print(output.argmax(1)) #打印训练出来的结果

image.png

参考资料

[1] b站课程链接

[2] 手敲代码链接