1. 程式人生 > >使用TextRank生成文字摘要

使用TextRank生成文字摘要

開發十年,就只剩下這套架構體系了! >>>   

因為專案內容中涉及自動生成文字摘要的功能,因此學習了一下TextRank演算法實現摘要提取。

1.介紹一下TextRank演算法
TextRank演算法的思想是,擬定一個通用的評分標準,給文字中的每一個句子打分,所得分數就是該句子的權重,最後得到權重排名靠前的幾個句子,構成最終的文字摘要。這就是所謂的TextRank自動生成摘要。

TextRank對每一個句子的打分思想由PageRank的迭代思想衍生而來,公式如下:

在這個公式中,WS(i)表示第i個句子的權重,右側的求和表示的是每一個句子對所在文字的貢獻程度。求和部分的分子wji表示兩個句子j和i的相似程度,分母則是文字中相對應的部分的句子的權重之和,WS(Vj)表示上次迭代j的權重。

從整個公式可以看出這是一個反覆迭代的過程。

由於wji需要計算兩個句子的相似程度,因此這裡我們需要引入另外的相似度演算法,通常推薦使用BM25,這是目前已知的計算結果較為準確的演算法之一。

這個公式中的d是一個常數,稱為阻尼係數,通常在演算法中我們取其值為0.85,當然也可以根據實際的情況進行調整。

2.TextRank演算法的Java實現
2.1首先需要宣告相關的變數
/**
 * 阻尼係數(DampingFactor),一般取值為0.85
 */
final double d = 0.85f;
/**
 * 最大迭代次數
 */
final int max_iter = 200;
final double min_diff = 0.001f;
/**
 * 文件句子的個數
 */
int D;
/**
 * 拆分為[句子[單詞]]形式的文件
 */
List<List<String>> docs;
/**
 * 排序後的最終結果 score <-> index
 */
TreeMap<Double, Integer> top;

/**
 * 句子和其他句子的相關程度
 */
double[][] weight;
/**
 * 該句子和其他句子相關程度之和
 */
double[] weight_sum;
/**
 * 迭代之後收斂的權重
 */
double[] vertex;

/**
 * BM25相似度
 */
BM25 bm25;


2.2 實現文字切割成句子
List<String> sentences = new ArrayList<String>();
if (document == null) return sentences;
for (String line : document.split("[\r\n]"))
{
    line = line.trim();//去掉字串的首尾空格
    if (line.length() == 0) continue;
    for (String sent : line.split("[,,.。::“”??!!;;]"))
    {
        sent = sent.trim();
        if (sent.length() == 0) continue;
        sentences.add(sent);
    }
}

2.3 使用開源jar包對中文文字進行分詞,並獲得分詞結果
List<String> sentenceList = spiltSentence(document);//用,。”“等標點將文字切割成了短句
List<List<String>> docs = new ArrayList<List<String>>();
for (String sentence : sentenceList)
{
    List<Term> termList = ToAnalysis.parse(sentence);//使用開源的ansj對句子進行分詞
    List<String> wordList = new LinkedList<String>();
    for (Term term : termList)
    {
        if (shouldInclude(term))
        {
            wordList.add(term.getRealName());
        }
    }
    docs.add(wordList);
}
TextRankSummary textRankSummary = new TextRankSummary(docs);
int[] topSentence = textRankSummary.getTopSentence(size);
List<String> resultList = new LinkedList<String>();
for (int i : topSentence)
{
    resultList.add(sentenceList.get(i));
}
return resultList;

2.4 運用公式計算出每個句子的權重並進行排序
int cnt = 0;
for (List<String> sentence : docs)
{

    double[] scores = bm25.simAll(sentence);//計算相似度
    System.out.println(Arrays.toString(scores));
    weight[cnt] = scores;
    weight_sum[cnt] = sum(scores) - scores[cnt]; // 減掉自己,自己跟自己肯定最相似
    vertex[cnt] = 1.0;
    ++cnt;
}
for (int _ = 0; _ < max_iter; ++_)
{
    double[] m = new double[D];
    double max_diff = 0;
    for (int i = 0; i < D; ++i)
    {
        m[i] = 1 - d;
        for (int j = 0; j < D; ++j)
        {
            if (j == i || weight_sum[j] == 0) continue;
            m[i] += (d * weight[j][i] / weight_sum[j] * vertex[j]);
        }
        double diff = Math.abs(m[i] - vertex[i]);
        if (diff > max_diff)
        {
            max_diff = diff;
        }
    }
    vertex = m;
    if (max_diff <= min_diff) break;
}
//
for (int i = 0; i < D; ++i)
{
    top.put(vertex[i], i);
}

2.5 設定想要獲取的目標摘要長度,並根據排序結果取出摘要
Collection<Integer> values = top.values();
size = Math.min(size, values.size());
int[] indexArray = new int[size];
Iterator<Integer> it = values.iterator();
for (int i = 0; i < size; ++i)
{
    indexArray[i] = it.next();
}
return indexArray;

以上就是對TextRank演算法的學習內容的概括。


--------------------- 
作者:GY_Grace 
來源:CSDN 
原文:https://blog.csdn.net/GY_Grace/article/details/72863632 
版權宣告:本文為博主原創文章,轉載請