• 梯度下降基础


    一 概述

    机器学习三大步骤:

    • model (define a set of function)
    • goodness of function
    • pick the "best" function

    step1:model

    在这里我们建立一个model

    这个Model称之为Linear model:

    不同的b、w,得到的 f 不尽相同

    而我们要找到最能满足要求的一个 f 。

    step2 goodness of function

    training data:

    当我们将准备好的training data(已知10个宝可梦的进化情况),建立一个二维坐标轴。

    通过上图可以看出,好像有一个函数能够拟合这些坐标点,而这正是我们想要的,为了选出最契合的 f ,我们要建立一个Loss function L ,也就是函数的函数。

    如果我们将 f 的 w 和 b 作为两轴,则在下图中每一点都确定了一个 function f ,而颜色代表output的大小,也就代表该function f 参数的好坏。易理解,smallest点做对应的函数 f 就是我们想要的。

    step3 best function

    接下来就是选出使Loss function值最小的f。该怎么计算出来呢?可以用线性代数的方法来计算出最佳的w和b。但我们也可以用Gradient Descent方法求出最佳的w和b。

    当我们在L(w)的二维平面中时,我们必须要找到函数的最低点。

    首先随机选取一个点w0,计算微分也就是斜率,如果为正,则减小w,如果为负,则增大w。

    而这有另一个问题,每次要增加或减少多少w值呢,有两个因素影响。第一,即微分值,如果微分值很大或很小,表示此处非常陡峭,那么证明距离最低点还有很远的距离,所以移动的距离就很大。第二个因素是我们事先自己定义的常数项 η 值,即步长(Learning Rate)。


    不断重复,经过多次的参数更新后,能达到一个最低点。
     
    过程如下:

    说到这里大家可能会担心,会不会产生下图左半部分的哪种情况,即不同的起始位置,找到的最低点是不一样的,其实,在我们案例的Linear regression中,是不会出现这种情况的。

    最后运行的结果如下图所示

    通过上图就会发现,并不是所有的点都能拟合函数,这就会造成很大的预测不准的情况,通过Loss Function也能看出,最优解的值依然很大,在测试数据的表现也不好,所以自然就要想办法做得更好。怎么做得更好呢?这个时候我们可以考虑更换Model。

    引入平方

     

    引入立方

    引入四次方

    引入五次方

     

    观察以上模型的表现,可以看到随着模型次数的增加,在Training Data上的表现越来越好(前提是Gradient Descent可以找到参数的最优值)。为什么呢?因为复杂的模型包含了简单的模型。

     
     

    而在Testing Data上的表现却不一样,甚至在五次方程时,大大超出了我们的预估,那么这种现象就叫做overfitting。

     

    所以,function不是越复杂越好,所以我们要选择一个最合适的,由上图可以看出,在三次方程中表现最好。

    你是不是以为这样就结束了?答案是否定的。
    当我们收集了更多的数据后,将其绘制成图像:

     

    可以看出来,肯定有什么别的因素影响着进化后的CP值。

    可以看到,进化后的CP值受物种影响很大。知道了这点后,我们自然要重新设计Model。

     
     

    结果如下:

    当然还可能有别的特征影响了进化的CP值,比如:

    我们还是从重新设置Model,并经过计算得到:

    出现了Overfitting的现象,如何改进呢?

     
     
     

    二 实例

    假设有如下数据:

    x_data = [338.,333.,328.,207.,226.,25.,179.,60.,208.,606]
    y_data = [640.,633.,619.,393.,428.,27.,193.,66.,226.,1591]

    其中,y_data = w * x_data + bwb都是参数,让我们用梯度下降(Gradient Descent)的方法将wb的值找出来。当然,还有许多其他的方法,但我们假装不知道这件事,用Gradient Descent的方法将其找出来。

    代码如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    x_data = [338.,333.,328.,207.,226.,25.,179.,60.,208.,606]
    y_data = [640.,633.,619.,393.,428.,27.,193.,66.,226.,1591]
    #ydata=b+w*xdata
    
    x = np.arange(-200,-100,1)# bias
    y = np.arange(-5,5,0.1)# weight
    z = np.zeros((len(x),len(y)))
    X,Y = np.meshgrid(x,y)
    for i in range(len(x)):
        for j in range(len(y)):
            b = x[j]
            w = y[j]
            z[j][i]=0
            for n in range(len(x_data)):
                z[j][i] = z[j][i] + (y_data[n] - b - w * x_data[n]) ** 2
            z[j][i] = z[j][i] / len(x_data)
    
    #ydata = b + w * xdata
    b = -120 #initial b
    w = -4 #initial w
    lr = 0.0000001 #learning rata
    iteration = 100000
    
    #store initial values for plotting
    b_history = [b]
    w_history = [w]
    
    #iterations
    for i in range(iteration):
        
        b_grad = 0.0
        w_grad = 0.0
        for n in range(len(x_data)):
            b_grad = b_grad - 2.0 * (y_data[n] - b - w * x_data[n]) * 1.0
            w_grad = w_grad - 2.0 * (y_data[n] - b - w * x_data[n]) * x_data[n]
           
            #updata parameters
        b = b - lr * b_grad
        w = w - lr * w_grad
            #store parameters for plotting
        b_history.append(b)
        w_history.append(w)
            
    # plot the figure
    plt.contourf(x,y,z,50,alpha=0.5,cmap=plt.get_cmap('jet'))
    plt.plot([-188.4],[2.67],'x',ms=12,markeredgewidth=3,color='orange')
    plt.plot(b_history,w_history,'o-',ms=3,lw=1.5,color='black')
    plt.xlim(-200,-100)
    plt.ylim(-5,5)
    plt.xlabel(r'$b$',fontsize = 16)
    plt.ylabel(r'$w$',fontsize = 16)
    plt.show()

    运行结果如下:

    其中,橙色的x代表最优解,图中的黑色块代表了100000次的迭代过程,可以看出此时离最优解还差得远。这显然是Learning Rate不够大,我们不妨把它调大点,比如说lr = 0.000001,也就是增大了10倍,得到结果如下:

    离最优解稍微近了一点,不过有一个剧烈震荡的现象。我们不妨再把Learning Rate调大,比如说lr=0.00001,得到结果如下:

    糟糕,Learning Rate此时太大了。此时我们该怎么办?如果两个参数都没办法解决,更不用谈更多参数的情况了,只好用大招!——我们要给bw客制化的Learning Rate。

    #ydata = b + w * xdata
    b = -120 #initial b
    w = -4 #initial w
    lr = 1 #learning rata
    iteration = 100000
    
    #store initial values for plotting
    b_history = [b]
    w_history = [w]
    
    lr_b = 0.0 
    lr_w = 0.0
    #iterations
    for i in range(iteration):
        
        b_grad = 0.0
        w_grad = 0.0
        for n in range(len(x_data)):
            b_grad = b_grad - 2.0 * (y_data[n] - b - w * x_data[n]) * 1.0
            w_grad = w_grad - 2.0 * (y_data[n] - b - w * x_data[n]) * x_data[n]
            
        lr_b = lr_b + b_grad ** 2
        lr_w = lr_w + w_grad ** 2
            
            #updata parameters
        b = b - lr / np.sqrt(lr_b) * b_grad
        w = w - lr / np.sqrt(lr_w) * w_grad
            #store parameters for plotting
        b_history.append(b)
        w_history.append(w)
            
    # plot the figure
    plt.contourf(x,y,z,50,alpha=0.5,cmap=plt.get_cmap('jet'))
    plt.plot([-188.4],[2.67],'x',ms=12,markeredgewidth=3,color='orange')
    plt.plot(b_history,w_history,'o-',ms=3,lw=1.5,color='black')
    plt.xlim(-200,-100)
    plt.ylim(-5,5)
    plt.xlabel(r'$b$',fontsize = 16)
    plt.ylabel(r'$w$',fontsize = 16)
    plt.show()

    运行结果如下:

    可以看到,在100000次的迭代内,找到了最优解。

    参考:

    https://www.jianshu.com/p/5ac76589ee7b

    https://www.jianshu.com/p/8463d08f4379

  • 相关阅读:
    杭电OJ-1031_Design T-Shirt
    杭电OJ-1036_Average is not Fast Enough!
    2019杭电多校一 L. Sequence (NTT)
    Binary Table CodeForces
    2019牛客多校一 H. XOR (线性基)
    Jzzhu and Numbers CodeForces
    Geometers Anonymous Club CodeForces
    [笔记] 扩展卢卡斯
    Luogu P2183 [国家集训队]礼物 扩展卢卡斯+组合数
    Luogu P4901 排队 fib数列+树状数组+倍增
  • 原文地址:https://www.cnblogs.com/Terrypython/p/9376407.html
Copyright © 2020-2023  润新知