Как получить среднее значение TF-IDF слова в корпусе?

Я пытаюсь получить среднее значение TF-IDF для слова во всем корпусе. Предположим, у нас есть слово «стек», которое встречается в нашем корпусе 4 раза (пара сотен документов). Он имеет эти значения 0.34, 0.45, 0.68, 0.78 в 4 найденных документах. Следовательно, его среднее значение TF-IDF по всему корпусу составляет 0.5625. Как я могу найти это для всех слов в документе?

Я использую реализацию TF-IDF из scikit-learn. Это код, который я использую для получения значений TF-IDF для каждого документа:

for i in docs_test:
    feature_names=cv.get_feature_names()

    doc=docs_test[itr]
    itr += 1
    tf_idf_vector=tfidf_transformer.transform(cv.transform([doc]))

    sorted_items=sort_coo(tf_idf_vector.tocoo())

    #Extracting the top 81 keywords along with their TF-IDF scores
    keywords=extract_topn_from_vector(feature_names,sorted_items,81)

Для каждой итерации выводится словарь из 81 слова и их оценка TF-IDF для этого документа: {'kerry': 0.396, 'paris': 0.278, 'france': 0.252 ......}

Поскольку я выводю только 81 верхнее слово, я знаю, что все слова в этом документе не будут охвачены. Итак, мне нужно среднее значение TF-IDF каждого из 81 верхнего слова в документе (слова будут повторяться).

РЕДАКТИРОВАТЬ: Я попробовал решение @mijjiga. Вот результаты:

{'the': 0.51203095036175, 'to': 0.36268858983957286, 'of': 0.3200193439760937, 'in': 0.256015475180875, 'he': 0.2133462293173958}
{'the': 0.5076730825668095, 'to': 0.3299875036684262, 'in': 0.3299875036684262, 'and': 0.30460384954008574, 'trump': 0.17768557889838335}
{'the': 0.5257856140532874, 'children': 0.292103118918493, 'to': 0.2336824951347944, 'winton': 0.2336824951347944, 'of': 0.2336824951347944}
{'the': 0.6082672845890075, 'to': 0.3146210092701763, 'trump': 0.2936462753188312, 'that': 0.23911196704533397, 'of': 0.21394228630371986}
{'the': 0.6285692218670833, 'to': 0.3610929572427925, 'of': 0.2139810116994326, 'that': 0.20060719846821806, 'iran': 0.18723338523700353}
{'the': 0.5730922466510651, 'clinton': 0.29578954665861423, 'of': 0.24032900666012408, 'in': 0.2218421599939607, 'that': 0.2218421599939607}
{'the': 0.7509270472649924, 'to': 0.34926839407674065, 'trump': 0.17463419703837033, 'of': 0.17463419703837033, 'delegates': 0.1571707773345333}
{'on': 0.4, 'administration': 0.2, 'through': 0.2, 'the': 0.2, 'tax': 0.2}
{'the': 0.5885277950982455, 'in': 0.3184973949943446, 'of': 0.3046496821685035, 'to': 0.29080196934266245, 'women': 0.2769542565168214}

Как мы видим, слово «the» имеет несколько значений. Прошу прощения, если мой вопрос не указывает на это, но мне нужно одно значение для каждого слова. И это значение представляет собой средний балл TF-IDF для этого слова в этом корпусе документов. Любая помощь относительно того, как заставить это работать? Спасибо!

Вот используемый код:

from sklearn.feature_extraction.text import TfidfVectorizer 
import numpy as np
itr = 0
for i in range(1,10):
    docs=docs_test[itr]
    docs=[docs]
    itr+=1
    tfidf_vectorizer=TfidfVectorizer(use_idf=True)
    tfidf_vectorizer_vectors=tfidf_vectorizer.fit_transform(docs)

    tfidf = tfidf_vectorizer_vectors.todense()
    # TFIDF of words not in the doc will be 0, so replace them with nan
    tfidf[tfidf == 0] = np.nan
    # Use nanmean of numpy which will ignore nan while calculating the mean
    means = np.nanmean(tfidf, axis=0)
    # convert it into a dictionary for later lookup
    means = dict(zip(tfidf_vectorizer.get_feature_names(), means.tolist()[0]))

    tfidf = tfidf_vectorizer_vectors.todense()
    # Argsort the full TFIDF dense vector
    ordered = np.argsort(tfidf*-1)
    words = tfidf_vectorizer.get_feature_names()

    top_k = 5
    for i, doc in enumerate(docs):
        result = { }
        # Pick top_k from each argsorted matrix for each doc
        for t in range(top_k):
            # Pick the top k word, find its average tfidf from the
            # precomputed dictionary using nanmean and save it to later use
            result[words[ordered[i,t]]] = means[words[ordered[i,t]]]
        print (result )

person Shawn    schedule 03.09.2019    source источник
comment
Почему docs=docs_test[itr] Не должно быть цикла, docs должен содержать все документы в корпусе. Что-то вроде docs=docs_test   -  person mujjiga    schedule 04.09.2019
comment
Ой! Вот в чем проблема. Спасибо!   -  person Shawn    schedule 04.09.2019


Ответы (1)


Документация встроена

from sklearn.feature_extraction.text import TfidfVectorizer 
import numpy as np

docs=["the house had a tiny little mouse",
      "the cat saw the mouse",
      "the mouse ran away from the house",
      "the cat finally ate the mouse",
      "the end of the mouse story"
     ]

tfidf_vectorizer=TfidfVectorizer(use_idf=True)
tfidf_vectorizer_vectors=tfidf_vectorizer.fit_transform(docs)

tfidf = tfidf_vectorizer_vectors.todense()
# TFIDF of words not in the doc will be 0, so replace them with nan
tfidf[tfidf == 0] = np.nan
# Use nanmean of numpy which will ignore nan while calculating the mean
means = np.nanmean(tfidf, axis=0)
# convert it into a dictionary for later lookup
means = dict(zip(tfidf_vectorizer.get_feature_names(), means.tolist()[0]))

tfidf = tfidf_vectorizer_vectors.todense()
# Argsort the full TFIDF dense vector
ordered = np.argsort(tfidf*-1)
words = tfidf_vectorizer.get_feature_names()

top_k = 5
for i, doc in enumerate(docs):
    result = { }
    # Pick top_k from each argsorted matrix for each doc
    for t in range(top_k):
        # Pick the top k word, find its average tfidf from the
        # precomputed dictionary using nanmean and save it to later use
        result[words[ordered[i,t]]] = means[words[ordered[i,t]]]
    print (result )

Выход

{'had': 0.4935620852501244, 'little': 0.4935620852501244, 'tiny': 0.4935620852501244, 'house': 0.38349121689490395, 'mouse': 0.24353457958557367}
{'saw': 0.5990921556092994, 'the': 0.4400321635416817, 'cat': 0.44898681252620987, 'mouse': 0.24353457958557367, 'ate': 0.5139230069660121}
{'away': 0.4570928721125019, 'from': 0.4570928721125019, 'ran': 0.4570928721125019, 'the': 0.4400321635416817, 'house': 0.38349121689490395}
{'ate': 0.5139230069660121, 'finally': 0.5139230069660121, 'the': 0.4400321635416817, 'cat': 0.44898681252620987, 'mouse': 0.24353457958557367}
{'end': 0.4917531872315962, 'of': 0.4917531872315962, 'story': 0.4917531872315962, 'the': 0.4400321635416817, 'mouse': 0.24353457958557367}

Давайте расшифруем result[words[ordered[i,t]]] = means[words[ordered[i,t]]]

Если размер словаря v, а количество документов n, то

  • ordered - это матрица размера nxv. Значением этой матрицы являются индексы, соответствующие словарю, и эта матрица сортируется на основе оценки TF-IDF для каждого документа.
  • words - это список размером v слов из словаря. Думайте об этом как о преобразователе идентификатора в слово
  • means - это диктант размера v, где каждое значение представляет собой среднее значение TF-IDF слова.
person mujjiga    schedule 03.09.2019
comment
Привет! Я попробовал. Пожалуйста, смотрите редактирование для получения дополнительной информации. Спасибо! - person Shawn; 03.09.2019
comment
@Abhijith Нет, у вас не может быть нескольких значений. Смотрите мое объяснение в ответе. - person mujjiga; 04.09.2019