手書き数式認識物語

ソフトウェアエンジニアの深谷です。

MonoxerではAndroid/iOS向けに数式手書き認識機能をリリースすることができました。

↓こんな感じの機能です。

社内外の多くの人が関わりながらUIデザインや実装、QA、OSSへのコントリビュートを経てリリースすることができ、印象深い仕事でした。

スマホ上で数学や物理などの問題を解き回答してもらうというのは、技術的にもデザイン的にもQA観点でもチャレンジングなテーマですが、インターンの大森さんをはじめモノグサの多くの人が職種の垣根を超えて協力することでUIの大きな改善をすることができました。

目次

なぜ記憶アプリ「Monoxer」で数式をサポートしているのか?

人間が記憶しているものというと例えば英単語や社会の年号などが想起されますが、実際には数学などの問題解決領域においても記憶が大きく関わっています。 九九など単純な計算はもちろん、数学の高度な問題についても定理や類似問題に関する知識があることによって大きく問題解決が促進されます。 それらを加速するため、Monoxerでは数式をサポートしています。

なぜ数式手書き認識なのか?

Monoxerで数学を扱うに当たって、ユーザーに数式の回答をさせるのが難しいという課題があります。

Monoxerでは上の図のキーボードを使って数式をユーザーに入力してもらっていましたが、累乗や分数を使った式をどのような手順で入力すればよいかは小中学生には難しいですし、わかっていてもタップ数が多くて繰り返し学習するには大変です。そのため、手書きした数式を認識することで入力を支援することが望まれていました。

フィジビリティスタディ、パフォーマンス改善

手書き数式認識ができるアルゴリズムの調査及びそのパフォーマンスの改善などほぼ全てをインターンの大森さんがやってくれました。 詳しくはぜひこちらをご覧ください。

UIの検討

フィジビリティスタディでBTTRによる数式手書き認識がいけそうであることは分かりましたが、これをアプリに組み込んでいくためにUIの観点で考えるべき要素があります。 手書き数式認識を導入する以前から、数式画面はすでに複雑度が高い画面でした。

数式キーボードの他にも途中式を書くためのメモ欄などの構成要素があります。

数式手書き認識を行う場合途中式用のメモ欄をそのまま使いたいところですが、画像認識が問題になります。

例えば上記の画像の場合、72が答えとなるためこの部分のみの画像を認識させたいのですが、どこからどこまでが回答なのか特定するのは技術的に非常に難しいです。

回答専用のスペースを設けるなどの対策がありますが、回答の大きさは問題によって異なりますし、回答用のスペースを確保した分途中計算用のスペースが狭くなってしまいます。

このような技術的な制約をクリアするとともに、既存のUIとの調和を図る必要がありました。 なんとかストロークを区別しつつメモ欄を共用する方法として思いついたのが、回答ペンと呼ばれる新機軸のUIです。 これはユーザーに途中式用のペンと回答用のペンを切り替えてもらい、回答用のペンを使って書いたストロークのみを認識対象とするというものです。

つまり、上記の画像でいうところの緑で書いた文字(正確にはストローク)のみを画像認識の対象とします。

極端な話、途中計算と回答ペンがここまで重なっていると人間にとってはみづらいですが、プログラムはストロークを区別しているので全く問題がありません。回答ペンで書いたストロークのみの画像を別途生成し、認識させます。 この部分の実装もそれなりに複雑なのですが、インターンの大森さんがやってくれました。ありがとうございます!

ユーザーインタビュー

本機能の導入にあたってはUIに大幅な変更を伴うため、ユーザーインタビューを綿密に行い影響を検証することにしました。

デザイナーと相談して検証項目とテストシナリオを決め、社員8人を対象に1人1時間ほどかけてユーザーインタビューを実施しました。

ユーザーインタビュー概要

テストシナリオ:

小中高の問題を実際に開発版のアプリで解いてもらいました。

検証項目:

ユーザーが理解可能か?ユーザーがスムーズに使えるUIか?

対象者:

なるべく多くの属性を持つ方(理系、文系、セールス、エンジニア、...)に積極的に関わっていただきました。

ユーザーインタビューの風景

ユーザーインタビューで見つかった課題

ユーザーインタビューからは多くの示唆が得られました。 使い方がわかった人にとっては便利であることが確かめられた一方で、重要な課題として、画面を見ただけでは使い方がわからない人がいるということが分かりました。

回答ペンは使い方がわかっている人には使いやすいのですが、新規性が高いUIであるがゆえに使い方の説明が必要になりました。

モノグサのValueには全人類に届けるのを諦めないというものがあり、このままではリリースすることができません。

デザイナーに相談したところ「アプリは繰り返し使うものなのでその中でユーザーは慣れていく、初心者のままでいたがるユーザーはいない、UIとしては中級者以上に便利なUIを目指すべき」という助言をもらいました。 アプリ自体は熟練者に使いやすく、初心者には適切に使い方を伝えるという方針にしました。

ユーザーインタビューで見つかった改善事項の反映

可能な限りチュートリアルがいらないほど使いやすいアプリを目指すべきではありますが、デザイナーと相談し、全人類に使ってもらうために数式の画面に関してはチュートリアルを入れる方向にしました。 アプリ内でチュートリアルとして、gifアニメを表示することにしました。

なんか分かりやすいアニメできますかと聞いたら、すぐに凄腕のデザイナーが素敵gifアニメを作ってくれました。

QA

数式手書き認識は大掛かりな変更であり、QAエンジニアに事前に相談しながら手書き認識周りの動作検証を項目の検討含めて依頼しました。 新規機能だけが壊れていないかだけでなく、既存の動作が壊れていないかも検証する必要があります。 10個のテストケースと40超の入力パターンで動作確認してくれました。

動作検証の結果、数式手書き認識で複数問解くと端末が遅くなり、最終的にはクラッシュするという事象が発見されました。 調べたところPytorchのモデルがメモリリークしていたことがわかり、メモリを適切に解放することで修正することができました。

iOSの適用、OSSへのコントリビュート

以上の経過を経て、Androidでは無事リリースできた数式手書き認識ですが、MonoxerはiOS向けにも提供しており、iOSサポートも進めました。 そのためにはロジックの移植の他に、深層学習モデルをiOS上で動作させる必要があります。 AndroidではPytorchを使って動作していますが、iOSではアプリ容量の削減や高速化のため、CoreMLを使うことにしました。 そこで、Pytorch向けのモデルをcoremltoolsを使って、コンバートすることにしました。 いざやってみると、使っている深層学習モデルのうち一部のPytorchでの記述がcoremltoolsによってコンバートできないことが発覚しました。

これに対しては、

  • Pytorchモデルの書き直しで対応できるものは書き直す(同等の計算結果が得られてcoremltoolsがサポートしている記述方法に書き換える)
  • coremltoolsにPRを出してエンハンス

の二つの戦略を取ることにしました。 coremltoolsのエンハンスは本家のリポジトリにPRを出し、Apple社のメンテナからいくつかレビューコメントを受けつつ、無事マージすることができました。 coremltoolsへのPRとしては

まとめ

書ききれなかったのですが、実際には機械学習モデルを含めた自動テストやモデルのデプロイなど色々悩ましいところも大森さんやインフラエンジニアと検討して進めるなど、広い領域にまたがったお仕事でした。

数式機能を初めMonoxerはまだまだ改善したいところばかりです! Monoxerを全人類に届けたいデザイナー、エンジニア、その他皆様大募集中です!