当前位置: 首页 > 科技观察

构建生产机器学习系统的一些注意事项

时间:2023-03-22 12:35:46 科技观察

随着数据和计算能力的提升,“机器学习”(ML)和“深度学习”这两个术语多年来一直备受争议。虽然跳上ML潮流可能看起来很酷,但公司的第一步是评估业务是否真的可以从中受益——这本身就是一个立场。既然您的公司已经决定ML是下一步的必要步骤,那么作为ML工程师,现在是时候考虑为生产系统构建ML流程的真正内容了。希望本文能帮助您了解这些问题。在本文中,只要提到“创业”一词,除非特别提到软件“服务”公司,否则都是指软件“产品”公司。软件产品公司专注于构建自己的软件产品,而软件服务公司(如代理或咨询公司)则为客户构建软件。虽然这篇文章是为早期软件产品初创公司的ML工程师编写的,但某些注意事项可能仍适用于其他阶段或公司类型。寻找合适的工具机器学习软件有多种选择,从PyTorch、TensorFlow和scikit-learn等开源工具到管理机器学习服务的平台,如GoogleAIPlatform、AmazonSageMaker和AzureMachineLearningPlatform。仅使用PyTorch和TensorFlow,有许多开源库(如HuggingFace的transformer)提供现成的模型作为起点。此外,每年都有不同领域的机器学习研究论文发表,其中部分论文提供开源代码。PapersWithCode:https://paperswithcode.com/是查找带有代码的论文的好资源。选择正确工具时要考虑的关键因素是:文档质量工具的开发状态(维护与停止或弃用、问题的严重性等)是否积极参与工具?您对该工具的熟悉程度?使用该工具的团队规模?与该工具相关的货币成本。我个人觉得,如果你是一个早期的创业公司,你不需要权衡和找出所有这些因素。你总是可以从一个强有力的候选人开始,然后从那里开始。此外,如果您认为收益大于成本,则可以从一开始就使用托管ML服务。何时开始机器学习与围绕机器学习的操作刚开始时,最好从一个简单的基线模型开始。从更简单的模型开始可以帮助您调试管道中的问题,并帮助您决定是否值得采用更耗时的解决方案。那么如何构建一个简单的基线模型呢?首先,“简单”是相对的。在某些情况下,简单实际上意味着一个简单的模型,例如对一些启发式方法进行硬编码。在其他情况下,模型本身可能很复杂,但易于应用。一些最广泛使用的数据集具有最先进的开源模型,并在研究论文或排行榜等地方列出,例如斯坦福问答数据集(SQuAD)。一种方法是查看一些顶级解决方案,看看是否可以找到相关研究论文附带的代码。在早期启动阶段,您可能没有时间立即构建ML管道。通常情况下,您需要专注于让投资者和客户容易看到的东西发挥作用。他们很少考虑调整过程。所以不要担心您的初始部署是完美的,只要有一个工作的产品——一个可见的最终产品。构建基本产品后,您可以更加担心ML的过程,因为通常需要更多的停机时间才能对ML过程进行小的增量改进。相反,如果您是一家机构,则出错的空间较小,因为您要将成品交付给不同的客户并尝试事先修复所有错误。在交付一个客户产品或一组产品后,您将继续执行下一个客户合同,并且通常没有足够的精力进行进一步的改进。不过,您还是要快点行动。为了更快地进步,最好有更精细的ML过程。因此,对于代理模型,从长远来看,也许花更多的时间在优化和自动化上可以节省时间。实验管理注意事项在ML中管理实验并非易事,当您运行尽可能多的实验时,您的项目工作区很容易变得混乱。但是,在启动阶段,您没有几个月的时间来做数百次实验。你只需要推动更好的东西并尽快更新。无论哪种方式,某种实验管理总比没有好。以下是管理ML实验时需要考虑的一些事项。模型版本在ToucanAI,我们使用GitHub来存储我们代码的版本。GitHub很棒,但它不适合大数据文件的版本控制。尽管存储库可以达到100GB,但GitHub建议将存储库的大小保持在1GB以下,并且单个文件不能超过100MB。您可以使用其他云存储选项,例如GoogleCloudStorage或AmazonS3。使用云提供商的命令行工具或WebUI,只需创建一个允许对其对象(文件或文件夹)进行版本控制的存储桶(文件夹)。但是,如果您希望将云存储中的文件与GitHub上的项目存储库同步,则需要额外的手动工作。因此,我们选择了最自然的集成,它结合了Git平台和其他云存储选项的最佳特性:数据版本控制(DVC),标记为“机器学习项目的开源版本控制系统”。DVC是一个命令行工具,其子命令与Git的子命令非常相似。Git平台和云存储搭建完成后,可以运行DVC的'add'和'push'命令设置版本,将文件或文件夹存储到云存储中。同时,通过DVC文件引用,可以在Git项目存储库中跟踪大数据文件。DVC的一个优点是只需要一些额外的类似Git的命令,这与现有的Git工作流没有太大区别。实验文档如果您正在进行超参数调整,很容易忽略在给定日期为模型运行的特定设置。您可能还想回顾您为准备或预处理上述模型所需的数据集所做的工作。你的JupyterNotebooks有描述性的文件名,但它仍然需要相当多的时间来处理首先发生的事情,或者如果你将预处理A或B应用于实验7。一个解决方案是在创建一个文件名时将Notebooks编号作为文件名的一部分新笔记本(我喜欢使用“01_”步骤),以后可以重新编号。为您的笔记本编号制定一个清晰的命名约定对于您的同事(以及未来的您)了解您如何进行实验非常有帮助。除了在实验中对Notebooks进行编号,我们还使用开源平台MLflow提供了一个web界面来查看实验超参数和测量结果。此外,在记录实验时,力求逻辑结构和简洁。利用文件夹结构和名称来组织您的笔记本和培训脚本。假设当读者查看您的笔记本时,他们会从头到尾阅读它,因此请删除您临时插入的任何“草稿”单元格。根据经验,将笔记本上的实验限制为一个模型和一个数据集,如果当前笔记本太长,则创建一个新笔记本。尽量让你的最终笔记本版本没有训练或推理代码,这些应该在单独的脚本中,可以从笔记本中调用。最后,在使用MLflow等软件生成实验笔记时,请尝试将运行实验的笔记本自动引用到生成的实验输出文件中。更好的测试框架测量结果并不总是与改进的真实样本推理性能相关。此外,在生产ML系统中,ML模型不会独立运行:例如,您可能将启发式、预处理和缓存作为管道的一部分。因此,当您尝试改进已有的ML模型时,您会意识到生成适合现实世界推理的样本需要花费大量时间。您需要深入研究更大的生产代码,以发现您尝试改进的模型实际被调用的位置。然后,您不想只检查模型本身的输入和输出,还要检查ML系统的整个管道。您的“更好”模型如何影响整个系统,是更好还是更坏?为了专注于模型改进,而不是提出推理样本或担心破坏生产管道中的某些东西,我们需要有一个自动化系统或端到端测试框架。在ToucanAI,由于我们的主要产品是AI销售代理,因此测试涵盖主要逻辑分支的样本对话就足够了,同时还提供了一种回归测试的形式。我们目前正在开发一个命令行界面(CLI)工具,它将在一系列示例会话中运行pytest断言。使用单个命令,可以测试所有对话,如果任何测试用例中断,我们可以手动更新测试或确定我们的“更好”模型实际上并不适合生产。简而言之,拥有一个适当的测试框架对于理解当前和实验模型在生产ML系统中的表现至关重要。有了适当的测试框架,您的模型改进管道应该会更有效地进行,从而使您能够运行比以前更多的实验。从快速发展的库中提取代码并将其写入使用经过修改的旧版本库的生产系统对于快速发展的工具来说很困难。您如何修改快速发展的库以满足您的需求并尽可能高效地应用其最新更新?我觉得没有正确答案,只有许多不同的路径。一种方法是将他们的代码与您的代码结合起来并使其工作。另一种方法是使用他们的代码并完全升级旧版本,但这通常需要更长的时间。简而言之,想想你有多少时间用于重构,以及你的优先事项是什么。在您自己的代码库和快速发展的工具变得更加稳定之后,您应该关注优先级并考虑完全重构。尝试整洁当您专注于获得结果时,通常很容易忽视整洁。考虑下一组要运行的实验及其超参数集。发生错误?没问题,更改输出文件夹上的时间戳并重新运行实验。但是,您最终得到的是由于不完整的实验而生成的额外文件或文件夹。之后,您滚动浏览MLflow中的一长串记录以查找已完成的实验,结果却让他们摸不着头脑。解决方案是自动删除您不想保存的任何试验。例如,最好在第一次训练迭代完成执行之前删除失败的运行。为了我们的同事和我们未来的自己,我们都应该尽最大努力保持实验室游泳池的整洁。关注点分离当您研究和试验各种ML项目以期改进您的模型时,您会遇到相互冲突的Python包要求。您最初可能会在两个开发人员之间共享一个云服务器,但这很快就会变得不方便,因为您的安装可能会覆盖您同事的运行时。进入Docker生态系统,这是一个用于管理项目环境和依赖项的轻量级容器化软件平台。通过为每个ML模型和应用程序服务使用单独的Docker容器,我们可以主动减少“它在我的机器上工作”问题的数量,并防止项目之间的依赖冲突。您的每个同事都可以在单个共享服务器上设置自己的Docker容器,而不是设置更多的开发服务器,如果这样更划算的话。此外,您可能想知道,为什么选择Docker而不是Conda,Conda还允许您使用不同的包版本创建不同的环境。我们选择Docker是因为它提供了更适合生产和处理云环境的工具。如果你想在远程机器上使用Conda,你必须先连接机器并处理文件传输。但是,只需在Docker中使用几个命令,您就可以更改本地文件并将它们反映在远程机器上的Docker容器中。此外,运行项目所需的一切都在Dockerfile或DockerCompose文件中指定。另一方面,对于Conda,如果不参考README,则不清楚是否需要额外的步骤。最后,借助DockerCompose的强大功能,如果ML项目需要运行其他服务,它们可以独立运行在其他Docker容器中,并根据DockerCompose文件设置相互通信。据我所知,在Conda中是无法实现跨环境通信的。准备扩展作为早期初创公司,您现在可能不需要扩展,但开始考虑可以扩展的技术是个好主意。Celery就是这样一种技术,它是一种异步任务队列系统,可以将任务分配给多个工作人员。目前,我们为每种类型的服务(服务器、客户端、嵌入等)配备了一个单独的worker,但如果有必要,为同一服务启动更多worker应该不需要太多工作。通过嵌入进行缓存会成为瓶颈吗?没问题,让我们启动另一个嵌入式Celeryworker,或者增加当前worker的“并发”计数,这样可以让多个子进程并行运行。在我们的ToucanAI配置中,Celeryworker在Docker容器内运行,因此也遵循关注点分离。除了允许您的生产系统扩展之外,Celery还非常适合长时间运行的任务,例如ML模型推理任务。服务器响应(代理的回答)可以立即返回给与ToucanAI代理交谈的最终用户,而不是让服务器响应挂起,而异步任务(例如缓存机制)可以在后台安静地运行。此外,我们使用Celerybeat来运行我们每天安排的分析工作任务。与同事和你未来的自己合作随着ML研究的不断发表,作为ML工程师,你如何让你的团队成员参与循环尝试使用模型或技术?没有任何魔法可以将他们获得的所有知识、经验和洞察力传递给您。但你能做的就是沟通。经常交流。尽可能多地沟通,尤其是在编写文档时。因为通常情况下,您正在做自己的项目,所以您现在正在做的事情可能与您的同事正在做的事情并不完全相关。但是,将来他们可能需要审查或扩展您已实施的内容。甚至可能几个月后你不得不对自己的项目进行更改,而忘记了其中的关键部分。文档,文档,文档。怎么强调都不为过。另一方面,有时文档是不够的。如果你不确定某件事,想要他们的诚实意见,并且你觉得谈话是一种更有效的沟通方式,请注意同事的心态,并寻求与他们讨论项目的方向。从一开始就尽可能清楚,对于防止误解、徒劳和后悔非常重要。成为机器学习工程师的内部斗争作为机器学习工程师,你必须学会??权衡你想要修复什么的想法和让流程变得更好以完成当前需求的想法。你必须学会??接受最直接的方式来完成工作。例如,我很愿意花时间改进3rd方训练/评估代码,但当时,我只需要走最短路径,看看我们的推理结果是否会有所改进。由于我有网络开发的背景,所以大部分时间我必须自己编写代码,但在ML工程中我必须学习如何应用其他人的代码。当你不断地使用不属于你自己的代码时——通常是学生和研究人员为此工作数月或数年——有时很难不觉得自己是个失败者,尤其是当你试图理解一些不属于你的东西时不能直接部署到生产系统中的代码的那个方面。归根结底,请记住,我们天生就是好奇的生物,想要了解比你需要的更多的东西是可以的。如果你想探索一些途径,那么对你的队友保持透明是关键。一个良好的工作环境不会责怪你想要了解更多,如果你有足够的时间到达那里。只要您有优先事项,就尽量少担心,多享受。结论为生产系统构建ML管道并非易事。尽管本文中提到了所有内容,但有时您可以做出的最佳决定就是做出一个决定。如果这不起作用,则转到下一条路径。不管怎样,我希望这篇文章能帮助我们更好地理解各种想法。