我认为我的问题部分与spaCy有关,而部分原因与对Python本身内最优雅的工作方式不了解有关。
我正在用python上传一个txt文件,将其标记为句子,然后使用nltk将其标记为单词:
sent_text = nltk.sent_tokenize(text)
tokenized_text = [nltk.word_tokenize(x) for x in sent_text]
这给了我一个列表列表,其中主列表中的每个列表都是一个带标记词的句子。到目前为止一切顺利。
然后我通过SpaCy运行它:
text = nlp(unicode(tokenized_text))
仍然是列表列表,同样,但包含所有SpaCy信息。
这是我遇到的障碍。基本上我想做的是,对于每个句子,仅保留名词,动词和形容词,并且在其中还摆脱了辅助词和连词。我可以通过创建一个新的空列表并仅附加我想要的内容来做到这一点:
sent11 = []
for token in sent1:
if (token.pos_ == 'NOUN' or token.pos_ == 'VERB' or token.pos_ =='ADJ') and (token.dep_ != 'aux') and (token.dep_ != 'conj'):
sent11.append(token)
这对于单个句子来说效果很好,但是我不想对一本书长度的文本中的每个单个句子都这样做。
然后,一旦我有了这些仅包含我想要的片段的新列表(或执行此操作的最佳方法),我想使用SpaCy的“相似性”功能来确定哪个句子在语义上与其他句子最接近,短得多的文本,除了名词,adj,动词等外,我对所有内容都进行了相同的剥离。
在使用以下方法将一个句子与另一个句子进行比较时,它可以正常工作:
sent1.similarity(sent2)
所以我想我的问题是
1)将列表列表变成仅包含我想要的作品的列表列表的最佳方法是什么?
和
2)如何循环浏览这个新的列表列表,并将每个列表与一个单独的句子进行比较,然后返回语义上最相似的句子(使用SpaCy随附的向量)?
答案 0 :(得分:0)
您在这里问了一堆问题,所以我将尝试将其分解。
答案:
通常是的,但是在现代系统上这没什么大不了的。书籍是文本,如果是英语,则可能只是UTF-8字符,否则它们可能是Unicode。一个UTF-8字符是一个字节,甚至一本长书,例如War and Peace都低于3.3 Mb。如果您使用chrome,firefox或IE来查看此页面,则您的计算机有足够的内存来容纳它的几个副本到ram中。
在python中,您无法做到。
您可以使用以下方法进行删除:
l = [1,2,3,4]
del l[-2]
print(l)
[1,2,4]
,但是在后台python会将那个列表的每个元素都复制到一个以上。不建议用于大型列表。取而代之的是使用将自己实现为双链表的dequeue,这会带来一些额外的开销,但可以有效地移除中间的元素。
如果存在内存问题,那么您也可以尽可能使用generators。例如,您可能会更改:
tokenized_text = [nltk.word_tokenize(x) for x in sent_text]
使用
创建一个包含整本书标记的列表tokenized_text = (nltk.word_tokenize(x) for x in sent_text)
创建一个生成器,该生成器生成整本书的标记。生成器几乎没有内存开销,而是在运行时计算下一个元素。
从外观上,您可以执行以下操作:
best_match = None
best_similarity_value = 0
for token in parsed_tokenized_text:
similarity = token.similarity(sent2)
if similarity > best_similarity_value:
best_similarity_value = similarity
best_match = token
如果您要检查多个句子(不连续),则可以设置一个遍历这些句子的外部循环:
for sent2 in other_token_list: