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\) 的计算结果刚好能解决最后权值过小的问题。

posted @ 2020-01-15 14:59  peacocks  阅读(2500)  评论(0编辑  收藏  举报