web-dev-qa-db-fra.com

comment implémenter une métrique personnalisée dans les keras?

Je reçois cette erreur:

sum () a obtenu un argument de mot clé inattendu 'out'

quand j'exécute ce code:

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)

Est-il possible d'implémenter une métrique personnalisée en plus de faire une boucle sur des lots et d'éditer le code source?

18
Philippe C

Ce code ne fonctionne pas car y_pred et y_true ne sont pas des tableaux numpy mais des tenseurs Theano ou Tensor Flow. C'est pourquoi vous avez cette erreur.

Vous pouvez définir vos métriques personnalisées, mais vous devez vous rappeler que ses arguments sont ces tenseurs - pas des tableaux numpy.

9
Marcin Możejko

Ici, je réponds à la question du sujet d'OP plutôt qu'à son problème exact. Je fais cela car la question apparaît en haut lorsque je recherche le problème du sujet sur Google.

Vous pouvez implémenter une métrique personnalisée de deux manières.

  1. Comme mentionné dans Keras doc .

    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])
    

    Mais ici, vous devez vous rappeler, comme mentionné dans la réponse de Marcin Możejko, que y_true et y_pred sont des tenseurs. Donc, pour calculer correctement la métrique, vous devez utiliser keras.backend fonctionnalité. Veuillez regarder cette SO question pour plus de détails Comment calculer la macro F1 dans Keras?

  2. Ou vous pouvez l'implémenter de manière hacky comme mentionné dans problème Keras GH . Pour cela, vous devez utiliser l'argument callbacks de model.fit.

    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()
    
20
vogdb

vous pouvez passer un model.predict () dans votre fonction métrique AUC. [cela itérera sur les bactéries afin que vous fassiez mieux d'utiliser model.predict_on_batch (). En supposant que vous ayez quelque chose comme une couche softmax en sortie (quelque chose qui génère des probabilités), vous pouvez l'utiliser avec sklearn.metric pour obtenir l'AUC.

from sklearn.metrics import roc_curve, auc

de ici

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)

faites maintenant votre métrique

# 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 )
4
ahmedhosny