架空世界の表意文字用の手書き文字認識を実装したい (part 1)
この記事は創作+機械学習 Advent Calendar 2021の22日目です。
自己紹介パート
(記事の技術的内容には本質的な関わりがないので、お時間のない方はこのパートは読み飛ばしていただいても構いません。)
こんにちは、hsjoihs です。
創作の種類の一つに「架空世界創作」、つまり、架空の世界の言語・文化・地理などを創作するという形態があり、ご縁あって、2017年頃から私もファイクレオネという架空世界についての創作を手伝わせていただいております。
さて、架空の世界の言語を創作している以上、用いられている文字も架空になります。上記地図ではペメセペ・ルヨットという一種のアルファベットを用いていますが、架空世界ファイクレオネではこれ以外にも様々な文字体系が用いられているという設定となっております。私はその中でも、ファイクレオネで使われている表意文字、「燐帝字母」にまつわる諸々の管理を主にさせていただいています。
たとえば、向こうの文化の一つとして、駒の役職が燐帝字母で書かれている架空伝統ゲーム「机戦」を我々は創作しており、現在企業に依頼してそれの製造を行っていただいていたりもするのですが、
このボドゲのオンライン対戦バージョンは私が実装していたりします。
本題
さて、以上の画像に散見された漢字のような文字「燐帝字母」に対して、手書き文字認識を実装したいと思い立ち、2020年7月5日、「そのためのデータセット」を自作するためのツールを作り始めました。
手書き文字の認識のデータセットを自作したいが、タッチパネルの入力を時系列データにしてくれる「だけ」のツールというのがなかなか見つからないし自分でcanvasで書くべきだろうか
— hsjoihs (@hsjoihs) 2020年7月5日
えーすごくテキトーにJSONを生成して集めようとしたらCORSに引っかかるをしています(めんどい~)(なるべく手抜きでJSONを集めるにはどうすればいいんだ)
— hsjoihs (@hsjoihs) 2020年7月5日
jsonファイルをユーザーにダウンロードさせて(これはObject URLで容易にできる)、Slackとかに投げてもらうのが小規模だと楽そう?(少し面倒だけど…。)
— hikalium (@hikalium) 2020年7月5日
誰の生成したデータなのかが自明に分かるのも嬉しいですね。完成しましたありがとうございます
— hsjoihs (@hsjoihs) 2020年7月5日
「ランダムに提示された文字を枠内に手書きし、↲ ボタンを押す」という作業をひたすら繰り返すとデータセットができる、という仕組みが出来上がりました。あとは地道にやっていくだけです。
皆で頑張った(具体的には11人が協力した)結果、2020年7月6日12:00~2020年7月9日12:00の72時間で3万枚(つまり1日で1万枚)という驚異のペースで画像が溜まっていき、2020年7月11日には当初目標としていた5万枚を達成。
その生 JSON、およびそれを変換した SVG と PNG 一枚一枚の生ファイルを git に直コミットして作られた、pull するにも push するにもあまりにも時間が掛かるヤバがこちら。みんなは真似しないでね!
2020年7月14日には、はこつきさん(@re_hako_moon)に学習を回していただき、
いまのところResNet-18+FCのネットワーク構成,各クラス10文字ずつ分離してテストデータを作成(train&validation: 46876, test: 3390)で精度99.08%くらいです
(testは毎回走らせていないのでこれはvalidationですが,だいたい挙動はこんな感じです)
という素晴らしい成果が得られました。めでたしめでたし。
本題2
その後、はこつきさんはかなりの多忙を極め、時は流れ、2021年11月9日、はこつきさんに
- そういえば、このプロジェクトの存在って覚えてます?
- 当時学習に使ったソースコードとかって、3秒で渡すことが可能です?
と訊いたところ、
- 覚えてますよ
- 別のパソコンに入ってますし、ぼくがやるとしても当時のは書き直すと思います
と言われたので、「書き直すかぁ」と思っていました。
思っていたらいつの間にかアドカレ2日前になっていました。ひーん。
ということで、再びはこつきさんと話したところ、
- pretrained からやったほうが文字のタスクにおいても精度がいい
- pytorchなら、torchhubからロードするのがよい
- ロードについては、ここhttps://pytorch.org/hub/pytorch_vision_resnet/ を見たら大丈夫
- あとは https://qiita.com/illumination-k/items/fa7508127d8942c1284f らへんとか読めばイケると思います
と言われました。ありがたい~。
気づいたらアドカレ当日になっていました。うぎゃぁ。
ということで、https://qiita.com/illumination-k/items/fa7508127d8942c1284f を実際に試み、
- 致命的な typo がソースコード内に 3 つあったので修正リクエストを送信
- torch.max ではなく torch.topk を使うことで複数候補を出せるようにする
- japanize-matplotlib というのを使うことで、Google Colab でも漢字を表示できることを突き止める (https://www.teamxeppet.com/matplotlib_in_japanize-colabo/)
- 「JSON だけコミットしてて、SVG や PNG にまだなっていないやつ」をなくす
- この記事を書く
などの活動を行いました。
よし、あとは実データで学習を回すだけ!!!!(現在23時55分)
ということで、今回の記事はここで終わりです♡
今後の楽観的な見通し
- 実データで学習を回す (part 2)
- 手書き文字認識 Web アプリを作る (part 3)
- データが増えるたびに再学習が走り Web アプリがデプロイされる CI とかを整える (part 4)
(こんなにうまくいくかねぇ?)
有象無象
*1:このツールはMITライセンスで公開しているので、「私も架空の文字の手書き文字認識を作りたいので、データセットを作りたい」という人は https://github.com/jurliyuuri/linzi-recognition/ からお使いください。ただし、やっつけ仕事で作っているので、あまり再利用しやすい形にはなっていません。