Quale algoritmo useresti meglio per la somiglianza delle stringhe?


23

Sto progettando un plug-in per identificare in modo univoco i contenuti su varie pagine Web, in base agli indirizzi.

Quindi potrei avere un indirizzo che assomiglia a:

1 someawesome street, anytown, F100 211

più tardi potrei trovare questo indirizzo in un formato leggermente diverso.

1 someawesome street, F100 211,

o forse vago come

someawesome street F100

Questi sono tecnicamente lo stesso indirizzo, ma con un livello di somiglianza. Vorrei a) generare un identificatore univoco per ciascun indirizzo per eseguire ricerche, e b) capire quando appare un indirizzo molto simile.

Quali algoritmi / tecniche / metriche di stringa dovrei guardare? La distanza di Levenshtein sembra una scelta ovvia, ma curiosa se ci siano altri approcci che si presterebbero qui.


"Levenshtein distance" non è un algoritmo.
gnasher729,

A meno che tu non introduca un po 'di analisi di base, la distanza di Levenstein non sarà così piacevole. Dovresti cercare di identificare almeno le parole che potrebbero essere via, nomi di città, ecc. E quelle che potrebbero essere numeri di strada o codici postali. Quindi forse applicare Levenstein su questi con alcuni fuzzy matcher statistici alimentati da luoghi reali / nomi di strade. Non è una cosa facile :)

7
@gnasher: Ma una funzione che calcola la distanza di Levenshtein è un algoritmo. Senza tale funzione, la distanza di Levenshtein è semplicemente una curiosità intellettuale.
Robert Harvey,

Ho trovato una spiegazione molto pratica con esempi qui: il confronto di Algortihms . In conclusione, raccomandano di usare la somiglianza di Jaro-Winkler poiché l'algoritmo di Levenstein dipende dalla lunghezza della stringa, quindi non è utile fare un confronto.
Sandra Meneses,

Risposte:


14

L'algoritmo di Levenstein si basa sul numero di inserimenti, eliminazioni e sostituzioni nelle stringhe.

Sfortunatamente non tiene conto di un errore ortografico comune che è la trasposizione di 2 caratteri (ad es. Qualcosa di fantastico contro qualcosa di simile). Quindi preferirei l' algoritmo Damerau-Levenstein più robusto .

Non penso sia una buona idea applicare la distanza su intere stringhe perché il tempo aumenta bruscamente con la lunghezza delle stringhe rispetto. Ma peggio ancora, quando vengono rimossi i componenti dell'indirizzo, come ZIP, indirizzi completamente diversi potrebbero corrispondere meglio (misurati usando il calcolatore Levenshtein online ):

1 someawesome street, anytown, F100 211       (reference) 
1 someawesome st.,anytown                     (difference of 15, same address)     
1 otherplaces street,anytown,F100211          (difference of 13, different ddress) 
1 sameawesome street, othertown, CA98200      (difference of 13, different ddress)
anytown, 1 someawesome street                 (28 different same address)
anytown, F100 211, 1 someawesome street       (37 different same address)

Questi effetti tendono a peggiorare per un nome di strada più breve.

Quindi è meglio usare algoritmi più intelligenti. Ad esempio, Arthur Ratz ha pubblicato su CodeProject un algoritmo per il confronto intelligente dei testi. L'algoritmo non stampa una distanza (può certamente essere arricchito di conseguenza), ma identifica alcune cose difficili come lo spostamento di blocchi di testo (ad esempio lo scambio tra città e strada tra il mio primo esempio e il mio ultimo esempio).

Se un tale algoritmo è troppo generale per il tuo caso, dovresti davvero lavorare per componenti e confrontare solo componenti comparabili. Questa non è una cosa facile se vuoi analizzare qualsiasi formato di indirizzo nel mondo. Ma se l'obiettivo è più specifico, diciamo gli Stati Uniti, è certamente fattibile. Ad esempio, "street", "st.", "Place", "plazza" e i loro soliti errori di ortografia potrebbero rivelare la parte della strada dell'indirizzo, la cui parte principale sarebbe in linea di principio il numero. Il codice postale aiuterebbe a localizzare la città, o in alternativa è probabilmente l'ultimo elemento dell'indirizzo, o se non ti piace indovinare, potresti cercare un elenco di nomi di città (ad esempio, scaricare un database di codici postali gratuito). È quindi possibile applicare Damerau-Levenshtein solo sui componenti pertinenti.


Che ne dici di ordinare entrambe le stringhe di confronto prima del confronto? Ho scoperto che questo può aiutare con la trasposizione.
openwonk

2

La distanza di Levenshtein è migliore per le parole

Se le parole sono (principalmente) scritte correttamente, guarda il sacco di parole . Potrei sembrare over kill ma TF-IDF e somiglianza del coseno .

Oppure potresti usare Lucene gratis. Penso che facciano la somiglianza del coseno.


1

In primo luogo, dovresti analizzare la pagina web per gli indirizzi, RegEx è uno scritto da prendere, tuttavia può essere molto difficile analizzare gli indirizzi utilizzando RegEx. Probabilmente finiresti per passare attraverso un elenco di potenziali formati di indirizzamento e una o più espressioni fantastiche che li corrispondono. Non ho troppa familiarità con l'analisi degli indirizzi, ma consiglierei di dare un'occhiata a questa domanda che segue una linea di pensiero simile: Analizzatore di indirizzi generali per testo a mano libera.

La distanza di Levenshtein è utile ma solo dopo aver separato l'indirizzo nelle sue parti. Considera i seguenti indirizzi. 123 someawesome st.e 124 someawesome st.Questi indirizzi sono posizioni totalmente diverse, ma la loro distanza Levenshtein è solo 1. Questo può anche essere applicato a qualcosa di simile 8th st.e 9th st.nomi di strade simili in genere non compaiono sulla stessa pagina web, ma non è inaudito. La pagina web di una scuola potrebbe avere l'indirizzo della biblioteca dall'altra parte della strada, per esempio, o la chiesa a pochi isolati di distanza. Ciò significa che gli unici dati per i quali la distanza di Levenshtein è facilmente utilizzabile è la distanza tra 2 punti dati, come la distanza tra la strada e la città.

Per quanto riguarda capire come separare i diversi campi, è abbastanza semplice una volta ottenuti gli indirizzi stessi. Per fortuna la maggior parte degli indirizzi è disponibile in formati molto specifici, con un po 'di procedura guidata RegEx dovrebbe essere possibile separarli in diversi campi di dati. Anche se l'indirizzo non è formattato bene, c'è ancora qualche speranza. Gli indirizzi seguono sempre (quasi) l'ordine di grandezza. Il tuo indirizzo dovrebbe cadere da qualche parte su una griglia lineare come questa a seconda della quantità di informazioni fornite e di cosa si tratta:

StreetNumber < Street < City < State < Country

Succede raramente, se non altro, che l'indirizzo salta da un campo a uno non adiacente. Non vedrai molto spesso Street, Country o StreetNumber, quindi City.


2
Solo che gli indirizzi non sono regolari e non possono essere analizzati in modo affidabile da espressioni regolari. Certamente non possono essere identificati con precisione se sono solo incorporati nel testo libero. Puoi, ovviamente, scrivere alcune espressioni regolari diverse per abbinare diversi formati comuni, se sai già dove stai cercando.
Inutile

@Useless È vero. In teoria è fattibile, ma ho sottovalutato la quantità di lavoro necessaria per metterlo in pratica. Soprattutto quando sono disponibili opzioni potenzialmente migliori. Ho modificato la mia risposta per riflettere questo.
Ucenna,

1

Ti chiedi degli algoritmi di somiglianza delle stringhe ma le tue stringhe sono indirizzi. Vorrei inviare gli indirizzi a un'API di localizzazione come Google Place Search e utilizzarli formatted_addresscome punto di confronto. Sembra l'approccio più accurato.

Per le stringhe di indirizzi che non possono essere individuate tramite un'API, è possibile ricorrere agli algoritmi di somiglianza.


1
+1 Esternalizzalo in modo da avere il potere degli esperti di fare il lavoro per te. Non deve essere Google in quanto ci sono alcuni fornitori di servizi là fuori. Non perdere tempo a farlo a meno che la corrispondenza degli indirizzi non sia il tuo core business.
LoztInSpace

0

Un algoritmo interessante che è utile ma richiede un database predefinito di risposte precedenti è chiamato: distanza di modifica della linea.

La distanza di modifica della linea, come funzione, può restituire "quanto sono diverse queste due parole".

Una parola come "dogma" e "cane", ti restituirà un valore di 3 (per 3 caratteri extra).

O "gatto" e "cappello", ottieni un valore di 1 (per un personaggio diverso).

(Fonte: https://en.wikipedia.org/wiki/Edit_distance )


2
Qual è il vantaggio rispetto al menzionato Levensthtein dell'OP?
Christophe,

-1

In effetti l'uso di alcune funzioni di distanza sembra un buon approccio. Ma il problema quindi è trovare la stringa più vicina da un determinato indirizzo, che è tutt'altro che banale.

Stai descrivendo una vasta categoria di algoritmi qui. Scopri la ricerca del vicino più vicino

Come indicato in un commento, se trovi un modo per separare i componenti dell'indirizzo (nome della via, numero, ecc.), Il compito sarà molto più semplice.


-1

LongestCommonSubsequence (dal testo comune di Apache) può essere un altro approccio da provare con gli indirizzi. Se si definisce la somiglianza di due come rapporto di " lunghezza di sottosequenza comune / max (lunghezze dell'indirizzo) ", è possibile applicare la soglia di tolleranza, ad esempio 0,8 che definirà la corrispondenza / nessuna corrispondenza. In questo modo ti permetterà di abbinare indirizzi come " 1 someawesome st., Anytown " e " 1 someawesome street., Anytown ".

Non è un algoritmo superveloce, quindi potresti voler applicare failback rapidi per ridurre al minimo i confronti. L'esempio sarebbe: evitare il confronto se i codici postali non corrispondono o se la sequenza delle cifre estratte è diversa.

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.