Large Model-learning(3)

Day 3-小土堆日

消失了一段时间,被老师拉去搞论文了,并且重新制定了以下学习计划。

算法题往后放一放,先速成小土堆,再去弄项目吧。

1.科研进展

消失这些天主要是去弄论文了,老师建议换个数据集,所以很多实验都需要重新做一遍。现在已经回到正轨了,论文快修正好了,争取四月底之前投出去吧。

2.速成小土堆

2.1 Python的内置函数dir(),打开工具箱

dir()函数,打开工具箱。用于列出一个对象的所有属性和方法。它返回一个包含对象所有属性和方法名称的列表。如果不传入参数,则返回当前作用域中所有可用的名称。

bash 复制代码
torch.cpu.is_available()
dir(torch)

可以更加具体详细的查看。

bash 复制代码
dir(torch.cpu)

继续套娃,返回的结果是一个函数对象的属性列表。

bash 复制代码
dir(torch.cpu.is_available())

python 里 前后各有双下划线 __函数名__是什么?

在 Python 中,魔术属性(Magic Attributes)也称为特殊属性(Special Attributes)也称为魔法方法、双下划线方法(Double Underscore Methods),是以双下划线 __ 开头和结尾的特殊命名方式,用于实现对象的特殊行为和操作,不允许被修改

所以下一步可以用help方法去查看这个函数了。

2.2 Python的内置函数help(),查看官方解释文档

help()函数,查看说明书。用于获取对象、模块、函数、关键字等的帮助信息。当传入对象时,它会显示该对象的帮助文档。如果没有传入任何参数,则会进入交互式帮助模式。

bash 复制代码
help(torch.cpu.is_available)
bash 复制代码
torch.cpu.is_available??

在 IPython 中,当输入 object?? 时,它会尝试显示该对象的源代码

python 复制代码
torch.cpu.is_available??

IPythonJupyter Notebook / JupyterLab 这类交互式 Python 环境中:

  • ? (单问号):显示对象的 简要帮助文档 和签名。

  • ?? (双问号):显示对象的源代码(如果该对象是用纯 Python 实现的)。

2.3 Pycharm和Jupyter工具对比

Pycharm差不多学一学就行了,Jupyter很久没用了我记录一下。

如果你和我一样把项目放到D盘去了,那建议这样启动,先切换到D盘再激活环境再打开Jupyter。

bash 复制代码
(base) C:\Users\深情付九>cd /d D:\

(base) D:\>conda activate pytorch

(pytorch) D:\>jupyter notebook

这样打开就可以直接看到我们的项目啦!

然后这里进入项目新建一个文件,进去之后再切换环境,就可以看到咯。

Shift + 回车快捷键 和直接点击运行,是一样的效果。

Pycharm 按shift + 回车 会跳转至下一行的行首

在Pycharm的Python Console中也可 以任意行为块 输入多行时 按shift + 回车

2.4 Pytorch读取数据的两个类 Dataset和DataLoader

2.4.1 Dataset

Dataset将数据和label进行组织编号0 1 2 3......,使得可以根据编号读取数据;需获取每一个数据及其label以及数据总数 ,要实现 len() 方法和 getitem() 方法。
**len()**方法返回数据集的样本数量;
**getitem()**方法根据给定的索引返回对应的数据样本;

2.4.2 DataLoader

DataLoader对数据进行打包将数据集划分为小批量,按batchsize送入网络模型;可以接收一个 Dataset 对象作为输入,并根据指定的批量大小、是否打乱数据、是否使用多线程等参数,来构建一个用于数据加载的迭代器

2.4.3 Dataset类代码实战:

通过继承Dataset类class MyData(Dataset),实现__len__和__getitem__方法,可以自定义自己的数据集类以适应不同的数据源和格式

蚂蚁蜜蜂/练手数据集:https://pan.quark.cn/s/e4c425fc4c0d

python 复制代码
from torch.utils.data import Dataset
from PIL import Image
import os

class MyDataset(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)

    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 = 'hymenoptera_data/train'
ants_label_dir = 'ants'
bees_label_dir = 'bees'
ants_dataset = MyDataset(root_dir,ants_label_dir)
bees_dataset = MyDataset(root_dir,bees_label_dir)

train_dataset = ants_dataset + bees_dataset

然后也跟着博主再控制台尝试调试。

2.5 Tensorboard的使用

2.5.1 SummaryWriter类使用

(1) writer.add_scalar()

add_saclar用于在TensorBoard中添加标量数据。该方法可以用来添加训练过程中的损失值、准确率等指标,以便于在TensorBoard中进行可视化和比较。

tag(字符串): 用于标识添加的标量数据的名称或标签。在TensorBoard中,这个标签将用作图表的标题。
scalar_value(数值): 要记录的标量数据的值。这可以是损失值、准确率等。
global_step(整数,可选): 表示记录的步数或迭代次数。这个参数对于在TensorBoard中显示随时间变化的数据非常有用。例如,在训练神经网络时,您可以将当前的迭代次数传递给global_step: 以便在TensorBoard中可视化损失值、准确率等随着训练步数的变化而变化的曲线
**walltime(时间戳,可选):**表示记录的时间。如果不指定,则默认使用当前时间

实战:使用tensorboard绘制 y = x 的函数

python 复制代码
from torch.utils.tensorboard import SummaryWriter #相当于:"我要从 torch 工具箱的 utils 抽屉的 tensorboard 夹层里,只把名为 SummaryWriter 的那把螺丝刀拿出来。"

writer = SummaryWriter("logs")

# writer.add_image()
# y = x
for i in range(100):
    writer.add_scalar("y = x", i, i)

writer.close()

然后安装 tensorboard(注意,下载失败的可以去Anacanda用管理员身份打开下载运行,还有Pycharm终端记得在设置里面改成cmd,这样就可以默认进入虚拟环境了),在终端运行以下命令行。

python 复制代码
tensorboard --logdir=logs

有时候可能端口占用导致错误,也可以自己指定端口,效果是一样的。

python 复制代码
可通过tensorboard --logdir==logs --port=XXXX 指定端口号

注意: 当未改变图像标题,重复修改y值 ,如writer.add_scalar("y = x", i, i),writer.add_scalar("y = x", 2i, i),writer.add_scalar("y = x", 3 i, i),会导致新绘制会包含之前绘制的图像

解决方法: 删除所有log文件,重新执行程序,再在tensorboard中查看

(2) add_image()

"练手数据集"在博主给的链接里面也有,直接下载解压,改名 data 放入自己的文件夹里面就可以

接下来开始学习add_image()。

直接 Ctrl 点击方法,查看类型:

**注意:**add_image的参数img_tensor类型需为torch.Tensor, numpy.array, or string/blobname

之前提取图片用的都是 PIL,所以我们通过控制台查看一下这个数据类型。

很遗憾,这不是我们能用的类型。

**解决方案:**利用numpy.array()对PIL的图像进行转换

具体操作:利用 Opencv 读取图片,获得 numpy 型数据类型。

现在已经获得 add_image() 需要的数据类型了,调试成功,开始写代码。

python 复制代码
from torch.utils.tensorboard import SummaryWriter #相当于:"我要从 torch 工具箱的 utils 抽屉的 tensorboard 夹层里,只把名为 SummaryWriter 的那把螺丝刀拿出来。"
import numpy as np
from PIL import Image

writer = SummaryWriter("logs")
image_path = "data/train/ants_image/0013035.jpg"
img_PIL = Image.open(image_path)
img_array = np.array(img_PIL)

writer.add_image("test", img_array, 1)
# y = x
for i in range(100):
    writer.add_scalar("y = x", i, i)

writer.close()

OK报错了,不要慌,因为博主也报错了。。。

问题原因: 图像形状默认为 :math:`(3, H, W),而上面通过打印发现 shape 为(512, 768, 3),需对通道参数进行转换
**解决方案:**使用 dataformats='HWC'

python 复制代码
from torch.utils.tensorboard import SummaryWriter #相当于:"我要从 torch 工具箱的 utils 抽屉的 tensorboard 夹层里,只把名为 SummaryWriter 的那把螺丝刀拿出来。"
import numpy as np
from PIL import Image

writer = SummaryWriter("logs")
image_path = "data/train/ants_image/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')
# y = x
for i in range(100):
    writer.add_scalar("y = x", i, i)

writer.close()

无报错,运行tensorboard进行刷新网页,成功显示:

2.6 Transforms的使用

新建一个 P9_Transforms.py 文件用于这一节的练习。

Transforms用于对图像进行预处理和数据增强操作,如调整图像大小、中心裁剪、随机裁剪、随机水平翻转、归一化、将 PIL 图像转换为 Tensor 等等

python 复制代码
from torchvision import transforms

查看用法,快捷键 Alt + 7 可以看到左侧出现对每个类的详细说明。

2.6.1 Python的__call__ 方法

在 Python 中,call 是一个特殊方法(也称为魔术方法或双下划线方法),用于使对象可以像函数一样被调用。当你在一个对象上调用 obj() 时,Python 解释器会查找该对象的__call__ 方法并调用它。

python 复制代码
class MyClass:
    def __init__(self, value):
        self.value = value
    
    def __call__(self, x):
        return self.value + x

obj = MyClass(10)
result = obj(5)  # 调用了 __call__ 方法
print(result)  # 输出: 15

在上面的示例中,MyClass 类实现了__call__方法,因此创建的 obj 实例可以像函数一样被调用。在调用 obj(5) 时,实际上会调用 obj.call(5),返回的结果是 self.value + x 的计算结果,即 10 + 5 = 15。

__call__方法的灵活性使得对象可以像函数一样被使用,这在某些情况下非常有用,例如实现可调用的对象或者定制对象的行为。
查看transforms的源代码,发现其实现了__call__方法

2.6.2 tensor数据类型

所以tensor_trans = transforms.ToTensor() ,tensor_img = tensor_trans(img)直接传入img调用了其中的__call__方法

python 复制代码
from PIL import Image
from torchvision import transforms

# python 的用法 -> tensor 数据类型
# 通过 transforms.ToTensor 去解决两个问题
# 1,Transforms如何使用(python)
# 2. 为什么需要Tensor数据类型

img_path = "data/train/ants_image/0013035.jpg"
img = Image.open(img_path)

tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)

print(tensor_img)

tensor是神经网络专用的数据类型,包含了许多神经网络需要的参数。

transforms的ToTensor()进行图片类型的转化问题已解决。

opencv 使用cv2.imread()读取的图像数据类型是numpy.ndarray

使用add_image()添加tensor类型的图像到日志文件中 通过tensorboard展示

python 复制代码
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

# python 的用法 -> tensor 数据类型
# 通过 transforms.ToTensor 去解决两个问题

img_path = "data/train/ants_image/0013035.jpg"
img = Image.open(img_path)

writer = SummaryWriter("logs")

# 1,Transforms如何使用(python)
tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)
print(tensor_img)

# 2. 为什么需要Tensor数据类型
writer.add_image("Tensor_img", tensor_img)

writer.close()

2.7 常见的Transforms

本小节新建文件 P10_UsefulTransforms.py。

2.7.1 ToTensor 的使用

python 复制代码
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
from torchvision import transforms

writer = SummaryWriter("logs") # 日志文件存储位置
img = Image.open("hymenoptera_data/train/ants/0013035.jpg")
print(img)

# ToTensor
tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)
writer.add_image("ToTensor", tensor_img)
writer.close()

2.7.2 Normalize 的使用

tensor是完成缩放的作用,从0到255转换为0到1。而Normalize完成的是归一化,从-1到1。但是通常这两步都被叫做归一化。

假设三个通道的均值和标准差都为0.5:

  • mean = [0.5, 0.5, 0.5]:分别对应 RGB 三个通道的均值。
  • std = [0.5, 0.5, 0.5]:分别对应 RGB 三个通道的标准差。

作用公式:对每个通道执行 output = (input - mean) / std。

这组参数的特殊效果:将原本在 [0, 1] 区间的像素值,线性映射到 [-1, 1] 区间:

  • 若 input = 0.0,则输出 (0 - 0.5) / 0.5 = -1.0。
  • 若 input = 1.0,则输出 (1 - 0.5) / 0.5 = 1.0。
python 复制代码
from tkinter import image_types

from torch.utils.tensorboard import SummaryWriter
from PIL import Image
from torchvision import transforms

writer = SummaryWriter("logs") # 日志文件存储位置
img = Image.open("hymenoptera_data/train/ants/0013035.jpg")
print(img)

# ToTensor
tensor_trans = transforms.ToTensor()
img_tensor = tensor_trans(img)
writer.add_image("ToTensor", img_tensor)

# 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)

writer.close()

归一化后图片不一样了。也可以进行其他数值的调试。

简而言之,归一化就是改变模型参数,让模型呈现出不同状态。不同维度之间的特征在数值上量纲可能不一样,归一化就是让他们量纲大致差不多,这样梯度下降更快,更容易求解,有利于预防梯度爆炸加速损失函数收敛。

2.7.3 Resize()的使用

Resize 是用来把图片变大或变小的工具,你可以告诉它具体的"宽和高",也可以只告诉它"短边的长度"。

|------------|----------------------|------|
| 输入参数 size | 效果 | 图片比例 |
| (224, 224) | 不管原来多长多宽,直接拉成正方形 | 会变形 |
| 256 | 把短边变成 256,长边按比例算 | 不变性 |

这是为了适应深度学习模型的两种需求:

  • 固定尺寸输入 (需要 (h, w) 元组):有些老模型必须输入确切的宽高,不管变形不变形。
  • 保持比例缩放 (需要 int):现代模型通常在缩放后还会进行 CenterCrop(中心裁剪),这样可以既保证输入尺寸一致,又保证物体不变形。
python 复制代码
from tkinter import image_types

from torch.utils.tensorboard import SummaryWriter
from PIL import Image
from torchvision import transforms

writer = SummaryWriter("logs") # 日志文件存储位置
img = Image.open("hymenoptera_data/train/ants/0013035.jpg")
print(img)

# ToTensor
tensor_trans = transforms.ToTensor()
img_tensor = tensor_trans(img)
writer.add_image("ToTensor", img_tensor)

# 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)

# Resize
print(img.size)
trans_resize = transforms.Resize((512,512))
# img : PIL -> resize -> PIL
img_resize = trans_resize(img)
# img_resize : PIL -> ToTensor -> tensor
img_resize = tensor_trans(img_resize)
writer.add_image("Resize",img_resize)
print(img_resize)

writer.close()

2.7.4 利用Compose进行resize

Compose其实就是一个聚合的作用,把前面两个工具放一起执行了。

python 复制代码
from tkinter import image_types

from torch.utils.tensorboard import SummaryWriter
from PIL import Image
from torchvision import transforms

writer = SummaryWriter("logs") # 日志文件存储位置
img = Image.open("hymenoptera_data/train/ants/0013035.jpg")
print(img)

# ToTensor
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("ToTensor", img_tensor)

# 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)

# Resize
print(img.size)
trans_resize = transforms.Resize((512,512))
# img : PIL -> resize -> PIL
img_resize = trans_resize(img)
# img_resize : PIL -> ToTensor -> 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)
trans_compose = transforms.Compose([trans_resize_2,trans_totensor])
trans_resize_2 = trans_compose(img)
writer.add_image("Resize",trans_resize_2,1)

writer.close()

2.7.5 随机裁剪RandomCrop

RandomCrop 是 PyTorch 中用于图像数据增强(data augmentation)的函数之一,它可以在图像或张量的随机位置裁剪 出指定大小的区域,不会像Resize那样进行缩放。

transforms.RandomCrop((128, 128))会随机在输入图像中裁剪出大小为 128x128 的区域,并返回裁剪后的图像对象。

  • 图片经过 RandomResizedCrop 后,输出的是 PIL Image(和原图一样是 Python 图片对象)。
  • 而 TensorBoard 只认 Tensor(张量)。
  • 所以必须用 Compose 把这两个动作串起来:先随机挖图 → 再转成张量。
python 复制代码
from tkinter import image_types

from torch.utils.tensorboard import SummaryWriter
from PIL import Image
from torchvision import transforms

writer = SummaryWriter("logs") # 日志文件存储位置
img = Image.open("hymenoptera_data/train/ants/0013035.jpg")
print(img)

# ToTensor
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("ToTensor", img_tensor)

# 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)

# Resize
print(img.size)
trans_resize = transforms.Resize((512,512))
# img : PIL -> resize -> PIL
img_resize = trans_resize(img)
# img_resize : PIL -> ToTensor -> 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)
# PIL -> PIL -> tensor
trans_compose = transforms.Compose([trans_resize_2,trans_totensor])
trans_resize_2 = trans_compose(img)
writer.add_image("Resize",trans_resize_2,1)

# RandomCrop
trans_random = transforms.RandomResizedCrop(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()

2.7.6 使用方法小节

  1. 关注输入和输出类型
  2. 多看官方文档
  3. 关注方法需要什么参数,如果没给的话自己 **print 试一下/断点尝试/type(),**当然了现在是2026,可以问AI了

OK今天就学到这里,撒花!!!

相关推荐
LX567772 小时前
传统销售如何系统学习成为AI智能销售顾问?认证指南
人工智能·学习
Moe4882 小时前
Spring AI Advisors:从链式增强到递归顾问
java·后端
程序员雷欧2 小时前
大模型应用开发学习第六天
人工智能
Bacon2 小时前
前端转型 Agent 开发工程师
人工智能
春末的南方城市2 小时前
比肩顶尖闭源模型!京东开源240亿参数多模态模型JoyAI-Image:统一理解/生成/编辑,重塑AI图像编辑。
人工智能·深度学习·机器学习·计算机视觉·aigc
37手游后端团队2 小时前
Claude Code 指南:终端 AI 编程助手的正确打开方式
人工智能·后端
阿里云大数据AI技术2 小时前
基于PAI的Agent数据构造与模型蒸馏解决方案
人工智能
新缸中之脑2 小时前
我的Stitch -> Claude Code 工作流
人工智能
kyle-fang2 小时前
大模型微调
人工智能·深度学习·机器学习