Le parole verso i numeri più veloci di ricerca
-
16-10-2019 - |
Domanda
Mi sto allenando un LSTM per l'analisi sentiment su una revisione di dati scaricati da qui . La rassegna di musica insieme di dati contiene circa 150K punti di dati (recensioni di varia lunghezza etichettato pos o neg). Dopo la creazione di un dizionario, sto esecuzione di uno script in Python per sostituire stringhe (parole) con i numeri che keras / Theano incorporerà più tardi.
Il problema è che un grande insieme di dati quali richiede un sacco di tempo per la ricerca. Le sarei grato se qualcuno avesse suggerimento su uno strumento per la ricerca più veloce o simili. Attualmente ho solo scorrere ogni parola del corpus e sostituirlo con il numero corrispondente dal dizionario (codifica 1-calda essenzialmente)
EDIT:
che sto facendo o meno la seguente: ogni lista Python è una frase (prima di tokenizzazione qui):
[ 'nobile', 'interesting_superlatives', ..., 'the_idea']
che voglio conver a un elenco di numeri interi, come:
[143599, 12387, ..., 7582]
ho fatto riferimento ad esso (probabilmente erroneamente) come la codifica di un caldo perché per ogni parola c'è esattamente un numero nel dizionario.
Soluzione
Mi piacerebbe estendere il grande @ risposta di Emre con un altro esempio - ci accingiamo a sostituire tutti parole tokenized del "1984" (c) di George Orwell (120K parole):
In [163]: %paste
import requests
import nltk
import pandas as pd
# source: https://github.com/dwyl/english-words
fn = r'D:\temp\.data\words.txt'
url = 'http://gutenberg.net.au/ebooks01/0100021.txt'
r = requests.get(url)
# read words into Pandas DataFrame
df = pd.read_csv(fn, header=None, names=['word'])
# shuffle DF, so we will have random indexes
df = df.sample(frac=1)
# convert Pandas DF into dictionary: {'word1': unique_number1, 'word2': unique_number2, ...}
lkp = df.reset_index().set_index('word')['index'].to_dict()
# tokenize "1984" (c) George Orwell
words = nltk.tokenize.word_tokenize(r.text)
print('Word Dictionary size: {}'.format(len(lkp)))
print('We have tokenized {} words...'.format(len(words)))
## -- End pasted text --
Word Dictionary size: 354983
We have tokenized 120251 words...
In [164]: %timeit [lkp.get(w, 0) for w in words]
10 loops, best of 3: 66.3 ms per loop
Conclusione: ci sono voluti 66 ms per costruire un elenco di numeri per la lista con 120K parole dal dizionario contenente 354.983 voci
.Altri suggerimenti
Si sta facendo qualcosa di sbagliato. Posso interrogare una parola 100K dict in nanosecondi
word_list = open('/usr/share/dict/words').read().split()
len(word_list)
> 99171
word_dict = {word: hash(word) for word in word_list}
%timeit word_dict['blazing']
> 10000000 loops, best of 3: 33.8 ns per loop
Si potrebbe usare un trie dalla definizione di Wikipedia:
è un tipo di ricerca ad albero di una struttura di dati albero ordinato che viene utilizzata per memorizzare un insieme dinamico o un array associativo in cui le chiavi sono di solito stringhe.
pygtrie offre un'implementazione di tentativi con un'interfaccia dict. Qui va un esempio
import pygtrie as trie
words = ['cat', 'caterpillar', 'dog', 'mouse']
structure = trie.Trie()
for i, word in enumerate(words):
structure[word] = i
print structure['caterpillar']