kaggle Titanic項(xiàng)目主頁(yè):https://www.kaggle.com/c/titanic
Titanic feature engineering
最新參考:https://ahmedbesbes.com/how-to-score-08134-in-titanic-kaggle-challenge.html
0 問題概述
根據(jù)給出的乘客特征(年齡懈万、艙室等級(jí)胸竞、登陸港口等),預(yù)測(cè)乘客是否幸存巍杈,屬于典型的分類問題。
數(shù)據(jù)文件:
- train.csv 訓(xùn)練集逾滥,包含1-891個(gè)記錄
- test.csv 測(cè)試集烘贴,包含892-1309的記錄禁添,不包含是否生存的label
- gender_submission.csv 提交樣例,測(cè)試集對(duì)應(yīng)的是否生存label
1 訓(xùn)練集桨踪、測(cè)試集數(shù)據(jù)對(duì)比分析
1.1 特征缺失值情況對(duì)比
存在兩個(gè)特殊情況老翘,數(shù)據(jù)缺失補(bǔ)全時(shí)應(yīng)特別注意;
Cabin特征存在大比例的缺失馒闷,可以將其忽略酪捡;
所有特征在訓(xùn)練集叁征、測(cè)試集中的缺失情況基本一致纳账,無需據(jù)此刪除任何特征。
1.2 特征數(shù)據(jù)分布情況對(duì)比
通過繪圖對(duì)所有10個(gè)特征在訓(xùn)練集捺疼、測(cè)試集中的分布情況進(jìn)行對(duì)比疏虫,未發(fā)現(xiàn)任何明顯差異,無需據(jù)此刪除任何特征啤呼。
1 特征工程
參考:https://triangleinequality.wordpress.com/2013/09/08/basic-feature-engineering-with-the-titanic-data/
離散特征:name 卧秘、'Cabin'、 'Embarked'官扣、'Pclass'翅敌、 'Sex'、'Ticket'
連續(xù)特征:age惕蹄、fare蚯涮、'SibSp'、Parch'
1.1 離散特征處理
1)name
乘客姓名作為一個(gè)整體時(shí)這些信息價(jià)值不大卖陵,此時(shí)它的作用和PassengerId相當(dāng)遭顶。
但是,name中包含的Mrs, Miss, Mr and Master.信息很有價(jià)值泪蔫,可以將name切分為first_name, last_name, mid_name三部分棒旗。這里只保留mid_name,其余兩個(gè)暫時(shí)不用撩荣。
def name_split(data):
first_name, last_name, mid_name = [], [], []
for name in data['Name']:
name = re.split(r'[,.]\s*', name)
first_name.append(name[0])
mid_name.append(name[1])
last_name.append(name[2])
#data['first_name'] = first_name
data['mid_name'] = mid_name
#data['last_name'] = last_name
print(data['mid_name'].value_counts()) # 輸出mid_name中的非重復(fù)元素
return data
>>
Mr 517
Miss 182
Mrs 125
Master 40
Dr 7
Rev 6
Mlle 2
Major 2
Col 2
Lady 1
Capt 1
Ms 1
Mme 1
Sir 1
Jonkheer 1
the Countess 1
Don 1
可以看出铣揉,mid_name中共含有十多個(gè)非重復(fù)元素。查找資料發(fā)現(xiàn)餐曹,稱謂的說明包含了這些稱謂的解釋老速。
Dr.= doctor 醫(yī)生/博士
Rev.= reverend,用于基督教的牧師凸主,如the Rev. Mr.Smith
Dona橘券,是西班牙語對(duì)女子的稱謂,相當(dāng)于英語的 Lady
Don,n. <西>(置于男士名字前的尊稱)先生旁舰,堂
Master锋华,小男孩,相當(dāng)于漢語的"少爺"箭窜。
jonkheer是貴族
Col毯焕,Colonel,上校
capt船長(zhǎng); captain (陸軍)上尉; (海軍) 上校
major磺樱, 陸軍少校意思有少校人意思
The Countless纳猫,女伯爵
Mlle,小姐
Mme是Madame的簡(jiǎn)寫,<法>(用于已婚婦女姓名前的尊稱)太太
方法1:利用專業(yè)知識(shí)對(duì)離散的字符特征進(jìn)行分組
根據(jù)常識(shí)竹捉,稱謂中一般包含以下三方面的信息:
- 【年齡】:Mrs, Miss, Mr and Master等芜辕。稱謂中的年齡信息基本和age特征同步。
- 【性別】:基本和sex特征同步块差;
- 【社會(huì)等級(jí)】:尊貴的人/平民侵续。??尊貴的人:jonkheer、The Countless
- 【職業(yè)】:可分為船員憨闰、牧師状蜗、軍人、醫(yī)生等鹉动。
檢查測(cè)試集中的稱謂是否和訓(xùn)練集中一致:一致√
print(data['mid_name'].value_counts())
>>
Mr 757
Miss 260
Mrs 197
Master 61
Rev 8
Dr 8
Col 4
Ms 2
Major 2
Mlle 2
Mme 1
Don 1
Dona 1
Lady 1
the Countess 1
Sir 1
Jonkheer 1
Capt 1
featureGroupbyList(data, 'mid_name', [['Mme', 'Ms', 'Mrs'],
['Mlle', 'Miss'],
['Mr'],
['Master'],
['other'],
['Capt', 'Col', 'Dr', 'Major', 'Rev']],
"mid_nameGroup", ['Mrs', 'Miss', 'Mr', 'Master', 'Royalty', 'officer'])
因此轧坎,參考Titanic Kaggle Challenge,對(duì)'mid_name'進(jìn)行分組:
1)以基數(shù)較多的Mr泽示、Miss缸血、Mrs和Master 為四個(gè)獨(dú)立類別;
2)從剩余基數(shù)較少的mid_name中歸納出Royalty边琉、officer兩個(gè)新類属百。
方法2:利用特征數(shù)據(jù)-label標(biāo)簽之間的相關(guān)程度進(jìn)行分組
這種方法忽略midname各取值的現(xiàn)實(shí)意義变姨,完全根據(jù)label列的表現(xiàn)進(jìn)行分組族扰。
--1)考慮子圖1中特征基數(shù)影響,將特征分為['Mr']定欧、['Miss', 'Mrs', 'Master']渔呵、其他 三類。
用字符標(biāo)識(shí)砍鸠,onehot處理扩氢,訓(xùn)練集正常0.83,測(cè)試集降低為0.53588;
用數(shù)值標(biāo)識(shí),試驗(yàn)發(fā)現(xiàn)陆错,離散特征標(biāo)識(shí)的數(shù)值大小遥巴,對(duì)SVM模型的預(yù)測(cè)結(jié)果有顯著影響!P嘟伞蝇完!
當(dāng)數(shù)值依次為-1洒敏、1咏花、0時(shí)趴生,訓(xùn)練集0.83,測(cè)試集0.636昏翰。
--2)忽略子圖1中特征基數(shù)的影響苍匆,按照子圖3中存活率比例,將所有特征劃分為三類:
featureGroupbyList(data, 'mid_name', [['Lady', 'Mlle', 'Mme', 'Ms', 'Sir', 'the Countless'],
['other'],
['Capt', 'Don', 'Jonkheer', 'Major', 'Mr', 'Rev']],
"mid_nameGroup", ['high', 'medium', 'low'])
結(jié)果表明:
第二種方法不如第一種方法浸踩,應(yīng)該依靠特征的實(shí)際意義進(jìn)行處理。
另計(jì):??標(biāo)識(shí)的數(shù)值依次為2窍株、1000民轴、0時(shí)攻柠,訓(xùn)練集0.83球订,測(cè)試集0.79904,竟然刷新了個(gè)人最高分瑰钮,說明這個(gè)特征是有益的冒滩,且數(shù)值標(biāo)識(shí)value有顯著影響。
2)Pclass座艙等級(jí)
該特征雖然是用123數(shù)字表示浪谴,它本質(zhì)是離散特征开睡,應(yīng)該進(jìn)行onehot處理。
- 該屬性本質(zhì)是離散特征苟耻,改變它的數(shù)值標(biāo)識(shí)大小為100篇恒、2、0時(shí)凶杖,測(cè)試集得分從0.79904小幅回跌至0.79425胁艰;
- 改變它的數(shù)值標(biāo)識(shí)大小為100、10智蝠、1時(shí)腾么,測(cè)試集得分為0.79425;
提示:后續(xù)的Fare特征補(bǔ)全中利用了該特征杈湾,因此修改Pclass的value時(shí)應(yīng)該同步修改data['Fare'].fillna(data.Fare[data.Pclass == 3].median(), inplace=True)
3)sex性別
??性別特征無缺失解虱,屬于典型的兩種取值的離散特征,0/1數(shù)值編碼(1個(gè)特征)漆撞、onehot編碼(2個(gè)特征)是完全等效的殴泰。用數(shù)值編碼等效于pd.dummpy(drop_first=True)于宙。
data['Sex'] = data['Sex'].map({'male': 1, 'female': 0})
可以看出悍汛,登船的男性乘客數(shù)量顯著多余女性限煞,但是幸存率卻顯著低于女性,這說明了性別確實(shí)存在顯著影響员凝。但是署驻,該特征屬于典型的兩種取值的離散特征,即使用1/100的數(shù)值編碼健霹,當(dāng)0-1標(biāo)準(zhǔn)化處理后依然等效于0/1數(shù)值編碼旺上。
4)ticket票號(hào)
??票號(hào)和座艙等級(jí)、座位位置(靠窗糖埋、過道)等有關(guān)宣吱,猜想是很有用的特征。
它的value形式如:A/5 21171 瞳别,可大致劃分為兩部分征候,
-- 1)提取首字母
-- 2)提取數(shù)字的位數(shù)。注意:存在四個(gè)票后為L(zhǎng)INE祟敛,不包含任何數(shù)字的ticket疤坝。
將 'TicketFirstLetter'特征進(jìn)一步Group處理:
featureGroupbyList(data, 'TicketFirstLetter', [[3, 4, 5, 6, 7, 8, 'A', 'W'], [1, 9, 'P'], ['other']],
"TicketFirstLetterGroup", ['verylow', 'high', 'medium'])
5)cabin 艙室號(hào)碼
print(data['Cabin'].unique())
>>
nan 'C85' 'C123' 'E46' 'G6' 'C103' 'D56' 'A6' 'C23 C25 C27' 'B78' 'D33'
'B30' 'C52' 'B28' 'C83' 'F33' 'F G73' 'E31' 'A5' 'D10 D12' 'D26' 'C110'
'B58 B60' 'E101' 'F E69' 'D47' 'B86' 'F2' 'C2' 'E33' 'B19' 'A7' 'C49'
提取首字母馆铁。只有cabin=T時(shí)存活率極低跑揉,其他取值并無區(qū)分性。
處理:featureGroupbyList(data, 'Cabin', [['T'], ['other']], "CabinGroup", [0, 1])
對(duì)于這種缺失值比例極大的特征历谍,需要注意干擾。
6)embarked 登船港口
C = Cherbourg,
Q = Queenstown,
S = Southampton
缺失補(bǔ)全問題:訓(xùn)練集僅有2個(gè)缺失記錄辣垒,測(cè)試集無缺失望侈,因此沒必要考慮是否用unknown來標(biāo)記缺失值。由于該三種取值的字符型特征不好尋找相關(guān)特征勋桶,直接用眾數(shù)填充脱衙。
data['Embarked'].fillna(data['Embarked'].mode()[0], inplace=True)
等價(jià)于:df['Embarked'][df['Embarked'].isnull()]=df.Embarked.dropna().mode().values
print('embark_fill value:', data['Embarked'].mode())
1.2 連續(xù)特征處理
1)SibSp 兄弟姐妹哥遮、配偶數(shù)量 + Parch 父母岂丘、兒女?dāng)?shù)量 = Family_Size
Sibling = brother, sister, stepbrother, stepsister
Spouse = husband, wife (mistresses and fiancés were ignored)
Parent = mother, father
Child = daughter, son, stepdaughter, stepson
featureGroupbyList(data, 'Family_Size', [[1, 2, 3], [0, 4, 5, 6], [7, 8, 9, 10]],
"Family_SizeGroup", ['medium', 'low', 'verylow'])
3)fare 票價(jià)
缺失補(bǔ)全問題:測(cè)試集中只有存在唯一一個(gè)fare缺失項(xiàng)奥帘。基于常識(shí)仪召,我們猜想fare票價(jià)和Pclass艙室等級(jí)具有較強(qiáng)的相關(guān)性寨蹋。
用皮爾遜相關(guān)系數(shù)查看:確實(shí)√松蒜,在所有特征列中,fare和Pclass的相關(guān)性最高已旧。備注:Fare_Per_Person是基于Fare構(gòu)造的新特征秸苗,需排除在外。
因此运褪,查詢到該fare缺失乘客Pclass = 3惊楼,所以用該艙室等級(jí)對(duì)應(yīng)的fare平均值進(jìn)行填充。
def fare_fill(data):
fare = data.Fare[data.Pclass == 3].mean()
print('fare fillvalues:', fare)
data.Fare.replace(np.NaN, fare, inplace=True)
return data
將Fare劃分為:[0,51]檀咙、(51,...) 兩個(gè)區(qū)間。結(jié)果如下圖璃诀,F(xiàn)areGroup特征表現(xiàn)出了不錯(cuò)的區(qū)分度弧可。
4)Age
age特征存在缺失值,但由于占比只有1-714/891=0.198劣欢,可以對(duì)其進(jìn)行補(bǔ)全后利用棕诵。
補(bǔ)全思路:考慮到mid_name稱謂中包含部分age信息,可通過前者對(duì)人群進(jìn)行分類后凿将,再按照子類別的age信息進(jìn)行補(bǔ)全校套。注意:這里同時(shí)對(duì)訓(xùn)練集、測(cè)試集補(bǔ)全丸相,最大限度利用已知數(shù)據(jù)信息Iθ贰彼棍!
首先灭忠,查看age缺失記錄中對(duì)應(yīng)的mid_name種類和缺失數(shù)量。
print(data.loc[data.Age.isnull(), 'mid_name'].value_counts())
Mr 176
Miss 50
Mrs 27
Master 8
Ms 1
Dr 1
其次座硕,再看看這幾種人群的基數(shù)數(shù)量(見name特征處理部分)弛作。他們的基數(shù)均偏多,基本可以用各自的age均值進(jìn)行填充华匾。
填充結(jié)果:
age fillvalues: {
'Mr': 32.25215146299484,
'Ms': 28,
'Mrs': 36.99411764705882,
'Miss': 21.774238095238097,
'Master': 5.482641509433963,
'Dr': 43.57142857142857}
可以看出映琳,五種人群都匹配了較好的缺失填充年齡,和常識(shí)基本吻合蜘拉。只是這個(gè)master:4.57 五歲的小寶寶萨西?原來,master并不是碩士稱謂旭旭,而是對(duì)小男孩的稱呼谎脯。詳見:http://blog.udn.com/article/article_print.jsp?uid=z1627384950&f_ART_ID=7592122
再將Age劃分為40個(gè)連續(xù)區(qū)間,觀察其是否可以進(jìn)行g(shù)roup處理持寄。
1.3 高階特征
所謂高階特征娱俺,是指通過特征間的乘除、冪指等運(yùn)算得到的新特征废麻。這里荠卷,暫時(shí)不把加減運(yùn)算得到的新特征歸為高階特征,前面已對(duì)這種進(jìn)行了分析烛愧。
高階特征1:df['Age*Class']=df['Age']*df['Pclass']
理由:This is an interaction term, since age and class are both numbers we can just multiply them.
高階特征2::df['Fare_Per_Person']=df['Fare']/(df['Family_Size']+1)
理由:Here we divide the fare by the number of family members traveling together, I’m not exactly sure what this represents, but it’s easy enough to add in.因?yàn)椴僮鞑宦闊┯鸵耍蜆?gòu)造了一個(gè)新特征,很隨性怜姿。
總結(jié)1:One thing you can do to create new features is linear combinations of features. In a model like linear regression this should be unnecessary, but for a decision tree may find it hard to model such relationships.
【通過線性方法(加減)去構(gòu)建新的特征,這對(duì)于線性回歸等模型來說社牲,是沒有必要的粪薛,但是它對(duì)決策樹等模型來說就很有意義〔簦】因此违寿,這種構(gòu)建新特征的方法仍是可取的。
總結(jié)2:interaction term交互項(xiàng)至少對(duì)線性模型來說熟空,是很有必要的藤巢,猜想它對(duì)決策樹等模型也是有益的。interaction term交互項(xiàng)就是對(duì)兩個(gè)或多個(gè)均數(shù)值型特征【相乘】息罗,構(gòu)造出的新特征掂咒。交互項(xiàng)=自變項(xiàng)×調(diào)節(jié)項(xiàng),即一對(duì)存在主從迈喉、因果關(guān)系的特征相乘绍刮。
參考:因果關(guān)係的第三者-調(diào)節(jié)變項(xiàng)(Moderator / Moderation)
文獻(xiàn):Interpreting Interactions in Regression
以線性模型為例:
假設(shè) 減肥行為模型model = 截距 + a×減肥知識(shí) + b×性別 + c×(性別×知識(shí))+ 殘差error
如果不自行構(gòu)造(性別×知識(shí))的interaction term交互項(xiàng)特征,僅靠減肥知識(shí)挨摸、性別兩個(gè)原有特征孩革,通過線性模型或其他常見模型是不能擬合出來的。
1.4 離散字符特征的連續(xù)化處理:
# 刪除label列以及無用的離散特征原列得运,用于特征選擇
x_use_all = x_all.drop(
['Survived', 'Cabin', 'Name', 'Parch', 'PassengerId', 'SibSp', 'mid_name',
'Ticket'], axis=1)
x_use_all = pd.get_dummies(x_use_all,drop_first=True) # 對(duì)選的use_feature進(jìn)行onehot處理
print('use_feature經(jīng)onehot處理后的特征共%d個(gè)膝蜈,分別為:' % x_use_all.columns.size, x_use_all.columns) # 對(duì)所有字符特征進(jìn)行onehot處理
1.5 特征選擇
# 選擇特征: 嵌入法,用于模型擬合
sfm = SelectFromModel(XGBClassifier(n_estimators=90, learning_rate=0.1, max_depth=6, min_child_weight=8, gamma=0),
threshold=0.004, max_features=15) # 設(shè)置特征選擇的相關(guān)閾值
x_train = sfm.fit_transform(x_train_dummy, y_train)
x_test = sfm.transform(x_test_dummy)
print('-' * 20, '以下為特征選擇結(jié)果信息:', '-' * 20)
feature_selected = x_train_dummy.columns[sfm.get_support(indices=False)]
# print('最終選取的特征共%d個(gè)熔掺,分別為:' % feature_selected.size, feature_selected)
features = pd.DataFrame()
features['feature'] = x_use_all.columns
features['importance'] = sfm.estimator_.feature_importances_
features.sort_values(by=['importance'], ascending=True, inplace=True)
features.index = range(features.index.size, 0, -1)
# features.set_index('feature', inplace=True)
print('最終選取的特征共%d個(gè)饱搏,按importances排序分別為:' % len(feature_selected))
print(features[-len(feature_selected):][::-1])
# features.plot(x='feature', y='importance', kind='barh', figsize=(25, 50))
# plt.show()
print('-' * 50)
2. 模型-調(diào)參-評(píng)估
2.1 LR調(diào)參
parameters_lr = {'penalty': ['l1'],
"C": [0.001, 0.01, 1],
'solver': ['liblinear','saga']
}
2.2 SVM調(diào)參
# SVM模型屬于距離計(jì)算模型,需要對(duì)輸入X進(jìn)行歸一化處理
x_train = MinMaxScaler().fit_transform(X=x_train)
x_test = MinMaxScaler().fit_transform(X=x_test)
# gridsearch
parameters_svm = {'C': np.arange(2.5, 7, 0.5),
'kernel': ['rbf'],
'gamma': np.arange(0.05, 0.7, 0.1),
# 'degree': [3, 4],
# 'probability': [True, False],
# 'class_weight': ['balanced', None]
}
調(diào)參總結(jié):
1)SVM要計(jì)算margin置逻,margin是一種距離計(jì)算推沸,因此一定要對(duì)數(shù)據(jù)進(jìn)行歸一化,否則收斂會(huì)非常非常慢诽偷;
2)如下圖坤学,gridsearch時(shí)疯坤,應(yīng)該先找到影響最大的參數(shù),這里gamma參數(shù)的變化就給score帶來了明顯的提升深浮。
經(jīng)過對(duì)gamma參數(shù)的兩輪調(diào)節(jié)压怠,知道它的最優(yōu)取值大概在3~5附近。
3)第二重要參數(shù)是C
經(jīng)過兩輪C參數(shù)調(diào)參飞苇,可以看出它的最優(yōu)取值基本在1~5之間菌瘫。
4)class_weight參數(shù)
原以為該問題中存在輕微的survival樣本不均衡,設(shè)置class_weight=balanced會(huì)提升效果布卡,但事實(shí)證明相反雨让。
5)其他模型參數(shù)
degree : int, optional (default=3) 僅當(dāng)kernel= ‘poly’多項(xiàng)式核函數(shù)時(shí)有效;
'decision_function_shape': ['ovo', 'ovr'] 參數(shù)對(duì)結(jié)果基本沒有任何影響忿等。
SVM調(diào)參結(jié)果:
best_score_: 0.8260381593714927
best_params_: {'C': 2, 'class_weight': None, 'gamma': 5, 'kernel': 'rbf', 'probability': True}
提交后的得分為:0.78468
除了前述的對(duì)模型參數(shù)優(yōu)化以外栖忠,還可以:
- 針對(duì)模型特點(diǎn),對(duì)特征數(shù)據(jù)進(jìn)行修改贸街;
- 對(duì)調(diào)參過程中的超參數(shù)(如交叉驗(yàn)證的CV參數(shù))進(jìn)行優(yōu)化庵寞。
先對(duì)超參數(shù)CV進(jìn)行優(yōu)化:
for cv in [3, 5, 7, 9]:
print('cv=', cv)
model = grid(SVC(), parameters_svm, cv)
test_prediced = model.predict(x_test)
final_df = pd.DataFrame(data={'PassengerId': range(892, 892 + 418), 'Survived': test_prediced})
final_df.to_csv(r'test_pred_svm\test_pred__bySVM_gridsearch_noEmBark_cv=%d.csv' % cv, index=False)
print('-' * 20)
>>
cv= 3
best_score_: 0.8237934904601572
best_params_: {'C': 2, 'class_weight': None, 'gamma': 7, 'kernel': 'rbf', 'probability': True}
--------------------
cv= 5
best_score_: 0.8271604938271605 #得分最高
best_params_: {'C': 5, 'class_weight': None, 'gamma': 5, 'kernel': 'rbf', 'probability': True}
--------------------
cv= 7
best_score_: 0.8249158249158249
best_params_: {'C': 2, 'class_weight': None, 'gamma': 7, 'kernel': 'rbf', 'probability': True}
--------------------
cv= 9
best_score_: 0.8260381593714927
best_params_: {'C': 2, 'class_weight': None, 'gamma': 5, 'kernel': 'rbf', 'probability': True}
--------------------
將CV=5的預(yù)測(cè)結(jié)果提交kaggle,得分小幅提升至:0.78947
2.3 DT薛匪、GBDT調(diào)參
# 因?yàn)樽幽P褪荄T捐川,因此需要進(jìn)行歸一化處理
x_train = MinMaxScaler().fit_transform(X=x_train)
x_test = MinMaxScaler().fit_transform(X=x_test)
parameters_gbdt = {'learning_rate': [0.1], # np.arange(0.001, 0.1, 0.005),
'n_estimators': [65], # np.arange(25, 100, 5),
# 樹參數(shù)
'max_depth': [9], # np.arange(2, 10, 1),
'min_child_weight': [6], # np.arange(2, 10, 1), # 剪枝部分,肯定會(huì)降低訓(xùn)練集準(zhǔn)確率逸尖,因此要逐個(gè)嘗試
'gamma': [0.8], # [i / 10 for i in range(0, 10)],
# 'subsample': [i / 100 for i in range(10, 100, 5)], # [i / 100 for i in range(60, 100, 5)]
# 'colsample_bytree': [i / 100 for i in range(10, 100, 5)], # [i / 100 for i in range(60, 100, 5)]
# 'reg_alpha': [0], # [0, 1e-6, 1e-5, 1e-2, 0.1,1]
# 'reg_lambda': [0.05], # np.arange(0.01, 0.3, 0.02)
}
核心思想:
learning rate越小越好古沥,learning rate和n_estimators互相制約
1)先在learning rate=0.1(偏大)時(shí),找出最佳的n_estimators子樹數(shù)量
發(fā)現(xiàn)n_estimators在30-35附近娇跟,此時(shí)應(yīng)該根據(jù)訓(xùn)練集樣本量岩齿、特征數(shù)來評(píng)估n_estimators取值是否合理?
由于這里樣本數(shù)僅為900個(gè)逞频,特征10個(gè)左右纯衍,無需那么多n_estimators,因此基本合理苗胀。如果n_estimators明顯過小,則應(yīng)該適當(dāng)增大learning rate瓦堵,重新測(cè)試基协;反之,減小learning rate菇用。
這里澜驮,繼續(xù)用np.arange(25, 40, 2)嘗試:最佳為29
2)再優(yōu)化tree參數(shù),對(duì)結(jié)果影響最大的參數(shù)應(yīng)該優(yōu)先調(diào)節(jié)
參數(shù):max_depth, min_child_weight, gamma, subsample, colsample_bytree
'max_depth': np.arange(2, 10, 1),
'min_child_weight': np.arange(1, 5, 1),
最佳取值為:'max_depth': 7, 'min_child_weight': 1惋鸥,此時(shí)best_score_: 0.8462401795735129
再調(diào)gamma參數(shù):'gamma': [i / 10.0 for i in range(0, 5)]
最優(yōu)值為:0
再調(diào)subsample杂穷、colsample_bytree參數(shù):
'subsample': [i / 10.0 for i in range(6, 10)],
'colsample_bytree': [i / 10.0 for i in range(6, 10)],
最優(yōu)值為:'subsample': 0.8悍缠,'colsample_bytree': 0.7,此時(shí)0.8540965207631874
再以0.05為步長(zhǎng)進(jìn)行微調(diào):
'subsample': [i / 100.0 for i in range(70, 90, 5)],
'colsample_bytree': [i / 100.0 for i in range(60, 80, 5)],
結(jié)果一樣
最優(yōu)值為:'reg_alpha': 1e-05,reg_lambda': 0.15耐量,此時(shí)best_score_: 0.8552188552188552飞蚓,小幅上升。
進(jìn)一步優(yōu)化:'reg_alpha':[0, 1e-6, 1e-5, 1e-2, 0.1]廊蜒,'reg_alpha':0趴拧,得分未變。
3)最后逐步降低learning rate山叮,同時(shí)等比例放大n_estimators
先將earning rate降低1倍為0.05著榴,n_estimators放大1倍為58,best_score_: 0.8406285072951739得分明顯降低屁倔。
最終脑又,best_score_: 0.8552188552188552
2.4 模型融合
所謂三個(gè)臭皮匠賽過諸葛亮,單個(gè)模型的結(jié)果不盡如人意锐借,應(yīng)該考慮進(jìn)行融合處理挂谍,通常能夠提升性能。
xgboost_pred = pd.read_csv(r"test_pred_DT\test_pred__byGBDT_gridsearch_with_cv=5.csv", engine='python', index_col=[0],
skiprows=[0], header=None, names=['xgboost_label'])
xgboost_prob = pd.read_csv(r"test_pred_DT\test_prob__byGBDT_gridsearch_with_cv=5.csv", engine='python', index_col=[0],
skiprows=[0], header=None, names=['xgboost_prob'])
svm_pred = pd.read_csv(r"test_pred_svm\test_pred__bySVM_gridsearch_withAgeGroup_cv=6.csv", engine='python',
index_col=[0], skiprows=[0], header=None, names=['svm_label'])
svm_prob = pd.read_csv(r"test_pred_svm\test_prob__bySVM_gridsearch_withAgeGroup_cv=6.csv", engine='python',
index_col=[0], skiprows=[0], header=None, names=['svm_prob'])
lr_pred = pd.read_csv(r"test_pred_LR\test_pred_byLR_gridsearch_cv=3.csv", engine='python',
index_col=[0], skiprows=[0], header=None, names=['lr_label'])
lr_prob = pd.read_csv(r"test_pred_LR\test_prob_byLR_gridsearch_cv=3.csv", engine='python',
index_col=[0], skiprows=[0], header=None, names=['lr_prob'])
all_pred = pd.concat([xgboost_pred, svm_pred, xgboost_prob, svm_prob, lr_pred, lr_prob], axis=1)
# all_pred['xgboost_0.5'] = all_pred['xgboost_prob'] - 0.5
# all_pred['svm_0.5'] = all_pred['svm_prob'] - 0.5
all_pred['mean'] = all_pred[['xgboost_prob', 'svm_prob', 'lr_prob']].mean(axis=1)
all_pred['mean'] = all_pred['mean'].apply(lambda x: 1 if x >= 0.5 else 0)
all_pred['Survived'] = all_pred['mean']
print(all_pred[all_pred['xgboost_label'] != all_pred['svm_label']])
all_pred['Survived'].to_csv(r'ensembel.csv', index_label='PassengerId', index=True, header=True)
這里用三個(gè)模型預(yù)測(cè)概率的mean進(jìn)行判斷瞎饲。三個(gè)模型單獨(dú)得分為:
LR: 0.78947
SVM: 0.79904
XGBoost: 0.79904
融合模型:0.80382
賽事評(píng)價(jià)
kaggle排名中有很多準(zhǔn)確率達(dá)到1的結(jié)果口叙,國(guó)內(nèi)外網(wǎng)站上的討論How do those awesome people improve their score to above 0.9, to an even 1, for the competition “Titanic: Machine Learning from Disaster” in Kaggle?
都認(rèn)為可能是利用Titanic的公開性,進(jìn)行了作弊嗅战。例如妄田,https://en.wikipedia.org/wiki/Passengers_of_the_RMS_Titanic這個(gè)網(wǎng)站就有相關(guān)幸存者信息等。
而根據(jù)樣本數(shù)據(jù)能夠做到的實(shí)際最優(yōu)效果可能是在0.8~0.9之間驮捍。為了避免這個(gè)問題疟呐,消除作弊者的影響,可盡量采用非公開事件的賽題东且,即不能通過公開渠道獲取正確lable的問題启具。
參考:
- https://ahmedbesbes.com/how-to-score-08134-in-titanic-kaggle-challenge.html
- Megan Risdal Exploring Survival on the Titanic
- Edward Lu
- 刪除了訓(xùn)練集中票價(jià)fare=0的樣本數(shù)據(jù)
理由:票價(jià)為零屬于一種特殊情況(勞力、苦役等珊泳?)鲁冯,通過查看,發(fā)現(xiàn)所有的這15個(gè)人都是男性色查、都是獨(dú)行(沒有家人同行)薯演、且只有1/15的比例幸存。因此秧了,作者認(rèn)為這些數(shù)據(jù)屬于無效的干擾數(shù)據(jù)跨扮。
疑問補(bǔ)充:測(cè)試集中情況呢?發(fā)現(xiàn)測(cè)試集中有2個(gè)票價(jià)為零的記錄,且他們也都是男性衡创、沒有家人同行帝嗡。
- Konstantin’s kernel Titanic [0.82] - [0.83] utilized the Family Survival feature which was introduced by Sina in his kernel Titanic best working Classifier
-
Chris Deotte’s Titantic Mega Model - [0.84210] combines Kaggle's top 6 Titanic models
很有意思,作者開頭就說這篇文章 is not for beginners 璃氢,感覺很厲害的樣子哟玷。
- 對(duì)各個(gè)特征列是否有貢獻(xiàn)進(jìn)行了分析,例如作者認(rèn)為登船港口特征對(duì)模型沒有任何貢獻(xiàn)拔莱,為什么還要保留它碗降。
??嘗試了一下,保留/刪除Embarked特征前后塘秦,利用XGB分類模型讼渊,模型在訓(xùn)練集上的準(zhǔn)確率從93%跌落至87.%,但提交到Kaggle后尊剔,在測(cè)試集上的表現(xiàn)反而從0.75提升至0.77爪幻。很神奇。 - 認(rèn)為dummy這種類似onehot處理须误,對(duì)模型沒有提升挨稿;
-
Tomi Gelo's model combines some of the features above together with the AutoML-tool TPOT to score 0.81 (top 4%)
https://github.com/dashjim/kaggle-titanic