泰坦尼克号幸存者预测


版权声明

本文首发于微信公众号

沁机迈可思(zw_life-long_doing)

无需授权即可转载

转载时请注明出处

有这么一家银行,他家的信用卡非常受人欢迎。我们假设这家银行批准某种信用卡申请,记作“1”;而它拒绝某种信用卡的申请,则记为“0”。某天,你想要去这家银行申请信用卡,能知道银行将批准你使用某种信用卡的概率吗?

当然可以。最简单的方法就是使用逻辑回归算法。

看到算法两个字,大多数人会觉得头大,因为不懂嘛。但简单的讲,我们常说的算法,就是套路。即用这个套路来解决实际问题。

那逻辑回归算法解决什么问题呢?

我们假设有一组数据,它服从伯努利分布(也称0-1分布)。那么逻辑回归算法则通过极大化似然函数的方法,运用梯度下降来求解参数,达到将数据二分的目的。

所以说,虽然逻辑回归带有“回归”两个字,但它最终解决的是二分类问题。即判断某数据更大概率是属于A结果,还是B结果。

这里解释两个概念:

回归:指研究一组变量(y1, y2, ……, yi)和另一组变量(x1, x2, ……, xi)之间关系的一个统计分析方法。

最大似然函数:在统计学中,用来估计一个概率模型参数的一种方法。可以利用已知的样本结果,反推最大概率导致这个结果的参数值。

梯度下降法:它是一个一阶最优算法,目的是为了找到一个函数的极小值。梯度方向表示了函数增长速度最快的方向,当我们需要求解函数极小值的时候,以函数上一点为起点,朝着梯度的相反方向迭代搜索,就能求解该函数的极小值。

那么,我们知道了逻辑回归的含义和作用,但是要怎么使用呢?本文就用逻辑回归算法,来预测一下泰坦尼克号海难中,哪一类的乘客更容易生存下来。

首先,在kaggle平台上下载好我们需要的数据,并用python加载。

importpandasaspd

frompandasimportSeries,DataFrame

# 自己的文件路径

train=pd.read_csv('/Users/weizhong/Desktop/Titanic_train.csv')

test=pd.read_csv('/Users/weizhong/Desktop/Titanic_test.csv')

# 看看数据表的基本信息

print('训练数据信息:',train.shape,'预测数据信息:',test.shape)

数据集,是我们用来训练模型用的数据,有891行,12列数据,数据集是我们最后用模型来预测的数据,有418行,11列数据,对比训练数据集少了这列内容。因为这一列是我们要预测的结果嘛。

虽然是两个数据集,但是二者的差别并不大。因此,我们仍然可以将两个数据集合并来进行数据处理。

full=train.append(test,ignore_index=True)

print('合并后的数据:',full.shape)

full.head()

然后我们用语句看看数据的基本情况。

通过这个描述信息,我们发现该数据集是有缺失数据的。因此,我们可以使用语句来进一步查看该数据集的基本情况。

不难发现,在、、、这四列的数据是有不同程度缺失的。因此,我们先进行缺失值的处理。一般情况下,我们处理缺失值有三种方法:

数值型数据,用均值填充;

分类数据,用最常见的类别填充;

使用模型预测预测缺失值,如K-NN模型。

这里我们就简单粗暴一点,用前两种方法。

# 数值型数据的缺失值填充

full['Age']=full['Age'].fillna(full['Age'].mean())

full['Fare']=full['Fare'].fillna(full['Fare'].mean())

# 字符串类型数据填充

full['Cabin']=full['Cabin'].fillna('U')# U=unkown

full['Embarked']=full['Embarked'].fillna('S')

缺失值填充好了,接下来就是对现有的数据标签进行特征工程操作了。为什么需要有这么一步?国外一位大牛这么形容特征工程:

Feature Engineering is manually designing what the input x’s should be.

为什么在数据处理中,“特征工程”会如此的重要呢?我们都知道,机器学习算法的最终目的,是为了预测未知数据。先不说算法的好坏会影响最终结果,数据的好坏也会影响到最终结果。

因此,特征工程的作用就是从原始数据最大限度的提取出我们需要的数据,供模型与算法使用。但你也知道,我们在处理数据的时候,字符串类型是不方便我们进一步处理的,因为我们在选取特征之前,需要对数据集进行几个基本操作:

数值型:直接使用;

时间序列:转成单独年、月、日;

分类数据:用数值代替类别。使用one-hot编码。

我们将数据集中的数据简单分个类。

发现我们有5项分类数据需要进行数值化处理(船票编号因为没有实际意义,所以不做处理)。但是因为在处理两类以上数据的时候,会更加高效。因此在性别这一栏,我们就直接用赋值法修改。

sex_dict={'male':1,'female':}

# 用map函数批量对一维数组中的每个数据应用某规则

full['Sex']=full['Sex'].map(sex_dict)

在剩下的5项中,、因为是重复的进行编码,因此这里就仅仅以Embarked的编码代码为例。

# 登船港口

embarked_df=DataFrame()

embarked_df=pd.get_dummies(full['Embarked'],prefix='Embarked')

# 将数据添加到原数据集中

full=pd.concat([full,embarked_df],axis=1)

# 删除新表中“Embarked”这一列

full=full.drop('Embarked',axis=1,inplase=True)

效果图如下。

再来说说Cabin这一列的编码。从数据表中,我们可以看到,这一列的数据多是“一个字母+数字”的形式。由于我们需要的是哪一类的客舱号,而不是具体的数字,所以,这里我们仅仅是需要客舱号的首字母,知道该客舱是属于哪一类客舱即可。因此,在上面的代码基础上,我们需要先对这一列的数据进行批量的提取之后,再进行编码。(编码步骤一样,因此这里就只是展示提取的代码)

# 运用lambda语句构建一个简易的自定义函数

full['Cabin']=full['Cabin'].map(lambdax:x[])

比较困难一点的是姓名这一列。

或许说你叫什么名字,对最后的预测帮助不大。但是你的头衔就说不准啦。通过上图,可以看出,在每一个名字的中间,会有这个人的头衔称谓。通过这个头衔,不仅可以知道他们的性别,而且可以知道他们的地位阶级。因此,先用函数将头衔分离出来。

defname_title(f):str1=f.split(',')[1]str2=str1.split('.')[]# strip()函数主要移除字符串头尾指定字符,默认是空格str3=str2.strip()returnstr3

title_df=DataFrame()

name_ser=full['Name']

title_df=name_ser.map(name_title)

但是,1300多行数据,我们不能说只有“Mr”和“Mrs”这两类头衔,因此我们先用语句将数据去重看看。这里要注意,一定不要在原代码中操作,重新复制一个变量查看,避免内容错乱。

我的乖乖,总共有18个头衔。但是因为泰坦尼克号在三个不同国家的港口停靠(分别是英国的南安普顿、法国的瑟堡和爱尔兰的昆士敦),所以不排除这些头衔里面有重复的情况。因此,我们按照网上划分,先将这些头衔分成Officer(政府官员)、Royalty(王室/皇室)、Mr(男士)、Mrs(已婚女士)、Miss(未婚女士)、Master(有技能的人)这六大类,再进行编码。

到此,分类数据倒是被我们处理完了。但是家庭情况,我们仍是需要汇总归类处理一下。虽说原表中已有和两列数据,但是他们只是记录一个家庭的人数,并没有表现出这个家庭的大小。因此,我们这里讲它进行汇总分类处理。

family_df=DataFrame()

# 家庭总人数需要加上自己

family_df['Family_size']=full['SlibSp']+full['Parch']+1

# 对家庭大小进行条件判断

family_df['Family_small']=family_df['Family_df'].map(lambdaa:1ifa==1else)

family_df['Fmaily_middle']=family_df['Family_df'].map(lambdaa:1ifa>=2anda

family_df['Family_large']=family_df['Family_df'].map(lambdaa:1ifa>5else)

# 将家庭总数表和类别表添加进原表

full=pd.concat([full,family_df],axis=1)

现在,所有的数据处理完了,我们看看这个数据集的相关系数。

或许你会说,这里有太多列了,不如画热力图来的直观一些。但是你可别忘记了,我们需要预测的是幸存者。因此,我们需要的是Survived这列的相关系数信息。

从这列结果来看,相关系数最高的,是已婚女士和未婚女士,最低的果然是男士。看来当时的绅士礼仪,真是深入到了各个阶层……好了,不扯远了,既然我们知道了与最终幸存呈现正相关的特征是哪些,那么我们接下来要做的就是选取要训练的特征了。这里我们重新赋值一个变量。

但是因为我们在清洗数据的时候,是讲测试集合预测集合并在一起进行清洗的,因此我们最后需要拆分出训练数据集和预测数据集。

最后,就是关键的训练模型了。

# 拆分训练数据

fromsklearn.model_selectionimporttrain_test_split

# 拆分成80%的训练集合20%的测试集

train_X,test_X,train_y.test_y=train_test_split(source_X,source_y,train_size=.8)

# 用训练集来训练数据

fromsklearn.linear_modelimportLogisticRegression

model=LogisticRegression()model.fit(train_X,train_y)

# 用测试数据来评估模型

model.score(test_X,test_y)

训练了模型之后,我们用分离出来的测试数据和来评估一个模型的准确率。

这里需要说明一点的是,因为我们训练的数据太小,所以每次重新运行代码的时候,这里的正确率的波动会比较大。

训练好了模型之后,就是运用模型了。但是因为在kaggle中提交预测结果要求的是整形,因此我们还需要将数据类型转换为类型,并输出“.csv”格式的文件。

pred_y=model.predict(pred_X)

# 将数据类型转换成整形,并匹配对应的乘客编号

pred_y=pred_y.astype(int)

passengerId=full.loc[source_row:,'PassengerId']

# 汇总成一个数据集

pred_df=DataFrame({'PassengerId':passengerId,'Survived':pred_y})

pred_df.to_csv('Titanic_pred.csv',index=False)

当我解决玩一个项目,满怀欣喜的将结果上传至kaggle之后,看着自己的排名仅仅才top49%,排名5000多名去了,有点惨不忍睹。黯然神伤……

经过了这次项目,小小的总结一下:

从整个项目来看,数据清洗几乎占据了整个项目60%的工作量。而且这里面的“特征工程”又是极为重要的一环。因此,鉴于编码能对分类数据进行数值化处理,共模型使用,需要熟练运用。

数据特征的选取质量,直接影响这最后模型的预测准确度。

在数据总量既定的情况下,用多个模型进行预测,最后再选出最合适的模型是不错的选择。我相信下次再做这个项目,就不仅仅是top49%这么简单了。

我叫钟小韦,爱折腾的天府小生,期待与你一同成长。


优质内容筛选与推荐>>
1、SqlServer清除日志并收缩数据库
2、SQL数据库
3、如何演示你的App?Android录制Gif动态图教程
4、linux本地文件上传之RZ/SZ和sftp
5、Buffalo WZR-HP-AG300H 刷 OpenWRT 固件(2014.07.03版本)

长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号