【问题标题】:Custom macro for recall in keras用于在 keras 中调用的自定义宏
【发布时间】:2018-07-22 09:33:04
【问题描述】:

我正在尝试为recall = (recall of class1 + recall of class2)/2 创建一个自定义宏。我想出了以下代码,但我不确定如何计算 0 类的真阳性。

def unweightedRecall():
    def recall(y_true, y_pred):
        # recall of class 1
        true_positives1 = K.sum(K.round(K.clip(y_pred * y_true, 0, 1)))
        possible_positives1 = K.sum(K.round(K.clip(y_true, 0, 1)))
        recall1 = true_positives1 / (possible_positives1 + K.epsilon())

        # --- get true positive of class 0 in true_positives0 here ---
        # Also, is there a cleaner way to get possible_positives0
        possible_positives0 = K.int_shape(y_true)[0] - possible_positives1
        recall0 = true_positives0 / (possible_positives0 + K.epsilon())
        return (recall0 + recall1)/2
    return recall

看来我必须使用Keras.backend.equal(x, y),但是我如何创建一个形状为K.int_shape(y_true)[0] 和所有值的张量,比如x?


编辑 1

基于 Marcin 的 cmets,我想创建一个基于 keras 回调的自定义指标。在 browsing issues in Keras 时,我遇到了以下 f1 指标代码:

class Metrics(keras.callbacks.Callback):
    def on_epoch_end(self, batch, logs={}):
        predict = np.asarray(self.model.predict(self.validation_data[0]))
        targ = self.validation_data[1]
        self.f1s=f1(targ, predict)
        return
metrics = Metrics()
model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, validation_data=[X_test,y_test], 
       verbose=1, callbacks=[metrics])

但是回调如何返回准确性?我想实现unweighted recall = (recall class1 + recall class2)/2。我可以想到以下代码,但希望能帮助我完成它

from sklearn.metrics import recall_score
class Metrics(keras.callbacks.Callback):
    def on_epoch_end(self, batch, logs={}):
        predict = np.asarray(self.model.predict(self.validation_data[0]))
        targ = self.validation_data[1]
        # --- what to store the result in?? ---
        self.XXXX=recall_score(targ, predict, average='macro')
        # we really dont need to return anything ??
        return
metrics = Metrics()
model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, validation_data=[X_test,y_test], 
       verbose=1, callbacks=[metrics])

编辑 2:型号:

def createModelHelper(numNeurons=40, optimizer='adam'):
    inputLayer = Input(shape=(data.shape[1],))
    denseLayer1 = Dense(numNeurons)(inputLayer)
    outputLayer = Dense(1, activation='sigmoid')(denseLayer1)
    model = Model(input=inputLayer, output=outputLayer)
    model.compile(loss=unweightedRecall, optimizer=optimizer)
    return model

【问题讨论】:

  • 使用 keras.metricskeras.losses API. Remember - that the final value of loss or metric is a mean across every batch - but for precision` 和 recall 计算 precisionrecall 时出现问题 - 批次间的平均值不等于最终值度量值。我建议您使用keras.callbacks 来计算适当的值。
  • 感谢您提供的信息! (自定义)回调的任何指针将不胜感激!如果为 (recall class1 + recall class2)/2 实现回调很容易,我将非常感谢您的回答:)

标签: tensorflow machine-learning keras backpropagation precision-recall


【解决方案1】:

keras 版本(带有平均问题)。

你的两个类实际上只是一维输出(0或1)吗?

如果是这样:

def recall(y_true, y_pred):
    # recall of class 1

    #do not use "round" here if you're going to use this as a loss function
    true_positives = K.sum(K.round(y_pred) * y_true)
    possible_positives = K.sum(y_true)
    return true_positives / (possible_positives + K.epsilon())


def unweightedRecall(y_true, y_pred):
    return (recall(y_true,y_pred) + recall(1-y_true,1-y_pred))/2.

现在,如果你的两个类实际上是一个 2 元素输出:

def unweightedRecall(y_true, y_pred):
    return (recall(y_true[:,0],y_pred[:,0]) + recall(y_true[:,1],y_pred[:,1]))/2.

回调版本

对于回调,您可以使用LambdaCallback,然后手动打印或存储结果:

myCallBack = LambdaCallback(on_epoch_end=unweightedRecall)
stored_metrics = []

def unweightedRecall(epoch,logs):
    predict = model.predict(self.validation_data[0])
    targ = self.validation_data[1]

    result = (recall(targ,predict) + recall(1-targ,1-predict))/2. 
    print("recall for epoch " + str(epoch) + ": " + str(result))
    stored_metrics.append(result)

其中recall 是一个使用np 而不是K 的函数。还有epsilon = np.finfo(float).epsepsilon = np.finfo(np.float32).eps)

【讨论】:

  • 非常感谢您的精彩回答!回调版本如何用于model.compile中的metrics参数?我仍然不确定metrics 参数如何将结果与指标相关联。
  • 回调不是一个指标,这就是我们创建stored_metrics列表的原因。
  • 在反向传播阶段,我想使用“未加权召回”来更新权重。如何使用回调函数实现这一点?根据我的理解,我可以使用第一种方法通过将metrics更新为使用unweightedRecall来实现这一点。
  • 您必须使用“损失”函数。 loss = unweightedRecall -- 但这仅适用于 keras 函数,不适用于回调版本。你会遇到 Marcin 提到的问题。但这似乎不是一个相关的问题。毕竟,几乎所有的申请都是分批处理的。
  • 感谢指正!这真的很有帮助:)
猜你喜欢
  • 2018-11-06
  • 2019-06-07
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
  • 2019-11-19
  • 2012-07-24
  • 1970-01-01
相关资源
最近更新 更多