Skip to content

Commit 03192c3

Browse files
authored
Merge pull request #13 from dmonllao/MDL-66476
MDL-66476
2 parents 40ecbed + 14a4632 commit 03192c3

File tree

2 files changed

+26
-47
lines changed

2 files changed

+26
-47
lines changed

moodlemlbackend/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.2.1
1+
2.3.0

moodlemlbackend/processor/estimator.py

Lines changed: 25 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def reset_metrics(self):
200200
self.accuracies = []
201201
self.precisions = []
202202
self.recalls = []
203-
self.mccs = []
203+
self.f1_scores = []
204204

205205

206206
class Classifier(Estimator):
@@ -388,7 +388,8 @@ def evaluate_dataset(self, filepath, min_score=0.6,
388388
logging.info("Recall (real elements that are predicted): %.2f%%",
389389
result['recall'] * 100)
390390
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'])
392393

393394
return result
394395

@@ -420,35 +421,12 @@ def rate_prediction(self, classifier, X_test, y_test):
420421
self.roc_curve_plot.add(fpr, tpr, 'Positives')
421422

422423
# 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)
427426
self.accuracies.append(acc)
428427
self.precisions.append(prec)
429428
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)
452430

453431
@staticmethod
454432
def get_score(classifier, X_test, y_test):
@@ -487,36 +465,37 @@ def calculate_metrics(y_test_true, y_pred_true):
487465
else:
488466
recall = 0
489467

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]
491474

492475
def get_evaluation_results(self, min_score, accepted_deviation):
493476
"""Returns the evaluation results after all iterations"""
494477

495478
avg_accuracy = np.mean(self.accuracies)
496479
avg_precision = np.mean(self.precisions)
497480
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
507481

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)
510485
else:
511-
acc_deviation = 1
486+
score = 0
487+
score_deviation = 1
488+
512489
result = dict()
513-
if self.is_binary:
490+
if self.is_binary and len(self.aucs) > 0:
514491
result['auc'] = np.mean(self.aucs)
515492
result['auc_deviation'] = np.std(self.aucs)
493+
516494
result['accuracy'] = avg_accuracy
517495
result['precision'] = avg_precision
518496
result['recall'] = avg_recall
519-
result['acc_deviation'] = acc_deviation
497+
result['f1_score'] = score
498+
result['score_deviation'] = score_deviation
520499
result['score'] = score
521500
result['min_score'] = min_score
522501
result['accepted_deviation'] = accepted_deviation
@@ -527,11 +506,11 @@ def get_evaluation_results(self, min_score, accepted_deviation):
527506

528507
# If deviation is too high we may need more records to report if
529508
# this model is reliable or not.
530-
if acc_deviation > accepted_deviation:
509+
if score_deviation > accepted_deviation:
531510
result['info'].append('The evaluation results varied too much, ' +
532511
'we might need more samples to check if this ' +
533512
'model is valid. Model deviation = ' +
534-
str(acc_deviation) +
513+
str(score_deviation) +
535514
', accepted deviation = ' +
536515
str(accepted_deviation))
537516
result['status'] = NOT_ENOUGH_DATA
@@ -543,7 +522,7 @@ def get_evaluation_results(self, min_score, accepted_deviation):
543522
str(min_score))
544523
result['status'] = LOW_SCORE
545524

546-
if acc_deviation > accepted_deviation and score < min_score:
525+
if score_deviation > accepted_deviation and score < min_score:
547526
result['status'] = LOW_SCORE + NOT_ENOUGH_DATA
548527

549528
return result

0 commit comments

Comments
 (0)