线性回归介绍及Python完整实现
线性回归通常是每个数据科学家遇到的第一个机器学习算法。这是一个简单的模型,但每个人都需要掌握它,因为它为其他机器学习算法奠定了基础。
哪里可以使用线性回归?
这是一种非常强大的技术,可以用来了解影响盈利能力的特征。它可以通过分析前几个月的销售数据来预测未来几个月的销售情况。它还可以用来获得关于客户行为的各种见解。在文章结束时,我们将构建一个如下图所示的模型,即确定最拟合数据的线。
什么是线性回归
线性回归模型的目标是找到一个或多个特征(自变量)和连续目标变量(因变量)之间的关系。当只有特征时,它被称为单变量线性回归,如果有多个特征,则称为多元线性回归。
线性回归的假设
线性回归模型可以由以下等式表示
- Y是预测值
- θ ₀是偏差项。
- θ ₁,...,θ ₙ是模型参数
- X ₁,X ₂,...,X ₙ是特征值。
上述假设也可以用
其中
- θ是模型的参数向量包括偏差项θ₀
- x是特征向量,x 0 = 1
数据集
让我们创建一些随机数据集来训练我们的机器学习模型,Python代码如下:
# imports import numpy as np import matplotlib.pyplot as plt # generate random data-set np.random.seed(0) x = np.random.rand(100, 1) y = 2 + 3 * x + np.random.rand(100, 1) # plot plt.scatter(x,y,s=10) plt.xlabel('x') plt.ylabel('y') plt.show()
使用上面Python代码生成的数据集的图如下所示:
训练线性回归模型
此处模型的训练意味着找到参数,以便模型最拟合数据。
我们如何确定最佳拟合线?
预测值与观测值之间的误差最小的直线称为最佳拟合直线或回归直线。这些误差也称为残差。残差可以通过从观测数据值到回归线的垂直线来可视化。
为了定义和测量模型的误差,我们将成本函数定义为残差平方和。成本函数
其中假设函数h(x)表示为
和m是在我们的数据组训练实例的总数。
为什么我们取残差的平方而不是残差的绝对值?我们想惩罚离回归线较远的点比靠近回归线的点要严厉得多。。
我们的目标是找到模型参数,使成本函数最小化。我们将使用Gradient Descent来找到它。
梯度下降
梯度下降是许多机器学习算法中使用的通用优化算法。它迭代地调整模型的参数,以最小化成本函数。梯度下降的步骤概述如下。
1.我们首先使用一些随机值初始化模型参数。这也称为随机初始化。
2.现在我们需要测量成本函数如何随参数的变化而变化。因此我们计算了成本函数的偏导数 w.r.t to the parameters θ₀, θ₁, … , θₙ
类似地,成本函数wrt对任何参数的偏导数可以表示为
我们可以一次计算所有参数的偏导数
其中h(x)是
3.计算导数后,我们更新下面给出的参数
其中α 是学习参数。
我们可以一次更新所有参数,
我们重复步骤2,3,直到成本函数收敛到最小值。 如果α的值太小,则成本函数需要更长的时间来收敛。如果α太大,则梯度下降可能超过最小值并且最终可能无法收敛。
为了演示梯度下降算法,我们用0初始化模型参数。方程变为Y = 0.梯度下降算法现在尝试更新参数的值, 以便我们到达最佳拟合线。
当学习速度非常慢时,梯度下降需要更长的时间来找到最佳拟合线。
当学习率正常时
当学习速率任意高时,梯度下降算法会保持超调最佳拟合线,甚至可能无法找到最佳线。
从头开始实现线性回归
下面给出了具有梯度下降的线性回归的Python完整实现。
# imports import numpy as np class LinearRegressionUsingGD: """Linear Regression Using Gradient Descent. Parameters ---------- eta : float Learning rate n_iterations : int No of passes over the training set Attributes ---------- w_ : weights/ after fitting the model cost_ : total error of the model after each iteration """ def __init__(self, eta=0.05, n_iterations=1000): self.eta = eta self.n_iterations = n_iterations def fit(self, x, y): """Fit the training data Parameters ---------- x : array-like, shape = [n_samples, n_features] Training samples y : array-like, shape = [n_samples, n_target_values] Target values Returns ------- self : object """ self.cost_ = [] self.w_ = np.zeros((x.shape[1], 1)) m = x.shape[0] for _ in range(self.n_iterations): y_pred = np.dot(x, self.w_) residuals = y_pred - y gradient_vector = np.dot(x.T, residuals) self.w_ -= (self.eta / m) * gradient_vector cost = np.sum((residuals ** 2)) / (2 * m) self.cost_.append(cost) return self def predict(self, x): """ Predicts the value after the model has been trained. Parameters ---------- x : array-like, shape = [n_samples, n_features] Test samples Returns ------- Predicted value """ return np.dot(x, self.w_)
模型参数如下
The coefficient is [2.89114079]
The intercept is [2.58109277]
最佳拟合线的图像
下面给出了成本函数与迭代次数的关系图。我们可以观察到,成本函数最初随着每次迭代而减小,并且最终在近100次迭代后收敛。
到目前为止,我们已经从头开始实施线性回归,并使用梯度下降来查找模型参数。但是我们的模型有多好呢?我们需要一些措施来计算模型的准确性。让我们看看各种指标来评估我们上面构建的机器学习模型。
评估机器学习模型的性能
我们将使用均方根误差(RMSE)和确定系数(R²分数)来评估我们的机器学习模型。
RMSE是残差平方和的平均值的平方根。
RMSE定义为
Python代码如下:
# mean squared error mse = np.sum((y_pred - y_actual)**2) # root mean squared error # m is the number of training examples rmse = np.sqrt(mse/m)
RMSE得分为2.764182038967211。
R²分数或确定系数通过使用最小二乘回归解释了因变量的总方差可以减少多少。
R²取决于
如果我们将观测值的平均值作为预测值,则 SSₜ是误差的总和。
SSᵣ 是残差平方的总和
Python代码如下
# sum of square of residuals ssr = np.sum((y_pred - y_actual)**2) # total sum of squares sst = np.sum((y_actual - np.mean(y_actual))**2) # R2 score r2_score = 1 - (ssr/sst)
SSₜ - 69.47588572871659
SSᵣ - 7.64070234454893
R² score - 0.8900236785122296
如果我们使用观测值的平均值作为预测值,则方差为69.47588572871659,如果我们使用回归,则总方差为7.64070234454893。通过使用回归,我们将预测误差减少了~ 89%。
现在让我们尝试使用流行的scikit-learn库实现线性回归。
Scikit-learn实现
sckit-learn是一个非常强大的数据科学库。完整的Python代码如下:
# imports import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, r2_score # generate random data-set np.random.seed(0) x = np.random.rand(100, 1) y = 2 + 3 * x + np.random.rand(100, 1) # sckit-learn implementation # Model initialization regression_model = LinearRegression() # Fit the data(train the model) regression_model.fit(x, y) # Predict y_predicted = regression_model.predict(x) # model evaluation rmse = mean_squared_error(y, y_predicted) r2 = r2_score(y, y_predicted) # printing values print('Slope:' ,regression_model.coef_) print('Intercept:', regression_model.intercept_) print('Root mean squared error: ', rmse) print('R2 score: ', r2) # plotting values # data points plt.scatter(x, y, s=10) plt.xlabel('x') plt.ylabel('y') # predicted values plt.plot(x, y_predicted, color='r') plt.show()
模型参数和模型的性能指标如下:
The coefficient is [[2.93655106]]
The intercept is [2.55808002]
Root mean squared error of the model is 0.07623324582875013.
R-squared score is 0.9038655568672764.
这与我们从头开始实施线性回归时的效果几乎相似。
结论
我们已经了解了线性回归和梯度下降的概念。我们也使用scikit-learn库实现了该模型。