python 中从头开始的梯度下降不起作用

Gradient descent from scratch in python not working

我正在尝试在 python 中从头开始实现梯度下降算法,这应该相当容易。然而,我现在一直在用我的代码挠头,无法让它工作。

我生成的数据如下:

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('darkgrid')

#Defining the x array. 
x=np.array(range(1,100)) 

#Defining the y array. 
y=10+2*x.ravel() 
y=y+np.random.normal(loc=0, scale=70, size=99)

然后定义参数:

alpha = 0.01  # Which will be the learning rate
NbrIter = 100  # Representing the number of iteration
m = len(y)
theta = np.random.randn(2,1)

我的GD如下:

for iter in range(NbrIter):
    theta = theta - (1/m) * alpha * ( X.T @ ((X @ theta) - y) )

我得到的是一个巨大的矩阵,这意味着我的线性代数有些问题。但是,我实在是看不出问题出在哪里。

(玩弄矩阵试图让它们匹配我达到了具有正确形式(2x1)的theta: theta = theta - (1/m) * alpha * ( X.T @ ((X @ theta).T - y).T ) 但它看起来确实不对,实际值相差甚远(数组([[-8.92647663e+148], [-5.92079000e+150]])) )

我猜你是被广播击中了。变量 y 的形状是 (100,)。当从 X.T@X@theta 的结果中减去 y 时。 Theta 是列向量,所以我猜结果是列向量。变量 y 被广播到形状为 (1,100) 的 row 向量。减法的结果是(100,100)。使用 y.reshape(-1,1)

将此重塑 y 修复为列向量

现在,一些优化:

X.T @ ((X @ theta) - y[:,None])

可以改写为:

(X.T@X) @ theta - (X.T*y[:,None])

成本最高的计算可以从循环中取出:

XtX = X.T@X
Xty = X.T*y[:,None]

for iter in range(NbrIter):
    theta = theta - (1/m) * alpha * (XtX @ theta - Xty)

现在您在 2x2 矩阵而不是 100x2 矩阵上操作。

让我们来看看收敛。 假设 X 的构造如下:X=np.column_stack((x, np.ones_like(x)) 可以检查矩阵条件:

np.linalg.cond(XtX)

产生了: 13475.851490419038

表示最小特征向量和最大特征向量之比约为13k。因此,使用大于 1/13k 的 alpha 可能会导致收敛不良。

如果您使用 alpha=1e-5,算法将会收敛。 祝你好运!