Calcolo rapido della distanza Levenshtein


24

Dato un enorme database di parole consentite (in ordine alfabetico) e una parola, trova la parola dal database più vicina alla parola data in termini di distanza di Levenshtein.

L'approccio ingenuo è, ovviamente, semplicemente calcolare la distanza di levenshtein tra la parola data e tutte le parole del dizionario (possiamo fare una ricerca binaria nel database prima di calcolare effettivamente le distanze).

Mi chiedo se esiste una soluzione più efficiente a questo problema. Forse un po 'euristico che ci consente di ridurre il numero di parole da cercare, o ottimizzazioni dell'algoritmo di distanza Levenshtein.

Collegamenti a documenti sull'argomento benvenuto.

Risposte:


16

Quello che ti stai chiedendo è il problema della ricerca del vicino vicino alla distanza di modifica. Non hai detto se sei interessato a risultati teorici o euristici, quindi risponderò al primo.

La distanza di modifica è piuttosto sgradevole da gestire per la costruzione di strutture di ricerca vicine. Il problema principale è che, come metrica, si comporta (in qualche modo) come altre metriche negative ben note come ai fini della riduzione e dell'approssimazione della dimensionalità. C'è un vasto lavoro da leggere su questo argomento, e la tua migliore fonte è il set di articoli di Alex Andoni : seguendo i puntatori all'indietro (ad esempio dal suo documento FOCS 2010) otterrai una buona serie di fonti.1


1
Tutto quello che so sugli spazi metrici proviene dalla semantica, quindi una domanda: ci sono incorporamenti decenti (per qualsiasi valore di decenti) della metrica di Levenshtein in un ultrametrico? A parte, ciò potrebbe dare origine all'algoritmo binary-tree-ish.
Neel Krishnaswami,

Non ne sono del tutto sicuro. Sospetto che la risposta sia no in generale, ma non ho nulla da indicare.
Suresh Venkat,

Il secondo documento su boytsov.info/pubs è una buona rassegna delle possibili soluzioni per la ricerca del vicino vicino sotto la distanza di modifica di Levenshtein e Damereau-Levenshtein.
a3nm,

@NeelKrishnaswami Un incorporamento in un ultrametrico avrebbe una distorsione di almeno dove d è la lunghezza della stringa. Ciò deriva da una distorsione inferiore al limite per l'incorporamento in L 1 dovuta a Krauthgamer e Rabani , poiché l'ultrametria si incorpora isometricamente nello spazio euclideo, che si inserisce isometricamente in L 1 . Ω(logd)dL1L1
Sasho Nikolov,


5

Se hai un numero limitato di modifiche errate che intendi tollerare, puoi provare a utilizzare un albero di suffissi punteggiato . Disclaimer: ho scritto quel documento, ma risolve quello che vuoi: ha un alto costo dello spazio su disco, ma le query sono molto veloci.

In generale, è meglio guardarlo al contrario: hai un indice di tutte le parole nel dizionario. Ora, per una parola di input w, se si trova nel dizionario, fermarsi. Altrimenti, genera tutte le variazioni alla distanza 1 e cerca quelle. Se non ci sono, cerca le variazioni alla distanza 2 e così via ...

Ci sono molti miglioramenti a questa idea di base.


1
Avresti dovuto includere un link al tuo archivio di ricerca riproducibile per il documento .
Dan D.

4

O(mk+1σk)mσk


4

Ho scritto una risposta a una domanda molto simile su cs.stackexchange.com ( /cs//a/2096/1490 ) e poi ho trovato questa domanda. La risposta è per la ricerca approssimata del vicino vicino nella distanza di modifica (cioè l'algoritmo genera una stringa che è approssimativamente più vicina alla stringa della query del vicino più vicino della stringa della query). Sto postando qui poiché non trovo nessuno dei riferimenti che ho dato lì nelle risposte fornite qui.



2

Puoi usare Intendevi?

E poi trova la distanza di Levenshtein tra la risposta restituita da "Intendevi" "e inserisci la stringa usando la Programmazione dinamica.


Non capisco questa risposta. La domanda si pone come si possa trovare in modo efficiente una parola in un grande dizionario con una distanza Levenshtein vicina a un dato input, non su come calcolare la distanza Levenshtein o sul confronto con l'output di un controllo ortografico black box ...
Huck Bennett

@Huck Bennett: pensavo che @Grigory Javadyan stesse costruendo Did you mean?funzionalità. Inoltre Did you mean?restituisce la parola che è molto vicina all'input dato e lo fa in modo abbastanza efficiente. :)
Pratik Deoghare

Penso che le tue idee siano buone, ma sembra che Grigory stia chiedendo qualcosa di più profondo e più specifico.
Huck Bennett,

@Huck Bennett: Sì, hai ragione! :)
Pratik Deoghare

-1

Un modo è addestrare un modello di apprendimento automatico per mappare le parole ai vettori e mappare la distanza di levenshtein alla distanza euclidea. Quindi è possibile creare un KDTree dai vettori per il dizionario che si desidera utilizzare. Ho creato un notebook jupyter che fa questo qui: https://gist.github.com/MichaelSnowden/9b8b1e662c98c514d571f4d5c20c3a03

Secondo i commenti di DW:

  1. procedura di allenamento = discesa gradiente stocastica con gradienti adattativi
  2. funzione di perdita = errore quadratico medio tra la distanza di modifica reale e la distanza euclidea
  3. dati di allenamento = stringhe casuali comprese tra 1 e 32 caratteri (potrebbero essere migliorate con dati che corrispondono a una distribuzione effettiva di errori di battitura comuni)
  4. risultati quantitativi: dopo l'allenamento per circa 150 epoche con una dimensione del lotto di 2048 (tempo di parete = circa un minuto), usando incorporamenti di parole di 512 dimensioni, con un livello nascosto, l'errore assoluto medio tra la distanza di modifica reale e la distanza di modifica prevista si trova a circa 0,75, il che significa che la distanza di modifica prevista è di circa un carattere

Riepilogo della struttura del modello:

  1. Crea un incorporamento appreso per ogni carattere, incluso il carattere null (utilizzato in seguito per il pad del testo destro sotto il limite di caratteri)
  2. Riempi il lato destro del testo con il carattere null fino a raggiungere il limite di caratteri (32)
  3. Concatena questi matrimoni
  4. Esegui gli incorporamenti attraverso una rete neurale feed-forward per produrre un incorporamento di parole di dimensione inferiore (512-dimensionale)
  5. Fallo per entrambe le parole
  6. Trova la distanza euclidea tra i vettori
  7. Imposta la perdita come errore quadratico medio tra la distanza reale di Levenshtein e la distanza euclidea

I miei dati di allenamento sono solo stringhe casuali, ma penso che i risultati potrebbero davvero migliorare se i dati di allenamento fossero (errori di battitura / parola corretta). Ho finito per usare solo /usr/share/dict/wordsperché è comunemente disponibile.


2
Come si allena un modello ML in modo che le parole che si trovano nelle vicinanze della distanza Levenshtein mappino a vettori simili? Quale procedura di allenamento e funzione di perdita usi per questo? Puoi riassumere il metodo nella tua risposta, in modo che la risposta sia ancora utile anche se il collegamento smette di funzionare e in modo che non dobbiamo scavare attraverso il tuo taccuino per capire il metodo che stai utilizzando? Inoltre, puoi valutare quanto funziona in modo quantitativo? È meglio delle alternative?
DW

Allo stato attuale, questa è (penso) una scelta inadeguata per CSTheory. Cioè, nessuna idea di ciò che è specificamente suggerito e nessuna giustificazione teorica per questo.
Clemente C.

@DW Siamo spiacenti, ho apportato una modifica piuttosto sostanziale che dovrebbe essere completa in caso di interruzione del collegamento (o nel caso in cui non si desideri scorrere il blocco note). Sebbene questa non sia in realtà una teoria CS perché non è una ricerca, penso che sia un approccio pratico perché è veloce e facile sia per la formazione che per l'inferenza.
michaelsnowden,

1
Ti stai allenando su stringhe casuali. La distanza prevista di Levenshtein tra due di queste stringhe sarà approssimativamente la lunghezza della corda più lunga. Pertanto, è molto facile stimare questa distanza su stringhe casuali, ma non è utile per gestire i dati del mondo reale. Sospetto che i tuoi incorporamenti potrebbero semplicemente codificare la lunghezza della stringa, e quindi potresti aver creato un modo elegante per fare qualcosa di banale e inutile. Questo è un problema con l'utilizzo di ML; è molto sensibile alla funzione di perdita che usi.
DW,

@DW Se si osservano i risultati nel notebook, il recupero ha restituito risultati decenti, non solo stringhe della stessa lunghezza. Ti incoraggio davvero a scremarlo. Non lo definirei banale e inutile.
michaelsnowden,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.