梯度下降法溢出问题
来源:6-4 实现线性回归中的梯度下降法
MMXDH
2018-07-20
bobo老师您好,课程让我受益匪浅,感谢。我参照上课的练习在用梯度下降法处理波士顿房产数据这个多元线性回归问题的时候,运行出现了异常,一时搞不明白来请教。以下是代码(Pycharm环境)
def lossFunction(y, X_b, theta):
try:
return np.sum((y - X_b.dot(theta))**2)/len(X_b)
except:
return float("inf")
def dlossFunction(y, X_b, theta):
res = np.empty(len(theta)) #列向量
res[0] = np.sum(X_b.dot(theta) - y)
for i in range(1, len(theta)):
res[i] = np.sum((X_b.dot(theta) - y).T.dot(X_b[:,1]))
return res * 2. / len(X_b)
def gradientDescent(X_b, y, initial_theta, eta, n_iters=1e4, epsilon=1e-8):
theta = initial_theta
i_iter = 0
while i_iter < n_iters:
gradient = dlossFunction(y, X_b, theta)
last_theta = theta
theta = theta - eta * gradient
if abs(lossFunction(y, X_b, theta) - lossFunction(y, X_b, last_theta)) < epsilon:
break
i_iter += 1
return theta
if __name__ == "__main__":
bosten = datasets.load_boston()
X = bosten.data
y = bosten.target
X = X[y<50]
y = y[y<50]
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)
X_b = np.hstack([np.ones((len(X), 1)), X])
initial_theta = np.zeros(X_b.shape[1])
eta = 0.01
print(gradientDescent(X_b, y, initial_theta, eta))
运行结果:
E:/pycharm/workspace/gradient2.py:16: RuntimeWarning: overflow encountered in square
return np.sum((y - X_b.dot(theta))**2)/len(X_b)
E:/pycharm/workspace/gradient2.py:34: RuntimeWarning: invalid value encountered in double_scalars
if abs(lossFunction(y, X_b, theta) - lossFunction(y, X_b, last_theta)) < epsilon:
E:/pycharm/workspace/gradient2.py:25: RuntimeWarning: overflow encountered in multiply
return res * 2. / len(X_b)
[nan nan nan nan nan nan nan nan nan nan nan nan nan nan]
2回答
-
我没有验证你的程序是否正确。不管怎样,批量梯度下降法是可能有这个问题的。在课程的这里,主要是通过实验让大家理解什么是梯度下降法。在实际应用中,随机梯度下降法或者小批量梯度下降法更实用:)(课程后续会讲)
首先,你的运算结果溢出了,那么肯定是梯度下降法没有收敛,也就是eta太大了。要想得到收敛的结果,只能调小eta。但是调小eta,相应的搜索的次数就要调高,也就是n_iters要增大。由于在高维空间(虽然这个数据只有10几个特征),搜索过程需要考虑的维度过多,最终要找到合适的那个高维空间的点,n_iters需要非常非常大,才能得到正确的结果。(想象一下,对于10个维度,即使在每个维度走10步,整体都有10^10种可能,虽然这个数字不是梯度下降法真正的搜索方式,但是可以展示出维度变高以后对搜索的影响。其实也是维度灾难的一种表现:)
对于这种情况,建议:
1)首先对数据进行一下正规化,使用StandardScaler:)这样所有的特征都在同一尺度下,搜索起来不需要考虑各个维度步长不统一的问题;
2)使用随机梯度下降法,对于这种维度规模,批量梯度下降法已经不适用了。关于随机梯度下降法,这一章后续就会讲。
我尝试了一下使用课程中的随机梯度下降法的代码,使用1e5或者1e6次迭代,就能得到很好的效果:)
当然了,其实,在sklearn的内部实现,LinearRegression的非正规解,根本不是用梯度下降法求解的,而是使用最小二乘法。在这个课程中,由于我希望尽量降低数学门槛,没有介绍最小二乘法。而是使用计算机专业的同学都熟悉的“搜索策略”来解决这个问题。但是搜索的缺点就是性能低,尤其是对于线性回归这个数学性质极其突出的最优化问题来说:)如果有兴趣,也可以在网上搜索一下最小二乘法的基本原理,甚至实现一下试试看:)
最后,这不意味着梯度下降法没有用!事实上,梯度下降法的思想极其有用。只不过因为线性回归问题数学性质太突出了,所以可以使用各种数学方式快速求解。但是稍微复杂一些的机器学习算法,本质都要使用梯度下降法。只不过对于维度非常高的情况,应该选择随机梯度下降法或者小批量梯度下降法而已:)
加油!
012018-07-20 -
MMXDH
提问者
2018-07-20
老师,我想是这个eta和n_iters取的有问题,eta应该是取大了,n_iters取小了,但我改这倆超参数,发现跟正规方程解还是对不上,并且求出来的参数除了theta0其它13个参数都一样,感谢答疑
00
相似问题