31、机器学习模型调优、部署与实时应用全解析

机器学习模型调优、部署与实时应用全解析

1. 模型调优

在机器学习中,为了找到最优的模型参数,我们可以创建一个调优配置文件,尝试不同的学习率和不同大小的网络。以下是一个示例配置文件:

trainingInput:
  scaleTier: STANDARD_1
  hyperparameters:
    goal: MINIMIZE
    maxTrials: 15
    maxParallelTrials: 3
    params:
    - parameterName: learning_rate
      type: DOUBLE
      minValue: 0.01
      maxValue: 0.25
      scaleType: UNIT_LINEAR_SCALE
    - parameterName: hidden_units
      type: CATEGORICAL
      categoricalValues: ["64,16,4", "64,64,16,4", "64,64,64,16,4", 
                          "64,64,64,64,16,4"]

将此作为超参数调优作业在云机器学习中运行后,我们发现调整学习率并没有带来显著的好处。使用学习率为 0.06 的五层网络时,均方根误差(RMSE)会更低,但降低幅度不大。例如:

- finalMetric:
     objectiveValue: 0.186218
     trainingStep: '6407'
   hyperparameters:
     hidden_units: 64,64,64,16,4
     learning_rate: '0.060623111774000711'
   trialId: '12'

这些就是最终的参数,我们可以使用这些参数在完整数据集上重新训练网络。当以批量大小为 100 和学习率为 0.06 重新训练五层模型时,得到的模型评估 RMSE 为 0.1856。

2. 模型部署

现在我们有了训练好的模型,接下来可以使用它进行预测。由于我们使用了 Experiment 类并指定了带有服务输入函数的导出策略,该模型具备接受输入和进行预测所需的所有组件。我们只需要使用 REST 端点部署模型即可。

部署模型类似于部署 Google App Engine 应用程序。我们需要为模型命名并指定版本,版本在进行 A - B 测试时非常有用,这样可以在将模型从测试环境推广到生产环境之前,将当前模型与之前的版本并行测试。

具体操作步骤如下:
1. 在导出目录中,云机器学习引擎会在带有时间戳的文件夹中创建一个模型。我们选择云机器学习引擎输出文件夹中最新的模型:

MODEL_LOCATION=\
  $(gsutil ls gs://${BUCKET}/flights/chapter9/output/export/Servo/
        | tail -1)
  1. 由于这是第一次部署,我们创建一个名为 flights 的模型和该模型的版本 v1
gcloud ml-engine models create flights --regions us-central1
gcloud ml-engine versions create v1 --model flights \
                                   --origin ${MODEL_LOCATION}
3. 使用模型进行预测

模型版本创建完成后,我们可以使用任何语言发送 REST 请求进行预测。下面以 Python 为例:
1. 进行身份验证并获取访问云机器学习引擎部署服务的凭据:

#!/usr/bin/env python
from googleapiclient import discovery
from oauth2client.client import GoogleCredentials
import json
credentials = GoogleCredentials.get_application_default()
  1. 使用 Google APIs 发现服务形成客户端:
api = discovery.build('ml', 'v1', credentials=credentials,
      discoveryServiceUrl=
      'https://storage.googleapis.com/cloud-ml/discovery/ml_v1_discovery.json')
PROJECT = 'cloud-training-demos'
parent = 'projects/%s/models/%s/versions/%s' % (PROJECT, 'flights', 'v1')
  1. 提供输入变量字典作为请求数据:
request_data = {'instances':
  [
      {
        'dep_delay': 16.0,
        'taxiout': 13.0,
        'distance': 160.0,
        'avg_dep_delay': 13.34,
        'avg_arr_delay': 67.0,
        'carrier': 'AS',
        'dep_lat': 61.17,
        'dep_lon': -150.00,
        'arr_lat': 60.49,
        'arr_lon': -145.48,
        'origin': 'ANC',
        'dest': 'CDV'
      }
  ]
}
  1. 发送请求并获取响应:
response = api.projects().predict(body=request_data, name=parent).execute()
print "response={0}".format(response)

上述请求的响应结果如下:

{u'predictions': [{u'probabilities': [0.8313459157943726, 0.16865408420562744],
u'logits': [-1.59519624710083], u'classes': 0, u'logistic':
[0.16865406930446625]}]}

从这个 JSON 中,我们可以得出该航班晚点的概率为 0.83。可以看出,在云机器学习引擎中使训练好的模型投入使用非常简单。

4. 模型解释

为什么模型认为航班晚点的概率为 0.83 呢?机器学习中的一个活跃研究领域是用人类可理解的形式解释特定模型预测的原因。一种简单的方法是用平均值(从训练数据集中计算得出)替换关键预测变量,观察这种变化的影响。

我们可以发送多个请求变体来解释模型的预测结果:

request_data = {'instances':
  [
      {
        'dep_delay': dep_delay,
        'taxiout': taxiout,
        'distance': 160.0,
        'avg_dep_delay': 13.34,
        'avg_arr_delay': avg_arr_delay,
        'carrier': 'AS',
        'dep_lat': 61.17,
        'dep_lon': -150.00,
        'arr_lat': 60.49,
        'arr_lon': -145.48,
        'origin': 'ANC',
        'dest': 'CDV'
      }
      for dep_delay, taxiout, avg_arr_delay in
        [[16.0, 13.0, 67.0],
         [13.3, 13.0, 67.0], # if dep_delay was the airport mean
         [16.0, 16.0, 67.0], # if taxiout was the global mean
         [16.0, 13.0, 4] # if avg_arr_delay was the global mean
        ]
  ]
}

我们传递了四个实例进行预测。第一个实例是实际观测值,接下来的三个是变体。第二个实例使用该机场的平均出发延误,第三个实例将滑行时间改为训练数据集中所有航班的平均滑行时间,第四个实例将到达延误改为训练数据集中的平均到达延误。

预测服务的响应结果可以解析为:

probs = [pred[u'probabilities'][0] \
              for pred in response[u'predictions']]

得到的概率数组(四舍五入后)为:

[0.17, 0.27, 0.07, 0.51]

从这些结果可以推断,平均到达延误是影响最大的特征。因为 CDV 的到达延误为 67 分钟,而不是 4 分钟,航班准点到达的可能性从 0.51 降至 0.17。出发延误 16 分钟(平均为 13 分钟)也对整体延误可能性有贡献,但影响仅约为到达延误影响的 30%(0.10 / 0.34)。另一方面,较短的滑行时间有所帮助,如果滑行时间为 16.0 分钟,准点到达的可能性会更低。

虽然解释不是非常详细,但为模型预测提供一个简单的原因非常有帮助,例如:“您有 83% 的可能性晚点到达。这主要是因为 CVG 当前的平均到达延误为 67 分钟。此外,您的航班晚了 16 分钟离开登机口,通常为 13 分钟。”

5. 实时机器学习

在前面的步骤中,我们已经完成了模型的训练、调优、部署和预测。接下来,我们将构建一个实时的 Apache Beam 管道,为每个航班添加预测的准点性能并将其写入数据库。

在之前的工作中,我们使用历史航班数据训练了一个机器学习模型,用于预测航班是否晚点。模型的输入变量包括航班的出发延误、距离、滑行时间等,还包括特定出发机场的历史出发延误和航班目的地的当前到达延误这两个时间聚合值。

在实时场景中,我们可以在航班起飞时计算一次准点到达概率,然后根据用户需求查询航班信息,这样效率更高。而且,由于我们的模型是基于起飞时的航班数据训练的,所以只在起飞时进行预测。

使用 Apache Beam 计算时间平均值的优势在于,其编程模型对于历史数据和实时数据是相同的,因此我们可以重用大部分训练管道代码,只需要修改输入(从 Pub/Sub 读取)和输出(添加预测概率而不是已知的准点性能)。

6. 调用预测服务

我们之前使用云机器学习引擎将训练好的 TensorFlow 模型部署为 Web 服务,并通过发送正确格式的 JSON 请求进行调用。例如:

{"instances":[{
"dep_delay":16.0,
"taxiout":13.0,
"distance":160.0,
"avg_dep_delay":13.34,
"avg_arr_delay":67.0,
"dep_lat":61.17,
"dep_lon":-150.0,
"arr_lat":60.49,
"arr_lon":-145.48,
"carrier":"AS",
"origin":"ANC",
"dest":"CDV"
}]}

响应结果如下:

{"predictions": [{
"probabilities": [0.8313459157943726, 0.16865408420562744],
"logits": [-1.59519624710083],
"classes": 0,
"logistic": [0.16865406930446625]
}]}

返回的两个概率中,第一个对应航班晚点(标签 = 0),第二个对应航班准点(标签 = 1)。在这个例子中,航班准点到达的概率仅为 16.86%。

7. Java 类处理请求和响应

为了在 Apache Beam Java 管道中调用 REST API,我们需要在 Java 程序中处理 JSON 消息。可以将 JSON 请求和响应表示为 Java 类,然后使用 Jackson 或 GSON 等库进行 JSON 序列化和反序列化。

以下是根据上述 JSON 示例定义的 Java 类:

class Request {
    List<Instance> instances = new ArrayList<>();
}

class Instance {
    double dep_delay, taxiout, distance, avg_dep_delay, avg_arr_delay,
           dep_lat, dep_lon, arr_lat, arr_lon;
    String carrier, origin, dest;
 }   

class Response {
    List<Prediction> predictions = new ArrayList<>();
}

class Prediction {
    List<Double> probabilities = new ArrayList<>();
    List<Double> logits        = new ArrayList<>();
    int          classes;
    List<Double> logistic      = new ArrayList<>();
}

创建 JSON 请求时,我们可以创建 Request 对象并使用 GSON 库生成 JSON 表示:

Request req = …
Gson gson = new GsonBuilder().create();
String json = gson.toJson(req, Request.class);

同样,我们可以使用相同的库将 JSON 流反序列化为 Response 对象:

String response = … // invoke web service
Response response = gson.fromJson(response, Response.class);

为了避免代码污染,我们可以添加从 Flight 对象创建 Request 的方法和从 Response 对象提取感兴趣概率的方法。例如:

Instance(Flight f) {
    this.dep_delay = f.getFieldAsFloat(Flight.INPUTCOLS.DEP_DELAY);
    // etc.
    this.avg_dep_delay = f.avgDepartureDelay;
    this.avg_arr_delay = f.avgDepartureDelay;
    // etc.
    this.dest = f.getField(Flight.INPUTCOLS.DEST);
}

public double[] getOntimeProbability() {
    double[] result = new double[predictions.size()];
    for (int i = 0; i < result.length; ++i) {
        Prediction pred = predictions.get(i);
        result[i] = pred.probabilities.get(1);
    }
    return result;
}

通过以上步骤,我们完成了从模型调优、部署到实时应用的整个流程,实现了一个完整的机器学习解决方案。在实际应用中,我们可以根据具体需求对模型和管道进行进一步的优化和扩展。

机器学习模型调优、部署与实时应用全解析

8. 实时 Beam 管道构建流程

为了构建实时的 Apache Beam 管道,我们可以参考以下流程图:

graph LR
    A[从 Pub/Sub 读取数据] --> B[添加预测概率]
    B --> C[写入数据库]

具体步骤如下:
1. 从 Pub/Sub 读取数据 :修改之前训练管道的输入部分,使其从 Pub/Sub 读取实时的航班数据。
2. 添加预测概率 :调用之前部署的 TensorFlow 模型的预测服务,为每个航班数据添加预测的准点性能。
3. 写入数据库 :将添加了预测概率的航班数据写入数据库,以便用户查询。

9. 实时管道代码示例

以下是一个简化的实时 Beam 管道 Java 代码示例:

import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.io.gcp.pubsub.PubsubIO;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.transforms.ParDo;
import org.apache.beam.sdk.values.PCollection;

public class RealTimePipeline {
    public static void main(String[] args) {
        Pipeline pipeline = Pipeline.create();

        // 从 Pub/Sub 读取数据
        PCollection<String> input = pipeline.apply(PubsubIO.readStrings().fromTopic("projects/your-project/topics/your-topic"));

        // 添加预测概率
        PCollection<String> output = input.apply(ParDo.of(new AddPredictionProbability()));

        // 写入数据库(示例中简单打印输出)
        output.apply(ParDo.of(new WriteToDatabase()));

        pipeline.run();
    }

    static class AddPredictionProbability extends DoFn<String, String> {
        @ProcessElement
        public void processElement(ProcessContext c) {
            String flightData = c.element();
            // 调用预测服务添加预测概率
            String flightDataWithProbability = addPrediction(flightData);
            c.output(flightDataWithProbability);
        }

        private String addPrediction(String flightData) {
            // 调用预测服务的代码
            return flightData + " with prediction probability";
        }
    }

    static class WriteToDatabase extends DoFn<String, Void> {
        @ProcessElement
        public void processElement(ProcessContext c) {
            String flightData = c.element();
            // 写入数据库的代码
            System.out.println("Writing to database: " + flightData);
        }
    }
}
10. 总结与优势回顾

通过上述步骤,我们实现了从模型调优、部署到实时应用的完整机器学习流程。以下是整个过程的优势总结:
| 步骤 | 优势 |
| ---- | ---- |
| 模型调优 | 通过超参数调优找到更优的模型参数,提高模型性能 |
| 模型部署 | 使用 REST 端点轻松部署模型,便于与其他系统集成 |
| 实时应用 | 利用 Apache Beam 构建实时管道,高效处理实时数据 |

11. 注意事项

在实际应用中,还需要注意以下几点:
1. 数据质量 :确保实时数据的质量,避免因数据错误导致预测结果不准确。
2. 性能优化 :对实时管道进行性能优化,如合理设置并行度、减少数据传输延迟等。
3. 安全与权限 :确保对云服务的访问具有适当的安全权限,保护数据安全。

12. 未来展望

随着机器学习和实时数据处理技术的不断发展,我们可以进一步扩展和优化这个解决方案。例如:
1. 模型更新 :定期使用新的历史数据更新模型,以适应数据分布的变化。
2. 多模型集成 :集成多个不同的机器学习模型,提高预测的准确性和可靠性。
3. 实时监控 :建立实时监控系统,及时发现和处理模型性能下降等问题。

通过不断地改进和创新,我们可以更好地利用机器学习技术解决实际问题,为用户提供更优质的服务。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值