天天看点

DataScience Process Analysis数据科学工作流解析

数据科学工作流解析

假如您正在开始一个新的数据科学项目(可以是对一个数据集的简短分析,也可以是复杂的多年合作项目)。您应该如何组织你的工作流程呢?你把数据和代码放在哪里?你使用什么工具?为什么使用它们?一般来说,在首先进入数据工作之前,您应该考虑什么?在软件工程行业中,这些问题具有一些众所周知的答案。尽管每家软件公司都有其独特的特点和喜好,但大多数软件公司的核心流程都基于相同的既定原则,实践和工具。这些原则在教科书中有所描述,并在大学中教授。

数据科学是一个不太成熟的行业,各行业的具体事项是不同的。虽然你可以找到各种模板项目,文章,博客帖子,讨论或专业平台(开源[1,2,3,4,5,6,7,8,9,10],商业[11,12,13,14,15,16,17]和内部[18,19,20]),以帮助您组织工作流程的各个部分,还没有教科书提供普遍接受的答案。每个数据科学家最终都会发挥他们的个人偏好,主要是从经验和错误中学习。我也不例外。随着时间的推移,我逐渐了解了什么是典型的“数据科学项目”,应该如何构建,使用什么工具以及应该考虑什么。我想在这篇文章中分享我的愿景。

工作流

尽管数据科学项目的目标,规模和技术范围很广,但在某种抽象层次上,大多数项目可以实现为以下工作流程:

DataScience Process Analysis数据科学工作流解析

彩色框表示关键过程,而图标是相应的输入和输出。 根据项目的不同,重点可能集中在一个或另一个过程上。 其中一些可能相当复杂,而另一些则琐碎或缺失。 例如,科学数据分析项目通常缺少“部署”和“监控”组件。 现在让我们逐一考虑每个步骤。

源数据接入

无论您是在使用人类基因组数据还是使用iris.csv,您通常都会有一些“原始源数据”的概念。 它可以是* .csvfiles的目录,SQL Server中的表或HDFS集群。 数据可以是固定的,不断变化的,自动生成的或流式的。 它可以存储在本地或云端。 无论如何,您的第一步是定义对源数据的访问。 以下是一些示例:

•您的源数据是作为一组* .csv文件提供的。您遵循cookiecutter-data-science方法,在项目的根文件夹中创建一个data / raw子目录,并将所有文件放在那里。您可以创建docs / data.rst文件,在其中描述源数据的含义。 (注意:Cookiecutter-DataScience模板实际上建议 references/作为数据字典的位置,而我个人更喜欢docs。然而这并不重要。)

•您的源数据是作为一组* .csv文件提供的。您设置SQL服务器,创建名为raw的模式,并将所有CSV文件作为单独的表导入。您可以创建docs / data.rst文件,在其中描述源数据的含义以及SQL Server的位置和访问过程。

•您的源数据是基因组序列文件,患者记录,Excel文件和Word文档的混乱集合,后来可能以不可预测的方式增长。此外,您知道您需要查询多个外部网站以接收额外信息。您在云中创建SQL数据库服务器,并从那里的Excel文件导入大多数表。您在项目中创建数据/原始目录,将所有巨大的基因组序列文件放入dna子目录中。某些Excel文件太脏而无法导入数据库表,因此您将它们与Word文件一起存储在data / raw / unprocessed目录中。您可以使用DVC创建Amazon S3存储桶并将整个data/raw目录推送到那里。您创建一个用于查询外部网站的Python包。您可以创建docs / data.rst文件,在其中指定SQL服务器的位置,S3存储桶,外部网站,描述如何使用DVC从S3下载数据以及Python包来查询网站。您还可以根据您的理解描述所有Excel和Word文件的含义和内容,以及添加新数据时要采取的步骤。

•您的源数据包含不断更新的网站日志。您设置ELK堆栈并配置网站以在那里流式传输所有新日志。您可以创建docs / data.rst,在其中描述日志记录的内容以及访问和配置ELK堆栈所需的信息。

•您的源数据包含100,000张尺寸为128x128的彩色图像。将所有图像放在一起,尺寸为100’000 x 128 x 128 x 3,并将其保存在HDF5文件images.h5中。您创建一个Quilt数据包并将其推送到您的私人Quilt存储库。您可以创建docs / data.rst文件,在其中描述为了使用数据,必须首先通过quilt install mypkg / images将其拉入工作区,然后通过from quilt.data.mypkg import images 在代码中导入。

•您的源数据是模拟数据集。您将数据集生成实现为Python类,并在README.txt文件中记录其使用。

通常,在设置源数据时请记住以下经验法则:

1.无论何时,只要您能够以方便的可查询/可索引的形式(SQL数据库,ELK堆栈,HDF5文件或栅格数据库)有意义地存储源数据,您就应该这样做。即使您的源数据是单个csv并且您不愿意设置服务器,也请帮自己一个忙,然后将其导入到SQLite文件中。如果您的数据干净整洁,可以这么简单:

import qlalchemy as sa
import pandas as pd   
e = sa.create_engine(“sqlite:///raw_data.sqlite”)  
pd.read_csv(“raw_data.csv”).to_sql(“raw_data”,e)   
           

2.如果您在团队中工作,请确保数据易于共享。使用NFS分区,S3存储桶,Git-LFS存储库,Quilt包等。

3.确保您的源数据始终是只读的,并且您有备份副本。

4.花些时间记录所有数据的含义及其位置和访问程序。

5.一般来说,非常认真地对待这一步。你在这里犯的任何错误,无论是无效的源文件,误解的功能名称,还是配置错误的服务器,都可能会浪费你很多时间和精力。

数据处理

数据处理步骤的目的是将源数据转换为“干净”形式,适用于以下建模阶段。 在大多数情况下,这种“干净”的形式是一个特征表,因此“数据处理”的要点通常归结为各种形式的特征工程。 这里的核心要求是确保特征工程逻辑可维护,目标数据集是可重现的,有时,整个管道可追溯到源表示(否则您将无法部署模型)。 如果处理是在明确描述的计算图中组织的,则可以满足所有这些要求。 但是,实现此图表有不同的可能性。 这里有些例子:

•您遵循cookiecutter-data-science路线并使用Makefile来描述计算图。 每个步骤都在一个脚本中实现,该脚本将一些数据文件作为输入并生成一个新的数据文件作为输出,您将其存储在项目的data/interim或data/processed子目录中。 您可以通过make -j 轻松进行并行计算。

•您依靠DVC而不是Makefile来描述和执行计算图。整个过程与上面的解决方案大致相似,但您可以获得一些额外的便利功能,例如轻松共享生成的文件。

•您使用Luigi,Airflow或任何其他专用工作流管理系统代替Makefile来描述和执行计算图。除此之外,这通常可以让您在基于Web的精美仪表板上观察计算的进度,与计算集群的作业队列集成,或提供其他一些特定于工具的好处。

•所有源数据都作为一组表存储在SQL数据库中。您可以根据SQL视图实现所有功能提取逻辑。此外,您还使用SQL视图来描述对象的样本。然后,您可以使用这些要素和样本视图,使用自动生成的查询来创建最终的建模数据集,像这样:

select 
   s.Key 
   v1.AverageTimeSpent, 
   v1.NumberOfClicks, 
   v2.Country 
   v3.Purchase as Target 
from vw_TrainSample s 
left join vw_BehaviourFeatures v1 on v1.Key = s.Key 
left join vw_ProfileFeatures v2 on v2.Key = s.Key 
left join vw_TargetFeatures v3 on v3.Key = s.Key 

           

这种特殊的方法非常通用,所以让我稍微扩展一下。首先,它允许您轻松跟踪所有当前定义的功能,而无需将它们存储在大型数据表中 - 功能定义仅作为代码保存,直到您实际查询它们为止。其次,将模型部署到生产变得相当简单 - 假设实时数据库使用相同的模式,您只需要复制相应的视图。此外,您甚至可以使用一系列CTE语句将所有要素定义编译为单个查询以及最终模型预测计算:

with _BehaviourFeatures as (
 ... inline the view definition ...
),

_ProfileFeatures as (
 ... inline the view definition ...
),

_ModelInputs as (
 ... concatenate the feature columns ...
)
select 
     Key, 
     1/(1.0 + exp(-1.2 + 2.1*Feature1 - 0.2*Feature3)) as Prob 
from _ModelInputs 

           

这项技术已经在我设计的一个内部数据科学工作台工具中实现(不幸的是,到目前为止还没有公开),并提供了一个非常简化的工作流程。

DataScience Process Analysis数据科学工作流解析

基于SQL的功能工程管道示例无论您选择哪种方式,请牢记以下几点:

1.始终以计算图的形式组织处理并保持重现性。

2.这是您需要考虑可能需要的计算基础设施的地方。你打算进行长时间的计算吗?您是否需要并行或租用群集?您是否可以从具有用于跟踪任务执行的管理UI的作业队列中受益?

3.如果您计划稍后将模型部署到生产中,请确保您的系统支持该用例。例如,如果您正在开发一个包含在Java Android应用程序中的模型,但是您更喜欢用Python进行数据科学,那么避免很多麻烦的一种可能性就是表达您的所有数据处理一个专门设计的DSL而不是免费的Python。然后可以将该DSL翻译成Java或PMML之类的中间格式。

4.考虑存储有关您的设计功能或临时计算的一些元数据。这不必太复杂 - 例如,您可以将每个要素列保存到单独的文件中,或者使用Python函数注释来注释每个要素生成函数及其输出列表。如果您的项目很长并且涉及多个人设计功能,那么拥有这样的注册表可能会非常有用。

建模

完成清理数据,选择适当的样本并设计有用的功能后,即可进入建模领域。 在某些项目中,所有建模都归结为单个m.fit(X,y)命令或单击按钮。 在其他情况下,它可能涉及数周的迭代和实验。 通常,您可以从“特征工程”阶段的建模开始,当您确定一个模型的输出本身构成了很多特征时,因此该步骤与前一个步骤之间的实际边界是模糊的。 这两个步骤都应该是可重复的,并且必须成为计算图的一部分。 两者都围绕计算,有时涉及作业队列或集群。 尽管如此,单独考虑建模步骤仍然是有意义的,因为它往往有一个特殊的需求:实验管理。 和以前一样,让我通过例子来解释我的意思。

•您正在训练模型,用于在iris.csv数据集中对Irises进行分类。您需要尝试十个左右的标准sklearn模型,每个模型应用多个不同的参数值并测试手工制作的不同子集。您没有正确的计算图或计算基础设施 - 您只需使用一个Jupyter笔记本即可。但是,请确保所有训练运行的结果都保存在单独的pickle文件中,您可以稍后分析这些文件以选择最佳模型。

•您正在设计基于神经网络的图像分类模型。您使用ModelDB(或替代实验管理工具,如TensorBoard,Sacred,FGLab,Hyperdash,FloydHub,Comet.ML,DatMo,MLFlow,…)来记录学习曲线和所有实验的结果,以便稍后选择最好的一个。

•使用Makefile(或DVC或工作流引擎)实现整个管道。模型训练只是计算图中的一个步骤,它输出一个模型 - .pkl文件,将模型最终AUC分数附加到CSV文件并创建一个模型 - .html报告,一堆用于以后评估的有用模型性能图表。

•这是实验管理/模型版本控制在上述自定义工作台的UI中的外观:

DataScience Process Analysis数据科学工作流解析

其他信息:决定您计划如何管理具有不同超参数的多个模型,然后选择最佳结果。 您不必依赖复杂的工具 - 有时即使手动更新的Excel工作表也能正常使用。 但是,如果您计划进行冗长的神经网络培训,请考虑使用基于Web的仪表板。 所有酷酷的孩子都这样做。

模型部署

除非您的项目纯粹是探索性的,否则您可能需要将最终模型部署到生产环境中。 根据具体情况,这可能是一个相当痛苦的步骤,但仔细的计划将减轻痛苦。 这里有些例子:

•您的建模管道使用经过训练的模型吐出一个pickle文件。您的所有数据访问和功能工程代码都是作为一组Python函数实现的。您需要将模型部署到Python应用程序中。您创建一个Python包,其中包含必要的函数和模型pickle文件作为文件资源。你记得要测试你的代码。部署过程是一个简单的软件包安装,然后是一系列集成测试。

•您的管道使用经过培训的模型吐出一个pickle文件。要部署模型,您可以使用Flask创建REST服务,将其打包为docker容器,并通过公司的Kubernetes云进行服务。或者,您将保存的模型上载到S3存储桶并通过Amazon Lambda提供。您确保测试了部署。

•您的培训管道生成TensorFlow模型。您可以使用Tensorflow服务(或任何替代方案)将其作为REST服务提供。每次更新模型时,都不要忘记创建测试并运行它们。

•您的管道生成PMML文件。您的Java应用程序可以使用JPMMLlibrary读取它。确保PMML导出器包含PMML文件中的模型验证测试。

•您的管道以自定义JSON格式保存模型和预处理步骤的描述。要将它部署到您的C#应用程序中,您已经开发了一个专用组件,该组件知道如何加载和执行这些JSON编码模型。您确保在Python中对模型导出代码进行100%测试,C#中的模型导入代码以及您部署的每个新模型的预测。

•您的管道将模型编译为SQL查询。您将此查询硬编码到您的应用程序中。你还记得测试。

•您通过付费服务培训模型,该服务还提供了将其作为REST发布的方法(例如Azure ML Studio,YHat ScienceOps)。你付了很多钱,但你仍然测试部署。

总结这些:

1.如何部署模型有很多方法。确保您了解您的情况并提前计划。您是否需要将模型部署到用不同语言编写的代码库中,而不是用于训练它的语言?如果您决定通过REST提供服务,那么如果服务能够批量预测,那么该服务会产生什么样的负载呢?如果您打算购买服务,请估计您需要支付多少费用。如果您决定使用PMML,请确保它可以支持您预期的预处理逻辑以及您计划使用的奇特的随机森林实施。如果您在培训期间使用了第三方数据源,请考虑是否需要在生产中与它们集成,以及如何在从管道导出的模型中对此访问信息进行编码。

2.一旦将模型部署到生产环境,它就会从数据科学的人工制品转变为实际的代码,因此应该满足应用程序代码的所有要求。这意味着测试。理想情况下,您的部署管道应生成用于部署的模型包以及测试此模型所需的所有内容(例如,样本数据)。模型在从出生地转移到生产环境后停止正常工作的情况并不少见。它可能是导出代码中的错误,pickle版本不匹配,REST调用中的错误输入转换。除非您明确地测试已部署模型的预测是否正确,否则您可能在不知情的情况下运行无效模型。一切看起来都不错,因为它会一直预测一些价值,只是错误的价值。

模型监控

将模型部署到生产环境时,数据科学项目不会结束。 热量仍在继续。 也许训练集中的输入分布与现实生活不同。 也许这种分布缓慢漂移,模型需要重新训练或重新校准。 也许系统不像你期望的那样工作。 也许你正在进行A-B测试。 在任何情况下,您都应该设置基础架构以持续收集有关模型性能的数据并对其进行监控。 这通常意味着设置可视化仪表板,因此主要示例如下:

•对于模型的每个请求,将输入和模型的输出保存到logstash或数据库表(确保以某种方式保持GDPR兼容)。 您可以设置Metabase(或Tableau,MyDBR,Grafana等)并创建可视化模型性能和校准指标的报告。

探索和报告

在数据科学项目的整个生命周期中,您将不得不回避主要建模管道,以便探索数据,尝试各种假设,生成图表或报告。这些任务在两个重要方面与主要管道不同。

首先,它们中的大多数不必具有可再现性。也就是说,您不必像计算数据预处理和模型拟合逻辑那样将它们包含在计算图中。当然,您应该始终坚持使用可重复性 - 当您拥有从原始数据重新生成给定报告的所有代码时,这很棒,但仍有许多情况下这种麻烦是不必要的。有时在Jupyter中手动制作一些图并将它们粘贴到Powerpoint演示文稿中就可以达到目的,不需要过度工程。

第二点,这些“探索”任务实际上有问题的特殊性在于它们往往有些混乱和不可预测。有一天,您可能需要分析性能监控日志中的一个奇怪的异常值。第二天你想要测试一个新的算法等。如果你没有决定一个合适的文件夹结构,很快你的项目目录将被填充有奇怪名称的笔记本,团队中没有人会理解什么是什么。多年来,我只找到了一个或多或少的解决方案来解决这个问题:按日期订购子项目。即:

•在您的工程文件夹中创建项目目录。 您同意为每个“探索性”项目必须创建名为 “projects / YYYY-MM-DD” - 子项目标题的文件夹,其中YYYY-MM-DD是子项目启动的日期。 经过一年的工作,您的项目文件夹如下所示:

./2017-01-19 - Training prototype/
                (README, unsorted files)
./2017-01-25 - Planning slides/
                (README, slides, images, notebook)
./2017-02-03 - LTV estimates/
                 README
                 tasks/
                   (another set of 
                    date-ordered subfolders)
./2017-02-10 - Cleanup script/
                 README
                 script.py
./... 50 folders more ...
           

请注意,您可以根据需要自由组织每个子项目的内部。 特别是,它本身甚至可能是一个“数据科学项目”,它有自己的raw/processed data子文件夹,它自己的基于Makefile的计算图,以及自己的子项目(在这种情况下我倾向于命名任务)。 在任何情况下,始终记录每个子项目(至少有一个README文件)。 有时它还有一个根项目/ README.txt文件,它简要列出了每个子项目目录的含义。

最终您可能会发现项目列表变得太长,并决定重新组织项目目录。 您压缩其中一些并移动到存档文件夹。 您重新组合一些相关项目并将它们移动到某个父项目的tasks子目录。

探索型任务有两种形式。 有些任务是真正的一次性分析,可以使用永远不会再次执行的Jupyter笔记本来解决。 其他人的目标是生成可重复使用的代码(不要与可重现的输出相混淆)。 我发现建立一些关于如何保留可重用代码的约定很重要。 例如,约定可能是在子项目的根目录中有一个名为script.py的文件,该文件在执行时输出基于argparse的帮助消息。 或者您可能决定要求提供配置为Celery任务的运行功能,以便可以轻松地将其提交到作业队列。 或者它可能是别的东西 - 只要它是一致的,任何事情都可以。

服务列表

关于数据科学工作流程还有另一个正交的观点,我觉得这很有用。 也就是说,我们可能会讨论数据科学项目通常依赖的关键服务,而不是在流程管道方面谈论它。 这样,您可以通过指定提供以下9个关键服务的具体内容来描述您的特定(或期望)设置:

DataScience Process Analysis数据科学工作流解析

数据科学服务

1.文件存储。你的项目必须有一个家。通常这个家必须由团队共享。它是网络驱动器上的文件夹吗?它是Git存储库的工作文件夹吗?你如何组织其内容?

2.数据服务。您如何存储和访问您的数据?这里的“数据”包括您的源数据,中间结果,对第三方数据集的访问,元数据,模型和报告 - 基本上是计算机读取或写入的所有内容。是的,保留一堆HDF5文件也是“数据服务”的一个例子。

3.Versioning。代码,数据,模型,报告和文档 - 一切都应该保留在某种形式的版本控制之下。 Git代码?被子数据? DVC的型号? Dropbox报告?维基文件?一旦我们做到了,不要忘记为所有事情设置定期备份。

4.Metadata和文档。您如何记录您的项目或子项目?您是否维护有关功能,脚本,数据集或模型的任何机器可读元数据?

5.交互式计算。交互式计算是数据科学中大部分辛勤工作的完成方式。你使用JupyterLab,RStudio,ROOT,Octave还是Matlab?您是否为交互式并行计算设置了一个集群(例如ipyparallel或dask)?

6.Job队列和调度程序。你如何运行你的代码?您是否使用作业处理队列?您是否有能力(或需要)安排定期维护任务?

7.计算图。您如何描述计算图并建立可重复性? Makefile文件? DVC?Airflow?

8.实验经理。您如何收集,查看和分析模型培训进度和结果? ModelDB? Hyperdash? FloydHub?

9.监控仪表板。您如何收集和跟踪模型在生产中的表现?元数据库?画面? PowerBI? Grafana?

工具

总结这次浏览,这里有一个小电子表格,列出了这篇文章中提到的工具(以及我后面添加或稍后将添加的一些额外的工具),根据数据科学工作流程的哪些阶段对其进行分类(在 这篇文章中定义的术语)他们的目标是支持。 免责声明 - 我确实尝试过很多,但不是全部。 特别是,到目前为止,我对列表中非免费解决方案功能的理解仅基于其在线演示或网站上的描述。

继续阅读