Pytorch中的dataset和dataloader

转载自:https://blog.youkuaiyun.com/qq_36556893/article/details/86505934


目录

一、概念

二、Dataset的创建和使用

三、DataLoader的创建和使用

*四、将Dataset数据和标签放在GPU上(代码执行顺序出错则会有bug)

五、Dataset和DataLoader总结


一、概念

1.torch.utils.data.dataset这样的抽象类可以用来创建数据集。学过面向对象的应该清楚,抽象类不能实例化,因此我们需要构造这个抽象类的子类来创建数据集,并且我们还可以定义自己的继承和重写方法。

2.这其中最重要的就是__len____getitem__这两个函数,前者给出数据集的大小,后者是用于查找数据和标签

3.torch.utils.data.DataLoader是一个迭代器,方便我们去多线程地读取数据,并且可以实现batch以及shuffle的读取等。

二、Dataset的创建和使用

1.首先我们需要引入dataset这个抽象类,当然我们还需要引入Numpy:


 
  1. import torch.utils.data.dataset as Dataset
  2. import numpy as np

2.我们创建Dataset的一个子类:

(1)初始化,定义数据内容和标签


 
  1. #初始化,定义数据内容和标签
  2. def __init__(self, Data, Label):
  3. self.Data = Data
  4. self.Label = Label

(2)返回数据集大小


 
  1. #返回数据集大小
  2. def __len__(self):
  3. return len(self.Data)

(3)得到数据内容和标签


 
  1. #得到数据内容和标签
  2. def __getitem__(self, index):
  3. data = torch.Tensor(self.Data[index])
  4. label = torch.Tensor(self.Label[index])
  5. return data, label

(4)最终这个子类定义为:


 
  1. import torch
  2. import torch.utils.data.dataset as Dataset
  3. import numpy as np
  4. #创建子类
  5. class subDataset(Dataset.Dataset):
  6. #初始化,定义数据内容和标签
  7. def __init__(self, Data, Label):
  8. self.Data = Data
  9. self.Label = Label
  10. #返回数据集大小
  11. def __len__(self):
  12. return len(self.Data)
  13. #得到数据内容和标签
  14. def __getitem__(self, index):
  15. data = torch.Tensor(self.Data[index])
  16. label = torch.Tensor(self.Label[index])
  17. return data, label

值得注意的地方是:

class subDataset(Dataset.Dataset):
 

如果只写了Dataset而不是Dataset.Dataset,则会报错:module.__init__() takes at most 2 arguments (3 given)

                                       

因为Dataset是module模块,不是class类,所以需要调用module里的class才行,因此是Dataset.Dataset!

3.在类外对Data和Label赋值:


 
  1. Data = np.asarray([[ 1, 2], [ 3, 4],[ 5, 6], [ 7, 8]])
  2. Label = np.asarray([[ 0], [ 1], [ 0], [ 2]])

4.声明主函数,主函数创建一个子类的对象,传入Data和Label参数


 
  1. if __name__ == '__main__':
  2. dataset = subDataset(Data, Label)

5.输出数据集大小和数据:


 
  1. print(dataset)
  2. print( 'dataset大小为:', dataset.__len__())
  3. print(dataset.__getitem__( 0))
  4. print(dataset[ 0])

代码变为;


 
  1. import torch
  2. import torch.utils.data.dataset as Dataset
  3. import numpy as np
  4. Data = np.asarray([[ 1, 2], [ 3, 4],[ 5, 6], [ 7, 8]])
  5. Label = np.asarray([[ 0], [ 1], [ 0], [ 2]])
  6. #创建子类
  7. class subDataset(Dataset.Dataset):
  8. #初始化,定义数据内容和标签
  9. def __init__(self, Data, Label):
  10. self.Data = Data
  11. self.Label = Label
  12. #返回数据集大小
  13. def __len__(self):
  14. return len(self.Data)
  15. #得到数据内容和标签
  16. def __getitem__(self, index):
  17. data = torch.Tensor(self.Data[index])
  18. label = torch.IntTensor(self.Label[index])
  19. return data, label
  20. if __name__ == '__main__':
  21. dataset = subDataset(Data, Label)
  22. print(dataset)
  23. print( 'dataset大小为:', dataset.__len__())
  24. print(dataset.__getitem__( 0))
  25. print(dataset[ 0])

结果为:

                                                     

三、DataLoader的创建和使用

1.引入DataLoader:

import torch.utils.data.dataloader as DataLoader
 

2. 创建DataLoader,batch_size设置为2,shuffle=False不打乱数据顺序,num_workers= 4使用4个子进程


 
  1. #创建DataLoader迭代器
  2. dataloader = DataLoader.DataLoader(dataset,batch_size= 2, shuffle = False, num_workers= 4)

3.使用enumerate访问可遍历的数组对象:


 
  1. for i, item in enumerate(dataloader):
  2. print( 'i:', i)
  3. data, label = item
  4. print( 'data:', data)
  5. print( 'label:', label)

4.最终代码如下:


 
  1. import torch
  2. import torch.utils.data.dataset as Dataset
  3. import torch.utils.data.dataloader as DataLoader
  4. import numpy as np
  5. Data = np.asarray([[ 1, 2], [ 3, 4],[ 5, 6], [ 7, 8]])
  6. Label = np.asarray([[ 0], [ 1], [ 0], [ 2]])
  7. #创建子类
  8. class subDataset(Dataset.Dataset):
  9. #初始化,定义数据内容和标签
  10. def __init__(self, Data, Label):
  11. self.Data = Data
  12. self.Label = Label
  13. #返回数据集大小
  14. def __len__(self):
  15. return len(self.Data)
  16. #得到数据内容和标签
  17. def __getitem__(self, index):
  18. data = torch.Tensor(self.Data[index])
  19. label = torch.IntTensor(self.Label[index])
  20. return data, label
  21. if __name__ == '__main__':
  22. dataset = subDataset(Data, Label)
  23. print(dataset)
  24. print( 'dataset大小为:', dataset.__len__())
  25. print(dataset.__getitem__( 0))
  26. print(dataset[ 0])
  27. #创建DataLoader迭代器
  28. dataloader = DataLoader.DataLoader(dataset,batch_size= 2, shuffle = False, num_workers= 4)
  29. for i, item in enumerate(dataloader):
  30. print( 'i:', i)
  31. data, label = item
  32. print( 'data:', data)
  33. print( 'label:', label)

结果为:

                                                  

可以看到两个对象,因为对象数*batch_size就是数据集的大小__len__

*四、将Dataset数据和标签放在GPU上(代码执行顺序出错则会有bug)

1.改写__getitem__函数


 
  1. if torch.cuda.is_available():
  2. data = data.cuda()
  3. label = label.cuda()

代码变为:


 
  1. #得到数据内容和标签
  2. def __getitem__(self, index):
  3. data = torch.Tensor(self.Data[index])
  4. label = torch.IntTensor(self.Label[index])
  5. if torch.cuda.is_available():
  6. data = data.cuda()
  7. label = label.cuda()
  8. return data, label

2.报错啦:

 文字描述为:


 
  1. THCudaCheck FATIHCudaCheck FAIL file=Lc:\n efwile=-builder_3\win-whce:el\\pnyteorwch-\tborucihl\cdsrec\rge_3n\weirinc\StorageSharing.cpp-w helienl\epy=t2or3ch1\ toercrhr\cosrrc=\g71e ne:r ioc\pSteorartagieSohanr niotng .cspupppo line= 231 error=rt7e1d
  2. : operProcess Process -2:
  3. ation not supportedTraceback (most recent call last):
  4. File "D:\Anaconda3\lib\multiprocessing\process.py", line 258, in _bootstrap
  5. self.run()
  6. File "D:\Anaconda3\lib\multiprocessing\process.py", line 93, in run
  7. self._target(*self._args, **self._kwargs)
  8. File "D:\Anaconda3\lib\site-packages\torch\utils\data\dataloader.py", line 110, in _worker_loop
  9. data_queue.put((idx, samples))
  10. Process Process -1:
  11. File "D:\Anaconda3\lib\multiprocessing\queues.py", line 341, in put
  12. obj = _ForkingPickler.dumps(obj)
  13. File "D:\Anaconda3\lib\multiprocessing\reduction.py", line 51, in dumps
  14. cls(buf, protocol).dump(obj)
  15. File "D:\Anaconda3\lib\site-packages\torch\multiprocessing\reductions.py", line 109, in reduce_tensor
  16. (device, handle, storage_size, storage_offset) = storage._share_cuda_()
  17. RuntimeError: cuda runtime error ( 71) : operation not supported at c:\new-builder_3\win-wheel\pytorch\torch\csrc\generic\StorageSharing.cpp: 231
  18. Traceback (most recent call last):
  19. File "D:\Anaconda3\lib\multiprocessing\process.py", line 258, in _bootstrap
  20. self.run()
  21. File "D:\Anaconda3\lib\multiprocessing\process.py", line 93, in run
  22. self._target(*self._args, **self._kwargs)
  23. File "D:\Anaconda3\lib\site-packages\torch\utils\data\dataloader.py", line 110, in _worker_loop
  24. data_queue.put((idx, samples))
  25. File "D:\Anaconda3\lib\multiprocessing\queues.py", line 341, in put
  26. obj = _ForkingPickler.dumps(obj)
  27. File "D:\Anaconda3\lib\multiprocessing\reduction.py", line 51, in dumps
  28. cls(buf, protocol).dump(obj)
  29. File "D:\Anaconda3\lib\site-packages\torch\multiprocessing\reductions.py", line 109, in reduce_tensor
  30. (device, handle, storage_size, storage_offset) = storage._share_cuda_()
  31. RuntimeError: cuda runtime error ( 71) : operation not supported at c:\new-builder_3\win-wheel\pytorch\torch\csrc\generic\StorageSharing.cpp: 231

 

3.那怎么办呢?有两种方法:

(1)只需要将num_workers改成0即可

dataloader = DataLoader.DataLoader(dataset,batch_size= 2, shuffle = False, num_workers= 0)
 

代码变为:


 
  1. import torch
  2. import torch.utils.data.dataset as Dataset
  3. import torch.utils.data.dataloader as DataLoader
  4. import numpy as np
  5. Data = np.asarray([[ 1, 2], [ 3, 4],[ 5, 6], [ 7, 8]])
  6. Label = np.asarray([[ 0], [ 1], [ 0], [ 2]])
  7. #创建子类
  8. class subDataset(Dataset.Dataset):
  9. #初始化,定义数据内容和标签
  10. def __init__(self, Data, Label):
  11. self.Data = Data
  12. self.Label = Label
  13. #返回数据集大小
  14. def __len__(self):
  15. return len(self.Data)
  16. #得到数据内容和标签
  17. def __getitem__(self, index):
  18. data = torch.Tensor(self.Data[index])
  19. label = torch.IntTensor(self.Label[index])
  20. if torch.cuda.is_available():
  21. data = data.cuda()
  22. label = label.cuda()
  23. return data, label
  24. if __name__ == '__main__':
  25. dataset = subDataset(Data, Label)
  26. print(dataset)
  27. print( 'dataset大小为:', dataset.__len__())
  28. print(dataset.__getitem__( 0))
  29. print(dataset[ 0][ 0])
  30. #创建DataLoader迭代器
  31. dataloader = DataLoader.DataLoader(dataset,batch_size= 2, shuffle = False, num_workers= 0)
  32. for i, item in enumerate(dataloader):
  33. print( 'i:', i)
  34. data, label = item
  35. print( 'data:', data)
  36. print( 'label:', label)

结果为:

                       

可以看到多了一个device='cuda:0'

(2)把Tensor放到GPU上的操作放在DataLoader之后,即删除__getitem__函数里的下面内容


 
  1. if torch.cuda.is_available():
  2. data = data.cuda()
  3. label = label.cuda()

并在主函数的for循环里添加删除的语句,代码变为 


 
  1. import torch
  2. import torch.utils.data.dataset as Dataset
  3. import torch.utils.data.dataloader as DataLoader
  4. import numpy as np
  5. Data = np.asarray([[ 1, 2], [ 3, 4],[ 5, 6], [ 7, 8]])
  6. Label = np.asarray([[ 0], [ 1], [ 0], [ 2]])
  7. #创建子类
  8. class subDataset(Dataset.Dataset):
  9. #初始化,定义数据内容和标签
  10. def __init__(self, Data, Label):
  11. self.Data = Data
  12. self.Label = Label
  13. #返回数据集大小
  14. def __len__(self):
  15. return len(self.Data)
  16. #得到数据内容和标签
  17. def __getitem__(self, index):
  18. data = torch.Tensor(self.Data[index])
  19. label = torch.IntTensor(self.Label[index])
  20. return data, label
  21. if __name__ == '__main__':
  22. dataset = subDataset(Data, Label)
  23. print(dataset)
  24. print( 'dataset大小为:', dataset.__len__())
  25. print(dataset.__getitem__( 0))
  26. print(dataset[ 0][ 0])
  27. #创建DataLoader迭代器
  28. dataloader = DataLoader.DataLoader(dataset,batch_size= 2, shuffle = False, num_workers= 8)
  29. for i, item in enumerate(dataloader):
  30. print( 'i:', i)
  31. data, label = item
  32. if torch.cuda.is_available():
  33. data = data.cuda()
  34. label = label.cuda()
  35. print( 'data:', data)
  36. print( 'label:', label)

 结果为

                                                   

五、Dataset和DataLoader总结

1.Dataset是一个抽象类,需要派生一个子类构造数据集,需要改写的方法有__init____getitem__等。

2.DataLoader是一个迭代器,方便我们访问Dataset里的对象,值得注意的num_workers的参数设置:如果放在cpu上跑,可以不管,但是放在GPU上则需要设置为0;或者在DataLoader操作之后将Tensor放在GPU上。

3.数据和标签是tuple元组的形式,使用Dataloader然后使用enumerate函数访问它们


继续下一篇:PyTorch 入门实战(四)——利用Torch.nn构建卷积神经网络

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值