十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LFW人脸数据集lfw_home.zip拆解:目录结构、加载与实战

LFW人脸数据集lfw_home.zip拆解:目录结构、加载与实战 简介这是面向人脸识别研究者与深度学习初学者的经典数据集资源围绕 LFW 基准整理而成用于人脸验证、辨识算法训练与性能对比。压缩包内共 9 个文件主要包含图像归档、配对标注文件、Python 序列化数据与辅助脚本其中 tgz 归档存放经预处理的人脸图像txt 文件提供训练/开发/测试集的同人异人配对pkl 与 json 则便于加载中间特征或元数据py 脚本可用于自动化处理与作业调度整体大小约 241.84MB。已有 506 人学习下载。借助该资源使用者可快速搭建标准的人脸验证实验环境理解 LFW 的协议划分并通过配对样本与标签文件完成模型训练、指标评估及错误分析说明文档和工具脚本也有助于降低复现门槛。 拿到手的是一个再普通不过的压缩包lfw_home.zip。这个文件名第一眼看上去有点奇怪既不是官方发布的lfw.tgz也不是常见的lfw-funneled.tgz而是一个带了home后缀的zip包。如果你和我一样是从某个开源项目、老教程或者团队内部网盘里把它扒拉下来的那大概率会遇到同一个问题这里面到底装了什么目录结构是什么样的怎么把它喂给模型训练今天就把这个包从头到尾拆一遍顺带把我踩过的坑也一并倒出来。1. lfw_home.zip到底是什么一个不算新的经典数据集先给结论lfw_home.zip本质上是LFW人脸数据集的一个“家目录打包”LFW全称是Labeled Faces in the Wild最早由马萨诸塞大学阿默斯特分校发布专门用来研究真实场景下的人脸识别问题。所谓“wild”指的是照片不是在影棚里拍的而是从新闻、网络、活动照片里收集来的姿态、光照、表情、遮挡都乱七八糟。早期的人脸识别算法在实验室数据集上跑得挺漂亮一到这种“野生”场景就崩LFW就是为了解决这个痛点出现的。为什么叫lfw_home而不是直接叫lfw我个人的判断是这多半是第三方制作压缩包时为了区分层级做的命名解压出来会得到一个lfw_home文件夹里面再放lfw、lfw_funneled、lists这些子目录。官方发布的数据只是图片和列表文件但实际项目使用中通常还需要配套的开发目录、说明文档于是有人就把这些凑在一起打了个包用home表示“这是整个家的根目录”。你实际拿到手的lfw_home.zip解压后大概率和我下面描述的目录结构一致。这个数据集到今天还有使用价值吗说实话拿它刷SOTA肯定是不现实了但做以下几类事情依然非常合适做人脸识别、人脸验证、人脸属性分析的学习和baseline实验验证自己写的训练pipeline和数据加载器是否正确做迁移学习、度量学习的小规模起步验证写课程作业、毕业设计或者在组内快速搭个演示demo。所以如果你刚接触人脸识别或者只是想在本地数据上快速跑通一套流程lfw_home.zip仍然是个相当顺手的“手边数据集”。别急着把它当成老古董扔一边先解压了再说。2. 解压前的准备工作压包类型、体积与校验2.1 先摸清楚压缩格式虽然文件名写的是zip但网络上传的资源难免被二次处理过名字不一定靠得住。正确做法是先用file命令看一眼真实格式file lfw_home.zip正常输出应该是Zip archive data字样。如果显示的是gzip压缩的tar包那就说明有人改过后缀需要按.tar.gz的方式解压。这种细节在Linux服务器上操作时特别常见我遇到过不止一次。2.2 磁盘占用与解压时长预估LFW数据集本身包含一万多张250x250的JPEG图片压缩包体积大约在200MB上下不同版本有差异解压后占用空间会到300MB左右。这个体量对现在的硬盘来说不算什么但如果在内存吃紧的容器环境里一次性全量加载进内存还是会让机器卡顿。我建议解压前先确认目标分区至少有1GB的余量避免解压到一半报No space left on device。2.3 MD5校验确认数据完整性从非官方渠道拿到的包我习惯先对一下校验值。官方LFW数据集的MD5在网上能查到但lfw_home.zip是第三方打包的校验值未必能对上。即便如此算一次MD5也值得md5sum lfw_home.zip这一步至少能确认文件在传输过程中没有损坏。之前有次我图省事直接解压结果某张图片读取到一半报EOFError排查半天才发现是压缩包损坏重新下载才解决。从那以后凡是超过100MB的包我解压前都会随手算一下校验值。2.4 解压命令和权限处理确认无误后解压本身很简单unzip lfw_home.zip解压时注意两点第一如果包内根目录名是lfw_home而不是散落一堆文件直接在当前目录解压最稳妥第二如果解压后提示权限问题用ls -l看下目录权限必要时chmod -R urw lfw_home纠正一下。服务端解压的文件经常会遇到属主不对的问题尤其是从别人机器上拷过来的包特别容易出现“能看图但无法写文件”的怪象。3. 解压后的目录结构拆解每一层文件夹放的是什么东西3.1 顶层结构lfw、lfw_funneled、lists一个都不能少解压完成后lfw_home目录下的典型结构是这样的lfw_home/ ├── lfw/ │ ├── Aaron_Eckhart/ │ │ ├── Aaron_Eckhart_0001.jpg │ │ └── Aaron_Eckhart_0002.jpg │ ├── Aaron_Guiel/ │ │ └── Aaron_Guiel_0001.jpg │ └── ... ├── lfw_funneled/ │ └── ... ├── lists/ │ ├── people.txt │ ├── pairs.txt │ ├── train.txt │ └── test.txt └── README.txtlfw和lfw_funneled是两套图片目录lists里是官方标注文件README.txt一般是对数据集的说明。别小看这个结构很多拿到包的人就是没搞懂lfw和lfw_funneled的区别在后面训练时白白浪费时间。3.2 人名目录的含义一个文件夹就是一个人在lfw目录下每个人名对应一个文件夹文件夹名就是人的名字例如Aaron_Eckhart、George_W_Bush这类格式。文件夹内部是这个人多张角度、表情不同的照片命名统一为人名_编号.jpg比如Aaron_Eckhart_0001.jpg。编号从0001开始递增但一个人手里到底有几张图完全看真实数据里的出现频率有的人只有一张有的人有十几张甚至几十张。这里需要特别提醒文件夹名既是“身份标签”又是“类别名”后续处理时最好不要改动这些名字否则很容易在数据集划分、结果验证时把自己绕晕。我早期做实验时嫌名字太长自作主张把文件夹重命名成class_01这种形式结果pairs.txt里的对应关系全对不上白白排查了大半天。3.3 lists目录下的关键列表文件people、pairs、train、testlists目录里的文件是数据集的“说明书”people.txt每一行是一门人名的记录格式通常是名字 图片数比如Aaron_Eckhart 2后面跟着具体的图片文件名。这个文件主要用于统计和划分身份类别。pairs.txt这是LFW最核心的验证协议文件定义了人脸验证任务中“是同一个人”和“不是同一个人”的图片对并且预先划分好了10折交叉验证的集合。训练和评估人脸验证模型时几乎都是围绕这个文件来的用它可以公平地和历史方法做对比。train.txt和test.txt在部分版本的lfw_home中存在。它们提供了按指定协议划分好的训练集和测试集列表通常用于“image-restricted”这种不依赖身份标签信息的训练设置。日常使用中people.txt是分类任务的依据pairs.txt是验证任务的依据train.txt和test.txt则在你不想自己动手划分数据集时可以拿来直接用。3.4 原始图与funneled对齐图的差异lfw和lfw_funneled两套图内容上是对应的但处理方式不同。lfw是未经对齐的原始人脸图直接从原图中裁切出来脸部位置、角度、尺度都不统一lfw_funneled则是经过“漏斗”对齐方法处理过的版本会把人眼、鼻子等关键位置做归一化让脸在图片里的大致位置和尺度更接近。实际选哪套我的经验是做通用人脸算法验证用funneled更快更稳训练时省去不少预处理麻烦但如果你要测试算法在完全不规则、没对齐情况下的鲁棒性那lfw原始图更有价值。另外注意两套图片虽然是同一批人的但不要混在一起用训练集和测试集必须来自同一套否则评估结果会虚高属于典型的“数据泄漏”。4. 用Python把数据集真正用起来从路径到张量4.1 快速遍历并建立文件名到标签的映射拿到目录后第一步通常是遍历生成“图片路径身份标签”的索引表。用Python标准库就能搞定import os from collections import Counter data_root lfw_home/lfw image_paths [] labels [] for name in sorted(os.listdir(data_root)): name_dir os.path.join(data_root, name) if not os.path.isdir(name_dir): continue for fname in os.listdir(name_dir): if fname.endswith(.jpg): image_paths.append(os.path.join(name_dir, fname)) labels.append(name) print(ftotal images: {len(image_paths)}) print(ftotal identities: {len(set(labels))})正常跑下来图片总数在13000张左右身份数在5700多个。看到这个数字心里就有底了平均每个身份只有两张图左右类别非常多、每类样本非常少这是LFW和普通图像分类数据集最大的不同。4.2 图片读取与基础检查接下来读取图片并检查尺寸和通道数from PIL import Image import random sample_path random.choice(image_paths) img Image.open(sample_path) print(img.size, img.mode)lfw和lfw_funneled里的图一般是250x250的RGB图。偶尔会遇到灰度图或者尺寸异常的文件建议在读取循环里加一层校验把异常文件单独列出来for path in image_paths[:500]: try: with Image.open(path) as im: im.verify() except Exception as e: print(fcorrupted: {path}, error: {e})verify()不会真正解码整张图执行速度快用来快速排查损坏文件很合适。记住这一步不是可选项尤其是从网盘之类渠道拉下来的数据出现个别文件损坏几乎是必然事件。4.3 规范化的数据加载器示例如果用的是PyTorch最简单的做法是用torchvision.datasets.ImageFolder直接加载from torchvision import datasets, transforms train_transform transforms.Compose([ transforms.Resize((224, 224)), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) dataset datasets.ImageFolder(lfw_home/lfw, transformtrain_transform)ImageFolder会自动把一级子目录名当作类别标签正好匹配LFW的目录结构。但要注意它默认把每个子目录当前一个类别如果你只需要其中一部分人比如图片数大于等于2的人需要在传入前先过滤目录。自定义一个Dataset也不复杂而且可控性更强import torch from torch.utils.data import Dataset from PIL import Image class LFWDataset(Dataset): def __init__(self, image_paths, labels, transformNone): self.image_paths image_paths self.labels labels self.transform transform def __len__(self): return len(self.image_paths) def __getitem__(self, idx): img Image.open(self.image_paths[idx]).convert(RGB) if self.transform: img self.transform(img) return img, self.labels[idx]关键点是convert(RGB)避免个别单通道图混进来导致张量维度不一致。这个坑非常隐蔽不写转换时训练过程大概率会在某个step突然爆炸。4.4 验证pairs.txt跑人脸验证任务的最小流程人脸验证任务要求判断两张图“是否同一个人”评测依据是pairs.txt。最小实现思路是解析pairs.txt得到若干组图片对和对应的“同/不同”标签用特征提取模型分别得到两张图的特征向量计算余弦相似度设置阈值判断是否同一人统计准确率通常在90%以上算基本可用用现代方法轻松到99%。解析pairs.txt的代码逻辑不复杂但有个细节要留意同一行里“同一个人”的写法是name fold_index1 index2两张图分别对应name_0001.jpg和name_0002.jpg而“不同的人”的写法是name1 index1 name2 index2对应两个不同身份的照片。解析时必须区分这两种模式否则会把图片对搞错。写个简单的分支判断就好def parse_pairs(pairs_path): pairs [] with open(pairs_path) as f: lines f.readlines() # 第一行是总对数和折数可以跳过 for line in lines[1:]: parts line.strip().split() if len(parts) 3: name, idx1, idx2 parts pairs.append((f{name}_{int(idx1):04d}.jpg, f{name}_{int(idx2):04d}.jpg, 1)) elif len(parts) 4: name1, idx1, name2, idx2 parts pairs.append((f{name1}_{int(idx1):04d}.jpg, f{name2}_{int(idx2):04d}.jpg, 0)) return pairs5. 实际使用中常见的问题与绕坑方案5.1 人名解析的坑文件夹名即标签但不是理想标签用文件夹名当标签初看没问题但实际训练时有多少类就有多少个全连接输出LFW有5700多个类直接做分类任务会导致模型头部非常大、训练速度很慢。更合理的做法是把LFW当“预训练/特征学习”数据用度量学习或者对比学习的方式训练Backbone评估时再切换到验证协议。或者干脆只取出现次数2的人的子集做小规模分类实验减少类别数。5.2 图片尺寸不一致统一resize策略虽然标准LFW是250x250但不同版本打包可能会有轻微差异。统一到224x224还是112x112取决于你的模型设计。人脸识别领域很多Backbone习惯用112x112输入比如FaceNet和ArcFace系列。我自己的建议是如果模型是现成的按模型要求的输入尺寸来如果是自己搭的112x112能极大节省显存开销是个不错的默认选择。5.3 类别不均衡有人只有一张图有人几十张LFW的数据分布非常不均衡大部分身份只有一两张图。做分类训练时这种不均衡会让模型对样本多的类过拟合、样本少的类学不到特征。常见绕坑方案按图片数量过滤只保留5张图的人缩小范围做实验用WeightedRandomSampler给图片数少的类别更高采样权重或用pairs.txt的验证协议做训练避免“类别数过多”的问题。不管选哪种都要在评估时回到pairs.txt上测不要用分类准确率自我安慰。5.4 原始图与funneled的选择标准我做过一次对比实验同样一个轻量模型用lfw_funneled训练和测试Acc能比用lfw高1到2个百分点主要原因就是对齐消除了位置和尺度的干扰。但如果你的目标是“模拟真实场景”比如给门禁系统做原型那lfw原始图更接近实际使用条件。建议实验记录里明确标注用的是哪一套图不同套图跑出来的分数不能直接对比。5.5 内存与速度直接读全量图片进内存的后果13000张250x250的图片全量转成NumPy数组占用大约2到3GB内存。听着还能接受但训练时配合DataLoader的多进程、数据增强、梯度计算内存很容易顶到红线。常见优化手段使用torch.utils.data.DataLoader的num_workers0用子进程并行加载把图片缩到更小尺寸如112x112再缓存第一次运行生成预处理的张量缓存文件.npy或lmdb后续训练直接从缓存读。我最开始偷懒把所有图片一次性numpy.stack成一个大矩阵结果训练到第二个epoch时容器直接OOM被Kill。后来改成惰性加载缓存速度和稳定性都好了很多。6. 把它变成自己的训练集组织、增强与扩展6.1 按用途拆分目录避免在代码里硬编码路径拿到lfw_home后我通常会在外部另外建一套工作目录把数据按“train/val/test”重新组织而不是直接在原目录上改。直接改原目录的问题在于万一划分错了想重来你还得重新解压。mkdir -p work/train work/val work/test然后通过脚本按人名或按图片对划分软链接或拷贝。这样做的好处是代码只依赖work目录路径清晰换数据集时只需换软链接指向。很多人喜欢在原目录里增删图片到最后数据分布被改得面目全非训练结果还没法复现非常不值得。6.2 数据增强的时机与注意点数据增强对人脸识别任务相当重要但要注意验证和测试时不要做随机增强只做Resize和Normalize。训练时常用的增强包括RandomHorizontalFlip、RandomResizedCrop、ColorJitter。有一点需要特别留意人脸验证的pairs.txt里如果同时出现同一张图的正样本对水平翻转会导致原本不同姿态的两张图看起来更像因此增强参数不宜过猛否则会干扰相似度计算的公平性。6.3 基于LFW的简单baseline思路如果你只想快速跑通一个人脸验证的baseline我推荐按这个顺序来用lfw_funneled图片按pairs.txt组织好数据对选择一个预训练的图像分类模型如ResNet18或MobileNet去掉最后的分类层当“特征提取器”对每张图提取特征计算pairs.txt所有对子的余弦相似度用最优点作为阈值算ACC和AUC。这里有个经验直接用ImageNet预训练的模型提取特征在LFW上就能取得不错的准确率因为LFW里的面孔大多是知名公众人物和ImageNet里的人物类有一定重叠。这算是一个“基线中的基线”但它能帮你验证数据加载、评估流程是否无误后面换算法时也有个参照物。6.4 后续扩展换用对齐版本或与其它数据集组合如果实验做下来觉得LFW的难度不够可以考虑换用lfw-deepfunneled等更精细对齐的版本或者把人脸检测对齐环节加进pipeline里自己清洗一遍。再进一步可以把LFW作为辅助训练集配合大规模人脸数据集一起做预训练然后在LFW上做小样本微调。这种“预训练微调”的套路在人脸识别任务里非常常见。更重要的是理解lfw_home的目录组织和协议设计思路后你可以把同一套加载和评估代码迁移到其他数据集上比如自己的业务数据、线下采集的人脸库等。数据集的目录结构、标注文件、验证协议本质上是一套规范真正有价值的不是那13000张图而是围绕这套规范建立的评测思维。我自己习惯在每轮实验前做一件事把lfw_home的目录结构打印一份贴在手边时刻提醒自己图像目录、列表文件、验证协议三者是如何关联的。很多时候实验出了诡异的结果问题不在模型而在于数据集里的路径和标签对不上。希望这篇拆解能让你少走一点弯路拿到lfw_home.zip后不再对着目录发懵。本文还有配套的精品资源点击获取
返回列表