还在用Github管理机器学习专案?你早该了解这些更专业的新工具 _模型

大资料文摘出品
编译:钱天培、胡笳
“太复杂了!机器学习(ML)专案实在太复杂了!”
听到这种抱怨,熟悉软件开发的小伙伴们往往是嗤之以鼻的。
机器学习,不过是和资料和软件打交道。那就应该是是执行程式码、迭代演算法的简单问题呀?一段时间后,我们就能拥有一个完美的训练有素的ML模型。
有什么复杂的?
然而,当真正着手起机器学习专案,你就会发现:事情可没有那么简单!
在专案进行了一段时间后,你的训练资料或许已经被更改或删除,而你对训练指令码的理解可能也已经十分模糊。
回过头看你训练好的模型,你可能也记不得每一个模型是怎么训练出来的了;再或者,你想要检视先前训练好的模型,却发现模型早已被覆盖。
更可怕的是团队协作,你想要把你的工作分享给你的同事们,他们却怎么也无法复现你的结果,更别提参与协作了。
别慌!今天,文摘菌就来带大家系统地学习一下,如何正确地管理机器学习(ML)专案。
正如一般的软件开发专案一样,你需要更好地管理程式码版本和专案资产。在软件开发专案中,人们可能需要重新审视专案先前的状态。在机器学习专案中,我们该如何实现类似的审查呢?与Pull Request相对应的又是什么呢?
就我个人而言,我才刚刚开始接触机器学习工具。在学习过程中,我观看了一些教程视讯。老师们提到的一些问题会让我想起我在软件工程职业生涯早期碰到的难题。例如,在1993到1994年,我是一个开发电子邮件使用者代理的团队首席工程师。我们没有任何源代码管理(SCM)系统。每天我都会咨询其他团队成员,看看他们那天做了哪些改变,也就是在他们的源树和主源树之间执行一个diff操作,然后手动更改程式码。稍后,团队成员从主源树手动更新他们的源树。
在我们发现早期的SCM系统(CVS)之前,这真是一团糟。SCM工具使专案执行得更加顺利。
当我了解到机器学习和资料科学专案中使用的工具时,我发现机器学习过程就如上边所说的那样。即使在今天,机器学习研究人员有时会将实验(资料,程式码等)储存在并行目录结构中,以便于进行diff审查,就像我在1993年所做的那样。
那么,理想中的机器学习专案管理应该是怎么样的呢?
ML专案管理原则
让我们从一些简要的ML专案管理原则说起。
在任何ML专案中,程序员们都会进行许多实验,为目标场景开发最佳的训练模型。实验一般包含:
▪程式码和配置:实验中使用的软件,以及配置引数
▪资料集:任何输入资料的使用——这可以是千兆级别大小的资料,比如语音识别、影象识别专案中所用到的资料
▪输出:训练后的ML模型和实验的任何其他输出
机器学习专案本质也就是软件执行。但是,与同事共享档案或复制结果,并及时回顾以评估专案通常十分困难。我们需要更全面的管理工具。
解决方案需要涵盖以下几点(从Patrick Ball的题为《原则性资料处理》的演讲中摘录):
▪透明性:方便检查ML专案的方方面面
o使用什么程式码、配置和资料档案
o工程专案采用什么工序,工序的次序是什么
▪可稽核性:方便检查pipeline的中间结果
▪可复现性:在开发的任何阶段精确地重新执行专案的能力,以及同事精确地重新执行专案的能力
o记录处理步骤,以便任何人都可以自动重新执行这些步骤
o在专案进行过程中记录专案的状态。“状态”表示程式码、配置和资料集
o能够在专案历史的任何时候重新建立可用的精确资料集
▪可扩充套件性:支援多个同事同时处理一个专案的能力,以及同时处理多个专案的能力

为什么不在机器学习专案中使用常规的软件工程工具?
诚然,在常规软件工程专案中使用的许多工具可能对机器学习研究人员有用。
在常规的源代码管理系统(如Git)中可以轻松地管理程式码和实验配置,并且可以使用pull request之类的技术来管理对这些档案的更新。CI/CD(Jenkins等)系统甚至可以用于自动化专案执行。
但是,ML专案另有不同之处,使得普通的软件开发工具无法满足所有的需求。下面是几个重要的不同点:
▪度量标准驱动(metrics-driven)的开发与特性驱动(feature-driven)的开发:在常规软件工程中,“是否释出”这一决策基于团队是否达完成了一些特征。相比之下,机器学习研究人员研究的是一种完全不同的测量方法——生成的机器学习模型的预测值。研究人员将迭代地生成几十个(或更多)模型,测量每个模型的准确性。由于目标是找到最精确的模型,因此专案由每个实验中实现的度量指标来指导。
▪机器学习模型需要大量的资源来训练:一个常规的软件专案将档案组织在一起编译一个软件产品,而机器学习专案则训练一个描述AI演算法的“模型”。在大多数情况下,编译一个软件产品只需要几分钟,非常快速,因此许多团队遵循持续整合(continuous integration)的策略。训练一个机器学习模型则需要很长时间。除非必要,最好避免持续整合。
▪庞大的资料集和训练好的模型:机器学习开发阶段几乎总是需要庞大的资料集,此外,训练过的模型也可能是巨大的。普通的源代码管理工具(Git等)不能很好地处理大型档案,而且Git- lfs之类的附加元件也不适合ML专案。
▪工作流(pipelines):机器学习专案是一系列步骤——如下载资料、准备资料、将资料分离到培训/验证集、培训模型和验证模型。许多人使用pipelines这个词来描述整个过程,意思是用每个步骤的离散命令来构造机器学习专案,而不是把所有东西都塞进一个程式中。
▪专用硬件:软件开发商可以将其软件基础设施托管在任何型别的服务器装置上。如果他们想要一个云部署,他们可以从他们喜欢的云端计算提供商那里租用VPS。然而,机器学习研究人员有巨大的计算需求。高效能GPU不仅可以加速视讯编辑,还可以让ML演算法加速“飞”起来,大大缩短了训练ML模型所需的时间。
现在,我们已经有了一个机器学习专案开发的原则列表,并了解了ML专案和普通软件开发专案的不同之处。
接下来,让我们看看有哪些开源软件可以帮助我们实现这些原则。
我们将特别讨论两个工具,MLFlow和DVC。当然,还有很多其他软件可以取得类似的效果。

机器学习专案中的资料与模型储存
我们的讨论可以归结为:
总的来说,我们需要一个资料跟踪系统来透明地审计、或者复现结果。我们也需要一个资料共享系统来将专案团队扩充套件到多个同事。
就如我们先前讨论的一样,使用Git或其他SCM(源代码管理系统)来储存机器学习专案中使用的资料档案是不切实际的。
一些库提供了API来简化远端储存上的档案处理,并管理向远端储存上传或获取档案。虽然这有利于远端资料集的共享访问,但却对我们面对的问题没有帮助。
首先,它是嵌入式配置的一种形式,因为档名被嵌入到软件中。在源代码中嵌入配置设定的任何程式在其他情况下都更难以被重新使用。其次,它没有将指令码版本和其使用的资料档案关联起来。
下面,然后我们看一下MLFlow的示例程式码:
mlflow.pytorch.load_model("runs://run-relative/path/to/model")
这支援多种档案访问“方案”,包括S3这样的云端储存系统。这里的示例从“run”区域载入一个档案,在本例中是一个经过训练的模型。每次执行一段程式码时,MLFlow都会生成一个“run”。你需要配置一个储存“run”资料的位置,并且显然会为每个用于索引到资料储存区域的执行生成一个“run ID”。
这种方式有效地将资料与对应SCM源代码管理库中的程式码和配置档案的commit提交版本关联起来。此外,MLFLow API有多种实现语言,并不局限于 Python语言。
DVC采用的则是另一种方式。对比上面将档案API整合到ML指令码中,你的指令码可以简单地使用普通档案系统的API实现输入和输出档案。例如:
model=torch.load(‘path/to/model.pkl’)
通过上述程式码,路径名称将通过这条命令传入。你无需特别修改程式码,因为DVC可以通过外部传递训练程式码或验证模型程式码需要的值。
DVC让这一切变得透明——资料档案版本与程式码的Git版本是相匹配的。
通过下述命令,你可将档案或资料夹加入DVC的版本管理:
$ dvc add path/to/model.pkl
资料储存在你的工作目录中。浏览各项执行的结果也很简单,只需要浏览你的Git历史即可。检视特定结果就像git checkout一样简单,DVC将被呼叫,并确保将正确的资料档案连线到workspace。
一个”DVC档案”将被建立,用于追踪每个档案及目录,并将被新增到workspace中。这样做有两个目的,一是可以追踪资料和模型档案,另一个则是记录工作流程中的命令。我们将在下一节中介绍这部分。
这些DVC档案记录档案和目录的MD5总和校验码(MD5 checksum)。他们被提交到git workspace上,因此DVC档案记录了每次git提交的每个档案的总和校验码。DVC使用了“DVC快取目录”来储存每个档案的多个例项。档案例项通过总和校验码进行索引,并使用reflinks或symlinks连结到workspace。当DVC响应git checkout命令时,它能够根据DVC档案中的总和校验码快速地重排连结档案。
DVC支援远端快取目录,用于共享档案和模型。
$ dvc remote add remote1 ssh://[email protected]/path/to/dir$ dvc push$ dvc pull
DVC remote是一个储存池,可以进行资料共享。它支援许多储存服务,包括S3、HTTP和FTP等。建立一个DVC remote非常简单。dvc push和dvc pull命令高度模拟了git push 和git pull命令。dvc push用于将资料传送到远端DVC的快取中,dvc pull用于从远端DVC快取中拉取资料。

机器学习专案中的工作流描述
接下来,我们将讨论如何更好地描述机器学习专案的工作流。我们应该一股脑将所有东西堆成一个程式吗?还是应该使用多种工具?
为了尽可能地创造灵活性,我们可以将工作流通过pipeline或有向无环图(DAG),并采用命令列引数作为配置选项的方式来实现。这有点类似Unix哲学中的小而精巧的工具——小巧但可以很好地协同工作。其行为可由命令列选项或环境变数指定,并且可以根据需要任意搭配使用。
相比之下,很多ML框架采用不同的方式。他们编写单独的程式来驱动特定专案的工作流。程式第一步先将资料拆分为训练集和验证集,然后训练模型并验证模型。这种整套的单独程式可带来重用程式码的机会有限。
将ML专案构建pipeline可带来如下好处
▪管理复杂性:将这些步骤作为单独命令实现可以提高透明度,并帮助你更加集中精力。
▪优化执行:可以跳过那些没有修改且不需要返回值的步骤。
▪可重用性:在多个专案中可重用相同的工具。
▪可扩充套件性:不同的工具可由不同的团队成员独立开发。
在MLFlow中,你需要编写一个“驱动程式”。这个程式包含了所需的执行逻辑,例如处理及生成机器学习模型。在程式背后,MLFlow API传送请求给MLFlow 服务器,通过该服务器生成指定的命令。
下面这个多步骤工作流的MLFlow例子清晰的展示了这一切。
...load_raw_data_run = _get_or_run("load_raw_data", {}, git_commit)ratings_csv_uri = os.path.join(load_raw_data_run.info.artifact_uri, "ratings-csv-dir")etl_data_run = _get_or_run("etl_data", {"ratings_csv": ratings_csv_uri, "max_row_limit": max_row_limit}, git_commit)…als_run = _get_or_run("als", {"ratings_data": ratings_parquet_uri, "max_iter": str(als_max_iter)}, git_commit)…_get_or_run("train_keras", keras_params, git_commit, use_cache=False)...
_get_or_run函式是mlflow.run的一个wrapper。每个呼叫函式中的第一个引数为在MLproject档案中定义的entrypoint。每个entrypoint包含环境变数,要执行的命令,以及传递给该命令的引数。例如:
etl_data: parameters: ratings_csv: path max_row_limit: {type: int, default: 100000} command: "python etl_data.py --ratings-csv {ratings_csv} --max-row-limit {max_row_limit}"
乍一看感觉非常不错。但是这里有几个问题值得思考:
▪如果你的工作流是比直线流程更复杂的情况怎么办?你可以将传给mlflow.run的同步引数设为false,然后等待SubmittedRun物件标记任务已完成。也就是说,可以在MLFlow API上构建流程管道系统。
▪为什么需要服务器?为什么不直接通过命令列执行命令?增加服务器及其配置使得MLFlow专案的设定更加复杂。
▪如何避免执行那些不需要的任务?在许多ML专案中,训练模型通常需要数天时间。资源应该只有在需要时才应该被使用,例如更换资料,修改引数或演算法。
DVC可以使用常规命令列工具,并且既不需要设定服务器也不需要编写驱动程式。DVC支援使用前面提到的,通过一组DVC档案将工作流定义为有向无环图(DAG)。
我们之前提到了,DVC档案会与新增到workspace中的档案相关联。DVC档案同时还描述了要执行的命令:
$ dvc run -d matrix-train.p -d train_model.py \ -o model.p \ python train_model.py matrix-train.p 20180226 model.p$ dvc run -d parsingxml.R -d Posts.xml \ -o Posts.csv \ R parsingxml.R Posts.xml Posts.csv
dvc run命令定义了一个DVC档案,其中包含了需要执行的命令。-d引数记录了对档案的依赖性,DVC将根据校验总和码来检测档案的更改。-o引数表示命令输出设定。一个命令的输出同样可以用于另一个命令的输入。通过检视依赖关系和输出,DVC可以计算出执行命令的顺序。
AI输出(包含训练模型)将被自动的记录在DVC的快取中,workspace中的其他资料档案也如此。
因为它计算校验和,DVC可以检测到更改的档案。当使用者请求DVC重新执行管道时,它只执行有变化的那部分。输入档案没有变化的情况,DVC可以节省大量模型训练任务所需要的时间。
所有的执行都使用常规命令列,不需要设定服务器。如果你希望在云端计算环境,或在附加GPU的服务器上执行,只需要将程式码和资料部署到该服务器上,并通过命令列执行DVC命令即可。
总结
我们在提高机器学习实践原则的探索上已经走了很长一段路。如我们所知,机器学习领域需要更好的管理工具,以便机器学习团队能够更有效、更可靠地工作。
结果可复现意味着他人可以评估你已完成的工作,或者协作进行更深层的开发。可重复性具有很多先决条件,包括能够检查系统的每个部分,以及能够精确地重新执行软件及输入资料。
机器学习专案中,一些GUI工具有非常漂亮的使用者界面,例如Jupyter Notebook。这些工具在机器学习的工作中占有一席之地。但是,GUI工具不太适合本文讨论的原则。命令列工具非常适合处理在后台执行的任务,并且可以轻松地满足我们上述的所有原则。而一般的GUI则会妨碍这些原则。
正如本文中描述的一样,我们可以从常规软件工程中借用很多工具和实践方式。但是,机器学习专案的特殊性决定了我们需要用到更适合其目标的工具。这些有价值的工具包括:MLFlow,DVC,ModelDb,Git-LFS等等。
相关报道:
https://dev.to/robogeek/principled-machine-learning-4eho