使用 Matcher spaCy 只匹配最大的模式而不匹配子模式
Match only the largest pattern and not sub patterns with Matcher spaCy
我正在使用 Matcher class 和 spaCy v3.1.3。从句子中提取模式。
我有一个名为“Inteval”的标签和两个我想要捕获的模式。然而,最大的模式(下面显示的第二个“模式”)是由第一个“模式”中指定的子模式组成的,我希望当有来自最大模式的匹配时,只提取最大的模式而不是子模式。
例如,我的句子包含以下类型的字符串:“500 km até 543 km”、“13 a 22 km”、“550 km - 500 km”和“568 km até 420 km até 190 km” .我希望它们都具有相同的标签(“间隔”)。在这种情况下:“568 km até 420 km até 190 km”,有没有办法只提取“568 km até 420 km até 190 km”而不提取:“568 km até 420 km”,“420 km até 190”千米"?
import spacy
from spacy.matcher import Matcher
nlp = spacy.load('pt_core_news_lg')
UN = ['km']
TEXTS = ['500 km até 543 km', 'de 568 km até 420 km até 190 km', 'de 700 km até 400 km até 100 km']
matcher = Matcher(nlp.vocab)
# Examples:
# 500 km até 543 km
# 13 a 22 km
# 550 km - 500 km
pattern = []
pattern.append([{'POS': 'NUM'},
{'OP': '?', 'TEXT': {'IN': UN}},
{'TEXT': {'IN': ['a', 'até', '-']}},
{'POS': 'NUM'},
{'TEXT': {'IN': UN}}
])
# Example:
# 568 km até 420 km até 190 km
pattern.append([{'POS': 'NUM'},
{'OP': '?', 'TEXT': {'IN': UN}},
{'TEXT': {'IN': ['a', 'até']}},
{'POS': 'NUM'},
{'TEXT': {'IN': UN}},
{'TEXT': {'IN': ['a', 'até']}},
{'POS': 'NUM'},
{'TEXT': {'IN': UN}}
])
matcher.add('Intervalo', pattern)
TRAINING_DATA = []
for doc in nlp.pipe(TEXTS):
spans = [doc[start:end] for match_id, start, end in matcher(doc)]
entities = [(span.start_char, span.end_char, "Intervalo") for span in spans]
training_example = (doc.text, {"entities": entities})
TRAINING_DATA.append(training_example)
print(*TRAINING_DATA, sep="\n")
结果:
('500 km até 543 km', {'entities': [(0, 17, 'Intervalo')]})
('de 568 km até 420 km até 190 km', {'entities': [(3, 20, 'Intervalo'), (3, 31, 'Intervalo'), (14, 31, 'Intervalo')]})
('de 700 km até 400 km até 100 km', {'entities': [(3, 20, 'Intervalo'), (3, 31, 'Intervalo'), (14, 31, 'Intervalo')]})
您正在直接使用 Matcher,但如果您改用 EntityRuler(就像里面的 Matcher),它将自动为您处理 - 当匹配重叠时,它需要最长的一个,或者如果长度相等,则较早开始的那个。
我正在使用 Matcher class 和 spaCy v3.1.3。从句子中提取模式。
我有一个名为“Inteval”的标签和两个我想要捕获的模式。然而,最大的模式(下面显示的第二个“模式”)是由第一个“模式”中指定的子模式组成的,我希望当有来自最大模式的匹配时,只提取最大的模式而不是子模式。
例如,我的句子包含以下类型的字符串:“500 km até 543 km”、“13 a 22 km”、“550 km - 500 km”和“568 km até 420 km até 190 km” .我希望它们都具有相同的标签(“间隔”)。在这种情况下:“568 km até 420 km até 190 km”,有没有办法只提取“568 km até 420 km até 190 km”而不提取:“568 km até 420 km”,“420 km até 190”千米"?
import spacy
from spacy.matcher import Matcher
nlp = spacy.load('pt_core_news_lg')
UN = ['km']
TEXTS = ['500 km até 543 km', 'de 568 km até 420 km até 190 km', 'de 700 km até 400 km até 100 km']
matcher = Matcher(nlp.vocab)
# Examples:
# 500 km até 543 km
# 13 a 22 km
# 550 km - 500 km
pattern = []
pattern.append([{'POS': 'NUM'},
{'OP': '?', 'TEXT': {'IN': UN}},
{'TEXT': {'IN': ['a', 'até', '-']}},
{'POS': 'NUM'},
{'TEXT': {'IN': UN}}
])
# Example:
# 568 km até 420 km até 190 km
pattern.append([{'POS': 'NUM'},
{'OP': '?', 'TEXT': {'IN': UN}},
{'TEXT': {'IN': ['a', 'até']}},
{'POS': 'NUM'},
{'TEXT': {'IN': UN}},
{'TEXT': {'IN': ['a', 'até']}},
{'POS': 'NUM'},
{'TEXT': {'IN': UN}}
])
matcher.add('Intervalo', pattern)
TRAINING_DATA = []
for doc in nlp.pipe(TEXTS):
spans = [doc[start:end] for match_id, start, end in matcher(doc)]
entities = [(span.start_char, span.end_char, "Intervalo") for span in spans]
training_example = (doc.text, {"entities": entities})
TRAINING_DATA.append(training_example)
print(*TRAINING_DATA, sep="\n")
结果:
('500 km até 543 km', {'entities': [(0, 17, 'Intervalo')]})
('de 568 km até 420 km até 190 km', {'entities': [(3, 20, 'Intervalo'), (3, 31, 'Intervalo'), (14, 31, 'Intervalo')]})
('de 700 km até 400 km até 100 km', {'entities': [(3, 20, 'Intervalo'), (3, 31, 'Intervalo'), (14, 31, 'Intervalo')]})
您正在直接使用 Matcher,但如果您改用 EntityRuler(就像里面的 Matcher),它将自动为您处理 - 当匹配重叠时,它需要最长的一个,或者如果长度相等,则较早开始的那个。