Kaggle竞赛网址:https://www.kaggle.com/c/titanic
上一章:Kaggle竞赛——Titanic泰坦尼克之灾(保姆级基础版)

本次Kaggle泰坦尼克之灾分析过程大致分为:

第1步:了解数据(上一章)
第2步:分析数据之间的关系(上一章)
第3步:缺失项数据处理(上一章)
第4步:特征因子化(上一章)
第5步:处理特殊值或浮动较大的数值(上一章)
第6步:数据筛选(上一章)
第7步:数据建模(上一章)
第8步:测试集预处理(上一章)
第9步:结果预测(上一章)
第10步:模型优化(本章)
第11步:模型融合(本章)

好的,基于上一章的分析与讲解,我们大致的得到了一个简单baseline。那么我们下一步该怎么优化呢?

先思考一下:
1.如果不断地做特征工程,产生的特征越来越多,用这些特征去训练模型,会对我们的训练集拟合得越来越好,同时也可能逐步地丧失泛化能力,从而在测试集上表现不佳,也就是发生过拟合问题;
2.如果模型在测试集上表现不佳,除掉上面说的过拟合问题,也有可能是欠拟合问题,也就是说在训练集上,其实拟合的也不是那么好;
a. 对过拟合而言,通常以下策略对结果优化是有用的:做一下特征筛选,挑出较好的特征子集为训练提供更多的数据,从而弥补原始数据的bias问题,学习到的模型也会更准确;
b. 而对于欠拟合而言,通常需要更多的特征,更复杂的模型来提高模型的准确度。

第10步:逻辑回归优化
10.1 模型系数分析

# 模型系数关联分析
pd.DataFrame({"columns":list(train_df.columns)[1:], "coef":list(clf.coef_.T)}) # LR模型系数


从上表格可以看出:

  1. SibSp和Parch一定程度上呈现的是一个负相关,这个需要看看进一步验证;
  2. 有Cabin(客舱)值会很大程度拉升最后获救概率;(但事实上从最上面的有无Cabin记录的Survived分布图上看出,即使有Cabin记录的乘客也有一部分遇难了,估计这个属性上我们挖掘还不够。)
  3. 登船港口S会有一定程度拉低获救的概率,另外俩港口没啥作用;(但我们从之前的统计图上并没有看到S港口的获救率非常低,可以考虑把登船港口这个feature去掉试试)
  4. Sex属性,如果是female会极大提高最后获救的概率,而male会很大程度拉低这个概率;
  5. Pclass属性,头等舱乘客最后获救的概率会上升,而乘客等级为3会极大地拉低这个概率;
  6. Age是一个负相关,意味着在我们的模型里,年龄越小,越有获救的优先权;(需要看看原数据上是否合理)
  7. 船票Fare有小幅度的正相关。(并不意味着这个feature作用不大,有可能是细化的程度还不够)

10.2 交叉验证
把交叉验证里面的bad case拿出来,看看人眼审核是否能发现什么蛛丝马迹,是忽略了哪些信息,使得这些乘客被判定错了?再把bad case上得到的想法和前头系数分析的合在一起,然后逐个试试。

# 交叉验证
from sklearn.model_selection import cross_val_score, train_test_split# 简单看看打分情况
clf = linear_model.LogisticRegression(C=1.0, penalty='l1', tol=1e-6, solver='liblinear')
all_data = df.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
X = all_data.values[:,1:]
y = all_data.values[:,0]
cross_val_score = cross_val_score(clf, X, y, cv=5)
cross_val_score


10.3 特征挖掘

# 分割数据
split_train, split_cv = train_test_split(df, test_size=0.3, random_state=0)
train_df = split_train.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
# 生成模型
clf = linear_model.LogisticRegression(C=1.0, penalty='l1', tol=1e-6, solver='liblinear')
clf.fit(train_df.values[:,1:], train_df.values[:,0])# 对cross validation数据进行预测
cv_df = split_cv.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
predictions = clf.predict(cv_df.values[:,1:])
predictions
# split_cv[ predictions != cv_df.values[:,0]].drop()
# # 出现这个报错:ValueError: Need to specify at least one of 'labels', 'index' or 'columns'
# 去除预测错误的case看原始dataframe数据
# split_cv['PredictResult'] = predictions
origin_data_train = pd.read_csv("Train.csv")
bad_cases = origin_data_train.loc[origin_data_train['PassengerId'].isin(split_cv[predictions != cv_df.values[:,0]]['PassengerId'].values)]
bad_cases


对比bad case:仔细看看预测错的样本,到底是哪些特征有问题,还是处理得不够细?
列一些可能做的优化操作:

  1. Age属性不使用现在的拟合方式,而是根据名称中的Mr、Mrs、Miss等的平均值进行填充;
  2. Age不做成一个连续值属性,而是使用一个步长进行离散化,变成离散的类目特征;
  3. Cabin再细化一些,对于有记录的Cabin属性,将其分为前面的字母部分(可能是位置和船层之类的信息) 和后面的数字部分(可能是房间号); Pclass和Sex俩太重要了,我们试着用它们去组出一个组合属性来试试,这也是另外一种程度的细化;
  4. 单加一个Child字段,Age<=12的,设为1,其余为0(看看这一类的乘客优先度如何) ;
  5. 如果名字里面有Mrs,而Parch>1的,我们猜测她可能是一个母亲,应该获救的概率也会提高,因此可以多加一个Mother字段,此种情况下设为1,其余情况下设为0;
  6. 登船港口可以考虑先去掉试试(Q和C本来就没权重,S有点诡异) ;
  7. 把堂兄弟/兄妹 和 Parch 还有自己个数加在一起组一个Family_size字段(考虑到大家族可能对最后的结果有影响)Name是一直没有触碰的属性,可以做一些简单的处理,比如说男性中带某些字眼的(‘Capt’,‘Don’, ‘Major’, ‘Sir’)可以统一到一个Title,女性也一样。
data_train[data_train['Name'].str.contains("Major")]

# 继续特征挖掘
data_train = pd.read_csv("Train.csv")
data_train['Sex_Pclass'] = data_train.Sex + "_" + data_train.Pclass.map(str) # 性别_乘客等级合并
data_train


10.4 补全缺失值

from sklearn.ensemble import RandomForestRegressor# 使用 RandomForestClassifier 填补缺失的年龄属性
def set_missing_ages(df):# 把已有的数值型特征取出来丢进Random Forest Regressor中age_df = df[['Age','Fare', 'Parch', 'SibSp', 'Pclass']]# 乘客分成已知年龄和未知年龄两部分known_age = age_df[age_df.Age.notnull()].valuesunknown_age = age_df[age_df.Age.isnull()].values# y即目标年龄y = known_age[:, 0]# X即特征属性值X = known_age[:, 1:]# fit到RandomForestRegressor之中rfr = RandomForestRegressor(random_state=0, n_estimators=2000, n_jobs=-1)rfr.fit(X, y)# 用得到的模型进行未知年龄结果预测predictedAges = rfr.predict(unknown_age[:, 1::])# 用得到的预测结果填补原缺失数据df.loc[ (df.Age.isnull()), 'Age' ] = predictedAges return df, rfrdef set_Cabin_type(df):df.loc[ (df.Cabin.notnull()), 'Cabin' ] = "Yes"df.loc[ (df.Cabin.isnull()), 'Cabin' ] = "No"return df

10.5 特征因子化

data_train, rfr = set_missing_ages(data_train)
data_train = set_Cabin_type(data_train)
# 向量化
dummies_Cabin = pd.get_dummies(data_train['Cabin'], prefix= 'Cabin')
dummies_Embarked = pd.get_dummies(data_train['Embarked'], prefix= 'Embarked')
dummies_Sex = pd.get_dummies(data_train['Sex'], prefix= 'Sex')
dummies_Pclass = pd.get_dummies(data_train['Pclass'], prefix= 'Pclass')
dummies_Sex_Pclass = pd.get_dummies(data_train['Sex_Pclass'], prefix= 'Sex_Pclass')df = pd.concat([data_train, dummies_Cabin, dummies_Embarked, dummies_Sex, dummies_Pclass, dummies_Sex_Pclass], axis=1)
df.drop(['Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked', 'Sex_Pclass'], axis=1, inplace=True)
df


10.6 处理浮动较大的数值

# 处理数据集中浮动较大的数值到(-1,1)之间
import sklearn.preprocessing as preprocessing
scaler = preprocessing.StandardScaler()# fit的数据需要以2维([[]])的形式传入
age_scale_param = scaler.fit(df[['Age']])
# 将fit的数据处理后的结果以np.array的形式返回
df['Age_scaled'] = scaler.fit_transform(df[['Age']], age_scale_param)
fare_scale_param = scaler.fit(df[['Fare']])
df['Fare_scaled'] = scaler.fit_transform(df[['Fare']], fare_scale_param)
df


10.7 筛选数据

# 筛选数据(结果+特征)
# 利用正则表达式
train_df = df.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass.*')
train_np = train_df.values

10.8 数据建模

# y即Survival结果
y = train_np[:, 0]
# X即特征属性值
X = train_np[:, 1:]from sklearn import linear_model
# fit到RandomForestRegressor之中
clf = linear_model.LogisticRegression(C=1.0, penalty='l1', tol=1e-6, solver='liblinear')
clf.fit(X, y)
clf


10.9 测试集预处理

# 测试集预处理
data_test = pd.read_csv("test.csv")# 缺失值处理
data_test.loc[ (data_test.Fare.isnull()), 'Fare' ] = 0
data_test['Sex_Pclass'] = data_test.Sex + "_" + data_test.Pclass.map(str)# 对test_data做和train_data中一致的特征变换
# 用同样的RandomForestRegressor模型填上丢失的年龄
tmp_df = data_test[['Age','Fare', 'Parch', 'SibSp', 'Pclass']]
null_age = tmp_df[data_test.Age.isnull()].values# 根据特征属性X预测年龄并补上
X = null_age[:, 1:]
predictedAges = rfr.predict(X)
data_test.loc[ (data_test.Age.isnull()), 'Age' ] = predictedAges# 向量化
data_test = set_Cabin_type(data_test)
dummies_Cabin = pd.get_dummies(data_test['Cabin'], prefix= 'Cabin')
dummies_Embarked = pd.get_dummies(data_test['Embarked'], prefix= 'Embarked')
dummies_Sex = pd.get_dummies(data_test['Sex'], prefix= 'Sex')
dummies_Pclass = pd.get_dummies(data_test['Pclass'], prefix= 'Pclass')
dummies_Sex_Pclass = pd.get_dummies(data_test['Sex_Pclass'], prefix= 'Sex_Pclass')# 合成新的数据集
df_test = pd.concat([data_test, dummies_Cabin, dummies_Embarked, dummies_Sex, dummies_Pclass, dummies_Sex_Pclass], axis=1)
df_test.drop(['Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked', 'Sex_Pclass'], axis=1, inplace=True)# 处理浮动值大的数据
df_test['Age_scaled'] = scaler.fit_transform(df_test[['Age']], age_scale_param)
df_test['Fare_scaled'] = scaler.fit_transform(df_test[['Fare']], fare_scale_param)
df_test


10.10 结果预测

# 筛选数据(特征)
test = df_test.filter(regex='Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass.*')
predictions = clf.predict(test)
result = pd.DataFrame({'PassengerId':data_test['PassengerId'].values, 'Survived':predictions.astype(np.int32)})
result.to_csv("result_2.csv", index=False)

第11步:模型融合
模型融合可以比较好地缓解训练过程中产生的过拟合问题,从而对于结果的准确度提升有一定的帮助。

思路
由于我这里只用了logistic regression,所以只能从数据上入手了,每次训练的时候不用全部训练集,而是每次取训练集的子集做训练。这样一来,虽然用的是同一个机器学习算法,但是得到的模型却是不一样的;
同时,因为没有任何一份子集是全的,因此即使出现过拟合,也是在子训练集上出现过拟合,而不是全体数据上,这样做一个融合,可能对最后的结果有一定的帮助(常用的是scikit-learn里面的Bagging)。

# 导入sklearn中的BaggingRegressor
from sklearn.ensemble import BaggingRegressor# 正则表达式处理
train_df = df.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass.*|Mother|Child|Family|Title')
train_np = train_df.values# y即Survival结果
y = train_np[:, 0]
# X即特征属性值
X = train_np[:, 1:]# fit到BaggingRegressor之中
clf = linear_model.LogisticRegression(C=1.0, penalty='l1', tol=1e-6, solver='liblinear')
# 根据需要进行调参
bagging_clf = BaggingRegressor(clf, n_estimators=20, max_samples=0.8, max_features=1.0, bootstrap=True, bootstrap_features=False, n_jobs=-1)
bagging_clf.fit(X, y)test = df_test.filter(regex='Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass.*|Mother|Child|Family|Title')
predictions = bagging_clf.predict(test)
result = pd.DataFrame({'PassengerId':data_test['PassengerId'].values, 'Survived':predictions.astype(np.int32)})
result.to_csv("result_bagging2.csv", index=False)

至此,我们通过了对特征进行简单加工处理,使用了scikit-learn里面的Bagging进行模型融合之后,我们的分数有上升了一个档次啦~ 然后把预测的结果上传到kaggle上,看看你们的分数上涨了多少!!!
我的分数是从0.76315(10861名)到0.79186(1051名)的提升,总参赛人数14251人,后续的分数排名上可能还会往上冲一冲,一起加油把!

当然,本次也仅仅是针对个别特征、个别算法做的优化工作。其实像模型融合,还有很多比较常见常用的手段。比如:简单加权融合回归,stacking/blending ,还有boosting,这个大家后面可以自己了解了解,多尝试尝试。

Kaggle竞赛——Titanic泰坦尼克之灾(0.76315==>0.79186)相关推荐

  1. Kaggle竞赛——Titanic泰坦尼克之灾(保姆级基础版)

    Kaggle竞赛网址:https://www.kaggle.com/c/titanic 本次Kaggle泰坦尼克之灾分析过程大致分为: 第1步:了解数据 第2步:分析数据之间的关系 第3步:缺失项数据 ...

  2. 小白的机器学习之路(1)---Kaggle竞赛:泰坦尼克之灾(Titanic Machine Learning from Disaster)

    我是目录 前言 数据导入 可视化分析 Pclass Sex Age SibSp Parch Fare Cabin Embarked 特征提取 Title Family Size Companion A ...

  3. kaggle竞赛:泰坦尼克幸存者预测

    kaggle竞赛:泰坦尼克幸存者预测--(一) import pandas as pd import numpy as np import matplotlib.pyplot as plt impor ...

  4. kaggle入门泰坦尼克之灾内容总结

    [泰坦尼克之灾](https://www.kaggle.com/c/titanic):求生问题预测,是一个二分类问题,判断每名乘客的存活情况,读了寒小阳大牛的博客,现做以下整理.阳哥只介绍了逻辑回归算 ...

  5. Kaggle滑水 - 泰坦尼克之灾(决策树)

    本文以Kaggle新手习题--Titanic: Machine Learning from Disaster为场景开展实验,以此熟悉Kaggle平台. 本文的源码托管于我的Github:Practic ...

  6. Titanic 泰坦尼克数据集 特征工程 机器学习建模

    以下内容为讲课时使用到的泰坦尼克数据集分析.建模过程,整体比较完整,分享出来,希望能帮助大家.部分内容由于版本问题,可能无法顺利运行. Table of Contents 1  经典又有趣的Titan ...

  7. Kaggle案例之泰坦尼克船员幸存预测(sklearn机器学习库)

    无意间在网易云课堂上找了一个Kaggle案例,泰坦尼克获救船员预测,在此之前我是从没接触过kaggle,毕竟是刚入门的小白,看着视频,算是真正实战了一次,主要是在这个过程中学到了很多东西. 下面视频地 ...

  8. kaggle入门之泰坦尼克幸存预测

    kaggle入门之泰坦尼克幸存预测 # 数据集什么的就不介绍了,官网上都有 主要的工作步骤 1.提出和定义问题 2.获取训练和测试数据 3.获取,准备和清洗数据 4.分析,识别,探究数据 5.建模,预 ...

  9. Kaggle案例之泰坦尼克船员幸存预测

    无意间在网易云课堂上找了一个Kaggle案例,泰坦尼克获救船员预测,在此之前我是从没接触过kaggle,毕竟是刚入门的小白,看着视频,算是真正实战了一次,主要是在这个过程中学到了很多东西.  下面视频 ...

最新文章

  1. 富文本编辑器Quill(二)上传图片与视频
  2. python2.7+pyqt4实现记事本基本功能
  3. delphi mysql dll直接_十万火急!!!那位高手用过libmysql.dll直接连接MySql数据库?如何将二进制文件保存到blob字段中? (60分)...
  4. 如何获取元素与当前可视区域顶部的距离
  5. 整数规划matlab实例,整数规划matlab
  6. 上交大博导:写给不想做学术的你
  7. javascript Blob
  8. Android 内部存储安装apk文件实现
  9. 基本music matlab,求利用MUSIC算法进行DOA估计的Matlab源程序
  10. H5手机端JS实现微博分享实例详解
  11. 体育教学硕士毕业论文题目
  12. linux系统安装步骤
  13. 忘记网站后台密码 PHP+mysql+md5 破解
  14. predict函数 R_第四十讲 R-线性回归:预测模型及可信区间
  15. 前端自检梳理——Vue.js项目实战开发
  16. 7-20 打印九九口诀表 (15 分) 下面是一个完整的下三角九九口诀表:
  17. 普中51秒表简单易懂
  18. HDU 6194 string string string :后缀数组+单调队列 | 后缀自动机
  19. MySQL||主键(primary key)及主键约束
  20. linux不能显示文本文件内容的命令,Linux之文本文件查看命令

热门文章

  1. POS单上的商户编号解释
  2. #今日论文推荐#CVPR 2022 | 只需要一组预训练参数,所有恶劣天气一次解决
  3. Redis实战demo
  4. android教程丿it教程网,[IT教程吧-www.itjc8.com]_Da类android视频
  5. android上传sd卡文件格式,Android开发学习:向模拟器的sdcard中添加文件
  6. thinkpad E430 电源连接未充电的问题解决方法
  7. 云计算技术的产生、思想、原理、应用和前景
  8. 华硕服务器怎么装win7系统教程视频,华硕电脑离线重装win7系统详细教程
  9. 网络安全工程师的职业前景如何?
  10. 信息安全技术——(三)标识与认证技术