0


10种常见的回归算法总结和介绍

线性回归是机器学习中最简单的算法,它可以通过不同的方式进行训练。 在本文中,我们将介绍以下回归算法:线性回归、Robust 回归、Ridge 回归、LASSO 回归、Elastic Net、多项式回归、多层感知机、随机森林回归和支持向量机。除此以外,本文还将介绍用于评估回归模型的最常用指标,包括均方误差 (MSE)、均方根误差 (RMSE) 和平均绝对误差 (MAE)。

导入库和读取数据

  1. import pandas as pd
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. import seaborn as sns
  5. import hvplot.pandas
  6. %matplotlib inline
  7. sns.set_style("whitegrid")
  8. plt.style.use("fivethirtyeight")
  9. USAhousing = pd.read_csv('../usa-housing/USA_Housing.csv')
  10. USAhousing.head()

探索性数据分析 (EDA)

下一步将创建一些简单的图表来检查数据。 进行EDA将帮助我们熟悉数据和获得数据的信息,尤其是对回归模型影响最大的异常值。

  1. USAhousing.info()
  2. <class 'pandas.core.frame.DataFrame'>
  3. RangeIndex: 5000 entries, 0 to 4999
  4. Data columns (total 7 columns):
  5. # Column Non-Null Count Dtype
  6. --- ------ -------------- -----
  7. 0 Avg. Area Income 5000 non-null float64
  8. 1 Avg. Area House Age 5000 non-null float64
  9. 2 Avg. Area Number of Rooms 5000 non-null float64
  10. 3 Avg. Area Number of Bedrooms 5000 non-null float64
  11. 4 Area Population 5000 non-null float64
  12. 5 Price 5000 non-null float64
  13. 6 Address 5000 non-null object
  14. dtypes: float64(6), object(1)
  15. memory usage: 273.6+ KB

查看数据集的描述

  1. USAhousing.describe()

训练前的准备

我们将从训练一个线性回归模型开始,训练之前需要确定数据的特征和目标,训练的特征的 X ,目标变量的 y ,在本例中我们的目标为 Price 列。

之后,将数据分成训练集和测试集。 我们将在训练集上训练我们的模型,然后使用测试集来评估模型。

  1. from sklearn.model_selection import train_test_split
  2. X = USAhousing[['Avg. Area Income', 'Avg. Area House Age', 'Avg. Area Number of Rooms',
  3. 'Avg. Area Number of Bedrooms', 'Area Population']]
  4. y = USAhousing['Price']
  5. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

为了评估回归模型还创建了一些辅助函数。

  1. from sklearn import metrics
  2. from sklearn.model_selection import cross_val_score
  3. def cross_val(model):
  4. pred = cross_val_score(model, X, y, cv=10)
  5. return pred.mean()
  6. def print_evaluate(true, predicted):
  7. mae = metrics.mean_absolute_error(true, predicted)
  8. mse = metrics.mean_squared_error(true, predicted)
  9. rmse = np.sqrt(metrics.mean_squared_error(true, predicted))
  10. r2_square = metrics.r2_score(true, predicted)
  11. print('MAE:', mae)
  12. print('MSE:', mse)
  13. print('RMSE:', rmse)
  14. print('R2 Square', r2_square)
  15. print('__________________________________')
  16. def evaluate(true, predicted):
  17. mae = metrics.mean_absolute_error(true, predicted)
  18. mse = metrics.mean_squared_error(true, predicted)
  19. rmse = np.sqrt(metrics.mean_squared_error(true, predicted))
  20. r2_square = metrics.r2_score(true, predicted)
  21. return mae, mse, rmse, r2_square

训练回归模型

对于线性回归而言,一般都会有以下的假设:

线性假设:线性回归假设输入和输出之间的关系是线性的。所以可能需要转换数据以使关系线性化(例如,指数关系的对数转换)。

去除噪音:线性回归假设您的输入和输出变量没有噪声。这对于输出变量最重要,如果可能希望删除输出变量 (y) 中的异常值。

去除共线性:当具有高度相关的输入变量时,线性回归将会过拟合。需要将输入数据进行相关性计算并删除最相关的。

高斯分布:如果输入和输出变量具有高斯分布,线性回归将会做出更可靠的预测。对于分布的转换可以对变量使用变换(例如 log 或 BoxCox)以使它们的分布看起来更像高斯分布。

对数据进行处理:使用标准化或归一化重新调整输入变量,线性回归通常会做出更可靠的预测。

  1. from sklearn.preprocessing import StandardScaler
  2. from sklearn.pipeline import Pipeline
  3. pipeline = Pipeline([
  4. ('std_scalar', StandardScaler())
  5. ])
  6. X_train = pipeline.fit_transform(X_train)
  7. X_test = pipeline.transform(X_test)

下面我们开始进行回归回归算法的示例

1、线性回归和评价指标

  1. from sklearn.linear_model import LinearRegression
  2. lin_reg = LinearRegression(normalize=True)
  3. lin_reg.fit(X_train,y_train)

有了第一个模型,那么就要知道评价模型的指标,以下是回归问题的三个常见评估指标:

平均绝对误差 (MAE) 是误差绝对值的平均值:

均方误差 (MSE) 是均方误差的平均值:

均方根误差 (RMSE) 是均方误差的平方根:

这三个指标中:

  • MAE 是最容易理解的,因为它是平均误差。
  • MSE 比 MAE 更受欢迎,因为 MSE “惩罚”更大的错误,这在现实世界中往往很有用。
  • RMSE 比 MSE 更受欢迎,因为 RMSE 可以用“y”单位解释

这些都是损失函数,我们的训练目标就是最小化他们。

  1. test_pred = lin_reg.predict(X_test)
  2. train_pred = lin_reg.predict(X_train)
  3. print('Test set evaluation:\n_____________________________________')
  4. print_evaluate(y_test, test_pred)
  5. print('Train set evaluation:\n_____________________________________')
  6. print_evaluate(y_train, train_pred)
  7. results_df = pd.DataFrame(
  8. data=[["Linear Regression", *evaluate(y_test, test_pred) ,
  9. cross_val(LinearRegression())]],
  10. columns=['Model', 'MAE', 'MSE', 'RMSE', 'R2 Square', "Cross Validation"])
  11. Test set evaluation:
  12. _____________________________________
  13. MAE: 81135.56609336878
  14. MSE: 10068422551.40088
  15. RMSE: 100341.52954485436
  16. R2 Square 0.9146818498754016
  17. __________________________________
  18. Train set evaluation:
  19. _____________________________________
  20. MAE: 81480.49973174892
  21. MSE: 10287043161.197224
  22. RMSE: 101425.06180031257
  23. R2 Square 0.9192986579075526
  24. __________________________________

2、Robust回归

Robust回归是一种回归分析形式,它的目标是克服传统参数和非参数方法的一些局限性,旨在不受基础数据生成过程违反回归假设的过度影响。

当数据包含异常值时,则会考虑Robust回归。 在存在异常值的情况下,最小二乘估计效率低下并且可能存在偏差。 因为最小二乘预测被拖向离群值,并且因为估计的方差被人为夸大,结果是离群值可以被掩盖了。

随机样本共识——RANSAC

随机样本共识 (RANSAC) 是一种迭代方法,它从一组观察到的包含异常值的数据中估计数学模型的参数,而异常值不会对估计值产生影响。 因此它也可以理解为一种异常值检测方法。

一个基本的假设是,数据由“内值”和“异常值”组成,“内值”即数据的分布可以用一组模型参数来解释,但可能受噪声影响,“异常值”是不符合模型的数据。RANSAC还假设,给定一组(通常很小)内点,存在一个程序可以估计模型的参数,以最优地解释或拟合该数据。

  1. from sklearn.linear_model import RANSACRegressor
  2. model = RANSACRegressor(base_estimator=LinearRegression(), max_trials=100)
  3. model.fit(X_train, y_train)
  4. test_pred = model.predict(X_test)
  5. train_pred = model.predict(X_train)
  6. print('Test set evaluation:\n_____________________________________')
  7. print_evaluate(y_test, test_pred)
  8. print('====================================')
  9. print('Train set evaluation:\n_____________________________________')
  10. print_evaluate(y_train, train_pred)
  11. results_df_2 = pd.DataFrame(
  12. data=[["Robust Regression", *evaluate(y_test, test_pred) , cross_val(RANSACRegressor())]],
  13. columns=['Model', 'MAE', 'MSE', 'RMSE', 'R2 Square', "Cross Validation"]
  14. )
  15. results_df = results_df.append(results_df_2, ignore_index=True)
  16. Test set evaluation:
  17. _____________________________________
  18. MAE: 84645.31069259303
  19. MSE: 10996805871.555056
  20. RMSE: 104865.65630155115
  21. R2 Square 0.9068148829222649
  22. __________________________________
  23. ====================================
  24. Train set evaluation:
  25. _____________________________________
  26. MAE: 84956.48056962446
  27. MSE: 11363196455.35414
  28. RMSE: 106598.29480509592
  29. R2 Square 0.9108562888249323
  30. _________________________________

3、Ridge回归

Ridge回归通过对系数的大小施加惩罚来解决普通最小二乘法的一些问题。 Ridge系数最小化惩罚残差平方和

alpha >= 0 是控制收缩量的复杂性参数:alpha 值越大,收缩量越大,因此系数对共线性的鲁棒性更强。

Ridge回归是一个 L2 惩罚模型。 将权重的平方和添加到最小二乘成本函数。

  1. from sklearn.linear_model import Ridge
  2. model = Ridge(alpha=100, solver='cholesky', tol=0.0001, random_state=42)
  3. model.fit(X_train, y_train)
  4. pred = model.predict(X_test)
  5. test_pred = model.predict(X_test)
  6. train_pred = model.predict(X_train)
  7. print('Test set evaluation:\n_____________________________________')
  8. print_evaluate(y_test, test_pred)
  9. print('====================================')
  10. print('Train set evaluation:\n_____________________________________')
  11. print_evaluate(y_train, train_pred)
  12. results_df_2 = pd.DataFrame(
  13. data=[["Ridge Regression", *evaluate(y_test, test_pred) , cross_val(Ridge())]],
  14. columns=['Model', 'MAE', 'MSE', 'RMSE', 'R2 Square', "Cross Validation"]
  15. )
  16. results_df = results_df.append(results_df_2, ignore_index=True)
  17. Test set evaluation:
  18. _____________________________________
  19. MAE: 81428.64835535336
  20. MSE: 10153269900.892609
  21. RMSE: 100763.43533689494
  22. R2 Square 0.9139628674464607
  23. __________________________________
  24. ====================================
  25. Train set evaluation:
  26. _____________________________________
  27. MAE: 81972.39058585509
  28. MSE: 10382929615.14346
  29. RMSE: 101896.66145239233
  30. R2 Square 0.9185464334441484
  31. __________________________________

4、LASSO 回归

LASSO 回归是一种估计稀疏系数的线性模型。 在数学上,它由一个用 L1 先验作为正则化器训练的线性模型组成。 最小化的目标函数是:

  1. from sklearn.linear_model import Lasso
  2. model = Lasso(alpha=0.1,
  3. precompute=True,
  4. # warm_start=True,
  5. positive=True,
  6. selection='random',
  7. random_state=42)
  8. model.fit(X_train, y_train)
  9. test_pred = model.predict(X_test)
  10. train_pred = model.predict(X_train)
  11. print('Test set evaluation:\n_____________________________________')
  12. print_evaluate(y_test, test_pred)
  13. print('====================================')
  14. print('Train set evaluation:\n_____________________________________')
  15. print_evaluate(y_train, train_pred)
  16. results_df_2 = pd.DataFrame(
  17. data=[["Lasso Regression", *evaluate(y_test, test_pred) , cross_val(Lasso())]],
  18. columns=['Model', 'MAE', 'MSE', 'RMSE', 'R2 Square', "Cross Validation"]
  19. )
  20. results_df = results_df.append(results_df_2, ignore_index=True)
  21. Test set evaluation:
  22. _____________________________________
  23. MAE: 81135.6985172622
  24. MSE: 10068453390.364521
  25. RMSE: 100341.68321472648
  26. R2 Square 0.914681588551116
  27. __________________________________
  28. ====================================
  29. Train set evaluation:
  30. _____________________________________
  31. MAE: 81480.63002185506
  32. MSE: 10287043196.634295
  33. RMSE: 101425.0619750084
  34. R2 Square 0.9192986576295505
  35. __________________________________

5、Elastic Net

Elastic Net 使用 L1 和 L2 先验作为正则化器进行训练。 这种组合允许学习一个稀疏模型,其中很少有像 Lasso 那样的非零权重,同时仍然保持 Ridge 的正则化属性。

当多个特征相互关联时,Elastic Net络很有用。 Lasso 可能会随机选择关联特征其中之一,而 Elastic Net 可能会同时选择两者。 Elastic Net最小化的目标函数是:

  1. from sklearn.linear_model import ElasticNet
  2. model = ElasticNet(alpha=0.1, l1_ratio=0.9, selection='random', random_state=42)
  3. model.fit(X_train, y_train)
  4. test_pred = model.predict(X_test)
  5. train_pred = model.predict(X_train)
  6. print('Test set evaluation:\n_____________________________________')
  7. print_evaluate(y_test, test_pred)
  8. print('====================================')
  9. print('Train set evaluation:\n_____________________________________')
  10. print_evaluate(y_train, train_pred)
  11. results_df_2 = pd.DataFrame(
  12. data=[["Elastic Net Regression", *evaluate(y_test, test_pred) , cross_val(ElasticNet())]],
  13. columns=['Model', 'MAE', 'MSE', 'RMSE', 'R2 Square', "Cross Validation"]
  14. )
  15. results_df = results_df.append(results_df_2, ignore_index=True)
  16. Test set evaluation:
  17. _____________________________________
  18. MAE: 81184.43147330945
  19. MSE: 10078050168.470106
  20. RMSE: 100389.49232100991
  21. R2 Square 0.9146002670381437
  22. __________________________________
  23. ====================================
  24. Train set evaluation:
  25. _____________________________________
  26. MAE: 81577.88831531754
  27. MSE: 10299274948.101461
  28. RMSE: 101485.34351373829
  29. R2 Square 0.9192027001474953
  30. __________________________________

6、多项式回归

机器学习中的一种常见模式是使用在数据的非线性函数上训练的线性模型。 这种方法保持了线性方法通常快速的性能,同时允许它们适应更广泛的数据。

可以通过从系数构造多项式特征来扩展简单的线性回归。 在标准线性回归中,可能有一个看起来像这样的二维数据模型:

如果我们想对数据拟合抛物面而不是平面,我们可以将特征组合成二阶多项式,使模型看起来像这样:

这仍然是一个线性模型:那么如果我们创建一个新的变量

通过重新标记数据,那么公式可以写成

可以看到到生成的多项式回归属于上面的同一类线性模型(即模型在 w 中是线性的),并且可以通过相同的技术求解。 通过考虑使用这些基函数构建的高维空间内的线性拟合,该模型可以灵活地拟合更广泛的数据范围。

  1. from sklearn.preprocessing import PolynomialFeatures
  2. poly_reg = PolynomialFeatures(degree=2)
  3. X_train_2_d = poly_reg.fit_transform(X_train)
  4. X_test_2_d = poly_reg.transform(X_test)
  5. lin_reg = LinearRegression(normalize=True)
  6. lin_reg.fit(X_train_2_d,y_train)
  7. test_pred = lin_reg.predict(X_test_2_d)
  8. train_pred = lin_reg.predict(X_train_2_d)
  9. print('Test set evaluation:\n_____________________________________')
  10. print_evaluate(y_test, test_pred)
  11. print('====================================')
  12. print('Train set evaluation:\n_____________________________________')
  13. print_evaluate(y_train, train_pred)
  14. results_df_2 = pd.DataFrame(
  15. data=[["Polynomail Regression", *evaluate(y_test, test_pred), 0]],
  16. columns=['Model', 'MAE', 'MSE', 'RMSE', 'R2 Square', 'Cross Validation']
  17. )
  18. results_df = results_df.append(results_df_2, ignore_index=True)
  19. Test set evaluation:
  20. _____________________________________
  21. MAE: 81174.51844119698
  22. MSE: 10081983997.620703
  23. RMSE: 100409.0832426066
  24. R2 Square 0.9145669324195059
  25. __________________________________
  26. ====================================
  27. Train set evaluation:
  28. _____________________________________
  29. MAE: 81363.0618562117
  30. MSE: 10266487151.007816
  31. RMSE: 101323.67517519198
  32. R2 Square 0.9194599187853729
  33. __________________________________

7、随机梯度下降

梯度下降是一种非常通用的优化算法,能够为各种问题找到最佳解决方案。 梯度下降的一般思想是迭代地调整参数以最小化成本函数。 梯度下降测量误差函数相对于参数向量的局部梯度,它沿着梯度下降的方向前进。 一旦梯度为零,就达到了最小值。

  1. from sklearn.linear_model import SGDRegressor
  2. sgd_reg = SGDRegressor(n_iter_no_change=250, penalty=None, eta0=0.0001, max_iter=100000)
  3. sgd_reg.fit(X_train, y_train)
  4. test_pred = sgd_reg.predict(X_test)
  5. train_pred = sgd_reg.predict(X_train)
  6. print('Test set evaluation:\n_____________________________________')
  7. print_evaluate(y_test, test_pred)
  8. print('====================================')
  9. print('Train set evaluation:\n_____________________________________')
  10. print_evaluate(y_train, train_pred)
  11. results_df_2 = pd.DataFrame(
  12. data=[["Stochastic Gradient Descent", *evaluate(y_test, test_pred), 0]],
  13. columns=['Model', 'MAE', 'MSE', 'RMSE', 'R2 Square', 'Cross Validation']
  14. )
  15. results_df = results_df.append(results_df_2, ignore_index=True)
  16. Test set evaluation:
  17. _____________________________________
  18. MAE: 81135.56682170597
  19. MSE: 10068422777.172981
  20. RMSE: 100341.53066987259
  21. R2 Square 0.914681847962246
  22. __________________________________
  23. ====================================
  24. Train set evaluation:
  25. _____________________________________
  26. MAE: 81480.49901528798
  27. MSE: 10287043161.228634
  28. RMSE: 101425.06180046742
  29. R2 Square 0.9192986579073061
  30. __________________________________

8、多层感知机

多层感知机相对于简单回归任务的好处是简单的线性回归模型只能学习特征和目标之间的线性关系,因此无法学习复杂的非线性关系。 由于每一层都存在激活函数,多层感知机有能力学习特征和目标之间的复杂关系。

  1. from tensorflow.keras.models import Sequential
  2. from tensorflow.keras.layers import Input, Dense, Activation, Dropout
  3. from tensorflow.keras.optimizers import Adam
  4. X_train = np.array(X_train)
  5. X_test = np.array(X_test)
  6. y_train = np.array(y_train)
  7. y_test = np.array(y_test)
  8. model = Sequential()
  9. model.add(Dense(X_train.shape[1], activation='relu'))
  10. model.add(Dense(32, activation='relu'))
  11. # model.add(Dropout(0.2))
  12. model.add(Dense(64, activation='relu'))
  13. # model.add(Dropout(0.2))
  14. model.add(Dense(128, activation='relu'))
  15. # model.add(Dropout(0.2))
  16. model.add(Dense(512, activation='relu'))
  17. model.add(Dropout(0.1))
  18. model.add(Dense(1))
  19. model.compile(optimizer=Adam(0.00001), loss='mse')
  20. r = model.fit(X_train, y_train,
  21. validation_data=(X_test,y_test),
  22. batch_size=1,
  23. epochs=100)
  24. pd.DataFrame({'True Values': y_test, 'Predicted Values': pred}).hvplot.scatter(x='True Values', y='Predicted Values')
  25. pd.DataFrame(r.history)

  1. pd.DataFrame(r.history).hvplot.line(y=['loss', 'val_loss'])

  1. test_pred = model.predict(X_test)
  2. train_pred = model.predict(X_train)
  3. print('Test set evaluation:\n_____________________________________')
  4. print_evaluate(y_test, test_pred)
  5. print('Train set evaluation:\n_____________________________________')
  6. print_evaluate(y_train, train_pred)
  7. results_df_2 = pd.DataFrame(
  8. data=[["Artficial Neural Network", *evaluate(y_test, test_pred), 0]],
  9. columns=['Model', 'MAE', 'MSE', 'RMSE', 'R2 Square', 'Cross Validation']
  10. )
  11. results_df = results_df.append(results_df_2, ignore_index=True)
  12. Test set evaluation:
  13. _____________________________________
  14. MAE: 101035.09313018023
  15. MSE: 16331712517.46175
  16. RMSE: 127795.58880282899
  17. R2 Square 0.8616077649459881
  18. __________________________________
  19. Train set evaluation:
  20. _____________________________________
  21. MAE: 102671.5714851714
  22. MSE: 17107402549.511665
  23. RMSE: 130795.2695991398
  24. R2 Square 0.8657932776379376
  25. __________________________________

9、随机森林回归

  1. from sklearn.ensemble import RandomForestRegressor
  2. rf_reg = RandomForestRegressor(n_estimators=1000)
  3. rf_reg.fit(X_train, y_train)
  4. test_pred = rf_reg.predict(X_test)
  5. train_pred = rf_reg.predict(X_train)
  6. print('Test set evaluation:\n_____________________________________')
  7. print_evaluate(y_test, test_pred)
  8. print('Train set evaluation:\n_____________________________________')
  9. print_evaluate(y_train, train_pred)
  10. results_df_2 = pd.DataFrame(
  11. data=[["Random Forest Regressor", *evaluate(y_test, test_pred), 0]],
  12. columns=['Model', 'MAE', 'MSE', 'RMSE', 'R2 Square', 'Cross Validation']
  13. )
  14. results_df = results_df.append(results_df_2, ignore_index=True)
  15. Test set evaluation:
  16. _____________________________________
  17. MAE: 94032.15903928125
  18. MSE: 14073007326.955029
  19. RMSE: 118629.70676417871
  20. R2 Square 0.8807476597554337
  21. __________________________________
  22. Train set evaluation:
  23. _____________________________________
  24. MAE: 35289.68268023927
  25. MSE: 1979246136.9966476
  26. RMSE: 44488.71921056671
  27. R2 Square 0.9844729124701823
  28. __________________________________

10、支持向量机

  1. from sklearn.svm import SVR
  2. svm_reg = SVR(kernel='rbf', C=1000000, epsilon=0.001)
  3. svm_reg.fit(X_train, y_train)
  4. test_pred = svm_reg.predict(X_test)
  5. train_pred = svm_reg.predict(X_train)
  6. print('Test set evaluation:\n_____________________________________')
  7. print_evaluate(y_test, test_pred)
  8. print('Train set evaluation:\n_____________________________________')
  9. print_evaluate(y_train, train_pred)
  10. results_df_2 = pd.DataFrame(
  11. data=[["SVM Regressor", *evaluate(y_test, test_pred), 0]],
  12. columns=['Model', 'MAE', 'MSE', 'RMSE', 'R2 Square', 'Cross Validation']
  13. )
  14. results_df = results_df.append(results_df_2, ignore_index=True)
  15. Test set evaluation:
  16. _____________________________________
  17. MAE: 87205.73051021634
  18. MSE: 11720932765.275513
  19. RMSE: 108263.25676458987
  20. R2 Square 0.9006787511983232
  21. __________________________________
  22. Train set evaluation:
  23. _____________________________________
  24. MAE: 73692.5684807321
  25. MSE: 9363827731.411337
  26. RMSE: 96766.87310960986
  27. R2 Square 0.9265412370487783
  28. __________________________________

结果对比

以上就是我们常见的10个回归算法,下面看看结果的对比

  1. results_df

  1. results_df.set_index('Model', inplace=True)
  2. results_df['R2 Square'].plot(kind='barh', figsize=(12, 8))

可以看到,虽然本例的差别很小(这是因为数据集的原因),但是每个算法还是有细微的差别的,我们可以根据不同的实际情况选择表现较好的算法。

总结

在本文中,我们介绍了机器学习中的常见的线性回归算法包括:

  • 常见的线性回归模型(Ridge、Lasso、ElasticNet……)
  • 模型使用的方法
  • 采用学习算法对模型中的系数进行估计
  • 如何评估线性回归模型

如果你对代码感兴趣,本文的完整源代码在这里:

https://www.kaggle.com/faressayah/linear-regression-house-price-prediction

作者:Fares Sayah

“10种常见的回归算法总结和介绍”的评论:

还没有评论