使用NumPy进行LMS批量梯度下降

时间:2017-05-29 19:40:55

标签: python numpy linear-regression least-squares gradient-descent

我正在尝试编写一些非常简单的LMS批量梯度下降,但我相信我对渐变做错了。对于theta的元素,theta的数量级与初始值之间的比率非常不同,因此theta[2]不会移动(例如,如果alpha = 1e-8)或theta[1]开枪(例如,如果alpha = .01)。

import numpy as np

y = np.array([[400], [330], [369], [232], [540]])
x = np.array([[2104,3], [1600,3], [2400,3], [1416,2], [3000,4]])
x = np.concatenate((np.ones((5,1), dtype=np.int), x), axis=1)
theta = np.array([[0.], [.1], [50.]])
alpha = .01

for i in range(1,1000):
    h = np.dot(x, theta)
    gradient = np.sum((h - y) * x, axis=0, keepdims=True).transpose()
    theta -= alpha * gradient
    print ((h - y)**2).sum(), theta.squeeze().tolist()

1 个答案:

答案 0 :(得分:1)

编写的算法是完全正确的,但没有特征缩放,收敛将非常缓慢,因为一个特征将控制梯度计算。

您可以通过各种方式执行缩放;现在,让我们按照L ^ 1规范来缩放特征,因为它很简单

import numpy as np
y = np.array([[400], [330], [369], [232], [540]])
x_orig = np.array([[2104,3], [1600,3], [2400,3], [1416,2], [3000,4]])
x_orig = np.concatenate((np.ones((5,1), dtype=np.int), x_orig), axis=1)
x_norm = np.sum(x_orig, axis=0)
x = x_orig / x_norm

也就是说,x中每列的总和为1.如果您想保持对正确参数的良好猜测,则必须相应地缩放这些参数。

theta = (x_norm*[0., .1, 50.]).reshape(3, 1)

有了这个,我们可以像你原来的帖子那样继续进行,在那里你必须再次学习学习率,直到找到最佳位置。

alpha = .1
for i in range(1, 100000):
    h = np.dot(x, theta)
    gradient = np.sum((h - y) * x, axis=0, keepdims=True).transpose()
    theta -= alpha * gradient

让我们看看我们现在得到的东西,我们已经找到了似乎收敛的东西。同样,您的参数必须缩放以与原始未缩放的特征相关联。

print (((h - y)**2).sum(), theta.squeeze()/x_norm)
# Prints 1444.14443271 [ -7.04344646e+01   6.38435468e-02   1.03435881e+02]

此时,让我们作弊并检查我们的结果

theta, error, _, _ = np.linalg.lstsq(x_orig, y)
print(error, theta)
# Prints [ 1444.1444327] [[ -7.04346018e+01]
#                         [  6.38433756e-02]
#                         [  1.03436047e+02]]

关于特征缩放的一般介绍性参考是this Stanford lecture