使用sci-kit learn计算TF-IDF


使用sci-kit learn计算TF-IDF

TF-IDF是衡量词在某文本中重要性的一种度量。它比其他诸如简单地统计词频的方法好的一点是,它对那些在各处十分常见而又不具有太多实际意义的词处理地比较好,比如”a”, “the”等等,使得它们不能占据很多的权重。所以TF-IDF被广泛地应用在文本分类等多个领域,取得了不错的效果。

以下首先简单介绍以下TF-IDF的计算原理,其次讲一讲具体的实例,用sklearn计算各文档词的权重矩阵。最后输出某些文档前5个最关键的词。

TF即term frequency,可以理解为一个词出现在所给文档中的次数。IDF即inverse document frequency,如果利用sklearn中默认的设置,像如下代码:

TfidfTransformer(norm='l2', use_idf=True, smooth_idf=True, sublinear_tf=False)

IDF这里设置smooth_idf=True,此时IDF按如下公式计算:

进行平滑的idf计算

如果不用默认的属性,设置为smooth_idf = false,则IDF按如下公式计算:

不进行平滑的idf计算

这里的IDF即总文档数除以包含词t的文档数取对数再加1。

可以看出,前者相比后者在计算IDF时其实多了一步数据平滑的操作,也就是假设额外有一个包含所有词的文档。

TF-IDF也就是TF乘IDF。

用以上sklearn的函数计算除了TF-IDF之后,还会对计算出来的每个文档词的权重向量做一个欧几里得标准化,让权重向量长度为1。

标准化

标准化可以用以下代码实现:

>>> from sklearn.feature_extraction.text import TfidfTransformer
>>> transformer = TfidfTransformer(smooth_idf=False)
>>> transformer
TfidfTransformer(norm=...'l2', smooth_idf=False, sublinear_tf=False,
use_idf=True)

以下用一个例子具体计算:

>>> counts = [[3, 0, 1],
... [2, 0, 0],
... [3, 0, 0],
... [4, 0, 0],
... [3, 2, 0],
... [3, 0, 2]]
...
>>> tfidf = transformer.fit_transform(counts)
>>> tfidf
<6x3 sparse matrix of type '<... 'numpy.float64'>'
with 9 stored elements in Compressed Sparse ... format>

>>> tfidf.toarray()
array([[ 0.81940995, 0. , 0.57320793],
[ 1. , 0. , 0. ],
[ 1. , 0. , 0. ],
[ 1. , 0. , 0. ],
[ 0.47330339, 0.88089948, 0. ],
[ 0.58149261, 0. , 0.81355169]])

这样的counts矩阵意味着一共有六个文档,三个词。数字代表每个词出现在某文档中的次数。

让我们来计算第一个文档的tfidf权重向量。

首先计算第一个词的tfidf:

接下来计算第二个词和第三个词的tfidf:

至此,我们的初始向量为:

再进行标准化:

就得到了我们代码程序中所显示的第一行的结果。

以上为smooth_idf=False即未平滑的结果,假如smooth_idf=Ture,则有一个步平滑的操作(具体区别文首已解释过),用以下公式计算IDF:

具体的,我们代码中计算第一个文档中第3个词的idf就会改变为1.8473:

其他两个值并没有变化。然后标准化:

以上为sklearn中计算tfidf的过程。下面通过一个实例,用sklearn计算各文档词的权重矩阵。最后输出某些文档前5个最关键的词。

from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
import os


documents = "./documents/"
txt_list = []
for txt in os.listdir(documents):
#读取documents目录下的每个文件并将其路径存入txt_list列表中
txt_list.append("./documents/"+txt)


corpus = []
for i in txt_list:
f = open(i,'r')
corpus.append(f.read())
f.close


vectorizer = CountVectorizer()
transformer = TfidfTransformer()

X = vectorizer.fit_transform(corpus)
tfidf = transformer.fit_transform(X)

weight = tfidf.toarray()
t = vectorizer.get_feature_names()
key_words = []

for i in weight:#对于tfidf权重矩阵中的每一行(即单个文档的tfidf权重向量)操作

#设定一个存储前五个关键词的列表
each_key = []

#由于i是numpy的array类型,将其转化为列表,个人习惯操作
a = i.tolist()

#找tfidf权重最大的五个所对应的词
for j in range(5):
max_index = a.index(max(a))
each_key.append(t[max_index])

#找到一个当前最大值后将其设为0以便找下一个最大的
a[max_index] = 0
key_words.append(each_key)


for i in key_words:
print i

以上代码从本地文件夹documents中读入了所有的文本文件,并把每个文本文件的内容作为一个文档读入了corpus列表中。

X = vectorizer.fit_transform(corpus) 这行代码可以实现类似于之前那个例子中生成counts矩阵的功能,即得到每个词在每个文档中出现的次数的矩阵。

tfidf = transformer.fit_transform(X)计算tfidf权重矩阵,利用之前出现次数的X矩阵,来计算tfidf。

vectorizer.get_feature_names()可以依次得到每个特征名,也即每个词是什么,由于我们要得到每个文档中前五个关键词是什么,所以需要这一个操作。

for循环内即在权重矩阵中找矩阵每一行前五大的数字所对应的词,将其存入key_words中。

最后输出所有文档中tfidf排在前五的关键词。具体可以见代码注释。

得到每个文档中前n个关键词之后,后面可以进行很多有意义的工作,如文本分类,就不具体介绍了。

总之,tfidf用途很广,还是值得了解一番的。

本文前半部分主要参考:Feature extraction,后半部分计算前五个重要的词的代码等内容为自己编写。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com