2012-05-09 11 views
5

Recentemente, ho implementato il campionamento Gibbs per il modello argomento LDA su Python utilizzando numpy, prendendo come riferimento del codice da un sito. In ogni iterazione di campionamento di Gibbs, togliamo una parola (corrente), il campione A nuovo argomento per quella parola secondo una distribuzione a posteriori probabilità condizionale dedotta dal modello LDA e aggiornamento parola argomento conteggi, come segue:Implementazione del modello di argomento con Python (numpy)

for m, doc in enumerate(docs): #m: doc id 
    for n, t in enumerate(doc): #n: id of word inside document, t: id of the word globally 
    # discount counts for word t with associated topic z 
    z = z_m_n[m][n] 
    n_m_z[m][z] -= 1 
    n_z_t[z, t] -= 1 
    n_z[z] -= 1 
    n_m[m] -= 1 

    # sample new topic for multinomial     
    p_z_left = (n_z_t[:, t] + beta)/(n_z + V * beta) 
    p_z_right = (n_m_z[m] + alpha)/(n_m[m] + alpha * K) 
    p_z = p_z_left * p_z_right 
    p_z /= numpy.sum(p_z) 
    new_z = numpy.random.multinomial(1, p_z).argmax() 

    # set z as the new topic and increment counts 
    z_m_n[m][n] = new_z 
    n_m_z[m][new_z] += 1 
    n_z_t[new_z, t] += 1 
    n_z[new_z] += 1 
    n_m[m] += 1 

Nel codice precedente, campioniamo una nuova (singola) z con la funzione scipy multinomiale.

Ora, voglio implementare un modello di Joint Sentiment Topic di this paper. Ora, avrei bisogno le seguenti strutture per tenere traccia dei conti necessari:

3D matrix containing # occurrences for a word for each topic, for each sentiment 
3D matrix containing # occurrences for a topic, for each sentiment, for each document 
2D matrix containing # occurrences for a topic, for each sentiment 
2D matrix containing # occurrences for a sentiment for each document 

E ora viene il problema: in questo campionatore Gibbs, per ogni parola visto in un documento sia un nuovo argomento e un'etichetta sentimento sono ora campionati da una parte posteriore condizionale (equazione 5 pagina 5 del foglio). Come posso "campionare quei 2 valori" in Python ora?

Grazie in anticipo ...

risposta

2

Prova questo. Campionare da una distribuzione congiunta su argomenti e etichette di sentimento significa semplicemente che l'intera matrice T x S deve sommarsi a 1.

docs=[[0,1],[0,0],[1,0,1]] 
D=len(docs) 
z_d_n=[[0 for _ in xrange(len(d))] for d in docs] 
l_d_n=[[0 for _ in xrange(len(d))] for d in docs] 

V=2 
T=2 
S=2 
n_m_j_k=numpy.zeros((V,T,S)) 
n_j_k_d=numpy.zeros((T,S,D)) 
n_j_k=numpy.zeros((T,S)) 
n_k_d=numpy.zeros((S,D)) 
n_d=numpy.zeros((D)) 

beta=.1 
alpha=.1 
gamma=.1 

for d, doc in enumerate(docs): #d: doc id 
    for n, m in enumerate(doc): #i: index of the word inside document, m: id of the word in the vocabulary 
     # j is the topic 
     j = z_d_n[d][n] 
     # k is the sentiment 
     k = l_d_n[d][n] 
     n_m_j_k[m][j][k] += 1 
     n_j_k_d[j][k][d] += 1 
     n_j_k[j][k] += 1 
     n_k_d[k][d] += 1 
     n_d[d] += 1 

for d, doc in enumerate(docs): #d: doc id 
    for n, m in enumerate(doc): #i: index of the word inside document, m: id of the word in the vocabulary 
     # j is the topic 
     j = z_d_n[d][n] 
     # k is the sentiment 
     k = l_d_n[d][n] 
     n_m_j_k[m][j][k] -= 1 
     n_j_k_d[j][k][d] -= 1 
     n_j_k[j][k] -= 1 
     n_k_d[k][d] -= 1 
     n_d[d] -= 1 

     # sample a new topic and sentiment label jointly 
     # T is the number of topics 
     # S is the number of sentiments 
     p_left = (n_m_j_k[m] + beta)/(n_j_k + V * beta) # T x S array 
     p_mid = (n_j_k_d[:,:,d] + alpha)/numpy.tile(n_k_d[:,d] + T * alpha, (T,1)) 
     p_right = numpy.tile(n_k_d[:,d] + gamma,(T,1))/numpy.tile(n_d[d] + S * gamma,(T,S)) 
     p = p_left * p_mid * p_right 
     p /= numpy.sum(p) 
     new_jk = numpy.random.multinomial(1, numpy.reshape(p, (T*S))).argmax() 
     j=new_jk/T 
     k=new_jk%T 

     z_d_n[d][n]=j 
     l_d_n[d][n]=k 
     n_m_j_k[m][j][k] += 1 
     n_j_k[j][k] += 1 
     n_k_d[k][d] += 1 
     n_d[d] += 1 
+0

Cosa fa il primo ciclo 'for'? sembra che tutto ciò che viene fatto nel primo 'for' sia annullato nel secondo. – Netzsooc