代码之家  ›  专栏  ›  技术社区  ›  Olivier Girardot

如何创建一个简单的梯度下降算法

  •  7
  • Olivier Girardot  · 技术社区  · 14 年前

    我正在学习简单的机器学习算法,从一个简单的梯度下降开始,但是我在用Python实现它时遇到了一些困难。

    下面是我试图复制的例子,我得到了关于(居住区(2英尺)和卧室数量)的房子的数据,以及由此产生的价格:

    生活区(feet2):2104

    卧室:3

    价格(1000美元):400

    我试图用梯度下降法做一个简单的回归,但是我的算法不起作用… 算法的形式并不是有意使用向量(我正在逐步理解它)。

    i = 1
    import sys
    derror=sys.maxint
    error = 0
    step = 0.0001
    dthresh = 0.1
    import random
    
    theta1 = random.random()
    theta2 = random.random()
    theta0 = random.random()
    while derror>dthresh:
        diff = 400 - theta0 - 2104 * theta1 - 3 * theta2
        theta0 = theta0 + step * diff * 1
        theta1 = theta1 + step * diff * 2104
        theta2 = theta2 + step * diff * 3
        hserror = diff**2/2
        derror = abs(error - hserror)
        error = hserror
        print 'iteration : %d, error : %s' % (i, error)
        i+=1
    

    我懂数学,我在构造一个预测函数 $$h_{\theta}(x) = \theta_0 + \theta_1 x_1 + \theta_2 x_2$$ http://mathurl.com/hoy7ege.png 具有 $x_1$ http://mathurl.com/2ga69bb.png $x_2$ http://mathurl.com/2cbdldp.png 是变量(居住面积、卧室数量)和 $h_{\theta}(x)$ http://mathurl.com/jckw8ke.png 估计价格。

    我用的是成本函数( $hserror$ http://mathurl.com/guuqjv5.png )(一点): $$hserror = \frac{1}{2} (h_{\theta}(x) - y)^2$$ http://mathurl.com/hnrqtkf.png 这是一个常见的问题,但我更像是一个软件工程师,我一步一步地学习,你能告诉我怎么了吗?

    我把它和这个代码结合起来:

    data = {(2104, 3) : 400, (1600,3) : 330, (2400, 3) : 369, (1416, 2) : 232, (3000, 4) : 540}
    for x in range(10):
        i = 1
        import sys
        derror=sys.maxint
        error = 0
        step = 0.00000001
        dthresh = 0.0000000001
        import random
    
        theta1 = random.random()*100
        theta2 = random.random()*100
        theta0 = random.random()*100
        while derror>dthresh:
            diff = 400 - (theta0 + 2104 * theta1 + 3 * theta2)
            theta0 = theta0 + step * diff * 1
            theta1 = theta1 + step * diff * 2104
            theta2 = theta2 + step * diff * 3
            hserror = diff**2/2
            derror = abs(error - hserror)
            error = hserror
            #print 'iteration : %d, error : %s, derror : %s' % (i, error, derror)
            i+=1
        print ' theta0 : %f, theta1 : %f, theta2 : %f' % (theta0, theta1, theta2)
        print ' done : %f' %(theta0 + 2104 * theta1 + 3*theta2)
    

    结果是这样的答案:

     theta0 : 48.412337, theta1 : 0.094492, theta2 : 50.925579
     done : 400.000043
     theta0 : 0.574007, theta1 : 0.185363, theta2 : 3.140553
     done : 400.000042
     theta0 : 28.588457, theta1 : 0.041746, theta2 : 94.525769
     done : 400.000043
     theta0 : 42.240593, theta1 : 0.096398, theta2 : 51.645989
     done : 400.000043
     theta0 : 98.452431, theta1 : 0.136432, theta2 : 4.831866
     done : 400.000043
     theta0 : 18.022160, theta1 : 0.148059, theta2 : 23.487524
     done : 400.000043
     theta0 : 39.461977, theta1 : 0.097899, theta2 : 51.519412
     done : 400.000042
     theta0 : 40.979868, theta1 : 0.040312, theta2 : 91.401406
     done : 400.000043
     theta0 : 15.466259, theta1 : 0.111276, theta2 : 50.136221
     done : 400.000043
     theta0 : 72.380926, theta1 : 0.013814, theta2 : 99.517853
     done : 400.000043
    
    1 回复  |  直到 8 年前
        1
  •  8
  •   Michael Anderson    14 年前

    第一个问题是,只使用一个数据来运行这个系统会给您一个不确定的系统…这意味着它可能有无限多的解。对于三个变量,您希望至少有三个数据点,最好更高。

    其次,在阶跃大小为比例阶跃的情况下,使用梯度下降并不能保证收敛,除非在解的一个小邻域中。您可以通过切换到负渐变(慢)方向上的固定大小步骤或负渐变(快,但稍微复杂)方向上的行搜索来解决此问题。

    因此,对于固定的步长,而不是

    theta0 = theta0 - step * dEdtheta0
    theta1 = theta1 - step * dEdtheta1
    theta2 = theta2 - step * dEdtheta2
    

    你这样做

    n = max( [ dEdtheta1, dEdtheta1, dEdtheta2 ] )    
    theta0 = theta0 - step * dEdtheta0 / n
    theta1 = theta1 - step * dEdtheta1 / n
    theta2 = theta2 - step * dEdtheta2 / n
    

    看起来您的步骤中可能有符号错误。

    我也不确定德罗尔是否是一个好的阻止标准。(但众所周知,阻止标准很难做到“正确”)。

    最后一点是,梯度下降对于参数拟合来说是非常缓慢的。您可能希望使用共轭梯度或LevenbergMarquadt方法来代替。我怀疑这两种方法已经存在于numpy或scipy包中(默认情况下,这不是python的一部分,但非常容易安装)。