keras Tensorflow:自定义损失函数,以鼓励/限制误报/漏报

rn0zuynd  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(100)

我正在寻找一种方法来鼓励/限制假阳性/阴性。我一直无法找到一个解决方案,我可以得到工作-最有可能是由于我缺乏经验。
我发现这篇文章:Custom loss function in Keras to penalize false negatives,它几乎有相同的目的,但我不能得到工作的答案。
首先,我一直在得到这个错误:

属性错误:“Tensor”对象没有属性“_numpy”

经过一番搜索,我发现它可以解决与 ”model.run_early = True”,这虽然提供了这个错误:

  • 没有为任何变量提供梯度 *

我不想使用 ”model.run_early = True”,因为我不完全确定它是做什么的,但很明显,它使我需要做一些计算梯度的事情。因此,我修改了代码,但仍然得到 * 没有为任何变量提供梯度 *。
我举了一个例子:

import tensorflow as tf
import tensorflow.keras.backend as K

from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

class Custom_loss_Class(tf.keras.losses.Loss):
    def __init__(self, recall_weight = 0.5, spec_weight = 0.5, name="custom"):
        super().__init__(name=name)
        self.recall_weight = recall_weight
        self.spec_weight = spec_weight

    def call(self, y_true, y_pred):
        y_pred = tf.math.round(y_pred)
        y_true = tf.math.round(y_true)

        TN = tf.dtypes.cast(tf.math.logical_and(tf.math.equal(y_true, 0), tf.math.equal(y_pred, 0)), tf.float32)
        TP = tf.dtypes.cast(tf.math.logical_and(tf.math.equal(y_true, 1), tf.math.equal(y_pred, 1)), tf.float32)

        FP = tf.dtypes.cast(tf.math.logical_and(tf.math.equal(y_true, 0), tf.math.equal(y_pred, 1)), tf.float32)
        FN = tf.dtypes.cast(tf.math.logical_and(tf.math.equal(y_true, 1), tf.math.equal(y_pred, 0)), tf.float32)

        TN = tf.reduce_sum(TN)
        TP = tf.reduce_sum(TP)

        FP = tf.reduce_sum(FP)
        FN = tf.reduce_sum(FN)

        specificity = TN / (TN + FP + K.epsilon())
        recall = TP / (TP + FN + K.epsilon())

        loss = tf.Variable(1- (self.recall_weight * recall + self.spec_weight * specificity))

        return loss

data = load_breast_cancer()

X_train, X_test, Y_train, Y_test = train_test_split(data.data, data.target, test_size=0.3)
N, D = X_train.shape

scalar = StandardScaler()
X_train = scalar.fit_transform(X_train)
X_test = scalar.transform(X_test)

i = Input(shape=(D,))
x = Dense(64, activation="relu")(i)
x = Dense(1, activation="sigmoid")(x)

model = Model(i, x)

model.compile(optimizer="adam", 
          loss=Custom_loss_Class(recall_weight=0.1, spec_weight=0.9), 
          metrics="accuracy")

r = model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=10)

我知道我可以使用 class_weight 来给予多一个类的权重,但这并不是我真正想要的。在这个例子中,我想严格限制假阴性,这样癌症患者就不会得到阴性预测,但同时也不会得到太多的假阳性。这似乎是一个常见的用例,因此我希望有人为它做了一个好的功能。

编辑

我知道这很可能是由于我的损失函数不可微,但我不知道如何改变,所以我得到了所描述的功能。

pb3skfrl

pb3skfrl1#

我知道这是很久以前的事了,但可能有人也有同样的问题。我也遇到了同样的问题,我通过计算找到了解决办法

TP =  tf.reduce_sum(y_true * y_pred)

在图像建模中,我们没有TN,因为我们仅限于地面实况和预测图像,因此:

FN = tf.reduce_sum(y_true) - TP

FP = tf.reduce_sum(y_pred) - TP

和,

specificity = TN / (TN + FP + K.epsilon())

recall = TP / (TP + FN + K.epsilon())

相关问题