#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. Это работает, и я использую это сейчас., Что-то замедляется, но трудно протестировать проект на текущем этапе.