TF-IDF(term frequency–inverse document frequency,词频-逆向文件频率)是一种用于信息检索(information retrieval)与文本挖掘(text mining)的常用加权技术。
TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。
TF-IDF的主要思想是:如果某个单词在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
TF是词频(Term Frequency)
词频(TF)表示词条(关键字)在文本中出现的频率。
$$ tf_{ij}=\frac{n_{ij}}{\sum_k n_{kj}} $$
IDF是逆向文件频率(Inverse Document Frequency)
逆向文件频率 (IDF) :某一特定词语的IDF,可以由总文件数目除以包含该词语的文件的数目,再将得到的商取对数得到。
如果包含词条word的文档越少, IDF越大,则说明词条具有很好的类别区分能力。
$$ idf_i=\log{\frac{|D|}{|\{j:t_i\in d_j\}|}}=\log{\frac{\text{语料库文档总数}}{\text{语料库中含词word的文档数}+1}} $$
+1避免分母为0
j 是文档,i 是文档 j 中的词
总公式:
$$ \text{TF-IDF}=tf * idf $$
有了每个词的TF-IDF值后,再搞一个阈值,超过阈值的视为新词。
# -*- coding: utf-8 -*-
from collections import defaultdict
import math
import operator
"""
函数说明:创建数据样本
Returns:
dataset - 实验样本切分的词条
classVec - 类别标签向量
"""
def loadDataSet():
dataset = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'], # 切分的词条
['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
['stop', 'posting', 'stupid', 'worthless', 'garbage'],
['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
classVec = [0, 1, 0, 1, 0, 1] # 类别标签向量,1代表好,0代表不好
return dataset, classVec
"""
函数说明:特征选择TF-IDF算法
Parameters:
doc_list:词列表
Returns:
dict_feature_select:特征选择词字典
"""
def feature_select(doc_list):
# 总词频统计
doc_frequency = defaultdict(int)
for word_list in doc_list:
for i in word_list:
doc_frequency[i] += 1
# 计算每个词的TF值
word_tf = {} # 存储每个词的tf值
for i in doc_frequency:
word_tf[i] = doc_frequency[i] / sum(doc_frequency.values())
# 计算每个词的IDF值
doc_num = len(doc_list)
word_idf = {} # 存储每个词的idf值
word_doc = defaultdict(int) # 存储包含该词的文档数
for word in doc_frequency:
for doc in doc_list:
if word in doc:
word_doc[word] += 1
for i in doc_frequency:
word_idf[i] = math.log(doc_num / (word_doc[i] + 1))
# 计算每个词的TF*IDF的值
word_tf_idf = {}
for i in doc_frequency:
word_tf_idf[i] = word_tf[i] * word_idf[i]
# 对字典按值由大到小排序
dict_feature_select = sorted(word_tf_idf.items(), key=operator.itemgetter(1), reverse=True)
return dict_feature_select
if __name__ == '__main__':
data_list, label_list = loadDataSet() # 加载数据
features = feature_select(data_list) # 所有词的TF-IDF值
print(features)
print(len(features))
TF-IDF 采用文本逆频率 IDF 对 TF 值加权取权值大的作为关键词,但 IDF 的简单结构并不能有效地反映单词的重要程度和特征词的分布情况,使其无法很好地完成对权值调整的功能,所以 TF-IDF 算法的精度并不是很高,尤其是当文本集已经分类的情况下。
在本质上 IDF 是一种试图抑制噪音的加权,并且单纯地认为文本频率小的单词就越重要,文本频率大的单词就越无用。这对于大部分文本信息,并不是完全正确的。IDF 的简单结构并不能使提取的关键词, 十分有效地反映单词的重要程度和特征词的分布情 况,使其无法很好地完成对权值调整的功能。尤其是在同类语料库中,这一方法有很大弊端,往往一些同类文本的关键词被盖。