クーの自由研究

冬の到来:空気が教えてくれるよ。う~んと深呼吸して、鼻がツンとしたら、それが冬のはじまり。

自由研究の準備(その4)課題にいろいろ対応します

おおまかな内容

初版のAutoEncoder(のレポート機能)をいろいろ改良して実験結果をまとめやすくしました。これで準備完了です!

なぜやるのか・どこまでやるのか

初版のAutoEncoderができましたが、少し動作させただけで課題がたくさんでてきました。このプログラムが当面の実験の最大の「かなめ」になるのでもうすこしだけがんばります。

やりたかったことと、やったこと

・実験結果表示の改善。できれば実験結果(要約)は1枚のイメージにまとめたいです。→レポートに見やすく配置しました。

・実験結果はpythonのmatplotlibで表示していますが、こまかいファイルがたくさんできて、結果をBlogにあげるだけで一苦労でした。→概要を1枚にまとめました。

・実験条件をmatplotlibに直接表記したいです。→レポート上部に記載しました。

・Wだけでなくバイアスbの変化も見たいので追加します。→見やすいグラフがなかなかできませんでしたが、最初の10個のMin/mean/Maxを小さなグラフで表示しました。全体の傾向が知りたい場合があると思うので、右下のイメージにまとめました。

・コスト関数の見直しが必要かもしれません。

雑感:コスト関数は他にも誤差関数やLoss、エントロピーなど本によって呼び方がいろいろですが、ブログではMichael Nielsen先生にならって、コスト関数に統一します。(変数名も!)

Sigmoid用のコスト関数はとてもいい具合なのですが、それ以外の平均二乗誤差などはコスト関数として本当に適切なのか疑問があります。(このあたりは実験課題ですが。。。)コーディングに問題がある可能性も高いのでよく見直します。

Sigmoid用のコスト関数は収束がとてもはやいことが知られていますが、平均二乗誤差を使っての学習の収束は「とっても」遅い場合があるようです。このことを知らなかったのでそのように感じました。コスト関数はいろいろあってよさそうなので、考えてみようと思います。(訂正)Sigmoidの収束が早いのはコスト関数のためではなく、Sigmoidを使用した場合の特性のようです。単層ではいいのですが、多層では勾配消失問題が起きやすい模様です。

 

以上をやると、(matplotlibの勉強を含めてですが)2週間はかかりそうです。でもmatplotlibがマスターできればとっても幸せになれそうです。

→本当に2週間くらいかかりました。ほとんどがmatplotlibを使ってのレポートの作成の調整でした。matplotlibはマスターにはほど遠いですが、ネットで探して必要なものを切り貼りできるくらいにはなりました。

・そもそも「ボクが切り貼りした作ったプログラムが正しく動作するわけがない」ので、Chainerなどの実行結果(encode/decode変換前後、処理速度など)を比較してみた方がよいと思います。

→ここまではできませんでした。本編の実験で余裕があれば行おうと思います。

できたのが以下のレポートです。(matplotlibを使用)

 

できたもの

1つのPNGファイル(もしくはPDF)にてんこ盛りでまとめました。

f:id:np2LKoo:20160812165246p:plain

ソースはまとめ中なので、近々アップします。

おおまかなレポートフォーマットの説明

てんこ盛にしたので、説明が長くなります。すみません。イメージだけみてもらえればよまなくてもいいかもです。

 

1.実験の条件、情報等

名前機能補足
Node Count ニューロンの数です。 10~1000くらい
Activation Func 活性化関数です。 活性化関数の簡単なクラスを作成して組み込みます。SigmoidとかReLUとかです。
Batch Size バッチサイズです。 プログラムの構成上必ず10の倍数で指定します。
Noise Ratio ノイズ付加の割合 0から0.9くいらいの間で適当な数字を指定します。0.3~0.4くらいがよさげです。
Epoch Limit 学習の条件回数 1まとまりの学習(Epoch)を何回まで行うか指定します。
DropOut ドロップアウト (未作成)ドロップアウトを行う割合を0から0.9くらいの間で指定します。
Train Shuffle 学習データ読み込みのシャッフル (未作成)当面の実験では再現性を重視するため実装しません。学習の汎用性のためには必要です。ちなみにpythonプログラムでは乱数も再現性のあるようにしています。
Optimizer オプティマイザー (未作成)いろいろな学習アルゴリズムがありますが、未作成です。このプログラムで使用しているのは、確率的勾配降下法です。(たぶん)
Alpha Ratio 学習率 活性化関数にあわせて適切な値を設定しないとなかなか学習がすすまなかったり、とっても遅かったりします。0.01から0.25くらいがよさげです。
Beta Ratio スパース正則化の重み (未作成)やることがたくさんありそうなので、かなり後になりそうです。
Nomalization 正則化 (未作成)上に同じ
Whitening 白色化 (未作成)自動調整とかZCAとかPCAとか指定できるようにしたいです。
Train SubScale 学習間引き この部分は当プログラムのオリジナルです。チュートリアルや実装例のとおりだとCPUだけでは遅すぎることと、学習の立ち上がりや途中のこまかい変化をみたいときには、学習を間引いてでもEpochを多数おこなった方がよいのでこのようにしました。半面、収束精度や最終精度を求める場合には全く役にたちません。1~6000の間で指定します。6000の指定をするとボクのマシンで1Epoche 0.004Sec でおわります。
Option いろいろ

やっているうちにいろいろ出てくると思いますので、リザーブとして準備しています。

重み共有の有無の表示を忘れてました。現在「重み共有あり」にしています。修正すると(他の修正したいところを含めて)際限がないので、当面保留となります。この実験の当面は「重み共有あり」です。とても重要な事項です。収束が早いようにみえるのはこのためです。(たぶん)

 

2.学習回数・期間とW重みの範囲

名前機能補足
Period ピリオド(マイルストーン)です。

1~14くらい。ピリオドごとに情報を記録します。本当は全epochでの情報を記録したかったのですが、メモリ不足となるため、一定期間ごとに記録する場所を決めました(このプログラムオリジナル)これにより1回の実験情報が10MB~500MB程度に抑制できるようになりました。ピリオド0(ゼロ)は実行前の状態です。ピリオド11は1024Epochです。ピリオドはおおむねEpoch=2**(Period -1)の関係があります。エリア2.~8.まではピリオドごとに行をすすめて状況をレポートします。

(epoch) Epochの回数です この部分の表示ではピリオド数に対応するEpoch数を表示します。
Wmax 隠れ層Wのパラメータ最大値

この見出しの右側に表示する隠れ層Wのパラメータ最大値を数字で表示します。学習の進み具合で気にすることがあります。

mean 隠れ層Wのパラメータ平均値

ほぼゼロになるはずですが、アルゴリズムに誤りがあるとゼロからどんどんずれていくケースもあります。

Wmin 隠れ層Wのパラメータ最小値 この見出しの右側に表示する隠れ層Wのパラメータ最小値を数字で表示します。学習の進み具合で気にすることがあります。組み合わせによってはWのプラスデータが少なく、ほとんどマイナス側にデータができる場合があるようです。

 

3.W重みの範囲(グラフ表示)

名前機能補足
W Range Wの各重みのグラフ

4.で表示している10個のWノードについてその最大値、平均値、最小値をエラーバーグラフで表示します。縦幅のレンジは3、の部分で共通なので、どれくらいの感じで大きくなっているががわかります。

なお、グラフが左から10本ありますが、表示は4.の表示順序に対応しています。

 

4.W重みのグレイイメージ表示

名前機能補足
W (Hidden Layer) 隠れ層Wの重みのグレースケール表示

Matplotlibのgray() 機能を使ってイメージ表示したものです。(おそらく)最大、最小の幅を256段階に区切って256諧調のグレースケール表示に「自動的に」調整して表示します。だんだん全体が白色になってきたり、逆に黒色になってきたりするように見える場合がありますが、ほとんど、山(max)がとても高くなり相対的に「ふもと」が低くなったため多くのエリアをしめる「ふもと」が黒く見えます。逆に谷(min)がどんどん深くなると、「平地」が相対的に高くなるため「平地」が白く見えます。左側3.のバーグラフ と見比べれば感じがよくわかると思います。

AutoEncoderはどのようにして効率的な「W重み」の組み合わせを獲得するかがポイントになると考えています。「W重み」は「重み共有」(青イルカ本:5.2.2)をしている場合、Encoderとしての「フイルター」でありDecoderとしての「合成元パターン」そのものであるともいえます。

↑(補足) 形成されるWについて注目したり、並べてみたりしたい場合があります。このプログラムではWの番号(ノード個数範囲内)を指定すれば、その画像を表示できます。実験完了後に指定番号を変更して、レポートを再表示することも可能です。Period事の情報として、すべての重みWの価、バイアスbの価を保持しています。
↑(補足2) 選択したノードの番号はヘッダー表示部に [番号] の形で表示しています。

 

5.バイアス b のグラフ表示

名前機能補足
b range バイアスBの値のエラーバーグラフです。 4.で表示した重みWに対応した、バイアス b の値を表示しています。横棒ラインがゼロです。各Wに対して単一の値しかありません。小さくてもわかりやすいよう、Wと形式をあわせてエラーバーグラフとしているだけです。横線よりしたに棒がのびている場合は値がマイナスです。

 

6.バイアス b の範囲、処理時間、W(学習前後)及びx_hat(デコード前後)のエントロピー

名前機能補足
bmax 全ノードのbの最大値 表示していない部分を含めて、全ノードのBias最大値です。
mean 全ノードのbの平均 〃平均値です。
bmin 全ノードのbの最小値 〃最小値です。
Time(s) Period実行時間 ピリオドの実学習実行時間です。例えば(sample例の)Period11ではEpoch513からEpoch1025までの実行時間 117.16秒を表示しています。(全体の経過時間ではなく、そのPeriodの開始から終了までの時間です。)
Wentgain 重みWのエントロピー利得合計 256諧調であるとした場合の画像エントロピーを求め、開始前のノイズ状態(Period 0)との差を「ゲイン(利得)」として計算した結果を出力しています。エントピーが減少しているので「マイナス」表記にすべきですが、表記欄の都合でプラス表記にしています。
dx-ent. エンコード・デコード後の画像エントロピ差

上のWentgainは「重みW」にのみ注目したエントロピーでしたが、この欄はオリジナルのMNIST画像(9.欄)とエンコードデコード後の画像(7.欄)の画像(「0」~「9」)のエントロピ-差の合計を出力しています。上と同様に256諧調とした場合のエントロピー差です。見た目にはそれほどわからなくても、確実にエントローピー差が減少しているのがわかります。最初は「コスト」を表示させていたのですが、活性化関数により数値がまちまちでしっくりこないので、こちらにしました。名前(略記名)は微分みたくて気持ちわるいので、もっといい名前に変えます。

 

7.x_hatのデコードのグレイスケール表示

名前機能補足
x_hat of Sample MNIST DATA & calibration AutoEncoderでエンコード/デコードした画像 「9.」のMNISTサンプルについて、該当するPeriodの[Wとb]でエンコード/デコードした画像です。帳票出力時に計算して出力しています。
(補足)

最初の「Period 0」は学習前の「乱数」でしかないので、当然のようにノイズ画像です。学習を数えるほどしかしていないPeriod 1 で結構形が再現できていることに驚きです。画像がはっきりしてくるとコスト関数やデコード画像だけでは学習が進んでいるのか、停滞してきているのかがはっきりわかりません。その場合は「6.」のdx-ent.の数値や「10.」のentropyグラフで進行状況を補助的に確認できます。

 

8.(将来的)補正試行のためのデコード表示

名前機能補足
Flat Zero フラットゼロのデコード画像 フラットゼロ(全ゼロ配列)画像(元画像は「9.」に表示)を該当するPeriodの情報でエンコード・デコードした画像です。全ゼロの画像はデコードしてもほぼ全ゼロであるほうが自然との考えから、補正を行う場合(実験で考えています)の状態をみるためのものです。
Flat Mean

フラットMean(平らな全平均画像)

全学習画像の平均値(おおむね0.1くらい)をフラットな配列(すべての要素が平均値)の画像を該当するPeriodの情報でエンコード・デコードした画像です。
Flat Max フラットMax値のデコード画像 全学習画像の最高値(1.0)をフラットな配列(すべての要素が最高値)の画像を該当するPeriodの情報でエンコード・デコードした画像です。「全ゼロがあるなら・・・」の軽いノリの情報です。

 

9.MNISTオリジナルデータ及び補正用FLATデータの表示

名前機能補足
a Sample MNIST & Calibration DATA

MNISTと補正用のオリジナル画像

Meanはそのまま出力すると自動で全黒になるので、見栄え的に少し調整しています。Maxは全白です。この「数字」画像は数多くある画像のうちの、最初の要素でよく見かけるmのです。他の数字にしたい場合はPG内部のオフセット値を調整すれば、別の数字を元画像にできます。

 

10.コスト関数とエントロピー差のグラフ

名前機能補足
Cost Fig. コストのグラフ(左側軸)

横軸:XはEpoch数です。縦軸左側Yはコストです。コストはいろいろな評価関数を使用します。

コストは変化を誇張してグラフ化したいため、べき乗して出力しています。

エントロピー(右側軸:エントロピー差)

[9.」MNIST画像の表示されていないものを含む「100づつのサンプル」データについて、元画像とAutoEncoderデコード変換後の画像のエントロピー差を「数字ごとに」グラフにしています。(1個だとあたりはずれがあり、全部だと時間がかかりすぎるためです。)傾き的にエントロピー差のほうが学習の進行がわかりやすいです。おおむねはずれておらず、右下がりであれば、学習は進んでいます。エントロピーの数値は軸表示の関係で計算結果を1/100にしています。また、エントロピーは毎Epocheで計算しておらず、帳票出力時にPeriodでデコード&256諧調化&エントロピー計算をしています。そのため、レポート出力であってもそこそこ時間がかかります。

 

11.W重み範囲とバイアスb のプロット

名前機能補足
Last W Range & b Bios Fig. 最終W&bについて、すべてのノードの値範囲をプロットしたものです。

「3.」「5.」のRangeグラフ部は画面に表示されているイメージの範囲(10ノード)だけのもではなく、全ノード(指定により異なる)の情報を出力します。このグラフをみて特出した「山フィルタノード」や「谷フィルタノード」の発達をみたければ、selectノード指定をし直してレポート表示することで、再学習計算しないで、観察が可能です。

↑(補足) 重みWは赤色のエラーバー形式のグラフで出力します。バイアスbは青い点をプロットします。

 

12.MNISTサンプルのエンコード結果

名前機能補足
Last Z=f(Wx+b) Range Fig. 表示しているサンプルMNIST画像をエンコードしたときのZ=f(Wx+b)の値 活性化関数により、とりえる値がかなり異なります。例えばsigmoid関数は-1から1の範囲ですが、他の関数はそれ以外の値もとりえるので、グラフの形はかなり異なります。
↑(補足) c0~9,Sumのグラフをそのまま重ねるとたいへん見にくいグラフとなってしまうので、0~9までは1つづオフセットをずらしてプロットしています。Sumは0から9までの値を全部足して重ねて出力をしています。スパースな感じになっているか、特徴分離でなく「そのもの」となっていそうかはのグラフである程度見ることができます。

 

13.フッター各種情報表示

名前機能補足
Training time 学習時間 指定した条件での学習の開始から終了までの時間です。レポート生成の時間は含んでいません。アルゴリズムを含めた、学習効率や収束率をもとめる場合の指標にする予定です。「短く、効率よくしていこう」というモチベーションの元にもなります。
WEntorpyGain 重みWのエントロピー利得 最初のランダム状態に比べて最終的な「重みW」がどれくらいエントロピー現象しているかを計算して出しています。「6.」Wentgain と同じ値です。最終Periodのひとつ前をだしているのに気が付いたのでなおしておきます。
W Use Ratio Z=f(Wx+b)の計算で0.2より大きな値である割合 (感想)いろいろな本を読み、ほどよく分散してかつスパースな状態で動作するのが、いちばんいい感じらしいイメージをもっています。ノードが100くらいだと総動員しないと難しいのだと思いますが、例の場合はもう少しノードを増やして0.3~0.4の割合のノードがメインで動くくらいがバランスがいいのかもしれません。

※学習結果は学習完了後、所定のドライブ、所定の名称で保存します。

※学習とレポート出力は機能をわけているので、切り離せます。学習結果を後日レポート出力することが可能です。

※jupyter Notebookはグラフ出力のしくみが若干異なるので、出力したpickleデータをPythonとjupyter Notebookで使いまわせません。これはとっても痛いです。

その他、こまかな調整をして再調整しないといけない部分があるように思いますが、自分の実験用プログラムなので、これくらいのレベルでもいけそうです。最終的には実験の枝をそぎ落とし、きれいなプログラムにしたいと思います。

まとめ

※periodはepochをある程度まとめた便宜上のものです。一般的な呼び方ではありません。最初は「マイルストーン」という呼び方をしていたのですが、periodのほうがしっくりくるのでこう呼んでいます。このことを軸にプログラムしているので、当サイトでは結構重要事項です。

※実際行うべき処理の1/1000 の学習量ですませると1Epoch0.04秒程度で終わります。ています。(単に端折っているだけですが、これで学習の立ち上がりがとってもわかりやすくなるんです。)ちなみに端折らないと1 Epoch が40秒程度で、4096Epoch流すと3日弱かかります。過学習の実験をするときはそれくらい回さないといけない気がします。

思ったこと・感じたこと

 「ポケモンGO」や「オリンピック」の誘惑に敗北せず、予想の2週間+αくらいで調整できたのでよかったです。(ほとんどがレポートの調整でした)

まだGPUが買えそうにないのでしばらくはGPUなしでがんばります。このPGの範囲くらいだと、まだいける感じはします。

蛇の足は退化しました

3D グラフで悪戦苦闘しました。。。Wを3Dで出すとgrayイメージよりわかりやすい(山と谷の感じなど)ですが、小さくたくさん出すとなんのグラフか全くわかりません。悩みところです。ちなみに下のグラフは とある実験のW 重みの最初のイメージです。グレイイメージではx軸目盛が上側、Y軸目盛が右側です。

高い山のふもとに沿って、谷ができているのがよくわかります。(上のグレイイメージだとそこまではわかりにくいです。)ただし、グラフを小さくすると判読できないので(要約レポートに採用するのは)あきらめました。

f:id:np2LKoo:20160805072332p:plain

 あと、ボクの悪いクセですが、3秒前にグーグル先生から得た知識を100年前から知っているような感じで書きます。どうもすいません。正直「エントロピー」なんて何者か全くわかりませんし、微分はすこしだけイメージがわいてきたくらいです。100mを9.58秒でジャンプしたときの秒速(10.438...m/s)のことです!!