小土堆pytorch学习笔记一
本节使用到的数据集如下:
蚂蚁蜜蜂/练手数据集:链接: https://pan.baidu.com/s/1jZoTmoFzaTLWh4lKBHVbEA 密码: 5suq
Pycharm 查看需传入的参数ctrl+P
查看库类的说明:按住ctrl后鼠标点击
目录
3.2 使用transforms的ToTensor()进行图片类型的转化(图片转为tensor)
3.3.1 transforms.Normalize()标准化
一、Dataset类使用
本节用蚂蚁蜜蜂的数据集进行讲解


通过继承Dataset类class MyData(Dataset),实现__len__和__getitem__方法,可以自定义自己的数据集类以适应不同的数据源和格式
蚂蚁蜜蜂/练手数据集:链接: https://pan.baidu.com/s/1jZoTmoFzaTLWh4lKBHVbEA 密码: 5suq
from torch.utils.data import Dataset
from PIL import Image
import os # 获取地址要引入此库
# 定义函数
class MyData(Dataset):
# 以列表形式,获取图片文件夹下所有图片的地址
def __init__(self, root_dir, label_dir):
self.root_dir = root_dir # 根目录
self.label_dir = label_dir
self.path = os.path.join(self.root_dir, self.label_dir) # 图片文件夹路径拼接
self.img_path = os.listdir(self.path) #将文件夹路径传入——>以列表list形式获取所有图片的地址
# getitem()根据给定的索引idx返回对应的数据样本(信息、标签)
def __getitem__(self, idx):
img_name = self.img_path[idx] #读取 图片列表中的第idx索引的图片名
img_item_path = os.path.join(self.root_dir, self.label_dir,img_name) #拼接(地址+名) 图片列表中的第idx索引的图片相对地址
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" #相对路径:“dataset/train”
# 读取蚂蚁的数据集
ants_label_dir = "ants"
ants_dataset = MyData(root_dir, ants_label_dir)
print(ants_dataset)
print(ants_dataset[0] ) # 根据重写的getitem返回 img 与 label
img, label = ants_dataset[0]
img.show()
# 读取蜜蜂的数据集
bees_label_dir = "bees"
bees_dataset = MyData(root_dir, bees_label_dir)
img, label = bees_dataset[0]
img.show()
#两个数据集的拼接 未改变顺序,ants在前 bees在后
train_dataset =ants_dataset + bees_dataset
print(len(ants_dataset))
print(len(bees_dataset))
print(len(train_dataset))
生成蚂蚁和蜜蜂的txt标签文件:
# 生成蚂蚁和蜜蜂的label txt文件
# 运行后再dataset/train/ants_label目录下生成001.txt、002.txt等文件,且每个文件中都包含文本 "ants"。
import os
root_dir = "dataset/train" # 根目录路径
target_dir = "ants_image" # 存放蚂蚁图片的目录名
bee_target_dir = "bees_image" # 存放蜜蜂图片的目录名
img_path = os.listdir(os.path.join(root_dir,target_dir)) # 拼接图片目录的完整路径,,获取蚂蚁图片列表
bee_img_path = os.listdir(os.path.join(root_dir,bee_target_dir)) # 拼接图片目录的完整路径,,获取蜜蜂图片列表
label = target_dir.split('_')[0] # 将target_dir按"_"分割,取第一个部分作为标签("ants_image" -> ["ants", "image"] -> "ants")
bee_label = bee_target_dir.split('_')[0] # 将bee_target_dir按"_"分割,取第一个部分作为标签("bees_image" -> ["bees", "image"] -> "bees")
out_dir = "ants_label" # 存放标签文件的目录名
bee_out_dir = "bees_label"
# 遍历每张图片
for i in img_path:
# 分割列表的文件名(去掉.jpg后缀)
file_name = i.split('.jpg')[0]
# 创建并写入标签文件
## with open(...) as f:上下文管理器,自动处理文件的打开和关闭
## 文件打开模式'w':表示以写入模式打开文件,如果文件不存在则创建
## open()会自动生成数据集图片对应的txt标签文件
## "{}.txt".format(file_name) 是 Python 中的字符串格式化操作,作用是将 file_name 的值插入到字符串模板中,生成一个以 .txt 为后缀的文件名。
### 如果 file_name 的值是 "001",那么格式化后得到的结果就是 "001.txt"
with open(os.path.join(root_dir, out_dir, "{}.txt".format(file_name)), 'w') as f:
# f.write(label):将标签内容写入文件
f.write(label)
for i in bee_img_path:
file_name = i.split('.jpg')[0]
with open(os.path.join(root_dir,bee_out_dir,"{}.txt".format(file_name)),'w') as f:
f.write(bee_label)
二、TensorBoard的使用
TensorBoard是一个用于可视化机器学习实验结果的工具,可以帮助我们更好地理解和调试训练过程中的模型。
2.1 安装TensorBoard
可在pycharm的终端中安装:
pip install tensorboard

2.2 在代码中配置Tensorboard
from torch.utils.tensorboard import SummaryWriter #从PyTorch的工具模块中导入SummaryWriter类,用于连接代码与TensorBoard
# y = 2x
writer = SummaryWriter("logs") # 指定日志文件存储位置,如果该目录不存在,会自动创建
# 记录标量数据
for i in range(100):
# 生成 x 值从 0 到 99 的整数(共 100 个点)
# 第一个参数"y = 3x":标量数据的标签(名称),会显示在 TensorBoard 的图表标题中
# 第二个参数3*i:要记录的标量值(纵坐标 y 值),这里通过计算得到 y=3x 的关系。
# 第三个参数i:全局步数(global_step),即 x 轴横坐标,用于指定当前数据点的位置。
writer.add_scalar("y = 3x", 3*i,i)
writer.close() # 关闭SummaryWriter对象
这段代码是 TensorBoard 最基础的用法,主要用于展示:
- 训练过程中的损失值(loss)变化
- 准确率(accuracy)、学习率(learning rate)等指标的趋势
实际应用中,你可以修改add_scalar()的参数,例如在训练循环中记录每一步的损失
for epoch in range(10):
loss = ... # 计算当前轮次的损失
writer.add_scalar("Training Loss", loss, epoch) # 以轮次为x轴,损失为y轴
通过 TensorBoard 可视化后,能直观判断模型是否收敛、是否过拟合等问题,是深度学习训练中重要的调试工具。
2.3 打开TensorFlow事件
logdir = 事件文件所在文件夹名

通过端口的设置,可以避免与其他人端口冲突,导致打不开--port=6007

点击网址后,要点击scalars查看

当图像变为y=3x时,但标题没变,则仍在该标题下进行绘制:


当标题tag和纵轴同时变时,生成新的图像:


2.4 add_image()使用
add_image() 是 PyTorch 中 SummaryWriter 类的一个方法,用于将图像数据写入 TensorBoard 日志,以便在 TensorBoard 中可视化图像

注:add_image的参数img_tensor类型需为torch.Tensor, numpy.array, or string/blobname
# 查看图像类型为PIL ,并将图像类型从PIL——>numpy,符合add
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
img_path = "E:\\Desktop\\learn_torch\\dataset\\train\\ants_image"
img = Image.open(img_path)
print(type(img)) # 查看图像类型 此图像类型为PIL格式
# 将PIL图像格式转为numpy格式
import numpy as np
img_array = np.array(img)
print(type(img)) # 此时图像类型为numpy格式
一个步长对应一个图片
运行时出错,原因是图像形状默认为 :math:`(3, H, W)——即(通道数3,高,宽)

而通过打印发现形状为(H,W,3)——(512, 768, 3),因此需对通道参数进行转换,在add_image
()中加入dataformats=“HWC”,规定图片格式为“HWC”,C为通道数channel,运行成功:

运行tensorboard查看:

图像格式转换
共有三种类型的图像:PIL、Numpy、Tensor格式
转换代码如下:
from PIL import Image
import numpy as np
import torch
from torchvision import transforms
# 1. PIL格式
img_pil = Image.open("test.jpg") # <class 'PIL.JpegImagePlugin.JpegImageFile'>
# 2. 转换为NumPy格式
img_np = np.array(img_pil) # shape: (H, W, 3),dtype: uint8
# 3. 转换为Tensor格式
tensor_trans = transforms.ToTensor()
img_tensor = tensor_trans(img_pil) # shape: (3, H, W),dtype: float32,范围[0.0, 1.0]
三、Transformer的使用
3.1 补充python中的__call__方法
__call__是python中的一个特殊方法(魔术方法),当一个类定义了__call__方法后,该类的实例对象就可以像函数一样被调用。调用的参数会直接传递给__call__方法。
实例演示:
class Person:
def __call__(self,name):
print("__call__"+name)
def hello(self,name):
print(name)
person = Person()
person.hello("lihua") # 输出为lihua
person("zhangqiang") # __call__zhangqiang
3.2 使用transforms的ToTensor()进行图片类型的转化(图片转为tensor)
from torchvision import transforms
from PIL import Image
img_path = "dataset/train/ants_image/6240338_93729615ec.jpg"
# 使用PIL的Image.open()方法打开指定路径的图片,返回一个PIL Image对象
img = Image.open(img_path)
print(type(img))
# 创建一个ToTensor类型的转换对象,该对象用于将PIL图像或numpy数组转换为PyTorch的Tensor
tensor_trans = transforms.ToTensor() # 实例化ToTensor对象为tensor_trans
tensor_img = tensor_trans(img) # 使用tensor_trans对象对PIL图像img进行转换,得到PyTorch张量(Tensor)
print(type(tensor_img))
使用torchvision.transforms中的ToTensor将 PIL 库读取的图像转换为 PyTorch 框架可处理的张量(Tensor),这是深度学习中处理图像数据时的常见预处理步骤,用于对图像进行预处理和数据增强操作。


tensor_img = tensor_trans(img)这里使用了ToTensor类中的__call__方法
完整代码如下:
# 将PIL图像转为tensor形式
from torchvision import transforms
from PIL import Image
# 使用PIL的Image.open()方法打开指定路径的图片,返回一个PIL Image对象
img = Image.open("dataset/train/bees_image/16838648_415acd9e3f.jpg")
print(img)
# 创建一个ToTensor类型的转换对象,该对象用于将PIL图像或numpy数组转换为PyTorch的Tensor
trans_tensor = transforms.ToTensor() # 实例化ToTensor对象为tensor_trans
img_tensor = trans_tensor(img) # 使用tensor_trans对象对PIL图像img进行转换,得到PyTorch张量(Tensor)
print(img_tensor)
print(type(img_tensor))
3.3 常见的Transformer
3.3.1 transforms.Normalize()标准化
transforms.Normalize 是 PyTorch 中 torchvision.transforms 模块提供的图像标准化操作,用于对图像的每个通道进行标准化处理,三个通道的像素值会分布在相似的范围。
公式:output[channel] = (input[channel] - mean[channel]) / std[channel]
其中,mean 是每个通道的均值,std 是每个通道的标准差(需提前指定,通常基于训练数据集计算)。
代码如下:三个通道的均值和标准差都设为0.5
#现将img变为tensor形式,再进行标准化
from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter
img_path = "dataset/train/bees_image/2405441001_b06c36fa72.jpg"
img = Image.open(img_path)
# img——>tensor
trans_tensor = transforms.ToTensor()
img_tensor = trans_tensor(img)
#tensor——>标准化norm
trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5]) #参数分别为均值 (mean) 和标准差 (std),这里三个通道都使用 0.5
img_norm = trans_norm(img_tensor)
print(img_tensor[0][0][0]) # tensor的形状为CHW,打印标准化后 tensor 第一个通道、第一行、第一列的像素值
print(img_norm[0][0][0])
writer = SummaryWriter("logs")
writer.add_image("Normalize",img_norm)
writer.close()


3.3.2 transforms.Resize()
注意图片数据类型,通过Image.open读取的是PIL类型的
transform.Resize() 可以处理 PIL 图像对象,也可以处理张量tensor类型的数据
代码如下:
# transforms.Resize()使用
from PIL import Image
from torchvision import transforms
img_path = "dataset/train/bees_image/39747887_42df2855ee.jpg"
img = Image.open(img_path)
print("原始图片为PIL类型,大小为:",img.size)
# 对原始图像进行缩放
tran_resize = transforms.Resize((512,512)) #
img_resize = tran_resize(img)
print("对PIL类型进行resize后,大小为:",img_resize)
#将PIL Resize图片转为tensor
trans_tensor = transforms.ToTensor()
img_tensor = trans_tensor(img_resize)
print("将PIL Resize图像转为tensor,大小为:",img_tensor)
#对tensor类型图片进行resize
trans_tensor2 = transforms.Resize((256,256))
img_resize = trans_tensor2(img_tensor)
print("对tensor类型图片进行resize",img_resize)
运行结果如下:

3.3.3 compose()串联多种变换
Compose用于组合多个图像转换(transform)操作。通过 Compose,可以创建一个转换流水线。这个流水线可以按顺序执行多个图像处理操作。这些操作可以包括缩放、裁剪、归一化等,其需要的参数是一个列表,其元素类型是transforms类型。
格式Compose([transforms参数1,transforms参数2,…])
from PIL import Image
from torchvision import transforms
img_path = "dataset/train/bees_image/150013791_969d9a968b.jpg"
img = Image.open(img_path)
print(img)
#实例化两个对象
trans_resize2 = transforms.Resize(512) #参数 512 表示将图像的最短边调整为 512 像素(长边按比例缩放,保持原图像比例)。
trans_totensor = transforms.ToTensor() #将 PIL Image 对象转换为 PyTorch 的 Tensor 格式
#将多个转换操作组合成一个转换流水线。这里的顺序是:先执行 trans_resize2(缩放),再执行 trans_totensor(转为 Tensor)。
trans_compose = transforms.Compose([trans_resize2,trans_totensor])
img_resize_2 = trans_compose(img)
print(img_resize_2)
这段代码的流程是:读取 PIL 图像 → 定义两个转换操作(缩放和转 Tensor)→ 用 Compose 组合这两个操作 → 对图像执行组合转换 → 得到处理后的 Tensor 图像。
resize——>可以处理PIL和tensor类型
writer.add_image()——>可以处理tensor和numpy类型
Normalize——>支持tensor形式
3.3.4 RandomCrop() 随机裁剪
RandomCrop 是 PyTorch 中用于图像数据增强(data augmentation)的函数之一,它可以在图像或张量的随机位置裁剪出指定大小的区域
注意:随机裁剪大小不要超过图像本身大小
代码如下:
#RandomCrop
trans_random = transforms.RandomCrop((500,1000))
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)
writer.close()
3.4 总结
所有transforms的代码:
from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter
from P9_Transforms import trans_tensor
writer = SummaryWriter("logs")
img_path = "dataset/train/bees_image/39747887_42df2855ee.jpg"
img = Image.open(img_path)
#ToTensor
trans_totensor = transforms.ToTensor() # 实例化tensor对象
img_tensor = trans_totensor(img)
writer.add_image("ToTensor",img_tensor)
#Normalize 支持tensor形式
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([6,3,2],[9,3,1])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize",img_norm,2)
#Resize 支持tensor PIL形式
print(img.size)
trans_resize = transforms.Resize((512,512)) #实例化一个resize对象 强制将图像调整为指定的宽高尺寸(可能改变比例)
# 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)
print(img_resize)
# Compose - resize - 2
trans_resize_2 = transforms.Resize(512) #只传入一个整数(如 512)作为参数时,其含义是将图像的最短边调整为该数值,长边则按原比例缩放,以保持图像的宽高比不变。
# 顺次执行compose里的顺序
trans_compose = transforms.Compose([trans_resize_2,trans_totensor])
img_resize_2 = trans_compose(img)
writer.add_image("Resize",img_resize_2,1)
#RandomCrop
trans_random = transforms.RandomCrop((500,1000))
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)
writer.close()

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)