【问题标题】:How to replace bigrams in place using NLTK?如何使用 NLTK 替换二元组?
【发布时间】:2017-12-20 13:17:18
【问题描述】:

假设我有一个元组列表,top_n,是文本语料库中最常见的 n 最常见的二元组:

import nltk
from nltk import bigrams
from nltk import FreqDist

bi_grams = bigrams(text) # text is a list of strings (tokens)
fdistBigram = FreqDist(bi_grams)

n = 300
top_n= [list(t) for t in zip(*fdistBigram.most_common(n))][0]; top_n
>>> [('let', 'us'),
    ('us', 'know'),
    ('as', 'possible')
    ....

现在我想替换 top_n 中的二元组词集实例用它们的连接就位。例如,假设我们有一个新变量query,它是一个字符串列表:

query = ['please','let','us','know','as','soon','as','possible']

会变成

['please','letus', 'usknow', 'as', 'soon', 'aspossible']

在所需的操作之后。更明确地说,我想搜索 query 的每个元素并检查第 i 个和第 (i+1) 个元素是否在 top_n 中;如果是,则将 query[i]query[i+1] 替换为单个连接的二元组,即 (query[i], query[i+1]) -> query[i] + query[i+1]

有没有办法使用 NLTK 来做到这一点,或者如果需要循环遍历 query 中的每个单词,最好的方法是什么?

【问题讨论】:

  • 我感觉你的输入有误,查询不是二元组列表。
  • 如果没有,[token_1+token_2 for token_1, token_2 in zip(query[:-1], [""]+query[2:])]
  • 不用等待,您的输出包括除第一个单词之外的其他单个单词。你到底想要什么,那不是串联的二元组列表:
  • 为什么 8 个单词的查询返回一个只有 6 个单词的列表...?你是什​​么意思?你的标题似乎有点误导。

标签: python nltk n-gram


【解决方案1】:

鉴于您的代码和查询,如果单词在 top_n 中,它们将被它们的二元组贪婪地替换,这将起到作用:

lookup = set(top_n)  # {('let', 'us'), ('as', 'soon')}
query = ['please', 'let', 'us', 'know', 'as', 'soon', 'as', 'possible']
answer = []
q_iter = iter(range(len(query)))
for idx in q_iter:
    answer.append(query[idx])
    if idx < (len(query) - 1) and (query[idx], query[idx+1]) in lookup:
        answer[-1] += query[idx+1]
        next(q_iter)
        # if you don't want to skip over consumed 
        # second bi-gram elements and keep 
        # len(query) == len(answer), don't advance 
        # the iterator here, which also means you
        # don't have to create the iterator in outer scope

print(answer)

结果(例如):

>> ['please', 'letus', 'know', 'assoon', 'as', 'possible']

【讨论】:

  • 我很欣赏这个答案,但问题是你在替换query 中的单词时没有使用变量top_n。我想搜索变量query 的每个元素并检查第 i 个和第 (i+1) 个元素是否在 top_n 中;如果是,则将query[i]query[i+1] 替换为单个连接的二元组,即(query[i], query[i+1]) -&gt; query[i] + query[i+1]。让我编辑我的问题,使其更明确。
  • 好吧,我想我现在明白了你的问题,并会重新表述我的答案。但是,天哪,破译那是一项艰苦的工作。
  • 好吧,我刚刚注意到我还是错了。如果 top_n 列表中有三个相关的词会怎样?
  • 如果在 top_n 中出现 3 个或更多连续单词,我想要这个结果:query=['as','possible','as','possible'] -&gt; ['aspossible','aspossible'],如果这有意义的话。
  • 调试一部手机很难,但现在应该可以了。 q_iter 确实不是一个合适的迭代器,它需要在实例化时转换为一个。 IndexError 需要通过跳过双语法检查的最后一个条目来避免。
【解决方案2】:

另一种答案:

from gensim.models.phrases import Phraser
from gensim.models import Phrases
phrases = Phrases(text, min_count=1500, threshold=0.01)
bigram = Phraser(phrases)
bigram[query]
>>> ['please', 'let_us', 'know', 'as', 'soon', 'as', 'possible']

不完全是问题中所需的输出,但它可以作为替代方案。输入 min_countthreshold 将强烈影响输出。感谢this question here

【讨论】:

    猜你喜欢
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 2023-03-09
    • 2017-01-07
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多