文本主题发现(一)-- 数据预处理
点击蓝字关注这个神奇的公众号~
作者:赵镇宁 R语言中文社区特约作者
往期回顾:
R语言相关关系可视化函数梳理
主题发现能够帮助我们处理和分析大规模信息并从中发现文本主要内容和主题,相关探测方法有文本聚类法、主题建模、多维尺度分析等等。这些分析方法的前期数据处理都不同程度的涉及分词、建立文档-词条矩阵、生成词条相似(相异)矩阵等关键步骤,本期主要是对前期数据预处理流程的大致总结,主要内容包括:
(1)分词:分词引擎+自定义词典+停用词词典
(2)特征(核心词)提取:高频词法+TF*IDF算法
(3)文档-词条矩阵(数据矩阵)建立:语料库+特征词+生成矩阵+稀疏矩阵处理
(4)词条相似性(相异度)矩阵建立:主要相关系数计算
本文用到的包有:
1. 数据收集
本文以《复仇者联盟3》500条热门豆瓣短评作为示例数据,数据抓取代码如下:
```
library(RCurl) # 网络请求
library(XML) # 网页解析
library(magrittr) # 管道操作
Cookie='your cookie'
headers <- c('Accept'='text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'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<-c() # 短评
errorurl<-c() # 错误url
start<-0
i<-0
while(TRUE){
start=20*i
tryCatch({
url<-sprintf("https://movie.douban.com/subject/24773958/comments?start=%s&limit=20&sort=new_score&status=P&percent_type=",start)
web<-getURL(url,httpheader=headers)%>% htmlParse()
comment<-xpathSApply(web,"//div[@class='comment']//p[@class='']",xmlValue)
if(length(comment)==0) break
comments<-c(comments,comment)
cat(sprintf("第%s页抓取成功",i),sep = "\n")
},error = function(e){
errorurl<-c(errorurl,start)
})
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<-c()
for(i in 1:500)
term<-segment(comments[i], wk ) %>% c(term,.)
termFreq<-freq(term) # 统计词频
termFreq<-termFreq[order(termFreq$freq,decreasing = TRUE),]
rownames(termFreq)<-as.character(1:4541)
head(termFreq)
char freq
1 灭霸 181
2 电影 96
3 漫威 96
4 反派 58
5 宇宙 57
6 英雄 48
keys<-worker(type="keywords",topn=1500) %>% vector_keywords(term,.) # 利用tf-idf提取核心词
keydf<-data.frame("tf-idf value"=names(keys),"term"=as.character(keys),stringsAsFactors = FALSE)
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<-c()
for(i in 1:500)
commentseg[i]<-segment(comments[i], wk ) %>% 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<-read.csv("commentseg.csv",fileEncoding = "GBK",stringsAsFactors = FALSE)
docs<-ss$x %>% tolower()
d.corpus<-VCorpus(VectorSource(docs)) # 建立语料库
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<-read.csv("keydf.csv", fileEncoding = "GBK",stringsAsFactors = FALSE)
keyword<-keyword$term %>% tolower() # 之前通过tf-idf筛选的核心词汇
dtm <- DocumentTermMatrix(d.corpus,control = list(wordLengths=c(1,Inf),dictionary=keyword)) # 注意wordLengths的取值设定
df_mat<-as.matrix(dtm) # 转换为矩阵形式
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<-removeSparseTerms(dtm,0.7)
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<-t(df_mat)%*%df_mat# 共现矩阵
similarity_mat<-matrix(nrow=ncol(df_mat),ncol=ncol(df_mat)) # 利用Salton’s cosine得相似矩阵
dimnames(similarity_mat) <- list(colnames(df_mat),colnames(df_mat))
for(i in 1:ncol(df_mat))
for(j in 1:ncol(df_mat))
ifelse(i==j,similarity_mat[i,j]<-1,similarity_mat[i,j]<-cooccurance_mat[i,j]/(sqrt(cooccurance_mat[i,i]*cooccurance_mat[j,j])))
dissimilarity_mat<-1-similarity_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参数的设置,我的语料库中所有的大写英文单词都不能提取出来,只有转换为小写才能提取。
往期精彩内容整理合集
2017年R语言发展报告(国内)
R语言中文社区历史文章整理(作者篇)
R语言中文社区历史文章整理(类型篇)
公众号后台回复关键字即可学习
回复 R R语言快速入门及数据挖掘
回复 Kaggle案例 Kaggle十大案例精讲(连载中)
回复 文本挖掘 手把手教你做文本挖掘
回复 可视化 R语言可视化在商务场景中的应用
回复 大数据 大数据系列免费视频教程
回复 量化投资 张丹教你如何用R语言量化投资
回复 用户画像 京东大数据,揭秘用户画像
回复 数据挖掘 常用数据挖掘算法原理解释与应用
回复 机器学习 人工智能系列之机器学习与实践
回复 爬虫 R语言爬虫实战案例分享
文本主题发现(一)-- 数据预处理相关推荐
- word该值小于列表中的前一条目_文本主题发现(一)-- 数据预处理
作者:赵镇宁 R语言中文社区特约作者 主题发现能够帮助我们处理和分析大规模信息并从中发现文本主要内容和主题,相关探测方法有文本聚类法.主题建模.多维尺度分析等等.这些分析方法的前期数据处理都不同程度的 ...
- 属性子集选择的基本启发方法_一文看懂数据预处理最重要的3种思想和方法
导读:本文我们考虑应当采用哪些预处理步骤,让数据更加适合挖掘.数据预处理是一个广泛的领域,包含大量以复杂的方式相关联的不同策略和技术.我们将讨论一些最重要的思想和方法,并试图指出它们之间的相互联系. ...
- 一文看懂数据预处理最重要的3种思想和方法
导读:本文我们考虑应当采用哪些预处理步骤,让数据更加适合挖掘.数据预处理是一个广泛的领域,包含大量以复杂的方式相关联的不同策略和技术.我们将讨论一些最重要的思想和方法,并试图指出它们之间的相互联系. ...
- Python数据预处理:机器学习、人工智能通用技术(1)
1 什么是数据预处理 数据预处理简而言之就是将原始数据装进一个预处理的黑匣子之后,产生出高质量数据用来适应相关技术或者算法模型.为了大家更明确的了解数据预处理,我们举个新闻分类的例子: 将原始的数据直 ...
- [Python从零到壹] 十五.文本挖掘之数据预处理、Jieba工具和文本聚类万字详解
欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...
- python文本数据处理_从 App 描述介绍文字中发掘 Python 文本数据预处理实例
本文为 AI 研习社编译的技术博客,原标题 What App Descriptions Tell Us: Text Data Preprocessing in Python,作者为 Finn Qiao ...
- [深度学习TF2][RNN-LSTM]文本情感分析包含(数据预处理-训练-预测)
基于LSTM的文本情感分析 0. 前言 1. 数据下载 2. 训练数据介绍 3. 用到Word2Vector介绍 wordsList.npy介绍 wordVectors.npy介绍 4 数据预处理 4 ...
- 第二节:文本数据预处理
目录 0.介绍 知识点 1.正则表达式 基本的正则表达式的语法 re 模块 综合训练 2.分词 分词的⽅法 中文分词工具 3.词性标注 词性标注的方法 NLTK在词性标注的应用 4.词干提取与词形还原 ...
- python数据预处理的方法_文本数据预处理的方法
文本数据分析(一):基本框架 在文本数据分析基本框架中,我们涉及到了六个步骤: 数据收集 数据预处理 数据挖掘和可视化 模型构建 模型评估 虽然框架需要迭代,但是我们先将其看作是一个线性的过程: 修正 ...
- python爬取京东商品数据要先登录_京东商品评论情感分析|文本数据预处理
本文爬取了十款热销手机的文本评论数据后,首先对文本评论数据做文本预处理,文本评论数据中存在大量的无价值信息,引入无用的文本数据,对其作情感分析,显然没有价值,得出的文本挖掘结果也不尽人意.所以对于文本 ...
最新文章
- python逗号bug
- 砂.随笔.三十四.用时间在等待
- 【django】自定义中间件
- UDFs实现Memcached与Mysql的自动更新
- 快播王欣明天就出狱了,他能借钱东山再起吗?
- 关于java包_关于Java包
- 4段简短代码教你用Python读写Excel
- android csv显示乱码问题,Android CSV解析器问题
- Java正则表达式中的捕获组的概念及相关API使用
- CXF框架介绍及Spring集成
- 一台计算机英语美式发音,请教美式英语的几个发音问题!
- qmh(qtmediahub)插件研究
- Linux下获取外网IP地址的方法
- java fop_XSL-FO 和FOP相关技术详解(转载)
- FTPserver 配置
- 触摸屏和显示屏参考文献
- M3D GIS三维数字沙盘可视化交互地理信息系统开发教程第44课
- java ssh 服务器文件传输_java使用SFTP上传文件到资源服务器
- 修改linux下用户和root密码
- 洛谷刷题C语言:潇湘の雨、分糖果、Addition、Ljeto、TRI
热门文章
- Mysql 的优化方式,都给你整理好了(附思维导图)
- 如何设计一个本地缓存,涨姿势了!
- 全站HTTPS来了!有何优势、与HTTP有何不同
- 爱我或者恨我,我就是我!
- 如何更高效地使用 OkHttp
- php如何使用网关,在某种情况下,由于PHP代码,网关已关闭(Gateway is down because of PHP code in one situation)...
- Windows中安装 Redis 解压版
- 【原创】公司各个阶段 CTO 需要做什么?(上篇)
- 百度地图之添加控件——比例尺、缩略图、平移缩放
- 【转】html5离线储存,application cache,manifest使用体验