zoukankan      html  css  js  c++  java
  • 15、优化算法之Mini-batch 梯度下降法

    再进行Mini-batch 梯度下降法学习之前,我们首先对梯度下降法进行理解

    一、梯度下降法(Gradient Descent)

      优化思想:用当前位置的负梯度方向作为搜索方向,亦即为当前位置下降最快的方向,也称“最速下降法”。越接近目标值时,步长越小,下降越慢。

      首先来看看梯度下降的一个直观的解释。比如我们在一座大山上的某处位置,由于我们不知道怎么下山,于是决定走一步算一步,也就是在每走到一个位置的时候,求解当前位置的梯度,沿着梯度的负方向,也就是当前最陡峭的位置向下走一步,然后继续求解当前位置梯度,向这一步所在位置沿着最陡峭最易下山的位置走一步。这样一步步的走下去,一直走到觉得我们已经到了山脚。当然这样走下去,有可能我们不能走到山脚,而是到了某一个局部的山峰低处。

      从上面的解释可以看出,梯度下降不一定能够找到全局的最优解,有可能是一个局部最优解。当然,如果损失函数是凸函数,梯度下降法得到的解就一定是全局最优解。

     接下来我们了解一下梯度下降法的相关概念

     二、批量梯度下降法(Batch Gradient Descent,BGD)

        在更新参数时,BGD根据batch中的所有样本对参数进行更新。

      三、随机梯度下降法(Stochastic Gradient Descent,SGD)

      随机梯度下降法,其实和批量梯度下降法原理类似,区别在与求梯度时没有用所有的m个样本的数据,而是仅仅选取一个样本j来求梯度。对应的更新公式是:

       随机梯度下降法,和批量梯度下降法是两个极端,一个采用所有数据来梯度下降,一个用一个样本来梯度下降。自然各自的优缺点都非常突出。对于训练速度来说,随机梯度下降法由于每次仅仅采用一个样本来迭代,训练速度很快,而批量梯度下降法在样本量很大的时候,训练速度不能让人满意。对于准确度来说,随机梯度下降法用于仅仅用一个样本决定梯度方向,导致解很有可能不是最优。对于收敛速度来说,由于随机梯度下降法一次迭代一个样本,导致迭代方向变化很大,不能很快的收敛到局部最优解。

    四、小批量梯度下降法(Mini-batch Gradient Descent)——>重点

      小批量梯度下降法是批量梯度下降法和随机梯度下降法的折衷,也就是对于m个样本,我们采用x个样子来迭代,1<x<m。一般可以取x=10,当然根据样本的数据,可以调整这个x的值。对应的更新公式是:

    五、三种方法代码演示

    (一)准备工作

      1、导入相关的包

    import numpy as np
    import os
    #画图
    %matplotlib inline
    import matplotlib.pyplot as plt

      2、保存图像

    #保存图像
    PROJECT_ROOT_DIR = "."
    MODEL_ID = "linear_models"

      3、生成随机种子

    np.random.seed(42)

      4、定义一个保存图像的函数

    #定义一个保存图像的函数
    def save_fig(fig_id,tight_layout=True):
        path = os.path.join(PROJECT_ROOT_DIR,"images",MODEL_ID,fig_id + ".png")#指定保存图像的路径
        print("Saving figure",fig_id)#提示函数,正在保存图片
        plt.savefig(path,format="png",dpi=300)#保存图片(需要指定保存路径,保存格式,清晰度)

      5、过滤掉讨厌的警告信息

    #过滤掉讨厌的警告信息
    import warnings
    warnings.filterwarnings(action="ignore",message="internal gelsd")

      6、定义变量

    #定义变量
    import numpy as np
     
    x = 2 * np.random.rand(100,1) #生成训练数据(特征部分)
    y = 4 + 3 * x + np.random.randn(100,1) #生成训练数据(标签部分)

      7、画出图像

    #画出图像
    plt.plot(x,y,"b.") #画图
    plt.xlabel("$x_1$",fontsize=18)
    plt.ylabel("$y$",fontsize=18,rotation=0)
    plt.axis([0,2,0,15])
    save_fig("generated_data_plot") #保存图片
    plt.show()

       8、添加新特征

    #添加新特征
    x_b = np.c_[np.ones((100,1)),x]

      9、创建测试数据

    #创建测试数据
    x_new = np.array([[0],[2]])
    x_new_b = np.c_[np.ones((2,1)),x_new]
     
    #从sklearn包里导入线性回归模型
    from sklearn.linear_model import LinearRegression
    line_reg = LinearRegression() #创建线性回归对象
    line_reg.fit(x,y) #拟合训练数据
    line_reg.intercept_,line_reg.coef_  #输出截距,斜率
    (array([4.21509616]), array([[2.77011339]]))

      10、对测试集进行预测

    #对测试集进行预测
    line_reg.predict(x_new)

    (二)用批量梯度下降求解线性回归

    #用批量梯度下降求解线性回归
    eta = 0.1
    n_iterations = 100   #迭代次数
    m =100
    theta = np.random.randn(2,1)
     
    for iteration in range(n_iterations):
        # h theta (x(i)) = x_b.dot(theta)
        
        gradients = 2/m * x_b.T.dot(x_b.dot(theta) - y )
        theta = theta - eta * gradients
    m = len(x_b)
    theta_path_bgd = []
    def plot_gradient_descent(theta,eta,theta_path = None):
        m = len(x_b)
        plt.plot(x,y,"b.")
        n_iterations = 1000
        for iteration in range(n_iterations):
            if iteration <10:
                y_predict = x_new_b.dot(theta)
                style = "b-"
                plt.plot(x_new,y_predict,style)
            gradients = 2/m * x_b.T.dot(x_b.dot(theta) - y)
            theta = theta - eta *gradients
            if theta_path is not None:
                theta_path.append(theta)
        plt.xlabel("$x_1$",fontsize=18)
        plt.axis([0,2,0,15]) #坐标,横坐标0-2,纵坐标0-15
        plt.title(r"$eta = {}$".format(eta),fontsize=16)
    np.random.seed(42)
    theta = np.random.randn(2,1) #random initialization
     
    plt.figure(figsize=(10,4))
    plt.subplot(131);plot_gradient_descent(theta,eta=0.02)
    plt.ylabel("$y$",rotation=0,fontsize=18)
    plt.subplot(132);plot_gradient_descent(theta,eta=0.1,theta_path=theta_path_bgd)
    plt.subplot(133);plot_gradient_descent(theta,eta=0.5)
     
    save_fig("gradient_descent_plot")
    plt.show()

     (三)用随机梯度下降求解线性回归

    #用随机梯度下降求解线性回归
    theta_path_sgd = []
    m = len(x_b)
    np.random.seed(42)
    n_epochs = 50
     
    theta = np.random.randn(2,1) #随机初始化
     
    for epoch in range(n_epochs):
        for i in range(m):
            if epoch == 0 and i < 20:
                y_predict = x_new_b.dot(theta)
                style = "b-"
                plt.plot(x_new,y_predict,style)
            random_index = np.random.randint(m)
            xi = x_b[random_index:random_index+1]
            yi = y[random_index:random_index+1]
            gradients = 2 * xi.T.dot(xi.dot(theta)-yi)
            eta = 0.1
            theta = theta - eta * gradients
            theta_path_sgd.append(theta)
        
    plt.plot(x,y,"b.")
    plt.xlabel("$x_1$",fontsize=18)
    plt.ylabel("$y$",fontsize=18,rotation=0)
    plt.axis([0,2,0,15])
    save_fig("sgd_plot") #保存图片
    plt.show()

    from sklearn.linear_model import SGDRegressor
    sgd_reg = SGDRegressor(max_iter=50,tol=np.infty,penalty=None,eta0=0.1,random_state=42)
    sgd_reg.fit(x,y.ravel())
    SGDRegressor(eta0=0.1, max_iter=50, penalty=None, random_state=42, tol=inf)
    #查看截取,斜率
    sgd_reg.intercept_,sgd_reg.coef_

    运行结果:(array([4.25857953]), array([2.95762926]))

    (四)用小批量梯度下降求解线性回归

    #用小批量梯度下降求解线性回归
    theta_path_mgd = []
     
    n_iterations = 50
    minibatch_size = 20
     
    np.random.seed(42)
    theta = np.random.randn(2,1) #random intialization
     
    for epoch in range(n_iterations):
        shuffled_indices = np.random.permutation(m)
        x_b_shuffled = x_b[shuffled_indices]
        y_shuffled = y[shuffled_indices]
        for i in range(0,m,minibatch_size):
            xi = x_b_shuffled[i:i+minibatch_size]
            yi = y_shuffled[i:i+minibatch_size]
            gradients = 2/minibatch_size * xi.T.dot(xi.dot(theta) - yi)
            eta = 0.1
            theta = theta - eta * gradients
            theta_path_mgd.append(theta)
    theta_path_bgd = np.array(theta_path_bgd)
    theta_path_sgd = np.array(theta_path_sgd)
    theta_path_mgd = np.array(theta_path_mgd)
     
    plt.figure(figsize = (7,4))
    plt.plot(theta_path_sgd[:,0],theta_path_sgd[:,1],"r-s",linewidth=1,label="Stochastic")
    plt.plot(theta_path_mgd[:,0],theta_path_mgd[:,1],"g-+",linewidth=2,label="Mini-Batch")
    plt.plot(theta_path_bgd[:,0],theta_path_bgd[:,1],"b-o",linewidth=3,label="Batch")
    plt.legend(loc="upper left",fontsize=16)
    plt.xlabel(r"$theta_0$",fontsize=20)
    plt.ylabel(r"$theta_1$",fontsize=20,rotation = 0)
    plt.axis([2.5,4.5,2.3,3.9])
    save_fig("gradients_descent_paths_plot")
    plt.show()

    参考:https://blog.csdn.net/weixin_36365168/article/details/112484422

  • 相关阅读:
    [React Native] Error Handling and ActivityIndicatorIOS
    [GIF] Colors in GIF Loop Coder
    [React Native] Passing data when changing routes
    [Javascript] Object.freeze() vs Object.seal()
    [React Native] State and Touch Events -- TextInput, TouchableHighLight
    [GIF] GIF Loop Coder
    [GIF] GIF Loop Coder
    [Angular 2] ROUTING IN ANGULAR 2 REVISITED
    Log文件太大,手机ROM空间被占满
    strcpy,memcpy,memmove和内存重叠分析
  • 原文地址:https://www.cnblogs.com/hzzhbest/p/15180620.html
Copyright © 2011-2022 走看看