Odpowiedz

10

Na co warto, LDA jako klasyfikator będzie dość słaba, ponieważ jest to generatywna model i klasyfikacja jest dyskryminacyjna problem. Istnieje wersja LDA o nazwie supervised LDA, która używa bardziej dyskryminującego kryterium do tworzenia tematów (możesz uzyskać w tym celu źródło w różnych miejscach), a także jest papier z formularzem max margin, w którym nie znam stanu źródła. pod względem kodu. Uniknęłabym sformułowania Labelled LDA, chyba że masz pewność, że tego właśnie chcesz, ponieważ zawiera silne założenie o zgodności między tematami i kategoriami w problemie klasyfikacji.

Warto jednak zauważyć, że żadna z tych metod nie wykorzystuje bezpośrednio modelu tematu do klasyfikacji. Zamiast tego biorą dokumenty, a zamiast używać funkcji opartych na słowach, wykorzystują posterior na tematach (wektor, który wynika z wnioskowania o dokumencie) jako reprezentację cech przed przekazaniem go do klasyfikatora, zwykle liniowego SVM. W ten sposób uzyskujesz redukcję wymiarów opartą na modelu tematycznym, a następnie silny klasyfikator dyskryminacyjny, który prawdopodobnie jest tym, na co masz ochotę. Ten potok jest dostępny pod numerem w większości języków przy użyciu popularnych narzędzi.

+0

Innym i nowszym podejściem, które warto rozważyć, jest częściowo oznakowane LDA. [link] (http://research.microsoft.com/en-us/um/people/sdumais/kdd2011-pldp-final.pdf) Rozluźnia wymaganie, aby każdy dokument w zbiorze treningowym miał etykietę. – metaforge

3

Tak można spróbować znakowany LDA w parsera Stanford w http://nlp.stanford.edu/software/tmt/tmt-0.4/

+1

Dzięki, popatrzę na to! Czy wiesz, czy istnieje implementacja L-LDA w C/C++/Pythonie? –

+0

Niestety, początkowo nie widziałem Twojej wiadomości. Nie jestem świadomy implementacji c/Pythona, ale nie wyglądałem wcześniej. Wiem, że Biel (autor LDA) zazwyczaj publikuje swój kod (C/C++) na swojej osobistej stronie internetowej, więc sprawdziłem to. – Steve

+0

Problem z tym podejściem polega na tym, że wymaga ono dopasowania etykiety 1 do 1 z tematem, więc jest bardzo restrykcyjne. – metaforge

3

można zaimplementować nadzorowane LDA z PyMC który używa Metropolis sampler nauczyć zmienne ukryte w poniższym modelu graficznego: sLDA graphical model

Korpus Szkolenie składa się z 10 recenzji filmowych (5 pozytywnych i 5 negatywnych) wraz z przypisaną gwiazdką dla każdego dokumentu. Gwiazdka jest znana jako zmienna odpowiedzi, która jest ilością zainteresowania powiązaną z każdym dokumentem. Dokumenty i zmienne odpowiedzi są modelowane wspólnie, aby znaleźć ukryte tematy, które najlepiej przewidują zmienne odpowiedzi dla przyszłych dokumentów bez etykiety. Aby uzyskać więcej informacji, zapoznaj się z original paper. Rozważmy następujący kod:

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

Biorąc pod uwagę dane treningowe (obserwowane słowa i zmienne Response), możemy dowiedzieć się globalne tematy (beta) i współczynników regresji (ETA) do przewidywania zmiennej odpowiedzi (Y) w uzupełnieniu na temat proporcji dla każdego dokumentu (theta). W celu dokonania prognozy Y podano dowiedział beta i eta, możemy zdefiniować nowy model, w którym nie obserwujemy Y i korzystania z wcześniej nauczył beta i eta aby uzyskać następujący wynik:

sLDA prediction

Przewidywaliśmy pozytywną recenzję (ok. 2 oceny zakresu od 2 do 2) dla korpusu testowego składającego się z jednego zdania: "to naprawdę pozytywna recenzja, świetny film", jak pokazuje tryb tylnego histogramu na dobrze. Aby uzyskać pełną implementację, zobacz ipython notebook.

+0

Hi @ vadim-smolyakov, czy to różni od Multinomial Naive Bayes? – laguittemh

+0

Tak, celem sLDA jest jednoczesne poznanie globalnych tematów i lokalnego wyniku dokumentu (np. Ocena filmu), podczas gdy Multinomial Naive Bayes koncentruje się bardziej na klasyfikacji. Oba modele wymagają nadzoru (punktacja dla sLDA i etykieta klasy dla MNB). Zrobiłem kilka analiz dla Bernoulli NB, który może być pomocny tutaj: https://github.com/vsmolyakov/experiments_with_python/blob/master/chp01/info_planning.ipynb –

Powiązane problemy