共计 2236 个字符,预计需要花费 6 分钟才能阅读完成。
1. CelebA 数据集结构解析
CelebA 数据集包含 202,599 张名人面部图像,每张图像标注有 40 个二进制属性和 5 个关键点坐标。主要文件结构如下:

CelebA/
├── img_align_celeba/ # 图像文件夹(JPEG 格式)├── list_attr_celeba.csv # 属性标注文件
└── list_landmarks_celeba.txt # 关键点坐标文件
属性标注示例(前 5 个属性):
| 图像名称 | 5_o_Clock_Shadow | Arched_Eyebrows | Attractive | Bags_Under_Eyes | Bald |
|---|---|---|---|---|---|
| 000001.jpg | -1 | 1 | 1 | -1 | -1 |
| 000002.jpg | -1 | -1 | -1 | 1 | -1 |
注:1 表示属性存在,- 1 表示不存在
关键点坐标格式:
lefteye_x lefteye_y righteye_x righteye_y nose_x nose_y leftmouth_x leftmouth_y rightmouth_x rightmouth_y
2. 预处理方案对比
OpenCV vs PIL 性能测试(处理 1000 张图像)
| 操作 | OpenCV(ms) | PIL(ms) | 内存峰值 (MB) |
|---|---|---|---|
| 读取图像 | 120 | 180 | 850 |
| 中心裁剪 | 45 | 65 | 900 |
| 水平翻转 | 2 | 5 | 950 |
内存映射优化方案 :
import numpy as np
from PIL import Image
class MappedImageDataset:
def __init__(self, file_paths):
self.file_paths = file_paths
self.mmaps = [np.array(Image.open(f)) for f in file_paths] # 预加载内存映射
def __getitem__(self, idx):
return self.mmaps[idx] # 直接访问内存
3. PyTorch 数据加载实战
自定义 Dataset 实现
import torch
from torch.utils.data import Dataset
class CelebADataset(Dataset):
def __init__(self, img_dir, attr_file, transform=None):
self.img_dir = img_dir
self.attributes = pd.read_csv(attr_file)
self.transform = transform
def __len__(self):
return len(self.attributes)
def __getitem__(self, idx):
img_path = os.path.join(self.img_dir, self.attributes.iloc[idx, 0])
image = Image.open(img_path).convert('RGB')
label = torch.tensor(self.attributes.iloc[idx, 1:].values.astype(int))
if self.transform:
image = self.transform(image)
return image, label
数据增强配置
from torchvision import transforms
train_transform = transforms.Compose([transforms.RandomResizedCrop(178), # 原始图像尺寸
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
多进程加载配置
dataloader = DataLoader(
dataset,
batch_size=64,
num_workers=4, # 建议设置为 CPU 核心数 -1
pin_memory=True # 加速 GPU 传输
)
4. 常见问题避坑指南
- 标签未做 one-hot 编码 :
- 错误现象:直接使用 -1/ 1 会导致 sigmoid 输出不稳定
-
修正方案:将标签转换为 0 / 1 格式
label = (label + 1) // 2 # [-1,1] -> [0,1] -
验证集数据泄露 :
- 错误现象:测试集准确率异常高于验证集
-
预防措施:使用官方划分(train:162770, val:19867, test:19962)
-
batch size 与显存不匹配 :
- 现象:CUDA out of memory 错误
- 计算方法:
显存需求 ≈ batch_size × (3×218×178×4 + 40×4) bytes - 建议:GTX 1080Ti 建议 batch_size≤32
5. 扩展思考
渐进式加载方案
- 按需加载:
class LazyDataset(Dataset): def __getitem__(self, idx): # 每次访问时从磁盘读取 return Image.open(self.paths[idx]) - 分块缓存:将数据集划分为多个 HDF5 文件
有效的数据增强策略
- 几何变换:弹性变形(参考 《Understanding Data Augmentation》)
- 光度变换:随机亮度 / 对比度(对人脸关键点稳定)
结语
通过本文的实践流程,开发者可以系统掌握 CelebA 数据集的处理方法。建议在模型训练时使用 wandb 等工具监控数据加载耗时,根据 GPU 利用率动态调整 num_workers 参数。后续可尝试将预处理流水线迁移到 DALI 等高性能框架,进一步提升训练效率。
正文完
发表至: 未分类
近两天内
