把 car 改名成 automobile,要动 1 处标签定义 + 2 处框引用。
少改一处,那个框就引用了不存在的标签——训练时它会被当成背景,模型学成「这类目标不用管」。
上一节把框画完了,这一节处理一个「看着很小、后果很大」的操作:改名。 标签名和项目名都要改,但两者的风险完全不同。
一、改名为什么是个危险操作
标注文件里,同一个名字出现在两个地方:标签定义表(有哪些标签), 和每个框上的引用(这个框属于哪个标签)。 它们是两套数据,靠字符串对起来。改名要同时改两边,漏一边就断链。 断了之后不会报错——数据照样能读,训练照样能跑。 但那个框的类别找不到定义,多数框架会静默地把它当背景。 结果就是:你标了 40 个汽车框,其中 8 个因为改名漏了,模型学到的是「这 8 个位置什么都没有」。 它会把汽车学成背景。
二、两处引用,一个检查
Demo 里的数据很小:3 个标签、3 张图、5 个框。改名之后统计:改了 1 处标签定义、2 处框引用。
为什么框引用只有 2 处?因为 5 个框里只有 2 个是 car,其余是 person 和 traffic light。
这个数字必须跟改之前数出来的对上。
改完跑三项检查,一项都不能省:
① 引用都在定义里:框用到的每个标签,定义表里必须都有。
② 没有残留旧名:全文搜旧名,命中次数必须是 0。
③ 数量没变:改前 5 个框,改后还是 5 个。
这三项都是「不检查也不会报错」的类型,所以必须写成脚本自动跑。
手工改一次、人眼核一遍,是这套流程里最不可靠的一环。
三、项目名和标签名,风险不一样
标签名进数据,改错会影响训练——这是硬伤。 项目名不进数据,它只是这批标注的标题,导出时可能被当成文件名前缀。 它不影响模型,但影响交付。 所以风险等级要分开看:标签名改动要「改 + 查 + 复标抽检」;项目名改动只要「确认下游没按名字匹配」。 项目名改动的坑在自动化流程里:如果有脚本按「项目名_日期.json」这种规则去找文件, 改了名字就找不到了。改之前先搜一遍有没有人依赖它。 还有一条:改名之后,之前导出的文件要不要跟着改?答案是「不要」。 旧文件保持原样、加个说明,新文件用新名——批量改历史文件,是把一次风险放大成 N 次。
四、在 MakeSense 里改名
📋 实操清单(要在浏览器里点): 第一步,打开项目,左侧标签面板上右键(或点标签旁边的小图标),选重命名/编辑标签那一项,改完回车。 第二步,这个动作会自动更新所有已画的框——这是工具帮你做的一致性。 所以界面上改名比改文件安全得多。 第三步,改完立刻导出一份,用脚本跑那三项检查。不要只看界面上显示对了就放心。 🐍 沙箱等价物:三项检查的脚本见 Demo。 沙箱里点不了界面,但「引用和定义对不对得上」是纯数据结构问题,脚本一跑就知道。 而且脚本能处理工具处理不了的场景——比如合并两个项目、批量改历史数据。
五、动手 Demo:改名要动 1 处定义加 2 处引用,漏一处就断链
造一份小标注文件(3 个标签、3 张图、5 个框),把 car 改名成 automobile,统计改了几处;
再核对「定义表里的标签」和「框里用到的标签」是否一致。
# 两处引用都要改
for lb in data[u'labels']:
if lb[u'name'] == OLD:
lb[u'name'] = NEW
for im in data[u'images']:
for bx in im[u'boxes']:
if bx[u'label'] == OLD:
bx[u'label'] = NEW
# 三项检查
names = set(lb[u'name'] for lb in data[u'labels'])
used = set(bx[u'label'] for im in data[u'images'] for bx in im[u'boxes'])
print(used - names) # 应该为空
实跑输出:
--------------------------------------------------------------------
改标签名:改一处漏三处,模型就学错了
--------------------------------------------------------------------
文件 annotations.json
项目名 旧项目名
标签 3 个
图 3 张、5 个框
需求:把标签 car 改名成 automobile。
改了标签定义 1 处
改了框上的引用 2 处
标签定义里有 automobile、person、traffic light
框里用到 automobile、person、traffic light
不一致的 无
**一次改名要动两处:标签定义,和每个框上的引用。**
少改一处,就会得到一个「框引用了不存在的标签」的数据集——
训练时这个框会被当成背景,**模型就学成「这类目标不用管」。**
顺手把项目名也改掉(它不影响标注,但影响交付):
新项目名 新项目名·2026
项目名在导出时经常被当成文件名前缀。**改之前先确认下游有没有按名字匹配。**
改完必须跑一次一致性检查,三项都要过:
① 引用都在定义里 框用到的标签,定义里必须都有
② 没有残留旧名 全文搜旧名,命中 0 次
③ 数量没变 改前 5 个框,改后还是 5 个
结果:标签定义改了 1 处、框引用改了 2 处。 总共 3 处,都是字符串替换。
改完之后两个集合都对上了:定义里有 automobile、person、traffic light,框里用到的也是这三个,
差集为空。
这个「差集为空」就是第一项检查。
如果差集不为空,说明有框引用了不存在的标签——那一刻数据就已经坏了。
第二项检查(搜旧名命中 0 次)Demo 里没单独打印,因为改动是程序做的,天然不会有残留。
但手工改的时候这一项最容易漏,比如某个文件里还存着旧名的一份缓存。
第三项检查(框数不变)也值得单独跑:
改名只该改字符串,不该增减任何元素。 数量一变就说明处理逻辑写错了。
30 秒实验
- 只改标签定义、不改框引用,再跑一次三项检查,看差集里出现什么。 这就是「少改一处」的后果,一眼就能看见。
- 把两个标签合并成一个(比如
car和automobile都要并成vehicle),看需要改几处、 合并后每一类各有多少框。合并比改名更容易漏。 - 加一项检查:标签名里有没有空格和大写字母。改名是顺手把命名规范统一的最好时机。
常见误区
- 「改个名而已,编辑器全局替换一下就行」。 全局替换会改到不该改的地方(比如输出文本里恰好有这个词)。要按结构改,不按字符串改。
- 「界面上显示对了就没问题」。界面只显示一层。导出文件里有没有残留旧名,得跑脚本查。
- 「历史文件也一起改掉保持一致」。批量改历史文件是把一次风险放大成 N 次。 旧文件保持原样,新文件用新名。
自测三问(点开对答案)
1. 改名要改哪两处? —— 标签定义表里的名字,和每个框上记录的标签引用。它们是两套数据,靠字符串对齐,漏一边就断链。 2. 漏改会有什么后果?为什么不会报错? —— 那个框的类别找不到定义,多数框架会静默地把它当背景,模型学成「这类目标不用管」。 因为它不违反格式,所以不报错。 3. 改完要跑哪三项检查? —— 框用到的标签都在定义里、全文搜旧名命中 0 次、框的数量没变。 三项都是「不检查也不报错」的类型。名字改好了,最后一步是把数据交出去。下一节讲导出,以及坐标格式的坑。
- ☐ (本节完,下一节 4.2.5 导出打标数据文件)