Confronto di stringhe fuzzy ad alte prestazioni in Python, usa Levenshtein o difflib [chiuso]


127

Sto eseguendo la normalizzazione dei messaggi clinici (controllo ortografico) in cui controllo ogni parola data rispetto a un dizionario medico di 900.000 parole. Sono più preoccupato per la complessità / prestazione temporale.

Voglio fare un confronto sfocato delle stringhe, ma non sono sicuro di quale libreria usare.

Opzione 1:

import Levenshtein
Levenshtein.ratio('hello world', 'hello')

Result: 0.625

Opzione 2:

import difflib
difflib.SequenceMatcher(None, 'hello world', 'hello').ratio()

Result: 0.625

In questo esempio entrambi danno la stessa risposta. Pensi che entrambi si esibiscano allo stesso modo in questo caso?

Risposte:


152

Nel caso in cui ti interessi un rapido confronto visivo della somiglianza tra Levenshtein e Difflib, ho calcolato entrambi per ~ 2,3 milioni di titoli di libri:

import codecs, difflib, Levenshtein, distance

with codecs.open("titles.tsv","r","utf-8") as f:
    title_list = f.read().split("\n")[:-1]

    for row in title_list:

        sr      = row.lower().split("\t")

        diffl   = difflib.SequenceMatcher(None, sr[3], sr[4]).ratio()
        lev     = Levenshtein.ratio(sr[3], sr[4]) 
        sor     = 1 - distance.sorensen(sr[3], sr[4])
        jac     = 1 - distance.jaccard(sr[3], sr[4])

        print diffl, lev, sor, jac

Ho quindi tracciato i risultati con R:

inserisci qui la descrizione dell'immagine

Rigorosamente per i curiosi, ho anche confrontato i valori di somiglianza Difflib, Levenshtein, Sørensen e Jaccard:

library(ggplot2)
require(GGally)

difflib <- read.table("similarity_measures.txt", sep = " ")
colnames(difflib) <- c("difflib", "levenshtein", "sorensen", "jaccard")

ggpairs(difflib)

Risultato: inserisci qui la descrizione dell'immagine

La somiglianza con Difflib / Levenshtein è davvero piuttosto interessante.

Modifica del 2018: se stai lavorando per identificare stringhe simili, puoi anche dare un'occhiata al minhashing: qui c'è un'ottima panoramica . Il minhashing è sorprendente nel trovare somiglianze in grandi raccolte di testi in tempo lineare. Il mio laboratorio ha messo insieme un'app che rileva e visualizza il riutilizzo del testo usando minhashing qui: https://github.com/YaleDHLab/intertext


2
Questo è fantastico! Cosa ne pensi di questo allora? Levenshtein è solo male per le stringhe di lunghezza del titolo?
Ulf Aslak,

3
Dipende davvero da cosa stai cercando di catturare nella tua metrica di somiglianza ...
duhaime

2
Penso che parte del disaccordo tra difflib e levenshtein possa essere spiegato a causa dell'euristica autojunk usata da difflib. Cosa succede se lo disabiliti?
Michael,

2
Questa è una buona domanda. Il filtro autojunk ha effetto solo se il numero di osservazioni è> 200, quindi non sono sicuro che questo particolare set di dati (titoli di libri) sarebbe stato fortemente influenzato, ma vale la pena indagare ...
duhaime

2
@duhaime, grazie per questa analisi dettagliata. Sono nuovo di questi tipi di trame e non ho idea di come interpretarli. Come vengono chiamati i grafici, in modo che io possa cercarli e conoscerli?
Zach Young,

104
  • difflib.SequenceMatcher utilizza l' algoritmo Ratcliff / Obershelp che calcola il numero raddoppiato di caratteri corrispondenti diviso per il numero totale di caratteri nelle due stringhe.

  • Levenshtein utilizza l' algoritmo Levenshtein che calcola il numero minimo di modifiche necessarie per trasformare una stringa nell'altra

Complessità

SequenceMatcher è il tempo quadratico per il caso peggiore e il comportamento previsto per il caso dipende in modo complicato da quanti elementi le sequenze hanno in comune. ( da qui )

Levenshtein è O (m * n), dove n e m sono la lunghezza delle due stringhe di input.

Prestazione

Secondo il codice sorgente del modulo Levenshtein: Levenshtein ha una certa sovrapposizione con difflib (SequenceMatcher). Supporta solo stringhe, non tipi di sequenza arbitraria, ma d'altra parte è molto più veloce.


Grazie mille per l'informazione. Ho aggiunto più dettagli. eccolo: I am doing clinical message normalization (spell check) in which I check each given word against 900,000 word medical dictionary. I am more concern about the time complexity/performance.pensi che entrambi si esibiscano allo stesso modo in questo caso.
Maggie,
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.