文字列の類似度を測る(2) 発音に着目する

概要
文字列の表面上の形でなく、発音に注目したい場合に、文字列の類似度をどう測るかについて。具体的には、Soundex と Metaphone という手法を紹介する。

はじめに

前回、文字列の類似度を測る手法として、最小編集距離、なかんずくレーベンシュタイン距離について紹介した。この手法は、表層的な形しか見ていないということに注意することが必要である。言語データの場合、基本的には綴りだけしか見ていないということになる。英語の場合、綴りと音が大きくかけ離れているので、発音がよく似ていても綴りは似ても似つかないということが起こりうる。この場合、発音はよく似ているのに、距離は大きくなってしまうのである。

綴りに着目したい場合もあるが、発音に着目する必要がある場合も当然ある。このような場合、何らかの手法で発音を見える形にする必要がある。英語では、Soundex や Metaphone といったアルゴリズム [1] で、スペルから音に変換することができる。今回はこういった手法について簡単に紹介したい。

発音が似ているのに、綴りが似ていない場合

先ほど触れたように、英語 [2] は綴りと音がかけ離れているので、発音が似ているのに、綴りが似ていない場合 [3] ということが起こりうる。距離が大きくなってしまうことがある。

例えば、人名で“Christiansen”(クリスチャンセン)と“Kris Jenson”(クリス・ジャンソン) [4] は綴りこそかなり違うものの、カナを見れば分かるようにほぼ同じ音である。単に綴りに着目してレーベンシュタイン距離を求めると、6となり、かなり大きくなってしまう。

単に綴りだけを見ている場合は、それでも構わないのだが、発音に着目した方が良い場合もある。発音が記されたレキシコン(語彙集)があれば、それで発音を調べることもできる。しかし、綴りから発音を近似する手法がいくつかあるので、ここではそういった手法を紹介したい。

Soundex

Soundex は、綴りから発音(の近似形)を導くアルゴリズムの1つである。この手法では、アルファベット1つと3桁の数字で発音を表示する。例えば、“Smith”なら“S530”のように変換される [5]

Soundexのアルゴリズムの概略を挙げると以下の通りになる。

  1. 母音字など(a, e, i, u, o, h, y, w)を削除する。ただし、先頭のアルファベット1文字はそのまま残す。“Smith”では、“i”と“h”が削除されて、“Smt”のようになる。
  2. 子音字を以下の法則によって数字に変換する。ただし、先頭のアルファベット1文字はそのまま残す。以下の法則では、よく似た音の字が同じ数字になるようにしている [6] 。先に述べたように、先頭のアルファベット1文字はそのままにする。“Smith”では、“Smt”の“m”と“t”がそれぞれ5, 3に置き換えられ、“S53”になる。
    • b, f, p, v は1に置き換える。
    • c, g, j, k, q, s, x, z は2に置き換える。
    • d,t は3に置き換える。
    • l は4に置き換える。
    • m, n は5に置き換える。
    • r は6に置き換える。
  3. 同じ数字が連続する場合は、1つだけ残す。例えば、“Ackermann”の場合、先頭以外の母音を落として“Ackrmnn”となり、それを数字にすると“A226555”となるが、“A265”に縮める。
  4. 数字が3桁になるように調整する。
    • 桁数が足りない場合は、0で補う。“Smith”の場合は、“S53”で1桁たりないので、“S530”になる。
    • 桁数が多すぎる場合は、末尾をカットする。“Christiansen”の場合は、“C623525”となるが、“C623”にする。

ポイントは、母音を基本的に無視しているということにある。無視していると理由には色々あると思うが、以下のようなことが考えられるだろう。

Soundex をRで処理する手法

Rで Soundex を使うには、RecordLinkage パッケージを使う。RecordLinkage パッケージには、soundex というコマンドがあり、このコマンドで”Ackermann” を “A265” のように変換できる。

library("RecordLinkage")
soundex("Ackermann")

Metaphone

Metaphone も Soundex と同じく、綴りから発音(の近似形)を導くアルゴリズムの1つである。Soundex と同様、Metaphone も、綴りから母音を取り除き、子音だけで発音を近似させている。

Soundex は結構乱暴な手法で、子音字を単独で見て数字に変換している。しかし、英語では、2つの子音字がくっつくことで、別の発音になることがある。例えば、“ph”は、“philosophy”の例のように、“f”のように発音される。Soundex は、こういった例を無視しているのである。

Metaphone はその辺のことをもう少し考えてできている。アルゴリズムの中で、例えば、“ph”は“f”に置き換えるといったことが行われている。結局の所、Metaphone は、英語の綴り字の規則をより考えて作られているのである。

Metaphone は、英語のすべての単語を、16種類の子音で表現する。大文字で表現するのが通例で、0BFHJKLMNPRSTWXYの16種を用いる。なお、“0”は“th”の音、“X”は“sh”や“ch”の音を示す。例えば、“Smith”は、“SM0”と表現される。ただし、例外的に先頭のアルファベット1文字が母音字だった場合は、それを残す。例えば、“absent”なら、“ABSNT”になる。

発音を文字化したもの同士で距離を測る

さて、先ほど“Christiansen”’と“Kris Jenson”という発音が似ているのに、綴りがかけ離れている例を挙げた。単に綴りに着目して、両者のレーベンシュタイン距離を測ると、6になる。

それでは、発音に変換した場合はどうなるだろうか。Metaphone を用いた場合、“Christiansen”は“KRSXNSN”’となり、“Kris Jenson”は“KRSJNSN”となる。“KRSXNSN”と“KRSJNSN”との間のレーベンシュタイン距離は1である [7] 。このように、発音を文字化したもの同士でレーベンシュタイン距離を測ると、かなり小さくなり、発音が近いという実感に近づく。

脚注
  1. 今回は、Soundex と Metaphone だけしか紹介しないが、他にも色々なアルゴリズムがある。 []
  2. 今回は英語の話しかしないが、他の言語でも応用可能で、実際に応用例がある。ただ、英語ほど綴りと音がかけ離れている言語はそうそうなく、今回挙げた手法が必要になる場合も少ない。日本語の場合は、振り仮名を振ることがちゃんとできれば、仮名を比べることで、実質的に発音を比べることができる。 []
  3. この逆で、綴りが似ているのに音が似ていないということもありうる []
  4. この例は、Perlクックブック第2版第1巻(2004年、オライリー・ジャパン)P.62で、著者のトム・クリスチャンセンが挙げている例である。 []
  5. Soundex は元々人名の綴りから発音を導くためのアルゴリズムなので、事例は基本的に人名で挙げていく。 []
  6. 例えば、b, f, p, v は、みな唇を使って作る音(唇音)であり、1番のカテゴリに入れられる。 []
  7. “KRSXNSN”の“X”を“J”に置換するという編集を1回するだけで、“KRSJNSN”になる。 []