Аннотирование вручную отнимает много времени и чревато ошибками. Мы можем ускорить процесс, программно аннотируя наш набор данных. Этот пост показывает, что без особых усилий мы можем быстро и точно маркировать сотни экземпляров.

Весь код для этого поста можно найти в этом Github Repository.

pip install extr-ds

Данные

(6:37–1-е) Л. Фурнетт оставил подкат на DAL 25 на 2 ярда (Н. Галлимор; Дж. Кирс).



Разделить данные



Сущности

С минимальными усилиями мы можем настроить шаблоны маркировки и/или базу знаний.

  • ВРЕМЯ, ПЕРИОД, ИГРОК, КОМАНДА, КОЛИЧЕСТВО и т. д.

полную настройку смотрите в файле конфигурации

import re
from extr.regexes import RegEx, RegExLabel

kb = {
    'PERSON': ['T.J. Watt'],
    'PERIOD': [
        '1st',
        '2nd',
        '3rd',
        '4th',
        'OT',
    ]
}

entity_patterns: List[RegExLabel] = [
    RegExLabel(
        label='TIME',
        regexes=[
            RegEx(expressions=[
                r'\b[0-9]{1,2}:[0-9]{2}\b',
            ]),
        ],
    ),
    RegExLabel(
        label='QUANTITY',
        regexes=[
            RegEx(expressions=[
                r'(?<=\s)-?\d{1,3}(?=\b)',
            ])
        ]
    ),
    ...
]


Программно аннотировать набор данных

На этом этапе мы перебираем наши экземпляры и применяем правила нашего шаблона. Мы извлекаем объекты и применяем аннотацию к экземпляру(см. пример IOB2 ниже).

from extr.entities import create_entity_extractor, \
                          LabelOnlyEntityAnnotator

text_annotations: List[str] = []
extracted_text_by_label: Dict[str, Set[str]] = {}

annotator = LabelOnlyEntityAnnotator()
entity_extractor = create_entity_extractor(entity_patterns, kb)

for row in dataset:
    entities = entity_extractor.get_entities(row)
    annotations.append(
        annotator.annotate(row, entities).annotated_text
    )

    for entity in entities:
        label = entity.label
        text = entity.text

        if not label in extracted_text_by_label:
            extracted_text_by_label[label] = set()

        extracted_text_by_label[label].add(text)

Аннотации

(6:37–1-е) Л. Фурнетт оставил подкат на DAL 25 на 2 ярда (Н. Галлимор; Дж. Кирс).

(‹ВРЕМЯ›6:37‹/ВРЕМЯ› — ‹ПЕРИОД›1-й‹/ПЕРИОД›) ‹ИГРОК›Л.Фурнетт‹/ИГРОК› ‹НАПРАВЛЕНИЕ›налево‹/НАПРАВЛЕНИЕ› подкатите к ‹КОМАНДА›ДАЛ‹/КОМАНДА› ‹ КОЛИЧЕСТВО›25‹/КОЛИЧЕСТВО› за ‹КОЛИЧЕСТВО›2‹/КОЛИЧЕСТВО› ярдов (‹ИГРОК›Н.Галлимор‹/ИГРОК›; ‹ИГРОК›Дж.Кирс‹/ИГРОК›).

Извлеченный текст по метке

Быстро просмотрите все, что было проанализировано, с помощью словаря extracted_text_by_label.

{
  "PLAYER": [
    "A.Abdullah",
    "A.Adams",
    "A.Al-Shaair",
    "A.Amos",
    ...
  ],
  "QUANTITY": [
    "-1",
    "-10",
    "-14",
    ...
  ],
  "PERIOD": [
    "1st",
    "2nd",
    "3rd",
    "4th",
    "OT"
  ],
  ...
]

Хотите вместо этого IOB2?

from extr_ds.labelers import IOB

def sentence_tokenizer(text: str) -> List[str]:
    return ## sentence tokenizer of your choice ##

observations = IOB(sentence_tokenizer, entity_extractor).label(text)

На этом этапе можно построить слабую модель, которая поможет в дальнейшей помощи в нашей маркировке.