【问题标题】:how to implement custom metric in keras?如何在 keras 中实现自定义指标?
【发布时间】:2016-10-06 01:13:54
【问题描述】:

我得到这个错误:

sum() 得到了一个意外的关键字参数 'out'

当我运行这段代码时:

import pandas as pd, numpy as np
import keras
from keras.layers.core import Dense, Activation
from keras.models import Sequential

def AUC(y_true,y_pred):
    not_y_pred=np.logical_not(y_pred)
    y_int1=y_true*y_pred
    y_int0=np.logical_not(y_true)*not_y_pred
    TP=np.sum(y_pred*y_int1)
    FP=np.sum(y_pred)-TP
    TN=np.sum(not_y_pred*y_int0)
    FN=np.sum(not_y_pred)-TN
    TPR=np.float(TP)/(TP+FN)
    FPR=np.float(FP)/(FP+TN)
    return((1+TPR-FPR)/2)

# Input datasets

train_df = pd.DataFrame(np.random.rand(91,1000))
train_df.iloc[:,-2]=(train_df.iloc[:,-2]>0.8)*1


model = Sequential()
model.add(Dense(output_dim=60, input_dim=91, init="glorot_uniform"))
model.add(Activation("sigmoid"))
model.add(Dense(output_dim=1, input_dim=60, init="glorot_uniform"))
model.add(Activation("sigmoid"))

model.compile(optimizer='rmsprop',loss='binary_crossentropy',metrics=[AUC])


train_df.iloc[:,-1]=np.ones(train_df.shape[0]) #bias
X=train_df.iloc[:,:-1].values
Y=train_df.iloc[:,-1].values
print X.shape,Y.shape

model.fit(X, Y, batch_size=50,show_accuracy = False, verbose = 1)

除了批量循环和编辑源代码之外,是否可以实现自定义指标?

【问题讨论】:

    标签: python neural-network deep-learning keras metrics


    【解决方案1】:

    问题在于 y_predy_true 不是 NumPy 数组,而是 Theano 或 TensorFlow 张量。这就是您收到此错误的原因。

    您可以定义自定义指标,但您必须记住,它的参数是那些张量,而不是 NumPy 数组。

    【讨论】:

    • 您能否详细说明如何解决这个问题?如何将张量转换为 numpy 数组?
    • 您需要将张量视为代数变量。您不能将 numpy 数组转换为张量。您只能将 numpy 数组分配为张量的值。
    • 我不想将 numpy 数组转换为张量,但反过来。如果我们采用 OP 的功能,我尝试了:def AUC(y_true,y_pred): numpy_y_true = y_true.eval() ... return ... 但它没有用。您将如何解决 OP 的问题?
    • 自定义指标不能是典型的数字返回函数。甚至 "def auc(y_true, y_pred): return 1.0" 也不起作用。在看到任何训练示例之前,度量函数在编译时被调用一次。
    • 确实如此。但是输入仍然需要是张量
    【解决方案2】:

    在这里,我回答的是 OP 的主题问题,而不是他的确切问题。我这样做是因为当我用谷歌搜索主题问题时,问题会显示在顶部。

    您可以通过两种方式实现自定义指标。

    1. Keras docu 中所述。

      import keras.backend as K
      
      def mean_pred(y_true, y_pred):
          return K.mean(y_pred)
      
      model.compile(optimizer='sgd',
                loss='binary_crossentropy',
                metrics=['accuracy', mean_pred])
      

      但在这里你必须记住,正如 Marcin Możejko 的回答中提到的那样,y_truey_pred 是张量。因此,为了正确计算您需要使用keras.backend 功能的指标。详情请看这个 SO question How to calculate F1 Macro in Keras?

    2. 或者你可以用Keras GH issue 中提到的hacky 方式来实现它。为此,您需要使用model.fitcallbacks 参数。

      import keras as keras
      import numpy as np
      from keras.optimizers import SGD
      from sklearn.metrics import roc_auc_score
      
      model = keras.models.Sequential()
      # ...
      sgd = SGD(lr=0.001, momentum=0.9)
      model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy'])
      
      
      class Metrics(keras.callbacks.Callback):
          def on_train_begin(self, logs={}):
              self._data = []
      
          def on_epoch_end(self, batch, logs={}):
              X_val, y_val = self.validation_data[0], self.validation_data[1]
              y_predict = np.asarray(model.predict(X_val))
      
              y_val = np.argmax(y_val, axis=1)
              y_predict = np.argmax(y_predict, axis=1)
      
              self._data.append({
                  'val_rocauc': roc_auc_score(y_val, y_predict),
              })
              return
      
          def get_data(self):
              return self._data
      
      metrics = Metrics()
      history = model.fit(X_train, y_train, epochs=100, validation_data=(X_val, y_val), callbacks=[metrics])
      metrics.get_data()
      

    【讨论】:

    • 我建议使用 self.model 而不是 model 以便可以将此类隐藏在不同的文件中。
    • @对于使用大型验证数据集的人,您将面临两倍的验证时间。一项由 keras 完成验证,一项由您的指标通过调用 predict 完成。另一个问题是现在您的指标使用 GPU 进行预测,而 cpu 使用 numpy 计算指标,因此 GPU 和 CPU 是串行的。如果指标计算成本很高,您将面临更差的 GPU 利用率,并且必须进行已经在 keras 中完成的优化。
    • @saurabheights 任何解决方法,然后使用回调
    • 当我使用这段代码时,我认为validation_data不会传递给on_epoch_end方法,它说None type not subscriptable
    • 这种技术效果很好。提示:使用y_predict = np.asarray(model.predict(X_val, batch_size=32768)) 减少预测时间,在我的例子中它从 14 秒变为 0.40 秒。
    【解决方案3】:

    您可以在 AUC 度量函数中传递 model.predict()。 [这将在 bacthes 上进行迭代,因此您最好使用 model.predict_on_batch()。假设你有类似 softmax 层的东西作为输出(输出概率的东西),那么你可以将它与 sklearn.metric 一起使用来获得 AUC。

    from sklearn.metrics import roc_curve, auc
    

    来自here

    def sklearnAUC(test_labels,test_prediction):
        n_classes = 2
        # Compute ROC curve and ROC area for each class
        fpr = dict()
        tpr = dict()
        roc_auc = dict()
        for i in range(n_classes):
            # ( actual labels, predicted probabilities )
            fpr[i], tpr[i], _ = roc_curve(test_labels[:, i], test_prediction[:, i])
            roc_auc[i] = auc(fpr[i], tpr[i])
    
        return round(roc_auc[0],3) , round(roc_auc[1],3)
    

    现在制定您的指标

    # gives a numpy array like so [ [0.3,0.7] , [0.2,0.8] ....]    
    Y_pred = model.predict_on_batch ( X_test  ) 
    # Y_test looks something like [ [0,1] , [1,0] .... ]
    # auc1 and auc2 should be equal
    auc1 , auc2 = sklearnAUC(  Y_test ,  Y_pred )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-14
      • 2020-02-05
      • 2017-10-02
      相关资源
      最近更新 更多