旧仮名キーボード開発記#9|開発の変遷(前篇)
ちょうど区切りとなったので、開発開始からリリースまでの変遷について一旦まとめようと思います。
また、note記事のカバー画像を作るのが面倒になったので、今後はずっと同じ画像を使います。
***
令和3年5月〜(辞書作成&停滞期)
ここから記事が途絶えていたと思うので、ここから書きます。
辞書作成計画
キーボードの基礎機能自体は比較的早くにできたのですが、辞書作りが大変でした。
以前にも書いたとおり、辞書はNAIST Japanese Dictionaryを下敷きにしているため、初期状態では「新仮名読み」と「新字新仮名」しかありません。旧仮名で入力変換できるようにするためには、そこから「旧仮名読み」「旧字新仮名」「新字旧仮名」「旧字旧仮名」を作成していかなければなりません。
なるべく効率的に新字新仮名を旧字旧仮名に書き換えるため、スプレッドシートを編集するための様々なツールを自作しました。もしそれがなければ、何万倍も時間がかかっていたと思います。
せっかくなので、今回は自作したツールについて書いていきます。
単漢字一覧作成ツール
まずは単漢字一覧を作りたいと思いました。
単漢字一覧を先に作っておけば、旧仮名読みも旧字体表記もほぼ自動的に生成できると考えたからです。
たとえば、「しょう」という新仮名読みを旧仮名読みに直すと「しゃう」になったり「せう」になったり「しょう」のままだったりするのですが、どれが正しいのかは単語によります。しかし、もし漢字表記が判明していれば、そのどれを取るべきかがほぼ特定できるため、漢字から自動推定したほうが明らかに効率的です。
今回は各単語の漢字表記が判明しているため、漢字ごとの読みの対照表さえあれば自動で旧仮名読みを生成できることになります。また、単漢字一覧があれば旧仮名だけでなく旧字についても同時に生成可能であるため、これを早期に完成させるメリットはかなり大きいと考えました。
よって、以下のような一覧を作成することにしました。
全部で6568字あります。
「新仮名読み」「旧仮名読み」という列はキーボードの単漢字変換候補としてそのまま利用した読みであり、「新仮名読み2」「旧仮名読み2」は辞書データの旧仮名推定のためだけに利用した読みです。
新字と旧字の組合せはネット上の変換器を利用して作成したのですが、異体字セレクタの指定や新旧仮名遣いの組合せについては、典拠としている辞書を見ながらすべて手作業で行うことにしました。
手作業で行うにあたり、スプレッドシート上での編集はあまり能率が良くなかったので、Google Apps Scriptで以下のようなツール(Web画面)を作って、スマホから編集していきました。
あくまで自分用なので、他人が見て分かるようにはデザインしていないのですが、このツールのおかげでサクサクと作業が進みました。
このツールでは、一番上の欄に旧仮名読みを入力したうえで字形をタップすると次の字に進むことができます(入力内容はスプレッドシートに書き込まれます)。また、新仮名読みについては旧仮名読みから機械的に生成できるので、わざわざ入力しなくても自動で変換されるように作りました。さらに、備考を書くのも面倒なので、タップ1つで定型文を挿入できるボタンも大量に配置しました。
こうして6568字の単漢字一覧が完成しました。
旧仮名生成ツール
さきほど示したとおり、初期の語彙辞書は以下のような感じでした。「新仮名読み」と「新字新仮名」だけが分かっている状態です。
まずは各データの「旧仮名読み」を推定するため、ボタン1つで旧仮名を生成するツールを自作しました(以下はデモ画像)。
このツールは単漢字一覧の情報に基づき、各単語の適切な旧仮名読みを推定します(漢字と仮名が混在していても推定できます)。
また、送り仮名部分に新旧の相違が現れうる仮名が存在するなど、漢字の力に頼ることができない場合も多いので、これを見逃さないために「解決に成功した仮名遣い」と「解決できなかった疑惑がある仮名遣い」とを区別できるようにもしています。
次に、生成された仮名遣いを目視と手作業で修正した後、清書の列に移したうえで、残りの表記(旧字旧仮名表記など)を推測する処理を実行します。
旧字体については「学→學」や「会→會」のように一意に直せるものと「弁→辨・瓣・辯」や「台→臺・颱・台」のように一意には直せないものとがあるので、それもシート上で後から区別できるようにしてあります。
また、シート上の漢字と新仮名読みとを照合したときに、単漢字一覧には未収録の読みが混ざっている場合があるので、以下の画面から単漢字一覧にフィードバックを送れるようにしました。これにより、作業が進むごとに単漢字一覧がどんどん強化され、自動推定の守備範囲が広がっていきます。
以上のように、ツールによって自動生成されたデータを目視チェックするという流れで辞書作成を進めていきました。
どうせ目視チェックするならツールは必要ないように見えますが、自分の手で書き換えるのと単に確認するだけなのとでは大変さがかなり違います。また、ツールで行うと打ち間違いなども起こりにくくなります。
リリース後の今でも、新しい単語を追加するときには、ヒューマンエラーによる打ち間違いを防ぐ目的でこのツールを常用しています。
停滞期に突入
ほかにも色々ツールは作ったのですが、辞書とデータの確認作業ばかりで面倒になったこともあり、何ヶ月も放置しては少し作業するというような進め方で年末まで過ごしていました。
令和4年1月〜(MeCabの改造)
開発宣言から丸1年経っていることを思い出し、正月休みで実装を再開することにしました。
この頃までには名詞以外の辞書はほぼ完成していたため、名詞が登場しない入力変換はできるようになっていました。ただ、予測変換(入力文字列の後方を補う機能)がうまくできていませんでした。Trie木自体の仕組みはわかっていたのでMeCabのソースコードを直接改造しようと思い、核心となっているらしいdart.hというファイルを解読していました。しかし、読めば読むほど不思議な操作が行われており、あまり実装が進みませんでした。
『形態素解析の理論と実践』との出会い
その後、MeCabやdartについて調べている過程で『形態素解析の理論と実践』という本(MeCab作者が著者)を知り、購入を検討するために本屋で立ち読みしてみたのですが、まさしく求めている情報が分かりやすく載っており、そのまま買って帰りました。
読めば読むほど良書で、この本のおかげでdart.hがどういうつもりで書かれたものなのかが非常によく分かるようになり、末尾補完検索機能のほか、濁点や小書きの入力を省いても辞書引きできるような仕組みが一気に完成しました。
普段はプログラミングの本を買わずにネットの資料で済ませることが多いのですが、この本にはネットではなかなか見つからなかった情報が充実していたため、これから自分でMeCab改造をしたい方は読んでおいて損はないと思います。
文字列の扱い方
MeCabのファイルの拡張子はcppなのですが、中身のプログラムはいかにもC言語風で、char配列(1バイト型の配列)に文字を流し込み、ポインタによって管理されていました。さすが爆速で動くだけあると思いました。
知っている人は知っていると思いますが、本来のC言語には文字列型はなく、文字(char型など)の配列で文字列を表現することが多いです。
さて、utf-8における平仮名は3バイトなので、char配列では平仮名1文字が配列3要素分になります。つまり、インデックス(またはポインタ)を1つずらしても次の平仮名が参照されるわけではなく、元の平仮名の3分の1の地点が参照されるだけです。混乱しやすいので、MeCab改造時には紙に図を書きながら実装しました。
念のために付け加えておくと、1バイトとは8ビットのことです。8ビットとは、値を2進数にしたときの8桁分のことをいいます(上図の0や1を、8桁ひとかたまりで見てください)。
なお、配列のことを箱に譬えることがありますが、ここでやっていることは平仮名1文字を3分割して、それを3つの連続する箱にバラバラに納めているようなことです。
そもそも箱というのは架空の概念なので、メモリ上で見れば文字は割られてなどいないのですが、一旦はこのようなイメージでもいいのではないかと思います。
※なぜ3分割なのかということを説明しておくと、「utf-8の平仮名が3バイトなのに対し、箱のサイズが1バイトしかないから」です。1バイト文字ならば1つの箱に納まるので分割されることはありません。
僕は元々C言語出身(初めて本格的に学んだ言語はC言語)で、大学1回生のころはC言語とDXライブラリを使って自己満ゲームをよく作っていたので、配列とメモリとポインタの関係なども未だに覚えているのですが、JavaScriptやPythonなど文字列型が当たり前に存在している言語からプログラミングを始めた人にとっては、この時点で結構躓くのではないかと思います。
このことを知らないと、そもそもMeCab改造以前の問題として、ソースコード内で文字列を扱えないことになるので、余談として取り上げました。
その他のC言語の注意点としては、関数内で宣言された変数は関数終了時に寿命が尽きるので、配列類を戻り値にすると、戻った先で値が壊れることくらいですかね。
令和4年中頃〜(辞書作成&再・停滞期)
変換機能や末尾補完機能も一応形になり、各種設定(片仮名モード、濁点無しモード、踊り字モードなど)も実装が完了したので、再度辞書作成作業に戻りました。
日本語の名詞は想像以上に厖大で、また段々と面倒になってきたので、令和4年はこのあとずっと停滞期でした。
次回予告
次回の記事では、今年の春から11月リリースにかけてのことを書きます。
リリース3日前にMeCabファイル消失事故が起こったり、リリース前日に審査で却下されたりする話です。
この記事が気に入ったらサポートをしてみませんか?