13

我在某些组中有一堆已经被人类分类的文件。

是否有修改版本的 lda 可以用来训练模型,然后用它对未知文档进行分类?

4

3 回答 3

15

就其价值而言,LDA 作为分类器将相当薄弱,因为它是一个生成模型,而分类是一个判别问题。有一个 LDA 的变体称为监督 LDA,它使用更具区分性的标准来形成主题(您可以在各个地方获得此来源),还有一篇论文具有最大边距公式,我不知道它的状态源代码方面。除非您确定这是您想要的,否则我会避免使用 Labeled LDA 公式,因为它对分类问题中主题和类别之间的对应关系做出了强有力的假设。

然而,值得指出的是,这些方法都没有直接使用主题模型来进行分类。相反,他们使用文档,而不是使用基于单词的特征,而是使用主题的后验(文档推理产生的向量)作为其特征表示,然后将其馈送到分类器,通常是线性 SVM。这将为您提供基于主题模型的降维,然后是强大的判别分类器,这可能是您所追求的。此管道可使用流行的工具包以大多数语言提供。

于 2012-11-26T10:26:48.767 回答
6

您可以使用 PyMC 实现监督 LDA,它使用 Metropolis 采样器来学习以下图形模型中的潜在变量: sLDA图形模型

训练语料库包含 10 条电影评论(5 条正面和 5 条负面)以及每个文档的相关星级。星级评级被称为响应变量,它是与每个文档相关的感兴趣的数量。文档和响应变量被联合建模,以便找到最能预测未来未标记文档的响应变量的潜在主题。有关更多信息,请查看原始论文。考虑以下代码:

import pymc as pm
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer

train_corpus = ["exploitative and largely devoid of the depth or sophistication ",
                "simplistic silly and tedious",
                "it's so laddish and juvenile only teenage boys could possibly find it funny",
                "it shows that some studios firmly believe that people have lost the ability to think",
                "our culture is headed down the toilet with the ferocity of a frozen burrito",
                "offers that rare combination of entertainment and education",
                "the film provides some great insight",
                "this is a film well worth seeing",
                "a masterpiece four years in the making",
                "offers a breath of the fresh air of true sophistication"]
test_corpus =  ["this is a really positive review, great film"]
train_response = np.array([3, 1, 3, 2, 1, 5, 4, 4, 5, 5]) - 3

#LDA parameters
num_features = 1000  #vocabulary size
num_topics = 4       #fixed for LDA

tfidf = TfidfVectorizer(max_features = num_features, max_df=0.95, min_df=0, stop_words = 'english')

#generate tf-idf term-document matrix
A_tfidf_sp = tfidf.fit_transform(train_corpus)  #size D x V

print "number of docs: %d" %A_tfidf_sp.shape[0]
print "dictionary size: %d" %A_tfidf_sp.shape[1]

#tf-idf dictionary    
tfidf_dict = tfidf.get_feature_names()

K = num_topics # number of topics
V = A_tfidf_sp.shape[1] # number of words
D = A_tfidf_sp.shape[0] # number of documents

data = A_tfidf_sp.toarray()

#Supervised LDA Graphical Model
Wd = [len(doc) for doc in data]        
alpha = np.ones(K)
beta = np.ones(V)

theta = pm.Container([pm.CompletedDirichlet("theta_%s" % i, pm.Dirichlet("ptheta_%s" % i, theta=alpha)) for i in range(D)])
phi = pm.Container([pm.CompletedDirichlet("phi_%s" % k, pm.Dirichlet("pphi_%s" % k, theta=beta)) for k in range(K)])    

z = pm.Container([pm.Categorical('z_%s' % d, p = theta[d], size=Wd[d], value=np.random.randint(K, size=Wd[d])) for d in range(D)])

@pm.deterministic
def zbar(z=z):    
    zbar_list = []
    for i in range(len(z)):
        hist, bin_edges = np.histogram(z[i], bins=K)
        zbar_list.append(hist / float(np.sum(hist)))                
    return pm.Container(zbar_list)

eta = pm.Container([pm.Normal("eta_%s" % k, mu=0, tau=1.0/10**2) for k in range(K)])
y_tau = pm.Gamma("tau", alpha=0.1, beta=0.1)

@pm.deterministic
def y_mu(eta=eta, zbar=zbar):
    y_mu_list = []
    for i in range(len(zbar)):
        y_mu_list.append(np.dot(eta, zbar[i]))
    return pm.Container(y_mu_list)

#response likelihood
y = pm.Container([pm.Normal("y_%s" % d, mu=y_mu[d], tau=y_tau, value=train_response[d], observed=True) for d in range(D)])

# cannot use p=phi[z[d][i]] here since phi is an ordinary list while z[d][i] is stochastic
w = pm.Container([pm.Categorical("w_%i_%i" % (d,i), p = pm.Lambda('phi_z_%i_%i' % (d,i), lambda z=z[d][i], phi=phi: phi[z]),
                  value=data[d][i], observed=True) for d in range(D) for i in range(Wd[d])])

model = pm.Model([theta, phi, z, eta, y, w])
mcmc = pm.MCMC(model)
mcmc.sample(iter=1000, burn=100, thin=2)

#visualize topics    
phi0_samples = np.squeeze(mcmc.trace('phi_0')[:])
phi1_samples = np.squeeze(mcmc.trace('phi_1')[:])
phi2_samples = np.squeeze(mcmc.trace('phi_2')[:])
phi3_samples = np.squeeze(mcmc.trace('phi_3')[:])
ax = plt.subplot(221)
plt.bar(np.arange(V), phi0_samples[-1,:])
ax = plt.subplot(222)
plt.bar(np.arange(V), phi1_samples[-1,:])
ax = plt.subplot(223)
plt.bar(np.arange(V), phi2_samples[-1,:])
ax = plt.subplot(224)
plt.bar(np.arange(V), phi3_samples[-1,:])
plt.show()

给定训练数据(观察到的词和响应变量),我们可以学习全局主题(beta)和回归系数(eta),以预测响应变量(Y)以及每个文档的主题比例(theta)。为了在给定学习的 beta 和 eta 的情况下对 Y 进行预测,我们可以定义一个不观察 Y 的新模型,并使用先前学习的 beta 和 eta 来获得以下结果:

sLDA 预测

在这里,我们预测了测试语料库的正面评论(大约 2 条评论评分范围为 -2 到 2),其中包含一句话:“这是一篇非常正面的评论,很棒的电影”,如后验直方图的模式所示正确的。有关完整的实现,请参阅ipython 笔记本。

于 2017-07-25T19:28:14.947 回答
3

是的,您可以在 http://nlp.stanford.edu/software/tmt/tmt-0.4/的 stanford 解析器中尝试 Labeled LDA

于 2012-11-25T21:59:44.313 回答