TF-IWF
1、背景
在上篇特征加权之TFIDF 中,我们提到了IDF的固有缺点,即\(IDF\) 的简单结构并不能使提取的关键词,十分有效地反映单词的重要程度和特征词的分布情况,使其无法很好地完成对权值调整的功能。尤其是在同类语料库中,这一方法有很大弊端,往往一些同类文本的关键词被掩盖。例如:语料库 \(D\) 中教育类文章偏多,而文本 \(j \)是一篇属于教育类的文章,那么教育类相关的词语的\( IDF \)值将会偏小,使提取文本关键词的召回率更低。因此我们在此提出词语逆频率方式计算加权算法 \(TF-IWF\) (Term Frequency-Inverse Word Frequency)。
2、TF-IWF
此处的\(TF\)与\(TF-IDF\)中意义一样,表示词频:
\[
tf_{ij} = \frac{n_{i,j}}{\sum_{k}n_{k,j}}
\]
上式中分子\( n_{i,j}\) 表示词语\(t_i\)在文本\(j\)中的频数,分母\(\sum_{k}n_{k,j}\)表示文档\(j\)中所有词汇量总和,即是说:
\[
TF_w = \frac{给定词w在当前文章出现的次数}{当前文章中的总词量}
\]
不同之处在于\(IWF\)部分,定义为:
\[
iwf_{i} = log\frac{\sum_{i=1}^m nt_{i}}{nt_{i}}
\]
上式中分子 \(\sum_{i=1}^m nt_{i}\) 表示语料库中所有词语的频数之和,分母 \(nt_{i}\) 表示词语 \(t_{i}\) 在语料库中的总频数,即:
\[
IWF_{i}=\frac{语料库中所有词语的频数}{给定词w在语料库中出现的频数和}
\]
因此,\(TF-IWF\) 定义为:
\[
TF-IWF_{i,j}\rightarrow tf_{i,j} \times iwf_{i}=\frac{n_{i,j}}{\sum_{k}n_{k,j}}\times log\frac{\sum_{i=1}^m nt_{i}}{nt_{i}}
\]
3、代码实现
这里我用python简单实现一下该算法
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019/11/3 12:31
# @Author : mokundong
import math
import numpy as np
class TF_IWF:
'''
tf-iwf 算法
'''
def __init__(self, lines):
self.iwf = dict()
self.median_iwf = 0
self.__build_iwf(lines)
def __get_tf(self, strs):
tf_dict = {}
line_words = strs.split(" ")
total_word_line = len(line_words)
for word in line_words:
if word not in tf_dict:
tf_dict[word] = 1
else:
tf_dict[word] = tf_dict[word] + 1
for k, v in tf_dict.items():
tf_dict[k] = v / total_word_line
return tf_dict
def __build_iwf(self, lines):
for line in lines:
line_words = line.split(" ")
for word in line_words:
if word not in self.iwf:
self.iwf[word] = 1
else:
self.iwf[word] = self.iwf[word] + 1
total_word_lines = len(self.iwf.values())
values = []
for k, v in self.iwf.items():
self.iwf[k] = math.log(total_word_lines / v, 10)
values.append(math.log(total_word_lines / v, 10))
self.median_iwf = np.median(values)
def get_tfiwf(self, strs):
result = dict()
tf_dict = self.__get_tf(strs)
line_words = strs.split(" ")
for word in line_words:
if word not in self.iwf.keys():
result[word] = tf_dict[word] * self.median_iwf
else:
result[word] = tf_dict[word] * self.iwf[word]
return result
if __name__ == "__main__":
lines = [
'这是 第一 篇 文章 ',
'这 篇 文章 是 第二 篇 文章 ',
'这是 第三 篇 文章 '
]
line = '这是 第几 篇 文章'
tfiwf = TF_IWF(lines)
result = tfiwf.get_tfiwf(line)
print(result)
从结果我们可以看到这句话的关键词是“第几”,也符合句话的预期,而在上篇我们用TF-IDF算法中同样的训练预料得到的结果却不尽人意。
4、总结
这种加权方法降低了语料库中同类型文本对词语权重的影响,更加精确地表达了这个词语在待 查文档中的重要程度。在传统方法 \(TF-IDF\) 所求的权值一般很小接近 \(0\),精确度也不是很高,公式 \(TF-IWF\) 的计算结果刚好能解决最后权值过小的问题。