u++の備忘録

Pythonによる勾配降下法の実装

勾配降下法

 目的関数{J}の1次微分を求めて、勾配の逆方向にパラメータ{\omega}を逐次的に更新していく手法。

数式表現

{\omega^{(m+1)}\gets\omega^{(m)}}-\eta\nabla_\omega J(\omega^{(m)})

実装

条件

 目的関数は{J(x)=x*(x-4)+5}に設定。明らかに{x=2}で最小となる。
f:id:upura:20170705111311p:plain

コード
import numpy as np
import matplotlib.pyplot as plt

def J(x):
    return x*(x-4)+5

def diffJ(x):
    h = 1e-4
    return (J(x+h) - J(x)) / h

n = 100
x = np.linspace(0, 5, n)
np.random.seed(seed = 32)
stack = [] # プロット用のリスト

'''
# Graph
plt.xlim(-1, 6)
plt.ylim(-1, 8)
plt.xlabel(r"$\omega$")
plt.ylabel(r"$J(\omega)$")
plt.plot(x, J(x), "b")
plt.show()
'''

# 初期値
omega = np.random.rand()*5
# ステップ幅
eta = 0.01

for i in range(100000):
    # プロット用のリスト
    stack.append(omega)
    # パラメータ更新
    omega = omega-eta*diffJ(omega)
    # 収束判定
    if eta*diffJ(omega)<=0.0001:
        break

# 結果表示
plt.xlabel(r"number of steps")
plt.ylabel(r"$\omega$")
plt.plot(stack, "r")
plt.show()
出力

 {x=2}辺りに収束していると分かる。
f:id:upura:20170705111346p:plain