Почему расчет TF-IDF занимает так много времени? - PullRequest
0 голосов
/ 12 июня 2018

Я использую код 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 нечетных текстовых файлов, которые были значительно короче (например, 2-3 абзаца в среднем), и там он мог мгновенно показывать результаты TF-IDF.Что не так с 3 документами по 270 страниц каждый?

Ответы [ 2 ]

0 голосов
/ 13 июня 2018

Как уже упоминалось в другом ответе, вы слишком много звоните 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) каждый раз.

0 голосов
/ 12 июня 2018

Некоторые вещи появляются из беглого взгляда: 1) Не видя, как реализован метод tb, кажется, однако, что вы вызываете tb(blob) для каждого слова.Возможно, создание объекта из того, что tb(blob) возвращает один раз для каждого слова, ускорит процесс.2) nltk имеет собственную реализацию tfidf, которая была бы намного более оптимизированной и которая могла бы ускорить процесс.3) Вы могли бы сделать свою реализацию, но с numpy вместо vanilla python, который определенно ускорит процесс. Но даже с этим, было бы лучше зашифровать результаты и использовать их вместо вызова, возможно, тяжелой функции несколько раз.

...