之前有寫過兩篇關(guān)于Titanic比賽的簡書,這幾天上kaggle-Titanic的kernels在MostVost找了一篇排第一的kernels來看惠呼,參考鏈接,這個Kernels在模型方面做得特別好宋舷,所以,另寫一篇簡書作為總結(jié)袍嬉。
流程
- 觀察數(shù)據(jù)颁井,我們要對數(shù)據(jù)有所了解厅贪,可以參考簡書
- 特征工程以及數(shù)據(jù)清洗
- 介紹模型
- 跑模型
- 修改第二層模型
- 總結(jié)
1.代碼分析
首先,導(dǎo)入我們需要用到的庫
import pandas as pd
import numpy as np
from sklearn.cross_validation import KFold
import re
import plotly.graph_objs as go
import plotly.offline as py
from sklearn.ensemble import (RandomForestClassifier, AdaBoostClassifier,
GradientBoostingClassifier, ExtraTreesClassifier)
from sklearn.svm import SVC
import xgboost as xgb
import warnings
warnings.filterwarnings('ignore') # 忽略warning
pd.set_option('display.max_columns', None) # 輸出結(jié)果顯示全部列
然后雅宾,導(dǎo)入數(shù)據(jù)
train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')
PassengerId = test['PassengerId']
full_data = [train, test]
接下來养涮,我們可以查看我們的數(shù)據(jù)
# 查看train集的數(shù)據(jù)
print(train.describe()) # 查看描述性統(tǒng)計,只能看數(shù)值型數(shù)據(jù)。
print(train.info()) # 查看數(shù)據(jù)的信息
# print(train.head()) # 查看train的前n行數(shù)據(jù)眉抬,默認(rèn)為前5行
從圖上我們可以看到贯吓,其中有5列不是數(shù)值型的,我們需要對其進(jìn)行轉(zhuǎn)換成數(shù)值蜀变,而且Age悄谐、Cabin這兩列是有缺失值的,我們要對其進(jìn)行填充或者丟棄库北。
2.特征工程以及數(shù)據(jù)清洗
添加一些新的特征
# 添加新的特征爬舰,名字的長度
train['Name_length'] = train['Name'].apply(len)
test['Name_length'] = test['Name'].apply(len)
# 乘客在船上是否有船艙
train['Has_Cabin'] = train["Cabin"].apply(lambda x: 0 if type(x) == float else 1)
test['Has_Cabin'] = test["Cabin"].apply(lambda x: 0 if type(x) == float else 1)
# 結(jié)合SibSp和Parch創(chuàng)建新的特性FamilySize
for dataset in full_data:
dataset['FamilySize'] = dataset['SibSp'] + dataset['Parch'] + 1
基于特征FamilySize創(chuàng)建新的特征IsAlone,因?yàn)橐粋€人的話寒瓦,顧慮沒有那么多情屹,只需要管好自己,生存的幾率會大點(diǎn)杂腰,其中又分‘male’和‘female’垃你,因?yàn)槲矣浀秒娪爸惺怯羞@樣的一句臺詞“讓女人和小孩先走”,所以颈墅,我們有理由相信蜡镶,女性的生存率會比男性的要高。
for dataset in full_data:
dataset['IsAlone'] = 0
dataset.loc[dataset['FamilySize'] == 1), 'IsAlone'] = 1
通過name恤筛,添加特征Title
# 定義從乘客名中提取新的特征[Title]的函數(shù)
def get_title(name):
title_search = re.search(' ([A-Za-z]+)\.', name)
# 如果title存在,提取并返回它芹橡。
if title_search:
return title_search.group(1)
return ""
# 創(chuàng)建一個新的特征[Title]
for dataset in full_data:
dataset['Title'] = dataset['Name'].apply(get_title)
# 將所有不常見的Title分組為一個“Rare”組
for dataset in full_data:
dataset['Title'] = dataset['Title'].replace(
['Lady', 'Countess', 'Capt', 'Col', 'Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')
dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss')
dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')
缺失值填充
- Embarked只缺了兩個毒坛,所以通過統(tǒng)計三個登船地點(diǎn),選出了登船人數(shù)最多的登船地點(diǎn)(s)來填充林说。
- Test集的Fare只有一個缺失,所以用了中位數(shù)來填充
- Age缺失的比較多煎殷,所以在[age_avg - age_std, age_avg + age_std]這個范圍取值來填充(其中age_avg是Age的平均值,age_std是Age的標(biāo)準(zhǔn)差)
# 通過統(tǒng)計三個登船地點(diǎn)人數(shù)最多的填充缺失值
for dataset in full_data:
dataset['Embarked'] = dataset['Embarked'].fillna('S')
# 缺失值填充腿箩,Test集的Fare有一個缺失豪直,按中位數(shù)來填充,以及創(chuàng)建一個新的特征[CategoricalFare]
for dataset in full_data:
dataset['Fare'] = dataset['Fare'].fillna(train['Fare'].median())
train['CategoricalFare'] = pd.qcut(train['Fare'], 4)
# 缺失值填充,以及創(chuàng)建新的特征[CategoricalAge]
for dataset in full_data:
age_avg = dataset['Age'].mean()
age_std = dataset['Age'].std()
age_null_count = dataset['Age'].isnull().sum()
age_null_random_list = np.random.randint(age_avg - age_std, age_avg + age_std, size=age_null_count)
dataset['Age'][np.isnan(dataset['Age'])] = age_null_random_list
dataset['Age'] = dataset['Age'].astype(int)
通過Age,創(chuàng)建新的特征珠移,一會用來給Age分組
train['CategoricalAge'] = pd.cut(train['Age'], 5)
print(train['CategoricalAge'])
從圖片可以看出弓乙,年齡分為了5個范圍末融,所以一會把年齡分為5組(0-4)。
分組以及轉(zhuǎn)換數(shù)值
Sex:把性別轉(zhuǎn)為0和1.
Embarked:把登船地點(diǎn)轉(zhuǎn)為0暇韧、1勾习、2.
Fare:把費(fèi)用分為4組
Age:把年齡分為5組
for dataset in full_data:
dataset['Sex'] = dataset['Sex'].map({'female': 0, 'male': 1}).astype(int)
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
dataset['Title'] = dataset['Title'].map(title_mapping)
dataset['Title'] = dataset['Title'].fillna(0)
dataset['Embarked'] = dataset['Embarked'].map({'S': 0, 'C': 1, 'Q': 2}).astype(int)
dataset.loc[dataset['Fare'] <= 7.91, 'Fare'] = 0
dataset.loc[(dataset['Fare'] > 7.91) & (dataset['Fare'] <= 14.454), 'Fare'] = 1
dataset.loc[(dataset['Fare'] > 14.454) & (dataset['Fare'] <= 31), 'Fare'] = 2
dataset.loc[dataset['Fare'] > 31, 'Fare'] = 3
dataset['Fare'] = dataset['Fare'].astype(int)
dataset.loc[dataset['Age'] <= 16, 'Age'] = 0
dataset.loc[(dataset['Age'] > 16) & (dataset['Age'] <= 32), 'Age'] = 1
dataset.loc[(dataset['Age'] > 32) & (dataset['Age'] <= 48), 'Age'] = 2
dataset.loc[(dataset['Age'] > 48) & (dataset['Age'] <= 64), 'Age'] = 3
dataset.loc[dataset['Age'] > 64, 'Age'] = 4
特征選擇,丟棄一些不必要的特征
PassengerID懈玻、Name巧婶、Ticket、Cabin涂乌、Sibsp等特征丟棄的原因是都已組合成新的特征艺栈,所以給予丟棄
CategorcalAge、CategoricalFare這些特征創(chuàng)建時是用來查看Age湾盒、Fare的分組區(qū)間湿右,已使用,所以給予丟棄
drop_elements = ['PassengerId', 'Name', 'Ticket', 'Cabin', 'SibSp']
train = train.drop(drop_elements, axis=1)
train = train.drop(['CategoricalAge', 'CategoricalFare'], axis=1)
test = test.drop(drop_elements, axis=1)
# print(train.head())
print(train.describe())
# print(train.head())
3.模型介紹
在跑模型之前历涝,先提及一下本次kernels的基礎(chǔ)知識诅需,本次使用的
是Stacking融合模型,stacking集成模型與《機(jī)器學(xué)習(xí)》提及Bagging與Boosting不同荧库,Bagging與Boosting是用弱模型的結(jié)果經(jīng)過投票加權(quán)等方法集成一個新的強(qiáng)模型堰塌。而stacking翻譯成中文叫做模型堆疊,接下來我們將對stacking進(jìn)行介紹分衫,是如何將模型堆疊在一起的场刑。
stacking定義
stacking是一種分層模型集成框架。以兩層為例蚪战,第一層由多個基學(xué)習(xí)器組成牵现,其輸入為原始訓(xùn)練集,第二層的模型則是以第一層基學(xué)習(xí)器的輸出作為訓(xùn)練集進(jìn)行再訓(xùn)練邀桑,從而得到完整的stacking模型瞎疼。
首先,我們來看一下下面這個圖(兩層基礎(chǔ))壁畸,并進(jìn)行步驟分解
步驟:
- 首先將數(shù)據(jù)分為5份贼急,
- 在stacking的第一層定義5個基模型,其中每個模型選擇做一下5折的交叉驗(yàn)證的預(yù)測捏萍,這樣就相當(dāng)于每個模型將所有數(shù)據(jù)預(yù)測了一遍
- 將第一層5個基模型的輸出預(yù)測向量太抓,作為第二層模型的特征做訓(xùn)練,
- 做test時令杈,直接將test的數(shù)據(jù)喂給之前第一層訓(xùn)練好的5個基模型走敌,5個模型預(yù)測出的至平均后作為第二層模型的輸入
- 第二層使用一個分類器,將前面得出的特征逗噩,進(jìn)行一次分類掉丽,因?yàn)橹饕Y(jié)果在第一層已經(jīng)預(yù)測完成跌榔,第二層要求不大(xgboost、LGBM等)即可机打。
Stacking注意事項(xiàng)
第一層的基模型最好是強(qiáng)模型矫户,而第二層的基模型可以放一個簡單的分類器,防止過擬合残邀。
第一層基模型的個數(shù)不能太小皆辽,因?yàn)橐粚幽P蛡€數(shù)等于第二層分類器的特征維度。大家可以把勉強(qiáng)將其想象成神經(jīng)網(wǎng)絡(luò)的第一層神經(jīng)元的個數(shù)芥挣,當(dāng)然這個值也不是越多越好驱闷。
第一層的基模型必須“準(zhǔn)而不同”,如果有一個性能很差的模型出現(xiàn)在第一層空免,將會嚴(yán)重影響整個模型融合的效果
本次比賽中部分模型的準(zhǔn)確率:
- 樸素貝葉斯(Gaussian Naive Bays):72.2%
- 隨機(jī)梯度下降(Stochastic Gradient Descent):76.8%
- 感知器(Perceptron):78%
- Linear SVC:79.12%
- 邏輯回歸(Ligistic Regression):80.3%
- SVC(support Vector Machines):83.4%
- ExtraTreesClassifie: 84.5%
- AdaBoostClassifier: 85.6%
- 決策樹(Decision tree):86.7%
- 隨機(jī)森林(Random Forest):86.7%
4. 跑模型
這部分是這個kernels的重點(diǎn)空另,用的是Stacking。Stacking使用第一級分類器的預(yù)測作為對第二級模型的訓(xùn)練輸入蹋砚。我們使用了(RandomForestClassifier, AdaBoostClassifier,GradientBoostingClassifier, ExtraTreesClassifier扼菠,Support Vector Classifier)這5個分類器的預(yù)測作為下一個分類器(xgboost)的特征。
為什么使用的是這5個模型坝咐,其他需求還是這5個模型嗎循榆?為什么不用其他如神經(jīng)網(wǎng)絡(luò)等強(qiáng)模型呢?
-
這5個模型是當(dāng)前比賽排名準(zhǔn)度率最好的5個強(qiáng)模型墨坚,而其他的模型準(zhǔn)度較低如邏輯回歸(準(zhǔn)確率0.80左右秧饮,而強(qiáng)模型均在0.83以上),這樣會影響堆疊后的準(zhǔn)確率泽篮,決策樹準(zhǔn)確率雖然達(dá)到86%盗尸,但是和隨機(jī)森林相關(guān)性過高,且屬于單樹模型帽撑,容易過擬合泼各,所以選取隨機(jī)森林。
注意:當(dāng)碰到其他需求的時候亏拉,不一定還是這5個模型历恐,需要進(jìn)行對其他模型的準(zhǔn)確率測試,相關(guān)性確認(rèn)等专筷。
不使用神經(jīng)網(wǎng)絡(luò)原因:
- 神經(jīng)網(wǎng)絡(luò)不太可控,調(diào)參困難蒸苇,容易出現(xiàn)過擬合等問題
- 較好的神經(jīng)網(wǎng)絡(luò)計算量較大磷蛹,需要很大的數(shù)據(jù)量,而本次的比賽中Data只有890行溪烤,學(xué)習(xí)速度調(diào)整困難味咳,收斂可能發(fā)生過快等問題庇勃,無法工作
在下面的代碼中,我們編寫了一個類SklearnHelper槽驶,它允許擴(kuò)展所有Sklearn分類器所共有的內(nèi)置方法(如train责嚷、predict和fit)。這消除了冗余掂铐,因?yàn)槿绻覀兿胝{(diào)用5個不同的分類器罕拂,就不需要編寫相同的方法5次。
# 一些有用的參數(shù)全陨,下面會用到
ntrain = train.shape[0]
ntest = test.shape[0]
SEED = 0
NFOLDS = 5
kf = KFold(ntrain, n_folds=NFOLDS, random_state=SEED)
class SklearnHelper(object):
def __init__(self, clf, seed=0, params=None):
params['random_state'] = seed
self.clf = clf(**params)
def train(self, x_train, y_train):
self.clf.fit(x_train, y_train)
def predict(self, x):
return self.clf.predict(x)
def fit(self, x, y):
return self.clf.fit(x, y)
def feature_importances(self, x, y):
return self.clf.fit(x, y).feature_importances_
def get_oof(clf, x_train, y_train, x_test):
oof_train = np.zeros((ntrain,))
oof_test = np.zeros((ntest,))
oof_test_skf = np.empty((NFOLDS, ntest))
for i, (train_index, test_index) in enumerate(kf):
x_tr = x_train[train_index]
y_tr = y_train[train_index]
x_te = x_train[test_index]
clf.train(x_tr, y_tr)
oof_train[test_index] = clf.predict(x_te)
oof_test_skf[i, :] = clf.predict(x_test)
oof_test[:] = oof_test_skf.mean(axis=0)
return oof_train.reshape(-1, 1), oof_test.reshape(-1, 1)
現(xiàn)在讓我們準(zhǔn)備五個學(xué)習(xí)模型作為我們的第一級分類爆班。這些模型都可以通過Sklearn庫方便地調(diào)用,如下所示
1.Random Forest classifier
2.Extra Trees classifier
3.AdaBoost classifer
4.Gradient Boosting classifer
5.Support Vector Machine
輸入上述分類器的參數(shù)
# 隨機(jī)森林的參數(shù)
rf_params = {
'n_jobs': -1,
'n_estimators': 100,
'warm_start': True,
#'max_features': 0.2,
'max_depth': 6,
'min_samples_leaf': 2,
'max_features': 'sqrt',
'verbose': 0
}
# Extra Trees的參數(shù)
et_params = {
'n_jobs': -1,
'n_estimators': 100,
#'max_features': 0.5,
'max_depth': 8,
'min_samples_leaf': 2,
'verbose': 0
}
# AdaBoost的參數(shù)
ada_params = {
'n_estimators': 100,
'learning_rate': 0.01
}
# Gradient Boosting的參數(shù)
gb_params = {
'n_estimators': 100,
#'max_features': 0.2,
'max_depth': 5,
'min_samples_leaf': 2,
'verbose': 0
}
# Support Vector Classifier的參數(shù)
svc_params = {
'kernel': 'linear',
'C': 0.025
}
第一級分類器
# 通過前面定義的SklearnHelper類創(chuàng)建5個對象來表示5個學(xué)習(xí)模型
rf = SklearnHelper(clf=RandomForestClassifier, seed=SEED, params=rf_params)
et = SklearnHelper(clf=ExtraTreesClassifier, seed=SEED, params=et_params)
ada = SklearnHelper(clf=AdaBoostClassifier, seed=SEED, params=ada_params)
gb = SklearnHelper(clf=GradientBoostingClassifier, seed=SEED, params=gb_params)
svc = SklearnHelper(clf=SVC, seed=SEED, params=svc_params)
# 創(chuàng)建包含train辱姨、test的Numpy數(shù)組柿菩,以提供給我們的模型
y_train = train['Survived'].ravel()
train = train.drop(['Survived'], axis=1)
x_train = train.values
# test = test.drop(['Parch', 'Embarked', 'Has_Cabin', 'IsAlone'], axis=1)
x_test = test.values
#這些將會作為新的特征被使用
et_oof_train, et_oof_test = get_oof(et, x_train, y_train, x_test) # Extra Trees
rf_oof_train, rf_oof_test = get_oof(rf, x_train, y_train, x_test) # Random Forest
ada_oof_train, ada_oof_test = get_oof(ada, x_train, y_train, x_test) # AdaBoost
gb_oof_train, gb_oof_test = get_oof(gb, x_train, y_train, x_test) # Gradient Boost
svc_oof_train, svc_oof_test = get_oof(svc, x_train, y_train, x_test) # Support Vector Classifier
現(xiàn)在已經(jīng)獲得了我們的第一級預(yù)測,我們可以把它看作是一組新的特性雨涛,作為下一個分類器的訓(xùn)練數(shù)據(jù)枢舶。
查看各個特征對上述分類器的重要性
rf_features = rf.feature_importances(x_train, y_train)
et_features = et.feature_importances(x_train, y_train)
ada_features = ada.feature_importances(x_train, y_train)
gb_features = gb.feature_importances(x_train, y_train)
cols = train.columns.values
feature_dataframe = pd.DataFrame({'features': cols,
'Random Forest feature importances': rf_features,
'Extra Trees feature importances': et_features,
'AdaBoost feature importances': ada_features,
'Gradient Boost feature importances': gb_features})
feature_dataframe['mean'] = feature_dataframe.mean(axis=1) # axis = 1 computes the mean row-wise
print(feature_dataframe.head(11))
以圖形形式顯示各模型對特征的相關(guān)性,觀察
從圖中觀察可以知道替久,第一層模型特征相關(guān)性平均后凉泄,各特征的相關(guān)性相對降低,準(zhǔn)而不同”這個要求的侣肄。所以第一層五個模型融合是符合的旧困。
畫圖查看各個分類器的相關(guān)性
base_predictions_train = pd.DataFrame( {'RandomForest': rf_oof_train.ravel(),
'ExtraTrees': et_oof_train.ravel(),
'AdaBoost': ada_oof_train.ravel(),
'GradientBoost': gb_oof_train.ravel()
})
data = [
go.Heatmap(
z= base_predictions_train.astype(float).corr().values ,
x=base_predictions_train.columns.values,
y= base_predictions_train.columns.values,
colorscale='Viridis',
showscale=True,
reversescale = True
)
]
py.iplot(data, filename='labelled-heatmap')
這些模型彼此之間的相關(guān)性越低,得分越高稼锅。
第二級分類器xgboost
x_train = np.concatenate((et_oof_train, rf_oof_train, ada_oof_train, gb_oof_train, svc_oof_train), axis=1)
x_test = np.concatenate((et_oof_test, rf_oof_test, ada_oof_test, gb_oof_test, svc_oof_test), axis=1)
gbm = xgb.XGBClassifier(
#learning_rate=0.01,
n_estimators=2000,
max_depth=4,
min_child_weight=2,
# gamma=1,
gamma=0.9,
subsample=0.8,
colsample_bytree=0.8,
objective='binary:logistic',
nthread=-1,
scale_pos_weight=1).fit(x_train, y_train)
predictions = gbm.predict(x_test)
提交
StackingSubmission = pd.DataFrame({'PassengerId': PassengerId,
'Survived': predictions})
StackingSubmission.to_csv("StackingSubmission.csv", index=False)
提交后的分?jǐn)?shù)如下
訓(xùn)練所用時間:
5.對模型第二層進(jìn)行修改
LGBM與XGBOOST:
XGBoost是在GBDT(梯度提升決策樹)基礎(chǔ)上發(fā)展而來,針對傳統(tǒng)GBDT算法做了很多細(xì)節(jié)改進(jìn)吼具,包括損失函數(shù)、正則化矩距、切分點(diǎn)查找算法優(yōu)化拗盒、稀疏感知算法、并行化算法設(shè)計等等
LightGBM 是一個梯度 boosting 框架锥债,使用基于學(xué)習(xí)算法的決策樹陡蝇。它可以說是分布式的,高效的
與以往的算法比較①histogram算法替換了傳統(tǒng)的Pre-Sorted哮肚,某種意義上是犧牲了精度(但是作者聲明實(shí)驗(yàn)發(fā)現(xiàn)精度影響不大)換取速度登夫,直方圖作差構(gòu)建葉子。(xgboost的分布式實(shí)現(xiàn)也是基于直方圖的允趟,利于并行)②帶有深度限制的按葉子生長 (leaf-wise) 算法代替了傳統(tǒng)的(level-wise) 決策樹生長策略恼策,提升精度,同時避免過擬合危險潮剪。
LightGBM作者對模型的一些解釋:
https://www.zhihu.com/question/51644470/answer/130946285
- 兩者的結(jié)構(gòu)主要區(qū)別:在過濾數(shù)據(jù)樣例尋找分割值時涣楷,LightGBM 使用的是全新的技術(shù):基于梯度的單邊采樣(GOSS)分唾;而 XGBoost 則通過預(yù)分類算法和直方圖算法來確定最優(yōu)分割。
選擇LGBM替換XGBOOST的理由:
1.在速度上LGBM比XGBOOST的快十倍甚至百倍以上
2.LGBM與xgboost的精度不相上下
將stacking第二層xgboost替換成LGBM
lgbm_train = lgbm.Dataset ( data=x_train ,
label=y_train)
lgbm_params = {
'boosting': 'dart' ,
'application': 'binary' ,
'learning_rate': 0.01 ,
'feature_fraction': 0.5 ,
'verbose' : -1,
'drop_rate': 0.02
}
cv_results = lgbm.cv ( train_set=lgbm_train ,
params=lgbm_params ,
nfold=5 ,
num_boost_round=600 ,
early_stopping_rounds=50 ,
verbose_eval=50 ,
metrics=['auc'] )
optimum_boost_rounds = np.argmax ( cv_results['auc-mean'] )
print ( 'Optimum boost rounds = {}'.format ( optimum_boost_rounds ) )
print ( 'Best CV result = {}'.format ( np.max ( cv_results['auc-mean'] ) ) )
clf = lgbm.train ( train_set=lgbm_train ,
params=lgbm_params ,
num_boost_round=optimum_boost_rounds
)
##預(yù)測結(jié)果為浮點(diǎn)數(shù)狮斗,而本次比賽的預(yù)測結(jié)果需要0绽乔,1,所以將其轉(zhuǎn)換
predictions = clf.predict ( x_test )
predictions = predictions + 0.5
predictions = predictions.astype(int)
LGBM的重要參數(shù)用法:
學(xué)習(xí)控制參數(shù) | 含義 | 用法 |
---|---|---|
max_depth | 樹的最大深度 | 當(dāng)模型過擬合時,可以考慮首先降低 max_depth |
min_data_in_leaf | 葉子可能具有的最小記錄數(shù) | 默認(rèn)20碳褒,過擬合時用 |
feature_fraction | 例如 為0.8時折砸,意味著在每次迭代中隨機(jī)選擇80%的參數(shù)來建樹 | boosting 為 random forest 時用 |
bagging_fraction | 每次迭代時用的數(shù)據(jù)比例 | 用于加快訓(xùn)練速度和減小過擬合 |
early_stopping_round | 如果一次驗(yàn)證數(shù)據(jù)的一個度量在最近的early_stopping_round 回合中沒有提高,模型將停止訓(xùn)練 加速分析骤视,減少過多迭代 | |
lambda | 指定正則化 | 0~1 |
min_gain_to_split | 描述分裂的最小 gain v控制樹的有用的分裂 | |
max_cat_group | 在 group 邊界上找到分割點(diǎn) | 當(dāng)類別數(shù)量很多時鞍爱,找分割點(diǎn)很容易過擬合時 |
核心參數(shù) | 含義 | 用法 |
---|---|---|
Task | 數(shù)據(jù)的用途 | 選擇 train 或者 predict |
application | 模型的用途 | 選擇 regression: 回歸時,binary: 二分類時专酗,multiclass: 多分類時 |
boosting | 要用的算法 | gbdt睹逃, rf: random forest, dart: Dropouts meet Multiple Additive Regression Trees祷肯, goss: Gradient-based One-Side Sampling |
num_boost_round | 迭代次數(shù) | 通常 100+ |
learning_rat | e 如果一次驗(yàn)證數(shù)據(jù)的一個度量在最近的 early_stopping_round 回合中沒有提高沉填,模型將停止訓(xùn)練 | 常用 0.1, 0.001, 0.003… |
num_leaves | 默認(rèn) 31 | |
device | cpu 或者 gpu | |
metric | mae: mean absolute error , mse: mean squared error 佑笋, binary_logloss: loss for binary classification 翼闹, multi_logloss: loss for multi classification |
IO參數(shù) | 含義 |
---|---|
max_bin | 表示 feature 將存入的 bin 的最大數(shù)量 |
categorical_feature | 如果 categorical_features = 0,1,2, 則列 0蒋纬,1猎荠,2是 categorical 變量 |
ignore_column | 與 categorical_features 類似,只不過不是將特定的列視為categorical蜀备,而是完全忽略 |
save_binary | 這個參數(shù)為 true 時关摇,則數(shù)據(jù)集被保存為二進(jìn)制文件,下次讀數(shù)據(jù)時速度會變快 |
調(diào)參
IO parameter | 含義 |
---|---|
num_leaves | 取值應(yīng) <= 2 ^(max_depth)碾阁, 超過此值會導(dǎo)致過擬合 |
min_data_in_leaf | 將它設(shè)置為較大的值可以避免生長太深的樹输虱,但可能會導(dǎo)致 underfitting,在大型數(shù)據(jù)集時就設(shè)置為數(shù)百或數(shù)千 |
max_depth | 這個也是可以限制樹的深度 |
下表對應(yīng)了 Faster Speed 脂凶,better accuracy 宪睹,over-fitting 三種目的時,可以調(diào)的參數(shù)
Faster Speed | better accuracy | over-fitting |
---|---|---|
將 max_bin 設(shè)置小一些 | 用較大的 max_bin | max_bin 小一些 |
num_leaves 大一些 | num_leaves 小一些 | |
用 feature_fraction 來做 sub-sampling | 用 feature_fraction | |
用 bagging_fraction 和 bagging_freq | 設(shè)定 bagging_fraction 和 bagging_freq | |
training data 多一些 | training data 多一些 | |
用 save_binary 來加速數(shù)據(jù)加載 | 直接用 categorical feature | 用 gmin_data_in_leaf 和 min_sum_hessian_in_leaf |
用 parallel learning 用 dart | 用 lambda_l1, lambda_l2 蚕钦,min_gain_to_split 做正則化 | |
num_iterations 大一些亭病,learning_rate 小一些 | 用 max_depth 控制樹的深度 |
本次比賽使用的參數(shù)解釋:
- 'boosting': 'dart' # dart通過刪除已經(jīng)構(gòu)建好的樹,來降低模型過擬合的情況嘶居。
- application': 'binary' # 本次比賽為一個二分類問題命贴,所以,選擇binary
- 'learning_rate': 0.01 # 學(xué)習(xí)速率,基于數(shù)據(jù)量和精準(zhǔn)度去選擇胸蛛,本次比賽數(shù)據(jù)量小,所以選擇0.01即可以提高準(zhǔn)度樱报,也可以提高速度
- 'verbose' : -1#取消警告No further splits with positive gain, best gain: -inf葬项,不設(shè)置為-1的話,數(shù)據(jù)量較少可能會提出警告
- 'drop_rate': 0.02 # 解決類別不平衡所采用的的欠采樣方法迹蛤,類別不平衡就是指分類任務(wù)中不同類別的訓(xùn)練樣例數(shù)目差別很大的情況民珍,而欠采樣,即去除一些反例使得正盗飒、反例數(shù)目接近嚷量,然后再進(jìn)行學(xué)習(xí)。
- nfold=5 #第一層有5個分類器逆趣,所以使用5折即可
提交
提交后分?jǐn)?shù)如下
訓(xùn)練所用時間:
6.總結(jié)
相比于其他的kernels蝶溶,這個kernels的特征工程方面做的不突出,突出的方面是用了新的方法Stacking宣渗,這個其他人在Titanic比賽中沒有用到過的抖所,這也是他排第一的原因。
進(jìn)一步改善的步驟
必須指出的是痕囱,上述步驟只是顯示了一個非常簡單的方法田轧。聽說過在Kaggle的最高級別比賽中創(chuàng)建的組合,其中包括stacked classifiers的巨大組合鞍恢,以及超過2級的stacking級別傻粘。這次嘗試修改這個模型的第二層的時候,結(jié)果得分比xgboost更高帮掉,有可能是因?yàn)樵谧鳛榉诸悓酉蚁ぃ瑇gboost需要人工去選擇權(quán)重的變化,而LGBM可以根據(jù)實(shí)際變化而修改旭寿,xgboost權(quán)重在第一層的時候應(yīng)該還可以調(diào)節(jié)警绩。但是速度上真的LGBM大約快了60倍,Xgboost由于對比LGBM屬于'元老'級模型盅称,對于調(diào)參方面在網(wǎng)上的攻略更加完善肩祥,而且優(yōu)化方面也相對突出,LGBM因?yàn)檫\(yùn)行速度的提升或許在后面會優(yōu)化并超越XGBOOST也有可能
代碼地址:
https://gitee.com/ZHBIT-MachineLearning/Machine-Learning-Base/tree/master/TItanic