数式手書き認識アプリを作る

UI側の実装の事情を最大限に考えた手書き数式認識のモデルとアプリを作る。 Galaxy Note 3のペンで使うのでCPUで。名前を「手書き数式認識」を縮めて「tegashiki」と呼ぶ事にする。

github: tegashiki

考えている事

数年前まではDeep Learningはやりたい事から考え始めてもうまく行くモデルが作れなかった。

ただ一昨年と去年の経験では、そろそろやりたい事から始めてもいい線行くんじゃないか?という気がしてきている。 それはモデルの学習回りが進んだ事と、モデル自体も学習しやすくてシンプルな奴が増えてきた事、 ライブラリ回りもより成熟してきた事、自分自身に経験が貯まってきた事などの複合的な要因で。

そこで今年はやりたい事から考えてモデルをそれに合わせて設計する、というのをやってみようと思う。

さて、最近数式表示のAndroidのViewを作ったら、これが出来が大変良くて気に入っている結果、 フリックでTexを入力する事がすごく増えたが、これは凄くかったるい。 という事でペンでTeXを入力したい。

という事で、今の所はアプリに組み込む、手書き数式入力の機能を実装したい。 最終的には単体アプリでは無くMeatPieDayに組み込むつもりだが、しばらくは単体アプリとして開発していくと思う。

最終的には全体の画像を与えて認識するというよりは、IMEのように使いたい。 入力の途中で候補が複数出て選んでいく、という感じで。 モデルも最終的にはその用途に応じた物を作りたい。 ただ最初にあんまり最終形を目指してもいつまでたっても出来る気がしないので、既存のモデルに近い形から始めて、 徐々に最終形に変えていきたいと思っている。

この時期の要約

  • プロジェクトの名前をtegashikiに決定
  • 最初は画像からtexを生成する既存モデルを評価し、それを単純化した物を作った
  • ただ、TPU使う形に作れなかった事からあまりしっかりした評価は出来てない
  • Crohme2019でベクトルデータが公開されたのと、ここまでの経験から画像は辛いと結論づけて入力をベクトルデータに変更
  • 簡単なGRU+Attentionのモデルを作る
  • データセットの準備や評価の環境を整える
  • TPUでのトレーニング回りを整備
  • 全然スコアが出ない事を確認

開発日記

2019/05/06

開始。

ベンチマークとして作りたい物とはちょっと違うが、以下を動かしてみよう。

https://github.com/whywhs/Pytorch-Handwritten-Mathematical-Expression-Recognition

PyTorch環境作るのと、作業用のGCPインスタンスを作ったりする。

Androidに載せるのはもっと単純なTensorflowで適当に書いたモデルから始めたいが、 まず既存モデルでトレーニングとかの周辺を整備。

まずはDockerfile。Pytorch環境は初めて作るので、適当にそこらへんにあるのを持ってきて自分用に書き換える所から。 一発で持ってきたモデルが動くとも思えないので、しばらく格闘する事になるのかしらね。

ディスクが足りないといわれて増やして今日は終了。

2019/05/08

再開。イメージは出来た。

サイトのreadmeによると、まずtrainingとtestのデータを解凍せよ、とか書いてある。やってみよう。

rarのver 5で開けない、とか言われてnon-free版のインストール方法を調べたりする。 https://www.linuxquestions.org/questions/linux-software-2/which-unrar-is-available-in-debian-today-4175614117/

次にgen_pkl.pyを、中のハードコードされてるパスを変えて実行せよ、と言われる。 これはdockerの中でやるか。

pandasが無いといわれる。このイメージは良く理解してないが、どうもcondaのenvironmentというのを使っているな。

conda install --name pytorch-py35 pandas

でpython gen_pkl.pyが動くようになる。イメージはあとで作り直そう。

次はDensenet_testway.pyを実行するっぽい。

$ python Densenet_testway.py
Traceback (most recent call last):
  File "Densenet_testway.py", line 6, in <module>
    import torch
  File "/opt/conda/envs/pytorch-py35/lib/python3.5/site-packages/torch/__init__.py", line 80, in <module>
    from torch._C import *
ImportError: libcudart.so.9.0: cannot open shared object file: No such file or directory

ふむ。少し調べるとCPU onlyでもlibcudartは入ってて動くはず、との事。 findを見るとlibcudart.so.9.2は入っている。 何かバージョン違いっぽい。

なんかpytorch=0.4じゃなくてpytorch=0.4.0じゃないとダメっぽい?

いろいろいじって、GPUじゃないと動かない感じのコードになっているのを理解。 だがとりあえず少しいじってCPUで動かせるならCPUで動かしておきたいな。

少しPyTorchを勉強するか。

PyTorchのGetting Startedを読む。

2019/05/09

PyTorchの基本くらいは理解したので、続きの作業に戻る。 まずDockerのイメージをpytorch-cpuに変更。

一通り直して動き出した。CPUでも一件あたりは1secはかかってないな。 これなら実機でもCPUで動かせそうな気がする。 ダラダラと流れるログをぼけーっと見てると、まぁまぁいい感じに動いているように見える。 誤認識している時も結構惜しい。

一旦変更をgithubに残す作業をする。 本家をforkしてcpuというブランチを作ってそこに入れておく、くらいでいいか。 今の所これを直していくというよりは、これをベンチマークにもっとしょぼい奴を動かしてそれを改善していく予定なので。

とりあえずこのモデルとコードを理解してみよう。方針を考えるのはそれからかな。

encoderとdecoderがあって、encoderにはdensnetというのが使われている。 これは https://arxiv.org/abs/1608.06993 らしい。 ちらっと読んだ感じskip connectionがたくさんあります、という程度に見えるが、めっちゃreferされてるので意外と定番なのかもしれない。

軽く読んでみた。思ったより良さそう。 当初はMobileNet使う気だったが、Densenet-BCでいいのでは?という気がしてきたので、少しこの路線で行ってみようと思う。

で、元の手書き認識、Encoder回りはDensenetがほぼそのまま使われている。 いろいろコードを書いてあるのだが、だいたいは本家のPyTorchのDenseNetのコードをコピペしているだけっぽい。

https://pytorch.org/docs/stable/_modules/torchvision/models/densenet.html

encoderは最後のpoolingとclassifyだけ外した物に、ロードした物をそのまま食わせている。 ただ結果のoutのsizeの1と2を取り出して何かやっているなぁ。

  output_area1 = output_highfeature.size()
  output_area = output_area1[2]
  dense_input = output_area1[1]

これはなんだろう?ちょっと次元を出力したりしたいな。

decoderは自分で手作りしている感じはある。こちらも思ってたよりもずっとシンプルだな。 これをベンチマークにもっとシンプルな所から始める気だったのだが、思ってたよりずっとシンプルだ。

(追記: これについての論文は以下と思われる。 arxiv: 1801.03530 Multi-Scale Attention with Dense Encoder for Handwritten Mathematical Expression Recognition

Multi scale attention、というのが発明らしい。確かにそれっぽいコードがある。 自分としてはこういうの無しの、単純なdensent+GRUのdecoder+attentionというあたりから始めるのが良さそう)

よし、次にやるべき事はこのdecoder周辺の入力の理解だな。 ここを理解すればこのモデルはすべて理解した事になりそう。

codelabに移植するか悩むな。 本格的に開発していくならやるんだが、あくまでこれはベースラインだからなぁ。 移植するくらいなら自分のモデルを作ってしまいたい気もする。

このまま進む前に周辺の既存研究を見ておこう、と関連論文をいろいろ探す。 2017年のarxiv:1609.04938 Image-to-Markup Generation with Coarse-to-Fine Attentionがこの手の問題設定としては初期の物っぽい。 手書きフォントで合成したデータセットを作っていてそれでpre-trainした、みたいな事が書いてあって、そのデータも公開されてるっぽい。 これは同じ事をやる気だったので、既にあるなら使わせてもらおう。

モデルはちょっとグリッドに切ったり特殊だな。 最初に評価するモデルとしてはもっとシンプルな奴にしたい。

2019/05/10

実機で動かすモデルを考えるべくTensorFlow LiteでDenseNetとか動くのか?というのを調べる。

https://www.tensorflow.org/lite/guide/hosted_models

うーむ、floating point operationが必要で、こいつはTensorFlow Liteをカスタムビルドしないといけないのか。 しかもそれじゃあたぶん自分のL端末では使えないだろうなぁ。 なおCPUの方はtarget SDKが21だったので手持ちの端末でも動きそう。よしよし。

上のページはDenseNetのスコアがやけに低いのは気になるが、MobileNetは結構良かったと菊田さんも言ってたので、EncoderはMobileNetに出来ないかしら?

とりあえずサイズ的にはV2でも良さそうなので、V2の使い方とかを見る所から始めたいな。

トレーニングはTF.slimというAPIを使ってるんだが、これはトレーニングとかまで含めたコマンドラインから実行するフレームワークみたいになっている。 TPUEstimatorから使う方法は良く分からんなぁ。

ググってると、kerasのMobileNetモデルの変換はまぁまぁハマるっぽいが、 一応皆なんらかの形では出来ているっぽい。

例えば一番参考になりそうなのが みらいテックラボというブログで書いてある「金魚って見分けられる?(3)」。

実は以前Inception V3ベースの自作モデルをコンバートした事はあるので、どの程度めんどくさいかは多少は知ってる。 出来る実例があれば頑張れるかな。

という事で、とりあえずはKeras+MobileNet V2+TPUEstimatorベースで作って、それから実機にもっていく、というのが良さそう。 最初に作る環境は決まった。

機械学習の勉強において、具体的なタスクに挑む大切さ

機械学習というのは、入門書を読んだりMNISTのトレーニング的なのを動かしても、いまいち分からない。 そこから先何をやっていったらよいかもいまいち分からない。

やはり何か具体的なタスクを解く、というのが良いよな。

具体的なタスクを解くのは凄く難しくて、 ほとんどの機械学習屋は出来てないくらい難しいんだが、 一部のスーパーマンしか出来ないという程でも無い。

TensorFlow Liteとは何か?とかセッションの動画とか見るよりは、 DenseNetベースのモデルを自分のLollipop端末に載せたいが出来るのか?という視点で調べる方が、 それが何なのかとか現状がどうなのか、というのは良く分かる。 それは作り手が宣伝してない項目を多く含むからだ。

また実際に何かタスクを解くと、関連する論文をいろいろ読む事になる。 DenseNetが何なのかとかMobileNet v2はどんななのか、とか。 この解きたい問題に向かって論文を読んでいくというのが大切だと思う。

普通は仕事だとその辺の進め方を表に見せるのが難しい事もあるのだが、 今回は完全に趣味の機械学習でかなり手ごわいタスクなので、 割と珍しいコンテンツになるかも?

2019/05/11

今日はcodelabsに環境を作る。 このMLを使った実アプリ開発という観点では大きく三つの作業があると思っている。

  1. codelabs上でトレーニング、テスト環境を作る
  2. 実機に載せる作業
  3. モデルを改善していく作業

という事でついに三つの主要な作業の一つ目に取り掛かる時が来た。

まずはベースラインと同じデータセットに対して自分のモデルに対して同じ評価をして、どの位性能が落ちるかを確認しよう。 という事でCROHME14のデータを確認するとgzipで10Mbくらい。 これならcloud storageに置いてcodelabsから毎回落とせばいいか。

cloud storageを作るにあたり、バケットの名前を決めたい。 この手書き数式認識は最終的にはMeatPieDayに組み込む事になる気がしているので単体のアプリじゃなさそうだが、 ライブラリとして分離出来るならするかもしれないし、プロジェクトの名前はやはり要るだろう。

手書き数式を略して、なんかローマ字で短いのがいいな。手式とかteshikiでググったら結構ぶつかるので、「手が式」、つまり「tegashiki」に決定。 5日目にしてようやく名前が決まる。

午後。codelabsにdictとかをロードして必要な形に変形する作業。 画像のサイズが可変なのでpandasにつっこみにくいな。どうしたもんか。

とりあえずencoderがなんとなく出来た。といっても一画像のpredictを動かしただけ。 まずは全部つなげるのが最初なので。

decoderをどう作るか思案中。 最初は簡単な構成にしたい。 kerasでRNN書いた事は無いので書き方を見ているが、tensorflowより式をそのまま書かない分かえって分かりにくいな。 ただやりたい事は一通り出来そう。

ここはちょっと時間かかるのは仕方ないな。モデルの本体なので。

2019/05/13

昨日はスマホが動かなくなって復旧作業してたらやる気が尽きたのでお休み。 今日は本題のDecoderの方を考える。 一番シンプルだがとりあえず動きそうな物にしたい。

keras側で必要な道具をなんとなく理解したので、ベースラインとしているデコーダーのコードを理解する。 これはmultiescale attentionというのが売りになってる都合でその周辺のコードが複雑になっているのでちょっと手間取ったがだいたい理解。

自分が試すモデルとしては単純にencoderのoutputをWxHとした時、適当な小さめのNNにこれを食わせてアテンションのweightとし、 このweightとencoderのoutput自身の内積をもってコンテキストベクトルとしよう。 足として残るのはMobileNet V2の1280かな。 なんとかなりそうか?

調べものとかしてただけで今日は終わってしまった。

ただ、だいたい方針は決まったかな。 一番シンプルな物だと、以下の論文のデコーダーに、

arxiv: 1609.04938 Image-to-Markup Generation with Coarse-to-Fine Attention

単純なアテンションにした物が一番単純な気がする。 この論文ではpositional encoding的な効果が入るような工夫が入っているが、それはやらないでやってみたい。

という事で最初はそんな感じの実装にしよう、と決めた。

だいたいの方針は固まったので明日実装しよう。

2019/05/14

モデルをちまちま書いて行く。 ちょっとトリッキーなので通常のkerasのRNNでは組めないという結論だが、 それを理解するのに時間がかかった。 まぁKerasでのRNNは初めてなので想定内。

2019/05/15

ちょっと千葉に用事があって電車で往復してる間にKerasの作者の本のRNNのあたりを読んだり考えたりする。 KerasでのRNNを自分で一から書くのは初めてなんだなぁ、といろいろな所で引っかかって思う。 やはりこの手のは自分のタスク用に自分で一回作る、が一番良い勉強になるのだが、 それって相当難度高いのだよねぇ。

いろいろ考えた結果、これまで考えていたモデルよりもう一段単純化する事にする。 だいたい整理出来て、それを元に実装していって、とりあえず入力からoutputまでのshapeは合った。

encoderの入力が可変長なのでどうしよっかなぁ、と思っていたが、MobileNet V2自体は今の所トレーニングする気はないので、 画像をfeatureに変換してpickleしておいて、このnumpyを食わせる、とすれば良いか、と思いつく。 将来的にはネットワークをfine tuningするなりグレースケール用に学習するなりしたいが、まずはこの辺を手抜きにする事でイテレーション速度を上げる。

とりあえずトレーニング出来る所までは行った。何か学習は進んでそう。 ただオーバーフィットさせようと少なめのデータで少し回したがダメだった。 うまく動いているかは微妙だな。まぁ調査は明日以降で良かろう。

2019/05/16

今日はいろいろ試行錯誤したいので、とりあえずTPUを有効にしよう。 TPUEstimatorはおいといて、とりあえず一つだけで。

と試していったら、batchの所以外の次元は確定させい、と怒られた。あらま。 どうしよっかなぁ。widthとheightは固定されてないのだが。トレーニングの時には固定すりゃ良いという話はあるにはある。 ちょっと固定させて作り直すか。

input_lengthが指定されてないー>MAX_WとMAX_Hを決める(本当は動的に変えたいしネットワーク的には変わってOKなのだが、TPUの制約)

tf.kerasじゃなくてkerasになってるー>知らんがな、と言いながら直す

以下のエラーが出る

ValueError: slice index 0 of dimension 0 out of bounds. ....

どうも入力が複数あるケースで動かないみたい? https://github.com/tensorflow/tensorflow/issues/28176

うーむ、20日前オープンのバグなので割とホットな奴か。 どうしよっかなぁ。TPU使えないとやっぱ辛いので、TensorFlowで書き直すかなぁ。かったるいけど。 ただせっかくkerasでトレーニング出来る所までやってしまったので、 学習回りでおかしい所が無いかを調べるまではここでやっておきたい。

とりあえずサンプル数14個でオーバーフィットしてない問題を追おう。

lossが下がらない時の定番、という事で、learning rateを下げてみよう。 またバッチサイズも1にする。お、ラーニングrate下げたら下がっていくね。

参考にしている方のtrainを見ると1000 Epochとか書いてある。マジか… 今14件でもまだ100 epochくらいしか試してないのに。

ただ、現状はlossが0.4167くらいであまり下がらなくなった。 ちょっとずつは下がるかもしれないが、やはりモデルが間違っている気がする。 少し考えたが、Decoderのinitial stateに何か画像の情報が要るよなぁ。 現状は何も渡してないが、これを適当に画像を集計した何かにしてやるのが良い気がする。 参考にしていたモデルもなんか平均を渡している?

さて、300 Epochくらい回してみたらだいたい飽和した。 だいたい感じはつかめてきたがどうしようかな。 100 epochくらいは回さないと結果が分からないとなると、やはりCPUでは辛いな。 TensorFlowに書き直すか。

2019/05/17

今日はTensorFlowで書き直してみる。 これでTPUで使えるようになるかは分からないのだが、それを確認する為の最小のサンプルを作るのとあまりコストは変わらない気がするので、TF版を作ってみる事に。 といってもtf.layersがほとんど同じなので、自分の認識ではplaceholderとloss回り書き直すだけ、と思っている。

とりあえずtensorflow化は終わってトレーニングは動き出した。少し流しているがlossの減り方はだいたい同じかな。 次はTPUEstimator化してTPUで動くかだな。

Estimatorで動くところまでは来たが、なんかロスが全然下がらない。何か間違っているのかしら? TensorFlowで普通に実行したらそれっぽく動いていたが…

2019/05/19

昨日はお休み。今日も頑張っていきましょう。

昨日NLP系の友人と話したところ、やはりこの程度ならちゃんとオーバーフィット出来るはずだからたぶんバグってるんじゃないか?と言われてそんな気がしてくる。 という事でその辺を調査していく。

softmaxが二回取られていた。前もこれやったなぁ。

サンプル一つ(98timespan)で過学習を試す。 なんか学習が進まない。全部EOSを学習したところで学習が止まる。

単純にGRUだけでこの系列を学習させる事は出来ないか?と試してみた>すぐ学習出来た。

attentionのコンテキストとconcatすると学習が進まなくなる。 attention側の次元が多すぎて系列側の情報と識別する事が出来ないっぽいな。 何も考えずにFCを挟んで次元を落としてみよう>学習するようになった

ロスがかなり下がった後、今度は上がって発散してしまった。 lrを下げても良いのだが、こんな簡単な問題がうまく学習出来ないのはモデルの方に問題があろう。 ちょっとパラメータが多すぎる気がするので、FCでは無くavg poolingに変更。>1サンプルにオーバーフィット出来るようになった

次は14件でオーバーフィットさせてみる。lrを下げないと学習出来なかったが、今のところうまく進んでいるっぽい? >400エポックくらい学習させたところで打ち切る。ロスはまだ下がり続けてそう。

Estimatorで学習させてみる>100エポックくらい回したところ、だいたい同じような動きをしていた。よさそう。

TPUEstimatorに乗せ換える作業の途中で燃え尽き。まぁここまで来れば大分順調だろう。

2019/05/20

TPUEstimatorではinput_fnで可変長が扱えないっぽい。まぢで? うーん、どうしたもんかなぁ。

CROHME2019ではベクターデータがあるよ、と教えてもらう。 ベクターデータのseq2seqの方がモデルは素直になるので、スコアがとりあえず出るならこっちのほうが良いのでは?という気がしてくる。 データを眺めていると単純にxとyの座標の列が入っているだけなのでアプリで同じのは作れそう。

latexの答えはground truthじゃなくて参考程度にしてね、との事だが、まぁとりあえずは使えそうな気もする。

実機に載せる所まで行かずに方針を変えるのは危険な兆候だ、というポッドキャストを昨日録ったばかりだが、ちょっとこっちの路線でやってみるかなぁ。

データを少し整形してみたところ、texがなかなか汚い。 ただ、knownなトークンだけ切り出していけば、だいたいはトークナイズ出来るんじゃないか?という気になり、その方針でやってみる。

validation setでアドホックなクレンジングの処理を入れてトークナイズしたところ、 1000件中50件くらいは使え無さそうなデータ、という頻度。これならまぁいいか。

training setでは9993件中 1803件がエラーに。う、トレーニングセットの方がエラーの割合が多いな。 ただ8000件くらいあれば学習は出来そうだし、現在のデータは一時的に公開されてる物で後日正式版が出るとの事なので、この位で進めてみるか。

座標データにfloatとintが混ざっている。そしてfloatの時は絶対値が小さい?うーん。 intは1000くらいの範囲っぽいので、1000でノーマライズしてみるかね? それなら全部1000でnormalizeする方が良いか? 画面サイズが1280とかなので全部2000でノーマライズする事にした。 大きい事には本当は意味もあるのだが、CNNと違って所詮は相対的な大きさだけが問題だし、 意味があったり無かったりするスケールの問題はやはり学習して勝手にやってほしいので。

なんとなくencoder-decoderにattentionを入れた物で学習が始まった。 ただencoder側はちょっと系列が長すぎるのでconv1d入れてavgpoolingで1/10にしてみた。 これでは元が短い系列だとまずいだろうが、とりあえず動くかどうかを確認、という事で。

1サンプルのオーバーフィットは出来た。14サンプルは遅くてちょっと確認の為にやるには時間がかかりすぎる感じ。 ただ30分くらい回した範囲ではロスは落ち続けているので問題なさそう。

2019/05/21

今日はベクトルデータのモデルをTPUEstimator化してみる。 まずはEstimator化から。

input_fn回りでちょっとてこずったが無事完成。 全データを食わせるとメモリ不足で落ちるが、これまで試したデータサイズ(14サンプル)にしたら動いているっぽい。

次にTPUEstimator化。 昔TPUEstimatorにした時のコードを持ってきたらどうも動かない。 以前より理解も進んだし、インストラクションに従って結局model_fnを書き直す方が早いな、と思い直して書き直す。

一応完成したっぽいが、やはりメモリ不足で落ちる。なぜだろう?バッチサイズさえ小さければ問題無いと思うんだが… ただそろそろTFRecordにするかと思っていた所でもあるので、TFRecordにしてみよう。 しばらく使ってみてcloud storageの料金の様子を見て、辛そうならちゃんとトラブルシューティングする。

numpy_input_fnというのを見つけて、これを使ってみたらEstimatorではちゃんと動いた。 単にDatasetやるだけではダメっぽいなぁ。

そしてnumpy_input_fnではTPUEstimatorは動かん。 うーん、仕方ない、TFRecord化するか。

TFRecord化してTPUEstimator動いた!爆速!すばら!

まだ動いただけでlossの履歴とか分からないのでそこはなんとかしたいな。 host_callというのを使うのか?>tensorboardでmodeldir開いたらlossは見れた。

validation setのlossが見れないな。 一応データセットの性質を考えればオーバーフィットは大分あとまではしないと思うが、どこかで比較してみる必要はあるか。

validation setはtrainingより大分長いストロークの長さのがあるので、これはTPUEstimatorの枠組みに載せるよりはEstimatorで計算する方がいいかもしれん。 あとでTPUEstimatorでトレーニングしたモデルをEstimatorで使う方法も調べてみよう。

とりあえずこれで全トレーニングデータでトレーニング回す環境は出来た。 1時間くらい回してみた所順調にlossは減っていってる。

まだかなり無駄なパラメータがあるので、とりあえずパラメータを削っていってから真面目な評価をしていきたいな。 という事でまずはおおざっぱな指針となる程度の指標で作業を進めていきたいな。

1000ステップで210secか。

結果をexport_savedmodelで保存しようとしたら、Conv1Dの所のExpandDimで、ReadVariableOpが使われてる、とかで保存できない。 ちょっと良く分からないが、export_to_tpuをFalseにしてしのぐ。

evaluationも動くようになったのでいろいろ評価。 EOSの時に終わりとうのを認識している以外はほとんどランダムかなぁ。 EOS以外のaccuracyを知りたいな。

そしてなんかpreprocesssがバグってるなぁ。

バグってた所を直して結果を見ると、なんかtokenize失敗する物が増えた。 そして増えた結果を眺めていると、結構直せそうなのも多いな。 いい機会なので日を改めてもうちょっとトレーニングデータを精査してみよう。

2019/05/24

二日ほどツーリングに行ってた。リフレッシュして再開。

ツーリングの間に、やはりロスでpaddingの所は抜くべきだ、という結論になる。 のでそこに向けての調査を少しやって、出来そうなあたりをつけた。

前回はpreprocessのバグに気づいて途中まで直したんだったな。今日はそこをもう少し精査していこう。

一通りデータのクレンジングを見直して壊れてた物を直した。

午後はmaskしたcross entropyを実装。結局自分で手で実装するのが一番楽、という結論に。 Maskレイヤーを正しく理解してればそれで良いはずと思うのだが、アテンション入れた時にどうふるまうかがいまいち分からず、そういう事を理解するよりロスを手書きする方がシンプルなので。 (追記:weightsで実装するのが正しかったがこの時点では気づかなかった)

で、accuracyもマスクを考慮するように変更して、一応解きたい問題と最適化している問題は大分近くなった。 指標も割と素直に実際のスコアを反映している気がする。

ただ全然良くないね。すぐオーバーフィットしてしまうし、accuracyも30%とか。これでは使い物にならない。 dropoutとかを入れるよりはモデル自体のパラメータを減らす所から始めたいな。

なんにせよ、ちゃんとしたモデルがとりあえず評価できる所までは来たヽ(´ー`)ノ

少しいろいろ評価していたが、やはり全然ダメだなぁ。ここからどうしたもんか?

パラメータを変えた物を流しつつ、モデル回りで論文をいろいろ眺めてみよう。 まず間のパラメータが明らかに多すぎる所があるので、それらを踏まえていろいろ削ったモデルの挙動を見てみる。

パラメータサイズを変えてみた所、なんか変な事が起きている。 validation setのlossが上がっているのにvalidation setでのaccuracyが上がってる。 トレーニングのロスは下がり続けていて、トレーニングとvalidationのロスのロジックは同じにしているつもり。

validation setでのaccuracyはvalidation setのロスとだいたい一致しそうなものだが。 ただ、どちらにせよスコアが悪すぎるのでこれはパラメータを減らし過ぎな気がする(いっぱい学習すると違うのかもしれないが)。

眺めた論文

既存研究から、点が多すぎる問題をどうしているのか、という視点で見ていると、 やはりプリプロセスで減らしている気がする。 音声はメル・ケプストラムを使っている事が多くて、 sketch-RNNはRamer–Douglas–Peucker algorithmというのを使っている。 これを使ってみるか。 実装しようかと思ったらパッケージがある。

https://pypi.org/project/rdp/

よしよし。これを評価してみるか。

評価してみた所、sketch-RNNのepsilonは大きすぎる。0.05~0.07なら何が書かれてるかは分かりそう。 0.05で試してみるかな。

そして何気なく8000件のトレーニングセットに実行したら帰ってこない… 今日はここまでにしておくか。

次スレ 手書き数式認識ソフト、tegashiki開発その2