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


127

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

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

オプション1:

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

Result: 0.625

オプション2:

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

Result: 0.625

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

回答:


152

Levenshteinと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を使用して結果をプロットしました。

ここに画像の説明を入力してください

好奇心旺盛な方のために、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)

結果: ここに画像の説明を入力してください

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

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


2
これはすごい!それであなたはこれについてどう思いますか?Levenshteinはタイトルの長さの文字列に適していませんか?
Ulf Aslak 2015年

3
これは、類似性メトリックでキャプチャしようとしている内容に本当に依存します...
duhaime 2015年

2
difflibが使用するオートジャンクヒューリスティックのために、difflibとlevenshteinの不一致の一部が説明されると思います。無効にするとどうなりますか?
マイケル

2
それは良い質問です。autojunkフィルターは、観測数が200を超える場合にのみ有効になるため、この特定のデータセット(本のタイトル)に大きな影響があったかどうかは
わかりませ

2
@duhaime、この詳細な分析に感謝します。私はこれらの種類のプロットに不慣れであり、それらをどのように解釈するかわかりません。私はそれらを調べてそれらについて学ぶことができるように、プロットは何と呼ばれていますか?
Zach Young

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

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

複雑

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

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

パフォーマンス

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


情報をたくさんありがとう。詳細を追加しました。ここにあります: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.この場合、両方が同じように機能すると思いますか?
マギー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.