risposta

10

Per quel che vale, LDA come un classificatore sta per essere abbastanza debole, perché si tratta di un modello generativo, e la classificazione è un problema discriminante. Esiste una variante di LDA denominata supervised LDA che utilizza un criterio più discriminante per formare gli argomenti (è possibile ottenere l'origine per questo in vari punti) e c'è anche un documento con una formulazione max margin che non conosco lo stato di origine- codice-saggio. Eviterei la formulazione LDA etichettata a meno che tu non sia sicuro che sia quello che vuoi, perché fa una forte supposizione sulla corrispondenza tra argomenti e categorie nel problema di classificazione.

Tuttavia, è importante sottolineare che nessuno di questi metodi utilizza direttamente il modello di argomento per eseguire la classificazione. Invece, prendono i documenti e invece di usare le funzionalità basate su parole usano il posteriore sopra gli argomenti (il vettore che risulta dall'inferenza per il documento) come rappresentazione della sua caratteristica prima di inviarlo a un classificatore, di solito un SVM lineare. Questo ti dà una riduzione della dimensionalità basata sul modello di argomento, seguita da un forte classificatore discriminante, che è probabilmente quello che stai cercando. Questa pipeline è disponibile nella maggior parte delle lingue utilizzando i popolari toolkit.

+0

L'altro, e più recente, approccio che potrebbe essere utile esaminare è LDA parzialmente etichettato. [collegamento] (http://research.microsoft.com/en-us/um/people/sdumais/kdd2011-pldp-final.pdf) Rilassa il requisito che ogni documento nel set di addestramento debba avere un'etichetta. – metaforge

3

sì, si può provare il LDA Labeled nel parser di Stanford a http://nlp.stanford.edu/software/tmt/tmt-0.4/

+1

Grazie, vedrò quello! Sai se esiste un'implementazione C/C++/Python di l-LDA? –

+0

Spiacente, non ho visto il tuo messaggio inizialmente. Non sono a conoscenza di un'implementazione c/python ma non l'ho mai vista prima. So che Biel (l'autore della LDA) di solito pubblica il suo codice (C/C++) sul suo sito web personale, quindi lo verificherei. – Steve

+0

Il problema con questo approccio è che richiede un'etichetta per abbinare 1-a-1 con un argomento, quindi è molto restrittiva. – metaforge

3

È possibile implementare supervisione LDA con PyMC che utilizza Metropolis campionatore per imparare le variabili latenti nel seguente modello grafico: sLDA graphical model

Il corpus di formazione è costituito da 10 recensioni di film (5 positivi e 5 negativi) lungo con la valutazione a stelle associata per ciascun documento. La valutazione a stelle è nota come variabile di risposta che è una quantità di interesse associata a ciascun documento. I documenti e le variabili di risposta sono modellati congiuntamente al fine di trovare argomenti latenti che possano predire meglio le variabili di risposta per i futuri documenti senza etichetta. Per ulteriori informazioni, consulta lo original paper. Si consideri il seguente codice:

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

Visti i dati di allenamento (osservate le parole e le variabili di risposta), siamo in grado di imparare i temi globali (Beta) e coefficienti di regressione (ETA) per predire la variabile di risposta (Y) in aggiunta alle proporzioni dell'argomento per ciascun documento (theta). Al fine di fare previsioni di Y dato beta appreso e eta, possiamo definire un nuovo modello in cui non osserviamo Y e utilizziamo il beta precedentemente appreso e eta per ottenere il seguente risultato:

sLDA prediction

Qui abbiamo previsto una recensione positiva (approssimativamente 2 date range di valutazione da -2 a 2) per il corpo del test composto da una frase: "questa è una recensione veramente positiva, ottimo film" come mostrato dalla modalità dell'istogramma posteriore sul destra. Vedere ipython notebook per un'implementazione completa.

+0

Ciao @ vadim-smolyakov, è diverso da Naive Bayes multinomiale? – laguittemh

+0

Sì, lo scopo di sLDA è quello di apprendere simultaneamente argomenti globali e punteggio del documento locale (ad esempio valutazione del film), mentre Multinomial Naive Bayes si concentra maggiormente sulla classificazione. Entrambi i modelli necessitano di supervisione (punteggio per sLDA e etichetta di classe per MNB). Ho fatto alcune analisi per Bernoulli NB, che potrebbe essere utile qui: https://github.com/vsmolyakov/experiments_with_python/blob/master/chp01/info_planning.ipynb –

Problemi correlati