【问题标题】:Batch Gradient Descent with Python not convergingPython的批量梯度下降不收敛
【发布时间】:2019-12-19 08:44:05
【问题描述】:

这是我用于此练习的 Jupyter Notebook:https://drive.google.com/file/d/18-OXyvXSit5x0ftiW9bhcqJrO_SE22_S/view?usp=sharing

我正在使用this 数据集练习简单的线性回归,这是我的参数:

sat = np.array(data['SAT'])
gpa = np.array(data['GPA'])
theta_0 = 0.01
theta_1 = 0.01
alpha = 0.003
cost = 0
m = len(gpa)

我尝试通过将成本函数计算转换为矩阵并执行元素操作来优化成本函数计算。这是我想出的结果公式:

成本函数优化:

成本函数

def calculateCost(matrix_x,matrix_y,m):
    global theta_0,theta_1
    cost = (1 / (2 * m)) * ((theta_0 + (theta_1 * matrix_x) - matrix_y) ** 2).sum()
    return cost

我也尝试对梯度下降做同样的事情。

梯度下降

def gradDescent(alpha,matrix_x,matrix_y):
    global theta_0,theta_1,m,cost
    cost = calculateCost(sat,gpa,m)
    while cost > 1
        temp_0 = theta_0 - alpha * (1 / m) * (theta_0 + theta_1 * matrix_x - matrix_y).sum()
        temp_1 = theta_1 - alpha * (1 / m) * (matrix_x.transpose() * (theta_0 + theta_1 * matrix_x - matrix_y)).sum()
        theta_0 = temp_0
        theta_1 = temp_1

我不完全确定这两种实现是否正确。该实现返回了 114.89379821428574 的成本,当我绘制成本图时,不知何故,这就是“下降”的样子:

梯度下降图:

如果我正确实现了成本函数梯度下降,请纠正我,并尽可能提供解释,因为我仍然是多元微积分的初学者。谢谢。

【问题讨论】:

    标签: python machine-learning linear-regression gradient-descent


    【解决方案1】:

    该代码存在许多问题。

    首先,bug 背后的两个主要问题:

    1) 线

    temp_1 = theta_1 - alpha * (1 / m) * (matrix_x.transpose() * (theta_0 + theta_1 * matrix_x - matrix_y)).sum()
    

    特别是矩阵乘法matrix_x.transpose() * (theta_0 + ...)* 运算符进行逐元素乘法,因此,结果的大小为 20x20,您期望的梯度大小为 1x1(当您更新单个实变量 theta_1

    2) 梯度计算中的while cost>1: 条件。你永远不会在循环中更新成本......

    这是您的代码的有效版本:

    import numpy as np
    import matplotlib.pyplot as plt
    
    sat=np.random.rand(40,1)
    rand_a=np.random.randint(500)
    rand_b=np.random.randint(400)
    gpa=rand_a*sat+rand_b
    theta_0 = 0.01
    theta_1 = 0.01
    alpha = 0.1
    cost = 0
    m = len(gpa)
    
    def calculateCost(matrix_x,matrix_y,m):
        global theta_0,theta_1
        cost = (1 / 2 * m) * ((theta_0 + (theta_1 * matrix_x) - matrix_y) ** 2).sum()
        return cost
    
    def gradDescent(alpha,matrix_x,matrix_y,num_iter=10000,eps=0.5):
        global theta_0,theta_1,m,cost
        cost = calculateCost(sat,gpa,m)
        cost_hist=[cost]
        for i in range(num_iter):
            theta_0 -= alpha * (1 / m) * (theta_0 + theta_1 * matrix_x - matrix_y).sum()
            theta_1 -= alpha * (1 / m) * (matrix_x.transpose().dot(theta_0 + theta_1 * matrix_x - matrix_y)).sum()
            cost = calculateCost(sat,gpa,m)
            cost_hist.append(cost)
            if cost<eps:
                return cost_hist
    
    if __name__=="__main__":
    
        print("init_cost==",cost)
        cost_hist=gradDescent(alpha,sat,gpa)
        print("final_cost,num_iters",cost,len(cost_hist))
        print(rand_b,theta_0,rand_a,theta_1)
        plt.plot(cost_hist,linewidth=5,color="r");plt.show()
    

    最后,编码风格本身虽然不对错误负责,但这里绝对是一个问题。通常,全局变量只是不好的做法。它们只会导致容易出错、无法维护的代码。最好将它们存储在小型数据结构中并将它们传递给函数。在您的情况下,您可以将初始参数放在一个列表中,将它们传递给您的梯度计算函数并在最后返回优化的参数。

    【讨论】:

    • 感谢您的帮助,我想我可能已经收敛了!不确定这是否是正确的实现。我将alpha 更改为3e-8
    • 我也修改了theta_0theta_1这样:temp_0 = theta_0 - alpha * (1 / m) * (theta_0 + theta_1 * matrix_x - matrix_y).sum() temp_1 = theta_1 - alpha * (1 / m) * (matrix_x.transpose().dot(theta_0 + theta_1 * matrix_x - matrix_y)).sum() theta_0 = temp_0 theta_1 = temp_1
    • 对了,eps代表什么?
    • @theasianmamba24 错误阈值。一旦您对收敛感到满意,您希望梯度下降停止,这是一种快速而肮脏的方式,类似于您最初的 cost&lt;1 条件。
    【解决方案2】:

    你错误地实现了成本函数:

    1 / 2 * m 被解释为m/2,你应该写1/2/m

    【讨论】:

    • 注意了,我刚刚改了。谢谢!
    猜你喜欢
    • 2020-04-28
    • 1970-01-01
    • 1970-01-01
    • 2015-02-18
    • 2019-01-31
    • 2013-06-21
    • 2017-07-17
    • 2023-03-12
    • 2021-11-16
    相关资源
    最近更新 更多