机器学习下的持续交付( 四 )

在我们的示例中 , 鉴于我们的消费应用程序也是用Pyhton编写的 , 我们已经决定使用更简便的方法去嵌入这个模型 。 我们的模型被以一种序列化对象(pickle文件)的方式导入 , 由DVC进行推送到储存 。 当构建我们的应用程序的时候 , 我们将它拉下来并嵌入到同一个Docker容器之中 。 从那时起 , 这个Docker镜像成为了我们获得版本和部署到生产环境的应用程序+模型的一个组件 。
除了使用pickle序列化模型对象之外 , 这里也有其他的工具选择可以来实现这个嵌入模型的方式 。 MLeap提供了一种常用的序列格式来导出/导入 Spark , scikit-learn和Tensorflow 模型 。 也有和语言无关的交换格式来共享模型 , 比如说PMML , PFA和ONNX 。 其中一些序列化选项也是可以应用到实现“模型作为数据”的这一模式上的 。
另一种方法是使用比如像H2O的工具来导出在JAR的java库里的模型作为POJO , 这样你就可以在应用程序中增加它们作为依赖 。 这个方法的好处在于你能使用数据科学家熟悉的语言训练模型 , 比如说Python或者R , 导出编译好可以在不同目标环境(JVM)中运行的二进制模型 , 这样做可以使推断更快耗时更少 。
为了实现这个“把模型作为服务”的模式 , 很多云服务提供者都有工具和SDK来包装你的模型然后部署至他们的MLaaS(把机器学习作为一种服务) , 比如说 Azure Machine Learning , AWS Sagemaker或者Google AI 平台 。 其他的选项是使用工具像kubeflow , 这是一个被设计用来部署ML工作流到Kubernetes上的项目 , 即使它尝试去解决更多的不止模型服务这部分的问题 。
MLflow Models 正在试图提供一种基础的方法来根据不同的喜好打包模型 , 以供不同的下游工具使用 , 一些是“把模型作为服务”的模式 , 一些是“让模型可嵌入”的模式 。 我们只想说 , 现今领域开发的各种工具和供应商都在努力工作简化这项任务 。 但是这也意味着那里还没有明确的基准(开放或者私有)可以被认为一定是赢家 , 因此你需要根据你的需求来改进正确的选择 。
值得注意的是 , 不论你决定使用哪种模式 , 模型与其消费者总是存在着隐式的关联 。 模型将会经常性的期望输入数据是一种确定的形状 , 如果数据科学家改变了关联关系以要求新的输入或者添加新的特征 , 你就会遇到集成的问题并打断使用它的应用程序 。 这又将会把我们引入到测试的话题上 。
集成测试这里有一些不同类型的测试————自动化的或者是手动的————这些都能在ML工作流中提供 。 第一点是去验证模型和消费应用程序的关联 。 我们能够使用相似的方法来测试服务或者应用程序的集成性 , 在模型改变时使用关联测试来验证预期的接口是适合消费应用程序的 。 这样可以用来阻止在生产环境的集成问题 , 同时可以给出应用程序需要改变去使用新模型的早期反馈 。
另一种测试类型是当你的模型以不同的格式生产出的时候 , 确保你的导出模型依然产生同样的结果 。 这样可以通过运行原来的和生产的模型输入同样的验证数据集 , 然后比较两者的结果应该是相同的来做到 。
因为ML模型的性能是不确定的 , 数据科学家经常收集和监控许多许多指标来确定一个模型的性能 , 比如错误率、准确率、AUC、ROC、混淆矩阵、精度、回调等等 。 这些指标在参数和超参数优化期间也是相当有用的 。 我们可以使用这些指标来引入Threshold Tests或者ratcheting 到我们的pipeline中 , 这样可以确认新模型不会在已知性能指标基础上降低 。
在我们的样例应用程序中 , 评估指标是Favorita指定的错误率所确定的 。 我们写来一个简单的如果错误率超过80%就会停止的PyUnit threshold test , 并且可以在发布新模型版本之前将此测试添加到部署pipeline中 , 从而防止错误模型进入生产阶段 。
我们也考虑过其他类型的测试 , 但是其中很多的难以全自动化 。 因此 , 我们认为添加一些手动阶段到部署的pipeline中是很重要的 , 这是为了显示关于模型的信息进而使得人们决定他们是否进行到部署的pipeline这一步骤 。 这样允许你为机器学习治理的流程建模并引入模型权重检查 , 模型的公平性以及收集可被人类解释的信息用来帮助人们理解模型的行为 。
实验跟踪为了支持这种治理流程 , 获取并展示信息是非常重要的 , 这使得人们能够决定是否或者哪一个模型投入到生产环境中 。 由于数据科学的流程几乎全部以研究为中心 , 所以在通常的情况下同时会进行多次实验 , 然而大部分的实验结果最终不会进入到生产环境中 。