当前位置: 首页 > 面试题库 >

NLTK-双曲的计数频率

岳曦
2023-03-14
问题内容

这是Python和NLTK新手问题。

我想查找双峰发生的频率,这些双峰发生在一起的次数超过10次,并且具有最高的PMI。

为此,我正在使用此代码

def get_list_phrases(text):

    tweet_phrases = []

    for tweet in text:
        tweet_words = tweet.split()
        tweet_phrases.extend(tweet_words)


    bigram_measures = nltk.collocations.BigramAssocMeasures()
    finder = BigramCollocationFinder.from_words(tweet_phrases,window_size = 13)
    finder.apply_freq_filter(10)
    finder.nbest(bigram_measures.pmi,20)

    for k,v in finder.ngram_fd.items():
      print(k,v)

但是,这并不会将结果限制在前20位。我看到的结果的频率小于10。我是Python世界中的新手。

有人可以指出如何修改它以仅获得前20名。

谢谢


问题答案:

问题在于您尝试使用的方式apply_freq_filter。我们正在讨论单词搭配。如您所知,单词搭配是关于单词之间的依赖关系。在BigramCollocationFinder从一个类继承类的命名AbstractCollocationFinder和功能apply_freq_filter属于这一类。apply_freq_filter不应完全删除某些单词搭配,但如果某些其他功能尝试访问列表,则提供过滤后的搭配列表。

现在为什么呢?想象一下,如果过滤并置只是简单地删除它们,那么就有很多概率测度,例如似然比或PMI本身(用于计算一个词相对于语料库中其他词的概率),在从随机位置删除多个词后它们将无法正常运行在给定的语料库中。通过从给定单词列表中删除一些搭配,将禁用许多潜在的功能和计算。而且,在删除之前计算所有这些度量将带来巨大的计算开销,而用户可能根本不需要。

现在,问题是如何正确使用apply_freq_filter function?有几种方法。在下文中,我将展示问题及其解决方案。

让我们定义一个示例语料库,并将其拆分为类似于您所做的单词的列表:

tweet_phrases = "I love iphone . I am so in love with iphone . iphone is great . samsung is great . iphone sucks. I really really love iphone cases. samsung can never beat iphone . samsung is better than apple"
from nltk.collocations import *
import nltk

为了进行实验,我将窗口大小设置为3:

finder = BigramCollocationFinder.from_words(tweet_phrases.split(), window_size = 3)
finder1 = BigramCollocationFinder.from_words(tweet_phrases.split(), window_size = 3)

请注意,为了进行比较,我仅在finder1以下位置使用过滤器:

finder1.apply_freq_filter(2)
bigram_measures = nltk.collocations.BigramAssocMeasures()

现在,如果我写:

for k,v in finder.ngram_fd.items():
  print(k,v)

输出为:

(('.', 'is'), 3)
(('iphone', '.'), 3)
(('love', 'iphone'), 3)
(('.', 'iphone'), 2)
(('.', 'samsung'), 2)
(('great', '.'), 2)
(('iphone', 'I'), 2)
(('iphone', 'samsung'), 2)
(('is', '.'), 2)
(('is', 'great'), 2)
(('samsung', 'is'), 2)
(('.', 'I'), 1)
(('.', 'am'), 1)
(('.', 'sucks.'), 1)
(('I', 'am'), 1)
(('I', 'iphone'), 1)
(('I', 'love'), 1)
(('I', 'really'), 1)
(('I', 'so'), 1)
(('am', 'in'), 1)
(('am', 'so'), 1)
(('beat', '.'), 1)
(('beat', 'iphone'), 1)
(('better', 'apple'), 1)
(('better', 'than'), 1)
(('can', 'beat'), 1)
(('can', 'never'), 1)
(('cases.', 'can'), 1)
(('cases.', 'samsung'), 1)
(('great', 'iphone'), 1)
(('great', 'samsung'), 1)
(('in', 'love'), 1)
(('in', 'with'), 1)
(('iphone', 'cases.'), 1)
(('iphone', 'great'), 1)
(('iphone', 'is'), 1)
(('iphone', 'sucks.'), 1)
(('is', 'better'), 1)
(('is', 'than'), 1)
(('love', '.'), 1)
(('love', 'cases.'), 1)
(('love', 'with'), 1)
(('never', 'beat'), 1)
(('never', 'iphone'), 1)
(('really', 'iphone'), 1)
(('really', 'love'), 1)
(('samsung', 'better'), 1)
(('samsung', 'can'), 1)
(('samsung', 'great'), 1)
(('samsung', 'never'), 1)
(('so', 'in'), 1)
(('so', 'love'), 1)
(('sucks.', 'I'), 1)
(('sucks.', 'really'), 1)
(('than', 'apple'), 1)
(('with', '.'), 1)
(('with', 'iphone'), 1)

如果为编写相同的结果,我将获得相同的结果finder1。因此,乍一看,过滤器不起作用。但是,看看它是如何工作的:诀窍是使用score_ngrams

如果我score_ngrams在上使用finder,它将是:

finder.score_ngrams (bigram_measures.pmi)

输出为:

[(('am', 'in'), 5.285402218862249), (('am', 'so'), 5.285402218862249), (('better', 'apple'), 5.285402218862249), (('better', 'than'), 5.285402218862249), (('can', 'beat'), 5.285402218862249), (('can', 'never'), 5.285402218862249), (('cases.', 'can'), 5.285402218862249), (('in', 'with'), 5.285402218862249), (('never', 'beat'), 5.285402218862249), (('so', 'in'), 5.285402218862249), (('than', 'apple'), 5.285402218862249), (('sucks.', 'really'), 4.285402218862249), (('is', 'great'), 3.7004397181410926), (('I', 'am'), 3.7004397181410926), (('I', 'so'), 3.7004397181410926), (('cases.', 'samsung'), 3.7004397181410926), (('in', 'love'), 3.7004397181410926), (('is', 'better'), 3.7004397181410926), (('is', 'than'), 3.7004397181410926), (('love', 'cases.'), 3.7004397181410926), (('love', 'with'), 3.7004397181410926), (('samsung', 'better'), 3.7004397181410926), (('samsung', 'can'), 3.7004397181410926), (('samsung', 'never'), 3.7004397181410926), (('so', 'love'), 3.7004397181410926), (('sucks.', 'I'), 3.7004397181410926), (('samsung', 'is'), 3.115477217419936), (('.', 'am'), 2.9634741239748865), (('.', 'sucks.'), 2.9634741239748865), (('beat', '.'), 2.9634741239748865), (('with', '.'), 2.9634741239748865), (('.', 'is'), 2.963474123974886), (('great', '.'), 2.963474123974886), (('love', 'iphone'), 2.7004397181410926), (('I', 'really'), 2.7004397181410926), (('beat', 'iphone'), 2.7004397181410926), (('great', 'samsung'), 2.7004397181410926), (('iphone', 'cases.'), 2.7004397181410926), (('iphone', 'sucks.'), 2.7004397181410926), (('never', 'iphone'), 2.7004397181410926), (('really', 'love'), 2.7004397181410926), (('samsung', 'great'), 2.7004397181410926), (('with', 'iphone'), 2.7004397181410926), (('.', 'samsung'), 2.37851162325373), (('is', '.'), 2.37851162325373), (('iphone', 'I'), 2.1154772174199366), (('iphone', 'samsung'), 2.1154772174199366), (('I', 'love'), 2.115477217419936), (('iphone', '.'), 1.963474123974886), (('great', 'iphone'), 1.7004397181410922), (('iphone', 'great'), 1.7004397181410922), (('really', 'iphone'), 1.7004397181410922), (('.', 'iphone'), 1.37851162325373), (('.', 'I'), 1.37851162325373), (('love', '.'), 1.37851162325373), (('I', 'iphone'), 1.1154772174199366), (('iphone', 'is'), 1.1154772174199366)]

现在注意当我计算finder1被过滤为2的频率的相同内容时会发生什么:

finder1.score_ngrams(bigram_measures.pmi)

和输出:

[(('is', 'great'), 3.7004397181410926), (('samsung', 'is'), 3.115477217419936), (('.', 'is'), 2.963474123974886), (('great', '.'), 2.963474123974886), (('love', 'iphone'), 2.7004397181410926), (('.', 'samsung'), 2.37851162325373), (('is', '.'), 2.37851162325373), (('iphone', 'I'), 2.1154772174199366), (('iphone', 'samsung'), 2.1154772174199366), (('iphone', '.'), 1.963474123974886), (('.', 'iphone'), 1.37851162325373)]

请注意,此列表中不存在所有频率小于2的搭配。而这正是您要寻找的结果。因此过滤器已经起作用。此外,文档还提供了有关此问题的最小提示。

我希望这能回答您的问题。否则,请告诉我。

免责声明:如果您主要处理推文,则窗口大小为13太大。如果您注意到,在我的示例语料库中,我的示例推文的大小太小,以至于将窗口大小设置为13可能会导致发现无关紧要的搭配。



 类似资料:
  • 问题内容: 我有以下代码。我知道我可以使用函数过滤掉少于频率计数的搭配。但是,在决定设置过滤频率之前,我不知道如何获取文档中所有n- gram元组(在我的情况下为bi-gram)的频率。如您所见,我正在使用nltk搭配类。 问题答案: 该功能有效

  • NLTK书中有几个单词计数的例子,但实际上它们不是单词计数,而是标记计数。例如,第1章“计算词汇”中说,下面给出了一个单词计数: 然而,它没有-它给出了一个单词和标点符号计数。你怎样才能得到一个真正的字数(忽略标点符号)? 同样,如何获得一个单词中的平均字符数?显而易见的答案是: 但是,这将关闭,因为: len(文本的字符串)是一个字符计数,包括空格 我是不是遗漏了什么?这一定是一个非常常见的NL

  • 我想计算文本语料库中单词的词频。我一直在使用NLTK的word_tokenize,后跟概率。FreqDist一段时间来完成这项工作。单词_tokenize返回一个列表,该列表由FreqDist转换为频率分布。然而,我最近在collections(collections.Counter)中遇到了计数器函数,它似乎在做完全相同的事情。FreqDist和Counter都有一个最常用(n)函数,返回n个最

  • 问题内容: 假设我有一个单词列表,并且我想查找每个单词出现在该列表中的次数。 一个明显的方法是: 但是我发现这段代码不是很好,因为该程序在单词列表中运行两次,一次构建集合,第二次计算出现次数。 当然,我可以编写一个函数来遍历列表并进行计数,但是那不是Pythonic。那么,有没有更有效和Pythonic的方法呢? 问题答案: 在类中模块是专为解决这类问题的目的:

  • 问题内容: 我有一张表,上面有像 我想做一张像这样的桌子 等等。 问题答案: WITH basedata(id,keywords) AS ( SELECT 1,’cat, dog, man, mouse’ union all SELECT 2 ,’man, pen, pencil, eraser’ union all SELECT 3,’dog, man, friends’ union all S

  • 问题内容: NLTK书中有几个字数示例,但实际上它们不是字数而是令牌数。例如,第1章“计数词汇”说以下内容给出了单词计数: 但是,事实并非如此-它给出了单词和标点计数。如何获得真实的字数(忽略标点符号)? 同样,如何获得一个单词的平均字符数?显而易见的答案是: 但是,这将因为以下原因而关闭: len(string_of_text)是一个字符数,包括空格 len(text)是令牌计数,不包括空格,但