@@ -200,7 +200,7 @@ def reset_metrics(self):
200
200
self .accuracies = []
201
201
self .precisions = []
202
202
self .recalls = []
203
- self .mccs = []
203
+ self .f1_scores = []
204
204
205
205
206
206
class Classifier (Estimator ):
@@ -388,7 +388,8 @@ def evaluate_dataset(self, filepath, min_score=0.6,
388
388
logging .info ("Recall (real elements that are predicted): %.2f%%" ,
389
389
result ['recall' ] * 100 )
390
390
logging .info ("Score: %.2f%%" , result ['score' ] * 100 )
391
- logging .info ("Score standard deviation: %.4f" , result ['acc_deviation' ])
391
+ logging .info ("Score standard deviation: %.4f" ,
392
+ result ['score_deviation' ])
392
393
393
394
return result
394
395
@@ -420,35 +421,12 @@ def rate_prediction(self, classifier, X_test, y_test):
420
421
self .roc_curve_plot .add (fpr , tpr , 'Positives' )
421
422
422
423
# Calculate accuracy, sensitivity and specificity.
423
- mcc = self .get_mcc (y_test , y_pred )
424
-
425
- [acc , prec , rec ] = self .calculate_metrics (y_test == 1 , y_pred == 1 )
426
-
424
+ [acc , prec , rec , f1_score ] = self .calculate_metrics (
425
+ y_test == 1 , y_pred == 1 )
427
426
self .accuracies .append (acc )
428
427
self .precisions .append (prec )
429
428
self .recalls .append (rec )
430
- self .mccs .append (mcc )
431
-
432
- @staticmethod
433
- def get_mcc (y_true , y_pred ):
434
- C = confusion_matrix (y_true , y_pred )
435
- t_sum = C .sum (axis = 1 , dtype = np .float64 )
436
- p_sum = C .sum (axis = 0 , dtype = np .float64 )
437
- n_correct = np .trace (C , dtype = np .float64 )
438
- n_samples = p_sum .sum ()
439
- cov_ytyp = n_correct * n_samples - np .dot (t_sum , p_sum )
440
- cov_ypyp = n_samples ** 2 - np .dot (p_sum , p_sum )
441
- cov_ytyt = n_samples ** 2 - np .dot (t_sum , t_sum )
442
- denominator = np .sqrt (cov_ytyt * cov_ypyp )
443
- if denominator != 0 :
444
- mcc = cov_ytyp / np .sqrt (cov_ytyt * cov_ypyp )
445
- else :
446
- return 0.
447
-
448
- if np .isnan (mcc ):
449
- return 0.
450
- else :
451
- return mcc
429
+ self .f1_scores .append (f1_score )
452
430
453
431
@staticmethod
454
432
def get_score (classifier , X_test , y_test ):
@@ -487,36 +465,37 @@ def calculate_metrics(y_test_true, y_pred_true):
487
465
else :
488
466
recall = 0
489
467
490
- return [accuracy , precision , recall ]
468
+ if precision + recall != 0 :
469
+ f1_score = 2 * precision * recall / (precision + recall )
470
+ else :
471
+ f1_score = 0
472
+
473
+ return [accuracy , precision , recall , f1_score ]
491
474
492
475
def get_evaluation_results (self , min_score , accepted_deviation ):
493
476
"""Returns the evaluation results after all iterations"""
494
477
495
478
avg_accuracy = np .mean (self .accuracies )
496
479
avg_precision = np .mean (self .precisions )
497
480
avg_recall = np .mean (self .recalls )
498
- avg_mcc = np .mean (self .mccs )
499
- if len (self .aucs ) > 0 :
500
- avg_aucs = np .mean (self .aucs )
501
- else :
502
- avg_aucs = 0
503
-
504
- # MCC goes from -1 to 1 we need to transform it to a value between
505
- # 0 and 1 to compare it with the minimum score provided.
506
- score = (avg_mcc + 1 ) / 2
507
481
508
- if len (self .mccs ) > 0 :
509
- acc_deviation = np .std (self .mccs )
482
+ if len (self .f1_scores ) > 0 :
483
+ score = np .mean (self .f1_scores )
484
+ score_deviation = np .std (self .f1_scores )
510
485
else :
511
- acc_deviation = 1
486
+ score = 0
487
+ score_deviation = 1
488
+
512
489
result = dict ()
513
- if self .is_binary :
490
+ if self .is_binary and len ( self . aucs ) > 0 :
514
491
result ['auc' ] = np .mean (self .aucs )
515
492
result ['auc_deviation' ] = np .std (self .aucs )
493
+
516
494
result ['accuracy' ] = avg_accuracy
517
495
result ['precision' ] = avg_precision
518
496
result ['recall' ] = avg_recall
519
- result ['acc_deviation' ] = acc_deviation
497
+ result ['f1_score' ] = score
498
+ result ['score_deviation' ] = score_deviation
520
499
result ['score' ] = score
521
500
result ['min_score' ] = min_score
522
501
result ['accepted_deviation' ] = accepted_deviation
@@ -527,11 +506,11 @@ def get_evaluation_results(self, min_score, accepted_deviation):
527
506
528
507
# If deviation is too high we may need more records to report if
529
508
# this model is reliable or not.
530
- if acc_deviation > accepted_deviation :
509
+ if score_deviation > accepted_deviation :
531
510
result ['info' ].append ('The evaluation results varied too much, ' +
532
511
'we might need more samples to check if this ' +
533
512
'model is valid. Model deviation = ' +
534
- str (acc_deviation ) +
513
+ str (score_deviation ) +
535
514
', accepted deviation = ' +
536
515
str (accepted_deviation ))
537
516
result ['status' ] = NOT_ENOUGH_DATA
@@ -543,7 +522,7 @@ def get_evaluation_results(self, min_score, accepted_deviation):
543
522
str (min_score ))
544
523
result ['status' ] = LOW_SCORE
545
524
546
- if acc_deviation > accepted_deviation and score < min_score :
525
+ if score_deviation > accepted_deviation and score < min_score :
547
526
result ['status' ] = LOW_SCORE + NOT_ENOUGH_DATA
548
527
549
528
return result
0 commit comments