数据处理-10

    数据对于深度学习而言是至关重要的, 丰富、 完整、 规范的数据集往往能训练出效果更佳的网络模型。 本节将首先介绍当前较为主流的公开数据集, 然后从数据的加载、 数据的GPU加速、 数据的可视化3个方面介绍PyTorch的使用方法。

1. 主流公开数据集
    深度学习能够取得快速发展的一个原因是建立在大量数据的基础上, 数据为王毫不夸张。 世界上一些先进的研究机构与公司开源了一些公开数据集, 这些数据集规模较大, 质量较高, 一方面方便研究者利用这些数据训练自己的模型, 同时也为先进的论文研究提供了标准的评测平台。
    数据集随着深度学习算法的提升, 其规模也不断变大, 任务也渐渐地由简单到复杂。 下面简要介绍在物体检测领域较为重要的3个公开数据集。
1)ImageNet数据集
ImageNet数据集首次在2009年计算机视觉与模式识别(CVPR) 会 议上发布, 其目的是促进计算机图像识别的技术发展。 ImageNet数据集
从问世以来, 一直被作为计算机视觉领域最重要的数据集之一, 任何基于ImageNet的技术上的进步都会对计算机视觉领域产生重要的影响。
ImageNet数据集一共有1400多万张图片, 共计2万多个类别, 超过百万的图片有明确的类别标注, 以及图像中物体的位置信息, 如图2.6所示。

ImageNet数据集对应的有一个享誉全球的ImageNet国际计算机视觉挑战赛(ILSVRC) , 该竞赛包含了图像分类、 物体检测与定位、 视
频物体识别等多个领域。 在2012年, Hinton带领的团队利用深度学习算法在分类竞赛中完胜其他对手, 在计算机领域引起了轰动, 进而掀起了
深度学习的浪潮。

 

 

 随后的几年中, 众多公司与知名研究机构展开了激烈的角逐, 陆续诞生了众多先进的算法, 而在2017年的比赛则是最后一届, 以后会往更高的理解层发展。 值得一提的是, 通常我们在训练自己的模型时也经常使用从ImageNet上预训练得到的模型。

2PASCAL VOC数据集

PASCAL VOC为图像分类与物体检测提供了一整套标准的数据集,并从2005年到2012年每年都举行一场图像检测竞赛。 PASCAL全称为Pattern Analysis,Statistical Modelling and Computational Learning, 其中常用的数据集主要有VOC 2007VOC 2012两个版本, VOC 2007中包含了9963张标注过的图片及24640个物体标签。 在VOC 2007之上, VOC2012进一步升级了数据集, 一共有11530张图片, 包含人、 狗、 椅子和桌子等20个物体类别, 图片大小约500×375像素。 VOC整体图像质量较 好, 标注比较完整, 非常适合进行模型的性能测试, 如图2.7所示。

 

 

 PASCAL VOC的另一个贡献在于提供了一套标准的数据集格式, 尤其是对于物体检测领域, 大部分的开源物体检测算法都提供了PASCALVOC的数据接口。 对于物体检测, 有3个重要的文件夹, 具体如下:
·JPEGImages: 包含所有训练与测试的图片。
·Annotations: 存放XML格式的标签数据, 每一个XML文件都对应于JPEGImages文件夹下的一张图片。
·ImageSets: 对于物体检测只需要Main子文件夹, 并在Main文件夹中建立Trainval.txttrain.txtval.txttest.txt, 在各文件中记录相应的图片名即可。

3) COCOCommon Objects in Context) 数据集

COCO是由微软赞助的一个大型数据集, 针对物体检测、 分割、 图 像语义理解和人体关节点等, 拥有超过30万张图片, 200万多个实例及80个物体类别。 在ImageNet竞赛停办后, COCO挑战赛成为了当前物体检测领域最权威的一个标杆。 相比PASCAL VOCCOCO数据集难度更大, 其拥有的小物体更多, 物体大小的跨度也更大, 如图2.8所示 。

 

 

 PASCAL VOC一样, 众多的开源算方法也通常会提供以COCO格式为标准的数据加载方式。 为了更好地使用数据集, COCO也提供了基于LuaPythonMATLABAPI, 具体使用方法可以参考开源代码。
   当然, 随着自动驾驶领域的快速发展, 也出现了众多自动驾驶领域的数据集, 如KITTICityscapeUdacity等, 具体使用方法可以查看相关数据集官网。

2. 数据加载

PyTorch将数据集的处理过程标准化, 提供了Dataset基本的数据类, 并在torchvision中提供了众多数据变换函数, 数据加载的具体过程主要分为3步, 如图2.9所示 。

 

 

 3步的具体功能与实现如下 :

2.1 继承Dataset
     对于数据集的处理, PyTorch提供了torch.utils.data.Dataset这个抽象类, 在使用时只需要继承该类, 并重写__len__()__getitem()__函数,即可以方便地进行数据集的迭代

 1 from torch.utils.data import Dataset
 2 
 3 class my_data(Dataset):
 4 
 5     def __init__(self, image_path, annotation_path, transform =None):
 6         # 初始化,读取数据集
 7 
 8     def __len__(self):
 9         # 获取数据集的总大小
10 
11     def __getitem__(self, id):
12         # 对于指定的id, 读取该数据并返回
View Code

对上述类进行实例化, 即可进行迭代如下:

dataset = my_data("your image path", "your annotation path") # 实例化该类
for data in dataset:
    print(data)
View Code

2.2 数据变换与增强: torchvision.transforms
  第一步虽然将数据集加载到了实例中, 但在实际应用时, 数据集中的图片有可能存在大小不一的情况, 并且原始图片像素RGB值较大( 0~255) , 这些都不利于神经网络的训练收敛, 因此还需要进行一些图像变换工作。 PyTorch为此提供了torchvision.transforms工具包, 可以方便地进行图像缩放、 裁剪、 随机翻转、 填充及张量的归一化等操作,操作对象是PILImage或者Tensor
    如果需要进行多个变换功能, 可以利用transforms.Compose将多个变换整合起来, 并且在实际使用时, 通常会将变换操作集成到Dataset的继承类中。 具体示例如下:

 1 from torchvision import transforms
 2 # 将transforms集成到Dataset类中, 使用Compose将多个变换整合到一起
 3 dataset = my_data("your image path", "your annotation path",transforms =
 4                                     transforms.Compose([
 5                                         transforms.Resize(256) # 将图像最短边缩小至256, 宽高比例不变
 6                                         # 以0.5的概率随机翻转指定的PIL图像
 7                                         transforms.RandomHorizontalFlip()
 8                                         # 将PIL图像转为Tensor, 元素区间从[0, 255]归一到[0, 1]
 9                                         transforms.ToTensor()
10                                         # 进行mean与std为0.5的标准化
11                                         transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
12                                     ]   
13                                     )
14 )
View Code

2.3 继承dataloader

经过前两步已经可以获取每一个变换后的样本, 但是仍然无法进行批量处理、 随机选取等操作, 因此还需torch.utils.data.Dataloader类进一步进行封装, 使用方法如下例所示, 该类需要4个参数, 第1个参数是之前继承了Dataset的实例, 第2个参数是批量batch的大小, 第3个参数是是否打乱数据参数, 第4个参数是使用几个线程来加载数据 。

1 from torch.utils.data import DataLoader
2 
3 dataloader = DataLoader(dataset, batch_size=4, 
4                     shuffle=True, num_workers=4)
5                     
View Code

dataloader是一个可迭代对象, 对该实例进行迭代即可用于训练过程。

1 data_iter  = iter(dataloader)
2 for step in range(iters_per_epoch):
3     data =  next(data_iter)
4     # 将data用于训练网络即可
View Code

3. GPU加速
PyTorch为数据在GPU上运行提供了非常便利的操作。 首先可以使用torch.cuda.is_available()来判断当前环境下GPU是否可用, 其次是对于Tensor和模型, 可以直接调用cuda()方法将数据转移到GPU上运行, 并且可以输入数字来指定具体转移到哪块GPU上运行 .

 1 import torch
 2 from torchvision import models
 3 
 4 a = torch.randn(3,3)
 5 b = models.vgg16()
 6 
 7 if torch.cuda.is_available():
 8      a = a.cuda()
 9 
10      b = b.cuda(1)
11 
12 device = torch.device("cuda: 0")
13 c = torch.randn(3, 3, device=device, requires_grad= True)
View Code

对于在全局指定使用哪一块GPU, 官方给出了两种方法, 首先是在终端执行脚本时直接指定GPU的方式, 如下 :

1 CUDA_VISIBLE_DEVICES=2 python3 train.py
View Code

其次是在脚本中利用函数指定, 如下:

1 import torch
2 torch.cuda.set_device(1)
View Code

官方建议使用第一种方法, 即CUDA_VISIBLE_DEVICE的方式。

在工程应用中, 通常使用torch.nn.DataParallel(module,device_ids)函数来处理多GPU并行计算的问题。 示例如下 :

1 model_gpu = nn.DataParallel(model, device_ids=[0,1])
2 output = model_gpu(input)
View Code

GPU处理的实现方式是, 首先将模型加载到主GPU上, 然后复制模型到各个指定的GPU上, 将输入数据按batch的维度进行划分, 分配每个GPU上独立进行前向计算, 再将得到的损失求和并反向传播更新单个GPU上的参数, 最后将更新后的参数复制到各个GPU上 。

 

posted @ 2020-09-10 20:41  赵家小伙儿  阅读(215)  评论(0编辑  收藏  举报