【问题标题】:Scikit Learn TfidfVectorizer : How to get top n terms with highest tf-idf scoreScikit Learn TfidfVectorizer:如何获得具有最高 tf-idf 分数的前 n 个术语
【发布时间】:2016-03-17 21:02:57
【问题描述】:

我正在研究关键字提取问题。考虑非常普遍的情况

from sklearn.feature_extraction.text import TfidfVectorizer

tfidf = TfidfVectorizer(tokenizer=tokenize, stop_words='english')

t = """Two Travellers, walking in the noonday sun, sought the shade of a widespreading tree to rest. As they lay looking up among the pleasant leaves, they saw that it was a Plane Tree.

"How useless is the Plane!" said one of them. "It bears no fruit whatever, and only serves to litter the ground with leaves."

"Ungrateful creatures!" said a voice from the Plane Tree. "You lie here in my cooling shade, and yet you say I am useless! Thus ungratefully, O Jupiter, do men receive their blessings!"

Our best blessings are often the least appreciated."""

tfs = tfidf.fit_transform(t.split(" "))
str = 'tree cat travellers fruit jupiter'
response = tfidf.transform([str])
feature_names = tfidf.get_feature_names()

for col in response.nonzero()[1]:
    print(feature_names[col], ' - ', response[0, col])

这给了我

  (0, 28)   0.443509712811
  (0, 27)   0.517461475101
  (0, 8)    0.517461475101
  (0, 6)    0.517461475101
tree  -  0.443509712811
travellers  -  0.517461475101
jupiter  -  0.517461475101
fruit  -  0.517461475101

这很好。对于任何进来的新文档,有没有办法获得 tfidf 分数最高的前 n 个词条?

【问题讨论】:

  • 您可能不应该覆盖 Python 数据类型 str。

标签: python scikit-learn nlp nltk tf-idf


【解决方案1】:

您必须做一些歌舞才能将矩阵作为 numpy 数组,但这应该可以满足您的需求:

feature_array = np.array(tfidf.get_feature_names())
tfidf_sorting = np.argsort(response.toarray()).flatten()[::-1]

n = 3
top_n = feature_array[tfidf_sorting][:n]

这给了我:

array([u'fruit', u'travellers', u'jupiter'], 
  dtype='<U13')

argsort 调用确实很有用,here are the docs for it。我们必须做[::-1] 因为argsort 只支持从小到大排序。我们调用flatten 将维度减少到一维,以便排序索引可用于索引一维特征数组。请注意,包含对flatten 的调用仅在您同时测试一个文档时才有效。

另外,另外,你的意思是像tfs = tfidf.fit_transform(t.split("\n\n")) 这样的东西吗?否则,多行字符串中的每个术语都被视为“文档”。使用 \n\n 代替意味着我们实际上正在查看 4 个文档(每行一个),当您考虑 tfidf 时,这更有意义。

【讨论】:

  • 如何通过使用 DictVectorizer + TfidfTransformer 来实现?
  • 如果我们想为每个类而不是每个文档列出前 n 个术语怎么办?我问了一个问题here,但还没有回复!
  • 奇怪的是,最后一行给出了内存错误,而将其替换为top_n = feature_array[tfidf_sorting[:n]] 却没有。
  • 顺便说一句,@hume 这一行tfidf_sorting = np.argsort(response.toarray()).flatten()[::-1] 给了我一个内存错误,这一定是因为我的 tf-idf 矩阵太大了。所以我想我可以分批做到这一点?
  • 我根本没有研究过这个,但是将 tfidf.get_feature_names() 转换为 numpy.array 使用比默认 Python 列表更多的内存。当我在 get_feature_names() 上调用 numpy.array 时,我的 300mb TFIDF 模型在 RAM 中变成了 4+ Gb,而简单地使用 feature_array = tfidf.get_feature_names() 可以正常工作并且使用很少的 RAM。
【解决方案2】:

使用稀疏矩阵本身的解决方案(没有.toarray())!

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

tfidf = TfidfVectorizer(stop_words='english')
corpus = [
    'I would like to check this document',
    'How about one more document',
    'Aim is to capture the key words from the corpus',
    'frequency of words in a document is called term frequency'
]

X = tfidf.fit_transform(corpus)
feature_names = np.array(tfidf.get_feature_names())


new_doc = ['can key words in this new document be identified?',
           'idf is the inverse document frequency caculcated for each of the words']
responses = tfidf.transform(new_doc)


def get_top_tf_idf_words(response, top_n=2):
    sorted_nzs = np.argsort(response.data)[:-(top_n+1):-1]
    return feature_names[response.indices[sorted_nzs]]
  
print([get_top_tf_idf_words(response,2) for response in responses])

#[array(['key', 'words'], dtype='<U9'),
 array(['frequency', 'words'], dtype='<U9')]

【讨论】:

  • 它还会返回重复的单词,当我再次尝试将这些前 n 个单词用作 tfidfvectorizer 中的词汇表时,它会抛出并赋值错误,因为词汇中有重复的单词。我将如何获得前 n 个唯一词?
  • 有趣。我使用get_feature_names() 来获取feature_names,因此get_top_tf_idf_words 不应返回任何重复项。你能发布一个新问题,有一个可重复的例子并标记我吗?
【解决方案3】:

这是一个快速代码: (documents 是一个列表)

def get_tfidf_top_features(documents,n_top=10):
  fidf_vectorizer = TfidfVectorizer(max_df=0.95, min_df=2, max_features=no_features, stop_words='english')
  tfidf = tfidf_vectorizer.fit_transform(documents)
  importance = np.argsort(np.asarray(tfidf.sum(axis=0)).ravel())[::-1]
  tfidf_feature_names = np.array(tfidf_vectorizer.get_feature_names())
  return tfidf_feature_names[importance[:n_top]]

【讨论】:

  • 第二行有错别字。缺少第一个字符“t”。
猜你喜欢
  • 2020-01-11
  • 2019-11-04
  • 2019-11-04
  • 2019-06-09
  • 2019-07-31
  • 2016-10-11
  • 2015-02-11
  • 2019-08-13
  • 2019-11-14
相关资源
最近更新 更多