task5-模型融合
模型融合是比赛后期一个重要的环节,大体来说有如下的类型方式。
一,简介
1.简单加权融合:
回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean);
分类:投票(Voting)
综合:排序融合(Rank averaging),log融合
2.stacking/blending:
构建多层模型,并利用预测结果再拟合预测。
3.boosting/bagging(在xgboost,Adaboost,GBDT中已经用到):
多树的提升方法
Stacking本质上就是这么直接的思路,但是直接这样有时对于如果训练集和测试集分布不那么一致的情况下是有一点问题的,其问题在于用初始模型训练的标签再利用真实标签进行再训练,毫无疑问会导致一定的模型过拟合训练集,这样或许模型在测试集上的泛化能力或者说效果会有一定的下降,因此现在的问题变成了如何降低再训练的过拟合性,这里我们一般有两种方法。
次级模型尽量选择简单的线性模型
利用K折交叉验证
K-折交叉验证: 训练:
模型融合的关键:得分近似,(特征、模型的)差异大
二、代码实践
5.4.1 回归\分类概率-融合:
1)简单加权平均,结果直接融合
test_pre1 = [1.2, 3.2, 2.1, 6.2]
test_pre2 = [0.9, 3.1, 2.0, 5.9]
test_pre3 = [1.1, 2.9, 2.2, 6.0]
y_test_true = [1, 3, 2, 6]
def Weighted_method(test_pre1,test_pre2,test_pre3,w=[1/3,1/3,1/3]):
weighted_result=w[0]*pd.Series(test_pre1)+w[1]*pd.Series(test_pre2)+w[2]*pd.Series(test_pre3)
return weighted_result
from sklearn import metrics
print(‘Pred1 MAE:’,metrics.mean_absolute_error(y_test_true,test_pre1))
print(‘Pred2 MAE:’,metrics.mean_absolute_error(y_test_true,test_pre2))
print(‘Pred3 MAE:’,metrics.mean_absolute_error(y_test_true,test_pre3))
根据加权计算MAE
w=[0.3,0.4,0.3]
weighted_pre=Weighted_method(test_pre1,test_pre2,test_pre3,w)
print(‘Weighted_pre MAE:’,metrics.mean_absolute_error(y_test_true,weighted_pre))
2) Stacking融合(回归):
from sklearn import linear_model
def Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,test_pre1,test_pre2,test_pre3,model_L2=linear_model.LinearRegression()):
model_L2.fit(pd.concat([pd.Series(train_reg1),pd.Series(train_reg2),pd.Series(train_reg3)],axis=1).values,y_train_true)
stacking_result=model_L2.predict(pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).values)
return stacking_result
train_reg1 = [3.2, 8.2, 9.1, 5.2]
train_reg2 = [2.9, 8.1, 9.0, 4.9]
train_reg3 = [3.1, 7.9, 9.2, 5.0]
y_train_true = [3, 8, 9, 5]
test_pre1 = [1.2, 3.2, 2.1, 6.2]
test_pre2 = [0.9, 3.1, 2.0, 5.9]
test_pre3 = [1.1, 2.9, 2.2, 6.0]
y_test_true = [1, 3, 2, 6]
model_L2=linear_model.LinearRegression()
stacking_pre=Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,
test_pre1,test_pre2,test_pre3,model_L2)
print(‘Stacking_pre MAE:’,metrics.mean_absolute_error(y_test_true,stacking_pre))
5.4.2 分类模型融合:
对于分类,同样的可以使用融合方法,比如简单投票,Stacking…
from sklearn.datasets import make_blobs
from sklearn import datasets
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestClassifier,VotingClassifier
from xgboost import XGBClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_moons
from sklearn.metrics import accuracy_score,roc_auc_score
from sklearn.model_selection import cross_val_score,StratifiedKFold
1)Voting投票机制:
Voting即投票机制,分为软投票和硬投票两种,其原理采用少数服从多数的思想。
硬投票:对多个模型直接进行投票,不区分模型结果的相对重要度,最终投票数最多的类为最终被预测的类。
iris=datasets.load_iris()
x=iris.data
y=iris.target
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)
clf1=XGBClassifier(learning_rate=0.1,n_estimators=150,max_depth=3,min_child_weight=2,
subsample=0.7,colsample_bytree=0.6,objective=‘binary:logistic’)
clf2=RandomForestClassifier(n_estimators=50,max_depth=1,min_samples_split=4,
min_samples_leaf=63,oob_score=True)
clf3=SVC(C=0.1)
硬投票
eclf=VotingClassifier(estimators=[(‘xgb’,clf1),(‘rf’,clf2),(‘svc’,clf3)],voting=‘hard’)
for clf,label in zip([clf1,clf2,clf3,eclf],[‘XGBBoosting’,‘Random Forest’,‘SVM’,‘Ensemble’]):
scores=cross_val_score(clf,x,y,cv=5,scoring=‘accuracy’)
print(‘Accuracy: %0.2f (+/- %0.2f)[%s]’%(scores.mean(),scores.std(),label))
软投票:和硬投票原理相同,增加了设置权重的功能,可以为不同模型设置不同权重,进而区别模型不同的重要度。
x=iris.data
y=iris.target
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)
clf1 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=3, min_child_weight=2, subsample=0.8,
colsample_bytree=0.8, objective=‘binary:logistic’)
clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
min_samples_leaf=63,oob_score=True)
clf3 = SVC(C=0.1, probability=True)
软投票
eclf = VotingClassifier(estimators=[(‘xgb’, clf1), (‘rf’, clf2), (‘svc’, clf3)], voting=‘soft’, weights=[2, 1, 1])
for clf, label in zip([clf1, clf2, clf3, eclf], [‘XGBBoosting’, ‘Random Forest’, ‘SVM’, ‘Ensemble’]):
scores = cross_val_score(clf, x, y, cv=5, scoring=‘accuracy’)
print(“Accuracy: %0.2f (+/- %0.2f) [%s]” % (scores.mean(), scores.std(), label))
三、总结
1.次级模型尽量选择简单的模型
2.单个基学习器的效果要好,而且得分相近
3.模型、特征差异要大