Deine erste NER-Annotationsaufgabe bauen
Schritt-für-Schritt-Anleitung für eine Named-Entity-Recognition-Aufgabe in Potato, mit Span-Konfiguration, Labelfarben, überlappenden Spans, Tastenkürzeln und CoNLL-Export.
Dieses Tutorial baut in Potato eine Aufgabe zur Named Entity Recognition (NER) mit fünf Entitätstypen, Kürzeln auf den Zahlentasten, Anweisungen für Annotierende und einem CoNLL-2003-Export für das Modelltraining. Die Span-Optionen dahinter findest du in der Dokumentation zur Span-Annotation.
Was Annotierende bekommen
Die fertige Aufgabe zeigt Annotierenden einen Satz mit einer Reihe beschrifteter Schaltflächen darüber. Sie ziehen über eine Wortgruppe, um sie auszuwählen, drücken eine Zahlentaste oder klicken auf eine Schaltfläche, um sie zu labeln, und klicken einen gelabelten Span erneut an, um ihn zu ändern oder zu entfernen. Jeder Span wird mit seinen Zeichenoffsets gespeichert, sodass dieselbe Annotationsdatei sowohl einen CoNLL-2003-Export als auch eine Übereinstimmungsberechnung auf Span-Ebene speist.
Voraussetzungen
Du brauchst ein installiertes Potato, eine Textdatendatei und genug YAML-Kenntnisse, um eine Konfiguration zu bearbeiten:
pip install potato-annotationSchritt 1: Das Span-Schema
Span-Annotation ist in Potato der Typ span. Jedes Label braucht einen Namen. Die nützlichen optionalen Felder sind color, das Entitätstypen in dichtem Text visuell trennt, key_value, das dem Label ein Tastenkürzel zuordnet, und tooltip, das beim Überfahren mit der Maus die Definition des Labels anzeigt, damit Annotierende die Seite nicht verlassen müssen, um im Codebuch nachzusehen.
Mit fünf Typen lässt sich die Aufgabe in einer Sitzung lernen. Ab etwa acht beginnen Annotierende, bei jedem Item die Richtlinien nachzuschlagen, und genau dort sinkt der Durchsatz. sequential_key_binding schaltet die Zahlentasten ein, und key_value legt fest, welche Zahl zu welchem Label gehört, statt das der Reihenfolge der Liste zu überlassen. Lege config.yaml an:
annotation_task_name: "Named Entity Recognition"
task_dir: "."
data_files:
- data/sentences.json
item_properties:
id_key: id
text_key: text
output_annotation_dir: "annotation_output/"
export_annotation_format: "jsonl"
annotation_schemes:
- annotation_type: span
name: entities
description: "Highlight and label named entities in the text"
sequential_key_binding: true
labels:
- name: PER
tooltip: "Person names, including fictional characters"
color: "#FF6B6B"
key_value: "1"
- name: ORG
tooltip: "Companies, institutions, agencies"
color: "#4ECDC4"
key_value: "2"
- name: LOC
tooltip: "Places, including countries, cities, landmarks"
color: "#45B7D1"
key_value: "3"
- name: DATE
tooltip: "Dates, times, and temporal expressions"
color: "#96CEB4"
key_value: "4"
- name: MISC
tooltip: "Named entities that fit none of the above"
color: "#FFEAA7"
key_value: "5"
user_config:
allow_all_users: trueSchritt 2: Die Datendatei
Potato liest ein JSON-Objekt pro Zeile und übernimmt die in item_properties benannten Felder. Lege data/sentences.json an:
{"id": "1", "text": "Apple Inc. announced that CEO Tim Cook will visit Paris next Tuesday."}
{"id": "2", "text": "The United Nations headquarters in New York hosted delegates from Japan."}
{"id": "3", "text": "Dr. Sarah Johnson published her research at Stanford University in March 2024."}Drei Sätze reichen, um zu prüfen, ob die Oberfläche funktioniert. Lade das echte Korpus erst, wenn der Labelsatz einen Pilotlauf überstanden hat.
Schritt 3: Anweisungen in Reichweite der Annotierenden
Die meisten Meinungsverschiedenheiten bei NER entstehen durch Abgrenzungsregeln und nicht durch die Entitätstypen selbst. Die Regeln, die über die meisten Items entscheiden, gehören deshalb auf den Annotationsbildschirm. annotation_instructions erscheint als einklappbares Panel oben auf jedem Item, standardmäßig geöffnet, und Annotierende klappen es weg, sobald sie mit der Aufgabe vertraut sind. Füge diesen Block der obigen Konfiguration hinzu:
annotation_instructions: |
## Entity types
- **PER** covers people, including fictional characters ("John Smith", "Dr. Johnson", "Batman")
- **ORG** covers companies, institutions, and agencies ("Apple Inc.", "United Nations", "Stanford University")
- **LOC** covers places, including countries, cities, and landmarks ("Paris", "New York", "Mount Everest")
- **DATE** covers dates, times, and temporal expressions ("Tuesday", "March 2024", "next week")
- **MISC** covers named entities that fit none of the above ("Nobel Prize", "iPhone", "COVID-19")
## Boundary rules
1. Include titles (Dr., Mr.) with person names.
2. For nested entities, annotate the largest meaningful span.
3. Leave articles (the, a) outside the span.Markdown wird hier gerendert, sodass du denselben Text aus deinem Codebuch übernehmen kannst, ohne ihn als HTML neu zu schreiben. Beschränke dieses Panel auf die Regeln, die die meisten Items entscheiden, und hinterlege das vollständige Codebuch über annotation_codebook_url, das sich in einem eigenen Tab öffnet.
Die Span-Oberfläche zeigt die Labels dann als Schaltflächen über dem Text:
Annotierende heben Textspans hervor und weisen Entitätslabels wie PER, ORG, LOC und DATE zu
Schritt 4: Die Aufgabe starten
Starte den Server mit der Konfiguration aus Schritt 1:
potato start config.yamlÖffne die ausgegebene Adresse und melde dich an. Annotierende arbeiten dann pro Entität vier Schritte ab:
- Text auswählen. Über die Wortgruppe klicken und ziehen.
- Typ zuweisen. Die Zahlentaste drücken oder auf die Label-Schaltfläche klicken.
- Fehler korrigieren. Einen vorhandenen Span anklicken, um sein Label zu ändern oder ihn zu entfernen.
- Absenden. Zum nächsten Item wechseln, wenn der Satz fertig ist.
Schritt 5: Was die Ausgabedatei enthält
Jedes annotierte Item wird als ein JSON-Objekt nach annotation_output/ geschrieben, mit dem Schemanamen als Schlüssel und einem Eintrag pro Span:
{
"id": "1",
"text": "Apple Inc. announced that CEO Tim Cook will visit Paris next Tuesday.",
"entities": [
{"start": 0, "end": 10, "label": "ORG", "text": "Apple Inc."},
{"start": 30, "end": 38, "label": "PER", "text": "Tim Cook"},
{"start": 50, "end": 55, "label": "LOC", "text": "Paris"},
{"start": 61, "end": 73, "label": "DATE", "text": "next Tuesday"}
]
}Die Zeichenoffsets machen die Datei für die Weiterverarbeitung nützlich. Sie überstehen Änderungen an der Tokenisierung, sodass sich dieselben Annotationen an jeden Tokenizer anpassen lassen, den dein Modell verwendet.
Schritt 6: Export nach CoNLL-2003
Modelle für Sequenz-Labeling lesen getaggte Tokens statt Zeichenoffsets, deshalb wandelt Potato die Spans beim Export um:
python -m potato.export -c config.yaml -f conll_2003 -o ./conll_export/Das Ergebnis enthält ein Token pro Zeile mit seinem Tag und Leerzeilen zwischen den Sätzen. Die Option tag_scheme schreibt BIO, BIOES oder IOB, mit BIO als Standard. Stimme sie also vor dem Export auf das ab, was dein Trainingscode erwartet.
Die Richtlinien schärfen
Unscharfe Regeln führen zu abweichenden Entscheidungen beim selben Span, deshalb lohnt es sich, die Regeln zu überarbeiten, solange der Pilot noch klein ist. Geh die schwierigen Fälle mit den Annotierenden vor dem Start durch statt danach, und führe eine gemeinsame Liste geklärter Grenzfälle, sobald sie auftauchen. Sinkende Übereinstimmung zwischen Annotierenden ist das Signal, dass eine Regel geschärft werden muss, und das bei 50 Items zu bemerken ist billiger als bei 5000.
Nächste Schritte
- Füge eine Trainingsphase hinzu, um Annotierende einzuarbeiten, bevor sie echte Items bearbeiten
- Richte mehrere Annotierende ein, damit sich Spans vergleichen lassen
- Exportiere ins Hugging-Face-Format für das Modelltraining
- Lies die Dokumentation zur Span-Annotation für die vollständige Optionsliste