「Deep Learning」って何? 復習します! 勾配!
ネットワークができました!このネットワークをうまく動かす 、「重み」パラメータを更新して良い結果となるように調整していかなければなりません。「学習」です。
必要なもの、
損失関数・・・ 入力値"y"と教師データ(正解ラベル)"t"と比較します。
def cross_entropy_error(y, t) :
delta = 1e-7
return -np.sum(t*np.log(y+delta))
微分・・・ 偏微分を使って、勾配を求めます。
def numerical_gradient(f, x):
h = 1e-4 # 0.0001
grad = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = it.multi_index
tmp_val = x[idx]
x[idx] = float(tmp_val) + h
fxh1 = f(x) # f(x+h)
x[idx] = tmp_val - h
fxh2 = f(x) # f(x-h)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val # 値を元に戻す
it.iternext()
return grad
今回は"np.nditer"を使ってます。
出力層の関数 ・・・ソフトマックス関数。(出力の総和は"1")
def softmax(a) :
c = np.max(a)
exp_a = np.exp(a - c)
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a
return y
これらを使って簡単なネットワークを作ったものが以下です。
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
def __init__(self):
self.W = np.random.randn(2,3)
では重みをランダムに作っておきます。
def predict(self, x):
return np.dot(x, self.W)
ネットワークの計算。この値を変数"x"に入れます。
def loss(self, x, t):
z = self.predict(x)
y = softmax(z)
loss = cross_entropy_error(y, t)
return loss
で損失関数でその差を求めます。この差はなるべき”0”に近くなるようにする。
実際に計算してみます。
x = np.array([0.6, 0.9])
t = np.array([0, 0, 1])
net = simpleNet()
f = lambda w: net.loss(x, t)
dW = numerical_gradient(f, net.W)
print(dW)
[[ 0.41293446 0.0412291 -0.45416356]
[ 0.61940169 0.06184365 -0.68124534]]
と勾配が算出できました。
それぞれの損失関数の値が算出できます。例えば、 勾配の値が0.41293446(0.4とします)はhだけ増やすと損失関数の値が0.4hだけ増えるということを示しています。この場合は更新する場合はマイナス方向へパラメータの値を更新すべき("0"に近づける)ことがわかります。
勾配が求まれば、次は勾配法を使って「重み」をパラメータの更新できます。
この記事が気に入ったらサポートをしてみませんか?