Skip to content
ट्यूटोरियल7 मिनट में पढ़ें

अपना पहला NER एनोटेशन कार्य बनाना

Potato में named entity recognition कार्य बनाने की चरण-दर-चरण मार्गदर्शिका, जिसमें span एनोटेशन कॉन्फ़िग, लेबल के रंग, आपस में ओवरलैप करते span, कीबोर्ड शॉर्टकट और CoNLL निर्यात शामिल हैं।

Potato Team

यह ट्यूटोरियल Potato में एक named entity recognition (NER) कार्य बनाता है, जिसमें पाँच entity प्रकार, नंबर-कुंजी शॉर्टकट, एनोटेटरों के लिए निर्देश और मॉडल प्रशिक्षण के लिए CoNLL-2003 निर्यात शामिल हैं। इसके पीछे के span कॉन्फ़िगरेशन विकल्पों के लिए span एनोटेशन दस्तावेज़ देखिए।

एनोटेटर को क्या मिलता है

तैयार कार्य एनोटेटर को एक वाक्य दिखाता है, जिसके ऊपर लेबल वाले बटनों की एक पंक्ति होती है। एनोटेटर किसी वाक्यांश पर खींचकर उसे चुनता है, उसे लेबल देने के लिए कोई नंबर कुंजी दबाता है या बटन पर क्लिक करता है, और किसी लेबल लगे span पर दोबारा क्लिक करके उसे बदलता या हटाता है। हर span अपने character offsets के साथ सहेजा जाता है, इसलिए वही एनोटेशन फ़ाइल CoNLL-2003 निर्यात और span-स्तर की सहमति की गणना, दोनों के काम आती है।

पहले से ज़रूरी चीज़ें

आपको Potato इंस्टॉल होना चाहिए, एक पाठ डेटा फ़ाइल चाहिए, और कॉन्फ़िग बदलने लायक YAML की समझ चाहिए:

bash
pip install potato-annotation

क़दम 1: span scheme

span एनोटेशन Potato का span प्रकार है। हर लेबल को एक नाम चाहिए, और काम के वैकल्पिक फ़ील्ड ये हैं: color, जो घने पाठ में entity प्रकारों को देखने में अलग करता है; key_value, जो लेबल से एक कीबोर्ड शॉर्टकट जोड़ता है; और tooltip, जो माउस ले जाने पर लेबल की परिभाषा दिखाता है, ताकि एनोटेटरों को codebook देखने के लिए पेज छोड़ना न पड़े।

पाँच प्रकार रखने से कार्य एक ही बैठक में सीखा जा सकता है। लगभग आठ से ज़्यादा होने पर एनोटेटर हर आइटम पर दिशानिर्देश देखने लगते हैं, और यहीं से काम की रफ़्तार गिरती है। sequential_key_binding नंबर कुंजियाँ चालू करता है, और key_value तय करता है कि कौन-सा नंबर किस लेबल के साथ जाएगा, बजाय इसके कि यह सूची के क्रम पर छोड़ दिया जाए। config.yaml बनाइए:

yaml
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: true

क़दम 2: डेटा फ़ाइल

Potato हर पंक्ति में एक JSON ऑब्जेक्ट पढ़ता है और item_properties में नामित फ़ील्ड लेता है। data/sentences.json बनाइए:

json
{"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."}

इंटरफ़ेस काम कर रहा है या नहीं, यह जाँचने के लिए तीन वाक्य काफ़ी हैं। असली कॉर्पस तब लोड कीजिए जब लेबल सेट एक पायलट में टिक जाए।

क़दम 3: ऐसे निर्देश जो एनोटेटर तक पहुँचें

NER में ज़्यादातर असहमति entity प्रकारों से नहीं, सीमा के नियमों से आती है, इसलिए जो नियम सबसे ज़्यादा आइटम तय करते हैं, उनकी जगह एनोटेशन स्क्रीन पर है। annotation_instructions हर आइटम के ऊपर एक समेटा जा सकने वाला पैनल दिखाता है, जो शुरू में खुला रहता है और जिसे एनोटेटर कार्य से परिचित होने पर बंद कर देते हैं। ऊपर वाले कॉन्फ़िग में यह ब्लॉक जोड़िए:

yaml
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 रेंडर होता है, इसलिए वही पाठ आपके codebook से सीधे लिया जा सकता है, उसे HTML में दोबारा लिखने की ज़रूरत नहीं। इस पैनल में सिर्फ़ वे नियम रखिए जो ज़्यादातर आइटम तय करते हैं, और पूरा codebook annotation_codebook_url के पीछे रखिए, जो अपने अलग टैब में खुलता है।

इसके बाद span इंटरफ़ेस लेबलों को पाठ के ऊपर बटनों के रूप में दिखाता है:

रंगों से पहचाने जाने वाले entity प्रकारों के साथ named entity span एनोटेशन इंटरफ़ेसएनोटेटर पाठ के span हाइलाइट करते हैं और PER, ORG, LOC तथा DATE जैसे entity लेबल लगाते हैं

क़दम 4: कार्य चलाइए

क़दम 1 वाले कॉन्फ़िग पर सर्वर शुरू कीजिए:

bash
potato start config.yaml

सर्वर जो पता दिखाता है उसे खोलिए और लॉग इन कीजिए। इसके बाद एनोटेटर हर entity के लिए चार काम करता है:

  1. पाठ चुनिए। वाक्यांश पर क्लिक करके खींचिए।
  2. प्रकार लगाइए। नंबर कुंजी दबाइए या लेबल बटन पर क्लिक कीजिए।
  3. ग़लती ठीक कीजिए। किसी मौजूदा span पर क्लिक करके उसका लेबल बदलिए या उसे हटाइए।
  4. सबमिट कीजिए। वाक्य पूरा होने पर अगले आइटम पर जाइए।

क़दम 5: आउटपुट फ़ाइल में क्या होता है

हर एनोटेट किया गया आइटम annotation_output/ में एक JSON ऑब्जेक्ट के रूप में लिखा जाता है, जिसमें scheme का नाम कुंजी होता है और हर span की एक प्रविष्टि होती है:

json
{
  "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"}
  ]
}

आगे के काम में फ़ाइल को उपयोगी character offsets ही बनाते हैं। tokenization बदलने पर भी ये सही रहते हैं, इसलिए वही एनोटेशन आपके मॉडल के किसी भी tokenizer के साथ फिर से संरेखित किए जा सकते हैं।

क़दम 6: CoNLL-2003 में निर्यात

sequence labeling मॉडल character offsets नहीं, टैग लगे tokens पढ़ते हैं, इसलिए Potato निर्यात के समय spans को बदल देता है:

bash
python -m potato.export -c config.yaml -f conll_2003 -o ./conll_export/

नतीजे में हर पंक्ति में एक token और उसका टैग होता है, और वाक्यों के बीच ख़ाली पंक्तियाँ होती हैं। tag_scheme विकल्प BIO, BIOES या IOB लिखता है, और डिफ़ॉल्ट BIO है, इसलिए निर्यात चलाने से पहले इसे अपने प्रशिक्षण कोड की अपेक्षा से मिला लीजिए।

दिशानिर्देशों को कसना

धुँधले नियम एक ही span पर बँटे हुए फ़ैसले पैदा करते हैं, इसलिए जब तक पायलट छोटा है, तभी नियमों को सुधारना फ़ायदेमंद है। मुश्किल मामले एनोटेटरों को शुरू करने से पहले समझाइए, बाद में नहीं, और तय हो चुके किनारे के मामलों की एक साझा सूची बनाते चलिए। एनोटेटरों के बीच गिरती सहमति इस बात का संकेत है कि किसी नियम को कसने की ज़रूरत है, और इसे 5,000 के बजाय 50 आइटम पर पकड़ना सस्ता पड़ता है।

अगले क़दम