R语言自然语言处理:关键词提取与文本摘要(TextRank)
作者:黄天元,复旦大学博士在读,目前研究涉及文本挖掘、社交网络分析和机器学习等。希望与大家分享学习经验,推广并加深R语言在业界的应用。
邮箱:huang.tian-yuan@qq.com
关于提取关键词的方法,除了TF-IDF算法,比较有名的还有TextRank算法。它是基于PageRank衍生出来的自然语言处理算法,是一种基于图论的排序算法,以文本的相似度作为边的权重,迭代计算每个文本的TextRank值,最后把排名高的文本抽取出来,作为这段文本的关键词或者文本摘要。之所以提到关键词和文本摘要,两者其实宗旨是一样的,就是自动化提取文本的重要表征文字。
![](/assets/blank.gif)
如果分词是以词组作为切分,那么得到的是关键词。以词作为切分的时候,构成词与词之间是否连接的,是词之间是否相邻。相邻关系可以分为n元,不过在中文中,我认为2元关系已经非常足够了(比如一句话是:“我/有/一只/小/毛驴/我/从来/也/不/骑”,那么设置二元会让“一只”和“毛驴”发生关联,这就足够了)。如果是以句子切分的,那么得到的称之为文本摘要(其实就是关键的句子,俗称关键句)。如果要得到文本的关键句子,还是要对每句话进行分词,得到每句话的基本词要素。根据句子之间是否包含相同的词语,我们可以得到句子的相似度矩阵,然后再根据相似度矩阵来得到最关键的句子(也就是与其他句子关联性最强的那个句子)。当句子比较多的时候,这个计算量是非常大的。 下面,我要用R语言的textrank包来实现关键词的提取和文本摘要。
准备工作
安装必备的包。
1library(pacman)2p_load(tidyverse,tidytext,textrank,rio,jiebaR)
然后,导入数据。数据可以在我的github中获得(github.com/hope-data-sc)。文件名称为hire_text.rda。
1import("./hire_text.rda") -> hire_text2hire_text
这里面包含了互联网公司的一些招聘信息,一共有4102条记录,只有一列,列名称为hire_text,包含了企业对岗位要求的描述。
关键词提取
因为要做关键词和关键句的提取,因此我们要进行分词和分句。分词还是利用jiebaR,老套路。如果没有了解的话,请看专栏之前的文章(R语言自然语言处理系列)。不过这次,我们希望能够在得到词频的同时,得到每个词的词性,然后只把名词提取出来。 分词代码如下:
1hire_text %>% 2 mutate(id = 1:n()) -> hire_txt #给文档编号34worker(type = "tag") -> wk #构造一个分词器,需要得到词性56hire_txt %>% 7 mutate(words = map(hire_text,tagging,jieba = wk)) %>% #给文档进行逐个分词8 mutate(word_tag = map(words,enframe,name = "tag",value = "word")) %>% 9 select(id,word_tag) -> hire_words
然后,我们分组进行关键词提取。
1#构造提取关键词的函数 2 3extract_keywords = function(dt){ 4 textrank_keywords(dt$word,relevant = str_detect(dt$tag,"^n"),ngram_max = 2) %>% 5 .$keywords 6} 7 8hire_words %>% 9 mutate(textrank.key = map(word_tag,extract_keywords)) %>% 10 select(-word_tag) -> tr_keyword
现在我们的数据框中,包含了每个文档的关键词。每个关键词列表中,包含freq和ngram两列,freq代表词频,ngram代表多少个n元,2元就是“上海市-闵行区”这种形式,1元就是“上海市”、“闵行区”这种形式。 现在,我要从中挑选每篇文章最重要的3个关键词。挑选规则是:词频必须大于1,在此基础上,n元越高越好。
1tr_keyword %>% 2 unnest() %>% 3 group_by(id) %>% 4 filter(freq > 1) %>% 5 top_n(3,ngram) %>% 6 ungroup() -> top3_keywords 7 8top3_keywords 9## # A tibble: 3,496 x 410## id keyword ngram freq11## <int> <chr> <int> <int>12## 1 1 上海市-长宁区 2 213## 2 1 长宁区 1 214## 3 1 上海市-静安区 2 215## 4 4 客户 1 416## 5 5 招商银行 1 217## 6 6 事业部 1 318## 7 7 房地产 1 219## 8 9 技术 1 320## 9 10 电商 1 221## 10 10 协调 1 222## # ... with 3,486 more rows
仔细观察发现,有的文档就没有出现过,因为他们分词之后,每个词的词频都是1。现在让我们统计一下最火的十大高频词。
1top3_keywords %>% 2 count(keyword) %>% 3 arrange(desc(n)) %>% 4 slice(1:10) 5## # A tibble: 10 x 2 6## keyword n 7## <chr> <int> 8## 1 客户 298 9## 2 公司 17310## 3 产品 11011## 4 能力 9712## 5 项目 8913## 6 技术 5114## 7 市场 4815## 8 系统 4816## 9 广告 4117## 10 企业 41
这些词分别是:客户、公司、产品、能力、项目、技术、市场、系统、广告、企业。
文本摘要
文本摘要其实就是从文档中提出我们认为最关键的句子。我们会用textrank包的textrank_sentences函数,这要求我们有一个分句的数据框,还有一个分词的数据框(不过这次需要去重复,也就是说分词表中每个文档不能有重复的词)。非常重要的一点是,这次分词必须以句子为单位进行划分。 我们明确一下任务:对每一个招聘文档,我们要挑选出这个文档中最关键的一句话。要解决这个大问题,需要先解决一个小问题。就是对任意的一个长字符串,我们要能够切分成多个句子,然后按照句子分组,对其进行分词。然后我们会得到一个句子表格和单词表格。 其中,我们切分句子的标准是,切开任意长度的空格,这在正则表达式中表示为“[:space:]+”。
1get_sentence_table = function(string){2 string %>% 3 str_split(pattern = "[:space:]+") %>% 4 unlist %>% 5 as_tibble() %>% 6 transmute(sentence_id = 1:n(),sentence = value)7}
上面这个函数,对任意的一个字符串,能够返回一个含有两列的数据框,第一列是句子的编号sentence_id,另一列是句子内容sentence。我们姑且把这个数据框称之为sentence_table。 下面我们要构造另一个函数,对于任意的sentence_table,我们需要返回一个分词表格,包含两列,第一列是所属句子的编号,第二列是分词的单词内容。
1wk = worker() #在外部构造一个jieba分词器 2 3get_word_table = function(string){ 4 string %>% 5 str_split(pattern = "[:space:]+") %>% 6 unlist %>% 7 as_tibble() %>% 8 transmute(sentence_id = 1:n(),sentence = value) %>% 9 mutate(words = map(sentence,segment,jieba = wk)) %>% 10 select(-sentence) %>% 11 unnest()12}
如果分词器要在内部构造,每次运行函数都要构造一次,会非常消耗时间。 目前,对于任意一个字符串,我们有办法得到它的关键句了。我们举个例子:
1hire_text[[1]][1] -> test_text2test_text %>% get_sentence_table -> st3st %>% get_word_table -> wt4## Warning in stri_split_regex(string, pattern, n = n, simplify = simplify, :5## argument is not an atomic vector; coercing
有了这st和wt这两个表格,现在我们要愉快地提取关键句子。
1textrank_sentences(data = st,terminology = wt) %>% 2 summary(n = 1) #n代表要top多少的关键句子3## [1] "1279弄6号国峰科技大厦"
我们给这个取最重要关键句子也编写一个函数。
1get_textrank_sentence = function(st,wt){2 textrank_sentences(data = st,terminology = wt) %>% 3 summary(n = 1)4}
因为数据量比较大,我们只求第10-20条记录进行求解。不过,如果句子只有一句话,那么是会报错的。因此我们要首先去除一个句子的记录。
1hire_txt %>% 2 slice(10:20) %>% 3 mutate(st = map(hire_text,get_sentence_table)) %>% 4 mutate(wt = map(hire_text,get_word_table)) %>% 5 mutate(sentence.no = unlist(map(st,nrow))) %>% 6 select(-hire_text) %>% 7 filter(sentence.no != 1) %>% 8 mutate(key_sentence = unlist(map2(st,wt,get_textrank_sentence))) %>% 9 select(id,sentence.no,key_sentence) -> hire_abstract1011hire_abstract12## # A tibble: 10 x 313## id sentence.no key_sentence 14## <int> <int> <chr> 15## 1 10 9 开拓电商行业潜在客户 16## 2 11 5 EHS 17## 3 12 9 负责招聘渠道的维护和更新; 18## 4 13 6 荣获中国房地产经纪百强企业排名前六强; 19## 5 14 7 2、逻辑思维、分析能力强,工作谨慎、认真,具有良好的书面及语言表达能力;~20## 6 15 5 2、能独立完成栏目包装、影视片头、广告片、宣传片的制作,包括创意图设计、动画制作、特效、剪辑合成等工作;~21## 7 16 7 3、公司为员工提供带薪上岗培训和丰富的在职培训,有广阔的职业发展与晋升空间;~22## 8 17 7 您与该职位的匹配度? 23## 9 18 13 接触并建立与行业内重点企业的良好关系,及时了解需求状态;~24## 10 20 7 具有财务、金融、税务等领域专业知识;具有较强分析判断和解决问题的能力;~
如果对所有记录的摘要感兴趣,去掉slice(10:20) %>%
这一行即可。等待时间可能会较长。
总
结
实践证明,TextRank算法是一个比较耗时的算法,因为它依赖于图计算,需要构成相似度矩阵。当数据量变大的时候,运行时间会呈“几何级”增长。但是对于中小型的文本来说,这个方法还是非常不错的。但是中小型的文本,还需要摘要么?尽管如此,这还是一个非常直观的算法,如果TF-IDF在一些时候不好用的话,这是一个非常好的候补选项。
参
考资料
textrank包基本教程
http://blog.itpub.net/31562039/viewspace-2286669/
手把手 | 基于TextRank算法的文本摘要(附Python代码)
http://blog.itpub.net/31562039/viewspace-2286669/
往期精彩:
头条、快手,那些我曾经错过的暴富机会
同为数据分析师,有人14k,你却6k?
我和我的闺蜜们都在聊什么?
R语言中文社区2018年终文章整理(作者篇)
R语言中文社区2018年终文章整理(类型篇)
公众号后台回复关键字即可学习
回复 爬虫 爬虫三大案例实战
回复 Python 1小时破冰入门
回复 数据挖掘 R语言入门及数据挖掘
回复 人工智能 三个月入门人工智能
回复 数据分析师 数据分析师成长之路
回复 机器学习 机器学习的商业应用
回复 数据科学 数据科学实战
回复 常用算法 常用数据挖掘算法
给我【好看】
你也越好看!
R语言自然语言处理:关键词提取与文本摘要(TextRank)相关推荐
- 文本处理算法_关键词提取和文本摘要算法TextRank详解及实战
关键词提取和文本摘要算法TextRank详解及实战 写在前面 最近一直没有更新文章,实在惭愧.伴随着小老弟的职业方向由风控转向了NLP,后面的文章也会集中在NLP领域,希望大家能够继续支持~ 导读 本 ...
- 自然语言处理NLP中文分词,词性标注,关键词提取和文本摘要
NLP相关工具包的介绍 1.1 jieba "结巴"中文分词,理念是做最好的 Python 中文分词组件. 支持三种分词模式: (1)精确模式,试图将句子最精确地切开,适合文本分析 ...
- R语言ggplot2可视化自动换行适配长文本图例(legend)实战:Multiple Lines for Text per Legend Label
R语言ggplot2可视化自动换行适配长文本图例(legend)实战:Multiple Lines for Text per Legend Label #导入包及数据处理 library(string ...
- R语言在可视化图像中添加文本(Adding Text to plot)
R语言在可视化图像中添加文本(Adding Text to plot) 创建一个好的可视化包括引导读者,使用图形讲述一个直观的故事.在某些情况下,这个故事可以以完全直观生动的方式呈现,而不需要添加文本 ...
- 中文文本摘要提取 (文本摘要提取 有代码)基于python
任务简介 文本摘要旨在将文本或文本集合转换为包含关键信息的简短摘要.文本摘要按照输入类型可分为单文档摘要和多文档摘要.单文档摘要从给定的一个文档中生成摘要,多文档摘要从给定的一组主题相关的文档中生成摘 ...
- 寻找与疾病相关的SNP位点——R语言从SNPedia批量提取搜索数据
SNP是单核苷酸多态性,人的基因是相似的,有些位点上存在差异,这种某个位点的核苷酸差异就做单核苷酸多态性,它影响着生物的性状,影响着对某些疾病的易感性.SNPedia是一个SNP调査百科,它引用 ...
- java 文本分析 关键词提取_文本关键词提取算法总结
1.TF-IDF 昨天给大家演示简单的文本聚类,但要给每个聚类再提取一两个关键词用于表示该聚类.我们还是用TFIDF算法来做,因为这是比较简单的提取特征算法,不过这里的TF是指某词在本聚类内所有文章的 ...
- R语言笔记3:提取R对象的子集
R语言基础系列前情提要: 1数据类型(向量.数组.矩阵. 列表和数据框) 2读写数据所需的主要函数.与外部环境交互 Subsetting R Objects 取子集的三种基本方法 [ :"单 ...
- r语言用行名称提取数据框信息显示na_学会这些R语言技巧至少可以节省半年时间...
ubuntu备忘定期清空回收站 扩增子数据牢记 r ubuntu 相关技巧和备忘待解决问题1:phyloseq有一篇文章案例使用输入和输出文件相同的文件名,无法执行 待解决问题2: 待解决问题3:样品 ...
- fastrtext︱R语言使用facebook的fasttext快速文本分类算法
FastText是Facebook开发的一款快速文本分类器,提供简单而高效的文本分类和表征学习的方法,不过这个项目其实是有两部分组成的.理论介绍可见博客:NLP︱高级词向量表达(二)--FastTex ...
最新文章
- iSCSI故障查询列表
- java 文件 加解密_Java实现文件的加密解密功能示例
- JAVA 读取图片储存至本地
- [转]MD5(1)-安全性与原理
- 20 道 Spring Boot 面试题
- excel判断字符串包含另一个字符串_【前端冷知识】如何正确判断一个字符串是数值?...
- 【Linux】一步一步学Linux——seq命令(221)
- 5G NR SRS (R15)
- LabVIEW串口接收实例
- TensorFlow 2.x GPU版在conda虚拟环境下安装步骤
- mysql常用命令整理
- 联通g网java业务的是什么_联通发力G网增值业务
- spring教程(一):简单实现(转)
- 南天PR2、PR2E驱动下载,xp,win7,win8,win8.1,win10 32位64位驱动下载安装教程
- Topaz DeNoise AI 3.7 人工智能降噪
- PDCA过程模式在信息安全管理体系的应用
- Excel教程视频《Excel大神上分攻略》50个工作场景,从案例到实践
- 设置android应用闪屏图片_android 闪屏设计
- oralce 递归查询语句
- matlab 动画生成avi,MATLAB 生成.avi和.gif
热门文章
- iOS简单实现查看更多/收起的效果[最新]
- 重磅:阿里发布神器工具,直接帮你改代码,我高潮了!网友:工作量又减轻了!...
- 90后程序猿失业倒计时,还剩4年时间!!!
- SQL 子查询怎么优化?写的很深!
- 互联网架构技术干货视频分享地址发布和情况说明
- php如何使用网关,在某种情况下,由于PHP代码,网关已关闭(Gateway is down because of PHP code in one situation)...
- python前景如何调用带有event参数的方法_13、第七 - 网络编程基础 - Python中协程EVENT()函数-事件函数...
- nosql数据库之Redis集群
- Linux进阶之日志管理
- redis连接数据库进行操作