笔者寄语:在自己学LDA主题模型时候,发现该模型有这么几个未解决的问题:
1、LDA主题数量,多少个才是最优的。
2、作出主题之后,主题-主题,主题与词语之间关联如何衡量。
于是在查阅几位老师做的成果之后,将他们的成果撮合在一起。笔者发现R里面目前有两个包可以做LDA模型,是lda包+topicmodels包,两个包在使用的过程中,需要整理的数据都是不一样的,所以数据处理会是一个不省心的过程。
主题模型的概念,网络上的博客很多都有介绍,算是比较成型的一个方法,笔者推荐以下博客:
1、主题模型-LDA浅析
————————————————————————————————————————
本部分来自于大音如霜(公众号)团队,用不同主体数量下的复杂度以及对数似然值作为评判指标。
对于未知分布q,复杂度的值越小,说明模型越好,而对数似然值越大越好,刚好相反。基于复杂度和对数似然值判断语料库中的主题数量,就是计算不同主题数量下的复杂度和对数似然值之间的变化。可以将复杂度和对数似然值变化的拐点对应的主题数作为标准主题数,拐点以后复杂度和对数似然值的变化区域平缓。观察拐点和趋势需要对数据可视化,因此,分别做复杂度、对数似然值与主题数目的趋势图。
————————————————————————————————————————
该包作者探究了主题-主题,主题-词语之间的关联,主题-主题用多维标度的方式,将两者投影在低维空间,从而进行比较。
主题与词语之间的关联,以前一般是直接用每个词条的词频、TFIDF来衡量主题与词语的关联,作者用了以下的公式(公式整理来自计算传播网)
relevance(term w | topic t) = λ * p(w | t) + (1 - λ) * p(w | t)/p(w);
该主题-词语关联度大概就是综合了,词频+词语的独特性,两种属性,其中这个λ就是调节两种属性哪个重要的参数。在0-1之间,可以由研究者自己调节,当然这个λ究竟多少为好,看具体案例具体分析。
笔者在实践的过程中,因为分词的过程中没有把无效词洗干净,最后主题数会出现很多垃圾词,通过调节这个λ,碰运气可以消除一些垃圾词,笔者还没找出λ最优办法,基本靠蒙...
打开文件需要用特殊的浏览器:Mozilla Firefox(如图)
————————————————————————————————————————
三个包的使用,所需要的数据结构都是不一样的,一个个来看一下。当然最开始的基本文本处理都是一样的,整理文本,分词,清洗,去停用词,去垃圾词之类的。
特别是去垃圾词这个步骤,对结果影响很大,很多无效词凭借着高出现率,占据每个主题的较高排名。去除无效词的清洗过程,一定要反复执行,清洗。
topicmodels包+lda包都需要将文本数据,转化成list,一个list装着一个文档的词语,笔者跟着大音如霜老师,拿到的46个政府工作报告。于是list存着46个文档,每个list存在每年政府工作报告的所有单词(假设该数据名字为list)(Mark:标记(一)中的第90行代码)。
需要把list成为文档-词频矩阵,用tm包可以实现。此包解释不如lda包,因为里面有很多的东西都没作出比较好的解释。
wordcorpus <- Corpus(VectorSource(list)) # `VectorSource`是将vector转化为Source,`Corpus`函数再将Source对象转化为Corpus对象 library(tm) dtm <- DocumentTermMatrix(wordcorpus, control = list( wordLengths=c(2, Inf), # 限制词长 bounds = list(global = c(5,Inf)), # 设置词的最小频率 removeNumbers = TRUE, #removeNumbers设置是否移除数字 weighting = weightTf, #词频率权重,以TF(词频),还可以设置weighTfIdf,weightBin,weightSMART encoding = "UTF-8"))
lda包需要两个特殊数据集。一个是全文档的单词数据vocab、一个是每个文档的固定格式的数据documents。
vocab就是所有文档放在一起的一个chr格式文件。
documents是一个list格式,每个文档存放一个list。
上图是documents的数据结构,46个文档中的一个文档,第一行代表某个词的序号,第二行代表某个词出现在这个文档中的词频。
get.terms <- function(x) { index <- match(x, vocab) #获取词的ID index <- index[!is.na(index)] #去掉没有查到的,也就是去掉了的词 rbind(as.integer(index - 1), as.integer(rep(1, length(index)))) #生成上图结构 } documents <- lapply(list, get.terms)
可视化对数据的要求比较高,从以下的代码可以看出,需要主题-词语分布矩阵(phi)、文档—主题分布矩阵(theta)、单词(vocab)、每篇文章单词个数(doc.length)、
词频(term.frequency)。
library(LDAvis) json <- createJSON(phi = phi, theta = theta, doc.length = doc.length, vocab = vocab, term.frequency = term.frequency)
单词,4855个,chr字符型;
词频,4855个,int整数型;
主题-词语分布矩阵(phi)为一个大矩阵,30*4855(主题*词语),Matrix格式,具体计算过程可参考计算传播网;
文档—主题分布矩阵(theta),46*30(文档*主题),matrix格式,参考计算传播网;
每篇文章单词个数,46个,Int整数型,46个文档46个数字。
之后就可以开始建模了。