文本挖掘:情感分析详细步骤(基础+源码)
训练数据集、neg/pos情感词典、分词+数据清洗清洗(一、二、三级清洗步骤)、计算情感得分、模型评价 (1)在分析过程中,难免会产生很多中间变量,它们会占用大量内存。书中提到通常会将所有的临时中间变量命名为temp,只需要保证下一个temp出现之前,临时变量不会再延用就可以了。 (2)毫无疑问,如果不追求高大上的算法的话,词典法不失为一种好方法,其实有时候我们使用了很多方法,结果发现并没有什么质变,也浪费了大量时间; 比如在优化词典的时候,我希望使用高大上的算法解决问题,自动分辨出情感词,结果浪费了大量的时间,尝试了卡方统计量、各种分类器等等,结果可想而知,最后还是使用人工的方法将词典优化了一遍,是的,是用肉眼。
回复此公众号“情感分析”获取源码,以及word版原文查看。向小编咨询问题,联系微信:hai299014 一、训练数据集文本作为非结构化数据,在构造训练集的时候,很少会发给你完整的数据集,可能需要批量读取txt字符。
批量读取txt字符文件如何导入? 如何用函数批量导入文本,并且能够留在R的环境之中?循环用read.table,怎么解决每个文本文件命名问题? list函数能够有效的读入,并且存放非结构化数据。
代码解读:reviewpath为文件夹的目录名字,completepath为读取文件夹中所有的文件,生成字符串(character)格式。 如何读取单文本内容? 前面文档导入,相当于是给每个文档定了位,现在需要读入单个文档内的文本信息。 文本文档读取的时候会出现很多问题,比如分隔符、制表符等,而出现乱码,需要逐行读取。 [plain]?view plain?copy?print
代码解读:read.txt是一个简单的逐行读取的函数,readLines函数,是将一段文字分成以下的形式,需要粘贴起来; print?
lapply表示逐文本读取。 加入文档名字读取了每个文档到list之中,怎么跟每个文档名字匹配在一起?
利用as.data.frame成为一个数据框,并且不变成因子型,stringsAsFactors是因为文档名字列,很容易变成字符因子型,需要关闭这功能; colnames修改列名,还有names也可以达到同样的效果。 图 1 `read.csv`函数读取文件时,可能报警:“EOF within quoted string”,一般为数据中不正常的符号所致,常见的方法是将`quote = ""`设置为空,这样做虽然避免了警告,但是仍然解决不了问题,有时数据会对不上号,所以最好从符号上着手将一些特殊符号去除。 本文中导入的数据集是清华大学李军标注的近24000个酒店评论文本和谭松波整理的12000个来自京东、携程、当当网的跨行业评论文本。并给出了每个文本数据的评分。李军老师的数据是众多的txt文件的评论文本+用rlabelclass文件来存放文本标签,可以用read.table来调用。中科院自动化所的中英文新闻语料库?http://www.datatang.com/data/13484
train<-?read.csv("./train.csv",quote?=?"",sep?=?""",?header?=?T,?stringsAsFactors?=?F)?? #没有quote,会出现Warning?message:EOF?within?quoted?string?? #读入csv格式的时候,出现所有字符变成双引号,需要sep?=?""",来划分开,字符串分隔符的问题??? 会出现的问题: (1)EOF?within?quoted?string 解决方法:quote=""; (2)CSV格式被读入R内存中时,所有字符、变量内容都被加了双引号? 解决方案:需要调整,需要sep = """,来划分开。除了英文逗号可能引起`read.csv`函数读取csv文件报错以外, 二、正向、逆向情感词典1、词典导入与处理市面上关于情感词典,有多家研究机构进行了分析,并且公布了结果,比如大连理工、汉语情感词极值表、台湾大学情感NTUSD、知网Hownet情感词、中文褒贬义词典v1.0(清华大学李军)等,有些词典分为正向、逆向单词两个部分;有些放在一起,然后有单独的标签,可以cbind合并在一起。本文引用的是谭松波老师的正向、逆向情感词典。
#1、情感正向词,词组+打“+1”-label?? pos?<-?read.csv("./pos.csv",?sep?=?",",?stringsAsFactors?=?F)?? weight?<-?rep(1,?length(pos[,1]))?? pos?<-?cbind(pos,?weight)?? ?? #2、情感负向词,词组+打“-1”-label?? neg?<-?read.csv("./neg.csv",?stringsAsFactors?=?F)?? weight?<-?rep(-1,?length(neg[,1]))?? neg?<-?cbind(neg,?weight)?? 代码解读:weight是标签,主动贴在正向、逆向词典上。然后进行正向、逆向词典的合并。
各个词典对情感词的倾向定义可能矛盾,出现同一个词具有情感正向和负向两种倾向的情况,尽管这种情况更加符合现实,但是违背了基于词典的情感分析的原假设,所以要将这些词去重,我们的方法是一个词如果同时属于正向和负向,仅保留正向分类。用duplicated语句,保留重复的第一个词语,详细可见博客:?R语言︱数据去重。 图1? 2、词典读入词库 另外既然整合了大量的词典,就要尽量保证分词器能够把这些情感词汇分出来,所以需要将情感词典添加到分词器的词典中去,虽然这种方法在特殊情况下并不一定凑效。 已知了词典,需要把情感词放到词库里面,以备后续的匹配、分词。在这分词选用Rwordseg包来进行分词。
dict?<-?posneg[,?"term"]?? #library(Rwordseg)?? #listDict()??#查看已有词库?? #uninstallDict()?#删除安装的词典???? insertWords(dict)?? 关于Rwordseg包,如果已经存放了词库,应该先删除原有的词库。 listDict函数是查看词库,uninstallDict函数是删除词库,insertWords是把单词加入词库。加入的词库,应该是单词,所以需要posneg[,"term"]项。 三、数据清洗+分词1、一、二级清洗 文本挖掘中,对文本的清洗工作尤为重要,会出现比如:英文逗号、波浪线、英文单引号、英文双引号、分隔符等。一级清洗去掉一些特殊符号,二级清洗去掉一些内容较少、空缺值。
sentence?<-?as.vector(train.test$msg)?#文本内容转化为向量sentence?? sentence?<-?gsub("[[:digit:]]*",?"",?sentence)?#清除数字[a-zA-Z]?? sentence?<-?gsub("[a-zA-Z]",?sentence)???#清除英文字符?? sentence?<-?gsub(".",?sentence)??????#清除全英文的dot符号?? train.test?<-?train.test[!is.na(sentence),?]??????????#清除一些空值文本(文本名)?? sentence?<-?sentence[!is.na(sentence)]???#清除对应sentence里面的空值(文本内容),要先执行文本名?? train.test?<-?train.test[!nchar(sentence)?<?2,?]??#筛选字符数小于2的文本?? sentence?<-?sentence[!nchar(sentence)?<?2]?#`nchar`函数对字符计数,英文叹号为R语言里的“非”函数?? 2、分词每次可能耗费时间较长的过程,都要使用少量数据预估一下时间,这是一个优秀的习惯
system.time(x?<-?segmentCN(strwords?=?sentence))??? 分词之后需要分出来的词语,把ID、label加上,如图2所示。参考?R语言︱词典型情感分析文本操作技巧汇总(打标签、词典与数据匹配等)第四节
temp?<-?lapply(x,?length)???????????????????????#每一个元素的长度,即文本分出多少个词?? temp?<-?unlist(temp)????????????????????????????#lapply返回的是一个list,所以3行unlist?? ?? id?<-?rep(train.test[,?"id"],?temp)?????????????#将每一个对应的id复制相应的次数,就可以和词汇对应了?? ?? label?<-?rep(train.test[,?"label"],?temp)???????#id对应的情感倾向标签复制相同的次数?? term?<-?unlist(x)???????????????????????????????#6行将list解散为向量?? ?? testterm?<-?as.data.frame(cbind(id,?term,?label),?stringsAsFactors?=?F)?#生成一个单词-文档-数据框?? 3、三级清洗——去停用词 虽然算法已经足够简单,没有必要去除停用词,但是为了显示诚意,文本分析里每一个环节都不能少,这里还是认真的去除停用词,真的不是走过场哦。
stopword?<-?read.csv("./stopword.csv",?stringsAsFactors?=?F)?? stopword?<-?stopword[!stopword$term?%in%?posneg$term,]#函数`%in%`在posneg$term中查找stopword的元素,如果查到了就返回真值,没查到就返回假?? testterm?<-?testterm[!testterm$term?%in%?stopword,]#去除停用词?? 最后生成了图2中的前三列,weght是下面关联情感权重的结果。 图2 四、情感得分 1、关联情感权重已经获得了训练集的分词,而且也有了情感词典+情感词权重,那么如何把情感词典中的情感权重,加入到训练集的数据集中呢? 这时候需要进行词库之间的匹配,用plyr包中的join函数就可以匹配、并合并。
library(plyr)?? testterm?<-?join(testterm,?posneg)?? testterm?<-?testterm[!is.na(testterm$weight),?]?? head(testterm)?? 2、计算情感得分关联了情感权重,那么每个文档的得分自然而然可以求得,以weight为例,进行分组汇总即可,用aggregate函数。
#2、计算情感指数?? dictresult?<-?aggregate(weight?~?id,?data?=?testterm,?sum)?? dictlabel?<-?rep(-1,?length(dictresult[,?1]))?? dictlabel[dictresult$weight?>?0]?<-?1??????????#很有技巧地把情感词语正负赋值到情感得分表中?? dictresult?<-?as.data.frame(cbind(dictresult,?dictlabel),?stringsAsFactors?=?F)?? 图3 得到了如图3中weight的数列,为了与原来的文本分类进行比较,需要简单知道每个文本的情感偏向,得分>0则偏向为1,得分<0,偏向为-1,这时候引入了一个辅助列,dictlabel来进行这样的操作。 3、模型评价
最后可以和原先的分类进行混淆矩阵评价。从结果查看,并不是很精确。 via:http://blog.csdn.net/sinat--26917383/article/details/51313336 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |