TF-IDF介绍及相关代码实现

2021-06-28  本文已影响0人  骆旺达

一、TF-IDF介绍

TF-IDF(词频-逆向文件频率)是一种用于信息检索与文本挖掘的常用加权技术。

TF-IDF的主要思想是:如果某个单词在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。

1.1 TF(Term Frequency,词频)
1.2 IDF(Inverse Document Frequency,逆向文件频率)
1.3 TF-IDF(词频-逆向文件频率)

TF-IDF(w) = \frac{在某一类词条w出现的次数}{该词条所有词数} log{ \frac{语料库中文档总数}{包含词语w的文档数目+1}}

二、基于sklearn的TF-IDF用于词向量获取

2.1、库引用
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
2.2、TF-IDF训练
x_train = ['TF-IDF 主要 思想 是','算法 一个 重要 特点 可以 脱离 语料库 背景',
           '如果 一个 网页 被 很多 其他 网页 链接 说明 网页 重要']
x_test=['原始 文本 进行 标记','主要 思想']

# max_features为维度词信息
#该类会将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在i类文本下的词频
vectorizer = CountVectorizer(max_features=10)

#该类会统计每个词语的tf-idf权值
tf_idf_transformer = TfidfTransformer()

#将文本转为词频矩阵并计算tf-idf
tf_idf = tf_idf_transformer.fit_transform(vectorizer.fit_transform(x_train))
#将tf-idf矩阵抽取出来,元素a[i][j]表示j词在i类文本中的tf-idf权重

x_train_weight = tf_idf.toarray()
 
#对测试集进行tf-idf权重计算
tf_idf = tf_idf_transformer.transform(vectorizer.transform(x_test))

x_test_weight = tf_idf.toarray()  # 测试集TF-IDF权重矩阵
 
print('输出x_train文本向量:')
print(x_train_weight)
print('输出x_test文本向量:')
print(x_test_weight)

2.3、向量结果
输出x_train文本向量:
[[0.70710678 0.         0.70710678 0.         0.         0.
  0.         0.         0.         0.        ]
 [0.         0.3349067  0.         0.44036207 0.         0.44036207
  0.44036207 0.44036207 0.         0.3349067 ]
 [0.         0.22769009 0.         0.         0.89815533 0.
  0.         0.         0.29938511 0.22769009]]
输出x_test文本向量:
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]]

三、基于原始代码的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:
     list_words:词列表
Returns:
     dict_feature_select:特征选择词字典
"""
def feature_select(list_words):
    #总词频统计
    doc_frequency=defaultdict(int)
    for word_list in list_words:
        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(list_words)
    word_idf={} #存储每个词的idf值
    word_doc=defaultdict(int) #存储包含该词的文档数
    for i in doc_frequency:
        for j in list_words:
            if i in j:
                word_doc[i]+=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))

改进版:速度从上述代码3小时变成1分钟

def feature_select(list_words):
    
    print("1、总词频统计:")
    #总词频统计
    doc_frequency=defaultdict(int)
    for word_list in tqdm(list_words):
        for i in word_list:
            doc_frequency[i]+=1
    
    print("2、TF计算:")
    #计算每个词的TF值
    n = sum(doc_frequency.values())
    word_tf={}  #存储没个词的tf值
    for i in tqdm(doc_frequency):
        word_tf[i]=doc_frequency[i]/n
   
    print("3、IDF计算:")
    #计算每个词的IDF值
    doc_num=len(list_words)
    word_idf={} #存储每个词的idf值
    word_doc=defaultdict(int) #存储包含该词的文档数
    for i in tqdm(range(len(list_words))):
        for word in list_words[i]:
            word_doc[word]+=1
    
    for i in tqdm(doc_frequency):
        word_idf[i]=math.log(doc_num/(word_doc[i]+1))

    print("4、TF计算:")
    #计算每个词的TF*IDF的值
    word_tf_idf={}
    for i in tqdm(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

四、基于sklearn的TF-IDF用于权值获取

4.1、库引用
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
4.2、数据集
corpus = [
  "帮我 查下 明天 北京 天气 怎么样",
  "帮我 查下 今天 北京 天气 好不好",
  "帮我 查询 去 北京 的 火车",
  "帮我 查看 到 上海 的 火车",
  "帮我 查看 特朗普 的 新闻",
  "帮我 看看 有没有 北京 的 新闻",
  "帮我 搜索 上海 有 什么 好玩的",
  "帮我 找找 上海 东方明珠 在哪"
]
4.3、字典构造
# 步骤1
vectoerizer = CountVectorizer(min_df=1, max_df=1.0, token_pattern='\\b\\w+\\b')

# 步骤2
vectoerizer.fit(corpus)

# 步骤3
bag_of_words = vectoerizer.get_feature_names()

print("Bag of words(词袋):")
print(bag_of_words)
# 字典大小
print(len(bag_of_words))

# 步骤4
X = vectoerizer.transform(corpus)
# 每句话种每个词出现的次数
print("Vectorized corpus:")
print(X.toarray())

# 步骤5:字典
print("index of `的` is : {}".format(vectoerizer.vocabulary_.get('上海')))
4.4、TF-IDF权值获取
from sklearn.feature_extraction.text import TfidfTransformer


# 步骤1
tfidf_transformer = TfidfTransformer()
# 步骤2
tfidf_transformer.fit(X.toarray())

# 步骤3,tf-idf权值
word_list = {}
for idx, word in enumerate(vectoerizer.get_feature_names()):
#       print("{}\t{}".format(word, tfidf_transformer.idf_[idx]))
    word_list[word] = tfidf_transformer.idf_[idx]
    

dic = sorted(word_list.items(),key=lambda x:-x[1])
print(dic)

# 步骤4 # 句子向量
# tfidf = tfidf_transformer.transform(X)
# print(tfidf.toarray())
4.5、结果
[('东方明珠', 2.504077396776274), ('什么', 2.504077396776274), ('今天', 2.504077396776274), ('到', 2.504077396776274), ('去', 2.504077396776274), ('在哪', 2.504077396776274), ('好不好', 2.504077396776274), ('好玩的', 2.504077396776274), ('怎么样', 2.504077396776274), ('找找', 2.504077396776274), ('搜索', 2.504077396776274), ('明天', 2.504077396776274), ('有', 2.504077396776274), ('有没有', 2.504077396776274), ('查询', 2.504077396776274), ('特朗普', 2.504077396776274), ('看看', 2.504077396776274), ('天气', 2.09861228866811), ('新闻', 2.09861228866811), ('查下', 2.09861228866811), ('查看', 2.09861228866811), ('火车', 2.09861228866811), ('上海', 1.8109302162163288), ('北京', 1.587786664902119), ('的', 1.587786664902119), ('帮我', 1.0)]

五、基于gensim的TF-IDF用于权值获取

gensim原始地址:models.tfidfmodel – TF-IDF model — gensim (radimrehurek.com)

5.1 语料库
corpus = [
    'this is the first document',
    'this is the second second document',
    'and the third one',
    'is this the first document'
]
5.2 分词
[输入]:
word_list = []
for i in range(len(corpus)):
    word_list.append(corpus[i].split(' '))
print(word_list)
    
[输出]:
[['this', 'is', 'the', 'first', 'document'],
 ['this', 'is', 'the', 'second', 'second', 'document'],
 ['and', 'the', 'third', 'one'],
 ['is', 'this', 'the', 'first', 'document']]
5.3 字典和词袋模型构建
from gensim import corpora
# 赋给语料库中每个词(不重复的词)一个整数id
dictionary = corpora.Dictionary(word_list)
new_corpus = [dictionary.doc2bow(text) for text in word_list]
print(new_corpus)

# 元组中第一个元素是词语在词典中对应的id,第二个元素是词语在文档中出现的次数
[输出]:
[[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1)], 
 [(0, 1), (2, 1), (3, 1), (4, 1), (5, 2)], 
 [(3, 1), (6, 1), (7, 1), (8, 1)], 
 [(0, 1), (1, 1), (2, 1), (3, 1), (4, 1)]]

通过下面的方法可以看到语料库中每个词对应的id

 [输入]:
 print(dictionary.token2id)

 [输出]:
 {'document': 0, 'first': 1, 'is': 2, 'the': 3, 'this': 4, 'second': 5, 'and': 6,
 'one': 7,   'third': 8}
5.4 TF-IDF模型训练
[输入]:
# 训练模型并保存
from gensim import models
tfidf = models.TfidfModel(new_corpus)
tfidf.save("my_model.tfidf")

# 载入模型
tfidf = models.TfidfModel.load("my_model.tfidf")

# 使用这个训练好的模型得到单词的tfidf值
print(list(tfidf[new_corpus]))

[输出]:
[[(0, 0.33699829595119235),
  (1, 0.8119707171924228),
  (2, 0.33699829595119235),
  (4, 0.33699829595119235)],
 [(0, 0.10212329019650272),
  (2, 0.10212329019650272),
  (4, 0.10212329019650272),
  (5, 0.9842319344536239)],
 [(6, 0.5773502691896258), (7, 0.5773502691896258), (8, 0.5773502691896258)],
 [(0, 0.33699829595119235),
  (1, 0.8119707171924228),
  (2, 0.33699829595119235),
  (4, 0.33699829595119235)]]
核心代码
# TF-IDF
dictionary = corpora.Dictionary(Descartes_doc)
new_corpus = [dictionary.doc2bow(text) for text in Descartes_doc]
tfidf = models.TfidfModel(new_corpus)
corpus_tfidf = tfidf[new_corpus]

结论:

参考文献

上一篇下一篇

猜你喜欢

热点阅读