Antwort

10

Für das, was es wert ist, LDA als Klassifizierer ziemlich schwach sein wird, weil es sich um ein generatives Modell ist, und Klassifikation ist ein diskriminativen Problem. Es gibt eine Variante der LDA mit dem Namen supervised LDA, die ein diskriminativeres Kriterium zur Bildung der Themen verwendet (Sie können die Quelle dafür an verschiedenen Stellen erhalten), und es gibt auch eine Veröffentlichung mit einer max margin Formulierung, die den Status der Quelle nicht kennt. Code-weise. Ich würde die Labelled-LDA-Formulierung vermeiden, wenn Sie nicht sicher sind, dass Sie das wollen, weil sie eine starke Annahme über die Übereinstimmung zwischen Themen und Kategorien im Klassifizierungsproblem macht.

Es ist jedoch erwähnenswert, dass keine dieser Methoden das Topic-Modell direkt für die Klassifizierung verwendet. Stattdessen verwenden sie Dokumente, und anstatt wordbasierte Funktionen zu verwenden, verwenden Sie die Rückseite über die Themen (der Vektor, der aus der Inferenz für das Dokument resultiert) als Feature-Repräsentation, bevor Sie sie einem Klassifizierer, normalerweise einer linearen SVM, zuführen. Dadurch erhalten Sie eine auf dem Thema Modell basierende Reduzierung der Dimensionalität, gefolgt von einem starken diskriminierenden Klassifikator, was wahrscheinlich auch Ihr Ziel ist. Diese Pipeline ist in den meisten Sprachen mit den beliebten Toolkits verfügbar.

+0

Der andere und neuere Ansatz, der sich zu untersuchen lohnt, ist die partiell beschriftete LDA. [link] (http://research.microsoft.com/en-us/um/people/sdumais/kdd2011-pldp-final.pdf) Es entspannt die Anforderung, dass jedes Dokument im Trainingssatz ein Label haben muss. – metaforge

3

Ja können Sie den markierten LDA im Parser an der Stanford versuchen http://nlp.stanford.edu/software/tmt/tmt-0.4/

+1

Danke, ich werde mir das ansehen! Weißt du, ob es eine C/C++/Python-Implementierung von l-LDA gibt? –

+0

Leider habe ich Ihre Nachricht zunächst nicht gesehen. Ich bin mir einer c/python-Implementierung nicht bewusst, aber ich habe nicht vorher gesehen. Ich weiß, dass Biel (LDA-Autor) normalerweise seinen Code (C/C++) auf seiner persönlichen Website veröffentlicht, also würde ich das überprüfen. – Steve

+0

Das Problem bei diesem Ansatz besteht darin, dass ein Label benötigt wird, um 1: 1 mit einem Thema zu vergleichen, daher ist es sehr restriktiv. – metaforge

3

Sie implementieren können LDA überwacht mit PyMC, den Metropolis-Sampler verwendet die latenten Variablen in dem folgende grafischen Modell zu lernen: sLDA graphical model

Der Trainingskorpus besteht aus 10 Filmkritiken (5 positiven und 5 negativ) entlang mit der zugehörigen Sternbewertung für jedes Dokument. Die Sternbewertung ist als eine Antwortvariable bekannt, bei der es sich um eine Menge von Interesse handelt, die jedem Dokument zugeordnet ist. Die Dokumente und Antwortvariablen werden gemeinsam modelliert, um latente Themen zu finden, die die Antwortvariablen für zukünftige unmarkierte Dokumente am besten vorhersagen. Weitere Informationen finden Sie unter original paper. Betrachten Sie den folgenden Code ein:

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

die Trainingsdaten (beobachtete Worte und Antwortvariablen) Da können wir die globalen Themen (beta) und Regressionskoeffizienten (eta) zur Vorhersage der Reaktion Größe (Y) zusätzlich lernen zu den Proportionen für jedes Dokument (Theta). Um Vorhersagen von Y gegeben der gelernte Beta und eta zu machen, können wir ein neues Modell definieren, wo wir beobachten Y nicht und verwenden Sie die zuvor gelernten Beta und eta das folgende Ergebnis zu erhalten:

sLDA prediction

Hier haben wir für den Testkorpus eine positive Bewertung (ca. 2 Bewertungspunkte von -2 bis 2) aus einem Satz vorhergesagt: "Das ist eine wirklich positive Bewertung, toller Film", wie der Modus des posterioren Histogramms am Recht. Eine vollständige Implementierung finden Sie unter ipython notebook.

+0

Hi @ vadim-smolyakov, unterscheidet sich das von Multinomial Naive Bayes? – laguittemh

+0

Ja, der Zweck von sLDA ist es, globale Themen und lokale Dokumentpunktzahl (z. B. Filmbewertung) gleichzeitig zu lernen, während Multinomial Naive Bayes mehr auf Klassifizierung konzentriert. Beide Modelle benötigen eine Überwachung (Score für sLDA und Klassenlabel für MNB). Ich habe eine Analyse für Bernoulli NB gemacht, die hier vielleicht hilfreich ist: https://github.com/vsmolyakov/experiments_with_python/blob/master/chp01/info_planning.ipynb –

Verwandte Themen