• 基于Pytorch完整的训练一个神经网络并进行验证


    原视频链接:Pytorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】

    土堆老师的Github地址

    之前学的也不少了,现在要去训练一个完整的神经网络,利用Pytorch和CIFAR10数据集

    准备数据集

    import torchvision#导入torchvision
    ##准备数据集
    train_data=torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),
                                            download=True)##数据集的目录,是否训练,将PIL型变为Tensor型,需要下载
    test_data=torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),
                                            download=True)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    测试数据集长度

    #length 长度
    train_data_size=len(train_data)
    test_data_size=len(test_data)
    #如果train_data_size为10,训练集的长度为:10
    print("训练数据集长度为:{}".format(train_data_size))#{},会被替换为后面的值,把他变成字符串了
    print("测试数据集长度为:{}".format(test_data_size))#{},会被替换为后面的值,把他变成字符串了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    输出结果

    Files already downloaded and verified
    Files already downloaded and verified
    训练数据集长度为:50000
    测试数据集长度为:10000
    
    • 1
    • 2
    • 3
    • 4

    用DataLoader加载数据

    #利用dataloader来加载数据集
    train_dataloader=DataLoader(train_data,batch_size=64)#一次训练所抓取的数据样本数量为64
    test_dataloader=DataLoader(test_data,batch_size=64)
    
    • 1
    • 2
    • 3

    搭建神经网络

    在这里插入图片描述
    这是CIFAR10 model的结构

    class NetWork(nn.Module):
        def __init__(self):
            super(NetWork, 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,x):
            x=self.model(x)
            return x
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    将此程序放入另一个新创建的python文件中,注意在同一个文件夹下

    from torch import nn
    import torch
    class NetWork(nn.Module):
        def __init__(self):
            super(NetWork, 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,x):
            x=self.model(x)
            return x
    
    
    
    if __name__ == '__main__':
         network=NetWork()
         input=torch.ones((64,3,32,32))
         output=network(input)
         print(output.shape)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    输出结果:

    torch.Size([64, 10])
    
    • 1

    输出了64行,每一行上有10个数据,10代表了我们每一张图片在我们十个类别中的概率

    创建损失函数

    loss_fn=nn.CrossEntropyLoss()#交叉熵
    
    • 1

    创建优化器

    learning_rate=0.01#学习速率
    optimizer=torch.optim.SGD(network.parameters(),lr=learning_rate)#随机梯度下降,先填网络模型,然后是学习速率
    
    • 1
    • 2

    开始训练

    #设置训练网络的一些参数
    total_train_step=0#记录训练次数
    #记录测试的次数
    total_test_step=0
    #训练的轮数
    epoch=10
    
    for i in range(epoch):
        print("----------------第{}轮训练开始-------------".format(i+1))
    
        #训练步骤开始
        for data in train_dataloader:
            imgs,targets=data
            outputs=network(imgs)
            loss=loss_fn(outputs,targets)
            #优化器优化模型
            optimizer.zero_grad()#优化器梯度清零
            loss.backward()#反向传播
            optimizer.step()#优化器进行优化
    
            total_train_step=total_train_step+1 #记录训练次数
            print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    输出结果

    Files already downloaded and verified
    Files already downloaded and verified
    训练数据集长度为:50000
    测试数据集长度为:10000
    ----------------1轮训练开始-------------
    训练次数:1,Loss:2.31258487701416
    训练次数:2,Loss:2.312842607498169
    训练次数:3,Loss:2.302748918533325
    训练次数:4,Loss:2.3247387409210205
    训练次数:5,Loss:2.307778835296631
    训练次数:6,Loss:2.311138868331909
    训练次数:7,Loss:2.290013551712036
    训练次数:8,Loss:2.302402973175049
    训练次数:9,Loss:2.293430805206299
    训练次数:10,Loss:2.2981677055358887
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这里如果不停止会一直输出,所以,我们要把训练过程改善一下

        for data in train_dataloader:
            imgs,targets=data
            outputs=network(imgs)
            loss=loss_fn(outputs,targets)
            #优化器优化模型
            optimizer.zero_grad()#优化器梯度清零
            loss.backward()#反向传播
            optimizer.step()#优化器进行优化
    
            total_train_step=total_train_step+1 #记录训练次数
            if total_train_step %100==0:#每100次才打印
                print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    每100次才打印数据

    开始测试步骤

    训练完毕之后,我们接下来采用测试数据进行测试

    total_test_loss=0
        with torch.no_grad():
            for data in test_dataloader:
                imgs,targets =data
                outputs =network(imgs)#输入放到网络当中我们可以得到对应输出
                loss =loss_fn(outputs,targets)#计算误差
                total_test_loss=total_test_loss+loss.item()
        print("整体测试集上的Loss:{}".format(total_test_loss))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    输出结果

    Files already downloaded and verified
    Files already downloaded and verified
    训练数据集长度为:50000
    测试数据集长度为:10000
    ----------------1轮训练开始-------------
    训练次数:100,Loss:2.2861547470092773
    训练次数:200,Loss:2.273378372192383
    训练次数:300,Loss:2.238002300262451
    训练次数:400,Loss:2.1429920196533203
    训练次数:500,Loss:2.050020694732666
    训练次数:600,Loss:2.005511522293091
    训练次数:700,Loss:2.015151262283325
    整体测试集上的Loss:314.1541121006012
    ----------------2轮训练开始-------------
    训练次数:800,Loss:1.8569183349609375
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    训练结果可视化

    为了使得我们可以清晰地看到训练结果,我们用Tensorboard把他画出来

    需要在训练步骤和测试步骤里面加上一句代码

    开头启用Tensorboard

    writer=SummaryWriter("logs_train")
    
    • 1

    训练步骤下

        if total_train_step %100==0:#每100次才打印
                print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))
                writer.add_scalar("train_loss",loss.item(),total_train_step)##标题,loss值,训练次数
                writer.add_scalar("train_loss",loss.item(),total_train_step)##标题,loss值,训练次数
    
    • 1
    • 2
    • 3
    • 4

    测试步骤下

    writer.add_scalar("test_loss",total_test_loss,total_test_step)##标题,测试误差值,测试次数
    total_test_step=total_test_step+1
    
    • 1
    • 2

    最后加上

    writer.close()
    
    • 1

    在Terminal中加上启动tensorboard的代码,要在pytorch的环境下

    tensorboard --logdir=logs_train
    
    • 1

    打开连接后,画出的图像如下

    输出结果

    train_loss
    在这里插入图片描述
    test_loss
    在这里插入图片描述
    loss一直在下降,证明训练有一定效果

    拓展

    二分类问题求准确率

    先来了解一个函数叫做Argmax()

    import torch
    outputs=torch.Tensor([[0.1,0.2],
                          [0.3,0.4]])
    print(outputs.argmax(1))#1表示横向,0表示纵向比较
    
    • 1
    • 2
    • 3
    • 4

    输出结果

    tensor([1, 1])
    
    • 1

    表示在横向上,0.2比0.1大,为1,0.4比0.3大,也为1,如果将argmax换成0

    import torch
    outputs=torch.Tensor([[0.1,0.2],
                          [0.05,0.4]])
    print(outputs.argmax(0))#1表示横向,0表示纵向比较
    
    • 1
    • 2
    • 3
    • 4

    输出结果

    tensor([0, 1])
    
    • 1

    在纵向上,0.05比0.1小,所以是0,另一纵向同理

    再将其与真实结果比较,计算其总和

    import torch
    outputs=torch.Tensor([[0.1,0.2],
                          [0.05,0.4]])
    print(outputs.argmax(0))#1表示横向,0表示纵向比较
    
    preds=outputs.argmax(1)
    targets =torch.Tensor([0,1])
    print((preds==targets).sum())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    输出结果

    tensor([1, 1])
    tensor(1)
    
    • 1
    • 2

    测试模型的准确率

    通过以上的内容,我们可以优化我们的模型,计算其准确率

     total_test_loss=0
        total_accuracy=0#整体正确率
        with torch.no_grad():
            for data in test_dataloader:
                imgs,targets =data
                outputs =network(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))
        writer.add_scalar("test_loss",total_test_loss,total_test_step)##标题,测试误差值,测试次数
        writer.add_scalar("test_accuracy",total_accuracy/test_data_size,total_test_step)
        total_test_step=total_test_step+1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    输出结果

    ----------------1轮训练开始-------------
    训练次数:100,Loss:2.2833285331726074
    训练次数:200,Loss:2.2706451416015625
    训练次数:300,Loss:2.203575849533081
    训练次数:400,Loss:2.102896213531494
    训练次数:500,Loss:2.012601852416992
    训练次数:600,Loss:2.006645441055298
    训练次数:700,Loss:1.9837690591812134
    整体测试集上的Loss:309.36241841316223
    整体测试集上的正确率:0.2946999967098236
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在Tensorboard中显示
    在这里插入图片描述
    准确率是在上升的

    以上就是训练一个完整的模型的步骤了

    完整代码

    #######################一个完整的神经网络 准备数据,加载数据,准备模型,设置损失函数,设置优化器,开始训练,最后验证,结果聚合展示
    
    import torchvision
    from torch import nn
    from torch.utils.data import DataLoader
    from torch.utils.tensorboard import SummaryWriter
    
    from model import *#引入model中的所有import
    ##准备数据集
    train_data=torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),
                                            download=True)##数据集的目录,是否训练,将PIL型变为Tensor型,需要下载
    
    test_data=torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),
                                            download=True)
    #length 长度
    train_data_size=len(train_data)
    test_data_size=len(test_data)
    #如果train_data_size为10,训练集的长度为:10
    print("训练数据集长度为:{}".format(train_data_size))#{},会被替换为后面的值,把他变成字符串了
    print("测试数据集长度为:{}".format(test_data_size))#{},会被替换为后面的值,把他变成字符串了
    
    
    #利用dataloader来加载数据集
    train_dataloader=DataLoader(train_data,batch_size=64)#一次训练所抓取的数据样本数量为64
    test_dataloader=DataLoader(test_data,batch_size=64)
    
    #创建网络模型
    network=NetWork()
    
    #损失函数
    loss_fn=nn.CrossEntropyLoss()#交叉熵
    
    #优化器
    learning_rate=0.01#学习速率
    optimizer=torch.optim.SGD(network.parameters(),lr=learning_rate)#随机梯度下降,先填网络模型,然后是学习速率
    
    
    #设置训练网络的一些参数
    total_train_step=0#记录训练次数
    #记录测试的次数
    total_test_step=0
    #训练的轮数
    epoch=10
    
    #添加tensorboard
    writer=SummaryWriter("logs_train")
    
    for i in range(epoch):
        print("----------------第{}轮训练开始-------------".format(i+1))
    
        #训练步骤开始
        network.train()
        for data in train_dataloader:
            imgs,targets=data
            outputs=network(imgs)
            loss=loss_fn(outputs,targets)
            #优化器优化模型
            optimizer.zero_grad()#优化器梯度清零
            loss.backward()#反向传播
            optimizer.step()#优化器进行优化
    
            total_train_step=total_train_step+1 #记录训练次数
            if total_train_step %100==0:#每100次才打印
                print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))
                writer.add_scalar("train_loss",loss.item(),total_train_step)##标题,loss值,训练次数
        #测试步骤开始
        network.eval()
        total_test_loss=0
        total_accuracy=0#整体正确率
        with torch.no_grad():#网络模型没有梯度,不需要梯度优化
            for data in test_dataloader:
                imgs,targets =data
                outputs =network(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))
        writer.add_scalar("test_loss",total_test_loss,total_test_step)##标题,测试误差值,测试次数
        writer.add_scalar("test_accuracy",total_accuracy/test_data_size,total_test_step)
        total_test_step=total_test_step+1
        torch.save(network,"network_{}.pth".format(i))#保存每一轮的训练结果
        print("模型已保存")
    
    writer.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    利用GPU去训练神经网络

    只需要稍作改动

    #创建网络模型
    network=NetWork()
    if torch.cuda.is_available():
        network=network.cuda()#利用gpu进行训练
    
    • 1
    • 2
    • 3
    • 4

    损失函数改成cuda

    #损失函数
    loss_fn=nn.CrossEntropyLoss()#交叉熵
    loss_fn=loss_fn.cuda()#利用gpu训练
    
    • 1
    • 2
    • 3

    在训练和测试那里,吧imgs和targets改成cuda就OK了

    imgs=imgs.cuda()
    targets=targets.cuda()
    
    • 1
    • 2

    跟CPU跑的比较了下,CPU跑100轮用了4.9s,GPU用了3.2s,确实会快

  • 相关阅读:
    【英语:基础进阶_听口实战运用】D4.听力题目的类别与应对方法
    项目经理,你真的有领导力吗?
    JMeter:断言之响应断言
    LipidSearch 5.1
    Servlet urlPatterns配置
    iptables、firewalld防火墙详解
    MySQL从安装、配置到日常操作和管理的关键步骤
    C语言 100道经典编程题适用于专升本,专接本【详细分析版】
    1.4_10 Axure RP 9 for mac 高保真原型图 - 案例9 【按钮】单选按钮组
    计算机视觉与深度学习-全连接神经网络-训练过程-欠拟合、过拟合和Dropout- [北邮鲁鹏]
  • 原文地址:https://blog.csdn.net/qq_42887663/article/details/125482871