《PyTorch深度学习实践》学习笔记:加载数据集


前言

在前面的内容中,在训练的时候我们使用的都是全部的数据进行训练,这种在时间上比较好,但是性能上会遇到一些问题,比如鞍点;此外,我们还知道一种随机梯度下降,这种训练是每次取一个数据去计算梯度,这种方法能够有效的解决鞍点的问题,而且性能相对较好,但是每次一个点时间消耗多,而且不能利用CPU/GPU的并行计算能力;把全部的梯度下降和随机梯度下降进行一个折中(时间和性能进行折中),得出了批量梯度下降,也就是Mini-batch梯度下降,也就是每次训练时去一小批数据进行训练。


一、Mini-batch基础概念

当我们使用Mini-batch进行训练的时候,我们就需要通过两层循环还进行:

for epoch in range(trainging_epochs):  # 外层代表训练轮数
	for i in range(total_batchs):      # 内存对batch进行迭代
  • Epoch:1次epoch表示把所有的训练样本都进行了一次前馈和反馈的训练;

  • Batch_Size:表示一次前馈和反馈所使用的样本数量;

  • Iteration:将样本一共分成了几个Mini-Batch。

例:10000个样本,其中Batch_size=1000,则Iteration=10000/1000=10。

采用Mini-Batch的方法来训练数据时,需要使用Dataset和DataLoader两个工具类:

Dataset:用来构造数据集,使数据集可以通过索引快速取出

DataLoader:取出一个Mini-Batch,一组数据


二、DataLoader使用

使用DataLoader时需要两个基本参数:

  1. shuffle :是否打乱数据顺序,打乱的话每次epoch的Mini-Batch数据都是随机的
  2. batch-size:每个Mini-Batch需要的数据量

dataset提供了索引和长度,这样的话dataloader就可以根据dataset进行小批量的数据集的生成。
在这里插入图片描述
上图batch_size = 2,dataloader的工作先通过shuffle将数据样本打乱,打乱之后进行分组,按照每batch_size为一组,之后在迭代的过程中就是按照每组进行Mini-batch取数据。

在代码层面实现dataset和dataloader:

pytorch的utils.data里面提供Dataset和Dataloader。Dataset是抽象类,而抽象类是不能够实例化的,他只能被其他的子类进行继承,所以我们只能通过继承的方式来自定义我们自己的类。Dataloader是一个类帮助我们来加载数据,可以shuffle以及batch_size,因此我们可以实例化一个Dataloader。

接下来定义我们自己数据集的类:

class DiabetesDataset(Dataset):
    def __init__(self):
        pass
    def __getitem__(self, index):
        pass
    def __len__(self):
        pass

getitem(): 实现数据集的索引,dataset[index]

len(): 返回数据集的长度

在构造数据集的时候需要注意有两点:

  1. 我们把所有的数据都通过init()加载到内存当中,然后我们通过getitem()把构造好的数据集的第i个样本给传出去,这种方法适合于本身的数据集不大,但是对于打的数据集比如图像数据集,init()把数据都读到内存是不可能的,对于图像有时候会把它变成一个一个的文件,有时候会把它放到一个package文件里,所以在init()里面只是做一些初始化,或者说都是读写的,定义一些列表,然后数据集里面的每一条数据的文件名放到相应的列表里面,相应的标签可以读到内存里(比较简单的标签),但是一些数据集的标签也很复杂,例如输入一张图像,输出是图像的每一个像素是属于背景还是前景,这就使得输出的结果也很大,所以对于简单的输出标签,可以选择加载到内存;对于复杂的输出,就可以把它的文件名放到列表里面,等到getitem()可以读取列表里面的第i个文件,然后输入X和输出Y再从文件里读出来,然后再进行返回,这样才能保证内存的高效使用。
  2. 如果数据比较小,就直接读到内存;如果数据集比较大,我们应该考虑是否可以把它直接加载到内存。

关于Dataloader的参数,我们常使用的有四个:

train_loader = DataLoader(dataset=dataset,   # 数据集对象
                          batch_size=32,     # 小批量的样本数量
                          shuffle=True,      # 数据是否打乱
                          num_workers=2)     # 读数据的是否需要多线程(并行化)

关于num_workers在windows中使用需要注意的:
在这里插入图片描述
如果直接使用trainloader进行训练的话,可以会报错(pytorch 0.4),报错的原因是在Linux和windows下实现多进程的方式是不同的,在windows中使用spawn替代了fork,可以会出现runtimeError。

解决问题方法:把loader迭代的训练代码封装起来,封装到if语句里面,或者是封装到函数里面,不直接写到程序的主体里面。
在这里插入图片描述
最终实现我们自己的数据集和加载器:

class DiabetesDataset(Dataset):
    def __init__(self,filepath):
        xy = np.loadtxt(filepath,delimiter=',',dtype=np.float32)  # 糖尿病数据集,结构化表格比较小,直接全部加载到内存
        self.len = xy.shape[0]                                    # 数据集的样本数量
        self.x_data = torch.from_numpy(xy[:,:-1])                 # 输入数据
        self.y_data = torch.from_numpy((xy[:,[-1]]))              # 输出标签


    def __getitem__(self, item):
        return self.x_data[item],self.y_data[item]                # 数据索引

    def __len__(self):
        return self.len                                           # 数据集的长度

dataset = DiabetesDataset('diabetes.csv.gz')
train_loader = DataLoader(dataset=dataset,
                          b
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值