1. 项目概述与核心需求解析
做毕设选题时,导师丢给我一个方向:城市道路病害智能辨识,要求用深度学习,最好能有一个能看得见摸得着的界面。说实话,一开始我脑子里全是问号,道路病害是什么,辨识什么,为什么非得用深度学习来做?查了一堆资料,又跑了几个月的实验,踩了无数坑之后,才算是把整个项目从底层逻辑到上层界面给理顺了。这篇博文就当成一个复盘记录,把我自己从选题到答辩全流程的经验拆开揉碎讲清楚,希望能给正在做同类毕设或者想入门图像识别落地的人省点时间。
先把这个项目要解决的实际问题说透。城市道路在长期使用后会出现各种损伤,比如最常见的裂缝、坑槽、修补区域,甚至更复杂的网状裂纹和龟裂。这些病害如果不及时发现和处理,小问题会演变成大坑,影响行车安全,增加后期养护成本。传统的道路病害检测依赖人工巡检,也就是养护工人开车或者步行沿线查看,效率低、主观性强、容易漏检,而且夜间或恶劣天气下作业风险很高。所以,基于深度学习的自动识别就成了一个非常实际的工程需求——用摄像头采集路面图像,算法自动判断图像里有没有病害、病害是什么类型、在哪里,辅助养护部门快速决策。
这个毕设项目的核心目标其实可以拆成三个层面。首先是算法层面,训练一个能够准确分类和定位道路病害的深度学习模型,这是整个系统的引擎。其次是系统层面,模型不能只活在训练脚本里,得封装成一个可用的工具,让用户能加载图片、运行推理、查看结果。最后是交互层面,也就是题目里提到的PyQt,用桌面图形界面把算法能力暴露给使用者,即便是不懂深度学习的人也能直接操作。这三点结合起来,恰恰是“智能辨识算法研究”落到工程实处的完整路径。
从毕设答辩的角度看,这个选题的好处也很明显:研究目标明确,属于计算机视觉领域的热门方向,技术栈覆盖了数据处理、模型训练、系统开发、UI设计,展示的时候既有算法深度又有可视化效果,评审老师能直观看到系统运行结果。无论从工作量还是创新点的角度,都比较容易撑起一篇完整的毕业论文。当然,难点也不少——数据集怎么搞、模型精度怎么保证、PyQt界面怎么和推理逻辑衔接,这几个环节如果前期没有清晰规划,后期很容易手忙脚乱。我的建议是,动手之前先把整个流程画一遍,每一步该输入什么、输出什么,心里要有数,然后再开始写代码。
2. 整体方案设计与技术选型思路
项目定下来之后,最让人纠结的其实是技术选型。深度学习框架有PyTorch和TensorFlow两个主流选择,桌面界面有PyQt和Tkinter,模型结构又有好几种现成的分类网络可以套。到底选哪个,怎么选,背后都是有逻辑的,不是哪个火就用哪个。
先说深度学习框架。我最终选了PyTorch,理由很直接:调试体验好,模型定义灵活,社区资料多,而且大多数最新的论文和预训练模型都优先放PyTorch版本。TensorFlow当然也能做,但它的图机制和部署链路对毕设这种偏研究性质的项目来说显得更重,出了问题排查起来也麻烦。PyTorch的动态计算图允许我用print随时查看中间张量的形状,这对初学者理解卷积神经网络的前向传播过程帮助很大。举个例子,我刚接触卷积网络时经常搞不明白特征图尺寸是怎么变化的,在PyTorch里直接打印某一层的输出形状,一目了然,比盯着论文里的公式推导高效得多。
再来说模型结构。道路病害识别从技术本质上看是一个图像分类问题——模型输入一张路面图,输出病害类别标签。如果只做分类,最简单的做法是拿ResNet、VGG这些在ImageNet上预训练好的模型做迁移学习,把最后一层全连接换成自己的类别数,然后在自建数据集上微调。这个路线对于毕设来说非常稳妥,因为ImageNet上预训练的模型已经学会了大量底层视觉特征(边缘、纹理、形状),这些特征对路面病害这种纹理型目标同样有效,微调收敛快、精度高,也不需要从零开始训练几天几周。
不过,仅仅做分类有一个局限:它只能告诉你图片里有没有某种病害,却无法定位病害在图像中的具体位置。考虑到答辩时评审老师很可能追问“你的系统能不能框出来病害在哪里”,我决定把任务升级为目标检测——不只要判断类别,还要输出边界框坐标和置信度。目标检测的经典模型有两个方向,一个是两阶段Faster R-CNN,精度高但速度慢;另一个是单阶段YOLO系列,速度快且精度也能接受。道路病害检测通常需要部署在移动巡检设备上,对实时性有要求,所以我最终选了YOLOv5s这个轻量版本。它有官方预训练权重,代码结构清晰,文档完善,对新手极其友好。
这里插一个经验总结:很多同学做毕设容易陷入“模型越复杂越好”的误区,一上来就想用最新的Transformer检测头、大模型主干,结果训练时间爆炸,调参调到崩溃,最后精度反而不如预训练的小模型。毕设的核心是证明你完整掌握了从数据到系统的一整套流程,并且能够针对问题做出合理的工程设计决策,不是比拼刷分。轻量模型加迁移学习在这个规模的项目中完全够用,而且显存占用小,训练时间可控,复现性也好。
界面方案选PyQt5,这一点题目里已经定死了,但我还是想说说为什么这个选择合理。PyQt5是Python绑定Qt的成熟GUI框架,控件丰富、样式美观、跨平台支持好,用它做桌面工具很合适。最关键的是,PyQt的信号与槽机制和深度学习的异步推理场景配合得比较自然——界面线程负责响应用户点击,推理线程负责跑模型,两者通过信号传递结果,这样界面不会因为推理耗时太长而卡死。如果你的目标是做一个有实用价值的毕设Demo,PyQt5几乎是首选。
整体流程我梳理成了这样一条线:原始图像数据输入 → 数据预处理和增强 → YOLOv5模型训练与评估 → 模型导出 → PyQt界面加载模型 → 用户选择图像 → 推理线程执行检测 → 结果绘制并展示。每一步都有明确的输入输出,模块之间低耦合,哪里出了问题可以单独调试。这个架构一直到答辩前都没有重构过,实践下来很稳。
3. 数据集准备与标注细节
算法项目有一句至理名言:数据决定上限,模型只是逼近这个上限。路面病害检测也不例外。我一开始天真地以为网上能直接下到现成的道路病害数据集,结果搜了一圈发现,公开数据集要么分辨率参差不齐,要么标注格式五花八门,而且类别定义不完全一致。有的数据集只标裂缝,有的数据集把坑槽和裂缝混在一起,这完全没法直接用。最后我决定自己攒数据集,过程虽然麻烦,但对毕业设计的完整性来说很有价值。
数据来源主要有两个渠道:一是网上爬取公开的街道、公路巡检图像,二是自己用手机在校园周边的硬化路面拍一些样本。这里要注意,爬取图像必须仔细筛选,保证画面主体是路面而不是车辆、行人或者街景建筑遮挡。路面病害的视觉特征本来就比较细微,如果背景太复杂,模型学到的东西会被噪声带偏。我前后大概攒了4000多张原始图像,每张图经过筛选后缩放到统一尺寸,剔除模糊和重复的样本,最终留下约3500张可用数据。
标注工具我用的LabelImg,这是一个开源图形标注工具,可以画矩形框并把标注结果保存为YOLO格式的txt文件。YOLO格式的坐标是归一化的相对坐标:每行对应一个目标,格式为“类别id 中心点x 中心点y 框宽 框高”,五个值全部是0到1之间的小数。这个格式和YOLOv5的训练要求完全匹配,省去了格式转换的麻烦。
标注是一个极度枯燥但极其关键的环节。我把病害类别定义成四类:裂缝(crack)、坑槽(pothole)、修补区域(patch)、网状裂纹(net_crack)。每张图我都要逐张放大检查,框出病害的完整区域,边界要贴合病害边缘,不能多框也不能少框。这里有个重要的心得:矩形框不是越紧越好,也不是越松越好,而是应该覆盖病害的主要视觉区域,并且尽量保持标注风格的一致性。如果第一张图的框很紧实,第二张图的框却把周围路面都包进去了,模型会学到混乱的边界概念。
标注数量分布也要刻意控制。我统计了一下,裂缝样本大约占了45%,坑槽约占20%,修补区域约占20%,网状裂纹约占15%。这种不均衡其实反映了真实场景中的频率差异——裂缝是最常见的病害,坑槽虽然严重但出现频率相对低。如果不做任何处理直接训练,模型会天然偏向预测多数类,导致少数类召回率很低。我的处理方式是先按原始比例训练一个版本,观察各类别的精确率和召回率,然后对样本量偏少的类别做重复采样(复制一部分样本),最终把各类别比例拉近到大致均衡,模型的少数类表现提升非常明显。
数据集划分也是容易被忽视的细节。我按约7:2:1比例将数据划分为训练集、验证集、测试集,并且确保同一张图像的不同版本不会同时出现在训练集和验证集里。比如我做了水平翻转、亮度调整这类增强操作,生成的增强样本和原始样本必须放在同一集合里,否则会造成数据泄露,模型精度虚高,答辩演示时一验就露馅。
关于数据增强,YOLOv5内部自带了一套增强策略,包括马赛克拼接、随机仿射变换、HSV颜色扰动等,训练时默认启用,效果已经很好了。我又额外加了一个小技巧:用OpenCV对部分图像做轻度的高斯模糊和增加噪声,模拟雨天或者低光照条件下的采集环境,这能提升模型的泛化能力。实测下来,加了噪声扰动之后,在夜间光照不均的测试图上确实更鲁棒了。
4. 模型训练、评估与推理实现
数据准备完毕后进入模型环节。考虑到训练时间和硬件条件,我租了一块显存约11GB的消费级显卡做训练,YOLOv5s的参数量大约只有7.3M,Batch Size设为16,初始学习率0.01,整个训练过程大约持续了100轮。YOLOv5的官方代码库把训练入口封装得很简洁,一条命令就能启动训练,它会自动生成训练曲线、验证指标和权重文件,训练过程的工程体验比从零手写网络要好很多。
启动训练前我调整了几个关键参数,这里值得展开说一说。第一个是图像输入尺寸,默认值是640×640,这个值平衡了精度和速度,对道路病害这种中大型目标来说足够用了,我没有刻意改大,因为改大意味着训练时间成倍增加而收益有限。第二个是类别数,从默认的COCO80类改成了自己的4类。第三个是预训练权重,我加载了yolov5s.pt作为初始权重,利用在COCO上学习到的通用特征来加速收敛。第四个是超参数文件,YOLOv5提供了遗传算法自动调参功能,我跑了一轮自动搜索,发现它在学习率、增强强度上有小幅优化,就沿用了最优结果。
整个训练过程的损失曲线值得关注。前10轮损失下降非常快,从最初的0.08左右降到0.04附近;之后逐渐进入平缓期,约在60轮后基本稳定在0.02上下。如果训练结束时损失仍然明显下降,说明还没收敛,应该增加轮数;如果验证集损失在某个节点开始回升,说明过拟合了,应该提前停止。我用的YOLOv5版本自带早停机制,监控验证集指标连续多轮不提升就会自动终止,省了手动干预的麻烦。
评估环节不能只看训练损失,关键要看mAP(mean Average Precision)这个综合指标。我训练出来的模型在验证集上的mAP@0.5达到了0.86,mAP@0.5:0.95约为0.58。拆开来看,裂缝类别的精确率和召回率最高,坑槽次之,网状裂纹相对偏低。这个结果符合直觉:网状裂纹形态散乱、边界模糊、标注难度大,模型难以稳定捕捉它的特征。如果答辩时有老师质疑某个类别效果不佳,你可以把这一类别的样本分布可视化拿出来,说明是数据分布导致的局限,并且提出改进思路,比如增加该类别样本数量或者采用更细粒度的分割模型,这样比单纯辩解有说服力得多。
训练完成后,我把PyTorch权重导出了TorchScript格式。为什么不用默认的.pt文件直接在PyQt里加载?原因在于推理速度。TorchScript是PyTorch的静态图表示,推理时不需要Python解释器做动态图调度,前向传播速度明显更快,而且调用方式也更干净。虽然YOLOv5自带的detect.py脚本可以直接做推理,但那个脚本是为命令行设计的,输出信息混杂,不适合直接嵌入GUI程序,所以我还是选择把推理逻辑单独封装成一个类,在PyQt的后台线程中调用。
推理的核心流程是:读取图像 → 缩放至640×640 → 归一化到0到1区间 → 调整通道顺序为CHW → 转为张量 → 输入模型 → 得到推理结果 → 按置信度阈值过滤 → 执行非极大值抑制→ 还原边界框坐标到原图尺寸 → 绘制框和标签。这里的非极大值抑制是目标检测里绕不开的一步:模型对同一个目标可能输出多个重叠的预测框,NMS会保留置信度最高的框,同时抑制那些和它重叠度(IoU)超过阈值的其他框,最终每个目标只留下一个干净的检测结果。YOLOv5的推理代码里已经封装好了NMS,但如果想手写理解一遍,建议去看它的实现在tolist中如何循环处理,这能帮你应对答辩时关于“为什么多个框都会出现”的追问。
5. PyQt桌面系统的架构与关键代码实现
GUI部分是我踩坑最多也收获最大的环节,它决定了一个算法项目能否变成一个“像样”的软件。PyQt5的程序结构其实很清晰:先创建QApplication,然后构造主窗口,在窗口上放置控件,最后启动事件循环。但如果你把所有代码都堆在MainWindow类里,很快会陷入回调地狱。我采取的分层方案是:界面层、逻辑层、推理层三者分离。
界面层只负责接收用户输入和展示结果。主窗口左边是一块图像显示区域,右侧是一个结果面板,底部是文件选择按钮、运行按钮和状态栏。用户点击“选择图像”按钮后,通过QFileDialog打开文件,选中的图像路径由信号传递到逻辑层。逻辑层校验路径、创建推理任务并启动后台线程。推理层持有模型实例,执行前向传播,返回检测结果列表。推理完成后通过信号把结果传回界面层,在图像上绘制边界框并显示类别、置信度信息。
这里有几个工程细节我认为很值得分享。第一,模型加载必须只做一次,放到推理线程初始化时加载,不要每次推理都重新加载权重,否则会卡到你怀疑人生。第二,推理一定要放到独立线程,不能直接在主线程里跑,否则点击按钮后界面会冻结,在Windows上甚至会弹出“程序无响应”窗口,答辩演示时出现这个画面就太尴尬了。第三,界面刷新需要把QPixmap的更新放到主线程完成,跨线程操作控件会触发Qt的警告甚至崩溃,正确做法是用信号槽机制,在子线程里emit结果信号,主线程的槽函数再更新界面。这就是PyQt官方推荐的方式。
让我把界面关键控件的组织逻辑具体化。图像显示区域用QLabel并设置setScaledContents(True),这样图像能自动缩放适配控件尺寸。绘制边界框我用了QPainter在QPixmap上画矩形和文字,颜色按类别区分,例如裂缝用红色、坑槽用橙色、修补区域用蓝色、网状裂纹用绿色,这样一眼就能区分不同病害类型。右侧结果面板用一个QTableWidget展示检测结果表格,每一行显示“病害类型、置信度、坐标范围”,这样用户不仅能看到图像上的框,还能看到结构化的数据,对答辩演示很有帮助——老师问“置信度是多少”的时候,你直接指着表格说数据,不慌。
另外我加了两个实用的小功能,看上去不起眼但实际很加分。一是置信度阈值滑块,拖动它可以动态调整过滤条件,让用户在界面上直观看到不同阈值下检测结果的变化,这展示了你对模型判断逻辑的理解深度。二是历史检测记录列表,每做一次检测就把结果追加到列表里,可以回溯之前检测过的图片和对应结果。这两个功能代码量不大,但显著提升了系统的完整性和演示效果。
代码结构上我按照功能拆了三个文件:main.py负责程序入口和QApplication创建,ui_mainwindow.py负责主窗口界面搭建和信号连接,detector.py封装YOLOv5推理类。界面布局如果用纯代码写会比较繁琐,我这里特别推荐一个辅助工具:Qt Designer。它允许用拖拽方式设计界面并导出.ui文件,再用PyUIC工具转成.py代码。当然,转出来的代码是上世纪的风格,变量命名也比较机械,我不建议直接在里面塞业务逻辑,而是作为初始界面骨架,再手工调整布局和响应逻辑。这么做能省下大量调整控件尺寸的时间,把精力集中在核心逻辑上。
6. 测试过程、系统集成与展示准备
在正式交付之前,我花了大量时间做系统集成测试,目的只有一个:确保答辩演示的时候不会翻车。这在毕设中太重要了,模型精度再高,演示时程序崩溃或者界面卡死,之前的努力都会被大大削弱。我的测试思路分三步:功能测试、性能测试、边界条件测试。
功能测试覆盖每个按钮的行为。比如打开文件按钮能不能正确弹出对话框并显示图片,运行检测按钮在推理过程中会不会导致界面卡顿,置信度阈值滑块调整后结果表格和图像框是否同步更新。这些看似琐碎,但任何一个环节出错都会影响演示流畅性。我测试中发现过一个典型的线程问题:第一次点击运行按钮后推理线程正常返回,第二次点击时,程序就直接退出了,原因是线程对象被重复启动,Qt会抛出“线程已经在运行”的致命错误。解决办法是在启动新线程前,判断当前线程是否还在运行,如果还在就等待其结束后再启动新的。这个判断我放在了运行按钮的槽函数里,一行if条件就解决了。
性能测试重点看推理耗时。我拿不同尺寸的图片做了一轮测试:960×720的图像推理时间约为70毫秒,1920×1080的图像约为110毫秒,加上图像前后处理,整体单张处理时间控制在0.2秒以内,这个速度在演示时完全流畅,还能留出余量边说边操作。如果发现速度偏慢,首先检查推理线程是否绑定到了错误GPU,其次确认TorchScript模型没有回退到CPU推理,这两个都是最常见的性能杀手。
边界条件测试是为刁钻提问做准备。我专门准备了几张不含任何病害的干净路面图,点击检测后系统应该显示“未检测到病害”的提示,而不是输出一堆假的边界框或者崩溃。还准备了几张尺寸特别大和特别小的图片,验证缩放逻辑是否正确,以及一张带严重噪声的夜间路面图,考察模型的鲁棒性。这些测试结果我全部记录在项目文档里,答辩时如果问“你的系统边界情况怎么处理”,我能直接给出回答和实测截图,这一手准备能展现出工程意识。
展示环节还有一个小建议:答辩PPT里不要只放训练曲线和mAP表格,最好插入一个系统运行视频,大约1分钟,内容包含打开软件、选择一张带裂缝的图片、点击检测、弹出边界框和置信度、切换另一张带坑槽的图片、再检测一次。这种动态演示比静态截图冲击力强得多,能直观证明系统真的能跑起来。视频可以用屏幕录制工具录制,保持界面清晰、操作步骤流畅即可。
我还做了一个小的模型鲁棒性对比实验,用来充实论文的实验章节。选取同一张测试图,分别用未做数据增强训练的模型和使用了增强的模型跑一遍,对比检测框数量和置信度差异,配上可视化对比图,连数据图都不需要额外画,直接截图标注就行。这种对比给论文增加了说服力,也体现出你对“为什么这样做”是有思考的,而不只是照搬训练脚本。
7. 常见问题排查与答辩避坑实录
分享一些实际踩过的坑和排查方法,每一个都有切肤之痛。做个速查表放在这里,遇到相同问题可以直接对照。
| 问题现象 | 可能原因 | 排查与解决方案 | | 训练时CUDA out of memory | Batch Size过大或输入分辨率太高 | 调小Batch Size,或改用更轻量的模型版本(如YOLOv5s换成YOLOv5n) | | 验证集mAP很低但训练集损失很低 | 过拟合,或者训练集和验证集分布不一致 | 增加数据增强强度,检查数据集划分有无泄漏,增加验证集多样性 | | 模型推理结果全都是同一个类别 | 数据集类别严重不平衡 | 对少数类做过采样,或调整损失函数中的类别权重 | | PyQt界面点击运行后卡死 | 推理代码跑在主线程,阻塞了事件循环 | 将推理逻辑移到QThread中,通过信号槽传递结果 | | 第二次运行按钮程序崩溃 | 重复启动了同一线程对象 | 启动前判断线程isRunning(),结束后再创建新线程 | | 边界框位置偏移或尺寸错误 | 没有把坐标从416/640尺寸还原到原图 | 记录原始图像的缩放比例,推理结果按比例映射回去 | | 中文字体显示为方块 | PyQt默认字体不支持中文 | 设置支持中文的字体,如“Microsoft YaHei”或“SimHei”,并在绘图时设置字体族 |
和我一起做类似项目的另外一位同学,他用的数据集是从某个公开仓库直接下载的,训练时没注意样本里有大量重复图片,导致验证集和训练集存在重叠,mAP显示0.95但换了新图测直接掉到0.6,这个教训就是数据隔离没做好。所以我也提醒大家,如果你用了别人的数据集,最好自己写脚本检测重复图像,最简单的办法是计算图像的感知哈希,把重复项标记出来并剔除。这个细节要不要写进论文都可以,但一定要在私下里自查。
关于答辩准备,还有几个重要的避坑经验。第一,演示环境一定要提前到现场测试。我曾见过有同学在自己的电脑上一切正常,到答辩教室投影后分辨率一变,界面字体错位,图像显示区域被压缩,整个效果大打折扣。建议提前设置好演示窗口的固定尺寸,或者使用自适应布局,并预先在演示机器上安装好Python环境、显卡驱动和依赖包。如果现场机器没有GPU,务必提前准备好CPU版本的推理逻辑,虽然慢一点但至少能跑出来。
第二,准备一套“弱网、无网环境应急预案”。答辩现场的网络状况不可控,如果你的代码依赖在线加载预训练权重或远程模型,万一现场断网就直接瘫痪。我的做法是把所有依赖打包到本地目录,推理时从本地加载TorchScript模型,完全没有外网请求。这一点我在答辩时特意提了一下,老师在提问环节就没有追问环境依赖的问题。
第三,对模型的局限性要诚实且有准备。答辩老师如果问“你这个模型在实际道路上表现怎么样”,一定要实事求是地说明:测试集是在有限条件下采集的,实际场景中光照、阴影、水渍都会影响效果,并提出后续改进方向,比如引入更多场景数据、采用分割模型辅助检测。这种回答比一味吹嘘模型强得多,更能体现工程思维和学术素养。
8. 项目扩展方向与个人经验复盘
项目做完之后回头看,其实还有几个方向值得进一步挖掘。如果以后想把系统做到生产级别,可以增加视频流处理模块,接入实时摄像头或者巡检车的行车记录仪画面,用视频帧序列做连续检测,结合目标跟踪算法预测病害框在帧间的运动轨迹,减少重复告警。这个方向在技术上升级不大,但场景价值提升非常明显,论文的工程性会更强。
另一个值得思考的方向是从目标检测走向语义分割。道路病害尤其是裂缝和网状裂纹,形状不规则且边界模糊,矩形框表达信息的粒度比较粗,而分割模型能输出像素级掩膜,对病害的面积计算、损坏程度评估帮助很大。虽然训练数据的标注成本会更高,但在真实养护场景中更有实用价值。如果你有余力,可以尝试用分割模型对裂缝做精细标注,对比检测和分割的效果,这也是一个很有亮点的实验章节。
性能优化方面也可以继续做文章。当前模型在嵌入式设备上的运行效率没有充分优化,以后可以尝试用TensorRT进行推理加速,把模型转为INT8量化版本,在同样的精度损耗下提升2到3倍推理速度。或者用知识蒸馏把YOLOv5s压缩成一个更小的自蒸馏版本,让检测速度更快。将这些内容写进论文的展望部分,会显得你对项目方向有深入思考和规划能力。
说回个人经验。我在这个项目中最大的收获不是模型的mAP数字,而是完整理解了“模型之外的工程”有多重要。深度学习训练只占了整个项目大约三分之一的时间,剩下三分之二都花在了数据整理、界面开发、系统调试和演示准备上。而且踩过的那些坑——线程崩溃、数据泄漏、中文字体、路径中文导致读取失败——每一样都是网上教程不会告诉你的实战经验。
这里顺便提一个多数初学者容易忽略的点:项目文件路径中不能有中文和空格。我在开发时因为项目文件夹名字带了“毕设”两个字,结果OpenCV读取图像的时候没有任何报错,但推理结果始终为空,排查了半天才发现是路径编码问题。把项目路径规范为全英文之后一切恢复正常。这种问题看起来很蠢,但一旦遇到就会白白消耗好几个小时。
答辩前的那一周,我又花时间把代码做了完整的注释整理,把训练命令、数据集下载方式、运行步骤都写进了README。不是为了给别人看,是为了让自己在最后调试时不用费力回忆几个月前的设计逻辑。事实证明这个习惯非常明智——答辩前三天我突然发现推理类里有个变量命名不清晰,差点改出错,幸好有文档辅助定位;另外,如果评审老师要求现场走上线的流程,你也可以快速说出每一步该怎么做。
做毕设的体验就像跑一个完整的工程项目,你不会只学到调参技巧,而是学会怎么把所有环节串起来。不要觉得PyQt界面只是陪衬,它在答辩中的作用很可能比模型本身更能决定成败。一个能现场运行、交互顺畅、结果清晰的系统,远比一个只在笔记本里有高精度数字的模型更容易赢得认可。希望这篇复盘能帮即将面对这个课题的同学少走一些弯路,把精力花在真正值得打磨的地方。最后想说一句,你的毕设是证明你具备解决完整问题能力的机会,别浪费它。