Pytorch
在PyTorch中读取数据主要设计两个类:Dataset和Dataloader
- Dataset:提供一种方式去获取数据及其label
- 如何获取每一个数据及其label
- 告诉我们总共有多少的数据
- Dataloader:为后面的网络提供不同的数据形式
三种常见的数据组织方式:
- 文件名是标签
- 每个训练文件有对应的标签文件
- 文件名是标签
一、Database类代码
os模块提供各种 Python 程序与操作系统进行交互的接口
listdir()函数
列出指定目录下的所有文件和目录,包括隐藏文件,并以列表方式打印
path.join()函数
将指定的几个路径合在一起
from torch.utils.data import Dataset # util表示通用工具,即导入torch通用工具中的Dataset
from PIL import Image # 读取图片
import os # 关于系统的库
class MyData(Dataset): # 创建Mydata类来继承Dataset
def __init__(self, root_dir, label_dir): # 初始化,可以设置以索引获取图片
self.root_dir = root_dir
self.label_dir = label_dir
self.path = os.path.join(root_dir, label_dir) # 将根目录和label拼接起来
self.img_path = os.listdir(self.path) # 可以获得图片中所有地址作为列表(ant)
def __getitem__(self, idx): # 获取其中每一个图片
img_name = self.img_path[idx] #获取图片名字
img_item_path = os.path.join(self.root_dir, self.label_dir,img_name) # 该图片相对路径
img = Image.open(img_item_path) #读取图片
label = self.label_dir
return img, label
def __len__(self):
return len(self.img_path)
root_dir = "dataset/train" #定义一个相对路径
ants_label_dir = "ants" #获取蚂蚁数据集
bees_label_dir = "bees" # 获取蜜蜂数据集
ants_dataset = MyData(root_dir, ants_label_dir)
bees_dataset = MyData(root_dir, bees_label_dir)
train_dataset = ants_dataset +bees_dataset # 训练数据集为两个数据集相加
利用img,label接收ants_dataset[1]传回来的数据(数列,通过索引访问),再通过img.show()函数可以将图片打开
二、TensorBoard的使用
在pytorch的虚拟环境中输入以下代码安装tensorboard
pip install tensorboard
1、add_scalar()的使用
代码如下
from torch.utils.tensorboard import SummaryWriter # 导入SummaryWriter
writer = SummaryWriter("logs") #生成logs文件,包含事件文件
for i in range(100): #事件文件的内容
writer.add_scalar("y=x", i, i)
writer.close()
在项目中生成logs文件
在终端中输入
tensorboard --logdir=事件文件所在的文件夹名
在以上代码后输入 --port=参数,修改参数即可更换端口
点击网址即可进入tensorboard中查看
2、add_image()的使用
先利用numpy.array(),对PIL图片进行转换即可获得add_image()所需要的数据类型
from torch.utils.tensorboard import SummaryWriter
import numpy as np #导入numpy
from PIL import Image
writer = SummaryWriter("logs")
image_path = "D:\\Androws\\pythonProject1\\hymenoptera_data\\train\\ants\\0013035.jpg" # 图片地址
img_PIL = Image.open(image_path)
img_array = np.array(img_PIL) #将PIL转换为numpy
writer.add_image("test", img_array,1, dataformats='HWC')
writer.close()
注:从PIL到numpy,需要再add_image()中指定shape中每一个数字/维表示的含义
H表示高度,W表示宽度,C表示图片显示通道
再打开TensorBoard即可显示图像
可以通过修改step实现在同一tag下中添加多个图片
三、Transforms的使用
1、transforms结构及用法
transforms是一个工具箱,我们利用这个工具箱创建自己的工具,再利用自己的工具得到想要的结果
2、transforms.ToTensor
(1)、transforms该如何使用
from PIL import Image
from torchvision import transforms
img_path = "hymenoptera_data/train/ants/0013035.jpg"
img = Image.open(img_path)
tensor_trans = transforms.ToTensor() # 创建class,返回ToTensor的对象,相当于函数,直接调用实例化的功能
tensor_img = tensor_trans(img) # 需要传入图片类型的数据,转换为tensor类
print(tensor_img)
得到tensor类的数据结果
类似于使用魔法方法__call__
也可使用opencv进行操作获得numpy型的数据类型
import cv2
cv_img = cv2.imread(img_path)
(2)、为什么需要Tensor数据类型
Tensor数据类型包装了神经网络所需要的理论基础的参数,所以需要将数据类型转换为Tensor类才能进行训练
3、在Tensorboard中打开
与Tensordboard的使用中的方法相同
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
img_path = "hymenoptera_data/train/ants/0013035.jpg"
img = Image.open(img_path)
writer = SummaryWriter("logs")
tensor_trans = transforms.ToTensor() # 创建class,返回ToTensor的对象
tensor_img = tensor_trans(img) # 需要传入图片类型的数据,转换为tensor类
writer.add_image("Tensor_img", tensor_img)
writer.close()
四、常见的Transforms
1、ToTensor
与上述结果相同
# ToTensor
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("Tensor_img", img_tensor)
2、Normalize
代码如下
# Normalize
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize", img_norm)
运行结果
在Tensorboard中打开得到以下图片
归一化是为了消除奇异值,及样本数据中与其他数据相比特别大或特别小的数据 这样可以加快训练速度
3、Resize
简单来说就是调整PILImage对象的尺寸,注意不能是用io.imread或者cv2.imread读取的图片,这两种方法得到的是ndarray。
# Resize
print(img.size)
trans_resize = transforms.Resize([512, 512])
# img PIL -> resize -> img_resize PIL
img_resize = trans_resize(img)
# img_resize PIL -> totensor -> img_resize tensor
img_resize = trans_totensor(img_resize)
writer.add_image("Resize",img_resize,0)
4、Compose
这个类的主要作用是串联多个图片变换的操作。相当于流水线打包
# Compose - resize - 2
trans_resize_2 = transforms.Resize(512)
# PIL -> PIL -> tensor
trans_compose = transforms.Compose([trans_resize_2, trans_totensor])
img_resize_2 = trans_compose(img)
writer.add_image("Resize", img_resize_2, 1)
Compose()中的参数需要是一个列表,数据需要是transforms类型,所以得到Compose([transforms参数1, transforms参数2])
5、RandomCrop
将给定图像随机裁剪为不同的大小和宽高比,然后缩放所裁剪得到的图像为制定的大小;(即先随机采集,然后对裁剪得到的图像缩放为同一大小),
# RandomCrop
trans_random = transforms.RandomCrop(512)
trans_compose_2 = transforms.Compose([trans_random, trans_totensor])
for i in range(10):
img_crop = trans_compose_2(img)
writer.add_image("RandomCrop", img_crop, i)
五、torchvision中的数据集使用
torchvision是pytorch的一个图形库,主要用来构建计算机视觉模型。以下是torchvision的基本构成:
1. torchvision.datasets: 一些加载数据的函数及常用的数据集接口;
2. torchvision.models:包含常用的模型结构(含预训练模型),例如AlexNet、VGG、ResNet等;
3. torchvision.transforms:常用的图片变换,例如裁剪、旋转等;
4. torchvision.utils: 其他的一些有用的方法。
在官网中可看到torchvision模块中包含的数据集。主要的数据集如下所示:
现在以CIFAR10数据集的使用为例
首先下载数据集
import torchvision
train_set = torchvision.datasets.CIFAR10(root="./dataset", train=True, download=True)
test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, download=True)
然后与TensorBoard进行联动
import torchvision
from torch.utils.tensorboard import SummaryWriter
dataset_transform = torchvision.transforms.Compose([ # 用Compose打包
torchvision.transforms.ToTensor()
])
train_set = torchvision.datasets.CIFAR10(root="./dataset", train=True, transform=dataset_transform, download=True)
test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, transform=dataset_transform, download=True)
writer = SummaryWriter("p10")
for i in range(10):
img, target =test_set[i]
writer.add_image("test_set", img, i)
writer.close()
六、Dataloader的使用
DataLoader是Pytorch中用来处理模型输入数据的一个工具类。组合了数据集(dataset) + 采样器(sampler),并在数据集上提供单线程或多线程(num_workers )的可迭代对象。在DataLoader中有多个参数,这些参数中重要的几个参数的含义说明如下:
1. epoch:所有的训练样本输入到模型中称为一个epoch;
2. iteration:一批样本输入到模型中,成为一个Iteration;
3. batchszie:批大小,决定一个epoch有多少个Iteration;
4. 迭代次数(iteration)=样本总数(epoch)/批尺寸(batchszie)
5. dataset (Dataset) – 决定数据从哪读取或者从何读取;
6. batch_size (python:int, optional) – 批尺寸(每次训练样本个数,默认为1)
7. shuffle (bool, optional) –每一个 epoch是否为乱序 (default: False);
8. num_workers (python:int, optional) – 是否多进程读取数据(默认为0);
9. drop_last (bool, optional) – 当样本数不能被batchsize整除时,最后一批数据是否舍弃(default: False)
10. pin_memory(bool, optional) - 如果为True会将数据放置到GPU上去(默认为false)
继续以CIFAR10数据集的使用为例,与TensorBoard联动
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
# 准备测试数据集
from torch.utils.data import DataLoader
test_data = torchvision.datasets.CIFAR10(root="./dataset", train=False, transform=torchvision.transforms.ToTensor())
test_loader = DataLoader(dataset=test_data, batch_size=4, shuffle=True, num_workers=0, drop_last=False)
writer = SummaryWriter("dataloader")
step = 0
# 测试数据集中第一张图片及target
img, target = test_data[0]
for data in test_loader:
imgs, targets = data
writer.add_images("test_data", imgs, step)
step += 1
writer.close()
注:add_image要加s,否则会报错