使用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首先需要宣告相關的變數
/**
* 阻尼係數(DampingFactor),一般取值為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
版權宣告:本文為博主原創文章,轉載請