Python 机器学习 基础 之 【实战案例】轮船人员获救预测实战
目录
Python 机器学习 基础 之 【实战案例】轮船人员获救预测实战
一、简单介绍
二、轮船人员获救预测实战
三、数据处理
1、导入数据
2、对缺失数据的列进行填充
3、属性转换,把某些列的字符串值转换为数字
四、建立模型
1、引入机器学习库
2、实例化模型
3、把数据传入模型,预测结果
五、算法概率计算
六、集成算法,构建多棵分类树
1、构造多个分类器
2、随机森林
七、特征提取
1、进行特征选择
2、用视图的方式展示
八、集成多种算法
九、小结
一、简单介绍
Python是一种跨平台的计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越多被用于独立的、大型项目的开发。Python是一种解释型脚本语言,可以应用于以下领域: Web 和 Internet开发、科学计算和统计、人工智能、教育、桌面界面开发、软件开发、后端开发、网络爬虫。
Python 机器学习是利用 Python 编程语言中的各种工具和库来实现机器学习算法和技术的过程。Python 是一种功能强大且易于学习和使用的编程语言,因此成为了机器学习领域的首选语言之一。Python 提供了丰富的机器学习库,如Scikit-learn、TensorFlow、Keras、PyTorch等,这些库包含了许多常用的机器学习算法和深度学习框架,使得开发者能够快速实现、测试和部署各种机器学习模型。
Python 机器学习涵盖了许多任务和技术,包括但不限于:
- 监督学习:包括分类、回归等任务。
- 无监督学习:如聚类、降维等。
- 半监督学习:结合了有监督和无监督学习的技术。
- 强化学习:通过与环境的交互学习来优化决策策略。
- 深度学习:利用深度神经网络进行学习和预测。
通过 Python 进行机器学习,开发者可以利用其丰富的工具和库来处理数据、构建模型、评估模型性能,并将模型部署到实际应用中。Python 的易用性和庞大的社区支持使得机器学习在各个领域都得到了广泛的应用和发展。
二、轮船人员获救预测实战
在接下来的内容中,我们将深入探索轮船人员获救预测的实战演练,这将是一个将理论知识转化为实际应用的绝佳机会。通过应用我们之前学习的各种算法,例如决策树分类算法、随机森林等,我们将能够将机器学习的强大能力整合到具体的业务场景中。
本文将系统地覆盖从数据的初步处理到最终模型的评估与优化的全过程。首先,我们会对数据进行清洗和预处理,确保数据的质量,为后续分析打下坚实的基础。接着,我们将进入特征工程阶段,这一步骤至关重要,因为它涉及到从原始数据中提取有用信息,并构建能够代表问题本质的特征集。
随后,我们将面临模型选择的挑战,这需要我们根据问题的具体情况和数据的特性,选择最合适的机器学习模型。这可能包括决策树、随机森林、支持向量机、神经网络等算法,每种算法都有其独特的优势和适用场景。
一旦模型被选定,我们将进入模型训练阶段,通过不断调整参数,优化模型的性能,使其达到最佳的预测效果。最后,我们将对模型进行严格的评估,通过交叉验证、混淆矩阵、ROC曲线等手段,全面了解模型的准确性、泛化能力和预测能力。
通过这一系列的步骤,我们不仅能够掌握机器学习算法在实际问题中的应用,还能够学习到如何对模型进行迭代优化,以应对不断变化的数据和业务需求。这将是一次充满挑战和收获的学习旅程,让我们期待在实战中取得丰硕的成果。
三、数据处理
本文的实战项目将使用CSV格式的数据集,这种格式的数据文件非常适合进行数据分析和机器学习任务。数据集以典型的dataframe格式呈现,它包含了12列丰富的信息,每列都对应着乘客的不同个人信息。以下是对这些数据列的详细介绍:
-
PassengerId:这是每位乘客的唯一标识符,有助于在数据集中唯一确定一个乘客。
-
Pclass:表示乘客的舱位等级,通常分为头等舱(1)、二等舱(2)和三等舱(3),这可能与乘客的社会经济地位有关。
-
Name:乘客的姓名,这可能包括乘客的全名和可能的头衔。
-
Sex:乘客的性别,通常用男性(male)和女性(female)来区分。
-
Age:乘客的年龄,这可能对预测乘客是否获救有重要影响。
-
SibSp:表示乘客的兄弟姐妹和配偶的人数,这可能反映了乘客的家庭状况。
-
Parch:表示乘客的父母和孩子的人数,这有助于了解乘客的家庭结构。
-
Ticket:包含乘客的船票信息,可能包括船票号码和相关的预订信息。
-
Fare:乘客支付的票价,这可能与舱位等级和乘客的社会经济地位有关。
-
Cabin:乘客的客舱信息,可能包括客舱的位置和类型。
-
Embarked:乘客登船的港口,这可能对分析乘客的地理分布和登船习惯有帮助。
这些数据列为我们提供了一个全面的视角来分析和预测乘客的生存情况。通过对这些特征的深入分析和特征工程,我们可以构建出能够预测乘客是否能够在灾难中幸存的模型。此外,这些数据列还可能揭示出一些有趣的模式和关联,比如不同舱位等级、性别、家庭状况等因素对生存率的影响。通过对这些数据的深入挖掘和分析,我们将能够更好地理解历史事件,并为未来的数据分析和预测建模提供宝贵的经验。
1、导入数据
首先导入Pandas库,Pandas是常用的Python数据处理包,可以把CSV文件读入成dataframe格式。代码如下:
# 导入warnings模块,用于控制警告信息的显示
import warnings# 设置warnings模块,忽略所有的警告信息
# 这通常用于避免在执行代码时显示不必要的警告,使输出更清晰
warnings.filterwarnings('ignore')# 导入pandas库,pandas是一个强大的数据分析和操作库,常用于数据预处理
import pandas# 导入numpy库,并将其简称为np
# numpy是一个用于科学计算的Python库,提供大量的数学函数操作
import numpy as np# 使用pandas的read_csv函数读取名为"data/ship_train.csv"的CSV文件
# 这个文件被加载到一个名为ship的pandas DataFrame对象中
# DataFrame是pandas中用于存储表格数据的主要数据结构
ship = pandas.read_csv("data/ship_train.csv")# 打印ship DataFrame的描述性统计信息
# describe()函数提供了数据的概览,包括计数、平均值、标准差、最小值、四分位数和最大值
# 这有助于快速了解数据的分布情况
print(ship.describe())
这里的describe可以对数据进行简单处理,例如可以查看数据的大小、判断有无缺失,以及查看平均值、最小值等。在ipython notebook中,data_train如下:PassengerId Survived Pclass Age SibSp \ count 891.000000 891.000000 891.000000 714.000000 891.000000 mean 446.000000 0.383838 2.308642 29.699118 0.523008 std 257.353842 0.486592 0.836071 14.526497 1.102743 min 1.000000 0.000000 1.000000 0.420000 0.000000 25% 223.500000 0.000000 2.000000 20.125000 0.000000 50% 446.000000 0.000000 3.000000 28.000000 0.000000 75% 668.500000 1.000000 3.000000 38.000000 1.000000 max 891.000000 1.000000 3.000000 80.000000 8.000000 Parch Fare count 891.000000 891.000000 mean 0.381594 32.204208 std 0.806057 49.693429 min 0.000000 0.000000 25% 0.000000 7.910400 50% 0.000000 14.454200 75% 0.000000 31.000000 max 6.000000 512.329200
这段代码主要用于数据的加载和初步的统计分析。通过pandas库读取CSV文件,并使用describe()函数快速查看数据的基本统计特征。忽略警告信息是为了在输出时避免显示可能的非关键性警告,使得输出结果更加专注于数据本身。
上述的处理是无法查看数据类型的,例如字符串中类型的“名字”这个类别就没有被包含进去。因为下一步我们要将所需数据的类型全部转换成数字以方便计算,所以使用info方法查看数据的类型。查看类型的代码如下:
print(ship.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 float646 SibSp 891 non-null int64 7 Parch 891 non-null int64 8 Ticket 891 non-null object 9 Fare 891 non-null float6410 Cabin 204 non-null object 11 Embarked 889 non-null object dtypes: float64(2), int64(5), object(5) memory usage: 83.7+ KB None
2、对缺失数据的列进行填充
在处理矩阵运算时,缺失值是一个必须面对的问题,因为它们会直接影响到数据分析和模型训练的有效性。以下是对缺失值处理方法的进一步阐述和丰富:
-
高比例缺失值的处理:当某个特征的缺失值占到数据集的很大一部分时,这个特征可能不再具有足够的信息价值。在这种情况下,我们可能会选择舍弃这个特征,因为它不仅不能提供有用的信息,反而可能引入噪声,降低模型的预测准确率。
-
适度比例缺失值的处理:如果缺失值的数量不是很多,我们可以考虑使用一些统计方法来估计缺失值。这些方法可能包括:
- 使用该特征的均值、中位数或众数来填充缺失值。
- 根据其他特征与缺失特征之间的关系,使用回归模型来预测缺失值。
- 应用更高级的算法,如K-最近邻(K-NN)或基于模型的方法来估计缺失值。
-
重要特征的缺失值处理:对于那些对模型预测至关重要的特征,如年龄,我们不能简单地舍弃它们。对于这类特征,即使缺失值不多,我们也需要采用一种更加精细的处理方法。
-
年龄特征的缺失值填充:以年龄为例,由于它是一个关键的预测因素,我们通常会选择用该特征的平均值来填充缺失值。这种方法简单易行,能够在保持数据集完整性的同时,最小化对模型准确率的影响。
-
填充代码示例:以下是使用Python的pandas库来填充年龄列缺失值的示例代码:
# 使用pandas库中的fillna方法填充DataFrame中'Age'列的缺失值
# fillna方法用于替换DataFrame中的缺失值(NaN)
# 这里,我们使用ship["Age"].median()来计算'Age'列的中位数
# 然后将这个中位数用来填充'Age'列中的所有缺失值
# 中位数作为填充值可以减少极端值的影响,是一种常用的缺失值处理方法
ship["Age"] = ship["Age"].fillna(ship["Age"].median())# 打印更新后的DataFrame 'ship'的描述性统计信息
# describe()方法提供了DataFrame中数值型列的统计摘要
# 包括计数、平均值、标准差、最小值、25%分位数、50%分位数(中位数)、75%分位数和最大值
# 这有助于快速了解填充缺失值后数据的分布情况
print(ship.describe())
填充后Age的数据由原本的714个变成了891个,达到了我们的目的。数据如下:PassengerId Survived Pclass Age SibSp \ count 891.000000 891.000000 891.000000 891.000000 891.000000 mean 446.000000 0.383838 2.308642 29.361582 0.523008 std 257.353842 0.486592 0.836071 13.019697 1.102743 min 1.000000 0.000000 1.000000 0.420000 0.000000 25% 223.500000 0.000000 2.000000 22.000000 0.000000 50% 446.000000 0.000000 3.000000 28.000000 0.000000 75% 668.500000 1.000000 3.000000 35.000000 1.000000 max 891.000000 1.000000 3.000000 80.000000 8.000000 Parch Fare count 891.000000 891.000000 mean 0.381594 32.204208 std 0.806057 49.693429 min 0.000000 0.000000 25% 0.000000 7.910400 50% 0.000000 14.454200 75% 0.000000 31.000000 max 6.000000 512.329200
这段代码的目的是处理数据集中'Age'列的缺失值,并提供了填充后的统计摘要,帮助我们理解数据的基本情况和分布特征。通过使用中位数来填充缺失值,我们能够在一定程度上减少由于极端值带来的影响,并且保持数据的中心趋势。
3、属性转换,把某些列的字符串值转换为数字
数据操作的另一步是将字符用数值代表,例如sex是字符串,无法进行计算,将它转换成数字,用0代表man,用1代表female。属性转换代码如下:
# 将字符用数值代表
# 这一步骤是为了将分类数据(categorical data)转换为数值数据(numerical data)
# 因为大多数机器学习算法不能直接处理字符串类型的分类数据# sex是字符串,无法进行计算,将它转换为数字,用0代表man,用1代表female
# 首先打印出'Sex'列中所有不同的值(即唯一值)
# unique()函数返回Series中的唯一值,这有助于我们了解数据中的分类情况
print(ship["Sex"].unique())# 将所有的male替换为数字0
# loc是pandas中的一个函数,用于基于标签的索引/赋值
# 这里使用loc选择'Sex'列中值为'male'的所有行,并将对应的'Sex'值替换为0
ship.loc[ship["Sex"] == "male", "Sex"] = 0# 将所有的female替换为数字1
# 同样使用loc函数,选择'Sex'列中值为'female'的所有行,并将对应的'Sex'值替换为1
# 这样,'Sex'列就从字符串类型的分类数据转换为了数值型的0和1
ship.loc[ship["Sex"] == "female", "Sex"] = 1
['male' 'female']
这段代码的目的是将ship
DataFrame中的Sex
列,由原来的字符串分类数据("male"和"female")转换为数值型数据(0代表"male",1代表"female")。这种转换对于后续的机器学习模型训练是非常必要的,因为大多数模型只能接受数值型输入。通过这种方式,我们能够将分类数据编码为模型可以理解的格式。
同样地,将3个登录地点“S”“C”“Q”转换成数字,0代表S,1代表C,2代表Q,代码如下:
# 打印'Embarked'列中所有不同的值
# Embarked列代表乘客登船的港口,其值可能是'S'、'C'或'Q',分别代表南安普顿(Southampton)、瑟堡(Cherbourg)和皇后镇(Queenstown)
# unique()函数返回Series中的唯一值,这有助于了解数据中包含的港口类别
print(ship["Embarked"].unique())# 登船的地点也是字符串,需要转换为数字,并填充缺失值
# 在机器学习中,通常需要将分类变量转换为数值型,以便算法可以处理
# 首先,使用fillna方法填充'Embarked'列中的缺失值
# 这里将缺失值填充为'S',假设'S'是数据集中的一个有效港口代码
ship["Embarked"] = ship["Embarked"].fillna('S')# loc通过索引获取数据
# loc是pandas中的一个函数,用于基于标签的索引/赋值
# 接下来,使用loc函数将'Embarked'列中的港口代码转换为数值型
# 这里将'S'、'C'和'Q'分别映射为0、1和2# 将'Embarked'列中所有值为'S'的行的'Embarked'列替换为0
ship.loc[ship["Embarked"] == "S", "Embarked"] = 0# 将'Embarked'列中所有值为'C'的行的'Embarked'列替换为1
ship.loc[ship["Embarked"] == "C", "Embarked"] = 1# 将'Embarked'列中所有值为'Q'的行的'Embarked'列替换为2
ship.loc[ship["Embarked"] == "Q", "Embarked"] = 2
['S' 'C' 'Q' nan]
这段代码的目的是将ship
DataFrame中的Embarked
列,由原来的字符串分类数据(代表不同的登船港口)转换为数值型数据。这种转换对于后续的机器学习模型训练是非常必要的,因为大多数模型只能接受数值型输入。通过这种方式,我们能够将分类数据编码为模型可以理解的格式,并且填充了缺失值,确保了数据的完整性。
四、建立模型
1、引入机器学习库
导入线性回归,使用回归算法二分类进行预测;导入交叉验证,代码如下:
# 机器学习算法(线性回归)
# 线性回归是一种监督学习算法,用于预测连续的输出值
# 它尝试找到特征和目标变量之间的线性关系,并用该关系来预测新数据的目标值# 导入线性回归库
# 使用sklearn的LinearRegression类,我们可以创建一个线性回归模型
# 这个模型将用于拟合数据并预测连续的目标变量
from sklearn.linear_model import LinearRegression# 导入交叉验证库
# 交叉验证是一种模型评估方法,用于评估模型的泛化能力
# 它通过将数据集分成多个部分,在不同的子集上训练和测试模型,来减少评估误差# KFold是交叉验证的一种实现,它将数据集分割成K个子集
# 在每一轮中,选择其中一个子集作为测试集,其余的作为训练集
# 这样,每个数据点都被用于测试一次,而作为训练数据K-1次
# 这有助于我们更全面地评估模型的性能
from sklearn.model_selection import KFold
这段代码的目的是为机器学习任务准备所需的工具和方法。首先,通过LinearRegression
类导入线性回归模型,这是一种常用的回归算法,适用于预测连续的输出值。接着,通过KFold
类导入交叉验证方法,这是一种评估模型性能的重要技术,可以帮助我们更准确地了解模型在未知数据上的表现。通过结合使用线性回归和交叉验证,我们可以构建一个稳健的预测模型,并对其性能进行有效的评估。
2、实例化模型
选中一些用来训练模型的特征,并将样本数据进行3层交叉验证,代码如下:
# 用来预测目标的列
# 定义predictors列表,包含用于预测的自变量列名
# 这些列将作为特征输入到线性回归模型中
# "Pclass"代表乘客的舱位等级,"Sex"代表性别,"Age"代表年龄
# "SibSp"代表兄弟姐妹/配偶的数量,"Parch"代表父母和孩子的数量
# "Fare"代表票价,"Embarked"代表登船港口
predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]# 对线性回归类进行实例化
# 创建一个LinearRegression类的实例,命名为alg
# 这个实例将用于拟合数据并进行预测
alg = LinearRegression()# 为泰坦尼克号数据集生成交叉验证折叠
# 使用KFold类创建一个交叉验证器,它将数据集分割成多个部分
# 每一部分轮流作为测试集,而其他部分作为训练集
# n_splits=3表示数据集将被分成3份,进行3次训练和测试
# random_state=1设置随机数生成器的种子,以确保每次分割的一致性
# shuffle=True表示在分割前对数据进行随机打乱,以避免数据顺序影响结果
kf = KFold(n_splits=3, random_state=1, shuffle=True)
这段代码的目的是为线性回归模型的建立和评估做准备。首先,定义了一个特征列表predictors
,这些特征将用于预测目标变量。然后,实例化了一个LinearRegression
对象alg
,用于后续的数据拟合和预测。最后,使用KFold
创建了一个交叉验证器,用于生成训练集和测试集的索引,以便于评估模型的性能。通过设置random_state
和shuffle
参数,确保了交叉验证的可重复性和随机性。
3、把数据传入模型,预测结果
# 初始化一个空列表,用于存储所有测试折叠的预测结果
predictions = []# 使用KFold对象kf进行交叉验证,遍历每一对训练集和测试集的索引
for train, test in kf.split(ship):# 根据训练集索引从ship DataFrame中选取特征列# predictors是特征列的列表,.iloc[train,:]根据行索引选择数据train_predictors = ship[predictors].iloc[train,:]# 根据训练集索引从ship DataFrame中选取目标列"Survived"# 目标列是我们想要预测的列,即乘客是否存活train_target = ship["Survived"].iloc[train]# 使用fit方法训练线性回归模型alg# 传入训练特征集train_predictors和目标集train_target# 这一步是模型学习特征和目标之间关系的过程alg.fit(train_predictors, train_target)# 使用训练好的模型alg对测试集进行预测# 根据测试集索引从ship DataFrame中选取特征列# predict方法返回测试集的预测结果test_predictions = alg.predict(ship[predictors].iloc[test,:])# 将得到的测试集预测结果添加到predictions列表中# 最终,predictions列表将包含每一轮交叉验证的预测结果predictions.append(test_predictions)
这段代码的目的是实现交叉验证过程中的模型训练和预测。通过KFold
对象kf
,代码遍历每一对训练集和测试集的索引。对于每一对索引,代码从ship
DataFrame中选取相应的特征列和目标列,然后使用这些数据训练线性回归模型alg
。训练完成后,模型被用来对当前的测试集进行预测,并将预测结果存储在predictions
列表中。这个过程重复进行,直到所有的测试集都被预测过,从而完成整个交叉验证过程。
五、算法概率计算
将预测正确的数目除以总量,代码如下:
# 使用numpy的concatenate函数将predictions列表中所有的数组合并成一个数组
# predictions列表包含了通过交叉验证得到的各个测试集的预测结果
# axis=0参数表示沿着第一个轴(行)进行合并,即将所有数组垂直堆叠起来
predictions = np.concatenate(predictions, axis=0)# 将预测结果映射到二分类结果(0或1)
# 线性回归模型的输出是一个连续值,我们需要将其转换为二分类结果
# 这里使用的阈值是0.5,大于0.5的预测结果被视为1(预测为存活),小于等于0.5的被视为0(预测为未存活)
predictions[predictions > .5] = 1
predictions[predictions <= .5] = 0# 计算准确率
# 首先,使用条件索引找出预测正确的结果,即预测结果与实际结果(ship["Survived"])相等的元素
# 然后,计算这些正确预测的数量,并除以总预测数(len(predictions)),得到准确率
accuracy = sum(predictions[predictions == ship["Survived"]]) / len(predictions)# 打印准确率
# 这个值表示模型预测的准确性,是评估模型性能的一个重要指标
print(accuracy)
这段代码的目的是将交叉验证得到的连续预测结果转换为二分类结果,并计算模型的准确率。首先,使用np.concatenate
将所有测试集的预测结果合并成一个数组。然后,根据阈值0.5将连续的预测结果转换为0或1的分类结果。最后,通过比较预测结果和实际结果,计算并打印出模型的准确率,这是一个衡量模型性能的关键指标。
该算法得到的准确率为:0.13468013468013468。
目前的准确率比较低,下面我们再介绍其他几种算法来提高一下预测的准确率。
六、集成算法,构建多棵分类树
1、构造多个分类器
从sklearn库导入交叉验证和逻辑回归模块,实例化逻辑回归算法,使用3层交叉验证得到概率值,代码如下:
# 导入逻辑回归所需的库
# 逻辑回归是一种用于二分类问题的机器学习算法,它预测的是事件发生的概率
from sklearn.linear_model import LogisticRegression# 导入cross_val_score函数
# cross_val_score用于计算交叉验证的分数,如准确率、召回率等
from sklearn.model_selection import cross_val_score# 实例化LogisticRegression类,创建一个逻辑回归模型
# random_state参数设置为1,确保每次分割数据时结果相同,增加模型的可复现性
alg = LogisticRegression(random_state=1)# 计算所有交叉验证折叠的准确率
# cross_val_score函数计算给定模型在交叉验证中的表现
# alg是逻辑回归模型,ship[predictors]是特征数据,ship["Survived"]是目标变量
# cv=3表示使用3折交叉验证,即数据被分为3份,每份轮流作为测试集
scores = cross_val_score(alg, ship[predictors], ship["Survived"], cv=3)# 打印分数的平均值
# 由于每一折交叉验证都会得到一个分数,scores.mean()计算这些分数的平均值
# 这个平均值提供了模型整体性能的一个估计
print(scores.mean())# 注意事项
# 逻辑回归与线性回归的输出类型不同
# 逻辑回归输出的是概率值,表示某个事件发生的可能性
# 而线性回归输出的是[0,1]区间的数值,表示连续的预测结果
# 通常逻辑回归的输出需要通过阈值(如0.5)转换为二分类结果
这段代码的目的是使用逻辑回归模型对轮船数据集进行分类,并评估模型的性能。首先,通过LogisticRegression
类创建逻辑回归模型实例。然后,使用cross_val_score
函数计算模型在3折交叉验证中的准确率。最后,打印出这些准确率的平均值,作为模型性能的一个估计。同时,代码注释中提到了逻辑回归与线性回归在输出类型上的区别。
通过逻辑回归,最终准确率为:0.7957351290684623。可以看出相较于之前的算法,准确率有了明显的提高。
2、随机森林
导入交叉验证与随机森林模块,random_state=1表示此处代码多运行几次得到的随机值都是一样的,如果不设置,则两次执行的随机值是不一样的。n_estimators指定有多少棵决策树,树的分裂的条件是:min_samples_split代表样本不停地分裂,某一个节点上的样本如果只有2个,就不再继续分裂。min_samples_leaf是控制叶子节点的最小个数。构建随机森林(构造多少棵树、最小切分点、最少的叶子节点个数)控制树的高度,以防止过拟合,代码如下:
# 导入随机森林分类器和梯度提升分类器
# 这两个都是集成学习方法,用于分类任务
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier# 定义用于模型训练的特征列
predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]# 初始化随机森林分类器算法
# 使用默认参数,同时指定一些关键参数以控制模型的行为
# n_estimators参数定义了要生成的决策树的数量,更多的树通常可以提高模型的性能
# min_samples_split定义了在决策树中进行拆分操作所需的最小样本数
# min_samples_leaf定义了决策树中叶节点的最小样本数
alg = RandomForestClassifier(random_state=1, n_estimators=10, min_samples_split=2, min_samples_leaf=1)# 计算所有交叉验证折叠的准确率
# 使用KFold对象进行3折交叉验证,每次拆分数据前都会打乱
kf = KFold(n_splits=3, random_state=1, shuffle=True)# 使用cross_val_score函数计算随机森林模型在交叉验证中的准确率
# ship[predictors]是特征数据,ship["Survived"]是目标变量
# cv参数设置为kf,使用上面定义的交叉验证方案
scores = cross_val_score(alg, ship[predictors], ship["Survived"], cv=kf)# 打印分数的平均值
# 每一折交叉验证都会给出一个准确率分数,scores.mean()计算这些分数的平均值
# 这个平均准确率提供了模型整体性能的一个估计
print(scores.mean())
这段代码的目的是使用随机森林分类器对轮船数据集进行分类,并评估模型的性能。首先,定义了模型将要使用的特征列。然后,创建了一个RandomForestClassifier
实例,并设置了一些关键的参数来控制模型的行为。接着,使用KFold
对象定义了一个3折交叉验证方案,并使用cross_val_score
函数来计算模型在交叉验证中的准确率。最后,打印出这些准确率的平均值,作为模型性能的一个估计。
随机森林算法处理后得到准确率为:0.7957351290684626。
这里增加决策树的数量,能使模型准确率更高。当然,也不是树越多越好,达到一定数量后,将不会对准确率产生很大的影响。
# 初始化随机森林分类器算法
# RandomForestClassifier是一种集成学习方法,适用于分类和回归任务
# random_state设置为1,以确保每次运行代码时数据分割的一致性
# n_estimators=50表示使用50棵树构建随机森林,增加树的数量可以提高模型的准确性
# min_samples_split=4表示只有当一个节点的样本数大于或等于4时,才会进行拆分
# min_samples_leaf=2表示只有当叶节点的样本数大于或等于2时,才会保留该叶节点
alg = RandomForestClassifier(random_state=1, n_estimators=50, min_samples_split=4, min_samples_leaf=2)# 创建KFold对象,用于3折交叉验证
# n_splits=3表示将数据集分为3份,每份轮流作为测试集
# random_state=1确保每次分割的数据相同,shuffle=True表示在分割前会随机打乱数据
kf = KFold(n_splits=3, random_state=1, shuffle=True)# 使用cross_val_score计算随机森林模型在交叉验证中的准确率
# 传入模型alg,特征数据ship[predictors],目标变量ship["Survived"],以及交叉验证方案kf
# cross_val_score会返回一个数组,包含每次交叉验证的准确率分数
scores = cross_val_score(alg, ship[predictors], ship["Survived"], cv=kf)# 打印分数的平均值
# scores.mean()计算交叉验证得到的准确率分数的平均值
# 这个平均准确率是模型性能的一个指标,反映了模型在未知数据上的泛化能力
print(scores.mean())
这段代码的目的是使用随机森林分类器对数据集进行分类任务,并使用交叉验证来评估模型的性能。通过设置不同的参数,可以调整模型的复杂度和性能。交叉验证的目的是减少模型评估的方差,提供更稳健的性能估计。最后,通过打印平均准确率,我们可以了解模型在整体数据集上的表现。
得到准确率为:0.8260381593714926。可以看出,准确率由于决策树数量的增加而有了相应的提高。
七、特征提取
由于事先不知道哪些数据对模型的预测有影响,我们假设兄弟姐妹、老人小孩的人数对实验有影响,把这两个数据整合到一起统称为家庭人数。再假设人名字的长度也有影响。代码如下:
# 生成一个名为"FamilySize"的新列
# 这个列是通过将"SibSp"(兄弟姐妹/配偶的数量)和"Parch"(父母和孩子的数量)相加得到的
# "FamilySize"列表示乘客的家庭大小,即与乘客一起旅行的家庭成员总数
ship["FamilySize"] = ship["SibSp"] + ship["Parch"]# 使用apply方法生成一个新的列"NameLength"
# apply方法允许我们对DataFrame中的列应用一个函数
# 这里使用了一个lambda函数,它是一个匿名函数,用于返回每个姓名的长度
# len(x)计算每个乘客姓名字符串的长度
# 这样,"NameLength"列将包含每个乘客姓名的长度
ship["NameLength"] = ship["Name"].apply(lambda x: len(x))
这段代码的目的是为ship
DataFrame添加两个新的特征列:FamilySize
和NameLength
。FamilySize
列通过将SibSp
和Parch
列的值相加来计算乘客的家庭规模。NameLength
列则利用apply
方法和lambda
表达式来计算每个乘客姓名的长度。这些新生成的特征可能会在后续的数据分析或模型训练中起到作用,因为它们可能与乘客的生存概率有关联。
导入正则表达式模块,统计打印所有称谓的个数,并将称谓转换成数字。代码如下:
import re
# 导入正则表达式模块re,用于文本的搜索和匹配# 定义一个函数get_title,用于从乘客姓名中提取标题
def get_title(name):# 使用正则表达式re.search来查找符合模式的字符串# 模式' ([A-Za-z]+)\.'用于匹配由一个空格开头,后面跟着一个或多个大小写字母,并且以句号结束的字符串# 这通常对应于乘客姓名中的头衔部分title_search = re.search(' ([A-Za-z]+)\.', name)# 如果正则表达式搜索找到了匹配项,返回匹配的字符串(即标题)# group(1)方法返回第一个括号中匹配的字符串if title_search:return title_search.group(1)# 如果没有找到标题,返回空字符串return ""# 使用apply方法和get_title函数从"Name"列中提取所有乘客的标题
titles = ship["Name"].apply(get_title)# 打印每个标题出现的频率
# 使用pandas的value_counts函数统计各个标题的数量
print(pandas.value_counts(titles))# 定义一个字典title_mapping,用于将标题映射为整数
# 某些罕见的标题被映射为常见标题的相同数字代码
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
}# 遍历title_mapping字典中的所有项
for k, v in title_mapping.items():# 将titles列中匹配特定标题的值替换为对应的整数代码titles[titles == k] = v# 在映射所有标题之后,再次打印标题的频率
# 这验证了映射是否成功应用
print(pandas.value_counts(titles))# 将处理后的标题添加到原始的ship DataFrame中,作为新的列"Title"
ship["Title"] = titles
这段代码的目的是处理泰坦尼克号乘客名单中的姓名数据,提取出乘客的头衔,并将其映射为整数代码。首先,定义了一个函数get_title
来从姓名中提取头衔。然后,使用apply
方法和get_title
函数从姓名列中提取所有乘客的头衔,并统计每个头衔的出现频率。接下来,定义了一个映射字典title_mapping
,将常见的头衔映射为整数。通过遍历这个映射字典,将提取出的头衔替换为对应的整数代码。最后,将这些处理后的头衔作为新列"Title"
添加到原始的ship
DataFrame中。这个过程有助于简化数据,并可能为后续的数据分析或模型训练提供有用的特征。
显示结果为:
Name Mr 517 Miss 182 Mrs 125 Master 40 Dr 7 Rev 6 Mlle 2 Major 2 Col 2 Countess 1 Capt 1 Ms 1 Sir 1 Lady 1 Mme 1 Don 1 Jonkheer 1 Name: count, dtype: int64 Name 1 517 2 183 3 125 4 40 5 7 6 6 7 5 8 3 10 3 9 2 Name: count, dtype: int64
1、进行特征选择
导入特征选择模块,通过特征选择库,对选择的特征进行进一步筛选,看看哪些特征比较重要。f_classif(方差分析的F值)是评估特征的指标,k表示选择的特征的个数。特征选择代码如下:
import numpy as np
# 导入NumPy库,NumPy是一个用于科学计算的Python库,提供大量的数学函数操作from sklearn.feature_selection import SelectKBest, f_classif
# 从scikit-learn库中导入SelectKBest类和f_classif函数
# SelectKBest用于选择最佳的特征,f_classif是一个用于评估特征重要性的统计测试import matplotlib.pyplot as plt
# 导入matplotlib的pyplot模块,用于绘图predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked", "FamilySize", "Title", "NameLength"]
# 定义一个列表predictors,包含用于特征选择的特征列名# 进行特征选择
# 使用SelectKBest选择得分最高的k个特征
# f_classif是ANOVA F-value,用于分类问题的单变量特征选择
selector = SelectKBest(f_classif, k=5)
# k=5表示选择5个最佳特征# 用训练数据拟合选择器
# fit方法用于计算各个特征的得分和p值
selector.fit(ship[predictors], ship["Survived"])# 获取每个特性的原始p值,并将p值转换为分数
# p值是统计测试中的概念,用于测试特征的重要性
# 这里使用-np.log10转换p值,这是一种常见的转换方法,可以强调较小的p值(即更显著的特征)
# np.log10是以10为底的对数函数
scores = -np.log10(selector.pvalues_)
这段代码的目的是使用基于ANOVA F-value的统计测试进行特征选择,以确定对预测乘客是否存活("Survived")最有影响的特征。首先,导入所需的库和模块,然后定义一个包含所有候选特征的列表。接着,创建一个SelectKBest
实例,指定使用f_classif
函数和选择前5个特征。使用fit
方法计算各个特征的得分和p值。最后,获取p值并应用对数转换,以便在后续步骤中评估或排序特征的重要性。
2、用视图的方式展示
通过feature_selection对选择的特征做进一步选择,画出直方图可以直观地看出哪些特征对最终的准确率影响较大。代码如下:
import matplotlib.pyplot as plt
# 导入matplotlib的pyplot模块,这是一个用于绘图的库predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked", "FamilySize", "Title", "NameLength"]
# 假设predictors列表已经定义,包含所有候选特征的名称scores = -np.log10(selector.pvalues_)
# 假设scores变量已经计算,包含转换后的p值分数,用于评估特征的重要性# 画出成绩,看看“Pclass”“Sex”“Title”和“Fare”怎样才是最好的
# 使用bar函数绘制柱状图,显示每个特征的分数
# range(len(predictors))生成一个序列,作为x轴的位置
plt.bar(range(len(predictors)), scores)# 设置x轴的刻度,使其显示每个特征的名称
# range(len(predictors))生成一个序列,作为x轴的刻度位置
# predictors列表作为x轴的刻度标签
# rotation='vertical'将标签旋转90度,使其垂直显示,便于阅读
plt.xticks(range(len(predictors)), predictors, rotation='vertical')# 将图表保存到文件
# 'Images/01Main-01.png'是文件的保存路径和名称
# bbox_inches='tight'确保所有的图表内容都被包含在保存的图像中,没有被裁剪掉
plt.savefig('Images/01Main-01.png', bbox_inches='tight')# 显示图表
plt.show()
这段代码的目的是绘制一个柱状图,用于可视化不同特征的分数,这些分数是通过特征选择过程计算得出的。首先,使用plt.bar
函数创建柱状图,其中x轴位置由range(len(predictors))
给出,y轴的高度由scores
变量给出。然后,使用plt.xticks
设置x轴的刻度标签,使其显示每个特征的名称,并通过rotation='vertical'
参数将标签垂直显示。接着,使用plt.savefig
函数将图表保存为图像文件。最后,使用plt.show
函数显示图表。这样,用户可以直观地看到哪些特征在模型中更为重要。
通过以上特征的重要性分析,选择出4个最重要的特性,重新进行随机森林算法的运算。本处理是为了练习在随机森林中的特征选择,它对于实际的数据挖掘具有重要意义。特征选择之后的算法代码如下:
# 通过以上特征的重要性分析,选择出4个最重要的特性,重新进行随机森林算法的运算
# 根据之前的特征重要性分析,选择了"Pclass"、"Sex"、"Fare"和"Title"这四个特征
# 这些特征被认为在预测乘客是否存活方面最为重要
predictors = ["Pclass", "Sex", "Fare", "Title"]# 初始化随机森林分类器算法
# RandomForestClassifier是一个集成学习方法,用于分类任务
# random_state设置为1,以确保每次运行代码时结果的一致性
# n_estimators=50表示使用50棵树构建随机森林
# min_samples_split=8表示只有当一个节点的样本数大于或等于8时,才会进行拆分
# min_samples_leaf=4表示只有当叶节点的样本数大于或等于4时,才会保留该叶节点
alg = RandomForestClassifier(random_state=1, n_estimators=50, min_samples_split=8, min_samples_leaf=4)# 进行交叉验证
# 使用KFold对象进行3折交叉验证,每次拆分数据前都会打乱
kf = KFold(n_splits=3, random_state=1, shuffle=True)# 使用cross_val_score计算随机森林模型在交叉验证中的准确率
# ship[predictors]是特征数据,ship["Survived"]是目标变量
# cv=kf指定使用KFold对象定义的交叉验证方案
scores = cross_val_score(alg, ship[predictors], ship["Survived"], cv=kf)# 打印交叉验证的平均准确率
# scores.mean()计算交叉验证得到的准确率分数的平均值
# 这提供了模型在所选特征上的整体性能估计
# 根据注释,目前的结果并无明显提升,这可能是由于特征选择或其他因素
print(scores.mean())# 注释中提到,本处理是为了练习在随机森林中的特征选择
# 特征选择是数据挖掘中的一个重要步骤,有助于提高模型的性能和解释性
准确率为:0.819304152637486。
这段代码的目的是使用随机森林分类器对泰坦尼克号数据集进行分类任务,并使用交叉验证来评估模型的性能。首先,根据之前的特征重要性分析,选择了四个最重要的特征。然后,创建了一个RandomForestClassifier
实例,并设置了一些关键参数来控制模型的行为。接着,使用KFold
对象定义了一个3折交叉验证方案,并使用cross_val_score
函数来计算模型在交叉验证中的准确率。最后,打印出这些准确率的平均值,作为模型性能的一个估计。同时,代码注释中提到了特征选择的重要性和本处理的目的。
八、集成多种算法
在数据科学竞赛和实际应用中,算法集成是一种提高模型泛化能力和减少过拟合的有效策略。下面,我将对您提供的段落进行丰富和扩展:
集成学习是一种强大的机器学习技术,它通过结合多个模型的预测来提高整体性能。这种方法的核心思想是“众人拾柴火焰高”,即多个模型的集体智慧往往优于单个模型。在实践中,我们通常会遇到各种不同的算法,它们各自有着独特的优势和局限性。通过集成这些算法,我们可以充分利用它们的长处,同时减少单一模型可能带来的过拟合风险。
在这段描述中,我们关注的是两种特定的算法:GradientBoostingClassifier和逻辑回归。
-
GradientBoostingClassifier:这是一种基于梯度提升决策树的集成学习算法。它通过逐步添加新的弱学习器(通常是决策树)来最小化损失函数,每个新的弱学习器都试图纠正前一个学习器的错误。这种方法可以显著提高模型的性能,因为它专注于那些模型预测错误较多的样本。
-
逻辑回归:虽然逻辑回归本身是一个简单的线性模型,但它在分类问题中非常有效,尤其是二分类问题。它通过使用逻辑函数将线性回归的输出映射到0和1之间,从而预测事件发生的概率。
为了进一步增强这两种算法的性能,我们可以采用**软投票(Soft Voting)**策略。与传统的硬投票(Hard Voting)不同,软投票考虑的是每个模型输出的预测概率,而不是最终的分类决策。具体来说,每个模型都会输出一个介于0和1之间的概率值,表示样本属于正类的概率。然后,我们计算所有模型输出的概率的平均值,并根据这个平均概率来确定最终的分类。
在Python的scikit-learn库中,我们可以使用VotingClassifier
来轻松实现软投票。这个工具允许我们将多个模型组合成一个集成模型,并自动处理概率的计算和平均。通过这种方式,我们可以构建一个更加健壮和准确的分类器,它能够更好地泛化到新的数据上,减少过拟合的风险。
总之,算法集成是一种提高模型性能、减少过拟合的有效方法。通过结合GradientBoostingClassifier的强学习能力和逻辑回归的简单有效性,再利用软投票策略来整合它们的预测,我们可以构建一个更加强大和可靠的分类系统。这种方法在数据科学竞赛和实际应用中都非常受欢迎,是提高模型泛化能力的重要手段。代码如下:
from sklearn import ensemble
from sklearn.model_selection import cross_validate
# 导入sklearn库中的ensemble模块,用于创建集成模型
# 导入cross_validate函数,用于进行交叉验证# 定义我们要集成的算法列表。
# 这里使用了两种不同的分类器:GradientBoostingClassifier和LogisticRegression。
# 每种分类器都通过名称(如 'gbc')和实例进行配对。
voting_est = [('gbc', GradientBoostingClassifier(random_state=1, n_estimators=25, max_depth=5)),('lr', LogisticRegression(random_state=1)),
]predictors = ["Pclass", "Sex", "Fare", "FamilySize", "Title", "Age", "Embarked"]
# 定义predictors列表,包含用于训练模型的特征列名# 创建一个软投票分类器,用于集成上面定义的分类器。
# 'soft'投票意味着分类器将使用预测的概率进行平均,而不是使用多数投票。
voting_soft = ensemble.VotingClassifier(estimators=voting_est, voting='soft')# 执行交叉验证,并返回一个包含多个结果的字典。
# 这里使用kf定义的交叉验证方案(假设kf已经定义为KFold对象)
voting_soft_cv = cross_validate(voting_soft, ship[predictors], ship["Survived"], cv=kf)# 训练集成模型voting_soft,使用选定的特征和目标变量。
voting_soft.fit(ship[predictors], ship["Survived"])# 打印软投票分类器在交叉验证中测试集的平均准确率(以百分比形式)。
# {:.2f} %是一个格式化字符串,表示将数字格式化为百分比,保留两位小数。
print("Soft Voting Test w/bin score mean: {:.2f} %".format(voting_soft_cv['test_score'].mean() * 100))
这段代码的目的是创建一个集成模型,该模型结合了梯度提升分类器(GradientBoostingClassifier)和逻辑回归(LogisticRegression)两种算法,并通过软投票(即概率平均)的方式来进行集成。首先,定义了两种分类器的实例,并存储在列表voting_est
中。然后,使用ensemble.VotingClassifier
创建了一个软投票分类器voting_soft
。接着,使用cross_validate
函数对集成模型进行交叉验证,并存储结果。最后,训练集成模型,并打印出交叉验证中测试集的平均准确率。这样的集成方法有助于提高模型的泛化能力,减少过拟合的风险。
代码运行结果为:Soft Voting Test w/bin score mean: 83.73 %,准确率有明显的提高。
九、小结
本文将遵循机器学习的标准流程,对“轮船人员沉船生存率”这一主题进行深入的数据分析和预测建模。我们的目标是通过历史数据来预测乘客在沉船事故中的获救概率。为了实现这一目标,文章将依次展开以下几个关键步骤:
-
数据收集与处理:作为分析的基础,我们将首先收集相关数据,并使用Pandas等库进行清洗和预处理,以确保数据质量。
-
特征工程:接下来,我们将探索数据中的各种特征,并进行必要的转换和编码,以增强模型的性能。这可能包括处理缺失值、创建新特征或对现有特征进行规范化。
-
模型选择:在准备好数据之后,我们将尝试多种机器学习算法,如逻辑回归、随机森林、梯度提升等,以确定最适合我们数据的模型。
-
模型评估:选择合适的模型后,我们将使用交叉验证、精确度、召回率等指标来评估模型的性能,并根据需要进行调整和优化。
-
实战演练:本章将通过实际的代码示例,引导读者一步步完成从数据加载到模型预测的全过程,确保读者能够将理论应用到实践中。
-
结果分析与应用:最后,我们将分析模型的预测结果,并探讨如何将这些结果应用到实际情况中,以帮助提高事故应对和救援工作的效率。
通过本文的学习,读者不仅能够获得宝贵的机器学习实战经验,还将对如何处理实际问题、如何评估和优化模型有一个全面的理解。我们希望读者能够通过本章内容,提升自己的数据分析能力,并在未来的工作中有效地应用机器学习技术。
附录
一、代码地址
github:GitHub - XANkui/PythonMachineLearningBeginner: Python 机器学习是利用 Python 编程语言中的各种工具和库来实现机器学习算法和技术的过程。Python 是一种功能强大且易于学习和使用的编程语言,因此成为了机器学习领域的首选语言之一。这里我们一起开始一场Python 机器学习基础入门到精通学习旅程。