¿Cómo obtener precisión, F1, precisión y recuperación para un modelo keras?

21

Quiero calcular la precisión, la recuperación y la puntuación F1 para mi modelo binario KerasClassifier, pero no encuentro ninguna solución.

Aquí está mi código real:

# Split dataset in train and test data 
X_train, X_test, Y_train, Y_test = train_test_split(normalized_X, Y, test_size=0.3, random_state=seed)

# Build the model
model = Sequential()
model.add(Dense(23, input_dim=45, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))

# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])


tensorboard = TensorBoard(log_dir="logs/{}".format(time.time()))

time_callback = TimeHistory()

# Fit the model
history = model.fit(X_train, Y_train, validation_split=0.3, epochs=200, batch_size=5, verbose=1, callbacks=[tensorboard, time_callback]) 

Y luego pronostico nuevos datos de prueba y obtengo la matriz de confusión como esta:

y_pred = model.predict(X_test)
y_pred =(y_pred>0.5)
list(y_pred)

cm = confusion_matrix(Y_test, y_pred)
print(cm)

Pero, ¿hay alguna solución para obtener el puntaje de precisión, el puntaje F1, la precisión y la recuperación? (Si no es complicado, también el puntaje de validación cruzada, pero no es necesario para esta respuesta)

¡Gracias por cualquier ayuda!

ZelelB
fuente

Respuestas:

20

Las métricas se han eliminado del núcleo de Keras. Necesitas calcularlos manualmente. Los eliminaron en la versión 2.0 . Esas métricas son métricas globales, pero Keras funciona en lotes. Como resultado, puede ser más engañoso que útil.

Sin embargo, si realmente los necesita, puede hacerlo así

from keras import backend as K

def recall_m(y_true, y_pred):
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    recall = true_positives / (possible_positives + K.epsilon())
    return recall

def precision_m(y_true, y_pred):
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
    precision = true_positives / (predicted_positives + K.epsilon())
    return precision

def f1_m(y_true, y_pred):
    precision = precision_m(y_true, y_pred)
    recall = recall_m(y_true, y_pred)
    return 2*((precision*recall)/(precision+recall+K.epsilon()))

# compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc',f1_m,precision_m, recall_m])

# fit the model
history = model.fit(Xtrain, ytrain, validation_split=0.3, epochs=10, verbose=0)

# evaluate the model
loss, accuracy, f1_score, precision, recall = model.evaluate(Xtest, ytest, verbose=0)
Tasos
fuente
si pueden ser engañosos, ¿cómo evaluar un modelo de Keras?
ZelelB
1
Dado que Keras calcula esas métricas al final de cada lote, puede obtener resultados diferentes de las métricas "reales". Una forma alternativa sería dividir su conjunto de datos en capacitación y prueba y usar la parte de prueba para predecir los resultados. Luego, como conoce las etiquetas reales, calcule la precisión y recupere manualmente.
Tasos
Taso, ¿puedo sugerirle que vuelva a publicar su respuesta en esta pregunta SO: ¿Cómo debo implementar la precisión y recordar métricas en mi modelo de red neuronal en keras? Saludos, Iraklis
desertnaut
Lo siento, acabo de ver que estaba cerrado :(
desertnaut
¿Alguna idea de por qué esto no funciona en la validación para mí? funciona bien para el entrenamiento.
Rodrigo Ruiz
13

Podrías usar el informe de clasificación scikit-learn . Para convertir sus etiquetas a un formato numérico o binario, eche un vistazo al codificador de etiquetas scikit-learn .

from sklearn.metrics import classification_report

y_pred = model.predict(x_test, batch_size=64, verbose=1)
y_pred_bool = np.argmax(y_pred, axis=1)

print(classification_report(y_test, y_pred_bool))

que le da (salida copiada del ejemplo scikit-learn):

             precision  recall   f1-score    support

 class 0       0.50      1.00      0.67         1
 class 1       0.00      0.00      0.00         1
 class 2       1.00      0.67      0.80         3
matze
fuente
2
Esto es lo que uso, simple y efectivo.
Mateo
2

También puedes probar como se menciona a continuación.

from sklearn.metrics import f1_score, precision_score, recall_score, confusion_matrix
y_pred1 = model.predict(X_test)
y_pred = np.argmax(y_pred1, axis=1)

# Print f1, precision, and recall scores
print(precision_score(y_test, y_pred , average="macro"))
print(recall_score(y_test, y_pred , average="macro"))
print(f1_score(y_test, y_pred , average="macro"))
Ashok Kumar Jayaraman
fuente
0

Pruebe esto: https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_recall_fscore_support.html con Y_test, y_pred como parámetros.

Viacheslav Komisarenko
fuente
Intenté esto: model.recision_recall_fscore_support (Y_test, y_pred, average = 'micro') y obtengo este error en la ejecución: AttributeError: el objeto 'Secuencial' no tiene el atributo 'recision_recall_fscore_support'
ZelelB
No necesita especificar model.recision_recall_fscore_support (), sino recision_recall_fscore_support (Y_test, y_pred, average = 'micro') (sin "model") y asegúrese de tener la importación correcta: desde sklearn.metrics import precision_recall_fscore_support)
Viacheslav Komisarenko