一、原因分析:
在 MMPretrain 中准备 ImageNet 数据集时,通常每个子文件夹会被视为一个独立的类别,且子文件夹的名称默认作为类别的标识符。以下是具体说明:
1. ImageNet 子文件夹结构
ImageNet 数据集的标准格式如下:
imagenet/
├── train/
│ ├── n01440764/ # 类别 1(实际对应 "tench, Tinca tinca" 等类别名)
│ │ ├── image1.JPEG
│ │ ├── image2.JPEG
│ │ └── ...
│ ├── n01443537/ # 类别 2
│ └── ...
└── val/
├── n01440764/
└── ...
• 子文件夹名称(如 n01440764
)是类别的唯一标识符(通常是 WordNet ID)。
• 每个子文件夹内的图像属于同一类别。
2. MMPretrain 的默认约定
• 类别名称映射:默认情况下,MMPretrain 不会直接使用子文件夹名称作为可读的类别名,而是通过以下方式处理:
• 在训练时,类别会按照子文件夹的字母顺序被映射到整数标签(如 0, 1, 2, ...
)。
• 实际可读的类别名(如 “tench”)需要通过额外的元数据文件(如 meta/category.txt
)或配置文件中的 classes
参数指定。
3. 字母顺序是怎么排列的呢
假设文件夹名称如下:
data/
├── train/
│ ├── class_10/ # 注意:字符串比较时 "class_10" < "class_2"
│ ├── class_2/
│ └── class_1/
• 排序规则:
• 字符串逐字符比较,class_10
、class_1
、class_2
的排序是:
class_1 → 标签 0 class_10 → 标签 1 class_2 → 标签 2
• 原因:前 7 个字符 class_1
相同,第 8 个字符分别是 0
(ASCII 48)、1
(ASCII 49)、2
(ASCII 50),因此 class_1
< class_10
< class_2
。
为什么字母顺序重要?
• 标签一致性:模型的输出标签会依赖此顺序。例如,如果训练和验证集的文件夹排序不一致,会导致预测结果混乱。
二、解决方法:
4. 如何验证当前数据集的类别顺序?
在代码中直接打印类别名称:
from mmpretrain.datasets import build_dataset
dataset = build_dataset(dict(
type='ImageNet',
data_prefix='path/to/train',
))
print(dataset.CLASSES) # 输出按字母顺序排序的类别列表
将类别顺序复制到mmpretrain-main/mmpretrain/datasets/categories.py中IMAGENET_CATEGORIES中替换,重新训练。