2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PythonでGenderAPIとPykakasiを使って氏名から性別を予測する

Last updated at Posted at 2020-08-10

##はじめに
氏名から性別を予測したい利用シーンがあるかと思います。
例えば、会員制のサービスで登録フォームで性別を聞くとCVRが下がってしまう、だったら予測で補おう!などと言ったシーンでしょうか。

氏名から性別を予測する方法は、機械学習で分類器を生成し予測する方法や外部APIを用いて予測を行う方法などいくつかあります。
今回はPythonで名前からGenderAPIを用いて性別を予測するアプローチとなります。

GenderAPIはアメリカの企業で、膨大な氏名データから性別予測をこれまで行ってきたようです。
類似するサービスはいくつかありますが、今回はこのGenderAPIを用いて性別予測を行います。

##前準備
###Gender API
まずは、GenderAPIのアカウントを作成しましょう。
作成後、API_KEYを取得します。
無料で使用したい方は、500の氏名までなら無料で使用することができます

###擬似個人情報取得
PersonalGeneratorを使って、擬似的に個人情報を生成します。
自由に表示する項目を選択できますが、今回は、正解判定も行いたいので、連番,氏名,氏名(カタカナ),性別を取得します。
今回は30人程度の氏名から性別を予測してみます。
スクリーンショット 2020-08-10 15.27.17.png

###Pykakasi
予測対象の氏名はFirst_nameになり、名前を漢字、カタカナ、ひらがな、ローマ字のいづれで予測させるかは精度に大きく影響します。
結論、海外のサービスだからか、ローマ字に変換し、予測させた方が精度が最も高かったです。(検証過程は割愛します。)

ですので、下の名前からローマ字変換を行う必要があります。
使い方については、開発者のドキュメントが参考になります。pykakasiの使い方
以下の2点のパッケージをインストールします。

pip install six semidbm
pip install pykakasi

##性別予測
###pythonで性別予測
実際に対象者30人の性別を予測していきます。
大まかな手順は以下の通りです。

  1. 対象者のdataframeを用意、全角スペースで分割し名前列を生成
  2. Pykakasiインスタンスを生成し、ローマ字変換する設定をし、名前を変換しローマ字列を生成
  3. ローマ字リストをGenderAPIに渡し、予測結果を取得
  4. 予測結果と元のdataframeをマージ
gender_estimation.py
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までの経過時間
スクリーンショット 2020-08-10 15.29.07.png

###性別予測精度検証
最後に、性別予測結果の精度について検証しましょう。
以下の表の用に、正解と予測結果とその数をプロットし、マトリックスを生成します
正解率はほぼほぼ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%
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?