バッチ正規化の効果

前書き

以前バッチ正規化の記事を書いたけど使用する場合と使用しない場合の比較を書き忘れていたので書く。

 

比較対象は

akikanr.hatenablog.com

 

でバッチ正規化をする場合としない場合で比較する。

 

 

バッチ正規化をした場合

比較対象の記事ではバッチ正規化を施した状態の正解率を書いているが比較のためここで再度記述する

 

tep 0, training accuracy 0.113636 
step 1000, training accuracy 0.997727 
step 2000, training accuracy 0.997727 
step 3000, training accuracy 0.997727 
step 4000, training accuracy 0.997727 
step 5000, training accuracy 0.997727 
step 6000, training accuracy 0.995454 
step 7000, training accuracy 0.997727 
step 8000, training accuracy 0.997727 
step 9000, training accuracy 0.997727

汎化性能は以下の通り 
test accuracy 0.878788

 

バッチ正規化をしなかった場合

step 0, training accuracy 0.0772727
step 1000, training accuracy 0.995454
step 2000, training accuracy 0.997727
step 3000, training accuracy 0.995454
step 4000, training accuracy 0.986364
step 5000, training accuracy 0.995454
step 6000, training accuracy 0.995454
step 7000, training accuracy 0.995454
step 8000, training accuracy 0.995454
step 9000, training accuracy 0.995454

汎化性能
test accuracy 0.757576

 

比較した結果

汎化性能に明らかな性能差がみられる。

またtraining accuracyについても若干の性能向上がみられており、無いよりはあった方が良い。

今回のケースに限り性能が良かったのではないかという話も無いわけではないので自分のモデルで使う場合はバッチ正規化を使用してみて性能を比較して検討してみてほしい。

 

Tensorflowでの書き方は比較対象の記事からgithubのコード置き場に行けるのでそこで読んでほしい。

もしくは

Tensorflowでbatch normlization(バッチ正規化)を使用する際の注意点(常に同じものしか出力しなくなったら) - akikanR’s blog

で紹介している記事にも書き方が載っている

 

Tensorflowでストライクウィッチーズのキャラ判別をしてみた

【はじめに】
今回の奴はストライクウィッチーズのキャラを認識する。

 


 【モデル】

今回のはTensorflowのチュートリアルにはdeep MNISTを基にして作成している。具体的にはバッチ正規化処理を追加しただけだが・・・。


【学習データ】

第一期、第二期ともにエイラーニャ回においてopencvで顔画像を切り取って学習データとしている。
11キャラ、各キャラ40枚を学習データ各キャラ10枚ずつをテストデータとしている

 

【精度】

学習データはエポック1000ぐらいで早々に収束した(99.7%)
step 0, training accuracy 0.113636
step 1000, training accuracy 0.997727
step 2000, training accuracy 0.997727
step 3000, training accuracy 0.997727
step 4000, training accuracy 0.997727
step 5000, training accuracy 0.997727
step 6000, training accuracy 0.995454
step 7000, training accuracy 0.997727
step 8000, training accuracy 0.997727
step 9000, training accuracy 0.997727

凡化性能は以下の通り
test accuracy 0.878788

 

bot化】

twitterボットとして運用していた。

→成果 

f:id:akikanR:20170923214229p:plain

まぁまぁ割とよかった
でもストライクウィッチーズの画像を入れてくれる人は少なかった

f:id:akikanR:20170923214636p:plain

 

【コード】

githubにあげている

github.com

 

【参考サイト】

opencvのアニメ顔を切り出すのに使用させていただきました。

誠にありがとうございます。

OpenCVによるアニメ顔検出ならlbpcascade_animeface.xml - デー

フーリエ変換 メモ3 -フーリエ変換で得られるデータの意味とスペクトルを用いた逆変換-

【5】逆フーリエ変換について
まずは逆フーリエ変換の定義式です

f:id:akikanR:20170605205109p:plain

これを離散フーリエ変換の時と同様に展開していきます
※F (t) を前回離散フーリエ変換した実数部と虚数部が足し合わせたものだとして実数部をR[t] 虚数部をI[t]とします

f:id:akikanR:20170605205120p:plain


となります
ここで注意して欲しいのが「現実の音には虚数は存在しない」ということです
つまり虚数は無視します
すると上記の逆離散フーリエ変換の展開の式は

f:id:akikanR:20170605205136p:plain


ということになります

虚数が扱えないプログラミング言語の場合はこの式を用いていくことになります


【6】フーリエ変換で得られるデータ
フーリエ変換では様々なデータを得られると思うのですが、ここでは特に振幅スペクトルと位相スペクトルについて求め方を記述します

その前に離散フーリエ変換の定義式を思い出してください
Σの中身はcosとisinで記述されていましたね?
ここでcosとsinの幾何的な意味を見てみましょう

f:id:akikanR:20170605205224p:plain


k*cosθは原点から伸びるθ度に傾いた長さkの直線と半径kの円周の交点のX座標を示します
sinθの場合はcosθと同じ点のY座標を示しています


では求め方を説明します
フーリエ変換で得られた値は何かというとF(t)でした
もう少し厳密に言うと実数(=R [t]) と 虚数(=I [t])の和であるF (t) でしたね
この時のR[t] がcosθ、 I[t]がisinθに対応しており、θが位相スペクトル、半径が振幅スペクトルです
あとは単純な計算ですね
上の図の円周と直線kの交点から垂線をおろすと直角三角形が得られます
つまり振幅スペクトルは
三平方の定理より
直角三角形の斜辺の二乗 = 高さの二乗 + 底辺の二乗
よって
周波数 t の振幅スペクトル = √(R[t]の二乗 + I[t]の二乗)

次は位相スペクトルです
手始めにtanθを求め、その後アークtanで角度を求めます
周波数 t の位相スペクトル = arctan ( I[t] / R[t] )

以上で振幅スペクトルと位相スペクトルは求められました

以下これらスペクトルが示す意味です
興味の無い人は見なくても問題ありません

振幅スペクトルと位相スペクトルとはなんなのかを説明しましょう
先ほどの図に時間変化を加えてみます

f:id:akikanR:20170605205249p:plain


歪な図ですみません
この図のθが位相スペクトル、時間経過を加える前の図の円の半径が振幅スペクトルになります
位相スペクトルは周波数(時間経過を加えた時の緑の線)の位相差
振幅スペクトルは周波数(時間経過を加えた時の緑の線)の振幅を表しています
名前通りですね
まとめるとフーリエ変換で得られた各周波数に関する情報が位相スペクトルと振幅スペクトルなのです
また、含まれる周波数に関する情報があるのですから当然足し合わせて元のデータを得ることもできます

 

【7】スペクトルを用いた逆変換
このスペクトルを用いて
周波数 t の振幅スペクトル * e^周波数 t の位相スペクトル という式を立てます
これは F( t )を極座標で表現したものです
つまりは
F( t ) = 周波数 t の振幅スペクトル * e^周波数 t の位相スペクトル
という式が成り立ちます
これを逆離散フーリエ変換の式に当てはめれば無事元のデータになるというわけです
※展開するときに i がついた項は無視することを忘れないでください

Tensorflowでbatch normlization(バッチ正規化)を使用する際の注意点(常に同じものしか出力しなくなったら)

バッチ正規化とは

書く層ごとに分散が1平均が0になるようにするらしい

これを使うことでL2正規化やdropoutの必要性を減らせたり過学習を防げたりといろいろなメリットがあるらしい

こいつを使わないと人生損してるぜHAHAHA的な話もあるらしい

 

 

注意点(落とし穴)

タイトルにも書いた通りちゃんと理屈を知らないと常に同じものしか出力しなくなる

私は理屈知らないのに実装して出力全部同じになった

Tensorflowで実装する際は学習中と学習後で別の処理をしなくてはいけないらしい

 

 

具体的に言うと学習中は与えられるミニバッチの平均や分散を計算する必要があるが学習後は入力に対してそのような処理を行う必要はないらしい

 

じゃあどうすればいいの

Implementing Batch Normalization in Tensorflow - R2RT

この記事の

def batch_norm_wrapper(inputs, is_training, decay = 0.999):

    scale = tf.Variable(tf.ones([inputs.get_shape()[-1]]))
    beta = tf.Variable(tf.zeros([inputs.get_shape()[-1]]))
    pop_mean = tf.Variable(tf.zeros([inputs.get_shape()[-1]]), trainable=False)
    pop_var = tf.Variable(tf.ones([inputs.get_shape()[-1]]), trainable=False)

    if is_training:
        batch_mean, batch_var = tf.nn.moments(inputs,[0])
        train_mean = tf.assign(pop_mean,
                               pop_mean * decay + batch_mean * (1 - decay))
        train_var = tf.assign(pop_var,
                              pop_var * decay + batch_var * (1 - decay))
        with tf.control_dependencies([train_mean, train_var]):
            return tf.nn.batch_normalization(inputs,
                batch_mean, batch_var, beta, scale, epsilon)
    else:
        return tf.nn.batch_normalization(inputs,
            pop_mean, pop_var, beta, scale, epsilon)

のようにバッチ正規化を実装するとよい

 

 

 

フーリエ変換 メモ2 -フーリエ変換の変数の意味と使用例-

【3】フーリエ変換の変数
どの言語でも対応できるようにしたいので実際のコードではなく、あくまで具体的な利用法を文章で記述していきます

まず現実の音データを受け取ったものを f(x) とします
前回のフーリエ変換の定義式の f(x) に対応しています

さて、前回ディリクレの条件を満たすあらゆる関数はsin波とcos波の足し合わせで出来ていることを説明しました
これは受け取る音データに関しても言えることです。ちなみにある関数をsin波とcos波の足し合わせで表現できる形に直すことをフーリエ変換といいます。
これから受け取ったデータをフーリエ変換しよう、つまり「sin波とcos波で表現しよう」というのですから、そのデータはディリクレの条件を満たしていると仮定して進めていくことになります
というか基本的に無視しても問題ないと思います

前回の定義式は

f:id:akikanR:20170605203632p:plain


でした
音に関しては f (x)のxは時間経過で増えていくサンプルの数になります
例えばサンプリングレートが44100Hz(1秒間に44100回サンプルを取る)で一秒間録音した場合
一番最初のサンプルの値はf(0 ) 、一番最後のものはf (44099)に入っています
ここで定義式の中の変数の具体的な意味を見ていきましょう
まずは2πですこれは言わずもがな、360度であり、円です
次にN、これは周期です
周期で2πを割るということは1周期で丁度1回転しますね
Σで変化させている x は2π/Nを0から2πギリギリまで変化させています
周期の単位は「秒」ですからxは時間による変化を示す変数と言えます

では t は何を示す変数なのでしょうか
t = 1のときのcos と sin の中身について考えて見ましょう
t = 1のときのcos と sin の中身は共に 2πx/N
先ほども説明したとおり x は 2π/Nを0から2πギリギリまで変化させます
要するに t = 1のときは丁度周期Nで一周する周波数のフーリエ変換と言えます
この波形を示すとこうなります

f:id:akikanR:20170605204717p:plain

では次にtを2にした波形を示します

f:id:akikanR:20170605204732p:plain


横軸の長さは変わらす繰り返しの回数が増えましたね?

ではt=3のときは?もう画像を貼らなくても分かりますね?繰り返しの回数は3回になります
そう、t は周波数を制御する変数といえます

こと音に関して言えばフーリエ変換とは
時間の関数を周波数の関数に写像する変換
ということができます

では周波数 t はどこからどこまでの範囲にすればいいの?
という話になりますね
私の経験則で申し訳ないのですが音データのサンプル数/2まで移動させれば大丈夫です
もし不十分な場合は音データのサンプル数と同じHz(サンプル数が10000なら10000Hz)まで移動させれば確実です

以上までがフーリエ変換の詳しい話です

 

【4】フーリエ変換の具体的な使用法
いよいよもって具体的な利用法です

といっても[3]で殆ど説明してしまったのでまとめるだけになります
虚数を格納する変数 image と実数を格納する変数 real を用意します

変数 k を1ずつ増やして、音データ数の半分になるまでループ

    real (k) = 0で初期化
    image (k) = 0で初期化
    変数 t を 周期-1 まで1ずつ増やしてループする
    {
        real ( k ) = real ( k ) + real ( t ) * cos(2πtx / N)
        imag( k ) = imag( k ) + image( t ) * sin(2πtx / N)
    }

こんな形になります
ね?簡単でしょ?

 

#初稿2015年4月1日

フーリエ変換 メモ1 -フーリエ変換の発想と離散フーリエ変換-

 

音に関するプログラムをいろいろ組んでみたので忘れないうちにここにメモして置きます
※正しいとは限りません御了承ください

フーリエ変換について
第一にフーリエ変換とは与えられた関数の構成要素を調べる数式です
定義式は

f:id:akikanR:20170605203139p:plain

となります
π:円周率
i :虚数

しかしこれをコンピュータ上で行う場合∞というのは扱いに困りますし、これだけ与えられても具体的にどう取り扱っていいのか分かりませんよね?少なくとも私は分かりませんでした。
よって以下に私が分かればいいや程度で説明していきます。

 

【1】そもそもフーリエ変換の基本的な発想は?
(まとめだけ読んでもたぶん差し支えありません)
そもそもの始まりは「あらゆる関数はsin波とcos波の足し合わせで表現できる」ということをフーリエさんが発見したことでした(流れは違うかもしれませんが基本的なアイディアはこれです)sin波とcos波の足し合わせで表現する関数をフーリエ級数と呼びます。
フーリエさんの「あらゆる関数はsin波とcos波の足し合わせで表現できる」という考え、
実際にはあらゆる関数に適応させることは出来ませんでした
フーリエさんの考えを適応するためには条件があったのです
その条件はディリクレの条件と呼ばれています
といってもディリクレの条件はゆるく、殆どの関数が条件を満たします。唯一注意する必要のありそうな条件は
「周期的な関数でなくてはならない」というものです
周期的といっても大抵の関数は周期的と呼ぶには些か不規則です
ですがこう見るとどうでしょう

ここに全く周期的でない波形があります

f:id:akikanR:20170605203311p:plain

 

上の波形が周期的に繰り返される関数だと考えると

f:id:akikanR:20170605203354p:plain

ね?周期的でしょう?

 

非周期的な関数でも同じものが後に繰り返されていると考えると良いです
こうして考えるとあらゆる関数は周期的であるということができます
<まとめ>
・ディリクレの条件を満たすあらゆる関数はsin波とcos波での足し合わせで表現できる
・ディリクレの条件は非常にゆるい

 

 

【2】コンピュータ上でのフーリエ変換の利用
さて、前項に「ディリクレの条件を満たすあらゆる関数はsin波とcos波での足し合わせで表現できる」 と書いているのに最初に提示されたフーリエ変換にcosもsinもないじゃないか!と思う人もいるでしょう
フーリエ変換の∞の扱いどうするんだ!という疑問と共に答えていきます
まずコンピュータ上では∞を厳密に扱えないため、離散フーリエ変換(略称DFT)を扱います

以下が定義式です

f:id:akikanR:20170605203516p:plain

N:任意の整数(周期をいれる変数)
i :虚数
π:円周率


というわけで∞は消えました
Σの意味はいいですね?
xが0からN-1までxの値を変化させながらΣの中の物を足していくという意味です
このままsin波とcos波を出していきます

ここにオイラーの公式があります

f:id:akikanR:20170605203601p:plain

θ:角度
i : 虚数
これを離散フーリエ変換の式に入れると

f:id:akikanR:20170605203632p:plain

となりsinとcosが出てきました
離散フーリエ変換の定義式がsin波とcos波の足し合わせで表現されていることが理解できましたか?
f(x)はいいの?という声もあるかもしれませんがsinとcosの係数なので問題ないです

虚数を扱えるプログラミング言語では離散フーリエ変換の定義式をそのまま使えば問題はありません
しかし扱えないプログラミング言語の場合は最後に示したフーリエ変換のsinとcosの状態から実数と虚数で分けて計算しなくてはいけません

プログラムでの具体的な使い方は長くなってきたのでまた今度

 

#初稿2015年4月1日

AA自動作成ツール(ひとまずりりーす)

前回の記事で別の手法を試すと言ったな

 

 

 

 

 

あれは嘘だ

 

 

 

 

 

正直いうともうちょっとでなんとかなりそうな気がしたので頑張ってた。

前回までのはMSゴシックの文字をビットマップで読み込んでいた。

これは等幅フォントと呼ばれていて横幅も縦幅も全ての文字で一致している。

だからもうこっちの方でサイズを指定しちゃえばよくね?と思い至った。

その結果がこれ

f:id:akikanR:20170604135224p:plain

ちょっと縦に潰れちゃってるけど大体わかる。

潰れてる部分は今後の課題、二値化の部分の精度がわるいこともあって今はこんなところ。

もっと簡単な画像だともうすこしだけ綺麗になる。

f:id:akikanR:20170604135550p:plain

右端になんか出てるのはたぶん二値化のせい

そのうちgithubにあげる

githubにあげた

github.com