学习机器学习的第一个模型是线性回归。除了作为一个简单的理解算法,结合正确的特征,还可以是一个强大的预测模型。
在本文中,我们将在Python中构建一个线性回归模型,并应用梯度下降的优化技术来降低成本函数。
以下是我们将要讨论的主题:
- 线性回归:模型的解释和概念;
- 梯度下降:关于GD及其变化的解释;
- 代码实现:通过编写Python代码来演示学习的概念;
线性回归
线性回归是一种基本的预测算法,能够找到两个或多个变量之间的关系,模型基本上调整了观察到的数据之间的线性方程。在线性回归中,我们有输入变量(x)和输出变量(y)。当x是模型中的唯一变量时,我们称之为简单线性回归,当有多个输入时,我们称之为多元线性回归。
在试图将线性模型拟合到数据之前,必须确定变量之间是否存在关系。散点图可以是显示元素分布的绝佳工具。
线性回归的例证
模型表示
简单线性回归是以下形式的公式:
- Y - 预测值;
- β0 -偏差系数,该系数允许模型具有额外的自由度;
- β1 -称为比例因子;
- X -特征的值;
同样的概念也适用于多线性回归,但有更多的变量。
梯度下降
梯度下降是一种通用的优化算法,能够找到一种方法来最小化成本函数。我们使用成本函数来查找模型预测中的错误。因此,最小化意味着在预测值中有较小的误差范围。
该技术通过将输入变量的权重转换为与数据集的每个交互的小部分来工作。
一个重要的参数是算法将作为基础的步骤的大小,称为“学习速率”。如果学习速率很小,算法将不得不经历许多交互并花费更多时间来收敛。否则,如果它太大,算法可能会跳过最小点。
梯度下降的例子
梯度下降有三种变体:
- 批量梯度下降;
- 随机梯度下降;
- 小批量梯度下降;
算法的变化和不同的交互直到最小点
在应用任何这些算法变体之前,重要的是执行数据的预处理,即将所有特征放在相同的比例中,否则优化可能不具有预期的结果。
简而言之,在机器学习中,我们使用梯度下降来改进模型的参数。
使用哪种变体?
让我们使用批量梯度下降算法来最小化我们的成本函数。
批量梯度下降在使用每个交互中的整个数据集计算梯度时构成,同时更新参数。因此,对于每次互动,我们都要加上所有的例子。
为了检查变化之间的差异,我建议查看一下批量梯度下降和随机梯度下降之间的差异(这里略过)。
使用Python实现代码
让我们使用一个数据集,其中包含不同动物种类的平均大脑和体重。该数据集是在1990年左右为线性回归实践创建的。
数据集包含以下列:
- 动物:动物种类;
- 体重:体重;
- 脑重:脑重 ;
让我们首先导入此任务所需的库。
import numpy as npimport pandas as pdimport matplotlib.pyplot as plt%matplotlib inline
数据可视化
目标是在考虑身体重量的情况下预测大脑的重量,因此通常我们可以看到变量的相关性。
data = pd.read_excel('animals-weight.xlsx')data.corr()
这两个变量是完全相关的,所以它们之间存在依赖关系。
让我们创建一个散点图并检查数据的分布。
figure = plt.figure(figsize=(9,6))plt.scatter(data['Body Weight'], data['Brain Weight'])plt.xlabel('Body Weight')plt.ylabel('Brain Weight')
有了这个图表,我们并不能得到那么多信息。表示数据的更好方法是对元素进行对数转换。
figure = plt.figure(figsize=(9,6))plt.scatter(np.log(data['Body Weight']), np.log(data['Brain Weight']))plt.xlabel('Body Weight')plt.ylabel('Brain Weight')
现在我们可以更清楚地看到元素的分布。
准备数据
如上所述,在应用梯度下降之前,所有的输入都必须在相同的范围内。
让我们使用sklearn进行数据预处理,并使用StandardScaler。
from sklearn.preprocessing import StandardScalerscaler = StandardScaler()data_scaled = scaler.fit_transform(data.drop('Animals', axis=1))col = ['Body Weight', 'Brain Weight']new_data = pd.DataFrame(data_scaled, columns=col)new_data.head()
批量梯度下降
现在让我们使用我们的成本函数运行批量梯度下降。
learning_rate = 0.1 interations = 1000 theta = np.array([0,0])
我们的数据集有一个特征来达到大脑的大小,那就是我们的β1。另外,我们需要定义偏差β0,所以我们将theta初始化为一个包含两个零的数组。
要解决梯度,我们需要迭代数据。
feature = new_data['Body Weight'].valuesy = new_data['Brain Weight'].valuesm = len(y)x0 = np.ones(m)X = np.c_[x0, feature]for interation in range(interations): gradients = 2/m * X.T.dot(X.dot(theta) - y) theta = theta - learning_rate * gradients
如果我们看看我们的变量theta。
数组的第一个值是截距,第二个值是系数。基本上,我们的简单线性回归模型将基于它们进行计算。
到目前为止,我们已经准备好了线性回归模型。但是,我们仍然可以使用scikit-learn库进行相同的实现,并比较两个模型之间的最终结果。
from sklearn.linear_model import LinearRegressionX_new = feature.reshape((m,1))ln = LinearRegression()ln.fit(X_new, y)
使用scikit-learn获得以下截距值和系数。
我们现在可以将RMSE应用于两个模型并检查错误率。这是线性回归模型的很好的指标。它基于计算模型预测值与实际值之间的差异。
from sklearn.metrics import mean_squared_errory_pred_zero = X.dot(theta)y_pred = ln.predict(X_new)rmse_zero = np.sqrt(mean_squared_error(y, y_pred_zero))rmse = np.sqrt(mean_squared_error(y, y_pred))print('Regressao Linear do zero: ', rmse_zero)print('Regressao Linear usando sklearn: ', rmse)
请注意,两种模型都具有相同的余量。
学习速率的重要性
下图显示了学习速率值如何改变算法的解决方案。
在左边的例子中,我们声明一个低值,因此,算法需要时间来找到解决方案。在中间的例子中,在很少的交互中,算法找到了完美的解决方案并且表现出良好的性能。在右边,我们声明一个非常高的值,算法采取更大的步骤,最终找不到满足模型的解决方案。
现在您已经了解了ML模型是如何从头构建的。这给了我们一些灵活性,可以与不同的优化器一起工作,并测试新的想法。