Tf-Idf详解及应用

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的计算公式如下:TF_w=\frac{N_w}{N}其中N_w是在某一文本中词条w出现的次数,N是该文本总词条数。

IDF的计算公式:
IDF_w=log(\frac{Y}{Y_w+1})其中Y是语料库的文档总数,Y_w是包含词条w的文档数,分母加一是为了避免w未出现在任何文档中从而导致分母为0的情况。
TF-IDF的就是将TF和IDF相乘
TF-IDF_w=TF_w * IDF_w从以上计算公式便可以看出,某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容