我正在使用Spacy,我对它如何分割句子有问题。由于某些原因,一些句子被分割成两个或多个部分,而不是一个,所以当我尝试用TensorFlow训练一个模型时,我得到了一个向量维数不匹配的错误。
我已经尝试将令牌更改为空白标记,如此链接中所示。因此,我的类看起来像( Benepar组件注释掉了):
class BeneparAnnotator(SyntaxAnnotator):
class WhitespaceTokenizer:
def __init__(self, vocab):
self.vocab = vocab
def __call__(self, text):
words = text.split(" ")
spaces = [True] * len(words)
# Avoid zero-length tokens
for i, word in enumerate(words):
if word == "":
words[i] = " "
spaces[i] = False
# Remove the final trailing space
if words[-1] == " ":
words = words[0:-1]
spaces = spaces[0:-1]
else:
spaces[-1] = False
return Doc(self.vocab, words=words, spaces=spaces)
def __init__(self):
self.nlp = spacy.load('en')
# self.nlp.add_pipe(BeneparComponent("benepar_en2"))
self.nlp.tokenizer = self.WhitespaceTokenizer(self.nlp.vocab)
self.extract_arc_representation = False
... other stuff ...
def ... other stuff ...现在,当用以下方法分析句子时:
def parse_sentences(nlp, captions: List[str]) -> List[Span]:
parsed_sentences = []
for caption in tqdm(captions, desc="Parsing sentences"):
parsed_caption = nlp(caption)
if len(list(parsed_caption.sents)) > 1: # This if is for debug
length = len(list(parsed_caption.sents))
as_list = list(parsed_caption.sents)
pass
parsed_sentence = list(parsed_caption.sents)[0]
parsed_sentences.append(parsed_sentence)
return parsed_sentences这种获得句子的方法取自这里,因为我想检索与Benepar解析的句子,但是其中一些句子被分成几个句子,而不是得到全部解析的句子,我得到了几个被解析的句子。
出于某种原因,对于某些句子,它们被分成2或3部分:
我还有其他类似于例1的句子,它们被正确地分割成一个句子。例如:
一只站在草地上的背羊
它被分成两部分:一只站在草地上的后羊
因此,当我用list(parsed_caption.sents)[0]得到一个标题时,我得到的是整个标题,而不是标题的一部分。
问题出在哪里?
-更新一下,想更好地解释我的问题
我有一个句子清单,我想用Benepar来分析,然后用它们作为工具的输入,看看我是否得到了更好的结果。由于该工具的anaconda环境的限制,我需要使用2019年版本,它是在Python3.6上工作的版本。
我遇到的问题是,一些句子被拆分,Benepar将它们解析为独立的块(而不是整个句子),当我试图用list(parsed_caption.sents)[0] (因为应该只有一个元素,整个句子)来获取它们时,我只得到了一个块,当我运行实验时,我得到了一个错误,即原始句子和解析的句子的大小不匹配。
我对这套训练有超过616 K的句子。它们中的大多数都被分析得很好,不被分割成块,如果我这样做的话:
caption = list(parsed_caption.sents)[0]然后:
caption._.parse_string我从Benepar那里得到了所有分析过的句子。
假设我有一句话:The time for action is now.
我在list(parsed_caption.sents)[0]中的预期内容应该是:
[The time for action is now.]因此,当我想得到caption._.parse_string解析的句子时,我得到:
(S (NP (NP (DT The) (NN time)) (PP (IN for) (NP (NN action)))) (VP (VBZ is) (ADVP (RB now))) (. .))但问题是,对于某些句子,它们被划分为(例如):
[The time, for action is now.]所以,如果我尝试用list(parsed_caption.sents)[0]来得到这个句子,我只会得到一大块的解析。我只期待一句话,不会再多了。
由于只有时间,当我训练模型和句子的时候,行动的时间到了。如果选中,我将得到一个错误,因为操作时间的长度是现在。时间也不一样。
发布于 2021-08-24 09:18:09
我终于找到了解决我的需要的办法。
由于tool 伯克利神经分析器提供了两个选项(NLTK和Spacy),所以我尝试了NLTK选项并设法实现了我的目标。由于环境的限制,我不得不使用支持Python3.6的2019年版本。
对于NLTK,我只需要做:
import benepar
class BeneparAnnotator(SyntaxAnnotator):
def __init__(self):
self.parser = benepar.Parser("benepar_en2")
self.extract_arc_representation = False
....然后:
for caption in tqdm(captions, desc="Parsing sentences"):
parsed_caption = parser.parse(caption)
tree_as_string = parsed_caption.pformat(margin=500, indent=0, nodesep='', parens='()', quotes=False)
parsed_sentences.append(tree_as_string)在tree_as_string中,您将得到解析的句子:
(S (NP (DT a) (NN restaurant)) (VP (VBZ has) (NP (JJ modern) (JJ wooden) (NNS tables) (CC and) (NNS chairs)))) 您必须调整margin参数以设置短语的长度,因为如果短语长度大于页边距,则pformat将以这种方式将其分割为几行带有\n字符的行(确切地说,只是显示一个示例):
(S\n (NP\n (DT a)\n (NN restaurant)) (VP\n (VBZ has) (NP\n (JJ modern) (JJ wooden) (NNS tables) (CC and) (NNS chairs)))) 在这种情况下,所有的句子都被正确地处理了,我可以训练模型,而不需要区分最初的标号向量和解析的向量的长度,因为现在有Spacy的句子被分割成几个部分,不再被分成几个部分。
我希望这能帮助使用相同版本的工具的人。
诚挚的问候。
发布于 2021-08-23 08:52:24
我不会在您的阶段使用定制标记器,并且肯定不会分割空格,请使用spacy常规标记器:
from spacy.tokenizer import Tokenizer
self.nlp = spacy.load("en")
self.nlp.tokenizer=Tokenizer(self.nlp.vocab) 如果您想看到令牌:
def _TokoniezData(self,sentence):
self.doc = self.nlp(sentence)
self._tokonized=[]
for token in self.doc:
self._tokonized.append((token.text ,token.lemma_, token.pos_, token.tag_, token.dep_,
token.shape_, token.is_alpha, token.is_stop,token.head,token.left_edge,token.right_edge,token.ent_type_))发布于 2021-08-23 10:50:26
我对你想做的事情很困惑,但我的理解是:
您的问题是,benepar可靠地返回一句话,但spaCy不返回,这会导致Tensorflow的维度问题。
如果上面有任何错误,请纠正我。
假设这是正确的,则令牌程序与您的问题无关。它决定了字符串是如何分裂成单词的,而不是句子是如何定义的。(拥有不同数量的令牌也可能导致维度问题,但听起来这并不是您的问题。)
如果您只想要一个来自spaCy的文本标记列表,您可以这样做:
tokens = list(nlp(text))就这样。如果您已经知道每个输入应该是一个句子,则不需要使用句子迭代器。
我还注意到,您链接到的指令来自于旧版本的docs,并不真正适用于最新版本的benepar。使用最新版本和当前的自述,我能够编写下面的示例代码,将输入的文本分割成一个句子,没有问题。(我确实收到了火炬发出的警告,但这似乎是内部的一些事情。)
import benepar, spacy
nlp = spacy.load('en_core_web_md')
nlp.add_pipe("benepar", config={"model": "benepar_en3"})
doc = nlp("a black sheep having just had it s haired shaved off")
for sent in doc.sents:
print(sent)
print(sent._.parse_string)
print("---")https://stackoverflow.com/questions/68889124
复制相似问题