TowardsDataScience 博客中文翻译 2019(四百三十五)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

为机器学习工作流扩展 Apache 气流

原文:https://towardsdatascience.com/scaling-apache-airflow-for-machine-learning-workflows-f2446257e495?source=collection_archive---------8-----------------------

了解如何在云上轻松执行 Airflow 任务,并获得每个机器学习任务的自动版本控制。

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

Apache Airflow 是一个用 Python 创建、调度和监控工作流的流行平台。它在 Github 上有超过 15k 颗星,被 Twitter、Airbnb 和 Spotify 等公司的数据工程师使用。

如果您使用的是 Apache Airflow,那么您的架构可能已经根据任务的数量及其需求进行了改进。在 Skillup.co 工作时,我们首先有几百个 Dag 来执行我们所有的数据工程任务。然后我们开始做机器学习。

我们希望继续使用气流来编排机器学习管道,但我们很快意识到我们需要一种解决方案来远程执行机器学习任务。

在本文中,我们将看到:

  • 在气流中扩展工作节点的不同策略。
  • 机器学习任务与传统 ETL 管道的不同之处。
  • 如何在云上轻松执行气流任务?
  • 如何获得每个机器学习任务的自动版本控制?

使用执行器扩展 Apache 气流

Apache Airflow 具有基于调度器、工作节点、元数据数据库、web 服务器和队列服务的多节点架构。

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

Example Airflow architecture.

使用气流时的首选之一是执行器的类型。执行器与调度器通信,在任务排队时为每个任务分配资源。遗嘱执行人之间的区别在于他们拥有的资源。

顺序执行者

默认的执行器使得在本地测试气流变得很容易。它在一台机器上顺序运行任务,并使用 SQLite 存储任务的元数据。

本地执行者

本地执行器可以并行运行任务,并且需要像 PostgreSQL 这样支持并行性的数据库。虽然您可以在生产环境中运行本地执行器,但通常会迁移到 Celery executor 来提高可用性和可伸缩性。

芹菜执行者

Celery executor 要求设置 Redis 或 RabbitMQ 来向工作人员分发消息。气流然后将任务分配给芹菜工人,他们可以在一台或多台机器上运行。这是我们在 Skillup.co 使用的执行器,能够运行多达 256 个并发数据工程任务。

库伯内特遗嘱执行人

Kubernetes 执行器为每个任务实例创建一个新的 pod。它允许您根据任务需求动态地伸缩。

与运营商一起扩展 Apache 气流

另一种扩展气流的方法是让操作员远程执行一些任务。2018 年,杰西卡·拉夫林认为我们都在错误地使用气流,正确的方法是只使用 Kubernetes 算子。她认为应该有一个单一的无 bug 操作符来执行任意任务,而不是一个不断增长的特定功能操作符列表。

Kubernetes 算子

Kubernetes 操作员将在一个新的 pod 中启动一个任务。当您有一组需要定期运行的任务时,我发现只对有特定需求的任务使用 Kubernetes 操作符是一个更好的主意。

我认为 Kubernetes 操作符的主要问题是,您仍然需要理解 Kubernetes 配置系统并设置一个集群。例如,Dailymotion 在谷歌 Kubernetes 引擎上的一个集群中部署了 Airflow,并决定通过 KubernetesPodOperator 来扩展 Airflow 用于机器学习任务。

在我们的案例中,我们是一个小型数据团队,几乎没有资源来建立一个 Kubernetes 集群。我们希望专注于构建机器学习模型,而不是管理基础设施。

机器学习任务与 ETL 任务有何不同?

在 Skillup.co,我们不得不作为一个小团队在一年内构建和部署几个数据产品。我们知道我们想要使用开源库来构建我们的模型,从经典的机器学习模型到深度学习。我们也在寻找一个机器学习平台来帮助我们扩展和版本控制我们所有的模型

Airflow 在跟踪元数据数据库中的每个任务细节方面做得很好,但机器学习任务与 ETL 任务有不同的要求。机器学习任务与数据、代码、环境、参数和指标相关联。这些信息不是由气流收集和显示的。Kubernetes 只在基础设施方面帮助你。

在一个地方收集每次执行的所有相关信息有助于调试机器学习模型。在下表中,你可以看到我们跟踪的信息,以更快地迭代机器学习模型。

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

Important information for machine learning version control.

我们对扩展机器学习任务的选择

你已经可以找到几个像谷歌数据流,亚马逊 SageMaker 和 Databricks 这样的机器学习平台的气流运营商。这些操作符的问题在于,它们都有不同的规范,并且仅限于在这些平台上执行代码。

在我们开始在 Skillup.co 做任何机器学习之前,我们将 Airflow 用于所有数据工程,这些工程主要由 Airflow BashOperator 调用的 Python CLIs 组成。

然后我们决定使用 Valohai ,一个基于开放标准构建的机器学习平台,帮助我们远程启动机器学习任务,并获得自动版本控制。

拥有一个混合解决方案使我们能够将敏感数据保存在我们的 Airflow 装置中,并将机器学习委托给 Valohai。

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

Machine learning workflow with an Airflow DAG. Blue tasks are executed remotely thanks to Valohai.

感谢 Valohai 的开放 API ,我们开发了开源的 airflow-valohai-plugin 来整合两个平台。去年,我们用它在生产中发布了四个机器学习模型。

瓦罗海算子

Valohai 运算符背后的思想类似于 Kubernetes 运算符。好处是你不需要理解 Kubernetes,你也可以获得机器学习的自动版本控制。

Valohai 将根据您的需求、代码和数据启动和停止云实例。Valohai 操作符只是在 Docker 容器中执行一个命令,轮询它的完成情况并返回最终的状态代码。

通过提供 Docker 映像和您的代码库,您可以执行任何语言和库的代码。你还可以访问 AWS、Google 和 Azure 中的 50 多个云环境。

要创建一个关于 Airflow 的任务,您只需要指定要执行的 Valohai 项目和步骤。如果需要,您还可以覆盖默认的云环境、输入和参数。

Sample code to submit an execution to Valohai from Airflow [source].

另一方面,您需要通过创建 valohai.yaml 在 Valohai 端进行一些简单的配置。 valohai.yaml 作为一个配置文件来设置默认值,并验证机器环境、docker 映像、要运行的命令、参数和每次执行的输入数据文件。

从一开始就拥有机器版本控制有助于我们调试数据、代码和参数,从而更快地进行预测和修复。就像你希望你的气流任务是幂等的,以避免重新启动它们时的副作用一样,你希望你的机器学习模型基于代码和数据的审计版本。如果您总是使用存储在数据湖中的文件来训练您的模型,这很容易做到。下面你可以在 Valohai UI 中看到一个执行的解析配置。

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

Valohai UI with execution details [source code].

Valohai 建立在两个明智的选择之上,这两个选择使得它可以很容易地与任何编程语言和库集成。

首先,选择一个对所有编程语言通用的 CLI 优先接口。CLI 是一个流行的接口,用来包装您的函数,以便在本地执行它们。CLI 也是 Bash、Kubernetes 和 Valohai 操作符的接口。

第二,从标准输出中收集执行指标,而不是为每种语言安装一个定制的库。所有语言都有将 JSON 对象写入标准输出的工具。Valohai 将自动解析该对象,例如,帮助您比较每个模型的准确性。

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

Valohai UI to compare execution’s parameters and accuracy.

您还可以在 Valohai UI 中手动启动执行,而不会有任何副作用。在 Airflow 中,清除一个任务的状态将触发下游任务。

最后但同样重要的是,新的 Valohai 操作符允许您轻松地将一次执行的输出作为下一次执行的输入。这帮助我们创建了管道,数据在 S3 上自动版本化。此外,每个新的执行都在与 S3 bucket 相同的云提供商和区域上运行,这使得 Valohai 可以快速地将它下载到 AWS EC2 实例上。

结论

Apache Airflow 是创建、调度和监控工作流的强大工具,但它是为 ETL 任务而构建的。机器学习任务需要特定的资源,并且它们的执行细节应该受到版本控制。

如果你有资源来维护一个 Kubernetes 集群,你可以用 KubernetesPodOperator 来扩展机器学习任务。

如果你想专注于建立模型,你可以用ValohaiSubmitExecutionOperator来缩放用于机器学习任务的气流。通过这种方式,您还可以通过 Valohai 获得每次执行的自动版本控制。

有用的资源

从 0 到数百万用户扩展机器学习—第 1 部分

原文:https://towardsdatascience.com/scaling-machine-learning-from-0-to-millions-of-users-part-1-a2d36a5e849?source=collection_archive---------3-----------------------

突破笔记本电脑

我认为大多数机器学习(ML)模型都是在白板或餐巾纸上构思出来的,诞生于笔记本电脑上。当这些羽翼未丰的生物开始咿咿呀呀地说出它们的第一个预言时,我们充满了自豪,并对它们未来的能力寄予厚望。唉,我们内心深处知道,并非所有人都会成功,远非如此。

当我们建造它们时,一小部分很快就让我们失望了。其他的看起来很有希望,并显示出一定程度的预测能力。然后,我们面临着在生产环境中部署它们的严峻挑战,在生产环境中,它们要么证明自己传奇的勇气,要么不光彩地死去。

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

One day, your models will rule the world… if you read all these posts and pay attention 😉

在这一系列观点鲜明的帖子中,我们将讨论如何训练 ML 模型并将其部署到生产中,从卑微的开始到统治世界。在这一过程中,我们将努力采取公正合理的措施,与过度设计、炒作驱动的开发以及“为什么不直接用 XYZ 呢?”的邪恶势力作斗争。

尽可能享受您的数据科学沙盒的安全舒适,并为寒冷、严酷的生产世界做好准备。

第 0 天

所以你想建立一个 ML 模型。嗯。让我们停下来想一想:

不要对此置之不理:没有机器学习比没有机器学习更容易管理。找到一种使用高级服务的方法可以为你节省几周甚至几个月的时间。

如果答案是“是”

请扪心自问:

  • 为什么您要费尽周折构建一个冗余的定制解决方案呢?
  • 你真的是“缺失功能”吗?什么是真正的业务影响?
  • 你真的需要“更高的精确度”你怎么知道能达到呢?

如果你不确定,为什么不用你自己的数据进行一次快速概念验证呢?这些服务是完全托管的(不需要…更多…服务器),并且非常容易集成到任何应用程序中。弄清楚它们不需要花太多时间,然后你就会有可靠的数据来做出有根据的决定,决定你是否真的需要训练你自己的模型。

如果这些服务对你来说足够好,那么恭喜你,你基本上完成了!如果你决定建造,我希望听到你的反馈。请保持联系。

如果这个答案是“否”

请再问自己一次这个问题!我们大多数人都有扭曲现实和欺骗自己的惊人能力:)如果诚实的答案真的是“不”,那么我仍然建议考虑一下您可以使用高级服务的子流程,例如:

  • 使用 Amazon 翻译支持的语言对,并使用您自己的解决方案来翻译其余的语言对。
  • 在将人脸输入到你的模型之前,使用亚马逊的识别功能来检测人脸,
  • 使用 Amazon Textract 来提取文本,然后将其提供给 NLP 模型。

这不是推销 AWS 服务(我看起来像销售人员吗?).我只是想让你免于重新发明轮子(或轮子的部件):你真的应该专注于手头的业务问题,而不是建造你在博客帖子中读到的或在会议上看到的卡片房子。是的,它在你的简历上可能看起来很棒,这个轮子最初是一个有趣的旋转木马…然后,它变成了痛苦之轮,你被拴在它上面,别人拿着鞭子

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

Why did I blindly trust that meetup talk? Crom! Help me escape and bash that guy’s skull with his laptop.

反正消极够了:)你确实需要一个模型,我们继续吧。

第一天:一个用户(你)

我们将从您在本地机器(或本地开发服务器)上训练模型的阶段开始我们的旅程,使用流行的开源库,如 scikit-learnTensorFlowApache MXNet 。也许你甚至已经实现了自己的算法(数据科学家,你们这些魔鬼)。

您已经使用测试集测量了模型的准确性,情况看起来不错。现在您想要将模型部署到生产中,以便检查它的实际行为,运行 A/B 测试,等等。从哪里开始?

批量预测还是实时预测?

首先,您应该弄清楚您的应用程序是否需要批量预测(即收集大量数据点,定期处理它们并将结果存储在某个地方),或者实时预测(即向 web 服务发送一个数据点并接收一个即时预测)。我之所以提前提出这一点,是因为它对部署复杂性有很大的影响。

乍一看,实时预测听起来更有吸引力(因为…实时,耶!),但它也带来了 web 服务固有的更强的需求:高可用性、处理流量突发的能力等。批处理更加轻松,因为它只需要时不时地运行:只要不丢失数据,没有人会看到它是否在中间被破坏了;)

缩放现在不是一个问题:您关心的只是部署您的模型、测试轮胎、运行一些性能测试等等。从我的经验来看,您可能选择了最短的路线,将所有东西部署到一个 Amazon EC2 实例。每个人都知道一点 Linux CLI,你在某处读到过使用“IaaS 将保护你免受邪恶的供应商锁定”。哈!那就 EC2 吧!

我听到 AWS 时空连续体中充满恐惧和怀疑的尖叫声,也许还有一些类似“哦,这太愚蠢了,没有人真的这么做!”。嗯,我敢打赌,到目前为止,大多数人都是这样开始的。如果你没有,恭喜你,但是请让我告诉这些好人,在他们真正伤害自己之前,哪条路是出路;)

所以,盯着我的魔镜,我看到…

批量预测

您已经将模型、批处理脚本和应用程序复制到 EC2 实例中。您的批处理脚本作为 cron 作业定期运行,并将预测数据保存到本地存储。您的应用程序在启动时加载模型和初始预测数据,并使用它来做任何它必须做的事情。它还会定期检查更新的预测,并在它们可用时加载它们。

实时预测

您已经将模型嵌入到应用程序中,在启动时加载它,并使用各种数据(用户输入、文件、API 等)提供预测。).

不管怎样,你现在正在云中运行预测,生活是美好的。你用一品脱黑啤酒来庆祝…或者可能是无麸质、公平交易的有机豆奶拿铁,因为毕竟是 2019 年了。

第一周:一个抱歉的用户(你)

该模型预测得很好,并且您希望投入更多时间来收集更多数据和添加功能。不幸的是,没过多久事情就变糟了,你现在陷入了各种各样的问题(下面是不完整的列表):

  • 在您的笔记本电脑上进行培训并手动部署到云是一件痛苦且容易出错的事情。
  • 您意外地终止了 EC2 实例,不得不从头开始重新安装。
  • 你’ pip 安装了-Python 库,现在你的 EC2 实例全乱了。
  • 您必须为您的同事手动安装另外两个实例,现在您真的不能确定你们都在使用相同的环境。
  • 您的第一个负载测试失败了,但是您不确定应该归咎于什么:应用程序?模特?阴间的古人巫师?
  • 您希望在 TensorFlow 中实现相同的算法,也许在 Apache MXNet 中也是如此:更多的环境,更多的部署。没时间了。
  • 当然还有大家的最爱:销售听说“你的产品现在有 AI 能力了”。你害怕他们会把它卖给一个客户,然后让你下周去大规模现场。

这样的例子不胜枚举。如果不是真的会很搞笑(欢迎在评论里补充自己的例子)。突然之间,这个 ML 的冒险听起来不那么令人兴奋了,不是吗?你将大部分时间花在救火上,而不是建立最好的模型上。不能这样下去了!

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

I’ve revoked your IAM credentials on ‘TerminateInstances’. Yes, even in the dev account. Any questions?

第 2 周:反击

团队中有人观看了这个非常酷的 AWS 视频,其中展示了一个名为亚马逊 SageMaker 的新 ML 服务。您记住了这一点,但是现在,没有时间重新构建一切:销售人员正紧盯着您,几天后您有一个客户演示,您需要强化现有的解决方案。

很有可能,你还没有堆积如山的数据:训练可以等等。你需要专注于让预测变得可靠。这里有一些可靠的技术措施,实施起来不会超过几天。

使用深度学习 AMI

由 AWS 维护的这个亚马逊机器映像带有预装的许多你可能需要的工具和库:开源、NVIDIA 驱动程序等。不必管理它们将为您节省大量时间,并且还将保证您的多个实例以相同的设置运行。

AMI 还附带了 Conda 依赖和环境管理器,它可以让您快速轻松地创建许多隔离的环境:这是一个用不同的 Python 版本或不同的库测试您的代码的好方法,而不会意外地破坏一切。

最后但同样重要的是,这个 AMI 是免费的,就像任何其他 AMI 一样,如果你真的有必要,你可以定制。

打破巨石

您的应用程序代码和您的预测代码有不同的需求。除非你有令人信服的理由这样做(超低延迟可能是一个),否则它们不应该生活在同一个屋檐下。让我们来看一些原因:

  • 部署:每次更新模型都要重启或者更新 app 吗?或者 ping 你的应用程序重新加载它或其他什么?不不不,保持简单:说到解耦,没有什么比构建独立的服务更好的了。
  • 性能:如果您的应用程序代码在内存密集型实例上运行得最好,而您的 ML 模型需要 GPU,该怎么办?你将如何处理这种权衡?你为什么会偏爱其中一个?将它们分开让你为每个用例挑选最佳的实例类型。
  • 可伸缩性:如果您的应用程序代码和您的模型具有不同的可伸缩性配置文件,那该怎么办?在 GPU 实例上横向扩展是一种耻辱,因为您的一小部分应用程序代码正在热运行…同样,最好将事情分开,这将有助于采取最适当的扩展决策以及降低成本。

那么,预处理/后处理代码呢,也就是说,你需要在预测之前和之后对数据采取的行动。它该何去何从?很难给出一个明确的答案:我会说独立于模型的动作(格式化、日志记录等)。)应该留在应用程序中,而依赖于模型的动作(特征工程)应该靠近模型以避免部署不一致。

构建预测服务

将预测代码从应用程序代码中分离出来并不一定很痛苦,您可以重用可靠的、可扩展的工具来构建预测服务。让我们来看看一些选项:

  • Scikit-learn :说到用 Python 构建 web 服务,我是 Flask 的忠实粉丝。它整洁、简单并且可伸缩性好。不用再找了。你的代码应该是这样的。
# My awesome API
from flask import Flask
import pickleapp = Flask(__name__)
model = pickle.load(open("my_awesome_model.sav", 'rb'))
...
@app.route('/predict', methods=['POST'])
def predict():
    # Grab data from the HTTP request
    ...
    model.predict(...)
    ...
  • 张量流:不需要编码!您可以使用tensor flow Serving来提供大规模预测。一旦训练好模型并将其保存为正确的格式,为预测服务所需要做的就是:
docker run -p 8500:8500 \
--mount type=bind,source=/tmp/myModel,target=/models/myModel \
-e MODEL_NAME=myModel -t tensorflow/serving &
  • Apache MXNet :同样的,Apache MXNet 提供了一个 模型服务器能够服务 MXNet 和 ONNX 模型(后者是 PyTorch、Caffe2 等支持的常用格式)。它既可以作为独立的应用程序运行,也可以在 Docker 容器中运行

两个模型服务器都预装在深度学习 AMI: 这是使用它的另一个原因。为了简单起见,您可以将您的前/后处理留在应用程序中,并调用由模型服务器部署的模型。但是,有一个警告:这些模型服务器既不实现认证也不实现节流,所以请确保不要将它们直接暴露给互联网流量。

  • 还有什么:如果你正在使用另一个环境(比如定制代码)或者非 web 架构(比如消息传递),同样的模式应该适用:构建一个可以独立部署和扩展的独立服务

(可选)容器化您的应用程序

既然你已经决定拆分你的代码,我强烈建议你利用这个机会将不同的部分打包到 Docker 容器中:一个用于训练,一个用于预测,一个(或多个)用于应用。这个阶段严格来说没有必要,但是如果你能抽出时间,我相信过早的投资是值得的。

如果你一直生活在岩石下,或者从未真正关注过容器,现在可能是赶上的时候了:)我强烈推荐运行 Docker 教程,它将教你为了我们的目的需要知道的一切。

容器使得跨不同环境(开发、测试、生产等)移动代码变得容易。)和实例。它们解决了各种依赖问题,即使您只管理少量实例,这些问题也会突然出现。随后,容器也将成为 Docker clusters 或 Amazon SageMaker 等大型解决方案的先决条件。

第二周结束

经过一个艰难的开始,事情正在好转!

  • 深度学习 AMI 提供了一个稳定的、维护良好的基础。
  • 容器帮助您移动和部署您的应用程序,比以前少了很多基础设施。
  • 预测现在存在于您的应用程序之外,使得测试、部署和扩展更加简单。
  • 如果您可以使用它们,模型服务器将为您省去编写预测服务的大部分麻烦。

不过,不要太激动。是的,我们回到了正轨,并准备好做更大的事情,但仍有大量的工作要做。那么对多个实例的伸缩预测、 高可用性管理成本等呢?当堆积如山的训练数据开始堆积时,我们该怎么办?面对现实吧,我们仅仅触及了表面。

老傻瓜!负载平衡器!自动缩放!自动化!“我听到你的哭声。哦,你是说你又急着管理基础设施了?我以为你们想要机器学习。)

这个重磅炸弹,是时候收工了。在下一篇中,我们将开始比较和挑战更大规模 ML 培训的选项:EC2vsECS/EKSvsSageMaker。一场史诗般的战斗,毫无疑问。

感谢阅读。同意吗?不同意?太好了!乐于在此讨论或在 Twitter 上讨论。

有史以来最佳电影配乐。是的,魔戒团契只排第二:)

将 Transformer-XL 扩展至 128 个 GPU

原文:https://towardsdatascience.com/scaling-transformer-xl-to-128-gpus-27afce2d23d6?source=collection_archive---------15-----------------------

本·曼雅罗斯拉夫·布拉托夫,大流士·拉姆

TL;DR: 我们在 AWS 上的 128 个 GPU 上高效地进行了 Transformer-XL 训练。该代码可在https://github.com/cybertronai/transformer-xl获得

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

We achieved almost linear throughput scaling on AWS p3dn.24xlarge instances with 8 V100–32GB each on a 100Gbps network

概观

研究语言模型的困难之一是,你通常不知道你的想法是否可行,直到你在真实世界的数据集上尝试它们。然而,在一台机器上对这样的数据集进行训练可能需要数周时间。

幸运的是,有一个简单的方法可以加速这个过程:

  1. 找一个好的单机型号
  2. 在 N 台机器上并行运行模型的 N 个副本,每一步都要同步
  3. 解决所有剩余的技术挑战

我们使用这个方法将 ImageNet 培训时间从 2 周减少到 18 分钟。您还可以应用相同的优化在 2 周内训练一个模型,这原本需要 4 年,因此您可以选择扩大您的研究范围,而不是迭代时间。

通过几分钟的训练,图像模型训练“基本上解决了”,而语言模型训练时间仍然是创新的障碍。我们的目标是看看通过在云中分布我们的培训,我们可以增加多少培训吞吐量。

对于单机模型,我们选定了 Transformer-XL 的正式实现。这种体系结构在语言建模方面取得了几项最先进的成果。作者通过发布代码和指令,使得重现他们的结果变得很容易。

一旦我们在他们的自述文件中重现了准确性,我们就迭代性能,在不影响质量的情况下获得大约 2.6 倍的吞吐量提升。

然后,我们将这个模型扩展到在多台机器上训练,使用 all-reduce 来同步梯度。分布式语言模型每一步发送的数据至少比典型的图像模型多 10 倍,因此我们使用 AWS p3dn 实例来实现 100 Gbps 的网络连接。这些实例有 32GB 的 GPU 内存,因此我们能够通过增加每个 GPU 的批处理大小来将培训效率再提高 25%。最终结果是:一个 64 GPU 版本的 small Transformer-XL 模型的训练速度比原来“慢”的 4 GPU 实现快 44 倍。我们的 Transformer-XL 具有 75M 参数(相当于论文中的 186M),在 128 GPUss 上的训练速度比在 8 GPU 上快 13.2 倍。

训练程序需要改变,以防止更大批量的数值发散,所以我们遵循谷歌在他们的 1024 TPU 缩放论文中提供的配方。我们在一个独立的回购中开源了这个优化器。

技术细节

资料组

我们主要用 Wikitext-103 进行实验,这是一个由维基百科的预标记子集组成的标准语言建模数据集。训练集在 515MB 中包含大约 1 亿个标记和 267K 个唯一单词。它使用了修改过的摩西记号化,用< UNK >符号替换 0.4%的单词来限制 vocab 的大小。Transformer-XL 代码库在训练开始时将整个数据集加载到 GPU 内存中。

为了在训练时加快速度,我们对数据集进行了预编码,并将它们放入 AWS 磁盘映像中。

基础设施

我们已经自动化了许多常见的任务,这些任务来自于分布式培训系统的原型设计,并将它们打包成一个工具 ncluster 。其理念是任何频繁的任务都应该是单一的命令行调用。一些例子:

  1. 提出一些实例,以现货价格进行测试
  2. 修复一个错误,并在 30 秒内重新启动多机实验。
  3. 登录到最近的机器,看看它在做什么
  4. 保持远程计算机上的文件夹与本地文件夹同步
  5. 登录到另一个用户的计算机来解决问题

以太网

我们尝试了各种网络配置来寻找可以优化吞吐量的设置。运行 iperf3 测试,我们可以看到机器之间的吞吐量为 93 Gbps,而 NCCL all-reduce 性能下降到大约 50 Gbps 的。AWS 网络设置的一个特点是每个网络流量被限制在大约 10 Gbps,因此我们使用多个 NCCL 环来支持多个流量。由于 NCCL 最新版本中的一个错误,我们不得不恢复到旧版本,旧版本支持多个流,但是没有有效地利用带宽。特别是,随着我们增加 GPU 的数量,传输的字节量增加了 4 倍,这是像 ring-allreduce 这样的带宽恒定算法所没有预料到的。然而,当我们让 LAMB 工作并且我们的本地批处理大小达到 32GB RAM 的饱和时,我们的网络需求下降得足够多,即使每台机器的通信负载过大,我们也没有达到带宽限制。

在某个时候,我们注意到我们最高效的带宽运行表现不佳,性能下降了 30%(见左下图)。一些调查显示,过于接近内存限制会导致 CUDA 缓存分配器反复耗尽内存,并在垃圾收集期间导致额外的同步(下图)。解决方案是通过降低批处理大小来稍微减少内存使用,这样问题就消失了。

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

Left: backwards time in ms, right: torch.cuda.memory_cached()

我们发现运行之间存在一些吞吐量差异。例如,一个不幸运的 64 GPU 运行将需要 2.5 分钟来完成 wt103 的一个纪元,而一个“幸运的”128 GPU 运行可以在 1 分钟内完成。我们认为这是由于 AWS 集群放置组是近似的:AWS 试图将放置组中的所有实例放置到本地连接的配置或“砖”上,但当这不可能时,一些实例将溢出到相邻的砖。

混合精度

依靠 16 位精度,我们可以利用 Volta TensorCores 减少内存使用,提高处理速度。我们测试了两种形式的 fp16 训练——纯 fp16 和混合精度训练。在纯 fp16 模式下,所有操作的精度都会降低。我们无法匹配纯 fp16 中的准确性数字,因为训练会很快变得不稳定。

在混合精度训练中,我们在 fp32 中保留一个权重的主副本,并在每个优化器步骤中对该主副本进行更新,然后将权重转换为 fp16,以便向前传递。这使我们能够在节省空间的同时保持精度。动态损耗缩放增加了传播的梯度信息量,同时保持了数值稳定性。为了实现这些,我们使用了 NVidia 开发的 Apex 和威震天包中的代码。

在合成实验中,我们发现张量核没有被完全激活,除非维度是 8 的倍数。

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

Figure 1: Time to multiply n x n matrices. Orange is fp32, blue is fp16. The Y axis shows log seconds averaged over three runs.

使用 tensorcores,fp16 矩阵乘法对于大的 n 几乎快 10 倍。注意,对于小的 n ,使用半精度带来的性能提升可以忽略不计。

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

Figure 2: However, when n is shifted by one, so that n is not a multiple of 8, fp16 performs equally with fp32, ie there is no performance increase at all and we simply save memory.

通过修改模型大小,我们能够显著提高速度,从最初的 1.2 倍提高到 2 倍,方法是转换为混合精度并增加批量大小。

小绵羊

LAMB optimizer 使用了这是一个简单的调整,据说它允许学习率随着工人的全局批量大小而线性增长。LAMB 将每个参数的学习率乘以权重(r1)的范数与 Adam 步骤(r2)的范数之比®。

如何解释下面的左图:Y 轴显示处理的令牌数的时间步长,第一个在顶部。X 轴是直方图桶,例如 N 个样本的值在 0 和 1、1 和 2 之间,等等。Z 轴是网络中每个参数值的直方图频率,例如 X%的图层权重落在 0 到 1 的范围内。你可以把它想象成每个时间步长的一个直方图,按时间堆叠,这样我们就可以看到直方图是如何随时间变化的。右图显示了相同的数据,但显示为面积图。颜色越深意味着越多的直方图柱在阴影区域中具有值,X 轴是时间,Y 轴是值(例如 r1 的权重的范数)。

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

大多数参数权重(r1)始终接近 0,但一些会增长和扩散,一些会变得相当大(最大 6.5 桶)

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

亚当步长规范(r2)在开始时非常大,但很快稳定在 0 到 0.5 之间。

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

上述两个影响导致信任比®促使一些参数长时间持续增长,在剪辑值为 10 时达到最大值。

在我们的测试中,我们发现 LAMB 甚至在一台全局批量为 768 的 p3dn . 24x 大型机器上也产生了影响,而 Adam 立即出现了分歧。我们还发现,我们可以完全消除学习速率计划中的预热,因为在训练开始时,梯度很大,这导致 LAMB 信任比很小,并降低了最不稳定层的学习速率。

也就是说,我们没有看到兰姆论文描述的线性缩放。他们没有公布他们的代码,甚至没有公布他们的超参数的细节,所以需要什么来使这个工作仍然有待观察。

字节对编码与自适应嵌入

Wikitext-103 的 vocab 大小为 267K,这需要很大的模型空间来表示。我们尝试切换到字节对编码(BPE),这在机器翻译中已经显示出了性能优势。我们使用 OpenAI 的 BPT 实现,因为它可以处理超出词汇表的序列。

Transformer-XL 有一个非常大的 vocab 大小(267K),所以大多数参数都在令牌嵌入中。我们能够使用 vocab 大小为 50K 的 BPE 来减少模型大小,这将我们的小模型配置从 186M 减少到 75M 参数,同时具有相同的表示能力。最初的 Transformer-XL 代码使用自适应输入和 softmax 来减少嵌入大小。

一个稍微棘手的细节是,BPE 产生的标记比 Wikitext-103 长 15%。这是意料之中的,因为 Wikitext-103 已经被标记化了(比如把“不”分成“不”。如果不是这样,BPE 可能会把“不”作为一个单独的标记来处理,而 Wikitext-103 的标记器会把它分开。在 BPE,通过将字符分割成单独的字节,将词汇表以外的单词分解成词汇表中的子单词片段,即使是 unicode 也是如此。这种行为是标记化长度增加 15%的原因。

在我们的消融研究中,我们发现,在考虑标记化长度后,以每个标记的训练损失衡量的性能几乎相同。由于模型规模更小,每秒令牌数增加了约 10%,而对于相同的批处理规模,GPU 利用率显著下降,从约 90%降至约 55%。这意味着当我们扩展到更大的模型时,我们可以保持每个 GPU 更高的批处理大小。

为了公平起见,我们还在大型模型配置上将 BPE 与自适应嵌入进行了比较:

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

为了验证困惑进行转换是 math . exp(math . log(26.25)* 1950/1699)= 42.5,所以令人印象深刻的等价(尽管上面看起来不一样)!尽管我们使用的 BPE 编码是在网络的一般样本(OpenAI 的网络文本数据集)上训练的,而不是在我们的训练集 Wikitext-103 上训练的。

这两种技术是兼容的,所以将它们结合起来可能会很有趣。也就是说,由于 BPE 如此灵活,代码也更简单,我们倾向于在未来的实验中只使用它。

学习率探测器

fast.ai part 2 中了解到这个想法后,Ben 很兴奋地看到它的工作。亚当的情况很好:

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

上图的最小值恰好就是文中用到的学习率(0.00025)!我们只需要运行几分钟就可以发现这一点,这比传统的完整超参数搜索要便宜得多,在传统的完整超参数搜索中,您将使用您打算稍后使用的单个 LR 时间表运行至少一个时期。

当应用于兰姆时,发现者明显高估了学习率。

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

灰色曲线最小损失处的学习率为 0.0263;橙色(使用重量衰减 1e-4)为 0.0435。但是当我们以 0.01 的学习率运行它时,它仍然发散。我们不得不一直降到 0.005,以获得稳定的收敛。我们认为这是因为 LAMB 导致实际的每层学习率在训练的不同时间差异很大,导致学习率查找器不在分布范围内。我们或许可以通过运行学习率查找器更长时间来解决这个问题,或者在训练中的一个检查点上。相反,我们选择做一个更传统的学习率超参数搜索。

批量缩放

在我们的许多实验中,我们发现当我们通过使用更多的 GPU 来增加全局批量时,收敛速度在短期内会下降。为了试验这种效果,我们尝试在单台机器上调度批量大小。我们发现,尽管这在短期内有所帮助,但随着我们训练时间的延长,这种好处消失了。

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

对初始收敛速度增加的一个解释是,我们在不同的批量中使用了恒定的学习速率,这导致了每个例子的学习速率更高。最后蓝色和灰色线之间的差距约为 1 亿个令牌(1 小时),因此它确实有大约 10%的帮助,即使我们没有使用整个 GPU 容量。

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

然而,如果我们保持基本学习速率不变,并应用线性学习速率缩放来调整不同批量的学习速率,则训练会发散。

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

对这些影响的更原则性的解释可能来自于梯度噪声标度。可以通过将工人批次中的梯度范数与全局批次中的梯度进行比较来估计噪声等级。在训练开始时或对于小数据集,噪声尺度较小,因此高温(η/B)训练更快。随着损耗的减少,我们需要降低温度来继续训练。

所有的维基百科

下图显示了 Wikitext-103 上大模型配置的训练损失与验证损失。你可以在下面的图表中看到,在仅仅 8 亿个令牌(1.5 小时)中,我们的验证损失停止下降,这表明我们过度拟合了数据集。

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

出于这个原因,我们很高兴尝试在 NVIDIA 的所有维基百科转储上进行培训,这比 Wikitext-103 大 25 倍。

  • 它是 12GB 的文本,所以我们不能将它全部加载到 GPU 内存中
  • 它被存储为 JSON,所以首先需要在保持文章边界的情况下将其扁平化
  • 它包含任意的唯一标记,所以需要一些技巧来限制 vocab 的大小

幸运的是,Transformer-XL 已经包含了一个用于 10 亿单词语料库的多文件数据加载器,所以只需要一点点按摩就可以让它工作了。请注意,因为标记化不同,所以不应比较损失数字。下面,我们展示了使用 64 个 GPU 在所有维基百科上以每小时约 6 亿个令牌的速度运行两次。我们发现验证损失对学习速率非常敏感。

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

在进一步的实验中,我们发现在不降低学习率的情况下,损失并没有减少。我们将继续试验学习率计划以提高性能。我很想尝试的一种方法是波动-耗散关系,它试图动态降低学习率。

结论

我们已经展示了如何在 Transformer-XL 的小型配置上,通过使用

  • AWS 100Gbps 网络
  • Pytorch 的分布式数据并行+ NCCL
  • BPE
  • 小绵羊
  • 混合精度

我们进行了数百次实验来提高收敛速度。到目前为止,我们还没有在标准基准测试中击败最先进的技术。也就是说,我们的高通量使我们能够以同样的成本更快地进行实验。我们还在用 spot 实例进行实验,这对于运行一个小时或更短时间的实验开始变得可行。

你是在做 AWS 的语言建模研究吗?试试我们的代码库,让我们知道你的想法!

承认

这项工作是以下各方共同努力的结果

Ben —数据管道、LAMB、参数搜索和调整
Darius —使用混合精确训练在单机模型上实现 2 倍加速
Yaroslav —实验基础设施、分布式训练

另外感谢 AWS 提供计算资源。

数字时代的稀缺

原文:https://towardsdatascience.com/scarcity-of-the-digital-age-e0eafed6c2bf?source=collection_archive---------32-----------------------

焦点

如何分配 21 世纪最重要的资源

稀缺。这是我们必须做出决定的原因。我们不能拥有一切。尽管菜单上摆满了令人垂涎的菜肴,但我们知道我们(通常)不可能把它们都吃光。稀缺资源的其他例子是金钱、时间和精力。在本文中,我介绍了另一种稀缺资源,它的分配可能需要您的一些关注。

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

FOCUS

创新不能欺骗我们的大脑

我们的大脑以不同的方式关注我们周围的世界*。我们可以有选择地关注一个单独的观察。这需要主动忽略其他干扰物。我们也可以对多种输入给予不同的关注。*

最近,我们正在处理比过去更多的感官输入。我们的生活变得如此简单,而我们的大脑似乎比以往任何时候都更忙碌。推荐系统确切地知道展示什么来引起我们的注意。

认知的下一步:记忆

当我们确实关注某些感官输入时,目标是 处理 这个并从中获得一些价值。这里的价值可以是娱乐性的,也可以是知识性的。尽管如此,信息过载使处理变得更加复杂。

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

Screens, notifications, we are always ‘ON’

信息过载与我们的大脑

因此,接收信息和处理信息都需要集中注意力。我们接触到的信息量越来越多,这就增加了我们关注焦点的需求。与此同时,我们不能简单地“增加”我们的关注。可以通过几种方法来提高注意力。然而,这并不容易,也不是无限的。这种不断增加的需求和固定的供给使我们专注于一种 稀缺 良好。

如何找到稀缺商品的最优配置?

在经济学中,商品的最优配置是通过设定一个单位的附加值等于一个单位的附加成本来计算的。出现的问题是,焦点的 是什么?这无法用货币单位来衡量。专注带来进步和思维清晰,它帮助你完成任务。

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

Be guided by your values through the forest of information!

从为什么开始

以西蒙·西内克为例,我们从为什么开始。‘你为什么要关注 x?’。为了衡量专注的价值,我看的是完成我所专注的任务的价值。是学习我感兴趣的东西吗?朝着我的个人或商业目标努力?

价值观,兴趣,目标…

如果这些话让你畏缩,我很抱歉。这些概念对我来说也不算什么。然而,我决定认真对待它,并参加了“个人领导力”课程。发现我的个人价值,并将这些与我的兴趣和目标联系起来,帮助我专注于对我来说重要的事情。

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

Think deeply, then act.

采取行动

无处可逃。尽管我建议花时间仔细思考你的价值观、兴趣和目标。你必须采取行动。采取行动将在两个方面帮助你进步:

  1. 你前进
  2. 你重新调整

要么你通过从经验、导师或课程中学习来提高,要么你意识到你必须做出调整。两者都向前迈进了一步。

那么,如何分配你的注意力,战胜信息过载呢?

一旦你知道你需要什么样的输入,你就可以扭转这个故事,利用信息过载。利用你对自己需求和匮乏的意识,明智地使用你的注意力。

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

The solution is in the problem

工业化信息处理

总结这篇文章,大量的数据让我们的注意力变得麻木。我们被娱乐、信息、社交信息等淹没了。所有这些输入都需要处理,而我们的认知过程无法处理。

信息处理是数据科学的全部内容。数据科学是将大量数据转化为有洞察力的信息的方法。最大的困难是让社会承认和使用数据科学。

一旦我们的社会变得有数据素养,我们就可以使用聚类和降维等技术来为我们处理信息。我们也可以建立模型来模拟势不可挡的过程。一旦这样的模型适合,我们可以调整输入来分析单一事件,而不是一次全部。

呼唤数据科学的场景

原文:https://towardsdatascience.com/scenarios-that-scream-data-science-6f2fc6b4526e?source=collection_archive---------42-----------------------

好莱坞恐怖片如何激励我们关注产生可衡量结果的问题

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

数据科学家充满好奇心、创造力和足智多谋。他们来自不同的背景,他们能够在平凡的事物中发现奇迹。他们不断地问为什么如果会怎样,并在这个过程中找到乐趣。有时这些问题会产生有趣的结果,但是有趣并不意味着有影响。如果数据科学家想要证明他们工作的价值,他们需要偶尔强调其影响。他们必须将他们的好奇心应用到能够产生可测量结果的场景中。他们必须关注迫切需要数据科学的场景。

这些场景看起来像什么?

开始识别它们的一个好方法是寻找具有以下特征的属性:

  • 系统设计固有的和任意分配的。就像网页上的推荐位置。如果有任何推荐,它们必须在页面上以某种顺序呈现。有时,这种放置是任意决定的,例如,通过分配给每个建议的随机整数对建议进行数字排序。有时,这些推荐会按字母顺序排列,以便按名称查找,即使最终用户不熟悉内容,不知道首先要查找什么名称。在这两种情况下,推荐都需要放在某个地方,但是从来没有人仔细考虑过这个地方应该放在哪里。在其他情况下,你会发现人们对物体的放置考虑了很多,但他们的决定基于过时或次优的指标,比如棒球经理只依赖球员的击球率来确定他在击球阵容中的位置,而不是使用他的上垒率。这些位置属性的其他示例可能包括您的区域销售办公室的物理位置;您的服务车队使用的维修车间的工作时间;配送中心内放置货物的过道、货架、 和箱柜;或者将专家人力资源分配给世界各地的销售团队。所有这些属性都是母系统设计所固有的(毕竟,专家员工需要被分配到某个地方),但是它们通常是基于什么是方便的,或者当系统第一次被设计时什么是已知的。
  • **易变。**有了足够的时间和金钱,你可以改变任何事情。没有什么是永恒的。理想情况下,你应该寻找那些你 可以以可接受的代价改变的属性。如果你自己不能改变它,考虑你对你的利益相关者团队的影响以及他们将会产生的成本。在车间里改变装配线的顺序,比把所有的机器打包搬到一个新的地方要便宜得多。
  • 体积充足的。如果你能在你的网页上重新排列推荐,这是很好的,但是如果没有人首先点击它们,那么你就是在对着一个空房间大喊大叫。你应该首先关注你的漏斗,发展你的获取渠道。接受有规模的问题。如果你的领域中不存在大规模的问题,你应该把认为是你的第一个问题。

你有没有注意到每年这个时候电影里的蒙面杀手会追逐尖叫的人?这些虚构的杀手无视沉默的受害者,因为娱乐价值太低。他们想要一个奇观。他们想要一场表演。他们想为刺激而优化。从恐怖电影中学习,找到尖叫的问题。寻找具有足够容量的可变属性的事物,它们作为一个更大系统的一部分被任意分配。这些场景迫切需要数据科学。他们真的在演戏。

纱线中的调度器:从概念到配置

原文:https://towardsdatascience.com/schedulers-in-yarn-concepts-to-configurations-5dd7ced6c214?source=collection_archive---------4-----------------------

先进先出,容量或公平调度,选择权在你。

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

Like this picture? See more here.

当我们开始深入大数据世界时,许多新词和缩略语开始出现——YARN 也是其中之一。Apache YARN(另一个资源协商者)是一个用于分布式计算范例的集群资源管理平台,它最常与 Hadoop 一起使用,但它也足够通用于其他平台。

在本文中,我们将不会把纱线作为一个整体来讨论,而是讨论它的一个很小但很重要的子集:调度。调度器通常处理提交给 YARN 的作业的资源分配。简而言之,例如,如果一个计算机应用程序/服务想要运行,并且需要 1GB 的 RAM 和 2 个处理器才能正常运行,那么 YARN scheduler 的工作就是根据定义的策略为该应用程序分配资源。

YARN 中有三种类型的调度器:FIFO、容量和公平。FIFO(先进先出)最容易理解,不需要任何配置。它通过将应用程序放入队列中,按照提交顺序运行应用程序。首先提交的应用程序首先获得资源,完成后,调度程序为队列中的下一个应用程序服务。然而,FIFO 不适合共享集群,因为大型应用程序将占用所有资源,并且队列将由于较低的服务率而变得更长。

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

Source: Hadoop: The Definitive Guide

图 1 展示了三个调度器之间的区别。现在很明显,在 FIFO 的情况下,一个小任务会阻塞,直到大任务完成。Capacity scheduler 为小型作业维护一个单独的队列,以便在请求启动时立即启动它们。但是,这是有代价的,因为我们正在划分群集容量,因此大型作业将需要更多时间来完成。

公平调度器对预留容量没有任何要求。它动态地将资源平衡到所有接受的作业中。当一个作业启动时(如果它是唯一正在运行的作业),它将获得群集的所有资源。当第二个作业启动时,它会在一些容器(容器是固定数量的 RAM 和 CPU)空闲时立即获得资源。小作业完成后,调度程序将资源分配给大作业。这消除了 FIFO 和容量调度程序中的两个缺点,即总体效果是以高集群利用率及时完成小型作业。

现在让我们来看看一些配置。我们在沙盒环境中使用 HDP 2.4(对任何 HDP 2.x 都有效)进行了这些配置。然而,默认情况下,Hortonworks 使用容量调度程序;Cloudera 默认是 Fair scheduler。合并后,他们仍然使用相同的惯例,保持业务如常,但这可能会在未来发生变化。

让我们假设您想要为您部门的需求配置能力计划程序。我们可以从将作业分为三类开始:默认、工作流和首选项。提交给调度程序的普通临时作业、摄取和 ETL 流程的工作流以及需要立即关注的任何作业的首选项的默认值。尽管 Hortonworks 默认的是容量调度器,但是您仍然可以通过使用一种叫做“”的东西来模仿公平调度的行为。

首先,登录 Ambari web 控制台,从右上角的虚线菜单中选择纱线队列管理器。

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

在这里,您可以看到默认设置:只有一个队列(根)和一个子队列(默认),当前分配了 100 %的资源。

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

接下来,点击 添加队列 ,再添加两个作业队列。根据需要,您可以将资源分配给队列。

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

在这种情况下,让我们将 20%分配给默认值,它可以增加到 40 %,最需要资源的工作流可以获得 60–80%的资源,而 20%的首选项可以增加到 80 %,总计为 100%。

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

这就是我们所说的具有队列弹性的能力调度,例如,如果有人在优先队列中提交一个作业,它肯定会获得 20%的资源,而如果没有未完成的作业,它最多可以获得 80%的资源。保存您的更改以使其在操作菜单中生效。

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

以下是 Hortonworks 沙盒中容量调度程序的一些基本队列配置。

在结束之前,我将简单解释一下从采访角度来看很重要的先发制人的概念。如果一个队列占用的容器多于其合理的资源份额,而另一个作业正在等待其合理份额下的资源,抢占允许它从第一个队列中删除容器,并将其分配给第二个队列。然而,这是以降低集群效率为代价的。可以从yarn.scheduler.fair.preemption 属性启用抢占,并将其设置为True

我想链接一下可以帮助理解纱线调度概念的参考资料。

1。 Hadoop:权威指南

2。 用 Apache Ambari 配置纱线产能调度器

3。 纱—产能调度

4。 YARN 和 MapReduce 调度器

推特上的一个关注也许!

学术网络分析(SNA)

原文:https://towardsdatascience.com/scholarly-network-analysis-22cd352c0f86?source=collection_archive---------15-----------------------

深入分析

科研网络研究导论

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

Photo by Alfons Morales on Unsplash

R 科学和研究的飞速发展导致每天产生和收集大量的数字学术数据。这些学术数据可以是科学出版物、书籍、教材和许多其他学术信息源的形式。随着时间的推移,这些信息来源开始通过引用、合著在它们之间建立复杂的关系,并导致形成大型学术网络,这些网络变得越来越难以破解。

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

Figure 1: An Example of Heterogeneous Scholarly Network¹³

在这种情况下,学术网络分析(SNA)是对这一科学研究网络的研究,旨在发现有意义的见解,以实施数据驱动的研究决策。

学术网络中的重要分析点

考虑图 2 所示的原始图上的 SNA,至少有七个关注点:

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

Figure 2: Overview of Scholarly Network Analysis on raw graphs¹⁴

  1. 在论文上合作的作者(合著网络)

合著网络分析可用于发现作者之间的科学合作,描绘作者的个体科学想法如何通过合作聚集在一起,以引起科学发现的爆炸。

2.相互引用的文档(引用网络)

3。被共同引用的文献(共引网络)

引用和共引网络分析用于发现被引用论文和引用这些论文的一组论文之间的关系。这在作为网络分析的基本任务之一的社区检测中证明是有用的。

4.以类似方式引用其他文件的文件(书目耦合)

书目耦合还包括引文分析,以查找在 bibliography⁴.中引用第三次引用作品的文献

5.文档集中的内容聚类(主题网络)

从底层网络中提取主题有助于发现当前的研究领域及其随时间的演变。

6.一起出现的词群(共词)

共词 analysis⁵通过发现关键词的共现来帮助识别特定研究领域中主题之间的关系。

7.类型和关系的多样性(异构网络)

异构网络 analysis⁶,⁷涉及两个或多个耦合网络的研究。例如,通过耦合合著和引文网络,发现引文随时间的演变或未来的引文。

那么,如何从学术网络分析开始呢?

基于分而治之的方法,SNA 的第一个起点是从大的出版网络中缩小范围并创建一个可管理的学术网络图。该学术图表可以基于从学术数据库收集的信息,以我们当前的研究领域(如数据库、数据科学、机器人、能源)为重点创建,可用的学术图表如 DBLP⁸作为计算机科学的书目数据库,微软学术 Graph⁹.这进一步需要一个公式化的设计方法来策划最终的学术图表进行分析。可以考虑一个起点,其可以包括从基础研究论文节点开始,通过爬行相关节点来形成学术图。

一旦我们创建了最终的图表,下一步包括制定要回答的研究问题,并相应地设计分析的切入点。根据数据所需的信息,可以有不同的入口点。其中一些包括发现网络中的潜在主题,基于引用计数或作者联系信息的分析。

图 3 描绘了在名为 Codd 的世界的数据库发布网络的子集上执行的一个这样的 SNA 的概述,其中学术图从 Edgar Codd 关于关系数据库⁰ 的基础论文开始创建,并利用入口点*来发现网络中的底层主题(主题建模)*以基于主题及其在数据库社区发布图中的演变来驱动进一步的分析。此外,利用不同切入点的一些其他 SNA 研究实例包括分析引用关系以评估给定论文或作者的影响,或研究合著者行为以确定科学界分布。

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

Figure 3: Scholarly Network Analysis on the heterogeneous network named as Codd’s World¹⁴

本文作为学术网络分析主题的介绍性文章,分享了科学 SNA 研究工作出版物 Codd 的世界:数据库社区出版物 Graph 中的主题及其演变,作者为 Rutuja Shivraj Pawar、Sepideh Sobhgol、Gabriel Campero Durand、Marcus Pinnecke、David Broneske 和 Gunter Saake,德国马格德堡奥托-冯葛利克大学

参考文献

[1]夏风,王巍,特肖梅格尔萨贝克勒和刘欢。大学术数据:一项调查。IEEE 大数据汇刊,3(1):18–35,2017。

[2]黄子豪和毛。用于理解学术合作和单个研究人员的知识领域的合著网络的分析和可视化。计算机图形学,成像和可视化,2006 年国际会议,18-23 页。IEEE,2006 年

[3]萨特里奥·巴斯库洛·尤多阿特莫霍和穆罕默德·李北·萨穆尔。基于 linkrank 算法的 dblp 数据样本集引文网络社区发现。Procedia 计算机科学,124:29–37,2017。

[4]凯文·博亚克和理查德·克莱文斯。共引分析、书目耦合和直接引用:哪种引用方法最准确地代表了研究前沿?

[5]秦和。透过共词分析的知识发现》1999

[6]严尔嘉和丁樱。学术网络分析。《社会网络分析和挖掘百科全书》,第 1643-1651 页。斯普林格,2014。

[7]严尔嘉和丁樱。学术网络的相似性:书目耦合网络、引用网络、共同引用网络、主题网络、共同作者网络和共同词汇网络如何相互联系。美国信息科学与技术学会杂志,63(7):1313–1326,2012

8 迈克尔·莱伊。dblp 计算机科学书目:进化,研究问题,观点。在字符串处理和信息检索国际研讨会上,第 1-10 页。斯普林格,2002 年。

[9]阿纳·辛哈、、、达林·艾德、许宝俊和王宽山。microsoft 学术服务(mas)和应用程序概述。《第 24 届万维网国际会议论文集》,第 243-246 页。美国计算机学会,2015。

[10]埃德加·F·科德。大型共享数据库的数据关系模型。美国计算机学会通讯,13(6):377–387,1970 年。

[11]马克·纽曼.网络.牛津大学出版社,2018 年。

[12],,,,,张,,等。挖掘学术大数据中的顾问-被顾问关系:一种深度学习方法。第 16 届 ACM/IEEE-CS 数字图书馆联合会议论文集,第 209-210 页。ACM,2016。

[13]严,尔嘉,,和。" P-Rank:衡量异质学术网络声望的指标."贾斯特 62(2011):467–477。

[14] Pawar,R.S .,Sobhgol,s .,Durand,G.C .,Pinnecke,m .,Broneske,d .和 Saake,g .,2019 年。Codd 的世界:数据库社区出版图中的主题及其演变。在 Grundlagen von Datenbanken (第 74–81 页)。

非科幻科学

原文:https://towardsdatascience.com/science-non-fiction-e50b589aa435?source=collection_archive---------24-----------------------

人工智能将改变你的生活。问题是,没有人真正知道怎么做。

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

In this article we will talk about artificial intelligence (hereinafter referred to as AI), and about the risks and consequences that could come from its development. You may not be interested on the subject a tiny bit or be just fed up with headlines about it. But the thing is, AI will affect your life sooner or later, and most likely in a profound way. We’ll try to give you here a good take on the topic, so that you at least know what to expect. As always, if you want to go deeper, follow the links throughout the text to access other articles and videos with much more info.

Let’s start with a quote from I.J. Good, an English mathematician who worked with the legendary Alan Turing in the mid-twentieth century in the design of the first modern computers: “The first ultra intelligent machine is the last invention that man need ever make, provided that the machine is docile enough to tell us how to keep it under control. It is curious that this point is made so seldom outside of science fiction. It is sometimes worthwhile to take science fiction seriously”.

Maybe so. The blogger Tim Urban thinks otherwise: he says that when we hear about AI we think about things like Star Wars or Terminator, and that makes us associate the term with fiction, making us not take it too seriously.

Tim is right. When you start reading in depth about AI, the first reaction is one of absolute surprise, because one realizes that the general level of knowledge and concern about this issue is so very far from where it should be. The rapid development of Artificial Intelligence could be described as an 8-axle trailer truck that is hurdling towards us at 300 mph. So how come we are looking the other way?

It seems a relevant question, don’t you think? It doesn’t seem normal that we are arguing all the time over some nonsense that always seems to be a matter of life and death, while issues that may not be a matter of life or death but of immortality or extinction are considered by most as stories for nerds. This may seem like an exaggeration, but actually, it isn’t.

We’ll go over that question in the second part of Science Non-Fiction, which will be posted next. This first part has the goal of describing for you the truck and its speed; enough in detail to maybe erase that smile you have right now.

The topic of AI is actually a very broad one. Yes, AI is behind you getting all those advertisements for hotels in London after doing a search for flights over the internet; and maybe you’ve also read about AI​​ beating every human at chess and at that Chinese board game (it’s called Go). Nowadays many AI tools and applications are being developed across many fields with sweeping advances. Some of that stuff could actually deliver great outcomes for us, such as the ability to diagnose diseases much more accurately, or the breaking of communication barriers with natural language processing. In the case of the financial industry, which is our main concern at Goonder, AI can help algorithms not only to be able to better predict market fluctuations, but also to be able to learn from the individual evolution of each investor, allowing us to offer a much more personalized service. But some other stuff already in development can be really scary, such as the police use of facial recognition (especially when there are clear signs of gender and skin type biased systems), lethal autonomous weapons or the use in China of social credits for citizen behavior.

Beyond all these developments and the debate over the possible implications, the general perception today for ordinary mortals seems to be that if one of these AI tools has not yet taken my job, so far so good.

Looking into the future, things could get seriously unsettling if we get to the next step, which is not a step but a huge leap, one that would make Neil Armstrong look like a child playing hopscotch. It would be to get to AGI, or Artificial General Intelligence: a system that would be as efficient as a human not just in concrete tasks, but in every task. Put another way, a system that has the same level of intelligence as we do. From today’s perspective it may seem that we are very far from reaching that point. But are we?

The classic way to measure progress in the field of AI is the famous Turing test. A machine will have passed the test when the evaluator considers that its answers are indistinguishable from those of a human. 5 or 10 years ago this seemed a distant goal. Nowadays you talk to Siri or Alexa and yeah, if you ask them about the meaning of life they’ll probably answer some nonsense, but you may have noticed that they give fewer and fewer nonsense answers. According to 2016 measurements, Google’s AI was approaching the intelligence level of a 6-year-old child. And like children, these things grow fast. Catching up with us seems to be getting more likely and less far away.

In terms of technological evolution, reaching AGI basically depends on achieving significant increases in process and learning capacities. Regarding the first one, the process capacity to have an AGI system actually already exists; we just have to make it more efficient and cheaper. At the current pace, it would be a matter of a few years. The second increase is the most difficult: how do you improve the learning capacity of a system? Contrary to what one could intuitively think, it seems that the fastest way is not to feed the system with all available knowledge, but to program it so that it can learn on its own, based on trial and error. In fact, one of the strategies that is making more progress today is programming the systems using neural networks and what is called deep reinforcement learning, so they learn and improve alone.

Here’s an illustrative example. Do you remember Deep Blue, the system created by IBM that in 1997 beat the then world chess champion, Gary Kasparov? Deep Blue was a system that was fed with all the knowledge accumulated in chess, millions of games. With that and raw process capacity, it was able to choose better strategies than the best human and thus defeat him. Since then, systems created under that approach have routinely won over any chess grandmaster, and since a couple of years they also beat us at go, an even more complex and abstract game. However, the artificial intelligence company DeepMind (owned by Google) has achieved a huge evolutionary breakthrough this last year with AlphaZero, a system that they fed with just the rules of three complex board games: chess, shogi, and go. The idea, and hence the name, is that the system learned to play all three games from scratch using neural networks and deep reinforcement learning, and without it being contaminated with any prior human knowledge. Thus, it began playing ultra-fast games against itself, and it took the thing a few hours to reach the most advanced strategies of the grandmasters, and a little while more to discover absolutely unthinkable strategies for us pitiful humans. Of course, AlphaZero is now the unofficial world champion of all three disciplines. And even when playing with a hand tied behind its back, it’s a walk in the park: of 100 games of go, and with the tenth of chips and time to move, AlphaZero crushed 100–0 the previous champion, its older brother AlphaGo (which was the system that in 2016 had defeated the last human champion, Lee Sedol, as you can see in this documentary).

So, summarizing a bit: for a system to reach a level of human intelligence, the problem of process capacity will be solved in the medium term, and solving the problem of learning ability is achieving huge qualitative leaps with the use of neural networks and machine deep learning techniques.

Now before we go on with the description of the truck, a word about the growing speed in which it’s coming. There is a concept that may be not that difficult to understand, but which is in fact really hard to visualize: exponential growth. In this case, we can see that the more a system learns and improves, the better it will be at learning and improving afterwards, since each improvement cycle will allow for better and faster increases in capacity, eventually leading to exponential growth. But this concept is at the same time very difficult to grasp, since us humans are designed to think in linear, not exponential terms. Tim Urban explains it very well with the help of really funny and illustrative graphics in his blog Wait but why, where he has published two posts about the AI revolution: The road to superintelligence and Immortality or extinction (if you’re interested in AI, reading these two posts is highly recommended: they’re quite exhaustive and very entertaining). At the end of his first post, Tim presents us with the following conclusion: for a system that is learning exponentially, getting to AGI state will be just something that happened for a second, and was left behind the next one. This is exactly what AlphaZero did with the game strategies that humans had been able to come up with.

Reached this point, let’s introduce two new concepts: Singularity and ASI. Both concepts are based on the ability of technology to generate that exponential growth that will go faster and faster and over which we will have less and less control. The singularity would be that moment in which a system’s capacity for recurrent self-improvement reaches such a degree that an intelligence explosion happens. ASI means Artificial Superintelligence, or the system that would emerge from that intelligence explosion. ASI is something that could leave humans so far behind that we would have about the same capacity for understanding and controlling it as that of an ant colony on the generation of atomic energy. (Actually, much smaller. See the stairs graph in Tim Urban’s second post).

So that’s the truck.

Before going over possible consequences, maybe it’s worth stopping here a moment to consider what you just read. You’re thinking you’ve seen this before, aren’t you? Skynet in Terminator, Hal 9000 in 2001, Agent Smith in The Matrix… Science fiction. Right?

Actually, it’s a logical path, one that many experts think that is going from possible to probable. It has even been predicted by one of the pioneers of computing. Do you remember that quote we started with? Alright, so you never heard of that I.J. Good. Well, here are more quotes from people you should know. Stephen Hawking: “The development of full artificial intelligence could spell the end of the human race.” Bill Gates: “I don’t understand why some people are not concerned.” Elon Musk: “We are summoning the demon.”

Okay, maybe lately Elon Musk is not the most credible source of news in the world. So, what do the experts think? Surveys of those leading the AI field from 2011, 2013 and 2018 show some powerful data. For starters, the number of those who consider that all this remains pure science fiction and that a system will never reach human intelligence, depending on the survey you look at, vary between 2 and 20%. That is, the vast majority of experts disagree on the when, not in the if. Regarding the when, the median in the experts’ answers is that we would have an AGI system between 2040 and 2060, and that an ASI would arrive afterwards, either very quickly, or at the most 30 years later.

Put another way: if you are between 20 and 40 years old, there is a 50% chance that your children will be run over by the truck. And your grandchildren’s odds look very ugly.

Or very beautiful. Because maybe when the time comes the truck instead of running over us, picks us up and take us to an instantaneous future in which almost all our limitations will disappear, starting with death (and maybe even taxes.)

It’s now time to introduce you to Ray Kurzweil, or as they call him in a documentary, “The Transcendent Man”. Scientist, inventor, writer, musician, entrepreneur, creator of the Singularity University, lately director of engineering at Google. A guy that even those who think he is nuts admit that he is a genius. 21 honoris causa doctorates, an off-the-chart IQ and a quite impressive fulfilled predictions track record. He’s the equivalent of a rock superstar for technologists. You can see him in action in TED talks, read profiles on him by The New Yorker or Rolling Stone, or interviews with him in Playboy or The Guardian.

Ray is one of the optimists. He believes that everything will happen for the better, and that it will happen much faster than his colleagues believe: he assures that a machine will pass the Turing test in 2029 and that the Singularity will happen by 2045. He also believes that exponential growth of knowledge across several fields will end up making us immortal. He predicts that the whole process will be controlled, and that very soon there will be breakthroughs that will overcome the classical barriers of biology, turning us effectively into a new species, with a human base and artificial evolutions. Ray is taking great care of himself because he’s not that young anymore and of course he’d like to get to live forever. In fact, just in case he doesn’t make it, his plan B is to freeze his brain. He also intends to make his father alive again using DNA.

There’s that smile again. Who could blame you? But leave aside Ray’s ability to generate headlines and think about it a bit, and you’ll see that it’s not such a deranged scenario. We know that we are not biologically designed for today’s living conditions, but for a time when we were hunter-gatherers, just one more animal trying to survive and transmit our genes. Biological evolution, which uses roughly the same tools as AlphaZero, (a trial-and-error system with rewards for the most successful strategies), works in temporary terms that have nothing to do with the artificial capacity for improvement that we have achieved. Therefore, if we aspire to get on the truck and not to be run over, any future evolution minimally appreciable, and needless to say if it is so radical, must necessarily have a technological base.

Let’s try with a more visual example: Who runs faster, Usain Bolt or your grandmother? Ok. Yes. Usain Bolt. But what if we give your grandmother a Ferrari? She’ll probably have some trouble getting to handle the gears, she might crash into a tree or run over some pedestrians… but hypothetically it’s clear that she’ll run much faster than Usain Bolt, right? Change that Ferrari for exponential advances in AI and biotechnology, and suddenly it’s not that crazy to foresee all those things that Ray imagines will be common for future generations. Direct access with the mind to all the data in the cloud. Daily backups of our brain: memories, sensations, thoughts, emotions. Possibility of using nanotechnology and augmented reality to inhabit other bodies, other realities. Nanobots circulating through our bloodstream and our brain, repairing and improving all biological systems, giving us physical and mental abilities that can only be described as post-human. Building genetic and enhanced copies of ourselves and of our parents, in case we don’t make it to the party. And immortality.

Of course to Ray, who is more than 70 years old, all this seems like a great prospect. For Charlie Brooker, who is in his forties, it inspired Black Mirror.

Charlie is a storyteller. The dystopias he imagines in Black Mirror stem from a dark vision of the human condition mixed with technological developments that don’t seem so distant. And the most worrying thing is not that these projections seem so creepy; it’s that these are scenarios in which the truck doesn’t run over us. Therefore, they are optimistic scenarios.

Because another possible scenario is that the ASI system that comes after the singularity may have the same interest in the survival of humans as any human would in the survival of mosquitoes, except maybe for Greenpeace members. And yet another scenario is that the ASI system has strategic goals incompatible with human existence, as in Nick Bostrom’s famous example of the paperclip maximizer.

Nick Bostrom is not like Ray Kurzweil at all. Maybe they have similar IQs and areas of interest, but that’s about it. Nick is definitely no rock star. Philosopher, thinker, author of more than 200 papers, he’s an expert in ethics and technology, and the director of the Future of Humanity Institute at Oxford University. If you have the time and you like the topic, you should read his book Superintelligence. If you don’t have that much time, you might enjoy reading his profile in The New Yorker and watching the talk he gave at Google. And if you have no time at all, maybe you can watch this TED talk for a quick summary.

Nick sees the arrival of the ASI as an existential risk for the human species, the most likely candidate to be the black ball that we take out of the bag of new technologies and that means our doom. He wonders if it is not a Darwinian mistake to create something that is smarter than us. He concludes that, whether or not we end up creating a superintelligent system, it would be a good idea to start laying some solid foundations so that the outcome is as benevolent as possible for humanity. Sounds pretty logical, right?

Because if it happens, regardless of when it happens, the truth is that no one knows for sure what would come next. Whether it will be good or bad for the species, or very good for a few and very bad for the majority. Or maybe it won’t be better or worse, but very different, like Black Mirror. Those surveys that we talked about earlier show much more diverse results on this point. In the 2013 survey, experts who thought that the result would be good or very good for humanity added up to 52%, and those who thought it would be bad or very bad, 31%. So, when Nick was asked at the end of that talk he gave at Google if he thought we were going to make it, he answered the question laterally. “Yeah, probably less than 50% risk of doom, I don’t know what the number is”, he said. And then he added, “But the more important question I guess is what is the best way to push it down.”

This may be the most important issue that we have to face in the coming years.

googler2019 年

脸书广告的科学方法

原文:https://towardsdatascience.com/scientific-approach-to-facebook-ads-661ce129bf38?source=collection_archive---------17-----------------------

需要多少次浏览才能确定新创意不起作用,设计师们又一次不得不为他们的晚餐而歌唱?有多少浏览网站的用户意识到弹出购买按钮是个坏主意?

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

unsplash.com

这篇文章是为谁写的

从事广告活动和登录页面有效性优化的专家总是发现他们自己在问完全相同或相似的问题。对于那些用于测试新渠道和假设的计划预算也是如此。在寻找答案的时候,你可以依靠直觉,但是最好回到概率论的基础上,让你计算出所需的顺序。

引入术语

直觉表明,测试时间越长(在其他条件相同的情况下),结果就越精确。但是更精确是什么意思,什么时候会变得足够精确?为了回答这些问题,让我们通过广告浏览量和点击量来介绍一些概率论术语。

让一个随机事件成为我们广告的单一视图。这种事件有两种结果:用户要么点击具有 CTR 概率的广告,要么不点击具有 100% CTR 概率的广告。

一个随机的点击数被记录在一系列默认长度的视图中,这个数字就是我们的随机值。因为,如果我们再次用同样数量的视图重复这个实验,我们会得到不同数量的点击。我们永远也不能提前说出准确的点击次数,但我们可以通过计算一系列视图的点击期望来推测。

我们只需要将一次浏览中的点击概率,即我们的点击率,乘以适当的浏览次数。例如,当点击率为 1%时,250 次浏览的点击率期望值为 2.5。按照纯粹的逻辑,我们理解一半的用户(可能是美人鱼?)不会点击我们的广告,因此在广告管理器中,我们会看到大约两三次点击。

但是,如果我们继续测试我们的 250 个视图系列,并记录每个系列的点击数,我们将得到一个接近预期的平均值。这里,这种实验的次数越多,平均值就越接近预期值。这是对符合我们直觉的概率论大数定律的一种相当轻率的解释。

导致需要计算置信区间

你可能会问:“很明显,精确是指接近期望(即,一个更小的变量范围),但我们为什么需要这个?”

在广告管理器中,如果有一千次点击,我们会得到十次点击,系统会自豪地说点击率是 1%。高兴得要命,我们会去旅行,但回来后我们会发现,在第一次数千次浏览后,点击率只有 0.6%。真是一团糟!但是,当然,我们既没有考虑到观众,也没有考虑到创作倦怠。问题是,你的第一千次浏览比平均水平要好,经理显示的点击率与实际相差甚远。但是随着一系列更长的观点,它接近了它的真正价值。单独使用 CTR 很方便,因为它不依赖于视图的数量。它的精确程度直接取决于点击次数的精确程度。

作为一个真正的 CTR,我会考虑我们在文章开头定义随机事件时提到的概率。因为该值被设置为无穷大,并且广告管理器中的 CTR 倾向于在延长一系列视图时达到该值,因为真实的 CTR 被用于计算点击期望。

预测你创意的未来效果需要了解真实的 CTR。但这是不可能的(除非你的预算是无穷无尽的),因此你只能通过钥匙孔进行窥探。用数学术语来说,真实 CTR 的潜在范围可以根据我们用测试预算购买的数据来粗略估计。现在是公式登场的时候了。

关于泊松分布

一个意想不到的免责声明:不要把这篇文章当作精确计算的正式指南。它的科学特性只是用来粗略地计算。

泊松分布可以帮助定义在 n 个视图上获得 m 次点击的概率,

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

其中 p 是真实的 CTR,λ是从真实的 CTR 和 n 个视图中得出的,是对这种大小的采样的点击期望。不幸的是,这只适用于 10 阶的λ,这会降低所有进一步计算的精度。

但是不要害怕公式,因为我们只需要它的图形

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

该图显示了 n 次浏览的真实点击率转化为随机点击数的概率。您可能会看到概率峰值的形式,以及在 n 个视图上的点击期望及其在峰值上的近似值。在图表的底部(或峰值的根部),当点击数量远离预期时,我们的一系列视图的实现可能性较小。因此,确定一系列视图的点击数的可能值的范围意味着确定我们的峰值有多宽。

随机值相对于其期望值的程度范围称为离差,其根是标准偏差(图上的 s ),实际上决定了峰宽。

最终,为了进行计算,需要弄清楚实现一系列视图的概率是在顶部还是在底部。换句话说,某个样本的点击量不会超过期望值的标准差的概率是多少?而恰好是 70%左右。

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

计算置信区间

有问题的音程,

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

被称为置信水平为 70%的置信区间。我们将进一步关注它。

我们非常幸运,因为泊松分布的离差等于它的期望,即等于 λ,以及标准偏差值——等于λ的根。因此,70%置信区间如下

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

假设我们广告的真实点击率是 1%,那么 900 次点击的预期点击率就是 9。因此,我们有

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

这意味着,在 900 次浏览后,70%的情况下,我们将获得 6 到 12 次点击(9 次仍然是最有可能的)。将这些值除以浏览量,我们很容易猜到广告经理显示的点击率在 0.67%到 1.33%之间。在 ads 管理器中,这个范围可以称为 CTR 的置信区间。

因此,如果你对点击率超过 1%感到满意,而你的前 900 次浏览没有幸运地获得 0.67%的点击率,那么这个在未来会表现良好的广告可能会被不必要的删除。在这种情况下,测试期应该被延长。

但是等等,你很可能会问为什么我们要预测真实的点击率,并在此基础上做出结论,如果事实上任务恰恰相反——在广告管理器的点击率基础上定义潜在的真实点击率。你是对的。从技术上来说,这样的计算应该更复杂,但最终它会在上述相同的领域结束。所以,不要害怕表面上的困难。现在让我们对提到的每件事做一个简短的总结。

间歇结论

理解误差比比理解置信区间更容易,置信区间中的比率误差是期望偏差与正确期望的比率。在我们的情况下,我们有

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

除了与我们没有包括在 70%置信区间中的 30%的情况相关的误差之外,前面提到的例子的误差率不小于 33%。在这 30%中,我们可以得到不包含在置信区间中的任意随机点击数。

那么,我们得出的结论是什么?例如,我们可以得出结论测试的准确性(即比率误差的小)不取决于累积的随机事件的数量,而是取决于成功的数量,或者不取决于查看的数量,而是取决于点击的数量。

这就是为什么没有共同的边界来决定进行测试的正确程度。如果除了从测试运行依赖的持续时间来谈论登录页面,我们需要提到 CTR 依赖和转换依赖。但是你必须随时准备好自己定义每个特定案例的边界。

就固定的真实 CTR 值而言,精确度随着视图数量的增加而增加。让我回忆一下,点击期望值是通过将固定的真实点击率值乘以点击次数来确定的,并向您显示,当点击期望值增加时,错误率在下降

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

此外,您可能会注意到下降的以下规律性— **我们测试的时间越长,准确性增长得越慢,**意味着测试应该按时结束。否则,时间和预算就没有得到有效的利用。

但是准时是什么意思呢?要求的准确度是多少?那要由你来决定。唯一可以确定的是,在点击 25-30 次之后,准确率会以一种非常缓慢的速度增长。

一个逆向任务

让我们回到计算置信区间,并最终弄清楚如何在广告管理器中粗略地绘制潜在的真实点击率。

我们已经确定,在广告管理器中,n 个视图的真实 CTR 有 70%的概率被实现为相关置信区间内的一个值,这意味着管理器中的每个 CTR 是各种真实 CTR 的过多置信区间的一部分。我们只需要确定哪些最小和最大真实点击率可以在我们的经理身上实现(具有给定的准确度)。长话短说,我们需要找到这样的真实点击率,它们与经理的点击率在置信区间的边界上相对应。

因此,看看广告经理,在那里看到一定的点击率,我们将最终回答关于我们广告的潜在真实点击率的问题。答案将是真实 CTR 的范围

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

让我们通过将上面提到的图片翻译成点击期望的语言来找出 CTR1 和 CTR2,回忆置信区间的宽度。因此,λ是广告管理器中的点击次数,而带有数字的λs 对应于 CTR1 和 CTR2

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

等式的左边部分对应于左置信区间的右边界。它的右边部分是右音程的左边界。他们的交汇点正好对应我们的点击量。

这是方程式的解

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

可能看起来很恶心。但是如果管理器中的点击次数明显大于 1,就可以丢弃它,这样解决方案就相当不错了。因此,点击次数的计算置信区间为

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

看起来是不是很眼熟?所以,结果是我们不需要解任何方程,因为在精确度上有一点点误差,我们已经把逆向任务转换成了直接任务。

例证

好吧,让我们用一个恰当的例子来说明上述的方法。

  1. 我们在管理器中看到每 1000 次点击有 25 次。系统会为我们计算点击率。也就是 2.5%。
  2. 现在我们计算点击次数的平方根。因此,我们得到了我们的标准差,即置信区间的宽度。对我们来说,是 5。
  3. 然后我们计算点击次数的置信区间(25–5;25+5)= (20;30)
  4. 然后我们计算真实 CTR 的相关区间。我们只需将之前计算的值除以点击次数(并计算百分比)(2%;3%)
  5. 利润

顺便说一下,评估测试准确度的程度需要误差比,误差比是通过将标准偏差除以点击次数来计算的

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

基准表

为了方便起见,我会在下面放一个表格,说明上面提到的所有内容,并展示广告测试所需的浏览次数(一组 25 次点击,之后准确度会慢慢增加),具体取决于其 CTR

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

AB 测试

如果在你看来,70%的置信区间加上 20%的误差率给出了相当不准确的结果,欢迎你使用宽度不是两倍而是四倍于标准差的 95%的置信区间。在这种情况下,我们需要用点击次数的根来代替它的双倍值。所以,20%的相对准确度将在 100 次点击时达到。

上述推理很可能为测试持续时间设置一个理论下限。对于较短的测试,样品将没有代表性。然而,我们很少对适当测试的准确性感兴趣,因为我们通常需要将我们的结果与默认结果进行比较,例如,在媒体计划中详细说明或通过其他(已经测试过的)广告获得的结果,或者与 A/B 测试中第二个变量的结果进行比较。

就第一种情况而言,如果测试结果即使在置信区间的上界也不令人满意,测试可以提前完成。例如,如果我们有 9 次点击率为 0.9%的点击,而真实点击率的 70%范围是(0.6%;1.2%)而我们需要不低于 2%的点击率,等待 25 次点击是没有用的。达到这种结果的机会非常小,因为即使是 95%的真实 CTR 范围也只有(0.3%;1.5%).

在 A/B 测试的情况下,有两个图形有自己的宽度。测试的准确度取决于它们重叠的程度(指数随时间变化)。你可能会问为什么。事情是这样的,在某个特定的时刻,我们变量的每一个结果看起来都像图表上的一条垂直线(或者水平轴上的一个点)。如果这种重叠很大,在某个时刻,左边的结果可能实际上属于右边的图,而右边的结果属于左边的图。如果我们提前完成测试,我们将选择一条死路,尽管在那一刻它似乎是一条胜利之路。左图上的测试准确度与右图相比还有很大的差距。

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

然而,电子邮件营销或 UX/XI 专家可以在他们专业工具的界面上计算 A/B 测试的程度,或者至少使用在线服务。因此,与广告经理打交道的人以及因此进行大量 A/B 测试的人可以使用下面的建议。

计算图表的准确交叉点是一项具有挑战性的任务,因此我们只能根据真实 CTR 范围的交叉点做出决定。在这种情况下,最好使用 95%的间隔。如果最初相关区间彼此远离,我们可以提前完成测试。但是,如果它们重叠,我们应该继续进行测试,直到缺少重叠的时刻或达到代表性抽样的时刻。代表性的程度取决于重叠的程度。如果 90%的区间重叠,而 70%的区间不重叠,那么每个变量点击 30 次就足够了。但是,如果 70%的区间也重叠,这意味着各种变体的有效程度彼此非常接近,那么没有一百次点击就不行。

结案陈词

最后,我要提醒你的是,上面提到的一切都可能在漏斗的任何阶段使用,不仅适用于视图(条目)和点击,也适用于从销售线索到购买的转化。唯一的保留是指泊松分布,因为它只对低概率的随机值有效。因此,我们将无法使用我们的方法来实现从填充铅表格的一行到另一行的高转换系数。

很有可能将漏斗作为一个整体来分析,即从广告点击到整个漏斗的最终转化的转化准确率,尽管中间有过多的微转化。因此,我们只需要将我们的随机事件称为广告点击,将结果称为最终的转化或缺乏转化。这最终有助于我们定义(我不能说计算)必要的方法,根据随机事件的相同 25-30 个成功结果,通过媒体规划进行假设检验。

sci kit-学习决策树解释

原文:https://towardsdatascience.com/scikit-learn-decision-trees-explained-803f3812290d?source=collection_archive---------0-----------------------

使用决策树进行训练、可视化和预测

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

Photo by Lukasz Szmigiel on Unsplash

D 决策树是随机森林中最重要的元素。它们能够拟合复杂的数据集,同时允许用户看到决策是如何做出的。当我在网上搜索的时候,我找不到一篇清晰的文章可以很容易地描述它们,所以我在这里写下我到目前为止学到的东西。值得注意的是,一个单独的决策树不是一个很好的预测器;然而,通过创建它们的集合(森林)并收集它们的预测,可以获得最强大的机器学习工具之一——所谓的随机森林。

Make sure you have installed pandas and scikit-learn on your machine. If you haven't, you can learn how to do so [here](https://medium.com/i-want-to-be-the-very-best/installing-keras-tensorflow-using-anaconda-for-machine-learning-44ab28ff39cb).

Scikit 学习决策树

让我们从使用 iris 花卉数据 se t 创建决策树开始。iris 数据集包含四个特征、三类花卉和 150 个样本。

**功能:**萼片长(厘米)、萼片宽(厘米)、花瓣长(厘米)、花瓣宽(厘米)

**类:**刚毛藻、云芝、海滨草

从数字上看,刚毛花用 0 表示,杂色花用 1 表示,海滨花用 2 表示。

为简单起见,我们将使用所有特征训练决策树,并将深度设置为 2。

可视化决策树

当然,我们仍然不知道这个树是如何对样本进行分类的,所以让我们通过首先使用 Scikit-Learnexport _ graphviz模块创建一个点文件,然后使用 graphviz 处理它来可视化这个树。

这将创建一个名为 tree.dot 的文件,需要在graphviz*上进行处理。*这里有一个 YouTube 教程向你展示如何用 graphviz 处理这样一个文件。最终结果应该类似于图-1 所示;但是,即使训练数据相同,也可能会生成不同的树!

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

Figure-1) Our decision tree: In this case, nodes are colored in white, while leaves are colored in orange, green, and purple. More about leaves and nodes later.

单一决策树是一种被称为白盒的分类器的经典例子。白盒分类器做出的预测很容易理解。这里有一篇关于黑白盒分类器的优秀文章

了解节点的内容

图-1 中,可以看到每个盒子都包含几个特征。让我们从描述最顶层节点的内容开始,最常见的是称为根节点。根节点深度为零,参见图-2 。节点是决策树上的一个点,在这里提出一个问题。该操作将数据分成更小的子集。

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

Figure-2) The depth of the tree: The light colored boxes illustrate the depth of the tree. The root node is located at a depth of zero.

花瓣长度(cm) < =2.45: 决策树问的第一个问题是花瓣长度是否小于 2.45。根据结果,它要么遵循正确的路径,要么遵循错误的路径。

**Gini = 0.667:**Gini score 是一个量化节点/叶子纯度的指标(一点关于叶子的更多内容)。大于零的基尼系数意味着包含在该节点内的样本属于不同的类别。基尼系数为零意味着该节点是纯的,在该节点中只存在一类样本。你可以在这里找到更多关于杂质测量的信息。请注意,我们的基尼系数大于零;因此,我们知道包含在根节点中的样本属于不同的类。

samples = 150: 由于 iris flower 数据集包含 150 个样本,因此该值设置为 150。

value = [50,50,50]:value列表告诉你在给定的节点上有多少样本属于每个类别。列表的第一个元素显示属于 setosa 类的样本数,列表的第二个元素显示属于 versicolor 类的样本数,列表的第三个元素显示属于 virginica 类的样本数。注意这个节点不是一个纯粹的节点,因为不同类型的类包含在同一个节点中。我们已经从基尼系数中知道了这一点,但是真的看到这一点还是很好的。

class = setosa:class值显示给定节点将做出的预测,它可以从value列表中确定。节点中出现次数最多的类将被选为class值。如果决策树在根节点结束,它将预测所有 150 个样本都属于 setosa 类。当然这没有意义,因为每个类都有相同数量的样本。在我看来,如果每个类别的样本数量相等,决策树被编程为选择列表中的第一个类别。

理解树是如何分裂的

为了确定使用哪个要素进行第一次分割(即生成根结点),该算法选择一个要素并进行分割。然后,它会查看子集,并使用基尼系数来衡量它们的不纯度。它对多个阈值这样做,并确定给定特征的最佳分割是产生最纯子集的分割。对训练集中的所有特征重复这一过程。最终,根节点由产生具有最纯子集的分裂的特征来确定。一旦确定了根节点,树的深度就会增长到 1。对树中的其他节点重复相同的过程。

理解一棵树如何做出预测

假设我们有一朵花,有petal_length = 1petal_width = 3。如果我们遵循图-1 所示的决策树的逻辑,我们会看到我们最终会出现在橙色框中。在图-1 中,如果一个节点问的问题结果是真(假),我们就向左(右)移动。橙色框深度为 1,参见图-2 。因为这个盒子里没有东西生长出来,所以我们称它为叶节点。注意这与真实的树有相似之处,参见图-3 。此外,请注意基尼系数为零,这使它成为一片纯粹的树叶。样本总数为 50。在结束于橙色叶节点的 50 个样本中,我们可以看到它们都属于 setosa 类,参见这个叶的value 列表。因此,树将预测样本是 setosa 花。

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

Figure-3) Real tree vs Decision Tree Similarity: The tree on the left is inverted to illustrate how a tree grows from its root and ends at its leaves. Seeing the decision tree on the right should make this analogy more clear.

让我们挑选一个更有趣的样本。比如petal_length = 2.60petal_width = 1.2。我们从询问花瓣长度是否小于 2.45 的根节点开始。这是假的;因此,我们移至右侧的内部节点,这里基尼系数为 0.5,样本总数为 100。这个深度为 1 的内部节点会问“花瓣宽度小于 1.75 吗?”在我们的例子中,这是真的,所以我们向左移动,最后到达深度为 2 的绿色叶子节点。决策树会预测这个样本是杂色花。你可以看到这是最有可能的情况,因为在绿叶节点结束的 54 个样本中有 49 个是杂色花,见这个叶子的value列表。

使用训练树对新样本进行预测

现在我们知道了决策树是如何工作的,让我们来做预测。输入应在一个列表中,并按[sepal length, sepal width, petal length, petal width]排序,其中萼片长度和萼片宽度不会影响图-1 所示决策树的预测;因此,我们将可以给它们分配一个任意的值。

输出应该是:

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

This is exactly what we predicted by following the Decision Tree logic.

sci kit-学习决策树参数

如果你看一下决策树分类器可以采用的参数,你可能会感到惊讶,让我们来看看其中的一些。

标准:该参数决定如何测量分割的杂质。默认值是“基尼系数”,但你也可以用“熵”来衡量杂质。

**拆分器:**这是决策树搜索拆分特征的方式。默认值设置为“最佳”。也就是说,对于每个节点,该算法考虑所有特征并选择最佳分割。如果您决定将分割器参数设置为“随机”,则将考虑要素的随机子集。然后,将由随机子集中的最佳特征进行分割。随机子集的大小由 max_features 参数决定。这也是随机森林得名的部分原因。

max_depth: 这决定了树的最大深度。在我们的例子中,我们使用深度为 2 来构建决策树。默认值设置为无。这通常会导致过度拟合的决策树。深度参数是我们可以调整树的方式之一,或者限制它的增长方式以防止过度拟合。在图-4 中,你可以看到如果不设置树的深度会发生什么——纯粹的疯狂!

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

Figure-4) A fully grown Decision Tree: In the tree shown above, none of the parameters were set. The tree grows to a fully to a depth of five. There are eight nodes and nine leaves. Not limiting the growth of a decision tree may lead to over-fitting.

min_samples_split: 为了考虑分裂,节点必须包含的最小样本数。默认值是 2。您可以使用此参数来调整您的树。

min_samples_leaf: 需要被视为叶节点的最小样本数。默认值设置为 1。使用此参数来限制树的增长。

max_features: 寻找最佳分割时要考虑的特征数量。如果未设置该值,决策树将考虑所有可用的功能来进行最佳分割。根据您的应用,调整这个参数通常是个好主意。这里有一篇文章推荐如何设置 max_features。

出于语法目的,让我们设置一些参数:

结束语

现在您知道了如何使用 Scikit-learn 创建决策树。更重要的是,你应该能够将它可视化,并理解它是如何对样本进行分类的。需要注意的是,我们需要限制决策树的自由度。有几个参数可以正则化一棵树。默认情况下,max_depth 设置为 none。所以一棵树会长满,往往会造成过拟合。此外,单个决策树不是一个非常强大的预测器。

决策树的真正力量在培养大量决策树时表现得更加明显,同时限制它们的增长方式,并收集它们各自的预测以形成最终结论。换句话说,你种植了一片森林,如果你的森林在性质上是随机的,使用 bagging 的概念,并带有splitter = "random",我们称之为随机森林。Scikit-Learn 随机森林中使用的许多参数与本文中解释的参数相同。因此,在使用大家伙之前,理解什么是单个决策树以及它是如何工作的是一个好主意。

你可以在 LinkedIn 找到我,或者访问我的个人博客

sci kit-了解设计原则

原文:https://towardsdatascience.com/scikit-learn-design-principles-d1371958059b?source=collection_archive---------11-----------------------

优雅、进步、务实

介绍

这篇博客文章是对 Scikit-Learn 库的设计原则的简要反思。需要澄清的是:这是而不是使用 Scikit-Learn 的教程。Scikit-Learn 是一个强大、丰富和广泛的 Python 库,用于实现机器学习。该库提供用于建模(例如,分类、回归和聚类算法)、模型选择(例如,网格搜索)、预处理(例如,特征提取)等的工具。我坚持认为,这个库的成功与其强大而深刻的功能一样,与它的界面和易用性密切相关。

如下面的 Scikit-Learn“算法备忘单”图所示,这个库非常大,非常丰富:

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

但是在这篇博客中,我采用了一种不同的方法,从一个不同的角度来看问题:我不太关注 Scikit-Learn 的功能,而更关注它的设计能力,这样,我借此机会反思了一些我最喜欢的软件模式和设计主题。这篇文章的灵感来自经典论文“机器学习软件的 API 设计:来自 scikit-learn 项目的经验”(以及其他来源——见下面的参考文献)。Scikit-Learn 文档(通过scikit-learn.org,在下面的参考资料中注明)也是最棒的,反映了与库本身一样的深思熟虑和清晰的设计和组织。

Scikit-Learn 库提醒人们设计模式在软件设计中的力量。关于设计模式的开创性工作——设计模式:可重用面向对象软件的元素——提倡“编程对接口的重要性,而不是对实现的重要性。”Scikit-Learn 在其语义非常简单的接口后面隐藏了巨大的复杂性。换句话说,这个库非常容易“开箱即用”。当然,理解机器学习算法的细节很重要,成功的 Scikit-Learn 模型需要进行适当的调整以产生良好的预测;但是,即使是默认的超参数通常也会产生合理的结果。(事实上,对于最近的分类模型,我发现在运行网格搜索后,决策树的 fit 方法的默认参数比推荐的超参数产生了更好的结果!)

此外,因为 Scikit-Learn 是一个而不是一个框架,所以使用起来要简单得多。该库的用户只需要导入他们想要使用的给定功能所需的包,然后从具体的类中实例化对象。不需要从指定的类层次结构继承,也不需要反转控制。

接口

该库是围绕三个基本 API(接口)组织的:预测器转换器 。重要且关键的是,这些接口是互补的——它们并不代表类之间的严格界限或精确的语义分离,而是一种重叠。例如,决策树分类器既是估计器又是预测器——稍后会详细介绍。

评估者

估计器代表 Scikit-Learn 中的核心接口。所有的学习算法,不管是有监督的还是无监督的,分类,回归,还是聚类,都实现了 Estimator 接口,并公开了一个 fit 方法。

估计器的 拟合 方法将(训练)特征向量(“样本”或“预测器”)以及(训练)目标标签(在监督学习的情况下)作为输入,通过这种方式,估计器“学习”如何对看不见的数据进行预测(同样,在监督学习的情况下)。

一个关键的设计原则是,估计器的实例化(例如,您表示模型的超参数)与学习过程(您用训练数据(您的特征向量,例如,“X_train”)拟合模型)是分离的;以及您的训练标签/目标变量,例如“Y_train”)。也就是说,当你构造一个估计器(比如前面提到的决策树分类器)时,你传入超参数,但是你传入的是训练数据的 而不是;训练数据通过 fit 方法传入。正如“API 设计…”一文中提到的,这种分离类似于“部分函数应用”的思想,其中某些参数被绑定(或冻结)到一个函数,然后该函数(及其冻结的参数)被传递到另一个函数——一种高阶函数,或函数组合。事实上,这种“模式”可以说是由 Python 标准库通过 functools.partial 支持的。

这种解耦也可以通过更具侵入性的类机制来实现,也就是说,通过引入另一个类层次结构。然而,Scikit-Learn 的创建者明智地选择了更务实的道路,即使表面上看起来 Estimator 类似乎合并了两个语义边界。

从机器学习的角度来看,估计器是一个

管理模型的估计和解码的对象。该模型被估计为以下确定性函数:

-对象构造中提供的参数或 set_params 提供的参数;

-如果估计量的 random_state 参数设置为 None,则为全局 numpy.random 随机状态;

-以及传递到最近一次对 fit、fit_transform 或 fit_predict 的调用的任何数据或样本属性,或者在对 partial_fit 的一系列调用中以类似方式传递的数据。" (Scikit-Learn 词汇表)

预言者

Scikit-Learn 界面选择的一个令人困惑的方面是预测器与估计器的分离;预测器扩展了估计器接口,对于一个要“工作”的给定模型,它必须实现(并公开)一个 预测 方法。事实上,Scikit-Learn 的词汇表将预测器定义为“支持预测和/或 fit_predict 的估计器”然而 Scikit-Learn 通过 API 在语义上将这两个概念分开。虽然这不是一个关于如何使用库的教程,虽然这可能是显而易见的,但是模型作为预测器接口的一部分实现的方法做了预测结果的工作——给定测试特性;并且在模型被训练之后,预测器返回给定输入特征向量的预测标签。预测器也可以提供概率和预测分数,这是另一个设计原则的一部分(稍后讨论)。**

下面的类图表示了一个通用分类器——决策树——的特定类层次结构,其中我们看到该类既作为一个估计器(事实上它的 通过继承是 一个估计器)又作为一个预测器——因为它实现了 预测 方法。此外,它提供的 score 方法(返回给定测试数据和标签的平均准确度),源自一个“mixin”类——“classifier mixin”。所谓的“mixin”类是分离和打包特定功能(通常通过单个类方法提供)的标准方式,用于简单继承,同时避免“可怕的菱形模式”,这是多重继承的一个危险。

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

虽然类机制很好地协调和平衡了设计和实现的复杂性,但代码接口非常简单易用,允许您用三行代码实例化、拟合和使用模型:

变形金刚(电影名)

毫不奇怪,变压器会修改数据。“API 设计…”一文说得好:

预处理、特征选择、特征提取和降维算法都作为库中的转换器提供。

像模型一样,变形金刚也需要安装,一旦安装完成,就可以调用它们的 转换 方法。为了保持库的优雅和一致的简单性, fit 方法总是返回它所调用的 估计器 ,允许您链接 fit 和 transform 方法。为了方便起见,变形金刚还支持一个fit _ transform方法,因此用户可以一步完成这两个操作。

下面的类图显示了 StandardScaler 转换器也是一个估计器,并且也混合了 TransformerMixin 类。然而,使用这个转换器的代码非常简单。

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

透明度

用于构建估计器和转换器的所有超参数,以及拟合和预测的结果,对于界面的用户来说都是可见的公共属性。从表面上看,这似乎违背了封装和信息隐藏原则,这些原则长期以来一直是面向对象设计的标志,在面向对象设计中,对象状态通常只能通过类方法的中介来实现。但是这种设计选择极大地简化了库(通过避免访问方法的扩散):因为接口已经是一致的(并且既清晰又有说服力),添加免费的方法来获取关键的模型属性或预测结果只会降低其有效性。

核心数据结构

该库的设计者同样做出了直接而具体的决定,将机器学习所需的核心数据表示基于 Numpy 多维数组——而不是引入一组定制的类来封装表示特征和标签/目标的数据。与许多其他选择一样,这降低了进入的障碍,可以说,用户不必学习机器学习数据表示的新的类层次结构,以及确保时间和空间方面的性能,因为 Numpy 使用 c 针对性能进行了优化。

合成估算器-管道

所有核心语义组件——估计器、预测器和转换器——之间的一致和统一接口为该库提供了额外的能力和灵活性,允许用户通过将估计器链接在一起来组成新的或增强的功能。记住,变压器是一种估计器(回想一下上面的 StandardScaler 的类图,从 BaseEstimator 派生而来),Scikit-Learn 提供了一个管道类,允许用户将多个变压器链接在一起;因为所有的转换器共享相同的接口,所以管道可以将用户的数据适配到所有的转换器(通过迭代构造它的转换器的集合),然后,如果 fit_transform 也被调用,则应用转换并返回转换后的数据。下面的代码片段演示了用相似特征的平均值填充缺失值(通过 SimpleImputer 类),然后缩放数据(通过 StandardScaler 类)是多么容易。

通过 Duck-Typing 的可扩展性

我想提到的最后一个设计原则是库对所谓的鸭式输入的依赖,以允许对库进行扩展。鸭子类型化意味着如果一个类支持一个特定的方法——也就是说,如果它“看起来像一只鸭子”——那么它可以与同一接口的其他对象互换使用——也就是说,它 是一只 鸭子。这避免了对继承的需要,从理论上讲,这使得代码不那么紧密耦合、脆弱和复杂。也就是说,如果用户想要扩展库,例如,通过编写定制的转换器,他们不一定需要从 Scikit-Learn 类继承。通过这种方式,库的创建者将 Pythonic 的灵活性和实用性带到了 Scikit-Learn。

结论

数据科学家,无论是学生还是专业人士,都很幸运拥有如此丰富和设计良好的库,如 Scikit-Learn,它允许我们用漂亮和设计良好的代码来处理复杂的机器学习问题。

参考

Lars Buitinck,Gilles Louppe,Mathieu Blondel,Fabian Pedregosa,Andreas Mueller,Olivier Grisel,Vlad Niculae,Peter Prettenhofer,Alexandre Gramfort,Jaques Grobler,Robert Layton,Jake Vanderplas,Arnaud 乔利,Brian Holt,gal Varoquaux,“机器学习软件的 API 设计:scikit-learn 项目的经验”,https://arxiv.org/abs/1309.0238,2013 年。

aurel in géRon,使用 Scikit-Learn 和 TensorFlow 进行机器学习,O’Reilly Media,2013 年

** [## sci kit-学习

编辑描述

scikit-learn.org](https://scikit-learn.org)**

Scikit-Learn 与机器学习的 MLR

原文:https://towardsdatascience.com/scikit-learn-vs-mlr-for-machine-learning-exxact-blog-e8eb173a5d65?source=collection_archive---------29-----------------------

检查两个库的 ML 工作流

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

Image Source: stokpic

Scikit-Learn 以其易于理解的 API 而闻名,对于 Python 用户来说,MLR 成为了流行的 Caret 包的替代品,提供了更多的算法套件和一种调整超参数的简单方法。这两个包在某种程度上是相互竞争的,因为许多参与自动分析的人转向 Python 进行机器学习,R 进行统计分析。

偏爱 Python 的原因之一可能是因为当前机器学习的 R 包是通过包含该算法的其他包提供的。这些包通过 MLR 调用,但是仍然需要额外的安装。甚至需要外部特征选择库,并且它们还需要满足其他外部依赖性。

Scikit-Learn 被称为许多机器学习算法的统一 API,不需要用户调用任何库。

**这绝不意味着怀疑 R。**不管在线调查结果如何,R 仍然是数据科学领域的一个重要组成部分。任何有统计学或数学背景的人都会知道为什么你应该使用 R(不管他们自己是否使用它,他们认识到了它的吸引力)。

现在,我们将看看用户如何经历典型的机器学习工作流。在 Scikit-Learn 中,我们将继续学习 MLR 中的逻辑回归和决策树。

创建您的培训和测试数据

  • train <- sample(1:nrow(data), 0.8 * nrow(data))
  • test <- setdiff(1:nrow(train), train)
  • MLR 没有用于子集数据集的内置函数,因此用户需要依赖其他 R 函数来实现这一点。这是一个创建 80/20 训练测试集的例子。

选择算法

  • makeLearner('classif.rpart')。这个算法被称为学习器,这个函数被调用来初始化它。
  • makeClassifTask(data=, target=)。如果我们正在做分类,我们需要进行一个调用来初始化一个分类任务。这个函数将接受两个参数:训练数据和目标变量的名称。

超参数调谐

在任一软件包中,优化超参数时都有一个过程要遵循。您首先需要指定要更改哪些参数以及这些参数的间距。然后进行网格搜索或随机搜索,以找到参数估计的最佳组合,从而获得最佳结果(即误差最小化或精度最大化)。

Scikit-Learn

C = np.logspace(0, 4, 10)
max_iter= [100,110,120,130,140]
hyperparameters = dict(C=C, penalty=penalty, dual=dual, max_iter=max_iter)
GridSearchCV(logreg, hyperparameters, cv=5, verbose=0)
clf.fit(x_train, y_train)

最低贷款利率(minimumlendingrate)

makeParamSet( makeDiscreteParam("minsplit", values=seq(5,10,1)), makeDiscreteParam("minbucket", values=seq(round(5/3,0), round(10/3,0), 1)), makeNumericParam("cp", lower = 0.01, upper = 0.05), makeDiscreteParam("maxcompete", values=6), makeDiscreteParam("usesurrogate", values=0), makeDiscreteParam("maxdepth", values=10) )
ctrl = makeTuneControlGrid()
rdesc = makeResampleDesc("CV", iters = 3L, stratify=TRUE)
tuneParams(learner=dt_prob, resampling=rdesc, measures=list(tpr,auc, fnr, mmce, tnr, setAggregation(tpr, test.sd)), par.set=dt_param, control=ctrl, task=dt_task, show.info = TRUE) )
setHyperPars(learner, par.vals = tuneParams$x)

培养

这两个软件包都提供了训练模型的单行代码。

这可以说是这个过程中最简单的步骤之一。最困难的步骤是调整超参数和特征选择。

预言;预测;预告

就像训练模型一样,预测只需要一行代码就可以完成。

Scikitlearn 将返回预测标签的数组,而 MLR 将返回预测标签的数据帧。

模型评估

评估监督分类器最流行的方法是一个混淆矩阵,你可以从中获得准确度、误差、精确度、召回率等。

Scikit-Learn

  • confusion_matrix(y_test, prediction)或者
  • classification_report(y_test,prediction)

MLR

  • performance(prediction, measures = list(tpr,auc,mmce, acc,tnr))
  • calculateROCMeasures(prediction)

这两个软件包都提供了多种获取混淆矩阵的方法。**然而,对于尽可能简单的信息视图,python 不如 r 信息丰富。第一个 Python 代码将只返回一个没有标签的矩阵。用户不得不返回到文档中去辨认哪些列和行对应于哪个类别。**第二种方法具有更好和更丰富的输出,但它只会产生精确度、召回率、F1 分数和支持度;但这也是不平衡分类问题中更重要的性能指标。

判定阈值(即改变分类阈值)

分类问题中的阈值是将每个实例分类到预测类别中的给定概率。默认阈值将始终为 0.5(即 50%)。这是在 Python 和 R. R 中进行机器学习时的一个主要区别。R . R 提供了一行代码的解决方案来操纵阈值以解决类的不平衡。Python 对此没有内置函数,而是由用户通过定义自己的自定义脚本/函数来以编程方式操纵阈值。

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

pair of graphs showing decision thresholds

Scikit-Learn

  • 在 Scikitlearn 中没有一种标准的阈值方法。查看这篇文章,你可以自己实现它:在 Scikit-Learn 中微调分类器

MLR

  • setThreshold(prediction, threshold)。mlr 中的这一行代码将自动更改您的阈值,并可以作为参数来计算您的新绩效指标(即混淆矩阵等)。)

结论

最后,在处理机器学习时,mlr 和 Scikitlearn 都有各自的优点和缺点。这是使用其中一种进行机器学习的比较,并不能作为使用其中一种而不是另一种的理由。对这两方面都有所了解,才能给职场上的人带来真正的竞争优势。对流程的概念性理解将使工具的使用更加容易。

原载于 2019 年 8 月 21 日【https://blog.exxactcorp.com】

体育界数据科学/分析的范围

原文:https://towardsdatascience.com/scope-of-analytics-in-sports-world-37ed09c39860?source=collection_archive---------10-----------------------

你好世界!!在本文中,我们将讨论在体育界,先进的分析预测建模如何胜过常规的定制/传统分析。我们已经见证了人工智能和最先进的机器学习模型如何超越旧的分析师方法,其分析已经重塑了许多企业的运营。令人惊讶的是,尽管有如此丰富的数据,体育分析的采用却相当坎坷和不均衡。

只是在最近,体育分析已经成熟,即使如此,还有足够的渗透空间。2016–2022 年体育分析预测估计,2022 年,40.1%的 CAGR 可能达到 39.7 亿美元的价值。认识到我们将在体育世界中处理的数据范围,利用分析是非常有意义的。每天,体育界都在不断提高其使用体育分析工具来提高胜率的能力。

为什么体育分析正在改变世界?

基本上,体育分析是为直接参与比赛的运动队或体育博彩公司进行的。

体育分析可以解释为使用与任何体育或游戏相关的数据。像统计球员,天气情况,球队最近的胜败等。有了这些数据,我们可以创建预测性的机器学习模型,代表管理层做出明智的决策。运动分析的主要目标是提高团队表现,增加赢得比赛的机会。一场胜利的价值说明了一切,并以不同的形式表现出来,如涓涓细流渗透到体育场座位上的球迷、电视合同、球迷商店商品、停车、特许权、赞助、注册、保留和当地自豪感。

主要团队及其分析合作伙伴

  • 皇家马德里和微软,世界上最大的足球俱乐部之一-皇家马德里-正在使用微软技术来转变其运营、性能、健身以及与 5 亿全球球迷的关系。
  • 曼联和怡安,像全球成千上万的企业一样,曼联足球俱乐部依赖怡安作为长期值得信赖的顾问,寻找创新的解决方案,使他们在竞争中保持领先地位。

正如我们所见,顶级全球体育品牌使用先进的体育分析,在整体表现、健身和与粉丝的关系方面保持领先。

体育分析用例

预测分析

主要用例是进行预测分析,这可以提供关于团队在比赛日应该如何的见解。哪个实习生给的团队表现更好,增加了团队的获胜概率。

使用我们的机器学习模型,我们可以预测比赛日哪个球员在哪个位置上表现更好。我们的模型将建立在球员的数据基础上,他在与对手的比赛中表现如何,比赛条件如比赛是主场还是客场,等等。因此,在给定比赛条件和我们面对的对手的情况下,我们可以预测哪些球员适合哪个位置。

  • 球员分析 ,我们可以通过分析每个球员的训练模式和饮食图表来改善他们在球场上的表现和健康水平,然后根据我们的分析改进这些。
  • 团队分析 ,使用团队统计数据,我们可以建立最先进的机器学习模型,如深度神经网络、支持向量机等,以帮助团队管理人员计算获胜组合及其概率。
  • 粉丝管理分析 ,有了社交把手数据,我们可以在粉丝群内发现模式,使用聚类算法形成聚类/群组,针对目标群体开展活动。知道了最能吸引粉丝的因素,团队管理层就可以专注于改善这一方面,从而获得新的粉丝群并留住老粉丝。

使用高级可视化技术提供见解

在当今以数据为中心的世界中,数据可视化是一个至关重要的工具,体育领域也不例外。使用表格格式的原始数据,管理层无法获得清晰的见解,并且需要很长时间来浏览整个数据并掌握内容。因此,以图形格式呈现数据使管理层能够看到通过图形和图表直观呈现的分析,因此他们可以掌握困难的概念或识别新的见解。

图形表示的下一步是交互式可视化,您可以通过使用 tableau、clickview 和 rshiny 应用程序等技术深入了解图表和图形,以获得区域级别的更多详细信息和洞察力,从而以交互方式改变您看到的数据深度及其处理方式,从而将这一概念向前推进一步。

  • 球队经理仪表盘, 球员比赛表现统计数据将以互动仪表盘格式呈现,以便更好地了解比赛情况。
  • 球迷仪表盘 ,球迷可以获得自己喜欢的球员的比赛数据,并可以与对手或同队的其他球员进行比赛对比。

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

了解粉丝网络

每个运动队都有自己热情的粉丝群,他们需要一种方式来更好地与他们联系,无论他们在世界的哪个角落。我们的反应式仪表板允许他们与粉丝一对一互动,创建有针对性的促销活动,并使用收集的数据来跟踪和分析粉丝行为。这样管理层就知道,是什么驱使他们的球迷为他们的球队疯狂,并为此付出更多。

  • 找到共同兴趣,利用从脸书、推特、Instagram 等社交平台收集的数据,我们可以分析最吸引球队热情粉丝的因素,并据此开展宣传活动。

进入体育赌博的世界

体育分析不仅对体育领域内外产生了巨大影响,还促进了体育博彩行业的发展,该行业约占全球博彩行业的 13%。价值在 7,000-1,000 亿美元之间的体育博彩在各种群体中非常流行,从狂热的体育迷到休闲赌徒,你很难找到一项职业体育赛事不依赖结果。许多赌徒被体育赌博所吸引,因为他们在做决定时有大量的信息和分析。

我们到此结束,希望我已经给了一些体育分析世界的介绍。查看其他作品这里。关于未来的讨论,请联系媒体Linkedin脸书

酷热:随着全球纪录的暴跌,圣保罗遭遇了有史以来最热的第三季度之一

原文:https://towardsdatascience.com/scorcher-as-global-records-tumbled-spore-baked-under-one-of-the-warmest-q3-ever-436837cb5b0?source=collection_archive---------35-----------------------

7 月至 9 月是这个城市国家过去 36 年来经历的最热的三个月之一,2019 年将打破气温纪录。

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

File photo, circa Singapore 2015. Photo: Chua Chin Hon

新加坡也未能幸免于最近席卷全球的创纪录热浪。

如果有什么不同的话,对这个城市国家 2019 年 7 月至 9 月的天气数据的检查表明,新加坡遭受了一场长时间的热浪,其强度明显高于同期的长期平均水平*(即 2019 年第三季度数据与往年第三季度数据的对比)*。

在 2019 年第三季度的 92 天中,有 84 天,即 10 天中的 9 天,日平均气温超过了 7 月至 9 月 27.92 摄氏度的长期平均值,这是自 1983 年以来的最高水平。

2019 年第三季度还有 81 天的日最高气温超过了同期 31.39 摄氏度的长期平均气温,与 1997 年新加坡和世界遭受厄尔尼诺效应冲击时创下的当前纪录持平。

气象局早些时候表示,2019 年 8 月可能是自 1929 年有记录以来最干燥和最温暖的 8 月,2019 年将创造新的温度记录

目前还不清楚新加坡的天气是否已经转向新常态。但是趋势线确实指向一个令人担忧的方向。

数据和基准

比较天气记录总是很棘手,即使对于像新加坡这样的小城市国家也是如此。这在很大程度上取决于您使用的数据,以及用于比较的基准和时间框架。

在这篇文章中,我将使用 36 年的天气数据集,这是我之前从新加坡气象局的网站上收集的。因此,这里提到的“长期”是指 1983 年至 2019 年(9 月)之间的时期。这些数据在早期的 Jupyter 笔记本中进行了预处理,我已经用 2019 年 7 月至 9 月的数据进行了更新。

为了确保进行同类比较,我主要将 2019 年第三季度的数据与前几年的第三季度数据进行比较。如果你对所有季度进行比较,结果会有所不同,包括 12 月这样较冷的月份。

数据探测和温度记录

浏览数据,很快就发现 2019 年第三季度没有打破任何单日气温记录。

例如,在过去的 36 年里,最高日最高温度是 36 摄氏度,记录在一个闷热的 1998 年 3 月 26 日。但 2019 年第三季度记录的最高日最高气温“仅”为 34.3 摄氏度(9 月 28 日),远低于该数据集中的纪录。

1998 年 5 月的两天——5 月 21 日和 5 月 28 日——共同保持了 30.9 摄氏度的最高日平均气温纪录,比 1983 年至 2019 年期间的日平均气温高出约 3.23 摄氏度。这一长期纪录几乎没有受到 2019 年第三季度最高日平均气温 29.8℃(8 月 12 日和 8 月 16 日记录)的威胁。

虽然 2019 年第三季度的数据没有打破任何单日记录,但仔细观察发现,这一时期的平均气温都高于长期平均水平。

例如,2019 年 7 月至 9 月的日平均最高气温为 32.59 摄氏度,比 1983 年至 2019 年期间的长期平均气温 31.52 摄氏度高出 1.07 摄氏度。

同样,2019 年第三季度的日平均气温和日平均最低气温分别比这两个类别的长期平均气温高 1.39 摄氏度和 1.97 摄氏度。

当你比较苹果和苹果时,这种趋势变得更加明显,也就是说,相互比较第三季度的温度记录,而不是整体的长期平均值,其中包含较冷的月份。

2019 年第三季度的日平均最高气温(32.59 摄氏度)比 1983 年至 2019 年期间同类第三季度长期平均气温 高 1.2 摄氏度**。**

同样,2019 年第三季度的日平均气温和日平均最低气温都高于 1983 年至 2018 年第三季度的长期平均气温。

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

这可以通过一些图表得到最好的说明。

2019 年第三季度与第三季度长期天气数据

至少可以说,这种对比是惊人的。2019 年第三季度的平均气温在所有三个类别中都明显升高,包括最低日气温,这意味着我们将迎来更热的白天和更温暖的夜晚。

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

By default, Seaborn line plots aggregate over multiple y values at each value of x and shows an estimate of the central tendency and a confidence interval for that estimate — which was turned off for this chart.

2019 年第三季度的记录也违背了长期趋势,如灰色线条所示。总的来说,从七月到九月,气温往往会下降。

但引人注目的是,2019 年第三季度的最高日气温随着月份的推移而飙升,从 7 月到 9 月平均呈现持续上升的趋势。与此同时,2019 年 9 月底的日平均气温几乎与 7 月初持平,与第三季度末略有降温的长期趋势形成鲜明对比。

2019 年第三季度的最低日气温遵循了更符合长期趋势的形状,但它比我们在 1983 年至 2018 年期间经历的温度高得多,如上图的第三个子图所示。

2019 年第三季度与 2016 年第三季度和 1997 年第三季度

我们还可以做单年对比。对于下面的图表,我选择了 2016 年和 1997 年第三季度的数据,因为这两年都有很长的高温期。

新加坡气象局称 2016 年是这个城市国家有记录以来最热的一年。1997 年,由于“T4”厄尔尼诺现象,新加坡和当时世界上的许多地方一样,遭受了长时间的酷热和干燥天气。

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

一眼看去,很明显,2019 年第三季度的温度-由红色实线代表-比 2016 年和 1997 年的类似时期更高。

正如媒体今年早些时候报道的那样,2019 年看起来肯定会打破新加坡的年度气温记录。

快乐图或堆积密度图

流行的 joyplots 提供了另一种方式来可视化 2019 年第三季度与过去 36 年同期相比有多激烈。我将绘制一个版本来比较日平均气温。

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

这些差异再次显而易见:2019 年第三季度的日平均气温分布(右侧图表)与长期趋势(左侧图表)相比,显示出明显的右移,标志着一个更高的温度时期。

比较日平均温度和日最高温度高于长期平均温度的天数

说明 2019 年第三季度相对于其他年份的第三季度有多热的另一种方法是比较数据集中汞飙升至第三季度长期平均值以上的天数。

我要用的两个基准是:
*31.39℃:1983 年至 2018 年间 7 月至 9 月间记录的日平均最高气温。

*27.92℃:1983 年至 2018 年间 7 月至 9 月间记录的日平均气温。

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

2019 年第三季度,有 81 天的日最高气温超过了同期 31.39 摄氏度的长期平均气温,与 1997 年创下的当前纪录持平。

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

在 2019 年第三季度的 10 天中有 9 天(准确地说是 92 天中的 84 天),日平均气温超过了 7 月至 9 月 27.92 摄氏度的长期平均值。按照这个标准,这是我们自 1997 年以来看到的最高水平。如果您使用不同的基准进行比较,结果会明显不同。

2019 年第三季度是有记录以来最热的第三季度吗?

没有完整的数据——新加坡有文字记载的温度记录可以追溯到 1929 年——很难说清楚。这在很大程度上还取决于您采用的比较基准和时间框架。

我不是训练有素的气象学家,也不是新加坡天气专家,所以我不能说我在这里使用的基准和假设是否反映了该领域可接受的规范。

但 2019 年第三季度肯定是我们在新加坡过去 36 年中看到的最温暖的三个月之一,也可能是未来更不舒服的时期的一个迹象。

这篇文章的 Jupyter 笔记本可以在这里找到,旁边还有处理过的数据集

我之前尝试想象和分析新加坡不断变化的天气模式,可以在这里找到这里这里

像往常一样,如果你发现任何错误,ping 我@

推特: @chinhon

领英:www.linkedin.com/in/chuachinhon

评分和排列

原文:https://towardsdatascience.com/scored-and-arranged-4f09fb3b314f?source=collection_archive---------33-----------------------

深入分析

和 Nick Scavo 对 20,783 个 Pitchfork 评论的探索性数据分析

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

数据集使用:20783 条干草叉评论

尼克·詹姆斯·斯加沃 是一位居住在纽约的音乐家和作家。他与实际的学校合作进行各种个人和合作项目,定期向微型混音带提供评论和论文,并与现代艺术博物馆 PS1、艺术家空间、新博物馆、根茎、控制合成器和电子设备合作,并在 NTS 电台常驻。他是 发行项目室 的传播总监兼助理策展人。

在整个访谈中,“钟形曲线”一词被不严格地用来指任何单峰分布,其中中间值附近的值表示评估分数的中间值,而不是指对称分布。

安德鲁·汤普森(Andrew Thompson):我认为应该从 Pitchfork 的分数分布图开始,看看 Pitchfork 是如何对事物进行评级的,以此来考虑 Pitchfork 评级的想法和这个评估系统。

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

Fig. 1

这是他们分数分布的直方图。干草叉的平均分数几乎正好是 7,中位数是 7.3。从你的角度来看,干草叉评级系统是什么?它的意图和效果是什么?

尼克·斯加沃:当你看到这样一个模型时,我不禁会想到根据钟形曲线来评分。因此,很明显,从专家或教授到评论家,都存在一种假定的教育权力动态,以某种方式给表演打分。我觉得在批评史上,你通常没有一个实际的数值。在很大程度上,在 20 世纪艺术史中,你有某种智力参与。但在 21 世纪初,随着 Pitchfork 和类似的出版物的出现,评论家们通过在工业化条件下运作来反映他们正在处理的内容——他们开始给美学作品赋予数字价值。我认为这可能是相对特定于音乐形式的——例如,在视觉艺术中看到量化的价值是很奇怪的。你能想象有人给 MoMA 最近的展览打分吗?

没有,但是你会看到一些量化电影的尝试,这可以追溯到 90 年代

像罗杰·伊伯特一样

:右,拇指向上拇指向下,这已经转移到烂番茄汇总成元评论的任何内容。有了 Pitchfork,它总是把像罗杰·伊伯特这样的人和使用这种系统的其他人区分开来,这是他们声称评估一件作品的准确性——这是一种分米精度,可以衡量一件事情的好坏。当你说某样东西是 7.7 时,你是说它不是 7.6 或 7.8,它就是这么有价值。甚至没有恒星系统的模糊性,比如一到五颗恒星。就像他们试图超越任何一种分数的可解释性或三星级评论可能暗示的任何普遍性的承认,相反,它传达了这种科学主义。

NS :这很奇怪,因为虽然它看起来像是精确或科学的,就像钟形曲线一样,但它是一种更相关的数字。之所以评分是 7.7 而不是 7.6,是因为也许另一张专辑被给了 7.6,我们需要看着那张专辑断言这张专辑更好。因此,在某种程度上,它遵循一条线,这条线是根据一系列相互发展的点绘制的——这就是你在这里看到的:音乐评论的独特分布。当你回顾过去的一年,回顾 2010 年所有最好的新音乐时,你会看到 Pitchfork 的作者给出的一系列文化价值观,然后你会看到给它们的不同的数字分数。这总是很奇怪,因为你会有人给某张专辑打 10 分,但往往这张专辑不是年度最佳专辑。这是一个非常松散的,有争议的,相关的数字情况,几乎有一个错误的或伪量化发生。

是的,我的意思是,毫无疑问这是假的。这里面也有愤世嫉俗的唯物主义。我记得在我听了 Sote 的设计的神圣恐怖之后,我想这是我去年听到的最好的事情之一,我认为我真正理解了艺术体验的概念,当我听到这个想法时,就像打开了世界。干草叉给了它…让我看看他们给了它什么。他们有 7.8 分。这张专辑的体验是完全非物质的,对吗?看到这张专辑的评分降到 7.8 分,我对音乐的精神感到非常矛盾。

我百分之百同意。归根结底,这是建立权力或权威的一种方式。这是对客观性的一种尝试,但我认为它不适用于这种情况。我的意思是,很明显,干草叉评论是一个作家量化的尝试。但是,作为一名读者,我们的任务是对量化做出回应——我是同意还是不同意这一点?人们对这种情况很着迷。这就是为什么人们总的来说对社论或专栏文章着迷——他们想不同意作者的观点,当他们看到一个分数时,这几乎是一种耸人听闻的挑衅。他们甚至不用读任何东西。他们只是看到这个荒谬的数字,只是对它吐口水,然后你在午夜的时候在互联网上等待下一个 Pitchfork 评论——我真的不认为现在是这样了,但在其全盛时期,有一段时间我会在午夜刷新页面,看看新的 Pitchfork 对一张专辑的评论,只是看看它被赋予了什么价值。在 2008 年和 2009 年左右,那是独立在线网络博客“品味制作”的巅峰时期。我觉得这已经从信息来源的纯粹多样性中扩散了一点点。当你看这个分布时,我认为你能做的最安全的事情就是给某样东西打 7.8 分。它本质上只是确认记录——你必须质疑以这种方式写评论的目的。在这种情况下,我认为这是公关周期的一部分。一个极低的评价或者一个极高的评价都有一种耸人听闻的性质,这将在公共话语中造成某种破裂。如果一张专辑获得了 Pitchfork 10,这是非常罕见的事情。记录低于 3、2 或 1 的情况同样罕见。我会对这些数据提出这样的问题:也许从 2009 年、2010 年开始,随着音乐变得更加工业化,通过 Pitchfork 这样的东西在我们的消费中变得更加普遍,我只能猜测平庸、中值/均值评论的实际数量只会上升。

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

Fig. 2.1

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

Fig 2.2

:好吧,让我们看看……中间值有一点移动(图 2,顶部),但方差实际上已经下降了(图 2,底部)。

NS :相当狂野。早期互联网音乐评论的自由自在的日子。

自 2001 年以来,它下降了…那是什么…超过 30%。所以你在某种程度上是对的。随着时间的推移,分数越来越接近中间值。

我认为这表明它已经变得不那么独立了。当你有一个更大的分数偏差时,你会有非常不同的观点,对音乐做出非常不同的断言。你会看到人们一路向左,然后一路向右,而不是更多的中间路线评论,我认为这是一种正常化,反映了我们在过去 20 年里看到的每一种经济趋势——包括美国的政治话语。

AS :万物无情同质化。

NS :不要太随意地使用这个词,但这是一种超正常化,这种字面意义上的将偏差挤压到更紧密的集合中。东西靠得更近了,它们受到限制,不能像以前那样移动。

AT :我的意思是,一方面,看着这张原始图表,也许可以说,工作确实是按照这种形状进行的,大部分工作都很一般:有大量糟糕的工作,但有一小部分确实很棒。那么有没有什么可以说这反映了艺术的现实呢?即使他们的数字系统是一种虚假的客观性,在这种虚假的客观性中,它正在描绘出事物的形状?

我认为这是一个我们必须质疑的说法。我认为这是一个在我们看待事物的方式中占主导地位的模型,钟形曲线,其中大部分作品是平庸的,很少一部分是精选的,天才的作品。这是一个我们不得不质疑的神话,因为它在西方思想和资本主义中占据主导地位。这是一个模型,我们已经被编程为定期查看。我会说——我不相信品味的完全相对主义,但我想也许有一个更少等级,也许更分散的模型,来描述我们如何思考我们与艺术和审美体验的关系,这也许会看起来完全不同于钟形曲线。

:你几乎可以把这两个图表连在一起【图 1 和图 2,底部】,并且说评论感觉几乎应该反映自然模型的想法。我刚才说的这个想法:这难道不反映自然吗?钟形曲线是自然的。显然,我们已经通过相信一切都必然符合钟形曲线,展示了历史上各种各样的问题。干草叉持续的时间越长,他们就越觉得自己需要为了牛市曲线而坚持下去,如果他们偏离了 7.3,7.4,这在某种意义上是不自然的。我认为这是一个好主意:也许有更多的作品,如果不是天才的话——也许我们应该完全抛弃天才作品的想法。

是的,我觉得我们有很多实验性的和批判性的模型来量化我们听音乐的体验,这真的很令人兴奋,值得谈论和思考。你可以提出一个又一个完全破坏钟形曲线的模型。你也可以用全新的方式用这些模型来写音乐。Pitchfork 特别令人沮丧的一点是,他们的音阶变得如此之小,这是他们一遍又一遍地使用同一个模型的近 20 年历史。我认为你看着这些数据并从中提取各种假设是正确的。当我们看这些数据时,我们看到的是我们在世界其他地方看到的同样令人沮丧的现实,那就是事情变得越来越不明显,越来越中间,越来越自动连接,在同样的 7.8 或 7.3 或 7.4 之后也是如此。如果你看看过去五年中最好的新音乐,实际上我们有更多市场准备好的,市场友好的最好的新音乐。所以它实际上是在执行一个行业功能。它以一种野心家的方式表现的能力被赋予了价值,因为这关系到音乐行业对它的期望,即销售唱片,成功巡演,在流媒体平台上表现出色。

这可能很难做到,因为它受制于历史的经济流动,但我很好奇,过去五年最好的新音乐是否比 90 年代或 21 世纪初或那个时候最好的新音乐有更好的盈利能力。

:如果不引入外部数据,只看评论本身,很难说,比如巡演收入、专辑销量或流媒体数据等等。但是我之前看这些数据时发现,Pitchfork 给 10 分的东西往往是这些怀旧的回顾。

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

Fig. 3.1

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

Fig. 3.2

NS :哦耶。再版。

****在处:右,龙刚。

NS :在这里,我们有后知之明是 20/20 的想法。当你能够回顾文化并说,那正是那个时代的时代精神时,你会有一个更完美的愿景。那张唱片确实总结了发生的 X 件事或其他什么。现在真正弄清楚什么是重要的要困难得多,尤其是当它变得模糊到第 n 度的时候。

****在的时候:感觉那个时候评审也不再冒险了,对吧?如果你对一个已经确立的批评意见表示肯定,你们两个都不会冒险,同时也把自己描绘成一个圣徒,对一张专辑的名声和它在音乐史上的地位负责。

越往后,分数越高。所以当你到了 10 年、20 年的时候,事情并不真的…过去有一些神圣的东西。

NS :我记忆中最难忘的 10 叉之一是电台司令的小子 A 。那是 2000 年左右的事了,当时我还很年轻,我觉得这个记录无可否认是完美的 10 分。根据我当时的教育和音乐听力,这是一本关于什么是好的实验音乐唱片的大部头。尽管我在 2000 年的时候认为这是一张晦涩难懂、声音怪异的专辑,但这时候电台司令并不是一个小乐队。Pitchfork 给这个记录打 10 分是一个非常有品牌效应的决定。许多其他出版物,大众媒体音乐出版物,都在谴责和反对他们从 OK 电脑转移声音。每个人都表现得很惊讶。但这也是 Pitchfork 的一个转变,因为我认为他们的受欢迎程度在 2003 年后呈指数增长,并持续到后期。**

我也想知道,在音乐评论文本中存在的形容词的分布是怎样的。

AT :你是说形容词的数量?

是的,比如音乐评论家在多大程度上依赖于用形容词来描述声音,以及形容词对我们理解声音的意义有多大帮助?有一种趋势是叙述音乐,用描述性的词来描述它,比如“粗糙”或者用隐喻,比如“往钢铁上泼水”。

形容词使用 Python 的空间库及其最大的英语语料库来识别。SpaCy 非常好,但是像所有自然语言处理工具一样,它并不完美。这里存在一些小错误,主要是在很少使用的单词的尾部,像“gyaaaah”这样的单词被标记为形容词。少数单词也没有被正确地识别为形容词,其中包括“天才”,不幸的是,图书馆总是将其识别为名词。

AT :在你看来,这些词有什么问题,一个人应该如何写音乐?

随着写作音乐和定期量化音乐并试图证实这种量化的实践,我们常常不得不去看实际的文本,去看那些用来赋予事物意义的词。因此,为了支持某事的 8.8 或其他什么,我们必须看看用来庆祝它们的形容词,并确定其在英语中的含义。通常这种语言无论如何都不是对音乐的实际辩护。这种写作不包含政治论点主张其意义,或社会评论。我们可能会在评论中偶尔看到这种情况,但我想说的是,捍卫可量化分数地位的主要方法是这种类型的描述性语言,这些脆弱的词——你可以像剥颜料一样剥下它们,它们就这样脱落了,当你剥去所有这些词时,你还剩下什么?《音乐评论》本身的实际主张是什么?

当你看这些评论时,这个人到底想说什么?这是一件很奇怪的事情?这就像一首时髦的音乐?在语言中,很难找到什么是真实的,用数字表示的量。这就是为什么我对形容词或者陈词滥调感兴趣,因为我觉得这些是第一道防线。

:所以这几乎就像量化的价值必须证明自己,几乎通过使用这些词,每个词本身都有一个值,并聚集在所有其他词的顶部,这相当于这个等于 8.1 或什么的马赛克。

NS :是的,因为正如我们已经说过的,数字使语言尴尬。作者知道这一点,必须用语言来证实。那是给作者的简报——他们必须以书面形式证实它,他们不能只给出一个数字。我们看到的一件事是大量的假设,这些假设反映了量化音乐本身的基本假设。你知道,我只是在意识形态上有所不同。我们必须——我的意思是,我也一直这么做,我经常用这样的语言来描述音乐。

我也一直在使用这样的语言。和“斯塔克”一样,我也一直用“斯塔克”这个词。不一定用声音,但是我们用形容词来描述事物,比如“缥缈的”。如果是“缥缈”,是不是一定要不说是缥缈?

我真的对这些词没有问题,事实上,我认为它们让人联想到某些画面。通常,这些单词是我们已经非常具体地理解的关系建立的单词——这是语言的惊人之处之一,它被编码为具有这些特定的互文意义,当你将它们配对在一起时,它们创建了这些富有诗意和表现力的酷结构,可以触及事物的核心。我想说的是,这些词和数字之间的关系完全是个问题,在语言中用来捍卫数字的策略是我希望看到进一步证实的东西,我希望梳理出这些说法。也可能只是纯粹的诗歌。如果这只是纯粹的诗歌,那就更让人质疑这个数字的用途了。

基本上你要做的就是描述…这有点,我确定在电影中有这些书面的比喻。在影评中,影评人经常说:“不要只叙述情节”,这在影评中是不被认可的。而在很多方面,音乐评论不具备这一点。音乐评论希望你讲述专辑的架构,因为它在大多数时候并不明显。实际上只是不明显。听音乐只是一种幻觉。

:我想我总是在 Pitchfork 的语言中看到的是他们总是无法做到这一点,对吗?你对写声音有自己的想法。我不认为写声音是不可能的,但我认为写声音比写其他任何东西都难。

NS :当然,我认为音乐的幻觉性质让我们真的依赖某些语言修辞,真的让我们特别依赖形容词和这种真正描述性的语言来赋予它实质。从本质上来说,我们通过使用这些东西,自动地将叙事雕刻成声音,或者我们在谈论它时,给它一些它不具备的东西——那就是语言。或者我们必须通过隐喻来谈论它,或者我们必须赋予它社会或政治的价值来做到这一点。我认为在实际的评论文章中,有一些非常正式或结构性的东西是我想要注意的。如果我们在一个段落试图做的事情中分离出某些段落,比方说评论是七个段落,你可能会有三个或四个段落只是描述专辑。你可能会有一两个段落给出某种社会或政治背景,更广泛,然后具体到艺术家的职业生涯或什么的。所以你有这些非常具体的关键议程,它们实际上被编码到音乐评论的各个段落中。这可能是一个更大的数据项目,但几乎像给那些数字或东西。

就我而言,如果我们看看这个偏差[图 2,底部],如果我们得到越来越多相似的评分评论,我也会争论这些评论的实际形状,评论的文本变得越来越相似。所以基本上我们得到了这些回流的形式,它们遵循非常特定的脚本,以相似的方式给可能相同的音乐赋予相同的乐谱。所以我的意思是,在那个关头,除了肯定一般的公关活动,还有什么意义呢?在那一点上,它就变成了一种存在主义。就像,嗯,我们为什么要写音乐?这就是为什么我认为这个钟形曲线模型会破裂。实际发生了什么?

如果你回去读一些早期的干草叉评论,有一些真正奇怪的写作。在某种程度上,这是一个实验平台,随着事情沿着轨迹发展,这条线穿过更长的轨迹,你只会得到更多的一致性。你说的关于新询价 T3 的也有点像。作为一个出版平台,我认为新的调查最初是为一些非常狂热的写作或其他东西而设计的——论战、评论、文化下层阶级自由写作的一些出口。但是当它本身成为一个机构时,你就有了为新的调查写的东西意味着什么,你就有了你最终的这种形状或这种形式——这是它实际上试图做的事情的代表。

AT :这只是评论的长度。

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

Fig. 4. During the interview, the standard deviation (bottom right) was used to measure the variance of article length. This was arguably a mistake, although arguably not: While the standard deviation is considered formally improper method for the measure of variance for non-normal distributions (like the right-skewed distributions of review length), it is considered so because of the weight it places on outliers — in this case, unusually long articles. The discussion surrounded the idea of a normalization of writing in Pitchfork. If that type of homogenization had occurred, it would essentially preclude the existence of outliers almost altogether. It’s possible that although even if formally improper, the standard deviation, given the weight it does place on outliers, is a valid measurement in this particular instance. Still, the median absolute deviation is included in this array for clarity (bottom left). It shows no such increase in variance. Regardless, both graphs refute the hypothesis at hand — that Pitchfork’s articles have become more regular in size — and either statistic was capable of momentarily disrupting a stream of criticism and prompting a consideration of Pitchfork’s virtues.

在采访过程中,标准差(右下)用于测量文章长度的方差。这可能是一个错误,但也可能不是:虽然标准偏差被正式认为是非正态分布(如综述长度的右偏分布)方差测量的不当方法,但它被认为是如此,因为它对异常值(在这种情况下,异常长的文章)施加了权重。讨论围绕着干草叉书写规范化的想法。如果这种类型的均质化已经发生,它将基本上完全排除离群值的存在。尽管形式上不合适,但考虑到标准差对异常值的权重,它可能是这种特定情况下的有效度量。

尽管如此,为了清楚起见,这个数组中包含了中值绝对偏差(左下方)。它显示方差没有这样的增加。无论如何,这两个图表都驳斥了手头的假设——Pitchfork 的文章在大小上变得更加规则——并且这两个统计数据都能够暂时打断一连串的批评,并促使人们考虑 Pitchfork 的优点。

NS :长度上去了。

:嗯,长度的方差上升了【图 4,右下】。这些年来的长度是全面的(图 4,右上方),没有真正的模式。这是所有评论的评论长度分布图(图 4,左上角)。这并不能告诉你太多,事实上中值评论大约是 700 字。但这是长度的方差。所以现在的差异比以前要大得多。

NS :是有评论还是有特写?

AS :一切都是有分数的。因此,至少就评论的规模而言,我们可能必须在这方面对他们宽容一点。这就引出了另一个问题,干草叉有什么好的地方吗?在一天结束的时候,我宁愿干草叉存在,也不愿干草叉不存在,没有任何东西可以替代它。它仍然是康泰纳仕旗下的音乐出版物,根本不用写 Sote。他们可以完全忽略这些音乐,也不会有主流出版物讨论它们。所以在看到他们的方差上升的图表中,我想借此机会说一些关于他们的好话。

可能只是因为他们出版了更多,所以基于他们出版的规模会有更多的差异。有各种各样的事情可能会发生。

AS: 但它们实际上已经趋于平稳[图 5]。现在一年大概有 1200 条评论。我不知道这两者相比如何—

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

Fig. 5

NS :很多。我是说那就像一台机器,写了那么多东西。这很酷,我是说我喜欢这个事实。我想我要强调的一件事是,我认为这个模型有一系列的假设,我认为像 Pitchforks 这样的网站以他们这样做的方式量化审美体验,我认为这就是你所说的那种叙事性的东西,它如何与其他领域中存在的某些经济模型相匹配。但我也认为它存在于可量化的列表和内容排名中,这种情况不在审查范围之内。但我认为这最终是一种资本主义的思维方式。

AT :就像美国大学已经被这个系统毁了,对吗?我自己的大学,天普大学,他们的商学院因为捏造这些数据而陷入排名丑闻。

因为他们可以通过夸大这些数字来吸引更多的钱。

:在美国新闻中拥有更高的排名所带来的全部好处。**

这是我们在几乎所有事情中都会遇到的同样的问题。在某种程度上,我几乎喜欢这种扁平化。如果说资本主义现实主义做了什么,那就是平抑了这种极端化,我们认为音乐是我们可以逃避的特殊的小东西,但当我们看到它如何在文化上改变自己时,我们看到的是同样的老一套。在这种情况下,我认为扁平化是有益的,因为它允许我们看到事物的本来面目,以及在出版和批评中使用的某些策略的动机,评论排名或其他。但是我的想法是,我们可以用很多其他的模式来谈论音乐。它必须是这个非常明显的,反映了一套非常具体的价值观吗?那是…当然,问题是,我们怎么才能爬上去呢?我们怎样才能让人们用这些术语或其他什么来写作呢?因为这就是我们所理解的。然后我们进入一个非常具体的政治讨论。

AT :这是很多数据可视化本身的问题。希望这不是我们现在正在做的事情的问题。但我为组件制作的第一件作品,就像是对顺序和数字的盲目崇拜。当你把一个数字或一种定量方法的出现与某样东西联系起来的时候,你就把它放在了遥不可及的地方,不仅仅是因为大多数人不使用这些方法,而且即使是那些真正理解这些方法的人也被它的存在所吸引,事实上你知道这种光芒来自哪里,你会情不自禁地感觉到它的温暖。

数字的出现几乎让语言变得尴尬,如果这有意义的话。说某事得到负面评价。就像今天,詹姆斯·布雷克,歌手,制作人,2010 年,2011 年我最喜欢的艺术家之一,因为他开始了这种新的制作风格,喜欢空间配音音乐,同时也是一个歌手兼作曲家,他制作了这张新专辑,他变得非常主流,我仍然尊重的少数几个干草叉作家之一发表了一篇评论,一个叫菲利普·舒尔伯恩的家伙,他给了这张唱片 5.8 分。我和他是脸书的朋友,他发了一条微博,“今天在 Twitter 上过得很糟糕”,因为他被这位艺术家的粉丝们激怒了,因为他给了这张唱片 5.8 分,而 Pitchfork 有着给他的唱片提供最佳新音乐的巨大历史。所以基本上就像,你知道他是一个非凡的作家,但 5.8 级的出现对詹姆斯·布雷克的粉丝来说是如此的可耻,以至于他们可以看看菲利普·舒尔伯恩的作品,然后就把他撕成碎片。文字变成了这种脆弱的防御,数字的存在和它如此强大的权威几乎吸引了人们去看这种语言,他们开始把它撕裂。在那一点上,这种语言实际上变得很可笑,因为你开始看它,这个数字只是在嘲笑这种语言。这个数字根本不在乎语言,整个事情就这样分崩离析了。

:谁也不在乎谁。

NS :差不多就是这诡异古怪的一对。然后你看着语言,模因开始产生,引用作者的话。如果你从中抽象出任何一句话,它看起来都很可笑。但是他有一个关于詹姆斯·布雷克职业生涯的观点,他在某种程度上做了很好的讨论。如果你只是边喝啤酒边和那个人聊他对音乐的看法——他住在巴塞罗那,在巴塞罗那的一个酒吧里,我肯定你会更开心地谈论唱片,或者实际上更多地了解他对唱片的看法。

AT :但是,你可以有一个没有号码的对话版本。去掉这个号码,你就可以在酒吧里进行那次谈话了。

再次,我认为是权威赋予了它那种耸人听闻的品质,并基本上使整个事情成为这个机器的一部分,你希望人们有那种反应,因为你想把事情放在美好的小地方并对它们进行排序。每个人都喜欢列清单。这是人类喜欢做的一件大事。我也喜欢列清单。我认为,列出一个 100 比 1 的列表,其中 1 是最好的,100 是最差的,与列出一个向各个不同方向扩散的疯狂的分形列表有很大的区别。

AT :对分类顺序的需求是如此强烈,以至于即使我们知道这个数字是扯淡,我们还是会情不自禁地对它做出反应,并以某种方式受到它的影响。

T2:我们要么庆祝它的存在,要么被它压迫。它实际上是权力的替身。它最终消除了关于音乐的语言和文字所能有效做到的细微差别,这是一个人在聆听体验中非常微妙、亲密的反映。这个数字的存在是荒谬的。这是荒谬的。就像…什么?它以最粗俗的方式困扰着写作。

:虽然数字是干草叉存在的必要条件,对吧?康泰纳仕拥有 Pitchfork 是因为 Pitchfork 公布了一个数字,人们点击就能看到。去掉这个数字,它们就不是康泰纳仕的财产了。这又回到了这个问题上—

NS :资本主义现实主义。

当然,我的意思是一切都回到那个问题上。但是问题是没有干草叉,没有任何东西可以替代它,还是有它。资本主义现实主义者对此的反应是,这实际上是你能得到的最好的了。在我们生活的这个系统的范围内,我们需要量化,测量任何时候的一切,Pitchfork 可能是你能得到的最好的版本。我是说,你还能得到什么?他妈的滚石

是的,也许是大规模的。我认为这就是为什么我们把实验主义视为次要形式。你会看到这些本土的音乐写作社区或杂志或各种类型的东西,人们蜂拥而至来解决这个问题。

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

最初发表于components . one**

用 5 行 Python 代码抓取并总结新闻文章

原文:https://towardsdatascience.com/scrape-and-summarize-news-articles-in-5-lines-of-python-code-175f0e5c7dfc?source=collection_archive---------6-----------------------

好程序员写的代码,伟大的先搜 github。

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

Photo by Thomas Charters on Unsplash

想从一群只做机器学习和可视化的数据科学家中脱颖而出?然后,您可以通过收集自己的数据集,而不是使用 Kaggle 中过时的 CSV 文件,提前一步开始。

在这篇文章中,我将向你展示如何以一种统一的方式从许多来源收集大量的新闻数据。因此,你将使用 newspaper3k 自动提取结构化信息,而不是花费数月时间为每个新闻网站编写脚本。

安装软件包:

$ pip install newspaper3k

现在让 newspaper3k 把文章刮下来,摘抄信息,给我们总结一下。

>>> from newspaper import Article>>> article = Article('https://www.npr.org/2019/07/10/740387601/university-of-texas-austin-promises-free-tuition-for-low-income-students-in-2020')>>> article.download()>>> article.parse()>>> article.nlp()

这是所有的乡亲。5 行代码,包括包导入。

如果您执行了之前的所有步骤,并且没有出现错误,您应该可以访问以下信息:

>>> article.authors['Vanessa Romo', 'Claire Mcinerny']>>> article.publish_datedatetime.datetime(2019, 7, 10, 0, 0)>>> article.keywords['free', 'program', '2020', 'muñoz', 'offering', 'loans', 'university', 'texas', 'texasaustin', 'promises', 'families', 'lowincome', 'students', 'endowment', 'tuition']

关于文本本身,您可以选择访问全文:

>>> print(article.text)University of Texas-Austin Promises Free Tuition For Low-Income Students In 2020toggle caption Jon Herskovitz/ReutersFour year colleges and universities have difficulty recruiting...

除此之外,您还可以获得内置摘要:

>>> print(article.summary)University of Texas-Austin Promises Free Tuition For Low-Income Students In 2020toggle caption Jon Herskovitz/ReutersFour year colleges and universities have difficulty recruiting talented students from the lower end of the economic spectrum who can't afford to attend such institutions without taking on massive debt.To remedy that — at least in part — the University of Texas-Austin announced it is offering full tuition scholarships to in-state undergraduates whose families make $65,000 or less per year.The endowment — which includes money from oil and gas royalties earned on state-owned land in West Texas — more than doubles an existing program offering free tuition to students whose families make less than $30,000.It also expands financial assistance to middle class students whose families earn up to $125,000 a year, compared to the current $100,000.In 2008, Texas A&M began offering free tuition to students whose families' income was under $60,000.

对于一个内置功能来说还不错。

要从所有功能中获益,包括自动订阅杂志和访问热门话题,请参考官方文档

使用 newspaper3k,您可以收集独特的数据集来训练您的模型。更重要的是,在模型准备好之后,您将有一个真实的数据馈送,因此您也将能够看到真实的性能。

首先定义一个问题,然后才搜索数据,而不是相反。试着成为一个真正的问题解决者,思考你的模型如何解决真正的商业问题,因为这是你将会得到报酬的。

如果你喜欢这篇文章,我想强调的是,你应该读一下启发我的那篇文章。

用 Scrapy 刮多页

原文:https://towardsdatascience.com/scrape-multiple-pages-with-scrapy-ea8edfa4318?source=collection_archive---------2-----------------------

一个用 Scrapy 成功完成你的网络抓取项目的完整例子

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

Tetiana Yurchenko/Shutterstock.com

在这篇文章中,我将开发一个网络爬虫,它将从myanimelist上可用的每个漫画中收集信息。为此,我们将迭代几个页面和子页面来创建一个完整的数据集。

什么是 Scrapy?

Scrapy是*“一个从网站提取你需要的数据的开源协作框架”。*

我为什么选择 Scrapy?

有几种类型的框架库允许我们进行网络抓取。尤其是 Scrapy、Selenium、BeautifulSoup,仅举几个最著名的例子。

Scrapy 是一个专门创建的工具,用于请求、抓取和保存 web 上的数据,它本身就足以构建一个健壮的 web 抓取项目,而 BeautifulSoup 是一个实用程序包,只对我们访问 web 页面的元素有用,它通常需要导入额外的库,如 requests 或 urllib2 和其他库,以具有 Scrapy 功能的范围。

此外,

  • Scrapy 强加了关于代码结构的习惯用法,这使得新手可以在网上找到非常有意义的例子,并很快掌握这个框架。
  • 我们有一个特定于 scrapy 的 Shell,在准备部署之前,它可以用来调试脚本。
  • 在一个 Scrapy 命令行中创建项目构建所需的所有附加文件(如 Django)。
  • 最后 Scrapy 非常快,可以同时刮几十页。此外,还可以调整脚本的速度或其他参数。

开始你的项目吧!

我将向你展示完成一个抓取项目所需的每个步骤,并用 Scrapy 建立你的第一个数据集,在本教程中,我们将只使用:

  • Anaconda 的命令提示符(任何其他要安装 scrapy 和 python 的命令提示符都可以)
  • Scrapy 的壳
  • Python 3.x

开始我们的项目,我们将安装 Scrapy。

pip install scrapy
​
conda install scrapy

然后,仍然在 anaconda 命令提示符下,我们将指向我们选择的文件,并告诉 Scrapy 我们想要开始一个新项目。我们将这个文件夹称为 MEDIUM_REPO。

cd /d c://path/MEDIUM_REPO
​
scrapy startproject WebCrawler

因此,Scrapy 已经创建了我的刮刀所需的每个文件,让我们来看看。其结构如下:

WebCrawler
│   scrapy.cgf
└───WebCrawler
│   │   __init__
│   │   items.py
│   │   middlewares.py
│   │   pipelines.py
│   │   settings.py
│   │
│   └───__pycache__
│   │   scrapy.cgf
│   │
│   └─── spiders
│   │   __pycache__
│   │   __init__ 
│   │   your spider here

我们需要知道什么?Scrapy 给了我们几个. py 文件,我们不一定要接触它们,但有时它会很有用,这就是你需要知道的:

  • settings.py 给了你修改每秒/每个 ip 的请求数量的权利,添加一些扩展,错误处理程序和其他一些特性
  • Pipelines.py 让你有可能编写一些管道来以你想要的格式编写你的输出,尽管 scrapy 已经有了一些内置的命令来编写 json、csv、jsonlines 等等。
  • **Items.py,**抓取的主要目标是从非结构化数据源中提取结构化数据,Scrapy spiders 可以将提取的数据以 Python dicts 的形式返回。为了定义通用的输出数据格式,Scrapy 提供了[Item](https://doc.scrapy.org/en/latest/topics/items.html#scrapy.item.Item)类。[Item](https://doc.scrapy.org/en/latest/topics/items.html#scrapy.item.Item)对象是用来收集抓取数据的简单容器。它们提供了一个类似于字典的 API,用一种方便的语法来声明它们的可用字段。这个文件就是在这里定义了那些[Item](https://doc.scrapy.org/en/latest/topics/items.html#scrapy.item.Item)
  • 允许你编写自己的蜘蛛中间件。

写你的刮刀

在这个阶段,我们将能够开始编写我们的蜘蛛。首先,让我们看看我们要抓取什么,更准确地说是我们要抓取的页面的 HTML 代码。在这个项目中,我们的目标是收集网站上所有的漫画及其相关的各种信息。因此,我们将尝试抓取的网站结构如下:

[https://myanimelist.net](https://myanimelist.net)
└───https://myanimelist.net/manga.php
│   │   page A
│   │       └─── Page 1 to n 
│   │           └───    informations of several manga
│   │   page B
│   │   page C
│   │   .... 
│   │   page Z

我们可以看到漫画是按字母顺序排序的,在每个漫画中,都有 n 个子页面,包含了具有相同字母的其他漫画。如果我们点击其中的一个页面,我们可以看到有几个漫画的子页面,包括分数、概要、标题、数量和漫画类型。

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

我们可以看到的另一点是,对于每个页面,子页面的确切数量是未知的。我们将如何处理这些多个页面和子页面呢?让我们分阶段进行。

  1. 首先,我们需要确定如何检索单个页面上的信息。
  2. 然后我们必须找出如何从一个子页面移动到下一个子页面。
  3. 最后是如何从一个字母转到另一个字母。

刮你的第一页!

让我们从一个页面开始,不管它是哪一个,我们将检索它的 URL 并通过 Scrapy 的 Shell 打开它。

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

让我们让 Scrapy 向一个 URL 发送一个请求。

url = 'https://myanimelist.net/manga.php?letter=B]'
fetch(url)

这里,我们在 anaconda 命令提示符中启用了 Scrapy shell 接口。Scrapy 在我们的请求返回给我们一个响应对象,我们将使用它来访问页面的 HTML 代码元素。

type(response)
scrapy.http.response.html.HtmlResponse

由于这个响应对象,我们将能够访问页面的特定元素。为此,我们将使用开发者工具或 google chrome 工具来检查 HTML 代码。为此,只需将自己定位在您想要右键单击的页面上,然后单击已检查。

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

我们现在可以访问该页面的源代码。我们可以看到,列表形式的第一页上的所有漫画都包含在属于类“class = " js-categories-seasonal js-block-list list”的 division 标签< div >中,我们将对该列表进行迭代,以提取每个漫画的特征。

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

#css
for sub_block in response.css('div.js-categories-seasonal tr ~ tr') :
    do_something
​
#xpath 
for sub_block in response.xpath('//div[@class="js-categories-seasonal js-block-list list"]/tr') :
    do_something
  • 标题

我们编写了第一行代码来迭代列表中的每个漫画。现在我们需要编写允许我们访问感兴趣的元素的代码。通过我们的 devs 工具,我们试图检索标题,我们可以看到它包含在一个标签< a >下,这个标签指定了一个锚或者一个超链接。

<a class="hoverinfo_trigger fw-b" href="[https://myanimelist.net/manga/4499/B_-_Wanted](https://myanimelist.net/manga/4499/B_-_Wanted)" id="sarea4499" rel="#sinfo4499">
    <strong> B - Wanted </strong> == $0
</a>

这个标题实际上链接到几个元素,一个唯一的 id,一个指向关于这个特定漫画的更多信息的 URL,以及用粗体写的标题(见:强标签)。这里,我们只需要标题,所以我们将寻找标签< strong >下的文本。要选择 HTML 代码中的特定元素,有两种常用的方法,可以通过 css 路径(参见:级联样式表)或 xpath (xpath 是一种查询语言,用于选择 XML 文档中的节点)进行访问。

#Take the first manga as illustration
sub = response.css('div.js-categories-seasonal tr ~ tr')[0]
#xpath method 
title = sub.xpath('//a[@class="hoverinfo_trigger fw-b"]/strong/text()').extract_first().strip()#css method
title = sub.css('a[id] strong::text').extract_first().strip()
print(title) 
'B - Wanted'

我们做了什么?

  • 通过语法“//”使用 xpath,我们可以选择 HTML 代码中出现的所有< a >,并指出将 URL 链接到标题的特定类,现在我们在这个标签中,所以我们可以选择粗体文本,并通过 scrapy [extract_firs](https://docs.scrapy.org/en/latest/topics/selectors.html)t方法提取它,这相当于 extract()[0]。
  • 对于 CSS 方法,我们直接在标签中使用 id,它和 URL 一样是唯一的,所以这是相同的操作。
#xpath 
synopsis = sub.xpath('//div[@class="pt4"]/text()').extract_first()
#css
synopsis = sub.css("div.pt4::text").extract_first()
  • 类型|分数|卷数

寻找分数时,我们发现了一个相当有趣的结构,其中我们感兴趣的下 3 条信息彼此相邻。让我们详细介绍一下这个结构:

<tr>
└───    <td> ... </td>
└───    <td>
│   │   └─── div
│   │   └─── a
│   │   └─── div
</td>
└─── td (type informations) </td>
└─── td (numbers of volumes informations) </td>
└─── td (rating informations) </td>
</tr>

我们的 3 条信息包含在标签< tr >中,它只是 HTML 中的一行。这一行可以包含几个单元格< td >。因此,这里有几种方法来选择可用的元素。我们可以通过指示元素在结构中的位置来访问元素,或者指示信息的特定类别,并自己索引结果。

#we can acces of the child of our 3 previous td and extract it 
#css
type_= sub.css('td:nth-child(3)::text').extract_first()
volumes=  sub_block .css('td:nth-child(4)::text').extract_first().strip()
rating =  sub_block .css('td:nth-child(5)::text').extract_first().strip()#xpath 
informations = sub.xpath("//tr/td[@class='borderClass ac bgColor0']/text()").extract().strip()
#the 3 first information are type - volumes- score  so :
type_ = d[:1]
volumes = d[:2]
rating = d[:3]

所以,写在一块,我们得到:

for sub_block in response.css('div.js-categories-seasonal tr ~ tr'):
                {  "title":  sub_block .css('a[id] strong::text').extract_first().strip(),
                "synopsis": tr_sel.css("div.pt4::text").extract_first(),
                "type_": sub_block .css('td:nth-child(3)::text').extract_first().strip(),
                "episodes": sub_block .css('td:nth-child(4)::text').extract_first().strip(), 
                "rating": sub_block .css('td:nth-child(5)::text').extract_first().strip(),
            }

我们在一页纸上收集了所有的数据。现在我们进入第二步,从当前页面过渡到下一个页面。如果我们检查允许我们访问下一个页面的图,我们会看到所有指向下一个页面的 URL 都包含在一个< span >中,它允许我们通过指示这个标签的类来对元素进行分组,我们访问超链接< a >和定义链接目的地的元素 href

response.xpath('//span[@class="bgColor1"]//a/@href').extract()
#output
['/manga.php?letter=B&show=50', 
'/manga.php?letter=B&show=100', 
'/manga.php?letter=B&show=950',
'/manga.php?letter=B&show=50', 
'/manga.php?letter=B&show=100', '/manga.php?letter=B&show=950'
]

发生了什么事?我们拿到了接下来的两页,最后一页,一式两份。如果我们更仔细地观察,我们会看到页面呈现如下:[1] [2] [3] … 20],这就是为什么我们没有获得所有的 URL,因为在[3]和[20]之间没有指向 URL 的指针。为了弥补这一点,我们将迭代页面[1]以获得[2]和[2]以获得[3]到[n],这里 n=950)。

next_urls = response.xpath('//span[@class="bgColor1"]//a/@href').extract()for next_url in next_urls:
    yield Request(response.urljoin(next_url), callback=self.parse_anime_list_page)

为了用 Scrapy 做到这一点,我们将使用一个名为[url_join](https://doc.scrapy.org/en/latest/topics/request-response.html)的函数,它将允许我们简单地将我们项目的基本 URL[https://myanimelist.net]与下一页的 URL[manga.php?letter=B&show=50]连接起来。

既然已经定义了这一步,我们仍然需要找到迭代每个字母的方法,以获得字母表中的所有漫画。仍然感谢我们应用于字母选择栏的检查工具,我们可以看到每个 URL 都包含在一个 division < div >中,并且有一个唯一的 id 指向一个导航栏。所有这些都包含在一个条目列表< li >中,最后是一个锚和一个 href(具体地说,URL 总是包含在一个 href 标签中)。

"""
we can define the xpath of every url easily thanks to navbar id 
then each url are stored in a < li > = list of item then an hyperlink tag < a > followed by a href so we can wrote that :
"""
 xp = "//div[@id='horiznav_nav']//li/a/@href"

一旦完成这些,我们就已经编写了成功完成项目所需的 99%的代码!现在有必要将所有这些形式化,以便在页面上迭代并启动我们的蜘蛛。我们主要在 shell 上工作,现在我们必须写一个集成了 Scrapy 的习惯用法的脚本。

当我们开始我们的项目时,我们定义了一个 URL,并在上面启动了一个[fetch](https://doc.scrapy.org/en/latest/topics/request-response.html)命令来发送请求,Scrapy 提出了一个与函数[Requests](https://doc.scrapy.org/en/latest/topics/request-response.html)功能相同的函数,除了发送一个请求之外,这个函数将参数[Callbacks](https://doc.scrapy.org/en/latest/topics/request-response.html)作为参数,或者我们传递另一个函数,在这个函数中,我们编写所有指向要废弃的元素的脚本。

重要的一点是,我们的 python 类必须继承scrapy . Spider 类,以便访问它的所有组件,并通过命令行授权启动蜘蛛。也可以给我们的蜘蛛命名,这将是一个启动快捷方式,使我们的任务更容易。

我们的机器人已经准备好抓取网页,所以现在你必须把它保存在蜘蛛文件夹中,如上图所示。现在让我们打开一个命令提示符,指向包含我们的蜘蛛的文件夹。

cd /d C:\Users\xxxxx\Documents\MEDIUM_REPO\WebCrawler\WebCrawler\spidersscrapy crawl Manga -o dataset_name.jsonlines

您的数据集准备好了,祝贺您!

总结

在数据是一种非常珍贵的资源的时代,知道如何创建自己的数据集可能是一笔可观的资产。这有时需要做大量的工作,但这种技能在数据科学中是必不可少的,而且它也是构建贴近您内心的开发项目的主要资产。如果你对这篇文章有任何问题或评论,请在下面随意评论。

使用 Python 和 Google BigQuery 抓取 Reddit 数据

原文:https://towardsdatascience.com/scrape-reddit-data-using-python-and-google-bigquery-44180b579892?source=collection_archive---------8-----------------------

访问 Reddit API 和 Google Bigquery 的用户友好方法

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

source

Reddit 是最古老的社交媒体平台之一,就其用户和每年产生的内容而言,它仍然保持着强劲的势头。在古老的用户界面背后,是数百万用户每天以问题和评论的形式创造的信息宝库。

在这篇文章中,我们将一步一步地看到如何使用 python 和 Google Bigquery 从 Reddit 网站获取数据。为了说明这一过程,我决定提取关于插队者的数据,这些人切断了他们的电缆连接并购买了流媒体网站订阅,因为这一现象令我感兴趣。

作为第一步,让我们了解 Reddit 网站的结构。

Reddit 中的信息是如何组织的?

这个网站被分成不同的**子栏目,**每个用户根据自己的兴趣选择他们想要订阅的子栏目。这些包括音乐子编辑区,在那里可以分享关于音乐的链接,体育子编辑区,人们可以详细谈论体育,或者在我们的例子中,人们可以讨论有线连接或他们新的流媒体订阅。

向上投票和向下投票系统是 Reddit 的精髓,因为它显示了社区成员对特定主题的一致意见。一个帖子获得的支持票越多,它在网站上的显示就越显著。值得注意的是,评论和帖子一样重要,因为它们经常成为扩展的嵌套讨论。

让我们从 Reddit 的数据收集开始

Reddit API:

而网络抓取是著名的(或臭名昭著的!)从网站收集数据的方式,很多网站都提供 API 来访问它们在网站上托管的公共数据。这是为了避免抓取机器人产生的不必要的流量,经常导致网站崩溃,给用户带来不便。甚至 Reddit 也提供这种易于访问的 API。

以下是你在这个练习中需要的东西:

  1. Python 3.x :你可以在这里下载
  2. Jupyter 笔记本电脑:我们将把它作为我们的交互控制台
  3. Reddit 账户:你必须创建一个 Reddit 账户

在获得所需主题的数据之前,您需要遵循几个步骤。

  1. 创建一个应用:

注册后的第一步是创建一个应用程序来获取 Oauth 密钥以访问数据。点击这里开始。

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

creating an app

单击创建一个应用程序,如快照所示。然后出现如下所示的对话框。

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

在对话框中输入应用程序的名称,然后单击脚本,因为我们将把它用于个人用途。确保在重定向 URL 框中输入 http://localhost:8080 。如果您需要任何澄清,您可以参考 praw 文档。现在点击底部的创建应用程序按钮。

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

现在您的应用程序已经创建好了。将您的 14 字符个人使用脚本和 27 字符密钥存储在安全的地方。现在,您已经拥有了 OAuth2 身份验证连接到 Reddit API 所需的所有凭证。

现在是时候打开 Jupyter 笔记本了!

2。建立连接

我们在这个练习中需要的包装是 praw 和熊猫。PRAW 是说唱歌手的缩写,我们将使用它向 Reddit API 发出请求。确保您已经安装了这两个软件。第一步是导入这些包

import praw
import pandas

导入包后的下一步是使用我们之前创建的凭证建立与 Reddit API 的连接。Client_id 将是您的 14 个字符的个人使用脚本密钥,client_secret 是您的 27 个字符的秘密密钥。用户名和密码是您的 Reddit 帐户凭据。其余的代码将保持不变。

reddit = praw.Reddit(user_agent='Comment Extraction (by /u/USERNAME)',client_id='**********',client_secret="***********",username='********', password='*******')

通过运行上面的代码片段,我们将建立连接并将该信息存储在一个名为 reddit 的变量中。

3。获取数据

正如我们之前所讨论的,我们将专注于为“cordcutter”子编辑获取数据。

标题、分数、url、id、评论数量、创建日期、正文是从 Reddit API 获取数据时可用的字段。但是在我们的分析中,我不会考虑任何时间方面,我们主要关注的是从子编辑中获取正文(评论)。参考 praw 文档了解不同种类的实现。这里,我将代码限制为所需的输出,它只是所有注释的正文文本。

为了让所有的评论都包含嵌套回复,我必须想出一个包含 3 个部分的嵌套代码。

获取评论 id 列表

comm_list = []
header_list = []
i = 0
for submission in reddit.subreddit('cordcutters').hot(limit=2):
    submission.comments.replace_more(limit=None)
    comment_queue = submission.comments[:]

在这个循环中,首先我们在循环开始时获取每个提交信息,然后提取所有的评论 id 并将它们存储在 list 中。

在这里。hot(limit)可以是任何数字,具体取决于您的要求。我在这里将它设置为 2 来说明输出,但是将其设置为 None 将获取 cordcutter subreddit 中所有的顶级提交。replace_more(limit=None)将帮助我们考虑包含嵌套回复的评论。

该循环的输出如下所示:

[Comment(id='ed5ssfg'),
  Comment(id='ed64a72'),
  Comment(id='edth3nc'),
  Comment(id='ed680cg'),
  Comment(id='ed699q2'),
  Comment(id='ed80ce8'),
  Comment(id='edau9st'),
  Comment(id='edcx477'),
  Comment(id='ee0fp3g'),
  Comment(id='ed5qrvh')]

获取所有嵌套回复

我们就要得到我们想要的数据了。在这部分代码中,我们将获得之前获得的每个注释 id 的主体。如果评论有嵌套回复,它将进入下一个循环,并以类似的方式提取信息。

while comment_queue:
    header_list.append(submission.title)
    comment = comment_queue.pop(0)
    comm_list.append(comment.body)
    t = []
    t.extend(comment.replies)
    while t:
        header_list.append(submission.title)
        reply = t.pop(0)
        comm_list.append(reply.body)

到目前为止,我们从 Reddit 下载了评论,并且需要一些预处理来将其下载为 csv 格式。

下面是经过整理的代码

comm_list = []
header_list = []
i = 0
for submission in reddit.subreddit('cordcutters').hot(limit=2):
    submission.comments.replace_more(limit=None)
    comment_queue = submission.comments[:]  # Seed with top-level
    while comment_queue:
        header_list.append(submission.title)
        comment = comment_queue.pop(0)
        comm_list.append(comment.body)
        t = []
        t.extend(comment.replies)
        while t:
            header_list.append(submission.title)
            reply = t.pop(0)
            comm_list.append(reply.body)df = pd.DataFrame(header_list)
df['comm_list'] = comm_list
df.columns = ['header','comments']
df['comments'] = df['comments'].apply(lambda x : x.replace('\n',''))
df.to_csv('cordcutter_comments.csv',index = False)

您可以在我的 github 资源库中找到代码的最终版本。

[## akhilesh-Reddy/使用 Reddit 数据的电缆切割升降机和情感分析

从 Reddit 抓取数据并执行命名实体识别,对评论进行主题建模以了解公众…

github.com](https://github.com/akhilesh-reddy/Cable-cord-cutter-lift-and-sentiment-analysis-using-Reddit-data)

我们的最终输出如下所示:

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

我们有自己的数据,但这里有一个挑战。一般来说,使用 Reddit API 获取几个月的历史数据需要更多的时间。感谢pushshift . io(Reddit 上的又名 /u/Stuck_In_The_Matrix )的杰森·迈克尔·鲍姆加特纳,我们清理了多年的 Reddit 历史数据,并将其存储在 Bigquery 中,这是本文的第二部分。

big query 中的 Reddit 数据:

对于那些不知道 Bigquery 是什么的人来说,

Google BigQuery 是一个企业数据仓库,它通过使用 Google 基础设施的处理能力实现超快速 SQL 查询来解决这个问题。

最好的部分是查询这些数据将是免费的。Google 免费提供第一个 10GB 的存储和第一个 1 TB 的查询内存,作为免费层的一部分,我们的任务需要不到 1 TB 的内存。

让我们看看如何查询这些信息。

首先点击这个 Google BigQuery 链接开始。Google 会自动使用您浏览器中存储的 Google 凭据让您登录。如果这是您第一次使用 BigQuery,将会出现一个对话框,要求您创建一个项目。

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

点击创建一个项目按钮。

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

为该组织命名,然后单击顶部的 create project。

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

给出项目的名称,您可以暂时保留位置框。然后点击创建。现在您已经创建了您的项目,一个仪表板出现在屏幕上。

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

现在在这之后,点击 链接 。这将在您创建的项目下打开 reddit 数据集。在左侧,您将看到在模式名 fh-bigquery 下每个月更新的数据集。

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

让我们运行查询,从表中获取一个月的数据。

select subreddit,body,created_utc
from `fh-bigquery.reddit_comments.2018_08` 
where subreddit = 'cordcutters'

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

这将得到所有关于“割线者”subreddit 的评论。但是请确保您没有选中选项中的“使用遗留 sql”复选框,因为上面的代码片段是在标准 SQL 中。但是,您可以选择您所选择的 sql,并相应地对代码进行更改。

这是结果的样子,您可以通过单击“下载为 csv”按钮下载 CSV 格式的结果。

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

在这里,我只是专注于获取我们需要的数据。如果你想在 bigquery 上更多地使用 reddit 数据,你可以参考 Max Woolf 的这篇文章,这篇文章更详细地介绍了 Bigquery 中的 Reddit 数据。

总结:

在这篇文章中,我们看到了如何创建 OAuth2 凭据以连接到 Reddit,向 Reddit API 发出数据请求以获取最新数据,并通过 Google Bigquery 快速查询历史数据。

除了通过 API 和 Bigquery 获取数据,您可能会发现使用 Selenium 和 python 进行 web 抓取很有趣。下面是一篇由 UT Austin 的同学( Atindra Bandi )写的文章。

[## 使用 Selenium-Python 进行 Web 抓取

在这篇文章中,你将学习如何浏览一个网站的多个页面并收集大量数据…

towardsdatascience.com](/web-scraping-using-selenium-python-8a60f4cf40ab)

那都是乡亲们!请继续关注我在未来几周发布的关于推荐系统、数据科学统计和数据可视化的一系列文章的更新。

收集和探索体育博彩数据——套利可能吗?用代码进行实际分析。

原文:https://towardsdatascience.com/scraping-and-exploring-sports-betting-data-is-arbitrage-possible-a-hands-on-analysis-with-code-2ba656d7f5b?source=collection_archive---------4-----------------------

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

Photo by Richard Boyle on Unsplash

如何下载实时体育博彩时间序列数据,解析它并使用 Python 分析套利机会

谁不想拥有一台无风险盈利机?我想每个人都想有一个。利用不同市场或博彩公司之间的价格差异(在这种情况下是博彩利率差异)的做法也被称为套利。这个想法是在样本空间的每一个结果上下赌注,并在每一个案例中产生利润。在足球比赛中,你可以打赌哪个玩家赢了一场比赛,也就是说,样本空间将由三种结果组成:“玩家 1 赢”、“平局”和“玩家 1 输”。

在我们深入分析之前,我们应该先看看数据收集和我们将涉及的更多主题:

  1. 网页抓取现场投注数据( BeautifulSoup )
  2. 将结果存储在数据帧 ( 熊猫)中
  3. 自动化带有功能的刮削过程
  4. 使用 matplotlib-pyplot 的结果可视化
  5. 首先进行套利分析和利润计算

关于这个数据,我已经提出了许多其他令人兴奋的主题,但是我现在将它们排除在范围之外。(可能会在下一篇文章中跟进。)

  • 来自多个网站的网络抓取和数据整合
  • 衍生投注/交易策略的规则,包括模拟和评估自动化策略的性能
  • 驱动因素分析:是什么驱动了下注率的演变(可能包括来自会议直播行情的文本分析)
  • 大概还有很多更有趣的话题;很高兴听取您的意见

**法律免责声明:**我不是法律专家,也不在这里提供任何行动建议,只是纯粹的技术解释。网站的大规模抓取会导致高流量,从而加重他们的负担。我相信,如果你在访问网站,你应该始终考虑他们的服务条款,最好事先获得像刮擦这样的项目的许可。此外,我不提倡赌博,不管是哪种赌博。

1.网络抓取现场投注数据(BeautifulSoup)

为了收集数据,我们将使用 library BeautifulSoup。我已经通过命令行下载并安装了它:

pip 安装美丽组 4

安装完成后,我们可以开始导入所有相关的库。

from bs4 import BeautifulSoup
import urllib.request
import re

我们现在可以使用它们来检索任何页面的源代码并解析它。
我选择了德国博彩网站 tipico.de 的现场投注页面。

url = “[https://www.tipico.de/de/live-wetten/](https://www.tipico.de/de/live-wetten/)"try:
 page = urllib.request.urlopen(url)
except:
 print(“An error occured.”)soup = BeautifulSoup(page, ‘html.parser’)
print(soup)

上面的代码检查它是否可以访问页面,然后打印出页面的整个 html 源代码。按照惯例,这将被分配给一个名为“soup”的变量,长度大约为 200-300 页 A4 纸,取决于当前在线下注的数量。

下一步,我们希望以一种结构良好的方式只提取相关的信息。让我们看看网站,看看我们关注哪些信息。

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

首先,我们可以尝试提取用绿色标记的七个值:时间、玩家的名字、当前分数和每种可能结果的比率。这里,比率 1 对应于玩家 1 赢,比率 2 对应于平局,比率 3 对应于玩家 1 输。要做到这一点,用浏览器检查元素是很方便的(右击并用 Chrome ’ Inspect ')。

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

我们看到费率存储在“c_but_base c_but”类的按钮中。为了提取费率,我们将使用 soup.find_all 来获取该类的所有按钮。

regex = re.compile(‘c_but_base c_but’)
content_lis = soup.find_all(‘button’, attrs={‘class’: regex})
print(content_lis)

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

为了去掉 html 代码,我们使用。getText()函数,然后将所有按钮的值存储在一个列表中,并删除换行符和制表符。

content = []
for li in content_lis:
 content.append(li.getText().replace(“\n”,””).replace(“\t”,””))
print(content)

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

其他变量可以类似地查询。你可以在 Github 上的我的笔记本里找到细节。如果有不清楚的地方,不要犹豫问问题。

2.将结果存储在数据框中(熊猫)

有了原始的和解析过的数据,我们现在想以一种实用的方式来构造它。我们理解游戏有一个时间,两个玩家,一个分数,每排十一个比率。至于比率,我们只想存储“谁赢了比赛”的三个比率和“谁进了下一个球”的三个比率,因为这些在大多数下注方上都是可用的,并且以后将允许我们有高度的可比性。

N_games = 10 # number of games observed, say we want the first 10
N_players = 2 # number of players per game
N_outcomes = 11 # number of possible outcomes (Win, lose, tie, Next goal etc.)
df = []
for i in range(N_games):
    df.append([datetime.now(), content_names[i*N_players], content_names[1+i*N_players], content_minute[i],
        content_score[i], content[i*N_outcomes], content[1+i*N_outcomes], content[2+i*N_outcomes],
        content[6+i*N_outcomes], content[7+i*N_outcomes], content[8+i*N_outcomes]])pdf = pd.DataFrame(df, columns = ['Time', 'Player_1', 'Player_2', 'MinuteOfGame', 'Score', 'Win_1', 'Win_X', 'Win_2', 'NextGoal_1' , 'NextGoal_X' , 'NextGoal_2' ])pdf.head()

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

(注:在我的笔记本里,还有两个变量,j 和 k,它们是用来除 bug 的,当每场比赛多了一行‘上半场比赛结果’。为了简单起见,我将它排除在描述之外。)

3。具有功能的刮削过程的自动化

要多次重复这个刮削过程,可以方便地写成一个函数:

**def get_soccer_rates_tipico**():
    """
    This function creates a table with the live betting information,
    this includes a timestamp, the players, the score and the rates
    for each party winning and scoring the next goal.

    Arguments:
    None

    Returns:
    pdf -- pandas dataframe with the results of shape (N_games, 11)
    """

   ... FULL CODE ON GITHUBreturn pdf

返回的表格的形状取决于当前正在进行的游戏的数量。我已经实现了一个功能,查找第一个网球比赛条目,以计算实况足球比赛的总数,并获得所有比赛。

现在我们可以把它写成一个循环,以固定的时间间隔重复这个刮擦函数。

**def repeat_scraping**(timedelay, number_of_scrapes, filename = 'bet_rates_scraping_tipico.csv'):
    """
    This function repeadetly calls the scraping function to create a timeseries of scraping data. The time interval between scrapes and number of scrapes in total are taken as argument. The result is saved in a csv-file.

    Arguments:
    timedelay -- delay between each scrape request in seconds (min. 15 sec recommended due to processing time) number_of_scrapes --  number of scrape requests 

    Returns:
    Void
    """        
           ... FULL CODE ON GITHUB dataframe = pdf.to_csv(filename, index=False)

# Check processing time and add sleeping time to fit the timedelay
        time_run = time.time() - start_time
        time.sleep(timedelay - time_run)

请注意,页面的加载和解析可能需要 10 秒钟。我们可以使用时间库来跟踪我们的函数从睡眠时间中减去它需要多长时间来调整时间延迟(假设所有查询花费的时间大致相同)。

我们可以调用这个函数来抓取整个游戏,例如 15 秒的时间延迟和 500 个查询,即覆盖 125 分钟。

repeat_scraping(15, 500, 'scraping_500x15s.csv')

4。使用 matplotlib-pyplot 对结果进行可视化和分析

作为第一步,在导入数据后,我们需要做一些数据清理。这包括用零填充所有汇率的 NaNs,用点替换逗号,并将它们转换为浮点类型。

dataframe = pd.read_csv('scraping_500x15s.csv', encoding = 'unicode_escape')
dataframe = dataframe.fillna(0)
ratecols = ['Win_1','Win_X','Win_2','NextGoal_1','NextGoal_X','NextGoal_2']
dataframe[ratecols] = dataframe[ratecols].apply(lambda x: x.str.replace(',','.')).astype(float)

因为我们希望每分钟查询多次,所以“游戏的一分钟”不够精确,因此,我们添加了查询时间戳。

dataframe['Time_parsed'] = 0
# Check for dates without milliseconds and add .000 to have a consistent formatting
dataframe.Time.iloc[np.where(dataframe.Time.apply(lambda x: True if len(x) == 19 else False))] \
= dataframe.Time.iloc[np.where(dataframe.Time.apply(lambda x: True if len(x) == 19 else False))].apply(lambda t: t + ".000")
dataframe.Time_parsed = dataframe.Time.apply(lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S.%f').time())
dataframe = dataframe.drop(['Time'], axis=1)

现在,我们可以探索第一场比赛的数据并可视化结果。让我们看看牌桌上的第一位玩家:

df1 = dataframe[dataframe[‘Player_1’] == dataframe[‘Player_1’][0]]
df1

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

我们现在有拜仁慕尼黑 vs 1 的数据。科隆俱乐部比赛从第 5 分钟开始,每 15 秒一次。下面的图表显示了下一个进球得分率的变化。我在 y 轴上使用了对数标度来计算超过 30 的比率。此外,我还加入了一条比率为 3 的水平线,表明了一种简单的套利形式:如果所有报价都大于 3,那么你可以通过对所有三种结果进行均匀分布的押注(例如,每人 100 €)来产生无风险利润。

# Data for plotting
t = df1.Time_parsed.values
w1 = df1.NextGoal_1.values
w2 = df1.NextGoal_X.values
w3 = df1.NextGoal_2.values# Plot setup
fig, ax = plt.subplots(figsize=(15, 6))        
ax.plot(t, w1, marker ='', label = 'Player 1 scores next' ,color = 'green', linewidth = 2)
ax.plot(t, w2, marker ='', label = 'No more goals', color = 'orange', linewidth = 2)
ax.plot(t, w3, marker ='', label = 'Player 2 scores next', color = 'red', linewidth = 2)
plt.axhline(y=3., label = 'Critical line', color='grey', linewidth = 2, linestyle='--') # Line for arbitrage detectionax.set(xlabel='Time', ylabel='Betting rates', title=str(np.unique(df1.Player_1)[0]) + ' vs ' + \
               str(np.unique(df1.Player_2)[0]) + ': Rates for "Who scores next?"')
ax.grid()
plt.legend()ax.set_yscale('log')

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

在我的笔记本里,你会发现一个自动为所有游戏创建剧情并保存为图片的功能。

5.首先进行套利分析和利润计算

回到我们寻找套利交易的想法,很可能不太可能在一个网站上找到它们。我相信利用多个庄家之间的信息差异实现套利投注的可能性更大。但是,我们现在将只研究对 Tipico 数据的分析。这种分析可以很容易地扩展到多个网站。

一个简单的数学问题:
假设 n 是一个事件的可能结果的数量,q_i 是每个结果的比率,那么如果所有 1/q_i 之和小于 1,套利是可能的。

df2['Check_a_1'] = df2.Win_1.apply(lambda x: 1/x)
df2['Check_a_2'] = df2.Win_X.apply(lambda x: 1/x)
df2['Check_a_3'] = df2.Win_2.apply(lambda x: 1/x)
df2['Check_a_sum']=0
df2['Check_b_1'] = df2.NextGoal_1.apply(lambda x: 1/x)
df2['Check_b_2'] = df2.NextGoal_X.apply(lambda x: 1/x)
df2['Check_b_3'] = df2.NextGoal_2.apply(lambda x: 1/x)
df2['Check_b_sum']=0
df2['Check_a_sum'] = df2.Check_a_1 + df2.Check_a_2 + df2.Check_a_3
df2['Check_b_sum'] = df2.Check_b_1 + df2.Check_b_2 + df2.Check_b_3
df2['Arbitrage_flag']=0
arb_idx = np.unique(np.append(np.where(df2.Check_a_sum <= 1)[0],np.where(df2.Check_b_sum <= 1)[0]))
df2.Arbitrage_flag[arb_idx] = 1

如果我们想获得一个独立于结果的利润,我们需要根据利率来分配赌注。当你考虑利率 q 乘以金额 s 等于利润 p 以满足 *p_i = p_j,*你得到 s_j = q_i/q_j * s_i。

# Give the first bet the weight of 1 and adjust the other two bets accordingly
df2['Win_1_betting_fraction'] = 1
df2['NextGoal_1_betting_fraction'] = 1
... FULL CODE ON GITHUB
df2['Win_profit_percentage'] = df2.Win_1 * df2.Win_1_betting_amount * 100 - 100

在我收集的数据中,我发现了以下例子:

下一个进球得分率:
球员 1: 1.70
不再进球:4.70
球员 2: 7.00

这就导致了如下投注金额分布:
投注 1: 62.32%
投注 2: 22.54%
投注 3: 15.14%

这导致了 5.9%的确定利润。

(在我看来很奇怪,我在一个单一的网站上找到了套利的机会。可能是抓取数字时出现了错误,我会对此进行调查。)

正如所展示的,这个过程使你能够计算出一个赌注组合的确定利润。现在就看你自己去寻找积极的价值观了!

包扎

在本文中,您可以学习如何使用 Python 和 BeautifulSoup 加载和解析 web 页面,只提取想要的信息并将其加载到结构化数据表中。为了提取时间序列,我们研究了如何将其实现为函数,并以固定的时间间隔重复我们的查询。之后,我们编写代码来自动清理数据,然后进行可视化和额外的计算,使数据可以被解释。

我们已经看到,套利赌博很可能是可能的——如果不是在一个网站上,那么通过与多家博彩公司联合下注。(请注意,我不是在推广赌博和/或网络搜集,即使是套利交易也可能存在风险,例如延迟或取消交易。)

非常感谢您花时间阅读这篇文章!

我非常感谢并欢迎您的反馈和意见。
你可以通过 LinkedIn 联系我:https://www.linkedin.com/in/steven-eulig-8b2450110/
……你可以在这里找到我的 github 包括 Jupyter 笔记本:
https://github.com/Phisteven/scraping-bets

干杯,
史蒂文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值