我目前正在用Python编写单变量线性回归的实现:
# implementation of univariate linear regressionimport numpy as npdef cost_function(hypothesis, y, m): return (1 / (2 * m)) * ((hypothesis - y) ** 2).sum()def hypothesis(X, theta): return X.dot(theta)def gradient_descent(X, y, theta, m, alpha): for i in range(1500): temp1 = theta[0][0] - alpha * (1 / m) * (hypothesis(X, theta) - y).sum() temp2 = theta[1][0] - alpha * (1 / m) * ((hypothesis(X, theta) - y) * X[:, 1]).sum() theta[0][0] = temp1 theta[1][0] = temp2 return thetaif __name__ == '__main__': data = np.loadtxt('data.txt', delimiter=',') y = data[:, 1] m = y.size X = np.ones(shape=(m, 2)) X[:, 1] = data[:, 0] theta = np.zeros(shape=(2, 1)) alpha = 0.01 print(gradient_descent(X, y, theta, m, alpha))
这段代码会在theta值趋于无穷大后输出NaN,我无法找出问题所在,但肯定与我在梯度下降函数中对theta的更改有关。
我使用的数据是从网上获取的一个简单的线性回归对数据集,并且数据加载正确。
有人能指导我解决这个问题吗?
回答:
你遇到的问题是,当你使用X[:,1]
或data[:,1]
时,你得到的是形状为(m,)的对象。当你将形状为(m,)的对象与形状为(m,1)的矩阵相乘时,你会得到一个大小为(m,m)的矩阵
a = np.array([1,2,3])b = np.array([[4],[5],[6]])(a*b).shape #prints (3,3)
如果你在if __name__
块中执行y=y.reshape((m,1))
,并在你的gradient_descent
函数中执行
X_1 = X[:,1].reshape((m,1))
应该可以解决这个问题。目前的情况是,当你执行
((hypothesis(X, theta) - y) * X[:, 1])
你得到的是一个100乘100的矩阵,这不是你想要的。
我用于测试的完整代码是:
# implementation of univariate linear regressionimport numpy as npdef cost_function(hypothesis, y, m): return (1 / (2 * m)) * ((hypothesis - y) ** 2).sum()def hypothesis(X, theta): return X.dot(theta)def gradient_descent(X, y, theta, m, alpha): X_1 = X[:,1] X_1 = X_1.reshape((m,1)) for i in range(1500): temp1 = theta[0][0] - alpha * (1 / m) * (hypothesis(X, theta) - y).sum() temp2 = theta[1][0] - alpha * (1 / m) * ((hypothesis(X, theta) - y) * X_1).sum() theta[0][0] = temp1 theta[1][0] = temp2 return thetaif __name__ == '__main__': data= np.random.normal(size=(100,2)) y = 30*data[:,0] + data[:, 1] m = y.size X = np.ones(shape=(m, 2)) y = y.reshape((m,1)) X[:, 1] = data[:, 0] theta = np.zeros(shape=(2, 1)) alpha = 0.01 print(gradient_descent(X, y, theta, m, alpha))