【问题标题】:How to determine the learning rate and the variance in a gradient descent algorithm?如何确定梯度下降算法中的学习率和方差?
【发布时间】:2013-05-14 11:26:45
【问题描述】:

我上周开始学习机器学习。当我想做一个梯度下降脚本来估计模型参数时,我遇到了一个问题:如何选择合适的学习率和方差。我发现,不同的(学习率,方差)对可能会导致不同的结果,有些有时你甚至无法收敛。此外,如果更改为另一个训练数据集,一个精心挑选的(学习率,方差)对可能不起作用。例如(下面的脚本),当我将学习率设置为0.001,方差设置为0.00001时,对于'data1',我可以得到合适的theta0_guess和theta1_guess。但是对于‘data2’,他们无法使算法收敛,即使我尝试了几十个(学习率,方差)对仍然无法收敛。

所以如果有人能告诉我有一些标准或方法来确定(学习率,方差)对。

import sys

data1 = [(0.000000,95.364693) ,
    (1.000000,97.217205) ,
    (2.000000,75.195834),
    (3.000000,60.105519) ,
    (4.000000,49.342380),
    (5.000000,37.400286),
    (6.000000,51.057128),
    (7.000000,25.500619),
    (8.000000,5.259608),
    (9.000000,0.639151),
    (10.000000,-9.409936),
    (11.000000, -4.383926),
    (12.000000,-22.858197),
    (13.000000,-37.758333),
    (14.000000,-45.606221)]

data2 = [(2104.,400.),
     (1600.,330.),
     (2400.,369.),
     (1416.,232.),
     (3000.,540.)]

def create_hypothesis(theta1, theta0):
    return lambda x: theta1*x + theta0

def linear_regression(data, learning_rate=0.001, variance=0.00001):


    theta0_guess = 1.
    theta1_guess = 1.


    theta0_last = 100.
    theta1_last = 100.

    m = len(data)

    while (abs(theta1_guess-theta1_last) > variance or abs(theta0_guess - theta0_last) > variance):

        theta1_last = theta1_guess
        theta0_last = theta0_guess

        hypothesis = create_hypothesis(theta1_guess, theta0_guess)

        theta0_guess = theta0_guess - learning_rate * (1./m) * sum([hypothesis(point[0]) - point[1] for point in data])
        theta1_guess = theta1_guess - learning_rate * (1./m) * sum([ (hypothesis(point[0]) - point[1]) * point[0] for point in data])   

    return ( theta0_guess,theta1_guess )



points = [(float(x),float(y)) for (x,y) in data1]

res = linear_regression(points)
print res

【问题讨论】:

    标签: python machine-learning gradient-descent


    【解决方案1】:

    绘图是查看算法执行情况的最佳方式。要查看是否已实现收敛,您可以绘制每次迭代后成本函数的演变,在特定给定的迭代之后,您会发现它并没有太大改善,您可以假设收敛,请查看以下代码:

    cost_f = []
    while (abs(theta1_guess-theta1_last) > variance or abs(theta0_guess - theta0_last) > variance):
    
        theta1_last = theta1_guess
        theta0_last = theta0_guess
    
        hypothesis = create_hypothesis(theta1_guess, theta0_guess)
        cost_f.append((1./(2*m))*sum([ pow(hypothesis(point[0]) - point[1], 2) for point in data]))
    
        theta0_guess = theta0_guess - learning_rate * (1./m) * sum([hypothesis(point[0]) - point[1] for point in data])
        theta1_guess = theta1_guess - learning_rate * (1./m) * sum([ (hypothesis(point[0]) - point[1]) * point[0] for point in data])   
    
    import pylab
    pylab.plot(range(len(cost_f)), cost_f)
    pylab.show()
    

    这将绘制以下图形(执行 learning_rate=0.01,variance=0.00001)

    如您所见,经过一千次迭代后,您并没有得到太大的改进。如果成本函数在一次迭代中减小到小于 0.001,我通常会声明收敛,但这只是基于我自己的经验。

    对于选择学习率,您可以做的最好的事情是绘制成本函数并查看它的表现,并始终记住这两件事:

    • 如果学习率太小,收敛速度会很慢
    • 如果学习率太大,您的成本函数可能不会在每次迭代中降低,因此不会收敛

    如果您选择 learning_rate > 0.029 和 variance=0.001 运行您的代码,您将在第二种情况下,梯度下降不会收敛,而如果您选择值 learning_rate

    learning_rate=0.03 的不收敛示例

    learning_rate=0.0001 的慢收敛示例

    【讨论】:

    • ,感谢您的建议。我仍然不确定一件事:继续尝试是我们获得合适的(率,方差)对的唯一方法吗?
    • 我想你总是可以做一个脚本来检查 GD 收敛的速度(也许计算一阶导数),但是我从来没有做过这样的事情,我更愿意了解我的算法在做什么以及如何它正在执行。
    【解决方案2】:

    有很多方法可以保证梯度下降算法的收敛。有线搜索,与梯度的 Lipschitz 常数相关的固定步长(即在函数的情况下。在像你这样的表的情况下,你可以在连续值之间产生差异),减小步长每次迭代和其他一些迭代。其中一些can be found here

    【讨论】:

    • 欢迎来到 Stack Overflow。请在您的答案中总结链接;这样,如果链接失效,答案也不会完全没用。
    猜你喜欢
    • 2020-08-07
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2016-10-27
    • 2016-03-31
    • 2018-01-31
    相关资源
    最近更新 更多