【问题标题】:Compute nGrams across a list of lists of sentences using nltk使用 nltk 跨句子列表计算 nGram
【发布时间】:2017-05-13 04:57:15
【问题描述】:

我有一个列表列表,其中每个内部列表都是一个被标记为单词的句子:

sentences = [['farmer', 'plants', 'grain'], 
             ['fisher', 'catches', tuna'], 
             ['police', 'officer', 'fights', 'crime']]

目前我正在尝试像这样计算 nGram:

numSentences = len(sentences)
nGrams = []
for i in range(0, numSentences):
       nGrams.append(list(ngrams(sentences, 2)))

这会导致找到整个列表的二元组,而不是每个内部列表的单个单词(并且它会重复句子的数量,这在某种程度上是可预测的):

[[(['farmer', 'plants', 'grain'], ['fisher', 'catches', tuna']),
  (['fisher', 'catches', tuna'], ['police', 'officer', 'fights', 'crime'])], 
[(['farmer', 'plants', 'grain'], ['fisher', 'catches', tuna']), 
 (['fisher', 'catches', tuna'], ['police', 'officer', 'fights', 'crime'])], 
[(['farmer', 'plants', 'grain'], ['fisher', 'catches', tuna']), 
 (['fisher', 'catches', tuna'], ['police', 'officer', 'fights', 'crime'])]]

如何(按单词)计算每个句子的 nGram?换句话说,如何确保 nGram 不跨越多个列表项?这是我想要的输出:

farmer plants
plants grain
fisher catches
catches tuna
police officer
officer fights
fights crime

【问题讨论】:

    标签: python list nltk n-gram


    【解决方案1】:

    取每个句子的ngram,把结果汇总起来。你可能想数一数,而不是把它们放在一个庞大的集合中。以sentences 开头的单词列表:

    counts = collections.Counter()   # or nltk.FreqDist()
    for sent in sentences:
        counts.update(nltk.ngrams(sent, 2))
    

    或者,如果您更喜欢单个字符串而不是元组,则您的键:

    for sent in sentences:
        count.update(" ".join(n) for n in nltk.ngrams(sent, 2))
    

    这就是它的全部内容。然后你可以看到最常见的等等。

    print(counts.most_common(10))
    

    附言。如果你真的想堆积二元组,你会这样做。 (您的代码形成句子而不是单词的“bigrams”,因为您忽略了写sentences[i]。)但是跳过这一步,直接计算它们。

    all_ngrams = []
    for sent in sentences:
        all_ngrams.extend(nltk.ngrams(sent, 2))
    

    【讨论】:

      【解决方案2】:

      您也可以考虑使用 scikit-learn 的 CountVectorizer 作为替代方案。

      from sklearn.feature_extraction.text import CountVectorizer
      
      sents = list(map(lambda x: ' '.join(x), sentences)) # input is a list of sentences so I map join first
      count_vect = CountVectorizer(ngram_range=(2,2)) # bigram
      count_vect.fit(sents)
      count_vect.vocabulary_
      

      这会给你:

      {'catches tuna': 0,
       'farmer plants': 1,
       'fights crime': 2,
       'fisher catches': 3,
       'officer fights': 4,
       'plants grain': 5,
       'police officer': 6}
      

      【讨论】:

        【解决方案3】:

        使用list comprehensionchain to flatten the list

        >>> from itertools import chain
        >>> from collections import Counter
        >>> from nltk import ngrams
        
        >>> x = [['farmer', 'plants', 'grain'], ['fisher', 'catches', 'tuna'], ['police', 'officer', 'fights', 'crime']]
        
        >>> Counter(chain(*[ngrams(sent,2) for sent in x]))
        Counter({('plants', 'grain'): 1, ('police', 'officer'): 1, ('farmer', 'plants'): 1, ('officer', 'fights'): 1, ('fisher', 'catches'): 1, ('fights', 'crime'): 1, ('catches', 'tuna'): 1})
        
        >>> c = Counter(chain(*[ngrams(sent,2) for sent in x]))
        

        获取keys of the Counter dictionary

        >>> c.keys()
        [('plants', 'grain'), ('police', 'officer'), ('farmer', 'plants'), ('officer', 'fights'), ('fisher', 'catches'), ('fights', 'crime'), ('catches', 'tuna')]
        

        Join strings with spaces

        >>> [' '.join(b) for b in c.keys()]
        ['plants grain', 'police officer', 'farmer plants', 'officer fights', 'fisher catches', 'fights crime', 'catches tuna']
        

        【讨论】:

          猜你喜欢
          • 2015-10-25
          • 2016-10-08
          • 2015-02-14
          • 2023-03-19
          • 1970-01-01
          • 1970-01-01
          • 2013-06-20
          • 2011-07-13
          • 1970-01-01
          相关资源
          最近更新 更多