この記事を書いたとき、Wikipediaの宝塚の生徒一覧は、芸名が姓名に分かれていないと記載しました。
せっかくなので、芸名も姓名に分けてみたいなと思っていたところ、こちらの記事でNameDividerなる姓名を分離するPythonライブラリがあるのを見つけたので、トライしてみました。
サンプルコードでずっこける
インストールはNameDividerの公式サイトにある通りのコマンドで完了。
同じく公式サイトにあるサンプルのコードを実行したところ、FileNotFoundErrorでずっこけました…
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
/var/folders/cl/wm2yh_cj509fjnj8d5nw0vtw0000gn/T/ipykernel_12025/2559231275.py in <module>
8 basic_divider = BasicNameDivider() # BasicNameDivider is fast but accuracy is 99.2%
9
---> 10 gbdt_divider = GBDTNameDivider() # GBDTNameDivider is slow but accuracy is 99.9%
11 divided_name = gbdt_divider.divide_name("菅義偉")
12 print(divided_name)
~/.pyenv/versions/anaconda3-2021.11/envs/ai_study/lib/python3.9/site-packages/namedivider/divider/gbdt_name_divider.py in __init__(self, config)
21 config = GBDTNameDividerConfig()
22 super().__init__(config=config)
---> 23 download_family_name_pickle_if_needed(config.path_family_names)
24 download_gbdt_model_v1_if_needed(config.path_model)
25 kanji_statistics_repository = KanjiStatisticsRepository(path_csv=config.path_csv)
~/.pyenv/versions/anaconda3-2021.11/envs/ai_study/lib/python3.9/site-packages/namedivider/util.py in download_family_name_pickle_if_needed(path)
39 if path.exists():
40 return None
---> 41 DEFAULT_CACHE_DIR.mkdir(exist_ok=True)
42 print("Download FamilyNameRepository from GitHub...")
43 content = requests.get(FAMILY_NAME_REPOSITORY_URL).content
~/.pyenv/versions/anaconda3-2021.11/envs/ai_study/lib/python3.9/pathlib.py in mkdir(self, mode, parents, exist_ok)
1321 """
1322 try:
-> 1323 self._accessor.mkdir(self, mode)
1324 except FileNotFoundError:
1325 if not parents or self.parent == self:
FileNotFoundError: [Errno 2] No such file or directory: '/Users/"user_name"/.cache/namedivider-python'
Pathlibの仕様から、/Users/"user_name"/.cache/がないのが原因だなとアタリをつけたので、
mkdir /Users/"user_name"/.cache/
して、無事このエラーを回避(解決しましたが念の為、作者の方に同エラーはご報告)。
回避したと思ったのも束の間。今度は次のエラーが起きました…
Download FamilyNameRepository from GitHub...
Download GBDT Model from GitHub...
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/var/folders/cl/wm2yh_cj509fjnj8d5nw0vtw0000gn/T/ipykernel_12025/2559231275.py in <module>
8 basic_divider = BasicNameDivider() # BasicNameDivider is fast but accuracy is 99.2%
9
---> 10 gbdt_divider = GBDTNameDivider() # GBDTNameDivider is slow but accuracy is 99.9%
11 divided_name = gbdt_divider.divide_name("菅義偉")
12 print(divided_name)
~/.pyenv/versions/anaconda3-2021.11/envs/ai_study/lib/python3.9/site-packages/namedivider/divider/gbdt_name_divider.py in __init__(self, config)
31 self.feature_extractor = FamilyRankingFeatureExtractor(kanji_statistics_repository=kanji_statistics_repository,
32 family_name_repository=family_name_repository)
---> 33 self.model = lgb.Booster(model_file=config.path_model)
34
35 def calc_score(self, family: str, given: str) -> float:
~/.pyenv/versions/anaconda3-2021.11/envs/ai_study/lib/python3.9/site-packages/lightgbm/basic.py in __init__(self, params, train_set, model_file, model_str, silent)
2262 self.handle = ctypes.c_void_p()
2263 _safe_call(_LIB.LGBM_BoosterCreateFromModelfile(
-> 2264 c_str(model_file),
2265 ctypes.byref(out_num_iterations),
2266 ctypes.byref(self.handle)))
~/.pyenv/versions/anaconda3-2021.11/envs/ai_study/lib/python3.9/site-packages/lightgbm/basic.py in c_str(string)
200 def c_str(string):
201 """Convert a Python string to C string."""
--> 202 return ctypes.c_char_p(string.encode('utf-8'))
203
204
AttributeError: 'PosixPath' object has no attribute 'encode'
こっちのエラーは、多分NameDividerではなく、依存するlightgbmの方の不備です。
lightgbm.Booster(model_file)は、公式ドキュメントによれば、
model_file (str, pathlib.Path or None, optional (default=None)) – Path to the model file.
なので、pathilib.Pathで呼び出しているNameDividerは間違ってないと思うので。
なおこちらは自分でも未解決かつ未報告です。
と、エラーにぶち当たり、未解決なので、より精度の高いGBDTNameDivider()の使用は諦め、BasicNameDivider()で姓名を分けてみます
宝塚の生徒の芸名を姓名に分けてみる
92期の生徒一覧を姓名に分けてみます。参考に読み仮名も併記します。
import csv
from namedivider import BasicNameDivider
basic_divider = BasicNameDivider()
with open("takaraduka_actress/takaraduka_actress_92period.csv".format(period), "rt") as f:
reader = csv.DictReader(f)
for row in reader:
actress_name = row["芸名"]
divided_name = basic_divider.divide_name(actress_name)
print(divided_name, row["読み仮名"])
結果は下記の通りです。
48名中、6名がNGと精度としては87.5%でした。
NameDividerは、実在する名前をソースにしていますが、流石に一般的な名前ではない芸名の場合、精度は落ちるようです。
百 千糸 ももち いと -> NG: 百千 糸が正しい
真瀬 はるか まなせ はるか
美春 あやか みはる あやか
蘭乃 はな らんの はな
鞠花 ゆめ まりか ゆめ
透水 さらさ とうみ さらさ
松風 輝 まつかぜ あきら
煌月 爽矢 あきづき さや
千海 華蘭 ちなみ からん
天輝 トニカ あまき とにか
すみれ 乃麗 すみれのれい
天真 みちる てんま みちる
妃白 ゆあ ひしろ ゆあ
初花 美咲 はつはな みさき
真風 涼帆 まかぜ すずほ
凛城 きら りんじょう きら
彩 凪翔 あやなぎ しょう -> NG: 彩凪 翔が正しい
瀬稀 ゆりと せき ゆりと
笙 乃茅桜 しょうの ちお -> NG: 笙乃 茅桜が正しい
舞乃 ゆか まいの ゆか
貴澄 隼人 たかすみ はやと
天咲 千華 あまさき ちはな
日高 大地 ひだか だいち
月 映樹茉 つきえ じゅま -> NG: 月映 樹茉が正しい
夢莉 みこ ゆめり みこ
鳳月 杏 ほうづき あん
桃花 ひな ももはな ひな
真那 春人 まな はると
大澄 れい おおすみ れい
銀 華水 ぎんか すい -> NG: 銀華 水が正しい
花城 舞 はなしろ まい
花織 千桜 はなおり ちさ
紫月 音寧 しづき おとね
本城 くれは ほんじょう くれは
風凛水 花 ふうり みずか -> NG: 風凛 水花が正しい
真愛 涼歌 まあい すずか
月野 姫花 つきの ひめか
若夏 あやめ わかなつ あやめ
輝咲 玲央 きざき れお
紗羽 優那 さはね ゆな
貴月 美礼 きづき みれい
安里 舞生 あんり まう
千紗 れいな ちさ れいな
愛那 結梨 あいな ゆうり
神房 佳希 かずさ よしき
花輝 真帆 はなき まほ
剣崎 裕歌 けんざき ゆうか
白百合 ひめ しらゆり ひめ