简介这份资源是西安电子科技大学雾霾检测项目的阶段性成果包面向环境科学、电子信息工程及数据分析方向的学习者与研究人员可用于空气质量监测、传感器数据采集与可视化分析的实践参考。压缩包共73个文件约10.51MB以JavaScript、Vue组件、JSON配置、Markdown说明及图片素材为主涵盖前端页面、图表渲染、接口请求与项目文档等模块整体结构接近一个可运行的监测数据展示工程。资源中可能包含测试报告、实测数据集、数据处理源码及空气质量变化图、污染物浓度分布图等图表有助于理解从数据采集到分析呈现的完整流程。目前已有513人学习下载适合关注雾霾监测、环境数据分析与前端可视化实现的学习者参考借鉴。1. 西电B测雾霾检测一个课程项目包为什么值得你花一晚上跑通如果你手里正好有一个叫「西电B测雾霾检测.zip」的压缩包或者你正在搜「西电B测」到底测什么、雾霾检测这种题目能不能当练手项目那这篇就是写给你的。先说结论这不是一个工业级部署方案而是一个典型的课程设计级计算机视觉项目——用图像做雾霾等级分类或能见度回归核心链路是「数据预处理 → 特征提取/模型训练 → 指标评估 → 可视化输出」。它解决的不是「预测明天PM2.5」这种气象问题而是「给一张户外照片判断雾霾严重程度」这类图像分类/回归问题。适合谁适合刚学完机器学习或深度学习基础、想找一个完整闭环练手的人适合要交课程大作业、需要快速搭出可演示系统的人也适合想理解「图像去雾/雾霾检测」这条技术线到底怎么落地的人。不适合谁不适合指望拿它直接做产品的人——数据规模、标注质量、泛化能力都撑不住真实场景。我见过太多人拿到这种包第一步就翻车环境跑不起来或者跑起来了但不知道每个文件在干嘛。所以下面我不按「项目介绍」的套路写而是按「你要复现它、改造它、讲清楚它」的路径来拆。西电B测这个关键词背后大概率是西安电子科技大学某门课的B类测试或大作业雾霾检测是题目方向。你不需要纠结它是不是官方出品你需要的是把这条技术链路吃透。2. 拆开压缩包之前雾霾检测到底在检测什么2.1 图像雾霾检测的两种技术路线分类还是回归拿到「雾霾检测」四个字很多人第一反应是传感器数据、PM2.5数值。但这个项目包是图像方向的所以你要先分清两条路。第一条是分类路线把图像分成「无雾/轻雾/中雾/重雾」几个等级本质是CNN分类任务输出是离散标签。第二条是回归路线预测一个连续值比如能见度距离或雾霾浓度指数输出是浮点数。课程项目里分类更常见因为标注成本低、评估指标直观准确率、混淆矩阵。怎么判断你手里这个包是哪条路看标签文件。如果标签是0/1/2/3这种整数就是分类如果是带小数的数值就是回归。看损失函数也能判断交叉熵就是分类MSE/MAE就是回归。我一般会先打开数据目录看一眼这一步花两分钟能省后面两小时。选型理由上分类路线对新手更友好因为你可以用预训练模型直接fine-tune数据量小也能出结果。回归路线更接近真实需求但标注难度大课程项目里少见。如果你要改造这个项目去参加比赛或写论文建议从分类切入再考虑加一个回归头做多任务。2.2 数据集长什么样从文件名到标签的映射逻辑课程项目的数据集通常有两种组织方式。第一种是按文件夹分好类比如data/train/haze/、data/train/clear/这种最省事直接用ImageFolder就能读。第二种是图片全放在一个目录标签写在CSV或txt里格式类似img_001.jpg,2。你得先确认是哪种不然写数据加载器时会对不上。这里有个血泪经验很多包里的标签文件和图片文件名大小写不一致或者有隐藏的空格。Windows下看不出来Linux下直接报错找不到文件。我一般会先跑一段脚本做一致性检查把图片名和标签名做交集看有没有对不上的。import os import pandas as pd # 假设标签文件是 labels.csv两列filename, label label_df pd.read_csv(data/labels.csv) img_dir data/images # 检查标签里的文件名是否都能在图片目录找到 img_files set(os.listdir(img_dir)) label_files set(label_df[filename].tolist()) missing label_files - img_files extra img_files - label_files print(f标签里有但图片目录没有的: {len(missing)}) print(f图片目录有但标签里没有的: {len(extra)}) if missing: print(示例缺失文件:, list(missing)[:5])这段脚本的逻辑很简单把两个集合做差集。参数上你只需要改labels.csv的路径和列名。如果missing不为空说明标签文件有问题要么是路径写错要么是文件名编码不一致。这一步不做后面训练时会在某个batch突然报FileNotFoundError排查起来很烦。2.3 环境依赖为什么你直接pip install会翻车课程项目包的requirements.txt经常是「当时能跑就行」的状态版本号可能写得很随意甚至没写。你直接pip install -r requirements.txt大概率会遇到两个问题一是torch版本和CUDA不匹配二是某个包已经改名或废弃。我一般不会直接装而是先看代码里import了什么再手动装核心依赖。核心依赖通常就这几个torch、torchvision、numpy、PIL、matplotlib、pandas、scikit-learn。如果代码里用了tqdm就加上用了tensorboard就加上。版本上torch选1.10以上都行但要注意torchvision要和torch版本对应。比如torch 2.0配torchvision 0.15torch 1.13配torchvision 0.14。这个对应关系去PyTorch官网查别凭感觉装。提示如果你没有GPU装CPU版torch就行命令里加--index-url https://download.pytorch.org/whl/cpu。课程项目的数据量CPU跑也能出结果就是慢点。3. 把项目跑起来从数据加载到第一次训练3.1 数据预处理resize、归一化和增强的取舍图像分类项目里预处理决定了模型能不能收敛。课程项目包里的预处理代码通常写在transforms.Compose里你要看懂每一行的作用。Resize((224, 224))是把短边缩到224再中心裁剪这是ImageNet标准输入。ToTensor()把PIL图像转成0-1的tensor。Normalize(mean, std)用ImageNet的均值和标准差做标准化这一步不能省否则预训练模型的效果会打折。数据增强是另一个关键点。训练集一般加RandomHorizontalFlip、RandomRotation、ColorJitter验证集不加。但雾霾检测有个特殊之处ColorJitter改亮度对比度可能会改变雾霾的视觉特征所以增强力度要小。我一般只加水平翻转和轻微旋转颜色相关的增强慎用。from torchvision import transforms train_transform transforms.Compose([ transforms.Resize((224, 224)), transforms.RandomHorizontalFlip(p0.5), transforms.RandomRotation(degrees10), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) val_transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ])参数说明p0.5表示一半概率翻转degrees10是旋转角度范围。归一化的均值和标准差是ImageNet的统计值如果你从头训练不用预训练模型可以改成自己数据集的均值和标准差但课程项目里直接用ImageNet的值就行。3.2 模型选择ResNet18够不够用课程项目里最常见的模型是ResNet18或VGG16。ResNet18参数量小、训练快在几千张图的规模上够用。如果你要追求更高精度可以换ResNet50或EfficientNet-B0但训练时间会翻倍。我的建议是先用ResNet18跑通全流程再考虑换模型。加载预训练模型时要注意最后一层全连接层的输出维度要改成你的类别数。比如雾霾分4类就把model.fc改成nn.Linear(512, 4)。如果代码里用的是model.classifier那就是VGG系列改法类似。import torch.nn as nn from torchvision import models def build_model(num_classes4, pretrainedTrue): model models.resnet18(pretrainedpretrained) # 冻结前面的层只训练最后的全连接层可选 # for param in model.parameters(): # param.requires_grad False model.fc nn.Linear(model.fc.in_features, num_classes) return model model build_model(num_classes4) print(model.fc)逻辑说明pretrainedTrue会下载ImageNet预训练权重第一次运行需要联网。model.fc.in_features是ResNet18最后一层的输入维度512。如果你冻结了前面的层只训练fc层收敛更快但精度可能低一点。课程项目里我一般不冻结直接全量fine-tune效果更好。3.3 训练循环损失函数、优化器和学习率怎么设训练循环的骨架是前向传播 → 计算损失 → 反向传播 → 更新参数。损失函数用CrossEntropyLoss优化器用Adam或SGD。Adam学习率设1e-3SGD设1e-2加动量0.9。课程项目里Adam更省心不用调太多参数。学习率调度器可以用StepLR每10个epoch降一半。batch size根据显存来8G显存用324G用16CPU用8。epoch数一般20-50看验证集准确率什么时候不涨了就可以停。import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader # 假设 train_dataset 和 val_dataset 已经定义好 train_loader DataLoader(train_dataset, batch_size32, shuffleTrue, num_workers4) val_loader DataLoader(val_dataset, batch_size32, shuffleFalse, num_workers4) device torch.device(cuda if torch.cuda.is_available() else cpu) model build_model(num_classes4).to(device) criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.parameters(), lr1e-3) scheduler optim.lr_scheduler.StepLR(optimizer, step_size10, gamma0.5) for epoch in range(30): model.train() running_loss 0.0 for images, labels in train_loader: images, labels images.to(device), labels.to(device) optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() running_loss loss.item() scheduler.step() print(fEpoch {epoch1}, Loss: {running_loss/len(train_loader):.4f})参数说明num_workers4在Windows下可能报错改成0就行。shuffleTrue只在训练集用验证集必须False。scheduler.step()放在epoch末尾不是batch末尾。这些细节错了训练结果会差很多。3.4 验证与指标准确率之外还要看什么训练完看准确率是基本操作但只看准确率会漏掉很多问题。比如数据不平衡时模型全预测多数类也能有高准确率。所以你要看混淆矩阵看每个类别的召回率和精确率。sklearn.metrics里的classification_report一行搞定。from sklearn.metrics import classification_report, confusion_matrix import numpy as np model.eval() all_preds [] all_labels [] with torch.no_grad(): for images, labels in val_loader: images, labels images.to(device), labels.to(device) outputs model(images) _, preds torch.max(outputs, 1) all_preds.extend(preds.cpu().numpy()) all_labels.extend(labels.cpu().numpy()) print(classification_report(all_labels, all_preds, target_names[clear, light, medium, heavy])) print(confusion_matrix(all_labels, all_preds))逻辑说明torch.no_grad()关闭梯度计算省显存。torch.max(outputs, 1)取最大值的索引作为预测类别。classification_report会输出每个类别的precision、recall、f1-score。如果某个类别的recall特别低说明模型没学好这个类别可能是样本太少或特征不明显。4. 避坑与排查课程项目包里最常见的5个翻车点4.1 路径问题Windows和Linux的斜杠之争现象在Windows上跑得好好的代码换到Linux服务器上就报FileNotFoundError。原因代码里写死了反斜杠\或者用了绝对路径C:\Users\...。解决全部改成os.path.join或pathlib.Path路径用相对路径。我一般会在代码开头加一句os.chdir(os.path.dirname(__file__))把工作目录切到脚本所在目录这样相对路径就不会乱。4.2 显存不够batch size调小还是换模型现象训练时突然报CUDA out of memory。原因batch size太大或者模型参数量太大。解决先把batch size减半如果还不行就换小模型。另外torch.cuda.empty_cache()可以清缓存但治标不治本。还有一个隐藏原因是验证时没加torch.no_grad()导致显存持续累积。4.3 损失不下降学习率太大还是数据有问题现象训练几个epoch后loss一直在2.0左右震荡不下降。原因学习率太大或者标签有问题。解决先把学习率降到1e-4试试。如果还不行检查标签是不是全0或全1或者图片和标签是不是错位了。我遇到过一次标签文件的行顺序和图片顺序不一致导致模型在学随机噪声。4.4 验证集准确率远低于训练集过拟合怎么破现象训练集准确率95%验证集只有60%。原因过拟合模型记住了训练集但没学到泛化特征。解决加数据增强、加Dropout、加权重衰减weight_decay1e-4或者减少模型复杂度。课程项目里数据量小过拟合很常见我一般会加RandomHorizontalFlip和RandomRotation再把ResNet18换成更小的模型。4.5 预测结果全是同一类类别不平衡的锅现象模型对任何输入都预测为「重雾」。原因训练集里「重雾」样本太多模型学会了偷懒。解决用WeightedRandomSampler做重采样或者在损失函数里加类别权重weighttorch.tensor([1.0, 2.0, 3.0, 4.0])。另外评估时不要只看准确率要看每个类别的f1-score。5. 从能跑到好用三个让课程项目加分的进阶技巧5.1 用Grad-CAM可视化模型到底在看哪里课程项目答辩时老师最爱问「你的模型凭什么判断这是雾霾」。如果你能拿出一张热力图标出模型关注的区域说服力直接拉满。Grad-CAM的原理是取最后一层卷积层的梯度做全局平均池化后加权求和得到一张和输入图像同尺寸的热力图。import cv2 import numpy as np import torch from pytorch_grad_cam import GradCAM from pytorch_grad_cam.utils.image import show_cam_on_image # 假设model是训练好的ResNet18target_layer是最后一层卷积 target_layer model.layer4[-1] cam GradCAM(modelmodel, target_layers[target_layer]) # 取一张验证集图片 input_tensor val_transform(image).unsqueeze(0).to(device) grayscale_cam cam(input_tensorinput_tensor)[0] # 叠加到原图 rgb_img np.array(image.resize((224, 224))) / 255.0 visualization show_cam_on_image(rgb_img, grayscale_cam, use_rgbTrue) cv2.imwrite(cam_output.jpg, cv2.cvtColor(visualization, cv2.COLOR_RGB2BGR))参数说明target_layer选最后一层卷积层太浅的层语义信息不够。pytorch_grad_cam需要额外安装pip install pytorch-grad-cam。如果装不上可以用torchcam替代。生成的cam_output.jpg里红色区域就是模型关注的地方。如果红色区域集中在天空或远景说明模型学到了雾霾的视觉特征如果集中在无关物体上说明模型走偏了。5.2 用ONNX导出模型让部署不再依赖PyTorch课程项目通常只在本地跑但如果你想让别人也能用导出ONNX是个好选择。ONNX是跨框架的模型格式可以用ONNX Runtime在C、Java、Python里加载不依赖PyTorch环境。import torch.onnx model.eval() dummy_input torch.randn(1, 3, 224, 224).to(device) torch.onnx.export( model, dummy_input, haze_model.onnx, input_names[input], output_names[output], dynamic_axes{input: {0: batch_size}, output: {0: batch_size}}, opset_version11 ) print(ONNX模型已导出)逻辑说明dummy_input是一个示例输入用来追踪计算图。dynamic_axes让batch size可变这样推理时可以一次传多张图。opset_version11兼容性较好。导出后用onnxruntime加载验证一下输出是否一致差异在1e-5以内就算成功。5.3 一个我踩过的坑别在验证集上调超参数最后说一个我自己的教训。有一次做课程项目我在验证集上反复调学习率、batch size、数据增强策略最后验证集准确率刷到92%但答辩时老师换了一个新测试集准确率直接掉到70%。原因很简单验证集被我「用」成了训练集模型间接过拟合了验证集。正确做法是把数据分成训练集、验证集、测试集三份。验证集只用来选模型和调超参数测试集只在最后跑一次。如果数据量太小至少也要做交叉验证。课程项目里很多人图省事只分两份短期看没问题但一旦老师换数据就露馅了。我现在的习惯是拿到任何项目先切出10%做测试集锁在一边不动。调参只看验证集最后用测试集出一份报告。这个习惯让我少翻了很多车。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
ASP+ACCESS毕业设计包实战:IIS环境搭建、源码解析与避坑指南 简介:这份毕业设计资料包面向高校计算机相关专业学生,提供一套基于ASP与ACCESS数据库的网上远程教育网完整实现方案,可用于课程设计、毕业设计参考或Web开发入门练手。资源共65个文件,约594KB,包含23个asp动态页面、17… · 2026/9/26 11:28:40
OpenCV手势识别打地鼠:从摄像头到锤子的完整链路与避坑指南 简介:这份资源面向人机交互课程学习者、OpenCV 入门开发者及需要完成课程设计的学生,提供一套基于手势识别控制的打地鼠游戏完整项目。项目通过 Python 调用 mediapipe 库,识别食指与中指骨节点位置判定手势,实现光标移动与击打动… · 2026/9/26 11:28:40
微信小程序+SSM学生签到系统:设计、实现与踩坑实战 这套"基于微信小程序的学生签到系统"我实际做下来最有感触的一点是:签到这个动作看起来简单,真正设计起来却同时牵扯到身份、时间、位置和状态流转四套逻辑。学校大课堂上,老师拿着纸质名单点名,六十多个人点完基本就过… · 2026/9/26 12:29:50
玩转 Openclaw 玩法技巧:搭建中国开发者 Skills 并接入 TaoToken 统一 Key 通道 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 12:29:38
谷歌封杀也挡不住!OpenClaw+Qwen3.5,开源AI彻底疯了:TaoToken统一Key接入配置实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 12:29:38
BitLocker锁图标+感叹号:脱机状态诊断与修复指南 1. 锁图标感叹号:这不是普通磁盘故障,而是BitLocker状态告警的明确信号你刚打开“磁盘管理”(diskmgmt.msc),一眼就看到某个卷图标上叠着一把小锁,旁边还挂着一个醒目的黄色感叹号——这种组合在Windows系统… · 2026/9/26 12:29:38
Windows 11安装Node.js与npm国内镜像源永久配置教程 如果你也在Windows 11上准备装Node.js,多半已经体会过那几步的酸爽:官网下载半天不动,装完在终端敲node -v没反应,好不容易跑通,npm install又慢得像老牛拉车。其实这三件事都能拆开解决,今天我就把完整过程… · 2026/9/26 12:29:38
IDEA 2026.1 里 Cursor 智能体切换账号:TaoToken 统一 Key 配置与验证 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 12:29:38
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46