线性回归梯度下降实现问题

我正在参加Coursera上的这门课程,学习机器学习/线性回归。他们描述用于求解估计OLS系数的梯度下降算法如下:

enter image description here

他们使用w表示系数,H表示设计矩阵(或他们称之为特征),y表示因变量。他们的收敛标准是RSS梯度的范数小于容差epsilon;也就是说,他们定义的“未收敛”是:

enter image description here

我无法使这个算法收敛,想知道我的实现中是否遗漏了什么。以下是我的代码。请注意,我还将我使用的样本数据集(df)通过了statsmodels回归库,只是为了确认回归可以收敛,并获取系数值以进行对比。确实可以,并且它们是:

Intercept    4.344435x1           4.387702x2           0.450958

这是我的实现。在每次迭代时,它会打印RSS梯度的范数:

import numpy as npimport numpy.linalg as LAimport pandas as pdfrom pandas import DataFrame# 首先定义grad函数:grad(RSS) = -2H'(y-Hw)def grad_rss(df, var_name_y, var_names_h, w):    # 设置特征矩阵H    H = DataFrame({"Intercept" : [1 for i in range(0,len(df))]})    for var_name_h in var_names_h:        H[var_name_h] = df[var_name_h]    # 设置y向量    y = df[var_name_y]    # 计算RSS的梯度: -2H'(y - Hw)    result = -2 * np.transpose(H.values) @ (y.values - H.values @ w)    return resultdef ols_gradient_descent(df, var_name_y, var_names_h, epsilon = 0.0001, eta = 0.05):    # 将所有初始w值设置为0.0001(与我们的epsilon选择无关)    w = np.array([0.0001 for i in range(0, len(var_names_h) + 1)])    # 迭代计数器    t = 0    # 基本算法:持续从w中减去eta * grad(RSS),直到    # ||grad(RSS)|| < epsilon。    while True:        t = t + 1        grad = grad_rss(df, var_name_y, var_names_h, w)        norm_grad = LA.norm(grad)        if norm_grad < epsilon:            break        else:            print("{} : {}".format(t, norm_grad))            w = w - eta * grad            if t > 10:                raise Exception ("未能收敛")    return w# ########################################## df = DataFrame({        "y" : [20,40,60,80,100] ,        "x1" : [1,5,7,9,11] ,        "x2" : [23,29,60,85,99]             })# 运行ols_gradient_descent(df, "y", ["x1", "x2"])

遗憾的是,这没有收敛,实际上每次迭代都会打印一个爆炸的范数:

1 : 44114.315060513332 : 98203544.030678123 : 218612547944.953864 : 486657040646682.95 : 1.083355358314664e+186 : 2.411675439503567e+217 : 5.368670935963926e+248 : 1.1951287949674022e+289 : 2.660496151835357e+3110 : 5.922574875391406e+3411 : 1.3184342751414824e+38---------------------------------------------------------------------------Exception                                 Traceback (most recent call last)......Exception: 未能收敛

如果我将最大迭代次数增加到足够多,它不会收敛,而是会爆炸到无穷大。

这里是否有实现错误,或者我是否误解了课程笔记中的解释?

更新及答案

正如@Kant建议的,每次迭代都需要更新eta。课程本身提供了一些用于此的示例公式,但这些公式都没有帮助算法收敛。维基百科关于梯度下降的这一部分提到了Barzilai-Borwein方法作为更新eta的好方法。我实现了它,并修改了我的代码以在每次迭代时使用它来更新eta,回归成功收敛了。以下是我将维基百科版本的公式翻译成回归中使用的变量,以及实现它的代码。同样,这段代码在我的原始ols_gradient_descent循环中被调用以更新eta

enter image description here

def eta_t (w_t, w_t_minus_1, grad_t, grad_t_minus_1):    delta_w = w_t - w_t_minus_1    delta_grad = grad_t - grad_t_minus_1    eta_t = (delta_w.T @ delta_grad) / (LA.norm(delta_grad))**2    return eta_t

回答:

尝试降低eta的值。如果eta过高,梯度下降可能会发散。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注