【PyTorch】(二)----数据集加载及可视化

打印 上一主题 下一主题

主题 651|帖子 651|积分 1953

该系列笔记主要参考了小土堆的视频教程,传送门:P1. PyTorch环境的配置及安装(Configuration and Installation of PyTorch)【PyTorch教程】_哔哩哔哩_bilibili
涉及到的文件/数据集网盘:
链接:https://pan.baidu.com/s/1aZmXokdpbA97qQ2kHvx_JQ?pwd=1023
提取码:1023
Dataset加载数据

加载数据最主要的就是获取数据及其label,但是在加载不同的数据集时,碰面临相同的问题:


  • 如何获取每一个数据及其label
  • 需要知道有几个数据
Dataset是torch.utils.data下的一个工具,它可以资助我们办理上述两个问题,学习一门新技术的时候,假如你有充足的英语基础或者熟练使用翻译软件,我会保举你从看源码开始入手,这是一个非常好的习惯。
下面是Dataset的源码中的形貌:
  1. class Dataset(Generic[T_co]):
  2.     r"""An abstract class representing a :class:`Dataset`.
  3.     All datasets that represent a map from keys to data samples should subclass
  4.     it. All subclasses should overwrite :meth:`__getitem__`, supporting fetching a
  5.     data sample for a given key. Subclasses could also optionally overwrite
  6.     :meth:`__len__`, which is expected to return the size of the dataset by many
  7.     :class:`~torch.utils.data.Sampler` implementations and the default options
  8.     of :class:`~torch.utils.data.DataLoader`. Subclasses could also
  9.     optionally implement :meth:`__getitems__`, for speedup batched samples
  10.     loading. This method accepts list of indices of samples of batch and returns
  11.     list of samples.
复制代码
大致翻译一下主要内容:全部的子类必须重写_getitem_方法,子类也可以选择重写_len_ 方法。这两个方法就可以办理上述提出的两个问题
【代码示例】将下载好的练手数据集(网盘中的dataset)放在项目目次下,起首观察数据集的目次结构,数据集起首分为train和val两部分,train部分用于练习集数据,val部分用于测试集数据。两者子目次下又分为ants和bees两类数据,每类数据下面即为图片数据,那么ants和bees就可以作为我们的label(标签)使用。此处我们创建自定义的Dataset读取详细的数据。
  1. from torch.utils.data import Dataset
  2. from PIL import Image   # 用于读取图片信息
  3. import os
  4. # 自定义一个MyData继承自Dataset
  5. class MyData(Dataset):
  6.     def __init__(self, root_dir, label_dir):
  7.         self.root_dir = root_dir
  8.         self.label_dir = label_dir
  9.         self.path = os.path.join(self.root_dir, self.label_dir)   # 拼接两个地址
  10.         self.img_path = os.listdir(self.path)   # os.listdir 将目录中的所有内容存入列表中
  11.     def __getitem__(self, index) :
  12.         img_name = self.img_path[index]   # 根据索引去除列表中的所有名字
  13.         img_item_path = os.path.join(self.path, img_name)   # 拼接当前的目录和具体的图片名字
  14.         # getitem的作用就是获取每一个对象和label并返回
  15.         img = Image.open(img_item_path)
  16.         label = self.label_dir
  17.         return img, label
  18.     def __len__(self):
  19.         return len(self.img_path)
  20. root_dir = "dataset/train"
  21. ants_label_dir = "ants"
  22. bees_label_dir = "bees"
  23. ants_dataset = MyData(root_dir, ants_label_dir)
  24. bees_dataset = MyData(root_dir, bees_label_dir)
  25. train_dataset = ants_dataset + bees_dataset
  26. img, label = train_dataset[0]
  27. img.show()
  28. print(label)
  29. print(ants_dataset.__len__())
  30. # 因为ants的长度为124,所以下表第124个数据应该为bee
  31. img, label = train_dataset[124]
  32. img.show()
  33. print(label)
复制代码
运行结果:
  1. ants
  2. 124
  3. bees
复制代码
熟悉上述代码之后可以自己编写建立一个测试集
TensorBoard可视化

TensorBoard 是 TensorFlow 提供的一个强盛的可视化工具,但它不但仅局限于 TensorFlow,也可以用于其他深度学习框架,如 PyTorch。TensorBoard 的主要目标是资助研究人员和开发人员更好地明白和调试机器学习模子,以及监控练习过程。
在PyTorch中使用torch.utils.tensorboard.SummaryWriter 类来图形数据写入到日记中,然后在命令行中启动TensorBoard服务并指定读取的日记文件
假如多次执行代码且没有修改不同的图片形貌信息(tag),则会出现杂乱的画面,这种环境可以把logs文件删除,然后重新运行代码即可。
在TensorBoard中展示函数图像

可以使用SummaryWriter类的add_scalar() 方法在TensorBoard中画函数图像,其函数语法如下:
  1. writer.add_scalar(tag, scalar_value, global_step=None)
  2. # tag (str): 这是一个字符串,用于标识记录的是什么数据。例如,你可以使用 "Loss" 或 "Accuracy" 作为标签来区分不同的数据序列。
  3. # scalar_value (float): 要记录的标量值。这个值可以是你想跟踪的任何单个数值,比如训练损失或者验证精度。
  4. # global_step (int, optional): 这是一个可选参数,用来指定当前的全局步数。这对于按步骤跟踪进度非常有帮助,特别是在训练循环中。默认值是 None,此时会自动递增步数。
复制代码
【代码示例】使用SummaryWriter和TensorBoard可视化工具画出函数y=2x的图像并检察
  1. writer = SummaryWriter("logs")   #“logs”为指定的存放日志文件的目录路径
  2. # 画出y=2x的图像
  3. for i in range(100):
  4.     writer.add_scalar("y=2x", 2*i, i)  # "y=2x"作为图片的描述信息
  5.    
  6. writer.close() # 关闭
复制代码
在终端命令行中启动TensorBoard服务:port指定端口
  1. tensorboard --logdir=path/to/log_directory [--port=6006]
复制代码
然后点击默认的端口链接,进入前端页面

在左上角选择SCALARS, 即可看到我们刚刚画的样例图
origin_url=D%3A%2Fdocument%2FMachine%20Learning%2Fpytorch%2Fimgs%2F3.png&pos_id=img-DjwI6WjC-1717168151301)
在tensorboard中展示图片

上面的代码中,通过writer.add_scalar我们展示了自定义的标量(函数)图片,假如需要使用tensorboard展示自定义图片则需要使用writer.add_image方法,下面是其根本语法:
  1. writer.add_image(tag, img_tensor, global_step=None, dataformats='CHW')
  2. # tag (str): 图像的标签,用于在TensorBoard中区分不同的图像序列。
  3. # img_tensor (Tensor or numpy.array): 要记录的图像数据。它应该是一个形状符合预期格式的张量或NumPy数组。格式可以是 (C, H, W) 或 (H, W, C),具体取决于 dataformats 参数。
  4. # global_step (int, optional): 同样是一个可选参数,用于指定当前的全局步数,有助于按步骤查看图像变化。
  5. # dataformats (str, optional): 指定图像数据的维度顺序,默认为 'CHW'(通道、高度、宽度)。如果你的数据格式是 (H, W, C),则应设置为 'HWC'。
复制代码
img_tensor为你需要展示的图片对象,必须为Tensor范例或者ndarray范例,Tensor范例会在背面详细解说。
【代码示例】添加一张图片到SummaryWriter日记中,并使用tensorboard服务举行检察
  1. from torch.utils.tensorboard import SummaryWriter
  2. from PIL import Image
  3. import torchvision
  4. writer = SummaryWriter("logs")
  5. # # y = 2x
  6. # for i in range(100):
  7. #     writer.add_scalar("y=2x", 3*i, i)
  8. # 展示图片
  9. img_path="dataset/train/ants/0013035.jpg"
  10. img = Image.open(img_path)
  11. myTotensor = torchvision.transforms.PILToTensor()
  12. img_tensor = myTotensor(img)
  13. writer.add_image("img_test",img_tensor)
  14. writer.close()
复制代码
在命令行中启动tensor服务后,在浏览器中点击左上角IMAGES举行检察

transform

transform是torchvision提供的工具包,主要用来对图像信息举行处理,包括归一化,裁剪等功能。
ToTensor

ToTensor用于将PIL范例图像或者ndarray范例图像转为tensor范例,注意ToTensor是一个类,只用将着实例化后才气举行调用,不能像普通方法直接举行传参调用。
为什么需要使用tensor范例图像?
在python控制台中创建一个tensor范例对象并观察即可发现,tensor范例图像多出了一些属性,如trackback、grad等,这些属性主要用于神经网络的反向传播之中,资助模子举行快速迭代。

使用opencv读取的图片范例为nparray,Image读取的为PIL,使用这两种常用方法读取的图片信息均可使用ToTensor方法将其转换为tensor范例后再举行后续的神经网络处理。
【代码示例】分别使用opencv和Image读取图片,并输出它们的范例
起首在虚拟环境中安装opencv,打开终端,先确保是否在正确的虚拟环境当中,然后使用
  1. pip install opencv-python
复制代码
安装完毕后,验证是否安装正确
  1. pip list
复制代码
  1. from PIL import Image
  2. import torchvision
  3. import cv2
  4. img_path="dataset/train/ants/0013035.jpg"
  5. img_PIL = Image.open(img_path)
  6. print("img_PIL`s type : " , type(img_PIL))
  7. img_cv = cv2.imread(img_path)
  8. print("img_cv`s type : " , type(img_cv))
  9. myTotensor = torchvision.transforms.ToTensor()
  10. img_tensor1 = myTotensor(img_PIL)
  11. img_tensor2 = myTotensor(img_cv)
  12. print("img_tensor1`s type : " , type(img_tensor1))
  13. print("img_tensor2`s type : " , type(img_tensor2))
复制代码
输出结果:
  1. img_PIL`s type :  <class 'PIL.JpegImagePlugin.JpegImageFile'>
  2. img_cv`s type :  <class 'numpy.ndarray'>
  3. img_tensor1`s type :  <class 'torch.Tensor'>
  4. img_tensor2`s type :  <class 'torch.Tensor'>
复制代码
Normalize

Normalize用于将一个tensor范例的图像举行规范化处理,其主要参数为mean(均值)和std(方差),使用(input[channel] - mean[channel]) / std[channel] 公式举行处理。
图片的Normalize处理主要应用于深度学习、机器学习和盘算机视觉使命的预处理阶段,它的目标是为了使得数据具有更好的数值属性,从而提高模子练习的服从和结果。Normalize的详细作用和目标主要包括以下几点:

  • 归一化:通过减去均值并除以标准差(或其它方式),将图片像素值调解到一个特定的范围内(通常是0-1之间,或者-1到1之间)。如许做的利益是可以统一输入数据的尺度,减少不同图片间因亮度、对比度差异带来的影响。
  • 加速练习过程:归一化后的数据可以使梯度下降等优化算法更加稳固高效,由于特性值范围缩小后,学习率可以设置得更大而不至于导致权重更新过猛,跳出最优解区域。
  • 提拔模子性能:标准化数据可以减轻权重初始化对模子练习的影响,使得模子更容易收敛,并大概到达更高的正确率。
  • 减少过拟合:某些归一化技术(如Batch Normalization)还能起到正则化的作用,有助于减少过拟合征象,使模子泛化本领更强。
  • 简化参数学习:通过Normalization,可以让网络中的权重在练习初期有相近的尺度,这有助于优化算法更快地找到符合的权重值。
总之, Normalize处理是图像处理和深度学习范畴中一个非常重要的预处理步调,它能够显著影响模子的练习速度和最终性能。
【代码示例】对图像举行规范化处理,并使用tensorboard可视化举行展示
  1. from PIL import Image
  2. import torchvision
  3. from torch.utils.tensorboard import SummaryWriter
  4. img_path="dataset/train/ants/0013035.jpg"
  5. # 使用Image读取PIL类型的图像
  6. img_PIL = Image.open(img_path)
  7. # 使用ToTensor将PIL转为tensor类型
  8. myTotensor = torchvision.transforms.ToTensor()
  9. img_tensor = myTotensor(img_PIL)
  10. # 将tensor图片进行规范化处理
  11. myNormalize = torchvision.transforms.Normalize([0.5,0.5,0.5], [1,1,1])
  12. img_normalize = myNormalize(img_tensor)
  13. # 可视化
  14. writter = SummaryWriter("logs")
  15. writter.add_image('原图:', img_tensor)
  16. writter.add_image('规范化后:', img_normalize)
  17. writter.close()
复制代码
运行结果:

resize

对于图片尺寸的处理也是图像增强和图像预处理的一个重要步调,在transform中,用resize举行实现
resize的参数可以有两种表示方法,假如传入了两个数字,则宽高分别变为指定的大小;假如只传入一个数字,则使用最小边匹配,另一条变举行等比缩放
【代码示例】对图片resize操作,并举行可视化展示
  1. from PIL import Image
  2. import torchvision
  3. from torch.utils.tensorboard import SummaryWriter
  4. img_path="dataset/train/ants/0013035.jpg"
  5. # 使用Image读取PIL类型的图像
  6. img_PIL = Image.open(img_path)
  7. # 使用ToTensor将PIL转为tensor类型
  8. myTotensor = torchvision.transforms.ToTensor()
  9. img_tensor = myTotensor(img_PIL)
  10. # 将tensor图片进行resize
  11. myResize = torchvision.transforms.Resize((80, 100))
  12. img_resize = myResize(img_tensor)
  13. # 只传一个参数
  14. myResize2 = torchvision.transforms.Resize((50))
  15. img_resize2 = myResize2(img_tensor)
  16. # 可视化
  17. writter = SummaryWriter("logs")
  18. writter.add_image('原图:', img_tensor)
  19. writter.add_image('两个参数变形后:', img_resize)
  20. writter.add_image('一个参数变形后:', img_resize2)
  21. writter.close()
复制代码

Compose

在上述的多个例子中,我们通常会使用两个transform工具,常常是先使用ToTensor方法将图片转化为Tensor范例,然后再使用别的工具处理Tensor范例数据。Compose的作用就是将两个工具归并起来,让我们的代码更加简洁。
【代码示例】使用compose组合ToTensor和normalize
  1. from PIL import Image
  2. import torchvision
  3. from torch.utils.tensorboard import SummaryWriter
  4. img_path="dataset/train/ants/0013035.jpg"
  5. # 使用Image读取PIL类型的图像
  6. img_PIL = Image.open(img_path)
  7. my_totensor = torchvision.transforms.ToTensor()
  8. my_normalize = torchvision.transforms.Normalize([0.5,0.5,0.5], [1,1,1])
  9. mycompose = torchvision.transforms.Compose(
  10.     (my_totensor,my_normalize)
  11. )
  12. img_compose = mycompose(img_PIL)
  13. # 可视化
  14. writter = SummaryWriter("logs")
  15. writter.add_image('compose:', img_compose)
  16. writter.close()
复制代码
randomcrop

上面已经介绍了很多工具,这里的randomcrop是举行随机裁剪的,盼望各人可以通过自学看源码等方式覅掌握这个工具,下面我只给出一个使用它的简单例子
  1. from PIL import Image
  2. import torchvision
  3. from torch.utils.tensorboard import SummaryWriter
  4. img_path="dataset/train/ants/0013035.jpg"
  5. writter = SummaryWriter("logs")
  6. # 使用Image读取PIL类型的图像
  7. img_PIL = Image.open(img_path)
  8. my_totensor = torchvision.transforms.ToTensor()
  9. my_randomcrop = torchvision.transforms.RandomCrop((100.200))
  10. mycompose = torchvision.transforms.Compose(
  11.     (my_totensor,my_randomcrop)
  12. )
  13. for i in range(10):
  14.     img_randomcrop = mycompose(img_PIL)
  15.     writter.add_image('random:',img_randomcrop,global_step=i)
  16. writter.close()
复制代码
torchvision数据集

在pytorch官网页面Datasets — Torchvision 0.18 documentation (pytorch.org),中详细列出了torchvision中的一些不同功能使用到的公共数据集的,如下图为图像分类使用的数据集

点进去之后可以看到数据集的详细信息,包括数据集大小、分类范例、以及下载方式等,接下来我都会使用CIFAR10数据集为例举行展示,由于其数据量不是很大,下载到当地后对存储的压力不是很大,
CIFAR10数据练习集主要包含了50000张10种类别的32*32图片信息,用于图像分类的使用,它的类别编号如下:
{‘airplane’: 0, ‘automobile’: 1, ‘bird’: 2, ‘cat’: 3, ‘deer’: 4, ‘dog’: 5, ‘frog’: 6, ‘horse’: 7, ‘ship’: 8, ‘truck’: 9}
下载CIFAR10数据集的语法如下:
  1. dataset = torchvision.datasets.CIFAR10(root=“./dataset”, train = True, download = True,transform=torchvision.transforms.ToTensor())
  2. # CIFAR10为数据集的名字
  3. # root为存放数据的目录
  4. # train表示是否为训练数据集
  5. # download表示是否将数据下载到本地
  6. # transform可以指定如何对数据集进行预处理,通常都是使用ToTensor
复制代码
运行后得到的下载链接可以放到迅雷中使用,下载速度更快,下载后将压缩文件复制到当前的目次下面即可,体系再次运行时会对其举行解压使用

第一次下载后,纵然继续打开download运行,体系在检测到之后就不需要继续举行下载了,以是download常常处于打开状态后续也无需举行修改
DataLoader

datalorader主要设置从DataSet中举行取数据的方式,比如每次取多少个数据,是否随机取数等。其根本语法如下:
  1. test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)
  2. # dataset指定从哪个DataSet中进行读取数据
  3. # batch_size指定每次读取数据的多少
  4. # shuffle指定是否进行随机抽取
  5. # num_workers指定的多线程数量,在Windows中设置大于0可能出问题
  6. # drop_last表示是否保留最后余出的几个数据,比如一共有1024张图片,batch_size设置为100,最终会余出24个数据
复制代码
【代码示例】使用DataLoader读取CIFAR10数据集,每次读取64张图片
  1. import torchvision
  2. # 准备的测试数据集
  3. from torch.utils.data import DataLoader
  4. from torch.utils.tensorboard import SummaryWriter
  5. test_data = torchvision.datasets.CIFAR10("./dataset/CIFAR10", train=False, transform=torchvision.transforms.ToTensor())
  6. test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)
  7. # 测试数据集中第一张图片及target
  8. img, target = test_data[0]
  9. print(img.shape)
  10. print(target)
  11. writer = SummaryWriter("dataloader")
  12. for epoch in range(2):
  13.     step = 0
  14.     for data in test_loader:
  15.         imgs, targets = data
  16.         # print(imgs.shape)
  17.         # print(targets)
  18.         writer.add_images("Epoch: {}".format(epoch), imgs, step)
  19.         step = step + 1
  20. writer.close()
复制代码
运行结果:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

渣渣兔

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表