低代码AI:使用BigQuery ML训练线性回归模型

在本章中,您将学习如何从头开始构建一个线性回归模型和一个神经网络模型,用于预测发电厂的产量。您将使用SQL进行数据分析,使用Jupyter Notebook进行数据探索,并使用BigQuery Machine Learning(BigQuery ML)来训练ML模型。在此过程中,您将学习新的技术,以更好地理解数据,为进行机器学习做准备,并将这些知识应用于提高模型性能。

业务用例:发电厂产量

在这个项目中,您的目标是根据电厂附近的天气条件来预测联合循环发电厂(CCPP)的净每小时电能输出。CCPP由燃气轮机、汽轮机和余热锅炉组成。电力是由燃气和汽轮机生成的,它们在一个循环中结合在一起,从一个涡轮机传递到另一个涡轮机。而真空是从汽轮机收集的,其他三个环境变量(温度、环境压力和相对湿度)会影响燃气轮机的性能。

本节的数据集包含了在发电厂设置为满负荷运行时,六年(2006年至2011年)内从CCPP收集的数据点。数据是按小时聚合的,尽管数据集没有提供记录的精确时间,用于记录天气条件和能源产量。从实际角度来看,这意味着您将无法将数据视为序列或时间序列数据,其中您使用以前记录的信息来预测未来记录。

数据最初以CSV文件的形式提供,因此您需要花一些时间将数据加载到BigQuery中,然后才能探索它,并最终用它来创建ML模型。正如您马上将看到的,我们的数据集中有五列,如表6-1所示,共有9,590行。

这些期望值范围得到了电厂工程师的详细记录,并已与您共享(例如通过技术报告)。这将在探索数据时非常有帮助,以确保没有出现空值或类似第4章中讨论的"魔法数字"等问题。

在BigQuery中使用SQL清理数据集

正如之前讨论的,了解数据集在开始构建机器学习模型之前非常重要。请记住,您训练的任何机器学习模型的质量将严重依赖于用于训练模型的数据集的质量。如果数据集中充满错误的数据或缺失值,那么机器学习模型将无法学到正确的见解。

在本节中,您将使用SQL作为首选工具,以及BigQuery作为平台。本章中的所有SQL代码也可在low-code-ai存储库中找到。BigQuery是Google Cloud的无服务器数据仓库解决方案。这里的"无服务器"意味着您可以快速将数据加载到BigQuery中,并开始进行SQL数据分析,而无需提供任何服务器。如果您不熟悉SQL,那么Coursera上的Google提供的"准备数据进行探索"课程是一个很好的免费起点。Alan Beaulieu的《Learning SQL》(第3版,O'Reilly,2020)是希望深入了解SQL的人的良好资源。

如果您尚未使用BigQuery,它有一个免费套餐,可以覆盖本章线性回归中的活动。每个月通过SQL查询处理的前1 TB数据和每个月的前10 GB存储是免费的。此外,用于创建某些类型的ML模型(如线性回归)的前10 GB数据处理也是免费的。如果您有兴趣在BigQuery中对存储的数据进行机器学习,那么可以使用BigQuery ML。 BigQuery ML使用Vertex AI的资源来训练神经网络模型。如果您希望按照本节的内容在BigQuery ML中训练神经网络模型,您将会针对免费试用或结算账户产生费用。

将数据集加载到BigQuery中

CCPP数据集尚未在BigQuery中可用。首先,您需要将数据加载到BigQuery中。为了方便起见,我们已经将数据放置在一个公共的Google Cloud存储桶中(可在oreil.ly/zY85-下载)。 要将数据加载到BigQuery中,首先打开Google Cloud控制台,返回到BigQuery SQL工作区。在UI的左侧,选择您的项目名称,然后单击项目名称右侧的"查看操作"按钮,即三个垂直点。如图6-1所示,选择"创建数据集"。

确保在"项目ID"下选择您的项目。对于数据集ID,请在框中输入"data_driven_ml"。选择数据位置为美国,因为我们将加载到BigQuery中的数据位于基于美国的Cloud Storage存储桶中。现在点击"创建数据集"。按照图6-2中显示的字段输入数据。

一旦数据集创建完成,您可以使用"查看操作"按钮,如图6-3所示,来创建一个BigQuery表。选择数据集,点击"查看操作",然后选择"创建表"。

您需要指定从哪里加载数据、文件格式以及要创建的表的名称。这些选择已在表6-2中进行了总结。

如图6-4所示,展示了已填写所有必要值的"创建表"窗口。在您的情况下,CSV文件具有标题行,所有值都是浮点数,因此您可以让BigQuery从这些信息中检测模式。

保留"表类型","表分区"和"分簇"的默认值。单击"创建表"按钮,开始加载作业并创建原始数据的表格。

在表创建完成后,您可以通过选择表并选择"模式"选项卡来查看表的模式。您还可以通过选择"预览"选项卡来预览表中的数据。图6-5和6-6展示了在这些步骤中您应该在BigQuery控制台中看到的内容。

使用SQL在BigQuery中探索数据

现在数据已加载到BigQuery中,是时候开始探索数据了。首先,检查是否存在任何空值。在BigQuery中,最简单的方法是使用IF函数。IF语句,IF(expr, true_result, else_result),接受三个参数。expr语句返回一个布尔值,确定它是true_result还是else_result。正如您可能期望的那样,如果expr返回TRUE,那么将返回true_result,否则将返回else_result。

使用Null函数来检查空值

如果您想查看"Temp"列是否有空值,您可以使用以下语句:IF(Temp IS NULL, 1, 0)。这将在"Temp"为空时返回1,在"Temp"不为空时返回0。运行以下查询,将"your-project-id"替换为您的Google Cloud项目ID,并查看结果:

vbnet 复制代码
SELECT 
  IF(Temp IS NULL, 1, 0) AS is_temp_null
FROM
  `your-project-id.data_driven_ml.ccpp_raw`

如果您浏览结果,您将在超过9,000个值的列中找到两个1。这种方法可以工作,但效率不高,对吗(见图6-7)?相反,让我们利用true_result和else_result分别为1和0的事实。

您可以通过简单地使用SUM()函数来计算空值的数量,而不是在列表中滚动。运行以下查询,将"your-project-id"替换为您的Google Cloud项目ID,以计算每列的空值数量:

sql 复制代码
SELECT
  SUM(IF(Temp IS NULL, 1, 0)) AS no_temp_nulls,
  SUM(IF(Exhaust_Vacuum IS NULL, 1, 0)) AS no_ev_nulls,
  SUM(IF(Ambient_Pressure IS NULL, 1, 0)) AS no_ap_nulls,
  SUM(IF(Relative_Humidity IS NULL, 1, 0)) AS no_rh_nulls,
  SUM(IF(Energy_Production IS NULL, 1, 0)) AS no_ep_nulls
FROM
  `your-project-id.data_driven_ml.ccpp_raw`

运行此查询后,您应该会看到除"环境压力"(Ambient_Pressure)列之外,所有其他列都有空值。将您的结果与图6-8中的结果进行比较。

对于包含空值的行,应采取什么措施呢?最简单的方法是简单地省略这些行。另一个选项,在第7章中进行了探讨,是采用插补策略。插补是用替代值替换缺失数据的过程,通常以一种使替代值在特定上下文中看起来合理的方式进行。在这种情况下,您可能不是CCPP的专家。在最坏的情况下,包含空值的行将占数据的大约0.1%。因此,简单地省略这些行是一个非常合理的策略。

什么时候应该进行插补而不是丢弃数据?如果您有一个小的数据集,或者具有缺失值的行占数据集的重要百分比,那么丢弃相关行可能会极大地影响模型性能。另一个移除数据的更微妙问题涉及到偏差。统计偏差是指数据分布与实际数据分布之间的系统差异。如果空值出现在特定示例的特定子集中(例如,市场营销数据集中的某些人口统计信息),那么删除具有缺失值的行将使模型无法学习重要信息。

使用最小值(Min)和最大值(Max)函数来确定可接受的数据范围

接下来,请确保所有值都在预期范围内。快速执行此操作的最简单方法是使用MIN和MAX函数。与SUM函数类似,MIN和MAX是聚合函数的示例。聚合函数是接受一列或列的子集并返回单个值的函数。MIN和MAX函数分别返回它们应用于的列的最小值和最大值。继续通过运行以下SQL查询将这些函数应用于"Temp"列,再次将"your-project-id"替换为您的Google Cloud项目ID:

scss 复制代码
SELECT
  MIN(Temp) as min_temp,
  MAX(Temp) as max_temp
FROM
  `your-project-id.data_driven_ml.ccpp_raw`

您应该会看到最低温度为1.81°C,最高温度为37.11°C(请参见图6-9)。好消息是,这个数值范围与之前指定的温度数值范围相符。尝试使用相同的逻辑来检查其他列的范围。这次尝试自己编写查询,但如果遇到困难,查询已包含在图下方。

scss 复制代码
SELECT 
  MIN(Temp) as min_temp,
  MAX(Temp) as max_temp,
  MIN(Exhaust_Vacuum) as min_ev,
  MAX(Exhaust_Vacuum) as max_ev,
  MIN(Ambient_Pressure) as min_ap,
  MAX(Ambient_Pressure) as max_ap,
  MIN(Relative_Humidity) as min_rh,
  MAX(Relative_Humidity) as max_rh,
  MIN(Energy_Production) as min_ep,
  MAX(Energy_Production) as max_ep
FROM
  `your-project-id.data_driven_ml.ccpp_raw`

如果您仔细观察,您会发现有一些可疑的值。最低环境压力为0.0,最低能源生产值为-1.0。根据提供的数值范围以及常识,我们知道这两个值都没有意义。很可能,-1.0的值是一个神奇数字的示例。神奇数字是特殊的独特值,意味着它们代表的不是标准含义。由于-1.0作为能源生产值没有意义,这很可能是一个用来表示缺失数据的神奇数字。同样,最低环境压力的0.0值很可能是默认值的示例。默认值通常存在于应用程序中,用于在没有报告值时记录一个值。这用于避免一些可能会出现的NULL值引发的问题。

了解来自技术报告的预期值范围后,确保避免这些不现实值的最简单方法是基于预期范围进行筛选。请注意,这也会消除您之前检测到的NULL值,因为这些值也不在这些范围内。

在BigQuery中使用DDL语句保存查询结果

在编写用于筛选NULL和其他不需要的值的查询之前,重要的是要考虑如何将该查询的结果存储以供在训练ML模型中使用。这可以通过在BigQuery中执行DDL语句来完成。DDL代表数据定义语言,用于创建和修改数据集中的对象,如表格。您将使用CREATE TABLE语句来创建新表。在BigQuery中,CREATE TABLE语句的基本语法如下:

sql 复制代码
CREATE TABLE
  table_name
AS  
  query_statement

这个查询将创建一个名为"table_name"的新表,并将查询语句的结果保存到这个表中。请注意,使用这个语句,如果表已经存在,它不会被覆盖。如果您想这样做,您可以将CREATE TABLE替换为CREATE OR REPLACE TABLE。

现在您知道如何使用CREATE TABLE语句保存查询结果,您可以编写查询来清理原始发电厂数据,并将数据保存到一个新表中,比如ccpp_cleaned,以供训练ML模型使用。

这个查询很简单,但如果使用不等式来书写,可能会相当冗长。然而,可以利用BETWEEN运算符来简化查询。要使用BETWEEN,您需要通过以下方式指定一个最小值和一个最大值:

sql 复制代码
Field_name BETWEEN min_value AND max_value

如果您要检查的值在min_value和max_value之间,该语句将返回TRUE;否则,该语句将返回FALSE。例如,您正在查找介于420.26和495.76之间的Energy_Production值。之前讨论过的-1.0的值不在此范围内,因此将被过滤掉。特别是,我们只想保留与技术报告中共享的范围匹配的值。

与之前一样,尝试自己编写查询并在BigQuery中运行它,但如果需要帮助,以下是查询的内容:

sql 复制代码
CREATE TABLE
  `data_driven_ml.ccpp_cleaned`
AS
  SELECT 
    *
  FROM 
    `your-project-id.data_driven_ml.ccpp_raw`
  WHERE
    Temp BETWEEN 1.81 AND 37.11 AND
    Ambient_Pressure BETWEEN 992.89 AND 1033.30 AND
    Relative_Humidity BETWEEN 25.56 AND 100.16 AND
    Exhaust_Vacuum BETWEEN 25.36 AND 81.56 AND
    Energy_Production BETWEEN 420.26 AND 495.76

在执行查询后,您可以查看我们创建的新表的元数据,方法是在BigQuery UI左侧的面板中选择您的项目名称,然后单击数据集名称(data_driven_ml),最后选择表ccpp_cleaned。在打开与表对应的选项卡后,单击"详细信息"选项卡以查看表的元数据(请参见图6-11)。

新创建的ccpp_cleaned表有9,576行。如果您按照相同的过程查看原始ccpp_raw表,您会发现它有9,590行。这意味着您从我们的数据集中筛选出了14行,大约占所有数据的0.15%。由于进行清理,损失的数据非常少!然而,一些不正确的值,尤其是如果它们导致极端的异常值,可能会严重影响模型性能。因此,经过这个过程是一件好事。

线性回归模型

现在您已经清理了数据,准备好开始训练模型了,对吧?并不完全是这样。在早前的章节中,您依赖像AutoML这样的工具,在幕后为您处理了很多特征选择的过程。但现在在BigQuery ML中,特征选择需要您来完成。您将在下一个项目中深入探讨特征选择和工程方面的内容,但目前,您将集中在解决此问题时要使用的模型类型以及特征选择的标准。

在继续之前,请退一步,对问题再深思熟虑一下。目标是基于温度、环境压力、相对湿度和排气真空压力来预测CCPP的能源生产,如图6-12所示。

这是一个回归问题的示例,因为目标是预测一个实数:发电厂的能源生产,以兆瓦(MW)为单位。虽然BigQuery ML支持许多不同的模型类型,但通常最好的起点是最简单的一个,即线性回归模型,其中您试图找到最佳拟合线。

在第4章,您看到了线性回归的一个简化示例。在本章中,讨论会更深入,以便更好地理解模型的工作原理(请参见图6-13)。这样,当在本章后面选择要在ML模型训练中使用的特征时,您会更明智。

假设您有一些数值特征,x₁,...,xₙ,并且您想根据特征值来预测某个实数y。通常,x→被用作简写来表示特征列表x₁,...,xₙ。线性回归模型是一个具有以下形式的函数:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> f ( x ) = w 0 + w 1 × x 1 + . . . + w n × x n f(x)=w0+w1×x1+...+wn×xn </math>f(x)=w0+w1×x1+...+wn×xn

其中w₀、w₁、...、wₙ也是实数,它们被称为权重;w₀通常被称为模型的偏差。当然,您可以选择任何随机的权重并得到一个函数,但那会是一个多好的模型呢?

回顾一下,您在第4章中使用均方根误差(RMSE)来评估回归模型,您在这里也可以这样做。在继续之前,请回顾一下RMSE的定义。假设您的数据集D有N个示例(x→(i), y(i)),即对于特征值x→(i),相应的标签是y(i)。上标(i)表示我们正在查看数据集中的第i个示例。

给定一个模型f(x→),模型的RMSE表达式为:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> L ( f , D ) = 1 N ∑ i ( f ( x → ( i ) ) − y ( i ) ) 2 L ( f , D ) = 1 N ∑ i ( f ( x → ( i ) ) - y ( i ) ) 2 </math>L(f,D)=1N∑i(f(x→(i))−y(i))2

其中总和是针对数据集D中的所有示例。在这里包括参数D是为了提醒您,RMSE取决于用于计算它的数据集,就像我们正在评估的模型一样。

如果您只是选择一些权重w₀,...,wₙ,那么您如何知道您已经得到了给您最佳模型的权重呢?另一种提问这个问题的方式是,您希望尽量减小损失函数,即RMSE L(f, D)。

确定线性回归模型的适当权重通常有两种常用方法。第一种称为正规方程。使用数据集和相应的标签,解决正规方程可以提供最适合已选择特征的最佳模型的确切解决方案。许多分析软件包和产品(包括BigQuery)在其工具包中包含了这种方法。

如果有一种总是找到最佳权重的好方法,为什么不总是使用呢?嗯,有几个原因。首先是计算复杂性,或者计算所需的工作量。从技术上讲,我们说解决正规方程的计算复杂性略低于O(n³)。这实际上是什么意思呢?假设数据集从1,000增加到10,000个示例,增加了十倍。需要解决正规方程的工作量将大约增加1000倍!您可以看到,对于越来越大的数据集,这很快会变得不可控。

另一个稍微更加数学微妙的原因是计算可能涉及非常大的数字。由于计算机上的算术处理方式(浮点算术),这些大数字可能会在解决正规方程时引发问题。这种情况的技术术语是系统的条件状况不好。

不管情况如何,如果您有大量示例或在解决正规方程时遇到问题,还有一种可以采取的第二种方法,称为梯度下降。我们在这里不详细介绍,但要知道大多数(如果不是全部)ML框架都提供了梯度下降及其变种,可用于训练模型。要了解有关梯度下降基础知识的更多信息,请参阅Google的"机器学习速成课程"中的相应部分。

特征选择和相关性

现在已经确定了要使用的模型类型(线性回归),是时候选择要使用的特征了。回想一下,BigQuery中的已准备好的数据集中有四列可用于预测能源生产:Temp、Ambient_Pressure、Relative_Humidity和Exhaust_Vacuum。如何决定使用哪些特征呢?

一般来说,在选择特征时,有三个基本准则可以遵循:

  1. 特征应与问题目标相关。
  2. 特征在预测时应是已知的。
  3. 特征应该是数字的,或者可以转化为数字值。

这当然不是唯一的考虑因素,您将在本章和后续章节中了解更多的考虑因素,但这是一个很好的起点。第三个条件由于线性回归模型的性质,以及实际应用中使用的大多数其他模型类型,都是重要的。归根结底,ML模型是一个数学函数,它将数字特征作为输入并输出某个实数,然后根据模型目标进行解释。因此,从计算的角度来看,要么具有数字特征,要么能够将选择的特征转化为数字特征对于模型至关重要。

你的特征与问题目标相关吗?嗯,一般来说,回答这个问题可能有点棘手。要正确回答这个问题,您必须具有一定领域知识,即使在某些情况下,答案也可能相当微妙。有几种不同的方法来解决这个问题:

  1. 您可以利用您自己或其他专家的领域专业知识。
  2. 您可以使用统计方法,如相关性,来了解特征与目标之间的关系。

至于第一种方法,为简单起见,假设在报告中,领域专家明确表示这些特征与目标相关。这可能是一个不令人满意的答案,但通常作为ML从业者,您必须依赖那些真正了解领域的人来指导您寻找可能的特征。但这不应阻止您尝试研究您的模型所涉及的问题领域!随着在一个领域中解决更多问题,您将了解更多关于该领域的信息,并能够真正获得对该领域关键概念的直观理解。这种直觉是为模型引入人类洞察力的另一种方式。这不仅是一个有用的工具,通常也是构建解决问题的健壮模型的必要组成部分。

现在来看第二种方法。是的,您知道所有的特征都应该与模型目标相关,但您如何理解这种关系呢?在构建模型时,了解如何利用和转换特征的方式非常重要。这个过程,通常被称为特征工程,往往是改善模型性能的最有力的工具之一,可以超越改善数据的质量和数量。

对于线性模型,您可以使用的一个简单工具是皮尔逊相关性。给定两个(数值)变量X和Y,皮尔逊相关系数Corr(X, Y)是一个介于-1和1之间的数字,用于衡量这两个变量之间关系与线性关系有多接近。特别是,如果系数恰好为1,则X和Y具有完全线性关系。也就是说,存在一些正数m和b,使得Y = m × X + b。如果系数恰好为-1,那么思想是相同的,只是现在m是负数。那么介于之间呢?系数的绝对值越接近0,变量之间的线性关系就越远。有几种方法可用来确定特征之间的相关性。图6-14中显示了一些散点图及其对应的相关系数示例。

第一种方法是计算每对变量的相关系数。例如,在BigQuery中计算Temp列和Exhaust_Vacuum列之间的相关系数,您可以使用如下查询中所示的CORR函数:

sql 复制代码
SELECT
  CORR(Temp, Exhaust_Vacuum)
FROM
  `your-project-id.data_driven_ml.ccpp_cleaned`

您会发现Temp和Exhaust_Vacuum之间的相关系数约为0.844。您应该如何解释这个结果呢?这表示这两个特征之间存在中等到强的(正)线性关系。从物理角度来看,这是合理的,因为温度增加时,压力也会增加(假设所有其他变量保持不变)。

您可以更高效一些,一次计算一个列与多个列的相关性,但仍需要一些时间来编写查询。例如:

scss 复制代码
SELECT 
  CORR(Temp, Ambient_Pressure) AS corr_t_ap,
  CORR(Temp, Relative_Humidity) AS corr_t_rh,
  CORR(Temp, Exhaust_Vacuum) AS corr_t_ev
FROM 
  `your-project-id.data_driven_ml.ccpp_cleaned`

对于列数较少的情况,这并不是一个不合理的方法。在这里,我们有5列,包括标签,所以总共需要计算10个相关系数。但随着列数的增加,这个数量会迅速增长。当然,您可以进一步创建更高级的查询,并使用自动化来计算所有相关系数,但这种方法超出了本书的范围。

Google Colaboratory

另一种方法是利用Google Colaboratory,简称Google Colab,来创建、绘制和可视化相关矩阵。在后面的章节中,当介绍Python中的ML包时,您将使用Colaboratory作为无需提前设置环境的运行Python代码的简便方式。现在,您将了解如何将BigQuery的查询结果导入到Google Colab,以使用一些基本的Python进行探索性数据分析(EDA)。

从BigQuery加载所需数据的最简单方式是使用Google Colab中的内置连接器。BigQuery具有一个功能,可以创建一个模板笔记本,将查询的结果加载到笔记本环境中。现在,让我们走一遍设置这个环境的步骤。

首先,您需要运行要加载到笔记本环境的结果的查询。在这种情况下,编写并运行一个查询,该查询将返回整个清理过的数据集。与以前一样,以下是查询,以防您需要一点帮助:

markdown 复制代码
SELECT 
  *
FROM
  `your-project-id.data_driven_ml.ccpp_cleaned`

接下来,在刚刚运行的查询窗口中,选择控制台中的"探索数据"(在查询编辑器下),然后选择"使用Python笔记本进行探索",如图6-15所示。

当您选择"使用Python笔记本进行探索"时,Google Colab中将创建一个模板笔记本,使您能够使用通用的Python代码进行可视化探索或创建描述性统计。要创建可视化,只需在第一个单元格(设置)中添加两个导入语句:

javascript 复制代码
import matplotlib.pyplot as plt 
import seaborn as sns

在添加这两行之后,第一个单元格应如下所示:

python 复制代码
# @title Setup
from google.colab import auth
from google.cloud import bigquery
from google.colab import data_table
import matplotlib.pyplot as plt 
import seaborn as sns

project = 'your-project-id' 
location = 'US'
client = bigquery.Client(project=project, location=location)
data_table.enable_dataframe_formatter()
auth.authenticate_user()

现在,您已准备好运行笔记本中目前存在的所有单元格。要这样做,请点击单元格,然后点击单元格左侧的"运行单元格"按钮。您还可以按Ctrl+Enter(如果您使用的是macOS X,则为Cmd+Enter)来执行单元格。逐个单元格运行单元格,按顺序运行单元格非常重要,不要跳过单元格,以确保一切顺利运行。

最后一个单元格是预编码的,用于显示描述性统计信息,例如results.describe()。请注意,results是图6-16中显示的DataFrame。

现在,您可以轻松地创建一个相关矩阵,其中包含每对特征的不同相关系数。

要创建此矩阵,请通过点击笔记本上方的"+ 代码"按钮创建一个新的单元格,然后键入以下代码results.corr().round(2)。round方法用于将相关系数四舍五入到小数点后两位,以提高可读性。像以前一样运行单元格,并将结果与图6-17中的结果进行比较。

相关矩阵易于阅读。要找到两个特征之间的相关性,比如Temp和Ambient_Pressure,可以查找Temp的列和Ambient_Pressure的行(或反之亦然)以查找该值。在这种情况下,该值为-0.508(四舍五入到千分之一)。这意味着这两个特征之间存在中等的负相关性,降低温度会增加环境压力,反之亦然。

您还可以使用热图可视化此矩阵。要这样做,请在一个新单元格中键入以下代码,并像以前一样运行该单元格。请注意,您早些时候添加到笔记本的第一个单元格的两个导入语句是运行这些代码行所必需的。结果如图6-18所示:

ini 复制代码
plt.figure(figsize=(10,6))  
sns.heatmap(results.corr());

在继续之前,请完成以下关于您所提供的数据的知识检查:

  1. 哪些特征与Energy_Production具有强相关性?为什么?
  2. 哪些特征与Energy_Production具有弱相关性?为什么?
  3. 哪些特征与Energy_Production具有中等相关性?为什么?

绘制特征与标签之间的关系

进行探索性数据分析(EDA)以可视化特征和标签之间的关系也是了解哪些特征对模型最有用的绝佳方式。您可以继续在之前使用的同一Google Colab笔记本中可视化数据。

首先,通过将以下代码添加到新单元格并运行该单元格,可视化Temp特征与标签Energy_​Pro⁠duction之间的关系。将您的结果与图6-19中的可视化进行比较:

ini 复制代码
ax = sns.regplot(
    x='Temp', y='Energy_Production',
    fit_reg=False, ci=None, truncate=True, data=results)
ax.figure.set_size_inches(10,8)

现在,可视化Ambient_Pressure特征与标签Energy_Production之间的关系。首先尝试自己编写代码,如果需要帮助,以下是解决方案。将您的结果与图6-20中的可视化进行比较:

ini 复制代码
ax = sns.regplot(
    x='Ambient_Pressure', y='Energy_Production',
    fit_reg=False, ci=None, truncate=True, data=results)
ax.figure.set_size_inches(10,8)

最后,重复此过程,分别针对Relative_Humidity和Exhaust_Vacuum特征进行操作。与以前一样,解决方案代码在下面可视化,您应该将您的结果与图6-21和6-22中的可视化进行比较:

ini 复制代码
ax = sns.regplot(
    x='Relative_Humidity', y='Energy_Production',
    fit_reg=False, ci=None, truncate=True, data=results)
ax.figure.set_size_inches(10,8)
ini 复制代码
ax = sns.regplot(
    x='Vacuum_Pressure', y='Energy_Production',
    fit_reg=False, ci=None, truncate=True, data=results)
ax.figure.set_size_inches(10,8)

总结一下,Temp和Energy_Production之间存在强烈的"反向"关系------温度越低,能源产量越高。如果您查看之前的相关矩阵(图6-17),Temp和Energy_Production之间的相关系数为-0.948。这与图6-19中关于期望负线性关系的内容相符。

请记住,您的目标是基于温度、环境压力、相对湿度和排气真空压力来预测能源生产。是否应该丢弃相关性较弱的特征?这将使您从多变量模型转为单变量模型。本质上,您只会使用一个特征(Temp)来预测标签(Energy_Production)。这个模型是否具有可推广性?是否有其他数据可以收集以确定特征对能源生产的重要性?这些是在面临这种情况时需要自己考虑的问题。可以使用第1章的业务决策模型来帮助您决策。

在BigQuery ML中的CREATE MODEL语句

在本节中,您将使用BigQuery ML创建一个线性回归模型,该模型使用您的发电厂数据集中的所有特征。正如您将看到的,现在您已经准备好数据,这个过程非常简单。

使用CREATE MODEL语句

返回到BigQuery控制台。在BigQuery编辑器窗口中输入以下SQL语句来创建一个线性回归模型:

ini 复制代码
CREATE OR REPLACE MODEL data_driven_ml.energy_production OPTIONS
  (model_type='linear_reg',
   input_label_cols=['Energy_Production']) AS
SELECT
  Temp,
  Ambient_Pressure,
  Relative_Humidity,
  Exhaust_Vacuum,
  Energy_Production
FROM
  `your-project-id.data_driven_ml.ccpp_cleaned`

在执行查询之前,请注意以下关于符号的几点说明。CREATE OR REPLACE MODEL语句将在名为energy_production的数据集中创建一个新的ML模型,或者替换同名的模型。BigQuery中的ML模型是数据集中的对象,类似于表格。CREATE OR REPLACE MODEL语句有两个选项。第一个选项model_type指定模型类型(在这里是使用linear_reg的线性回归)。第二个选项input_label_cols是您指定用作标签的列。在本例中,该列是Energy_Production列。 现在运行查询来训练模型。这只需要几分钟的时间。在进入下一步之前,请等待模型训练完成。

查看已训练模型的评估指标

您可以在控制台中查看模型的度量指标。在模型表创建后,选择"评估"选项卡以查看评估指标。这些评估指标的示例如图6-23所示。请注意,您看到的度量指标可能与图中略有不同。

ML.EVALUATE函数也提供了评估指标。运行以下SQL查询以返回您模型的评估指标:

sql 复制代码
SELECT
  *
FROM
  ML.EVALUATE(MODEL data_driven_ml.energy_production)

JSON格式的输出如图6-24所示。

如您所见,控制台输出和ML.EVALUATE函数的输出是相同的,除了多出一个输出。ML.EVALUATE函数还通过explained_variance列提供了一个叫做"解释方差"的度量指标。解释方差可以看作是回答这个问题的一个指标:"我们的模型在其输出中捕获了多少标签的方差?"我们在这里不会深入讨论具体的细节,但如果平均标签值和平均预测值相同,那么我们期望解释方差和R2分数是相同的。这被称为无偏估计器,而线性回归就是这样的一个例子。 为什么这些分数在这里不同呢?因为您没有在我们的训练数据集上评估模型!在评估数据集上,只要评估数据集和训练数据集在统计上相似,您只期望这些指标彼此接近。当您训练模型时,BigQuery ML会自动将您的数据集分为训练和评估数据集,但在第7章中将探讨更多关于如何控制数据分割的选项。

使用ML.PREDICT函数进行预测

现在,您已经训练了模型并探索了评估指标,接下来是什么?ML的终极目标是为您的用例提供预测,而不仅仅是训练最佳的模型。一旦您在BigQuery ML中拥有一个性能令您满意的模型,使用ML.PREDICT函数非常简单来进行预测。请注意,ML.PREDICT只能用于BigQuery可以处理的数据进行预测。

假设您想要了解在平均温度为27.45°C,环境压力为1,001.23毫巴,相对湿度为84%,排气真空压力为65.12 cm Hg的情况下的发电量。您可以运行以下查询来计算这个预测:

vbnet 复制代码
SELECT
  *
FROM
  ML.PREDICT(MODEL `your-project-id.data_driven_ml.energy_production`,
    (
    SELECT
      27.45 AS Temp,
      1001.23 AS Ambient_Pressure,
      84 AS Relative_Humidity,
      65.12 AS Exhaust_Vacuum) )

请注意,第二个SELECT语句包括用于预测能源产量的特征值。最佳做法是使用AS关键字对列进行别名设置,以确保值被适当地传递到模型中。请注意,如果包含了不对应于特征的额外列,那么它们将被传递到结果中。这在您希望在结果表中包含预测的标签作为列,但还想包含未在模型中使用的列时会很有用。

将您的结果与图6-25中的结果进行比较,但请注意,您的模型预测的标签可能与此处所示的略有不同。predicted_label列包含了预测的能源产量。

在这里进行的方法非常适用于单个预测,但如果您想对一张包含多个特征值的表进行预测怎么办?您可以像使用ML.PREDICT函数进行单行预测一样,使用ML.PREDICT函数来在表格上提供预测。您可以将前面示例中的第二个SELECT语句替换为指定表格作为结果,而不是单行数据。例如:

sql 复制代码
SELECT
  *
FROM
  ML.PREDICT(MODEL `your-project-id.data_driven_ml.energy_production`,
    (
    SELECT
      Temp,
      Ambient_Pressure,
      Relative_Humidity,
      Exhaust_Vacuum
    FROM
      `your-project-id.some_dataset.some_table`) )

这种形式的查询将BigQuery转变为一个出色的批量预测工具,用于一次需要对大量实例进行预测的情况。

介绍可解释人工智能(Explainable AI)

在过去的十年中,随着深度学习和更复杂的模型的增长,可解释人工智能(或简称XAI)已成为快速增长的研究领域。XAI的目标是以人可以理解的术语描述模型的行为。这种理解可以在许多不同的情境下使用:提高模型的性能,理解模型存在的问题,确保模型避免特定的偏见以符合法规或伦理原因,以及许多其他用例。本节在使用BigQuery ML时提供了一个简要的介绍。

在讨论XAI时,通常会讨论本地或全局解释。本地解释关注单个实例或可能是一小组实例。您可以将其目标视为"为什么我的模型对这个特定示例进行了这个预测?"全局解释则将模型在某个数据集上的整体行为视为一个整体。例如,为了回答问题"哪些特征往往对这个模型的预测贡献最大?",您可以使用全局解释。

如何计算这些解释?大多数方法是事后使用的,也就是在模型训练之后。这些方法可以特定于某些模型类型,也可以对所使用的模型不加限制。通常,事后方法使用特定数据集(比如您的评估数据集)以及对模型在该数据集上的行为和扰动进行解释。

某些模型本质上是可解释的,比如线性回归模型。在这种情况下,解释可以直接从模型本身中派生,无需使用单独的数据集。然而,存在一种权衡。一般来说,越复杂的模型越不容易解释。更复杂的模型类型,如大多数图像和语言模型中使用的深度神经网络,无法从模型定义中解释,您必须依赖事后方法。

在本章和接下来的章节中,您将看到其中一些方法,但如果想更深入地了解这些概念,Michael Munn和David Pitman的《Explainable AI for Practitioners》(O'Reilly,2022)是一个很好的资源。

BigQuery ML中的可解释人工智能(Explainable AI)

在BigQuery中,除了ML.EVALUATE函数提供的评估指标之外,还提供了一种解释模型和其生成的预测的方式的函数。BigQuery中提供的全局和局部解释使用了Google Cloud的可解释人工智能(Explainable AI)服务。BigQuery中的可解释AI提供了"特征归因"(feature attributions),显示哪些输入特征对您的模型整体和特定预测最重要。要计算全局解释,您需要修改CREATE MODEL查询,并添加一个额外的选项以启用全局可解释性:

ini 复制代码
enable_global_explanation = TRUE

全局可解释性返回特征对模型的整体影响,通常是通过对整个数据集上的特征归因进行汇总得出的。较高的绝对值表示该特征对模型的预测有更大的影响。

局部解释可以在不启用全局解释的情况下计算。接下来,您将看到这两种解释的示例。

修改 CREATE MODEL 语句

复制原始的 CREATE OR REPLACE MODEL 查询到一个新的查询窗口。然后通过添加 enable_global_explain=TRUE 语句来修改查询,如下所示:

ini 复制代码
CREATE OR REPLACE MODEL data_driven_ml.energy_production: OPTIONS
  (model_type='linear_reg',
   input_label_cols=['Energy_Production'],
   enable_global_explain=TRUE) AS
SELECT
  Temp,
  Ambient_Pressure,
  Relative_Humidity,
  Exhaust_Vacuum,
  Energy_Production
FROM
  `your-project-id.data_driven_ml.ccpp_cleaned`

运行这个修改后的查询,以训练一个启用了全局解释的新模型版本。这应该只需要几分钟的时间。等到模型完成训练后再进行下一步。

使用 ML.GLOBAL_EXPLAIN 函数

为了查看解释,您可以创建一个基本的"SELECT * FROM" SQL语句。不同之处在于FROM语句。FROM语句不再引用项目ID、数据集和表格,而是修改为以下示例代码中所示。ML.GLOBAL_EXPLAIN函数调用模型本身(在这种情况下是"energy_production")来检索结果。在BigQuery控制台中运行以下查询,以自行探索这一点:

sql 复制代码
SELECT 
  *
FROM
  ML.GLOBAL_EXPLAIN(MODEL `data_driven_ml.energy_production`)

图6-26包含了查询结果,并显示了模型整体上具有最重要分数的特征。根据之前对相关性使用的特征分析,您可以期望温度特征具有最大的贡献分数,这在这里得到了确认。

使用ML.EXPLAIN_PREDICT函数计算局部解释

回想一下我们之前的例子:您想知道当温度平均为27.45°C,环境压力为1,001.23毫巴,相对湿度为84%,排气真空为65.12厘米汞柱的一个小时内,发电量会是多少。您使用了ML_PREDICT函数来预测这个小时的能量产出将达到433.35兆瓦。根据模型的全局特征归因,您预计温度将具有最大的影响。然而,一般情况下,全局解释是基于整个数据集的汇总 - 那么特别的这个示例呢? 您可以将ML.PREDICT方法替换为ML.EXPLAIN_PREDICT方法,以返回带有局部特征归因的预测。运行以下查询以获取前三个特征的特征归因。请注意,您的确切输出可能与图6-27中显示的输出不同:

vbnet 复制代码
SELECT
  *
FROM
  ML.EXPLAIN_PREDICT(
    MODEL `your-project-id.data_driven_ml.energy_production`,
    (
    SELECT
      Temp,
      Ambient_Pressure,
      Relative_Humidity,
      Exhaust_Vacuum
    FROM
      `your-project-id.data_driven_ml.ccpp_cleaned`),
    STRUCT(3 AS top_k_features) )

在输出结果中有一些新的语法和列需要解释。ML.EXPLAIN_PREDICT的附加参数是STRUCT(3 AS top_k_features),它限制了特征归因的输出,仅包括前三个重要特征。top_k_features选项用于实现此目的,而ML.EXPLAIN_PREDICT期望这些信息以STRUCT的形式传递。在SQL中,STRUCT可以被看作是一系列具有特定名称和可能不同类型的值(或列)的集合。

接下来是新列。top_feature_attributions本身也是一个STRUCT,包括两个字段,feature和attribution。字段feature给出了相应的特征名称,而attribution给出了该实例的归因值。还有另一个新列:baseline_prediction_value。此值提供了一个与实例进行比较以获取局部特征归因的基线。在线性回归模型的情况下,此基线是整个数据集中标签值(能源生产)的平均值。

那么,如何解释这些归因值呢?请注意,预测标签小于基线预测,并且所有归因值都为负数。温度值平均从基线值减少了约18.52 MW,相对湿度平均减少了约2.16 MW,气压平均减少了0.31 MW。排气真空压力在此处没有包括在内,因为它不在前三名中,但对于此示例的贡献甚至比环境压力小。因此,可以看到,对于这个示例,与基线能源生产相比,温度占据了大部分偏差,其他特征只有一些小的贡献。

还有另一个选择,即在Jupyter笔记本中使用解释性AI库,例如Google Colab笔记本。LIME和SHAP是两个常用的Python库,通常在许多不同的用例中使用。本书无法详细讨论这些内容;我们建议查看已经提到的博客文章和其他解释性AI参考资料,以获得更深入的讨论和明确的示例。

BigQuery ML中的神经网络

现在,您已经使用BigQuery ML训练了线性回归模型,现在是时候看一下另一种流行的ML模型类型:神经网络。由于额外的计算资源的可用性、新的模型架构以及它们具有将一个问题中的知识应用到另一个问题中的灵活性,神经网络在过去的十年中变得非常流行。本节提供了关于神经网络的简要介绍,然后展示如何在BigQuery ML中构建这样的模型。

神经网络的简要概述

与线性回归模型类似,神经网络也是数学函数,它以数值特征值作为输入并输出标签的预测值。神经网络可以用于回归和分类问题,但在本节中,重点将放在回归模型上。 为了描述神经网络,让我们用直观的方式重新描述线性回归。回想一下,对于预测能源产量的问题,有四个特征:温度、环境压力、相对湿度和排气真空压力。为了简化,将它们标记为x1、x2、x3和x4。使用这四个特征的线性回归模型将具有以下形式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> f ( x ) = y = w 0 + w 1 x 1 + w 2 x 2 + w 3 x 3 + w 4 x 4. f ( x ) = y = w 0 + w 1 x 1 + w 2 x 2 + w 3 x 3 + w 4 x 4 . </math>f(x)=y=w0+w1x1+w2x2+w3x3+w4x4.

为了将这个模型可视化为一个网络,可以绘制一个类似于图6-28的图表。为四个特征和输出y分别绘制一个顶点。从特征顶点到输出顶点绘制箭头,并在这些边上标上权重w1、w2、w3和w4。通常,在这种表示中,偏差w0不绘制成任何内容。

现在,您已经将一个线性回归模型可视化为一个神经网络!在一般情况下,我们将首先以图形表示一个不是线性回归模型的神经网络。现在,假设您想将原始特征组合成新的隐藏特征z1和z2,其中每个特征都是原始特征的线性组合,或者您可以将其视为特征的加权和。从技术上讲,这是一个如下形式的表达式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> z 1 = c 0 + c 1 x 1 + c 2 x 2 + c 3 x 3 + c 4 x 4 z 1 = c 0 + c 1 x 1 + c 2 x 2 + c 3 x 3 + c 4 x 4 </math>z1=c0+c1x1+c2x2+c3x3+c4x4

其中ci是一些实数。隐藏特征z2将具有相似的定义,但常数不同(例如,使用di而不是ci)。严格来说,c0项使得这与仅仅是特征的线性组合有些不同,但如果您将1包括作为一个常数特征,那么技术上的定义与此处的用法是一致的。 我们将这些隐藏特征一起称为一个隐藏层。它们被称为"隐藏",因为您在模型的输入或输出中看不到它们,但它们在从输入计算输出时起作用。您可以以与之前相同的方式进行可视化表示,但现在特征节点连接到新的隐藏特征z1和z2,而隐藏特征连接到输出y,如图6-29所示。

这是一个具有一个隐藏层的神经网络示例。然而,您如何确定这些隐藏特征应该是什么呢?也就是说,如何找到各种 c i 和 d i 的最佳值呢?神经网络没有正规方程,但您可以像之前一样使用梯度下降!与尝试不同组合不同,您可以将 c i 和 d i 视为线性回归模型中的其他权重,然后训练模型以找到最佳权重。

相关推荐
artificiali2 小时前
Anaconda配置pytorch的基本操作
人工智能·pytorch·python
酱香编程,风雨兼程3 小时前
深度学习——基础知识
人工智能·深度学习
Lossya3 小时前
【机器学习】参数学习的基本概念以及贝叶斯网络的参数学习和马尔可夫随机场的参数学习
人工智能·学习·机器学习·贝叶斯网络·马尔科夫随机场·参数学习
Trouvaille ~3 小时前
【Python篇】深度探索NumPy(下篇):从科学计算到机器学习的高效实战技巧
图像处理·python·机器学习·numpy·信号处理·时间序列分析·科学计算
#include<菜鸡>4 小时前
动手学深度学习(pytorch土堆)-04torchvision中数据集的使用
人工智能·pytorch·深度学习
有颜有货4 小时前
低代码开发平台系统架构概述
低代码·系统架构
lgbisha4 小时前
828华为云征文|华为云Flexus X实例docker部署最新Appsmith社区版,搭建自己的低代码平台
低代码·docker·华为云
程序员-杨胡广4 小时前
从0-1 用AI做一个赚钱的小红书账号(不是广告不是广告)
人工智能
AI进修生4 小时前
全新WordPress插件简化成功之路
人工智能·语言模型·自然语言处理
GG_Bond194 小时前
【项目设计】Facial-Hunter
服务器·人工智能