人名の比較:このタスクにアプローチする方法
-
06-07-2019 - |
質問
私は自然言語プログラミングの学生ではありませんが、些細なstrcmp(n1、n2)ではないことを知っています。
これまでに学んだことは次のとおりです。
- 個人名の比較は100%解決できません
- ある程度の精度を達成する方法があります。
- 回答はロケール固有であるため、問題ありません。
代替のスペルを探していません!入力のスペルが正しいことを前提としています。
たとえば、以下のすべての名前は同じ人物を参照できます:
- ベリーツァカラ
- バーナード・ツァカラ
- ベリーJ.ツァカラ
- サカラ、ベリー
次のことをしようとしています:
- 関係2の入力名を評価するアルゴリズムを構築(またはコピー)します
- インデックス作成方法を見つける(データベース内の名前、ハッシュテーブルなど)
注: 私の仕事は、テキストで名前を見つけることではなく、2つの名前を比較することです。例えば
name_compare( "James Brown", "Brown, James", "en-US" ) ---> 99.0%
解決
Tanimoto Coefficientを使用して、Pythonでの迅速な(ただしスーパーではない)ソリューションを作成しました。
"""
Formula:
Na = number of set A elements
Nb = number of set B elements
Nc = number of common items
T = Nc / (Na + Nb - Nc)
"""
def tanimoto(a, b):
c = [v for v in a if v in b]
return float(len(c)) / (len(a)+len(b)-len(c))
def name_compare(name1, name2):
return tanimoto(name1, name2)
>>> name_compare("James Brown", "Brown, James")
0.91666666666666663
>>> name_compare("Berry Tsakala", "Bernard Tsakala")
0.75
>>>
編集: 有益で役立つ本へのリンク。
他のヒント
Soundex は、類似した名前を比較するために使用されることがあります。姓/名の順序は扱いませんが、コードでコンマを探してその問題を解決できる可能性があります。
最近、この種の作業をノンストップで行っていますが、私たちが取ったアプローチは、ルックアップテーブルまたはエイリアスリストを作成することです。スペルミス/聞き違え/英語以外の名前を割引できる場合、難しい部分は取り除かれます。あなたの例では、最初の単語と最後の単語が前名と姓であると仮定します。間にあるものはすべて破棄されます(ミドルネーム、イニシャル)。 BerryとBernardはエイリアスリストに含まれます。TsakalaがBerryに一致しなかった場合、単語の順序を逆にして一致を取得します。
理解する必要がある1つのことは、扱っているデータベース/人のリストです。英語圏ではミドルネームが一貫して記録されていません。そのため、ミドルネームまたはミドルネームのイニシャルに基づいて一致を作成または拒否することはできません。 Soundexは、" Dick"などの一般的な名前のエイリアスでは役に立ちません。および「リチャード」、「ベリー」および「バーナード」おそらく" Steve"および「Stephen」。一部のコミュニティでは、人々が同じ住所に住んでいて、同じ名前でその住所に2世代または3世代住んでいることがよくあります。それらを分離できる唯一の方法は、生年月日です。生年月日は記録される場合とされない場合があります。影響力がある場合は、おそらく生年月日の記録を必須にする必要があります。多くの「人のデータベース」生年月日を記録しないか、プライバシー上の理由でそれらを提供しません。
事実上、人名のマッチングはそれほど複雑ではありません。提供されるデータの品質に完全に基づいています。実際に起こることは、多くのレコードが不一致のままであるということです-そして、それらを見ている人間でさえ、不一致を解決することはできません。人はエイリアスリストに記録されていない名前のエイリアスに気付くか、インターネット上でその人の詳細を調べることができるかもしれませんが、プログラムがそれを行うことを本当に期待することはできません。
銀行、信用格付け機関、および政府には、当社に関する詳細な情報がたくさんあります。以前の住所、生年月日など。これは、名前を結合するのに役立ちます。しかし、通常のプログラマーにとって魔法の弾丸はありません。
名前の順序とミドルネーム/イニシャルの存在を分析することはもちろん簡単なことなので、本当の課題は一般的な名前の代替を知ることです。ニックネーム検索テーブルのようなものを使用せずにこれを行うことができるとは思わない。 このリストは良い出発点です。 BernardをBerryにマッピングしませんが、おそらく最も一般的なケースをキャッチします。おそらく他の場所でさらに網羅的なリストを見つけることができますが、ロケール固有のルックアップテーブルを使用する方法は間違いないと思います。
utf-8を使用してTanimotoで実際に問題が発生しました。
発音区別符号を使用する言語で機能するのは、 difflib.SequenceMatcher()