Spacy中是否有二元组或三元组功能?

16
下面的代码将句子分解为单独的标记,输出如下:
 "cloud"  "computing"  "is" "benefiting"  " major"  "manufacturing"  "companies"


import en_core_web_sm
nlp = en_core_web_sm.load()

doc = nlp("Cloud computing is benefiting major manufacturing companies")
for token in doc:
    print(token.text)

我理想中的要求是将'cloud computing'作为一个单词一起阅读。

基本上我正在寻找一个双字组合。Spacy是否有任何功能允许Bi gram或Tri grams?


@chirag。我看过那个解决方案。我想你是指这个。https://dev59.com/TFkS5IYBdhLWcg3w-KpF?rq=1。但那只是一个小技巧,它没有从根本上解决问题。更不用说在名词块方法中需要写入许多额外的代码行了。 - venkatttaknev
4个回答

15

Spacy允许检测名词短语。因此,要将您的名词短语解析为单个实体,请执行以下操作:

  1. 检测名词短语https://spacy.io/usage/linguistic-features#noun-chunks

  2. 合并名词短语

  3. 再次进行依赖分析,现在它会将“cloud computing”解析为单个实体。

>>> import spacy
>>> nlp = spacy.load('en')
>>> doc = nlp("Cloud computing is benefiting major manufacturing companies")
>>> list(doc.noun_chunks)
[Cloud computing, major manufacturing companies]
>>> for noun_phrase in list(doc.noun_chunks):
...     noun_phrase.merge(noun_phrase.root.tag_, noun_phrase.root.lemma_, noun_phrase.root.ent_type_)
... 
Cloud computing
major manufacturing companies
>>> [(token.text,token.pos_) for token in doc]
[('Cloud computing', 'NOUN'), ('is', 'VERB'), ('benefiting', 'VERB'), ('major manufacturing companies', 'NOUN')]

4
谢谢您的回答,但是您提供的解决方案只是一种“变通”的方法,而不是通用解决方案。以这个文本为例 doc = nlp("Big data cloud computing cyber security machine learning")。它不是一个连贯的句子,而是词语的集合。在这种情况下,我得到的不是云计算,而是['Big data cloud', 'cyber security machine learning'] - venkatttaknev
1
因为这就是它的工作方式,它是在训练具有良好语法结构的连贯句子上进行的。你要寻找的是像命名实体识别(NER)这样的特定功能,你需要针对你的用例训练你的模型。 - DhruvPathak
更新2022,现在应该使用以下代码: nlp.add_pipe("merge_noun_chunks") - Yost777

13
如果您拥有一个带有空格的 doc,您可以将其传递给 textacy:
ngrams = list(textacy.extract.basics.ngrams(doc, 2, min_freq=2))

1
我如何对文件列表执行此操作?只需将其附加到ngrams列表中即可吗? - Adit Sanghvi
@AditSanghvi 使用extend或列表推导式。 - Suzana
链接已经失效。在这里找到Github和有用的链接。 - bendl
1
@bendl 我更新了链接和模块名称。 - Suzana

5
警告:这里只是对Zuzana正确回答的扩展。
我的声望不允许我评论,因此我只是为了回答Adit Sanghvi上面的问题而作出这个答案:“当你有一个文件列表时,你该如何处理?”
1.首先需要创建一个包含文档文本的列表。 2.然后将文本列表连接成一个文档。 3.现在使用spacy解析器将文本文档转换为Spacy文档。 4.使用Zuzana的答案创建bigram。
以下是示例代码:
第一步
doc1 = ['all what i want is that you give me back my code because i worked a lot on it. Just give me back my code']
doc2 = ['how are you? i am just showing you an example of how to make bigrams on spacy. We love bigrams on spacy']
doc3 = ['i love to repeat phrases to make bigrams because i love  make bigrams']
listOfDocuments = [doc1,doc2,doc3]
textList = [''.join(textList) for text in listOfDocuments for textList in text]
print(textList)

这将打印以下文本:

['我只希望你把代码还给我,因为我花了很多时间在上面。请还给我我的代码', '你好吗?我只是向你展示了如何在spacy上制作bigram的示例。我们喜欢在spacy上制作bigram', '我喜欢重复短语以制作bigram,因为我喜欢制作bigram']

然后进行第二步和第三步:

doc = ' '.join(textList)
spacy_doc = parser(doc)
print(spacy_doc)

并将打印出以下内容:

我想要的只是你把我的代码还给我,因为我在上面花费了很多时间。只要把我的代码还给我,你好吗?我只是向你展示如何在spacy上制作二元组的例子。我们喜欢在spacy上制作二元组,我喜欢重复短语来制作二元组,因为我喜欢制作二元组。

最后步骤4(Zuzana的答案)

ngrams = list(textacy.extract.ngrams(spacy_doc, 2, min_freq=2))
print(ngrams)

将打印此内容:

[制作双字母词,制作双字母词,制作双字母词]


1
我有一个类似的问题(bigrams,trigrams,如您所说的“云计算”)。我制作了一个简单的n-gram列表,word_3gram,word_2grams等,以gram为基本单位(cloud_computing)。
假设我有句子“我喜欢云计算,因为它很便宜”。句子_2gram是:“I_like”,“like_cloud”,“cloud_computing”,“computing_because”...与您的bigram列表进行比较,只有“cloud_computing”被认为是有效的bigram;句子中的所有其他bigram都是人工的。要恢复所有其他单词,只需取其他单词的第一部分。
"I_like".split("_")[0] -> I; 
"like_cloud".split("_")[0] -> like
"cloud_computing" -> in bigram list, keep it. 
  skip next bi-gram "computing_because" ("computing" is already used)
"because_it's".split("_")[0]" -> "because" etc.

为了捕获句子中的最后一个单词("cheap"),我添加了标记"EOL"。我用Python实现,速度还可以(3分钟内处理了500k个单词),我的电脑是i5处理器,8G内存。无论如何,你只需要做一次就行了。我认为这比官方(spacy-style)块处理方法更直观。它也适用于非spacy框架。
在正式的标记化/词形还原之前,我这样做是因为你可能会得到"cloud compute"作为可能的二元组。但我不确定这是否是最好/正确的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接