【Kaggle】Titanic 生存预测模型

数据集可以在这里下载:

https://www.kaggle.com/c/titanic


在此项目中,我们会用到以下Python库:

  • Numpy - python科学计算库(矩阵运算)
  • Pandas - python数据分析处理库
  • Scikit-learn - python机器学习库(机器学习算法)

一、首先查看一下数据

import pandas as pd
titanic = pd.read_csv(r"S:\数据分析\kaggle_Titanic\train.csv")
titanic.head() # 默认前五行

在这里插入图片描述
我们可以看看 Titanic数据中有哪些特征,并分析一下哪些特征对生存几率的影响比较大。


二、接下来进行数据预处理

print(titanic.describe()) # 按列统计特征

通过对列的特征统计,我们发现Age值存在缺失的情况,于是下面进行缺失值处理:

import pandas as pd
titanic['Age'] = titanic['Age'].fillna(titanic['Age'].mean()) # 使用均值填充缺失值
print(titanic.describe())

于是,Age数据就填充完毕了。

然后对 Sex特征进行独热编码:
print(titanic['Sex'].unique()) # 查看Sex特征有哪些值
>>> ['male' 'female']

# loc定位到目标行,对Sex特征进行独热编码
titanic.loc[titanic['Sex'] == 'male', 'Sex'] = 0 # 令Sex等于male那行的Sex值为1
titanic.loc[titanic['Sex'] == 'female', 'Sex'] = 1 # 令Sex等于female那行的Sex值为0
再对 Embarked特征进行缺失值处理和独热编码:
print(titanic['Embarked'].unique())
>>> ['S' 'C' 'Q' nan] # 存在缺失值

titanic['Embarked'] = titanic['Embarked'].fillna('S') # S数量多,可以用S补充缺失值
titanic.loc[titanic['Embarked'] == 'S', "Embarked"] = 0
titanic.loc[titanic['Embarked'] == 'C', "Embarked"] = 1
titanic.loc[titanic['Embarked'] == 'Q', "Embarked"] = 2

三、使用线性回归模型预测生存几率

from sklearn.linear_model import LinearRegression # 导入线性回归的类,采用二分类进行分类预测
from sklearn.model_selection import KFold # K折交叉验证,取平均,调参

predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"] # 输入机器学习算法的特征

alg = LinearRegression() # 初始化线性回归类
kf = KFold(n_splits=3, random_state=1) # KFold类实例化
# kf.get_n_splits(titanic) # 交叉验证集的拆分迭代次数

predictions = []

# 有3次for循环,每次建立一个回归模型
for train, test in kf.split(titanic):
    train_predictors = (titanic[predictors].iloc[train,:]) # 取出训练数据
    train_target = titanic["Survived"].iloc[train] # 获取到数据集中交叉分类好的标签,即是否活了下来
    alg.fit(train_predictors, train_target) # 训练模型
    test_predictions = alg.predict(titanic[predictors].iloc[test,:]) # 检验模型误差
    predictions.append(test_predictions)

在 sklearn 0.18及以上的版本中,cross_validation包已经被废弃。

KFold文档:https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.KFold.html?highlight=kfold#sklearn.model_selection.KFold

看看模型训练的效果:
import numpy as np

predictions = np.concatenate(predictions, axis=0) # 转换成数组,才能比较大小

# 使用线性回归得到的结果是在区间[0,1]上的某个值,需要将该值转换成0或1
predictions[predictions > 0.5] = 1
predictions[predictions <= 0.5] = 0

print("测试数据的总数量:", len(predictions))
print("正确的数量:", sum(predictions == titanic["Survived"]))
accuracy = sum(predictions == titanic["Survived"]) / len(predictions)
print("准确率为:", accuracy)

在这里插入图片描述


四、使用逻辑回归模型预测生存几率

from sklearn import model_selection
from sklearn.linear_model import LogisticRegression

alg = LogisticRegression(random_state=1, solver='liblinear') # 初始化逻辑回归类

# 逻辑回归交叉验证
score = model_selection.cross_val_score(alg, titanic[predictors], titanic["Survived"], cv=3)
print("准确率为:", score.mean())

在这里插入图片描述

貌似用回归模型做预测,效果没那么好……


五、使用随机森林模型预测生存几率

随机的含义:

  1. 随机进行数据样本的采样
  2. 随机对特征采样

也许某些特征是消极的,随机森林可以中和特征,因此随机森林能够防止过拟合,让算法得出来的准确性更可靠一些。

from sklearn import model_selection
from sklearn.ensemble import RandomForestClassifier

predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]

alg = RandomForestClassifier(random_state=1, n_estimators=50, min_samples_split=4, min_samples_leaf=2)

kf = model_selection.KFold(n_splits=3, random_state=1) # 三次交叉验证
# print(kf.get_n_splits(titanic)) # 交叉验证集的拆分迭代次数

score = model_selection.cross_val_score(alg, titanic[predictors], titanic["Survived"], cv=kf.split(titanic))

print("准确率为:", score.mean())

在这里插入图片描述

可以看到比上面两种回归模型得到的准确率高。


了解一下随机森林分类器的参数:
  • random_state
    每次产生随机数的种子。

  • n_estimators(int,可选(默认值=100))
    森林中树木的数量。

  • min_samples_split(int,float,可选(默认值=2)
    拆分内部节点所需的最少样本数。
    如果为int,则认为 min_samples_split 是最小值。
    如果为 float,min_samples_split则为分数,是每个拆分的最小样本数。

  • min_samples_leaf(int,float,可选(默认值= 1))
    在叶节点处需要的最小样本数。
    只有 min_samples_leaf 在左分支和右分支中的每个分支上至少留有训练样本的情况下,才会考虑任何深度的分裂点。这可能具有平滑模型的效果,尤其是在回归中。
    如果为int,则认为 min_samples_leaf 是最小值。
    如果为float,min_samples_leaf 则为分数,是每个节点的最小样本数。


六、建立特征工程

# 第一个特征:亲属数量
titanic["FamilySize"] = titanic["SibSp"] + titanic["Parch"]
# 第二个特征:名字长度
titanic["NameLength"] = titanic["Name"].apply(lambda x:len(x))
titanic
import re

def get_title(name):
    title_search = re.search('([A-Za-z]+)\.', name) # \.匹配.(转义)
    if title_search:
        return title_search.group(1)
    return ""

titles = titanic["Name"].apply(get_title)
print(pd.value_counts(titles))

title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Dr": 5, "Rev": 6, "Major": 7, "Col": 7, "Mlle": 8,
                 "Mme": 8, "Don": 9, "Lady": 10, "Countess": 10, "Jonkheer": 10, "Sir": 9, "Capt": 7, "Ms": 2}
for k, v in title_mapping.items():
    titles[titles == k] = v

print(pd.value_counts(titles))

titanic["Title"] = titles # 添加新特征:身份

七、特征选择

通过添加噪声,分析特征的重要程度:

from sklearn.feature_selection import SelectKBest, f_classif # 特征选择库
import matplotlib.pyplot as plt # 画出直方图,分析特征的权重

predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked", "FamilySize", "Title", "NameLength"]

selector = SelectKBest(f_classif, k=5) # f_classif:基于方差分析的检验统计f值,根据k个最高分数选择功能
selector.fit(titanic[predictors], titanic["Survived"])

scores = -np.log10(selector.pvalues_)

plt.bar(range(len(predictors)), scores)
plt.xticks(range(len(predictors)), predictors, rotation='vertical')
plt.show()

predictors = ["Pclass", "Sex", "Fare", "Title"]

alg = RandomForestClassifier(random_state=1, n_estimators=50, min_samples_split=8, min_samples_leaf=4)
kf = model_selection.KFold(n_splits=3, random_state=1)
scores = model_selection.cross_val_score(alg, titanic[predictors], titanic["Survived"], cv=kf)
print("再次利用随机森林模型的准确率:" + str(scores.mean()))

八、集成多个算法

from sklearn.ensemble import GradientBoostingClassifier
import numpy as np

algorithms = [
    [GradientBoostingClassifier(random_state=1, n_estimators=45, max_depth=6), ['Pclass','Sex','Age','SibSp','Parch','Fare','Embarked','FamilySize','NameLength','Title']],
    [LogisticRegression(random_state=1, solver='liblinear'), ['Pclass','Sex','Age','SibSp','Parch','Fare','Embarked','FamilySize','NameLength','Title']]
]

kf = KFold(n_splits=3, random_state=1)

predictions = []

for train, test in kf.split(titanic):
    train_target = titanic["Survived"].iloc[train]
    full_test_predictions = []

    for alg, predictors in algorithms:
        alg.fit(titanic[predictors].iloc[train,:], train_target)
        test_predictions = alg.predict_proba(titanic[predictors].iloc[test,:].astype(float))[:,1]
        full_test_predictions.append(test_predictions)

    test_predictions = (full_test_predictions[0] + full_test_predictions[1]) / 2

    test_predictions[test_predictions <= 0.5] = 0
    test_predictions[test_predictions > 0.5] = 1
    predictions.append(test_predictions)

predictions = np.concatenate(predictions, axis=0)

accuracy = sum(predictions == titanic["Survived"]) / len(predictions)
print("准确率为:", accuracy)

在这里插入图片描述


参考资料:天善智能云课堂Python机器学习Kaggle案例

发布了75 篇原创文章 · 获赞 267 · 访问量 5202

猜你喜欢

转载自blog.csdn.net/weixin_45961774/article/details/104934979