自然语言处理工具hanlp关键词提取图解TextRank算法
看一个博主(亚当-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},分数最高的关键词就是要提取的关键词
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
盘它!40篇+阿里技术经典案例,看完必收藏(上)
阿里妹导读:很多小伙伴在后台发信息,表示一天一篇技术干货看不过瘾。这里统一回复下:阿里妹去年偷偷开了个“小号”,叫做“阿里巴巴机器智能”(据说很多读算法的博士同学都在关注),平时会发AI领域的阿里经典案例,同样期待小伙伴们的关注。 错过去年的干货也没事。今天,阿里妹就从“阿里巴巴机器智能”公众号搬了不少历史文章,包括计算机视觉、语音识别、文本处理、搜索推荐等AI干货,希望你会喜欢。 计算机视觉篇点击标题即可直接阅读 《蚂蚁实时视频通话技术和实践》《基于时间尺度选择的在线行为预测》《基于尺度空间变换的本征图像分解》《如何处理多种退化类型的卷积超分辨率?》《基于风格化对抗自编码器的图像生成算法》《所见所想所找:基于生成模型的跨模态检索》《用于行人重识别的多层相似度感知CNN网络》《如何检测视频异常事件?阿里工程师提出全新检测模型》《针对场景
- 下一篇
示范了200句后,我的声音“双胞胎”诞生了!
小叽导读:语音合成的主要目的是让机器将文字变为人可以听得懂的声音。针对某个人,如果希望机器比较好地发出他的声音,那么需要录制这个人大量(几千到几万句话不等)的音频。很多时候,用户没有时间也没有精力录制这么多的音频。说话人自适应算法就是用来解决这个问题的,它利用用户少量的音频来学习,并能够发出令人满意的声音。使用本文提出的语音合成中的说话人自适应技术,用户只需要录制200句话,便能够获得与1000句话普通的语音合成系统相当的效果。 作者:黄智颖、卢恒、雷鸣、鄢志杰 会议:ICASSP-2018 摘要 说话人自适应算法利用说话人少量语料来建立说话人自适应语音合成系统,该系统能够合成令人满意的语音。在本文中,我们提出了基于线性网络的语音合成说话人自适应算法。该算法对每个说话人学习特定的线性网络,从而获得属于目标说话人的声学模型。通过该算法,使用
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- Linux系统CentOS6、CentOS7手动修改IP地址
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合Redis,开启缓存,提高访问速度
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作