kaggle项目之Titanic数据集

本例主要针对kaggle上的Titanic数据集进行分析预测,文章主体分为以下两个部分:

  • 机器学习流程的回顾
  • Titanic数据集的分析和处理
    image

    PS:流程回顾来源于Udacity的机器学习入门课程,Titanic数据的处理参考了kaggle上众位大佬的分享。
    ——————流程回顾——————

在开始进行分析之前,让我们仔细回顾下一个机器学习项目的流程。

数据集/问题——>特征处理——>算法建模——>评估

第一步,数据集/问题

机器学习是用来解决实际问题的,收集与实际问题有关的数据,能够有助于后续步骤的继续进行。在这个阶段需要知道

  • 数据量足够大?
  • 我提出了什么问题?
  • 要回答这个问题,有足够的正确的特征么?
第二步,特征处理
  • 探索型分析(EDA)
    分析特征与变量的相关性(pearsonr相关系数)
    删除一些离群值
    清理特征与数据

  • 生成新的特征
    一般来说,基于对现实业务的了解,生成新的特征。

  • 特征选择

    • 单变量特征选择工具:
      SelectPercentile :最强大的 X% 特征(X 是参数)
      SelectKBest :选择 K 个最强大的特征(K 是参数)
    • 迭代特征(增/减)
    • lasso回归:
      在最小误差与特征数量之间寻找一个平衡,实际应用中,该数值越接近0,说明该特征带来的影响也就越小。
    • 删除不必要的特征
  • 特征的缩放(适用于维度变化的算法):
    减去平均值:x - mean
    minmax scaler:(x-min)/(max-min)
    standard scaler:(x-mean)/sigma

  • 转换特征:

    • PCA(主成分分析):数据中使方差最大化的方向,在对这些成分压缩或投影时,将信息丢失的可能性降至最低。
      【只对符合高斯分布的样本点有效】
      一般用于转换成新的特征,也可以用来划分等级,方差最大为第一等级,以此类推,但第一主成分绝对不会与第二主成分叠加。主成分等级的数量是有上限的,受制于输入特征的数量。

      用处:

      • 寻找隐藏特征
      • 降维:可视化高维数据,减噪
    • ICA(独立成分分析)

    • FA(因子分析)

第三步,算法

根据是否需要labels,分为监督学习和非监督学习

  • 监督学习:
    • 回归:线性回归、lasso回归、决策树回归、sv回归
    • 分类:决策树、朴素贝叶斯、SVM、随机森林、Adaboost、knn、LDA、logistic回归
  • 非监督学习:
    • 聚类:K均值、DBSCN、EM算法、离群值检测
  • 运行算法:调参、可视化检验、在测试集上运行、寻找最佳参数(GridsearchCV)
第四步,评估
  • 验证:
    分隔测试集和训练集、k-flods法、可视化
  • 评估指标
    SSE/R^2、准确率、召回率、F1 分数、特征曲线

PS:
以上步骤的顺序不是绝对的,为了获得拥有强大泛化能力的模型,我们需要不断地重复某些步骤。

———————Titanic数据集的分析与预测——————

n久之前,初生不畏牛犊的我,进入了kaggel,第一个练手的数据集——Titanic,死得剧惨。重新整理了思路了之后,预测效果也好了很多,具体思路见下文。

主要思路

  1. 加载数据集并进行简要探索性分析
  2. 特征工程
  3. 建模与模型评估

以前分析思路:
加载数据集——数据清理——探索性分析——特征处理——建模评估

1. 加载数据集&探索性分析

(1)数据概览:

train:


头几行数据

数据类型与空值状况

数据分布的整体状况

从简要的概览中,可以看出训练集中存在这些情况:

  • Age,Cabin,Embarked存在空值
  • Age,SibSp,Parch,Fare分布似乎呈偏右分布,具体还需要验证

测试集的加载和训练集类似,可以自己去试下。
这里为方便处理,合并训练集和测试集,生成新的DataFrame.

#合并测试集和训练集
df =  pd.concat([train, test], axis=0).reset_index()
(2)从分布来看:

a. 整体的生存状况


image

b. SeX


image

c. Pclass
image

image

d. Embarked


image

e. Age
image

f. Fare
image

g. Parch
image

h. SibSp
image

发现:

  • 女性的存活率高于男性
  • Pclass1,2,3的生存率依次降低,这有可能与不同层的乘船人的社会地位,富裕程度有关
  • Pclass 1,2女性的生存率远大于Pclass 3的女性,Pclass 1 的男性的生存率大于Pclass 2,3层的男性
  • S口岸登船的人数最多,生存率也最低,C、Q口岸登船的人数和生存率正好相反。那个时代,远没有现在网络时代的发达,所以我们可以假定认为一个口岸登船的同一层的很容易坐在一起的,这也很可能是一个影响逃生率的因素。
  • 年龄上来说,似乎很统一,小孩先走,存活率较高
  • Fare分布差异很大,可能存在幼童免票,团体票,家庭票等情况
  • Parch 代表同船的父母或子女,SipSp代表同船的兄弟姐妹,这都是两个表现亲人的关系,后面一起会做特征处理。
  • 单人的存活几率低于有1个以上的或3个以下的亲人同船的存活几率,但过于一些过于庞大的家庭成员的生存几率。家庭成员过多也不好,过少也不好。

2. 特征工程

(1)Embarked
#缺失值填充
df['Embarked'].fillna("S",inplace=True)
#数值化S,C,Q
le = LabelEncoder()
le.fit(df['Embarked'])
df['Embarked'] = le.transform(df['Embarked'])
(2)Fare
#分配到个人票价
df['Fare'] = df['Fare'] / df.groupby('Ticket')['Fare'].transform('count')
df['Fare'].fillna(df['Fare'].median(),inplace=True)
sns.distplot(df["Fare"])
plt.title("Distribution of Fare");
image
#定义一个票价分级函数
def fare_level(s):
    if s <= 5 :
        m = 0
    elif s>5 and s<=20:
        m = 1
    elif s>20 and s<=40:
        m = 2
    else:
        m = 3
    return m
df['Fare_level'] = df['Fare'].apply(fare_level)
(3)Parch and SibSp
#组合Parch,SibSp
df['Family_memebers'] = df['Parch'] + df['SibSp'] + 1
(4)Sex
#数值化性别
le.fit(df['Sex'])
df['Sex'] = le.transform(df['Sex'])
(5)Age

年龄拥有大量的缺失值,处理方法有很多中,这里采用建立一个回归模型预测年龄缺失值。

#利用线性回归和随机森林回归模型预测Age的值
age_nan = pd.DataFrame(df[['Age', 'Sex','Family_memebers', 'Fare',  'Pclass', 'Embarked']])
age_train = age_nan[age_nan.Age.notnull()]
age_test = age_nan[age_nan.Age.isnull()]
#线性回归
lr = LinearRegression()
lr_grid_pattern = {'fit_intercept': [True], 'normalize': [True]}
lr_grid = GridSearchCV(lr, lr_grid_pattern, cv=10, n_jobs=25, verbose=1, scoring='neg_mean_squared_error')
lr_grid.fit(age_train.drop("Age",axis=1), age_train["Age"])
print('Age feature Best LR Params:' + str(lr_grid.best_params_))
print('Age feature Best LR Score:' + str(lr_grid.best_score_))
lr = lr_grid.predict(age_test.drop("Age",axis=1))
#随机森林回归
rfr = RandomForestRegressor()
rfr_grid_pattern = {'max_depth': [3], 'max_features': [3]}
rfr_grid = GridSearchCV(rfr, rfr_grid_pattern, cv=10, n_jobs=25, verbose=1, scoring='neg_mean_squared_error')
rfr_grid.fit(age_train.drop("Age",axis=1), age_train["Age"])
print('Age feature Best LR Params:' + str(rfr_grid.best_params_))
print('Age feature Best LR Score:' + str(rfr_grid.best_score_))
rfr = rfr_grid.predict(age_test.drop("Age",axis=1))
#取二者均值
age_test["Age"] = (lr+rfr)/2
#定义年龄分级的函数
def age_level(s):
    if s <= 15 :      #儿童
        m = 0      
    elif s>15 and s<=30: #青年及少年
        m = 1
    elif s>30 and s<=60: #壮年
        m = 2
    else:               #老年
        m = 3
    return m
df["Age_level"] = df["Age"].apply(age_level)

3. 建模与模型评估

X = df[:len(train)][['Age_level', 'Sex','Family_memebers', 'Fare_level',  'Pclass', 'Embarked']]
y = df[:len(train)]["Survived"]
(1)评估方法
  • 混淆矩阵
    有准确率、召回率、F1值等指标,本文采用准确率。
  • 交叉检验
    将数据集划分成n份,选择一份作为测试集,其余n-1份作为训练集,重复n次(每次的测试集都不同)。
(2)建模

利用交叉检验得到结果,cv = 10,指标为准确率,可以看到SVC具有出色的表现。


image
(3)模型优化

主要利用GridSearchCV寻找最佳拟合的结果。

SVMC = SVC(probability=True)
svc_param_grid = {'kernel': ['rbf'], 
                  'gamma': [ 0.001, 0.01, 0.1, 1],
                  'C': [1, 10, 50, 100,200,300, 1000]}

gsSVMC = GridSearchCV(SVMC,param_grid = svc_param_grid, cv=10, scoring="accuracy", n_jobs= 4, verbose = 1)

gsSVMC.fit(X,y)
SVMC_best = gsSVMC.best_estimator_
(4)预测
features = ['Age_level', 'Sex','Family_memebers', 'Fare_level',  'Pclass', 'Embarked']

SVMC_best.fit(X,y)

out_text = SVMC_best.predict(df[len(train):][features])
text = pd.DataFrame(out_text.astype(int),index=df[len(train):]['PassengerId'].values).reset_index() 
text.rename(columns={"index":"PassengerId",0:"Survived"}).to_csv('predict_02.csv',index=False)

最后的结果:


image

笔者终于从倒数爬到了正数,不容易。
总体上来看,

  • Titanic的特征数量比较少,很容易入手
  • 后来我又用VotingClassifier进行集成,但结果居然没有单独的SVC表现更好,这可能与其强大随机性有关,具体的原因还可以再探究一下。
  • 就特征方面来说,name和ticket可能包含了同一家人的信息,笔者没有做具体分析,这块可以再继续深入。

原文代码:在这里

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,306评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,657评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,928评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,688评论 0 220
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,105评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,024评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,159评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,937评论 0 212
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,689评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,851评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,325评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,651评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,364评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,192评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,985评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,154评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,955评论 2 279

推荐阅读更多精彩内容