如何将字符索引转换为 SpaCy 令牌索引?
How to transform character indices to SpaCy token indices?
我正在使用 SpaCy 查找文本中的模式。
对于某些模式(例如单个单词),这很简单,我对结果很满意。
例如,
import re
import spacy
from spacy.matcher import Matcher
nlp = spacy.load("en_core_web_sm")
matcher = Matcher(nlp.vocab)
matcher.add("Month", [[{"TEXT": "January"}]])
doc = nlp("The date 1 January 2022 can also be written as 1/1/2022.")
for match_id, start, end in matcher(doc):
match_id_string = matcher.vocab.strings[match_id]
span = doc[start:end]
print(match_id_string, span.text, start, end)
将在 doc
中找到“January”作为第四个标记并将其识别为“Month”模式。
对于日期模式,事情要复杂一些。
我使用 SpaCy 来搜索被表述为正则表达式的模式。
添加代码
matcher.add("Date", [[{"TEXT": {"REGEX": "1/1/2022"}}]])
其中“1/1/2022”是一个(非常简单的)正则表达式,
将在上面定义的 doc
中找到日期“1/1/2022”
并将其识别为“日期”模式。
但是添加
matcher.add("Date", [[{"TEXT": {"REGEX": "1 January 2022"}}]])
找不到日期“2022 年 1 月 1 日”。
作为 SpaCy 网站上的 explained
这是因为匹配器只匹配单个标记。
SpaCy提供的解决方案是
“在 doc.text
上与 re.finditer
匹配”:
for match in re.finditer("1 January 2022", doc.text):
start, end = match.span()
span = doc.char_span(start, end)
print(span.text, start, end)
这会发现“2022 年 1 月 1 日”是从索引 9 到 23 的字符范围。
但是,我想将使用 re.finditer
找到的匹配项放入
转换为通常的 SpaCy 格式的匹配项,
这是一个包含匹配 ID 和 tokens 的开始和结束索引的 3 元组
而不是字符范围的开始和结束索引。
问题:
如何将这些字符索引转换为标记索引?
SpaCy 是否提供了执行此操作的方法?
我想那将是理想的,但我没有找到。
否则,还有其他聪明的工具可以做到这一点吗?
我可以试着从头开始或多或少地做一个,
但这感觉就像重新发明轮子。
您可以从跨度中获取令牌索引。
for match in re.finditer("1 January 2022", doc.text):
start, end = match.span()
span = doc.char_span(start, end)
match = (match_id, span[0].i, span[-1].i + 1)
此外,如果您尝试匹配文字短语,您可以只使用 EntityRuler 已经支持的 PhraseMatcher - 您只需将字符串作为模式而不是字典传递。
我正在使用 SpaCy 查找文本中的模式。 对于某些模式(例如单个单词),这很简单,我对结果很满意。 例如,
import re
import spacy
from spacy.matcher import Matcher
nlp = spacy.load("en_core_web_sm")
matcher = Matcher(nlp.vocab)
matcher.add("Month", [[{"TEXT": "January"}]])
doc = nlp("The date 1 January 2022 can also be written as 1/1/2022.")
for match_id, start, end in matcher(doc):
match_id_string = matcher.vocab.strings[match_id]
span = doc[start:end]
print(match_id_string, span.text, start, end)
将在 doc
中找到“January”作为第四个标记并将其识别为“Month”模式。
对于日期模式,事情要复杂一些。 我使用 SpaCy 来搜索被表述为正则表达式的模式。 添加代码
matcher.add("Date", [[{"TEXT": {"REGEX": "1/1/2022"}}]])
其中“1/1/2022”是一个(非常简单的)正则表达式,
将在上面定义的 doc
中找到日期“1/1/2022”
并将其识别为“日期”模式。
但是添加
matcher.add("Date", [[{"TEXT": {"REGEX": "1 January 2022"}}]])
找不到日期“2022 年 1 月 1 日”。
作为 SpaCy 网站上的 explained
这是因为匹配器只匹配单个标记。
SpaCy提供的解决方案是
“在 doc.text
上与 re.finditer
匹配”:
for match in re.finditer("1 January 2022", doc.text):
start, end = match.span()
span = doc.char_span(start, end)
print(span.text, start, end)
这会发现“2022 年 1 月 1 日”是从索引 9 到 23 的字符范围。
但是,我想将使用 re.finditer
找到的匹配项放入
转换为通常的 SpaCy 格式的匹配项,
这是一个包含匹配 ID 和 tokens 的开始和结束索引的 3 元组
而不是字符范围的开始和结束索引。
问题: 如何将这些字符索引转换为标记索引?
SpaCy 是否提供了执行此操作的方法? 我想那将是理想的,但我没有找到。 否则,还有其他聪明的工具可以做到这一点吗? 我可以试着从头开始或多或少地做一个, 但这感觉就像重新发明轮子。
您可以从跨度中获取令牌索引。
for match in re.finditer("1 January 2022", doc.text):
start, end = match.span()
span = doc.char_span(start, end)
match = (match_id, span[0].i, span[-1].i + 1)
此外,如果您尝试匹配文字短语,您可以只使用 EntityRuler 已经支持的 PhraseMatcher - 您只需将字符串作为模式而不是字典传递。