Keras模型TP/TN/FP/FN数值过高、总和与样本量不符问题咨询
共有39209张图像用于模型训练,需要获取所构建机器学习模型的tp, tn, fp, fn指标值,核心疑问为:tp + tn + fp + fn的总和是否必须等于训练图像的总数量?当前观测到输出的真/假分类指标数值远高于预期,不确定结果是否合理。
对应的模型构建代码如下:
model = Sequential() model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=X_train.shape[1:])) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(43, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=[tf.keras.metrics.TruePositives(name='tp'), tf.keras.metrics.TrueNegatives(name='tn'), tf.keras.metrics.FalsePositives(name='fp'), tf.keras.metrics.FalseNegatives(name='fn')]) model.fit(X_train, y_train, epochs=10)
模型训练10轮的日志输出如下:
Epoch 1/10 39209/39209 [==============================] - 16s 414us/sample - loss: 1.2279 - tp: 20191.0000 - tn: 1643982.0000 - fp: 2796.0000 - fn: 19018.0000 Epoch 2/10 39209/39209 [==============================] - 11s 292us/sample - loss: 0.4241 - tp: 31887.0000 - tn: 1644121.0000 - fp: 2657.0000 - fn: 7322.0000 Epoch 3/10 39209/39209 [==============================] - 11s 287us/sample - loss: 0.2881 - tp: 34487.0000 - tn: 1644681.0000 - fp: 2097.0000 - fn: 4722.0000 Epoch 4/10 39209/39209 [==============================] - 11s 287us/sample - loss: 0.2177 - tp: 35696.0000 - tn: 1645046.0000 - fp: 1732.0000 - fn: 3513.0000 Epoch 5/10 39209/39209 [==============================] - 11s 285us/sample - loss: 0.1828 - tp: 36241.0000 - tn: 1645204.0000 - fp: 1574.0000 - fn: 2968.0000 Epoch 6/10 39209/39209 [==============================] - 11s 291us/sample - loss: 0.1457 - tp: 36813.0000 - tn: 1645488.0000 - fp: 1290.0000 - fn: 2396.0000 Epoch 7/10 39209/39209 [==============================] - 11s 290us/sample - loss: 0.1231 - tp: 37267.0000 - tn: 1645655.0000 - fp: 1123.0000 - fn: 1942.0000 Epoch 8/10 39209/39209 [==============================] - 11s 288us/sample - loss: 0.1117 - tp: 37427.0000 - tn: 1645699.0000 - fp: 1079.0000 - fn: 1782.0000 Epoch 9/10 39209/39209 [==============================] - 11s 287us/sample - loss: 0.0990 - tp: 37720.0000 - tn: 1645846.0000 - fp: 932.0000 - fn: 1489.0000 Epoch 10/10 39209/39209 [==============================] - 11s 287us/sample - loss: 0.0867 - tp: 37847.0000 - tn: 1645879.0000 - fp: 899.0000 - fn: 1362.0000
你观测到的指标数值是完全正常的,tp + tn + fp + fn不需要等于训练图像总数量,核心原因是你训练的是43类的多分类单标签模型,而Keras内置的TruePositives/TrueNegatives/FalsePositives/FalseNegatives指标默认采用逐类别(一对多)的计算逻辑,会对每个类别单独统计四个指标后做全局累加:
- 对43个类别中的每一类,都会单独判断每个样本在该类别下的分类结果属于tp、tn、fp、fn中的哪一类
- 每个样本总共会在43个类别维度上各产生1次统计结果,因此四个指标的总和应该等于
样本总数 * 类别数
你可以自行核算最后一轮的指标总和:37847 + 1645879 + 899 + 1362 = 1685987,除以样本量39209刚好等于43,和你的类别数完全匹配,不存在计算错误。
日志里tn数值达到160多万也符合逻辑:对单个样本来说,它只属于43个类别中的1类,剩下42个类别都属于负类,只要模型没有把样本错分到这些负类,每个负类都会贡献1个tn统计值,仅这部分就会产生39209 * 42 = 1646778的tn基数,和你日志里的tn数值基本吻合,差值就是错分样本产生的fp、fn带来的偏差,完全符合预期。
注意:如果需要计算多分类任务的全局混淆矩阵、精确率、召回率等指标,不要直接使用默认参数下的这四个内置指标的输出值计算,否则结果会完全失真。正确做法是拿到模型预测结果后,对输出的softmax概率做argmax得到最终预测类别,再和真实标签比对计算全局多分类混淆矩阵,或者使用支持多分类模式的指标计算接口。
内容的提问来源于stack exchange,提问作者Jan

