TF-IDF

一、分词

1. 分词的基本原理

现代分词都是基于统计的分词,而统计的样本内容来自于一些标准的语料库

分词通常采用马尔科夫假设,每一个分词出现的概率仅仅和前一个分词有关:

                                  

联合分布为:

                                  

而通过我们的标准语料库,我们可以近似的计算出所有的分词之间的二元条件概率,比如任意两个词w_{1}, w_{2},它们的条件概率分布可以近似的表示为:

                                  

 

2. 维特比算法与分词

维特比算法采用的是动态规划来解决这个最优分词问题的,首先我们看一个简单的分词例子:"人生如梦境"。

 

jieba分词

 

二、文本挖掘预处理之向量化与Hash Trick

1. 词袋模型

词袋模型假设我们不考虑文本中词与词之间的上下文关系,仅仅只考虑所有词的权重。而权重与词在文本中出现的频率有关。

词袋模型首先会进行分词,在分词之后,通过统计每个词在文本中出现的次数,我们就可以得到该文本基于词的特征,如果将各个文本样本的这些词与对应的词频放在一起,就是我们常说的向量化。

例如将下面4个短文本做了词频统计:

corpus=["I come to China to travel", 
    "This is a car polupar in China",          
    "I love tea and Apple ",   
    "The work is to write some papers in science"] 

词向量如下:

from sklearn.feature_extraction.text import CountVectorizer  
vectorizer=CountVectorizer()
corpus=["I come to China to travel", 
    "This is a car polupar in China",          
    "I love tea and Apple ",   
    "The work is to write some papers in science"] 
print(vectorizer.fit_transform(corpus))


print(vectorizer.fit_transform(corpus).toarray())
print(vectorizer.get_feature_names())
[[0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 2 1 0 0]
 [0 0 1 1 0 1 1 0 0 1 0 0 0 0 1 0 0 0 0]
 [1 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0]
 [0 0 0 0 0 1 1 0 1 0 1 1 0 1 0 1 0 1 1]]
[u'and', u'apple', u'car', u'china', u'come', u'in', u'is', u'love', u'papers', u'polupar', u'science', u'some', u'tea', u'the', u'this', u'to', u'travel', u'work', u'write']


如果我们直接将统计词频后的19维特征做为文本分类的输入,会发现有一些问题。比如第一个文本,我们发现"come", "China"和 “Travel”各出现1次,而“to“出现了两次。似乎看起来这个文本与”to“这个特征更关系紧密。但是实际上”to“是一个非常普遍的词,几乎所有的文本都会用到,因此虽然它的词频为2,但是重要性却比词频为1的"China"和“Travel”要低的多。如果我们的向量化特征仅仅用词频表示就无法反应这一点。因此我们需要进一步的预处理来反应文本的这个特征,而这个预处理就是TF-IDF。

 

三、文本挖掘预处理之TF-IDF

向量化完毕后一般也会使用TF-IDF进行特征的权重修正,再将特征进行标准化。

1. TF-IDF概述

TF-IDF是Term Frequency -  Inverse Document Frequency的缩写,即“词频-逆文本频率”。它由两部分组成,TF和IDF。

TF也就是我们前面说到的词频,我们之前做的向量化也就是做了文本中各个词的出现频率统计,并作为文本特征。

IDF反应了一个词在所有文本中出现的频率,如果一个词在很多的文本中出现,那么它的IDF值应该低,比如上文中的“to”。而反过来如果一个词在比较少的文本中出现,那么它的IDF值应该高。比如一些专业的名词如“Machine Learning”。这样的词IDF值应该高。一个极端的情况,如果一个词在所有的文本中都出现,那么它的IDF值应该为0。

一个词x的IDF的基本公式如下:

                                  

其中,N代表语料库中文本的总数,而N(x)代表语料库中包含词x的文本总数,表示文本频率

上面的IDF公式已经可以使用了,但是在一些特殊的情况会有一些小问题,比如某一个生僻词在语料库中没有,这样我们的分母为0, IDF没有意义了。所以常用的IDF我们需要做一些平滑,使语料库中没有出现的词也可以得到一个合适的IDF值。平滑的方法有很多种,最常见的IDF平滑后的公式之一为:

                                  

 

有了IDF的定义,我们就可以计算某一个词的TF-IDF值了:

                                  

其中TF(x)指词x在当前文本中的词频。

2. 用scikit-learn进行TF-IDF预处理

2.1 CountVectorizer类向量化 + TfidfTransformer类进行预处理

第一种方法是在用CountVectorizer类向量化之后再调用TfidfTransformer类进行预处理。


from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer

corpus=["I come to China to travel",
    "This is a car polupar in China",
    "I love tea and Apple ",
    "The work is to write some papers in science"]

vectorizer=CountVectorizer()
transformer = TfidfTransformer()

tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))
print(tfidf)

2.2 TfidfVectorizer

from sklearn.feature_extraction.text import TfidfVectorizer
corpus=["I come to China to travel",
    "This is a car polupar in China",
    "I love tea and Apple ",
    "The work is to write some papers in science"]

tfidf2 = TfidfVectorizer()
re = tfidf2.fit_transform(corpus)
print(re)
from sklearn.feature_extraction.text import CountVectorizer
train_set = ("The sky is blue.", "The sun is bright.")
test_set = ("The sun in the sky is bright.","We can see the shining sun, the bright sun.")
count_vectorizer = CountVectorizer(stop_words=['is','The','the'])
count_vectorizer.fit_transform(train_set)

print( "Vocabulary:", count_vectorizer.vocabulary_)
freq_term_matrix = count_vectorizer.transform(test_set)
print("测试集的词频矩阵:\n", freq_term_matrix.todense())

# 注意:在最新的sklearn中idf是# smooth_idf = Talse, log(N / df) + 1,所以只要同时出现的话,就是1;
# smooth_idf = True, idf(d, t) = log [ (1 + n) / (1 + df(d, t)) ] + 1.
from sklearn.feature_extraction.text import TfidfTransformer
tfidf = TfidfTransformer(norm="l2", smooth_idf = True)
tfidf.fit(freq_term_matrix)
print("IDF:", tfidf.idf_)

详细:

{'sky': 2, 'blue': 0, 'sun': 3, 'bright': 1}

字典为:['blue','sun','bright','sky']

测试集的词频矩阵:
 [[0 1 1 1]
 [0 1 0 2]]

计算TF-IDF值

 

3. 中文文本TF-IDF

2.1 语料集

corpus = [
  "帮我 查下 明天 北京 天气 怎么样",
  "帮我 查下 今天 北京 天气 好不好",
  "帮我 查询 去 北京 的 火车",
  "帮我 查看 到 上海 的 火车",
  "帮我 查看 特朗普 的 新闻",
  "帮我 看看 有没有 北京 的 新闻",
  "帮我 搜索 上海 有 什么 好玩的",
  "帮我 找找 上海 东方明珠 在哪"
]

2.2 将语料转换为词袋向量

步骤:

  • step 1. 声明一个向量化工具vectorizer; 注:此时需要设定常用参数(6个常用参数)
  • step 2. 根据语料集统计词袋(fit); 词袋:一系列词的集合。
  • step. 打印语料集的词袋信息;
  • step 3. 将语料集转化为词袋向量(transform);
  • step. 还可以查看每个词在词袋中的索引;
from sklearn.feature_extraction.text import CountVectorizer
# step 1
vectoerizer = CountVectorizer()
# step 2
vectoerizer.fit(corpus)
# step 打印语料集的词袋信息
bag_of_words = vectoerizer.get_feature_names()
print("Bag of words:")
print(bag_of_words)
print(len(bag_of_words))
# step 3
X = vectoerizer.transform(corpus)
print("Vectorized corpus:")
print(X.toarray())
# step
print("index of `的` is : {}".format(vectoerizer.vocabulary_.get('的')))

输出:

Bag of words:
['上海', '东方明珠', '什么', '今天', '北京', '在哪', '天气', '好不好', '好玩的', '帮我', '怎么样', '找找', '搜索', '新闻', '明天', '有没有', '查下', '查看', '查询', '火车', '特朗普', '看看']
22
Vectorized corpus:
[[0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 1 0 0 0 0 0]
 [0 0 0 1 1 0 1 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0]
 [0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0]
 [1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0]
 [0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0]
 [0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1]
 [1 0 1 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0]
 [1 1 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0]]

2.3 根据词袋向量统计TF-IDF

  • step 1. 声明一个TF-IDF转化器(TfidfTransformer);
  • step 2. 根据语料集的词袋向量计算TF-IDF(fit);
  • step. 打印TF-IDF信息:比如结合词袋信息,可以查看每个词的TF-IDF值;
  • step. 将语料集的词袋向量表示转换为TF-IDF向量表示;
from sklearn.feature_extraction.text import TfidfTransformer
# step 1
tfidf_transformer = TfidfTransformer()
# step 2
tfidf_transformer.fit(X.toarray())
# step 3
for idx, word in enumerate(vectoerizer.get_feature_names()):
  print("{}\t{}".format(word, tfidf_transformer.idf_[idx]))
# step 4
tfidf = tfidf_transformer.transform(X)
print(tfidf.toarray())

输出(tf-idf矩阵 元素a[i][j]表示j词在i类文本中的tf-idf权重):

上海	1.8109302162163288
东方明珠	2.504077396776274
什么	2.504077396776274
今天	2.504077396776274
北京	1.587786664902119
在哪	2.504077396776274
天气	2.09861228866811
好不好	2.504077396776274
好玩的	2.504077396776274
帮我	1.0
怎么样	2.504077396776274
找找	2.504077396776274
搜索	2.504077396776274
新闻	2.09861228866811
明天	2.504077396776274
有没有	2.504077396776274
查下	2.09861228866811
查看	2.09861228866811
查询	2.504077396776274
火车	2.09861228866811
特朗普	2.504077396776274
看看	2.504077396776274
[[0.         0.         0.         0.         0.3183848  0.
  0.42081614 0.         0.         0.20052115 0.50212047 0.
  0.         0.         0.50212047 0.         0.42081614 0.
  0.         0.         0.         0.        ]
 [0.         0.         0.         0.50212047 0.3183848  0.
  0.42081614 0.50212047 0.         0.20052115 0.         0.
  0.         0.         0.         0.         0.42081614 0.
  0.         0.         0.         0.        ]
 [0.         0.         0.         0.         0.42141948 0.
  0.         0.         0.         0.26541316 0.         0.
  0.         0.         0.         0.         0.         0.
  0.6646151  0.55699932 0.         0.        ]
 [0.50057382 0.         0.         0.         0.         0.
  0.         0.         0.         0.27641806 0.         0.
  0.         0.         0.         0.         0.         0.58009435
  0.         0.58009435 0.         0.        ]
 [0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.24938702 0.         0.
  0.         0.52336667 0.         0.         0.         0.52336667
  0.         0.         0.62448441 0.        ]
 [0.         0.         0.         0.         0.35097418 0.
  0.         0.         0.         0.22104618 0.         0.
  0.         0.46389023 0.         0.55351674 0.         0.
  0.         0.         0.         0.55351674]
 [0.37686288 0.         0.52110999 0.         0.         0.
  0.         0.         0.52110999 0.20810458 0.         0.
  0.52110999 0.         0.         0.         0.         0.
  0.         0.         0.         0.        ]
 [0.37686288 0.52110999 0.         0.         0.         0.52110999
  0.         0.         0.         0.20810458 0.         0.52110999
  0.         0.         0.         0.         0.         0.
  0.         0.         0.         0.        ]]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值