使用 numpy 实现线性回归

Implementing Linear Regression using numpy

我正在尝试学习线性方程 y = x1 + x2 + e,其中 e 是 0 到 0.5 之间的随机误差。 数据定义如下:

X1 = np.random.randint(1, 10000, 5000)
X2 = np.random.randint(1, 10000, 5000)
e = np.array([random.uniform(0, 0.5) for i in range(5000)])
y = X1 + X2 + e

当我实现一个简单的梯度下降来寻找参数时,损失和梯度都在爆炸。我哪里错了?梯度下降的代码:

w1, w2, b = 1, 1, 0
n = X1.shape[0]
alpha = 0.01
for i in range(5):
    y_pred = w1 * X1 + w2 * X2 + b
    L = np.sum(np.square(y - y_pred))/(2 * n)
    dL_dw1 = (-1/n) * np.sum((y - y_pred) * X1)
    dL_dw2 = (-1/n) * np.sum((y - y_pred) * X2)
    dL_db = (-1/n) * np.sum((y - y_pred))
    w1 = w1 - alpha * dL_dw1
    w2 = w2 - alpha * dL_dw2
    b = b - alpha * dL_db
    print(L, w1, w2, b)

这个输出是:

0.042928723015982384 ,  13.7023102434034 ,  13.670617201430483 ,  0.00254938447277222 

9291487188.8259 ,  -7353857.489486973 ,  -7293941.123714662 ,  -1261.9252592161051 

3.096713445664372e+21 ,  4247172241132.3584 ,  4209117175658.749 ,  728518135.2857293 

1.0320897597938595e+33 ,  -2.4520737800716524e+18 ,  -2.4298158059267333e+18 ,  -420579738783719.2 

3.4398058610314825e+44 ,  1.415615899689713e+24 ,  1.402742160404974e+24 ,  2.428043942370682e+20 

好的,问题的表述有一些问题

  1. 缩放:梯度下降通常需要对变量进行很好的缩放,以确保可以正确设置 alpha。在大多数情况下,一切都是相对的,你总是可以将一个问题乘以一个固定的常数。然而,因为权重直接由 alpha 值操纵,所以很难达到非常高或非常低的权重值,我特此将您的机制缩小约 10000,并将随机误差减少到 scale
import numpy as np
import random
X1 = np.random.random(5000)
X2 = np.random.random(5000)
e = np.array([random.uniform(0, 0.0005) for i in range(5000)])
y = X1 + X2 + e
  1. y_pred 对 b 的依赖性:B 的值 我不确定它应该做什么以及为什么要明确向 y_pred 引入错误。您的预测应该假设没有错误:D

  2. 如果 X 和 Y 缩放得很好,使用超参数尝试几次会产生一个好的值

for i in range(5):
    y_pred = w1 * X1 + w2 * X2
    L = np.sum(np.square(y - y_pred))/(2 * n)
    dL_dw1 = -(1/n) * np.sum((y - y_pred) * X1)
    dL_dw2 = -(1/n) * np.sum((y - y_pred) * X2)
    dL_db = -(1/n) * np.sum((y - y_pred))
    w1 = w1 - alpha * dL_dw1
    w2 = w2 - alpha * dL_dw2
    print(L, w1, w2)
    

您可以尝试使用这些值,但它们会收敛

w1, w2, b = 1.1, 0.9, 0.01
alpha = 1
0.0008532534726479387 1.0911950693892498 0.9082610891021278
0.0007137567968828647 1.0833134985852988 0.9159869797801239
0.0005971536415151483 1.0761750602775175 0.9231234590515701
0.0004996145120126794 1.0696746682185534 0.9296797694772246
0.0004180103133293466 1.0637407602096771 0.9356885401106588

您所缺少的只是数据规范化。对于基于梯度的学习算法,您必须确保数据已标准化,即它具有 mean=0std=1.

让我们通过一个恒定的错误来验证这一点(比如 e=33)。

X1 = np.random.randint(1, 10000, 5000)
X2 = np.random.randint(1, 10000, 5000)
e = 33

# Normalize data
X1 = (X1 - np.mean(X1))/np.std(X1)
X2 = (X2 - np.mean(X2))/np.std(X2)

y = X1 + X2 + e


w1, w2, b = np.random.rand(), np.random.rand(), np.random.rand()

n = X1.shape[0]
alpha = 0.01
for i in range(1000):
    y_pred = w1 * X1 + w2 * X2 + b
    L = np.sum(np.square(y - y_pred))/(2 * n)
    dL_dw1 = (-1/n) * np.sum((y - y_pred) * X1)
    dL_dw2 = (-1/n) * np.sum((y - y_pred) * X2)
    dL_db = (-1/n) * np.sum((y - y_pred))
    w1 = w1 - alpha * dL_dw1
    w2 = w2 - alpha * dL_dw2
    b = b - alpha * dL_db
    
    if (i)%100 == 0:
        print(L)
    
print (w1, w2, b)

输出:

Loss: 517.7575710514508
Loss: 69.36601211594098
Loss: 9.29326322560041
Loss: 1.2450619081931993
Loss: 0.16680720657514425
Loss: 0.022348057963833764
Loss: 0.002994096883392299
Loss: 0.0004011372165515275
Loss: 5.374289796164062e-05
Loss: 7.2002934167549005e-06
0.9999609731610163 0.9999911458582055 32.99861157362915

如您所见,它确实收敛了。

除了必须规范化数据外,您的代码没有任何问题。

现在您可以补回错误并找到可能的最佳估计值。