使用 'word groups' 创建字典

Create a dictionary with 'word groups'

我想对职位描述做一些文本分析,打算使用 nltk。我可以建立一个字典并删除停用词,这是我想要的一部分。然而,除了单个单词及其频率之外,我还想保持有意义 'word groups' 并计算它们。

例如,在包含 'machine learning' 的职位描述中,我不想单独考虑 'machine' 和 'learning',但如果它经常一起出现,请在我的字典中保留该词组。最有效的方法是什么? (我想我不需要超越包含 2 或单词的单词组)。并且:我应该在什么时候删除停用词?

这是一个例子:

    text = 'As a Data Scientist, you will focus on machine 
            learning and Natural Language Processing'

我想要的字典是:

     dict = ['data scientist', 'machine learning', 'natural language processing', 
             'data', 'scientist', 'focus', 'machine', 'learning', 'natural' 
             'language', 'processing']

听起来你想要做的是使用 nltk 中的 collocations

将您的多词表达式标记为元组,然后将它们放在一个集合中以便于查找。最简单的方法是使用 nltk.ngrams,它允许您直接遍历文本中的 ngram。由于您的示例数据包含三元组,因此此处搜索 n 最多 3.

raw_keywords = [ 'data scientist', 'machine learning', 'natural language processing', 
         'data', 'scientist', 'focus', 'machine', 'learning', 'natural' 
         'language', 'processing']
keywords = set(tuple(term.split()) for term in raw_keywords)

tokens = nltk.word_tokenize(text.lower())
# Scan text once for each ngram size. 
for n in 1, 2, 3:
    for ngram in nltk.ngrams(tokens, n):
        if ngram in keywords:
            print(ngram)

如果您有大量文本,您可以通过仅迭代最大 ngram(使用选项 pad_right=True 以避免丢失较小的 ngram 大小)来检查您是否会获得加速。两种方式的查找次数相同,所以我怀疑它会产生很大的不同,除了返回结果的顺序。

for ngram in nltk.ngrams(tokens, n, pad_right=True):
    for k in range(n):
        if ngram[:k+1] in keywords:
            print(ngram[:k+1])

至于删除停用词:如果删除它们,您将在之前有 none 的地方生成 ngram,例如,"sewing machine and learning center" 将在删除停用词后匹配 "machine learning"。您必须决定这是否是您想要的。如果是我,我会在关键字扫描之前删除标点符号,但保留停用词。

谢谢@Batman,我用 collocations 玩了一下,结果只需要几行代码。 (显然 'meaningful text' 应该要长得多才能找到实际的搭配)

meaningful_text = 'As a Data Scientist, you will focus on machine 
            learning and Natural Language Processing'

from nltk.collocations import *

bigram_measures = nltk.collocations.BigramAssocMeasures()
finder = BigramCollocationFinder.from_words(word_tokenize(meaningful_text))
scored = finder.score_ngrams(bigram_measures.raw_freq)
sorted(scored, key=lambda s: s[1], reverse=True)