深度学习------Pytorch数据处理工具箱
目录
一、先解决 “数据加载”:utils.data 的两大核心工具
二、再搞定 “数据预处理”:torchvision 的实用工具
之前手动处理深度学习数据时,简直是 “步步踩坑”:图片散在不同文件夹里,写了几十行代码才读进来;批量加载时维度总对不上,报错 “size mismatch”;训练时想看看损失值变化,只能一遍遍 print,满屏数字根本看不出趋势。今天学了 PyTorch 数据处理工具箱,才发现原来有这么多 “现成工具”—— 从数据加载到预处理,再到训练可视化,一套流程下来省了超多事。整理了我觉得最实用的知识点,用自己踩过的坑当例子,帮和我一样刚入门的小伙伴少走弯路。
一、先解决 “数据加载”:utils.data 的两大核心工具
处理数据的第一步是 “把数据读进模型”,PyTorch 的utils.data里有两个 “神器”——Dataset和DataLoader,搭配起来用简直绝了。
1. Dataset:自定义数据集的 “基础模板”
Dataset是 PyTorch 读取自定义数据的 “标准接口”,不管是 CSV 表格、numpy 数组还是图片,都要继承它并重写三个方法:
__init__:初始化数据集(比如读数据文件、存标签);
__getitem__:按索引取单个样本(必须转成 Tensor,不然模型不认);
__len__:返回数据集总长度(方便后续批量计算)。
我之前用 numpy 存了个简单的 2 维数据集,用Dataset包装后超清爽:
import torch
from torch.utils import data
import numpy as np
# 继承Dataset基类
class MyFirstDataset(data.Dataset):
def __init__(self):
# 初始化数据和标签(比如从CSV读进来的numpy数组)
self.data = np.asarray([[1,2], [3,4], [2,1], [3,4], [4,5]]) # 2维特征
self.label = np.asarray([0, 1, 0, 1, 2]) # 对应的标签
def __getitem__(self, index):
# 单个样本:numpy转Tensor(模型只认Tensor!)
sample_data = torch.from_numpy(self.data[index])
sample_label = torch.tensor(self.label[index])
return sample_data, sample_label # 返回(数据,标签)对
def __len__(self):
# 数据集总样本数
return len(self.data)
# 测试一下
my_data = MyFirstDataset()
print(my_data[2]) # 取索引2的样本,相当于调用__getitem__(2)
print(f"总样本数:{my_data.__len__()}")
运行后会输出(tensor([2, 1], dtype=torch.int32), tensor(0, dtype=torch.int32))和总样本数 5—— 之前手动写循环取样本,还总忘了转 Tensor,现在用Dataset规范多了。
2. DataLoader:批量加载的 “加速器”
Dataset一次只能取一个样本,而模型训练需要 “批量输入”(batch),这时候就需要DataLoader—— 它能自动把Dataset的样本打包成 batch,还能打乱数据、多进程加载,效率直接拉满。
它的参数里有几个新手必调的,我踩过的坑都标在注释里了:
# 用DataLoader包装刚才的数据集
data_loader = data.DataLoader(
dataset=my_data, # 要加载的Dataset
batch_size=2, # 每次加载2个样本
shuffle=False, # 要不要打乱数据(训练时设True,测试时设False!)
num_workers=0, # 多进程加载数(Windows下设0,不然容易报错!)
drop_last=False # 样本数不是batch整数倍时,要不要丢最后一批(比如5个样本,batch=2,不丢的话最后一批1个)
)
# 遍历加载的batch
for batch_idx, (batch_data, batch_label) in enumerate(data_loader):
print(f"第{batch_idx}批:")
print(f"数据:{batch_data}")
print(f"标签:{batch_label}\n")
运行后会输出 3 批数据:前两批各 2 个样本,最后一批 1 个(因为drop_last=False)。之前我没设shuffle=True,训练时模型总 “记熟” 数据顺序,准确率虚高;后来把shuffle改成 True,准确率才正常 —— 这个参数一定要注意!
二、再搞定 “数据预处理”:torchvision 的实用工具
加载数据后,还要做 “预处理”(比如缩放图片、标准化),不然模型训练慢还容易过拟合。torchvision里的transforms和ImageFolder,简直是图像数据的 “救星”。
1. transforms:图像预处理的 “流水线”
transforms提供了各种图像操作,比如缩放、裁剪、翻转、标准化,还能用Compose把这些操作串成 “流水线”,像工厂加工一样处理图片。
我做猫狗分类时,写了个常用的预处理流水线,每个操作的作用都标清楚了:
import torchvision.transforms as transforms
# 用Compose串联操作(顺序很重要!先裁剪再转Tensor,最后标准化)
image_transform = transforms.Compose([
transforms.Resize((224, 224)), # 先把图片缩放到224×224(模型输入要求统一尺寸)
transforms.RandomHorizontalFlip(p=0.5), # 50%概率水平翻转(数据增强,避免过拟合)
transforms.ToTensor(), # 把PIL图片转Tensor:(H,W,C)→(C,H,W),值从[0,255]→[0,1]
transforms.Normalize(mean=(0.5,0.5,0.5), std=(0.5,0.5,0.5)) # 标准化到[-1,1](加速模型收敛)
])
之前我忘了ToTensor这步,直接把 PIL 图片喂给模型,报错 “expected Tensor but got PIL Image”;还有一次没做Normalize,模型训练了 10 轮损失还没降下来 —— 这些预处理步骤真的不能省!
2. ImageFolder:多目录图片的 “自动读取器”
如果图片存在不同文件夹,手动读标签要写一堆代码,而ImageFolder能自动把 “文件夹名” 当标签,直接读取数据 + 标签,省了超多事。
from torchvision import datasets
# 用ImageFolder读取多目录图片
train_dataset = datasets.ImageFolder(
root="../data/cat_dog", # 根目录(里面是子文件夹)
transform=image_transform # 刚才定义的预处理流水线
)
# 包装成DataLoader
train_loader = data.DataLoader(
train_dataset,
batch_size=8,
shuffle=True,
num_workers=0
)
# 查看标签映射(文件夹名→数字标签)
print(f"标签映射:{train_dataset.class_to_idx}") # 输出{'cat':0, 'dog':1}
三、最后搞定 “训练监控”:TensorBoard 可视化
训练时只看 print 的损失值,根本看不出趋势;想看看模型结构对不对,也没法直观检查 —— 这时候就需要TensorBoard,它能把损失值、网络结构、特征图都画出来,训练过程一目了然。
1. TensorBoard 的 “使用四步走”
用TensorBoard很简单,记住四个步骤就行,我以 “可视化损失值” 为例:
from torch.utils.tensorboard import SummaryWriter
import torch.nn as nn
import numpy as np
# 步骤1:实例化SummaryWriter,指定日志保存路径(自动创建logs文件夹)
writer = SummaryWriter(log_dir="logs", comment="linear_train")
# 模拟一个简单的线性回归训练(用来说明可视化)
input_size = 1
output_size = 1
model = nn.Linear(input_size, output_size) # 线性模型
criterion = nn.MSELoss() # 均方损失
optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # SGD优化器
# 生成模拟数据
x_train = np.linspace(-1, 1, 100).reshape(100, 1) # 输入:100个1维数据
y_train = 3 * x_train**2 + 2 + 0.2 * np.random.rand(100, 1) # 输出:带噪声的二次函数
# 步骤2:训练并记录损失值
num_epochs = 60
for epoch in range(num_epochs):
# 数据转Tensor
inputs = torch.from_numpy(x_train).float()
targets = torch.from_numpy(y_train).float()
# 前向传播
outputs = model(inputs)
loss = criterion(outputs, targets)
# 反向传播+优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 记录损失值:add_scalar(标签名,要记录的值,迭代次数)
writer.add_scalar("训练损失值", loss.item(), epoch)
# 步骤3:关闭writer
writer.close()
# 步骤4:启动TensorBoard(在命令行输入)
# tensorboard --logdir=logs --port 6006
# 然后在浏览器打开 http://localhost:6006 查看
打开浏览器后,在 “Scalars” 页面能看到损失值随 epoch 下降的曲线 —— 之前我只能 print 每轮损失,现在看曲线能直观判断模型有没有收敛,比如损失降到 1 以下后不再下降,就知道该调学习率了。
2. 额外技能:可视化网络结构和特征图
TensorBoard还能画网络结构、看特征图,帮我排查了很多问题:
- 可视化网络结构:用
writer.add_graph(model, inputs),能看到每一层的输入输出维度,之前我卷积层的out_channels设错了,看结构时一眼就发现了; - 可视化特征图:用
writer.add_image把卷积层输出的特征图画出来,能看到浅层提取边缘、深层提取纹理,判断模型有没有学到有用的特征。
四、新手总结:数据处理的 “标准流程”
今天学完这些工具,我整理了一套 “数据处理流程”,现在跑项目都按这个来,再也不手忙脚乱了:
- 读数据:用
ImageFolder(多目录图片)或自定义Dataset(其他数据)读取数据 + 标签; - 预处理:用
transforms.Compose串联缩放、翻转、标准化等操作; - 批量加载:用
DataLoader打包成 batch,训练时shuffle=True; - 监控训练:用
TensorBoard记录损失值、画网络结构、看特征图。
现在我用这套流程跑猫狗分类,比之前手动处理数据快了一倍,模型收敛也更稳定了。如果和我一样刚入门,建议先从简单的数据集(比如 MNIST)练手,把这些工具用熟,再挑战复杂项目 ——PyTorch 的工具箱真的很友好,只要找对方法,数据处理一点都不难~
更多推荐


所有评论(0)