我有一些数据集,它们有两个类。当我尝试使用某些度量时——例如,tf.keras.metrics.AUC
、tf.keras.metrics.FalseNegatives
、tf.keras.metrics.FalsePositives
、tf.keras.metrics.TrueNegatives
或tf.keras.metrics.TruePositives
——我会得到类似于的错误
ValueError: Shapes (None, None, None, 2) and (None, 1) are incompatible.
我想我可以使用tfa.metrics.MultiLabelConfusionMatrix
并为PR和ROC编写自己的AUC。但说真的,我只有两节课。AFAIK,两个类相当于一个类。
如何将tfrecords分解为一个类?
完整地说,这里有一个完整的工作示例来重新创建这个错误,从导入、全局和争用开始:
from tempfile import mkdtemp
from os import path, mkdir
from shutil import rmtree
import tensorflow as tf
import numpy as np
from PIL import Image
NUM_CLASSES = 2
INPUT_SHAPE = 32, 32, 3
def create_random_ds(tempdir):
for class_num in range(NUM_CLASSES):
directory = path.join(tempdir, 'class{}'.format(class_num))
mkdir(directory)
for i in range(20):
Image
.fromarray((np.random.rand(100,100,3) * 255).astype('uint8'))
.convert('RGBA')
.save(path.join(directory, 'image{}.png'.format(i)))
return tf.keras.preprocessing.image_dataset_from_directory(
tempdir, labels='inferred', label_mode='int',
)
tempdirs = mkdtemp(), mkdtemp()
train_dataset = create_random_ds(tempdirs[0])
validation_dataset = create_random_ds(tempdirs[1])
然后CNN模型构建:
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(INPUT_SHAPE[0], (INPUT_SHAPE[-1], INPUT_SHAPE[-1]),
activation='relu', ),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(NUM_CLASSES)
])
最后是肉:
try:
model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=False),
optimizer=tf.keras.optimizers.RMSprop(),
metrics=['accuracy', tf.keras.metrics.AUC(curve="PR")
])
model.fit(train_dataset,
epochs=2,
validation_data=validation_dataset)
finally:
for directory in tempdirs:
rmtree(directory)
ValueError: Shapes (None, 2) and (None, 1) are incompatible
由于您想将模型输出的形状从2更改为1,以下是您可以做的。
更改型号的最后一行
tf.keras.layers.Dense(NUM_CLASSES)
至
tf.keras.layers.Dense(1, activation='sigmoid')
这将使您的模型与AUC指标兼容。
另外,这里需要注意的是,两个类等价于一个类,但不等价于输出层的形状。你可以训练你的二进制分类模型,输出层有两个值,而不是一个,反之亦然,但在计算值时,你需要考虑形状。