##はじめに
氏名から性別を予測したい利用シーンがあるかと思います。
例えば、会員制のサービスで登録フォームで性別を聞くとCVRが下がってしまう、だったら予測で補おう!などと言ったシーンでしょうか。
氏名から性別を予測する方法は、機械学習で分類器を生成し予測する方法や外部APIを用いて予測を行う方法などいくつかあります。
今回はPythonで名前からGenderAPIを用いて性別を予測するアプローチとなります。
GenderAPIはアメリカの企業で、膨大な氏名データから性別予測をこれまで行ってきたようです。
類似するサービスはいくつかありますが、今回はこのGenderAPIを用いて性別予測を行います。
##前準備
###Gender API
まずは、GenderAPIのアカウントを作成しましょう。
作成後、API_KEYを取得します。
無料で使用したい方は、500の氏名までなら無料で使用することができます
###擬似個人情報取得
PersonalGeneratorを使って、擬似的に個人情報を生成します。
自由に表示する項目を選択できますが、今回は、正解判定も行いたいので、連番,氏名,氏名(カタカナ),性別を取得します。
今回は30人程度の氏名から性別を予測してみます。
###Pykakasi
予測対象の氏名はFirst_nameになり、名前を漢字、カタカナ、ひらがな、ローマ字のいづれで予測させるかは精度に大きく影響します。
結論、海外のサービスだからか、ローマ字に変換し、予測させた方が精度が最も高かったです。(検証過程は割愛します。)
ですので、下の名前からローマ字変換を行う必要があります。
使い方については、開発者のドキュメントが参考になります。pykakasiの使い方
以下の2点のパッケージをインストールします。
pip install six semidbm
pip install pykakasi
##性別予測
###pythonで性別予測
実際に対象者30人の性別を予測していきます。
大まかな手順は以下の通りです。
- 対象者のdataframeを用意、全角スペースで分割し名前列を生成
- Pykakasiインスタンスを生成し、ローマ字変換する設定をし、名前を変換しローマ字列を生成
- ローマ字リストをGenderAPIに渡し、予測結果を取得
- 予測結果と元のdataframeをマージ
import sys
import json
from urllib import request, parse
from urllib.request import urlopen
import pandas as pd
import pykakasi
class GenderEstimation:
"""
ローマ字変換した氏名から性別を予測
"""
__GENDER_API_BASE_URL = 'https://gender-api.com/get?'
__API_KEY = "your api_key"
def create_estimated_genders_date_frame(self):
df = pd.DataFrame(self._estimate_gender())
print('\n{}人の性別予測を完了しました。'.format((len(df))))
df.columns = [
'estimated_gender', 'accuracy', 'samples', 'duration'
]
df1 = self._create_member_data_frame()
estimated_genders_df = pd.merge(df1, df, left_index=True, right_index=True)
return estimated_genders_df
def _estimate_gender(self):
unique_names = self._convert_first_name_to_romaji()
genders = []
print(u'{}人の性別予測を行います'.format(len(unique_names)))
for name in unique_names:
res = request.urlopen(self._gender_api_endpoint(params={
'name': name,
'country': 'JP',
'key': self.__API_KEY
}))
decoded = res.read().decode('utf-8')
data = json.loads(decoded)
genders.append(
[data['gender'], data['accuracy'], data['samples'], data['duration']])
return genders
def _gender_api_endpoint(self, params):
return '{base_url}{param_str}'.format(
base_url=self.__GENDER_API_BASE_URL, param_str=parse.urlencode(params))
def _convert_first_name_to_romaji(self):
df = self._create_member_data_frame()
df['first_name_roma'] = df['first_name'].apply(
lambda x: self._set_kakasi(x))
return df['first_name_roma']
def _set_kakasi(self, x):
kakasi = pykakasi.kakasi()
kakasi.setMode('H', 'a')
kakasi.setMode('K', 'a')
kakasi.setMode('J', 'a')
kakasi.setMode('r', 'Hepburn')
kakasi.setMode('s', False)
kakasi.setMode('C', False)
return kakasi.getConverter().do(x)
def _create_member_data_frame(self):
df = pd.read_csv('personal_infomation.csv').rename(columns={
'連番':'row_num',
'氏名':'name',
'氏名(カタカナ)':'name_katakana',
'性別':'gender'
})
df['first_name']=df.name_katakana.str.split().str[1]
print(u"{}人の予測対象者を抽出します。".format(len(df)))
return df
###性別予測結果
予測結果のdataframeは以下のようになりました。
GenderAPIの予測に関するレスポンスは以下のような定義になります。
estimated_gender | accuracy | samples | duration |
---|---|---|---|
性別予測結果 | 予測の正しさ | 予測に用いたサンプルサイズ | 1callまでの経過時間 |
###性別予測精度検証
最後に、性別予測結果の精度について検証しましょう。
以下の表の用に、正解と予測結果とその数をプロットし、マトリックスを生成します
正解率はほぼほぼ100%となりました。
今回の場合、1件だけ本当は女性なのに、男性と予測してしまいました。
やはり「イオリ」など男性とも女性とも取れる名前の予測は困難なようです。
正解 | 予測 | num |
---|---|---|
male | male | 11 |
male | female | 0 |
male | unknown | 0 |
female | male | 1 |
female | female | 18 |
female | unknown | 0 |
unknown | male | 0 |
unknown | female | 0 |
unknown | unknown | 0 |
予測/正解 | male | female | unknown | 正解率 |
---|---|---|---|---|
male | 11 | 0 | 0 | 100.00% |
female | 1 | 18 | 0 | 94.74% |
unknown | 0 | 0 | 0 | 0% |