资讯动态

GAN行人重识别毕设源码:数据预处理到训练调参实战

发布时间:2026/10/4 4:25:58 来源:尧图企业网站定制
简介基于生成对抗网络GAN的行人重识别Python源码包面向计算机相关专业的在校学生、教师及企业开发者覆盖课程作业、课程设计、大作业与毕业设计等场景尤其适合作为毕设项目演示或初期立项。压缩包共96个文件包含16个Python核心脚本、44张训练效果与损失曲线图、16个日志文本、6张网络结构示意图并附带实验报告PDF、分享PPT及YAML配置文件整体约36.97MB目录组织清晰便于按功能模块查找。Python脚本分别负责数据预处理、模型搭建、训练主流程与辅助工具可视化图片展示了不同超参数下的训练结果日志则保留了迭代过程与错误记录方便复现和调试。项目代码经验证可稳定运行适合不同基础人群按需取用目前已有160人浏览学习。代码通过DCGAN配置和日志可还原实验过程帮助理解生成对抗网络在行人重识别任务中的实际应用配套实验报告与答辩PPT能直接支撑毕业设计展示也适合在此基础进行二次开发拓展新的功能场景无论是课程汇报、实验复现还是工程实践均具参考价值。1. GAN行人重识别开源项目适合毕设的代码包到底长什么样毕业设计选“行人重识别”这个方向的人十个里有八个会在复现环节卡住——不是论文公式看不懂而是找到的代码要么只有残缺片段要么根本跑不起来。这个基于GAN的生成对抗网络行人重识别Python源码包恰好是那种“能跑、有日志、有实验报告、有PPT”的完整交付形态而不是一个光秃秃的源码目录。它把GAN和行人重识别两个热点绑在一起既覆盖了生成对抗网络的训练流程又落到了ReID的实际检索任务上拿来作毕设、课程设计或者初期项目立项演示都合适。包里有main.py、model.py这些核心训练脚本也带了训练日志、损失曲线图和实验报告适合计科、人工智能、数据科学方向的学生照着复现也适合想快速上手GANReID这套组合的工程师参考。2. 技术方案拆解为什么用GAN做行人重识别以及四个核心模块的职责2.1 GAN在ReID里到底是干什么的不是拿来生成图片好看行人重识别的本质是跨摄像头检索给定一张query行人图在gallery里找出同一个ID的所有图像。难点不在分类而在不同摄像头下的光照、姿态、遮挡差异太大同一行人的特征可能比不同行人的特征差距还大。传统方案用颜色直方图、LBP纹理做手工特征泛化能力有限深度学习方案则用CNN提取特征再通过ID损失或三元组损失拉近同一ID的距离、推远不同ID的距离。但深度学习ReID需要大量带ID标注的跨摄像头数据采集成本高而且某些姿态、视角下的样本天然稀缺。这就是GAN介入的动机。常见路线有两种一种是生成器负责数据增强合成新视角、新姿态的行人图像扩充训练集让主干网络见过更多样本变化另一种是判别器做域对抗训练把不同摄像头的图像当作不同域通过对抗学习消除域风格差异让特征提取器学到的内容与摄像头风格无关。这个项目走的是DCGAN路线从包里的dcgan.yml、model.py、ops.py能看出来生成器和判别器都是标准的卷积网络结构训练时通过对抗博弈逐步提升生成样本的质量同时用生成样本来辅助ReID主干训练。从毕设的角度看这种组合有一个额外好处可讲的东西多。模型结构可以讲GAN的生成器和判别器设计训练过程可以讲对抗损失的收敛情况最终效果可以讲ReID的Rank-1、mAP指标变化。一个方案里同时覆盖生成模型和判别模型两类知识点答辩时不容易被问住。2.2 代码包的模块划分main.py、model.py、ops.py、prepare.py各管什么这个包的核心代码在code目录下结构很清晰没有乱七八糟的嵌套。我之前拆过不少课程项目的源码这个包的模块划分属于“一眼能看明白”的类型直接看入口main.py就能把整个流程串起来。# main.py 简化结构 from model import Generator, Discriminator from ops import load_model, save_model from prepare import load_dataset def main(): # 1. 加载配置 config load_config(dcgan.yml) # 2. 准备数据 train_loader load_dataset(config) # 3. 初始化网络 G Generator(config.z_dim, config.channels) D Discriminator(config.channels) # 4. 训练循环 for epoch in range(config.epochs): for real_img, labels in train_loader: # 训练判别器 d_loss D.train_step(real_img, G) # 训练生成器 g_loss G.train_step(D) # 5. 周期性保存模型和日志 save_model(G, fcheckpoint_epoch{epoch}.pth) write_log(epoch, d_loss, g_loss)main.py负责训练流程编排model.py定义了生成器和判别器的网络结构ops.py封装了模型保存与加载比如每隔多少轮存一次checkpointprepare.py把原始图片处理成训练所需的张量格式。这四个模块在训练循环里各司其职改配置、换数据、调网络结构都只需要碰对应文件不用在整个项目里翻来翻去找代码。Generator类接收随机噪声z和通道数channels参数经过转置卷积逐层上采样得到生成图像Discriminator类接收图像输入输出一个真伪概率同时在某些ReID变体中还会额外输出一个ID分类分支。这个设计的好处是后续想调隐藏层维度、加BatchNorm、换激活函数都只需要改model.py里的构造函数。2.3 这套资源在交付形态上的加分项源码之外压缩包里还带了“行人重识别实验报告.pdf”、“智能计算系统lab2-2实验分享.pptx”和“智能计算系统分组实验.pdf”。这三份材料对做毕设的人来说价值很大实验报告里有方案设计、实验过程、结果分析PPT里有结构化的讲解思路基本等于把“怎么写毕设论文”的半成品也放进来了。很多学生的毕设代码是自己写的但论文不知道从哪下笔这个包恰好补上了这一环。提示下载解压后项目名和项目路径不要用中文建议解压重命名为英文名字后再运行。这是项目必读里反复强调的后面遇到莫名其妙报错的时候十有八九就是路径或文件名的中文问题。3. 数据准备全流程prepare.py 如何把原始图片变成可训练数据集3.1 预处理三件套resizeImage.py、changeIndex.py、prepare.py行人重识别实验用的图片往往是数据集里直接切出来的行人框尺寸不一致、命名混乱、ID编号有空洞这些都不能直接喂给训练脚本。这个包的做法是分三步处理先用resizeImage.py把原始图片统一缩放再用changeIndex.py把标签重映射成连续从0开始的ID最后用prepare.py完成训练集、验证集、测试集的划分。以常见公开数据集为例原始图片可能是各种分辨率比如192×64、128×64而GAN的生成器通常希望输入是固定大小的张量。统一缩放到128×64或64×32是ReID任务里的常见做法太小会丢失细节太大则增加显存压力。changeIndex.py解决的是标签连续性问题原始数据集的ID可能是1、3、8这种稀疏分布训练时交叉熵损失要求标签从0开始连续排列重映射后模型才能正常收敛。# changeIndex.py 核心逻辑 import os import json from collections import defaultdict def remap_ids(image_dir): # 读取原始文件名提取ID编号 files [f for f in os.listdir(image_dir) if f.endswith(.jpg)] id_list [] for f in files: # 假设文件名格式为 ID_摄像头序号_帧号.jpg pid int(f.split(_)[0]) id_list.append(pid) # 去重后排序建立原ID到连续ID的映射 unique_ids sorted(set(id_list)) mapping {old_id: new_id for new_id, old_id in enumerate(unique_ids)} return mapping这段代码做的事情很朴素但很关键。将原始ID映射为从0开始的连续编号需要保证同一个行人的所有图片映射到同一个新ID不同行人的新ID各不相同。mapping字典保存了这个对应关系之后prepare.py加载数据时直接用映射后的ID作为训练标签。需要注意映射字典要保存下来因为测试时计算Rank-1指标需要把预测结果映射回原始ID才能和ground truth比对。3.2 按ID划分数据集训练集、query、gallery怎么切行人重识别和普通图像分类的划分方式不一样分类任务随机切分图片就行ReID必须按ID划分同一个ID的所有图片不能同时出现在训练集和测试集里。这个包遵循了Market-1501这类数据集的划分惯例训练集的ID和测试集的ID完全不相交这样测出来的指标才有意义。# prepare.py 数据集划分逻辑 import os import random from torch.utils.data import Dataset, DataLoader class ReIDDataset(Dataset): def __init__(self, img_dir, id_mapping, image_size(64, 32), trainTrue): self.samples [] # 按ID聚合图片 id_to_files {} for f in os.listdir(img_dir): pid int(f.split(_)[0]) mapped_pid id_mapping[pid] id_to_files.setdefault(mapped_pid, []).append(f) # 划分trainTrue时取全部图片否则取部分作为gallery for pid, file_list in id_to_files.items(): if train: selected file_list else: # 测试阶段每个ID取一张query其余作gallery selected file_list[:-1] if len(file_list) 1 else file_list for f in selected: self.samples.append((os.path.join(img_dir, f), pid)) def __len__(self): return len(self.samples) def __getitem__(self, idx): path, label self.samples[idx] img load_and_resize(path, size(64, 32)) return img, label这个数据集类有两个关键设计第一个是train参数控制训练和测试模式。训练时取该ID下所有图片参与训练测试时每个ID留一张图片做query其余做gallery模拟真实检索场景中的“给一张查询图在底库中找同一ID”。第二个是__getitem__里做了图像加载和尺寸统一返回的是张量形式的图像和对应的映射后标签。训练时DataLoader会按照设定的batch_size自动打乱并批量输出。3.3 数据增强与样本均衡GAN训练最怕的就是生成器“偷懒”生成样本单一。同样ReID训练也怕训练集样本分布不均——某些ID只有两三张图某些ID有几十张图。prepare.py里预留了数据增强的空间比如随机水平翻转、随机擦除这些操作在行人重识别里被证明是有效的因为行人图像天然存在左右对称性翻转不会改变身份。随机擦除则能模拟遮挡强迫模型关注非遮挡区域的特征。我一般会建议在prepare.py里增加一个控制开关比如use_augmentation参数打开时在__getitem__里执行翻转和擦除关闭时保持原图。训练初期先关掉增强验证基本流程能跑通后期再打开增强观察Rank-1是否提升。别一开始就把所有增强都加上否则出问题时分不清是模型问题还是数据问题。4. 训练参数逐个调batch size 4/16、学习率 1e-4/2e-4 对收敛的影响4.1 从日志文件名读出的参数组合这个压缩包里的日志和图片命名很有意思trainsize4learn0.0001.png、train size16learn0.0002.png、16-10轮size4迭代.jpg这些名字直接暴露了训练参数batch size分别用了4和16学习率用了0.0001和0.0002迭代轮次大概在16轮左右。这说明上传者至少跑过两组对照实验而不是只跑通一次就完事。参数对照是毕设实验部分最容易出彩的地方有对照组就能画曲线、能分析原因、能写结论。GAN训练里batch size和学习率的选择比普通CNN更敏感。小batch size4省显存但梯度估计的噪声大判别器和生成器的博弈会很不稳定大batch size16梯度更平滑收敛更稳但对显存的要求直接翻倍。学习率方面生成对抗网络对学习率极其敏感0.0002这个值在DCGAN原论文里用的就是Adam优化器的默认学习率实操中我一般从0.0002开始如果发现判别器loss直接把生成器压死就降到0.0001。参数实验组1实验组2对收敛的影响batch size416小batch噪声大收敛慢但省显存大batch更稳需要更多显存learning rate0.00010.0002lr过小收敛慢lr过大会导致生成器loss震荡迭代轮次16左右16左右小数据集16轮足够观察趋势不必追求大epoch数Adam beta1默认0.5默认0.5beta10.5是DCGAN标配避免训练震荡4.2 训练循环里的对抗博弈判别器和生成器交替更新打开main.py的训练循环核心是两个交替更新的step。判别器的目标是区分真实行人图和生成器伪造的行人图生成器的目标是让判别器分不清真假。如果判别器先更新一次生成器再更新一次这个比例在DCGAN默认实现里是1:1。实际训练ReIDGAN时我发现判别器经常比生成器学得快尤其是数据集中行人外观差异明显的情况下判别器很容易达到接近100%的判别准确率这时候生成器的梯度就消失了。解决手段有三个降低判别器的学习率、减少判别器更新频率、给生成器的损失加一个特征匹配项。这个项目在ops.py里预留了优化器配置接口可以分别为G和D设置不同的学习率。常见做法是G的lr保持0.0002D的lr降到0.0001这样生成器有更多机会“追赶”判别器。# ops.py 训练优化器配置 from torch.optim import Adam def get_optimizers(G, D, lr_g0.0002, lr_d0.0001): optimizer_G Adam(G.parameters(), lrlr_g, betas(0.5, 0.999)) optimizer_D Adam(D.parameters(), lrlr_d, betas(0.5, 0.999)) return optimizer_G, optimizer_D两个优化器分别绑定生成器和判别器参数betas统一用0.5和0.999这是DCGAN从实践里总结出来的配置。把D的学习率设置为G的一半可以缓解判别器碾压生成器的问题。训练时每轮记录G_loss和D_loss到日志文件观察两条曲线的趋势就能判断当前的对抗状态。如果D_loss迅速降到0.1以下而G_loss还在1.0以上横盘说明判别器过强需要把lr_d调得更低。4.3 从训练日志看两种失败模式翻看包里的日志文件能看到两种典型的GAN训练失败模式。第一种是D_loss持续下降G_loss完全不下降这种叫判别器过强生成器输出的图像很快被判别器识破生成器梯度消失学不到任何东西。第二种是G_loss和D_loss都在高位震荡降不下来这种是训练不收敛常见原因是学习率太高或者网络结构里有数值不稳定的层。注意GAN的loss曲线不像分类任务那样单调下降属于正常现象两条曲线在动态对抗中波动是常态。真正需要警惕的是“一条曲线碾压另一条”和“两条曲线一起发散”这才是训练失败的信号。判别器过强时优先降lr_d两条线都震荡时检查是否用对了tanh做生成器输出层的激活函数、判别器最后一层是否用了sigmoid。这两个细节是DCGAN的标配缺一个都会导致loss数值异常。项目里result目录下的图片就是训练过程中生成的样本可视化每过固定轮次保存一张看生成图从模糊噪点到隐约有人形轮廓的演变过程也能辅助判断训练是否正常。5. 避坑与排查从 ERROR.jpg 和三个日志里看到的五个翻车点5.1 中文路径导致的数据加载失败压缩包的“项目必读.txt”里写着建议解压重命名为英文路径这不是随口一说的建议是很多人踩过坑之后的血泪经验。现象是程序启动后报类似“FileNotFoundError”或“Cant open image file”的错误报错文件指向的路径里带着中文或空格但明明文件就存在。原因是Python在Windows下处理中文路径时编码方式不一致某些库比如OpenCV的imread对中文路径支持不好导致文件读取失败。解决方法是解压后重命名为纯英文路径例如改为reid-gan-project后再运行。从那以后我自己处理任何源码包第一件事永远是检查路径先把这一步做成肌肉记忆。5.2 迭代过程生成图像全黑或全白打开result目录里的生成图像如果发现生成器输出的都是纯黑色或纯白色图这属于GAN训练里的典型崩溃模式。现象是G_loss和D_loss数值看起来还正常但保存的图像完全无结构。原因是判别器梯度回传方式不当或者生成器输出层的激活函数用错了。DCGAN要求生成器最后一层用Tanh输出范围是[-1, 1]而判别器输入图像也要归一化到同样的范围。如果数据预处理时图像是[0, 1]范围而生成器输出是[-1, 1]范围两边对不上训练就会发生奇怪的漂移。解决方法是检查prepare.py里是否对图像做了到[-1, 1]的归一化同时确认生成器输出层用的确实是Tanh。5.3 CUDA out of memory日志里出现ERROR.jpg包里的ERROR.jpg大概率和显存溢出有关。现象是训练跑到一半终端打印“CUDA out of memory”程序直接崩掉。原因大多数是batch size设得太大或者输入图像分辨率设定太高。生成器在128×64分辨率下占用的显存远高于32×32。解决方法是把batch size从16降到4或者把图像尺寸从128×64降到64×32。这时候就能看出trainsize4learn0.0001.png那组实验存在的现实意义——小batch size就是为了在这种硬件条件下能跑起来。5.4 二次训练时结果无法复现同样的代码、同样的数据集你跑出来的结果和包里的日志对不上这是很常见的现象。原因分两类一类是PyTorch的随机种子没固定卷积初始化和数据打乱都有随机性另一类是训练环境和对方不同——CUDA版本、PyTorch版本、cuDNN版本差异都会引入数值偏差。解决方法是在main.py开头固定随机种子random.seed(0)、np.random.seed(0)、torch.manual_seed(0)三个都加上。另外把dcgan.yml里的环境版本记录下来复现时尽量对齐大版本。# main.py 开头固定随机种子 import random import numpy as np import torch def setup_seed(seed0): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) # 如果用了GPU也固定CUDA的随机种子 if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed)setup_seed函数在main函数第一行调用即可。固定随机种子之后同一份代码在同一环境下跑两次结果基本一致。但要注意不同型号的GPU之间结果仍然可能有微小差异这是浮点运算顺序不同导致的不影响整体趋势判断。5.5 数据加载卡死或进度条不动Windows上跑PyTorch训练时DataLoader如果把num_workers设置成大于0经常会出现程序卡死的现象日志文件停在同一行GPU显存也被占了但利用率是0%。原因是Windows下多进程数据加载需要放在ifname main保护块内否则子进程会递归创建子进程造成死锁。解决方法是把入口代码全部包进main()函数然后在文件末尾写ifname main: main()。如果还卡就把num_workers改成0使用主进程加载数据训练速度慢一些但至少不会卡死。6. 进阶技巧用十行代码画出损失曲线判断模型是否在正常收敛拿到训练日志log1.txt、log2.txt之后很多人不知道怎么看。眼花缭乱的数字其实只需要提取G_loss和D_loss两列画成曲线训练状态一目了然。下面这个脚本可以从日志文件里解析loss和准确率并绘制曲线图。# plot_loss.py import re import matplotlib.pyplot as plt def parse_log(log_path): epochs, g_loss, d_loss [], [], [] with open(log_path, r, encodingutf-8) as f: for line in f: # 假设日志格式: epoch3 g_loss1.234 d_loss0.567 m re.search(repoch(\d).*?g_loss([\d.]).*?d_loss([\d.]), line) if m: epochs.append(int(m.group(1))) g_loss.append(float(m.group(2))) d_loss.append(float(m.group(3))) return epochs, g_loss, d_loss epochs, g_loss, d_loss parse_log(log1.txt) plt.plot(epochs, g_loss, labelGenerator Loss, linewidth1.5) plt.plot(epochs, d_loss, labelDiscriminator Loss, linewidth1.5) plt.xlabel(Epoch) plt.ylabel(Loss) plt.legend() plt.title(GAN Training Curve) plt.savefig(loss_curve.png, dpi150)parse_log函数用正则表达式从每行日志里提取epoch编号、g_loss和d_loss数值三个不同的日志文件可以分别解析后画在同一张图上对比。注意正则表达式要和日志实际格式匹配如果字段名不同就调整一下匹配模式。画出来的曲线如果两条线在波动中缓慢靠近最终都维持在0.5到1.0之间说明对抗训练处于健康状态。如果G_loss走高而D_loss走低说明判别器占优势需要调低判别器学习率。如果两条线都发散到很大数值基本可以判断是学习率太高或网络结构有问题直接停掉重新配置。对于行人重识别而言损失曲线只是训练健康度的指标最终要看的是Rank-1准确率和mAP。这些指标在实验报告PDF里应该有记录你可以在自己的复现实验里每训练5轮就在测试集上算一次Rank-1记录到日志里这样损失曲线和准确率曲线就能对照着看。准确率持续上升说明模型的检索特征在变好这时候即使G_loss有小幅波动也不用太担心——GAN只是辅助手段ReID主干的收敛状态才是核心。从那以后我每次拿到别人的ReID项目都会先解析日志、画曲线、看趋势再决定要不要调参训练。这套分析流程已经成了我的固定习惯能帮你节省大量盲目调参的时间希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑