掌握基本的回归模型
使用sklearn构建完整的机器学习项目流程
一般来说,一个完整的机器学习项目分为以下步骤:
- 明确任务类型:回归/分类
- 收集数据集并选择合适的特征。
- 选择度量模型性能的指标。
- 选择具体的模型并进行训练以优化模型。
- 评估模型的性能并调参。
使用sklearn构建完整的回归项目
1.首先任务类型已指定:回归任务。
2.收集数据集并选择合适的特征:
3.选择度量模型性能的指标:
- MSE均方误差:mean_squared_error 函数计算均方误差
- MAE平均绝对误差:平均绝对误差可以避免误差相互抵消的问题,因而可以准确反映实际预测误差的大小,mean_absolute_error 函数计算平均绝对误差。
- 𝑅2拟合优度:拟合优度反应了y的波动有多少百分比能被x的波动所描述,即表征依变数Y的变异中有多少百分比,可由控制的自变数X来解释,r2_score函数计算拟合优度。
- 解释方差: explained_variance_score 函数计算解释方差,其值取值范围是[0,1],越接近于1说明自变量越能解释因变量
的方差变化,值越小则说明效果越差。 - 最大残留误差:捕获预测值和真实值之间最坏情况误差的度量,max_error函数计算最大残留误差。
- 均方对数误差:计算对应于平方对数(二次)误差或损失的期望值的风险度量, mean_squared_log_error函数计算均方对数误差。
- 平均绝对百分比误差:
- 中位数绝对误差:
4.选择具体的模型并进行训练:
回归的概念:在大数据分析中,回归分析是一种预测性的建模技术,它研究的是因变量(目标)和自变量(预测器)之间的关系。这种技术通常用于预测分析,时间序列模型以及发现变量之间的因果关系,当因变量和自变量为线性关系时,它是一种特殊的线性模型。高尔顿在研究父母和子代身高关系时,观察得出的父母平均身高比子女平均身高矮一英寸,数据分布近似线性方程。他发现,在实际中,父母身高更高或更矮时,子女实际身高并不是比父母身高高一英寸,而是父母过矮的,子女比父母身高高不止一英寸,父母过高的,子女比父母身高还矮一点,也就是更接近平均身高。所以他认为自然界有一种约束力,使得身高的分布不会向高矮两个极端发展,而是趋于回到中心,所以称为回归。
- 线性回归模型:
(a) 最小二乘估计:
我们需要衡量真实值 𝑦𝑖 与线性回归模型的预测值 𝑤𝑇𝑥𝑖 之间的差距,在这里我们和使用二范数(||A||2指矩阵A的2范数,就是A的转置共轭矩阵与矩阵A的积的最大特征根的平方根值,是指空间上两个向量矩阵的直线距离。类似于求棋盘上两点间的直线距离。具体到复数里,共轭/Hermite就是实部相同,虚部相反的意思,Hermite阵主对角线上的元素必须是实数。对于只包含实数元素的矩阵(实矩阵),如果它是对称阵,即所有元素关于主对角线对称,那么它也是Hermite阵)的平方和L(w)来描述这种差距,即:
因此,我们需要找到使得𝐿(𝑤)最小时对应的参数𝑤,即:
为了达到求解最小化𝐿(𝑤)问题,我们应用高等数学的知识,使用求导来解决这个问题:
,因此:
(b) 几何解释:
在线性代数中,我们知道两个向量a和b相互垂直可以得出: ,而平面X的法向量为Y-Xw,与平面X互相垂直,因此: ,即:
下面我们用sklearn来演示一个线性回归模型:
from sklearn import linear_model # 引入线性回归方法
lin_reg = linear_model.LinearRegression() # 实例化一个线性回归的类
lin_reg.fit(X,y) # 输入特征X和因变量y进行训练
print("模型系数:",lin_reg.coef_) # 输出模型的系数
print("模型得分:",lin_reg.score(X,y)) # 输出模型的决定系数R^2
得到输出:
模型系数: [-1.08011358e-01 4.64204584e-02 2.05586264e-02 2.68673382e+00 -1.77666112e+01 3.80986521e+00 6.92224640e-04 -1.47556685e+00
3.06049479e-01 -1.23345939e-02 -9.52747232e-01 9.31168327e-03
-5.24758378e-01]
模型得分: 0.7406426641094095
- 线性回归模型的推广
在线性回归中,我们假设因变量与特征之间的关系是线性关系,这样的假设使得模型很简单,但是缺点也是显然的,那就是当数据存在非线性关系时,我们使用线性回归模型进行预测会导致预测性能极其低下,因为模型的形式本身是线性的,无法表达数据中的非线性关系。我们一个很自然的想法就是去推广线性回归模型,使得推广后的模型更能表达非线性的关系。
a. 多项式回归:
为了体现因变量和特征的非线性关系,一个很自然而然的想法就是将标准的线性回归模型:
换成一个多项式函数:
对于多项式的阶数d不能取过大,一般不大于3或者4,因为d越大,多项式曲线就会越光滑,在X的边界处有异常的波动。(图中的边界处的4阶多项式拟合曲线的置信区间(虚线表示置信区间)明显增大,预测效果的稳定性下降。)
b. 广义可加模型GAM:
回归模型中部分或全部的自变量采用平滑函数,降低线性设定带来的模型风险,对模型的假定不严,如不需要假定自变量线性相关于因变量(线性或非线性都可以)。解决logistic回归当解释变量个数较多时容易引起维度灾难(Curse of dimensionality)。光滑函数如应用到连续型解释变量。
标准的线性回归模型:
GAM模型框架:
GAM模型的优点与不足:
- 优点:简单容易操作,能够很自然地推广线性回归模型至非线性模型,使得模型的预测精度有所上升;由于模型本身是可加的,因此GAM还是能像线性回归模型一样把其他因素控制不变的情况下单独对某个变量进行推断,极大地保留了线性回归的易于推断的性质。
- 缺点:GAM模型会经常忽略一些有意义的交互作用,比如某两个特征共同影响因变量,不过GAM还是能像线性回归一样加入交互项的形式进行建模;但是GAM模型本质上还是一个可加模型,如果我们能摆脱可加性模型形式,可能还会提升模型预测精度,详情请看后面的算法。
(a) 多项式回归实例介绍:
from sklearn.preprocessing import PolynomialFeatures
X_arr = np.arange(6).reshape(3, 2)
print("原始X为:\n",X_arr)
poly = PolynomialFeatures(2)
print("2次转化X:\n",poly.fit_transform(X_arr))
poly = PolynomialFeatures(interaction_only=True)
print("2次转化X:\n",poly.fit_transform(X_arr))
class sklearn.preprocessing.PolynomialFeatures(degree=2, *, interaction_only=False, include_bias=True, order=‘C’)
参数解释:
degree:特征转换的阶数。
interaction_onlyboolean:是否只包含交互项,默认False 。
include_bias:是否包含截距项,默认True。
order:str in {‘C’, ‘F’}, default ‘C’,输出数组的顺序。
得到输出:
原始X为:
[[0 1]
[2 3]
[4 5]]
2次转化X:
[[ 1. 0. 1. 0. 0. 1.]
[ 1. 2. 3. 4. 6. 9.]
[ 1. 4. 5. 16. 20. 25.]]
2次转化X:
[[ 1. 0. 1. 0.]
[ 1. 2. 3. 6.]
[ 1. 4. 5. 20.]]
(b) GAM模型实例介绍:
需要安装pygam第三方库
from pygam import LinearGAM
import pandas as pd
from sklearn import datasets
boston = datasets.load_boston() # 返回一个类似于字典的类
X = boston.data
y = boston.target
features = boston.feature_names
boston_data = pd.DataFrame(X,columns=features)
gam = LinearGAM().fit(boston_data[boston.feature_names], y)
gam.summary()
- 决策树
决策树是一种基本的分类与回归方法,根据处理数据类型的不同,决策树又分为两类:分类决策树与回归决策树。分类决策树可用于处理离散型数据,回归决策树可用于处理连续型数据。决策树由结点(node)和有向边(diredcted edge)组成。结点有两种类型:内部结点(internal node)和叶结点(leaf node)。内部结点表示一个特征或属性,叶结点表示一个类别或者某个值。
建立回归树的过程大致可以分为两步:
- 将预测变量空间的可能取值构成的集合分割成J JJ个互不重叠的区域
- 对落入区域的每个观测值作同样的预测,预测值等于上训练集的各个样本取值的算术平均数。
小二乘回归树的生成方法如下:
- 选择最优的切分变量j和最优的切分点s,求解
- 用选定的对 (j,s)划分区域,并确定该区域的预测值,
- 继续对两个字区域调用上述步骤,直至满足停止条件。
- 生成回归树,
回归树与线性模型的比较:
如果特征变量与因变量的关系能很好的用线性关系来表达,那么线性回归通常有着不错的预测效果,拟合效果则优于不能揭示线性结构的回归树。反之,如果特征变量与因变量的关系呈现高度复杂的非线性,那么树方法比传统方法更优。
数模型的优缺点:
- 决策树易于理解和解释,可以可视化分析,容易提取出规则;
- 比较适合处理有缺失属性的样本;
- 能够处理不相关的特征;
- 树模型容易发生过拟合(随机森林可以很大程度上减少过拟合);
- 树模型容易忽略数据集中属性的相互关联;
sklearn使用回归树的实例:
class sklearn.tree.DecisionTreeRegressor(*, criterion=‘mse’, splitter=‘best’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, ccp_alpha=0.0)
参数:
criterion:{“ mse”,“ friedman_mse”,“ mae”},默认=“ mse”。衡量分割标准的函数 。
splitter:{“best”, “random”}, default=”best”。分割方式。
max_depth:树的最大深度。
min_samples_split:拆分内部节点所需的最少样本数,默认是2。
min_samples_leaf:在叶节点处需要的最小样本数。默认是1。
min_weight_fraction_leaf:在所有叶节点处(所有输入样本)的权重总和中的最小加权分数。如果未提供sample_weight,则样本的权重相等。默认是0。
max_features:划分时考虑的最大特征数。默认是"None",意味着划分时考虑所有的特征数;如果是"log2"意味着划分时最多考虑log2Nlog2N个特征;如果是"sqrt"或者"auto"意味着划分时最多考虑N−−√N个特征。如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数。其中N为样本总特征数。一般来说,如果样本特征数不多,比如小于50,我们用默认的"None"就可以了。
random_state:这是一个随机种子,是在任意带有随机性的类或函数里作为参数来控制随机模式。当random_state取某一个值时,也就确定了一种规则。如果为整数,则它指定了随机数生成器的种子;如果为RandomState实例,则指定了随机数生成器;如果为None,则使用默认的随机数生成器。
max_leaf_nodes:如果为None,则叶子节点数量不限;反之,则max_depth被忽略。
min_impurity_decrease:如果节点的分裂导致不纯度的减少(分裂后样本比分裂前更加纯净)大于或等于min_impurity_decrease,则分裂该节点。
个人理解这个参数应该是针对分类问题时才有意义。这里的不纯度应该是指基尼指数。回归生成树采用的是平方误差最小化策略。分类生成树采用的是基尼指数最小化策略。加权不纯度的减少量计算公式为:
min_impurity_decrease=N_t / N *(impurity-N_t_R / N_t * right_impurity- N_t_L / N_t * left_impurity)
其中N是样本的总数,N_t是当前节点的样本数,N_t_L是分裂后左子节点的样本数,N_t_R是分裂后右子节点的样本数。impurity指当前节点的基尼指数,right_impurity指分裂后右子节点的基尼指数。left_impurity指分裂后左子节点的基尼指数。
from sklearn.tree import DecisionTreeRegressor
reg_tree = DecisionTreeRegressor(criterion = "mse",min_samples_leaf = 5)
reg_tree.fit(X,y)
reg_tree.score(X,y)
得到输出:
0.9376307599929274
支持向量机回归SVR
svr的优化目标是l2 regularization+ c*epsilon-sensitive error. 前者正则化是为了控制模型复杂度不必多说,后者epsilon-sensitive error是理解svr的关键,但其实对照linear regression的损失函数也很容易,就如下图所示
左边是svr 的loss function,右图是lr的(图片来自coursera 林轩田机器学习技法)左图中,epsilon描述的是紫色区域的宽度,定义这个区域内的点损失为0,这个区域以外的点的损失是点到区域边界的距离,这些区域外的点(或者有可能边界上的点)就是svr 的support vector。所以大致上来说,svr就是要找一条线,忽略它周围的点,对剩余的点进行回归。
- 约束优化问题§:
我们假设为满足以上条件的局部最优解,,我们的目的就是要找到与,满足不等式和等式约束的x集合成为可行域,记作S。
- KKT条件(最优解的一阶必要条件)
因为KKT条件是最优化的相关内容,在本次开源学习中并不是重点,因此在这里我用一个更加简单的例子说明KKT条件,严格的证明请参见凸优化相关书籍。
在这个例子中,我们考虑:(为我们的最优解) - 我们可以看到:可以由与线性表出,因此有:,其中,即:
我们把没有起作用的约束也放到式子里面去,目的也就是为了书写方便,即要求:
由于点位于方程与上,因此:
因此,KKT条件就是:假设为最优化问题§的局部最优解,且 在某个适当的条件下 ,有:
- 对偶理论:
为什么要引入对偶问题呢?是因为原问题与对偶问题就像是一个问题两个角度去看,如利润最大与成本最低等。有时侯原问题上难以解决,但是在对偶问题上就会变得很简单。再者,任何一个原问题在变成对偶问题后都会变成一个凸优化的问题,这点我们后面会有介绍。下面我们来引入对偶问题:
首先,我们的原问题§是:
引入拉格朗日函数:
拉格朗日对偶函数:
因此:拉格朗日对偶函数是原问题最优解的函数值的下界,即每个不同的与确定的都是的下界,但是我们希望下界越大越好,因为越大就更能接近真实的。因此:
拉格朗日对偶问题(D)转化为:
我们可以观察到,对偶问题是关于和的线性函数,因此对偶问题是一个凸优化问题,凸优化问题在最优化理论较为简单。
弱对偶定理:对偶问题(D)的最优解一定小于原问题最优解,这点在刚刚的讨论得到了充分的证明,一定成立。
强对偶定理:对偶问题(D)的最优解在一定的条件下等于原问题最优解,条件非常多样化且不是唯一的,也就是说这是个开放性的问题,在这里我给出一个最简单的条件,即:与为凸函数,为线性函数,X是凸集,满足KKT条件,那么。
支持向量回归SVR - 在线性回归的理论中,每个样本点都要计算平方损失,但是SVR却是不一样的。SVR认为:落在的邻域空间中的样本点不需要计算损失,这些都是预测正确的,其余的落在邻域空间以外的样本才需要计算损失,因此:
引入拉格朗日函数:
再令对求偏导等于0,得: 。
上述过程中需满足KKT条件,即要求:
SVR的解形如:
sklearn中使用SVR实例:
class sklearn.svm.SVR(*, kernel=‘rbf’, degree=3, gamma=‘scale’, coef0=0.0, tol=0.001, C=1.0, epsilon=0.1, shrinking=True, cache_size=200, verbose=False, max_iter=- 1)
参数解释:
- kernel:核函数,{‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’}, 默认=’rbf’。(后面会详细介绍)
- degree:多项式核函数的阶数。默认 = 3。
- C:正则化参数,默认=1.0。(后面会详细介绍)
- epsilon:SVR模型允许的不计算误差的邻域大小。默认0.1。
from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler # 标准化数据
from sklearn.pipeline import make_pipeline # 使用管道,把预处理和模型形成一个流程
reg_svr = make_pipeline(StandardScaler(), SVR(C=1.0, epsilon=0.2))
reg_svr.fit(X, y)
reg_svr.score(X,y)
得到输出:
0.7024525421955277