优化|PLSA理论与实践

2024-01-07 02:20
文章标签 实践 优化 理论 plsa

本文主要是介绍优化|PLSA理论与实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述
PLSA又称为概率潜在语义分析,是一种利用概率生成模型对文本集合进行话题分析的无监督学习方法。该模型最大的特点是加入了主题这一隐变量,文本生成主题,主题生成单词,从而得到单词-文本共现矩阵。本文将对包含物理学、计算机科学、统计学、数学四个领域的15000条文献摘要的数据集(保存在Task-Corpus.csv中)使用PLSA算法进行处理。

一、算法推导

1.1 E-steps

设单词集合为 w i ( i = 1 , ⋯ , M ) w_i(i = 1,\cdots,M) wi(i=1,,M),其中 M M M为单词数;文本集合为 d j ( j = 1 , ⋯ , N ) d_j(j = 1,\cdots, N) dj(j=1,,N),其中 N N N为文本数;主题集合为 z k ( k = 1 , ⋯ , K ) z_k(k = 1,\cdots,K) zk(k=1,,K),其中 K K K为主题数。对给定的文本,主题的分布是一个有 K K K个选项的多项分布,因此参数个数为 N × K N\times K N×K,设参数矩阵为 Λ \Lambda Λ。对给定的主题,单词的分布是一个有 M M M个选项的多项分布,因此参数个数为 K × M K\times M K×M,设参数矩阵为 Θ \Theta Θ。一般来说 K ≪ M K \ll M KM,这就避免了模型的过拟合。

如果主题未知,根据全概率公式有
p ( w i , d j ) = p ( d j ) ∑ k = 1 K p ( w i ∣ z k ) p ( z k ∣ d j ) p(w_i, d_j) = p(d_j)\sum_{k = 1}^K p(w_i | z_k)p(z_k | d_j) p(wi,dj)=p(dj)k=1Kp(wizk)p(zkdj)
因此非完全数据(主题未知)的似然函数为
L ( Θ , Λ ∣ X ) = p ( X ∣ Θ ) = ∏ i = 1 M ∏ j = 1 N ( p ( d j ) ∑ k = 1 K p ( w i ∣ z k ) p ( z k ∣ d j ) ) n ( w i , d j ) L(\Theta, \Lambda | X) = p(X | \Theta) = \prod_{i = 1}^M\prod_{j = 1}^N (p(d_j)\sum_{k = 1}^K p(w_i | z_k)p(z_k | d_j))^{n(w_i, d_j)} L(Θ,Λ∣X)=p(X∣Θ)=i=1Mj=1N(p(dj)k=1Kp(wizk)p(zkdj))n(wi,dj)
对数似然为
log ⁡ L ( Θ , Λ ∣ X ) = ∑ i = 1 M ∑ j = 1 N n ( w i , d j ) log ⁡ ( p ( d j ) ∑ k = 1 K p ( w i ∣ z k ) p ( z k ∣ d j ) ) \log L(\Theta, \Lambda | X) = \sum_{i = 1}^M \sum_{j = 1}^N n(w_i, d_j)\log(p(d_j)\sum_{k = 1}^K p(w_i | z_k)p(z_k | d_j)) logL(Θ,Λ∣X)=i=1Mj=1Nn(wi,dj)log(p(dj)k=1Kp(wizk)p(zkdj))
对数似然中包含求和的对数,因此难以处理。

如果主题已知,文章 d j d_j dj出现单词 w i w_i wi的概率为
p ( w i , d j ) = p ( d j ) p ( w i ∣ z k ) p ( z k ∣ d j ) p(w_i, d_j) = p(d_j)p(w_i | z_k)p(z_k | d_j) p(wi,dj)=p(dj)p(wizk)p(zkdj)
因此完全数据的似然函数为
L ( Θ ∣ X ) = ∏ i = 1 M ∏ j = 1 N ( p ( d j ) p ( w i ∣ z k ) p ( z k ∣ d j ) ) n ( w i , d j ) L(\Theta | X) = \prod_{i = 1}^M \prod_{j = 1}^N (p(d_j)p(w_i | z_k)p(z_k | d_j))^{n(w_i, d_j)} L(Θ∣X)=i=1Mj=1N(p(dj)p(wizk)p(zkdj))n(wi,dj)
对数似然为
log ⁡ L ( Θ ∣ X ) = ∑ j = 1 N n ( w i , d j ) log ⁡ ( p ( d j ) p ( w i ∣ z k ) p ( z k ∣ d j ) ) \log L(\Theta | X) =\sum_{j = 1}^N n(w_i, d_j) \log(p(d_j)p(w_i | z_k)p(z_k | d_j)) logL(Θ∣X)=j=1Nn(wi,dj)log(p(dj)p(wizk)p(zkdj))
Q函数为对数似然 log ⁡ L ( Θ ∣ X ) \log L(\Theta | X) logL(Θ∣X)在后验分布 p ( z k ∣ w i , d j ) p(z_k | w_i, d_j) p(zkwi,dj)下的期望
Q = ∑ k = 1 K p ( z k ∣ w i , d j ) ∑ i = 1 M ∑ j = 1 N n ( w i , d j ) log ⁡ ( p ( d j ) p ( w i ∣ z k ) p ( z k ∣ d j ) ) = ∑ i = 1 M ∑ j = 1 N n ( w i , d j ) ∑ k = 1 K p ( z k ∣ w i , d j ) log ⁡ ( p ( d j ) p ( w i ∣ z k ) p ( z k ∣ d j ) ) \begin{aligned}Q &= \sum_{k = 1}^K p(z_k | w_i, d_j) \sum_{i = 1}^M \sum_{j = 1}^N n(w_i, d_j) \log(p(d_j)p(w_i | z_k)p(z_k | d_j)) \\&= \sum_{i = 1}^M \sum_{j = 1}^N n(w_i, d_j)\sum_{k = 1}^K p(z_k | w_i, d_j)\log(p(d_j)p(w_i | z_k)p(z_k | d_j))\end{aligned} Q=k=1Kp(zkwi,dj)i=1Mj=1Nn(wi,dj)log(p(dj)p(wizk)p(zkdj))=i=1Mj=1Nn(wi,dj)k=1Kp(zkwi,dj)log(p(dj)p(wizk)p(zkdj))
其中后验概率
p ( z k ∣ w i , d j ) = p ( w i ∣ z k ) p ( z k ∣ d j ) ∑ k = 1 K p ( w i ∣ z k ) p ( z k ∣ d j ) (1) p(z_k | w_i, d_j) = \frac{p(w_i | z_k) p(z_k | d_j)}{\sum_{k = 1}^K p(w_i | z_k) p(z_k | d_j)}\tag{1} p(zkwi,dj)=k=1Kp(wizk)p(zkdj)p(wizk)p(zkdj)(1)

1.2 M-step

p ( w i ∣ z k ) , p ( z k ∣ d j ) p(w_i | z_k), p(z_k | d_j) p(wizk),p(zkdj)满足约束条件
∑ i = 1 M p ( w i ∣ z k ) = 1 , k = 1 , ⋯ , K \sum_{i = 1}^M p(w_i | z_k) = 1, k = 1,\cdots,K i=1Mp(wizk)=1,k=1,,K
∑ k = 1 K p ( z k ∣ d j ) = 1 , j = 1 , ⋯ , N \sum_{k = 1}^K p(z_k | d_j) = 1,j = 1,\cdots,N k=1Kp(zkdj)=1,j=1,,N
引入拉格朗日函数
J = Q + ∑ k = 1 K r k ( 1 − ∑ i = 1 M p ( w i ∣ z k ) ) + ∑ j = 1 N ρ j ( 1 − ∑ k = 1 K p ( z k ∣ d j ) ) J = Q + \sum_{k = 1}^K r_k(1 - \sum_{i = 1}^M p(w_i | z_k)) + \sum_{j = 1}^N\rho_j(1 - \sum_{k = 1}^K p(z_k | d_j)) J=Q+k=1Krk(1i=1Mp(wizk))+j=1Nρj(1k=1Kp(zkdj))
∂ J ∂ p ∗ ( w i ∣ z k ) = ∑ j = 1 N n ( w i , d j ) p ( z k ∣ w i , d j ) p ( w i ∣ z k ) − r k = 0 \frac{\partial J}{\partial p^*(w_i | z_k)} = \sum_{j = 1}^N \frac{n(w_i, d_j) p(z_k | w_i, d_j)}{p(w_i | z_k)} - r_k = 0 p(wizk)J=j=1Np(wizk)n(wi,dj)p(zkwi,dj)rk=0
因此
r k p ∗ ( w i ∣ z k ) = ∑ j = 1 N n ( w i , d j ) p ( z k ∣ w i , d j ) r_k p^*(w_i | z_k) = \sum_{j = 1}^N n(w_i, d_j) p(z_k | w_i, d_j) rkp(wizk)=j=1Nn(wi,dj)p(zkwi,dj)
i i i求和,就有
r k = ∑ i = 1 M ∑ j = 1 N n ( w i , d j ) p ( z k ∣ w i , d j ) r_k = \sum_{i = 1}^M \sum_{j = 1}^N n(w_i, d_j) p(z_k | w_i, d_j) rk=i=1Mj=1Nn(wi,dj)p(zkwi,dj)
p ∗ ( w i ∣ z k ) = ∑ j = 1 N n ( w i , d j ) p ( z k ∣ w i , d j ) ∑ i = 1 M ∑ j = 1 N n ( w i , d j ) p ( z k ∣ w i , d j ) ( 2 ) p^*(w_i | z_k) = \frac{\sum_{j = 1}^N n(w_i, d_j) p(z_k | w_i, d_j)}{\sum_{i = 1}^M \sum_{j = 1}^N n(w_i, d_j) p(z_k | w_i, d_j)} \qquad (2) p(wizk)=i=1Mj=1Nn(wi,dj)p(zkwi,dj)j=1Nn(wi,dj)p(zkwi,dj)(2)
同理
p ∗ ( z k ∣ d j ) = ∑ j = 1 N n ( w i , d j ) p ( z k ∣ w i , d j ) ∑ i = 1 M n ( w i , d j ) ( 3 ) p^*(z_k | d_j) = \frac{\sum_{j = 1}^N n(w_i, d_j) p(z_k | w_i, d_j)}{\sum_{i = 1}^M n(w_i, d_j)} \qquad (3) p(zkdj)=i=1Mn(wi,dj)j=1Nn(wi,dj)p(zkwi,dj)(3)

( 1 ) ( 2 ) ( 3 ) (1)(2)(3) (1)(2)(3)三式共同构成PLSA算法的迭代公式。

二、算法实现

用python实现PLSA算法。首先对数据集先做预处理。对给定的文本进行分词,利用wordnet语料库将同义词进行替换(例如单复数不同的词需要替换成同一个词),并将停用词排除(停用词表在网上下载,参见作业中的stopwords.dic文件)。然后对全体文本构成的单词集合进行词频统计,构建词频矩阵 n ( w i , d j ) n(w_i, d_j) n(wi,dj)。这一部分用到了python的nltk包。核心代码如下。

words = set()word_counts = []for document in documents:seglist = word_tokenize(document)wordlist = []for word in seglist:synsets = wordnet.synsets(word)if synsets:syn_word = synsets[0].lemmas()[0].name()if syn_word not in stopwords:wordlist.append(syn_word)else:if word not in stopwords:wordlist.append(word)words = words.union(wordlist)word_counts.append(Counter(wordlist))word2id = {words:id for id, words in enumerate(words)}id2word = dict(enumerate(words))N = len(documents) # number of documentsM = len(words) # number of wordsX = np.zeros((N, M))for i in range(N):for keys in word_counts[i]:X[i, word2id[keys]] = word_counts[i][keys]

然后根据 ( 1 ) ( 2 ) ( 3 ) (1)(2)(3) (1)(2)(3)三式进行PLSA算法的编写。注意到这三个式子都可以写成矩阵的形式,提高运算效率。同时注意到这三个式子都和分子成正比,因此可以计算出份子再除以归一化常数即可。E-step的代码如下。

def E_step(lam, theta):# lam: N * K, theta: K * M, p = K * N * MN = lam.shape[0]M = theta.shape[1]lam_reshaped = np.tile(lam, (M, 1, 1)).transpose((2,1,0)) # K * N * Mtheta_reshaped = np.tile(theta, (N, 1, 1)).transpose((1,0,2)) # K * N * Mtemp = lam @ thetap = lam_reshaped * theta_reshaped / tempreturn p

M-step的代码如下。

def M_step(p, X):# p: K * N * M, X: N * M, lam: N * K, theta: K * M# update lamlam = np.sum(p * X, axis=2) # K * Nlam = lam / np.sum(lam, axis=0) # normalization for each columnlam = lam.transpose((1,0)) # N * K# update thetatheta = np.sum(p * X, axis=1) # K * Mtheta = theta / np.sum(theta, axis=1)[:, np.newaxis] # normalization for each rowreturn lam, theta

计算对数似然的代码如下。

def LogLikelihood(p, X, lam, theta):# p: K * N * M, X: N * M, lam: N * K, theta: K * Mres = np.sum(X * np.log(lam @ theta)) # N * Mreturn res

用随机数初始化 Θ , Λ \Theta,\Lambda Θ,Λ以避免落入局部最优。设定最大迭代次数为200。对数似然的阈值为10。当相邻两次对数似然的差小于阈值或者达到最大迭代次数时停止迭代。如果计算对数似然时报错,说明某个参数被舍入到0,此时也需要停止迭代。

三、结果分析

由于笔记本电脑的内存有限,从所给数据集中随机抽取1000篇文本进行实验。设定主题数为4。某次实验的结果如下。构建的字典中包含11342个单词。字典保存在dictionary.json文件中。

程序在迭代152次后停止。可以看到对数似然确实在不断上升。

每个文本的主题分布保存在DocTopicDistribution.csv文件中。每个主题的单词分布保存在TopicWordDistribution.csv文件中。每个主题中出现概率最高的9个单词保存在topics.txt文件中,如下图所示。可以看到出现概率最高的单词分别为astatine, network, Associate_in_Nursing, algorithm,分别对应了物理学、计算机科学、统计学、数学四个领域。这证明了PLSA方法的有效性。

项目开源

本项目开源在kungfu-crab/PLSA: A python implementation for PLSA(Probabilistic Latent Semantic Analysis) using EM algorithm. (github.com),仅作为学习交流使用,禁止转载与抄袭。

参考文献

[1] Hofmann, T. (1999). Probabilistic Latent Semantic Analysis. In Proceedings of the Fifteenth Conference on Uncertainty in Artificial Intelligence (pp. 289-296). Morgan Kaufmann Publishers Inc.

这篇关于优化|PLSA理论与实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/578404

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

MySQL不使用子查询的原因及优化案例

《MySQL不使用子查询的原因及优化案例》对于mysql,不推荐使用子查询,效率太差,执行子查询时,MYSQL需要创建临时表,查询完毕后再删除这些临时表,所以,子查询的速度会受到一定的影响,本文给大家... 目录不推荐使用子查询和JOIN的原因解决方案优化案例案例1:查询所有有库存的商品信息案例2:使用EX

MySQL中my.ini文件的基础配置和优化配置方式

《MySQL中my.ini文件的基础配置和优化配置方式》文章讨论了数据库异步同步的优化思路,包括三个主要方面:幂等性、时序和延迟,作者还分享了MySQL配置文件的优化经验,并鼓励读者提供支持... 目录mysql my.ini文件的配置和优化配置优化思路MySQL配置文件优化总结MySQL my.ini文件

Linux中Curl参数详解实践应用

《Linux中Curl参数详解实践应用》在现代网络开发和运维工作中,curl命令是一个不可或缺的工具,它是一个利用URL语法在命令行下工作的文件传输工具,支持多种协议,如HTTP、HTTPS、FTP等... 目录引言一、基础请求参数1. -X 或 --request2. -d 或 --data3. -H 或

Docker集成CI/CD的项目实践

《Docker集成CI/CD的项目实践》本文主要介绍了Docker集成CI/CD的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、引言1.1 什么是 CI/CD?1.2 docker 在 CI/CD 中的作用二、Docke

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义