在本文中,将探讨如何着手进行一个数据科学项目,特别是以泰坦尼克号乘客生存预测为例。将从数据的基本分析开始,接着进行特征工程,最后使用一些流行的模型来进行预测。这篇文章的目标是预测乘客是否在海难中幸存。将使用Kaggle上的数据集,链接如下。这篇文章将重点放在如何思考这些项目上,而不是具体的实现。许多初学者在开始和结束时感到困惑,希望这篇文章能成为入门手册。建议在Kaggle上实践这个项目。
将从导入基本的库开始,然后读取数据,并进行数据探索。在这个过程中,试图从数据中提取洞见,并熟悉数据,以便可以创建更有效的模型。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
training = pd.read_csv('/kaggle/input/titanic/train.csv')
test = pd.read_csv('/kaggle/input/titanic/test.csv')
training['train_test'] = 1
test['train_test'] = 0
test['Survived'] = np.NaN
all_data = pd.concat([training,test])
all_data.columns
接下来,将对数据进行探索,包括数值型和分类型数据。将绘制数值数据的直方图,并观察它们之间的关系。
df_num = training[['Age','SibSp','Parch','Fare']]
df_cat = training[['Survived','Pclass','Sex','Ticket','Cabin','Embarked']]
for i in df_num.columns:
plt.hist(df_num[i])
plt.title(i)
plt.show()
sns.heatmap(df_num.corr())
从这些图表中,可以观察到大多数分布是分散的,除了年龄,它看起来相当正常。可能会考虑稍后对其进行归一化处理。接下来,将比较数值变量之间的生存率。这可能会揭示一些有趣的见解。
pd.pivot_table(training, index = 'Survived', values = ['Age','SibSp','Parch','Fare'])
从这个表中,可以得出以下结论:幸存者的平均年龄是28岁,所以年轻人更有可能幸存。支付更高票价的人更有可能幸存,是其他人的两倍多。这可能是乘坐头等舱的人。因此,富人幸存下来,这在这种情况下是一个悲伤的故事。在第三列中,如果有父母,幸存的机会更高。所以父母可能在他们自己之前救了孩子,从而解释了这个比率。如果是孩子,并且有兄弟姐妹,幸存的机会就更低。
观察到票和船舱数据对来说并没有太大意义,这可能会阻碍模型的性能,所以需要通过特征工程来简化这些数据。
training['cabin_multiple'] = training.Cabin.apply(lambda x: 0 if pd.isna(x) else len(x.split(' ')))
training['cabin_multiple'].value_counts()
看起来绝大多数人没有单独的船舱,只有少数人拥有超过一个船舱。现在让看看生存率是否取决于这一点。
pd.pivot_table(training, index = 'Survived', columns = 'cabin_multiple', values = 'Ticket' ,aggfunc ='count')
接下来,让看看他们所在的船舱的实际字母。可以预期,具有相同字母的船舱大致在相同的位置,或者在相同的楼层上,逻辑上,如果一个船舱靠近救生艇,他们有更好的生存机会。让看看这一点。
training['cabin_adv'] = training.Cabin.apply(lambda x: str(x)[0])
print(training.cabin_adv.value_counts())
pd.pivot_table(training,index='Survived',columns='cabin_adv', values = 'Name', aggfunc='count')
还对票列进行了一些特征工程,但没有产生太多不知道的显著见解,所以为了保持文章简洁,将跳过这部分。只会将票分为数字和非数字,以有效使用。
training['numeric_ticket'] = training.Ticket.apply(lambda x: 1 if x.isnumeric() else 0)
training['ticket_letters'] = training.Ticket.apply(lambda x: ''.join(x.split(' ')[:-1]).replace('.','').replace('/','').lower() if len(x.split(' ')[:-1]) >0 else 0)
training['name_title'] = training.Name.apply(lambda x: x.split(',')[1].split('.')[0].strip())
training['name_title'].value_counts()
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
lr = LogisticRegression(max_iter = 2000)
cv = cross_val_score(lr,X_train_scaled,y_train,cv=5)
print(cv)
print(cv.mean())
knn = KNeighborsClassifier()
cv = cross_val_score(knn,X_train_scaled,y_train,cv=5)
print(cv)
print(cv.mean())
svc = SVC(probability = True)
cv = cross_val_score(svc,X_train_scaled,y_train,cv=5)
print(cv)
print(cv.mean())