重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
LDA可以分为以下5个步骤:
创新互联建站专注于邗江企业网站建设,自适应网站建设,商城系统网站开发。邗江网站建设公司,为邗江等地区提供建站服务。全流程按需定制开发,专业设计,全程项目跟踪,创新互联建站专业和态度为您提供的服务
关于LDA有两种含义,一种是线性判别分析(Linear Discriminant Analysis),一种是概率主题模型: 隐含狄利克雷分布(Latent Dirichlet Allocation,简称LDA) ,本文讲后者。
按照wiki上的介绍,LDA由Blei, David M.、Ng, Andrew Y.、Jordan于2003年提出,是一种主题模型,它可以将文档集 中每篇文档的主题以概率分布的形式给出,从而通过分析一些文档抽取出它们的主题(分布)出来后,便可以根据主题(分布)进行主题聚类或文本分类。同时,它是一种典型的词袋模型,即一篇文档是由一组词构成,词与词之间没有先后顺序的关系。此外,一篇文档可以包含多个主题,文档中每一个词都由其中的一个主题生成。
人类是怎么生成文档的呢?首先先列出几个主题,然后以一定的概率选择主题,以一定的概率选择这个主题包含的词汇,最终组合成一篇文章。如下图所示(其中不同颜色的词语分别对应上图中不同主题下的词)。
那么LDA就是跟这个反过来: 根据给定的一篇文档,反推其主题分布。
在LDA模型中,一篇文档生成的方式如下:
其中,类似Beta分布是二项式分布的共轭先验概率分布,而狄利克雷分布(Dirichlet分布)是多项式分布的共轭先验概率分布。此外,LDA的图模型结构如下图所示(类似贝叶斯网络结构):
先解释一下以上出现的概念。
至此,我们可以看到二项分布和多项分布很相似,Beta分布和Dirichlet 分布很相似。
如果想要深究其原理可以参考: 通俗理解LDA主题模型 ,也可以先往下走,最后在回过头来看详细的公式,就更能明白了。
总之, 可以得到以下几点信息。
在讲LDA模型之前,再循序渐进理解基础模型:Unigram model、mixture of unigrams model,以及跟LDA最为接近的pLSA模型。为了方便描述,首先定义一些变量:
反过来,既然文档已经产生,那么如何根据已经产生好的文档反推其主题呢?这个利用看到的文档推断其隐藏的主题(分布)的过程(其实也就是产生文档的逆过程),便是 主题建模的目的:自动地发现文档集中的主题(分布)。
文档d和词w是我们得到的样本,可观测得到,所以对于任意一篇文档,其 是已知的。从而可以根据大量已知的文档-词项信息 ,训练出文档-主题 和主题-词项 ,如下公式所示:
故得到文档中每个词的生成概率为:
由于 可事先计算求出,而 和 未知,所以 就是我们要估计的参数(值),通俗点说,就是要最大化这个θ。
用什么方法进行估计呢,常用的参数估计方法有极大似然估计MLE、最大后验证估计MAP、贝叶斯估计等等。因为该待估计的参数中含有隐变量z,所以我们可以考虑EM算法。详细的EM算法可以参考之前写过的 EM算法 章节。
事实上,理解了pLSA模型,也就差不多快理解了LDA模型,因为LDA就是在pLSA的基础上加层贝叶斯框架,即LDA就是pLSA的贝叶斯版本(正因为LDA被贝叶斯化了,所以才需要考虑历史先验知识,才加的两个先验参数)。
下面,咱们对比下本文开头所述的LDA模型中一篇文档生成的方式是怎样的:
LDA中,选主题和选词依然都是两个随机的过程,依然可能是先从主题分布{教育:0.5,经济:0.3,交通:0.2}中抽取出主题:教育,然后再从该主题对应的词分布{大学:0.5,老师:0.3,课程:0.2}中抽取出词:大学。
那PLSA跟LDA的区别在于什么地方呢?区别就在于:
PLSA中,主题分布和词分布是唯一确定的,能明确的指出主题分布可能就是{教育:0.5,经济:0.3,交通:0.2},词分布可能就是{大学:0.5,老师:0.3,课程:0.2}。
但在LDA中,主题分布和词分布不再唯一确定不变,即无法确切给出。例如主题分布可能是{教育:0.5,经济:0.3,交通:0.2},也可能是{教育:0.6,经济:0.2,交通:0.2},到底是哪个我们不再确定(即不知道),因为它是随机的可变化的。但再怎么变化,也依然服从一定的分布, 即主题分布跟词分布由Dirichlet先验随机确定。正因为LDA是PLSA的贝叶斯版本,所以主题分布跟词分布本身由先验知识随机给定。
换言之,LDA在pLSA的基础上给这两参数 加了两个先验分布的参数(贝叶斯化):一个主题分布的先验分布Dirichlet分布 ,和一个词语分布的先验分布Dirichlet分布 。
综上,LDA真的只是pLSA的贝叶斯版本,文档生成后,两者都要根据文档去推断其主题分布和词语分布(即两者本质都是为了估计给定文档生成主题,给定主题生成词语的概率),只是用的参数推断方法不同,在pLSA中用极大似然估计的思想去推断两未知的固定参数,而LDA则把这两参数弄成随机变量,且加入dirichlet先验。
所以,pLSA跟LDA的本质区别就在于它们去估计未知参数所采用的思想不同,前者用的是频率派思想,后者用的是贝叶斯派思想。
LDA参数估计: Gibbs采样 ,详见文末的参考文献。
推荐系统中的冷启动问题是指在没有大量用户数据的情况下如何给用户进行个性化推荐,目的是最优化点击率、转化率或用户 体验(用户停留时间、留存率等)。冷启动问题一般分为用户冷启动、物品冷启动和系统冷启动三大类。
解决冷启动问题的方法一般是基于内容的推荐。以Hulu的场景为例,对于用 户冷启动来说,我们希望根据用户的注册信息(如:年龄、性别、爱好等)、搜 索关键词或者合法站外得到的其他信息(例如用户使用Facebook账号登录,并得 到授权,可以得到Facebook中的朋友关系和评论内容)来推测用户的兴趣主题。 得到用户的兴趣主题之后,我们就可以找到与该用户兴趣主题相同的其他用户, 通过他们的历史行为来预测用户感兴趣的电影是什么。
同样地,对于物品冷启动问题,我们也可以根据电影的导演、演员、类别、关键词等信息推测该电影所属于的主题,然后基于主题向量找到相似的电影,并将新电影推荐给以往喜欢看这 些相似电影的用户。 可以使用主题模型(pLSA、LDA等)得到用户和电影的主题。
以用户为例,我们将每个用户看作主题模型中的一篇文档,用户对应的特征 作为文档中的单词,这样每个用户可以表示成一袋子特征的形式。通过主题模型 学习之后,经常共同出现的特征将会对应同一个主题,同时每个用户也会相应地 得到一个主题分布。每个电影的主题分布也可以用类似的方法得到。
那么如何解决系统冷启动问题呢? 首先可以得到每个用户和电影对应的主题向量,除此之外,还需要知道用户主题和电影主题之间的偏好程度,也就是哪些主题的用户可能喜欢哪些主题的电影。当系统中没有任何数据时,我们需要一些先验知识来指定,并且由于主题的数目通常比较小,随着系统的上线,收集到少量的数据之后我们就可以对主题之间的偏好程度得到一个比较准确的估计。
通俗理解LDA主题模型
LDA模型应用:一眼看穿希拉里的邮件
【 机器学习通俗易懂系列文章 】
输入 syso 之后 alt + / 就会快速帮你补全!
复制一行的快捷键是 选中要被复制的行 ctrl + alt + 上下 键
1.1 LDA实例
实例步骤:
1)加载数据
返回的数据格式为:documents: RDD[(Long, Vector)],其中:Long为文章ID,Vector为文章分词后的词向量;用户可以读取指定目录下的数据,通过分词以及数据格式的转换,转换成RDD[(Long, Vector)]即可。
2)建立模型
模型参数设置说明:
k: 主题数,或者聚类中心数
DocConcentration:文章分布的超参数(Dirichlet分布的参数),必需1.0
TopicConcentration:主题分布的超参数(Dirichlet分布的参数),必需1.0
MaxIterations:迭代次数
setSeed:随机种子
CheckpointInterval:迭代计算时检查点的间隔
Optimizer:优化计算方法,目前支持"em", "online"
3)结果输出
topicsMatrix以及topics(word,topic))输出。
实例代码如下:
[java] view plain copy
import org.apache.log4j.{ Level, Logger }
import org.apache.spark.{ SparkConf, SparkContext }
import org.apache.spark.mllib.clustering.LDA
import org.apache.spark.mllib.linalg.Vectors
object lda {
def main(args: Array[String]) {
//0 构建Spark对象
val conf = new SparkConf().setAppName("lda")
val sc = new SparkContext(conf)
Logger.getRootLogger.setLevel(Level.WARN)
//1 加载数据,返回的数据格式为:documents: RDD[(Long, Vector)]
// 其中:Long为文章ID,Vector为文章分词后的词向量
// 可以读取指定目录下的数据,通过分词以及数据格式的转换,转换成RDD[(Long, Vector)]即可
val data = sc.textFile("data/mllib/sample_lda_data.txt")
val parsedData = data.map(s = Vectors.dense(s.trim.split(' ').map(_.toDouble)))
// Index documents with unique IDs
val corpus = parsedData.zipWithIndex.map(_.swap).cache()
//2 建立模型,设置训练参数,训练模型
/**
* k: 主题数,或者聚类中心数
* DocConcentration:文章分布的超参数(Dirichlet分布的参数),必需1.0
* TopicConcentration:主题分布的超参数(Dirichlet分布的参数),必需1.0
* MaxIterations:迭代次数
* setSeed:随机种子
* CheckpointInterval:迭代计算时检查点的间隔
* Optimizer:优化计算方法,目前支持"em", "online"
*/
val ldaModel = new LDA().
setK(3).
setDocConcentration(5).
setTopicConcentration(5).
setMaxIterations(20).
setSeed(0L).
setCheckpointInterval(10).
setOptimizer("em").
run(corpus)
//3 模型输出,模型参数输出,结果输出
// Output topics. Each is a distribution over words (matching word count vectors)
println("Learned topics (as distributions over vocab of " + ldaModel.vocabSize + " words):")
val topics = ldaModel.topicsMatrix
for (topic - Range(0, 3)) {
print("Topic " + topic + ":")
for (word - Range(0, ldaModel.vocabSize)) { print(" " + topics(word, topic)); }
println()
}
}
}
import java.awt.event.ActionEvent;
import java.awt.*;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
testJFrame frame=new testJFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class testJFrame extends JFrame{
private JTextField text1;
private JTextField text2;
private JTextField text3;
private JButton button;
private JPanel panel;
private static final int WIDTH=300;
private static final int HEIGHT=300;
public testJFrame(){
setTitle("test");
setSize(WIDTH,HEIGHT);
text1=new JTextField(12);
text2=new JTextField(12);
text3=new JTextField(12);
button=new JButton("确定");
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
String str=text1.getText();
text2.setText(""+str.length());
for(int i=str.length()-1;i=0;i--){
text3.setText(text3.getText()+str.charAt(i));
}
}
});
panel=new JPanel();
panel.add(text1);
panel.add(text2);
panel.add(text3);
panel.add(button);
add(panel);
}
}
因为写的比较赶,所以做的比较粗糙,不过你要的功能都有实现。
针对短文本存在的稀疏问题,有一系列的算法被提出。可以大致分为三类。第一类采用一种的简单的假设去学习隐含的主题,可以认为是基于窗口的算法,一个窗口内的词具有同一主题或者共现的词具有相同的主题,代表算法Dirichlet Multinomial Mixture (DMM) in conference KDD2014, Biterm Topic Model (BTM) in journal TKDE2016。第二类算法可以成为伪长文档算法,主要是把短文本聚合成伪长文档来增强词的共现信息,代表算法有Pseudo-Document-Based Topic Model (PTM) in conference KDD2016, Self-Aggregation-Based Topic Model (SATM) in conference IJCAI2015。 第三类是通过外部语料(如词嵌入)增强词的语义信息,代表算法有Generalized P´olya Urn (GPU) based Dirichlet Multinomial Mixturemodel (GPU-DMM) in conference SIGIR2016, Generalized P´olya Urn (GPU) based Poisson-based Dirichlet Multinomial Mixturemodel (GPU-PDMM) in journal TIS2017 and Latent Feature Model with DMM (LF-DMM) in journal TACL2015.。
这些算法的源代码都可以在这个基于JAVA的包里获取到网页链接。