文本预处理:TF-IDF

前一篇博客已经讲了向量化,那么向量化之后一般都伴随着TF-IDF的处理,这篇博客就TF-IDF做一个解释。

1 向量化特征的不足

还是上一篇博客中的例子,如果我们直接将统计词频后的 9 {9} 9维向量作为文本分类的输入,会发现一些问题。比如第一个文本 ′ T h i s   i s   t h e   f i r s t   d o c u m e n t . ′ {'This\ is\ the\ first\ document.'} This is the first document.,每个词在该文本中都只出现了一次,似乎看起来很平等,但是,像 i s {is} is t h e {the} the这种特征非常普遍,几乎每个样本都会出现,经常出现的词说明它是烂大街的了,并不那么重要,不能和 f i r s t {first} first d o c u m e n t {document} document等这种实义词混为一谈。我们的向量化特征仅仅用词频表示不了这种语义特征(语义信息),因此我们需要进一步的预处理来反映文本(词)的重要性,这就引出了 T F − I D F {TF-IDF} TFIDF

2 TF-IDF

TF-IDF,全名:Term Frequency - Inverse Document Frequency,即“词频-逆文本频率”,由两部分组成: T F {TF} TF I D F {IDF} IDF
T F {TF} TF就是我们说的词频,之前做的向量化已经做了文本中各个词的出现频率统计,并作为文本特征。词频 t f {tf} tf等于词 w {w} w在文档(或者一段文本) d {d} d中出现的次数 c o u n t ( w , d ) {count(w,d)} count(w,d)和文档 d {d} d中总词数 s i z e ( d ) {size(d)} size(d)的比值。
t f ( w , d ) = c o u n t ( w , d ) s i z e ( d ) {tf(w,d)=\frac{count(w,d)}{size(d)}} tf(w,d)=size(d)count(w,d)
关键是 I D F {IDF} IDF怎么计算,即“逆文档频率”怎么理解。其实 I D F {IDF} IDF是帮助我们来反应一个词的重要程度的,这也是它修正仅仅用词频表示的特征值的原因和目的。如果一个词在所有文本中都出现了,那么它的 I D F {IDF} IDF值应该低,说明这个词属于烂大街的,比如 ′ ′ t h e ′ ′ {''the''} the这个单词,而反过来,如果一个词在比较少的文本中出现,那么它的 I D F {IDF} IDF值应该高,比如 ′ ′ f i r s t ′ ′ {''first''} first ′ ′ t h i r d ′ ′ {''third''} third。这是在定性上说明 I D F {IDF} IDF的作用,那么如何从定量上分析一个词的 I D F {IDF} IDF呢?这里给出公式:
I D F ( x ) = l o g N N ( x ) {IDF(x)=log\frac{N}{N(x)}} IDF(x)=logN(x)N
其中, N {N} N代表语料库中文本的总数,而 N ( x ) {N(x)} N(x)代表语料库中包含词 x {x} x的文本总数。但是这个公式在一些特殊情况下会有一些小问题,比如生僻词在语料库中没有,这样分母就为 0 {0} 0了,肯定不行吧。所以常常需要做一些平滑处理,使语料库中没有出现的词也可以得到一个合适的 I D F {IDF} IDF值。平滑的方法由很多种。这里我介绍在 s k l e a r n . f e a t u r e e x t r a c t i o n . t e x t {sklearn.feature_extraction.text} sklearn.featureextraction.text T f i d f V e c t o r i z e r {TfidfVectorizer} TfidfVectorizer T f i d f T r a n s f o r m e r {TfidfTransformer} TfidfTransformer类中用到的 I D F {IDF} IDF计算方法。
使用 T f i d f T r a n s f o r m e r {TfidfTransformer} TfidfTransformer的默认参数的话,即:

TfidfTransformer(norm='l2', use_idf=True, smooth_idf=True, sublinear_tf=False)

词频 t f {tf} tf用在了 i d f {idf} idf的计算公式中,如下:
i d f ( t ) = l o g 1 + n d 1 + d f ( d , t ) + 1 {idf(t)=log\frac{1+n_d}{1+{df(d,t)}}+1} idf(t)=log1+df(d,t)1+nd+1,(注意:参数smooth_idf=True
其中, n d {n_d} nd表示文档总数量, df ( d , t ) {\text{df}(d,t) } df(d,t)表示包含词 t {t} t的文档数量。再经过 tf-idf(t,d) = tf(t,d) × idf(t) {\text{tf-idf(t,d)}=\text{tf(t,d)} \times \text{idf(t)}} tf-idf(t,d)=tf(t,d)×idf(t),计算出来的结果 t f − i d f {tf-idf} tfidf向量还要做欧几里得范数( t h e E u c l i d e a n n o r m {the Euclidean norm} theEuclideannorm)的标准化处理,即: v n o r m = v ∣ ∣ v ∣ ∣ 2 = v v 1 2 + v 2 2 + ⋯ + v n 2 {v_{norm} = \frac{v}{||v||_2} = \frac{v}{\sqrt{v{_1}^2 + v{_2}^2 + \dots + v{_n}^2}}} vnorm=v2v=v12+v22++vn2 v
当参数smooth_idf=False时, i d f {idf} idf的计算公式为:
idf ( t ) = l o g n d df ( d , t ) + 1 {\text{idf}(t) = log{\frac{n_d}{\text{df}(d,t)}} + 1} idf(t)=logdf(d,t)nd+1。写到这儿可能读者有点晕了,下面我们重新整理一下思路。

3 使用scikit-learn进行TF-IDF预处理

s c i k i t − l e a r n {scikit-learn} scikitlearn中,有两种方法进行 T F − I D F {TF-IDF} TFIDF的预处理。

  • 第一种:在用 C o u n V e c t o r i z e r {CounVectorizer} CounVectorizer类向量化之后,调用 T f i d f T r a n s f o r m e r {TfidfTransformer} TfidfTransformer类进行预处理。
  • 第二种:直接调用 T f i d f V e c t o r i z e r {TfidfVectorizer} TfidfVectorizer完成向量化和 T F − I D F {TF-IDF} TFIDF的预处理。

第一种: C o u n V e c t o r i z e r {CounVectorizer} CounVectorizer+ T f i d f T r a n s f o r m e r {TfidfTransformer} TfidfTransformer的组合

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

corpus = [
    'This is the first document.',
    'This is the second second document.',
    'And the third one.',
    'Is this the first document?',
]

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

输出各个文本各个词的TF-IDF值如下:

  (0, 8)	0.4387767428592343
  (0, 6)	0.35872873824808993
  (0, 3)	0.4387767428592343
  (0, 2)	0.5419765697264572
  (0, 1)	0.4387767428592343
  (1, 8)	0.2723014675233404
  (1, 6)	0.22262429232510395
  (1, 5)	0.8532257361452786
  (1, 3)	0.2723014675233404
  (1, 1)	0.2723014675233404
  (2, 7)	0.5528053199908667
  (2, 6)	0.2884767487500274
  (2, 4)	0.5528053199908667
  (2, 0)	0.5528053199908667
  (3, 8)	0.4387767428592343
  (3, 6)	0.35872873824808993
  (3, 3)	0.4387767428592343
  (3, 2)	0.5419765697264572
  (3, 1)	0.4387767428592343

第二种:直接调用 T f i d f V e c t o r i z e r {TfidfVectorizer} TfidfVectorizer

from sklearn.feature_extraction.text import TfidfVectorizer
tfidf2 = TfidfVectorizer()
print(tfidf2.fit_transform(corpus))

输出的各个文本各个词的TF-IDF值和第一种方法的输出完全相同:

  (0, 8)	0.4387767428592343
  (0, 3)	0.4387767428592343
  (0, 6)	0.35872873824808993
  (0, 2)	0.5419765697264572
  (0, 1)	0.4387767428592343
  (1, 8)	0.27230146752334033
  (1, 3)	0.27230146752334033
  (1, 6)	0.2226242923251039
  (1, 1)	0.27230146752334033
  (1, 5)	0.8532257361452784
  (2, 6)	0.2884767487500274
  (2, 0)	0.5528053199908667
  (2, 7)	0.5528053199908667
  (2, 4)	0.5528053199908667
  (3, 8)	0.4387767428592343
  (3, 3)	0.4387767428592343
  (3, 6)	0.35872873824808993
  (3, 2)	0.5419765697264572
  (3, 1)	0.4387767428592343

第二种方法简洁,一步到位完成向量化,TF-IDF与标准化,推荐使用。

小结

TF-IDF是非常常用的文本预处理基本步骤,但是如果预处理中使用了Hash Trick,一般就无法使用TF-IDF了,因为Hash Trick后我们无法得到哈希后的各特征的IDF值。使用TF-IDF并标准化后,我们就可以使用各个文本的词特征向量作为文本的特征,进行分类或者聚类分析了。

==========================================

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值