ML 系列: — 简单线性回归
线性回归、损失函数、假设函数
图 1.线性回归
文章目录
- 一、说明
- 二、线性回归
- 2.1 简单线性回归
- 2.2 回归中的损失函数
- 三、线性回归中的评估标准
- 四、线性回归模型训练
- 五、可视化
- 5.1 假设函数
- 5.2 计算训练模型的损失:
- 5.3 绘制 Hypothesis 函数,其中包含模型计算的 coef 和 intercept
- 六、结论
一、说明
欢迎学习机器学习系列。这门综合课程目前包括40个部分,指导您了解机器学习、统计和数据分析的基本概念和技术。以下是最基本机器学习模型,线性回归模型。
二、线性回归
线性回归是一种从一个或多个其他变量预测一个或多个变量的方法。预测的变量称为因变量 (y),借助它们预测的变量称为自变量 (x)。如果只有一个自变量,则线性回归模型称为简单,否则称为多重。这里,重要的是因变量的连续性。通常,如果输入数据是 k 维(k 个特征或特征),则可以使用超平面在 k+1 维数据上拟合函数。在输入为一维的简单线性回归中,可以通过在二维数据上拟合一条线来解决回归问题。
2.1 简单线性回归
简单线性回归测量自变量与因变量之间的关系,并测量它们之间的相关性。在这种方法中,通过将线性方程拟合到观测数据,对两个变量(自变量和因变量)之间的关系进行建模。与回归问题相关的数据通常表示为一组输入/输出数据对。
表达式 1.对于回归数据:
在表达式 1 中,x_i 是指第 i 个输入数据,y_i 是指第 i 个输出数据。通常,x_i 或 input data 是长度为 n 和 y_i 的列向量,或者 outputs 是标量数。在简单线性回归中,有一个自变量;换句话说,数据是一维的,很明显输出是一个数字(定量标量)。
表达式 2.的行可以写成如下。
系数 x 或 a 是线的斜率,b 或常数是截距。
表 1.显示了简单线性回归的数据样本,在此示例中,自变量是发动机大小 (Engine_size),因变量是 CO2 排放量 (CO2_Emissions)。在这种情况下,数据是 x(自变量)和 y(因变量)点的二进制集。我们的目标是找到 a 和 b,从而产生 y 的最佳估计值。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
df = pd.read_csv('CO2-Emission-by-Vehicles.csv')
df.head()
表 1.简单线性回归中的自变量和因变量
图 2.以两个维度显示上述数据。
df = np.array(df)
x = df_test[['Engine_size']]
y = df_test[['CO2_Emissions']]
plt.scatter(x, y, edgecolors='b')
plt.xlabel('Engine_size')
plt.ylabel('CO2_Emissions')
图 2.二维数据
通过更改 a 和 b 的不同值,可以绘制不同的线条。在图 3 中,绘制了四条不同的线,并将线参数的值写入每个图中。
# Plot_1
fig, axs = plt.subplots(2, 2, figsize=(10, 10))
plt.subplot(2, 2, 1)
x_scatter = df_test[['Engine_size']]
y_scatter = df_test[['CO2_Emissions']]
plt.scatter(x_scatter, y_scatter, edgecolors='b', linewidths=4.)
plt.xlabel('Engine_size')
plt.ylabel('CO2_Emissions')
x_1 = np.linspace(1.5, 7.1, 50)
a_1, b_1 = 10, 15
y_1 = a_1*x_1 + b_1
plt.plot(x_1, y_1, 'r', label=f'a = {a_1}, b = {b_1}')
legend_properties = {'weight':'bold'}
plt.legend(prop=legend_properties)
plt.grid(alpha=0.5)
# Plot_2
plt.subplot(2, 2, 2)
x_scatter = df_test[['Engine_size']]
y_scatter = df_test[['CO2_Emissions']]
plt.scatter(x_scatter, y_scatter, edgecolors='b', linewidths=4.)
plt.xlabel('Engine_size')
plt.ylabel('CO2_Emissions')
x_2 = np.linspace(1.5, 7.1, 50)
a_2, b_2 = 20, 25
y_2 = a_2*x_2 + b_2
plt.plot(x_2, y_2, 'y', label=f'a = {a_2}, b = {b_2}')
plt.legend(prop=legend_properties)
plt.grid(alpha=0.5)
# Plot_3
plt.subplot(2, 2, 3)
x_scatter = df_test[['Engine_size']]
y_scatter = df_test[['CO2_Emissions']]
plt.scatter(x_scatter, y_scatter, edgecolors='b', linewidths=4.)
plt.xlabel('Engine_size')
plt.ylabel('CO2_Emissions')
x_3 = np.linspace(1.5, 7.1, 50)
a_3, b_3 = 30, 35
y_3 = a_3*x_3 + b_3
plt.plot(x_3, y_3, 'g', label=f'a = {a_3}, b = {b_3}')
plt.legend(prop=legend_properties)
plt.grid(alpha=0.5)
# Plot_4
plt.subplot(2, 2, 4)
x_scatter = df_test[['Engine_size']]
y_scatter = df_test[['CO2_Emissions']]
plt.scatter(x_scatter, y_scatter, edgecolors='b', linewidths=4.)
plt.xlabel('Engine_size')
plt.ylabel('CO2_Emissions')
x_4 = np.linspace(1.5, 7.1, 50)
a_4, b_4 = 65, 15
y_4 = a_4*x_4 + b_4
plt.plot(x_4, y_4, 'k', label=f'a = {a_4}, b = {b_4}')
plt.legend(prop=legend_properties)
plt.grid(alpha=0.5)
图 3.绘制多条不同的线条
在图 3 中,我们手动输入了 a 和 b 的参数或值,并通过试错法输入,但在机器学习中,我们正在寻找一种方法来计算这些值,以达到最低误差值并在上述函数中找到最小值。数据误差值由 loss 函数计算,该值应提供给优化算法,以便以最小化误差值的方式更改参数 (a 和 b)。更新参数和减少错误的过程称为 “学习”。
似乎黑线(右下角图)在其他三条线中更合适,并且在二维空间中,通过看到绘制的线,可以在一定程度上指定最佳参数;但我们知道,数据不能在高于三维的维度上可视化,为了能够将最佳线(在更高的维度中,超平面)拟合到数据,我们需要一个损失函数。
2.2 回归中的损失函数
回归问题有多种损失函数,下面给出了三种最常用的类型。
- 平均绝对误差或“MAE”
MAE 函数是最简单的损失函数之一。为了计算此函数,我们平均整个数据集上实际值与模型预测之间差值的绝对值。
表达式 3.对于 MAE:
import numpy as np
# MAE loss function
def mae_loss(y_pred, y_true):
absolute_error = np.abs((y_pred - y_true))
sum_absolute_error = np.sum(absolute_error)
loss = sum_absolute_error / y_true.size
return loss
- 均方误差或“MSE”
均方误差是使用最广泛的损失函数之一,为了计算 MSE,我们在整个数据集中平均实际值与模型预测之差的平方。
表达式 4.对于 MSE:
import numpy as np
# MSE loss function
def mse_loss(y_pred, y_true):
squared_error = (y_pred - y_true) ** 2
sum_squared_error = np.sum(squared_error)
loss = sum_squared_error / y_true.size
return loss
在上述两个关系中,y ̂_i 是指算法的输出或预测值,y_i 是指目标值或标签,这两个值之间的差异显示了每个数据样本的误差,在 “MAE” 中是误差的绝对值 |y_i - y ̂_i|然后计算它们的平均值;此函数对异常值数据不太敏感,但在 “MSE” 中,由于是针对每个误差计算平方,因此它对异常值样本具有很大的权重。因此,此函数对异常值高度敏感。在两个标准 MAE 和 MSE 中,值越低表示结果越好。
图 4.显示每个函数产生的误差量的可视化视图。
图 4.MAE 和 MSE 中产生的误差量
# Plot MSE
x_mse = np.arange(-1, 1, 0.01)
y_mse = np.square(x_mse)
plt.plot(x_mse, y_mse, "blue", label="MSE")
plt.grid(True, which="major", alpha=0.5)
# Plot MAE
x_mae = np.arange(-1, 1, 0.01)
y_mae = np.abs(x_mae)
plt.plot(x_mae, y_mae, "red", label="MAE")
plt.grid(True, which="major", alpha=0.5)
plt.xlabel('$y_i - y ̂_i$', size='x-large')
plt.ylabel('Loss', size='x-large')
plt.title('MAE vs MSE Loss Function')
plt.legend();
上述函数的图解如图 5 所示。
图 5. MAE 和 MSE 函数
3. Huber 函数
表达式 5.对于 Huber:
y_i 是指实际值或标签,y ̂_i 是指预测值,δ 也是指 delta 值。通过更改 delta 值,可以绘制各种函数,如图 6 所示。
图 6.具有不同 delta 值的 Huber 函数 (δ)
在图 6 中,横轴是指预测值和标签的减法,纵轴是指产生的损失量。
三、线性回归中的评估标准
回归问题有不同的标准。以下是三种最常用的类型。上一节中介绍的两个函数 MAE 和 MSE 也可以用作损失函数,但称为“R-Square”或“R2”的第三个标准仅用于评估。该标准的目的是以百分比的形式提供一个数字,以便我们可以更轻松地了解模型是否训练有素。这个准则的可解释性比前两个准则要容易,而且这个准则的值在无穷大和一的负范围内;标准越接近 1,模型在估计中的准确性就越好,而 MAE 和 MSE 的值越低,准确性就越好。
表达式 6.对于 R 平方准则:
在表达式 6 中,分数 y̅ 的分母是指目标数据或标签的平均值,其他项目与前面解释的 MSE 相同。
from sklearn.metrics import r2_score
# Actual values
actual = [1, 2, 3, 4, 5]
# Predicted values
predicted = [1.2, 1.8, 3.2, 3.9, 4.7]
# Compute R-Squared score
r2 = r2_score(actual, predicted)
print("R-Squared score:", r2)
# R-Squared score: 0.978
回归的目的是创建一个模型来估计以前未遇到的值。回归中的一种评估方法是 “Train/Test Split” 图 7。在这种方法中,样品分为两类:
1- 训练集 (Train) 或构建模型的部分。
2- 测试集或测试构建模型的零件。
图 7.通过训练/测试拆分方法划分样本来评估模型
在训练机器学习模型的过程中,通常会考虑训练数据 80% 和测试数据 20% 的比例。
四、线性回归模型训练
在下文中,我将解决一个简单线性回归的示例,我已将其代码放在我的 GitHub 上,您可以从那里下载数据集。我们必须训练一个模型,使其能够找到 a 和 b 的最佳值,从而获得尽可能小的误差。
包含入口
import pandas as pd
import numpy as np
数据
广告数据集包含有关产品在不同市场中的销售信息,以及该产品在每个市场中的广告预算。该数据集包括 200 个实例,具有电视广告预算、广播广告预算和报纸广告预算等 3 个特征。
目标变量是产品的销售额,它也是一个连续变量。我们可以使用广告预算来预测商品的销售情况。
df = pd.read_csv('Datasets/Advertising.csv')
# remove the first column from the DataFrame.
df = df.iloc[:, 1:]
df.head()
图 8. 绘制 5 行数据集
选择一项特征
df_new = df[['TV', 'Sales']]
df_new.head()
图 9. 绘制数据集的 5 行选定列
type(df_new) # pandas.core.frame.DataFrame
转换为 NumPy
dataset = np.array(df)
训练测试拆分
# Extract the values from array in the first column, assign them to the variable 'x'.
x = dataset[:, 0]
y = dataset[:, 1]
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
print(x_train.shape) # (160,)
print(y_train.shape) # (160,)
print(x_test.shape) # (40,)
print(y_test.shape) # (40,)
五、可视化
import matplotlib.pyplot as plt
plt.scatter(x_train, y_train);
图 10. 图 x_train 和 y_train
5.1 假设函数
如果我们有一个特征(也称为单变量线性回归),则线性回归中线的公式(也称为假设函数)可以简化为:
y h a t = β 0 + β 1 x y_hat = β₀ + β₁x yhat=β0+β1x
这里:
y_hat 是因变量或模型输出(也称为响应变量)
x 是自变量或输入(也称为预测变量)
β₀ 是 y 截距(也称为偏置项)
β₀ 确定直线与 y 轴相交的点。较大的值 β₀ 将整个行向上移动,而较小的值 β₀ 将整个行向下移动。
β₁ 是自变量 x 的系数(或权重)
β₁ 确定线的斜率。较大的 β₁ 值会使线条更陡峭,而较小的 β₁ 值会使线条更平坦。
β₀ 和 β₁ 是模型参数
x_train = x_train.reshape(-1, 1)
y_train = y_train.reshape(-1, 1)
代码 and 用于将训练数据数组从 1 维形状重塑为具有单列的 2 维形状。这样做通常是为了匹配某些机器学习算法的预期输入形状,或者执行需要 2 维输入的操作。
x_train.reshape(-1, 1)y_train.reshape(-1, 1)
x_train.shape, y_train.shape
# ((160, 1), (160, 1))
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(x_train, y_train)
model.coef_, model.intercept_
# 0.04652973, 7.11963843
5.2 计算训练模型的损失:
# Compute the predicted values
y_pred = model.predict(x_train)
# Compute the loss (mean squared error)
loss = np.mean((y_train - y_pred) ** 2)
print(loss) # 10.60
5.3 绘制 Hypothesis 函数,其中包含模型计算的 coef 和 intercept
plt.scatter(x_train, y_train);
x = np.linspace(0, 300, 100)
b0 = 7.11
b1 = 0.04
y_hat = b0 + b1*x
plt.plot(x, y_hat, 'r', label=f'b0 = {b0}, b1 = {b1}');
plt.legend()
图 11. 绘制具有 coef 和 intercept 的假设函数
如果您想访问代码,请打开我的 GitHub 存储库并打开 06. linear_regression。
六、结论
在第 2 天,我们讨论了简单线性回归。在下一节课:机器学习系列:第 3 天 — 使用梯度下降 (GD) 进行优化时,我们将讨论一种称为梯度下降的基本优化算法。