daruma3940の日記

理解や文章に間違い等あればどんなことでもご指摘お願いします

調和振動子のエネルギー固有状態の式についてオーバーフローを起こさない計算法

daruma3940.hatenablog.com

この前の続きです

この前は  (2^n n!)^{-1/2} をオーバーフローを起こさずに計算する方法についてと
それが量子的な調和振動子のエネルギー固有状態に出てくるという話をしました。
↓エネルギー固有状態の式
  \phi_n (x)= AHn( \xi )exp(- \xi^2 /2 )
ここで
  \xi = \frac{x}{x_0}
  A= \frac{C}{ \sqrt{n! 2^n} }
としてみました。
Cとかx0が何かはここに書いてる
調和振動子 - Wikipedia

Hnはエルミート多項式なのですが、これがやべーやつ
  H_{n+1}(\xi )=2 \xi  H_{n}(\xi ) +2 n H_{n-1}(\xi )

なので  (2^n n!)^{-1/2} が計算できるようになっても結局オーバーフローします
さっきのΦについての式をHnについて書き直してみましょう
  Hn( \xi )= \sqrt{ \frac{n! 2^n}{C} } exp( \xi^2 /2) \phi_n(x)
これをさっきの
  H_{n+1}(\xi )=2 \xi  H_{n}(\xi ) -2 n H_{n-1}(\xi )
に代入してまとめると
  \phi_{n+1} =\sqrt{ \frac{2}{n+1}} \xi \phi_{n} - \sqrt{ \frac{n}{n+1}} \phi_{n-1}

なのでn=0 とn=1について計算すれば計算出来ちゃいます

def zenka_oscn(n, x):
    if (n == 1 or n == 0):
        return occeogenfanclist[n](x)
    else:
        return ((2 / n) ** 0.5) * x/x0 * zenka_oscn(n - 1, x) - (((n - 1) / n) ** 0.5) * zenka_oscn(n - 2, x)

これを単純に計算しようとすると重いのでフィボナッチ数列の場合のようにメモ化(キャッシュ化?)してみましょう
pythonのメモ化はクッソ簡単です
頭に@lru_cache(maxsize=hoge)をつけるだけです。やっぱりpython便利

from functools import lru_cache

@lru_cache(maxsize=None)
def zenka_oscn(n, x):
    if (n == 1 or n == 0):
        return occeogenfanclist[n](x)
    else:
        return ((2 / n) ** 0.5) * x/x0 * zenka_oscn(n - 1, x) - (((n - 1) / n) ** 0.5) * zenka_oscn(n - 2, x)

これめっちゃ賢いなぁ~~と感心したのですがどうでしょう?

numpy.liag.eighの使い方について

numpy.liag.eighはnumpyのエルミート行列の固有値固有ベクトルを求める場合に使います
こんな感じ

eigval, eigvec = LA.eigh(a)

僕はこれの使い方をちゃんとわかっていませんでした
eigvecは2次元配列です何個目の固有ベクトルかとその固有ベクトルの何番目の成分かというので2次元になっています

つまり
eigvec[a][b]
とあらわされます
C++とかにおける二次元配列の扱いに慣れているとevec[a][b]は[a個目の固有ベクトル][この固有ベクトルのb番目の成分]と並んでいると勘違いしてしまいますね(僕だけかもしれないが)
しかしeighで帰ってくる固有ベクトルはevec[この固有ベクトルのa番目の成分][b個目の固有ベクトル]という順番で並んでいます。
マニュアルを読んでみてください。そう書かれてますね
numpy.linalg.eigh — NumPy v1.14 Manual

(この並びにしてる理由は行列の掛け算則に乗るようにしてるのだと思いますが確申が持てません 間違ってたら指摘して)

僕はこれを数ヶ月勘違いしたまま「データが取れないデータが取れない」とうんうん悩んでました当たり前ですね
皆さんもこういうライブラリを使うときはちゃんとマニュアルを読んで使いましょうね

(2^n n!)^{-1/2}のオーバーフローを起こさない計算法

  (2^n n!)^{-1/2}
こういう計算よくありますよね

これをpythonで愚直に計算してみましょう

import numpy as np
import math

nx = 100

ans = (((2 ** nx) * (math.factorial(nx))) ** (-0.5))

print(ans)

かっこが多すぎる糞コードですね

実行結果:
9.193870653018146e-95

nx=100の場合はちゃんと計算できているみたいですがnx=200にするとどうでしょうか

 ans = (((2 ** nx) * (math.factorial(nx))) ** (-0.5))
OverflowError: int too large to convert to float

あららオーバーフローしちゃいましたね

ここで
  a^x = exp( xln(a) )
を用いて工夫してみましょう
  a \equiv 2^n n!
とすると
  ln(a) \Rightarrow ln(2^n n!) =nln(2)+\sum_n ln( n)

  a^{-1/2} \Rightarrow (2^n n!)^{-1/2} =exp(- \frac{1}{2}(nln(2)+\sum_n ln( n) ) )

import numpy as np
import math

nx = 100

ans = (((2 ** nx) * (math.factorial(nx))) ** (-0.5))

def lnfact(n):
    sum = 0
    for i in np.arange(1, n+1, 1):
        sum += np.log(i)
    return sum


ans2 = np.exp( (-0.5) * (nx * np.log(2) + lnfact(nx) )  )
print(ans, ans2)

実行結果
9.193870653018146e-95 9.19387065302e-95

一致してますね
n=200の場合も計算してみましょう

import numpy as np
import math

nx = 200

#ans = (((2 ** nx) * (math.factorial(nx))) ** (-0.5))

def lnfact(n):
    sum = 0
    for i in np.arange(1, n+1, 1):
        sum += np.log(i)
    return sum


ans2 = np.exp( (-0.5) * (nx * np.log(2) + lnfact(nx) )  )
#print(ans, ans2)
print(ans2)

実行結果
2.80902829347e-218

計算が出来ましたやったね!


(研究が行き詰っているからって過去に学んだ内容をブログに書くのに逃げるな)

追記

  (2^n n!)^{-1/2}
が必要な場合っていうのは
調和振動子 - Wikipedia
の量子的な調和振動子のエネルギー固有状態とかです

次回
daruma3940.hatenablog.com

hoge

持ち時間学習を学習させよう

(研究が忙しくなってきたので適当に済ませる)


教師データはshogi liveにあるプロ棋士の持ち時間付きデータから学習させよう

とりあえずパパパっとデータがほしいならこのサイトから.
www.studiok-i.net

こういうhtmlを取り出してきて
http://live.shogi.or.jp/ryuou/kifu/30/ryuou201706260101.html
後ろの.htmlを.kifに変えてwgetをつかってダウンロードしてくればいいと思います

ぼくはいろいろサイトをめぐってデータを集めてきましたが結局290局ぐらいしかデータが集まりませんでした(2015年以降の棋譜しか持ち時間のデータがついてないし)

全体の消費時間のうち今の進行度で持ち時間の何割を使ったかを表示してみたらこんな感じ
f:id:daruma3940:20180113234719p:plain

これをすべてのデータでプロットしてみたらこんな感じ
f:id:daruma3940:20180113234905p:plain

ひえ~~~ばらけ方が大きいなぁ進行度で時間を決めるのでは全然ダメそう
というわけで局面を入力して時間を決める感じにしよう
しかしばらけが大きすぎてちゃんと機微を学習できるか怪しい

まあとりあえず学習してみよう
局面の情報だけを用いたNNでやってみた(その前に2駒関係でやってみたけどだめだめだった)
f:id:daruma3940:20180113235603p:plain
赤が教師データ 青がNNの出力

はい。全然機微ををとらえられていないですね。

いろいろ考えてはいるけどこの機微をとらえるのは結構難しそうだなぁ

リバーシアプリ作ってみた

スマホリバーシアプリ作ってみた
play.google.com

身近な人が、もし完成したらお子さん用にインストールしてくれるということだったのでターゲットを小学生か中学生またはリバーシ初心者にすることにした
(公開してからスマホ持ってる小学生中学生ってあんまりいないだろうしターゲットとしてはあんまりふさわしくなかったのではと思った
塾講師のアルバイトをしてる知り合いに聞いてみたらバイト先の中学生は結構スマホを持っているらしくターゲットとしてはそんなに間違ってなかったのかもしれない。
でもまあリバーシなんかよりFGOだよね




この文章はたまに主語が大きくなったりすることがありますが主語はすべて私です(本当か?)

本当はどうぶつしょうぎアプリを作ろうとしてたのだけれどどうぶつしょうぎ著作権があることがわかって泣く泣く没にした
知ってる方たちは「その権利を持ってる人に使わせてもらっていいか聞いてみては?」といってくれたが、
「どうせダメだろ」という気持ちが僕の中で強くてあきらめてしまった。
どうぶつしょうぎではない将棋をのスケールを小さくしたゲームを作ろうとしてみたが後手がひたすら先手の攻めを耐え続けるゲームばかりできてしまった。
どうぶつしょうぎがものすごく難しいバランス調整を乗り越えて作られているということがわかってさらに「どうせダメだろ」という気持ちが大きくなってあきらめた。
ホントにあれはすごいですよ。駒と駒が最初からぶつかり合ってるのに、完全解析の結果が後手必勝だし、あれだけサイズは小さいのに将棋のもつ難しさは残っているし作った人は天才としか言いようがないですね。
物理でも自然現象の本質を残したまま簡単なモデルを作ることは非常に難しいし、大事な仕事である(ex.イジングモデル)ということを担当教官が言っていた。


リバーシとか将棋のアプリって最低レベルの強さでもなんだかんだ強いんですよね(なんでもできる強い皆さんにはわからないかもしれない)
かといって弱いのを売りにしてる他のアプリを別にインストールするのには抵抗がある。
なんというか他の人が普通の教室で授業を受けてるのに自分だけ別室に移されてそこでレベルの低い授業を受けさせられている感覚というか
数学の授業で自分には全然わからない問題を、さっきまで一緒に休み時間あそんでた友人達が黒板にスラスラ解いてて仲間外れにされたように感じ不貞腐れるしかない感覚
たぶんそういう感覚を味わった人って僕のほかにもいっぱいいるんじゃないかなぁ
そういう人が(というかそういう人こそ)楽しめる、自信を持てるような設計にしようと考えた

とりあえず強さを弱くするのは必要なので強くしないことにした
強さのレベルには3種類用意してて強い、普通(というか中くらいの強さを表す単語として「普通」を使うべきではなかった)、弱いを用意した。
弱いは0.05秒,普通は0.08秒,強いで0.1秒しか考えさせていない。
しかしそんなに短い時間で指し手を返されると遊んでる側としては「手を抜かれてるな」とか「手加減されてるな」と思ってしまうと考えたので実際に指し手を返すのは1秒後にすることにした
(この1秒というのは固定だったのでAIが負けているときは深く考えているかに見えるように時間を変化させた方がいいかもしれない)
強いモードでもそこまで強くないので頑張れば勝てる。(というか大学生の友人に遊んでもらうと強いモードでも弱すぎるといわれる。それでいいんだよそれで)強いモードに勝てれば自分はこのアプリの最高レベルに勝てたんだという自信を持てるんじゃないか、自信を持てたらどんどんリバーシ、さらにはほかのボードゲームを好きになれるのではと思ってこの設計にすることにした。
しかしこれでも強すぎたみたいで反省。中学生でリバーシ初心者の弟にやらせてみたらこの探索時間でよさそうだったのでこれに決めたのだけれど...

こういうボードゲームって勝ち将棋鬼のごとしといわれるように一方的にやられたりしますよね。
そういうのすごくつらくないですか。
僕は昔リアル将棋で角道を開けた後、角を守る銀を動かしてしまって角をただでとられてしまったことあります。
そこで投了しようとしたんですが「そんなにすぐ投了するの?」といわれてそのまま試合を継続したことがあります。辛いですね。
ソフトでもαβ探索だとそういう加減をさせるには工夫が必要です
そこで囲碁で使われているモンテカルロ探索で探索させることにしました
モンテカルロ探索は勝率だけを最大化するので自分の陣地の最大化はせず「半目でも勝ちは勝ちっしょ?」って感じらしいです
なのでリバーシでもそんなに大差で勝とうとはしないのではないかと思ってます(検証はしてない)
なので負けてもまだ救いはあるように感じられるのではないかと思います。

弱さではなくかわいさを売りにすることにした
一番最初に言ったけど弱さを売りにしてるアプリに対して勝ってもうれしくないですよね(僕は)。
そしてそういうアプリをインストールするのにも抵抗があります。
自分の弱さと向き合うことは必要なことかもしれないけれど、そういうことをプレイヤーに求めるゲームは、「あなたはすごいよ!どんどん強くなってる!!」っていう報酬を与え続けてくれるゲームに比べて一般に嫌煙されるような気がします(なんでもできる強い皆さんにはわからないかもしれない)
なんか話がずれてきたけど
弱さをアピールするのではなくかわいさをアピールすることにしました


私がリバーシのテストプレイをする中で身に着けた勝つためのコツみたいなのをルール説明のところに書いておいた(私も初心者なのでダメなコツかもしれないけど)
後はトロフィー機能をつけてトロフィーを集める機能をつけた
勝てても勝てなくてもトロフィー集めるのたのしーーー!
(そろそろ文章書くの飽きてきた)



ここからは今の実装の反省とこれからやろうと考えているアイディアについて

とりあえず勝った時の報酬が弱い。もっとエフェクトをつけて
「あなたの勝ちですーーーーz_____!!!!すごーーーーーz_______い!」ぐらいしよう

そして勝った時しか報酬が与えられないというのは良くない。
終盤に差し掛かって、勝てそうな場合は勇ましいBGMをかけて、勝ちそうになったことに対して報酬を与えたい。
そしてその曲は勝負がつくまではサビの前で止めておいて、勝敗が決まった瞬間にサビを流す。(RPGツクールのゲームにこういうのがあった。毎回プレイするのが楽しくなるシステムだった。)

トロフィーを手に入れたことをちゃんとプレイヤーに知らせよう

ルールなんて今どき誰も読まないのでそんなところに勝ち方のコツを書くのではなく、
プレイヤーが勝負に負けてしまったらその時にTIPSとしてねぎらいの言葉として表示させよう

石を置くのも気持ちよく置けるようにエフェクトをかけよう

後は経験値やレベルの概念を導入したい。
勝っても負けても経験値が入り(その量にはもちろん差をつけるが)、
レベルが上がっていくのなら継続して遊びたいと思えるはず。
もちろんレベルはただの飾りではだめでそれが上がることでちゃんと強くなっている実感を与えないといけない

レベルといえばRPG RPGといえば攻撃力... 
敵にHPを用意してバトルものにするしかないように思えるが最近出てきたオセロニアというゲームとかぶりそうだし(アイディアとして参考になりそうだし遊んでみたいと思っているけどまだ遊んでないのでどんなゲームかはわかってないが)バトルがだめなのならリバーシなどといったボードゲームはほぼ実力であって、実力以外にレベルが上がれば有利にできるといった設計にするのは難しそうだな...
レベルが上がればリバーシの試合を有利にできるスキルを使えるようにするのはどうだろう。スキルはある相手の石を自分の石にできる(心変わり)とか、絶対に相手にひっくり返されなくする(聖なる守り)とかを用意して、レベルが上がればそういうのを使えるようになる。(使える回数はMP(レベルが上がれば増える)で決める)みたいなのはどうだろう。(しかしリバーシに慣れてくるとスキルは不要になってくるはずなのでレベルが上がれば使えるようになるというのは良くないかもしれない ミッションで「スキルを使わずに勝て!」みたいなのを用意すべきか)
敵にもスキルをつける(盤のある範囲にある石をすべて吹き飛ばしてしまう(大爆発)とか、2回石を置ける(2回攻撃)とか、盤に穴をあけてそこには置けなくする(メテオストライク)とか、盤を90度回転させてプレイヤーを混乱させるとか(Rotated Board),盤の一部を見えなくする(インビジブル)とか,盤の一部をランダムに入れ替える(Xor128)とか)
ここまで来たらホントにRPGみたいにストーリーモードをつけたいですね(主人公をSquirrel君にしてぷよぷよのストーリーモードみたいな感じで)こういうボードゲームでストーリーがついてるのってあんまり聞いたことがないし

なんか話が大きくなってきてしまったなぁ....
こんな理想を言っても、自分の実力のなさとモチベーションの低さによって理想は理想のままで終わってしまいそうなんだよな...
でも想像するだけでもすごく楽しそうなので頑張って作ってみたいですね

振り返りと抱負

f:id:daruma3940:20160520223745p:plain

陳腐だけど年末なので
今年の目標の達成度と来年の目標についてなのじぇ

f:id:daruma3940:20160520223745p:plain
まず去年立てた目標を振り返っていこうじぇ
1 コンピュータ将棋強くする
f:id:daruma3940:20160520223745p:plain
これは達成できたと思ってるのじぇ
そもそもどれぐらい強くするか何も言ってないけれど、自分で頑張ったと思えるので達成できたことにするのじぇ

目標2 TOEIC 700点
f:id:daruma3940:20160520223745p:plain
これはNoviceさんがTOEIC目標650と言っていたので「じゃあまりちゃは700取るのじぇ!」と意気込んでみた目標なのじぇ
これはまあ700点以上だったので達成できたのじぇ

目標3 ゲームを作る
まあアンドロイドアプリ作ったし
play.google.com
play.google.com
まあいろいろやってみてエターなったのばっかりだけど
f:id:daruma3940:20171231214140p:plain
目標としてはクリアかななのじぇ

目標4 研究室に入ったら研究を頑張る
f:id:daruma3940:20160520223745p:plain
なんかふわふわした目標ばっかりだな~~のじぇ
これはどうだろう...まぁ頑張ったとは思うんだけどバグが出てきたらそれを解決する気が起こらずだらだらしてばかりだったので駄目だな~~って感じなのじぇ
先生に甘えすぎた感があるので来年は甘えすぎないようにしたいじぇ
これは微妙だけどまあクリアかななのじぇ(自分に甘い)

f:id:daruma3940:20160520223745p:plain
来年の目標

1、面白いゲーム作りたい
もっと直球にいうとAdmobは最低8000円入らないと口座に入金してもらえないみたいなので8000円稼ぎたい
複雑な構造のゲームとかは全然作れないので作れるようになりたい。
素材の絵を描くのも苦にならないようになりたい。
アイディアとかデザインとか設計とか総合的な力も必要になるのでその辺りの力もつけたい(もちろんプログラミングの力もね)

2、3月までに今やってる研究の成果を出したい
学会でポスター発表とかも今年はあると思うのでそれも頑張りたい

3、研究テーマについて深く理解したい
担当の先生はそういったことに力を注ぐ必要はないといっていたのだけれど(早く他のテーマについてやらせたいからかもしれない)
せっかくこのテーマになったのだしもう少し深く理解したい

4、最強になりたい
これはコンピュータ将棋含むいろんなところでそう思う。
最強になりたい。というか滅茶苦茶強くなりたいというのを一言に纏めると最強になりたいになる。
というか弱さから逃げ出したい。でも最強になるその過程で弱さとひたすら向き合って受け入れ続けることになるので非常につらい。
まあ弱さと向き合うことから始めていこう


f:id:daruma3940:20160520223745p:plain
こんな感じなのじぇ
去年の目標は自分にとってできそうなものしか用意しなかったので大きめの目標を立ててみたのじぇ
来年もバーチャルのじぇまりちゃおじさんをよろしくお願いしますのじぇ

ニューラルネろうじぇ

f:id:daruma3940:20160520223745p:plain
みなさんおっはー!まりちゃなのじぇ!
今日は皆さんと一緒にニューラルネろうとおもいまーーす!

今日は
{ \displaystyle
 \vec{y}=W\vec{x}+\vec{b}
}
を計算するためのレイヤー、Affineレイヤーを作っていこうと思いま~~す
f:id:daruma3940:20160521003616p:plain
youtuberかな??
f:id:daruma3940:20160520223745p:plain
前向き伝搬は上の式をそのまま実装すればいいので簡単ですね~~
問題は誤差逆伝搬の方ですね~~~
f:id:daruma3940:20160520223745p:plain
とりあえず損失関数を定義しま~~す
{ \displaystyle
 \vec{y}=W\vec{x}+\vec{b}
}
に対していきなり損失を考えま~~す
{ \displaystyle
 \vec{t}
}
を正解となる教師データとしまーす
そうすると正解に対する損失は
{ \displaystyle
 E= \frac{1}{2} ( \vec{y}-\vec{t})^2 
}

となりま~~す
この損失に対してパラメーターをどの方向に動かせばいいか決めるために
\[
\frac{\partial E}{\partial W},
\frac{\partial E}{\partial \vec{b}},
\frac{\partial E}{\partial x}
\]
を計算しまーーす

ベクトルとか行列で微分するのは結構面倒な作業なので成分ごとに微分をみていってそのあと行列の形式に戻していきましょーー


まずはWについて!
\[
\frac{\partial E}{\partial W_{np}}=\frac{\partial }{\partial W_{np}} (\frac{1}{2} \sum_{i} ( y_{i}-t_{i})^2)= \frac{\partial }{\partial y_{i}} (\frac{1}{2} \sum_{i} ( y_{i}-t_{i})^2 )\frac{\partial y_{i}}{\partial W_{np}}
\]
ここで
\[
\frac{\partial }{\partial y_{i}} (\frac{1}{2} \sum_{i} ( y_{i}-t_{i})^2 )=\sum_{i}(y_i-t_i)
\]
\[
\frac{\partial y_{i}}{\partial W_{np}}= \frac{\partial}{\partial W_{np}}( \sum_{l} W_{il}x_{l}+B_i )=\delta_{in}\delta_{pl}x_l
\]
なので
\[
\frac{\partial E}{\partial W_{np}}=\sum_{i}(y_i-t_i)\delta_{in}\delta_{pl}x_l=(y_{n}-t_{n})x_p
\]
これより
\[
\frac{\partial E}{\partial W} =
\left(
\begin{array}{c}
\frac{\partial E}{\partial W_{np}} \\
\end{array}
\right)
=
  \left(
\begin{array}{cccc}
\frac{\partial E}{\partial W_{11}} & \frac{\partial E}{\partial W_{12}} & \ldots &\frac{\partial E}{\partial W_{1n}} \\
\frac{\partial E}{\partial W_{21}} & \frac{\partial E}{\partial W_{22}} & \ldots & \frac{\partial E}{\partial W_{2n}} \\
\vdots & \vdots & \ddots & \vdots \\
\frac{\partial E}{\partial W_{m1}} & \frac{\partial E}{\partial W_{m2}} & \ldots & \frac{\partial E}{\partial W_{mn}}
\end{array}
\right)
\]
がけいさんできて
\[
\frac{\partial E}{\partial W} =
  \left(
\begin{array}{cccc}
(y_1-t_1)x_1 & (y_1-t_1)x_2 & \ldots & (y_1-t_1)x_n \\
(y_2-t_2)x_1 & (y_2-t_2)x_2 & \ldots & (y_2-t_2)x_n \\
\vdots & \vdots & \ddots & \vdots \\
(y_m-t_m)x_1 & (y_m-t_m)x_2 & \ldots & (y_m-t_m)x_n
\end{array}
\right)
\]

つまりここから
\[
\frac{\partial E}{\partial W} =
\left(
\begin{array}{c}
y_1-t_1 \\
y_2-t_2 \\
\vdots \\
y_n-t_n
\end{array}
\right)
\left(
\begin{array}{c}
x_1,
x_2
\ldots
x_n
\end{array}
\right)
\]
行列形式になおすと
\[
\frac{\partial E}{\partial W} =(\vec{y}-\vec{t})\vec{x}^T
\]
と求まるじぇ


次はbについて
\[
\frac{\partial E}{\partial b_{n}}=\frac{\partial }{\partial b_{n}} (\frac{1}{2} \sum_{i} ( y_{i}-t_{i})^2)= \frac{\partial }{\partial y_{i}} (\frac{1}{2} \sum_{i} ( y_{i}-t_{i})^2 )\frac{\partial y_{i}}{\partial b_{n}} \\
ここで \\
\frac{\partial y_{i}}{\partial b_{n}}= \frac{\partial}{\partial b_{n}}( \sum_{l} W_{il}x_{l}+b_i )=\delta_{in}\\
なので\\
\frac{\partial E}{\partial b_{n}}=\sum_{i}(y_i-t_i)\delta_{in}=(y_{n}-t_{n})
\]
つまり行列形式になおすと
\[
\frac{\partial E}{\partial b}=(\vec{y}-\vec{t})
\]


最後にxについてなのじぇ。ここでは使わないけれどこれは下のレイヤーに送るのじぇ
\[
\frac{\partial E}{\partial x_{n}}=\frac{\partial }{\partial x_{n}} (\frac{1}{2} \sum_{i} ( y_{i}-t_{i})^2)= \frac{\partial }{\partial y_{i}} (\frac{1}{2} \sum_{i} ( y_{i}-t_{i})^2 )\frac{\partial y_{i}}{\partial x_{n}} \\
ここで\\
\frac{\partial y_{i}}{\partial x_{n}}= \frac{\partial}{\partial x_{n}}( \sum_{l} W_{il}x_{l}+B_i )=W_{in}\\
なので\\
\frac{\partial E}{\partial x_{n}}=\sum_{i}(y_i-t_i)W_{in}
\]
ここから行列形式になおそうじぇ
\[
\frac{\partial E}{\partial \vec{x}} =
\left(
\begin{array}{c}
\frac{\partial E}{\partial x_1} \\
\frac{\partial E}{\partial x_2} \\
\vdots \\
\frac{\partial E}{\partial x_n}
\end{array}
\right)
=
\left(
\begin{array}{c}
\sum_{i}(y_i-t_i)W_{i1} \\
\sum_{i}(y_i-t_i)W_{i2} \\
\vdots \\
\sum_{i}(y_i-t_i)W_{in}
\end{array}
\right)
=
\left(
\begin{array}{c}
\sum_{i} (W^{T})_{1i}(y_i-t_i) \\
\sum_{i}(W^{T})_{2i}(y_i-t_i) \\
\vdots \\
\sum_{i}(W^{T})_{ni}(y_i-t_i)
\end{array}
\right)
\]

\[
W^{T} =
\left(
\begin{array}{c}
\vec{w^t_1} \\
\vec{w^t_2} \\
\vdots \\
\vec{w^t_n}
\end{array}
\right)
\]
のように書くと
\[
\left(
\begin{array}{c}
\sum_{i} (W^{T})_{1i}(y_i-t_i) \\
\sum_{i}(W^{T})_{2i}(y_i-t_i) \\
\vdots \\
\sum_{i}(W^{T})_{ni}(y_i-t_i)
\end{array}
\right)
=
\left(
\begin{array}{c}
(\vec{w^{T}_1})(\vec{y}-\vec{t}) \\
(\vec{w^{T}_2})(\vec{y}-\vec{t}) \\
\vdots \\
(\vec{w^{T}_n})(\vec{y}-\vec{t})
\end{array}
\right)
=
W^{T}(\vec{y}-\vec{t})
\]


さあこれでAffineレイヤーは順方向逆方向両方実装すべきことは分かったのじぇ
これを用いて
ニューラルネットワーク - Wikipedia
wikiにある
\[ y=2x^2-1 \]
を学習しようじぇ
今回はwikiにある通りの構造
入力→Affineレイヤー→ReLU→Affine→出力
で行くのじぇ
f:id:daruma3940:20160520223745p:plain
これが初期値でプロットしたやつ
f:id:daruma3940:20171219213834p:plain
f:id:daruma3940:20160521003616p:plain
まあ初期値だしこんなもんかしらね

f:id:daruma3940:20160520223745p:plain
これが途中でプロットしたやつ
f:id:daruma3940:20171219213902p:plain

f:id:daruma3940:20160521003616p:plain
いい感じに学習途中感が出てるじゃない!とかいはね!
f:id:daruma3940:20160520223530p:plain
もうちょっと中央の値が下がってくれば文句なしだねっ
f:id:daruma3940:20160520223745p:plain
これが学習終了時のプロット
f:id:daruma3940:20171219214038p:plain
f:id:daruma3940:20160520223745p:plain
なんでうまくいってないのおおお??
f:id:daruma3940:20160521003616p:plain
は??
まっ平らじゃん
うまいオチのついた3コママンガね...
f:id:daruma3940:20160520223530p:plain
はい無能 世界一プログラミングが下手 実質バグ
f:id:daruma3940:20160520223745p:plain
これ絶対C++の線形台数ライブラリ(Eigen)がわるいきがするのじぇ...
だって内積がベクトル同士でしかできないし外積は3*3までしかできないしcolとrowがたてかよこかこんがらがるしうんたらかんたら...(無能特有の責任転嫁)
どこか間違ってたら誰か教えてください....

「追記」

f:id:daruma3940:20171220141510p:plain
ReLUを
return (x >= 0.0) ? x : 0.0;
にして、学習率を調整したらうまくいったのじぇ....よくわからないのじぇ....