用于文档分类的监督潜在Dirichlet分配?

时间:2012-11-25 20:12:20

标签: machine-learning nlp classification document-classification lda

我在一些群体中有一堆已经人为分类的文件。

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

3 个答案:

答案 0 :(得分:13)

对于它的价值,LDA作为一个分类器将会相当薄弱,因为它是一个生成模型,而分类是一个歧视性问题。有一个名为supervised LDA的LDA的变体,它使用更具辨别力的标准来形成主题(你可以在不同的地方获得这个主题的来源),并且还有一篇论文,其中max margin表达我不喜欢不知道源代码的状态。我会避免使用Labeled LDA配方,除非你确定这是你想要的,因为它对分类问题中主题和类别之间的对应关系作出了强有力的假设。

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

答案 1 :(得分:3)

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

答案 2 :(得分:3)

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

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

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()

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

sLDA prediction

在这里,我们预测了一个由一个句子组成的测试语料库的正面评论(约2个评估范围为-2到2):“这是一个非常积极的评论,很棒的电影”,如后面的模式所示直方图在右边。 有关完整的实施,请参阅ipython notebook