我有一组独特的 ngram(称为 ngramlist 的列表)和 ngram 标记化文本(称为 ngrams 的列表)。我想构造一个新向量 freqlist,其中 freqlist 的每个元素都是 ngrams 的分数,等于 ngramlist 的该元素。我编写了以下代码,它给出了正确的输出,但我想知道是否有办法优化它:
freqlist = [
sum(int(ngram == ngram_condidate)
for ngram_condidate in ngrams) / len(ngrams)
for ngram in ngramlist
]
我想 nltk 或其他地方有一个函数可以更快地执行此操作,但我不确定是哪一个。
谢谢!
编辑:就其值(value)而言,ngram 被生成为 nltk.util.ngrams 的连接输出。 ngramlist
只是一个由所有找到的 ngram 组成的列表。
编辑2:
这是用于测试 freqlist 行的可重现代码(其余代码并不是我真正关心的)
from nltk.util import ngrams
import wikipedia
import nltk
import pandas as pd
articles = ['New York City','Moscow','Beijing']
tokenizer = nltk.tokenize.TreebankWordTokenizer()
data={'article':[],'treebank_tokenizer':[]}
for article in articles:
data['article' ].append(wikipedia.page(article).content)
data['treebank_tokenizer'].append(tokenizer.tokenize(data['article'][-1]))
df=pd.DataFrame(data)
df['ngrams-3']=df['treebank_tokenizer'].map(
lambda x: [' '.join(t) for t in ngrams(x,3)])
ngramlist = list(set([trigram for sublist in df['ngrams-3'].tolist() for trigram in sublist]))
df['freqlist']=df['ngrams-3'].map(lambda ngrams_: [sum(int(ngram==ngram_condidate) for ngram_condidate in ngrams_)/len(ngrams_) for ngram in ngramlist])
最佳答案
您可以通过预先计算一些数量并使用 Counter
来对此进行一些优化。 。如果 ngramlist
中的大多数元素都存在,这将特别有用。包含在ngrams
中.
freqlist = [
sum(int(ngram == ngram_candidate)
for ngram_candidate in ngrams) / len(ngrams)
for ngram in ngramlist
]
您当然不需要迭代 ngrams
每次您检查 ngram
。一过ngrams
将使这个算法 O(n)
而不是 O(n<sup>2</sup>)
你现在拥有的一个。请记住,较短的代码不一定是更好或更高效的代码:
from collections import Counter
...
counter = Counter(ngrams)
size = len(ngrams)
freqlist = [counter.get(ngram, 0) / size for ngram in ngramlist]
要正确使用此函数,您必须编写 def
函数而不是 lambda
:
def count_ngrams(ngrams):
counter = Counter(ngrams)
size = len(ngrams)
freqlist = [counter.get(ngram, 0) / size for ngram in ngramlist]
return freqlist
df['freqlist'] = df['ngrams-3'].map(count_ngrams)
关于string - 标记化文本中 ngram(字符串)的频率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49620764/