欢迎光临散文网 会员登陆 & 注册

Hands-On Data Preprocessing in Python-6 预测

2022-10-29 17:21 作者:情报工作站  | 我要投稿

能够利用数据来预测未来正变得越来越可能。不仅如此;很快,能够进行成功的预测性建模将不再是一种竞争优势--它将成为生存的必需品。为了提高预测性建模的有效性,许多人把注意力集中在用于预测的算法上;然而,你可以采取许多有意义的步骤,通过进行更有效的数据预处理来提高预测的成功率。这就是本书的最终目标:学习如何更有效地预处理数据。然而,在本章中,我们将朝着这个目标迈出非常重要的一步。在本章中,我们将学习预测性建模的基础知识。当我们学习了数据预处理的概念和技术后,我们将依靠这些基础知识来做出更好的数据预处理决策。

虽然许多不同的算法可以应用于预测性建模,但这些算法的基本概念都是一样的。在本章中介绍了这些基本原理后,我们将介绍其中两种在复杂性和透明度方面有区别的算法:线性回归和多层感知器(MLP)。

1 预测模型

利用数据来预测未来是令人兴奋的,而且利用数据分析是可以做到的。在数据分析领域,有两种类型的未来预测,概述如下。

- 预测一个数值--例如,预测明年亚马逊股票市场的价格。

- 预测一个标签或一个类别--例如,预测一个客户是否有可能停止购买你的服务而转向你的竞争对手。

总的来说,当我们使用预测一词时,我们指的是预测一个数值

要预测一个类别或一个标签,所使用的术语是分类。在本章中,我们将重点讨论数据分析的预测目标,下一章将介绍分类。

对未来数值的预测也分为两个主要的总体类型:预测和回归分析。我们将简要地解释预测,然后再把注意力转向回归分析。

1.1 预测

在数据分析中,预测是指用于预测时间序列数据的未来数值的技术。预测的独特之处在于它对时间序列数据的应用--例如,最简单的预测方法是简单移动平均线(SMA:simple moving average )。在这种方法下,你将使用最近的数据点来预测你的时间序列数据中未来数据点的数值。

1.1.1 使用预测法来预测未来的例子

我们来看看一个以移动平均数(MA)为特征的预测例子。下表显示了密西西比州立大学(MSU)从2006年到2021年收到的学生申请的数量。

import pandas as pd
msu_df = pd.read_csv('https://raw.githubusercontent.com/PacktPublishing/Hands-On-Data-Preprocessing-in-Python/main/Chapter06/MSU%20applications.csv')
msu_df.set_index('Year',drop=True,inplace=True)
msu_df.head()

application_df = pd.DataFrame(msu_df.N_Applications)
application_df.transpose()

下面的截图用线图将前述表格中的数据可视化。

import matplotlib.pyplot as plt

plt.figure(figsize=(7,3))
plt.plot(application_df)
plt.xticks(application_df.index,rotation=90)
plt.show()

application_df.loc[2017:2021].mean()

average_df = pd.DataFrame(application_df.loc[2017:2021])
average_df['N_Applications']=15901.2
average_df.loc[2022]=15901.2
average_df

predict_df = pd.DataFrame(application_df.loc[2021]).transpose()
predict_df.loc[2022] = 15901.2
predict_df

plt.figure(figsize=(7,3))
plt.plot(application_df)
plt.plot(average_df,linestyle='--',c='C1')
plt.plot(predict_df,c='C1')
plt.xticks(application_df.index,rotation=90)
plt.show()

MSU,出于规划的目的,希望对他们在2022年将收到多少新的申请有一些想法。一种方法是使用MA方法。

对于这种方法,你需要指定你想用于预测的数据点的数量。这通常用n来表示。让我们使用五个数据点(n=5)。在这种情况下,你将在预测中使用2017、2018、2019、2020和2021年的数据。简单地说,你计算这些年的平均申请数量,并将其作为下一年的估计预测。13,930、13,817、17,363、18,269和16,127的平均值是15,901.2,这可以作为2022年申请数量的估计。

下面的截图描述了n=5的MA的应用。

使用时间序列数据进行预测还有更复杂的方法,如加权MA,指数平滑,双指数平滑,等等。

我们在本书中不涉及这些方法,因为所有时间序列数据所需的数据预处理都是一样的。然而,你想从预测中记住的是,这些方法在单维时间序列数据上的预测工作。

例如,在MSU的例子中,我们唯一的数据维度是N_ Applications。

这种单一维度与我们将要介绍的下一个预测方法形成了鲜明的对比。回归分析,与预测相反,找到多个属性之间的关系来估计其中一个属性的数值。

1.2 回归分析

回归分析的任务是利用预测属性和目标属性之间的关系来预测数值。

目标属性是指我们对其数值的预测感兴趣的属性。从属属性一词是用于同一概念的另一个名称。从属属性的含义来自于这样一个事实:目标属性的值取决于其他属性;我们把这些属性称为预测器或独立属性。

许多不同的方法可用于回归分析。只要这些方法是为了寻找独立属性和因果属性之间的关系以预测因果属性,我们就把这些方法归入回归分析。当然,线性回归是最简单而又广泛使用的回归分析方法之一,也是这些方法之一。然而,其他技术,如MLP和回归树,也被归入回归分析。

1.2.1 设计回归分析以预测未来价值的例子

例如,对下一年MSU申请数量的预测也可以用回归分析来建模。下图显示了有可能预测 "申请人数 "因果属性的两个独立属性。在这个例子中,你可以看到预测模型涉及到不止一个维度,我们有三个维度--两个独立属性和一个因果属性

第一个独立属性,前一年的足球表现,是MSU足球队的胜率。第二个独立属性是过去两年的平均申请数量。

第二个独立属性很有意思,因为它描述了你可以通过将预测方法的值作为回归分析的独立属性来对接预测方法和回归分析。过去两年的平均申请数量是SMA方法的值,n=2。

我们如何找到可能的独立属性?你可以看到在回归分析中,拥有适当的独立属性来预测感兴趣的属性(因果属性)的重要作用。

设想和收集可能的预测因素(独立属性)是进行成功回归分析的最重要部分。

到目前为止,你已经在本书中学到了宝贵的技能,可以帮助你设想可能的预测器。你在第4章 "数据库 "中积累的理解将使你能够想象可能的情况,并搜索和收集这些数据。

在未来的一章,即第12章,数据融合和整合,你将学到所有的技能,去整合来自不同来源的数据,以支持你的回归分析。

一旦确定了独立和因果属性,我们就完成了回归分析并建立了模型。接下来,我们需要采用适当的算法来寻找这些属性之间的关系,并利用这些关系进行预测。

在本章中,我们将介绍两种非常不同的算法,可以做到这一点:线性回归和MLP。

2 线性回归

线性回归这个名字会告诉你所有你需要知道的事情--回归部分告诉你这个方法进行回归分析,线性部分告诉你这个方法假设属性之间存在线性关系。

为了找到属性之间的可能关系,线性回归假设并建立一个通用方程,将目标(因果属性)与预测因子(独立属性)联系起来。这个方程在这里被描绘出来

这个方程采用的是参数法。在这个方程中,N代表预测因子的数量,显示了线性回归的通用方程。

线性回归的工作非常简单。该方法首先估计βs,使方程最适合数据,然后使用估计的βs进行预测

让我们通过一个例子来学习这个方法。我们将在下面的例子中继续解决MSU的应用数量。

2.1 应用线性回归来进行回归分析的例子

到目前为止,我们已经确定了我们的独立和因果属性,所以我们可以显示这个例子的线性回归方程。该方程显示在这里。

MSU applications.csv数据集有我们需要的所有属性来估计βs。

让我们先读一下这个数据,看一下它。下面的截图显示了我们为读取数据和整个数据集所运行的代码。

import pandas as pd
msu_df = pd.read_csv('https://raw.githubusercontent.com/PacktPublishing/Hands-On-Data-Preprocessing-in-Python/main/Chapter06/MSU%20applications.csv')
msu_df.set_index('Year',drop=True,inplace=True)
msu_df.head()

在这个数据集中,我们有以下属性。

- P_Football_Performance。这个属性是MSU足球队在上一学年的总胜率。

- SMAn2。这个属性是n=2的SMA的计算值。例如,2009行的SMAn2是2008年和2007年的N_Applications属性的平均值。在继续阅读之前,请确认这一计算结果。

- N_Applications。这与我们在图6.1和图6.2中看到的数据相同。这是我们感兴趣的预测的从属属性。

我们将使用scikit-learn模块用msu_df来估计这些βs,所以首先,我们需要在Anaconda平台上安装这个模块。运行下面的代码将安装该模块。

%pip install scikit-learn

一旦安装完毕,你需要导入该模块以开始每次使用它,就像我们一直在使用的其他模块一样。然而,由于scikit-learn相当大,我们每次都会准确地导入我们想要使用的东西。例如,下面的代码只从模块中导入 LinearRegression 函数:from sklearn.linear_model import LinearRegression

现在,我们有一个函数可以使用msu_df无缝地计算我们模型的βs。我们现在只需要以适当的方式将数据引入LinearRegression()函数。

我们可以分四步来完成,如下所示。

1.首先,我们将指定我们的独立和因果属性,通过指定X和Y的变量列表。请看下面的代码片断。

X = ['P_Football_Performance','SMAn2']
y= 'N_Applications'

2.其次,我们将使用X和Y的列表从msu_df创建两个独立的数据集:data_X和data_y。data_X是一个包含所有独立属性的DataFrame,data_y是一个系列,是依赖属性。下面的代码显示了这一点。

这一步和上一步本可以与下一步合并;然而,最好是保持你的代码干净整洁,我强烈建议使用我的指导方针,至少在开始时是这样。

data_X = msu_df[X]
data_y = msu_df[y]

3.接下来,我们将创建模型并引入数据。下面的代码将做到这一点。我们创建一个线性回归模型,称其为lm,并向其引入数据。

lm = LinearRegression()
lm.fit(data_X,data_y)

当你运行下面的代码时,几乎什么都没有发生,但是不要担心--模型已经完成了它的工作,我们只需要在下一步访问估计的βs。

4.如图所示,估计的βs是在训练好的lm模型内。我们可以用lm.intercept_来访问β0,lm.coef_将显示β1和β2。下面的代码会打印出一份有组织的报告,其中包括所有的β0实例。

print('intercept (b0)',lm.intercept_)
coef_name = ['b1','b2']
print(pd.DataFrame({
    'Predictor':data_X.columns,
    'coefficient Name':coef_name,
    'coefficient Value':lm.coef_
}))

完整代码

from sklearn.linear_model import LinearRegression


X = ['P_Football_Performance','SMAn2']
y= 'N_Applications'

data_X = msu_df[X]
data_y = msu_df[y]

lm = LinearRegression()
lm.fit(data_X,data_y)

print('intercept (b0)',lm.intercept_)
coef_name = ['b1','b2']
print(pd.DataFrame({
    'Predictor':data_X.columns,
    'coefficient Name':coef_name,
    'coefficient Value':lm.coef_
}))

现在我们已经估计了回归模型的βs,我们可以引入我们的训练模型。下面的方程式显示了训练后的回归方程式。

2.2 如何使用训练好的回归方程进行预测

为了使用该方程式来预测2022年MSU的申请数量,MSU需要把2022年的P_Football_performance和SMAn2属性放在一起。这里,我们介绍一下寻找这些数值的过程。

- P_Football_performance。在撰写本章时(2021年4月),2020-21年的大学橄榄球赛季已经结束,MSU在11场比赛中取得了4场胜利,胜率达到0.364。

- SMAn2。2021年和2020年的N_Applications值分别为18,269和16,127。这些数字的平均值是17,198。

下面是预测2022年的N_Applications值的计算。

我们不需要自己做前面的计算,我们这样做是为了学习。

我们可以使用所有scikit-learn预测模型附带的.predict()函数。下面的屏幕截图显示了如何做到这一点。

newData = pd.DataFrame({
    'P_Football_Performance':0.364,
    'SMAn2':17198,
    },index=[2022])
newData

lm.predict(newData) #array([16726.78787061])

前面的方程式计算和编程计算之间有一些区别。一个达到了16777.82,另一个达到了16726.78。这个差异是由于我们在呈现回归方程时做了四舍五入的处理。.predict()函数得出的数值,16726.78,是比较准确的。

请注意! 线性回归,以及一般的回归分析,是一个非常成熟的分析领域。有许多评估方法和程序来确保我们所创建的模型具有良好的质量。在本书中,我们将不涉及这些概念,因为本章的目标是介绍可能需要数据预处理的技术。通过了解这些技术的机制,你将能够更有效地进行数据预处理。

    https://realpython.com/linear-regression-in-python/  

    https://www.statsmodels.org/stable/generated/statsmodels.regression.linear_model.RegressionResults.html  

现在我们已经完成了这个预测,回过头来看看,研究一下线性回归的工作。在这里,线性回归实现了以下两个目标。

1. 线性回归用它的普遍性和线性方程来寻找独立属性和依赖属性之间的关系。每个独立属性的β系数告诉你独立属性与因果属性的关系--例如,SMAn2的系数,β2,得出的是0.91。这意味着,即使MSU橄榄球队输掉了所有的比赛(这使得N_Football_Performance的值为零),明年,申请人数将是一个-890.71+0.91×SMAn2的等式。

2. 线性回归方程已将估计的关系打包成一个方程,可用于未来的观察。

这两个事项,即关系的提取和估计以及为未来的数据对象包装估计的关系,对于任何预测模型的正常工作都是至关重要的。

线性回归的伟大之处在于,这些事项的简单性可以被看到和欣赏到。这种简单性有助于理解线性回归的工作和理解它所提取的模式。然而,就其在估计和包装独立和因果属性之间更复杂的非线性关系的范围而言,这种简单性对该方法不利。

接下来在本章中,我们将简要介绍另一种处于另一端的预测算法。MLP是一种复杂的算法,能够找到并包装独立和依赖属性之间更复杂的模式,但它缺乏线性回归的透明度和直观性。

3 MLP(Multilayer Perceptron:多层感知器

MLP是一个非常复杂的算法,有很多细节,抽象地去看它的运作和不同的部分会很难理解。因此,让我们通过一个例子来深入了解。在本节中,我们将继续使用MSU的应用数量。

线性回归使用一个方程式,而MLP使用一个神经元网络来连接独立属性和因果属性。这样一个网络的例子显示在下面的截图中。

每个MLP网络都有六个不同的部分。让我们用图来看看这些部分,如下所示。

- 神经元(Neurons)。图中的每个圆圈都被称为神经元。一个神经元可以在输入层、输出层和隐藏层。我们将在下一节中介绍三种树型的层。

- 输入层(Input layer)。一个由神经元组成的层,数值从这里输入到网络。

在预测任务中,对于独立属性的数量之多,我们将在输入层有神经元。在图中,你可以看到我们在输入层有两个神经元,每个独立属性一个。

- 输出层(Output layer)。一个由神经元组成的层,网络的处理值从这里出来。在预测任务中,只要有多少个从属属性,我们就会在输出层有神经元。更多时候,我们只有一个从属属性。图也是如此,因为我们的预测任务只有一个依赖属性,网络在输出层只有一个神经元。

- 隐蔽层(Hidden layers)。在输入和输出层之间的一个或多个神经元层。隐蔽层的数量和每个隐蔽层中的神经元数量可以--而且应该--根据所需的模型复杂性和计算成本水平进行调整。例如,图只有一个隐藏层,隐藏层中有六个神经元。

- 连接(Connections。将一个层的神经元连接到下一层的线被称为连接。这些连接必须从一层到下一层详尽地存在;详尽地意味着左层的所有神经元都与右层的所有神经元相连。

3.1 MLP怎样工作的

MLP的工作方式既与线性回归相似,又与线性回归不同。让我们先看看它们的相似之处,然后再介绍它们的区别。这里列出了它们的相似之处

- 线性回归依靠其结构化方程来捕捉独立属性和因果属性之间的关系。MLP也依靠其网络结构来捕捉相同的关系。

- 线性回归估计βs是一种使用其结构化方程来适应数据的方式,从而找到独立属性和因果属性之间的关系。MLP也为其结构上的每一个连接估计一个值,以使自己适合数据;这些值被称为连接的权重

因此,线性回归和MLP都使用数据来更新自己,以便它们能够使用其预定义的结构来解释数据。

- 一旦线性回归的βs和MLP的连接权重被正确地用数据估计出来,这两种算法就可以用来预测新的案例。

我们可以看到,这两种算法非常相似;但是,它们也有许多不同之处。现在让我们来看看这些,如下。

- 线性回归算法的结构方程是固定的、简单的,而MLP的结构是可调整的,可以设置为非常复杂。从本质上讲,MLP结构的隐藏层和神经元越多,该算法就越能捕捉到更复杂的关系。

- 线性回归依靠成熟的数学公式来估计βs,而MLP则必须借助启发式方法和计算来估计数据的最佳连接权重。

最著名的启发式方法是用来估计MLP的连接权重的,叫做反向传播法。这种启发式方法在本质上是非常简单的;然而,对其进行编码并使其发挥作用可能是很棘手的。对我们来说,好消息是我们不必担心编码问题,因为我们可以使用一些稳定的模块。然而,在看看我们如何使用上述模块之前,让我们先把它的简单想法看一遍。

3.1.1 反向传播

对于反向传播,每个连接的权重首先被分配一个介于-1和1之间的随机数。是的,这是完全随机的,它被称为MLP的随机初始化

在MLP的随机初始化之后,该算法将能够对任何输入的数据对象进行预测值。当然,这些预测将是错误的。逆向传播利用这些错误和这些错误的程度来学习。

每当一个数据对象暴露在MLP网络中时,MLP就会期望其依赖属性。如前所述,这种期望是错误的,至少在开始时是如此。因此,反向传播计算每次接触的网络错误,在网络上向后移动,并更新连接的权重,这样如果再次接触相同的数据对象,错误量会少一点

网络将不止一次地暴露在数据集中的所有数据对象面前。每次所有的数据对象被暴露给网络,我们称之为一个学习周期(epoch of learning

逆向传播使网络经历了足够多的历时学习,从而使网络的集体误差量可以接受。

现在我们对MLP及其主要的启发式方法有了大致的了解,让我们一起看看使用scikit-learn模块来执行MLP预测任务的例子。

3.2 应用MLP进行回归分析的例子

为了使用scikit-learn模块实现MLP,我们需要采取与线性回归相同的四个步骤。简而言之,这四个步骤列举如下。

1. 指定我们的独立和依赖属性

2. 创建两个独立的数据集:Data_X和Data_y

3. 创建一个模型并引入数据

4. 预测

下面的代码片段显示了这四个步骤被应用于MSU应用程序的数量问题。它显示了首先从sklearn.neural_network模块导入MLPRegressor类。

from sklearn.neural_network import MLPRegressor

X = ['P_Football_Performance','SMAn2']
y = 'N_Applications'

data_X = msu_df[X]
data_Y = msu_df[y]

mlp = MLPRegressor(hidden_layer_sizes=6,max_iter=10000)
mlp.fit(data_X,data_y)

newData = pd.DataFrame({
    'P_Football_Performance':0.364,
    'SMAn2':17198,
    },index=[2022])

mlp.predict(newData) #array([18812.15879652])

该代码与我们用于线性回归的代码几乎相同,但有一些小的改动。让我们来看看这些,如下所示。

- 我们没有使用LinearRegression()创建lm,而是使用MLPRegressor()创建mlp。

- LinearRegression()函数不需要任何输入,因为线性回归是一个简单的算法,没有超参数。但是MLPRegressor()至少需要两个输入,即hidden_layer_sizes=6和max_iter=10000。第一个输入(hidden_layer_sizes=6)指定了网络结构。通过只输入一个数字,我们表明我们只有一个隐藏层,而通过使用数字6,我们表明隐藏层有六个神经元。这与我们在图中看到的网络设计是一致的。第二个输入(max_ iter=10000)表示在模块放弃收敛之前,你希望至少有10,000个epochs的学习。

如果你成功地运行了几次前面的代码,你会观察到以下两个总体趋势。

- 代码每次都会输出一个有点不同的newData的预测值,但这些值都在18000左右。

- 在一些运行中,代码也会产生一个警告。这个警告是指MLP算法在经过1万次的学习后也无法收敛。

现在,让我们来讨论这两个趋势。

3.2.1 MLP在每次运行中达到不同的预测结果

我们来讨论一下第一个观察结果。代码每次都会为newData输出一个有些不同的预测值,但这些值都在18000左右。

MLP是一种基于随机的算法。如果你还记得我们的反向传播学习,每次网络被初始化时,都会给每个连接分配一个介于-1和1之间的随机数。然后,这些值会被更新,以便网络更好地适应数据;然而,开始是随机的,因此结果也会不同。

然而,如果你注意基于随机的模型得出的这些不同的结论,你会发现,即使它们是不同的,但它们在某种程度上是一致的。

它们都在18,000左右。这表明,基于随机的程序能够在数据中找到类似的、有意义的模式

3.2.2 需要大量历时学习的MLP

现在我们来讨论第二个观察结果。在某些运行中,代码也会产生一个警告。这个警告是指MLP算法在经过10000个epochs的学习后也无法收敛。

由于我们永远不知道基于随机的算法何时会收敛,所以我们必须给学习的epochs数量设置一个上限。事实上,有10,000个历时的学习是很奢侈的,我们能负担得起只是因为数据只有16个数据对象

MLPRegressor()的max_iter的默认值是200。这意味着如果我们没有指定max_iter=10000,该函数就会假定max_iter=200。在这种情况下,这就意味着算法不会更频繁地收敛,其结论也不会那么一致。试一试,观察一下前述的模式。

请注意! MLP是一个非常复杂和灵活的算法;在这里,我们只讨论了它的两个超参数(hidden_layer_sizes和max_iter),但它还有很多,要成功使用MLP,你需要先对它进行调整。调整算法就是要找到对数据集最有效的超参数。我们不会在这里介绍MLP是如何调整的,因为我们只需要对该算法有一个基本的了解,这样它就能支持我们的数据预处理之旅。

此外,就像线性回归一样,MLP在实施前应严格评估其有效性和可靠性。出于同样的原因,我们在本书中也不会使用这些概念和技术。

    http://zh.d2l.ai/chapter_multilayer-perceptrons/index.html  


参考资料:

[1] Jafari R. Hands-On Data Preprocessing in Python: Learn how to effectively prepare data for successful data analytics[M]. 第 1st 版. Packt Publishing, 2022.


Hands-On Data Preprocessing in Python-6 预测的评论 (共 条)

分享到微博请遵守国家法律