技術っぽいことを書いてみるブログ

PythonとかVue.jsとか技術的なことについて書いていきます。

ニューラルネットワークの学習について(勾配法編)

はじめに

前回は、関数の勾配を求めるところまで記載したので、
今回は勾配法について記載します。
勾配とは、「関数の値を最も減らす方向」でしたが、
勾配法を使用し、関数の値を勾配の方向に一定量だけ値を減らし、
減らした場所で、また勾配を求め、一定量だけ値を減らしていき、
これを繰り返し、最小値を探していきます。

勾配法の式

勾配法は、次の式で表されます。
X1・X2と変数がある場合、
X1=X1ー[学習率]×勾配
X2=X2ー[学習率]×勾配
となります。
つまり、取得した勾配の逆方向に学習率分だけX1・X2を更新する処理となります。
ここで学習率とは、1回の学習でどれだけ更新するかの指標です。

勾配法の実装

実装は、結構簡単でした。

import numpy as np

# 勾配を求める
def numrerical_gradient(f, x):
    h = 1e-4
    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 gradient_descent(f, init_x, learning_rate=0.01, count=100):
    x = init_x

    for i in range(count):
        grad = numrerical_gradient(f, x)
        x = x - (learning_rate * grad)
        print(x)

    return x

# 関数
def function2(x) :
    return x[0] ** 2 + x[1] ** 2

#X1=3.0、X2=4.0、学習率0.1で、10回繰り返して、最終的な勾配を求める
gd = gradient_descent(function2, init_x = np.array([3.0, 4.0]), learning_rate = 0.1, count = 10)

実行結果

[2.4 3.2]
[1.92 2.56]
[1.536 2.048]
[1.2288 1.6384]
[0.98304 1.31072]
[0.786432 1.048576]
[0.6291456 0.8388608]
[0.50331648 0.67108864]
[0.40265318 0.53687091]
[0.32212255 0.42949673]

徐々に[0, 0]に近づいています。

最後に・・・

次回は、この勾配法を用いて、
ニューラルネットワークの重みパラメータを更新し、
より教師データに近づいていく、重みパラメータを得る処理を実装してみます。

お読みいただき、ありがとうございました!