見出し画像

「Deep Learning」って何? 学習、パラメータの更新の最適化。

Deep Learningで大事なところです。学習してパラメータを最適化していくという過程を考えてみましょう。(第6章となります。)

何が大切か?ということからです。

ネットワークの中でのパラメータ更新の役割ですが、すごく重要です。これができないと正確な判定、判断できません!

これを使いやすく、わかりやすくするためにSGD(確率的勾配降下法)をクラス化します。

class SGD:
   def __init__(self, lr=0.01):
       self.lr = lr
   def update(self, params, grads):
       for key in params.keys():
           params[key] -= self.lr * grads[key]

paramsとgradsです。パラメータと勾配の更新をします。

実際には動かない単純なモデル(イメージ)で本の中で説明されていますのでそのまま引用します。

ネットワーク2層のネットワークを使います。

network = TwoLayerNet(...)

そして先ほど作ったクラス

optimizer = SGD()

ネットワーク、最適化するクラスを実装して実際に使う想定でコードを組むと、

for i in range(10000) :
       ...
   x_bath, t_bath = get_mini_batch(...)
   grads = network.gradient(x_batch, t_batch)
   params = network.params
   optimizer.update(params, grads)
   ...

こんな感じで"optimizer"を実行することでネットワークのパラメータ、勾配を最適化します。

例示しているSGDには欠陥(更新経路についてジグザグ)があるために他の方法も考えられていて、ネットワークごとに判断されているところです。

Momentum

更新経路についてSGDがジグザグなのに対して少し軽減することができる。

class Momentum:

   """Momentum SGD"""

   def __init__(self, lr=0.01, momentum=0.9):
       self.lr = lr
       self.momentum = momentum
       self.v = None
       
   def update(self, params, grads):
       if self.v is None:
           self.v = {}
           for key, val in params.items():                                
               self.v[key] = np.zeros_like(val)
               
       for key in params.keys():
           self.v[key] = self.momentum*self.v[key] - self.lr*grads[key] 
           params[key] += self.v[key]

AdaGrad

最小値に向かって効率的に動くことができる。

class AdaGrad:

   """AdaGrad"""

   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_like(val)
           
       for key in params.keys():
           self.h[key] += grads[key] * grads[key]
           params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)

Adam

MomentumとAdaGradとの融合

class Adam:
   """Adam (http://arxiv.org/abs/1412.6980v8)"""
   def __init__(self, lr=0.001, beta1=0.9, beta2=0.999):
       self.lr = lr
       self.beta1 = beta1
       self.beta2 = beta2
       self.iter = 0
       self.m = None
       self.v = None
       
   def update(self, params, grads):
       if self.m is None:
           self.m, self.v = {}, {}
           for key, val in params.items():
               self.m[key] = np.zeros_like(val)
               self.v[key] = np.zeros_like(val)
       
       self.iter += 1
       lr_t  = self.lr * np.sqrt(1.0 - self.beta2**self.iter) / (1.0 - self.beta1**self.iter)         
       
       for key in params.keys():
           #self.m[key] = self.beta1*self.m[key] + (1-self.beta1)*grads[key]
           #self.v[key] = self.beta2*self.v[key] + (1-self.beta2)*(grads[key]**2)
           self.m[key] += (1 - self.beta1) * (grads[key] - self.m[key])
           self.v[key] += (1 - self.beta2) * (grads[key]**2 - self.v[key])
           
           params[key] -= lr_t * self.m[key] / (np.sqrt(self.v[key]) + 1e-7)
           
           #unbias_m += (1 - self.beta1) * (grads[key] - self.m[key]) # correct bias
           #unbisa_b += (1 - self.beta2) * (grads[key]*grads[key] - self.v[key]) # correct bias
           #params[key] += self.lr * unbias_m / (np.sqrt(unbisa_b) + 1e-7)

いろいろ試してみたいと思います。まずはイメージから。最適化のイメージは少し持てたかな?少しずつやっていきましょ。


この記事が気に入ったらサポートをしてみませんか?