如何做一个梯度下降问题(机器学习)?

How to do a gradient descent problem (machine learning)?

有人可以解释一下如何在没有代价函数的情况下解决梯度下降问题吗?我看过无数使用成本函数解释梯度下降的教程,但我真的不明白它在更一般意义上是如何工作的。

我得到一个 3D 函数:

z = 3*((1-xx)2) * np.exp(-(xx2) - (yy+1) 2) \ - 10*(xx/5 - xx3 - yy5) * np.exp(-xx2 - yy2) - (1/3)* np.exp(-(xx+1)**2 - yy2)

我被要求:

编写一个简单的梯度算法。设置参数如下:

然后在

开始你的算法

我在任何谈论梯度下降的地方都看到过这段代码:

def update_weights(m, b, X, Y, learning_rate):
    m_deriv = 0
    b_deriv = 0
    N = len(X)
    for i in range(N):
        # Calculate partial derivatives
        # -2x(y - (mx + b))
        m_deriv += -2*X[i] * (Y[i] - (m*X[i] + b))

        # -2(y - (mx + b))
        b_deriv += -2*(Y[i] - (m*X[i] + b))

    # We subtract because the derivatives point in direction of steepest ascent
    m -= (m_deriv / float(N)) * learning_rate
    b -= (b_deriv / float(N)) * learning_rate

    return m, b
    enter code here

但我不明白如何使用它来解决我的问题。我的功能如何适应那里?我应该调整什么而不是 m 和 b?我很困惑。

谢谢。

梯度下降是寻找函数最小值的优化算法。

非常简化的视图

让我们从一维函数开始 y = f(x)

让我们从 x 的任意值开始,找到 f(x) 的梯度(斜率)。

  • 如果斜率在 x 处减小,则意味着我们必须向(数轴右侧)x 进一步移动(以达到最小值)

  • 如果斜率在 x 处增加,则意味着我们必须离开(数字线左侧)x

    我们可以通过对函数求导得到斜率。如果斜率正在减小,则导数为 -ve;如果斜率正在增加,则导数为 +ve

所以我们可以从 x 的任意值开始,然后使用 x 值的导数慢慢地向最小值移动。我们移动的速度有多慢取决于学习率或步长。所以我们有更新规则

x = x - df_dx*lr

我们可以看到,如果斜率正在减小,导数 (df_dx) 为 -ve,并且 x 正在增加,因此 x 正在向右移动。另一方面,如果斜率增加,df_dx 是 +ve,它会减少 x,所以我们向左移动。

我们继续这样做很多次或者直到导数非常小

多元函数 z = f(x,y)

除了现在我们采用偏导数而不是导数外,与上述逻辑相同。 更新规则为

x = x - dpf_dx*lr
y = y - dpf_dy*lr

其中dpf_dx是f关于x的偏导数

上述算法称为梯度下降算法。在机器学习中,f(x,y) 是一个 cost/loss 函数,我们感兴趣的是其最小值。

例子

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
from pylab import meshgrid
from scipy.optimize import fmin
import math

def z_func(a):
 x, y = a
 return ((x-1)**2+(y-2)**2)
 
x = np.arange(-3.0,3.0,0.1)
y = np.arange(-3.0,3.0,0.1)
X,Y = meshgrid(x, y) # grid of point
Z = z_func((X, Y)) # evaluation of the function on the grid

fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1,linewidth=0, antialiased=False)
plt.show()

z_func 的最小值在 (1,2)。这可以使用 scipy

的 fmin 函数来验证
fmin(z_func,np.array([10,10]))

现在让我们编写自己的梯度下降算法来找到 z_func

的最小值
def gradient_decent(x,y,lr):
    while True:
        d_x = 2*(x-1)
        d_y = 2*(y-2)
        
        x -= d_x*lr
        y -= d_y*lr
        
        if d_x < 0.0001 and d_y < 0.0001:
            break
    return x,y

print (gradient_decent(10,10,0.1)

我们从某个任意值 x=10 和 y=10 开始,学习率为 0.1。上面的代码打印 1.000033672997724 2.0000299315535326 是正确的。

所以如果你有一个连续的可微凸函数,要找到它的最优值(对于凸函数来说是最小的)你所要做的就是找到函数关于每个变量的偏导数并使用更新规则上文提到的。重复这些步骤,直到梯度变小,这意味着我们已经达到凸函数的最小值。

如果函数不是凸函数,我们可能会陷入局部最优。