为什么梯度下降在优化多项式回归方面如此糟糕?

机器算法验证 回归 机器学习 scikit-学习 梯度下降 统计模型
2022-04-04 07:25:55

作为自学练习的一部分,我正在比较多项式回归的各种实现:

  • 封闭式解决方案
  • 使用 Numpy 进行梯度下降
  • Scipy优化
  • 学习
  • 统计模型

当问题涉及 3 次或更小的多项式时,没问题,所有三种方法都会产生相同的系数。但是,当阶数增加到 5、10 甚至 15 阶时,我发现使用我的numpyscipy.optimize实现无法找到正确的最小值。

问题:

为什么梯度下降,在一定程度上是 scipy.optimize 算法,优化多项式回归如此糟糕?

这是因为成本函数是非凸的吗?不光滑 ?由于数值不稳定性或共线性?

例子

在我的模型中,只有一个变量,设计矩阵采用以下形式1,x,x2,x3,...,xn. 数据基于具有均匀噪声的正弦函数。

#Initializing noisy non linear data
x = np.linspace(0,1,40)
noise = 1*np.random.uniform(  size = 40)
y = np.sin(x * 1.5* np.pi ) 
y_noise = (y + noise-1).reshape(-1,1)

嘈杂的正弦波

多项式阶 3

  • 封闭式解决方案(XTX)1XTy=[0.0710.1420,159.1]
  • Numpy梯度下降相同的系数,50,000次迭代和步长= 1
  • Scipy使用 BFGS 方法和一阶导数(梯度)优化相同的系数
  • Sklearn:相同的系数
  • Statsmodel:相同的系数

多项式阶数 5

  • 封闭式解决方案(XTX)1XTy=[0.655.8217.8229.1035.2517.08]
  • Numpy 梯度下降具有 50,000 次迭代和步长 = 1 的较小系数:[0.713.985.23.230.083.44]
  • Scipy 优化还有更小的系数,与 Numpy 实现的顺序相同。使用 BFGS 方法和一阶导数(梯度):[0.704.145.832.730.183.09]
  • Sklearn:同解析解
  • Statsmodel : 同解析解

多项式阶 16+

所有方法都给出不同的结果。

由于问题已经很长了,您将在此处找到代码

2个回答

感谢您的回复,在调查了成本函数的形状和梯度下降算法的行为之后,这是我的发现(这不会让任何人感到惊讶,但一些自学者可能会发现这很有用)

1)成本函数呈现出一个非常“平坦”的底部

绘制不同多项式阶数和步长的成本函数的收敛曲线表明,梯度下降算法起初收敛非常快,然后显着减慢。这是一个情节X=[X,X2]但是对于更高的订单行为是相同的

情节收敛

我的直觉是,当成本函数平坦时自动增加步长的梯度下降算法会表现得更好。

2)由于成本函数看起来像一个平坦的山谷,所以起点很重要

事实上,初始化在[0,0]这不是一个特别好的主意,因为该值已经非常接近谷底了。因此梯度下降很难达到全局最小值。

谷

以随机值初始化并比较结果将改善这一点

3)Scipy.optimize 算法做得很好

'BFGS' 算法实际上非常擅长寻找全局最小值。问题是默认容差值太大,算法在达到全局最小值之前终止。设置选项:'gtol': 1e-10导致数百次迭代收敛(仅基于一阶导数)

4) 数值不稳定

确实正如@Jonny Lomond 暗示的那样,非常小X值导致高阶多项式的极值,所以我截断了接近零的值。这改进了多项式 15 阶及以上的算法的行为

代码在这里

这是因为成本函数是非凸的吗?不光滑 ?由于数值不稳定性或共线性?

这似乎是具有平方和损失函数的简单线性回归。如果您能够获得封闭形式的解决方案(即XX是可逆的),那么损失函数既是凸的又是连续可微的(平滑的)。( 1 , 2 )

为什么梯度下降,在一定程度上是 scipy.optimize 算法,优化多项式回归如此糟糕?

众所周知,梯度下降既慢(与二阶导数方法相比)又对步长敏感。我还想支持@Sycorax 和@Jonny Lomond 在评论中的内容——这个特殊问题对于 GD 来说是一个困难的问题,因为您的尺寸存在巨大的量级差异,而​​且您的封闭形式解决方案也可能不稳定。 这个链接有一些关于优化挑战和基于动量的解决方案的非常棒的材料,包括多项式回归示例。

您可能会考虑的几种方法:

  1. 正如@Jonny Lomond 建议的那样,分别标准化每个多项式,或调整步长。
  2. 在迭代中绘制您的损失函数,以确定您的优化是否存在任何明显的问题。如果您的梯度“过冲”,您可以尝试使用自适应步长(根据迭代次数减少它)。
  3. 使用回溯在每次迭代时动态确定更好的步长。
  4. 使用基于动量的梯度方法,例如Nesterov 加速梯度下降这些方法在实践中几乎与二阶方法一样快(在收敛方面)。