深度学习篇---数据预处理
数据增强是深度学习中一种通过 “人工制造” 多样化数据来提升模型泛化能力的技术。简单说,就是给原始图片 “做手脚”,生成看起来不同但本质内容一致的新图片,让模型见多识广,避免 “认死理”(过拟合)。以下是最常用的 10 种数据增强方法,用通俗语言解释:
1. 旋转(Rotation)
做法:把图片顺时针或逆时针转个角度(比如 - 30° 到 30° 之间随机转)。
例子:一张正立的猫的图片,旋转后变成斜着的猫。
作用:让模型学会识别不同角度的目标(比如猫可能躺歪、站正,都是同一只猫)。
2. 平移(Translation)
做法:把图片向左、右、上、下移动一点(比如最多移原图 10% 的距离),边缘空出来的地方用黑色或其他颜色填充。
例子:原本在图片中间的狗,平移后到了左上角。
作用:让模型适应目标在图片中不同位置的情况(比如照片里的人可能站左边,也可能站右边)。
3. 翻转(Flip)
做法:包括水平翻转(左右翻,像照镜子)和垂直翻转(上下翻,像倒影),最常用的是水平翻转。
例子:一张左手举起来的人,水平翻转后变成右手举起来。
作用:增加数据多样性,且不改变目标本质(人左右手举起来都是同一个人)。
4. 缩放(Scaling)
做法:把图片放大或缩小一点,再裁剪到原来的尺寸。比如先放大 1.2 倍,再裁成原图大小(相当于 “拉近” 看目标);或先缩小 0.8 倍,再用黑边补成原图大小(相当于 “拉远” 看目标)。
例子:一张包含全身的人像,缩放后可能只突出上半身。
作用:让模型适应目标在图片中 “大” 或 “小” 的情况(比如远处的人和近处的人)。
5. 裁剪(Cropping)
做法:从图片中随机截取一块区域(尺寸和原图一样)。比如从一张大风景照中,随机裁出包含山峰的部分,或包含河流的部分。
例子:一张有猫和沙发的图,裁剪后可能只保留猫的头部,或猫 + 部分沙发。
作用:模拟 “目标在图片中占比不同” 的场景,强迫模型关注核心特征(比如不管猫占图多大,都能认出来)。
6. 亮度 / 对比度调整(Brightness/Contrast Adjustment)
做法:随机调亮或调暗图片(亮度),或让目标与背景的差异变大 / 变小(对比度)。
例子:一张白天的照片调暗成黄昏效果,或一张模糊的图调清晰(提高对比度)。
作用:让模型在不同光线条件下都能工作(比如同样的猫,在晴天、阴天、灯光下都能识别)。
7. 色彩抖动(Color Jittering)
做法:轻微改变图片的颜色(比如让红色更红一点,蓝色偏绿一点,或整体色调偏暖 / 偏冷)。
例子:一张绿叶的图片,色彩抖动后可能变成稍微偏黄的叶子。
作用:避免模型 “认颜色不认物”(比如不会因为叶子颜色稍微变了就认成其他植物)。
8. 高斯噪声(Gaussian Noise)
做法:在图片上随机加一些小点(噪点),模拟拍照时的 “模糊” 或 “干扰”。
例子:一张干净的图片,加噪声后看起来有点像老式电视的雪花点。
作用:增强模型的抗干扰能力(比如照片有点模糊或有杂质时,依然能识别目标)。
9. 剪切(Shearing)
做法:把图片 “推歪”,让目标看起来像被拉伸了一个角度(比如长方形变成平行四边形)。
例子:一张正立的杯子,剪切后变成向左边倾斜的杯子(但不是旋转,是形状扭曲)。
作用:让模型适应目标的 “非标准形态”(比如拍照时角度刁钻,目标看起来有点变形)。
10. 混合图像(Mixup)
做法:把两张不同的图片 “混合” 成一张,比如 50% 的猫图片 + 50% 的狗图片,生成一张半猫半狗的图,标签也按比例混合(比如标签是 0.5 猫 + 0.5 狗)。
例子:一张猫的图和一张狗的图叠加,看起来像透明的猫和透明的狗重叠在一起。
作用:让模型学会 “折中” 判断,避免对模糊样本(比如像猫又像狗的动物)做出极端错误的预测。
数据增强的核心原则
- 不改变本质:比如把猫的图片旋转后还是猫,不能变成狗(否则会误导模型)。
- 贴近真实场景:比如雨天拍照会有噪点,就可以加高斯噪声;人不会倒着走路,就少用垂直翻转。
- 按需使用:比如医学影像不能随便调亮度(会掩盖病灶),而普通分类任务可以大胆用多种增强。
通过这些方法,原本 1000 张图片可以 “变” 出几万张,模型见得多了,自然就更会 “举一反三” 了。
pytorch中的实现:
在 PyTorch 框架中,图像数据处理流程主要通过torchvision
库实现,核心目标是将原始图像文件转换为模型可接收的张量格式,并通过预处理增强数据多样性。以下是完整的处理流程、原理解释及代码实现:
一、图像数据处理核心流程
完整流程可分为 5 个步骤,形成数据管道(Data Pipeline):
- 数据读取:从磁盘加载图像文件(如 JPG、PNG)
- 格式转换:将图像转为 PIL 格式(便于后续处理)
- 数据增强:对训练集进行随机变换(如旋转、翻转),验证集仅做标准化
- 格式标准化:转为张量并标准化(减均值、除标准差)
- 批量加载:按批次读取数据并打乱顺序
二、关键步骤原理解释
1. 数据读取
- 原理:通过
ImageFolder
或自定义Dataset
类,按文件夹结构读取图像(通常训练集和验证集分开存放,每个类别对应一个子文件夹)。 - 优势:无需手动维护标签列表,文件夹名称即类别标签。
2. 数据增强(核心)
- 训练集增强:通过随机变换增加数据多样性,避免模型过拟合。常用操作包括:
- 随机裁剪(
RandomResizedCrop
):模拟目标在不同位置和尺度的出现 - 随机翻转(
RandomHorizontalFlip
):适应左右方向变化 - 色彩抖动(
ColorJitter
):模拟不同光照和色彩条件
- 随机裁剪(
- 验证集处理:仅做确定性变换(如中心裁剪、固定缩放),保证评估一致性。
3. 标准化(Normalization)
- 原理:将图像像素值(0-255)转换为均值为 0、标准差为 1 的分布,公式为:
output=stdinput−mean - 作用:加速模型收敛(避免不同通道像素值差异过大影响梯度更新)。
- 常用参数:ImageNet 数据集的均值
[0.485, 0.456, 0.406]
和标准差[0.229, 0.224, 0.225]
(适用于预训练模型)。
4. 批量加载(DataLoader)
- 原理:将处理后的图像按批次(batch size)加载,支持多线程并行读取(
num_workers
)和随机打乱(shuffle
)。 - 优势:提高数据读取效率,避免 GPU 等待 CPU 加载数据的瓶颈。
三、完整代码实现
以下代码实现了从数据读取到批量加载的全流程,包含训练集和验证集的不同处理策略:
import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader# 1. 定义数据增强和预处理策略
# 训练集:使用随机增强增加多样性
train_transform = transforms.Compose([transforms.RandomResizedCrop(224), # 随机裁剪并缩放到224x224transforms.RandomHorizontalFlip(p=0.5), # 50%概率水平翻转transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2), # 随机调整亮度、对比度、饱和度transforms.ToTensor(), # 转换为张量(HWC→CHW,像素值归一化到0-1)transforms.Normalize(mean=[0.485, 0.456, 0.406], # 标准化(使用ImageNet均值和标准差)std=[0.229, 0.224, 0.225])
])# 验证集:仅做确定性处理,保证评估一致性
val_transform = transforms.Compose([transforms.Resize(256), # 缩放到256x256transforms.CenterCrop(224), # 中心裁剪到224x224transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
])# 2. 读取数据集(假设数据按文件夹结构存放)
# 文件夹结构示例:
# data/
# train/
# class1/
# img1.jpg, img2.jpg...
# class2/
# img1.jpg, img2.jpg...
# val/
# class1/
# class2/data_dir = "data" # 数据集根目录
train_dataset = datasets.ImageFolder(root=f"{data_dir}/train",transform=train_transform
)
val_dataset = datasets.ImageFolder(root=f"{data_dir}/val",transform=val_transform
)# 3. 查看数据集信息
print(f"训练集类别:{train_dataset.classes}")
print(f"训练集样本数:{len(train_dataset)}")
print(f"验证集样本数:{len(val_dataset)}")# 4. 批量加载数据
batch_size = 32
train_loader = DataLoader(train_dataset,batch_size=batch_size,shuffle=True, # 训练集打乱顺序num_workers=4 # 4个线程并行读取(根据CPU核心数调整)
)
val_loader = DataLoader(val_dataset,batch_size=batch_size,shuffle=False, # 验证集不打乱num_workers=4
)# 5. 测试数据加载效果
def test_dataloader(loader):# 获取一个批次的数据images, labels = next(iter(loader))print(f"图像张量形状:{images.shape}") # 输出 (batch_size, channels, height, width)print(f"标签形状:{labels.shape}") # 输出 (batch_size,)print(f"像素值范围:[{images.min():.2f}, {images.max():.2f}]") # 标准化后应在[-2.3, 2.7]左右print("\n训练集批次信息:")
test_dataloader(train_loader)
print("\n验证集批次信息:")
test_dataloader(val_loader)
四、代码关键细节说明
数据增强选择:
- 训练集的
RandomResizedCrop
同时实现随机缩放和裁剪,比固定裁剪更能模拟真实场景。 ColorJitter
的参数(如brightness=0.2
)表示在 ±20% 范围内调整,避免过度增强导致失真。
- 训练集的
标准化参数:
使用 ImageNet 的均值和标准差是因为大多数预训练模型(如 ResNet、VGG)基于该数据集训练,保持一致的输入分布可提升微调效果。若为自定义数据集,需计算自己的均值和标准差。DataLoader 参数:
num_workers
:建议设为 CPU 核心数(如 4 核 CPU 设为 4),过大会导致内存占用过高。shuffle=True
:仅用于训练集,确保每个 epoch 的样本顺序不同,增强模型泛化能力。
自定义数据集:
若数据不满足ImageFolder
的文件夹结构(如标签存于 CSV 文件),可通过继承torch.utils.data.Dataset
类实现自定义读取逻辑,核心重写__len__
和__getitem__
方法。
五、扩展:自定义数据集示例
当数据标签存于 CSV 文件时,可按以下方式自定义数据集:
import pandas as pd
from PIL import Image
from torch.utils.data import Datasetclass CustomDataset(Dataset):def __init__(self, csv_path, img_dir, transform=None):self.df = pd.read_csv(csv_path) # CSV格式:image_name, labelself.img_dir = img_dirself.transform = transformdef __len__(self):return len(self.df)def __getitem__(self, idx):img_name = self.df.iloc[idx]['image_name']img_path = f"{self.img_dir}/{img_name}"image = Image.open(img_path).convert('RGB') # 读取图像并转为RGBlabel = self.df.iloc[idx]['label']if self.transform:image = self.transform(image)return image, label# 使用自定义数据集
train_dataset = CustomDataset(csv_path="train_labels.csv",img_dir="train_images",transform=train_transform
)
通过上述流程,可将原始图像高效转换为适合模型训练的输入格式,同时通过数据增强提升模型的泛化能力。实际应用中需根据任务特点(如医学影像、遥感图像)调整增强策略,避免破坏关键特征。