PyTorch制作训练集

前面的文章(PyTorch安装环境与基础知识 )介绍了PyTorch的基本接口,已经掌握了 如何定义Net, forword参数,loss,参数更新。在这篇文章里,我们来看如何制作训练集,并且实现完整的训练和测试。和前一篇一样,我们还是从官方的一小时手册中的cifar10入手。

1.别人家的CIFAR10

由于torchvision中有函数可以自动获得几个常见的数据集(minist,cifar10,imagenet),因此可以直接获得trainset.然后transforms是对数据的一些预处理。transforms.Compose()是把几个transform语句合并到一起。ToTensor()是数据类型的转换,nomalize传入三通道的两个参数是:mean,std.

import torchvision
import torchvision.transforms as transforms

transform = transforms.Compose( 
         [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) 

trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) 

trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2) 
testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) 
testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)

2.你的数据集

Ref[1]模仿cifar10的训练集做了自己训练集,用于数字的分类。首先是定义了一个训练集图片train存放的地址path。然后使用ImageFolder()函数读取,并执行transforms预处理。其中Resize()可以传入两类参数。一类是(h,w)这将把图片缩放到(h,w)大小(长宽比会改变)。另一类是传入单个参数,这将把图片经过缩放后(保持长宽比不变),将最短的边缩放到传入的参数。

def loadtraindata(): 
    path = r"/home/********/folder/train"                                         # 路径
    trainset = torchvision.datasets.ImageFolder(path,
    transform=transforms.Compose([ transforms.Resize((32, 32)), 
                           # 将图片缩放到指定大小(h,w)或者保持长宽比并缩放最短的边到int大小
                           transforms.CenterCrop(32),
                           transforms.ToTensor()]) ) 
    trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                           shuffle=True, num_workers=2) 
    return trainloader

如何训练你的数据集?该项目的作者命名一个trainandsave函数,主要是把训练和网络的参数保存放在一起。作者写了详细的注释,我这里就原版引用。

def trainandsave(): 
    trainloader = loadtraindata() # 神经网络结构
    net = Net() 
    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # 学习率为0.001 criterion = nn.CrossEntropyLoss() # 损失函数也可以自己定义,我们这里用的交叉熵损失函数 # 训练部分
    
    for epoch in range(5): # 训练的数据量为5个epoch,每个epoch为一个循环
                            # 每个epoch要训练所有的图片,每训练完成200张便打印一下训练的效果(loss值)
        running_loss = 0.0  # 定义一个变量方便我们对loss进行输出
        for i, data in enumerate(trainloader, 0): # 这里我们遇到了第一步中出现的trailoader,代码传入数据
            # enumerate是python的内置函数,既获得索引也获得数据
            # get the inputs
            inputs, labels = data # data是从enumerate返回的data,包含数据和标签信息,分别赋值给inputs和labels

            # wrap them in Variable
            inputs, labels = Variable(inputs), Variable(labels) # 转换数据格式用Variable
           
            optimizer.zero_grad() # 梯度置零,因为反向传播过程中梯度会累加上一次循环的梯度

            # forward + backward + optimize
            outputs = net(inputs) # 把数据输进CNN网络net
            loss = criterion(outputs, labels) # 计算损失值
            loss.backward() # loss反向传播
            optimizer.step() # 反向传播后参数更新 
            running_loss += loss.data[0]      # loss累加
            if i % 200 == 199:
                print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 200)) # 然后再除以200,就得到这两百次的平均损失值
                running_loss = 0.0  # 这一个200次结束后,就把running_loss归零,下一个200次继续使用

    print('Finished Training') # 保存神经网络
    torch.save(net, 'net.pkl') # 保存整个神经网络的结构和模型参数
    torch.save(net.state_dict(), 'net_params.pkl') # 只保存神经网络的模型参数

可以看到enumerate把训练集的inputs和labels分开。input作为网络的输入,并使用lossfunction计算output 和label。

由于之后的项目会比较大,ref[2]给了不同文档执行不同功能的建议,我觉得这种做法有利于在一个整洁的环境中,完成项目,一并推荐给各位客官。

Ref

1.https://blog.csdn.net/a738833592/article/details/80900250

2.如何加载自己的训练数据 – woshicao11的博客 – CSDN博客

    原文作者:盐粒
    原文地址: https://zhuanlan.zhihu.com/p/55566505
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞