Dataset - DeepFashion:从数据构建到时尚AI应用实战
1. 从零开始认识DeepFashion你的时尚AI“弹药库”如果你对用AI做点跟时尚相关的事情感兴趣比如让机器自动识别一件衣服是“圆领T恤”还是“高腰阔腿裤”或者想做一个能根据用户上传的图片推荐相似款式的购物助手那你大概率绕不开一个名字DeepFashion。我第一次接触这个数据集是在做一个服装风格迁移的小项目当时找数据找得头大直到发现了它感觉就像在沙漠里找到了绿洲。简单来说DeepFashion就是一个专门为计算机视觉和时尚AI研究打造的大型“弹药库”。它不是什么商业公司的私有数据而是由学术机构公开的包含了海量的服装图片和极其丰富的标注信息。原始文章里提到了它的两个主要部分一个是用于服装类别和属性预测的数据集有将近29万张图片另一个是用于服装关键点Fashion Landmark检测的数据集有12万多张图片。这些数字听起来可能有点抽象我打个比方这就像你为了教一个小孩认识衣服不仅给他看了几十万张各种衣服的照片还每张照片都附上了详细的说明书告诉他“这是上衣材质是棉有印花领口在这里袖口在那里”。有了这么详细的“教材”AI模型才能学得又快又好。为什么我说它是“实战派”的首选呢因为很多公开数据集要么图片数量少要么标注太简单比如只告诉你这张图是“狗”还是“猫”。而DeepFashion的标注维度之多简直是为工业级应用量身定做的。它不仅仅告诉你图片里是“连衣裙”类别还告诉你这条裙子是“蕾丝面料”、“A字版型”、“及膝长度”属性甚至用一个个点精确标出了领口、袖口、腰线、下摆的位置关键点。这意味着基于它你可以训练出的模型能力是立体的既能做基础的分类这是什么衣服也能做精细的属性分析这件衣服有什么特点还能理解衣服的结构各个部件在哪。对于想真正做出点东西的算法工程师或研究者来说这种高质量、多任务的数据集就是最宝贵的起点。接下来我就带你一步步把这个“弹药库”搬回家并把它变成你模型训练流水线里高效运转的一部分。2. 实战第一步获取与解析DeepFashion数据拿到数据是万里长征的第一步但这一步走不好后面全是坑。DeepFashion的数据通常可以从论文作者的项目页面或一些学术数据平台找到原始文章里也提到了百度网盘的链接虽然时效性需要确认。这里我分享一个更通用的思路和需要注意的细节。2.1 数据下载与初步检查假设你已经通过官方渠道比如联系论文作者或访问GitHub项目拿到了数据压缩包。解压后你会看到类似这样的结构以“服装类别和属性预测集”为例DeepFashion_Category/ ├── Img/ │ ├── 000001.jpg │ ├── 000002.jpg │ └── ... (共289,222张图片) ├── list_bbox.txt ├── list_category_img.txt ├── list_category_cloth.txt ├── list_attr_img.txt ├── list_attr_cloth.txt └── list_eval_partition.txt我的第一个建议是别急着写代码先花10分钟浏览一下这些文本文件。用文本编辑器打开list_category_img.txt你会看到前几行是这样的000001.jpg 1 000002.jpg 2 ...这很容易理解图片名和对应的类别标签。但注意这个标签是数字你需要list_category_cloth.txt来查表把数字1对应到“Anorak”带风帽的厚夹克。同样list_attr_img.txt里的标注是1000维的向量1代表有该属性-1代表没有0代表未知。这里有个小坑原始文章说属性有1000种但实际读取文件时你会发现向量长度确实是1000但list_attr_cloth.txt里列出的属性名称可能略有出入需要以实际文件为准。我建议写个简单的Python脚本快速验证一下数据量是否匹配以及是否有损坏的图片文件。import os from PIL import Image img_dir DeepFashion_Category/Img label_file DeepFashion_Category/list_category_img.txt # 检查图片数量 all_imgs os.listdir(img_dir) print(f图片文件夹内文件数{len(all_imgs)}) # 检查标注文件行数减去表头 with open(label_file, r) as f: lines f.readlines() # 通常前两行是说明第三行开始是数据 num_annotations len(lines) - 2 print(f标注文件行数数据量{num_annotations}) # 快速抽查几张图片是否能正常打开 for img_name in all_imgs[:5]: try: img_path os.path.join(img_dir, img_name) img Image.open(img_path) img.verify() # 验证文件完整性 print(f{img_name}: 正常) except Exception as e: print(f{img_name}: 损坏 - {e})这个简单的检查能帮你提前发现数据包不完整或下载损坏的问题避免训练到一半才报错的尴尬。2.2 深入理解标注文件的结构与含义知道文件里有什么之后我们要理解每个标注到底怎么用。这步理解透了后面模型设计才能有的放矢。边界框BBoxlist_bbox.txt。格式是[x1, y1, x2, y2]这是目标检测里最常用的格式表示矩形框左上角和右下角的坐标。重要提示这些坐标是基于**原始图片被缩放后最长边为300像素**的尺寸。如果你在预处理时改变了图片大小记得同步缩放这些坐标。类别Categorylist_category_img.txt和list_category_cloth.txt。这是一个标准的单标签分类任务。但有趣的是原始文章指出虽然有50个类别名但实际标注中只使用了46个ID缺少了38, 45, 49, 50。这是一个关键细节你在构建标签映射字典时不能简单地用1到50而要使用文件中实际出现的ID否则会遇到标签越界错误。类别还分“上身(1)”、“下身(2)”、“全身(3)”这个信息在有些模型结构比如针对不同服装类型设计不同网络分支时可能有用。属性Attributelist_attr_img.txt和list_attr_cloth.txt。这是典型的多标签分类问题。一件衣服可以同时具有“条纹”纹理、“棉”面料、“修身”形状等多个属性。标注向量中的“-1”需要小心处理。在训练时常见的做法是将“-1”不存在和“1”存在作为有效标签而将“0”未知在计算损失时忽略掉即不对该属性的预测做惩罚。关键点Landmark在另一个数据集中。标注格式包含了可见性visibility和坐标x, y。可见性通常有三种2可见且已标注1遮挡或模糊但位置可推测0不可见。在训练姿态或关键点估计模型时通常只对可见性为1和2的点计算损失。数据划分list_eval_partition.txt。它指明了每张图片属于训练集train、验证集val还是测试集test。务必严格遵守这个划分尤其是如果你想和论文中的基准模型性能做公平对比。自己随机划分会导致结果不可比。理解这些你就知道手里的“弹药”是什么型号、怎么上膛了。接下来我们要把这些原始数据加工成模型能直接“吃”的格式。3. 构建高效数据管道预处理与Dataset类编写原始数据就像一堆需要组装的零件而PyTorch或TensorFlow的Dataset类就是我们的组装流水线。目标是把图片加载、标注解析、数据增强等步骤封装起来让训练循环能像for image, label in dataloader:这样简洁地调用。3.1 数据预处理与增强策略在把数据喂给模型之前通常需要做标准化处理。对于图像最常见的是减去均值、除以标准差这有助于模型收敛。我们可以计算数据集的均值和标准差或者直接使用ImageNet数据集上统计的通用值mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]因为很多预训练模型是在这个统计上训练的。数据增强是提升模型泛化能力、防止过拟合的利器。对于时尚图像我常用的增强组合包括随机水平翻转衣服左右对称翻转很合理。但要小心有些属性可能不适用比如“左衽”和“右衽”在汉服中是特定的但DeepFashion数据集中西式服装为主问题不大。随机旋转/裁剪小幅度的旋转和随机裁剪可以模拟拍摄角度的变化。颜色抖动轻微调整亮度、对比度、饱和度模拟不同光照和拍摄设备的影响。谨慎使用的增强避免使用过大角度的旋转、扭曲因为这会严重破坏服装的关键点位置和空间结构对于需要精确定位的任务如关键点检测可能是灾难性的。这里给出一个用albumentations库一个非常强大的图像增强库定义增强管道的例子import albumentations as A from albumentations.pytorch import ToTensorV2 # 训练阶段的增强 train_transform A.Compose([ A.Resize(height224, width224), # 统一缩放到模型输入尺寸 A.HorizontalFlip(p0.5), A.Rotate(limit15, p0.3), # 小角度旋转 A.RandomBrightnessContrast(brightness_limit0.1, contrast_limit0.1, p0.3), A.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ToTensorV2(), ]) # 验证/测试阶段的增强通常只进行缩放和标准化 val_transform A.Compose([ A.Resize(height224, width224), A.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ToTensorV2(), ])3.2 编写PyTorch Dataset类现在我们来创建一个自定义的Dataset类它负责在运行时读取图片、应用标注、应用增强。下面是一个支持多任务学习同时输出类别和属性标签的Dataset类框架import torch from torch.utils.data import Dataset from PIL import Image import os import numpy as np class DeepFashionMultiTaskDataset(Dataset): def __init__(self, img_dir, partition_file, bbox_file, category_file, attr_file, transformNone, phasetrain): Args: img_dir: 图片根目录 partition_file: 划分文件路径 ... 其他标注文件路径 transform: 数据增强变换 phase: train, val, 或 test self.img_dir img_dir self.transform transform # 1. 加载数据划分只保留当前phase的数据 self.img_names [] with open(partition_file, r) as f: lines f.readlines()[2:] # 跳过前两行说明 for line in lines: img_name, part line.strip().split() if part phase: self.img_names.append(img_name) # 2. 加载类别标签映射 self.cat_id_to_name {} self.cat_name_to_id {} with open(category_file, r) as f: lines f.readlines()[2:] for line in lines: cat_name, cat_type line.strip().split() # 注意这里需要根据实际文件格式调整解析逻辑 # 假设格式是 Anorak 1 self.cat_id_to_name[len(self.cat_id_to_name)1] cat_name self.cat_name_to_id[cat_name] len(self.cat_name_to_id)1 # 3. 加载属性标签映射类似方法 # 4. 加载图片到类别、图片到属性的映射字典 # 为了简洁这里省略具体的加载代码原理是读取txt文件存入字典key为图片名 self.img_to_category self._load_mapping(...) self.img_to_attributes self._load_mapping(...) def __len__(self): return len(self.img_names) def __getitem__(self, idx): img_name self.img_names[idx] img_path os.path.join(self.img_dir, img_name) # 加载图片 image Image.open(img_path).convert(RGB) image np.array(image) # 转换为numpy数组供albumentations使用 # 获取标签 category_label self.img_to_category[img_name] # 假设是整数ID attr_label self.img_to_attributes[img_name] # 假设是1000维的numpy数组值为1/-1/0 # 处理属性标签将-1,0,1转换为多标签常用的0/1并处理未知标签 # 常见策略1-1, -1-0, 0--1 (在损失函数中忽略) attr_label_tensor torch.from_numpy(attr_label).float() # 或者进行更复杂的转换... # 应用数据增强 if self.transform: augmented self.transform(imageimage) image augmented[image] # 返回多任务数据 return image, {category: category_label, attributes: attr_label_tensor}这个Dataset类是一个强大的基础。你可以根据任务扩展它比如增加边界框的返回用于检测或者增加关键点坐标用于姿态估计。关键是它把繁琐的数据读取和解析工作封装了起来后面我们用DataLoader加载时就会非常清爽。4. 模型训练实战从分类到多标签识别数据管道搭好了接下来就是挑选模型、定义任务和开始训练。DeepFashion数据集的丰富性允许我们尝试多种任务。4.1 服装类别分类单标签这是最直接的任务。我们可以直接使用在ImageNet上预训练好的经典模型比如ResNet、EfficientNet、Vision Transformer (ViT) 等将其最后的全连接层原本输出1000类替换为输出46类根据实际类别数的新层。训练技巧微调Fine-tuning这是标准操作。冻结模型前面的卷积层只训练最后几层和新的分类头。训练几个epoch后再解冻所有层进行微调学习率要设置得更小。处理类别不平衡原始文章给出的每个类别的图片数量差异巨大从几十张到几万张。直接训练模型会偏向于样本多的类别。解决办法有在DataLoader中使用WeightedRandomSampler让样本少的类别在每个epoch中被抽到的概率更高。在损失函数中使用nn.CrossEntropyLoss的weight参数给样本少的类别更大的损失权重。对样本少的类别进行过采样或者对样本多的类别进行欠采样。import torch.nn as nn import torchvision.models as models class FashionClassifier(nn.Module): def __init__(self, num_classes46, pretrainedTrue): super(FashionClassifier, self).__init__() # 加载预训练的ResNet50 self.backbone models.resnet50(pretrainedpretrained) # 获取原始全连接层的输入特征数 num_features self.backbone.fc.in_features # 替换最后的全连接层 self.backbone.fc nn.Linear(num_features, num_classes) def forward(self, x): return self.backbone(x) # 定义加权损失函数 from collections import Counter # 假设你有一个列表 train_labels 包含了所有训练集的类别ID label_counts Counter(train_labels) total_samples sum(label_counts.values()) class_weights [total_samples / (len(label_counts) * count) for _, count in sorted(label_counts.items())] class_weights_tensor torch.FloatTensor(class_weights).to(device) criterion nn.CrossEntropyLoss(weightclass_weights_tensor)4.2 服装属性识别多标签这是DeepFashion数据集更精华的部分。我们需要一个能同时输出1000个二进制预测有/无的模型。结构上我们依然可以用ResNet等作为特征提取器但最后的全连接层要输出1000维并且每个维度之后接一个Sigmoid激活函数将其映射到[0,1]之间表示拥有该属性的概率。损失函数多标签任务通常使用二元交叉熵损失Binary Cross-Entropy Loss。我们需要处理标签中的“未知”0。一种常见的做法是在计算损失时只对那些标签明确为1有或-1无的属性进行计算忽略标签为0的属性。这可以通过在损失函数中设置ignore_index或手动实现掩码mask来实现。class FashionAttributeModel(nn.Module): def __init__(self, num_attributes1000, pretrainedTrue): super(FashionAttributeModel, self).__init__() self.backbone models.resnet50(pretrainedpretrained) num_features self.backbone.fc.in_features # 输出维度为属性数量 self.backbone.fc nn.Linear(num_features, num_attributes) self.sigmoid nn.Sigmoid() def forward(self, x): features self.backbone(x) return self.sigmoid(features) # 输出每个属性的概率 # 自定义损失函数处理未知标签 def masked_bce_loss(preds, targets, ignore_val0): preds: 模型预测值 (batch_size, num_attrs) targets: 真实标签 (batch_size, num_attrs)值为 1, -1, 或 0 ignore_val: 需要忽略的标签值这里是0 # 创建掩码忽略标签为0的位置 mask (targets ! ignore_val).float() # 将标签-1转换为0用于BCE Loss targets_bce (targets 1).float() # 计算BCE Loss loss nn.BCELoss(reductionnone)(preds, targets_bce) # 应用掩码并求平均 loss (loss * mask).sum() / (mask.sum() 1e-8) return loss训练策略多标签任务中正负样本有属性和无属性通常也极不平衡。除了在损失函数层面处理也可以在数据层面进行采样策略的调整。此外由于属性之间存在相关性例如“丝绸”面料很可能与“礼服”风格同时出现可以考虑在模型结构中加入注意力机制或使用图神经网络GNN来建模属性间的关系但这属于更进阶的优化了。4.3 联合训练与模型设计思路既然数据同时提供了类别和属性标签一个很自然的想法是进行多任务学习Multi-Task Learning, MTL。我们可以设计一个共享主干网络Backbone然后分出两个任务头Heads一个用于分类一个用于属性预测。这样两个任务共享低层视觉特征可以相互促进提升模型的泛化能力。class FashionMultiTaskModel(nn.Module): def __init__(self, num_categories46, num_attributes1000, pretrainedTrue): super(FashionMultiTaskModel, self).__init__() backbone models.resnet50(pretrainedpretrained) # 移除原来的全连接层和平均池化层视情况而定 self.feature_extractor nn.Sequential(*list(backbone.children())[:-2]) self.global_pool nn.AdaptiveAvgPool2d((1, 1)) # 任务特定头 self.category_head nn.Linear(backbone.fc.in_features, num_categories) self.attribute_head nn.Sequential( nn.Linear(backbone.fc.in_features, 512), nn.ReLU(), nn.Dropout(0.5), nn.Linear(512, num_attributes), nn.Sigmoid() ) def forward(self, x): features self.feature_extractor(x) pooled self.global_pool(features).squeeze() cat_out self.category_head(pooled) attr_out self.attribute_head(pooled) return cat_out, attr_out在训练时我们需要计算两个损失分类损失交叉熵和属性损失掩码BCE然后按一定权重加起来作为总损失。权重的设置可以手动调整也可以设计自适应的方法。多任务学习往往能学到更鲁棒的特征表示尤其是在某个任务数据有限的情况下另一个任务可以起到正则化的作用。5. 超越分类关键点检测与时尚应用展望DeepFashion的“Fashion Landmark”数据集将我们的能力边界从“识别是什么”扩展到了“理解在哪里”。这对于许多前沿的时尚AI应用至关重要。5.1 服装关键点检测模型搭建关键点检测本质上是一个密集预测问题我们需要为图片上的每个像素点预测其属于某个关键点的概率。常用的模型架构是**编码器-解码器Encoder-Decoder**结构比如U-Net或基于HRNetHigh-Resolution Network的架构。HRNet能在整个过程中保持高分辨率特征图对于需要精确定位的任务非常有效。我们可以使用torchvision中提供的预训练模型作为编码器Backbone然后接上一个解码器Decoder来生成热图Heatmap。每个关键点对应一张热图热图上该点位置的值最高。import torch.nn.functional as F class FashionLandmarkDetector(nn.Module): def __init__(self, num_landmarks8, pretrainedTrue): super(FashionLandmarkDetector, self).__init__() # 使用ResNet作为编码器取中间层特征 backbone models.resnet50(pretrainedpretrained) self.layer1 nn.Sequential(backbone.conv1, backbone.bn1, backbone.relu, backbone.maxpool, backbone.layer1) self.layer2 backbone.layer2 self.layer3 backbone.layer3 self.layer4 backbone.layer4 # 简单的解码器上采样卷积 self.upconv4 nn.ConvTranspose2d(2048, 256, kernel_size4, stride2, padding1) self.upconv3 nn.ConvTranspose2d(256, 128, kernel_size4, stride2, padding1) self.upconv2 nn.ConvTranspose2d(128, 64, kernel_size4, stride2, padding1) self.final_conv nn.Conv2d(64, num_landmarks, kernel_size1) def forward(self, x): x1 self.layer1(x) x2 self.layer2(x1) x3 self.layer3(x2) x4 self.layer4(x3) # 逐步上采样并融合特征这里简化了实际中常使用跳跃连接 u4 self.upconv4(x4) u3 self.upconv3(u4 x3) # 需要调整x3的通道数 u2 self.upconv2(u3 x2) # 需要调整x2的通道数 heatmaps self.final_conv(u2) # 将热图缩放到原始输入尺寸 heatmaps F.interpolate(heatmaps, size(256, 256), modebilinear, align_cornersFalse) return heatmaps损失函数关键点检测常用均方误差损失MSE Loss或Mean Squared Error (MSE)来比较预测热图和真实热图通常以关键点为中心生成一个2D高斯核的差异。同样需要根据关键点的可见性visibility来对损失进行加权不可见的关键点不参与计算。5.2 落地应用场景与挑战当你成功训练出能准确识别类别、属性和关键点的模型后这些能力可以组合起来解锁很多实用的时尚AI应用智能时尚搜索与推荐用户上传一张街拍图你的系统可以识别出图中的服装类别如“牛仔裤”、属性如“破洞”、“直筒”然后在商品库中精准检索出相似款。结合关键点甚至可以实现“以图搜同款”时对齐服装的版型和结构让结果更准确。虚拟试衣与搭配关键点检测是虚拟试衣的基础。准确定位领口、袖口、腰身、下摆后才能将一件虚拟服装“穿”到人物图像上并保证贴合自然。属性识别则可以帮助系统自动生成搭配建议比如“这件丝绸衬衫可以搭配一条垂感好的西装裤”。时尚趋势分析对海量社交媒体图片进行自动化分析统计不同季节、地区流行的服装类别、颜色、材质属性从而预测时尚趋势。电商平台自动化运营自动为商家上传的商品图片打上丰富的类别和属性标签节省大量人工标注成本并提升搜索和筛选的体验。当然从实验室模型到稳定可靠的工业应用还有很长的路要走。你会遇到数据分布差异训练数据是街拍但应用场景是电商白底图、复杂背景干扰、服装遮挡、类别长尾分布等挑战。解决这些问题可能需要收集更多领域特定的数据进行微调设计更鲁棒的模型架构或者利用半监督、自监督学习来利用海量的无标注数据。在我自己的项目中踩过最大的一个坑就是忽略了关键点“可见性”标签的处理。一开始我把所有标注点都同等对待结果模型对遮挡严重的关键点预测非常混乱。后来根据可见性标签对损失进行加权完全可见的权重最高推测位置的次之不可见的权重为0模型的定位精度才有了显著提升。所以处理数据时一定要吃透每一个标注字段的含义它往往藏着提升模型性能的关键线索。DeepFashion这座宝库值得你花时间细细挖掘它的价值远不止于跑通一个基线模型而在于为你提供了探索更广阔时尚AI世界的坚实跳板。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2409832.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!