TextRank算法及用途

TextRank详细资料可以参考:http://www.hankcs.com/nlp/textrank-algorithm-to-extract-the-keywords-java-implementation.html


TextRank是在Google的PageRank算法启发下,针对文本里的句子设计的权重算法,目标是自动摘要。

它利用投票的原理,让每一个单词给它的邻居(术语称窗口)投赞成票,票的权重取决于自己的票数。

这是一个“先有鸡还是先有蛋”的悖论,PageRank采用矩阵迭代收敛的方式解决了这个悖论


TextRank算法,首先会对提供的句子进行分词操作,得到的分词放入到一个集合中,分词的重要程度,主要看这个分词的前后邻居有多少,邻居越多,给它投票的分词就越多,权值越高,也就越重要,

当这个分词出现的持续越多,它的邻居也越多;这个分词越在中间(相比开头和结尾),它的邻居也越多;


用途:

1.提取出文本中比较重要的关键词

2.选出一段话中,哪个关键词出现的次数多的问题

import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.dictionary.stopword.CoreStopWordDictionary;
import com.hankcs.hanlp.seg.common.Term;

import java.util.*;

/**
 * TextRank关键词提取
 * 
 * @author hankcs
 */
public class TextRankKeyword {
	/**
	 * 阻尼系数(DampingFactor),一般取值为0.85
	 */
	static final float d = 0.85f;
	/**
	 * 最大迭代次数
	 */
	static final int max_iter = 200;
	static final float min_diff = 0.001f;

	public TextRankKeyword() {
		System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
	}

	public List<Textbean> getKeyword(String title, String content) {
		//使用的HanLP分词算法
		List<Term> termList = HanLP.segment(title + content);
		//分完的词,放到list集合中
		List<String> wordList = new ArrayList<String>();
		for (Term t : termList) {
			if (shouldInclude(t)) {
				wordList.add(t.word);
			}
		}
		
		Map<String, Set<String>> words = new HashMap<String, Set<String>>();
		//list集合是按照存放的顺序排序的,对任何一个分词在所在的位置的前后5个词都作为该词的邻居
		Queue<String> que = new LinkedList<String>();
		for (String w : wordList) {
			if (!words.containsKey(w)) {
				words.put(w, new HashSet<String>());
			}
			que.offer(w);
			if (que.size() > 5) {
				que.poll();
			}

			for (String w1 : que) {
				for (String w2 : que) {
					if (w1.equals(w2)) {
						continue;
					}

					words.get(w1).add(w2);
					words.get(w2).add(w1);
				}
			}
		}
		
		Map<String, Float> score = new HashMap<String, Float>();
		//最多的遍历次数为200
		for (int i = 0; i < max_iter; ++i) {
			Map<String, Float> m = new HashMap<String, Float>();
			float max_diff = 0;
			for (Map.Entry<String, Set<String>> entry : words.entrySet()) {
				String key = entry.getKey();
				Set<String> value = entry.getValue();
				m.put(key, 1 - d);
				for (String other : value) {
					int size = words.get(other).size();
					if (key.equals(other) || size == 0)
						continue;
					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)
				break;
		}
		List<Map.Entry<String, Float>> entryList = new ArrayList<Map.Entry<String, Float>>(
				score.entrySet());
		//对分完的词按大小进行排序
		Collections.sort(entryList, new Comparator<Map.Entry<String, Float>>() {
			@Override
			public int compare(Map.Entry<String, Float> o1,
					Map.Entry<String, Float> o2) {
				return (o1.getValue() - o2.getValue() > 0 ? -1 : 1);
			}
		});
		List<Textbean> TextbeanList = new ArrayList<Textbean>();
		
		for (int i = 0; i < entryList.size(); ++i) {
			Textbean textbean = new Textbean();
			textbean.setName(entryList.get(i).getKey());
			textbean.setNum(entryList.get(i).getValue().toString());
			TextbeanList.add(textbean);
		}
		System.out.println("原值:" + entryList);
		return TextbeanList;
	}

	public static void main(String[] args) {
		String content = "程序员(英文Programmer)是从事程序开发、维护的专业人员。一般将程序员分为程序设计人员和程序编码人员,但两者的界限并不非常清楚,特别是在中国。软件从业人员分为初级程序员、高级程序员、系统分析员和项目经理四大类";
		System.out.println(new TextRankKeyword().getKeyword("", content));

	}

	/**
	 * 是否应当将这个term纳入计算,词性属于名词、动词、副词、形容词
	 * 
	 * @param term
	 * @return 是否应当
	 */
	public boolean shouldInclude(Term term) {
		return CoreStopWordDictionary.shouldInclude(term);
	}
}

如有不恰当之处,请指教

你可能感兴趣的:(自动摘要,textrank,自动提取重要词语,提取关键词)