Skip to content
Guides6 min read

Misurare l'accordo tra annotatori

Come calcolare e interpretare il kappa di Cohen, il kappa di Fleiss e l'alpha di Krippendorff nei progetti di annotazione con Potato, con esempi di codice Python e criteri di lettura.

Potato Team

L'accordo tra annotatori (IAA) misura quanto coerentemente annotatori diversi etichettano gli stessi elementi. Quando l'accordo è alto, puoi fidarti delle etichette. Quando è basso, il colpevole di solito è una linea guida poco chiara oppure un task intrinsecamente soggettivo.

Come scegliere una metrica di accordo: due valutatori usano il kappa di Cohen, molti valutatori il kappa di Fleiss, dati ordinali o mancanti l'alpha di KrippendorffQuale metrica di accordo usare

Perché misurare l'accordo?

Ci sono diversi motivi per cui vale la pena farlo. Un accordo basso rimanda quasi sempre a istruzioni da riscrivere, quindi il numero funziona anche come verifica delle linee guida. Ti dice inoltre quanto è difficile davvero il task, dato che alcune domande non hanno una risposta unica. Ti fa vedere quali annotatori hanno bisogno di più formazione. E se pubblichi, i revisori si aspetteranno un valore di accordo. Infine, la metrica orienta il modo in cui combini più annotatori in un'unica etichetta.

Per come Potato gestisce tutto questo dall'inizio alla fine, vedi la documentazione sorgente.

Metriche di accordo

Kappa di Cohen (2 annotatori)

Per confrontare due annotatori su dati categoriali:

text
κ = (Po - Pe) / (1 - Pe)

Dove:

  • Po = accordo osservato
  • Pe = accordo atteso per caso

Interpretazione:

KappaInterpretazione
< 0Inferiore al caso
0.01-0.20Minimo
0.21-0.40Discreto
0.41-0.60Moderato
0.61-0.80Sostanziale
0.81-1.00Quasi perfetto

Kappa di Fleiss (3+ annotatori)

Per tre o più annotatori su dati categoriali:

yaml
quality_control:
  agreement:
    metrics:
      - fleiss_kappa

Stessa scala di interpretazione del kappa di Cohen.

Alpha di Krippendorff

È la più flessibile delle tre. Regge qualsiasi numero di annotatori, gestisce i dati mancanti e funziona su dati nominali, ordinali, a intervalli e di rapporto.

yaml
quality_control:
  agreement:
    metrics:
      - krippendorff_alpha
    alpha_level: nominal  # or ordinal, interval, ratio

Interpretazione:

  • α ≥ 0.80: affidabile
  • 0.67 ≤ α < 0.80: accettabile in via provvisoria
  • α < 0.67: non affidabile

Configurare l'accordo in Potato

Impostazione di base

yaml
quality_control:
  agreement:
    enabled: true
    calculate_on_overlap: true
 
    metrics:
      - cohens_kappa
      - fleiss_kappa
      - krippendorff_alpha
 
    # Per annotation scheme
    per_scheme: true
 
    # Reporting
    report_interval: 100  # Every 100 annotations
    export_file: agreement_report.json

Configurazione della sovrapposizione

yaml
quality_control:
  redundancy:
    # How many annotators per item
    annotations_per_item: 3
 
    # Minimum overlap for calculations
    min_overlap_for_agreement: 2
 
    # Sampling for agreement
    agreement_sample_size: 100  # Calculate on 100 items
    agreement_sample_method: random  # or stratified, all

Calcolare l'accordo

Nella dashboard

Potato mostra le metriche di accordo nella dashboard di amministrazione:

yaml
quality_control:
  dashboard:
    show_agreement: true
    agreement_chart: true
    update_frequency: 60  # seconds

Tramite API

bash
# Get current agreement metrics
curl http://localhost:8000/api/quality/agreement
 
# Response:
{
  "overall": {
    "fleiss_kappa": 0.72,
    "krippendorff_alpha": 0.75
  },
  "per_scheme": {
    "sentiment": {
      "fleiss_kappa": 0.78,
      "krippendorff_alpha": 0.80
    },
    "topic": {
      "fleiss_kappa": 0.65,
      "krippendorff_alpha": 0.68
    }
  },
  "sample_size": 150,
  "annotator_pairs": 10
}

Tramite CLI

bash
# Calculate agreement from output files
potato agreement --annotations annotation_output/ --output agreement_report.json
 
# With specific metric
potato agreement --annotations annotation_output/ --metric krippendorff --level ordinal

L'accordo nei diversi tipi di annotazione

Categoriale (radio, multiselect)

yaml
quality_control:
  agreement:
    schemes:
      sentiment:
        type: nominal
        metrics: [cohens_kappa, fleiss_kappa]
 
      urgency:
        type: ordinal  # Low < Medium < High
        metrics: [krippendorff_alpha]

Scale Likert

yaml
quality_control:
  agreement:
    schemes:
      quality_rating:
        type: ordinal
        metrics: [krippendorff_alpha, weighted_kappa]
 
        # Weighted kappa for ordinal
        weighting: linear  # or quadratic

Annotazioni a span

Gli span sono più insidiosi delle etichette categoriali, perché due annotatori possono concordare sull'etichetta e non essere d'accordo su dove esattamente inizia e finisce. Il NER richiede un trattamento apposito:

yaml
quality_control:
  agreement:
    schemes:
      entities:
        type: span
        span_matching: overlap  # or exact, token
 
        # What to compare
        compare: label_and_span  # or label_only, span_only
 
        # Overlap threshold for "match"
        overlap_threshold: 0.5
 
        metrics:
          - span_f1
          - span_precision
          - span_recall

Ranking

yaml
quality_control:
  agreement:
    schemes:
      preference_rank:
        type: ranking
        metrics:
          - kendall_tau
          - spearman_rho

Accordo a coppie o complessivo

A coppie (ogni coppia)

yaml
quality_control:
  agreement:
    pairwise: true
    output_matrix: true  # Agreement matrix
 
# Output:
# annotator1 × annotator2: κ = 0.75
# annotator1 × annotator3: κ = 0.68
# annotator2 × annotator3: κ = 0.82

Complessivo (tutti gli annotatori)

yaml
quality_control:
  agreement:
    overall: true
    metrics:
      - fleiss_kappa  # Designed for 3+ annotators
      - krippendorff_alpha

Che fare quando l'accordo è basso

Individuare i punti critici

yaml
quality_control:
  agreement:
    diagnostics:
      enabled: true
 
      # Items with most disagreement
      show_disagreed_items: true
      disagreement_threshold: 0.5
 
      # Labels with most confusion
      confusion_matrix: true
 
      # Annotators with low agreement
      per_annotator_agreement: true

Interventi quando l'accordo è basso

yaml
quality_control:
  agreement:
    alerts:
      - threshold: 0.6
        action: notify
        message: "Agreement below 0.6 - review guidelines"
 
      - threshold: 0.4
        action: pause
        message: "Agreement critically low - pausing task"
 
    # Automatic guideline reminders
    show_guidelines_on_low_agreement: true
    guideline_threshold: 0.5

Configurazione completa

yaml
annotation_task_name: "Agreement-Tracked Annotation"
 
quality_control:
  # Redundancy setup
  redundancy:
    annotations_per_item: 3
    assignment_method: random
 
  # Agreement calculation
  agreement:
    enabled: true
 
    # Metrics
    metrics:
      - fleiss_kappa
      - krippendorff_alpha
 
    # Per-scheme configuration
    schemes:
      sentiment:
        type: nominal
        metrics: [fleiss_kappa, cohens_kappa]
 
      intensity:
        type: ordinal
        metrics: [krippendorff_alpha]
        alpha_level: ordinal
 
      entities:
        type: span
        span_matching: overlap
        overlap_threshold: 0.5
        metrics: [span_f1]
 
    # Calculation settings
    calculate_on_overlap: true
    min_overlap: 2
    sample_size: all  # or number
 
    # Pairwise analysis
    pairwise: true
    pairwise_output: agreement_matrix.csv
 
    # Diagnostics
    diagnostics:
      confusion_matrix: true
      disagreed_items: true
      per_annotator: true
 
    # Alerts
    alerts:
      - metric: fleiss_kappa
        threshold: 0.6
        action: notify
 
    # Reporting
    report_file: agreement_report.json
    report_interval: 50
 
  # Dashboard
  dashboard:
    show_agreement: true
    charts:
      - agreement_over_time
      - per_scheme_agreement
      - annotator_comparison

Report di output

json
{
  "timestamp": "2024-10-25T15:30:00Z",
  "sample_size": 500,
  "annotators": ["ann1", "ann2", "ann3"],
 
  "overall_agreement": {
    "fleiss_kappa": 0.72,
    "krippendorff_alpha": 0.75
  },
 
  "per_scheme": {
    "sentiment": {
      "fleiss_kappa": 0.78,
      "confusion_matrix": {
        "Positive": {"Positive": 180, "Negative": 5, "Neutral": 15},
        "Negative": {"Positive": 8, "Negative": 165, "Neutral": 12},
        "Neutral": {"Positive": 12, "Negative": 10, "Neutral": 93}
      }
    }
  },
 
  "pairwise": {
    "ann1_ann2": 0.75,
    "ann1_ann3": 0.70,
    "ann2_ann3": 0.72
  },
 
  "per_annotator": {
    "ann1": {"avg_agreement": 0.73, "items_annotated": 500},
    "ann2": {"avg_agreement": 0.74, "items_annotated": 500},
    "ann3": {"avg_agreement": 0.71, "items_annotated": 500}
  },
 
  "most_disagreed_items": [
    {"id": "item_234", "disagreement_rate": 1.0},
    {"id": "item_567", "disagreement_rate": 0.67}
  ]
}

Buone pratiche

Calcola l'accordo presto, invece di aspettare la fine del progetto, perché a quel punto è troppo tardi per sistemare le linee guida. Scegli la metrica adatta ai tuoi dati: nominali, ordinali o a span. Quando l'accordo risulta basso, indaga prima di prendertela con gli annotatori, perché il problema sono spesso le istruzioni. Riporta il valore in qualsiasi pubblicazione. E decidi una soglia accettabile prima di iniziare, non dopo aver visto il risultato che ti è uscito.

Per un approfondimento sulla stima della competenza quando gli annotatori sono in disaccordo, vedi la documentazione di MACE.

Passi successivi


Documentazione completa sull'accordo su Gestione Utenti.