作者:黄天元,复旦大学博士在读,目前研究涉及文本挖掘、社交网络分析和机器学习等。希望与大家分享学习经验,推广并加深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)相关推荐

  1. R语言笔记3:提取R对象的子集

    R语言基础系列前情提要: 1数据类型(向量.数组.矩阵. 列表和数据框) 2读写数据所需的主要函数.与外部环境交互 Subsetting R Objects 取子集的三种基本方法 [ :"单 ...

  2. r语言用行名称提取数据框信息显示na_学会这些R语言技巧至少可以节省半年时间...

    ubuntu备忘定期清空回收站 扩增子数据牢记 r ubuntu 相关技巧和备忘待解决问题1:phyloseq有一篇文章案例使用输入和输出文件相同的文件名,无法执行 待解决问题2: 待解决问题3:样品 ...

  3. 寻找与疾病相关的SNP位点——R语言从SNPedia批量提取搜索数据

       SNP是单核苷酸多态性,人的基因是相似的,有些位点上存在差异,这种某个位点的核苷酸差异就做单核苷酸多态性,它影响着生物的性状,影响着对某些疾病的易感性.SNPedia是一个SNP调査百科,它引用 ...

  4. r语言用行名称提取数据框信息显示na_R语言-05数据框创建,以及按条件取数据框数据...

    创建数据框 数据框是R语言的一种基础数据格式,通常excel等表格形式数据读入后都是数据框格式. 下例创建了一个3列5行的数据框,列的名字分别是site.season.pH my.dataset si ...

  5. R语言 基于共现提取《雪中悍刀行》人物关系并画网络图

    概述 雪中悍刀行作为现象级的网文,电视剧版即将上映,作为曾经的一员"妖孽"书粉,按捺不住想做点啥.最近在研究知识图谱,就以此为契机展开相关研究吧. 本文将基于简单共现关系,编写 R ...

  6. r语言用行名称提取数据框信息显示na_用R语言提取数据框中日期对应年份(列表转矩阵)...

    [Fine原创]JMeter分布式测试中踩过的那些坑 最近因为项目需要,研究了性能测试的相关内容,并且最终选用了jmeter这一轻量级开源工具.因为一直使用jmeter的GUI模式进行脚本设计,到测试 ...

  7. R语言 substring() 函数 :提取字符串的一部分

    substring()函数的基本语法是: substring(x,first,last) 以下是所使用的参数的说明: x - 是字符向量输入. first - 是第一个字符要被提取的位置. last ...

  8. NLP算法-关键词提取之Jieba算法库

    关键词提取 什么叫关键词提取? 关键词提取方法分类 有监督 无监督 优缺点 Jieba 关键词提取 TF/IDF算法 TF-IDF的主要思想 如何训练关键词提取算法 demo PageRank算法 T ...

  9. R语言对推特twitter数据进行文本情感分析

    原文链接:http://tecdat.cn/?p=4012 我们以R语言抓取的推特数据为例,对数据进行文本挖掘,进一步进行情感分析,从而得到很多有趣的信息(点击文末"阅读原文"获取 ...

  10. R语言对耐克NIKEID新浪微博数据K均值(K-MEANS)聚类文本挖掘和词云可视化

    全文链接:http://tecdat.cn/?p=31048 2009年8月,新浪微博(micro-blog)开始服务,随后各家微博服务在国内得到广泛传播和应用"(点击文末"阅读原 ...

最新文章

  1. wince 6.0 串口 读取 readfile 超时问题
  2. AI:你们是不是在等一顶红帽子?
  3. Linux下git的使用——将已有项目放到github上
  4. 开放世界下的混合域适应 ——面向真实自然场景下的全新迁移学习范式
  5. javascript 对象属性
  6. request.setAttribute()与getParameter() 的区别
  7. 十字连接焊盘_PCB板上的那些“特殊焊盘 “到底起什么作用?
  8. 《Java安全编码标准》一导读
  9. 数据窗口 label_Python实现数据可视化,让你的数据清晰起来!
  10. SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEM...
  11. Welcome to Xiao
  12. [linux] ab压测工具进行post压力测试
  13. Fastjson存在0day漏洞
  14. Fst, pi, TajimaD plink 计算
  15. IBC和电信管理论坛将在数字转型世界峰会上进行媒体-电信融合项目演示
  16. python缺失值处理 fillna_python 处理缺失值
  17. linux下编译ts工程,linux下搭建生成HLS所需的.ts和.m3u8文件
  18. APP开发接入广告平台及应用市场(应用分发平台)记录
  19. Ruoyi的功能简单介绍
  20. 论文精读-基于双目图像的视差估计方法研究以及实现

热门文章

  1. iOS原生地图开发进阶——使用导航和附近兴趣点检索
  2. Spring 双层事务,我抛出的异常去哪了?
  3. 淘宝现重大BUG,是程序员报复?官方回应
  4. 架构师进阶:Linux进程间如何共享内存?
  5. 推荐两个非常不错的公众号
  6. 计算机网络负载均衡图片,负载均衡计算机网络课程网.ppt
  7. 互联网金融的前世、今生和未来-系列三(今生):一场跨界的战争
  8. 两种方式实现java生成Excel
  9. 习题4-6 水仙花数(20 分)
  10. iOS - 个人项目流程(建立项目和提交Git 进行代码迭代管理)