基于TextRank的中文摘要抽取算法(一)

BM25 is a bag-of-words retrieval function that ranks a set of documents based on the query terms appearing in each document, regardless of the inter-relationship between the query terms within a document (e.g., their relative proximity). It is not a single function, but actually a whole family of scoring functions, with slightly different components and parameters. One of the most prominent instantiations of the function is as follows.

BM25算法,通常用来作搜索相关性平分。一句话概况其主要思想:对Query进行语素解析,生成语素qi;然后,对于每个搜索结果D,计算每个语素qi与D的相关性得分,最后,将qi相对于D的相关性得分进行加权求和,从而得到Query与D的相关性得分。

BM25算法的一般性公式如下:


其中,Q表示Query,qi表示Q解析之后的一个语素(对中文而言,我们可以把对Query的分词作为语素分析,每个词看成语素qi。);d表示一个搜索结果文档;Wi表示语素qi的权重;R(qi,d)表示语素qi与文档d的相关性得分。

下面我们来看如何定义Wi。判断一个词与一个文档的相关性的权重,方法有多种,较常用的是IDF。这里以IDF为例,公式如下:


其中,N为索引中的全部文档数,n(qi)为包含了qi的文档数。

根据IDF的定义可以看出,对于给定的文档集合,包含了qi的文档数越多,qi的权重则越低。也就是说,当很多文档都包含了qi时,qi的区分度就不高,因此使用qi来判断相关性时的重要度就较低。

我们再来看语素qi与文档d的相关性得分R(qi,d)。首先来看BM25中相关性得分的一般形式:



其中,k1,k2,b为调节因子,通常根据经验设置,一般k1=2,b=0.75;fi为qi在d中的出现频率,qfi为qi在Query中的出现频率。dl为文档d的长度,avgdl为所有文档的平均长度。由于绝大部分情况下,qi在Query中只会出现一次,即qfi=1,因此公式可以简化为:


从K的定义中可以看到,参数b的作用是调整文档长度对相关性影响的大小。b越大,文档长度的对相关性得分的影响越大,反之越小。而文档的相对长度越长,K值将越大,则相关性得分会越小。这可以理解为,当文档较长时,包含qi的机会越大,因此,同等fi的情况下,长文档与qi的相关性应该比短文档与qi的相关性弱。

综上,BM25算法的相关性得分公式可总结为:


从BM25的公式可以看到,通过使用不同的语素分析方法、语素权重判定方法,以及语素与文档的相关性判定方法,我们可以衍生出不同的搜索相关性得分计算方法,这就为我们设计算法提供了较大的灵活性。

基于此算法算例与应用场景,可以用来在文本摘要应用进行语素与句子的相似度。在一篇document当中,该document看成是一个sentences的集合,而中文文本摘要本质上是按文本中对句子的重要性权值进行排名,取权值最高的若干句子作为文章的摘要句子,按原文的语句排列顺序输出,输出的结果即为文章的摘要内容。目前有许多算法可以用来进行中文摘要的抽取,这里先介绍基于TextRank打分思想的中文摘要抽取算法:

TextRank的打分思想依然是从PageRank的迭代思想衍生过来的,如下公式所示:

基于TextRank的中文摘要抽取算法(一)_第1张图片

等式左边表示一个句子的权重(WS是weight_sum的缩写),右侧的求和表示每个相邻句子对本句子的贡献程度。与提取关键字的时候不同,一般认为全部句子都是相邻的,不再提取窗口。

求和的分母Wji表示两个句子的相似程度,分母又是一个weight_sum,而WS(Vj)代表上次迭代j的权重。整个公式是一个迭代的过程。相似程度Wji的计算,推荐使用BM25算法。BM25算法,通常用来作搜索相关性平分。一句话概况其主要思想:对Query进行语素解析,生成语素qi;然后,对于每个搜索结果D,计算每个语素qi与D的相关性得分,最后,将qi相对于D的相关性得分进行加权求和,从而得到Query与D的相关性得分。相关代码实现:

 //bm25算法:计算两个句子之间的相关性,对当前语句进行打分
    public double sim(List<String> sentence, int index)
    {
        double score = 0;
        for (String word : sentence)
        {
            if (!f[index].containsKey(word)) continue;    //不是共有的词,则看成对句子之间的相似度没有任何贡献,直接过滤掉
            int d = docs.get(index).size();   //该句子的长度
            Integer wf = f[index].get(word);     //获取word在该句子中的词频
            score += (idf.get(word) * wf * (k1 + 1) / (wf + k1 * (1 - b + b * d / avgdl)));
        }


        return score;
    }

    //用于计算当前语句与文本中所有语句的相似性,从而求得该语句的分数
    public double[] simAll(List<String> sentence)
    {
        double[] scores = new double[D];
        for (int i = 0; i < D; ++i)
        {
            scores[i] = sim(sentence, i);   //句子与其他句子都看成是相邻的
        }
        return scores;
    }




你可能感兴趣的:(基于TextRank的中文摘要抽取算法(一))