Titanic是Kaggle入门竞赛的第一个问题,泰坦尼克号已经是众所周知的事情,在这场灾难中存活下来的人非常少,运用机器学习的知识预测某个人在这场灾难中是否能够存活是这道题目的目的。这道题一共做了三次,总结一下做本题的步骤:
(1)首先是读取数据,使用python的数据分析包pandas,numpy等读取csv格式的数据;
(2)查看是否有缺失值,使用第三方模块missingno可以十分直观的查看数据是否有缺失值,在网上学到了处理缺失值的方法:如果缺失值达到15%以上即可删掉,或者可以再去查看一下有缺失值的变量的异常值分布,如果既有缺失值同时异常值也较多那么该变量可能对最终的结果分析没太大作用,可以考虑删掉。这样简单粗暴的做法会对预测的结果产生影响吗?应该会,不过影响不会很大;
(3)填充缺失值,对于那些缺失值较少的变量,还是有填充的必要的,可以用loc寻找缺失值的位置,然后用直接赋值的方法填充数据;
(4)对各个变量进行分析。分析每个变量之前,可以先画一个热度图(heatmap),查看每个变量与survived之间的相关性,热度图可以让我们对数据有一个比较全面的认识,在分析每个变量的时候,可以用seaborn模块画箱图,直方图,因子图(factorplot),不知道是不是这么翻译的)等,观察变量与是否存活的关系,对于一些出现频数高,但与survived相关性小的变量可以选择删掉;
(5)训练模型:当前面的数据预处理部分都做的差不多的时候,可以用模型对数据进行训练了,这个过程中如果能对模型进行调参就更好了~~
(6)提交结果,最终的结果分为两列,一个是PassengerId,另一个是Survived,把模型预测的结果写为csv格式后便可提交了~
另外:1.放入模型训练的数据要转化成int或float型,并且数据不能有缺失值,之前做实验的对结果预测的时候程序一直报错,Input contains NAN,infinit or a value too large...后来查看数据发现Ticket1这个变量有一个缺失值==这个错误找了很久,可能是1308和1309长得比较像吧。。导致之前用info()查看数据的时候没有发现==
2.对于Name这个变量,我选择直接删除了,因为觉得没什么作用,但是看到别人的分析,名字中的Miss,Master中暗含了此人的年龄范围,所以可以通过姓名来推测Age中的缺失值,这样比随机填充一个数值要更准确,这种方法非常可取。
下面是代码,有详细注释:
#-*- coding:utf-8 -*-
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import missingno as msno
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
#import re
import sklearn
from sklearn import *
from sklearn.linear_model import LogisticRegression
train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')
df = train.append(test)
#用info()函数查看缺失值,观察哪些变量需要填充
#可视化缺失值,因为有12个变量,所以figsize的宽度设置为12
msno.matrix(df,figsize=(11,5))
#plt.show()
#填充Age缺失值
ave_age = df['Age'].mean()
std_age = df['Age'].std()
df.loc[pd.isnull(df['Age']),'Age']= np.random.randint(ave_age-std_age,ave_age+std_age,df['Age'].isnull().sum())
#填充Embarked缺失值
sns.countplot(data=train,x='Embarked')
#plt.show()
#S占大多数,填充S
df.Embarked = df.Embarked.fillna('S')
#填充Fare变量
df['Fare'] = df['Fare'].fillna(df['Fare'].median())
#除了Survived和Cabin之外的缺失值都已经填充
# df.drop('Cabin',axis=1,inplace=True)
#画热度图看各个变量与Survived之间的关系
#pd.notnull(df['Survived'])是为了取出train中的数据,但是train没有被填充,所以用这种方法取出来
cottMatt = df[pd.notnull(df['Survived'])].corr()
#mask把cottmatt转换成矩阵
mask = np.array(cottMatt)
mask[np.tril_indices_from(mask)] = False
fig,axes = plt.subplots()
fig.set_size_inches(12,12)
sns.heatmap(data=cottMatt,mask=mask,annot=True,square=True)
#对Pclass分析,画因子图
sns.set_style('ticks')
sns.factorplot(x='Pclass',y='Survived',data=df)
#sns.countplot(x='Pclass',data=df)
#为了删掉Pclass里的3,先把Pclass用指标矩阵表示出来
pclass_get_dummies = pd.get_dummies(df['Pclass'])
pclass_get_dummies.columns = ['class1','class2','class3']
pclass_get_dummies.drop(['class3'],axis=1,inplace=True)
df = pd.concat([df, pclass_get_dummies], axis=1)
df.drop(['Pclass'],axis=1,inplace=True)
# print df.info()
#分析name变量
df.drop(['Name'],axis=1,inplace=True)
#分析Sex变量
plt.figure()
plt.subplot(1,2,1)
sns.countplot(x='Sex',data=df)
plt.subplot(1,2,2)
sns.factorplot(x='Sex',y='Survived',data=df)
#plt.show()
#df['Sex'] = df['Sex'].map({'male':0,'female':1})
sex_get_dummies = pd.get_dummies(df['Sex'])
sex_get_dummies.drop(['male'],axis=1,inplace=True)
df.drop('Sex',axis=1,inplace=True)
df = pd.concat([df, sex_get_dummies], axis=1)
#Age变量分析
fig,axes = plt.subplots()
fig.set_size_inches(10,5)
bins=[0,18,28,38,48,60,80]
x = df['Age']
sns.distplot(x,bins=bins,hist=True,kde=True,rug=True,ax=axes)
df['Age'] = df['Age'].astype(int)
#plt.show()
#创建Family变量
df['Family'] = df['SibSp']+df['Parch']
df['Family'].loc[df['Family']<1] = 0
df['Family'].loc[df['Family']>=1] = 1
sns.set_style('whitegrid')
fig,axes = plt.subplots(nrows=2,ncols=1)
fig.set_size_inches(10,15)
#countplot()只有x,没有y
sns.countplot(x='Family',data=df,ax=axes[0])
grouped = df[['Family','Survived']].groupby(df['Family']).mean()
sns.barplot(x='Family',y='Survived',data=grouped,ax=axes[1])
axes[0].set_xticklabels(["Alone","With Family"])
axes[1].set_xticklabels(["Alone","With Family"])
#从上图可以看出,与家人在一起的比单独乘船的存活率高
#把这两个变量组合成一个变量Family之后,删掉这两个变量
df.drop('SibSp',axis=1,inplace=True)
df.drop('Parch',axis=1,inplace=True)
#分析Ticket变量,用正则表达式把Ticket中的前缀提取出来,分析不同类别的Ticket与survived之间的关系
def analysis(ticket):
ticket = ticket.replace('/','')
ticket = ticket.replace(',','')
ticket = ticket.split()
ticket = map(lambda t:t.strip(),ticket)
#用filter函数取出经过split后的字母部分
ticket = list(filter(lambda t:not t.isdigit(),ticket))
if len(ticket)>0:
return ticket[0]
else:
#这是全部是数字的部分
return 'X'
df['Ticket1'] = df['Ticket'].map(analysis)
df['Ticket1'] = df['Ticket1'].replace(['A5','A5.','A.5.','A4.','A4'],'A')
df['Ticket1'] = df['Ticket1'].replace(['PC','PP','PPP'],'P')
df['Ticket1'] = df['Ticket1'].replace(['STON02','SCParis','S.C.A.4.','S.P.','S.O.C.','SOC','SOTONOQ','STONO','S.O.P.P','SOTONO.Q.','SWPP','SCOW','SCAH','STONO2.','SC','S.O.P.P.'],'S')
df['Ticket1'] = df['Ticket1'].replace(['C.A.','CA','C','CA.'],'C')
df['Ticket1'] = df['Ticket1'].replace(['W.C.','W.E.P.','WC'],'W')
df['Ticket1'] = df['Ticket1'].replace(['Fa','FC','LINE','F.C.C.','F.C.','S.C.PARIS','WEP','SCPARIS','S.O.P.','SCON02.','SCA.3','STONOQ.','SCA4','SOTON2','AQ4','A','LP','AQ3.','AS','S.W.PP','C.A.SOTON','SOTONO2'],'O')
df['Ticket1'] = df['Ticket1'].map({'X':0,'A':1,'P':2,'S':3,'C':4,'W':5,'O':6})
#df['Ticket1'] = df['Ticket1'].astype(int)
#df['Ticket1'] = df['Ticket1'].map({'X':0,'A':1,'P':2,'S':3,'C':4,'W':5,'O':6})
#df['Ticket1'] = df['Ticket1'].drop(pd.isnull(df['Ticket1']))
fig,axes = plt.subplots()
sns.countplot(x='Ticket1',data=df)
plt.show()
#df['Ticket1'] = df['Ticket1'].astype(int)
df.drop(['Ticket'],axis=1,inplace=True)
#分析Fare变量
#根据describe()中25%的Fare,50%,75%...划分Fare的范围
# fig,axes = plt.subplots()
# sns.countplot(x='Fare',data=df)
# plt.show()
df.loc[df['Fare']<=7.89,'Fare'] = 0
df.loc[(df['Fare']>7.89)&(df['Fare']<=14.45),'Fare'] = 1
df.loc[(df['Fare']>14.45)&(df['Fare']<=31.28),'Fare'] = 2
df.loc[df['Fare']>31.28,'Fare'] = 3
df['Fare'] = df['Fare'].astype(int)
fig,axes = plt.subplots(2,1)
sns.countplot(x='Fare',data=df,ax=axes[0])
sns.barplot(x='Fare',y='Survived',data=df,ax=axes[1])
#plt.show()
#分析Cabin变量,因为缺失值太多,删掉此变量
df.drop('Cabin',axis=1,inplace=True)
#分析Embarked变量
# fig,axes = plt.subplots(nrows=1,ncols=2)
# fig.set_size_inches(6,8)
# sns.countplot(x='Embarked',data=df,ax=axes[0])
# sns.factorplot(x='Embarked',y='Survived',data=df,ax=axes[1])
fig,ax = plt.subplots()
sns.countplot(x='Embarked',data=df)
sns.factorplot(x='Embarked',y='Survived',data=df)
#plt.show()
#根据上面两个图,发现Embarked的S虽然数量多,但是存活率低,可以考虑删掉
embarked_get_dummies = pd.get_dummies(df['Embarked'])
embarked_get_dummies.drop(['S'],axis=1,inplace=True)
df['Embarked'] = df['Embarked'].map({'S':0,'C':1,'Q':2})
df.drop(['Embarked'],axis=1,inplace=True)
df = pd.concat([df, embarked_get_dummies], axis=1)
cottMatt = df[pd.notnull(df['Survived'])].corr()
#print (cottMatt)
#mask把cottmatt转换成矩阵
mask = np.array(cottMatt)
mask[np.tril_indices_from(mask)] = False
fig,axes = plt.subplots()
fig.set_size_inches(12,12)
sns.heatmap(data=cottMatt,mask=mask,annot=True,square=True)
#plt.show()
X = df[pd.notnull(df['Survived'])].drop(['Survived'],axis=1)
X_test = df[pd.isnull(df['Survived'])].drop(['Survived'],axis=1)
y = df[pd.notnull(df['Survived'])].Survived.astype(int)
#print (df)
logreg = LogisticRegression()
logreg.fit(X, y)
pre = logreg.predict(X_test)
print (pre)
logreg.score(X, y)
submission =pd.DataFrame({'PassengerId':X_test['PassengerId'],
'Survived':pre})
submission.to_csv('submission.csv',index=False)
另外第一次使用seaborn模块,在知乎上学习了有关seaborn画图的方法,链接: Seaborn(sns)官方文档学习笔记,这是第一章,在文末还有第二章第三章,学会了可以画更炫酷的图。嗯..就写到这儿吧