Je suis en train de normaliser le message clinique (vérification orthographique) dans lequel je vérifie chaque mot donné par rapport au dictionnaire médical 900 000 mots. Je suis plus préoccupé par la complexité du temps/performance.
Je veux faire une comparaison de chaîne floue, mais je ne suis pas sûr de la bibliothèque à utiliser.
Option 1:
import Levenshtein
Levenshtein.ratio('hello world', 'hello')
Result: 0.625
Option 2:
import difflib
difflib.SequenceMatcher(None, 'hello world', 'hello').ratio()
Result: 0.625
Dans cet exemple, les deux donnent la même réponse. Pensez-vous que les deux fonctionnent de la même manière dans ce cas?
Si vous souhaitez une comparaison visuelle rapide de la similarité Levenshtein et Difflib, j'ai calculé les deux pour environ 2,3 millions de titres de livres:
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
J'ai ensuite tracé les résultats avec R:
Strictement pour les curieux, j'ai également comparé les valeurs de similarité de Difflib, Levenshtein, Sørensen et Jaccard:
library(ggplot2)
require(GGally)
difflib <- read.table("similarity_measures.txt", sep = " ")
colnames(difflib) <- c("difflib", "levenshtein", "sorensen", "jaccard")
ggpairs(difflib)
Résultat:
La similitude Difflib/Levenshtein est vraiment très intéressante.
Édition 2018: Si vous travaillez à identifier des chaînes similaires, vous pouvez également vérifier minhashing - il y a un très bon aperçu ici . Minhashing est étonnant de trouver des similitudes dans les grandes collections de textes en temps linéaire. Mon laboratoire a mis au point une application qui détecte et visualise la réutilisation du texte à l'aide de minhashing ici: https://github.com/YaleDHLab/intertext
difflib.SequenceMatcher utilise l'algorithme Ratcliff/Obershelp . Il calcule le nombre doublé de caractères correspondants divisé par le nombre total de caractères des deux chaînes.
Levenshtein utilise algorithme de Levenshtein il calcule le nombre minimal de modifications nécessaires pour transformer une chaîne en une autre
Complexité
SequenceMatcher est un temps quadratique pour le cas le plus défavorable et a un comportement de cas attendu qui dépend de manière compliquée du nombre d'éléments communs aux séquences. ( à partir d'ici )
Levenshtein est O (m * n), où n et m sont la longueur des deux chaînes en entrée.
Performance
Selon le code source du module Levenshtein: Levenshtein a un certain chevauchement avec difflib (SequenceMatcher). Il ne supporte que les chaînes, pas les types de séquence arbitraires, mais par contre c'est beaucoup plus rapide.