見出し画像

旧仮名キーボード開発記#5|形態素解析器をつかってみる

今日は形態素解析について考えます。

形態素解析とは、たとえば「かんがへてゐた」という文字列を以下のように単語ごとに区切ったり品詞を解釈したりする処理のことをいいます。

かんがへ:かんがへる・動詞・ハ下一・連用形
:て・接続助詞
:ゐる・動詞・ワ上一・連用形
:た・助動詞・終止形

この処理をSwiftでできるようにしていきます。

***

形態素解析器をさがす

形態素解析をおこなうプログラムのことを形態素解析器といいますが、世の中では、すでにいろいろな人たちが形態素解析器を作って公開しているので、その中から適当なものを選ぼうと思います。

「形態素解析器」と検索すると、以下の記事(2020年)が一番上に出てきました。

以前、何かをしようと思ってKuromojiという形態素解析器を使ってみたことがあるのですが、ここにラインナップされていないということはあまり有名ではないのでしょうか。そのときは有名なものだと思っていたのですが。

また、ChaSenなんかも有名な形態素解析器だと思うのですが、それも載っていませんでした。

おそらく自然言語処理の界隈では、上の記事で挙げられているのが現在実用的とみなせる選択肢ということになっているのだと勝手に思い込むことにします。

形態素解析器をきめる

前章の比較記事を読むかぎり、旧仮名キーボードを実装するにあたっては、MeCabが一番適格に思えたので、これを採用することにします。選定理由は以下のとおりです。

・処理が高速である
・辞書とロジックが切り離されている
・BSDライセンスで使用可能である

処理が高速であるというのは、キーボードアプリにおいて最重要項目と考えられます。既存キーボードアプリのレビューでも、速度に関しては厳しい意見が多いので、ほかを多少犠牲にしても速度を重視しようと思います。

辞書とロジックが切り離されているというのは、旧仮名キーボードのような特殊な辞書を使わざるを得ないシステムにおいては、ほぼ必須要件です。

BSDライセンスで使用可能であるというのは、前回の記事でいうコピーレフトには該当しないライセンスで使えるということなので、そのルールのもとで使わせてもらおうと思います。

なお、精度を必要な場合にはJUMAN++という形態素解析器がおすすめされているのですが、以下の記事によると、JUMAN++はMeCabと比較して1085倍の解析時間がかかるという結果も出ており、キーボードアプリとしてはやはりMeCabを選んだほうが賢明だと思いました。そもそも「精度」というのは、かなりの部分が辞書に依存しているような気がするので、辞書を置き換える必要のある旧仮名キーボードでは、せっかく高精度なものを導入しても無駄になるような予感がします。

MeCabについてしらべる

公式サイトからはC++で提供されています。

iOSでMeCabを使用するための方法もいろいろ見つけました。

実装してみる

以下で公開されているサンプルプロジェクト(iOSでMeCabを動かせるようにしているもの)をもとに作ることにしました。

先日作ったキーボードに対して上のサンプルを付け加えようとしたのですが、どうもうまくいかなかったので、上のサンプルのほうにキーボードを追加しました。

辞書を置き換える実験として、一旦以下の辞書に置き換えて動作確認してみました(リリース版では自前の辞書を作って収容するつもりです)。

辞書を置き換えた後、自作キーボードから「かんがへてゐた」と打ったときの解析結果(ログ)は以下のようになりました。

スクリーンショット 2021-01-26 18.30.07

いろいろ試したのですが、ひらがなで書かれても自然な言葉については精度よく解析できることが多いですが、漢字で書かれることの多い言葉はひらがなで書くと精度が落ちることが多い気がしました。

そもそもMeCabや辞書の仕様がまだよくわかっていないので、データ構造として採用されているというTrie木の各節には「ひらがな」しか存在しないのか「漢字」もあるのかというところから調べていく必要がありそうです(パフォオーマンス上は実際の表記のまま引けるようにしたほうがTrie木の強みが生きてきそうなので、漢字も混ざっているような気がしています)。旧仮名キーボードでは変換前の文字列に漢字を使うことはないので、ひらがなだけの木を作ったほうがよさそうです。

また、今は1つの入力に対して1通りの候補しか取れていないので、今後はひとまずドキュメントなどを見ながら複数候補を取れるようにしていきたいと思います。

ちなみに、ちょっとソースを改造してみようと思い、MeCabの関数を呼び出して使っているあたりを見てみたのですが、引数として渡す文字列はchar配列(charのポインタ)になおす必要があるようでした。おそらく呼び出しているのはC言語の関数で、引数も戻り値もすべてC言語に存在する形式(ポインタや構造体)でなければならないのだと思います。

次回予告

次回はMeCabや辞書の仕様をしらべたり、旧仮名キーボードとしての辞書のデザインを考えていきたいと思います。

つづく。

この記事が気に入ったらサポートをしてみませんか?