You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python计算嵌套数组的精确率、召回率与F1值

Alright, let's break down how to calculate precision, recall, and F1-score for your entity labeling task. You've got two large nested arrays (ground truth correct and predictions predicted) where each subarray corresponds to a sequence of labels, and you need metrics across the classes PER, ORG, MISC, LOC, *, and GPE.

Core Approach

First, we need to track three key metrics for each class:

  • True Positives (TP): The number of times we correctly predicted the class
  • False Positives (FP): The number of times we predicted the class when it wasn't the ground truth
  • False Negatives (FN): The number of times the ground truth was the class, but we predicted something else

We'll iterate through every label pair in the nested arrays, update these counters, then use them to compute precision, recall, and F1 for each class plus overall micro/macro averages.

Python Implementation

# Define the target classes
CLASSES = ['PER', 'ORG', 'MISC', 'LOC', '*', 'GPE']

# Initialize counters for each class
tp = {cls: 0 for cls in CLASSES}
fp = {cls: 0 for cls in CLASSES}
fn = {cls: 0 for cls in CLASSES}

# Iterate through each sequence pair
for true_seq, pred_seq in zip(correct, predicted):
    # Compare each label in the sequence
    for true_label, pred_label in zip(true_seq, pred_seq):
        if true_label == pred_label:
            # Correct prediction: increment TP for the matching class
            tp[true_label] += 1
        else:
            # Wrong prediction: increment FP for the predicted class, FN for the true class
            fp[pred_label] += 1
            fn[true_label] += 1

def calculate_metrics(tp, fp, fn):
    metrics = {}
    
    # Calculate class-wise metrics
    for cls in CLASSES:
        # Handle division by zero cases to avoid errors
        precision = tp[cls] / (tp[cls] + fp[cls]) if (tp[cls] + fp[cls]) > 0 else 0.0
        recall = tp[cls] / (tp[cls] + fn[cls]) if (tp[cls] + fn[cls]) > 0 else 0.0
        f1 = 2 * (precision * recall) / (precision + recall) if (precision + recall) > 0 else 0.0
        
        metrics[cls] = {
            'precision': round(precision, 4),
            'recall': round(recall, 4),
            'f1': round(f1, 4)
        }
    
    # Calculate micro-average (treat all classes as a single group)
    total_tp = sum(tp.values())
    total_fp = sum(fp.values())
    total_fn = sum(fn.values())
    
    micro_precision = total_tp / (total_tp + total_fp) if (total_tp + total_fp) > 0 else 0.0
    micro_recall = total_tp / (total_tp + total_fn) if (total_tp + total_fn) > 0 else 0.0
    micro_f1 = 2 * (micro_precision * micro_recall) / (micro_precision + micro_recall) if (micro_precision + micro_recall) > 0 else 0.0
    
    # Calculate macro-average (average metrics across all classes)
    macro_precision = sum(metrics[cls]['precision'] for cls in CLASSES) / len(CLASSES)
    macro_recall = sum(metrics[cls]['recall'] for cls in CLASSES) / len(CLASSES)
    macro_f1 = sum(metrics[cls]['f1'] for cls in CLASSES) / len(CLASSES)
    
    metrics['micro-average'] = {
        'precision': round(micro_precision, 4),
        'recall': round(micro_recall, 4),
        'f1': round(micro_f1, 4)
    }
    metrics['macro-average'] = {
        'precision': round(macro_precision, 4),
        'recall': round(macro_recall, 4),
        'f1': round(macro_f1, 4)
    }
    
    return metrics

# Compute and print results
results = calculate_metrics(tp, fp, fn)

print("Class-wise Metrics:")
for cls in CLASSES:
    print(f"\n{cls}:")
    print(f"  Precision: {results[cls]['precision']}")
    print(f"  Recall:    {results[cls]['recall']}")
    print(f"  F1-Score:  {results[cls]['f1']}")

print("\nOverall Metrics:")
print("Micro-Average (weighted by class frequency):")
print(f"  Precision: {results['micro-average']['precision']}")
print(f"  Recall:    {results['micro-average']['recall']}")
print(f"  F1-Score:  {results['micro-average']['f1']}")

print("\nMacro-Average (equal weight per class):")
print(f"  Precision: {results['macro-average']['precision']}")
print(f"  Recall:    {results['macro-average']['recall']}")
print(f"  F1-Score:  {results['macro-average']['f1']}")

Key Notes

  • Handling *: If * represents "no entity" and you don't want to include it in entity-specific metrics, simply remove it from the CLASSES list. The code will automatically adjust counters and averages.
  • Efficiency: This implementation uses basic Python loops, which will handle your 10K+ subarrays efficiently without needing external libraries.
  • Division by Zero: We explicitly handle cases where a class has no TP/FP or TP/FN to avoid runtime errors.

内容的提问来源于stack exchange,提问作者Harsh2093

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:23:38