我正在训练一个网络,用Keras进行语义分割 . 通常,数据集包含void / unlabeled类 . 在论文中,这门课总是被忽略 . 这意味着网络不会将任何像素预测为无效,并且在计算度量时会忽略实际无效的像素 .
简而言之,我希望网络不能预测给定的类 . 在混淆矩阵中,这意味着给定类的一行0:
[[ 0 0 0]
[ 553 109791 310]
[ 121 1756 264292]]
由于 fit_generator
中的 class_weight
参数不支持3维数据,而我的输入数据是4D(批量,高度,宽度,类),我现在尝试创建一个自定义损失函数来计算加权分类交叉熵 . 实施:
def weighted_categorical_crossentropy(class_weights):
tf_weights = tf.convert_to_tensor(class_weights, np.float32)
def run(y_true, y_pred):
# scale preds so that the class probas of each sample sum to 1
y_pred /= tf.reduce_sum(y_pred, -1, True)
# manual computation of crossentropy
_epsilon = tf.convert_to_tensor(1e-7, y_pred.dtype.base_dtype)
output = tf.clip_by_value(y_pred, _epsilon, 1. - _epsilon)
return - tf.reduce_sum(tf.multiply(y_true * tf.log(output), tf_weights), -1)
return run
该实现非常类似于tensorflow backend和TensorFlow: Implementing a class-wise weighted cross entropy loss?中的 categorical_crossentropy
,因为我的模型的最后一层是Softmax层 .
用法: model.compile(optimizer=optim, loss=weighted_categorical_crossentropy(class_weights), metrics='accuracy')
.
根据我的测试,属于具有类权重0的void类的像素总是如预期的那样丢失0 . 问题是网络仍然预测像素为空 .
我究竟做错了什么?