2014-12-14 21 views

risposta

2

Radim ha appena pubblicato un tutorial sulle caratteristiche di doc2vec di gensim (ieri, credo, la tua domanda è tempestiva!).

Gensim supporta il caricamento di vettori pre-formati da the C implementation, come descritto in the gensim models.word2vec API documentation.

+1

Grazie Aaron .. Effettivamente domanda tempestiva :) Questo è scritto nel tutorial: "... se vuoi solo imparare le rappresentazioni per le etichette e lasciare le rappresentazioni di parole fisse, il modello ha anche la bandiera train_words = False" .. So che è possibile utilizzare vettori pre-formati per word2vec. La domanda è: come posso chiamare doc2vec con quei vettori pre-addestrati? – Stergios

+1

@Stergios: Forse sto fraintendendo la domanda (e sto ancora inciampando in questo io stesso). Ma sembra che l'inferenza non sia ancora implementata - vedi https://groups.google.com/forum/#!topic/gensim/EFy1f0QwkKI. Per fortuna, ci sono almeno un paio di persone che ci lavorano attivamente. Immagino che la sequenza sarà simile a 1) Caricare vettori pre-addestrati; 2) Crea un vettore per la tua frase non vista con una nuova etichetta; 3) Chiama most_similar ("NEW_LABEL"). In alternativa, crea i vettori per più frasi invisibili e calcola le distanze tra quei vettori. Ma questa è solo una supposizione. – AaronD

+1

@AaronD FYI, l'inferenza funziona ora – Renaud

9

Bene, recentemente sto usando anche Doc2Vec. E stavo pensando di usare il risultato LDA come vettore di parole e fissare quei vettori di parole per ottenere un vettore di documenti. Il risultato non è molto interessante però. Forse è solo il mio set di dati non è buono. Il codice è di sotto. Doc2Vec salva insieme vettori di parole e vettori di documenti nel dizionario doc2vecmodel.syn0. Puoi dirigere a cambiare i valori del vettore. L'unico problema potrebbe essere che è necessario scoprire quale posizione in syn0 rappresenta quale parola o documento. I vettori sono memorizzati in ordine casuale nel dizionario syn0.

import logging 
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) 
from gensim import corpora, models, similarities 
import gensim 
from sklearn import svm, metrics 
import numpy 

#Read in texts into div_texts(for LDA and Doc2Vec) 
div_texts = [] 
f = open("clean_ad_nonad.txt") 
lines = f.readlines() 
f.close() 
for line in lines: 
    div_texts.append(line.strip().split(" ")) 

#Set up dictionary and MMcorpus 
dictionary = corpora.Dictionary(div_texts) 
dictionary.save("ad_nonad_lda_deeplearning.dict") 
#dictionary = corpora.Dictionary.load("ad_nonad_lda_deeplearning.dict") 
print dictionary.token2id["junk"] 
corpus = [dictionary.doc2bow(text) for text in div_texts] 
corpora.MmCorpus.serialize("ad_nonad_lda_deeplearning.mm", corpus) 

#LDA training 
id2token = {} 
token2id = dictionary.token2id 
for onemap in dictionary.token2id: 
    id2token[token2id[onemap]] = onemap 
#ldamodel = models.LdaModel(corpus, num_topics = 100, passes = 1000, id2word = id2token) 
#ldamodel.save("ldamodel1000pass.lda") 
#ldamodel = models.LdaModel(corpus, num_topics = 100, id2word = id2token) 
ldamodel = models.LdaModel.load("ldamodel1000pass.lda") 
ldatopics = ldamodel.show_topics(num_topics = 100, num_words = len(dictionary), formatted = False) 
print ldatopics[10][1] 
print ldatopics[10][1][1] 
ldawordindex = {} 
for i in range(len(dictionary)): 
    ldawordindex[ldatopics[0][i][1]] = i 

#Doc2Vec initialize 
sentences = [] 
for i in range(len(div_texts)): 
    string = "SENT_" + str(i) 
    sentence = models.doc2vec.LabeledSentence(div_texts[i], labels = [string]) 
    sentences.append(sentence) 
doc2vecmodel = models.Doc2Vec(sentences, size = 100, window = 5, min_count = 0, dm = 1) 
print "Initial word vector for word junk:" 
print doc2vecmodel["junk"] 

#Replace the word vector with word vectors from LDA 
print len(doc2vecmodel.syn0) 
index2wordcollection = doc2vecmodel.index2word 
print index2wordcollection 
for i in range(len(doc2vecmodel.syn0)): 
    if index2wordcollection[i].startswith("SENT_"): 
     continue 
    wordindex = ldawordindex[index2wordcollection[i]] 
    wordvectorfromlda = [ldatopics[j][wordindex][0] for j in range(100)] 
    doc2vecmodel.syn0[i] = wordvectorfromlda 
#print doc2vecmodel.index2word[26841] 
#doc2vecmodel.syn0[0] = [0 for i in range(100)] 
print "Changed word vector for word junk:" 
print doc2vecmodel["junk"] 

#Train Doc2Vec 
doc2vecmodel.train_words = False 
print "Initial doc vector for 1st document" 
print doc2vecmodel["SENT_0"] 
for i in range(50): 
    print "Round: " + str(i) 
    doc2vecmodel.train(sentences) 
print "Trained doc vector for 1st document" 
print doc2vecmodel["SENT_0"] 

#Using SVM to do classification 
resultlist = [] 
for i in range(4143): 
    string = "SENT_" + str(i) 
    resultlist.append(doc2vecmodel[string]) 
svm_x_train = [] 
for i in range(1000): 
    svm_x_train.append(resultlist[i]) 
for i in range(2210,3210): 
    svm_x_train.append(resultlist[i]) 
print len(svm_x_train) 

svm_x_test = [] 
for i in range(1000,2210): 
    svm_x_test.append(resultlist[i]) 
for i in range(3210,4143): 
    svm_x_test.append(resultlist[i]) 
print len(svm_x_test) 

svm_y_train = numpy.array([0 for i in range(2000)]) 
for i in range(1000,2000): 
    svm_y_train[i] = 1 
print svm_y_train 

svm_y_test = numpy.array([0 for i in range(2143)]) 
for i in range(1210,2143): 
    svm_y_test[i] = 1 
print svm_y_test 


svc = svm.SVC(kernel='linear') 
svc.fit(svm_x_train, svm_y_train) 

expected = svm_y_test 
predicted = svc.predict(svm_x_test) 

print("Classification report for classifier %s:\n%s\n" 
     % (svc, metrics.classification_report(expected, predicted))) 
print("Confusion matrix:\n%s" % metrics.confusion_matrix(expected, predicted)) 

print doc2vecmodel["junk"] 
17

Si noti che il (dm=0) modalità di formazione "DBOW" non richiede o addirittura creare word-vettori come parte della formazione. Apprende semplicemente i vettori di documenti che sono bravi a prevedere ogni parola a turno (proprio come la modalità skip-gram wordv2).

(Prima gensim 0.12.0, c'era il parametro train_words detto in un'altra commento, che qualche documentazione suggerisce saranno parole co-treno. Comunque, io non credo che questo mai realmente funzionato. A partire dal gensim 0.12.0, c'è il parametro dbow_words, che funziona per saltare le parole del treno simultaneamente con i doc-vettori DBOW. Nota che questo rende la formazione più lunga - di un fattore correlato a window. Quindi, se non hai bisogno di vettori di parole, puoi ancora lasciare questo fuori.)

Nel metodo di addestramento "DM" (dm=1), i vettori di parole sono intrinsecamente addestrati durante il processo insieme a doc-vettori e possono anche influire sulla qualità dei doc-vettori. È teoricamente possibile pre-inizializzare i vettori di parole dai dati precedenti. Ma non conosco alcun motivo teorico o sperimentale forte per essere sicuro che ciò migliorerebbe i doc-vettori.

Un esperimento frammentario che ho seguito lungo queste linee ha suggerito che l'addestramento del doc-vector ha avuto un avvio più veloce - migliori qualità predittive dopo i primi passaggi - ma questo vantaggio è sfumato con più passaggi. Se si mantengono costanti i vettori di parole o si lascia che continuino a regolarsi con il nuovo allenamento è probabilmente anche una considerazione importante ... ma quale scelta è migliore può dipendere dagli obiettivi, dal set di dati e dalla qualità/pertinenza dei vettori di parole preesistenti .

(si può ripetere il mio esperimento con il metodo intersect_word2vec_format() disponibile in gensim 0.12.0, e provare diversi livelli del processo vettori precaricati resistente-to-new-formazione attraverso i valori syn0_lockf Ma ricordate questo è un territorio sperimentale:. La base i risultati di doc2vec non si basano o sono necessariamente migliorati con i vettori di parole riutilizzati)

6

This forked version of gensim consente di caricare i vettori di parole pre-formati per la formazione di doc2vec. Here hai un esempio su come usarlo.I vettori di parole devono essere nel formato di testo dello strumento C-word2vec: un vettore di una riga per parola dove prima viene una stringa che rappresenta la parola e quindi valori float separati dallo spazio, uno per ciascuna dimensione dell'incorporazione.

Questa opera appartiene a un paper in cui affermano che l'utilizzo di matrimoni pre-formati aiuta effettivamente a costruire i vettori del documento. Tuttavia sto ottenendo quasi gli stessi risultati, non importa se carico le immersioni pre-addestrate o meno.

Modifica: effettivamente c'è una differenza notevole nei miei esperimenti. Quando ho caricato gli embarghi pre-addestrati, ho addestrato doc2vec per metà delle iterazioni per ottenere lo quasi lo gli stessi risultati (un allenamento più lungo di quello che ha prodotto risultati peggiori nel mio compito).