Google人工知能入門講座 20190317 その2

Machine learning crash course (Google)
03 /17 2019
本日、2回目の更新です。

場所は Neural Networks: Playground Exercises のNeural Net Initializationからです。


・ Neural Net Initialization Task 1

ここでは初期条件によってモデルががらりと変わってしまうことを学んでいきます。
まあ、前のtaskで実感しているとは思いますが、やってみましょう。

とりあえず、デフォルトの条件下でトレーニングをしていきます。回数は500回を目安とします。
トレーニングが終わるごとに左上の”Reset the network”ボタンを押して、初期条件を変えてから再度トレーニングをしていきます。
計5回行い、training lossとtest lossの変化具合を見てみましょう。

まず、結果が一番悪かった場合です。
結果は以下の様になりました。

20190317_21.jpg


明らかに学習しきれていないですね。
training lossは0.311、test lossは0.350となっています。


次に、もっとも良かった場合です。
結果は以下の通りです。

20190317_22.jpg


しっかりと学習できていますね。
training lossは0.131、test lossは0.171となっています。
悪かった場合と比べると半分くらい小さな値となりました。

このように、初期条件が違うだけで結果が大きく変わってきます。



・ Neural Net Initialization Task 2

次は、隠れ層とノードの数を増やした場合にどうなるのか見ましょう。
ここでは、様々な初期化の条件に対してモデルが安定するようになるのかが焦点となります。

隠れ層を3つに増やし、1層目にノードを4つ、2層目にノードを4つ、3層目にノードを3つとしてみました。
そして、さっきと同じように5回初期化してトレーニングを行いました。

まず、training lossの値が一番悪かった結果がこちらです。

20190317_23.jpg


training lossは0.130、test lossは0.201となっています。
次に、training lossの値が一番良かった結果がこちらです。

20190317_24.jpg


training lossは0.125、test lossは0.179となっています。
test lossは10 %くらい変わっていますが、training lossはほとんど変わっていないですね。

それぞれのノードでの分布は違っていますが、網目状になっている重み付けがうまいこと機能して、正しく分類を行っていることがわかりますね。

このように隠れ層とノードの数を増やすと、よりモデルが安定するようになることがわかりました。



・ Neural Net Spiral Task 1

ここからはデータの分布が先ほどよりも複雑なスパイラル状の分布へと変化します。

まず、入力変数としてx1とx2の2つだけを用いて、このスパイラル状のデータを記述できるようなモデルを探してみましょう。
とりあえず、隠れ層とノードの数を増やして動かしてみます。
トレーニングの回数は多めにして1500回くらいにしました。
結果は以下の通りです。

20190317_26.jpg


training lossが0.189、test lossが0.368となっています。
出力がかなり上下していて安定していませんし、test lossはtraining lossの2倍ほどあります。

活性化関数を変えたり、正則化や学習率を変えたりしましたが、変数を2つ使ったモデルではこれが一番良い結果でした。


・ Neural Net Spiral Task 2

次は、入力変数として全ての変数を使用していこうと思います。
まずは、前回と同じ条件でやってみます。
結果は以下の通りです。

20190317_27.jpg


training lossが0.109、test lossが0.366となっています。
明らかにオーバーフィッティングですね。
あと、出力も安定していませんし、学習のスピードも遅いですね。

*入力する特徴量を増やすことは、よりニューラルネットワークのモデルを複雑にすることに対応しています。ですので、特徴量を増やした分、モデルをより一般化する必要があるのです。

これらを解決するために、

1.ノードと隠れ層を減すことで、学習のスピードを上げる。
2.曲線を滑らかにするために、学習率を0.01から0.003に減らす。
3.過学習を防ぐために、L2正則化を用いて正則化率を0.001に設定する。
4.入力変数の内、x1x2を落とす。

以上のことを行いました。
その結果がこちらです。

20190317_28.jpg


安定するまでに2000回以上必要となってしまいましたが、なんとか出力の安定した結果を得ることができました。
training lossが0.204、test lossが0.342となっています。

非常に微妙な結果ですね・・・。

この問題、左端のDATAのところをみるとわかりますが、Noiseのところが80となっています。
そりゃあ良い結果が得られるわけがありませんよねぇ~


ちなみに、活性化関数をtanhにすると良い感じのモデルができます。

20190317_29.jpg


前回解説したように、連続的な関数は滑らかな境界を作ります。
螺旋を描く場合は、tanhの方が活性化関数として適しているのかもしれませんね。


今回の問題は明確な答えが無い問題なので、いろいろとパラメーターをいじって遊んでみてください。

今日はここまでです。

お疲れさまでした!

Google人工知能入門講座 20190317

Machine learning crash course (Google)
03 /17 2019
前回の続きから始めていきたいと思います。

場所は Neural Networks: Playground Exercises のA First Neural NetworkのTask 3からですね。


・A First Neural Network Task 3


ここではいろいろと設定を変えてみて、できるだけ少ないノードと隠れ層(hidden layer)のモデルを作るということをします。
また、test lossが0.177以下であることを要請します。
非線形の活性化関数が3つありますので、それぞれの場合で試していきましょう!

*筆者がやっつけ仕事で探し出した設定ですので、それよりも良い設定があると思われます。


ここで、非常に重要なことなのですが、同じモデルでもトレーニングごとに結果が変わってきます

なんかもう一度トレーニングし直したいなと思ったら、”Reset the network” ボタンを押してもう一度再トレーニングしてください。

20190317_0.jpg


1.ReLUの場合

まず、training lossが0.130以下の設定を探しました。


20190317_1.jpg



隠れ層は全部で3層あり、1層目にノードが3つ、2層目にノードが3つ、3層目にノードが2つとなっています。
training lossは0.124、test lossは0.195となっています。

次に、学習率と正則化の条件を変えてtest lossが0.177以下の設定を探しました。


20190317_2.jpg



学習率は0.003、正則化はL2で0.001に設定しました。
やってみるとわかるのですが、ほとんど正則化する必要がないですね。
というか、初期条件で変わりすぎですね・・・。

あと、区分の判別をしている線(青色とオレンジ色の境界にある白い線)が角ばっている感じがしますね。


2.tanh(ハイパボリックタンジェント)の場合

ハイパボリックというのは双曲線関数のことです。
数式だと tanh(x) = (exp(x)-exp(-x))/(exp(x)+exp(-x)) = sinh(x)/cosh(x) と示されます。

ウィキペディアからグラフを引っ張ってくると、以下の図の渋い黄緑色みたいな曲線となっています。


20190317_3.jpg


シグモイド関数のように-∞にいくほど-1に近づき、+∞にいくほど+1に近づく連続的な関数です。
この関数を活性化関数として使用してみましょう。


まずは、training lossが0.130以下の物を探します。


20190317_4.jpg



隠れ層は全部で2層あり、1層目にノードが3つ、2層目にノードが3つとなっています。
training lossは0.128、test lossは0.200となっています。

次に、学習率と正則化の条件を変えてtest lossが0.177以下の設定を探しました。


20190317_5.jpg



学習率は0.003、正則化はL2で0.001に設定しました。
結果的にはReLU関数よりも少ない隠れ層とノード数を持ったモデルとなりましたね。

区分の判別をしている線がReLUよりも丸まっている感じがしますね。


3.シグモイド関数の場合

ロジスティック回帰でおなじみのシグモイド関数を使用していきましょう。
まずは、training lossが0.130以下の物を探します。


20190317_6.jpg


隠れ層は1層だけであり、ノードが5つとなっています。
training lossは0.128、test lossは0.177となっています。

このシグモイド関数、隠れ層の積み重ねにめちゃくちゃ弱いです。

隠れ層を1層でも増やすと、学習のスピードがガクッと落ちます。


20190317_7.jpg


とりあえず、Epochsが1000くらいという縛りを設けていますので、隠れ層が1層だけのモデルを使用しましょう。

次に、学習率と正則化の条件を変えてtest lossが0.177以下の設定を探しました。


20190317_8.jpg


学習率は0.03、正則化はL2で0.001に設定しました。
Test lossの値が変わっていないので、正則化の意味がないですね!

区分の判別をしている線がtanhと同じように丸まっている感じがしますね。

ちなみに、2層のモデルだと学習率を上げることで学習のスピードを上げることができます。

20190317_9.jpg



とりあえず、こんな感じです。
活性化関数によっていろいろと設定を変えなければならないことがわかりましたね。



気付いた方がいるかと思いますが、ここで使用してきた活性化関数はあるところを境目として、2つの値の内のどちらかの値をとっていることがわかります
*ReLUは0を境目に0とx、tanhは0を境目に-1と+1、sigmoidは0を境目に0と+1に分かれる。

これは入力された特徴量の組み合わせに応じて、2種類の値の内どちらかを出すのか判断していることと同じです

つまり、ノードでは入力変数を用いた論理演算がされているのです!


これがニューラルネットワークと呼ばれる所以なのです。
人間の脳みそのニューロンでは入力された電気信号がある閾値を越えた場合に発火します(出力信号を出す)。
ここでは一つ一つのノードがそのニューロンと同じ役目を担っているのです。

以前出てきた図を用いて考えてみましょう。


201903102_6.jpg


活性化関数としてReLUを使用していた場合、一番左のノードでは

output = 入力された変数 ( w11x1+w21x2+w31x3+b > 0  の場合)
output = 0           (w11x1+w21x2+w31x3+b < 0 の場合)

といった計算が行われており、ノードのb(バイアス)の部分は閾値を上げたり下げたりする役割を担っています。

例えば、x1がお腹が空いているかいないかを示すbool型、x2が外食にするかしないかを示すbool型、x3が洋食か和食かを示すbool型とします。
重みをw11=100、w21=10、w31=1とし、b=-110.5と設定します。
すると、お腹が空いていて(x1=1)、かつ外食にして(x2=1)、かつ和食にする(x3=1)の時のみ、入力された変数(w11x1+w21x2+w31x3+b)を出力するようなノードができます。
実際にはこれよりも難しいことを行っていますが、そんな感じの計算を行っているのです。



次に、活性化関数には連続的に変化する関数不連続に変化する関数の2種類があることがわかります。

この違いはどこにでてくるのでしょうか?

それは微分(偏微分)を行うことで分かります。

ReLU関数を微分してみましょう。すると、

output = 0 (x<0)、 x(x>0) が Δoutput = 0 (x<0)、1 (x>0)
*本当は、xは複数の変数から成り立っているので、偏微分をする。

となることがわかります。
つまり、outputの微小な変化は入力変数では調節できないことを示しています。
これは、出力のon、offの境目が非常にハッキリしているということです。


逆に連続的な活性化関数であるシグモイド関数を微分すると、
output = 1/(1+exp(-x))  が 
Δoutput= -1/(1+exp(-x))^2 × (1+exp(-x))'
= -1/(1+exp(-x))^2 × -exp(-x)
= exp(-x)/(1+exp(-x))^2
*本当は、xは複数の変数から成り立っているので、偏微分をする。

となります。
つまり、出力の微妙な変化に対して、入力変数をわずかに変えることで対応できるということです。
これは、出力のon、offの境目を滑らかにすることができるということです。

このように、連続的なのか、不連続的なのかでも出力に大きな差がでてきます。


連続的な関数の場合、この関数の滑らかさが隠れ層を増やしたときの振る舞いに直結しています。
値の境目において、入力変数の変化に対する出力の変化が小さい関数ほど、隠れ層を重ねた時に塗りつぶされてしまうのです。

シグモイド関数がtanh関数よりも学習に時間がかかったのは、おそらくそのせいでしょう。


とりあえず、今回はここまでです。

お疲れさまでした。

Google人工知能入門講座 20190312

Machine learning crash course (Google)
03 /12 2019
今回は短めに記事を更新します。

場所はNeural Networksの Playground Exercises をやっていきたいと思います。

ここでは簡単なニューラルネットワークモデルをトレーニングしていきます。
今回のエクササイズはいろいろとパラメーターを好きにできるので、ちょっと時間をかけていきます。


・ Task1

まず、与えられた設定で動かしてみましょう。

デフォルトの設定では
特徴量=2つ、ニューロン(ノード)=1つ、Hidden layer=1つ、学習率=0.01、活性化関数=線形関数、正則化=L2、正則化率=0
となっています。
とりあえず、1000Epochsくらいまでやります。

20190312_01.jpg


test lossとtraining lossの差が小さいですね。
絶対値としてはどうなのでしょうか?
背景色が左側に行くほど青色、右に行くほどオレンジ色となっています。
明らかにデータの分布に合っていないので、この値は悪いだろうと予測できます。
また、0のところに線を引いて分類している感じなので、線形のモデルだと予想できます。
まあ、デフォルトの設定を見れば当たり前にわかるんですけどね。


・ Task2

次に、Hidden layerを2つにして、ニューロンの数を2つに増やしてみます。
また、活性化関数をReLUに変えてみましょう。

20190312_1.jpg


まだまだ線形っぽいですね・・・。
特徴量の掛け合わせが足りないので、Hidden layerとニューロンの数を増やします。

まず、Hidden layerを4つに増やしてみましょう。

20190312_2.jpg


非線形のモデルになったのがわかりますね。
だいぶデータの分布にあってきましたが、まだまだ合っていません。
図のノードの部分を見るとわかるのですが、分類のパターンが少なく、何層にもわたって同じ分類に強く重みづけされています。

おそらく、ニューロンの数が少ないのでしょう。


今度はHidden layerを2つに戻し、かわりにニューロンの数を4つに増やします。

20190312_3.jpg


すると、どうでしょうか。
さっきよりデータの分布にあっていることがわかります。
ノードの分布をみれば、Hidden layerごとに違った分布を示していて、うまい具合に特徴量が混合されていることがわかります。

このことから、Hidden layerをいくら増やしてもニューロンの数を増やさなければ意味が無いことがわかりますね。


今回はここまでです。

Google人工知能入門講座 20190310 その2

Machine learning crash course (Google)
03 /10 2019
続けて読んでいきます。

今回はNeural NetworksのStructureからです。


・ Structure

Video Lectureの内容とほぼ同じです。

例えば、以下のようなデータの分布があったとします。

201903102_1.jpg

このデータの分類は単純な線形モデル(w1x1+w2x2+b)で行うことはできず、合成特徴量を用いた線形モデル(w3x3, x3=x1x2)で行うことができます。
今回は非常に単純な非線形データだったので、ちょっと工夫をすれば解くことができました。
では、以下のようなデータの分布の場合はどうでしょうか?

201903102_2.jpg


ここまで複雑になると合成特徴量を使った線形モデルでは対応できなくなってきます。
そこで、複雑な非線形データの分類を行うためにニューラルネットワークを導入していきます。

ニューラルネットワークの構造を理解するために、ここでは線形モデルの構造から入っていきます。

線形モデルを図で示すとこんな感じになります。

201903102_3.jpg


青色の丸が入力変数(特徴量)を示し、緑色の丸がモデルの出力を示しています。また、線の部分は重みづけを示しています。
特徴量をx1,、x2、 x3とすれば、出力はそれぞれの重みづけの和(w1x1+w2x2+w3x3)で記述されます。

次に、モデルをもっと複雑にするために中間層(Hidden layer)を導入してみましょう。

201903102_4.jpg


黄色の丸がHidden layerを示していて、それぞれ特徴量の重みづけの和で記述されます。
また、出力はそのHidden layerからの出力の重みづけの和で記述できます。
Hidden layer部分は左から  w11x1+w21x2+w31x3、 w12x1+w22x2+w32x3、 w13x1+w23x2+w33x3 と記述されます。
また、出力は w4(w11x1+w21x2+w31x3)+w5(w12x1+w22x2+w32x3)+w6(w13x3+w23x2+w33x3)と記述されます。

つまり、重みづけの部分を適当に置き換えれば、 w1'x1+w2'x2+w3'x3 という線形の関係で記述できます。

では、もう一つHidden layerを入れてみたらどうなるでしょうか?

201903102_5.jpg


もう気付いていると思いますが、このモデルの出力は w1''x1+w2''x2+w3''x3 といった線形の式で記述されます。
結局のところ、いくら層を追加しても重みづけの回数が増えるだけで、非線形のモデルにはならないのです。

ということで、非線形にする層をぶち込んでみました

201903102_6.jpg


Hidden layerの間にあるピンク色の丸が非線形へと変換している部分になります。
ここでは活性化関数を用いてHidden layer1からの出力を非線形なものへと変換して、Hidden layer2に渡しています。
この非線形化層の数をたくさん増やすことにより、より複雑なモデルを作っていくことができるのです。


非線形へと変換する活性化関数にはいくつか種類があります。
ここではシグモイド(Sigmoid)関数とランプ(ReLU)関数の2つについて触れていきます。

まず、シグモイド関数です。
この関数はロジスティック回帰モデルで出てきましたね。
入力された値を0から1の値へと変換します。数式は以下のようになります。

201903102_7.jpg


入力を横軸、出力を縦軸にとると、その関数の振る舞いは以下のようになります。

201903102_8.jpg


つぎに、ReLU関数を見てみましょう。
数式では以下のように記述されます。

201903102_9.jpg


この関数はシグモイド関数よりも急激に関数が変化しています(x=0付近)。
グラフで示すと以下の通りです。

201903102_10.jpg


ReLU関数はシグモイド関数のような連続的に変化する関数よりも良い結果を出すことが多いです。
また、反応性もReLU関数の方が優れています。


活性化関数は入力された特徴量同士を掛け合わせることができればいいので、非線形であればどんな関数でも活性化関数となりえます。
*次の項目で解説しますが、活性化関数は出力が入力変数の値に応じて2つの値に分かれる必要があります。

Tensorflowではたくさんの活性化関数を使用することができますが、やはりReLU関数が一番良いでしょう。
*他の関数に関しては こちら を参照してください。


最後にニューラルネットワークの構成要素をまとめておきます。
構成要素は以下の通りです。

1.ノード(丸の部分): 各層に存在し、脳のニューロンに似たようなものである。
2.重み(線の部分): 各層を繋いでいる。
3.バイアス: それぞれのノードに対して与えられている。
4.活性化関数: ノードからの出力を変換している。活性化関数は層によって違うものになり得る。

今日はここまでです。

ありがとうございました。

Google人工知能入門講座 20190310

Machine learning crash course (Google)
03 /10 2019
遂にここまで来ました。
ここから佳境に入っていきます。
今回から Neural Networks を読んでいきます。


Neural Networks(ニューラルネットワーク)は文字だけ見ると難しく思えるかもしれませんが、このモデルは合成特徴量を使った線形モデルの発展形みたいなものです。
合成特徴量を使う場合は、あらかじめユーザーがその特徴量同士の組み合わせを決めておく必要がありました。
ニューラルネットワークではモデルの学習を通して特徴量同士の最適な組み合わせを見つけ出し、それを用いて予測を行います。


・ Video Lecture

まず、以下のように分布しているデータがあったとします。

20190309_1.jpg


以前Feature crossesのところで話したように、このような分布は非線形モデルによって記述することができます。
具体的には、合成特徴量x3=x1x2を用いることで
y = sign(x3)
と記述できるのです。


では、次の図のような場合はどうでしょうか?

20190309_2.jpg


この分布を記述できるような特徴量の組み合わせを見つけるのは至難の業です。
数学の天才だったらできるかもしれませんが、私では無理ですね。


ここで登場するのが、ニューラルネットワークなのです。

ニューラルネットワークをモデルとして使用することで、特徴量の組み合わせの最適化をモデルの学習時に行ってしまおうというのがポイントですね。
それでは、ニューラルネットワークのモデルが具体的にどうなっているのか見ていきましょう。

まず、線形モデルを図で示します。

20190310_1.jpg


個々の入力変数に対して重み付けを行い、最後に足し合わせています。
次に、この線形モデルを非線形モデルへと変えていきましょう。
まず、特徴量を組み合わせる層を1つ追加してみます。

201903101_01.jpg


組み合わせは複雑になりましたが、まだ線形モデルですね。
それではもう一層追加してみましょう。

20190310_3.jpg


重みづけのパターンが増えましたね。
でも、組み合わせが増えただけで、まだ線形モデルです。
非線形モデルに必要な入力変数同士を掛け合わせる作業に対応する部分がどこにもありません。

なので、Hidden Layerからの出力を非線形のものへと変換する層を導入します。

20190310_4.jpg


ここではray louと呼ばれる手法を用いて、非線形へと変換する層を加えて非線形モデルにしています。
その変換層ではHidden Layerからの出力を以下のようなRectified Linear Unit(正規化線形関数)を用いて変換しています。

20190310_5.jpg


この関数への入力が0以下の場合は0となり、0以上の場合はその入力値をそのまま出力します。
見るとわかるように、0を境目に振る舞いが変わっていて非線形な関数となっています。
これのおかげで、線形モデルから非線形モデルへと変換しているのです。
もちろん、非線形モデルへと変換する関数は他にもありますが、このray louは幅広い問題に対して十分な成果を出してくれます。

ーーーー脱線開始ーーーー

非線形関数を間に挟むことが、なぜ変数同士を組み合わせる作業に対応するのでしょうか?
それはテイラー展開などで関数の近似を見てみるとわかりやすいです。
Relu関数では0付近での展開が不可能(不連続で微分ができない)なので確かめられませんが、同じように活性化関数として使用されるシグモイド関数などを試しに展開してみると、xの多項式が出てくることがわかります。
つまり、入力変数同士を掛け合わせた多項式で表現できるということです。
よって、シグモイド関数を通して入力変数が掛け合わされて非線形なものに出力されるわけですね。

ーーーー脱線終了ーーーー

この変換層をぶち込んでいくことにより、線形モデルでは表現できないような複雑な組み合わせを持ったニューラルネットワークモデルが完成するのです!
*通常、この変換層は図に示されていません。

20190310_6.jpg


こうして、非線形なデータに対応できるモデルが出来上がりました。
しかし、このニューラルネットワークモデルをトレーニングする際に、最適化の問題(non convex)と初期化の問題が生じます。
なので、線形モデルで使用していた最小化の方法(最急降下法(gradient descent))ではなく、back propagationと呼ばれる方法を用います。


今回はここまでです。

シジミパワー

 ブログ初心者です。よろしくお願いします。

 チャットボットにこちらからアクセスできます。
 チャットボットの開発及び運用は終了しました。使ってくださった皆様、ありがとうございました。

 
 ふりーむにゲームを掲載させていただきました。掲載されているページへ移動する場合はここをクリックしてください。