学习参考
仓库
https://github.com/xiaotudui/pytorch-tutorialhttps://github.com/xiaotudui/pytorch-tutorial
https://github.com/AccumulateMore/CV
参考博客
https://blog.csdn.net/weixin_44216612/article/details/124203730?
https://www.morinha.cc/posts/courses/pytorch-小土堆/
只做一些必要的记录,很多直接看的博客。
P3两大法宝
- dir():打开,看见里面有多少分区、多少工具。
- help():说明书。
在conda环境里,输入jupyter notebook,打开jupyter
Python
import torch
print(torch.cuda.is_available())
help(torch.cuda.is_available) # 查看 torch.cuda.is_available 的用法
dir(torch) # 查看torch包中有哪些区、有哪些工具
help代码结果:
Help on function is_available in module torch.cuda:
is_available() -> bool
Returns a bool indicating if CUDA is currently available.
P5加载数据
Pytorch中加载数据需要Dataset、Dataloader。
- Dataset提供一种方式去获取每个数据及其对应的label,告诉我们总共有多少个数据。
- Dataloader为后面的网络提供不同的数据形式,它将一批一批数据进行一个打包。
用help查看Dataset信息
Python
from torch.utils.data import Dataset
help(Dataset)
同样可以在pycharm里按ctrl点击进去查看。
Dataset、Dataloader大概的作用
Pytorch中加载数据需要Dataset、Dataloader。
- Dataset提供一种方式去获取每个数据及其对应的label,告诉我们总共有多少个数据。
- Dataloader为后面的网络提供不同的数据形式,它将一批一批数据进行一个打包
使用Dataset
导入Dataset类
PYTHON
from torch.utils.data import Dataset
"""
utils 即工具的意思,从torch这个大工具箱中挑选出的实用工具区
data 从这个工具区中挑选出的数据有关工具
前面已经介绍了如何查看帮助,可以查到Dataset的用法
①应该继承 `Dataset` 这个抽象类
②应该重写 `__getitem__` 和 `__len__` 方法
"""
PIL的一些操作(读取图片)
读取图片和显示
PYTHON
from PIL import Image
img=Image.open(img_path)
img.show()
文件操作(路径、目录)
列出目录下的文件,路径拼接
PYTHON
import os
# r防止转义字符生效
dir_path=r"D:\FDownload\hymenoptera_data\train\ants"
# 返回目录下一个包含这些文件和文件夹名称的列表,可以用[索引]访问
img_path_list=os.listdir(dir_path)
# 在init里截取的语句
os.path.join(self.root_dir, self.label_dir)
P7 tensorBoard
使用SummaryWriter类的方法
Python
from torch.utils.tensorboard import SummaryWriter
"""
SummaryWriter类
创建一个事件文件,在给定的目录中添加摘要和事件
参数1 存放日志的文件夹名
本节视频只用到领个方法
add_image() 在事件文件中添加图片
add_scalar() 在TensorBoard中添加标量数据
该方法可以用来添加训练过程中的损失值、准确率等指标,以便于在TensorBoard中进行可视化和比较
"""
SummaryWriter
是 PyTorch 中用于记录训练过程中的日志信息的工具,通常用于与 TensorBoard 配合使用。add_scalar
方法用于记录标量值(如损失函数值、准确率等)到日志中。以下是 add_scalar
方法的详细用法和示例。
方法签名
python
add_scalar(tag, scalar_value, global_step=None, walltime=None)
tag
:字符串,用于标识标量值的名称(如'Loss/train'
或'Accuracy/test'
)。scalar_value
:标量值,可以是 Python 的数字类型(如int
、float
)或 PyTorch 的张量。global_step
:可选参数,表示当前的全局步数(如训练的轮数或批次数)。walltime
:可选参数,表示事件发生的时间,以秒为单位。
示例用法
记录训练损失
python
from torch.utils.tensorboard import SummaryWriter
# 创建一个 SummaryWriter 实例
writer = SummaryWriter(log_dir='runs/experiment_1')
# 假设你有一个训练循环
for epoch in range(num_epochs):
train_loss = ... # 计算训练损失
writer.add_scalar('Loss/train', train_loss, global_step=epoch)
记录测试准确率
python
test_accuracy = ... # 计算测试准确率
writer.add_scalar('Accuracy/test', test_accuracy, global_step=epoch)
记录多个标量
python
writer.add_scalar('Loss/train', train_loss, global_step=epoch)
writer.add_scalar('Loss/test', test_loss, global_step=epoch)
writer.add_scalar('Accuracy/train', train_accuracy, global_step=epoch)
writer.add_scalar('Accuracy/test', test_accuracy, global_step=epoch)
在 TensorBoard 中查看结果
-
启动 TensorBoard:
bashtensorboard --logdir=runs/experiment_1
-
打开浏览器,访问
http://localhost:6006
,即可查看记录的标量值。
注意事项
-
日志目录:
log_dir
是日志文件的保存路径。如果路径不存在,SummaryWriter
会自动创建。- 可以通过
tensorboard --logdir
指定日志目录来查看多个实验的结果。
-
全局步数:
global_step
用于记录当前的训练进度。通常设置为训练的轮数或批次数。
-
性能影响:
SummaryWriter
会对性能产生一定影响,尤其是在频繁写入日志时。可以通过减少写入频率来优化性能。
总结
SummaryWriter
的 add_scalar
方法用于记录训练过程中的标量值,如损失函数值和准确率。通过将这些值记录到日志中,可以使用 TensorBoard 可视化训练过程,帮助分析模型的性能和调试训练过程。
使用一下「tensorboard」,同时查看生成的事件文件
Python
from torch.utils.tensorboard import SummaryWriter
# 传入路径参数"logs"
writer = SummaryWriter("logs")
# add_scalar(
# tag, 相当于标题
# scalar_value, 相当于y轴
# global_step=None, 相当于 x轴
# )
# y = 2x
# 同一个图像标题下,重复修改y值会导致,新图会包含之前的旧图
for i in range(100):
writer.add_scalar("y = 2x", 2*i, i)
writer.close()
shell
# 查看日志的命令
# logdir=事件文件所在的 文件夹名
tensorboard --logdir=logs
# 可以修改端口,改成自己的路径
tensorboard --logdir=logs --port=6007
tensorboard --logdir=learn_pytorch/logs --port=6007
添加图片
添加图片, 方便观察训练过程的不同阶段的输出
Python
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
import numpy as np
writer = SummaryWriter("logs")
# 第1步
# image_path = "data/train/ants_image/0013035.jpg"
# 第2步
image_path = "data/train/bees_image/16838648_415acd9e3f.jpg"
img_PIL = Image.open(image_path)
# 需要numpy.array类型的参数
img_array = np.array(img_PIL)
print(type(img_array))
print(img_array.shape)
# 从PIL到Numpy,需要在add_image()中指定图像的每一维的含义,需要指定高度宽度通道数的顺序
writer.add_image("test", img_array, global_step=2, dataformats="HWC")
writer.close()
P9 transforms结构及用法
什么是transforms?
常用的图像预处理方法 ,一般用于转换图片格式
有多个图片处理方法,如:
ToTensor()对象可传入两种图片格式:
- PIL:用PIL的Image工具打开
- numpy:用OpenCV打开
transforms该如何使用?
首先创建一个具体的工具(如ToTensor工具,相当于创建类对象):tool = transforms.ToTensor()
然后给工具传入参数(传入图片):result = tool(input)
最后得到tensor类型的图片
为什么我们需要Tensor数据类型?
tensor类型中的很多属性我们都需要在神经网络中用到,如反向传播、梯度等
所以我们必定要用到transforms将数据转换为tensor类型,然后进行训练
py
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
img_path = "data/train/ants_image/0013035.jpg"
img = Image.open(img_path)
print(img)
# 使用transforms
"""
ToTensor() 可传入`PIL Image` 和 `numpy.ndarray` 两种图片格式
PIL Image:即用PIL的Image工具打开图像的格式
numpy.ndarray:即用OpenCV打开图像的格式(所以一般用这种方式打开,不用再转换图像了)
"""
tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)
print(tensor_img)
writer = SummaryWriter("logs")
writer.add_image("Tensor_img", tensor_img, 0)
writer.close()
了解__call__函数
transforms里有一个call函数,用下面的一段代码来说明其使用方法:
直接通过**对象(参数)**来使用
py
# __call__ 类似「类的有参构造」,可看作为「对象-有参构造」
# 测试
class Person:
def __call__(self, name):
print("__call__"+" Hello "+name)
def hello(self, name):
print("Hello "+name)
person = Person()
person("zhangsan")
person.hello("lisi")
P13常用transfroms
py
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
writer = SummaryWriter("logs")
img = Image.open("D:\\FDownload\\hymenoptera_data\\train\\ants\\0013035.jpg")
# 打印后得知,图像为RGB三通道
print(img)
# 01 transforms.ToTensor()
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
print(img_tensor[0][0][0]) # 当使用transforms.ToTensor()将PIL图像转换为张量时,生成的张量维度遵循 (Channels, Height, Width) 格式
writer.add_image("ToTensor", img_tensor, 0)
# 02 transforms.Normalize()
# output[channel] = (input[channel] - mean[channel]) / std[channel]
trans_norm = transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize", img_norm, 0)
# 03 Resize
# 图像为PIL,经过Resize后,仍为PIL
trans_resize = transforms.Resize((512, 512)) # 如果参数是一个int数,调整尺寸,短的那一边和参数一样,另一个进行等比例调整
img_resize = trans_resize(img)
# 将PIL转为Tensor
img_resize = trans_totensor(img_resize)
writer.add_image("Resize", img_resize, 0)
# 04 Compose 将几个转换组合在一起,先resize,再tensor
trans_resize_2 = transforms.Resize(512)
trans_compose = transforms.Compose([trans_resize_2, trans_totensor])
img_resize_2 = trans_compose(img)
writer.add_image("Resize", img_resize_2, 0)
# 05 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)
writer.close()
dataloader
Dataloader():
概念:是一个迭代器,方便我们去多线程地读取数据,并且可以实现batch以及shuffle的读取等
用法:
test_loader = DataLoader(dataset=test_data, batch_size=4, shuffle=True, num_workers=0, drop_last=True)
如上,test_loader 就是我们生成的数据迭代器,
即加载test_data数据集,每次打包四个数据,打包成imgs和targets,
shuffle表示每次迭代完之后,下次迭代是否打乱顺序
drop_list 表示是否删除非完整页的结尾数据
完整参数参考官方文档。
P16 神经网络的基本骨架--nn.Module的使用
- 注:nn=neural network
module
torch.nn是非常常用的包,其中torch.container中的 「Module」 是所有神经网络的基类
自己定义的模型需要实现「Module」的__init__和forward函数
一个nn.module可以视为一个块。所有的module包含两个主要函数:
init函数:在里边定义一些需要的类或参数。包括网络层
forward函数:做最终的计算和输出,其形参就是模型(块)的输入。
PYTHON
import torch
from torch import nn
class Lana(nn.Module):
# ctrl+ o 可以找到有哪些方法要重写
def __init__(self) -> None:
super().__init__()
def forward(self,input):
output = input + 1
return output
lana=Lana()
x=torch.tensor(1.0)
print(x)
output = lana(x)
print(output)