一. 基础理论
1.训练均方误差与测试均方误差
在回归中,我们最常用的评价指标为均方误差,即:MSE=1N∑i=1N(yi−f̂(xi))2MSE=1N∑i=1N(yi−f^(xi))2,其中f̂(xi)f^(xi)是样本xixi应用建立的模型f̂f^预测的结果。如果我们所用的数据是训练集上的数据,那么这个误差为训练均方误差,如果我们使用测试集的数据计算的均方误差,我们称为测试均方误差。
当我们的模型的训练均方误差达到很小时,测试均方误差反而很大,但是我们寻找的最优的模型是测试均方误差达到最小时对应的模型,因此基于训练均方误差达到最小选择模型本质上是行不同的。正如上右图所示:模型在训练误差很小,但是测试均方误差很大时,我们称这种情况叫模型的过拟合。
2.偏差-方差的权衡
E(y0−f^(x0))2=Var(f^(x0))+[Bias(f^(x0))]2+Var(ε)
测试均方误差的期望值可以分解为^(x0)的方差、f̂(x0)f的偏差平方和误差项ϵ的方差。Var(ε)为建模任务的难度,这个量在我们的任务确定后是无法改变的,也叫做不可约误差。
所谓模型的方差就是:用不同的数据集去估计f时,估计函数的改变量。一般来说,模型的复杂度越高,f的方差就会越大。 如加入二次项的模型的方差比线性回归模型的方差要大。
另一方面,模型的偏差是指:为了选择一个简单的模型去估计真实函数所带入的误差。模型的复杂度引起的这种误差我们称为偏差。偏差度量了学习算法的期望预测与真实结果的偏离程度,即刻画了学习算法本身的拟合能力。
偏差度量的是单个模型的学习能力,而方差度量的是同一个模型在不同数据集上的稳定性。
“偏差-方差分解”说明:泛化性能是由学习算法的能力、数据的充分性以及学习任务本身的难度所共同决定的。给定学习任务,为了取得好的泛化性能,则需使偏差较小,即能够充分拟合数据,并且使方差较小,即使得数据扰动产生的影响小。

一般而言,增加模型的复杂度,会增加模型的方差,但是会减少模型的偏差,我们要找到一个方差--偏差的权衡,使得测试均方误差最。
3.特征提取
对测试误差的估计方式有两种:训练误差修正与交叉验证。
训练误差修正:构造一个特征较多的模型,加入关于特征个数的惩罚,从而对训练误差进行修正
Cp=1N(RSS+2dσ̂2)Cp=1N(RSS+2dσ^2),其中d为模型特征个数,RSS=∑i=1N(yi−f̂(xi))2RSS=∑i=1N(yi−f^(xi))2,σ̂2σ^2为模型预测误差的方差的估计值,即残差的方差。
交叉验证:K折交叉验证:我们把训练样本分成K等分,然后用K-1个样本集当做训练集,剩下的一份样本集为验证集去估计由K-1个样本集得到的模型的精度,这个过程重复K次取平均值得到测试误差的一个估计CV(K)=1K∑i=1KMSEiCV(K)=1K∑i=1KMSEi。
最优子集选择、向前逐步选择:通过计算RSS进行迭代,每次选择RSS值最小的模型,最后选择测试误差最小的模型作为最优模型
4.压缩估计(正则化)
岭回归(L2正则化的例子):在线性回归的损失函数的基础上添加对系数λ的约束或者惩罚,通过牺牲线性回归的无偏性降低方差,有可能使得模型整体的测试误差较小,提高模型的泛化能力(无偏性的直观意义是样本估计量的数值在参数的真值附近摆动)
Lasso回归(L1正则化的例子):使用系数向量的L1范数替换岭回归中的L2范数
由于Lasso回归的RSS曲线与坐标轴相交时,回归系数中的某一个系数会为0,这样就能实现特征提取
5.降维
主成分分析(PCA):通过最大投影方差将原始空间进行重构,即由特征相关重构为特征无关,即落在某个方向上的点(投影)的方差最大
二.实战练习
1.特征提取的实例:向前逐步回归
案例来源:https://blog.csdn.net/weixin_44835596/article/details/89763300
根据AIC准则定义向前逐步回归进行变量筛选
#定义向前逐步回归函数
def forward_select(data,target):
variate=set(data.columns) #将字段名转换成字典类型
variate.remove(target) #去掉因变量的字段名
selected=[]
current_score,best_new_score=float('inf'),float('inf') #目前的分数和最好分数初始值都为无穷大(因为AIC越小越好)
#循环筛选变量
while variate:
aic_with_variate=[]
for candidate in variate: #逐个遍历自变量
formula="{}~{}".format(target,"+".join(selected+[candidate])) #将自变量名连接起来
aic=ols(formula=formula,data=data).fit().aic #利用ols训练模型得出aic值
aic_with_variate.append((aic,candidate)) #将第每一次的aic值放进空列表
aic_with_variate.sort(reverse=True) #降序排序aic值
best_new_score,best_candidate=aic_with_variate.pop() #最好的aic值等于删除列表的最后一个值,以及最好的自变量等于列表最后一个自变量
if current_score>best_new_score: #如果目前的aic值大于最好的aic值
variate.remove(best_candidate) #移除加进来的变量名,即第二次循环时,不考虑此自变量了
selected.append(best_candidate) #将此自变量作为加进模型中的自变量
current_score=best_new_score #最新的分数等于最好的分数
print("aic is {},continuing!".format(current_score)) #输出最小的aic值
else:
print("for selection over!")
break
formula="{}~{}".format(target,"+".join(selected)) #最终的模型式子
print("final formula is {}".format(formula))
model=ols(formula=formula,data=data).fit()
return(model)
import statsmodels.api as sm #最小二乘
from statsmodels.formula.api import ols #加载ols模型
forward_select(data=boston_data,target="Price")
lm=ols("Price~LSTAT+RM+PTRATIO+DIS+NOX+CHAS+B+ZN+CRIM+RAD+TAX",data=boston_data).fit() lm.summary()
2.岭回归实例分享:
sklearn.linear_model.ridge_regression(X, y, alpha, *, sample_weight=None, solver='auto', max_iter=None, tol=0.001, verbose=0, random_state=None, return_n_iter=False, return_intercept=False, check_input=True)
参数:
alpha:较大的值表示更强的正则化。浮点数
sample_weight:样本权重,默认无。
solver:求解方法,{‘auto’, ‘svd’, ‘cholesky’, ‘lsqr’, ‘sparse_cg’, ‘sag’, ‘saga’}, 默认=’auto’。“ svd”使用X的奇异值分解来计算Ridge系数。'cholesky'使用标准的scipy.linalg.solve函数通过dot(XT,X)的Cholesky分解获得封闭形式的解。'sparse_cg'使用scipy.sparse.linalg.cg中的共轭梯度求解器。作为一种迭代算法,对于大规模数据(可能设置tol和max_iter),此求解器比“ Cholesky”更合适。 lsqr”使用专用的正则化最小二乘例程scipy.sparse.linalg.lsqr。它是最快的,并且使用迭代过程。“ sag”使用随机平均梯度下降,“ saga”使用其改进的无偏版本SAGA。两种方法都使用迭代过程,并且当n_samples和n_features都很大时,通常比其他求解器更快。请注意,只有在比例大致相同的要素上才能确保“ sag”和“ saga”快速收敛。您可以使用sklearn.preprocessing中的缩放器对数据进行预处理。最后五个求解器均支持密集和稀疏数据。但是,当fit_intercept为True时,仅'sag'和'sparse_cg'支持稀疏输入。
from sklearn import linear_model reg_rid = linear_model.Ridge(alpha=.5) reg_rid.fit(X,y) reg_rid.score(X,y)
3.Lasso实例分享:
class sklearn.linear_model.Lasso(alpha=1.0, *, fit_intercept=True, normalize=False, precompute=False, copy_X=True, max_iter=1000, tol=0.0001, warm_start=False, positive=False, random_state=None, selection='cyclic')
参数:
alpha:正则化强度,1.0代表标准最小二乘。
fit_intercept:是否计算模型截距。默认true。
normalize:是否标准化,默认false。
positive:是否强制系数为正,默认false。
from sklearn import linear_model reg_lasso = linear_model.Lasso(alpha = 0.5) reg_lasso.fit(X,y) reg_lasso.score(X,y)
网友评论