TowardsDataScience 博客中文翻译 2020(四百九十五)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

如何利用 MLOps 自动化更快地将 ML 产品化

原文:https://towardsdatascience.com/how-to-productize-ml-faster-with-mlops-automation-d3f25caf38c4?source=collection_archive---------25-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源 shutterstock

在我们最近在两周一次的 MLOps Live 网络研讨会系列中进行的一项调查中,数百名与会者证实了数据科学团队正在努力应对的头号挑战——将机器学习引入生产。这一点得到了 Gartner research 的证实,该公司一直认为将人工智能产品化是当今人工智能实践中最大的挑战之一。许多人工智能项目,根据研究超过 80% ,陷入实验室,产生部分成功,或者消耗远多于最初计划的资源和时间。找到更快、更简单的方法将机器学习项目产品化是必不可少的,这样它们才能对业务产生影响。

抛开政治和组织方面的挑战不谈,主要障碍是数据科学团队通常在孤岛中工作,与工程和 DevOps 团队分离,并使用手动开发流程(也称为“jumbo”Jupyterplaygrounds),然后需要手动转换为生产就绪的 ML 管道。这需要 ML 工程师、数据工程师、DevOps 和开发人员的独立团队投入额外的时间和资源,通常远远超过最初的预期。每当数据准备或模型训练逻辑发生变化时,整个循环都会重复。

人工智能服务和应用开始成为任何业务的重要组成部分。伴随着这种趋势而来的是责任,这进一步增加了复杂性。需要添加数据、代码和实验跟踪,监控模型以检测概念漂移,通过使用 AutoML 技术和集成提高模型准确性,等等。

目前占主导地位的以研究为导向的数据科学方法在这种环境下不再流行。数据科学必须采用具有微服务、持续集成 (CI)、持续部署 (CD)、代码版本化(Git)和配置/元数据版本化(GitOps)的敏捷软件开发实践。

当我与数据科学团队领导交谈时,他们都同意这种方法,但在实施方面存在困难。毕竟,数据科学家不是软件开发人员或 ML 工程师,反之亦然,这是有原因的。我们需要自动化流程的方法,并弥合软件和数据科学实践之间的差距。这就是一些新的开源工具可以派上用场的地方,我将演示这一点。

在这篇文章中,我将建议并展示如何加速 ML 的可操作性并减少摩擦。

各个击破

你有没有尝试过将数据科学笔记本或一个 Kaggle 项目转化为可以在生产中运行的东西?祝你好运。典型的项目包括 XXL 笔记本,从数据收集、数据准备、特征分析、制图、培训、验证等开始。

您通常会发现相同的模板和助手函数在多个笔记本中重复,代码没有在函数中组织,异常很少被处理,等等。如果您尝试对笔记本进行版本控制,很难发现版本之间的差异,更不用说尝试查看和评论拉取请求了。

我们需要采取的第一步是将我们的项目分解成功能(例如数据探索、培训等。)和定义良好并记录在案的 API。如果这些函数是共享的,我们应该把它们放在一个单独的 Python 或 notebook 文件中。当我们定义 API 时,调试、跟踪和理解代码变得更加容易,我们可以测试单个的功能,或者将它们作为更大流程的一部分。将单个功能或步骤重构为微服务要比重构整个项目笔记本简单得多。稍后我将展示如何实现自动化。

从实验到生产,没有任何麻烦

既然我们已经将数据科学代码和工作流分解为一组独立的功能,我们需要找到一种方法来运行这些功能,同时考虑生产或规模,并满足以下要求:

  • 使其可部署(用所需的包、Kubernetes 运行时规范等构建 docker 映像。)
  • 增加健壮性和故障处理
  • 使用参数、结果、数据和元数据跟踪执行情况
  • 针对性能进行优化,支持针对要求苛刻的工作负载或更大的数据集进行扩展
  • 实施:支持日志记录、监控、强化安全等。

这通常是开发人员、数据和 ML 工程师团队重构代码并为生产做好准备的地方,这意味着添加更多的资源并显著延迟该过程。在团队各自为政的组织中,这是极其困难的,并且会导致许多数据科学计划中途被放弃。

另一种方法是跨团队协作,通过自动化从代码到产品的迁移以及我们跟踪执行和数据的方式,最大限度地减少人工工作。

我们希望利用我们的数据科学功能,自动构建和部署它们,根据实际使用情况扩展它们,并以最少的工作量监控它们的所有输入和输出。这在今天已经用“无服务器”技术实现了,我们只需要让它适应独特的数据科学问题和开发实践。

一个名为 MLRun (由我的公司 Iguazio 发起)的新开源框架与其他工具结合使用,如 Nuclio (无服务器引擎)和 Kubeflow pipelines (管道编排),以自动化 MLOps 流程,并将 CI/CD + Git 实践引入数据科学。这项技术的早期采用者报告说,他们将整体交付时间从几个月缩短到几周,显著减少了计算资源和劳动力,现在他们终于可以完全了解所有的实验和数据。

MLRun 提供 SDK 和 Kubernetes 服务。SDK 可以在任何地方使用(在你的代码 IDE、Jupyter 笔记本、像 Google Colab 或 AWS Sagemaker 这样的托管笔记本服务、生产容器等等。).它可以自动跟踪你所有的功能活动,输入和输出。它处理各种函数之间的参数和数据传递,它可以使用一个命令将您的本地代码转换为分布式函数或完整的 ML 管道。(详见 mlrun 文档)

MLRun 服务记录来自所有客户端的跟踪信息,基于所提供的代码+元数据自动提供“无服务器”功能,通过编排 Kubeflow 管道端到端管理工作流,并提供基于 web 的 UI,用于端到端管理正在运行的作业/实验、功能和工件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从代码到可重用微服务(图片由作者提供)

您可以查看这个笔记本来了解一个函数是如何在 Jupyter 中编写和记录的,以及如何通过一个命令将它转换成一个无服务器的函数(微服务)对象,该对象可以发布到 Git 或在可重用函数市场中编目。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

功能代码(图片由作者提供)

该笔记本还演示了如何从存储库/市场加载功能,并使用以下三种方式之一来执行任务:1 .作为本地可执行文件,2。作为一个自动扩展的容器化微服务,3。作为内存模块。执行及其元数据、输入和输出被自动跟踪。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

MLRun 实验跟踪(图片由作者提供)

在其他示例中,您可以看到如何使用受支持的分布式运行时引擎之一(Nuclio、Dask、Spark、Horovod over MPI)横向扩展计算、管理模型、管理完整的项目以及提供按需资源或 GPU 分配(在我的 GPU 即服务博客中有详细介绍)。

这些功能是原子的(代码+所有的运行时定义),版本化的,文档化的,这使得它们高度可重用。开发人员可以对功能进行扩展/增强,或者直接使用它们。这可以大大加快开发时间,并且您可以查看和重用一系列适用于不同数据科学阶段和算法的有用的预烤函数。

查看我的视频,它展示了我们如何自动将笔记本代码转换为可扩展的、自动跟踪的微服务:

自动化 ML 管道

我们的数据科学管道需要的不仅仅是一个功能。我们需要接收和准备数据,选择主要特性,训练我们的模型,验证它,部署它,等等。我们需要组装一个管道(工作流)——我们为此使用 Kubeflow 管道——并让 MLRun 组合、执行和跟踪我们的管道。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从 ML 函数构建自动化工作流(图片由作者提供)

你可以看到这个例子,它展示了一个由笔记本和市场功能组成的完整的 ML 管道。管道接收数据,通过 AutoML、验证、模型部署和生产测试运行功能分析培训。可以通过命令行或 SDK 手动触发管道,也可以通过 Git 事件(如 pull 请求注释)触发管道。基于 Git 的 MLOps 自动化将在我的下一篇博客文章中详细讨论。

如果我们想要跟踪我们的管道结果,我们可以使用 MLRun UI,或者简单地将结果摘要作为注释推送到我们的 slack 通道或 Git pull 请求中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

获取时差通知(作者图片)

摘要

通过采用敏捷、CI/CD 和无服务器实践,数据科学和 MLOps 任务可以以节省大量时间和资源的方式实现自动化。MLRun 项目是一个新项目,但它是第一个旨在加快生产率和生产时间的整体 MLOps 自动化解决方案。MLRun 开发团队欢迎想要试用它的新用户和新贡献者,如果您不喜欢安装和开发,您可以通过 Iguazio 将其作为管理服务使用。

如果您想讨论这个博客或其他与 MLOps 相关的挑战和最佳实践,我邀请您到加入 MLOps Live Slack 社区,与我和其他 MLOps 粉丝/专家聊天。

如何在 Python 中分析您的代码

原文:https://towardsdatascience.com/how-to-profile-your-code-in-python-e70c834fad89?source=collection_archive---------2-----------------------

使用 cProfile 查找瓶颈并优化性能

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来自 PexelsAnthony Maggio 摄影

如果你曾经写过一行代码(或者甚至几万行),你一定想知道“为什么我的代码需要这么长时间才能运行?”回答这个问题并不总是简单的,但如果你以正确的方式寻找答案,它会变得更容易。

也许你相信你手头问题的知识,利用你的专业知识先检查某些片段。也许你对几个不同的模块/类/函数计时,看看大部分执行时间花在哪里。更好的是,您可以分析您的代码,以获得更多关于不同函数和子函数所花费的相对时间的信息。不管你的过程是什么,这个博客可能会教你一些更快找到答案的方法。

在这篇文章中,我将首先向您展示一个基本的分析方法。我将为它添加越来越多的特性和味道,以一个好的、可靠的剖析装饰器结束。对于那些赶时间的人(或者想回头参考这些资料的人),可以去这个 GitHub 仓库,在那里你可以找到概要文件装饰器和一个例子。

计时!

要分析你的代码,你需要知道如何计时。为此,您可以使用如下简单的方法:

**from** time **import** timestart = time()
*# your script here* end = time()
print(**f'It took {**end - start**} seconds!'**)

为了方便地为几个函数/代码片段计时(或者如果您只是喜欢使用更简洁、更 pythonic 化的方法),您可以将上面的内容转换成一个计时器装饰器(这里用示例讨论)。

在任何函数上使用定时器都可以单独显示该部分的运行时间。为了使这种方法有助于找到瓶颈,我们需要更多的信息。为了有效地分析代码,下列两个条件中至少有一个应该为真:

  1. **我们应该知道程序的总运行时间,以便更好地了解我们期望的功能/部分的相对运行时间。**例如,如果一段代码需要 5 分钟来执行,那是总运行时间的 10%、40%还是 90%?
  2. 我们应该对手头的问题或程序其他部分的运行时间有足够的了解,从而有把握地将一段给定的代码标记为瓶颈。即使一个功能需要 10 分钟才能运行(假设 10 分钟相对来说很长),如果我们确信没有其他部分需要更长的时间,我们就应该担心它的低效率。正如唐纳德·克努特的名言:

过早优化是万恶之源。

[cProfile](https://docs.python.org/3.8/library/profile.html)这样的分析器包通过满足这两个条件来帮助我们找到代码中的瓶颈。

如何使用 cProfile

基本用法

cProfile进行概要分析的最基本方式是使用run()函数。您需要做的就是将您想要分析的内容作为字符串语句传递给run()。这是报告的一个示例(为简洁起见,进行了删节):

>>> **import** cProfile
>>> **import** pandas **as** pd>>> cProfile.run(**"pd.Series(list('ABCDEFG'))"**)258 function calls (256 primitive calls) in 0.001 secondsOrdered by: standard namencalls  tottime  percall  cumtime  percall filename:lineno(function)
     4    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:997(_handle_fromlist)
     1    0.000    0.000    0.000    0.000 <string>:1(<module>)
     1    0.000    0.000    0.000    0.000 _dtype.py:319(_name_get)
  ....
  11/9    0.000    0.000    0.000    0.000 {built-in method builtins.len}
     1    0.000    0.000    0.000    0.000 {built-in method numpy.array}
     1    0.000    0.000    0.000    0.000 {built-in method numpy.empty}
  ....

第一行表示监控了 258 个调用,其中 256 个是原始调用(原始调用不是通过递归引起的)。下一行Ordered by: standard name表示报告是基于标准名称排序的,标准名称是filename:lineno(function)列中的文本。其后的一行是列标题:

ncalls:呼叫次数。当有两个数字时(如上面的 11/9),该函数循环出现。第一个值是调用的总数,第二个值是原始或非递归调用的数量。

tottime:给定函数花费的总时间(不包括调用子函数的时间)。

percall:是tottime除以ncalls的商。

cumtime:该功能及所有子功能的累计时间。这个数字对于递归函数来说是精确的甚至

percall:是cumtime的商除以原语调用。

filename:lineno(function):提供各功能各自的数据。

run()函数可以再接受两个参数:一个filename将结果写入文件而不是 stdout,另一个sort参数指定输出应该如何排序。您可以查看文档以了解更多关于有效排序值的信息。常见的有'cumulative'(累计时间)'time'(总时间)'calls'(通话次数)。

如果您传递一个文件名并保存结果,您可能会注意到输出不是人类可读的。在这种情况下,您需要使用pstats.Stats类来格式化结果,我们将在接下来讨论。

使用Profilepstats.Stats进行更多控制

虽然在大多数情况下使用cProfile.run()就足够了,但是如果您需要对分析进行更多的控制,您应该使用cProfileProfile类。下面的片段摘自Profile文档

**import** cProfile, pstats, io
**from** pstats **import** SortKey

pr = cProfile.Profile()
pr.enable()
*# ... do something ...* pr.disable()
s = io.StringIO()
sortby = SortKey.CUMULATIVE
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
print(s.getvalue())

让我们一行一行地过一遍:

首先,我们创建一个Profile类(pr)的实例,并通过调用enable收集概要分析数据。当我们想要停止收集分析数据时,我们调用disable。接下来是对收集的统计数据进行格式化。然后,我们可以使用[pstats.Stats](https://docs.python.org/3.8/library/profile.html#pstats.Stats)类构造函数来创建 statistics 对象的实例(ps)。

Stats类可以从 profile 对象(pr)创建一个 statistics 对象,并将输出打印到传递给它的流中。Stats类还有一个sort_stats方法,根据提供的标准对结果进行排序。在这种情况下,标准是SortKey.CUMULATIVE,它代表在一个函数中花费的累计时间。如[sort_stats](https://docs.python.org/3.8/library/profile.html#pstats.Stats.sort_stats)文档所述,排序标准可以是SortKey枚举(在 Python 3.7 中添加)或字符串的形式(即使用'cumulative'代替SortKey.CUMULATIVE也是有效的)。最后,创建结果并打印到标准输出。

这是构建装饰器的好样板(要了解更多关于装饰器的知识,我推荐这本伟大而全面的初级读本):

**import** cProfile
**import** io
**import** pstats**def** profile(func):
    **def** wrapper(*args, **kwargs):
        pr = cProfile.Profile()
        pr.enable()
        retval = func(*args, **kwargs)
        pr.disable()
        s = io.StringIO()
        sortby = SortKey.CUMULATIVE  # **'cumulative'** ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
        ps.print_stats()
        print(s.getvalue())
        **return** retval

    **return** wrapper*# Profile foo* @profile
**def** foo():
    print(**'Profile me!'**)

虽然这是一个好的开始,但是上面的装饰器中还有几个部分可以做得更好。特别是,更全面的职能可以:

  1. 允许用户指定排序键(单个键或一组排序键)
  2. 仅显示最大时间消费者,而不是所有线路
  3. 通过删除文件名中的所有前导路径信息来整理报告,减小打印输出的大小并使报告更易于阅读
  4. 将输出保存到文件,而不是打印到标准输出

以上所有情况都可以使用pstats.Stats中的方法进行处理。让我们按顺序复习一下:

  1. 将所需的排序键传递给sort_stats()方法(尽管我们仍然需要检查它是单个值还是一个元组)
  2. 将最大所需打印行数传递给print_stats()
  3. 使用strip_dirs()
  4. 默认情况下,输出被打印到[sys.stdout](https://docs.python.org/3/library/sys.html#sys.stdout),因为pstats.Stats()使用它作为默认的流参数,但是要将结果写入文件,我们可以将文件作为流传递

将上述更改应用到profile装饰器将产生以下函数(在 docstring 中提供了参数的更多解释):

总结示例

为了了解profile装饰器如何帮助我们检测瓶颈,让我们创建一个具有多个函数的例子。假设您有一份过去一年销售的产品列表,并且您想通过计算售出的数量来了解每种产品的受欢迎程度。(我们想要的可以通过使用[collections.Counter](https://docs.python.org/3/library/collections.html#collections.Counter)很容易地完成,或者如果你是一个pandas用户,通过[pandas.Series.value_counts](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.value_counts.html),但是为了这个练习,让我们忘记那些。)

**import** random
random.seed(20)**def** create_products(num):
    *"""Create a list of random products with 3-letter alphanumeric name."""* **return** [**''**.join(random.choices(**'ABCDEFG123'**, k=3)) **for** _ **in** range(num)]

*# version1* @profile(sort_by=**'cumulative'**, lines_to_print=10, strip_dirs=**True**)
**def** product_counter_v1(products):
    *"""Get count of products in descending order."""* counter_dict = create_counter(products)
    sorted_p = sort_counter(counter_dict)
    **return** sorted_p

**def** create_counter(products):
    counter_dict = {}
    **for** p **in** products:
        **if** p **not in** counter_dict:
            counter_dict[p] = 0
        counter_dict[p] += 1
    **return** counter_dict

**def** sort_counter(counter_dict):
    **return** {k: v **for** k, v **in** sorted(counter_dict.items(),
                                    key=**lambda** x: x[1],
                                    reverse=**True**)}

*# ===========
# Analysis starts here
# ===========* num = 1_000_000  *# assume we have sold 1,000,000 products* products = create_products(num)
*# Let's add profile decorator to product_counter_v1 function* counter_dict = product_counter_v1(products)

结果将保存在您当前目录下的product_counter_v1.prof中,它应该是这样的:

1007 function calls in 0.228 seconds

Ordered by: cumulative time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.228    0.228 scratch_6.py:69(product_counter_v1)
     1    0.215    0.215    0.215    0.215 scratch_6.py:86(create_counter)
     1    0.000    0.000    0.013    0.013 scratch_6.py:105(sort_counter)
     1    0.013    0.013    0.013    0.013 {built-in method builtins.sorted}
     1    0.000    0.000    0.000    0.000 scratch_6.py:106(<dictcomp>)
  1000    0.000    0.000    0.000    0.000 scratch_6.py:107(<lambda>)
     1    0.000    0.000    0.000    0.000 {method 'items' of 'dict' objects}
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

检查这个文件,我们可以看到绝大部分的执行时间(0.228 秒中的 0.215 秒)都花在了create_counter函数上。所以,让我们制作一个新的create_counter函数,并检查它的效果。

*# version2* @profile(sort_by=**'cumulative'**, lines_to_print=10, strip_dirs=**True**)
**def** product_counter_v2(products):
    *"""Get count of products in descending order."""* counter_dict = create_counter_v2(products)
    sorted_p = sort_counter(counter_dict)
    **return** sorted_p

**def** create_counter_v2(products):
    counter_dict = {}
    **for** p **in** products:
        **try**:
            counter_dict[p] += 1
        **except** KeyError:
            counter_dict[p] = 1
    **return** counter_dict

剖析结果product_counter_v2如下所示:

1007 function calls in 0.169 seconds

Ordered by: cumulative time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.169    0.169 scratch_6.py:78(product_counter_v2)
     1    0.158    0.158    0.158    0.158 scratch_6.py:95(create_counter_v2)
     1    0.000    0.000    0.010    0.010 scratch_6.py:105(sort_counter)
     1    0.010    0.010    0.010    0.010 {built-in method builtins.sorted}
     1    0.000    0.000    0.000    0.000 scratch_6.py:106(<dictcomp>)
  1000    0.000    0.000    0.000    0.000 scratch_6.py:107(<lambda>)
     1    0.000    0.000    0.000    0.000 {method 'items' of 'dict' objects}
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

运行时间从 0.228 秒减少到 0.169 秒,减少了约 26%。如果这仍然不令人满意,您可以尝试使用[collections.defaultdict](https://docs.python.org/3/library/collections.html#collections.defaultdict)来创建counter_dict。对于最后一个实现,我们将使用collections.Counter:

**import** collections

*# version3* @profile(sort_by=**'cumulative'**, lines_to_print=10, strip_dirs=**True**)
**def** product_counter_v3(products):
    *"""Get count of products in descending order."""* **return** collections.Counter(products)

性能分析product_counter_v3显示它比product_counter_v1提高了 62%。

11 function calls in 0.086 seconds

Ordered by: cumulative time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.086    0.086 scratch_6.py:118(product_counter_v3)
     1    0.000    0.000    0.086    0.086 __init__.py:517(__init__)
     1    0.000    0.000    0.086    0.086 __init__.py:586(update)
     1    0.086    0.086    0.086    0.086 {built-in method _collections._count_elements}
     1    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
     1    0.000    0.000    0.000    0.000 abc.py:180(__instancecheck__)
     2    0.000    0.000    0.000    0.000 _weakrefset.py:70(__contains__)
     2    0.000    0.000    0.000    0.000 {built-in method builtins.len}
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

试验一下profile装饰器的不同参数,看看输出会如何变化。你可以在这个 GitHub 库中找到完整的例子。

快乐剖析!

我希望这篇博客对你有用。我可以在TwitterLinkedIn上联系,我欢迎任何反馈。

作为数据科学家,如何更有效地编程和调试

原文:https://towardsdatascience.com/how-to-program-and-debug-more-effectively-as-a-data-scientist-92e753144d54?source=collection_archive---------41-----------------------

我的第一个数据科学软件项目的经验教训

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

奥斯卡·伊尔迪兹在 Unsplash 上拍摄的照片

最近,我交付了我的第一个软件包,旨在自动化一些对我的团队的数据工作流至关重要的时间密集型计算。这个过程包括了比我愿意承认的更多的调试周期,部分是因为代码复杂性的增加和需求的发展,部分是因为我可以更有效地计划和执行。

经过一番思考,这里有一些从那次经历中得到的重要教训,可以帮助你作为一名数据科学家更有效地编写软件。

1。规划你的软件设计

当我开始我的项目时,我在有限的前期规划下投入到编码中,认为我的软件设计的确切细节会随着我的编码变得更加清晰。

随着我的代码变得越来越复杂,我开始忘记所有的函数是如何组合在一起的。当需求发生变化时,我不得不重新投入时间去理解我的代码,以做出想要的修改。

相对来说,避免这一陷阱并不费力。对你的软件在高层次上做了什么有一个简单而清晰的描述,不管你是画一个图表还是对你的软件的设计和功能做笔记。用纸笔、盒子和箭头画一张草图就足够了。我亲自在一个工作文档上写下了我可以不断修改的项目符号。

保留设计图有几个好处。首先,记录你的软件设计会给你一个更清晰的想法,你的所有代码是如何组合在一起的。用语言表达数据操作的逻辑可以帮助你检查你的逻辑是否会给你想要的结果。当然,当您需要对代码设计进行更大的更改时,有一个清晰的参考会变得非常方便。

2。投资文件组织

在多个脚本和 Excel 文件之间,我严重低估了我将在整个项目中导航的文件的数量。当我的专用文件命名系统最终失败时,我发现自己重新编写了几个函数,因为我找不到我编写它们的原始文件。

投资于你的组织必然会减轻压力,提高长期效率。在开始一个项目之前,投入一些前期工作来定义一个清晰的、可维护的文件组织和命名系统是有帮助的。

一些基本准则是:

  • 您正在处理的每个项目都有一个单独的文件夹
  • 每个文件类别(即脚本、数据、输出、QA 等)对应一个文件夹。)
  • 代码的一致命名约定
  • 数据文件的一致命名约定

除此之外,我发现在代码和数据文件(v2-file-2020-08-03)上使用版本标签和日期标签很有帮助,可以更容易地按时间顺序导航。

3。验证每个代码单元

到目前为止,调试是我的编程项目中最痛苦的部分。这种痛苦通常源于缩小 bug 的位置。我学到的一个教训是在每个转换步骤定期进行验证,以确保任何数据处理结果都具有我期望的值和维度。

这使我能够在早期捕捉到意外的行为,并让我对每一步的数据充满信心。

我经常使用的几个基本检查:

  • 检查连接两个数据框前后的行数
  • 检查处理前后变量的和是否匹配
  • 检查缺少的值

为了提高效率和重复击键,我会考虑自动验证的方法,要么通过创建简单的验证函数,要么通过 Excel 模板。对我来说,在自动化验证上投入的时间很容易获得十倍的回报。

4。有条不紊地调试

当出现错误时,根据直觉进行调试有时会有回报。但是如果没有一个计划,这种方法可能是武断和令人沮丧的。从长远来看,遵循有条不紊的调试过程是更有效的策略。

建立一个系统来缩小错误的来源并记录尝试的解决方案,可以帮助你更有效地找到解决方案。此外,这可以缓解压力,让你以一种有条理和冷静的心态专注于调试。

在高层次上,我认为一个系统应该包括理解错误信息,围绕 bug 开发上下文,以及以一种有组织的方式测试和记录解决方案。在这个系统中,您可以更好地控制您的调试过程,为未来的调试周期提供参考文档,并以少量额外的时间和精力投入来换取压力的显著降低。我一直使用的程序是:

1.如果有错误信息,仔细阅读,查找;如果不是,请以书面形式描述意外行为

2.通过插入手动测试来缩小违规代码的位置

3.一旦您确定了错误发生的位置,检查进入违规代码的数据的结构、格式和值——通常这将导致一个解决方案

4.修复、重新运行、评估、记录

5.如果错误仍然存在,请进一步研究错误并再次测试

6.如果错误仍然存在,请寻求调试帮助

虽然您的系统可能不同,但我认为核心原则是相同的:理解您的错误,定位错误,调查明显的错误来源,并测试和记录。

5。记录错误和解决方案

在我的项目过程中,我发现自己多次调试同一个问题,这是对时间的低效利用。

为了避免两次解决同一个问题,我开始维护一个文档,记录我遇到的错误以及它们的解决方案。这个参考还有一个预防性的好处,允许我跟踪常见的错误,避免一开始就犯那些错误。

我建议保持你的解决方案文档简单;你可以在电子表格中记录你遇到的每一个错误——我的表格只有四栏:错误、背景、解决方案和下次注意事项。

在这个项目的过程中,我学到了很多教训,希望这篇文章能为你在下一次软件开发中节省一些压力和时间。请在下面的评论中告诉我你的想法,并随时在 Twitter 上与我联系。

如何正确地发布和部署您的机器学习模型

原文:https://towardsdatascience.com/how-to-properly-ship-and-deploy-your-machine-learning-model-8a8664b763c4?source=collection_archive---------4-----------------------

FastAPI、Docker 和 GitHub 操作实用指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

汤姆·菲斯克在像素上拍摄的照片

作为一名数据科学家,训练你的机器学习模型只是为客户提供解决方案的一部分。除了生成和清理数据、选择和调整算法之外,您还需要交付和部署您的结果,以便它可以在生产中使用。这本身就是一个很大的领域,有着不断发展的工具和标准。在这篇文章中,我的目标是提供一个实用的指南,告诉你如何使用当前可用的最先进的工具和最佳实践来完成这项工作。我们将构建一个系统,它可以作为您部署任务的起点,而不考虑实际的机器学习问题本身!我的目标是介绍最佳实践和展示高级特性,而不是一个仅仅触及所用工具表面的最小化应用程序,这样你就不必学习艰难的方法。从你自己的错误中学习固然很好,但是提前思考并且不犯那些错误要好得多。

为了创建我们的部署就绪应用程序,我们将使用两个工具作为我们的主要构建块: DockerFastAPI 。Docker 可能不需要介绍,它是一个容器化工具,允许您在任何环境中轻松打包和运行您的应用程序。它与 FastAPI 配合得特别好,FastAPI 在过去的几个月里获得了令人难以置信的流行。它使得围绕您的模型构建 web 框架和根据您客户的需求进行定制变得容易。

[## 您应该现在就开始使用 FastAPI

如果您还没有尝试过 FastAPI,现在是时候了

towardsdatascience.com](/you-should-start-using-fastapi-now-7efb280fec02)

我们的玩具问题将是一个简单的回归,我们将根据犯罪率、财产税率等 13 个特征来预测房地产价格。为此,我们将使用波士顿房价数据集作为我们的训练数据。关于模型选择,我们将使用来自牛逼的 scikit-learn 包的随机森林回归器。当然,您并不局限于 scikit-learn,您可以使用 TensorFlow、PyTorch 或任何您喜欢的工具。为了简单起见,我选择了这个,因为它几乎不需要额外的工作,比如大量的数据预处理,而且它的依赖性相对较轻,易于安装。

在这篇文章中,我将展示如何

  • 打包您的模型并构建一个 API 来与之通信,
  • 设计一个方便简单的用户界面,
  • virtualenv设置合适的开发环境,
  • 使用 FastAPI,
  • 通过包装你的机器学习模型为将来的代码变化做准备,
  • 使用依赖注入使测试更容易,
  • 验证用户输入,
  • 用模拟测试 API,
  • 用 Docker 和 Docker compose 打包,
  • 最后是如何使用 GitHub 动作来自动化测试。

要遵循这个指南,你根本不需要有使用 Docker 或 FastAPI 的经验!熟悉 scikit-learn 和 NumPy 将是有益的,但我们不会非常集中地关注这些部分。我们将要构建的应用程序可以在https://github.com/cosmic-cortex/fastAPI-ML-quickstart找到,随时可以使用。在我们直接进入开发之前,让我们评估需求并设计应用程序的架构!

如何设计一个小型的机器学习 app

部署期间的一个主要考虑因素是客户的需求。在我们的例子中,我们假设他们不需要理解算法是如何工作的,也不想重新训练算法。他们只想发送数据,然后马上得到答案。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

与机器学习模型通信

用技术术语来说,我们将构建一个应用程序,它以 HTTP 请求的形式接收数据,并以 HTTP 响应的形式发回预测。除了接口简单之外,作为微服务很容易集成到更大的应用中,这是一个巨大的优势。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来自高层的应用程序

我们的应用程序将通过 API 进行通信,该 API 将被打包在 Docker 容器中。在这个简单的例子中,在应用程序本身中,我们需要做三件事:处理输入、进行预测、处理输出并将其返回给用户。使用 FastAPI,输入将是一个 JSON,如下所示:

{"data":[[0.00632,18,2.31,0,0.538,6.575,65.2,4.09,1,296,15.3,396.9,4.98]]}

这将由 FastAPI 在内部转换成适当的 Python 对象。(稍后将详细介绍这一点,因为这是 FastAPI 中最简洁的特性之一。)我们需要为 scikit-learn 模型处理它,这意味着将它转换成一个 NumPy 数组。它可以用来计算我们的预测,我们将再次把它转换成 FastAPI 使用的格式。最后,用户将收到一个类似输入的 JSON:

{"data": [25.813999999999993]}

马上投入开发吧!我们的首要工作是建立适当的开发环境。

设置开发环境

如果您曾广泛使用 Python,那么您可能使用过虚拟环境。如果没有,要点如下。Python 虚拟环境是 Python 的独立安装,您可以在其中安装项目所需的特定包。当您有许多项目具有可能冲突的依赖关系时(比如一个项目要求 NumPy ≥ 1.13,而另一个项目要求 NumPy ≤ 1.10),您最好使用虚拟环境来避免完全混乱。要创建虚拟环境,请使用

virtualenv /path/to/venv --python=/path/to/python3

在这里可以找到全局 Python3 解释器的路径

which python3

如果你在 Linux 下。(如果不显式提供解释器,就会回退到别名为python的 Python 解释器,有些情况下可以是 Python 2.7。不要使用 Python 2.7:)虚拟环境可以用

source /path/to/venv/bin/activate

在这之后,如果你用 pip 安装包,它将只在虚拟环境活动时可见。在您克隆了包含我们将要构建的应用程序的库之后,您可以使用

pip install -r requirements.txt

在根文件夹中时执行命令。尽管您不需要将您的依赖项收集到一个单独的需求文件中,但是强烈建议您这样做。这使得维护你的应用程序更加容易,而且当你把应用程序打包成 Docker 镜像时,你可以使用同一个文件。

构建应用程序的框架

粗略地说,每个 FastAPI 应用程序都由一个主文件组成,该主文件负责启动应用程序/定义端点和端点使用的附加模块。(可以在主文件之外的其他地方定义端点,但是在最简单的情况下,这种结构是更可取的。)

.
├── api
│   ├── __init__.py
│   ├── main.py
│   └── ml
│       ├── __init__.py
│       ├── model.joblib
│       └── model.py
└── requirements.txt

当 FastAPI 应用程序的结构清晰后,我们先构建main.py的框架,然后实现ml模块!

我们基本上需要导入两个类:为我们的 API 提供所有功能的FastAPI类和来自 awesome Pydantic 库的BaseModel,它充当 HTTP 请求和响应的模型。

在实例化一个FastAPI对象后,我们可以通过使用它的适当方法来修饰描述端点逻辑的函数,从而向它注册端点。例如,这里我们有

这意味着我们的应用程序期望一个对/predict端点的POST请求,该请求包含一个由PredictRequest对象描述的 JSON 有效负载,并将返回一个由PredictResponse描述的 JSON 有效负载的响应。这些都是由函数前的@app.post装饰器指定的,它将这个函数注册到名为appFastAPI实例,并将请求路由到这个函数的/predict URL。predictinput参数的类型注释描述了请求数据的适当格式。

在这个例子中,PredictRequest对象有一个名为data的属性,它必须是一个 floats 列表的列表。(由于数据通常是成批传递的,所以外部列表中的每个列表都是一个数据点。)Pydantic 非常重视类型检查:如果类型不匹配,它会无情地抛出一个异常。这种用 Pydantic 进行的类型检查是 FastAPI 的一个极其强大的特性,使我们的生活变得更加容易。如果请求的格式不正确,您会立即收到一个 422 不可处理的实体状态代码作为响应。而你要为此做几乎为零的工作!如果您已经使用请求和响应模型指定了模式,FastAPI 和 Pydantic 会为您执行验证。

您可以立即使用此应用程序

uvicorn api.main:app

并且通过检查由 FastAPI 生成的自动文档来试用端点,默认情况下可以在http://localhost:8000/docs找到该文档。或者,您可以使用curl来发布请求,例如

curl -X POST “[http://localhost:8000/predict](http://localhost:8000/predict)" -H “accept: application/json” -H “Content-Type: application/json” -d “{\”data\”:[[0]]}”

会管用的。目前,这个简单的框架将总是返回一个伪响应

{"data":[0]}

但是,一旦我们的模型到位,这种情况很快就会改变。既然框架已经建立并运行,我们就可以开始实现机器学习模型了!

创建机器学习算法

正如我提到的,我们将使用 Boston 数据集训练一个简单的随机森林回归器,两者都可以在 scikit-learn 中找到。尽管直接使用 scikit-learn 对象很有吸引力,但我更喜欢为我们的模型构建一个抽象接口,它将由 API 端点使用,而不是由 scikit-learn 对象本身使用。其背后的原因是该接口在整个代码库中是可重用的,如果您希望替换您的底层模型(比如使用 PyTorch 模型而不是 scikit-learn 的随机森林回归器),您只需要更改该类的实现,而不是更改实际使用该模型的所有函数和端点。

我们需要四个基本方法:一个用于训练模型,一个用于计算预测,两个用于保存和加载模型。当界面清晰时,我们就可以开始具体的实现了,这非常简单。

除了模型接口本身,我们还将在api.ml.model模块中定义模型对象。这个特定的实例将在整个应用程序中使用。这被称为单例,是最重要的 OOP 模式之一。虽然在这里使用是安全的,但是在大型应用程序中必须小心使用单例变量,因为它们基本上是全局变量。通过调用get_model()函数,可以在应用程序的其余部分访问这个模型对象。这有两个原因。首先,这个函数在代码中到处都是可重用的,因此如果以后我们决定添加额外的逻辑来获取模型(如检查等),在一个地方修改代码就足够了。第二,稍后将会解释,如果我们在端点中使用依赖注入,那么为应用程序编写单元测试会更好。(如果你现在不明白这一点也不要担心,后面会解释的。)

为了准备我们的应用程序,在执行这个脚本时,一个模型被训练并保存到磁盘上。这将在以后用于预测。

构建 API 端点 I:处理 JSON 输入

在应用程序框架和机器学习算法到位后,我们就可以实施端点背后的逻辑了。让我们切换回main.py模块!预测是一个相对简单的过程,只需要几行代码就可以实现。

在函数体中,有三件事情正在进行:

  1. 输入(是PredictRequest的一个实例)被转换成一个 NumPy 数组。
  2. 计算预测,产生一个 NumPy 数组。
  3. 结果被转换成一个PredictResponse对象并返回。

FastAPI 将返回值转换为正确的响应。有一个重要的变化可能已经引起了您的注意:我们向我们的predict函数传递了一个额外的参数:

model: Model = Depends(get_model)

其中get_model函数是返回模型的函数,在api.ml.model模块中定义。这种技术被称为依赖注入。虽然model是函数的一个参数,但是每次调用predict函数,都会执行get_model并传递返回值。为什么这很有用,这一点可能并不明显,但是这对于编写正确的单元测试非常重要。想想看:我们的端点依赖于一个 scikit-learn 对象,它背后有数千行代码。例如,它可以在软件包的新版本中进行磨合。(就像最近发生在 pip 上的一样:https://github.com/pypa/pip/issues/7217,影响了相当一部分用户。)一般来说,不管它们有多重要,外部依赖都会带来潜在的错误。当我们想要对我们的应用程序进行单元测试时,我们不希望结果依赖于一些可能超出我们控制的对象的正确性。因此,这些通常在单元测试中被嘲笑。mock 是一个伪对象,实现了与原始对象相同的接口,具有 100%可预测的行为。有了依赖注入,通过覆盖依赖,这些模拟可以很容易地注入到代码中。如果您没有马上明白这一点,请不要担心,在测试部分会有更详细的解释。

永远不要相信用户的输入

既然端点本身已经实现,让我们考虑一些可能的用例。如果你尝试

curl -X POST “[http://localhost:8000/predict](http://localhost:8000/predict)" -H “accept: application/json” -H “Content-Type: application/json” -d “{\”data\”:[[0]]}”

使用当前的实现,您将得到一个内部服务器错误,应用程序将崩溃。这是因为由于模型是使用 13 个特征训练的,所以它需要 13 个特征来进行预测。虽然 uvicorn 很聪明,会在这种情况下重启你的应用程序,但是内部服务器错误听起来很糟糕,你肯定不想在生产中遇到这种情况。为了解决这个问题,我们将在 Pydantic 请求模型中添加额外的验证。默认情况下,它们只检查 JSON 有效负载是否有一个“data”键,其值是一个 floats 列表的列表。在我们的定制验证器(除了默认验证之外还运行)中,我们检查数据的维度是否正确,也就是说,每个子列表都准确地包含了n_features元素。(也就是 13。)

当传递了错误的数据并且验证失败时,应用程序不会崩溃,而是返回 422 不可处理的实体错误代码。虽然这对最终用户来说不一定是更好的结果,但对你和你的 devops 团队来说肯定是更愉快的。一般来说,当您构建处理数据的应用程序时,您不应该相信用户输入。事情可能会意外出错,也可能会受到恶意攻击,比如 SQL 注入,这是黑客工具包中一个流行而危险的工具。

最终的模块会是这样的:https://github . com/cosmic-cortex/fastAPI-ML-quick start/blob/master/API/main . py

下一节将添加predict_csv端点。

构建 API 端点 II:处理。csv 文件

如果您想接收另一种格式的数据,如 csv 文件,您可以这样做。你应该使用[File](https://fastapi.tiangolo.com/tutorial/request-files/) [UploadFile](https://fastapi.tiangolo.com/tutorial/request-files/)来代替使用 Pydantic 模型作为输入。

注意,这一次,Pydantic 没有为我们执行验证,因此我们必须手动执行。有两件事需要验证。

  1. 该文件包含表格形式的数据。
  2. 该数据正好包含 13 个特征。

我们在函数体内手动完成这两项工作。当出现问题时,我们会抛出一个异常,由 FastAPI 在一个适当的 HTTP 响应中返回。

测试 API

现在我们已经准备好了一切,是时候测试我们的应用程序了!使用未经测试的代码就像打地鼠游戏:你修复了一个 bug,另一个 bug 马上就会出现。就个人而言,我是测试的大力支持者,我认为你也应该是一个。尽管测试需要最初的时间投入,但它将在开发的后期得到指数回报。

为了测试 API,我们将使用pytest,这是 Python 中单元测试的标准工具。我们将把测试模块放在api旁边,因此文件结构将如下所示:

.
├── api
│   ├── __init__.py
│   ├── main.py
│   ├── ml
│   │   ├── __init__.py
│   │   ├── model.joblib
│   │   └── model.py
│   └── tests
│       ├── api
│       │   ├── __init__.py
│       │   └── test_api.py
│       ├── conftest.py
│       ├── __init__.py
│       └── mocks.py
└── requirements.txt

我们要构建的第一件事是一个模拟的Model对象,这样我们的端点测试就不依赖于 scikit-learn。正如我所提到的,这是不可取的,因为我们希望将代码中的错误和外部代码中的错误分离开来。

这个类相对简单,完全模仿我们的api.ml.model.Model类的接口,但是基本上它不执行任何有意义的计算,并且返回随机数据。(尽管随机数据将在形状上匹配预期的输出。)

接下来,我们将根据pytest需求添加位于conftest.py模块中的测试配置。在我们的情况下,我们应该做两件事。

  1. 覆盖端点中使用的依赖注入,以使用一个MockModel对象来代替真实模型。
  2. 定义测试中使用的 fixtures,它们本身就是依赖注入。(我们很快会看到一个例子。)

首先,我们从我们的main模块导入实际的app对象。要覆盖对get_model()的依赖,我们只需提供一个新函数,并用新函数在app.dependency_overrides字典中设置适当的键。这段代码不会在部署期间执行,因此我们的依赖关系不会被意外覆盖,它是特定于测试的。接下来,我们准备一个 Starlette TestClient,它“允许你对你的 ASGI 应用程序做出请求”,一个非常方便的测试工具。这个定义意味着使用TestClient实例,我们可以向端点发送请求并接收响应,这正是我们想要测试的。

首先,我们用有效数据测试用户输入。为了看到它在多批量(从 1 到 9)下工作良好,我们添加了数据点的数量作为n_instances参数。在测试函数中遍历所有可能的大小被认为是不好的做法,因为如果它对某个特定的大小失败了,您会想知道它失败的确切位置。因此,我们可以使用@pytest.mark.parametrize装饰器,它为参数的每个值自动生成一个新的测试函数。在测试函数中,我们简单地生成一些假数据,并使用TestClient将其发送到应用程序。我们要检查两件事:1)响应代码是 200,这是 HTTP-okay 的说法 2)响应包含的预测与输入数据集的大小一样多。

然而,测试端点的正确输入数据是不够的。如果是这样,更重要的是确保我们的应用程序在出现不正确的数据时表现正常。这在下面介绍。

为了完整起见,我已经为predict_csv端点添加了测试,这些测试与之前的测试相似,所以我不再详述。

一旦测试准备好了,您就可以通过在 bash 中从项目的根目录执行pytest来运行它们。输出将如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

毕竟测试模块应该是这样的:https://github . com/cosmic-cortex/fastAPI-ML-quick start/tree/master/API/tests

打包您的应用程序

当应用程序经过适当的测试并在您的本地机器上正确运行时,就该将它打包成可移植的格式了。如果没有这一点,在另一台机器上设置它将是一个缓慢而痛苦的过程。为此,我们将使用 Docker。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Docker 架构。来源:https://docs.docker.com/engine/docker-overview/

Docker 将应用打包成镜像,镜像是自包含的应用,甚至是操作系统。它们由 Docker 容器运行,Docker 容器是隔离的执行环境。它们在原理上非常类似于虚拟机。尽管它们不像虚拟机那样提供严格的隔离,但当您第一次使用 Docker 时,这是一个很好的模型。

Docker 映像由Dockerfile定义,它基本上是 Docker 如何构建映像的一组指令。映像通常不是独立的,它们是从其他基础映像构建的。这些图像在 https://hub.docker.com 有它们自己的存储库,你可以在那里推送你的图像和拉取其他图像。打个比方,这些图像就像 git 存储库。使用基本映像就像分叉一个存储库,并将一些提交推到您自己的分叉上。

我们将使用包含 19.10 版本 Ubuntu 的ubuntu:19.10映像来打包我们的应用程序。(这是 Ubuntu docker 官方图片。)选择基础映像会显著影响后面的大部分工作流程。对于 Python 应用程序,基于 Alpine Linux 的映像也是一个很好的选择,Python 甚至有一些基于 Alpine 的官方映像。然而,将 NumPy 和某些机器学习库安装到基于 Alpine 的映像可能会很困难,所以我们将坚持使用 Ubuntu。

这是我们的 Dockerfile,包含在项目的根文件夹中。我们将一行一行地走一遍。

第一行描述了基本图像,如前所述是ubuntu:19.10。在构建时,这个映像从中央存储库中取出。完成后,Docker 将把./api文件夹复制到图像中。(每个映像都有自己的文件系统。)然后我们准备安装 Python3 以及 FastAPI 等所需的包。在图像内执行RUN后的命令。在这之后,我们正确地设置PYTHONPATH变量和工作目录。

为了服务于我们的应用程序,我们将向主机映像公开容器的端口 8000。出于安全原因,默认情况下不会这样做,您必须手动这样做。最后,我们告诉 Docker 在容器运行时要做什么:我们要启动uvicorn并为应用程序提供服务。ENTRYPOINT指定每次执行容器时将运行的命令,而CMD指定其参数。

图像本身可以用

docker build --file Dockerfile --tag fastapi-ml-quickstart .

命令。构建可能需要一段时间,但完成后,您可以使用

docker run -p 8000:8000 fastapi-ml-quickstart

在 run 命令中,您需要指定 Docker 将容器的 TCP 端口 8000 映射到主机中的同一个端口。如果您在浏览器中打开 http://localhost:8000 ,您可以看到应用程序正在运行,并且您可以正确地连接到它。

组合容器

在这个简单的例子中,我们的应用程序不依赖于其他服务,比如 Redis 或 PostgreSQL。在这种情况下,docker-compose可以用来组合容器。与Dockerfile类似,docker-compose 需要一个名为docker-compose.yaml的 YAML 配置文件来描述要启动哪些服务。

在这之后,只需执行

docker-compose up

从项目根目录。Docker compose 将在图像不可用时自动构建图像。我发现即使你只有一个容器,每次用这个手动调用docker builddocker run也要简单得多。

与 GitHub 动作的持续集成

维护良好的代码的支柱之一是持续集成。即使我们有测试,实际上也没有强迫程序员在提交变更之前使用它们。我们可以通过在某些触发条件下自动执行测试来解决这个问题,比如对特定分支的 push 和 pull 请求。这样,向共享代码库的主线推送更改可以比通常更快地完成。与旧的学校开发工作流程相比,当合并每周进行一次,并需要团队的大部分人员来监督时,通过适当的持续集成设置,代码交付可以由一个人完成,甚至每天几次。

在这个项目中,我们将使用 GitHub Actions,它允许您根据预定义的触发器自动执行操作。它要求您在 GitHub 托管的存储库的.github/workflows子目录中定义您的动作脚本。以下是该项目的 YAML 配置文件

如您所见,配置文件有两个主要部分:第二部分定义将要发生什么,第一部分定义何时发生。在这个例子中,我们希望脚本在对master分支的每个 push 和 pull 请求上执行。

动作本身是根据工作定义的,并给出了每个步骤。这个名为build的特定作业在 Ubuntu 实例中运行,如runs-on参数所示。首先它检查存储库,然后它使用docker-compose.test.yaml文件启动 Docker compose,这是专门为测试目的而制作的。

与我们之前使用的相比,这个 Docker compose 只有一行不同:它覆盖了fastapi-ml-quickstart容器的入口点,启动了pytest而不是uvicorn。完成后,容器退出,Docker 编写被中止,从fastapi-ml-quickstart容器返回退出代码。这些事情都不是docker-compose的默认行为,所以你要特别指示它这么做:

docker-compose -f docker-compose.test.yaml up --abort-on-container-exit --exit-code-from fastapi-ml-quickstart

就个人而言,我是 GitHub Actions 的忠实粉丝。它是非常通用的,你甚至可以用它将更新推送到产品中,在 PyPI 中发布,以及许多其他任务。它明显的缺点是只对 GitHub 用户开放。然而,也有替代者,例如 Jenkins、CircleCI、Travis CI、GitLab CI 等等。

包扎

在本指南中,我的目标是为机器学习应用程序构建一个小应用程序,并遵循最佳实践和使用现代工具对其进行适当的打包。但是,总有进步的空间!如果你有任何想法,欢迎在https://github.com/cosmic-cortex/fastAPI-ML-quickstart提出来!我希望你觉得这个指南有用。现在去开始构建令人敬畏的人工智能应用程序:)

如果你喜欢把机器学习概念拆开,理解是什么让它们运转,我们有很多共同点。看看我的博客,我经常在那里发表这样的技术文章!

如何在 Docker 容器中正确使用 GPU

原文:https://towardsdatascience.com/how-to-properly-use-the-gpu-within-a-docker-container-4c699c78c6d1?source=collection_archive---------1-----------------------

注意:我们也在博客上发布了如何在 Docker 中使用 GPU。在这篇文章中,我们将介绍在 Docker 容器中访问机器的 GPU 所需的步骤。

在你的机器上配置 GPU 可能非常困难。配置步骤会根据您机器的操作系统和 NVIDIA GPU 的种类而有所不同。更困难的是,当 Docker 启动一个容器时,它几乎是从零开始的。某些东西,比如 CPU 驱动程序是为你预先配置的,但是当你运行 docker 容器时,GPU 并没有被配置。幸运的是,您已经找到了这里解释的解决方案。它叫做 NVIDIA 容器工具包

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Nvidia 容器工具包(引文)

Docker 中的潜在错误

当您试图在 Docker 中运行需要 GPU 的容器时,您可能会收到以下任何错误。

错误:Docker 找不到 Nvidia 驱动程序

docker: Error response from daemon: Container command 'nvidia-smi' not found or does not exist..

错误:tensorflow 无法访问 Docker 中的 GPU

I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:150] kernel reported version is: 352.93
I tensorflow/core/common_runtime/gpu/gpu_init.cc:81] No GPU devices available on machine.

错误:pytorch 无法访问 Docker 中的 GPU

RuntimeError: cuda runtime error (100) : no CUDA-capable device is detected at /pytorch/aten/src/THC/THCGeneral.cpp:50

错误:keras 无法访问 Docker 中的 GPU

The TensorFlow library wasn't compiled to use FMA instructions, but these are available on your machine and could speed up CPU computations.

您可能会收到许多其他错误,表明您的 Docker 容器无法访问机器的 GPU。在任何情况下,如果您有任何类似上面的错误,您已经在这里找到了正确的位置。

首先,确保你的基本机器有 GPU 驱动程序

您必须首先在您的基本计算机上安装 NVIDIA GPU 驱动程序,然后才能在 Docker 中使用 GPU。如前所述,由于操作系统、NVIDIA GPU 和 NVIDIA GPU 驱动程序的分布过多,这可能很困难。您将运行的确切命令会因这些参数而异。这里有一些资源,你可能会发现在你的基本机器上配置 GPU 有用。

一旦你完成了这些步骤,通过运行 nvidia-smi 命令并查看如下输出,你就会知道你成功了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我已经成功地在我的谷歌云实例上安装了 GPU 驱动程序

现在,我们可以保证我们已经成功地保证 NVIDIA GPU 驱动程序安装在基础机器上,我们可以移动到 Docker 容器的更深一层。

接下来,向 Docker 公开 GPU 驱动程序

为了让 Docker 识别 GPU,我们需要让它知道 GPU 驱动程序。我们在图像创建过程中这样做。Docker 映像创建是一系列命令,用于配置 Docker 容器将要运行的环境。

强力方法— 强力方法包括您在基本机器上用来配置 GPU 的相同命令。当 docker 构建映像时,这些命令将会运行并在您的映像上安装 GPU 驱动程序,一切都会好的。在你的 docker 文件中,暴力方法看起来会像这样(代码归功于栈溢出):

FROM ubuntu:14.04
MAINTAINER Regan <[http://stackoverflow.com/questions/25185405/using-gpu-from-a-docker-container](http://stackoverflow.com/questions/25185405/using-gpu-from-a-docker-container)>RUN apt-get update && apt-get install -y build-essential
RUN apt-get --purge remove -y nvidia*ADD ./Downloads/nvidia_installers /tmp/nvidia                             > Get the install files you used to install CUDA and the NVIDIA drivers on your host
RUN /tmp/nvidia/NVIDIA-Linux-x86_64-331.62.run -s -N --no-kernel-module   > Install the driver.
RUN rm -rf /tmp/selfgz7                                                   > For some reason the driver installer left temp files when used during a docker build (i don't have any explanation why) and the CUDA installer will fail if there still there so we delete them.
RUN /tmp/nvidia/cuda-linux64-rel-6.0.37-18176142.run -noprompt            > CUDA driver installer.
RUN /tmp/nvidia/cuda-samples-linux-6.0.37-18176142.run -noprompt -cudaprefix=/usr/local/cuda-6.0   > CUDA samples comment if you don't want them.
RUN export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64         > Add CUDA library into your PATH
RUN touch /etc/ld.so.conf.d/cuda.conf                                     > Update the ld.so.conf.d directory
RUN rm -rf /temp/*  > Delete installer files.

强力方法的缺点— 首先,每次你重新构建 docker 镜像时,你都必须重新安装镜像,这会减慢开发速度。第二,如果您决定将 docker 映像从当前机器中取出,放到一台具有不同 GPU、操作系统的新机器上,或者您想要新的驱动程序,那么您将不得不每次都为每台机器重新编码这一步骤。这违背了建立码头工人形象的目的。第三,您可能不记得在您的本地机器上安装驱动程序的命令,并且在 Docker 中重新配置 GPU。

最佳方法— 最佳方法是使用 NVIDIA 容器工具包。NVIDIA 容器工具包是一个 docker 映像,它支持自动识别您的基本计算机上的 GPU 驱动程序,并在运行时将这些相同的驱动程序传递给您的 Docker 容器。因此,如果你能够在你的基本机器上运行 nvidia-smi ,你也将能够在你的 Docker 容器中运行它(并且你的所有程序将能够引用 GPU)。为了使用 NVIDIA Container Toolkit,您只需将 NVIDIA Container Toolkit 映像放在 Dockerfile 的顶部,就像这样— nano Dockerfile :

FROM nvidia/cuda:10.2-base
CMD nvidia-smi

这是你需要向 Docker 公开 GPU 驱动的所有代码。在该 docker 文件中,我们已经导入了 10.2 驱动程序的 NVIDIA 容器工具包映像,然后我们指定了一个在运行容器来检查驱动程序时要运行的命令。现在我们用 docker build 构建图像。-t 英伟达-测试:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

构建 docker 映像,并将其命名为“nvidia-test”

现在,我们通过使用命令docker run-GPU all NVIDIA-test 从映像运行容器。请记住,我们需要—GPU all,否则 GPU 不会暴露给运行的容器。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

成功!我们的 docker 容器看到了 GPU 驱动程序

从这个基础状态开始,您可以相应地开发您的应用程序。在我的情况下,我使用英伟达容器工具包来支持实验性深度学习框架。完整构建的 docker 文件的布局可能如下所示(其中/app/包含所有 python 文件):

FROM nvidia/cuda:10.2-base
CMD nvidia-smi#set up environment
RUN apt-get update && apt-get install --no-install-recommends --no-install-suggests -y curl
RUN apt-get install unzip
RUN apt-get -y install python3
RUN apt-get -y install python3-pipCOPY app/requirements_verbose.txt /app/requirements_verbose.txtRUN pip3 install -r /app/requirements_verbose.txt#copies the applicaiton from local path to container path
COPY app/ /app/
WORKDIR /appENV NUM_EPOCHS=10
ENV MODEL_TYPE='EfficientDet'
ENV DATASET_LINK='HIDDEN'
ENV TRAIN_TIME_SEC=100CMD ["python3", "train_and_eval.py"] 

上述 Docker 容器使用基础机器 GPU 基于规范训练和评估深度学习模型。相当酷!

在 Dockerfile 中需要不同的基础图像

假设您一直依赖 docker 文件中的不同基础映像。然后,你可以安装 NVIDIA 容器运行时

apt-get install nvidia-container-runtime
docker run -it --rm --gpus all ubuntu nvidia-smi

现在你可以用 nvidia 容器运行时运行其他基础镜像(这里我们运行 ubuntu 基础)。

NVIDIA 容器工具包的威力

现在,您已经编写了映像以通过基础机器的 GPU 驱动程序,您将能够从当前机器中提取映像,并将其部署到在您想要的任何实例上运行的容器中。

更新:需要 Docker 上的 CuDNN 和 NVCC cuda 工具包吗?

只有当你需要从其他 NVIDIA Docker 基础映像中获得cuDNNnvcc --version时,nvidia/cuda:10.2-base才会获得nvidia-smi.,即:nvidia/cuda:10.2-devel-ubuntu18.0.(获得 nvcc cuda 工具包)和nvidia/cuda:10.2-cudnn7-devel-ubuntu18.04.(获得 cuDNN)。

结论

恭喜你!现在,您知道如何使用 NVIDIA 容器工具包将 GPU 驱动程序暴露给正在运行的 Docker 容器。

想使用你的新 Docker 功能做一些很棒的事情吗?你可能会喜欢我们关于训练一个最先进的物体检测模型训练一个最先进的图像分类模型的其他帖子,或者只是通过查看一些免费的计算机视觉数据

如何保护您的数据免受未经授权的访问

原文:https://towardsdatascience.com/how-to-protect-your-data-from-unauthorized-access-bd74105d2ce4?source=collection_archive---------38-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

澳门图片社Unsplash 上拍摄的照片

数据保护是当今世界各地组织主要关注的问题之一。信息安全(InfoSec)主要是禁止未经授权访问信息,它使数据保护成为可能。

到 2020 年,安全信息和事件管理(SIEM)等安全服务和其他托管服务预计将占网络安全预算的近50。这意味着企业越来越重视网络安全,并实施更好、更强大的安全实践来防止攻击者或恶意内部人员的未授权访问。

您的数据是否足够安全,可以防止未经授权的访问?在本文中,让我们看看您可以做些什么来提高安全性。

防止未经授权的数据访问:帮助您提高网络安全的 9 个技巧

但首先,要学会收集相关数据,对其进行分析,并将其转化为可操作的情报资源。

您可以决定聘请第三方分析师来监控、利用和保护您的数据,或者让您的团队参加专业的分析课程来提高他们的知识。

这样,他们不仅可以依赖分析和数据安全工具,还可以保护和利用数据来做出有益的业务决策。

想要确保您的洞察力数据是 100%安全的吗?以下是我们帮助您防止未经授权的数据访问的建议:

1.保持所有安全补丁的最新状态

对于任何组织来说,防止未经授权的数据访问的第一步是更新所有的安全补丁。

原因如下:

安全补丁解决软件、操作系统、驱动程序等中的漏洞。,攻击者可能会利用它来访问您的设备和数据。Windows、Linux、Android、iOS 等操作系统的安全补丁是必不可少的,因为操作系统漏洞会带来严重后果。此外,随着新补丁的推出,不断更新驱动程序和软件应用程序。

WannaCry 病毒导致 150 个国家超过 40 万台计算机系统瘫痪,是近年来最严重的攻击之一。它攻击了 Windows 的 SMB V1(服务器消息块)协议中的漏洞,并通过使用 EternalBlue exploit 启动。

有趣的是,早在攻击发起之前,这些漏洞的安全补丁就已经存在了。但是有成千上万的用户没有更新他们的安全补丁,因此成为攻击的受害者。

通过使用更新的安全补丁,用户可以防止对系统攻击进行未经授权的访问。

请务必为您的操作系统和其他软件下载最新的安全补丁和更新,以保护其免受网络攻击。您还可以启用自动更新,以便每当发布安全修补程序或更新时,系统都会自动安装它。

通过保持准备和更新,您可以保护您的数据免受那些试图获得未经授权的访问。

2.快速检测和响应入侵

当然,您需要保持警惕,并做好准备防止黑客未经授权访问数据。

但是如果您无法检测到入侵呢?

前进的方向是什么?

您越早检测到入侵,就能越早做出响应。预防无疑是重要的,但是监控用户活动、登录尝试、日志和其他活动也可以让您了解系统的安全性。

有几种方法可以快速检测和响应入侵:

入侵检测系统/入侵防御系统

IDS 使用已知的入侵迹象或行为试探法来评估网络流量中的可疑活动。

入侵检测是监控和分析您的网络或系统中的活动的过程,以发现入侵事件的可能迹象,如即将发生的威胁、违规或对您的安全策略的威胁。

另一方面,IPS 通过主动监控系统的传入流量来识别恶意请求,对 IDS 起到了补充作用。IPs 通过阻止未授权或违规的 IPS、禁止恶意数据以及提醒安全人员注意潜在的安全威胁来防止入侵攻击。

安全事故事件经理

安全事故事件管理器(SIEM)是一种安全管理方法,使安全专业人员能够深入了解 IT 环境中的活动。SIEM 软件收集和分析公司技术基础设施生成的日志数据,从应用程序、主机系统、网络到安全设备。

然后,该软件会对事件和事故进行检测和分类,并对其进行分析。SIEM 主要有两个目标:

  • 跟踪记录并提供有关安全相关事件和事故的报告,例如失败和成功的登录尝试、恶意软件活动或任何其他可疑活动。
  • 如果检测到任何表明存在安全威胁的可疑活动,请通知安全人员。
  • 实施用户和事件行为分析(UEBA)
  • 为了防止未经授权的数据访问,您需要掌控您的分析游戏。

如果与用户的“正常”行为模式存在偏差,用户和事件行为分析有助于检测任何异常行为或实例。例如,如果用户每天定期下载 10MB 大小的文件,但突然下载千兆字节的文件,系统会检测到这种异常并立即向管理员发出警报。

用户和事件行为分析使用算法、统计分析和机器学习来确定与既定模式的偏差,显示哪些异常正在发生以及它们如何可能导致潜在威胁。通过这种方式,您可以得到关于未经授权的数据访问的警告。

此类分析侧重于您系统内的用户和实体,尤其是内部威胁,如可能滥用其权限实施有针对性的攻击或欺诈企图的员工。

3.实现最小特权原则(最小化数据访问)

最低特权是将帐户、用户和计算进程的访问权限限制为仅执行合法的日常活动所需的特定资源的做法。2019 年全球数据风险报告称,平均而言,一名员工可以访问 1700 万个文件。

实现最低特权可以帮助您保护数据免受未经授权的访问。最小特权原则(POLP)强制实施最低级别的用户权限,允许用户访问仅履行其角色所需的特定资源。它降低了被未经授权的用户、应用程序或系统利用的风险,而不会影响组织的整体工作效率。

虽然最小特权有助于仅为完成手头工作所需的特定资源提供权限,但它也实施更好的安全实践并降低您的组织成为网络攻击受害者的可能性。

4.使用多因素身份验证

对于公司来说,除了多因素身份认证之外,还必须通过实施强大的密码策略来使用强身份认证。这对于防止未经授权的数据访问大有帮助。

顾名思义,多因素身份认证要求用户提供多条信息,并在被授权访问系统之前由系统进行验证。这使得攻击者很难侵入用户的帐户,因为这比简单地破解密码需要更多的努力。

多因素身份验证可能使用通过带外通信渠道发送的一次性密码,例如自动电话呼叫或 SMS 文本消息发送给用户的授权设备、用户设置的安全问题或生物特征身份验证。虽然这使得身份验证有点麻烦,但它确保了更好的安全性,并迫使攻击者不仅要破解密码,还要破坏第二个因素。这使得攻击者破解身份验证变得更加困难。

想要一个专业的提示,以防止未经授权的访问您的数据?

利用密码。

虽然肯定应该使用多因素身份验证,但是您也可以使用通行短语来代替密码。密码短语是一系列随机单词或一个句子,单词之间也可以包含空格,如“十群大象经常在坦桑尼亚打保龄球!!"

密码短语不一定要语法正确;它可以是任意单词的组合,也可以包含符号。记住复杂的密码比记住复杂的密码更容易。仍然必须小心生成强有力的密码短语。只使用日常词汇的简单密码仍然很容易被破解。

5.实施 IP 白名单

另一种防止未经授权的数据访问的方法是通过 IP 白名单。

IP 白名单有助于限制和控制仅受信任用户的访问。它允许您创建可信和授权的 IP 地址列表,用户可以从这些地址访问您的网络。通常,公司通过一组定义好的 IP 地址使用互联网,因此他们可以添加一个允许访问的所有可信 IP 地址的列表。

通过将 IP 地址列入白名单,您可以仅向特定 IP 地址范围内的受信任用户授予访问特定网络资源(如 URL、应用程序、电子邮件等)的权限。

如果有人使用不受信任的 IP 地址试图访问您的网络,他们将被拒绝访问。IP 白名单还使组织能够保护对网络的远程访问,包括允许员工使用自己设备的自带设备(BYOD)。

6.加密系统内部的网络流量

通过加密网络流量,您可以确保它不会被窥探网络流量的攻击者截获。

然而,服务器间通信和数据中心内部的网络流量通常不加密。如果攻击者获得了对这种网络的访问权,他们就可以拦截多机集群中服务器之间传输的数据。

为了防止攻击者通过未经授权的访问窥探数据,组织越来越多地监控自己的网络流量以检测入侵。公司可能会在其监控系统中长时间存储网络流量的副本。

如果所有网络存储受隐私保护的数据,那么使用加密是至关重要的。这适用于授权用户从数据中心外部建立的访问系统的连接,以及多服务器系统中节点之间的网络链接。

您可以在用户和系统之间使用 VPN 层,或者实施 SSL/TLS 来加密网络流量。在系统内部,可以使用 IPsec、SSL/TLS 或其他 VPN 技术来保护通信。

7.加密静态数据

静态数据加密可确保数据安全存储,而不是以纯文本形式存储。当数据被写入磁盘时,它通过一组只有系统的授权管理员知道的秘密密钥被加密。

对这些密钥的访问受到限制和控制,以确保只有特权用户才能访问和使用加密数据。这种技术保护数据免受攻击者的攻击,攻击者可能试图获得对系统的远程访问,并保护数据不被破坏。

这是保护您的数据免受任何人未经授权访问的有效方法。静态加密需要对所有可能存储数据的地方进行适当的审计,比如缓存服务器或临时存储设备。

8.确保防恶意软件保护/应用程序白名单

恶意软件是最常见的网络攻击形式之一。事实上,每 13 个网络请求中就有 1 个会导致恶意软件。这是一个困扰众多计算机系统的严重问题,并且因出现在用户不知道的不显眼位置而臭名昭著。

恶意软件是设计用来在未经用户同意或授权访问的情况下攻击或渗透计算机的软件。特洛伊木马、计算机病毒、蠕虫、恶意软件和间谍软件是一些最常见的恶意软件攻击类型。它们可以出现在电子邮件和网站上,或者隐藏在附件、视频和照片中。

这种恶意软件很容易给黑客提供未经授权的数据访问。

反恶意软件保护非常重要,因为它为您的设备建立了安全基础。运行良好的防病毒程序,避免点击可疑的电子邮件或下载不明来源的附件,并定期扫描间谍软件。

或者,更强的控制是利用应用程序白名单。它可以非常有效地防止未经授权的数据访问。

这样,您就可以识别允许在您的计算机系统上运行的已知和可信的应用程序,并拒绝所有其他应用程序。即使有人获得未经授权的访问,如果该应用程序尚未被批准为白名单应用程序,他们也无法在您的系统上运行恶意软件。

9.跟踪和管理您的风险

风险可能是对项目的绩效、预算或时间表有潜在影响的任何事情。如果这些风险变得很大,它们就会成为必须解决的漏洞,以避免网络安全攻击。

组织以有效和及时的方式识别、分类、优先化和减轻风险是至关重要的。通过在风险升级之前跟踪它们,您可以防止它们成为问题。此外,您应该制定一个应对计划来立即应对风险。

最后的想法

数据保护不是一个线性过程或一次性活动。您需要不断投入资源、时间和精力来确保安全,防止未经授权的数据访问。

网络犯罪分子每天都在变得越来越先进,他们使用最新的技术来锁定组织并获得未经授权的数据访问。

随着数据泄露事件的增加,您需要提高警惕。您必须在企业中集成强大的安全措施,每位员工都必须将网络安全放在首位。

如果您想对您现有的安全实践进行快速安全审计,请告诉我们,我们将帮助您确保您受到良好保护,免受未经授权的数据访问和其他网络威胁。

关于作者:

Steve Kosten 是 Cypress Data Defense 的首席安全顾问,也是“Java/JEE 中的 SANS DEV541 安全编码:开发可防御应用程序”课程的讲师。

新冠肺炎期间如何保护自己的心理健康?

原文:https://towardsdatascience.com/how-to-protect-your-mental-health-during-the-covid-19-3840e4015435?source=collection_archive---------53-----------------------

该项目获得了加州大学戴维斯分校 MSBA 新冠肺炎挑战赛的二等奖和最有价值的数据集。这是由、【黄毅军】戴、凯拉邹王浩男合作完成的。python 编码的分步指导已经在 Github 分享:https://github.com/jennnh/4G_COVID-19_Challenge

概观

新冠肺炎疫情给人们的身体健康和福祉带来了极大的威胁。然而,许多精神疾病在不被注意的情况下被同时唤醒。在美国,每个人都面临着这场 COVID 危机中的精神健康问题,这是由工作机会消失、企业倒闭以及与朋友和家人分离引起的。更糟糕的是,前国会议员 Patrick J Kennedy 说,随着资源转移到新冠肺炎救援,自杀热线电话增加了 800%。

在这种情况下,这个项目旨在对隔离期间释放人们情绪紧张的活动提出详细的建议。具体来说,我们的团队首先在不同地区和日期的 Twitter 上收集标签为 #StayHome 的推文作为数据源。第二,我们利用情绪分析和词云来理解和可视化人们的情绪。第三,我们使用主题建模找到了 13 个与活动相关的主题,并将它们与其他专栏进行交叉分析,以确定导致人们积极和消极情绪的因素。最后,我们向人们提出了建议,告诉他们应该参加什么活动,应该避免什么活动来保持快乐。

网页抓取

首先,我们需要通过网络抓取从 Twitter 上抓取数据。我们没有使用 Twitter 的免费 API,因为它只提供过去 7 天内的推文,但我们从一个月前就需要推文了。因此,我们使用了一个名为“ GetOldTweets3 ”的包,它为我们的分析提供了足够多的 Tweets。

我们想选择一些有代表性的城市进行分析。为此,我们根据约翰·霍普斯金大学 2020 年 4 月 13 日的数据,选择了 10 个既有大量人口,又有大量确诊病例的城市进行刮痧。这 10 个城市是纽约市(纽约州)、波士顿(马萨诸塞州)、芝加哥(伊利诺伊州)、底特律(密歇根州)、洛杉矶(加利福尼亚州)、休斯顿(得克萨斯州)、纽瓦克(新泽西州)、迈阿密(佛罗里达州)、费城(宾夕法尼亚州)和新奥尔良(路易斯安那州)。

之后,我们搜集了这些城市附近发布的推文。对于每条推文,我们都收集了用户的姓名、文本、推文的日期和时间、转发次数、收藏夹数和标签。刮完数据后,我们还做了一个基于每个城市新增用户比例的分层抽样。新用户由用户是否第一次发布关于#StayHome 的帖子来定义。

探索性数据分析

拿到数据集后,我们开始做一些探索性的分析。我们收集的数据集包含 2020 年 3 月 5 日至 2020 年 4 月 11 日的推文,其中包括 11631 条推文和 6741 个独立用户。下图显示了不同城市的推文数量随时间的分布情况。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不同城市的推文数量

根据图表,在大多数城市,三月下旬左右推特数量会突然增加。这是大多数城市宣布避难所到位的时候。比如蓝线之后灰色区域大大增加,纽约刚刚宣布了命令。这意味着避难所到位的公告增加了人们对新冠肺炎的认识和关注,因此人们开始非常重视“呆在家里”,并在推特上更多地谈论它。几天后,推文的数量减少了,这表明人们开始不那么关注这个问题,他们习惯了呆在家里。

自然语言处理分析

文本预处理

在 EDA 之后,我们进行了文本预处理以提高 NLP 模型的性能,包括:

  • 让一切都变成小写。
  • 文本去收缩。例如,将“不会”替换为“不会”,将“有”替换为“有”,将“有”替换为“会”。
  • 移除奇怪的符号、网址、表情符号和#标签
  • 使用 NLTK 词干的单词词条化。词汇化是将一个词的不同屈折形式组合在一起的过程,这样它们就可以作为一个项目进行分析。例如,在词汇化之后,“哭”就是“哭”。

文本预处理前后的评论比较如下:

之前

A sunny day haiku #quarantinepoetry for an old friend down in Texas summerdaenen THANK YOU!!! VENMO @randsomnotes for a poem of your very own! #quarantinelife #stayhome #summer @New York, New York [https://www.instagram.com/p/B-29p1rp1la/?igshid=12yeaszfhp7o2](https://www.instagram.com/p/B-29p1rp1la/?igshid=12yeaszfhp7o2%27)

之后

A sunny day haiku  for an old friend down in Texas summerdaenen THANK YOU!!! VENMO @randsomnotes for a poem of your very own!    @New York, New York

情感分析

我们使用“Textblob”软件包为每条推文分配一个名为“极性”的情感分数,以衡量评论的积极或消极程度。之后,我们将情绪分为积极情绪和消极情绪,阈值为 0。极性分数大于 0 的推文是正面的,极性小于 0 的是负面的,极性等于 0 的是中性的。不同情绪的推文比例如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

根据图表,一半的推文是正面的,只有一小部分推文是负面的。这意味着没有多少人因为新冠肺炎而呆在家里做坏事。

我们还绘制了一个线形图来观察情绪如何随着时间的推移而变化,图表显示,人们在适应这种情况后开始感觉好一点了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一段时间内推特的平均情绪

世界云

为了了解负面推文和正面推文中最常见的词是什么,我们在这两个情绪类别中分别创建了两个词云。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

左:正世界云/右:负世界云

在删除这两个词云中的常用词后,我们可以看到积极的推文通常包含积极的词,如“安全”、“朋友”或“快乐”。还有像“视频”、“音乐”这样暗示积极活动的词。相反,在否定词云中,我们可以推断推文主要是在表达对生病的担忧,或者是抱怨在家待久了无聊。另外,“游戏”这个词也出人意料地出现在负面词汇 cloud 中。

主题建模

自然语言处理分析的第三部分是主题建模。首先,我们进一步预处理文本以提高主题建模的性能,包括:

  • 标记化:将每个句子标记成一个单词列表
  • 删除标点符号。
  • 使用 NLTK 库删除停用词。停用词是非常常见的词,如“如果”、“但是”、“我们”、“他”和“他们”。我们还在这个语料库的基础上增加了多个新的常用词。

在预处理之后,我们通过 Mallet 使用潜在的 Dirichlet 分配(LdaMallet)从所有 Tweets 中提取主题。首先,我们尝试了不同数量的主题,并使用一致性值来选择最佳数量的主题。在确定选择 30 个话题后,我们得到了每个话题的关键词,并筛选出了 13 个与人们的活动相关的话题进行进一步分析。

随后,我们结合情感分析和话题建模的结果,分析哪些话题有助于人们的积极情绪,哪些会导致消极情绪。更具体地说,我们计算了每个主题的平均极性,并将结果可视化在下面的树形图中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

显示 13 个活动相关主题的平均情绪的树形图

面积和颜色由每个话题的极性决定,也就是说面积越大越暗,话题越积极。因此,左上方的活动是最积极的活动,如观看视频、捐赠以及通过文字和消息进行交流。另一方面,右下角的活动是最不积极的,比如做饭和打扫房子。

除了话题的情绪,我们还分析了不同城市最受欢迎的活动。因此,我们根据与话题相关的推文数量,列出了每个城市排名前三的活动。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不同城市的前 3 项活动

根据图表,我们得到了几个有趣的发现:

  • 在许多城市,观看视频、锻炼和送货是受欢迎的活动。
  • 纽约人更喜欢与朋友和家人呆在一起,而洛杉矶人最喜欢看表演和电影。
  • 通过文字、信息和图片进行交流在波士顿非常流行。
  • 芝加哥人特别喜欢祈祷。

除了话题,我们还想了解更多影响人们感受的具体词汇,所以我们从这些话题中挑选了一系列高频词,并计算了包含每个词的所有推文的平均极性。条形图根据单词的极性对其进行排序。浅红色的单词是最积极的,然后是暗红色和灰色的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

包含关键词的所有推文的平均极性

与主题建模结果一致,观看视频、虚拟连接和去健身房与极其积极的情绪相关。此外,像唱歌、收快递、喝酒和祈祷这样的活动也是非常积极的。值得注意的是,“游戏”一词在条形图中排名最后,这与我们认为玩游戏有助于人们感觉更好的知识不一致。

推荐

基于对话题和单字的分析,我们给感到精神不适的人以下建议:

你可以花更多的时间在这些活动上:听歌、唱歌、看电影或电视剧、锻炼、阅读,以及虚拟地与你的家人和朋友联系,即使你在物理上是遥远的。

此外,根据我们的分析,这些活动对你的情绪非常有益:

  • 帮助他人,无论是分享免费食物还是捐款帮助。
  • 祈祷确实有助于释放你的情绪不适。
  • 网上订餐比做饭对你的情绪有更积极的影响,所以当你想享受美食时,可以考虑点外卖
  • 不要整天玩游戏。没有你想的那么积极。

如何修剪决策树以充分利用它们

原文:https://towardsdatascience.com/how-to-prune-decision-trees-to-make-the-most-out-of-them-3733bd425072?source=collection_archive---------25-----------------------

用可视化来解释。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

加里·本迪格在 Unsplash 上的照片

决策树是受监督的机器学习算法,通过迭代地将数据集划分为更小的部分来工作。划分过程是构建决策树的最关键部分。

分区不是随机的。目的是在每次分区时尽可能提高模型的预测性,以便模型不断获得有关数据集的信息。

例如,下面是一个深度为 3 的决策树。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

深度为 3 的决策树(图片由作者提供)

第一个分区基于特征 6 (X[6]),并且能够将属于第一类(59)的所有数据实例放在树的右侧。

这清楚地表明,最大化信息增益的分区被优先考虑。信息增益可以用熵或基尼系数来量化。一般来说,信息增益与纯度的增加(或杂质的减少)成正比。

节点的纯度与该节点中不同类的分布成反比。

考虑这样一种情况,您选择一个数据实例并随机标记它。基尼系数衡量你的随机标签出错的频率。如果所有数据点都有相同的标签,那么标签总是正确的,基尼系数将为零。另一方面,如果数据点平均分布在多个标签中,随机标签通常是不正确的。因此,基尼系数随着随机性的增加而增加。

熵是不确定性或随机性的另一种度量。一个变量的随机性越大,熵就越大。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

熵 vs 随机性(图片由作者提供)

选择产生更纯节点的分区。因此,当选择一个特征来划分数据集时,决策树算法试图实现:

  • 更多的预测
  • 杂质少
  • 低熵

决策树需要仔细调整,以充分利用它们。太深的树可能会导致过度拟合。Scikit-learn 提供了几个超参数来控制树的生长。

我们将看到这些超参数是如何使用 scikit-learn 的 tree 模块的 plot_tree 函数实现的。

我将使用 scikit-learn 的 datasets 模块下的 wine 数据集。让我们首先导入库并加载数据集。

import numpy as np
import pandas as pdfrom sklearn import tree
from sklearn.datasets import load_wineimport matplotlib.pyplot as plt
%matplotlib inlineX, y = load_wine(return_X_y=True)

数据集包括属于 3 个不同类别的 178 个观察值。有 13 个特征描述了观察结果。

X.shape
(178,13)np.unique(y, return_counts=True)
(array([0, 1, 2]), array([59, 71, 48]))

我们现在可以开始用不同的超参数值构建决策树。最明显的一个是 max_depth,它在指定的深度级别停止树的生长。

clf = tree.DecisionTreeClassifier(criterion='gini', max_depth=2)\
.fit(X, y)plt.figure(figsize=(16,8))
tree.plot_tree(clf, filled=True, fontsize=16)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

深度为 2 的决策树(图片由作者提供)

基于 Gini 杂质选择分区,并且树的深度是 2。Max_depth 提供了一种简单的方法来控制树的增长,这在更复杂的情况下可能是不够的。

min_samples_split 指定节点中要进一步分割的最小样本数。

clf = tree.DecisionTreeClassifier(criterion='gini', min_samples_split=10).fit(X, y)plt.figure(figsize=(20,8))
tree.plot_tree(clf, filled=True, fontsize=16)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

min_samples_split=10(图片由作者提供)

我只放了一部分可视化,我们可以看到当前超参数的效果。右边的节点没有进一步分割,因为其中只有 5 个样本。如果没有 min_samples_split=10,它将被进一步拆分如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(图片由作者提供)

控制树生长的另一个超参数是 min _ infinity _ decrease,它设置杂质减少的阈值以考虑分区。这是一个比最大深度更好的方法,因为它考虑了分区的质量。

clf = tree.DecisionTreeClassifier(criterion='gini', min_impurity_decrease=0.1).fit(X, y)plt.figure(figsize=(10, 6))
tree.plot_tree(clf, filled=True, fontsize=16)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

min _ 杂质 _ 减少=0.1(图片由作者提供)

所有隔板都实现了超过 0.1 的杂质减少。在设置这个值时,我们还应该考虑标准,因为基尼系数杂质和熵具有不同的值。

max_leaf_nodes 也可以用来控制树的生长。它限制了决策树可以拥有的叶节点的数量。叶节点是决策树末端的节点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

决策树的结构(图片由作者提供)

该树以最佳优先的方式不断增长,直到达到最大数量的叶节点。基于杂质的减少来选择最佳分区。

clf = tree.DecisionTreeClassifier(criterion='gini', max_leaf_nodes=5).fit(X, y)plt.figure(figsize=(14, 8))
tree.plot_tree(clf, filled=True, fontsize=16)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

max_leaf_nodes=5(图片由作者提供)

我们已经介绍了 5 种不同的超参数,它们可以用来控制树木的生长。

  • 标准
  • 最大深度
  • 最小 _ 样本 _ 分割
  • 最小 _ 杂质 _ 减少
  • Max_leaf_nodes

我们对它们逐一进行了调整,以查看各自的效果。然而,在现实生活中,这些超参数需要一起调整,以创建一个稳健和准确的模型。

如果我们过多地种植一棵树,我们很可能会有一个过度适应的模型。当一棵树与训练集拟合得太好时,就会发生过度拟合。在训练集和测试集上具有非常不同的精确度是过度拟合的强烈指示。在这种情况下,我们应该控制树的生长以获得一个通用的模型。

感谢您的阅读。如果您有任何反馈,请告诉我。

如何发布闪亮的应用程序:以 shinyapps.io 为例

原文:https://towardsdatascience.com/how-to-publish-a-shiny-app-example-with-shinyapps-io-ec6c6604d8?source=collection_archive---------20-----------------------

查看如何使用 shinyapps.io 在线部署和发布闪亮应用的分步指南(带截图)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

介绍

病毒导致许多人创建了交互式应用程序和仪表盘。一位读者最近问我如何发布她刚刚创建的闪亮应用。类似于之前的一篇文章,我向展示了如何在 GitHub 上上传 R 代码,我认为这对一些人来说是有用的,看看我是如何发布我闪亮的应用程序的,这样他们也可以这样做。

在完成在线部署闪亮应用程序所需的不同步骤之前,您可以在这里查看我的应用程序的最终结果。

注 1:截图都是在 MacOS 上拍的,没有在 Windows 上测试过。请在评论中告诉我它在其他操作系统上是否相似。

注 2:有其他方法可以发布你的应用程序(比如用 Docker),但下面显示的方法(在我看来)很简单,而且效果很好。

先决条件

我个人使用 shinyapps.io 平台来部署我的闪亮应用。因此,为了遵循这个指南,你首先需要创建一个帐户(如果你还没有)。

他们提供免费计划,但你被限制在 5 个活动应用程序和每月 25 个活动小时的使用。

供你参考,如果你让你的应用程序面向广泛的受众,预计会很快超过每月活跃时间的上限。要增加每月限额(或发布 5 个以上的应用程序),您需要将您的计划升级为付费计划。

逐步指南

下面是图片中要遵循的步骤。

第一步:打开 RStudio 并创建一个新的闪亮应用程序:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第二步:给它一个名字(没有空格),选择保存它的位置,然后点击创建按钮:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第三步:以同样的方式,当你打开一个新的 R Markdown 文档时,一个基本的闪亮应用程序的代码就创建好了。单击运行应用程序按钮运行应用程序,查看结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 4:基本应用程序打开,发布它:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第五步:如果这是你的第一个闪亮的应用程序,“从账户发布”框应该是空的。点击“添加新帐户”链接您刚刚创建的 shinyapps.io 帐户:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第六步:点击第一个备选项(ShinyApps.io):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第七步:点击你的 ShinyApps 账户链接:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第 8 步:单击仪表板按钮登录您的帐户:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第九步:点击你的名字,然后点击代币

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 10:如果这是你的第一个应用程序,应该还没有创建令牌。通过单击“添加令牌”按钮创建一个。然后点击显示按钮:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第 11 步:点击显示秘密按钮:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第 12 步:现在代码完成了(不再隐藏任何东西)。点击复制到剪贴板按钮:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 13:复制代码并点击 OK 按钮:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 14:返回 RStudio,将代码粘贴到控制台中并运行它:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

您的计算机现在已被授权将应用程序部署到您的 shinyapps.io 帐户。

第 15 步:返回到可以发布应用程序的窗口,选择一个标题(不带空格)并点击发布按钮:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 16:几秒钟后(取决于你的应用程序的重量),闪亮的应用程序应该出现在你的互联网浏览器中:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第 17 步:你现在可以编辑应用程序(或者用你的另一个应用程序替换整个代码),点击运行应用程序按钮再次运行应用程序。对于这个示例,我只是在侧面板中添加了一个链接以获取更多信息:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 18:检查修改是否被考虑(链接如预期出现在侧面板中)并重新发布你的应用程序:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第 19 步:点击发布按钮:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第 20 步:你的应用程序是活的!您现在可以共享它,每个拥有该链接的人都可以使用它:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

附加注释

您的应用程序的设置

如果您需要更改您的 Shiny 应用程序的设置,请转到您的 shinyapps.io 仪表板,然后单击您刚刚创建的应用程序来访问设置:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

查看位于窗口顶部的选项卡中的不同设置,并查看 URL 字段旁边的应用程序链接:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

发布数据集

通常情况下,你的闪亮应用程序使用一个默认情况下没有加载到 R 中的数据集(例如,它使用一个保存在本地计算机上的数据集)。

要使应用程序处理您的数据,您还需要在发布应用程序时发布数据(选中与您的数据对应的复选框):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将数据集与应用程序一起发布

如果您希望拥有更大的灵活性,在应用程序中使用外部数据集的另一种方法是在线托管它:

  • 如果你有一个网站,你可以很容易地通过你的网站发布
  • 如果你没有网站,你可以通过 GitHub 托管数据集(如果你没有账户,现在是创建一个的好时机!)

最后一步是通过新的 URL 导入数据(将数据导入到应用程序的代码中)。

感谢阅读。我希望这篇教程能帮助你发布你的第一个闪亮的应用。

和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。

相关文章

原载于 2020 年 5 月 29 日 https://statsandr.com

如何使用 Python 请求从 API 中提取数据

原文:https://towardsdatascience.com/how-to-pull-data-from-an-api-using-python-requests-edcc8d6441b1?source=collection_archive---------0-----------------------

技术应用编程接口指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从 API 中自动检索数据至关重要。

我被反复要求做的事情是从 API 中自动提取数据。尽管我拥有“数据科学家”的头衔,但我在一个小团队中,所以我不仅负责构建模型,还负责提取数据、清理数据,以及将数据推送到任何需要的地方。你们中的许多人可能都在同一条船上。

当我第一次开始学习如何发出 HTTP 请求、取回 JSON 字符串、解析它,然后将它推入数据库时,我很难找到清晰、简洁的文章来解释如何实际完成这项非常重要的任务。如果你曾经为了解决一个技术问题而陷入谷歌黑洞,你可能会发现非常技术化的人喜欢使用技术语言来解释如何执行给定的任务。问题是,如果你像我一样是自学的,你不仅要学习如何完成要求你做的任务,还要学习一门新的技术语言。这可能会令人非常沮丧。

如果你想避免学习技术术语,直接切入正题,那你来对地方了。在本文中,我将向您展示如何从 API 中提取数据,然后自动执行每 24 小时重新提取数据的任务。对于这个例子,我将利用 Microsoft Graph API 并演示如何从电子邮件中提取文本。我将避免使用预先准备好的 API 包,而是使用 Python Requests 包来处理 HTTP 请求——这样,您就可以将您在这里学到的知识应用到您需要使用的几乎任何其他 RESTful API 上。

如果你在本教程中遇到 API 请求的问题,这里有一个提示:使用邮递员。Postman 是一个非常棒的应用程序,它允许你通过一个干净的界面来设置和调用 API。它的美妙之处在于,一旦您让 API 调用工作,您就可以用 Python 导出代码,然后将其直接粘贴到您的脚本中。太神奇了。

*注意:本教程旨在提供一种简单易懂的访问 API 的方法,仅此而已。它可能无法满足您的具体情况或数据需求,但应该有望让您走上正确的道路。我发现下面的方法是最容易理解的快速获取数据的方法。如果你有让事情变得更简单的建议,请在评论中提出来。

API 文档

没有办法浏览 API 文档。要使用 Outlook,您需要到这里。如果您成功地完成了本教程,并希望使用 API 做更多的事情,请使用该链接作为参考。

授权

大多数 API,包括 Microsoft Graph,在给你一个允许你调用 API 的访问令牌之前都需要授权。对于不熟悉从 API 中提取数据的人来说,这通常是最困难的部分(对我来说就是这样)。

注册你的应用

按照这里的说明注册你的应用(这些很简单,使用 Azure GUI ),你需要一个学校、工作单位或个人的微软账户来注册。如果你使用工作邮件,你需要 Azure 实例的管理员权限。如果你是为了工作而这样做,请联系你的 IT 部门,他们可能会为你注册该应用程序。选择“web”作为你的应用类型,并为你的重定向 URI 使用受信任的 URL(只有你有权访问底层 web 数据的 URL)。我使用了 franklinsports.com,因为只有我的团队可以访问那个网站的数据。如果您正在构建一个应用程序,您将重定向到您的应用程序,在那里您的应用程序可以获取代码并授权给用户。

启用 Microsft 图形权限

应用注册后,请转到应用注册门户:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

点按显示您的应用名称的位置:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在接下来的页面中,单击“查看 API 权限”。

最后,选择 Microsoft Graph,然后选中“委托权限”消息下的所有复选框(注意,在本例中,我将只从单个登录用户处获取电子邮件,要获取某个组织的电子邮件数据,您需要应用程序权限,请遵循此处的流程)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好了—您已经准备好开始进行 API 调用了。

授权步骤 1:获取访问代码

您将需要一个访问代码来获得访问令牌,这将允许您调用 MS Graph API。为此,请在您的浏览器中输入以下 URL,用您的应用程序页面上显示的信息交换相应的凭据。

放在 URL 中:

将代码片段输出的 URL 粘贴到您的浏览器中。点击回车键,你将被要求授权你的微软账户进行授权访问。使用您用来注册应用程序的 Microsoft 帐户。

如果授权不起作用,则您选择的重定向 URL 或应用程序注册有问题。我以前在这一部分遇到过麻烦——所以如果你第一次尝试没有成功,不要担心。如果授权成功,您将被重定向到您在应用程序注册中使用的 URL。追加到 URL 的参数将包含您将在下一步中使用的代码,它应该是这样的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

获取完整的代码,并将其保存在 python 脚本中。

授权步骤 2:使用您的访问代码获取一个刷新令牌。

在继续之前,确保您已经安装了最新版本的 Python 请求包。最简单的方法是使用 pip:

在这一步中,您将使用步骤 1 中生成的代码,并向 MS Graph OAuth 授权端点发送一个 POST 请求,以获取一个刷新令牌。(*注意:出于安全考虑,我建议将 client_secret 存储在不同于用于调用 API 的脚本中。您可以将这个秘密存储在一个变量中,然后导入它(或者使用 pickle,您将在下面看到)。

将代码片段中的######与您自己的应用程序信息和您在步骤 1 中收到的代码交换,然后运行它。(*注意:重定向 URI 必须是 url 编码的,这意味着它看起来像这样:“https % 3A % 2F % 2 ffranklinsports . com”)

您应该会收到类似如下的 JSON 响应:

{ ’ access _ token ‘:’ # # # # # # # # # # # # # # # # # #,’ refresh _ token ‘:’ # # # # # # # # # # # # # # # ’ }

授权步骤 3:使用您的刷新令牌获取访问令牌

此时,您已经有了一个访问令牌,可以开始调用 API,但是,该访问令牌将在一段时间后过期。因此,我们希望设置我们的脚本,在每次运行它时获取一个新的访问令牌,这样我们的自动化就不会中断。我喜欢将步骤 2 中的新 refresh_token 存储在 pickle 对象中,然后在脚本运行时加载它以获得新的 access_token:

filename = ####path to the name of your pickle file#######
print(filename) 
filehandler = open(filename, ‘rb’) 
refresh_token = pickle.load(filehandler)url = “https://login.microsoftonline.com/common/oauth2/v2.0/token" payload = “””client_id%0A=##########& redirect_uri=##################& client_secret=##################& code={}& refresh_token={}& grant_type=refresh_token”””.format(code,refresh_token) 
headers = { ‘Content-Type’: “application/x-www-form-urlencoded”, ‘cache-control’: “no-cache” } response = requests.request(“POST”, url, data=payload, headers=headers)
r = response.json() 
access_token = r.get(‘access_token’) 
refresh_token = r.get(‘refresh_token’) with open(filename, ‘wb’) as f: 
      pickle.dump(refresh_token, f)

调用 API 并清理和解析 JSON

有了 access_token,就可以调用 API 并开始提取数据了。下面的代码片段将演示如何检索最近 5 封带有特定主题参数的电子邮件。将 access_token(下面加粗)放在头中,并在 get 请求中将其传递给电子邮件消息端点。

import json
import requestsurl = ‘[https://graph.microsoft.com/v1.0/me/messages
$search=](https://graph.microsoft.com/v1.0/me/messages?$search=)"subject:###SUBJECT YOU WANT TO SEARCH FOR###”’headers = {
 ‘Authorization’: ‘Bearer ‘ +**access_token**,
 ‘Content-Type’: ‘application/json; charset=utf-8’
 }r = requests.get(url, headers=headers)files = r.json()print(files)

上面的代码将返回一个包含您的数据的 json 输出。

如果你想要 5 封以上的邮件,你需要对结果进行分页。大多数 API 都有自己的方法来实现结果的最佳分页(在英语中,大多数 API 不会只通过一次 API 调用就提供您想要的所有数据,所以它们提供了进行多次调用的方法,允许您在结果中逐块移动,以获得您想要的全部或尽可能多的数据)。MS Graph 很好,因为它提供了获取下一页结果所需的确切端点,使分页变得容易。在下面的代码片段中,我演示了如何使用 while 循环对 api 进行连续调用,并将每封电子邮件的主题和文本添加到列表列表中。

emails = []
while True:
 try:
   url = files[‘[@odata](http://twitter.com/odata).nextLink’]
   for item in range (0,len(files[‘value’])):
     emails.append(files['value'][item]['Subject'],[files[‘value’]     [item][‘bodyPreview’])
   r = requests.get(url, headers=headers)
   print(r.text)
   files = r.json()
 except:
   break

把数据放在某个地方

最后,我将展示一个例子,展示如何将 JSON 数据放入 CSV 文本文件,然后可以用 excel 对其进行分析或将其放入数据库。这段代码将演示如何将我们的列表中的每一行写入一个 CSV 文件。

import csv write_file =‘###LOCATION WHERE YOU WANT TO PUT THE CSV FILE###’
 with open(write_file,’w’, newline = ‘’) as f:
   writer = csv.writer(f, lineterminator = ‘\n’)
   writer.writerows(emails)

使自动化

既然我们的剧本已经写好了。我们希望将其自动化,这样我们就可以在每天收到新消息时,在我们的参数范围内获取它们。

我用两种方法做到了这一点,然而,还有许多自动化的方法:

  1. 在 Ubuntu 服务器上使用 Crontab

这很简单。如果你用的是 Ubuntu,在你的控制台上输入“crontab -e ”,它会在一个文本文件中打开你的 cronjobs。转到新的一行,键入:

0 1 * * * /full path to python environment/python /full path to file/example.py

假设 cron 设置正确,上面将脚本设置为每天在 1 UTC 自动运行(或者服务器所在的时区)。您可以通过更改代码中的 1 来更改时间。如果你想了解 cron 计时的复杂性,这个网站是一个不错的资源。

2.使用 Windows 任务调度器

这是在使用任务计划程序的 windows 中实现自动化的一种简单又好的方法。只需打开任务计划程序,然后单击右侧的“创建任务”。这个应用程序非常简单,允许你使用 GUI 设置时间表和你想运行的程序。

当您在“操作”中感到痛苦时,选择 Python 作为程序,然后在“添加参数”选项卡(旁边带有“(可选)”的选项卡)中,将路径放入您的。py 文件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

就是这样!

在本演练中,我向您展示了如何从 Microsoft Graph API 中提取电子邮件数据。这里演示的原则可以用于几乎任何 RESTful API,或者使用 Microsoft Graph 执行更复杂的任务(我已经使用 MS Graph API 将文件推入和推出我们公司的 sharepoint,将 sharepoint 文件夹中的数据推入我们的数据库,以及发送自动电子邮件和报告)。

有问题或意见吗?你可以给我发电子邮件,地址是 cwarren@stitcher.tech,或者在 Linkedin 上关注我,地址是https://www.linkedin.com/in/cameronwarren/

我还提供数据服务,你可以在 http://stitcher.tech/了解更多。

如何量化数据质量?

原文:https://towardsdatascience.com/how-to-quantify-data-quality-743721bdba03?source=collection_archive---------9-----------------------

入门

从单独的数据质量指标到统一的分数。

在本文中,我将解释计算统一数据质量分数背后的概念,因为它在IBM Cloud Pak for DataIBM Information Server/Information Analyzer中用于量化结构化数据的质量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图卡皮克关于 https://pixabay.com/users/tookapic-1386459/的图片

需要一个简单的数据质量分数

衡量数据质量并不是一个新领域。 IBM Information Analyzer 和其他数据分析工具已经上市十多年了,帮助数据工程师更好地了解他们的数据中有什么,以及他们可能需要修复什么。
在数据概要分析的早期,尽管这些工具可以提供丰富的功能来查看数据集的质量,但回答这些简单的问题并不容易:

这个数据集的整体质量有多好?

这两个数据集哪个数据质量更好?

与上月相比,该数据集的数据质量如何?

即使像早期一样使用单一的数据分析工具,如 IBM Information Analyzer,您也可以通过使用不同的特性从完全不同的角度来评估数据集的质量:

  • 您可以使用数据探查器收集的统计信息来确定在数据集中检测到的哪些值或格式应该在每一列中被视为有效或无效。
  • 您可以将每一列的域有效性定义为有效值的最小/最大范围,或者将它指向一个引用值列表。
  • 您可以为每一列检测或分配数据类,并搜索与预期数据类不匹配的值。
  • 您可以查看缺失的值。
  • 您可以识别主键候选项并搜索意外的重复值。
  • 您可以识别表之间的主键-外键(PK-FK)关系,并在外键列中搜索在该关系的主键中找不到的孤立值。
  • 您可以定义数据规则来设置对数据的任何非平凡的额外期望。

此列表仅涵盖了信息分析器的数据分析和质量特性可以告诉您的数据。 IBM Information Server 套件的其他组件,如 QualityStage 可以为您提供其他数据质量信息,如重复的行,或缺乏适当标准化的值等

尽管这些特性本身都很强大,并且可以为专家提供有趣的单个指标,但是它们的结果并不适合回答本文引言中列出的简单问题。其主要原因是人类不擅长相互比较多维度量,特别是如果那些结果不包括完全相同的度量,或者是从具有不同数量的行、列的不同数据集计算的,或者具有它们应该匹配的不同约束/规则。

随着数据湖、数据科学、数据治理和所有这些围绕数据的新型活动的出现,数据目录变得越来越重要,数据质量变得不仅对专家用户重要,而且需要让非专家也能理解。

在之前的文章中,我展示了如何自动获取、分析、编目、管理大量数据集,并提供给数据科学家或数据分析师等消费者。这些用户需要在自助服务模式下找到具有正确质量的正确数据集。在这种情况下,很明显需要一个更简单的指标来更好地了解数据集的质量水平,而不必查看细节,即使这些细节在第二次查看时仍然可用。

这就是为什么数据质量的概念在 IBM Information Server 和现在的IBM Cloud Pak for Data/Watson 知识目录中引入的原因。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据质量分数显示在数据 UI 的云包中

但是如何设计一个好的数据质量评分呢?

考虑到数据质量可以从非常不同的角度来看,并且可以用非常不同的度量标准来衡量,例如我前面列出的几个度量标准,计算质量分数的公式不一定是显而易见的。为了更好地理解它在 IBM 产品中是如何计算的,让我们先来看看我们对这样一个分数的要求:

  1. 数据质量分数应该简单易懂:当查看目录中的大量数据集时,应该可以快速识别高质量或低质量的数据集,而不必查看细节。
  2. 数据质量分数应该不依赖于数据集上设置的行数、列数或约束条件:例如,如果通过分析数据集的所有行来计算,就像在较小的样本上计算一样,则大型数据集的数据质量分数应该或多或少是相同的——假设采样足够好,足以具有统计代表性。
  3. 数据质量分数应该与其他数据质量分数具有可比性,即使每个分数使用的指标不同和/或比较的数据集具有不同的行数和列数——请参见前面的要求。
  4. 数据质量得分应该是标准化的:它应该提供一个清晰的最低和最高可能得分的范围,以便用户可以看到数据集的数据质量离理想值有多远。

为了定义一个公式,将各种数据质量函数计算出的不同指标转换为符合这些要求的分数,我们首先需要将我们所理解的数据质量(一般而言)和数据质量分数(具体而言)的概念形式化。

数据质量有许多定义。你可以在维基百科上看到其中的一些。但是一个简单的定义可以是:

衡量数据集的数据质量就是衡量数据集与您对数据的期望的匹配程度。

这意味着数据质量分数只能取决于您对数据的期望,而不是一些原始的调查结果。

这听起来可能是显而易见的,但这意味着,如果我们在一列中发现大量缺失值,但我们确实期望该列中有缺失值,或者我们不关心那里的缺失值,那么数据集的数据质量分数不应因发现的缺失值而降低。

这也意味着,如果我们对数据没有具体的期望,那么数据质量分数应该是最大的,不管数据中有什么。

这些简单明了的事实对于建立乐谱的架构非常重要。

约束的概念和数据质量问题

让我们定义几个在数据质量分数计算中起重要作用的概念:

我们对数据的期望就是我们所说的约束。约束可以用非常不同的形式表示:

  • 它可以是在列上设置的简单标志,以指示该列中的值不应该为空,或者应该是不同的,或者不应该是有符号的。
  • 它可以是列的域有效性的定义,设置为最终的最小或最大允许值,或者是指向定义列的可接受域的参考值列表的指针
  • 它可以是分配给列的数据类,不仅描述列的内容,还可以用于识别不符合列的预期域的值。
  • 它可以是两个数据集之间的标识关系,设置多个列之间的相关性或函数依赖关系。
  • 它可以是一个数据规则,表达一个非平凡类型的约束,甚至可能涉及多个表。

只要数据不满足其中一个约束条件,我们就会遇到数据质量问题。

一个数据质量问题是一个特定的数据质量问题类型的报告,或者是一个数据集的一个单元格,或者一行,或者一列或者一组列,或者是整个数据集。数据质量问题报告的数据质量问题类型取决于数据不满足的约束类型。

数据质量问题可以在列或数据集上以一定的频率检测到。相对频率,计算为有质量问题的列/数据集的所有值的百分比,我们称之为问题的普遍性

例如,如果数据集有 100 行,并且在标记为强制或不可空的列中检测到 15 个缺失值,则在此列上报告问题类型 *【缺失值】*的数据质量问题,其发生率15%

隐式或显式约束以及数据质量问题的置信度概念

除了流行度之外,数据质量问题可能与置信度相关联。置信度表示报告的问题是真实问题的概率。

为了更好地理解这一概念,您需要理解,并非所有对数据设置的约束都是由人指定或确认的明确约束——我们将这种指定或确认的约束称为显式约束

如果数据质量仅基于显式约束来衡量,那么我们就不需要置信度的概念,因为所有由人指定的约束,如果不被某些数据所尊重,就会导致 100%置信度的数据质量问题——我们肯定知道这个问题是一个真实的问题,因为有人已经指定任何不满足这个约束的东西都应该被认为是数据质量问题。

但是,如果我们只查看显式约束,那么所有数据集都将以 100%的分数开始,直到有人花时间查看它并指定约束。这将导致大量数据集出现高质量的假象,或者导致需要管理员仔细检查每个摄取的数据集的过程,这对于大规模导入来说不太适合。

因此,在数据质量分析期间,系统可能会根据数据中看到的内容,尝试猜测一些约束条件。例如,如果一列的大部分数据不为空,或者它们使用相同的格式或者具有任何类型的可识别模式——即使一些值不遵循这些模式——那么系统可以假设存在隐含约束,并且不满足该约束的值可能是数据质量问题。

由于一个隐含约束是由系统从数据中看到的推断出来的,它与一个置信度的概念相关联,确定系统有多确定这应该是一个真实约束。

例如,如果一列中 95%的值是 5 位数,但是 5%的值具有完全不同的格式,则系统可以——根据设置——假设在该列上有一个隐式约束,即值应该具有 5 位数,置信度为 95%。如果用户检查这个隐式约束并确认它,那么它将成为一个显式约束**,其置信度为 100%。**

检测到的质量问题的普遍性和可信度将用于计算实际质量分数。

将它们放在一起形成一个统一的质量分数

既然我们已经介绍了在数据质量分数中起作用的所有重要概念,让我们看一个简单的例子,看看如何在 IBM Cloud Pak for DataInformation Analyze r:

让我们假设一个简单的数据集,有 3 列 6 行,以及以下确定的数据质量问题:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

已识别的数据质量问题及其可信度

  • 第 1 行违反了数据规则。由于数据规则是由用户指定的,所以它是一个显式约束,问题的置信度100%
  • 行#3 是一个重复行,但是没有明确的约束表明不允许重复行。但是,根据数据,分析确定有 70%的可能性该数据集不应该出现重复行。= >数据集上有一个隐含约束,用 70%的置信度表示不应该有任何重复记录。
  • 第 2 行第 1 列的单元格不满足隐含约束,其置信度为 80% 定义了有效域应该是什么。例如,如果分析确定该列的推断数据类的置信度为 80%,并且该单元格中的值与该数据类不匹配,则可能会出现这种情况。
  • 列 Col 2 已经设置了一个显式约束,表示该列中的所有值都应该不同,但是分析发现其中有 20%的重复值。这导致了一个数据质量问题,其置信度为 100%发生率为 20%
  • 除此之外,行#4 中第 2 列的值缺失,并且存在置信度为 90%隐含约束,即该列中不应出现缺失值。
  • 最后,第 5 行/第 3 列的单元格似乎是该列的异常值,其置信度为 60%** 。离群值总是隐含的约束,因为没有硬性的规则来定义一个值何时是离群值。**

单个细胞的数据质量得分

请注意,单个单元格、列或行可能有一个以上的数据质量问题,如果可能,不应重复计算该问题:如果单个值违反了其预期的数据类和预期的格式,则不应加倍惩罚该列或数据集的数据质量分数,因为无论该值有多少个问题,都只有一个值是无效的。

基于此,数据集的单个单元格的得分可以计算为该值完全没有问题的概率。这可以计算为 100%减去在单元上检测到的每个问题的置信度的乘积。举例来说:如果我们有 90%的把握某个单元格存在问题,那么这些值没有问题的概率是 100–90 = 10%。如果问题的置信度为 100%(对于显式约束),则该值没有问题的概率为 100–100 = 0%

对于在数据集的单个单元格上报告的数据质量问题,计算单元格得分的公式如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

单个单元的质量分数,仅考虑单元级别报告的问题

如果一个单元有两个问题,一个置信度为 80%,另一个置信度为 60%,那么第一个问题不真实的概率是 100%-80%=20%,第二个问题不真实的概率是 100%-60%=40%,根据概率定律,这些问题都不真实且该单元没有数据质量问题的概率仅为 20%乘以 40% = 8%。

请记住,我在本文开头提到过,数据质量问题也可以针对完整的行、完整的列或完整的数据集进行报告。我们需要分配这些问题对细胞得分的影响。

对于针对完整行报告的问题,这很容易,因为如果该行无效,我们可以假设该行的所有值都无效。这些问题对细胞评分的影响可以计算如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

仅考虑行级别报告的问题的单元的质量分数

conf(pb[row]) 在这里表示为被测量的单元的行报告的一个行级数据质量问题的置信度。

但是,整个列报告的问题需要通过使用问题的普遍性在该列的所有值中平均分布。普遍性告诉我们, n% 的价值观受到了问题的影响,尽管我们并不确切知道哪些价值观有问题,哪些没有。因此,每个值的得分将降低一个系数,该系数等于流行率乘以问题真实存在的置信度,如下式所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

仅考虑在列级别报告的问题的质量分数

conf(pb[col]) 表示针对被测量单元的列报告的一个列级数据质量问题的置信度,而 prev(pb[col]) 表示其出现率——具有该问题的列中的值的百分比。

针对整个数据集报告的数据质量问题的影响以相同的方式分布在所有像元中:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

仅考虑在数据集级别报告的问题的质量分数

考虑到单元本身、其列、其行或数据集上报告的所有问题,单个单元的最终数据质量得分可计算如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

考虑所有问题的单元的质量分数

列的数据质量分数

前面的公式为数据集的每个单个像元计算 0%到 100%之间的标准化数据质量分数奠定了基础。基于这一点,计算任何列的数据质量分数就像计算该列的每个值的数据质量分数的平均值一样简单。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

列的质量分数

行的数据质量分数

同样,可以通过对该行的每个单元格计算的分数进行平均来计算数据集的任何行的分数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

行的质量分数

数据集的数据质量分数

计算数据集的数据质量分数就像计算每列分数的平均值或每行分数的平均值一样简单。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据集的质量分数

请注意,这也等同于计算所有单元格得分的平均值。由于公式的对称性,所有这些计算将返回相同的结果,这使得它很优雅。

示例:

让我们将这些公式应用到之前的具体例子中:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

计算的数据质量分数

使用前面的公式,您可以计算每个单元格、每列或每行的质量分数,对单元格分数、列分数或行分数进行平均,您将返回代表数据集数据质量分数的相同结果(55%)。

然后,报告可以深入查看任何列或行,并显示有关其数据质量分数的更多详细信息,哪些行或列对数据集分数的影响最大,等等。这种深入查看功能对于数据清理操作非常有用。

摘要

我们已经看到了为每个数据集建立统一的标准化数据质量分数的重要性,这样非数据质量专家也可以使用它。我们已经看到,这样的数据质量分数应该满足什么要求,即使在具有不同结构或约束的数据集需要相互比较的重要情况下也是有用的。我们终于看到了这个数据质量分数是如何在 IBM 产品组合中实现的。

利用蒙特卡罗量化模型预测误差

原文:https://towardsdatascience.com/how-to-quantify-the-prediction-error-made-by-my-model-db4705910173?source=collection_archive---------19-----------------------

蒙特卡洛模拟证明

预测是非常困难的,尤其是关于未来的时候。—尼尔斯·玻尔

作为一名在工程领域工作的数据科学家,我经常与物理学方面的其他研究工程师合作,任务是开发定量模型来预测感兴趣的物理现象。然而,获得可靠的预测从来都不容易,主要是因为我很少能确定模型超参数的正确值。那些传达特定物理解释的超参数通常通过噪声实验来校准。因此,由于校准过程中固有的随机性,无法确定它们的精确值。简单来说,那些超参数是不确定的。

我通常有两个选择:一,我可以只选择超参数的名义值(或最可能值)并基于它们进行预测,希望获得的结果是准确的或至少接近事实;第二,我可以接受这些超参数不确定的事实,并使用适当的不确定性传播技术将不确定性从模型超参数传播到模型的预测误差/不确定性。

在实践中,第二种选择通常是首选。在这种情况下,预测输出将不仅仅是一个值。相反,我们将得到它的完整的概率分布。这是有利的,因为该选项的结果提供了更多的信息,因为它为我们提供了与我们的预测相关联的置信度,从而实现了我们量化预测误差的目标。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1 虽然选项(a)仅选取单个输入值,但选项(b)承认输入是不确定的,并通过模型将这些不确定性传播到输出。(图片由作者提供)

在本文中,我们将介绍一种有用的技术来实现预测误差的不确定性传播和量化。文章的其余部分结构如下:

  • 动机:什么是前向不确定性传播?
  • 解决方案:基于抽样的蒙特卡罗方法
  • 插图:一个简单的案例研究
  • 摘要:挑战和应对措施

所以让我们开始吧!

1.正向不确定性传播

如前所述,建模者经常需要解决不确定的超参数问题,这很容易损害模型预测的可靠性。在此背景下,提出了前向不确定性传播策略,以充分考虑输入参数的不确定性,量化诱导的预测不确定性。

形式上,前向不确定性量化的主要目标是评估在各种输入不确定性的影响下输出的变化。

Forward 这里指的是不确定性信息从输入,通过正在研究的物理模型,流向输出。根据分析师的目标,向前不确定性传播的重点可能是简单地估计基本统计数据(例如,平均值、方差等)。)或输出值超过某个阈值的概率(即风险分析),或输出的整个概率密度函数(PDF)。

前向不确定性传播属于计算科学与工程中不确定性管理的一个更大的研究领域,其中传播构成了朝向管理目标的一个主要步骤。读者可以在我之前发表的博客中找到不确定性管理的更多细节:计算科学与工程中的不确定性管理。

在实践中,设计了几种方法来传递期望的前向不确定性传播。这些方法包括概率分析法、摄动法、谱方法等。通常,这些方法涉及大量的数学推导,并且它们的实现远非简单明了。除此之外,它们可能只对特定问题有效,并且可能只在超参数的不确定性水平较小时才是准确的。因此,这些方法还没有在工业实践中广泛采用,本文也不讨论。相反,我们将关注一个更受欢迎的方法:蒙特卡洛模拟。

2.蒙特 卡罗模拟

直观易懂,易于实现,无需对模型进行额外的修改(或者如果您喜欢技术术语的话,称为非侵入式),高度并行化,对模型及其相关的超参数做最少的假设。听起来像是每个从业者都会喜欢的方法,对吗?事实上,正是这些特性使得蒙特卡罗模拟成为实现不确定性传播的最流行的方法。

从技术上讲,蒙特卡罗模拟包括从输入概率分布中抽取随机样本,并使用自己的模型计算每个样本的相应响应。然后可以基于获得的结果集合来推断输出的统计。

蒙特卡洛模拟的工作流程可总结如下:

  1. 从模型超参数的分布中随机抽取个样本。这里,每个样本对应于模型超参数的特定组合。
  2. 对于模型超参数的每个组合,将它们插入到模型中,并使用这个新配置的模型进行预测。在这一步的最后,我们将获得一组预测。
  3. 基于这种预测的集合,我们可以很容易地估计各种感兴趣的统计数据,从简单的平均值和方差到完整的概率密度函数。

您可能已经注意到,要开始蒙特卡罗模拟,我们需要知道不确定模型超参数的概率分布。这一点很重要,因为如何对输入进行统计建模将直接影响输出的不确定性。在实践中,贝叶斯统计通常用于从现有数据(例如,实验的和计算的)中导出目标概率分布。在其他情况下,这些概率分布可以由领域专家根据他们的经验和判断简单地分配。在这种情况下,认知的不确定性可能被引入不确定超参数的统计建模中。

3.案例研究:大炮射击

现在,让我们看看蒙特卡洛模拟在实践中是如何使用的。这里我们考虑一个抛体运动问题,我们感兴趣的是计算大炮的射程。在现实生活中,这种分析可以用来推导成功摧毁敌方目标的概率。

我们的物理模型很简单,其中射击距离 R 由初速度 v ₀、射击角度 θ 以及重力加速度 g 、决定,如图 2 所示(如果你对如何推导这个方程感兴趣,这里是链接)。这是一个简单的模型,因为没有考虑空气阻力的影响。然而,对于我们的演示目的来说,这已经足够好了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2 火炮射击案例研究示意图。(图片由作者提供)

现在,假设我们不太确定 v ₀和 θ 的值,但我们知道 g =9.8m/s。因此,在我们当前的案例研究中, v ₀和 θ 被视为不确定模型超参数。为了描述它们的不确定性,我们为 v ₀选择了一个正态分布,为 θ 选择了一个均匀分布:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3 我们给 v ₀分配一个正态分布,给 *θ分配一个均匀分布。(*图片作者 )

对于初速度 v ₀,其平均值为 150m/s,标准偏差值为 5m/s,对于射击角度 θ ,其不确定度范围从 40ᵒ到 50ᵒ.由于模型超参数( v ₀和 θ )中嵌入的不确定性,我们对射程 R 的预测也将是不确定的。现在我们的目标是准确量化我们的 R 预测的不确定性,并推导出它的全概率分布。

是时候应用蒙特卡罗程序了。按照上一节概述的步骤,我们首先从各自的分布中抽取 10000 个随机样本 v ₀和 θ (图 3)。为此,可以使用 Numpy 的随机数生成器。随后,对于 v ₀和 θ 的每个组合,我们计算相应的 R 值。

图 4(a)描绘了基于 v ₀和 θ 的一些选定样本的几个计算轨迹。我们可以看到,当初始拍摄条件(即 v ₀和 θ )变化时,这些轨迹有很大不同。这表明 v ₀和 θ 的不确定性的影响是不可忽略的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4 我们的火炮射击案例的蒙特卡罗结果。(a)中的红线代表使用 v ₀和 *θ的标称值计算的火炮弹道。其计算的 R 值在(b)中用红色虚线表示。(*图片作者 )

R 对应的直方图如图 4(a)所示。在这里,我们可以看到射击场 R 的分布呈钟形,中心在 2270 米左右。另一方面,红色虚线的 R 值为 2296 米,是利用 v ₀和 θ 的标称值,即 150m/s 和 45ᵒ.计算出来的请注意,这两个 R 值并不相同。当基础模型是非线性的时,这是很常见的(就像我们当前的情况)。这一观察还告诉我们,简单地插入输入的最可能值一般不会产生输出的最可能值。这表明执行严格的不确定性传播分析的重要性。

4.挑战和解决方案

正如每个硬币都有两面一样,蒙特卡洛方法也有其自身的缺点。在本节中,我们将讨论在实践中实施蒙特卡罗技术时的主要挑战和可能的补救措施。

对蒙特卡罗方法的主要批评在于它的收敛速度慢。这意味着我们需要大量的样本(∼ o(10⁴)来确保蒙特卡罗结果的可靠性。因此,我们需要重复计算每个样本的模型预测,从而潜在地导致令人望而却步的计算成本。在下文中,我们介绍两种流行的方法来解决这个收敛问题。

4.1 智能采样方案

当使用蒙特卡罗方法时,我们可以做的第一件事是改进抽样方案。简单的蒙特卡罗方法利用随机抽样来完成这项工作。该采样方案不是特别好,因为它在参数空间中产生了明显的“簇”和“洞”(我们将在后面说明这一点)。因此,我们需要大量样本来覆盖整个参数空间。

相反,研究人员提出了更先进的采样方案,具有更好的“空间填充”属性,这意味着这些方案可以在参数空间中更均匀地生成样本。这一类的例子有拉丁超立方体采样,还有 Sobol 序列和 Halton 序列,都是低差异序列

图 5 比较了应用于 2D 参数空间的各种采样方案,样本数量相同。这里我们可以看到,随机采样方案往往会形成团块并留下空隙,而其他高级采样方案能够生成更多的“空间填充”样本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5 在 2D 参数空间中由各种采样方案产生的样本。(图片由作者提供)

4.2 代理建模技术

另一种避免高计算成本问题的方法是采用代理建模技术。这背后的核心思想是训练廉价的统计模型来近似(或“替代”)原始物理模型,例如图 2 中的抛射体运动模型。之后,蒙特卡罗方法可以直接应用于训练的统计模型。由于统计模型的一次评估涉及可忽略不计的计算成本,蒙特卡罗程序的总费用变得可以承受。

代理建模的核心是监督机器学习,因为目标是基于输入数据和相应的标记输出数据来训练代理模型。许多机器学习技术,如支持向量机、高斯过程、神经网络等。已经被用于加速蒙特卡罗模拟。随着越来越多强大的机器学习技术不断被开发出来,我们可以期待蒙特卡洛模拟的准确性和效率将会进一步提高。

5.关键要点

  • 前向不确定性传播对于估计由不确定模型超参数引起的模型预测误差/不确定性是至关重要的。
  • 蒙特卡罗模拟是实现不确定性传播的最流行的方法之一。
  • 蒙特卡洛模拟在计算上可能是昂贵的,因为可能需要许多样本来确保准确性。
  • 更智能的采样方案和代理建模技术有助于减轻与蒙特卡罗模拟相关的高计算成本

延伸阅读:

[1]阿特·b·欧文,蒙特卡洛理论、方法和实例,2013 年

关于作者

我是一名博士研究员,致力于航空航天应用的不确定性量化和可靠性分析。统计学和数据科学是我日常工作的核心。我喜欢分享我在迷人的统计世界中学到的东西。查看我以前的帖子以了解更多信息,并在 Linkedin上与我联系。

如何在 BigQuery 中查询和计算 GA4 事件数据

原文:https://towardsdatascience.com/how-to-query-and-calculate-ga-app-web-event-data-in-bigquery-a77931176d3?source=collection_archive---------5-----------------------

Google Analytics 4 基于事件的报告示例(之前为 App + Web)

应用程序和网络分析的未来就在这里:谷歌在谷歌分析中宣布了一种新的衡量方式。虽然仍处于测试阶段,但这是网络和应用分析的一次小革命。

最重要的是:所有(甚至非 360)谷歌分析账户都有一个原始数据 BigQuery 导出。让我们开始吧!

注:你喜欢这篇文章吗?那么你也会喜欢我的新网站GA4BigQuery.com:一个关于如何在 BigQuery &摇滚你的数字营销分析中查询谷歌分析数据的数字指南🤘

您可能也会对我与 Mari 和 Simo Ahava 共同设计的数字课程感兴趣,该课程面向希望深入查询世界的营销专业人士,以及需要掌握 GA4 特定知识的数据专业人士:

[## 在 Google BigQuery 中查询 GA4 数据

关于如何使用 Google BigQuery 访问 Google Analytics 4 生成的原始数据的在线课程。一门必学的课程…

www.teamsimmer.com](https://www.teamsimmer.com/checkout/ga4-google-bigquery/bq-course-page/) 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由柏柏尔人 Bijlsma

在本文中,我将只关注 web 数据。我将向您展示如何计算新的 GA4 参与度指标,以及如何复制在 GA4 用户界面中再也找不到的“经典”Google Analytics 维度和指标。但是要小心…

这不是万能分析。尝试将新的测量模型视为超越 Universal Analytics 所能做到的机会,而不仅仅是填充 GA 古老数据模型的另一种方式。(来源)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

App 和 web 统一(来源)

如果你是 BigQuery 的新手,我推荐你阅读我之前关于如何在 BigQuery 中查询 Google Analytics(通用分析)数据的文章的第一部分。

目录

这是怎么回事?
文档
新参与度指标
Google Analytics 4 big query 导出模式
嵌套字段
获取所有唯一事件和参数
示例查询:“标准”维度&指标
示例查询:计算维度&指标

这是怎么回事?

谷歌前分析倡导者克里斯塔·塞登在一系列博客中解释了为什么新的谷歌分析 4 属性是一大进步:

目前,如果你同时拥有应用程序和网站数据,你需要分别收集和分析这些数据,在 Google Analytics for web 和 Google Analytics for Firebase for apps 中。虽然平台不同,但在理解数据和报告方面,许多 KPI 和业务需求是相同的,因此是时候将这些数据整合到一个分析属性中了!(来源)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

谷歌分析 4 报告用户界面

这一发展对收集和分析数据的方式有着严重的影响。

这种新的测量类型使用与 Google Analytics for Firebase(GA4F)相同的数据模式(……)关于这种新的数据模式,最重要的是它脱离了传统的会话+页面视图方法,传统的 Google Analytics 已经使用了 15 年以上。相反,它使用事件+参数模型。这是不同的,但它打开了一个全新的可能性世界,就您可以跟踪的内容以及您可以通过相关参数添加到每个事件操作的所有附加细节而言。(来源)

返回目录

证明文件

如果所有这些对您来说都是新的,请在继续查询之前阅读所有关于 GA4 属性的内容。

[## 关于 Google Analytics 4 (GA4)属性的最佳资源

GA4BigQuery 将主要关注如何在 BigQuery 中利用你的谷歌分析数据。由于 GA4 对…来说相当新

www.ga4bigquery.com](https://www.ga4bigquery.com/best-resources-on-google-analytics-4-ga4-properties/)

新的参与度指标

在 Google Analytics 4 属性中,我们看到了一些以前没有的新指标:

参与会议

持续时间超过 10 秒、有转换事件、有 2 个或更多屏幕或页面视图的会话数。(来源:GA4 UI 中的定义)

以下是克里斯塔·塞登的一些背景资料:

参与式会话的概念源于希望从会话计数中删除反弹,因此,只有在用户在网站上停留 10 秒钟后,参与式会话才会被计数。如果他们在此之前离开,这将被视为反弹,而不是参与会议。(来源)

弗洛里安·佩尔补充道:

这或多或少与通用分析反弹相反。参与式会话是指至少有两次浏览量,或一次浏览量+一次互动,或一次持续时间为 10 秒的浏览量。目前,10 秒超时不能更改。(来源

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

参与度指标

每个用户参与的会话数

每个用户参与的会话数,因此,如果我们看到相同的用户 ID 返回多次,则每个用户可能有 3、4 或 5 个会话,然后在您的总用户数中取平均值,得出平均值大于 1,实际数量取决于您的内容有多少新用户与返回用户(或删除的 cookies)。(来源)

订婚时间

这可能是我最喜欢的新指标。为什么?多年来,我一直在谈论为什么我讨厌通用谷歌分析中的“跳出率”和“页面时间”这两个指标。这种不喜欢有很好的理由:这些指标在计算方式上有缺陷,因为自 15 年前这些指标问世以来,网络的使用发生了变化。(…)在 Firebase 的谷歌分析中,有一个指标叫做“参与时间”,我更喜欢这个指标,因为它是作为应用程序在前台的实际时间计算的,比通用谷歌分析中的“页面时间”可靠得多。

对于 A+W,我们想引入类似的逻辑,但由于浏览器和标签的工作方式,这要困难得多。我们的小团队花了相当多的时间来讨论计算对分析有意义的指标的最佳方法,最终得出了“web 参与时间”,这意味着它是如何在应用程序中计算的同义词,使用一些新的处理程序来密切关注前台标签、屏幕睡眠时间等。本质上,一个更好的计算时间的页面。(来源)

订婚率

参与会话的百分比(参与会话数除以会话数)。(来源:GA4 UI 中的定义)

转换策略

如果我们打算在 App+Web 中复制 Universal Analytics 报告,这些不会立即有用:转换是标记为转换的事件计数,而不是在会话级别进行重复数据删除(因此它不是真正的会话范围指标)。更重要的是,现在没有办法指定我们想要查看哪个转换——它们都被扔进了同一个锅里。最有可能的用例是当我们只跟踪单个转换事件时,那么报告将更有意义。(来源)

返回目录

GA4 大查询导出模式

由于没有谷歌分析 4 属性的样本数据集(还没有?),我将使用一个来自 OrangeValley 的出口数据集(仅限网络),这是我在撰写本文时工作的数字营销机构。除了通过’ enhanced measurement 收集的标准事件之外,您可能会在我们的数据集中看到一些自定义事件参数,如事件’ page_view ‘中的’ wordCount '。这不会以任何方式影响我们的模式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GA4 在 BigQuery 中导出数据

让我们来看看 GA4 BigQuery 导出模式:

GA4 大查询导出模式

你会注意到,数据集主要围绕事件和用户数据组织,并辅以一些设备、地理、应用和交通来源数据。

根据不同的定义,您可以预期 Google Analytics 4 用户界面和 BigQuery 导出数据查询的结果之间存在一些相对较小的差异。了解用户计数或维度&度量定义差异。

返回目录

嵌套字段

通用分析导出模式中,数据集中的每一行代表一个会话。因为 GA4 属性是基于事件的,所以数据集中的每一行都代表一个事件。每个事件又可以包含多个事件参数和相应的值。为了向您展示这在 BigQuery 中是如何工作的,我们查询我们的嵌套样本集:

SELECT
  *
FROM
  `ga4.analytics_1234567890.events_*`
LIMIT
  3

这给了我们 3 行,表示为平面表,如下所示:

记住,在这个例子中,只有第 2、9 和 15 行是我们表中真正的行。其他“行”实际上是嵌套字段,大多数情况下是NULL值。只有event.params列填充了值。

为了处理这些字段,并能够查询我们的表以满足我们的需求,我们需要UNNEST函数。

这里的问题是它本质上是一个数组(实际上在 BigQuery 中它是一个“重复的记录”,但是你可以把它看作一个数组)。(…)这就是*UNNEST*函数的用武之地。它基本上允许你在一个数组中获取元素,然后展开每一个单独的元素。然后,可以将原始行与每个未嵌套的元素连接起来,将它们添加到表中。(来源)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

取消嵌套事件 _ 参数(来源)

我强烈推荐阅读这篇文章,它以 Firebase Analytics 样本数据集为例详细解释了UNNEST概念。

您只需UNNEST包含“重复字段”的记录。对于我们的 Google Analytics 4 数据集,这些可能涉及:

  • 事件参数
  • 用户属性
  • 项目

返回目录

获取所有唯一的事件和参数

因为每个数据集都可能包含不同数据类型的不同事件和事件参数,所以查询实际的表来找出答案是非常有帮助的。尤其是当您缺少关于数据收集方式的文档时。要获得所有唯一的事件和参数,您可以使用如下查询:

罗伯特·萨赫林启发的疑问

在我们的数据集的情况下,这导致所有唯一事件和参数的列表及其相应的数据类型。这些重复的字段包含大量数据,我们将使用这些数据来计算维度和指标。

返回目录

“标准”维度和指标

许多数据可以直接从表中导出,而不需要对数据进行计算。借助UNNESTPARSE获取日期或时间戳,我们可以做到这一点。

查看示例查询中的-- comments的名称和定义,并从SELECT子句中复制您需要的部分。确保您还添加了正确计算结果所需的任何附加条件(即WITHFROMWHEREGROUP BYHAVINGORDER BY)。

用户维度

user _ id
user _ pseudo _ id
user _ first _ touch _ timestamp
user _ string _ value
user _ set _ timestamp _ micros
user _ ltv _ revenue 货币

用户指标

用户整数值
用户浮点值
用户双精度值

[## 用户:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/user-dimensions-metrics-ga4/)

设备尺寸

device . category
device . mobile _ brand _ name
device . mobile _ model _ name
device . mobile _ marketing _ name
device . mobile _ OS _ hardware _ model
device . operating _ system
device . operating _ system _ version
device . vendor _ id
device . advertising _ id
device . language
device . is _ limited _ tracking
device . time _ zone _ offset _ seconds
device . browser

[## 设备、应用、网络、流和平台:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/device-app-web-stream-platform-dimensions-metrics-ga4/)

地理维度

地理大陆
地理亚大陆
地理国家
地理区域
地理城市
地理地铁

[## 地理位置:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/geo-location-dimensions-metrics-ga4/)

应用程序维度

app _ info . id
app _ info . version
app _ info . install _ store
app _ info . firebase _ app _ id
app _ info . install _ source

[## 设备、应用、网络、流和平台:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/device-app-web-stream-platform-dimensions-metrics-ga4/)

流量来源维度

traffic_source.name(用户)
traffic_source.medium(用户)
traffic_source.source(用户)

[## 流量来源:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/traffic-source-dimensions-metrics-ga4/)

事件维度

event _ date
event _ timestamp
event _ name
event _ key
event _ previous _ timestamp
event _ bundle _ sequence _ id
event _ server _ timestamp _ offset
stream _ id
平台
event_dimensions.hostname

事件度量

事件 _int_value
事件 _float_value
事件 _double_value
事件 _value_in_usd

[## 事件:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/events-dimensions-metrics-ga4/)

返回目录

电子商务维度

commerce.transaction_id

电子商务指标

ecommerce . total _ item _ quantity
ecommerce . purchase _ revenue _ in _ USD
ecommerce . purchase _ revenue _ value _ in _ USD
ecommerce . refund _ value _ in _ USD
ecommerce . shipping _ value _ in _ USD
ecommerce . shipping _ value
ecommerce . tax _ value _ in _ USD
ecommerce . tax _ value
ecommerce . unique _ items

[## 电子商务:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/ecommerce-dimensions-metrics-ga4/)

返回目录

项目尺寸

items . item _ id
items . item _ name
items . item _ brand
items . item _ variant
items . item _ category 2
items . item _ category 3
items . item _ category 4
items . item _ category 5
items . coupon
items . affiliation
items . location _ id
items . item _ list _ id

项目度量

items . price _ in _ USD
items . price
items . quantity
items . item _ revenue _ in _ USD
items . item _ revenue
items . item _ refund _ in _ USD

[## 项目:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/items-dimensions-metrics-ga4/)

返回目录

计算维度和指标

你在谷歌分析分析和报告中习惯的其他维度和指标有点难以获取。您必须使用自己的查询来计算它们。

由于我已经尝试整理出了最常用的维度和指标,我希望我能对下面的示例查询有所帮助。有很多其他的,甚至可能更好的方法来实现这些结果,但这里是我的两美分。

这些示例查询(按类别排序)包含以下所有 Google Analytics 维度和指标。如果您只需要一个维度或度量,请查看示例查询中的-- comments的名称和定义,并从SELECT子句中复制您需要的部分。确保您还添加了正确计算结果所需的任何附加条件(即WITHFROMWHEREGROUP BYHAVINGORDER BY)。

用户维度

用户类型
会话计数

用户指标

用户
新用户
%新会话
每个用户的会话数量
每个用户的事件计数

[## 用户:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/user-dimensions-metrics-ga4/)

会话指标

会话
参与会话
参与率
参与时间
反弹
反弹率
每次会话的事件计数

[## 会议:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/sessions-dimensions-metrics-ga4/)

高级:定制您参与的会议

上述参与会话的计算基于事件“user_engagement”。更具体地说:当参数’ session_engaged’ = '1 '时。根据 GA4 用户界面,参与会话的定义是:

持续时间超过 10 秒、有转换事件、有 2 个或更多屏幕或页面视图的会话数。

您可以在 UI 中设置转换事件,但如果您使用事件“user_engagement ”,则不能更改会话长度或页面浏览量的定义。但是,如果我们想要自定义参与式会话的定义,该怎么办呢?您可以使用这个高级查询(的变体)。

时间维度

日期
年份
ISO 年份
年份月份
年份月份
年份星期
年份星期
ISO 年份星期
ISO 年份星期
月份日期
星期日期
星期名称
小时
分钟
日期小时和分钟

[## 日期和时间:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/date-and-time-dimensions-metrics-ga4/)

备注:时区格式

BigQuery 通常以 UTC 显示数据。这在使用日期格式化函数时会导致问题,因为日期和时间可能会不一致。将日期时间格式转换为正确的时区可以解决这些问题。
( 出处&如何)

交通来源维度

默认频道分组(用户或会话)
源/媒体(用户或会话)
活动(用户或会话)
完整推荐人

[## 流量来源:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/traffic-source-dimensions-metrics-ga4/)

页面跟踪尺寸

主机名
页面
上一页路径
页面路径一级
页面路径二级
页面路径三级
页面路径四级
页面标题
登陆页面
第二页
退出页面

页面跟踪指标

入口
浏览量
独特浏览量
页面/会话
出口
%出口

[## 页面跟踪:维度和指标(GA4)

许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…

www.ga4bigquery.com](https://www.ga4bigquery.com/page-tracking-dimensions-metrics-ga4/)

电子商务维度和指标

由于到目前为止我还没有访问过 GA4 的任何电子商务数据集,我建议看看 Bounteous 查询 GA4 数据指南中的电子商务交易产品的查询示例。

返回目录

如何使用 Python(带 SSH)通过 3 个步骤查询 PostgreSQL

原文:https://towardsdatascience.com/how-to-query-postgresql-using-python-with-ssh-in-3-steps-cde626444817?source=collection_archive---------13-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Pixabay 提供

-这个故事描述了如何使用这个脚本在有或没有 SSH 的情况下快速建立与远程 PostgreSQL 数据库的连接。pem 认证。-

数据通常存储在远程服务器上的 PostgreSQL 等数据库中,这使得数据分析师很难快速访问数据。有时,有中间团队协助分析师从数据库中检索数据。在这个故事中,我们将讨论如何使用 Python 直接查询数据,而不需要中间媒介。

如果你知道如何使用 Python(主要用于分析和可视化),但没有数据库经验或如何与它们交互,那么这篇文章就是为你准备的!

有各种各样的工具供我们使用,使您能够自己从数据库中交互/检索数据,并花更多的时间来提取见解。

  • **第一步:**安装所有需要的包。
  • **第二步:**将 query.py 的内容导入或粘贴到笔记本中。
  • **第三步:**开始查询!

这个故事假设如下:

  • 您已经在本地环境中安装了 Python
  • 您正在使用像 Jupyter 笔记本这样的实时代码环境
  • 已经获得了 SSH 到远程服务器的必要凭证。pem 证书)并查询 PostgreSQL 数据库(用户名和密码)。

步骤 1:安装所有必需的软件包:

首先,我们需要从终端安装几个软件包。

pip3 install paramiko
pip3 install sshtunnel
pip3 install SQLAlchemy
pip3 install pandas

步骤 2:将 query.py 内容导入或粘贴到笔记本中

接下来,您需要将 repo 中的 query.py 文件保存到您的工作目录(Jupyter 笔记本文件所在的目录)中,或者直接将该文件的内容复制到您的笔记本中。

如果将 query.py 文件放在工作目录中,则在笔记本中包含以下导入行:

from query.py import *

或者,只需将下面的代码复制并粘贴到笔记本的代码单元格中:

第三步:查询!

现在我们可以开始查询了!定义的类只提供了少量的基本函数。让我们看一下如何使用这个类,以及我们可以用它做什么。

首先,我们需要指定 PostgreSQL 连接参数和 SSH 参数(如果访问远程服务器需要 SSH 隧道)。

我们将 pgres 定义为我们的连接,以简化每次我们想要查询数据库或探索数据库的组织结构。还会提示您输入 PostgreSQL 用户名和密码,它们存储为临时变量(最佳实践是将这些变量保存为环境变量)。

接下来,我们可以探索名为’ database_name '的给定数据库的模式,使用找到我们感兴趣的模式。schemas() 函数。

如果我们想探索名为’ schema_name '的模式,我们可以使用*返回模式中的表名。*tables()【函数。

最后可以用*。query()* 运行标准的 SQL 查询(针对 PostgreSQL)。在本例中,我们从名为’ ey_test_table '的表中查询列名和数据类型

尝试用您自己的查询替换 sql_statement 的内容,并从中获得乐趣!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值