Pytorch:从加载数据集到跑起自己的第一个模型

用代码处理数据样本的活一般比较脏。 我们希望解耦读取数据和训练的过程。

PyTorch提供了两个库:torch.utils.data.DataLoadertorch.utils.data.Dataset

允许预加载数据集以及自己的数据。

Dataset存储样本和相应的标签并支持索引,而DataLoader把数据集做成iterable方便迭代。

加载数据集

包的依赖关系:

import numpy as np
from torchvision import datasets, transforms
from torch.utils.data import DataLoader, Dataset
import torch
import gzip, os
import torch.nn.functional as F
import torch.nn as nn
import torch.optim as optim

Pytorch自带了一些数据集(它们已经继承了Dataset类)

从 TorchVision 加载Fashion-MNIST数据集的示例。

  • Fashion-MNIST是Zalando的商品图片数据集,其中包含60,000个训练示例和10,000个测试示例。 每个示例包括一个28×28灰度图像和一个来自10个类别之一的关联标签。
  • torchvision包含一些常用的数据集、模型、转换函数等等。版本0.5.0包括图片分类、语义切分、目标识别、实例分割、关键点检测、视频分类等工具
import torch
from torch.utils.data import Dataset
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda
import matplotlib.pyplot as plt


training_data = datasets.FashionMNIST(
    root="data", # server端的目录名
    train=True, # 训练集还是测试集
    download=True, # 从server端下载
    transform=ToTensor() # 图像预处理,转换成torch的数据格式
)

test_data = datasets.FashionMNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor()
)

然而,似乎是由于gfw的原因,带有download=True的东西现在似乎不太容易下载了…

ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。

于是我们退而求其次,使用已经下载好的本地数据集MNIST:

前面说了torch.Dataset可以用来存储样本和标签并提供索引,torch.DataLoader为负责迭代。下面就定制一下自己的Dataset和DataLoader:

class DealDataset(Dataset):
    def __init__(self, folder, data_name, label_name, transform = None):
        (train_set, train_labels) = load_data(folder, data_name, label_name)
        self.train_set = train_set
        self.train_labels = train_labels
        self.transform = transform
        
    def __getitem__(self, index):
        img,target = self.train_set[index],int(self.train_labels[index])
        if self.transform is not None:
            img = self.transform(img)
        return img, target
    
    def __len__(self):
        return len(self.train_set)
    
# 其中load_data定义如下:
def load_data(data_folder, data_name, label_name):
    with gzip.open(os.path.join(data_folder,label_name), 'rb') as lbpath:
        y_train = np.frombuffer(lbpath.read(), np.uint8, offset=8)
    with gzip.open(os.path.join(data_folder,data_name), 'rb') as imgpath:
        x_train = np.frombuffer(imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)
    return (x_train, y_train)

定制Dataset需要覆写三个方法:

  • __init__:进行类的初始化
  • __getitem__:进行索引
  • __len__:返回数据集的长度

上述代码在__init__中实现了从MNIST目录中读取所有数据(包括训练集和测试集)并且对数据类型进行适当转化(幸好MNIST数据集不大)

trainDataset = DealDataset('.\\mnist_dataset', "train-images-idx3-ubyte.gz","train-labels-idx1-ubyte.gz",transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ]))
testDataset = DealDataset('.\\mnist_dataset', "t10k-images-idx3-ubyte.gz","t10k-labels-idx1-ubyte.gz",transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
    ]))

在训练模型时,我们通常希望小批量传递样本,防止数据集太大,并且在每个时期重新整理数据以减少模型的过拟合,用Python多进程来加快数据检索(retrieve)的速度。这时便可以使用Dataloader。

接下来是对一些参数的初始化以及使用DataLoader对Dataset进行简易包装:

batch_size = 20
learning_rate = .01
epochs = 50
train_loader = DataLoader(trainDataset, batch_size, shuffle=True)
test_loader = DataLoader(testDataset, batch_size, shuffle=True)

下面构建一个简易的三层神经网络模型:

class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(784, 200), 
            nn.ReLU(inplace=True), 
            nn.Linear(200, 200), 
            nn.ReLU(inplace=True), 
            nn.Linear(200, 10), 
            nn.ReLU(inplace=True)
            )
        
    def forward(self, x):
        x = self.model(x)
        return x

接下来便开始训练了:

net = MLP()
optimizer = optim.SGD(net.parameters(), lr = learning_rate)
criterion = nn.CrossEntropyLoss()
i = 0
for epoch in range(epochs):
    for batch_idx, (data, target) in enumerate(train_loader):
        data = data.view(-1, 28*28)
        data, target = data, target
        
        logits = net(data)
        loss = criterion(logits, target)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if batch_idx % 100 == 0: 
            print('Train Epoch:{} [{}/{} ({:.0f}%)]\tLoss:{:.6f}'.format( epoch,batch_idx*len(data),len(train_loader.dataset),100.*batch_idx/len(train_loader),loss.item())) 
     
        test_loss = 0
        correct = 0
        for data, target in test_loader:
            data = data.view(-1, 28*28)
            data, target = data, target
            logits = net(data)
            test_loss += criterion(logits, target).item()
        
            pred = logits.argmax(dim=1)
            correct += pred.eq(target).float().sum().item()
            test_loss /= len(test_loader.dataset)
            i = i+1
            if i % 1000 == 0:
                print('\nTest set:Average loss:{:.4f},Accuracy:{}/{} ({:.0f}%)\n'.format(test_loss,correct,
                                                                                     len(test_loader.dataset),
                                                                                     100.*correct/len(test_loader.dataset))) 

这里因为计算机版本的问题,所以没有使用cuda加速。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PenguinLeee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值