Как насчет замены #
на di git?
В первой версии этого ответа я выбрал di git 9
, потому что он напоминает мне номер COBOL c полевые форматы, которые я использовал около 30 лет go ... Но затем я взглянул на набор данных и понял, что для правильной обработки НЛП нужно разобраться хотя бы в двух вещах:
- порядковые номера (1-й, 2-й, ...)
- даты
Порядковые цифры требуют специальной обработки для любого выбора di git, но di git 1
дает разумные даты, за исключением года (конечно, 1111 может или не может быть истолкован как действительный год, но давайте будем осторожнее). 11/11/2020
явно лучше, чем 99/99/9999
...
Вот код:
import re
ic = re.IGNORECASE
subs = [
(re.compile(r'\b1(nd)\b', flags=ic), r'2\1'), # 1nd -> 2nd
(re.compile(r'\b1(rd)\b', flags=ic), r'3\1'), # 1rd -> 3rd
(re.compile(r'\b1(th)\b', flags=ic), r'4\1'), # 1th -> 4th
(re.compile(r'11(st)\b', flags=ic), r'21\1'), # ...11st -> ...21st
(re.compile(r'11(nd)\b', flags=ic), r'22\1'), # ...11nd -> ...22nd
(re.compile(r'11(rd)\b', flags=ic), r'23\1'), # ...11rd -> ...23rd
(re.compile(r'\b1111\b'), '2020') # 1111 -> 2020
]
text = '''spain 's colonial posts #.## billion euro loss
#nd, #rd, #th, ##st, ##nd, ##RD, ##TH, ###st, ###nd, ###rd, ###th.
ID=#nd#### year=#### OK'''
text = text.replace('#', '1')
for pattern, repl in subs:
text = re.sub(pattern, repl, text)
print(text)
# spain 's colonial posts 1.11 billion euro loss
# 2nd, 3rd, 4th, 21st, 22nd, 23RD, 11TH, 121st, 122nd, 123rd, 111th.
# ID=1nd1111 year=2020 OK
Если предварительная обработка корпуса преобразует любой ди git в #
в любом случае, вы не потеряете информацию с этим преобразованием. Некоторая «истинная» #
станет 1
, но это, вероятно, будет незначительной проблемой по сравнению с числами, которые не распознаются как таковые. Кроме того, при визуальном осмотре около 500000 строк набора данных я не смог найти ни одного кандидата для «истинного» * 1024 *.
Примечание: \b
в приведенных выше регулярных выражениях обозначает для «границы слова», т. е. границы между символом \w
(слово) и символом \W
(не словом), где символом слова является любой алфавитный символ c (дополнительная информация здесь ). \1
в замене обозначает первую группу, то есть первую пару круглых скобок (дополнительная информация здесь ). При использовании \1
регистр всего текста сохраняется, что было бы невозможно при замене строк, таких как 2nd
. Позже я обнаружил, что ваш набор данных нормализован для всех строчных букв, но я решил оставить его обобщенным c.
Если вам нужно получить текст с #
s обратно из частей речи, это просто
token.text.replace('0','#').replace('1','#').replace('2','#').replace('3','#').replace('4','#')