为什么TF-IDF计算需要这么多时间?



我在文档语料库中使用了TF-IDF代码,该文档是3个PDF文档,每个文档长约270页。

# Calculating the Term Frequency, Inverse Document Frequency score
import os
import math
from textblob import TextBlob as tb
def tf(word, blob):
return tb(blob).words.count(word) / len(tb(blob).words)
def n_containing(word, bloblist):
return sum(1 for blob in bloblist if word in tb(blob).words)
def idf(word, bloblist):
return math.log(len(bloblist) / (1 + n_containing(word, bloblist)))
def tfidf(word, blob, bloblist):
return tf(word, blob) * idf(word, bloblist)


# Stemming the articles
from nltk.stem import PorterStemmer
port = PorterStemmer()
bloblist = []
doclist = [pdf1, pdf2, pdf3]   # Defined earlier, not showing here as it is not relevant to the question
for doc in doclist:
bloblist.append(port.stem(str(doc)))


# TF-IDF calculation on the stemmed articles
for index, blob in enumerate(bloblist):
print("Top words in document {}".format(index + 1))
scores = {word: tfidf(word, blob, bloblist) for word in tb(blob).words}
sorted_words = sorted(scores.items(), key=lambda x: x[1], reverse=True)
i=1
for word, score in sorted_words[:5]:
print("tWord "+str(i)+": {}, TF-IDF: {}".format(word, round(score, 5)))
i+=1

问题是,它只是继续运行,而不显示任何超出Top words in document 1的内容。为什么计算scores需要这么长时间?我已经让它运行了一个小时,代码还没有终止。早些时候,我尝试了 50 多个 txt 文件的代码,这些文件的长度要短得多(例如平均 2-3 个段落(,并且它能够立即显示 TF-IDF 分数。3 个文档,每个 270 页有什么问题?

粗略一瞥就会冒出一些东西, 1(在没有看到方法tb是如何实现的情况下,似乎你正在为每个单词调用tb(blob)。也许用每个单词返回一次tb(blob)的东西制作一个对象会加快速度。 2(nltk有自己的tfidf实现,这将更加优化,并且可以加快速度。 3(你可以做你的实现,但用numpy而不是香草蟒蛇,这肯定会加快速度。但即使这样,缓存结果并使用它们而不是多次调用可能很重的函数也是一个更好的主意。

正如另一个答案提到的,你对tb(blob)的调用太多了;看起来对于一个有 N 个单词的文档,你调用它超过 N^2 次。这总是很慢的。您需要进行如下更改:

for index, blob in enumerate(bloblist):
print("Top words in document {}".format(index + 1))
# XXX use textblob here just once
tblob = tb(blob)
scores = {word: tfidf(word, tblob, bloblist) for word in tblob.words}
sorted_words = sorted(scores.items(), key=lambda x: x[1], reverse=True)
i=1
for word, score in sorted_words[:5]:
print("tWord "+str(i)+": {}, TF-IDF: {}".format(word, round(score, 5)))
i+=1

您还需要更改 tfidf 函数,以便它们使用tblob而不是每次都调用tb(blob)

最新更新