TF-IDF(Term Frequency/Inverse Document Frequency)是信息检索领域非常重要的搜索词重要性的度量;用以衡量一个关键词 \(w\) 对于查询(Query,可看作文档)所能提供的信息。词频(Term Frequency, TF)表示关键词 \(w\) 在文档 \(D_i\) 中出现的频率:
\[TF_{w,D_i}= \frac {count(w)} {\left| D_i \right|} \]
其中,\(count(w)\) 为关键词 \(w\) 的出现次数,\(\left| D_i \right|\) 为文档 \(D_i\) 中所有词的数量。逆文档频率(Inverse Document Frequency, IDF)反映关键词的普遍程度——当一个词越普遍(即有大量文档包含这个词)时,其 IDF 值越低;反之,则 IDF 值越高。IDF 定义如下:
\[IDF_w=\log \frac {N}{\sum_{i=1}^N I(w,D_i)} \]
其中,\(N\) 为所有的文档总数,\(I(w,D_i)\) 表示文档 \(D_i\) 是否包含关键词,若包含则为 1,若不包含则为 0。若词 \(w\) 在所有文档中均未出现,则 IDF 公式中的分母为 0;因此需要对 IDF 做平滑(smooth):
\[IDF_w=\log \frac {N}{1+\sum_{i=1}^N I(w,D_i)} \]
关键词 \(w\) 在文档 \(D_i\) 的 TF-IDF 值:
\[TF-IDF_{w,D_i}=TF_{w,D_i}*IDF_w \]
从上述定义可以看出:
《》从概率的角度给出 TF-IDF 的数学解释,《》为 TF-IDF 的实操教程,包括 TF-IDF 的一般计算、正则化,以及如何使用 scikit-learn(sklearn)来计算 TF-IDF 矩阵。
最近碰到一个需求,挖掘行业关键词;比如,IT 行业的关键词有:Java、Python、机器学习等。TF-IDF 正好可用来做关键词的抽取,词 TF-IDF 值越大,则说明该词为关键词。那么,问题来了:如何套用 TF-IDF 模型呢?
为了做关键词挖掘,首先得有数据;我们从某招聘网站爬取了 20 个行业招聘信息数据。然后,对数据进行分词。我们发现,行业关键词具有领域特定性,即一个行业的关键词一般不会同属于另外几个行业。因此,我们每一个行业的分词结果作为一个大 doc,则 doc 的总数量为 20。用 sklearn 计算 TF-IDF 矩阵,取每个行业 top 词。
在上述模型套用中,因为 doc 总数少,发现 top 词中会有一些常见词,诸如 "认真负责"、"岗位" 之类。为了过滤常见词,采取两个办法:
分词采用的 jieba,如果觉得分词效果不太理想,可采用百度词条作为自定义分词词典;TF-IDF 计算依赖于 sklearn;求 matrix 的 row top 则用到了 numpy。具体代码如下:
- # - *-coding: utf - 8 - *-#@Time: 2016 / 9 / 6#@Author: rain import codecs import os import jieba.analyse import numpy as np import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer base_path = "./resources/corpus/"seg_path = "./resources/segmented/"def segment() : """word segment"""
- for txt in os.listdir(base_path) : whole_base = os.path.join(base_path, txt) whole_seg = os.path.join(seg_path, txt) with codecs.open(whole_base, 'r', 'utf-8') as fr: fw = codecs.open(whole_seg, 'w', 'utf-8') for line in fr.readlines() : #seg_list = jieba.cut(line.strip()) seg_list = jieba.analyse.extract_tags(line.strip(), topK = 20, withWeight = False, allowPOS = ()) fw.write(" ".join(seg_list)) fw.close() def read_doc_list() : """read segmented docs"""trade_list = [] doc_list = []
- for txt in os.listdir(seg_path) : trade_list.append(txt.split(".")[0]) with codecs.open(os.path.join(seg_path, txt), "r", "utf-8") as fr: doc_list.append(fr.read().replace('\n', '')) return trade_list,
- doc_list def tfidf_top(trade_list, doc_list, max_df, topn) : vectorizer = TfidfVectorizer(max_df = max_df) matrix = vectorizer.fit_transform(doc_list) feature_dict = {
- v: k
- for k,
- v in vectorizer.vocabulary_.items()
- }#index - >feature_name top_n_matrix = np.argsort( - matrix.todense())[: , :topn]#top tf - idf words
- for each row df = pd.DataFrame(np.vectorize(feature_dict.get)(top_n_matrix), index = trade_list)#convert matrix to df
- return df segment() tl,
- dl = read_doc_list() tdf = tfidf_top(tl, dl, max_df = 0.3, topn = 500) tdf.to_csv("./resources/keywords.txt", header = False, encoding = 'utf-8')
来源: http://www.cnblogs.com/en-heng/p/5848553.html