为什么 sklearn 中的 SGDRegressor 函数无法收敛到正确的最优值?

Why the SGDRegressor function in sklearn can't converge to the correct optima?

我在sklearn中练习使用SGDRegressor,但遇到了一些问题,我将其简化为以下代码。

import numpy as np
from sklearn.linear_model import SGDRegressor

X = np.array([0,0.5,1]).reshape((3,1))
y = np.array([0,0.5,1]).reshape((3,1))

sgd = SGDRegressor()  
sgd.fit(X, y.ravel())

print("intercept=", sgd.intercept_)
print("coef=", sgd.coef_)

这是输出:

intercept= [0.19835632]
coef= [0.18652387]

所有的输出都在intercept=0.19和coef=0.18左右,但显然正确答案是intercept=0coef=1。 即使在这个简单的例子中,程序也无法得到参数的正确解。我想知道我哪里弄错了。

SGD(随机梯度下降)用于大规模数据。对于如此微不足道的数量,我建议您改用简单的线性回归。正如“没有免费的午餐定理”所述,没有一种模型适合所有解决方案,因此您应该经常试验不同的模型以找到最佳模型(但是您还应该了解数据的背景,例如分布类型,多样性因素、偏度等)。请查看以下模型:

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X,y.ravel())
lr.predict([[0],[0.5],[1]])
# output -> array([1.11022302e-16, 5.00000000e-01, 1.00000000e+00])

使用 n=10000 个数据点(从您的 3 个原始点中抽取样本并进行替换),您将使用 SGD

获得以下结果
n = 10000

X = np.random.choice([0,0.5,1], n, replace=True)
y = X

X = X.reshape((n,1))

sgd = SGDRegressor(verbose=1)  
sgd.fit(X, y)

# -- Epoch 1
# Norm: 0.86, NNZs: 1, Bias: 0.076159, T: 10000, Avg. loss: 0.012120
# Total training time: 0.04 seconds.
# -- Epoch 2
# Norm: 0.96, NNZs: 1, Bias: 0.024337, T: 20000, Avg. loss: 0.000586
# Total training time: 0.04 seconds.
# -- Epoch 3
# Norm: 0.98, NNZs: 1, Bias: 0.008826, T: 30000, Avg. loss: 0.000065
# Total training time: 0.04 seconds.
# -- Epoch 4
# Norm: 0.99, NNZs: 1, Bias: 0.003617, T: 40000, Avg. loss: 0.000010
# Total training time: 0.04 seconds.
# -- Epoch 5
# Norm: 1.00, NNZs: 1, Bias: 0.001686, T: 50000, Avg. loss: 0.000002
# Total training time: 0.05 seconds.
# -- Epoch 6
# Norm: 1.00, NNZs: 1, Bias: 0.000911, T: 60000, Avg. loss: 0.000000
# Total training time: 0.05 seconds.
# -- Epoch 7
# Norm: 1.00, NNZs: 1, Bias: 0.000570, T: 70000, Avg. loss: 0.000000
# Total training time: 0.05 seconds.
# Convergence after 7 epochs took 0.05 seconds

print("intercept=", sgd.intercept_)
print("coef=", sgd.coef_)
# intercept= [0.00057032]
# coef= [0.99892893]

plt.plot(X, y, 'r.')
plt.plot(X, sgd.intercept_ + sgd.coef_*X, 'b-')

下面的动画展示了在上述代码中随着 n 的增加,SGD 回归器如何开始收敛到正确的最优值: