Como obter precisão, F1, precisão e recall, para um modelo keras?

20

Quero calcular a precisão, recall e pontuação F1 para o meu modelo binário KerasClassifier, mas não encontro nenhuma solução.

Aqui está o meu 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]) 

E então estou prevendo novos dados de teste e obtendo a matriz de confusão 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)

Mas existe alguma solução para obter a pontuação de precisão, a pontuação de F1, a precisão e o recall? (Se não for complicado, também a pontuação da validação cruzada, mas não é necessária para esta resposta)

Obrigado por qualquer ajuda!

ZelelB
fonte

Respostas:

20

As métricas foram removidas do núcleo Keras. Você precisa calculá-los manualmente. Eles os removeram na versão 2.0 . Essas métricas são todas globais, mas o Keras trabalha em lotes. Como resultado, pode ser mais enganoso do que útil.

No entanto, se você realmente precisa deles, pode fazê-lo assim

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
fonte
se eles podem ser enganosos, como avaliar um modelo de Keras?
ZelelB
1
Como o Keras calcula essas métricas no final de cada lote, você pode obter resultados diferentes das métricas "reais". Uma maneira alternativa seria dividir seu conjunto de dados em treinamento e teste e usar a parte de teste para prever os resultados. Então, como você conhece os rótulos reais, calcule a precisão e recupere manualmente.
Tasos
Portanto, gostaria de sugerir que você publique novamente sua resposta nesta pergunta do SO: Como devo implementar métricas de precisão e recuperação no meu modelo de rede neural em keras? Cheers, Iraklis
desertnaut 26/09/19
Desculpe, acabei de ver que estava fechado :(
desertnaut 27/09/19
Alguma idéia de por que isso não está funcionando na validação para mim? funciona bem para treinamento.
Rodrigo Ruiz
13

Você pode usar o relatório de classificação do scikit-learn . Para converter seus rótulos em um formato numérico ou binário, dê uma olhada no codificador de rótulos 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 fornece a você (saída copiada do exemplo do 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
fonte
2
É isso que eu uso, simples e eficaz.
6186 Matthew
2

Você também pode tentar conforme mencionado abaixo.

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
fonte
0

Tente o seguinte: https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_recall_fscore_support.html com Y_test, y_pred como parâmetros.

Viacheslav Komisarenko
fonte
Eu tentei o seguinte: model.recision_recall_fscore_support (Y_test, y_pred, average = 'micro') e recebo este erro na execução: AttributeError: o objeto 'Sequential' não tem atributo 'recision_recall_fscore_support'
ZelelB
Você não precisa especificar model.recision_recall_fscore_support (), apenas recision_recall_fscore_support (Y_test, y_pred, average = 'micro') (sem "model") (sem "model") e verifique se você tem a importação correta: de sklearn.metrics import precision_recall_fscore_support
Viacheslav Komisarenko 6/02/19