豪鬼メモ

一瞬千撃

英和辞書の曖昧一致検索と類語検索

オープンなデータで英和辞書と和英辞書を構築して検索する連載の5回目である。今回は、曖昧一致検索も含めた複雑なパターン一致検索を実装し、さらに類語検索も実装する。曖昧一致検索と類語検索は、辞書の利便性を飛躍的に高めてくれる。いつものデモサイトにそれらを実装しておいたので、実際に試してみてほしい。オープンなデータでできる範囲では、最善の英和・和英辞書が実現できていると思う。
f:id:fridaynight:20200925093414p:plain


今回の改修により、以下の検索モードを選択できるようになった。

  • 英和 完全一致 : 英和辞書の見出し語を検索語の完全一致で検索する。
  • 和英 完全一致 : 語義の日本語の索引を検索語の完全一致で検索する。
    • e.g.: "りんご" -> "apple"
  • 英和 類語 : 英和辞書の見出し語を類語展開して検索する。
    • e.g.: "apple" -> "apple", "pome", "orange", "pome", "fluit"
  • 和英 類語 : 語義の日本語の索引を類語展開して検索する。
    • e.g.: "りんご" -> "apple", "pome", "orange", "pome", "fluit"
  • 英和 前方一致 : 英和辞書の見出し語を検索語の前方一致で検索する。
  • 和英 前方一致 : 語義の日本語の索引を検索語の前方一致で検索する。
    • e.g.: "りんご" -> "apple", "apple candy" (りんご飴), "malic" (りんご酸)
  • 英和 後方一致 : 英和辞書の見出し語を検索語の後方一致で検索する。
    • e.g.: "apple" -> "apple", "grapple", "pineapple"
  • 和英 後方一致 : 語義の日本語の索引を検索語の後方一致で検索する。
    • e.g.: "イモ" -> "taro" (タロイモ), "potato" (ジャガイモ)
  • 英和 中間一致 : 英和辞書の見出し語を検索語の中間一致で検索する。
    • e.g.: "mist" -> "chemistry", "mistake", "economist"
  • 和英 中間一致 : 語義の日本語の索引を検索語の中間一致で検索する。
    • e.g.: "mist" -> "chemistry", "mistake", "economist"
  • 英和 単語一致 : 英和辞書の見出し語を検索語の単語一致で検索する。
    • e.g.: "go" -> "go", "go on", "go for", "go to", "go by"
  • 英和 曖昧一致 : 英和辞書の見出し語を検索語の曖昧一致で検索する。
    • e.g.: "coocurence" -> "concurrence", "co-occurrence"
  • 和英 曖昧一致 : 語義の日本語の索引を検索語の曖昧一致で検索する。

英和の前方一致検索は、長い語の最初の何文字かだけを入れて検索できるので便利だ。「misc」で「mischellaneous」が探せる。英和の単語一致検索は、熟語を探すのに便利だ。例えば「go」を含む熟語の一覧を得ることができる。英和と和英の曖昧検索は、英単語のスペルや複雑なカタカナ語の正則表記がうろ覚えでも探せるので便利だ。「miscellaneous」とかの長ったらしい語はミスしがちなので、適当にそれっぽい綴りを入れて検索できると楽だ。そして、英和と和英の類語検索は、英作文の際に似た言葉の一覧が見られて便利だ。


完全一致検索と類語検索以外の検索モードでは、英和辞書本体や和英索引のデータベースからキーだけを抜き出したテキストファイルを準備しておくことで効率的に処理を行なっている。英和辞書本体をスキャンすると120MBのファイル全体に対してシーケンシャルアクセスを行うことになるが、キーだけのファイルをスキャンするなら2MBで済むので高速だ。前方一致や後方一致に関してはインデックスを使うとさらに高速化できるだろうが、17万件の2MB程度なら全体をスキャンしてもミリ秒単位で終わるのでそれで良しとする。どっちみち、最もよく使う曖昧一致検索ではインデックスは使えないし。テキストファイルに対するフィルタ処理はDBMの機能に含まれている。つまり、ファイルの入出力や文字列の一致検査はC++での実装に任せるので、高速に動作する。

キーのリストを抽出する際には、アルファベット順ではなく、重要度順にソートしておく。そうすると、検索時には、単に上から下まで判定処理を行なって、十分な該当数が溜まったところで処理を終了させ、結果として最も重要な語をユーザに提示することができる。重要度はその見出し語がコーパスにおいて出現する頻度を元に計算する。つまり、よく使われる語ほど重要ということだ。

曖昧検索とは、入力された文字列に似た文字列の辞書エントリを探す機能だ。文字列が似ているかどうかはレーベンシュタイン編集距離で測る。つまり、ある文字列を別の文字列に加工するために、文字の「挿入」「削除」「置換」の操作を何回行えば良いかという尺度だ。辞書内の全ての見出し語に対して編集距離を測り、それが小さい順にソートして上位何件かを表示する。これは実用的な英和辞書としてぜひとも欲しい機能である。我々英語学習者にとって、英単語のスペルミスや覚え違いはつきものだからだ。「cooccurrence」なんて、いつまで経っても間違うよね。曖昧検索は和英辞書として利用する際にも便利だ。「バイオリン」と「ヴァイオリン」などの表記揺れを吸収して検索できるからだ。曖昧検索の結果の順序は編集距離が小さい順になるのだが、編集距離が同じ語の間の順位は入力ファイル内の順序を継承するようにしているので、したがって頻出語が先に提示されるようになる。

ついでに、屈折検索も実装した。屈折(=インフレクション)とは、同一の語が文法上の役割に応じて品詞や基本的な意味を変えずに語形変化する現象である。英語では、名詞の複数形、動詞の三人称単数現在形・現在分詞・過去形・過去分詞、形容詞・副詞の比較級・最上級の変化が屈折にあたる。通常、意味や品詞まで変化した派生語(publicに対するpublishとか)は辞書では別の語として収録されるが、屈折形は同一の語の変化形という範疇なので、別の語としては収録されない。bestとかhiddenとかの頻出語は独立して収録されていたりもするが、割合は大きくない。英文読解の際に辞書を用いる場合、今調べようとしている語の原型がわからない場合や、そもそもその語の品詞すらわからない場合もあるので、屈折形のままを入力して検索したい。それを実現するのが屈折検索だ。「ran」で検索して「run」を調べられるということだ。屈折検索を実現するにあたっては、屈折形から原型を調べるための専用の索引を作る必要がある。各語の屈折形の情報はWiktionaryから抽出して辞書本体に付与してあるので、あとはそれを転置して索引のDBMにすればよい。

デフォルトのオート検索モードでは、まずは検索語の完全一致で検索を行い、結果が該当なしの場合には自動的に曖昧検索に移行する。入力語が屈折形である場合には、その原型の語も同時に提示される。そうすれば、ほとんどのケースで、わざわざモードを設定することなく検索操作が完了する。


類語検索とは、入力語に似た意味を持つ辞書エントリを探す機能だ。曖昧検索が文字列の字面が似ているものを探すのと対照的に、検索語と意味が似ているものを探すのだ。例えば「big」と入力すると「large」「great」「major」といった語を探すことができる。それを実現するために、英和辞書本体に類語の情報を統合している。つまり、「big」の辞書エントリに類語として「great」や「major」が記述されているということだ。和英の類語検索の場合、まず和英の索引を調べて英単語のリストを得てから、該当する英単語のリストを起点として類語検索を行う。

和英辞書として使う場合、訳語の選択ぶれを吸収できることが重要だ。「enormous」の訳語は「巨大な」かもしれないし「大規模な」かもしれないし「非常に大きい」かもしれないが、そのいずれでも検索できた方が便利だ。もっと言えば単純に「大きい」で検索できると楽だ。「大きい」で和英索引を引いて「big」が該当し、その類語として「enormous」に到達できれば目的が達成できる。

Wiktionaryの英語版および日本語版から抽出した類語と、WordNetから抽出した類語を、辞書本体の各エントリに追記しておく。WiktionaryでもWordNetでも、各英単語に関連づけて、同義語語(synonym)、上位語(hypernym)、下位語(hyponym)、対義語(antonym)、派生語(derivation)などが記録されている。それらの各々に適当に重み付けをして並び替えた上位の語を類語とみなす。

各英単語に類語が登録されている構造は、有向グラフ構造とみなすことができる。各語をノードとみなし、その類語関係をエッジとみなす。さらに、すでに調べたノードを重複して見ないようにすることで、木の探索として処理することができるようになる。具体的には、検索語のノードを起点として、最大100ステップくらいの幅優先探索を行う。

探索の結果として、100語くらいの類語が得られる。それらを類似度順に並べたい。何との類似度かというと、検索語に完全一致する語との類似度である。「big」が検索語であれば「big」との類似度を考えるべきだし、「大きい」が検索語であれば、それに該当する「big」や「large」の特徴を合成したものとの類似度を考えるべきだ。そのために、各単語の類語と翻訳語を特徴量とみなし、順位を重みとしたbag-of-wordsのベクトルの内角のコサインを類似度とみなす。例えば「big」の類語として「large」と「enormous」があり、またその翻訳語として「大きい」「でかい」「重要な」があると仮定すると、その特徴量として {"big": 1.0, "large": 0.9, "enormous": 0.8, "大きい": 1.0, "でかい": 0.9, "重要な": 0.8} といったベクトルを作ることができる。同じことを検索語に完全一致する全ての語に行い、それを加算したベクトルを作る。あとはそのラベル空間で各々の類語の特徴量を表せば、統一した基準でコサイン距離を測ることができる。

実際に「大きい」の検索結果を見ていただきたい。たとえ「大きい」という訳語が登録されていなくても、文脈によっては「大きい」と訳せそうな語が網羅的に取得できている。このような再現率重視の挙動は英作文をする時に役に立つ。


まとめ。曖昧検索と類語検索が実装できたことで、「俺の考える最強の辞書検索システム」としての基本的な機能は揃った。辞書データの質を上げたりUIを改良したりする余地はまだまだあるが、自分が常用する辞書として使えるレベルにはなってきたかなと思う。上に挙げたデモサイトは実際に私が使うものとして設置しておくので、これを読んだ皆様もよろしければ日常使いしていただいて構わない。データやシステムに不具合があればご報告いただけると嬉しい。

類語検索に関してはもうちょっと掘り下げたい感じがしている。「上司みたいに偉そうに振る舞う様」を英語で「bossy」というのだが、それには「横暴」という訳語しか付いていない。それを「偉そう」で検索して到達できるようにするには、もう少し工夫が必要だ。同様に、「dash」には「疾走」などの訳語はついているが、「走る」で類語検索しても100番目までに入らないのが現状だ。共起語データベースによる重み付けではこれは改善できないことがわかったので、もうちょい賢い何かを考えねばならない。

さらに言えば、「担当者」や「責任者」が「a person in charge」や「people in charge」で表されるというのも拾いたいのだが、辞書データとしては「in charge」の英文説明がWiktionary英語版にあるだけで、訳語も類語も付与されていない。「charge」の訳語に「担当」「任務」があるので、「責任者」の同義語として「担当者」を拾って、その類語である「担当」から「charge」を拾って、その熟語である「in charge」や「person in charge」を導くみたいなことは不可能ではないだろうが、あまり現実的ではない。英辞郎だと「in charge」の訳語に「担当して」「責任者で」とかがあるので訳語の曖昧一致検索で拾えるのだが、オープンなデータだけだとなかなか難しい。ここまで来ると機械翻訳っぽい仕事になってくるので、そういったサービスを使う方が早いのだけど。