手書き数式認識ソフト、tegashiki開発その3
前スレ
ここでやった事概要
- 一シンボルのみのデータセットを使って認識問題を解いてみた(acc 0.77くらい)
- ストロークをフィーチャーに直す、という路線で行く事にした
- やはりスコアが出ない事を確認
- ストロークを全部無視したのと大差無い事を確認
やはりdecoderの組み合わせが複雑すぎなのでこのデータセットでは本質的に学習出来ない、と結論づける。 簡単な数式のデータセットを人工的に合成する路線で行く事を決定した。
2019/05/29
今朝歩いていて、シンボルのサブタスクのデータを使って、二つくらい並べる、という事が出来るんじゃないか?と思いつく。 2xはOKだがx2はダメなので、その辺並べ方に制約はあるが。 一文字だと後の長い奴と別物として学習されてしまうんじゃないかなぁ、と思っていたが、 二文字が学習出来れば長い奴もその延長で学習できるんじゃないか?という気がする。
という事で今日はサブタスクのデータ処理から始めよう。
取り出して保存する所のロジックは書いたが、飽きてきた。うーん、かったるい。 こういうのはちょっとずつやっていくのが大切だな。 適当な所で切り上げて、しばらく別の事をやろう。
うーん、切り出したデータを眺めてて思ったが、TeXとして完全じゃないトレーニングセットはどうだろうか? 例えば閉じ括弧だけ、とかはTeX的には正しくない。 最初の段階ではそういうのでトレーニングするのも有効かもしれないが、組み合わせの処理とか考えておくと抜いておいてもいい気はする。
さらに考えると、意味のある最小の組み合わせ、は手動で作る方が良い気もするな。 5文字くらいでいろんなパターンを人力で考えてそのデータを生成して、それでトレーニングする事から始めたい気がする。 これは結構時間のかかる作業だなぁ。
2019/06/05
一週間ぶりに再会。 最近は引っ越し回りで人にあったりいろいろしていたのと、今後の方針をちょっと時間を取って考えていた。
とりあえずサブタスクのシンボルデータを前処理して、シンボル認識問題を解いてみる。 これはsequential MNISTに毛が生えた程度の問題なので解けるだろう。 シンボルの終わりも判定する必要があるが、その前にまずシンボル認識問題を解く所から始める。
Ramer–Douglas–Peucker algorithmでシンボルの頂点データを削ってとりあえずシンボルのトレーニングデータを作った。 なんだかんだでrdpは10分ちょっとかかるし、そこそこ時間はかかる。 最大のシークエンス長は300ちょっと。これならpooling無しで行けそうね、よしよし。
TPU用にtfrecordの用意も出来たので、何かモデルを作ってみよう。 まずはただconvolutionした後にGRUに食わせて、最後の結果をFCにつないでsoftmaxしてみよう。 この位でもまぁまぁ解けるんじゃないか。
パラメータ小さい奴でやってみたら、acc 0.24とかで学習が遅くなってきた? とりあえず回しながら寝る事にするが、なんか意外と苦戦しているなぁ。 sequential MNISTなら0.93とか行くのに。
2019/06/06
2.7時間くらい回した所 acc 0.297とかでまだ伸びている模様。もっと回しておくんだったなぁ。 メモリ回りとか殺され回避(になってるか知らんが)のため、セッションを作り直してトレーニング再開。
最低でも0.8くらいは行ってくれないと前処理には使えないと思うので、全然足りないなぁ。 実際にはストロークの終わりも判定したいので、もっと難しい問題になる事を思うと、この問題自体は0.9くらいは行って欲しい。
もう1.5時間くらい流したら、なんか傾きがまた大きくなってきた。まだしばらく下がるのか。回しまくろう。
さらに3時間くらい回したが、まだロスは下がり続けて、accも0.492に。 やはりlearning rate低すぎじゃないか?という気もするんだが、昨日ちょっと上げたら全然ダメだったんだよなぁ。回し足りなかったか?
何にせよこのペースでも一日とかのオーダーでそれなりに良いスコアまでたどり着くはずなので、ひたすら回しつつ他の事をやる。
夕方、accが0.59くらいまで来た。 トレーニングセットとvalidation setのlossもそろそろ追いついてきてトレーニングのlossが下がらなくなってきたので、この辺で限界っぽい。 これなら間の層とかのパラメータ増やせばもっと行きそうね。
だいたいacc 0.60で飽和したので止める。
これならパラメータサイズ大きくすればいい線行きそうだが、その前にTCNを試したいのでTCNを試す。
2019/06/07
tcn_large_nonreg acc 0.129
(追記:バグでdropoutは指定を無視して0.2になってた)
元論文の実装と比較すると、自分の方がfilterサイズが小さい。 これはresidualに足す時に次元を合わす為にこうしたのだが、本来はここで1x1 convを挟んでdown sampleすべきと書いてある。 やってみよう。
tcn_large_nonreg_filter25 acc 0.135
(追記:バグでdropoutは指定を無視して0.2になってた)
あ、入力の方を増やしてそろえるのか。逆にしてた。やり直し。
tcn_large_nonreg_filter25_fix acc 0.048
(追記:バグでdropoutは指定を無視して0.2になってた)
なんかトレーニングのロスは下がるようになったが、全くvalidationのlossが下がらない。 単純に答えを覚えてしまっている、という事だよなぁ。dropout入れるか?
tcn_large_dropout05 acc 0.02
(追記:バグでdropoutは指定を無視して0.2になってた)
全然ダメ。トレーニング誤差は割と下がるのだが、validation lossは全く下がらない。 どういう事だろう?
tcnがバグってるかの切り分けの為に、試しにrcnnのlargeを試してみよう。
l2 regularizationは0.0だと怒られるが、この処理をコードに入れると煩雑になっていまいちだな。 以後はいつも0.1で試すか。(ここまではnonregは0.0だった)
おや?これでもvalidation lossが下がらない。 largeがダメなのか? >しばらく学習を続けていたら下がった。
ただトレーニングのlossはTCNの方が低い。どうもTCNは答えを丸暗記してるっぽいなぁ。
途中からオーバーフィットしてaccは上昇してしまう。
rcnn_large_nonreg acc N/A
今度はtcnでdropoutを直して試してみよう。
tcn_filter25_dropout09
これまたtraining lossだけ下がっていく。
dropoutを0.9にしてもtcnがトレーニング誤差だけを下げていくのはやはりおかしい、と思いデータセットを見直す。 ノーマライズせずにintにしているので結構問題がある気がしてきた。 やはりノーマライズしよう。
ノーマライズはバグってた事に気づいたのと、いろいろなデータがあればそのまま食わせても平気か?と思った事からやらなかったのだが、これだとデータの特徴が多すぎてダメだなぁ。
という事でnormalizeを直した。normalizeしよう。
tcn_filter25_dropout09_datanormalize
やはりトレーニングセットだけ下がっていく。
ふとデータをいじってて、そういえばpaddingする長さが違うよな、と気づく。 マスク処理が要る気がするな。どうしたらいいんだろう? >短い方(validation set)をpaddingしてみた
2019/06/08
tcn_pad_valid acc 0.658
よし!ちゃんと動いた!training lossはかなり下がるがvalidation lossは途中で下げ止まる。 augmentation入れると良くなりそうな気がするが、とりあえず今日は勉強会なので時間も取れないので、 filter sizeを10に減らして流しておく。
そういえば、シンボルにfracとかあるのかね?これ無かったらpreprocessに使う、という作戦は出来ないよなぁ。
2019/06/09
tcn_filter10 acc 0.645
まだ下がっているのでもうちょっと改善しそうだが、もう結構回したので一旦違う事をやる。 気配としてはfilter10の方がオーバーフィットしてなさそう。スコアがfilterが25より良くなるかはまだ分からないな。
昨日勉強会で少し話したのと、しばらく散歩して考えた結果、ストロークをやはり何かのfeature vectorにするのが良い気がしてきた。 ストロークは可変長だが、適当にpaddingしてcnnでフィーチャーを取り出す。 そしてそのトレーニングはシンボル一つのデータセットで行う。 これは結構いいんじゃないかな?やってみよう。
ストロークごとにパディングしていろいろ整理していたら結構時間がかかってしまった。 まずストロークの長さの分布を調べて、最大を50になるようにrdpで削減する。50より小さくなるまでepsilonを倍にしていく、みたいなコードなので結構時間がかかるが無事終わった。
無事それっぽいデータが出来たのでモデルを作る。
まずはfeature extractorとして3層のconv netにして、その先にGRUをつなげてみる。 長さは今回はたかだか10なので、大したモデルである必要も無いが。 extractされた次元は512で行ってみる。
rnn_dropout05_pad acc 0.775
劇的に改善した。トレーニングの時間も12時間以上かかってたのが30分くらいに短縮。やはりモデルを工夫するのは大切だよなぁ。
feature extractorをそのまま流用する為にtf.variable_scopeをつけてトレーニングしなおしたい。 という事で、ついでにfeatureの次元を256で試してみよう。
rnn_fdim256 acc 0.758
512次元のケースより多少オーバーフィッティングしている風味だが、大差無さそう。 これで行ってみよう。
明日は数式の方のタスクのデータセットを同じ形にする作業からだな。
2019/06/10
なんか朝早く目が覚めてしまったので昨日の続き。 数式の方のデータセットもストローク数をpaddingしたり削ったりして50に固定するデータセットを作る。 シンボルの方とほとんど同じ処理なので割と関数は使いまわし出来て、まぁまぁ順調に作れた。
次に昨日作ったrnn_fdim256のfeature extractorの部分だけ使いまわし、その先にGRUのencoderとdecoderをattentionをつけてつなげてみる。 こちらはストローク数が100くらいにはなりうるので、たぶんこの程度のモデルではそこまでうまくは行かないだろうけれど、方針があっているかくらいは確認出来る事を期待。
padstroke_small_rnn_small_dropout05 acc 0.36
なんか前のcrnnとあまり変わらない挙動だな。 どうもvalidation setのロスがすぐ下がらなくなる。 なんかこれ、token lenがそろってないせいなんじゃないか? attentionのコード見てると、ストローク側のマスクをちゃんと見れてない気がするので、paddingの影響をsoftmaxが受けてしまいそうな気がする。
揃えてみるか。
samelen_small_rnn_small_dropout05 acc=0.34
ダメっぽい。
比較の為、strokeを一切見ないモデルを作ってみよう。 teacher forcingの入力だけから結果を予測する。
samelen_nostroke acc=0.38
何もストロークを見ないモデルの方が当たる。うがぁ。つまりこれまでのモデルは全然ダメか。
少し短いシーケンスについてだけ問題を解いてみたいな。 その為にはpaddingしてないデータセットを作り、padded_batchで食わせれば良さそう? やってみよう。
うーん、バッチの中だけpaddingすれば良い、とどこかに書いてあった気がしたので試しているが、 そもそもXLAは全Tensorのdimがstaticに決まらないとダメだ、と書いてある。
そしてstrokeの長さをpadding_batchのNoneでバッチ内の最大長にしていると、どうしてもdimの定まらないtensorが出来てしまう。 という事でバッチごとに長さの違うフィールドを持たせるのは無理なんじゃないか。
別に最大長は分かるので、numpyで調べてそのサイズでパディングする。 トークン10以下のトレーニングセットは3000件くらい。 さすがにこれでは学習は出来ないだろうなぁ。
varlen_10_small_rnn_small_dropout05: acc 0.31
全然ダメだ。
やはり簡単なケースを生成して、そこから学習していく、という路線にしよう。
1シンボル認識問題のモデル
issueは立てたがまだ何も書いてない。
この日記と手元のスクリーンショットを突き合せれば一通り書けるのだがかったるい。 うーむ、まぁ必要になったら書こう。
次スレに続く。 手書き数式認識ソフト、tegashiki開発その4