2023.03.30-2023.03.31
目录
4.1 ToTensor:将其他类型的数据转为Tensor类型
4.3 Normalize:改变图片的均值、方差?(具体改变在图片的色调上)
4.4 Compose:是第二种resize,不改变图片的高和宽,等比剪裁
(一)读取数据
先创建一个类来读取数据
# 首先创建一个类:名为 MyData
class MyData(Dataset):
# 先初始化类 即根据此类去创建实例时要运行的函数
def __init__(self, root_dir, label_dir): # 此函数的作用为 为整个类提供全局变量 可以最后来写
# 因为要地址的列表,所以要获取图片的地址、label是图片上一级的名称,所以需要上一级的地址
self.root_dir = root_dir # 将root_dir变成全局变量 'dataset/train'
self.label_dir = label_dir # 将label_dir变成全局变量 'ants'
# 将两个地址连接起来
self.path = os.path.join(self.root_dir, self.label_dir)
self.img_path = os.listdir(self.path)
def __getitem__(self, idx): # idx作为标号,可以用来索引图片地址
# 从上上行的list中读取图片
img_name = self.img_path[idx] # 加self是因为引用的是全局变量
# 每一个图片的位置
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) # 返回数据的长度(有几张图片
给定 图片的地址 和 图片label的地址 就能够过去到所有图片及其label
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)
(二)TensorBoard 的使用
有一行语句是使用 TensorBoard 时必须要有的:
writer = SummaryWriter('logs')
使用Image.open()打开的图片是PIL类型的
将PIL类型的图片转为np类型:
img_array = np.array(img_PIL)
2.1使用TensorBoard显示图片
writer.add_image('tltle', 需要显示的图片名称, 第几步, dataformats = '')
首先 对图片类型的要求是:必须是np类型,且需要使用特定类型的dataformats,具体可以按Ctrl移动鼠标点击add_image。值得注意的是:用此函数显示图片必须得是tensor数据类型。
2.2使用TensorBoard显示函数的曲线
writer.add_scalar('title'(一般是函数表达式), y 轴参数,x轴参数)
最后需要将writert关闭: writer.close()
具体代码:
from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image
writer = SummaryWriter('logs')
image_path = 'dataset/train/ants/0013035.jpg'
img_PIL = Image.open(image_path) # 通过Image.open()打开的图片是PIL类型的
img_array = np.array(img_PIL) # 将PIL类型的图片转为np类型
print(type(img_array))
# 会使用到以下俩个方法
# 方法一
writer.add_image('test', img_array, 1, dataformats='HWC') # 参数1:title 参数2:特定类型的图片数据 参数3:步数
# y = x
for i in range(100):
# 方法二
writer.add_scalar('y = 2x', 2*i, i) # 参数1:表达式 参数2:y轴 参数3:x轴
# 最后需要将writer关闭
writer.close()
(三)transform的使用
Tensor数据类型很重要,因为他包括了很多神经网络苏要的参数
因为函数显示图片必须得是tensor数据类型,所以要使用函数transforms.ToTensor()
将PIL->Tensor
首先 transforms.ToTensor() 是 transforms 中的一个工具,即 tool = transforms.ToTensor()
而result = tool(input)
上两式又等效于 :
tensor_img = transforms.ToTensor()(img)
所以代码为:
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from PIL import Image
# tensor数据类型 :包括了神经网络需要的参数
img_path = 'dataset/train/ants/0013035.jpg'
img = Image.open(img_path)
writer = SummaryWriter('logs')
tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)
writer.add_image('Tensor_img', tensor_img) # 前者是title,后者是要显示的图片
# 上两式等效于 tensor_img = transforms.ToTensor()(img)
# 因为 transforms.ToTensor() 是 transforms 中的一个工具,即 tool = transforms.ToTensor()
# result = tool(input)
writer.close()
(四)常用Transform工具的使用
4.1 ToTensor:将其他类型的数据转为Tensor类型
# ToTensor 的使用
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image('ToTensor', img_tensor)
结果:
其实就是把PIL类型的图片变成Tensor类型
4.2 Resize:将图片改变大小
下面是将图片大小修改为512*512:
trans_resize = transforms.Resize((512, 512))
img_resize = trans_resize(img)
# img_PIL -> resize -> img_resize PIL -> trans_totensor -> img_tensor
img_resize = trans_totensor(img_resize)
writer.add_image('Resize', img_resize, 0)
结果:
4.3 Normalize:改变图片的均值、方差?(具体改变在图片的色调上)
# Normalize 的使用 按Ctrl+p可以得到提示输入参数
print(img_tensor[0][0][0]) # 表示这幅图片第0行第0列第0个通道的数据
trans_norm = transforms.Normalize([2, 3, 6], [1, 4, 1])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0]) # 表示这幅图片第0行第0列第0个通道的数据
writer.add_image('Normalize', img_norm, 2)
4.4 Compose:是第二种resize,不改变图片的高和宽,等比剪裁
# Compose - resize 第二种resize的使用
trans_resize_2 = transforms.Resize(512) # 这种是等比裁剪,不改变高和宽
trans_compose = transforms.Compose([trans_resize_2, trans_totensor]) # 前者输入,后者输出
img_resize_2 = trans_compose(img)
# img_PIL -> resize -> img_resize_2 PIL -> trans_totensor -> img_tensor
writer.add_image('resize', img_resize_2, 1)
4.5 RandomCrop:将图片进行给定大小的随机剪裁
# RandomCrop 的使用
trans_random = transforms.RandomCrop((500, 600))
trans_compose_2 = transforms.Compose([trans_random, trans_totensor])
for i in range(10):
img_crop = trans_compose_2(img)
writer.add_image('RandomCropHW', img_crop, i)
结果:
整体代码:
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
writer = SummaryWriter('logs')
img = Image.open('dataset/train/ants/0013035.jpg')
# ToTensor 的使用
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image('ToTensor', img_tensor)
# Normalize 的使用 按Ctrl+p可以得到提示输入参数
print(img_tensor[0][0][0]) # 表示这幅图片第0行第0列第0个通道的数据
trans_norm = transforms.Normalize([2, 3, 6], [1, 4, 1])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0]) # 表示这幅图片第0行第0列第0个通道的数据
writer.add_image('Normalize', img_norm, 2)
# Resize 的使用
print(img.size)
trans_resize = transforms.Resize((512, 512))
img_resize = trans_resize(img)
# img_PIL -> resize -> img_resize PIL -> trans_totensor -> img_tensor
img_resize = trans_totensor(img_resize)
writer.add_image('Resize', img_resize, 0)
print(img_resize)
# Compose - resize 第二种resize的使用
trans_resize_2 = transforms.Resize(512) # 这种是等比裁剪,不改变高和宽
trans_compose = transforms.Compose([trans_resize_2, trans_totensor]) # 前者输入,后者输出
img_resize_2 = trans_compose(img)
# img_PIL -> resize -> img_resize_2 PIL -> trans_totensor -> img_tensor
writer.add_image('resize', img_resize_2, 1)
# RandomCrop 的使用
trans_random = transforms.RandomCrop((500, 600))
trans_compose_2 = transforms.Compose([trans_random, trans_totensor])
for i in range(10):
img_crop = trans_compose_2(img)
writer.add_image('RandomCropHW', img_crop, i)
writer.close()
(五)数据集类型转换和dataloader
将所有数据转换成Tensor类型:
dataset_transform = torchvision.transforms.Compose([
torchvision.transforms.ToTensor()
])
等效于下面代码中的最后一块:
test_data = torchvision.datasets.CIFAR10('./new_dataset', train=False, transform=torchvision.transforms.ToTensor())
整体代码:
import torchvision
from torch.utils.tensorboard import SummaryWriter
# 将所有数据都变成Tensor数据类型
dataset_transform = torchvision.transforms.Compose([
torchvision.transforms.ToTensor()
])
# 参数1:创建一个文件夹 new_dataset 参数2:表示这个数据集是训练集 参数3:要下载这个数据集
train_set = torchvision.datasets.CIFAR10(root='./new_dataset', train=True, transform=dataset_transform, download=True)
# 参数1:创建一个文件夹 new_dataset 参数2:表示这个数据集是测试集 参数3:要下载这个数据集
test_set = torchvision.datasets.CIFAR10(root='./new_dataset', train=False, transform=dataset_transform, download=True)
# 右键运行后控制台开始下载这个数据集,提示保存到左侧生成的new_dataset文件夹内
# print(test_set[0])
writer = SummaryWriter('P14')
for i in range(10):
img, target = test_set[i]
writer.add_image('test_set', img, i)
writer.close()
dataloader:打开pytorch官网,在Docs中选择pytorch(官方文档),搜索dataloader
其参数:
dataset:就是数据集,由数据的详细信息
Batch_size:每次处理的数量(如果为n就是每次抓两张牌的意思
shuffle:是否打乱顺序(打第二轮牌的时候洗完牌之后的顺序是否与第一轮一样,如果为false则顺序一样,默认为false,但一般设置为 true
Num_workers:加载数据时是使用多进程还是单进程(默认为0,采用主进程进行加载
Drop_list :假如有100张牌,每次取三张,最后余一张是否要舍去,true为舍去
下例中使用的数据集为
torchvision.datasets.CIFAR10 按住Ctrl将鼠标移动到CIFAR10 可以看到此类返回值如图所示
所以通过使用上述语句可以获得两个返回值:img 和 target (前者表示图像内容,后者表示对应的target或者是label)
整体代码:
import torchvision.datasets
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
# 测试数据集
test_data = torchvision.datasets.CIFAR10('./new_dataset', train=False, transform=torchvision.transforms.ToTensor())
# 从这个数据集中每次取4个,第二轮的时候打乱顺序,采用主进程加载数据,若有余数不舍去
test_loader = DataLoader(test_data, batch_size=4, shuffle=True, num_workers=0, drop_last=False)
# 测试数据集中第一张图片及target
img, target = test_data[0]
print(img.shape)
print(target)
writer = SummaryWriter('dataloader')
for epoch in range(2):
step = 0
for data in test_loader:
imgs, targets = data
# print(imgs.shape)
# print(targets)
writer.add_images('Epoch:{}'.format(epoch), imgs, step)
step += 1
writer.close()
这里batch_size = 4表示将返回的img0 - img3打包返回到imgs ,将target0 - target3打包返回到targets ,通过data接收这些数据,再由
writer.add_images('Epoch:{}'.format(epoch), imgs, step)将这些图片在tensorboard上显示(注意这里的images,加了s)
这里单独打印出来的结果为:
(六)简单的神经网络
输出结果为:tensor(2.)