Titanic 泰坦尼克数据集 特征工程 机器学习建模

这篇具有很好参考价值的文章主要介绍了Titanic 泰坦尼克数据集 特征工程 机器学习建模。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

以下内容为讲课时使用到的泰坦尼克数据集分析、建模过程,整体比较完整,分享出来,希望能帮助大家。部分内容由于版本问题,可能无法顺利运行。

Table of Contents

1  经典又有趣的 Titanic问题
1.1  目标
1.2  解决方法
1.3  项目目的
2  导入模块
3  加载数据
4  探索性数据分析
4.1  描述性统计分析
4.1.1  了解数据集的总体情况
4.1.2  预览数据
4.1.3  了解数据的中心趋势和离散趋势
4.1.4  特征间相关性的热图
4.2  提出假设
4.3  关联性分析与数据可视化
4.3.1  Survived与每个特征
4.3.1.1  没有缺失值的特征
4.3.1.2  有缺失值的特征
4.3.2  Survived与多个特征
4.3.2.1  数值型特征、定序特征与Survived之间的关系——Pclass、Age&Survived
4.3.2.2  多个分类特征与Survived之间的关系——Sex、Embarked、Pclass&Survived
4.3.2.3  多个分类特征和数值特征与Survived之间的关系——Sex, Fare,Embarked&Survived
4.3.3  总结
5  数据预处理
5.1  删除特征
5.2  填补缺失值
5.2.1  连续型数值特征
5.2.1.1  Age
5.2.1.2  Fare
5.2.2  分类特征——Embarked
5.3  特征提取
5.3.1  从已有特征中提取新特征——Name提取Title
5.3.2  特征组合创建新特征
5.3.3  交叉特征
5.4  特征缩放
5.5  特征因子化/one-hot编码
5.5.1  什么是one-hot编码
5.5.2  one-hot编码必要性
5.5.3  连续特征离散化
6  逻辑回归
6.1  模型系数分析
6.2  逻辑回归优化
6.2.1  交叉验证
6.2.1.1  常见类型的交叉验证
6.2.1.2  训练集和测试集的选取
6.2.2  模型状态判断(欠拟合or过拟合)
6.2.2.1  什么是欠拟合/过拟合
6.2.2.2  如何处理过拟合
6.2.2.3  如何处理欠拟合
6.2.2.4  如何判断模型状态
6.2.3  模型融合
6.2.3.1  什么是模型融合
6.2.3.2  模型融合的作用
6.3  其他算法实现
6.3.1  可以解决问题的算法
6.3.2  随机森林算法的特征工程
6.3.3  模型部分的代码实现参考
7  模型比较
8  输出预测结果
9  总结
10  参考资料

经典又有趣的Titanic问题

目标

【Jack and Rose】的故事大家都熟悉,然而今天,我们要探讨的问题是我们该如何预测豪华游轮上的乘客的存活状况。也就是说,我们要利用已有的训练和测试数据,其中包含一些乘客的个人信息及存活状况,利用这些信息,生成合适的模型,最终去预测其他人的存活状况。

解决方法

这是一个二分类问题,有很多分类算法都可以用来解决这个问题。我们希望:

  1. 同学们先从最简单最基础的逻辑回归模型入手,实现逻辑回归算法。
  2. 再利用其他算法来解决这个问题,进行模型比较或者模型融合,最终给出一个最优的解决方案。

项目目的

通过完成这个项目,我们希望同学们可以学习到:

  1. 在本地电脑上,完成机器学习建模的的基本流程。
  2. 能够使用逻辑回归来解决二分类问题。
  3. 能够运用其他已学习过的分类算法来解决分类问题,进一步理解分类算法。
  4. 理解并能够运用常用技巧来提高模型的预测准确性。
  5. 实现你的第一个神经网络。

导入模块

# 进行数据分析和整合数据
import pandas as pd
import numpy as np
import random as rnd

# 用于数据可视化
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline

# 使用机器学习算法进行建模
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC, LinearSVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import Perceptron
from sklearn.linear_model import SGDClassifier
from sklearn.tree import DecisionTreeClassifier

加载数据

八卦一句,有人的地方就有鄙视链。跟知乎一样。Kaggle的也是个处处呵呵的危险地带。Kaggle上默认把数据放在input文件夹下。所以我们没事儿写个教程什么的,也可以依据这个convention来,显得很入流。

# 使用Pandas分别加载训练数据和测试数据
train_df = pd.read_csv('../input/train.csv')
test_df = pd.read_csv('../input/test.csv')
# 将训练集和测试集合并
combine = [train_df, test_df]

已给的数据描述:

PassengerId/乘客ID

Survived/是否获救 ==> 0/否, 1/是

Pclass/船票等级 ==> 1/上等, 2/中等, 3/下等

Name/乘客姓名

Sex/乘客性别

Age/乘客年龄

SibSp/乘客的堂兄弟或堂妹或配偶的个数

Parch/父母与小孩个数

Ticket/船票号码

Fare/乘客的船票票价

Cabin/客舱号码

Embarked/登船港口 ==> C/Cherbourg, Q/Queenstown, S/Southampton

探索性数据分析

描述性统计分析

了解数据集的总体情况

  • 说明:本章节需要回答的问题中,会涉及到一些统计学的专业术语,如果对于术语概念不了解的,推荐大家先阅读相关书籍的介绍,对统计术语理解后,然后再进行回答。
  • 推荐书目
    1. 数据挖掘
    2. 深入浅出统计学
# 显示训练集和测试集总体信息
train_df.info()
print ("#"*40)
test_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
########################################
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 418 entries, 0 to 417
Data columns (total 11 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  418 non-null    int64  
 1   Pclass       418 non-null    int64  
 2   Name         418 non-null    object 
 3   Sex          418 non-null    object 
 4   Age          332 non-null    float64
 5   SibSp        418 non-null    int64  
 6   Parch        418 non-null    int64  
 7   Ticket       418 non-null    object 
 8   Fare         417 non-null    float64
 9   Cabin        91 non-null     object 
 10  Embarked     418 non-null    object 
dtypes: float64(2), int64(4), object(5)
memory usage: 36.0+ KB
# 显示train_df/test_df列数据类型
train_df.dtypes,test_df.dtypes
(PassengerId      int64
 Survived         int64
 Pclass           int64
 Name            object
 Sex             object
 Age            float64
 SibSp            int64
 Parch            int64
 Ticket          object
 Fare           float64
 Cabin           object
 Embarked        object
 dtype: object,
 PassengerId      int64
 Pclass           int64
 Name            object
 Sex             object
 Age            float64
 SibSp            int64
 Parch            int64
 Ticket          object
 Fare           float64
 Cabin           object
 Embarked        object
 dtype: object)
# 显示train_df和test_df的行数和特征数量
train_df.shape,test_df.shape
((891, 12), (418, 11))
# 打印训练集和测试集中所有特征列的名称
print(train_df.columns.values)
print("#"*40)
print(test_df.columns.values)
['PassengerId' 'Survived' 'Pclass' 'Name' 'Sex' 'Age' 'SibSp' 'Parch'
 'Ticket' 'Fare' 'Cabin' 'Embarked']
########################################
['PassengerId' 'Pclass' 'Name' 'Sex' 'Age' 'SibSp' 'Parch' 'Ticket' 'Fare'
 'Cabin' 'Embarked']

问题1:特征在python中的数据类型和数据集基本信息

  1. 训练集中,哪些特征在python中的数据类型为interger或者floats?
    PassengerId,Survived,Pclass,Age,SibSp,Parch,Fare
  2. 训练集中,哪些特征在python中数据类型为Object?
    Name,Sex,Ticket,Cabin,Embarked
  3. 训练集中,特征___、___、___有缺失值,测试机中特征___、___、___有缺失值?
    Age,Cabin,Embarked; Age,Fare,Cabin
  4. 训练集中,总共有___名乘客的记录,___个特征?
    891, 12
  5. 测试集中,总共有___名乘客的记录,___个特征?
    418, 11
  6. 测试集与训练集相比,缺少特征___?
    Survived
  7. 泰坦尼克号上,实际总共有2224人登船,测试集和训练集的样本分别约占总人数的___%,___%(保留整数)?
    40,19

预览数据

对于大数据集,我们很难去查看所有的数据记录,然而,我们可以查看其中的多个小样本来了解数据。这些样本可以直接告诉我们哪些特征是需要修正的。

# 显示数据集前5行的记录
train_df.head() 
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
# 显示训练集最后5行的记录
train_df.tail()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
886 887 0 2 Montvila, Rev. Juozas male 27.0 0 0 211536 13.00 NaN S
887 888 1 1 Graham, Miss. Margaret Edith female 19.0 0 0 112053 30.00 B42 S
888 889 0 3 Johnston, Miss. Catherine Helen "Carrie" female NaN 1 2 W./C. 6607 23.45 NaN S
889 890 1 1 Behr, Mr. Karl Howell male 26.0 0 0 111369 30.00 C148 C
890 891 0 3 Dooley, Mr. Patrick male 32.0 0 0 370376 7.75 NaN Q

问题2:特征类型

  1. 特征___是数值和字母数字混合型的数据?
    Ticket
  2. 特征___是字母数字型数据?
    Cabin
  3. 特征___有可能包含错误或者拼写错误?
    Name

    提示:Name特征中包含title信息,如Mr.,Miss等,包含括号信息,包含双引号信息。
  4. 哪些是分类特征?
    Survived, Sex, Embarked, Pclass
  5. 哪些分类特征是二分类型?
    Survived, Sex
  6. 哪些分类特征是定序类型?
    Pclass
  7. 哪些是数值特征?
    Age, Fare, SibSp, Parch
  8. 哪些数值特征是连续型特征?
    Age, Fare
  9. 哪些数值特征是离散型特征?
    SibSp, Parch

了解数据的中心趋势和离散趋势

# python中数据类型为float64和int64的特征信息
train_df.describe()
PassengerId Survived Pclass Age SibSp Parch Fare
count 891.000000 891.000000 891.000000 714.000000 891.000000 891.000000 891.000000
mean 446.000000 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208
std 257.353842 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429
min 1.000000 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000
25% 223.500000 0.000000 2.000000 20.125000 0.000000 0.000000 7.910400
50% 446.000000 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200
75% 668.500000 1.000000 3.000000 38.000000 1.000000 0.000000 31.000000
max 891.000000 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200
# 查看train_df不同特征的分位数,以确定不同特征的分布情况
train_df['Survived'].quantile([.61, .62])
train_df['Parch'].quantile([.75, .8])
train_df['Age'].quantile([.1, .2, .3, .4, .5, .6, .7, .8, .9, .99])
train_df['Fare'].quantile([.1, .2, .3, .4, .5, .6, .7, .8, .9, .99])
0.10      7.55000
0.20      7.85420
0.30      8.05000
0.40     10.50000
0.50     14.45420
0.60     21.67920
0.70     27.00000
0.80     39.68750
0.90     77.95830
0.99    249.00622
Name: Fare, dtype: float64

问题3:统计指标与信息


统计意义上:

  1. 以上指标中,可以用于度量中心趋势的有___?
    mean/均值
  2. 以上指标中,可以用于度量离散趋势的有___?
    std/标准差,极差(min最小值,max最大值),四分位数(25%,50%,75%)

    说明:当我们不把50%与25%和75%组合在一起作为四分位数时,而是把它看成一个单独的值时,它实际为中心趋势度量指标的中位数,我们可以通过这个数值来判断特征的大致分布情况。
  3. 训练集中,有___%的人获救了(保留整数)?
    38
  4. 特征Survived的取值为___和___?
    0,1
  5. 训练集中,三种船票等级中人数最多的是___?
    3
  6. 忽略掉空值,训练集中乘客的平均年龄为___岁(保留一位小数)?
    29.7
  7. 训练集中,特征Parch在75%的位置值为0,说明?
    训练集中,75%以上的乘客没有和家人或者孩子一起出行。
  8. 约有___%的乘客有兄弟姐妹或伴侣一起登船(保留整数)?
    30
  9. 票价为$512的乘客小于___%?
    1
  10. 年龄在65-80岁的乘客小于___%?
    1
# python中数据类型为object的特征信息
train_df.describe(include=['O'])
Name Sex Ticket Cabin Embarked
count 891 891 891 204 889
unique 891 2 681 147 3
top Braund, Mr. Owen Harris male 347082 B96 B98 S
freq 1 577 7 4 644

问题4:区分特征

统计意义上(注意不是以Python中的数据类型来定义的):

  1. 哪些是分类特征? Survived, Sex, Embarked, Pclass
  2. 哪些分类特征是二分类型? Survived, Sex
  3. 哪些分类特征是定序类型? Pclass
  4. 哪些是数值特征? Age, Fare, SibSp, Parch
  5. 哪些数值特征是连续型特征? Age, Fare
  6. 哪些数值特征是离散型特征? SibSp, Parch

特征间相关性的热图

特征间相关性的热图可以帮助我们了解哪些变量可能更重要。

# 定义特征间相关性热图函数,查看变量之间的相关性大小
def plot_correlation_map(df):
    corr = df.corr() # 查看的是train_df的特征间相关性
    _ , ax = plt.subplots(figsize = (10,8))
    cmap = sns.diverging_palette(220,10,as_cmap = True)
    _ = sns.heatmap(
        corr, 
        cmap = cmap,
        square=True, 
        cbar_kws={'shrink':.9}, 
        ax=ax, 
        annot = True, 
        annot_kws = {'fontsize':12}
    )
plot_correlation_map(train_df)

titanic数据集中的以下哪个特征属于排序型数据( ),机器学习,python,数据挖掘,人工智能,算法

问题5:特征相关性

  1. 从热图中你能了解到哪些信息?

    提示

    1) 所有特征与Survived之间的相关性:
    与其他特征相比,Fare,Pclass与Survived相关性较大。Fare与Survived负相关,Pclass与Survived正相关。

    2) 除Survived之外,特征之间的相关性特点:
    特征之间相关性较强:Age与Pclass负相关,Sibsp与Age负相关,Parch与Sibsp正相关,Fare与Parch正相关。

提出假设

问题6:你想到了哪些可能性?

根据目前我们已经完成的【描述性统计分析】部分提供给我们的信息,我们可以提出以下假设:

  • 相关性

    了解所有特征与要预测的特征Survival/是否获救之间的关系。
  • 处理缺失值
    1. 我们需要Age特征,它可能与Survived相关。
    2. 我们需要Fare特征,它可能与Survived相关。
    3. 我们需要Embarked特征,因为它可能与Survived或其他重要特征相关。
  • 数据修正
    1. Ticket/船票号码特征有可能会被删掉,因为它有22%的比例为重复值,它可能和Survival之间不相关。
    2. Cabin/客舱号码特征有可能会被删掉,因为它在训练集和测试集的缺失值都很多。
    3. PassengerId特征有可能删除,有可能和Survival无关。
    4. Name特征是一个不太能够标准化的特征,它可能和Survival没有直接关系,可能会被删掉。
  • 特征提取
    1. 基于Parch和SibSp创造一个新特征Family,表示登船的家庭成员的数量。
    2. 基于Name,提取出新特征Title。
    3. Age离散化处理:基于Age,新建Ageband,将Age转变为分类特征。
    4. Fare离散化处理:基于Fare,新建FareBand,将Fare转变成分类特征。
  • 猜想
    1. 女性(Sex=female)有更大可能性获救。
    2. 儿童(Age<?)有更大可能性获救。
    3. 上等舱位乘客更有可能获救。
    4. 船票价格高的乘客更有可能获救。

【描述性统计分析】部分提供的信息,只是帮助我们对数据集的总体情况有一个初步的了解,但是对于最终建模和预测结果的帮助非常有限。接下来让我们从其他唯独来详细分析一下数据,探索每个/多个特征与Survived之间的关系,进一步验证自己提出的假设。

关联性分析与数据可视化

接下来,我们将通过关联性分析和数据可视化的方法开始验证以上相关假设。

Survived与每个特征

没有缺失值的特征

Ticket是船票编号,PassengerId是乘客ID和Survived没有太大的关系,不纳入我们的考虑范围。


Sex,Pclass,SibSp和Parch这四个特征没有缺失值,并且对于他们的探索不需要对数据进行处理,所以我们首先来探索这四个特征与Survived之间的关系。


结论:

  • Pclass=1和Survived显著相关(>0.5) ==> 猜想#3 ==> Pclass特征将被保留。
  • Sex=female的存活率在74% ==> 猜想#1
  • SibSp和Parch特征中有些值和Survived无关 ==> 我们可能需要利用这两个特征构造出一个新特征 ==> 特征提取#1
# Pclass与Survived
train_df[['Pclass', 'Survived']].groupby(['Pclass'], as_index=False).mean().sort_values(by='Survived', ascending=False)
Pclass Survived
0 1 0.629630
1 2 0.472826
2 3 0.242363
# Sex与Survived
train_df[["Sex", "Survived"]].groupby(['Sex'], as_index=False).mean().sort_values(by='Survived', ascending=False)
Sex Survived
0 female 0.742038
1 male 0.188908
# SibSp与Survived
train_df[["SibSp", "Survived"]].groupby(['SibSp'], as_index=False).mean().sort_values(by='Survived', ascending=False)
SibSp Survived
1 1 0.535885
2 2 0.464286
0 0 0.345395
3 3 0.250000
4 4 0.166667
5 5 0.000000
6 8 0.000000
# Parch与Survived
train_df[["Parch", "Survived"]].groupby(['Parch'], as_index=False).mean().sort_values(by='Survived', ascending=False)
Parch Survived
3 3 0.600000
1 1 0.550847
2 2 0.500000
0 0 0.343658
5 5 0.200000
4 4 0.000000
6 6 0.000000
有缺失值的特征

Age与Survived

直方图对于分析连续型特征是非常有帮助的:

  1. 发现特征变化的特点或模式。
    我们可以通过将Age特征的取值分割成多个等长度的连续区间,来观察Age的变化特点或模式。
  2. 可以使用自定义的宽度相等的条纹来说明样本的分布。
    可以帮助我们回答需要自定义特定条纹宽度才能确定的问题。例如,针对这个数据集,我们可以自定义宽度来回答是否幼儿更容易获救这个问题。

备注: Y轴表示乘客的人数

问题7:关于Age特征,你有什么发现或结论?


观察发现

  • 婴儿(Age<=4)的存活率较高
  • 老人(Age=80)都存活下来了
  • 大部分15-25岁的人没有存活
  • 大多数乘客的年龄在15-35岁

结论

  • 我们应该把Age特征放到训练模型中 ==> 猜想#2
  • 需要给Age进行缺失值填充处理 ==> 处理缺失值#1
  • 应该对Age进行分组处理 ==> 特征提取#3
# Age与Survived
g = sns.FacetGrid(train_df, col='Survived')
g.map(plt.hist, 'Age', bins=20) # 年龄每4岁进行分割

titanic数据集中的以下哪个特征属于排序型数据( ),机器学习,python,数据挖掘,人工智能,算法

Fare与Survived

问题8:关于Fare特征,你有什么发现或结论?


观察发现

  • 票价更高的人更有可能生存(Fare>50区间尤其明显)

结论

  • 我们应该把Fare特征放到训练模型中 ==> 猜想#4
# Fare与Survived
g = sns.FacetGrid(train_df, col='Survived')
g.map(plt.hist, 'Fare', bins=30) 

titanic数据集中的以下哪个特征属于排序型数据( ),机器学习,python,数据挖掘,人工智能,算法

Survived与多个特征

数值型特征、定序特征与Survived之间的关系——Pclass、Age&Survived

我们可以通过一幅图来探索多个特征之间的相关性,但是不管是数值特征还是分类特征,它们的取值必须都是数值,不能是字符串。

问题9:Pclass、Age和Survived之间,你有什么发现或结论?


观察发现

  • Pclass=3的乘客最多,但是大部分都是没有获救 ==> 猜想#3
  • Pclass=2和Pclass=3中的幼儿大部分都获救了==> 进一步验证了猜想#2
  • Pclass=1中的大部分乘客都获救了 ==> 证实猜想#3
  • Pclass因乘客的年龄分布而变化。

结论:
考虑将Pclass放入模型训练。

# grid = sns.FacetGrid(train_df, col='Pclass', hue='Survived')
grid = sns.FacetGrid(train_df, col='Survived', row='Pclass', size=2.2, aspect=1.6)
grid.map(plt.hist, 'Age', alpha=.5, bins=20) 
grid.add_legend();

titanic数据集中的以下哪个特征属于排序型数据( ),机器学习,python,数据挖掘,人工智能,算法

多个分类特征与Survived之间的关系——Sex、Embarked、Pclass&Survived

接下来,我们来探索多个分类特征与Survived之间的关系。
问题10:Sex、Embarked、Pclass和Survived之间,你有什么发现或结论?


观察发现:

  • 女性乘客的获救的可能性高于男性 ==> 猜想#1
  • 只有Embarked=C时,男性获救的可能性高于女性。 ==> 这可能是因为Embarked与Pclass相关,进而Pclass与Survived相关,即Embarked与Survived之间不直接相关。
  • 与Pclass=2,Embarked为C和Q的情况相比,Pclass=3中,男性存活率更高。 ==> 处理缺失值#2
  • 登船港口的不同对Pclass=3和男乘客的存活率有影响。

结论:

  • Sex放入模型训练。
  • 修正Embarked特征,并将其放入模型训练。
# grid = sns.FacetGrid(train_df, col='Embarked')
grid = sns.FacetGrid(train_df, row='Embarked', size=2.2, aspect=1.6)
grid.map(sns.pointplot, 'Pclass', 'Survived', 'Sex', palette='deep')
grid.add_legend()

titanic数据集中的以下哪个特征属于排序型数据( ),机器学习,python,数据挖掘,人工智能,算法

多个分类特征和数值特征与Survived之间的关系——Sex, Fare,Embarked&Survived

问题11:Sex, Fare,Embarked和Survived之间,你有什么发现或结论?

观察发现:

  • 购买票价贵的乘客更有可能获救 ==> 特征提取#4
  • 登船港口不同与存活率有关 ==> 处理缺失值#2

结论:后续需要对Fare进行离散化处理。

# grid = sns.FacetGrid(train_df, col='Embarked', hue='Survived', palette={0: 'k', 1: 'w'})
grid = sns.FacetGrid(train_df, row='Embarked', col='Survived', size=2.2, aspect=1.6)
grid.map(sns.barplot, 'Sex', 'Fare', alpha=.5, ci=None)
grid.add_legend()

titanic数据集中的以下哪个特征属于排序型数据( ),机器学习,python,数据挖掘,人工智能,算法

总结

通过关联性分析和数据可视化的方式对数据进行分析,验证了我们最初提出的假设,这些结论将作为我们下一步工作流程的起点。

数据预处理

基于关联性分析和数据可视化为我们提供的信息,下一步,我们将对特征进行处理相应的处理,最终将每个特征符合放入逻辑回归中特征的要求。
注意:

  1. 我们要对训练集和测试集进行相同的处理,以保持数据一致性。

    在这个参考代码中,我们将测试集和训练集同时进行处理,也可以先处理训练集,然后再处理测试集。
  2. 如果同学们对这个课件中的不同特征的处理方法有自己的看法,可以按照自己的想法处理。我们只是提供整体思路,希望同学们可以得到更好的预测结果。

删除特征

基于最初的假设,我们将删掉Ticket和Cabin特征。

# 删除前的每个df的结构
print("Before", train_df.shape, test_df.shape, combine[0].shape, combine[1].shape)

train_df = train_df.drop(['Ticket','Cabin'], axis=1)
test_df = test_df.drop(['Ticket', 'Cabin'], axis=1)
combine = [train_df, test_df]

# 删除后的每个df的结构
print("After", train_df.shape, test_df.shape, combine[0].shape, combine[1].shape)
Before (891, 12) (418, 11) (891, 12) (418, 11)


('After', (891, 10), (418, 9), (891, 10), (418, 9))

填补缺失值

通常遇到缺值的情况,我们会有几种常见的处理方式:

  1. 如果缺失值的样本占总数比例极高,我们可能就直接舍弃了,作为特征加入的话,可能反倒带入noise,影响最后的结果了。
  2. 如果缺失值的样本适中,而该属性非连续值特征属性(比如说类目属性),那就把NaN作为一个新类别,加到类别特征中。
  3. 如果缺失值的样本适中,而该属性为连续值特征属性,有时候我们会考虑给定一个步长(比如这里的age,我们可以考虑每隔2/3岁为一个步长),然后把它离散化,之后把NaN作为一个type加到属性类目中。
  4. 有些情况下,缺失的值个数并不是特别多,那我们也可以试着根据已有的值,拟合一下数据,补充上。

连续型数值特征

Age

针对这个数据集,第3和4中处理方式应该都是可行的。我们先尝试拟合补全缺失值,虽然这可能并不是一个很好的选择,因为没有太多背景信息来支持拟合,我们只好先试试看。同学们可以自行尝试使用第3种方法来实现对缺失值的处理,并带入模型对比不同方法对模型的影响。


针对拟合补全Age缺失值的处理方法,我们提供两种思路。

思路1:利用需要填补缺失值的特征和其他与之存在相关关系的特征这一特点来填补缺失值。


在这个数据集中,我们已经发现Age,Sex和Pclass三个特征之间是相关的。因此,我们可以利用Sex和Pclass的组合特征来找到这个组合特征下Age上午中位数,用这个中位数来填补缺失值。即我们需要找到Pclass=1和Sex=0时Age的中位数,用这个中位数去填补Pclass=1和Sex=0时,有缺失值的Age。Sex和Pclass共有6中组合,因此,我们需要找到6个中位数去分别填补对应情况下Age的缺失值。

# 建立一个空的数组来存放基于Pclass和Gender组合信息来猜测Age的值
guess_ages = np.zeros((2,3))
guess_ages
array([[0., 0., 0.],
       [0., 0., 0.]])
# 将Sex转变值为0,1的变量。
for dataset in combine:
    dataset['Sex'] = dataset['Sex'].map( {'female': 1, 'male': 0} ).astype(int)
# 循环Sex(0, 1)和Pclass(1, 2, 3)来猜测Age的值,共有6中组合
for dataset in combine:
    for i in range(0, 2):
        for j in range(0, 3):
            guess_df = dataset[(dataset['Sex'] == i) & \
                                  (dataset['Pclass'] == j+1)]['Age'].dropna()

            # age_mean = guess_df.mean()
            # age_std = guess_df.std()
            # age_guess = rnd.uniform(age_mean - age_std, age_mean + age_std)

            age_guess = guess_df.median()

            # 将age_guess的值近似为最近的整数
            guess_ages[i,j] = int( age_guess/0.5 + 0.5 ) * 0.5
            
    for i in range(0, 2):
        for j in range(0, 3):
            dataset.loc[ (dataset.Age.isnull()) & (dataset.Sex == i) & (dataset.Pclass == j+1),\
                    'Age'] = guess_ages[i,j]

    dataset['Age'] = dataset['Age'].astype(int)

train_df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Fare Embarked
0 1 0 3 Braund, Mr. Owen Harris 0 22 1 0 7.2500 S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 1 38 1 0 71.2833 C
2 3 1 3 Heikkinen, Miss. Laina 1 26 0 0 7.9250 S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 1 35 1 0 53.1000 S
4 5 0 3 Allen, Mr. William Henry 0 35 0 0 8.0500 S

连续型数值特征常常需要被离散化或面元(bin)划分,使用pandas库中的cut函数实现。

说明:详见5.5.3 连续特征离散化

# 创建AgeBand
train_df['AgeBand'] = pd.cut(train_df['Age'], 5)
train_df[['AgeBand', 'Survived']].groupby(['AgeBand'], as_index=False).mean().sort_values(by='AgeBand', ascending=True)
AgeBand Survived
0 (-0.08, 16.0] 0.550000
1 (16.0, 32.0] 0.337374
2 (32.0, 48.0] 0.412037
3 (48.0, 64.0] 0.434783
4 (64.0, 80.0] 0.090909
# 根据AgeBand提供的区间切分信息,对Age进行分组处理
for dataset in combine:    
    dataset.loc[ dataset['Age'] <= 16, 'Age'] = 0
    dataset.loc[(dataset['Age'] > 16) & (dataset['Age'] <= 32), 'Age'] = 1
    dataset.loc[(dataset['Age'] > 32) & (dataset['Age'] <= 48), 'Age'] = 2
    dataset.loc[(dataset['Age'] > 48) & (dataset['Age'] <= 64), 'Age'] = 3
    dataset.loc[ dataset['Age'] > 64, 'Age'] = 4
train_df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Fare Embarked AgeBand
0 1 0 3 Braund, Mr. Owen Harris 0 1 1 0 7.2500 S (16.0, 32.0]
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 1 2 1 0 71.2833 C (32.0, 48.0]
2 3 1 3 Heikkinen, Miss. Laina 1 1 0 0 7.9250 S (16.0, 32.0]
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 1 2 1 0 53.1000 S (32.0, 48.0]
4 5 0 3 Allen, Mr. William Henry 0 2 0 0 8.0500 S (32.0, 48.0]
# 删掉AgeBand,更新combine
train_df = train_df.drop(['AgeBand'], axis=1)
combine = [train_df, test_df]
train_df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Fare Embarked
0 1 0 3 Braund, Mr. Owen Harris 0 1 1 0 7.2500 S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 1 2 1 0 71.2833 C
2 3 1 3 Heikkinen, Miss. Laina 1 1 0 0 7.9250 S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 1 2 1 0 53.1000 S
4 5 0 3 Allen, Mr. William Henry 0 2 0 0 8.0500 S

思路2:使用scikit-learn中的RandomForest来拟合Age的缺失值。

注意:使用思路1方法处理完数据后,不能直接使用下面的代码会报错误,因为:

  1. Parch和SibSp特征已经被删除。
  2. Age特征已经被思路1的方法修改了,原始值已经被改变。
# # 使用RandomForestClassifier填补年龄的缺失值
# from sklearn.ensemble import RandomForestRegressor
# def set_missing_ages(df):
    
#     # 把已有的数值型特征取出来丢进Random Forest Regressor中
#     age_df = df[['Age','Fare', 'Parch', 'SibSp', 'Pclass']]

#     # 乘客分成已知年龄和未知年龄两部分
#     known_age = age_df[age_df.Age.notnull()].values
#     unknown_age = age_df[age_df.Age.isnull()].values
    
#     print(unknown_age)
#     # y即目标年龄
#     y = known_age[:, 0]

#     # X即特征属性值
#     X = known_age[:, 1:]

#     # fit到RandomForestRegressor之中
#     rfr = RandomForestRegressor(random_state=0, n_estimators=2000, n_jobs=-1)
#     rfr.fit(X, y)
    
#     # 用得到的模型进行未知年龄结果预测
#     predictedAges = rfr.predict(unknown_age[:, 1::])
    
#     # 用得到的预测结果填补原缺失数据
#     df.loc[ (df.Age.isnull()), 'Age' ] = predictedAges
    
#     return df, rfr

# # 处理训练集Age特征
# train_df, rfr = set_missing_ages(train_df)
# train_df.head(10)
Fare

对测试集中的Fare特征进行处理。


处理步骤

  1. 填补缺失值:使用Fare的中位数去填补缺失值。
  2. 离散化
  3. 保留两位小数,因为Fare代表货币。
# 使用中位数测试集中的Fare的空值进行填充
test_df['Fare'].fillna(test_df['Fare'].dropna().median(), inplace=True)
test_df.head()
PassengerId Pclass Name Sex Age SibSp Parch Fare Embarked
0 892 3 Kelly, Mr. James 0 2 0 0 7.8292 Q
1 893 3 Wilkes, Mrs. James (Ellen Needs) 1 2 1 0 7.0000 S
2 894 2 Myles, Mr. Thomas Francis 0 3 0 0 9.6875 Q
3 895 3 Wirz, Mr. Albert 0 1 0 0 8.6625 S
4 896 3 Hirvonen, Mrs. Alexander (Helga E Lindqvist) 1 1 1 1 12.2875 S
# 创造FareBand特征
train_df['FareBand'] = pd.qcut(train_df['Fare'], 4) # 分成4份
train_df[['FareBand', 'Survived']].groupby(['FareBand'], as_index=False).mean().sort_values(by='FareBand', ascending=True)
FareBand Survived
0 (-0.001, 7.91] 0.197309
1 (7.91, 14.454] 0.303571
2 (14.454, 31.0] 0.454955
3 (31.0, 512.329] 0.581081
# 基于FareBand将Fare转变为定序特征
for dataset in combine:
    dataset.loc[ dataset['Fare'] <= 7.91, 'Fare'] = 0
    dataset.loc[(dataset['Fare'] > 7.91) & (dataset['Fare'] <= 14.454), 'Fare'] = 1
    dataset.loc[(dataset['Fare'] > 14.454) & (dataset['Fare'] <= 31), 'Fare']   = 2
    dataset.loc[ dataset['Fare'] > 31, 'Fare'] = 3
    dataset['Fare'] = dataset['Fare'].astype(int)

# 删掉FareBand
train_df = train_df.drop(['FareBand'], axis=1)
combine = [train_df, test_df]
    
train_df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Fare Embarked
0 1 0 3 Braund, Mr. Owen Harris 0 1 1 0 0 S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 1 2 1 0 3 C
2 3 1 3 Heikkinen, Miss. Laina 1 1 0 0 1 S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 1 2 1 0 3 S
4 5 0 3 Allen, Mr. William Henry 0 2 0 0 1 S

分类特征——Embarked

训练集中Embarked特征有两个缺失值,我们现在用Embarked的众数去填补缺失值。

# 查看非空Embarked特征的众数
freq_port = train_df.Embarked.dropna().mode()[0]
freq_port
'S'
# 将使用众数对Embarked的空值进行填充
for dataset in combine:
    dataset['Embarked'] = dataset['Embarked'].fillna(freq_port)
    
train_df[['Embarked', 'Survived']].groupby(['Embarked'], as_index=False).mean().sort_values(by='Survived', ascending=False)
Embarked Survived
0 C 0.553571
1 Q 0.389610
2 S 0.339009
# 转变成数值特征
for dataset in combine:
    dataset['Embarked'] = dataset['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)

train_df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Fare Embarked
0 1 0 3 Braund, Mr. Owen Harris 0 1 1 0 0 0
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 1 2 1 0 3 1
2 3 1 3 Heikkinen, Miss. Laina 1 1 0 0 1 0
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 1 2 1 0 3 0
4 5 0 3 Allen, Mr. William Henry 0 2 0 0 1 0

特征提取

从已有特征中提取新特征——Name提取Title

我们想分析Name特征是否能够提取title信息,并验证title与Survived之间的相关性。

观察发现
当我们绘制称呼、年龄和Survived时,我们注意到以下几点:

  • 多数称呼与年龄段相对应,例如:称呼为master的人,平均年龄为5岁。
  • 称呼年龄段的存活率略有差别。
  • 称呼为Mme,Lady和Sir的人更有可能获救,称呼为Don,Rev和Jonkheer的人获救的可能性很低。

结论: 保留Title特征,放入模型进行训练。

# 通过正则表达式提取所有title字符串
# ([A-Za-z]+)\. 匹配符号“.”之前第一个单词
for dataset in combine:
    dataset['Title'] = dataset.Name.str.extract('([A-Za-z]+)\.', expand=False) # expand=False返回一个DataFrame
# 交叉表查看提取出的title与sex关系
pd.crosstab(train_df['Title'], train_df['Sex'])
Sex 0 1
Title
Capt 1 0
Col 2 0
Countess 0 1
Don 1 0
Dr 6 1
Jonkheer 1 0
Lady 0 1
Major 2 0
Master 40 0
Miss 0 182
Mlle 0 2
Mme 0 1
Mr 517 0
Mrs 0 125
Ms 0 1
Rev 6 0
Sir 1 0
# 交叉表查看提取出的title与Survived关系
pd.crosstab(train_df['Title'], train_df['Survived'])
Survived 0 1
Title
Capt 1 0
Col 1 1
Countess 0 1
Don 1 0
Dr 4 3
Jonkheer 1 0
Lady 0 1
Major 1 1
Master 17 23
Miss 55 127
Mlle 0 2
Mme 0 1
Mr 436 81
Mrs 26 99
Ms 0 1
Rev 6 0
Sir 0 1
# 将有相同title的文本进行替换,或者归为Rare类
# 对于当时外国称呼的说明,可以参考:https://zhidao.baidu.com/question/591037721.html
for dataset in combine:
    dataset['Title'] = dataset['Title'].replace(['Lady' ,'Capt', 'Col',\
 	'Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')

    dataset['Title'] = dataset['Title'].replace(['Mlle', 'Ms'], 'Miss')
    dataset['Title'] = dataset['Title'].replace(['Mme','Countess'], 'Mrs') 
    
train_df[['Title', 'Survived']].groupby(['Title'], as_index=False).mean()
Title Survived
0 Master 0.575000
1 Miss 0.702703
2 Mr 0.156673
3 Mrs 0.795276
4 Rare 0.318182
# 对应分类
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
for dataset in combine:
    dataset['Title'] = dataset['Title'].map(title_mapping)
    dataset['Title'] = dataset['Title'].fillna(0)

train_df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Fare Embarked Title
0 1 0 3 Braund, Mr. Owen Harris 0 1 1 0 0 0 1
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 1 2 1 0 3 1 3
2 3 1 3 Heikkinen, Miss. Laina 1 1 0 0 1 0 2
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 1 2 1 0 3 0 3
4 5 0 3 Allen, Mr. William Henry 0 2 0 0 1 0 1
# 在训练集和测试集中都删除Name,把PassengerId从训练集中删除
train_df = train_df.drop(['Name'], axis=1)
test_df = test_df.drop(['Name'], axis=1)
combine = [train_df, test_df]
train_df.shape, test_df.shape
((891, 10), (418, 9))

特征组合创建新特征

我们可以将Parch和SibSp组合获得新特征FamilySize,我们发现FamilySize中有两个取值Survived取值为零。进而创建新特征IsAlone,判断乘客是否是一个登船。

# 组合Parch和SibSp特征创建FamilySize
for dataset in combine:
    dataset['FamilySize'] = dataset['SibSp'] + dataset['Parch'] + 1

train_df[['FamilySize', 'Survived']].groupby(['FamilySize'], as_index=False).mean().sort_values(by='Survived', ascending=False)
FamilySize Survived
3 4 0.724138
2 3 0.578431
1 2 0.552795
6 7 0.333333
0 1 0.303538
4 5 0.200000
5 6 0.136364
7 8 0.000000
8 11 0.000000
# 创建IsAlone特征
for dataset in combine:
    dataset['IsAlone'] = 0
    dataset.loc[dataset['FamilySize'] == 1, 'IsAlone'] = 1

train_df[['IsAlone', 'Survived']].groupby(['IsAlone'], as_index=False).mean()
IsAlone Survived
0 0 0.505650
1 1 0.303538
# 在train_df,test_df删掉Parch,SibSp和FamilySize
train_df = train_df.drop(['Parch', 'SibSp', 'FamilySize'], axis=1)
test_df = test_df.drop(['Parch', 'SibSp', 'FamilySize'], axis=1)
combine = [train_df, test_df]

train_df.head()
PassengerId Survived Pclass Sex Age Fare Embarked Title IsAlone
0 1 0 3 0 1 0 0 1 0
1 2 1 1 1 2 3 1 3 0
2 3 1 3 1 1 1 0 2 1
3 4 1 1 1 2 3 0 3 0
4 5 0 3 0 2 1 0 1 1

交叉特征

交叉特征指的是将两个或更多的类别属性组合成一个新特征。值得注意的是,当数据量较大时,或者暴力进行特征交叉时,交叉后的新特征容易产生数据稀疏问题,同学们在未来应用这个方法的时,需要特别去处理数据稀疏问题。


针对这个数据集,我们已经在5.2.1.1 Age部分对Age特征按照区间定义了不同类别。在这个Age类别和Pclass类别的基础上,通过特征交叉的方法,建立新特征Age*PClass。


如果同学们认为,在这个数据集中,还有其他分类特征的交叉能够对模型预测有帮助,也可以尝试。

# 创建交叉特征Age*Class
for dataset in combine:
    dataset['Age*Class'] = dataset.Age * dataset.Pclass

train_df.loc[:, ['Age*Class', 'Age', 'Pclass']].head(10)
Age*Class Age Pclass
0 3 1 3
1 2 2 1
2 3 1 3
3 2 2 1
4 6 2 3
5 3 1 3
6 3 3 1
7 0 0 3
8 3 1 3
9 0 0 2

特征缩放

在5.2.1 连续型数值特征部分,我们对数据集中的两个连续数值特征填补缺失值并进行了分桶处理。大家已经学习过逻辑回归与梯度下降的相关知识,我们知道实际上逻辑回归模型中可以放入连续数值特征,但是如果特征中各属性值之间数值差距太大,将对收敛速度有很大的影响。仔细观察Age和Fare两个特征分布,我们发现这两个特征的数值变化幅度很大。


因此,如果我们想要将Age和Fare连续型数值特征不做分桶处理,直接带入到逻辑回归中,我们就需要先用scikit-learn中的preprocessing模块对这两个特征进行特征缩放,就是将一些变化幅度较大的特征化到[-1,1]区间之内。


sklearn.preprocessing.StandardScaler官方文档说明

# 将一些变化幅度较大的特征化到[-1,1]之内,这样可以加速logistic regression的收敛
import sklearn.preprocessing as preprocessing
scaler = preprocessing.StandardScaler()
age_scale_param = scaler.fit(train_df['Age'].values.reshape(-1, 1))
train_df['Age_scaled'] = scaler.fit_transform(train_df['Age'].values.reshape(-1, 1), age_scale_param)
fare_scale_param = scaler.fit(train_df['Fare'].values.reshape(-1, 1))
train_df['Fare_scaled'] = scaler.fit_transform(train_df['Fare'].values.reshape(-1, 1), fare_scale_param)

train_df
PassengerId Survived Pclass Sex Age Fare Embarked Title IsAlone Age*Class Age_scaled Fare_scaled
0 1 0 3 0 1 0 0 1 0 3 -0.392999 -1.346777
1 2 1 1 1 2 3 1 3 0 2 0.827078 1.337738
2 3 1 3 1 1 1 0 2 1 3 -0.392999 -0.451938
3 4 1 1 1 2 3 0 3 0 2 0.827078 1.337738
4 5 0 3 0 2 1 0 1 1 6 0.827078 -0.451938
... ... ... ... ... ... ... ... ... ... ... ... ...
886 887 0 2 0 1 1 0 5 1 2 -0.392999 -0.451938
887 888 1 1 1 1 2 0 2 1 1 -0.392999 0.442900
888 889 0 3 1 1 2 0 2 0 3 -0.392999 0.442900
889 890 1 1 0 1 2 1 1 1 1 -0.392999 0.442900
890 891 0 3 0 1 0 2 1 1 3 -0.392999 -1.346777

891 rows × 12 columns

问题12:如果直接将Age和Fare的连续数值特征放入逻辑回归模型中,其他特征不变的情况,最终预测结果会有怎样的变化?为什么会有这种变化?



有的时候,特征与Survived小幅相关,并不意味着这个特征作用不大,有可能是我们细化的程度还不够,举个例子,Fare特征如果对它离散化,再分至各个乘客等级上会有更高的权重?

特征因子化/one-hot编码

因为逻辑回归建模时,需要输入的特征都是数值型特征,我们通常会先对类目型的特征因子化/one-hot编码。

对于连续特征,如年龄、薪水、阅读数、身高等特征,如果需要放入逻辑回归模型中,则最好先进行离散处理,也叫 one-hot 编码;离散化处理的方式有几种,

什么是one-hot编码

一些属性是类别型而不是数值型,拿这个数据集中的Embarked来举例说明。Embarked由{S,C,Q}三个类别组成,最常用的方式是把每个类别属性转换成二元属性,即从{0,1}取一个值。因此基本上增加的属性等于相应数目的类别,并且对于你数据集中的每个实例,只有一个是1(其他的为0),这也就是独热(one-hot)编码方式


以Embarked为例,原本一个属性维度,因为其取值可以是[‘S’,’C’,’Q‘],one-hot编码后将其平展开为’Embarked_C’,’Embarked_S’, ‘Embarked_Q’三个属性。

  • 原本Embarked取值为S的,在此处的”Embarked_S”下取值为1,在’Embarked_C’, ‘Embarked_Q’下取值为0
  • 原本Embarked取值为C的,在此处的”Embarked_C”下取值为1,在’Embarked_S’, ‘Embarked_Q’下取值为0
  • 原本Embarked取值为Q的,在此处的”Embarked_Q”下取值为1,在’Embarked_C’, ‘Embarked_S’下取值为0

即{1,0,0}表示Embarked取值为S,{0,1,0}表示Embarked取值为C,{0,0,1}表示Embarked取值为Q。

one-hot编码必要性

如果你不了解这个编码的话,你可能会觉得分解会增加没必要的麻烦,因为独热编码大量地增加了数据集的维度。相反,你可能会尝试将类别属性转换成一个标量值,例如Embarked可能会用{1,2,3}表示{S,C,Q}。这里存在两个问题:

  1. 对于一个数学模型,这意味着某种意义上S和C比和Q更“相似”(因为|1-3| > |1-2|)。除非你的类别拥有排序的属性(比如铁路线上的站),这样可能会误导你的模型。
  2. 可能会导致统计指标(比如均值)无意义,更糟糕的情况是会误导你的模型。例如颜色属性可能会用{1,2,3}表示{红,绿,蓝},假如你的数据集包含相同数量的红色和蓝色的实例,但是没有绿色的,那么颜色的均值可能还是得到2,也就是绿色的意思。

连续特征离散化

实际上,针对这个数据集中的Age和Fare特征,我们已经在5.2.1 连续型数值特征进行了等值分桶处理,将两个特征转变为分类特征。


在这里,我们系统的说明一下对连续特征进行one-hot编码常用的三种方法:

  1. 等值分桶

    等值分桶是指每个区间同样大小,比如年龄特征区间为0-80岁。我们可以设定为每隔4岁为一个桶,则年龄特征被切分为20个区间,26岁对应的独热编码对应的应该就是{0,0,0,0,0,0,1,0…}。
  2. 等频分桶

    等频分桶是指每个区间里的人数分布基本持平。因此,需要先对样本进行一个分布的统计。仍然以年龄为例,我们首先要制作一个年龄分布的直方图,了解年龄特征的总体分布。一般这类特征都会大致符合正太分布。这就需要对中间较为集中的区间拆分出跟多的桶。比如年龄特征分布的两边边缘区域,我们设定为0-18一个区间,50-80一个区间;在特征分布的集中区域,我们设定为每2岁一个区间,即18-20一个区间,20-22一个区间,以此类推。最终达到使得每个桶的人数基本相等。
    如 0-18一个区间,18-20一个区间,20-22一个区间,20-30 一个区间。
  3. 根据对业务的理解分桶

    例如对于电商类,可能22岁以下的没有什么经济能力,22-40的经济能力差不多,这时候可以人工根据业务需求划分。

总结

对于连续型数值特征,我们有两种处理方法,一种是离散化,如5.2.1连续型数值特征部分处理过程,另一种是5.4 特征缩放将连续之缩放到符合模型要求的区间内。

# 对train_df和test_df中需要进行one-hot编码的进行处理
train_df = pd.get_dummies(train_df,columns=['Pclass', 'Sex', 'Embarked','Title','IsAlone','Age','Fare'])
test_df = pd.get_dummies(test_df,columns=['Pclass', 'Sex', 'Embarked','Title','IsAlone','Age','Fare'])
combine = [train_df, test_df]

# 查看one-hot编码数据结果
train_df.head()
PassengerId Survived Age*Class Age_scaled Fare_scaled Pclass_1 Pclass_2 Pclass_3 Sex_0 Sex_1 ... IsAlone_1 Age_0 Age_1 Age_2 Age_3 Age_4 Fare_0 Fare_1 Fare_2 Fare_3
0 1 0 3 -0.392999 -1.346777 0 0 1 1 0 ... 0 0 1 0 0 0 1 0 0 0
1 2 1 2 0.827078 1.337738 1 0 0 0 1 ... 0 0 0 1 0 0 0 0 0 1
2 3 1 3 -0.392999 -0.451938 0 0 1 0 1 ... 1 0 1 0 0 0 0 1 0 0
3 4 1 2 0.827078 1.337738 1 0 0 0 1 ... 0 0 0 1 0 0 0 0 0 1
4 5 0 6 0.827078 -0.451938 0 0 1 1 0 ... 1 0 0 1 0 0 0 1 0 0

5 rows × 29 columns

# 确认是否分类特征全部进行one-hot编码
train_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 29 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Age*Class    891 non-null    int64  
 3   Age_scaled   891 non-null    float64
 4   Fare_scaled  891 non-null    float64
 5   Pclass_1     891 non-null    uint8  
 6   Pclass_2     891 non-null    uint8  
 7   Pclass_3     891 non-null    uint8  
 8   Sex_0        891 non-null    uint8  
 9   Sex_1        891 non-null    uint8  
 10  Embarked_0   891 non-null    uint8  
 11  Embarked_1   891 non-null    uint8  
 12  Embarked_2   891 non-null    uint8  
 13  Title_1      891 non-null    uint8  
 14  Title_2      891 non-null    uint8  
 15  Title_3      891 non-null    uint8  
 16  Title_4      891 non-null    uint8  
 17  Title_5      891 non-null    uint8  
 18  IsAlone_0    891 non-null    uint8  
 19  IsAlone_1    891 non-null    uint8  
 20  Age_0        891 non-null    uint8  
 21  Age_1        891 non-null    uint8  
 22  Age_2        891 non-null    uint8  
 23  Age_3        891 non-null    uint8  
 24  Age_4        891 non-null    uint8  
 25  Fare_0       891 non-null    uint8  
 26  Fare_1       891 non-null    uint8  
 27  Fare_2       891 non-null    uint8  
 28  Fare_3       891 non-null    uint8  
dtypes: float64(2), int64(3), uint8(24)
memory usage: 55.8 KB

逻辑回归

我们终于可以建模了!

# 准备放入模型中的最终训练数据和测试数据
X_train = train_df.drop(["Survived","PassengerId"], axis=1)
Y_train = train_df["Survived"]
X_test  = test_df.drop("PassengerId", axis=1).copy()
X_train.shape, Y_train.shape, X_test.shape
((891, 27), (891,), (418, 25))
x_1=X_train.columns
x_2=X_test.columns
[x for x in x_1 if x in x_1 and not x in x_2]
['Age_scaled', 'Fare_scaled']
del X_train["Age_scaled"]
del X_train["Fare_scaled"]
# Logistic Regression
logreg = LogisticRegression()
logreg.fit(X_train, Y_train)
Y_pred = logreg.predict(X_test)
acc_log = round(logreg.score(X_train, Y_train) * 100, 2)
acc_log
81.71
# 输出预测结果
lr_result = pd.DataFrame({"PassengerId": test_df["PassengerId"],"Survived": Y_pred})
lr_result.to_csv('../input/logistic_regression_bagging_predictions.csv', index=False)
from sklearn.ensemble import BaggingRegressor

# fit到BaggingRegressor之中
logreg = LogisticRegression()
bagging_clf = BaggingRegressor(logreg, n_estimators=25, max_samples=0.8, max_features=1.0, bootstrap=True, bootstrap_features=False, n_jobs=-1)
ensemble = bagging_clf.fit(X_train, Y_train)
predictions = bagging_clf.predict(X_test)

acc_bagging = round(ensemble.score(X_train, Y_train) * 100, 2)
acc_bagging
34.39

模型系数分析

我们可以通过每个特征的相关系数的值来判断每个特征对于最终预测结果的影响程度。

  1. 相关系数绝对值大小:相关系数的绝对值越大,即越接近1,关系越强;相关系数的绝对值越小,即越接近0,关系越弱。
  2. 相关系数正负号:相关系数为正数,则正相关;相关系数为负数,则减负相关。
coeff_df = pd.DataFrame(train_df.columns.delete(0))
coeff_df.columns = ['Feature']
coeff_df["Correlation"] = pd.Series(logreg.coef_[0]) # 获得特征的相关系数
coeff_df
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

Input In [68], in <cell line: 3>()
      1 coeff_df = pd.DataFrame(train_df.columns.delete(0))
      2 coeff_df.columns = ['Feature']
----> 3 coeff_df["Correlation"] = pd.Series(logreg.coef_[0]) # 获得特征的相关系数
      4 coeff_df


AttributeError: 'LogisticRegression' object has no attribute 'coef_'
# 根据相关系数的大小从高到底排序
coeff_df.sort_values(by='Correlation', ascending=False) 

问题13:如何解释特征权重?从特征工程的角度,还有什么可以优化?

  • Sex:female会极大提高最后获救的概率,male会很大程度拉低这个概率。
  • Pclass:1等舱乘客最后获救的概率会上升,而乘客等级为3会极大地拉低这个概率。
  • Age:是一个负相关,意味着在我们的模型里,年龄越小,越有获救的优先权(还得回原数据看看这个是否合理)
  • Embarked:登船港口S会很拉低获救的概率,另外俩港口提高获救的概率。
  • Fare:船票价格低会拉高获救的概率,船票价格高的会拉低获救的概率(这个和我们对Fare分布的判断结果不太符合,需要对这个变量进一步进行细化处理)。
  • Title:Mrs和Master会提高获救的概率,Mr,Miss和Rare会拉低获救的概率。
  • IsAlone:独自一人登船的人会拉低获救的概率,有家人同行的人会提高获救的概率。
  • Age*Class是一个不错的特征,它的相关系数的绝对值没有很低。

到目前为止,总算是把模型建完,得到了一个baseline的预测结果了!有没有尝试把自己跑出来的预测结果提交到Kaggle上去看看自己的名次?

难道你真的以为只要完成数据预处理,再用sklearn跑完所有可能的算法,挑选一个预测效果最好的结果提交,这样就大功告成了嘛?
看到自己现在的排名,没有想过进一步优化嘛?
万里长征才刚刚开始,我们还是继续干活儿吧!

逻辑回归优化

交叉验证

交叉验证的基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set or test set),首先用训练集对分类器进行训练,再利用验证集来测试训练得到的模型(model),以此来做为评价分类器的性能指标。

也就是说,我们把题目中所给的训练集当成一个原始数据,将这个数据切分成训练集和测试集。利用切分出的训练集进行训练,切分出的测试集进行验证。

常见类型的交叉验证

1. 重复随机子抽样验证

将数据集随机的划分为训练集和测试集。对每一个划分,用训练集训练分类器或模型,用测试集评估预测的精确度。进行多次划分,用均值来表示效能。

优点:与k倍交叉验证相比,这种方法的与k无关。

缺点:有些数据可能从未做过训练或测试数据;而有些数据不止一次选为训练或测试数据。

2. K倍交叉验证(K>=2)

将样本数据集随机划分为K个子集(一般是均分),将一个子集数据作为测试集,其余的K-1组子集作为训练集;将K个子集轮流作为测试集,重复上述过程,这样得到了K个分类器或模型,并利用测试集得到了K个分类器或模型的分类准确率。用K个分类准确率的平均值作为分类器或模型的性能指标。10-倍交叉证实是比较常用的。
优点:每一个样本数据都即被用作训练数据,也被用作测试数据。避免的过度学习和欠学习状态的发生,得到的结果比较具有说服力。

3. 留一法交叉验证

假设样本数据集中有N个样本数据。将每个样本单独作为测试集,其余N-1个样本作为训练集,这样得到了N个分类器或模型,用这N个分类器或模型的分类准确率的平均数作为此分类器的性能指标。

优点:每一个分类器或模型都是用几乎所有的样本来训练模型,最接近样本,这样评估所得的结果比较可靠。实验没有随机因素,整个过程是可重复的。

缺点:计算成本高,当N非常大时,计算耗时。

训练集和测试集的选取
  1. 训练集中样本数量要足够多,一般至少大于总样本数的50%。
  2. 训练集和测试集必须从完整的数据集中均匀取样。均匀取样的目的是希望减少训练集、测试集与原数据集之间的偏差。当样本数量足够多时,通过随机取样,便可以实现均匀取样的效果。(随机取样,可重复性差)
from sklearn.model_selection import cross_val_score
from sklearn import linear_model

#简单看看打分情况
clf = linear_model.LogisticRegression(C=1.0, penalty='l2', tol=1e-6)
X = train_df.values[:,1:]
y = train_df.values[:,0]
# 交叉验证的结果
cross_val_score(clf, X_train, Y_train, cv=5) # cv=5,5倍交叉验证
array([0.79888268, 0.80337079, 0.81460674, 0.78651685, 0.83146067])

我们已经进行了交叉验证,其实我们可以把交叉验证里预测错误的记录拿出来,通过人工审核,去帮助我们发现新的优化方向,继续探索。


对于以下方法对应的参数不了解的,可以参考官方文档说明:

linear_model.LogisticRegression官方文档说明

cross_validation.cross_val_score官方文档说明

cross_validation.train_test_split官方文档说明

from sklearn.model_selection import train_test_split

# 分割数据,按照 训练数据:cv数据 = 7:3的比例
split_train, split_cv = train_test_split(train_df, test_size=0.3, random_state=0) # test_size测试集占数据的比例
train_df = split_train

# 生成模型
clf = linear_model.LogisticRegression(C=1.0, penalty='l2', tol=1e-6)
clf.fit(train_df.values[:,1:], train_df.values[:,0])

# 对cross validation数据进行预测
cv_df = split_cv
predictions = clf.predict(cv_df.values[:,1:])

origin_data_train = pd.read_csv("../input/train.csv")

# 交叉验证没有预测对的记录
bad_cases = origin_data_train.loc[origin_data_train['PassengerId'].isin(split_cv[predictions != cv_df.values[:,0]]['PassengerId'].values)]
bad_cases
D:\Anaconda3\lib\site-packages\sklearn\linear_model\_logistic.py:814: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.

Increase the number of iterations (max_iter) or scale the data as shown in:
    https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
    https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
  n_iter_i = _check_optimize_result(
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
32 33 1 3 Glynn, Miss. Mary Agatha female NaN 0 0 335677 7.7500 NaN Q
67 68 0 3 Crease, Mr. Ernest James male 19.0 0 0 S.P. 3464 8.1583 NaN S
87 88 0 3 Slocovski, Mr. Selman Francis male NaN 0 0 SOTON/OQ 392086 8.0500 NaN S
88 89 1 1 Fortune, Miss. Mabel Helen female 23.0 3 2 19950 263.0000 C23 C25 C27 S
... ... ... ... ... ... ... ... ... ... ... ... ...
858 859 1 3 Baclini, Mrs. Solomon (Latifa Qurban) female 24.0 0 3 2666 19.2583 NaN C
861 862 0 2 Giles, Mr. Frederick Edward male 21.0 1 0 28134 11.5000 NaN S
866 867 1 2 Duran y More, Miss. Asuncion female 27.0 1 0 SC/PARIS 2149 13.8583 NaN C
879 880 1 1 Potter, Mrs. Thomas Jr (Lily Alexenia Wilson) female 56.0 0 1 11767 83.1583 C50 C
881 882 0 3 Markun, Mr. Johann male 33.0 0 0 349257 7.8958 NaN S

64 rows × 12 columns

观察这些预测错误的记录,提出新的优化方向,继续尝试挖掘,可能还可以想到更多可以细挖的部分。将新的特征和已有特征组合在一起,查看模型预测准确度是否有所提升。继续迭代下去。

问题14:观察这些预测错误的记录,你还能想到什么优化的方向?



仅供参考:

  1. Fare细化处理,可能可以考虑将Fare与乘客等级Pclass相关连。
  2. 可以考虑将除Age*Class之外的分类特征进行特征交叉。
  3. 可能考虑加入Cabin特征,并进一步对其进行细化研究。

模型状态判断(欠拟合or过拟合)

当我们不断地丰富特征时,模型对训练集拟合越来越好,有可能同时在丧失泛华能力,对测试集变现不佳,存在过拟合问题。而我们最终的目的是希望我们训练的出来的模型,不仅能对训练数据集有很好的预测效果,更希望它对测试数据集也有很好的预测效果。过拟合问题是机器学习建模过程中常见的问题。


实际上,如果模型在测试集上表现不佳,除了过拟合问题,也有可能出现欠拟合问题,也就是说在训练集上,其实拟合的也不是那么好。

什么是欠拟合/过拟合

举个来说:

过拟合就像是你班那个学数学比较刻板的同学,老师讲过的题目,一字不漏全记下来了,于是老师再出一样的题目,分分钟精确出结果。but数学考试,因为总是碰到新题目,所以成绩不咋地。

欠拟合就像是连老师讲的练习题也记不住的同学,于是连老师出一样题目复习的周测都做不好,考试更是可想而知了。

经典解释

解释1
解释2
titanic数据集中的以下哪个特征属于排序型数据( ),机器学习,python,数据挖掘,人工智能,算法
titanic数据集中的以下哪个特征属于排序型数据( ),机器学习,python,数据挖掘,人工智能,算法

在机器学习的问题上,对于过拟合和欠拟合两种情形。我们优化的方式是不同的。

如何处理过拟合

对过拟合而言,通常以下策略对结果优化是有用的:

  1. 进行特征选择,挑出较好的特征的子集进行训练。
  2. 提供更多的数据,从而弥补原始数据的bias问题,学习到的模型也会更准确。
如何处理欠拟合

通常需要增加更多的特征,使模型变得更复杂来提高准确度。

如何判断模型状态

著名的learning curve可以帮我们判定我们的模型现在所处的状态。

我们以样本数为横坐标,训练和交叉验证集上的错误率作为纵坐标,我们也可以把错误率替换成准确率(得分),得到另一种形式的learning curve(sklearn 里面是这么做的)。

回到我们的问题,我们用scikit-learn里面的learning_curve来帮我们分辨我们模型的状态。

举个例子,这里我们一起画一下我们最先得到的baseline model的learning curve。

# import numpy as np
# import matplotlib.pyplot as plt
# from sklearn.model_selection import learning_curve

# # 用sklearn的learning_curve得到training_score和cv_score,使用matplotlib画出learning curve
# def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None, n_jobs=1, 
#                         train_sizes=np.linspace(.05, 1., 20), verbose=0, plot=True): # train_sizes训练集占数据的比例
#     """
#     画出data在某模型上的learning curve.
#     参数解释
#     ----------
#     estimator : 你用的分类器。
#     title : 表格的标题。
#     X : 输入的feature,numpy类型
#     y : 输入的target vector
#     ylim : tuple格式的(ymin, ymax), 设定图像中纵坐标的最低点和最高点
#     cv : 做cross-validation的时候,数据分成的份数,其中一份作为cv集,其余n-1份作为training(默认为3份)
#     n_jobs : 并行的的任务数(默认1)
#     """
#     train_sizes, train_scores, test_scores = learning_curve(
#         estimator, X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes, verbose=verbose)

#     train_scores_mean = np.mean(train_scores, axis=1)
#     train_scores_std = np.std(train_scores, axis=1)
#     test_scores_mean = np.mean(test_scores, axis=1)
#     test_scores_std = np.std(test_scores, axis=1)

#     if plot:
#         plt.figure()
#         plt.title(title)
#         if ylim is not None:
#             plt.ylim(*ylim)
#         plt.xlabel(u"training_sample")
#         plt.ylabel(u"cv_sample")
#         plt.gca().invert_yaxis()
#         plt.grid()

#         plt.fill_between(train_sizes, train_scores_mean - train_scores_std, train_scores_mean + train_scores_std, 
#                          alpha=0.1, color="b")
#         plt.fill_between(train_sizes, test_scores_mean - test_scores_std, test_scores_mean + test_scores_std, 
#                          alpha=0.1, color="r")
#         plt.plot(train_sizes, train_scores_mean, 'o-', color="b", label=u"train_scores")
#         plt.plot(train_sizes, test_scores_mean, 'o-', color="r", label=u"cv_scores")

#         plt.legend(loc="best")

#         plt.draw()
#         plt.show()
#         plt.gca().invert_yaxis()

#     midpoint = ((train_scores_mean[-1] + train_scores_std[-1]) + (test_scores_mean[-1] - test_scores_std[-1])) / 2
#     diff = (train_scores_mean[-1] + train_scores_std[-1]) - (test_scores_mean[-1] - test_scores_std[-1])
#     return midpoint, diff

# plot_learning_curve(clf, u"learning curve", X, y)

在实际数据上看,我们得到的learning curve没有理论推导的那么光滑哈,但是可以大致看出来,训练集和交叉验证集上的得分曲线走势还是符合预期的。

目前的曲线看来,我们的model并不处于overfitting的状态(overfitting的表现一般是训练集上得分高,而交叉验证集上要低很多,中间的gap比较大)。因此我们可以再做些feature engineering的工作,添加一些新产出的特征或者组合特征到模型中。

模型融合

什么是模型融合

模型融合是机器学习/数据挖掘中经常使用到的一个利器,它通常可以在各种不同的机器学习任务中使结果获得提升。顾名思义,模型融合就是综合考虑不同模型的情况,并将它们的结果融合到一起。


举个例子来说,你和你班某数学大神关系好,每次作业都『模仿』他的,于是绝大多数情况下,他做对了,你也对了。突然某一天大神脑子犯糊涂,手一抖,写错了一个数,于是…恩,你也只能跟着错了。

我们再来看看另外一个场景,你和你班5个数学大神关系都很好,每次都把他们作业拿过来,对比一下,再『自己做』,那你想想,如果哪天某大神犯糊涂了,写错了,but另外四个写对了啊,那你肯定相信另外4人的是正确答案吧?

最简单的模型融合大概就是这么个意思,比如分类问题,当我们手头上有一堆在同一份数据集上训练得到的分类器(比如logistic regression,SVM,KNN,random forest,神经网络),那我们让他们都分别去做判定,然后对结果做投票统计,取票数最多的结果为最后结果。

模型融合的作用

模型融合可以比较好地缓解,训练过程中产生的过拟合问题,从而对于结果的准确度提升有一定的帮助。

问题15:模型融合实现:将逻辑回归和随机森林进行模型融合

思考题

到目前为止,我们只实现了逻辑回归一个模型,这是时候如果我们想利用模型融合的思路提高模型的预测准确率,我们应该怎么做呢?

思路

如果模型出现过拟合,一定是在我们的训练上出现拟合过度造成的对吧。

那我们干脆就不要用全部的训练集,每次取训练集的一个subset,做训练,这样,我们虽然用的是同一个机器学习算法,但是得到的模型却是不一样的;同时,因为我们没有任何一份子数据集是全的,因此即使出现过拟合,也是在子训练集上出现过拟合,而不是全体数据上,这样做一个融合,可能对最后的结果有一定的帮助。这就是常用的方法之一Bagging。

Bagging:

Bagging的特点在于随机采样,随机采样(bootsrap)就是从我们的训练集里面采集固定个数的样本,每采集一个样本后,都将样本放回,是有放回的随机抽样

sklearn.ensemble.BaggingRegressor官方文档说明 回归器组合

sklearn.ensemble.BaggingClassifier官方文档说明 用于分类器组合


两个结果预测准确性效果差别很大,BaggingClassifier的结果更好一些,比最初的81.71提高了0.33.

代码参考如下:

from sklearn.ensemble import BaggingRegressor

# fit到BaggingRegressor之中
logreg = LogisticRegression() # 基于baseline逻辑回归的结果
bagging_clf = BaggingRegressor(logreg, n_estimators=25, max_samples=0.8, max_features=1.0, bootstrap=True, bootstrap_features=False, n_jobs=-1)
ensemble = bagging_clf.fit(X_train, Y_train)
predictions = bagging_clf.predict(X_test)

acc_BaggingRegressor = round(ensemble.score(X_train, Y_train) * 100, 2)
acc_BaggingRegressor
35.25
from sklearn.ensemble import BaggingClassifier

# fit到BaggingClassifier之中
logreg = LogisticRegression() # 基于baseline逻辑回归的结果
bagging_clf = BaggingClassifier(logreg, n_estimators=25, max_samples=0.8, max_features=1.0, bootstrap=True, bootstrap_features=False, n_jobs=-1)
ensemble = bagging_clf.fit(X_train, Y_train)
predictions = bagging_clf.predict(X_test)

acc_BaggingClassifier = round(ensemble.score(X_train, Y_train) * 100, 2)
acc_BaggingClassifier
81.03
# 保存预测结果
bagging_result = pd.DataFrame({"PassengerId": test_df["PassengerId"],"Survived": predictions})
bagging_result.to_csv('../input/logistic_regression_baggingRegressor_predictions.csv', index=False)
bagging_result.to_csv('../input/logistic_regression_baggingClassifier_predictions.csv', index=False)

其他算法实现

实际上,除逻辑回归算法外,我们有60多个算法供我们选择。然而我们应该如何思考,今儿选择合适的算法进行尝试呢?

我们还可以使用mlxtend中的其他工具进行模型融合。

可以解决问题的算法

需要理解清楚我们正在解决的问题和所需给出的答案要求的类型,然后进一步缩小范围,最终去选择一些算法用于解决问题,并进一步来评估算法的预测结果。


问题界定:

  1. 分类和回归问题。
    我们需要解决的是输入的特征和是否获救这个输出结果之间的关系。
  2. 监督学习问题。
    我们使用一个已经给出是否获救分类结果的数据集来训练模型。

通过以上两点,我们可以确定缩小范围,选择以下算法来预测结果:

- Logistic Regression
- KNN/k-Nearest Neighbors
- Support Vector Machines
- Naive Bayes classifier
- Decision Tree
- Random Forrest
- Perceptron
- RVM or Relevance Vector Machine
- Artificial neural network

根据大家已经学过的知识,不同的模型对放入模型中的特征值要求不同,处理方法不同。那么大家能不能基于上面我们已经完成的特征工程部分的思路,对数据进行相应的处理以适应不同算法,获得以上其他算法的预测结果,并验证是否过拟合进行相应的处理。

随机森林算法的特征工程

实际上,放入随机森林中的特征,只要根据上面特征工程部分进行相同的处理,最后一步不进行one-hot编码即可。在这里我们就不再给出具体代码了。

模型部分的代码实现参考

不同的模型对于放入模型中的特征有不同的要求,我们暂时先不管那么多,先暴力实现其他算法,开心开心。

说明:所得结果,均使用最终放入随机森林算法中的特征处理结果带入,仅供参考。

import sklearn.metrics as sm

# Support Vector Machines
svc = SVC()
svc.fit(X_train, Y_train)
Y_pred = svc.predict(X_train)
# acc_svc = round(svc.score(Y_pred, Y_train) * 100, 2)
# acc_svc
print(sm.classification_report(Y_pred, Y_train))

              precision    recall  f1-score   support

           0       0.92      0.83      0.87       606
           1       0.70      0.84      0.76       285

    accuracy                           0.83       891
   macro avg       0.81      0.83      0.82       891
weighted avg       0.85      0.83      0.84       891
# KNN
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(X_train, Y_train)
Y_pred = knn.predict(X_train)
# acc_knn = round(knn.score(X_train, Y_train) * 100, 2)
# acc_knn
print(sm.classification_report(Y_pred, Y_train))

              precision    recall  f1-score   support

           0       0.92      0.84      0.88       600
           1       0.72      0.85      0.78       291

    accuracy                           0.84       891
   macro avg       0.82      0.85      0.83       891
weighted avg       0.86      0.84      0.85       891
# Gaussian Naive Bayes
gaussian = GaussianNB()
gaussian.fit(X_train, Y_train)
Y_pred = gaussian.predict(X_train)
# acc_gaussian = round(gaussian.score(X_train, Y_train) * 100, 2)
# acc_gaussian
print(sm.classification_report(Y_pred, Y_train))

              precision    recall  f1-score   support

           0       0.78      0.85      0.81       504
           1       0.78      0.69      0.73       387

    accuracy                           0.78       891
   macro avg       0.78      0.77      0.77       891
weighted avg       0.78      0.78      0.78       891
# Perceptron
perceptron = Perceptron()
perceptron.fit(X_train, Y_train)
Y_pred = perceptron.predict(X_train)
# acc_perceptron = round(perceptron.score(X_train, Y_train) * 100, 2)
# acc_perceptron
print(sm.classification_report(Y_pred, Y_train,digits=4))
              precision    recall  f1-score   support

           0     0.8725    0.7983    0.8338       600
           1     0.6462    0.7595    0.6983       291

    accuracy                         0.7856       891
   macro avg     0.7593    0.7789    0.7660       891
weighted avg     0.7986    0.7856    0.7895       891
# Linear SVC
linear_svc = LinearSVC()
linear_svc.fit(X_train, Y_train)
Y_pred = linear_svc.predict(X_train)
# acc_linear_svc = round(linear_svc.score(X_train, Y_train) * 100, 2)
# acc_linear_svc
print(sm.classification_report(Y_pred, Y_train,digits=4))

              precision    recall  f1-score   support

           0     0.8743    0.8421    0.8579       570
           1     0.7368    0.7850    0.7602       321

    accuracy                         0.8215       891
   macro avg     0.8056    0.8136    0.8090       891
weighted avg     0.8248    0.8215    0.8227       891



D:\Anaconda3\lib\site-packages\sklearn\svm\_base.py:1206: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  warnings.warn(
# Stochastic Gradient Descent
sgd = SGDClassifier(max_iter=5000)
sgd.fit(X_train, Y_train)
Y_pred = sgd.predict(X_train)
# acc_sgd = round(sgd.score(X_train, Y_train) * 100, 2)
# acc_sgd
print(sm.classification_report(Y_pred, Y_train,digits=4))

              precision    recall  f1-score   support

           0     0.8871    0.8144    0.8492       598
           1     0.6754    0.7884    0.7276       293

    accuracy                         0.8058       891
   macro avg     0.7813    0.8014    0.7884       891
weighted avg     0.8175    0.8058    0.8092       891
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

pipe_sgd = Pipeline([ ("scaler",StandardScaler() ),('sgd', SGDClassifier(loss="modified_huber",penalty="l1", max_iter=1000))])
pipe_sgd.fit(X_train,Y_train)
y_pre=pipe_sgd.predict(X_train)
y_pre_prob_=pipe_sgd.predict_proba(X_train)
y_pre_prob=[]
for i in range(len(y_pre)):
    if y_pre[i]==1:
        y_pre_prob.append(y_pre_prob_[i][1])
    else:
        y_pre_prob.append(1-y_pre_prob_[i][0])
        
print(sm.classification_report(Y_pred, Y_train,digits=4))
print(sm.mean_absolute_error(Y_pred_prob,Y_train))
              precision    recall  f1-score   support

           0     0.9290    0.8644    0.8955       590
           1     0.7661    0.8704    0.8149       301

    accuracy                         0.8664       891
   macro avg     0.8475    0.8674    0.8552       891
weighted avg     0.8739    0.8664    0.8683       891

0.22110828951156772
# xgb
from xgboost.sklearn import XGBClassifier
from sklearn.model_selection import RandomizedSearchCV


sample_weight=[]
for i in range(len(Y_train)):
    if Y_train[i]==0:
        sample_weight.append(1)
    else:
        sample_weight.append(2)
xgb= XGBClassifier(n_estimators=5000,max_depth=10,scale_pos_weight =0.3,learning_rate =0.01,gamma =0.05,subsample=0.7,colsample_bytree=0.4,min_child_weight=0.2)

xgb.fit(X_train,Y_train)

Y_pred=xgb.predict(X_train)
Y_pred_prob_=xgb.predict_proba(X_train)
Y_pred_prob=[]
for i in range(len(Y_pred)):
    if Y_pred[i]==1:
        Y_pred_prob.append(Y_pred_prob_[i][1])
    else:
        Y_pred_prob.append(1-Y_pred_prob_[i][0])
    
print(sm.classification_report(Y_pred, Y_train,digits=4))
print(sm.mean_absolute_error(Y_pred_prob,Y_train))

              precision    recall  f1-score   support

           0     0.9891    0.7915    0.8794       686
           1     0.5819    0.9707    0.7276       205

    accuracy                         0.8328       891
   macro avg     0.7855    0.8811    0.8035       891
weighted avg     0.8954    0.8328    0.8444       891

0.19012825731208963
# Decision Tree
decision_tree = DecisionTreeClassifier()
decision_tree.fit(X_train, Y_train)
Y_pred = decision_tree.predict(X_train)
Y_pred_prob_=decision_tree.predict_proba(X_train)
Y_pred_prob=[]
for i in range(len(Y_pred)):
    if Y_pred[i]==1:
        Y_pred_prob.append(Y_pred_prob_[i][1])
    else:
        Y_pred_prob.append(1-Y_pred_prob_[i][0])
    
print(sm.classification_report(Y_pred, Y_train,digits=4))
print(sm.mean_absolute_error(Y_pred_prob,Y_train))

              precision    recall  f1-score   support

           0     0.9344    0.8607    0.8961       596
           1     0.7573    0.8780    0.8132       295

    accuracy                         0.8664       891
   macro avg     0.8459    0.8694    0.8546       891
weighted avg     0.8758    0.8664    0.8686       891

0.1870742685334913
# Random Forest
random_forest = RandomForestClassifier(n_estimators=1000) # 定义决策树的个数为100
random_forest.fit(X_train, Y_train)
Y_pred = random_forest.predict(X_train)
Y_pred_prob_=random_forest.predict_proba(X_train)
Y_pred_prob=[]
for i in range(len(Y_pred)):
    if Y_pred[i]==1:
        Y_pred_prob.append(Y_pred_prob_[i][1])
    else:
        Y_pred_prob.append(1-Y_pred_prob_[i][0])
    
print(sm.classification_report(Y_pred, Y_train,digits=4))
print(sm.mean_absolute_error(Y_pred_prob,Y_train))

              precision    recall  f1-score   support

           0     0.9253    0.8669    0.8952       586
           1     0.7719    0.8656    0.8161       305

    accuracy                         0.8664       891
   macro avg     0.8486    0.8662    0.8556       891
weighted avg     0.8728    0.8664    0.8681       891

0.19873776366870244
from sklearn.ensemble import AdaBoostClassifier,HistGradientBoostingRegressor,GradientBoostingClassifier

# gbdt
gbdt = GradientBoostingClassifier(criterion="friedman_mse",n_estimators=1000,learning_rate=0.05)
gbdt.fit(X_train,Y_train)
Y_pred=gbdt.predict(X_train)
Y_pred_prob_=gbdt.predict_proba(X_train)
Y_pred_prob=[]
for i in range(len(Y_pred)):
    if Y_pred[i]==1:
        Y_pred_prob.append(Y_pred_prob_[i][1])
    else:
        Y_pred_prob.append(1-Y_pred_prob_[i][0])
    
print(sm.classification_report(Y_pred, Y_train,digits=4))
print(sm.mean_absolute_error(Y_pred_prob,Y_train))
              precision    recall  f1-score   support

           0     0.9199    0.8707    0.8946       580
           1     0.7807    0.8585    0.8178       311

    accuracy                         0.8664       891
   macro avg     0.8503    0.8646    0.8562       891
weighted avg     0.8713    0.8664    0.8678       891

0.19961541192640012
#mlp
from sklearn.ensemble import AdaBoostClassifier,HistGradientBoostingRegressor,GradientBoostingClassifier

# mlp
gbdt = MLPClassifier(solver='lbfgs', alpha=1e-5,
                     hidden_layer_sizes=(32,16,4),learning_rate="invscaling",random_state=1)
gbdt.fit(X_train,Y_train)
Y_pred=gbdt.predict(X_train)
Y_pred_prob_=gbdt.predict_proba(X_train)
Y_pred_prob=[]
for i in range(len(Y_pred)):
    if Y_pred[i]==1:
        Y_pred_prob.append(Y_pred_prob_[i][1])
    else:
        Y_pred_prob.append(1-Y_pred_prob_[i][0])
    
print(sm.classification_report(Y_pred, Y_train,digits=4))
print(sm.mean_absolute_error(Y_pred_prob,Y_train))

              precision    recall  f1-score   support

           0     0.9162    0.8672    0.8911       580
           1     0.7749    0.8521    0.8116       311

    accuracy                         0.8620       891
   macro avg     0.8455    0.8597    0.8513       891
weighted avg     0.8669    0.8620    0.8633       891

0.1949298895378452

问题16:神经网络实现

我们已经尝试使用这么多的算法来尝试解决问题,现在只差一个神经网络了。是时候自己动手,实现你的第一个神经网络了!
sklearn中已经有了成熟的实现。

模型比较

我们将上面所有的模型结果进行排序,选择一个分数最高的模型作为最终预测结果。
决策树和随机森林的得分一样,我们最终选择随机森林,因为它也刚好修正了决策树对于训练集的过拟合问题。

models = pd.DataFrame({
    'Model': ['Support Vector Machines', 'KNN', 'Logistic Regression', 
              'Random Forest', 'Naive Bayes', 'Perceptron', 
              'Stochastic Gradient Decent', 'Linear SVC', 
              'Decision Tree'],
    'Score': [acc_svc, acc_knn, acc_log, 
              acc_random_forest, acc_gaussian, acc_perceptron, 
              acc_sgd, acc_linear_svc, acc_decision_tree]})
models.sort_values(by='Score', ascending=False)
Model Score
3 Random Forest 86.64
8 Decision Tree 86.64
1 KNN 84.40
0 Support Vector Machines 83.28
7 Linear SVC 82.15
2 Logistic Regression 81.71
5 Perceptron 78.56
4 Naive Bayes 78.11
6 Stochastic Gradient Decent 76.88

问题17:实现逻辑回归以外的其他算法

到这里,我们把解决Titanic数据集问题的思路,全部带领同学们过了一遍。希望大家可以把除了逻辑回归以外的其他模型,都认真地自己动手实现一遍,以更好的理解每一个算法和使用机器学习解决问题中需要应对的问题和处理的方法。

集成学习

sgd作为基学习器

from mlxtend.classifier import StackingClassifier
from sklearn.linear_model import SGDClassifier
sreg = StackingClassifier(verbose=2,classifiers=[xgb,decision_tree,gbdt,random_forest,pipe_sgd], 
                          meta_classifier=SGDClassifier( loss="log",penalty="l1", max_iter=5000)
)
sreg.fit(X_train, Y_train)
Y_pred = sreg.predict(X_train)

Y_pred_prob_= sreg.predict_proba(X_train)

Y_pred_prob=[]
for i in range(len(Y_pred)):
    if Y_pred[i]==1:
        Y_pred_prob.append(Y_pred_prob_[i][1])
    else:
        Y_pred_prob.append(1-Y_pred_prob_[i][0])
    
print(sm.classification_report(Y_pred, Y_train,digits=4))
print(sm.mean_absolute_error(Y_pred_prob,Y_train))

Fitting 5 classifiers...
Fitting classifier1: xgbclassifier (1/5)
XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None,
              colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,
              early_stopping_rounds=None, enable_categorical=False,
              eval_metric=None, feature_types=None, gamma=0, gpu_id=-1,
              grow_policy='depthwise', importance_type=None,
              interaction_constraints='', learning_rate=0.300000012,
              max_bin=256, max_cat_threshold=64, max_cat_to_onehot=4,
              max_delta_step=0, max_depth=10, max_leaves=0, min_child_weight=1,
              missing=nan, monotone_constraints='()', n_estimators=3000,
              n_jobs=0, num_parallel_tree=1, predictor='auto', random_state=0, ...)
Fitting classifier2: decisiontreeclassifier (2/5)
DecisionTreeClassifier()
Fitting classifier3: mlpclassifier (3/5)
MLPClassifier(alpha=1e-05, hidden_layer_sizes=(32, 16, 4),
              learning_rate='invscaling', random_state=1, solver='lbfgs')

Fitting classifier4: randomforestclassifier (4/5)
RandomForestClassifier(n_estimators=1000)
Fitting classifier5: pipeline (5/5)
Pipeline(steps=[('scaler', StandardScaler()),
                ('sgd', SGDClassifier(loss='modified_huber', penalty='l1'))])
              precision    recall  f1-score   support

           0     0.9217    0.8694    0.8948       582
           1     0.7778    0.8608    0.8172       309

    accuracy                         0.8664       891
   macro avg     0.8497    0.8651    0.8560       891
weighted avg     0.8718    0.8664    0.8679       891

0.24045011034849822

神经网络作为基学习器

from sklearn.neural_network import MLPClassifier

sreg = StackingClassifier(verbose=2,classifiers=[xgb,decision_tree,gbdt,random_forest,pipe_sgd],
                          meta_classifier=MLPClassifier(solver='lbfgs', alpha=1e-5,
                     hidden_layer_sizes=(8,4,4),learning_rate="invscaling",random_state=1))

sreg.fit(X_train, Y_train)
Y_pred = sreg.predict(X_train)
Y_pred_prob_= sreg.predict_proba(X_train)

Y_pred_prob=[]
for i in range(len(Y_pred)):
    if Y_pred[i]==1:
        Y_pred_prob.append(Y_pred_prob_[i][1])
    else:
        Y_pred_prob.append(1-Y_pred_prob_[i][0])
    
print(sm.classification_report(Y_pred, Y_train,digits=4))
print(sm.mean_absolute_error(Y_pred_prob,Y_train))

Fitting 5 classifiers...
Fitting classifier1: xgbclassifier (1/5)
XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None,
              colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,
              early_stopping_rounds=None, enable_categorical=False,
              eval_metric=None, feature_types=None, gamma=0, gpu_id=-1,
              grow_policy='depthwise', importance_type=None,
              interaction_constraints='', learning_rate=0.300000012,
              max_bin=256, max_cat_threshold=64, max_cat_to_onehot=4,
              max_delta_step=0, max_depth=5, max_leaves=0, min_child_weight=1,
              missing=nan, monotone_constraints='()', n_estimators=3000,
              n_jobs=0, num_parallel_tree=1, predictor='auto', random_state=0, ...)
Fitting classifier2: decisiontreeclassifier (2/5)
DecisionTreeClassifier()
Fitting classifier3: mlpclassifier (3/5)
MLPClassifier(alpha=1e-05, hidden_layer_sizes=(32, 16, 4),
              learning_rate='invscaling', random_state=1, solver='lbfgs')

Fitting classifier4: randomforestclassifier (4/5)
RandomForestClassifier(n_estimators=1000)
Fitting classifier5: pipeline (5/5)
Pipeline(steps=[('scaler', StandardScaler()),
                ('sgd', SGDClassifier(loss='modified_huber', penalty='l1'))])
              precision    recall  f1-score   support

           0     0.9162    0.8733    0.8942       576
           1     0.7865    0.8540    0.8189       315

    accuracy                         0.8664       891
   macro avg     0.8514    0.8636    0.8565       891
weighted avg     0.8704    0.8664    0.8676       891

0.22000066108562064

输出预测结果

submission = pd.DataFrame({
        "PassengerId": test_df["PassengerId"],
        "Survived": Y_pred
    })
submission.to_csv('../input/submission.csv', index=False)

总结

在后面的项目作业中,希望大家可以按照这个步骤去处理和分析数据。当然,这个项目不能可能学习所有处理各类问题的技巧和方法,但是最基础最主要的内容都已经通过结构化和流程化的方式放在这里了,希望未来遇到自己无法处理的问题,能够合理使用搜索工具,找到解决方案。当然,在Titanic比赛的Kaggle主页,还介绍了一些其他的更高级的方法。感兴趣的同学可以进一步自行阅读和实践。
有一些内容我们没有讲到,或者没有系统的讲完整的(如下),希望大家能够在实践中不断学习,并完善自己的知识体系。
1. 变量选择
2. 模型评估
3. 模型选择
3. 模型选择


通过这个项目,你觉得哪些工作对模型预测准确度的提升有较大影响?
文章来源地址https://www.toymoban.com/news/detail-763122.html

  1. 对数据的认识很重要
  2. 数据中的特殊点/离群点的分析和处理很重要
  3. 特征工程很重要
  4. 模型融合很重要

参考资料

  1. A journey through Titanic
  2. Getting Started with Pandas: Kaggle’s Titanic Competition
  3. Titanic Best Working Classifier
  4. Titanic Data Science Solutions
  5. An Interactive Data Science Tutorial
  6. 机器学习系列(3)_逻辑回归应用之Kaggle泰坦尼克之灾
  7. 七种常用特征工程
  8. 知乎-特征工程到底是什么?
  9. 点击率预测综述(上篇)
  10. 用简单易懂的语言描述「过拟合 overfitting」?
  11. Seaborn示例
  12. 交叉验证(Cross-validation)
  13. 交叉验证在sklearn中的实现
  14. 交叉验证和bias-tradeoff的权衡
  15. Kaggle机器学习之模型融合(stacking)心得
  16. 逻辑回归(Logistic Regression)
  17. sklearn官方文档
  18. 如何在 Kaggle 首战中进入前 10%
  19. Kaggle Ensembling Guide
  20. 【机器学习】模型融合方法概述
  21. 机器学习:聊聊机器学习模型集成学习算法——Bagging
  22. 机器学习(二) 如何做到Kaggle排名前2%
  23. Scikit-learn使用总结

到了这里,关于Titanic 泰坦尼克数据集 特征工程 机器学习建模的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 泰坦尼克号沉船数据分析与可视化、数据建模与分类预测【Python | 机器学习-Sklearn】

    前言:泰坦尼克号,不只是卡梅隆导演的经典电影,它是一个真实存在的悲剧,也是电影的故事背景与题材。作为一个IT人,分析事实还得看数据,了解到泰坦尼克号沉船幸存者多为老人、小孩和妇女,而牺牲者多为年轻的男士,这样的历史数据,让我感受到了人性之美与善

    2024年02月02日
    浏览(54)
  • 用决策树或随机森林解决泰坦尼克号乘客生存预测(内附数据集百度网盘)

     实现该模型的训练要用到的主要算法和实现思路是   首先的首先当然是导包啦   然后就是读取文件里面的数据进来了 数据集下载:百度网盘 链接:https://pan.baidu.com/s/1slaouE4Es37U8u0U-kDJnw 提取码:ss5o   接着是进行对数据进行基本的处理了,以下是作者的处理方法: 第一步是

    2024年02月15日
    浏览(49)
  • 【机器学习kaggle赛事】泰坦尼克号生存预测

    目录 写在前面  数据集情况查看 数据清洗 Embarked: Fare Age Cabin  特征工程 1,探究Sex与Survived的相关性  2,探究Pcalss与Survived的关联性  3,Embarked:不同的上船地点对生存率是否有影响  ​4,Name与Survived的相关性  5,Cabin与Survived之间的相关性 6,探究孤身一人和有家人陪伴的

    2023年04月23日
    浏览(53)
  • 速通——决策树(泰坦尼克号乘客生存预测案例)

    一、决策树 1、概述         树中每个内部节点表示一个特征上的判断,每个分支代表一个判断结果的输出,每个叶子节点代表一种分类结果 2、建立过程         1. 特征选择:选取有较强分类能力的特征。         2. 决策树生成:根据选择的特征生成决策树。  

    2024年01月21日
    浏览(49)
  • 【从零开始学Kaggle竞赛】泰坦尼克之灾

    注册kaggle账号后,进入titanic竞赛界面 https://www.kaggle.com/competitions/titanic 进入后界面如下 Overview部分为竞赛整体介绍,包括竞赛介绍以及结果评估。 Data部分为数据集介绍,介绍使用的数据集。 Code部分为提交的代码 泰坦尼克号的沉没是历史上最臭名昭著的沉船事故之一。 19

    2024年02月13日
    浏览(92)
  • Kaggle实战入门:泰坦尼克号生还预测(进阶版)

    Kaggle实战入门:泰坦尼克号生还预测(基础版)对机器学习的全流程进行了总体介绍。本文继续以泰坦尼克号生还预测为例,对机器学习中的特征工程、模型构建进行深入解读。 数据集及代码下载 由于针对训练数据集、测试数据集均要做空值填充、编码转换、离散化、归一

    2024年02月02日
    浏览(43)
  • 深度学习项目:泰坦尼克号生存预测【附完整源码】

    数据处理 建立模型 训练模型 评估模型 模型预测 保存模型 数据文件: 2.1 泰塔尼克号数据 数据描述: RMS 泰坦尼克号的沉没是历史上最为人熟知的海难事件之一。 1912 年 4 月 15 日,在她的处女航中,泰坦尼克号在与冰山相撞后沉没,在船上的 2224 名乘客和机组人员中,共造

    2024年02月09日
    浏览(52)
  • 基于用Hive泰坦尼克号乘客信息存储与分析

    实现以下任务: 创建数据库taitan 创建乘客信息表 导入数据到表中 统计获救与死亡情况 统计舱位分布情况 统计港口登船人数分布情况 统计性别与生存率的关系 统计客舱等级与生存率的关系 统计登船港口与生存率的关系 1.创建一个内/外部表,指定数据的存放路径。 (1)创建

    2024年02月06日
    浏览(53)
  • 极简sklearn-使用决策树预测泰坦尼克号幸存者

    泰坦尼克号幸存者数据集是kaggle竞赛中入门级的数据集,今天我们就来用决策树来预测下哪些人会成为幸存者。 数据集下载地址: https://download.csdn.net/download/ting4937/87630361  数据集中包含两个csv文件,data为训练用数据,test为测试集。 首先我们通过pandas来读取并查看数据 数据如

    2024年02月04日
    浏览(81)
  • 深度学习之构建MPL神经网络——泰坦尼克号乘客的生存分析

          大家好,我是带我去滑雪!       本期使用泰坦尼克号数据集,该数据集的响应变量为乘客是生存还是死亡(survived,其中1表示生存,0表示死亡),特征变量有乘客舱位等级(pclass)、乘客姓名(name)、乘客性别(sex,其中male为男性,female为女性)、乘客年龄(ag

    2024年02月05日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包