今天为大家带来的是kaggle上的入门题目--泰坦尼克号存活预测,根据提供的乘客信息来预测乘客能否幸存。

最近在琢磨机器学习方面,之前唯一接触过的python相关只有写了几个简单爬虫和脚本,因为课程不涉及相关内容,之前根本不知道机器学习是怎么回事,希望可以通过这个简单的例子练练手,最近因该也会更新相关内容,希望和大家一起学习成长。

代码参考来源:YouTube@neuralNine

目录

题目概括

数据分析

数据处理

模型训练

源码


题目概括

以泰塔尼克号沉没为背景,现提供了船上乘客的个人信息(ID,性别,pclass等等......),需要你建立一个预测模型并预测具有什么条件的乘客最可能幸存。相对陌生词语如pclass等题目做了详细解释,有兴趣可以去研究一下。

说人话就是:我们现在可以从题目获取三个文件,train是我们的机器学习素材,完成机器学习模型后代入test数据进行预测,gender_submission是本题答案,我们预测得出的文件最后可以和答案对比准确度(一般不会是100%)

数据分析

【原博主教学使用的编译软件是jupyter,我这里使用的PyCharm,其实用啥都行没啥影响】

第一步,先下需要的包:numpy,pands,seaborn,scikit-learn,matplotlib

然后导包读取文件

这里用train数据生成了一个相关性热力图(如下),用来参考具体是哪些条件影响了幸存率(这个自己做题时能提供思路很有帮助,但是如果本身对python和相关数学知识了解不多,学习比较吃力的不打算深入学习这方面的,这道题可以直接从给的答案推题目)

sns.heatmap(titanic_data.corr(numeric_only=True),cmap='coolwarm')
plt.show()

数据处理

这一步,对训练数据和测试数据进行分层抽样并分别装成两个数据集,并且比对抽样分布图作为验证手段(下图左test,右train),如果相似性较高则抽样有效,数据集可用(用来找最优模型)。

split=StratifiedShuffleSplit(n_splits=1, test_size=0.2)
for train_indices, test_indices in split.split(titanic_data,titanic_data[["Survived","Pclass","Sex"]]):
    strat_train_set=titanic_data.loc[train_indices]
    strat_test_set = titanic_data.loc[test_indices]

plt.subplot(1,2,1)
strat_test_set["Survived"].hist()
strat_test_set["Pclass"].hist()

plt.subplot(1,2,2)
strat_train_set["Survived"].hist()
strat_train_set["Pclass"].hist()
plt.show()

这里我们定义三个类进行数据的修缮,主要有三点:

1.数据缺失的部分比如年龄,我们用均值mean进行补充。

2.对于一些不好处理的数据(特指数据非整型数据的),我们给他们用独热编码器进行编码,便于计算机进行理解(毕竟机器不认识男女老少,只知道0123...)

3.对于相关性差的冗余数据,我们直接删掉

from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.impute import SimpleImputer

class AgeImputer(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        return self
    def transform(self, X):
        imputer = SimpleImputer(strategy="mean")
        X['Age'] = imputer.fit_transform(X[['Age']])
        return X

from sklearn.preprocessing import OneHotEncoder

class FeatureEncoder(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        return self
    def transform(self, X):
        encoder = OneHotEncoder()
        matrix = encoder.fit_transform(X[['Embarked']]).toarray()

        column_names=["C","S","Q","N"]

        for i in range(len(matrix.T)):
            X[column_names[i]]=matrix.T[i]

        matrix=encoder.fit_transform(X[['Sex']]).toarray()

        column_names=["Female","Male"]

        for i in range(len(matrix.T)):
            X[column_names[i]] = matrix.T[i]

        return X

class FeatureDropper(BaseEstimator, TransformerMixin):
        def fit(self, X, y=None):
            return self
        def transform(self, X):
            return X.drop(["Embarked","Name","Ticket","Cabin","Sex","N"],axis=1,errors="ignore")

最后用定义的方法处理数据

pipeline = Pipeline([("ageimputer",AgeImputer()),
                     ("featureencoder",FeatureEncoder()),
                     ("featuredropper",FeatureDropper())])
strat_train_set=pipeline.fit_transform(strat_train_set)

删除原有的结果,并且消除数据之间可能存在的过大差异(如男女数据范围0-1,年龄范围0-100)把他们转化为平均0方差1的形式,转换标签格式使之符合所用包的需要。

from sklearn.preprocessing import StandardScaler

x=strat_train_set.drop(['Survived'],axis=1)
y=strat_train_set['Survived']
scaler = StandardScaler()
X_data=scaler.fit_transform(x)
y_data=y.to_numpy()

模型训练

这里使用了森林分布器和网格搜索工具,并用三折交叉验证,准确率为指标进行评价来找出最佳模型,找到最优模型后,我们去除数据集标签,评估所找模型的准确性,这里比较复杂,具体看注释

# 初始化随机森林分类器
clf = RandomForestClassifier()
# 定义参数网格:用于网格搜索最优参数
param_grid = [
    {"n_estimators": [10, 100, 200, 500], 
     "max_depth": [None, 5, 10],  
     "min_samples_split": [2, 3, 4]} 
]

# cv=3:3折交叉验证;scoring="accuracy":以准确率为评价指标
grid_search = GridSearchCV(clf, param_grid, cv=3, scoring="accuracy", return_train_score=True)
grid_search.fit(X_data, y_data)  # 在训练集上拟合

# 获取最优模型
final_clf = grid_search.best_estimator_

# 用管道处理测试集(仅转换,不重新拟合,避免数据泄露)
strat_test_set = pipeline.transform(strat_test_set)

#去标签并标准化数据集
X_test=strat_test_set.drop(['Survived'],axis=1)
y_test=strat_test_set['Survived']
scaler=StandardScaler()
X_data_test=scaler.fit_transform(X_test)
y_data_test=y_test.to_numpy()

#在测试集上评估最优模型的准确率
final_clf.score(X_data_test,y_data_test)
final_data=pipeline.fit_transform(titanic_data)

我们去除全部数据集标签,用找到并验证的这个最佳模型对全部数据进行模型训练,得到训练好的最终模型(做到这一步就算真正训练出了机器模型,不容易啊!)


#分离全部数据的特征和标签
X_final=final_data.drop(['Survived'],axis=1)
y_final=final_data['Survived']
scaler=StandardScaler()
X_data_final=scaler.fit_transform(X_final)
y_data_final=y_final.to_numpy()

#用全部数据训练
prod_clf=RandomForestClassifier()
param_grid=[
    {"n_estimators":[10,100,200,500],"max_depth":[None,5,10],"min_samples_split":[2,3,4]},
]

grid_search=GridSearchCV(prod_clf,param_grid,cv=3,scoring="accuracy",return_train_score=True)
grid_search.fit(X_data_final,y_data_final)

#获取最终用于预测的最优模型
prod_final_clf=grid_search.best_estimator_

最后我们对test数据进行规范化处理,就可以进行预测啦,生成并保存最后的文件,这个文件就是我们最后可以提交的结果,在kaggle网站测试与所给完整数据相似度78%以上

# 读取测试集数据(这里文件路径需要是自己文件下载解压的位置)
titanic_test_data = pd.read_csv('E:/ttnkdatas/titanic/test.csv')

final_test_data = pipeline.fit_transform(titanic_test_data)

# 准备测试集特征,填充可能的缺失值(向前填充)
X_final_test = final_test_data
X_final_test = X_final_test.fillna(method='ffill') 

# 标准化测试集特征
scaler = StandardScaler()
X_data_final_test = scaler.fit_transform(X_final_test)

# 用最终模型预测测试集的存活情况
predictions = prod_final_clf.predict(X_data_final_test)

# 生成提交文件:包含乘客ID和预测结果
final_df = pd.DataFrame(final_test_data['PassengerId'], columns=['PassengerId'])  
final_df['Survived'] = predictions 
# 保存同样保存在自己能找见的地方
final_df.to_csv("E:/ttnkdatas/titanic/predictions.csv", index=False)

源码

最后附上完整源码(没写注释,有不懂的请看上面部分的代码注释)

from os.path import split
from typing import final
from xml.etree.ElementPath import prepare_predicate

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from joblib.testing import param

titanic_data=pd.read_csv('E:/ttnkdatas/titanic/train.csv')

import seaborn as sns

sns.heatmap(titanic_data.corr(numeric_only=True),cmap='coolwarm')
plt.show()

from sklearn.model_selection import StratifiedShuffleSplit

split=StratifiedShuffleSplit(n_splits=1, test_size=0.2)
for train_indices, test_indices in split.split(titanic_data,titanic_data[["Survived","Pclass","Sex"]]):
    strat_train_set=titanic_data.loc[train_indices]
    strat_test_set = titanic_data.loc[test_indices]

plt.subplot(1,2,1)
strat_test_set["Survived"].hist()
strat_test_set["Pclass"].hist()

plt.subplot(1,2,2)
strat_train_set["Survived"].hist()
strat_train_set["Pclass"].hist()
plt.show()

from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.impute import SimpleImputer

class AgeImputer(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        return self
    def transform(self, X):
        imputer = SimpleImputer(strategy="mean")
        X['Age'] = imputer.fit_transform(X[['Age']])
        return X

from sklearn.preprocessing import OneHotEncoder

class FeatureEncoder(BaseEstimator, TransformerMixin):
    def fit(self, X, y=None):
        return self
    def transform(self, X):
        encoder = OneHotEncoder()
        matrix = encoder.fit_transform(X[['Embarked']]).toarray()

        column_names=["C","S","Q","N"]

        for i in range(len(matrix.T)):
            X[column_names[i]]=matrix.T[i]

        matrix=encoder.fit_transform(X[['Sex']]).toarray()

        column_names=["Female","Male"]

        for i in range(len(matrix.T)):
            X[column_names[i]] = matrix.T[i]

        return X

class FeatureDropper(BaseEstimator, TransformerMixin):
        def fit(self, X, y=None):
            return self
        def transform(self, X):
            return X.drop(["Embarked","Name","Ticket","Cabin","Sex","N"],axis=1,errors="ignore")

from sklearn.pipeline import Pipeline

pipeline = Pipeline([("ageimputer",AgeImputer()),
                     ("featureencoder",FeatureEncoder()),
                     ("featuredropper",FeatureDropper())])
strat_train_set=pipeline.fit_transform(strat_train_set)

from sklearn.preprocessing import StandardScaler

x=strat_train_set.drop(['Survived'],axis=1)
y=strat_train_set['Survived']
scaler = StandardScaler()
X_data=scaler.fit_transform(x)
y_data=y.to_numpy()

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV

clf=RandomForestClassifier()
param_grid=[
    {"n_estimators":[10,100,200,500],"max_depth":[None,5,10],"min_samples_split":[2,3,4]},
]

grid_search=GridSearchCV(clf,param_grid,cv=3,scoring="accuracy",return_train_score=True)
grid_search.fit(X_data,y_data)

final_clf=grid_search.best_estimator_

strat_test_set=pipeline.transform(strat_test_set)

X_test=strat_test_set.drop(['Survived'],axis=1)
y_test=strat_test_set['Survived']

scaler=StandardScaler()
X_data_test=scaler.fit_transform(X_test)
y_data_test=y_test.to_numpy()

final_clf.score(X_data_test,y_data_test)
final_data=pipeline.fit_transform(titanic_data)

X_final=final_data.drop(['Survived'],axis=1)
y_final=final_data['Survived']

scaler=StandardScaler()
X_data_final=scaler.fit_transform(X_final)
y_data_final=y_final.to_numpy()

prod_clf=RandomForestClassifier()
param_grid=[
    {"n_estimators":[10,100,200,500],"max_depth":[None,5,10],"min_samples_split":[2,3,4]},
]

grid_search=GridSearchCV(prod_clf,param_grid,cv=3,scoring="accuracy",return_train_score=True)
grid_search.fit(X_data_final,y_data_final)

prod_final_clf=grid_search.best_estimator_

titanic_test_data=pd.read_csv('E:/ttnkdatas/titanic/test.csv')

final_test_data=pipeline.fit_transform(titanic_test_data)

X_final_test=final_test_data
X_final_test=X_final_test.fillna(method='ffill')

scaler=StandardScaler()
X_data_final_test=scaler.fit_transform(X_final_test)

predictions=prod_final_clf.predict(X_data_final_test)

final_df=pd.DataFrame(final_test_data['PassengerId'],columns=['PassengerId'])
final_df['Survived']=predictions
final_df.to_csv("E:/ttnkdatas/titanic/predictions.csv",index=False)

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐