Deep Learning 考え方まとめ。
イメージを膨らませていきたいと思います。
"ゼロから作る Deep Learning"のコードを参考に考えていきます。
まず、必要なものとしてはネットワーク。単純化して
"重みの決定(初期化)"、"推論"、"検証(損失関数)
とします。
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
このネットワークでは初期の重み"W"を使って入力値"x"を受けて推論predict()します。
入力して推論して結果をだすという部分ではこれで終了です。
Deep Learningなので、この推論したものが正しいのか検証して、もし正解と違いがあれば修正していくという操作が必要です。その部分を"loss()"としています。
実際の推論値"pd"は以下で求められます。
x = np.array([0.6, 0.9]) // 入力値
net = simpleNet()
pd = net.predict(x) // 推論結果
mIndex = argmax(pd) // 最大値のインデックス
推論値"pd"は出ました。配列で出力の場合は一番可能性のある最大のインデックス"mIndex"を推論の回答とします。
学習済みのネットワークではここで終わり、実際に使う場合はこの"pd"が結果となります。推論で結果が出ました。
ここで切り分けます。
以下は推論値の精度を上げるために行うものです。この部分がDeep Learningのキモとなる部分ですが実際に使う場合は気にしない部分です。ここを切り分けて考えておかないとなんだか自分としては理解が進まない気がします。
正解の値と比べてどれくらい違うかを損失関数として出します。
f = lambda w: net.loss(x, t)
損失関数を使ってこの部分(重み)の勾配を求めます。
重みがどれくらい"正解の値を出せる重み"から離れているかを調べます。
dW = numerical_gradient(f, net.W)
"dw"は重みをどの方向にどれくらいずらして行けば正解を導ける数値となるかを示しています。
"dw"の数値を参考に重みを更新していき精度を上げていきます。それを学習と呼びます。例えば以下。
def gradient_descent(f, init_x, lr=0.01, step_num=100):
x = init_x
for i in range(step_num):
grad = numerical_gradient(f, x)
x -= lr * grad
return x
初期値"x"を"step_num"回損失関数"f"に関して勾配"numerical_gradient(f, x)"を求めて"0"に近づけていきます。
この"x"が重みになれば学習となり重み、パラメータの更新、最適化につながります。
学習の実装としては
for i in range(step_num):
grad = network.numerical_gradient(x, t)
# パラメータの更新
for key in ('W1', 'b1', 'W2', 'b2'):
network.W[key] -= 0.1 * grad[key]
こんな感じになると思います。
学習では正しい結果になるようにパラメータの更新をしていくこと求められています。
重要な点としては、損失関数の勾配を求めることで正しいパラメータの方向性を決めて、更新していくということです。
この記事が気に入ったらサポートをしてみませんか?