NLTK—双随机数的计数频率

2024-06-01 09:27:11 发布

您现在位置:Python中文网/ 问答频道 /正文

这是一个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名。

谢谢你


Tags: 代码textinforfindertweet频率words
3条回答

有关NLTKcollocation函数以及https://en.wikipedia.org/wiki/Pointwise_mutual_information中数学的更多用法,请阅读http://nltk.googlecode.com/svn/trunk/doc/howto/collocations.html上的教程。希望下面的脚本可以帮助您,因为您的代码问题没有指定输入内容。

# This is just a fancy way to create document. 
# I assume you have your texts in a continuous string format
# where each sentence ends with a fullstop.
>>> from itertools import chain
>>> docs = ["this is a sentence", "this is a foo bar", "you are a foo bar", "yes , i am"]
>>> texts = list(chain(*[(j+" .").split() for j in [i for i in docs]]))

# This is the NLTK part
>>> from nltk.collocations import BigramAssocMeasures, BigramCollocationFinder>>> bigram_measures= BigramAssocMeasures()
>>> finder  BigramCollocationFinder.from_words(texts)
# This gets the top 20 bigrams according to PMI
>>> finder.nbest(bigram_measures.pmi,20)
[(',', 'i'), ('i', 'am'), ('yes', ','), ('you', 'are'), ('foo', 'bar'), ('this', 'is'), ('a', 'foo'), ('is', 'a'), ('a', 'sentence'), ('are', 'a'), ('bar', '.'), ('.', 'yes'), ('.', 'you'), ('am', '.'), ('sentence', '.'), ('.', 'this')]

PMI通过计算log ( p(x|y) / p(x) )来度量两个单词之间的关联,因此它不仅仅是关于一个单词出现的频率或一组单词同时出现的频率。要实现高PMI,您需要同时满足以下两个条件:

  1. 高p(x | y)
  2. 低p(x)

以下是一些极端PMI的例子。

假设你的语料库中有100个单词,如果频率是某个单词的X为1,并且只与另一个单词一起出现Y一次,那么:

p(x|y) = 1
p(x) = 1/100
PMI = log(1 / 1/100) = log 0.01 = -2

假设你在语料库中有100个单词,如果某个单词的频率是90,但它从不与另一个单词一起出现Y,那么PMI是

p(x|y) = 0
p(x) = 90/100
PMI = log(0 / 90/100) = log 0 = -infinity

因此,从这个意义上说,第一种情况比第二种情况的PMI介于X,Y之间,尽管第二个词的频率非常高。

问题在于您试图使用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

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

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的搭配在这个列表中都不存在;这正是您要寻找的结果。所以过滤器起作用了。此外,文档对这个问题给出了一个最小的提示。

我希望这已经回答了你的问题。否则,请告诉我。

免责声明:如果你主要处理的是tweets,那么13的窗口太大了。如果你注意到,在我的样本语料库中,我的样本tweets的大小太小,应用13的窗口大小可能会导致找到不相关的搭配。

有关NLTKcollocation函数以及https://en.wikipedia.org/wiki/Pointwise_mutual_information中数学的更多用法,请阅读http://nltk.googlecode.com/svn/trunk/doc/howto/collocations.html中的教程。希望下面的脚本可以帮助您,因为您的代码问题没有指定输入内容。

# This is just a fancy way to create document. 
# I assume you have your texts in a continuous string format
# where each sentence ends with a fullstop.
>>> from itertools import chain
>>> docs = ["this is a sentence", "this is a foo bar", "you are a foo bar", "yes , i am"]
>>> texts = list(chain(*[(j+" .").split() for j in [i for i in docs]]))

# This is the NLTK part
>>> from nltk.collocations import BigramAssocMeasures, BigramCollocationFinder>>> bigram_measures= BigramAssocMeasures()
>>> finder  BigramCollocationFinder.from_words(texts)
# This gets the top 20 bigrams according to PMI
>>> finder.nbest(bigram_measures.pmi,20)
[(',', 'i'), ('i', 'am'), ('yes', ','), ('you', 'are'), ('foo', 'bar'), ('this', 'is'), ('a', 'foo'), ('is', 'a'), ('a', 'sentence'), ('are', 'a'), ('bar', '.'), ('.', 'yes'), ('.', 'you'), ('am', '.'), ('sentence', '.'), ('.', 'this')]

PMI通过计算log ( p(x|y) / p(x) )来度量两个单词之间的关联,因此它不仅仅是关于一个单词出现的频率或一组单词同时出现的频率。要实现高PMI,您需要同时满足以下两个条件:

  1. 高p(x | y)
  2. 低p(x)

以下是一些极端PMI的例子。

假设你的语料库中有100个单词,如果频率是某个单词的X为1,并且只与另一个单词一起出现Y一次,那么:

p(x|y) = 1
p(x) = 1/100
PMI = log(1 / 1/100) = log 0.01 = -2

假设你的语料库中有100个单词,如果某个单词的频率是90,但它从不与另一个单词一起出现Y,那么PMI是

p(x|y) = 0
p(x) = 90/100
PMI = log(0 / 90/100) = log 0 = -infinity

因此,从这个意义上说,第一种情况比第二种情况的PMI介于X,Y之间,尽管第二个词的频率非常高。

相关问题 更多 >