使用回归预测数值

编辑

回归分析是一种监督式机器学习过程,用于估计数据中不同字段之间的关系,然后根据这些关系对数值数据进行进一步预测。例如,您可以根据历史数据预测 Web 请求的响应时间或服务器与客户端交换的大致数据量。

执行回归分析时,必须识别要用于创建预测其他字段模型的字段子集。特征变量是用于创建模型的字段。因变量是要预测的字段。

回归算法

编辑

回归使用一种类似于极端梯度提升 (XGBoost) 的集成学习技术,它将决策树与梯度提升方法相结合。XGBoost 训练一系列决策树,并且每棵决策树都从迄今为止森林的错误中学习。在每次迭代中,添加到森林中的树都会提高组合决策森林的决策质量。默认情况下,回归算法针对称为均方误差损失的损失函数进行优化。

您可以使用这三种类型的特征变量:数值型、分类型或布尔型。不支持数组。

1. 定义问题

编辑

在需要预测连续量的情况下,回归非常有用。回归分析可以预测的值是数值。如果您的用例需要预测连续的数值,那么回归可能是适合您的选择。

2. 设置环境

编辑

在使用 Elastic Stack 机器学习功能之前,必须解决一些配置要求(例如安全权限)。请参阅设置和安全

3. 准备和转换数据

编辑

回归是一种监督式机器学习方法,这意味着您需要提供带标签的训练数据集。此数据集必须包含用于训练模型的特征变量和因变量的值。此信息在训练期间用于识别数据各种特征与预测值之间的关系。此带标签的数据集在模型评估中也起着至关重要的作用。

您可能还需要转换您的数据以创建可作为回归源的数据框。

要详细了解如何准备数据,请参阅监督学习概述的相关部分

4. 创建作业

编辑

数据框分析作业包含执行分析任务所需的配置信息和元数据。您可以通过 Kibana 或使用创建数据框分析作业 API创建数据框分析作业。

选择回归作为作业的分析类型,然后选择要预测的字段(因变量)。您还可以包含和排除分析中的字段。

您可以在数据框分析向导中查看可选字段的统计信息。弹出窗口中显示的字段统计信息提供了更有意义的上下文,以帮助您选择相关字段。

5. 启动作业

编辑

您可以通过 Kibana 或使用启动数据框分析作业 API启动作业。回归作业具有以下阶段

  • 重新索引:文档从源索引复制到目标索引。
  • 加载数据:作业从目标索引获取必要的数据。
  • 特征选择:该过程识别预测因变量最相关的分析字段。
  • 粗略参数搜索:该过程识别未定义超参数的初始值。
  • 微调参数:该过程识别未定义超参数的最终值。请参阅超参数优化
  • 最终训练:模型训练发生。
  • 写入结果:作业将结果与目标索引中的数据行匹配,合并它们,并将它们索引回目标索引。
  • 推理:作业根据数据集的测试拆分验证训练好的模型。

最后一个阶段完成后,作业停止,结果就可以进行评估了。

创建数据框分析作业时,如果模型太大而无法放入 JVM,则该过程的推理步骤可能会失败。有关解决方法,请参阅此 GitHub 问题

6. 评估结果

编辑

使用数据框分析功能从数据集中获取见解是一个迭代过程。在定义了要解决的问题并选择了可以帮助您解决问题的分析类型后,您需要生成高质量的数据集并创建相应的数据框分析作业。在获得满足您的用例的结果之前,您可能需要尝试不同的配置、参数和数据转换方式。此过程的一个宝贵伴侣是评估数据框分析 API,它使您能够评估数据框分析的性能。它可以帮助您了解错误分布,并识别数据框分析模型表现良好或不太可靠的点。

要使用此 API 评估分析,您需要使用一个字段注释包含分析结果的索引,该字段用地面实况标记每个文档。评估数据框分析 API 根据此手动提供的地面实况评估数据框分析的性能。

您可以使用评估数据框分析 API回归评估类型来衡量模型在训练数据上的表现。评估在训练数据集上提供的均方误差 (MSE)值是训练误差。迭代地训练和评估模型意味着找到产生尽可能低的训练误差的模型参数组合。

另一个关键指标是模型在未见过的数据上的表现。为了评估训练好的模型在从未见过的数据上的表现,您必须为测试保留一部分训练集(测试数据)。模型训练完成后,您可以让它预测它从未见过的数据点的值,并将预测值与实际值进行比较。此测试提供了称为模型泛化误差的数量的估计。

回归评估类型提供以下指标来评估模型性能

  • 均方误差 (MSE)
  • 均方对数误差 (MSLE)
  • 伪 Huber 损失
  • R 平方 (R2)

均方误差

编辑

MSE 是真实值与预测值之差的平方和的平均值。(Avg (预测值-实际值)2)。

均方对数误差

编辑

MSLE 是均方误差的一种变体。它可用于目标值是正数且分布具有长尾的情况,例如价格或人口数据。请参阅回归分析的损失函数页面,详细了解损失函数。

伪 Huber 损失

编辑

伪 Huber 损失指标对于大于预定义值(默认为1)的误差表现为平均绝对误差 (MAE),对于小于预定义值的误差表现为均方误差 (MSE)。此损失函数使用delta参数定义 MAE 和 MSE 之间的转换点。请参阅回归分析的损失函数页面,详细了解损失函数。

R 平方

编辑

R 平方 (R2) 表示拟合优度,并衡量预测能够解释数据中多少变化。R2 的值小于或等于 1,其中 1 表示预测值和真实值相等。当所有预测值都设置为真实值的平均值时,获得值为 0。R2 为 0.5 表示预测值比其平均值更接近真实值 1 - 0.5(1/2)(约 30%)。

特征重要性

编辑

特征重要性提供了有关分析结果的更多信息,并有助于以更细致的方式解释结果。如果您想详细了解特征重要性,请点击此处

7. 部署模型

编辑

您创建的模型作为 Elasticsearch 文档存储在内部索引中。换句话说,训练好的模型的特征已保存并准备作为函数部署和使用。推理功能使您能够在摄取管道的预处理器或搜索查询的管道聚合中使用您的模型来预测数据。

  1. 要在管道中部署数据框分析模型,请在 Kibana 中导航到机器学习 > 模型管理 > 训练好的模型
  2. 在列表中找到要部署的模型,然后在操作菜单中点击部署模型

    The trained models UI in Kibana
  3. 创建推理管道以能够通过管道对新数据使用模型。添加名称和描述或使用默认值。

    Creating an inference pipeline
  4. 配置管道处理器或使用默认设置。

    Configuring an inference processor
  5. 配置处理摄取失败或使用默认设置。
  6. (可选)通过运行管道的模拟来测试您的管道,以确认它产生预期结果。
  7. 查看设置,然后点击创建管道

模型已部署并准备通过推理管道使用。

推理

编辑

推理使您能够以连续的方式对传入数据使用训练好的机器学习模型

例如,假设您有一个在线服务,并且想要预测客户是否可能流失。您有一个包含历史数据的索引——关于客户在您业务中多年行为的信息——以及在此数据上训练的分类模型。新信息进入连续转换的目标索引。通过推理,您可以使用与训练模型相同的输入字段对新数据执行分类分析,并获得预测。

推理处理器
编辑

推理可以用作摄取管道中指定的处理器。它使用经过训练的模型对管道中正在摄取的数据进行推理。该模型在摄取节点上使用。推理通过使用模型预处理数据并提供预测。处理完成后,管道继续执行(如果管道中有其他处理器),最后将新数据连同结果一起索引到目标索引中。

查看推理处理器机器学习数据帧分析 API 文档以了解更多信息。

推理聚合
编辑

推理也可以用作管道聚合。您可以在聚合中引用经过训练的模型,以对父桶聚合的结果字段进行推理。推理聚合在结果上使用模型以提供预测。此聚合使您能够在搜索时运行分类或回归分析。如果您想对一小部分数据执行分析,此聚合使您能够生成预测,而无需在摄取管道中设置处理器。

查看推理桶聚合机器学习数据帧分析 API 文档以了解更多信息。

如果您使用经过训练的模型别名在推理处理器或推理聚合中引用您的训练模型,则可以将训练模型替换为新的模型,而无需更新处理器或聚合。通过使用创建或更新训练模型别名 API将您使用的别名重新分配给新的训练模型 ID。新的训练模型需要使用与旧模型相同类型的数据帧分析。

在示例航班数据集中执行回归分析

编辑

让我们尝试使用示例航班数据来预测航班延误。数据集包含诸如天气状况、航班目的地和始发地、航班距离、航空公司以及每个航班延误的分钟数等信息。当您创建回归作业时,它会学习数据中字段之间的关系,以预测因变量的值,在本例中,它是数字FlightDelayMins字段。有关这些概念的概述,请参阅使用回归预测数值监督学习简介

准备您的数据

编辑

数据集中每个文档都包含单个航班的详细信息,因此此数据已准备好进行分析;它已经处于二维实体为基础的数据结构中。通常,您需要转换数据到以实体为中心的索引,然后再对其进行分析。

要进行分析,文档必须至少包含一个具有受支持数据类型(numericbooleantextkeywordip)的字段,并且不得包含超过一个项目的数组。如果您的源数据包含一些包含因变量的文档,而另一些则不包含,则模型将在包含因变量的文档子集上进行训练。

示例源文档
{
  "_index": "kibana_sample_data_flights",
  "_type": "_doc",
  "_id": "S-JS1W0BJ7wufFIaPAHe",
  "_version": 1,
  "_seq_no": 3356,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "FlightNum": "N32FE9T",
    "DestCountry": "JP",
    "OriginWeather": "Thunder & Lightning",
    "OriginCityName": "Adelaide",
    "AvgTicketPrice": 499.08518599798685,
    "DistanceMiles": 4802.864932998549,
    "FlightDelay": false,
    "DestWeather": "Sunny",
    "Dest": "Chubu Centrair International Airport",
    "FlightDelayType": "No Delay",
    "OriginCountry": "AU",
    "dayOfWeek": 3,
    "DistanceKilometers": 7729.461862731618,
    "timestamp": "2019-10-17T11:12:29",
    "DestLocation": {
      "lat": "34.85839844",
      "lon": "136.8049927"
    },
    "DestAirportID": "NGO",
    "Carrier": "ES-Air",
    "Cancelled": false,
    "FlightTimeMin": 454.6742272195069,
    "Origin": "Adelaide International Airport",
    "OriginLocation": {
      "lat": "-34.945",
      "lon": "138.531006"
    },
    "DestRegion": "SE-BD",
    "OriginAirportID": "ADL",
    "OriginRegion": "SE-BD",
    "DestCityName": "Tokoname",
    "FlightTimeHour": 7.577903786991782,
    "FlightDelayMin": 0
  }
}

本示例中使用了示例航班数据,因为它易于访问。但是,数据包含一些不一致之处。例如,航班可以同时延误和取消。这是一个很好的提醒,即输入数据的质量会影响结果的质量。

创建回归模型

编辑

预测每个航班延误的分钟数

  1. 验证您的环境是否已正确设置以使用机器学习功能。Elastic Stack 安全功能需要具有创建和管理数据帧分析作业权限的用户。请参阅设置和安全
  2. 创建一个数据帧分析作业。

    您可以在 Kibana 中的机器学习 > 数据帧分析选项卡或创建数据帧分析作业API 上使用向导。

    Creating a data frame analytics job in Kibana
    1. 选择kibana_sample_data_flights作为源索引。
    2. 选择regression作为作业类型。
    3. 可以选择通过添加删除错误数据的查询来提高分析质量。在本例中,我们省略了距离为 0 公里或更短的航班。
    4. 选择FlightDelayMin作为因变量,即我们要预测的字段。
    5. CancelledFlightDelayFlightDelayType添加到排除字段列表中。这些字段将从分析中排除。建议排除包含错误数据或描述dependent_variable的字段。

      向导包含一个散点图矩阵,它使您能够探索数值字段之间的关系。每个点的颜色受该文档因变量的值影响,如图例所示。您可以突出显示其中一个图表中的区域,其余图表中的对应区域也会突出显示。您可以使用此矩阵来帮助您确定要包含或排除哪些字段进行分析。

      A scatterplot matrix for three fields in Kibana

      如果您希望这些图表表示来自更大样本量或来自文档随机选择的数据,则可以更改默认行为。但是,更大的样本量可能会降低矩阵的性能,而随机选择可能会由于更密集的查询而给集群带来更多负载。

    6. 选择90的训练百分比,这意味着它会随机选择 90% 的源数据进行训练。
    7. 如果您想尝试特征重要性,请在高级配置选项中指定一个值。在本例中,我们选择每个文档最多返回 5 个特征重要性值。此选项会影响分析速度,因此默认情况下它处于禁用状态。
    8. 使用至少 50 MB 的模型内存限制。如果作业需要超过此内存量,则无法启动。如果节点上的可用内存有限,此设置可以防止作业执行。
    9. 添加作业 ID(例如model-flight-delay-regression)以及可选的作业描述。
    10. 添加将包含分析结果的目标索引的名称。在 Kibana 中,索引名称默认情况下与作业 ID 匹配。它将包含源索引数据的副本,其中每个文档都用结果进行注释。如果索引不存在,则会自动创建。

      API 示例
      PUT _ml/data_frame/analytics/model-flight-delays-regression
      {
        "source": {
          "index": [
            "kibana_sample_data_flights"
          ],
          "query": {
            "range": {
              "DistanceKilometers": {
                "gt": 0
              }
            }
          }
        },
        "dest": {
          "index": "model-flight-delays-regression"
        },
        "analysis": {
          "regression": {
            "dependent_variable": "FlightDelayMin",
            "training_percent": 90,
            "num_top_feature_importance_values": 5,
            "randomize_seed": 1000
          }
        },
        "model_memory_limit": "50mb",
        "analyzed_fields": {
          "includes": [],
          "excludes": [
            "Cancelled",
            "FlightDelay",
            "FlightDelayType"
          ]
        }
      }

      配置完作业后,配置详细信息会自动验证。如果检查成功,您可以继续并启动作业。如果配置无效,则会显示警告消息。该消息包含有关改进配置以进行验证的建议。

  3. 在 Kibana 中启动作业或使用启动数据帧分析作业API。

    作业需要几分钟才能运行。运行时间取决于本地硬件以及分析的文档和字段的数量。字段和文档越多,作业运行时间越长。分析完成后会自动停止。

    API 示例
    POST _ml/data_frame/analytics/model-flight-delays-regression/_start
  4. 检查作业统计信息以跟踪 Kibana 中的进度,或使用获取数据帧分析作业统计信息 API

    Statistics for a data frame analytics job in Kibana

    作业停止后,结果即可查看和评估。要了解有关作业阶段的更多信息,请参阅数据帧分析作业的工作原理

    API 示例
    GET _ml/data_frame/analytics/model-flight-delays-regression/_stats

    API 调用返回以下响应

    {
      "count" : 1,
      "data_frame_analytics" : [
        {
          "id" : "model-flight-delays-regression",
          "state" : "stopped",
          "progress" : [
            {
              "phase" : "reindexing",
              "progress_percent" : 100
            },
            {
              "phase" : "loading_data",
              "progress_percent" : 100
            },
            {
              "phase" : "feature_selection",
              "progress_percent" : 100
            },
            {
              "phase" : "coarse_parameter_search",
              "progress_percent" : 100
            },
            {
              "phase" : "fine_tuning_parameters",
              "progress_percent" : 100
            },
            {
              "phase" : "final_training",
              "progress_percent" : 100
            },
            {
              "phase" : "writing_results",
              "progress_percent" : 100
            },
            {
              "phase" : "inference",
              "progress_percent" : 100
            }
          ],
          "data_counts" : {
            "training_docs_count" : 11210,
            "test_docs_count" : 1246,
            "skipped_docs_count" : 0
          },
          "memory_usage" : {
            "timestamp" : 1599773614155,
            "peak_usage_bytes" : 50156565,
            "status" : "ok"
          },
          "analysis_stats" : {
            "regression_stats" : {
              "timestamp" : 1599773614155,
              "iteration" : 18,
              "hyperparameters" : {
                "alpha" : 19042.721566629778,
                "downsample_factor" : 0.911884068909842,
                "eta" : 0.02331774683318904,
                "eta_growth_rate_per_tree" : 1.0143154178910303,
                "feature_bag_fraction" : 0.5504020748926737,
                "gamma" : 53.373570122718846,
                "lambda" : 2.94058933878574,
                "max_attempts_to_add_tree" : 3,
                "max_optimization_rounds_per_hyperparameter" : 2,
                "max_trees" : 894,
                "num_folds" : 4,
                "num_splits_per_feature" : 75,
                "soft_tree_depth_limit" : 2.945317520946171,
                "soft_tree_depth_tolerance" : 0.13448633124842999
              },
              "timing_stats" : {
                "elapsed_time" : 302959,
                "iteration_time" : 13075
              },
              "validation_loss" : {
                "loss_type" : "mse"
              }
            }
          }
        }
      ]
    }

查看回归结果

编辑

现在您有一个新的索引,其中包含源数据的副本以及因变量的预测。

当您在 Kibana 中查看结果时,它会以表格格式显示目标索引的内容。它还提供有关分析详细信息、模型评估指标、总特征重要性值和散点图矩阵的信息。让我们从查看结果表开始

Results for a data frame analytics job in Kibana

在本例中,该表显示了因变量(FlightDelayMin)的列,其中包含我们尝试预测的基本事实值。它还显示了预测值(ml.FlightDelayMin_prediction)的列和指示文档是否用于训练集(ml.is_training)的列。您可以过滤表格以仅显示测试或训练数据,并且可以选择在表格中显示哪些字段。您还可以启用直方图图表以更好地了解数据中值的分布。

如果您选择计算特征重要性,则目标索引还包含ml.feature_importance对象。包含在回归分析中的每个字段(称为数据点的特征)都会分配一个特征重要性值。此值既有大小也有方向(正或负),表示每个字段如何影响特定预测。索引中仅存储最重要的值(在本例中为前 5 个)。但是,训练模型元数据还包含所有训练数据中每个字段的特征重要性值的平均大小。您可以在 Kibana 中查看此汇总信息

Total feature importance values in Kibana

您还可以以决策图的形式查看每个单独预测的特征重要性值

A decision plot for feature importance values in Kibana

决策路径从基线开始,基线是训练数据集中所有数据点的预测值的平均值。从那里开始,特征重要性值被添加到决策路径中,直到它到达最终预测。影响最大(正向或负向)的特征显示在顶部。因此,在这个例子中,与航班距离相关的特征对这个特定的预测航班延误影响最大。这种类型的信息可以帮助您了解模型如何得出其预测结果。当您训练和调整模型时,它还可以指示数据集中哪些方面影响最大或最不有用。

如果您不使用 Kibana,您可以使用获取训练模型 API查看汇总的特征重要性值,并通过搜索目标索引查看各个值。

API 示例
GET _ml/inference/model-flight-delays-regression*?include=total_feature_importance,feature_importance_baseline

下面的代码片段显示了训练模型元数据中特征重要性详细信息的示例。

{
  "count" : 1,
  "trained_model_configs" : [
    {
      "model_id" : "model-flight-delays-regression-1601312043770",
      ...
      "metadata" : {
        ...
        "feature_importance_baseline" : {
          "baseline" : 47.43643652716527 
        },
        "total_feature_importance" : [
          {
            "feature_name" : "dayOfWeek",
            "importance" : {
              "mean_magnitude" : 0.38674590521018903, 
              "min" : -9.42823116446923, 
              "max" : 8.707461689065173 
            }
          },
          {
            "feature_name" : "OriginWeather",
            "importance" : {
            "mean_magnitude" : 0.18548393012368913,
            "min" : -9.079576266629092,
            "max" : 5.142479101907649
          }
          ...

特征重要性决策路径的基线。它是所有训练数据的预测值的平均值。

所有训练数据中dayOfWeek字段的平均绝对特征重要性值。

此字段在所有训练数据中的最小特征重要性值。

此字段在所有训练数据中的最大特征重要性值。

要查看每个预测的顶级特征重要性值,请搜索目标索引。例如

GET model-flight-delays-regression/_search

下面的代码片段显示了带有注释结果的文档的一部分。

          ...
          "DestCountry" : "CH",
          "DestRegion" : "CH-ZH",
          "OriginAirportID" : "VIE",
          "DestCityName" : "Zurich",
          "ml": {
            "FlightDelayMin_prediction": 277.5392150878906,
            "feature_importance": [
            {
              "feature_name": "DestCityName",
              "importance": 0.6285966753441136
            },
            {
              "feature_name": "DistanceKilometers",
              "importance": 84.4982943868267
            },
            {
              "feature_name": "DistanceMiles",
              "importance": 103.90011847132116
            },
            {
              "feature_name": "FlightTimeHour",
              "importance": 3.7119156097309345
            },
            {
              "feature_name": "FlightTimeMin",
              "importance": 38.700587425831365
            }
            ],
            "is_training": true
          }
          ...

最后,Kibana 在结果中提供了散点矩阵。它与您在作业向导中看到的矩阵具有相同的功能。其目的也是帮助您可视化和探索数据中数值字段与因变量之间的关系。

评估回归结果

编辑

虽然您可以查看单个结果并将预测值(ml.FlightDelayMin_prediction)与实际值(FlightDelayMins)进行比较,但通常需要整体评估回归模型的成功程度。

Kibana 提供训练误差指标,表示模型在训练数据集上的表现。它还提供泛化误差指标,表示模型在测试数据上的表现。

Evaluating regression analysis results in Kibana

均方误差 (MSE) 为零表示模型以完美的准确度预测了因变量。这是理想情况,但通常无法实现。同样,R 平方值为 1 表示因变量的所有方差都可以由特征变量解释。通常,您会比较多个回归模型的 MSE 和 R 平方值,以找到最适合数据的平衡或拟合。

有关解释评估指标的更多信息,请参阅6. 评估结果

您也可以使用数据帧分析评估 API生成这些指标。

API 示例
POST _ml/data_frame/_evaluate
{
 "index": "model-flight-delays-regression",
  "query": {
      "bool": {
        "filter": [{ "term":  { "ml.is_training": true } }]  
      }
    },
 "evaluation": {
   "regression": {
     "actual_field": "FlightDelayMin",   
     "predicted_field": "ml.FlightDelayMin_prediction", 
     "metrics": {
       "r_squared": {},
       "mse": {},
       "msle": {},
       "huber": {}
     }
   }
 }
}

通过仅评估训练数据来计算训练误差。

包含实际(基本事实)值的字段。

包含预测值的字段。

API 返回如下响应

{
  "regression" : {
    "huber" : {
      "value" : 30.216037330465102
    },
    "mse" : {
      "value" : 2847.2211476422967
    },
    "msle" : {
      "value" : "NaN"
    },
    "r_squared" : {
      "value" : 0.6956530017255125
    }
  }
}

接下来,我们计算泛化误差。

POST _ml/data_frame/_evaluate
{
 "index": "model-flight-delays-regression",
  "query": {
      "bool": {
        "filter": [{ "term":  { "ml.is_training": false } }] 
      }
    },
 "evaluation": {
   "regression": {
     "actual_field": "FlightDelayMin",
     "predicted_field": "ml.FlightDelayMin_prediction",
     "metrics": {
       "r_squared": {},
       "mse": {},
       "msle": {},
       "huber": {}
     }
   }
 }
}

仅评估不属于训练数据的文件。

当您训练了一个令人满意的模型后,您可以部署它以对新数据进行预测。

如果您不想保留数据帧分析作业,可以将其删除。例如,使用 Kibana 或删除数据帧分析作业 API。当您在 Kibana 中删除数据帧分析作业时,可以选择同时删除目标索引和数据视图。

进一步阅读

编辑