梯度下降基本算法超调并且在python中不收敛

时间:2019-05-06 01:47:11

标签: python algorithm machine-learning gradient

因此,我是学习ML的新手,并且我将梯度下降作为我想要擅长并学习得很好的第一个算法。我编写了第一个代码,并在网上查找了我所面临的问题,但是由于缺乏具体的知识,我很难理解如何诊断问题。我的梯度从接近正确答案开始,当误差减少了8倍时,算法将丢失其值,b值开始变为负值,m值超过目标值。很抱歉,我措辞很奇怪,希望代码会有所帮助。

我正在从youtube和google的多个来源中学习这一点。我一直在youtube上关注Siraj Raval的智能数学播放列表,我了解基本算法的工作原理,但是我决定采用自己的方法,但效果似乎不太好。由于我对算法的含义以及如何将其实现到python缺乏经验,因此我正在努力阅读在线资源。我知道这个问题与培训和测试有关,但我不知道在哪里应用。

def gradient_updater(error, mcurr, bcurr):

    for i in x:
        # gets the predicted y-value
        ypred = (mcurr * i) + bcurr
        # uses partial derivative formula to get new m and b
        new_m = -(2/N) * sum(x*(y - ypred))
        new_b = -(2/N) * sum(y - ypred)
    # applies the new b and m value
    mcurr = mcurr - (learning_rate * new_m)
    bcurr = bcurr - (learning_rate * new_b)
    return mcurr, bcurr

def run(iterations, initial_m, initial_b):

    current_m = initial_m
    current_b = initial_b
    for i in range(iterations):
        error = get_error(current_m, current_b)
        current_m, current_b = gradient_updater(error, current_m, current_b)
        print(current_m, current_b, error)

我希望m和b值收敛到一个特定值,这不会发生,并且值在相反方向上不断增加。

2 个答案:

答案 0 :(得分:0)

如果我正确地理解了您的代码,我认为您的问题是您采用偏导数来获得新的斜率并仅在一点上进行截距。我不确定gradient_updater中的某些变量到底是什么,所以我将尝试提供一个更好地解释这一概念的示例:

我不确定我们是否以相同的方式来计算优化,因此在我的代码中,b0是y = mx + b中的“ x”,而b1是相同方程式中的“ b”。以下代码用于计算总的b0_temp和b1_temp,将其除以批处理大小以显示新的b0和b1以适合您的图形。

for i in range(len(X)):

    ERROR = ERROR + (b1*X[i] + b0 - Y[i])**2

    b1_temp = b1_temp + (1/2)*((1/len(X))*(b1*X[i] + b0 - Y[i])**2)**(-1/2) * (2/len(X))*(b1*X[i] + b0 - Y[i])*X[i]
    b0_temp = b0_temp + (1/2)*((1/len(X))*(b1*X[i] + b0 - Y[i])**2)**(-1/2) * (2/len(X))*(b1*X[i] + b0 - Y[i])

我对数据集中的每个值进行遍历,其中X[i]Y[i]代表单个数据点。

接下来,我调整当前适合该图的斜率:

        b1_temp = b1_temp / batch_size
        b0_temp = b0_temp / batch_size

        b0 = b0 - learning_rate * b0_temp
        b1 = b1 - learning_rate * b1_temp

        b1_temp = 0
        b0_temp = 0

其中batch_size可以仅用作len(X)。我经历了一些时期(即for循环的某个数目,应该工作100个),并且最合适的线会随着时间而相应地调整。其背后的总体概念是将每个点与直线之间的距离减小到最小。

希望我能更好地向您解释这一点,并为您提供基本的代码库,以适应您的需求!

答案 1 :(得分:0)

这是我认为您的代码中存在错误的地方-梯度的计算。我相信您的成本函数类似于https://ml-cheatsheet.readthedocs.io/en/latest/gradient_descent.html中使用的成本函数。要求解梯度,您需要汇总所有偏导数的效果。但是,在您的实现中,您在 x 范围内进行了迭代,而没有累积效果。因此,您的new_mnew_b仅针对最后一项 x (以下标记为1和2的项)进行计算。

您的实施:

def gradient_updater(error, mcurr, bcurr):
    for i in x:
        # gets the predicted y-value
        ypred = (mcurr * i) + bcurr
        # uses partial derivative formula to get new m and b
        new_m = -(2/N) * sum(x*(y - ypred))    #-- 1 --
        new_b = -(2/N) * sum(y - ypred)    #-- 2 --
    # applies the new b and m value <-- Indent this block to place inside the for loop
    mcurr = mcurr - (learning_rate * new_m)
    bcurr = bcurr - (learning_rate * new_b)
    return mcurr, bcurr

也就是说,如果您在每次迭代中仅更新mcurrbcurr(请参阅内联注释),我认为您的实现应该更接近数学公式。另一件事是在计算sum(x*(y - ypred))sum(y - ypred)时,也将new_mnew_b除以 N

注意 由于我不知道您的实际成本函数是什么,我只想指出您在代码中也使用了恒定的y值。它更有可能是一个不同值的数组,分别由Y [i]和X [i]调用。