目录
#Pytorch加载数据
# read_data.py
# rename_dataset.py
# test_tensorboard.py
# test_transform.py
# dataset_transform.py
# test_dataloader.py
# 读取数据涉及两个类:Dataset和DataLoader | |
Dataset提供一种方式去获取数据及其对应的真实label值; | DataLoader为网络提供不同的数据形式 |
Dataset告诉程序数据集存在什么位置、每个数据是什么; | Dataloader将数据加载到神经网络中,从Dataset中取数据,怎么取、取多少由DataLoader的参数来控制 |
# Dataset主要实现什么样的功能? |
#①如何获取每一个数据及其label;②告诉我们总共有多少数据 |
# 如何使用Dataset? |
#help(Dataset) # All datasets that represent a map from keys to data samples should subclass it. # All subclasses should overwrite :meth:`__getitem__`, supporting fetching a data sample for a given key. |
#代码文件概述 |
# read_data.py(自定义Dataset)\rename_dataset.py(更改dataset文件存储形式) # dataset_transform.py(torchvision dataset与图像变换、可视化的结合) # test_dataloader.py(DataLoader的使用) |
from torch.utils.data import Dataset
from PIL import Image #Python Image Library
import os
#继承Dataset类
class LoadData(Dataset):
# 初始化,读取数据集 根据这个类创建一个特例示例的时候会运行的一个类
#一般会为整个class提供全局变量,为后面的函数提供所需要的量
def __init__(self,root_dir,label_dir):
self.root_dir=root_dir #实例化:root_dir=“dataset/train”
self.label_dir=label_dir #实例化:label是ants或bees label_dir="ants"
self.path=os.path.join(self.root_dir,self.label_dir) #获取数据所在文件夹地址
self.img_path_list=os.listdir(self.path) #将文件夹下的数据所在地址形成一个列表
# 对于指定id,获取该数据并返回
#在init中创建数据地址列表
def __getitem__(self, index):
img_name=self.img_path_list[index]
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_list)
#实例化
root_dir="dataset/train"
ants_label_dir="ants"
bees_label_dir="bees"
ants_dataset=LoadData(root_dir,ants_label_dir)
bees_dataset=LoadData(root_dir,bees_label_dir)
train_dataset=ants_dataset+bees_dataset
print(ants_dataset[0])
#常见数据集的形式是将数据与label分开存放
#并且两个文件夹以相同文件名命名 label文件为txt格式
import os
# root_dir="dataset/train"
# target_dir="ants"
# img_path=os.listdir(os.path.join(root_dir,target_dir))
# label=target_dir.split("_")[0]
# out_dir="ants_label"
# for i in img_path:
# file_name=i.split('.jpg')[0]
# with open(os.path.join(root_dir,out_dir,"{}.txt".format(file_name)),'w') as f:
# f.write(label)
root_dir="dataset/train"
target_dir="bees"
img_path=os.listdir(os.path.join(root_dir,target_dir))
label=target_dir.split("_")[0]
out_dir="bees_label"
for i in img_path:
file_name=i.split('.jpg')[0]
with open(os.path.join(root_dir,out_dir,"{}.txt".format(file_name)),'w') as f:
f.write(label)
from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image
writer=SummaryWriter("logs")
#运行后产生文件在logs中
#打开logs文件:在Terminal命令台输入 tensorboard --logdir=事件文件所在文件夹名 --port=指定端口 避免和其他人一样
# 两个重要方法
# ①writer.add_image()
# ②writer.add_scalar() #标量、数
# def add_image(self,
# tag: str, 显示title
# img_tensor: Any, 图像类型:torch.Tensor, numpy.ndarray, or string/blobname
# global_step: int = None, 纵轴
# walltime: float = None,
# dataformats: str = "CHW") -> None 指定shape中每一维度的含义 e.g. dataformats='HWC'(高度、宽度、通道)
#图片格式及打开方式
# ①PIL Image.open()
# ②tensor transforms.ToTensor()
# ③narrays cv2.imread()
#img_tensor参数 图片类型的处理:
# ①如何由常见的图片类型PIL转换为torch.Tensor类型:利用numpy.array()对PIL图片进行转换;
# ②利用OpenCV读取图片,获得numpy型图片数据(narrays) # pip install opencv-python
# ①PIL->torc.Tensor
image_path="dataset/train/ants/0013035.jpg"
img_PIL=Image.open(image_path)
img_array=np.array(img_PIL)
print(type(img_array))
print(img_array.shape)
writer.add_image("test",img_array,1,dataformats='HWC')#Note:从PIL到numpy需要在add_image()中指定shape中每一个数字/维表示的含义
#②Opencv读取图片->numpy
import cv2
img_cv=cv2.imread(image_path)
writer.add_image("train",img_cv,1,dataformats='HWC')
# def add_scalar(self,
# tag: str, 显示图像的title
# scalar_value: Any, 横轴
# global_step: int = None, 纵轴
# walltime: float = None,
# new_style: bool = False,
# double_precision: bool = False) -> None
#y=2x
for i in range(100):
writer.add_scalar("y=2x",2*i,i)
writer.close()
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
# transforms结构及用法
#transforms.py相当于工具箱 里面不同的class相当于工具 例如:totensor、resize等等
#transforms的使用:特定格式的图片根据工具箱创建具体的工具(初始化/实例化)后,使用工具(调用方法),输出我们想要图片的结果(预期图片变换)
#transforms在python中的用法 其中比较重要的一个概念是Tensor数据类型
#通过transform.ToTensor解决两个问题:
# ①transforms该如何使用(python)
# ②为什么我们需要Tensor数据类型
#summary
#多看官方文档;关注每个方法class的输入输出参数类型;关注方法需要什么参数;可以通过print/debug查看输出数据类型print()/print(type())
#绝对路径 D:\PycharmProjects\pythonProject\dataset\train\ants\5650366_e22b7e1065.jpg
#相对路径 dataset/train/ants/5650366_e22b7e1065.jpg
img_path="dataset/train/ants/5650366_e22b7e1065.jpg"
img=Image.open(img_path)
writer=SummaryWriter("logs")
# # # ToTensor使用
# Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor.
#方法①
tensor_trans=transforms.ToTensor()
img_tensor=tensor_trans(img)
print(img_tensor)
#方法②
# img_tensor=transforms.ToTensor().__call__(img)
# print(img_tensor)
# 方法③
# img_tensor=transforms.ToTensor()(img)
# print(img_tensor)
writer.add_image("img_ToTensor",img_tensor)
#在test_tensorboard中使用了利用numpy将PIL图片转换为torch.Tensor类型方法;
# 在这里直接调用transforms.ToTensor()中的call方法实现
# # # Normalize使用
#Normalize a tensor image with mean and standard deviation
# output[channel] = (input[channel] - mean[channel]) / std[channel]=2*input-1
#将input限定为[0,1] ,则output会限定在[-1,1]
print(img_tensor[0][0][0])
trans_norm=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])#3 channes mean and standard deviation 可以随意设定
img_norm=trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("img_Normalize",img_norm,0)
trans_norm=transforms.Normalize([1,3,5],[2,1,1])#3 channes mean and standard deviation 可以随意设定
img_norm=trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("img_Normalize",img_norm,1)
trans_norm=transforms.Normalize([6,2,5],[3,4,1])#3 channes mean and standard deviation 可以随意设定
img_norm=trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("img_Normalize",img_norm,2)
# # # Resize使用
print(img.size)
#img_PIL -> resize -> img_resize PIL
trans_resize=transforms.Resize((512,512))
img_resize=trans_resize(img)
print(img_resize) #PIL类型
#img_resize ->totensor ->img_resize tensor
img_resize=tensor_trans(img_resize)
print(img_resize)#tensor类型
writer.add_image("img_Resize",img_resize,0)
print(img_resize)
# # #Compose()使用
#Composes several transforms together.
#Compose()中的参数需要是一个列表,python中列表的表示形式为[数据1,数据2...];Compose中数据需要是transforms类型
#因此Compose([transforms参数1,transforms参数2,...])
#Note:Compose中transforms参数的输入输出匹配原则:后一个变换所需的输入类型要与前一个变换的输出类型匹配
# # # Compose-resize-2
# #利用Compose将Resize与ToTensor变换一起实现
# Resize只有一个参数时 transforms.Resize(x)其表示将短边缩放至x,长宽比保持不变
trans_resize_2=transforms.Resize(512)
#PIL(trans_resize_2输入) -> PIL(trans_resize_2输出、tensor_trans输入) -> tensor(tensor_trans输出)
trans_compose=transforms.Compose([trans_resize_2,tensor_trans])
img_resize_2=trans_compose(img)
writer.add_image("img_Resize",img_resize_2,1)
# # #RandomCrop使用
trans_random=transforms.RandomCrop(100)
trans_compose_2=transforms.Compose([trans_random,tensor_trans])
for i in range(10):
img_crop=trans_compose_2(img)
writer.add_image("img_RandomCrop",img_crop,i)
writer.close()
#可以在pytorch官网查看torchvision的官方文档
#左侧栏改为v0.9.0可看到与土堆相同的界面
#查看官方文档中数据集所需要的参数及含义
#在pytorch中引用下载即可
#以torchvision中的CIFAR10数据集为例
import torchvision
from torch.utils.tensorboard import SummaryWriter
# # #①dataset应用transforms前
# train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True)
# test_set=torchvision.datasets.CIFAR10(root="./dataset",train=False,download=True)
# print(train_set[0]) #数据集应用transforms前,此处打印出的信息为img_PIL
# print(test_set.classes) #数据集类别列表
#
# img,target=test_set[0]#数据集中的数据组成为img和target两部分
# print(img)
# print(target) #target是类别对应的数字/索引
# print(test_set.classes[target]) #根据索引打印出特定数据对应类别
# img.show()
# # #②dataset应用transforms后
#将transforms应用到数据集中的每一张图片
dataset_transform=torchvision.transforms.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)
print(test_set[0])#将transforms应用到数据集后,此处打印出的信息为img_tensor
#③结合tensorboard使用
writer=SummaryWriter("logs")
for i in range(10):
img,target=test_set[i]
writer.add_image("test_set",img,i)
writer.close()
#DataLoder 参数含义
# dataset (Dataset) – dataset from which to load the data.
# batch_size (int, optional) – how many samples per batch to load (default: 1).
# shuffle (bool, optional) – set to True to have the data reshuffled at every epoch (default: False).是否打乱顺序
# num_workers (int, optional) 数据加载子进程数目 取0时表示只有一个主进程
# drop_last (bool, optional) 是否舍去没有整除剩下的数据
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
# 从torchvision中获取数据集并利用transforms将其中的img_PIL转换为img_tensor
test_data=torchvision.datasets.CIFAR10("./dataset",train=True,transform=torchvision.transforms.ToTensor())
# 每batch_size个样本进行打包,并在一个epoch后打乱顺序
test_loader=DataLoader(dataset=test_data,batch_size=64,shuffle=True,num_workers=0,drop_last=False)
# 测试数据集中第一个样本信息img及target(单个数据)
img,target=test_data[0]
print(img.shape)
print(target)
writer=SummaryWriter("logs")
# 可以在外层加上对epoch变量的for循环,观察多轮抓取数据时数据顺序是否一致
# 这由dataloader中的shuffle参数控制
for epoch in range(2):
step=0
#一个for循环便是抓取完一轮数据,也就是一个epoch
# 每次将多个数据进行打包抓取(每batch_size个数据打包)
for data in test_loader:
imgs,targets=data
# print(imgs.shape)
# print(targets)
writer.add_images("Epoch:{}".format(epoch),imgs,step)#Note:add_images!!! #format是输出格式,{}里输出内容为format括号里的内容
step=step+1
writer.close()