看一个博主(亚当-adam)的关于hanlp关键词提取算法TextRank的文章,还是非常好的一篇实操经验分享,分享一下给各位需要的朋友一起学习一下!
TextRank是在Google的PageRank算法启发下,针对文本里的句子设计的权重算法,目标是自动摘要。它利用投票的原理,让每一个单词给它的邻居(术语称窗口)投赞成票,票的权重取决于自己的票数。这是一个“先有鸡还是先有蛋”的悖论,PageRank采用矩阵迭代收敛的方式解决了这个悖论。本博文通过hanlp关键词提取的一个Demo,并通过图解的方式来讲解TextRank的算法。
1//长句子
2 String content = "程序员(英文Programmer)是从事程序开发、维护的专业人员。" +
3 "一般将程序员分为程序设计人员和程序编码人员," +
4 "但两者的界限并不非常清楚,特别是在中国。" +
5 "软件从业人员分为初级程序员、高级程序员、系统" +
6 "分析员和项目经理四大类。";
最后提取的关键词是:[程序员, 程序, 分为, 人员, 软件]
下面来分析为什么会提取出这5个关键词
第一步:分词
把content 通过一个的分词算法进行分词,这里采用的是Viterbi算法也就是HMM算法。分词后(当然首先应把停用词、标点、副词之类的去除)的结果是:
[程序员, 英文, Programmer, 从事, 程序, 开发, 维护, 专业, 人员, 程序员, 分为, 程序, 设计, 人员, 程序, 编码, 人员, 界限, 并不, 非常, 清楚, 特别是在, 中国, 软件, 从业人员, 分为, 程序员, 高级, 程序员, 系统分析员, 项目经理, 四大]
第二步:构造窗口
hanlp的实现代码如下:
Map<String, Set<String>> words = new TreeMap<String, Set<String>>();
Queue<String> que = new LinkedList<String>();
for (String w : wordList)
{
if (!words.containsKey(w))
{
words.put(w, new TreeSet<String>());
}
// 复杂度O(n-1)
if (que.size() >= 5)
{
que.poll();
}
for (String qWord : que)
{
if (w.equals(qWord))
{
continue;
}
//既然是邻居,那么关系是相互的,遍历一遍即可
words.get(w).add(qWord);
words.get(qWord).add(w);
}
que.offer(w);
}
这个代码的功能是为分个词构造窗口,这个词前后各四个词就是这个词的窗口,如词分词后一个词出现了多次,像[程序员],那就是把每次出现取一次窗口,然后把各次结果合并去重,最后结果是:程序员=[Programmer, 专业, 中国, 人员, 从业人员, 从事, 分为, 四大, 开发, 程序, 系统分析员, 维护, 英文, 设计, 软件, 项目经理, 高级]。最后形成的窗口:
1 Map<String, Set<String>> words =
2
3 {Programmer=[从事, 开发, 程序, 程序员, 维护, 英文], 专业=[人员, 从事, 分为, 开发, 程序, 程序员, 维护], 中国=[从业人员, 分为, 并不, 清楚, 特别是在, 程序员, 软件, 非常], 人员=[专业, 分为, 并不, 开发, 清楚, 界限, 程序, 程序员, 维护, 编码, 设计, 非常], 从业人员=[中国, 分为, 清楚, 特别是在, 程序员, 软件, 高级], 从事=[Programmer, 专业, 开发, 程序, 程序员, 维护, 英文], 分为=[专业, 中国, 人员, 从业人员, 特别是在, 程序, 程序员, 系统分析员, 维护, 设计, 软件, 高级], 四大=[程序员, 系统分析员, 项目经理, 高级], 并不=[中国, 人员, 清楚, 特别是在, 界限, 程序, 编码, 非常], 开发=[Programmer, 专业, 人员, 从事, 程序, 程序员, 维护, 英文], 清楚=[中国, 人员, 从业人员, 并不, 特别是在, 界限, 软件, 非常], 特别是在=[中国, 从业人员, 分为, 并不, 清楚, 界限, 软件, 非常], 界限=[人员, 并不, 清楚, 特别是在, 程序, 编码, 非常], 程序=[Programmer, 专业, 人员, 从事, 分为, 并不, 开发, 界限, 程序员, 维护, 编码, 英文, 设计], 程序员=[Programmer, 专业, 中国, 人员, 从业人员, 从事, 分为, 四大, 开发, 程序, 系统分析员, 维护, 英文, 设计, 软件, 项目经理, 高级], 系统分析员=[分为, 四大, 程序员, 项目经理, 高级], 维护=[Programmer, 专业, 人员, 从事, 分为, 开发, 程序, 程序员], 编码=[人员, 并不, 界限, 程序, 设计, 非常], 英文=[Programmer, 从事, 开发, 程序, 程序员], 设计=[人员, 分为, 程序, 程序员, 编码], 软件=[中国, 从业人员, 分为, 清楚, 特别是在, 程序员, 非常, 高级], 非常=[中国, 人员, 并不, 清楚, 特别是在, 界限, 编码, 软件], 项目经理=[四大, 程序员, 系统分析员, 高级], 高级=[从业人员, 分为, 四大, 程序员, 系统分析员, 软件, 项目经理]}
第三步:迭代投票
每个词最后的投票得分由这个词的窗口进行多次迭代投票决定,迭代的结束条件就是大于最大迭代次数这里是200次,或者两轮之前某个词的权重小于某一值这里是0.001f。看下代码:
Map<String, Float> score = new HashMap<String, Float>();
//依据TF来设置初值
for (Map.Entry<String, Set<String>> entry : words.entrySet()){
score.put(entry.getKey(),sigMoid(entry.getValue().size()));
}
System.out.println(score);
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 element : value)
{
int size = words.get(element).size();
if (key.equals(element) || size == 0) continue;
m.put(key, m.get(key) + d / size * (score.get(element) == null ? 0 : score.get(element)));
}
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;
}
System.out.println(score);
return score;
}
投票的原理拿Programmer=[从事, 开发, 程序, 程序员, 维护, 英文],这个词来说明,Programmer最后的得分是由[从事, 开发, 程序, 程序员, 维护, 英文],这6个词依次投票决定的,每个词投出去的分数是和他本身的权重相关的。
1、投票开始前每个词初始化了一个权重,score.put(entry.getKey(),sigMoid(entry.getValue().size())),这个权重是0到1之间,公式是
1 //value是每个词窗口的大小
2 public static float sigMoid(float value) {
3 return (float)(1d/(1d+Math.exp(-value)));
4 }
这个函数的公式和图像如下,因为value一定是大于0的,所以sigMod值属于(0,1)
初始化后的分词是:{特别是在=0.99966466, 程序员=0.99999994, 编码=0.99752736, 四大=0.98201376, 英文=0.9933072, 非常=0.99966466, 界限=0.99908894, 系统分析员=0.9933072, 从业人员=0.99908894, 程序=0.99999774, 专业=0.99908894, 项目经理=0.98201376, 设计=0.9933072, 从事=0.99908894, Programmer=0.99752736, 软件=0.99966466, 人员=0.99999386, 清楚=0.99966466, 中国=0.99966466, 开发=0.99966466, 并不=0.99966466, 高级=0.99908894, 分为=0.99999386, 维护=0.99966466}
进行迭代投票,第一轮投票,[Programmer, 专业, 中国, 人员, 从业人员, 从事, 分为, 四大, 开发, 程序, 系统分析员, 维护, 英文, 设计, 软件, 项目经理, 高级]依给次*程序员*投票,得分如下:
[Programmer]给[程序员]投票后,[]程序员]的得分:
[专业]给[程序员]投票
这样[Programmer, 专业, 中国, 人员, 从业人员, 从事, 分为, 四大, 开发, 程序, 系统分析员, 维护, 英文, 设计, 软件, 项目经理, 高级]依次给[程序员]投票,投完票后,再给其它的词进行投票,本轮结束后,判断是否达到最大迭代次数200或两轮之间分数差值小于0.001,如果满足则结束,否则继续进行迭代。
最后的投票得分是:{特别是在=1.0015739, 程序员=2.0620303, 编码=0.78676623, 四大=0.6312981, 英文=0.6835063, 非常=1.0018439, 界限=0.88890904, 系统分析员=0.74232763, 从业人员=0.8993066, 程序=1.554001, 专业=0.88107216, 项目经理=0.6312981, 设计=0.6702926, 从事=0.9027207, Programmer=0.7930236, 软件=1.0078223, 人员=1.4288887, 清楚=0.9998723, 中国=0.99726284, 开发=1.0065585, 并不=0.9968608, 高级=0.9673803, 分为=1.4548829, 维护=0.9946941},分数最高的关键词就是要提取的关键词
相关推荐
6、算法应用实践:通过实际案例介绍机器学习算法在各个领域的应用,如图像识别、自然语言处理、推荐系统和语音识别等。 7、模型评估与优化:讲解如何评估机器学习模型的性能并进行优化,包括常用的评估指标和调参...
算法图解.pdf,就是个简单的一个pdf,这里有字数要求啊,哎呀哎呀,算法图解算法图解算法图解算法图解算法图解算法图解算法图解算法图解算法图解算法图解算法图解算法图解算法图解算法图解算法图解算法图解算法图解...
### 图解算法小册-Java版 #### 一、引言 随着计算机科学的发展,算法作为其中不可或缺的一部分,越来越受到人们的重视。《图解算法小册-Java版》旨在通过直观的方式,帮助读者理解并掌握各种算法的核心思想,无论你...
《算法图解-python,算法图解python3》是一本针对初学者和有一定编程基础的读者设计的算法入门书籍,特别注重使用Python语言进行讲解。这本书旨在帮助读者理解算法的基本概念,提升解决实际问题的能力,同时也为深入...
《算法图解》是一本旨在帮助读者以直观易懂的方式理解和掌握算法的书籍。通过图形化的方法,本书降低了算法学习的门槛,使原本抽象复杂的概念变得生动有趣。书中的每一个算法都配有精心设计的插图,让读者在视觉上更...
图解算法 很好的高清电子版pdf
《算法的动画图解》是针对安卓手机系统设计的一款学习应用,主要目的是通过生动的动画形式,帮助用户直观地理解各种算法的工作原理。这个1.2.7版本为简体中文解锁版,确保了国内用户可以无障碍地进行学习,无需担心...
**标题:“图解FPGrowth算法”** **一、引言** FPGrowth算法是一种用于关联规则挖掘的高效数据挖掘技术,尤其适用于处理大规模数据集。它由Hua Fan和Zhi-Hua Zhou在2000年提出,旨在解决Apriori算法在处理大量数据...
算法图解的源代码,包含各种不同语言的算法实现方法,具体算法包括:二分查找的方式和实现、选择排序实现、递归实现、快速排序实现、散列表实现、广度优先搜索实现、最短路径算法实现、贪婪算法解析、动态规划等一...
《用Python进行自然语言处理》是一本非常重要的书籍,它为中文读者提供了深入理解自然语言处理(NLP)以及如何使用Python实现这些技术的宝贵资源。NLTK(Natural Language Toolkit)是这本书的重点,它是一个开源的...
图解机器学习算法matlab实现完整源码(课程设计).zip已获导师指导并通过的97分的高分课程设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 图解机器学习算法matlab实现完整源码...
**标题:“图解Bellman-Ford算法”** **正文:** Bellman-Ford算法是一种用于解决最短路径问题的图算法,特别是在存在负权边的情况下。这个算法由Richard Bellman在1958年提出,后来由Ford进一步发展和完善。在...
《图解算法》是一本非常受欢迎的算法学习书籍,它以直观、易懂的方式介绍了各种基础及进阶的算法。本书旨在帮助读者通过图形化的方式理解复杂的算法思想,从而更好地掌握编程中的问题解决技巧。配套的示例代码是学习...
《算法图解》这本书以图形化的方式讲述了各种算法,旨在让读者能够轻松理解并掌握算法知识。 首先,算法简介部分介绍了算法的基本概念,如算法的定义和基本构成。简单查找和二分查找是基础查找算法,分别对应着线性...
算法是一系列解决问题或执行任务的明确指令,它们可以处理数据结构中的数据。常见的算法包括排序(冒泡排序、选择排序、插入排序、快速排序、归并排序等)、搜索(线性搜索、二分搜索、深度优先搜索、广度优先搜索等...
利用关键词研究工具,如Google Keyword Planner或SEMrush,量化关键词的流行度,获取搜索量数据,这有助于确定哪些关键词具有较高的潜力和价值。 在关键词研究的第三步,你需要结合外部因素全面分析收集到的数据。...
《统计自然语言处理基础》是一本深入探讨自然语言处理(NLP)领域的核心教材,尤其强调了统计方法在其中的应用。21世纪的初期,随着信息技术的飞速进步,自然语言处理作为信息产业的重要组成部分,得到了前所未有的...
数据结构是程序员应精通的一门技术,而算法部分又是这门课程的重中之重。...而该数据结构算法图解详细的介绍了数据结构涵盖的所有算法,对帮助大家理解算法并应用到实际中去又很大作用。相信,它将是你学习的好帮手!
内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、...
《算法图解源代码》是针对各种算法的实践性学习资源,涵盖了多种编程语言的实现。这个压缩包中包含了各种经典算法的详细源代码,旨在帮助开发者深入理解并掌握算法的核心概念。以下将对其中涉及的主要算法进行详细...