我按照教程创建了一个线性回归算法,并将其应用于提供的数据集,结果运行良好。然而,同样的算法在另一个相似的数据集上却无法正常工作。能有人告诉我这是为什么吗?
def computeCost(X, y, theta): inner = np.power(((X * theta.T) - y), 2) return np.sum(inner) / (2 * len(X))def gradientDescent(X, y, theta, alpha, iters): temp = np.matrix(np.zeros(theta.shape)) params = int(theta.ravel().shape[1]) cost = np.zeros(iters) for i in range(iters): err = (X * theta.T) - y for j in range(params): term = np.multiply(err, X[:,j]) temp[0, j] = theta[0, j] - ((alpha / len(X)) * np.sum(term)) theta = temp cost[i] = computeCost(X, y, theta) return theta, costalpha = 0.01iters = 1000g, cost = gradientDescent(X, y, theta, alpha, iters) print(g)
当我使用这个数据集运行算法时,输出为matrix([[ nan, nan]])
,并出现以下错误:
C:\Anaconda3\lib\site-packages\ipykernel\__main__.py:2: RuntimeWarning: overflow encountered in power from ipykernel import kernelapp as appC:\Anaconda3\lib\site-packages\ipykernel\__main__.py:11: RuntimeWarning: invalid value encountered in double_scalars
然而,这个数据集运行正常,输出为matrix([[-3.24140214, 1.1272942 ]])
这两个数据集非常相似,我已经多次检查但始终无法找出为什么在其中一个数据集上有效,而在另一个上却无效。欢迎任何帮助。
编辑:感谢@人名提供的编辑建议 🙂
回答:
[顺便说一句,这是一个更好的问题]
很难确切知道这里发生了什么,但基本上你的成本函数在错误的方向上螺旋上升,最终导致你在尝试平方值时发生溢出。
我认为在你的情况下,问题归结于你的步长(alpha)太大,这可能导致梯度下降朝错误的方向前进。你需要在梯度下降中监控成本,确保它始终在下降,如果没有下降,要么是代码有问题,要么是alpha
值太大。
就我个人而言,我会重新评估代码,并尝试去掉循环。这取决于个人偏好,但我发现以列向量的形式处理X
和Y
更容易。这里是一个最小的示例:
from numpy import genfromtxt# 这是你从GitHub上获取的'坏'数据集my_data = genfromtxt('testdata.csv', delimiter=',')def computeCost(X, y, theta): inner = np.power(((X @ theta.T) - y), 2) return np.sum(inner) / (2 * len(X))def gradientDescent(X, y, theta, alpha, iters): for i in range(iters): # 你不需要额外的循环 - 这可以向量化 # 使其更快更简单 theta = theta - (alpha/len(X)) * np.sum((X @ theta.T - y) * X, axis=0) cost = computeCost(X, y, theta) if i % 10 == 0: # 每十次循环查看一次成本以便调试 print(cost) return (theta, cost)# 注意较小的alpha值alpha = 0.0001iters = 100# 这里x是列X = my_data[:, 0].reshape(-1,1)ones = np.ones([X.shape[0], 1])X = np.hstack([ones, X]) # theta是一个行向量theta = np.array([[1.0, 1.0]])# y是一个列向量y = my_data[:, 1].reshape(-1,1)g, cost = gradientDescent(X, y, theta, alpha, iters) print(g, cost)
另一个有用的技术是在进行回归之前对数据进行归一化。这在你有多个需要最小化的特征时尤其有用。
顺便提一下,如果你的步长设置正确,无论你进行多少次迭代,都不应该发生溢出,因为每次迭代成本都会降低,且降低的速度会减慢。
经过1000次迭代,我得到了theta和成本值为:
[[ 1.03533399 1.45914293]] 56.041973778
经过100次迭代:
[[ 1.01166889 1.45960806]] 56.0481988054
你可以使用这个在iPython笔记本中查看拟合情况:
%matplotlib inlineimport matplotlib.pyplot as pltplt.scatter(my_data[:, 0].reshape(-1,1), y)axes = plt.gca()x_vals = np.array(axes.get_xlim())y_vals = g[0][0] + g[0][1]* x_valsplt.plot(x_vals, y_vals, '--')