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

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

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

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


こんにちは!

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

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



前回の記事↓に続き

www.fukuko-parallel-work.com




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


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

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

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

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


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




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

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

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


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

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


と、まとめに入る前に…

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



「永遠というのは、人の想いだ。

人の想いこそが、永遠であり

不滅なんだよ。」

by 産屋敷 耀哉



おなじみ私の大好きな鬼滅の刃から

お館様、産屋敷 耀哉の名言です。

お館様鬼殺隊第97代当主

鬼殺隊の剣士たちを「私の子供たち」と呼び

鬼殺隊の剣士たちからは「お館様」と呼ばれ慕われ、

そして

代々短命の一族で病に冒されていても、

自分のことよりも隊員たち、子供たちのことをいつも一番に考えるようなヒトです。


そうですよね! 想いは不滅、やろうと思えば何でもできる!

お館様、どうもありがとう! (^0^)

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

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

というコトで、今日もコツコツ私はノルマをこなしますよ! 笑


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



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

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

本の目次

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


ちなみに…

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

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

今回も第4章のつづきからでーす。


第4章 ニューラルネットワークの学習つづき


ニューラルネットワークの学習とは、

訓練データから最適な重みパラメータの値を自動で獲得するようにできるコト


4.4.2 ニューラルネットワークに対する勾配つづき


ニューラルネットワークにおいても勾配を求める必要がある。

ココでいう勾配

重み(w)パラメータに関する損失関数の勾配


コレを実際に式で表すと…


 \boldsymbol{W} =
\begin{pmatrix}
W₁₁&W₁₂&W₁₃\\
W₂₁&W₂₂&W₂₃
\end{pmatrix}


 {\displaystyle\dfrac{\partial L}{\partial W}} =
\begin{pmatrix}
\dfrac{\partial L}{\partial W₁₁} & \dfrac{\partial L}{\partial W₁₂} & \dfrac{\partial L}{\partial W₁₃} \\
\dfrac{\partial L}{\partial W₂₁}& \dfrac{\partial L}{\partial W₂₂} & \dfrac{\partial L}{\partial W₂₃} 
\end{pmatrix}


簡単なニューラルネットワークを例にして、

実際に勾配を求める実装を、Pythonで↓おこなってみる

# 簡単なニューラルネットワークを例にして、実際に勾配を求める実装
# まずはライブラリインポート
import sys, os
sys.path.append(os.pardir)
import numpy as np
from common.functions import softmax, cross_entropy_error
from common.gradient import numerical_gradient

# simpleNetというクラスを実装
class simpleNet:
    def __init__(self):
        self.W = np.random.randn(2,3)#ガウス分布で初期化
    
    def predict(self, x):
        return np.dot(x, self.W)
    
    def loss(self, x, t):
        z = self.predict(x)
        y = softmax(z)
        loss = cross_entropy_error(y,t)
        
        return loss

さて、

このsimpleNetというクラス

2つのメソッドがあり、

1つはメソッドpredict(x)

もうひとつは、loss(x, t)


試しにsimpleNetというクラス↓を使ってみる。

net = simpleNet()
print(net.W)#重みパラメータ
# 答えのサンプルは、
# [[ 1.0931522  -0.47853908 -0.1972123 ]
#  [ 0.35372926  1.93712001 -1.20250256]]

x = np.array([0.6, 0.9])
p = net.predict(x)
print(p)
# 答えのサンプルは、
# [ 0.97424765  1.45628456 -1.20057968]

np.argmax(p)#最大値のインデックス
# 答えのサンプルは、
# 1

t = np.array([0,0,1])#正解ラベル
net.loss(x,t)
# 答えのサンプルは、
# 2.253856304885929

つづいて

numerical_gradient(f,x)を使って、Pythonで勾配を求めてみる。

# numerical_gradient(f,x)を使って、Pythonで勾配を求めてみる。

def f(W):
    return net.loss(x, t)

dW = numerical_gradient(f, net.W)
print(dW)

# 答えは、
# [[ 0.0908701   0.44613331 -0.53700342]
#  [ 0.13630516  0.66919997 -0.80550512]]


この↑の関数の定義はlambdaという記法で↓のように書くことも可能

# この↑の関数の定義はlambdaという記法で↓のように書くことも可能。

f = lambda w:net.loss(x,t)
dW = numerical_gradient(f, net.W)
print (dW)
# 答えは、
# [[ 0.0908701   0.44613331 -0.53700342]
#  [ 0.13630516  0.66919997 -0.80550512]]
4.5 学習アルゴリズムの実装


ニューラルネットワークの学習の手順を確認する。



- 前提


ニューラルネットワークは、適応可能な重みとバイアスがあり

この重みとバイアスを訓練データに適応するように調整することを「学習」するという。



- 学習ステップ1(ミニバッチ)


訓練データの中からランダムに一部のデータを選び出す

その選ばれたデータは、「ミニバッチ」とよばれ、

ミニバッチの損失関数を最小にすることが目的とされる。



- 学習ステップ2(勾配の算出)


ミニバッチの損失関数を減らすのに、各重みパラメータの勾配を求める

勾配は、 損失関数の値を最も減らす方向を示す



- 学習ステップ3(パラメータの更新)

重みパラメータを勾配方向に微笑量だけ更新する



- 学習ステップ4

ステップ1~3を繰り返す


ランダムにデータは選ばれたものに対して勾配を求めていくので、

確率的勾配降下法」(Stochastic Gradient Descent) = SGD

という名前の関数で実装される。


4.5.1 2層ニューラルネットワークのクラス


2層ニューラルネットワーク

1つのクラスとして実装することからやってみる

TwoLayerNetという名前のクラスとして、

Pythonで↓の様に実装してみる。

# 1つのクラスとして実装することからやってみる。
# TwoLayerNetという名前のクラスとして、
# Pythonで↓の様に実装してみる。

import sys, os
sys.path.append(os.pardir)
from common.functions import *
from common.gradient import numerical_gradient
import numpy as np

class TwoLayerNet:
    
    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        #重みの初期化
        self.params = {}
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hiddent_size)
        
        self.params['b1'] = np.zeros(hidden_size)
        
        self.params['W2'] = weight_init_std * np.random.randn(input_size, hiddent_size)
        
        self.params['b2'] = np.zeros(output_size)

    def predict(self, x):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
        
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)
        
        return y
        
    # x:入力データ t:教師データ
    
    def loss(self, x, t):
        y = self.predit(x)
        
        return cross_entropy_error(y,t)
    
    def accuracy(self,x,t):
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        t = np.argmax(t, axis=1)
        
        accuracy = np.sum(y == t) / float(x.shape[0])
        return accuracy
    
    # x:入力データ t:教師データ
    
    def numerical_gradient(self,x,t):
        loss_W = lambda W: self.loss(x,t)
        
        grads = {}
        
        grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
        grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
        grads['b2'] = numerical_gradient(loss_W, self.params['b2'])
        
        return grads

今日のまとめ


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

今回はコーディングが多かったわ~(>ー<)ふう…

もともとコーディングの勉強なんだから当たり前ですね。 笑

ということで、第4章はまだまだつづきます!

引き続き頑張りまっす。


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

フクコ


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