Как заключить в кавычки некоторые специальные слова (номера реестра), чтобы они не были помечены с помощью Spacy?

#python-3.x #spacy

#python-3.x #spacy

Вопрос:

У меня есть несколько чисел внутри текста, которые я хотел бы сохранить в виде одного предложения. Некоторые из них:

 7-2017-19121-B
7-2016-26132
wd/2012/0616
JLG486-01
H14-0890-12
  

Как я могу защитить их, чтобы они не были разделены на слова. Я уже использую regex для пользовательского tokenizer, чтобы никогда не разделять слова тире, но это работает только с буквами, а не с цифрами. Я не хочу менять регулярное выражение по умолчанию, которое является большим и очень сложным. Как я могу сделать это легко?

Что я уже сделал, так это использовал этот «протектор дефиса». Для 7-2014-1721-Y меня есть токены [7,-,2014,-,1721-Y] , поэтому последняя фраза не разделена, но разделены предыдущие. Как я уже сказал, код сложный, и я хотел бы добавить то же самое, чтобы включить такое действие для объекта number-number.

Это функция:

 def custom_tokenizer(nlp):
    prefix_re = compile_prefix_regex(nlp.Defaults.prefixes)
    suffix_re = compile_suffix_regex(nlp.Defaults.suffixes)
    # changing default infixed
    def_infx = nlp.Defaults.infixes    
    cur_infx = (d.replace('-|–|—|', '') for d in def_infx)
    infix_re = compile_infix_regex(cur_infx)

    return Tokenizer(nlp.vocab, prefix_search=prefix_re.search, suffix_search=suffix_re.search,
                                infix_finditer=infix_re.finditer, token_match=None)
  

Может быть, есть какой-то более простой способ, кроме модификации? Я пытался заключить эти «таблички» в кавычки с помощью некоторых escape-символов, таких как {7-2017-19121-B} , но это не работает.

Кстати, есть регулярное выражение, которое соответствует этим специальным «номерам». Возможно, обходным путем для меня будет просто удаление их из текста (что я попробую позже), но сейчас я спрашиваю, есть ли у меня здесь какие-либо шансы.

["(?=[^ds]*d)(?:[a-zA-Zd] (?:/[a-zA-Zd] ) )", "(?:[[A-Zd] (?:[-][A-Zd] ) )"]

Подсказка. Я обнаружил, что изменение с 7-2017-19121-B на 7/2017/19121/B работает по мере необходимости. Вопрос в том (мне нужно проверить), как я могу адаптировать это к моему текущему коду и сохранить производительность, которая у меня есть сейчас.

Ответ №1:

Вы можете добавить их как «особые случаи»:

 nlp.tokenizer.add_special_case("7-2017-19121-B", [{ORTH: "7-2017-19121-B"}])
...
nlp.tokenizer.add_special_case("H14-0890-12", [{ORTH: "H14-0890-12"}])
  

Тест:

 print([w.text for w in nlp("Got JLG486-01 and 7-2017-19121-B codes.")]) 
# => ['Got', 'JLG486-01', 'and', '7-2017-19121-B', 'codes', '.']
  

Комментарии:

1. Спасибо за некоторую идею. Проблема в том, что мне нужна такая же производительность (с очень малыми потерями), потому что я работаю с миллионами записей. Здесь вызывается tokenizer для каждого предложения… Возможно, это не проблема, в любом случае, я попробую ваш пример.

2. @Peter. k Ну, это простой способ. Если у вас есть регулярное выражение, которое соответствует словам, и вы хотите использовать его с re.sub , идите этим путем. Если у вас возникнут проблемы с регулярным выражением, я буду рад помочь.

3. Это работает, и я использую это сейчас., Что-то замедляется, но трудно протестировать проект на текущем этапе.