当我手动构建文档时,Spacy 标记化为带有连字符分隔符的日期添加额外的白色 space
Spacy tokenization add extra white space for dates with hyphen separator when I manually build the Doc
一段时间以来,我一直在尝试解决 spacy Tokenizer 的问题,但没有成功。另外,我不确定是分词器还是管道的其他部分有问题。
欢迎任何帮助!
描述
我有一个应用程序,出于除此之外的原因,它从 spacy 词汇和字符串中的标记列表创建了一个 spacy Doc
(请参见下面的代码)。请注意,虽然这不是执行此操作的最简单和最常用的方法,但根据 spacy doc 这是可以做到的。
但是,当我为包含以连字符作为分隔符的复合词或日期的文本创建 Doc
时,我得到的行为不是我所期望的。
import spacy
from spacy.language import Doc
# My current way
doc = Doc(nlp.vocab, words=tokens) # Tokens is a well defined list of tokens for a certein string
# Standard way
doc = nlp("My text...")
例如,对于以下文本,如果我使用标准程序创建 Doc
,spacy Tokenizer
会将 "-"
识别为标记,但 Doc
text 与输入文本相同,此外 spacy NER 模型正确识别 DATE 实体。
import spacy
doc = nlp("What time will sunset be on 2022-12-24?")
print(doc.text)
tokens = [str(token) for token in doc]
print(tokens)
# Show entities
print(doc.ents[0].label_)
print(doc.ents[0].text)
输出:
What time will sunset be on 2022-12-24?
['What', 'time', 'will', 'sunset', 'be', 'on', '2022', '-', '12', '-', '24', '?']
DATE
2022-12-24
另一方面,如果我从模型的 vocab
和之前计算的标记创建 Doc
,得到的结果是不同的。请注意,为了简单起见,我使用了 doc
中的标记,因此我确信标记没有差异。另请注意,我手动 运行 每个管道模型以 doc
的正确顺序排列,因此在该过程结束时,理论上我会得到相同的结果。
但是,正如您在下面的输出中看到的,虽然 Doc 的标记相同,但 Doc 的文本不同,数字和日期分隔符之间有空白 space。
doc2 = Doc(nlp.vocab, words=tokens)
# Run each model in pipeline
for model_name in nlp.pipe_names:
pipe = nlp.get_pipe(model_name)
doc2 = pipe(doc2)
# Print text and tokens
print(doc2.text)
tokens = [str(token) for token in doc2]
print(tokens)
# Show entities
print(doc.ents[0].label_)
print(doc.ents[0].text)
输出:
what time will sunset be on 2022 - 12 - 24 ?
['what', 'time', 'will', 'sunset', 'be', 'on', '2022', '-', '12', '-', '24', '?']
DATE
2022 - 12 - 24
我知道我错过的一定是愚蠢的东西,但我没有意识到。
有人可以向我解释我做错了什么并指出正确的方向吗?
非常感谢!
编辑
按照 Talha Tayyab 的建议,我必须创建一个布尔值数组,其长度与我的标记列表中的每个标记的长度相同,如果标记后跟一个空 space。然后在 doc 构造中传递这个数组,如下所示:doc = Doc(nlp.vocab, words=words, spaces=spaces)
.
为了根据我的原始文本字符串和标记列表计算这个布尔值列表,我实现了以下普通函数:
def get_spaces(self, text: str, tokens: List[str]) -> List[bool]:
# Spaces
spaces = []
# Copy text to easy operate
t = text.lower()
# Iterate over tokens
for token in tokens:
if t.startswith(token.lower()):
t = t[len(token):] # Remove token
# If after removing token we have an empty space
if len(t) > 0 and t[0] == " ":
spaces.append(True)
t = t[1:] # Remove space
else:
spaces.append(False)
return spaces
通过我的代码中的这两个改进,获得的结果符合预期。但是,现在我有以下问题:
是否有更类似 spacy 的方法来计算白色space,而不是使用我的普通实现?
请试试这个:
from spacy.language import Doc
doc2 = Doc(nlp.vocab, words=tokens,spaces=[1,1,1,1,1,1,0,0,0,0,0,0])
# Run each model in pipeline
for model_name in nlp.pipe_names:
pipe = nlp.get_pipe(model_name)
doc2 = pipe(doc2)
# Print text and tokens
print(doc2.text)
tokens = [str(token) for token in doc2]
print(tokens)
# Show entities
print(doc.ents[0].label_)
print(doc.ents[0].text)
# You can also replace 0 with False and 1 with True
这是完整的语法:
doc = Doc(nlp.vocab, words=words, spaces=spaces)
space是一个布尔值列表,表示每个单词是否有后续的space。如果指定,必须与单词具有相同的长度。默认为 True 序列。
因此您可以选择要拥有哪些 space 以及不需要哪些。
一段时间以来,我一直在尝试解决 spacy Tokenizer 的问题,但没有成功。另外,我不确定是分词器还是管道的其他部分有问题。
欢迎任何帮助!
描述
我有一个应用程序,出于除此之外的原因,它从 spacy 词汇和字符串中的标记列表创建了一个 spacy Doc
(请参见下面的代码)。请注意,虽然这不是执行此操作的最简单和最常用的方法,但根据 spacy doc 这是可以做到的。
但是,当我为包含以连字符作为分隔符的复合词或日期的文本创建 Doc
时,我得到的行为不是我所期望的。
import spacy
from spacy.language import Doc
# My current way
doc = Doc(nlp.vocab, words=tokens) # Tokens is a well defined list of tokens for a certein string
# Standard way
doc = nlp("My text...")
例如,对于以下文本,如果我使用标准程序创建 Doc
,spacy Tokenizer
会将 "-"
识别为标记,但 Doc
text 与输入文本相同,此外 spacy NER 模型正确识别 DATE 实体。
import spacy
doc = nlp("What time will sunset be on 2022-12-24?")
print(doc.text)
tokens = [str(token) for token in doc]
print(tokens)
# Show entities
print(doc.ents[0].label_)
print(doc.ents[0].text)
输出:
What time will sunset be on 2022-12-24?
['What', 'time', 'will', 'sunset', 'be', 'on', '2022', '-', '12', '-', '24', '?']
DATE
2022-12-24
另一方面,如果我从模型的 vocab
和之前计算的标记创建 Doc
,得到的结果是不同的。请注意,为了简单起见,我使用了 doc
中的标记,因此我确信标记没有差异。另请注意,我手动 运行 每个管道模型以 doc
的正确顺序排列,因此在该过程结束时,理论上我会得到相同的结果。
但是,正如您在下面的输出中看到的,虽然 Doc 的标记相同,但 Doc 的文本不同,数字和日期分隔符之间有空白 space。
doc2 = Doc(nlp.vocab, words=tokens)
# Run each model in pipeline
for model_name in nlp.pipe_names:
pipe = nlp.get_pipe(model_name)
doc2 = pipe(doc2)
# Print text and tokens
print(doc2.text)
tokens = [str(token) for token in doc2]
print(tokens)
# Show entities
print(doc.ents[0].label_)
print(doc.ents[0].text)
输出:
what time will sunset be on 2022 - 12 - 24 ?
['what', 'time', 'will', 'sunset', 'be', 'on', '2022', '-', '12', '-', '24', '?']
DATE
2022 - 12 - 24
我知道我错过的一定是愚蠢的东西,但我没有意识到。
有人可以向我解释我做错了什么并指出正确的方向吗?
非常感谢!
编辑
按照 Talha Tayyab 的建议,我必须创建一个布尔值数组,其长度与我的标记列表中的每个标记的长度相同,如果标记后跟一个空 space。然后在 doc 构造中传递这个数组,如下所示:doc = Doc(nlp.vocab, words=words, spaces=spaces)
.
为了根据我的原始文本字符串和标记列表计算这个布尔值列表,我实现了以下普通函数:
def get_spaces(self, text: str, tokens: List[str]) -> List[bool]:
# Spaces
spaces = []
# Copy text to easy operate
t = text.lower()
# Iterate over tokens
for token in tokens:
if t.startswith(token.lower()):
t = t[len(token):] # Remove token
# If after removing token we have an empty space
if len(t) > 0 and t[0] == " ":
spaces.append(True)
t = t[1:] # Remove space
else:
spaces.append(False)
return spaces
通过我的代码中的这两个改进,获得的结果符合预期。但是,现在我有以下问题:
是否有更类似 spacy 的方法来计算白色space,而不是使用我的普通实现?
请试试这个:
from spacy.language import Doc
doc2 = Doc(nlp.vocab, words=tokens,spaces=[1,1,1,1,1,1,0,0,0,0,0,0])
# Run each model in pipeline
for model_name in nlp.pipe_names:
pipe = nlp.get_pipe(model_name)
doc2 = pipe(doc2)
# Print text and tokens
print(doc2.text)
tokens = [str(token) for token in doc2]
print(tokens)
# Show entities
print(doc.ents[0].label_)
print(doc.ents[0].text)
# You can also replace 0 with False and 1 with True
这是完整的语法:
doc = Doc(nlp.vocab, words=words, spaces=spaces)
space是一个布尔值列表,表示每个单词是否有后续的space。如果指定,必须与单词具有相同的长度。默认为 True 序列。
因此您可以选择要拥有哪些 space 以及不需要哪些。