snø*_*ven 12 nlp classification machine-learning document-classification lda
我在一些群体中有一堆已经人为分类的文件.
是否有lda的修改版本,我可以用它来训练模型,然后用它来分类未知文档?
Ben*_*son 14
对于它的价值,LDA作为一个分类器将会相当薄弱,因为它是一个生成模型,而分类是一个歧视性问题.有一种称为监督LDA的LDA变体,它使用更具辨别力的标准来形成主题(你可以在不同的地方得到这个),还有一篇论文有最大边际公式,我不知道它的状态源代码,明智的.我会避免使用Labeled LDA配方,除非你确定这是你想要的,因为它对分类问题中主题和类别之间的对应关系做出了强有力的假设.
但是,值得指出的是,这些方法都没有直接使用主题模型进行分类.相反,它们采用文档,而不是使用基于单词的特征,而是在将主题(通常是线性SVM)提供给分类器之前,使用主题的后验(由文档推断产生的向量)作为其特征表示.这将为您提供基于主题模型的降维,然后是强烈的判别分类器,这可能就是您所追求的.使用流行的工具包,大多数语言都可以使用此管道.
您可以使用 PyMC实现监督 LDA,该 PyMC 使用 Metropolis 采样器学习以下图形模型中的潜在变量:

训练语料库由 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()
Run Code Online (Sandbox Code Playgroud)
给定训练数据(观察到的词和响应变量),除了每个文档的主题比例(theta)之外,我们还可以学习全局主题(beta)和回归系数(eta)来预测响应变量(Y)。为了在给定学习到的 beta 和 eta 的情况下对 Y 进行预测,我们可以定义一个不观察 Y 的新模型,并使用之前学习的 beta 和 eta 获得以下结果:
在这里,我们为测试语料库预测了正面评价(在 -2 到 2 之间给出了大约 2 个评价),测试语料库由一个句子组成:“这是一篇非常正面的评价,很棒的电影”,如后验直方图的模式所示对。有关完整的实现,请参阅ipython notebook。