卫星云图识别:从CSV数据到模型对比的完整实战指南
2026/9/24 20:07:21 网站建设 项目流程

简介:一份面向计算机视觉课程设计与毕业设计场景的卫星云层图像理解与识别项目完整资料包。项目基于Python实现,涵盖数据处理、模型训练、测试与可视化完整流程,适合计科、人工智能、电子信息等专业学生用于课设、大作业或毕设参考。压缩包内共140个文件,以70个.py源码和44个.pyc编译文件为主,另含5个CSV数据集、3个YAML配置、6个Shell脚本,以及实验报告PDF、汇报PPT和结果图片,整体约62.33MB,目录结构清晰、便于按模块查阅。代码经测试运行通过后上传,答辩平均分达96分;配套项目说明文档与多份模型测试结果,方便快速复现实验、理解算法思路,也可在此基础上扩展功能。目前已有239人学习/下载,适合需要完整项目范例的人群参考。

1. 卫星云图识别:一份能直接跑的计算机视觉大作业源码

计算机视觉大作业里,卫星云图识别是特别容易出片子的题目:数据公开可拿、任务边界清晰、结果可视化也直观。但这份资源真正打动我的,不是题目本身,而是它的完成度——Python 源码、实验报告 PDF、答辩 PPT、结果图片、训练集和测试集 CSV 全都在一个包里,train_700.ver0.csv 和 test.csv 一看就是真实跑过完整流程的产物。更关键的是 model_test_1.csv、model_test_3.csv、model_test_4.csv 三个预测文件,说明源码里至少跑了三个模型做对比实验,这是答辩拉开分数的地方。适合两类人:正在赶计算机视觉课设、需要完整参照的学生,以及刚入门 Python 做视觉项目、想把从 CSV 到模型输出的整条通路看明白的新手。先跑通,再改,是打开这份资源最正确的姿势。

2. 数据集与标注结构:从 train_700 到 test.csv 的拆解

拆这份资源的时候,我先看的不是模型代码,而是那个 train_700.ver0.csv。文件名里的 700 基本可以断定训练样本是 700 张带标注的卫星云图,ver0 则表示数据清洗迭代过至少一版。test.csv 是独立的测试集,model_test_1/3/4.csv 是三个模型在测试集上的预测输出。理解了这套文件关系,后面的代码读起来就顺了。

2.1 从 CSV 结构反推标注体系

课程设计里的 CSV 格式通常很朴素,最常见的是两列:一列指向图像路径,一列是类别编号或类别名。下载后先用 pandas 探测一下结构,确认列名、样本量和类别分布,再决定预处理怎么写。千万不要跳过这一步直接写 DataLoader,列名对不上后面全是坑。

import pandas as pd df = pd.read_csv("train_700.ver0.csv") print("列名:", df.columns.tolist()) print("样本量:", len(df)) print(df["label"].value_counts()) # 假设标签列名为 label

这段代码做了三件事:确认列名是 image_path 还是别的,否则后面所有按列名的操作都会报 KeyError;确认样本量是否真的是 700 条;看每个类别的样本数量是否均衡。卫星云图分类常见的类别体系是把云系分成晴空、层云、积云、卷云等几类,类别数一般在 4 到 6 之间。如果 value_counts() 的结果里某一类占了大头,后面训练就要考虑类别不均衡的应对方案。

2.2 训练集与测试集的划分逻辑

拿到带标签的训练数据后,第一件事是从里面切出一部分做验证集。700 张图本身不多,如果随机切,可能把某一类小类别全部切到验证集里,训练集反而缺了这类样本。这里要用分层抽样,也就是按标签比例切分,保证训练集和验证集的类别分布一致。

from sklearn.model_selection import train_test_split train_df, val_df = train_test_split( df, test_size=0.2, stratify=df["label"], random_state=42 ) print(train_df["label"].value_counts()) print(val_df["label"].value_counts())

stratify 参数是这行代码的灵魂,它要求切分后的两个子集在 label 列上的比例和原数据集一致。random_state 设为固定值,是为了让每次运行切的都一样,实验可复现。验证集占 20%,也就是 140 张,对评估模型来说够用了。这里要特别提醒一句:所有预处理操作,比如归一化的均值和标准差,必须在训练集上计算,再应用到验证集和测试集,否则会有轻微的数据泄漏,导致验证指标虚高。

2.3 数据增强与类别均衡:小数据集的保命手段

700 张训练图对深度学习模型来说确实紧张,好在这种作业题不会要求你在不预训练的情况下从零训一个超大网络。数据增强是绕不开的一步,好在卫星云图有个天然优势:云系的方向感不强,旋转、翻转都不会改变语义,这给增强留了很大空间。

from torchvision import transforms train_transform = transforms.Compose([ transforms.RandomHorizontalFlip(p=0.5), transforms.RandomRotation(degrees=15), transforms.ColorJitter(brightness=0.2, contrast=0.2), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ])

RandomHorizontalFlip 以 0.5 的概率水平翻转,RandomRotation 允许图像旋转 ±15 度,ColorJitter 则模拟不同时段、不同光照条件下云图的亮度差异。最后的 Normalize 用的是 ImageNet 的统计值,这是迁移学习场景下的常见做法,因为预训练模型就是在这些参数下训练的。如果类别分布确实不均衡,我一般会在损失函数里加类别权重,或者对少数类做重复采样,这比单纯堆增强更可控。

3. 模型与训练配置:三个 test 文件背后的对比实验

model_test_1.csv、model_test_3.csv、model_test_4.csv 三个文件名放在一起,信息量很大:编号不连续,说明作者在实验过程中淘汰过中间版本,这是正常的实验记录习惯。三个模型做对比,既能让报告里的实验章节有内容可写,也能在答辩时展示你对模型差异的理解。

3.1 从 model_test 文件反推模型对比思路

课程设计场景下,最常见的对比组合是一个简单 CNN 加一两个预训练网络。简单 CNN 作为 baseline,证明基线性能;预训练模型证明迁移学习的价值。三者的参数量和精度差异天然构成了实验对比表。

模型参数量级训练方式在云图任务中的特点
Baseline CNN(3-4 层卷积)小,训练快从零训练收敛慢,容易过拟合,但逻辑清晰,适合讲原理
VGG16(预训练)冻结主干+微调分类头特征提取能力强,对小数据集友好
ResNet18(预训练)中等冻结部分层+微调残差结构缓解梯度消失,参数量比 VGG 小,性能通常更稳

我拆这份资源时看到三个输出文件,第一反应就是作者大概率做了这样的三模型对比。实际跑下来通常是:Baseline CNN 的精度最低,但训练最快;VGG16 和 ResNet18 借助预训练权重,收敛速度和精度都明显占优。报告里只需要一页对比表和两张曲线图,实验的丰富度就呈现出来了。

3.2 训练循环:从 DataLoader 到 checkpoint

不管哪个模型,训练循环的骨架是一样的。下面这段代码是 PyTorch 风格的训练函数,课程设计用这个框架最多,资料也好找。

import torch import torch.nn as nn from torch.utils.data import DataLoader def train_one_epoch(model, loader, criterion, optimizer, device): model.train() total_loss, correct, total = 0.0, 0, 0 for images, labels in loader: images, labels = images.to(device), labels.to(device) optimizer.zero_grad() outputs = model(images) loss = criterion(outputs, labels) loss.backward() optimizer.step() total_loss += loss.item() * images.size(0) correct += (outputs.argmax(1) == labels).sum().item() total += labels.size(0) return total_loss / total, correct / total

criterion 用交叉熵损失,多分类任务的默认选择。optimizer 一般用 Adam,初始学习率给 1e-4,这个值在预训练模型微调时比较安全,太大容易把预训练权重冲坏。batch_size 设 32,700 张图每个 epoch 约 22 个 batch,训练 30 个 epoch 很快。如果显存不够,把 batch_size 降到 16 也问题不大,但学习率最好跟着降到 5e-5 左右,否则收敛曲线会抖得厉害。

3.3 预训练权重怎么用:冻结还是全量微调

用预训练模型时有个常见争论:特征提取层是全部冻结还是全部微调。卫星云图和 ImageNet 里的自然图像差异不小,全部冻结只训分类头,前几层提取的纹理特征可能不太适配。我一般会折中:把模型的前几层冻结,后几层和分类头一起微调,这样既保留了通用特征,又能让深层特征适应云图分布。

model = torchvision.models.resnet18(pretrained=True) for name, param in model.named_parameters(): if "layer4" not in name and "fc" not in name: param.requires_grad = False optimizer = torch.optim.Adam( [p for p in model.parameters() if p.requires_grad], lr=1e-4 )

上面这段代码冻结了 ResNet18 除 layer4 和全连接层以外的所有参数,只有最后一层残差块和分类头参与训练。这样做的好处是参数量大幅减少,训练速度快,而且在小数据集上不容易过拟合。如果训练曲线显示验证集精度还有上升空间,可以再解冻 layer3 继续微调,这是调参方向上的先后顺序,比一上来就全量微调稳。

4. 实验报告与答辩 PPT:96 分交付物的材料骨架

这份资源的摘要信息里提到答辩评审平均分 96 分,这不是模型有多牛,而是材料齐整、逻辑闭环。很多人的代码能跑,但实验报告和 PPT 写得像流水账,拉低了整体印象分。源码包里带的实验报告 PDF 和 PPT 模板,正好是比着代码组织结构写的范本。

4.1 实验报告的章节骨架与数据支撑

课程设计实验报告有固定的套路:问题定义、方法设计、实验设置、结果分析、结论。每一章必须有对应的内容支撑,光贴代码不解释是拿不到高分的。

报告章节必写内容对应资源文件
绪论与背景卫星云图识别在气象分析中的作用,任务定义README.md 中的项目说明
数据集介绍样本数量、类别体系、训练/验证/测试划分方式train_700.ver0.csv、test.csv
方法设计数据增强策略、三个模型的结构对比、损失函数与优化器源码中的 train.py、model 定义
实验设置batch_size、学习率、epochs、冻结策略、软硬件环境训练日志
结果分析三模型精度对比、损失曲线、混淆矩阵、错误案例结果图片.png、model_test_*.csv
结论与反思哪些方法有效、哪些失败、后续改进方向实验报告 PDF 结论段

写结果分析时有一个取巧但有效的写法:用 model_test_1/3/4.csv 三个文件生成一个精度对比表,再挑两张典型错误样本图分析失败原因。这样的报告看上去就是完整做实了实验的,而不是只抄了代码跑了个 acc。

4.2 结果图片与 README:把压箱底的东西摊开

源码包里有一张结果图片.png,这个文件的含金量在于它是验证实验是否完成的直接证据。我建议你下载后自己复现时,把这张图重新生成一遍:训练集和验证集的 loss 曲线放在一张图里,准确率曲线放另一张,下面附一个三模型的精度柱状图,最后是混淆矩阵热力图。这一张 PNG 就能撑起整个 PPT 的实验部分。

README.md 是每个项目的门面,下载后第一件事就是读它。这份资源的 README 我不知道具体写法,但合格的项目说明至少包含运行环境、安装依赖、训练和测试的命令顺序。

pip install -r requirements.txt python train.py # 训练模型并保存权重 python test.py # 在 test.csv 上推理,输出 model_test.csv

按这个顺序跑完,基本不会出问题。如果源码里没有 requirements.txt,就从 import 语句反推依赖列表,最核心的也就是 torch、torchvision、pandas、numpy、matplotlib 这几项。

4.3 答辩现场的提问预演

答辩比的是谁更了解自己的工作。讲的时候按这个节奏控制时间:30 秒讲任务和数据,1 分钟讲模型对比思路,1 分钟讲实验结果,最后 30 秒讲不足和改进。常见提问基本逃不出下面这几个,提前想好答案就不会卡壳。

试探性问题应答思路
为什么选这三个模型?Baseline CNN 给基线,VGG16 和 ResNet18 验证迁移学习效果,形成对比
数据增强会不会导致测试集失去代表性?增强只加在训练集,验证集和测试集只做统一尺寸调整和归一化
准确率是不是有点低?承认小数据集和云图类别相近的困难,指出错误主要发生在哪两类之间
为什么用 ImageNet 预训练权重?虽然云图和自然图像有差异,但底层边缘纹理特征通用,微调后高层特征能适配

如果被问到模型参数量的细节,直接用第 3 章的对比表回答就行,不用背数字,讲清楚差异即可。

5. 卫星云图识别避坑:五个运行期真问题

这类资源拿来后真正跑一遍,总会撞上几个问题。我挑五个最常见、也最影响交付质量的记录一下,每条都是「现象 → 原因 → 解决」的结构,你现在遇到哪个直接对号入座。

5.1 相对路径导致的 FileNotFoundError

现象:运行训练脚本后立刻报错,FileNotFoundError,提示某个图片文件找不到。

原因:CSV 里保存的图像路径是相对路径,比如data/train/cloud_001.jpg,但你把代码和数据目录的层级关系动了,脚本当前工作目录和 CSV 里的相对路径对不上。

解决:先确定源码里是不是在读取 CSV 后拼接了统一的图像根目录,比如os.path.join("dataset", row["image_path"])。如果没有拼接,就在自己的复现目录里保持和压缩包一致的目录结构,或者在代码开头加一行os.chdir(os.path.dirname(__file__)),把工作目录切到脚本所在目录,路径问题能消掉一半。

5.2 分隔符错位导致标签整体偏移

现象:pd.read_csv()读完后,发现数据只有一列,或者标签列的值看起来像是文件名。

原因:CSV 文件用的是分号或制表符分隔,但 pandas 默认按逗号解析,导致整行被读成了一列。train_700.ver0.csv 这个文件名带了版本号,可能是从某些标注工具导出的,格式未必是标准的逗号分隔。

解决:先用文本编辑器打开 CSV 看一眼第一行,确认分隔符再读。

import pandas as pd df = pd.read_csv("train_700.ver0.csv", sep=";") # 分号分隔 df = pd.read_csv("train_700.ver0.csv", sep="\t") # 制表符分隔

sep 参数按实际分隔符调整即可。读完后再执行一次print(df.columns.tolist()),确认列数和列名符合预期再往下走。

5.3 准确率虚高的训练集幻觉

现象:训练损失降到很低,训练集准确率接近 99%,但验证集准确率只有 60% 上下。

原因:过拟合,这是 700 张小数据集的典型症状。尤其是从零训练的 Baseline CNN,模型容量大但数据量撑不住,本质上是把训练样本的噪声也背下来了。

解决:三类手段叠加。第一,加数据增强,这是第 2 章里那套 transform 的作用;第二,在卷积层后加 Dropout 或 BatchNorm,抑制过拟合;第三,换用预训练模型,预训练权重相当于给模型灌了先验知识,比从零训收敛更稳。如果用了预训练模型还是过拟合,检查一下数据增强是不是没挂到训练集上,只做了 ToTensor 和 Normalize。

5.4 云图类别不均衡导致模型偷懒

现象:整体准确率看起来还行,但逐类看,某一类的召回率几乎是 0,模型把所有样本都预测成了多数类。

原因:数据集中不同云系样本数量差距过大,模型学到的最优策略是全猜多数类,代价最小。

解决:训练前跑一遍第 2 章的value_counts(),如果最少类样本数不到最多类的三分之一,就要干预了。最简单的做法是在 DataLoader 里对少数类做重复采样,用一个 WeightedRandomSampler 让每个类别出现在每个 epoch 的次数接近;或者在损失函数里传类别权重,让少数类的误判代价更大。两种方法我都用过,重复采样实现更直观,类别加权调参更精细,课程设计用前者就够了。

5.5 测试输出格式与评分脚本不匹配

现象:测试集推理完成了,生成的 model_test.csv 内容看起来也对,但一跑评分脚本就报格式错误。

原因:评分脚本要求的是两列,第一列是样本 id,第二列是预测类别,而且顺序要和 test.csv 完全一致。你生成的 CSV 可能没有表头,或者预测结果是 one-hot 形式而不是类别编号,甚至行顺序在推理时被打乱了。

解决:生成输出文件前,先保留 test.csv 的样本 id 顺序,推理结果按索引一一对应。写完文件后立刻读回来验证一次。

import pandas as pd sub = pd.DataFrame({"id": test_ids, "label": predictions}) sub.to_csv("model_test.csv", index=False) # 验证 check = pd.read_csv("model_test.csv") print(check.head()) print(check.isnull().sum())

提交前务必确认输出文件里没有空值,预测类别都在合法范围内,行数也和 test.csv 一致。这三个条件满足,格式问题基本就排除了。

6. 用混淆矩阵再推一步:找类别盲区,给实验加可信度

三模型的对比实验做完了,如果你还有余力,我建议做一次混淆矩阵级别的错误分析。这是从“跑通”到“懂”的分水岭,也是答辩时最能体现深度的材料。

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay import matplotlib.pyplot as plt cm = confusion_matrix(y_true, y_pred) disp = ConfusionMatrixDisplay(confusion_matrix=cm) disp.plot(cmap="Blues") plt.title("Confusion Matrix of ResNet18") plt.savefig("confusion_matrix.png", dpi=150)

拿到混淆矩阵后的读法不是看对角线有多亮,而是找对角线以外的密集点。比如云图里层云和积云如果经常互相误判,说明这两类在纹理特征上确实接近,这是数据集本身的性质决定的,不是模型的错。把这个发现写进报告里,说明你理解为什么模型会犯错,比单纯报一个准确率更有说服力。

进一步验证的话,可以用 K 折交叉验证替换掉单次的训练验证划分。700 张数据量小,单次划分的偶然性很大,K 折交叉验证能给出一个均值加标准差的精度范围,实验的稳健性立刻体现出来。课程设计阶段做到这两步,材料的深度已经超过绝大多数同学了。

从那以后我每次跑完训练,第一件事不是看 loss 曲线,而是直接打印混淆矩阵,看一眼模型把哪两类搞混了、每类的召回率分布如何,确认整体趋势合理再决定要不要继续调参。这一次先读 CSV、再跑通三个模型、最后补一轮错误分析的流程走下来,比单纯把代码跑一遍收获大得多,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询