任务要求:学习TF-IDF理论并实践,使用TF-IDF表示文本

初识TF-IDF

概念

TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。TF意思是词频(Term Frequency),IDF意思是逆文本频率指数(Inverse Document Frequency)。TF-IDF加权的各种形式常被搜寻引擎应用,作为文件与用户查询之间相关程度的度量或评级。

原理

TF表征词汇w在文档d出现的频率;IDF表征词的普遍重要性,它可由总文件数目除以包含该词语的文件数目取对数得到。

一般而言;词的重要性随着它在文本中出现的次数成正比,但也会随着其在语料库中出现的频率成反比,例如词汇 你,我,她,的 等,这类词汇称为停用词。所以说TF-IDF是一种基于bag-of-word的方法。TF-IDF的主要思想就是寻找在该文档中出现频率高但在其他文章中很少出现的词汇,其计算方式为:TF * IDF ,其中TF计算方式为:TFi,j=ni,jknk,jTF_{i,j} = \frac {n_{i,j}} {\sum_k n_{k,j}}

上式中ni,jn_{i,j} 表示词wiw_i 在文档djd_j中出现的次数,分母为文件djd_j中所有词出现次数之和
IDF的计算方式为:IDFi=logDj:tidjIDF_i = log \frac {|D|} {|{j:t_i\in d_j}|}

上式中|D| 表示语料库中的文件总数;j:tidj{|{j:t_i\in d_j}|} 包含词语tit_i文件数目(即ni,j=/ 0n_{i,j}{=}\mathllap{/\,}0的文件数),需注意 当词语不在语料库中时,会导致分母为0,故一般情况下使用 1+j:tidj1+{|{j:t_i\in d_j}|}

最后,词wiw_i在文档djd_j中的 “重要程度” TFIDFi,j=TFi,j×IDFiTF-IDF_{i,j} = TF_{i,j} \times IDF_i

TF-IDF 倾向于过滤掉常见的词语,保留重要的词语
For example:

假如一篇文件的总词语数是100个,而词语“母牛”出现了3次,那么“母牛”一词在该文件中的词频就是3/100=0.03。一个计算文件频率 (DF) 的方法是测定有多少份文件出现过“母牛”一词,然后除以文件集里包含的文件总数。所以,如果“母牛”一词在1,000份文件出现过,而文件总数是10,000,000份的话,其逆向文件频率就是 log(10,000,000 / 1,000)=4。最后的TF-IDF的分数为0.03 * 4=0.12

优缺点

优点:简单快速且便于理解。
缺点:在一些情况下仅使用词频的信息去衡量文章中词的重要性时不够全面,例如重要词汇出现次数不够多,或者重要词汇是用同义词形式表达的,那么就需要考虑词的上下文信息,这时就需要考虑word2vec算法。

TF-IDF实现

TF-IDF的python实现

编写TF-IDF函数

from collections import Counter
import pandas as pd
import math

def tf(word,doc_count):
    return doc_count[word]/sum(doc_count.values())

def doc_contain_word(word,doc_list):
    return sum(1 for doc_count in doc_list if word in doc_count)

def idf(word,doc_list):
    return math.log(len(count_list)/(1+doc_contain_word(word,doc_list)))

def tfidf(word,doc_count,doc_list):
    return tf(word,doc_count)*idf(word,doc_list)

## doc_count 为字典形式,统计了词频信息{'python':23,...}
## doc_list 为列表形式[list1,list2,list3]
  • 读取数据
df_train = pd.read_csv('D:/NLP_datasets/daguan/new_data/train_set.csv',nrows=5000)
df_test = pd.read_csv('D:/NLP_datasets/daguan/new_data/test_set.csv',nrows=5000)   
df_train.head()                  
  • 计算每个文本的词频(doc_count)
np_train_seg = df_train['word_seg'].as_matrix()
count_list=[]
for doc in np_train_seg:
    doc = list(map(int,doc.split(' ')))
    count = Counter(doc)
    count_list.append(count)
  • 计算并输出每个文档中tf-idf最高的三个词
for i, count in enumerate(count_list[:5]): #文档太多,只输出前5个
    print("Top words in document {}".format(i + 1))
    scores = {word: tfidf(word, count, count_list) for word in count}
    sorted_words = sorted(scores.items(), key=lambda x: x[1], reverse=True)
    for word, score in sorted_words[:3]:
        print("\tWord: {}, TF-IDF: {}".format(word, round(score, 5)))

out:
达观杯数据竞赛项目--提取TF-IDF特征(Date2)

sklearn提取TF-IDF特征

sklearn 有封装好的函数用于提取TF-IDF特征,即sklearn.feature_extraction.text.TfidfVectorizer

class sklearn.feature_extraction.text.TfidfVectorizer(input=’content’, encoding=’utf-8’, decode_error=’strict’, strip_accents=None, lowercase=True, preprocessor=None, tokenizer=None, analyzer=’word’, stop_words=None, token_pattern=’(?u)\b\w\w+\b’, ngram_range=(1, 1), max_df=1.0, min_df=1, max_features=None, vocabulary=None, binary=False, dtype=<class ‘numpy.float64’>, norm=’l2’, use_idf=True, smooth_idf=True, sublinear_tf=False)

这里主要介绍几个主要的参数:

参数 用途
stop_word {‘english’}, list, or None ;若为english,用于英语内建的停用词列表,若为list,该列表被假定为包含停用词,列表中的所有词都将被删除
ngram_range tuple (min_n, max_n) (default=(1, 1));划词个数的范围
max_df 严格忽略高于给出阈值的词条,语料指定的停用词,若为浮点值,则代表词频,整型则为绝对计数值
min_df 效果等同于max_df
from sklearn.feature_extraction.text import TfidfVectorizer
import pickle

vectorizer = TfidfVectorizer(ngram_range=(1,2),min_df=3,max_df=0.9,sublinear_tf=True)
#
vectorizer.fit(df_train['word_seg'])
x_train = vectorizer.transform(df_train['word_seg'])
x_test = vectorizer.transform(df_test['word_seg'])

y_train = df_train['class'].values

# 保存至本地
data = (x_train,y_train,x_test)
fp = open('D:\\NLP_datasets\\daguan\\data_w_tfidf.pkl','wb')
pickle.dump(data,fp)
fp.close()

pickle 用来保存和加载python数据对象的(是python的专有格式文件,其他语言无法识别),数据用dump保存到文件,用load加载

pickle 存储数据

例子:

#coding:utf8
import pickle
a = {'a':1, 'b':2, 'c':3, 'e':4, 'f':5, 'g':6}
#用上下文以二进制的方式打开一个文件,
#并把a的的数据用dump保存到文件里面
with open('dumpfile.pk', 'wb') as f:
    pickle.dump(a, f)
#直接以二进制读取方式打开保存数据的文件用load加载
with open('dumpfile.pk', 'rb') as a:
    data = pickle.load(a)
print data  #打印保存的数据

参考资料

1)https://github.com/Heitao5200/DGB/blob/master/feature/feature_code/tfidf.py
2)https://baike.sogou.com/v73026138.htm?fromTitle=tf-idf
3)https://blog.csdn.net/sangyongjia/article/details/52440063
4)TF-IDF算法解析 https://www.jb51.net/article/128346.htm
5)https://blog.csdn.net/feng_zhiyu/article/details/81952697

相关文章:

  • 2021-04-14
  • 2021-11-19
  • 2022-12-23
  • 2021-07-06
  • 2022-01-11
  • 2021-04-14
  • 2021-08-06
  • 2022-02-06
猜你喜欢
  • 2021-11-25
  • 2021-04-19
  • 2021-05-16
  • 2021-06-16
  • 2021-11-22
  • 2022-01-05
相关资源
相似解决方案