web-dev-qa-db-ja.com

Pythonでの高性能ファジー文字列比較、Levenshteinまたはdifflibを使用

臨床メッセージの正規化(スペルチェック)を行っており、指定された各Wordを900,000 Wordの医学辞書と照合します。私は、時間の複雑さ/パフォーマンスについてより懸念しています。

あいまいな文字列比較を行いたいのですが、どのライブラリを使用するのかわかりません。

オプション1:

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

Result: 0.625

オプション2:

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

Result: 0.625

この例では、どちらも同じ答えを提供します。この場合、両方とも同じように機能すると思いますか?

115
Maggie

レーベンシュタインとDifflibの類似性をすばやく視覚的に比較したい場合は、両方の書籍タイトルを230万冊で計算しました。

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

次に、結果をRでプロットしました。

enter image description here

好奇心が強い人のために、Difflib、Levenshtein、Sørensen、Jaccardの類似値も比較しました。

library(ggplot2)
require(GGally)

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

ggpairs(difflib)

結果: enter image description here

Difflib/Levenshteinの類似性は本当に興味深いものです。

2018年の編集:同様の文字列の識別に取り組んでいる場合は、minhashingをチェックアウトすることもできます。 素晴らしい概要 があります。 Minhashingは、大規模なテキストコレクションで線形時間で類似性を見つけるのに素晴らしいです。私のラボでは、ここでminhashingを使用してテキストの再利用を検出および視覚化するアプリを作成しました。 https://github.com/YaleDHLab/intertext

133
duhaime
  • difflib.SequenceMatcherは Ratcliff/Obershelp アルゴリズムを使用して、一致する文字の2倍の数を2つの文字列の合計文字数で割った値を計算します。

  • Levenshteinは Levenshteinアルゴリズム を使用して、1つの文字列を他の文字列に変換するために必要な編集の最小数を計算します

複雑さ

SequenceMatcherは、最悪の場合の2次時間であり、シーケンスが共通する要素の数に複雑な方法で依存する期待されるケースの動作を持っています。 ( ここから

レーベンシュタインはO(m * n)です。ここで、nとmは2つの入力文字列の長さです。

パフォーマンス

Levenshteinモジュールの ソースコード によると、Levenshteinはdifflib(SequenceMatcher)と一部重複しています。任意のシーケンス型ではなく、文字列のみをサポートしますが、一方でははるかに高速です。

97