2016-03-01 38 views
7

Ho bisogno di addestrare una rappresentazione word2vec sui tweet usando gensim. A differenza della maggior parte dei tutorial e del codice che ho visto su gensim, i miei dati non sono grezzi, ma sono già stati preelaborati. Ho un dizionario in un documento di testo contenente 65k parole (incluso un token "sconosciuto" e un token EOL) e i tweet sono salvati come una matrice numpy con indici in questo dizionario. Un semplice esempio del formato dei dati può essere visto sotto:Gensim word2vec sul dizionario predefinito e dati sugli indici delle parole

dict.txt

you 
love 
this 
code 

tweets (5 è sconosciuta e 6 è EOL)

[[0, 1, 2, 3, 6], 
[3, 5, 5, 1, 6], 
[0, 1, 3, 6, 6]] 

Sono incerto su come dovrei gestire la rappresentazione degli indici. Un modo semplice è solo convertire l'elenco di indici in un elenco di stringhe (cioè [0, 1, 2, 3, 6] -> ['0', '1', '2', '3', '6 ']) mentre lo leggo nel modello word2vec. Tuttavia, questo deve essere inefficiente poiché gensim tenterà quindi di cercare l'indice interno usato per es. '2'.

Come caricare questi dati e creare la rappresentazione word2vec in modo efficiente utilizzando gensim?

risposta

7

Il modo normale per inizializzare un modello Word2Vec in gensim è [1]

model = Word2Vec(sentences, size=100, window=5, min_count=5, workers=4) 

La domanda è: che cosa è sentences? sentences dovrebbe essere un iteratore di iterable di parole/token. È proprio come la matrice numpy che hai, ma ogni riga può avere lunghezze diverse.

Se si consulta la documentazione di gensim.models.word2vec.LineSentence, è possibile caricare i file di testo come frasi direttamente. Come suggerimento, secondo la documentazione, è necessario

una frase = una riga; parole già preelaborate e separate da spazi bianchi.

Quando si dice words already preprocessed, si riferisce al processo di lower-case, arginamento, stopword e tutti gli altri processi di pulizia del testo. Nel tuo caso non vorrai che 5 e 6 siano nella tua lista di frasi, quindi devi filtrarle.

Dato che hai già la matrice numpy, supponendo che ogni riga sia una frase, è meglio quindi gettarla in un array 2d e filtrare tutto 5 e 6. L'array 2d risultante può essere utilizzato direttamente come argomento sentences per inizializzare il modello. L'unico problema è che quando si desidera interrogare il modello dopo l'allenamento, è necessario inserire gli indici anziché i token.

Ora una domanda è se il modello prende direttamente l'intero. Nella versione Python non controlla il tipo e passa semplicemente i token univoci in giro. I tuoi indici unici in quel caso funzioneranno bene. Ma la maggior parte delle volte vorresti usare la routine C-Extended per allenare il tuo modello, il che è un grosso problema perché può dare prestazioni 70 volte. [2] Immagino che in quel caso il codice C possa verificare il tipo di stringa, il che significa che è stata memorizzata una mappatura da stringa a indice.

È inefficiente?Penso di no, perché le stringhe che hai sono numeri, che sono generalmente molto più brevi del vero token che rappresentano (supponendo che siano indici compatti da 0). Pertanto i modelli saranno di dimensioni più ridotte, il che farà risparmiare un po 'di sforzo nella serializzazione e nella deserializzazione del modello alla fine. Essenzialmente hai codificato i token di input in un formato stringa più corto e li hai separati dal training word2vec, e il modello word2vec non ha bisogno di sapere che questa codifica è avvenuta prima dell'allenamento.

La mia filosofia è try the simplest way first. Vorrei solo inserire un campione di input di numeri interi nel modello e vedere cosa può andare storto. Spero che sia d'aiuto.

[1] https://radimrehurek.com/gensim/models/word2vec.html

[2] http://rare-technologies.com/word2vec-in-python-part-two-optimizing/

+0

Posso confermare che non posso semplicemente inserire numeri interi nel modello. Come affermato nel post originale (forse non abbastanza chiaramente), funziona semplicemente mappando gli interi alle stringhe. – pir

+0

Per curiosità, come filtrare '5' e' 6' da una matrice numpy 2D? Ogni riga dovrebbe sempre avere la stessa dimensione. Potrebbe essere fatto quando si itera sulla matrice per fornirlo alla parola 2vec, ma ciò sembra molto inefficiente. – pir

1

Ho avuto lo stesso problema. Anche la conversione in array di stringhe tramite

>>> arr_str = np.char.mod('%d', arr) 

causato un'eccezione durante l'esecuzione Word2Vec:

>>> model = Word2Vec(arr_str) 
ValueError: The truth value of an array with more than one element is ambiguous. 
Use a.any() or a.all() 

La mia soluzione era di scrivere la serie di numeri interi come testo e quindi utilizzare word2vec con LineSentence.

import numpy as np 
from gensim.models import Word2Vec 
from gensim.models.word2vec import LineSentence 

np.savetxt('train_data.txt', arr, delimiter=" ", fmt="%s") 
sentences = LineSentence('train_data.txt') 
model = Word2Vec(sentences)