概述
PLSA模型的再理解以及源码分析
之前写过一篇PLSA的博文,其中的收获就是知道PLSA是LSA在概率层面的扩展,知道了PLSA是一种主题模型,知道了PLSA中的参数估计使用的是EM算法。当时我就认为,这样子经典好用的算法,我是会回头再来理解它的,这样子才会有更加深刻的心得。所以有了这篇PLSA模型的再理解。
1. 两种思路解PLSA模型
参考了很多资料,发现大体上有两种解决PLSA模型的思路。下面我们大致说一下它们的思路。
思路一:EM算法中需要更新两个概率
PLSA模型的示意图如下:
其中包括的概率有:
也就是说我们知道的是P(d,w),需要求解的是P(z,d)和P(w,z)。
我们根据P(d,w)构建似然函数,而且我们需要最大化这个似然函数,如下:
需要明确的是,这个似然函数中的自变量是P(z,d)和P(w,z),不巧的是,这两个变量在Log函数的内部是相加的关系,我们知道这为对似然函数的求导带来了很多麻烦。所以我们使用的是EM算法。
EM算法的基本实现思想是:
(1)E步骤:求隐含变量Given当前估计的参数条件下的后验概率。
(2)M步骤:最大化Complete data对数似然函数的期望,此时我们使用E步骤里计算的隐含变量的后验概率,得到新的参数值。
两步迭代进行直到收敛。
具体而言,
在PLSA模型中的E步骤,我们直接用贝叶斯公式计算隐含变量zk在当前参数取值条件下的后验概率,记住是后验概率,如下:
这里的都是已知的,因为我们一开始会对它们设置一个初始值,这样后面的迭代就可以依据于此。使用上面的公式我们计算出了隐含变量的后验概率,然后我们进入M步骤。
M步骤中,我们需要计算complete data的对数似然函数的期望,而且要最大化这个期望。那么首先我们要先计算出这个对数似然期望,如下:
(整篇算法就是这个无法理解,为什么期望是这样子的公式)
注意,这个时候的P(z|d,w)是已知的了,因为在E步骤中已经计算过了,这时候我们需要最大化这个期望,其中包含的自变量有P(z,d)和P(w,z),所以我们需要分别对它们求偏导,令偏导为0:
解方程可得如下的结果:
这个就是我们在M步骤中最大化complete data对似然函数的期望,得到的两个参数的更新公式。
不断重复EM两个步骤,可以得到最终的两个参数P(z,d)和P(w,z)的值。
思路二:EM算法中需要更新3个参数
这个思路和上面思路的区别就在于对P(d,w)的展开公式使用的不同,思路二使用的是3个概率来展开的,如下:
这样子我们后面的EM算法的大致思路都是相同的,就是表达形式变化了,最后得到的EM步骤的更新公式也变化了。当然,思路二得到的是3个参数的更新公式。如下:
你会发现,其实多了一个参数是P(z),参数P(d|z)变化了(之前是P(z|d)),然后P(w|z)是不变的,计算公式也相同。
2. PLSA算法的应用效果
对于数据X,如下:
我们使用思路二的PLSA算法,更新许多次之后的概率为:
iteration 27:
p(d/z)=
0.0000 0.0769 0.2931 0.2934 0.0000 0.0733 0.1467 0.1166 0.0000
0.1952 0.3223 0.0002 0.0000 0.1952 0.0000 0.0000 0.0918 0.1952
p(w/z)=
0.0733 0.0733 0.0000 0.0823 0.2878 0.0000 0.0000 0.1467 0.0000 0.2200 0.1166 0.0000
0.0651 0.0652 0.1302 0.1222 0.0049 0.1302 0.1302 0.0000 0.1302 0.0000 0.0918 0.1302
p(z)=
0.4702 0.5298
迭代了27次,得到了这三个概率。那么这三个概率有什么用呢?
我们知道LSA模型是利用SVD把原来的数据矩阵X降维,使用两个词之间的语义关系被挖掘了出来。两个原始空间中不相关的却语义上相关的词,在LSA模型中是比较相关的,这个是LSA直接的作用。那么PLSA有什么作用呢?
给定一个文档d,我们可以将其分类到一些主题词类别下。
PLSA算法可以通过训练样本的学习得到三个概率,而对于一个测试样本,其中P(w|z)概率是不变的,但是P(z)和P(d|z)都是需要重新更新的,我们也可以使用上面的EM算法,假如测试样本d的数据,我们可以得到新学习的P(z)和P(d|z)参数。这样我们就可以计算:
为什么要计算P(z|d)呢?因为给定了一个测试样本d,要判断它是属于那些主题的,我们就需要计算P(z|d),就是给定d,其在主题z下成立的概率是多少,不就是要计算吗。这样我们就可以计算文档d在所有主题下的概率了。
这样既可以把一个测试文档划归到一个主题下,也可以给训练文档打上主题的标记,因为我们也是可以计算训练文档它们的的。如果从这个应用思路来说,思路一说似乎更加直接,因为其直接计算出来了。
如果从上面这个应用的角度来说,LSA和PLSA的目的就是从一群文档集中找到潜在的语义因子latent factors。由于提取到的主题词比文档中的词的数量要少很多,而且我们在学习的过程中不需要知道文档的类型信息,所以说LSA和PLSA是无监督的特征降维方法。
3. PLSA源码分析
知道PLSA算法的理论和作用,我们还要会用,下面提供一个MATLAB源码,人家写的挺简单的,我加了一些分析,帮助理解。
main函数:
% function demo
%
close all; clear all;
load data.mat;
k=2;
[pz pdz pwz pzdw]=plsa(X,k);
% 返回的是4种概率
imagesc(pz); colormap(gray); colorbar;
title('Probability of topics pz');
xlabel('topic z_i'); ylabel('probability');
figure;
imagesc(pdz); colormap(gray); colorbar;
title('Category probability of document pdz');
xlabel('document d_i (pdz_{(i,j)} is the prob. that d_i belongs to z_j)'); ylabel('topic z_j');
figure;
imagesc(pwz); colormap(gray); colorbar;
title('Category probability of word pwz');
xlabel('word w_i (pwz_{(i,j)} is the prob. that w_i belongs to z_j)'); ylabel('topic z_j');
PLSA子函数:
function [pz pdz pwz pzdw]=plsa(X,k)
% function [pz pdz pwz pzdw]=plsa(X,k)
% Return pLSA probability matrix p of m*n matrix X
% X is the document-word co-occurence matrix
% k is the number of the topics--z
% document--collums,word--rows
err=0.0001;
x = X;
[m n]=size(x);
% m个词,n个文档
pz=rand(1,k);
% 随机初始化pz, k个主题词
pz2=pz;
pz2(1)=pz2(1)+2*err;
% 初始化的都是随机值
pdz=rand(k,n);
% 二维
pwz=rand(k,m);
% 二维
pzdw=rand(m,n,k);
% 三维
%initialize
h=0;
deno=zeros(1,k);
%denominator of p(d/z) and p(w/z)
denopzdw=zeros(m,n);
%denominator of p(z/d,w)
numepdz=zeros(k,n);
%numerator of p(d/z)
numepwz=zeros(k,m);
% numerator of p(w/z)
R=sum(sum(x));
%
所有的文档的词数总和
for ki=1:k
for i=1:m
for j=1:n
% P(w|z)和P(d|z)的分母,是每个zk一个值,所以是个向量
deno(ki)=deno(ki)+x(i,j)*pzdw(i,j,ki); % 叠加,计算的是P(w|z)和P(d|z)的分母
end
end
end
% p(d/z)
for ki=1:k
for j=1:n
for i=1:m
% P(d|z)的分子,每个zk和dj一个值,所以是一个矩阵
numepdz(ki,j)=numepdz(ki,j)+x(i,j)*pzdw(i,j,ki); % 叠加,计算的是P(d|z)的分子
end
pdz(ki,j)=numepdz(ki,j)/deno(ki);
% 分子除以分母,一个矩阵
end
end
% disp(pdz);
% p(w/z)
for ki=1:k
for i=1:m
for j=1:n
% 计算的是P(w|z)的分子,每个zk和wi一个值,一个矩阵
numepwz(ki,i)=numepwz(ki,i)+x(i,j)*pzdw(i,j,ki);
end
% 分子除以分母,矩阵中的每个元素
pwz(ki,i)=numepwz(ki,i)/deno(ki);
end
end
% disp(pwz);
% p(z)
for ki=1:k
pz(ki)=deno(ki)./R;
% 即为前面的分母
end
%denominator of p(z/d,w)
for i=1:m
for j=1:n
for ki=1:k
% 计算的是P(z|d,w)的分母,对zk叠加,每个wi和dj一个值,一个矩阵
denopzdw(i,j)=denopzdw(i,j)+pz(ki)*pdz(ki,j)*pwz(ki,i);
end
end
end
% p(z/d,w)
for i=1:m
for j=1:n
for ki=1:k
% 计算的是P(z|d,w),每个zk和wi和dj一个值,一个三维矩阵
pzdw(i,j,ki)=pz(ki)*pdz(ki,j)*pwz(ki,i)/denopzdw(i,j);
end
end
end
% fprintf('p(z/d,w)=n');
% disp(pzdw)
%
iteration
iteration=0;
fprintf('iteration:n');
while abs(pz2(1)-pz(1))>err || abs(pz2(2)-pz(2))>err
iteration=iteration+1;
% 迭代次数
deno=zeros(1,k);
%denominator of p(d/z) and p(w/z)
denopzdw=zeros(m,n);
%denominator of p(z/d,w)
numepdz=zeros(k,n);
%numerator of p(d/z)
numepwz=zeros(k,m);
% numerator of p(w/z)
fprintf('iteration %d:n',iteration);
for ki=1:k
for i=1:m
for j=1:n
deno(ki)=deno(ki)+x(i,j)*pzdw(i,j,ki); % 继续迭代,deno回到0,因为需要叠加,不过pzdw就是上次的新值
end
end
end
% p(d/z)
for ki=1:k
for j=1:n
for i=1:m
numepdz(ki,j)=numepdz(ki,j)+x(i,j)*pzdw(i,j,ki);
% 计算公式同上,只不过此时的pzdw是更新过后的值
end
pdz(ki,j)=numepdz(ki,j)/deno(ki);
end
end
fprintf('p(d/z)=n');
disp(pdz)
% p(w/z)
for ki=1:k
for i=1:m
for j=1:n
numepwz(ki,i)=numepwz(ki,i)+x(i,j)*pzdw(i,j,ki);
end
pwz(ki,i)=numepwz(ki,i)/deno(ki);
end
end
fprintf('p(w/z)=n');
disp(pwz)
% p(z)
pz=pz2;
for ki=1:k
pz2(ki)=deno(ki)./R;
end
fprintf('p(z)=n');
disp(pz2)
%denominator of p(z/d,w)
for i=1:m
for j=1:n
for ki=1:k
denopzdw(i,j)=denopzdw(i,j)+pz2(ki)*pdz(ki,j)*pwz(ki,i);
end
end
end
% p(z/d,w)
for i=1:m
for j=1:n
for ki=1:k
pzdw(i,j,ki)=pz2(ki)*pdz(ki,j)*pwz(ki,i)/(denopzdw(i,j)+eps);
end
end
end
end
%end while
return;
参考:
http://www.cnblogs.com/ywl925/p/3552815.html
http://blog.csdn.net/huangxy10/article/details/8091478
http://blog.csdn.net/huangxy10/article/details/8091558
LSA和PLSA 唐克坦
http://blog.csdn.net/puqutogether/article/details/41720073
最后
以上就是坚定学姐为你收集整理的PLSA模型的再理解以及源码分析1. 两种思路解PLSA模型2. PLSA算法的应用效果3. PLSA源码分析的全部内容,希望文章能够帮你解决PLSA模型的再理解以及源码分析1. 两种思路解PLSA模型2. PLSA算法的应用效果3. PLSA源码分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复