おひとりさま現役パラレルワーカーフクコろぐ

これからの会社員は、複数の収入源をもとう! 会社に翻弄されずアナタらしく仕事ができる。 そんなパラレルワーカーを広めるフクコのブログです。

【文系プログラミング初心者deE資格】ゼロつくディープラーニング #28

f:id:fukuko-parallel-work:20211127163503j:plain

こんにちは!

現役パラレルワーカー フクコです。

f:id:fukuko-parallel-work:20210212204833p:plain



前回の記事↓に続き

www.fukuko-parallel-work.com







来年の2月の試験に向けてE資格試験勉強中のため


E資格とは?の記事はコチラ↓

www.fukuko-parallel-work.com




ゼロつくシリーズでおなじみ

オーライリーから出版されている

ディープラーニングの本格的な入門書でよくおススメされる

「ゼロからつくる Deep Learning」本


f:id:fukuko-parallel-work:20211029220008j:plain





この本↑を毎日5ページずつコツコツこなす

約2か月間で今年中に終了するので

来年のE資格試験までにこれで基礎力をつけることにしました。(^^)


ついつい私は何もないとだらけてしまうので(笑)

毎日5ページ終わった後の記録とまとめを書いていこうと思います。


と、まとめに入る前に…

やる気を出すためのコトバをシェアします!!(主に私のやる気を出すために 笑)

「一番弱い人が一番可能性を持ってるんだよ」

by 炭治郎


私の大好きな鬼滅の刃から

炭治郎の名言です。


そう!まだよくわかっていないひよっこな弱い立場だからこそ

これから大きく伸びる可能性があるんですよね。

あ~、もうホント鬼滅の刃」のコトバはグッときますよね。(^^)


炭治郎、どうもありがとう! (^0^)

今日もやる気が出てきました! 

よし!! 今日も頑張るぞ~! お~!! 

というコトで、

まだまだへっぽこなプログラミング初心者な私ですが、とにかく努力と継続あるのみ!今日もノルマをこなしますよ! 笑


ではでは、いい加減まとめに入ります。笑




その前に本の目次の紹介です。

ゼロつくディープラーニングは、下記↓の合計8章で構成されています。

本の目次

  • 5章 誤差伝播法
  • 6章 学習に関するテクニック



ちなみに…

ゼロつくディープラーニング第1章はPython入門のセクション(20ページ分)なので、

とりあえず今回私は飛ばし、第2章からまとめています。

現在は、第6章からで~す。



第6章 学習に関するテクニックつづき


ニューラルネットワークの学習において

キーとなる重要なアイディアを説明する。

ニューラルネットワークの学習を効率的に進め、認識精度を高める手法を紹介。

RMSPropについて


(なぜか本には書いていないですが)
RMSPropについてちょっと補足:

RMSPropAdaGradの進化系誤差をパラメータで微分したものと再定義した学習率の積を減算


RMSPropの更新方法の数式は以下のとおり。


h_{t}αh_{t - 1} + {(1‐α)} {\nabla}{E}^{2}

W^{t+1}W^{t} - \varepsilon \dfrac{1}{\sqrt{n_{t}}+\theta }\nabla E


RMSPropの実装Pythonでは以下のとおり。

# RMSProp
import numpy as np

class RMSProp:
    def __init__(self, lr = 0.01):
        self.lr = lr
        self.h = None
    
    def update(self, params, grads):
        if self.h is None:
            self.h = {}
            for key, val in params.items():
                self.h[key] = np.zeros(val)
        
        for key in params.keys():
            self.h[key] *= self.decay_rate
            self.h[key] += (1-self.decay_rate) * grad[key] * grad[key]
            params[key] -= self.learning_rate * grad[key] / (np.sqrt(self.h[key])+1e-7)
6.1.6 Adam


Adam
↑1番よく使われる!!

Momentumは、ボールがお椀を転がるように物理法則に準じる動き

RMSPropは、Momentumの進化系適応的に更新ステップを調整する

では、このRMSPropAdaGradくっつけるとどうなるか??

それが、Adamという手法。

Adamは、RMSPropAdaGradの融合した手法


Adamを数式で表すと以下のとおり。


V_{t}\beta_{1} V_{t-1}+ ( 1‐ \beta_{1} ) G

S_{t}\beta_{2} S_{t-1}+ ( 1‐ \beta_{2} ) G^{2}

W_{t}=W_{t-1}-\alpha \dfrac{v_{t}}{\sqrt{S_{t}+\varepsilon }}

ハイパーパラメータの「バイアス補正」が行われていることもAdamの特徴。

メリットモメンタムとRMSPropのいいとこどりを取った最適化アルゴリズム


6.1.7 どの更新手法を用いるか?


5つのパラメータ更新法を見てきた。

1. SGD
2. Momentum
3. RMSProp
4. AdaGrad
5. Adam


最近では、一番Adamが使われている


Pythonでそれぞれを実装して比較してみると

次の結果のとおり↓。

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import numpy as np
import matplotlib.pyplot as plt
from collections import OrderedDict
from common.optimizer import *


def f(x, y):
    return x**2 / 20.0 + y**2


def df(x, y):
    return x / 10.0, 2.0*y

init_pos = (-7.0, 2.0)
params = {}
params['x'], params['y'] = init_pos[0], init_pos[1]
grads = {}
grads['x'], grads['y'] = 0, 0


optimizers = OrderedDict()
optimizers["SGD"] = SGD(lr=0.95)
optimizers["Momentum"] = Momentum(lr=0.1)
optimizers["AdaGrad"] = AdaGrad(lr=1.5)
optimizers["Adam"] = Adam(lr=0.3)

idx = 1

for key in optimizers:
    optimizer = optimizers[key]
    x_history = []
    y_history = []
    params['x'], params['y'] = init_pos[0], init_pos[1]
    
    for i in range(30):
        x_history.append(params['x'])
        y_history.append(params['y'])
        
        grads['x'], grads['y'] = df(params['x'], params['y'])
        optimizer.update(params, grads)
    

    x = np.arange(-10, 10, 0.01)
    y = np.arange(-5, 5, 0.01)
    
    X, Y = np.meshgrid(x, y) 
    Z = f(X, Y)
    
    # for simple contour line  
    mask = Z > 7
    Z[mask] = 0
    
    # plot 
    plt.subplot(2, 2, idx)
    idx += 1
    plt.plot(x_history, y_history, 'o-', color="red")
    plt.contour(X, Y, Z)
    plt.ylim(-10, 10)
    plt.xlim(-10, 10)
    plt.plot(0, 0, '+')
    #colorbar()
    #spring()
    plt.title(key)
    plt.xlabel("x")
    plt.ylabel("y")
    
plt.show()

Pythonでそれぞれを実装結果と結果を図にすると↓のとおり。


f:id:fukuko-parallel-work:20211127222430j:plain


f:id:fukuko-parallel-work:20211127222501j:plain



黄色ハイライトにあるように、Adamの結果がイチバン最適化されている。

6.1.8 MNISTデータセットによる更新手法の比較


MNISTデータをつかって

最適化手法の比較をPythonで実装してみると↓のとおり。

# coding: utf-8
import os
import sys
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from common.util import smooth_curve
from common.multi_layer_net import MultiLayerNet
from common.optimizer import *


# 0:MNISTデータの読み込み==========
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)

train_size = x_train.shape[0]
batch_size = 128
max_iterations = 2000


# 1:実験の設定==========
optimizers = {}
optimizers['SGD'] = SGD()
optimizers['Momentum'] = Momentum()
optimizers['AdaGrad'] = AdaGrad()
optimizers['Adam'] = Adam()
#optimizers['RMSprop'] = RMSprop()

networks = {}
train_loss = {}
for key in optimizers.keys():
    networks[key] = MultiLayerNet(
        input_size=784, hidden_size_list=[100, 100, 100, 100],
        output_size=10)
    train_loss[key] = []    


# 2:訓練の開始==========
for i in range(max_iterations):
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
    
    for key in optimizers.keys():
        grads = networks[key].gradient(x_batch, t_batch)
        optimizers[key].update(networks[key].params, grads)
    
        loss = networks[key].loss(x_batch, t_batch)
        train_loss[key].append(loss)
    
    if i % 100 == 0:
        print( "===========" + "iteration:" + str(i) + "===========")
        for key in optimizers.keys():
            loss = networks[key].loss(x_batch, t_batch)
            print(key + ":" + str(loss))


# 3.グラフの描画==========
markers = {"SGD": "o", "Momentum": "x", "AdaGrad": "s", "Adam": "D"}
x = np.arange(max_iterations)
for key in optimizers.keys():
    plt.plot(x, smooth_curve(train_loss[key]), marker=markers[key], markevery=100, label=key)
plt.xlabel("iterations")
plt.ylabel("loss")
plt.ylim(0, 1)
plt.legend()
plt.show()


そして結果が↓となる。

f:id:fukuko-parallel-work:20211127222535j:plain


f:id:fukuko-parallel-work:20211127222559j:plain


黄色ハイライトにあるように、今回もAdamの結果がイチバン最適化されている。

とはいうものの、必ずしも毎回Adamがイイとは限らない

それぞれの最適化手法には特徴があり

全てのモンダイで優れた手法というのは今のところない

6.2 重みの初期値


ニューラルネットワークの学習で特に重要になってくるのが、

重みの初期値


重みの初期値の値の設定次第で、

ニューラルネットワークの学習の成否がわかれることが結構ある

6.2.1 重みの初期値を0にする?


Weight Decay(荷重減衰)

過学習を抑え、汎化性能を高めるテクニック

重みのパラメータの値が小さくなるように学習を行う手法


重みの初期値は、

小さい値からはじめるのが正攻法


基本的には、

ガウス分布から生成される0.01倍した小さな値からはじめるとイイ。


ちなみに

重みの初期値を0にするのはダメ!!


なぜなら、

全ての重みが均一に更新されてしまうから

今日のまとめ


ハイ、今日はここまで!!

慣れてないので数式をLaTeXを使ってキレイに表すのに今日はてこずりました…

そのうち慣れるのかな…?(>ー<)

第6章の学習に関するテクニックまだまだ続きます!(^^)

引き続き頑張りまっす。


最後まで読んでくださり、ありがとうございます!

フクコ


ディープラーニング入門書おススメ本


E資格とは?

www.fukuko-parallel-work.com