web-dev-qa-db-ja.com

文字列の類似性に最適なアルゴリズムは何ですか?

私は、アドレスに基づいて、さまざまなWebページ上のコンテンツを一意に識別するプラグインを設計しています。

したがって、次のようなアドレスが1つある場合があります。

1 someawesome street, anytown, F100 211

後で私はこのアドレスを少し異なる形式で見つけるかもしれません。

1 someawesome street, F100 211,

あるいは多分

someawesome street F100

これらは技術的には同じアドレスですが、ある程度の類似性があります。 a)検索を実行するためにアドレスごとに一意の識別子を生成し、b)非常に類似したアドレスが表示されるタイミングを把握したいと思います。

どのアルゴリズム/テクニック/文字列メトリックスを見る必要がありますか?レーベンシュタイン距離は明らかな選択のように思われますが、ここで役立つ他のアプローチがあるかどうか知りたいです。

23
Squiggs.

Levensteinのアルゴリズム は、文字列の挿入、削除、および置換の数に基づいています。

残念ながら、2つの文字の転置である一般的なスペルミスは考慮されていません(たとえば、somesomeawesome vs someaewsome)。したがって、より堅牢な Damerau-Levensteinアルゴリズム を使用します。

文字列の長さを比較すると時間は急激に増加するため、文字列全体に距離を適用するのは良い考えではないと思います。しかし、さらに悪いことに、Zipのような住所コンポーネントが削除されると、完全に異なる住所がよりよく一致する可能性があります( オンラインレーベンシュタイン計算機 を使用して測定):

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)

これらの影響は、ストリート名が短いほど悪化する傾向があります。

したがって、よりスマートなアルゴリズムを使用することをお勧めします。たとえば、 CodeProjectで公開されたArthur Ra​​tz スマートテキスト比較のアルゴリズム。アルゴリズムは距離を出力しません(確かにそれに応じて豊かになる可能性があります)が、テキストブロックの移動(たとえば、最初の例と最後の例の間の町と通りの入れ替えなど)のようないくつかの難しいことを識別します。

そのようなアルゴリズムがあなたのケースに対して一般的すぎる場合は、実際にコンポーネントで作業し、比較可能なコンポーネントのみを比較する必要があります。世界中のアドレス形式を解析したい場合、これは簡単なことではありません。しかし、目標がより具体的である場合、たとえば米国の場合、それは確かに実現可能です。たとえば、「street」、「st。」、「place」、「plazza」、およびそれらの通常のスペルミスは、住所のストリート部分を明らかにする可能性があり、その先頭部分は原則として番号になります。郵便番号は町を見つけるのに役立ちます。あるいは、おそらく住所の最後の要素です。または、推測したくない場合は、都市名のリストを探すことができます(たとえば、無料の郵便番号データベースをダウンロードします)。その後、関連するコンポーネントのみにDamerau-Levenshteinを適用できます。

15
Christophe

レーベンシュタイン距離は言葉にとってより良い

単語のスペルが(主に)正しい場合は、 単語のバッグ を確認します。私は殺しすぎているように見えるかもしれませんが、 TF-IDF および コサイン類似度 です。

または、無料のLuceneを使用することもできます。彼らはコサイン類似性をしていると思います。

2
paparazzo

まず、アドレスのWebページを解析する必要があります。RegExはそのために作成されたものですが、RegExを使用してアドレスを解析することは非常に難しい場合があります。おそらく、潜在的なアドレス指定形式とそれに一致する1つ以上の優れた式のリストを確認する必要があります。私は住所の解析にあまり慣れていませんが、同様の考え方に従ってこの質問を検討することをお勧めします: Freeform Textの一般的な住所パーサー

レーベンシュタイン距離は便利ですが、住所をパーツに分離した後でのみ有効です。以下のアドレスを検討してください。 123 someawesome st.124 someawesome st.これらの住所は完全に異なる場所ですが、レーベンシュタイン距離は1のみです。これは、8th st.9th st.などにも適用できます通常は同じWebページに表示されますが、前代未聞のことではありません。学校のウェブページには、たとえば通りの向こう側にある図書館のアドレスや、教会が数ブロック下にある場合があります。これは、レーベンシュタイン距離が簡単に使用できる唯一のデータが、通りと都市の間の距離など、2つのデータポイント間の距離であることを意味します。

異なるフィールドを分離する方法を理解する限り、アドレス自体を取得すると、それは非常に簡単です。ありがたいことに、ほとんどのアドレスは非常に特殊な形式で提供されます。RegExウィザードを使用すると、それらをさまざまなデータフィールドに分離できるはずです。アドレスが適切にフォーマットされていなくても、希望はまだあります。アドレスは常に(ほぼ)大きさの順序に従います。提供される情報の量とその内容に応じて、住所はこのような線形グリッドのどこかにあるはずです。

StreetNumber < Street < City < State < Country

アドレスが1つのフィールドから隣接していないフィールドにスキップすることはほとんどありません。ストリート、カントリー、ストリートナンバー、シティの順に表示されることはあまりありません。

1
Ucenna

文字列類似性アルゴリズムについて尋ねますが、文字列はアドレスです。 Google Place Search などのLocation APIにアドレスを送信し、formatted_address比較のポイントとして。それが最も正確なアプローチのようです。

APIを介して検索できないアドレス文字列の場合、類似性アルゴリズムにフォールバックできます。

1
Dan Wilson

便利ですが、事前の回答の事前設定されたデータベースが必要な1つの優れたアルゴリズムは、ライン編集距離と呼ばれます。

関数としての行編集距離は、「これらの2つの単語の違い」を返すことができます。

「dogma」や「dog」のような単語の場合、3の値が返されます(追加の3文字)。

または、「猫」と「帽子」の場合、1の値(1つの異なる文字)を返します。

(ソース: https://en.wikipedia.org/wiki/Edit_distance

0
John Greene