-
-
Save jgera/52192736f90868fd0a0afa2bfb7159ef to your computer and use it in GitHub Desktop.
Custom Metrics for Keras and TensorFlow
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import tensorflow as tf | |
from keras import backend as K | |
def recall(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_keras = true_positives / (possible_positives + K.epsilon()) | |
return recall_keras | |
def precision(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_keras = true_positives / (predicted_positives + K.epsilon()) | |
return precision_keras | |
def specificity(y_true, y_pred): | |
tn = K.sum(K.round(K.clip((1 - y_true) * (1 - y_pred), 0, 1))) | |
fp = K.sum(K.round(K.clip((1 - y_true) * y_pred, 0, 1))) | |
return tn / (tn + fp + K.epsilon()) | |
def negative_predictive_value(y_true, y_pred): | |
tn = K.sum(K.round(K.clip((1 - y_true) * (1 - y_pred), 0, 1))) | |
fn = K.sum(K.round(K.clip(y_true * (1 - y_pred), 0, 1))) | |
return tn / (tn + fn + K.epsilon()) | |
def f1(y_true, y_pred): | |
p = precision(y_true, y_pred) | |
r = recall(y_true, y_pred) | |
return 2 * ((p * r) / (p + r + K.epsilon())) | |
def fbeta(y_true, y_pred, beta=2): | |
y_pred = K.clip(y_pred, 0, 1) | |
tp = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)), axis=1) | |
fp = K.sum(K.round(K.clip(y_pred - y_true, 0, 1)), axis=1) | |
fn = K.sum(K.round(K.clip(y_true - y_pred, 0, 1)), axis=1) | |
p = tp / (tp + fp + K.epsilon()) | |
r = tp / (tp + fn + K.epsilon()) | |
num = (1 + beta ** 2) * (p * r) | |
den = (beta ** 2 * p + r + K.epsilon()) | |
return K.mean(num / den) | |
def matthews_correlation_coefficient(y_true, y_pred): | |
tp = K.sum(K.round(K.clip(y_true * y_pred, 0, 1))) | |
tn = K.sum(K.round(K.clip((1 - y_true) * (1 - y_pred), 0, 1))) | |
fp = K.sum(K.round(K.clip((1 - y_true) * y_pred, 0, 1))) | |
fn = K.sum(K.round(K.clip(y_true * (1 - y_pred), 0, 1))) | |
num = tp * tn - fp * fn | |
den = (tp + fp) * (tp + fn) * (tn + fp) * (tn + fn) | |
return num / K.sqrt(den + K.epsilon()) | |
def equal_error_rate(y_true, y_pred): | |
n_imp = tf.count_nonzero(tf.equal(y_true, 0), dtype=tf.float32) + tf.constant(K.epsilon()) | |
n_gen = tf.count_nonzero(tf.equal(y_true, 1), dtype=tf.float32) + tf.constant(K.epsilon()) | |
scores_imp = tf.boolean_mask(y_pred, tf.equal(y_true, 0)) | |
scores_gen = tf.boolean_mask(y_pred, tf.equal(y_true, 1)) | |
loop_vars = (tf.constant(0.0), tf.constant(1.0), tf.constant(0.0)) | |
cond = lambda t, fpr, fnr: tf.greater_equal(fpr, fnr) | |
body = lambda t, fpr, fnr: ( | |
t + 0.001, | |
tf.divide(tf.count_nonzero(tf.greater_equal(scores_imp, t), dtype=tf.float32), n_imp), | |
tf.divide(tf.count_nonzero(tf.less(scores_gen, t), dtype=tf.float32), n_gen) | |
) | |
t, fpr, fnr = tf.while_loop(cond, body, loop_vars, back_prop=False) | |
eer = (fpr + fnr) / 2 | |
return eer |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment