TowardsDataScience 博客中文翻译 2021(九十二)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

Airflow 2.0 部署 Azure Kubernetes 服务

原文:https://towardsdatascience.com/airflow-2-0-deployment-azure-kubernetes-service-35d8b8ba270a?source=collection_archive---------12-----------------------

Airflow 推出了一个具有新功能的新版本(2.0.0 ),因此在将其部署到生产中之前,是时候开始测试了。本文提供了几个脚本,可以帮助有同样想法的人。

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

Pixabay — EdWhiteImages

我对部署的定义是:

  • Azure 云— Kubernetes 服务
  • 库伯内特遗嘱执行人
  • Azure 存储帐户(远程日志)
  • Azure 注册表到容器图像
  • Postgresql 容器(气流后端)
  • Git-Sync(同步 Dag)

我写这篇文章的目的是帮助那些花费大量时间寻找例子来使用相同或等效的基础设施进行部署的人。气流文档并不是在所有场景中都有足够的帮助。

首先,我选择 Kubernetes executor 是因为我在云中工作,每个人都知道按需付费云系统是如何工作的。那么重要的是节约资源。然后 Kubernetes executor 这是一个很好的执行任务的方法,执行后杀死豆荚。远程日志系统可以将日志保存在存储器中,您可以在 airflow web 服务器 UI 中正常查看它们。最初,我想使用 helm,但我直接在 Kubernetes 中使用,我对所有部署步骤有更多的控制权。

好了,我们去码吧!

为了部署 Postgres,这是我的 YAML 文件。我使用了持久卷,这样我就限制了数据库的大小。你可以在不同的文件中分开,然后在 Kubernetes 中应用(我就是这样做的),或者你可以自动化。

在下一步中,我创建了两个持久卷(opt/airflow/dags,opt/airflow/logs)。我将跳过这些脚本,因为它们与上面 PostgreSQL 部署中使用的脚本相同。我需要构建自己的映像,因为我正在使用 Kafka 和其他组件,但是您可以使用默认的映像,比如(来自 Apache/air flow:2 . 0 . 0-python 3.8-build)或您喜欢的其他映像。如果你使用你的图片并将它推送到 azure 注册表,你需要应用一个 Kubernetes 的秘密,并将“imagePullSecrets”设置为我下面的脚本。对于我的 git 密码,我创建了一个 Kubernetes configmap,避免了这些环境的硬代码,所有其他的我直接在 YAML 文件中做了代码,以显示如何设置这些环境。服务帐户有权创建、列出和删除窗格,这一点很重要。我之前说过,Kubernetes 执行器在部署后会删除豆荚。
这个脚本差不多就是我的部署脚本了。我更改了一些细节,因为我没有将调度程序与 airflow webserver 一起部署,我的资源限制是不同的,并且我在其他服务帐户中运行,为了便于理解,我做了一些简化。

好了,在应用这个部署之后,您将有两个 pod 在运行。你可以用 8080 端口绑定并访问 airflow 服务器。在我的开发环境中,我直接为 kubectl port-forward 命令这样做。

在最后一个脚本中,你可以看到我在 Azure 中创建了一个存储帐户,并建立了一个连接。我在 airflow > connections 中创建了一个连接,然后用这个连接设置了我的 env air flow _ _ LOGGING _ _ REMOTE _ LOG _ CONN _ ID。

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

因此,现在您可以使用 KubernetesPodOperator 运行您的任务。这种方法是可配置的,在启动之前可以更改 Kubernetes pod 配置。我喜欢创建自己的 pod_template 并设置这个 env:air flow _ _ KUBERNETES _ _ POD _ TEMPLATE _ FILE。你可以在上面看到我的剧本。但是没有这些模板设置也可以工作。

我希望这些脚本可以帮助人们快速找到 Kubernetes 的气流配置,并通过这种 Kubernetes executer 方法最小化云成本。

气流与完美—数据项目的工作流管理

原文:https://towardsdatascience.com/airflow-vs-prefect-workflow-management-for-data-projects-5d1a0c80f2e3?source=collection_archive---------3-----------------------

介绍

我非常喜欢 Airflow 及其在工作流管理工具上的优势。然而,我最近开始在我的工作流程中使用提督。两者都是使用 python 构建的。在本文中,我将讨论这两者之间的区别。

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

照片由杰森·登特Unsplash 拍摄

为什么选择工作流管理?

工作流是许多生产相关应用程序不可或缺的一部分。它包括 MLOps、自动化、批处理、投资组合跟踪等。在数据世界中,一个系统需要按顺序处理数据并将数据发送给另一个系统/任务。

气流

Airflow 是 apache 孵化的项目,已经存在了相当长的时间。随着时间的推移,气流比最初的用例更加灵活。Airflow 还可以连接从 AWS Lambda 到 GCP 数据流的云服务。在大多数情况下,大到中等规模的组织使用 Airflow 来处理大量的数据,并在其上执行一些数据操作。它也可以在集群模式下运行。AWS 和 GCP 提供了气流的管理实例,以便与其他云服务一起使用。

  1. AWS 管理的气流工作流程
  2. GCP 云作曲

阅读文章下方关于气流的更多信息。它将显示设置和创建

[## 不受重视的工作流程工具——气流

towardsdatascience.com](/under-appreciated-workflow-tool-airflow-a078a3c71a67)

长官

提督,市场新进入者,相比气流。它是一个开源项目;然而,有一个付费的云版本来跟踪你的工作流程。提督仍然落后于气流带来的所有铃声和哨声。然而,它完成了工作,并且有许多集成。

Prefect 还支持云,这意味着您可以在任何服务器上运行执行工作流,并监控/管理它https://cloud . prefect . io

比较

在下面的部分,我们将看到气流和提督的比较

设置

这两个工具都可以使用 pip、docker 等安装。气流增加了引擎盖下的一些不同的包;也可能会有一些冲突。为了让 Airflow 运行,您需要一个调度程序和 web 服务器。AWS 和 GCP 提供基于气流的托管服务。

Prefect 被整齐地组织成不同的附加组件,并与各种其他组件集成。

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

不同的附加组件— 来源

要起来跑,提督可以快速启动。提督只需要一个代理人来运行流程。

编码工作流

对任何程序员来说,编写工作流代码都是最重要的决定因素。我们经常为了学习而想学习新的语法和新的东西。

气流有一个学习曲线。你需要理解 DAG 和其中不同的操作符。

示例气流 Dag —来源作者

Prefect 就像初级 python 函数一样简单。我们需要用流把它包在下。

完美流示例—源代码作者

开发 Prefect 看起来像是 pythonic 式的编码方式。我们不需要学习很多来创造一个心流。

工作流 UI

气流

Airflow UI 非常适合监控工作流,并且易于启动。该界面作为 web 服务器的一部分创建。

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

气流用户界面— —源代码作者

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

作者执行 Dag 源作者

长官

默认情况下,没有提督用户界面。Else prefect 云环境是一个简单的设置。我们需要设置服务器。我们需要创建一个帐户和一个 API 密钥。然后需要在我们运行的系统中配置密钥。

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

完美用户界面—源代码作者

项目组织所有的流程。我们可以在一个项目中运行多个流程。总的来说,它组织得很好,执行起来没有问题。

版本化工作流

任何基于代码的系统的一个基本特征是能够版本化你的代码。

气流的一个最显著的缺点是使 DAGs 变得清爽。我们不知道当前执行的是哪个版本的工作流,也没有正确的版本控制。

另一方面,适当的版本控制和对流程的每次更新将被标记以纠正版本。

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

完美中的版本控制—源代码作者

结论

在本文中,我们已经触及了两个工作流工具。在成为 Airflow 的狂热用户之后,我开始喜欢上了 Prefect 和它的易用性。一个最突出的原因是我不需要重构代码来创建工作流。

我已经开始将我的许多工作流程/自动化迁移到 Prefect。然而,我仍然有我在气流沉重的工作流程。

获取代码

请订阅我的 简讯 获取不同文章及其他更新。

如何使用 Airflow 集群策略和任务回调来跟踪元数据

原文:https://towardsdatascience.com/airflows-best-kept-secrets-2a7acf59d13b?source=collection_archive---------32-----------------------

如何使用气流的两个最保守的秘密来监控你的狗

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

图像通过 Shutterstock 在许可下传输到 Databand。图片由 Honor Chan 编辑。

检测气流任务中的问题所需的时间是一个主要问题。这有一个很大的原因。你没有写每一条狗。很难找到一种可扩展的方式来使你的平台可维护当有数百条管道用逻辑编写时,如果没有适当的文档,你可能无法理解。如果你不了解管道是如何工作的,那么你就无法找到一种方法来跟踪关于重要的数据质量 &管道问题的&警报。这是个大问题。

虽然这听起来像是一个绝望的情况,但它不是——它只是一个具有挑战性的情况。让我们将这一挑战简化为三个移动部分:

  1. 收集所有运算符对象
  2. 收集执行元数据
  3. 基于上述元数据设置警报和监控仪表板

有很多不同的方法可以解决这些问题。您可以使用开源工具和代码构建自己的解决方案,也可以使用托管解决方案来集中管理您的元数据、监控和警报。

但是对于本文,您将学习如何使用 Airflow 的集群策略和任务回调来实现 1 & 2,并且您将有一种方法来监视:

  • 任务的工期
  • 任务状态
  • 您的任务与之交互的数据集的数据质量。

至于第三点,我们将在另一篇文章中解决。

用气流集群策略包装您的运营商

从哪里开始?您的第一个想法可能是创建一些包装操作符对象或装饰符,以添加到团队正在使用的当前操作符中,但是对于一个大型组织来说,将您的解决方案实现到每个操作符会花费大量时间。

幸运的是,airflow 提供了一个解决方案——集群策略允许您通过向 Airflow 设置添加一个policy来在不同的阶段操纵 Dag 和操作符。Airflow 公开了 3 个策略,每个策略都是 airflow 将在不同阶段加载和调用的功能:

  • task_policy–加载时将调用任何Operator
  • dag_policy–将在任何DAG加载时被调用。
  • task_instance_mutation_hook–将在任务执行之前调用任何TaskInstance

对于我们的情况,任何策略都可能是实现的很好的候选,因此我们将很快回来。

使用 Airflow 任务回调收集事件元数据

你需要解决的第二个问题是:如何捕捉不同的事件进行报道?

有两条途径可以做到这一点。

第一种选择非常简单;您可以包装任务的execute方法,并添加与原始执行相关的新功能。这里有一个你如何做到这一点的例子:

在上面的例子中,我们使用任务策略来强制用我们的time_task_duraiton记录器包装我们所有的气流任务。task_policy是气流寻找用来包装每个操作符的函数,task_time_duration负责计算任务的持续时间。实现这一点将使跟踪任务持续时间成为可能。

另一个选择是使用 Airflow 任务回调。我说的是 Airflow 在任务实例运行过程中调用不同事件的回调函数。

一个不使用任务回调的解决方案,比如上面的,可能满足你的需求,但是我认为在很多情况下这不是最好的选择。如果您想要构建一个更易维护、更可靠、更可伸缩的数据平台,使用 Airflow 任务回调是理想的解决方案。

为什么?它对用户代码的干扰较小。操纵execute方法(读作:用户代码)会影响用户的逻辑并导致我们意外的行为。根据经验,作为平台工程师,您应该避免这种情况,并尽可能确保用户代码按预期执行。

那么,什么是气流任务回调?以下是所有的回调及其作用:

  • pre_execute -正好在execute方法运行之前运行。
  • post_execute -在execute方法运行后立即运行,并且只有在没有错误的情况下。
  • on_failure_callback -如果执行中出现错误且任务失败,则运行
  • on_success_callback -如果执行过程中没有错误并且任务成功,则运行。
  • on_retry_callback -如果执行中出现错误并且任务设置为重试,则运行。
  • on_kill -如果 execute 方法超时,就在引发超时错误之前或获得 SIGTERM 之后运行。

我们将在接下来的例子中使用其中的一些。

跟踪任务持续时间

你的 DAG 有过比预期时间短的时候吗?可能平时跑两个小时的时候跑了两分钟?这个例子将探索如何解决这个问题。

在这个例子中,我创建了两个函数— pre_durationpost_duration,它们一起记录任务的运行持续时间。使用pre_executepost_execute回调来捕捉任务的开始和结束。

现在,您可以添加通用函数wrapadd_policy来减少添加多个策略的样板文件。

将这段代码放在$AIRFLOW_HOME/config/airflow_local_settings.py下,这样 Airflow 会找到您的策略并加载它。

运行 DAG 后,日志文件中的输出应如下所示:

跟踪任务状态

当一项任务失败一次,并不一定意味着有大问题。因此,开发运维人员或数据运维人员配置其气流环境以便在发生这种情况时重新运行任务是非常常见的。这样做的问题是:您需要知道该任务是否超过了可接受的重试阈值,以便在需要时可以快速修复问题。

因此,下面是如何使用相同的逻辑来收集任务状态的元数据:

使用您的新工具跟踪气流中的数据运行状况

正如大多数 Airflow 用户可能知道的那样,可能发生的最可怕的事情是,您的 Airflow UI 显示为全绿色,但随后数据并没有以您期望的形式交付。这意味着数据本身正在破裂——而不是管道——而 Airflow 没有一种直接的方法来跟踪这一点。

在数据质量方面有很多盲点。您需要了解从以前的 Dag 中读取卷时的异常情况,数据提供商可以在不通知您的情况下更改他们的 API,从而导致有问题的模式更改,并且您需要验证数据集中的数据健康状况(例如null值的比率太高)。

Airflow 集群策略和回调可以帮助您跟踪类似的数据质量指标。

在下面的例子中,我们假设您想要开始跟踪Operators对他们正在使用的数据(读或写)的影响

以下是您想了解的一些数据信息:

  • 操作类型 —读或写。
  • 操作时间戳 —跟踪我们的数据有多新。
  • 受操作影响的行数和列数

给定您正在寻找的元数据,有许多方法可以做到这一点。为了简单起见,我假设我们的 DAG 遵循这种模式:

  • 返回值是操作符输出文件的路径
  • 我们使用 Xcom 来同步返回值
  • 接受输入值的操作符将 Xcom 传递给名为“path”的参数

以下是 DAG 的样子,可以为您提供一些背景信息:

关于python_callables的细节并不重要,您需要记住的唯一事情是,当函数将数据写入输出文件时,文件路径就是返回值。

现在,让我们来看看这些记录数据帧形状的跟踪函数:

在本例中,check_inputcheck_output尝试从 csv 加载数据帧,并记录包含列和行计数的shape

并将这些功能添加到我们的策略中:

气流元数据跟踪准备就绪!

综上所述:

  1. 您了解了“气流群集策略”以及我们如何使用它来跟踪系统中的每个Operator
  2. 从我们的Operators中了解了任务的回调、它们何时执行以及如何使用它们来收集执行数据

现在,由你来实现你自己的跟踪系统。这将是以后的一篇文章,但是我会给你留下一些你可能同时想要收集的数据的想法:

  1. SnowflakeOperatorPostgresOperator或任何带有 sqlparse 的 SQL 操作符中提取有关查询的信息。
  2. 关于每一列的统计信息—空值的数量、百分比、直方图等等。使用 pydeequ大期望来验证操作员的输出
  3. 跟踪您与****交互的数据的模式,这样您就可以确保知道它何时发生变化。
  4. 收集系统指标—内存、cpu 使用率。尝试 filprofiler 提取内存使用情况。
  5. 运行时跟踪[template_fields](<https://airflow.apache.org/docs/apache-airflow/stable/howto/custom-operator.html#templating>)

让我们知道您可能感兴趣的其他跟踪功能

想了解我和我的团队正在构建的数据可观察性平台的更多信息吗?在 Databand.ai 找到我们。

通过 GPS 和 Python 绘制后 Covid 时代的机场旅客行程图

原文:https://towardsdatascience.com/airport-passenger-journey-mapping-post-covid-era-5864a877b47b?source=collection_archive---------18-----------------------

日本成田机场每个过程的 GPS 数据驱动时间测量

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

JESHOOTS.COMUnsplash 上拍照

你好,奥马尔,我的航班将于 17:30 抵达成田机场,你能来接我吗?

**奥马尔:**当然,乐意之至!我应该什么时候去接你?

巴特兰:等等!有很多新冠肺炎措施,我听说我们需要在抵达后进行测试,这可能需要时间。

**奥马尔:**没错,但是你知道在机场等待是很有挑战性的,所以我们想估计一下你是否会在 17:30 着陆——你预计什么时候到达行李领取处

**巴特兰:**网上找不到多少?要是有人测量过那个时间就好了。

新冠肺炎给旅游业带来了许多变化。它还增加了从着陆到行李认领的机场流程中现有流程的复杂性。其中一些变化是:

  • 显示阴性 PCR 证书
  • 给你测体温
  • 做唾液测试,等待结果
  • 填写许多文件和同意书
  • 安装和配置运行状况监控应用程序

如此复杂的情况下,安排上门收件服务或建立任何依赖时间的承诺都是一项挑战。在本文中,我们展示了成田机场从航班降落到行李认领的操作流程和时间的数据驱动可视化分析。

数据

手机数据是了解和衡量不同地方进程时间的最佳方式之一。大多数移动电话收集用户位置数据以向用户提供更好的服务,并且它们通常允许用户访问他们的数据或请求副本。

一旦我们在成田机场着陆,我们就连上了互联网,GPS 定位开始被记录下来。平均每 5 秒收集一个点。通过观察一段时间内的点序列,很容易直观地看到我在什么时间在什么地方,并快速得出总距离或旅行总时间的结论。

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

成田机场从航班降落到行李提取的移动模式。“作者图片”。使用https://mobmap.locationmind.com/进行可视化

从航班落地到 2021 年 8 月提交报关单出境,我们用了 2 小时 20 分钟

向下采样数据点

以降低复杂性并更清楚地看到数据趋势,例如点累积的停止点。让我们把点数减少到每 10 秒一点,而不是每 5 秒一点。这个过程被称为子采样,在时间序列分析中被广泛使用。

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

将 GPS 数据的采样时间从 5 秒缩减到 10 秒

既然已经对数据进行了缩减采样,我们只想提取停止点。停止点表示一项活动,例如当你排队等待进行唾液测试或当你等待领取行李时。当有人停在同一个位置时,GPS 数据点会在同一点不断积累,很容易发现趋势。

通过速度检测行走点

为了捕捉这些停顿,我们首先需要移除我们行走或跑步的点。为了做到这一点,我们可以通过与前一点的比较来计算每个点的速度。人类的平均行走速度约为每秒 1.4 米。对我来说,我和我 2 岁的女儿一起走,所以速度几乎是每秒 1 米,这是在 velocity_mps 中,指的是每秒 1 米。

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

根据 GPS 数据计算速度(英里/秒)

接下来,我们要做的就是以等于或大于平均步行速度的速度丢弃数据点。由于我的行走速度本来就很低,所以去掉的都是高速点和飞机降落和移动时的点。然而以正常的行走速度。期待更好的结果。

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

从移动的 GPS 轨迹中快速滤除点

通过聚类查找停靠点

聚类是一种寻找公共数据点的技术,时空密度聚类或 STDBSCAN 是一种无监督的机器学习算法,用于聚类在空间和时间上接近的点,这些点可以表示潜在的停止。一旦我们在数据点上运行模型并调整参数。我们可以提取代表运动相对静止的停止点的相关点,如下所示。

每一站都代表了一个活动或描述我们最初为什么停下来的东西。在大多数情况下,我们可以将站点映射到附近的商店或餐馆等等。但在这种情况下,它特定于操作,因此我们可以手动标记这些点。毕竟他们只是几个集群。

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

使用无监督机器学习时空密度聚类检测 GPS 数据中的停靠点

测量每一站花费的时间

每道工序需要多长时间?

如果我们查看每个 GPS 聚类点,我们可以简单地找到每个聚类中时间最小的点和时间最大的点。这将代表站点的开始和结束。两者的区别在于停留的时间。在下表中,每个集群的持续时间代表我们完成每个流程所花费的时间。我们很放松,没有理由匆忙,我们也有孩子。所以单人跑步的时间可能会更短。

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

通过 STDBSCAN 聚类方法使用 GPS 数据测量停留时间

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

使用 GPS 数据为每个流程绘制机场旅客旅程图“图片由作者提供”

估计在机场的步行时间

步行时间是不同站点之间的时间,这是表征移动模式的一个重要部分。从一个地方走到另一个地方需要多长时间?根据数据计算,行走时间可以是上一个停靠点和下一个停靠点的第一个点之间的时间。下表列出了在中途停留的时间,包括四处闲逛或来回寻找下一站的时间,以及孩子们从玻璃上看飞机的时间。这是很常见的。尽管当一些点错误地没有被计算为聚类的一部分或者当一个小的停靠点被忽略时,行走时间可能被夸大。比如去洗手间。

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

机场不同流程间的步行时间估计

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

从成田机场的 GPS 数据点估计步行时间和停留时间

检测停止的大致位置

找到车站的大概位置有时很重要。当停车发生时,GPS 位置分散在一个点周围。这是因为移动电话中 GPS 的精度通常在 4 米左右。为了找到停止点的近似值,我们可以查看每个 GPS 点簇并估计该簇的质心位置。

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

基于“作者图像”聚类的 GPS 数据停留位置估计

决赛成绩

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

Covid Era 后的机场乘客旅程地图—成田机场从航班降落到行李认领的时间“图片由作者提供”

结论

  • 从航班降落到行李领取和通关大约需要 2 小时 30 分钟。
  • 等待唾液测试结果花费了大部分等待时间,随后是机场工作人员的应用程序下载和安装确认。
  • 从飞机上走到唾液测试地点花了大部分时间
  • 行李认领很快,因为现在使用成田机场的人很少

此分析/类似分析的商业机会

设计成功的设施体验始于监控现有情况。测量流程时间和绘制客户旅程可以反映这些流程的效率,以引入数据驱动的改进,并在迭代流程中不断改进运营(改善)。手机数据的无处不在和可用性为了解用户在离线世界的旅程和为这些客户提供的运营效率带来了机遇。引入数据驱动的性能监控产品有多个方面:

数据收集

数据收集带来了挑战,因为需要用户同意才能收集他们的数据。提供一种服务,例如一个专用于该设施的应用程序或免费 wifi,让客户同意提供他们的数据,并承诺保持匿名和安全,这是收集此类数据的一种方式。另一种途径是使用数据聚合公司或大规模运营手机应用的公司,并建立业务合作伙伴关系或数据共享协议。

数据代表性

收集的数据将始终代表一个样本。毕竟,并不是所有人都会安装这款应用或使用免费 wifi。即使与手机应用公司合作,也只能提供一小部分访问者。在计算聚合洞察时,这在数据处理标准中通常是可以接受的。此外,可以计算合适的比例因子,以获得有代表性的见解。

隐私

我很乐意在地图上告诉你我去过的地方。但是,大多数人知道这么多关于他们移动性的信息被提取出来并与他们的身份联系在一起,他们不会高兴的。此外,随着时间的推移,法规变得越来越严格。为了保持良好的隐私标准,需要遵循许多步骤,例如:

匿名化

来自用户的数据不应该追溯到他们的身份。这需要适当的私人信息散列在一个非反向的方式,如 SHA-2 或其他更复杂的散列不能反向工程。

聚合

应该聚合单个级别的计算洞察,以显示聚合产品的总体趋势或商业智能仪表板。例如,说名为 kyle、mark 和 Omar 的用户在这个过程中停留了 15 分钟,这不是一个好策略。相反,我们可以提取在该设施中停留的平均时间为聚合后 15 分钟± 3 分钟。

访问控制

当确保只有相关人员能够访问这些信息时,最大限度地减少管理员或数据用户的数量是最佳做法。

最终注释

数据驱动的运营增强不再仅仅是概念验证工作。它已经在许多企业和许多应用中大规模引入。以保护数据隐私标准的方式开始数据收集的能力将是一个实体未来采用数据驱动技术的关键。

话虽如此,了解服务时间和客户旅程的应用程序可以应用于许多设施和许多行业。举个例子,

商场

  • 根据需求对购物中心的不同区域进行动态定价
  • 提取工作日、周末和节假日之间行为差异的见解,以便更好地分配安保人员

工厂

  • 了解操作增强的每个过程所花费的时间
  • 通过绘制利用率热图找出未使用的空间或设施
  • 当紧急情况发生时,通过了解每个人的位置来管理人员安全

机场

  • 更好地了解高峰时间以及不同日期和周末服务时间的变化
  • 通过预测不同日期和不同地区的需求,分配更多或更少的人力资源

智能城市和住宅小区

  • 了解住宅的移动模式,以便更好地设计定制服务
  • 了解道路利用密度和 inro 根据重要性对道路进行排序的因素,以分配更好的维护策略

还有更多…

关于我

Mohamed Batran 是一名人工智能专家,也是一名在日本工作的数据货币化专家。在他的职业生涯中,他从事金融、电子商务、物流、电信、运输等行业的数据工作,设计数据利用来增加收入、降低成本或提高客户满意度。

您可以阅读同一篇文章或在此联系我,我将非常高兴收到任何评论、反馈或安排电话讨论合作事宜:

http://mohamedbatran.com/

10 分钟后起飞

原文:https://towardsdatascience.com/airtable-in-10-minutes-d06f7d73c6d1?source=collection_archive---------8-----------------------

实践教程

使用 Airtable 快速上手,了解它何时适合您

为什么要用 Airtable?

Airtable 结合了数据库的强大功能和电子表格的便捷用户界面。然后它还会在上面加一些樱桃。🍒对于许多用例来说,这是一个可靠的选择。

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

资料来源:pixabay.com

如果您正在组建一个没有数据专家的团队,并且您想要自动化、组织化和洞察力,您可能希望使用 Airtable 作为您的数据中心。和 Tableau 一样,这是一个快速学习的工具——也是你简历的一个很好的补充。🖋

在本文中,您将了解这种流行的关系数据库的基础知识,感觉就像是服用了类固醇的 Google Sheets。无论您是否使用过关系数据库,都会有一些陷阱——您也会看到。然后,我将分享如何充分利用 Airtable 的技巧。最后,我们将讨论一个可能让您组织中的技术人员和非技术人员都满意的解决方案。👍

有趣的是,谷歌正在推出自己的 Airtable 克隆版,谷歌表格——我可能会在未来的文章中探索它,所以请在 Medium 上关注 me 以确保你不会错过它。😀

Airtable 解决的是什么问题?

电子表格是分析数据的好工具,只需点击几下鼠标和几个公式。但是它们不太适合跟踪和显示数据中的关系。

关系数据库是存储大量数据和显示跨表关系的好工具。然而,如果您不了解 SQL,它们并不适合快速分析数据。

SQL(结构化查询语言)是从数据库中提取信息的方式。学基础不难,但是是另一种语言。学习一门新语言需要时间,对许多人来说是一个很大的障碍。不要脸的塞,我写了本记忆深刻的 SQL 这样你就能很快学会基础了。😉

如果你想使用数据库,但想避免使用 SQL,你需要一个程序员来创建一个 API 来显示你的数据——可能通过网站上的一个表单。创建和维护接口的技术工作需要时间、金钱和技术人力。💰

Airtable 是解决这一问题的低成本解决方案。它就像是数据库的内置图形用户界面(GUI)。换句话说,苹果对令人生畏的 DOS 命令行所做的,Airtable 对 SQL 数据库所做的。

接下来让我们深入探讨 Airtable 概念。👍

飞行表概念

要使用 Airtable,您需要知道一些术语,其中许多是直接从 SQL 借用的。

工作区是 Airtable 最高级别的抽象。如果您有多个工作空间,它们可能是您工作的多个组织的工作空间。

基地是数据库。你不能用 SQL 访问它们,但这就是 Airtable 正在做的事情。🚙

是 SQL 表。如果你没有使用过 SQL,你可以把表格想象成电子表格。

每一行都是一个记录

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

Jeff Hale 添加了网格视图和标注的示例表格

列被称为字段。田地很重要,所以我们开始挖吧。

单个字段包含相同类型的数据。可能的数据类型包括通常的文本、整数、小数和日期。Airtable 为其他一些常见的数据类型增添了新的光彩,包括经过专门验证的字段,如电子邮件地址和电话号码。📞复选框是一个布尔值 True-False 列。✅

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

可以选择字段数据类型的菜单。

另一个字段选项是附件。这实际上只是一个指向存储在 Airtable 服务器上的文件的链接。如果你上传了一张图片,你可以点击缩略图来查看完整的版本,下载它,或者留下评论给其他用户看。

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

甚至还有条形码字段数据类型。作为库存跟踪系统的一部分,你可以扫描 Airtable 的 Android 或 IOS 应用程序的条形码。两款应用都获得了极好的评价。哦 Airtable 也有一个星型数据类型。⭐️⭐️⭐️⭐️⭐️

我发现 Android 应用程序易于安装和使用基本功能,但主要是在我的电脑上使用 Airtable,因为它有表格。😉

您也可以在公式字段*中输入公式。*语法类似于 Google Sheets 或者 Microsoft Excel。你可以组合列中的值,用 if 语句控制流程,等等。这里有一个游乐场,你可以在这里玩各种功能。

添加字段菜单中,您可以创建到另一个表的连接。选择链接到另一条记录,然后在链接表中选择要加入的字段(您的外键是 you speak 数据库)。这就是在两个表之间创建持久连接的方法。😀

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

通过添加查找字段,您可以选择在下一个屏幕上显示更多的字段,但这不是必须的。稍后,您可以通过添加查找字段来选择显示更多来自连接的字段。

连接的表将链接字段作为一列。然后,您可以将特定记录添加到链接字段中。或者创建一个将被添加到链接字段的新记录。链接字段有点像两个表之间的魔法入口。💫

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

选择要链接的记录,或创建新记录

通过这些持久链接来连接表需要一些实践——无论您是数据库新手还是 SQL 专家。

Airtable 让你添加漂亮的元数据字段。例如,您可以看到谁以及何时创建和更新了记录。当然你也可以用我最常用的键盘快捷键 CMD + Z 在 Mac 上撤销事情(在 Windows 上是 CTRL + Z )。

凉爽的景色😎

Airtable 的观点是一个卖点。视图是以各种可视格式显示表格数据的方式。

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

从空中拍摄的漂亮照片!📸

网格视图是普通的表格,就像你从电子表格或数据库查询中得到的一样。您可以操纵网格视图来显示您想要的数据。例如,下面是一些伪 SQL,用于过滤、排序和隐藏列:

SELECT col1, col2
FROM my_table
WHERE col1 > 3
ORDER BY col2 DESC;

要在 Airtable 中创建这个查询,可以使用顶部的菜单按钮。

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

菜单按钮

创建视图时,可以隐藏除列 1 和*列 2 之外的所有字段。*或者你可以过滤所有满足某种条件的记录,比如 *col1 > 3。*您可以使用分组按钮对记录进行分组。最后,您可以通过单击鼠标按列对记录进行排序。👍

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

部分分组

如果您了解 SQL,请将 Airtable 网格视图想象成 SQL 视图。

您可以隐藏视图中的字段。这就是为什么您会得到与在 SQL Select 语句中列出列相同的结果。

你查看的是一张桌子的实况。如果有人更新了为您的视图提供信息的表,它会以近乎实时的方式进行更新。

Airtable 有一种很好的方式来聚合字段中的信息。您可以通过在网格视图的底部显示字段的描述性统计信息甚至直方图来汇总列。

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

这些数据没有太大偏差。

网格视图不是显示数据的唯一方式。只需点击一下,您表格中的数据就可以显示为日历、看板或图库。付费计划也可以看到甘特图视图。这些观点超级俏皮。就好像他们给了你为团队成员添加各种前端应用的权力。🎉

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

看板视图

“视图”菜单也是您可以制作表单以将数据放入表格的地方。虽然把一个表单想象成一个视图有点奇怪,但这就是你在 Airtable 中找到选项的地方。🤔

Airtable 使用您的表格列和数据类型来自动生成可自定义的表单。

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

表单生成器视图

快速表单生成真的很好。👌

自动化🏄‍♀️

Airtable 自动化可以设置为每次触发某个触发器时运行。例如,当一个表中的记录被更新时,可以向另一个表中添加新行。每个月,Pro 计划让您运行 50,000 次自动测试。免费计划每月给你 100 英镑。

自定义自动化类似于 Zapier 的 zaps 或其他无代码解决方案。调试时,UX 可能会更清晰一点,错误消息可能会更有帮助一点,但是应用程序完成了工作。

截至 2021 年年中,Airtable 的内置自动化集成包括许多谷歌产品和其他几种流行的服务。我预计应用程序的数量很快会增加。

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

自动化集成的子集

如果你想要其他的操作,你可以使用你喜欢的集成工具,比如 Zapier, Integromat ,或者 IFTTT 。例如,Zapier 有 24 个 Airtable 和 Slack 的集成。👍

应用程序

Airtable 在其内置应用程序下集合了许多功能。应用程序包括基本的数据可视化、数据透视表、重复数据删除、更高级的 CSV 导入和运行自定义脚本。例如,下面是运行脚本进行查找和替换的代码片段。

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

查找和替换脚本

这很容易,但如果能看到这个非常普通的操作被移植到 Airtable 的核心功能中,那就太好了。

在网格视图中快速查找记录是可能的,在 Mac 上使用可靠的键盘快捷键 CMD + F (在 Windows 上使用 CTRL + F )。

Airtable Base schema 应用程序非常适合可视化您的表以及表中字段的关系。您可能知道该示意图是企业资源图(ERD)。

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

ERD 航空公司

设置建议

以下是帮助您成功设置 Airtable 的一些提示。🎉

  • 使用很少的碱基。你不能轻易地在基地之间分享信息。你的工作空间里可能只有一个基地,这很好。刚接触数据库或 Airtable 的人可能会创建一堆库。您不希望这样做,因为您失去了关系数据库的主要功能,即能够轻松地查看关系并保持数据同步。
  • 为每条记录使用唯一的主键。您将使用第一列作为与其他表链接(联接)的主键。如果每条记录的主键不是唯一的,这种情况就会发生。您可能需要经常进行重复数据删除,以确保您的数据有意义。
  • 如果您将相同的数据放入两个表中,那么您应该在其中一个表中使用链接列。这样,您就不必担心人们在一个地方更改了数据,而在另一个地方没有更改,从而导致表不同步。
  • 自由使用视图。一个表可能有许多视图。

随着时间的推移,你应该有很少的基础,很多的表,很多的视图。👍

高级飞行表

如果您想要与您自己的 SQL 数据库自动同步——无论是查询该数据库还是使用像 PowerBI 这样的工具,您都可以使用 Sync Inc 。它旋转出一个可查询的数据库,并与你的 Airtable 数据库保持同步。

您可以使用 Airtable API 并构建自己的集成。 Kaleb Nyquist 有一些关于使用 Python 的请求库从 Airtable 上传和下载数据的精彩讨论和代码,这里pyAirtable 使得与 API 的交互更加容易。

您可以向基、表、字段和视图添加元数据说明。只需右击你想要描述的对象。这对团队沟通是有帮助的。

你可以很容易地设置 Airtable,当你被提到时,它会接收电子邮件或短信,因为谁不想要更多的提醒。🙃

如前所述,Airtable 支持使用 Javascript 编写脚本。您可以创建操作脚本或使用脚本块。有什么区别?脚本块是为在 Airtable 中工作的人准备的。当您需要团队成员输入一些信息作为自动化的一部分时,可以使用它。相比之下,自动化脚本在后台自动运行。😎

还有一个可用的 API ,每秒最多 5 个请求。它有一个非常好的自我记录的例子。除了 Javascript Ruby 和。NET 客户端可用。文档中没有链接 Python 客户端,但是 pyAirtable 包可以很好地获取和更新记录。🐍

局限性和成本

那么为什么大家都不用 Airtable 而用 SQL 呢?有三个主要原因:成本、大小限制和没有原始 SQL 访问。

Airtable 有一个免费计划,但许多团队会发现他们需要每个用户 20 美元的 Pro 计划。我上次看到的 Enterprise 的起价是 60 美元一个座位,它提供了更多的功能,包括每个基座最多 100k 条记录。点击查看更多关于价格和功能的信息

Airtable 不是大数据解决方案。Pro 计划为您提供每基地最多 50,000 条记录,Enterprise 为您提供 100,000 条记录。有几百万行数据?Airtable 不是你的工具。☹️

Airtable 不会让你轻易跨垒。你可以同步整个表格,或者用集成和管道胶带把一些东西拼凑在一起,但是不可能链接单独的记录。如果你正在为一个客户整理一碗满是馅料的意大利面,你可能会发现自己在下载 CSV 文件,并使用 Airtable 应用程序上传它们。🍝

与此相关的是,Airtable 不允许您直接在数据库上执行 SQL 查询。如上所述,与 Sync Inc .一起使用它对于大型团队来说可能是一个双赢的解决方案。没有技能的人可以在 Airtable 中添加数据和自助查询。你那些想做高级事情的数据分析师可以在 Airtable 之外为自己服务。🎉

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

Airtable 是满足您数据需求的瑞士军刀。资料来源:pixabay.com

我的团队应该使用 Airtable 吗?

如果你的团队和你的数据都不庞大,并且你没有额外的数据和技术人员,这是一个不错的选择。你可以用它来解决很多常见的商业问题,而且不会破产。

Airtable 的入职流程非常快。一个稍微使用过电子表格的相当精通技术的人应该能够在几天内掌握基本知识。Airtable 文档很棒,用户界面非常直观。也就是说,使用更有经验的人确实有助于确保你为成功做好准备。👍

值得注意的是,Airtable 公司并不是昙花一现。🍳这家资金雄厚的初创公司成立于 2013 年,最近估值近 60 亿美元。

正如这个关于 Airtable 公司战略的大讨论所解释的,Airtable 对于一个 1000 人的销售部门来说并不是最全面的解决方案。为此,有 Salesforce 或其他专门的解决方案。但是 Airtable 对于小团队来说是一把很棒的瑞士军刀。👍

包装

在本文中,您已经学习了如何使用 Airtable。现在出去把你的手弄脏。个人客户关系管理是一个很好的第一个项目,可以创造一些有价值的东西,并学习该工具的基础知识。

我希望这个指南对你有所帮助。如果你有,请分享到你最喜欢的社交媒体上。🚀

我教授、咨询和撰写关于、Python 、数据科学和其他技术主题的文章。如果你对此感兴趣,请在这里阅读更多的并订阅我的 Data Awesome 时事通讯,获取有用数据资源的不定期更新。

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

资料来源:pixabay.com

快乐播音!🛩

注:截图是我自己从 Airtable 的模板基础。

Airtable & Python 使之成为可能 II:使用 Airtable 的 API 将数据从 Python 上传到 Airtable

原文:https://towardsdatascience.com/airtable-python-made-possible-ii-uploading-data-into-airtable-from-python-using-airtables-api-3075009abf98?source=collection_archive---------14-----------------------

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

作者的图片说明。

如何将 Python 设计的数据存储回 Airtable 用户友好的关系数据库

内容:

了解关系数据&记录 id
匹配字段值到记录 id
在 Airtable
匹配(&上传)多条记录
更新 Airtable
中的记录从 [pandas](#08b3) 到 Airtable
🎉复制粘贴表格功能⏮️第一部分:将 Airtable 数据下载到 Python 中

Python 是一种成熟的编程语言,尽管年代久远,但最近经历了某种复兴——最近成为第二种最广泛使用的通用编程语言。这种繁荣可能是由数据科学领域的快速发展推动的,Python 在这一领域占据主导地位,因为 Python 相对容易学习,但对数据工程和数据分析都很有用。

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

请务必阅读本教程的第一部分,使用 Airtable 的 API 将 Airtable 数据下载到 Python 中。

因为某些经济部门获取丰富数据的门槛相对较低,所以它们采用 Python 驱动的数据科学的速度相对较快。例如,金融部门从根本上讲是关于一个特定的数据点——“价格”——因此毫不奇怪,像花旗集团这样的组织向其新任分析师教授 Python 来管理他们的价格数据。经验科学,无论是应用科学还是学术科学,从根本上讲都是关于数据驱动的观察,因此所有学科的许多科学家都学习 Python 作为他们教育的一部分,以理解他们观察到的所有数据点。当然还有软件开发部门,包括我们每天花费越来越多的时间参与的所有应用程序,如网飞,这些应用程序将我们在其平台上的每次点击、查看或其他交互记录为数据点。猜猜看,网飞在“整个内容生命周期”中使用 Python 来优化他们的产品。

然而,在获取丰富数据方面,并不是每个组织都这么容易。例如,我的专业是非营利和社会变革部门。对于我们这些在“真实世界”(即,而不是在电脑屏幕或股票报价机后面)中工作的人来说,获得关于我们运营的有用数据可能需要一些真正的努力和规划。好消息是,一旦我们获得了这些数据,Python 的能力就变得唾手可得了。换句话说,我相信获取数据的最初障碍并不会使“真实世界”的组织丧失利用 Python 所提供的功能的资格。

进入气动工作台。Airtable 将关系数据库结构与用户友好的图形界面结合在一起,降低了入门门槛(特别是对于那些以低数据素养为特征的“真实世界”组织环境)。理想情况下,我们不仅希望能够在 Airtable 中收集可以在 Python 中使用的数据,还希望能够在 Python 中生成可以在 Airtable 中查看的数据集。拥有这种功能可以实现数据透明和审计,同时也使组织中的非程序员能够自己分析数据。

在之前的教程中,我一步一步地讲解了如何使用 Airtable 基础的 API 将 Airtable 数据下载到 Python 中。在这里,我带来了完整的教程:如何使用相同的技术和requests库将 Python 数据上传到 Airtable 的分步指南。然而,要充分利用 Airtable 的关系数据结构,需要一些仔细的预处理。本教程将涵盖这两个方面:首先是预处理步骤,然后是实际的上传步骤——上传步骤是在 Airtable 中创建新记录还是更新旧记录。

🎉特别奖励:如果你没有时间看完整的教程,请点击这里访问我的防呆的 Airtable 上传功能,我将其推广用于多个项目。您可以按原样运行它,它将指导您查找任何缺失的信息(例如,从哪里获取 API 密钥)并突出显示可能的错误。欢迎你免费复制、粘贴和修改这段代码,但是如果你想分享你的感激之情,你可以点击这里给我买杯咖啡

了解关系数据和记录 id

与 Google Sheets 或 Microsoft Excel 相比,Airtable 的“魔力”在于关系数据的集成。除了更加规范的数据管理,Airtable 的关系数据结构意味着一个表中的数据可以在另一个表中访问,以便于分析。这是通过“链接到另一个记录”字段类型完成的。

例如,如下图所示,在“People”表中有四个条目在 Rogers Park 工作。这些人的名字是布鲁斯·巴克、杰拉德·格里尔、卢拉·洛扎诺和马尔孔·麦金托什,他们分别在 9、3、4 和 8 班工作。在“位置”表中,这些人汇总在一行中,总共有 24 个班次。

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

**图 1:“链接到另一个字段记录”字段类型如何创建关系数据结构。**图片作者。

在图形 web 界面中,关系数据由浅蓝色方框表示,带有与“主字段”相对应的可读文本。当我们通过 API 而不是图形 web 界面访问 Airtable 数据时,这种关系数据看起来非常不同,可能有点吓人。

请考虑“人员”表中的观察结果:

{'id': 'recrN5WVNHl1pGxET',
 'fields': {'Name': 'Bruce Buck',
             'Shifts': 9,
             'Location': ['rec887G00dQIujFel'],
 'createdTime': '2021-02-17T22:59:38.000Z'}

并且,从“位置”表中:

{'id': 'rec887G00dQIujFel',
 'fields': {'Name': 'Rogers Park',
            'People': ['recrN5WVNHl1pGxET',
                       'recMQieZAnYIu860r',
                       'recXyTN7Mo9LNtxhe',
                       'recqYx6e3BrvxFv2s'],
            'Total Shifts': 24,
 'createdTime': '2021-02-17T22:59:56.000Z'}

如果仔细观察,您会发现直观表示为“Bruce Buck”的数据的idrecrN5WVNHl1pGxET,而直观表示为“Rogers Park”的数据的idrec887G00dQIujFel。通过像这样使用记录 id 来引用关系数据,Airtable 可以灵活地处理可能出现的复杂性(例如:如果有两个不同的 Bruce Bucks 呢?如果用户改变了定位的方式,不再用名字,而是用街道地址,那该怎么办?).

当通过 API 将数据从 Python 上传到 Airtable 时,这种关系数据结构就有了含义。例如,假设我们有一个编码的 webscraper 在一个关于 Rogers Park 的网站上寻找 Bruce Buck。webscraper 不是寻找与"recrN5WVNHl1pGxET"匹配的字符串,而是寻找与"Bruce Buck"匹配的字符串。但是如果我们上传"Bruce Buck"到一个关系数据字段,而不是一个记录 id 数组,Airtable 的 API 将为列 错误返回一个 无效值。

幸运的是,这是一个简单的问题,有一个显而易见的解决方案,(除了几个例外)将可靠地工作,正如我们现在将看到的。

将字段值与记录 id 匹配

在 Python 中,字典是基本的“映射”类型,用于将一个值从另一个值或“键”转换。出于我们的目的,我们需要创建一个记录 id 和字段值的字典,如下所示:

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

**图 2:记录 id 和字段值的字典。**图片作者。

使用 Airtable 记录的列表,比如从本教程的第一部分(“下载”)生成的记录,作为起点,只需要一些简单的 Python 代码就可以创建这个字典。

1 | record_dict = {}
2 | match_field = "Name"3 | for record in airtable_records:
4 |     if match_field in record['fields']:
5 |         record_value = record['fields'][match_field]
6 |         record_dict.update({record_value : record['id']})

第(1)行创建一个空字典。第(2)行定义了 Airtable 列,我们将记录 id 与该列的值进行匹配。第(3)行开始对每个 Airtable 记录进行迭代,为了防止错误,第(4)行检查我们从中提取数据的字段中是否存在值。第(5)和(6)行获取这个值,将它与记录 id 匹配,并相应地更新字典。

⚠️ 注意,在这个解决方案中,如果有重复的值(例如,两个“Bruce Buck ”),就会产生冲突。这可以用 in air table(“Bruce Buck 1”和“Bruck Buck 2”)或 Python(用附加代码)解决。这个问题的最佳解决方案将依赖于上下文。

创建了这个字典后,我们可以开始映射过程,如下图所示:

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

**图 3:使用 Python 字典从概念上匹配惟一字段值和 Airtable 记录 id。**图片作者。

有许多方法可以达到这个结果。对于单个值,record_dict["Dawn Douglas"]record_dict.get("Dawn Douglas")都可以;对于熊猫数据系列,pd.Series(data).map(record_dict)将转换它能找到匹配的所有值。

但是,如果我们找不到匹配的呢?这就是将数据上传到 Airtable 的过程变得相当复杂的地方,但如果我们愿意采取一些额外的步骤,仍然是完全可行的。但是首先我们需要通过 API 在 Airtable 中创建新记录的基本机制。

在 Airtable 中创建新记录

在本教程的第一部分的中,我们使用[requests](https://2.python-requests.org/en/master/)库通过 GET 方法从 Airtable 下载数据。现在,使用类似的代码,我们将使用 POST 方法创建一条记录(稍后,我们将使用 PATCH 方法更新一条记录)。

比较一下,注意用斜体标出的差异:

**# Download**
response = requests.*get*(url, *params=params*, headers=headers)**# Upload New** response = requests.*post*(url, *data=upload_json*, headers=headers)

我们可以使用相同的网址("https://api.airtable.com/v0/" + base_id + "/" + table_name)用于下载和上传。但是,我们必须扩展标题,以便:

{"Authorization" : "Bearer " + api_key,
 "Content-Type" : "application/json"}

这个新的Content-Type头的存在是对我们的一个暗示,当上传数据到 Airtable 时,我们现在以 JSON 的形式发送数据(你可能认为这是下载时传递参数的镜像)。

为了具体说明这一点,我们来看一个例子。

**# Step 1**
upload_data = {"Name" : "Otis Osborn",
               "Shifts" : 9,
               "Location" : ["rec887G00dQIujFel"]}**# Step 2**
upload_dict = {"records" : [{"fields" : upload_data}], 
               "typecast" : False}**# Step 3** upload_json = json.dumps(upload_dict)**# Step 4**
response = requests.*post*(url, data=upload_json, headers=headers)

步骤(1)创建了一个我们想要上传到 Airtable 的数据字典。请注意字符串、整数和列表数据类型的使用。这里确保字段名和数据类型匹配是很重要的——如果您遇到错误,请参考您的库的 API 文档

步骤(2)将该数据子集化到 Airtable 的 API 可以读取的另一个字典中。您可以将"typecast"设置为真或假。如果由于某种原因,您无法在步骤 1 中获得匹配的数据类型,将此设置为 True 会将字符串转换为 Airtable 对相应数据类型的最佳猜测。

步骤(3)将这个字典转换成 JSON,步骤(4)将最终产品上传到 Airtable。如果成功,Airtable 将发送回一个响应,当调用response.json()时,该响应将如下所示:

{'records': [
  {'id': 'recoiMuxqVvbNMRlG',
   'fields': {'Name': 'Otis Osborn',
              'Location': ['rec887G00dQIujFel'],
              'Shifts': 9},
   'createdTime': '2021-02-19T14:41:41.000Z'}]}

请注意,除了“创建时间”之外,我们现在还有另一个关键的新数据,一个专门针对该记录的 id。

我们可以通过检查图形界面来验证是否添加了 Otis Osborn:

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

**图 4:在图形界面中识别新记录。**作者图片。

很简单。这样可以一次只向 Airtable 添加一条记录。然而,当我们开始批量匹配和创建多个任意大小的 Airtable 记录时,我们开始遇到匹配问题。

匹配(&上传)多条记录

之前,我们使用基于 Airtable 数据下载的 Python 字典将字段值与记录 id 进行匹配。然而,当我们将新数据上传到 Airtable 时,Python 字典就过时了。

例如,想象一下,如果我们在数据集中两次遇到“Otis Osborn ”,并且我们知道这个“Otis Osborn”是同一个人(即,不存在 Otis 1 和 Otis 2)。如果我们在匹配多个记录时没有保持 Python 字典的更新,那么将会为同一个 Otis Osborn 创建两个单独的记录。

一种解决方案是在每次新上传后重新下载 Airtable 数据,但这将是带宽密集型的,尤其是对于较大的数据集。一个更好的解决方案是使用我们在向 Airtable 上传新的关系数据条目时收到的响应数据来更新 Python 字典。

下面,这个过程就直观的表现出来了。

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

**图 5:当没有找到预先存在的匹配时,创建一个具有唯一字段值的新记录的过程。**与上面的图 3 比较。图片作者。

在您将该图与上面的图 3 进行比较之后,让我们考虑如何对这些步骤进行编码。

步骤 1:尝试将字段值与记录 ID 匹配

match_value = "Otis Osborn"
record_id = record_dict.get(match_value)

这里,我们将一个 Airtable 字段值与一个记录 id 进行匹配。在这个特定的例子中,我们知道 Otis Osborn 不在字段值和记录 id 的字典中,所以record_dict.get("Otis Osborn")将返回一个 Python NoneType 对象

第二步:在 Airtable 中新建一条记录

match_field = "Name"
if record_id is None:
    upload_data = {match_field : match_value}
    upload_dict = {"records" : [{"fields" : upload_data}]}
    response = requests.post(url, data=upload_json, headers=headers)

因为记录 id 是None,我们指示计算机将 Otis Osborn 上传到 Airtable。我们创建一个简单的数据字典,将这个简单的字典添加到为 Airtable 上传而格式化的“上传字典”中,然后发送一个 POST 请求。

第三步:解析 Airtable 响应

airtable_record = response.json()['records'][0]

上面的代码帮助我们导航 Airtable 响应。因为我们成功上传了一条记录,所以我们取回了一条记录,索引在[0]

第四步:获取 Airtable 记录 ID

record_id = airtable_record['id']

记录 ID 应该类似于:rec3QjKqz8RiCz26r。这使我们到达了相同的点,好像我们已经在字典中有了这个字段值和记录 ID 对,但是如果我们想要避免重复上传,我们还有一个步骤。

第五步:更新字段值和记录 id 的字典

record_dict.update({match_value : record_id})

恭喜你。至此,我们已经完成了进行匹配代码的另一次迭代所需的所有工作。保持这个 Python 字典与 Airtable 同步是通过 API 上传数据最困难的部分。

现在我们已经完成了匹配和/或创建记录的复杂过程,我们准备进入上传过程的最后一部分:使用 Python 更新 Airtable 记录。

更新 Airtable 中的记录

在 Airtable 中更新记录的过程与创建记录的过程非常相似,只有几个关键的区别,具体如下。

第一个区别是 API 请求中使用的 URL:它需要指向我们正在更新的特定记录。幸运的是,我们需要做的只是将记录 ID 附加到我们用来创建新记录的 URL 上,就像这样:

url + "https://api.airtable.com/v0/" + base_id + "/" + table_name
record_url = url + "/" + record_id 

第二个区别是我们通过 API 发送的数据字典。由于我们在更新时一次只上传一条记录,所以字典要简单得多(参见上面的步骤 2)。

upload_dict = {“fields” : upload_data, “typecast” : typecast}

第三个区别是我们使用的 RESTful 方法。为了创作,我们发帖;为了更新,我们将打补丁,就像这样:

**# Upload Update** response = requests.*patch*(record_url, *data=*upload_json, headers)

与本教程的其余部分相比,这似乎没什么大不了的,但是更新 Airtable 记录的能力允许您创建可伸缩的数据解决方案,将 Python 的分析能力与 Airtable 的用户友好的数据存储能力结合起来。

从熊猫到飞行桌

[pandas](https://pandas.pydata.org/)是 Python 中一个流行的数据分析和操作包。在处理 Airtable 数据时,我们可能会有一个类似于下面这样的 pandas 数据帧,其中记录 id 构成了索引值:

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

**图 6:熊猫数据表,在 Jupyter 笔记本界面上显示。**图片作者。

在这种情况下,我们的第一步是将 dataframe (" df")转换为字典中的字典。我们可以使用代码为df.to_dict(orient="index")的来实现这一点,它将生成如下所示的内容:

{'rec6vFIUEH4Fk9Z4a': {'Shifts': 4,
  'Name': 'Alva Arnold',
  'Location': ['recyz79aQzGl3LXPT']},
 'recrN5WVNHl1pGxET': {'Shifts': 9,
  'Name': 'Bruce Buck',
  'Location': ['rec887G00dQIujFel']},
 'recUzv7g6PZi4FGbB': {'Shifts': 8,
  'Name': 'Charlotte Chaney',
  'Location': ['recSZBITRlt2juAJ0']},
 ...}

我们现在可以迭代字典中的每个键值对,如下所示:

dict_of_dicts = df.to_dict(orient="index")
for record_id, upload_data in dict_of_dicts.items():
   record_url = url + "/" + record_id
   upload_dict = {"records" : [{"fields" : upload_data}]}upload_json = json.dumps(upload_dict)
   requests.post(url, data=upload_json, headers=headers)

现在,我们可以无缝地从 pandas 转移到 Airtable,反之亦然(见本教程的第一部分下载 Airtable 数据到 pandas dataframe )!

结论

来源: GIPHY

首先,如果你遵循了上面的每一个步骤,仍然有问题,欢迎你将我的简单的 Airtable 帮助函数复制并粘贴到你的项目中。这个 Python 代码片段不仅将上述所有思想集成到一个函数中,而且还将打印故障排除消息,以帮助您找出不工作的地方。

一旦你把 Airtable 上传到工作中,天空就是极限。我使用 Python-to-Airtable 上传来促进数据审计方面的协作,增加数据分析的透明度,并用生成的数据作为数据库的种子。给我写封短信分享你创造性的 Python-Airtable 集成!

对于 Python- Airtable 开发者来说,有令人兴奋的消息,据报道,更多的功能正在向我们走来。特别是,有一个元数据 API正在开发中,它让开发者能够列出库、表、字段类型和视图。除此之外,这将使定位下载数据和上传数据更加容易,而不会因为键错误或数据类型不匹配而中断。当元数据 API 发布时,如果您对本教程的第三部分感兴趣,请对本文发表评论或鼓掌。

承认

甘的专辑封面

原文:https://towardsdatascience.com/album-covers-by-gans-c5c8ef48f50c?source=collection_archive---------28-----------------------

一步一步的代码和直觉指南生成专辑封面。

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

WGAN 生成的专辑封面随机样本

是的,甘斯很酷。

如果你不知何故偶然发现了这篇小文章,可以肯定地说,你对ggenerateanetworks—GANs 有点兴趣。

我绝对是。在网上看到无数令人惊奇的项目时,我也想创造一些有趣的东西。从人脸生成到图像恢复,GANs 的能力吸引了我——我需要学习更多。

完成了经典的 MNIST 和猫狗教程,我想知道…现在呢?正如你可能从标题和图片中知道的,是专辑封面抓住了我的好奇心。

目录

1。为什么是专辑封面?

2。编码专辑封面生成器

3。数据预处理

4。创建发电机

5。创建鉴别器

6。培训时间

7。结果——任何项目中最激动人心的部分

8。我们如何改进我们生成的专辑封面?

9。WGANs

10。WGAN 的实现

11。更好的 WGAN 结果!

项目回购环节

为什么是专辑封面?

看看下面的专辑封面,你注意到了什么?

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

照片由粘土银行Unsplash 上拍摄

这个例子揭示了一个有趣的观察结果——这些不同的封面之间似乎很少有一致性,至少在我看来是这样。

事实上,当深入研究我们的专辑封面数据集时,有各种各样的颜色、图案、形状、纹理、文字……不胜枚举。

单纯的甘能看懂什么是专辑封面吗?如果有,这种理解会是什么样子?

我开始尝试回答这些问题。

编码专辑封面生成器

作为对读者的一个快速提示,我假设对 GANs 的工作原理有一个基本的了解。网上有许多令人惊叹的资源可供学习,但这里有一些是我最喜欢的:

预处理数据

与任何机器学习项目一样,我们从预处理数据开始。

我们的目标是将原始数据集转换成可以将处理过的图像输入到我们的训练管道中的东西。通过利用 PyTorch 的数据加载器,我们可以用几行代码完成这两项任务。

将图像预处理到数据加载器中

创建生成器

准备好数据加载器后,我们要设置生成器模型。我们的模型将基于 PyTorch 教程中的 DCGAN。

我们的生成器将负责生成专辑封面的创建。

发电机模型

创建鉴别器

鉴别器是等式的下一部分。我们的鉴别器的工作是简单地将给定的图像分类为生成的或真实的。

由于创建专辑封面的复杂性,我们过于简单的生成器可能无法创建最令人信服的专辑封面。为此,我们可以满足于一个简单的卷积分类模型作为我们的鉴别器。

鉴别器模型

训练时间

数据…检查。发电机…检查完毕。鉴别器…检查。训练时间到了!

GAN 的训练过程可以归结为我们的生成器和鉴别器之间的最小-最大博弈。我们希望训练这两种模型相互对抗,以改进彼此。

首先,我们初始化我们的模型并定义损失函数和优化器。对于我们的 GAN,二进制交叉熵损失函数将工作得很好。我们的优化器将利用学习率为 0.002 的 Adam 优化算法。

对于我们的鉴别器的训练管道,我们希望将生成的和真实的样本用正确的标签输入到我们的模型中。

这个过程将感觉非常类似于典型的两级分类训练管道。

甄别训练程序

对于我们的生成器,我们将输入 0 到 1 之间的值的正态分布向量,以生成 120 x 120 像素的 RBG 图像。生成之后,我们将要求鉴别器在计算损失值和相应地调整生成器之前对我们的图像进行分类。

发电机培训程序

现在已经定义了所有的培训管道,我们可以开始培训过程了。在 Google Collab 上运行这个模型 15 个时期花费了相当多的时间,所以吃点零食,放松一下,享受一部电影吧!你应得的!

训练周期

结果——任何项目中最激动人心的部分

与大多数 GAN 项目一样,我们的损失值不能告诉我们多少关于生成图像的质量,所以我将从这里排除它。但是,让我们来看看我们生成的样本!

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

DCGAN 结果

嗯,它们看起来没有我希望的那么好。

有了香草甘架构,似乎我们能够捕捉专辑封面的一些基本特征。我们可以看到各种各样的颜色和形状。

然而,我们遇到了重复模式的问题,也被称为模式崩溃。这些形状也不能把自己建成任何明确的结构。

总的来说,不是最好的结果。

我们如何改进我们生成的专辑封面?

我们有几个选择可以探索。

我们可以尝试在我们的生成器模型中调整一些参数,但是超参数化模型的过程可能是冗长而缓慢的。

嗯,我们可以多训练我们的网络吗?大概不会。我们已经遇到了模式崩溃的迹象,所以进一步的训练可能会加剧这些影响。

那么我们为我们的 GAN 尝试不同的架构怎么样?

这可能行得通。

WGANs

Wasserstein GAN 已经被证明可以显著提高 GAN 的生成能力,同时也解决了模式崩溃和消失梯度的问题。

这两种架构的主要区别在于:

WGAN 的实现

让我们首先创建批评家。批评家和鉴别者真的是一样的,只是批评家最后没有包含一个 sigmoid 激活层。

我们将继续使用二进制交叉熵损失函数以及 Adam 优化算法。然而,我们将不得不对训练管道进行一些调整,以包括梯度惩罚。

梯度惩罚有助于约束批评家保持李普奇兹常数(有益于优化)。我们将采用这个梯度罚值,并将其纳入我们的评论家的损失。

定义了新的 WGAN 训练管道后,我们可以像以前一样运行相同的训练循环,并等待我们的新结果!

更好的 WGAN 结果!

正如我们从这篇文章的第一张图片中看到的,与我们的 GAN 结果相比,WGAN 生成的样本看起来更像专辑封面。

生成器模型可以更好地捕捉抽象的形状、纹理、颜色范围,甚至可能的文本模式。

下面,是我最喜欢的几个!

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

我最喜欢的样品封面

在最左边,我看到图像顶部附近有一个较浅的模糊图案。对我来说,这类似于出现在许多专辑封面上的文字。一个建筑上的变化就能捕捉到这种抽象的模式,真是太神奇了。

右边的两幅图像似乎显示了一个人的场景。在左边,我看到一个人在向远处的另一个人挥手。在右边,我看到两个女孩站在一起,看着黄色的草地。

一个简单的 WGAN 可以生成如此细节和色彩的图像,这是非常令人惊讶的。

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

一些结果之间的插值

生成性对抗网络是强有力的工具。全世界都清楚,这种技术的实际应用是无穷无尽的。

唯一的问题是…你打算用它做什么?

算法偏差

原文:https://towardsdatascience.com/algorithmic-bias-fff4d8c31290?source=collection_archive---------41-----------------------

当算法模仿和放大刻板印象时

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

资料来源:联合国人类住区规划署

谁在泰坦尼克号灾难中幸存了下来?

回想一下泰坦尼克号电影,救生艇附近的男人在尖叫——女人和孩子优先!现在,随着一些崭露头角的数据科学家探索著名的泰坦尼克号数据集(也可在 Kaggle 上获得)以预测谁幸存,在探索性数据分析的最初几步中,人们会得出结论,妇女和儿童幸存的概率更高。这些数字还表明,坐在较高阶层的人比坐在较低阶层的人有更高的生存机会,避免贿赂或地位偏见。

现在,如果有人随机问我——美国广播公司在泰坦尼克号灾难中幸存了吗?我的回答是 ABC 是女性吗?他/她富有吗?我只是放大了我的认知系统通过观看电影和探索数据集建立起来的经济地位偏见性别偏见

如果假设,泰坦尼克号数据集将被旅行社用于邮轮保险,它将预测女性的存活率高于男性的存活率;因此,与男子相比,向妇女收取的保险费较低。

主流应用中的偏差

偏见与信用额度 2019 年,苹果联合高盛推出信用卡。当科技企业家大卫·海涅迈尔·汉森在推特上说他被批准的信贷限额比他妻子被批准的限额高 20 倍时,事情发生了错误,尽管他们申报了联合税。包括苹果联合创始人史蒂夫·沃兹尼亚克在内的许多其他人表示,同样的事情也发生在他们身上。在这种情况下,如果算法是预测信用额度的算法,保持其他一切不变(税收、资产和负债),女性的信用额度预计会低于男性。

偏见和工作门户 几年前,亚马逊创建了一个内部招聘工具,根据简历是否符合工作描述/历史角色定义对简历进行排名。后来人们发现,这个工具并没有产生不分性别的排名。使用这一工具时,妇女的级别比男子低。

偏向和面部识别 许多面部识别技术已经以生物识别支付、机场移民检查、相机中的内置应用以及各种社交媒体网络的形式进入主流。然而,这些面部识别应用程序错误识别有色人种的事件越来越多。路透社文章:美国政府研究发现面部识别工具存在种族偏见。与对非白人的预测相比,该工具可以更准确地识别白人的性别。

它是如何发生的?

训练数据中的偏差 以苹果信用卡为例,最有可能是算法,根据历史数据训练,预测其新客户的信用额度。历史上,在算法接管之前,人类以承销商的形式做出信贷限额决定。也许,这是一种历史的非有意的人类偏见。由于多种原因,如男性和女性的工作稳定性更高,更容易因生育和照顾孩子而中断工作,承保人可能会给男性更高的信贷限额,给女性更低的信贷限额。

在招聘工具的例子中,模型是根据主要来自男性的历史简历进行训练的,而科技是男性主导的行业。因此,该工具惩罚像“女子象棋俱乐部”等词。从而导致女性的排名较低。

当算法根据历史数据进行训练时,它们会重复和混合社会/行业中存在的刻板印象/错误,从而降低特定人群的优先级。

训练数据的有限可变性 在面部识别算法存在偏见的情况下,种族偏见被注入算法的一个关键原因是训练数据在很大程度上偏向白人群体。如果训练数据适当地代表了人口的所有部分,可能就不会出现偏差。

因此,如果我们要训练一个只有女性人口的乳腺癌算法,那么如果一些男性被扔进预测数据,它将会抛出古怪的结果。不要误会我的意思,但乳腺癌也可能发生在男性身上!

直接偏差特征 作为数据科学家,当我们在开发算法时,我们的倾向是获得尽可能高的预测精度。我们踏上了特征提取之旅,将一切可能的东西(性别、收入、地址)放入模型中以提高准确性。我们很少考虑这个问题——基于性别做出这种预测是否道德?如果在历史上,人类有意识或无意识地考虑性别来做出信贷决策,我的算法也会这样做吗?将性别作为一个特征并不总是一件坏事。在一些场合,例如检测乳腺癌的概率,包括性别特征将是非常合适的决定。

间接偏见特征 虽然性别和收入等变量会直接引入偏见,但其他一些变量,如俱乐部会员资格、姐妹会/兄弟会隶属关系等也是会引入偏见的间接变量。加入兄弟会意味着客户是男性,加入姐妹会意味着客户是女性,交易数据中向印度俱乐部支付的会员费可能间接将客户描述为亚洲人。所有这些变量,如果不去偏差,涵盖一个或另一个偏差。

未来意味着什么?

对于数据科学家和开发人员来说
在我们追逐准确性最大化目标的时候,我们应该看看这个过程的其他一些结果。例如,大多数基于树的算法(决策树、随机森林、xgboost 等)会产生特征重要性度量,如果对其进行适当的分析,可以预先阻止算法中的任何偏差。

对于学术界来说 传统上,在社会、工作场所和其他地方有偏见的监管法规都坐在法律部门里。可能学术界需要创建专门的法律程序,培训律师理解算法中的偏见,并对机器学习产品进行“法律审计”。有了适当的算法知识,法律应该成为人工智能团队的一部分。

对于一个更广泛的人工智能网络 类似于从逻辑回归到 CNN 的一系列算法,为了自动化无数后端决策和预测,我们应该创建一系列算法——每一个都检测不同类型的偏差。比如模型中种族偏见的一个 XGBoost,收入偏见的深度学习等等。

数据科学的算法思维

原文:https://towardsdatascience.com/algorithmic-thinking-for-data-science-ab8c91416d83?source=collection_archive---------8-----------------------

数学和编程联系的衍生物

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

Unsplash 上拍摄的 ThisisEngineering RAEng

数据科学学生经常问的一个突出问题是,“为什么是算法?”老实说,我不怪他们。你会看到库和语言每天都在进步,使用 scikit-learn 的 Python 可以在一行代码中实现几乎任何数据结构。那么,为什么会有人想知道这些内置算法背后的科学和数学呢?

这与人类“学习”的方式有关。

回到你开始爬行和行走的时候,可能是 8 个月大的时候。几个月后,你开始听和说单词。几年后,你可以用父母教过的语言和他们交谈,你也可以用同样的语言和其他人交谈。这是在你上学之前。当学校开学的时候,教你的第一件事就是字母。当你已经可以用同一种语言与人交谈时,为什么还需要学习字母呢?因为学习不会停止。有了字母表和语言,你可以更有效地学习说和写。

几十年后,我们今天使用的算法可能不再适用。数据每秒都在呈指数级增长。五年前,1000 这个数字在货币和兆字节上都被认为很大。今天,这个数字很小。算法的根帮助我们理解它是如何构建的,这反过来又教会我们能够为现有算法从未见过的场景构建或修改这些算法的科学。这就是为什么,对于数据科学家、程序员和计算机科学行业的任何人来说,了解算法是如何从内部构建的非常重要。

什么是算法思维

概括算法的定义和实现就是算法思维。这意味着,如果我们有一个解决问题的标准,比如说一个排序问题,在问题陈述改变的情况下,我们不必完全修改方法。总会有一个攻击新习题集的起点。这就是算法思维的作用:它给出了一个起点。

为什么我们需要算法思维?–主要是为我们尚未遇到的问题建立新的解决方案。

设计任何算法时的两个关键要求是:

  1. **效率:**解决大问题的能力,就像解决小输入问题一样容易。
  2. **可伸缩性:**由于我们拥有的数据量每天都在增加,因此输入大小在未来总是会增加。我们今天设计的算法应该能够将自己扩展到输入的新高度。

理解算法思维的案例研究

让我们看看如何对一个问题实现算法思维,然后尝试改进我们原始的初始解决方案。我们从一个 寻峰器问题开始。 寻峰器(一维)是给我们一组输入整数,要求我们在那些数中找出峰值(最大的整数值)的问题。

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

假设字母(a 到 I)代表整数,这个数组的索引从 1 开始。我们需要找到作者的峰值(最大整数)|图像

策略 1:简单的算法

在我们的第一个策略中,我们简单地遍历给我们的整数数组,找到最大的元素。在上面显示的场景中,找到峰值需要多长时间?嗯,那要看情况。如果输入中的数字按降序排列,那么我们找到的第一个数字就是峰值。但是,无论哪种方式,要检查整个数组,我们都需要遍历它。因此,在该算法中将有总共‘n’个事务或迭代,‘n’是数组的大小。

策略 2:分而治之

在这个新策略中,我们尝试了一些不同的东西。我们尝试将输入数组分成两半。这种方法总共有三种可能的情况。要么中间的元素比左边的元素小,要么比右边的元素小,要么比两者都大。让我们看看下面的伪代码,了解分而治之找峰。

if a[n/2] < a[n/2 -1]
   search the left half { 1 -> a[n/2-1] } for peak
else if a[n/2] < a[n/2 + 1]
   search the right half { a[n/2+1] -> n } for peak
else
   middle number is the peak

我们观察到这个算法的迭代次数与我们最初的简单算法不同,这是为什么呢?这是真的,因为即使在最坏的情况下,该算法也不必遍历数组的每个元素。

不断增长的数据量的影响

为什么计算时间和空间的复杂性比以往任何时候都重要?这与我们之前讨论过的事情有关,即今天要处理的数据量。为了更好地解释这一点,让我们通过几个例子来展示大量数据在算法构建中的重要性。在测试场景中,当处理的数据量是我们处理的数据量的 100 多万倍时,我们在教室中随意创建的解决问题的算法与行业要求的算法非常不同。并且当输入大小明显较大时,时间复杂性总是可见的。

大数据问题的时间复杂度分析

当然,今天的计算机比以往任何时候都要快,内存也比以往任何时候都要大。但是,这些东西对我们来说都不是无限的。因此,计算时间是一种有限的资源,内存空间也是如此。因此,我们需要最佳地利用这些资源。

在这一节中,我们将回答为什么拥有在运行时节省空间和时间的高效算法如此重要。让我们以排序数字为例。排序中两个众所周知的算法是插入排序和合并排序。两者都工作得很好,都有专门的应用程序。我们想了解它们在非常大的输入下的性能。我们知道(在本文中我没有提供这些的证明)插入排序以 n 阶的效率运行。合并排序以 nlogn 的时间效率运行。这两种算法都有一些恒定定时的整数,但是在任何函数增长到非常大的数字时,这些 常数在函数各自的增长中不起任何重要作用(我们将在下面看到这一点的证明)。 非常清楚,如果我们将 log(n)与 n 进行比较,log(n)上的乘数永远较小。

取 n=1000,log(1000)大约是 10,即使 n 的值等于一百万,log(n)也是 20。另一方面,代表 1000 的 n 会跨越六位数,代表 100 万的 n 会更大。

让我们通过比较两台计算机 A 和 b 来考虑下面的工作示例。

计算机 A 是一台快速机器,每秒执行 100 亿条指令(这是假设的,目前很难在单个处理器上构建具有这种指令速率的机器)。计算机 B 是一台很慢的机器,每秒大约运行 1000 万条指令。从这些原始计算数据中,很明显计算机 A 比计算机 b 快 1000 倍。为了让事情更戏剧化,并将这种比较提升到另一个层次,让我们想象一个世界级的程序员用机器语言编写插入排序代码,运行时间复杂度为 2(n)。现在,一个编程新手,实现他的第一个合并排序代码,以 50n 的效率编写它。log(n)
我们在计算机 A 上运行
插入排序,在计算机 B 上运行
合并排序,输入1000 万个数字

如果你算一下(单位时间内算法求解的指令/计算机处理的指令)你会看到**计算机 A 需要 20000 秒,大约是 5.5 小时。**而速度较慢的计算机运行代码效率低下,**计算机 B 需要 1163 秒,不到 20 分钟。**这是高效且可扩展的算法设计能够带来的计算影响。使用库中预先设计的算法不会给针对单个机器的能力优化代码的自由。

为什么常数不重要

在故事的前面,我提到算法,对于一些任务,需要花费固定的时间(例如,将一个变量写入内存或者给一个变量赋值,等等。)我还提到,如果算法正在计算非常大的输入,这些常数可以忽略。这是为什么呢?

看看下面的正弦和二次函数:

g(x) = 1.1x^2 + (10 + sin(x + 1.15) * x^1.5) + 6006f(x) = x^2

让我们看看,这些函数是如何随着 x 值的变化而增长的。

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

看到趋势的变化。随着输入范围的扩大,噪声几乎消失。|作者图片

我们看到,在某一点之后,曲线的形状改变了,变得类似于函数 f(x ),它没有任何常数。如果我们确实看到一些噪声,那只是因为 x ^1.5 项。因此,忽略时间和空间效率计算中的常数是一种做法,因为对于大量的数据输入,它们变得可以忽略不计。

阅读有关数据科学算法的更多信息

结论

这场争论可能永远不会结束!随着学习编码的方式越来越多,编程场景变得相对容易。甚至机器学习算法也在慢慢变成 AutoML 应用程序上的拖放,比如微软的 Azure ML Studio。但是,尽管如此,设计高效算法的需求永远不会消失。机器可能变得强大,但与此同时,每秒处理的数据量也在增加。因此,必须设计有效的算法来处理这些数据。这个故事的目的不是教你算法设计的艺术,而仅仅是指出算法对数据科学家也很重要。构建、设计和测试高效、可扩展算法的目的没有也永远不会消失。

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

照片由西格蒙德Unsplash 上拍摄

关于我

我是纽约哥伦比亚大学的一名软件工程师兼数据科学研究员,目前正在研究如何减少气候变化对世界贫困人口的影响。这些人受我们砍伐树木和在地球表面推混凝土的行为影响最大。如果你的研究或工作抱负也与我一致,请务必通过 TwitterLinkedIn 与我联系,我们可以一起努力建设 负责任的人工智能。

参考

  1. https://www . cs . sjtu . edu . cn/~李江/teaching/cs 222/files/materials/Algorithm % 20 design . pdf
  2. https://www.cs.princeton.edu/~wayne/kleinberg-tardos/
  3. https://github . com/davie 890/cs 102-Algorithm-Analysis/blob/master/Algorithm % 20 design % 20 by % 20 Jon % 20 kleinberg % 2C % 20 EVA % 20 tardos . pdf
  4. https://www . cs . ut exas . edu/users/DJI menez/utsa/cs 1723/lecture 2 . html
  5. https://www . hackere earth . com/practice/basic-programming/complexity-analysis/time-and-space-complexity/tutorial/
  6. https://www . geeks forgeeks . org/time-complexity-and-space-complexity/
  7. https://towards data science . com/a-data-scientists-guide-to-data-structures-algorithms-1176395015 A0
  8. https://medium . com/swlh/why-data-scientists-should-learn-algorithms-and-data-structures-4d 93237 a 1026
  9. https://tdwi . org/articles/2018/07/02/adv-all-5-algorithms-for-big-data . aspx

经济学驱动的深度学习算法交易

原文:https://towardsdatascience.com/algorithmic-trading-with-economics-driven-deep-learning-50c219ee9334?source=collection_archive---------4-----------------------

将宏观经济理论融入深度学习模型

当开始学习金融 ML 时,很容易将一堆技术信号放入现成的 Keras RNNs 或 CNN 中。不用说,这些项目中的大部分都失败了,原因很简单,这些模型是为完全不同的应用开发的,不能反映金融数据的基本经济学。

今天,我们将看看在本文中开发的多图张量网络模型,并探索它如何将经济理论整合到更好的算法交易中。具体来说,我们将讨论如何将外汇(FX)套利因素(FX 回报的最重要驱动因素)纳入算法交易的深度强化学习代理的架构中。

(你可以在这里找到完整的代码和更多的细节

1.技术背景

为了将经济学原理纳入我们的深度学习模型,我们将不得不求助于在图形神经网络、张量网络和强化学习领域开发的工具。我们将在这里以非常概念性的方式讨论这些话题,因此请参考论文了解更多细节。此外,如果您已经熟悉这些主题,请随意跳过这一部分。

1.1.图形神经网络

图形神经网络(GNNs)是一种深度学习模型,用于处理在描述为图形的不规则域上定义的数据。与卷积神经网络(CNN)不同,它们不对底层数据几何做出假设,并且可以将卷积的概念推广到任何数据域。

下图直观地展示了如何将图像上的经典 2D 卷积(左)视为规则网格上互连像素图形上卷积的特殊实例(右)。

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

作者图片

1.2.张量分解

张量将向量和矩阵推广到多维数组。例如,矩阵是 2 阶张量,向量是 1 阶张量,标量是 0 阶张量。它们自然地描述许多类型的数据,例如图像(具有 3 种模态的 3 阶张量:x 轴、y 轴和 RGB 颜色)以及金融数据。

与矩阵类似,张量可以通过张量分解(TD)以低秩形式分解。TD 允许我们以对数方式大幅压缩大规模数据,这使我们能够有效地绕过维数灾难。

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

作者图片

1.3.深度 Q 强化学习

深度 Q 强化学习训练神经网络代理与给定环境交互,以最大化累积回报。这个学习框架特别适合算法交易,因为回报直接转化为代理买卖行为产生的利润。

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

作者图片

2。为什么金融深度学习经常失败

金融数据经常违反深度学习模型的假设

在我们可以开发自己的金融深度学习模型之前,我们需要了解为什么传统的 CNN 和 rnn 往往对金融数据不起作用,原因很简单:它们不是为这个领域开发的

每个深度学习模型都有自己的一套关于底层数据的假设,这可能不适用于金融市场,因为它有自己的一套独特的特征,正如本文所讨论的那样。

例如,CNN 是为计算机视觉任务开发的。他们假设基础数据是平移不变的,这对于图像来说是正确的,但是对于金融数据来说就不那么正确了。另一方面,RNNs 被开发用于序列建模。他们假设过去的状态可以通过可预测的趋势和季节性影响未来,这在一定程度上适用于金融数据,但往往不是一个充分的因素。

也就是说,通过非常仔细的问题公式化和数据预处理,我们可以绕过许多这样的问题,非常成功地将 CNN 和 RNNs 用于金融应用。因此,有必要仔细检查我们模型的基本假设,并确保它们反映了金融数据的基本经济学。

3.外汇金融背景

套利因素是外汇回报的主要驱动力,它与利率相关

现在让我们分析外汇数据的特征和驱动因素,以便我们能够设计我们的模型来反映基本的经济原则。

3.1.外汇数据的特征

外汇市场允许参与者以给定的即期汇率交易多种货币,即期汇率衡量一种货币在给定时刻相对于另一种货币的价值。

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

作者图片

外汇数据本质上是多模态的(多维的),因为它们包含随着时间的推移和跨几个相关资产索引的多个定价信息,这导致其计算遭受维数灾难的大维张量。这在过拟合方面具有严重的含义,这对于深度学习方法来说尤其成问题。

此外,由于市场中的套利力量,已知 FX 数据具有低信噪比,这使得模型训练特别容易过度拟合,尤其是对于深度学习模型。

最后,各种市场因素(如套利因素、价值因素、动量因素等。),可以根据时间范围在不同程度上影响定价;这构成了不是很多机器学习算法可以处理的多分辨率问题。

3.2.外汇数据的驱动因素-外汇进位

有许多因素可以影响货币对的即期汇率,但最重要的驱动因素可以说是套利因素。

长话短说,外汇套利描述了货币对升值/贬值的趋势,取决于相应国家之间的利率差异。

例如,假设欧元兑美元的即期汇率为 1(即你可以用 1 欧元兑换 1 美元),但利率在美国是 2%,在欧盟是 3%。你可以做的是以 2%的利率借入美元(短期),转换成欧元(长期),然后以 3%的利率贷出。如果即期汇率在年底前保持不变,你可以将欧元兑换回美元,由于利率差异,你实际上已经获得了 1%的无风险收益。

然而,在现实中,期望即期汇率完全保持不变是天真的。事实上,我们实际上预计欧元兑美元即期汇率会发生变化,以抵消利差。尽管过于简化,但这是利率平价背后的基本思想。

请注意,由于外汇数据是成对的,我们可以为每个货币对定义一个结转值。这允许我们定义下图所示的进位图,它以一种经济上有意义的方式对不同货币之间的成对关系进行编码。

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

作者图片

4.外汇交易的多图张量网络

在不涉及太多数学细节的情况下,本文在开发的多图张量网络(MGTN)模型利用了张量分解的能力来建模多维数据,以及图在不规则域上建模数据的能力。这使得 MGTN 能够应对外汇数据的几个挑战,例如:

  • FX 数据的多模态特性自然会导致张量表示,这可以通过 MGTN 的张量结构轻松处理。
  • 该模型可以利用张量分解的强大低秩压缩特性,这种特性固有地不受维数灾难的影响,并提供一个正则化框架来解决 FX 数据的低信噪比特性。
  • 长期市场因素如套利可以被封装在图形过滤器中,自然地吸引外汇数据的成对公式;这允许通过经济上有意义的低频图形拓扑来处理高频定价数据。

通过使用 MGTN 作为 deep-Q 强化学习代理的基础,我们可以训练它,并将其与其他深度学习代理进行比较,以完成 FX 算法交易的任务。下图显示了相应的样本外交易结果,其中 MGTN 模型的表现明显优于其他深度学习代理。

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

作者图片

需要强调的是,上述模拟做出了许多假设(例如,无延迟、无交易成本、无市场影响等)。),所以对结果要半信半疑。这个模拟的目的是展示如何将经济原则融入深度学习模型中,从而产生更强大的交易算法。

我希望你喜欢这篇文章!如果你想看更多这样的内容,请关注我。

此外,检查出我的网站的完整代码和其他资源。

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

如何通过算法生成图像数据集

原文:https://towardsdatascience.com/algorithmically-generated-image-dataset-71aee957563a?source=collection_archive---------7-----------------------

为机器学习创建您自己的图像数据集

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

生成图像的示例。(沙漠背景)作者林奈·马利特 |(乡村背景)作者道恩·哈德森 |(森林背景)作者乔治·霍丹 |(冰川背景)作者艾德·罗杰斯 |(人物和物体)作者craftpix.net

这篇文章的灵感来自最近发布的 NFT 艺术收藏,如 Cryptopunks、Sollamas、ON1 Force 或 Bored Ape Yacht Club。在所有这些项目中,有一些项目的图像是由艺术家创作的,而另一些项目的图像是通过算法生成的。正如我们在数据科学博客中一样,我们创建图片集的有趣方式是第二种。

在这篇文章中,我们将使用 Python 创建一个随机图像的集合,这些图像之间有许多共同的特征。我们将从一些基础图像开始,我们将在其上添加元素,以配置将形成集合的最终图像。在这种情况下,我们将使用一个背景,我们将在其上放置不同类型的字符,我们将在其上添加一个对象。

最后,我们将有一个图像数据集,其中每个图像都有特定的属性。例如,一个带着油炸圈饼的沙漠海盗,或者一个带着钥匙的森林怪物。

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

一个在森林里带着锚的海盗。(森林背景)作者乔治·霍丹 |(海盗兼主播)作者craftpix.net

由于目标不是创建艺术,我将把免费分发的像素艺术作为基础。我将使用这些图像作为基础来生成数百个衍生图像。作为一个有趣的练习,你可以选择一些不同的图像,创建自己完全不同的数据集。

我将使用三种类型的属性:背景、人物和物体。对于它们中的每一个,我将设置一个百分比形式的概率分布来定义每个特征的常见程度。您可以随意使用这些参数来创建不同种类的数据集。例如,一个数据集,其中 99%的图像使用一种特征,1%的图像使用另一种特征。通过做这类实验,并在此基础上建立预测模型,你可以学到很多东西。

属性的概率分布

为了生成文章的数据集,我将使用以下属性分布:

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

作者图片

让我们开始工作吧

第一步是找到将被用作基础的图像。利用各种各样的网站,我选择了一些图片作为基础。选择这些图像的主要标准是它们可以根据它们的许可进行修改和免费分发。您可以下载这个存储库中使用的所有图像。

一旦图像被选中,我们就可以开始编程算法图像生成器。为了生成图像,我将使用 Python 和 Pillow 库。这是生成图像的基本脚本:

from os import path, mkdirfrom PIL import Imageoutput_folder = "generated"if not path.exists(output_folder):mkdir(output_folder)background_file = path.join("backgrounds", "forest.png")background_image = Image.open(background_file)output_file = path.join(output_folder, "generated1.png")background_image.save(output_file)

首先生成“generated”文件夹来保存生成的文件。如果文件夹已经存在,我们什么也不做。我们加载一个背景,并将其保存在“生成”文件夹中。我们已经完成了第一次图像操作!现在只需要在上面添加更多的元素,直到生成最终的图像。

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

例子背景(乡村背景)由道恩·哈德森

我们会给背景固定的尺寸,这样所有生成的图像都有相同的尺寸。为了简化工作,我把最大的背景图片缩放到和最小的一样大。我没有缩放字符,因为这个项目的目标是功能,而不是漂亮。我缩放了一些对象,因为它们明显比其他的要大,并且它们在图像之外。

所使用的背景图像在缩放后具有 1920x1078 px 的尺寸。

对字符和对象所做的唯一变换是消除边距,因为每幅图像的每一边都有不同的边距。这使得即使将它们放在相同的位置,其中一些也会比其他的更高或更靠右。

当在背景上添加人物和物体时,工作变得有点复杂。现在我们必须定义我们想要放置字符的位置以及它们应该有多大。为了定义位置,我们有几个选项:

-为所有图像定义固定位置
-为每种类型的人物/每种类型的风景定义固定位置
-随机化位置。如果我们选择后者,我们应该定义一些我们不希望图像出现的限制,我们不希望图像被放在边界上,只有一小部分被看到。

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

角色走了边。(森林背景)由乔治·霍丹 |(怪物和箱子)由craftpix.net

对于物体来说也是一样,我们必须根据角色在哪里或者在背景上的预定位置来定义放置物体的位置。对于这个数据集,我决定将对象放在字符的右边。

Pillow 使用的坐标系的原点在图像的左上角。如图所示:

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

作者图片

为了简化工作,我决定将所有的角色放在背景中相同的固定位置。我将位置定义为图像底部水平居中的一个点。小矩形的尺寸, hw 是字符的高度和宽度。用黑色标记的点是我们必须计算的,以告诉 Pillow 在图像中放置字符的位置。

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

作者图片

这个点可以用下面的公式计算,其中 1920 是背景的宽度,我们除以 2 来找到中点。1000 是 1078 的近似值,以便在角色的脚和图像的底部之间留一些空白。

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

作者图片

为了将对象放置在字符的右边,我使用了一个类似的公式,在这个例子中,我添加了一个边距 m ,这样对象就不会碰到字符。对我来说效果很好的一个值是 30 px。注意, hw 在这种情况下指的是角色的高度和宽度,而不是对象的高度和宽度,因为我们定位在角色的右侧。

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

作者图片

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

作者图片

所有这些计算转化成代码变成这样:

def generate_image(background, character, object, file_name): background_file = path.join("backgrounds", f"{background}.png") background_image = Image.open(background_file) #Create character character_file = path.join("characters", f"{character}.png") character_image = Image.open(character_file) coordinates = (int(1920/2-character_image.width/2), int(1000-character_image.height)) #x, y background_image.paste(character_image, coordinates, mask=character_image) #Create object if object != "none": object_file = path.join("objects", f"{object}.png") object_image = Image.open(object_file) coordinates = (int(1920/2+character_image.width/2+30), int(1000-object_image.height)) #x, y background_image.paste(object_image, coordinates, mask=object_image) output_file = path.join(output_folder, f"{file_name}.png") background_image.save(output_file)

好吧,但是…给我数据!

在我们生成图像的同时,我们还会将它们和它们的特征一起注册到数据库中。我们将使用 pandas 进行注册,并将数据保存在 CSV 文件中。

我们创建一个没有数据的 DataFrame,只命名列。每当我们生成一个图像,一个新的行将被添加到数据帧。最后,一旦生成了所有图像,CSV 将被保存。 num 变量是用于命名图像的顺序计数器。例如,生成的图像将被命名为生成 1生成 2生成 2894 、…。

保存图像文件的名称很重要,这样才能知道这些参数对应于哪个文件。

df = pd.DataFrame(columns = ["background", "character", "object", "generated image"])for … …. …. #Code to generate image data = [background, character, object, f"generated{num}"] s = pd.Series(data, index=df.columns) df = df.append(s, ignore_index=True)df.to_csv('data.csv', index=False)

我会得到多少图像?

您可以用一个简单的公式计算出可能的图像总数。只需将每个类别中可能的属性数量相乘即可。在我们的例子中,4 个背景* 5 个字符* 11 个对象= 220 张图像。

为了生成所有可能的图像,我们将使用这段代码。首先,我们为每个参数定义所有可能的值,然后对它们进行迭代。

backgrounds = ["countryside", "desert", "forest", "glacial"]characters = ["mage", "warrior", "pirate", "monster", "toadking"]objects = ["none", "barrel", "anchor", "axe", "bomb", "key", "chest", "bananas", "cupcake", "donut", "heart",]def generate_all_imgs(): num = 0 df = pd.DataFrame(columns = ["background", "character", "object", "generated image"]) for background in backgrounds: for character in characters: for object in objects: generate_image(background, character, object, f"generated{num}") data = [background, character, object, f"generated{num}"] s = pd.Series(data, index=df.columns) df = df.append(s, ignore_index=True) num += 1 df.to_csv('data.csv', index=False)

随机选择

在生成图像时,我们已经看到了如何生成所有可能的图像。在这种情况下,我们可以全部生成它们,因为它们很少,但是如果我们增加参数的数量或每个参数的可能性的数量,则可能要生成的图像的数量是巨大的。

使用这段代码,我们将生成给定数量( total_imgs )的图像。为了决定在每个图像中使用哪些特征,我们将求助于机会。请注意,可能会多次生成相同的图像,这在最有可能的参数的情况下是常见的(最有可能的背景,最有可能的角色和最有可能的对象,在我们的情况下,它可能是一个没有对象的森林中的法师)。

我们将使用上表中为每个属性定义的概率,并使用 Numpy 的 random.choice 函数来选择一个属性,同时考虑哪一个最有可能。

def generate_random_imgs(total_imgs): df = pd.DataFrame(columns = ["background", "character", "object", "generated image"]) for num in range(total_imgs): background = np.random.choice(np.arange(0,len(backgrounds)), p=[0.3, 0.3, 0.3, 0.1]) background = backgrounds[background] character = np.random.choice(np.arange(0,len(characters)), p=[0.4, 0.3, 0.2, 0.095, 0.005]) character = characters[character] object = np.random.choice(np.arange(0,len(objects)), p=[0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05, 0.04, 0.03, 0.025, 0.005]) object = objects[object] generate_image(background, character, object, f"generated{num}") data = [background, character, object, f"generated{num}"] s = pd.Series(data, index=df.columns) df = df.append(s, ignore_index=True) df.to_csv('data.csv', index=False)

注意不要使用太高的数字,因为生成过程可能需要几个小时,创建的图像可能会占用很多 GB。

结论

我们已经创建了一个小的基本程序来从基本图像生成合成图像的数据集。有了这个数据集,我们可以开始训练一个神经网络,根据背景的类型或根据人物的类型对图像进行分类。

有了这个脚本,我们就有了做更复杂事情的基础,我们可以给角色添加旋转,让他们有不同的大小,改变颜色等等…

您可以将此数据集生成器用作数据扩充技术的测试平台,例如,您可以创建新的图像,其中角色位于另一个位置,而不是始终相同。你可以创建角色或物体旋转的图像,等等…

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

怪物说感谢阅读!(森林背景)作者乔治·霍丹 |(怪物)作者【craftpix.net】T2

你可以在这个 Github 库中找到所有的代码和原始图片。

用于创建数据集的图像不是我的,它们的原始来源是:

算法没有偏见:我们有

原文:https://towardsdatascience.com/algorithms-are-not-sexist-we-are-795525769e8e?source=collection_archive---------39-----------------------

著名的人工智能创造了一个穿着比基尼的 AOC 的形象,它的行为是不恰当的,但却是理性的

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

如果你相信人工智能根据男性和女性的头像照片创造了男性和女性的形象,那么男性通常会穿西装,而女性则更喜欢低胸上衣和比基尼。

据媒体报道,这证明了人工智能的未来是性别歧视的。理由是,因为互联网上充斥着衣着暴露的女性照片,人工智能会认为这是正常的。

公平点?不一定——这项研究的全部目的是证明从人类活动中收集的数据中继承偏见的危险。

该实验使用了 ImageNet 库,该库通常用于人工智能的训练,由数百万张不同的图像组成,标记有描述。使用这些图像,他们训练一个人工智能从某人的头部图像创建一个全身图像。在 43%的情况下,输入一个男人的头像会产生一个穿西装的男人。但是有了女人的头,53%的全身照片是穿着比基尼或低胸上衣的女人——这包括一张来自民主党国会女议员亚历山大·奥卡西奥-科尔特斯的头像照片。

显然,结果反映了图像数据库的内容。如果你要重复这个实验,但用的是奥斯卡典礼红地毯上的人的图像,人工智能肯定会得出结论,所有男人都打黑色领带,大多数女人喜欢暴露的裙子。对人工智能的任何使用都会反映这些偏见。

这告诉我们什么?这并不是说人工智能天生就有偏见,而是我们不能简单地依赖反映负责这些数据的人的偏见观点的数据。

ImageNet 和互联网都不能反映现实生活。人们在互联网上发布东西,无论是在 Flickr 上的图片,还是在脸书、Twitter、Instagram 或其他网站上的帖子,以激起人们的反应。虽然有一些人(好吧,很多人)试图产生负面影响,但在我看来,大多数人都是发布他们喜欢的东西。

它会认为保时捷比大众甲壳虫更像汽车

如果你训练一个人工智能从 Flickr 上的图片中识别汽车,你可能会发现它在识别福特野马方面比福特嘉年华更有信心;它会认为保时捷比大众甲壳虫更像汽车。

这是否意味着大多数汽车都是高端运动车型?不,当然不是。这种车的帖子比较多,是因为人们对它的印象比较深。

我再说一遍:互联网不能反映现实。因此,任何不加思考地基于其内容的人工智能也不会。或者,就此而言,任何由有缺陷的人(当然是我们所有人)编辑的信息。

在不同的背景下,路透社在 2018 年报道称,亚马逊已经放弃了一个人工智能招聘系统,因为它无法摆脱性别偏见。这种偏见来自以前招募的历史数据。情况正在好转,但在过去,技术和编程工作几乎完全由男性完成。因此,这些领域成功员工的特征之一就是他们是男性。

因此,当人工智能关注新的潜在雇员时,它偏爱男性

这并不是说女性不能同样出色地完成这些工作,而是她们没有在当时男性主导的行业中申请这些工作。因此,当人工智能关注新的潜在雇员时,它更青睐男性。

亚马逊解决这个问题的方法是尝试在求职申请中删除所有涉及性别的内容。但这被证明是一项不可能的任务,因为性别信息的线索可能隐藏在候选人个人资料的许多部分:他们上过的学校或大学,他们参加的运动,他们喜欢的爱好。

值得称赞的是,亚马逊认识到了这个问题,并试图解决它。如果有更多的最新信息,这种偏见或许可以避免。

因为不是说 AI 就不能不偏。检测癌症的机器学习算法是在已知是癌症的图像上训练的,因此偏差的可能性很小。不仅如此,这些图像还要由专家进行审查,所以是人类在人工智能的帮助下,对干预是否合适做出最终判断。

大概也是人类的判断导致了亚马逊招聘系统的失败。因此,使用真人作为最终决策者是解决人工智能不足的一种方法。

机器学习产生黑盒系统

另一个是交代。机器学习产生了黑盒系统,其决策过程对人类用户来说是不透明的。但是更新、更强大的系统可以为他们的决定提供解释,使用户能够理解他们的推理,或者允许他们的设计者修复任何错误。

因此,当数据是由人编制的,或者反映了不能完全公平和公正地依赖的人(换句话说,任何人)做出的历史决策时,问题就可能出现。

也许解决亚马逊问题的更好方法是编码更积极的女性数据——也许对新招聘的女性比年长的男性评价更高——而不是试图完全消除性别信息。至于男人和女人的形象建设,也许在训练前消除某些类型的形象是一个解决办法。

但也许最好的解决方案是将人工智能作为人类决策的辅助手段。也许让人工智能提高人类的表现并将其作为一种辅助手段而不是替代品更好——特别是当它能够更好地解释自己的时候。

数据科学家的算法—插入排序

原文:https://towardsdatascience.com/algorithms-for-data-scientists-insertion-sort-6caa69f906b3?source=collection_archive---------33-----------------------

你会学到的最简单的算法之一。

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

Unsplash 上拍摄的 ThisisEngineering RAEng

算法在计算和机器学习领域很常见。这篇文章很可能是 Medium 背后的内容推荐算法推荐给你的——一个 ll 欢呼 Medium 算法!

算法是技术的一种形式

更严重的是,算法驱动着社交媒体应用、谷歌搜索结果、银行系统以及更多。算法是技术的一种形式。最重要的是,数据科学家和机器学习实践者对分析、设计和实现标准和新颖的算法有一种直觉。

当应用于大规模计算任务时,有效的算法已经为公司节省了数百万美元,并且减少了内存和能量消耗。

这篇文章介绍了你可能遇到的最简单的算法。插入排序

从这篇文章中可以期待什么:

  • 插入排序简介。
  • 对插入排序算法中涉及的操作的解释。
  • 插入排序算法在 python 中的实现
  • 提供了关于插入排序时间复杂度的信息。

插入排序说明

算法是一组指令,用于修改输入以产生期望的输出。

排序问题是数据科学家和其他编程学科遇到的典型编程任务。排序问题的主要任务是对一系列元素进行升序或降序排序。

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

照片由 Andrik LangfieldUnsplash 上拍摄

插入排序是排序问题的一种解决方案。通过考虑将一副牌按升序排列的方法,很容易描述插入是如何工作的。

在右边,你有一副面朝下的牌,在左边是一个初始的空白空间。第一张牌将在最初空着的左手空间,然后从右手堆中取出每张牌,与左手堆中的牌进行比较,以确定当前牌是否少于观察到的牌。

如果卡片不小于左侧被观察的卡片,则它留在当前位置。

本质上,本例中的左侧牌组始终是有序的。

下一节介绍正确插入排序的算法。一旦您对算法的工作原理有了直观的了解,后面的小节将展示插入排序算法是如何在 Python 中实现的。

算法描述

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

插入排序 GIF 。(该文件在知识共享协议下获得许可)

插入排序算法的工作方式类似于上面描述的一副牌的例子。该算法实际上将阵列分成左右两侧。分区左侧的元素是排序的,而右侧的元素不是。

在我们深入研究一些代码之前,下面是一个关于插入排序算法中涉及的操作的文本逐步信息,以升序对元素列表进行排序。

  1. 所有要排序的元素都放在一个列表或数组中。
  2. 从第一个元素到最后一个元素,遍历列表。
  3. 在每次迭代中,将引用的当前元素与其之前每个位置的元素(即左边的元素)进行比较。
  4. 如果引用的元素小于前面的任何元素,它将从初始位置移动一个位置。

Python 中的插入排序

下面的代码使用插入排序算法将一个无序列表排序为升序。

A = [3, 6, 2, 7, 2, 7, 1, 6, 3]for i in range(0, len(A)):
    key = A[i]
    j = i - 1
    while j >=0 and A[j] > key:
        A[j + 1] = A[j]
        j = j - 1
    A[j + 1] = key

print(A)
>> [1, 2, 2, 3, 3, 6, 6, 7, 7]
  1. 列表’ A’ 用无序数字序列初始化:[3,6,2,7,2,7,1,6,3]。
  2. 遍历列表*‘A’*,当前迭代(key)中引用的元素和前一个位置(j) 的索引都保存在变量中。
  3. 迭代的第一个实例(key)是 3,而(j)是-1。-1 不是列表的有效位置索引。为了确保运算中只考虑有效的索引,(j)必须大于或等于 0。
  4. 还需要比较当前引用的元素(key)和前一个元素(A[j])的值。
  5. 为了在当前迭代中遍历数组的左侧,使用了一个“ while ”循环。满足步骤 3 和 4 要求的完整 while 循环语句如下: while j > =0 和一个【j】>键
  6. 如果满足这些条件,则保存在前一个索引(A[j])处的元素被放置在其当前位置之前一个位置,即交换到右侧。 A[j + 1] = A[j]
  7. 变量(j)中保存的前一个元素的索引减少,表示虚拟向左移位。并且再次重复该过程,直到不再满足 while 循环条件。
  8. 如果当前值(key)大于 A[j]中引用的值,那么 key 从当前值(j)向上移动一个索引位置: A[j + 1] = key
  9. 对列表“A”中的每个元素重复整个操作,结果是一个按升序排序的列表。

复杂性和性能

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

插入排序 Gif (该文件在知识共享下获得许可)

使用大 O 符号,插入排序算法的时间复杂度为 O(n ) 。简单保留,最里面的语句执行两次(n*n)。

在列表已经按照期望的顺序排序的情况下,插入排序算法的时间复杂度为 O(n)。在这种情况下,只有一次迭代,并且没有执行内部循环中的操作。

插入排序通常适用于对小型列表或数组进行排序。然而,当面对包含更多元素的更大的列表时,有比插入排序算法更有效的算法可以使用。我将在以后的文章中探讨这些替代算法。

结论

插入排序是排序列表的最简单算法之一。这是一个简单的算法,可以用各种语言理解和实现。

对于一些机器学习从业者来说,回避算法的话题是典型的。算法的主题与复杂性相关联。

但就像计算和机器学习的所有学科领域一样,通过适当的资源、练习和时间,即使是最复杂的算法也很容易掌握。

感谢阅读。

</5-ways-to-provide-value-as-a-data-scientist-ce7bba57af02>

要联系我或找到更多类似本文的内容,请执行以下操作:

  1. 订阅我的 邮箱列表 获取每周简讯
  2. 跟我上
  3. 通过 LinkedIn 联系我

公平机器学习算法:导论

原文:https://towardsdatascience.com/algorithms-for-fair-machine-learning-an-introduction-2e428b7791f3?source=collection_archive---------21-----------------------

公平和偏见

三种类型的偏差缓解算法

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

埃琳娜·莫日维洛Unsplash 上拍摄的照片

负责任的 ML 模型开发的一个关键组成部分是确保我们的模型不会不公平地伤害我们人口中的任何亚群体。第一步是识别和量化模型中的任何潜在偏差,人们已经提出了许多不同的群体公平性定义。在亚瑟公司,我们感兴趣的不仅仅是识别偏见,而是努力让模型更加公平。在这篇文章中,我们简要描述了偏差缓解技术家族:改善不公平模型的方法。

虽然这是一个活跃的研究领域,但当前的缓解技术针对模型开发生命周期的特定部分:

  • 训练数据的预处理或调整。
  • 处理中,或算法特别是为了公平。
  • 后处理,或调整模型的输出。

正确的解决方案可能取决于用例、行业和模型部署;在这篇文章中,我们概述了几种公平 ML 的方法。

为什么我们会观察到不公平的量词?

通常,我们会观察到不公平的分类器,因为用于训练模型的数据在某种程度上是“有偏见的”。正式描述“有偏数据”与“有偏模型”的关系是一项稍微复杂一些的任务。

学习模型中偏差的一个常见原因是数据中子群之间的不平衡。根据定义,如果我们有一个在训练数据中代表少数群体的子群体,那么这意味着与多数群体相比,我们对他们的观察更少。当分类器被训练时,它在整个数据集上优化损失函数。如果主要类别确实占主导地位,那么在训练数据上实现高总体准确性的最佳方式可能是在多数群体上尽可能准确,同时在少数群体上招致错误

因此,如果多数群体和少数群体在属性和与目标变量的关系上有任何差异,模型很可能主要遵循主要数据的模式,并可能忽略少数群体的贡献。这可能意味着这个模型对于大多数群体来说是相当准确的,但是对于较小的群体来说就不那么准确了。

在其他情况下,偏差的产生是因为模型从数据集中编码的系统偏差中学习。。在“基础事实”结果与社会系统交叉的领域,如贷款履行、雇佣、刑事司法、住房等。数据可以对该系统内存在的歧视和偏见进行编码。例如,根据上世纪 60 年代的招聘数据训练的模型可能会表明,女性最适合做秘书,而不是高管。无论你选择哪种技术来改善这些选项中的偏差,都应该密切关注历史背景,通过它可以更好地理解数据收集实践和社会影响。

预处理偏差缓解

减轻偏差的预处理技术往往都与数据有关。如前一节所述,训练数据的特定特征可能直接导致学习模型的有问题的性能。由于这个原因,许多预处理技术集中于修改训练集以克服数据集版本的不平衡。

这可以通过多种方式实现,包括对数据行进行重新采样、对数据行进行重新加权、跨组翻转类标签以及省略敏感变量或代理。其他技术考虑学习实现期望的公平性约束的直接修改变换函数

在所有情况下,策略都是更改基础训练数据,然后使用任何所需的分类算法继续进行训练。通过以这些特定的方式修改训练数据,所学习的分类器的输出将更少偏差。

处理中偏差缓解

利用处理中技术,我们希望创建一个明确知道我们的公平目标的分类器。也就是说,在训练分类器时,仅仅优化训练数据的准确性是不够的。相反,我们修改损失函数来同时考虑我们的两个目标:我们的模型应该既准确又公平。

这种修改可以通过多种方式实现,比如使用对抗性 技术,确保底层表示是公平的,或者通过框定约束和规则化。在每种情况下,目标都是底层分类器直接考虑公平性。

因此,与对公平性一无所知的分类器相比,经过训练的分类器的结果将更少有偏差。

后处理偏差缓解

最后,有一系列技术旨在只调整模型的输出,而不改变底层分类器和数据。这里的好处在于它的简单性——在使用后处理方法时,我们允许模型开发团队使用他们希望的任何建模算法,他们不需要修改他们的算法或重新训练新的模型来使其更加公平。

相反,后处理方法的核心思想是调整不公平模型的输出,使最终输出变得公平。例如,该领域的早期工作集中在以组特定的方式修改结果和阈值

假设我们建立一个分类模型来帮助信用风险决策。经过大量的超参数调整,我们得到了一个准确且概括良好的模型,但我们注意到它倾向于支持年长的贷款申请人而不是年轻的申请人。

利用后处理技术,我们将保持分类器不变,但是调整结果,使得总体接受率更加公平。我们会挑选一个公平的定义(比如说,人口统计均等),然后调整不同组之间的待遇,以使最终结果符合预期。这意味着我们可能有特定于组的阈值,而不是用于分类器的单个阈值。

值得注意的是,在这种情况下,围绕偏见缓解仍有许多法律模糊之处。对于法院将如何处理算法歧视有如此多的未知,许多组织严重依赖他们的法律团队如何驾驭这种复杂性!

许多后处理技术都有这个共同的基本结构:它们不去管分类器和数据,只是以一种依赖于组的方式调整结果。虽然二元分类在过去一直是焦点,但最近的工作试图将这些想法扩展到回归模型以及。总体框架可以有效地实现 ML 系统中的公平性,尽管在某些用例中,区别对待不同的组可能是一个令人不舒服的提议,甚至是非法的。

公平和准确

当我们着手部署更加公平的 ML 模型时,我们必须承认这种公平不是免费的;事实上,在许多情况下,它可能会与模型准确性相冲突。

考虑一个极端:一个尽可能精确的模型(相对于现有的基本事实)可能是相当不公平的,并且歧视至少一个亚群。

考虑另一个极端:一个完全公平且对所有人群都公平的模型,这个模型肯定不如不考虑公平作为约束的模型准确。(尽管一些 最近的工作表明折衷不一定总是发生,但是“公平算法”在现实世界中部署时的行为并不总是与理论上证明的结果相匹配;因此,理解公平性和准确性之间的关系对我们选择使用的模型充满信心至关重要。)

在这两个极端之间存在着一个平衡准确性和公平性的可能模型的大家族。这组模型在准确性与公平性之间形成了一个帕累托边界(有效边界)。

下图来自 2019 年的一篇调查论文,描述了许多流行的公平 ML 算法的量化性能,说明了这种权衡。形象地说:我们想分享一个很好的图表,展示不同影响之间的权衡,衡量公平性,x 轴是不同影响,衡量公平性,而 y 轴是准确性。(整篇论文值得一读;它很好地介绍了公平 ML 模型性能的许多常见考虑因素。)作为实践者和利益相关者,我们必须面对关于这种权衡的问题:对于每一个用例,我们必须权衡通过不公平造成的潜在危害的成本和通过降低准确性造成的潜在危害的成本。

这些都是具有挑战性的问题,没有唯一正确的答案。相反,ML 从业者必须与利益相关者合作,如商业领袖、人文专家、合规和法律团队,并制定一个如何最好地对待你的人口的计划。更广泛地说,公平只是负责任地部署机器学习所需的一小部分:这篇文章应该是对话的开始,而不是结束。

背景#7 中的算法:决策树和阿尔法-贝塔剪枝

原文:https://towardsdatascience.com/algorithms-revisited-part-7-decision-trees-alpha-beta-pruning-9b711b6bf109?source=collection_archive---------23-----------------------

你的人工智能对手在机器学习之前是如何做决定的

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

Unsplash 上的 Pietro Jeng 拍摄

1997 年,IBM 的超级计算机“深蓝”在一场国际象棋比赛中击败了世界冠军加里·卡斯帕罗夫。人工智能历史上的一个标志性时刻,的确!在这一节中,我们将看到编写人工智能算法并不像在好莱坞电影中那样有趣。

决策树

想想任何双人棋盘游戏:国际象棋、西洋双陆棋,无论你喜欢什么…你和你的对手轮流,你们每个人都试图达到决定性的状态,你粉碎你的对手。在任何时候,你都有一套有限的移动,在每一步,你的目标是做出最好的移动。但这是人类玩游戏的方式,机器呢?

他们使用一种叫做决策树的东西。我们从一个根节点开始,它象征着游戏的当前状态。我们在那一点上的每一个可能的移动都将是那个节点的子节点。然后对于每个孩子,对手都有一套新的可能的行动。该树分支直到它覆盖游戏中的每一个可能的状态,并且当它到达一个叶节点时游戏结束。

最早的人工智能算法是基于在决策树上进行强力搜索。搜索算法试图到达使机器获胜的任何叶节点,并做出决定,以便它能够到达这些获胜节点之一。我们现在将看到这些算法中的一个在运行。

极大极小算法

现在把你自己从游戏中抽象出来,假设我们已经给游戏的每一个可能的结果分配了一个分数。分数被分配给树的叶节点。正分数表示机器赢了,负分数表示你赢了。所以,人工智能的目标是最大化分数,而你的目标是最小化分数。绿色箭头表示 AI(最大化者)的回合,红色箭头表示你的(最小化者)回合。

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

minimax 算法非常简单,它是深度优先搜索的修改版本。人工智能(绿色)将总是选择具有最大可能结果的移动,假设它的对手(红色)将总是选择最小可能结果。明智的做法是假设你的对手打得最好,这样你就可以做好最坏的打算。现在花一点时间,跟着树从底部到顶部,看看每个对手的举动。

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

你可以看到这个算法通过暴力搜索了所有可能的场景。如果我们假设 b 是分支因子 d 是决策树的深度,那么算法在 O(bᵈ) 哪个指数上起作用。

如果你正在实现一个井字游戏,这可能没那么糟糕。毕竟,第一回合有 9 种可能的走法,接下来是 8 种,7 种,以此类推,总共是 9 种!场景总数。然而,如果你正在做一个象棋游戏,可能性的数量将会以一个疯狂的数量增长!任何计算机要计算出所有的可能性都需要数百万年的时间。

需要我说一定有更好的方法吗?

阿尔法-贝塔剪枝

Alpha-beta 修剪是消除对解决方案没有帮助的分支的策略。我将用一个例子来解释这一点。**下面树中的红线标记了我们搜索的当前状态。**最大化器(AI)选择了 9 和 5,这是相应子树上的最大可达值。此时,极小值当前保持值 5,这是 9 和 5 中较小的一个。

还有一个分支需要搜索,深度优先搜索看到的第一个值是值 6。现在我们知道无论最大化者选择什么都至少是 6。但是我们也知道 minimizer 选择了 5,已经小于 6 了。在这一点上,我们不再需要检查剩余的孩子(1 和 7 ),因为我们肯定知道最小化将选择 5。

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

反过来也可能是正确的:如果最大化器已经选择了一个比最小化器选择的值更大的值,我们就不需要搜索其余的子树。在下面的树中,最大化器已经在根节点选择了 5。因为-2 小于 5,并且最小化器选择的任何东西最多是-2,所以我们不再需要搜索其余的子树。

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

所以继续吧,把这个策略应用到你的整个搜索中,从决策树中剔除 c**p。在最右边还有最后一个子树可以删除,我把它留给你来检查为什么我们可以跳过它。阿尔法-贝塔修剪算法的最终结果应该是这样的:

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

我们把树修剪了不少。Alpha-beta 修剪可以提供高达原始 minimax 算法的性能的平方根的性能优化。它也可能根本没有提供性能改进,这取决于你有多倒霉。

深度受限搜索

即使 alpha-beta 修剪提供了大量的性能改进,搜索整个可能的场景集仍然是多余的。我们可以采用智能策略来避免搜索整个树,并且仍然可以得到非常好的结果。

一种这样的策略是深度受限搜索,它听起来确实如此。不是搜索整个树,而是在预先定义的有限深度内搜索。例如,您可以在国际象棋中搜索下 5 步棋。但是为了做到这一点,你需要一种确定性的方法来对游戏的当前状态进行评分,因为当你到达搜索的终点时,你不再知道谁赢得了游戏。为此,我们将使用一个评估函数。

**注意:**深度受限搜索还有其他选择,比如迭代深化,但为了保持故事简短,我不喜欢包括它们。

你的搜索有多深入?明白了吗?那是个玩笑…

评估功能

所以,你决定将你的搜索限制在你和你的对手在游戏中的下 5 步棋。然后你意识到大部分时间游戏在 5 步之后仍然继续,你现在卡在这个中间步骤。你如何把数字输入到极大极小算法中?你需要的是一个评价函数。

一个评估函数是一种确定性地给游戏的当前状态打分的方法。例如,如果你在下棋,评估函数可以是你和你的对手拥有的棋子数量之间的数字差。差距越大,你的机会就越大。

一个更好的评估函数可以使用加权计算,其中每个部分都有一个取决于其重要性的权重。这可能会产生比简单地计数更好的结果。更好的是,除了它们的重量之外,还可以使用棋盘上的位置。

你如何定义你的评价函数完全取决于你自己。请注意,这将是你的算法中最关键的部分。你的评价函数有多好决定了游戏的状态,会很大程度上影响你算法的成功。当你写一个评估函数的时候,还有两件事你应该小心:

  1. **函数应该是确定性的:**给定相同的状态,应该总是产生相同的结果。
  2. **函数应该运行得很快:**您将会对您的评估函数进行很多调用。如果它工作缓慢,那么你的人工智能就会反应缓慢。

这是深度受限的极大极小算法的伪代码:

int minimax(Node* current, int depth, bool isMaximizer) { if (depth == DEPTH_LIMIT || current.isLeaf()) {
        return evaluate(current);
    } if (isMaximizer) { int val = INT_MIN;
        for (Node* child : current.getChildren()) {
            val = max(val, minimax(child, depth + 1, false));
        } return val; } else { int val = INT_MAX;
        for (Node* child : current.getChildren()) {
            val = min(val, minimax(child, depth + 1, true));
        } return val;
    }
}

加上α-β修剪,我们得到这样的结果:

int minimax(..., **int alpha, int beta**) { ... if (isMaximizer) { int val = INT_MIN;
        for (Node* child : current.getChildren()) {
            val = max(val, minimax(..., **alpha, beta**));
            **alpha = max(alpha, val);
            if (alpha >= beta) {
                break;
            }
**        } return val; } else { int val = INT_MAX;
        for (Node* child : current.getChildren()) {
            val = min(val, minimax(..., **alpha, beta**));
            **beta = min(beta, val);
            if (beta <= alpha) {
                break;
            }** } return val;
    }
}

我还有一个改进的建议。在您的搜索中,算法很可能会一次又一次地出现相同的状态。因此,您可以使用一个查找表来存储结果,而不是多次运行评估函数。见鬼,你甚至可以预先计算所有可能的结果。如果你想了解这个策略,你可以阅读我之前关于动态编程的故事。

你知道好莱坞电影中那些帅气的科学家走过一个长长的大厅,发表魅力演讲,讲述他们如何取得科学突破,并能用几句话向警察局长解释吗?是啊,那不是真的。事实上,有畸形的身体,没有生命的眼睛,彼此之间有沟通问题。当然除了我…

在人工智能应用中调整价值观

原文:https://towardsdatascience.com/aligning-values-in-ai-applications-afc9b814c000?source=collection_archive---------41-----------------------

最成功的人工智能系统与其用户、创造者和整个社会的价值观是一致的。

人工智能(AI)无处不在。当你使用互联网或一般计算机时,你会(有时不知不觉地)与数十个使用某种形式人工智能的系统互动。当你浏览网页时,广告网络为你提供个性化的广告,你的电话纠正你的拼写,你计算机的操作系统决定哪些程序优先使用计算资源。有些系统很好,有些不太好。我相信最成功的人工智能应用程序都有三方一致的价值观。

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

人工智能造福社会(图片由作者提供)

  1. 与系统互动的人,
  2. 这个系统的创造者,
  3. 所有者和参与者生活的社会。

所有的人工智能应用都或多或少地与这三组不同的价值观保持一致。我将简要阐述值集是什么,给出有不匹配的 AI 应用程序的例子,并以所有值都一致的例子结束。

三套价值观

与系统互动者的价值观

不同类型的人与人工智能系统交互,人工智能系统对他们的影响也不同。人们的理解水平和价值观各不相同。你可以肯定,与你的人工智能应用程序交互的人有一些价值观,从非常基本的价值观,比如发现能够养活自己和/或家人很重要。或者更复杂,比如发现有一个宽泛的参照系很重要。无论哪种方式,你的系统提供给他们的东西都会对他们追求价值的程度产生影响。

此外,人们可能或多或少地自愿与系统交互。他们不一定选择与一个系统互动,甚至可能没有意识地与它互动。一家银行开发了一个自动评估贷款申请的人工智能应用程序,迫使客户和员工都与它进行交互。人们可能没有意识到推荐系统会影响他们所呈现的内容,而这些内容会受到他们过去观看行为的影响。

人工智能系统可能会影响他们的价值观。贷款申请评估系统决定了人们是否会得到贷款。推荐系统影响他们接触的内容。

系统创造者的价值观

任何一方部署人工智能应用程序,无论出于何种原因,无论是服务于他们的客户群还是改善内部流程,都是基于一套价值观。这些可能非常琐碎,比如增加收入或降低成本。他们可能更无私,比如不浪费资源。或者,它们甚至可能是非常规范的,例如促进改善生活质量的健康生活方式。人工智能应用程序的目标是使部署系统的一方达到来自其价值观的目标。特别是对于推荐系统,对同时追求多个目标的系统的研究已经开始。一个系统可以增加人们观看或购买的视频数量,同时提供一个多样化的、广泛的参考框架。

部署应用程序的社会的价值观

现在,部署系统的一方和与系统互动的个人都是社会的一部分。这可能是国家层面的,但越来越多的是在全球社会中。现在一个社会也有价值观。法律和立法捕捉或正式化了这些价值观的一部分,而其他的价值观则稍微含蓄一些。例如,荷兰法律规定了广告商可以和不可以宣称什么来保护荷兰人免受欺骗。荷兰政府监察机构 Reclame Code Commissie 对此进行控制。另一方面,道德行为准则规定记者或编辑委员会在报道时应如何提供信息。虽然不符合他们的道德准则,但没有法律阻止他们不遵守这一准则。

使配合不当

有很多人工智能不成功的例子,因为不是所有的价值观都是一致的。上图提供了值之间只有部分匹配的 AI 应用程序的示例。

为创造者和个人服务的系统。

推荐系统是人工智能应用的例子,它符合个人和部署方的价值观。就我个人而言,我对 YouTube 和它为我创造的漂亮的循环过滤泡泡非常满意。我可以无休止地观看高度相关和令人愉快的骑行视频,完全符合我的个人喜好。我看视频,YouTube 可以给我看广告。双赢!然而,从社会的角度来看,我把所有的时间都花在看骑行视频上是不理想的,因为我也可以看新闻或其他话题,让自己得到更多的发展。如果我把时间花在看别的东西上,社会和我自己不会受益吗?

为造物主和社会服务的系统。

也有符合部署方及社会价值观的应用。虽然不是严格意义上的人工智能应用,但几年来,所有网站(应该)都要求我们同意通过 cookies 跟踪我们的行为。这完全符合部署方的价值观:他们没有支付罚款的风险,他们被允许使用我们的数据。这也符合我们的社会价值观:每个社会成员都拥有自己数据的所有权。但这符合我们作为公民的价值观吗?我们想拥有这种所有权吗?我们想被迫同意或拒绝同意吗?我个人重视毫不费力地浏览互联网,我不喜欢点击这种对我隐私的额外控制。法律的实施根本不能满足这一要求。

为社会和个人服务的系统。

我真的想不出这样的例子,这有什么意义,因为什么样的政党/组织会部署一个符合社会和个人,但不符合其自身价值观的系统?如果我们稍微搜索一下,可能会有一些例子,但我想这些例子不会存在很长时间,因为在某个时候部署方会拔掉这些例子的插头。

当所有三组值对齐时

在我读博士期间,我们也试图达到一致。在我们关于推荐系统中的选择过载的工作中,我们设计并测试了一个多样化算法来降低选择难度。当我们向用户提供一系列建议时,我们迫使他们做出决定。这个决定可能更容易,也可能更困难。我们的目标是创建易于选择的推荐列表,同时保持或提高满意度。通过大量研究,我们展示了增加推荐集多样性的效果,同时保持预测的相关性不变。这个想法是用户应该有满意的结果,但是从中选择不应该花费不必要的选择难度。然而,我们确实忽略了社会价值观。

一些系统将所有三组值对齐。这些系统的一个名字是 AI for Social Good (AI4SG ),这个运动正在通过学术研讨会、期刊、平台、LinkedIn 团体、博客获得越来越多的动力。也许并不奇怪,大多数 NGO 都在积极开发 AI4SG,例如通过使用机器学习来打击偷猎

那么,我们应该以什么为目标,又该如何实现呢?我不完全确定,但我 100%确信,无论我们在人工智能领域做什么,我们都必须开始沿着这三套价值观评估我们的举措。你有一个能让公司收入增加 20%的主意?酷!现在,去看看这个倡议与那些将与你的系统互动的人是如何一致的,以及社会将如何看待你的想法。你能确定你的想法会导致的结果符合你自己的价值观,与它互动的人的价值观,以及你将部署你的系统的社会所持有的价值观吗?那就去争取吧!否则,细化修改。我个人将确保我在 Obvion 的数据科学团队将对所有人工智能计划进行这些评估。我认为永远不出现任何不匹配是不现实的,但至少我们可以将任何无意识、无意的不匹配的可能性降至最低。

在实践中调整价值观

在我目前的角色中,我们正在创造人工智能。在早先的一篇文章中,我描述了我将如何尝试以一种对价值敏感的方式来做这件事,通过开发和部署人工智能,同时沿着两条轴线前进。我们成长的第一个方向是决策支持与自动化。我们将从为决策提供信息的模型开始,而不是自动决策。经理们最初可以使用预测贷款申请数量的模型来确保有足够的员工来处理这些申请。这种型号以后可以自动增加或减少容量。然而,这只有在经历了如何使用预测之后才会发生。其次,我们将从影响我们内部流程和利益相关者的人工智能开始,然后向外发展,到影响顾问和客户的人工智能。这也是为了确保我们可以实际检查我们的努力在多大程度上符合那些受我们人工智能影响的人的价值观。

原载于 2021 年 9 月 27 日【https://markgraus.net】

关于大数据的一切

原文:https://towardsdatascience.com/all-about-big-data-ae01afacc081?source=collection_archive---------21-----------------------

深入探讨什么是大数据以及如何存储大数据

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

约书亚·索蒂诺在 Unsplash 上拍摄的照片

在我最近的一篇文章中,我列出了一系列常见的数据科学术语,并对它们进行了简要描述。在列表中,我提到了大数据。但即使只是描述大数据的术语,也不足以描绘出数据究竟是如何存储的清晰画面。大数据被认为是太大而无法存储在单台计算机上的数据。但是,这些数据究竟是如何存储的呢?

本文的目标是了解关于大数据的更多信息,它是如何定义的,以及它存储在哪里。我们还将非常简要地讨论如何处理数据,尽管这可能是一个单独的主题。

什么是大数据?

如果您的数据太大,无法存储在单台计算机上,数据可能会快速增长,或者使用任何传统方法处理起来太困难或太耗时,那么您就拥有了大数据。随着结构化或非结构化数据集多样性的增长,数据的流入也可能是不可预测的。无论是从复杂性还是从数量上来看,大数据都难以用标准方法处理。例如,处理 SELECT 语句可能需要几天甚至几周,而不是几秒钟/几分钟。

因为数据太大,无法存储和处理,所以大数据在存储中的处理方式不同。大数据的一个存储位置是数据仓库,而不是计算机上的数据库。

什么是数据仓库?

为了存储和处理大量数据,数据仓库是数据存储的中心点。它是一个允许数据流入单一来源的系统,支持分析、数据挖掘、机器学习等。虽然它的目标是在一个位置存储数据,但不是在一台计算机上,另一个目标是处理数据。这从使用 ETL(提取、转换、加载)进行处理的数据管道开始。仓库收集数据,并以可用的方式对其进行格式化。无论数据来自哪里,它都是原始数据,可以被处理成有用的东西。

数据仓库处理大量的旧数据或新数据。但是,它存储的数据必须是结构化的。然后,可以将数据组织成模式,以供以后分析。

如上所述,数据仓库通常建立在结构化数据的基础上,并且通常使用关系数据库来保存数据。但是,如果数据是非结构化的,不适合关系数据库模型,该怎么办呢?这就是数据湖的由来。

数据一旦存储,就可以进行处理。这通常在处理系统中单独完成。处理需要单独进行,因为数据量,甚至其复杂性,对底层计算基础设施提出了很高的要求。在许多情况下,处理是在云中执行的。

什么是数据湖?

当数据是非结构化甚至不相关时,可以使用数据湖。数据湖存储没有定义模式的数据,因此数据不能存储在关系数据库中。但这并不意味着数据湖不能处理数据。数据湖可以创建各种可视化、实时分析等,但首先需要结构化数据。就像仓库一样,它是一个集中的存储场所,可以由多个来源提供信息。原始数据被存储起来供以后处理,但是数据湖可以简单地存储数据而不进行任何整理,而不是构造和添加模式。因为数据不需要结构化,所以它是高度可伸缩的,因为它可以容纳更多种类的数据。

回到模式,我们刚刚提到,您不需要创建任何模式来容纳数据,因为它不需要结构化。然而,模式仍然是数据湖的一部分。它们只是使用方式不同而已。例如,数据仓库将数据清理和过滤到模式中,这些模式是在预处理数据之前设计的。这被认为是写模式。有了数据湖,你就不用提前设计模式了。相反,模式是在分析数据时创建的。这被认为是读取模式。

为了存储数据,可以使用几种不同的存储设备。可以考虑云存储。如果需要数据库,数据湖使用非结构化或非关系模型,如 NoSQL 数据库。数据湖也可以存在于 Hadoop 集群等设备上。Hadoop 集群使用一系列称为节点的计算机,它们通过网络连接在一起。有一个主节点连接到剩余的节点(或工作节点),根据该节点的可用性分配任务。这允许在更大的数据集上进行并行计算。

您为数据湖选择的系统总是有可能不够用。这就是为什么数据湖可以与使用分布式体系结构的多个系统相结合。在这种情况下,数据湖将是存储和处理的集中点,但可以与其他平台分支。这可以是从多种存储类型到包括关系数据库和/或数据仓库的任何地方。尽管数据湖允许流入的数据保持其原始形式供以后处理,但您也可以选择使用不同的数据挖掘工具或数据准备软件进行预处理。

数据湖中的处理与数据仓库中的处理非常相似。两者的数据都太大,无法正常处理,因为这对底层基础架构的要求太高。值得注意的是,Hadoop 引擎还具有处理数据的能力。

结论

在本文中,我们深入探讨了大数据。我们定义了什么是大数据,以及如果大数据不能存储在单台计算机上,剩余的数据存储在哪里。在这个过程中,我们对什么是数据仓库有了更多的了解。我们还定义了什么是数据湖,以及如何在使用这种类型的流程中存储非结构化数据。

虽然没有详细介绍处理过程,但我们更关注什么是数据仓库,什么是数据湖。即使对 Hadoop 有一点了解,尽管不是很广泛。我希望你觉得这篇文章很有趣,也希望你能像我一样学到一些新东西。请随意留下您处理大数据的首选方法或您使用的存储类型的评论。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

看看我最近的一些文章:

https://python.plainenglish.io/i-suck-at-coding-cb9bc7ef6c06 https://python.plainenglish.io/arrays-vs-list-vs-dictionaries-47058fa19d4e https://python.plainenglish.io/converting-a-cli-app-to-typer-6c7462f5a9ff https://medium.com/codex/something-i-learned-this-week-entity-framework-is-picky-about-primary-keys-b5d7642c9ab7

参考资料:

https://aws.amazon.com/big-data/datalakes-and-analytics/what-is-a-data-lake/ https://www.ibm.com/analytics https://searchdatamanagement.techtarget.com/definition/big-data https://databricks.com/glossary/hadoop-cluster

关于 Deepfakes 的一切

原文:https://towardsdatascience.com/all-about-deepfakes-e481a55cf7e5?source=collection_archive---------24-----------------------

什么是 deepfake,它在当今世界有多“真实”?

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

约翰·努南在 Unsplash 上拍摄的照片

自从我一头扎进数据科学的世界已经有一段时间了。因此,在进行我的标准搜索时,我想看看哪些术语出现得更频繁,以及有哪些趋势值得关注。我注意到有一个术语出现得越来越多,那就是 deepfakes。我对什么是 deepfakes 有一个大致的概念,但在它们上面似乎有一些分歧。一些人认为它可能是破坏性的,另一些人认为它可能是无害的。很多人认为我们在技术上仍然落后很多年,所以它在很多年内都不会真正被看到,然而无论我们是否意识到,都有一些深度造假的例子已经持续了很多年。

这篇文章的目标是学习什么是 deepfake 以及它们现在是如何被使用的。这将是有益的,尽管我可能会分享一些故事或观点,但我无意试图说服您对该技术进行这样或那样的思考。在本文的最后,欢迎在评论中分享你的个人观点或经历。我期待着阅读它们。

但是没有任何进一步的延迟,让我们开始了解什么是 deepfake。

什么是 deepfake?

诚然,deepfakes 比我最初打算的要宽泛一点,所以一个清晰的定义有点难以挖掘。在更简短的定义中,deepfakes 是视频或照片被修改以包含其他人的肖像的实例。这是源于 AI(人工智能)的技术。

但我知道这听起来很模糊,所以让我们再深入一点。根据我的理解,从我看到的使用情况来看(不是说这可能是唯一的例子),deepfakes 是指你拍摄一个已经存在的视频或声音剪辑,然后把脸、声音或两者都换成别人。你在伪造版本中看到的不是真实的,并且会改变片段的上下文。这就是事情变得复杂的地方。这些视频的意图可能有点不清楚,或者海报的总体目标可以通过一个案例场景来改变。

当分解时,假的指的是剪辑不再是真实的,因为它们被从现实中操纵。然而,deep 可以指简短但仍然列出的各种会议。我的意思是,深度可以指变化的复杂性。然而,它也可以指强度。也许,这甚至意味着制造深度赝品的难度。

说到难度,制作一个深假需要什么?现在,对于用户来说,工作量可能会有所不同。例如,某些 Snapchat 滤镜会改变一个人的面部。我指的不是应用程序调整的面部,而是将你变成不同的人、角色甚至食物的特定过滤器。在这种情况下,改变你的脸对用户来说非常容易,尽管这并不令人信服。其他应用程序允许你根据另一个人的参考照片记录自己,但如果你稍微向左或向右移动头部,照片就不会向右伸展,这是一个非常明显的假货。然而,一些更真实的 deepfakes 需要机器学习和神经网络的混合。根据我们对机器学习和神经网络的了解,这将是一项非常困难的任务,更不用说耗时了。然而,这创建了更真实的图像,尤其是使用了更多的参考照片。

深度假货的例子

一个更真实的例子是抖音。在这个应用上,有一个用户假装成汤姆·克鲁斯(目前不在抖音)。现在,他不再诽谤甚至谈论今天的任何问题。相反,这些视频更多的是展示这项技术能做什么。其中一个视频只是关于吃的,它显示了当有数百万张照片供机器学习时,日常行为看起来有多真实。名人比普通人要容易得多,因为有更多的内容可以参考。

我还提到了 Snapchat 等不太现实的人脸交换应用。但这不是唯一的一个。在脸书上,你可以把你的脸加到一些电影角色上,这样你就可以在他们提供的任何场景中看到自己。它很简短,看起来不太真实,但是你的脸被融合到你从他们的列表中选择的一个角色上。

但这应该会让你想到 deepfakes 的意图。在你判断某件事是“不道德的”、“邪恶的”,或者甚至是“好的”和“创新的”之前,你需要考虑 deepfakes 的意图。当然,并不是所有人都有同样的意图。事情就是这样。但是,在你对这项技术做出最终判断之前,也许我们也应该考虑到这一点。

Deepfakes,他们邪恶吗?有创意?两者都有?

没有简单的方法让我们从创造性的一面开始,这并不坏。在我之前的例子中,他们都可以被视为只是有创意或有乐趣。使用一个有趣的过滤器并没有什么不好。Catfishing 是另一个故事,但我们假设如果你要做一个真正的 deepfake,它很可能是一个假的。把你的脸贴在你最喜欢的角色身上并不“邪恶”,这只是有点好玩。所以,在这种情况下,deepfakes 没有任何问题。

现在,有一些更现实的版本,如我们谈到的抖音汤姆克鲁斯,但帐户明确表示,他们的意图只是为了炫耀技术。因为他不是用它来影响,更多的是为了教育和娱乐的目的,所以在这种情况下,也不存在不道德的使用。

不幸的是,deepfakes 有一些“邪恶”或不道德的用法。例如,不用说太粗糙的话,有些人会把一个名人的脸伪装成一个不合适的身体,比如制作那个名人的虚假成人内容。尤其是如果那个名人选择不露出太多的皮肤,即使这是一个假的身体,这仍然是不道德的,通常只是出于自私或不适当的目的。

现在,我们最初谈论一个视频的意图。但如果目的是制造虚假信息或观点呢?例如,如果一些极端的政治观点被分享,然后有人把一个候选人伪造到那个极端的程度,只需要一个人相信这是真的就会导致诽谤。这是不道德的,也是一种诽谤。从伦理上讲,这将是不支持 deepfakes 的充分理由。然而,就目前而言,至少对普通大众而言,制作出足够真实的东西,让人们相信它毫无疑问是真实的,可能是遥不可及的。

deepfakes 还是新用的吗?

在我为获取资源而阅读的一些文章中,我注意到一个共同的趋势,即人们似乎认为技术还没有为 deepfakes 做好准备。他们可能指的是普通人还不能创造一个真实的深度赝品。但是对于那些认为它没有被使用的人来说,我认为这是不正确的。问问迷因社区就知道了。Deepfakes 用于制作我们在日常环境中发送给朋友的 memes、帖子或照片。他们可能看起来不太现实,但仍然,他们正在变得更好。不幸的是,成人内容中的名人头像在今天也是非常真实的,这些照片经常被修改以看起来更真实。你通常仍能分辨出它们是假的,但要区分起来要困难得多。现在,我们还没有普遍使用它来获得关于人们的错误信息或诽谤,这可能是他们所指的,或者至少它看起来很真实,但我们不知道诽谤将是主要用途。总会有人出于错误的原因使用技术,但这并不代表大多数人。

结论

最后,你应该做出你的结论,你是否认为 deepfakes 可以用于娱乐,或者它们是否会导致更不道德的道路。我们了解到 deepfake 是一种人工智能形式,它采用现有的剪辑,并交换诸如面部等事物。这就产生了一个视频的假版本。通常情况下,赝品看起来不太真实,但情况并非总是如此。技术、机器学习和神经网络可以用来创建更真实的假货版本,直到你剩下一个很难从现实中分辨出来的产品。

deepfake 的意图取决于人。有的用 deepfakes 来娱乐,有的用来教育,但有的也可能为自己的假货选择不道德的路线。在本文中,我们在定义了 deepfakes 之后介绍了几个例子。我们的目标只是简单地了解它们是什么,并举例帮助你熟悉识别一个深层次的假货,但不是说服你。你可能会对 deepfakes 做出判断,但很多人说技术还没有为逼真的假货做好准备,也许现在知道还为时过早。欢迎在评论中分享你对 deepfakes 的想法或你见过的例子。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

查看我最近的一些文章

https://medium.com/codex/quitting-kubernetes-kubeadm-and-switching-to-microk8s-b487e2abd482 https://miketechgame.medium.com/leaving-your-job-for-selfish-reasons-af1060ea51bf https://python.plainenglish.io/video-editing-with-python-73d419ba93ae https://medium.com/codex/kubernetes-vs-docker-swarm-d209e7cd58d7

参考资料:

https://www.merriam-webster.com/words-at-play/deepfake-slang-definition-examples https://us.norton.com/internetsecurity-emerging-threats-what-are-deepfakes.html https://www.technologyreview.com/2020/08/28/1007746/ai-deepfakes-memes/

提高不平衡机器学习分类器的性能

原文:https://towardsdatascience.com/all-about-imbalanced-machine-learning-classifiers-60563014d2b3?source=collection_archive---------13-----------------------

机器学习。数据科学。PYTHON。

处理不平衡数据集的综合指南

简介

作为一名菜鸟数据科学家,我犯的一个错误是高度重视准确性指标。现在,这并不是要否定准确性作为机器学习(ML)性能衡量标准的重要性。在某些模型中,我们的目标是具有高精度。毕竟,这个指标是高管和商业领袖最了解的。

但是,让我给你一个现实生活中的场景,当这样的指标可能会误导:

“你在一家成功的金融科技公司工作。你的老板给你一个识别欺诈性金融交易的模型。

用你的分类算法知识武装起来,你设计并实现了一个返回高达 98%准确率的算法。你的推销很成功,管理层对你这么快就想出这个模型印象深刻。

为了确保万无一失,他们希望你用真实世界的数据来尝试一下(实际上这是一个很常见的请求):一个用于欺诈性交易,一个用于非欺诈性交易, 都来自你的训练数据集 。令您惊讶的是:对于这两种情况,您的分类器都返回了 【非欺诈】 。这是怎么发生的?

您进行了调查,并了解到您使用的训练数据集包含 98%的非欺诈性交易和 2%的欺诈性交易(顺便说一句,这应该在探索性数据分析部分完成)”

直观地说,事情是这样的:因为数据集严重不平衡,而你的评分标准是“准确性”,它知道通过总是返回“非欺诈性”,它将总是有 98%的机会获得正确答案。

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

照片由 Alex BlockUnsplash 上拍摄

在分类机器学习(ML)模型的上下文中,不平衡数据集指的是数据不均匀分布在它所具有的类中的数据集。例如,在两个类的分类模型中,平衡数据集是指每个类在训练数据集中有五十(50%)个观察值。其他任何比例都是不平衡的。

在上面的示例中,我们称之为严重不平衡,因为与其他类(也称为多数类)相比,属于其他类(我们称之为少数类)的数据集比例非常小。

像我们例子中这样的不平衡数据集比你想象的更常见,也更重要。由于大多数数据科学家可能会在工作中处理它们,让我们概述一下我们可以做些什么来提高我们的不平衡数据集模型的性能。

对于下面的文章,我们将有一个直观的和理论的(数学讨论),我们将讨论一些代码。我们将以这种方式组织它,这样读者可以直接跳到他们最感兴趣的部分。

概要

为了让读者有机会跳到相关部分,下面是本文的大纲。

  1. 关于“原始”分类器方法的统计解释和直觉
  2. 适当的补救措施

对于适当的补救措施:我们将讨论以下内容

  1. 使用适当的指标
  2. 设定一个新的门槛:如何选择合适的门槛?
  3. 收集更多数据
  4. 扩充数据集和欠采样
  5. 重新思考模型的特征
  6. 方法(集合方法)

朴素分类器的统计理解

为了我们讨论的目的,让我们把我们在介绍中开发的分类器称为“简单分类器”。朴素分类器(与朴素贝叶斯分类器不同)之所以被称为朴素分类器,是因为它在产生或标记输出时过分简化了假设。

这方面的一个例子是总是预测多数类的分类器或总是预测少数类的分类器。另一种是从一组输出中随机猜测的分类器。

在上面的例子中,由于分类器总是输出多数类,所以这是一个简单分类器的例子。

我们直观地注意到,**通过将准确性设置为性能度量,**模型了解到通过总是返回多数类,它可以提供高准确性。

但是让我们试着用统计数据来理解为什么模型会有这样的反应。(这个借用了本 中的理论解释。)

编码—信用评分数据集

让我们使用哈佛大学的信用评分数据,这样我们就可以有一个具体的例子。

在使用的一个数据集中,我们分析了违约和非违约借款人的贷款金额分布。多数类属于非默认值(默认值== 0),少数类属于默认值(默认值== 1)。

让我们保持简单,只观察一维密度,因为直觉适用于更高维度。

#Individual Densities
fig,ax = plt.subplots(figsize=(10,12))
sns.kdeplot(df4[df4.default == 0]['total_inst_due'], color='#966fd6', linestyle="--")
sns.kdeplot(df4[df4.default == 1]['total_inst_due'],c='#900603', linestyle="--")fig.legend(labels=['p(x given Default == 0)p(Default == 0)','p(x given Default == 1)p(Default == 1)'])
plt.savefig("Individual Density.png")

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

违约与非违约的独立概率。(又名边际密度)。

从上图中,我们可以看到,就贷款金额而言,客户违约或未违约的概率遵循几乎相同的分布。

这将是有意义的,因为违约和非违约借款人都经历了相同的筛选过程,从这一逻辑出发,可以认为他们属于同质群体。这可能是也可能不是,取决于数据集和所讨论的变量。

但是,假设我们想要查看分类器输入特定类的概率,例如,它将为给定数据集输出“非默认”的概率。

为了解决这个问题,我们求助于贝叶斯定理中的全概率法则,并使用它们的联合密度来可视化这些类:

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

贝叶斯定理中的全概率定律应用于我们的例子。

如果我们考虑比例(也称为联合概率密度)并将其可视化,我们会得到以下结果:

#Joint-Densities
fig,ax = plt.subplots(figsize=(10,12))
sns.kdeplot(data = df4, x ='total_inst_due', hue='default',alpha =0.1, shade=True, legend=False)
fig.legend(labels=['p(Default == 0)','p(Default == 1)'])
plt.savefig("Joint-Density Plots.png")

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

联合密度图。

基于上面的密度图,我们看到,对于变量 x 的所有实例,属于多数类(非违约借款人)的图高于少数类的图。

这意味着:

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

简单来说,假设借款人没有违约,x 发生的概率总是大于借款人违约的概率。

因此,对于基于概率做出输出决策的分类器来说,总是预测多数类是很有意义的。

下图综合了上述所有图,便于参考:

#Combined Density Plots
fig,ax = plt.subplots(figsize=(10,12))
sns.kdeplot(df4[df4.default == 0]['total_inst_due'], color='#966fd6', linestyle="--")
sns.kdeplot(df4[df4.default == 1]['total_inst_due'],c='#900603', linestyle="--")
sns.kdeplot(data = df4, x ='total_inst_due', hue='default',alpha =0.1, shade=True, legend=False)fig.legend(labels=['p(x given Default == 0)p(Default == 0)','p(x given Default == 1)p(Default == 1)','p(Default == 0)','p(Default == 1)'])
plt.show()

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

便于参考的组合密度图。

如果各个阶层的人口差异很大怎么办?

假设类的个体密度显著不同。也就是说,不像在我们的信用决策数据集中,绘制它们显示人口有最小的重叠。

为了形象化这一点,让我们使用 seaborn 的虹膜数据集。

iris = sns.load_dataset('iris')

假设我们关心的是开发一个只能分类两个物种的分类器: setosaversicolor ,并且我们的数据集是不平衡的。

要查看单个(边缘)密度:

fig,ax = plt.subplots(figsize=(10,10))
sns.kdeplot(data = iris[iris.species.isin(['setosa', 'versicolor'])], 
            x ='petal_length', hue='species',alpha =0.1, shade=True, legend=False)#legend labels follow the order of plots according to the codes executed
fig.legend(labels=['P(species = setosa)', 'P(species = versicolor)'])plt.savefig("Iris.png")

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

一维——两个类别的个体密度:Setosa 和 Versicolor

因为个体密度彼此显著不同,我们将开发的分类器模型,即使它们不平衡,也不一定只预测多数类。

使用适当的指标

评估分类器性能的最常用方法之一是使用混淆矩阵。简单地说,混淆矩阵告诉我们,我们的模型在预测和识别数据集中的类时表现如何。从混淆矩阵中,我们可以推导出我们可以使用的多个度量标准。

为了便于理解,让我们定义将在公式中使用的因子。

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

将在指标公式中使用的变量的定义。在某些材料中,正类和负类被概括为 1 类和 2 类。

为了容易记住公式,只需知道第一个词(对或错)指的是预测的正确性,第二个词是预测的内容。

因此,混淆矩阵可以被形象化为:

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

我们使用 1 类和 2 类作为一般术语,但也可以称为“积极与消极类”,在我们的情况下,“多数与少数”类。

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

使用彩色块的分类度量。为了容易记住这一点,要知道对于任何类的精度和召回率,分子总是该类的“真正值”。现在对于分母,我通常认为对于“精度”,分母以字母“P”开始,因此是“类的预测”。(精确度听起来也更接近预测)。因此,通过排除过程,回忆在分母中具有该类别的“实际”。

回想一下,准确性告诉我们我们的模型获得了多少正确的预测。所以,通过正确,我们需要所有开头带“真”字的都是分子。

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

在这种情况下,我们使用“积极的”和“消极的”,但它们可以被称为“多数”对“少数”或更一般的“1 类”和“2 类”。注意,这里的分母只是预测的总数(N)。

所以这对于不平衡的类来说不理想的一个原因是,分子总是有一个高的 TP。

为了形象化,让我们试着为我们的信用决策示例编码并绘制一个混淆矩阵:

#Plotting for the ANN model
plot_confusion_matrix(mlp, X_test, y_test)  
plt.show()

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

信用决策分类器(ANN)的混淆矩阵

对于不平衡的二元分类器,我们上面的图是典型的,其中多数类的 TP 非常高,但少数类的 TP(或一些参考的假阴性)非常低。

请注意,scikit 和大多数机器学习包根据字母数字意义上哪个先出现来排列标签。由于我们期望的输出由“0”和“1”组成,分别代表“非违约借款人”和“违约借款人”,因此我们在混淆矩阵的左上角使用数字“0”作为其第一个元素。这恰好也是多数阶级。然而,如果我们翻转标签,请注意多数类的 TP 现在将显示在右下角。

精确和召回

对于不平衡的二元分类器,多数类的精度召回率(又名灵敏度或真阳性率(TPR)) 将总是高的。正如我们在上面所看到的,多数阶级的 TP 往往很高。

仅在分母上精度召回不同,其中精度具有该类别的预测总数,而召回具有该类别的观察总数。

精确度和召回率告诉我们模型的不同方面。 Precision 告诉我们模型在预测特定类别时的预测可靠性,而 recall 告诉我们模型识别特定类别的能力。理想的分类器应该同时具有高召回率和高精确度。

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

对此的解释借用了这个的帖子

为了创建一个表来提供每个类的精度和召回分数,让我们使用下面的代码。

labels = [0,1] #For a binary model, we use 0,1 but this can extend to multi-label classifiers
metrics =['precision', 'recall']def imbalance_classifier_metrics(labels, metrics, y_test, y_pred):
    summary = pd.DataFrame(columns=[i for i in metrics])
    summary.index.name = 'classes'for i in labels:
        precision = precision_score(y_test, y_pred, pos_label=i)
        recall = recall_score(y_test, y_pred, pos_label=i)
        summary.loc[len(summary)] = [precision, recall]
    return summaryimbalance_classifier_metrics(labels, metrics, y_test, y_pred)

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

以上函数的结果

如前所述,多数类的准确率和召回率都很高。我们理想地想要一个分类器,它能给我们一个少数类可接受的分数。让我们稍后讨论我们可以做些什么来改善这一点。

请注意,在一些

F1——得分

F1 分数,或者有些人可能称之为 F 分数,是精确度和召回率的加权调和平均值。

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

作为调和平均值,该度量惩罚精度和召回的极值。以高召回率(比如 0.95)和低召回率(比如 0)为例。).使用上面的公式,整个事情变成 0,表明该模型根本没有用。

请注意,F1 衡量标准对精确度和召回率赋予了相同的权重,但也可能对这些衡量标准赋予不同的权重。调和平均值在 F1 测量中的应用是最受欢迎的。

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

我们上面的函数的结果,包括 f1 分数

ROC 和 AUC

ROC 曲线同样有助于开发我们的分类器。然而,根据我的经验,我在细化部分使用它。

ROC 曲线代表受试者工作特性曲线。它是我们改变阈值时分类器如何执行的图形表示。

通常,二元分类器使用 50%作为默认阈值。这意味着为了将一个对象分类为属于某一类,该对象属于该类的概率应该大于 50%。

统计数据显示:

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

如果对象属于一个类别的条件概率大于或等于 50%,则该对象被分类为属于该类别。

然而,对于不平衡的数据集,默认阈值不起作用。更多细节请参考上面的统计解释。

然而,如果我们调整阈值 T,我们可能能够提高分类器的性能。

前面我们的分类器条件的一般形式如下:

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

因此,ROC 曲线告诉我们,当我们改变这个阈值时,分类器性能会发生什么。

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

根据模型性能不同的 ROC 曲线。

在我们上面的图中,红色图被认为是最好的分类器,因为它只牺牲了一点点精度来增加回忆。如果你看看精确度的公式,假阳性越高,精确度越低。图中最差的分类器牺牲了很多精度来提高召回率。

顾名思义,AUC 或(曲线下面积)测量曲线下的面积。此指标的最低可能值为 0.5,而最高可能值为 1。AUC 的好处是,它能够在一个缩放的级别上比较模型值。

为了在我们的示例中生成 ROC 和 AUC,让我们使用我们生成的三个模型之一,即随机森林。我们需要得到输出概率而不是输出标签:

#For Random Forestyhat = forest.predict_proba(X_test)
#retain only the positive class probability
yhat = yhat[:,1]fpr, tpr, thresholds = roc_curve(y_test, yhat)
roc_auc = metrics.auc(fpr, tpr)#PLOT
plt.title('Receiver Operating Characteristic')
plt.plot(fpr, tpr, 'b', label = 'AUC = %0.2f' % roc_auc)
plt.legend(loc = 'lower right')
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()

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

我们看到 AUC 得分为 0.62,这并不是很好,因为最低得分为 0.5。如果 AUC 分数是 0.5,这告诉我们的分类器“没有技能”。

如何选择合适的门槛?

为不平衡的分类器选择正确的阈值本身就是一门科学,我们需要问自己,我们想要为此优化什么。

给出一些决策规则:

  1. 使特异性(1-FPR)和敏感性(TPR) 之和最大化。这是直观的,因为这最大化了所有类的总正确预测。数学上:

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

T_func = (1-fpr) + tpr
ix = np.argmax(T_func)
best_thresh = thresholds[ix]
print('Best Threshold=%f' % (best_thresh))

2.**将敏感性和特异性之间的差异最小化。**根据希门尼斯-瓦尔夫德& Lobo (2007) **,的研究,使用阈值导致灵敏度和特异性之间的最小差异的分类器,**往往比使用阈值使两者之和最大化的分类器表现稍好。这是真的,尤其是如果犯错误和不犯错误的代价一样大的话。

3.选择哪个导致特异性和敏感性的最高几何平均值。其逻辑遵循第一点,我们的目标是选择一个具有高特异性和敏感性的模型。

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

实际上,这简化成了尤登的 J 统计量:

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

J = tpr - fpr
ix = np.argmax(J)
best_thresh = thresholds[ix]
print('Best Threshold=%f' % (best_thresh))

4.基于成本的阈值

分类器算法通常使用两个假设:类是平衡的,错误的代价是相等的。因此,需要考虑类别不平衡和成本不平等,以优化使用默认假设的分类器。

根据分类器的使用情况,假阳性可能比假阴性代价更高。

举一个极端的例子,将嫌疑人归类为死刑。将一个无辜的人归类为“阳性”以判死刑(假阳性),比将一个有罪的嫌疑人归类为无辜(假阴性)的代价要大得多。

对于这些情况,单独的研究应该指出这些成本的权重以及它们最终将如何影响阈值。

下面是一个最小化成本函数的示例:

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

正如 W.B .兰登建议的那样。这个成本函数的好处是,它考虑了阶级不平衡和成本不平等。

alpha  = 1
beta = 2 #Let us assume that the cost of missing a positive case is twice as costly as incorrectly marking one as positivep = sum(y_test ==1)
p_prime = len(y_test) - p#Cost function
C = (p_prime*alpha*fpr)+(p*beta*(1-tpr))
ix = np.argmax(C)
best_thresh = thresholds[ix]
print('Best Threshold=%f' % (best_thresh))

选择阈值后,使用以下代码来使用阈值:

#Use the predict_proba method of your classifier
y_pred = (forest.predict_proba(X_test)[:,1] >= best_thresh).astype(bool)

收集更多数据

有时,尽管我们对模型进行了修改,它们仍然不能产生能够可靠地预测少数阶级的模型。

收集更多的数据是你能做的唯一最好的事情,以提高你的模型的有效性,最好是少数民族的模型。更多的数据有助于模型更好地学习该类的特征,从而提高其识别和预测该类的可靠性。

扩充数据集和欠采样

虽然这是大多数数据科学家采用的一种技术,但在应用这种技术时应该小心,因为这不能代替收集更多数据。

在不平衡机器学习的上下文中,欠采样和过采样分别指删除多数类的实例和创建少数类的新实例。

扩增和欠采样的危险在于,它改变了潜在的类别比例,这可能与现实世界中的比例不同。那么,人工比例将是你的模型所学习到的,在现实世界中进行预测时可能不合适。

关于数据扩充的一个论点是,它可以用来使样本比例达到人口比例。例如,如果你知道人口中有 10%的少数民族,而你的样本只有 5%,那么数据扩充可能会弥补他的差距。这可能会给数据科学家一种虚假的安全感,因为数据扩充(甚至欠采样)不会产生任何 新信息。有可能我们刚刚完成的是改变我们的模型学习的比例,因此使它在现实世界中无效。

出于这些目的,可以采用分层抽样来分割训练和测试数据集,交叉验证。这有效地考虑了训练和测试数据集中类的比例。

X_train, X_test, y_train, y_test = train_test_split(X,y, stratify=y)

我们同样可以应用不平衡学习包中的 SMOTE。SMOTE 意味着合成少数过采样技术。顾名思义,它用于对 minority 类进行重采样,以便它在数据集中具有更高的代表性。同样,数据科学家在使用这些技术时应该谨慎。

反思模型的特点

有可能模型发现识别少数民族类具有挑战性,因为其分布在某些特征上与多数民族相似。但是,如果您碰巧有一个特征,其中类之间的分布差异很大,则模型可能会使用该特征来正确识别和预测。

使用 seaborn 包的 pairplot 可以帮助您快速识别这一点。如果将色调参数设置为类变量,配对图的主对角线(密度图)将告诉您是否存在多数类和少数类分布显著不同的要素。

sns.pairplot(df2, hue='default')

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

来自信用评分数据集的第二个交易数据集的 Pairplot。从最初看,似乎没有可用的特性可以帮助模型更好地学习这两个类。然而,如果我们观察“年龄”的密度,我们会发现在 X 轴的后半部分有一些分离。这意味着随着人们变老,他们更有可能违约。将此添加到模型中可能会提高模型性能。

集成方法

根据关于该主题的大量实验,集成方法是健壮的学习器,并且在处理不平衡数据集时比我们上面讨论的任何采样方法更有效。

集合方法的超参数需要改进,但我建议你不要使用 scikit 的内置参数,因为它是为了“准确性”而调整的。从头开始创建一个函数,并以 F1 值较高的函数为目标。

#Example of code to tune the learning rate:lr_list = [0.05, 0.075, 0.1, 0.25, 0.35, 0.5, 0.6, 0.75, 0.9, 1]
labels = [0,1] #For a binary model, we use 0,1 but this can extend to multi-label classifiers
metrics_to_calc =['precision', 'recall', 'f1']#we used the function above re: precision, recall, f1 scorerfor learning_rate in lr_list:
    gb_clf = GradientBoostingClassifier(n_estimators=20, learning_rate=learning_rate, max_depth=10, random_state=0)
    print("Learning rate: ", learning_rate)
    y_pred = gb_clf.fit(X_train_scaled, y_train).predict(X_test_scaled)
    display(imbalance_classifier_metrics(labels, metrics_to_calc , y_test, y_pred))

让我们用上面的数据集来举一个具体的例子:

models = {"Logistic Regression": logreg,
          "Multilayer Perceptron": mlp,
          "Random Forest": forest,
          "Gradient Boosting": gb_clf}titles = list(models.keys())#Generate the AUC plot for the models
fig, axes = plt.subplots(2,2, figsize=(12,12))
fig.suptitle("AUC for Different Models", fontsize=20)
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0.4, hspace=0.4)for i in range(4):
    #Calculate the metrics
    yhat = models[titles[i]].predict_proba(X_test_scaled)
    yhat = yhat[:,1]
    fpr, tpr, thresholds = roc_curve(y_test, yhat)
    roc_auc = metrics.auc(fpr, tpr)

    #Plo
    axes[i//2][i%2].plot(fpr, tpr, 'b', label = 'AUC = %0.2f' % roc_auc)
    axes[i//2][i%2].legend(loc = 'lower right')
    axes[i//2][i%2].plot([0, 1], [0, 1],'r--')
    axes[i//2][i%2].set_xlim([0, 1])
    axes[i//2][i%2].set_ylim([0, 1])
    axes[i//2][i%2].set_ylabel('True Positive Rate')
    axes[i//2][i%2].set_xlabel('False Positive Rate')
    axes[i//2][i%2].title.set_text("{}".format(titles[i]))

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

随机森林和梯度推进分类器在识别和预测少数类方面表现都非常好。回想一下,AUC 用于提供性能的标量测量,最高可能值为 1.0。对于梯度推进分类器,我们得到 0.93。

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

梯度推进分类器在精确度、召回率和 F1 分数方面的巨大改进。

以下是我们为提高该特定数据集的少数民族类的模型性能所做的工作:

  1. 选择具有更多默认值的事务数据集(收集更多数据,df2 比 df4)
  2. 反思特征:增加了“年龄”,因为分布在 x 轴的后半部分显示了潜力
  3. 使用分层参数来训练和测试数据集
  4. 使用超参数调整的集成方法来产生稳健的分类器
  5. 可选:人们甚至可以选择结合我们在中学习的技术来选择正确的阈值部分。

对于更加定制的算法,您可以使用具有分裂标准的集成方法,例如海灵格距离(例如海灵格距离额外决策树(HeDEx) )

结束语

不平衡的数据集是数据科学悖论的典型例子。一方面,虽然数据科学家处理不平衡的分类器(甚至可能比平衡的分类器更多)非常常见,但目的通常是识别不常见的类。

在处理这一问题时,没有一个放之四海而皆准的解决方案,虽然我们讨论了许多可能的补救措施,但人们应该注意到,处理不平衡的分类器可以早在数据收集阶段(例如收集更多数据)和探索性数据分析(例如查看密度以确定应该包括的特征)就开始了。

我们的清单虽然全面,但绝不完整。我鼓励每个人都尝试自己的补救措施,并与我们分享,这样我们所有人都能学得更好。

感谢您的阅读!

完整代码可以在我的 Github 页面找到。

参考文献

处理机器学习中的不平衡数据集

针对不平衡分类的阈值移动简介

混淆矩阵

如何使用概率开发和评估朴素分类器策略

准确度 vs F1 分数

用 SciKit 学习 Python 中的梯度增强分类器

选择最佳阈值的常用方法

手机扫码点餐功能:用户可以通过扫描二维码或者搜索菜品名称,选择菜品并下单。 多人在线同时点餐:当多人同时点餐时可以实时同步共享以点菜单,共享购物车。 商户前台点餐功能:商户管理端也有点餐功能,商户可以帮助顾客点餐,而并不是只能顾客扫码点餐。 餐桌状态实时监控:餐桌的使用情况可以实时的展示出来,无需手动刷新, 同时也方便顾客查看餐桌的使用情况,快速寻找可用餐桌。 菜品管理:商户可以在管理端对店铺中的菜品进行管理,例如可以对菜品进行增加、修改和删除等功能。 菜品分类管理:设置菜品包含的分类,商户点餐端可以根据分类快速查找商品,同时顾客点餐端也会根据菜品分类展示菜品。 桌号管理:商户可以对店铺中的就餐桌进行编号,并录入到系统中,就可以通过系统对餐桌进行管理。 区域管理:对餐桌的分布位置进行管理,使商户更加方便的进行管理。 生成餐桌二维码:商户可以针对某一桌号生成当前餐桌的二维码,用户扫描后就可以针对当前餐桌进行点餐。 店铺数据统计:餐厅可以通过扫码点餐系统统计订单数据,包括销售额、菜品销量等。 店铺设置:商户可以设置店铺的一些展示信息,例如店名、介绍、公告等信息。这些信息同时会展示在顾客点餐端。 小票打印机管理:商户可以绑定小票打印机,当有订单时就会自动打印当前订单的一些信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值