作者:赵镇宁 R语言中文社区特约作者

主题发现能够帮助我们处理和分析大规模信息并从中发现文本主要内容和主题,相关探测方法有文本聚类法、主题建模、多维尺度分析等等。这些分析方法的前期数据处理都不同程度的涉及分词、建立文档-词条矩阵、生成词条相似(相异)矩阵等关键步骤,本期主要是对前期数据预处理流程的大致总结,主要内容包括:

(1)分词:分词引擎+自定义词典+停用词词典

(2)特征(核心词)提取:高频词法+TF*IDF算法

(3)文档-词条矩阵(数据矩阵)建立:语料库+特征词+生成矩阵+稀疏矩阵处理

(4)词条相似性(相异度)矩阵建立:主要相关系数计算

本文用到的包有:

1. 数据收集

本文以《复仇者联盟3》500条热门豆瓣短评作为示例数据,数据抓取代码如下:

```

library(RCurl) # 网络请求

library(XML) # 网页解析

library(magrittr) # 管道操作

Cookie='your cookie'

headers

'Content-Type'='text/html; charset=utf-8',

'User'='Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36',

'Cookie'=Cookie

)

comments

errorurl

start

i

while(TRUE){

start=20*i

tryCatch({

url

web% htmlParse()

comment

if(length(comment)==0) break

comments

cat(sprintf("第%s页抓取成功",i),sep = "\n")

},error = function(e){

errorurl

})

Sys.sleep(runif(1,0.5,1.5))

i = i +1

}

save(comments,file="comment.Rdata")

```

2 文本预处理

以聚类为例,目前大多聚类算法通常选择两种代表性的数据结构,一是数据矩阵(对象-属性结构),即用P个变量(属性)来表现n个对象,如用年龄、身高、性别等属性来表现对象“人”,可以看成一个n*p的矩阵;二是相异度矩阵(对象-对象结构或属性-属性结构),即存储n个对象或p个属性两两之间的差异性,可以看成一个n*n(对象与对象之间)或p*p(属性与属性之间)的矩阵。对应在主题发现中,数据矩阵表现为文档-词条矩阵,相异度矩阵表现为词条-词条矩阵。因此接下来的文本预处理包括:分词、特征(核心词条)提取、建立文档-词条矩阵和建立词条-词条相异度矩阵几个关键步骤。

2.1

R中常用的分词包有Rwordseg和jiebaR,其中,Rwordseg使用rJava调用Java分词工具Ansj,Ansj基于中科院ictclas中文分词算法,采用隐马尔科夫模型(HMM),当前版本的Rwordseg完全引用了Ansj包,在这个Java包的基础上开发了R接口,并在Rforge(https://r-forge.r-project.org/R/?group_id=1054)进行维护,我们可以下载安装包进行本地安装。jiebaR是“结巴”中文分词(https://github.com/fxsjy/jieba)(Python)的R语言版本,支持隐马尔科夫模型、混合模型、最大概率法等八种分词引擎,同时具有词性标注,关键词提取,文本Simhash相似度比较等功能,本文选取jiebaR进行分词。

A. 关于分词引擎选择

本文选择的是混合模型,混合模型(MixSegment)结合使用最大概率法和隐马尔科夫模型,在分词引擎里面分词效果相对较好。

B. 关于自定义词典

为提高分词准确率,本文首先以搜狗细胞库提供的《复仇者联盟3》词库作为自定义词典,需要注意的是,搜狗词库scel文件是二进制,需要把二进制的词典转成可以使用的文本文件,jiebaR包的作者同时开发了一个cidian项目,可以转换搜狗的词典,目前托管在github,可通过devtools::install_github("qinwf/cidian")进行安装。此外,基于《复仇者联盟3》自定义词典进行分词后查看初步结果,不断往里面添加进行完善。

```

library(jiebaR)

library(cidian)

decode_scel(scel = "mydic.scel",cpp = TRUE)#将scel文件进行转换

output file: mydic.scel_2018-05-30_22_29_33.dict

scan(file="mydic.scel_2018-05-30_22_29_33.dict",what=character(),nlines=20,sep='\n',encoding='utf-8',fileEncoding='utf-8')#查看转换后的词典

Read 20 items

[1] "艾瑞克 n" "艾什莉 n" "埃文斯 n" "奥创 n" "奥创纪元 n"

[6] "奥克耶 n" "巴顿 n" "班纳 n" "鲍尔斯 n" "保罗 n"

[11] "贝坦尼 n" "变身巨人 n" "变种人 n" "变种人兄弟会 n" "波蒂埃 n"

[16] "波兹 n" "布鲁斯 n" "布鲁斯班纳 n" "布思 n" "操纵物体 n"

```

C. 关于停用词词典

首先在网上下载了一份常用停用词词典(结合哈工大停用词表、四川大学机器智能实验室停用词库、百度停用词表等),进行试分词,根据初步分词结果往停用词表中添加会对数据结果造成较大影响的停用词。

D. 关于特征(核心词条)提取

受研究工具、统计分析过程限制以及出于提高结果分析与可视化效用的目的,我们通常提取部分关键词(特征)来进行后续分析,通常用到的筛选方法有高频词法和TF*IDF算法,其中高频词法是将所有词汇按词频从高到底排序,根据经验或某一法则(如齐普夫法则)确定某一阈值,高于该阈值的为特征词,其核心思想是“一个词在文章中出现的次数越多,则它就越重要”;TF*IDF算法则考虑到“一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章”,本文利用TF*IDF算法提取。

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

```

term

for(i in 1:500)

term% c(term,.)

termFreq

termFreq

rownames(termFreq)

head(termFreq)

char freq

1 灭霸 181

2 电影 96

3 漫威 96

4 反派 58

5 宇宙 57

6 英雄 48

keys% vector_keywords(term,.) # 利用tf-idf提取核心词

keydf

head(keydf)

tf.idf.value term

1 2124.8 灭霸

2 1126.96 漫威

3 766.037 反派

4 639.156 电影

5 540.003 复联

6 419.996 宇宙

write.csv(keydf,file="keydf.csv", fileEncoding = "GBK")

```

2.2 进行分词

后期建立文档词条矩阵时需要特定的数据格式,因此利用jieba分词后,需要设置成符合tm包格式的输出,即分词之后每条评论存成一个单独的字符串,并用空格对词语进行分隔。

```

wk = worker(type = "mix", user = "mydic.scel_2018-05-30_22_29_33.dict",

stop_word = "stopword.txt") # 加载jiebaR库的分词引擎

commentseg

for(i in 1:500)

commentseg[i]% paste(.,collapse=" ")

str(commentseg)

chr [1:500] "复联 讲 猪队友 顺风 浪 一波 团灭 故事 卡魔拉 倒霉 爸爸 疯子 男朋友 傻子" ...

write.csv(commentseg,file="commentseg.csv", fileEncoding = "GBK")

```

2.3 建立文档-词条矩阵

A. 建立语料库

tm包中有一个Corpus对象用以存储原始预料,可以直接从文件中读取或者由R中的某个对象来转换,这里使用分词之后的向量对象commentseg。由于语料对象包含所有的文档的信息,不方面使用常规的方式对它们进行查看,可以使用inspect函数来查看。

```

library(tm)

ss

docs% tolower()

d.corpus

d.corpus

<>

Metadata: corpus specific: 0, document level (indexed): 0

Content: documents: 500

inspect(d.corpus[1:2]) # 查看语料库

<>

Metadata: corpus specific: 0, document level (indexed): 0

Content: documents: 2

[[1]]

<>

Metadata: 7

Content: chars: 42

[[2]]

<>

Metadata: 7

Content: chars: 137

```

B. 建立文档-词条矩阵

文本分析的基础对象是文档-词条矩阵,该数据结构在tm包中有一个专门的DocumentTermMatrix对象来实现,在文档-词条矩阵中每一行是一篇文档(评论),每一列是一个词,行和列的节点是该文档中包含该词的数目。此外,字典是一个字符集,它可以作为一个控制参数传入DocumentTermMatrix(),从而选择我们需要的词条建立文档-词条矩阵,这里以前面基于TF*idf算法得出的1500个词作为我们的词条。```

keyword

keyword% tolower() # 之前通过tf-idf筛选的核心词汇

dtm

df_mat

write.csv(df_mat,file="df_mat.csv")

```

C. 稀疏矩阵处理

```

dtm

<>

Non-/sparse entries: 4663/745337

Sparsity : 99%

Maximal term length: 22

Weighting : term frequency (tf)

```

Non-/sparse entries表示矩阵内有4663个元素大于0,而有745337个元素等于0,这种由大部分元素为0组成的矩阵成为稀疏矩阵,99%表示矩阵的稀疏程度为99%,我们可以通过tm包内的removeSparseTerms设定稀疏度大小阈值,对每个词汇做稀疏度筛选,下文将稀疏度阈值设定为0.7,表示原始矩阵的每个词汇稀疏度大于70%以上,就不予以放入DocumentTermMatrix中,下文得到的矩阵(500条评论,1词汇),矩阵内有153个元素大于347个元素是0,整体稀疏度为69%。考虑到本文评论文本规模以及经稀疏度处理后词汇量较少(小于5),因此这里不再做稀疏处理。```dtm_sub

dtm_sub

<>

Non-/sparse entries: 153/347

Sparsity : 69%

Maximal term length: 2

Weighting : term frequency (tf)

```

2.4 建立相似(相异度)矩阵

相似矩阵存储 n 个对象两两之间的相似性,目前我接触到的相似性计算方法大致可以分为三类,一是基于共现频次这一基本统计量衍生出来的,如互信息度、association strength、inclusion index、Jaccard’s coefficient、Salton’s cosine(Ochiia系数)等;二是借助知网(HowNet)、WordNet 等通用本体库以及领域词典的知识体系(包括词汇的定义及词汇间的相关关系),设计许多有用的算法来衡量词汇之间的相似程度;三是进行词向量化,如Word2vec。本文利用Salton’s cosine(Ochiia系数)来测度词语之间的相似性,具体算法如下(设文档词条矩阵为A):

(1)由文档-词条矩阵A生成共现矩阵C:

(Cij表示两两词条在同一文档中共现的频次,其中当i=j[即矩阵对角线]时表示词条本身在所有文档中出现的频次)

(2)由共现矩阵C生成相似矩阵S或相异矩阵D(1-S)

(上式表示两个词在同一评论中的共现频次/两个词出现频次的积的平方根)

```

cooccurance_mat

similarity_mat

dimnames(similarity_mat)

for(i in 1:ncol(df_mat))

for(j in 1:ncol(df_mat))

ifelse(i==j,similarity_mat[i,j]

dissimilarity_mat

write.csv(similarity_mat,file="similarity_mat.csv")

write.csv(dissimilarity_mat,file="dissimilarity_mat.csv")

```

3 总结

A. 乱码问题使用tm包建立文档-词条矩阵时经常遇到乱码问题,导致数据结果不正确,尝试过很多办法都无效……最后采取的办法是将语料库和特征词先按特定编码存储到本地,然后再读到R中。

B. 关于DocumentTermMatrix函数

(1)特别注意wordLengths参数的设置,该参数设置显示词的最小及最大长度,默认最小为3!!,也就意味着词长度小于3的词都不会被提取出来。

(2)注意tolower参数的设置,我的语料库中所有的大写英文单词都不能提取出来,只有转换为小写才能提取。

word该值小于列表中的前一条目_文本主题发现(一)-- 数据预处理相关推荐

  1. word该值小于列表中的前一条目_Word域的应和详解.doc

    Word域的应和详解 Word域的应用和详解 ■第一章 域基础一.域的作用 微软的文字处理软件Microsoft Word系列,其方便和自动化程度是其他任何文字处理软件所望尘莫及的.究其原因,其一,微 ...

  2. Python中怎么通过字典的值找到列表中对应的字典,并修改

    Python中怎么通过字典的值找到列表中对应的字典,并修改? 接下来就是我的代码 # 定义一个列表,存放字典 card_list = [{"name":"小米" ...

  3. python输出字典的前十项,从字典列表中获取前5个值?

    我从api密钥获取json. 这是我的json:{'[{"count":27,"stem":"obama","term" ...

  4. python列表删除算法_关于算法:如何从python中的列表中删除重复的条目

    最近在一次采访中,我被要求编写一个python代码来从列表中删除所有重复的条目. 例如: Input List = {1,2,4,5,2,3,1} Expected Output List = {4, ...

  5. python3 将列表中元素转化为字典_软件测试学Python(七):Python中的变量和标准数据类型...

    上一篇文章中,凯哥给大家介绍了Python中的常量(字面值). 测试凯哥:软件测试学Python(六):Python中的常量​zhuanlan.zhihu.com 在这篇文章中,凯哥带各位学习测试的知 ...

  6. python找列表中相邻数的个数_利用python求相邻数的方法示例

    前言 本文主要给大家介绍了关于利用python求相邻数的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 什么是相邻数? 比如5,相邻数为4和6,和5相差1的数,连续相差为1的 ...

  7. python 无序列表中第k大元素_查询无序列表中第K小元素

    当需要在无需列表中寻找第k小的元素时,一个显然的方法是将所有数据进行排序,然后检索k个元素.这种方法的运行时间为O(n log(n)). 无序列表调用分区函数将自身分解成两个子表,其长度为i和n-i. ...

  8. vue判断列表中包含某一项_判断字符串中是否包含某个字符串

    String对象的方法 1. indexOf() indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置. 如果要检索的 字符串值没有出现,则该方法返回 -1. var str='你 ...

  9. python 找出列表中出现最多的元素_利用Python找出序列中出现最多的元素示例代码...

    前言 Python包含6种内置的序列:列表.元组.字符串 .Unicode字符串.buffer对象.xrange对象.在序列中的每个元素都有自己的编号.列表与元组的区别在于,列表是可以修改,而组元不可 ...

最新文章

  1. storyboard搭建项目_Storyboard 快速搭建UICollectionView
  2. BIOS MCSDK 2.0 User Guide 示例学习
  3. 机电传动控制课程第一周学习笔记
  4. 有没有python与机械结合的工作-用 Python 自动化办公,我与大神之间的差距一下就...
  5. python常用命令汇总-python数据分析之pandas常用命令整理
  6. as3 访问远程计算机,Flash AS3中数据发送与接收
  7. 十年之后再看“面向对象”
  8. mac上php环境_在Mac系统下配置PHP运行环境
  9. 卧槽,又一款Markdown组合神器!!!
  10. word2003计算机考试题,[2018职称计算机Word2003考前练习题] 2018年职称计算机考试练习题库...
  11. DevOps知识地图实践指南
  12. mysql 字符串的hash函数_【转载】字符串Hash函数比较
  13. 关于《ADS-B点迹数据质量控制散及基础预警算法和实现流程》
  14. 泰迪杯数据挖掘挑战赛—数据预处理(一)
  15. java poi word 表格 重复_java使用poi操作word, 支持动态的行(一个占位符插入多条)和表格中动态行, 支持图片...
  16. 将android手机屏幕投影到电脑端
  17. [JAVA毕业设计]高铁在线购票系统源码获取和系统演示
  18. chrome浏览器小恐龙自动跑
  19. CF#446 Gluttony(思维题)
  20. [经验]iOS开发-记录下在开发过程中遇到的问题的解决方案及经验总结-1

热门文章

  1. win10重装系统修改信息
  2. 关于hostapd 2.7版本的移植问题
  3. Nginx 配置 HTTPS 证书
  4. Linux物理内存较少导致OOM问题分析
  5. ios 打包 验证应用失败原因汇总
  6. Hello hello world♥
  7. 分水岭matlab仿真,正确使用Matlab分水岭算法对细胞进行分割
  8. 三国杀Excel版–让你见证Excel的神奇
  9. 洛谷 U5750 疯暴英雄
  10. css实现3D长方形,可旋转