模型融合中的stacking方法
本文參考了Kaggle機(jī)器學(xué)習(xí)之模型融合(stacking)心得
stacking是用于模型融合的一個大殺器,其基本思想是將多個模型的結(jié)果進(jìn)行融合來提高預(yù)測率。,理論介紹有很多,實際的例子比較少,本文將其實例化,并給出詳細(xì)的代碼來說明具體的stacking過程是如何實現(xiàn)的。stacking理論的話可以用下面的兩幅圖來形象的展示出來。
結(jié)合上面的圖先做一個初步的情景假設(shè),假設(shè)采用5折交叉驗證:
訓(xùn)練集(Train):訓(xùn)練集是100行,4列(3列特征,1列標(biāo)簽)。
測試集(Test):測試集是30行,3列特征,無標(biāo)簽。
模型1:xgboost。
模型2:lightgbm。
模型3:貝葉斯分類器
第一步
對于模型1來說,先看訓(xùn)練集:
采用5折交叉驗證,就是要訓(xùn)練5次并且要預(yù)測5次。先把數(shù)據(jù)分成5份,每一次的訓(xùn)練過程是采用80行做訓(xùn)練,20行做預(yù)測,經(jīng)過5次的訓(xùn)練和預(yù)測之后,全部的訓(xùn)練集都已經(jīng)經(jīng)過預(yù)測了,這時候會產(chǎn)生一個100 ×\times× 1的預(yù)測值。暫記為P1。
接下來看一看測試集:
在模型1每次經(jīng)過80個樣本的學(xué)習(xí)后,不光要預(yù)測訓(xùn)練集上的20個樣本,同時還會預(yù)測Test的30個樣本,這樣,在一次訓(xùn)練過程中,就會產(chǎn)生一個30 ×\times× 1的預(yù)測向量,在5次的訓(xùn)練過程中,就會產(chǎn)生一個30 ×\times× 5的向量矩陣,我們隊每一行做一個平均,就得到了30 ×\times× 1的向量。暫記為T1。
模型1到此結(jié)束。接下來看模型2,模型2是在重復(fù)模型1的過程,同樣也會產(chǎn)生一個訓(xùn)練集的預(yù)測值和測試集的預(yù)測值。記為P2和T2。這樣的話,(P1,P2)就是一個100 ×\times× 2的矩陣,(T1,T2)就是一個30 ×\times× 2的矩陣。
第二步
第二步是采用新的模型3。其訓(xùn)練集是什么呢?就是第一步得到的(P1,P2)加上每個樣本所對應(yīng)的標(biāo)簽,如果第一步的模型非常好的話,那么得到的P1或者P2應(yīng)該是非常接近這個標(biāo)簽的。有人可能就會對測試集用求平均的方式來直接(T1+T2)/2,或者帶權(quán)重的平均來求得結(jié)果,但是一般是不如stacking方法的。
將(P1,P2)作為模型3訓(xùn)練集的特征,經(jīng)過模型3的學(xué)習(xí),然后再對測試集上的(T1,T2)做出預(yù)測,一般就能得到較好的結(jié)果了。
python實現(xiàn)
模型1采用xgboost,模型2采用lightgbm,模型3用貝葉斯分類器。
xgboost
##### xgb xgb_params = {'eta': 0.005, 'max_depth': 10, 'subsample': 0.8, 'colsample_bytree': 0.8, 'objective': 'reg:linear', 'eval_metric': 'rmse', 'silent': True, 'nthread': 4}#xgb的參數(shù),可以自己改 folds = KFold(n_splits=5, shuffle=True, random_state=2018)#5折交叉驗證 oof_xgb = np.zeros(len(train))#用于存放訓(xùn)練集的預(yù)測 predictions_xgb = np.zeros(len(test))#用于存放測試集的預(yù)測for fold_, (trn_idx, val_idx) in enumerate(folds.split(X_train, y_train)):print("fold n°{}".format(fold_+1))trn_data = xgb.DMatrix(X_train[trn_idx], y_train[trn_idx])#訓(xùn)練集的80%val_data = xgb.DMatrix(X_train[val_idx], y_train[val_idx])#訓(xùn)練集的20%,驗證集watchlist = [(trn_data, 'train'), (val_data, 'valid_data')]clf = xgb.train(dtrain=trn_data, num_boost_round=20000, evals=watchlist, early_stopping_rounds=200, verbose_eval=100, params=xgb_params)#80%用于訓(xùn)練過程oof_xgb[val_idx] = clf.predict(xgb.DMatrix(X_train[val_idx]), ntree_limit=clf.best_ntree_limit)#預(yù)測20%的驗證集predictions_xgb += clf.predict(xgb.DMatrix(X_test), ntree_limit=clf.best_ntree_limit) / folds.n_splits#預(yù)測測試集,并且取平均print("CV score: {:<8.8f}".format(mean_squared_error(oof_xgb, target)))這樣我們就得到了訓(xùn)練集的預(yù)測結(jié)果oof_xgb這一列,這一列是作為模型3訓(xùn)練集的第一個特征列,并且得到了測試集的預(yù)測結(jié)果predictions_xgb。
lightgbm
lightgbm和xgboost相似,在此把代碼寫一下。
##### lgb param = {'num_leaves': 120,'min_data_in_leaf': 30, 'objective':'regression','max_depth': -1,'learning_rate': 0.01,"min_child_samples": 30,"boosting": "gbdt","feature_fraction": 0.9,"bagging_freq": 1,"bagging_fraction": 0.9 ,"bagging_seed": 11,"metric": 'mse',"lambda_l1": 0.1,"verbosity": -1}#模型參數(shù),可以修改 folds = KFold(n_splits=5, shuffle=True, random_state=2018)#5折交叉驗證 oof_lgb = np.zeros(len(train))#存放訓(xùn)練集的預(yù)測結(jié)果 predictions_lgb = np.zeros(len(test))#存放測試集的預(yù)測結(jié)果for fold_, (trn_idx, val_idx) in enumerate(folds.split(X_train, y_train)):print("fold n°{}".format(fold_+1))trn_data = lgb.Dataset(X_train[trn_idx], y_train[trn_idx])#80%的訓(xùn)練集用于訓(xùn)練val_data = lgb.Dataset(X_train[val_idx], y_train[val_idx])#20%的訓(xùn)練集做驗證集num_round = 10000clf = lgb.train(param, trn_data, num_round, valid_sets = [trn_data, val_data], verbose_eval=200, early_stopping_rounds = 100)#訓(xùn)練過程oof_lgb[val_idx] = clf.predict(X_train[val_idx], num_iteration=clf.best_iteration)#對驗證集得到預(yù)測結(jié)果predictions_lgb += clf.predict(X_test, num_iteration=clf.best_iteration) / folds.n_splits#對測試集5次取平均值print("CV score: {:<8.8f}".format(mean_squared_error(oof_lgb, target)))這樣我們得到了模型3訓(xùn)練集的又一個特征oof_lgb,還有測試集的又一個特征predictions_lgb 。
貝葉斯分類器
# 將lgb和xgb的結(jié)果進(jìn)行stacking(疊加) train_stack = np.vstack([oof_lgb,oof_xgb]).transpose()#訓(xùn)練集2列特征 test_stack = np.vstack([predictions_lgb, predictions_xgb]).transpose()#測試集2列特征 #貝葉斯分類器也使用交叉驗證的方法,5折,重復(fù)2次,主要是避免過擬合 folds_stack = RepeatedKFold(n_splits=5, n_repeats=2, random_state=2018) oof_stack = np.zeros(train_stack.shape[0])#存放訓(xùn)練集中驗證集的預(yù)測結(jié)果 predictions = np.zeros(test_stack.shape[0])#存放測試集的預(yù)測結(jié)果#enumerate() 函數(shù)用于將一個可遍歷的數(shù)據(jù)對象(如列表、元組或字符串)組合為一個索引序列,同時列出數(shù)據(jù)和數(shù)據(jù)下標(biāo),一般用在 for 循環(huán)當(dāng)中。 for fold_, (trn_idx, val_idx) in enumerate(folds_stack.split(train_stack,target)):#target就是每一行樣本的標(biāo)簽值print("fold {}".format(fold_))trn_data, trn_y = train_stack[trn_idx], target.iloc[trn_idx].values#劃分訓(xùn)練集的80%val_data, val_y = train_stack[val_idx], target.iloc[val_idx].values#劃分訓(xùn)練集的20%做驗證集clf_3 = BayesianRidge()clf_3.fit(trn_data, trn_y)#貝葉斯訓(xùn)練過程,sklearn中的。oof_stack[val_idx] = clf_3.predict(val_data)#對驗證集有一個預(yù)測,用于后面計算模型的偏差predictions += clf_3.predict(test_stack) / 10#對測試集的預(yù)測,除以10是因為5折交叉驗證重復(fù)了2次mean_squared_error(target.values, oof_stack)#計算出模型在訓(xùn)練集上的均方誤差 print("CV score: {:<8.8f}".format(mean_squared_error(target.values, oof_stack)))總結(jié)
以上是生活随笔為你收集整理的模型融合中的stacking方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTML5标签canvas制作平面图
- 下一篇: 通过JTAG配置EPCS64芯片方法(将