这篇随笔记录我解答Kaggle”入门第一题“——Titanic问题的历程。将随着我对这个题目的思考而不断更新。

题目描述:

题目的数据集包含了当年乘坐泰坦尼克号出行的1309名乘客(失事时,船上据称有2224名船员和乘客)的各类信息,其中训练集891行,测试集418行。包含的特征如下:

变量名中文译名详情
PassengerId乘客编号无意义,仅用于为乘客进行编号,从1-1309
survival是否幸存

本次预测项目的目标——TestSet将其抹去,并作为评分标准。

在历史上,这个乘客有没有幸存下来。如果活下来标为1,没有存活则标为0.

pclass船舱等级1=头等舱; 2=二等舱; 3=三等舱 (Kaggle将其作为乘客社会地位的象征)
sex乘客性别标为male与female。
name姓名乘客的全名。emmmmm,这个特征一来不太好用,二来适合用来作弊.......
Age年龄

乘客的年龄,有很多NaN(其实在网上能够找到......)

sibsp同辈亲属

按照Kaggle的说法,这是sibling(兄弟姐妹)、spouse(配偶)的合写。

对于某个乘客而言,如果船上有他们的sibling或者spouse,那么有几个sibsp就是几,parch下同。

”Sibling“定义为”兄弟姐妹、义兄弟(stepbrother)、义姐妹(stepsister)”;

 "Spouse"仅限于正式夫妻。情人、未婚夫妻(mistresses, fiances)不计入

parch长辈晚辈

”parch“是”parent“和”child“的缩写。仅限于父母、子女、继子女。

Kaggle特别指出,有些孩子由保姆跟随旅行,他们的parch为0

ticket船票编号船票的编号,编号的形式有一点奇特,有的是纯数字,有的带有一些英文字母
fare票价乘客购票的价格
cabin客舱号乘客当时所处的客舱号码,有少量的数据(大多数的NaN)
Embarked登船港口

C = Cherbourg(法国瑟堡),S = Southampton(英国南安普顿),

Q = Queenstown( 昆士敦,今称科夫Cobh,位于爱尔兰),有少量的NaN

Kaggle要求提交一份CSV文件,包含两列418行,第一列是PassengerId,第二列是survived,即预测结果。提交后大约五分钟即可得到评分,每日可提交最多10次,成绩只保存两个月。不要理会LeaderBoard上那些满分的”大佬“,据讨论版的人说,那些人是作弊的——毕竟数据集里连乘客的名字都有,按照历史名单比对一下,”做个答案“出来也不是什么费劲的事,专注于自己的正确率就好了,在今天(2019年11月9日)更新的leaderboard上,84%的预测正确率已经可以达到第200名(前1.5%)。

Chapter 1 --  脑袋一热——原始型SVM

有必要提到的是,我的第一次尝试是在学术论坛的观众席上做出的,从开始读题到提交不超过一个半小时......

数据处理

  除了因变量survived之外,Kaggle给出了十种特征。

  在这次临时起意中,sibsp/parch/pclass这三个离散变量被完整保留。而name/cabin/ticket由于”意义不明“被我直接切除,换句话说,在这次分析过程中,我只采用了7种特征。

  •   sex - female 标为0, male标为1
  •   age - 缺失值采用平均值填补(这里是一处败笔,后来复盘的时候觉得这里应该考虑进行回归,并考虑年龄缺失这一现象是否与乘客幸存与否有关),并进行Z-Score做标准化。
  •   fare - 用Z-score做标准化
  •   embarked - 一分为三,做成三个0-1变量Cherbourg/Southampton/Queenstown,删除embarked列。其中Southampton的比例为70%以上(历史上Titanic航行的出发地)。

调参和预测

SVM调参利用了sklearn.model_selection下的GridSearchCV函数,这个函数适合在训练集较小的情况下进行调参,而大样本情形下效率很低(我又闻到了CPU的香气),其对不同参数组合的评价方式可以进行设定,默认采用Accuracy即分类精度。Python下的代码实现如下:

 1 svc = SVC()
 2 Parameters = [{'C' : [1,1.5,2,2.5,3,3.5,4,4.5,5],
 3 'gamma' : [0.01,0.05,0.1,0.5,1],
 4 'kernel' : ['rbf']},
 5 {'C':[1,2,3,4,5,6,7,8,9,10],
 6 'kernel':['linear']}]
 7 clf= GridSearchCV(svc,Parameters,cv = 5, n_jobs = 6)
 8 clf.fit(X_train,Y_train)
 9 print(clf.best_params_)
10 #Result: C = 2, gamma = 0.1 if using Gaussian Kernel

GridSearchCV的参数有很多种,这里填写的四种依次是分类器名(svc),候选参数集(Parameters),K折交叉验证的折数(cv),并行计算进程数(n_jobs)。并用clf.fit来对训练集的数据进行拟合,得到最佳的参数组合。这里设定的候选参数集有两类:一类是高斯核(‘rbf’),需要C和Gamma两个参数(罚项系数和分布幅宽),另一类是线性核(”linear"),仅需C一项系数。最后程序返回的结果是:

{'C': 2, 'gamma': 0.1, 'kernel': 'rbf'}

返回结果表示,C为2,gamma为0.1的高斯核形式具有最好的预测准确率。"clf.best_params_"返回的是一个字典,在下面设定正式的SVM模型参数时,可以直接调用这个字典的数据。将这组参数组合输入SVM中进行拟合和预测,即可得到最后的预测结果,为了检测这个SVM的预测性能,我做了一次五折交叉验证:

 1 from sklearn.model_selection import StratifiedKFold
 2 from sklearn.metrics import precision_score, recall_score, f1_score
 3
 4 skf = StratifiedKFold(n_splits= 5)
 5 clfer = SVC(kernel = 'rbf', C=clf.best_params_['C'],gamma = clf.best_params_['gamma'])
 6 precision = [];recall = []; f1 = []
 7 results = []
 8 X = np.array(X_train); Y = np.array(Y_train)
 9 for train_index, test_index in skf.split(X,Y):
10     X_TRAIN, X_TEST = X[train_index], X[test_index]
11     Y_TRAIN, Y_TEST = Y[train_index], Y[test_index]
12     #五折数据集分开,并自动分为4+1,且各数据集的0/1比例是完全相同的。
13     #下一步进行具体的SVM训练和评估。
14     clfer.fit(X_TRAIN,Y_TRAIN,None)
15     result = clfer.predict(X_TEST)
16     precision.append(precision_score(Y_TEST,result))
17     recall.append(recall_score(Y_TEST,result))
18     f1.append(f1_score(Y_TEST,result))
19     results.append(result)

StratifiedKFold据说可以尽可能均匀地将0观测点和1观测点均匀地分到各折,使得每次的数据集都具有同等的训练价值。在最后对五次交叉验证的precision、recall、f1进行计算,评估预测的精确程度。基本上这个算法可以保证F1值高于75%,precision比较高(80%以上),而recall相对较低(70%-75%),考虑可能出现了较多的False Negative。这一次的Kaggle提交得分为0.78948,提交后位列3347/14227。

01-08 04:29