#python #nlp #spacy
Вопрос:
Я новичок в spacy и играю со следующим сценарием;
import spacy
from spacy.language import Language
from spacy.matcher import Matcher
nlp = spacy.load('en_core_web_sm')
text = "Google announced a new Pixel at Google I/O. The Google I/O is a great place to get all the updates from Google I/O."
def add_event_ent(matcher, doc, i, matches):
match_id, start, end = matches[i]
entity = doc[start:end]
print(entity.text, start, end)
pattern = [[
{"TEXT": "Google"},
{"TEXT": "I"},
{"TEXT": "/"},
{"TEXT": "O"},
{"IS_PUNCT": True, "OP": "?"}
]]
matcher = Matcher(nlp.vocab)
matcher.add("Google", pattern, on_match = add_event_ent)
doc = nlp(text)
matcher(doc)
Выход:
Google I/O 11 15
[(11578853341595296054, 11, 15)]
Я ожидал бы, что это обнаружит все 3 случая Google I/O
, но это не так, и я не совсем уверен, почему. Я попробовал несколько разных вещей, но ничего не сработало, я думаю, что проблема в полной остановке.
Я написал то, что в основном является одним и тем же фрагментом кода с другим текстом и шаблоном:
text = "Hello, World! Hello, World! How are you?"
pattern = [[
{"LOWER": "hello"},
{"IS_PUNCT": True},
{"LOWER": "world"}
]]
matcher = Matcher(nlp.vocab)
matcher.add("Google", pattern, on_match = add_event_ent)
doc = nlp(text)
matcher(doc)
for ent in doc.ents:
print(f"[ENTITY] {ent.text:{15}} {ent.label_}")
print(doc)
Выход:
Hello, World 0 3
Hello, World 4 7
Hello, World! Hello, World! How are you?
Что, как вы можете видеть, сработало.
Я сделал это для первого примера, на случай, если это поможет, и это показывает, что это не работает, но опять же я не уверен, почему.
Комментарии:
1. Проблема связана с токенизацией,
O.
имеет.
внутри этот токен.2. Хм, я понимаю, в этом есть смысл, почему он обнаруживает только один из 3. Но как мне это исправить?
Ответ №1:
Проблема связана с токенизацией, O.
токен содержит .
символ в конце текста этого токена.
Вместо определения необязательного знака препинания в pattern
вы можете сопоставить любой O
знак с необязательным конечным символом препинания. Для этого вы можете использовать регулярное выражение:
pattern = [[
{"TEXT": "Google"},
{"TEXT": "I"},
{"TEXT": "/"},
{"TEXT": {"REGEX": r"^O(?:_|[^ws])?$"}}
]]
Выход:
Google I/O. 6 10
Google I/O 11 15
Google I/O. 25 29
Здесь {"TEXT": {"REGEX": r"^O(?:_|[^ws])?$"}}
будет соответствовать маркеру, который содержит один или два символа, начиная с O
и затем содержащий необязательный знак препинания.
^
— запуск токена (строки, в общем случае)O
—O
чар(?:_|[^ws])?
— a_
или (|
) любой символ, отличный от символа слова и пробела ([^ws]
, класс отрицаемых символов,w
обозначает буквы, цифры и подчеркивания иs
обозначает пробелы), один или ноль раз (из-за?
квантора)$
— конец токена (строки, в общем случае)