Merged in feature/test_files (pull request #578)

Feature/test files

* printing incorrect recall values

* values responsible for low recall added in spreadsheet

* changing match list to unmatch list for breakouts

* recall values added for 1-to-N

* print statements removed

* removed print statements

* Merged main into feature/test_files

* output formatting fix

* Merged main into feature/test_files


Approved-by: Katon Minhas
This commit is contained in:
Mayank Aamseek
2025-06-18 18:57:45 +00:00
committed by Katon Minhas
parent 69aebb053e
commit 4a8ddd331d
2 changed files with 21 additions and 7 deletions
+4 -4
View File
@@ -58,7 +58,7 @@ one_to_one_columns = ['FILE_NAME'] + [f for f in one_to_one_fields if f in testb
testbed_one_to_one = testbed[one_to_one_columns].drop_duplicates()
results_one_to_one = results[one_to_one_columns].drop_duplicates()
metrics_df = pd.DataFrame(columns=['Field', 'Precision', 'Recall', 'Accuracy'])
metrics_df = pd.DataFrame(columns=['Field', 'Precision', 'Recall', 'Accuracy', 'FN_list'])
comparison_df = pd.DataFrame(index=testbed_one_to_one['FILE_NAME'].unique())
for field in one_to_one_fields:
@@ -81,10 +81,10 @@ for field in one_to_one_fields:
raise
# Calculate metrics
precision, recall, accuracy = testbed_utils.calculate_field_metrics(merged, field)
metrics_df.loc[len(metrics_df)] = [field, precision, recall, accuracy]
precision, recall, accuracy, FN_list = testbed_utils.calculate_field_metrics(merged, field)
metrics_df.loc[len(metrics_df)] = [field, precision, recall, accuracy, FN_list]
else:
metrics_df.loc[len(metrics_df)] = [field, None, None, None]
metrics_df.loc[len(metrics_df)] = [field, None, None, None, None]
comparison_df[field] = None
# Display results with clean formatting
+17 -3
View File
@@ -167,6 +167,10 @@ def calculate_field_metrics(merged, field):
for pred, truth in zip(merged[f'{field}_pred'], merged[f'{field}_truth'])
)
FN_list = [
truth for pred, truth in zip(merged[f'{field}_pred'], merged[f'{field}_truth'])
if is_negative(pred) and is_positive(truth)
]
# print(field)
# print(f"TP: {TP}, FP: {FP}, TN: {TN}, FN: {FN}")
@@ -175,7 +179,7 @@ def calculate_field_metrics(merged, field):
recall = TP / (TP + FN) if (TP + FN) > 0 else 0
accuracy = (TP + TN) / (TP + FP + TN + FN)
return precision, recall, accuracy
return precision, recall, accuracy, FN_list
def evaluate_provider_fields_separately(testbed_df, results_df, verbose=False):
@@ -426,7 +430,7 @@ def match_rows(fields, labels_df, predictions_df, N):
return False
confusion_matrix = {field_name: {"tp": 0, "fp": 0} for field_name in fields}
confusion_matrix = {field_name: {"tp": 0, "fp": 0, "unmatched_labels": []} for field_name in fields}
# Check for completely blank fields and handle them separately
for field in fields:
@@ -438,6 +442,7 @@ def match_rows(fields, labels_df, predictions_df, N):
confusion_matrix[field]["tp"] = min(len(labels_df), len(predictions_df))
confusion_matrix[field]["fp"] = 0
confusion_matrix[field]["fn"] = 0
confusion_matrix[field]["unmatched_labels"] = []
# Skip this field in the regular matching process
fields = [f for f in fields if f != field]
@@ -488,6 +493,8 @@ def match_rows(fields, labels_df, predictions_df, N):
# Update the confusion matrix with the best match
for field in fields:
confusion_matrix[field]["tp"] += best_matches[field]["tp"]
if best_matches[field]["tp"] == 0:
confusion_matrix[field]["unmatched_labels"].append((label_idx, label_row[field]))
# Calculate FP and FN based on the number of matched fields
for field in fields:
@@ -495,6 +502,11 @@ def match_rows(fields, labels_df, predictions_df, N):
confusion_matrix[field]['fn'] = len(labels_df) - confusion_matrix[field]['tp']
# FP = number of prediction rows where this field wasn't matched
confusion_matrix[field]['fp'] = len(predictions_df) - confusion_matrix[field]['tp']
# add unmatched labels to the confusion matrix for cases where whole rows were unmatched
if list(set(labels_df.index) - set(matched_label_indices)):
confusion_matrix[field]["unmatched_labels"].append(("|", "|"))
for idx in list(set(labels_df.index) - set(matched_label_indices)):
confusion_matrix[field]["unmatched_labels"].append((idx, labels_df.loc[idx, field]))
return confusion_matrix
@@ -679,6 +691,7 @@ def calculate_precision_recall(accuracies):
for confusion_matrix in accuracies:
filename = confusion_matrix["Filename"]
precision_dict, recall_dict = {"Filename": filename}, {"Filename": filename}
recall_dict_value = {}
for field in confusion_matrix:
if field == "Filename":
@@ -699,9 +712,10 @@ def calculate_precision_recall(accuracies):
precision_dict[field] = precision
recall_dict[field] = recall
recall_dict_value[field+"_missed"] = confusion_matrix[field]["unmatched_labels"]
precision_dicts.append(precision_dict)
recall_dicts.append(recall_dict)
recall_dicts.append(recall_dict | recall_dict_value)
# Calculate overall precision, recall, and F1 score for all fields
overall_metrics_list = []