16 个标签、1255 个框,查出四个毛病:car 和 Car 分裂成两类;
8 个长尾标签只占 4.4% 的框;「汽车」和「车」字面相似度只有 0.67,却是同一个东西。
标签体系是契约,不是随手敲的词。
上一节定了任务类型,这一节定「标什么」。标签名敲错一个字,后面所有环节都要返工。
一、标签体系是一份契约
标签列表看起来只是个词表,实际上它规定了三件事:哪些东西要标、同一个东西叫什么、边界在哪里。 这三件事只要有一条不清楚,两个标注员就会标出两套数据。 而模型拿到的是这两套混在一起的结果——它会学到一个混乱的边界。 所以标签体系要满足四条:互斥(一个目标只能属于一类)、穷尽(该标的都有类可归)、 同层(「汽车」和「货车」不该并列)、可判定(两个人看同一张图能得出同样结论)。 四条里最容易破的是第四条。「什么算行人」——远处三像素的人算不算?被遮住一半的算不算? 照片里的海报上的人算不算?这些必须写进手册,不能靠「你懂的」。
二、四个毛病,能自动查的自动查
毛病一:大小写和拼写变体。 Demo 里 car 和 Car 同时存在,合并前 16 类、合并后 15 类。
模型会把它们当成两个完全不同的类,各学一半样本。
毛病二:同义标签。 「汽车」和「车」、「货车」和「卡车」、「行人」和「人」。
字面不同,意思一样。
麻烦在于字面相似度低的恰恰最危险:「汽车」和「车」只有 0.67,「摩托」和「摩托车」有 0.80。
按相似度排序,最该合并的排在后面。所以这一类只能靠人看,机器查不准。
毛病三:层级重叠。 「汽车」包含「货车」,它们就不该是并列标签。
查法是问一句「X 是不是一种 Y」,是就冲突。
毛病四:长尾标签。 Demo 里 16 个标签有 8 个出现不到 20 次,合计只有 55 个框、占 4.4%。
这些标签的标注成本一样花,对模型的贡献接近于零。
三、长尾标签怎么处理
两个办法,没有第三个:合并进父类,或者删掉。 「轿车」12 个框、「车」8 个、「car」3 个——这些全部并进「汽车」,从 4 个类变成 1 个类, 样本从 23 个变成 443 个。 「路面」只有 2 个框,而且它跟「交通标志」在语义上没什么关系——直接删掉, 或者归到一个「其他」类里,且不参与评估。 判断标准很简单:这个类如果只有十几个样本,模型学不会;学不会的类,在评估里只会拉低总分。 留着它唯一的用处是让报告难看。 有一个例外:如果这个类业务上极重要(比如「安全帽未佩戴」),样本少也要留, 但要做定向补采——去现场多拍,而不是靠现有数据硬撑。
四、在 MakeSense 里建标签
📋 实操清单(要在浏览器里点,沙箱里做不了):
第一步,打开 makesense.ai,点 Get Started,把图片拖进页面。
第二步,左侧面板就是标签区。
点「Create new label」逐个添加,每个标签会自动分配一个数字快捷键(1 到 9,再往上是 0 和字母)。
第三步,标签名一律用英文小写加下划线(traffic_light 而不是 Traffic Light)。
理由是导出到 YOLO 等格式时,中文和空格经常出问题。显示用中文可以另设,但键名要干净。
第四步,同一批数据里标签顺序定了就别改。
因为 YOLO 导出的是类别序号,不是类别名——顺序一变,之前导出的数据和之后的就对不上。
🐍 沙箱等价物:标签表的四个毛病用代码查,见 Demo。
其中大小写合并和长尾统计是纯字符串和计数,这两项能全自动查出来,一个脚本跑一遍就够。
五、动手 Demo:16 个标签里 8 个是长尾,合计只占 4.4% 的框
造一份 16 个标签、16 张图累计 1255 个框的标注统计,逐个查四类毛病:大小写变体、同义标签、 层级重叠、长尾标签。大小写和长尾两项用代码自动查,同义和层级靠人工判断。
# 毛病一:大小写/拼写变体(自动查)
var = {}
for t in raw:
var.setdefault(t.lower(), []).append(t)
bad = [(k, v) for k, v in var.items() if len(v) > 1]
# 毛病四:长尾标签(自动查)
rows = []
for t in raw:
if use[t] < 20:
rows.append([t, u'%d' % use[t]])
# 毛病二:同义标签(只能人看,机器给个参考值)
difflib.SequenceMatcher(None, u'汽车', u'车').ratio()
实跑输出:
--------------------------------------------------------------------
标签体系:四个毛病,全都能自动查出来
--------------------------------------------------------------------
标签总数 16 个
标注总数 1255 个框
第一个毛病:大小写和拼写变体。
car → car/Car
**同一个东西写成两种,训练时会被当成两类。** 合并前 16 类,合并后 15 类。
第二个毛病:同义标签(字面不同、意思一样)。
汽车 与 轿车,字面相似度 0.50
汽车 与 车,字面相似度 0.67
货车 与 卡车,字面相似度 0.50
行人 与 人,字面相似度 0.67
摩托 与 摩托车,字面相似度 0.80
**字面相似度低的恰恰最危险**——「汽车」和「车」只有 0.67,但它们是同一个东西。**
这类问题只能靠人看,机器查不准。**
第三个毛病:层级重叠。
「汽车」包含「货车」吗 包含。那它们就不该是并列标签
怎么查 问一句「X 是不是一种 Y」,是就层级冲突
同类问题还有「交通标志」和「红绿灯」——红绿灯算不算标志?
**必须二选一写进标注手册,否则两个人会标成两样。**
第四个毛病:长尾标签。
标签 出现次数
----------------
轿车 12
车 8
car 3
Car 2
卡车 9
人 15
person 4
路面 2
16 个标签里有 8 个出现不到 20 次,合计只有 55 个框——占全部的 4.4%。
**这 8 个标签的标注成本一样花,但对模型的贡献接近于零。**
处理办法只有两个:合并进父类,或者干脆删掉。**别留着。**
第一段输出很直接:car 和 Car 被当成两个标签。合并前 16 类、合并后 15 类。
这一类错误一个 .lower() 就能查出来。
第二段是相似度参考值:「汽车」对「车」0.67、「摩托」对「摩托车」0.80。
最该合并的那一对,相似度反而最低——所以这一项不能按阈值自动合并,只能当提示,人来定。
第三段是长尾:
8 个标签出现不到 20 次,合计 55 个框,占全部的 4.4%。这个 4.4% 是最有说服力的数——
八成标签只贡献了不到二十分之一的样本。
那句「标注成本一样花,对模型的贡献接近于零」不是夸张。
每个标签都要定义、要写手册、要在培训里讲一遍,这些固定成本跟样本量无关,全都摊在那 4.4% 上了。
要说明一点:这里的次数分布是我按真实数据集的样子设的,不是从某个公开数据集抓的。
要学的是查的方法和判断标准,不是这几个数。
30 秒实验
- 把
car和Car合并之后重算总类数,再算每一类的框数占比。 你会看到「汽车」从 420 变成 425,而「Car」这一类的独立意义消失了。 - 把长尾里 5 个标签合并进父类,再算一遍长尾数量。 从 8 个降到 3 个,剩余长尾的框数占比从 4.4% 降到 1% 以下。
- 加一条自动检查:标签名里有没有空格、大写、中划线。这三样在导出到 YOLO 或 CSV 时都会出问题。 一条正则就能拦住。
常见误区
- 「标签名字随便写,反正导出时会转」。YOLO 导出的是类别序号,顺序一变,之前的数据就对不上。 键名要干净,顺序要固定。
- 「多余的小标签留着以后可能有用」。样本不到二十个的类,模型学不会,还会拉低整体评估。 要么合并,要么删。
- 「同义标签可以按相似度自动合并」。最该合并的那一对相似度往往最低(「汽车」和「车」只有 0.67)。 这一项必须人工判断。
自测三问(点开对答案)
1. 标签体系要满足哪四条? —— 互斥(一个目标只属一类)、穷尽(该标的都有类)、同层(父子不并列)、 可判定(两个人看同一张图能得出同样结论)。 2. 为什么长尾标签要合并或删掉? —— 样本太少的类模型学不会,学不会就会在评估里拉低总分; 而它的定义、手册、培训这些固定成本照样要花。 3. 为什么标签名建议用英文小写加下划线? —— 因为导出到 YOLO、CSV 等格式时,中文和空格经常出问题。 显示名可以是中文,但键名要干净、可跨工具。标签定好了,可以真开始画了。下一节看「画得准不准」怎么量化。
- ☐ (本节完,下一节 4.2.3 给图像数据打标)