机器学习回归---概述

1  机器学习概述

1.1  机器学习简介

       机器学习(MachineLearning),作为计算机科学的子领域,是人工智能领域的重要分支和实现方式。

        机器学习并不是让机器像人一样学习,而是去寻找大量数据之间的隐藏规律,在同类型事件再次发生时,运用总结的规律在短时间内对实际问题进行决定或预测。

1.2  回归算法分类

1.3  线性模型

1.3.1 (单/多元)线性回归

        线性回归是最简单、最常用的回归算法之一,假设目标变量 ( y ) 与输入特征 ( X ) 之间存在线性关系。

 y=wX+by = w^{T}x_{i} + b

其中,w 是权重向量,( b ) 是偏置项。

 线性回归通过最小化均方误差(MSE)来找到最佳拟合线。

MSE = \frac{1}{n} \sum_{i = 1}^{n}(y_{i}-(w^{T}x_{i}+b))^{2}

通过梯度下降算法,求解最小MSE对应的最佳参数 W和 b组合。

import numpy as np                                   #基于数组对象的科学计算库
from sklearn.linear_model import LinearRegression    #从sklearn导入线性回归模型
from sklearn.model_selection import train_test_split #从sklearn导入训练/测试数据集划分模块
from sklearn.datasets import make_regression         #从sklearn导入生成回归样本数据模块

# 生成数据
# n_samples样本个数;n_features特征个数; noise数据噪声;random_state=42随机种子
# test_size=0.2 测试集数据占20%
X, y = make_regression(n_samples=100, n_features=2, noise=0.1, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练模型
model = LinearRegression()
model.fit(X_train, y_train)

# 预测与评估
y_pred = model.predict(X_test)  #模型预测Y值
print(f"Coefficients: {model.coef_}")    #模型权重W
print(f"Intercept: {model.intercept_}")  #模型参数b
print(f"Mean Squared Error: {np.mean((y_pred - y_test)**2)}") #输出模型MSE值

numpy:科学计算库,提供了矩阵,线性代数,傅立叶变换等等的解决方案, 最常用的是它的N维数组对象。

sklearn:是一个功能强大且易于使用的机器学习库,它提供了丰富的算法和工具集,使得机器学习变得更加简单和高效。

1.3.2  Lasso

       一般线性回归模型的目标是最小化残差平方和(MSE),即通过拟合一个线性方程来预测目标变量。然而,在实际问题中,可能存在大量的自变量,其中一些可能对目标变量的预测能力较弱或冗余。此时,Lasso回归通过引入L1正则化 (即Lasso惩罚项),可以将系数向量中小的权重变为0,从而实现特征选择和模型稀疏性。

MSE = \frac{1}{n} \sum_{i = 1}^{n}(y_{i}-(w^{T}x_{i}+b))^{2}+\lambda \sum_{i=1}^{n}\left | w_{i} \right |

其中,\lambda \sum_{i=1}^{n}\left | w_{i} \right | 是正则化项,它通过增加非零系数的数量来惩罚模型的复杂性。

        假设我们有两个特征  w_{1} 和 ,w_{2} ,lasso回归的惩罚项  \left |w_{1}\right |+\left | w_{2} \right | 的几何形状是一个菱形。而 OLS 的等值线是椭圆形。当我们在优化过程中缩小误差平方和的同时约束 \left |w_{1}\right |+\left | w_{2} \right |\leq C (即菱形内的区域),最终会导致优化解在菱形的顶点处。这些顶点对应于一些系数(如  w_{1} 或 w_{2} )为零,从而实现特征选择。

总之,通过Lasso回归,我们不仅能得到一个适合数据的模型,还能自动筛选出对结果有重要影响的特征,使得模型更加简洁和解释性更强。

import numpy as np                                   #基于数组对象的科学计算库
from sklearn.linear_model import Lasso    #从sklearn导入Lasso模型
from sklearn.model_selection import train_test_split #从sklearn导入训练/测试数据集划分模块
from sklearn.datasets import make_regression         #从sklearn导入生成回归样本数据模块
from sklearn.metrics import mean_squared_error,r2_score  #模型评估MSE,R2
from sklearn.model_selection import GridSearchCV     #超参数网格搜索
# 生成数据
# n_samples样本个数;n_features特征个数; noise数据噪声;random_state=42随机种子
# test_size=0.2 测试集数据占20%
X, y = make_regression(n_samples=100, n_features=5, noise=0.1, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练模型
model = Lasso()

#定义超参数网格,-4~4之间平均取50个点
alphas = np.logspace(-4, 4, 50)

#网格搜索
grid_search=GridSearchCV(estimator = model,param_grid = {'alpha':alphas},cv=5,scoring='neg_mean_squared_error')
grid_search.fit(X_train,y_train)

#最佳模型与超参数
best_lasso = grid_search.best_estimator_  #最佳模型
best_alpha=grid_search.best_params_['alpha']  #最佳超参数
print(f'Best alpha:{best_alpha}')

# #训练最终模型
# lasso_opt=Lasso(alpha = best_alpha)
# lasso_opt.fit(X_train,y_train)

#预测
y_pred_train=best_lasso.predict(X_train)
y_pred_test=best_lasso.predict(X_test)
print(f"Coefficients: {best_lasso.coef_}")    #模型权重W
print(f"Intercept: {best_lasso.intercept_}")  #模型参数b

#评估
mse_train=mean_squared_error(y_train,y_pred_train)
mse_test=mean_squared_error(y_test,y_pred_test)
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)

print(f'MSE (Train): {mse_train}')
print(f'MSE (Test): {mse_test}')
print(f'R^2 (Train): {r2_train}')
print(f'R^2 (Test): {r2_test}')

 超参数'alpha':  它控制了L1正则化项中惩罚项的大小。当alpha为0时,Lasso退化为普通的线性回归模型,不带任何正则化;如果alpha非常大,则所有特征的权重都会趋近于0;如果alpha适当,则不重要的特征的权重都会趋近于0,从而实现特征选择。

GridSearchCV: 它通过搜索定义的超参数值,筛选模型对应的最佳超参数值。然后使用最佳超参数训练最终模型,使模型表现良好。但对于多个超参数的模型,计算成本可能很高。

优点:

  1. 特征选择Lasso回归会将一些不重要的特征的系数缩减为零,从而实现特征选择。这使得模型更加简洁和易于解释。

  2. 减少过拟合通过引入正则化项,Lasso回归可以有效地减少过拟合,提高模型的泛化能力。

  3. 简单高效Lasso回归相对简单,计算效率高,适用于处理高维数据。

缺点:

  1. 多重共线性问题当特征之间存在多重共线性时,Lasso回归可能无法正确选择特征,导致模型性能下降。

  2. 计算复杂度在大规模数据集上,Lasso回归的计算复杂度可能较高,尤其是当使用网格搜索优化超参数时。

  3. 模型解释性虽然Lasso回归能进行特征选择,但对结果的解释性仍可能受到数据特性的影响,有时难以完全理解模型的行为。

1.3.3  Ridge

        Ridge 回归是一种用于处理多重共线性(即自变量之间高度相关)的线性回归技术。它通过在模型中引入一个额外的惩罚项(L2正则化)来避免过拟合,从而提高模型的泛化能力。

多重共线性问题在实际应用中,自变量之间有时候会高度相关,这叫做多重共线性。这种情况会导致线性回归模型的预测效果不好,因为模型对训练数据过于敏感(即过拟合),在新数据上表现不佳。

引入惩罚项Ridge 回归通过在损失函数中加入一个惩罚项(也叫正则化项)来解决这个问题。这个惩罚项是所有回归系数的平方和乘以一个常数(惩罚参数)。它的作用是限制回归系数的大小,使得模型不会过度拟合训练数据。

       可以说,Ridge 回归是一种增强版的线性回归,通过在损失函数中加入一个惩罚项来限制回归系数的大小,从而减少过拟合并提高模型在新数据上的预测能力。对于咱们大多数同学来说,可以把 Ridge 回归看作是在原有的线性回归基础上“加了一点约束”,使得模型更加稳健。

 MSE = \frac{1}{n} \sum_{i = 1}^{n}(y_{i}-(w^{T}x_{i}+b))^{2}+\lambda \sum_{i=1}^{n}\beta _{i}^{2}

其中, \lambda 是L2正则化参数,控制惩罚项的权重。较大的 \lambda  会更严格地限制  \beta 的大小,防止过拟合。 

import numpy as np                                   #基于数组对象的科学计算库
from sklearn.linear_model import Ridge    #从sklearn导入Lasso模型
from sklearn.model_selection import train_test_split #从sklearn导入训练/测试数据集划分模块
from sklearn.datasets import make_regression         #从sklearn导入生成回归样本数据模块
from sklearn.metrics import mean_squared_error,r2_score  #模型评估MSE,R2
from sklearn.model_selection import GridSearchCV     #超参数网格搜索
# 生成数据
# n_samples样本个数;n_features特征个数; noise数据噪声;random_state=42随机种子
# test_size=0.2 测试集数据占20%
X, y = make_regression(n_samples=100, n_features=5, noise=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练模型
model = Ridge()

#定义超参数网格,-4~4之间平均取50个点
alphas = np.logspace(-4, 4, 50)

#网格搜索
grid_search=GridSearchCV(estimator = model,param_grid = {'alpha':alphas},cv=5,scoring='neg_mean_squared_error')
grid_search.fit(X_train,y_train)

#最佳模型与超参数
best_lasso = grid_search.best_estimator_  #最佳模型
best_alpha=grid_search.best_params_['alpha']  #最佳超参数
print(f'Best alpha:{best_alpha}')

# #训练最终模型
# lasso_opt=Lasso(alpha = best_alpha)
# lasso_opt.fit(X_train,y_train)

#预测
y_pred_train=best_lasso.predict(X_train)
y_pred_test=best_lasso.predict(X_test)
print(f"Coefficients: {best_lasso.coef_}")    #模型权重W
print(f"Intercept: {best_lasso.intercept_}")  #模型参数b

#评估
mse_train=mean_squared_error(y_train,y_pred_train)
mse_test=mean_squared_error(y_test,y_pred_test)
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)

print(f'MSE (Train): {mse_train}')
print(f'MSE (Test): {mse_test}')
print(f'R^2 (Train): {r2_train}')
print(f'R^2 (Test): {r2_test}')

优点

  1. 解决多重共线性问题Ridge 回归通过引入  正则化项,可以有效地解决自变量之间存在多重共线性的问题,从而提高模型的稳定性和预测性能。

  2. 防止过拟合正则化项限制了回归系数的大小,防止模型过拟合训练数据,提升对新数据的泛化能力。

  3. 计算效率高相比于某些复杂的非线性回归模型,Ridge 回归的计算效率较高,适用于大规模数据集。

  4. 参数调整灵活通过调整正则化参数 ,可以在偏差和方差之间找到最佳平衡,从而优化模型性能。

缺点:

  1. 不适用于特征选择Ridge 回归不会将不相关的特征系数缩减到零,因此不适用于需要进行特征选择的场景。

  2. 无法处理非线性关系Ridge 回归是线性模型,如果数据中存在复杂的非线性关系,Ridge 回归的表现可能不如非线性模型。

  3. 解释性较差由于引入了正则化项,Ridge 回归模型的解释性可能较差,不易于解释每个特征对目标值的具体影响。

 1.3.4  ElasticNet

ElasticNet 回归结合了 Lasso 和 Ridge 的特点,通过引入 L1 和 L2 正则化项: 

 MSE = \frac{1}{n} \sum_{i = 1}^{n}(y_{i}-(w^{T}x_{i}+b))^{2}+\lambda \sum_{i=1}^{n}\left | w_{i} \right |+\lambda \sum_{i=1}^{n}\beta _{i}^{2}

import numpy as np                                   #基于数组对象的科学计算库
from sklearn.linear_model import ElasticNet    #从sklearn导入Lasso模型
from sklearn.model_selection import train_test_split #从sklearn导入训练/测试数据集划分模块
from sklearn.datasets import make_regression         #从sklearn导入生成回归样本数据模块
from sklearn.metrics import mean_squared_error,r2_score  #模型评估MSE,R2
from sklearn.model_selection import GridSearchCV     #超参数网格搜索
# 生成数据
# n_samples样本个数;n_features特征个数; noise数据噪声;random_state=42随机种子
# test_size=0.2 测试集数据占20%
X, y = make_regression(n_samples=100, n_features=5, noise=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练模型
model = ElasticNet()

#定义超参数网格,-4~4之间平均取50个点的二维网格
alphas = np.logspace(-4,4,50)
param_grid = {'alpha': alphas, 'l1_ratio':np.linspace(0,1,10)}

#网格搜索
grid_search=GridSearchCV(estimator = model,param_grid = {'alpha':alphas},cv=5,scoring='neg_mean_squared_error')
grid_search.fit(X_train,y_train)

#最佳模型与超参数
best_lasso = grid_search.best_estimator_  #最佳模型
best_alpha=grid_search.best_params_['alpha']  #最佳超参数
print(f'Best alpha:{best_alpha}')

# #训练最终模型
# lasso_opt=Lasso(alpha = best_alpha)
# lasso_opt.fit(X_train,y_train)

#预测
y_pred_train=best_lasso.predict(X_train)
y_pred_test=best_lasso.predict(X_test)
print(f"Coefficients: {best_lasso.coef_}")    #模型权重W
print(f"Intercept: {best_lasso.intercept_}")  #模型参数b

#评估
mse_train=mean_squared_error(y_train,y_pred_train)
mse_test=mean_squared_error(y_test,y_pred_test)
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)

print(f'MSE (Train): {mse_train}')
print(f'MSE (Test): {mse_test}')
print(f'R^2 (Train): {r2_train}')
print(f'R^2 (Test): {r2_test}')

优点

  • 结合了 Ridge 和 Lasso 的优点:既可以解决多重共线性问题,又可以进行特征选择。

  • 灵活性高:通过调整  \lambda _{1} 和  \lambda _{2} 的值,可以在 Ridge 和 Lasso 之间进行权衡。

缺点

  • 参数选择复杂:需要同时调优两个正则化参数,可能增加模型调参的复杂性。

  • 计算开销较大:由于引入了两个正则化项,计算复杂度相对更高。

 1.4  KNN

        K近邻回归(K-Nearest Neighbors Regression,简称KNN回归)是一种简单直观的机器学习算法。KNN回归通过寻找样本空间中与目标点最接近的K个邻居,利用这些邻居的平均值或加权平均值来预测目标点的值。KNN回归属于非参数模型,因为它不对数据的分布做出假设,也不需要训练过程。

       对于待预测的样本点,计算其与训练集中每一个样本点之间的欧氏距离:

d\left ( x_{i},y_{j} \right )=\sqrt{\sum_{i=1}^{k}\left (x_{i,k} -x_{j,k} \right )}

 其中, x_{i} 和 x_{j}分别是两个样本点的特征向量,n 是特征的维数。

根据计算得到的距离d\left ( x_{i},y_{j} \right ),选择距离待预测样本点最近的K个邻居。

根据选中的K个邻居的输出值,计算待预测样本点的加权平均输出值。

\hat{y}=\frac{\sum_{i=1}^{K}\frac{1}{d_{x,x_{i}}}y_{i}}{\sum_{i=1}^{K}\frac{1}{d\left ( x,x_{i} \right )}}

 其中, d\left ( x,x_{i} \right )是待预测样本点与第 i个邻居的距离。

from sklearn.neighbors import KNeighborsRegressor    #从sklearn导入KNeighborsRegressor模型
from sklearn.model_selection import train_test_split #从sklearn导入训练/测试数据集划分模块
from sklearn.datasets import make_regression         #从sklearn导入生成回归样本数据模块
from sklearn.metrics import mean_squared_error,r2_score  #模型评估MSE,R2

# 生成数据
# n_samples样本个数;n_features特征个数; noise数据噪声;random_state=42随机种子
# test_size=0.2 测试集数据占20%
X, y = make_regression(n_samples = 150, n_features = 3, noise = 0.1, random_state = 42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练模型
model = KNeighborsRegressor(n_neighbors = 4)  
model.fit(X_train, y_train)

# n_neighbors: 默认为5,表示用于 kneighbors 查询的默认邻居数。
# weights: 权重函数用于预测,可选值为 'uniform'(均匀权重)或 'distance'(距离权重),或者自定义的一个函数。默认为 'uniform'。
# algorithm: 计算最近邻的算法,可选 'auto'、'ball_tree'、'kd_tree'、'brute'。'auto' 会基于传递给 fit 方法的值尝试决定最合适的算法。
# p: 闵可夫斯基度量的幂参数。当 p=1 时,等同于使用曼哈顿距离; p=2 时为欧几里得距离。

#预测
y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)

#评估
mse_train=mean_squared_error(y_train,y_pred_train)
mse_test=mean_squared_error(y_test,y_pred_test)
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)

print(f'MSE (Train): {mse_train}')
print(f'MSE (Test): {mse_test}')
print(f'R^2 (Train): {r2_train}')
print(f'R^2 (Test): {r2_test}')

 n_neighbors:  默认为5,表示用于 kneighbors 查询的默认邻居数。

weights:  权重函数用于预测,可选值为 'uniform'(均匀权重)或 'distance'(距离权重),或者自定义的一个函数。默认为 'uniform'。

algorithm:  计算最近邻的算法,可选 'auto'、'ball_tree'、'kd_tree'、'brute'。'auto' 会基于传递给 fit 方法的值尝试决定最合适的算法。

p:  闵可夫斯基度量的幂参数。当 p=1 时,等同于使用曼哈顿距离; p=2 时为欧几里得距离。

优点:

  • 简单直观算法思想简单,容易理解和实现。

  • 无模型假设:KNN回归不对数据的分布做任何假设,适用于各种数据分布。

  • 高灵活性:由于无需训练过程,KNN回归可以处理在线学习问题,也可以随时加入新的数据。

缺点:

  • 计算复杂度高:对于大规模数据集,计算每个样本点的距离代价较高,影响预测效率。

  • 维度灾难:随着特征维数的增加,样本之间的距离变得越来越难以区分,导致预测效果下降。

  • 对异常值敏感:KNN回归直接依赖于邻居的输出值,如果邻居中存在异常值,可能会严重影响预测结果。

 1.5  SVR

       支持向量回归(SVR)是一种扩展到回归任务的支持向量机(SVM)。它的目标是找到一个能够最大限度地拟合训练数据的回归超平面,同时保持模型的复杂度尽可能小。SVR 通过在误差范围内(即“ε-不敏感”区域)不对数据点施加惩罚,从而控制模型的泛化能力。

from sklearn.svm import SVR    #从sklearn导入SVR模型
from sklearn.model_selection import train_test_split #从sklearn导入训练/测试数据集划分模块
from sklearn.datasets import make_regression         #从sklearn导入生成回归样本数据模块
from sklearn.metrics import mean_squared_error,r2_score  #模型评估MSE,R2

# 生成数据
# n_samples样本个数;n_features特征个数; noise数据噪声;random_state=42随机种子
# test_size=0.2 测试集数据占20%
X, y = make_regression(n_samples = 150, n_features = 2, noise = 0.2, random_state = 42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练模型
model = SVR(kernel = 'rbf',C = 100,epsilon = 0.1,gamma = 0.1)  #超参数太多GridSearchCV计算量太大,可以手动调超参数,
model.fit(X_train, y_train)

# kernel:算法中所使用的核函数类型,其中有(‘linear’,‘poly’, ‘rbf’,‘sigmoid’,‘precomputer’,默认使用‘rbf’).
# degree:多项式核函数的次数,默认为3,所以当核函数为‘poly’时用到,其它核函数忽略.
# gamma:核函数的系数,在核函数为‘rbf’,‘poly’,‘sigmoid’时使用,其他核函数忽略。gamma的值必须大于0,随着gamma的增大,对于测试集分类效果越差,对于训练集分类效果好,并且使模型的复杂度提高,泛化能力(对未知数的预测能力)较差,从而出现过拟合的情况。
# coef0:核函数中的常数值(y = kx + b中的b值),只在核函数为‘poly’跟‘sigmoid’时使用。
# tol:残差收敛条件,默认是0.0001,即容忍1000分类里出现一个错误,误差达到指定值时停止训练。
# C: 错误项的惩罚因子:原则上C可以根据需要选择所有大于0的数。C越大表示整个优化过程中对于总误差的关注程度越高,对于减小误差的要求越高,甚至不惜使间隔减小。
# 当C趋于无穷大时,这个问题也就是不允许出现分类误差的样本存在,那这就是一个hard - marginSVM问题;
# 当C趋于0时,我们不再关注分类是否正确,只要求间隔越大越好,那么我们将无法得到有意义的解且算法不会收敛。

#预测
y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)

#评估
mse_train=mean_squared_error(y_train,y_pred_train)
mse_test=mean_squared_error(y_test,y_pred_test)
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)

print(f'MSE (Train): {mse_train}')
print(f'MSE (Test): {mse_test}')
print(f'R^2 (Train): {r2_train}')
print(f'R^2 (Test): {r2_test}')

 kernel:算法中所使用的核函数类型,其中有(‘linear’,‘poly’, ‘rbf’,‘sigmoid’,‘precomputer’,默认使用‘rbf’)。

degree: 多项式核函数的次数,默认为3,所以当核函数为‘poly’时用到,其它核函数忽略.

 C: 错误项的惩罚因子(大于0),C越大表示整个优化过程中对于总误差的关注程度越高,对于减小误差的要求越高,甚至不惜使间隔减小。 

优点

  • 强大的泛化能力通过 ε-不敏感区域,SVR 能有效控制模型的复杂度,防止过拟合。

  • 非线性扩展:借助核技巧,SVR 能处理非线性数据。

  • 鲁棒性:对异常值具有一定的鲁棒性。

缺点

  • 计算复杂度高由于二次规划的计算复杂度,SVR 在大数据集上训练时间较长。

  • 参数调优复杂:需要仔细调节 C 和 ε 参数,以找到最优解。

 1.6  树模型

 1.6.1  决策树回归

        决策树回归是使用树状模型进行回归任务的算法。它通过不断将数据集划分成更小的子集,并在叶子节点上做出预测。决策树的划分基于对特征的某种度量,如均方误差(MSE),以最小化叶子节点的误差为目标。

 MSE=\frac{1}{n}\sum_{i=1}^{n}\left ( y_{i} -\bar{y}\right)^{2}

 其中,\bar{y} 是叶子节点中的平均值。

from sklearn.tree import DecisionTreeRegressor    #从sklearn导入DecisionTreeRegressor模型
from sklearn.model_selection import train_test_split #从sklearn导入训练/测试数据集划分模块
from sklearn.datasets import make_regression         #从sklearn导入生成回归样本数据模块
from sklearn.metrics import mean_squared_error,r2_score  #模型评估MSE,R2

# 生成数据
# n_samples样本个数;n_features特征个数; noise数据噪声;random_state=42随机种子
# test_size=0.2 测试集数据占20%
X, y = make_regression(n_samples = 150, n_features = 3, noise = 0.2, random_state = 42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练模型
model = DecisionTreeRegressor(max_depth=3,random_state=42)  #超参数太多GridSearchCV计算量太大,可以手动调超参数,
model.fit(X_train, y_train)

# "squared_error":平均平方误差,即方差减少,使用每个终端节点的平均值最小化L2损失;
# "friedman_mse":使用平均平方误差与Friedman改进得分寻找潜在的分裂;
# "absolute_error":平均绝对误差,使用每个终端节点的中位数最小化L1损失;
# "poisson":使用减少泊松偏差寻找分裂。
# splitter 参数决定了选择每个节点分割的策略,可选的策略有:"best":选择最佳分割;"random":选择最佳随机分割。
# max_depth 参数限制了树的最大深度。如果未设置,节点将继续展开直到所有叶子都是纯净的,或者每个叶子包含的样本少于 min_samples_split 指定的数量。
# min_samples_split 参数规定了分割内部节点所需的最小样本数。可以是整数或者浮点数,如果是浮点数,则表示最小样本数占总样本数的比例。
# min_samples_leaf 参数指定了一个叶子节点所需的最小样本数。这个参数可以平滑模型,特别是在回归中。
# max_features 参数决定了寻找最佳分割时考虑的特征数量。可以是整数、浮点数、"sqrt" 或 "log2"。
# random_state 参数控制估计器的随机性。即使 splitter 设置为 "best",特征在每次分割时也会随机排列。
# min_impurity_decrease 参数表示如果分割导致不纯度的减少大于或等于该值,则会进行分割。
# ccp_alpha 参数用于最小成本复杂性剪枝。选择成本复杂性最大且小于 ccp_alpha 的子树。

#预测
y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)

#评估
mse_train=mean_squared_error(y_train,y_pred_train)
mse_test=mean_squared_error(y_test,y_pred_test)
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)

print(f'MSE (Train): {mse_train}')
print(f'MSE (Test): {mse_test}')
print(f'R^2 (Train): {r2_train}')
print(f'R^2 (Test): {r2_test}')

max_depth:  参数限制了树的最大深度。如果未设置,节点将继续展开直到所有叶子都是纯净的,或者每个叶子包含的样本少于 min_samples_split 指定的数量。
min_samples_split:  参数规定了分割内部节点所需的最小样本数。可以是整数或者浮点数,如果是浮点数,则表示最小样本数占总样本数的比例。
min_samples_leaf:  参数指定了一个叶子节点所需的最小样本数。这个参数可以平滑模型,特别是在回归中。
max_features:  参数决定了寻找最佳分割时考虑的特征数量。可以是整数、浮点数、"sqrt" 或 "log2"。
random_state:  参数控制估计器的随机性。即使 splitter 设置为 "best",特征在每次分割时也会随机排列。
min_impurity_decrease:  参数表示如果分割导致不纯度的减少大于或等于该值,则会进行分割。

1.6.2  随机森林回归

        随机森林回归是通过集成多棵决策树来进行回归任务的算法。每棵树都是从数据的不同子集和特征子集上训练而成的,最终的预测结果通过这些树的平均值(Bagging)来给出。这种集成方法有效地降低了单棵决策树的过拟合风险,并提高了模型的稳定性和泛化能力。

       随机森林由多棵决策树组成,假设我们有 n 棵树,每棵树对输入特征 x 给出一个预测 h_{i}\left ( x \right ),则随机森林的预测结果为这些树的平均值:

 \hat{f}\left ( x \right )=\frac{1}{n}\sum_{i=1}^{n}h_{i}\left ( x \right )

from sklearn.ensemble import RandomForestRegressor    #从sklearn导入RandomForestRegressor模型
from sklearn.model_selection import train_test_split #从sklearn导入训练/测试数据集划分模块
from sklearn.datasets import make_regression         #从sklearn导入生成回归样本数据模块
from sklearn.metrics import mean_squared_error,r2_score  #模型评估MSE,R2

# 生成数据
# n_samples样本个数;n_features特征个数; noise数据噪声;random_state=42随机种子
# test_size=0.2 测试集数据占20%
X, y = make_regression(n_samples = 150, n_features = 3, noise = 0.2, random_state = 42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练模型
model = RandomForestRegressor(n_estimators=100,random_state=42)  #定义了100棵树
model.fit(X_train, y_train)

# criterion: “mse”来选择最合适的节点。
# splitter: ”best” or “random”(default=”best”)随机选择属性还是选择不纯度最大的属性,建议用默认。
# max_features: 选择最适属性时划分的特征不能超过此值。
# 当为整数时,即最大特征数;
# 当为小数时,训练集特征数*小数;
                    # if “auto”, then max_features=sqrt(n_features).
                    # If “sqrt”, thenmax_features=sqrt(n_features).
                    # If “log2”, thenmax_features=log2(n_features).
                    # If None, then max_features=n_features.
# max_depth: (default=None)设置树的最大深度,默认为None,这样建树时,会使每一个叶节点只有一个类别,或是达到min_samples_split。
# min_samples_split: 根据属性划分节点时,每个划分最少的样本数。
# min_samples_leaf: 叶子节点最少的样本数。
# max_leaf_nodes: (default=None)叶子树的最大样本数。
# min_weight_fraction_leaf: (default=0) 叶子节点所需要的最小权值
# verbose: (default=0) 是否显示任务进程

#预测
y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)

#评估
mse_train=mean_squared_error(y_train,y_pred_train)
mse_test=mean_squared_error(y_test,y_pred_test)
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)

print(f'MSE (Train): {mse_train}')
print(f'MSE (Test): {mse_test}')
print(f'R^2 (Train): {r2_train}')
print(f'R^2 (Test): {r2_test}')

criterion:  “mse”来选择最合适的节点。
splitter:  “best” or “random”(default=”best”)随机选择属性还是选择不纯度最大的属性,建议用默认。
max_features:  选择最适属性时划分的特征不能超过此值。
当为整数时,即最大特征数;
当为小数时,训练集特征数*小数;
                    # if “auto”, then max_features=sqrt(n_features).
                    # If “sqrt”, thenmax_features=sqrt(n_features).
                    # If “log2”, thenmax_features=log2(n_features).
                    # If None, then max_features=n_features.

max_depth:   (default=None)设置树的最大深度,默认为None,这样建树时,会使每一个叶节点只有一个类别,或是达到min_samples_split。
min_samples_split:  根据属性划分节点时,每个划分最少的样本数。
min_samples_leaf:  叶子节点最少的样本数。
max_leaf_nodes:  (default=None)叶子树的最大样本数。
min_weight_fraction_leaf:  (default=0) 叶子节点所需要的最小权值
verbose:  (default=0) 是否显示任务进程。

优点

  • 高准确度:通过集成学习方法,随机森林通常比单个决策树具有更高的预测准确度。

  • 防止过拟合:通过对多个子集和特征进行训练,降低了模型的过拟合风险。

  • 可处理高维数据:适用于高维特征的数据集。

缺点

  • 计算开销大:训练多个决策树需要较高的计算成本,尤其在数据集较大时。

  • 可解释性差:由于是集成模型,难以解释单个预测的逻辑。

 1.6.3  GBDT

       GBDT 是基于梯度提升(Gradient Boosting思想的一种集成学习方法。其核心思想是通过多个决策树模型的叠加,不断优化模型误差。每一棵树拟合的是前一棵树的残差(即预测误差),通过迭代减少误差,最终形成强大的预测模型。

对于回归问题,GBDT 的目标是最小化损失函数L\left ( y,F\left ( x \right ) \right ) ,其中F\left ( x \right )  表示模型的预测值。模型通过以下过程迭代更新:

1.初始模型:

F_{0}\left ( x \right )=arg\underset{\gamma }{min}\sum_{i=1}^{n}L\left ( y_{i},\gamma \right )

2.迭代训练第 m 棵树时,首先计算前一轮的残差\tau _{im} : 

 \tau _{im}=-\left [ \frac{\vartheta L\left ( y_{i},F\left ( x_{i} \right ) \right ) }{\vartheta F\left ( x_{i} \right )} \right ]_{F\left ( x_{i} \right )=F_{m-1}\left ( x \right )}

3. 通过拟合残差构建新的决策树,并更新模型:

F_{m}\left ( x \right )=F_{m-1}\left ( x \right )+\eta \cdot h_{m}\left ( x \right ) 

 其中, \eta 是学习率, h_{m}\left ( x \right ) 是拟合残差的新树。

from sklearn.ensemble import GradientBoostingRegressor    #从sklearn导入GradientBoostingRegressor模型
from sklearn.model_selection import train_test_split #从sklearn导入训练/测试数据集划分模块
from sklearn.datasets import make_regression         #从sklearn导入生成回归样本数据模块
from sklearn.metrics import mean_squared_error,r2_score  #模型评估MSE,R2

# 生成数据
# n_samples样本个数;n_features特征个数; noise数据噪声;random_state=42随机种子
# test_size=0.2 测试集数据占20%
X, y = make_regression(n_samples = 150, n_features = 3, noise = 0.2, random_state = 42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练模型
model = GradientBoostingRegressor(learning_rate=0.1,n_estimators=100,random_state=42)  #定义了100棵树
model.fit(X_train, y_train)

# Boosting 框架参数
# n_estimators:这是要构建的树的数量。太少可能会导致欠拟合,太多可能会导致过拟合。通常需要与 learning_rate 一起调整来找到最佳的组合。
# learning_rate:这是每棵树对最终预测的贡献。较小的学习率意味着需要更多的树来进行训练。通常从较小的值开始调整,例如 0.1 或更小。
# subsample:这是用于拟合每棵树的样本的比例。值小于 1 可以减少方差,防止过拟合,但也会增加偏差。推荐的值在 0.5 到 0.8 之间。
# loss:损失函数的选择对模型的性能有很大影响。对于回归问题,常用的损失函数包括均方差("ls"),绝对损失("lad"),Huber损失("huber")和分位数损失("quantile")。
# alpha:这是 Huber 损失和分位数损失的参数,它定义了分位数。当数据中有许多异常值时,可能需要调整此参数。
# 决策树参数
# max_features:在寻找最佳分割时要考虑的特征数量。这可以帮助提高模型的性能,并减少计算时间。
# max_depth:树的最大深度。较深的树可以捕获更复杂的模式,但也可能导致过拟合。
# min_samples_split 和 min_samples_leaf:这些参数控制树的生长。它们帮助定义了节点可以继续分割的条件,以及叶子节点所需的最小样本数。
# min_weight_fraction_leaf:这是叶子节点所有样本权重和的最小值,如果小于这个值,则节点将不会进一步分割。
# max_leaf_nodes:最大叶子节点数,通过限制叶子节点的数量,可以防止模型过于复杂。
# min_impurity_split:节点划分的最小不纯度。这个阈值越高,树就越容易停止生长。


#预测
y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)

#评估
mse_train=mean_squared_error(y_train,y_pred_train)
mse_test=mean_squared_error(y_test,y_pred_test)
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)

print(f'MSE (Train): {mse_train}')
print(f'MSE (Test): {mse_test}')
print(f'R^2 (Train): {r2_train}')
print(f'R^2 (Test): {r2_test}')

Boosting 框架参数
n_estimators:这是要构建的树的数量。太少可能会导致欠拟合,太多可能会导致过拟合。通常需要与 learning_rate 一起调整来找到最佳的组合。
learning_rate:这是每棵树对最终预测的贡献。较小的学习率意味着需要更多的树来进行训练。通常从较小的值开始调整,例如 0.1 或更小。
subsample:这是用于拟合每棵树的样本的比例。值小于 1 可以减少方差,防止过拟合,但也会增加偏差。推荐的值在 0.5 到 0.8 之间。
loss:损失函数的选择对模型的性能有很大影响。对于回归问题,常用的损失函数包括均方差("ls"),绝对损失("lad"),Huber损失("huber")和分位数损失("quantile")。
alpha:这是 Huber 损失和分位数损失的参数,它定义了分位数。当数据中有许多异常值时,可能需要调整此参数。
决策树参数
max_features:在寻找最佳分割时要考虑的特征数量。这可以帮助提高模型的性能,并减少计算时间。
max_depth:树的最大深度。较深的树可以捕获更复杂的模式,但也可能导致过拟合。
min_samples_split 和 min_samples_leaf:这些参数控制树的生长。它们帮助定义了节点可以继续分割的条件,以及叶子节点所需的最小样本数。
min_weight_fraction_leaf:这是叶子节点所有样本权重和的最小值,如果小于这个值,则节点将不会进一步分割。
max_leaf_nodes:最大叶子节点数,通过限制叶子节点的数量,可以防止模型过于复杂。
min_impurity_split:节点划分的最小不纯度。这个阈值越高,树就越容易停止生长。

优点

  • 强大的预测能力:梯度提升回归在处理复杂的非线性回归任务时表现尤为出色。

  • 计算效率高:(支持并行和分布式);支持自动处理缺失值;灵活性高,适合多种任务。

  • 可处理高维数据:适用于高维特征的数据集。

缺点

  • 模型复杂:参数较多,调参复杂;占用内存较大,特别是在处理超大规模数据集时。

 1.6.4  XGBoost

        XGBoost 是 GBDT 的优化版本,核心思想仍然是梯度提升(Boosting),但它在计算效率、模型精度等方面进行了多种优化。它通过使用正则化控制模型复杂度,防止过拟合,并且支持分布式计算和多线程并行,提升了计算速度。

XGBoost 的目标是通过加法模型最小化目标函数:

L\left ( \theta \right )=\sum_{i}^{}l\left ( y_{i},\hat{y_{i}} \right )+\sum_{k}^{}\Omega \left ( f_{k} \right )

其中, l 是损失函数,\Omega \left ( f_{k} \right ) 是正则化项,用于控制模型的复杂度。XGBoost 的优化过程使用了泰勒展开的二阶导数加速计算梯度和误差更新: 

L\left ( \theta \right )\approx \sum_{i}^{}\left [ g_{i}f\left ( x_{i} \right )+\frac{1}{2} h_{i}f\left ( x_{i}\right )^{2}\right ]+\Omega \left ( f \right )

其中, g_{i} 和 h_{i} 分别是损失函数的一阶和二阶导数,能更快地拟合新树。 

from xgboost import XGBRegressor    #从sklearn导入XGBRegressor模型
from sklearn.model_selection import train_test_split #从sklearn导入训练/测试数据集划分模块
from sklearn.datasets import make_regression         #从sklearn导入生成回归样本数据模块
from sklearn.metrics import mean_squared_error,r2_score  #模型评估MSE,R2

# 生成数据
# n_samples样本个数;n_features特征个数; noise数据噪声;random_state=42随机种子
# test_size=0.2 测试集数据占20%
X, y = make_regression(n_samples = 150, n_features = 3, noise = 0.2, random_state = 42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练模型
model = XGBRegressor(eta=0.2,n_estimators=100)  #定义了100棵树
model.fit(X_train, y_train)

# booster:默认值为 ‘gbtree’,基于树模型。 ‘gblinear’ 基于线性模型。
# silent:默认为0;当这个参数值为1时,静默模式开启,不会输出任何信息。
# nthread:默认值为最大可能的线程数。
# eta: 权重递减参数,典型值为0.01-0.2。
# min_child_weight:决定最小叶子节点样本权重和。
# max_depth:这个值为树的最大深度。
# max_leaf_nodes:树上最大的节点或叶子的数量。
# gamma:Gamma指定了节点分裂所需的最小损失函数下降值。 这个参数的值越大,算法越保守。
# max_delta_step:每棵树权重改变的最大步长。如果这个参数的值为0,那就意味着没有约束。
# alpha:权重的L1正则化项。 可以应用在很高维度的情况下,使得算法的速度更快。默认为1。
# lambda:权重的L2正则化项。默认为1。


#预测
y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)

#评估
mse_train=mean_squared_error(y_train,y_pred_train)
mse_test=mean_squared_error(y_test,y_pred_test)
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)

print(f'MSE (Train): {mse_train}')
print(f'MSE (Test): {mse_test}')
print(f'R^2 (Train): {r2_train}')
print(f'R^2 (Test): {r2_test}')

booster: 默认值为 ‘gbtree’,基于树模型。 ‘gblinear’ 基于线性模型。
silent: 默认为0;当这个参数值为1时,静默模式开启,不会输出任何信息。
nthread:默认值为最大可能的线程数。
eta: 权重递减参数,典型值为0.01-0.2。
min_child_weight:决定最小叶子节点样本权重和。
max_depth:这个值为树的最大深度。
max_leaf_nodes:树上最大的节点或叶子的数量。
gamma:gamma指定了节点分裂所需的最小损失函数下降值。 这个参数的值越大,算法越保守。
max_delta_step:每棵树权重改变的最大步长。如果这个参数的值为0,那就意味着没有约束。
alpha:权重的L1正则化项。 可以应用在很高维度的情况下,使得算法的速度更快。默认为1。
lambda:权重的L2正则化项。默认为1。

优点

  • 精度更高: GBDT 只用到一阶泰勒展开,而 XGBoost 对损失函数进行了二阶泰勒展开。XGBoost 引入二阶导一方面是为了增加精度,另一方面也是为了能够自定义损失函数,二阶泰勒展开可以近似大量损失函数。

  • 正则化: XGBoost 在目标函数中加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、叶子节点权重的  范式。正则项降低了模型的方差,使学习出来的模型更加简单,有助于防止过拟合,这也是XGBoost优于传统GBDT的一个特性。

  • 可处理高维数据:适用于高维特征的数据集。

缺点

  • 虽然利用预排序和近似算法可以降低寻找最佳分裂点的计算量,但在节点分裂过程中仍需要遍历数据集。

  • 预排序过程的空间复杂度过高,不仅需要存储特征值,还需要存储特征对应样本的梯度统计值的索引,相当于消耗了两倍的内存。

 1.7  机器学习的一般流程

如何通俗易懂的描述机器学习的流程?

 2  机器学习的python常用库

Numpy:  是一个Python库,提供了多维数组对象(ndarray)以及用于处理这些数组的函数。它是数据科学和机器学习领域最常用的库之一。Numpy提供了高效的数组操作和数学函数,使得在Python中进行数值计算更加简单和高效。 Numpy使用教程

Pandas:  为 Python 提供了高性能、易使用的数据结构与数据分析工具。 Pandas使用教程

Matplotlib:   是 Python 中最受欢迎的数据可视化工具之一,支持跨平台运行,它是 Python 常用的 2D 绘图库,同时它也提供了一部分 3D 绘图接口。 matplotlib使用教程

Scikit-Learn: 是基于 Python 语言的机器学习工具。有六大任务模块:分别是分类、回归、聚类、降维、模型选择和预处理。 scikit-learn使用教程

 今天就写到这里吧!下次基于这些回归模型,进行论文实战代码复现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小码贾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值