web-dev-qa-db-ja.com

どのアルゴリズムがスペルチェッカーで提案を提供しますか?

Wordの提案を伴うスペルチェッカーを実装するときに通常使用されるアルゴリズムは何ですか?

最初に、(辞書に見つからない場合は)入力された新しいWordを辞書内の他のすべてのWordからの Levenshtein distance に対してチェックし、上位の結果を返すことは理にかなっていると思いました。ただし、これは非常に効率が悪く、辞書全体を繰り返し評価する必要があるようです。

これは通常どのように行われますか?

111
Mithrax

Peter Norvigによる優れたエッセイ スペルコレクターの実装方法があります。基本的には、与えられた編集距離で候補文字列を試すブルートフォースアプローチです。 ( ここブルームフィルター および 高速候補ハッシュ を使用してスペル修正プログラムのパフォーマンスを向上させるためのヒントです。)

スペルチェッカーの要件はより弱くなります。 Wordが辞書にないことを知るだけです。 Bloom Filter を使用して、メモリの消費量が少ないスペルチェッカーを構築できます。古代のバージョンは Programming Pearls で英語の辞書に64kbを使用してJon Bentleyによって記述されています。

BK-Tree は代替アプローチです。素敵な記事は こちら です。

レーベンシュシュタインの距離は、スペルチェッカーの正確な編集距離ではありません。挿入、削除、および置換のみを知っています。転置が欠落しており、1文字の転置に対して2が生成されます(1削除および1挿入)。 Damerau–Levenshtein distance は正しい編集距離です。

196
Thomas Jung

私が首尾よく使用したがどこにも記述されていない提案を生成するアプローチは、「悪い」ハッシュ関数を使用して提案を事前に計算することです(辞書を構築するとき)。

アイデアは、人々が犯すスペルミスのタイプを調べ、正しいスペルと同じバケットに誤ったスペルを割り当てるハッシュ関数を設計することです。

たとえば、よくある間違いは、definiteの代わりにdefinateのような間違った母音を使用することです。したがって、すべての母音を同じ文字として扱うハッシュ関数を設計します。それを行う簡単な方法は、最初に入力Wordを「正規化」してから、正規化された結果を通常のハッシュ関数に入力することです。この例では、正規化関数はすべての母音を削除する可能性があるため、definitedfntになります。次に、「正規化された」Wordは、典型的なハッシュ関数でハッシュされます。

この特別なハッシュ関数を使用して、すべての辞書の単語を補助インデックス(ハッシュテーブル)に挿入します。このテーブルのバケットには、ハッシュ関数が「不良」であるため、衝突リストが長くなりますが、これらの衝突リストは基本的に事前計算済みの提案です。

これで、スペルミスのあるWordを見つけると、補助インデックスでスペルミスのマッピング先のバケットの衝突リストを検索します。 Ta da:提案リストがあります!あなたがしなければならないのは、その上の単語をランク付けすることです。

実際には、他のタイプのエラー(転置文字、シングル/ダブルレター、さらには発音のミススペルをキャッチするための単純なSoundexのようなエラー)を処理するために、他のハッシュ関数を備えたいくつかの補助インデックスが必要です。実際、私は単純な発音のものは長い道のりを歩み、些細なタイプミスを見つけるために設計されたもののいくつかを本質的に廃止しました。

したがって、各補助インデックスのスペルミスを検索し、ランキングの前に衝突リストを連結します。

コリジョンリストには、辞書にある単語のみが含まれていることに注意してください。 (Peter Norvigの記事のように)別のスペルを生成しようとするアプローチでは、最初に辞書に対してフィルター処理する必要がある(数万)候補を取得できます。事前に計算されたアプローチでは、おそらく数百の候補者が得られ、それらはすべて正しいスペルであることがわかっているので、ランキングにすぐにスキップできます。

Update:以来、これに似たアルゴリズムの説明を1つ見つけました FAROO Distributed Search 。これはまだ編集距離に制限のある検索ですが、事前計算ステップは私の「悪いハッシュ関数」のアイデアのように機能するため、非常に高速です。 FAROOは、不正なハッシュ関数という限られた概念を使用しています。

17
Adrian McCarthy

アルゴリズム

  1. スペルが間違っているWordを入力として使用します。
  2. 英語の単語のリストとその頻度をテキストファイルに保存します。
  3. 使用可能なすべての英語の単語(テキストファイルに格納されている)とその頻度(英語での単語の使用頻度の測定値)を3項検索ツリーに挿入します。
  4. 次に、三項検索ツリーに沿って移動します-
    • Ternary Search Treeで検出された各単語について、スペルが間違っている単語からのレーベンシュタイン距離を計算します。
    • Levensthein Distance <= 3の場合、Wordを優先度キューに保存します。
    • 2つの単語の編集距離が同じである場合、頻度の高い方がより大きくなります。優先度キューの上位10項目を印刷します。

最適化

  1. 現在のWordからの入力Wordの部分文字列の編集距離が3。よりも大きい場合、現在のノードのサブツリー内の単語を削除できます。
    詳細な説明とソースコードは githubプロジェクト にあります。
7
amarjeetAnand

辞書内の各単語の正確な編集距離を知る必要はありません。制限値に達した後にアルゴリズムを停止し、Wordを除外できます。これにより、計算時間を大幅に節約できます。

3
Petr Peller

スペルチェッカーは、Unixスペルプログラムのように非常に簡単に実装できます。ソースコードは公開されています。修正が含まれる場合があります。1つの手法は、編集を行い、この新しいWordが辞書にあるかどうかを再度確認することです。このような新しい編集はグループ化してユーザーに表示できます。

Unixシステムは、Mc IllRoyによって作成されたプログラムを使用します。別の方法は、巨大なファイルの場合に役立つTrieを使用することです。

UNIXアプローチは、スキャッタハッシュアルゴリズムを使用するため、巨大な辞書に必要なスペースが非常に少なくなります。