kaggle项目之Titanic数据集

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

  • 机器学习流程的回顾
  • Titanic数据集的分析和处理
    kaggle项目之Titanic数据集_第1张图片
    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:


kaggle项目之Titanic数据集_第2张图片
头几行数据

kaggle项目之Titanic数据集_第3张图片
数据类型与空值状况

kaggle项目之Titanic数据集_第4张图片
数据分布的整体状况

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

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

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

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

a. 整体的生存状况


kaggle项目之Titanic数据集_第5张图片
image

b. SeX


kaggle项目之Titanic数据集_第6张图片
image

c. Pclass
kaggle项目之Titanic数据集_第7张图片
image

kaggle项目之Titanic数据集_第8张图片
image

d. Embarked


kaggle项目之Titanic数据集_第9张图片
image

e. Age
kaggle项目之Titanic数据集_第10张图片
image

f. Fare
kaggle项目之Titanic数据集_第11张图片
image

g. Parch
kaggle项目之Titanic数据集_第12张图片
image

h. SibSp
kaggle项目之Titanic数据集_第13张图片
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");
kaggle项目之Titanic数据集_第14张图片
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具有出色的表现。


kaggle项目之Titanic数据集_第15张图片
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)

最后的结果:


kaggle项目之Titanic数据集_第16张图片
image

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

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

原文代码:在这里

你可能感兴趣的:(kaggle项目之Titanic数据集)