.NET 開発基盤部会 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

学習フェーズでは、信号は逆方向に伝播する。

  • 学習とは、重みパラメタを自動獲得するためのもの。
  • 実際のニューラルネットワークの重みパラメタは、
    • 数千、数万になるため、手動での設定は不可能。
    • 更に層を深めた深層学習(deep learning)では数億にも登る。
  • 重みパラメタの自動獲得のため、
    • 損失関数という指標を導入する。
      損失関数を使用して値が最小(最大)になるような重みパラメタを探す。
    • このようなパラメタを探し出すためには、勾配法という手法を用いる。
      勾配は、各場所で(損失)関数の値を最も減らす方向を示す。

学習はデータ駆動

  • MNISTデータセットの分類処理を行うアルゴリズムを考え出すのは困難。
    しかし、機械にデータを学習させる機械学習を用いれば分類処理が実現可能。

    人間が(暗黙的な学習によって、)これらを判別することはできる。
    従って、人間の脳も、一部は、このようなデータ駆動で動いているのかもしれない。

  • このように、アルゴリズムを捻り出すのではなく、データを有効活用して解決する方法に、
    画像から特徴量を抽出し、特徴量のパターンを機械学習の技術で学習するという方法がある。

機械学習

特徴量

  • 入力された学習データから特徴量と呼ばれる数値を抽出する。
  • 学習データにどのような特徴があるかを数値化したもの。
  • 特徴量の抽出は人間が設計し実装する必要がある。
  • 抽出した特徴量を元に機械はパターン・経験則をモデルを使って学習する。

特徴量選択

入力画像データから、本質的なデータを抽出できるように設計された変換器を指す。

  • 画像データの特徴量は通常、ベクトルを使用して表される。
  • SIFT, SURF, HOGなど、人が設計した変換器によって画像データをベクトル化する。

機械学習

ベクトル化された画像データを機械学習のSVMやKNNなどの識別器で学習させる。

深層学習(deep learning)

深層学習(deep learning)においては、特徴量についても機会が学習する。

損失関数

  • 深層学習(deep learning)では一つの指標を手がかりに最適なパラメタを探索する。
  • この指標を損失関数を呼び、パラメタに対して連続的に変化する関数を用いる。
  • これは学習時に、微分によって傾きが0になってパラメタの更新できなくなることを防ぐため。

2乗和誤差

ニューラルネットワークの出力と正解となる教師データの各要素の差の二乗の総和の2分の一。

  •                  2
    E = 1/2 Σ (yk-tk)
             k
  • 説明
    • k:データの次元数
    • yk:ニューラルネットワークの出力
    • tk:教師データ
  • 例(k=10)
    • yk:ニューラルネットワークの出力
      =[0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
      ソフトマックス関数の出力(全て足して1.0になる。)
  • tk:教師データ
    =[0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
    ※ 正解ラベルを1、ソレ以外を0とする、one-hot表現
  • Python
    • 実装
      """This is a test program."""
      
      import numpy as np
      
      def mean_squared_error(yk, tk):
          """損失関数(2乗和誤差)"""
          return 0.5 * np.sum((yk - tk)**2)
      
      tk = np.array([0, 0, 1, 0, 0, 0, 0, 0, 0, 0])
      yk = np.array([0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0])
      print(mean_squared_error(yk, tk))
      yk = np.array([0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0])
      print(mean_squared_error(yk, tk))
  • 出力
    正解(tk)に対応する確率(yk)が高ければ高いほど、1に近いデータになる。
    • tkで2が正解の場合、ykで2の確率が一番高いとしたデータの場合のE。
      0.0975
    • tkで2が正解の場合、ykで7の確率が一番高いとしたデータの場合のE。
      0.5975
  • 前者の損失関数(2乗和誤差)の出力Eの方が大きく
    前者のykがより適合していることを示している。

交差エントロピー誤差

  • 正解ラベルのykデータの底がeの自然対数 log eを計算する。
  • y = -log xでは、x=0-1の場合、xが0に近づくほど、yは大きな値になる。
  • E = - Σ tk log yk
           k
  • 説明
    • log:logは底がeの自然対数 log e
    • k:データの次元数
    • yk:ニューラルネットワークの出力
    • tk:教師データ
  • Python
    • 実装
      """This is a test program."""
      
      import numpy as np
      
      def cross_entropy_error(yk, tk):
          """損失関数(交差エントロピー誤差)"""
          delta = 1e-7 # log(0)はマイナス∞になるのを微小な値を足して防止。
          return -np.sum(tk * np.log(yk + delta))
      
      tk = np.array([0, 0, 1, 0, 0, 0, 0, 0, 0, 0])
      yk = np.array([0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0])
      print(cross_entropy_error(yk, tk))
      yk = np.array([0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0])
      print(cross_entropy_error(yk, tk))
  • 出力
    正解(tk)に対応する確率(yk)が低ければ低いほど、大きいデータになる。
  • tkで2が正解の場合、ykで2の確率が一番高いとしたデータの場合のE。
    0.510825457099
  • tkで2が正解の場合、ykで7の確率が一番高いとしたデータの場合のE。
    2.30258409299
  • 前者の損失関数(交差エントロピー誤差)の出力Eの方が小さく
    前者のykがより適合していることを示している。

ミニバッチ学習

  • ミニバッチ学習では、上記の損失関数を訓練用データセットに対して適用する。
  • ここでは、訓練用データセットに対する損失関数の総和を指標とする。
  • E = -1/N ΣΣ tnk log ynk
              n k
  • 説明
    • 交差エントロピー誤差の式をN個のデータを含む訓練用データセット用に拡張する。
    • 最後に、Nで割って正規化する(データ1個あたりの平均の損失関数を求める)。
  • Python
  • 実装
  • one-hot表現の場合
    """This is a test program."""
    
    import numpy as np
    
    def mean_squared_error(ynk, tnk):
        """損失関数(交差エントロピー誤差)"""
        print("tnk:" + str(tnk))
        print("ynk:" + str(ynk))
    
        batch_size = ynk.shape[0]
        print("batch_size:" + str(batch_size))
        delta = 1e-7 # log(0)はマイナス∞になるのを微小な値を足して防止。
        return - 1 / batch_size * (np.sum(tnk * np.log(ynk + delta)))
    
    TNK = np.array([[0, 0, 1, 0, 0, 0, 0, 0, 0, 0], \
        [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]])
    YNK = np.array([[0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0], \
        [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]])
    print("mean_squared_error:" + str(mean_squared_error(YNK, TNK)))
    YNK = np.array([[0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0], \
        [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]])
    print("mean_squared_error:" + str(mean_squared_error(YNK, TNK)))
  • one-hot表現でない場合
    """This is a test program."""
    
    import numpy as np
    
    def mean_squared_error(ynk, tnk):
        """損失関数(交差エントロピー誤差)"""
        print("tnk:" + str(tnk))
        print("ynk:" + str(ynk))
    
        batch_size = ynk.shape[0]
        print("batch_size:" + str(batch_size))
    
        delta = 1e-7 # log(0)はマイナス∞になるのを微小な値を足して防止。
        ynk = ynk + delta
         
        print("arange:" + str(ynk[np.arange(batch_size), tnk]))
        return - 1 / batch_size * (np.sum(np.log(ynk[np.arange(batch_size), tnk])))
    
    TNK = np.array([2, 2])
    YNK = np.array([[0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0], \
        [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]])
    print("mean_squared_error:" + str(mean_squared_error(YNK, TNK)))
    YNK = np.array([[0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0], \
        [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]])
    print("mean_squared_error:" + str(mean_squared_error(YNK, TNK)))

勾配法

勾配法では、(パラメタの微分を計算して得た)勾配の情報を使って進む方向を決める。

微分

ある瞬間の変化の量(=グラフの接線の傾き的な)。

df(x)  yの増量        f(x+h) - f(x)        f(x+h) - f(x)
── = ───  = lim  ──────  = lim  ──────
 dx    xの増量   h→0 (x+h) - (x)     h→0      h

解析的

式の展開によって微分を求める(誤差がない)。

     2
y = x
df(x)  yの増量        (x+h)^2 - x^2        (x^2+2hx+h^2) - (x^2)
── = ───  = lim  ──────  = lim  ──────────
 dx    xの増量   h→0 (x+h) - (x)     h→0           h
 dy         2hx+h^2
── = lim ──── = lim 2x+h  = 2x
 dx    h→0    h      h→0

数値微分

計算によって微分を求める(誤差がある)。

  • Python
  • 実装
    """This is a test program."""
    
    import numpy as np
    import matplotlib.pyplot as plt
    
    def numerical_diff(f, x):
        """数値微分"""
        h = 1e-4 # 微小な値hとして1の-4乗を用いる
        return (f(x + h) - f(x - h)) / (2 * h) # 前方差分から中心差分にして誤差減
    
    def function_1(x):
        """f(x)=0.01x^2+0.1x"""
        return 0.01 * x ** 2 + 0.1 * x
    
    X=5
    print("X=" + str(X) + " : " + str(numerical_diff(function_1, X)))
    X=10
    print("X=" + str(X) + " : " + str(numerical_diff(function_1, X)))
    
    X = np.arange(0.0, 20.0, 0.1)
    Y = function_1(X)
    plt.xlabel("x")
    plt.ylabel("f(x)")
    plt.plot(X, Y)
    plt.show()
  • 出力
    • グラフ
      グラフ
  • 傾き
    X=5 : 0.1999999999990898
    X=10 : 0.2999999999986347

偏微分

  • 例1:2つの引数の2乗和を計算する式
    •               2    2
      f(x0, x1) = x0 + x1
  • Python
    • 実装
      """This is a test program."""
      
      import numpy as np
      
      def function_2(x):
          """f(x0, x1) = x0^2 + x1^2"""
          return x[0] ** 2 + x[1] ** 2
          # or return np.sum(x ** 2)
  • 例2:2つの引数の2乗和を計算する式の偏微分
    •  df(x0, x1)
      ─────  = 2 * x0
          dx0
      
       df(x0, x1)
      ─────  = 2 * x1
          dx1
  • Python
    • 実装
      numerical_diff"""This is a test program."""
      
      import numpy as np
      
      def numerical_diff(f, x):
          """数値微分"""
          h = 1e-4 # 微小な値hとして1の-4乗を用いる
          return (f(x + h) - f(x - h)) / (2 * h) # 前方差分から中心差分にして誤差減
      
      def function_tmp1(x0):
          """x0=3, x1=4 の場合の x0 に対する偏微分用"""
          return x0 ** 2 + 4.0 ** 2
      
      def function_tmp2(x1):
          """x0=3, x1=4 の場合の x1 に対する偏微分用"""
          return 3.0 ** 2.0 + x1 ** 2
      
      print(numerical_diff(function_tmp1, 3.0))
      print(numerical_diff(function_tmp2, 4.0))
  • 出力 (x0=3, x1=4)
    6.00000000000378   (2 * x0 = 2 * 3 = 6)
    7.999999999999119   (2 * x1 = 2 * 4 = 8)

勾配

勾配の示す方向は、各場所で関数の値を最も減らす方向。

  •  df(x0, x1)    df(x0, x1)
    ─────   , ─────
        dx0           dx1
  • 説明
    • すべての変数の偏微分をベクトルとしてまとめたものを勾配と呼ぶ。
    • 上記の例なら、x0=3, x1=4の場合、勾配は、(6, 8)となる。
  • Python
    • 実装
      """This is a test program."""
      
      import numpy as np
      
      def numerical_gradient(f, x01):
          """偏微分"""
          h = 1e-4 # 微小な値hとして1の-4乗を用いる
      
          grad = np.zeros_like(x01) # x01と同じ形状で要素が0。
      
          for idx in range(x01.size):
              tmp_val = x01[idx]
              # 前方差分から中心差分にして誤差減
              # f(x + h)
              fxh1 = f(tmp_val + h)
              # f(x - h)
              fxh2 = f(tmp_val - h)
              # (f(x + h) - f(x - h)) / 2 * h
              grad[idx] = (fxh1 - fxh2) / (2 * h)
      
          return grad
      
      def function_2(x):
          return np.sum(x**2)
      
      print(numerical_gradient(function_2, np.array([3.0, 4.0])))
      print(numerical_gradient(function_2, np.array([0.0, 2.0])))
      print(numerical_gradient(function_2, np.array([3.0, 0.0])))
  • 出力
    [ 6.  8.]
    [ 0.  4.]
    [ 6.  0.]
  • 参考
    https://github.com/oreilly-japan/deep-learning-from-scratch/blob/master/ch04/gradient_2d.py
    • x = -2.0 - 2.5, y = -2.0 - 2.5 の範囲の0.25刻みのメッシュグリッドを生成
    • メッシュグリッドはm行n列の配列なので、これをflatten()メソッドで m * n にベクトル化。
    • np.array([X, Y])で x0, x1 の 2 行 m * n 列の配列にする。
    • バッチ関数ではforで 1 行つづ取り出し、m * n 列のベクトルとして処理する。
    • 各場所(x0, x1)での、勾配をplt.quiver使用してベクトル(矢印)として描画する。
      偏微分

勾配法

  • 勾配法では、広大なパラメタ空間から、複雑な損失関数が、
    最小(最大)値を出力する鞍点(saddle point)を、勾配を使用して探す。
    • 勾配降下法 : 最小値を探す。
    • 勾配上昇法 : 最大値を探す。
  • 注意点
    • 勾配の指す方向に最小(最大)値があることは保証されない。
    • 複雑な関数の場合は、勾配の指す方向に最小(最大)値が無い可能性が高い。
  •              df(x0, x1)
    x0 = x0 - η ─────
                    dx0
    
                  df(x0, x1)
    x1 = x1 - η  ─────
                    dx1
    • 説明
      • 上記は、一回の更新式で、勾配法では、このステップを繰り返す。
      • ηは学習率で、一回の学習でどれだけ学習すべきか?=どれだけパラメタ更新するか?
      • 学習率は、0.01、0.001など前もって値を決める、
        それから正しく学習できているか確認しながら調整する。
  • Python
    以下の式の最小値を勾配法で求める。
                  2    2
    f(x0, x1) = x0 + x1
  • 実装
    import numpy as np
    
    def numerical_gradient(f, x01):
        """偏微分"""
        h = 1e-4 # 微小な値hとして1の-4乗を用いる
    
        grad = np.zeros_like(x01) # x01と同じ形状で要素が0。
        # print("x01:" + str(x01));
        for idx in range(x01.size):
            tmp_val = x01[idx]
            # 前方差分から中心差分にして誤差減
            # f(x + h)
            fxh1 = f(tmp_val + h)
            # f(x - h)
            fxh2 = f(tmp_val - h)
            # (f(x + h) - f(x - h)) / 2 * h
            grad[idx] = (fxh1 - fxh2) / (2 * h)
    
        return grad
    
    def gradient_descent(f, init_x01, lr, step_num):
        print("ln : step_num = " + str(lr) + " : " + str(step_num))
        x01 = init_x01
        for i in range(step_num):
            grad = numerical_gradient(f, x01)
            x01 -= lr * grad
        
        return x01
    
    def function_2(x):
        return np.sum(x**2)
    
    init_x = np.array([-3.0, 4.0])
    print(gradient_descent(function_2, init_x, 0.1, 100))
    
    # 学習率が大きすぎる。
    init_x = np.array([-3.0, 4.0])
    print(gradient_descent(function_2, init_x, 10.0, 100))
    # 学習率が小さすぎる。
    init_x = np.array([-3.0, 4.0])
    print(gradient_descent(function_2, init_x, 1e-10, 100))
  • 出力
    ln : step_num = 0.1 : 100
    [ -6.11110793e-10   8.14814391e-10]
    ln : step_num = 10.0 : 100
    [ -1.91613251e+13  -1.26893162e+12]
    ln : step_num = 1e-10 : 100
    [-2.99999994  3.99999992]

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

ニューラルネットワークの学習における勾配は、
重みパラメタに関する損失関数勾配となる。

  •     ┌ w11 w21 vw31 ┐
    W = │              │
        └ w12 w22 vw32 ┘
    
          ┌  dL    dL    dL  ┐
          │ ──  ──  ── │
     dL   │ dw11  dw21  dw31 │
    ── =│                  │
     dW   │  dL    dL    dL  │
          │ ──  ──  ── │
          └ dw12  dw22  dw32 ┘
  • Python
  • 実行
    フォルダ構成を維持した状態でch04に定義した以下のファイルを実行。
    C:\deep-learning-from-scratch-master\ch04>python Untitled-1.py
  • simpleNetを使って推論/学習
    • 実装
      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
      from gradient_simplenet import simpleNet
      
      print("==================================================")
      print("==================================================")
      
      net = simpleNet()
      print("W:" + str(net.W))
      
      x = np.array([0.6, 0.9])
      p = net.predict(x)
      print("p:" + str(p))
      
      t = np.array([0, 0, 1])
      l = net.loss(x, t)
      print("loss:" + str(l))
  • 出力
    W:[[ 1.92087598  0.63971089 -0.26820797]
     [ 0.58411529 -0.04610929 -0.88999594]]
    p:[ 1.67822935  0.34232817 -0.96192113]
    loss:2.92853604814
  • simpleNetを使って勾配を求める
    • 実装
      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
      from gradient_simplenet import simpleNet
      
      print("==================================================")
      print("==================================================")
      
      net = simpleNet()
      print("W:" + str(net.W))
      
      x = np.array([0.6, 0.9])
      t = np.array([0, 0, 1])
      
      f = lambda w: net.loss(x, t)
      dW = numerical_gradient(f, net.W)
      print("dW:" + str(dW))
      
    • 出力
      ==================================================
      ==================================================
      W:[[ 1.83160192  0.4900981  -0.94188042]
       [-0.24946104  2.91410946 -0.00695892]]
      dW:[[ 0.06708443  0.51711391 -0.58419835]
       [ 0.10062665  0.77567087 -0.87629752]]
  • Wは、
    W :     [[ w11 = 1.83160192  w21 = 0.4900981  w31 = -0.94188042]
             [ w12 = -0.24946104 w22 = 2.91410946 w32 = -0.00695892]]
    dL/dW : [[ dL/dw11 = 0.06708443 dL/dw21 = 0.51711391 dL/dw31 = -0.58419835]
             [ dL/dw12 = 0.10062665 dL/dw22 = 0.77567087 dL/dw32 = -0.87629752]]
  • w11を h 増やすと、0.06708443 h 増加する。
  • w12を h 増やすと、0.10062665 h 増加する。
  • w21を h 増やすと、0.51711391 h 増加する。
  • w22を h 増やすと、0.77567087 h 増加する。
  • w31を h 増やすと、-0.58419835 h 増加する( = 減少する)。
  • w32を h 増やすと、-0.87629752 h 増加する( = 減少する)。
  • 勾配がプラスならhをマイナス方向に、マイナスならプラス方向に動かす。

学習アルゴリズムの実装

  • 要素
    • 損失関数
    • ミニバッチ
    • 勾配
    • 勾配降下法

手順

前提

  • ニューラルネットワークには適応可能な重みとバイアスがある。
  • 学習により、この重みとバイアスを訓練データに適応するように調整する。
  • ニューラルネットワークの学習は、以下の4つのステップで行われる。

ステップ 1

  • 訓練データから、ランダムに1つのデータを選択する。
    ランダムに選択する場合、確率的勾配下降法(SGD)と呼ぶ。
  • この選択した訓練データをミニバッチと言う。
  • ここでは、損失関数の値を減らすことを目的とする。

ステップ 2

  • ミニバッチの損失関数を減らすために、各重みパラメタの勾配を求める。
  • 勾配は、損失関数の値を最も減らす方向を示す。

ステップ 3

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

ステップ 4

ステップ 1, ステップ 2, ステップ 3を繰り返す。

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

TwoLayerNet?クラス
https://github.com/oreilly-japan/deep-learning-from-scratch/blob/master/ch04/two_layer_net.py

変数

#変数説明
1paramsニューラルネットワークの重みパラメタのディクショナリ変数
1-1params['W1']第1層の重み
1-2params['b1']第1層のバイアス
1-3params['W2']第2層の重み
1-4params['b2']第2層のバイアス
2gradsnumerical_gradientで計算された勾配を保持するディクショナリ変数
1-1params['W1']第1層の重みの勾配
1-2params['b1']第1層のバイアスの勾配
1-3params['W2']第2層の重みの勾配
1-4params['b2']第2層のバイアスの勾配

メソッド

#メソッド シグネチャ引数説明
1__init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):コンストラクタ
1-1selfインスタンス
1-2input_size入力層のニューロンの数
1-3hidden_size隠れニューロンの数
1-4output_size出力層のニューロンの数
1-5weight_init_std・・・
2predict(self, x):推論を行う
2-1selfインスタンス
2-2x画像データ
3loss(self, x, t):損失関数の値を求める
3-1selfインスタンス
3-2x画像データ
3-3t正解ラベル
4accuracy(self, x, t):推論の精度を求める
4-1selfインスタンス
4-2x画像データ
4-3t正解ラベル
5numerical_gradient(self, x, t):lossを使用し各重みパラメタの勾配を求める
5-1selfインスタンス
5-2x画像データ
5-3t正解ラベル
6gradient(self, x, t):numerical_gradientの高速版
6-1selfインスタンス
6-2x画像データ
6-3t正解ラベル

学習過程の実装

勾配法により(損失)関数を少なくしていく。


  • コチラと、コチラを参考に、以下のようになる。
    • 第1層 (100個のバッチ)
      • x(1) =
        (100,     784 = 28 * 28 pixel)
  • 重みパラメタ
    • W(1) =
      (784,     x = 100)
    • b(1) =
      (1,       x = 100)
  • 隠れ層 (x = 100)
    • A(1) =
      (100,     x = 100)
    • = x(2) =
      (100,     x = 100) 
  • 重みパラメタ
    • W(2) =
      (x = 100, 10)
    • b(2) =
      (1,       10)
  • 第2層
    • A(2) =
      (100,     10) # 0-9の数字
  • 実装
    C:\deep-learning-from-scratch-master\ch04\train_neuralnetを以下のように編集
    # coding: utf-8
    import sys, os
    sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
    import numpy as np
    import matplotlib.pyplot as plt
    from dataset.mnist import load_mnist
    from two_layer_net import TwoLayerNet
    
    # データの読み込み
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
    
    network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
    
    iters_num = 10000  # 繰り返しの回数を適宜設定する
    train_size = x_train.shape[0]
    batch_size = 100
    learning_rate = 0.1
    
    train_loss_list = []
    
    for i in range(iters_num):
        print(str(i) + " / " + str(iters_num))
        batch_mask = np.random.choice(train_size, batch_size)
        x_batch = x_train[batch_mask]
        t_batch = t_train[batch_mask]
        
        # 勾配の計算
        #grad = network.numerical_gradient(x_batch, t_batch)
        grad = network.gradient(x_batch, t_batch)
        
        # パラメータの更新
        for key in ('W1', 'b1', 'W2', 'b2'):
            network.params[key] -= learning_rate * grad[key]
        
        loss = network.loss(x_batch, t_batch)
        train_loss_list.append(loss)
    
    plt.xlabel("Iteration")
    plt.ylabel("loss")
    plt.plot(range(iters_num), train_loss_list)
    plt.show()
  • 実行
    フォルダ構成を維持した状態でch04に定義した上記ファイルを実行。
    C:\deep-learning-from-scratch-master\ch04>python train_neuralnet
  • 出力
    • CMD
      0 / 10000
      ...
      9999 / 10000
  • グラフ
    学習結果

学習結果を確認する実装

学習結果を使用して、学習データとテストデータを推論する。

  • 実装
    C:\deep-learning-from-scratch-master\ch04\train_neuralnetのオリジナルを実行
  • 実行
    フォルダ構成を維持した状態でch04に定義した上記ファイルを実行。
    C:\deep-learning-from-scratch-master\ch04>python train_neuralnet
  • 出力
    1バッチ・サイクル毎に学習した重みパラメタを使用した推論結果が表示される。
  • CMD
    train acc, test acc | 0.102183333333, 0.101
    train acc, test acc | 0.783416666667, 0.7894
    train acc, test acc | 0.874916666667, 0.8791
    train acc, test acc | 0.8964, 0.8991
    train acc, test acc | 0.907433333333, 0.9092
    train acc, test acc | 0.913616666667, 0.9147
    train acc, test acc | 0.9184, 0.9185
    train acc, test acc | 0.923366666667, 0.9238
    train acc, test acc | 0.926316666667, 0.9275
    train acc, test acc | 0.9294, 0.9298
    train acc, test acc | 0.932666666667, 0.9318
    train acc, test acc | 0.9341, 0.9341
    train acc, test acc | 0.936816666667, 0.9367
    train acc, test acc | 0.940133333333, 0.9382
    train acc, test acc | 0.94175, 0.9397
    train acc, test acc | 0.943566666667, 0.9417
    train acc, test acc | 0.945233333333, 0.9435
  • グラフ
    学習後の推論結果

ハイパーパラメータ

人間が手動で設定するパラメタ

  • 確率的勾配下降法(SGD)の繰り返し回数
    iters_num = 10000
  • 1回のミニバッチのサイズ
    batch_size = 100
  • 学習率
    learning_rate = 0.1

深層学習の高速化

深層学習のテクニック


添付ファイル: fileaccuracy.png 104件 [詳細] filelearning.png 135件 [詳細] filegradient_1d.png 113件 [詳細] filegradient_2d.png 96件 [詳細] filegraf.png 136件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2017-07-28 (金) 23:41:47 (781d)