相关阅读:
- 【机器学习竞赛+笔记干货】工业蒸汽量预测:赛题理解篇(一)
- 【机器学习竞赛+笔记干货】工业蒸汽量预测:数据探索篇(二)
- 【机器学习竞赛+笔记干货】工业蒸汽量预测:特征工程篇(三)
- 【机器学习竞赛+笔记干货】工业蒸汽量预测:模型训练篇(四)
- 【机器学习竞赛+笔记干货】工业蒸汽量预测:模型验证篇(五)
- 【机器学习竞赛+笔记干货】工业蒸汽量预测:特征优化篇(六)
- 【机器学习竞赛+笔记干货】工业蒸汽量预测:模型融合篇(七)
比赛地址:工业蒸汽量预测_学习赛_天池大赛
5 模型验证
5.1 模型评估的概念和方法
5.1.1 欠拟合和过拟合
数据关系是样本的分布规律,或者是特征与对应样本之间的关系。
- 欠拟合(underfitting),也称高偏差(bias)
一般可通过增加额外特征、增加多项式特征、减小 λ \lambda λ的值等方法优化模型。 - 过拟合(overfitting),也称高方差(variance)
一般可通过收集更多数据、使用更少的特征、增加 λ \lambda λ的值等方法优化模型。
5.1.2 模型的泛化和正则化
正则化(Regularization)是给需要训练的目标函数加上一些规则(限制),目的是为了防止过拟合。
- L1范数
∥ x ∥ 1 = ∑ i = 1 N ∣ x i ∣ \Vert{x}\Vert_1=\sum^N_{i=1}{\vert{x_i}\vert} ∥x∥1=i=1∑N∣xi∣
即向量元素绝对值之和。 - L2范数
∥ x ∥ 2 = ( ∑ i = 1 N ∣ x i ∣ 2 ) 1 2 \Vert{x}\Vert_2=(\sum^N_{i=1}{\vert{x_i}\vert^2})^\frac{1}{2} ∥x∥2=(i=1∑N∣xi∣2)21
又叫欧几里得(Euclid)范数,即向量元素绝对值平方和再进行平方。 - L-q范数
∥ x ∥ q = ( ∑ i = 1 N ∣ x i ∣ q ) 1 q \Vert{x}\Vert_q=(\sum^N_{i=1}{\vert{x_i}\vert^q})^\frac{1}{q} ∥x∥q=(i=1∑N∣xi∣q)q1
即向量元素绝对值的q次幂的累加和再 1 q \frac{1}{q} q1次幂。
from sklearn.linear_model import SGDRegressor
clf=SGDRegressor(max_iter=1000,tol=1e-3,penalty='L2',alpha=0.0001)
2. 岭回归和LASSO回归
在原始的损失函数后添加正则项,可以减小模型学习到的 θ \theta θ的大小,使模型的泛化能力更强。
- 对参数空间进行L1范数正则化的线性模型称为岭回归(Ridge Regression)
- 对参数空间进行L2范数正则化的线性模型称为LASSO回归(LASSO Regression)
两者不同之处:
(1)使用岭回归改进的多项式回归算法,随着 α \alpha α的改变,拟合曲线始终是曲线,直到最后变成一条几乎水平的直线,也就是说,在使用岭回归后,多项式回归算法在模型变量前还是有系数的,因此很难得到一条斜的直线。
(2)使用LASSO回归改进的多项式回归算法,随着 α \alpha α的改变,拟合曲线会很快变成一条斜的直线,最后慢慢变成一条几乎水平的直线。
5.1.3 回归模型的评估指标和调用方法
回归模型的评估有平均绝对值误差、均方误差、均方根误差和R平方值四种方法。
1. 平均绝对值误差
M A E = 1 n ∑ i = 1 n ∣ f i − y i ∣ = 1 n ∑ i = 1 n ∣ e i ∣ MAE=\frac{1}{n}\sum^n_{i=1}{\vert{f_i-y_i}\vert}=\frac{1}{n}\sum^n_{i=1}{\vert{e_i}\vert} MAE=n1i=1∑n∣fi−yi∣=n1i=1∑n∣ei∣
2. 均方误差
M S E = 1 n ∑ i = 1 n ( o b s e r v e d i − p r e d i t e d i ) 2 MSE=\frac{1}{n}\sum^n_{i=1}{(observed_i-predited_i)^2} MSE=n1i=1∑n(observedi−preditedi)2
3. 均方根误差
R M S E = M S E = S S E / N = 1 n ∑ i = 1 n w i ( y i − y i ^ ) 2 RMSE=\sqrt{MSE}=\sqrt{SSE/N}=\sqrt{\frac{1}{n}\sum^n_{i=1}{w_i(y_i-\hat{y_i})^2}} RMSE=MSE=SSE/N=n1i=1∑nwi(yi−yi^)2
4. R平方值
R 2 ( y , y ^ ) = 1 − ∑ i = 0 n s a m p l e s − 1 ( y i − y i ^ ) 2 ∑ i = 0 n s a m p l e s − 1 ( y i − y i ‾ ) 2 R^2(y,\hat{y})=1-\frac{\sum^{n_samples-1}_{i=0}(y_i-\hat{y_i})^2}{\sum^{n_samples-1}_{i=0}(y_i-\overline{y_i})^2} R2(y,y^)=1−∑i=0nsamples−1(yi−yi)2∑i=0nsamples−1(yi−yi^)2
5.1.4 交叉验证
1. 简单交叉验证
简单交叉验证是将原始数据随机分为两组,一组作为训练集,另一组作为验证集。通常划分30%的数据作为测试数据。
2. K折交叉验证
K折交叉验证(K-Fold Cross Validation)是将原始数据分为K组,然后每个子集数据分别做一次验证集,其余K-1组子集数据作为训练集,得到K个模型,将K个模型最终的验证集的分类准确率取平均值,作为K折交叉验证分类器的性能指标。通常设置K大于或等于3。
3. 留一法交叉验证
留一法交叉验证(Leave-One-Out Cross Validation,LOO-CV)是指每个训练集由除一个原本之外的其余样本组成,留一个样本组成检验集,最后训练得到N个模型,用N个模型最终的验证集的分类准确率取平均值,作为分类器的性能指标。
4. 留P法交叉验证
留P法交叉验证(Leave-P-Out Cross Validation,LPO-CV)是从完整的数据集中删除p个样本,产生所有可能的训练集和检验集。
5. 几种交叉验证在sklearn中的调用方法示例代码
from sklearn.model_selection import train_test_split,Kfold,LeaveOneOut,LeavePOut
X_train,X_test,y_train,y_test=train_test_split(data,target,test_size=.4,random_state=0)
kf=Kfold(n_split=10)
loo=LeaveOneOut()
lpo=LeavePOut(p=5)
5. 其他交叉验证分割方法
(1)基于类标签,具有分层的交叉验证
主要用于解决样本不平衡的问题。
一些分类问题在目标类别的分布式可能表现出很大的不平衡性,如可能会出现比正样本多数倍的负样本,在这种情况下,采用如StratifiedKFold和StratifiedShuffleSplit的分层抽样方法,可以确保相应的类别频率在每个训练和验证的折叠(fold)中得以保留。
- StratifiedKFold是K-Fold的变种,会返回stratified(分层)的折叠:在每个小集合中,各个类别的样例比例大致和完整数据集中的相同。
- StratifiedShuffleSplit是ShuffleSplit的一个变种,会返回直接的划分,比如创建一个划分,但是划分中每个类的比例和完整数据集中的相同。
(2)用于分组数据的交叉验证
主要用于进一步测试模型的泛化能力。
为了衡量一组特定数据上训练的模型能否很好地适用于新数据,需要确保验证数据中地所有样本均未在配对训练折叠中出现过,采用的办法就是流出一组特定的不属于测试集和训练集的数据。
- GroupKFold是K-Fold的变种,确保同一个组在测试集和训练集中都不被表示。
- LeaveOneGroupOut根据用户提供的整数组的数组来区别不同的组,以此来提供样本。
- LeavePGroupOut类似于LeaveOneGroupOut。
- GroupShuffleSplit生成一个随即划分的分区的序列,为每个组提供一个组子集。
(3)时间序列分割
TimeSeriesSplit是K-Fold的变种,首先返回K折作为训练数据集,把K+1折作为测试数据集。
有关时间序列的样本切分必须保证时间上的顺序性,不能用未来的数据去验证现在数据的正确性,只能用时间上之前一段的数据建模,而用后一段时间的数据来验证模型预测的效果。
5.2 模型调参
5.2.1 调参
1.调参的目标
达到整体模型的偏差和方差的大和谐。
- 过程影响类参数
子模型数(n_estimators)、学习率(learning_rate)等。 - 子模型影响类参数
最大数深度(max_depth)、分裂条件(criterion)等。
bagging的训练过程旨在降低方差,boosting的训练过程旨在降低偏差,过程影响类参数能够引起整体模型性能的大幅度变化。
5.2.2 网格搜索
网格搜索(Grid Search)是一种穷举搜索的调参手段。
在所有的候选参数中,通过循环遍历,尝试每一种可能性,变现最好的参数就是最终结果。
from sklearn.svm import SVC
# grid search start
best_score=0
for gamma in [0.001,0.01,0.1,1,10,100]:
for C in [0.001,0.01,0.1,1,10,100]:
svm=SVC(gamma=gamma,C=C)
svm.fit(X_train,y_train)
score=svm.score(X_test,y_test)
if score>beat_score:
best_score=score
best_parameters={
'gamma':gamma,'C':C}
print('Best score:{:.2f}'.format(best_score))
print('Best parameters:{}'.format(best_parameters))
5.2.3 学习曲线
学习曲线是在训练集大小不同时,通过绘制模型训练集和交叉验证集上的准确率来观察模型在新数据上的表现,进而判断模型的方差或偏差是否过高,以及增大训练集是否可以减小过拟合。
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import ShuffleSplit
from sklearn.linear_model import SGDRegressor
from sklearn.model_selection import learning_curve
plt.figure(figsize=(18,10),dpi=150)
def plot_learning_curve(estimator,titler,X,y,ylim=None,cv=None,n_jobs=1,train_sizes=np.linspace(.1,1.0,5)):
plt.figure()
pIt.title(title)
if ylim is not None:
plt.ylim(*ylim)
plt.xlabel("Training examples")
plt.ylabel("Score")
train_sizes,train_scores,test_scores=learning curve(estimator,X,y,cv=cv,n_jobs=n_jobs,train_sizes=train_sizes)
train_scores_mean=np.mean(train_scores,axis=1)
train_scores_std=np.std(train_scores,axis=l)
test_scores_mean=np.mean(test_scores,axis=l)
test_scores_std=np.std(test_scores,axis=1)
plt.grid()
plt.fill_between(train_sizes,train_scores_mean-train_scores_std,train_scores_mean+train_scores_std,alpha=0.1,color="r")
plt.fill_between(train_sizes,test_scores_mean-test_scores_std,test_scores_mean+test_scores_std,alpha=0.1,color="g")
plt.plot(train_sizes,train_scores_mean,'o-',color="r",label="Training score")
plt.plot(train_sizes,test_scores_mean,'o-',color="g",label="Cross-validation score")
plt.legend(loc="best")
return plt
X=train_data2[test_data2.columns].values
y=train_data2['target'].values
title="LinearRegression"
# Cross validation with 100 iterations to get smoother mean test and train
# score curves,each time with 20% data randomly selected as a validation set.
cv=ShuffleSplit(n_splits=100,test_size=0.2,random_state=0)
estimator=SGDRegressor()
plot_learning_curve(estimator,title,X,y,ylim=(0.7,1.01),cv=cv,n_jobs=-l)
5.2.4 验证曲线
验证曲线的横轴为某个超参数的一系列值,由此比较不同参数设置下(而非不同训练集大小)模型的准确率。
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import SGDRegressor
from sklearn.model_selection import validation_curve
X=train_data2[test_data2.columns].values
y=train_data2['target'].values
param_range=[0.1,0.01,0.001,0.0001,0.00001,0.000001]
train_scores,test_scores=validation_curve(SGDRegressor(max_iter=1000,tol=1e-3,penalty='L1'),X,y,param_name='alpha',param_range=param_range,cv=10,scoring='r2',n_jobs=1)
train_scores_mean=np.mean(train_scores,axis=1)
train_scores_std=np.std(train_scores,axis=l)
test_scores_mean=np.mean(test_scores,axis=l)
test_scores_std=np.std(test_scores,axis=1)
plt.title("Validation Curve with SGDRegressor")
plt.xlabel("alpha")
plt.ylabel("Score")
plt.ylim(0.0,1.1)
plt.semilogx(param_range,train_scores_mean,label="Training score",color="r")
plt.fill_between(param_range,train_scores_mean-train_scores_std,train_scores_mean+train_scores_std,alpha=0.2,color="r")
plt.semilogx(param_range,test_scores_mean,label="Cross-validation score",color="g")
plt.fill_between(param_range,test_scores_mean-test_scores_std,test_scores_mean+test_scores_std,alpha=0.2,color="g")
plt.legend(loc="best")
plt.show()
5.3 赛题模型验证和调参
5.2.3 模型正则化
3. ElasticNet联合L1和L2范数加权正则化
from sklearn.linear_model import SGDRegressor
clf=SGDRegressor(max_iter=1000,tol=1e-3,penalty='elasticnet',l1_ratio=0.9,alpha=0.0001)
5.3.3 模型交叉验证
1. 简单交叉验证
#简单交叉验证
from sklearn.model_selection import train_test_split
train_data,test_data,train_target,test_target=train_test_split(train,target,test_size=0.2,random,state=0)
clf=SGDRegressor(max_iter=1000,tol=1e-3)
clf.fit(train_data,train_target)
score_train=mean_squared_error(train_target,clf.predict(train_data))
score_test=mean_squared_error(test_traget,clf.predict(test_data))
print("SGDRegressor train MSE: ",score_train)
print("SGDRegressor test MSE: ",score_test)
2. K折交叉验证
#5折交叉验证
from sklearn.model selection import KFold
kf=KFold(n_splits=5)
for k,(train_index,test_index) in enumerate(kf.split(train)):
train_data,test_data,train_target,test_target=train.values[train_index],train.values[test_index], target[train_index],target[test_index]
clf=SGDRegressor(max_iter=1000,tol=le-3)
clf.fit(train_data,train_target)
score_train=mean_squared_error(train_target,clf.predict(train_data))
score_test=mean_squared_error(test_target,clf.predict(test_data))
print(k,"折","SGDRegressor train MSE:",score_train)
print(k,"折","SGDRegressor test MSE:",score_test,'\n')
5.3.4 模型超参空间及调参
1. 穷举网格搜索
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomDorestRegressor
randomForestRegressor=RandomForestRegressor()
parameters={
'n_estimators':[50,100,200],'max_depth':[1,2,3]}
clf=GridSearchCV(randomForestRegressor,parameters,cv=5)
'clf.cv_results_‘里面还有训练时间和验证指标的一些信息,如’mean_fit_time’、‘mean_score_time’、‘std_score_time’、‘std_test_score’。
2. 随机参数优化
from sklearn.model_selection import RandomizedSearchCV
from sklearn.ensemble import RandomDorestRegressor
randomForestRegressor=RandomForestRegressor()
parameters={
'n_estimators':[50,100,200,300],'max_depth':[1,2,3,4,5]}
clf=RandomizedSearchCV(randomForestRegressor,parameters,cv=5)