2018年6月24日日曜日

SAMSE: Sign-adjusted Mean Squared Error

回帰の損失関数は色々あるのですが、昔からなぜないのだろうと思う計測方法があります。 それがタイトルにも書いたように、符号調整済みの平均二乗誤差。 特定の数値を基準にして、一定の数値以上か以下かで損失の与え方を変える誤差関数です。 まあ平均二乗誤差 (MSE) ではなく、MAPEやMAEベースでも良いのですが、とにかく符号を考慮するとどうなるのかと思ってました。

この損失関数はどこに使えるかというと、 例えばノイズのあるsin波を予測し、0以上かどうかで何らかの処理を判定する時に使えます。 そのような条件の場合、0.1と予測して0.3だった時と、-0.1だった時では意味が異なるのですが、 MSEなどの有名な損失関数ではこれを適切に扱えません。

似たような事は他の手段でできない事もないのですが、 (1)分類誤差と二乗誤差の合計値を損失関数にすると二乗誤差部分は正負を考慮できない問題が残ります。 経験的にも二乗誤差に予測が引きづられ過ぎてしまう印象がある。 (2)クラス分類でサンプルの重みを変えたりすると多少は数値予測っぽさは出せますが、softmaxに縛られ過ぎてしまう問題が残ります。 (3)出力を分割してそれぞれMSEで損失を計測するのは近いと思いますが、これだと全体に損失をかけにくくなる。 そのためクラスの重みをある程度考慮しつつベースは距離関数という損失関数のほうが、 使い勝手が良いケースもあるのではないかと以前から思っていました。

回帰は1を基準にする事のほうが多いと思うので、以下のように1を中心にKerasでカスタム損失関数を実装してみましたが、ones_likeをzeros_likeにすればより符号っぽさが出ます。
def samse(y_true, y_pred):  # sign-adjusted mse
    ones = K.ones_like(y_true)
    p1 = K.cast(K.greater(y_true, ones), K.floatx())
    n1 = K.cast(K.less_equal(y_true, ones), K.floatx())
    p2 = K.cast(K.greater(y_pred, ones), K.floatx())
    n2 = K.cast(K.less_equal(y_pred, ones), K.floatx())
    rate = K.square(y_true - y_pred)
    pp = K.mean(p1 * p2 * rate, axis=-1)
    pn = K.mean(p1 * n2 * rate, axis=-1) * 2
    pn = K.mean(n1 * p2 * rate, axis=-1) * 2
    nn = K.mean(n1 * n2 * rate, axis=-1)
    return pp + pn + pn + nn

重みをどうするかとか、分布が少し歪むとかの問題もあるので一概に使い勝手が良いかはわかりません。 ただpp, nnのように予測が正しい場合には損失を計算しないようにするとか、部分的に絶対誤差にするとか、細かな改良はしやすい関数だと思います。 ちなみに上記の *2 の部分をなくせば普通のMSEと一緒。

まあ損失関数を作った事がないので遊びで作ってみただけですが、軽く確認してみた感じではMSEより正負を気持ち考慮できてるかなあという感じ。 計算上はMSEより損失が大きくなるはずですが、MSEより損失が小さくなるケースが多い。

2018年6月18日月曜日

non-CNNでMNIST

論文を読んでいたのですが、MNISTのランキングに載っていないnon-CNNの構造ってたくさんあるんですね。 2016年のRedditの内容としてLadder NetworkがCNNもData Augumentationも使わない構造としては99.43%でSoTAという話を見つけました。 色々な論文を読んでみたのですが、non-CNNで数値が載っているものとしてはだいたいこれが最良の結果になっているように思う。

Maxout Networksの論文にはランキングにないものがいくつか載っていて、 non-CNNでより良い精度を出すためには結構参考になるかも知れない。 RBFカーネルと組み合わせたりして良い性能が出る (計算量は…) ものもあります。 あとPermutation-invariant MNISTなどで検索すると微妙に意味合いは違うと思うのですが、よく似た研究が見つかります。 他にもGenerative ModelとかAdversarial Trainingを使ったものが結構あります。non-CNNの精度としてわかっているものはAAEで99.15%Adversarial trainingで99.29%VATで99.36%など。他にも99%くらいの結果はたくさんある。 ただCNNと組み合わせたものも多いのでこちらの正確な比較は大変。 学習も難しいし。


公開されている実装としては、確認しやすいものとしては以下の実装がある。 これらを利用して軽く確認してみたのですが、パラメータチューニングが難しかったり、学習が遅かったり簡単ではない感じ。 コツを掴まないとそう簡単には良い感じには取り扱えないような気がしている。 何となくですが、以下の論文がほどほどの精度で一番楽なんじゃないか。
手法はシンプルで、(1)入力層0.2、中間層0.5のDropoutと、(2)fine-tuningで精度が出るという話。 様々な構造が途中で出てきますが、一番良い結果の99.21%が出たのは以下の構造みたい。

項目利用手法
活性化関数ReLU
最適化関数SGD + Momentum
モデル1784-500-1000-10

普通は784なのに1784というよくわからない数値になっているのは、第2隠れ層へのmean-fieldの1000ユニットを特徴として追加しているからとか。 ここで全結合ではなくDeep Boltzmann Machines (簡単説明) を導入している。 チューニング前の論文では99.05%の精度が出ると主張しているので、0.21%の更新になるという事ですね。 ただDeep Boltzmann Machinesを使わない全結合でも99.08%まで出るらしい。 これがシンプルな割には良い結果だなと。

SGD + Momentumは遅いのでおもむろにAMSGrad + Early Stopping (patience=0) を使って確認してみました。 汎化性能はSGD + Momentumのほうが上という報告もあるし参考値です。 最初はlearning rate=1e-3で学習し、fine-tuningで学習率を上表のように下げればまあまあの精度が出ます。 追試するならSGD + Momentumを使うべきなのですが、Dropoutの調整とfine-tuningの効果はこれでも実感できるし、まあ良いかなと。

構造テスト性能
784-2000-2000-10 AMSGrad (lr=1e-4)98.79%
784-2000-2000-10 AMSGrad (lr=1e-5)98.73%
784-500-500-10 AMSGrad (lr=1e-4)98.52%
784-500-500-10 AMSGrad (lr=1e-5)98.45%
784-500-1000-10 AMSGrad (lr=1e-4)98.65%
784-500-1000-10 AMSGrad (lr=1e-5)98.57%

全結合の標準性能である98.40%は簡単に超えました。 99.08%には到達していませんが、思っていたよりは簡単に多少の精度改善ができました。

ついでなのでMaxoutもやってみる。Maxoutは from keras.legacy.layers import MaxoutDense すれば使えます。 最適な構造もわからないけど、軽くやってみた限り平凡ですね。

構造テスト性能
784-2000-2000-10 AMSGrad (lr=1e-4)98.47%
784-500-500-10 AMSGrad (lr=1e-4)98.53%

non-CNNで手軽にもっと性能が出ないものか。

2018年6月2日土曜日

フリゲ紹介: 人類滅亡後のPinocchia (ピノキア)

人類滅亡後のPinocchiaRPGアツマールでもプレイできるノンフィールド型のRPG。



アンドロイドを製造して仲間に加えながら上層部を目指していくゲームです (左下)。 最初は主人公の目的なども明確になっていませんが、階層が上がるごとに徐々にわかるようになっています。 30日の日数制限や限られたリソースのやりくりを考える必要がありますが、日数に関してはそれほど気にしなくても大丈夫だと思う。 最初仲間にできるのは汎用型のアンドロイド (右下) だけですが、探索が進むにうれて様々なアンドロイドが製造できるようになってきます。 このアンドロイドを駆使しないとクリアは難しいですが、全体を通してちょうど良い難易度だったと思います。



探索は前進と撤退の2つしかないですが (左下)、探索途中で様々な部品が拾えるので、それをアンドロイドの製造に活かします。 戦闘はアンドロイドたちは自律的に行動します (右下)。 そのため主人公がすべき事はアンドロイド達を補助する事になるでしょう。 アンドロイドは敵の攻撃を受けて壊れれば壊れるだけ攻撃の命中率が下がるなど、現実的な仕様になっているのが印象的でした。



早く次の階層を見てみたいと感じるせいか、一気にプレイしてしまいました。

ノンフィールド型のRPGは近年増えてきた気がしますね。 印象深い作品としては、メイジの転生録 (紹介) や、ロードライト・フェイス迷宮踏破K。 どれもノンフィールドの替わりに様々な趣向を凝らしていた事が面白さの根本にあったように思います。

本作品では、様々なアンドロイドを操り、リソースを管理しながら、主人公の謎を解くという3つの面白さが引き出せていた作品と思いました。 クリア後のエンディングもなかなか素晴らしい。

フリゲ紹介: イリゼグレイ -白黒姫と七色の宝石-

イリゼグレイ -白黒姫と七色の宝石-は、色が見えないお姫様エリスが、お城に迷い込んだ子竜のラナと一緒にお城を飛び出して冒険する探索RPG。



物事に興味があり過ぎるラナ (左下) と異なり、主人公のエリスは物事に興味がないため世界がモノクロに見えています。 マップも通常時はすべてモノクロになっていますが (右下)、頑張ってやる気を出すと短い時間だけ本当の色を見る事ができます。 色を見ることで、モノクロ時には見えなかった隠し通路などが見えるようになります。



カラーリングを活かしながら探索をするRPGというのはなかなか面白い仕組みだと思いました。 省エネプレイの私はカラーリングでTPを消費するのが嫌でサボりつつプレイしてしまいましたが、 回復アイテムは安価で手に入るので、ガンガン使いながらプレイしたほうがずっと楽しいと思います。 これからプレイする人はガンガンとカラーリングしましょう。

シンボルエンカウントのシンプルな探索RPG (左下) ですが、戦闘はちょっと風変わり。 1-3体の敵の攻撃をアクションでガードしながら魔法で攻撃します (右下)。 攻撃や防御をノーミスで行う事で様々な特典がもらえるような仕組みになっています。 慣れないと結構難しいけど、なかなか面白い。



プレイしていて新鮮なRPGでした。

フリゲ紹介: スターダスト ディフェンス -Extension-

スターダスト ディフェンス -Extension-はエフェクトの綺麗なタワーディフェンス。 私もふりーむで2018年からのDL版公開で知った作品ですが、作品自体は結構前からあったみたいです。



星座を巡り、様々な宝石をマップに配置して降り注ぐ星々を撃退するゲームになっています。 OPがあったり導入説明があったり、非常に丁寧・綺麗な作品で、プレイしていて気持ちが良いです (左下)。 仕組みそのものは普通のタワーディフェンスと一緒なので操作に困る事もありません (右下)。



エフェクトが綺麗なだけではなく、プレイしてみると非常に奥の深いタワーディフェンスでした。 左下図では牡牛座のタウラスをステージとして4種類の宝石を使ってプレイしてみた時の画像を載せてみました。 画像だけではわかりにくいかも知れませんが、配置された宝石はどれもかなり能力が違います (右下)。 さらにこれらの宝石は強化する事で様々な追加特性を得られる仕組みになっており、 レベルごとの性能を活かす事がスターダスト ディフェンスでは重要です。



というよりこの能力をフルに活用しないと「完全クリア」は無理だと思います。 標準ステージのクリアは、最終ステージあたりがややきつめとは言え、頑張れば問題なく可能です。 しかしノーミスクリアとなるともう少し前のステージから難しくなってきます。 そしてチャレンジステージのクリアは標準ステージのノーミスクリアより難しい…。 さらに標準ステージをクリアするとハードモードも完備という。

まったく攻略がわからなかったチャレンジステージはついつい攻略を見てしまいました。 案の定、かなり細かなところまで考慮していかないとクリアできないみたいです。 ノーヒントで解きたい人のために隠しつつ、たいしてネタバレにならない程度のヒントを書いてみると、

軽くヒント (クリックで展開): チャレンジステージは宝石の売却も視野に入れないとクリアできない。


難しい訳だ…。 タワーディフェンスは今まで難易度の低いものしかやった事がなかったので、正直侮っていました。 宝石の選び方が結構シビアでクリアできていないステージがまだたくさんあります。 こんなに奥深く、歯ごたえのあるタワーディフェンスは初めてじゃないかなあ。

歯ごたえのあるタワーディフェンスをプレイしてみたい方におすすめです。

フリゲ紹介: Acassia∞Reload

Acassia∞Reloadは、記憶喪失の少女アカシアを操作して、ダンジョンの脱出を目指す探索RPG。



本作品はセーブ機能がなく、アカシアが死亡する(ゲームオーバーになる)ことにより、状況の一部を保存できます。 いわゆる死んで覚えるタイプの死にゲーですね。 死にゲーは様々な難易度のものがありますが、Acassia∞Reloadはさほど厳しいゲームバランスではないので、2-3時間でクリアできます。

スキルや世界観は記憶の痕跡 (右下) を辿る事で思い出す仕組みになっています。 道を塞いでいるモンスターとは何度も戦う事になると思いますが、 モンスターの弱点や行動パターンを覚えていくと、それほど苦労せずに突破できるようになっていくはずです。



戦闘はシンプルなもの (左下) ですが、相手の属性に合わせて戦わないと結構苦労する場面もあります。 装備品はドロップではなく戦闘によって得られるエンチャントのみ (右下)。 エンチャントをうまく組み合わせる事がいくつかの場面ではかなり重要になってきます。



雰囲気を楽しみつつ手軽に楽しみたい人には良い作品かも。 私はボスが一体だけ強くて苦労した以外は、スムーズにクリアできました。