2017-01-04 12 views
9

Buduję niestandardową metrykę, aby zmierzyć dokładność jednej klasy w moim wieloklasowym zbiorze danych podczas treningu. Mam problem z wyborem klasy.Keras Custom Metric dla pojedynczej dokładności klasy

Cele są jednym gorąco (np: klasa 0 etykieta jest [1 0 0 0 0].

from keras import backend as K 

def single_class_accuracy(y_true, y_pred): 
    idx = bool(y_true[:, 0])    # boolean mask for class 0 
    class_preds = y_pred[idx] 
    class_true = y_true[idx] 
    class_acc = K.mean(K.equal(K.argmax(class_true, axis=-1), K.argmax(class_preds, axis=-1))) # multi-class accuracy 
    return class_acc 

Kłopot w tym, musimy użyć funkcji Keras do tensorów indeksu Jak utworzyć ? logiczną maska ​​dla tensora Dziękuję

+0

ja nie znam Keras i nie wiem, czy twój kod będzie działał z maskami boolowskimi czy jawnymi indeksami. Czy rzuciłeś maskę, aby wpisać boolean? tf.cast (binary_mask, tf.bool). Za pomocą Theano możesz użyć funkcji bool_mask.nonzero(), aby uzyskać indeksy maski boolowskiej. Daj nam znać, czy to rozwiązanie działa. – rafaelvalle

+0

Czy zaakceptowałbyś odpowiedź, która używa wywołania zwrotnego? –

+0

Aby się upewnić - y_true jest 2D? co mają reprezentować wiersze i kolumny? – ginge

Odpowiedz

8

Zauważ, że gdy mówimy o dokładności jednej klasy jeden może odnosić się do jednej z następujących (nie odpowiednik) dwóch kwot:.

  • dokładność, co dla klasy C jest stosunek przykładach oznaczonych klasy C że przewiduje się posiadają stopień C.
  • przywołanie, co dla klasy C jest stosunek przykładach przewiduje się klasy C, które są w rzeczywistości oznaczonego klasy C.

Zamiast wykonywać skomplikowane indeksowanie, możesz po prostu polegać na maskowaniu w celu obliczenia. Zakładając, że mówimy tu o precyzji (zmiana na przywołanie byłaby trywialna).

from keras import backend as K 

INTERESTING_CLASS_ID = 0 # Choose the class of interest 

def single_class_accuracy(y_true, y_pred): 
    class_id_true = K.argmax(y_true, axis=-1) 
    class_id_preds = K.argmax(y_pred, axis=-1) 
    # Replace class_id_preds with class_id_true for recall here 
    accuracy_mask = K.cast(K.equal(class_id_preds, INTERESTING_CLASS_ID), 'int32') 
    class_acc_tensor = K.cast(K.equal(class_id_true, class_id_preds), 'int32') * accuracy_mask 
    class_acc = K.sum(class_acc_tensor)/K.maximum(K.sum(accuracy_mask), 1) 
    return class_acc 

Jeśli chcesz być bardziej elastyczne, można również klasę zainteresowania sparametryzowane:

from keras import backend as K 

def single_class_accuracy(interesting_class_id): 
    def fn(y_true, y_pred): 
     class_id_true = K.argmax(y_true, axis=-1) 
     class_id_preds = K.argmax(y_pred, axis=-1) 
     # Replace class_id_preds with class_id_true for recall here 
     accuracy_mask = K.cast(K.equal(class_id_preds, interesting_class_id), 'int32') 
     class_acc_tensor = K.cast(K.equal(class_id_true, class_id_preds), 'int32') * accuracy_mask 
     class_acc = K.sum(class_acc_tensor)/K.maximum(K.sum(accuracy_mask), 1) 
     return class_acc 
    return fn 

a używać go jako:

model.compile(..., metrics=[single_class_accuracy(INTERESTING_CLASS_ID)]) 
+3

Precyzja i odwołanie można łączyć, ta miara nazywa się wynikiem F1. Jest to harmoniczna średnia precyzji i zapamiętywania i jest miarą dokładności testu. –

+0

Należy jednak pamiętać, że wynik F1 (a także precyzja i wycofanie) nie uwzględniają prawdziwych negatywów. Jest wysoce zależny od tego, co faktycznie robi się, aby wybrać odpowiednią metrykę. –

+0

co to jest class_num_true? – modesitt

Powiązane problemy