Last active
May 28, 2019 09:54
-
-
Save lmassaron/9e218a3ac53700a34c26e158d6d3e412 to your computer and use it in GitHub Desktop.
Custom metrics for Keras from Scikit-learn
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
| # Custom metrics for Keras from Scikit-learn | |
| from sklearn.metrics import roc_auc_score | |
| from sklearn.metrics import average_precision_score | |
| def auroc(y_true, y_pred): | |
| return tf.py_func(roc_auc_score, (y_true, y_pred), tf.double) | |
| def mAP(y_true, y_pred): | |
| return tf.py_func(average_precision_score, (y_true, y_pred), tf.double) | |
| def balanced_recall(y_true, y_pred): | |
| """ | |
| Computes the average per-column recall metric | |
| for a multi-class classification problem | |
| """ | |
| true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)), axis=0) | |
| possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)), axis=0) | |
| recall = true_positives / (possible_positives + K.epsilon()) | |
| balanced_recall = K.mean(recall) | |
| return balanced_recall | |
| """ | |
| Custom loss functions | |
| def custom_loss_function(y_true, y_pred): | |
| """ | |
| Compute custom loss, returns value | |
| """ | |
| from keras import backend as K | |
| return K.max(K.abs(y_pred - y_true), axis=-1) | |
| model.compile(loss=custom_loss_function, [...]) | |
| """ | |
| # FOCAL LOSS | |
| gamma = 2.0 | |
| epsilon = K.epsilon() | |
| def focal_loss(y_true, y_pred): | |
| pt = y_pred * y_true + (1-y_pred) * (1-y_true) | |
| pt = K.clip(pt, epsilon, 1-epsilon) | |
| CE = -K.log(pt) | |
| FL = K.pow(1-pt, gamma) * CE | |
| loss = K.sum(FL, axis=1) | |
| return loss | |
| # F2 | |
| from keras import backend as K | |
| def f_score(y_true, y_pred, threshold=0.1, beta=2): | |
| tp = tp_score(y_true, y_pred, threshold) | |
| fp = fp_score(y_true, y_pred, threshold) | |
| fn = fn_score(y_true, y_pred, threshold) | |
| precision = tp / (tp + fp) | |
| recall = tp / (tp + fn) | |
| return (1+beta**2) * ((precision * recall) / ((beta**2)*precision + recall)) | |
| def tp_score(y_true, y_pred, threshold=0.1): | |
| tp_3d = K.concatenate( | |
| [ | |
| K.cast(K.expand_dims(K.flatten(y_true)), 'bool'), | |
| K.cast(K.expand_dims(K.flatten(K.greater(y_pred, K.constant(threshold)))), 'bool'), | |
| K.cast(K.ones_like(K.expand_dims(K.flatten(y_pred))), 'bool') | |
| ], axis=1 | |
| ) | |
| tp = K.sum(K.cast(K.all(tp_3d, axis=1), 'int32')) | |
| return tp | |
| def fp_score(y_true, y_pred, threshold=0.1): | |
| fp_3d = K.concatenate( | |
| [ | |
| K.cast(K.expand_dims(K.flatten(K.abs(y_true - K.ones_like(y_true)))), 'bool'), | |
| K.cast(K.expand_dims(K.flatten(K.greater(y_pred, K.constant(threshold)))), 'bool'), | |
| K.cast(K.ones_like(K.expand_dims(K.flatten(y_pred))), 'bool') | |
| ], axis=-1 | |
| ) | |
| fp = K.sum(K.cast(K.all(fp_3d, axis=1), 'int32')) | |
| return fp | |
| def fn_score(y_true, y_pred, threshold=0.1): | |
| fn_3d = K.concatenate( | |
| [ | |
| K.cast(K.expand_dims(K.flatten(y_true)), 'bool'), | |
| K.cast(K.expand_dims(K.flatten(K.abs(K.cast(K.greater(y_pred, K.constant(threshold)), 'float') - K.ones_like(y_pred)))), 'bool'), | |
| K.cast(K.ones_like(K.expand_dims(K.flatten(y_pred))), 'bool') | |
| ], axis=1 | |
| ) | |
| fn = K.sum(K.cast(K.all(fn_3d, axis=1), 'int32')) | |
| return fn | |
| def precision_score(y_true, y_pred, threshold=0.1): | |
| tp = tp_score(y_true, y_pred, threshold) | |
| fp = fp_score(y_true, y_pred, threshold) | |
| return tp / (tp + fp) | |
| def recall_score(y_true, y_pred, threshold=0.1): | |
| tp = tp_score(y_true, y_pred, threshold) | |
| fn = fn_score(y_true, y_pred, threshold) | |
| return tp / (tp + fn) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment