news 2026/9/24 0:06:20

昆虫识别与数目统计毕设实战:从CSV到ResNet迁移学习全流程解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
昆虫识别与数目统计毕设实战:从CSV到ResNet迁移学习全流程解析

简介:一套完整的昆虫识别与数目统计毕业设计项目资源,面向大四学生及需要完成课设、大作业的开发者,提供从模型训练、目标检测到数量统计的闭环方案。压缩包共164个文件,大小14.59MB,内含23个Python脚本、97张JPG图片、13个npy数据文件、10个XML标注文件、3个模型文件、3个CSV表格,以及UI界面、PDF说明等,便于对照代码、数据与文档理解整体结构。目前已有140人学习下载,具备一定参考价值。读者可基于该项目快速搭建昆虫检测与计数实验环境,复用已训练模型与预处理数据,学习数据集标注格式、模型调用方式与统计逻辑;内置的界面文件与说明文档可帮助梳理交互流程,适合毕业设计查重、代码复现及功能扩展,也可在此基础上替换为其他昆虫类别,迁移到类似计数任务中。

1. 昆虫识别与数目统计:毕设里的两个坑,一个在识别精度,一个在统计口径

“大四毕业设计:昆虫识别和数目统计”这个主题,听起来不算难,无非是分类加计数,但真正复现过的人都知道,识别模型好训,数目统计才是翻车重灾区。这份 zip 资源从文件名看,结构是三个 CSV(data.csv、datatest.csv、ques.csv)、几张 fly*.jpg 测试图片和一个 .iml 工程文件,属于典型的课设/大作业/毕设骨架:表管数据、图管验证、工程文件管环境。它能解决的核心问题是——给你一套从数据读到识别再到统计的完整代码基础,不用从零搭环境、不需要自己拍图标注,改改参数就能往自己的方向迁移。适合 Python 有一定基础、但需要靠这份毕设快速产出可运行结果的在校生下载复现。

2. 拆包看结构:从 zip 压缩包到可复现工程,中间需要的几步

拿到资源后第一件事不是看代码,而是确认压缩包能不能安全解出来,以及解出来以后哪些文件是真的能用的。很多同学在这步就开始了“玄学调试”——文件还没看全,就开始改代码。这里把拆包过程完整走一遍。

2.1 解压与文件清单核对:先用 Linux 命令把 zip 安全打开

下载下来是一个 zip 压缩包,文件名是「课设&大作业&毕设-大四毕业设计:昆虫识别和数目统计.zip」。这个文件名的坑在解压前就会出现:文件名里带了&和中文冒号,在 Linux bash 里直接unzip会报找不到文件。我的处理方式是先把 zip 改名成纯英文,再解压:

mv '课设&大作业&毕设-大四毕业设计:昆虫识别和数目统计.zip' insect.zip unzip -q insect.zip -d insect_project cd insect_project && ls -la

这里-q是静默模式,不会把每个文件名刷屏打出来;-d insect_project指定解压目录,避免所有文件直接撒在当前目录。

解压后你会看到的文件,我用表格做一个清单:

文件作用
data.csv训练标注数据,通常是 image_path + label 的结构
datatest.csv测试集标注,可能比训练集多一列 count 或 bbox
ques.csv问题/需求描述,或者统计口径说明
fly2.jpg、fly11.jpg、fly15.jpg、fly16.jpg、fly17.jpg测试样本图,目测是苍蝇类昆虫
Insect_Identification.imlIntelliJ 系 IDE 的工程模块文件
.gitignoreGit 忽略规则,说明这个项目原本带版本管理

注意,清单里没有model.pth这类权重文件,也没有类似train.py的独立脚本,所以这份资源更接近「骨架 + 测试数据」的快照,而不是一个解压就能跑出结果的一键项目。你得自己把训练代码补上,这对毕设来说反而是好事——能写进论文“本人实现”的部分多了。

2.2 CSV 标注结构怎么看:data、datatest、ques 三份表的分工

看 CSV 这种文件,最快的方式是用head看前几行,不要直接用 Excel 打开,因为一旦文件是 UTF-8 编码且含中文,Excel 会把它拆得乱七八糟。在 Linux 下直接执行:

head -5 data.csv echo "-----" head -5 datatest.csv echo "-----" head -5 ques.csv

常见的列结构是image_path,label或者filename,class_id,如果 datatest 里多了count列,那这个项目的数量统计就不是靠目标检测,而是靠对每个图片样本的计数回归或者多标签分类实现的。ques.csv 一般是题目要求,里面可能包含“统计每类昆虫出现次数”这类口径描述。

拿到 CSV 以后,我建议先做一次快速统计,确认样本分布长什么样:

import pandas as pd train = pd.read_csv("data.csv") test = pd.read_csv("datatest.csv") # 打印列名,确认哪一列是图片路径、哪一列是标签 print("训练集列名:", train.columns.tolist()) print("测试集列名:", test.columns.tolist()) # 按标签统计样本数量,看是否存在类别不平衡 label_col = 'label' if 'label' in train.columns else train.columns[1] print(train[label_col].value_counts())

这段代码的目的是在动手训练之前就掌握两个信息:列名长什么样、每个类别的样本量是否均衡。如果某个类的样本数只有另一个类的十分之一,后面训练时就必须做类别加权或者过采样,否则模型会把这个类直接忽略掉。

2.3 .iml 文件意味着什么:用 PyCharm 打开工程,省掉配置痛苦

.iml是 IntelliJ 家族的模块描述文件,PyCharm 打开项目时会靠它识别目录结构和运行配置。如果你用的是 PyCharm,直接File -> Open选到解压出来的目录,IDE 会自动根据.iml恢复项目视图。如果你的环境是 VS Code 或者纯终端,忽略这个文件也不影响训练代码运行。

这里有个常见误区:很多人以为.iml是 Java 项目专属,看到它就往 Maven 上想。实际上 PyCharm 的 Python 项目同样会生成.iml,它里面记录的只是 module 名称、SDK 以及源码目录标记。真正决定依赖版本的是requirements.txtenvironment.yml,但这份资源里没有这两个文件,所以我一般会先手动建一个虚拟环境,把 PyTorch 相关依赖补上:

python -m venv venv source venv/bin/activate pip install torch torchvision pandas pillow scikit-learn matplotlib

为什么装这几样?torch 提供模型和训练循环,torchvision 提供预训练模型和图像变换,pandas 负责解析 CSV,pillow 负责读图,sklearn 负责生成混淆矩阵和分类报告,matplotlib 负责画图。这些都是昆虫识别项目的最小依赖集,缺一个后面都会报错。

3. 从识别到统计:为什么分类模型不能直接回答数量问题

很多同学把“昆虫识别和数目统计”理解成“图像分类 + 数数”,实际操作时才发现两个环节之间的衔接有大量细节。这一章把识别、统计的链路拆开讲清楚,顺带说明选型时为什么常见毕设会选“迁移学习 + 分类汇总”而不是从头训练一个检测器。

3.1 昆虫识别链路:图像分类模型的基座与选择理由

昆虫识别本质上是一个图像分类任务:输入一张图片,输出该昆虫属于哪个类别。毕业设计场景里几乎没有从零训练一个 CNN 的必要,因为数据量撑不起来,训练时间也不允许。常见做法是拿 torchvision 里在 ImageNet 上预训练过的 ResNet18 或 ResNet50 做迁移学习,把最后的全连接层替换成自己的类别数。

import torchvision.models as models # 使用预训练 ResNet18,只替换最后一层 model = models.resnet18(weights=models.ResNet18_Weights.DEFAULT) num_classes = 10 # 按你的数据类别数修改 model.fc = torch.nn.Linear(model.fc.in_features, num_classes)

这段代码背后有两个参数值得注意:weights=models.ResNet18_Weights.DEFAULT表示下载官方预训练权重,这个权重在 ImageNet 上学到的底层特征(边缘、纹理、形状)对昆虫图像同样有效;model.fc.in_features读取的是原全连接层的输入维度,ResNet18 是 512,ResNet50 是 2048,直接替换可以避免维度写死导致的兼容性问题。

不用更深的网络不代表 ResNet50 不好,关键看你的图片尺寸。如果数据集里的照片普遍小于 200×200,ResNet18 可能比 ResNet50 更稳,因为深网络在小图上容易过拟合;如果图片是高清的且昆虫在画面中占比较大,ResNet50 的精度优势会体现出来。

3.2 数目统计的三种口径:按图统计、按目标统计、按类别统计

目录统计这个环节,决定你用什么样的后处理逻辑。毕业设计里最常见的口径有三种:

统计口径实现方式对应资源类型
按图片统计每张测试图预测一个类别,最后统计各类别图片张数datatest.csv 每行是一张图
按目标统计单张图里可能有多个昆虫,需要检测或密度图回归数据集带 bbox 标注
按类别统计统计每个昆虫类别出现的总次数,可跨图片数据集带 count 列

这份资源里 fly2.jpg、fly11.jpg、fly15.jpg 等多张图片同时存在,且没有 bbox 相关文件,更接近第一种口径的工程结构。也就是说,数量统计的实现方式大概率是:先对测试集每张图做分类,再用Counter汇总每一类的张数。

如果你发现 datatest.csv 里真的带count列,那就要把思路切换到回归或者密度估计,但那需要目标检测框架,不是简单改一个全连接层能解决的。

3.3 选型对比:ResNet 迁移学习还是 YOLO 检测器

我见过不少同学一上来就要上 YOLO,理由是觉得它能直接完成“识别 + 定位 + 计数”。这个想法本身没问题,YOLO 确实适合“一张图里有多个昆虫”的场景,但代价是标注成本极高——每个目标都要画框,一个图里标几十个框是常有的事。

选型标注成本训练难度数量统计精度
ResNet 分类 + 张数汇总低,每图一个标签低,迁移学习效果好只能统计图片张数
Faster R-CNN 检测高,每个目标一个框高,需要调 anchor能统计每个目标数量
YOLO 检测 + 计数高,每个目标一个框中等,工程生态成熟能统计每个目标数量,但小目标漏检率不低

对于“昆虫识别和数目统计”这个题目,如果题目本身没有强调“单张图片里有多只昆虫”,老老实实用分类模型是最稳的。如果题目要求你必须统计单张图中的个体数,那么检测方案逃不掉,这时候你需要获取带 bbox 的公开昆虫数据集——这份资源里的数据体量大概率撑不起目标检测训练。

4. 动手跑通:数据读取、模型训练、数量统计三步走

理论说完了,进入实操环节。这一章我从数据读取开始,完整走一遍训练、推理、统计的流程。所有代码都按“能直接复制运行”的标准写,注释里说明每个参数的含义。

4.1 数据读取:把 CSV 变成 PyTorch Dataset

无论 CSV 列名叫什么,最终都要把它包装成 PyTorch 能识别的 Dataset。这里的关键是不要假设列名,而是动态判断:

import pandas as pd import torch from torch.utils.data import Dataset from PIL import Image import os class InsectDataset(Dataset): def __init__(self, csv_path, img_root, transform=None): self.df = pd.read_csv(csv_path) self.img_root = img_root self.transform = transform # 动态推断列名:优先找 image_path / file,否则取第一列 if 'image_path' in self.df.columns: self.img_col = 'image_path' elif 'filename' in self.df.columns: self.img_col = 'filename' else: self.img_col = self.df.columns[0] # 标签列同理,优先 label,否则取第二列 self.label_col = 'label' if 'label' in self.df.columns else self.df.columns[1] def __len__(self): return len(self.df) def __getitem__(self, idx): img_name = self.df.iloc[idx][self.img_col] label = int(self.df.iloc[idx][self.label_col]) img_path = os.path.join(self.img_root, img_name) img = Image.open(img_path).convert("RGB") if self.transform: img = self.transform(img) return img, label

这段代码的逻辑说明:__getitem__根据索引读图片并返回图像张量和标签;列名推断写在__init__里,避免因 CSV 列名不一致导致程序报 KeyError。

参数方面,img_root是图片所在根目录,如果 CSV 里存的是相对路径,就必须和根目录拼接;label强制转成 int,因为 CSV 读进来的分类标签可能是字符串,模型输出要求整数索引。transform在训练和测试时通常不一样,训练要用随机裁剪和翻转来增强,测试只用缩放和归一化。

4.2 训练配置:epoch、batch、learning rate 的合理区间

拿到 Dataset 之后,划分训练集和验证集,再定义数据加载器和训练超参数。这个环节最容易被忽略的是验证集的划分方式,一旦出现数据泄漏,数量统计的结果会虚高。

from torch.utils.data import DataLoader, random_split import torchvision.transforms as T # 训练时做增强,测试时只做缩放归一化 train_transform = T.Compose([ T.Resize((256, 256)), T.RandomCrop(224), T.RandomHorizontalFlip(), T.ToTensor(), T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 加载全量数据,再按 8:2 划分 full_dataset = InsectDataset("data.csv", img_root="images", transform=train_transform) train_len = int(len(full_dataset) * 0.8) val_len = len(full_dataset) - train_len train_ds, val_ds = random_split(full_dataset, [train_len, val_len]) train_loader = DataLoader(train_ds, batch_size=32, shuffle=True, num_workers=4) val_loader = DataLoader(val_ds, batch_size=32, shuffle=False, num_workers=4)

这里的参数含义:

  • Resize((256, 256))+RandomCrop(224):先放大再随机裁剪,相当于做了一定程度的尺度扰动,能提升模型对昆虫在画面中大小不一致的鲁棒性。
  • RandomHorizontalFlip():对昆虫图像有效的增强,因为昆虫左右翻转仍然是可信样本。
  • Normalize(mean=[0.485, ...], std=[0.229, ...]):ImageNet 统计出的均值和方差,使用预训练模型时必须沿用这组数值,不能随意改。
  • batch_size=32:在显存足够的 GPU 上一般不会爆,如果你的显卡只有 4GB 显存,降到 16 或者 8。这个参数直接影响梯度下降的平滑度,batch 太小收敛慢,太大容易卡在尖锐的局部最优。

训练循环不写了,直接跳到一个好的做法:验证集准确率卡片如何做,这会更实用。

以下是训练循环的标准骨架,用交叉熵损失和 Adam 优化器:

import torch.nn as nn device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = model.to(device) criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=1e-4) epochs = 20 best_acc = 0.0 for epoch in range(epochs): 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() # 每个 epoch 后跑一次验证集 model.eval() correct, total = 0, 0 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) correct += (preds == labels).sum().item() total += labels.size(0) val_acc = correct / total print(f"Epoch {epoch+1}/{epochs}, Loss: {running_loss/len(train_loader):.4f}, Val Acc: {val_acc:.4f}") if val_acc > best_acc: best_acc = val_acc torch.save(model.state_dict(), "best_insect_model.pth")

提一句:torch.save只存state_dict而不存整个模型,这是为了换机器部署时更灵活,也避免了 PyTorch 版本不一致导致的加载失败。

4.3 推理与数量统计:写一个从图片到统计结果的完整脚本

训练完成拿到权重后,要做的事是对测试图片做推理,并把结果汇总成数量。这里要注意:测试集的图片路径可能没有 CSV,或者 CSV 只在 datatest.csv 里,所以代码要兼容两种输入方式。

import torch import torchvision.transforms as T from collections import Counter from PIL import Image import glob # 测试变换不需要增强 test_transform = T.Compose([ T.Resize((224, 224)), T.ToTensor(), T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 加载模型和权重 model = models.resnet18(weights=None) model.fc = torch.nn.Linear(512, num_classes) model.load_state_dict(torch.load("best_insect_model.pth", map_location="cpu")) model.eval() # 找所有测试图片 test_images = sorted(glob.glob("images/test/*.jpg")) class_names = ["fly", "butterfly", "bee", "beetle", "ant"] # 按自己的类别名修改 # 逐张预测并统计 counter = Counter() with torch.no_grad(): for img_path in test_images: img = Image.open(img_path).convert("RGB") inputs = test_transform(img).unsqueeze(0) logits = model(inputs) pred_idx = logits.argmax(dim=1).item() counter[class_names[pred_idx]] += 1 print(f"{img_path} -> {class_names[pred_idx]} (conf={torch.softmax(logits, dim=1).max().item():.2f})") print("数量统计结果:", dict(counter))

这段代码有几个必须按需调整的地方:

  • model = models.resnet18(weights=None)后面必须接load_state_dict,因为如果你在这里用weights=DEFAULT,再加载自己的权重文件,会遇到预训练权重被覆盖的警告,虽然不影响最终结果,但会浪费一次预训练权重的下载时间。
  • class_names的顺序必须和训练时 CSV 里标签的编码顺序一致,否则预测结果对不上号。如果你不确定顺序,可以打印model.class_to_idx,但没有的话,就需要从 data.csv 里按sorted(set(labels))生成。
  • unsqueeze(0)把单张图变成 batch 维度为 1 的四维张量,这一步漏掉会直接报维度错误。

Counter在统计时天然对缺失类别返回 0,不会抛 KeyError。我一般会在统计完成后写一个汇总表到本地,方便答辩时直接贴到论文附录。

4.4 评估模型:看混淆矩阵,找出模型到底错在哪

准确率只告诉你好不好,不告诉你怎么改进。量化评估需要用 sklearn 生成混淆矩阵并可视化,这是答辩时的加分项。

from sklearn.metrics import confusion_matrix, classification_report import numpy as np all_preds, all_labels = [], [] model.eval() with torch.no_grad(): for images, labels in val_loader: images = images.to(device) outputs = model(images) _, preds = torch.max(outputs, 1) all_preds.extend(preds.cpu().numpy()) all_labels.extend(labels.cpu().numpy()) cm = confusion_matrix(all_labels, all_preds) print("混淆矩阵:\n", cm) print(classification_report(all_labels, all_preds, target_names=class_names))

classification_report输出的 precision、recall、f1-score 比准确率更能反映模型在每类上的真实表现。如果某一类的 recall 明显偏低,说明模型倾向于把它误判成其他类,这时候需要在训练时给这个类更高的权重。把混淆矩阵保存成图片,答辩时放在 PPT 上,比单纯说“准确率 95%”有说服力得多。

5. 避坑清单:复现这套毕设最常见的五个翻车点

这种毕业设计资源我前后复现过几套,翻车点高度集中。这里挑五个现象最典型、原因最隐蔽、解决方式最明确的写下来,都是血泪经验。

5.1 坑:CSV 中文路径乱码

现象Image.open()报 FileNotFoundError,但手动打开路径明明存在。

原因:CSV 是 UTF-8 编码,Excel 打开再保存后变成了 GBK 编码,路径里的中文文件名在程序里读出来是乱码。

解决:统一你代码的编码格式。读取 CSV 时显式指定编码:

df = pd.read_csv("data.csv", encoding="utf-8")

如果这样还报错,大概率文件已经是 GBK,改成encoding="gbk"再试。最稳的做法是用chardet探测文件编码:

import chardet with open("data.csv", "rb") as f: raw = f.read() encoding = chardet.detect(raw)["encoding"] df = pd.read_csv("data.csv", encoding=encoding)

但终极方案是直接把所有图片名和标签改成英文,用脚本重命名一次,以后再也不碰编码问题。

5.2 坑:zip 伪加密导致解压失败

现象:Windows 下用右键“全部解压缩”能打开部分文件,但 Linux 下unzip报 “unsupported compression method” 或者“加密文件”。

原因:不少从网盘下载的 zip 包被二次打包,添加了伪加密标志位。右键解压时 Windows 的 Zipfldr 会自动忽略伪加密,但 Linux 的 unzip 会把它当成真加密拒绝解压。

解决:优先用 7-Zip 处理。7-Zip 能识别伪加密,解压时加-p参数传入空密码:

7z x insect.zip -p

如果 7-Zip 也解不开,试试 Python 的zipfile模块,它有时能绕过伪加密:

import zipfile with zipfile.ZipFile("insect.zip") as zf: zf.extractall("insect_project")

还有一种情况是 zip 压缩包损坏,导致某个文件缺失。unzip -t insect.zip可以测试压缩包完整性,如果输出里有 “missing entry” 之类的报错,就该重新下载资源了。

5.3 坑:预训练权重下载超时,训练卡死在下载阶段

现象:代码跑到models.resnet18(weights=models.ResNet18_Weights.DEFAULT)时长时间卡住,最后报 timeout。

原因:torchvision 的权重托管在 download.pytorch.org,国内网络访问不稳定,几 MB 的权重文件经常断流。

解决:手动下载权重文件,放到本地目录,再通过torch.hub.load_state_dict_from_url加载时指定model_dir

torch.hub.set_dir("./pretrained_weights") model = models.resnet18(weights=None) state_dict = torch.hub.load_state_dict_from_url( "https://download.pytorch.org/models/resnet18-f37072fd.pth", model_dir="./pretrained_weights" ) model.load_state_dict(state_dict)

或者更干脆,让项目支持无预训练训练。对于数据量超过 2 万张的昆虫图集,不加载预训练权重也能收敛到不错的效果,只是训练时间翻几倍。毕设场景里我不建议等太久,预训练是值得的。

5.4 坑:数量统计时重复统计或漏统计

现象:测试集总共 50 张图,统计完数量之和是 62,明显不对。

原因glob.glob("images/test/*.jpg")把重复图片路径扫进来了,或者 CSV 里的测试图片和 glob 到的图片有大量重叠,统计时两个来源都算了一遍。

解决:统计之前先对图片路径去重,并且统一数据来源。用 datatest.csv 做输入,就不要再用 glob 扫目录,反之亦然:

test_df = pd.read_csv("datatest.csv") unique_paths = sorted(set(test_df["image_path"])) print(f"去重后测试样本数:{len(unique_paths)}")

这个 bug 特别隐蔽,因为它不报错,只是数字偏大,答辩时老师随口问一句“你统计的是个体数还是图片数”,你如果没注意过数据来源,很容易答错。所以统计口径必须写死在代码注释里,别靠记性。

5.5 坑:类别极度不平衡,模型把所有样本判成同一类

现象:训练 loss 正常下降,验证准确率高达 90% 以上,但看混淆矩阵发现模型只学会了预测数量最多的那一类,其他类全是 0。

原因:data.csv 里某类样本占比超过 80%,模型发现全预测成这一类的损失最小,不需要学任何特征。

解决:给 CrossEntropyLoss 传入类别权重,让小样本类有更大的惩罚权重:

weights = torch.tensor([1.0, 3.0, 5.0, 2.0, 4.0]) # 按各类样本量的倒数归一化 criterion = nn.CrossEntropyLoss(weight=weights.to(device))

类别的准确计算方式是num_samples / (num_classes * class_counts),比如某个类只有 300 个样本、总数 2400 个、类别数 5 个,那这个类的权重就是2400 / (5 * 300) = 1.6。写的时候直接按 sample_count 的倒数算,省心一些。

6. 答辩前的验证技巧:用置信度阈值回放让数量统计可解释

模型训练完成、数量统计也跑出来了,但查不了准确率时的“黑匣子”感就来了。答辩时老师会问“你判断哪张图是哪一类,依据是什么?”如果你只能回答“模型是这么预测的”,这个答案说服力不足。我的做法是给推理脚本加一个置信度阈值回放机制。

思路是这样的:模型对每张测试图都会输出一个概率分布,如果最高置信度低于某个阈值,说明模型自己也不太确定。那么设置两个阈值——高分区间和低分区间,高分区间直接采信,低分区间把图片原图输出到单独文件夹,对着文件夹人工核对一遍。

import shutil from pathlib import Path confidence_threshold = 0.85 # 置信度低于这个值的图片需要人工复核 low_conf_dir = Path("low_conf_review") low_conf_dir.mkdir(exist_ok=True) with torch.no_grad(): for img_path in test_images: img = Image.open(img_path).convert("RGB") inputs = test_transform(img).unsqueeze(0) logits = model(inputs) probs = torch.softmax(logits, dim=1) conf, pred = probs.max(dim=1) pred_idx = pred.item() if conf.item() < confidence_threshold: shutil.copy(img_path, low_conf_dir / Path(img_path).name) print(f"低置信样本: {img_path}, 预测={class_names[pred_idx]}, conf={conf.item():.3f}")

这个脚本的价值在于,它把模型的不确定性与统计结果绑定在一起。当你汇报“识别准确率 91%”时,可以同时说“这 91% 建立在置信度大于 0.85 的基础上,低置信样本已经单独挑出人工复核”。这比拿一个不设阈值的总分去描述更诚实,也更有工程味道。

有了这些低置信样本之后,可以做两件事保证数量统计的可靠:一是人工核对并修正 label,二是在论文里说明这个阈值的选择依据,比如对不同置信度区间画一条准确率曲线,选在“准确率开始大幅下降前”的位置。这个操作我一般会顺手画个小图,几行 matplotlib 代码搞定:

import matplotlib.pyplot as plt thresholds = [0.5, 0.6, 0.7, 0.8, 0.9, 0.95] accs = [] # 每次在验证集上计算:只统计置信度大于阈值的样本,看准确率 for t in thresholds: acc = compute_accuracy_with_threshold(val_loader, t) accs.append(acc) plt.plot(thresholds, accs, marker="o") plt.xlabel("confidence threshold") plt.ylabel("accuracy") plt.savefig("threshold_curve.png", dpi=150)

从那次之后,我每次做昆虫识别相关的毕设辅助,都会在推理脚本里强制走一遍置信度回放,不再直接信任模型的原始输出。这个习惯救了我好几次——数据标注错误、类别混淆、模型欠拟合,都会通过低置信样本暴露出来。希望这一套流程对你也同样管用,祝你顺利跑通。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 0:01:00

Flutter数值映射库num_remap在鸿蒙开发中的应用与优化

1. Flutter 三方库 num_remap 鸿蒙适配实战指南在 OpenHarmony 生态中开发动态交互应用时&#xff0c;数值范围映射是个高频需求场景。无论是处理传感器数据、手势操作还是动画效果&#xff0c;都需要将原始数据转换为适合 UI 展示的数值范围。传统的手写映射代码不仅冗长难维护…

作者头像 李华
网站建设 2026/9/23 23:58:34

Python毕业设计评价系统:Flask+SQLite教学质量管理实战

简介&#xff1a;本资源是一套基于Python开发的毕业设计教学质量评价系统完整源码与数据库实现&#xff0c;面向高校教务管理人员、计算机专业毕业设计指导教师及本科毕设项目开发者&#xff0c;旨在解决毕业设计过程中的多角色协同评价、成绩量化分析与教学质量管理难题。压缩…

作者头像 李华
网站建设 2026/9/23 23:54:04

YOLO智慧工地安全检测:7538张图像数据集训练全攻略

简介&#xff1a;这是一套面向智慧工地安全监测场景的YOLO算法数据集&#xff0c;适用于计算机视觉开发者、算法工程师以及施工现场安全管理人员。资源对应7538张真实工地图像&#xff0c;对安全帽、反光衣、头盔、背心、靴子五类安全装备进行了详细标注&#xff0c;图像覆盖不…

作者头像 李华
网站建设 2026/9/23 23:49:12

基于深度学习的量化投资策略:从数据管道到实盘部署的工程实践

简介&#xff1a;这份资源是面向高校学生与量化投资初学者的深度学习实战项目包&#xff0c;适用于毕业设计、期末大作业或人工智能与金融科技交叉方向的课程实践。项目围绕量化投资策略的完整开发流程展开&#xff0c;涵盖数据预处理、模型构建、训练调优以及回测评估等关键环…

作者头像 李华