文本挖掘:中文分词

Posted 数据小白工作间

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文本挖掘:中文分词相关的知识,希望对你有一定的参考价值。

R语言文本分词

史昱天  张丹

关键词:文本分词

文本挖掘:中文分词
1

前言

文本挖掘是数据挖掘中一个非常重要的部分,许多使用场景都会包含文本挖掘,比如我们可以对新闻事件进行分析,了解国家大事;也可以对微博信息进行分析,通过社交舆情看看大家的关注点。通过文本挖掘找到文章中的隐藏信息,对文章的结构进行分析,判断是不是同一个作者写文章;同时可以对邮件分析,结合bayes算法判断哪些是垃圾邮件,哪些是有用的邮件。

文本挖掘的第一步,就是要进行分词,分词将直接影响文本挖掘的效果,当前分词工具较为丰富,其中中文分词工具主要包括NLPLR(原ICTCLAS)、IKAnalyzer、PaodingAnalyzer等,一些工具也提供使用编程语言调用分词包的功能,但整体而言较为复杂,且因用户词库的限制导致分词效果一般,虽然在自然语言处理的课程上有演示Demo,然而在真正实践过程中困难重重,各种Bug的出现让初次接触的人来说会感到十分反感。对于编程基础较弱的同学而言,R语言语法简单,操作方便,在分词方面也有很好的支持,接下来就给大家介绍一个不错的R语言中文分词包“结巴分词”(jiebaR)。


2

   jiebaR包介绍

结巴分词(jiebaR),是一款高效的R语言中文分词包,底层使用的是C++,通过Rcpp进行高效调用。结巴分词基于MIT协议,就是免费和开源的,感谢国人作者的给力支持,让R的可以方便的处理中文文本。

https://github.com/qinwf/jiebaR

本文所使用的系统环境:

Win10 64bit

R: 3.3.3 x86_64-w64-mingw32/x64 b4bit

jiebaR包是在CRAN发布的标准库,安装起来非常简单,2条命令就可以了。

> install.packages("jiebaR")
> library("jiebaR")

3

   使用方法

具体操作过程十分简单,直接看第一个例子吧,使用jiebaR对一段文字进行分词。

> library("jiebaR")

> wk = worker()
> wk["我是《R的极客理想》图书作者"]
[1] "我是" "R"    "的"   "极客" "理想" "图书" "作者"
> wk["我是R语言的深度用户"]
[1] "我"   "是"   "R"    "语言" "的"   "深度" "用户"

很简单地,2行代码,就完成了中文分词。

jiebaR提供了3种分词语句的写法,例子上面的用[]符号的语法,还可以使用<=符合语法,或者使用segment()函数。虽然形式不同,但是分词效果是一样的。 使用<=符号的语法,如下

> wk<='另一种符合的语法'
[1] "另"   "一种" "符合" "的"   "语法"

很简单地,2行代码,就完成了中文分词。

jiebaR提供了3种分词语句的写法,例子上面的用[]符号的语法,还可以使用<=符合语法,或者使用segment()函数。虽然形式不同,但是分词效果是一样的。 使用<=符号的语法,如下

> segment( "segment()函数语句的写法" , wk )
[1] "segment" "函数"    "语句"    "的"      "写法"

我们也可以直接对文本文件进行分词,在当前目录新建一个文本文件“写作词汇.txt”。

当然,我们运行分词程序,会在当前目录生成一个新的分词结果的文件。

> wk['./写作词汇.txt']
[1] "./写作词汇.segment.2017-03-15_14_19_10.txt"

打开文件“写作词汇.segment.2017-03-15_14_19_10.txt”,整个本文以空格进行分词。当然,如果不是在当前目录下,则直接输入绝对路径即可。

4

分词引擎

在调用worker()函数时,我们实际是在加载jiebaR库的分词引擎。jiebaR库提供了7种分词引擎。

  • 混合模型(MixSegment):是四个分词引擎里面分词效果较好的类,结它合使用最大概率法和隐式马尔科夫模型。

  • 最大概率法(MPSegment) :负责根据Trie树构建有向无环图和进行动态规划算法,是分词算法的核心。

  • 隐式马尔科夫模型(HMMSegment):是根据基于人民日报等语料库构建的HMM模型来进行分词,主要算法思路是根据(B,E,M,S)四个状态来代表每个字的隐藏状态。 HMM模型由dict/hmm_model.utf8提供。分词算法即viterbi算法。

  • 索引模型(QuerySegment):先使用混合模型进行切词,再对于切出来的较长的词,枚举句子中所有可能成词的情况,找出词库里存在。

  • 标记模型(tag)

  • Simhash模型(simhash)

  • 关键词模型(keywods)

如果你不太关心引擎的事,那么直接用官方推荐的混合模型(默认选择)就行了。查看worker()函数的定义。

worker(type = "mix", dict = DICTPATH, hmm = HMMPATH, user = USERPATH,
  idf = IDFPATH, stop_word = STOPPATH, write = T, qmax = 20, topn = 5,
  encoding = "UTF-8", detect = T, symbol = F, lines = 1e+05,
  output = NULL, bylines = F, user_weight = "max")

参数列表:

  • type, 引擎类型

  • dict, 系统词典

  • hmm, HMM模型路径

  • user, 用户词典

  • idf, IDF词典

  • stop_word, 关键词用停止词库

  • write, 是否将文件分词结果写入文件,默认FALSE

  • qmax, 最大成词的字符数,默认20个字符

  • topn, 关键词数,默认5个

  • encoding, 输入文件的编码,默认UTF-8

  • detect, 是否编码检查,默认TRUE

  • symbol, 是否保留符号,默认FALSE

  • lines, 每次读取文件的最大行数,用于控制读取文件的长度。大文件则会分次读取。

  • output, 输出路径

  • bylines, 按行输出

  • user_weight, 用户权重

5

配置词典

分词引擎的质量在一定程度上能够影响分词速度,而用户词典的构建则能够为准确分词提供强有力的保障,jiebaR默认有配置标准的词典。对于我们的使用来说,不同行业或不同的文字类型,最好用专门的分词词典。在jiebaR中通过show_dictpath()函数可以查看默认的标准词典,可以通过上一小节介绍的配置项,来指定我们自己的词典。日常对话的常用词典,比如搜狗输入法的词库。

# 查看默认的词库位置
> show_dictpath()
[1] "D:/R-3.3.3/library/jiebaRD/dict"

# 查看目录
> dir(show_dictpath())
[1] "D:/R-3.3.3/library/jiebaRD/dict"

[1] "backup.rda"      "hmm_model.utf8"  "hmm_model.zip"   "idf.utf8"        "idf.zip"         "jieba.dict.utf8"

[7] "jieba.dict.zip" "model.rda" "README.md" "stop_words.utf8" "user.dict.utf8

看到词典目录中,包括了多个文件。

jieba.dict.utf8, 系统词典文件,最大概率法,utf8编码的

hmm_model.utf8, 系统词典文件,隐式马尔科夫模型,utf8编码的

user.dict.utf8, 用户词典文件,utf8编码的

stop_words.utf8,停止词文件,utf8编码的

idf.utf8,IDF语料库,用于关键词提取,utf8编码的

jieba.dict.zip,jieba.dict.utf8的压缩包

hmm_model.zip,hmm_model.utf8的压缩包

idf.zip,idf.utf8的压缩包

backup.rda,无注释

model.rda,无注释

README.md,说明文件

其中jieba.dict.utf8,就是jiebaR分词时所使用的基本词典文件,通过scan函数查看其内容,如下所示:

> scan(file="D:/R-3.3.3/library/jiebaRD/dict/user.dict.utf8",
+      what=character(),nlines=30,sep='\n',
+      encoding='utf-8',fileEncoding='utf-8')

[1] "1号店 3 n"  "1號店 3 n"  "4S店 3 n"   "4s店 3 n"   "AA制 3 n"   "AB型 3 n"   "AT&T 3 nz"  "A型 3 n"  

 [9] "A座 3 n"    "A股 3 n"    "A輪 3 n"    "A轮 3 n"    "BB机 3 n"   "BB機 3 n"   "BP机 3 n"   "BP機 3 n" 

[17] "B型 3 n"    "B座 3 n"    "B股 3 n"    "B超 3 n"    "B輪 3 n"    "B轮 3 n"    "C# 3 nz"    "C++ 3 nz" 

[25] "CALL机 3 n" "CALL機 3 n" "CD机 3 n"   "CD機 3 n"   "CD盒 3 n"   "C座 3 n"   

我们发现系统词典每一行都有三列,并以空格分割,第一列为词项,第二列为词频,第三列为词性标记,例如n代表名词,nz代表专用名词。然而查看user.dict.uft8则发现,默认的用户字典只包含5个词汇。

> scan(file="D:/R-3.3.3/library/jiebaRD/dict/user.dict.utf8",
+      what=character(),nlines=50,sep='\n',
+      encoding='utf-8',fileEncoding='utf-8')
Read 5 items
[1] "云计算"  "韩玉鉴赏"  "蓝翔 nz"  "CEO" "江大桥"  

可以使用Notepad++编辑该用户词典,加入自己定义的分词规则,从而改善分词效果。而更为有效的方法是使用已有的字典,我们可以用搜狗词典,来丰富用户自己的词库。接下来,让我们配置搜狗词典。首先,找到搜狗的安装目录,并找到词典文件,我的字典文件的路径如下:D:\搜狗输入法\SogouInput\8.2.0.9069\scd\14108.scel。把14108.scel文件复制到自己的项目目录里,用文本编辑器打开文件,发现是二进制的。那么需要用工具进行转换,把二进制的词典转成我们可以使用的文本文件。jiebaR包的作者,同时开发了一个cidian项目,可以转换搜狗的词典,那么我们只需要安装cidian包即可。

安装cidian项目

> install.packages("devtools")
> install.packages("stringi")
> install.packages("pbapply")
> install.packages("Rcpp")
> install.packages("RcppProgress")
> library(devtools)
> install_github("qinwf/cidian")
> library(cidian)

在安装Github的“qinwf/cidian”包时遇到了如下错误:

Error in curl::curl_fetch_disk(url, x$path, handle = handle) :

Problem with the SSL CA cert (path? access rights?)

查了很多解决方法,但都跟这个错误并不匹配,最后在知乎上发现了一篇帖子,可以通过输入httr::set_config( httr::config( ssl_verifypeer = 0L ) )这行语句,执行之后即可解决,然后再用install_github重新安装。

转换二进制词典到文本文件,发现总共有7524个用户词汇,查看其中前30个词汇。

# 转换
> decode_scel(scel = "./14108.scel",cpp = TRUE)output file: ./14108.scel_2017-03-16_18_34_40.dict
# 查看生成的词典文件
> scan(file = "./14108.scel_2017-03-16_18_34_40.dict", what = character(), nlines = 30, sep = "\n", encoding = "utf-8", fileEncoding = "utf-8") Read 30 items

[1] "阿党相为 n"     "阿房 n"     "阿附 n"     "阿胶 n"               

[5] "阿胶补血膏 n"    "阿胶补血颗粒 n"    "阿胶补血口服液 n"    "阿胶丁 n"             

[9] "阿胶粉 n"    "阿胶糕 n"    "阿胶膏 n"    "阿胶贡枣 n"           

[13] "阿胶固元膏 n"    "阿胶红糖 n"    "阿胶红枣 n"             "阿胶浆 n"             

[17] "阿胶胶囊 n"    "阿胶颗粒 n"    "阿胶口服液 n"           "阿胶蜜枣 n"           

[21] "阿胶片 n"    "阿胶汤 n"    "阿胶益寿口服液 n"       "阿胶枣 n"             

[25] "阿胶珠 n"      "阿兰若 n"    "阿弥陀佛 n"    "婀娜 n"               

[29] "婀娜 n"    "阿房 n"

查看未使用用户词典的分词情况,如下所示:

> wk <- worker(type = "mix", dict = DICTPATH, user = USERPATH, idf = IDFPATH)

> word1 <- wk["我不喜欢吃阿胶红糖和阿胶胶囊"]

> word1

[1] "我"   "不"   "喜欢" "吃"   "阿胶" "红糖" "和"   "阿胶" "胶囊"

将搜狗词典转化的文件14108.scel_2017-03-16_18_34_40.dict名称修改为user.dict.utf8,替换jiebaR中的用户词典文件。再进行分词处理,则可以获得更为准确的分词效果。

> wk_new <- worker(type = "mix", dict = DICTPATH, user = USERPATH, idf = IDFPATH)

> word2 <- wk_new["我不喜欢吃阿胶红糖和阿胶胶囊"]

> word2

[1] "我"       "不"       "喜欢"     "吃"       "阿胶红糖" "和"       "阿胶胶囊"

6

关键词提取

关键词提取是文本处理非常重要的一个环节,一个经典算法是TF-IDF算法。其中,TF(Term Frequency)代表词频,IDF(Inverse Document Frequency)表示逆文档频率。如果某个词在文章中多次出现,而且不是停止词,那么它很可能就反应了这段文章的特性,这就是我们要找的关键词。再通过IDF来算出每个词的权重,不常见的词出现的频率越高,则权重越大。计算TF-IDF的公式为:

TF-IDF = TF(词频) * 逆文档频率(IDF)

> install.packages("jiebaR")
> library("jiebaR")

对文档中每个词计算TF-IDF的值,把结果从大到小排序,就得到了这篇文档的关键性排序列表。jiebaR包的关键词提取提取的实现,也是使用了TF-IDF的算法。在安装目录中的idf.utf8文件,为IDF的语料库。查看idf.utf8内容。

> scan(file = "D:/R-3.3.3/library/jiebaRD/dict/idf.utf8", what = character(), nlines = 30, sep = "\n", encoding = "utf-8", fileEncoding = "utf-8")

Read 30 items

 [1] "劳动防护 13.900677652"      "生化学 13.900677652"      

 [3] "奥萨贝尔 13.900677652"      "考察队员 13.900677652"    

 [5] "岗上 11.5027823792"         "倒车档 12.2912397395"     

 [7] "编译 9.21854642485"         "蝶泳 11.1926274509"       

 [9] "外委 11.8212361103"         "故作高深 11.9547675029"   

[11] "尉遂成 13.2075304714"       "心源性 11.1926274509"     

[13] "现役军人 10.642581114"      "杜勃留 13.2075304714"     

[15] "包天笑 13.900677652"        "贾政陪 13.2075304714"     

[17] "托尔湾 13.900677652"        "多瓦 12.5143832909"       

[19] "多瓣 13.900677652"          "巴斯特尔 11.598092559"    

[21] "刘皇帝 12.8020653633"       "亚历山德罗夫 13.2075304714"

[23] "社会公众 8.90346537821"     "五百份 12.8020653633"     

[25] "两点阈 12.5143832909"       "多瓶 13.900677652"        

[27] "冰天 12.2912397395"         "库布齐 11.598092559"      

[29] "龙川县 12.8020653633"       "银燕 11.9547675029"   

idf.utf8文件每一行有2列,第一列是词项,第二列为权重。然后,我通过计算文档的词频(TF),与语料库的IDF值相乘,就可以得到TF-IDF值,从而提取文档的关键词。

比如,我们对下面的有关网络直播的文本内容进行关键词的提取。

> wk = worker()
> segment<-wk["丰富直播内容,提升UGC质量。外部链接的形成一定程度上是基于用户的关注意愿,所以确保网络直播平台内容的持续更新是吸引用户长期关注的保障,同时也是获得更多外部链接的必备条件。当前直播平台以泛娱乐、游戏、版权和垂直四大类为主,不同类别之间在内容及观看用户等方面有较大差异。网络直播平台的迅速发展与硬件设备的性能提升密切相关,尤其是摄像头的像素、捕获速度等指标直接关系到视频直播内容的整体质量,并进一步影响用户的观看体验。与综合视频网站“上传在前、观看在后”的模式不同,网络直播的时效性要求很高,视频内容的生成与用户观看几乎是同时进行的,无门槛的即兴表演发挥也在一定程度上会降低用户生成内容(UGC)的质量,而PGC的出现则是以素人的创作方式和表现力,加上公会规模化的指导包装,再经过平台产品的加持、优化及推荐,形成比普通UGC更具专业品质和观赏价值的直播内容。"]
# 计算词频
> freq(segment)

得到词频列表

# 取TF-IDF的前5的关键词

> keys <- worker("keywords", topn = 5)

# 计算关键词

> vector_keywords(segment, keys)

63.7342  40.934   35.94 35.2176  28.717

 "直播"  "用户"  "内容"   "UGC"  "观看"

本文改编自张丹《R语言中文分词jiebaR》,

作者系南京大学情报学硕士生史昱天 。

如果你也想投稿

请联系我

以上是关于文本挖掘:中文分词的主要内容,如果未能解决你的问题,请参考以下文章

如何快速入门中文分词及文本挖掘

文本挖掘模型:文本特征提取

R语言之文本挖掘--分词

文本挖掘模型:本特征提取

文本挖掘的分词原理

文本挖掘:灵玖大数据汉语智能分词技术