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