2016-12-17 3 views
0

私は非常に素朴な勾配descentをPythonで実装しようとしています。しかし、それは無限ループになるようです。私はそれをデバッグするのを助けてくれますか?Pythonで素朴なグラデーションディセントを実装する

y = lambda x : x**2 
dy_dx = lambda x : 2*x 
def gradient_descent(function,derivative,initial_guess): 
    optimum = initial_guess 
    while derivative(optimum) != 0: 
     optimum = optimum - derivative(optimum) 
    else: 
     return optimum 
gradient_descent(y,dy_dx,5) 

編集:

今、私はこのコードを持って、私は本当に出力を理解することはできません。 P.S. CPUがフリーズすることがあります。

y = lambda x : x**2 
dy_dx = lambda x : 2*x 
def gradient_descent(function,derivative,initial_guess): 
    optimum = initial_guess 
    while abs(derivative(optimum)) > 0.01: 
     optimum = optimum - 2*derivative(optimum) 
     print((optimum,derivative(optimum))) 
    else: 
     return optimum 
gradient_descent(y,dy_dx,5) 

今私は回帰問題に適用しようとしている、しかし、出力は以下の出力のように正しく表示されません。

固定

Output of gradient descent code below

import matplotlib.pyplot as plt 
def stepGradient(x,y, step): 
    b_current = 0 
    m_current = 0 
    b_gradient = 0 
    m_gradient = 0 
    N = int(len(x)) 
    for i in range(0, N): 
     b_gradient += -(1/N) * (y[i] - ((m_current*x[i]) + b_current)) 
     m_gradient += -(1/N) * x[i] * (y[i] - ((m_current * x[i]) + b_current)) 
    while abs(b_gradient) > 0.01 and abs(m_gradient) > 0.01: 
     b_current = b_current - (step * b_gradient) 
     m_current = m_current - (step * m_gradient) 
     for i in range(0, N): 
      b_gradient += -(1/N) * (y[i] - ((m_current*x[i]) + b_current)) 
      m_gradient += -(1/N) * x[i] * (y[i] - ((m_current * x[i]) + b_current)) 
    return [b_current, m_current] 

x = [1,2, 2,3,4,5,7,8] 
y = [1.5,3,1,3,2,5,6,7] 
step = 0.00001 
(b,m) = stepGradient(x,y,step) 


plt.scatter(x,y) 
abline_values = [m * i + b for i in x] 
plt.plot(x, abline_values, 'b') 
plt.show() 

:D

import matplotlib.pyplot as plt 
def stepGradient(x,y): 
    step = 0.001 
    b_current = 0 
    m_current = 0 
    b_gradient = 0 
    m_gradient = 0 
    N = int(len(x)) 
    for i in range(0, N): 
     b_gradient += -(1/N) * (y[i] - ((m_current*x[i]) + b_current)) 
     m_gradient += -(1/N) * x[i] * (y[i] - ((m_current * x[i]) + b_current)) 
    while abs(b_gradient) > 0.01 or abs(m_gradient) > 0.01: 
     b_current = b_current - (step * b_gradient) 
     m_current = m_current - (step * m_gradient) 
     b_gradient= 0 
     m_gradient = 0 
     for i in range(0, N): 
      b_gradient += -(1/N) * (y[i] - ((m_current*x[i]) + b_current)) 
      m_gradient += -(1/N) * x[i] * (y[i] - ((m_current * x[i]) + b_current)) 
    return [b_current, m_current] 

x = [1,2, 2,3,4,5,7,8,10] 
y = [1.5,3,1,3,2,5,6,7,20] 
(b,m) = stepGradient(x,y) 


plt.scatter(x,y) 
abline_values = [m * i + b for i in x] 
plt.plot(x, abline_values, 'b') 
plt.show() 
+0

勾配降下を持つ事は、それは非常にまれに0の派生物に到達していないということです。グラデーションが高い場合はプロセスは正常に動作しますが、小さな変化に達するとプロセスが最適なポイントを中心に回転することがわかります。 whileループに制限を書くか、微分を0.0001のような小さなε値より大きくしてみてください。 –

+0

「出力が正しいと思われません」とはどういう意味ですか?期待される出力と実際に得られる出力(コンソール出力、トレースバック、グラフプロットなど)を表示します。あなたが提供する詳細が高いほど、あなたが受け取る可能性のあるより良い回答です。 [FAQ](http://stackoverflow.com/tour)と[How to Ask](http://stackoverflow.com/help/how-to-ask)を参照してください。 –

答えて

2

whileあなたのループは、calcul ated浮動小数点値はゼロに等しい。これは、浮動小数点値がまれに正確に計算されることが少ないため、単純です。代わりに、計算された値がで十分に近い場合は、ループを停止してをゼロにします。

while math.abs(derivative(optimum)) > eps: 

ここで、epsは、計算された値の望ましい精度です。これはおそらくデフォルト値1e-10またはそのようなものを用いて、別のパラメータにすることができます。


しかし、あなたの場合の問題は悪化しています。あなたのアルゴリズムは計算

optimum = optimum - 2*derivative(optimum) 

が実際の最適値に近いoptimumの値を移動すると仮定ではあまりにもナイーブです。あなたの特別なケースでは、変数optimumは、5(最初の推定値)と-5の間で前後に循環します。 5の誘導体は10であり、-5の誘導体は-10であることに留意されたい。

このようなサイクリングを避ける必要があります。デルタ2*derivative(optimum)1より小さい何かを掛けることができます。具体的には、y=x**2で動作します。しかし、これは一般的には機能しません。

完全に安全であるためには、より小さい値と大きな値で最適点を「ブラケット」し、次の推測を見つけるために導関数を使用します。しかし、あなたの次の推測が括弧で囲まれた間隔の外に出ないようにしてください。そうした場合、または推測の収束が遅すぎる場合は、二分法や黄金平均法などの別の方法を使用してください。

もちろん、これは、あなたの「非常に純粋な勾配降下」アルゴリズムは、一般的に動作するにはあまりにも純粋ではないことを意味します。そのため、実際の最適化ルーチンはより複雑です。

+0

ありがとうございます。私はちょうどそれを試みたが、ループはまだ進行中です。 –

+0

スレッドが更新されました。 –

+0

申し訳ありませんが、私はpplがコードを実行すると思ったので、すぐにグラフを更新します。 –

0

はまた、(勾配降下式にガンマ)あなたのステップサイズを小さくする必要があります。

y = lambda x : x**2 
dy_dx = lambda x : 2*x 
def gradient_descent(function,derivative,initial_guess): 
    optimum = initial_guess 
    while abs(derivative(optimum)) > 0.01: 
     optimum = optimum - 0.01*derivative(optimum) 
     print((optimum,derivative(optimum))) 
    else: 
     return optimum 
+0

ありがとう、アルゴリズムは動作しますが、戻り値が機能しません、どのように私は最終的な最適を返す関数を作ることができます –

+0

スレッドが更新されました。 –

関連する問題