我正在尝试在图像数据集上训练 CNN 模型,但我被获取 TruePositives、TrueNegatives、FalsePositives 和 FalseNegatives 的十进制值所困扰。这怎么可能?
ERROR sample
Epoch 1/3
36/36 ━━━━━━━━━━━━━━━━━━━━ 69s 2s/step - false_negatives: 30.1351 - false_positives: 35.3784 - loss: 2.1995 - true_negatives: 389.0540 - true_positives: 437.6487
有一些 (tp+tn+fp+tn)不等于样本总数。
完整代码
import pandas as pd
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.layers import Dense,Flatten,InputLayer,Conv2D,MaxPooling2D,Concatenate,Input,BatchNormalization
from tensorflow.keras.models import Sequential,Model
from tensorflow.keras.losses import BinaryCrossentropy,CategoricalCrossentropy
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
from tensorflow.keras.models import Model
from sklearn.metrics import classification_report
from tensorflow.keras.callbacks import EarlyStopping
datagen=ImageDataGenerator(rescale=1.0/255.0)
train_gen=datagen.flow_from_directory('train',class_mode='binary',
target_size=(224,224),batch_size=32,shuffle=True)
output
Found 1146 images belonging to 2 classes.
tp = tf.keras.metrics.TruePositives()
tn = tf.keras.metrics.TrueNegatives()
fp = tf.keras.metrics.FalsePositives()
fn = tf.keras.metrics.FalseNegatives()
tp.update_state([0.4, .9, .7, .8], [1.0, 0.0, 1.0, 1.0])
tp.result()
output
<tf.Tensor: shape=(), dtype=float32, numpy=3.0>
model_input=Input(shape=(224,224,3))
x=Conv2D(filters=32, kernel_size=(3,3),activation='relu',padding='valid')(model_input)
x=MaxPooling2D(pool_size=(2,2),strides=2)(x)
x=Conv2D(filters=64, kernel_size=(3,3),activation='relu',padding='valid')(x)
x=MaxPooling2D(pool_size=(2,2),strides=2)(x)
x=BatchNormalization()(x)
x=Conv2D(filters=64, kernel_size=(3,3),activation='relu',padding='valid')(x)
x=MaxPooling2D(pool_size=(2,2),strides=2)(x)
x=BatchNormalization()(x)
x=Flatten()(x)
x=Dense(units=1000,activation='relu')(x)
output=Dense(units=1,activation='sigmoid')(x)
model=Model(inputs=model_input,outputs=output)
model.compile(optimizer=Adam(),loss=BinaryCrossentropy(),metrics=[tp,fp,fn,tn])
early_stopping = EarlyStopping(monitor='val_loss', patience=2,restore_best_weights=True)
history=model.fit(x=train_gen,epochs=3,callbacks=[early_stopping])
十进制值错误
Epoch 1/3
36/36 ━━━━━━━━━━━━━━━━━━━━ 69s 2s/step - false_negatives: 30.1351 - false_positives: 35.3784 - loss: 2.1995 - true_negatives: 389.0540 - true_positives: 437.6487
Epoch 2/3
36/36 ━━━━━━━━━━━━━━━━━━━━ 61s 2s/step - false_negatives: 7.8378 - false_positives: 13.5135 - loss: 0.1692 - true_negatives: 283.1081 - true_positives: 300.4054
Epoch 3/3
36/36 ━━━━━━━━━━━━━━━━━━━━ 65s 2s/step - false_negatives: 2.3243 - false_positives: 3.0811 - loss: 0.0546 - true_negatives: 289.8108 - true_positives: 308.3513
在 Keras 中看到的十进制值对于
TruePositives
、
TrueNegatives
、
FalsePositives
和
FalseNegatives
是因为这些指标在每个时期结束时
平均
。
Keras 默认情况下不计算每个时期的指标的总和。相反,它计算指标的 运行平均值 ,因为它看到了更多的小批量数据。这就是为什么看到十进制值而不是整数的原因。
让我们分解一下:
- 小批量更新: 在每个时期内,的数据集被分成多个小批量(在本例中为 32)。在处理完每个小批量后,都会根据到目前为止看到的数据计算并更新指标(TP、TN、FP、FN)。
- 运行平均值: 为了给出指标值的表示,Keras 维护一个运行平均值。使用此公式更新此运行平均值:
当前平均值 = ((当前平均值 * (先前看到的样本数)) + (当前小批量指标值)) / (先前看到的样本数 + 当前小批量大小)
- 并非总和: 重要的是,在每个时期结束时显示的值不是所有样本的简单总和,而是在整个时期内计算出的这些指标的平均值的表示。
为什么这些数字不加起来?
正确地观察到 (tp + tn + fp + fn) 的总和不等于样本总数。这是因为:
- 平均值,而非总和: 如前所述,显示的值是平均值,而非总和。
- 类别不平衡: 如果在类别之间的数据不平衡(例如,一个类别中的图像比另一个类别中的多得多),那么即使在考虑平均值后,这些数字也可能不会直接对应于类别总数。
如果希望获得每个时期的指标总和,则需要实现自定义回调函数。 但是,出于大多数目的,使用 Keras 提供的运行平均值就足够了,并且可以很好地了解模型的性能。
标签:python,tensorflow,machine-learning,keras,metrics From: 78787112