
做过垃圾分类识别项目的人应该都有体会真正难的往往不是把模型跑通而是让它在小区楼下那种光照乱、遮挡多、垃圾袋五花八门的环境里还能稳定工作。这篇文章记录的是一个基于深度学习目标检测的垃圾图像识别项目核心模型选了 YOLOv8并且在原版基础上做了几处针对性改进。内容会覆盖数据集怎么搭、YOLOv8 的改进点怎么选、训练参数到底是什么意思、模型怎么落地成一套能用的识别服务。适合正在做相关课题、参加竞赛、或者想把垃圾分类功能集成到智能硬件里的朋友参考我会尽量把“为什么这么做”也讲明白。1. 项目整体设计与需求拆解1.1 先想清楚你要做的是“识别”还是“交互”垃圾分类识别这种需求不同场景的差别可以非常大。我这次定位的是智能回收箱/智能垃圾桶摄像头对着投放口或者桶内识别人投放的垃圾属于可回收、厨余、有害还是其他然后联动对应箱门打开或者通过屏幕语音提示用户“请投放至对应箱门”。这个场景有几个特点。第一强调实时性。用户手举着垃圾站在桶前面识别不能让人等 2 秒模型单帧推理时间要控制在 50ms 内比较稳妥设备上屏幕才会有“即投即识别”的感觉。第二环境不可控。小区垃圾投放点白天强光、晚上偏暗有些地方摄像头正对投放口有些是斜视角度垃圾袋还可能部分遮住里面的物体。这些扰动必须在数据层面就模拟进去模型才能扛得住。第三分类体系不能拍脑袋。我们用的是国内通用的“四分类”标准可回收物、厨余垃圾、有害垃圾、其他垃圾。这里要特别注意可回收里的金属罐和有害电池容易混厨余里面的果皮和餐巾纸也经常被一起丢类别边界必须写死不然标注员和模型都会迷糊。1.2 为什么选 YOLOv8 而不是其他检测框架现在目标检测算法选择不少Faster R-CNN 也有、YOLOv5 也有人用这两年 Transformer 检测器和开放词汇检测也火。但在这个项目里我把最终方案锁在 YOLOv8 上理由很现实。一是实时性和精度的平衡。Faster R-CNN 这类两阶段检测器精度确实能打但部署到边缘设备做实时推理太吃力YOLOv8 是单阶段的起步就能跑到几十帧配上端侧 NPU 能直接起飞。二是生态成熟。Ultralytics 官方库把训练、验证、导出 ONNX/NCNN/TensorRT 的链路做得非常顺社区资料多跑 YOLOv8 训练自己的数据集这种需求网上有大量参考遇到问题排查成本低。三是改进空间明确。YOLOv8 的 C2f 结构、解耦头、无锚框设计都留有很清晰的优化入口很适合作为“研究的设计与实现”这类项目的基线模型。给个直观对比我当时做的候选方案评估方案mAP50 基线自建垃圾数据集单帧推理耗时边缘设备结论YOLOv5s87.2%38ms备用方案YOLOv8s89.1%40ms最终基线Faster R-CNN ResNet5090.3%210ms放弃实时RT-DETR88.6%52ms备选表格里的数据是内部测试记录不同数据集会浮动但趋势很清楚YOLOv8s 在当前需求和算力条件下综合最划算。1.3 系统架构分几层整套系统我按四层拆解数据层、模型层、服务层、应用层。数据层负责采集图片、清洗、标注、增强最终产出训练集和验证集模型层就是 YOLOv8 的训练、改进选型、评估和导出服务层把模型封装成 HTTP 接口或嵌入式推理程序应用层是前端 UI、语音提示、闸机电机联动等。我把“能跑通模型”和“能用起来”当成两个验收节点前一个节点验证精度后一个节点验证整体可用性。项目初期就定了这个拆法后面每阶段的目标都很清楚。2. 数据集构建模型上线表现的一半取决于这里2.1 数据从哪来公开数据 自采垃圾识别这类项目最尴尬的就是缺少高质量开源数据集。我调研过几个公开数据集比如华为云垃圾分类数据集、TrashNet、还有一些 GitHub 上的垃圾图片项目。这些数据集量大但有两个明显问题类别体系非常不统一有的数据集把“塑料瓶”当成单一类别有的又把“可回收”作为一个大类直接混用会导致标签语义错乱。我的做法是以自采数据为主、公开数据为辅。用手机和现场摄像头拍了一周的真实投放场景覆盖几个不同小区的垃圾房、智能箱试点点位。同时利用公开数据集里图像质量好的单类图片通过裁剪、抠图、贴入真实背景的方式扩充样本相当于人工造了一批“合理场景”。最终整理出 1.6 万张有效图片其中自采约 1.1 万张公开数据改造约 0.5 万张。2.2 类别体系的坑别把“物”和“类”混为一谈四分类标准下模型到底输出什么类别很多人第一反应是输出“可回收垃圾、厨余垃圾”这四个大类这其实是个大坑。我们用深度学习的逻辑想一下模型是通过图像特征识别具体物体的塑料瓶和铁皮罐虽然都被归为可回收但它们的形状、纹理、反光度完全不同如果把这两种差异巨大的物体硬绑在一个类里模型内部特征空间会非常混乱。反过来四大类之外的东西比如牙刷、鞋、纸尿裤到底算什么我实际采用的方案是“底层的具体物品类别 上层的四分类映射”。模型先识别塑料瓶、易拉罐、硬纸盒、玻璃瓶、果皮、菜叶、剩饭、废电池、药瓶、烟蒂、纸巾等 20 类具体物品到了应用层再根据映射规则把识别结果归到可回收、厨余、有害、其他四类。这样模型在每个类别上的特征更集中准确率明显更好。2.3 标注规范一件事定下整个项目上限标注质量直接影响检测效果。我踩过一次标完 3000 张图才发现边界框偏大导致模型定位偏移、mAP 一直卡着不动的教训。这个项目的标注规则定得很死边界框要贴合物体的实际可见区域不包含明显背景严重遮挡、模糊到认不出的物体不标注不硬标同一物体出现在画面里多个角度时每个有效实例都要标标完一轮后必须有人抽检抽检率不低于 15%。工具用的是 LabelImg 和 X-AnyLabeling。X-AnyLabeling 带自动化预标注能力先让现有模型预标注人工再改一遍标注效率能提升两倍以上。队里两个标注同学一天能完成约 500 张图的精标整体进度可控。2.4 数据增强不只是扩充数量是模拟真实世界真实投放场景的光线和角度比多数人想象得复杂。所以我在训练时用了几组针对性增强Mosaic 四图拼接把 4 张图随机裁剪拼接再缩放相当于用小显存合成丰富背景对小物体尤其友好HSV 调整模拟早中晚不同色温、灯光颜色变化随机翻转、旋转、仿射模拟相机安装角度偏差一定概率加入 8% 的高斯噪声模拟低照度摄像头画面。这里有个 trick训练最后 10 个 epoch 关掉 Mosaic。这是我实际体会很深的一点Mosaic 拼出来的图风格和真实场景差异不小一直开着会导致最后阶段模型在真实数据上的分布适应不足损失曲线能看出来波动变大但 mAP 不见涨。2.5 类别不均衡少数类要“手工扶一把”垃圾数据天然失衡瓶子和纸盒特别多废电池、药瓶、烟蒂特别少。我用三类方法处理对少数类过采样复制样本并做轻微增强变换对多数类降采样同类图片在数据加载时按概率跳过避免一个 batch 全是瓶子给少数类设定更高的 Loss 权重在 YOLOv8 的损失计算环节按类别乘系数比如废电池、烟蒂权重设置为 1.5 左右。个人体感类别不均衡问题里数据过采样是最立竿见影的模型对少数类的召回率能提升 5 到 10 个百分点而单纯调 Loss 权重容易出现边界框回归不稳定。3. YOLOv8 网络结构拆解与三项改进实践3.1 先看懂 YOLOv8 网络结构图再谈改进YOLOv8 可以按三段理解。Backbone 部分保留 Darknet 风格核心是 CSPDarknet C2f 模块C2f 的“多分支梯度流”设计让梯度传输更丰富末尾接 SPPF把不同尺度的特征池化并拼接扩大感受野。Neck 部分是 PAN-FPN自顶向下把高层语义传给底层再自底向上回传定位细节把多尺度特征充分融合。Head 部分从 YOLOv5 的耦合头改成了 anchor-free 解耦头分类分支和回归分支分离不再需要预设锚框推理速度更快收敛也更稳。看结构图时重点盯三个接口位置Backbone 输出三个尺度特征图的位置、Neck 中上下采样连接的节点、Head 分类尺度数量的定义。改进方案几乎都落在这三个位置。3.2 改进点一注意力机制用在最该用的地方我们测试过 SE、CBAM、协调注意力CoordAtt几种注意力机制。很多网友关心的“yolov8 协调注意力机制”就是 CoordAtt它比 SE 多了位置信息的编码对定位遮挡目标和细微纹理差异更有帮助。最后方案是把 CoordAtt 插在 Backbone 的最后一层输出后面以及在 Neck 上采样前后的 C2f 模块里各加一组 SE。为什么要这样分布因为 Backbone 末端通道数多、语义强让注意力去强调“垃圾主体”特征Neck 融合过程中加入 SE是为了让不同层级的特征融合时互相校准权重。实测这类组合比只在 Backbone 加一个注意力机制效果更稳定。需要强调加注意力机制不是越多越好。有次我在每个 C2f 后面都塞了一个注意力模块模型直接过拟合mAP 反而掉了 2 个点。注意力是“重排优先级”不是“放大信息量”通道数一旦被注意力模块反复压信息冗余就没了小目标反而丢。3.3 改进点二针对小目标的检测头策略生活垃圾里小目标非常多烟蒂、药瓶、废电池都是尺寸很小的物体。原版 YOLOv8 默认三个检测尺度对小目标偏弱我把策略分成两档方案 A给 Neck 增加一个 P2更大分辨率检测层相当于把检测头从三个变成四个让模型在小物体上的定位更细方案 B不动检测头只在训练时启用辅助损失分支把深层的大感受野特征用于辅助监督浅层不增加部署时推理成本。考虑到最终要部署到边缘设备我选了方案 B 为主。效果上mAP50-95 的提升有 2.1 个百分点推理耗时只增加了不到 2ms。这个方案的思路在很多 YOLOv8 head 改进讨论里能看到变体本质就是“训练时多算一点部署时不变”。3.4 改进点三轻量化换高性价比搜“yolov8 改进”的时候经常看到一堆花哨模块但真正到项目里我会优先选带轻量化属性的。测试下来GSConv 替换 C2f 内部部分常规卷积是性价比很高的方案参数量降约 18%推理速度提升约 10%mAP 基本不降。如果全面替换端侧 FPS 会有明显改善但分类精度会有一点损失需要权衡。这个环节的核心观点是改进必须做成消融实验并且以“速度-精度”双维度评价。过了这一关的模块才保留不过关一律回滚。没有人愿意为了点赞数牺牲项目上线体验。4. 训练环境、参数含义与损失曲线解读4.1 环境配置与硬件选型训练环境用 PyTorch Ultralytics。版本锁死很重要我这里用的是 Python 3.9、PyTorch 1.13.1、CUDA 11.7、Ultralytics 8.0.x。不同版本间的部分操作符会影响导出结果锁版本能减少无谓的 workaround。训练硬件一台带 RTX 3090 的服务器承担本轮训练另外也用 GTX 1660Ti 的笔记本跑小验证。1660Ti 6GB 显存实测可以跑 YOLOv8sbatch 设 8 左右imgsz 640虽然慢一点但完全能完成微调任务。如果你只有 1660Ti 这类卡建议直接下载预训练权重做迁移学习别从零训练否则一个 epoch 等半小时。4.2 训练参数逐项说明YOLOv8 训练命令很多参数很多新手是照着默认值跑跑完也不知道调什么。我整理一套实际项目里常用的关键参数model指定模型结构或预训练权重路径用yolov8s.pt属于迁移学习用yolov8s.yaml是从零训练前者收敛快得多data数据集 yaml 路径里面写 train/val 的图片路径和类别字典epochs训练轮数垃圾数据集 100 轮左右收敛小数据集设成 300 但配合早停batch一次迭代的图片数6GB 显存建议 8~16显存不够就只能小 batchimgsz输入分辨率通常 640小目标多可以试 960但耗时和显存都会涨optimizer默认 SGD也可以选 AdamW。用 AdamW 时学习率建议调低到 0.001 附近lr0初始学习率默认 0.01小数据集建议 0.005太大容易梯度爆炸lrf最终学习率占初始学习率的比例默认 0.01支持余弦退火时用momentumSGD 动量默认 0.937一般不改weight_decay权重衰减防过拟合默认 0.0005cos_lr是否用余弦退火学习率策略是就 Trueamp混合精度训练会自动减少显存占用6GB 卡应该开着cache是否把数据缓存到内存默认 False内存足够时开 True 能提升读取速度patience早停连续多少个 epoch 验证指标没提升就停推荐 20~30close_mosaic训练后期关闭 Mosaic 增强的轮数默认 10这是 YOLOv8 默认就有的优化策略device显卡编号0 表示第一张卡多卡用 0,1plots训练结束后生成 loss、PR、混淆矩阵等可视化图默认 True。我实际项目里的一条训练指令是这样yolo detect train modelyolov8s.pt datatrash.yaml \ epochs120 batch16 imgsz640 optimizerSGD \ lr00.005 lrf0.01 cos_lrTrue \ patience20 ampTrue cacheTrue \ projecttrash_train nameyolov8s_coordatt4.3 损失函数看曲线判断什么时候能停训练结束后Ultralytics 会产出results.csv里面有每轮 train_loss、val_loss、precision、mAP 等数据。很多人以为 YOLOv8 没有现成的 loss 曲线图其实直接用 CSV 画就行。import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(results.csv) plt.figure(figsize(10, 5)) plt.plot(df[epoch], df[train/box_loss], labeltrain/box_loss) plt.plot(df[epoch], df[train/cls_loss], labeltrain/cls_loss) plt.plot(df[epoch], df[val/box_loss], labelval/box_loss) plt.plot(df[epoch], df[val/cls_loss], labelval/cls_loss) plt.xlabel(epoch) plt.ylabel(loss) plt.legend() plt.grid(True) plt.show()读曲线的要点很简单训练和验证的 box/cls loss 都持续下降并且尾部区域不再大幅波动说明收敛基本到位训练 loss 降了但验证 loss 在某个点后开始反弹说明从那里开始过拟合最佳权重通常在验证 loss 拐点之前。YOLOv8 本身会保留best.pt到 val 指标最高的轮次省去不少手动找最优权重的麻烦。4.4 迁移学习从头训还是用预训练垃圾分类图片里的物体瓶子、纸盒、果皮与其他数据集中的各种物体存在大量共通的低层特征因此加载yolov8s.pt预训练权重能明显提供收敛速度。我的建议是分两阶段操作第一阶段冻结 Backbone只训练 Neck 和 Head用较低学习率跑 30 轮第二阶段解冻全部参数降低学习率再微调 40~60 轮。这样做的原因很直接冻结阶段相当于让模型先记住“物体在哪儿”的通用知识解冻后再让全局参数适应垃圾图像特殊纹理。直接全部参数一起训通常也能出结果但波动更大收敛更慢。5. 模型评估与 bad case 分析5.1 看哪些指标mAP50 与 mAP50-95目标检测的评估我不只看单一指标。项目里重点记录 Precision、Recall、mAP50、mAP50-95。Precision 高说明模型大多数预测都是对的但可能漏了很多Recall 高说明模型把该找到的物体都找到了但可能夹杂很多误检mAP50 是常用工程指标IoU 阈值 0.5 下的平均精度mAP50-95 更严格从 0.5 到 0.95 每 0.05 算一次再求平均小物体和精确定位要求高时这个指标更能反映差距。训练结束我把 20 个类别的 PR 曲线、混淆矩阵、F1 曲线都导出来。混淆矩阵特别重要它能直观看出哪些类互相混淆比如“易拉罐”和“金属罐”如果同时在类别体系里矩阵上肯定会出现大块对角外响应这时就要考虑合并类别。5.2 改进前后的对比账我整理一组当时消融实验的记录模型配置mAP50 (%)mAP50-95 (%)推理耗时 (ms)YOLOv8s 基线89.472.640 CoordAttBackbone90.874.243 CoordAtt 辅助分支损失91.675.144 CoordAtt 辅助分支 GSConv 轻量化92.175.939这个结果是本地测试集实测不同数据集会略有差异。肉眼可见轻量化不仅没拖后腿反而通过减少冗余参数把速度拉回接近基线的水准最终方案保留的就是“CoordAtt 辅助分支损失 GSConv”这一套组合。5.3 热力图验证模型到底在看什么用 Grad-CAM 生成目标检测特征图和热力图是一个被低估的调试手段。我处理过用户集中反馈的“模型总是把袋装垃圾错判为其他垃圾”的问题改成观察热力图后发现模型注意力集中在袋子的提手和折痕上而真正的塑料特征关注不足。解决办法是加入一批撕开袋口、露出内部物件的样本并在增强时增加局部遮挡。这个过程非常启发人模型学到的“判别区域”和人类理解的“物体核心特征”如果没有对齐再复杂的网络也救不回来。建议所有做图像识别项目的朋友都把热力图当成常规质量检查工具。5.4 Bad case 排查漏检、误检、置信度分布我在项目里专门做了 bad case 分类发现垃圾识别场景下三类问题最多第一类是密集堆叠漏检。一堆瓶子叠在一起时模型容易只检出边缘的 2~3 个漏掉中间遮挡严重的。对策是加强遮挡增强同时将置信度阈值从 0.5 放宽到 0.35允许更多低置信度候选进入后处理再靠 NMS 过滤重叠框。第二类是材质反光误检。金属罐、玻璃瓶在强光下反光严重模型会把反光区识别成白色物体。对策是增加强光实测数据同时在 HSV 增强里提高高光样本比例并额外打了 200 张反光样本让模型看到光照变化的“正确版本”。第三类是袋装不透明垃圾。无法从外表看出内部类别时模型天然只会给出一个置信度很低的猜测。我最终在系统逻辑上做个兜底置信度低于 0.4 时反馈“请将垃圾袋拆开后再次投放”而不是硬猜。这个设计对用户体验的提升非常明显。6. 部署落地从 PT 权重到可用服务6.1 导出 ONNX 与 TensorRT训练得到的best.pt不能直接放到服务端跑需要先导出。标准流程是先转 ONNX再根据硬件选择优化方案。yolo export modelruns/detect/yolov8s_coordatt/weights/best.pt \ formatonnx opset12 simplifyTrue如果服务器或工控机有 NVIDIA GPU推荐继续转 TensorRTtrtexec --onnxbest.onnx \ --saveEnginebest.engine \ --fp16 \ --workspace4096TensorRT 的 FP16 推理在实测中比 PyTorch 快 1.5~2 倍这对嵌入式系统或者算力有限的边缘盒子非常关键。注意转换时 CUDA 版本和 TensorRT 版本需要匹配否则经常会报一些令人摸不着头脑的算子错误。6.2 用 FastAPI 封装识别服务我建议团队把模型封装成一个独立 HTTP 服务这样前端小程序、闸机控制、摄像头采集都能复用同一套识别接口。简单的实现如下from fastapi import FastAPI, UploadFile from ultralytics import YOLO from PIL import Image import numpy as np app FastAPI() model YOLO(best.pt) app.post(/infer) async def infer(file: UploadFile): img Image.open(file.file) results model.predict(sourceimg, conf0.4, imgsz640) det results[0] boxes det.boxes.xyxy.cpu().numpy() labels det.boxes.cls.cpu().numpy().astype(int) scores det.boxes.conf.cpu().numpy() names det.names return { boxes: boxes.tolist(), labels: [names[i] for i in labels], scores: scores.tolist() }实际生产里还要加请求超时、图片大小限制、并发控制不然高并发下 GPU 显存会被撑爆。这一层的设计虽然不直接影响模型精度但直接决定系统能不能被项目验收。6.3 边缘硬件部署RK3588 实战不少朋友搜过“rk3588部署yolov8”这确实是现在很常见的硬件选型。RK3588 的 6 TOPS NPU 跑 YOLOv8s 是在预算和算力之间比较平衡的取舍部署时我用的是瑞芯微 RKNN-Toolkit2 流程把 ONNX 模型转成 RKNN 格式。导 ONNX 时尽量用opset12和simplifyTrue部分算子 RKNN 工具还不支持简化后能避免很多转换报错准备校准集。RKNN 做 INT8 量化时需要校准集来统计激活值分布校准图最好选 500 张覆盖所有类别的真实场景图而不是随便截几张量化掉点能控制在 2% 以内编译生成.rknn文件在板端调用 RKNN Python/ C API 做推理。部署过程中遇到的高频坑是PC 端 PyTorch 推理和 NPU 推理结果不一致主要原因是预处理细节不同。YOLOv8 默认的归一化是除以 255而 RKNN 示例里经常用归一化参数硬编码还要注意 BGR/RGB 通道顺序和 letterbox 缩放方式要一致。我先在板端写了比对脚本逐帧对比 PC 端与 NPU 端输出发现问题后调整到完全一致。6.4 再补充一个低配摄像头方案ESP32-S3如果项目预算极低还有人问过 ESP32-S3 图像识别行不行。以我的经验直接用 TF 微控制器框架在 ESP32-S3 上跑完整的 YOLOv8s 并不现实内存和算力都不够。但风格可以考虑这种做法ESP32-S3 负责拍图和上传识别全部交给局域网内的服务器或 RK3588 盒子得到结果再通过串口或 WiFi 反馈。把“端侧识别”降级为“端侧采集”项目稳定性会有质的提升。7. 训练中的常见问题与排查速查表这部分我把训练几个月里踩过的坑整理成一张速查表给同样在跑 YOLOv8 的读者直接抄作业。现象可能原因排查方向解决办法Loss 直接为 NaN学习率过大、标签中出现空标注、输入图像损坏看日志前几轮 loss 变化调低 lr0清洗数据集删除无法解码的损坏图片Loss 迟迟不掉Backbone 被冻结且 Learning Rate 设置过小检查冻结范围与参数名解冻颈部模块或提高 lr0 到 0.001验证 mAP 震荡剧烈数据量过少、batch 过小、数据集分布不均按类别统计样本数过采样少数类提高 batch减少验证集随机性PyTorch 内存不足batch 太大或 cacheTrue 时内存不够观察内存占用batch 调小cache 改为 False开启 amp导出 ONNX 报算子错误某些模块不支持 opset 或 exporter检查具体报错算子换 simplify升级 ultralytics手动替换算子RKNN 转换失败ONNX 里包含动态尺寸或特殊算子查看 unoptimized 日志固定输入尺寸 640x640用 opset12 重新导出训练正常但测试集表现差数据增强与测试分布差距过大对比增强前后结果关闭 Mosaic 或降低增强系数采集真实场景测试集过拟合严重数据量不足但参数量过大对比 train_loss 与 val_loss用预训练权重增加 Dropout调整 weight_decay你如果遇到“KeyError: class_names”这类模型加载问题多半是训练用的权重文件和当前项目的数据集 YAML 对不上要么重新导出权重要么确保测试环境里data.yaml里的类别名称与训练时完全一致。另一个容易忽略的问题是信息泄漏。如果做数据预处理时用了全图片统计的归一化参数测试时会泄漏训练集分布的信息虽然 YOLOv8 默认用固定 255 归一化规避了这一点但一旦自己写预处理脚本就要特别小心。8. 避坑总结与分享一点个人体会这个项目做完我最大的体会是“数据集质量决定模型上限模型结构决定距离上限还有多远”。很多人一上来就改 YOLOv8 的 Head、堆注意力模块结果发现数据标注混乱、类别分配不合理改来改去精度都上不去还白白增加调试时间。再分享一个可以直接用的技巧每次在某一个 C2f 或注意力模块改动之后不仅看 mAP也盯一下推理 FPS 和模型参数量。我习惯把每一版改动记录成一张表用什么模块、放哪里、训练了多少轮、mAP 多少、FPS 多少、有没有副作用。后面发现模型不行回滚速度非常快不用重跑十几个小时去猜。如果你也想做类似方向我的建议是先用官方 YOLOv8 权重在原数据集上跑出一个基线再看哪些类别的识别效果明显不行优先针对性地采集数据而不是一上来就往网络结构上动刀。很多时候补几百张难例比换任何花哨模块都有效。训练时固定随机种子、固定库版本、做好实验记录这些“看不见”的事情对项目长期推进的收益远大于在结构上一时的灵感迸发。最后说一点贴近实际项目的经验垃圾分类识别这类系统在真实环境里大概会有 10%~15% 的图片让模型怎么都不确定这时与其硬识别不如在产品交互上允许用户手动选择。有些回收箱已经加了“摄像头判定用户按钮确认”的双确认机制误判率一下子下降了很多。技术方案要和产品逻辑配合而不是让模型一个人扛所有责任。这个思路放在很多图像识别项目里都适用。