「.NET 開発基盤部会 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
ニューラルネットワークにおいては、特徴量を機械が選択し重みを学習(自動獲得)する。
学習フェーズでは、信号は逆方向に伝播する。
人間が(暗黙的な学習によって、)これらを判別することはできる。
従って、人間の脳も、一部は、このようなデータ駆動で動いているのかもしれない。
回帰の場合(ニューラルネットワークの出力と正解となる教師データの各要素の差の二乗の総和の2分の一。
2
E = 1/2 Σ (yk-tk)
k"""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))0.0975
0.5975
多値分類(正解ラベルのykデータの底がeの自然対数 log eを計算する。
E = - Σ tk log yk
k"""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))0.510825457099
2.30258409299
微分(偏微分)で求めた勾配の示す方向は、
各場所で関数の値を最も減らす方向(である可能性が高い)。
df(x0, x1) df(x0, x1)
───── , ─────
dx0 dx1"""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.]
df(x0, x1)
x0 = x0 - η ─────
dx0
df(x0, x1)
x1 = x1 - η ─────
dx1
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 ┘predict ---> softmax ---> cross_entropy_error
- predict(推論する)
- softmax(Softmax関数)
- cross_entropy_error(交差エントロピー誤差)
C:\deep-learning-from-scratch-master\ch04>python Untitled-1.py
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
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 : [[ 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]]| バッチ学習(一括学習) | ミニバッチ学習 | オンライン学習(逐次学習) | |
| 効率 | ✕ | ○ | ◎ |
| 安定性 | ◎ | ○ | ✕ |
E = -1/N ΣΣ tnk log ynk
n k"""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)))"""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)))重みパラメタを勾配の方向に微小量だけ更新する。
TwoLayerNet?クラス
https://github.com/oreilly-japan/deep-learning-from-scratch/blob/master/ch04/two_layer_net.py
| # | 変数 | 説明 | |
| 1 | params | ニューラルネットワークの重みパラメタのディクショナリ変数 | |
| 1-1 | params['W1'] | 第1層の重み | |
| 1-2 | params['b1'] | 第1層のバイアス | |
| 1-3 | params['W2'] | 第2層の重み | |
| 1-4 | params['b2'] | 第2層のバイアス | |
| 2 | grads | numerical_gradientで計算された勾配を保持するディクショナリ変数 | |
| 1-1 | params['W1'] | 第1層の重みの勾配 | |
| 1-2 | params['b1'] | 第1層のバイアスの勾配 | |
| 1-3 | params['W2'] | 第2層の重みの勾配 | |
| 1-4 | params['b2'] | 第2層のバイアスの勾配 | |
| # | メソッド シグネチャ | 引数 | 説明 |
| 1 | __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01): | コンストラクタ | |
| 1-1 | self | インスタンス | |
| 1-2 | input_size | 入力層のニューロンの数 | |
| 1-3 | hidden_size | 隠れニューロンの数 | |
| 1-4 | output_size | 出力層のニューロンの数 | |
| 1-5 | weight_init_std | ・・・ | |
| 2 | predict(self, x): | 推論を行う | |
| 2-1 | self | インスタンス | |
| 2-2 | x | 画像データ | |
| 3 | loss(self, x, t): | 損失関数の値を求める | |
| 3-1 | self | インスタンス | |
| 3-2 | x | 画像データ | |
| 3-3 | t | 正解ラベル | |
| 4 | accuracy(self, x, t): | 推論の精度を求める | |
| 4-1 | self | インスタンス | |
| 4-2 | x | 画像データ | |
| 4-3 | t | 正解ラベル | |
| 5 | numerical_gradient(self, x, t): | lossを使用し各重みパラメタの勾配を求める | |
| 5-1 | self | インスタンス | |
| 5-2 | x | 画像データ | |
| 5-3 | t | 正解ラベル | |
| 6 | gradient(self, x, t): | numerical_gradientの高速版 | |
| 6-1 | self | インスタンス | |
| 6-2 | x | 画像データ | |
| 6-3 | t | 正解ラベル | |
(784, x = 100)
(1, x = 100)
(100, x = 100)
(100, x = 100)
(x = 100, 10)
(1, 10)
(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()C:\deep-learning-from-scratch-master\ch04>python train_neuralnet
0 / 10000 ... 9999 / 10000
学習結果を使用して、学習データとテストデータを推論する。
C:\deep-learning-from-scratch-master\ch04\train_neuralnetのオリジナルを実行
C:\deep-learning-from-scratch-master\ch04>python train_neuralnet
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
人間が手動で設定するパラメタ
iters_num = 10000
batch_size = 100
learning_rate = 0.1