您的位置:首页 > 其它

KNN算法预测泰坦尼克号乘客生存率

2017-08-09 21:08 579 查看
完成某团队的考核任务所写下的博客,先放上具体任务要求:
1.读取titanic_data.csv文件
2.对数据进行预处理(分割数据集为训练集和测试集,缺少数据处理等)
3.选择模型(目前只要求用knn,算法自己实现)
4.调整模型参数,确定最终模型
5.预测生存率
先看一下数据集的情况:




可以看出,Name和PassengerID这一项是明显弱相关的,我把这两个删掉。接下来看Cabin这一项,这是船舱号的意思,粗略地浏览了一下这一项数据,发现数据缺损严重,虽然说船舱的分布对生存有一定的影响,但考虑到数据的大量缺损,我也把它删掉。接下来看到Ticket这一项,这是船票编号,显然对生存率的影响不大,我也把它删掉,然后就剩下这些了:




我们的数据项也就剩下:Pclass(阶级,1最高,3最低),Sex,Age,Sibsp(同船兄的姐妹数量), parch(是否有配偶、亲人同船),Fare(恐惧指数), Embarked(登船港口)以及Survived(0表示遇难,1表示幸存)。

接下来进行数据预处理,读取数据,本文的代码用了python中的pandas包来进行读取。我用了pandas.read_csv()函数,这里有一个很蛋疼的地方,就是unicode编码格式是不支持的,后来我转为ANSI编码格式后才解决了问题,这是代码:

import pandas as pd

data=pd.DataFrame(pd.read_csv('D:gg.csv')) #创建并读取数据表

print (data)


我打印出来看看,结果发现有一些数据是缺损的,这就要在后续步骤里进行处理。



然后对数据集进行一下describe,运行结果如下:



刚刚提到,在Age这一块有一定的空值,在这里我用其平均值来填充空值。在后来我又发现,Embarked这一列数据中有少许空值,我先分别用1、2、3来代替S、C、Q三个港口的名称,然后我决定用这一组数据的众数进行填充空值。显而易见众数为1,所以我用1取代了空值。

完成这些任务后,我用先直接用python中已经封
4000
装好的knn函数来进行预测。

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn import model_selection  #模型比较和选择包
from sklearn.metrics import classification_report  #将主要分类指标以文本输出
from sklearn.metrics import confusion_matrix #计算混淆矩阵,主要来评估分类的准确性
from sklearn.metrics import accuracy_score #计算精度得分
from sklearn.neighbors import KNeighborsClassifier #导入最近邻算法中的KNN最近邻分类包

data=pd.DataFrame(pd.read_csv('D:gg.csv')) #创建并读取数据表
#设置特征值和目标值
X = np.array(data[['Pclass', 'Sex', 'SibSp', 'Parch', 'Fare','Embarked']])
Y = np.array(data['Survived'])
#分割数据集
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.1, random_state = 0)
#测试机制:采用10倍交叉验证法。即通过把数据集分为10份,9份用于训练,1份用于验证,并重复训练分组的所有组合。
models = [] #建立列表
models.append(('KNN', KNeighborsClassifier()))
results = []
names = []
seed = 7
for name, model in models: #将算法名称与函数分别读取
kfold = model_selection.KFold(n_splits=10, random_state=seed) #建立10倍交叉验证
cv_results = model_selection.cross_val_score(model, X_train, Y_train, cv=kfold, scoring='accuracy')
results.append(cv_results)
names.append(name)
msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
print(msg)

# 对数据集进行预测
knn = KNeighborsClassifier(n_neighbors=20, weights= 'distance', algorithm='auto',
leaf_size=5, p=1, metric='minkowski', metric_params=None, n_jobs=-1)
knn.fit(X_train, Y_train) #knn拟合序列集
predictions = knn.predict(X_test) #预测验证集
print(accuracy_score(Y_test, predictions)) #验证集精度得分
print(confusion_matrix(Y_test, predictions)) #混淆矩阵
print(classification_report(Y_test, predictions)) #分类预测报告


运行结果如下:



结果,准确率低的惊人。。。这里面必定有弱相关特征造成了影响,或者我误删了某些强相关的特征。那么我先用一种简单粗暴的方法来解决里面是否有弱相关特征的影响,就是用启发式验证法。

我先删掉了Parch这一项,然后运行结果提高了一个点。。我同时又删掉Embarked这一项后,预测准确率只比原来提高了两个点;但我单独删掉Embarked这一项,预测准确率却比原来提高了三个点,所以我选择了保留Parch而删掉Embarked,其实考虑一下实际情况也有道理,如果你一家老小去乘船出事了,你肯定要顾及自己的家人而可能导致部分家庭成员失去了逃生的机会,死亡率也会提高;而独自一人的话,可能没有这方面因素会影响自己的逃生,幸存率也就上来了。

然后我接着删,但结果都不尽人意,反而还导致了下降,所以我回头看我是否删掉了某些重要的强相关的特征。我用pandas来进行数据分析。观察原始数据发现,cabin这一项数据存在一定量的缺损值,但并不可以就此否定其对结果的影响,所以我选择查看一下有Cabin信息和无Cabin信息的获救比例:

import pandas as pd
import matplotlib.pyplot as plt
data = pd.DataFrame(pd.read_csv('D:gg.csv')) #创建并读取数据表
plt.subplot2grid((1, 2), (0, 0))
plt.title('when Cabin exist')
data[data['Cabin'].notnull()]['Survived'].value_counts().plot(kind = 'bar')
plt.subplot2grid((1, 2), (0, 0))
plt.title('when Cabin does not exist')
data[data['Cabin'].isnull()]['Survived'].value_counts().plot(kind = 'bar')
plt.show()


结果如下:



可以看出,若有Cabin这一项获救的机率会大大增加。所以在之前我删掉的Cabin应该很有必要加进去并且实行一定的处理。在这里我简单的把有Cabin和无Cabin直接用0和1来替换。可惜准确率还是停留在76%的样子,也许KNN算法并不合适吧。。。



最后放上源码,这里我是直接调用sklearn里面已经封装好的函数。

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn import model_selection  #模型比较和选择包
from sklearn.metrics import accuracy_score #计算精度得分
from sklearn.neighbors import KNeighborsClassifier #导入最近邻算法中的KNN最近邻分类包

data = pd.DataFrame(pd.read_csv('D:gg.csv')) #创建并读取数据表
#设置特征值和目标值
X = np.array(data[['Pclass', 'Sex', 'SibSp', 'Parch', 'Fare', 'Cabin']])
Y = np.array(data['Survived'])
#分割数据集
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.1, random_state = 0)
#测试机制:采用10倍交叉验证法。即通过把数据集分为10份,9份用于训练,1份用于验证,并重复训练分组的所有组合。
models = [] #建立列表
models.append(('KNN', KNeighborsClassifier()))
results = []
names = []
seed = 7
for name, model in models: #将算法名称与函数分别读取
kfold = model_selection.KFold(n_splits=10, random_state=seed) #建立10倍交叉验证
cv_results = model_selection.cross_val_score(model, X_train, Y_train, cv=kfold, scoring='accuracy')
results.append(cv_results)
names.append(name)
msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
print(msg)

# 对数据集进行预测
knn = KNeighborsClassifier(n_neighbors=20, weights= 'distance', algorithm='auto',
leaf_size=5, p=1, metric='minkowski', metric_params=None, n_jobs=-1)
knn.fit(X_train, Y_train) #knn拟合序列集
predictions = knn.predict(X_test) #预测验证集
print(accuracy_score(Y_test, predictions)) #验证集精度得分
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: