任务8,泰坦尼克号

按老师给的代码第一次提交得分

 

 

下面进行改进

 

一,       首先进行数据的清洗

先观察数据,首选'Pclass','Sex','Age'作为是否生还(Survived)的 考虑条件来建模

“Sex”的数值是字符型,于是用特征编码将性别用0,1表示

随后发现”Age”中有缺少值,由于age是数值量,可以直接使用,那么在”Age”的缺失值处理中,可以采用的是删除法,和填补法。

(一,   删除法)

 由于缺失值超过原数据的10%,所以不考虑用删除法

(二,   填补法)

(1)     用0填补

(因为该属性是年龄,用0填补可能误差比较大)

老师给的代码中就是用0填补

得分为0.69856

(2)     用平均值填补

将Age的缺失值由0改为该列的平均值后得分为0.70813

(默认K=5)

(3)    用中位数填补

将Age的缺失值由0改为该列的中位数后得分为0.60765

(默认K=5)

 

说明在本题中使用平均值比用0和中位数更好,于是在下面的尝试中都是采用Age缺少值填补为平均值的方法

 

 

二,训练KNN模型,以及用KNN模型做预测

 在继续改进的时候想到,会不会KNN的K值对结果有影响。

(KNN的K值默认是5,得分为0.70813)

通过K折交叉验证来选择KNN模型中的K值

——查了资料发现,K折交叉验证的K的取值没有一定的要求,现在较流行的是十折交叉验证和留一法。

(1)  5折交叉验证后best_k值为1,把K值改为1后,发现得分比K值为5小

(2) 留一法后,得到best_k为13

结果更低了,再试十折交叉验证

(3) 十折验证法后得到best_k=7

虽然比留一法的高,但是没有当K等于5时高,为什么K折交叉验证法不能找出最优的K值呢?

 

在搜索其他博客时发现有人用KNN算法时K取3,于是我又在上述的基础上把K改为3,分数更高了

 

三,添加特征

(一) 添加'Embarked'上船城市

考虑到上船城市不同可能会影响结果,于是加入该特征

由于只有两个缺失值,于是直接把缺失值赋为“S”

 

下面是我把'Embarked'的值S,C,Q直接用0,1,2(标签编码)代替时得到的结果

但是因为0,1,2之间有大小之分,但是我认为这三个城市更适合用独热编码(向量)来表示

于是得到下面的结果

很神奇,用标签编码得到的分数要比独热编码高,但是我还是想不出为什么,直到我看到了一篇博客,里面说道

 “S口岸,登船人数644,女性乘客占比46%;C口岸,登船人数168,女性占比接近77%;Q口岸,登船人数77,女性占比接近88%。前面已知女性生存率明显高于男性生存率,所以上述问题可能由性别因素引起。”

 因为女性的存活率会比女性的高,所以用0,1,2分别表示S,C,Q确实是有大小的区别,但很有可能不是因为城市,而是因为该城市上船的女性比例较高,这只是我的一个想法,可能有其他我没想到的原因。

 

 (二)添加堂兄弟和堂兄妹个数(SibSp)、父母和孩子的个数(Parch)

(1) 添加堂兄弟和堂兄妹个数(SibSp)、父母和孩子的个数(Parch),并且删除'embarked‘

得分:0.69856

得分比原来不添加还低

 

(2)添加堂兄弟和堂兄妹个数(SibSp)、父母和孩子的个数(Parch),并且添加'embarked‘

得分:0.68412

反而比不添加Embarked更低。

可能是否有家人在这个因素对是否生存没有直接的联系.

(3)添加父母和孩子的个数(Parch),并且添加'embarked‘

得分:0.72248

 

(4)添加堂兄弟和堂兄妹个数(SibSp)并且添加'embarked‘

得分:0.67464

 

(5)删Embarked,只用Parch

得分:0.70813

 

(6)删Embarked,只留SibSP

得分:0.68421

上述情况表示,加上SibSp和Parch之后的得分要比不加时都低,这两个特征不考虑

 

最后得分最高的情况是:

(1)     “Age”的缺失值用平均数填补,“Embarked”的缺失值用众数填补

(2)     只考虑'Age''Sex''Pclass'和“Embarked”这四个特征

(3)     'Embarked'用标签编码而不是独热编码

(4)     KNN算法中参数n_neighbors取3值

最高得分:0.72727

心得总结:

(1)     在分析数据时没有做到把数据可视化来观察,而是凭感觉选出“年龄性别舱位等级”这些特征来拟合模型。

(2)     验证的顺序有点乱,应该一个验证完再尝试下一个。

(3)     不仅对训练数据'train'要进行数据清洗,对测试数据'test'也要。

(4)     有一个疑惑的问题,为什么K折交叉验证法得出的best_k K值得分不是最高的?难道是KNN的K值在这个问题中没什么影响吗?

 

最后上代码

  1 import pandas as pd
  2 train = pd.read_csv(r'C:\Users\tanha\Desktop\机器学习\train.csv')
  3 test = pd.read_csv(r'C:\Users\tanha\Desktop\机器学习\test.csv')
  4 print(train)
  5 
  6 traindata = train[['Pclass','Sex','Age','Embarked']].copy()
  7 #trainlabel = pd.Series(train['Survived'])
  8 trainlabel = train['Survived'].copy()#目标值
  9 #为何要.copy()? https://www.jianshu.com/p/72274ccb647a
 10 
 11 #对性别以0-1取代,male-1,female-0
 12 traindata.loc[traindata.Sex =='female', 'Sex'] = 0
 13 traindata.loc[traindata.Sex =='male', 'Sex'] = 1
 14 #对城市也同样用0,1,2取代S,C,Q
 15 traindata.loc[traindata.Embarked =='S', 'Embarked'] = 0
 16 traindata.loc[traindata.Embarked =='C', 'Embarked'] = 1
 17 traindata.loc[traindata.Embarked =='Q', 'Embarked'] = 2
 18 traindata
 19 
 20 #查看缺失值情况
 21 traindata.info()
 22 #显示Age的缺失值
 23 traindata[traindata.Age.isnull()]
 24 traindata[traindata.Embarked.isnull()]
 25 
 26 ##填充Age的缺失值为0
 27 #traindata.loc[traindata.Age.isnull(), 'Age'] = 0
 28 #填充Age的缺失值为该列平均值mean()
 29 #中位数median()
 30 print(traindata.Age.mean())
 31 traindata.loc[traindata.Age.isnull(), 'Age'] = traindata.Age.fillna(round(traindata.Age.mean(),1))
 32 #填充Embarked的缺失值为0
 33 traindata.loc[traindata.Embarked.isnull(), 'Embarked'] = 0
 34 traindata.head(10)
 35 
 36 from sklearn.model_selection import train_test_split
 37 train_data, test_data, train_label, test_label = train_test_split(traindata, trainlabel, random_state=7, test_size=0.3 )
 38 print(len(train_data), len(test_data),len(train_label))
 39 type(train_data)
 40 type(train_label)
 41 
 42 #选出一个K的值
 43 #把训练集分为训练数据和验证数据
 44 import numpy as np
 45 from sklearn.model_selection import KFold
 46 from sklearn.neighbors import KNeighborsClassifier
 47 
 48 #X = np.array(traindata[['Pclass', 'Sex', 'Age']])
 49 X = np.array(traindata)
 50 #y = np.array(trainlabel['Survived'])
 51 y = trainlabel.values.ravel()
 52 #已经把X,y化为列表
 53 
 54 kf = KFold(n_splits=891,shuffle=True) #如果要使用留一法交叉验证,那n_splits=样本数量
 55 
 56 ks = [1,3,5,7,9,11,13,15,17,19,20]
 57 
 58 best_k = ks[0]
 59 best_score = 0
 60 
 61 for k in ks:
 62     curr_score = 0    
 63     
 64     for train_index, valid_index in kf.split(X):
 65         clf = KNeighborsClassifier(n_neighbors=k)
 66         clf.fit(X[train_index], y[train_index])
 67         curr_score += clf.score(X[valid_index], y[valid_index])
 68     
 69     avg_score = curr_score/891 #前面n_splits=5,5折交叉验证
 70     
 71     if avg_score>best_score:
 72         best_score = avg_score
 73         best_k = k
 74     print("current best score is: %.2f"%best_score, "best k: %d"%best_k)
 75 
 76 print("after cross validtion, the final best k is: %d"%best_k)
 77 
 78 from sklearn.neighbors import KNeighborsClassifier
 79 clf = KNeighborsClassifier(n_neighbors=3)
 80 
 81 clf.fit(traindata, trainlabel)
 82 
 83 pred = clf.predict(test_data)
 84 
 85 from sklearn.metrics import accuracy_score
 86 accuracy_score(pred, test_label)
 87 
 88 #清洗test数据
 89 testdata = test[['Pclass','Sex','Age','Embarked']].copy()
 90 #对性别以0-1取代,male-1,female-0
 91 testdata.loc[testdata.Sex =='female', 'Sex'] = 0
 92 testdata.loc[testdata.Sex =='male', 'Sex'] = 1
 93 
 94 testdata.loc[testdata.Embarked =='S', 'Embarked'] = 0
 95 testdata.loc[testdata.Embarked =='C', 'Embarked'] = 1
 96 testdata.loc[testdata.Embarked =='Q', 'Embarked'] = 2
 97 
 98 #查看缺失值情况
 99 testdata.info()
100 #显示Age的缺失值
101 testdata[testdata.Age.isnull()]
102 
103 #填充Embarked的缺失值为0
104 testdata.loc[testdata.Embarked.isnull(), 'Embarked'] = 0
105 
106 #填充Age的缺失值为该列平均值
107 testdata.loc[testdata.Age.isnull(), 'Age'] = testdata.Age.fillna(round(testdata.Age.mean(),1))
108 testdata.head(100)
109 
110 import numpy as np
111 #testdata = test[['Pclass','Sex','Age','Embarked']].copy()
112 result0 = clf.predict(testdata)
113 index = test['PassengerId']
114 sumission = pd.DataFrame({'PassengerId':test['PassengerId'].values,'Survived':result0.astype(np.int32)})
115 #sumission = sumission.reset_index(drop=True)
116 #index = test_data['PassengerId']
117 sumission['Survived'] = result0
118 sumission = sumission.reset_index(drop=True)
119 sumission.to_csv(r'C:\Users\tanha\Desktop\机器学习\submission6.csv',index=0)#不保留行索引

 

 

 

 

 

 

 

参考博客:

python 分析泰坦尼克号生还率(数据可视化很清晰)

https://blog.csdn.net/sixkery/article/details/83239375

用Python随机森林预测泰坦尼克号生存情况

https://www.cnblogs.com/annebang/p/8731300.html

Kaggle泰坦尼克数据科学解决方案

https://www.cnblogs.com/zackstang/p/8185531.html

GridSearchCV,CV调优超参数使用】【K最近邻分类器 KNeighborsClassifier 使用】【交叉验证】

https://blog.csdn.net/feifei_csdn/article/details/84103071

 

posted @ 2020-02-13 18:04  Y000  阅读(247)  评论(0编辑  收藏  举报