本篇文章将详细介绍Tensorflow2.x中模型训练标签顺序和预测结果标签顺序不一致问题,这个问题如果考虑不周,或者标签顺序没有控制好的情况下会出现预测结果精度极其不准确的情况。
训练数据集的结构:数据集有超过10的类别数,这里包含16类数据,每个类别放置到一个文件夹中,文件夹名称按照其类别命名为1,2,3……16。文件夹结构如下图所示:
这组数据在系统中的排序是1,2,3,4,……顺序排序的。
使用Tensorflow读取数据,代码如下:
data_all = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
labels='inferred',
batch_size=batch_size,
image_size=(img_height, img_width),
shuffle=False # 关闭洗牌以保持与文件夹中图像的顺序一致
)
按照有的说明,tf.keras.preprocessing.image_dataset_from_directory()函数是按照文件夹中的排序读取的数据,但实际上并不是。我们来查看一下这个函数读取的数据是什么顺序,这里直接使用一下一行代码:
class_names = data_all.class_names
print("类别标签:", class_names)
看看输出结果是什么:
类别标签: ['1', '10', '11', '12', '13', '14', '15', '16', '2', '3', '4', '5', '6', '7', '8', '9']
这里我们可以看到,以上函数读取的数据顺序和文件夹中的顺序并不一致,因此,我们在进行精度评的时候一定要保持这个标签的顺序一致。
Tensorflow2.训练的模型预测出来的结果是按照0,1,2,……编码顺序编码的,也就是说,训练数据集中第1类预测出来的标签代码实0,第2类是1,第3类是2.
在这里我们进行评估时,如果是使用以下代码进行训练和评估时,训练集和测试集数据顺序一致,所以不会出现什么问题。
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.7,
subset='training',
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
test_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.7,
subset='validation',
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
不过预测出来的标签和我们的类别不一致,这时候我们需要将两者变换为一致,我们可以通过建立一个类别对应关系的字典来进行变换,使预测的标签值变换为实际类别代码如下:
label_dict={'0': 1, '1': 10, '2': 11, '3': 12, '4': 13, '5': 14, '6': 15,
'7': 16, '8': 2, '9': 3, '10': 4, '11': 5, '12': 6,'13': 7, '14': 8,'15': 9}
print(label_dict)
# 将原始标签映射到调整后的标签
adjusted_labels = [label_dict[str(label)] for label in original_labels]
df[adjusted_name] = adjusted_labels
通过以上代码,可以将预测的标签值变换为实际类别ID.
对于这个问题,我们可以通过修改文件夹名称来控制数据读取的顺序,比如将文件夹名称改为01,02,03,……16.或者按照字母a,b,c,d……的顺序来控制顺序。不过这样对后面评价计算的时候也有不好的影响,评价函数通常是使用数值类别来进行评价计算的,所以用字母的话后面也还需要再进行类别代码的转换。