BETA

fastai動かしてみたLesson5④ Adam、Momentum、CrossEntropyLoss

投稿日:2019-05-26
最終更新:2019-05-26

今回はLesson5 https://course.fast.ai/videos/?lesson=5

notebookはこちら https://github.com/fastai/course-v3/tree/master/nbs/dl1

Adam

Excelで勾配降下法を行ってみよう

Excelファイルはこちら:https://github.com/fastai/course-v3/blob/master/files/xl/graddesc.xlsm

dataのシートを見てみる
xとyはランダムに生成された数値である

basicのシートを見てみよう

このシートにはSGDで行った結果が示されている
y = ax + bを行う
このExcelではy_pred = slope × x+interceptと表せる

Lesson2では、全てのデータを1バッチとして扱った
今回は全てのデータを分割し、ミニバッチを作った
このシート内では、一つ一つの行がバッチである
つまり、バッチサイズは1である

いつも通り、傾き(slope)と切片(intercept)に任意の数値を入れる
ここではとりあえず適当に1を入れておく

勾配を計算し、更新する
勾配を計算する方法は2つある
1つは、WolframAlpha(https://ja.wolframalpha.com/ )みたいな計算ツールを使ったり手計算でde/dbを行って求める方法
もう1つはFinite differening(有限差分?)と呼ばれるものを使う方法だ
勾配というのは結果がどれだけ移動するかをどれくらいの小さい変更で動くかで割った数値である
少し変更を加えてみよう

ここでは損失を
$$(((切片+0.01)+傾き×x)-y)^2$$を行う事で求めている
つまり
$$y_{pred} = ax + (b+0.01)$$
として損失を計算している
0.01を加えることによって、何もしない場合の損失(err^2)と比べて損失が小さくなったことがわかる

est de/dbには、err^2とerrb1の差を0.01で割ったものが入っている
この値をfinite differencingという

あるいは、de/dbとxを掛け合わせる事で、似たような値を得ることが出来る
$$\frac{de}{db} = 2(y-y_{pred})$$
$$
\frac{de}{da} = x\frac{de}{db}
$$

そして、現在の重みa、切片bと学習率(learning_rate)×de/daを使って、重みと切片の更新を行う
$$new_a = 重みa(slope)-学習率lr(learning rate)×\frac{de}{da}$$
$$new_b = 切片b(intercept)-学習率lr(learning rate)×\frac{de}{da}$$

ここまでで1epochとなり、次のepochではここで新しくしたnew_aとnew_bを傾きと切片として扱う

これをどんどん行っていく事で精度を上げる
コピペなどの単純作業なのでマクロをJeremy氏が作っておいてある
コピペするだけで実行できるので、とりあえず5epochだけ実行してみると

epochごとのエラーを表示することが出来た
しかしながら、このままだとスピードがとても遅い

Momentum

Momentumを使う事で速度を上げることが出来る

Momentumのシートである
これはさっきのシートと中身は同じであり、微分積分の列(est~~)はいらないので削除してある

今回行うのは、微分した奴(2(ax+b-y))に0.1を掛けて今回のupdate(仮)を求め、前回のupdateに0.9を掛けて、その総和をupdate(更新結果)としている

今まではepoch数が進んでも同じ事をやり続けていた
epoch数が進んだ場合は、どんどん学習率を小さくしないと局所の解にたどり着く事が出来なくなる
そこで、momentumを設定する事で、小さなステップでまず動き出し、だんだん大きくなり、そして最終的に小さく動くという風になる

上で行っている事を簡単に書くと、$$S_t = αg+(1-α)S_{t-1}$$
となり、これを指数平滑移動平均(Exponentially Weighted Moving Average)、EWMAという

RMSProp


RMSPropのシート

RMSPropはMomentumに似ている
Momentumでは勾配をそのまま使ったが、EMSPropは勾配の二乗を使う

さっきと同じようにRMSPropを使って学習を進めると、RMSPropの方がMomentumよりも早く損失を小さくすることが出来る

Adam

Adamは、勾配の二乗を使ってEWMA(RMSProp)した物と勾配を使ってEWMA(Momentum)した物を持つ
そして両方をEWMAで割り、そして前と似たように0.9を掛け合わせる

このRMSPropとMomentumを組み合わせたものをAdamという

この最適化手法を動的学習率という
多くの人が学習率を設定しなくていいと誤解している
しかし、実際のところは設定した方がいい
そうしないと、最終的におんなじ所を動き回るからだ

AdamとWeight Decayを組み合わせることで、ものすごい速度で学習させることが出来る

いつも通り最適な学習率を探してみる

learn = Learner(data, Mnist_NN(), loss_func=loss_func, metrics=accuracy)  
learn.lr_find()  
learn.recorder.plot()  

見つけた学習率で学習させる

learn.fit_one_cycle(1, 1e-2)  

epoch train_loss valid_loss accuracy time
0 0.153200 0.131962 0.960700 00:04

すごいはやい

Fit one cycle

ここにきて、fit one cycleとは何だろうという事である

左がLearning rate、右がMomentumである
どちらもバッチごとの状態をプロットしている
Adamは学習率を持っており、FastaiではデフォルトでAdamを設定してある

学習率は初めは小さい値から半分の時間までは増え、残りは小さくなっていく
なぜなら、学習が始まったばかりだと、自分がどこにいるかわからないからである
関数空間のどこかに居て、そこは凸凹している
そこで初めは少しずつ動き出しめないと、自分は変な所に飛んで行ってしまう
従って、少しずつ動き出すことで、重み空間の理にかなった点に移動でき、理にかなった点にたどり着くと、勾配は自分が行きたい方向にあるので、学習率を増加させていく

右はMomentumである

(ここら辺うまく解釈できませんでした)

表形式データに戻る

Lesson4のTabularのノートブックはこちら:https://github.com/fastai/course-v3/blob/master/nbs/dl1/lesson4-tabular.ipynb

from fastai.tabular import *  

path = untar_data(URLs.ADULT_SAMPLE)  
df = pd.read_csv(path/'adult.csv')  

dep_var = 'salary'  
cat_names = ['workclass', 'education', 'marital-status', 'occupation', 'relationship', 'race']  
cont_names = ['age', 'fnlwgt', 'education-num']  
procs = [FillMissing, Categorify, Normalize]  

初めにやる事は、どのようにカテゴリカル変数を予測するかわからないという事だ
ここではnn.CrossEntropyLossを使わずに、Excelでやってみる

今回は正しい物を正確に、自身をもって予測したい
MSEはこれにはあまり向いていない
Cross Entropy Lossは向いている

ここでは例として、犬か猫かを判別するものとする

これは犬か猫かのone-hot エンコードである
その横に犬か猫かの確率がある
一行目は全然自信がない
2行目は猫であることに非常に自信がある
3行目も猫であることに非常に自信があるが、実際は犬である
Cross Entropy Lossは間違っていれば1に近くなり、あっていれば0になる

Cross Entropy Lossはone-hotにその確率の対数を掛けて、その総和を正にしたものである

X-Entropyの列の右は、Softmax関数を使った結果を示している
これは、入力された値が0~1になるように設定する

指数関数eでやったとしたらどうなるだろうか
expの最も下にある奴はexpの総和である
softmaxは、それぞれのexpをexpの総和で割ったものである
つまり、softmaxというのは、exp活性化をその総和で割ったものと等しいという事である
そのため、シングルラベルのマルチクラス分類を行う場合には、一般的には活性化関数としてsoftmax関数が、損失関数としてはCross Entropyが必要であり、よく使われる

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

大学生の書きなぐりブログ 間違ってる事も書いてるので自己責任で勉強しましょう

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!