TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。TF意思是词频(Term Frequency),IDF意思是逆文本频率指数(Inverse Document Frequency)。
为什么要用TF-IDF?因为计算机只能识别数字,对于一个一个的单词,计算机是看不懂的,更别说是一句话,或是一篇文章,而TF-IDF就是用来将文本转换成计算机看得懂的语言,或者说是机器学习或深度学习模型能够进行学习训练的数据集。
首先看一下一个文本经过TF-IDF转换后得到的是什么?(后文附代码)
arr=train_text_vector.toarray() # transform to array shape
shape of Tf-Idf matrix这是在做一次文本分类项目时的结果,其中6100是样本个数,每一个样本是一句话(一个字符串),总样本数为9283个,这9283个样本包括了训练集和预测集,可以看作是一个总的语料库,经过9283个样本的训练(fit),将该训练器运用到6100个样本上,将其转换(transform)为对应的文本矩阵,即图中看到的6100x21864大小的矩阵,也就是说经过TF-IDF的转换,每一个样本可以被表示成1x21864的向量,这就是我们想要的结果(这里没有降维,可以去掉一些平凡词或者特殊词),它可以变成计算机看得懂的语言。
了解了TF-IDF是干什么的之后,接下来说说它的算法原理以及实现代码。其实TF-IDF的算法原理很简单。
TF是term frequency的缩写,指的是某一个给定的词语在该文件(注意这里的该文件与后面所有文本的区别)中出现的次数,这个数字通常会被归一化(一般是词频除以文章总词数), 以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否)。
而IDF逆向文件频率 (inverse document frequency, IDF)反应了一个词在所有文本(整个文档)中出现的频率,如果一个词在很多的文本中出现,那么它的IDF值应该低。而反过来如果一个词在比较少的文本中出现,那么它的IDF值应该高。比如一些专业的名词如“Machine Learning”。这样的词IDF值应该高。一个极端的情况,如果一个词在所有的文本中都出现,那么它的IDF值应该为0。
如果单单以TF或者IDF来计算一个词的重要程度都是片面的,因此TF-IDF综合了TF和IDF两者的优点,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。上述引用总结就是,一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章,越能与其它文章区分开来。
TF-IDF的计算方法十分简单
TF的计算公式如下:
其中
是在某一文本中词条w出现的次数,
是该文本总词条数。
IDF的计算公式:
其中
是语料库的文档总数,
是包含词条
的文档数,分母加一是为了避免
未出现在任何文档中从而导致分母为
的情况。
TF-IDF的就是将TF和IDF相乘
从以上计算公式便可以看出,某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。
接下来看看代码实现,用一个简单的语料库(只有两个文本)来模拟
TfidfTransformer是把TF矩阵转成TF-IDF矩阵,所以需要先词频统计CountVectorizer,转换成TF-IDF矩阵
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
# corpus 模拟语料库
corpus=["second third document",
"second second document"]
tfvectorizer=CountVectorizer()
count_vector=tfvectorizer.fit_transform(corpus) # Tf 矩阵
transformer = TfidfTransformer() # 转换Tf矩阵
tfidf = transformer.fit_transform(count_vector) # 将TF转换成Tf-Idf
arr=tfidf.toarray()
结果如下,那么这两个文件就可以分别用这两个向量来表示了
TF-IDF
以上是先计算了TF然后再转换成了TF-IDF,也有一步到位的方法
# TF-IDF一步到位
# 训练整个语料库
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(max_df=0.5,min_df=0.0003) # 可以不加参数,这里加参数是为了降维
# =============================================================================
# all_text_vector = tfidf.fit_transform(all_text) #when fit transform to vector
# =============================================================================
tfidf.fit(corpus) # use vectorizer to fit the corpus
corpus_vector=tfidf.transform(corpus).toarray()
# print(corpus_vector)
整个项目源代码
import pandas as pd
from string import punctuation
import re
def cleandata(data):
clean=[]
# 英文标点符号+中文标点符号
punc = punctuation + u'.,;《》?!""''@#¥%…&×()——+【】{};;●,。&~、|\s::'
for line in data:
line = re.sub(r"[{}]+".format(punc)," ",line)
clean.append(line)
clean=pd.DataFrame(clean)
return clean
# clean predict data
predata=pd.read_csv('test.csv') #
pre_clean=[]
pre_clean=cleandata(predata['review'])
# clean train data
traindata=pd.read_csv('train.csv',lineterminator='\n') #
train_clean=[]
train_clean=cleandata(traindata['review'])
# 所有清洗后的文本
all_clean=train_clean.append(pre_clean)
all_text=all_clean.iloc[:,0] # 取第一列 否则报错 转成了series
m=6100
n=6328
train_text=train_clean[0:m].iloc[:,0]
test_text=train_clean[m:n].iloc[:,0]
# Tf-idf
# 训练整个语料库
# TF-IDF一步到位
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(max_df=0.5,min_df=0.0003)
# =============================================================================
# all_text_vector = tfidf.fit_transform(all_text) #fit的同时transform成vector
# =============================================================================
tfidf.fit(all_text) # 让tfidf去fit这些数据
all_text_vector=tfidf.transform(all_text).toarray()
train_text_vector=tfidf.transform(train_text)
test_text_vector=tfidf.transform(test_text)
train_label=traindata[0:m]['label']
test_label=traindata[m:n]['label']
# =============================================================================
# 先算TF 再算IDF
# count_v1=CountVectorizer(vocabulary=count_v0.vocabulary_);
# counts_train = count_v1.fit_transform(train_text);
#
# count_v2=CountVectorizer(vocabulary=count_v0.vocabulary_);
# counts_test = count_v2.fit_transform(test_text);
#
# tfidftransformer = TfidfTransformer();
# train_text_vector = tfidftransformer.fit(counts_train).transform(counts_train)
# test_text_vector = tfidftransformer.fit(counts_test).transform(counts_test)
# print(train_text_vector)
# =============================================================================
# classifcation methods
# bayes alpha=0.2 0.7
from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB(alpha = 0.2)
# svm 0.64
# =============================================================================
# from sklearn.svm import SVC
# clf = SVC(kernel = 'linear')
# =============================================================================
# decition tree
# =============================================================================
# from sklearn.tree import DecisionTreeClassifier
# clf = DecisionTreeClassifier()
# =============================================================================
# logistic
# =============================================================================
# from sklearn.linear_model import LogisticRegression
# clf = LogisticRegression()
# =============================================================================
# MLP
# =============================================================================
# from sklearn.neural_network import MLPClassifier
# clf = MLPClassifier()
# =============================================================================
# output auc
clf = clf.fit(train_text_vector,train_label)
# =============================================================================
# preds = clf.predict(test_text_vector); #输出预测标签
# preds = preds.tolist()
# =============================================================================
# proba
proba=clf.predict_proba(test_text_vector)
from sklearn import metrics
auc=metrics.roc_auc_score(test_label,proba[:,1]) # 看测试集的auc如何
pre_text=pre_clean.iloc[:,0]
pre_text_vector=tfidf.transform(pre_text)
pre_proba=clf.predict_proba(pre_text_vector)