R语言自然语言处理:关键词提取(TF-IDF)
作者:黄天元,复旦大学博士在读,目前研究涉及文本挖掘、社交网络分析和机器学习等。希望与大家分享学习经验,推广并加深R语言在业界的应用。
邮箱:huang.tian-yuan@qq.com
本文希望诠释如何利用TF-IDF方法对文本中的关键词进行提取。关键词提取的输入是一大段文本材料,输出是少数的关键词。比如我们日常看的论文,会有关键词。但是这些一般都是作者自己根据文章内容,向杂志社提供的关键词。事实上,如果有了正文的文本,我们完全可以利用计算机自动提取关键词(在一些数据库中,这些关键词的名称叫做Index Keywords,即索引关键词,区别于作者关键词Author Keywords)。
从海量的文本文档中,提取少量表征其内容的关键词,这就是关键词提取的主要任务。掌握了这项技能,能够自动化地给文本贴标签,非常有用。根据大部分从业者和学界的实践证明,TF-IDF算法能够解决大部分的关键词抽取场景,简单有效,其实大部分能够做文章的地方不是在算法,而是在中文分词和词性标注的部分。所以,掌握这个简单有效的方法,并利用它来做关键词提取,是非常重要的。本文会首先对TF-IDF算法做简要介绍,然后提供这个算法在R语言中的实现代码。
TF-IDF简介
TF-IDF的基本思想是:词语的重要性与它在文件中出现的次数成正比,但同时会随着它在语料库中出现的频率成反比下降。也就是说,如果在一篇论文或一次演讲中,我们反复提到一些词,那么这些词可能会比其他的词更重要。但是如果这些词,别人也都在用,那么这些词就不能称之为我们文章或者演讲的特色(比如大量的常用词)。为了能够提取出文本中“最具特色”的表征性关键词,需要利用TF-IDF算法,也就是说:如果某个词或者短语在一个文档中出现多次,但是在其他文档中很少出现,就可以认为这个词或短语具有很好的区分性,适合用来对这个文档进行表征。
TF(Term Frequency)表示一个词在文档中出现的次数。
DF(Document Frequency)表示整个语料库中含有某个词的文档个数
IDF(Inverse Document Frequency)为逆文档频率,其计算公式为:IDF= log(语料库中文档总数/(包含该词的文档数+1))。如果没有加1,那么分母为零的时候会出错,因此必须加1。图中没有加1,一般认为既然对这个词进行统计,这个词应该至少出现一次。这在训练模型的时候是正确的,但是在运用模型的时候,就不一定了。为了保险,加1没错。
TF-IDF = TF * IDF
由公式可知:一个词在文档中出现的次数越多,其TF值就越大,整个语料库中包含某个词的文档数越少,则IDF值越大,因此某个词的TF-IDF值越大,则这个词是关键词的概率越大。
TF-IDF关键词提取算法的一大缺点是:为了精确的提取一篇文档中的关键词,需要有一整个语料库来提供支持。这个问题的解决方法,通常是在一个通用的语料库上提前计算好所有词的IDF值,jieba就是这么做的。这样的解决方案对于普通文档关键词提取有一定的效果,但是对于专业性稍微强一点的文档,表现就会差很多。因此如果是一个垂直领域,需要自己先对模型进行训练,形成一个IDF的库(里面装的东西就是一个数据框,一列是词语,一列是这个词语的IDF)。jieba是用《人民日报》语料库进行训练的,对新闻类的特征提取有一定效果。但是随着时代的变迁,大家用语习惯的变化,无论是分词库还是IDF词库都需要定期更新,才能够有良好的效果。
R语言中的实现
基本准备
首先安装必要的包。
1library(pacman)2p_load(tidyverse,tidytext,data.table,rio,jiebaR)
然后,导入数据。数据在我的Github中可以下载,网址为:github.com/hope-data-sc. 我们导入到R环境中
1import("./hire_text.rda") -> hire_text2hire_text
这里面包含了互联网公司的一些招聘信息,一共有4102条记录,只有一列,列名称为hire_text,包含了企业对岗位要求的描述。
下面,我们要对这些文本进行分词,然后提取能够表征这些文本的关键词。这样,我们就可以知道这些企业究竟想要什么样的人才。
分词
首先,要进行高质量的分析,就需要用到外部词库。这里我会用搜狗词胞库,网址为pinyin.sogou.com/dict/。经过对数据的观察,我认为这些互联网公司主要招聘的对象还是IT,有的则是金融行业,因此我要使用两个词库:计算机词库(pinyin.sogou.com/dict/d/pinyin.sogou.com/dict/d)和财经词库(pinyin.sogou.com/dict/d)。下载到本地之后,我会把它们转化为文本格式,然后统一复制粘贴到用户词库中(详细方法见之前的文章R语言自然语言处理:中文分词)。 下面先对scel文件进行转格式。
1p_load(cidian)2decode_scel(scel = "./财经金融词汇大全【官方推荐】.scel", output = "./finance.utf8", cpp = TRUE)3## output file: ./finance.utf84decode_scel(scel = "./计算机词汇大全【官方推荐】.scel", output = "./it1.utf8", cpp = TRUE)5## output file: ./it1.utf86decode_scel(scel = "./开发大神专用词库【官方推荐】.scel", output = "./it2.utf8", cpp = TRUE)7## output file: ./it2.utf8
然后把这些词典加载到用户词典中。进入DICTPATH
所在目录,然后找到“user.dict.utf8”,把转格式之后的文本内容复制粘贴进去。
现在,我们的分词能力就已经得到了一定程度的提高。 现在我们要求每一个文本的关键词,首先给每个文档一个ID。
1hire_text %>% 2 mutate(id = 1:n()) -> hire_txt
然后,我们用jiebaR的工具开始分词。
1worker() -> wk 2 3hire_txt %>% 4 mutate(words = map(hire_text,segment,jieba = wk)) %>% 5 select(id,words) -> corpus 6 7corpus 8## # A tibble: 4,102 x 2 9## id words 10## <int> <list> 11## 1 1 <chr [41]>12## 2 2 <chr [51]>13## 3 3 <chr [50]>14## 4 4 <chr [54]>15## 5 5 <chr [44]>16## 6 6 <chr [63]>17## 7 7 <chr [53]>18## 8 8 <chr [18]>19## 9 9 <chr [57]>20## 10 10 <chr [49]>21## # ... with 4,092 more rows
因为这一步不是很好理解,我先停一下解释一下。我先构建了一个名为wk的worker,默认会调用我放在自定义的分词库和原有的词库。然后,我用这个分词器,对表格中每一个文本,都做了分词。这里用了map函数,它会对hire_text的每一个元素,进行segment函数的处理,而且jieba参数都会设为wk,也就是我们用同一个分词器对所有的文本进行处理。最后得到一个新的列,我命名为words,它包含了每一个文本处理的分词结果,不过因为每个文本分词的长度都不一样,我们把它们都放在一个list里面,然后放在数据框中。
不过这个格式还是不能用的,我们最后要得到tidy的格式:也就是id是所属的文本编号,而另一列应该是这个文本分词的每一个词,再一列是这个词出现的词频(TF),然后我们再来计算IDF和TF-IDF。 听起来好像很复杂,不过让你看看它在R里面能有多简单。
1corpus %>% 2 unnest() %>% 3 count(id,words) -> f_table 4 5f_table 6## # A tibble: 172,877 x 3 7## id words n 8## <int> <chr> <int> 9## 1 1 1228 110## 2 1 1279 111## 3 1 1666 112## 4 1 360 113## 5 1 567 114## 6 1 6 115## 7 1 D 116## 8 1 大厦 117## 9 1 栋 118## 10 1 高宝 119## # ... with 172,867 more rows
现在这个f_table中,id是文档编号,words是分词结果得到的每一个词,n则是这个词在当前文档中出现的频次。
求TF、IDF和TF-IDF
至此,根据原理,我们需要的数据其实全部都有了,因此无论是TF还是IDF都可以求,其乘积TF-IDF也就出来了。不过我们已经加载了tidytext这个包,因此,这个任务基本是马上就完成了。
1f_table %>% 2 bind_tf_idf(term = words,document = id,n = n) -> tf_idf_table 3 4tf_idf_table 5## # A tibble: 172,877 x 6 6## id words n tf idf tf_idf 7## <int> <chr> <int> <dbl> <dbl> <dbl> 8## 1 1 1228 1 0.0244 8.32 0.203 9## 2 1 1279 1 0.0244 8.32 0.203 10## 3 1 1666 1 0.0244 7.22 0.176 11## 4 1 360 1 0.0244 5.37 0.131 12## 5 1 567 1 0.0244 8.32 0.203 13## 6 1 6 1 0.0244 2.75 0.067114## 7 1 D 1 0.0244 5.14 0.125 15## 8 1 大厦 1 0.0244 5.23 0.128 16## 9 1 栋 1 0.0244 5.83 0.142 17## 10 1 高宝 1 0.0244 7.22 0.176 18## # ... with 172,867 more rows
我专门把形参都显示出来,大家能够知道应该怎么放进去。term接收的是分词的结果,document接收的是文档的编号,n接收的是在文档中出现的词频。一个bind_tf_idf函数,统统搞定。
关键词提取
既然关键词提取是基于TF-IDF,那么我们现在只要把每个文档中TF-IDF最高的n个词提出来,就是这个文档最重要的关键词。比如,我需要提出最重要的3个关键词,可以使用分组提取操作。
1tf_idf_table %>% 2 group_by(id) %>% 3 top_n(3,tf_idf) %>% 4 ungroup() -> top3
需要明确的是,top_n函数选择前三名的时候,如果有并列第三的,会全部纳入表格中。 最后,让我们做个词云来看看。
1p_load(wordcloud2)23top3 %>% 4 count(words) %>%5 top_n(200) %>% #只显示出现次数最多的200个关键词6 wordcloud2(size = 2, fontFamily = "微软雅黑",7 color = "random-light", backgroundColor = "grey")
因为数据是随机选的,所以不用太在意结果。此外,用jieba分词的时候,自动调用了里面的停用词库。但是,其实根据个性化的需求,可以定义更多的停用词。
参考
https://www.jianshu.com/p/837539f116d8
往期精彩:
shinydashboard与shiny_史上最全(一)
R语言自然语言处理:词性标注与命名实体识别
R语言中文社区2018年终文章整理(作者篇)
R语言中文社区2018年终文章整理(类型篇)
公众号后台回复关键字即可学习
回复 爬虫 爬虫三大案例实战
回复 Python 1小时破冰入门
回复 数据挖掘 R语言入门及数据挖掘
回复 人工智能 三个月入门人工智能
回复 数据分析师 数据分析师成长之路
回复 机器学习 机器学习的商业应用
回复 数据科学 数据科学实战
回复 常用算法 常用数据挖掘算法
给我【好看】
你也越好看!
R语言自然语言处理:关键词提取(TF-IDF)相关推荐
- R语言笔记3:提取R对象的子集
R语言基础系列前情提要: 1数据类型(向量.数组.矩阵. 列表和数据框) 2读写数据所需的主要函数.与外部环境交互 Subsetting R Objects 取子集的三种基本方法 [ :"单 ...
- r语言用行名称提取数据框信息显示na_学会这些R语言技巧至少可以节省半年时间...
ubuntu备忘定期清空回收站 扩增子数据牢记 r ubuntu 相关技巧和备忘待解决问题1:phyloseq有一篇文章案例使用输入和输出文件相同的文件名,无法执行 待解决问题2: 待解决问题3:样品 ...
- 寻找与疾病相关的SNP位点——R语言从SNPedia批量提取搜索数据
SNP是单核苷酸多态性,人的基因是相似的,有些位点上存在差异,这种某个位点的核苷酸差异就做单核苷酸多态性,它影响着生物的性状,影响着对某些疾病的易感性.SNPedia是一个SNP调査百科,它引用 ...
- r语言用行名称提取数据框信息显示na_R语言-05数据框创建,以及按条件取数据框数据...
创建数据框 数据框是R语言的一种基础数据格式,通常excel等表格形式数据读入后都是数据框格式. 下例创建了一个3列5行的数据框,列的名字分别是site.season.pH my.dataset si ...
- R语言 基于共现提取《雪中悍刀行》人物关系并画网络图
概述 雪中悍刀行作为现象级的网文,电视剧版即将上映,作为曾经的一员"妖孽"书粉,按捺不住想做点啥.最近在研究知识图谱,就以此为契机展开相关研究吧. 本文将基于简单共现关系,编写 R ...
- r语言用行名称提取数据框信息显示na_用R语言提取数据框中日期对应年份(列表转矩阵)...
[Fine原创]JMeter分布式测试中踩过的那些坑 最近因为项目需要,研究了性能测试的相关内容,并且最终选用了jmeter这一轻量级开源工具.因为一直使用jmeter的GUI模式进行脚本设计,到测试 ...
- R语言 substring() 函数 :提取字符串的一部分
substring()函数的基本语法是: substring(x,first,last) 以下是所使用的参数的说明: x - 是字符向量输入. first - 是第一个字符要被提取的位置. last ...
- NLP算法-关键词提取之Jieba算法库
关键词提取 什么叫关键词提取? 关键词提取方法分类 有监督 无监督 优缺点 Jieba 关键词提取 TF/IDF算法 TF-IDF的主要思想 如何训练关键词提取算法 demo PageRank算法 T ...
- R语言对推特twitter数据进行文本情感分析
原文链接:http://tecdat.cn/?p=4012 我们以R语言抓取的推特数据为例,对数据进行文本挖掘,进一步进行情感分析,从而得到很多有趣的信息(点击文末"阅读原文"获取 ...
- R语言对耐克NIKEID新浪微博数据K均值(K-MEANS)聚类文本挖掘和词云可视化
全文链接:http://tecdat.cn/?p=31048 2009年8月,新浪微博(micro-blog)开始服务,随后各家微博服务在国内得到广泛传播和应用"(点击文末"阅读原 ...
最新文章
- wince 6.0 串口 读取 readfile 超时问题
- AI:你们是不是在等一顶红帽子?
- Linux下git的使用——将已有项目放到github上
- 开放世界下的混合域适应 ——面向真实自然场景下的全新迁移学习范式
- javascript 对象属性
- request.setAttribute()与getParameter() 的区别
- 十字连接焊盘_PCB板上的那些“特殊焊盘 “到底起什么作用?
- 《Java安全编码标准》一导读
- 数据窗口 label_Python实现数据可视化,让你的数据清晰起来!
- SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEM...
- Welcome to Xiao
- [linux] ab压测工具进行post压力测试
- Fastjson存在0day漏洞
- Fst, pi, TajimaD plink 计算
- IBC和电信管理论坛将在数字转型世界峰会上进行媒体-电信融合项目演示
- python缺失值处理 fillna_python 处理缺失值
- linux下编译ts工程,linux下搭建生成HLS所需的.ts和.m3u8文件
- APP开发接入广告平台及应用市场(应用分发平台)记录
- Ruoyi的功能简单介绍
- 论文精读-基于双目图像的视差估计方法研究以及实现