はじめに・・・
今回は、勾配について記述します。
機械学習では、ニューラルネットワーク内の最適な重みを得ることで、精度をあげる必要があります。
その精度を図るための指標となるのが、前回記述した「損失関数」です。
精度を上げるために、この損失関数の値を減らすことが必要になってきます。
勾配を求めることで、損失関数の値を減らす指標を得ることができます。
数値微分
勾配を求める前に、まずは数値微分について記載します。
微分の公式は、次のように表します。
ただし、プログラム上では誤差を考慮し、
で実装します。
# 数値微分を求める def numeric_diff(f, x): h = 1e-4 return (f(x+h) - f(x-h)) / (2 * h) # 関数を3x**2+10x+5とする def function1(x): return 3 * x ** 2 + 10 * x + 5 # xが5の時の微分を算出 nd = numeric_diff(function1, 5) print(nd) # xが10の時の微分を算出 nd = numeric_diff(function1, 10) print(nd)
実行結果
39.99999999990678 70.00000000005002
勾配
数値微分では、関数の引数は一つの値でしたが、
損失関数を求める場合、複数の引数を対象に処理する必要があります。
そこで、関数をX12+X22とし、
複数の引数は、numpyの配列で受け取るようにして、微分を算出します。
import numpy as np # 勾配を求める def numrerical_gradient(f, x): h = 1e-4 # xと同じ要素数で値が0のnumpy配列を用意する gradient = np.zeros_like(x) for index in range(x.size): #片方の値はそのままで、一方の値の微分を求めます。 temp_val = x[index] x[index] = temp_val + h f1 = f(x) x[index] = temp_val - h f2 = f(x) gradient[index] = (f1 - f2) / (2 * h) # 次のループのために値を戻す x[index] = temp_val return gradient # 関数 def function2(x) : return x[0] ** 2 + x[1] ** 2 ng = numrerical_gradient(function2, np.array([3.0, 4.0])) print(ng) ng = numrerical_gradient(function2, np.array([3.0, 0.0])) print(ng) ng = numrerical_gradient(function2, np.array([0.0, 4.0])) print(ng)
実行結果
[6. 8.] [6. 0.] [0. 8.]
実行結果を基に簡単に解説すると、
実行結果[6.0, 8.0]の「6.0」は、X1=3.0、X2=4.0のときのX1に対する微分であり、
実行結果[6.0, 8.0]の「8.0」は、X1=3.0、X2=4.0のときのX2に対する微分となります。
で、この勾配[6.0, 8.0]にマイナスをつけたものが、関数の値を最も減らす方向(ベクトル)となります。
つまり、この求められた勾配を基に機械学習の重みパラメータを更新することで、損失関数の値を減らしていくことができるということです。
最後に・・・
次回は、勾配法により重みパラメータを更新する処理を記載したいと思います。
ディープラーニングの勉強としては、まだまだ序盤ですが、微分やら勾配やらの計算がイロイロ登場します。
現時点では、ディープラーニングのフレームワークは用いていないのですが、
将来的な勉強の対象としてフレームワークも見ていきたいと考えております。
フレームワークを使うことで、どのような事が便利になのかもブログに書いていきたいと思います。
お読みいただき、ありがとうございました!