请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

梯度下降法溢出问题

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回答

liuyubobobo 2018-07-20 16:42:40

我没有验证你的程序是否正确。不管怎样,批量梯度下降法是可能有这个问题的。在课程的这里,主要是通过实验让大家理解什么是梯度下降法。在实际应用中,随机梯度下降法或者小批量梯度下降法更实用:)(课程后续会讲)


首先,你的运算结果溢出了,那么肯定是梯度下降法没有收敛,也就是eta太大了。要想得到收敛的结果,只能调小eta。但是调小eta,相应的搜索的次数就要调高,也就是n_iters要增大。由于在高维空间(虽然这个数据只有10几个特征),搜索过程需要考虑的维度过多,最终要找到合适的那个高维空间的点,n_iters需要非常非常大,才能得到正确的结果。(想象一下,对于10个维度,即使在每个维度走10步,整体都有10^10种可能,虽然这个数字不是梯度下降法真正的搜索方式,但是可以展示出维度变高以后对搜索的影响。其实也是维度灾难的一种表现:)


对于这种情况,建议:

1)首先对数据进行一下正规化,使用StandardScaler:)这样所有的特征都在同一尺度下,搜索起来不需要考虑各个维度步长不统一的问题;

2)使用随机梯度下降法,对于这种维度规模,批量梯度下降法已经不适用了。关于随机梯度下降法,这一章后续就会讲。


我尝试了一下使用课程中的随机梯度下降法的代码,使用1e5或者1e6次迭代,就能得到很好的效果:)


当然了,其实,在sklearn的内部实现,LinearRegression的非正规解,根本不是用梯度下降法求解的,而是使用最小二乘法。在这个课程中,由于我希望尽量降低数学门槛,没有介绍最小二乘法。而是使用计算机专业的同学都熟悉的“搜索策略”来解决这个问题。但是搜索的缺点就是性能低,尤其是对于线性回归这个数学性质极其突出的最优化问题来说:)如果有兴趣,也可以在网上搜索一下最小二乘法的基本原理,甚至实现一下试试看:)


最后,这不意味着梯度下降法没有用!事实上,梯度下降法的思想极其有用。只不过因为线性回归问题数学性质太突出了,所以可以使用各种数学方式快速求解。但是稍微复杂一些的机器学习算法,本质都要使用梯度下降法。只不过对于维度非常高的情况,应该选择随机梯度下降法或者小批量梯度下降法而已:)


加油!


0 回复 有任何疑惑可以回复我~
  • 提问者 MMXDH #1
    了解,谢谢bobo老师
    回复 有任何疑惑可以回复我~ 2018-07-20 16:50:10
提问者 MMXDH 2018-07-20 11:38:45

老师,我想是这个eta和n_iters取的有问题,eta应该是取大了,n_iters取小了,但我改这倆超参数,发现跟正规方程解还是对不上,并且求出来的参数除了theta0其它13个参数都一样,感谢答疑

0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信