🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎
📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
🖍foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟👋
目录
Bagging 和 Boosting
使用 scikit-learn 默认值的 XGBoost 模型在使用 pandas 预处理数据并构建标准回归和分类模型后打开本书。通过推进决策树(XGBoost 基础学习器)、随机森林(装袋)和梯度提升来比较分数和微调集成和基于树的超参数,探索了 XGBoost 背后的实用理论。
欢迎阅读使用 XGBoost 和 Scikit-Learn 进行梯度提升的动手实践,这本书将教您 XGBoost 的基础、提示和技巧,这是用于从表格数据进行预测的最佳机器学习算法。
的重点这本书就是XGBoost,也称为Extreme Gradient Boosting。XGBoost 的结构、功能和原始功能将在每一章中越来越详细地充实。这些章节展开讲述了一个令人难以置信的故事:XGBoost 的故事。在本书结束时,您将成为利用 XGBoost 从真实数据进行预测的专家。
在第一章中,XGBoost 在预览中进行了介绍。它在机器学习回归和分类的更大背景下客串,为即将发生的事情奠定了基础。
本章重点关于为机器学习准备数据的过程,也称为数据争论。除了构建机器学习模型,您还将学习使用高效的Python代码加载数据、描述数据、处理空值、将数据转换为数值列、将数据拆分为训练集和测试集、构建机器学习模型以及实现跨验证,以及将线性回归和逻辑回归模型与 XGBoost 进行比较。
本章介绍的概念和库在整本书中都会用到。
本章包含以下主题:
预览 XGBoost
整理数据
预测回归
预测分类
机器学习1940 年代第一个神经网络获得了认可,随后在 1950 年代获得了第一个机器学习跳棋冠军。在沉寂了几十年之后,当深蓝在 1990 年代击败世界象棋冠军加里·卡斯帕罗夫时,机器学习领域开始腾飞。随着计算能力的激增,1990 年代和 2000 年代初期产生了大量的学术论文,揭示了新机学习算法,例如随机森林和AdaBoost。
boosting 背后的总体思路是通过对错误进行迭代改进,将弱学习者转变为强学习者。梯度提升背后的关键思想是使用梯度下降来最小化残差的误差。从标准机器学习算法到梯度提升,这一进化链是本书前四章的重点。
XGBoost 是 Extreme Gradient Boosting 的缩写。极限部分是指推动计算的极限以实现准确性和速度的提高。XGBoost 的人气飙升很大程度上得益于其在Kaggle 比赛中的空前成功。在 Kaggle 比赛中,参赛者构建机器学习模型,试图做出最好的预测并赢得丰厚的现金奖励。与其他型号相比,XGBoost 一直在竞争中脱颖而出。
了解 XGBoost 的细节需要了解梯度提升背景下的机器学习前景。为了描绘完整的画面,我们从机器学习的基础开始。
机器学习是计算机从数据中学习的能力。2020 年,机器学习可以预测人类行为、推荐产品、识别面孔、超越扑克专业人士、发现系外行星、识别疾病、驾驶自动驾驶汽车、个性化互联网以及与人类直接交流。机器学习正在引领人工智能革命,影响着几乎所有大公司的底线。
在实践中,机器学习意味着实施计算机算法,其权重会在新数据出现时进行调整。机器学习算法从数据集中学习,以预测物种分类、股票市场、公司利润、人类决策、亚原子粒子、最佳交通路线和更多的。
机器学习是将大数据转化为准确、可操作的预测的最佳工具。然而,机器学习并不是凭空发生的。机器学习需要行和列的数据。
数据整理是一个综合性术语,涵盖机器学习开始之前数据预处理的各个阶段。数据加载、数据清理、数据分析和数据操作都包含在数据整理的范围内。
第一章详细介绍了数据整理。这些示例旨在涵盖可由Python 处理数据分析的特殊库pandas快速处理的标准数据争论挑战。虽然不需要熊猫的经验,但熊猫的基本知识将是有益的。所有代码都进行了解释,以便 Pandas 的新读者可以跟进。
自行车租金dataset 是我们的第一个数据集。数据源是 UCI 机器学习存储库 ( UCI Machine Learning Repository ),这是一个世界著名的免费向公众开放的数据仓库。我们的自行车租赁数据集已从原始数据集 ( UCI Machine Learning Repository: Bike Sharing Dataset Data Set ) 中调整,添加了空值,以便您可以练习纠正它们。
下载数据。本书的所有文件都存储在 GitHub 上。您可以通过按克隆按钮将所有文件下载到本地计算机。这是一个视觉效果:
图 1.1 – 访问数据
下载数据后,将其移动到方便的位置,例如桌面上的数据文件夹。
打开一个 Jupyter 笔记本。您将在前言中找到下载 Jupyter Notebooks 的链接。单击Anaconda,然后单击Jupyter Notebooks。或者,在终端中输入jupyter notebook 。Web 浏览器打开后,您应该会看到文件夹和文件的列表。转到与该文件夹相同的文件夹自行车租赁数据集并选择New: Notebook: Python 3。这是一个视觉指南:
图 1.2 – 访问 Jupyter Notebook 的可视化指南
小费
如果您在打开 Jupyter Notebook 时遇到困难,请参阅 Jupyter 的官方故障排除指南: What to do when things go wrong — Jupyter Notebook 6.4.12 documentation.
在 Jupyter Notebook 的第一个单元格中输入以下代码:
import pandas as pd
按Shift + Enter运行单元格。现在您可以在编写pd时访问pandas库。
使用 pd.read_csv加载数据。加载数据需要读取方法。read方法将数据存储为 DataFrame,这是一个用于查看、分析和操作数据的pandas对象。加载数据时,将文件名放在引号中,然后运行单元格:
df_bikes = pd.read_csv('bike_rentals.csv')
如果您的数据文件与 Jupyter Notebook 位于不同的位置,则必须提供文件目录,例如Downloads/bike_rental.csv。
现在数据已正确存储在名为df_bikes的 DataFrame 中。
小费
制表符完成:何时在 Jupyter Notebooks 中编码,输入几个字符后,按Tab按钮。对于 CSV 文件,您应该会看到文件名出现。用光标突出显示名称并按Enter。如果文件名是唯一可用的选项,您可以按Enter。制表符补全将使您的编码体验更快、更可靠。
使用.head()显示数据。最后一步是查看数据以确保已正确加载。 .head() 是一个 DataFrame 方法,用于显示 DataFrame 的前五行。您可以将任何正整数放在括号中以查看任意数量的行。输入以下代码并按Shift + Enter:
df_bikes.head()
这是前几行的屏幕截图以及预期的输出:
图 1.3 -bike_rental.csv 输出
既然数据已经加载,是时候理解数据了。了解数据对于在未来做出明智的决策至关重要。以下是理解数据的三种好方法。
你有已经见过.head(),一种广泛使用的解释列名和数字的方法。正如前面的输出所示,dteday是一个日期,而instant是一个有序索引。
数字可以使用 .describe()查看统计信息,如下所示:
df_bikes.describe()
这是预期的输出:
图 1.4 – .describe() 输出
您可能需要向右滚动才能查看所有列。
比较平均值和中位数 (50%) 可以看出偏度。如您所见,均值和中位数彼此接近,因此数据大致对称。最大值和最小值_ _还显示了每列的值以及四分位数和标准差 ( std )。
另一个伟大的方法是 .info(),它显示有关列和行的一般信息:
df_bikes.info()
这是预期的输出:
- <class 'pandas.core.frame.DataFrame'>
- RangeIndex: 731 entries, 0 to 730
- Data columns (total 16 columns):
-
- # Column Non-Null Count Dtype
- --- ------ -------------- -----
- 0 instant 731 non-null int64
- 1 dteday 731 non-null object
- 2 season 731 non-null float64
- 3 yr 730 non-null float64
- 4 mnth 730 non-null float64
- 5 holiday 731 non-null float64
- 6 weekday 731 non-null float64
- 7 workingday 731 non-null float64
- 8 weathersit 731 non-null int64
- 9 temp 730 non-null float64
- 10 atemp 730 non-null float64
- 11 hum 728 non-null float64
- 12 windspeed 726 non-null float64
- 13 casual 731 non-null int64
- 14 registered 731 non-null int64
- 15 cnt 731 non-null int64
-
- dtypes: float64(10), int64(5), object(1)
-
- memory usage: 91.5+ KB
如您所见,.info() 给出行数、列数、列类型和非空值。由于列之间非空值的数量不同,因此必须存在空值。
如果空值是不纠正,可能会出现意想不到的错误。在本小节中,我们介绍了可用于纠正空值的各种方法。我们的示例不仅旨在处理 null 值,还旨在突出pandas的广度和深度。
以下方法可用于更正空值。
df_bikes.isna().sum().sum()
结果如下:
12
请注意,需要两个 .sum() 方法。第一种方法对每一列的空值求和,而第二种方法对列数求和。
df_bikes[df_bikes.isna().any(axis=1)]
此代码可分解如下:df_bikes[conditional]是满足括号中条件 的df_bikes的子集。.df_bikes.isna().any 收集所有空值,而 (axis=1) 指定列中的值。在 pandas 中,行是轴 0,列是轴 1。
这是预期的输出:
图 1.5 – Bike Rentals 数据集空值
正如您从输出中看到的那样,在windspeed、 humidity, 和 temperature 列以及最后一行中都有空值。
小费
如果这是您第一次使用pandas,可能需要一些时间来适应这种表示法。查看 Packt 的 使用 Pandas 进行数据分析的详细介绍:https://subscription.packtpub.com/book/data/9781789615326.
替换为中位数/平均值
一种常见的策略是用中位数或平均值替换空值。这里的想法是用平均列值替换空值。
对于“windspeed”列,可以将空值替换为中值,如下所示:
df_bikes['windspeed'].fillna((df_bikes['windspeed'].median()), inplace=True)
df_bikes['windspeed'].fillna 表示将填充'windspeed'列的空值。df_bikes['windspeed'].median()是'windspeed'列的中位数。最后,inplace=True确保更改是永久性的。
小费
中位数通常是比均值更好的选择。中位数保证一半数据大于给定值,一半数据小于给定值。相比之下,平均值容易受到异常值的影响。
在上一个单元格中, df_bikes[df_bikes.isna().any(axis=1)] 显示第56行和第81行的windspeed值为空。这些行可以使用 .iloc显示,是index location的缩写:
df_bikes.iloc[[56, 81]]
这是预期的输出:
图 1.6 – 第 56 和 81 行
小费
用户在使用pandas时经常会用单括号或双括号出错。.iloc对一个索引使用单括号,如下所示:df_bikes.iloc[56]。现在,df_bikes还接受括号内的列表以允许多个索引。多个索引需要双括号,如下所示: df_bikes.iloc[[56, 81]]。有关更多文档,请参阅pandas.DataFrame.iloc — pandas 1.5.0 documentation。
Groupby 与中位数/平均值
groupby 按共享值组织行。由于有四个共享季节分布在各行之间,因此一组季节会产生总共四行,每个季节一个。但是每个季节都来自许多具有不同值的不同行。我们需要一种方法来组合或聚合这些值。聚合的选择包括 .sum()、 .count( )、 .mean( )和 .median()。我们使用 .median()。
使用.median ()聚合按季节对df_bikes 进行分组的方法如下:
df_bikes.groupby(['season']).median()
这是预期的输出:
图 1.7 – 按季节分组 df_bikes 的输出
如您所见,列值是中位数。
为了纠正hum列中的空值,即湿度的缩写,我们可以按季节取中值湿度。
用于纠正hum列中的空值的代码是df_bikes['hum'] = df_bikes['hum'].fillna()。
fillna内部的代码是所需的值。从groupby获得的值需要变换方法如下:
df_bikes.groupby('season')['hum'].transform('median')
这是一个很长的步骤中的组合代码:
df_bikes['hum'] = df_bikes['hum'].fillna(df_bikes.groupby('season')['hum'].transform('median'))
您可以通过检查df_bikes.iloc[[129, 213, 388]]来验证转换。
从特定行获取中位数/平均值
在一些在这种情况下,用来自特定行的数据替换空值可能是有利的。
在校正温度时,除了查阅历史记录外,取前一天和后一天的平均温度应该可以很好地估计。
要查找“temp”列的空值,请输入以下代码:
df_bikes[df_bikes['temp'].isna()]
这是预期的输出:
图 1.8 – 'temp' 列的输出
如您所见,索引701包含空值。
要查找701指数前一天和后一天的平均温度,请完成以下步骤:
将第700行和第702行中的温度相加并除以2。对'temp'和'atemp'列执行此操作:
- mean_temp = (df_bikes.iloc[700]['temp'] + df_bikes.iloc[702]['temp'])/2
- mean_atemp = (df_bikes.iloc[700]['atemp'] + df_bikes.iloc[702]['atemp'])/2
替换空值:
- df_bikes['temp'].fillna((mean_temp), inplace=True)
- df_bikes['atemp'].fillna((mean_atemp), inplace=True)
推断日期
我们的最终策略纠正空值涉及日期。当提供真实日期时,可以推断日期值。
df_bikes['dteday'] 是日期列;但是, df_bikes.info()显示的列类型 是一个对象,通常表示为一个字符串。诸如年和月之类的日期对象必须从日期时间类型中推断出来。df_bikes['dteday'] 可以使用to_datetime方法转换为'datetime'类型,如下所示:
df_bikes['dteday'] = pd.to_datetime(df_bikes['dteday'],infer_datetime_format=True)
infer_datetime_format=True 允许pandas决定要存储的日期时间对象的种类,在大多数情况下这是一个安全的选择。
要推断单个列,首先导入datetime库:
import datetime as dt
我们现在可以使用一些不同的方法来推断空值的日期。标准方法是将“ mnth ”列转换为从“dteday”列推断的正确月份。这样做的好处是可以纠正转换中可能出现的任何其他错误,当然假设“ dteday ”列是正确的。
代码如下:
ddf_bikes['mnth'] = df_bikes['dteday'].dt.month
验证很重要变化。由于空日期值在最后一行,我们可以使用.tail(),一种类似于.head( ) 的 DataFrame 方法,它显示最后五行:
df_bikes.tail()
这是预期的输出:
图 1.9 – 外推日期值的输出
如您所见,月份值都是正确的,但年份值需要更改。
' dteday ' 列最后五行的年份都是2012 年,但 ' yr ' 列提供的对应年份是1.0。为什么?
数据被标准化,这意味着它被转换为0和1之间的值。
归一化数据通常更有效,因为机器学习权重不必针对不同的范围进行调整。
您可以使用 .loc 方法填写正确的值。.loc方法用于按行和列定位条目,如下所示:
df_bikes.loc[730, 'yr'] = 1.0
现在您已经练习了更正空值并获得了丰富的经验使用pandas,是时候解决非数字列了。
机器用学习,所有数据列应该是数字。根据df.info(),唯一不是数字的列是df_bikes['dteday']。此外,它是多余的,因为所有日期信息都存在于其他列中。
该列可以按如下方式删除:
df_bikes = df_bikes.drop('dteday', axis=1)
现在我们有了所有数字列并且没有空值,我们已经准备好进行机器学习了。
机器学习算法旨在使用来自一个或多个输入列的数据来预测一个输出列的值。预测依赖于由正在解决的一般机器学习问题确定的数学方程。大多数监督学习问题被归类为回归或分类。在本节中,机器学习是在回归的背景下介绍的。
在自行车租赁数据集,df_bikes['cnt'] 是一天内的自行车租赁数量。预测此列对自行车租赁公司非常有用。我们的问题是根据诸如这一天是假期还是工作日、预测的温度、湿度、风速等数据来预测给定日期的正确自行车租赁数量。
根据数据集,df_bikes['cnt'] 是df_bikes['casual']和 df_bikes['registered']的总和。如果 将 df_bikes['registered'] 和 df_bikes['casual']作为输入列,则预测将始终 100% 准确,因为这些列的总和总是正确的结果。尽管理论上完美的预测是理想的,但包含在现实中未知的输入列是没有意义的。
当前所有列可用于预测df_bikes['cnt']除了如前所述,对于'casual'和'registered' 。使用.drop方法删除'casual'和'registered'列,如下所示:
df_bikes = df_bikes.drop(['casual', 'registered'], axis=1)
数据集现已准备就绪。
自行车出租数据集将被多次使用这本书。您可以将干净的数据集导出到 CSV 文件以供将来使用,而不是每次都运行此笔记本来执行数据整理:
df_bikes.to_csv('bike_rentals_cleaned.csv', index=False)
index=False 参数可防止索引创建附加列。
机器通过执行数学学习工作对每个预测列(输入列)进行操作以确定目标列(输出列)。
将预测列分组为大写X和目标列分组为小写y是标准的。由于我们的目标列是最后一列,因此可以通过使用索引表示法进行切片来将数据拆分为预测列和目标列:
X = df_bikes.iloc[:,:-1]y = df_bikes.iloc[:,-1]
逗号将列与行分开。第一个冒号 :表示包含所有行。逗号后的:-1 表示从第一列开始一直到最后一列列而不包括它。第二个 -1取仅最后一列。
预测数字实际上,自行车租赁的数量可能会导致任何非负整数。当目标列包含无限范围的值时,机器学习问题归类为回归。
最常见的回归算法是线性回归。线性回归将每个预测变量列作为多项式变量,并将值乘以系数(也称为权重)来预测目标列。梯度下降在幕后工作以最小化错误。线性回归的预测可以是任何实数。
在运行线性回归之前,我们必须将数据拆分为训练集和测试集。训练集将数据拟合到算法中,使用目标列来最小化错误。建立模型后,将根据测试数据对其进行评分。
用测试集对模型进行评分的重要性怎么强调都不为过。在大数据世界中,将数据过度拟合到训练集是很常见的,因为要训练的数据点太多。过度拟合通常是不好的,因为模型过于接近异常值、异常实例和临时趋势调整自身。强大的机器学习模型在很好地概括新数据和准确掌握手头数据的细微差别之间取得了很好的平衡,第2章“深度决策树”中详细探讨了这个概念。
所有机器学习库将通过scikit-learn处理。Scikit-learn 的范围、易用性和计算能力使其成为世界上最广泛的机器学习库之一。
从 scikit-learn导入 train_test_split 和 LinearRegression ,如下所示:
- from sklearn.model_selection import train_test_split
- from sklearn.linear_model import LinearRegression
接下来,将数据拆分为训练集和测试集:
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=2)
注意random_state=2参数。每当您看到random_state=2时,这意味着您正在选择伪随机的种子数字生成器,以确保可重复的结果。
建造前您的第一个机器学习模型,消除所有警告。Scikit-learn 包含警告以通知用户未来的变化。一般来说,不建议使警告静音,但由于我们的代码已经过测试,因此建议在 Jupyter Notebook 中节省空间。
警告可能会被静音,如下所示:
- import warnings
- warnings.filterwarnings('ignore')
是时候建立你的第一个模型了。
初始化机器学习模型:
lin_reg = LinearRegression()
在训练集上拟合模型。这是建立机器学习模型的地方。请注意,X_train是预测列,y_train是目标列。
lin_reg.fit(X_train, y_train)
对测试集进行预测。X_test的预测,即测试集中的预测列,使用 lin_reg 上的.predict方法存储为y_pred:
y_pred = lin_reg.predict(X_test)
将预测与测试集进行比较。对模型进行评分需要比较的基础。标准线性回归是均方根误差( RMSE )。RMSE 需要两部分:mean_squared_error,预测值和实际值之间差异的平方和,以及平方根,以保持单位相同。可以导入mean_squared_error ,并且可以使用Numerical Python取平方根,通常已知作为NumPy,一个专为处理pandas而设计的超快速库。
导入mean_squared_error和 NumPy,然后计算均方误差并取平方根:
- from sklearn.metrics import mean_squared_error
- import numpy as np
- mse = mean_squared_error(y_test, y_pred)
- rmse = np.sqrt(mse)
打印结果:
print("RMSE: %0.2f" % (rmse))
结果如下:
RMSE: 898.21
这是构建您的第一个机器学习模型的所有代码的屏幕截图:
图 1.10 – 构建机器学习模型的代码
在不知道预期范围的情况下,很难知道898租金的错误是好是坏每天的租金。
可以在df_bikes['cnt']列上使用.describe()方法来获取范围等:
df_bikes['cnt'].describe()
这是输出:
- count 731.000000
- mean 4504.348837
- std 1937.211452
- min 22.000000
- 25% 3152.000000
- 50% 4548.000000
- 75% 5956.000000
- max 8714.000000
-
- Name: cnt, dtype: float64
在22到8714的范围内,平均值为4504,标准差为1937,898的 RMSE不是不好,但也不是很好。
线性回归是许多算法之一可用于解决回归问题。其他回归算法可能会产生更好的结果。一般的策略是尝试不同的回归器来比较分数。在本书中,您将尝试使用各种回归器,包括决策树、随机森林、梯度提升以及本书的重点 XGBoost。
本书后面将提供对 XGBoost 的全面介绍。现在,请注意 XGBoost 包含一个名为XGBRegressor的回归器,可用于任何回归数据集,包括刚刚评分的自行车租赁数据集。现在让我们使用XGBRegressor将自行车租赁数据集的结果与线性回归进行比较。
您应该已经在前言中安装了 XGBoost。如果您还没有这样做,请立即安装 XGBoost。
XGBoost 之后已安装,XGBoost 回归器可能是导入如下:
from xgboost import XGBRegressor
构建XGBRegressor的一般步骤与使用LinearRegression相同。唯一的区别是初始化XGBRegressor而不是LinearRegression:
初始化机器学习模型:
xg_reg = XGBRegressor()
在训练集上拟合模型。如果您在此处收到来自 XGBoost 的一些警告,请不要担心:
xg_reg.fit(X_train, y_train)
对测试集进行预测:
y_pred = xg_reg.predict(X_test)
将预测与测试集进行比较:
- mse = mean_squared_error(y_test, y_pred)
- rmse = np.sqrt(mse)
打印结果:
print("RMSE: %0.2f" % (rmse))
输出如下:
RMSE: 705.11
XGBRegressor的表现要好得多!
XGBoost经常出现的原因表现比其他人更好在第 5 章中探讨,XGBoost Unveiled。
一次考试成绩不可靠,因为将数据分成不同的训练和测试集会产生不同的结果。实际上,将数据分成训练集和测试集是任意的,不同的random_state将给出不同的 RMSE。
一种解决方法不同拆分之间的分数差异是k-fold cross-validation。这想法是将数据多次拆分为不同的训练集和测试集,然后取分数的平均值。拆分的数量,称为folds,用k表示。使用 k = 3、4、5 或 10 个分割是标准的。
这是交叉验证的直观描述:
图 1.11 – 交叉验证
(重绘自https://commons.wikimedia.org/wiki/File:K-fold_cross_validation_EN.svg)
交叉验证通过在第一个训练集上拟合机器学习模型并针对第一个测试集。为第二次拆分提供了不同的训练集和测试集,从而产生了具有自己分数的新机器学习模型。第三次拆分会产生一个新模型,并针对另一个测试集对其进行评分。
训练集中会有重叠,但测试集中不会。
选择折叠的数量是灵活的,并且取决于数据。五折是标准的,因为每次都会保留 20% 的测试集。10折,只保留10%的数据;但是,90% 的数据可用于训练,并且平均值不易受到异常值的影响。对于较小的数据集,三折可能效果更好。
最后,将有 k 个不同的分数针对 k 个不同的测试集评估模型。取 k 次折叠的平均分数比任何单次折叠都更可靠。
cross_val_score是实现交叉验证的便捷方式。cross_val_score将机器学习算法以及预测变量和目标列作为输入,并带有可选的附加参数,包括评分指标和所需的折叠数。
首先,从cross_val_score库中导入cross_val_score :
from sklearn.model_selection import cross_val_score
现在使用交叉验证在以下步骤中构建和评分机器学习模型:
初始化机器学习模型:
model = LinearRegression()
使用模型X、y、scoring='neg_mean_squared_error'和折叠数cv=10作为输入实现cross_val_score :
scores = cross_val_score(model, X, y, scoring='neg_mean_squared_error', cv=10)
小费
为什么 score='neg_mean_squared_error'?Scikit-learn 旨在在训练模型时选择最高分。这对准确性很有效,但在最低值最好时不适用于错误。通过取每个均方误差的负数,最低的最终成为最高的。稍后使用 rmse = np.sqrt(-scores) 对此进行补偿,因此最终结果是积极的。
通过取负分数的平方根求 RMSE:
rmse = np.sqrt(-scores)
显示结果:
- print('Reg rmse:', np.round(rmse, 2))
- print('RMSE mean: %0.2f' % (rmse.mean())
输出如下:
- Reg rmse: [ 504.01 840.55 1140.88 728.39 640.2 969.95
- 1133.45 1252.85 1084.64 1425.33]
- RMSE mean: 972.02
线性回归的平均误差为972.06。这比之前得到的980.38略好一些。这里的重点不是分数是好是坏。关键是它更好估计线性回归将如何执行在看不见的数据上。
始终建议使用交叉验证来更好地估计分数。
关于打印功能
运行您自己的机器学习代码时,全局打印功能通常不是必需的,但如果您想打印出多行并按此处所示格式化输出,它会很有帮助。
现在让我们使用使用XGBRegressor进行交叉验证。这步骤是相同的,除了初始化模型:
初始化机器学习模型:
model = XGBRegressor()
使用模型X、y、评分和折叠数cv作为输入实现cross_val_score :
scores = cross_val_score(model, X, y, scoring='neg_mean_squared_error', cv=10)
通过取负分数的平方根求 RMSE:
rmse = np.sqrt(-scores)
打印结果:
- print('Reg rmse:', np.round(rmse, 2))
- print('RMSE mean: %0.2f' % (rmse.mean()))
输出如下:
- Reg rmse: [ 717.65 692.8 520.7 737.68 835.96 1006.24 991.34 747.61 891.99 1731.13]
- RMSE mean: 887.31
你学到了XGBoost 在回归方面可能有优势,但分类呢?XGBoost 有一个分类模型,但它会像逻辑回归等经过测试的分类模型一样准确吗?让我们来了解一下。
与回归,当预测输出数量有限的目标列时,机器学习算法被归类为分类算法。可能的输出可能包括以下内容:
是的,没有
垃圾邮件,不是垃圾邮件
0, 1
红、蓝、绿、黄、橙
我们会移动一点通过第二个数据集,人口普查收入数据集 ( UCI Machine Learning Repository: Census Income Data Set ) 更快速地预测个人收入。
前实现机器学习,必须对数据集进行预处理。在测试新算法时,所有数字列都必须没有空值。
由于这个数据集直接托管在 UCI 机器学习网站上,可以使用pd.read_csv直接从 Internet 下载:
- df_census = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data')
- df_census.head()
这是预期的输出:
图 1.12 – 人口普查收入数据框
输出显示列标题代表第一行的条目。发生这种情况时,可能会使用header=None参数重新加载数据:
- df_census = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data', header=None)
- df_census.head()
这是没有标题的预期输出:
图 1.13 – header=None 参数输出
如您所见,列名仍然缺失。它们列在人口普查收入数据集网站 ( UCI Machine Learning Repository: Census Income Data Set ) 的属性信息下。
- df_census.columns=['age', 'workclass', 'fnlwgt', 'education', 'education-num', 'marital-status', 'occupation', 'relationship', 'race', 'sex', 'capital-gain', 'capital-loss', 'hours-per-week', 'native-country', 'income']
- df_census.head()
这是带有列名的预期输出:
图 1.14 – 预期的列名
如您所见,列名已恢复。
一个很棒的方法检查空values 是看DataFrame .info()方法:
df_census.info()
输出如下:
- <class 'pandas.core.frame.DataFrame'>
- RangeIndex: 32561 entries, 0 to 32560
- Data columns (total 15 columns):
-
- # Column Non-Null Count Dtype
- --- ------ -------------- -----
- 0 age 32561 non-null int64
- 1 workclass 32561 non-null object
- 2 fnlwgt 32561 non-null int64
- 3 education 32561 non-null object
- 4 education-num 32561 non-null int64
- 5 marital-status 32561 non-null object
- 6 occupation 32561 non-null object
- 7 relationship 32561 non-null object
- 8 race 32561 non-null object
- 9 sex 32561 non-null object
- 10 capital-gain 32561 non-null int64
- 11 capital-loss 32561 non-null int64
- 12 hours-per-week 32561 non-null int64
- 13 native-country 32561 non-null object
- 14 income 32561 non-null object
-
- dtypes: int64(6), object(9)
- memory usage: 3.7+ MB
由于所有列都有相同数量的非空行,我们可以推断没有空值。
dtype对象的所有列必须是转化成数值列。pandas get_dummies方法获取 每列的非数字唯一值并将它们转换为自己的列,其中1表示存在,0表示不存在。例如,如果名为“Book Types”的 DataFrame 的列值为“hardback”、“paperback”或“ebook”, 则 pd.get_dummies 将创建三个名为“hardback”、“paperback”和“ebook”的新列替换“书籍类型”列。
这是一个“书籍类型”数据框:
图 1.15 – 一个“书本类型”数据框
这是 pd.get_dummies 之后的相同DataFrame:
图 1.16 – 新的 DataFrame
pd.get_dummies 将创建许多新列,因此值得检查是否可以消除任何列。对df_census数据的快速查看会发现一个“教育”列和一个education_num列。Education_num列是'education'的数值转换。由于信息相同,可以删除“教育”一栏:
df_census = df_census.drop(['education'], axis=1)
现在使用 pd.get_dummies 将非数字列转换为数字列:
- df_census = pd.get_dummies(df_census)
- df_census.head()
图 1.17 – pd.get_dummies – 非数字到数字列
如您所见,新列是使用引用原始列的column_value语法创建的。例如,native-country是原始列,Taiwan 是众多值之一。如果此人来自台湾,则新的native-country_Taiwan列的值为1 ,否则为0。
小费
使用pd.get_dummies可能会增加内存使用量,这可以使用相关 DataFrame 上的.info()方法并检查最后一行来验证。稀疏矩阵可用于节省内存,其中仅存储值1而不存储值0 。有关稀疏矩阵的更多信息,请参阅第 10 章,XGBoost 模型部署,或访问SciPy API — SciPy v1.9.1 Manual上的 SciPy 官方文档。
由于所有列是数字,没有无效的值,是时候将数据拆分为目标列和预测列。
目标列是是否有人赚了 50K。在 pd.get_dummies之后,两列 df_census['income_<=50K']和 df_census['income_>50K']用于确定某人是否赚了 50K。由于任一列都可以,我们删除df_census['income_ <=50K']:
df_census = df_census.drop('income_ <=50K', axis=1)
现在将数据拆分为X(预测列)和y(目标列)。请注意,-1用于索引,因为最后一列是目标列:
X = df_census.iloc[:,:-1]y = df_census.iloc[:,-1]
是时候构建机器学习分类器了!
逻辑回归是最基本的分类算法。在数学上,逻辑回归的工作方式类似于线性回归。对于每一列,逻辑回归会找到一个适当的权重或系数,以最大限度地提高模型的准确性。主要区别在于,不是像线性回归那样对每个项求和,而是逻辑回归回归使用sigmoid 函数。
这是 sigmoid 函数和相应的图表:
图 1.18 – Sigmoid 函数图
sigmoid 通常用于分类。所有大于 0.5 的值都匹配为 1,所有小于 0.5 的值都匹配为 0。
使用 scikit-learn 实现逻辑回归与实现线性回归几乎相同回归。主要区别在于预测变量列应适合类别,而误差应与准确性有关。作为奖励,默认情况下错误是在准确性方面,因此不需要明确的评分参数。
您可以按如下方式导入逻辑回归:
from sklearn.linear_model import LogisticRegression
让我们构建一个交叉验证分类函数,而不是复制和粘贴,该函数将机器学习算法作为输入,并使用cross_val_score将准确度得分作为输出:
- def cross_val(classifier, num_splits=10):
- model = classifier
- scores = cross_val_score(model, X, y, cv=num_splits)
- print('Accuracy:', np.round(scores, 2))
- print('Accuracy mean: %0.2f' % (scores.mean()))
现在用逻辑回归调用函数:
cross_val(LogisticRegression())
输出如下:
- Accuracy: [0.8 0.8 0.79 0.8 0.79 0.81 0.79 0.79 0.8 0.8 ]
- Accuracy mean: 0.80
80% 的准确率是开箱即用的。
小费
每当您发现自己在复制和粘贴代码时,请寻找更好的方法!计算机科学的目标之一是避免重复。从长远来看,编写自己的数据分析和机器学习函数将使您的生活更轻松,工作效率更高。
XGBoost 有一个回归器和分类器。要使用分类器,请导入以下算法:
from xgboost import XGBClassifier
现在在cross_val函数中运行分类器并添加一个重要内容。由于有 94 列,并且 XGBoost 是一种集成方法,这意味着它每次运行都会组合许多模型,每个模型都包含 10 个拆分,因此我们将n_estimators(模型的数量)限制为5 个。通常,XGBoost 非常快。事实上,它以最快的提升集成方法而闻名,我们将在本书中查看这一声誉!然而,对于我们最初的目的,5 个估计量虽然不如默认的100 个稳健,但就足够了。选择n_estimators的细节将是第 4 章的重点,从梯度提升到 XGBoost:
cross_val(XGBClassifier(n_estimators=5))
输出如下:
- Accuracy: [0.85 0.86 0.87 0.85 0.86 0.86 0.86 0.87 0.86 0.86]
- Accuracy mean: 0.86
您的 XGBoost 之旅正式开始!您从学习数据整理和pandas的基础知识开始本章,这是所有机器学习从业者的基本技能,重点是纠正空值。接下来,您通过比较线性回归和 XGBoost,了解了如何在 scikit-learn 中构建机器学习模型。然后,您准备了一个用于分类的数据集,并将逻辑回归与 XGBoost 进行了比较。在这两种情况下,XGBoost 都是明显的赢家。
恭喜您构建了您的第一个 XGBoost 模型!您开始使用pandas、NumPy 和 scikit-learn 库进行数据整理和机器学习已经完成。
在第 2 章“深度决策树”中,您将通过构建决策树、XGBoost 机器学习模型的基础学习器和微调超参数来提高您的机器学习技能以改善结果。