2.1.1线性回归的推广 task2
1.多项式的回归
将标准的线性函数换成一个多项式函数
但是阶数d不宜过大,否则容易造成过拟合,一些噪声点也会拟合到,从而让模型的稳定性变差
// A code block
var foo = 'bar';
// An highlighted block
from sklearn.preprocessing import PolynomialFeatures
x_arr=np.arange(6).reshape(3,2)
print('原始矩阵为:',x_arr)
poly=PolynomialFeatures(2)
print('两次转化为:',poly.fit_transform(x_arr))
poly=PolynomialFeatures(interaction_only=True)
print('两次转化为:',poly.fit_transform(x_arr))
参数解读:interaction_onlyboolean:是否只包含交互项,默认为false
include_bias:是否包含截距项,默认为True
2.广义可加模型(GAM)
GAM模型是一种框架,可以使线性回归的特征都用一个非线性函数来代替,但是模型本身保留可加性
GAM模型可以控制其他因素不变单独对某个变量进行推断,保留线性回归的易推断性
// A code block
var foo = 'bar';
// An highlighted block
from pygam import LinearGAM
gam=LinearGAM().fit(x,y)
gam.summary()
决策回归树
如果特征变量与因变量之间存在线性关系,线性回归的效果可能更好一些,如果存在非线性关系,则决策回归数更好
支持向量机回归SVR
SVR作为SVM的的分支,主要目标为要使到超平面的最远的样本点的距离最小,通过最大化间隔带的宽度与最小化总损失来优化模型
当数据为非线性的时候,SVR的核函数会把数据映射到一个高维空间,其主要核函数为
// A code block
var foo = 'bar';
// An highlighted block
from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler # 标准化数据
from sklearn.pipeline import make_pipeline # 使用管道,把预处理和模型形成一个流程
reg_svr=make_pipeline(StandardScaler(),SVR(kernel='linear',C=1.0,epsilon=0.2))
reg_svr.fit(x,y)
reg_svr.score(x,y)
主要参数说明:
2.1.2偏差和方差理论 task3
模型的偏差:模型的预测值与真实值之间的差异,即每一个红点到蓝线的距离。在集成算法中,每个基评估器都会有自己的偏差,集成评估器的偏差是所有基评估器偏差的均值。模型越精确,偏差越低。
模型的方差:反映的是模型每一次输出结果与模型预测值的平均水平之间的误差,即每一个红点到红色虚线的距离,衡量模型的稳定性。模型越稳定,方差越低。
特征提取:
主要目标:我们要选择一个测试误差达到最小的模型。但是实际上我们很难对实际的测试误差做精确的计算,因此我们要对测试误差进行估计,估计的方式有两种:训练误差修正与交叉验证。
训练误差修正:
模型越复杂,训练误差越小,测试误差先减后增。因此,我们先构造一个特征较多的模型使其过拟合,此时训练误差很小而测试误差大,那这时我们加入关于特征个数的惩罚。因此,当我们的训练误差随着特征个数的增加而减少时,惩罚项因为特征数量的增加而增大,抑制了训练误差随着特征个数的增加而无休止地减小。
交叉验证:
加入正则化(岭回归和lasso回归)
在线性回归的损失函数上添加对系数的约束或者惩罚,岭回归和lasso回归的区别在于岭回归尽可能把系数压缩到0但不会成为0,所以岭回归无法做到特征提取(但是将正则化项换成lasso的也可以),lasso回归可以做到特征提取
向前逐步回归:
逐步回归分为三种,分别是向前逐步回归,向后逐步回归,逐步回归。向前逐步回归的特点是将自变量一个一个当如模型中,每当放入一个变量时,都利用相应的检验准则检验,当加入的变量不能使得模型变得更优良时,变量将会被剔除,如此不断迭代,直到没有适合的新变量加入为止。向后逐步回归的特点是,将所有变量都放入模型之后,一个一个的剔除变量,将某一变量拿出模型而使得模型更优良时,将会剔除此变量。如此反复迭代,直到没有合适的变量剔除为止。逐步回归则是结合了以上的向前和向后逐步回归的特点。
#定义向前逐步回归函数
def forward_select(data,target):
variate=set(data.columns) #将字段名转换成字典类型
variate.remove(target) #去掉因变量的字段名
selected=[]
current_score,best_new_score=float('inf'),float('inf') #目前的分数和最好分数初始值都为
#循环筛选变量
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")
ols模型:最小二乘法
lm=ols("price~LSTAT+RM+PTRATIO+DIS+NOX+CHAS+B+ZN+CRIM+RAD+TAX",data=boston_data).fit()
lm.summary()
from sklearn import linear_model
reg_rid = linear_model.Ridge(normalize=True,alpha=0.3)
reg_rid.fit(x,y)
reg_rid.score(x,y)
参数解读:
from sklearn import linear_model
reg_lasso = linear_model.Lasso(normalize=False,alpha = 0.1)
reg_lasso.fit(x,y)
reg_lasso.score(x,y)
参数解读:
2.1.2回归模型的评估和超参数调优 task4
配合pipeline,pipeline可以将可以抽象为一个包括多个步骤的流水线式工作,从数据收集开始至输出我们需要的最终结果。因此,对以上多个步骤、进行抽象建模,简化为流水线式工作流程则存在着可行性,对利用spark进行机器学习的用户来说,流水线式机器学习比单个步骤独立建模更加高效、易用。
首先要确定参数和非参数的区别
参数:形如线性回归中的beta0,beta1,beta2等,可以通过最小二乘法计算出来的
超参数:形如随机森林中树的个数,这种需要通过网格搜索,和其他超参数形如max_depth等结合
# 我们先来对未调参的SVR进行评价:
from sklearn.svm import SVR # 引入SVR类
from sklearn.pipeline import make_pipeline # 引入管道简化学习流程
from sklearn.preprocessing import StandardScaler # 由于SVR基于距离计算,引入对数据进行标准
from sklearn.model_selection import GridSearchCV # 引入网格搜索调优
from sklearn.model_selection import cross_val_score # 引入K折交叉验证
from sklearn import datasets
boston = datasets.load_boston() # 返回一个类似于字典的类
X = boston.data
y = boston.target
features = boston.feature_names
pipe_SVR = make_pipeline(StandardScaler(),
SVR())
score1 = cross_val_score(estimator=pipe_SVR,
X = x,
y = y,
scoring = 'r2',
cv = 10) # 10折
print("CV accuracy: %.3f +/- %.3f" % ((np.mean(score1)),np.std(score1)))
estimator:选择使用的分类器,并且传入除需要确定最佳的参数之外的其他参数。
from sklearn.pipeline import Pipeline
pipe_svr = Pipeline([("StandardScaler",StandardScaler()),
("svr",SVR())])
param_range = [0.0001,0.001,0.01,0.1,1.0,10.0,100.0,1000.0]
param_grid = [{"svr__C":param_range,"svr__kernel":["linear"]}, # 注意__是指两个下划线,一个下划线会报错的
{"svr__C":param_range,"svr__gamma":param_range,"svr__kernel":["rbf"]}]
gs = GridSearchCV(estimator=pipe_svr,
param_grid = param_grid,
scoring = 'r2',
cv = 10) # 10折交叉验证
gs = gs.fit(X,y)
print("网格搜索最优得分:",gs.best_score_)
print("网格搜索最优参数组合:\n",gs.best_params_)
# 下面我们使用随机搜索来对SVR调参:
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import uniform # 引入均匀分布设置参数
pipe_svr = Pipeline([("StandardScaler",StandardScaler()),
("svr",SVR())])
distributions = dict(svr__C=uniform(loc=1.0, scale=4), # 构建连续参数的分布
svr__kernel=["linear","rbf"], # 离散参数的集合
svr__gamma=uniform(loc=0, scale=4))
rs = RandomizedSearchCV(estimator=pipe_svr,
param_distributions = distributions,
scoring = 'r2',
cv = 10) # 10折交叉验证
rs = rs.fit(X,y)
print("随机搜索最优得分:",rs.best_score_)
print("随机搜索最优参数组合:\n",rs.best_params_)
网格搜索可以计算出最优的超参数组合,作为最为常见的超参数寻找方法,但是缺点也比较明显,当数据集较大时,网格搜索往往需要的时间比较长。
网格搜索往往可以搭配评价指标的可视化来进行