Отладка CLI spaCy показывает 0 документов train / dev в формате JSON в формате CLI, преобразованном spacy.gold.docs_to_json - PullRequest
0 голосов
/ 23 октября 2019

Issue

Я пытаюсь запустить spaCy CLI, но мои данные о тренировках и данные о разработчиках кажутся как-то неправильными, как видно при запуске отладки:

| => python3 -m spacy debug-data en 

./CLI_train_randsplit_anno191022.json ./CLI_dev_randsplit_anno191022.json --pipeline ner --verbose 




=========================== Data format validation =========================== 

✔ Corpus is loadable 




=============================== Training stats =============================== 

Training pipeline: ner 

Starting with blank model 'en' 

0 training docs 

0 evaluation docs 

✔ No overlap between training and evaluation data 

✘ Low number of examples to train from a blank model (0) 

It's recommended to use at least 2000 examples (minimum 100) 




============================== Vocab & Vectors ============================== 

ℹ 0 total words in the data (0 unique) 

10 most common words: 

ℹ No word vectors present in the model 




========================== Named Entity Recognition ========================== 

ℹ 0 new labels, 0 existing labels 

0 missing values (tokens with '-' label) 

✔ Good amount of examples for all labels 

✔ Examples without occurrences available for all labels 

✔ No entities consisting of or starting/ending with whitespace 




================================== Summary ================================== 

✔ 5 checks passed 

✘ 1 error 

Попытка тренироваться в любом случаевыходы:

| => python3 -m spacy train en ./models/CLI_1 ./CLI_train_randsplit_anno191022.json ./CLI_dev_randsplit_anno191022.json -n 150 -p 'ner' --verbose 

dropout_from = 0.2 by default 

dropout_to = 0.2 by default 

dropout_decay = 0.0 by default 

batch_from = 100.0 by default 

batch_to = 1000.0 by default 

batch_compound = 1.001 by default 

Training pipeline: ['ner'] 

Starting with blank model 'en' 

beam_width = 1 by default 

beam_density = 0.0 by default 

beam_update_prob = 1.0 by default 

Counting training words (limit=0) 

learn_rate = 0.001 by default 

optimizer_B1 = 0.9 by default 

optimizer_B2 = 0.999 by default 

optimizer_eps = 1e-08 by default 

L2_penalty = 1e-06 by default 

grad_norm_clip = 1.0 by default 

parser_hidden_depth = 1 by default 

subword_features = True by default 

conv_depth = 4 by default 

bilstm_depth = 0 by default 

parser_maxout_pieces = 2 by default 

token_vector_width = 96 by default 

hidden_width = 64 by default 

embed_size = 2000 by default 




Itn  NER Loss   NER P   NER R   NER F   Token %  CPU WPS 

---  ---------  ------  ------  ------  -------  ------- 

✔ Saved model to output directory 

models/CLI_1/model-final 




Traceback (most recent call last): 

  File "/usr/local/lib/python3.7/site-packages/spacy/cli/train.py", line 389, in train 

    scorer = nlp_loaded.evaluate(dev_docs, verbose=verbose) 

  File "/usr/local/lib/python3.7/site-packages/spacy/language.py", line 673, in evaluate 

    docs, golds = zip(*docs_golds) 

ValueError: not enough values to unpack (expected 2, got 0) 




During handling of the above exception, another exception occurred: 




Traceback (most recent call last): 

  File "/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/runpy.py", line 193, in _run_module_as_main 

    "__main__", mod_spec) 

  File "/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/runpy.py", line 85, in _run_code 

    exec(code, run_globals) 

  File "/usr/local/lib/python3.7/site-packages/spacy/__main__.py", line 35, in <module> 

    plac.call(commands[command], sys.argv[1:]) 

  File "/usr/local/lib/python3.7/site-packages/plac_core.py", line 328, in call 

    cmd, result = parser.consume(arglist) 

  File "/usr/local/lib/python3.7/site-packages/plac_core.py", line 207, in consume 

    return cmd, self.func(*(args + varargs + extraopts), **kwargs) 

  File "/usr/local/lib/python3.7/site-packages/spacy/cli/train.py", line 486, in train 

    best_model_path = _collate_best_model(meta, output_path, nlp.pipe_names) 

  File "/usr/local/lib/python3.7/site-packages/spacy/cli/train.py", line 548, in _collate_best_model 

    bests[component] = _find_best(output_path, component) 

  File "/usr/local/lib/python3.7/site-packages/spacy/cli/train.py", line 567, in _find_best 

    accs = srsly.read_json(epoch_model / "accuracy.json") 

  File "/usr/local/lib/python3.7/site-packages/srsly/_json_api.py", line 50, in read_json 

    file_path = force_path(location) 

  File "/usr/local/lib/python3.7/site-packages/srsly/util.py", line 21, in force_path 

    raise ValueError("Can't read file: {}".format(location)) 

ValueError: Can't read file: models/CLI_1/model0/accuracy.json 

Мои документы для обучения и разработки были сгенерированы с помощью spacy.gold.docs_to_json (), сохранены в виде файлов json с помощью функции:

def make_CLI_json(mock_docs, CLI_out_file_path): 
    CLI_json = docs_to_json(mock_docs) 
    with open(CLI_out_file_path, 'w') as json_file: 
        json.dump(CLI_json, json_file) 

Я проверил их обадействительный json в http://www.jsonlint.com.

Я создал документы, из которых эти json были созданы, используя функцию:

def import_from_doccano(jx_in_file_path, view=True): 
    annotations = load_jsonl(jx_in_file_path)     
    mock_nlp = English()     
    sentencizer = mock_nlp.create_pipe("sentencizer")     
    unlabeled = 0     
    DATA = []     
    mock_docs = [] 

    for anno in annotations:                      
        # get DATA (as used in spacy inline training)     
        if "label" in anno.keys():     
            ents = [tuple([label[0], label[1], label[2]])     
                               for label in anno["labels"]] 
        else: 
            ents = [] 

        DATUM = (anno["text"], {"entities": ents}) 
        DATA.append(DATUM) 

        # mock a doc for viz in displacy 
        mock_doc = mock_nlp(anno["text"]) 
        if "labels" in anno.keys():     
            entities = anno["labels"]     
            if not entities:     
                unlabeled += 1     
            ents = [(e[0], e[1], e[2]) for e in entities]     
            spans = [mock_doc.char_span(s, e, label=L) for s, e, L in ents]     
            mock_doc.ents = _cleanup_spans(spans)     
            sentencizer(mock_doc) 

            if view:     
                displacy.render(mock_doc, style='ent') 

        mock_docs.append(mock_doc)                      
    print(f'Unlabeled: {unlabeled}')                      
    return DATA, mock_docs 

Я написал функцию выше, чтобы возвращать примеры в обоих форматах, необходимых для inlineобучение (например, как показано в https://github.com/explosion/spaCy/blob/master/examples/training/train_ner.py), а также для формирования такого рода «фиктивных» документов, чтобы я мог использовать вытеснение и / или CLI. Для последней цели я следовал коду, показанному в https://github.com/explosion/spaCy/blob/master/spacy/cli/converters/jsonl2json.py с парой заметных отличий. Функция _cleanup_spans () идентична той, что в примере. Я не использовал минибат (), но создал отдельный документ для каждой помеченной аннотации. итак?) Я обнаружил, что использование предложения с помощью предложения разрушило многие мои аннотации, возможно, из-за того, что диапазоны смещены таким образом, что функция _cleanup_spans () не может исправить должным образом. Удаление предложения приводит к тому, что функция docs_to_json () выдает ошибку. Поэтому в моей функции (в отличие от связанного примера) я запускаю предложение на каждом документе после , в которые записываются сущности, что правильно сохраняет мои аннотации и позволяет запускать функцию docs_to_json () без жалоб.

Функция load_jsonl, вызываемая в import_from_doccano (), определяется как:

def load_jsonl(input_path):     
    data = []     
    with open(input_path, 'r', encoding='utf-8') as f:     
        for line in f:     
            data.append(json.loads(line.replace('\n|\r',''), strict=False))     
    print('Loaded {} records from {}'.format(len(data), input_path))     
    print()     
    return data 

Каждая моя аннотация имеет длину ~ 10000 символов или меньше. Они экспортируются из doccano

(https://doccano.herokuapp.com/) как JSONL, используя формат:

{"id": 1, "text": "EU rejects ...", "labels": [[0,2,"ORG"], [11,17, "MISC"], [34,41,"ORG"]]}
{"id": 2, "text": "Peter Blackburn", "labels": [[0, 15, "PERSON"]]}
{"id": 3, "text": "President Obama", "labels": [[10, 15, "PERSON"]]}
...

Данные разбиваются на наборы поездов и испытаний с помощью функции:

def test_train_split(DATA, mock_docs, n_train):
    L = list(zip(DATA, mock_docs))
    random.shuffle(L)
    DATA, mock_docs = zip(*L)
    DATA = [i for i in DATA]
    mock_docs = [i for i in mock_docs]
    TRAIN_DATA = DATA[:n_train]
    train_docs = mock_docs[:n_train]
    TEST_DATA = DATA[n_train:] 
    test_docs = mock_docs[n_train:]
    return TRAIN_DATA, TEST_DATA, train_docs, test_docs

И, наконец, каждый из них записывается в json с использованием следующей функции:

def make_CLI_json(mock_docs, CLI_out_file_path):
    CLI_json = docs_to_json(mock_docs)
    with open(CLI_out_file_path, 'w') as json_file:
        json.dump(CLI_json, json_file)

Я не понимаю, почему отладка показывает 0 учебных документов и 0 документов разработки или почему команда train не выполняется. Насколько я могу судить, JSON выглядит правильно. Неправильно ли отформатированы мои данные или что-то еще происходит? Буду признателен за любую помощь или советы.

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

Среда

Mac OS 10.15 Catalina Все в pip3 установлено в путь пользователя Нет виртуальной среды

| => python3 -m spacy info --markdown

## Info about spaCy

* **spaCy version:** 2.2.1
* **Platform:** Darwin-19.0.0-x86_64-i386-64bit
* **Python version:** 3.7.4

1 Ответ

2 голосов
/ 23 октября 2019

Это законно сбивающий с толку аспект API. По внутренним / историческим причинам spacy.gold.docs_to_json() создает указание, которое все еще необходимо заключить в список, чтобы добраться до окончательного формата обучения. Попробуйте:

srsly.write_json(filename, [spacy.gold.docs_to_json(docs)])

spacy debug-data пока не имеет надлежащих проверок схемы, поэтому это более расстраивает / сбивает с толку, чем должно быть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...