Bird Presence Classifier

Bird / no-bird classification plan · 2026-07-22

不做框,也能做得像样:YOLO26n 有鸟 / 无鸟分类方案

如果唯一输出是“这张照片有没有鸟”,可以直接使用 YOLO26n-cls 两类分类头,不训练 Detect 或 Pose。真正决定效果的不是把 head 改成多简单,而是保留整张照片、补足小鸟尺度、用现成昆虫/飞行物困难负样本,并把 100 张七月人工标签作为第二阶段本地域适配与回归集。

输出:bird probability + yes/no模型:YOLO26n-cls / 2 classes设备:Apple M5 / 32 GB数据:不新增图片数据集
1.53M本机实例化的两类 YOLO26n-cls 训练参数
15,731阶段 A 唯一训练图:9,231 有鸟 + 6,500 无鸟
36.9%COCO train 中最大鸟框仍小于整图 1% 的图片比例
1–5 hM5 阶段 A 初始训练窗;须以 1 epoch 校准替换
Executive decision

可以做,而且应当先做成“多视图分类器”

单次整图分类对大鸟很合适,对远小鸟天然吃亏。推荐保留极小的 YOLO26n-cls 主干,但把训练与推理都改成全图保真、多尺度视图和困难负样本驱动。

01

推荐主线:两阶段 YOLO26n-cls + 全图 / tile 双模式

阶段 A用 CUB train、COCO bird train 和 6,500 张通用困难负样本建立“鸟的视觉概念”;阶段 B用 60 张七月 train 图按每轮约 25% 权重做本地域适配,同时保留 75% 通用 replay。部署时提供 384 全图快速模式,以及“全图不够肯定才运行 2×2 tiles”的高召回模式。

训练期可以使用现成 bbox 保证 tile 里真的含鸟,但 bbox 不作为模型输出、不进入部署接口。最终只返回 p_birdis_bird、阈值版本与推理模式。

不改网络主干

加载官方 ImageNet 预训练 yolo26n-cls.pt,将最后分类 head 替换成 2 类即可。两类 softmax 已足够;改成单 logit BCE 不会解决小鸟、域偏移或误报问题。

不误用 Detect 权重

当前本机发现的是 yolo26n.pt Detect,而不是 yolo26n-cls.pt。正式实现需一次性获取正确的 n-cls checkpoint;从 Detect 权重硬转分类不是首选初始化。

Positive

CUB + COCO bird

CUB 教“大而清楚的鸟形”,COCO 教复杂场景和远小鸟。

Negative

8,491 困难无鸟图

蝴蝶/昆虫、飞机/风筝、动物和自然环境人物,按来源分层。

Fine-tuning

YOLO26n-cls · bird / no_bird

完整画面 letterbox;训练期 bbox-aware tile;两阶段 sampler。

Output

一张图一个判断

全图或全图+tiles 聚合,仍然不返回框与坐标。

最重要的边界:

分类器回答“画面整体像不像含鸟”,没有实例级监督。多鸟、半只鸟和远小鸟都能训练,但模型无法说明鸟在哪里;如果未来对焦评分、关键点、鸟种裁切仍要继续,就必须另加定位模块。若当前工作流只做第一轮“有鸟照片筛选”,分类器是合理且更便宜的选择。

官方模型/格式本机数据审计条件化时间估算能力边界
01 · Model choice

正确模型名是 YOLO26n-cls,不是 YOLO26n Detect

两者共享品牌和部分设计语言,但 checkpoint、head、预训练数据与输出契约不同。这个方案只保留分类任务,不让检测 head 白白消耗训练与部署复杂度。

模型预训练输出规模口径本项目判断
YOLO26n-cls.ptImageNet整图类别概率官方融合模型约 2.8M 参数、0.5B FLOPs@224;本机两类训练结构 1,533,666 参数推荐 直接替换 1000 类 head 为 bird/no_bird。
YOLO26n.ptCOCO Detect框、类别、置信度本机已有,但包含检测 head不用 与“不需要框”的目标不匹配。
YOLO26s-cls.ptImageNet整图类别概率两类训练结构 5,445,570 参数;旧 PoC 已跑对照 保留旧成绩,不作为新版默认。
单 logit 自定义 BCE视初始化而定一个 sigmoid仅减少极小的最后层没必要 破坏现成 trainer/export 兼容,收益几乎不可见。

类别顺序要冻结

torchvision ImageFolder 按字母排序时,bird 通常为 0、no_bird 为 1。训练、推理与报告都必须从 checkpoint 的 names 读取,不能在代码里凭记忆写死索引。

384 是首个平衡点

官方分类 checkpoint 以 224 为常见口径;本项目有大量小鸟,建议首跑 384。YOLO26n 的近似 FLOPs 随面积增长,384 相对 224 约 2.94×,仍远小于检测/姿态方案。

模型小不等于任务简单

两类 head 只有 bird/no_bird,但“无鸟”包含无限外观,“有鸟”还包含不同尺寸、遮挡和模糊。主要工程成本在数据采样、预处理与阈值,而不是最后一层。

02 · Current labeled assets

现有数据足够做 v2,但四组数据职责不同

不要把所有“有鸟图”看成同一种正样本。CUB 与 COCO 的鸟尺寸分布几乎相反;七月 100 张图虽然小,却是唯一直接贴近实际摄影流程的人工标签。

数据源当前规模已有标签最适合教什么主要风险
CUB-200-201111,788 图;train 5,994 / test 5,794每图有鸟、bbox、15 点、物种稳定鸟体外观、视角、羽色;大主体正样本单鸟、居中、主体大;背景分布与本地不一致。
COCO birdtrain 3,237 图 / 10,542 非 crowd 框;val 125 图 / 427 框图中有鸟及 bbox复杂场景、多鸟、远小鸟与自然/城市背景鸟类定义粗;部分鸟像素极少,默认随机 crop 会裁没。
困难负样本 v18,491 图;约 2.4 GB确认无鸟、来源/类别/hash蝴蝶、蜻蜓、飞机、风筝、动物、自然环境人物不是本地相机分布;仍需抽查隐蔽鸟和来源许可。
七月 100 图train 60 / val 20 / test 20;每个 split 平衡人工 bird/no_bird;日期隔离本地相机、镜头、曝光和实际误报纹理test 已在早期看过;每类仅 10 张,一个错误就是 10%。

鸟在画面里到底有多大

本机逐图 bbox 面积审计

CUB:鸟通常很大

p10 面积
14.1%
p25 面积
21.1%
中位数
32.2%
p75 面积
45.8%

以上为 CUB train 的鸟框面积 / 整图面积。仅用 CUB 会诱导“主体大、居中才是鸟”的捷径。

COCO:大量鸟非常小

p10 最大鸟框
0.059%
p25 最大鸟框
0.323%
中位数
2.71%
p75 最大鸟框
14.3%

1,195/3,237 图的最大鸟框 <1%,1,871/3,237 图 <5%。这正是全图分类器最难、但最有价值的正样本。

一个容易被忽略的标签噪声:

Ultralytics 默认分类训练使用 RandomResizedCrop,验证/推理使用 CenterCrop。对“鸟在角落”或“鸟只占 0.1%”的图,crop 可能把鸟完全裁掉,却仍保留 bird 标签;模型会被迫把纯背景学成 bird。官方文档也明确提示极端长宽比可能丢失关键区域。这个项目必须改成保留全图的 letterbox/resize-pad,或先生成已正确转正和填充的方形代理图。

03 · Split & sampling

先按来源隔离,再在每个 epoch 内重新配比

物理 split 决定数据泄漏;sampler 决定模型每轮实际看见什么。二者不能混为一谈,也不要通过随意复制文件把验证图混进训练。

用途有鸟无鸟合计规则
阶段 A train pool5,994 CUB train + 3,237 COCO train = 9,2316,500 困难负样本15,731唯一图片池;负样本按 source/category/hash 分层抽取。
generic val1,000 CUB test(每种 5 张)+ 125 COCO val1,000 困难负样本2,125仅选阈值/模型;不将 tile 当独立样本重复计数。
generic stress剩余 4,794 CUB test剩余 991 困难负样本5,785分别报告正样本 recall 与负样本 FP/1k,不用总体 accuracy 掩盖不平衡。
local train30 七月 bird30 七月 no_bird60只进入阶段 B;同一捕获日期/组不跨 split。
local val101020参与阈值约束;样本太小,只能做报警器。
local regression101020复用旧 PoC test 做纵向比较;不是封存盲测。

阶段 A 每轮采样目标

  • 50% bird / 50% no_bird,避免 0.5 阈值被训练先验随意推歪。
  • bird 内建议 45% CUB、55% COCO,刻意提高复杂场景权重。
  • COCO 最大鸟框 <5% 时,一半抽样返回保证含鸟的 tile,一半返回全图。
  • no_bird 内建议 50% 昆虫/蛛形纲、25% 飞行物、20%其他动物、5%自然人物。

阶段 B 每轮采样目标

  • 25% 七月 local train、75% generic replay。
  • local 和 generic 内各自保持 bird/no_bird 平衡。
  • 每个 epoch 约 6,000 views 即可,不必完整扫 15,731 图。
  • 本地 60 图通过随机色彩、轻微缩放和翻转产生不同视图,但不做大面积随机裁切。
为什么要 replay:

如果阶段 B 只在 60 张七月图上继续训练,YOLO26n 很容易记住具体水面、天空、镜头噪声或拍摄日期,并遗忘 COCO 小鸟与昆虫负样本。25% local + 75% generic 是起点;最终比例应由 generic stress 与新日期本地集共同决定。

04 · Preprocess & views

推理不要框,但训练可以借 bbox 保证“看见鸟”

bbox 在这里是数据工具,而不是模型任务:只用于生成含鸟 crop、按目标面积分片评测,以及确认某个随机增强没有把唯一的鸟裁走。

A

Full view

EXIF 转正,保持长宽比缩放到 384 方形内,以 114 灰色填充;训练时仅允许保留 90%–100% 面积的轻微 crop、水平翻转和有限色彩扰动。

B

Guaranteed-bird tile

从 CUB/COCO bbox 周围取 1.5×–4× context,保证至少 80% 鸟框留在 tile 内。它帮助 head 学到小鸟纹理,但不替代 full view。

C

Negative tile

从确认无鸟图生成与部署 2×2 tile 相似的局部视图。否则推理时放大蝴蝶、树皮或水面高频纹理,会出现训练中没见过的误报。

建议的自定义 transform

规避默认 RandomResizedCrop / CenterCrop 风险
# 概念流程;Notebook 中封装为 FullFrameClassificationDataset
PIL image
  → EXIF transpose
  → RGB
  → aspect-ratio contain
  → centered square padding (RGB 114,114,114)
  → RandomHorizontalFlip(p=0.5)
  → conservative ColorJitter / RandAugment
  → ToTensor + ImageNet normalize
  → NO vertical flip
  → NO default large RandomResizedCrop
  → NO RandomErasing for the first baseline
增强阶段 A 建议原因需要避免
水平翻转p=0.5鸟的左右方向不改变有无鸟标签。无。
垂直翻转0大多数拍鸟姿态不自然。倒置天空/水面带来伪分布。
随机裁切full view 仅保留 90%–100%;tile 单独生成防止小鸟被裁掉但仍标 bird。默认大范围 RandomResizedCrop。
色彩/曝光轻—中等覆盖阴天、逆光、不同白平衡。极端 hue 使羽色和背景失真。
模糊10%–20% 轻度离焦/运动模糊presence 不能只认锐利羽毛。过强模糊把“完全不可辨识”仍标 bird。
Random Erasingbaseline 关闭小鸟本就只有少量像素,擦除可能删掉主体。默认高概率 erasing。
MixUp/CutMix首轮关闭binary presence 的标签混合与最终 yes/no 语义不完全一致。未经校准直接开启。
不想写自定义 Dataset 的简单实现:

先批量生成 768×768 的方形代理 JPEG(EXIF 转正、等比 contain、居中填充),再用标准 ImageFolder,训练设置 scale=0.1auto_augment=Noneerasing=0。它比自定义 transform 多占约 2–6 GB,但更容易用 Notebook 复现。当前约 140 GB 可用磁盘足够,仍应维持 40 GB 安全线。

05 · Training ladder

四步实验梯子,把“模型大小”和“数据改进”拆开

直接把新模型与旧 YOLO26s 的 85% 对比会混淆模型、数据、分辨率和推理方式。建议用同一份七月回归集逐步增加变量,每一步都保留 checkpoint 和预测 CSV。

实验训练内容输入 / 推理回答的问题M5 初始时间窗
N0 · 容量基线只用原 60 张七月 train;复刻旧参数320 full onlyn 与旧 s 在完全相同数据下差多少?< 2 分钟
N1 · Generic阶段 A:15,731 唯一图;每轮约 16K views;20–30 epoch384 fullCUB+COCO+hard negatives 带来多少泛化?约 1–5 小时
N2 · Local adaptN1 best + 25% local / 75% replay;5–8 epoch×6K views384 full60 张本地图能否降低本地误报/漏报且不遗忘?约 15–60 分钟
N3 · Recall mode不重训;在 N2 上增加 2×2 tile 推理并重选阈值384 full + 4 tiles不输出框的前提下,小鸟召回能提升多少、FPR 增加多少?仅评测耗时,约 full 的 3–5×

阶段 A 建议起点

model = YOLO("yolo26n-cls.pt")

model.train(
    data="data/bird_presence_cls",
    trainer=BirdPresenceTrainer,
    device="mps",
    imgsz=384,
    epochs=25,
    batch=32,       # 先 smoke;有压力降为 16
    workers=0,      # Jupyter / macOS 先求稳定
    optimizer="AdamW",
    lr0=3e-4,
    weight_decay=5e-4,
    dropout=0.10,
    scale=0.10,
    fliplr=0.5,
    flipud=0.0,
    auto_augment=None,
    erasing=0.0,
    seed=42,
)

阶段 B 建议起点

load N1 best.pt
sampler:
  local views   = 25%
  generic replay = 75%
  bird/no_bird = 50% / 50%

training:
  imgsz = 384
  epoch_views = 6000
  epochs = 5..8
  lr0 = 5e-5 .. 1e-4
  freeze backbone for first 1..2 epochs
  then unfreeze all
  early stop only on constrained metric
时间校准:

先让 N1 用完整 sampler 跑 1 个 warm-up epoch + 2 个计时 epoch;取后两轮中位数,再用 T ≈ median_epoch × 目标 epochs × 1.15。1–5 小时是容量规划,不是本机已跑出的 YOLO26n 大数据训练时间。旧 YOLO26s 在 60 张、320、9 epoch 的 14.6 秒只能证明 MPS 管线可用,不能直接按图片数线性外推。

模型选择不能只看 val top-1:

用于照片筛选时,漏掉真鸟通常比多送一张无鸟图到人工复核更严重。每轮 checkpoint 应保存逐图概率,并按“达到目标 recall 后,specificity 最大”选择,而不是让总体 accuracy 或类别均衡的 top-1 决定。

06 · No-box inference

两种部署模式,输出仍然只有一行结果

tile 是内部视图,不等于检测框。高召回模式可以在完全不保存坐标、不展示位置的前提下,给远小鸟更多像素。

Fast · 384 full frame

  • 整张图等比 contain + padding,一次分类。
  • 适合大多数主体明显的候选照片和快速预扫。
  • 输出 p_full 与冻结阈值判断。
  • 缺点:COCO 式极小鸟可能被全局池化淹没。

Recall · full + 2×2 overlap tiles

  • 先跑 full;若 p_full 未达到 fast positive 阈值,再跑 4 个带 10%–15% 重叠的 tiles。
  • 最终分数先用 max(p_full, p_tile_1...4)
  • 同一套验证图重新选择 tile 阈值,不能沿用 full 的 0.5。
  • 不输出最高 tile 坐标;仅记录使用了 recall 模式。
# 推荐输出契约
{
  "bird_probability": 0.873,
  "is_bird": true,
  "inference_mode": "full_plus_2x2",
  "threshold": 0.61,
  "threshold_version": "val-2026-07-v1",
  "model_sha256": "..."
}

# 不包含 boxes、keypoints、tile_xy 或物种

为什么用 max

远小鸟通常只进入一个 tile;平均四个 tile 会被三个无鸟 tile 稀释。max 与“任一视图确认有鸟”语义一致,但会放大误报,所以必须单独校准。

为什么要训练负 tile

多看四次相当于增加四次误报机会。若训练只见过完整无鸟图,模型遇到放大的蝴蝶、树皮和水面纹理时会明显更激进。

为什么仍不能等同 Detect

tile 只把搜索空间粗分成四块,不学习实例边界。它提升尺度可见性,但无法给对焦网络或物种识别器提供精确裁切。

07 · Evaluation & thresholds

用 recall、FP/1k 和尺寸分片决定是否值得用

现有 val/test 并不完美,因此报告必须同时给出来源内指标、跨来源 stress、本地日期回归和置信区间,避免一个 85% 或 95% 掩盖小鸟漏检。

评测层必须报告首轮目标(不是当前成绩)作用
generic valRecall、specificity、balanced accuracy、PR-AUC、ROC-AUC、Brier/ECEbird recall ≥98%;specificity ≥95%选 checkpoint 与 full/tile 各自阈值。
COCO 尺寸分片最大鸟框 <0.1%、0.1–1%、1–5%、>5% 的 recall<1% 分片相对 full baseline 明显提升判断 tile 是否真正解决远小鸟,而不是只抬高总体分。
hard-negative stressFP/1k;昆虫、飞行物、动物、人物分别统计总体 ≤30 FP/1k;蝴蝶单列决定 Lightroom 工作量是否可接受。
local val10 bird / 10 no_bird 的逐图概率10/10 bird 保留,再看 specificity作为域偏移报警器,不单独决定上线。
local regression与旧 s-cls 同 20 图;列出 3 个旧失败是否修复不得比旧 90% bird recall / 80% specificity 更差纵向可解释,但因为已看过,不算盲测。
新日期 sealed test至少 500–1,000 张,连拍组隔离keeper recall ≥97%,误删率 ≤2%未来真正上线门槛;当前数据仍缺。

阈值选择规则

0.5 不是自然常数
for threshold in candidate_thresholds:
    require generic_bird_recall >= 0.98
    require local_val_bird_recall == 1.00
    require coco_tiny_recall does not regress
select threshold with maximum generic specificity

# full-only 与 full+tiles 分别执行
# 阈值、模型 hash、预处理和聚合规则一起冻结

旧 PoC 是对照,不是上限

YOLO26s-cls 旧测试为 17/20:bird recall 90%、specificity 80%。两个 false positive 是蝴蝶与水面反光,一个 false negative 是远小鸟,刚好对应新版数据与 tile 设计。

不要把 tile 当独立 test 图

同一原图的 full 和四个 tiles 是相关视图。统计单位永远是原图:先聚合成一条概率,再计算 TP/FP/FN/TN。

保存所有逐图概率

只保存 yes/no 会丢掉重新定阈值的能力。CSV 至少包含 source、split、truth、p_full、p_tile_max、p_final、prediction 和错误类型。

当前无法证明的内容:

现有数据没有系统的“真实失焦/运动模糊 bird”标签,也没有一个从未看过的新日期大型本地 test。因此报告可以规划 blur augmentation 和错误分片,但不能宣称分类器已经能可靠保留所有严重模糊鸟片。下一轮最有价值的新标注不是更多 CUB,而是 300–500 张真实本地困难 bird/no_bird,尤其远小鸟、半鸟、虚焦鸟、蝴蝶、水面和树枝。

08 · Implementation plan

两天跑通,之后用新日期决定是否继续分类路线

先把 N0–N3 做成同一 Notebook 和同一评测脚本;若多视图分类仍无法兼顾 tiny-bird recall 与蝴蝶 FPR,再把问题升级为检测,而不是盲目放大分类器。

Day 1 上午 · manifest 与 split

解析 CUB/COCO bbox、负样本 manifest 和七月标签;写 source/category/hash,建立 15,731 train、2,125 generic val 和 stress 清单;原图只读。

Day 1 下午 · transform / sampler smoke

可视化 32 个 full、positive tile 和 negative tile;断言 bird tile 与 bbox 重叠、train/val hash 零重合;运行 N0 与 N1 1 epoch 校准。

Day 1 晚–Day 2 · N1 / N2

完成 20–30 epoch generic 与 5–8 epoch local replay;保存 best/last、完整配置、环境、逐图预测和 checkpoint hash。

Day 2 · N3 与 HTML 结果报告

在完全相同的 val/stress/local 图上比较 full 与 full+tiles,冻结两套阈值,列出错误接触表和每类 FP/1k。

下一轮 · 新日期封存集

从未参与训练/挑样的新日期建立 500–1,000 图组隔离 test;只在结果冻结后打开。未达到 keeper recall 时优先加本地困难真值。

项目目录与 Notebook 单元

面向可复现与初学者阅读

建议目录

experiments/yolo26n_bird_presence/
├── README.md
├── configs/
├── notebooks/
│   ├── 01_build_and_train.ipynb
│   └── 01_build_and_train.executed.ipynb
├── scripts/
│   ├── build_manifest.py
│   ├── bird_presence_dataset.py
│   ├── train_n0_n2.py
│   ├── evaluate_multiview.py
│   └── make_html_report.py
├── data/
│   ├── bird_presence_cls/
│   │   ├── train/{bird,no_bird}/
│   │   ├── val/{bird,no_bird}/
│   │   └── test/{bird,no_bird}/
│   ├── manifest.csv
│   └── split_policy.json
├── runs/{n0,n1,n2}
└── artifacts/{metrics,predictions,contacts,...}

Notebook 必须解释

  1. 为什么选 n-cls 而不是 n Detect。
  2. 四个数据源各自解决什么问题。
  3. 默认 crop 为什么会制造错误标签。
  4. bbox 只如何用于训练 tile。
  5. N0–N3 每次只改变哪个变量。
  6. 如何从 val 选择阈值。
  7. 为什么 20 张本地 test 不能代表生产。
  8. 如何重载 best.pt 并输出一行 JSON。
最终观察解释下一步
full 已满足 recall/FPR主体普遍够大,最简方案成立部署 384 full;tiles 只保留为疑难复核工具。
tiles 显著提 tiny recall,FPR 可控主要瓶颈是像素尺度部署两级 cascade,不需要检测框。
tiles 提 recall 但蝴蝶 FPR 爆炸局部形状歧义是主要瓶颈继续挖真实 hard negatives;比较二阶段“鸟候选”验证器。
CUB/COCO 好、本地差域偏移而非容量不足新增本地标注和 replay,不先换 yolo26s/m。
新日期仍漏远小鸟整图分类信息瓶颈已到上限转单类 Detect;分类器保留为快速预筛,不继续堆大模型。
未来需要对焦/物种裁切下游需要坐标分类器不能替代定位;另接 Detect/Pose。
建议立即执行的版本:

先实现 N0、N1 与 full-only 验收;确认 transform 没裁掉鸟、N1 在 COCO tiny 分片有可用 recall 后,再做阶段 B 和 tiles。这样最早半天就能知道 n-cls 是否有学习能力,最迟 1–2 天得到一个可以与旧 s-cls 公平讨论的 v2 结果。

独立范围与去重:

线上已有“100 张 YOLO26s 鸟/非鸟 PoC 复盘”,它记录旧模型、旧数据和实际 85% 结果。本报告不是重写旧结论,而是利用后来下载完成的 CUB、COCO bird 和 8,491 张困难负样本,给出 YOLO26n、无框、多视图、两阶段微调的正式实现基线,因此保留为独立方案。

Sources & evidence

官方能力、本机事实与项目目标分开

模型参数、预训练和默认 crop 依据官方文档/本机源码;数据规模与分布来自本机逐图审计;时间和指标门槛均标为估算或目标。

本机审计范围

读取了 CUB 官方 train/test 与 bbox,COCO bird train/val annotations 和图像目录,8,491 张负样本的来源、类别、尺寸与 hash,100 张七月人工标签的日期拆分、旧 YOLO26s-cls 权重/训练参数/逐图结果,以及本机 Ultralytics 8.4.100 的 ClassificationDataset、RandomResizedCrop、CenterCrop 和两类 YOLO26n-cls 实例化参数。公开报告不包含私人照片路径、设备序列号、凭据或可还原私人图库的信息。

许可提示:

Ultralytics、CUB、COCO、Open Images 和 iNaturalist 各有独立许可与图片条款。本地研发可先验证技术;分发训练集、衍生权重或商业部署前,应按当期条款重新核对。本报告不构成法律意见。