基于TextRank获取关键词中心性

TextRank算法是从Google的PageRank算法发展而来,主要用于文本摘要和关键词提取。它通过构建单词间的共现关系图,并进行迭代权重传播来确定关键词的重要性。在给定的Java实现中,首先进行分词和停用词过滤,然后建立关键词的共现网络,最后通过迭代更新关键词的权重并选择排名最高的关键词作为结果。该算法在信息技术领域可用于高效地提取文本关键信息。
摘要由CSDN通过智能技术生成

一、textRank算法

TextRank是在Google的PageRank算法启发下,针对文本里的句子设计的权重算法,目标是自动摘要。它利用投票的原理,让每一个单词给它的邻居(术语称窗口)投赞成票,票的权重取决于自己的票数。这是一个“先有鸡还是先有蛋”的悖论,PageRank采用矩阵迭代收敛的 方式解决了这个悖论,TextRank也不例外!

 1、正规的TextRank公式


正规的TextRank公式在PageRank的公式的基础上,引入了边的权值的概念,代表两个句子的相似度,但是很明显,如果只想计算关键字,就把一个单词视为一个句子,那么所有句子(单词)构成的边的权重都是0(没有交集,没有相似性),所以分子分母的权值w约掉得了,算法退化为PageRank。

在这里算是简单说明了TextRank的内在原理,以下对其关键词提取应用做进一步说明。

2、 关键词提取算法
TextRank用于关键词提取的算法如下:

①把给定的文本T按照完整句子进行分割,即
②对于每个句子Si属于T,进行分词和词性标注处理,并过滤掉停用词,只保留指定词性的单词,如名词、动词、形容词,即
其中 ti,j 是保留后的候选关键词。

③构建候选关键词图G = (V,E),其中V为节点集,由(2)生成的候选关键词组成,然后采用共现关系(co-occurrence)构造任两点之间的边,两个节点之间存在边仅当它们对应的词汇在长度为K的窗口中共现,K表示窗口大小,即最多共现K个单词。
④根据上面公式,迭代传播各节点的权重,直至收敛。
⑤对节点权重进行倒序排序,从而得到最重要的T个单词,作为候选关键词。
⑥由⑤得到最重要的T个单词,在原始文本中进行标记,若形成相邻词组,则组合成多词关键词。
 

二、实现

1、keyword.class

package com.example.demo.util.keyWordUtil;


import org.ansj.domain.Result;
import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;

import java.io.IOException;
import java.util.*;

/**
 * @author summer
 * @date 2020/07/30
 */
public class KeyWord {

    private static float min_diff = 0.001f; //差值最小
    private static int max_iter = 200;//最大迭代次数
    private static int k = 2;  //窗口大小/2
    private static float d = 0.85f;

    public List<String> textRank(String field, int keywordNum) throws IOException {
        //分词
        List<WOD<String>> wods = ToAnalysisParse(field);
//        System.out.println(wods);
         wods=StopWord.filter(wods);//过滤掉不需要的分词,可省略

        Map<String, Set<String>> relationWords = new HashMap<>();
        //获取每个关键词 前后k个的组合
        for (int i = 0; i < wods.size(); i++) {
            String keyword = wods.get(i).getName();
            Set<String> keySets = relationWords.get(keyword);
            if (keySets == null) {
                keySets = new HashSet<>();
                relationWords.put(keyword, keySets);
            }

            for (int j = i - k; j <= i + k; j++) {
                if (j < 0 || j >= wods.size() || j == i) {
                    continue;
                } else {
                    keySets.add(wods.get(j).getName());
                }
            }
        }

        Map<String, Float> score = new HashMap<>();
        //迭代
        for (int i = 0; i < max_iter; i++) {
            Map<String, Float> m = new HashMap<>();
            float max_diff = 0;
            for (String key : relationWords.keySet()) {
                Set<String> value = relationWords.get(key);
                //先给每个关键词一个默认rank值
                m.put(key, 1 - d);
                //一个关键词的TextRank由其它成员投票出来
                for (String other : value) {
                    int size = relationWords.get(other).size();
                    if (key.equals(other) || size == 0) {
                        continue;
                    } else {
                        m.put(key, m.get(key) + d / size * (score.get(other) == null ? 0 : score.get(other)));
                    }
                }
                max_diff = Math.max(max_diff, Math.abs(m.get(key) - (score.get(key) == null ? 0 : score.get(key))));
            }
            score = m;
            if (max_diff <= min_diff) {
//                System.out.println("迭代次数:" + i);
                break;
            }
        }
        List<WOD<String>> scores = new ArrayList<>();
        for (String s : score.keySet()) {
            WOD<String> score1 = new WOD(s, score.get(s));
            scores.add(score1);
        }

        scores.sort(new Comparator<WOD<String>>() {
            @Override
            public int compare(WOD<String> o1, WOD<String> o2) {
                return o1.compareTo(o2);
            }
        });
        System.out.println(scores);
        List<String> keywords = new ArrayList<>();
        int index = 0;
        for (WOD<String> score1 : scores) {
            keywords.add(score1.getName());
            index++;
            if (index==keywordNum)
                break;
        }
        return keywords;
    }

    public static List<WOD<String>> ToAnalysisParse(String str) {
        List<WOD<String>> wods = new ArrayList();
        Result terms =ToAnalysis.parse(str);
        Iterator var4 = terms.iterator();

        while(var4.hasNext()) {
            Term term = (Term)var4.next();
            wods.add(new WOD(term.getName(), term.getNatureStr()));
        }

        return wods;
    }
}

2、stopwords.class添加停用词

public class StopWord {
    public static List<WOD<String>> filter(List<WOD<String>> termList) throws IOException {
        String filePath="src/main/resources/stopword.dict";
        File file=new File(filePath);

        BufferedReader bufferedReader=new BufferedReader(new FileReader(file));
        List<WOD<String>> stopwords=new ArrayList<>();
        String temp=null;
        while((temp=bufferedReader.readLine())!=null){
            stopwords.add(new WOD<String>(temp.trim()));
        }
        List<WOD<String>> termStringList=new ArrayList<>();
        for (WOD<String> wod:termList) {
            termStringList.add(wod);
        }
        termStringList.removeAll(stopwords);
        return termStringList;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值