多算法不调包实现Titanic生还者分类预测

多算法不调包实现Titanic生还者分类预测

博主本科的机器学习课程作业,要求不使用机器学习包实现分类算法

数据集

数据集概况

本次选择的数据集是Titanic数据集,来自于Kaggle,可以在kaggle比赛的官网上下载到:Titanic - Machine Learning from Disaster | Kaggle

在这里插入图片描述

下载到的数据集解压后包括两个csv文件,train.csv和test.csv。train.csv是训练集,共12列,依次代表乘客的编号passengerID,船舱等级Pclass,姓名name,性别sex,年龄age,在船上有几个兄弟/配偶sibsp,在船上有几个双亲/孩子parch,船票号tickets,费用fare,船舱号cabin,登船地点embarked,是否存活survived。训练集test.csv相比较train,csv少了幸存这一项,查阅另一款数据集后找到了测试集的真实标签,将测试集的标签列补全,方便我们后面进行预测效果的比较。

关于数据集里的属性还需要作以下的说明:

pclass:社会经济地位代号(SES)1st = 上,2nd = 中,3rd = 下

age:如果年龄小于1,则年龄为分数。

sibsp:数据集以这种方式定义了家庭关系

embarked的字母表示的是登船的地点,以城市的首字母代替。

部分数据有缺失,全部以空的形式表示。
在这里插入图片描述

特征工程

整个数据预处理阶段需要将合适的属性保留,并将里面的非数值化的数据用数据去表示。将tarin.csv和test.csv用dataframe导入。
先看看数据集的描述:
在这里插入图片描述
首先先设置乘客的编号作为索引。
train_data = train_data.set_index(“PassengerId”)
test_data = test_data.set_index(“PassengerId”)
接下来要对缺失值做处理:
先输出一下看看那些属性是有缺失的
在这里插入图片描述
发现年龄Age船舱 Cabin Embarked是有缺失的,船舱属性缺失太严重,直接drop,age 可以用平均值代替一下,name ticket不好数值化,drop掉
考虑到年龄其实是和船舱等级有很大的关系的,一般来说年龄越大的话,资本累积应该越高,社会地位应该也越高,更有能力负担起高等级的船舱。如果将所有的人的平均年龄作为缺失值的补充显然是不科学的,因此看看年龄和船舱等级这两个属性的关联程度:
在这里插入图片描述
可以明显地看到船舱等级越高的话,年龄也越大,证明之前的猜测是正确的,因此我们应该将不同船舱的人分别计算平均年龄,然后分别设置给对应船舱年龄缺失的人。
还有要注意的是,性别属性,登船地点属性都是字符类型的,对于我们数据来说是不能够训练的,因此我们将其数值化,总的来说数据处理如下:
在这里插入图片描述
Embarked属性不好数值化,因此这里将不同的类别分别拿出来作为二值化的属性。

数据处理大概差不多了,效果大概是这样的:
在这里插入图片描述
数据处理的最后一步,划分训练集和测试集,因为数据集已经被划分好了,就将传入dataframe:

X_train=train_data.drop('Survived',axis=1)
Y_train=train_data['Survived']
X_test=test_data.drop('Survived',axis=1)
Y_test=test_data['Survived']

朴素贝叶斯算法实现

实现步骤

为了能让一个数据集为多个算法使用,还是决定将要实现的算法写在不同的cell里面,每个cell包含几个函数,对于朴素贝叶斯算法,一个函数足矣。函数包括两个参数,分别是测试集,训练集。最后的输出是六项,分别是处理过后的测试集,准确率,TP,TN,FP,FN。
整个高斯贝叶斯分类器函数分为三个部分:
第一步,计算每个标签类别的均值和方差,将计算出的均值和方差转化为df格式,方便后面使用。
第二步,计算未知样本取值不同标签类别的概率,然后预测其标签,原理已经介绍过,就是算出每个测试样本在各个属性的概率,然后相乘,最后选一个概率高的作为该样本的预测类别,将预测结果放进数组里,然后加到测试集中。
第三步,计算模型准确率,混淆矩阵,读取预测列的内容,计算出predict和survived是否相同作为准确率score的标准,每次比较时动态的=改变TP,TN,FP,FN的值。最后输出所有的结果。
在这里插入图片描述

实现效果

先将输出的测试集调出来看看:
在这里插入图片描述
可以看到最后一列成功添加了一列作为预测,从前五列来看正确预测了三个,错误了两个,貌似准确率不是很好。
输出准确率和TP,TN,FP,FN的值:
在这里插入图片描述
准确率是79.14%,比想象中要好一点。正确预测的样本还是挺多的。
因为这是二分类问题,混淆矩阵比较简单,就自己实现:
在这里插入图片描述

逻辑梯度下降算法实现

BGD,SGD实现过程

(1)首先因为是分类算法,我们要设置一个sigmoid函数,让最后输出的值代入函数中得到类别。也可以选择其他的判别函数,为了简单我这次选择的是sigmoid函数。
(2)要归一化,从数据集可以看到,数据并不归一,因此要定义归一化的函数,所以计算每一个属性的均值,方差,进行标准化操作:

def regularize(xMat):
    inMat = xMat.copy()
    inMeans = np.mean(inMat,axis = 0) # 均值
    inVar = np.std(inMat,axis = 0)  # 方差
    inMat = (inMat - inMeans)/inVar # 标准化
    return inMat

(3)定义计算权重的函数,这里我选择了两种梯度下降算法,BGD,SGD算法。两种计算梯度的算法大同小异,只是计算梯度的过程中是有一点差别:
在这里插入图片描述
学习率设置的是0.001.实践证明设置的小一点是有利的,最大迭代次数设置的是500,关于参数比较可以参考后面结果的展示。
(4)建立主函数,可以选择哪一种梯度下降方式,输出准确率和TP,TN,FP,FN的值。

实现效果

因为采用的是notebook编程环境,先要把之前加在test_data的预测列的数据全部drop掉,不然会影响之后准确率的计算。
#先把之前导入的predict列drop掉

test_data.drop('predict',axis=1,inplace=True)

首先用BGD的方式试一试:
在这里插入图片描述
准确率达到了81.8%,相比较略有提升。混淆矩阵如下所示:
在这里插入图片描述
再用随机梯度下降的方法试一试:
在这里插入图片描述
准确度是79.1%,比BGD的要低一些。混淆矩阵如下:
在这里插入图片描述
逻辑梯度下降算法比较容易用ROC曲线展现效果,这里我用自己写的roc曲线的函数drawroc,我将阈值的间隔设置为0.01,从0-1,也就是说应该有100个点在roc曲线上
带入BGD得到的ROC曲线如下:
在这里插入图片描述
带入SGD得到的ROC曲线如下:
在这里插入图片描述

KNN算法

实现过程

(1)首先要对于数据进行标准化,所用的函数和上面逻辑梯度下降的函数是一样的。就不再赘述。
(2)定义距离函数,就是定义样本和训练集的差异的。为了便于处理,将数据集和测试集都定义成矩阵的形式,进行矩阵的运算加和:
在这里插入图片描述
(3)最后定义分类函数,将预测列加到测试集的最后一列

实现效果

令k = 5先测试一下:
准确率:0.7218225419664268
混淆矩阵:
在这里插入图片描述
经过比较,传统的逻辑梯度下降和朴素贝叶斯方法对于泰坦尼克数据集有比较好的效果,而对于KNN算法,效果就相较前面两种算法比较逊色。
当然这是基于经典的二分类算法,而且数据集呢也有一些不足的地方,首先来说虽然有8列数据属性用作了分类,但其实真正对于分类有效的还是比较少的,年龄、船舱等级等属性甚至相关性比较大,能达到80%的准确度水平也不容易了。
实验过程中涉及了一些参数调整的过程,比如调整学习率,最大迭代次数,KNN算法中的K值等

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值