TowardsDataScience-博客中文翻译-2020-十五-
TowardsDataScience 博客中文翻译 2020(十五)
统计学导论—第一部分
想象给了你一些你不知道的问题的答案。
如果你曾经翻到笔记本的最后一页,读到一些有趣的事实和陈述,比如“一个普通人一生中行走的距离相当于绕地球两圈”,请举手。我们中的许多人都对给出的统计数据感兴趣。难道不是吗?我当然这么认为,从大量定量数据中解读有用信息的艺术(使用基于数学的方法)就是统计学。
在统计学中,我们总是对研究大量的人或物体感兴趣。
人群 —所有拟研究对象的集合。
样本 —我们为了对总体做出推断而研究的总体子群。
参数 —参数是总体的数字属性。
统计量 —统计量是样本的数值属性,用于估计总体的相应参数。示例包括均值、中值、众数、标准差等。
例如,假设您想知道某个特定杂志的订阅者的平均收入,这是一个总体参数。你随机抽取 100 名订户,并确定他们的平均收入是₹27,500(一个统计数字)。你得出结论,人口平均收入μ也可能接近₹27,500。这是统计推断的一个例子。
如何挑选样本?
- 样本应该永远是总体的真实代表。
- 样本应涵盖所有地区/所有类型的人口。
选择样本的不同方法有:
简单随机抽样:
简单随机抽样是一种抽样技术,其中总体中的每个项目都有均等的机会和可能性在样本中被选中。在这里,项目的选择完全取决于机会或概率,因此这种抽样技术有时也被称为机会法。
人们是随机挑选的。
整群抽样:
当自然群体(年龄、性别等)出现时,在统计中使用整群抽样..)存在于一个种群中。整个群体被细分为群或组,然后从每个组中收集随机样本。
- 单阶段聚类采样:使用每个所选聚类中的所有元素。
- 两阶段整群抽样:对选定的整群应用随机抽样技术。例如,一旦您决定了您的分类,您可以使用简单的随机抽样从这些选择的分类中选择您的
选择聚类 3 和聚类 1。
简单的随机抽样应用于聚类 3 和聚类 1。
分层抽样:
这种技术基于相似性将群体的元素划分为小的子群(层),使得组内的元素是同质的,而形成的其他子群中的元素是异质的。然后从这些地层中随机选择元素。我们需要有关于人群的先验信息来创建子群。
从每个阶层中随机选择。
我们如何描述和总结数据?
让我们假设您被要求分析表格形式的网飞用户数据,并回答以下问题。
用表格形式很难回答哪怕是简单的问题。
资料来源:PadAI 四分之一实验室
20-25 岁年龄段的用户看电视节目的最少/最多时间是多少?
工作时间较短(5-10 小时)或较长(60-70 小时)的用户多吗?
这就是描述性统计发挥作用的地方。
描述性统计是对给定数据集进行概括的简要描述性系数,该数据集可以是总体的代表,也可以是总体的样本。
不同类型的数据:
数据通常有两种类型。
- 定性 —名词性和序数。
- 定性数据是用 有限离散类描述对象的数据。 例子包括颜色、图案等。
- 没有自然排序的定性数据是名义上的。
- 具有自然排序的定性数据是有序的。
- 定量 —离散和连续
- 定量数据是用 数值描述对象的数据。
- 只能取有限个数值的定量数据是离散的(整数或整数)。
- 定量数据可以取有限个数值,以及分数值,是连续的(实数)。
描述定性数据
定性数据的典型特征是重复值。
频率图:
- 一个值出现的总次数被称为频率。
- 数据的频率可以用频率表来描述。
- 表格有点老派,因此频率图用于可视化频率。
- 当值较多时,频率图变得难以处理。
- 因此,根据频率对数据进行分类有助于更好的可视化。
- 有许多类型的频率图可用。用法取决于需要回答的问题。
图片来源:NIST
描述定量数据
- 直方图用于描述定量数据。
- 直方图中 x 轴上的值有一个自然的顺序。
- 如果 x 轴上有许多值,我们可以使用容器大小概念来使用类间隔。随着仓大小的增加,粒度受到很少细节的影响。
- 理想的箱大小揭示有意义的模式既不隐藏也不揭示太多数据。
- Bin 大小取决于感兴趣的领域和所需的洞察力。
茎和叶图
茎叶图是一种显示某类值出现频率的方法。你可以为这些值制作一个频率分布表或直方图,或者你可以使用一个茎-叶图,让数字本身显示几乎相同的信息。例如,假设您有以下值列表:12,13,21,27,33,34,35,37,40,40,41。
你可以做一个频率分布表,显示你有多少个十岁、二十岁、三十岁和四十岁。
你可以做一个柱状图,它是一个显示发生次数的条形图,每一类都是十次、二十次、三十次和四十次。
频率分布表和直方图的缺点是,虽然每个类别的频率很容易看到,但原始数据点已经丢失。例如,您可以判断出,列表中一定有三个 40 多的值,但是无法从表格或直方图中判断出这些值可能是多少。另一方面,您可以为相同的数据绘制茎和叶图。
“stem”是包含十位数字的左侧列。“叶子”是右栏中的列表,显示了 10、20、30 和 40 的所有一位数。如你所见,原始值仍然可以确定;你可以从底部的叶子看出,四十年代的三个数值分别是 40,40 和 41。
我希望你理解了所解释的概念。你可以在这里阅读这篇文章的下一部分。
Apache Flink 流处理简介
探索 Apache Flink 的分布式流处理引擎的功能!
在许多应用领域,大量的流数据是从不同的来源生成的,例如,用户在网上的活动、来自物联网(IoT)设备的测量、来自金融服务的交易以及位置跟踪源。这些数据流(无界的)过去通常存储为数据集(有界的),稍后由批处理作业进行处理。尽管由于数据的时间价值,这在某些情况下不是一种有效的方式,但实时处理是企业所希望的,以使他们能够从数据中获得洞察力,并在数据产生时主动响应变化(运动中))。
为此,必须使用实时流处理器更新应用程序,使其更加基于流。这就是 Apache Flink 的用武之地;Flink 是一个用于有状态、大规模、分布式和容错流处理的开源框架。
这篇博客文章概述了 Apache Flink 及其用于流应用程序的关键特性。它重点介绍了 Flink 的 DataStream API,并探讨了一些底层的架构设计概念。
这篇文章的大部分细节都是基于我在参与 datAcron EU 研究项目期间在 Flink 的亲身经历,本文对此进行了总结。
Distributed Online Learning System Archircture using Apache Flink.
作者图片|图片来自 一种针对运动事件流的模式预测的分布式在线学习方法 。
Apache Flink 越来越受欢迎,并被用于生产中,以构建大规模数据分析和处理海量流数据的组件,其中它为世界上一些要求最苛刻的流处理应用程序提供动力,例如,它是阿里巴巴搜索引擎的重要组件。
Apache Flink 概述
Apache Flink 是一个开源平台,提供可伸缩、分布式、容错和有状态的流处理能力。Flink 是最新和最具开拓性的大数据处理框架之一。
Apache Flink 允许从不同来源接收大量流数据(高达数 TB ),并在将派生的流推送到其他服务或应用程序(如 Apache Kafka、DBs 和 Elastic search)之前,在多个节点上以分布式方式进行处理。简单地说,Flink 管道的基本构件:输入、处理和输出。其运行时以容错方式支持极高吞吐量的低延迟处理。Flink 功能能够实时洞察流数据和基于事件的功能。Flink 支持流数据的实时数据分析,非常适合流数据的连续提取-转换-加载(ETL)管道以及事件驱动的应用程序。
它给出了流数据和批处理数据的处理模型,其中批处理模型被视为流模型(即有限流)的特例。Flink 的软件栈包括分别用于处理无限和有限数据的数据流和数据集 API。Flink 提供了对数据流或数据集的多种操作,如映射、过滤、分组、更新状态、连接、定义窗口和聚合。
Flink 的两个主要数据抽象是数据流和数据集,它们表示数据元素的只读集合。元素列表在数据集中是有界的(即有限的),而在数据流的情况下是无界的(即无限的)。
Flink 程序由在 Flink 核心上执行的数据流图(即,有向非循环图 DAG)表示,Flink 核心是分布式流数据流引擎。数据流图由有状态操作符和中间数据流分区组成。每个操作符的执行由多个并行实例处理,其数量由并行级别决定。每个并行操作符实例在计算机集群中的机器上的独立任务槽中执行。下图显示了 Flink 应用程序的数据流图示例。
Apache Flink-Flink中的并行数据流图
以下是对 Flink 主要特性的简要描述:
- 健壮的有状态流处理:Flink 应用程序能够处理需要上下文状态的业务逻辑,同时使用其数据流 API 以任何规模处理数据流
- 容错:Flink 提供了一种基于定期异步检查点的故障状态恢复机制(将内部状态保存到外部持久存储,如 HDFS)
- 恰好一次一致性语义:Flink 的核心确保在失败的情况下,流中的每个事件都恰好被提交和处理一次
- 可扩展性:应用程序被并行化,以扩大或缩小处理任务的数量
- 内存性能:Flink 应用程序通过访问本地(通常在内存中)状态来执行所有计算,产生非常低的处理延迟
- Flink 提供了与各种数据源的无缝连接,包括 Apache Kafka、Elasticsearch、Apache Cassandra、Kinesis 等等
- 灵活的部署:Flink 可以部署在各种集群环境上,比如 YARN、Apache Mesos 和 Kubernetes
- 复杂事件处理(CEP)库,用于检测数据流中的模式(即事件序列)
- Java 和 Scala 中流畅的 API
- 与 Spark 流的微批处理模型相比,Flink 是一个真正的流引擎
摘要
在这篇博文中,我们介绍了作为 Flink 框架构建块的高级流处理组件。简而言之,Apache Flink 是一个强大的系统,用于实现事件驱动、数据分析和 ETL 管道流应用程序,并大规模运行它们。在这篇文章中,我仅仅触及了表面,我鼓励你查看 Apache Flink 的文档。
Apache Flink——数据流上的有状态计算
资源:
(1) 艾哈布·卡达赫、迈克尔·莫克、埃利亚斯·阿列维佐斯和格奥尔格·富克斯。基于 Apache Flink 的运动事件流模式预测的分布式在线学习方法。在 2018 年经济技术发展局/ICDT 研讨会上。
[## Blink:阿里巴巴如何使用 Apache Flink
在电子商务网站上,是什么造就了一个伟大的搜索引擎?实时的结果,就像…
www.ververica.com](https://www.ververica.com/blog/blink-flink-alibaba-search)
[## 阿帕奇弗林克培训
Apache Flink 是一个用于可伸缩流和批处理数据处理的开源平台。它提供了富于表现力的 API 来…
training.ververica.com](https://training.ververica.com/) [## 扩展雅虎!流式基准测试
2017 年 12 月 18 日更新:在这篇初始帖子发布近两年后,我们在另一篇文章中讨论了雅虎流媒体基准测试…
www.ververica.com](https://www.ververica.com/blog/extending-the-yahoo-streaming-benchmark)
支持向量回归机简介
使用支持向量机进行回归
支持向量机在分类问题中是众所周知的。然而,在回归中使用支持向量机并没有很好的记录。这些类型的模型被称为支持向量回归(SVR)。
在本文中,我将介绍 SVR 与其他回归模型相比的用处,深入研究算法背后的数学,并提供一个使用波士顿房价数据集的示例。
简单线性回归
在大多数线性回归模型中,目标是最小化误差平方和。以普通最小二乘法(OLS)为例。具有一个预测值(特征)的 OLS 的目标函数如下:
其中,yᵢ是目标,wᵢ是系数,xᵢ是预测值(特征)。
OLS 对波士顿房价的预测
Lasso、Ridge 和 ElasticNet 都是这个简单方程的扩展,带有一个额外的惩罚参数,旨在最小化复杂性和/或减少最终模型中使用的特征数量。不管怎样,和许多模型一样,目标是减少测试集的误差。
然而,如果我们只关心在一定程度上减少误差呢?如果我们不在乎我们的误差有多大,只要它们在可接受的范围内,会怎么样?
以房价为例。如果我们认为预测在一定的金额范围内——比如说 5000 美元——是可以接受的,那会怎么样呢?只要误差在这个范围之内,我们就可以在寻找预测值时给我们的模型一些灵活性。
SVR FTW
输入支持向量回归。SVR 让我们可以灵活地定义模型中可以接受的误差,并找到合适的线(或更高维的超平面)来拟合数据。
与 OLS 相反,SVR 的目标函数是最小化系数——更具体地说,是系数向量的 l 2 范数——而不是平方误差。误差项改为在约束中处理,其中我们将绝对误差设置为小于或等于指定的裕量,称为最大误差ϵ(ε)。我们可以调整 epsilon 来获得我们的模型所需的精度。我们新的目标函数和约束如下:
最小化:
约束:
说明性示例:
简单 SVR 的说明性示例
让我们在数据集上尝试简单的 SVR。下图显示了训练好的 SVR 模型对波士顿房价数据的结果。红线代表最佳拟合线,黑线代表误差幅度,ϵ,我们将其设置为 5($5000)。
基于ϵ=5 的波士顿房价 SVR 预测
你可能会很快意识到这个算法并不适用于所有的数据点。该算法尽可能好地解决了目标函数,但是一些点仍然落在边界之外。因此,我们需要考虑比ϵ.更大的误差的可能性我们可以用松弛变量做到这一点。
给我们自己一些空间(和另一个超参数)
松弛变量的概念很简单:对于任何落在ϵ之外的值,我们可以用ξ来表示它与边距的偏差。
我们知道这些偏差有可能存在,但是我们仍然希望尽可能地减少它们。因此,我们可以将这些偏差添加到目标函数中。
最小化:
约束:
例证:
带有松弛变量的支持向量回归的示例
我们现在有了一个额外的超参数, C ,,我们可以对其进行调整。随着 C 的增加,我们对ϵ以外积分的容忍度也在增加。当 C 接近 0 时,容差接近 0,方程就变成了简化的(尽管有时不可行)方程。
让我们设置 C =1.0,重新训练上面的模型。结果绘制如下:
用ϵ=5,C=1.0 的 SVR 预测波士顿房价
寻找 C 的最佳值
上述模型似乎更符合数据。我们可以更进一步,在 C 上进行网格搜索,以获得更好的解决方案。让我们定义一个评分标准,ε内的 %。该指标衡量测试集中的总点数有多少落在我们的误差范围内。我们还可以监控平均绝对误差( MAE )如何随 C 变化。
下面是网格搜索结果图,x 轴上的值为 C ,左右 y 轴上的值分别为ε和 MAE 内的值为 %。
C 语言网格搜索
我们可以看到, MAE 一般随着 C 的增加而减少。然而,我们看到ε指标中的 %出现最大值。因为我们这个模型的最初目标是在我们的误差范围($5000)内最大化预测,我们想要找到在ε内最大化 %的 C 的值。因此, C =6.13。
让我们用我们最终的超参数,ϵ=5, C =6.13,建立最后一个模型。
用ϵ=5 的 SVR 预测波士顿房价,C=6.13
如上图所示,正如预期的那样,这个模型又比以前的模型有所改进。
结论
SVR 是一种强大的算法,允许我们通过可接受的误差 margin(ϵ和调整我们对超出可接受误差率的容忍度来选择我们对误差的容忍度。希望本教程已经向您展示了 SVR 的来龙去脉,并让您有足够的信心将它添加到您的建模武库中。
感谢阅读!如果你喜欢这个帖子或者有任何问题/评论,请在下面留下评论!
如果你想更新我正在写的东西、我正在构建的辅助项目或我觉得有趣的文章,请随时加入我的时事通讯— 【有抱负的数据科学家 。
这篇帖子的代码可以在我的 GitHub 页面找到。
关于这个话题的附加信息:https://sci kit-learn . org/stable/modules/generated/sk learn . SVM . SVR . htmlhttps://en . Wikipedia . org/wiki/Support-vector _ machine # Regressionhttps://www.saedsayad.com/support_vector_machine_reg.htm
代理建模介绍,第一部分:基础知识
代理建模
加速工程设计的机器学习方法
在工程中,产品设计很大程度上依赖于在各种设计参数下对产品性能的全面分析。这些分析大多是通过高保真、耗时的计算机模拟进行的。
为了更快地将产品推向市场,加速这些基于模拟的分析是关键。为此,一种叫做代理建模的数据驱动方法最近在各个工程领域越来越受欢迎。
在本博客的第一部分,我们将通过以下几个方面来关注这种方法的基本原理:
- 动机:为什么我们需要一种方法来加速计算机模拟?
- 解决方案:代理建模对这种情况有什么帮助?
- 细节:如何实际应用代理建模?
本文末尾列出了第一部分的要点。
在第二部分中,我们将通过一个案例研究来演示实际代理建模的关键步骤。
在第三部分中,我们将简要介绍一些高级概念,以进一步增强代理建模能力。
目录
1。需要加速的计算机模拟
2。代理造型
∘ 2.1 创意
∘ 2.2 特征
3 .代理建模的工作流程
∘ 3.1 采样
∘ 3.2 输出评估
∘ 3.3 构造代理模型
∘ 3.4 主动学习
∘ 3.5 充实训练数据集
4 .关键要点
延伸阅读
关于作者
1.加速计算机模拟的需要
计算机模拟被设计成通过求解相应的物理过程的数学方程来预测物理系统的行为。例如,工程师使用空气动力学模拟来计算飞机的阻力和升力,并使用结构动力学模拟来确定飞机机翼的强度。
这些模拟是有价值的,因为它们为工程师提供了对产品性能的丰富见解,而无需实际构建产品,因此在虚拟原型中起着至关重要的作用。
为了促进高效可靠的设计流程,工程师通常需要执行:
- 灵敏度分析,探索设计参数变化时的产品行为;
- 优化,找到产生最高性能和/或最低成本的最佳设计参数;
- 风险分析(或不确定性量化),计算设计参数不确定时产品失效的风险。
上述分析有一个共同点,即它们都需要大量的模拟运行,其中每次运行都采用不同的设计参数组合作为输入。(注:关于为什么风险分析需要多次模拟运行,可以查看我之前的帖子:管理计算科学与工程中的不确定性)****
不幸的是,计算机模拟通常不便宜:在工业中,在集群上运行的单个模拟通常需要几天才能完成。因此,需要许多模拟运行的分析将导致令人望而却步的计算成本,从而使它们在实践中不可行。
那么我们如何解决这个问题呢?代理建模可能会对此有所启发。
2.代理建模
2.1 理念
代理建模是如何做到这一点的:它构建一个统计模型(或代理模型)来精确地逼近模拟输出。随后,这种经过训练的统计模型可以被部署来代替原始的计算机模拟,以执行敏感性分析、优化或风险分析。****
图 1 使用替代模型来代替昂贵的计算机模拟是提高分析效率的一种方式。(图片由作者提供)
由于训练统计模型的单次评估通常比原始模拟的单次评估快得多,所以在给定各种设计参数组合的情况下,执行成百上千次输出评估不再是问题。总之,代理建模技术使得那些昂贵的分析变得可以承受。
2.2 特征
代理模型,也称为元模型或模拟器,使用数据驱动的方法进行训练。它的训练数据是通过在设计参数空间中几个智能选择的位置探测模拟输出而获得的。在这些位置中的每一个,进行完全模拟以计算相应的模拟输出。
通过将成对的输入(设计参数)和它们相应的输出组合成训练数据集,我们可以基于获得的数据集建立统计模型。
嗯,根据标记的训练数据集训练预测模型,这听起来像有监督的机器学习吗?确实是的!代理建模是监督机器学习应用于工程设计领域的一个特例。那些流行的机器学习技术,如多项式回归、支持向量机、高斯过程、神经网络等。,也被广泛采用为代理模型,以加速产品设计和分析过程。
由于这种联系,工程师可以方便地利用机器学习中的既定实践来构建、验证和选择代理模型,并有效地解决相关的欠拟合/过拟合问题。
3.代理建模的工作流程
图 2 代理建模工作流程(图片由作者提供)
3.1 取样
我们从生成初始训练数据开始。为了实现这一点,我们从参数空间中仔细选择设计参数的样本。这种做法也被称为 设计实验 。
在这个阶段,最好让样本均匀分布在参数空间中。这是有益的,因为我们可以从所研究的参数空间的所有区域获得近似输入-输出关系的代表。通常,空间填充采样方案用于产生具有上述性质的样本。这一类中最著名的是 拉丁超立方体方案 。**
3.2 产出评估
一旦我们确定了初始训练样本,我们需要通过运行它们来计算它们相应的输出值。在组合成对的选定训练样本及其相应的输出值之后,我们现在有了初始训练数据集。
3.3 构建代理模型
在这一步中,我们通过使用上一步中收集的训练数据来构建代理模型。这里,应该采用模型验证和选择的已建立的机器学习实践来指导模型训练过程。此外,高级机器学习技术,如 bagging 和 boosting,可以进一步增强代理模型的性能。
3.4 主动学习
一般来说,分析师无法预见建立一个准确的替代模型所需的样本数量。这是由近似输入-输出关系的复杂性决定的。因此,随着训练的进行,丰富训练数据集更有意义。这种做法被称为主动学习。**
为此,我们可以使用特制的学习函数来帮助我们识别下一个具有最高信息价值的样本。这些学习功能被设计成将样本分配到**
- 代理模型被认为是不准确或不确定的,
- 或者应用于设计参数的特别感兴趣的组合所在的区域,例如可能包含设计参数的全局最优值的区域。
3.5 丰富训练数据集
一旦识别出新的样本,就执行新的模拟运行来计算其相应的输出值。随后,在丰富的训练数据集上重新训练代理模型。我们重复这个过程,直到我们对代理模型的准确性感到满意。
4.关键要点
在这篇博客中,我们介绍了代理建模的基本思想:
- 产品设计依靠计算机模拟来评估产品性能和探索新的设计理念。
- 许多模拟运行在计算上可能过于昂贵,从而严重限制了产品设计和分析的效率。
- 代理建模技术,构建评估成本低廉的统计模型来精确逼近模拟输出,可以规避这个问题。
- 代理建模是监督机器学习应用于工程设计领域的一个特例。
- 代理模型不是在预先固定的数据集上进行训练,而是使用主动学习来随着训练的进行丰富训练数据,这大大提高了训练的效率和准确性。
在下一篇博客中,我们将通过一个工业实例来了解如何利用代理建模来促进依赖性可视化和加速不确定性量化分析。那里见!
延伸阅读:
[1] Alexander I. J. Forrester,András Sóbester,Andy J. Keane,通过代理建模进行工程设计:实用指南,2008 年。**
关于作者
我是一名博士研究员,致力于航空航天应用的不确定性量化和可靠性分析。统计学和数据科学是我日常工作的核心。我喜欢分享我在迷人的统计世界中学到的东西。查看我以前的帖子以了解更多信息,并在 中 和Linkedin*上与我联系。*
代理建模介绍,第二部分:案例研究
代理建模
加速工程设计的机器学习方法
在本系列的第一部分中,我们介绍了使用代理模型来加速基于模拟的产品设计过程的想法。这是通过训练一个统计模型来实现的,该模型在执行各种设计任务时充当模拟的廉价而精确的替代物,从而显著提高分析效率。
在第二部分中,我们将通过一个案例研究来演示如何在实践中使用代理模型。本案例研究的路线图如下所示:
图 1 路线图。(图片由作者提供)
我们将首先介绍问题的物理背景,然后将代理建模技术应用到问题中。最后,我们将说明如何使用经过训练的代理模型来执行两种类型的分析。
在本系列的第三部分中,我们将简要讨论一些进一步增强代理建模能力的高级概念。
我们开始吧!
目录
∘ 代理建模
1。背景
2。代理建模
∘ 2.1 采样
∘ 2.2 模型训练
∘ 2.3 主动学习
∘ 2.4 测试
3 .模型部署
∘ 3.1 可视化
∘ 3.2 不确定性量化
4 .
概要 5。延伸阅读
关于作者
1.背景
图 2 涡轮和涡轮叶片(来源)
涡轮是喷气发动机的关键部件。来自燃烧室的燃烧气体冲击涡轮叶片,推动涡轮旋转产生推力。
涡轮叶片直接面对高温废气,因此工作环境极其恶劣。极端的温度会熔化叶片材料,危及喷气发动机的可靠运行。
因此,热分析是涡轮叶片设计的必要条件。为此,通常构建物理模型来模拟叶片内的温度场,将燃烧气体和叶片内部冷却空气的温度作为边界条件。
在当前的案例研究中,我们采用以下分析管道(图 3)。我们将燃烧气体和冷却空气的温度及其相关的传热系数作为输入变量。我们感兴趣的是在给定输入值的情况下预测叶片的最高温度(输出)。在我的个人电脑上,图 4 中的单次模拟运行需要大约 4 秒钟。
详细的物理建模不是主要关注点(更多信息可在这里找到)。从概念上讲,您可以将模拟视为一个黑盒,只关注输入-输出关系。
图 3 将建立一个替代模型来近似模拟输出。(图片由作者提供)
2.代理建模
叶片设计可能需要多次运行模拟(图 3 ),以了解最高叶片温度如何响应不同的气体温度值、冷却空气温度及其各自的传热系数。加速这一过程的一种方法是通过训练一个代理模型来精确地近似“慢”模拟。这就是我们在本案例研究中要做的事情。
2.1 取样
首先,我们为代理模型训练生成一些初始训练样本。在这个阶段,让样本均匀分布在输入参数空间是有益的。为了实现这一点,我们采用拉丁超立方体采样方案。这个抽样方案更多的技术细节可以在我之前的帖子里找到:如何量化我的模型的预测误差?(第 4.1 节)****
如图 2 所示,我们总共生成了 8 个初始样本。现在我们可以进入下一步了。
图 4 通过拉丁超立方体方法生成的训练样本。(图片由作者提供)
2.2 模型训练
基于最初生成的样本,我们可以训练一个代理模型。这里我们选择高斯过程 (GP) 作为我们的代理模型。**
选择 GP 模型的一个主要动机是,与许多其他监督机器学习技术不同,GP 模型提供测试样本的预测,并估计相关的预测不确定性。这个特性是实现主动学习的关键,这将在下面讨论。
2.3 主动学习
我们希望用更多的训练样本来改进最初训练的代理模型。我们迭代地进行,在每次迭代中,我们只生成一个样本添加到现有的训练数据集中。
为了确定生成哪个样本,我们在输入参数空间中寻找当前代理模型具有最大预期预测误差的位置。这也是当前代理模型“感觉”对其预测准确性最没有信心的位置。**
通过在模型预测产生最大误差的位置提供样本,代理模型可以最快地“学习”。这个模型训练方法的更多技术细节将在本系列的第三部分中讨论。
最后,我们添加了 14 个额外的训练样本,使得最终预测误差下降到初始预测误差的 1%以下。总之,我们使用了 22 个样本来训练当前的代理模型。
图 5 昂贵的模拟和经过训练的替代模型对温度预测的比较。(图片由作者提供)
2.4 测试
为了测试模型的准确性,我们生成了一个包含 20 个测试样本的测试数据集。从图 5 中,我们可以看到,经过训练的替代模型达到了非常高的精确度,因为所有的预测都与模拟结果完全匹配。
3.模型部署
现在我们已经训练了我们的代理模型,并评估了它的预测精度。是时候部署模型来执行我们期望的分析任务了。
3.1 可视化
替代模型可用于以可忽略不计的成本可视化投入产出函数的“景观”。这有助于分析师快速识别输出和各种输入之间的重要依赖关系。
图 6 不同气体传热系数下叶片温度与气体温度的关系(图片由作者提供)
例如,图 6 展示了在不同气体传热系数值下气体温度和最大叶片温度之间的关系。我们可以看到,叶片温度几乎是气体温度的线性函数:随着气体温度升高,叶片温度成比例增加,这很直观。
同时,我们看到叶片温度和气体传热系数之间的关系稍微呈非线性,尤其是在高气体温度区域。当气体温度固定时,假定传热系数增加相同的量,最大叶片温度的增加量减少。
3.2 不确定性量化
实际上,涡轮机的运行条件是不断变化的。这意味着我们不确定气体和冷却空气温度的准确值及其相关的传热系数。因此,我们需要评估由不确定的操作条件引起的产品性能变化。这正是不确定性量化分析试图实现的目标。**
通常,我们使用蒙特卡罗方法来进行不确定性量化。对于这一点,我有专门的文章来解释技术细节:如何量化我的模型的预测误差?
简而言之,蒙特卡罗方法从给不确定的输入变量分配概率分布开始(这些变量代表我们当前对它们不确定程度的了解)。随后,我们从输入分布中抽取大量随机样本(~o(10⁴),并计算它们对应的输出值。基于输出结果的集合,我们可以绘制输出的直方图,该直方图在统计上完全描述了输出的不确定性。
我们按照上述程序来做蒙特卡洛。这里我们假设我们的四个输入是独立的,并且遵循正态分布(如图 7 所示)。我们抽取了总共 10000 个随机样本来进行不确定性量化。
图 7 四个输入遵循独立的正态分布。(图片由作者提供)
图 8 替代模型准确量化了叶片最高温度的不确定性。(图片由作者提供)
图 8 给出了由替代模型预测的叶片最高温度的分布。此外,我们将该结果与通过将蒙特卡罗程序直接应用于原始模拟而获得分布进行了比较。我们可以看到,代理模型已经精确地量化了由不确定的输入参数引起的叶片最高温度的变化。
在计算成本方面,基于代理模型的蒙特卡罗在我的个人电脑上花费了 0.01 秒,而基于模拟的蒙特卡罗花费了大约 11 个小时。这就是一个训练有素的代理模型可以实现的加速程度。
4.摘要
在本文中,我们研究了如何采用代理建模技术来加速喷气发动机涡轮叶片的热分析。我们演示了代理建模流程中的关键步骤:
- 初始采样:生成“空间填充”样本的拉丁超立方体方法;
- 模型训练:高斯过程
- 主动学习:依次丰富训练样本,最大化模型训练效率
- 模型测试:使用测试数据集进行基准测试
- 模型部署:依赖关系可视化和不确定性量化分析
在本系列的下一部分中,我们将简要讨论一些高级概念,以进一步增强代理建模能力。
5.进一步阅读
[1] Alexander I. J. Forrester,András Sóbester,Andy J. Keane,通过代理建模进行工程设计:实用指南,2008 年。**
关于作者
我是一名博士研究员,致力于航空航天应用的不确定性量化和可靠性分析。统计学和数据科学是我日常工作的核心。我喜欢分享我在迷人的统计世界中学到的东西。查看我以前的帖子以了解更多信息,并在 中 和Linkedin*上与我联系。*
代理建模介绍,第三部分:超越基础
代理建模
加速工程设计的机器学习方法
在本系列的第一部分中,我们已经介绍了代理建模的基本概念。在第二部分中,我们已经通过一个展示完整分析管道的案例研究看到了代理建模的作用。
总的来说,代理建模技术训练一个便宜但精确的统计模型,作为计算昂贵的模拟的代理,从而显著提高产品设计和分析的效率。
在第三部分中,我们将简要讨论代理建模研究和应用中出现的以下三个趋势:
- 梯度增强代理建模:在训练样本中加入梯度,提高模型精度;
- 多保真度代理建模:同化各种保真度的训练数据,达到更高的训练效率;
- 主动学习:通过主动选择下一个训练数据,智能训练代理模型。
目录
1。渐变增强代理模型
∘ 1.1 基本思路
∘ 1.2 举例
∘ 1.3 挑战
2。多保真代理模型
∘ 2.1 基本思想
∘ 2.2 举例
3 .主动学习
∘ 3.1 基本思想
∘ 3.2 预期预测误差【EPE】
4 .关键要点
延伸阅读
关于作者
1.梯度增强代理模型
1.1 基本理念
梯度被定义为输出相对于输入的灵敏度。由于诸如伴随方法和自动 differentiation 等技术的快速发展,现在工程模拟代码不仅可以在给定输入向量的情况下计算输出f(x),还可以计算梯度∂f(x**
因此,我们可以将我们的训练数据对( x ᵢ ,f(xᵢ)扩展为训练数据三元组( x ᵢ ,f(xᵢ)、∂通过利用额外的梯度信息,与仅在( x ᵢ ,f(xᵢ)上训练的模型相比,训练的代理模型可以达到更高的精度,假定两个模型使用相同数量的训练数据点。**
我们也可以用一种等价的方式来陈述包含梯度的好处:它允许减少数据点的数量来达到给定的精度。这是实践中期望的特征。回想一下,生成每个训练数据点需要运行一次昂贵的模拟代码。如果我们可以减少训练数据点的总数,我们就可以用较小的计算预算来训练代理模型,从而提高训练效率。
1.2 示例
让我们用一个例子来看看梯度增强的代理模型如何进一步提高预测精度。在本例中,我们使用高斯过程及其梯度增强版本作为替代模型来逼近图 1 所示的函数。**
两个代理模型使用相同的训练样本。对于梯度增强的高斯过程,在那些训练样本上的 y 相对于 x 的梯度也被提供用于训练。
图 1 给定相同数量的训练样本,替代模型的梯度增强版本比基本版本更准确。(图片由作者提供)
从图 1 中显示的预测结果,我们可以清楚地看到,替代模型的梯度增强版本比其基本版本具有更好的准确性。尤其是在大约 x =0.8 的区域中:即使在该区域中没有分配训练样本,梯度增强模型仍然能够正确地捕捉趋势。
1.3 挑战
数据爆炸构成了阻碍梯度增强代理建模实施的主要问题。
首先,随着输入参数数量的增加,可用的信息呈指数增长。例如,假设有 2 个输入参数,我们使用 10 个训练样本来训练代理模型。在这种情况下,我们的总训练数据由 30 条信息组成:
现在,假设我们必须考虑总共 4 个输入参数。随着输入数量的增加,我们需要更多的样本来进行模型训练。假设我们使用 20 个样本。现在,我们的总训练数据将由 100 条信息组成:
因此,当输入参数增加时,总的训练数据增长非常快。拥有丰富的训练数据不一定是一件好事,因为它会减慢模型调整过程(即模型超参数优化)。在极端情况下,训练代理模型甚至比运行模拟需要更多的时间。
第二,理论上,高阶导数也可以纳入代理模型训练。这也导致了数据爆炸:模型训练中使用的导数数量随着导数阶数的升高而呈指数级增长。例如,给定 2 个输入参数 x ₁和 x ₂,一阶导数只包含 2 项(即∂ f /∂ x ₁和∂ f /∂ x ₂),而二阶导数包含额外的 3 项(即:f/x****
面对训练数据爆炸的问题,我们需要更加小心地决定哪些样本的哪些导数进入训练数据集。找到合适的梯度,以减少整体训练的努力,这是一个活跃的研究领域。
2.多重保真代理模型
2.1 基本理念
在跨计算工程的许多实例中,具有不同保真度和评估成本的多个仿真代码可用于相同的输出。
高保真仿真考虑了底层物理过程的更精细的空间/时间分辨率。虽然结果更符合实际,但计算成本也很高。在光谱的另一端,我们有低保真度模拟,通常具有较粗糙的空间/时间分辨率,并嵌入较粗糙的物理细节。然而,它们比高保真度的同类产品跑得快得多。
图 2 物理模型通常有不同的保真度。(图片由作者提供)
自然,我们希望我们的代理模型具有与高保真模拟相同的保真度。然而,纯粹从高保真仿真中产生样本是相当昂贵的。那么如何才能在代理模型训练中获得足够的精度,却又不付出太多的代价呢?
我们可以做的一种方法是只生成少量的高保真样本,但同时生成大量的低保真度样本(因为它们生成起来很便宜)。通过聚集来自两个真实度的样本,我们可以最大化代理模型的准确性,同时最小化相关的训练成本。
这正是多保真策略试图实现的目标。更具体地,该策略利用丰富的低保真度样本来探索参数空间,并获得对近似输入-输出关系的一般趋势的定性(但还不是定量)正确描述。同时,该策略利用可用的高保真样本有效地提炼低保真度结果,从而保证训练好的代理模型的定量正确性。
2.2 示例
让我们来看一个使用多保真度方法来实现目标模型准确性的例子,只需要几个高保真训练样本。
在本例中,我们的低/高保真度训练样本以及我们想要逼近的真实函数如图 3(a)所示。我们可以看到,低保真度样本是不准确的,因为它们远离真实的函数曲线。然而,它们与真实函数的总体趋势相匹配,这可以被多保真度方法利用来提高模型训练效率。
图 3 (a):低和高保真度训练样本;(b)完全建立在高保真度样本基础上的单一保真度模型;(c):建立在低保真度和高保真度样本基础上的多保真度模型。(图片由作者提供)
在图 3(b)中,我们看到高保真训练样本的数量远远不够,因为拟合的代理模型不能捕捉基础函数的特征。然而,在图 3(c)中,通过用大量定性正确的低保真度样本来扩充少数高保真度样本,多保真度方法可以产生好得多的预测,其与真实函数完全一致。
3.主动学习
3.1 基本理念
付出少,收获多。
在构建代理模型时,我们希望使用尽可能少的训练样本来达到目标模型的预测精度。回想一下,生成训练样本需要运行昂贵的计算机模拟。因此,较少的训练样本意味着获得代理模型的效率更高。
以前,人们倾向于在整个参数空间中均匀分布训练样本,以保证模型的准确性。然而,这种实践也可能导致计算资源的大量浪费:一般来说,近似的输入-输出关系在参数空间的不同区域中并不同样“复杂”,因此,不值得相同数量的训练数据。
相反,一个更聪明的方法是随着训练的进行,丰富训练数据集。通过这种方式,代理模型可以主动探索近似输入-输出关系的前景,并在模型“认为”其预测不准确的区域添加样本。
学习函数在主动学习中起着关键作用,因为它决定将哪个样本添加到现有的训练数据集中。构建学习功能是一个活跃的研究领域。一般来说,学习功能在追求的目标方面各不相同。
在下文中,我们讨论一个特定的学习函数,其目的是建立一个在参数空间各处都准确的代理模型。当经过训练的替代模型稍后用于执行参数研究、灵敏度分析和输入-输出关系的可视化时,这种学习功能是期望的。
3.2 预期预测误差(EPE)
该学习函数将下一个训练样本分配到代理模型具有最大预期预测误差的位置。这很直观,因为这是代理模型学习最快的方式。
在机器学习中,预期预测误差可以写成一个偏差项和一个方差项的组合。这就是著名的偏差-方差分解:**
偏差-方差分解。(图片由作者提供)
为了实现这种学习功能,一个要求是所采用的替代模型能够估计其预测不确定性(即方差)。满足这一要求的一种替代模型是高斯过程。
显然,我们不会提前知道真正的函数值f(x)(否则,我们就不需要建立一个代理模型来近似它了!).因此,必须估计上式中的偏差项。一种方法是通过交叉验证。刘等【1】讨论了具体实现。****
4.关键要点
在这篇博客中,我们讨论了代理建模的一些高级概念:
- 梯度增强的代理建模,它在训练模型时合并了输出对输入的梯度,以提高模型预测的准确性。
- 多保真代理建模,其将一些定量正确的高保真训练数据与许多定性正确的低保真训练数据聚合,以用最小的计算努力训练高度准确的代理模型。
- 主动学习,它鼓励代理模型主动探索参数空间,并在它可以学习最多的区域添加训练样本。
延伸阅读:
[1]刘汉忠、蔡俊杰和宋永祥。一种通过最大化预期预测误差进行克里金元建模的自适应采样方法。计算机&化学工程,106(2):171–182,2017 年 11 月。**
[2] Alexander I. J. Forrester,András Sóbester,Andy J. Keane,通过代理建模进行工程设计:实用指南,2008 年。**
关于作者
我是一名博士研究员,研究航空航天应用的不确定性量化和可靠性分析。统计学和数据科学是我日常工作的核心。我喜欢分享我在迷人的统计世界中学到的东西。查看我以前的帖子以了解更多信息,并在 中 和Linkedin上与我联系。**
茱莉亚和 PKG 回复的介绍
朱莉娅综合教程
熟悉茱莉亚的魔法世界进行科学编程!
(图片由作者提供)
本文视频:
介绍
编程语言的世界可能会非常混乱,尤其是对于一个希望尝试一下的新的有抱负的开发者或科学家来说。应该先学什么语言?要回答这个问题,你当然应该始终衡量你的个人兴趣和职业目标。虽然像 Python 和 Java-script 这样的选项可以在 web 开发等方面为您提供潜在的帮助,但是在处理更多面向软件的问题时,例如编译可执行文件,您肯定会在这些语言方面有所欠缺。
这才是朱莉娅真正闪光的地方。尽管 Julia 肯定保留了其作为未来科学编程语言的主要目的,但它也是当今拥有开源许可的最通用的高级通用语言之一。在这一领域,Julia 比大多数竞争对手都有许多优势:
- 与软件工程中常用的 Java 或 C++等语言相比,Julia 的读写简单得多——这使得用一种语法类似于 Python 的语言开发复杂的应用程序变得快速而简单。虽然 Julia 肯定不是编译二进制文件最容易的语言,但事实上这是可能的!如果您想了解更多关于这样做的内容,请查看这篇文章,我正是在这篇文章中探索了这一点!:
用 C 编译 Julia!(这一点也不好玩。)
towardsdatascience.com](/creating-my-first-julia-executable-53e0f6bd0db5)
- “作为范例的多重分派”——你没听错,Julia 以戏剧性的、改变语言的方式使用参数多态性,这使它变得非常通用。前一秒钟,您可能纯粹是在函数上使用 Julia,下一秒钟,您可能使用带有数据的调度函数来有效地创建一个类。如果你想了解更多,你也可以点击这里!:
[## 用静态类型语言将 Julia 转换成 Python 和 Duck-Type
通过结合 Julia 富有表现力的语法和令人敬畏的调度,将 Julia 变成 Python。
towardsdatascience.com](/turn-julia-into-python-and-duck-type-in-a-statically-typed-language-119f708936ff)
- 元编程和宏——谁不喜欢元编程?嗯,也许喜欢简单调试的人..不管 meta 有什么问题,Julia 有这个能力!这里有一个介绍!:
在 Julia 中使用 Julia 的元包进行编程的基础。
towardsdatascience.com](/a-swift-introduction-to-metaprogramming-in-julia-5eef529f5a8a)
我已经到了什么都有文章的地步了。
获得正确的 Julia 安装
每当我第一次被介绍给 Julia 时,我犯了一个致命的错误,从我的软件包管理器安装了这种语言。虽然这将为您提供一个稳定且完全可用的 Julia 版本 1.1,并提供长期支持,但您将无法获得自那时以来所取得的所有进步的好处。特别是多线程是我在 1.4 +中更喜欢的东西,很快就连车床也将使用 spawn 宏,并且将与 1.1–1 . 3 . 9 不兼容。
记住这一点,不要通过 Brew、Apt、Pacman 或 Yum 安装 Julia,而是直接进入
丰富的科学计算生态系统 Julia 从一开始就被设计为非常擅长数字和…
julialang.org](https://julialang.org)
并下载官方和最新的二进制文件。之后,您可以按照下面列出的适用于您各自平台的安装说明进行操作:
Linux(或其他非 Mac 类 Unix)
首先,从 Julia mirror 下载 tarball。您可以通过您的网络浏览器或 wget:
wget https://julialang-s3.julialang.org/bin/linux/x64/{{stable_release_short}}/julia-1.5.1-linux-x86_64.tar.gz
接下来,您将需要提取 tarball。这可以通过双击您的文件管理器(取决于您的文件管理器,但我知道这在 Nautilus 和 Dolphin 中也能工作)或使用 tar zxvf 来完成:
tar zxvf julia-1.5.1-linux-x86_64.tar.gz
现在只需在任一路径下创建一个到 Julia 可执行文件的链接。巴沙尔或者。bash_profile 与您最喜欢的文本编辑器:
nano ~/.bash_profile**export** PATH="$PATH:/path/to/<Julia directory>/bin"
我建议使用您的 bash_profile,这样您就不会覆盖 PATH!
Windows 操作系统
至于在 Windows 上安装,过程相当简单。下载安装程序并安装 Julia。接下来,您需要将 Julia 添加到您的路径中,就像我们在 Linux 上所做的那样。首先按下 Windows 键+ R,这将打开“运行”之后,输入undll32 sysdm.cpl,EditEnvironmentVariables
按 enter 键,然后在“用户变量”部分,找到行“路径”并单击“编辑”单击新建,然后粘贴到您的 Julia 目录中。这通常在 app-data 中,可以通过在搜索栏中键入%appdata%并按回车键来访问。
马科斯
要安装 Julia for Mac,请使用。朱莉娅网站上提供的 DMG 文件。接下来,导航到/usr/local/bin
并删除julia
文件。然后使用以下命令链接它:
ln -s /Applications/Julia-1.5.1.app/Contents/Resources/julia/bin/julia /usr/**local**/bin/julia
唷!
熟悉朱莉娅·REPL
朱莉娅 REPL 是一个快速和方便的方式来测试和执行朱莉娅代码。这也是访问 Pkg 来激活新环境和添加新包的好方法。REPL 是“读取评估打印循环”的首字母缩写,这正是它所表达的意思。
阅读—表示阅读输入文本。
评估—意味着评估文本内部的逻辑
打印—表示显示退货
循环——这意味着在应用程序的整个生命周期中都有一个 while 循环。
如果你需要从朱莉娅 REPL 打开 Pkg REPL,你只需按
]
这将允许您使用命令而不是 Julian 语法来处理您的 Julia 包。有几个不同的命令可供您使用,但是最重要的命令是
- 增加
- 状态
- 例示
- 建设
- 空间
- 使活动
Add 当然会添加新的包。状态将报告。toml 文件,我们将在未来的版本中对它更加熟悉。实例化将更新所有项目依赖项。Build 将构建一个选定的包,当包或包的组件不能正常工作时,它会很有用。Rm 是 add 的逆运算,将删除提供的包。最后,activate 将激活一个虚拟环境,并将一个名称作为参数。
基本朱莉娅
虽然不一定是 Julia 特有的,但在全面了解计算机编程之前,您可能需要了解一些事情。编程简单来说就是数据的移动或者数据的处理。从低级汇编代码一直到最高级别的编程都是如此。
重要的是要记住你正在使用什么语言,以及它将如何处理类型。如果你想了解更多关于语言和它们如何处理类型的知识,以及 Julia 属于哪一类,我也有一篇文章:
快速浏览类型以及它们如何与语言交互。
towardsdatascience.com](/all-about-typing-explicit-vs-implicit-and-static-vs-dynamic-980da4387c2f)
结论
Julia 是一种非常棒的编程语言,我很高兴能与您分享更多关于它的内容!这个系列教程将带你从计算机编程的基础开始,以你自己的方式成为一名伟大的程序员。在下一个教程中,我们将复习基本函数的编写,并熟悉不同的类型。接近尾声时,我们将触及条件句!如果你已经是一个有经验的程序员,向前跳一点可能是一个好主意,但我试图保持步调一致,以便每个人都可以从每个教程中获得某种知识——因此,反馈是受欢迎的!感谢您的阅读、观看,并感谢您慷慨捐赠的时间!
R 中的管道介绍
r 基础知识
r 对数据处理最重要的运算符,解释道。
照片由 Erlend Ekseth 在 Unsplash 上拍摄
数据分析通常包括许多步骤。从原始数据到结果的典型过程可能涉及筛选案例、转换值、汇总数据,然后运行统计测试。但是,我们如何将所有这些步骤联系在一起,同时保持代码的有效性和可读性呢?
输入管道,R 对数据处理最重要的操作符。
管子是做什么的?
管道操作符写为%>%
,是 r 的magritter包的一个长期特性。它接受一个函数的输出,并将其作为参数传递给另一个函数。这使我们能够将一系列分析步骤联系起来。
为了形象化这个过程,想象一个工厂,不同的机器沿着传送带放置。每台机器都是一种功能,执行我们分析的一个阶段,比如过滤或转换数据。因此,管道就像传送带一样工作,将一台机器的输出传输到另一台机器进行进一步处理。
一个美味的分析程序。图片:Shutterstock
我们可以在使用 mtcars 数据集的真实示例中看到这是如何工作的。这个数据集带有 base R,包含各种汽车的规格和燃油效率的数据。
下面的代码根据每辆车的气缸数对数据进行分组,然后返回每组的平均每加仑英里数。确保在运行这段代码之前安装好 tidyverse 套件,因为它既包括管道又包括group_by
和summarise
函数。
library(tidyverse)
result <- mtcars %>%
group_by(cyl) %>%
summarise(meanMPG = mean(mpg))
管道操作员将 mtcars 数据帧送入group_by
功能,然后将group_by
的输出送入summarise
。该过程的结果存储在 tibble result
中,如下所示。
mtcars 数据集中车辆的平均每加仑英里数,按发动机气缸数量分组。
尽管这个例子非常简单,但它演示了基本的管道工作流。为了更进一步,我鼓励用这个来玩。也许交换和添加新的功能到“管道”中,以获得对数据的更多了解。这样做是了解如何使用管道的最佳方式。
但是我们为什么要首先使用它呢?
为什么要用管子?
与 R 中处理数据的任何其他方法相比,管道有一个巨大的优势:它使进程易于阅读。如果我们将%>%
读作“then ”,上一节的代码很容易理解为一组简单的英语指令:
Load tidyverse packagesTo get our result, take the mtcars dataframe, THEN
Group its entries by number of cylinders, THEN
Compute the mean miles-per-gallon of each group
这比我们用另一种方式来表达这个过程更具可读性。下面的两个选项是前面代码的不同表达方式,但两者都更糟糕,原因如下。
# Option 1: Store each step in the process sequentially
result <- group_by(mtcars, cyl)
result <- summarise(result, meanMPG = mean(mpg))
# Option 2: chain the functions together
> result <- summarise(
group_by(mtcars, cyl),
meanMPG = mean(mpg))
选项 1 完成了工作,但是在每一行覆盖我们的输出数据帧result
是有问题的。首先,对于包含许多步骤的过程来说,这样做是没有效率的,并且会在代码中产生不必要的重复。在某些情况下,这种重复也使得准确识别每一行上的变化变得更加困难。
选项 2 更不实际。嵌套我们想要使用的每个函数变得很快,特别是对于长过程。很难阅读,更难调试。这种方法还使得很难看到分析中的步骤顺序,如果您希望以后添加新功能,这是个坏消息。
显而易见,使用管道可以极大地改进大多数 R 脚本。它使分析更具可读性,消除了重复,并简化了添加和修改代码的过程。有什么是它做不到的吗?
管道的局限性是什么?
尽管它非常方便,但管道并不是在所有情况下都有用。以下是它的一些局限性:
- 因为它以线性顺序链接函数,所以管道不太适用于包含多方向关系的问题。
- 管道一次只能传输一个对象,这意味着它不太适合需要多个输入或产生多个输出的函数。
- 它不适用于使用当前环境的函数,也不适用于使用惰性求值的函数。Hadley Wickham 的书《数据科学的 R》中有几个这样的例子。
这些事情是意料之中的。就像你想用一个工具建造一座房子一样,没有一个单独的特性可以解决你所有的编程问题。但是不管怎样,这种管子还是很通用的。虽然这篇文章关注的是基础,但是有足够的空间以高级或创造性的方式使用管道。我在各种各样的脚本中使用过它,无论是面向数据的还是非面向数据的,它都让我的生活变得更加轻松。
额外管道提示
谢谢你读到这里。作为奖励,这里有一些奖金管道提示和资源:
- 厌倦了笨拙地打字
%>%
?稍微简单一点的键盘快捷键CTRL + SHIFT + M
会在 RStudio 中打印一个管道! - 需要关于如何格式化管道的样式指导?看看哈德利·威克姆的《R 风格指南》中这一有用的章节。
- 想了解更多关于 R 中管道的历史吗?查看阿道夫·Á·阿尔瓦雷斯的博客文章。
烟斗很棒。它将您的代码转换成一系列可读的指令,并有许多其他的实际好处。现在您已经了解了管道,使用它,并看到您的代码变成了一个故事。
想阅读我所有关于编程、数据科学等方面的文章吗?在这个链接注册一个媒体会员,就可以完全访问我所有的作品和媒体上的所有其他故事。这也直接帮助了我,因为我从你的会员费中得到一小部分,而不需要你额外付费。
你也可以通过订阅这里让我的所有新文章直接发送到你的收件箱。感谢阅读!
分类任务中 ROC-AUC 的介绍
曲线是什么意思?
弗朗西斯科·温加罗在 Unsplash 上拍摄的照片
在机器学习中,一个基本的学习目标是将数据分类成组。虽然分类可以包括无监督学习(例如,聚类),但在大多数情况下,我们的任务涉及已知的标签,因此我们正在进行监督学习来分类我们的数据。您的模型将生成预测标签,这将允许我们比较我们的预测是否准确。当预测的标签和真实的标签匹配时,我们说预测是正确的,显然当它们不匹配时,我们说预测是错误的。
为了将我们的讨论放在上下文中,假设我们有一些糖尿病诊断已知的受试者的临床数据。在我们继续之前,只是一个快速的免责声明——这些数据不是真实的数据,它们不构成任何医疗建议。
基于这些数据,我们建立了一个逻辑回归模型,根据人们的空腹血糖水平来预测他们是否患有糖尿病。在下表中,空腹血糖水平表示为 mg/dL。diabetic_clinical 列显示临床诊断,diabetic_predicted 列显示逻辑回归模型的预测结果。根据临床和预测的结果,我们可以简单地知道预测是否正确,如最后一列所示。
空腹血糖水平与糖尿病
混淆矩阵
基于这种与真实标签相关的二元评估结果(正确对错误),我们可以构建 2 x 2 混淆矩阵,如下所示。
困惑矩阵(作者)
正确预测:
- 真阳性(TP) :预测和真标签均为阳性。在上面的例子中,这些人患有糖尿病,根据他们的空腹血糖水平预测他们会患糖尿病。
- 真阴性(TN) :预测和真标签均为阴性。这些是非糖尿病受试者,他们被预测为非糖尿病患者。
错误预测:
- 假阳性(FP) :预测标签为阳性,真实标签为阴性。这些人被预测为糖尿病患者,但实际上他们不是。
- 假阴性(FN) :预测标签为阴性,真实标签为阳性。那些糖尿病患者被预测为非糖尿病患者。
我们可以导出许多对分类模型评估至关重要的度量。下面列出了一些常用的指标,您可以在 Wikipedia 页面找到生成的指标的完整列表。
- 准确率:正确预测数除以预测总数:
***(TP + TN) / (TP + TN + FP + FN)***
。在示例中,我们的模型的精度是 0.7(即 7 / 10)。 - 真阳性率(TPR、灵敏度或召回率):真阳性标签数除以阳性标签数:
***TP / (TP + FN)***
。我们模型的 TPR 是 0.8(即 4 / 5)。 - 假阳性率(FPR,脱落):假阳性标记数除以阴性标记数:
***FP / (FP + TN)***
。我们模型的 FPR 是 0.4(即 2 / 5)。 - 真阴性率(特异性):真阴性标记数除以阴性标记数:
***TN / (FP + TN)***
。你可以注意到***specificity = 1 — FPR***
。我们模型的特异性是 0.6(即 3 / 5)。
接收机工作特性
接收器操作特性曲线是一个图表,显示您的分类模型在所有阈值下的表现。下图是一条假设的 ROC 曲线。
ROC 示例图(按作者)
- 在 ROC 曲线图中,x 轴是 FPR,而 y 轴是 TPR。
- 对于一个完美的模型,它的 FPR 是 0,它的 TPR 是 1。相比之下,对于最差的模型,其 FPR 为 1,TPR 为 0。图中显示了这两种极端情况的 ROC 曲线。
- 在一个典型的模型中,我们应该看到真实的曲线。具体来说,通过改变阈值,我们的模型将产生不同的 TPR 和 FPR,并且这些点可以绘制在该图上。连接这些点,我们可以生成一个 ROC 曲线。
为了将 ROC 曲线放入糖尿病诊断示例的上下文中,让我们假设我们可以有不同的阈值来预测糖尿病诊断。如你所料,如果我们有一个极低的阈值,我们会将所有受试者归类为糖尿病患者。虽然我们可以得到 1 的 TPR,但是 FPR 也会变成 1。考虑一些适中的阈值,我们应该能够找到 TPR 和 FPR 的许多不同组合。
因为显示的数据很小,如果您有更多的数据点,通过改变阈值,您应该创建更多的点作为 TPR 和 FPR 的函数。如果我们连接所有这些点并平滑曲线,我们就得到我们正在构建的特定模型的 ROC 曲线。
ROC 曲线下面积
我们如何量化模型的性能?如上所述,我们说 ROC 是为了显示我们的模型性能,但是我们如何用 ROC 曲线准确地评估性能呢?
如果你比较这两种极端情况(完美与最坏),你可能会注意到曲线下的区域似乎意味着什么。你的猜测完全正确。假设您考虑一个典型的模型,在大多数情况下,您的模型的 TPR 应该大于各种阈值的 FPR。在这种情况下,您将看到图表对角线上方的 ROC 曲线。
更重要的是,如果你的模型更好,你应该看到 TPR 和 FPR 之间更大的差异,这将曲线推向完美的模型状态。下图显示了您在使用真实模型时可能遇到的一些情况。
ROC 曲线的 AUC(按作者)
- 灰色区域表示 ROC 曲线下的区域。
- 模型 2 的 AUC 大于模型 1 的 AUC。我们通常认为模型 2 优于模型 1。换句话说,我们可以粗略地将分类模型的性能等同于它们各自的 AUC。
- 对角线描绘了用于二元分类任务的随机分类器。这里是关于为什么 TPR 和 FPR 的随机猜测的 AUC 都是 0.5 的附加讨论。
在你走之前
虽然 ROC 和 AUC 经常用于评估分类任务的性能,但它们并不总是首选。最主要的原因是它没有考虑实际的问题。例如,不同的模型可以具有相似的 AUC,但是它们可以具有不同的形状,这意味着模型具有 TPR 和 FPR 的不同组合。
因此,我们应该考虑其他因素来选择理想的模型。问自己的问题可以包括。你更关心正确识别阳性病例吗?还是更在乎正确识别负面案例?
这里有关于 ROC 和 AUC 的一个简单讨论,我觉得对初学者很有用。
TinyML 简介
机器学习遇上嵌入式系统
Alexandre Debiève 在 Unsplash 上的照片
我们目前生活在一个被机器学习模型包围的世界。在一天中,你对这些模型的利用比你意识到的要多。日常任务,如滚动社交媒体,拍照,查看天气,都依赖于机器学习模型。你甚至可能会看到这个博客,因为一个机器学习模型向你建议了这一点。
我们都知道训练这些模型在计算上是昂贵的。但是大多数时候,在这些模型上运行推理在计算上也是昂贵的。我们使用机器学习服务的速度,我们需要足够快的计算系统来处理它。因此,这些模型中的大多数都运行在由 CPU 和 GPU(有时甚至是 TPU)集群组成的大型数据中心上。
大并不总是更好
当你拍照时,你希望机器学习的神奇瞬间发生。你不想等待图像被发送到数据中心,在那里进行处理并再次发送回来。在这种情况下,您希望机器学习模型在本地运行。
当你说“Alexa”或“好的,谷歌”时,你希望你的设备能立即响应你。等待设备将您的语音发送到服务器进行处理,并检索信息。这需要时间,并削弱了用户体验。同样,在这种情况下,您希望机器学习模型在本地运行。
TinyML 是什么
TinyML 是机器学习和嵌入式系统的一个研究领域,探索可以在小型低功耗设备(如微控制器)上运行的模型类型。它支持边缘设备的低延迟、低功耗和低带宽模型推断。标准消费类 CPU 的功耗在 65 瓦到 85 瓦之间,标准消费类 GPU 的功耗在 200 瓦到 500 瓦之间,而典型的微控制器的功耗在毫瓦或微瓦的数量级。这大约减少了 1000 倍的功耗。这种低功耗使 TinyML 设备能够在不使用电池的情况下运行数周、数月,在某些情况下甚至数年,同时在 edge 上运行 ML 应用程序。
ML 的未来是微小而光明的
TinyML 的优势
- 低延迟:由于模型运行在边缘,数据不必发送到服务器来运行推理。这减少了输出的延迟。
- 低功耗:正如我们之前讨论过的,微控制器功耗非常低。这使得它们可以长时间不充电运行。
- 低带宽:由于数据不需要不断发送到服务器,所以使用的互联网带宽较少。
- 隐私:由于模型运行在边缘,你的数据不会存储在任何服务器上。
TinyML 的应用
通过总结和分析低功耗设备的边缘数据,TinyML 提供了许多独特的解决方案。尽管 TinyML 是一个新兴领域,但它已经在生产中使用了很多年。“OK Google”、“Alexa”、“嘿 Siri”等唤醒词就是 TinyML 的一个例子。在这里,设备总是开着的,并分析你的声音来检测唤醒词。这里我再补充一些 TinyML 的应用。
- 工业预测性维护:机器容易出故障。在低功耗设备上使用 TinyML,可以持续监控机器并提前预测故障。这种预测性维护可以显著节约成本。澳大利亚初创公司 Ping Services 推出了一种物联网设备,该设备通过磁性附着在涡轮机外部,并在边缘分析详细数据,来自主监控风力涡轮机。该设备可以在潜在问题发生之前就向当局发出警报。
- 医疗保健:太阳能驱蚊项目利用 TinyML 遏制登革热、疟疾、寨卡病毒、基孔肯雅热等蚊媒疾病的传播。它的工作原理是检测蚊子滋生的条件,并搅动水以防止蚊子滋生。它依靠太阳能运行,因此可以无限期运行。
- 农业:Nuru 应用程序通过使用 TensorFlow Lite 在设备上运行机器学习模型,只需拍摄一张照片,就可以帮助农民检测植物中的疾病。因为它在设备上工作,所以不需要互联网连接。这对于偏远地区的农民来说是一个至关重要的要求,因为他们所在的地方可能没有合适的互联网连接。
- 海洋生物保护:智能 ML 供电设备用于实时监控西雅图和温哥华周围水道的鲸鱼,以避免繁忙航道上的鲸鱼袭击。
我该如何开始?
- 硬件:****Arduino Nano 33 BLE Sense是在 edge 上部署机器学习模型的建议硬件。它包含一个 32 位 ARM Cortex-M4F 微控制器,运行频率为 64MHz,具有 1MB 程序存储器和 256KB RAM。这个微控制器提供足够的马力来运行 TinyML 模型。Arduino Nano 33 BLE 传感器还包含颜色、亮度、接近度、手势、运动、振动、方向、温度、湿度和压力传感器。它还包含一个数字麦克风和一个蓝牙低能耗(BLE)模块。这种传感器套件对于大多数应用来说已经足够了。
- 机器学习框架:迎合 TinyML 需求的框架屈指可数。其中, TensorFlow Lite 最受欢迎,拥有最多的社区支持。使用 TensorFlow Lite Micro,我们可以在微控制器上部署模型。
- 学习资源:由于 TinyML 是一个新兴领域,所以到目前为止学习资料还不多。但也有少数优秀的资料像 Pete Warden 和 Daniel Situnayake 的书《TinyML:在 Arduino 和超低功耗上用 TensorFlow Lite 进行机器学习》哈佛大学关于 TinyML 的课程 Vijay Janapa Reddi 和 Digikey 关于 TinyML 的博客和视频。
结论
微控制器无处不在,它们收集大量的数据。有了 TinyML,我们可以利用这些数据来构建更好的产品。今天有超过 2500 亿个微控制器单元,并且这个数字在未来只会增加。这会导致价格降低(因为,经济学!咄!).在微控制器中实现机器学习将开启新的机遇。
关于我
我是一个对 AI 研发感兴趣的学生。我喜欢写一些较少谈论的人工智能主题,如联邦学习,图形神经网络,人工智能中的公平,量子机器学习,TinyML 等。关注我,了解我未来所有博客的最新动态。
你可以在 Twitter 、 LinkedIn 和 Github 上找到我。
如何用 Python 对 Tweets 进行标记
我们应该选择 TweetTokenizers 还是其他 4 种常见的 Tokenizers?
什么是标记化?
记号是整体的一个片段,所以单词是句子中的记号,句子是段落中的记号。记号化是将一个字符串分割成一系列记号的过程。
如果你对标记化有点熟悉,但不知道文本使用哪种标记化,本文将使用 Twitter 上的原始 Tweets 来展示不同的标记化及其工作原理。
本文将介绍如何用以下语句将句子标记成单词:
word_tokenize
WordPunctTokenizer
RegrexTokenizer
TweetTokenizer
标记化是预处理原始文本的第一步,所以我希望您对掌握这个重要的概念感到兴奋!
照片由 Eric Prouzet 拍摄于 Unsplash
要处理的数据
Twitter 是一个社交平台,每天都会发布许多有趣的推文。因为与正式文本相比,tweets 更难标记,所以我们将使用 tweets 中的文本数据作为示例。
"https://t.co/9z2J3P33Uc FB needs to hurry up and add a laugh/cry button 😬😭😓🤢🙄😱 Since eating my feelings has not fixed the world's problems, I guess I'll try to sleep... HOLY CRAP: DeVos questionnaire appears to include passages from uncited sources [https://t.co/FNRoOlfw9s](https://t.co/FNRoOlfw9s) well played, Senator Murray Keep the pressure on: [https://t.co/4hfOsmdk0l](https://t.co/4hfOsmdk0l) @datageneral thx Mr Taussig It's interesting how many people contact me about applying for a PhD and don't spell my name right."
上面的句子里有很多信息。在对整个句子进行记号化之前,我们先挑选一些我们有兴趣比较的句子。这个列表将用于比较不同令牌化器之间的性能。
compare_list = ['[https://t.co/9z2J3P33Uc'](https://t.co/9z2J3P33Uc'),
'laugh/cry',
'😬😭😓🤢🙄😱',
"world's problems",
"[@datageneral](http://twitter.com/datageneral)",
"It's interesting",
"don't spell my name right",
'all-nighter']
word_tokenize
将句子标记成单词时最流行的方法是使用word_tokenize.
和空格和标点符号将单词分开。
from nltk.tokenize import word_tokenizeword_tokens = []
for sent in compare_list:
print(word_tokenize(sent))
word_tokens.append(word_tokenize(sent))
结果:
['https', ':', '//t.co/9z2J3P33Uc']
['laugh/cry']
['😬😭😓🤢🙄😱']
['world', "'s", 'problems']
['@', 'datageneral']
['It', "'s", 'interesting']
['do', "n't", 'spell', 'my', 'name', 'right']
['all-nighter']
我们希望laugh/cry
被拆分成 2 个单词。所以我们应该考虑另一个记号赋予器选项。
单词标点符号化器
WordPunctTokenizer
将所有标点符号拆分成单独的记号。所以这可能就是我们想要的?
from nltk.tokenize import WordPunctTokenizerpunct_tokenizer = WordPunctTokenizer()punct_tokens = []
for sent in compare_list:
print(punct_tokenizer.tokenize(sent))
punct_tokens.append(punct_tokenizer.tokenize(sent))
结果:
['https', '://', 't', '.', 'co', '/', '9z2J3P33Uc']
['laugh', '/', 'cry']
['😬😭😓🤢🙄😱']
['world', "'", 's', 'problems']
['@', 'datageneral']
['It', "'", 's', 'interesting']
['don', "'", 't', 'spell', 'my', 'name', 'right']
['all', '-', 'nighter']
嗯,这个分词器成功地把laugh/cry
拆分成两个单词。但是缺点是:
- 链接
‘[https://t.co/9z2J3P33Uc'](https://t.co/9z2J3P33Uc')
被分成 7 个单词 world's
被"'"
字符拆分成两个单词@datageneral
分为@
和datageneral
don't
被拆分为do
和n't
既然这些单词应该被认为是一个单词,那么这个分词器也不是我们想要的。有没有一种方法可以根据空格来拆分单词?
再氧化器
由于没有分词器专门根据空格拆分单词,我们可以使用RegrexTokenizer
来控制如何对文本进行分词。有两种方法可以避免根据标点符号或缩写来拆分单词:
- 在代币上匹配
- 匹配分隔符或间隙
在代币上匹配
RegexpTokenizer
类通过编译我们的模式,然后在我们的文本上调用re.findall()
来工作。我们可以利用这个函数来匹配字母数字标记和单引号
from nltk.tokenize import RegexpTokenizer
match_tokenizer = RegexpTokenizer("[\w']+")match_tokens = []
for sent in compare_list:
print(match_tokenizer.tokenize(sent))
match_tokens.append(match_tokenizer.tokenize(sent))
如果您不熟悉正则表达式语法,\w+
匹配一个或多个单词字符(字母数字&下划线)
结果:
['https', 't', 'co', '9z2J3P33Uc']
['laugh', 'cry']
[]
["world's", 'problems']
['datageneral']
["It's", 'interesting']
["don't", 'spell', 'my', 'name', 'right']
['all', 'nighter']
虽然像'world’s', 'It’s', 'don’t’
这样的单词如我们所愿被保留为一个实体,但是‘[https://t.co/9z2J3P33Uc'](https://t.co/9z2J3P33Uc')
仍然被拆分成不同的单词,并且我们失去了“datageneral”
之前的“@”
字符。也许我们可以根据空白分割?
空白匹配
RegexpTokenizer
也可以通过匹配缺口来工作。当添加参数gaps=True
时,匹配模式将被用作分隔符。\s+
匹配一个或多个空格。
space_tokenizer = RegexpTokenizer("\s+", gaps=True)space_tokens = []
for sent in compare_list:
print(space_tokenizer.tokenize(sent))
space_tokens.append(space_tokenizer.tokenize(sent))
结果:
['https://t.co/9z2J3P33Uc']
['laugh/cry']
['😬😭😓🤢🙄😱']
["world's", 'problems']
['@datageneral']
["It's", 'interesting']
["don't", 'spell', 'my', 'name', 'right']
['all-nighter']
不错!现在我们将链接‘https://t.co/9z2J3P33Uc'
解释为一个单词!但是看起来表情符号组合成了一个单词。由于不同的表情符号在情感分析中可能是有意义的,我们可能希望将它们分成不同的单词。所以我们需要考虑另一种正则表达式模式来实现这一点。
好消息!有一个标记器可以在不使用正则表达式的情况下有效地拆分 tweets。
TweetTokenizer
是的,对 tweet 进行标记的最好方法是使用标记器来标记 tweet
from nltk.tokenize import TweetTokenizer
tweet_tokenizer = TweetTokenizer()tweet_tokens = []
for sent in compare_list:
print(tweet_tokenizer.tokenize(sent))
tweet_tokens.append(tweet_tokenizer.tokenize(sent))
结果:
['https://t.co/9z2J3P33Uc']
['laugh', '/', 'cry']
['😬', '😭', '😓', '🤢', '🙄', '😱']
["world's", 'problems']
['@datageneral']
["It's", 'interesting']
["don't", 'spell', 'my', 'name', 'right']
['all-nighter']
厉害!推文被标记成我们想要的样子!
把所有东西放在一起
我们可以把所有东西放在一个pd.dataframe
中进行快速准确的解释,而不是花时间去分析每个分词器的结果。
import pandas as pdtokenizers = {'word_tokenize': word_tokens,
'WordPunctTokenize':punct_tokens,
'RegrexTokenizer for matching':match_tokens,
'RegrexTokenizer for white space': space_tokens,
'TweetTokenizer': tweet_tokens }df = pd.DataFrame.from_dict(tokenizers)
不同标记器之间的比较
根据对上表的观察,TweetTokenizer
似乎是最佳选择。所以我们可以继续用这个来标记我们的句子:
tweet_tokenizer.tokenize(sent)
结论
恭喜你!您已经从 nltk 库中学习了不同的分词器来将句子分词。似乎标记 Twitter 原始文本的赢家是TweetTokenizer
。但情况并非总是如此,你的选择可能会根据你分析的文本而改变。重要的一点是,您知道这些标记器的功能差异,这样您就可以做出正确的选择来标记您的文本。在这个 Github repo 中,您可以随意使用本文的代码。
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上和我联系。
如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:
关于如何使用 Beautiful Soup 的分步教程,这是一个用于 web 抓取的简单易用的 Python 库
towardsdatascience.com](/step-by-step-tutorial-web-scraping-wikipedia-with-beautifulsoup-48d7f2dfa52d) [## 用 Python 模块 Newspaper 和 NLTK 查找文章中的常用词
使用 newspaper3k 和 NLTK 从报纸中提取信息和发现见解的分步指南
towardsdatascience.com](/find-common-words-in-article-with-python-module-newspaper-and-nltk-8c7d6c75733) [## 跟踪数据的 Python 技巧
如何用列表、字典计数器和命名元组来跟踪信息
towardsdatascience.com](/python-tricks-for-keeping-track-of-your-data-aef3dc817a4e) [## 使用 Python 最大化您的生产力
你创建了一个待办事项清单来提高效率,但最终却把时间浪费在了不重要的任务上。如果你能创造…
towardsdatascience.com](/maximize-your-productivity-with-python-6110004b45f7) [## 高效 Python 代码的计时
如何比较列表、集合和其他方法的性能
towardsdatascience.com](/timing-the-performance-to-choose-the-right-python-object-for-your-data-science-project-670db6f11b8e)
Unity ML-agent 简介
Unity-ML 代理课程
训练一个强化学习代理跳过墙。
我们推出了新的免费、更新、 深度强化学习课程从初学者到专家,用拥抱面对🤗
👉新版教程:https://huggingface.co/deep-rl-course/unit0/introduction
下面的章节是以前的版本,新版本在这里👉https://huggingface.co/deep-rl-course/unit5/introduction?fw=pt
我们推出了新的免费、更新、 从初学者到专家的深度强化学习课程,用拥抱面对🤗
👉新版教程:https://huggingface.co/deep-rl-course/unit0/introduction
下面的章节是以前的版本,新版本在这里👉https://huggingface.co/deep-rl-course/unit5/introduction?fw=pt
过去的几年见证了强化学习的突破。从 2013 年深度学习模型首次成功使用 RL 从像素输入学习策略到 2019 年 OpenAI 灵巧程序,我们生活在 RL 研究的一个激动人心的时刻。
因此,作为 RL 研究人员,我们需要创造越来越复杂的环境,Unity 帮助我们做到这一点。Unity ML-Agents toolkit 是一个基于游戏引擎 Unity 的新插件,允许我们使用 Unity 游戏引擎作为环境构建器来训练代理。
来源:Unity ML-Agents Toolkit Github 存储库
从踢足球、学习走路、跳过高墙,到训练一只可爱的小狗去抓棍子,Unity ML-Agents Toolkit 提供了大量令人惊叹的预制环境。
此外,在这个免费课程中,我们还将创造新的学习环境。
现在,我们将学习 Unity ML-Agents 是如何工作的,在文章的最后,您将训练一个代理学习FQ。
但是首先,有一些要求:
- 这不是强化学习入门课程,如果你之前没有深度强化学习的技巧,需要查看免费课程【Tensorflow 深度强化学习。
- 而且这不是一门关于 Unity 的课程,所以你需要有一些 Unity 基本功。如果不是这样,你绝对应该看看他们为初学者开设的令人惊叹的课程:用代码创造。
所以让我们开始吧!
Unity ML-Agents 如何工作?
什么是 Unity ML-Agents?
Unity ML-Agents 是游戏引擎 Unity 的一个新插件,它允许我们创建或使用预先制作的环境来训练我们的代理。
它是由 Unity Technologies 开发的,Unity 是有史以来最好的游戏引擎之一。这是 Firewatch,Gone Home,Cuphead 和许多 AAA 游戏的创作者使用的。
Firewatch 是用 Unity 做的
三个组成部分
使用 Unity ML-Agents,您有三个重要的组件。
来源:Unity ML-Agents 文档
第一个是学习组件(关于 Unity),即包含 Unity 场景和环境元素。
第二个是 Python API 包含 RL 算法(比如 PPO 和 SAC)。我们使用这个 API 来启动培训、测试等。它通过外部通信器与学习环境通信。
在学习组件内部
在学习组件中,我们有不同的元素:
来源:Unity ML-Agents 文档
首先是经纪人,现场的演员。他就是我们要通过优化他的策略(这将告诉我们在每种状态下采取什么行动)来训练的人。
最后,还有学院,这个元素编排代理和他们的决策过程。把这个学院想象成处理来自 python API 的请求的大师。
为了更好地理解它的作用,让我们回忆一下 RL 过程。这可以建模为一个循环,其工作方式如下:
来源:萨顿的书
现在,让我们想象一个代理学习玩一个平台游戏。RL 流程如下所示:
- 我们的代理从环境接收状态 S0—我们接收游戏的第一帧(环境)。
- 基于状态 S0,代理采取行动 A0 —我们的代理将向右移动。
- 环境过渡到一个新的状态 S1。
- 给代理一个奖励 R1——我们没死(正奖励+1) 。
这个 RL 循环输出状态、动作和奖励的序列。代理人的目标是最大化期望的累积报酬。
事实上,学院将向我们的代理发送订单,并确保代理同步:
- 收集观察结果
- 使用您的策略选择您的操作
- 采取行动
- 如果达到最大步数或完成,则重置。
训练一名特工FQ
现在我们已经了解了 Unity ML-Agents 的工作原理,让我们来训练一个代理从墙上跳下来。
我们在 github 上发布了我们训练过的模型,你可以在这里下载 。
跳墙环境
在这种环境下,我们的目标是训练我们的代理人走上绿区。
但是,有 3 种情况:
- 首先,你没有墙,我们的代理只需要走上绿色瓷砖。
无墙情况
- 在第二种情况下,代理需要学习跳跃以到达绿色瓷砖。
小墙情况
- 最后,在最困难的情况下,我们的代理人将无法跳得和墙一样高,所以他需要推动白色方块以便跳到它上面来跳过墙。
大墙情况
我们将根据墙的高度学习两种不同的政策:
- 第一个小墙跳将在无墙和矮墙情况下学习。
- 第二个,大墙跳跃,将在高墙情况下学习。
奖励制度是:
在观察方面,我们没有使用正常视觉(帧),而是 14 个光线投射,每个光线投射可以探测 4 个可能的物体。把光线投射想象成激光,如果它穿过物体就会被探测到。
我们还使用代理的全球位置以及是否接地。
来源:Unity ML-Agents 文档
动作空间是离散的,有 4 个分支:
我们的目标是以 0.8 的平均回报达到基准。
我们跳吧!
首先我们打开 UnitySDK 项目。
在示例中搜索 WallJump 并打开场景。
你可以在场景中看到,许多代理,他们每个人都来自同一个预置,他们都共享同一个大脑。
同一个代理预置的多个副本。
事实上,正如我们在经典的深度强化学习中所做的那样,当我们启动一个游戏的多个实例(例如 128 个并行环境)时,我们在此复制并粘贴代理,以便有更多不同的状态。
所以,首先,因为我们想从头开始训练我们的特工,我们需要从特工身上移除大脑。我们需要进入预置文件夹并打开预置。
现在在预设层级中,选择代理并进入检查器。
首先,在行为参数中,我们需要移除模型。如果你有一些图形处理器,你可以把推理机从 CPU 改成 GPU。
然后在跳墙代理组件中,我们需要移除无墙脑、小墙脑和大墙脑情况下的大脑。
现在你已经完成了,你可以从头开始训练你的代理了。
对于第一次训练,我们将只修改两个策略(SmallWallJump 和 BigWallJump) 的总训练步骤,因为我们只需要 300k 的训练步骤就可以达到基准。
为此,我们转到,您可以在config/trainer _ config . YAML中将 SmallWallJump 和 BigWallJump 情况下的这些步骤修改为 max_steps 至 3e5
为了训练这个代理,我们将使用 PPO (近似策略优化)如果你不知道或者你需要刷新你的知识,查看我的文章。
我们看到,为了训练这个代理,我们需要使用 Python API 调用我们的外部通信器。该外部通信器将要求学院启动代理。
因此,您需要打开您的终端,进入 ml-agents-master 所在的位置并键入以下内容:
mlagents-learn config/trainer_config.yaml — run-id=”WallJump_FirstTrain” — train
它会要求你运行 Unity 场景,
按下编辑器顶部的▶️按钮。
您可以使用以下命令启动 Tensorboard 来监控您的训练:
tensorboard — logdir=summaries
看着你的特工FQ
你可以在训练的时候通过观看游戏窗口来观察你的经纪人。
培训结束后,您需要将保存在ML-Agents-master/models中的模型文件移动到unity SDK/Assets/ML-Agents/Examples/wall jump/TF models中。
再次打开 Unity 编辑器,选择 WallJump 场景。
选择 WallJumpArea 预设对象并打开它。
选择代理。
在代理行为参数中,拖动 SmallWallJump.nn 文件到模型占位符中。
将 SmallWallJump.nn 文件拖到无墙脑占位符。
将 SmallWallJump.n n 文件拖到小墙脑占位符中。
将 BigWallJump.nn 文件拖到无墙脑占位符。
然后,按下编辑器顶部的▶️按钮,瞧!
🎉
是时候做些实验了
我们刚刚训练我们的特工学会了FQ。既然我们有了好的结果,我们可以做一些实验。
记住,最好的学习方法是通过实验保持活跃。所以你要试着做一些假设,并验证它们。
将贴现率降至 0.95
我们知道:
- γ越大,折扣越小。这意味着学习代理更关心长期回报。
- 另一方面,伽玛越小,折扣越大。这意味着我们的代理更关心短期回报。
这个实验背后的想法是,如果我们通过将 gamma 从 0.99 降低到 0.95 来增加折扣,我们的代理将会更关心短期回报,也许这将帮助他更快地收敛到最优策略。
有趣的是,我们的代理人在小墙跳跃的情况下表现完全相同,我们可以解释说,这种情况很容易,如果有小墙,他只需要向绿色网格移动并跳跃。
另一方面,在大墙跳的情况下表现真的很差。我们可以解释说,因为我们的新代理更关心短期回报,他无法进行长期思考,因此没有真正理解他需要推动白砖才能跳过墙。
增加了神经网络的复杂性
对于第三次也是最后一次培训,假设是如果我们增加网络复杂性,我们的代理会变得更聪明吗?
我们所做的是将隐藏单元的大小从 256 增加到 512。
但是我们发现这个新代理的表现比我们的第一个代理差。
这意味着当我们遇到这种简单的问题时,我们不需要增加网络的复杂性,因为这增加了收敛之前的训练时间。
今天就到这里吧!你刚刚训练了一个学会FQ的特工。厉害!
别忘了去实验,换一些超参数试试新闻的东西。玩得开心!
如果你想和我们的实验进行比较,我们在这里公布了我们训练过的模型 。
在下一篇文章中,我们将训练一个智能代理,它需要按下一个按钮来生成一个金字塔,然后导航到金字塔,撞倒它,并移动到顶部的金砖。为了做到这一点,除了外在奖励,我们还将好奇心作为内在奖励。
如果你有任何想法,评论,问题,欢迎在下面评论或者给我发邮件:hello@simoninithomas.com,或者发推特给我。
不断学习,保持牛逼!
第 2 章:深入探究 Unity-ML 代理
第三章:玛雅奇遇
变分自动编码器介绍
使用 PyTorch 从理论到实践理解变分自动编码器
来自https://joanielemercier.com/的艺术作品(纽约艾雅法拉火山,2010 年 5 月 onedotzero 委托)
VAE 是潜在变量模型[1,2]。这种模型依赖于这样的思想,即由模型生成的数据可以通过一些变量来参数化,这些变量将生成给定数据点的一些特定特征。这些变量被称为潜在变量。
VAE 背后的一个关键思想是,我们不是试图显式地构建一个潜在空间(潜在变量的空间)并从中进行采样,以便找到可以实际生成适当输出(尽可能接近我们的分布)的样本,而是构建一个类似编码器-解码器的网络,该网络分为两部分:
- 编码器学习生成依赖于输入样本 X 的分布,从中我们可以采样很可能生成 X 个样本的潜在变量。换句话说,我们学习一组参数θ1,它们产生一个分布 Q(X,θ1 ),从中我们可以采样一个潜在变量 z,使 P(X|z)最大化。
- 给定潜在变量 z 作为输入,解码器部分学习生成属于真实数据分布的输出。换句话说,我们学习一组参数θ2,该参数生成函数 f(z,θ2 ),该函数将我们学习的潜在分布映射到数据集的真实数据分布。
可变自动编码器全局架构
为了理解变分自动编码器背后的数学,我们将通过理论,看看为什么这些模型比旧的方法更好。
本文将涵盖以下内容
- 如何定义建筑的潜在空间
- 如何从潜在空间采样中高效地生成数据?
- VAEs 的最终架构
- 一些显示 VAEs 有趣性质的实验
1.潜在变量模型
潜在变量模型来源于这样一种想法,即模型生成的数据需要通过潜在变量来参数化。这个名字来源于这样一个事实:给定的只是模型产生的一个数据点,我们不一定知道潜在变量的哪些设置产生了这个数据点。
在一个更正式的设置中,我们在高维空间 Z 中有一个潜在变量的向量 z ,我们可以根据 Z 上定义的某个概率密度函数 P ( z )轻松地对其进行采样。然后,我们有一族确定性函数f(Z; θ ,由某空间θ中的一个向量 θ 参数化,其中f:Z×θ→x .f是确定性的,但如果 z 是随机的, θ 是固定的,那么f(Z; θ 是空间 X 中的随机变量。
在训练过程中,我们对 θ 进行了优化,使得我们可以从 P ( z )中采样 z ,并且有很大概率得到f(z); θ 与数据集中的 X 一样近。为了实现这一点,我们需要找到参数 θ ,使得:
这里我们只是把f(z); θ 乘一个分配P(X|z; θ 为了利用全概率定律使 X 对 z 的依赖关系显式。我们做的另一个假设是假设 P(W | z; θ )遵循高斯分布 N(X |f(z; θ ),σ*I)(这样做我们认为生成的数据几乎为 X 但不完全为 X)。
定义潜在空间
正如开始所解释的,潜在空间被认为是对影响我们数据分布的某些特定特征的变量空间进行建模。我们可以想象,如果我们考虑的数据集由汽车组成,那么我们的数据分布就是所有可能的汽车的空间,我们潜在向量的一些分量会影响汽车的颜色、方向或门的数量。
然而,很快就很难明确定义每个潜在组件的角色,尤其是当我们处理数百个维度时。除此之外,一些组件可以依赖于其他组件,这使得手工设计这个潜在空间变得更加复杂。换句话说,定义这个复杂的分布 P(z)真的很难。
解决办法
为了克服这个问题,诀窍是利用概率分布的数学性质和神经网络的能力,在具有反向传播的某些约束下学习某些确定性函数。
使问题更容易处理的数学特性是:
通过取一组正态分布的 d 变量,并通过一个足够复杂的函数对它们进行映射,可以生成 d 维中的任何分布。
因此,我们可以任意决定我们的潜在变量为高斯型,然后构建一个确定性函数,将我们的高斯潜在空间映射到复杂的分布中,我们将从该分布中采样以生成我们的数据。
将我们简单的潜在分布映射到代表我们复杂潜在空间的更复杂的潜在分布所需的确定性函数可以使用神经网络来构建,该神经网络具有一些可以在训练期间微调的参数。
2.学会从潜在空间中产生数据
在进入本文有趣的部分之前,让我们回忆一下我们的最终目标:
我们有一个正态分布的 d 维潜在空间,我们想学习一个函数 f(z;θ2),这将把我们的潜在分布映射到我们的真实数据分布。换句话说,我们希望对潜在变量进行采样,然后使用该潜在变量作为生成器的输入,以便生成尽可能接近真实数据点的数据样本。
我们仍然需要解决两件事:
- 我们如何有效地探索我们的潜在空间,以便发现使概率 P(X|z)最大化的 z?(我们需要在训练中为给定的 X 找到正确的 z)
- 我们如何使用反向传播来训练这整个过程?(我们需要找到一个优化 f 的目标,将 P(z)映射到 P(X))
为我们的 X 数据样本找到正确的 z 潜变量
实际上,对于大多数的 z , P (X|z)几乎为零,因此对我们估计的 P (X)几乎没有贡献。变分自动编码器背后的关键思想是试图对可能产生 X 的 z 值进行采样,并根据这些值计算 P(X)。为了做到这一点,我们需要一个新的函数 Q (z|X ),它可以取值为 X,并给出一个可能产生 X 的 z 值的分布。希望可能在 Q 下的 z 值的空间将比可能在前一个 P(z)下的所有 z 的空间小得多。
VAE 的这一部分将是编码器,并且我们将假设 Q 将在训练期间由神经网络学习,该神经网络将输入 X 映射到输出 Q(z|X ),这将是我们最有可能从中找到好的 z 以生成该特定 X 的分布
用反向传播训练模型
为了理解如何训练我们的 VAE,我们首先需要定义什么应该是目标,而要做到这一点,我们首先需要做一点数学。
让我们从编码器开始,我们希望 Q(z|X)尽可能接近 P(X|z)。为了测量两个分布有多接近,我们可以使用两个分布之间的 Kullback-Leibler 散度 D:
用一点数学知识,我们可以用一种更有趣的方式改写这个等式。
通过对 P(z|X)应用贝叶斯规则,我们得到:
这相当于:
让我们花点时间看看这个公式
- A 部分:左边的项对我们的反向传播设置并不感兴趣(我们不知道 P(X)的简单表达式),但 log(P(X))实际上是给定 z 后我们想要最大化的,我们可以看到,我们可以通过最小化右边的部分来实现这一点(使 Q(z|X)尽可能接近 P(z|X))。这正是我们一开始提到的。
- B 部分:这个术语更有趣,因为我们知道 P(X|z)(它是我们的解码器部分- >生成器)和 Q(z|X)(它是我们的编码器)。我们可以看到,为了最大化该项,我们需要最大化 log(P(X|z)),这意味着我们不想最大化概率的对数似然性,并最小化 Q(z|X)和 P(z)之间的 KL 散度。
为了使部分 B 更容易计算,假设 Q(z|X)是高斯分布 N(z|mu(X,θ1),sigma(X,θ1)),其中θ1 是我们的神经网络从我们的数据集中学习的参数。
我们的公式还有一个问题不清楚:我们如何在反向传播过程中计算期望值?
处理期望操作符
一种方法是进行多次前向传递,以便能够计算对数(P(X|z))的期望,但是这在计算上是低效的。有希望的是,由于我们处于随机训练中,我们可以假设我们在历元期间使用的数据样本 Xi 代表整个数据集,因此有理由认为我们从该样本 Xi 获得的 log(P(Xi|zi))和相关生成的 zi 代表 log(P(X|z))的 Q 上的期望。
最后,解码器只是一个生成器模型,我们希望重建输入图像,因此一个简单的方法是使用输入图像和生成图像之间的均方误差。
3.VAEs 的最终架构
我们可以知道恢复一个 VAE 的最终架构。如简介中所述,网络分为两部分:
- 学习生成依赖于输入样本 X 的分布的编码器,我们可以从中对很可能生成 X 个样本的潜在变量进行采样。这部分需要优化,以使 Q(z|X)成为高斯型。
- 给定潜在变量 z 作为输入,解码器部分学习生成属于真实数据分布的输出。该部分将采样的 z(最初来自正态分布)映射到更复杂的潜在空间(实际代表我们的数据的空间),并从该复杂的潜在变量 z 生成尽可能接近我们分布中真实数据点的数据点。
可变自动编码器详细架构。(左)和(右)是等价的,但是我们不能在(左)的例子中进行反向传播,所以我们在实践中使用(右)的例子。
4.VAEs 实验
现在你已经知道了变分自动编码器背后的所有数学原理,让我们通过使用 PyTorch 做一些实验来看看我们能用这些生成模型做些什么。
py torch 的全球建筑
训练
下面的图表显示了我们在训练中得到的结果。为了这个演示,VAE 已经在 MNIST 数据集[3]上进行了训练。每隔 10 个时期,我们绘制输入 X 和产生该给定输入的 VAE 的生成数据。
训练样本(输入向上,输出向下)—时期 1
训练样本(输入向上,输出向下)—时期 10
训练样本(输入向上,输出向下)—时期 20
训练样本(输入向上,输出向下)—时期 30
训练样本(输入向上,输出向下)—时期 40
训练样本(输入向上,输出向下)—时期 50
潜在空间
关于 VAEs 的一个有趣的事情是,在训练期间学习的潜在空间有一些很好的连续性。我们可以通过考虑一个二维潜在空间来可视化这些性质,以便能够在 2D 容易地可视化我们的数据点。
当查看在训练期间学习的 2D 潜在空间中的 MNIST 数据集样本的重新划分时,我们可以看到相似的数字被分组在一起(绿色的3
都被分组在一起并且接近非常相似的8
)。
2D 潜在空间可视化
更直观地理解潜在空间连续性的一个好方法是观察潜在空间区域生成的图像。我们可以在下图中看到,当在潜在空间中移动时,数字被平滑地转换成如此相似的数字。
从 2D 潜在空间抽样生成的数字
结论
变分自动编码器真的是一个惊人的工具,由于神经网络的力量,解决了一些真正具有挑战性的生成模型问题。与以前的方法相比,VAEs 解决了两个主要问题:
- 如何对潜在空间中最相关的潜在变量进行采样,以产生给定的输出。
- 如何将潜在的空间分布映射到真实的数据分布。
然而,vae 也有一些缺点:
- 生成的图像是模糊的,因为均方误差倾向于使生成器收敛到平均最优值。
生成式反向串行网络(GANs)通过使用鉴别器而不是均方误差损失来解决后一个问题,并产生更真实的图像。然而,GAN 潜在空间非常难以控制,并且不具有(在经典设置中)像 VAEs 那样的连续性特性,而 VAEs 有时是某些应用所需要的。
参考
[1]多尔施,c,2016。变分自动编码器教程。 arXiv 预印本 arXiv:1606.05908 。
[2]金玛,D.P .和韦林,m .,2019。变分自动编码器导论。 arXiv 预印本 arXiv:1906.02691 。
[3]http://yann.lecun.com/exdb/mnist/MNIST 数据集
密码
我在神经网络上做的所有实验的集合
github.com](https://github.com/sinitame/neural-networks-experiments)
面向数据科学家的 NLP 入门指南,包含 7 种常用技术
自然语言处理的基础
我为学习者写了一份名为《强大的知识》的时事通讯。每一期都包含链接和最佳内容的关键课程,包括引文、书籍、文章、播客和视频。每一个人都是为了学习如何过上更明智、更快乐、更充实的生活而被挑选出来的。 在这里报名 。
现代组织处理大量数据。这些数据可能以各种不同的形式出现,包括文档、电子表格、录音、电子邮件、JSON 等等。记录此类数据的最常见方式之一是通过文本。这种文字通常与我们日常使用的自然语言非常相似。
自然语言处理 (NLP)是对编程计算机处理和分析大量自然文本数据的研究。自然语言处理的知识对于数据科学家来说是必不可少的,因为文本是一种非常容易使用和常见的存储数据的容器。
面对从文本数据执行分析和构建模型的任务,人们必须知道如何执行基本的数据科学任务。这包括清理、格式化、解析、分析、可视化和建模文本数据。当数据由原始数字组成时,除了通常的完成这些任务的方法之外,还需要一些额外的步骤。
本指南将教你在数据科学中使用 NLP 的要点。我们将介绍 7 种最常用的处理文本数据的技术,包括使用 NLTK 和 Scikit Learn 的代码示例。
(1)标记化
标记化是将文本分割成句子或单词的处理。在这个过程中,我们也扔掉了标点符号和多余的符号。
这并不像看起来那么简单。例如,上面第一个例子中的单词“New York”被分成两个标记。然而,纽约是一个代名词,在我们的分析中可能相当重要——我们最好只使用一个标记。因此,在这一步需要小心。
标记化的好处是,它将文本转换成一种更容易转换成原始数字的格式,这实际上可以用于处理。在分析文本数据时,这是很自然的第一步。
(2)停用字词删除
标记化后的下一个自然步骤是停用词移除。停用词的移除与标记化有着相似的目标:将文本数据转换成更便于处理的格式。在这种情况下,停用字词删除会删除英语中常见的语言介词,如“and”、“the”、“a”等。这样,当我们分析我们的数据时,我们将能够穿过噪音并专注于具有实际现实意义的单词。
通过删除预定义列表中的单词,可以很容易地删除停用词。需要注意的一点是,没有通用的停用词列表。因此,该列表通常是从头开始创建的,并根据正在处理的应用程序进行定制。
(3)堵塞
词干处理是另一种清理文本数据进行处理的技术。词干化是将单词还原成其词根形式的过程。这样做的目的是将因上下文而拼写略有不同但含义相同的单词减少到相同的标记中进行处理。例如,考虑在句子中使用“cook”这个词。根据上下文的不同,我们可以用很多方法来写“cook ”:
所有这些不同形式的单词 cook 本质上都有相同的定义。因此,理想情况下,当我们进行分析时,我们希望它们都映射到同一个令牌。在本例中,我们将它们都映射到单词“cook”的标记。这大大简化了我们对文本数据的进一步分析。
(4)单词嵌入
既然我们的数据已经从前三种方法中清除了,我们就可以开始把它转换成一种实际上可以处理的格式。
单词嵌入是一种将单词表示为数字的方式,通过这种方式,具有相似含义的单词具有相似的表示。现代的单词嵌入将单个单词表示为预定义向量空间中的实值向量。
所有的单词向量都有相同的长度,只是值不同。两个词向量之间的距离代表两个词的意思有多相似。例如,单词“cook”和“bake”的向量会相当接近,但是单词“football”和“bake”的向量会相当不同。
创建单词嵌入的一种常见方法叫做 GloVe ,代表“全局向量”。GloVe 捕获文本语料库的全局统计和局部统计,以便创建单词向量。
GloVe 使用所谓的共生矩阵。共现矩阵表示每对单词在文本语料库中一起出现频率。例如,考虑我们将如何为以下三个句子创建共现矩阵:
- 我喜欢数据科学。
- 我喜欢编码。
- 我应该学 NLP。
该文本语料库的共现矩阵如下所示:
对于真实世界的数据集,矩阵会大得多,大得多。好的方面是单词嵌入只需要为数据计算一次,然后就可以保存到磁盘上。
然后,GloVe 被训练来学习每个单词的固定长度的向量,使得任何两个单词的向量的点积等于来自共现矩阵的单词共现概率的对数。这表现在如下所示的纸的目标函数中:
在等式中, X 表示来自位置 (i,j) 处的共生矩阵的值,并且w’s 是要学习的单词向量。因此,通过使用该目标函数,GloVe 最小化了两个单词向量的点积和同现之间的差异,有效地确保了所学习的向量与矩阵中的同现值相关。
在过去的几年中,GloVe 已经被证明是一种非常健壮和通用的单词嵌入技术,这是由于它对单词的含义及其相似性进行了有效的编码。对于数据科学应用,这是一种久经考验的方法,可以将文字转换成我们可以处理和分析的格式。
这里有一个关于如何在 Python 中使用 GloVe 的完整教程!
(5)术语频率-逆文档频率
词频-逆文档频率,更普遍的说法是 TF-IDF,是一种常用于信息检索、文本挖掘等应用的权重因子。TF-IDF 使用统计数据来衡量一个单词对特定文档的重要性。
- TF —术语频率:测量字符串在文档中出现的频率。计算方式为文档中出现的总次数除以文档的总长度(用于标准化)。
- IDF —逆文档频率:衡量一个字符串在文档中的重要性。例如,某些字符串,如“is”、“of”和“a ”,会在许多文档中出现很多次,但实际上并没有太多意义——它们不是形容词或动词。因此,IDF 根据每个字符串的重要性对其进行加权,计算方法是数据集中文档总数的 log() 除以该字符串出现的文档数(分母加 1,以避免被零除)。
- TF-IDF:TF-IDF 的最终计算就是 TF 和 IDF 项的简单相乘: TF * IDF 。
考虑到目标词的局部和全局统计水平,TF-IDF 是完美平衡的。在文档中出现频率较高的单词权重较高,但前提是它们在整个文档中出现频率较低。
由于其鲁棒性,TF-IDF 技术经常被搜索引擎用来对给定关键字输入的文档相关性进行评分和排序。在数据科学中,我们可以使用它来了解哪些单词和相关信息在我们的文本数据中是最重要的。
(6)主题建模
主题建模,在 NLP 的上下文中,是从文本数据或文档的集合中提取主要主题的过程。本质上,这是一种形式的维度缩减,因为我们将大量的文本数据缩减为更少的主题。主题建模在许多数据科学场景中都很有用。仅举几个例子:
- 文本的数据分析——提取数据的潜在趋势和主要成分
- 对文本进行分类——与降维有助于解决经典的机器学习问题类似,主题建模在这里也有帮助,因为我们将文本压缩到关键特征中,在这种情况下,就是主题
- 构建推荐系统——主题建模自动为我们提供文本数据的一些基本分组。它甚至可以作为构建和训练模型的附加功能
主题建模通常使用一种叫做 潜在狄利克雷分配 (LDA)的技术来完成。使用 LDA,每个文本文档被建模为主题的多项式分布,并且每个主题被建模为单词的多项式分布(单个字符串,我们可以从我们的标记化、停用词移除和词干化的组合中获得)。
LDA 假设文档是由主题组合产生的。然后,这些主题根据它们的概率分布生成单词。
我们首先告诉 LDA 每个文档应该有多少个主题,以及每个主题由多少个单词组成。给定一个文档数据集,LDA 试图确定什么样的主题组合和分布可以准确地重新创建这些文档和其中的所有文本。它可以通过构建实际的文档来判断哪个(哪些)主题起作用,其中构建是通过给定所选主题,根据单词的概率分布对单词进行采样来完成的。
一旦 LDA 找到了能够最准确地在数据集中重新创建所有文档及其内容的主题分布,那么这些就是我们具有适当分布的最终主题。
(7)情感分析
情感分析是一种 NLP 技术,试图识别和提取文本数据中包含的主观信息。与主题建模类似,情感分析可以帮助将非结构化文本转换为嵌入数据中的信息的基本摘要。
大多数情感分析技术分为两类:基于规则的方法和机器学习方法。基于规则的方法遵循简单的步骤来实现它们的结果。在进行了一些文本预处理(如标记化、停用词移除和词干化)之后,基于规则的可以例如经历以下步骤:
- 为不同的情绪定义单词列表。例如,如果我们试图确定一个段落是消极的还是积极的,我们可以定义像不好和可怕这样的词来表达消极情绪,而很好和很棒来表达积极情绪
- 通读课文,数一数积极词的数量。对消极的单词做同样的事情。
- 如果被识别为肯定的词的数量大于被识别为否定的词的数量,那么文本的情感是肯定的——反之亦然,对于否定的情感。
基于规则的方法对于了解情感分析系统的工作原理非常有用。然而,现代最先进的系统通常会使用深度学习,或者至少是经典的机器学习技术来自动化这个过程。
利用深度学习技术,情感分析被建模为分类问题。文本数据被编码到嵌入空间中(类似于上面描述的单词嵌入),这是特征提取的一种形式。这些特征然后被传递到分类模型,在该模型中文本的情感被分类。
这种基于学习的方法是强大的,因为我们可以将其作为一个优化问题来自动化。事实上,我们可以不断地向模型提供数据,以获得持续的改进,这也是一个巨大的好处。更多的数据改善了特征提取和情感分类。
关于如何使用各种机器学习模型进行情感分析,有很多很棒的教程。这里有几个很棒的:
- 用逻辑回归
- 与随机森林
- 与深度学习的 LSTM
喜欢学习?
在推特上关注我,我会在这里发布所有最新最棒的人工智能、技术和科学!也请在 LinkedIn 上与我保持联系!
一个介绍性强化学习项目:通过自玩表格 Q-learning 学习井字游戏
在这个项目中,我将介绍一个表格 Q-learning 项目。我们将训练一个简单的 RL 代理,使其能够评估井字游戏的位置,以便在许多游戏中通过与自己对抗来返回最佳移动。
首先,让我们导入所需的库
注意,表格 q-learning 只适用于可以用合理数量的动作和状态来表示的环境。井字游戏有 9 个方块,每个方块可以是 X 和 O,也可以是空的。因此,大约有 3⁹ = 19683 个状态(当然还有 9 个动作)。因此,我们有一个包含 19683 x 9 = 177147 个单元格的表格。这不算小,但是对于表格 q-learning 来说肯定是可行的。事实上,我们可以利用棋盘的旋转不会改变井字游戏的事实。因此,如果你认为一个特定的电路板配置的旋转和反射是相同的,那么实际上“唯一状态”要少得多。我不会深入 Q-learning,因为这是一个介绍性的项目。
首先,我们用前面提到的形状初始化我们的 q 表:
现在,让我们为训练设置一些超参数:
现在,我们需要建立一个探索策略。假设你理解 RL 中的探索-开发,那么探索策略就是我们将逐渐减少ε(采取随机行动的概率)的方式。我们最初需要至少半随机地玩游戏,以便正确地探索环境(可能的井字游戏棋盘配置)。但我们不能永远采取随机行动,因为 RL 是一个迭代过程,它依赖于对未来回报的评估会随着时间的推移而变得更好的假设。如果我们只是简单地永远玩随机游戏,我们会试图将随机的行动列表与一些最终的游戏结果联系起来,而这些结果实际上并不依赖于我们采取的任何特定行动。
现在,让我们用 matplotlib 创建一个 epsilon 与剧集(模拟的游戏数量)的关系图,并将该图保存到一个图像文件中:
当我们开始模拟游戏时,我们需要设置一些限制,以便代理人不能做出无意识的举动。在井字游戏中,被占据的方块不再可用,所以我们需要一个函数来返回合法的移动,给定一个棋盘配置。我们将用一个 3x3 的 NumPy 数组来表示我们的棋盘,其中未被占据的方格是 0,X 是 1,O 是-1。我们可以使用 NumPy 的np.argwhere
来检索 0 个元素的索引。
我们还需要一个助手函数来在 3x3 棋盘表示和整数状态之间进行转换。我们将未来的奖励估计存储在 q 表中,因此我们需要能够轻松地索引任何特定的董事会配置。我之前描述的在棋盘之间进行转换的算法是通过将可能状态的总数划分为与动作数量相对应的多个部分来实现的。对于板中的每个单元:
- 如果单元格为-1,则不改变
state
- 如果单元格为 0,那么将
state
改变窗口大小的三分之一 - 如果单元格为 1,你将
state
改变窗口大小的三分之二。
最后,我们需要最后一个辅助函数来确定游戏何时到达了终止状态。如果游戏确实结束了,这个函数也需要返回游戏的结果。我的实现通过对每个轴上的板阵列求和来检查一系列 3 个连续 1 或 3 个连续-1 的行、列和对角线。这会产生 3 个和,每个轴或列一个。如果-3 是这些和中的一个,这个轴必须全是-1,表示对应-1 的玩家赢了,反之亦然。对角线的作用是一样的,除了只有 2 条对角线,而有 3 行 3 列。我最初的实现有点幼稚,我在网上找到了一个好得多的。它要短得多,速度也略有提高。
现在,让我们初始化一些列表来记录训练指标。
past_results
会存储每个模拟游戏的结果,0 代表平局,1 表示正整数对应的玩家获胜,反之用-1 表示。
win_probs
将存储百分比列表,每集后更新。每一个值都表示到当前一集为止,玩家获胜的游戏的分数。draw_probs
也记录百分比,但是对应于出现平局的游戏的分数。
培训后,如果我们绘制win_probs
和draw_probs
的图形,他们应该展示以下行为。
- 在训练的早期,赢的概率会很高,而平局的概率会很低。这是因为当两个对手在像井字游戏这样的游戏中采取随机行动时,赢的情况比平的情况更多,这仅仅是因为赢的情况比平的情况多。
- 训练进行到一半时,当代理开始根据其牌桌的策略玩游戏时,赢和平局的概率将在 50%线上对称波动。一旦代理人开始与自己竞争,它将遇到更多的平局,因为双方都根据相同的战略政策进行博弈。每当代理人发现一个新的进攻策略时,图中就会出现波动,因为代理人能够在短时间内欺骗对手(自己)。
- 波动了一段时间后,抽奖概率应该接近 100%。如果代理人真的对自己进行最优博弈,它将总是遇到和局,因为它正试图根据预期未来回报表来最大化回报…对手(自己)也在使用同一张表。
我们来写训练脚本吧。对于每一集,我们从一个非终结状态开始:一个空的 3×3 的棋盘,上面填满了 0。它每移动一步,以一定的概率ε,代理从可用的方块列表中随机选择一个动作。否则,它查找 q 表中对应于当前状态的行,并选择最大化预期未来回报的动作。计算新板状态的整数表示,我们记录对(s,a,s’)。一旦这个游戏结束,我们将需要把我们刚刚观察到的状态-动作对与最终的游戏结果关联起来(这还没有确定)。一旦游戏结束,我们回头参考每个记录的状态-动作对,并根据以下内容更新 q 表的相应单元:
q-学习更新规则
在上面的更新公式中,s
是状态的整数表示,a
是代理在状态s
时采取的动作的整数表示,α是学习率,R(s, a)
是奖励(在我们的例子中,是观察到这对(s, a)
的相应游戏的最终结果),Q
是 q 表,涉及max
的语句表示结果状态的最大预期奖励。假设电路板配置为:
[[0, 0, 0],
[0, 0, 0],
[0, 0, 1]]
我们采取动作 3,对应于坐标为(1, 0)
的单元格,结果状态将是:
[[0 0, 0],
[-1, 0, 0],
[0, 0, 1]]
更新公式的这一部分指的是根据我们当前 q 表定义的政策,我们可以从这里采取的任何行动的最大预期回报。因此,s'
是我刚刚描述的第二种状态,a'
是我们理论上可以从这种状态(0–8)采取的所有行动,尽管在现实中,有些是非法的(但这是不相关的)。
在每 1000 集结束时,我只保存训练指标列表和这些指标的图表。最后,我保存了 q 表和存储这些训练指标的列表。
结果
我用 Google Colab 的在线 GPU 训练我的,但是如果你愿意,你可以在本地训练你的;你不一定要一直训练到收敛才能看到好的结果。
正如我之前提到的,以输赢结束的游戏和以平局结束的游戏之间的关系应该如下:
- 在早期的训练中,一个不熟练的,随机发挥的代理人会经常遇到输赢的情况。
- 每次代理发现一个新的策略,都会有波动。
- 在训练接近尾声,接近收敛时,代理人几乎总是会遇到和局,因为它是在与自己进行最优博弈。
因此,图形中较大的波动表示代理学会很好地评估特定的棋盘配置的时刻,这样做允许它防止和棋。
我们可以在结果图中清楚地看到这一点:
整个培训过程中的赢/输-平比率
在整个训练过程中,似乎 q 表经常会收敛,但很快就会完全改变。这些就是前面提到的第一次利用重大战略的时刻。
此外,正如你所看到的,随着你在整个训练过程中的进步,波动发生得越来越少。这是因为随着你的进步,还有更少的战术有待发现。理论上,如果代理收敛,就不会再有像这样的大波动了。抽牌会在 100%的时间发生,在抽牌百分比快速上升后,它不会再回落。
我决定将 Q 值随时间的变化可视化是一个好主意,所以我重新训练它,同时记录每集 Q 表的绝对值之和。无论特定的 q 值是正还是负,记录所有绝对 q 值的总和向我们显示何时发生收敛(当我们达到收敛时,q 值随时间的梯度降低)。
整个训练过程中的赢/输-平比率+整个训练过程中 Q 表的绝对值之和
你可以在这里访问 Google Colab 的完整代码:
编辑描述
colab.research.google.com](https://colab.research.google.com/drive/1w3RYXZ_tg80qNDQZf1I2KyZcigwz8Not?usp=sharing)
或者在 GitHub 上点击:
尝试探索策略会影响训练。您可以更改与 epsilon 相关的参数,以及它是如何衰减的,以便获得不同的结果。
最后要注意的是,井字游戏可以用更简单的值迭代方法更容易地实现,因为转移矩阵和回报矩阵都是给定的。对于像井字游戏这样的环境来说,这种ε-贪婪优化是不必要的。
DTW 的直观方法——动态时间弯曲
如何将算法可视化,让你可以自己定制。
奈杰尔·塔迪亚恩多在 Unsplash 上拍摄的照片
既然你在这里,我想你已经知道我们为什么在时间序列数据中使用动态的或 DTW。简单地说,它用于对齐或匹配两个相似的模式。
简要概述
最初开发 DTW 的原因之一是为了语音识别。你的母亲可能一天说得很慢,另一天又说得很快;即使有些日子会有点感冒和喉咙痛,但你仍然可以听出她的声音。机器也能做到吗?它们能以某种方式匹配她的声音的高低、高低、频率,而不是她说话的方式,并告诉我们这确实是她的声音吗?
DTW 在现实生活中有几个令人敬畏的场景——如果你还不知道,我推荐你去了解它们——它们真的很有趣!
两个信号对齐——“作者的图像”
带我去那里,快!
我喜欢这个算法!本质上,它是一种短小精悍的算法。这是一个使用 动态规划 方法寻找最短路径的经典例子。
我有同事逃避理解算法的内部运作,因为它涉及到 递归 。这最终会阻止他们理解方法的细微差别,以及学习如何根据他们的需求进行调整。
让我们用一种非编程的方式来可视化算法背后的逻辑,这样我们就可以从头开始写了。
要理解递归,首先必须理解递归。
——斯蒂芬·霍金
想象你站在蓝色广场,希望去红色广场。你在沿途的单元格中看到的所有数字,对应于你在每一步必须支付的通行费金额(暂时是任意决定的)。如果我问你,“告诉我一个人要从蓝色变成红色最少需要花多少钱”,你会怎么做?
寻找“最便宜”的路线——“作者图片”
事实上,我可以简单地说,你应该只朝“向前”的方向移动。黑色箭头显示仅有的 3 个“允许”方向(右、下、右下对角线),红色箭头显示“限制”方向,即除了 3 个允许方向(上、左、其他对角线等)之外的所有方向。).这类似于 DTW 在解决问题之前的假设。
允许的方向—“按作者分类的图像”
上述事实的另一种说法是,“你只能从 3 个相邻的方格中的一个到达任何方格”:
另一种看待它的方式——“作者的图像”
一种“蛮力”方法是尝试从蓝色到红色方块的所有可能路径,并选择最便宜的一条。然而,动态编程和递归给了我们一个更好、更聪明的方法。
懒惰的老板
我喜欢以“懒惰老板”的身份来解决所有递归问题,他有无数的手下来完成这项工作。如果有人让我解决上述问题,我会简单地说:“小黄人 A,B,C,告诉我到达红色方块周围的 3 个方块的最小成本,然后我一分钟后计算出答案。在那之前,不要打扰我。”
这就是递归使用的技巧——将你被要求做的 完全相同的工作 交给你的下属,在将工作“缩小”一点之后。一定要给自己留一些简单的东西,这样就没人会说你什么也没做!
假设通过某种魔法(你没兴趣知道),小喽啰给你带来了答案,标在绿色的格子里:
小黄人 A、B、C 的回答——“作者图片”
我现在需要做的就是找到 (10,7,7) 的最小值,也就是 7,然后加上当前方块的成本,也就是 2。这给了我答案为 9 。搞定了。
9 是从蓝色到红色旅行的最小花费。但是等等,奴才们是怎么想出绿色价值观的?他们当然会模仿你,也扮演懒惰老板的角色!
每个爪牙抓 3 个低级爪牙(我告诉你,办公室里该死的等级制度!)并告诉他们为他们的 3 个邻居/相邻方块带来最小成本值。下面的动画可以更好地解释这一点:
工作中的奴才——“作者的形象”
这种情况一直持续下去,每一个小跟班都“神奇地”得到了答案。但是能持续多久呢?它肯定会结束吗?是的,确实如此。当没有办法进一步细分作品时。当一个仆从在蓝色方块得到计算费用的任务时,他不能把它委托给任何人,因为没有邻居可去。他只需要知道那里的成本是零。
就是这样。只需几行代码,您就可以将它转化为一个递归 python 函数:
def cheapest(cost, i, j):
if (i==0) & (j==0):
return 0 ## can't subdivide the work anymore if (i<0) | (j<0):
return np.inf ## current square's cost + minimum of the 3 neigbours
return cost[i][j] + min(cheapest(cost, i-1, j-1),
cheapest(cost, i-1, j),
cheapest(cost, i, j-1))
这里,cost
是一个二维数组,我们的初始矩阵:
cost = [
[0,2,5,1,1],
[5,3,4,2,2],
[1,1,6,1,3],
[1,3,2,1,2]
]
请注意,当i
或j
小于零时,我是如何返回np.inf
(无穷大)的。这只是忽略不存在的邻居的一种方式。例如,当你在一个顶行方块中时,你需要考虑的唯一邻居是左边的那个,因为在当前方块的上面没有方块。类似的逻辑也适用于第一列中的正方形,这里左边没有邻居。
您可以通过简单地调用以下命令来调用递归函数:
output_cost = cheapest(cost, 3, 4)
print(output_cost)
它将给出的输出是 9。
如果对所有方块调用它,最终可以创建一个最便宜的成本矩阵作为输出:
output_cost_matrix = [] ## used to store all outputs
for i in range(4):
for j in range(5):
output_cost_matrix.append(cheapest(cost, i, j))## reshape the output for better display
output_cost_matrix= (np.array(output_cost_matrix)).reshape(-1,5)
print(output_cost_matrix)
输出:
[[ 0, 2, 7, 8, 9],
[ 5, 3, 6, 8, 10],
[ 6, 4, 9, 7, 10],
[ 7, 7, 6, 7, 9]]
那么,从蓝色方块到红色方块最便宜的路径是什么呢?
我们只需要跟踪每个方块周围的最小邻居。如果您也想打印路径,下面是代码。这当然没有优化,但很容易理解:
def trace_path(output_cost_matrix, i, j):
path = [(i, j)]
while ((i>0) | (j>0)):
neighbours = [output_cost_matrix[i-1, j-1],
output_cost_matrix[i-1, j],
output_cost_matrix[i, j-1]]
## see which neighbour is the smallest
path_min = np.argmin(neighbours) ## store the position of the smallest neighbour
if path_min==0:
i=i-1
j=j-1
elif path_min==1:
i=i-1
else:
j=j-1
path.append((i, j)) return path[::-1] ## return after reversing the list
让我们通过调用来查看从蓝色返回到红色方块的路径:
trace_path(output_cost_matrix, 3, 4)
输出:
[(0, 0), (0, 1), (1, 2), (2, 3), (3, 4)]
用图形表示出来:
追踪的路径——“作者的图像”
或者在我们的原始矩阵上追踪它:
最便宜的路径——“按作者排序的图像”
酷!但是 DTW 在这一切中处于什么位置呢?
问对了!DTW 是如何看待这一切的?
DTW 不过是简单地将时间序列模式 1 中的一个点与模式 2 中最近的点进行匹配。
我们再来看两个信号的映射。青色的是图案 1,橙色的是图案 2,红线试图为图案 2 上的每个点找到图案 1 上的对应点:
模式映射——“作者的图像”
所以本质上,我们在寻找模式 2-点和模式 1-点之间的最短或最便宜的路径。但是任意两点之间的成本是多少。我们是否像例子中那样,对每个方块随机放置?
根据您的用例,您可以从这里选择各种选项,但最常见的是这些点之间的欧几里德距离。
您将所有模式 1 点排列为矩阵的列轴,所有模式 2 点排列为行轴。然后用欧几里德距离填充每个正方形:
排列成矩阵的图案——“作者的图像”
然后是我们刚刚经历过的递归算法。像[(0,0), (0,1), (1,1), (2,2), (3,3), (4,3)]
这样的输出路径意味着模式 1 中的点 0 应该与模式 2 中的点 0 和 1 匹配。模式 1 中的点 1、2、3 和 4 应与模式 2 中的点 1、2、3 和 3 相匹配。
但是这实际上能达到什么目的呢?这样的最短距离匹配意味着什么?
我喜欢把它想象成这样一种解决方案:你试图以一种确保模式 2 的拉伸(或收缩)最小的方式来匹配模式 2 和模式 1;贪婪地将它匹配到最近的邻居。
现在你知道了。从头开始实现一个简单的 DTW 算法。
我没有提到 DTW 过程的一些细微差别和变化,例如一个窗口 DTW ,我们在其中添加了一个位置约束。我希望这篇文章已经激发了你想了解更多的兴趣。如果你发现了一些很酷的东西,一定要告诉我!
对分享想法、提问或简单讨论想法感兴趣?在 LinkedIn 、 YouTube 、 GitHub 上或通过我的网站与我联系:我只是一个学生。
回头见&学习愉快!
www.linkedin.com](https://www.linkedin.com/in/himanshu-chandra-33512811/)
一个直观但全面的*args 和**kwargs 教程,最终解决您的问题
TLDR;使用
**args*
将元组打包/解包到变量*args*
和***kwargs*
将字典打包/解包到变量*kwargs*
你可以在这个链接找到原始代码库。
在最近的一篇文章中,我解释了如何用 matplotlib 创建自定义绘图函数。不可避免的是,为了做到这一点,我们需要大量使用**kwargs,所以我在这里简要介绍了它们。
不幸的是,**kwargs
和*args
是 python 编程初学者最困惑的方面之一。你可能已经看到过*args
和*kwargs
被用在其他人的代码中,或者可能在你最喜欢的库的文档中。你可能已经在寻找简单的解释,但是你找到的所有教程都和主题本身一样令人困惑。
虽然我在前面的帖子中对**kwargs
的解释已经足够了(至少我希望如此!),我已经被要求上映续集(前传?)在这篇文章中,我以一种直观的、循序渐进的方式更全面地介绍了著名的*args
和**kwargs
,这样你就再也不需要关于它们的其他教程了。我希望在这篇文章结束时,你会看到它们实际上是非常简单的操作符,你将能够马上开始把它们放到你所有的函数中,使它们更加灵活,更容易使用和阅读。
写完这篇文章后,我强烈推荐你去看看我的另一篇文章,这样你就可以看到这里展示的理论在用 matplotlib 创建自定义绘图函数中的实际应用。话虽如此,不再赘述,我向你介绍*args
和**kwargs
。
单一星级运营商— *
*打包参数—为丢失的参数找到一个家
第一种使用著名明星*
、**
的方式是作为“包装工”。把星星想象成把所有被预定义的变量悬挂着的物体都存储在一个物体里。让我们在下面的一系列例子中看到这一点。
首先,让我们创建一个包含 3 个元素的数组,然后将每个元素存储在不同的变量中:
a, b, c = [1, 2, 3]
print(f"a: {a}\nb: {b}\nc: {c}") #Printing them on separate lines>a: 1
>b: 2
>c: 3
这可能特别无趣,但是现在想象一下,我们保留三个变量 a 、 b 、 c ,而不是三个变量和三个元素,但是将元素的数量增加到 6 个。你可以先试着这样做:
a, b, c = [1, 2, 3, 4, 5, 6]
如果你真的尝试过,你会发现这会导致一个错误。毕竟,我们试图将六个不同的元素放入三个变量中。假设您希望第一个元素存储在 a 中,第二个元素存储在 b 中,其余的元素存储在 c 中的一个列表中。
你绝对可以这样做:
array = [1, 2, 3, 4, 5, 6]
a, b, c = array[0], array[1], array[2:]
相反,请看这个示例一行程序:
a, b, *c = [1, 2, 3, 4, 5, 6]print(f"a: {a}\nb: {b}\nc: {c}") #Printing them on separate lines>a: 1
>b: 2
>c: [3, 4, 5, 6]
这个例子和那个没成功的例子有什么区别?假设变量由数组元素一次填充一个:
- 1 放在 a 内。没问题。
- 2 放在 b 内。没问题。
- 3 放在 c 内。没问题。
- 从 4 到 6 的数字的整个子列表不能放在任何地方。问题。
事实上,我们留下了一大块孤儿列表,python 不能很好地处理被挂起的对象。我们需要的是一个函数,它能够识别哪些对象被留在中间状态,并将它们放在一个列表中,这样我们就不会得到更多的错误。这正是*
的含义。
当我们写*c
时,我们实际上是在说c = [all that's left, packed inside a list]
。代替*c
,我们也可以写*args
、*random_name
、*args_is_a_convention
,因为*
后面的实际单词将是列表的名称,该列表将保存所有尚未放入变量的元素:
a, b, *args = [1, 2, 3, 4, 5, 6]
print(args)>[3, 4, 5, 6]a, b, *random_name = [1, 2, 3, 4, 5, 6]
print(random_name)>[3, 4, 5, 6]
我一直使用带有最后一个变量的*
来存储在a
和b
获得列表份额后剩下的所有元素。但是当我说*
将获取所有剩余的元素时,并不一定是指列表末尾的元素。我们也可以将第一个和最后一个元素分别保存在a
和c
中,并使用*
来存储剩下的内容:
a, *args_is_a_convention, c = [1, 2, 3, 4, 5, 6]print(args_is_a_convention)>[2, 3, 4, 5]
这一切都很棒,但对于经常被谈论的东西来说,这似乎是一个非常合适的用例。为什么有人要关心它?当在函数定义中使用*
这个很酷的属性时,就能找到答案。
*打包参数——为函数的参数输入增加了灵活性
让我们创建并使用一个具有不同可能输入的基本函数(又名。争论。你可能已经明白我的意思了):
def basic_function(a, b, c):
print(f"a: {a}\nb: {b}\nc: {c}")
basic_function('The name', 2, False)>a: The name
>b: 2
>c: False
没什么特别的。我们所做的是设置该函数,使其接受三个值,并将它们分别存储在变量a
、b
和c
中。我们选择分别给这些变量赋予'The name'
、2
和False
的值。这和上面的第一个场景很像,不是吗?
a, b, c = ['The name', 2, False]
print(f"a: {a}\nb: {b}\nc: {c}")>a: The name
>b: 2
>c: False
基本上,我们的函数定义与我们的变量声明(等号的左边)的作用相同,使用函数本身就像写下要放入每个变量中的值(等号的右边)。
那么,如果我们尝试像这样传递 5 个值,而不是传递 3 个值,会发生什么呢?
basic_function(‘The name’, 2, False, 1, ‘Last Name’)
你可以试一下,但是它会再次给你一个错误。这是因为我们本质上是在试图将太多的值打包到太少的变量中:
a, b, c = ['The name', 2, False, 1, 'Last Name']
为了解决这个问题,我们将使c
能够获取a
和b
无法获取的所有值。为此,我们将稍微修改我们的函数,以匹配我们之前的解决方案:
def basic_function(a, b, *c):
print(f"a: {a}\nb: {b}\nc: {c}")
basic_function('The name', 2, False, 12, 5)>a: The name
>b: 2
>c: (False, 12, 5)
我们再次看到,语法*c
将所有没有被a
和b
接受的参数打包到一个名为c
的数组中(像往常一样,这个数组可以被命名为任何名称,而不是c
)。然而,在上一个例子中,有一个重要的警告你可能已经注意到了,它是非常重要的。默认情况下,得到的对象c
将是一个元组,而不是一个列表,当您稍后试图使用它时,这将带来重要的考虑因素(例如,与列表相反,元组是不可变的)。如果需要,您可以在函数中将其转换为列表...
第一次使用*
时,有一件事让很多人感到困惑,那就是c
并没有“充当元组,但暗地里它是一个带星号的元组”。c
是一个元组,句号。值得重复的是,*name
将简单地获取所有额外的参数,并将它们存储在一个名为name
的元组中。因此,我们可以像使用所有元组一样使用它。请看下面的例子,它稍微调整了一下基本函数:
def basic_function(a, b, *args):
args_type = type(args)
first_element = args[0]
summed_args = sum(args)
print(f"Type of args: {args_type}")
print(f"First element of args list: {first_element}")
print(f"Summed elements of args: {summed_args}")
basic_function('The name', False, 2, 5, 5)>Type of args: <class 'tuple'>
>First element of args list: 2
>Summed elements of args: 12
你看,这里的 args 很像一个 tuple,所以我们可以请求它的类型(tuple…),我们可以通过索引得到元素,对它求和,等等。
如果这不是你第一次学习关于*args
的教程,你可能已经看到了它是如何被用来定义一个对所有提供的数字求和的函数的。虽然我认为它通常是一个糟糕的例子,同时也是一个使用不当的例子,但是通过前面的例子,您应该能够理解它是如何工作的:
def example_of_sum(*args):
print(sum(args))
example_of_sum(1, 9, 4, 6)>20
因为除了*args
(no a
或b
)之外没有其他变量可用,所以结果元组args
包含所有提供的值(1,9,4,6)。
在您开始使用*
定义自己的函数之前,有一个小提示。正如您在前两个例子中看到的,我对结果元组使用了传统的名称args
。我建议你也使用args
作为你的元组的名称(或者至少是一些明确包含“args”的词),这样当人们阅读你的代码时,他们可以很容易地识别你在做什么。
第二点也是更重要的一点:虽然我们以前可以这样做:
a, *b, c = [1, 2, 3, 4, 5, 6]
要在b
内部存储除第一个和最后一个以外的所有值,在定义函数时不能这样做。换句话说,这是行不通的(所以一定要试试):
def basic_function(a, *args, c):
print(a) #example of a random command
当你在函数中使用*args
时,它必须出现在所有已定义参数的最后(实际上在**kwargs
之前,但我们很快就会看到)。所以def basic_function(a, *args, c):
是错,而def basic_function(a, c, *args):
是对。
这基本上涵盖了*
所做的我称之为“包装机器”的事情。它将被遗忘的对象或输入放入一个元组中。现在让我们看看硬币的另一面。
*用于解包的参数—自由设置列表元素
与下一节相比,这一节将会出奇地短,那些解释**kwargs
如何工作的部分也是如此,因为要点主要在前一节中已经涵盖了。
在这里,我们将看到*
的另一个常见用法,即与之前的完全相反。这是*
的另一个令人困惑的行为,它让人们不敢在他们的代码中使用*args
。当我们以前使用它时,它总是与我们所谓的“无人认领的争论”联系在一起。换句话说,*args
相当于说“将所有剩余的参数放入名为args
的元组中”。
如果在一个元组或列表中使用*
(不管它们是否是用*
创建的),这一次,存储在元组中的所有元素都将被解包。因为你不能简单地把对象扔到风中而没有一个变量来捕捉它们,通常用*
对元组和列表的解包是在另一个函数中完成的。让我们用一个例子来说明这一切:
my_tuple = (1, 2, 3)
print(my_tuple)>(1, 2, 3)
这里没什么有趣的。让我们看看*
会发生什么:
my_tuple = (1, 2, 3)
print(*my_tuple)
>1 2 3
乍一看可能不明显,但您应该注意到,元组中的数字现在都是自由的,彼此独立的,而不是在括号内,用逗号分隔。你可以用一个列表试试:
my_list = [1, 2, 3]
print(*my_list)>1 2 3
实际上,您可以对所有类型的对象进行尝试,并看到不同的结果(对于初学者来说,字典可能会给出意想不到的结果):
my_set = {1, 2, 3}
print(*my_set)>1 2 3my_dict = {'first':1, 'second':2, 'third':3}
print(*my_dict)>first second third
不过,你明白了。那么这为什么有用呢?主要是,这样您可以将列表中的元素作为独立元素传递给需要独立值而不是元组或列表的函数。当你在函数中有函数时,这是一个特别有用的行为(我发现这对于**kwargs
更加重要)...不会太久了...).
例如,假设我们对函数定义没有太多的控制权(也许它是另一个库的一部分,而您不想深入研究源代码),而您恰好已经将数据存储在一个元组中:
def function_from_library(a, b, c):
print(f"a: {a}\nb: {b}\nc: {c}")
my_tuple = ("First Name", "Last Name", "email")
现在,您可以通过以下方式轻松添加元组:
function_from_library(*my_tuple)>a: First Name
>b: Last Name
>c: email
如果这不是一个令人满意的结果,那么:
- 那太好了,你明白*args 实际上一点也不难
- 将来你可能会发现,它实际上可以非常灵活地解决一些问题
- **kwargs 实际上可能对您更感兴趣(差不多了……)
简而言之,您看到了如何根据数据是一组单独的对象还是它们的捆绑集合,将*
用作数据的打包和解包操作符。如今,现在...到**kwargs
!。
双星运营商——* *
* *打包的 kwargs 为丢失的关键字参数找到一个家
如果你已经阅读并理解了上面关于*
和args
的解释,那么接下来的部分将会很顺利。我们看到*name
会将自由漫游参数打包到一个元组中,供以后在变量name
下使用。
另一方面,**kwargs
将做完全相同的事情,但是将键值对打包到一个字典中。了解这一点的最佳方式是直接进入函数定义:
def not_using_kwargs(a, b, c):
print(f"a: {a}\nb: {b}\nc: {c}")
not_using_kwargs(a=4, b=[1, 2, 3], c=True)>a: 4
>b: [1, 2, 3]
>c: True
虽然函数本身与我们之前使用的没有什么不同,但我们在这里实际上使用了不同的方法。在这种情况下,我们非常明确地告诉函数我们希望每个参数是什么:
not_using_kwargs(a**=**4, b**=**[1, 2, 3], c**=True**)
而不是简单地
not_using_kwargs(4, [1, 2, 3], **True**)
显式地写出参数的名称是有用的,因为您不需要记住它们在函数中的顺序就可以正确地使用它(想象一下,如果您有 10 或 20 个可能的参数)。例如,我们可以按照不同的顺序编写它们,函数仍然可以按预期工作:
not_using_kwargs(b=[1, 2, 3], c=True, a=4)>a: 4
>b: [1, 2, 3]
>c: True
那么,如果我们像下面这样使用函数,引入一个新的未定义参数,会发生什么呢?
not_using_kwargs(b**=**[1, 2, 3], c**=True**, a**=**4, so_new**=True**)
不出所料,事情会失败,因为函数不需要第四个参数。正如我们将在下面的例子中看到的,我们可能希望允许函数接受一些其他潜在的命名参数。那么我们如何修复我们的功能呢?这一次,用**
。
def using_kwargs(a, b, **c):
print(f"a: {a}\nb: {b}\nc: {c}")
using_kwargs(a=4, b=[1, 2, 3], so_new=True, even_newer=100, freshest_of_all=[20, 5, 1])>a: 4
>b: [1, 2, 3]
>c: {'so_new': True, 'even_newer': 100, 'freshest_of_all': [20, 5, 1]}
我们在这里看到,以前没有定义的所有新命名输入现在都存储在一个字典中,其中键表示参数的名称,例如so_new
,字典条目的值是函数中传递的值,例如True
。如果这还不够好,你可以考虑将它们结合使用:
def using_both(a, *b, **c):
print(f"a: {a}\nargs: {b}\nkwargs: {c}")
using_both(4, 5, 6, "I'm an arg", [1, 2, 3], test="success", so="simple", where="I'm in a dictionary")>a: 4
>args: (5, 6, "I'm an arg", [1, 2, 3])
>kwargs: {'test': 'success', 'so': 'simple', 'where': "I'm in a dictionary"}
如果还不清楚,我建议你多花一秒钟看看前面的例子。这个想法是,a
接受第一个输入(数字 4),b
接受其余未命名的输入(5 一直到列表[1,2,3]),因为有了*
,而c
接受了所有命名的输入,因为有了**
,事实上我们拥有的唯一真正定义的输入是a
。
和以前一样,定义函数时参数的顺序很重要。为了安全起见,切记始终将*args
和**kwargs
放在最后:
def my_function(a, b, c, d, ..., *args, **kwargs)
当您使用该函数时,也要考虑这一点。如果你尝试这样做,你会得到一个错误(无论如何要试试看):
def my_function(a, b, c, d, *args, **kwargs):
pass #Since we can't leave this blank, we put pass to say "don't do anything"my_function(5, 4, 3, 2, 'extra arg', a='this is A', extra='extra kwarg')
有人可能会认为,既然我们明确地告诉函数将'This is A'
放入变量a
,那么它将能够通过将“额外的”参数(5、4、3、2 和‘额外的 arg’)放入args
来处理它们。然而,在您显式使用a='This is A'
之前,a
内的位置已经被 5 占据。请注意这种情况。
*用于拆包的 kwargs 释放字典
我想那些通读了整篇文章的人已经明白这一部分将要发生什么了。但是我不期望每个人都已经阅读了我到目前为止写的每一个字,所以,这里是**
拆包的秘密。
有时,您可能有一个字典,其中充满了您希望在函数中使用的键值对。也许你没有自己编写这个函数,或者你没有计划让它接受一个字典,你现在真的不能改变它,否则你将冒着破坏你的代码的风险。有了**
,你可以像这样轻松使用你的字典:
def interesting_function(x, y):
print(f'What an interesting result: {x + y}')my_dict_data = {"x":2, "y":8}
interesting_function(**my_dict_data)>What an interesting result: 10
这也很乏味吗?然后:
- 太好了,你明白**kwargs 其实一点都不难
- 将来你可能会发现它可以非常灵活地解决一些问题
另外,如果你想要一个更有趣的使用**kwargs
解包的例子,我再次推荐你访问我的最近的帖子,在那里我解释了如何用 matplotlib 创建定制的绘图函数。
结论
如果你一直读到这里,希望你能理解*args
和**kwargs
到底是做什么的。事实上,从现在开始,希望你会认为它们是*
和**
,并看到它们本质上并不比元组打包/解包和字典打包/解包函数更特殊。
如果您有任何问题或意见,我希望通过评论/消息/一般社交媒体听到它们。否则,就在你的代码上撒一些星星吧!
原载于 2020 年 5 月 11 日https://matic derini . github . io。
波束搜索的直观解释
波束搜索的简单易懂的解释
在本文中,我们将了解:
- 什么是波束搜索,它是如何工作的?
- 波束搜索和贪婪搜索的区别
先决条件:
如果你有兴趣知道谷歌语音搜索或亚马逊的 Alexa 或苹果的 Siri 是如何工作的。你需要有一个…
medium.com](https://medium.com/datadriveninvestor/recurrent-neural-network-rnn-52dd4f01b7e8) [## 神经机器翻译的直观解释
简单解释用于神经机器翻译的序列到序列模型(NMT)
towardsdatascience.com](/intuitive-explanation-of-neural-machine-translation-129789e3c59f)
在本文中,您将详细了解神经机器翻译是如何使用序列到序列算法在目标语言的句子中找到最相关的单词的。
什么是光束搜索?
为了理解波束搜索,我们将使用序列的神经机器翻译用例来对序列进行排序。
序列到序列模型使用具有长短期记忆(LSTM)或门控循环单元(GRU)作为基本块的编码器和解码器框架。
编码器映射源序列,对源信息进行编码,并将其传递给解码器。解码器将来自编码器的编码数据作为输入,并将字符串开始标记<START>
作为初始输入,以产生输出序列。
这里,源序列是印地语的一个句子,目标序列是用英语生成的。您不希望任何随机的英语翻译,但您希望选择最好的和最有可能的单词来翻译,以匹配北印度语句子的意思。
我有印地语的例子,因为这是我所知道的除英语之外的另一种语言。
如何为目标序列选择最好的、最有可能的词?
一个简单的方法是拥有目标语言的词汇,比如说 10,000 个单词,然后根据源句子,获得 10,000 个目标单词中每个单词的概率。
源句子在目标语言中可能有多种可能的翻译。
要不要随便挑一个翻译?
我们的目标是挑选最好的、最有可能翻译的单词,所以我们根据源句选择概率最大的目标单词。
你应该只选择一个最好的翻译吗?
贪婪搜索算法为每个时间步长选择一个最佳候选作为输入序列。仅选择一个最佳候选可能适合当前的时间步长,但当我们构建完整的句子时,它可能是次优的选择。
波束搜索算法基于条件概率在每个时间步长为输入序列选择多个备选方案。多个备选方案的数量取决于一个名为波束宽度 B 的参数。在每个时间步长,波束搜索选择 B 个概率最高的最佳备选方案作为该时间步长最有可能的选择。
我们举个例子来理解这一点。
我们将选择波束宽度= 3;我们的英语词汇量有 10,000 个单词。
步骤 1:在给定输入句子的情况下,找出概率最高的前 3 个单词。最可能单词的数量基于波束宽度
- 将编码的输入句子输入到解码器;然后,解码器将对词汇表中的所有 10,000 个单词应用 softmax 函数。
- 从 10,000 种可能性中,我们将只选择概率最高的前 3 个单词。
- 当波束宽度设置为三个时,考虑翻译单词的三个最佳和最有可能的备选。
- 如果波束宽度设置为 10,那么我们将选择概率最高的前 10 个单词。我们在内存中存储前三个单词:我、我的和我们
第一步:根据输入的句子找出三个概率最高的单词
贪婪搜索总是只考虑一个最佳选择。
第二步: 根据条件概率为第一个和第二个单词找出三个最佳配对
第二步:找出翻译句子中第一个和第二个单词的前三对单词
- 将步骤 1 中选择的前三个单词(我、我的、我们)作为第二步的输入
- 将 softmax 函数应用于词汇表中的所有 10,000 个单词,以找到第二个单词的三个最佳备选项。在这样做的时候,我们将使用条件概率找出最有可能形成一对的第一个和第二个单词的组合。
- 为了找到第一个和第二个单词的三个最佳对,我们将取第一个单词“I”,将 softmax 函数应用于词汇表中的所有 10,000 个单词。
- 评估其他两个词的概率,选择第一个词:“我的”和“我们”
- 运行 30,000 种不同的组合来选择第一个和第二个单词的前 3 对。
- 前三个第一和第二单词对组合是:“我是”、“我的父母”和“我会”
- 我们现在已经删除了第一个单词“We ”,因为我们没有找到任何将“We”作为第一个和第二个单词的具有高条件概率的单词对
- 在每一步,我们实例化编码器-解码器网络的三个副本,以评估这些部分句子片段和输出。网络的拷贝数与波束宽度的大小相同
第三步: 根据输入的句子和选择的第一个和第二个单词找到第一个、第二个和第三个单词的三个最佳对
第三步:找出翻译句子中前三个单词最可能的选择
- 沿着输入的句子和前 3 个第一和第二单词对组合:“我是”、“我的父母”、“我将”,找到条件概率最高的第三个单词。
- 再次运行 30,000 个组合来选择第一、第二和第三个字的最佳和最可能的组合,并实例化 seq2seq 编码器-解码器模型的三个副本
- 前三个第一、第二和第三单词组合是:“我正在访问”、“我将要访问”和“我将要去”。
- 我们放弃了组合“我的父母”,因为我们在前 3 个组合中没有找到第一、第二和第三个单词组合“我的父母”。
我们继续这个过程,我们选出三个概率最高的句子。前三个句子的长度可以不同,也可以相同。
具有最高条件概率和不同长度的三个输出句子
我们最终选择解码器的输出作为概率最高的句子
光束宽度值越大,翻译效果越好吗?
更高的波束宽度将提供更好的翻译,但会使用大量的内存和计算能力。
当我们有 3 的波束宽度和 10,000 个单词的词汇时,我们在每个时间步评估 30,000 个组合,创建三个编码器-解码器实例,最大句子长度是 9。创建多个编码器-解码器副本并在每个时间步计算 30,000 个单词的条件概率需要大量内存和计算能力。
较低的波束宽度将导致质量更差的翻译,但是在存储器使用和计算能力方面将是快速和有效的
结论:
波束搜索是序列到序列深度 NLP 算法(如神经机器翻译、图像字幕、聊天机器人等)最流行的搜索策略。
波束搜索使用条件概率基于波束宽度考虑多个最佳选项,优于次优贪婪搜索。
参考资料:
https://www.youtube.com/watch?v=RLWuzLLSIgw
场感知因式分解机的直观解释
从 LM 到 Poly2 到 MF 到 FM 到 FFM
在推荐系统中,场感知因子分解机器(FFM)特别有用,因为它们能够处理具有许多分类特征的大型稀疏数据集。
为了理解 FFM 是如何产生的,让我们明确一些基础知识,理解为什么 FFM 是好的,它们有什么好处。
由作者改编(文章底部的原始照片)
线性回归
当我们试图对因变量和一个或多个自变量之间的关系建模时,我们能想到的最简单的模型是线性回归模型。
例如,为了预测用户对某部电影的评价,我们可以使用许多不同的特征作为预测指标。然而,为了简单起见,让我们假设两个变量——性别(x1
)和电影的类型(x2
)。
作者照片
在这种情况下,我们将以下面的等式结束(假设没有偏差,并假设对分类变量进行了一些编码):
作者照片
然后我们将求解权重w1
和w2
。自然,线性回归不会表现得很好,因为它试图学习每个变量的平均行为,并且没有考虑这些变量之间相互作用的可能性(即,它不能学习x1
可能与x2
具有相关性)。
Poly2
为了模拟这些相互作用,我们引入下一个最简单的模型——poly 2。代替上面的等式,我们为每个 特征对 添加一个交互项。这给了我们:
作者照片
然而,很明显,这种方法有一些主要的缺点。首先,非常少的交互将具有不可靠的预测,其次,看不见的交互(即零交互)将具有微不足道的预测。
例如,在 10000 个示例的训练集中,如果我们只有 2 个男性观看惊悚电影的示例,我们对男性观看惊悚电影的未来预测将仅基于这 2 个训练示例(即,交互项的权重由 2 个数据点确定)。此外,如果我们的训练集没有女性观看科幻电影的例子(如上表所示),对这些电影做出的预测将是琐碎而无意义的。
矩阵分解
在 MF 中,我们通常以稍微不同的方式表示数据。我们希望捕捉到用户和物品之间的互动,而不是将每个变量编码为男性或女性,或者使用电影的类型。让我们看看我们的新数据:
作者照片
在上图中,用户位于行中,而项目位于列中。给定的用户-项目交互的正值是用户对该电影的评价(注意,值也可以是二进制的,如下图所示,以表示观看或未观看)。
作者照片
给定上面的用户-物品矩阵R[MxN】,目标是近似两个矩阵——一个用户潜在矩阵P[Mxk和一个物品潜在矩阵Q[Nxk,其中更稳健的 MF 方法是加权 MF,其中非相互作用值用零填充,然后使用加权交替最小二乘(WALS)或随机梯度下降(SGD)进行优化,将(观察和未观察条目的)误差平方和作为损失函数。通常添加一个超参数来加权来自未观察条目的误差,因为由于稀疏性,它们往往更多。
来源:谷歌的推荐系统课程
MF 如何改进线性回归和 Poly2?
MF 本质上是一个潜在因子模型,这意味着它可以将一个非常稀疏(和高维)的矩阵表示为两个维度低得多的矩阵。在高层次上,人们可以想象它与主成分分析(PCA)类似,我们试图在 k 成分中捕获尽可能多的方差。
注:潜在向量的概念与向量嵌入同义,其思想是从高维空间中学习一种紧凑的表示。
MF 的一个缺点是它只是一个矩阵分解框架。因此,我们只能将矩阵表示为一个用户条目矩阵,而不能包含诸如电影类型、语言等辅助特性。因式分解过程必须从现有的相互作用中学习所有这些。因此,因式分解机作为 MF 的改进版本被引入。
(由于本文关注的是 FFM,我就不深究 MF 的更多细节了。为了了解更多,我强烈推荐 谷歌的推荐系统入门课程 。)
因子分解机器(FM)
如前所述,FM 是 MF 的改进版本。更具体地说,FM 是一种更一般化的预测器,如支持向量机(SVM),但能够在稀疏性下估计可靠的参数[2]。简单来说, FM 公式化为线性模型,特征之间的相互作用作为附加参数(特征)。这些特征交互是在它们的潜在空间表示中完成的,而不是在它们的平面格式中。它在数学上表示为:
作者照片
如上所述,我们可以将上面的等式分解为两部分——左边的一个线性回归模型和右边的一个等价的矩阵分解。
与 Poly2 相比,交互的捕获有何不同?
上面等式的右边可能会把人吓跑,因为它看起来很吓人。为了更容易理解,让我们来看看如何表示我们在 MF 中看到的用户条目矩阵。
作者照片
首先,我们希望将用户-项目交互表示为一个 hot 编码向量,其中转换后的每一行都只有一个活动用户和项目。然后,我们可以添加辅助特征(例如,用户评价的其他电影、评价的最后一部电影、他消费该电影的时间等)作为一次性编码或归一化向量。
一般来说,因式分解机器能够估计稀疏设置中的相互作用,因为它们通过因式分解打破了相互作用参数的独立性(使用<v_i, v_j>
中表示的潜在向量)。这意味着一个交互的数据也有助于估计相关交互的参数(类似于矩阵分解和协同过滤的思想)。
来源:媒体文章作者:迈克尔·魏
与 Poly2 相比,FM 中每个相互作用的权重使用两个潜在向量的内积来估计。这意味着,即使在训练集中x_i
和x_j
之间没有交互,FM 也能够概括这种交互,因为它已经在训练期间创建了嵌入(如在 MF 示例中,我们获得了两个潜在矩阵)。在 Poly2 中,这是不可能的,因为模型没有看到这种特殊的相互作用。注意,在 FM 中,有一个额外的超参数 k — 所使用的潜在特征的数量(如上图所示)。
如果调频已经可以概括得这么好,f FM 如何超越调频?
场感知因式分解机(FFM)
在深入研究 FFM 之前,注意术语上的差异是至关重要的:自变量如流派和性别现在将被称为字段。每个字段的分类值将被称为特征。比如男、女、动作、言情等都是特色。
作者照片
在 FM 中,每个特征只有一个潜在向量来学习所有其他特征的潜在效果[1]。例如,如果我们有 3 个字段性别、流派和国家,我们将 FM 下的交互计算为:
作者照片
以上表第一行为例,用男的潜在向量来学习动作T0北美的潜在效果。然而,动作属于流派领域,而北美属于地区领域,然而我们使用相同的潜在向量来表示男性。
FFM 将这种单一的表现方式分解成多个潜在向量——每个向量代表一个场。这样做背后的直觉是,<v_male, v_action>
和<v_male, v_northamerica>
的潜在向量可能非常不同,我们希望更准确地捕捉它们。FFM 领导下的互动将如下:
作者照片
为了了解<v_male, v_action>
的潜在效果,我们使用v_male,genre
,因为我们想要将潜在向量专门用于类别字段。同样,我们使用v_action,gender
是因为我们想要捕获专门针对性别字段的潜在向量。
什么时候我们应该使用 FFM 而不是调频?
比较 FFM 和 FM,FFM 为每个特征学习多个潜在向量,而 FM 为每个特征学习一个潜在向量。人们可以把前者解释为试图在更细粒度的层次上表现相互作用。因此,表示这种颗粒相互作用所需的潜在特征 k 的数量较少,即 FFM 中的 k 、FM 中的< < k 。
在 FFM 的官方论文中,经验证明,对于具有许多分类特征的大型稀疏数据集,FFM 表现更好。相反,对于小而密集的数据集或数值数据集,FFM 可能不如 FM 有效。FFM 还容易在训练数据集上过度拟合,因此应该使用独立的验证集,并在损失增加时使用早期停止。
摘要
作者照片
希望这对那些探索 FFM 或 FM 在稀疏矩阵监督学习应用中的使用或探索推荐系统的人有所帮助。:)欢迎随时留言评论!
来源: UncleLeo /Shutterstock
支持我! —如果你喜欢我的内容并且没有订阅 Medium,请考虑支持我并通过我在这里的推荐链接订阅 ( 注意:你的一部分会员费将作为推荐费分摊给我)。
参考资料:
[2] 因式分解机
[3] 谷歌的推荐系统课程
梯度下降的直观解释
最广泛使用的机器学习算法之一将在 5 分钟内解释
梯度下降广泛应用于机器学习领域,本质上是一种用于寻找成本函数最小值的优化算法。在数据科学中,梯度下降用于细化我们的模型的参数(系数),以最小化误差。我们将通过下面的示例来了解梯度下降的工作原理。
想象一下,上面的图表代表了人的身高和体重之间的关系;高个子的人通常比矮个子的人更重。假设我们希望找到最佳拟合线,即最能代表上述数据的等式。
上图显示,左边的(红色)最佳拟合线比右边的精确得多。这可以通过观察每个点和最佳拟合线之间的距离来看出。距离越小(误差越小),最佳拟合线越好。最佳拟合线由我们在高中时都学过的方程表示,y = mx + b。
要理解梯度下降,我们首先需要理解什么是成本函数。
成本函数本质上是我们希望最小化的东西;在这种情况下,我们希望最小化数据点和最佳拟合线之间的距离。如果成本函数更直观,可以将其视为误差函数。为了理解成本函数,让我们使用一个更简单的例子。
假设有数据点正好落在最佳修复线上,y = x,其中斜率等于 1。在这种情况下,数据点与最佳拟合线之间的距离又称成本函数 、 将等于零。
现在假设我们将最佳拟合线移动到绿线,以使斜率等于 2(绿线)。现在,数据点和最佳拟合线之间的距离增加了。表示成本函数增加。类似地,如果我们移动最佳拟合线以使斜率等于(蓝线), t 成本函数将等于绿线增加。
如果我们用相应的成本函数绘制最佳拟合线的斜率,我们可以看到 1 的斜率最小化成本函数,也就是最小化数据点和最佳拟合线之间的距离。如果你回头看我们的图,斜率等于 1,这是真的!
现在谈谈有趣的事情。
梯度下降是一种算法,用于实质上最小化成本函数;在上面的例子中,梯度下降会告诉我们,1 的斜率会给我们最精确的最佳拟合线。
虽然看起来令人生畏,但其实很简单。让我解释一下:
- θj 等于 m(斜率)
- α等于学习速率(稍后我将对此进行更详细的解释)
- (∂/ ∂θj)*J(θ)等于点 m 处成本函数的偏导数(成本函数的斜率,不是最佳拟合线)
- 重复直到收敛仅仅意味着重复算法直到它达到全局最优值(在本例中为最小值)。
换句话说,这种算法意味着:
重复用 m 点处成本函数的斜率乘以系数(α)减去最佳拟合线的斜率,直到偏导数的斜率为零。
新斜率=最佳拟合线的旧斜率—α*点 m 处成本函数的偏导数
为了展示一个例子,假设我们从一条斜率为 2 的最佳拟合线开始。如果我们观察成本函数上斜率为 2 的点(绿点),我们可以得到该点的偏导数,也就是与曲线相切的绿线的斜率。在这里,我们可以看到偏导数是正的。回顾我们的等式,
*新斜率=最佳拟合线的旧斜率—α**点 m 处成本函数的偏导数
新的斜率(m)将等于 2 减去 一个正数(因为偏导数是正的),这将我们带到红点(如上所示)。
如果部分推导是负的 aka,如果点开始于图的左侧,则新斜率将等于旧斜率减去负数,其等于旧斜率加上 正数。
我们会重复这个过程,直到我们达到收敛,也就是我们达到一个最小值,因此,我们会确定最佳拟合线的斜率,使成本函数最小化!
在梯度下降算法中关于 alpha (α)的一个简短注释,
如果α太大,则算法将在每次迭代中过冲(如左图所示),这可能会阻止它达到最小值。反之,如果α太小,则需要太长时间才能达到最小值。因此,α必须介于两者之间,使得这两种情况都不发生。
简而言之,这就是梯度下降!
支持向量机(SVM)内核的直观解释
简而言之,内核是帮助我们更快完成某些计算的捷径,否则这些计算将涉及到更高维度空间的计算。这听起来相当抽象。在这篇博文中,我将带你看一个只需要基本算法的简单例子。
简单的例子:
我们有一个三维向量 x = (x1,x2,x3)。我们这样定义这个运算 f(x):f(x)=(x1x 1,x1x2,x1x3,x2x1,x2x2,x2x3,x3x1,x3x2,x3x3)。换句话说,它想把 x 中的每一对相乘,产生一个 9 维向量。
我们插上一些数字,更直观一点!假设 x = (1,2,3);y = (4,5,6)。然后:
f(x) = (1,2,3,2,4,6,3,6,9)
f(y) = (16,20,24,20,25,30,24,30,36)
现在,由于某种原因,我们实际上并不关心 f(x)和 f(y)。我们只想知道点积,
一大堆代数!主要是因为 f 是从 3 维到 9 维空间的映射。尽管最终的答案只有一个数字,但我们必须在中间“膨胀”,在 9 维空间中完成所有这些繁琐的计算,然后才能浓缩成一个数字。
如果我告诉你有一条捷径呢?
我声称“内核”,K(x,y ) = (
让我们来测试一下:
提醒:x = (1,2,3);y = (4,5,6)。
K(x,y) = ( < x,y > ) = 32 = 1024
瞧,同样的结果。但是这个计算要容易得多,因为我们只在三维空间中操作。我们从未涉足 9 维空间!
数学定义:
现在让我们继续讨论一些数学形式。
K(x,y) =
k 表示核函数。这里 x,y 是 n 维输入。 f 是从 n 维度到 m 维度空间的映射。通常 m 比 n 大很多。内核是一个函数,取 x 和 y作为输入,不需要计算 f(x) 和 f(y) 就能得到与<f(x)、 f(y) >相同的结果。
内核还有一个好处:它们允许我们在无限的维度上做事情! f(x) 可以是从 n 维到无限维的映射,因而不可能先写出 f(x) 和 f(y) ,再做点积。那么内核给了我们一个绝妙的捷径。一个这样的例子是径向基函数(RBF)内核。
与 SVM 的关系:这与 SVM 有什么关系?SVM 的思想是 y = wφ(x)+b,其中 w 是权重,φ是特征向量,b 是偏差。如果 y >为 0,那么我们将数据分类为 1 类,否则分类为 0 类。我们希望找到一组权重和偏差,以使利润最大化。一些教材说,对于 SVM 来说,内核使数据线性可分。我认为更准确的说法是,内核不能让数据线性分离。特征向量 phi(x)使数据线性可分。核是为了让计算过程更快更容易,特别是当特征向量 phi 的维数非常高的时候。
为什么也可以理解为相似度的度量:
如果我们把核的定义放在上面,< f(x),f(y) >,在 SVM 和特征向量的上下文中,就变成了< phi(x),phi(y) >。点积意味着 phi(x)到 phi(y)的投影,或者通俗地说,x 和 y 在它们的特征空间中有多少重叠。换句话说,他们是多么的相似。点积是衡量相似性的指标。内核只是一种实现点积效果的方法,而不需要在 f(x)和 f(y)之间做点积。
原载于www.quora.com。
随机森林的直观解释
在 Unsplash 上由 Deglee Degi 拍摄的照片
群体的智慧…决策树的智慧
2004 年,记者 James Surowiecki 出版了一本名为《群体的智慧》的书,在书中他认为一个群体的平均决策往往比任何一个个体的决策要好。
例如,这个理论表明,如果你问一群人一个罐子里有多少块糖,然后把他们的答案加起来平均,结果会比许多最佳的个人猜测更准确。
Surowiecki 继续解释说,这种效应并不总是正确的,而是有一些特定的特征使群体变得明智:
▹:这个小组必须有不同的信息和背景
▹人必须独立做出决定
▹一定有收集信息的方法
同样的思路也支撑着最受欢迎的机器学习算法之一——随机森林——一种结合多个决策树的结果进行准确预测的方法。
决策树是现代机器学习中最重要的概念之一。他们不仅是一个有效的…
towardsdatascience.com](/building-an-intuition-for-the-decision-tree-algorithm-75e0786e86d)
算法是如何工作的
正如一个群体必须有不同的个体才能变得明智一样,一个随机森林必须由不同的决策树组成才能有效。
随机森林算法通过两种方式鼓励这种多样性。
首先,随机森林中的每个决策树都根据不同的数据子集进行训练。这是通过一种称为“随机抽样替换”的抽样过程实现的,其中记录是随机选择的,但不会从初始数据集中删除。通过设计,这鼓励了每个树的训练数据集中的重复。因为这个过程是重复的,所以每个决策树“知道”不同的数据子集。
作者图片
随机森林算法还通过在每个决策树的每次分裂中选择完整特征列表的随机子集来创建多样性。该子集的大小是一个灵活的参数,但一个常见的选择是使用特征总数的平方根(这是随机森林分类器的 scikit-learn 实现默认使用的)。
例如,假设我们正在用三个决策树和十个特征训练一个随机森林。
在第一个决策树的根(第一个)节点,算法将随机选择三个特征(10 的平方根是 3.2)。然后,它会找到可能的最佳分割,并再次选择三个随机特征来评估下一次分割。对每棵树的每一次分裂都重复这一过程。
作者图片
最终,这一过程会生成暴露于不同信息的树,然后将这些树聚合在一起以做出最终预测。
对于回归问题,随机森林取每棵树预测的平均值。对于分类,它采用众数或多数。
关键超参数
随机森林和决策树的最重要的超参数几乎是相同的。
标准或成本函数定义了用于识别每棵树最佳分割的方法——基尼系数、特征重要性等。最大深度告诉每棵树离根节点有多远可以生长。用于分割的最小样本定义了每个节点中必须存在的记录数量,以继续另一个分割。
有两个额外的超参数专门适用于随机森林。
首先,数量估计器定义了森林中包含多少棵树。虽然增加树的数量不太可能损害准确性,但往往会有收益递减。当然,估计器越多,训练模型的时间就越长。
第二, max features 超参数定义了在每棵树的每个分割点有多少个可用的特性。如上所述,一个常见的默认值是特征总数的平方根。
与大多数算法类似,正确的超参数集通常因项目而异。交叉验证搜索有助于确定最佳值。
好处和权衡
随机森林算法有几个好处。首先,它是通用的——它适用于分类和回归问题。第二,它不需要特征缩放或异常值处理,因为数据的方差不影响底层决策树如何找到最佳分裂点。这使得实现起来相当快。最后,由于上面讨论的原因,随机森林比决策树更不容易过度拟合——它们是在比单个树更多样化的数据集上训练的。
随机森林算法的一个主要缺点是更难解释。决策树非常清晰地讲述了预测是如何从各种特征组合中得出的。另一方面,在一个随机的森林中,推论分布在无数的树上。从本质上讲,随机森林也比简单决策树需要更长的训练时间,并且在大型数据集上运行缓慢。
摘要
随机森林是一种算法,它聚合大量独立训练的决策树来进行预测。这种“群体智慧”的方法允许它从一组不同的数据中学习,从而得到更稳定、更概括的结果。由于其独创性和易用性,随机森林是应用数据科学的中流砥柱。
P.S. →如果你想了解更多关于 SQL、Python、数据科学的知识,订阅我的 免费邮件列表 。
自我注意的直观解释
多头自我注意块的逐步解释
来源:注意力是你所需要的全部
在这篇文章中,我将解释你需要知道的关于自我关注的一切。
变压器神经网络包含什么使它们比常规递归神经网络更强大、性能更好?
答:他们使用多头自我注意块给单词嵌入输入更多的上下文信息。但是,自我关注模块对单词嵌入究竟做了什么,使得这些变形金刚模型变得如此强大?
这是本文的重点。这篇文章的主要目的是描述自我关注块的每个部分背后的直觉和其中涉及的数学运算。
本文的目的不是解释变压器神经网络的整体结构。它也没有描述自我注意和常规注意之间的区别。
什么是自我关注,为什么我们需要它?
我们知道单词嵌入是代表单词语义的向量。意思相似的词可能有相似的嵌入。然而,在一个句子中,单词的单个含义并不代表它们在句子中的含义。例如,如果我有一个短语,Bank of a river,Bank 和 river 的嵌入分别表示完全不同的东西,但它们在句子中有很强的相关性。没有自我关注的单词嵌入不具备这种上下文信息的意义,因此给定上面的短语,语言模型预测 river 的机会很低。为了解决这个问题,在论文中提出了自我关注模块,作为原始变压器架构的一部分。
自我注意模块通过将句子中的每个单词与句子中的每个其他单词(包括其自身)进行比较,并重新加权每个单词的单词嵌入以包括上下文相关性来工作。它接受没有上下文的 n 个单词嵌入,并返回有上下文信息的 n 个单词嵌入。例如,在短语 Bank of the river 中,Bank 将与 Bank、of、the 和 river 进行比较,当 Bank 与这四个单词进行比较时,其单词 embedding 将被重新加权,以相应地包括单词与其在句子中的含义的相关性。
但是它到底是如何工作的呢?
自我关注模块由三个步骤/部分组成:
- 点积相似性来查找比对分数
- 对分数进行归一化以获得权重
- 使用权重对原始嵌入进行重新加权
1.点积相似度
当输入的单词嵌入被传递到自我注意模块并找出他们应该注意谁时,他们需要一个函数来找出他们与句子中的其他单词有多相似。这就是点积相似性发挥作用的地方。
对于下面的解释,我将使用下面的例子:
Words:
v1 v2 v3 v4
其中 v1、v2、v3 和 v4 是单词在句子中的单词嵌入。
在我们的例子中,我们将自我关注 v3,并将其与 v1、v2、v3 和 v4 进行比较。我们还必须将每个单词与其自身进行比较(例如 v3 到 v3)的原因是为了使模型能够了解它应该注意单词的语义的哪些部分。一个词可能不得不关注它自己,这似乎是不寻常的。然而,有时一个单词在其嵌入中可以有一个以上的含义(如 Bank 的例子),除非我们也将它自己包括在点积相似性中,否则模型将无法了解它应该注意单词含义的哪些部分。简而言之,单词通常有不止一个含义,为了让模型识别出它应该关注单词的哪个含义,我们必须通过将单词包括在点积相似度中来将单词与它们自身进行比较。在我们的示例中,v3 与所有其他单词及其自身进行比较,如下所示:
(v1*v3) = S31
(v2*v3) = S32
(v3*v3) = S33
(v4*v3) = S34
我们将取 v1 和 v3、v2 和 v3、v3 和 v3 以及 v4 和 v3 的点积来确定每对嵌入的比对分数。比对分数 S31、S32、S33 和 S34 将告诉我们 v3 和四个被比较单词中的每一个的语义有多相似。对齐分数越高,单词的语义就越相似,v3 就必须更加注意该对中的另一个单词。注意,每个比对分数是单个数字,而不是数字的向量或矩阵。
我只对一个词做过这个过程:v3。实际上,这个过程将使用向量化和线性代数对所有四个单词同时进行。
为什么点积相似会起作用?
就拿国王和王后的嵌字来说吧。
King = [0.99, 0.01, 0.02]Queen = [0.97, 0.03, 0.02]
这一对的比对分数将是:
(0.99 * 0.97) + (0.01 * 0.03) + (0.02 * 0.02) = 0.961
现在以单词“国王和狗”的嵌入为例
King = [0.99, 0.01, 0.02]Dog = [0.01, 0.02, 0.02]
这一对的比对分数是
(0.99 * 0.01) + (0.01 * 0.02) + (0.02 * 0.02) = 0.0105
请注意,这些单词嵌入是虚构的,真实的单词嵌入 dog、king 和 queen 的大小可能要大得多。还要注意第一个索引,其中 king 和 queen 的数字较高,表示特定单词的版税。
如你所见,国王和王后的比对分数比国王和狗大得多。这是因为国王和狗的语义不同,所以它们在句子中对彼此并不重要。指数 1 代表这个词的王权,因此国王和王后在这方面是相似的。
简而言之,如果两个单词的语义不同,则对齐分数不会很高,单词的对应性会很低,并且每个单词对彼此的关注度会很低,因此每个单词的原始单词嵌入不会改变太多。如果两个单词的语义在任何方面都相似,那么对齐分数将会很高,这些单词将具有很高的对应性,并且这两个单词将会高度关注彼此,因此每个单词的原始单词嵌入将会经历显著的变化。
2.标准化比对分数
通过激活函数归一化任何神经网络的输出值是一个常见的过程。我们将使用 SoftMax 激活函数来归一化对齐分数,以获得我们将应用于原始单词嵌入的权重。SoftMax 函数将使每个比对分数成为概率分布,因此它们加起来都是 1。在我们的例子中,
S31 -> SoftMax -> W31
S32 -> SoftMax -> W32
S33 -> SoftMax -> W33
S34 -> SoftMax -> W34
将对所有四个对齐分数进行软最大化,以获得必须应用于原始单词嵌入的最终权重,从而创建最终的上下文化嵌入。
请注意,当我在上面的段落中说“权重”时,我不是指模型将学习的参数。
3.最终重新称重过程
现在进行最后的重新称重过程。为了确定单词(v3)应该给予其他单词的关注总量,我们将权重乘以它们各自的原始单词嵌入,然后将所有这些值加在一起,以获得被比较单词(v3)的最终单词嵌入;在这种情况下,
W31 * v1 = Y31
W32 * v2 = Y32
W33 * v3 = Y33
W34 * v4 = Y34Y31 + Y32 + Y33 + Y34 = Y3
Y3 是 v3 的最终重新加权的字嵌入向量。请记住,Y31、Y32、Y33 和 Y34 都是独立的向量,因此我们必须将它们相加,以获得一个最终向量。
请记住,上述过程也将针对句子中的每一个其他单词进行。
直觉上,上述所有过程都是有意义的,除了一件事:因为没有要学习的权重,所以对齐分数和自我关注权重本质上是预先确定的,模型将无法学习两个单词之间的任何更深层次的联系。这就是为什么我们将在自我关注模块中引入权重。但是在哪里?为了让模型学习单词之间最深层的联系,我们将在三个位置引入权重:输入单词嵌入、点积相似性比较和重新加权单词嵌入的最后一步。此外,在这些位置引入单词的另一个好处是相乘的向量的形状/维度不会改变。请记住,如果我们有一个 1 x k 形状的向量,我们把它乘以一个 k x k 形状的矩阵,这将产生 1 x k 形状的向量。因此,即使我们在描述的位置引入权重,维度或形状也不会有任何改变。
这就是为什么我们必须在具有原始单词嵌入向量 v1、v2、v3 和 v4 的地方引入权重,因为这些向量的形状都是相同的,并且即使我们引入 k×k 的权重矩阵,这些向量的形状仍然是 1×k。我们使用原始嵌入向量的三个位置是输入单词嵌入、当我们将每个单词与其他单词进行比较时的点积相似性,以及在最终的重新加权过程中当我们将归一化权重乘以原始单词嵌入时的点积相似性。对于权重,我们的计算如下所示:
(v1 * Mk) * (v3 * Mq) = S31
(v2 * Mk) * (v3 * Mq) = S32
(v3 * Mk) * (v3 * Mq) = S33
(v4 * Mk) * (v3 * Mq) = S34S31 -> SoftMax -> W31
S32 -> SoftMax -> W32
S33 -> SoftMax -> W33
S34 -> SoftMax -> W34(v1 * Mv) * W31 = Y31
(v2 * Mv) * W32 = Y32
(v3 * Mv) * W33 = Y33
(v4 * Mv) * W34 = Y34Y31 + Y32 + Y33 + Y34 = Y3
如您所见,无论我们在哪里使用原始的单词嵌入 v1、v2、v3 和 v4,我们都将这些向量与相应的权重矩阵相乘。Mk、Mq 和 Mv 只是模型将学习的键、查询和值矩阵/权重。记得在上面的计算中,我只做了一个词的自我关注操作,v3。实际上,通过矢量化和一些线性代数,这将同时发生在所有单词上。
请注意,在上图中,当我将键、查询和值矩阵与它们各自的嵌入向量相乘时,我做的是矩阵乘法,而不是点积。
多头注意力
虽然一个自我注意块足以让一个词获得语境相关性似乎是合理的,但事实并非如此。往往一个词会不得不关注多个其他词,一个自我关注块对多个词来说可能不够关注。这在输入文本非常大的例子中尤其明显(例如,对于文本摘要任务)。因此,一对具有上下文相关性的单词有时不会得到足够的关注,从而使它们各自的嵌入发生可观察到的变化。
为了解决这个问题,我们将使用多头注意力块。多头注意力块扩展了模型关注输入文本中不同位置的能力。
多头关注块本质上与常规的自我关注块是相同的东西,但是多头关注块将包含并行操作的多个自我关注块,而不是仅仅一个关注块。这些自我关注块将不共享任何权重;他们唯一共享的是相同的输入单词嵌入。多头注意块中自我注意块的数量是模型的超参数。假设我们选择有 n 个自我关注块。这样做的结果是,在每个自我关注模块完成所有单独的计算后,我们将为每个单词提供 n 个嵌入。为了修复这个问题,多头注意力块将这些嵌入串联起来,最后通过一个密集层传递。请记住,我们希望输入的形状和数量等于输出的形状和数量。因为我们连接了嵌入,所以我们保持输入的数量等于输出的数量。因为我们通过密集层传递连接的输出,所以我们能够控制它们的形状,确保它与输入的形状相同。
摘要
自我注意块将句子中单词的单词嵌入作为输入,并返回相同数量的单词嵌入,但带有上下文。它通过一系列键、查询和值权重矩阵来实现这一点。多头关注块由多个并行操作且不共享权重的自我关注块组成。在每个自关注块返回新的上下文化单词嵌入之后,多头关注块将这些新的嵌入连接在一起,并通过密集层传递它们,以便控制输出的形状。这允许单词嵌入得到足够的关注,这将在其嵌入中产生可观察到的变化。
我希望您觉得这些内容简单易懂。如果你认为我需要进一步阐述或澄清,请在下面留言。
参考
你所需要的就是关注(arxiv.org)
相关文章
插图:自我关注(towardsdatascience.com)
贝叶斯信息准则的直观解释
如何知道你是否选择了正确的模型
米歇尔·特雷瑟默在 Unsplash 上拍摄的照片
在机器学习中,当面对堆积如山的未标记数据时,数据科学家的第一个冲动是尝试对数据进行聚类。聚类为我们提供了一种描述数据、发现数据点之间的共性以及捕捉异常值的方法。
但是在没有任何先验知识的情况下,我们如何知道数据中存在多少个聚类呢?
大多数聚类技术要求我们选择固定数量的聚类。像 k-means 这样的算法然后会找到这些 k 不同聚类的中心。有时目视检查会有所帮助。
该数据集中似乎有 3 个聚类。
目视检查可以是一个良好的开端,尤其是如果您的数据是二维或三维的。除此之外,可视化变得更加棘手。
让我们停下来一分钟,问问自己,当我们进行视觉检查时,我们的大脑在做什么。
我们的视觉系统非常善于分辨对比。我们寻找点密度的对比,然后挑选出高密度的空间分离区域。然后我们计算我们发现的这种区域的数量。对于这些致密区域之外的点,我们会问:“这代表另一个星团吗?”或者“这是原始集群之一的异常值吗?”
我们的大脑正在执行类似贝叶斯估计的东西。我们实际上是在问,“我们的数据被我们的模型解释的概率是多少?”以及“解释我们的数据的最简单的可能模型是什么?”
模型 m 的极大似然函数。
第一个问题是关于似然函数,用 L 表示。我们的数据 x 用模型 M 来解释的可能性有多大(比如一些聚类的方法),这些模型有一定的模型参数(比如聚类的中心和范围)。
当我们找到最大化这个概率的参数值时,我们用克拉( ^ )来表示它们。这给出了“最大似然函数”,用一个克拉表示为 L 。
回到我们的例子,您可以想象一个模型,它有多少个数据点就有多少个聚类。看,没有异常值!
但这不是一个非常有用的模型。
所有的模型都是错的,但有些是有用的。
我们必须平衡我们模型的最大可能性, L ,与模型参数的数量, k 。我们寻求参数数量最少但仍能很好地解释数据的模型。因此,我们引入了模型参数数量的惩罚。**
我们现在已经接近贝叶斯信息准则(BIC)。
BIC 针对最大似然函数平衡模型参数数量 k 和数据点数量 n 、 L 。我们寻求找到最小化 BIC 的模型参数 k 的数量。
这种形式的 BIC 源自 Gideon Schwarz[1]1978 年的一篇论文。这种推导可能很难理解,所以我们在这里不做深入探讨。
计算最大似然函数是最难的部分,但对于大多数常见的模型,存在分析函数。例如,在线性回归中,对数似然就是均方误差。
标准的机器学习库通常会为你计算似然函数,所以不要绝望。
让我们完成数据聚类的例子。我想使用高斯混合模型对数据进行聚类,并确定要选择的最佳聚类数。在 Python 中,使用 scikit-learn 库,方法如下:
绘制不同值的 k 的 BIC,我们可以看到 3 个集群的 BIC 是如何最小化的。
BIC 同意我们最初的视觉估计。它还告诉我们,更大数量的聚类也可以很好地拟合数据,但代价是必须引入更多的参数。
结论
您总是可以找到适合您的数据的模型,但这并不能使它成为一个伟大的模型。遵循奥卡姆剃刀原理,我们应该总是选择做出最少假设的模型。在机器学习中,过度拟合模型在野外表现不佳。
有了四个参数,我就能适应一头大象,有了五个参数,我就能让它扭动鼻子。
—约翰·冯·诺依曼
使用贝叶斯信息标准,您可以找到仍然工作良好的最简单的可能模型。希望这篇文章已经让您对它的工作原理有了直观的感受。
参考
[1] G. E .施瓦茨,估计模型的维数 (1978),统计年鉴,6(2):461–464
向量的直观解释
涉猎线性代数
在这篇介绍性的文章中,我将定义向量,讨论一些解释它们的方法,然后对它们相关的数学运算提供一个直观的解释。
定义向量
先说一个大家熟悉的小学时的练习题。我们将在 X,Y 数字网格上绘制一个点(1,2),其中 X 代表水平方向,Y 代表垂直方向。
我们已经在定义向量的道路上走得很好了。关键的区别在于,我们不再用网格上的“点”来思考世界,而是需要开始思考“线”。
在上面的例子中,我们已经从点(0,0)移动到点(1,2)。我们的矢量就是代表这种运动的直线:
如果您仔细观察,您会发现我们的产品系列有两个关键特性,而我们的观点没有:
- 星等:这是“长度”的同义词我们也可以认为这是“我们已经走了多远。”
- 方向:与我们的点不同,我们的线实际上是朝着某个方向运动的。
现在我们可以给这个概念下一个正式的定义了。根据韦伯斯特的说法一个矢量是:
"一个具有大小和方向的量,通常用一条有向线段来表示,其长度代表大小,其空间方向代表方向。"
我更喜欢简单的定义:“空间中的一条线。”
表示向量的一种常见方式是将 X 和 Y 维堆叠在一起:
2D 向量的简单表示
我们也可以通过超越二维来扩展我们小学对坐标系的理解。
在可感知的现实世界中,我们有三个维度——左/右、前/后和上/下。在空中挥动你的手,想想它是如何向这些方向移动的。现在你对三维向量有了理解。
我们也可以尝试可视化我们的三维向量。让我们取原始向量(1,2)并添加一个第三维,我们称之为 Z,并设置值为 1。下面是生成的向量(1,2,1):
这幅插图没有很好地体现三维,因为它是在 2D 的屏幕上显示的。一旦我们开始超越三维,人类大脑的视觉化就变得非常具有挑战性。如果你想试试,我推荐你去 youtube 看看一些流行的尝试。
但是,虽然我们的空间解释停留在三维,数学或分析解释可以更高。我们也可以开始从数字跳到它们可能代表的真实世界的实体。
让我们以 iris 数据集为例,这是一个用于在机器学习中引入分类的流行数据集:
这里,我们有四个“特征”或预测因子——萼片长度、萼片宽度、花瓣长度和花瓣宽度,我们可以用它们来预测我们的目标变量;花的类型(表示为 0、1 或 2)。
上表中的每一行和每一列都可以解释为向量。例如,我们可以这样表示我们的第一行:
或者,从几何学上来说,我们可以把花的这个实例想象成空间中的一条线,它在 4 个不同的方向上距离原点 5.1、3.5、1.4 和 0.2 个单位。
在我们进入数学之前,我恳求你停下来想一想我们刚刚发现了什么。每一个捕捉世界上真实和有形事物的数据集,都可以被转化为多维空间中的线。
向量运算
在本节中,我们将简要介绍与向量相关的数学运算。
在此之前,我将快速分享我学习数学的哲学。除非你是严格意义上的学者,否则数学的 目的是帮助我们解决世界上的真实问题 。不幸的是,我们必须在这一点与建立对基础知识的初步理解的需要之间取得平衡。在这篇文章中,我们没有时间去解决任何现实世界的问题,但是我鼓励你不要忘记这是最终的目标。
向量加法
数值上: 我们把两个向量上的每个维度相加。
举例: [1,2] + [1,-1] = [2,1]
几何上: 我们通过将一个向量的尾部放在另一个向量的头部,然后从我们的起点到我们的终点画一条线,来添加两个向量。
当我们把向量看作“旅行”的表示时,这有很大的直观意义我们只是将一段旅程加到另一段旅程上,然后测量我们的总旅程。
下面我们展示了蓝色向量[1,2] +红色向量[1,-1] =绿色向量[2,1]。
向量减法
数值上: 我们减去两个向量上的每一维。
例子: [1,2]-[1,-1] = [0,3]
几何上: 既然我们在做减法,那么我们可以把这个想象成把第二个向量(红色)的方向反过来,然后把它的尾巴放在第一个向量(蓝色)的头上,得到我们的结果(绿色):
标量乘法
数值上: 我们将向量的每一维乘以一个标量值:[1,1] * 2 = [2,2]
几何上: 我们的起始向量[1,1]保持它的方向但是“缩放”或者增长了标量值的因子。
向量的大小
数值上: 为了度量大小或长度 、 我们使用勾股定理:取向量中每个平方元素之和的平方根。下面是几个例子:
例 1:[1,2]的量级= sqrt(1 + 2 ) = sqrt(5) = 2.23
例二:[3,5,6]的量级= sqrt(3+5+6)= sqrt(9+25+36)= sqrt(70)= 8.36
几何上: 这个不需要可视化。你看到的只是矢量的长度。向量的大小通常用管道符号来表示:|V|。
矢量乘法(点积)
数值上: 我们对两个向量中每一维的乘积求和。结果将总是一个标量值。下面是几个例子:
例一:【1,2】【2,3】= 1 * 2+2 * 3 = 8。
例二:【1,2,3】【2,3,4】= 1 * 2+2 * 3+3 * 4 = 20。
几何: 这个有点棘手。与其进行直接的空间解释,不如让我们取一个向量0,1,并找出它与多个其他向量(下面的蓝色)的点积:
在这个练习中,我注意到了一些事情:
- 当蓝色向量的方向与红色向量的方向相似时,点积较大。
- 蓝色向量的大小越大,点积就越大。
- 当蓝色向量垂直于红色向量时,点积为 0。
鉴于这些观察,我对点积的简化解释是这样的: 点积告诉我们两条直线在方向上有多相似;按两个向量的大小缩放。
现在让我们看一个例子来巩固我们的理解,在这个例子中,X 在二维空间中具有非零值:
上面的每个点积在我们上面的解释中应该是有意义的。
为什么蓝色向量[1.5,2]与我们的红色向量的点积比蓝色向量[2,1]大?因为它的星等更大,方向更类似于我们的红色矢量。
为什么蓝色向量[1,-1]与我们的红色向量的点积为 0?因为这两个向量是正交的(彼此成直角)。它们指向不同的方向。
摘要
到目前为止,我们已经把向量定义为一个有大小和方向的线空间。我们已经知道,数据集中的每一行或每一列都可以在几何上表示为一个理论上无限维的向量。最后,我们已经完成了主要向量运算的数值和几何解释。
在我的下一篇文章中,我将定义矩阵并解释它们在线性代数中的作用。
word2vec 的直观解释
没有数学,没有代码,只有单词嵌入背后的逻辑
对单词嵌入的需求
在传统的监督机器学习任务中,数据科学家需要两个关键要素:
- 数据
- 发现数据模式的方法(算法)
反过来,计算机可以做两件事:
- 通过将算法应用于数据来学习模式
- 使用这些学习到的模式对新数据进行预测
一个经典的例子——我们取了一些关于不同花的数据点(即花瓣长度,花瓣宽度),我们选择一个分类算法(即。随机森林),我们的计算机使用该算法来识别模式并对其他花卉进行分类。
将这种通用方法联系在一起的一个关键因素是,数据科学家用计算机理解的语言——数字——与计算机交流。提供的“数据”必须是数字,这样才能工作。
那么,当我们拥有的“数据”是文本而不是数字时,我们能做什么呢?当花瓣长度= 1.4 厘米,花瓣宽度= 0.2 厘米时,我们有一个句子——“我爱数据。”自然,我们必须找到一种方法将文本转换成数字。
一种方法是简单地创建用 1 和 0 表示单词的数据点。整个词典中的每个单词都成为一个数据点,只有给定句子、短语或文档中的单词被标记为 1。
例如,如果整个字典包含单词“I”、“love”、“data”、“Is”和“Cool”,我们对句子“I love data”的表示将是[1,1,1,0,0],其中前三个 1 表示存在“I”、“Love”和“Data”,后面的零表示不存在“Is”和“Cool”。“爱很酷”这句话看起来应该是这样的:[0,1,0,1,1]。
句子的一键编码表示
如果我们将上面的例子扩展到有更多单词的字典,我们现在有一个可伸缩的方法将文本转换成数字。这种方法被称为“一个热门编码”或“一袋单词”——通常对文本分类和情感分析等事情非常有用。例如,我可以将许多不同的推文转换成这些数字列表,然后训练一个模型来预测推文是正面还是负面(我可以使用数字 1 表示正面,0 表示负面)。
虽然这种方法有其优点,但它在几个关键方面失败了:
- 没有意义感或上下文感:计算机可以学习包含“欣喜若狂”这个词的推文是一条快乐的推文,但它无法学习“欣喜若狂”这个词与“激动不已”这个词几乎同义,与“失望”这个词几乎相反。
- 太多的数据点:为了对字典中每个单词的存在或不存在进行编码,每个单词都需要一个数据点(又名变量或特征)。英语中大约有一百万个单词。
解决方案是创建数字列表(线性代数术语中的“向量”),以更有创意的方式表示单词。这被称为单词嵌入。
Word2Vec 是 Google 在 2013 年开发的一种建模方法,用于创建这样的嵌入。(Word2Vec 旗下有几种不同的型号。我在下面概述了跳过克的方法)。
创建复杂的单词嵌入
为了克服单词袋方法的不足,我们需要一个系统来为相似的单词创建彼此相似的向量。
例如,单词 dog 和 cat 应该用比单词 dog 和 orange 更接近的数字来表示。大概是这样的:
为了创建这个系统,我们可以通过查看文本中“附近”的单词来利用上下文。例如,它可以了解到狗和猫有些相似,因为它们出现在句子中“treat”和“playing”这样的词附近:
“我给了我的狗一份礼物”
“我的狗喜欢玩捡球游戏”
“我的猫喜欢这种款待”
“我总是看到我的猫在玩那个玩具”
现在——困难的部分——我们如何教计算机解决这个问题?
Word2vec 的方法是训练一个模型,该模型可以预测整个文本(语料库)中每个单词的每次出现的所有相邻单词。
我们可以将我们正在关注的每个单词称为“中心单词”,将每个邻近的单词称为“上下文单词”。同样,我们试图预测全文中每个中心词的每次出现的所有上下文词。
下面是我们将用来训练模型的前 9 个“实例”,给定上面的句子,并假设窗口为 2(该窗口指定我们应该在每个中心单词的左右两侧寻找多少个点):
为了对每个训练实例进行预测,我们从字典中每个单词的随机数字向量开始。同样,我们这个练习的最终目标是让相似的单词有相似的向量。
在这个例子中,每个单词向量的长度为 3,但是理论上它可以是我们指定的任何长度。
一旦我们有了这些“起始向量”,我们就使用文本中的每个中心词/上下文词对来遵循以下步骤:
- 将中心单词向量乘以单词表示的完整矩阵。这个矩阵是所有其他单词向量的简单水平堆叠(行)。当这个乘法完成后,我们剩下一个向量,它有一个元素代表字典中的每个单词。下面是一个简单的视觉:
实际上,我们对每个上下文单词都有一个“结果向量”。
2。将向量转换成概率。这里我们使用的是 softmax 函数,它实际上是将每个数字除以向量中所有数字的总和。这给了我们一个有用的特性,即新向量中的所有数字的总和都是 1。它们现在可以被认为是概率。
3.计算概率。现在我们有了一个概率向量,我们的下一步是将它与“目标变量”(基础事实)进行比较。我们如何表示那些目标变量?我们只需要一个热编码。一个向量,上下文单词用 1 表示,其他单词用 0 表示。
然后我们可以计算一个损失函数(你的预测有多错误的分数)。这鼓励系统调整其预测向量,使得它们在更可能出现在上下文中的单词上具有更大的权重。
系统 怎么知道 去调整这些向量值也就是所谓的权重?
4.尽量减少损失。最后一步——反向传播——是神经网络调整其权重以最小化损失函数的过程。在这种情况下,权重是每个词向量的值。它们调整得越好,预测向量就越精确,损失就越低。
突然间,最初随机的权重被收紧,以创造我们所寻求的现实:彼此相似的词向量具有相似的数字,因为这些数字最小化了损失函数。他们为什么要最小化损失函数?因为它们准确地预测了相同的上下文单词。
申请
最终,我们对文本中的每个单词都进行了随机加权,并对它们进行了优化以表达含义,从而构建了一种新的与计算机对话的方言。下面是 3 个例子,说明如何使用生成的向量:
- 文本分类 — 通过平均/组合单词向量,以无数不同的方式对文本进行分类。
- 语音识别 —将口语单词转换成矢量,以便识别意思。
- 建议 — 创建任何有“上下文”的数字表示例如,歌曲可以表示为预测播放列表或队列中附近歌曲的向量。
自动编码器直观指南:理论、代码和可视化
自动编码器是最有用的非监督算法之一,可以洞察数据,从而优化训练算法的学习算法。
什么是自动编码器?
自动编码器是一种神经网络,它将数据作为输入,将数据作为输出。起初,这可能看起来很荒谬:一个数和它本身之间的关系仅仅是 1,为什么神经网络是必要的?这是真的,但是自动编码器已经创造了一种方法来绕过它。
利用瓶颈。瓶颈,从其常见的定义来看,意味着玻璃瓶颈部的狭窄缝隙。在这种情况下,瓶颈是指减少隐藏层中神经元的数量。因此,这就迫使数据只能由更少数量的神经元来表示。默认情况下,网络将学习压缩和解压缩数据的方法,将数据编码和解码为更大和更小的数据表示。
为什么自动编码器如此有用?
在一个数据集高达万亿字节的世界里,我们需要找到一种方法来有效地减少数据占用的内存。此外,处理信息的计算能力有限。由自动编码器创建的较小的表示变得如此重要,因为它占用的数据少得多。
此外,通过我将向你展示的可视化技术,你实际上可以可视化每个神经元在寻找什么。
代码:
既然自动编码器的理论已经很清楚了,我们可以继续看代码了。对于实际的自动编码器,我将使用 Keras,但是对于每一层所寻找的可视化,我将使用我自己的神经网络框架。
from keras.layers import Dense
from keras.models import Sequential
import requests
import json
除了标准的 keras 层和模型,我还将使用 requests 和 json,通过 alpha-vantage API 访问财务数据。
API_KEY = 'XXXXXXX'
from_symbol = 'EUR'
to_symbol = 'USD'close_price = [
r = requests.get(
'[https://www.alphavantage.co/query?function=FX_INTRADAY&from_symbol='](https://www.alphavantage.co/query?function=FX_INTRADAY&from_symbol=') +
from_symbol + '&to_symbol=' + to_symbol +
'&interval=1min&outputsize=full&apikey=' + API_KEY)
jsondata = json.loads(r.content)
pre_data = list(jsondata['Time Series FX (1min)'].values())
fx_data = []
for data in pre_data:
fx_data.append(list(data.values()))
fx_data.reverse()
for term in fx_data:
close_price.append(float(term[-1]))
这是我用来从 alpha-vantage 访问数据集的脚本。然而,要使用这个脚本,将 API 密钥更改为一个有效的密钥,您可以在这里得到。为了简单起见,脚本也只选择收盘价。
model = Sequential()
model.add(Dense(10,input_shape = (None,10),activation = 'relu'))
model.add(Dense(1))
model.compile(optimizer = 'adam', loss = 'mse')
model.fit(close_price,close_price,epochs = 100)
这个脚本创建了模型,只是使用密集层。你可以使用 KL-Divergence,一种防止模型仅仅记忆输入数据的方法。它通过激活神经元的数量来惩罚网络,从而减少表示数据所需的神经元数量。
这是完整的程序!简单吧?
可视化:
自动编码器的主要优势是能够可视化每个神经元在寻找什么。首先,将这个框架复制到你的程序中。
import numpy as np
from matplotlib import pyplot as pltdef sigmoid(x):
return 1/(1+np.exp(-x))def sigmoid_p(x):
return sigmoid(x)*(1 -sigmoid(x))def relu(x):
return np.maximum(x, 0)def relu_p(x):
return np.heaviside(x, 0)def tanh(x):
return np.tanh(x)def tanh_p(x):
return 1.0 - np.tanh(x)**2def flatten(itr):
t = tuple()
for e in itr:
try:
t += flatten(e)
except:
t += (e,)
return tdef deriv_func(z,function):
if function == sigmoid:
return sigmoid_p(z)
elif function == relu:
return relu_p(z)
elif function == tanh:
return tanh_p(z)class NeuralNetwork:
def __init__(self):
self.layers = []
self.weights = []
self.loss = []
def add(self,layer_function):
self.layers.append(layer_function)
def initialize_weights(self):
for layer in self.layers:
index = self.layers.index(layer)
weights = layer.initialize_weights(self.layers,index)
self.weights.append(weights)
def propagate(self,X):
As,Zs = [],[]
input_data = X
for layer in self.layers:
a,z = layer.propagate(input_data)
As.append(a)
Zs.append(z)
input_data = a
return As,Zs
def train(self,X,y,iterations):
loss = []
for i in range(iterations):
As,Zs = self.propagate(X)
loss.append(sum(np.square(flatten(y - As[-1]))))
As.insert(0,X)
g_wm = [0] * len(self.layers)
for i in range(len(g_wm)):
pre_req = (y-As[-1])*2
a_1 = As[-(i+2)]
z_index = -1
w_index = -1
if i == 0:
range_value = 1
else:
range_value = 2*i
for j in range(range_value):
if j% 2 == 0:
pre_req = pre_req * sigmoid_p(Zs[z_index])
z_index -= 1
else:
pre_req = np.dot(pre_req,self.weights[w_index].T)
w_index -= 1
gradient = np.dot(a_1.T,pre_req)
g_wm[-(i+1)] = gradient
for i in range(len(self.layers)):
self.layers[i].network_train(g_wm[i])
return loss
class Perceptron:
def __init__(self,nodes,input_shape= None,activation = None):
self.nodes = nodes
self.input_shape = input_shape
self.activation = activation
def initialize_weights(self,layers,index):
if self.input_shape:
self.weights = np.random.randn(self.input_shape[-1],self.nodes)
else:
self.weights = np.random.randn(layers[index-1].weights.shape[-1],self.nodes)
return self.weights
def propagate(self,input_data):
z = np.dot(input_data,self.weights)
if self.activation:
a = self.activation(z)
else:
a = z
return a,z
def network_train(self,gradient):
self.weights += gradient
model = NeuralNetwork()Perceptron = model.Perceptron
我不会深入讨论框架的代码,但它本质上是 Keras 的透明版本,可以给出每一层的传播值。
X = np.array([[1, 1, 1, 1, 0],
[1, 1, 0, 0, 1],
[0, 0, 0, 1, 0],
[1, 0, 0, 0, 0],
[0, 0, 1, 1, 1],
[1, 1, 0, 0, 0],
[1, 0, 0, 1, 0],
[1, 0, 1, 1, 0],
[0, 0, 0, 0, 0],
[1, 1, 0, 0, 1]])model.add(Perceptron(2,input_shape = (None,5),activation = sigmoid))
model.add(Perceptron(5,activation = sigmoid))model.initialize_weights()
loss = model.train(X,X,1000)
这个自动编码器仅用 MSE 训练了 1000 个时期。
As,Zs = model.propagate(X)
full_set = []
for a in range(len(As)):
a_set_values = []
for z in range(5):
zeroes =np.zeros(5)
zeroes[z] = 1
As,Zs = model.propagate(zeroes)
a_set_values.append(As[a])
full_set.append(a_set_values)
full_setimport matplotlib.pyplot as plt
import numpy as npplt.subplot(212)
for sets in full_set:
plt.imshow(sets, cmap='Greys', interpolation='nearest')
plt.show()full_set
然后,用数据传播网络。由于这里的数据很简单,我们遍历数据中的每一项,将其更改为 1,并查看它如何更改数据的每一层。然后我们绘制它的黑白图像,看看效果
谢谢你看我的文章!
我的链接:
如果你想看更多我的内容,点击这个 链接 。
基本统计学直观指南
基本统计概念入门
克里斯·利维拉尼在 Unsplash 上的照片
揭开数据集秘密的过程中最基本的部分之一是统计学(及其词汇,即概率)。直到最近,我一直对统计数据又爱又恨。这个主题对我来说总是令人生畏,从来没有直观的感觉。我最近看到了一本书,书名是《T4 统计学》,作者是蒂莫西·c·乌尔丹。这本书让我对统计学有了直观的认识,我希望通过总结这本书的观点也能让你对统计学有同样的认识。如果你有时间,我强烈建议你看看这本书。我会在这里尽力,但绝对值得。
目录
我们为什么关心?
让我们从理解我们为什么需要统计数据开始。从最简单的意义上说,统计学允许我们管理信息。它允许我们收集、研究和总结信息(/数据)。研究人员从大量人群中收集一些信息,利用这些信息总结他们的经验,并对一个群体做出一些一般性的陈述。例如,假设您正在建模一个数据集,目标是开发一个预测模型。从某种意义上来说,您正在做类似的事情:您收集一些信息(在 ML 中称为训练数据),通过做出一些合理的假设来总结这些信息(例如,作为模型参数),并(对测试数据)做出一般的陈述。所以,我认为加深对统计学的理解可以帮助我们成为更好的数据建模者。
人群 v/s 样本
简单来说,总体是我们希望拥有的,但样本是我们拥有的。总体代表感兴趣的某个组或类别的所有成员,而样本是从总体中抽取的子集。维恩图的一个类比是:群体是我们感兴趣的宇宙,样本是其中的一个事件。
图 1 事件 A 和宇宙 u 的维恩图。
从图 1 中,‘A’是样本,‘‘U’是总体。这就是我们在一个典型的数据建模练习中所做的事情:尝试使用可以推广到人口中未知部分的训练数据,即测试数据(=U-A),来建立一个模型。我们希望使用样本而不是总体的原因可能有很多:总体太大而无法收集(例如,在语言建模练习中,所有可能的句子的总集合非常庞大),信息收集过程昂贵且耗时,等等。这里的关键是,因为我们和一小部分人一起工作,所以我们希望它能代表真实的事情。这就是为什么统计学家们不厌其烦地思考抽样问题。
抽样
为了确保样本能够代表总体,我们采用了所谓的随机抽样。在统计学中,随机抽样意味着人口中的每个成员都有同等的机会被选入样本。基于这种方法,我们可以确定样本和总体之间的任何差异都不是系统性的,而是随机的。换句话说,我们可以说通过随机抽样,我们不会偏向于人口中的任何特定成员。这种类型的取样是最流行的方法之一,也用于 k 倍交叉验证。还有其他(细微差别)类型的采样技术,你可以在这里阅读更多。
分布
采集的样本可以包含不同类型的特征(/ 随机变量),如连续或分类。分布只是变量(/feature)上的数据或分数的集合。此外,一个变量上的任何分数集合,不管变量的类型如何,都会形成分布,并且这种分布可以用图表表示。我们通常对这些分布的特征感兴趣,例如分布的典型值、值的变化、分布的形状等等。研究随机变量的分布能让我们洞察它的行为。****
分布中的典型值通常使用均值(其他测量方法包括中位数、众数)和方差(或范围、IQR)等统计方法进行测量。其中最受欢迎的选择是均值和方差,但根据数据类型,其他选择可能更有用(例如,对于异常值,中值可能是比均值更好的选择)。方差提供分数分布中离差量的统计平均值。观察方差的一个问题是它的单位与原始变量不同。为了解决这个问题,我们通常看标准差(方差的平方根)。
为了对标准差有更深入的理解,我们来看两个词:离差是指一个个体值与平均分之差;标准指的是典型的或平均的。所以标准差是个别值和分布平均值之间的典型或平均偏差。标准差用于检查分数在分布中的平均离差。因此,当平均值的度量与离散值的度量结合时,我们可以得到分数分布的大致情况。关于样本标准偏差和方差公式中的修正,可在这里找到。检查分布的另一个有用的方法是箱线图。
正态分布
我计划通过谈论正态分布的重要性来激发这一部分。我认为这个问答线程做得很好。因此,我将在这里总结一些关于正态(也称为钟形曲线)分布的事实。
标准的正态分布。图片来源:维基媒体
它有三个基本特征:a)对称,b)均值,中值,众数都在同一个地方,即分布的中心,c)渐近,即上下尾部从不接触 x 轴。之所以在实践中使用正态分布,是因为我们关心的是样本中某件事只是偶然发生的确切概率。如果我们只对描述一个样本感兴趣,那么这些值是否正态分布并不重要。例如,如果样本中的普通人每天消耗 2000 卡路里,那么样本中出现一个每天消耗 5000 卡路里的人的机会(或概率)是多少?此外,我们通常对从总体中抽取样本进行推断感兴趣,这可以通过使用正态分布来完成。
那么,给定一个分布,我们如何发现它是否遵循正态分布?我们可以看一下偏斜度和峰度。这些是用来描述分布的特征。我们可以将分布的偏斜度和峰度与正态分布进行比较,以检查我们对给定随机变量是否遵循正态分布的假设。正如我们将在后面的章节中看到的,理论正态分布是统计学的一个关键要素,因为推断统计学中使用的许多概率都是基于正态分布的假设。
z 分数
有时我们对描述分布中的单个值感兴趣。使用平均值和标准差,我们可以生成一个标准分数,也称为 z 分数,来比较各个值的相对重要性。此外,这种标准化有助于我们比较两个独立变量的分布值(因为两者现在都在同一尺度上)。
例如,我们想比较吉姆的英语考试和统计学考试的成绩。假设英语测试的分值范围是 0-100,而统计学测试的分值范围是 0-200。此外,我们看了试卷,意识到统计学考试比英语考试更难。直接比较吉姆两次考试的分数是不正确的。比较合理的办法是先把分数标准化再比较。标准化以标准偏差为单位对测试分数进行重新分级。请注意,即使一个测试比另一个更难,这种差异在平均值和标准偏差中有所体现。换句话说,z 分数以标准差为单位表示分布中给定分数高于或低于平均值的程度。此外,当整个分布被标准化时,标准化分布的平均 z 得分始终为 0,标准差始终为 1。
让我们在这里暂停一会儿,以理解 z=1 的 z 分数会告诉我们什么。在吉姆的英语测试中,z=1 的 z 分数会告诉我们:a)吉姆比参加测试的一般学生做得更好,b)他的分数是平均值的 1 个标准差,c)如果分数是正态分布的,他比班上大约三分之二的学生做得更好(来自68–95–99.7 规则)。但是,仍然可能有许多 z 分数不打算描述的信息。例如,Jim 正确拼写了多少单词,或者他是否是一个好的拼写者,如果参加测试的其他学生是好的拼写者,则测试的难度水平,等等。类似于上面的例子如果我们确信我们的随机变量的分布是正态的,我们可以计算百分位数(使用 z 得分表)。****
值得注意的是,我们只是对计算百分位数感兴趣,我们可以在不计算 z 分数的情况下计算这些值:等级顺序观察值,并使用百分位数的定义。
标准误差
这是推断统计学中最重要的概念之一,并被广泛使用。考虑标准误差有两种方式。从形式上来说,标准误差被定义为某个统计量的抽样分布的标准偏差(如果这让你感到头晕,等一下,我们将把它分成几行)。另一种看待标准误差的方式是,它是许多推断统计中用于计算的公式中的分母。
让我们后退一步,试着更深入地理解这些定义。想象一下,我们对测量一个社区的平均身高感兴趣。基于我到目前为止所描述的一切,我们从社区的所有人中抽取一个样本。为了简单起见,我假设社区里有 4 个人,身高分别是 1cm、2cm、3cm、4cm。此外,让我们假设我们的样本大小为 2。这些都是可能的配对:(1,2),(1,3),(1,4),(2,3),(2,4),(3,4),以及基于这些的平均身高:分别是 1.5cm,2cm,2.5cm,2.5cm,3cm,3.5cm,群体平均身高是 2.5cm,我们可以观察到,我们计算的平均身高取决于我们抽取的样本,并且随着我们改变样本而改变。换句话说,我们感兴趣的统计数据(平均身高)由于随机抽样而有一些变化(即标准偏差),我们称之为标准误差。
如果我们试图在这种情况下剖析定义,它说存在一个抽样分布(我们得到这是随机抽样的结果;在示例中,这是平均身高的集合),该分布与平均身高(可以是我们感兴趣的任何其他统计数据,例如体重、智商等)相关联。),这样一个分布的标准差就叫做标准差。从本质上说,标准误差是对从同一人群中抽取的相同大小的样本的随机变异程度的度量。尽管所有的统计数据都有标准误差,但平均值的标准误差是最常用的。
为了避免混淆,区分抽样分布和简单的频率分布,抽样分布的均值和标准差被赋予了特殊的名称,即均值的期望值分别为和标准差。平均值被称为期望值,因为平均值的抽样分布的平均值(即通过重复收集样本并计算平均值生成的分布平均值)与总体平均值相同:当我们从总体中选择样本时,我们的最佳猜测是样本的平均值将与总体的平均值相同。这为我们提供了对标准误差的解释:当我们说样本平均值代表总体的平均值时,它为我们提供了可以预期有多大误差的度量(记住,标准偏差告诉我们个体值和平均值之间的平均差)(因此,命名为标准误差)。
很多时候,我们没有时间和资源从总体中抽取多个样本,求样本均值的分布(或抽样分布)的均值和标准差。到目前为止,我们已经说服自己,标准误差是存在的,它对分析很重要,而且我们通常无法获得抽样分布。这就给我们带来了这样一个问题:我们能利用样本中的信息来提供一些标准误差的估计值吗?
为了检验这个问题,让我们考虑一下样本的两个特征。首先,我们的样本有多大?样本越大,我们对总体的估计误差就应该越小,因为样本越大,就越像总体,所以估计也就越准确。其次,我们需要检查样本的标准差。这里我们假设总体标准差等于样本标准差。这个关于人口的假设可能不正确,但我们必须依赖他们,因为这是我们所有的信息。此外,如果我们知道总体标准差,我们可以使用它。因此,标准误差的公式为:
如果你最终浏览了我之前链接的 Q/A 主题,并且知道中心极限定理(CLT),那么我们也可以在这里说,CLT 指出,当我们有一个合理的大样本(例如,n=30)时,均值的采样分布将是正态分布的。
p 值
我认为这个术语相当流行。但是,让我试着让它更直观一点。在继续之前,我想稍微停顿一下,回顾一下我们到目前为止讨论的内容。我们发现,我们通常处理的数据和实际人口之间存在差异,因为不方便处理人口。为了生成样本,我们考虑适当的采样技术。一旦我们得到一个样本,我们就可以研究随机变量的分布,以了解我们的样本。我们还研究了所有统计中最基本的分布之一的一些特征,以及证明/否定随机变量的分布是否遵循正态分布的方法。我们还研究了一种标准化技术,它可以帮助我们比较不同尺度/分布上的随机变量的值。最后,我们理解了在将样本结果推广到总体的问题中,标准误差的重要性。在这里,让我们一起使用所有这些概念来进一步探索从我们的样本中归纳见解的想法。
假设我们有一个样本(来自城市 A),其平均智商测试得分为 110,全国平均水平为 100。我们可以看到,样本和总体得分 10 分之间存在差异,但这种差异是有意义的,还是微不足道的?也许,如果我再次采样数据,差异可能会改变。如果这给你的头脑带来了标准误差,你就在正确的轨道上!那么,我们如何知道这种差异不仅仅是由于随机机会(来自随机抽样技术)?更具体地说,我们正在寻找获得随机样本的概率,使得与全国平均水平的差异为 10 个点。暂停一下,想一想这个概率能给我们带来什么。
如果我们有这种概率,而且它很小,那么我们知道这种差异不是随机的,而是由样本的某些特征决定的。这就是 p 值的症结所在。一个流行的概率临界值是 0.05。这个 0.05 的 p 值表示,如果 10 个点的差异概率≤ 0.05,那么我们知道这个差异在某种意义上是有意义的,因为随机抽样我们看不到这个。
那么,让我们回到我们最初计算概率的问题。您可能还记得之前的内容,正态分布使我们能够计算概率(68–95–99.7 规则和 z 得分表)。为了确定 10 个点的差异概率,我们需要样本均值的正态分布或均值的正态抽样分布。我们也可以使用一个密切相关的 t 分布族来计算这个概率。正如你在这里看到的,这看起来非常类似于正态分布。您可以观察到,随着分布的大小(/ 自由度)增加,它趋向于正态分布。因此,考虑选择 t-分布的一种方式是,当我们不知道总体标准差,并且正在查看有限的数据(以样本的形式)时,在某些事件中减少信念可能是一个更好的想法:我们可以观察到 t-分布的 PDF 被压扁,这意味着尾端的概率相对于正态分布增加。计算 t 值的公式与 z 得分相同,只是它使用了从样本计算的标准误差(因为我们不知道总体标准偏差;如果我们知道它,我们就可以计算出 z 值,它被称为 t 值,因为我们使用 t 分布来计算概率。
实质上,如果我们知道总体标准偏差,我们可以使用它来计算 z 得分和正态分布,以计算样本与总体相比存在 10 个点差异的概率,如果不知道,我们可以使用标准误差来计算 t 值,并使用 t 分布来计算概率。
统计显著性
在这一节中,我们将把我们到目前为止学到的所有思想用于探索统计学的一个流行应用——推理。推断背后的想法是研究样本并推断出关于更大人群的结论。对于许多推断统计,我们经常问的问题的共同主题是,我们在样本中观察到的一些统计值与随机抽样产生的方差相比是大还是小(即,就标准误差而言)。请记住,这是一个重要的问题,因为作为随机抽样的结果,我们预计样本中会有一些变化(与总体相比),我们使用样本标准差和大小来量化这种变化,并将其称为标准误差。
继续上一节的智商测试示例,我们试图回答的具有统计学意义的问题是,10 分的差异是否是随机抽样的结果。三种常用工具用于得出关于统计数据的统计显著性的结论,它们是测试、效应大小和置信区间。简而言之,检验就是简单地使用标准误差来计算 p 值,并以此来检验统计显著性;由于观察到样本越大,标准误差越小(因为标准误差与样本大小成反比,导致 z 值(/t 值)越高),因此忽略样本大小的影响是有意义的;置信区间是量化区间的另一种方式,在该区间内,如果我们重复收集样本,我们可以确保实际的统计数据是真实的。
简单地说,统计显著性帮助我们决定我们从样本研究中得出的结论是否也适用于(更广泛的)人群。
假设检验
统计学中的另一个流行词。在这里,我们试图做的只是提出一个假设,并确认或拒绝它。从上一节来看,甚至在我们执行统计显著性测试之前,我们就想要建立一个基准。这个基准是我们的假设。
通常,主要假设是零假设(h0)。顾名思义,这假设了一个无效效应,或者说该效应不存在(这可以是我们感兴趣在人群中测量的任何效应)。与此互补的是交替假说(H_a)。再次顾名思义,我们正在考虑零假设的替代方案,即效果是存在的。所以,现在问题稍微变了:样本均值(这是一个例子,我们可以选择任何我们喜欢的统计数据)与总体均值的差异有多大,我们才能认为这种差异是有意义的,或者是有统计学意义的?注意,在这个问题中,总体均值是我们的 H_0,样本均值是 H_a。
例如,在之前的智商测试示例中,h0 是全国平均值 100,H_a 是样本平均值 110,我们正在测试我们的假设,即这个样本是否有什么特殊之处导致了 10 点的差异,或随机抽样,即具有统计显著性。
你可能已经注意到,在所有这些讨论中有一个警告。我们之前提到过,如果计算出的概率(p 值)足够小(我们定义为 0.05),那么我们说这些差异在统计上是显著的,或者说是有意义的。当我们接受 0.05 的截止值时,有可能实际上是我们的随机样本导致了这样的差异,并且 h0 是真实的,即我们最终选择了一个极其罕见的随机样本(例如,对于正态分布,选择这样的样本的概率将是 1–0.997 = 0.003!).所以,在这种情况下,我们最终会犯错误。这种误差称为 I 型误差,截止值为α。
我希望一些基本的统计概念现在直观得多。我跳过了一些建立在上述想法上的重要概念,这些概念相当有趣:相关性、 t 检验、 ANOVA 、回归。我将留给你们一个有趣的测试,在我们讨论过的事情的背景下:正态性假设检验。
置信区间的直观指南
用理论和模拟解构置信区间
克里斯·利维拉尼在 Unsplash 上的照片
统计学是基于我们观察到的数据。假设基础数据生成过程是随机的,并且统计建模的目标之一是理解该数据生成过程。由于数据本身是随机的,所以我们根据观察到的数据估计的任何数字都有一些内在的不确定性。思考这个问题的一种方式是,如果我们再次收集数据,并试图再次估计这个数字,结果可能会发生变化。换句话说,估计是可变的(想想:方差)。因此,我们通常对单个值(或点估计)不感兴趣,而是对一系列值感兴趣,这是谈论我们不确定的估计的自然方式。在统计学术语中,这被称为置信区间。简而言之,置信区间让我们以一系列值的形式量化估计的不确定性。
我过去研究过置信区间,从未对自己的理解感到满意。每一次,我都有一种模糊的感觉,我明白置信区间意味着什么,但从来没有确定的感觉。最近,我发现了一些启示,在这篇文章中,我将使用理论和模拟来讨论置信区间。
在深入细节之前,让我们检查一下我们对置信区间的理解。看看这篇文章和关于美国人在公共场合是否戴口罩以应对冠状病毒传播的情节。根据数据,84%的美国人在公共场合戴口罩,误差幅度(或置信区间)为+/- 2.6%点。为了便于讨论,让我们假设他们在谈论 95%的置信区间,因为这是一个相当普遍的选择。有个问题要问你,
Q : 这是否意味着区间【81.4%,86.6%】包含了在公共场合 95%时间戴口罩的人的实际百分比?
如果你对上述问题的回答是肯定的,那么你就像以前的我一样,在置信区间上犯了一个常见的解释错误。
让我们先来回顾一下确切的置信区间。
置信区间
形式上,参数‘θ’的‘1-α’置信区间是区间 C = [a,b],其中 a = a(X₁,X₂,…,Xn)和 b = b(X₁,X₂,…,Xn)是数据的函数,这样,
在上面的口罩例子中,α = 0.05 (95%的置信度),参数θ =为应对病毒传播而在公共场合戴口罩的美国人的百分比,a = 81.4%,b = 86.6%,这两个数据都是使用收集到的数据计算出来的。换句话说,上面的等式表明(真)参数包含在区间 C 中的概率至少为 1-α。注意,在上面的句子中,我是如何在单词 parameter 的前面默默地添加了单词 true 的。这就是置信区间的关键,即θ代表真实的参数值,它是未知的(否则调查是无用的),但是是确定性的。更明确地说,在冠状病毒传播时,在公共场合戴口罩的美国人的百分比是未知的,但这不是一个随机数字。如果我们有意志力和手段去调查所有美国人,我们就能找到这个未知的(确定性的)数字。
调查整个美国人口是不现实的,我们想用我们收集的数据做一些合理的猜测。基本上,通过置信区间,我们试图得出一个数值范围,它将包含美国人在 95%的时间里戴口罩的真实比例。注意,置信区间中的不确定性通过区间‘a’和‘b’的端点悄悄进入,区间‘a’和‘b’是数据的函数(假设数据是随机的!).
要点:置信区间谈论一个随机区间包含(未知)确定性真参数的概率。
解释
对置信区间的自然解释如下:想象一遍又一遍地重复实验(在这种情况下,这意味着做几次独立的调查)。对于每个实验,我们可以计算包含真实(未知)参数的置信区间。根据大数的 law,(随机)区间 95%的时间将包含真参数。这是因为我们可以用一个指示函数来表示区间包含真参数的事件,然后从 LLN 得出 0.95 的比例。
例子
现在,让我们来看看《所有的统计数据》一书中的一个例子来收集这些概念。
设θ是一个固定的未知实数,X₁和 X₂是独立的随机变量,使得 p(xᵢ=1)=p(xᵢ=-1 = 0.5。设 Yᵢ = θ + Xᵢ,假设我们只观察 y₂.y₁定义下面的“置信区间”,它只包含一个点,
我们很容易验证,对于θ的任意值,P(θ ∈ C) = 0.75。这是因为在第二种情况下,Y₁ ≠ Y₂,C = {θ},发生概率为 0.5,而在第一种情况下,C={θ}或 C={θ-2},均发生概率为 0.25。所以,“C”是 75%的置信区间。
我们来看看这个实验的一个实现。假设我们观察到 Y₁ = 15,Y₂ = 17。基于这个数据,我们 75%的置信区间是 C={16}。
这个计算出的置信区间没有说‘C’包含θ的概率是 75%。而是由于θ是固定的(见问题),要么包含在置信区间内,要么不包含在置信区间内。我们知道θ是未知的。如果(神奇地)我们知道了θ的值,我们就可以明确地观察到它是否包含在区间内(P(θ ∈ C) = 1),或者不包含在区间内(P(θ ∈ C) = 0)。换句话说,对于一个固定的(或确定的)值,没有什么是不确定的:它要么在区间内,要么不在区间内(例如 P(2 < 3) = 1)。
一个常见的陷阱:在观察数据并计算水平为‘1-α’的置信区间后,不再是真参数被包含(/陷)在该区间的概率至少为 1-α。间隔包含或不包含 true 参数。由于置信区间是一个随机变量,其基于数据的值是一个实现,其中代表一个 1-α置信水平,不再是概率性的。当我们称一个区间为 x%置信区间时,“x%”与估计过程(计算“a”和“b”的过程)的可靠性相关联。
这看起来有点奇怪,因为我们从来没有看到真正的参数θ(感觉它是随机的),但请记住,它是被假定为确定性的。这个概念来自频率主义者的解释,即θ是一个确定的未知数,它不可能是随机的。
摘要
红框是随机输入到机器中的。蓝箱由我们控制,即我们可以确定我们感兴趣的置信区间的水平,我们还可以选择特定的机器(即估计器)。绿框是确定性的,即“C”是被称为“1-α”水平置信区间的和,θ是未知参数。
该图总结了我们在前面几节中讨论的内容:我们观察了一些数据(随机的),基于这些数据,我们计算了给定水平(α)的置信区间,这导致了 1-α置信区间,这是一个实现,因此不是概率性的。而且参数还有一个未知的确定性真值,要么位于‘C’中,要么不在(就像数字 2 要么位于区间[3,4]中,要么不在)。最后,当我们说[a,b]是 1-α置信水平时,“1-α”是估计过程中的一个标签,并不针对包含真实参数θ的任何概率陈述。本质上,上述机器消耗数据(和α)并吐出一个区间‘C’,我们称之为完全确定的 1-α置信水平。
一个可能萦绕在你脑海中的大问题是,我们如何确保真正的参数在不知道其实际值的情况下被限制在区间“C”内?这看起来很神奇(至少对我来说是这样),但它是基于一个对所有统计学都很重要的非常强大的定理的想法:中心极限定理(下一节将详细介绍)。我省略了置信区间的估计,因为它值得单独讨论。
模拟
在本节中,我们来看一个使用类似于掩模数据的示例的模拟。假设我们调查了一群美国人(不管他们是否戴口罩),观察到了以下反应:X₁,X₂,…,Xn,where
这是一个指示变量,表示一个人是否戴着面具(1)或(0),概率为 p 。此外,假设这些都是同分布的,这意味着 xᵢ~·伯恩(p)是伯努利随机变量。类似于前面的讨论,真实的比例 p 是未知的。估算 p 的一个方法是取我们数据的平均值,即:
这似乎是一个自然的估计:我们计算样本中戴口罩的人的比例。如前所述,这个估计值是可变的,因为如果数据改变,p_hat 也会改变。从数量上来说,大数定律和中心极限定理告诉我们以下内容,
假设某些假设得到满足,这两个定律一起谈论收敛到真实参数值以及收敛到真实参数过程中的分布(假设 n 足够大)。所以,我们可以确定我们的估计收敛于真实值。现在,我们来关注一下置信区间。顺便说一下,我们可以观察到,与我们的估计相关的可变性是 p(1-p)/n,随着我们从越来越多的人那里收集响应,这个可变性变为零。
在这个练习中,让我们关注 95%的置信区间。利用上面的等式,我们可以这样写,
这给了我们一种方法来包含真正的参数 p,
这里,“qₓ”是分位数函数,等于 ~ 1.96。最后一步是根据我们希望“C”包含真实参数的概率至少为 1-α这一事实。使用这个值,我们得到,
还有一个小问题:这个练习的要点是估计未知的 p,但是我们的 C 表达式包含 p。有几种方法可以继续,但为了保持本文简洁,让我们从一个简单的保守界限开始,即区间的最大宽度。这发生在 p = 0.5 时。因此,我们得出
我们现在将使用这个最终表达式进行模拟。对于下面的模拟,我假设 n = 1000,这在调查人的情况下是合理的。
从左到右:描绘当实验次数从 30 到 300 到 3000 增加时,包含真参数 p 的置信区间的比例收敛的图。这直接来自大数定律
从左到右:描绘基于反复做实验计算的置信区间的图(30,300,3000)。虚线代表真实比例,在这些模拟中假设 p=0.6
我们可以观察到,随着实验次数的增加(这是我们反复做实验的另一种说法),包含真参数的置信区间的比例收敛到水平 1-α(这里α=0.05)。我们还可以看到,对于少数实验,只有一个置信区间不包含真实参数,这似乎与我们在此分析中使用的 0.95 水平相反。但是,我们需要记住,我们在最左边的图中看到的 30 个置信区间是 30 个实现,它们是从具有一些可变性的置信区间的基本分布中提取的。如果你尝试对相同数量的实验重新运行模拟,这就是为什么它每次都吐出不同的结果。这也正是为什么我们说,一旦我们使用观测数据估计置信区间,它就不再是概率性的。现在,我们估计的置信区间可能不包含真实参数(例如,如果我们从最左侧的图中选择了 1 红色置信区间),但这正是我们在本节开始时的分析所涵盖的内容。虽然我们还没有完全排除这种可能性,但我们做出的是极不可能像任何概率分析那样。
你可以在这里找到用于这些模拟的脚本。
资源
这本书是给想快速学习概率统计的人看的。它汇集了许多主要观点…
link.springer.com](https://link.springer.com/book/10.1007/978-0-387-21736-9) [## 置信区间
这篇文章需要统计学专家的关注。具体问题是:许多回复和修复表明…
en.wikipedia.org](https://en.wikipedia.org/wiki/Confidence_interval)
Python 中差分时间序列的直观指南
了解时间序列差异的原因、内容和方式!
在处理时间序列时,你迟早会遇到差异这个术语。在这篇文章中,我将尽我所能提供一个简单和容易的数学理论介绍。然后,我还将展示在 Python 中可以遵循的两种不同方法。我们开始吧。
理论
在我真正解释什么是差异之前,我需要快速介绍另一个在处理时序数据时至关重要的概念——平稳性。有很多很棒的文章深入探讨了什么是平稳性,包括弱变量和强变量之间的区别等等。然而,为了这篇文章,我们将集中讨论一个非常基本的定义。
这都是因为时间序列数据不同于处理回归问题时可能遇到的其他类型的数据,例如,预测波士顿地区的房价。这是因为时间序列以时间结构为特征,这实际上意味着数据点的顺序确实很重要。
举一些例子,时间序列数据可以显示趋势(增加和/或减少的模式,例如,在一些商品的生产或销售中)或季节性(当一些时间段显示不同的模式时,例如,在夏季的几个月中与旅游相关的收入增加)。从统计学的角度来看,趋势意味着随时间变化的平均值,而季节性意味着变化的方差。在这样的情况下,我们处理的是非平稳系列。
因此平稳序列基本上是一个具有稳定/恒定统计特性(均值、方差等)的时间序列。)久而久之。或者换句话说,这种时间序列中的观测值不依赖于时间。我们为什么关心这个?简单地说,处理这样的序列并做出准确的预测要容易得多。时间序列建模的一些方法或者假设或者要求基本的时间序列是平稳的。
我将在另一篇文章中省略平稳性测试的细节(例如,用扩展的 Dickey-Fuller 测试),直接回到主题——差异。差分是处理非平稳数据的可能方法之一,它用于试图使这样的序列平稳。实际上,这意味着将后续观测值相互相减,公式如下:
diff(t) = x(t) — x(t — 1)
其中diff
是时间 t 的差分序列,x
代表原始序列的观测值。这种转换非常简单,但是我将在下面的实际例子中说明一些细微的差别。
Python 中的示例
设置
和往常一样,第一步是导入所需的库。
数据
对于这个简短的例子,我们将使用一个非常著名的航班乘客数据集(该数据集可以在我的 GitHub 上获得)。如果你上过关于时间序列的课程或读过这方面的书,你很可能会立刻意识到其中的情节。
我相信这是一个很好的地方来提及,在实践中,你很少会遇到这样一个清晰的时间序列与一个明显的模式。每个人都用这个作为例子,这不是巧合;)
标准差分
在 Python 中应用差异最简单的方法是使用pd.DataFrame
的diff
方法。使用periods
参数的默认值会产生一个差分序列,如上式所述。
如果我们有一个具有明显季节性模式的时间序列(比如夏季乘客数量的增加),我们可以应用diff
方法,并将periods
参数指定为我们想要差异的周期数。所以在这种情况下,使用periods = 12
会导致以下情况:
diff(t) = x(t) — x(t — 12)
季节变化不需要在一年的尺度上发生,事实上,它通常可以被定义为任何固定时期内的重复模式。
为了清楚地说明如何使用diff
方法,您可以运行下面的代码片段并检查输出。
递归差分
我们已经看到了pandas
对diff
的较量。numpy
的有点不同,因为它实现了递归差分。当处理递归差分时,执行差分的次数被称为差分顺序。让我们从一个将差序为 2 的变换应用于同一数据集的示例开始。这意味着我们首先应用常规差分(如上面的pandas
案例),然后对已经差分的序列再次应用变换。因此递归部分。看了结果表之后,逻辑就清晰可见了。
我们将一些NaN
值附加到差分序列的前面,以确保它们与原始序列的长度相同。
在表格中,我们可以看到diff_o1
(其中 o 代表顺序)与diff_1
相同。但是,我们可以清楚地看到diff_2
和diff_o2
的区别。
那么我们什么时候应该使用递归差分法呢?当我们有一个非平稳序列时,它就派上用场了,应用差分使序列平稳,它仍然是非平稳的。然后,我们可以使用 2 阶差分(也可能更多,尽管超过 2 阶并不常见)。这就是 ARIMA 模型中的情况,其中 I 代表积分,实际上对应于对序列求差分以获得平稳性。
结论
在本文中,我介绍了时间序列差异的概念,并解释了这种方法的两种变体之间的差异。但是这篇文章只是触及了时间序列分析、平稳性和处理非平稳数据的表面。希望我能在以后的文章中涵盖一些更实用的技巧。
您可以在我的 GitHub 上找到本文使用的代码。一如既往,我们欢迎任何建设性的反馈。你可以在推特上或者评论里联系我。
2020 年初,我出版了一本关于使用 Python 解决金融领域实际任务的书。在这本书里,我更全面地介绍了时间序列分析和预测,包括测试平稳性和处理非平稳数据的各种方法。如果你有兴趣,我贴了一篇文章介绍这本书的内容。你可以在亚马逊或者 Packt 的网站上买到这本书。
参考
- https://numpy . org/doc/stable/reference/generated/numpy . diff . html
- https://pandas . pydata . org/pandas-docs/stable/reference/API/pandas。DataFrame.diff.html
期望最大化算法的直观指南
艾米丽·莫特在 Unsplash 上的照片
使用 EM 算法对阶跃函数建模
期望值最大化算法是一种估计未观察变量的流行技术,也是工具箱中一个非常强大的工具。过去我曾多次尝试研究这种算法,但概念似乎太抽象,无法想象我可以使用这种算法的实际应用。此外,我发现的例子(可能)太局限于特定领域,不具有相关性。就像爱因斯坦说的,我们应该让一切尽可能简单,而不是更简单。我写这篇文章的目的是想出一个直观的例子来展示 EM 算法的威力。
我将在本指南中使用的示例显然可以使用其他(更简单的)技术来建模,但这里的目标仍然是使用这个相当简单的问题来演示 em 算法的基本概念。事不宜迟,问题来了:如何建模一个阶跃函数(图 1)?
图 1:使用正态分布在 y=2 和 y=3 附近生成的点,方差为 0.03
如果我们使用非线性模型来估计我们的函数,这个问题的答案是微不足道的。但是,为了理解 EM 算法的工作原理,现在让我们坚持使用线性模型。
这个想法很简单,如果这不是一个阶跃函数,我们可以简单地使用一个线性回归模型。此外,如果我们以某种方式知道跳跃点,我们可以在我们的特征空间中添加一个虚拟变量(时间序列分析中使用的一种流行技术),问题就已经解决了。让我们尝试使用线性模型来回答这个问题,并可能获得对 EM 算法的赞赏。我认为,理解所涉及的不同组成部分的数学知识可以有助于更深入地理解所涉及的思想,并将它们转移到其他问题上。所以,这将是一个相当数学化的指南。但是,我保证让事情尽可能简单,但不会更简单。
让我们从介绍我们的训练集 Z 的符号开始,
为了使用线性模型来模拟阶跃函数,我们需要两条平坦的线,并让这两条线,
其中 ϵ 为带参数的高斯噪声( μ,σ ),而 α,β 为常数(我们将尝试估计)。此外,请注意,我们对两条线使用了相同的噪声,因为我们可以假设数据产生过程是相同的。
为了完成对数据模型的描述,我们需要一个指示变量(δ),这样我们的完整模型如下:
这个想法是,当δ= 0 时,第一行被激活,当δ= 1 时,第二行被激活(你也可以把指示变量想象成一个开关)。这给了我们想要的效果:在跳跃之前 h1(x)是我们的数据模型,在跳跃之后 h2(x );指示器变量在跳跃时激活。这里的挑战是,我们没有关于指标变量的信息,或者换句话说,这是我们收集数据时没有观察到的。
本质上,我们是在说我们对指标变量不确定。那么,我们该怎么办?有印象吗,还是我们被困住了?如果你认为不是,那你就对了。让我们用概率的思想来进一步发展我们的数据模型。我们可以引入指标变量的概率分布来模拟这种不确定性。设δ为伯努利随机变量,其中δ= { 0,1},P(δ= 1)=θ。基于指示变量的这种分布(这可以被认为是给我们的数据增加了另一个潜在特征),我们可以得到下面的表达式(使用条件概率),
上面的表达式表明,我们对一个数据点(来自我们的数据)的信念可以根据我们对指标变量的信念分成两部分。这个想法是将我们对指标变量的不确定性纳入我们的模型 h(x)的关键。如果你在这一点上感到有点迷茫,请记住,一个简单的回归模型也旨在估计 P(Y |Z),即 Y 的概率,假设我们观察了我们的数据。所以,我们正在尝试做类似的事情。再坚持一会儿,你就会看到奇迹。
设 Y 表示模型 h(x),的输出,那么我们可以将 Y 的密度函数写成:
其中ϕ_{θ_{1}} ~n(α,σ^{2})和ϕ_{θ_{1}} ~n(β,σ^{2}).这就完成了我们对该数据模型的数学描述,剩下的就是确定模型参数θ=(α,β,θ )。
我们可以使用标准的最大似然估计技术来估计参数值。对数似然函数可以写成如下形式,
为了使我的工作简单一点,我跳过了上面等式中的一个步骤(产品的对数也可以写成对数的总和)。注意,由于对数项的总和,很难使上述等式最大化。这就是 E-M 算法的闪光点。通过对未观察到的(/潜在/缺失)变量(在我们的例子中是指标变量)进行假设,该算法可用于简化这一过程。
我想在这里稍作停顿,在我们正在努力解决的当前问题的背景下更多地谈论这一点。正如我前面提到的,如果我们在我们的特征空间中显式地添加一个虚拟变量,问题就会变得微不足道。然而,实际上在识别跳跃点方面可能存在挑战。因此,我们可以认为虚拟变量在我们的数据集中缺失,并从这个角度应用 E-M 算法。这是 EM 算法的妙处:假设关于一些缺失的(/未观察到的)数据的知识大大简化了问题。
让我们假设我们知道每个数据点的指标变量的值,那么对数似然函数就变成,
其中最后一行来自指示符变量的定义。注意,对于δI = 0,第一项非零,而第二项为零。
使用模型输出的密度函数,我们可以简化表达式,
我们现在可以通过对参数θ求微分来最大化对数似然(MLE)。重要的是,在这里花一点时间,思考如何纳入指标变量的不确定性简化了我们的估计问题。可以发现这些参数是,
换句话说,线参数的估计只是特定线处于活动状态的区域中值的平均值(类似于简单的回归模型),噪声的方差是我们预测中的方差,指示变量的概率分布是δI = 1 的点的比例,这正是我们直觉上要做的。
让我们再次暂停一下,回顾一下我们到目前为止所做的工作。我们试图建立一个阶跃函数模型。为此,我们定义了两条直线 h1(x)和 h2(x ),以及一个指示变量,用于在二维空间的不同区域激活这些直线。由于我们没有关于跳跃的信息,我们使用参数为θ的伯努利随机变量进行建模。这使我们能够完成对模型的描述。为了估计我们模型的参数,我们使用了极大似然估计。并且,为了简化我们的对数似然表达式,我们使用了 EM 算法中关于缺失(/未观测)变量的思想。因此,假设我们以某种方式知道每个数据点的指标变量值,我们通过最大化数据的对数似然来找到参数估计。
现在,让我们放松我们之前的假设关于指示变量(或跳跃)的知识。这就是 EM 算法帮助我们的地方。我们在这里能做的最好的事情就是用它的期望值替换每个指标值。该期望值定义如下,称为责任,
这被称为模型 2 的责任(因为当δI = 1 时 h2(x)有效)用于观察 i 。使用 E-M 算法,以迭代的方式计算这些责任。
在第一步中,我们计算指标值(或我们的缺失/未观察变量)的期望值,也称为责任,在第二步中,我们使用最大化对数似然的导出表达式来计算参数估计值。该算法总结如下,
期待-步骤:
最大化步骤:
简单来说,EM 算法所做的就是通过一个平均值(期望)解决关于指标变量的假设,然后解决原问题(最大化)。这是以迭代的方式进行的,并且算法收敛到正确的答案。
这就完成了问题的数学建模。为了测试这些想法,我用 Python 编写了算法程序(你可以在下面找到代码)。模拟数据集(50 个点)的建模结果如下所示。
点是从均值为 y=2、y=3、方差为 0.01(左)和方差为 0.05(右)的正态分布中生成的
正如我们所看到的,即使方差增加,EM 算法看起来也相当稳健。
代码:https://github . com/sahilgupta 2105/machine _ learning/blob/master/step _ function _ em . ipynb
我在这里讨论的大部分观点都是改编自一本叫做《统计学习的要素》的书。
信息压缩直观指南
信息:概率的负倒数值。
瓶颈(自行点击图片)
维数灾难指的是在高维空间中分析和组织数据时出现的各种现象,这些现象在低维环境中不会出现,例如日常经验的三维物理空间。因此,支持结果所需的数据量通常随着维数呈指数增长,而这并不总是可行的。此外,在处理更多的输入维度时也存在计算障碍。
Claude Shannon 的噪声信道编码定理表明,虽然从信源到接收机的信息传输过程中可能会添加噪声,并且对于通信信道的任何给定程度的噪声污染,都有可能通过信道以可计算的最大速率几乎无差错地传输离散数据。
来源:维基媒体
这激发了对基于编码器和解码器架构的更密集的低维输入表示的需求。其中除了解码器能够很好地有效估计消息之外,编码应该尽可能高效。有各种各样的降维技术和压缩方法可以找到解决方法。在这篇文章中,我将尝试给出一些这样的突出思想的直观概述。
信息瓶颈法
这种压缩方法的一个有趣的原理是来自信息论的信息瓶颈方法。如论文中所述的信息瓶颈方法
理解信号 X 不仅需要预测 y,还需要指定 X 的哪些特征在预测中起作用。我们将问题形式化为寻找 X 的一个短码,该短码保留关于 Y 的最大信息。也就是说,我们通过有限的码字集 X \'形成的“瓶颈”挤压 X 提供的关于 Y 的信息。
x 中关于 Y 的信息量由下式给出
我们可以通过最小化损失来找到最佳瓶颈表示 x
β是用于改变压缩分辨率的拉格朗日乘数。这直观地意味着瓶颈表示应该编码更多关于目标变量的信息和更少的自变量。这为我们提供了信息压缩的理想目标。
主成分分析
PCA 是一种正交线性变换,它将数据变换到超椭球形式的新坐标系中,使得数据的最大方差点位于第一主分量轴上,第二大方差点位于第二坐标上,依此类推。如何将这一想法进一步用于降维,我们移除解释最小方差的轴。
这是通过计算数据的协方差矩阵,找出协方差矩阵的特征向量和特征值,然后最终按照特征值的降序排列特征向量来实现的。这些特征向量被称为主分量。
PCA 用于一般的降维,也用于将多维点投影到更小的维度以便可视化。
来源:维基媒体
奇异值分解
这种思想可以用在许多应用中,其中很少是在推荐系统中,提取单词嵌入,执行 PCA,计算伪逆,伪逆大量用于找出封闭解,如在线性回归和一般矩阵分解的情况下。它是特征分解的推广,要求矩阵是正方形的,但这里也可以是矩形的。
其中 M 是分解成潜在矩阵 U 和 V的矩阵,也称为左右奇异矩阵,σ等于 M 的奇异值。MM 的特征向量构成 V 的列,MM的特征向量构成 U 的列,其中对应于矩阵的转置。奇异值是 MM 或 MM的特征值的平方根。
来源:维基媒体
自动编码器
自动编码器是最流行的信息压缩工具之一,它被扩展用于各种任务,例如嵌入学习、图像处理、维数减少和异常检测。
自动编码器的目的是学习编码,然后从简化的编码中重建尽可能接近其原始输入的表示。为了迫使自动编码器学习更鲁棒的表示,使用了正则化版本。
稀疏自动编码器不一定需要较少数量的隐藏单元,而是只允许少量的隐藏单元同时活动。为了在隐藏单元的激活中实现稀疏性,由某个参数缩放的激活的 L1 或 L2 正则化被添加到损失函数中。
去噪自动编码器采用部分受损的输入,并被训练以恢复原始的未失真输入,从而去除分离噪声。
收缩自动编码器试图实现类似于稀疏编码器的东西,不同之处在于它试图压缩编码器激活的雅可比矩阵相对于由某个参数缩放的输入的 Frobenius 范数。
来源:维基媒体
卷积神经网络
从自然语言处理到计算机视觉,卷积神经网络组件找到了自己的位置。1x1 卷积、卷积 1D、卷积 2D 与池结合为我们提供了有效的压缩技术。它们主要用于计算机视觉任务,这表明它在处理如此高输入维度空间方面的有效性。
在完全连接的神经网络中,每个神经元接收来自前一层的每个元素的输入。在卷积层中,神经元仅接收来自前一层的受限子区域的输入,该子区域称为感受野。在卷积层中,与全连接层相比,接收区域小于整个前一层。这些网络提供了各种优势,例如本地连接和参数共享。因此,它使我们能够有效地工作与压缩低维表示的图像。
来源:维基媒体
t-SNE
这是一种非线性降维技术,将数据嵌入二维或三维的低维空间,主要用于可视化目的。
t-SNE 计算高维空间和低维空间中的实例对之间的相似性度量,然后使用使用梯度下降优化的 KL 散度最小化这些相似性在更高和更低维空间中的差异。
代码输出
结论
“我喜欢密度,不喜欢体积。”
—莫林·霍华德
kNN 及其实现的直观指南
一个载体被它所保持的公司所知
图片来源:Unsplash(照片由乔恩·泰森拍摄)
kNN 是最简单的分类算法之一,因此仍然是社区的“宠儿”之一。有不少关于流行的机器学习算法的调查,kNN 很少能被排除在前 10 名之外。你可以在 KNN 查看我们的视频这里和我们的代码这里。
我们首先来看直觉。在任何班级,当有多个学科的学生参加时,都有同一个学科的学生坐在一起的倾向。kNN 利用了这个想法。
让我们从一个例子开始,来理解它是如何工作的。
图 1:KNN 插图(来源:作者)
有三种鸟。任务是找到问号标记的新鸟的类型(类)。
我们观察它的三个最近的邻居(被圈起来的),观察到大多数邻居是鸭子(3 个中的 2 个),并且断定这个未标记的观察结果是鸭子。在这个例子中,我们已经查看了三个最近的邻居,因此 k 的值被取为 3。
物以类聚
图片来源:Unsplash Photo byFungai Tichawangana
因此,有两个设计决策需要考虑:
- 需要考虑多少邻居?
如果我们保持一个小值,它将识别局部模式,在某些情况下也可能拾取噪声。一个很高的 k 值,它会看全局格局。在最坏的情况下,它的行为类似于朴素贝叶斯的先验概率。无论数据位于何处,它都会将其分配给多数类。
- 将使用哪种距离度量?
可以是欧几里德、曼哈顿、汉明距离、余弦相似度的倒数等。有兴趣的读者可以看看参考文献 1,一本只讲距离度量的书。
实施:
下面的代码足以导入和实例化分类器。
from sklearn.neighbors import KNeighborsClassifier
*#Initalize the classifier*
knn = KNeighborsClassifier(n_neighbors=15)
scikit 中 kNN 的重要参数有哪些?
- n_neighbors: 与‘k’含义相同,默认值为 5
- 权重:可能的值有均匀和距离。默认情况下,这是统一的,当您使用距离时,所有邻居都有相同的投票权重,这意味着较近的邻居比较远的邻居有更多的权重。
- 算法:最好的选择是使用“自动”,在这一步中计算距离矩阵,这是 kNN 中计算量最大的部分。
- p :如果 p =2,则为欧几里德距离,如果 1,则为曼哈顿距离,这适用于度量为 明可夫斯基的情况。 方程给出了两个 p 维向量 x1 和 x2。
闵可夫斯基距离(来源:作者)
- metric: 默认为 Minkowski, 基于两个向量的数据类型有很多选项,下表列出了其中一些。
图 2:基于数据类型的不同距离度量(来源:作者)
还有一个选项来创建您自己的距离度量,但那是一个单独的故事。
如何确定‘k’的最优值?
最简单的解决方案是采用不同的“k”值并运行算法,检查测试集的准确性,当我们看到饱和时,我们可以停止。
**# Initialize an array with diffrent choices of 'k'**
nc=np.arange(1,100,2)
#**Creating an array to store the accuracy values**
acc=np.empty(50)
i=0
for k in np.nditer(nc):
**#Initializing kNN with diffrent values of K** knn = KNeighborsClassifier(n_neighbors=int(k))
knn.fit(x_train, y_train)
**#Finding the testing set accuracy **
acc[i]== knn.score(x_test, y_test)
i = i + 1
接下来,绘制不同“k”值的精确度
x=pd.Series(acc,index=nc)
x.plot()
*# Add title and axis names*
plt.title('Neighbor vs Accuracy')
plt.xlabel('Count of Neighbor')
plt.ylabel('Accuracy')
plt.show()
图 3:确定“k”的最佳值(来源:作者)
我们可以停在一个很小的“k”值上,如图 3 所示,可能在 6,7 左右。
为什么基于距离的算法需要缩放?
让我们再举一个例子。假设,我们有三个客户的数据,我们有两个属性年龄和工资。三个向量,每个向量都是二维的。我们必须确定谁是 C1 最近的邻居。
图 4:缩放的需要(图片来源:作者)
如果我们计算一下,我们会发现两者的距离都是 1,因此它们是等距离的。然而,薪水的 1 Rs 的变化和年龄的 1 Rs 的变化是不等价的,并且由于薪水的范围与年龄相比会相当高,所以在欧几里德距离计算中,它会窒息或支配年龄。
使它们达到相同范围的一种标准技术称为归一化或最小-最大缩放,由等式 2 给出
等式 2:标准化
下面附上一张虚构的有年龄的插图
图 5:最小-最大缩放的图示(来源:作者)
因此,所有值都映射在 0 到 1 之间,最小值映射到 0,最大值映射到 1。
**# Impoting minmaxscaler**
from sklearn.preprocessing import MinMaxScaler
**#Initilization**
scaler = MinMaxScaler(feature_range=(0, 1))
**#Transforming the value**
x_scaled = scaler.fit_transform(x)
关键备注:
- kNN 是一个非常简单的算法,并且没有对数据分布做任何假设,因此被称为非参数。
- 确定“k”并不容易。
- 随着维度数量的增加,许多距离度量都不再适用。
- 最后,邻域矩阵的计算非常昂贵。
- 可以将简单地扩展到回归,其中目标变量的值将是其 k 个最近邻居的平均值。
- 它还能容忍输入数据的变化,因为它只在被要求分类时才开始计算。它通常被称为懒惰的学习者。
参考:
[1]德扎 MM,德扎 e .距离百科。《距离百科全书 2009》(第 1-583 页)。斯普林格,柏林,海德堡。
[2]https://towards data science . com/KNN-k-nearest-neighbors-1-a 4707 b 24 BD 1d
LSTMs 直观指南
从零开始创造它们
布伦特·德·兰特在 Unsplash 上拍摄的照片
LSTMs 是机器学习中最重要的突破之一;赋予机器学习算法回忆过去信息的能力,允许实现时间模式。理解一个概念比从头开始创造一个概念更好吗?
什么是 LSTMs?
宽泛:
LSTM 代表长期短期记忆,表示其利用过去信息进行预测的能力。LSTM 背后的机制非常简单。LSTMs 具有来自不同时间步长的不同处理信息源作为网络的输入,而不是用于数据传播的单一前馈过程,因此能够访问数据内与时间相关的模式。
LSTM 架构不仅仅由一个神经网络组成,而是由至少三个同时训练的神经网络组成的电池。此外,LSTM 体系结构还包含一些门,这些门为神经网络的最终预测赋予某些数据更高的权重。
详细信息:
以下是 LSTM 传播一条输入数据所采取的步骤的详细列表:
- 输入数据提供给三个不同的神经网络,即遗忘网络、选择网络和细胞状态网络
- 输入数据通过这些神经网络传播,给出输出
- 适当的激活函数用于每个输出,以防止消失或爆炸梯度。
- 对于遗忘门,数据然后与从上一时间步收集的可能性交叉相乘
- 将为收集的可能性交叉相乘的值存储为收集的可能性
- 将该值乘以选择神经网络的预测,以给出 LSTM 的预测
这是一个复杂的过程,但理解每一步是至关重要的,以便正确地应用导数。
代码:
现在,您已经很好地理解了 LSTM 应该如何工作(理论上),我们可以继续实际的程序。
代码:
第一步|设置:
import numpy
from matplotlib import pyplot as plt
def sigmoid(x):
return 1/(1+np.exp(-x))def sigmoid_p(x):
return sigmoid(x)*(1 -sigmoid(x))def relu(x):
return np.maximum(x, 0)def relu_p(x):
return np.heaviside(x, 0)def tanh(x):
return np.tanh(x)def tanh_p(x):
return 1.0 - np.tanh(x)**2def deriv_func(z,function):
if function == sigmoid:
return sigmoid_p(z)
elif function == relu:
return relu_p(z)
elif function == tanh:
return tanh_p(z)
在这段代码中,我安装了程序的唯一依赖项,Numpy 用于矩阵乘法和数组操作,不同的激活函数和它们的导数用于神经网络的灵活性
第二步| LSTM 框架:
class LSTM:
def __init__(self,network):
def plus_gate(x,y):
return np.array(x) + np.array(y)
def multiply_gate(x,y):
return np.array(x) * np.array(y)
class NeuralNetwork:
def __init__(self,network):
self.weights = []
self.activations = []
for layer in network:
input_size = layer[0]
output_size = layer[1]
activation = layer[2]
index = network.index(layer)
if layer[3] == 'RNN':
increment = network[-1][1]
else:
increment = 0
self.weights.append(np.random.randn(input_size+increment,output_size))
self.activations.append(activation)
在这一部分,我初始化了 LSTM 类,并定义了其中的关键组件。两个门和神经网络组件的框架。
第三步|神经网络功能:
def propagate(self,data):
input_data = data
Zs = []
As = []
for i in range(len(self.weights)):
z = np.dot(input_data,self.weights[i])
if self.activations[i]:
a = self.activations[i](z)
else:
a = z
As.append(a)
Zs.append(z)
input_data = a
return As,Zs
def network_train(self, As,Zs,learning_rate,input_data,extended_gradient):
As.insert(0,input_data)
g_wm = [0] * len(self.weights)
for z in range(len(g_wm)):
a_1 = As[z].T
pre_req = extended_gradient
z_index = 0
weight_index = 0for i in range(0,z*-1 + len(network)):
if i % 2 == 0:
z_index -= 1
if self.activations[z]:
pre_req = pre_req * deriv_func(Zs[z_index],self.activations[z])
else:
pre_req = pre_req * Zs[z_index]
else:
weight_index -= 1
pre_req = np.dot(pre_req,self.weights[weight_index].T)
a_1 = np.reshape(a_1,(a_1.shape[0],1))
pre_req = np.reshape(pre_req,(pre_req.shape[0],1))
pre_req = np.dot(a_1,pre_req.T)
g_wm[z] = pre_req
for i in range(len(self.weights)):
self.weights[i] += g_wm[i]*learning_rate
该部分包含网络的定义,以传播数据并计算每个相应权重的梯度,能够引入外部梯度以将权重直接链接到损失函数。
步骤 4|创建组件:
self.plus_gate = plus_gate
self.multiply_gate = multiply_gate
self.recurrent_nn = NeuralNetwork(network)
self.forget_nn = NeuralNetwork(network)
self.select_nn = NeuralNetwork(network)
有了这个框架,我只需要创建 LSTM 运行所需的每个组件。
步骤 5|定义结构:
def cell_state(self,input_data,memo,select):
global rnn_As,rnn_Zs
rnn_As,rnn_Zs = lstm.recurrent_nn.propagate(input_data)
yhat_plus = tanh(rnn_As[-1])
plus = self.plus_gate(yhat_plus,memo)
collect_poss = plus
yhat_mult = tanh(plus)
mult = self.multiply_gate(yhat_mult,select)
pred = mult
return pred,collect_poss
def forget_gate(self,input_data,colposs):
global forget_As,forget_Zs
forget_As,forget_Zs = lstm.forget_nn.propagate(input_data)
yhat_mult = sigmoid(forget_As[-1])
mult = self.multiply_gate(colposs,yhat_mult)
memo = mult
return memodef select_gate(self,input_data):
global select_As,select_Zs
select_As,select_Zs = lstm.select_nn.propagate(input_data)
yhat_mult = sigmoid(select_As[-1])
select = yhat_mult
return select
在上面的部分中,我定义了网络的三个主要架构元素,添加了全局变量以便于在培训期间访问。
步骤 6|定义传播:
def propagate(self,X,network):
colposs = 1
As = []
for i in range(len(X)):
input_data = X[i]
if i == 0:
increment = network[-1][1]
input_data = list(input_data) + [0 for _ in range(increment)]
else:
input_data = list(input_data) + list(pred)
input_data = np.array(input_data)
memory = self.forget_gate(input_data,colposs)
select = self.select_gate(input_data)
pred,colposs = self.cell_state(input_data,memory,select)
As.append(pred)
return As
现在,它就像浏览图表并按正确的顺序排列组件一样简单。比较图表和代码:这会让你更好地理解 LSTMs 是如何工作的。
第七步|训练:
def train(self,X,y,network,iterations,learning_rate):
colposs = 1
loss_record = []
for _ in range(iterations):
for i in range(len(X)):
input_data = X[i]
if i == 0:
increment = network[-1][1]
input_data = list(input_data) + [0 for _ in range(increment)]
else:
input_data = list(input_data) + list(pred)
input_data = np.array(input_data)
memory = self.forget_gate(input_data,colposs)
select = self.select_gate(input_data)
pred,colposs = self.cell_state(input_data,memory,select)loss = sum(np.square(y[i]-pred).flatten())gloss_pred = (y[i]-pred)*2
gpred_gcolposs = selectgpred_select = colposs
gloss_select = gloss_pred * gpred_selectgpred_forget = select*sigmoid_p(colposs)*colposs
gloss_forget = gloss_pred * gpred_forgetgpred_rnn = select*sigmoid_p(colposs)
gloss_rnn = gloss_pred*gpred_rnnself.recurrent_nn.network_train(rnn_As,rnn_Zs,learning_rate,input_data,gloss_rnn)
self.forget_nn.network_train(forget_As,forget_Zs,learning_rate,input_data,gloss_forget)
self.select_nn.network_train(select_As,select_Zs,learning_rate,input_data,gloss_select)
As = self.propagate(X,network)
loss = sum(np.square(y[i]-pred))
loss_record.append(loss)
return loss_record
继续前进!我已经检查了 96%的代码。解释每一个导数要花很长时间,所以我简单解释一下。画一条从最终预测到你想要计算偏导数的项的路径,把所有垂直于路径的项加到方程中。逐元素相乘。使用这些作为扩展梯度来训练嵌套神经网络内的权重。
第八步|运行程序:
X = np.array([[0,1,1],[1,1,0],[1,0,1]])
y = np.array([0,1,1])
network = [[3,5,sigmoid,'RNN'],[5,5,sigmoid,'Dense'],[5,1,sigmoid,'Dense']]
lstm = LSTM(network)
loss_record = lstm.train(X,y,network,5000,0.1)
plt.plot(loss_record)
该脚本的最后一段应该使用嵌套神经网络执行程序,以具有在网络变量下定义的架构。您可以在这里更改数字,但要确保矩阵是对齐的。
完整源代码:
import numpy
from matplotlib import pyplot as pltdef sigmoid(x):
return 1/(1+np.exp(-x))def sigmoid_p(x):
return sigmoid(x)*(1 -sigmoid(x))def relu(x):
return np.maximum(x, 0)def relu_p(x):
return np.heaviside(x, 0)def tanh(x):
return np.tanh(x)def tanh_p(x):
return 1.0 - np.tanh(x)**2def deriv_func(z,function):
if function == sigmoid:
return sigmoid_p(z)
elif function == relu:
return relu_p(z)
elif function == tanh:
return tanh_p(z)class LSTM:
def __init__(self,network):
def plus_gate(x,y):
return np.array(x) + np.array(y)
def multiply_gate(x,y):
return np.array(x) * np.array(y)
class NeuralNetwork:
def __init__(self,network):
self.weights = []
self.activations = []
for layer in network:
input_size = layer[0]
output_size = layer[1]
activation = layer[2]
index = network.index(layer)
if layer[3] == 'RNN':
increment = network[-1][1]
else:
increment = 0
self.weights.append(np.random.randn(input_size+increment,output_size))
self.activations.append(activation)def propagate(self,data):
input_data = data
Zs = []
As = []
for i in range(len(self.weights)):
z = np.dot(input_data,self.weights[i])
if self.activations[i]:
a = self.activations[i](z)
else:
a = z
As.append(a)
Zs.append(z)
input_data = a
return As,Zs
def network_train(self, As,Zs,learning_rate,input_data,extended_gradient):
As.insert(0,input_data)
g_wm = [0] * len(self.weights)
for z in range(len(g_wm)):
a_1 = As[z].T
pre_req = extended_gradient
z_index = 0
weight_index = 0for i in range(0,z*-1 + len(network)):
if i % 2 == 0:
z_index -= 1
if self.activations[z]:
pre_req = pre_req * deriv_func(Zs[z_index],self.activations[z])
else:
pre_req = pre_req * Zs[z_index]
else:
weight_index -= 1
pre_req = np.dot(pre_req,self.weights[weight_index].T)
a_1 = np.reshape(a_1,(a_1.shape[0],1))
pre_req = np.reshape(pre_req,(pre_req.shape[0],1))
pre_req = np.dot(a_1,pre_req.T)
g_wm[z] = pre_req
for i in range(len(self.weights)):
self.weights[i] += g_wm[i]*learning_rate
self.plus_gate = plus_gate
self.multiply_gate = multiply_gate
self.recurrent_nn = NeuralNetwork(network)
self.forget_nn = NeuralNetwork(network)
self.select_nn = NeuralNetwork(network)
def cell_state(self,input_data,memo,select):
global rnn_As,rnn_Zs
rnn_As,rnn_Zs = lstm.recurrent_nn.propagate(input_data)
yhat_plus = tanh(rnn_As[-1])
plus = self.plus_gate(yhat_plus,memo)
collect_poss = plus
yhat_mult = tanh(plus)
mult = self.multiply_gate(yhat_mult,select)
pred = mult
return pred,collect_poss
def forget_gate(self,input_data,colposs):
global forget_As,forget_Zs
forget_As,forget_Zs = lstm.forget_nn.propagate(input_data)
yhat_mult = sigmoid(forget_As[-1])
mult = self.multiply_gate(colposs,yhat_mult)
memo = mult
return memodef select_gate(self,input_data):
global select_As,select_Zs
select_As,select_Zs = lstm.select_nn.propagate(input_data)
yhat_mult = sigmoid(select_As[-1])
select = yhat_mult
return select
def propagate(self,X,network):
colposs = 1
As = []
for i in range(len(X)):
input_data = X[i]
if i == 0:
increment = network[-1][1]
input_data = list(input_data) + [0 for _ in range(increment)]
else:
input_data = list(input_data) + list(pred)
input_data = np.array(input_data)
memory = self.forget_gate(input_data,colposs)
select = self.select_gate(input_data)
pred,colposs = self.cell_state(input_data,memory,select)
As.append(pred)
return As
def train(self,X,y,network,iterations,learning_rate):
colposs = 1
loss_record = []
for _ in range(iterations):
for i in range(len(X)):
input_data = X[i]
if i == 0:
increment = network[-1][1]
input_data = list(input_data) + [0 for _ in range(increment)]
else:
input_data = list(input_data) + list(pred)
input_data = np.array(input_data)
memory = self.forget_gate(input_data,colposs)
select = self.select_gate(input_data)
pred,colposs = self.cell_state(input_data,memory,select)loss = sum(np.square(y[i]-pred).flatten())gloss_pred = (y[i]-pred)*2
gpred_gcolposs = selectgpred_select = colposs
gloss_select = gloss_pred * gpred_selectgpred_forget = select*sigmoid_p(colposs)*colposs
gloss_forget = gloss_pred * gpred_forgetgpred_rnn = select*sigmoid_p(colposs)
gloss_rnn = gloss_pred*gpred_rnnself.recurrent_nn.network_train(rnn_As,rnn_Zs,learning_rate,input_data,gloss_rnn)
self.forget_nn.network_train(forget_As,forget_Zs,learning_rate,input_data,gloss_forget)
self.select_nn.network_train(select_As,select_Zs,learning_rate,input_data,gloss_select)
As = self.propagate(X,network)
loss = sum(np.square(y[i]-pred))
loss_record.append(loss)
return loss_record
X = np.array([[0,1,1],[1,1,0],[1,0,1]])
y = np.array([0,1,1])
network = [[3,5,sigmoid,'RNN'],[5,5,sigmoid,'Dense'],[5,1,sigmoid,'Dense']]
lstm = LSTM(network)
loss_record = lstm.train(X,y,network,5000,0.1)
plt.plot(loss_record)
我的链接:
如果你想看更多我的内容,点击这个 链接 。
PCA 直观指南
主成分分析背后的思想
内森·杜姆劳在 Unsplash 上的照片
主成分分析(PCA)是一个非常有用的工具,可以用来获得关于数据集的直觉。它主要用于降维。我最近偶然看到一篇关于 PCA 的教程论文,它通过谈论这个强大概念背后的直觉为我揭开了 PCA 的神秘面纱,并启发我分享我在这个过程中发现的一些事情。这篇文章中的大部分想法都是从原始论文中得到启发的,我很感谢作者写了这篇文章。我将从基础开始构建概念,并以 PCA 在一些真实数据上的应用结束。
降维的需要
人类通过观察事物来学习。最常见的学习技巧之一是进行一项实验,收集一些数据,研究它,并就我们试图研究的现象得出结论。例如,假设我口袋里有一枚硬币,我正试图确定它是否有偏差。为了找到这一点,我多次投掷硬币,从我的实验中收集数据,并利用统计学原理,我可以推断出我的硬币。同样,在更现实的环境中,我们手头有一个数据集,它代表了对现实世界现象的观察,我们的目标是研究它,以深入了解潜在的现象。
让我们假设我们有兴趣了解弹簧是如何工作的。对于那些不熟悉这个的人来说,弹簧的动力学是由虎克定律控制的。我选择这个例子(类似于原始论文)是为了使讨论简单,并梳理出潜在的想法。为了做到这一点,我们将设置一个带有摄像机的实验,并在不同的时间记录弹簧尖端的位置(出于任何原因,我可能强烈怀疑弹簧的位置完全包含了动力学,这就是为什么我首先记录它)。因此,我们在这里收集的数据集将是一个矩阵 X,具有 n 个观察值和 2 个特征(X 和 y 坐标)。假设我们进行了实验并获得了一些观察结果,如图 1(左)。
图 1:(左)从弹簧实验(n=100,p=2)收集的观察结果,(右)旋转坐标框架以揭示弹簧的动力学可以仅被描述为一个方向
在我们的观察中有两件有趣的事情正在发生:a)看起来弹簧尖端在不同时间点的位置几乎沿着相对于 x 轴倾斜的直线(如果你读过胡克定律,你就知道为什么会发生这种情况),b)收集的数据有噪声,例如,由于固定相机的不稳定底座。第一个观察更多的是关于弹簧动力学的启发(我只提到了虎克定律来提供一些背景,应该记住,我们在进行这个实验时对这个定律是无知的,并且试图通过实验发现这个定律)。
尽管我们收集了沿任意选择的 x 轴和 y 轴的观察值,但看起来弹簧的动力学可以在一个方向上描述。例如,我们可以旋转我们的参照系,使所有的点都位于旋转坐标系中的 x '方向(图 1,右)。我们还可以看到,与 x 方向的可变性相比,y 方向的可变性似乎较小,这可能是数据收集过程中的噪声。换句话说,弹簧的动力学可以完全由单一的运动方向(新的 x 轴)来描述,并且在我们的观察中有一些以噪声形式存在的冗余。
总结:数据集可能包含不必要的复杂性,有时可能隐藏简化的结构。需要系统化方法来降低这种复杂性并从我们的数据集中去除冗余。
PCA 的目标
PCA 旨在识别最有意义的参考系(在线性代数中也称为 基 )来重新表达我们的数据集,希望这个新的基将过滤掉噪声并揭示任何隐藏的结构。
在 spring 实验中,我们手动实现了这个目标:观察图显示我们可以旋转坐标轴,y 方向上的微小变化(与 x 方向相比)显示有一些噪声,可以过滤掉。
参照系
让我们继续在春季实验的基础上提出更系统化的降维方法,即 PCA。我们需要引入线性代数中的一些基本概念。我会尽量让讨论简单一些。
一个幼稚的参照系
在春季实验中,我们使用在实验室中任意安装的相机收集我们的观察结果(这类似于真实世界中我们收集某些维度/特征的数据)。基于我们的摄像机的方向,定义了一个隐式坐标框架,即相对于摄像机定义的 x 轴和 y 轴(图 1,左侧)。这叫做幼稚的参照系。
上一段中的关键是单词隐含的,也就是说,如果没有一些关于弹簧如何工作的额外信息,我们不可能找到更好的框架。同样,在现实世界中,我们无法自由控制记录观察结果的维度,所以天真的选择已经为我们做好了。
总结:朴素参照系是数据收集方法的一个属性,它是(隐含地)赋予我们的。
迂回:在我们继续讨论之前,让我们简单地谈谈线性代数中的一个基本概念,叫做基。
基础可以被认为是参考框架的一个构建模块。考虑我们实验中的一个观察结果(0.9,0.85)。该观察可以被视为使用 x 轴向量的某一部分(=0.9)和 y 轴向量的某一部分(=0.85)来构建。
这是一种非常强大的思维方式,因为仅使用坐标轴方向上的两个向量(以及关于乘数(0.9,0.85)的信息),我们就可以描述我们的观察结果。这些乘数的一个稍微专业的术语是投影。比如观察沿 x 轴方向的投影是一个大小为 0.9 的矢量。上式中最右边的等式是这个事实的矩阵表述。
换句话说,我们可以将观察值(0.9,0.85)分解为两个独立部分的组合:x 轴(由向量(1,0)给出)和 y 轴(向量(0,1))。沿着 x 轴和 y 轴的向量一起形成了一个基础。我称它们为构建模块,因为二维平面中的任何向量都可以表示为(或者换句话说,构建为)这两个向量的组合。
让我们以矩阵的形式收集我们的原始参考系的构件。
我们可以对整个数据集的上述讨论简明地描述如下,
这个矩阵方程用朴素基描述了观测向量(x,y)(即数据)(这就像陈述 2 = 2,这就是为什么我们看到恒等矩阵出现在 RHS 中)。LHS 只是以矩阵 X^T 的形式并排堆叠的单个观测向量,而 RHS 是我们之前所说的所有观测向量的简明表述方式。这里我跳过了一个步骤:每个观察值都可以像第一个观察值一样分解,然后最右边的矩阵方程就出来了。
这个等式看起来相当简单,因为矩阵 B 就是单位矩阵。如果我们开始以稍微不同的方式思考这个等式,神奇的事情就会发生:矩阵 X^T 是数据,而最右边的矩阵(与单位矩阵相乘的矩阵)是乘数的集合,它为我们提供了构建数据集的方法。这可能感觉是一种尴尬的思考方式,但是一分钟后就会明白为什么它会如此强大。
更好的参照系
回想一下,作为系统化降维方法(PCA)的第一步,在 spring 实验的推动下,我们试图找到一个更好的参考框架,它可能会简化数据以揭示隐藏的结构(类似于我们如何能够确定 spring 的动力学基本上是一维的)。我将再次通过回顾春季实验来激发讨论。在 spring 实验中确定一个更好的参考框架意味着简单地旋转坐标框架(图 1,从左到右看起来像是所有点围绕原点的旋转)。
图 2:旋转第一个观察值,使其与水平方向对齐,这将作为新的 X 轴 X’。请注意,旋转角度约为 43.5ᵒ(这是将第一次观察与水平方向完全对齐的角度)。
图 2 描述了旋转第一观察的方法。在我们的原始参照系中的观察值是黑色的,旋转后的结果是红色的(沿原始 x 轴和 y 轴的分量是虚线)。沿着旋转后的观察向量的方向可以作为新的 X 轴,X ',类似于图 1 中看到的,对吧。还记得我们在迂回中看到,我们的数据中的任何观察值都可以使用基数和乘数来构建。这就是看矩阵方程的另一种方法派上用场的地方。让我们看看我们是否可以在这里利用这个想法。
用这个角度(43.5ᵒ)旋转朴素基的给定公式为:
我们能利用这种洞察力来计算第一次观测的新位置吗?
是啊!我们已经知道使用向量(1,0)和(0,1)创建第一个观察值的方法:使用乘数 0.9 和 0.85 将它们组合起来。因此,第一次观察的新位置是使用相同的乘数简单地组合变换的基向量,
如果您想知道如何对原始 x 轴和 y 轴的变换向量使用相同的乘数,请查看图 2,注意所有东西都旋转了相同的角度。
这只是一个观察,如果我们有一个简洁的方法来描述所有 100 个观察,不是很好吗?事实证明这是迂回路线的简单延伸,
希望现在您已经看到发生了什么以及为什么会这样:要旋转我们数据集中的任何观察值,我们需要使用观察值的相应乘数来组合上面转换的 x 轴和 y 轴向量。换句话说,p 是一个矩阵,它通过 43.5ᵒ旋转一个向量,并将我们的数据集从原始参照系(图 1,左)带到一个更好的参照系(图 1,右)。
让我们稍微概括一下这个想法。在观察我们的观察图的激励下,我们决定旋转可能是一个很好的转换选择,可以帮助我们找到一个更好的参考框架来研究我们的问题。原来对于这样的变换有很多可用的选择,比如旋转、剪切、 …一个自然的问题是如何挑选最好的?我们将在接下来的部分尝试回答。
图 3:对矩阵 P 的任意选择将原始参考系转换成一个新的参考系(红色)
需要注意的重要一点是,通过改变矩阵 P 中存储的数字,我可以生成新的变换。图 3 显示了一个例子。我生成了一个随机的 2 x 2 矩阵,产生的转换用红色表示。虽然这不是一个直观的选择,但红色向量一起形成了一个基础:任何二维向量都可以使用这些向量的组合来构建。
总结:将大小为 p x p 的矩阵乘以我们的大小为 p x n 的数据矩阵(其中 p 是维数)改变了参照系,或者更正式地可以称为基的改变。
主成分分析
前几节的观点使我们能够对我们的最终目标提出更好更精确的问题,
- 基础有什么好的选择?
- 如何最小化噪音或冗余?
我们将在调查第二个问题的过程中回答第一个问题。我们可以对数据做出的一个合理的 假设 是,与信号相比,测量噪声较低(否则数据噪声太大,无法得出任何有用的结果),换句话说,这与说噪声方差< <信号方差相同。这一假设为我们提供了一种数学求解第二个目标的方法,即我们可以最大化方差来识别信号。回想一下,我们在图 1 的 spring 实验中看到这个假设成立(右图,与 x 方向相比,y 方向的方差非常小)。
假设矩阵 X 是我们有 n 个观测值的数据,每个观测值有 p 个维度。为了最大化数据的方差,我们首先需要计算数据的方差。每个 p 维度代表一个可能的方向,我们的数据可能会沿着这个方向变化,即存在方差。因此,数学上描述数据方差的一种自然方式是协方差矩阵,
前提是数据以平均值为中心。该矩阵的对角元素表示沿每个维度的方差,非对角元素是协方差。注意σ是一个方阵( p x p )并且是对称的:协方差(X,Y) =协方差(Y,X)。
基于我们的目标(以及来自 spring 实验的直觉)的好的协方差矩阵将具有大的对角元素和小的(最好是零)非对角元素。这是因为两个原因,
- 我们假设我们的数据具有低噪声。因此,最大方差方向包含感兴趣的信号。
- 理想的基础是在独立的(/垂直)方向上分解数据,类似于图 1(右),以揭示任何隐藏的结构,这相当于协方差等于零。
这给了我们一个我们正在寻找的模板矩阵,即最好是一个对角矩阵。现在,剩下的就是找到这样一个矩阵。让我们通过一个简单的例子来建立一些直觉。
图 4:并排堆叠的黑色向量代表 2x2 协方差矩阵,当乘以“右”矩阵 P 时,将它们转换为红色向量,即对角矩阵
在图 4 中,我们得到了一个 2 x 2 的协方差矩阵(用黑色向量表示)。从这个例子中我们看到,选择“正确的”矩阵 P 会将协方差矩阵转换为对角矩阵(由红色向量表示)。因此,将给定的矩阵转换成对角矩阵是一个寻找正确的基础(或参照系)的问题。
有许多方法(/潜在基)对角化协方差矩阵,PCA 基于一种简单的方法:假设所有方向(形成基)相互垂直。然后,对角化协方差矩阵将涉及广义旋转(在 2D,这将类似于图 4)。
最后,我们有一个用于主成分分析的算法,
- 在最大方差中选择方向,称之为 d₁
- 接下来,选择方差最大的垂直于 d₁的方向,称之为 d₂
- 依此类推……我们可以计算出构成基础的方向
- 以矩阵的形式收集基,并将其乘以原始数据会导致基的变化
在 spring 实验(图 1)中,该算法会将 d₁识别为沿 x '的方向,将 d₂识别为 y '。得到的一组方向{d₁、d₂……}是主成分,这些成分中每一个的重要性都与这些方向中每一个的数据可变性相关联。最后,我们在改变基础后获得的结果矩阵代表了我们在这些主成分方面的数据(见图 1 右侧和基础改变部分)。
我们上面发现的算法是形成 PCA 的步骤的粗略轮廓。主要步骤(协方差矩阵的对角化)是线性代数中一个研究得很好的问题,有两个主要的分解来做这件事:特征值分解,和 S 奇异值分解。PCA 的实际实现使用这些分解技术中的任何一种。
总结 : PCA 把我们的数据转换成一个新的基,这个基是由相互垂直的方向定义的,叫做主成分,沿着主成分方差最大化,每个方向的重要性都与该方向数据的方差相关联。
例子
我将使用这个数据集作为例子。该数据集包含北京 12 个国控空气质量监测点每小时的空气污染物数据。我将只使用其中一个网站的数据(Data _ 数据 _ 万寿西工 _ 2013 03 01–2017 02 28 . CSV)。各种维度(/特征)是空气中常见污染物的浓度,如 SO₂、NO₂、一氧化碳、O₃、不同大小的颗粒物、环境空气条件,如温度、压力、露点温度(与空气密度密切相关)、风速和一天中的时间。这些尺寸可能是由环境监测中心的专家根据他们的领域知识选择的,并使用传感器进行测量(会有一些测量噪声)。数据集有 32,829 个观察值和 15 个维度。
图 5:PC1-PC2 平面数据集的散点图。(右)沿 PC1 和 PC2 方向投影的尺寸的投影表(/乘数)
图 5 显示了数据集在由两个主要成分 PC1 和 PC2 定义的平面中的散点图。PC1 和 PC2 是两个最重要的主分量,即分别与最大和第二大方差方向相关联。我们的数据集中的每个观察值都是 15 维的,并沿着 PC1 和 PC2 投影,这在图中有精确的描述(图 5)。散点图中的红色箭头表示相对于两个主要成分的原始尺寸。对应于两个主分量的方向向量在右边的表中给出。
我们已经可以从这些方向看到一些有趣的东西。在 PC1 方向,我们看到 PM2.5、PM10、SO₂、NO₂、CO 等污染物与 O₃、温度、露点压力、风速呈负相关。换句话说,随着温度和风速的下降,污染物的浓度增加,这是有道理的,因为在较低的温度下,由于重力的作用,分子倾向于沉降到更靠近地球表面的地方,而较小的风意味着空气分散更少(更高的压力、浓度……)。我们可以看到的另一件有趣的事情是臭氧(O₃)与所有其他污染物的负相关。虽然距离我最后一次遇到化学反应已经有一段时间了,但稍微挖掘一下就会发现,臭氧化学反应的形成取决于周围的空气条件。例如,在较低的温度下,一氧化碳/ NO₂)is 稳定,但在较高的温度下(即阳光),化合物反应形成 O₃ 。实质上,PC1 是在对比环境空气条件和污染物浓度。
PC2 方向在温度、露点温度和压力之间具有大的负相关性,这可能与连接这些变量的基本理想气体定律有关。
我们看到,主成分分析有助于理解和可视化数据集,并为我们提供了一种提取有用信息的系统方法。PCA 并不总是最好的选择,有时还会造成伤害。了解这种技术的局限性是有帮助的,这种局限性是由我们在推导这种技术时所做的一些假设造成的。对于 PCA 的更严格和详细的处理,请查看原始论文,这真的是非常有趣的阅读。
参考
简易决策树的直观指南
用例子和简单的数学解释!
作者图片
概观
我们如何做决定?
定义决策树
它是如何工作的?
我们如何建立一个有效的决策树?
在我们开始之前,我假设您至少在高层次上理解了回归和分类的概念。如果没有,这里快速总结一下:
作者图片
什么是决策树?
- 一种算法,即使用树状结构表示一组问题&决策。
- 它提供了一个过程来决定问什么问题、问哪个问题以及何时问它们以预测结果的价值。
我们如何做决定?
在我们深入细节之前,让我们通过两个非常简单的例子来了解我们是如何做决定的…
左> 根据天空的颜色,我们决定要不要出去玩一个游戏(绝对决定)。 右 >根据一只猫的腰围大小,我们决定对它的体重进行粗略的估计(数值决定)。另一方面,那只猫需要一些真正的帮助节食!
这里有一个更复杂的例子
作者图片
>评估患者感染老年人更易患疾病的风险。以上是一个医生在查看你的个人/健康记录以评估你患病风险时的假设心理模型(尽管是一个简化的模型)
行话时间
和大多数算法一样,我们可能会遇到一些术语。这里有一个直观的表示来帮助我们浏览这些术语…
作者图片
根节点:数据的整个样本或总体
分割:将一个节点分割成两个或更多子节点的过程
决策节点:有其他子节点的子节点。它们有指向它们的箭头和远离它们的箭头。
叶/终端节点:没有子节点的节点(不进一步拆分)。他们有指向他们的箭头,但没有指向远离他们的箭头。
父/子节点:被分成子节点的节点被称为子节点的父节点,而子节点是父节点的子节点。
子树/分支:树的子部分
既然这个问题已经解决了,让我们看看决策树是如何帮助我们预测问题的结果的!
决策树是如何构建的
示例数据集
这个虚拟数据集描述了如何使用患者的年龄以及常见的病毒症状(如呼吸困难和胸痛)来预测一个人是否感染了新冠肺炎病。
将患者数据集映射到决策树
逐步走查
1。整个患者数据集被输入到根节点。
作者图片
2。询问一个关于患者的问题,并根据答案是对还是错对数据集进行分割/分区。
作者图片
3。在每次分割时,该算法试图确保所得分区中的患者尽可能同质(即每个子节点上的所有病毒阳性或病毒阴性)。如果一个子节点没有被很好地分离,将会询问进一步的问题来进一步分割数据集。
作者图片
4。该过程继续进行,直到不再有患者可被分割或满足停止标准。
建立一棵有效的树的关键
为了建立一棵有效的树,有三个重要问题需要回答:
问:我们可以问什么问题?
为了获得问题,我们迭代出现在预测值列的每一行中的每个值。每个值都成为用于将数据划分为不同子集的阈值的潜在候选值:
作者图片
潜在问题:
此人是否超过 60 岁?
此人是否超过 30 岁?
此人是否有呼吸困难?
患者是否有胸痛?
问:我们应该问哪些问题?
最好的问题最能减少不确定性,并导致最纯粹的叶节点。
减少不确定性意味着什么?为了理解这一点,让我们在决策树的叶节点上看下面两个例子:
作者图片
在左侧,每个叶节点包含具有和不具有新冠肺炎的个体的混合物,即不纯。如果我们将左叶节点中的个体分类为阳性,则被正确分类的概率仅为 50% ,因为它仅包含 25/50 的 covid 阳性个体。
在右侧,决策树的每个叶节点是完全同质的(50/50 covid 为正,48/48 covid 为负),即纯。如果我们将左叶节点中的个体分类为阳性,则被正确分类的概率是 100% ,因为它仅包含 covid 阳性的个体。
因此,具有更纯的节点增加了被正确分类的机会,并减少了决策结果的不确定性。
问:如何量化节点中的不确定性/杂质?
有几种方法可以量化杂质,但我们现在只谈两种:
- Gini 杂质 —量化一个节点中有多少杂质(越低越好)
- 信息增益— 量化一个问题在多大程度上解混了节点中的标签/减少了不确定性(越高越好)
基尼杂质
公式:1——概率(“正结果”)2——概率(“负结果”)2
将该公式应用于我们的示例,如果我们的第一个问题是“有胸痛”,我们将得到以下输出:
作者图片
为了计算“有胸痛”的总基尼系数,我们取两个叶基尼系数的加权平均值如下:
作者图片
信息增益
公式:起始基尼系数——问题的平均加权基尼系数
作者图片
获得最多信息的问题将是最好的问题,即越高越好!
问:什么时候应该提问?
既然我们已经了解了基尼系数,我们可以用它来帮助我们决定…
决策树的开始问题,即在根节点
为此,我们只需计算每个候选问题的总基尼系数,然后选择基尼系数最低的问题:
作者图片
什么时候拆分一个节点或者使一个节点成为叶节点?
为此,我们执行以下步骤:
- 计算潜在叶节点的基尼系数。
- 通过另一个问题进一步拆分节点,计算总基尼系数。
- 比较两个基尼系数杂质,并选择导致基尼系数杂质较低的行动。
作者图片
在这种情况下,我们将使所讨论的节点成为叶节点,因为分裂会导致更高的 Gini 杂质。
问:如何在叶节点做出决策?
暂时就这样吧!希望你喜欢这个关于决策树如何工作的简单解释:)
关于作者
Ranon 是 NCS 的数据科学家,他使用高级数据分析和机器学习来解决问题。他在自愿的基础上教授数据分析概念,并且是 ML @ Georgia Tech 的非全日制硕士学生。
在空闲时间,他喜欢烘焙和了解金融市场。他的人生格言是保持谦虚,不断学习:)
如有任何问题,请随时通过 LinkedIn 联系我。只要我有时间,我很乐意回答你的问题!
强化学习的直观介绍
欢迎来到人工智能的未来
强化学习是最接近人类学习方式的学习类型。
强化学习与监督和非监督学习技术相反,是一种面向目标的学习技术。它基于在一个环境中操作,在该环境中,一个假设的人(代理人)被期望从一组可能的决策中做出一个决策(行动),并通过反复学习选择一个导致期望目标的决策(基本上是试错法)来最大化通过做出该决策获得的利润(回报)。当我们继续阅读这篇文章时,我会更详细地解释这一点。
在这篇文章中,我将讨论强化学习(RL)的基础知识(尽可能用例子)。
被监督?无人监管?强化学习!
重要的事情先来!在开始谈论 RL 之前,我们先来看看它与监督和非监督学习技术到底有什么不同。
让我们考虑一个正在学骑自行车的孩子的例子。我们将会看到,如果孩子在有人监督、无人监督或强化学习的情况下学习,这个问题将如何解决:
- 监督学习:现在,如果孩子开始计算他需要在踏板上施加的力,或者他需要与地面保持平衡的角度;他开始在每次骑自行车时优化这些计算,以完善他的骑行技术,那么可以说他是在监督下学习。
- 无监督学习:然而,如果孩子开始观察成千上万骑自行车的人,并基于这些知识,如果他开始弄清楚骑自行车到底要做什么,那么可以说他是以无监督的方式学习的。
- 强化学习:最后,如果给他几个选项,比如踩踏板、向左或向右转动手柄、踩刹车等等。以及在这些选项中尝试任何他想要成功骑自行车的自由,他首先会做错并失败(可能会摔下来);但最终,在几次失败的尝试后,他会想出如何去做,并最终成功。这个案例是强化学习的一个例子。
好了,现在你知道为什么说它是最接近人类学习的方式了吧!现在,随着我们继续深入,你可以预期话题会变得有点正式。
勘探开发
让我们继续这个孩子的例子,他知道他骑自行车时可以做的一系列动作。所以,考虑这样一个场景,他最终发现持续踩下踏板可以驱动自行车。然而,他没有意识到骑行之后,他必须在某个点停下来(即在正确的时间踩刹车是骑自行车的一个组成部分)。但是,他很高兴现在他知道如何骑自行车,并且不关心未来的事情。我们姑且把他的快乐称之为'奖励',意思是他因为踩踏板的动作而得到奖励。由于他得到了奖励,他纯粹是“利用”当前的行动,即踩踏板,不知道也许最终他可能会在某个地方撞车,这将使他远离实现他的最终目标;正确地骑自行车。
现在,他可以从一系列可用的动作中探索其他选项,而不仅仅是踩踏板。最终,他将能够随时停下自行车。以类似的方式,他将学习如何转弯,这样,他将是一个好骑手。
但是,任何东西太多都是不好的!我们看到,过度开发会导致失败。同理,过度探索也是不好的。例如,如果他只是在每一个情况下随机改变他的动作,他就不会骑自行车了,不是吗?所以基本上,这是一种权衡,它被称为勘探开发困境,是解决 RL 问题时要考虑的主要参数之一。
注意孩子会根据他对环境的当前状态【w r t】来决定他在给定情况下的行动,即他在骑车时的当前运动/位置以及从先前尝试中获得的奖励(这种决策机制就是 RL 的全部内容)。
RL 问题的构建模块
- 策略:策略定义了 RL 代理的行为。在我们的例子中,策略是孩子思考在可用的动作中选择什么动作的方式(孩子是代理)。****
- 奖励:这些定义了一个问题的目标。每走一步,环境都会给代理发送一个奖励。在我们的例子中,骑自行车的乐趣,或者从自行车上摔下来的痛苦,就是奖励(第二种情况可以称为惩罚)。
- 价值函数:奖励是环境对主体的即时反应。然而,我们感兴趣的是长期回报的最大化。这是使用值函数计算的。从形式上来说,一个状态的价值是一个代理在未来可以期望积累的总回报,从那个状态开始(萨顿&巴尔托)。如果孩子仔细考虑了未来可能发生的事情,如果他选择了一个特定的动作,比如说几百米,那么这可以被称为值。**
- 模型:环境的模型是计划的工具。它模拟实际环境,因此可用于推断环境的行为方式。例如,给定一个状态和一个动作,模型可能会预测下一个状态和下一个奖励(萨顿&巴尔托)。当然,RL 机制可以分为基于模型的方法和无模型的方法。
结论
我们对 RL 问题是什么样子以及如何解决它有一种直觉。此外,我们将 RL 与监督学习和非监督学习区分开来。然而,强化学习比本文中的概述要复杂得多;但这足以明确基本概念。
参考
萨顿和巴尔托:https://web . Stanford . edu/class/psych 209/Readings/suttonbartoiprlbook 2 nded . pdf
NPTEL RL 课程:https://www.youtube.com/watch?v=YaPSPu7K9S0&list = plyqspqzte 6m _ fwzhfayf 4 lskz _ ijmyjd 9&index = 5
对 GANs 的直观了解
学习 GANs 如何工作背后的直觉,而不需要复杂的数学方程。
马里奥·高在 Unsplash 上的照片
介绍
自 Goodfellow 等人于 2014 年在 NIPS 推出 GANs(生成对抗网络)以来,GANs 已经在深度学习和计算机视觉领域掀起了风暴。GANs 的主要思想是同时训练两个模型;一个生成器模型 G 基于随机噪声生成样本,另一个鉴别器模型 D 确定样本是真实的还是由 G 生成的。
这篇文章将介绍 GANs 工作背后的直觉,而不会过多地钻研损失函数、概率分布和数学。重点是对 GANs 如何运作有一个很好的顶层理解。鉴于 GANs 越来越受欢迎,重要的是任何人都能够在不预先加载太多复杂信息的情况下开始他们的深度学习之旅!对于完整的解释,约瑟夫·罗卡有一大篇T21 一篇关于它!
训练 GAN 框架类似于两个玩家的最小-最大游戏。 G 不断改进,生成更逼真、质量更好的图像。 D 提高了确定图像是否由 G 创建的能力。训练 GAN 可以完全通过反向传播来完成,这极大地简化了训练过程。通常,通过从 G 到 D 的定期切换来执行训练,以防止两个模型中的巨大性能差距。
发电机模型
发生器模型通常由一系列上采样和卷积层组成。一种常见的架构是 DC(深度卷积)-GAN 网络,由亚历克·拉德福德等人在 ICLR 2016 上展示。DCGAN 框架可以在下面找到。如果你见过其他常见的 CNN 框架,GAN 结构非常类似于标准的 CNN 分类器,只是它是水平“翻转”的。
来自 https://arxiv.org/abs/1511.06434的 DCGAN 架构
提供给发电机网络的输入在图中标记为“100z”。这意味着采样了 100 个点,创建了长度为 100 的潜在向量。“z”还表示这些点是从单位正态分布中取样的。因此,我们可以将生成器网络视为执行从潜在空间到训练数据的映射的函数。
我们可以把潜在空间(100 维)想象成基于高斯分布的固定分布。生成器网络从这个潜在空间中随机采样点,并将其映射到图像空间(64 x 64 x 3 维)。在所有可能图像的空间中,存在描述在输入训练数据中找到的图像的更小的子空间。鉴别器将对生成器进行处罚,因为它通过对抗性损失函数创建了不属于训练数据分布(非“真实”)的图像。
生成器的映射功能,由作者生成图像
鉴别器模型
鉴别器通常具有类似于标准 CNN 分类器的框架,例如 VGG。鉴别器的目的是学习根据图像是来自训练数据还是由 G 生成来将输入图像分类为真实或虚假。看下图,鉴别器的目的是学习红色虚线。因此,它将能够根据该输入数据分布来分类真实和伪造的图像。如果提供的图像位于红色空间之外,它们将被归类为“假的”。
鉴别学习,作者图片
g 和 D 串联
在 GAN 框架中, G 和 D 模型必须一起训练。这两种模型的改进最终会产生更好、更真实的图像。一个好的鉴别器模型可以完美地捕捉训练数据分布。这允许发生器具有良好的“参考”空间,因为发生器的训练高度依赖于鉴别器输出。
如果鉴别器没有很好地捕捉到训练数据分布,生成的与训练图像不相似的图像将被归类为“真实的”,这将降低模型性能!
限制
很明显,这个简单的 GAN 框架只能产生类似于训练数据分布的图像。因此,需要大量的训练数据!此外,甘的训练还有许多障碍。一个常见的问题是模式崩溃,即生成器模型学习将多个潜在向量映射到一个单独的图像。这极大地影响了 GAN 框架的多样性。
结论
近年来有许多解决这些问题的 GANs 的变化和发展。其中包括改进的损失函数和为特定任务定制的专门框架,如超分辨率或图像到图像的翻译。
对事件预测的直观观察
入门
4 个不同的标准来查找可能是目标事件标志的事件
当谈到数据科学时,首先想到的大多是先进的建模方法。你可能会听说有人将深度学习模型应用于非常简单的问题,尽管简单的传统模型可以获得更高的精度和更好的性能。
同样,一些对机器学习了解不多的人甚至可以通过后退一步,从更普遍的角度来看数据,做出一些推断。数据每时每刻都在诉说着什么。在这篇文章中,我只想给出一个事件预测的简单起点,而不是深入研究机器学习。它可以应用于基于事件的数据集的所有预测问题。
问题定义
为了更清楚起见,以电信领域为例,考虑一个由数千台设备和一个监控工具组成的网络,该工具记录设备上发生的所有警报。这些警报可以是各种类型的。简单地说,您正在处理一个包括报警日期时间、设备名称和报警类型的数据集。目标是在任何设备上发生警报之前预测特定类型的警报。
用一个简单的推理,找出相关的告警(指标)以便预测目标告警是第一件事。为此,你不需要成为机器学习专家。
我将提到大约 4 个不同的标准来缩小警报的范围,这些警报可能是整个警报集的指示器。这些标准肯定是可以扩展的。
标准参数
标准 1
- 总计 _ 设备 _Y /总计 _ 设备
它基本上给出了候选报警的发生频率,非常直观。目标警报很可能是不经常发生的警报,因此您预计指示器警报也不会经常发生。因此,它的价值越低,成为指示器警报的机会就越大。
标准 2
- 总计 _ 设备 _X_Y /总计 _ 设备 _Y
该标准是关于目标报警和候选报警之间的相关性。它说明了目标和候选报警在同一设备上出现的频率百分比。因此,它的值越高,成为指示器警报的机会就越大。
标准 3
- 总计 _ 报警 _Y_X /总计 _ 报警 _Z_Y
它实际上是标准 2 的一种扩展,表示目标和候选警报同时出现在相同的设备上。哪一个是另一个的原因?目标警报也可能导致候选警报:)我们感兴趣的是发生在目标警报之前的警报。要使用这个标准,我强烈建议为时间间隔设置一个阈值。例如,候选警报可能在目标警报之前 30 天出现,但最有可能不作为指标,因为这是很长的时间。根据目标警报的原因,可以使用具有更短时间周期的模式,例如一周或一天。因此,对于 30 天前发生的情况,候选警报将不被考虑,并且阈值被设置为一周。显然,它的值越高,成为指示报警的机会就越大。
标准 4
- 【avg(time _ lag)
最后但并非最不重要的是,候选警报和目标警报之间的时间间隔在预测范围方面非常关键。虽然一些指示器警报在目标警报之前 10 小时出现,但是一些在目标警报之前 5 分钟出现。在这种情况下,提前 5 分钟预测目标警报可能与业务目标不一致。我鼓励在这个标准中使用与前面标准类似的时间间隔阈值。时滞的平均值和最小值可以一起使用。该标准的值将给出关于预测范围的洞察,换句话说,它指定了多久目标警报可以被预测。
作者的图像—沿时间轴的简单描述
摘要
在事件预测中(这里我一般说的是电信领域的警报设置,类似地,它在制造领域的生产线中作为预测性维护实现有很大的使用领域),在目标事件发生之前找出指示事件是最具挑战性和最突出的部分。在正确决定指示事件之后,通过将它们用作传统机器学习模型中的特征,更容易做出关于目标事件的预测。这无疑不是一个琐碎而容易的任务,然而,我只想给出一个非常简单的起点,不需要任何机器学习背景。根据标准的输出,可以在数百个不同类型的事件中组成一个可能是目标事件标志的小事件集。实际上,我上面提到的标准背后的推理是基于先进的机器学习概念,如购物篮分析和关联规则挖掘。我以前在这里写过他们对基于事件的数据集中的预测问题的一种可能的适应。
差异隐私的直观视图
这篇文章将用最简单的数学直观地解释不同的隐私。
差异隐私的一个例子。作者图片
我猜想,当我们第一次接触“怪异”的数学定义时,我们大多数人在学习差分隐私时都会遇到困难。
图像由[3]定义 2.4。
当我第一次读到差分隐私(DP)的论文时,我正在努力理解它的含义。看了一些关于差分隐私的技术帖子,终于,我明白了它是什么。在这篇文章中,我将跳过 DP 中的所有其他定义(如敏感度),只解释 DP 的直观视图。
什么是差分隐私?
我先介绍一下什么是差分隐私(DP)。给定一个查询函数 f,它从给定的数据库 d 中检索用户的吸烟人数。
D = [0,1,1,1]其中 0 代表不吸烟,1 代表吸烟。
f(D) = 3
现在,给定两个数据库 D1 和 D2,仅相差 1 条记录(D1 和 D2 相邻),这意味着 D1 是[0,1,1,1],f(D1) = 3,D2 是[0,1,1],f(D2) = 2。你可以认为 D2 已经被更新,最后一条记录已经被删除(例如,由于用户删除了他的帐户)。
现在,让我们假设攻击者想要从数据库 D1 中检索一些私人信息。攻击者知道谁已经删除了他的帐户(例如,攻击者知道 Bob 从一些服务中删除了他的帐户),但是攻击者希望知道 Bob 是否是吸烟者(他可能想要对 Bob 做坏事)
昨天,攻击者查询系统得到一个结果,即 f(D1) = 3。今天,鲍勃删除了他的帐户,D1 变成了 D2,攻击者再次运行查询(假设没有其他新信息),即 f(D2) = 2。
现在,攻击者知道 Bob 是一个吸烟者,因为他可以通过这样做获得信息
鲍勃是一个吸烟者= f(D1)-f(D2)= 3–2 = 1,其中 1 代表以上定义的吸烟。
这就是“差分”隐私,我们可以通过旧的查询结果和新的查询结果之间的差异来获得隐私信息。
数学定义(只是直观地解释)
我在这里举了个例子[1]来解释 DP 的数学定义。
首先,为了理解 DP,我们可能需要知道 KL 散度[6]在做什么。KL 散度是衡量两个概率分布之间的距离。较高的 KL 散度表示两个概率分布更远(重叠较少),较低的表示更近(重叠较多)。
KL 散度的公式,顶部为离散分布,底部为概率分布。作者图片
你可以通过两个分布 P 和 q 之间的重叠程度来理解 KL 散度
现在,让我们回顾一下 DP 的一般数学定义,如下所示:
DP 的一般数学定义,以 D1 和 D2 为例。“S”是输出的集合,我们现在只假设这个 S 是一个实数 R(数学上可能是错误的,但足以直观地理解)。作者图片
乍一看这个公式,我无法解读。看了几个帖子和解释,特别是来自[1]的,现在理解了解释。我们还需要看看 KL 的背离(见本书[3]第 3.5.1 节)。
两边除以 Pr[M(D2)..s】。作者图片
通过放置自然对数来移除指数。作者图片
这种形式似乎很熟悉,不是吗?它类似于 KL 散度的公式,有一个概率分布 P 除以另一个概率分布 Q,在我们的例子中,P(x) = Pr[M(D1)],Q(x) = Pr[M(D2)] (M 稍后解释)。KL 散度是不对称的,也就是说 P(x)/Q(x)和 Q(x)/P(x)是不一样的,但是在 DP 这里我们不关心不对称。
DP 希望将确定性输出更改为概率分布。
查询函数 f 的确定性输出“吸烟者的数量”表示吸烟者的数量。作者图片
查询结果的概率分布。作者图片
因此,通过向查询结果添加由ε值限制的噪声(常见的噪声类型是高斯和拉普拉斯),可以找到新的随机化查询函数 M。
STD(ε)是一个基于ε计算标准差的函数,现在我只是假设这个函数可以计算理论上正确的标准差。
M(D) = f(D) + N(0,STD(ε))其中 N 是高斯噪声。
然后,查询结果不再是纯粹的 2 或 3。
f(D1) = 3 #原旧查询
M(D1) = 3+(-0.8) = 2.2 #第一个旧查询
M(D1) = 3+(0.7) = 3.7 #第二个旧查询f(D2) = 2 #原新查询
M(D2) = 2+(0.7) = 2.7 #第一次新查询
M(D2) = 2+(-0.4) = 1.6 #第二次新查询
现在我们只是得到了吸烟者的“大概”数量,有一个正确的概率(例如 70%)。
因此,当我们试图通过新旧查询之间的差异来获取私人信息时,我们只能知道 Bob 可能是吸烟者,也可能不是。
D1 和 D2 的概率输出。作者图片
如果两个概率分布重叠(P(M1)/P(M2) = 1,ln(1)< =ε0),那么,攻击者就不知道鲍勃是不是吸烟者。因为 P(M1)与 P(M2)生成相同的输出,所以攻击者无法区分结果。虽然这样可以防止信息通过差异泄露,但是也会影响查询功能的质量。更多的噪声(更小的ε,最小为 0)导致好的私密性和差的质量,更少的噪声(更高的ε)导致差的私密性和好的质量。因此,epsilon 是一个随机查询函数的“隐私预算”,它控制着为了保护数据库隐私你可以放弃多少质量。
结论
DP 意味着我们可以通过一个旧查询和一个新查询之间的差异来获得一些私人信息。DP 可以通过 KL 散度来理解,将查询函数改为随机化函数,可以避免隐私信息立即泄露。
然而,更多次的查询仍然可能泄露隐私信息(在他们得到查询的意思之后),这又涉及到很多新的概念,比如隐私花费(例如 TensorFlow DP optimizer 或 PyTorch Opacus PrivacyEngine 中的隐私会计师)来阻止用户查询系统。
一旦我理解了更多的 DP 概念,如隐私支出或 epsilon-differential private,我会写更多直观的解释。希望这篇文章能帮助你直观地理解什么是 DP。
以下是我了解 DP 的资源。
[1]https://zhuanlan.zhihu.com/p/139114240
[2]https://zhuanlan.zhihu.com/p/61179516
[3]https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf
https://www.sohu.com/a/252919825_354899
[5]https://towards data science . com/understanding-differential-privacy-85ce 191 e198 a
真理之岛
汤姆·温克尔斯在 Unsplash 上的照片
来自脸书和 Airbnb 的实用数据建议
由詹姆斯·梅菲尔德 — 9 分钟阅读
我承认……我不止一次发现自己在生产、出版和公开不正确的数据。我不记得我是如何找到这些数据的——也许我在我的数据湖或数据仓库中运行了一个 SHOW TABLES 命令,得到的结果是听起来合法。
照片由克利福德摄影在 Unsplash
使用 Python 对股票和加密货币进行均值-方差分析
乔纳斯·本纳 — 16 分钟阅读
加密货币多年来一直是一个热门话题,这是有充分理由的。对一些人来说,它们是一个黑匣子,对另一些人来说,它们是金融不可避免的未来。不用说,任何人,只要花了至少一部分时间和金钱投资股票和其他资产,近年来都会考虑投资这种新颖的资产类别。
图由麦迪逊井上 Pexels
研究基于内容的新闻源过滤
由 Michel Wijkstra — 14 分钟读取
随着新闻消费日益数字化,新闻平台不得不努力转移和保留他们的用户群。维持和增加任何数字平台的用户群的一个行之有效的方法是应用个性化技术。
作者图片
如何开始学习生物信息学而不被吓倒(带 R)
通过 Lathan Liou — 7 分钟读取
这篇文章的目标读者是那些希望“闯入”生物信息学领域并且有 R(理想情况下使用 tidyverse)经验的人。生物信息学可能是一个听起来很可怕的概念(至少对我来说是这样),因为它是一个如此广阔和快速发展的领域,以至于很难准确定义它是什么。
真实之岛:来自脸书和 Airbnb 的实用数据建议
在贵公司构建核心数据集的操作指南。探索数据湖、仓库、表模式和指标的概念。
我承认……我不止一次发现自己在生产、出版和公开不正确的数据。我不记得我是如何找到这些数据的——也许我在我的数据湖或数据仓库中运行了一个 SHOW TABLES 命令,得到的结果是听起来是合法的。或者,也许我在仪表盘上找到了一个参考栏,而这个参考栏似乎正是我需要的。也许我试图找到几个月前创建汇总表的人,却发现他们已经离开了公司。
有一次,当我运行一个查询并广泛地分享一些数据时,当一位高管发电子邮件问我“嘿,你从哪里得到这个的时候,我的心沉到了谷底。您的经理刚刚说这个指标高出了 24%。”这些太普通的故事中令人痛苦的部分,也是我感受最深的部分,是对数据的信任被打破了。
"不是你对我撒谎,而是我不再相信你,让我动摇了."——弗里德里希·尼采
这篇博客文章让我们深入了解了脸书和 Airbnb 的数据,并就如何建立一个值得信赖的数据生态系统提供了实用的建议。
脸书的数据
早在 2008 年我在脸书工作时,我的正式职位是增长团队的数据分析师。作为一个兼职项目,我亲自教 550 名同事如何编写他们的第一个 SQL 查询。这是一次很棒的经历,我的同事喜欢这种了解数据的感觉。脸书刚刚开发了 Hive,为了帮助它被采用,我主动创建了这些介绍类。
一旦我的同事掌握了 SELECT 和 FROM 的基本知识,他们问的第一个问题是“我如何找到我需要的数据?”这是一个很难回答的问题。我们有大量具有相似名称和不同相关程度的数据表。作为他们的老师,我不想给别人指错桌子,但是我怎么知道哪张桌子是正确的呢?
是 dim_user、dim_users 还是 dim_users_extended?即使我设法将它们指向正确的表,我也不知道如何查询它以生成准确的指标。例如,dim_users 表上的简单 COUNT(*)将返回比我们报告的活动用户数更大的数字。事实证明,如果我没有过滤掉 user_type=-1 并设置 active_30d=1,那么我的结果将是完全错误的。
这个度量定义警告是一个大问题,当我的同事得出不正确的结果时,他们会感到沮丧和尴尬。我发现这些度量问题非常具有挑战性,因此我的新公司 Transform 正在开发工具和框架,以帮助公司正确定义和分类他们的关键绩效指标。
脸书建筑示意图
*注意 BI 工具引用两个不同数据系统的潜在问题。
Airbnb 的数据
2014 年,当我离开脸书加入 Airbnb,担任数据基础设施和数据工具项目经理时,我发誓要在这个问题变得制度化和棘手之前解决它。乍一看,Airbnb 的数据湖已经看起来非常令人生畏,有数千个表和近 1pb 的数据。老实说,这很危险。
由于一些早期的基础架构挑战(我在这里写的),组织对数据的信任度很低。对于重要的数据表和关键指标,我们缺乏可信的、单一的真实来源。几乎所有的分析见解都是由少数几个特定数据领域的数据科学家产生的,这些人整天被问题轰炸。如果这些数据科学家中的一个离开了公司,展开他们迷宫般的管道来寻找定义他们指标的实际 SQL 将是一场噩梦。
虽然早期存在一些挑战,但我们仍然致力于解决这个问题,因为我们认识到创建可信、准确数据集的真正潜力。不过,这项工作的风险很高。如果我们没有建立对数据的信任,公司将会在大数据基础设施、提高生产力的数据工具和技术数据科学人员上浪费数百万美元。当危险无处不在时,我们如何重建对数据准确性和正确性的信心?
Airbnb 架构图
*我们将核心数据放在数据湖的中心,这样它就可以与所有其他数据资产相结合,减少了在不同系统之间保持数据集同步的负担。
创造真理之岛
我们的答案是将“核心数据”构建为我们大数据湖中的极乐真理岛。一片阳光明媚的绿洲,远离鲨鱼出没的水域。其核心数据是一组基于实际主题领域的事实表和维度表。当我们最初构建它时,我们与公司的领域专家一起工作来解开用于生成表格的逻辑,然后与不同部门的利益相关者一起验证度量定义。收入、发送的消息和创建的列表等事实很容易与地区、语言和列表类型等维度结合起来。
通过删除表中许多危险的细微差别并发布优秀的元数据,我们降低了 SQL 新手的入门门槛。我们的团队致力于确保表格始终准确、完整、可靠、相关、独特、可发现和及时。凭借这些品质,我们赢得了客户的信任,然后通过我们在交付高质量数据集方面的一致性来加强这种信任。
一旦真理岛建立起来,我们就将核心数据作为数据教育工作的核心。Airbnb 的新用户可以放心地开始他们的数据之旅,因为他们知道这些表格是值得信赖的。教授数据课现在是一种绝对的快乐!员工可以自助服务,减轻数据科学家和数据分析师回答简单问题的负担。
例证图式为一座真理之岛
许多事实表(fct_)要求财务报告具有高度的准确性,因此我们从生产数据库快照中获取它们。我们可以用点击流日志的维度来丰富这些事实,这些维度更能容忍小错误或损失。
接下来的几节将提供其他公司如何开始创建自己的真理岛的学习。
我们应该在哪里构建它?
要创建一个真理岛,您需要在您的数据生态系统中开辟一个安全的地方,让您的内部客户可以轻松访问。它需要能够足够快地运行查询,以鼓励探索和连接数据集。在脸书,我们通过将我们的 Hive 数据的一个子集移动到 Oracle 机器的机架上,建立了一个真理岛(注意:这是在 Presto 被开发出来之前)。这一物理屏障确保了只有高质量、值得信赖的数据才能跨越数据仓库的鸿沟,分析查询也能在 Oracle 中快速运行。这种方法的缺点是只有少数人知道如何构建在系统之间移动数据的 ETL 管道,并且保持数据同步是一个挑战。此外,没有人能够直接通过 SQL 访问 Oracle 表,因此只能通过 BI 工具访问那里的数据,这限制了探索。
在 Airbnb,我们采取了不同的方法,在我们的蜂巢生态系统中使用逻辑屏障来创建我们的真理岛——而不是物理屏障。好处是更多的人可以访问 Hive,因此可以轻松地将这些可信的核心数据表加入到他们自己的数据集中。Airbnb 还运行了 Presto,其速度足以在我们的生态系统中“以思维的速度”支持分析查询。这是一个很好的模式,因为我们不需要专门的数据工程师在两个系统之间移动数据,并且我们避免了保持数据集同步的麻烦。
建议:在你的数据湖中间建立你的真实岛,而不是在不同的系统中。廉价文件存储的普及,加上 Presto、Dremio、Spark、AtScale 等现代查询引擎的速度。让这成为可能。如果你有幸在一家拥有单一数据仓库的公司工作,该数据仓库将所有摄取数据和摘要数据存储在 Snowflake、Redshift、Azure 数据仓库或 Google BigQuery 中,那就太好了。这里的关键点是,您应该在一个所有源数据和汇总数据都可以访问的地方创建您的真理岛。
谁应该为我们的真理之岛做贡献?
建立这样一个可信的分析数据集的老方法是雇佣一个商业智能工程师团队,他们是数据集市和 OLAP 立方体的专家。总的来说,这些人擅长为数据集不常改变的财务和运营团队创建流程和构建可信的报告。这种方法的缺点是,这些 BI 工程师经常脱离产品开发工作流,他们的治理模型跟不上现代产品开发的步伐。
许多组织已经转向在产品开发团队中嵌入数据分析师和数据科学家,以便他们可以快速构建表格、定义指标和运行实验。这种范式帮助团队快速处理数据,但是一种反模式正在出现,在这种模式中,分析师和数据科学家快速构建管道原型(在诸如 Airflow 之类的工具中),然后“将他们的 ETL 扔到墙外”。BI 工程师被要求采用没有数据含义或如何使用的上下文的管道,这造成了不愉快的感觉。
建议:这是一个棘手的问题,因公司而异。我的建议是创建一小组数据工程专家,他们可以帮助在严格的过程和支持更快的产品开发速度之间找到平衡。该团队(或虚拟团队)应该概述结构和可重复的代码模式,以致力于真理岛,帮助嵌入式数据分析师和数据科学家做出贡献。
怎样才能保持酒吧的品质?
对数据质量(准确性、完整性、可靠性、相关性、唯一性、可发现性和及时性)设定严格的指导原则为进入数据创造了很高的门槛。在 Airbnb,我们为着陆时间设置了服务水平目标,测试了基数爆炸的列,并对类型不匹配的数据发出了警报。
建议:我的观察是,数据工程有两个重要的部分——有时称为 ETL、管道建设、分析工程或 BI 工程。
- 第一:从源数据中导出数据概念,如事实、维度、度量
- 第二:维护面向内部用户的数据集以供使用
两者都非常有价值,但只有第一个是对数据工程时间的良好利用,因为它利用创造性思维和洞察力来生成新的数据资产。第二种是重复的、耗时的、容易出错的,并且通常无助于数据工程师学习或成长他们的角色。数据工程师应该投资于框架、工具、测试和流程,以减轻他们为保持内部数据集的高标准而进行的持续维护负担。
我们应该从什么开始?
我见过项目陷入困境,人们在会议前协调预备会议,讨论他们想要召开的会议,以获得大量无关的利益相关者的支持。我所看到的工作是当人们开始建造这个真理之岛的时候。选择一个像“core_”或“gold_”这样的名字作为你桌子的前缀就足以开始建立和营销你的内部品牌。
“不要等待;时机永远不会“恰到好处”。“从你所站的地方开始,用你所掌握的任何工具去工作,在你前进的过程中会发现更好的工具。”—拿破仑·希尔
建议:找到驱动你最重要的公司成果的数据集,并开始构建这些表格。理想情况下,你的真理岛将开始概述最关键的事实,并开始编目推动你的度量的漏斗。拥有一个定义良好的星型架构来分离事实和维度,降低了内部客户的准入门槛。这篇博客文章不会提供如何建立星型模式的指导,因为有许多像 Kimball 这样的好资源可以帮助指导这个旅程。
我们如何从这些(大部分)规范化的表格中获得关键指标?
即使是从一组值得信赖的表中,关键指标的推导也可能很复杂。创建一个包含定义、注释、异常检测和生命周期管理的度量存储库更具挑战性。我的新公司正在开发工具来简化这一过程,但我将把这个话题留到另一篇博文中去讨论…
感谢和赞美
Rupen Parikh、Siva Kolappa、Ray Ko 和 Prashanth Nerella 感谢你们在脸书建造这座建筑的过程中所做出的贡献。感谢你教给我的关于数据架构、治理和 ETL 的一切。
Riley Newman、Aaron Keys、Jonathan Parks、Sid Kumar、Max Beauchemin、Marcus Schmaus、Lauren Chircus 以及 Airbnb 的整个数据科学团队,谢谢你们。你在构建核心数据方面兢兢业业、深思熟虑,帮助 Airbnb 成为一家让人们与数据打交道的世界级公司。延伸阅读:Airbnb 如何将数据民主化和扩展 Airbnb 的实验平台
感谢吉姆雷诺在这篇文章中的杀手图形。
取得联系
进入数据科学的 MBA 指南
我从商学院到谷歌产品分析经理的经历
非传统的旅行
对数据科学和分析感兴趣的 MBA 比以往任何时候都多。为了保持相关性,MBA 项目正在迅速扩充课程。然而,招聘具有商业背景的分析人员可能会很棘手。
作为一名应届毕业生,我很难联系招聘经理并建立信誉。我被拒绝了几十次才找到一个合适的。在旅程的许多点上,最好的前进方式是反直觉的。
以下是我如何在谷歌获得产品分析职位的。希望我的经历能对这个过程有所启发,并帮助你获得一个令人满意的数据科学职位。
发展这些不容置疑的技能
你需要发展许多技能来保持竞争力。虽然大多数会被包括在你的常规大学计划中,但有些仍然明显缺席。不要让这些让你措手不及。*
SQL
一个不知道 SQL 的数据科学家就像一个不知道如何使用刀子的厨师。要分割数据,您将需要 SQL。此外,不必依赖别人给你递来一份 CSV,这是一种解放。期待在这上面测试。
遗憾的是,SQL 培训仍然是关键的数据技能之一,但还不是 MBA 项目的必备技能。乍一看,这似乎有点吓人,但其实不必如此——语法很直观,通常只需几个基本函数就能搞定。对于温和的入门,我使用了 Mode 的 SQL 系列的介绍。
评书
如果你想对公司的商业决策产生切实的影响,你就必须有说服力。在大多数公司,充斥着图表和无用指标的幻灯片很常见;这会很快失去你的读者,并显示出你缺乏经验——你不希望这样。
照片由 Isaac Smith 在 Unsplash 上拍摄
我发现将自己与普通数据科学家区分开来的一个简单方法是掌握讲故事的艺术。虽然许多数据科学家都试图吹嘘他们对新工具和新技术的掌握,但 MBA 的优势在于平衡严谨性和消费。Tufte 的定量信息的可视化显示提供了一个关于数据思维的大师班,并帮助我在这里开始。
线条外的颜色
数据科学作为一种职业,尤其是对 MBA 来说,是年轻且发展迅速的——这意味着没有硬性规定或只有一种正确的做事方法。
课程设置
这个过程中我最喜欢的部分是让我大开眼界的机会,向从业者和教授学习最新的技术。我尽可能多地参加了数据密集型课程,但我避免拘泥于脚本,将自己局限于“曲目”所能提供的内容。通过攻读博士课程和计算机科学系的课程,我能够拓宽视野,树立信心。
我也跟着自己的好奇心走,允许不同的兴趣交集。这样做,即使是阅读量很大的理论课也可以变成“数据”课。例如,我最喜欢的课程之一是公共政策,每周的作业是论文,但期末考试是一个关于分析旧金山人口统计的重要项目。
职位名称
就像一场 Calvinball 的游戏,数据相关的标题是出了名的混乱和定义不清。当我在 LinkedIn 上搜索“高级数据科学家”的二级和三级关系时,我开始进一步观察。我寻找的其他常见职位包括客户洞察主管、决策科学主管或商业智能主管。
这是另一个超越界限的机会——今天大多数角色都是“数据相关的”一个人脉很广的产品经理、项目经理或运营主管也能帮助你理解一家公司的数据文化,并帮你打开大门。我在找实习的时候,并没有强调我的头衔。我寻找任何可以应用我所学的角色,并把它运用到全职工作中。
期望以不同的方式招聘
与咨询或银行业的招聘不同,商学院是运转良好的机器,我发现分析职位的招聘更具挑战性。经过几十份申请,我参加了 12 家公司的第一轮面试,收到了两家公司的录用通知。
找到适合你的
在寻找公司时,寻找那些将数据视为头等公民而不是事后想法的公司。通常这些都有集中的数据团队,而不是嵌入式的。他们往往在工程和数据基础设施领域拥有强大的合作伙伴。他们的领导力不仅仅停留在口头上,而且在做出大胆的非传统数据驱动的决策方面有着显著的历史。
诺德伍德主题公司在 Unsplash 上拍摄的照片
做好耐心和灵活的准备。没有数据科学招聘周期,大多数初创公司会在需要时发布职位描述。让你的名字出现在那里,在篮圈周围徘徊,尽早接触到关系,这样当时机到来时,他们就会想到你。
带回家的小贴士
在原本灰暗而漫长的招聘过程中,我发现带回家的东西是一个亮点,也是一个展示自己的机会。通过强有力的提交,招聘人员会很快引导你前进。区分你的提交的一个简单的方法是做一点额外的工作——比如不要使用默认的情节,包括展示热情或内部知识的参考资料,并添加一个“所以怎样”,这需要一个决定性的电话或建议未来的调查路线。
值得记住的是,每个面试官都在暗中支持你取得成功,所以你应该强调你能够完成的所有事情,而不是担心你没有完成的事情。
结论
如果你来自一个没有技术技能的背景,很容易感到不安全——不要让这种担心掩盖了你带来的一切。精通业务的技术人员或精通技术的业务人员是任何公司的资产。
你不会被你的 RMSE 评分。作为一名个人贡献者,你将会因为你处理一个定义不清的问题的能力而得到认可——组织它,设计度量标准,并自信地将结果社会化。作为一名经理,你会因为发现问题的能力而得到认可——领导一项计划,获得资源,并领导他人执行。
如果我们作为数据科学家的目标是推动变革,那么商业技能就是一种优势,无论我们在哪里,它们都会很好地为我们服务。
如果你在这个旅程中有任何问题,你可以在推特上联系我
莫·巴辛的最新推文(@ BernoulliSays)。产品经理变成了数据呆子。狂热的心理学家,业余爱好者…
twitter.com](https://twitter.com/BernoulliSays)
感谢 Nitin、Tanay、Rebecca、Anders、Usman 和 Nikhil 审阅草稿并改进这篇文章。
*本指南并非详尽无遗。您还希望精通 R 或 Python,精通像 scikit learn 这样的 ML 包,等等。
参考文献
[1] 沃顿商学院形式分析沃顿商学院 (2019)**
一种全方位自动机器学习——OptimalFlow
亨特·哈里特在 Unsplash 上的照片
optimal flow是一个 Omni-ensemble 自动化机器学习工具包,它基于流水线簇遍历实验方法,帮助数据科学家以一种简单的方式构建最优模型,并用简单的代码实现机器学习工作流的自动化。
OptimalFlow 包装 Scikit-learn 监督学习框架,根据每个框架组件中的算法排列,自动创建一组机器学习管道(管道簇)。
它的预处理模块包括特征工程方法,如缺失值插补、分类特征编码、数字特征标准化和异常值 winsorization。这些模型继承了 Scikit-learn 和 XGBoost 估计器在分类和回归问题上的算法。可扩展的编码结构支持从外部评估程序库中添加模型,这使得 OptimalFlow 的 可伸缩性不同于大多数 AutoML 工具包。
OptimalFlow 使用流水线簇遍历实验作为优化器来构建用于最优基线模型搜索的全集成工作流,包括特征预处理/选择优化、超参数调整、模型选择和评估。
与其他流行的“AutoML 或自动化机器学习”API 相比,optimal flow**被设计为 Omni-ensemble ML 工作流优化器,具有更高级别的 API 目标,以避免一般流水线构建中的手动重复训练-评估实验。**
它通过创建自动化集合管道(管道集群)遍历实验和评估机制,将重点从单个管道组件自动化切换到更高的工作流级别,从而重建了自动化机器学习框架。换句话说, OptimalFlow 跳出了单个管道的范围,而将整个管道作为一个实体,自动生成所有可能的管道进行评估,直到找到其中的一个导致最优模型。因此,当我们说一个流水线代表一个自动化的工作流时, OptimalFlow 被设计来组合所有这些工作流,并找到最优的一个。这也是将其命名为 OptimalFlow 的原因。
图一。OptimalFlow 的工作流程
为此,optimal flow创建流水线簇遍历实验来组装覆盖机器学习工作流主要任务的所有交叉匹配流水线,并应用遍历实验来搜索最优基线模型。此外,通过将所有关键管道组件模块化到可重用的包中,它允许所有组件进行定制更新,并具有高可扩展性。**
常见的机器学习工作流通过“单管道”策略实现自动化,该策略首先由 scikit-learn 库引入并得到很好的支持。在实际使用中,数据科学家需要在一个管道内的每个组件中实施重复实验,调整算法和参数,以获得最佳基线模型。我把这种运行机制称为“单管道重复实验”。无论是经典的机器学习还是当前流行的 AutoML 库,都很难避免这种单一流水线聚焦的实验,这是监督建模工作流程中最大的痛点。
图 2,单管道重复实验
****optimal flow中的核心概念/改进是流水线簇遍历实验,这是 Tony Dong 在 Genpact 2020 GVector 大会上首次提出的一种框架理论,利用系综流水线算法优化和自动化机器学习工作流。
与使用单个流水线的其他自动化或经典机器学习工作流的重复实验相比,流水线簇遍历实验更强大,因为它通过集合所有可能的流水线(流水线簇)和自动化实验将工作流从一维扩展到二维。凭借更大的覆盖范围,在没有人工干预的情况下找到最佳模型,以及由于其在每个组件中的系综设计而更加灵活地应对未知数据,管道簇遍历实验为数据科学家提供了一种替代性的更方便和“全自动”的机器学习方法。
图 3,流水线簇遍历实验
OptimalFlow 由以下 6 个模块组成,您可以在 文档 中找到关于每个模块的更多详细信息。每个模块都可以用到来简化和来单独自动化具体的组件流水线。另外,你可以在 文档 中找到它们的例子。
- 用于特征预处理的 autoPP
- 用于分类/回归特征选择的 autoFS
- 用于分类/回归模型选择和评估的 autoCV
- 用于管道簇遍历实验的自动管道
- 用于管道集群可视化的 autoViz
- 日志和跟踪的自动流程。
图 4,autoViz 模块生成的模型检索图
使用 OptimalFlow,数据科学家,包括有经验的用户或初学者,可以轻松地构建最佳模型,而无需繁琐的实验,并更加注重将他们的行业领域知识转化为实际实施的部署阶段。
OptimalFlow 从一开始就被设计成高度模块化,这使得继续开发变得容易,用户可以基于它构建应用。
在 0.1.10 版本之后,它增加了一个“无代码”的 Web 应用程序,作为基于 OptimalFlow 构建的应用程序演示。web 应用程序允许对 OptimalFLow 中的所有参数进行简单的点击和选择,这意味着用户可以构建端到端的自动化机器学习工作流,而无需任何编码!(阅读 TDS 上的文档或故事的更多详情)
关于 OptimalFlow 的相关阅读:
使用 OptimalFlow 在机器学习中进行集成特征选择——使用简单代码选择顶级特征的简单方法
集成模型选择&使用 OptimalFlow 的机器学习评估—使用简单代码选择最佳模型的简单方法
端到端 OptimalFlow 自动化机器学习教程结合真实项目-公式 E 圈数预测第 1 部分
总之,optimal flow为数据科学家分享了一些有用的属性:
- 简单&代码少 —高级 API 实现流水线簇遍历实验,每个 ML 组件高度自动化和模块化;**
- 井集合 —每个关键组件都是流行算法的集合,包括超参数调整;
- 全覆盖 — 管道簇遍历实验设计用于与所有关键的 ML 组件进行交叉实验,如组合置换输入数据集、特征选择和模型选择;
- 可扩展&一致性 —每个模块由于其集成&可重用设计,可以很容易地添加新算法;不需要额外修改现有的代码;
- 适应性强 — 流水线簇遍历实验使得使用正确的流水线来适应看不见的数据集变得更加容易;
- 欢迎自定义修改 —支持自定义设置,根据弹性需求添加/删除算法或修改超参数。
作为一个初始的稳定版本发布,所有的支持是受欢迎的!请随时在optimal flowGitHub这里 分享您的反馈、报告问题或作为贡献者加入。
关于我:
我是一名医疗保健和制药数据科学家以及大数据分析和人工智能爱好者。我开发了 OptimalFlow 库,帮助数据科学家以简单的方式构建最优模型,用简单的代码实现机器学习工作流程的自动化。
作为一名拥有多年分析经验的大数据洞察寻求者、流程优化者和人工智能专家,我使用数据科学中的机器学习和问题解决技能将数据转化为可操作的洞察,同时提供战略和量化产品作为最佳结果的解决方案。
你可以在我的 LinkedIn 或者 GitHub 上和我联系。
部署企业级应用程序的开源解决方案
使用 docker + ShinyProxy 交付您的 R 数据可视化产品
对于许多 R 用户来说,FR Shiny 已经成为构建数据科学交互式 web 应用的流行平台。它允许人们轻松地从 R 可视化数据分析,而不需要弄乱许多行代码。你可以在 R Shiny Gallery 中探索一些功能强大、视觉上吸引人的应用。
作为一名生物信息学科学家,我为生物学家提供最先进的高通量实验数据的数据分析和可视化解决方案。随着合作者数量的增长,我需要构建一个 R Shiny 应用程序的主机,以确保模块化、标准化和可复制的工作流。然而,如果我想扩大我的项目规模,让这个系统得到更广泛的应用,我必须面对几个问题:
- 如何在远程电脑或云端流畅运行 R Shiny apps?
- 如何从单个门户部署和管理多个 R Shiny 应用?
- R Shiny apps 如何在主机系统中动态读写文件?
- 在 R Shiny 应用程序中,不同的用户可以访问不同的数据集吗?
这些当然可以通过 RStudio 提供的 Shiny Server Pro 来实现。然而,我搜索了在线资源,经历了试验和错误,发现 docker + ShinyProxy 是一个很好的开源解决方案,它使我能够成功地部署一系列具有所需功能的 R Shiny 应用程序。
虽然整个过程对技术要求不高,但我还没有看到如何从头开始构建这些的分步教程。在这里,我的目的是向您展示部署两个具有特定于用户的数据访问的 example R 闪亮应用程序的旅程,并希望它能启发您的项目。
📝注: 本教程介绍如何在本地计算机上部署多应用系统。但是这些步骤通常适用于远程计算机或云上的部署。当远程部署需要注意时,我会特别说明。
ℹ️ 本教程需要的所有文件都托管在我的 GitHub 库 上。repo 中有五个带编号的子目录,对应于本教程中构建最终系统的五个步骤(第 02-06 节)。在我们学习教程的过程中,我还会向您展示特定文件夹或文件的链接。
01.软件要求
我们应该已经安装了 R 和 RStudio。为了构建我们的示例 R 闪亮的应用程序,我们还需要通过调用install.packages()
来安装shiny
和tidyverse
。
接下来,我们将安装 docker。由于我用的是 macOS,所以我用这个链接安装 Docker 桌面。要在其他操作系统上安装它,您可以在这里找到信息。
我们为什么要用 docker?
docker 的理念是封装软件代码及其所有依赖项,以便它可以在任何基础设施上统一和一致地运行,即容器化策略。r 闪亮的应用通常有很多包依赖。我们将首先在本地计算机上测试它的运行,然后让他们远程工作。没有 docker 的容器化,我们将不得不确保所有运行应用程序的计算机都有相同的运行环境。这意味着我们将花费大量的精力来安装和配置大量的软件和软件包。当一个包在测试计算机上更新时,它必须在所有其他计算机上更新。我们可以看到,以这种方式管理多个 R shiny 应用程序很容易变得很痛苦。有了 docker,我们可以将应用程序、它们的依赖项和运行环境打包成一个整体映像。图像可以复制到其他计算机上,我们可以开始运行应用程序(只要那台计算机安装了 docker)。在不被繁琐的安装和配置所干扰的情况下,这种类型的实践大大加快了软件开发和部署的工作流程。
02.构建闪亮的应用程序
由于这只是一个概念验证教程,我们将构建两个简单的 R Shiny 应用程序。因为一般结构和文件系统是相同的,所以它们可以很容易地扩展到更大的项目中。
第一个应用程序“Hist_App”读取存储在文件中的数字向量,并绘制其分布。如图 1 所示,我们可以选择四个数据集中的一个,并调整箱的数量。(💻 源文件 )
图一。第一个 App“Hist _ App”的界面
第二个应用程序“Scatter_App”读取存储在文件中的两列数据帧,并绘制两个变量的散点图。同样,我们可以选择四个数据集之一,并改变点的颜色。(💻 源文件 )。在这两个应用中,数据文件都位于./data/
文件夹中。
图二。第二个 app“散点 _App”的界面
当我们打开app.R
文件时,我们可以通过在 RStudio 中单击“运行应用”来本地测试这两个应用。
03.构建并运行 R 闪亮的应用程序 docker 映像
现在我们已经构建了两个 R Shiny 应用程序,但它们只能在我们的本地机器上运行。为了让它们在其他计算机上工作,我们将利用我在上面解释的 docker 容器化策略来构建 docker 映像。
为了构建 docker 映像,我们需要一个基础映像来开始。我们可以复制文件并将附加软件或软件包安装到基本映像中,以构建新映像。 Docker Hub 是一个可以公开获得大量预建 Docker 图像的地方。有一个名为' rocker '的社区知识库,定期更新常见的 R 相关 docker 图片。我们将使用的图像是[rocker/shiny-verse](https://hub.docker.com/r/rocker/shiny-verse)
。我们在终端中使用以下命令将映像拉至本地机器:
docker pull rocker/shiny-verse
正如你可能猜到的,rocker/shiny-verse
是一个已经安装了 R,R Shiny server,以及包括tidyverse
在内的几个常用包的环境。rocker/shiny-verse
是在其基础镜像rocker/shiny
上通过安装tidyverse
等构建而成。。rocker/shiny
又是从rocker/r-ver
开始构建的,是 base R 环境。现在你可以看到它是如何工作的:docker 镜像是一层一层构建的。当我们需要构建 docker 映像时,我们不会从头开始(例如,从基本操作系统或基本 R 开始)。我们可以从一些预煮的食物开始,然后在上面加上我们的食谱。下图试图解释这个概念。
图三。逐层构建 docker 图像。蓝色图层和图像显示的是已经建成的;棕色的层和图像表明那些需要被建造。
通常,我们需要额外的 R 包来运行我们的应用程序。因此,我们可以在rocker/shiny-verse
之上安装这些包来构建shiny-more
映像。最后,复制并配置应用程序文件以构建准备运行的shiny-app
映像。幸运的是,我们的两个应用不需要更多的 R 包,因此shiny-more
图像是不必要的。我们可以从rocker/shiny-verse
直接构建shiny-app
。
📝注意: 虽然在本教程中跳过了从 rocker/shiny-verse
到 shiny-more
的步骤,但是我在 GitHub 中包含了构建这个中间映像所需的 文件 ,因为您将需要它们。从技术上来说,即使需要更多的软件包,人们仍然可以直接从 rocker/shiny-verse
进入 shiny-app
,但这样做的话,每次更新应用程序时,都需要花费几分钟来重新安装所有的软件包。因此,最佳实践是逐层构建图像。
我们需要两个文件来构建shiny-app
映像:Dockerfile
,构建 docker 映像总是需要用到它;shiny-server.sh
,它运行着 R Shiny 服务器。从 GitHub 目录中可以看到,在每个 app 的文件夹中,这两个文件都被添加在之前的文件之上。现在,在终端的./Hist_App
文件夹中,运行以下命令:
*docker build . -t shiny-hist*
这将从rocker/shiny-verse
开始构建shiny-hist
图像。基本图像在Dockerfile
: FROM rocker/shiny-verse:latest
的第一行指定。剩下的几行只是要求 docker 进行复制/安装/配置的命令。在终端中,运行docker images
。现在我们应该看到rocker/shiny-verse
和shiny-hist
都在那里。然后,运行:
*docker run --rm -p 3838:3838 shiny-hist*
这将在端口 3838 的计算机上启动我们的直方图应用程序。打开网络浏览器,并转至localhost:3838
。我们将有一个闪亮的应用程序在 docker 中运行!
运行散点图 app 的步骤是一样的:在./Scatter_App
文件夹内,运行docker build . -t shiny-scatter
(记得更改图像标签),运行docker run —-rm -p 3838:3838 shiny-scatter
。散点图应用程序将通过端口 3838 访问。
现在,我们可以在本地计算机上运行 R 闪亮的应用程序 docker 映像。但是如何让它们在远程机器上运行呢?您可能会注意到rocker/shiny-verse
有一个rocker/
部件。这是 Docker Hub 上的存储库名称。我们构建的shiny-hist
和shiny-scatter
只是本地映像,并没有被推送到 Docker Hub。要进行推送,请注册 Docker Hub 帐户,并通过 Docker 桌面或终端登录:
*docker login -u "username" docker.io*
用存储库名称重新标记应用程序后,我们可以将 docker 映像推送到网上:
*docker tag shiny-hist username/shiny-hist
docker tag shiny-scatter username/shiny-scatterdocker push username/shiny-hist
docker push username/shiny-scatter*
在其他安装了 docker 的电脑上,我们只需将图像拖到本地并运行应用程序。
04.使用 ShinyProxy 部署多个 R Shiny 应用
我们已经构建了两个 R Shiny 应用程序,可以利用 docker 轻松地将它们部署在不同的计算机上。下一个挑战是:我们如何从单个门户访问和管理多个应用程序,并为不同的用户添加身份验证。这时 ShinyProxy 开始发挥作用。ShinyProxy 是一个开源解决方案,专门开发来结合 R Shiny 和 docker,并提供额外的多应用功能,包括用户认证(甚至 LDAP 认证)。这允许多个用户在企业环境中部署和使用一系列 R Shiny 应用程序。
假设我们想从一个网页访问我们构建的两个应用程序,并且只允许两个用户登录:Alice 和 Bob。为了实现这一点,我们需要在同一个文件夹中有三个新文件。两个文件Dockerfile
和application.yaml
在 GitHub 目录下。我们还应该从 ShinyProxy 下载页面下载shinyproxy-2.3.1.jar
文件,因为它很大。
在构建 ShinyProxy 映像和运行应用程序之前,我们应该看一下application.yaml
文件,了解它是如何配置运行的。线条authentication: simple
表示我们可以直接在user
部分设置用户名和密码。这里,设置了两个用户(“Alice”和“Bob”)及其密码。R 亮闪闪的 docker 映像在specs
部分配置:我们可以设置 ID、显示名称和应用程序的描述,最重要的是,container-image
应该是shiny-hist
或shiny-scatter
,这样 ShinyProxy 就知道运行正确的映像。
另一个新概念是 docker 网络。这使得 docker 通过连接多个容器变得更加强大。我们可以在application.yaml
中看到docker: internal-networking: true
和每个图像都有container-network: sp-test-net
。它使这两个应用程序在一个 docker 网络中运行,并由 ShinyProxy 管理。而且,ShinyProxy 本身可以作为容器运行。本节旨在建立一个包含shiny-hist
、shiny-scatter
和 ShinyProxy 的整体形象。同样,任何东西都可以打包并作为容器运行!下图展示了 ShinyProxy 的设计:
图 4。ShinyProxy 设计
因此,在构建 ShinyProxy 映像之前,我们需要首先构建 docker 网络:
*docker network create sp-test-net*
📝注意: 如果您尝试在远程服务器上构建 docker 网络,尤其是使用 VPN 时,您可能需要指定 IP 子网掩码以避免 IP 地址冲突。我用的命令是 docker network create --driver=bridge --subnet 172.17.253.9/30 sp-test-net
。详细解释请见 此链接 。
网络名称应该与我们在application.yaml
中指定的名称相同。接下来,我们构建 ShinyProxy 映像来连接多个 R Shiny 应用程序(该命令应该在带有application.yaml
、shinyproxy-2.3.1.jar
和Dockerfile
的目录中运行):
*docker build . -t shinyproxy-run*
最后,我们运行shinyproxy-run
并在 web 浏览器上转到localhost:8080
来查看结果:
*docker run --rm -v /var/run/docker.sock:/var/run/docker.sock --net sp-test-net -p 8080:8080 shinyproxy-run*
我们应该会看到一个登录页面。通过使用“Alice”或“Bob”和密码登录,我们将被定向到带有两个可用应用程序的门户页面。
📝注意:application.yaml
文件中有很多选项可以配置,发挥 ShinyProxy 的全部潜力。详细文档可以在 本页 找到。**
05.通过 docker 卷进行动态数据访问
完成前面的步骤后,我们现在可以从一个门户部署和管理多个 R Shiny 应用程序。但我们的多应用系统还有一个缺陷:目前,所有数据集都存储在每个应用的./data
文件夹中。这给动态数据访问带来了困难。如果 R Shiny 应用程序使用的数据集被更新,我们必须重新构建相应的应用程序 docker 映像,以使用户可以访问新数据。当更新频繁时,让用户看到即时的数据变化变得不可行。此外,我们可能还希望应用程序在主机系统中生成文件,如果 docker 容器只能操纵自己,这是不可能的。幸运的是,docker 可以使用 卷 在主机中创建一个“docker 区域”并将其挂载到容器中,因此容器可以访问和操作主机系统中的文件。
为了探索这个特性,我们应该首先将数据文件移出 app 文件夹。上一节的树形结构如下:
**04-shinyproxy/
├── Dockerfile
├── Hist_App
│ ├── Dockerfile
│ ├── Hist_App.Rproj
│ ├── app.R
│ ├── data
│ │ ├── alice_vector_1.txt
│ │ ├── alice_vector_2.txt
│ │ ├── bob_vector_1.txt
│ │ └── bob_vector_2.txt
│ └── shiny-server.sh
├── Scatter_App
│ ├── Dockerfile
│ ├── Scatter_App.Rproj
│ ├── app.R
│ ├── data
│ │ ├── alice_df_1.txt
│ │ ├── alice_df_2.txt
│ │ ├── bob_df_1.txt
│ │ └── bob_df_2.txt
│ └── shiny-server.sh
├── application.yml
└── shinyproxy-2.3.1.jar**
让我们重新组织结构,在应用程序文件夹之外创建一个目录,用于存储两个应用程序使用的数据文件:
**05-data-on-host/
├── Data
│ ├── DF
│ │ ├── alice_df_1.txt
│ │ ├── alice_df_2.txt
│ │ ├── bob_df_1.txt
│ │ └── bob_df_2.txt
│ └── Vector
│ ├── alice_vector_1.txt
│ ├── alice_vector_2.txt
│ ├── bob_vector_1.txt
│ └── bob_vector_2.txt
├── Dockerfile
├── Hist_App
│ ├── Dockerfile
│ ├── Hist_App.Rproj
│ ├── app.R
│ └── shiny-server.sh
├── Scatter_App
│ ├── Dockerfile
│ ├── Scatter_App.Rproj
│ ├── app.R
│ └── shiny-server.sh
├── application.yml
└── shinyproxy-2.3.1.jar**
现在,如果我们尝试运行直方图应用程序的./Hist_App
文件夹中的docker build
,将会出现错误,因为./Hist_App/data
文件夹不再存在。相反,我们应该对Dockerfile
和app.R
进行修改(见此处的具体修改)。
我们首先删除了Dockerfile
中的行COPY data /srv/shiny-server/data
,然后将app.R
中的./data/
改为/Data/Vector/
,以告知应用程序数据文件现在存储在不同的位置。用不同的标签重建 docker 映像后:
**# within ./Hist_App folder
docker build . -t shiny-hist-data**
我们运行以下命令:
**docker run --rm -v /Users/mingchuxu/Documents/projects/ShinyProxy-template/05-data-on-host/Data/:/Data -p 3838:3838 shiny-hist-data## Note: The absolute path to /Data in your computer is different, please change it accordingly.**
我们可以看到直方图应用在localhost:3838
上成功运行。app 如何知道数据文件的正确位置?窍门来自上面命令中的-v
选项。该选项告诉 docker,我们希望将主机目录/Users/mingchuxu/Documents/projects/ShinyProxy-template/05-data-on-hist/Data
挂载为容器中的/Data
(该选项接受<host-dir>:<container-dir>
格式)。这就是为什么当我们在app.R
中指定/Data/Vector/
时,直方图 app 知道去主机系统中的/Users/mingchuxu/Documents/projects/ShinyProxy-template/05-data-on-hist/Data/Vector
中找数据文件。
我们可以在散点图文件夹中进行相同的更改(参见这里的确切更改),构建一个新的 docker 映像,并在挂载主机目录的情况下运行它。散点图应用程序也应该在localhost:3838
运行:
**# within ./Scatter_App folder
docker build . -t shiny-scatter-datadocker run --rm -v /Users/mingchuxu/Documents/projects/ShinyProxy-template/05-data-on-host/Data/:/Data -p 3838:3838 shiny-scatter-data## Note: The absolute path to /Data in your computer is different, please change it accordingly.**
下一步是将 docker 音量功能与 ShinyProxy 结合起来。在application.yaml
中,选项container-volumes
等同于docker run
中的-v
选项,允许我们进行相应的配置。让我们修改application.yaml
文件(查看这里的确切变化),然后构建并运行一个新的 ShinyProxy 映像:
**docker build . -t shinyproxy-run-datadocker run --rm -v /var/run/docker.sock:/var/run/docker.sock --net sp-test-net -p 8080:8080 shinyproxy-run-data**
现在从localhost:8080
开始,我们可以运行多个 R 闪亮的应用程序,从我们的主机读取数据。下图说明了与图 4 相比改进的设计。我们可以自由地将./Data
文件夹移动到我们计算机上的任何地方。只要记住每次我们改变绝对路径并重建 ShinyProxy 映像时,都要修改application.yaml
中的container-volumes
选项。
图 5。带有 docker volumes 的改进 ShinyProxy 设计
06.配置用户特定的数据访问
完成了前面的步骤,我们现在面临最后一个问题:如何让 Alice 和 Bob 访问特定于用户的数据?这可以通过利用在 ShinyProxy 登录时创建的环境变量来解决:SHINYPROXY_USERNAME
。
首先,让我们在Data/
文件夹的层次结构中再增加一层。如下树形结构所示,alice*txt
放入Alice/
,bob*txt
放入Bob/
。这使得 R Shiny 应用可以基于不同的 ShinyProxy 登录用户名访问不同的文件夹。
**Data
├── DF
│ ├── Alice
│ │ ├── alice_df_1.txt
│ │ └── alice_df_2.txt
│ └── Bob
│ ├── bob_df_1.txt
│ └── bob_df_2.txt
└── Vector
├── Alice
│ ├── alice_vector_1.txt
│ └── alice_vector_2.txt
└── Bob
├── bob_vector_1.txt
└── bob_vector_2.txt**
接下来要做一系列的修改。请参见此 GitHub 提交了解所有需要的更改。具体来说,在每个 app 的app.R
文件中,我们需要添加username <- Sys.getenv("SHINYPROXY_USERNAME")
来获取登录用户名,在ui
和server
中都通过paste0()
来修改目录路径;在每个 app 的shiny-server.sh
文件中,我们应该添加以下两行,将环境变量传递到 R Shiny app 中(在此详细解释):
**env > /home/shiny/.Renviron
chown shiny.shiny /home/shiny/.Renviron**
然后,就像在第 5 节中一样,我们将为每个应用程序构建新的 docker 映像。同样,我们使用新的 docker 图像标签来区分它们和前面章节中构建的图像。
**# within ./Hist_App folder
docker build . -t shiny-hist-user# within ./Scatter_App folder
docker build . -t shiny-scatter-user**
在构建最终的 ShinyProxy 映像之前,我们还需要修改applicaiton.yaml
,因为 docker 映像和卷都已经发生了变化(参见这里的确切变化)。
最后,使用以下命令:
**docker build . -t shinyproxy-run-user
# Note the tag name changedocker run --rm -v /var/run/docker.sock:/var/run/docker.sock --net sp-test-net -p 8080:8080 shinyproxy-run-user**
我们可以检查localhost:8080
并看到 Bob 现在只能访问Bob/
文件夹中的文件。最后,我们构建了一个简单的 R Shiny app 系列原型,允许用户认证和特定于用户的数据访问!
图 6。ShinyProxy 针对用户的数据访问
稀疏均值回复投资组合选择的优化算法
算法交易
自动识别资产并确定多头/空头头寸
多头和空头。希瑟·m·爱德华兹在 Unsplash 上拍摄的照片
受配对交易和多空股票策略的行业实践的激励,我们研究了一种结合统计学习和优化的方法来构建具有均值回复价格动态的投资组合。
我们的主要目标是:
- 设计具有均值回复价格动态的投资组合,参数由最大似然估计;
- 选择具有理想特征的投资组合,如高均值回归;
- 建立一个简约的投资组合,即从大量的资产中找出一小部分来做多头/空头头寸。
在本文中,我们提出了完整的问题公式,并讨论了利用问题结构的专门算法。使用历史价格数据,我们在一系列的数值例子中说明了该方法。
问题定式化
给定在 T 时间步内观察到的 m 资产的历史数据。我们的主要目标是找到向量 w ,组成我们投资组合的资产的线性组合,这样相应的投资组合价格过程最好地遵循 OU 过程。在 T 时间步内观察到 OU 过程的可能性由下式给出
我们联合优化方法的一个主要特点是我们同时求解最优投资组合和相应的最大似然参数。
最小化负对数似然导致最优化问题
稀疏性和速度
给定一组候选资产,我们希望选择一个小的精简子集来构建投资组合。这一特性在实践中很有用,因为它降低了交易成本、执行风险和监控许多股票价格的负担。
为了给模型添加这个特性,我们想要对投资组合向量 w 施加稀疏惩罚。虽然 1-范数是经常使用的,但在我们的例子中,我们已经施加了 1-范数等式约束||w||₁ = 1。为了获得稀疏解(即,将非零权重限制为较小的数),我们使用 0 范数并将基数约束||w||₀ ≤η应用于优化问题。这个约束限制了投资组合中资产的最大数量,并且是非凸的。
除了简化解决方案之外,我们可能还想推广产品组合的其他功能。惩罚可能性框架足够灵活,允许这些增强。均值回复系数μ概括了一个重要特征;更高的可能是理想的。我们可以通过提升更低的 c 来寻求更高的值,例如使用线性惩罚。
有了新的约束和惩罚,优化问题就变成了
最优化算法
我们的策略是首先使用可变投影,如下所示:
这导致我们解决带有非凸约束的非凸优化问题:
如果我们想用梯度下降法迭代,但是下一次迭代 wᵢ₊₁可能在可行域之外。
在投影 梯度 下降中,我们简单地选择可行集合中最接近每次迭代的点。这可以简单地概括为
这是我们算法的总结:
投影梯度下降算法
例子
我们对三组选定资产的经验价格数据进行了实验:
贵金属: GLD、GDX、广东西江、SLV、GG、AB
大型资本股票/ETF:GOOG、JNJ、NKE、MCD、SBUX、SPY、VIG、VO
石油公司/ETF:BP,COP,CVX,石油,USO,VLO,XOM
数据来自雅虎财经,给出了过去五年每项资产的收盘价。前 70%的数据(随着时间的推移)用于训练,其余用于测试。
对于每个组,我们成对地逐步增加候选资产集,并应用我们的方法。下表显示了当允许 2、4 或 6 项资产时的优化投资组合权重,以及相应投资组合的样本内和样本外负对数可能性(nll)。
当我们包含更多的资产时,投资组合 nll 通常会减少,这意味着随着候选集的扩大,我们可以获得更多的可表示的投资组合。
接下来,我们看看资产价格的时间序列和由此产生的投资组合。
一段时间内的资产价格和投资组合价值对
在 8 项资产中,该算法选择了 NKE-SBUX 的双资产投资组合。放大的投资组合价值(黑色:样本内;蓝色:样本外)
BP、COP、CVX、石油、USO、VLO、XOM 的价格,以及由此产生的投资组合价值(黑色)。
在 7 项资产中,该算法为 2 项资产的投资组合选择了石油-USO。这是投资组合价值(黑色:样本内;蓝色:样本外)。
结论
我们的算法可以完全自动化,以处理更多的资产价格和识别价格模式,并进而发现交易机会。可扩展性的这一特性对于所有机器学习交易方法都至关重要。在我们的论文中,我们还讨论了我们算法的速度,这是 algo 交易策略的另一个重要元素。
为了交易均值回复投资组合,我们仍然需要确定进场和出场的时机以及止损策略,正如相关的文章所讨论的。
参考
J.张,A. Aravkin 和 T. Leung (2020),通过惩罚似然优化的稀疏均值回复投资组合,《自动化》,第 111 卷,108651。https://doi.org/10.1016/j.automatica.2019.108651
T.Leung T .和 X. Li (2015),有交易成本的最优均值回复交易&止损退出,国际理论&应用金融杂志,第 18 卷,第 3 期,第 1550020 页。https://doi.org/10.1142/S021902491550020X
来自《走向数据科学》编辑的注释: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
自然语言处理中的文本表示综述
讨论自然语言处理中三种最常用的输入类型。
当要阐明一个人对某个特定话题的理解时,写作总是一个不错的选择。通过把想法写在纸上,想法会被澄清,困惑会被暴露。虽然这可能不是最舒服的事情,但这确实是一种学习和提高的有效方式。
如果你发现自己很难向朋友解释一些事情,一些你已经研究了一段时间,但不知何故仍然无法清晰直观地描述的事情,你应该试着把它写下来。
在这篇文章中,我试图总结 NLP 中文本表示的一些想法,旨在为未来的复杂概念奠定基础,并希望对您的学习贡献我的 granito de arena 。
NLP 输入的预处理步骤
上图总结了一个文本 语料库转化为不同输入格式的过程,供一个机器 学习 模型使用。从左起,语料库经过几个步骤才获得记号,一组文本构建 组块即词、子词、字等。由于 ML 模型只能够处理数字 值,所以通过在关联 数组(词汇)中查找或者使用散列 技巧,句子中的记号被它们对应的id、所替换。一旦完成,它们就被转换成不同的输入 格式,如右图所示。这些格式中的每一种都有自己的优点、缺点,应该根据手头任务的特点有策略地选择。
我们将研究上面显示的每一个输入表示,直接从标记开始,忽略前面的步骤。
内容:
- 一键编码
- 计数向量/特征散列/Tf-idf
- 单词嵌入/训练嵌入/语境化嵌入
1.一键编码
单词“The”、“cat”和“on”在词汇表中分别具有索引值 0、1 和 2,只有在这些位置它们的独热向量将具有值 1。向量的长度由语料库中唯一标记的数量决定。图片来自来源。
当在一个数据集中遇到一个****特征时,一键编码可能是一个人的首选(显然,如果你认为这样的特征对模型有用的话)。这是一种简单而直接的技术,它通过用充满零的向量替换每个类别来工作,除了其对应的索引值的位置,其值为 1 。
当对文本文档应用独热编码时,标记被它们的独热向量所代替,并且给定的句子又被转换成形状为(【n,m】)的 2D 矩阵,其中 n 是句子中 标记的号** 以及 m 根据一个句子有多少个标记,它的形状将不同**。****
As an example, say that we were to use one-hot encoding for the following sentences:s1\. ***"This is sentence one."***
s2\. ***"Now, here is our sentence number two."***The vocabulary from the two sentences is:**vocabulary = {"here": 0, "is": 1, "now": 2, "number": 3, "one": 4, "our": 5, "sentence": 6, "this": 7, "two": 8}**The two sentences represented by one-hot vectors are:**indices** **words
** *0 1 2 3 4 5 6 7 8*
s1: **[[0, 0, 0, 0, 0, 0, 0, 1, 0],** - "this"
**[0, 1, 0, 0, 0, 0, 0, 0, 0],** - "is"
**[0, 0, 0, 0, 0, 0, 1, 0, 0],** - "sentence"
**[0, 0, 0, 0, 1, 0, 0, 0, 0]]** - "one"s2: **[[0, 0, 1, 0, 0, 0, 0, 0, 0],** - "now"
**[1, 0, 0, 0, 0, 0, 0, 0, 0],** - "here"
**[0, 1, 0, 0, 0, 0, 0, 0, 0],** - "is"
**[0, 0, 0, 0, 0, 1, 0, 0, 0],** - "our"
**[0, 0, 0, 0, 0, 0, 1, 0, 0],** - "sentence"
**[0, 0, 0, 1, 0, 0, 0, 0, 0],** - "number"
**[0, 0, 0, 0, 0, 0, 0, 0, 1]]** - "two"
改变形状和不认识的单词
随着训练库变得越来越大,词汇的大小只会增长,结果,每个记号将由具有越来越大长度的向量来表示,使得矩阵更加稀疏。代替单词级表示,更常见的方法是使用字符作为标记,因为它将限制向量的长度。****
但是无论是使用单词级还是字符级表示,不同的句子矩阵都不可避免地会有不同的形状(不同的行数)。对于大多数 ML 模型来说,这可能是一个问题,因为它们的输入形状应该是相同的。另一方面,基于 RNN** 的模型,如果设置正确,由于其'重现'的性质,不会有这种担心,但是同一个批次中的所有实例仍有望共享一个统一的形状。**
为了解决这个问题,一个解决方案是为所有实例固定一个长度*——截断较长的实例,而填充。对于像短文本的情感** 分析这样的任务(尽管使用一键处理不会产生好的结果),通常使用前 300 个字符就足够了。在 Keras 中,填充令牌可以被屏蔽,因此它们不会影响损失。***
训练语料库的规模可以想有多大就有多大,使词汇量越来越丰富,但在推理时间里,总有可能遇到未知* 单词。处理这个问题的一个方法是在初始化时在词汇表中保留一些空间,这样当一个不在词汇表中的单词弹出时,它可以被分配到其中一个保留位置(一个oovbucket)。***
另一种特征化文本的方法是通过 n-gram 计数矢量器,让我们来看看。
2.计数矢量器
一键编码的使用允许我们实现句子的记号* - 级表示,这是通过用向量替换其记号,同时保持其原始的顺序 排列来实现的。另一方面,计数矢量器基于词频,能够将整个句子压缩成一个单个矢量。如前所述,计数向量的每个位置被分配给一个特定的标记,其值代表该标记在句子中的 出现的号 。***
首先从语料库中生成标记,并且构建词汇以将标记映射到它们相应的 id。计数向量不是为每个单词构建一个向量,而是简单地计算每个单词在句子中出现的次数,并将该数字放在向量中它们对应的位置。**
*If we were to represent the sentences from the previous example with count vectors, they would look like this:s1: [0, 1, 0, 0, 1, 0, 1, 1, 0]s2: [1, 1, 1, 1, 0, 1, 1, 0, 1]vocabulary = {"here": 0, "is": 1, "now": 2, "number": 3, "one": 4, "our": 5, "sentence": 6, "this": 7, "two": 8}*
现在所有的句子都由共享相同长度 l 的向量表示,长度由词汇表中唯一标记的数量定义,默认为但也可以手动选择。这种表示句子的方式将无法提供原句子的任何标记排序* 信息,并且其关联的上下文信息丢失——只有术语 频率反映在计数向量中。*******
***For illustration purposes, let's vectorize sentence s3:s3: ***"this this this is is one one one one"***
--> feature counts: "this" x 3, "is" x 2, "one" x 4s3: [0, 2, 0, 0, 4, 0, 0, 3, 0]***
除了使用单个单词/字符作为标记,这可以被视为单字母计数矢量器,我们还可以使用两个或更多连续的单词/字符来形成标记,获得所谓的 2 字母、3 字母或更一般的 n 字母矢量器。**
垃圾邮件检测中的用法
计数向量的一个用例是,例如,垃圾邮件* 电子邮件 检测与朴素 贝叶斯模型。***
邮件过滤的主要标准是每类邮件中的术语* 频率,即一个单词在垃圾邮件和非垃圾邮件中出现的次数。***
***The model learns through training about what words are more spam-like words, and what words are not. It assumes **conditional** **independence** for each email’s content words, meaning they are mutually independent and their appearances are only conditioned by the email’s **label**(spam, Y=1, or non-spam, Y=0).The probability of a given email being a Spam(Y=1), given its content words(X), is calculated using **Bayes** **rule**. According to which, such probability is determined by the probability of seeing these words in those Spam emails, P(X|Y=1), multiplied by the portion of Spam emails the model has seen during training, P(Y=1), and divided by P(X).***
***With X being the collection of words from an email, {x1, x2, …, xm}, by assuming **conditional** **independence**, P(X|Y=1) is calculated as the product of the probabilities of seeing these words in Spam emails:***
这里使用计数向量的一个缺点是未知的单词被扔掉**。如果你有一个句子有 m 个单词和 n 个单词,而这些单词在模型中从未出现过,那么只有 m-n 个 单词会被考虑进去。这被狡猾的垃圾邮件发送者用于过滤* 规避——修改垃圾邮件关键词,使它们不为模型所知,但仍然对用户可读。该模型将看到的内容仅包含中性单词,并且该电子邮件可以被分类为非垃圾邮件。*******
*******- Sentence from a Spam email:*"come* ***make*** *some* ***money****, ten* ***thousand******dollar*** *a week for doing nothing"*- With modified words:*"come* ***mayke*** *some* ***m0ney****, ten* ***th0usand******dollar$*** *a week for doing nothing"*- The sentence the model will see:*"come some, ten a week for doing nothing"********
除了其他优点之外,特征散列有助于减轻损害。
特征散列
随着模型用越来越大的语料库训练,它产生的词汇需要越来越多的存储空间来存储。为了提高效率,这些查找表被存储在 RAM 中,用于快速令牌 id 映射,并且一旦它们的大小变得太大,能够减慢** 操作。******
通过使用散列 技巧,我们可以完全摆脱这种消耗内存的词汇,而代之以使用散列** 函数进行令牌-id 映射。对于一个给定的字符串,哈希函数能够返回一个数值、一个哈希、值,也就是对该字符串唯一的,并将其作为令牌、 id 。******
使用散列函数进行令牌-id 映射。
由于不涉及固定大小的词汇,所有的记号现在都可以分配给一个数字,不管模型之前是否见过它。在垃圾信息 检测的情况下,通过让垃圾信息词变得对模型陌生来绕过过滤器的方式不再那么有效。任何给定的字,“已知”或“未知”,都可以被馈送到散列T42 函数并输出一个在预定义的** 范围内的数字 值。它在计数向量中的相应位置将加 1,而不是丢弃未知单词,因此电子邮件中的所有单词都将被考虑在内,而不仅仅是中性单词。******
与词汇表不同,特性哈希是一种 one - way 操作——我们无法通过哈希函数使用其哈希 值找到初始** 特性。相同的输入将总是产生相同的输出,但是两个不同的特征可能碰巧被映射到相同的散列值(如果向量大小很大,即 2 个⁴).,这种可能性可以忽略不计)******
Tf-idf 术语权重
如前所述,当表示句子 上下文时,计数向量是有缺陷的,因为它们不反映任何初始的标记** 排序。当诸如“like”、“a”或“and”等几乎没有意义的上下文 信息的术语出现得太频繁时,事情会变得更糟,通过降低它们的频率,将模型的注意力从那些不太频繁但更有趣的术语上移开。******
Tf-idf 代表术语 - 频率 (tf)乘以逆** 文档 - 频率 (idf),它用于根据每个标记出现在多少个不同的句子中,通过重新加权计数特征来解决这个问题。假设一个术语的 相关性与其在不同文档中出现的的号之间存在逆 关系,则惩罚。******
作为一个例子,让我们看看 Scikit-Learn 的 tf-idf 实现、 TfidfTransformer ,在默认设置中:
Scikit-Learn 默认设置中的 TfidfTransformer。
3.单词嵌入
到目前为止,我们已经看到了两种类型的表示: One-hot 编码,这是一种标记级别的表示,允许保留初始句子中的标记顺序;以及计数向量,这是一种更紧凑的句子级别的表示,它依赖于术语频率。****
对于 NLP 任务,如文本生成或分类,一键表示或计数向量可能能够足以表示模型做出明智决策所需的信息。但是,它们的用法对于其他任务来说就不那么有效了,例如情感 分析、神经 机器 翻译以及问题 回答,这些任务需要对上下文有更深入的理解才能获得很好的结果。********
以 One-hot 编码为例,使用它不会导致这些任务的良好概括的模型,因为任何两个给定单词之间都不能进行比较。所有矢量都是彼此正交的,任意两个矢量的内积 积为零,它们的相似度不能用距离或余弦相似度来度量。
**Say that we were to train a language model for text generation and we've provided the model with the following sentence: ***"I want to have an orange",*** expecting it to output ***"juice"***.--> ***"I want to have an orange juice"***If done right, the model should learn that ***"orange juice"*** is a common thing, or the entire sentence is a common sentence.If we were asked to complete the following sentence with one word: ***"I want to have an apple"***. Having seen the first sentence, our common sense will tell us to use ***"juice"***, provided that we have a notion on the similarities between ***"orange"*** and ***"apple"***.But the model we just trained won't be able to mimic this since it doesn't have any clue about how similar these two words are. In fact, it doesn't have any clue on how similar any two given words are, so it won't be able to generalized from ***"orange juice"*** to ***"apple juice".*****
为此,我们求助于单词 嵌入,一种能够捕获单词的语义 含义的特征化单词级表示。
通过嵌入,每个单词由一个固定大小的密集 向量表示(通常范围从 50 到 300),其值对应于一组特征,即男性、女性、年龄等。如下图所示,这些特征被视为一个词的语义的不同的 方面,它们的值由随机 初始化得到,并在训练过程中更新,就像模型的参数一样。****
嵌入“国王”、“王后”、“女人”和“公主”的向量。图片来自来源。
当训练嵌入时,我们不告诉模型这些特征应该是什么,而是由模型来决定什么是学习任务的最佳特征。在建立一个嵌入 矩阵(一组单词嵌入)时,我们只定义它的形状——单词的数量和每个向量的长度。每个特征所代表的东西通常很难解释。
单词嵌入的可视化。图片来自来源。
单词嵌入捕捉语义 含义的能力可以通过将这些高维向量通过 t-SNE 投影到 2D 空间进行可视化来说明。如果成功地获得了嵌入,用 t-SNE 绘制这些向量将展示具有相似含义的单词如何最终变得更加接近。
不同嵌入向量之间的语义 关系也可以用下面的例子来说明。
**Say that we have the embedding vectors of the word "**king**", "**queen"**, "**man**", and "**woman"**. The resulting vectors of subtracting "**queen**" from "**king**" and "**woman**" from "**man**" would be very similar direction-wise since they both carry similar values for that ***Gender*** feature."**king**" - "**queen**" ≃ "**man**" - "**woman**"or equivalently,"**king**" - "**queen**" + "**woman**" ≃ "**man**"**
训练词嵌入
前面我们提到过嵌入向量可以像另一个层(在神经网络中)一样被训练,它们也可以被单独训练并在以后通过转移 学习用于不同的任务。****
有不同的方法来训练嵌入,但是原理大致相同。这里我们简单讨论两种 Word2Vec 方法,即连续 包字 (CBOW)和跳字。****
Word2Vec 是浅层的两层神经 网络,被训练来重构单词的语言上下文。我们从大型语料库中提取上下文/目标单词的对进行训练,其中目标单词是随机选择的单词,而上下文单词是位于目标单词周围给定窗口内的那些单词。********
****There are different varieties of context, they can be 1)all the words within the window, 2) n words before or 3) after the target word, or 4) simply a random word located within the window.Sentence: "*Learning Spanish* ***is*** *hard but also fun*"
- target word: "is"
- windows length is 2, for both directions
- context:
1\. "learning", "Spanish", "hard", "but"
2\. "learning", "Spanish"
3\. "hard", "but"
4\. "learning"****
CBOW(左)和 Skip-gram(右)的模型架构图。图片来自本文。
对于 CBOW ,将上下文字以其嵌入形式(随机初始化)输入到模型中,并且期望模型使用 softmax,P(目标|上下文)输出目标字。 Skip-gram ,另一方面,与相反的,它接受目标单词,并预期输出上下文单词。
现在,这些听起来可能很难学习 任务,但是请记住,目标不是做好任务本身,而是学习好嵌入,这些模型可以做到这一点。
语境化的单词嵌入
一词多义代表书写相同但根据上下文它们可以有完全 不同的意思。如上所述的单词嵌入将使无法处理这个问题。****
****The word "**bank**" in the following two sentences has **different** **meanings**, but since they are assigned to the **same** **token** **id**, their word **embedding** vectors are the **same**.1\. "I went to the **bank** to withdraw some money."
2\. "I went to the other side of the river **bank**."****
为了解决这个问题,每个工作嵌入必须考虑到找到单词的上下文并相应地修改它的值。携带一个一般化的嵌入 矩阵并将其插入到模型中对于我们正在尝试做的任务来说是不充分的,相反,一个更加复杂的结构 **必须被包含到模型的下部才能找到嵌入。******
用于神经 机器 翻译 (NMT)的基于编解码的架构是一个很好的例子来介绍预训练 + 微调方法论,这是近年来 NLP 中最新的突破的原因。
a)用于机器翻译的序列到序列模型的预训练。b)将模型的编码器用于其他任务。图片来自封面纸。
这张图来自 学习翻译:语境化的 字 向量 (CoVe)描述了在预训练中获得嵌入的过程,以及它们如何用于下游********
在左边,一个基于编码器-解码器的模型为 NMT 训练,来自原始语言的句子首先由编码器处理,然后其输出被传递到解码器进行最终翻译。这个预训练过程是受监督的,目标是让编码器学会如何捕捉单词的句法和语义含义,并输出上下文化的** 嵌入。编码器基于两层双向 LSTM 架构,解码器基于注意力 单向 LSTMs 。******
在右边,一个预先训练的编码器接收输入、手套嵌入,以找到上下文化的** 嵌入,然后它们与原始输入组合,用于一个下游任务。******
CoVe 的局限性在于:1)预训练是由监督的,因此它受到标注为 的数据的数量的限制,2)任务特定的模型的架构还有待定义,要找到一个能够实现出色结果的架构并不是一件轻而易举的事情。通过克服这两个障碍,我们希望找到一个模型,它可以 1)用无限数据进行预训练——无监督训练,2) 对有限的标记数据进行微调,并对其架构进行一些小的修改,以实现不同 NLP 任务的 SOTA 结果。********
下面简单介绍一下埃尔莫、奥纳尔 GPT 和伯特是如何解决上述局限性的。更详细的解释请看这篇惊人的帖子: 广义语言模型作者 Lilian Weng。**
语言模型的嵌入(ELMo)通过以无监督方式训练语言 模型来获得上下文化嵌入——接受一系列标记,并学习预测给定历史的下一个标记。其结构基于双向****LSTMs,其中 L 层的 lstm 是一层一层的堆叠,每一层输出一个不同的序列表示。****
双向 LSTM。图片来自 Lilian Weng 的博客。
不同的层次侧重于单词的句法/语义的不同方面。 ELMo 较高层更关注语义方面,而较低层可以捕捉更好的句法方面。
双向 LSTMs 用于确保模型不仅学习预测给定令牌的未来,还学习预测其过去。
ELMo 仅用于查找上下文化的嵌入。对于给定的任务,仍然需要找到特定的模型架构。
OpenAI GPT 用于不同的下游任务。图片来自原纸。
OpenAI GPT ,基于变压器的解码器,可直接用于所有终端任务。如图所示,不同的任务有不同的预处理步骤,但只需对 GPT 的变形金刚模型稍加修改即可完成任务。****
与 ELMo 不同, GPT 只被训练来预测未来,但是为了更好地理解给定令牌的上下文,来自其左和右的项目都应该被考虑。
BERT 基于 Transformer 的编码器,被训练预测来自左和右的上下文。它的预培训包括两项任务:****
- 屏蔽语言模型,用【屏蔽】"随机替换标记,该模型必须通过查看其上下文来输出其原始单词。通过这样做,它迫使模型更好地捕捉缺少的单词的句法和语义含义。****
- 下一句预测。BERT 不是每次只取一个句子,而是取其中的一对,A 和 B,作为输入,它必须预测 B 是否需要 A。经过这项任务的训练,模型将更有能力理解 句子之间的关系 。****
伯特的输入。图片来自伯特论文。
BERT 使用单词块 标记化 嵌入作为它们的输入。它不生成正常单词标记,而是使用子单词 标记化来更好地处理罕见和未知单词,因为它们中的大部分可以使用子单词重构。两个输入句子有不同的句子 嵌入,并且使用特殊字符来分隔它们。位置 嵌入也被使用。****
用于句子分类的微调 BERT。图片来自伯特论文。
当使用 BERT 进行下游任务时,就像 GPT 一样,只需添加几个新参数。以文本分类为例,我们需要做的是从最后一层取出【CLS】token 的嵌入,并传递给一个 softmax 。
结论:
如果你从头到尾都读完了,这就不是一篇短文,但是如果你没有,这里有一个快速回顾:
本文讨论了三种类型的文本 表示,其中前两种是稀疏向量:一键 编码一方面是一种标记级表示,其中一个句子在用作输入之前被转换成一个矩阵,其行数与其标记数相同。计数矢量器则可以把一个句子作为一个整体,挤压成一个 单个 矢量。它依赖于统计项 频率,而这是以丢失关于句子的标记 排序的信息为代价的。
使用散列 技巧可以帮助解决大词汇表的内存 消耗的问题,并且它还缓解了在垃圾邮件检测的情况下过滤器 规避的问题。 Tf-idf 用于重新加权 术语 频率用于计数向量,因此较少 频繁但上下文 - 揭示术语不会被“忽略”。
单词 嵌入,一种更高级的技术,在需要更好地捕捉单词的语义 含义时使用。使用更复杂的结构来处理输入,以获得上下文化的 嵌入,这又用于解决多义性的问题。****
文章最后对最新的自然语言处理模型进行了简要的讨论。目的是提供一些基本的想法,需要投入更多的努力来进一步理解这些模型。
强化学习算法的结构概述
演员评论家、政策梯度、DQN、VFA、SARSA、Q-learning、基于模型和无模型蒙特卡罗、动态规划
作者照片
强化学习在过去的十年里获得了极大的普及,在机器人、游戏和许多其他领域都有一系列成功的现实应用。
在本文中,我将提供经典强化学习算法的高级结构概述。讨论将基于它们在算法复杂性方面的异同。
RL 基础
让我们从一些基本概念的快速复习开始。如果您已经熟悉 RL 的所有术语,可以跳过这一部分。
强化学习模型是一种基于状态的模型,它利用了马尔可夫决策过程(MDP) 。RL 的基本要素包括:
插曲(展示):播放状态和动作的整个序列,直到达到终止状态;
当前状态 s(或 s t ) :代理当前所在的位置;
下一个状态 s’(或 s t+1 ) :当前状态的下一个状态;
动作 a :状态 s 时要采取的动作;
转移概率 P(s'|s,a) :在状态 s t 采取行动时到达 s '的概率;
Policy π(s,a) :从每个状态到一个动作的映射,决定了代理在每个状态下如何动作。它可以是确定的,也可以是随机的
奖励 R(或 R(s,a)) :奖励函数,生成在状态 s 采取行动 a 的奖励;
Return G t :状态 s t 的未来总报酬;
值 V(s) :从状态 s 开始的期望收益;
Q 值 Q(s,a) :从状态 s 开始,采取行动 a 的期望收益;
贝尔曼方程
根据贝尔曼方程,现值等于当前报酬加上下一步的贴现(γ)值,遵循政策 π 。它也可以用 Q 值表示为:
这是大多数强化学习算法中的理论核心。
预测与控制任务
强化学习有两个基本任务:预测和控制。
在预测任务中,我们被给定一个策略,我们的目标是通过估计遵循该策略采取行动的值或 Q 值来评估该策略。
在控制任务中,我们不知道策略,目标是找到让我们收集最多奖励的最优策略。在本文中,我们将只关注控制问题。
RL 算法结构
下面是我做的一个图,用来可视化不同类型算法的高层结构。在接下来的几节中,我们将深入研究每种类型的复杂性。
MDP 世界
在 MDP 世界中,我们有一个世界如何工作的心理模型,这意味着我们知道 MDP 动力学(跃迁 P(s'|s,a)和奖励函数 R(s,a)),所以我们可以直接使用贝尔曼方程建立一个模型。
同样,在控制任务中,我们的目标是找到一个给我们最大回报的策略。为了实现它,我们使用动态编程。
动态规划(迭代方法)
1。策略迭代
策略迭代本质上是重复执行两步直到收敛:策略评估和策略改进。
在策略评估步骤中,我们通过使用贝尔曼方程计算 Q 值来评估在状态 s 的策略 π :
在策略改进步骤中,我们通过贪婪地搜索在每个步骤中使 Q 值最大化的动作来更新策略。
让我们看看策略迭代是如何工作的。
2。值迭代
值迭代结合了策略迭代中的两个步骤,因此我们只需要更新 Q 值。我们可以将价值迭代解释为总是遵循贪婪的策略,因为在每一步,它总是试图找到并采取使价值最大化的行动。一旦价值收敛,就可以从价值函数中提取最优策略。
在大多数真实世界的情况下,我们不知道 MDP 动力学,所以迭代方法的应用是有限的。在下一节中,我们将转换话题,讨论可以处理未知世界的强化学习方法。
强化学习世界
在大多数情况下,MDP 动力学要么是未知的,要么在计算上无法直接使用,所以我们不是建立一个心理模型,而是从采样中学习。在下面所有的强化学习算法中,我们需要在环境中采取行动来收集奖励和估计我们的目标。
勘探-开采困境
在 MDP 模型中,我们可以在使用转移概率函数得出好的解决方案之前探索所有的潜在状态。然而,在过渡未知的强化学习中,如果我们继续贪婪地搜索最佳行动,我们可能会陷入几个状态,而无法探索整个环境。这就是探索-开发的困境。
为了走出次优状态,我们通常使用一种叫做ε贪婪的策略:当我们选择最佳行动时,有ε的概率我们可能会得到一个随机行动。
基于模型的强化学习
估计 MDP 动力学的一种方法是抽样。遵循随机策略,我们对许多(s,a,r,s’)对进行采样,并使用蒙特卡罗(计算出现次数)从数据中显式地估计转移和奖励函数。如果数据足够大,我们的估计应该非常接近真实值。
一旦我们有了估计,我们就可以使用迭代方法来寻找最优策略。
无模型强化学习(表格)
让我们后退一步。如果我们的目标只是找到好的政策,我们所需要的就是得到一个好的 q 估计。从这个角度来看,估计模型(过渡和奖励)只是达到目的的一种手段。为什么不直接切入正题,直接估算 Q 呢?
这就是所谓的无模型学习。
1。无模型蒙特卡罗
回想一下,当代理人从状态 s 采取行动 a 时,Q(s,a)是期望效用。
无模型蒙特卡罗的思路是对很多 rollouts 进行采样,用数据来估计 q,我们来看看算法。
我们首先随机初始化所有东西,并使用 epsilon greedy 对一个动作进行采样,然后我们开始玩 rollouts。在每个卷展结束时,我们计算卷展中每个状态 St 的返回 Gt。为了得到 Q(st,at),收益 Gt 的平均值,我们可以存储所有的收益,并在完成采样后更新 Q。然而,更有效的方法是在每个卷展结束时使用移动平均增量更新 Q,如下所示。
2。萨尔萨
SARSA 是一种时间差分(TD)方法,它结合了蒙特卡罗和动态规划方法。更新方程与蒙特卡洛的在线更新方程具有相似的形式,只是 SARSA 使用 rt + γQ(st+1,at+1)来替换来自数据的实际回报 Gt。N(s,a)也用参数α代替。
回想一下,在蒙特卡洛,我们需要等待该集结束,然后才能更新 Q 值。TD 方法的优点是,当我们移动一步并得到一个状态-动作对(st,at,rt,st+1,at+1)时,它们可以立即更新 Q 的估计。
3。q-学习
Q-learning 是另一种 TD 方法。SARSA 和 Q-learning 的区别在于,SARSA 是一个基于策略的模型,而 Q-learning 是基于策略的。在 SARSA 中,我们在状态 st 的返回是 rt + γQ(st+1,at+1),其中 Q(st+1,at+1)是根据状态-动作对(st,at,rt,st+1,at+1)计算的,该状态-动作对是通过遵循策略π获得的。然而,在 Q-learning 中,Q(st+1,at+1)是通过采取最优行动获得的,这可能不一定与我们的策略相同。
一般来说,策略上的方法更稳定,但是策略外的方法更可能找到全局最优。从下面我们可以看到,除了更新方程,算法的其他部分和 SARSA 一样。
价值函数近似(VFA)
到目前为止,我们一直假设我们可以将价值函数 V 或状态-动作价值函数 Q 表示为表格表示(向量或矩阵)。然而,许多现实世界的问题具有巨大的状态和/或动作空间,对于这些空间,表格表示是不够的。自然,我们可能想知道是否可以参数化值函数,这样我们就不必存储表了。
VFA 就是用参数化函数 Q hat 来表示 Q 值函数的方法。
状态和动作被表示为特征向量 x(s,a ),并且估计的 Q hat 是线性预测器的分数。
目标是最小化估计 Q(预测)和实际 Q(目标)之间的损失,我们可以使用随机梯度下降来解决这个优化问题。
我们如何得到我们的目标——目标函数中的真实 Q 值?
回想一下,Q 值是预期收益(Gt),因此获得 Q 值的一种方法是使用蒙特卡罗:播放许多集并统计出现次数。
对于参数化蒙特卡罗,我们有以下目标函数和梯度:
另一种方法是利用 Q 值的递归表达式:Q(st,at) = rt + γQ(st+1,at+1)。正如我们前面讨论的,时间差分(TD)方法结合了蒙特卡罗和动态规划,并允许实时更新。因此,我们也可以使用 TD 方法获得目标 Q 值:SARSA 和 Q-learning。
萨尔萨:
q 学习
注意,在上面的 TD 方法中,我们实际上是使用模型预测来逼近真实的目标值 Q(st+1,at+1),这种类型的优化称为半梯度。
深度 Q 网络(DQN)
如果我们有一套正确的功能,线性 VFA 通常工作得很好,这通常需要仔细的手工设计。一种替代方案是使用深度神经网络,该网络直接使用状态作为输入,而不需要特征的明确说明。
例如,在下图中,我们有一个神经网络,状态 s 作为输入层,2 个隐藏层,预测的 Q 值作为输出。这些参数可以通过反向传播来学习。
在 DQN 中有两个重要的概念:目标网和经验回放。
正如你可能已经意识到的,使用半梯度的一个问题是,模型更新可能非常不稳定,因为每次模型更新时,真实的目标都会改变。解决方案是创建一个目标网络,它以一定的频率复制训练模型,这样目标模型更新的频率就会降低。在下面的等式中,w-是目标网络的权重。
我们还创建了一个体验重放缓冲区,用于存储以前剧集中的(s,a,r,s’,a’)对。当我们更新权重时,我们从体验重放缓冲器中随机选择一个体验来运行随机梯度下降,而不是使用从剧集中生成的最新对。这将有助于避免过度拟合。
我以前实现了 DQN 与 Tensorflow 玩钢管舞游戏。如果您有兴趣了解更多关于实现的信息,请点击这里查看我的文章。
政策梯度
与之前对价值函数建模的算法不同,策略梯度方法通过将策略参数化为以下形式来直接学习策略:
然而,当谈到优化时,我们仍然必须回到价值函数,因为策略函数本身不能用作目标函数。我们的目标可以表示为价值函数 V(θ),它是我们从遵循随机策略π的轨迹τ中得到的期望总报酬。这里θ是策略的参数。注意不要将 V(θ)误解为参数化的值函数。
其中τ是状态-动作轨迹:
R(τ)是轨迹τ的奖励总和:
现在,目标是找到使值 V(θ)最大化的策略参数(θ)。为此,我们通过提升策略的梯度 w.r.t .参数θ来搜索 V(θ)中的最大值。
在如下所示的梯度中,策略ωθ通常使用 softmax、高斯或神经网络建模,以确保其可微分。
我们来看看政策梯度是什么样的。
演员兼评论家
行动者-评论家方法不同于政策梯度方法,因为行动者-评论家方法估计政策和价值函数,并更新两者。在策略梯度方法中,我们使用 Gt 来更新θ,Gt 是单次部署中对 st 的价值函数的估计。虽然这个估计是无偏的,但它有很高的方差。
为了解决这个问题,行动者-批评家方法使用自举和函数逼近引入了偏差。我们用一个参数化的函数来估算价值,而不是使用展开中的 Gt,这就是批评家的用武之地。
这是“普通的”演员兼评论家政策梯度:
在上述过程中,引入了两个新术语:优势(At)和基线(b(s))。
b(t)是状态 St 下的预期未来总报酬,相当于 V(St),这是评论家估计的价值函数。
在每一集之后,我们更新价值函数 b(s)和策略函数。与策略梯度中的不同,这里的策略函数用 at 而不是 Gt 更新,这有助于减少梯度的方差
除了普通的演员-评论家之外,还有两个流行的演员-评论家方法 A3C 和 A2C,它们用多个工作者更新策略和价值函数。他们的主要区别是 A3C 执行异步更新,而 A2C 是同步的。
结论和想法
在本文中,我们概述了许多经典和流行的强化学习算法,并讨论了它们在复杂性方面的异同。
值得一提的是,每个型号系列中都有很多我们没有涉及到的变体。例如,在 DQN 家族中,有决斗的 DQN 和双 DQN。在政策梯度上的影评世家,有 DDPG、宏碁、沈飞等。
此外,还有另一种 RL 方法:进化策略。受自然选择理论的启发,专家系统解决了目标函数没有精确解析形式的问题。因为它们超出了 MDP 的范围,所以我没有把它们包括在本文中,但是我可能会在以后的文章中讨论它们。敬请期待!😃
参考
斯坦福 CS234 课程笔记:https://web.stanford.edu/class/cs234/slides/
莉莲的博客:【https://lilianweng.github.io/lil-log/】T2
DeepSense 框架概述
我发现 DeepSense 框架是处理时序感测数据的有前途的深度学习架构之一。在这个简单而直观的概述中,我将介绍姚等人题为“Deep Sense:用于时间序列移动传感数据处理的统一 DL 框架”的原始论文的主要思想。(可在 www2017 找到)。
主要问题
DeepSense 使用来自各种传感器(加速度计、陀螺仪等)的时间序列数据来解决移动传感问题。由于传感器的质量问题,处理任何类型的传感器都会涉及噪声测量。很难找到描述现实生活中噪声的分布,所以最终,我们的测量结果被“未知”噪声(非线性、随时间相关等)破坏。).此外,对于跟踪应用程序,应定义物理系统模型。这个模型在不准确性方面也受到“噪声”的影响(因为我们不能无误差地预测/定义模型)。当我们处理实时测量(和物理模型)时,行为可以被描述为“物理量的时间序列测量”。
(核心)思想
作者提出了一个统一的 DL 框架来解决移动传感中描述的挑战:卷积神经网络(CNN)和递归神经网络(RNN)的集成。CNN 负责计算时间间隔内的感知量,提取所有传感器的局部特征,并将它们组合成全局特征。RNN 负责计算跨越时间间隔的传感量,在此提取时间相关性。DeepSense 以某种统一的方式解决了移动计算任务的分类和回归。
建筑
该架构由 3 部分组成:卷积层、递归层和输出层。由于 DeepSense 可以用于分类和回归任务,所以输出层要根据具体任务来设置。
原始论文中的架构。
卷积层:单个卷积子网可以用 3 层(单个卷积层 1,2,3)来表示。通过应用 2d 过滤器,网络可以学习传感器测量和局部模式之间的相互作用。接下来,通过展平&级联层,矩阵被展平成向量,该向量是接下来 3 层的输入:合并卷积层。此处还应用了一个 2d 过滤器来学习所有 K 个输入传感器之间的相互作用。对于每个卷积层,DeepSense 通过使用 ReLU 学习 64 个过滤器。在每一层应用批量标准化以减少内部协变量偏移。一个展平&级联层完成卷积层的这个阶段。
递归层:RNN 的强大之处在于能够近似函数,理解时间序列的重要特征。在这个架构中,RNN 扩展模型使用的是一个堆叠门控循环单元(GRU)。实施 2 层 RNN,并去除这些递归层(1,2) 之间的连接,以及递归批量归一化,以减少数据序列之间的内部协方差偏移。
输出层:到此阶段为止,网络在每个时间步都有一系列矢量。现在,我们应该小心处理任务:回归或分类。对于回归,要学字典。对于分类,应通过对一段时间内的要素进行平均来构成输出图层。然后,将最终特征输入 softmax 层以生成预测。
总结和我的观点
除了时间卷积网络、WaveNet 等,DeepSense 似乎非常有希望用于许多时间序列任务。当我第一次阅读这篇论文时,我认为扩展卡尔曼滤波器是一种很好的经典压缩方法,因为它处理的是同一类型的问题。这种深度学习架构可能会处理模型不确定性、噪声测量等等。
进一步阅读
姚,硕超,等。“Deepsense:面向时序移动传感数据处理的统一深度学习框架。”第 26 届国际万维网会议论文集。2017.
在 Python 中导入数据概述
库特萨山的暴风雨景象
了解应该使用哪种方法
在 Python 中进行任何与数据相关的操作,比如数据清理、数据聚合、数据转换和数据可视化,先决条件是将数据加载到 Python 中。取决于数据文件的类型(如.csv
、.txt
、.tsv
、.html
、.json
、Excel 电子表格、关系数据库等)。)和它们的大小,应该相应地应用不同的方法来处理这个初始操作。在这篇文章中,我将列出一些在 Python 中导入数据的常用方法。
像往常一样,所有需要的数据和笔记本都可以从 my Github 中访问。
- Python 内置函数(
**read()**
、**readline()**
、**readlines()**
)
一般来说,文本文件(.txt
)是我们要处理的最常见的文件。文本文件由一系列行组成,每一行都包含一系列字符。假设我们需要在 Python 中导入下面的文本文件(sample.txt
)。
Country/Region
Mainland China
Japan
Singapore
Hong Kong
Japan
Thailand
South Korea
Malaysia
Taiwan
Germany
Vietnam
France
Macau
UK
United Arab Emirates
US
Australia
要将其内容导入 Python,我们需要首先打开它。这一步就像在我们的计算机系统中双击一个文件打开它一样。然而,在 Python 中,这是通过调用open()
内置函数来完成的。open()
具有作为文件路径的必需参数和指示模式的可选参数(即,默认参数‘r’:打开读取;w ':打开以供写入)。通过这些设置,open()
然后返回给我们一个文件对象。
有三种读取内容的方法(即read()
、readline()
、readlines()
)可以在这个 file 对象上单独或组合调用。
read(size=-1)
:根据size
字节数从文件中读取。如果没有传递参数或者传递了None
或-1
,则读取整个文件。
图 1 |读取示例()
readline(size=-1)
:如果没有参数被传递或者None
或-1
被传递,则读取整行(图 2 上部面板)。或者如果用size
传递,则从该行读取size
个字符。此外,可以顺序调用多个readline()
功能(图 2 下面板),其中下一个readline()
功能将从上一个readline()
功能的结束位置继续。注意,第三个readline()
的输出附加了一个额外的换行符(\n,显示为新行)。这可以通过使用print(reader.readline(5), end=’’)
来避免。
图 2 | readline()示例
readlines()
:这将从 file 对象中读取所有的行或剩余的行,并将它们作为一个列表返回(图 3)。
图 3 |示例readines()
您可能会注意到以上所有代码都有with
语句。with
语句提供了一种确保文件在打开后总是关闭的方法。如果没有with
语句,我们需要显式地为 file 对象调用close()
。例如:
file = open("sample.txt")
data = file.read()
print**(**data)
file.close()
由于很容易忘记关闭文件,我们应该始终使用with
语句。这也提供了更好的语法和异常处理。
- Python
**csv**
库
我们刚刚处理的sample.txt
每行只有一个字段,这使得只使用内置函数(read()
、readline()
和readlines()
)进行处理非常方便。然而,更常见的情况是,我们将处理一个每行有多个字段的文件(又名表格数据),如图 4 所示。
图 4 |逗号分隔文件
正如我们看到的,每行的每个字段都用逗号分隔,表示一个字段的结束和下一个字段的开始。我们称这种类型的文件为分隔文件。这些文件通常以逗号分隔(.csv
)或制表符分隔(.tsv
或.txt
)。在极少数情况下,您可能还会遇到其他分隔符,如冒号(:
)、分号(;
)和字符。
尽管内置函数仍然可以处理这些文件,但它很可能会出错,尤其是在某些情况下,当每行有数百个文件时。或者,我们可以使用 Python 的 [csv](https://docs.python.org/3/library/csv.html)
库来读取分隔文件。这里让我们从这个模块中学习两个常用函数。
csv.reader()
:读取给定文件中的所有行,并返回一个 reader 对象。那么每一行都可以作为字符串列表返回。
图 5 | csv.reader()
csv.DictReader()
:如果文件有标题(通常是标识每个数据字段的第一行),这个函数将每一行读为dict
,标题为keys
(图 6,上图)。然后我们可以通过调用它的字段名来访问每一列的数据(图 6,下面的面板)
图 6 | csv。字典阅读器()
3.使用熊猫导入数据
在 Python 中导入数据的另一个非常流行的选项是必须去 Pandas ,尤其是当数据量很大时(比如几百 MB)。我们不会深究pandas
如何工作或如何使用的细节。有很多优秀的教程和书籍(如用于数据分析的Python,作者 Wes McKinney ,熊猫的创造者)。这里我只是展示一下pandas
在读取csv
和excel
文件时的一些威力。
pd.read_csv()
:将一个csv
文件读入DataFrame
对象。这里重要的一点是,pandas 足够智能,可以自动判断每个字段的标题行和数据类型,这使得下游分析更加高效。
图 7 | PD . read _ CSV()的示例
pd.read_excel()
:将 excel 文件(.xls
、.xlsx
、.xlsm
、.xlsb
、.odf
文件扩展名)读入熊猫DataFrame
。默认情况下,它只导入 excel 文件内的第一张数据表(sample.xlsx
有多张),如图 8 所示。
图 8 | PD . read _ excel()的示例
为了能够访问 excel 文件中的特定工作表,我们可以首先使用pd.ExcelFile()
导入整个 excel 文件,然后在调用pd.read_excel()
时指定工作表名称(图 8)。
此外,为了更方便地访问所有工作表,我们可以将所有工作表作为dataframe
对象存储在dict
中,而不是多次调用pd.read_excel()
(图 9)。在这篇帖子中也可以找到一个实际的例子。
图 9 | PD 示例。ExcelFile()
4。导入大尺寸数据的选项
在大数据时代,有时,我们需要从客户或同事那里导入文件,这些文件可能太大(千兆字节或兆兆字节)而无法加载到内存中。那么,我们应该如何解决这个瓶颈呢?
幸运的是,Pandas 提供了chunksize
选项来解决这个问题。本质上,我们不是一次性导入整个文件,而是导入部分内容。
此外,我发现了一个非常有用的帖子,作者是米哈伊尔·扬切夫,他提供了多种方法,并比较了他们在处理这种情况时的效率。在这里,我只是列出了他的帖子中提到的那些方法,如果这是你正在寻找的,你可以阅读他的帖子。
- dask.dataframe() :大型并行数据帧,由许多较小的熊猫数据帧组成,沿索引拆分。一个好的方面是,大多数与熊猫一起使用的功能也可以与 dask 一起使用。
- datatable :一个 Python 包,用于操作大型二维表格数据结构(又名数据帧,高达 100GB)。
好了,现在我们知道了用 Python 导入数据的基础。当然,在 Python 中导入数据还有许多其他情况,我无法在此一一列举,比如使用 BeautifulSoup 解析html
和使用pd.read_sql_query()
读取 sql 表。我希望这篇文章能让你从基础开始,探索更多的可能性。
以下是您可能感兴趣的链接:
- 在 Python 备忘单中导入数据
- 用 Python 读写文件(指南)
- 用 Python 读写 csv 文件
- 在 Python 中读写 json 数据
- 在熊猫中使用 chunk size
- 如何使用熊猫导入各种数据
- Python 的数据表包概述
和往常一样,我欢迎反馈、建设性的批评以及听到关于您的数据科学项目的信息。你可以在 Linkedin 和我的网站上找到我。
SemEval-2017 任务 3 概述:社区问答
SemEval-2017 的任务 3 由五个问答子任务组成,使用数万个问题和评论的数据集
SemEval 是评估 NLP 模型的主要方法之一,由几个不同的任务组成。今天我们将讨论 2017 版本的任务 3 ,包括它的数据是如何收集的,以及它呈现的五个独特的问答子任务。
SemEval-2017 任务 3 数据集概述。今年的任务包括该任务往年版本的数据,这些数据显示在第二列和第三列中。以前的数据用作训练数据,新收集的数据用作测试数据(第四列)。图片鸣谢纳科夫等人,SemEval-2017 Task 3 论文的原作者。
数据。由于 SemEval 是一个相当大的竞赛,它的数据来源收集得很好,并且有完整的注释。总而言之,数据是以三种方式收集和注释的——评论与它应该回答的问题的相关程度,提议的“相关问题”与原始问题的相关程度,以及提议的“相关问题”的评论对原始问题的回答程度。
- 首先,数据是从卡塔尔生活论坛收集的,这是一个基于社区的论坛,以线程组织,其中一个问题开始一个线程,对该问题的评论将继续该线程。
- 对于每个问题,该主题的注释被标注为“好”、“潜在有用”或“坏”。
- 接下来,每个问题都与谷歌搜索交叉引用(过滤,只包括也来自卡塔尔生活的结果),以找到相关的问题。这些相关的问题然后根据它们与原始问题的关系被标注为“完全匹配”、“相关”或“不相关”。
- 最后,相关问题线索中的评论根据其回答原始问题的能力被标注为“好”、“潜在有用”或“坏”。
从卡塔尔生活论坛(q)收集的问题示例、对问题(c)的评论以及来自卡塔尔生活论坛(q’)的相关问题。图片鸣谢纳科夫等人,SemEval-2017 Task 3 论文的原作者。
子任务。收集的数据允许任务 3 呈现五个主要的子任务。
- 子任务#1:问题-评论相似度。在第一个子任务中,模型被要求确定一个评论实际上如何回答它应该解决的问题。具体来说,给定一个问题,目标是根据问题线索中的前十条评论与所提问题的相关性对它们进行排序。为了检查模型预测的准确性,指南简单地要求模型将所有“好”的评论放在“潜在有用”和“坏”的评论之上。“潜在有用的”评论不必排在“坏的”评论之上,因为它们在评估期间都被认为是“坏的”。
- 子任务 2:问题与问题的相似性。在第二个子任务中,要求模型确定原始问题与提议的“相关问题”的关联程度这里的目标是根据与原始问题的相似性对论坛中的前十个相关问题进行排名(如 Google 所示)。为了实现这一点,模型只需将“完全匹配”和“相关”问题排在“不相关”问题之上,因为评估过程不区分“完全匹配”和“相关”问题。
- 子任务#3:问题-外部评论相似性。在第三个子任务中,模型被要求确定来自相关问题线索的评论能够在多大程度上回答原始问题。这里的具体目标是,给定一个原始问题,根据其与原始问题的相关性,对前十个相关问题中的前十个评论(总共 100 个评论)进行排序。同样,该模型只需将“好的”评论排在“潜在有用的”和“坏的”评论之上。此外,只考虑这 100 个评论中的前 10 个结果,这里的理由是现实世界的用户并不真正关心后面的位置会发生什么。就像你从来没有点击过谷歌的第二页一样!
- 子任务#4:对新问题的答案重新排序。在这里,模型被要求根据它们对原始问题的回答程度来排列相关问题的正确答案。具体来说,给定原始问题,为模型提供前 30 个相关问题中的每一个问题的单一正确答案(总共 30 个正确答案),并要求模型根据它们对原始问题的回答程度对这些问题进行排序。同样,只考虑前 10 个结果。
- 子任务#5:重复问题检测。这是 SemEval 的 Task 3 的 2017 版本中引入的一个新的子任务,它实际上与子任务 b 非常相似,注意,这个子任务使用的是从 StackExchange 子论坛而不是卡塔尔生活论坛收集的数据。不过,请放心,这些数据仍然是以与其他子任务相同的格式收集的。因此,在这个任务中,给定一个原始问题,一个模型应该从 50 个建议的候选问题列表中删除项目,以便只保留重复的问题。为了清楚起见,下面是作者提供的一个原始问题和一个重复问题的例子:为什么面包公司要在面包里加糖?和糖在烘焙普通面包中的作用是什么?
希望你在 SemEval-2017 中学到了很多关于任务 3 的基础知识。对于问答任务来说,这是一个很好的数据集,所以如果你正在寻找这方面的一些评估,我肯定会建议查看原始论文[链接这里。SemEval 中的一些其他任务更受欢迎,但我肯定地说,任务 3 是问答系统中最好的任务,因为它提出了五个基本的子任务,在任何现实世界的问答系统中都非常有用。
此外,我建议总体上检查一下 SemEval。对于分析模型如何评估语言中的语义,这是一个很大的竞争,并且在未来也可能继续是一个顶级的竞争。
Anaconda 发行版概述
将改变这种方式的科学 Python 发行版…由大卫·克洛德在 Unsplash 上拍摄
科学 Python 发行版将改变你研究数据科学的方式。
Anaconda 是科学 Python 包、工具、资源和 ide 的惊人集合。这个包包括许多重要的工具,数据科学家可以使用这些工具来驾驭 Python 的强大力量。Anaconda 个人版是免费和开源的。这使得使用 Anaconda 变得容易和容易。只需到网站上下载发行版。
数据科学的现代世界是极其动态的。每天都有新的挑战出现,不可思议的挑战也是如此…
www.anaconda.com](https://www.anaconda.com/)
拥有超过 2000 万用户,覆盖 235 个地区,超过 24 亿次包下载;Anaconda 已经成长为一个异常庞大的社区。Anaconda 使得连接几个不同的科学、机器学习和数据科学包变得很容易。
关键特性:
- 神经网络
- 机器学习
- 预测分析
- 数据可视化
- 偏差缓解
如果您对数据科学感兴趣,那么您应该了解这个 Python 发行版。Anaconda 非常适合深度模型和神经网络。您可以构建模型,部署它们,并与该领域的领先技术集成。Anaconda 针对机器学习任务进行了优化,可以高效运行,并且在开发优秀的算法时可以节省您的时间。发行版中包含 250 多个软件包。可以用conda install
通过 Anaconda 终端安装其他第三方包。他们基于云的存储库中有超过 7500 个数据科学和机器学习包,您需要的几乎任何包都可以轻松访问。Anaconda 提供个人版、团队版和企业版。还包括对 R 编程语言的支持。
Anaconda 发行版附带了可以在 Windows、Linux 和 MacOS 上使用的包。个人版包括流行的包名,如numpy
、pandas
、scipy
、sklearn
、tensorflow
、pytorch
、matplotlib
等等。Anaconda 提示符和 PowerShell 使得在文件系统中工作变得容易和易于管理。此外,Anaconda Navigator 上的 GUI 界面使得一切工作异常流畅。如果您正在寻找一个蓬勃发展的数据科学家社区和业内不断增长的支持,Anaconda 是一个很好的选择。在这样的伟大工具的帮助下,开展数据科学项目变得越来越简单。
包括在 Anaconda Navigator 中
Anaconda 提示符和 Powershell
作者图片
Jupyter 笔记本电脑和 Jupyter 实验室
Jupyter 笔记本是一个基于网络的交互式计算平台。该笔记本结合了现场代码,方程式…
jupyter.org](https://jupyter.org/)
允许数据科学家管理工作流并有效实现科学和计算解决方案的开源软件。Jupyter 笔记本强调演示和可读性,是合作项目和有见地的出版物的明智选择。Jupyter 笔记本是开源的,由 Jupyter 社区在 GitHub 上公开开发。
皮查姆
[## py charm:JetBrains 为专业开发人员提供的 Python IDE
在 PyCharm 处理日常事务时节省时间。专注于更大的事情,拥抱以键盘为中心的方法…
www.jetbrains.com](https://www.jetbrains.com/pycharm/)
一个顶级的 Python IDE,它包含了所有的特性和预安装的包。凭借舒适的环境管理和易于设置的工作站,PyCharm 在 Python 中独树一帜。无论是社区版、专业版还是企业版,都有适合每个人的版本。
Visual Studio 代码
[## Visual Studio 代码-代码编辑。重新定义的
Visual Studio Code 是一个重新定义和优化的代码编辑器,用于构建和调试现代 web 和云…
code.visualstudio.com](https://code.visualstudio.com/)
您可以为编程选择的最佳开源解决方案之一。这个文本编辑器是初学者和高级程序员的绝佳选择。Visual Studio 代码提供了 IntelliSense,一个内置的调试器,一个令人难以置信的可定制环境,以及与流行扩展的集成。
Qt 控制台
[## Jupyter 的 Qt 控制台- Jupyter Qt 控制台 4.7.7 文档
2020 年 9 月 3 日发布 4.7.7 版,启动 Qt 控制台:Qt 控制台是一个非常轻量级的应用程序…
qtconsole.readthedocs.io](https://qtconsole.readthedocs.io/en/stable/#)
一个轻量级的程序,就像一个充气的控制台。它提供了语法高亮、内嵌图形、呼叫提示、REPL 等等。
Spyder
Spyder 是一个强大的科学环境,用 Python 编写,为 Python 服务,由科学家设计,为科学家服务…
www.spyder-ide.org](https://www.spyder-ide.org/)
高度先进的数据科学 Python 平台。这个 IDE 是用 Python 为 Python 创建的,拥有一些非常健壮的工具集。凭借编辑器、IPython 控制台、变量资源管理器、高级绘图功能、内置调试器和对象文档助手工具,Spyder IDE 是大量数据科学任务的理想选择。
Glueviz
Glue 是一个开源的 Python 库,用于探索相关数据集内部和之间的关系。使用 Glue,用户可以…
glueviz.org](https://glueviz.org/)
使用 Glueviz 将您的数据集和数据链接到单个图表或图形。这个 Python 库允许您通过组合数据集并使用其中的逻辑链接来查看数据可视化。
橙色 3
通过巧妙的数据可视化执行简单的数据分析。探索统计分布、箱线图和散点图…
橘子生物实验室](https://orange.biolab.si/)
如果数据挖掘是你的目标,那么 Orange 3 已经覆盖了你。Orange 3 是为数据挖掘而构建的工具集。它们提供了优秀的 GUI、可扩展的附加功能、数据管理和交互式数据可视化。此外,因其引人入胜的可视化效果、数字和图表而受到教师和学生群体的喜爱。
r 工作室
控制您的 R 和 Python 代码一个 R 和 Python 的集成开发环境,带有一个控制台…
rstudio.com](https://rstudio.com/)
使用 R 编程语言的推荐环境。R Studio 有两个版本,R Studio 桌面版和 R Studio 服务器版。智能语法解决方案、编辑器中的 R 执行、助手工具、目录管理、集成的 R 文档和帮助、内置调试器以及包工具只是 R Studio Desktop 提供的部分功能。R Studio Desktop 和 R Studio Server 有开源版和专业版。
结论
如果您是数据科学的新手,想要获得 Python 的完整体验,或者如果您是一位经验丰富的数据科学家,正在寻找更多的功能和效率,我真的建议您看看这个惊人的发行版。它使包的管理和部署变得快速而简单。Anaconda 打包了工具、ide、包和库,对于数据科学来说是一个真正可信的决策。因为 Anaconda 的受欢迎程度似乎在许多新的行业和领域中不断扩大,而这些行业和领域又刚刚开始使用这种高级功能,所以现在开始使用这个不断增长的工具和资源包是再好不过了。我希望这篇文章有助于详细介绍 Anaconda 发行版,帮助那些想了解它带来了什么和包含了什么的人。感谢您的阅读和快乐编码!
2020 年全球聊天机器人解决方案市场概述
根据我对会话助手市场的积极观察,我给你一些统计数据和我研究的近 550 个解决方案的信息。最后,我会告诉你我对未来的看法。
来源:作者照片
这一事件似乎仍能感受到那些如此关注它的人心中的一切,它是否引人注目。在 2018 年 5 月 8 日的谷歌年度大会上,该公司将展示其新一代助手:Google Duplex。这是一个比生活更真实的助手。有一次,人类没有打电话给机器人,而是由助手打电话给人类(理发师)代替人来预约。生成的声音如此接近人类的音色及其变化,以至于几乎无法判断这是一个真正的自动化还是一个专门制作的设置,以模拟这样一个助手可能是什么样的[1]。整个对话和日常对话一样,非常标准,有停顿和语调。回想起来,这次演示的目的是为一个项目制造轰动,而不是展示一个已经可用的产品。但它确实暗示了支持解决方案的潜在未来。无论如何,它表明了谷歌想要走的路。
很难知道未来几年对话助手的市场会增长多少。分析师给出的值有时从简单到双精度不等。通过对分析师公布的数据取平均值,我们可以预见到 2024 年市场价值约为 110.5 亿美元,2027 年约为 445.8 亿美元,即 CAGR ( 复合年增长率)为 26%。所有的分析师都同意指数增长,在某个时间点肯定会趋于平稳。
按公司成立年份细分的解决方案
解决方案占公司创建年份的比例。值得注意的是,创建年份(在下图的横坐标上)并不总是与解决方案的可用年份相对应。许多公司在创建自己的对话解决方案之前,通常已经在相关领域存在过。这使得很难(除非你花大量时间搜索该公司何时交流其解决方案)确切知道该解决方案是何时创建的。
然而,让我们回到几年前,充分了解我们是从哪里开始的。人们普遍认为,帮助你创建自己的对话助手的最古老的解决方案(也称为"聊天机器人","聊天机器人"的缩写)被称为 A.L.I.C.E .这个缩写代表人工语言互联网计算机实体。它是由 William Wallace 在 1995 年开发的一个应用程序,用来模拟人和机器之间的对话。它允许执行符号规则,包括测试用户句子中关键词的存在。这种操作模式使用起来非常简单,并且足以涵盖许多使用案例。另一方面,一旦对话变得更加复杂,词汇量变得非常大,它就会很快发现自己的极限。
对话助手的原理在 2011 年 10 月 4 日的发布会上真正向公众普及了,这款新的 iPhone 4S 集成了一款名为 Siri 的革命性应用。重要的是要看到许多消费者创新已经被公司采用,因为员工在他们的个人生活中经常使用这种类型的解决方案,并期望公司提供相同的服务(参见企业社交网络、即时消息、强大的搜索引擎等)。)因此,助理有一天也会出现在公司里是很自然的事情。
为了理解 Siri 的起源,我们必须追溯到 8 年前,即 2003 年 5 月,当时 DARPA 启动了名为 CALO 的项目。在 2006 年 SRI 的 Calo 网站上写着[3]:
国防高级研究计划局(DARPA)在其感知学习助手(PAL)计划下,授予 SRI 一份为期五年的合同的前两个阶段,以开发一种持久的个性化认知助手。DARPA 希望 PAL 计划能够产生创新的想法,从而产生新的科学、解决当前问题的新的基本方法、新的算法和工具,并产生对军事具有重要价值的新技术。
该团队将其新项目命名为 CALO,意为学习和组织的认知助手。
CALO:学习和组织的认知助手
这个名字的灵感来自拉丁语“calonis”,意思是“士兵的仆人”。该项目的目标是创建认知软件系统,即可以推理、从经验中学习、被告知做什么、解释他们做什么、反思他们的经验并对惊喜做出强烈反应的系统。
该软件通过与用户互动并听取用户建议来学习,将处理广泛的相互依赖的决策任务,这些任务在过去一直抵制自动化。CALO 将有能力从事和指导日常工作,并在意外发生时提供帮助。为了专注于现实世界问题的研究,并确保软件满足隐私、安全和信任等要求,CALO 的研究人员在开发过程中也在使用这项技术。
该项目汇集了来自 25 个最好的学术和商业研究机构的 300 多名研究人员。因此,Siri 最初是由 SRI International 通过 DARPA 项目开发的。然而,SRI 在 2007 年从 Siri,Inc .分离出来,现在独立的公司在 2010 年 2 月推出了个人助理应用。
2010 年www.siri.com主页(互联网档案馆)
然而,这个应用程序将没有时间过它的生活,因为 Siri 公司在那一年被苹果公司收购,成为所有 iPhone 用户的个人助理。苹果向媒体发布声明的第二天,该公司的网页就消失了。尽管 Siri 不适合专业用途,但在这款著名智能手机的销售推动下,它仍将是这项技术大规模部署的起点。
那么解决方案和“聊天机器人”有什么区别呢?事实上,设计解决方案的编码团队之外的人可以配置聊天机器人,让它说出自己的意图。正如理查德·华莱士在他的 A.L.I. C.E .网页上写的“不要读我”[4]。
机器人大师是你,你的聊天机器人的主人。
很难找到第一个真正的商业解决方案,但 Pandorabots 解决方案肯定是第一个。这是理查德·华莱士与 Franz,Inc .合作的结果。Pandorabots [5]创建于 2002 年,到 2020 年,该公司仍然活跃着,迄今为止拥有超过 350,000 个机器人(在网站主页上显示)。
2002 年 10 月的潘多拉机器人主页(互联网档案)
历史将会记住,托管是免费的,商店菜单(出现在 2005 年 11 月)只允许购买潘多拉机器人的 t 恤,不允许购买机器人![6].
2015 年,IBM 的 Watson Dialog(几乎是偷偷地)发布,大规模地引入了人工智能的学习能力,以服务于语言处理,从而改善识别用户请求的机制,并由一个国际玩家进行。
根据公司创建年份显示解决方案分布的图表突出显示了 2013 年至 2018 年期间解决方案的爆炸式增长,其中 2/3 的解决方案是在这一年创建的。2015 年至 2017 年特别值得注意,因为这三年见证了全球一半的解决方案。发布对话式解决方案的公司中,有 20%是在 2016 年创建的,这是一个真正的创新关键年。这个日期前后各有一次。
根据编辑器的创建年份,解决方案在世界上的分布
即使公司继续被创建,速度也大幅放缓,2019 年仅创建了 9 个解决方案,2020 年可能也是这种趋势。
按国家细分
这些解决方案按照公司总部的位置进行分类。正如您所料,美国是托管最多解决方案的国家,共发现了 219 个聊天机器人解决方案。令人惊讶的是,尽管这是一个相当小的市场,但法国以 77 个解决方案位居第二。然后我们发现印度有 40 个解决方案。然后是英国的 28 人和加拿大的 20 人。德国、西班牙、以色列和新加坡各有 10 至 20 个解决方案。根据我的列表,其余每个国家的解决方案都在 10 个以下。我认为每个出版商只有一个解决方案,即使这个出版商发布了几个不同的解决方案。
按解决方案数量递减排列的前 20 个国家
总共有 48 个国家至少有一个解决方案。各大洲都有代表。
解决方案的数量取决于国家
编辑类型学
对编辑器类型的分析允许根据以下主要类别对其进行分类:
- 纯玩家
- 自然语言处理解决方案提供商
- ERP 和/或 CRM 解决方案发布者
- 呼叫中心、联络中心和/或 Livechat 解决方案发布者
- 云服务解决方案提供商
- 数字服务公司(DSC)和其他 IT 公司
- 其余的
纯粹的玩家是那些将几乎所有收入建立在出售机器人解决方案和相关服务上的发行商。这些解决方案大多是多租户的,托管在云中。
自然语言处理(NLP)解决方案的发行商通常在他们的市场上建立,他们在聊天机器人需求的爆炸中看到了机会,并基于自己的算法创建了解决方案。
企业资源规划(ERP)或客户关系管理(CRM)解决方案将受益于托管对话解决方案,尤其是如果该解决方案由到软件包模块的连接器和特权链接来补充的话。这些编辑通常不具备对话技巧,通常会进行并购。
对于用于管理用户、客户、供应商与公司之间的交流的解决方案,通过对话解决方案实现自动化成为一项强制性功能。在 Livechat 解决方案中,其中一个代理变成虚拟的,能够处理部分请求,从而自主响应。
已经迁移到云的企业软件发行商或纯云发行商,如亚马逊 WS、百度云、谷歌云平台、IBM Cloud、微软 Azure、SalesForce.com 等。最为人所知的是,提供一套服务,并且必须在他们的“工具包”中包含对话式解决方案。
数字和技术服务公司(咨询和 IT 公司),信息技术专家,必须掌握这些技术,因为他们的客户要求他们。许多公司整合了现有的解决方案,有些公司孤注一掷,创建了自己的解决方案。
最后,通常提供源代码的个人(通常以开源模式)创建解决方案。也有公司开发了自己的解决方案,并提供给最大数量的用户。也有人工智能和语言处理的研究人员分享他们的发现,甚至他们的论文成果。
公司规模
毫不奇怪,僵尸工具解决方案提供商的员工人数不到 50 人(73%)。
解决方案数量与公司员工数量之比
2017 年创建的公司中有 1/3 的员工不到 10 人,仍然是非常小的公司。2016 年创建的公司中有 1/3 的员工人数在 11 至 50 人之间,并且通常在其市场上提供成熟和公认的解决方案。发布多种解决方案或已经拥有软件基础(例如联络中心)的公司通常拥有超过 50 名员工的能力。
根据创建年份和公司员工人数确定的解决方案数量
如果我们拿公司规模的原始数据来看,我们会发现,按比例来说,法国是“小”公司最多的前 10 个国家,几乎一半的公司不超过 10 名员工。意大利和英国紧随其后。应该指出的是,对于法国来说,2017 年的新公司数量将超过 2016 年,而某些国家则相反,这可以解释为什么与拥有超过 10 名员工的公司的国家相比,法国的新公司数量会延迟一年。
根据公司规模(1 至 100 名员工)按国家列出的解决方案百分比
解决类别
每个解决方案都不同。它提供特定于它的服务、接口和设施。然而,当研究大量的这些解决方案时,有可能确定几类解决方案。要么是编辑器表达清楚,要么是所有的功能都对应一个可识别的类别。
以下是这些类别:
- 一般用途;30%的市场解决方案。我从最具代表性但也是最普遍的类别开始。此类别中的解决方案允许您配置所有类型的向导,而无需特殊功能。他们识别问题(用户的意图),并从主题专家配置的答案中给出最合适的答案。该解决方案通常被描述为能够管理多个类别。当解决方案过于笼统时,它往往过于笼统,无法从竞争对手中脱颖而出。
- 零售和电子商务(营销);26%.这当然是最具代表性的专业类别。它涵盖了支持销售网站的商业领域。它用于留住客户,帮助他选择产品,回答有关产品可用性的问题。当用户在页面上仍被阻止时,聊天窗口会打开。该解决方案提供了诸如转盘、产品表等工具,并且可以在回答之前添加延迟,以便显得更人性化、更友好。它有大量关于用户的统计数据,比如他来自哪里,是否是第一次访问,他的浏览器的名称和版本。许多解决方案都有一种用于未解决请求的邮箱。机器人会想尽一切办法获取用户的电子邮件地址,让他订阅时事通讯。助理变成了销售顾问,从这个意义上说,解决方案尽一切努力来促进机器人的配置。该解决方案具有与电子商务软件、联系人管理软件等的各种连接器。能够更好地了解客户,并尽可能以最有针对性的方式做出回应。通常,它也有一个广泛的社交网络连接列表。
- 客户支持、销售、服务台;17%.这些解决方案是专门针对用户问题而设计的。他们可以处理大量的问题,并有链接到文档。它们有助于创建复杂的对话,其目的是帮助用户找到答案。这些解决方案基于知识原理,指导用户解锁。他们还通过允许用户上传文档、从信息系统中检索信息来参与流程的自动化。
- SDK(软件开发工具包);5%.这个解决方案是一个工具箱,允许开发人员构建他们的对话解决方案。它提供了一整套功能(库),允许管理对请求的理解、功能的执行和对话上下文的管理……实现一个机器人需要有编程技能。大多数时候,这些解决方案都是开源的。有时候发行商提供一个云执行环境,然后付费。
- 银行、金融服务和保险(BFSI);4%.这些解决方案针对银行和保险市场,提供了特定于这些领域的功能:银行管理、偿付能力分析、报价、推荐/建议、将潜在客户发送给代理、索赔管理等。
- 个人助理;4%.可能是最“大众化”的解决方案,因为它们允许你创建助手来帮助你的日常生活。
- 医疗保健;2%.很少有医疗保健解决方案是可配置的。它们中的大多数都已经配置好了,不允许您更改它们的设置。
- 旅行和接待(旅游);2%.这些解决方案专注于旅游活动,并允许配置机器人,这些机器人可以帮助用户计划他们的假期,指示要参观的旅游景点,可用的酒店等。
- 招聘;2%.这些解决方案支持为招聘新员工的流程创建助手。他们可以回答关于公司的问题,参加能力测试,收集简历,作为招聘的联系人等等。
- 设备助手;1%.这些解决方案设计用于嵌入电子设备,如烤箱、冰箱、电视等。它们通常基于语音,并嵌入了请求识别所需的人工智能。
- 汽车;1%.这些解决方案旨在嵌入到汽车中,并在旅途中帮助司机。即使汽车是一个相当“大”的设备,这个类别也是设备助理类别的一个专门化。
- 对话过程自动化;1%.该解决方案将机器人的功能与 BPM(业务流程管理)软件或 RPA(机器人流程自动化)中常见的流程自动化功能相结合。
- 对话式搜索;1%.它的目标是允许您创建向导,帮助您在内容管理器中找到正确的文档和段落。
- 项目管理;1%.此解决方案允许您创建项目助手。他们支持项目经理的日常管理活动。用这些解决方案创建的机器人成为一种 PMO(项目管理办公室)助手。
- 其他;5%.这最后一类不是一个。它用于将出现率低于 1%的所有类别组合在一起。这些解决方案使响应管理请求成为可能,它们以图形方式显示数据库中的数据,用户在数据库中用自然语言表达他或她的请求,帮助接待新员工(入职),专门从事房地产,管理支持票据,专门从事农业,专门从事内容管理及其恢复。
按类别细分解决方案
美利坚合众国的类别细分
法国的分类细目
印度的分类细目
英国的类别细分
收购和死亡
正如在任何活跃和不断增长的市场中一样,我们正在目睹公司的动向。当进行收购时,该解决方案要么集成到更大的产品中,要么作为更大公司支持的产品保留,并可以保留他们的名称。一些解决方案因为未知的原因而夭折。
在购买现有技能和功能的情况下,解决方案完全消失,并被集成到一个不再允许创建聊天机器人的产品中(例如 Sonos 在 2019 年购买的 Snips)。
有时,一个软件套件集成了一个聊天机器人解决方案,将那些特定的功能添加到托管它的平台中。一个例子是 2016 年被谷歌收购的 Speaktoit 的 API . ai[8],它成为了谷歌 DialogFlow,从而加入了谷歌云平台的功能。另一方面,法国公司 Recast.ai 于 2018 年被 SAP 收购,以便德国出版商可以在其 ERP 开发平台中添加向导解决方案[9]。
每年收购的解决方案数量
一家公司的死亡并不总是令人愉快的,尤其是对那些生活在其中的人来说,但它们是市场和适应法则的一部分。虽然很难确定解决方案的确切死亡日期(公司一般不再能够或不愿意沟通),但网站的消失往往预示着公司生命的终结。
在 31 个已确定的已故解决方案中,50%是美国的。2/3 的缺失解决方案不到 5 年。
根据公司创建年份(不包括收购和放弃)的废弃解决方案数量
注意:这些统计数据中不包括消失的并购解决方案。不再维护的开源解决方案也不计算在内。
为了好玩……
完成这些统计数据时,不可能不带一丝轻松。有趣的是,有一半的答案是以下列字母之一开头的:C A S B M I。
解答第一个字母后的解答数
6%的解决方案以“Bot”开头,3%以“Chat”开头。一种解决方案是用一个字母命名。
解决方案的前景如何?
以下是我对会话辅助解决方案未来的预测:
- 除非有技术突破,否则每年创造的新方案不会超过几十个。
- 新的通用解决方案将无法在数百种现有解决方案中生存。这些解决方案必须做出选择,成为特定领域的专家。
- 过于一般化的解决方案只能通过降低价格来应对,因此,为了生存,必须提高产量,只有在已经建立了基础的情况下,才能实现这种产量。
- 一些解决方案做出的设计选择将在未来对他们不利。他们将不得不进行深刻的变革,否则将不得不失败。
- 解决方案必须达到 4 级复杂性,从而允许对话方在同一个接口中重用几个不同的业务域。为了找出这意味着什么,我邀请你阅读我关于对话复杂性的文章 。
- 这些解决方案目前使用的语言处理技术已经成熟,并允许通过合理数量的示例获得良好的识别率(意图检测和实体提取)。这些解决方案是成熟和稳健的,如今可以应对服务质量和稳健性的挑战。他们将不得不致力于分析,以帮助那些在改进工作中维护解决方案的人。
- 由于人工智能技术的进步,我们将看到模块或新解决方案的出现,它们将能够在不需要“手动”创建对话的情况下进行对话。
- 在未来的几年里,我们应该会看到企业合并、收购和企业死亡。市场肯定在增长,但不是所有的解决方案都能存活下来。收购应该允许还没有助手解决方案的出版商将对话解决方案集成到他们自己的解决方案中。
- 解决方案将不得不越来越多地管理其对话者的环境,以便提供越来越个性化的服务。
结论
创建按需会话助手的解决方案在短短几年内已经逐渐从阴影走向光明。随着大多数解决方案具有相同的基本功能,并试图通过相关功能脱颖而出,市场正在走向成熟。美国是出版商最多的国家,其次是法国和印度。这些公司大多不到 50 人,尤其是当他们只提供这种类型的解决方案时。电子商务领域是可以取代销售顾问并帮助用户选择的解决方案覆盖最多的领域。从市场上消失的解决方案中有 2/3 不到 5 年。
棘手的问题:“最好的解决方案是什么?”没有哪一个比所有其他的更好,但是有几个适合每个用例。为了能够在所有这些解决方案中进行选择,必须制定一个标准列表来快速筛选出十几个解决方案(例如,本地化、语言等)。).然后,必须应用第二个标准列表来得出 2-3 个解决方案。然后你需要测试它们,这样你就可以检查它们的整体性能,判断配置接口的质量。
参考文献
1]什么是 Google Duplex?有史以来最聪明的聊天机器人,解释-文章数字趋势https://www.digitaltrends.com/home/what-is-google-duplex/
2] A.L.I.C.E —维基百科—https://en . Wikipedia . org/wiki/Artificial _ language _ Internet _ Computer _ Entity
3]http://www.ai.sri.com/project/CALO CALO SIRI 项目—地点—
[4]不要读我——a . l . I . c . e .和 AIML【https://www.mediensprache.net/archiv/pubs/2760.html 文档
⑸Pandora bots 2002 年 10 月—互联网存档-https://web . Archive . org/web/20021001074218/http://www . Pandora bots . com:80/Pandora
6]2005 年 11 月 Pandorabots 店铺菜单https://web . archive . org/web/20051127022134/http://www . Pandora bots . com:80/bot master/en/store . html
7] Sonos 收购专注隐私的语音助手 Snips—https://www . the verge . com/2019/11/21/20975607/Sonos-buys-Snips-ai-voice-assistant-privacy
[8] 谷歌收购 API . ai—TechCrunch-www . TechCrunch . com/2016/09/19/Google-acquisites-API-ai-a-company-helping-developers-build-bots-that-parent-dark-to-talk/
[9] SAP 加大在法国推动创新的承诺—https://news . SAP . com/2018/01/SAP-powers-Innovation-France-acquires-reca stai/
多重比较问题概述
本文通过介绍相关问题、描述可能的修正以及使用 python 代码展示一个可视化示例,对多重比较问题进行了概述。
2012 年, IgNobel 奖被授予了一项对一条死鲑鱼的功能磁共振成像研究[1],因为在对体素进行多次测试后,他们在一条死鲑鱼的大脑中发现了显著的活动。
这项研究是所谓多重校正问题的一个例子,在维基百科中定义为“当一个人同时考虑一组统计推断或推断基于观察值选择的参数子集时出现的问题。换句话说,这是在同一实验中进行大量统计测试时出现的问题,因为我们做的测试越多,获得至少一个具有统计显著性的测试的概率就越高。
在对死亡鲑鱼的研究中,作者研究了典型 fMRI 体积中 130,000 个体素的大脑活动。由于大量的测试,获得至少一个假阳性的概率几乎是确定的(正如它发生的那样)。
因此,当运行多个测试时,意识到这个问题是很重要的。因此,为了警告数据科学家,本文旨在:
- 讲授如何根据α和检验次数计算两组间获得统计显著性的概率。
- 呈现多个比较校正。
- 使用 python 代码运行实验并显示结果。
1。根据α和测试次数计算两组间获得统计显著性的概率的公式
这个概率被称为家族错误率 (FWER),其公式为:
其中“α”是单独测试的α水平(例如 0.05),而“m”是测试次数
该错误率表示在执行多个假设测试时做出一个或多个错误发现的概率。
如果我们运行一个测试(α = 0.05)来评估两组之间是否有统计学显著性差异,则 FWER 为:
然而,如果我们运行相同的测试六次,FWER 将不再是 5%,而是增加到大约 26%。
图 1 显示了根据α和测试次数的 FWER 图。
图一。对于不同的α值,FWER 或 I 型错误率如何随着测试次数的增加而增加的图表。来源:作者照片
2。多重比较校正
有不同的方法可以防止这个问题发生。本文介绍了三种多重比较校正:Bonferroni、Bonferroni-Hold 和 idák。
Bonferroni 校正是最简单和最保守的方法,它将整组比较的α值设置为单个测试的α值除以执行的测试次数。
其中“α”是单个试验的α水平,“m”是进行试验的次数
“α”是一个新的阈值,需要达到该阈值才能将单个测试归类为显著性。
Bonferroni 方法的代价是,通过防止假阳性错误,无法拒绝一个或多个假零假设的风险增加了。因此,该另一种方法通过将获得的 p 值从最低到最高排序并将它们与α/m 到α的标称α水平进行比较来改进上述方法
最低 p _ value
该方法还定义了一个新的α'来达到。该阈值使用 FWER 和测试次数来定义。
其中“FWER”是家族误差率,“m”是测试次数
3。多重比较问题及例题纠正
本例旨在通过比较两个具有不同平均值( rvs1 为 5,rvs2 为 6.5)和标准偏差( rvs1 为 10, rvs2 为 8)的正态分布( rvs1 和 rvs2 )与 100 个具有类似于 rvs1 的平均值和标准偏差的正态分布来说明上述所有术语
常识告诉我们 rvs1 应该没有统计学意义,但是 rvs2 应该有统计学意义。
导入 Python 库
用随机数创建两个正态分布。rvs1 的平均值为 5,rvs2 的平均值为 6.5。rvs1 的标准偏差为 10,rvs2 的标准偏差为 8
图二。左边是正态分布 rvs1 的图。右边是正态分布 rvs2 的图。
t 检验分析功能:
Bonferroni 校正功能:
Bonferroni-Hold 校正功能:
idák 校正功能:
通过 rvs1 和 rvs2 运行上述四个函数的代码。对于本实验,α为 0.05。
结果是:
表 1
表 1 中的数字表示具有统计显著性的测试次数。
正如所观察到的,t 检验结果表明 rvs1 和 rvs2 在统计上是显著的,无论所有的校正方法如何显示 rvs2 是唯一显著的分布。
如果你喜欢这篇文章,请考虑 订阅 。你将获得我所有的内容+所有其他来自牛逼创作者的文章!
参考文献
[1] Craig M. Bennett 等人,大西洋鲑鱼死后物种间视角的神经相关性:适当多重比较校正的论证 (2009),《偶然发现和意外结果杂志》。
PEP 8 风格指南概述
让您的 Python 代码具有风格。
ython Enhancement Proposal 8 或 PEP 8 是一个全面的 Python 代码样式指南。PEP 8 的目标是将所有 Python 集合在一个样式指南下。这增加了 Python 代码的可读性和整体理解。PEP 8 并不意味着在任何情况下都要遵循。你会遇到不适用的代码,如果是这样,你可能需要暂时脱离风格指南。关键是尽可能使用风格指南。它将帮助你和其他所有看到你的代码的人阅读和处理它。我会涵盖我认为最重要的领域。我不会讨论一些领域和其他领域,我可能只是略读一下。我真的推荐完整阅读 PEP 8,因为这个指南更像是一个快速概览。为了真正理解并获得更深入的解释,以及我选择不包含在本文中的部分。PEP 8 中我将复习的部分如下:
- 代码布局
- 用线串
- 空白
- 尾随逗号
- 评论
- 命名规格
- 推荐
PEP 8 可在此处找到:
Python 编程语言的官方主页
www.python.org](https://www.python.org/dev/peps/pep-0008/)
代码布局
缩进:
- 4 个空格,虽然这取决于你的延续行,只要有某种形式的缩进。
- 您可以垂直排列括号中的换行元素,或者使用悬挂缩进。
# 4 space indent
def hello(var):
print(var)# vertical alignmentexample2 = function(first_var, second_var,
third_Var, fourth_var)# hanging indentexample3 = function(
first_var, second_var,
third_var, fourth_var)
- 您可以对太长或希望成为延续行的条件使用类似的工作流。您可以在两个字符的关键字后使用括号,这将允许在转到新行时自动缩进。这对于长条件语句很有用,比如一个
if
语句。对于嵌套语句,您可以选择没有额外的缩进,注释您的缩进细节,或者添加额外的缩进。 - 您可以将结束标点(大括号、中括号或圆括号)与最后一行的第一个字符或非空白的多行表达式的第一个字符对齐。
# last line, first character
new_list = [
'one', 'two', 'three',
'four', 'five', 'six'
]# first line, first character
new_list = [
'one', 'two', 'three',
'four', 'five', 'six'
]
制表符和空格
- 建议缩进时使用空格,而使用制表符是为了与使用制表符缩进的代码保持一致。
- Python 不允许在同一个代码中同时使用这两者。如果您正在转换混合了两者的 Python 2,请使用空格重做。
最大线路长度
- 最大的行长度应该是 79 个字符,虽然我发现这有时是限制性的,在那些情况下必须更长。在这种情况下,最多可以输入 99 个字符。
- 对于注释和文档字符串,应该使用 72 个字符,不能增加。
- 这有助于阅读 Python 代码并将其保存在编辑器、检查和调试工具中。
- 为了帮助你坚持下去,Python 有一个助手。您可以用括号将行括起来,从第一个关键字之后的所有内容开始,到下一个关键字之前结束。这是 PEP 8 建议的,它会根据正确的 Python 行样式格式自动换行。
- 也可以使用反斜杠,仅当圆括号换行不适用时,例如
assert
语句。
使用二元运算符换行
- 为了更好的可读性,你应该在二进制操作符之前换行,尽管在过去这是相反的,如果它们是一致的,这两者都是可以接受的。
空白行
- 在类定义之前和之后应该有两个空行。
- 方法定义前后都应该有一个空行。
- 您应该在代码中保守地使用空行来分隔函数组。
- 如果不同行之间只有一行代码相互独立,则不必包含空行。
- Python 使用 control-L (^L)换行符来表示空白。
源文件编码
- 代码应该使用核心 Python 3 发行版的 UTF-8(Python 2 的 ASCII ),并且不应该有声明。
- 除此之外的编码只应用于测试目的。
- 跳转到 PEP 3131 了解更多关于这项政策的信息。
- 标识符应该只使用 ASCII,如果可能的话,应该使用英文单词。
进口
- 导入通常没有空行分隔。
- 导入通常应该在不同的行上分开,除非使用
from
关键字。 - 导入属于代码的顶部,在注释和文档字符串之后,在全局变量和常量之前。
- 进口应该是这个顺序。
- 标准程序库
- 第三方
- 特定于本地/库。
5.推荐绝对导入,但是显式相对导入也很好。以不太冗长的为准。
6.从单独的类模块导入类。
7.除非必要,否则不应使用通配符(*
)。
8.模块级“dunders”是带有两个尾随下划线的名称。这些名称应该放在注释和文档字符串之后,但在导入之前。
9.from __future__
导入必须在除注释和文档字符串之外的任何代码之前。
用线串
- 字符串两边的单引号或双引号意思相同。你可以选择你更喜欢哪一个,但是要坚持,这样你就可以用你没有选择的替代来代替反斜杠。
- 三重引号应该使用双引号字符。检查一下 PEP 257 。
空白
避免尾随空白。
- 不要在你的表达式和语句中使用过多的空格。如果逗号、冒号和分号不在中括号、大括号或圆括号后面,则应该在逗号、冒号和分号后面有空格。
- 对于任何运算符,您都应该在运算符的两边使用空格。用于切片的冒号被视为二元运算符,它们之间不应该有任何空格。
- 当调用函数
function()
时,函数旁边应该有不带空格的括号。 - 索引或切片时,括号应直接紧挨着集合,没有空格
collection[‘index’]
。 - 不建议使用空格来排列变量值。
- 当可选选项可用时,请确保与您选择的格式一致。
尾随逗号
- 唯一需要尾随逗号的时候是在创建单个元素元组的时候。
- 如果您使用尾随逗号,请用括号将它们括起来。
- 尾部逗号经常在版本控制中使用,用来详细说明以后将要扩展的区域。
评论
- 确保您的注释有意义,并且对阅读代码有用。适得其反的注释可能会损害代码的可读性。
- 更新代码时,请确保更新您的注释。
- 确保你的评论对其他 Python 程序员来说容易理解。
- 块注释是一段或多段单行注释,以每行的结束标点结束。他们应该以
#
开头,然后是空格。同样,块注释的缩进量应该与它们将要进入的代码的缩进量相同。用一行没有任何内容的注释来分隔段落。 - 在多行注释中,在句尾使用两个空格,除了在最后一句后只使用一个空格。
- 行内注释是跟在同一行代码后面的注释。保守地使用行内注释。在您的代码后面,它们应该至少由两个空格分隔。只有在必要时才使用它们。
- 文档字符串或文档字符串确实如其所述。它们为模块、函数、类和方法提供文档。对于以下所有内容,您都应该有 Docstrings。通过在文档串的开头和结尾使用三个
“””
引号来创建文档串。要了解更多关于文档字符串的信息,请看 PEP 257 。
命名规格
尽管 Python 库中的命名约定与 Python 有些不一致,但仍然建议使用当前的命名约定,除非您正在使用的已经有了不同的约定,然后使用该格式。
最重要的原则是你应该为你的 API 的公共方面反映用法而不是实现。
有多种命名方式可供选择。记得要有描述性。您也可以使用前缀将名称组合在一起。
b
B
lowercase
lower_case_underscore
UPPERCASE
UPPER_CASE_UNDERSCORE
CamelCase
mixedCase
Cap_words_Underscore # not recommended
4.规范的命名约定
- 单前导下划线:弱,除非内部使用,否则不推荐使用。
- 单结尾下划线:用于避免 Python 关键字的问题。
- 双前导下划线:用于命名类属性。
- 双前导和尾随下划线是用户名称空间中的“神奇”对象或属性。
要避免的名字:
# try not to use.
l # lowercase L
O # uppercase o
I # uppercase i
ASCII 兼容性:
- 标准库要求标识符与 ASCII 兼容。
包和模块名称:
- 如果可能的话,包和模块应该有小写和简短的名字。
- 模块可以有下划线。
- 包不应有下划线。
- 如果一个模块在 C 或 C++中,并且与一个 Python 模块相关联,那么它会创建一个更高的接口,并且可以用一个前导下划线来命名。
类名:
- 使用大写单词的惯例
WordExample
。 - 如果函数有很好的文档记录,并且主要用于可调用,那么您可以使用函数命名约定。
- 内置名称通常是一个单词或两个单词长。他们也只对异常和内置常量使用大写单词约定。
类型变量名称:
- 类型变量应该使用大写字母约定和简称。
- 后缀
_co
用于具有协变行为的变量。 - 后缀
_contra
用于具有逆变行为的变量。
异常名称:
- 使用类命名约定。
- 后缀
Error
用于出错的异常名。
全局变量名称:
- 遵循函数命名约定。
__all__
机制应该用来防止由from M import *
引起的全局变量或者像前缀globals
一样使用。
功能&变量名:
- 函数和变量应该是带下划线的小写字母。
- 如果已经在使用混合案例风格,您可以使用它。
函数&方法参数:
- 包含
self
作为即时方法的第一个参数。 - 包含
cls
或类方法的第一个参数。 - 如果需要,最好使用尾随下划线,而不是缩写。
方法名&实例变量:
- 使用函数命名约定。
- 对非公共方法和实例变量使用前导下划线。
- 如有必要,您可以使用两个前导下划线,以使用 Python 的名称 mangling。
常量:
- 带下划线的大写命名约定。
继承:
- 确保您的类的属性是公共的或非公共的。
- 非公共属性不是为第三方设计的。
- “私有”是 Python 中使用的一个术语。
- “子类 API”(又名。“受保护”)。旨在继承。基类。
- 公共属性=没有前导下划线,除非关键字冲突。
- 只公开公共数据属性的属性名。
- 子类化的类可以用双前导下划线来命名,使用 Python 的名称转换器。
5.公共和内部接口
- 用户应该能够区分公共接口和内部接口。
- 如果一个接口被文档化,它就被认为是公共的,除非文档中另有说明。
- 未记录的接口是内部接口。
- 模块应该使用
__all__
来声明公共 API。如果__all__
设置为空列表,表示没有公共 API。 - 内部接口的单前导下划线。
- 如果任何名称空间是内部的,那么接口也是内部的。
- 导入是一个实现细节。
推荐
- 编写代码,以免对 Python 的其他实现产生负面影响。
is
或is not
来比较单件。is not
而不是not is
。- 将 lambda 表达式绑定到标识符时,使用
def
而不是赋值。 - 对于例外情况,使用
Exception
代替BaseException
。 - 确保您的异常链接被正确使用。
- 尽可能具体说明例外情况。
- 使用显式名称绑定语法。
- 对操作系统错误使用显式异常层次结构。
- 当使用
try
和except
时,在需要包装在try
块中的区域周围保持代码紧凑。 - 在本地资源上使用
with
语句。 - 确保正确使用
return
语句。要么有return
表情,要么没有。 - 与字符串模块相对的字符串方法。
- 使用方法
.startswith()
和.endswith()
进行字符串前缀和后缀切片。 - 使用
isinstance(<item>, <item>)
而不是if type(<item>) is type(<item>)
。 - 空序列被视为
False
。 - 不要用
==
来做True
False
的比较。 - 流控制语句应该在
finally
代码块中。
函数注释
- 功能注释见 PEP 484 。
可变注释
- 变量注释见 PEP 526 。
结论
对于任何 Python 程序员来说,PEP 8 都是一个不可思议的资源。如果使用正确,它将保持你的代码可读性和 PEP 8 的风格参数。同样,这只是对 PEP 8 的一个简要概述,如果你想真正了解这个令人惊叹的样式指南,我鼓励你在 Python 网站或 GitHub 上阅读整个内容。我希望你喜欢阅读和快乐编码!
Python 编程语言的官方主页
www.python.org](https://www.python.org/dev/peps/pep-0008/) [## python/peps
标题:Python 代码版本风格指南:\(Revision\) Last-Modified: \(Date\)作者:吉多·范·罗苏姆,巴里华沙…
github.com](https://github.com/python/peps/blob/master/pep-0008.txt)
TensorFlow 2.0 使用概述
一个想法的显现。
透明 tensor flow Logo Png@pngkit.com
Tensorflow 已经成为最受欢迎的深度学习库之一。程序员、数据科学家和研究人员可以使用它,通过使用 API 或从头开始编写东西来创建开箱即用的模型。它和你的需求一样抽象。
解决机器学习问题所需的基本步骤序列包括拥有数据集、创建模型、训练和评估模型以及最终部署它。我们将详细讨论这些步骤。不过,在此之前,让我们讨论一些与 TensorFlow 2 相关的有用更新。
急切的执行
TensorFlow 2 默认启用了急切执行。在 TensorFlow 的早期版本中,即使是打印张量这样最简单的任务也要创建一个会话。急切执行使代码更加直观。
打印张量 z 值的旧方法。它不是直观的。
更新更直观的方式打印张量(TF2)。
比如 Numpy
Numpy 是一个流行的 Python 库,专注于涉及矩阵的数学运算。由于急切的执行,TensorFlow 2 感觉更像 numpy。张量上的“numpy”方法也允许张量转换成 numpy 数组。
TensorFlow 更像 Numpy。
tf .函数装饰
这个装饰器加速了函数在后续调用中的执行。它允许使用 TensorFlow 使用的底层图模型的性能优势。装饰器告诉 TensorFlow 跟踪函数的计算并提高性能。
@ tf.function decorator 用来提升性能。
清洁剂 API
TensorFlow API 已经过清理,其中添加了 tf.keras.layers 和 TF . keras . loss 等命名空间。为了更好地组织,许多命名空间都被重命名,例如 tf.mod 被重命名为 tf.math.mod。少数端点(如 tf.rint)已被弃用。有关所有变更的详细列表,请参考 TensorFlow 名称空间。
数据设计
随着时间的推移,机器学习社区已经整合了许多有用的数据集,其中一些可以与深度学习库一起使用。很明显,您可以使用自己的数据并创建一个输入管道来进行训练。例如,“flow_from_directory”可用于高效地读取图像并动态地对其进行扩充。也可以使用 CSV 等文件中存储的数据。然而,在 TensorFlow 2 中,在数据集方面有两个选项—
使用 Keras 数据集
Keras datasets 提供回归数据集(如 boston housing)、图像分类数据集(如 mnist)和情感分类数据集(如 imdb)。这些数据集以 numpy 格式提供,并适合内存。
从 keras 数据集导入 MNIST 数据集。文档 tf.keras.datasets 。
使用张量流数据集
Tensorflow 数据集是使用数据的更快、更有效的方式。这是一种高性能的数据集格式。使用 TensorFlow 数据集读取的数据不是 numpy 格式,而是 tf.data 格式。它由大量面向研究的数据集组成,这些数据集被分类为音频、图像、图像分类、对象检测、结构化、摘要、文本、翻译和视频。这些数据集更加真实。
使用张量流数据集导入 MNIST 数据集。阅读数据集 TensorFlow 数据集的完整目录。 文档 张量流 _ 数据集。
模型设计
TensorFlow 2 已经推荐使用 Keras 作为其官方 API。在 Tensorflow 中设计模型就像插入内置层一样简单,从零开始为研究应用程序编写一切。
顺序 API
顺序 API 用于制作线性模型,一层一层的堆叠在另一层的顶部。使用 add()方法将不同的层(如 Dense、Flatten 和 Conv2D)添加到模型中。一旦你创建了你的模型,你就可以看到模型的概要。顺序 API 是创建模型最常用的 API。基本思想是堆叠一堆层来创建一个模型,该模型随后被编译和进一步训练以得出推论。
顺序卷积神经网络。
模型摘要。文档TF . keras . sequential .
功能 API
顺序 API 建立线性模型,而函数 API 用于建立非线性模型。这些模型的架构类似于有向图(DAG)。这些模型具有接受多个输入、产生多个输出和共享层的能力。
使用函数式 API 创建的模型。
用图形表示模型。文档 : Keras 功能 API
子类
子类化允许从头开始写所有的东西。它对创建模型的各个方面提供了更好的控制。框架给出了一个类,其中构造函数定义了要使用的层,调用方法将这些层按顺序放在一起。如果您想了解事情在幕后是如何工作的,推荐使用这种方法。
init 方法定义层。call 方法定义了如何使用已定义的层。您可以打印第 12 行生成的“x”值。你可以得到 x 的值,并对它应用各种数学函数。文档 : 编写自定义图层和模型
培训设计
使用拟合方法
拟合是用于训练模型的最常用方法。它适用于使用上述任何策略创建的模型。当数据集很小并且适合内存时使用它。
在使用 fit 方法训练模型之前,模型被编译,在此期间为模型指定损失函数、优化器和度量。
使用拟合方法训练模型。文档 model.fit() 。
使用回调
各种图表用于在训练期间监控模型的进度。或者,可以使用回调来监控各种评估指标的状态,并做出决定,例如停止训练、定期保存模型、安排学习速率、可视化训练进度等。它们在训练期间的不同点被调用,例如一个时期的开始、一批的结束等等。回调作为列表传递给 fit 方法。
EarlyStopping 的回调示例,它根据某个条件停止训练。文档 回调。
使用 Fit 生成器
这是训练模型的另一种方式。当数据集太大而无法放入内存时,使用拟合生成器方法。fit generator 的一个常见用例是从目录中读取图像,同时对它们应用数据扩充。
fit_generator()的示例。这些图像是从/tmp/data(第 3 行)中读取的,batch_size 为 20(第 16 行)。您还可以在从目录流动时应用放大,如缩放和剪切。文档 : fit_generator
批量使用列车
分批训练在分批水平上工作。它将单个批次作为输入,并在执行反向传播后更新模型参数。它允许我们在每批之间做额外的事情。一个用例是根据您可能稍后收集的一批新样本来更新预训练模型。它也用于 LSTM,其中 LSTM 的状态通常需要在每个数据系列之后复位。
批量训练的一个例子。文件 : 批量培训
编写自定义训练循环
在训练模型时,fit 和 fit_generator 函数抽象了许多细节。但是,如果需要,TensorFlow 2 允许您使用“GradientTape”查看网络的梯度。您还可以看到权重如何使用这些渐变进行更新。基本上,它可以让你更好地控制如何更新权重。讨论自定义训练循环的完整示例可能会让人不知所措。这里已经讨论过的一个详细例子。
分布式培训
在训练深度学习模型时,可扩展性至关重要。TensorFlow 2 允许在不对代码进行重大更改的情况下扩大学习任务的规模,以加快学习速度。训练过程可以扩展到多个 GPU、TPU 和机器。定义了多种策略来满足不同的用例。例如,MirroredStartegy 支持在一台机器上对多个 GPU 进行训练,而 MultiWorkerMirroredStrategy 支持在多台机器上进行同步分布式训练,每台机器都可以有多个 GPU。
使用 MirroredStrategy 的示例。代码中只添加了第 4 行和第 6 行,以支持分布式培训。其中的函数是分布式感知的。文档 : tf.distribute
序列化
一旦模型被训练,它需要被保存以便在生产中使用。在 TensorFlow 2 中,保存模型已使用 SavedModel 格式标准化,该格式保存完整的模型及其权重。SavedModel formal 使使用 TensorFlowJS、TensorFlowLite 或 TensorFlow Serving 部署模型变得更加容易。
使用 saved_model 保存张量流模型。文档: 已保存的模型
加载模型以备将来使用。
部署
使用 TensorFlow 服务
TensorFlow 服务允许机器学习模型作为 REST 或 gRPC(远程过程调用)客户端 API。通过提供 docker 文件,TensorFlow 中的服务变得更加容易。这里已经讨论了一个实现。
使用 TensorFlow Lite
移动和物联网设备也可用于部署 TensorFlow 模型。然而,这些设备具有诸如功耗和电池寿命的限制。TensorFlow 提供了一种方法,用于将最初训练的模型转换为它们的轻量级版本,这些版本可以部署在具有功率和处理约束的设备上。它是一个适用于 Android、iOS 和嵌入式系统的轻量级解决方案。
将 SavedModel 转换为较简单的格式。文档 : TFLite
使用 TensorFlowJS
TensorFlowJS 已经能够使用 NodeJS 在浏览器或服务器端直接使用机器学习。一旦保存了模型,就可以使用 TensorFlowJS 轻松地部署它。该模型首先被转换成 TensorFlowJS web 格式,然后被加载用于部署。
用于将 SavedModel 格式转换为 TensorFlow 的脚本。JS web 格式。文档 : 导入一个模型 TensorFlowJS
导入转换后的模型并将其用于预测。
结论
在 tf.keras 命名空间下整合不同的优化器、度量、损失函数和层之后,我能够在 TensorFlow 2 中编写更一致的代码。急切执行简化了调试。我现在可以使用 python 的标准 print 函数打印出来,而不是创建一个会话来获取张量的值。tf.function decorator 的加入使得使用标准 python 编写的函数能够通过 TensorFlow 进行性能优化。我可以使用 tf.distribute 提供的策略轻松调整我的模型的训练,而无需对代码进行重大更改。
此外, TensorFlow hub 允许我通过使用迁移学习来重用机器学习模型,从而加快训练过程。总的来说,TensorFlow 已经成长为一个开发者友好而强大的人工智能库。
探索新型冠状病毒的 R 包
冠状病毒(CoV)是一个大的病毒家族,可导致从普通感冒到更严重疾病的疾病,如中东呼吸综合征(MERS-CoV)和严重急性呼吸综合征(SARS-CoV)。一种新型冠状病毒(nCoV)是一种新的毒株,此前尚未在人类中发现。
最近发现南方医科大学生物信息学教授于广创的一篇博文,讲的是一个 R 包,里面包含了中国乃至全世界最新的 nCov 数据之一。在过去的几天里,我一直在把这个包从中文翻译成英文,以便让每个人都更容易理解。
*注:这篇博文是对于博士的原帖的尝试性英文翻译。我会在页面底部用中文链接他的博文。
第一部分—快速入门
首先,您可以通过在 R 中运行以下命令来轻松安装:
remotes::install_github("GuangchuangYu/nCov2019")
要获取最新数据,可以用get_nCov2019()
载入。
**library**(nCov2019)
x <- get_nCov2019(lang='en')
确保您包含了参数lang='en'
,否则,数据默认为中文(如果您能阅读中文,这没问题)。
如果打印数据,会显示中国确诊病例总数,以及最新更新时间:
> x
China (total confirmed cases): 40235
last update: 2020-02-10 15:12:35
此数据收集自腾讯,athttps://news.qq.com/zt2020/page/feiyan.htm,包含冠状病毒的最新公开信息之一。
全局数据
要查看全局数据,您可以运行代码x['global', ]
:
> x['global', ]
name confirm suspect dead heal showRate deadRate healRate
1 China 40235 23589 909 3371 FALSE 2.26 8.38
2 Japan 96 0 0 1 FALSE 0.00 1.04
3 Singapore 43 0 0 2 FALSE 0.00 4.65
4 Thailand 32 0 0 8 FALSE 0.00 25.00
5 Republic of Korea 27 0 0 3 FALSE 0.00 11.11
6 Malaysia 18 0 0 3 FALSE 0.00 16.67
7 Australia 15 0 0 5 FALSE 0.00 33.33
8 Germany 14 0 0 0 FALSE 0.00 0.00
9 Vietnam 14 0 0 3 FALSE 0.00 21.43
10 United States USA 12 0 0 1 FALSE 0.00 8.33
11 France 11 0 0 0 FALSE 0.00 0.00
12 Canada 7 0 0 0 FALSE 0.00 0.00
13 United Arab Emirates 7 0 0 0 FALSE 0.00 0.00
14 United Kingdom 4 0 0 0 FALSE 0.00 0.00
15 Italy 3 0 0 0 FALSE 0.00 0.00
中国省市数据
因为数据来源主要集中在中国,你有能力真正深入挖掘中国的案例。比如你有能力看到四川某个城市确诊病例数。
通过x[]
,您可以轻松查看中国各省的数据。
> x[]
name confirm suspect dead heal showRate deadRate healRate
1 Hubei 29631 0 871 1795 TRUE 2.94 6.06
2 Guangdong 1151 0 1 148 FALSE 0.09 12.86
3 Zhejiang 1092 0 0 215 FALSE 0.00 19.69
4 Henan 1073 0 6 181 FALSE 0.56 16.87
5 Hunan 879 0 1 201 FALSE 0.11 22.87
6 Anhui 830 0 3 89 FALSE 0.36 10.72
7 Jiangxi 771 0 1 102 FALSE 0.13 13.23
8 Jiangsu 492 0 0 80 FALSE 0.00 16.26
9 Chongqing 468 0 2 61 FALSE 0.43 13.03
10 Shandong 466 0 1 64 FALSE 0.21 13.73
11 Sichuan 405 0 1 79 FALSE 0.25 19.51
12 Beijing 337 0 2 44 FALSE 0.59 13.06
13 Heilongjiang 331 0 7 20 FALSE 2.11 6.04
14 Shanghai 299 0 1 48 FALSE 0.33 16.05
15 Fujian 261 0 0 36 FALSE 0.00 13.79
如果您想获得更精细的数据,您可以进入每个省,将数据分解到各个城市。例如,如果您想查看湖北省内的案例,您可以使用x[1,]
或x['Hubei',]
。
> x['Hubei', ] # replace Hubei with any province
name confirm suspect dead heal showRate deadRate healRate
1 Wuhan 16902 0 681 1044 TRUE 4.03 6.18
2 Xiaogan 2541 0 33 81 TRUE 1.30 3.19
3 Huanggang 2252 0 45 189 TRUE 2.00 8.39
4 Suizhou 1049 0 10 23 TRUE 0.95 2.19
5 Jingzhou 1045 0 15 46 TRUE 1.44 4.40
6 Xiangyang 1019 0 9 42 TRUE 0.88 4.12
7 Huangshi 805 0 3 67 TRUE 0.37 8.32
8 Yichang 749 0 8 43 TRUE 1.07 5.74
9 Ezhou 725 0 24 48 TRUE 3.31 6.62
10 Jingmen 641 0 20 63 TRUE 3.12 9.83
11 Xianning 507 0 4 44 TRUE 0.79 8.68
12 Shiyan 481 0 0 46 TRUE 0.00 9.56
13 Xiantao 416 0 7 16 TRUE 1.68 3.85
14 Tianmen 217 0 10 10 TRUE 4.61 4.61
15 Enshi 187 0 0 24 TRUE 0.00 12.83
当然,也可以将这些数据用于可视化。这里有一个安徽的例子。
library(forcats)
library(ggplot2)
d = x['Anhui',] # replace Anhui with any province
d$confirm=as.numeric(d$confirm)
d$name = fct_reorder(d$name, d$confirm)ggplot(d, aes(name, confirm)) +
geom_col(fill='steelblue') + coord_flip() +
geom_text(aes(y = confirm+2, label=confirm), hjust=0) +
theme_minimal(base_size=14) +
scale_y_continuous(expand=c(0,10)) +
xlab(NULL) + ylab(NULL)
每日数据
您已经在上面看到了如何获得总的累积数据,但是如果您有兴趣查看新添加的案例的数量呢?一种方法是使用参数by='today'
。要查看中国所有省份新增的数量,您可以运行以下命令:
> head(x[by='today'], 10)
name confirm suspect dead heal isUpdated
1 Hubei 2618 0 0 0 TRUE
2 Guangdong 31 0 0 0 TRUE
3 Zhejiang 29 0 0 0 TRUE
4 Henan 40 0 0 0 TRUE
5 Hunan 41 0 0 0 TRUE
6 Anhui 51 0 0 0 TRUE
7 Jiangxi 32 0 0 0 TRUE
8 Jiangsu 24 0 0 0 TRUE
9 Chongqing 22 0 0 0 TRUE
10 Shandong 31 0 0 0 TRUE
类似地,要获得更细粒度的视图,您可以通过运行以下命令来获得数据:
> x['Hubei', by='today'] # replace Hubei with any province
name confirm suspect dead heal isUpdated
1 Wuhan 1921 0 0 0 TRUE
2 Xiaogan 105 0 0 0 TRUE
3 Huanggang 115 0 0 0 TRUE
4 Suizhou 65 0 0 0 TRUE
5 Jingzhou 48 0 0 0 TRUE
6 Xiangyang 57 0 0 0 TRUE
7 Huangshi 52 0 0 0 TRUE
8 Yichang 45 0 0 0 TRUE
9 Ezhou 89 0 0 0 TRUE
10 Jingmen 12 0 0 0 TRUE
11 Xianning 14 0 0 0 TRUE
12 Shiyan 14 0 0 0 TRUE
13 Xiantao 37 0 0 0 TRUE
14 Tianmen 20 0 0 0 TRUE
15 Enshi 21 0 0 0 TRUE
16 Qianjiang 3 0 0 0 TRUE
17 Shennongjia 0 0 0 0 TRUE
18 Location TBD 0 0 0 0 TRUE
*注:第二部分中关于每日/历史数据的更多细节。
每日数据摘要
要获得每日数据的累积摘要,可以使用x
上的summary
函数。
> summary(x)
confirm suspect dead heal deadRate healRate date
1 41 0 1 0 2.4 0.0 01.13
2 41 0 1 0 2.4 0.0 01.14
3 41 0 2 5 4.9 12.2 01.15
4 45 0 2 8 4.4 17.8 01.16
5 62 0 2 12 3.2 19.4 01.17
6 198 0 3 17 1.5 8.6 01.18
7 275 0 4 18 1.5 6.5 01.19
8 291 54 6 25 2.1 8.6 01.20
9 440 37 9 25 2.0 5.7 01.21
10 571 393 17 25 3.0 4.4 01.22
11 830 1072 25 34 3.0 4.1 01.23
12 1287 1965 41 38 3.2 3.0 01.24
13 1975 2684 56 49 2.8 2.5 01.25
14 2744 5794 80 51 2.9 1.9 01.26
15 4515 6973 106 60 2.3 1.3 01.27
类似地,如果您想查看新的每日案例,您可以使用today
参数:
> summary(x, by="today")
confirm suspect dead heal deadRate healRate date
1 77 27 0 0 0.0 0.0 01.20
2 149 53 3 0 2.0 0.0 01.21
3 131 257 8 0 6.1 0.0 01.22
4 259 680 8 6 3.1 2.3 01.23
5 444 1118 16 3 3.6 0.7 01.24
6 688 1309 15 11 2.2 1.6 01.25
7 769 3806 24 2 3.1 0.3 01.26
8 1771 2077 26 9 1.5 0.5 01.27
9 1459 3248 26 43 1.8 2.9 01.28
10 1737 4148 38 21 2.2 1.2 01.29
11 1982 4812 43 47 2.2 2.4 01.30
12 2102 5019 46 72 2.2 3.4 01.31
13 2590 4562 45 85 1.7 3.3 02.01
14 2829 5173 57 147 2.0 5.2 02.02
15 3235 5072 64 157 2.0 4.9 02.03
如果您想要可视化累积汇总数据,示例图如下:
library(ggplot2)
ggplot(summary(x), aes(as.Date(date, "%m.%d"), as.numeric(confirm))) +
geom_col(fill='firebrick') + theme_minimal(base_size = 14) +
xlab(NULL) + ylab(NULL) +
labs(caption = paste("accessed date:", time(x)))
第二部分—历史数据
第一部分只能显示最新的数据,但大多数人真正关心的是每天的历史数据。
如果要分析一些详细的历史数据怎么办?不要害怕, *load_nCov2019()*
是来救援的。
> x <- load_nCov2019(lang='en')
> x
nCov2019 historical data
last update: 2020-02-07
同样,如果你想使用中文版本,你可以删除lang='en'
的说法。
注:该数据仅包含中国的病例。不幸的是,您将无法获得全球历史数据。
中国的历史数据
使用与get_nCov2019()
相同的方法,我们可以使用[
查询所有省级明细数据。
> head(x[][c(1:6, 9:11)])
province city time cum_confirm cum_heal cum_dead confirm dead heal
1 Shanghai Shanghai 2020-02-08 292 41 1 NA
2 Yunnan Yunnan 2020-02-08 140 17 0 NA
3 Yunnan Kunming 2020-02-08 41 6 0 NA
4 Yunnan Xishuangbanna 2020-02-08 15 2 0 NA
5 Yunnan Yuxi 2020-02-08 14 2 0 NA
6 Yunnan Zhaotong 2020-02-08 12 1 0 NA
我们可以只选择累积的和新添加的数据。相关列是province, city, time, cum_confirm, cum_heal, cum_dead, confirm, dead, heal
,所以x['Hubei', c(1:6,9:11)]
就足够了。
中国各省市的详细信息
与上面类似,如果您想更深入地获取特定于省份的数据,那么您只需要包括省份名称:
> head(x['Hubei', c(1:6, 9:11)]) # replace Hubei with any province
province city time cum_confirm cum_heal cum_dead confirm dead heal
250 Hubei Wuhan 2020-02-08 14982 877 608 NA
251 Hubei Xiaogan 2020-02-08 2436 45 29 NA
252 Hubei Huanggang 2020-02-08 2141 137 43 NA
253 Hubei Jingzhou 2020-02-08 997 34 13 NA
254 Hubei Xiangyang 2020-02-08 988 40 7 NA
255 Hubei Suizhou 2020-02-08 984 23 9 NA
如果您想更深入地挖掘特定于城市的数据,那么您可以在省内指定一个city
。例如,如果您想查看武汉的数据,您可以执行以下操作:
> head(subset(x['Hubei',], city == "Wuhan"))[c(1:6, 9:11)]
province city time cum_confirm cum_heal cum_dead confirm dead heal
250 Hubei Wuhan 2020-02-08 14982 877 608 NA
612 Hubei Wuhan 2020-02-07 13603 698 545 NA
972 Hubei Wuhan 2020-02-06 11618 535 478 NA
1084 Hubei Wuhan 2020-02-05 10117 432 414 NA
1464 Hubei Wuhan 2020-02-04 8351 369 362 1967 49 65
1976 Hubei Wuhan 2020-02-03 6384 303 313 1242 48 79
然后,您可以将这些数据用于可视化。例如:
library(ggplot2)
require(ggrepel)d <- x['Anhui',] # replace Anhui with any provinceggplot(d, aes(time, as.numeric(cum_confirm), group=city, color=city)) +
geom_point() + geom_line() +
geom_text_repel(aes(label=city), data=d[d$time == time(x), ], hjust=1) +
theme_minimal(base_size = 14) + theme(legend.position='none') +
xlab(NULL) + ylab(NULL)
中国的汇总结果
与get_nCov2019()
类似,您也可以对数据调用summary()
函数。
> head(summary(x)[,1:5])
province time cum_confirm cum_heal cum_dead
1 Shanghai 2020-02-07 281 30 1
2 Yunnan 2020-02-07 138 12 0
17 Inner Mongolia 2020-02-07 52 5 0
29 Beijing 2020-02-07 315 34 2
30 Taiwan 2020-02-07 16 1 0
31 Jilin 2020-02-07 69 4 1
如果您想查看特定省份的汇总,您只需将省份名称添加到summary
中,如下所示:
> summary(x, 'Hubei')[,1:5]
province time cum_confirm cum_heal cum_dead
251 Hubei 2020-02-07 24953 1119 699
611 Hubei 2020-02-06 22112 818 618
723 Hubei 2020-02-05 19665 651 549
1103 Hubei 2020-02-04 16678 520 479
1615 Hubei 2020-02-03 13522 396 414
1792 Hubei 2020-02-02 11177 295 350
2325 Hubei 2020-02-01 9074 215 294
2482 Hubei 2020-01-31 7153 166 249
2820 Hubei 2020-01-30 5806 116 204
3452 Hubei 2020-01-29 4586 90 162
3673 Hubei 2020-01-28 3554 80 125
3803 Hubei 2020-01-27 2714 47 100
4225 Hubei 2020-01-26 1423 44 76
4488 Hubei 2020-01-25 1052 42 52
4710 Hubei 2020-01-24 729 32 39
这是另一个快速可视化的例子:
ggplot(summary(x, 'Hubei'), aes(time, as.numeric(cum_confirm))) +
geom_col()# or city-specific
# ggplot(subset(x['Hubei',], city == "Huanggang"), aes(time, as.numeric(cum_confirm))) + geom_col()
第三部分—地图绘制
世界地图
得到世界地图的一个情节真的很简单。只需要三行代码:
require(nCov2019)
x = get_nCov2019(lang='en')
plot(x)
如你所见,与其他地方相比,中国确诊病例的数量高得吓人。你现在可能会想,有没有一种方法可以分解中国的案例?当然可以,但是你必须先安装chinamap
,才能得到中国地图。
remotes::install_github("GuangchuangYu/chinamap")
安装后,您可以运行以下代码来查看中国各地的确诊病例。
require(chinamap)cn = get_map_china()
## translate province
cn$province <- trans_province(cn$province)plot(x, chinamap=cn)
*注意:为了给中国着色,省份必须如上翻译。
如果红色不适合你,你可以使用palette
参数随意改变它:
plot(x, chinamap=cn, palette="Purples")
中国地图
为了更好地了解中国的情况,你可以在情节中添加一个region = ‘china'
参数。我建议使用font.size=2
,这样省的文本就不会太大。
plot(x, region='china', chinamap=cn, font.size=2)
如果到目前为止你已经看完了所有的内容,非常感谢!这是我的第一篇博客,但绝对不是最后一篇。如果你正在寻找余博士的中文帖子,我会在本页底部链接它们。
任何评论、问题或总体反馈总是。请随时通过我的LinkedIn联系我。
Thank you Dr. Yu for the package, as well as allowing me to contribute. And special thanks to Tencent and 新一线城市研究所×8 点健闻 for making the data available in the first place.
于博士文章的链接:
VADER 简介
对我在 Spotify 上播放最多的歌曲进行半监督情感分析。
答几周前,我写了一篇文章,讲述如何通过几行代码获得任何 Spotify 播放列表的歌词。在过去的两年里,Spotify 进行了一场聪明的营销活动,它编辑了一份年度最佳 100 首歌曲的播放列表。这通常会在社交媒体上传播,因为人们会分享他们在过去 365 天里在淋浴时摇头晃脑和唱歌的内容。我认为这将是我尝试一些半监督情绪分析的完美播放列表,同时希望发现一些关于我自己的收听习惯的有趣事实。
nltk .情操.维德
价觉词典和情感推理机(VADER)
它是什么。
VADER 是nltk.sentiment
Python 库中的一个模块,它是专门为处理社交媒体环境中产生的文本而创建的,然而,它当然也可以处理源自其他上下文的语言。当被分析的数据未被标注时,VADER 能够检测出给定文本的情感极性(积极或消极)。在传统的情感分析中,算法有机会从标记的训练数据中学习。一个经典的例子是根据给定评论家的书面评论来预测电影评论的星级。星级将是目标变量,文本将是预测变量。
在歌词的情感分析中,我们没有任何标签。歌词没有按 0 到 10 分(0 为负面,10 为正面)评分。那么,VADER 如何判断市场情绪呢?
VADER 使用情感相关词汇词典来确定给定文本的整体情感。下面是词典结构的一个例子,每个单词都有一个配价等级:
VADER 利用亚马逊的机械土耳其人(Mechanical Turk)建立了这个标签化的词典,这是一个众包平台,向“众包工作者”支付报酬,让他们一起完成任务,从而产生了一种令人印象深刻的高效方法。
预处理。没有。
VADER 令人难以置信的是,它不需要大量的预处理工作。与 NLP 的一些有监督的方法不同,不需要预处理,例如记号化和词干化/词尾化。你几乎可以插入任何文本,它将决定情绪。
VADER 甚至聪明到能够理解非常规文本的化合价,包括表情符号(即:-()、大写(即 sad vs SAD)和扩展标点符号(即?vs???).这就是该模块如此擅长分析社交媒体文本的原因。此外,VADER 删除停止字自动,所以没有必要这样做你自己。
与 VADER 合作
我们可以在命令行中使用pip install nltk
在我们的设备上安装这个库。然后,我们需要使用下面截取的第一行代码将 VADER 导入到我们的编程环境中。
然后,我们可以初始化情感分析对象,并使用polarity_scores()
方法来确定字符串的情感。其输出是四个标准化的分数:
- { ' neu ':0–1 }—陈述的中立程度。
- { ' neg ':0–1 }—陈述的负面程度。
- { ' pos ':0–1 }—陈述的积极程度。
- { ' compound ':-1–1 }—陈述的总体情绪。
我的 2019 音乐品味
我们开始吧。在我去年播放最多的 100 首歌曲中,有 66 首歌词是我用我在之前的一篇文章中概述的方法获得的(我的音乐库中有很大一部分是电子版的,没有歌词元素)。
下面的图表显示了每首歌歌词中积极和消极的“数量”。积极情绪多于消极情绪的歌曲会有一个正的复合分数,因此会有积极的情绪,反之亦然。
令我惊讶的是,45 首(68%)歌曲被认为是积极向上的。在进行这种分析时,我预计我的大多数歌曲都会有负面情绪。
这很可能是因为一首歌的歌词显然没有描绘出全貌。例如,对“爱”有强烈感情的句子可能看起来是积极的,然而,在它们后面有悲伤的旋律,它们可能会坚定地属于悲伤的情歌类别。
展望未来,看看这些年来我的听力习惯是如何改变的会很有趣。不幸的是,Spotify 只向用户提供了过去两年中播放次数最多的 100 首歌曲的播放列表,但当有更多数据可用时,我认为可以进行一些有趣的分析。尤其是如果 Spotify 将自己对歌曲的评级包括在内,比如通过其 API 提供的“可跳舞性”和“活力”。
谢谢你读到这里!我希望您喜欢这个关于 VADER 的简短介绍,并可以继续在您自己的数据集上尝试它。我很想听听你在评论里想说些什么。如果你想直接联系我,请在 LinkedIn上给我留言。
Numpy 的终极备忘单
由 Unsplash 上的 Pietro Jeng 拍摄
日常工作所需的所有 Numpy 功能
Numpy 是一个开源的 Python 库。这个库对于使用 python 的数据科学家来说是必不可少的。其他一些重要的库,如 Pandas、Scipy,都是在 Numpy 库的基础上构建的。所以我决定做一个小抄。在这里,我包含了迄今为止我使用过的所有 Numpy 函数。我相信这些功能足以满足您作为数据科学家或数据分析师的日常工作需求。
我将从最基本的 Numpy 函数开始,慢慢向更高级的函数发展。但是使用 Numpy 很容易。你在这里找不到任何复杂的编码技巧。
Numpy 是什么?
在 Numpy 文档中,Numpy 是这样定义的:
NumPy 是 Python 中科学计算的基础包。这是一个 Python 库,它提供了一个多维数组对象、各种派生对象(如掩码数组和矩阵)以及一系列对数组进行快速操作的例程,包括数学、逻辑、形状操作、排序、选择、I/O、离散傅立叶变换、基本线性代数、基本统计操作、随机模拟等等。
我每天都使用这个图书馆。如果是 python 用户,大多数数据科学家都会这么做。它快速、易用、易懂、简单。我不想写太多关于它如何以及为什么这么好。因为当你阅读这篇文章的时候,你会亲眼看到。
我的目标是记录 Numpy 每天使用的方法。
如题,是 Numpy 指南。它也可以用作备忘单。如果您正在使用 Numpy 库,或者计划在将来使用,或者试图学习,这个页面可以成为您日常生活的一个很好的资源。
这些是这里将要涉及的主题:
- Numpy 数组基础
- 重复
- 数学
- 统计数字
- 初始化不同类型的数组
- 重新排列或重组数组
- 数组的索引和切片
- 添加行或列
- 追加、插入、删除和排序
- 随意
- 文件导入、保存和加载
开始吧!!
Numpy 数组基础
这部分是
我在整个练习中使用了一个 Jupyter 笔记本。第一个导入数字。
import numpy as np
制作一个 Numpy 数组。为此,我们需要传递一个 Python 列表。
输入:
a = np.array([1,2,3])
a
输出:
array([1, 2, 3])
在数组 a 中,我使用了所有的整数。现在,制作一个浮点数组:
输入:
b = np.array([[9.0, 10.0, 6.0], [6.0,1.0,7.0]])
b
输出:
array([[ 9., 10., 6.],
[ 6., 1., 7.]])
让我们试着做一个既有整型又有浮点型的数组:
输入:
np.array([1, 3.0, 0.004, -2])
输出:
array([ 1\. , 3\. , 0.004, -2\. ])
注意,Numpy 自动将整数转换成浮点数!
找出数组 a 和 b 的维数:
输入:
a.ndim
输出:
1
输入:
b.ndim
输出:
2
数组“a”是一维数组,数组 b 是二维数组。
现在,找出数组‘a’和‘b’的形状:
输入:
a.shape
输出:
(3,)
输入:
b.shape
输出:
(2, 3)
数组“a”是一维数组。所以,它在形状上只有一个值。但是数组“b”是一个二维数组。所以,它的形状是 2 x 3。这意味着它有 2 行 3 列。
求数组的长度:
输入:
len(a)
输出:
3
输入:
len(b)
输出:
2
数组“a”的长度为 3,因为它包含 3 个元素。数组“b”是一个二维数组。所以,数组的长度并不意味着数组中元素的数量。长度是指其中一维数组的个数或其中的行数。它有两排。所以,长度是 2。
重复
有几种不同的方法来重复数组的元素。如果你想重复整个数组,
输入:
np.array([2,4,6]*4)
输出:
array([2, 4, 6, 2, 4, 6, 2, 4, 6, 2, 4, 6])
看,数组[2,4,6]重复了 4 次。
这里是如何做元素方面的重复,
输入:
np.repeat([1,2,3], 3)
输出:
array([1, 1, 1, 2, 2, 2, 3, 3, 3])
这次每个元素重复 3 次。
让我们用这个来表示一个二维数组,
输入:
arr = np.array([[2, 4, 6]])
arr
输出:
array([[2, 4, 6]])
现在,对它重复使用:
输入:
np.repeat(arr,3,axis=0)
输出:
array([[2, 4, 6],
[2, 4, 6],
[2, 4, 6]])
这里,我们提到了轴= 0。因此,重复发生在轴 0 方向或行方向。
输入:
np.repeat(arr,3,axis=1)
输出:
array([[2, 2, 2, 4, 4, 4, 6, 6, 6]])
轴 1 表示列的方向。因此,重复发生在列的方向。
数学
在这一部分,我将展示数学运算。大多数操作都是不言自明的。我将从一个数组的数学运算开始。
输入:
a = np.array([1,2,3,4])
a
输出:
array([1, 2, 3, 4])
输入:
a+2
输出:
array([3, 4, 5, 6])
它给数组的每个元素加 2。
输入:
a-2
输出:
array([-1, 0, 1, 2])
您可以简单地以这种方式使用类似的操作,例如:
输入:
a/2
输出:
array([0.5, 1\. , 1.5, 2\. ])
输入:
a**2
输出:
array([ 1, 4, 9, 16], dtype=int32)
两个星号表示指数。a 中的每个元素都是平方的。
输入:
np.sqrt(a) #square root
输出:
array([1\. , 1.41421356, 1.73205081, 2\. ])
我们还可以执行一些三角运算:
输入:
np.cos(a)
输出:
array([ 0.54030231, -0.41614684, -0.9899925 , -0.65364362])
输入:
np.sin(a)
输出:
array([ 0.84147098, 0.90929743, 0.14112001, -0.7568025 ])
输入:
np.tan(a)
输出:
array([ 1.55740772, -2.18503986, -0.14254654, 1.15782128])
现在看看我们如何在两个数组或矩阵中做一些数学运算。首先,再做一个数组,
输入:
b = np.array([3,4,5,6])
输出:
array([3, 4, 5, 6])
提醒一下,我们的数组“a”是这样的:
array([1, 2, 3, 4])
现在,我们有两个数组,a 和 b。让我们做同样的数学运算。同样,它简单明了,
输入:
a + b
输出:
array([ 4, 6, 8, 10])
同样,您可以执行以下操作:
a - b
a*b
a/b
a**b
另一个广泛使用的操作是,
输入:
a.dot(b)
输出:
50
什么是 a.dot(b)?它是逐元素的乘法,然后像这样加法,
1*3 + 2*4 + 3*5 + 4*6
其中数组“a”是[1,2,3,4],数组 b 是[3,4,5,6]。
您也可以编写稍微不同的语法,
np.dot(a, b)
这是一样的。输出将是 50。
我们可以在多维数组中使用这种点过程。让我们做两个多维数组,
输入:
c = np.array([[3, 5, 1], [6, 4, 9]])
c
输出:
array([[3, 5, 1],
[6, 4, 9]])
输入:
d = np.array([[5,2], [7,9], [4, 3]])
d
输出:
array([[5, 2],
[7, 9],
[4, 3]])
我们准备对多维数组进行“点”操作,
输入:
c.dot(d)
输出:
array([[54, 54],
[94, 75]])
当输入为 2D 阵列时,“点”函数的行为类似于矩阵乘法。
这意味着只有当第一个数组的列数与第二个数组的行数匹配时,才能执行“点”操作。
如果第一个数组是 m x n,第二个数组应该是 n x p。
矩阵乘法有另一种表达方式,
输入:
np.matmul(c, d)
输出:
array([[54, 54],
[94, 75]])
‘NP . mat mul’在一维数组中不起作用
记住,这个乘法法则不适用于其他运算,如加、减或除。我们需要相同形状和大小的数组来对一个矩阵进行加法、减法或除法运算。
统计数字
Numpy 也有基本的统计操作。这里有一些例子。
先做一个新的数组。
输入:
x = np.array([1,3,4,6,-3,-2])
x.sum()
输出:
9
输入:
x.max()
输出:
6
输入:
x.min()
输出:
-3
输入:
x.mean()
输出:
1.5
输入:
x.std() #standard deviation
输出:
3.2015621187164243
还有另外两个非常有用的函数,它们不完全是统计函数,
输入:
x.argmin()
输出:
4
输入:
x.argmax()
输出:
3
什么' argmin()'或者' argmax()'?
“argmin()”给出数组最小元素的索引,“argmax()”返回数组最大值的索引。
数组“x”的最小元素是-3,最大元素是 6。现在检查他们的索引是否与结果匹配。
初始化不同类型的数组
Numpy 中有很多不同的方法来初始化一个数组。在这里我将讨论一些常用的方法:
输入:
np.arange(10)
输出:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
这是初始化数字序列的方法。注意它从 0 开始,到 9 结束。上限始终被排除在外。这里的上限是 10。所以,它停在 9 点。
我们还可以给它添加一个数学运算:
输入:
np.arange(10)**2
输出:
array([ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81], dtype=int32)
在这种情况下,我们要求 10 平方的范围,我们在输出数组中得到 0 到 9 的平方。
我们可以按一定的间隔排列数列。
np.arange(0, 15, 3)
输出:
array([ 0, 3, 6, 9, 12])
这里,0 是下限,15 是上限,3 是区间。
另一种方法给出的序列稍有不同:
输入:
np.linspace(0, 3, 15)
输出:
array([0\. , 0.21428571, 0.42857143, 0.64285714, 0.85714286,
1.07142857, 1.28571429, 1.5 , 1.71428571, 1.92857143,
2.14285714, 2.35714286, 2.57142857, 2.78571429, 3\. ])
这里,0 是下限,3 是上限,15 是元素数。在这种情况下,Numpy 自动生成 15 个从 0 到 3 等间距的元素。
还有一些其他类型的数组:
输入:
np.ones((3, 4))
输出:
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
输入:
np.zeros((2, 3))
输出:
array([[0., 0., 0.],
[0., 0., 0.]])
你可以启动一个三维数组:
输入:
np.ones((4,3,2), dtype='int32')
输出:
array([[[1, 1],
[1, 1],
[1, 1]],[[1, 1],
[1, 1],
[1, 1]],[[1, 1],
[1, 1],
[1, 1]],[[1, 1],
[1, 1],
[1, 1]]])
这里,(4,3,2)表示 4 个二维数组,每个数组有 3 行 2 列。
输入:
np.full((2,2), 30)
输出:
array([[30, 30],
[30, 30]])
还有另一个名为 full_like 的方法可以替换数组中的元素:
输入:
ar = np.array([[2,3], [4,5]])
ar
输出:
array([[2, 3],
[4, 5]])
输入:
np.full_like(ar, 4)
输出:
array([[4, 4],
[4, 4]])
还有另一种称为单位矩阵的矩阵:
输入:
np.identity(5)
输出:
array([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]])
这是一个 5 乘 5 的矩阵,其中所有的元素都是 0,只有对角元素是 1。
还有一种叫做“眼睛”。它呈矩阵状:
输入:
np.eye(3,3)
输出:
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
输入:
np.eye(3,4)
输出:
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.]])
这些对角线数可以不同于 1。
输入:
a = np.array([2,4,5])
np.diag(a)
输出:
array([[2, 0, 0],
[0, 4, 0],
[0, 0, 5]])
重新排列或重组数组
有不同的方法来重新排列或调整一个数组。
我们来举例学习一下。首先,做一个数组,
输入:
x = np.arange(0, 45, 3)
x
输出:
array([ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42])
我在上一节解释了“arange”函数。让我们看看如何重塑它。
输入:
x.reshape(3, 5)
输出:
array([[ 0, 3, 6, 9, 12],
[15, 18, 21, 24, 27],
[30, 33, 36, 39, 42]])
我们通过了(3,5)。所以,它变成了一个有 3 行 5 列的二维数组。我们可以通过以下方式实现同样的目标:
x.resize(3,5)
如果我们想回到原来的一维数组呢?
方法是这样的,
输入:
x.ravel()
输出:
array([ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42])
看,我们找回了原来的数组!
注意另一件事。也就是说我们改变了数组的维度。数组“x”是一维数组。我们通过重塑使它成为一个二维数组。
现在,制作另一个数组来更好地理解它。这是另一个例子。
输入:
c = np.array([4,5,6])
c
输出:
array([4, 5, 6])
这次我将使用 resize。重塑也是如此。为了练习调整大小,让我们在这里使用 resize。
输入:
c.resize(3,1)
输出:
array([[4],
[5],
[6]])
看,我们提供(3,1)作为调整大小的参数。所以它有 3 行 1 列。这是一个 3x1 的矩阵。我们也可以有一个 1×3 的矩阵。
输入:
c.resize(1,3)
c
输出:
array([[4, 5, 6]])
原来 c 是一个一维数组。现在它是一个二维数组或矩阵。
不要认为你只能改变一维数组的形状。你也可以在一个更高维的数组中这样做。
这里我有一些例子:
输入:
x = np.array([[1,2,3,4], [5,6,7,8]])
x
输出:
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
现在重塑这个二维数组,
输入:
x.reshape(4,2)
x
输出:
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
你可以用我之前提到的“调整大小”来实现。还有另一种方法,
输入:
y = x.reshape(4, -1)
y
输出:
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
看起来很困惑?想象一下,你有一个巨大的数组或数据集。在重塑之前,你只知道一个维度。因此,在 reshape 方法中,传递一个维度,对另一个维度使用-1。这样 Numpy 自己就能找到另一个维度。
在上面的例子中,我传递了第一个维度 4。这意味着我告诉 Numpy 做 4 行。我不知道列数。所以我就在那里过了-1。因此,它自动知道要制作 2 列。
当我们处理大型数据集或数据帧,并且必须构建机器学习算法时,这是一个非常有用的技巧。
在上面所有的例子中,我们看到了如何重塑和改变尺寸。
这是改变维度的方法。上面的数组“y”是一个 4x2 的矩阵。我们再做一个 2×4 的矩阵。
输入:
y.T
输出:
array([[1, 3, 5, 7],
[2, 4, 6, 8]])
这种方法被称为转置。当你在一个数组或矩阵上使用转置时,它只是改变了维度。2×3 矩阵变成 3×2,3×6 矩阵变成 6×3 或者 1×3 矩阵变成 3×1。
索引或切片
索引和切片是一项非常常见的日常任务。让我们来看几个例子:
输入:
a = np.array([2,5,1,7,6,3,9,0,4])
输入:
a[0]
输出:
2
a[0]给出数组的第一个元素。同样,我们可以从 a[1],a[2],一直到整个数组。
输入:
a[3]
输出:
7
我们也可以切一片,
输入:
a[1:5]
输出:
array([5, 1, 7, 6])
这就是解释。我们通过了[1:5]。因此,切片将从索引 1 开始,在索引 5 之前结束。记住,下界包含,上界排除。
在本文中,我不会深入探讨切片和索引。因为我已经写了另一篇文章详细解释了它。请检查。学好它很重要。
[## Numpy 中 1D、2D 和 3D 数组的索引和切片
本文从基础到高级展示了 Numpy 数组的索引和切片。
towardsdatascience.com](/indexing-and-slicing-of-1d-2d-and-3d-arrays-in-numpy-e731afff0bbe)
添加行或列
Numpy 有几种不同的方法来添加行或列。首先,我将开始一些堆叠技术。这里有一些例子。
这次我将使用一些列表或数组。Numpy 会在堆叠的时候自动把它们变成数组。
这里有两个列表:
x1 = [[2, 4, 3, 7], [2, 5, 3, 1]]
x2 = [1, 0, 9, 5]
现在把它们垂直堆叠起来。
输入:
np.vstack([x1, x2])
输出:
array([[2, 4, 3, 7],
[2, 5, 3, 1],
[1, 0, 9, 5]])
你想叠多少次都可以。
输入:
np.vstack([x1, x2, x2])
输出:
array([[2, 4, 3, 7],
[2, 5, 3, 1],
[1, 0, 9, 5],
[1, 0, 9, 5]])
让我们做一些水平堆叠。我们需要行数相同的数组。
“x1”有 2 行。用它做一个数组。
输入:
np.array(x1)
输出:
array([[2, 4, 3, 7],
[2, 5, 3, 1]])
制作另一个数组“x3”。
输入:
x3 = np.ones((2,3))
x3
输出:
array([[1., 1., 1.],
[1., 1., 1.]])
水平堆叠的时间到了。
输入:
np.hstack([x1, x3])
输出:
array([[2., 4., 3., 7., 1., 1., 1.],
[2., 5., 3., 1., 1., 1., 1.]])
串联
添加列或行的另一种方式。但是与堆叠相反,这次我们需要两个相同维度的数组。记住,当我们做垂直堆叠时,我们有一个二维和一维列表。
这是我在这个例子中的两个列表。
x1 = [[2, 4, 3, 7], [2, 5, 3, 1]]
x2 = [[1, 0, 9, 5]]
串联操作,
输入:
np.concatenate((x1, x2), axis=0)
输出:
array([[2, 4, 3, 7],
[2, 5, 3, 1],
[1, 0, 9, 5]])
现在,水平连接。但是我们需要两个行数相同的数组。
x3 = [[2,4], [7,5]]
连接 x1 和 x3。
输入:
np.concatenate((x1, x3), axis=1)
输出:
array([[2, 4, 3, 7, 2, 4],
[2, 5, 3, 1, 7, 5]])
追加、插入、删除和排序
你可能知道这些操作的名字。
追加
输入:
np.append([2,3], [[4,5], [1, 3]])
输出:
array([2, 3, 4, 5, 1, 3])
输入:
np.append([2, 3, 1], [[4, 5], [1,3]])
输出:
array([2, 3, 1, 4, 5, 1, 3])
在这些例子中,我们没有提到任何轴。所以,默认情况下,他们取轴 1 或列方向或水平方向。现在,做一个垂直方向的附加操作。
输入:
np.append([[1,3,5], [4,3,6]], [[1,2,3]], axis=0)
输出:
array([[1, 3, 5],
[4, 3, 6],
[1, 2, 3]])
插入
这次我们将在某个位置插入一个元素。从新数组开始。
输入:
a = np.array([[2, 2], [3, 4], [5, 6]])
a
输出:
array([[2, 2],
[3, 4],
[5, 6]])
在数组的开头插入元素 5。
输入:
np.insert(a, 0, 5)
输出:
array([5, 2, 2, 3, 4, 5, 6])
首先,了解输入。在(a,0,5)中,a 是数组,0 是我们想要插入元素的位置,5 是要插入的元素。
注意,插入是如何发生的。首先,二维数组“a”被展平为一维数组。然后在索引 0 处添加 5。
我们也可以沿轴插入。
输入:
np.insert(a, 0, 5, axis=1)
输出:
array([[5, 2, 2],
[5, 3, 4],
[5, 5, 6]])
看,一列 5 被添加到数组“a”中。我们也可以添加一排 5。
输入:
np.insert(a, 0, 5, axis=0)
输出:
array([[5, 5],
[2, 2],
[3, 4],
[5, 6]])
删除
我会像以前一样做一个新的数组。
输入:
a= np.array([[1,3,2,6], [4,1,6,7], [9, 10, 6, 3]])
a
输出:
array([[ 1, 3, 2, 6],
[ 4, 1, 6, 7],
[ 9, 10, 6, 3]])
输入:
np.delete(a, [1, 2, 5])
输出:
array([ 1, 6, 4, 6, 7, 9, 10, 6, 3])
像插入操作一样,删除操作也会展平数组。在输入[1,2,5]中是我们想要删除的索引列表。为了看清楚,让我们把原来的数组‘a’展平。
输入:
a.flatten()
输出:
array([ 1, 3, 2, 6, 4, 1, 6, 7, 9, 10, 6, 3])
现在检查一下,索引 1、2 和 5 的元素被删除了。
像插入一样,我们可以删除特定的行或列。
删除列索引 1。
输入:
np.delete(a, 1, 1)
输出:
array([[1, 2, 6],
[4, 6, 7],
[9, 6, 3]])
在输入(a,1,1)中,a 是数组,1 是我们要删除的列的索引,最后一个 1 是轴。
输入:
np.delete(a, 1, 0)
输出:
array([[ 1, 3, 2, 6],
[ 9, 10, 6, 3]])
排序
这里是数组“a”:
array([[ 1, 3, 2, 6],
[ 4, 1, 6, 7],
[ 9, 10, 6, 3]])
输入:
np.sort(a)
输出:
array([[ 1, 2, 3, 6],
[ 1, 4, 6, 7],
[ 3, 6, 9, 10]])
看,它是双向分类的。我们可以指定轴并在特定的轴上排序。
输入:
np.sort(a, axis=None)
输出:
array([ 1, 1, 2, 3, 3, 4, 6, 6, 6, 7, 9, 10])
当坐标轴为 None 时,它将数组展平并排序。现在,在 0 轴和 1 轴排序。
输入:
np.sort(a, axis=0)
输出:
array([[ 1, 1, 2, 3],
[ 4, 3, 6, 6],
[ 9, 10, 6, 7]])
输入:
np.sort(a, axis=1)
输出:
array([[ 1, 2, 3, 6],
[ 1, 4, 6, 7],
[ 3, 6, 9, 10]])
翻转
听起来确实如此。翻转数组和行。
这是一个数组。
arr
输出:
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
现在,在轴 0 和 1 的方向翻转这个数组。
输入:
np.flip(arr, 0)
输出:
array([[ 9, 10, 11, 12],
[ 5, 6, 7, 8],
[ 1, 2, 3, 4]])
输入:
np.flip(arr, 1)
输出:
array([[ 4, 3, 2, 1],
[ 8, 7, 6, 5],
[12, 11, 10, 9]])
随意
Numpy 拥有优秀的随机数生成功能。它们在机器学习、研究或统计中非常有用。这里有一些例子。
输入:
np.random.rand()
输出:
0.541670003513435
它生成一个 0 到 1 之间的数字。我们可以像这样从随机数中得到一个数组或矩阵。
输入:
np.random.rand(3)
输出:
array([0.6432591 , 0.78715203, 0.81071309])
输入:
np.random.rand(2, 3)
输出:
array([[0.91757316, 0.74438045, 0.85259742],
[0.19826903, 0.84990728, 0.48328816]])
它不一定是从 0 到 1 的数字。我们可以生成随机整数。
输入:
np.random.randint(25)
输出:
20
它产生一个 0 到 25 之间的随机数。我们可以指定想要生成多少个数字。
输入:
np.random.randint(1, 100, 10)
输出:
array([96, 44, 90, 13, 47, 16, 9, 46, 49, 20])
这里,我们要求 Numpy 生成 1 到 100 范围内的 10 个数字。
现在,生成一个范围为 1 到 100 的 3x3 矩阵。
输入:
np.random.randint(1, 100, (3,3))
输出:
array([[25, 80, 42],
[95, 82, 66],
[64, 95, 55]])
您可以提供一个数组,并要求 Numpy 使用您提供的数组中的数字制作一个 3x3 的矩阵,而不是一个范围。
输入:
np.random.choice([1,2,3,4,5,6,7,8,9,10], size=(3,3))
输出:
array([[ 7, 9, 2],
[ 6, 4, 6],
[ 3, 10, 6]])
另一个有用的功能是“随机播放”。让我们做一个新的数组,然后洗牌。
输入:
a = np.array([3,6,3,1,0, 11])
np.random.shuffle(a)
a
输出:
array([ 3, 0, 6, 3, 11, 1])
看,我们有相同的元素,只是洗牌后重新排列。
保存、加载和导入文件
我们可以将数组“arr”保存在一个文件中。
输入:
np.save('arrfile', arr)
这里,我们创建一个名为“arrfile”的文件来保存数组“arr”。该文件将以扩展名'保存。npy。
我们可以加载该文件,并带回来进一步使用这样的数组,
输入:
np.load('arrfile.npy')
输出:
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
我们可以使用 Numpy 作为数组导入 CSV 文件或文本文件。我有一个名为“Cartwheeldata.csv”的文件,与我处理这些示例的 Jupyter 笔记本放在同一个文件夹中。现在,将文件导入到这里。
输入:
filedata = np.genfromtxt('Cartwheeldata.csv', delimiter=',')
filedata=filedata.astype('int32')
filedata
输出:
我在这里展示了数组的一部分。因为文件很大。这是那个文件的信息。
这些类型的数组在机器学习中非常有用。
结论
这就是我想在本文中分享的所有 Numpy 功能。Numpy 是一个大图书馆。它有很多可用的方法。但是这些功能对于日常使用来说已经足够好了。如果你认为我错过了这里的任何主题或者需要添加更多的功能,请告诉我。我会添加它们。
更多阅读:
熊猫的所有基本视觉类型和一些非常高级的视觉…
towardsdatascience.com](/an-ultimate-cheat-sheet-for-data-visualization-in-pandas-4010e1b16b5c) [## 使用 Pandas 的 Groupby 功能进行有效的数据汇总和分析
学习使用聚合函数,数据转换,过滤,映射,在数据框架中应用
towardsdatascience.com](/efficient-data-summarizing-and-analysis-using-pandas-groupby-function-7b2cc9eff186) [## 编程、软件工程和数据科学的最佳免费资源
麻省理工、哈佛和斯坦福等顶尖大学的免费课程
towardsdatascience.com](/best-free-courses-for-computer-science-software-engineering-and-data-science-50cd88cafd74) [## 如何在 Python 中呈现多个变量之间的关系
了解如何使用 Python 中的多元图表和绘图来呈现要素之间的关系
towardsdatascience.com](/how-to-present-the-relationships-amongst-multiple-variables-in-python-70f1b5693f5) [## 无经验的数据科学家如何抓住机遇
当技能遇到机会时,成长就会发生
towardsdatascience.com](/inexperienced-data-scientists-guide-to-meet-the-opportunity-9e8078e5ad74) [## 学习机器学习和深度学习的优质免费课程
顶级大学高质量免费课程的链接
towardsdatascience.com](/great-quality-free-courses-to-learn-machine-learning-and-deep-learning-1029048fd0fc)
无监督数学评分模型
释放数学模型的力量
一个数学模型是使用数学方程对一个系统的描述。该系统由一组数学方程控制,这些方程可以是线性的、非线性的、静态的或动态的。该模型可以从可用数据中学习方程的参数,甚至预测未来。
在这篇博客中,我将讨论一个这样的实用数学模型,它可以在缺乏带有一些领域知识的标记数据的情况下用于各种问题。本博客中使用的所有代码和数据集都可以在这里找到。
我们的数学模型:逻辑函数
逻辑函数俗称 Sigmoid 函数 是一种具有特征“S”形曲线或 sigmoid 曲线的数学函数。
逻辑函数可以取-∞到+∞ 源之间的任何 x 值
在哪里,
X₀ =乙状结肠中点的 x 值
L =曲线的最大值
k =曲线的逻辑增长率或陡度。
逻辑函数可以取-∞到+∞之间的任何 x 值。对于 x 接近+∞,f(x)接近 L,对于 x 接近-∞,f(x)接近 0。
标准 sigmoid 函数返回 0 到 1 范围内的值。该等式由下式给出
Sigmoid 可以取-∞到+∞之间的任何 x 值来源
对于 x = 0,S(x=0) = 0.5
x < 0, S(x<0) < 0.5 and x > 0,S(x>0) > 0.5
所以,Sigmoid 函数是以 0 为中心的。
来源:维基
问题陈述
我们有客户的财务数据。其中一个特征是信用额度,即客户名下的信用额度。现在,根据信用额度,我们打算生成一个介于 0-1 之间的风险评分。
客户和现有信贷金额数据的快照
在不同的数据集和不同的要素中,数据的分布会有所不同。我们来看看 credit_amount 的分布。
贷方金额直方图
credit_amount 向右倾斜。在不同的数据集和用例中,数据的偏斜度或分布可能会有所不同。
我们希望提出一个评分机制,更多地惩罚离群值。
在我们的例子中,我们将提出一个理想的行为,并尝试学习最能模拟理想行为的逻辑函数的参数。让我们定义一下理想行为:
- 风险分值在 0 到 1 的范围内。
- 数据以第 65 个百分位为中心。(假设,因为我们希望更多地惩罚异常值)
- 理想情况下,我们希望第 65 百分位的分数为 0.50,第 75 百分位的分数为 0.65,第 80 百分位的分数为 0.70,第 85 百分位的分数为 0.75。对于其余的数据,我们希望分数有相应的变化。
- 不同的特征可能具有不同的分布和范围,因此我们希望提出一种技术,能够学习逻辑函数的参数,以匹配步骤 3 中定义的理想行为。
对于我们使用逻辑函数为 credit_amount 定义风险分值的问题,让我们解码参数。
逻辑函数可以取-∞到+∞ 源之间的任何 x 值
在哪里,
X₀ =乙状结肠中点的 x 值
L =曲线的最大值
k =曲线的逻辑增长率或陡度。
因为我们希望风险分值范围在 0 到 1 之间,所以 L = 1。
因为我们希望逻辑函数以第 65 个百分点的数据为中心,所以 X₀ =信用额的第 65 个百分点
增长率 k,我们将通过随机搜索来学习,它可以从步骤 3 中定义的理想行为中以最小的均方误差最佳地模仿理想行为。
# Logistic function ~ b denotes X₀ and c denotes k(growth rate)
def sigmoid(x,b,c):
return 1 / (1 + math.exp(-c * (x-b)))
可能增长率“k”的计算误差
# Mean Squared error between ideal and observed behavior
# b denotes X₀ and c denotes k(growth rate)
def cal_error(c,pcts,values_expected):
error = math.pow(sigmoid(pcts[0],pcts[3],c) - values_expected[0],2) + math.pow(sigmoid(pcts[1],pcts[3],c) - values_expected[1],2) + math.pow(sigmoid(pcts[2],pcts[3],c) - values_expected[2],2) + math.pow(sigmoid(pcts[3],pcts[3],c) - values_expected[3],2)
return error
随机搜索以找到最佳“k”,增长率
def find_best_decay_parameter(pcts,values_expected):
best_error = 999999
best_c = 1.0
iterations = 5000
for i in range(iterations):
tmp = random.random()
error = cal_error(tmp,pcts,values_expected)
if error<best_error:
best_error = error
best_c = tmp
return best_c
调用函数
percentiles = [85,80,75,65]
values_expected = [0.75,0.70,0.65,0.50]
b,c = find_decay_parameter(df.credit_amount,values_expected)
输出
Best value of Growth rate 'k' = 0.00047
Value of L = 1
value of X₀ = 3187
**65th 75th 80th 85th**
**Value 3187 3972 4720 5969**
**Expected Score 0.50 0.65 0.70 0.75
Observed Score 0.50 0.59 0.67 0.79**
我检查了分数是如何随着不同的信用额度而变化的
credit_amounts = [100,500,1200,3000,4000,5200,6000,7500,10000,12000,20000,25000]
risk = []
mp_values = {}
for credit_amount in credit_amounts:
mp_values[credit_amount] = round(sigmoid(credit_amount,b,c),2)
输出:
不同信用额度的观察风险评分
信用金额的风险分值在 0 到 1 范围内的变化
找到参数“l”、“'X₀'”和“k”的正确值后,我们拟合了一个数学模型,使风险得分接近我们想要的理想得分行为,即更多地惩罚异常值。
提高
在上一节中,我们看到风险评分是一个变量的函数,即 credit_amount。但是,如果我们有不止一个变量,并且我们希望风险分数是所有这些变量的函数,那该怎么办呢?
在这种情况下,我们可以首先找到每个变量的权重/重要性,使得权重总和为 1。然后,我们可以为每个变量拟合一个单独的逻辑函数,最后对个体风险评分进行加权求和。
让我们以 3 个变量及其风险分值和权重为例。
变量和风险分数
变量和权重
最终风险得分= 0.72 * 0.3+0.65 * 0.25+0.81 * 0.45 = 0.743
结论
通过这篇博客,我们了解了什么是数学模型,并使用逻辑函数研究了一个这样的数学模型。这种模型可以在缺乏带有一些先验领域知识(如特征的重要性和特征的分布)的标记数据的各种问题中使用。本博客中使用的所有代码和数据集都可以在这里找到。
如果你有任何疑问,请联系我。我很想知道你是否认为你有一个可以利用这种数学模型的用例。
我的 Youtube 频道更多内容:
嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…
www.youtube.com](https://www.youtube.com/channel/UCg0PxC9ThQrbD9nM_FU1vWA)
关于作者-:
Abhishek Mungoli 是一位经验丰富的数据科学家,拥有 ML 领域的经验和计算机科学背景,跨越多个领域并具有解决问题的思维方式。擅长各种机器学习和零售业特有的优化问题。热衷于大规模实现机器学习模型,并通过博客、讲座、聚会和论文等方式分享知识。
我的动机总是把最困难的事情简化成最简单的版本。我喜欢解决问题、数据科学、产品开发和扩展解决方案。我喜欢在闲暇时间探索新的地方和健身。关注我的 中 、Linkedin或insta gram并查看我的往期帖子。我欢迎反馈和建设性的批评。我的一些博客-********
- 降维:PCA 与自动编码器
- 体验遗传算法的威力
- 每个数据科学家都应该避免的 5 个错误
- 以简单&直观的方式分解时间序列
- GPU 计算如何在工作中拯救了我?
- 信息论& KL 分歧第一部分和第二部分
- 使用 Apache Spark 处理维基百科,创建热点数据集
- 一种基于半监督嵌入的模糊聚类
- 比较哪个机器学习模型表现更好
- 分析 Fitbit 数据,揭开疫情封锁期间身体模式变化的神秘面纱
- 神话与现实围绕关联
- 成为面向商业的数据科学家指南
在 Windows 10 上安装 Tensorflow-GPU 2.0 的简单指南
根据你的网速,不会超过 15 分钟。
TensorFlow 是谷歌的开源库,使您能够开发和训练深度学习模型。虽然大多数安装指南侧重于安装 CPU 版本,这是您的常规pip install
,但今天我想重点安装它的更大、更强大的兄弟 GPU 版本。
你想要使用 GPU 版本而不是 CPU 版本的主要原因是速度——如果你决定在 GPU 上训练模型,速度会有令人难以置信的提高,我不会去解释原因——因为这是一个如何指南,而不是为什么指南。
最重要的是,安装将在 Windows 10 x64 机器上完成。所以这里没有 Linux,因为我知道在 Linux 上安装是相当简单的。
事不宜迟,让我们直接开始吧。下一节将简要讨论您需要什么。
要求
在整个过程中,我们需要下载并安装三个工具:
- 微软 Visual Studio (如果没有专业版的话社区版也可以)
- Nvidia CUDA 工具包 (我用的是 10.0 版本)
- Nvidia cud nn(7 . 6 . 5 版本即可)
下面几节将重点介绍如何安装每个工具。
Microsoft Visual Studio
现在我们不会真正使用 Visual Studio,但 Nvidia CUDA 工具包的一些组件需要它,所以它就是这样。
Visual Studio 可以从这个链接下载,从这里很容易下载社区版:
安装时,你不需要检查任何额外的组件——让一切保持原样,点击几次下一个。大约 5 到 10 分钟后,安装应该完成。在 Tensorflow 方面,您将不再需要接触 Visual Studio。
Nvidia CUDA 工具包
该工具包使您能够创建高性能 GPU 加速的应用程序。在可以从下载此链接的中,只需确保选择我已经选择的所有内容,然后点击下方的下载按钮即可。
它的大小略超过 2 GB,所以根据你的网速,可能需要一段时间。
下载后,您可以运行。exe 文件,它会要求你将内容解压到某个临时文件夹中。一旦安装开始,你可以坚持使用 Express 选项:
几分钟后,Nvidia CUDA Toolkit 将安装完毕!
接下来,Nvidia cuDNN。
Nvidia cuDNN
Nvidia cuDNN 是一个用于深度神经网络的 GPU 加速库。可以从这个链接下载。请记住,你需要创建一个帐户,但你可以登录谷歌,你就可以走了。
登录后,您将被重定向至以下页面—点击下载 cuDNN 7.6.5 for CUDA 10.0 :
这是一个 ZIP 文件,大小可能为 250MB,所以应该可以快速下载。下载完成后,你可以将 contents˛(that 解压到你的 CUDA 安装目录中,该目录位于:
C:\Program Files\Nvidia GPU Computing Toolkit\CUDA\v10.0
如果您在安装时没有做任何更改。仅此而已。设置完成!
在 GPU 上安装 TensorFlow 2.0
我们已经完成了繁琐的安装过程,现在只需要做一个简单的 pip 安装。在撰写本文时,最新的支持 GPU 的 TensorFlow 版本是 2.0.0 RC1。
要安装它,打开命令提示符并执行以下命令(我假设您已经安装了 Python):
pip install tensorflow-gpu=2.0.0-rc1
如果你不能提供版本,它将安装 1.14 版,这是我们不想要的。
就这样,下载需要一些时间(300+ MB),但是 TensorFlow 现在应该已经安装在你的机器上了。让我们快速验证一下这个说法:
如你所见,我在命令提示符下打开 Python shell,导入 TensorFlow 并检查 GPU 是否可用。这个函数调用了 return True,你也可以在提示符的底部看到我的 GPU 是黄色的。
在你走之前
拥有一台轻薄的笔记本电脑是很好的——你可以去任何地方而不会弄乱你的背。但比没有背部问题更酷的是拥有一台能够在 GPU 上训练神经网络的强大笔记本电脑。
如果你有一个合适的网速,这篇文章不应该花费你超过 5 分钟来阅读,15 分钟来安装和配置一切。
感谢阅读。玩得开心——我知道我会的。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
Anaconda:从这里开始学习 Python 中的数据科学!
在 Python 虚拟环境中使用 Anaconda
如果你一直关注我或者读过我的一些文章,你一定知道我是 Python 虚拟环境的忠实粉丝。我以前也写过这方面的文章,你可以在这里阅读从那以后,我几乎所有的项目都包含了requirements.txt
文件,其他人可以很容易地复制我的作品。
我和几个虚拟环境经理一起工作过,但是从来没有真正关注过 Anaconda。然而,现在我需要在康达环境下进行日常的大学工作。这里,推荐的工作方式是使用虚拟环境,我的同事使用 Anaconda。所以,我决定试一试!
Anaconda 就像任何其他虚拟环境管理器一样,但是它不仅仅是管理环境。它有自己的名为conda
的 Python 包管理器,也支持pip
。它并不局限于 Python,也可以用于其他语言。但是也有一些警告,比如一些包只能用pip
安装,而不能用conda
。因此,在这篇文章中,我们将探索一些关于 Anaconda 的知识,然后查看一些最有用的命令,这些命令是您成为虚拟环境专家所需要的。
什么是蟒蛇?为什么要用?
以一条蛇命名一个项目听起来很荒谬,但是,嘿,我们知道 Python 也是一条蛇
Anaconda 完全是关于数据科学的。它侧重于包含帮助数据科学家拥有一个可以完成所有工作的工作台的特性和包。它从一开始就托管了几个数据科学包,使数据科学家能够快速起步。凭借环境的额外优势,它成为任何人迈向数据科学之旅的理想起点。
听起来很有趣!但是,与其他虚拟环境管理器相比,您为什么更喜欢它呢?我已经使用了一段时间,以下是我发现它真正吸引人的地方:
- 不需要目录:与其他类似
virtualenv
的目录不同,您不需要指定某个目录来安装环境。这使您能够在系统的任何地方激活虚拟环境,而不必担心位置问题。 - 选择任意 Python 版本:只要服务器上存在 Python 的一个版本,它是否安装在您的系统上并不重要。Anaconda 的
conda
可以通过从服务器获取 Python 的精确版本来轻松创建环境。 - conda 包管理器:虽然
pip
擅长管理 Python 包,但是conda
在检索包并将它们安装到环境中也做了类似的工作。额外的好处是,它与 Anaconda 发行版捆绑在一起,使之变得容易。
但是,我还是觉得没有pip
的conda
是不完整的。如果你试图通过conda
安装一些软件包,它可能会给出一个错误,但同样的软件包可以很容易地使用pip
安装。
在 Python 环境中使用 conda 和 pip。
关于 Python3 和 Python2 的注记
由 Kelly Sikkema 在 Unsplash 上拍摄的照片
Python2 不再被开发,所有的开发工作都是针对 Python3 的。然而,有几个包和项目仍然依赖于 Python2,所以不要与它失去联系是一个好习惯。查看下面基于 Python 2 的项目。创造了一些非凡的艺术品。
在几分之一秒内将名画的风格添加到任何照片中!你甚至可以设计视频!在…上需要 100 毫秒
github.com](https://github.com/lengstrom/fast-style-transfer)
本文适用于 Python2 和 Python3,因为在设置环境时,它们在选择 Python 版本上只有本质上的不同,但我们现在将使用 Python3 发行版。
在 Python3 中启动任何新项目都是面向未来的。
安装 Anaconda
如果你以前安装过任何软件,你会有宾至如归的感觉。转到这里,选择你的操作系统(我用的是 Mac ),然后选择 Python 3.x 版本Download
按钮,它会将安装程序下载到你的机器上。
选择 Python 3.7 版本下方的“下载”按钮
然后,打开机器上的安装程序,按照所有步骤进行操作,同时阅读并同意协议。您不需要修改任何东西,因为所有的东西都是自己设置好的,一旦完成,您就可以在您的机器上使用 Anaconda 了。
使用 Python 包
正如我之前提到的,Anaconda 包附带了conda
管理器,它允许你安装包,创建和激活虚拟环境等等。
开放终端
我使用 iTerm2 作为我的主要终端,这是我根据自己的喜好设计的。按照我在 Medium 上发布的指南,您可以创建一个类似的(甚至更好的)终端视图。
简单的外壳定制技术
towardsdatascience.com](/customising-the-mac-terminal-to-increase-productivity-and-improve-the-interface-894f6d86d573)
您会注意到终端现在在计算机名前面写有(base)
。这意味着您的基本 conda 环境已经设置好了(意味着您正在为整个用户而不是一个特定的环境工作)。
(基地)在司令部前面
我将首先描述这个基础环境中的几个命令,但是它们也可以在任何特定的环境中工作。我们将在本文后面看到如何设置和使用环境。
查看已安装的软件包
一个最基本的命令是知道您的环境中所有已安装软件包的列表。请注意,Anaconda 内置了许多包,因此您将看到比预期多得多的包。该命令如下所示:
conda list
已安装软件包列表
搜索并安装软件包
conda
非常直观,因为您想要做的正是该命令可能看起来的样子。假设我们想安装numpy
,但是我们不知道版本。我们可以使用以下命令来搜索它的版本:
conda search numpy
在康达搜索一个包
假设我们计划安装版本为1.18.1
的numpy
,我们将使用以下命令来完成:
conda install numpy==1.18.1
安装 numpy 版本 1.18.1
移除包
假设在某种情况下,您不再需要某个特定的包,或者您安装了一个错误的版本,您可以简单地使用下面的命令来删除它。用numpy
来做吧。
conda remove numpy
拆卸数字
使用 Python 环境
conda
您还可以根据需要创建、激活和停用虚拟环境。所有这些环境都是相互隔离的,可以托管非常不同的包和包版本组合,而不会相互干扰。
创建虚拟环境
可以使用以下命令创建虚拟环境,并选择在创建环境时直接安装几个软件包:
conda create -n env_name python=3.7.6 <list_of_packages>
-n
后面的字就成了环境的名字。在我们这里,它是env_name
。然后,我们按照上面的定义指定 python 的版本。然后,我们可以指定在创建环境时要安装的软件包列表。这意味着包将在<list_of_packages>
处列出。例如,要创建环境并安装numpy
和pandas
,我们将使用以下命令:
conda create -n env_name python=3.7.6 numpy pandas
创建名为“环境名称”的虚拟环境
激活环境
激活环境非常容易。只需使用以下命令:
conda activate env_name
如果您碰巧使用了先前版本的conda
,您将需要在 Linux/MacOS 上使用命令source activate
或者在 Windows 上使用命令activate
。
激活环境
正如我们在上面的图像中看到的,环境的名称在命令行的前面,表明我们在环境中。
现在,我们可以使用conda install
或pip install
按需安装软件包,它们不会干扰这个环境之外的任何软件包。
停用环境
停用同样简单。使用命令
conda deactivate
同样,如果您使用的是先前版本的conda
,请在 Linux/MacOS 上使用source deactivate
或在 Windows 上使用deactivate
。
停用环境
你会注意到前面的文字变回了(base)
,表明我们已经不在我们的环境中了。
共享环境
使用环境的主要原因之一(除了管理隔离的环境之外)是能够与他人共享精确的 Python 包及其精确的版本。conda
使用 YAML 文件来共享环境信息,而requirements.txt
通常与pip
一起使用。为了导出所有包,无论是通过conda
还是pip
安装的,我们在环境中使用以下命令:
conda env export > environment.yml
该文件将类似于下图:
environment.yml
我建议我们也创建requirements.txt
文件,这样不使用conda
的用户仍然可以使用我们的环境配置。为此,请在环境中使用以下命令:
pip freeze > requirements.txt
您可以简单地与您的项目共享文件environment.yml
和requirements.txt
,以便于复制。
一旦你有了一个environment.yml
文件,你就可以在创建环境时简单地使用它,并像下面这样设置它以备使用:
conda create env --file environment.yml
列出所有环境
当您处理多个项目时,您会创建许多环境。您可能会忘记您可能已经创建的环境。有一个快速命令可以查看所有可用的环境:
conda env list
所有环境的列表
正如你所看到的,我有相当多的环境有我们通常有的特殊的base
。
移除环境
一旦您不再处理某个项目,您可能还想删除它的环境。使用命令来执行此操作:
conda env remove -n env_name
这里,env_name
应该替换为被删除的环境的名称。我正在删除env_name
,所以我将保持不变。
正在删除“环境名称”环境
结论
在本文中,我们探讨了什么是 Anaconda,以及它如何优于其他虚拟环境管理器。我们探索了使用conda
处理包以及创建和运行 Python 虚拟环境的方法。
一旦你熟悉了本文中的基础知识,你也可以参考 conda 备忘单。
我希望你喜欢我的作品。如果你有任何建议、想法或者你面临任何问题,请在评论中告诉我。也可以在 LinkedIn 上联系我。
分析和分类真实的患者咳嗽声
阴性(左)和阳性(右)新冠肺炎咳嗽谱图——分析吸入剂
冠状病毒:使用机器学习对新冠肺炎患者进行分类
作者劳里·威廉姆斯 — 7 分钟阅读
在近 5 个月内,当前的新型冠状病毒(新冠肺炎)将爆发一年。尽管我们还远远不知道如何全面应对这种病毒,但我们已经看到了一些非常酷的社交距离技术解决方案(如点餐应用),以及医疗领域的解决方案(如自动检测肺部 x 光片中的肺炎样迹象)。
Alexander Sinn 在 Unsplash 上拍摄的照片
创业公司需要问的关于人工智能的三个问题
维亚切斯拉夫·波隆斯基博士——8 分钟阅读
数十亿美元的人工智能投资正在蓬勃发展。这对那些指望人工智能来获得创新和竞争优势的初创公司来说意味着什么?这个策略看起来很简单:用机器学习解决人类的一个长期问题。谷歌、脸书、网飞和优步做到了。一个显而易见的问题是为什么不使用人工智能?
数据仓库综合指南
妮可·珍妮薇的账单 — 7 分钟阅读
作为一名数据科学家,了解一些基本的数据仓库概念是很有价值的。我们所做的大部分工作都涉及到在需要清晰易懂的数据集上增加企业价值。
使用 Pandas、Matplotlib、Seaborn 和 Plotly 分析和可视化 1955 年至 2020 年的乡村人口
100 天数据科学的第 1、2、3 天。
2020 年 8 月 12 日,我开始了 100 天的数据科学挑战。这项挑战的主要目标是在 100 天内每天学习 1 小时数据科学并编写代码。我打算学习和编码项目,以提高我的技能和获得实践经验。我将在 GitHub、Instagram 和 Medium 上分享我的旅程。别忘了在社交媒体上关注我。
前三天,我在 Kaggle 上研究一个国家的人口数据集。每天我都会用数据分析和可视化回答一些问题。
首先要做的事。让我们导入所有需要的库。对于这个项目来说, Pandas , Matplotlib , Seaborn ,和 Plotly 库就足够了。
先导入吧。
# data analysis
import pandas as pd# data visualization
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as pxplt.style.use('fivethirtyeight')%matplotlib inline
我用了fivethirtyeight
的剧情风格。点击查看更多款式。
现在让我们导入数据。你可以从 kaggle 下载数据集。从 kaggle 下载数据后,我们有一个 csv 文件— Countries Population from 1995 to 2020.csv
。现在让我们在 dataframe 中导入数据。
# load dataset
population = pd.read_csv('./Countries Population from 1995 to 2020.csv')
关于数据集:
Year — Year detail in which population data is recordedCountry — Name of CountryPopulation — Population of Country in a given yearYearly % Change — Change in population since last year (in %)Yearly Change — Change in population since last yearMigrants — Number of migrantsMedian Age — Median age of the populationFertility Rate — Fertility rate (in %)Density (P/Km²) — Density of countryUrban Pop % — % of the population is living in an Urban areaUrban Population — Net population living in Urban areaCountry’s Share of World Pop % — Country’s share in Total World PopulationWorld Population — World PopulationCountry Global Rank — Global rank of country
现在让我们来看一些例子。
population.head()
是时候进行一些数据分析了。
让我们看看数据的形状。
population.shape# output
(4195, 14)
我们有 4195 个样本和 14 个特征。
让我们检查数据集的信息。
population.info()# output<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4195 entries, 0 to 4194
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Year 4195 non-null int64
1 Country 4195 non-null object
2 Population 4195 non-null int64
3 Yearly % Change 4195 non-null float64
4 Yearly Change 4195 non-null int64
5 Migrants (net) 3600 non-null float64
6 Median Age 3600 non-null float64
7 Fertility Rate 3600 non-null float64
8 Density (P/Km²) 4195 non-null object
9 Urban Pop % 4082 non-null float64
10 Urban Population 4082 non-null float64
11 Country's Share of World Pop % 4195 non-null float64
12 World Population 4195 non-null int64
13 Country Global Rank 4195 non-null int64
dtypes: float64(7), int64(5), object(2)
memory usage: 459.0+ KB
通过查看上面的输出,我可以说一些事情。
- 国家和密度(P/Km)是对象类型。所以我会把它们分别换成 String 和 integer。
- 密度(P/Km)在数值上有额外千个逗号。例 1111。所以让我们先去掉它。
- 很少有丢失的值,但是现在我将忽略它们。
# remove extra symbol
population['Density (P/Km²)'] = population['Density (P/Km²)'].replace(',','')
现在让我们更改国家类型和密度值。
population['Density (P/Km²)'] = population['Density (P/Km²)'].astype(int)population['Country'] = population['Country'].astype(str)
现在我们来看看描述性统计。
population.describe()
数据分析和可视化
问题 1:2020 年人口排名前 30 的国家。
*# 2020 population data*
current_population = population[population['Year'] == 2020][:30]
plt.rcParams['figure.figsize'] = (25, 7)
ax = sns.barplot(x = current_population['Country'][:30], y = current_population['Population'][:30], palette = 'dark')
ax.set_xlabel(xlabel = 'Countries', fontsize = 10)
ax.set_ylabel(ylabel = 'Population in Billion', fontsize = 10)
ax.set_title(label = 'Population of top 30 countries in 2020', fontsize = 20)
plt.xticks(rotation = 90)
plt.show()
2020 年前 30 个国家的人口。
plt.figure(figsize=(9,25))
ax = sns.barplot(x="Population", y="Country",
data=current_population, palette="tab20c",
linewidth = 1)
for i,j **in** enumerate(current_population["Population"]):
ax.text(.5, i, j, weight="bold", color = 'black', fontsize =10)
plt.title("Population of each country in 2020")
ax.set_xlabel(xlabel = 'Population in Billion', fontsize = 10)
ax.set_ylabel(ylabel = 'Countries', fontsize = 10)
plt.show()
问题 2:2020 年前 10 个国家在世界人口中的总份额。
unique_countries = population['Country'].unique()
plt.style.use("seaborn-talk")
*# set year*
year = 2020df_last_year = population[population['Year'] == year]series_last_year = df_last_year.groupby('Country')['Population'].sum().sort_values(ascending=False)
labels = []
values = []
country_count = 10
other_total = 0
for country **in** series_last_year.index:
if country_count > 0:
labels.append(country)
values.append(series_last_year[country])
country_count -= 1
else:
other_total += series_last_year[country]
labels.append("Other")
values.append(other_total)
wedge_dict = {
'edgecolor': 'black',
'linewidth': 2
}
explode = (0, 0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
plt.title(f"Total Share of in World's Population the top 10 countries in **{**year**}**")
plt.pie(values, labels=labels, explode=explode, autopct='**%1.2f%%**', wedgeprops=wedge_dict)
plt.show()
- 中国是世界人口最多的国家,其次是印度。
问题 3:世界上人口最多的五个国家。
population_top5_2020 = population[population['Year'] == 2020][:5]
top_5_countries = population_top5_2020['Country'].unique()top5_popultion = population[population['Country'].isin(top_5_countries)][['Year', 'Country', 'Population']]
top5_popultion_pivot = top5_popultion.pivot(index='Year', columns='Country', values='Population')
top5_popultion_pivot.style.background_gradient(cmap='PuBu')# Please note, in medium I am unable show the gradient color.
fig,ax = plt.subplots(figsize=(20, 10))
sns.despine()
sns.set_context("notebook", font_scale=1.5, rc={"lines.linewidth": 2})
sns.barplot(x="Year", y="Population", data=top5_popultion, hue='Country')
ax.set_ylabel(ylabel = 'Population in Billion', fontsize = 10)
ax.set_xlabel(xlabel = 'Year', fontsize = 10)
ax.set_title('Top 5 most populated countries in the World')
ax.legend();
问题 4:2020 年哪个国家人口密度高?
population_2020 = population[population['Year'] == 2020]fig = px.choropleth(population_2020, locations="Country",
locationmode='country names', color="Density (P/Km²)",
hover_name="Country", range_color=[1,1000],
color_continuous_scale="blues",
title='Density of Countries in 2020')
fig.update(layout_coloraxis_showscale=True)
fig.show()
*# highest dense country by population*
population_2020[population_2020['Density (P/Km²)']==population_2020['Density (P/Km²)'].max()][['Country','Density (P/Km²)']]
*# lowest dense country by population*
population_2020[population_2020['Density (P/Km²)']==population_2020['Density (P/Km²)'].min()][['Country','Density (P/Km²)']]
问题 5:哪个国家人口众多?
*# highly populated country*
population_2020[population_2020['Population']==population_2020['Population'].max()][['Country','Population']]
fig = px.choropleth(population_2020, locations="Country",
locationmode='country names', color="Population",
hover_name="Country",
color_continuous_scale="dense",
title='Population of Countries in 2020')
fig.update(layout_coloraxis_showscale=True)
fig.show()
问题 6:人口超过 100 万的国家数量。
population_more_than_one_million = population[(population['Population'] >= 1000000) & (population['Year']==2020)]number_of_countries = population_more_than_one_million.shape[0]
print("There are **{}** countries in the world with more than 1 million population.".format(number_of_countries))## Output
There are 159 countries in the world with more than 1 million population.
让我们看看世界地图,那里的国家人口超过 100 万。
fig = px.choropleth(population_more_than_one_million, locations="Country",
locationmode='country names', color="Population",
hover_name="Country",
color_continuous_scale="blues",
title='Countries with more than 1 million Population')
fig.update(layout_coloraxis_showscale=True)
fig.show()
问题 7:人口超过 10 亿的国家数目。
population_more_than_one_billion = population[(population['Population'] >= 1000000000) & (population['Year']==2020)]number_of_countries = population_more_than_one_billion.shape[0]
print("There are **{}** countries in the world with more than 1 Billion population.".format(number_of_countries))# output
There are 2 countries in the world with more than 1 Billion population.
让我们看看世界地图,上面有超过 10 亿人口的国家。
fig = px.choropleth(population_more_than_one_billion, locations="Country",
locationmode='country names', color="Population",
hover_name="Country",
color_continuous_scale="reds",
title='Countries with more than 1 billion Population')
fig.update(layout_coloraxis_showscale=True)
fig.show()
只有两个国家中国和印度的人口超过 10 亿。
最后的话
我希望这篇文章对你有帮助。我尝试用数据科学来回答几个问题。还有很多问题要问。现在,明天我将转向另一个数据集。所有数据分析和可视化的代码都可以在这个 GitHub 库或者 Kaggle 内核中找到。
感谢阅读。我感谢任何反馈。
如果你喜欢我的工作并想支持我,我会非常感谢你在我的社交媒体频道上关注我:
- 支持我的最好方式就是跟随我上 中级 。
- 订阅我的新 YouTube 频道 。
- 在我的 邮箱列表 报名。
使用 Python 分析公司收入呼叫
构建一个 Python 脚本来分析公司盈利呼叫。
在本帖中,我们将摘录管理层在最近的收入电话会议中陈述的关于公司近期和未来业绩的主要要点。
代码将非常简单。我们将通过我们感兴趣的任何公司的股票,结果将是一个令人惊讶的收益电话会议的简短总结。
卡罗琳娜·格拉博斯卡在Pexels.com拍摄的照片
为什么要分析公司盈利电话
公司盈利电话是了解企业经营状况和下一季度预期的主要信息来源之一。
公司盈利电话是公开的。通常,我们可以访问该公司的网站,并拨入电话,听取管理层的意见。收益电话会议通常安排在公司收益公开发布的同一天。电话会议的结构很简单,管理层概述了上个季度的运营情况和未来的指导。此外,记者可以向最高管理层询问有关业务的问题。
他们听起来很有见地。但是,浏览整个电话可能会很耗时,尤其是当我们对多家公司感兴趣时。
因此,在这篇文章中,我们要做的是使用 Python 自动分析公司盈利呼叫。
Python 如何帮助分析公司盈利电话?
使用 Python,我们不仅能够执行定量分析,正如我们在我以前的帖子中所学的那样。其中,我们可以,例如,使用自然语言处理来分析语言结构或执行情感分析。
在本帖中,我们将重点传递公司收入电话的完整记录作为输入。然后,我们将提取关键点,这将有助于我们了解一家公司的发展方向以及最近的表现如何。以下是我们将回答的一些问题:
- 公司上个季度表现如何?
- 销售额的预期增长是多少?
- 哪条线的产品表现更好?
- 公司有望增加净利润吗?
- 还有更多
Python 脚本分析公司盈利电话
我们通过向 financialmodelingprep 发出 get 请求来开始我们的代码,以便检索最新收益的副本。
在本帖中,我们将分析苹果,但是可以随意更改公司名称来分析任何其他公司。此外,取消对变量 demo 的注释,并传递您的 API 密钥(注册后您可以在 financialmodelingprep 中免费获得一个),以便对 API 的请求能够工作。
然后,我们将从 API 获得的完整字符串存储在变量的副本中。接下来,我们可以使用 Python split 方法。该方法将创建一个 Python 列表,其中包含由每个新行(即/n 字符)分割的脚本,如下面的结果所示。
import requests
import pandas as pd
#demo= 'your api key'
company = 'AAPL'
transcript = requests.get(f'https://financialmodelingprep.com/api/v3/earning_call_transcript/{company}?quarter=3&year=2020&apikey={demo}').json()
transcript = transcript[0]['content'].split('\n')
print(transcript)
#outcome
["Operator: Good day, everyone. Welcome to the Apple Incorporated Third Quarter Fiscal Yea
现在我们有了一个 Python 列表,其中包含了最新的苹果公司的每一句话,我们将把它传递给熊猫数据帧。我们将用熊猫来分析收益记录。我们将搜索单词“expect”以保留包含单词 expect 的所有句子。
earnings_call = pd.DataFrame(transcript,columns=['content'])
word_to_analyze = 'expect'
analysis = earnings_call[earnings_call['content'].str.contains(word_to_analyze)]
text_earnings = analysis['content'].values
然后,在分析变量中,我们使用 str.contains 方法过滤掉所有含有except单词的句子。你可以随意改变这个词来分析公司的任何其他方面,比如收入、利润。
然后,我们从熊猫系列中提取值,以得到如下所示的句子。只保留带期待字样的句子。
print(text_earnings)
#outcome
array(["Tim Cook: Thanks, Tejas. Good afternoon, everyone. Thanks for joining the call today. Be...
如果你进一步研究变量 text _ incomes,你会发现有些句子还是太长了。我们将循环遍历它们,以便在每次遇到“.”时将它们分开。然后,我们将只打印包含单词和的句子:
for text in text_earnings:
for phrase in text.split('. '):
if word_to_analyze in phrase:
print(phrase)
print()
#outcome
Due to the uncertain and ongoing impacts of COVID-19, we did not provide our typical guidance when we reported our results last quarter, but we did provide some color on how we expected the June quarter to play out
In April, we expected year-over-year performance to worsen, but we saw better-than-expected demand in May and June
We expected iPad and Mac growth to accelerate and we saw very strong double-digit growth for these devices this quarter
Wearables growth decelerated as we expected, but still grew by strong double-digits and set a revenue record for a non-holiday quarter
First, results for advertising and AppleCare were impacted by the reduced level of economic activity and store closures to a degree that was in line with our expectations
However, we will provide some additional insight on our expectations for the September quarter for our product categories
On iPhone, we expect to see recent performance continue for our current product lineup, including the strong customer response for iPhone SE
We expect the rest of our product categories to have strong year-over-year performance
For services, we expect the September quarter to have the same trends that we have observed during the June quarter except for AppleCare where during the September quarter a year ago we expanded our distribution significantly
As a consequence, we expect a difficult comp for AppleCare also considering the COVID related point of sale closures this year
For OpEx, we expect to be between $9.8 billion and $9.9 billion
We expect the tax rate to be about 16.5% and OI&E to be $50 million
First one, Tim, when you look at the services business and in terms of your TV+ content production have the movement restrictions impacted the content production efforts? And along the same path four years ago your premonition on services being a $50 billion business in 2020 came sooner than expected, I don't know if you want to make any such forecast four years out and how you think services revenue is going to be
With the strong sales in Mac given the shelter-in-place, do you think the back-to-school season got pulled in by a quarter or do you expect the momentum to still continue? Thank you very much.
Luca Maestri: As I said, when I was talking about providing some commentary for the September quarter, we expect all the non-iPhone product categories to have a very strong year-over-year performance
So we expect the performance that we've seen for Mac in the June quarter to continue.
And then, can you talk a little bit more about the decision to bring Mac Silicon in-house, then the benefits that you
包扎
最后,我们总结了收益电话会议,以提取关键信息供我们分析。从上面的例子中,我们可以快速而容易地看出:
- 苹果在 5 月和 6 月的需求好于预期
- 苹果实现了非常强劲的收入增长,并创造了新的非假日季度记录
- 在今年余下的时间里,预计会有强劲的同比表现
- 运营支出约为 99 亿美元
- 产品类别绩效
这个脚本很酷的一点是,你可以将 expect 替换为要分析的单词(例如 profits ),你将得到你感兴趣的任何公司的简短摘要。
在以后的文章中,我们将继续分析盈利电话记录,执行 Python NLTK 情绪分析。
与此同时,你可以继续阅读我在 Python for Finance 上的其他帖子。
原载于 2020 年 10 月 18 日【https://codingandfun.com】。
用 Pyspark 分析 Scrum 和敏捷的区别
由 Kelly Sikkema 在 Unsplash 上拍摄的照片
Scrum 和 Agile 是两种现代软件开发方法,大多数科技公司一直在使用这些框架来开发或维护软件应用程序。那么这两者到底有什么区别呢?只需谷歌搜索,你可能会看到大量比较两者差异的文章,但如果我们尝试使用数据科学方法来发现差异,会怎么样呢?
资料组
那么我们从哪里开始呢?在这两个框架引起科技公司的注意之前,人们已经写了很多关于这两个框架的书,让我们来分析一下这些书吧!这是我们将要分析的两本书:
- 软件工程和极限编程中的敏捷过程
- Scrum 手册(杰夫·萨瑟兰)
正在初始化 Pyspark
Pyspark 是向 Python 公开 spark 编程模型的 Spark Python API。Sparkcontext 是 Spark 功能的主要入口点,它将在我们启动一个新应用程序时创建。这个 sparkcontext 向 master 请求一些内核来进行处理,这些内核将被搁置起来,不会用于其他应用程序。
我们将首先从 pyspark 创建一个 SparkContext sc
,通过设置master = local[*]
使用机器上所有可用的内核。然后,我们使用 SparkConf 对象中设置的配置创建 SparkContext 对象中提供的 SparkSession 对象spark
。
# create entry points to spark
from pyspark import SparkContext, SparkConf # Spark
from pyspark.sql import SparkSession # Spark SQL# create or use existing spark context
sc = SparkContext.getOrCreate()# If there is no existing spark context, we now create a new context using all local processors
if (sc is None):
sc = SparkContext(master="local[*]", appName="Agile Scrum comparison")
spark = SparkSession(sparkContext=sc)
创建弹性分布式数据集(rdd)
弹性分布式数据集(RDDs)是 Spark 的基本数据结构,我们将为集群上的每本书创建两个。
# read in first txt file
scrum_txt = sc.textFile('./Scrum Handbook.txt')
# print number of lines
print("Number of lines in Scrum Handbook is: ", str(scrum_txt.count()))# read in second txt file
agile_txt = sc.textFile('./Agile Processes in Software Engineering and Extreme Programming.txt')
# print number of lines
print("Number of lines in Agile Processes in Software Engineering and Extreme Programming is: ",\
str(agile_txt.count()))
我们看到软件工程和极限编程中的敏捷过程有 21569 行,大约是有 4617 行的 Scrum 手册的 5 倍。
数据清理
在此步骤中,我们执行以下文本清理和操作步骤:
- 使用
split
和flatMap
将这些行拆分成单个单词(即,标记化) - 使用正则表达式
[A-Za-z\s]
删除除空格以外的所有非字母字符 - 使用
lower
和map
将所有单词转换成小写 - 使用
strip
和map
删除所有前导或尾随空格
# import re for regular expression
import re# function to do the 3 text cleaning and manipulating steps
def cleantext(rdd):
# split the lines into individual words
words = rdd.flatMap(lambda x: x.split(' '))
# remove all characters which are not alphabets except spaces
alpha_words = words.filter(lambda x: re.findall('[A-Za-z\s]+',x))
# replace all characters which are not alphabets or spaces with ''
alpha_words_cleaned = alpha_words.map(lambda x: re.sub('[^A-Za-z\s]+','',x))
# change all to lower case
lower_alpha_words = alpha_words_cleaned.map(lambda x: x.lower())
# remove all leading or trailing spaces
cleaned_words = lower_alpha_words.map(lambda x: x.strip())
# return the result
return cleaned_words# apply cleantext function to scrum_txt
scrum_txt_cleaned = cleantext(scrum_txt)# apply cleantext function to agile_txt
agile_txt_cleaned = cleantext(agile_txt)
数数单词
在这一步中,我们执行一个转换步骤,首先使用map
为每个值为 1 的单词创建一个单词对,然后使用reduceByKey
对每个单词的频率求和。然后我们使用带有选项-1
的sortBy
按照单词出现的频率对单词进行排序,以表示降序。
# function to transform the data and count the words
def count_words(rdd):
# transformation to convert each word to a key/value pair of (word, 1)
pairs = rdd.map(lambda x: (x,1))
# transformation to sum the frequency of each word
word_count = pairs.reduceByKey(lambda x,y: x+y)
# sort the words by frequency in descending order
sorted_word_count = word_count.sortBy(lambda x: -x[1])
# output
return sorted_word_count
我们将count_word
应用于 Scrum,并使用take(20)
显示前 20 个最常用的单词
# apply count_words function to scrum_txt_cleaned and display top 20 most frequent words
scrum_txt_wordcount = count_words(scrum_txt_cleaned)
scrum_txt_wordcount.take(20)
我们将count_word
应用于敏捷,并使用take(20)
显示前 20 个最常用的单词
# apply count_words function to agile_txt_cleaned and display top 20 most frequent words
agile_txt_wordcount = count_words(agile_txt_cleaned)
agile_txt_wordcount.take(20)
根据每本书中的频率比较前 20 个词,它们大多是停用词,如 the,of 和。我们应该在下一步中删除它,以便更好地分析书籍。
删除停用词
在计算中,停用词是在处理自然语言数据之前或之后过滤掉的词。在自然语言处理中,无用词(数据)被称为停用词,它在文本分析中几乎不提供上下文。我们将从nltk.corpus
包中获取停用词列表,并使用函数filter
删除两本书中的停用词。最后,我们显示每本书中独特单词的数量。
# import nltk package and stopwords
import nltk
from nltk.corpus import stopwords
# get the english stopwords since there are 16 languages available
eng_stopwords = set(stopwords.words('english'))# filter off those words in scrum_txt_wordcount that are in eng_stopwords list
scrum_txt_no_stopwords = scrum_txt_wordcount.filter(lambda x: x[0] not in eng_stopwords)
# get the number of unique words of each text after removal of stopwords
print("Number of unique non stopwords in Scrum Handbook is:",str(scrum_txt_no_stopwords.count()))
# filter off those words in agile_txt_wordcount that are in eng_stopwords list
agile_txt_no_stopwords = agile_txt_wordcount.filter(lambda x: x[0] not in eng_stopwords)
# get the number of unique words of each text after removal of stopwords
print("Number of unique non stopwords in Agile Processes in Software Engineering and Extreme Programming is:",\
str(agile_txt_no_stopwords.count()))
一个词的平均出现次数
在这一步,我们先用sum
和map
求出每本书的总字数,然后用这个值除以唯一字的数量,从而求出一个字的平均出现次数。
# get total number of words in scrum_txt_no_stopwords
total_scrum_words = scrum_txt_no_stopwords.map(lambda x: x[1]).sum()
# find avg occurence of the words and return result in 3 decimal place
print("Average occurence of words in Scrum Handbook is:",\
round(total_scrum_words/scrum_txt_no_stopwords.count(),3))
# get total number of words in agile_txt_no_stopwords
total_agile_words = agile_txt_no_stopwords.map(lambda x: x[1]).sum()
# find avg occurence of the words and return result in 3 decimal place
print("Average occurence of words in Agile Processes in Software Engineering and Extreme Programming is:",\
round(total_agile_words/agile_txt_no_stopwords.count(),3))
单词分布
我们可以使用可视化matplotlib.pyplot
来分析单词的分布,方法是绘制每本书中的单词总数,然后绘制每本书中单词的平均出现次数。
# import the standard python plotting library and numpy for easy data manipulation
import matplotlib.pyplot as plt
import numpy as np
import math
# to show plot in jupyter notebook
%matplotlib inline# create three subplots
f, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(12,4), tight_layout=True)# Plot 1 - Total number of words
# prepare the data
y_axis_1 = [math.log10(total_scrum_words), math.log10(total_agile_words)]
x_axis = ('Scrum Handbook', 'Agile Processes')
bar_width = 0.5
# plot
ax1.bar(x_axis, y_axis_1, bar_width, align='center', color='C0')
ax1.set_xlabel('Book')
ax1.set_ylabel('Log Scale of number of words')
ax1.set_title('Total number of words in each book')# Plot 2 - Total number of unique words
# prepare the data
y_axis_2 = [scrum_txt_no_stopwords.count(), agile_txt_no_stopwords.count()]
x_axis = ('Scrum Handbook', 'Agile Processes')
bar_width = 0.5
# plot
ax2.bar(x_axis, y_axis_2, bar_width, align='center', color='C1')
ax2.set_xlabel('Book')
ax2.set_ylabel('Number of unique words')
ax2.set_title('Total number of unique words in each book')# Plot 3 -Average Occurence of word
# prepare the data
y_axis_3 = [total_scrum_words/scrum_txt_no_stopwords.count(), total_agile_words/agile_txt_no_stopwords.count()]
bar_width = 0.5
# plot
ax3.bar(x_axis, y_axis_3, bar_width, align='center', color='C2')
ax3.set_xlabel('Book')
ax3.set_ylabel('Average Occurence of word')
ax3.set_title('Average Occurence of word in each book')plt.show()
作者图片— matplotlib 绘制单词分布图
从图中可以清楚地看出,软件工程和极限编程中的敏捷过程是一本比 Scrum 手册更长的书,在去除了停用词和文本处理之后,在 log10 的标度上有 1.25 倍多的单词, 3 倍多的独特单词,并且前者中的每个单词比后者出现两次多。
最常见的单词
现在让我们比较一下每本书中最常见的 15 个单词。
# create two subplots
f, (ax1, ax2) = plt.subplots(1, 2, figsize=(12,4), tight_layout=True)# Plot 1 - Top 15 of scrum handbook
# prepare the data
top15_scrum_word = scrum_txt_no_stopwords.map(lambda x: x[0])
top15_scrum_word = top15_scrum_word.take(15)
top15_scrum_value = scrum_txt_no_stopwords.map(lambda x: x[1])
top15_scrum_value = top15_scrum_value.take(15)
# plot
bar_width = 0.5
ax1.bar(top15_scrum_word, top15_scrum_value, bar_width, align='center', color='C0',label='Scrum Handbook')
plt.setp(ax1.get_xticklabels(), rotation=90)
ax1.set_xlabel('Scrum Handbook')
ax1.set_ylabel('Count of words')
ax1.set_title('Total 15 words in Scrum Handbook')
ax1.legend()# Plot 2 - Top 15 of agile processes
# prepare the data
top15_agile_word = agile_txt_no_stopwords.map(lambda x: x[0])
top15_agile_word = top15_agile_word.take(15)
top15_agile_value = agile_txt_no_stopwords.map(lambda x: x[1])
top15_agile_value = top15_agile_value.take(15)
# plot
bar_width = 0.5
ax2.bar(top15_agile_word, top15_agile_value, bar_width, align='center', color='C1',label='Agile Processes')
plt.setp(ax2.get_xticklabels(), rotation=90)
ax2.set_xlabel('Agile Processes')
ax2.set_ylabel('Count of words')
ax2.set_title('Total 15 words in Agile Processes')
ax2.legend()plt.show()
按作者分类的图像— matplotlib 在最常用的单词上绘图
对比两本书的前 15 名,两本书的内容非常相似,都围绕着产品、团队、开发和软件。
摘要
基于这篇我在 Google 上找到的关于敏捷和 Scrum 的区别的文章,敏捷是一种项目管理哲学,它利用了一套核心的价值观或原则,而 Scrum 是一种特定的敏捷方法,用于促进项目。
基于我们对这两本书的分析,我们发现了一个相似的发现,即 Scrum Handbook 关注团队开发,这是项目经理促进项目的一种方式,而软件工程和极限编程中的敏捷过程更关注一般的软件开发。
这就对了,希望这种数据分析方法可以给你另一个角度来比较差异,而不是依赖我们最可靠的合作伙伴,谷歌!
分析我的锁定睡眠数据
过去的几个月对我们大多数人来说都是动荡不安的时期,不管是以这样还是那样的形式,但是我们的睡眠是变好了还是变坏了呢?
过去的几个月对我们大多数人来说都是一段动荡的时期,无论形式如何。无论这种动荡是来自生活方式的彻底改变,还是更简单的事情,比如与你的公寓“伙伴们”全天候关在一起。
就我个人而言,我经历过:
- 完全可变的工作时间表
- 由于搬家,完全不同的社会环境
- 对当前和未来计划的新看法
因此,我问自己的一个问题是,这种生活方式的改变在多大程度上改变了影响我健康的关键因素:睡眠、锻炼和饮食。不幸的是,我还没有记录任何关于我饮食的数据,然而,我很幸运地在去年 9 月投资了一个健康穿戴设备,允许我访问我在锁定前、锁定后和锁定中的睡眠和运动数据。以下是我的发现…
一年的睡眠数据
几周前,我在健身应用程序的设置中翻找,该应用程序允许我检查我的睡眠和健身数据(通过我的手表检测的运动来跟踪),我注意到了以下选项:
一个下载按钮!
在意识到我可以请求方便的 CSV 文件,包含我的数据的简化视图后,我知道我必须这样做。这将允许我执行任何我希望的分析,消除应用程序的所有限制(即,现在我可以比较更长时间内的数据,而不是滚动查看每周的平均值)。
通过少量的 Python 代码,我现在有能力可视化一整年的健康数据。想到的第一个分析指标是什么?每晚总睡眠时间。
因此,为了避免看到不可读、参差不齐的混乱,我选择了 30 天滚动平均值,加上一些颜色,瞧:
作者图片
很高兴看到我每晚的平均睡眠时间持续超过 7 小时。除此之外,随着国家进入封锁期,我们可以看到总睡眠时间明显增加,在我搬家后,这种情况还会继续(如果不是又一次增加的话)。
表面上看,这很棒。但是我们至少应该带着一些怀疑的态度来看待它(也许你已经是了)。更多的睡眠不一定意味着更好的睡眠。有趣的是,我们可以深入研究,看看睡眠是如何分为浅睡眠和深睡眠的:
作者图片
没想到啊!随着我的总睡眠时间在禁闭期间开始增加,深度睡眠没有明显的变化;但是,当我们进入八月时,价格明显下降。今年年初,我的浅睡和深睡比例接近 50:50(这实际上是标准应用程序指标所建议的),但当我进入一个新环境和新房子时,一个非常明显的差异出现了。
最后,我的手表还测量我晚上醒着的时间:
作者图片
另一个有趣的情节是,由于在任何特定点的总清醒时间从来没有那么高(谢天谢地),然而,随着我们从 2 月到 3 月,以及最终的锁定,仍然有明显的增加。也许是新冠肺炎时代前后矛盾的结果?
这就是我们对睡眠的长达一年的回顾,涵盖了全球疫情、全国禁闭和本地重新安置。总结一下:
- 当我们进入一级防范禁闭状态时,我的总平均睡眠时间似乎增加了,在我搬家后又增加了。
- 尽管浅睡眠遵循相似的趋势,但深睡眠看起来是负相关的。
- 在一月份,我的浅度睡眠和深度睡眠的平均时间大致相等,但是最近,在一级防范禁闭后,这种情况迅速逆转。
- 我醒着的时间也越来越长。这不是一个好的趋势,尽管实际金额仍然相对较低。
我对未来的最后想法是:
- 饮食也是分析封锁前/后/中期变化的有趣领域。感觉好像我已经养成了一些新习惯。特别是重复相同的食物组合。
- 想知道我在数据中发现的趋势对大多数人来说是否是共同的,这将是一件有趣的事情。或者其他人在禁闭期间有过相反的经历?
- 总的来说,这些实验提供了非常有用的见解,我愿意继续实验。具体来说,如果锁定导致我的总睡眠时间增加,但我的睡眠质量下降,那么可以隔离导致这些影响的锁定组件,从而使它们可以在锁定之外帮助增加睡眠和睡眠质量吗..?
如果您喜欢这篇文章,您可能也会喜欢我在锁定期间对我的活动数据所做的类似分析🏃🏼♂️即将上映…
用 Python 分析药品销售数据
如何使用 Python、Pandas、Matplotlib 和回归模型分析药品销售数据
介绍
这个项目的目的是分析药品销售数据。分析销售数据并根据历史数据预测未来销售是一项非常常见的数据科学任务。这是开始研究数据科学的好方法。
你会学到什么?
在本项目中,您将学习将数据集从文本文件加载到 Pandas,这是最流行的数据操作和数据分析 Python 库,并在不同的销售数据集中查找特定信息,如特定药物最常何时销售。除此之外,我们还将根据现有数据,使用线性回归、多项式回归和简单向量回归来预测未来的销售额。我们将做一些数据预处理和标准化。为了获得更好的结果,我们还将学习一种重要而有用的数据科学技术——集成学习。
您还将学习如何使用 Matplotlib 测试模型和绘制结果。
让我们开始吧。
问题定义
以下是我们将在本练习中回答的具体问题:
- 第二种药物(M01AE)最常在一周的哪一天售出?
- 2015 年 1 月,2016 年 7 月,2017 年 9 月哪三种药销量最高?
- 2017 年周一哪种药卖得最多?
- 2020 年 1 月可能有哪些药品销售?(我们的数据集仅包含 2014 年 1 月至 2019 年 10 月的销售信息)
逐步解决方案
创建项目文件夹
在电脑上为一个名为“分析-制药-销售-数据”的项目创建一个文件夹
从这个 Kaggle 项目下载数据集:
https://www.kaggle.com/milanzdravkovic/pharma-sales-data
将这些数据集放在项目文件夹中名为“data”的文件夹中。
如果你从未在电脑上使用过 Python 或 Jupyter Notebook,请阅读我的文章如何为数据科学设置你的电脑以检查你是否拥有在电脑上运行以下分析所需的一切。
开始新的笔记本
在终端/命令提示符下键入命令,启动 Jupyter Notebook:
$ jupyter notebook
点击右上角的新建,选择 Python 3。
作者图片
这将在您的浏览器中打开一个新的 Jupyter 笔记本。将未命名的项目名称重命名为您的项目名称,您就可以开始了。
作者图片
如果您的计算机上安装了 Anaconda,那么您的计算机上已经安装了这个项目所需的所有库。
如果你用的是 Google Colab,打开一个新的笔记本。
加载库和设置
在新笔记本中,我们通常做的第一件事是添加我们在项目中需要使用的不同库。
现在我们准备解决我们的第一个问题。
第二种药物(M01AE)最常于一周的哪一天售出?
一旦我们加载了所有的库,通常我们下一步要做的就是加载数据集。因为我们需要找出一周中的哪一天是第二种最常销售的药物,所以我们需要加载每日数据。我们正在加载此数据集,以便进一步探索熊猫数据框。
这是我们数据的样子。
作者图片
这将显示数据集中的前几行,这样我们就可以看到数据的结构和内容。
为了找出第二种药物(M01AE)在一周中的哪一天最常被卖出,我们需要将所有结果相加
因为 Python Pandas 非常强大,我们可以使用一行代码来完成这些事情中的大部分。
上面的命令将按工作日名称对所有销售额求和,然后进行排序,因此药品销售最多的那一天将出现在第一行。
作者图片
现在我们只需要从第一行中获取工作日的名称和值。
我们现在需要做的就是打印结果。
如果您正确完成了任务,屏幕上的结果应该是这样的。
第二种药物 M01AE 在周日的销量最高,为 1384.94 英镑
我们鼓励您也找出其他药物在一周中的哪一天最常出售。
现在我们来看第二个问题。
【2015 年 1 月、2016 年 7 月、2017 年 9 月哪三种药销量最高
对于这个任务,我们需要将每月的销售数据加载到 Pandas 数据框架中,让我们看看我们的数据是什么样子的。
作者图片
因为我们将对不同的年份和月份重复计算,所以最好定义一个将月份和年份作为参数的函数。
该函数将如下所示。
一旦定义了函数,我们就可以对一个月和一年的不同整数值运行该函数。
如果您正确完成了任务,您应该会收到以下结果。
【2015 年 1 月销售额排名前三的药物
- 产品:N02BE,销量:1044.24
- 产品编号:N05B,销量:463.0
- 产品:R03,销量:177.25
2016 年 7 月销售额排名前三的药物
- 产品:N02BE,销量:652.36
- 产品编号:N05B,销量:240.0
- 产品:M01AB,销量:203.97
2017 年 9 月销量前三的药品
- 产品:N02BE,销量:863.75
- 产品:N05B,销量:223.0
- 产品:R03,销量:139.0
这是我们完成的第二项任务。让我们看看第三项任务。
2017 年周一哪种药卖得最多?
为了回答这个问题,我们需要加载一个每日销售数据集。
这就是我们熊猫数据框的样子。
作者图片
现在,我们需要过滤销售额,以便只获得 2017 年星期一的销售额。
我们现在需要按照工作日名称和总和值对结果进行分组。
现在我们需要对这些值进行水平排序,以获得左边的最大值。水平排序类似于更常用的垂直排序,但水平滚动不是按列排序,而是按行排序。
现在,我们将在左起第一列中获得 2017 年周一销售最频繁的药物。
作者图片
我们唯一需要做的就是获取这个值并打印出结果。
The drug most often sold on Mondays in 2017 is N02BE
with the volume of 1160.56
在上述练习中,我们将数据集加载到 Pandas 数据框中,并使用分组、排序和汇总等功能寻找特定信息。这些是练习这些类型的数据操作的很好的练习,我们将在接下来的练习中经常使用它们。
【2020 年 1 月可能有哪些药品销售?
我们现在来看看回归,这是一项非常常见的数据科学任务。回归的思想是根据一个或多个自变量的值来预测因变量的值。使用不同的回归方法和过去的数据,我们可以尝试预测未来的值。
在本练习中,我们将针对 2014 年至 2019 年间记录的数据,尝试预测未来几个月的销量。
预处理
查看数据集,我们可以看到数据质量良好,但有些记录中至少有一组药物的销售额为 0。这通常是我们在运行任何机器学习模型之前需要注意的事情。在这种情况下,我们有几个选择;我们可以删除至少一组药物的记录销售值为 0 的行,或者我们也可以用该组的平均值或中值替换 0 值。为简单起见,我们将删除至少一组药物的记录销售额为 0 的所有记录,但我们建议您再次重复此练习,并用该组的平均值或中值替换 0 值,以查看您是否会获得更好的结果。
数据的另一个重要特征是,它包含了 2019 年不完整的销售数据。记录的最后一天是 10 月 8 日,这意味着 10 月份的销售数据不完整。因为对于本练习中的回归方法,我们仅使用月度销售数据,所以我们从分析中排除了 2019 年 10 月的数据。
车型和技术
我们将使用 Pandas 来读取 CSV 数据文件和数据预处理,并使用 Scikit-learn Python 库来学习回归模型。
对于数据可视化,我们将使用 Matplotlib Python 库。
我们将使用以下回归模型:
- 线性回归
- 多项式回归
- 简单向量回归
Scikit-learn 库包括所有上述模型的实现。
我们已经在笔记本的开头加载了所有需要的 Scikit-learn 库。
我们将分割数据,我们将使用 70%的数据训练模型,30%的数据进行测试。
我们将使用投票回归器来组合不同的机器学习回归器,并返回平均预测值。我们这样做是为了平衡个体回归者的弱点。
计算和绘图
我们将显示所有回归和投票回归变量的单个结果,并将所有回归绘制在图表上,以直观地评估数据如何分散以及回归如何在数据集值之间绘制。
因为我们正在处理一个相对较大的项目,所以使用函数来组织代码是一个好主意。
让我们从将我们的训练和测试数据分散在图表上的函数开始。
现在,我们将创建线性回归、多项式回归和 SVR 预测函数。这些函数将训练和测试值作为参数,计算回归并显示 2020 年 1 月的预测值以及计算的精度和误差值,以便我们可以看到模型的有效性。
线性回归预测函数。
多项式回归预测函数。
简单向量回归(SVR)预测函数。
在下一个 Jupyter 笔记本单元中,我们可以编写使用上述函数的代码,显示预测值,并使用 Matplotlib 可视化我们的训练和测试数据以及不同的回归模型。
对于计算,我们将再次使用第二个产品(M01AE),但我们鼓励您也对其他产品进行类似的计算。
我们需要用产品名定义我们的产品变量,我们将为其计算回归。接下来,我们将定义 Pandas 数据框,我们将在其中存储我们的回归结果。然后我们将定义 predictFor 变量,它是值序列中的一个月的数字,用于预测相关销售额。因为我们有 2019 年 10 月之前的数据,而不是 2019 年 12 月,我们预测未来 3 个月。
作者图片
作者图片
Predictions for the product N02BA sales in January 2020
执行并保存线性回归的结果。
作者图片
执行并保存多项式回归的结果。
作者图片
执行并保存简单向量回归(SVR)的结果。
为了获得更好的结果,我们将使用投票回归器,这是一种集成技术,它使用几个模型,然后对单个预测进行平均,并返回最终预测。
Voting Regressor January 2020 predicted value: 98.0
显示所有结果
regResults
作者图片
总结
在本练习中,我们学习了使用 Python Pandas,这是数据科学中最流行的数据操作和分析库。对于初学数据科学家来说,使用 Pandas 加载数据集并执行统计分析是最重要的元素之一。
接下来,我们看了回归,这是数据科学的另一个非常重要的元素。线性回归、多项式回归和支持向量回归是回归的基本模型。
为了巩固你的知识,考虑从头开始完成任务,不要看书中的代码示例,看看你会得到什么结果。这是巩固你的知识的一件极好的事情。
Jupyter 笔记本的完整 Python 代码可在 GitHub 上获得:
https://GitHub . com/pj online/Basic-Data-Science-Projects/tree/master/1-analyzing-Pharmaceutical-Sales-Data
编码快乐!
还没有订阅媒体?考虑报名成为中等会员。每月只需 5 美元,你就可以无限制地阅读媒体上的所有报道。订阅 Medium 支持我和其他作家在 Medium 上。
使用 tableau 分析(ADIL)股票
“作者提供的图像”
你在学习如何摆拍吗?厌倦了使用默认的超级商店数据,想尝试一些更实用的东西吗?试试这个分析股票的快速指南,看看它会带你去哪里!
收集您的数据
- 去雅虎财经查一只股票。真的,什么股票都行。如果是你碰巧持有的股票就更好了!
- 在股票的摘要页面上,转到标签为历史数据的选项卡。
- 将视图更改为所需的时间段(默认为一年)。
- 单击“下载数据”链接下载 CSV 文件。
请注意,在示例的剩余部分,我将使用 CSV 显示该股票在以下时间段的数据:2019 年 1 月 20 日-2020 年 1 月 20 日。
“作者提供的图像”
ADIL 雅虎财务历史数据
准备您的数据
数据准备始终是将原始数据引入 Tableau 的第一步。在这种情况下,我们的数据已经相对干净和简单。但为了以防万一,我们需要检查一下。
要准备数据,请在 Excel 或 Google Sheets 中打开它。检查一下格式。如果您愿意,可以更改任何列的默认标题。在这些情况下,我们很可能不会改变什么。
“作者提供的图像”
在 Tableau 中可视化您的数据
如果需要,在 Excel 中保存对 CSV 文件的任何更改,然后关闭它。然后,我们开始 Tableau 吧!
在 Tableau 中打开 CSV 文件
- 打开 Tableau 桌面。
- 在“连接”下,查找“到文件”,然后选择“更多…”
- 浏览到 CSV 文件的位置并打开它。现在我们看到了 Tableau 数据源视图。
- 单击“工作表 1”选项卡打开工作簿视图。现在我们准备开始可视化!
请注意左侧的数据窗格。这里,我们有维度和度量。由于这些数据大多包含可衡量的数字,如开盘价、收盘价和调整后收盘价以及成交量,因此需要衡量的项目要多得多。
构建工作簿—可视化每日收盘价
- 双击‘日期’维度。这将自动将其带到工作簿的列区域。
- 点击并拖动“调整接近”指标到工作簿的行区域。请注意,我们使用的是调整后的收盘价,而不是收盘价,因为这更准确。如果你想知道原因,请点击这里阅读更多内容。
现在我们有了一个基本的线图,向我们展示了……到底是什么?绝对不是我们要找的。所以,我们需要进一步分解。
注意到标有年份(日期)的列区域中的药丸了吗?当我们双击日期维度时,它出现了。这表明我们目前只查看了数据中的年份— 2019 年和 2020 年的前几周。我们的可视化显示,我们的股票价格在 2019 年至 2020 年期间下跌。它还把今年所有的收盘价加起来,这也肯定不是我们想要的。
这是因为我们的日期目前是离散的,这意味着它添加了整个相应年度的每个调整后收盘价。由于我们的例子中 2019 年大约有 49 周,2020 年有 3 周,当然 2019 年的价格更高。 - 将鼠标悬停在月份(日期)药丸上,直到您看到右侧有一个朝下的三角形。点击三角形调出菜单。
注意,菜单显示了两个看起来相同的日期选项,顶部的年份选项被选中。还要注意选择了离散。边注,我们也可以看出这个维度是离散的,因为药丸是蓝色的。如果它是绿色的,它将是连续的。 - 在菜单中,从第二组日期选项中选择“日”。注意药丸现在是绿色的,可视化看起来像我们需要的!我们现在正在查看一个线形图,显示 CSV 文件中整个日期期间每天调整后的收盘价。
“作者提供的图像”
我们的第一次股票价格可视化!
设置工作簿的格式
让我们清理一些东西,使这个东西看起来更专业一点。
格式化标题
- 双击工作簿的标题(当前为“工作表 1”)。
- 将名称改为描述性的名称,例如“ADIL 收盘价”,并在下面加上副标题和日期范围。调整字体大小,让标题比副标题更有影响力。
“作者提供的图像”
格式化 Y 轴
- 在 Y 轴(垂直轴)旁边,双击标题“Adj Close”
- 在对话框中,在轴标题下,让我们继续清除标题。假设我们已经将图表命名为 ADIL 收盘价,那么 Y 轴表示收盘价应该是很直观的。完成后关闭对话框。
- 右键单击(或在 Mac 上按住 control 键单击)Y 轴数字上的任意位置,然后选择“格式”
- 在“比例”下,选择“数字”旁边的箭头,然后选择“货币(标准)”现在我们的观众肯定知道这是收盘价的范围。
- 既然我们在这里,让我们继续将“Ticks”更改为“None”
X 轴格式 对于 X 轴(水平轴),我们真的不需要标题,因为我们知道那些是日期。
- 双击“日期”,在“轴标题”下,简单地删除标题。
看起来已经好多了!但是还有一件事我们可以做,让这个看起来更专业——删除那些网格线! - 转到格式>工作簿。
- 在现在出现在左侧的“工作簿格式”选项下,转到“线条”并选择“网格线”旁边的向下三角形。把它从自动改为关闭。
“作者提供的图像”
现在我们看起来不错!
但是等等,我们还可以添加更多!还记得我们的 CSV 文件有一个显示容量的列吗?这是某一天交易的股票数量。你可以在这里阅读更多关于交易量的信息,但是添加这个会让这个可视化看起来特别专业。我们有两个选择。
添加第二个度量值作为颜色
这个很简单。我们希望更改图表中线条的颜色,以指示交易量较高的区域。只需将“音量”从测量区域拖放到“标记”下的“颜色”框中
注意这条线在某些区域改变了颜色——较暗的区域是股票交易量较高的地方。你能把这些和股价的涨跌联系起来吗?
添加第二个度量作为双轴
如果你想看起来更高级更专业一点(你当然想),试试这个!
- 如果需要,通过将药丸从标记拖到下面的空白区域来删除上一部分的测量颜色。(将任何药丸拖到此区域会将其从工作簿中删除。)
- 将“Volume”从度量区域一直拖到工作簿的最右侧,直到它显示一个垂直矩形。在这里释放。现在,左边的 Y 轴显示了我们的收盘价范围,右边的 Y 轴显示了我们的成交量范围。现在,让我们格式化一下。
- 在“Marks”下,您现在应该会看到三个可折叠的部分——All、SUM(Adj Close)和 SUM(Volume)。展开最后一个,SUM(体积)。
- 使用下拉菜单,将其从线条更改为条形。
- 同样在标记>总和(体积)下,单击标记为“大小”的框,将其从“固定”更改为“手动”
- 让我们继续更改工作簿的标题,这样我们就可以完成新 Y 轴的格式化。双击标题,并将其更改为 ADIL 收盘价和成交量。单击“确定”退出对话框。
- 双击右侧的 Y 轴;删除标题。
- 在同一对话框中,选择“刻度”标签。将“主要刻度线”从“自动”更改为“固定”关闭对话。
- 最后一点家务——让我们去掉剩下的线。右键单击(或按住 command 键单击)左侧的 Y 轴,然后选择“格式”
- 在左侧“格式”面板的顶部,选择“边框”选项(看起来像方形窗格)。
- 在行分隔线>窗格下,选择无。
- 在列分隔符>窗格下,选择无。关闭“格式”面板。
“作者提供的图像”
嘿,你都快成职业选手了!
我们还没完呢!想解决股票分析和研究的基本介绍?你当然知道!
研究发现
看你的练习册。看到什么突出的东西了吗?
注解一下!
让我们从两个明显的点开始——52 周高点和 52 周低点。这些应该很容易在你的练习册中找到。你甚至可以将光标放在该点上,Tableau 会告诉你日期和价格。让我们这样注释它们。
- 右键单击(或按住 command 键单击)高点,然后选择“批注”>“点”。
- 清除对话中的默认值。将 justification 设置为 left,并输入一些内容来帮助我们理解这里发生的事情,如“52 周高点:6.88 美元,2 月 1 日。”
“作者提供的图像”
注释对话
对 52 周低点重复这些步骤。然后,对交易量中的主要异常值做类似的事情。在我们的例子中,我们可以在 2 月 21 日看到一个主要的异常值。让我们在 12 月 16 日标记今年晚些时候的另一个异常值。称之为“主要交易量:550 万,2 月 21 日。”使用与 52 周最高价和最低价相同的格式。
研究一下吧!
现在真正有趣的部分来了——看看我们是否能找出这些事件发生的原因。你能通过查看公司的投资者关系页面回答以下问题吗?提示:所有上市公司的网站上都有这一部分。
- 为什么该股在 2 月 1 日创下历史新高?
- 为什么股票在 12 月 5 日跌到了历史最低点?
- 为什么该股在 2 月 21 日出现如此高的交易量?
- 为什么 12 月 16 日会出现随机的高成交量?
- 季度业绩是什么时候公布的?(找到这些日期时,请注明)
在公司的投资者关系页面,从新闻稿开始。你的基本答案一般都在这里。就我们使用的股票而言,我们可以发现:
- 这位首席执行官出现在 2 月 1 日的两个新闻节目中,其中一个是在湾区…也是众所周知的充满风险资本和投资者的地区。请注意,这与同一天的高交易量(近 190 万)相关。
- 2 月 21 日,该公司公开发行 800 万美元股票,试图筹集更多资金。这与交易量的大幅上升相关,但也与股价的螺旋式下降相一致,因为这可能会稀释价值。
- 季度业绩分别于 5 月 13 日、8 月 13 日和 11 月 14 日发布。这些都与图上任何未完成的活动无关。然而,这种结果往往与交易量的上升和价格的上涨或下跌相关,这取决于消息的好坏。
- 最后,在 12 月 16 日,该公司宣布了一项额外专利的许可,这与更大的交易量和收盘价的大幅上升相关。
结论
在注释完你发现的重要的东西后,看看你可能会有什么!一张漂亮的信息图,有股票的基本分析。
“作者提供的图像”
你学到了什么:
- 如何在雅虎财经上查找一只股票并下载其一年的历史数据?
- 检查数据,以确保为 Tableau 做好准备。
- 将 CSV 导入 Tableau。
- 创建带有折线图、双轴折线图和条形图的工作簿。
- 研究和分析股票的基本历史活动。
最后说明:如果你想下载并玩它,这在 Tableau Public 上。祝你的舞台和股市之旅好运!
欧洲电视网变得不那么俗气了,我们可以从数学上证明这一点
数字音乐
借助 Spotify 公共 API 的一点点帮助
有一项年度电视赛事,全球观众约有两亿人(大约是超级碗的两倍)收看 T2 的比赛。它的 YouTube 频道号称有超过 43 亿的浏览量。没有它,不管是好是坏,你都不会听说过 ABBA。或者是史诗萨克斯手。
2019 年欧洲电视网歌曲大赛的获奖表演
“像凤凰一样崛起”
欧洲电视歌曲大赛于 1956 年由欧洲广播联盟创立,旨在将饱受战争蹂躏的欧洲大陆聚集在一个“轻松娱乐节目”的周围。尽管自成立以来技术细节已经发生了变化,但欧洲电视网的主要前提依然如故。每个参赛国都会送出一首原创歌曲,作为一个晚间电视节目的一部分。
在节目的最后,每个人都会根据全国听众来电的结果和音乐专业人士组成的“全国评审团”的意见,给其他国家的歌曲打分。哪首歌得分最高,哪首歌就获胜,获胜的国家将获得举办明年比赛的“荣誉”。
欧洲电视网以不敬和印花棉布闻名。精心制作的舞台表演、烟火表演和华丽的服装比比皆是(这场比赛在 LGBT 群体中拥有狂热的追随者。然而,许多人对真正的音乐的看法被 90 年代和 00 年代的记忆所模糊,在那个时期,大多数国家都不幸地倾向于非常令人震惊的流行音乐。对于英国的许多人来说,欧洲电视网仍然是吉娜·G 1996 年参赛作品的同义词,“哦,啊…就一点点”,一大块严重老化的音乐奶酪,最好被丢弃在时间的迷雾中。
如何看待欧洲电视网在过去十年里已经“长大”的说法?乌克兰在 2016 年以一首关于约瑟夫·斯大林驱逐克里米亚鞑靼人的歌曲赢得了比赛,这表明自吉娜·g 时代以来,一些事情确实发生了变化。
贾马拉为乌克兰赢得 2016 年世界杯
然而,由于 Spotify 的一些非常聪明的数据科学工作,我们甚至可以超越歌曲的抒情主题,而是通过音频特征来分析歌曲。为此,我们可以将欧洲电视网过去十年的歌曲与其他曲目的对照组进行比较,看看这场比赛的负面内涵是否仍然值得(未来的博客也将使用这些“音频”数据来预测哪首歌会赢得 2020 年的比赛,这场比赛在新冠肺炎之后不可避免地被取消)。
“这就是你如何写一首歌”
Spotify 的公共 API 允许用户访问平台上任何歌曲的信息。这些范围从显而易见的(歌名、作曲家、发行日期等。)到更奇特的,包括由音轨音频文件的波形直接推断出来的指标。
注意——Spotify 的 API 可以通过使用“ Spotipy ”库用 Python 访问。观看 Ian Annase 的系列视频以获得对此的完整介绍,或者深入研究这个项目的 GitHub repo。
要获得这些信息,我们只需将惟一的 track ID 输入 API。正如人们所希望的那样,获取数百首歌曲的 id 是一项可以由 Spotipy 自动完成的任务——只需创建所需歌曲的播放列表,然后调用一个方法来获取这些播放列表的信息。这将返回简洁的 JSON 文件,其中包含每个播放列表轨道的基本数据,包括其唯一的 ID。
芒斯·塞默洛为瑞典赢得 2015 年世界杯
除了 2009 年以来的欧洲电视网歌曲库,本博客还分析了另外两个“控制”歌曲列表:
- “图表”: 382 首曲目摘自 Spotify 自 2015 年以来英国最热门歌曲的年度“热门曲目”播放列表(注意——非整数是因为删除了多年播放列表中出现的重复曲目)。这包括商业上超级成功的艺术家,如艾德·希兰、德雷克、贾斯汀比伯等。
- “Pitchfork”:400 首选自 Pitchfork 的 200 首最佳歌曲,以及十年来的 200 张最佳专辑。这个播放列表代表了广受好评的“高质量”音乐(在之前的博客中,我们发现 Pitchfork 通常可以很好地判断一张唱片的内在质量)。
“玩数字”
让我们依次看看不同的音频特征,看看欧洲电视网过去十年与这两个对照组相比如何。
节奏。简单来说,每首歌每分钟多少拍(BPM)?
我们注意到欧洲电视集团紧紧围绕 120–125 BPM 范围。这可能是因为欧洲电视网的歌曲不能超过三分钟(比赛的乐趣之一是,如果你不喜欢一首歌,你永远不必等待它结束)。
一首典型的歌曲每小节有四个节拍。两个 16 小节的韵文、三个 16 小节的合唱、一个中 8 小节和四个引子和结尾小节(现代音乐的主要结构,全部在内)总共有 360 个节拍,当以 120BPM 播放时,正好需要三分钟。
我们应该注意到,图表音乐也有大约 100 和 120BPM 的峰值。这可能是出于类似的考虑(期望大量广播播放的歌曲将致力于 3 到 3.5 分钟的持续时间)。广受好评的 Pitchfork 播放列表上的歌曲对时长的限制更少,因此没有那么紧密地捆绑在一起。
能量。这是 Spotify 第一个更主观的指标。根据 API 文件:
能量代表强度和活动的感知度量。通常,高能轨道感觉起来很快,很响,很嘈杂。例如,死亡金属具有高能量,而巴赫前奏曲在音阶上得分较低。
我们可以看到所有三个歌曲组都向右倾斜(根据 Spotify 的说法,与人口分布一致)。然而,欧洲电视网的轨道特别有活力。我们预料到了这一点——欧洲电视网的参赛作品必须在漫长的表演之夜与 20 多首其他歌曲争夺关注。低能量的歌曲迷失在混音中,除非有惊人的声音转折。
可跳舞性。根据 Spotify:
可跳舞性描述了基于音乐元素(包括速度、节奏稳定性、节拍强度和整体规律性)的组合,一首曲目适合跳舞的程度。
不出所料,高度流动的排行榜音乐似乎非常适合跳舞。正如我们所料,Pitchfork 播放列表的范围要广得多——舞蹈和好评没有明显的相关性。也许出乎意料的是,尽管欧洲电视网的音乐是所有三个组合中最有活力的,但平均来说却不太适合跳舞(事实上,分布相当正常)。
Spotify 没有给出任何关于“danceability”背后的精确计算的进一步细节,但我们可以在下图的右下方找到线索:
可跳舞性最低的歌曲(Japandroids 的《Younger Us》)恰好是所有被分析歌曲中能量第二高的。曲目节奏非常快,由摇滚吉他和鼓带动。这听起来很有活力。然而,这首歌中有一些地方明显有损于它的可跳舞性——乐器在大约 30 秒钟内被完全切断,歌曲最后几个和弦的演奏不合拍(如果你试图跟着它们跳舞,你会看起来非常奇怪)。
键。不用过多钻研音乐理论,歌曲的“调”决定了演奏时使用的音符。最常见的键族是“大调”和“小调”。一般来说,大调听起来是快乐的,小调听起来是悲伤的。这不是一个听众通常会注意的事情,尽管你会注意到一首熟悉的歌曲的音调是错误的——听村民用小调唱“基督教青年会”是一种真正痛苦的经历。
我们看到,欧洲电视网的小调音比例最高(49%)。同时,c 大调、C#大调和 D 大调是所有播放列表中特别常见的调。
价。这是 Spotify 得出的最有趣的指标之一:
描述音轨所传达的音乐积极性的量度。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。
我们看到排行榜音乐更倾向于正面。这并不奇怪——自从有史以来,排行榜音乐一直是快乐和乐观的。然而,我们看到欧洲电视网实际上是所有组中最负向倾斜的,这表明它有更高浓度的情绪负面歌曲。
小调歌曲的较高比例将对此有所贡献,尽管 Pitchfork 组有类似的配价分布(尽管有更多的大调歌曲),但这可能不是整个故事。
“告别昨天”
从音乐上来说,我们已经看到欧洲电视网的歌曲占据了现代流行音乐和更小众、广受好评的音乐之间的一个有趣的中间地带。它乐观而充满活力,但也更情绪化,更可能是小调。
萨尔瓦多·索布拉尔(Salvador Sobral)为葡萄牙赢得了 2017 年欧洲电视网(Eurovision)近十年来最没有活力的歌曲
事实上,如果我们以年为基础绘制欧洲电视网条目的分布(kde),我们可以看到明显的趋势——歌曲变得越来越没有活力,它们的效价(或音乐“快乐”)比过去低得多。
我们可以将这两个指标绘制在一起,并显示欧洲电视网的歌曲是如何从右上角的高能量、快乐(俗气)的角落向左下角的低能量、悲伤(不那么俗气)的角落移动的。
给定年份欧洲电视网歌曲的平均价和能量值
在 2014 年的比赛之后,参赛作品的音乐性质发生了特别明显的变化(不管是不是巧合,一首能量和效价评级特别低的歌曲赢得了比赛——尽管声乐表演非常出色)。
肯奇塔·沃斯特为澳大利亚赢得 2014 年世界杯
这一趋势看起来似乎将持续到 2020 年——在整个取消之前,博彩公司最看好的是保加利亚。维多利亚的歌曲“眼泪变得清醒”的效价评分为 0.26,能量评分仅为 0.18——在整个欧洲电视网数据集中排名第二低。
“哦,啊…就一点点”,不是的。
这是我的“ Music By Numbers ”专栏中的最新博客,它使用数据来讲述关于音乐的故事。在接下来的博客中,我们将看到如何在机器学习环境中使用上述音频特征。我也很乐意听到对以上分析的任何评论——欢迎在下面留言,或者通过 LinkedIn 联系我!
分析具有因果影响的时间序列干预:货币波动
我们如何解释时间序列中的干预?
免责声明:本文是在“原样”的基础上编写的,没有任何担保。它旨在提供数据科学概念的概述,不应被解释为投资建议或任何其他类型的专业建议。
当检查一个时间序列时,有一个干预在一个特定的点上影响该序列是很常见的。
这方面的一些例子可能是:
- 导致销售显著变化的广告活动
- 交通政策的积极变化降低了交通事故的死亡率
- 影响资产价格的经济政策变化
分析干预效果的问题是,如果没有干预,人们就无法检查该序列的趋势。
例如,假设一家公司实施了一项广告活动,目的是促进销售。虽然可以在干预后记录销售数据,但如果没有干预,很难说的销售额会是多少。
我们的例子
对于这个例子,让我们考虑一下利率变化对货币波动的影响。
当中央银行操纵利率时——这被假设为对一种货币有重大影响,因为它影响了该货币相对于市场上其他货币的感知价值。
然而,如果我们希望量化这种影响,该怎么办呢?让我们看看这是如何与因果影响包一起工作的。这个包最初是由 Google 为 R 开发的,但是在这个例子中我们将使用 Python 版本(pycasualimpact)。
让我们考虑 2017 年英镑/美元的波动。
2017 年 11 月,英国央行决定加息。
资料来源:tradingeconomics.com
我们将使用因果影响来尝试调查:
- 如果没有这种干预,英镑对美元的预测汇率会是多少
- 这种干预是否重要,是否影响了货币水平
为了确定这种干预是否对时间序列有显著影响,我们必须使用合适的协变量(X)。这个协变量不能受到干预的影响。
例如,我们可以看到,2017 年,欧洲央行维持利率不变(此后一直如此):
资料来源:tradingeconomics.com
考虑到这一点,欧元/美元将被用作本例的协变量。
X = eurusd
y = gbpusd
虽然假设货币会受到美元波动以及许多其他宏观经济条件的影响,但假设英格兰银行的干预不会影响欧元/美元。
分析
使用 Quandl 从 FRED 数据库下载相关的货币对:
>>> eurusd = quandl.get("FRED/DEXUSEU", start_date='2017-01-01', end_date='2018-01-01', api_key='enter_api_key')>>> gbpusd = quandl.get("FRED/DEXUSUK", start_date='2017-01-01', end_date='2018-01-01', api_key='enter_api_key')
gbpusd
这是两种货币对的图表:
英镑/美元
资料来源:美联储经济数据
欧元/美元
资料来源:美联储经济数据
随着英国央行在 2017 年 11 月 2 日做出利率决定, t = 0 至 229 被定义为前期(干预前),而 t = 230 至 248 被定义为后期(干预后)。
data = pd.DataFrame({'y': y, 'X': X}, columns=['y', 'X'])
pre_period = [0, 229]
post_period = [230, 248]
根据这个软件包的官方 GitHub,这个模型“使用经典的卡尔曼滤波方法来求解状态空间方程”。
后验推断可以如下产生:
>>> ci = CausalImpact(data, pre_period, post_period)
>>> print(ci.summary())
>>> print(ci.summary(output='report'))
>>> ci.plot()
下面是生成的输出:
Posterior Inference {Causal Impact}
Average Cumulative
Actual 1.34 25.46
Prediction (s.d.) 1.32 (0.0) 25.17 (0.08)
95% CI [1.32, 1.33] [25.01, 25.33]
Absolute effect (s.d.) 0.02 (0.0) 0.29 (0.08)
95% CI [0.01, 0.02] [0.13, 0.45]
Relative effect (s.d.) 1.15% (0.32%) 1.15% (0.32%)
95% CI [0.52%, 1.77%] [0.52%, 1.77%]
Posterior tail-area probability p: 0.0
Posterior prob. of a causal effect: 100.0%
根据上述发现,英镑/美元的实际汇率为 1.34 ,而在没有干预的情况下,该汇率将为 1.32 。
此外,该模型表明,有一个 100%的因果关系的后验概率。
在分析更详细的报告时,输出还指出:
偶然获得这个效果的概率很小
(贝叶斯单侧尾区概率 p = 0.0)。
这意味着因果关系可以被认为是统计上
显著的。
从这个角度来看,有证据表明英镑/美元的走势比没有加息的情况下更高。以下是实际比率与预测比率的概述:
来源:Jupyter 笔记本输出
如前所述,Python 使用了一种不同于 R 的方法来生成预测,无需干预——后者更依赖于强调用户先验知识的贝叶斯方法。事实上,人们可以尝试这两种方法来验证生成的预测是否一致。
关于对数变换的一个注记
在处理资产价格数据时,通常的做法是将数据转换成对数格式。
这样做有两个原因:
- 能够比较不同价格范围的资产,例如,比较 200 美元股票和 2000 美元股票的变动
- 考虑百分比方面的波动
在上面的例子中,两种货币具有相似的标度,因为它们都以美元为基准。在这方面,没有使用对数变换。
此外,在我们试图分析的干预背景下,货币价格比股票价格相距更近的事实将使价格变化难以察觉。
但是,如果将这种转换应用到数据上会怎么样呢?是否仍然观察到统计上显著的因果影响?
以下是以对数形式表示的两个时间序列:
欧元/美元
来源:Jupyter 笔记本输出
英镑/美元
来源:Jupyter 笔记本输出
对经过对数转换的数据运行时,输出结果如下:
Posterior Inference {Causal Impact}
Average Cumulative
Actual 0.29 5.56
Prediction (s.d.) 0.28 (0.0) 5.34 (0.07)
95% CI [0.27, 0.29] [5.21, 5.47]
Absolute effect (s.d.) 0.01 (0.0) 0.22 (0.07)
95% CI [0.0, 0.02] [0.09, 0.35]
Relative effect (s.d.) 4.1% (1.22%) 4.1% (1.22%)
95% CI [1.68%, 6.47%] [1.68%, 6.47%]
Posterior tail-area probability p: 0.0
Posterior prob. of a causal effect: 100.0%
用对数表示,如果没有干预,英镑/美元的自然对数应该是 0.28。然而,实际结果是 0.29。
来源:Jupyter 笔记本输出
因此,即使进行了对数变换,干预仍会显示为改变了时间序列的轨迹。这两种货币的比例仍然有很大的不同,在这种情况下是否需要对数变换仍有争议(这种变换通常对比例偏差较大的大值最有效)。
然而,证据表明,干预导致了有关时间序列的变化。
结论
这是对因果影响库的一个介绍性示例,以及如何在一个时间序列中检查干预的效果。
非常感谢您的时间,任何问题或反馈都非常欢迎。
参考
使用 Python 分析 WhatsApp 群组消息
谁发的信息最多?最常用的词是什么?最常用的表情符号有哪些?人们什么时候最常发信息?如果你曾经想知道你和你的朋友们在 WhatsApp 上的这些事情,那么这篇文章就是给你的。用一些(相对)简单的 Python 来了解一下吧!
我相对来说是 Python 的新手,但是这个项目给了我一个很好的 Python 数据争论入门,因为我必须在这里使用许多不同的技术,并试图探索最好的一种。
卡斯帕·卡米尔·鲁宾在 Unsplash 上的照片
获取数据
比我想象的更简单,我从来没有意识到你可以在 WhatsApp 上得到这个。在你的手机上,进入 WhatsApp 群组,点击右上角的点点点。然后进入“更多”和“导出聊天”。然后,您可以选择保存该文件的位置。我选择了 Google Drive,并把它放在我将要创建 Jupyter 笔记本的地方。
设置
只是对我的设置做一点小小的评论。我用了一个 Jupyter 笔记本来进行这种分析,这种分析是在小部件中完成的,我认为它可以很好地执行每个单元。这里有几个技巧和一些在 Jupyter 中有用的特殊函数。
我已经在评论中解释了它们的作用,但是为了解释为什么:Jupyter 限制了每个单元格显示的输出数量。因此,如果您想在一个单元格中输出一些数据的图形以及一个支持表,那么您需要运行第一个命令。后两个我用来控制输出多少。我不喜欢它默认如此少的行数/列数,尤其是当您可以使用像。head()取而代之,所以我没有限制。但是在查看数据的时候一定要小心,当你需要的时候你会限制它。
争论数据
我在这里做了一些笔记。我喜欢有两组数据,留下一组作为原始数据,可以与争论的数据集进行比较,因此有了 raw_data_csv 和 data 。
不幸的是,WhatsApp 的这种数据导出并不完美,当一条消息包含多行/换行符时,很难将其归因于正确的消息细节。我尝试了一些方法,但是找不到任何简单的方法。为了这个分析的目的,我已经把它们去掉了,因为没有它们我们仍然可以得到足够好的洞察力。这就是日期时间列上的 dropna 正在做的事情。
text_message 的第二个缺点是去掉了一些系统消息,比如当人们被添加到组中时。
实际上,我在 Jupyter 的不同单元格中运行了这些部分,并在每个点运行 head、tail 和 info,以了解每个点的数据情况。
分析数据
一些 WhatsApp 群上下文
所以接下来的几个部分的一些背景,我用的 WhatsApp 群是我的(场)曲棍球队,所以主要谈论训练,比赛和我们度过的夜晚。但是你很快就会看到这个!
最受欢迎的消息时间
我认为热图可以最好地显示一天中的小时和一周中的天。这是我最感兴趣的,因为其他事情是显而易见的,比如曲棍球赛季开始的月份。因此,我的构建方法是为这两个数据点创建新列,然后用这些维度的分组计数创建一个新的数据框。
作者图片
你能猜出我们在哪个晚上训练吗?周一和周三晚上,是的。这将是消息说,人们是在,外出,或迟到的会议。我们的比赛显然是在周六,这是我们大部分信息的来源,将主要谈论前往比赛,然后是赛后的滑稽动作。
按发件人排列的邮件
接下来是发件人邮件数,我选择用条形图显示,如下所示:
作者图片
显示为条形图可以让您直观地看到数字的差异,而不仅仅是一个数字表。亚历克斯是队长,所以他会发送很多管理信息,而我是社交安全专员,当他们显然不想出去的时候,我会试图组织一群人出去做些有趣的事情。甚至我也很惊讶亚历克斯和我比其他人多发了多少信息,但我们经常得不到任何回应,所以这很有意义。
最流行的词
现在谈谈流行词,这确实需要相当多的操作和运行时间。希望这些评论能解释大部分正在发生的事情。
最难的部分,也可能是最大的警告是如何定义非 _ 词,最终我只是使用了那些我在分析中根本不关心的词,但我可能在这里可以走得更远,因此我们作为一个整体有一些非常无趣的顶级词:
作者图片
所以我想可能更有趣的是挑选单词,看看它们的排名有多高,就像这样:
健身搭售啤酒是一个有趣的“巧合”…作者图片
我认为另一件有趣的事情是发件人的字数统计。不幸的是,我们没有大量的信息/文字,所以除了 Alex S 和我之外,对任何人进行细分实际上只能提供很少的数据,但不管怎样,我们还是要这样做:
作者图片
最流行的表情符号
我想补充的最后一点是表情符号的使用。现在我们并不是表情符号用户中最疯狂的,所以也没有太多的数据,也很难定义/细分表情符号到底是什么,所以这里有一些奇怪的表情符号,我认为它们对应着与表情符号相关的性别和肤色,但我们开始了:
作者图片
好吧,那就结束了。对于这个数据集,我想不出更多可以分析的东西,但我很想听到一些建议。此外,如果任何人对代码有任何建议,请告诉我,因为我对 Python 还很陌生,所以我觉得肯定有更好的方法来完成某些部分。
享受吧。
多尺度 CNN 特征图的分析与应用
摘要
在这篇博文中,我们提出了卷积层感受域的正式处理方法,并使用一个衍生的数学框架描述了多尺度卷积特征图的特征。使用开发的数学框架,我们计算了不同卷积和汇集操作下的特征图的感受野和空间尺度。我们展示了汇集操作的重要性,以确保要素地图的空间比例作为图层深度的函数呈指数增长。此外,我们观察到,如果没有嵌入到 CNN 中的池化操作,要素地图空间比例只会随着图层深度的增加而线性增长。我们引入空间尺度轮廓作为 CNN 的分层空间尺度表征,其可用于评估特征图与训练数据集中对象维度直方图的兼容性。通过计算 ResNet-50 的空间比例剖面图来说明这一使用案例。此外,我们解释了特征金字塔模块如何生成多尺度特征地图丰富了增强语义表示。最后,与常规卷积滤波器相比,虽然扩展卷积滤波器保留了特征图的空间维度,但它们保持了更大的空间尺度指数增长率。
阅读这篇博文,你会更深入地了解最近提出的用于各种视觉任务的 CNN 架构中多尺度卷积特征图用例背后的直觉。因此,这篇博客帖子可以被视为一个教程,以了解不同类型的图层如何影响要素地图的空间比例和感受域。此外,这篇博客文章面向那些参与设计 CNN 架构的工程师和研究人员,他们厌倦了从 CNN 主干中选择哪些特征图来提高其模型的性能的盲目试验和错误,相反,他们更喜欢在设计过程的早期阶段将特征图的空间比例轮廓与训练数据集中的对象维度进行匹配。为了方便这样的用例,我们在 https://github.com/rezasanatkar/cnn_spatial_scale公开了我们的代码库。
介绍
一般的假设和理解是,由 CNN 的早期卷积层生成的特征图编码基本的语义表示,例如边和角,而更深的卷积层在其输出特征图中编码更复杂的语义表示,例如复杂的几何形状。细胞神经网络生成多语义层特征图的这一特性是其基于多层深层结构的分层表征学习能力的结果。具有不同语义级别的特征图对于 CNN 是至关重要的,因为以下两个原因:(1)复杂语义特征图建立在基本语义特征图之上,作为它们的构建块(2)许多视觉任务如实例和语义分割受益于基本和复杂语义特征图。基于视觉 CNN 的架构将图像作为输入,并将其通过几个卷积层,目的是生成对应于输入图像的语义表示。具体而言,每个卷积层输出一个特征图,其中该特征图中编码语义的程度取决于该卷积层及其先前卷积层的代表性学习能力。
CNN 特征图是空间方差
CNN 特征图的一个重要特征是它们是空间方差的,这意味着 CNN 特征图具有空间维度,并且由给定特征图编码的特征可能仅对特征图的空间区域的子集变得活跃。 为了更好的理解 CNN 特征图的空间方差性质,首先我们需要理解为什么全连通图层生成的特征图不是空间方差。由于全连接层的每个神经元都连接到全连接层的所有输入单元,因此由全连接层生成的特征图(可以将给定全连接层的神经元的激活视为其输出特征图)不具有空间维度。因此,不可能定义和考虑神经元激活输出的空间方面。
另一方面,CNN 特征图的每次激活仅连接到几个输入单元,这些输入单元在彼此的空间邻域中。CNN 特征图的这一特性导致了其空间方差特性,这是卷积滤波器的空间局部结构及其空间受限感受野的结果。下图显示了全连接图层和卷积图层之间的差异,这种差异会导致一个图层的空间不变性和另一个图层的空间变化,其中输入图像由绿色矩形表示,棕色矩形表示卷积要素地图。此外,具有两个输出神经元的全连接层由两个蓝色和灰色圆圈表示。如你所见,全连接层的每个神经元受到所有图像像素的影响,而特征图的每个条目只受到输入像素的局部邻域的影响。
此图说明了为什么全连接图层生成的要素不是空间差异,而卷积图层生成的是空间差异要素地图。绿色矩形表示输入图像,棕色矩形表示由 CNN 的卷积层生成的尺寸为 5×7×1 的特征图。另一方面,两个蓝色和灰色圆圈表示具有两个输出神经元的全连接层的激活输出。假设如果输入图像中有自行车,则全连接层的蓝色神经元(特征)将变为活动的,而如果输入图像中有汽车,则灰色神经元(特征)将变为活动的。换句话说,蓝色神经元是自行车特征,而灰色神经元是汽车特征。由于全连接层的性质,即每个神经元的输出受所有输入图像像素的影响,全连接层生成的特征不能编码任何现成的定位信息,以便告诉我们如果输入图像中有自行车,则自行车在输入图像中的位置。另一方面,由卷积层生成的特征图是空间变化的,因此,除了对象的存在信息之外,它们还编码了定位信息。特别地,由卷积层生成的 which 维的特征图包含 C 个不同特征的存在信息(每个通道,特征图的第三维,编码唯一特征的存在信息),其中特征的空间维度 W×H 告诉我们对于输入图像的哪个位置,该特征被激活。在这个例子中,布朗卷积特征映射只编码一个特征,因为它只有一个通道(它的第三维等于 1)。假设这个棕色特征图是自行车特征图,那么只有在输入图像中的该条目的感受域中有自行车时,该特征图的条目才变为活动的。换句话说,如果在输入图像中有一辆自行车,但在其特定的感受域中没有,则该条目不会被激活。卷积特征图的这种特性使得它们不仅能够编码关于输入图像中物体存在的信息,而且能够编码物体的定位信息。
CNN 特征图的空间比例和空间重叠
在本节中,我们正式定义了 CNN 特征地图的空间比例。CNN 特征图具有空间维度,它们的空间比例用于计算它们的条目和输入图像区域之间的空间映射。 特别地,给定 CNN 特征图的条目的空间尺度被定义为影响该特征图条目的值的输入图像的矩形子区域的像素大小 。最简单的情况是计算第一层的空间尺度。例如,如果 CNN 的第一层是 3×3 卷积层,那么第一层特征地图的条目的空间尺度是输入图像的 3×3 像素子区域。计算较深 CNN 图层的输出要素地图的空间比例需要知道其输入要素地图的空间比例和空间重叠。在后面的章节中,我们将根据输入要素地图的空间比例和空间重叠,推导出不同卷积和汇集图层的输出要素地图的空间比例和重叠公式。
这里,空间重叠被定义为两个相邻特征地图条目的空间尺度之间的重叠百分比。在下图中,我们绘制了两个相邻特征地图条目的空间比例和重叠,其中绿色矩形表示输入图像,棕色矩形表示由 CNN 的一个卷积层生成的特征地图。橙色要素地图条目的空间比例是输入图像上的橙色阴影区域,蓝色要素地图条目的空间比例是输入图像上的蓝色阴影区域。相邻蓝色和橙色条目之间的空间重叠是输入图像上两个空间尺度区域之间的重叠区域。
绿色矩形表示输入图像,而棕色矩形表示由 CNN 网络的一个卷积层生成的尺寸为 5×7×1 的 CNN 特征图。在该图中,该特征图的两个相邻条目用橙色和蓝色标记。橙色要素地图条目的空间比例在输入图像上绘制为橙色阴影区域,而蓝色要素地图的空间比例在输入图像上绘制为蓝色阴影区域。如您所见,蓝色和橙色的空间比例矩形大小相同,并且相互重叠。这两个相邻空间尺度矩形之间的重叠区域的大小与空间尺度区域的大小的比率被定义为空间重叠。
作为计算空间重叠的例子,假设 CNN 的第一层是跨度为 1 的 3×3 卷积层。然后,第一层生成的特征地图将具有 3×3 的空间比例和 9 个像素中的 6 个像素的空间重叠,这是大约 67%的空间重叠。这个重叠百分比是因为选择步幅等于 1。如果步幅选择为 2,则空间重叠将等于 33%,而步幅 3 导致 0%的空间重叠。 一般来说,我们应该避免非常高的空间重叠百分比,因为特征映射条目最终会以计算和存储资源的代价对冗余信息进行编码。另一方面,非常低的空间重叠百分比会导致生成的特征地图条目中的混叠效应。
汇集操作确保要素地图的空间比例呈指数级增长
在本节中,我们将讨论 CNN 如何依靠池化操作来确保要素地图空间比例的指数增长率作为图层深度的函数。首先,我们证明了在 CNN 中不嵌入池操作并且仅依赖于步长为 1 的卷积层导致了特征地图的空间尺度的线性增长率。然后,显示合并图层以实现要素地图空间比例的指数级增长。最后,给出了有和没有汇集操作的两种细胞神经网络变体的案例研究,以说明使用汇集操作对特征地图的空间尺度增长率的影响。
在这里,我们表明,仅由 3×3 卷积层组成的步幅为 1 的 CNN 只能显示特征地图空间比例的线性增长率。仅仅由于输入图像上的 3×3 感受野,第一层特征图的空间比例将是 3×3。步长为 1 的第二层 3×3 卷积的特征映射输出的空间比例将等于 5×5。这是因为第二层特征图的感受野相对于第一层特征图是 3×3,而第一层特征图的感受野也是 3×3,但是相对于输入图像。因此,如果您顺序组合这两个 3×3 感受野,并考虑第一层特征图的相邻条目的感受野的空间重叠,您可以计算出第二层特征图相对于输入图像的空间比例是 5×5。下图显示了这一点,为简化起见,假设输入图像是一维的,卷积层假设为 1 x 3,步长为 1。可以观察到,第二层特征地图的蓝色条目相对于输入图像的空间比例是 1×5。
在该图中,我们展示了 1 x 3 卷积层生成的特征图的空间比例,在 1 维输入图像上应用了步长 1。绿色矩形表示一维输入图像,其中棕色矩形示出了第一卷积层输出的三个相邻特征映射条目,蓝色矩形示出了第二卷积层生成的单个特征映射条目。如您所见,第一层要素地图条目的空间比例为 1 x 3,而第二层要素地图条目的空间比例为 1 x 5。
基于上述示例和归纳,可以表明,以步长 1 添加每个 3×3 卷积层,将沿着每个维度将特征地图的空间比例增加 2 个像素。让 S(n)表示第 n 层要素地图的空间比例。然后,我们可以写出 S(n) = (3 + 2 * (n-1)) x (3 + 2 * (n-1)),这表明空间尺度增长率相对于层深度是线性的。空间比例的这种线性增长率主要是因为相邻要素地图条目的显著空间重叠。如果使用该网络的视觉任务需要相对较大的空间比例特征地图,则空间比例的线性增长率将是一个问题。例如,为了将最终特征图(由网络的最后一个 CNN 层生成的特征图)的空间比例增加到输入图像的 40×40 像素,那么 CNN 网络需要大约 20 个 3×3 的 CNN 层。由于在训练和推断期间卷积层的计算成本,在大多数情况下,我们宁愿避免仅仅为了满足特征地图的空间比例要求而增加越来越多的卷积层。
联营业务
在大多数 CNN 架构中,卷积层与池操作交错,以通过减少特征地图条目之间的空间重叠来增加特征地图的空间尺度的增长率。将空间尺度的增长率提高到超过线性增长率,使我们能够节省仅仅为了更大的空间尺度而增加更多的卷积层。我们可以通过显式池层或选择大于 1 的卷积滤波器步长来实现池操作。最常见的池层是跨度为 2 的 2 x 2 最大池层。该池图层将要素地图的空间维度减半,这意味着它将大小为 W x H x C (W x H 表示要素地图的空间维度,C 表示要素地图的通道数)的输入要素地图转换为大小为 W/2 x H/2 x C 的输出要素地图。将要素地图的空间维度减半的主要动机是减少相邻要素地图条目之间的空间重叠。
跨度为 2 的 2 x 2 池图层的空间比例和重叠
在本节中,我们将根据输入要素地图的空间比例和重叠程度,推导出跨距为 2 的 2 x 2 池图层的输出要素地图的空间比例和重叠公式。让 S 和 P 分别表示输入特征地图的空间比例和空间重叠。此外,s '和 p '表示最大池图层的输出要素地图的空间比例和空间重叠。我们可以计算 S(S,P)= S+2(1-P)S+(1-P)S =(2-P)S。S
等式是基于以下事实得出的:由最大池化图层生成的要素地图条目的空间比例将等于其 4 个相应输入相邻要素地图条目的空间比例的总和,其中(1-P)和(1-P)因子确保 4 个输入条目的联合空间比例的每个子区域仅计数一次。
为了进一步阐明 2 x 2 池化图层的空间比例公式的推导过程,我们在下图中演示了其背后的推理过程。绿色矩形表示输入影像,而棕色矩形表示池图层的输入要素地图(尺寸为 5 x 7 x 1),蓝色矩形表示池图层的输出要素地图(尺寸为 3 x 4 x 1)。为了说明 s’的推导,我们考虑输出特征图的单个条目(用灰色标记)。灰色条目的空间比例取决于其 4 个相应输入要素地图条目的空间比例和重叠,如下图所示。不失一般性,我们可以假设 S` = S + 2(1-P)S + (1-P) S 中的第一项 S 对应于输入要素的橙色条目的空间比例。此外,第二项 2(1-P)考虑了输入要素地图的蓝色和紫色条目的空间比例,其中因子(1-P)用于确保它们不会与橙色条目的空间比例重叠。最后,项(1-P) S 对应于输入要素地图的黑色条目,其中因子(1-P)用于确保黑色条目的有效空间比例不会与橙色、蓝色和紫色条目的已计数空间比例重叠。
2 x 2 汇集图层空间比例公式推导演示。绿色矩形表示输入图像;棕色矩形表示稍后池化的输入要素地图,蓝色矩形表示池化图层的输出要素地图。橙色输出条目的空间比例是输入影像上标记的 4 个区域的联合,这 4 个区域对应于 4 个相邻输入要素地图条目的空间比例。
另一方面,在应用 2×2 最大汇集之后,每两个相邻条目之间的空间重叠的绝对值将等于 2PS-P S=P(2-P)S,其中 2PS 来自于两个相邻输出条目的 2×2 感受域通过两对输入条目相邻的事实。最后,我们需要减去 P S 以避免重复计算重叠的子区域。
下图说明了计算跨度为 2 的 2 x 2 最大合并图层的绝对空间重叠的上述推理,其中绿色矩形表示输入影像,棕色矩形表示合并图层的输入要素地图,蓝色矩形表示合并图层的输出要素地图。在此图中,不失一般性,我们关注用灰色和橙色标记的两个输出相邻条目的空间重叠。注意,由于步幅 2,这两个条目的感受野没有明显的重叠。但是,基于它们的输入相邻对,它们在空间尺度上具有有效的重叠。特别地,灰色输出条目的蓝色输入条目与橙色输出条目的绿色输入条目相邻,而灰色输出条目的黑色输入条目与橙色输出条目的红色输入条目相邻。2PS-P S 的绝对重叠被标记为输入图像上的紫色虚线区域。每个相邻对(蓝、绿)和(黑、红)在绝对空间尺度的最终值中贡献一个 P S 项,而减去 PS 是为了确保我们不会对重叠的空间尺度计数两次。
演示步幅为 2 的 2 x 2 池层的空间重叠推导。绿色矩形表示输入图像,而棕色矩形表示输入特征图,蓝色矩形表示输出特征图。相邻灰色和橙色输出条目之间的绝对空间重叠在输入图像上显示为紫色虚线区域。
空间重叠 P′等于绝对空间重叠 P(2-P)S 除以 S′。所以我们有 P`(S,P) = P(2-P)S/((2-P) S)=P/(2-P)。这个结果是有意义的,因为它表明 P’总是小于 P,这表明跨距为 2 的 2×2 汇集层将总是减少相邻特征地图条目之间的空间重叠。例如,如果在应用合并操作之前,空间重叠为 2/3,那么在应用合并操作之后,空间重叠将减少到 2/4。
跨度为 1 的 3×3 卷积层的空间比例和重叠
这里,我们依靠与上一节中讨论的相同的推理路线,来推导步长为 1 的 3×3 卷积层的空间比例和重叠公式。让 S 和 P 表示输入要素地图条目的空间比例和重叠。此外,让 s′和 p′表示在步长为 1 的 3×3 卷积滤波器输出端的特征映射入口的空间比例和空间重叠。然后,我们可以将 3 x 3 卷积层的空间比例计算为 S`(S,P) = S + 4(1-P)S + 4(1-P) S。接下来,我们重点计算空间重叠。特别是,计算步长为 1 的 3 x 3 卷积滤波器的输出要素地图的绝对空间重叠比计算步长为 2 的 2 x 2 合并图层的空间重叠更简单,如下图所示。
在下图中,绿色矩形表示输入图像,而棕色和蓝色矩形表示步长为 1 的 3 x 3 卷积层的输入和输出特征图。注意,步长 1 导致特征图的空间维度不变,因此输入和输出特征图的空间维度都是 4 x 6 x 1。在此,不失一般性,我们着重于计算相邻灰色和橙色输出要素地图条目之间的空间重叠。由于步幅 1,这两个输出条目在输入特征图上的重叠感受野是 3×2,并由棕色输入特征图上的紫色阴影区域表示。
这个 3×2 的显式重叠区域简化了计算灰色和橙色输出条目之间的空间重叠的绝对值。特别是,它们的绝对空间重叠等于属于 3 x 2 紫色重叠区域的输入要素地图条目的聚合空间比例。可以看出,绝对空间重叠等于 S + 3(1-P)S + 2(1-P) S。在该示例中,在输入图像上被标记为蓝色阴影区域的项 S 对应于紫色阴影区域的第二行第一列上的条目。此外,3 个术语(1-P)在输入图像上用黑色、红色和绿色区域标记,并且相对于第二行和第一列上的条目对应于顶部、右侧和底部条目。最后,2 个术语(1-P)在输入图像上被标记为棕色区域,并且对应于紫色重叠区域的右上和右下条目。因此,空间重叠 P(S,P)=(S+3(1-P)S+2(1-P)S)/S
=(1+(1-P)(5–2P))/(1+4(1-P)(2-P))。
演示步长为 1 的 3 x 3 卷积层输出特征图的空间重叠计算。绿色矩形表示输入图像,而棕色矩形表示到 3×3 卷积层的输入特征映射,蓝色矩形表示 3×3 卷积层的输出特征映射。输入棕色特征图上方的紫色阴影区域表示两个相邻输出特征图条目灰色和橙色的感受野的 3×2 重叠区域。这两个相邻输出条目之间的绝对空间重叠被标记为输入图像上 6 个区域(蓝色、黑色、红色、绿色、棕色和棕色)的并集。
案例研究-具有 20 个 3 x 3 卷积层的 CNN
通过使用步长为 1 的 3 x 3 卷积图层和步长为 2 的 2 x 2 最大合并的派生空间比例和重叠公式,我们展示了应用合并图层以增加要素地图条目的有效空间比例的重要性。对于我们的示例,我们考虑 20 层 CNN 的以下两种变化:(1)20 层 CNN,具有 20 个 3×3 CNN 层,跨度为 1,没有池层,下图中的蓝色曲线(2)20 层 CNN,具有 20 个 3×3 CNN 层,跨度为 1,与 2×2 最大池层交错,跨度为 2,每 4 个 CNN 层,下图中的红色曲线。
在下面绘制的曲线中,x 轴是图层深度,y 轴是由 CNN 图层在 x 轴指定的深度生成的要素地图条目的空间比例宽度(空间比例的宽度等于空间比例的平方根)。如您所见,在这两种情况下,要素地图条目的空间比例都会随着图层深度的增加而增加。然而,具有汇集层的 CNN(红色曲线)的空间比例增长率是指数的,而没有汇集层的 CNN(蓝色曲线)的空间比例增长率是线性的。具有合并图层的 CNN 的空间比例的指数增长率导致其最终要素地图条目具有 243 x 243 的空间比例,而没有合并图层的 CNN 的最终要素地图条目的空间比例仅增长到 50 x 50。这意味着由具有汇集层的 CNN 生成的特征地图可以编码在输入图像中捕获的大到 243 x 243 像素的对象,而没有汇集层的 CNN 只能编码大到 50 x 50 像素的对象。
两个都具有 20 个 3x3 CNN 层的 CNN 的空间尺度的比较;红色曲线:每 4 个 3x3 CN 层 2x2 最大池化;蓝色曲线:只有 3x3 CNN 层,没有池。x 轴:层深;y 轴:特定于图层的空间比例宽度。具有汇集的 CNN 的空间尺度增长率是指数的,而没有汇集的 CNN 的空间尺度增长率是线性的。
空间比例剖面
在设计 CNN 架构时,有必要聚集训练数据集中的对象维度的统计,并检查所设计的 CNN 架构的特征图是否提供了跨越对象维度直方图的所有主要模式的空间尺度。 我们称 CNN 的逐层空间尺度,为其空间尺度轮廓。作为最佳实践,有必要首先基于训练数据集的对象维度直方图来设计空间尺度轮廓,然后根据空间尺度轮廓要求来设计 CNN 架构。
例如,在这里,我们计算 ResNet-50 (50 层)的空间比例剖面。如前所述,CNN 架构中的池化操作可以通过使用显式池化层或选择大于 1 的卷积滤波器步长来实现。对于 resnet(用于图像识别的深度残差学习),跨距大于 1 的 CNN 卷积滤波器和显式池层都用于减少相邻特征地图整体之间的空间重叠。在用于图像识别的深度残差学习中给出的 5 种 ResNet 架构(下表所示的 18 层、34 层、50 层、101 层和 152 层)中,我们导出了 ResNet-50 的空间尺度轮廓。然而,给出的结果可以很容易地扩展到其他 4 个配置。在 ResNet50 中,使用了三种类型的池操作:(1)步长为 2 的 7×7 卷积滤波器(2)步长为 2 的 3×3 最大池层(3)步长为 2 的 1×1 卷积滤波器。
ResNet-18、ResNet-34、ResNet-50、ResNet-101 和 ResNet-152 配置。对于 ResNet-50,下采样按以下顺序执行:第一层(跨度为 2 的 7x7 卷积层)、第二层(跨度为 2 的 3x3 最大池层)和跨度为 2 的 1x1 卷积层,作为 conv3_1、conv4_1 和 conv5_1 块的第一层。
跨距为 2 的 7×7 卷积层仅被用作 ResNet-50 的第一层。因此,可以简化其输出空间比例和重叠计算。特别地,7×7 卷积滤波器的每个特征映射入口输出的空间尺度是 7×7,因为它们直接应用于输入图像。此外,相邻要素地图条目之间的绝对空间重叠等于 7 x 5。因此,其相应的空间重叠将等于(7×5)/(7×7)= 5/7。
跨距为 2 的 3 x 3 最大池层仅用作 ResNet-50 的第二层。让 S 和 P 分别表示输入特征地图条目的空间比例和重叠,S’和 P’表示输出特征地图条目的空间比例和空间重叠。3 x 3 汇集图层的空间比例等于 3 x 3 卷积图层的空间比例。因此,我们得到 S(S,P) = S + 4(1-P)S + 4(1-P) S。另一方面,我们需要使用我们已经针对其他图层讨论过的相同技术,推导出跨度为 2 的 3 x 3 池图层的空间重叠。我们可以将空间重叠计算为:P
(S,P) = (1+ 2(1-P)) / (1+4(1-P)(2-P))。
在 ResNet-50 的不同深度使用了跨度为 2 的 1 x 1 卷积层作为主要汇集操作,以减少相邻要素地图条目之间的空间重叠,并确保要素地图条目的空间比例呈指数增长。接收域为 1×1 的 1×1 卷积滤波器在应用于特征地图时不会改变特征地图条目的空间比例。但是,跨距为 2 时,它们会修改要素地图条目的空间重叠。设 P 和 P’分别表示应用步长为 2 的 1×1 卷积层之前和之后的特征映射条目的空间重叠。然后,我们可以计算 P`(S,P) = 2 max(P - 0.5,0)。这意味着,如果输入特征映射表项的空间重叠小于 0.5,则输出特征映射表项的空间重叠将为零,因为 1×1 卷积滤波器的感受域仅为 1×1,并且步长 2 确保它们相邻的输出表项没有重叠的感受域。因此,为了具有非零的空间重叠,必须从网络的前几层进行。
下图绘制了 ResNet-50 的空间比例剖面图,其中 x 轴横跨 ResNet-50 的各层,y 轴表示 ResNet-50 各层的空间比例宽度(空间比例宽度等于空间比例的平方根)。可以看出,ResNet-50 中使用的汇集操作导致 ResNet-50 的空间规模以指数速度增长,这是层深度的函数。特别地,由 ResNet-50 生成的最终特征图具有 483×483 像素的空间比例,这意味着其特征图条目对嵌入在输入图像中的大至 483×483 像素的对象的表示进行编码。此外,我们观察到 ResNet-50 的空间尺度是分段常数,这是由主要在 ResNet-50 中使用的步长为 1 的 1×1 卷积层引起的,以对特征图进行通道维度缩减。
ResNet-50 的空间比例剖面图,其中 x 轴横跨 ResNet-50 的各层,y 轴表示 ResNet-50 各层的空间比例。ResNet-50 的空间尺度剖面显示,作为层深的函数,逐层空间尺度呈指数增长。
多比例特征地图
在本节中,我们将讨论为什么针对不同视觉任务的大多数 CNN 架构依赖多尺度特征图来提高其检测、分类和回归性能。答案相当简单明了。在自然图像中捕获的对象以各种像素维度来表现它们自己。例如,如果一辆汽车距离摄像机 5 米远,那么与它距离摄像机 50 米远的情况相比,它在图像中显得更大。因此,对于这个示例,我们需要两个具有不同空间比例的特征地图,其中一个适用于汽车距离摄像机 5 米的情况,另一个适用于汽车距离摄像机 50 米的情况。注意,即使具有较大空间比例的特征地图(当它离摄像机 5 米远时匹配汽车图像)也能够封装当它离摄像机 50 米远时的汽车图像,但是它不能为 50 米远的汽车提供准确的表示,因为它在图像汽车周围的空间比例不够紧密,并且包含来自场景中其他物体的大量信息泄漏。
在具有不同像素维度的图像中出现的对象的问题被称为图像的,并且连同遮挡和相机视点变化一起,使基于视觉的检测系统变得复杂。设计用于解决图像比例模糊的最著名的非基于 ML 的方法是比例不变特征变换 (SIFT)。可以说,SIFT 一直是深度学习多尺度特征地图图像编码器的主要灵感。SIFT 依靠图像金字塔(将输入图像调整到不同的比例,并在处理输入图像的每个比例版本后聚合检测到的关键点)和具有不同σ的高斯平滑滤波器来检测不同比例的斑点,作为输入图像的关键点。当自然图像中存在尺度模糊时,检测具有不同尺度的斑点使得 SIFT 生成可靠的图像编码。
由对应于输入图像的给定 CNN 生成的语义表示是由 CNN 的每个卷积层生成的所有特征图的联合,而不仅仅是最终特征图。依靠几幅特征图提供不同空间尺度的网络。
用于目标检测模型的多尺度特征图
可以肯定地说,在基于 CNN 的视觉模型领域,多尺度特征图的优势最初表现在 2d 对象检测模型上。特别是 SSD:单次多盒探测器依靠 VGG-16 作为骨干网络(特征生成器),通过 6 个不同空间尺度的特征图对输入图像进行编码。特征图的不同空间尺度允许 SSD 检测嵌入在输入图像中的具有不同像素维度的对象。
再如,用于目标检测的特征金字塔网络 (FPN)使用 ResNet-50 和 ResNet-101 作为主干网络来生成多尺度特征地图。在 ResNet-50 的情况下,选择 conv2_3(第 11 层)、conv3_4(第 23 层)、conv4_6(第 41 层)和 conv5_3(第 50 层)的特征地图输出,以提供不同空间比例的特征地图。使用我们在上一节中介绍的 ResNet-50 的空间比例配置文件,我们可以将 conv2_3、conv3_4、conv4_6 和 conv5_3 的输出要素地图的空间比例分别计算为 35 x 35、99 x 99、291 x 291 和 483 x 483。因此,所选择的特征图可以表示输入图像中出现的不同大小的对象。
然而,FPN 的主要贡献是利用深层特征图中编码的语义信息,增强了浅层特征图的语义表示能力。 浅层生成的特征图的主要弱点是语义不如深层生成的特征图丰富。是因为输入图像的语义编码到特征图的过程是一个层次化的过程,意味着基本语义出现在早期的层特征图中,而更复杂的语义出现在更深层的特征图中。
为了更好地理解为什么这将是对象检测模型的一个问题,考虑以下以 ResNet-50 作为主干网络的例子。假设一辆汽车距离摄像机 50 米,它是通过一个 35×35 像素的方框在输入图像中捕获的,因此由 conv2_3(第 11 层)生成的特征图是对其进行编码的最佳候选。此外,假设第二辆汽车距离摄像机 5 米远,并且其在输入图像中的对应框具有 480×480 像素的尺寸,因此 conv5_4(第 50 层)最适合对其进行编码。有理由假设这两辆车具有相似的语义复杂度,与它们在输入图像中的大小无关。但是,我们知道 ResNet-50 的第 11 层在语义上不如 ResNet-50 的第 50 层丰富。
FPN 使用自上而下的路径来解决这个问题,该路径经由最近邻上采样操作将由较深层编码的语义传送到较浅层,以确保传送的较深特征地图的空间维度与较浅特征地图的空间维度相匹配(较浅层特征地图具有更大的空间维度,其特征在于较深层的地图)。下图演示了这一过程。来自较深层和较浅层的语义的合并通过在 1×1 横向卷积层下较深层的上采样特征图和较浅层特征图的变换版本的逐元素相加来实现。最后,为了确保由这些元素相加操作生成的特征图不会受到混叠效应的影响,它们使用 3×3 卷积层进行过滤。
FPN 模块,通过右侧自上而下的分支将较深层的丰富语义转移到较浅层。
扩张的回旋
在本节中,我们将重点介绍 2016 年首次推出的扩张卷积层(通过扩张卷积进行多尺度上下文聚合)。与常规卷积滤波器不同,扩展卷积滤波器对输入特征图进行稀疏采样,以增加输出特征图的空间比例。因此,您可以将它们视为跨距大于 1 的池图层和卷积图层的替代方案,以增加 CNN 要素地图的空间比例。扩展卷积滤波器基于嵌入在它们的卷积滤波器中的孔来执行输入特征图的稀疏采样,这不同于没有孔并且依赖于输入特征图的密集局部采样的常规卷积滤波器。
为了更好地理解如何将膨胀卷积滤波器应用于输入要素地图,在下图中,我们在左侧(红色标记)显示了常规 3 x 3 卷积滤波器的卷积运算,在右侧(蓝色标记)显示了膨胀率为 2 的膨胀 3 x 3 卷积滤波器的卷积运算。如您所见,扩展卷积滤波器通过跳过(跳过被称为孔洞)每个维度中的每隔一个输入条目来对其输入要素图执行稀疏采样。换句话说,膨胀率为 2 意味着卷积滤波器对输入特征图的每个 2 x 2 区域只采样一个条目。因此,一般来说,n 的膨胀率相当于对输入特征图的每个 n×n 区域采样一个条目。注意,常规卷积滤波器是膨胀率为 1 的膨胀卷积滤波器的特例。
左:常规 3 x 3 卷积滤波器,右:膨胀率为 2 的膨胀 3 x 3 卷积滤波器
扩张卷积依赖于其感受野中的孔来增加其输出特征地图条目的空间比例。具体而言,扩展卷积滤波器的感受域中的空洞(跳跃)减少了采样的输入特征映射表条目之间的空间重叠,这导致输出特征映射表条目的空间比例增加。在上面的例子中,扩张率为 2 的扩张卷积滤波器在每两个连续的采样条目之间跳过一个特征映射条目,这导致采样特征映射条目之间的空间重叠减少。如果相邻输入要素地图条目之间存在非零空间重叠,则扩展卷积滤波器的有效空间比例将大于常规卷积滤波器的空间比例。
在这里,首先,我们推导出计算步长为 1、扩展速率为 2 的扩展的 3×3 卷积滤波器的空间尺度和重叠的公式,然后,我们将它们的空间尺度的增长率与步长为 1 和 2 的常规 3×3 卷积滤波器的增长率进行比较。让 S 和 P 分别表示输入要素地图的空间比例和重叠。此外,让 s’和 p’分别表示跨距为 1 和扩张率为 2 的扩张的 3×3 卷积滤波器的输出特征图的空间比例和重叠。然后,对于 P < 0.5, then S will be equal to 9 times of the input spatial scale S, which is the maximum increase in spatial scale that we can expect from dilated 3 x 3 convolution filters with dilation rate of 2\. In order to compute P
, two formulas are derived based on whether P < 0.5 or P > 0.5 的特殊情况,我们可以计算出 S(S,P) = 9S - 24Max(P - 0.5,0)S .如果 P < 0.5, then P
(S,P) = 15P / [9 — 24Max(P — 0.5, 0)] and if P > 0.5,那么 P`(S,P)=[6+3(1-P)-(14+4(1-P))Max(P-0.5,0)]/[9–24 Max(P-0.5,0)]。
接下来,我们比较了步长为 1 和扩张率为 2 的扩张型 3×3 卷积滤波器与步长为 1 和 2 的常规 3×3 卷积滤波器的空间尺度增长率。在下图中,我们根据图层深度绘制了对比图。蓝色曲线指的是一个 5 层卷积网络,其中所有 5 层都是步长为 1、膨胀率为 2 的膨胀卷积层。红色曲线是由 5 个步长为 2 的规则 3×3 卷积层组成的 5 层卷积网络,绿色曲线对应的是由 5 个步长为 1 的规则 3×3 卷积层组成的 5 层 CNN 网络。y 轴表示分层空间尺度宽度,其中空间尺度宽度等于空间尺度的平方根。
正如可以观察到的,具有步距 1 和扩张率 2 的扩张的 3×3 卷积层和具有步距 2 的常规 3×3 卷积层都显示了作为层深度的函数的空间尺度的指数增长率,而具有步距 1 的常规 3×3 卷积层的增长率是线性的。也就是说,扩张的 3×3 卷积层的空间尺度增长率大于步长为 2 的常规 3×3 卷积层的空间尺度增长率。特别地,扩展卷积层的最终特征图的空间比例是 243×243 像素,而跨度为 2 和 1 的 3×3 卷积层的最终特征图的空间比例分别等于 63×63 和 11×11。
步长为 1 且扩张率为 2 的扩张的 3×3 卷积层、步长为 2 的常规 3×3 卷积层和步长为 1 的常规 3×3 卷积层的逐层空间尺度宽度的比较。x 轴表示层深度,而 y 轴表示对应于每个层的空间尺度宽度。虽然步长为 1 且扩张率为 2 的扩张的 3×3 卷积层和步长为 2 的常规 3×3 卷积层都显示了作为层深度的函数的空间尺度的指数增长率,但是步长为 1 的常规 3×3 卷积层仅显示了空间尺度的线性增长率。
尽管步长为 2 的常规 3×3 卷积滤波器显示了与扩展卷积滤波器相似的空间尺度的指数增长率,但是步长为 2 的常规卷积滤波器在每次将特征地图应用于特征地图时都会导致特征地图的空间维度(宽度和高度)减半。如前所述,合并操作(如跨距大于 1 的显式合并层和跨距大于 1 的卷积层)依赖于降低要素地图的空间维度,以增加要素地图条目的空间比例。另一方面,扩张卷积滤波器基于它们的步幅 1 保持特征图的空间维度。 保持特征图的空间维度,同时通过扩张卷积滤波器以指数增长率增加其空间尺度,使其能够兼容具有密集预测的视觉任务。
具有密集预测的视觉任务的例子是语义分割、实例分割、深度估计和光流。例如,在语义分割的情况下,目标是对每个输入图像像素的类别进行预测。换句话说,如果输入图像是 W×H 像素,那么为语义分割设计的 CNN 预计会为像素类生成 W×H 预测。与执行像图像分类这样的稀疏检测任务的 CNN 相比,针对这种密集预测的 CNN 需要具有更高分辨率(更大空间维度)的特征图。对于像图像分类这样的稀疏预测视觉任务,CNN 只需要为整个输入图像输出单个预测,因此高分辨率特征图不像密集预测任务那样重要。
对于密集预测视觉任务,每个像素对应的预测既要基于嵌入在该像素局部邻域的信息,也要基于称为图像上下文的全局信息 。例如,考虑单目(单个相机)深度估计任务,像像素是建筑物的一部分这样的全局信息向网络提供像素深度的粗略估计,而像纹理这样的局部特征帮助网络进一步改进其对像素深度的估计。 保持特征图中像素的局部邻域信息需要卷积层保持特征图的空间维度,这就是为什么步长为 1 的扩张卷积滤波器对于密集预测视觉任务是必不可少的。
步长为 1 的扩展卷积滤波器保持了特征图的空间维度,这不足以确保由这些卷积滤波器生成的特征图准确地编码了像素的局部邻域信息。特别是,我们需要步长为 1 的扩展卷积滤波器将它们的空间比例限制在局部邻域内。也就是说,具有显著的空间尺度指数增长率的扩张卷积滤波器也适用于编码全局图像上下文信息。 事实上,一个设计良好的 CNN 网络受益于并行的具有一系列不同膨胀率的膨胀卷积滤波器,以编码一组具有一系列不同空间尺度的特征图,从而同时表示局部和全局信息。 这种思想被用在下面的论文中。
在用于单目深度估计的深度有序回归网络中,他们使用三个平行的膨胀卷积层(下图中称为 ASPP 模块)生成不同空间尺度的特征图,其核大小为 3×3,膨胀率为 6、12 和 18。这三个具有不同膨胀率的卷积层被应用步长 1 和零填充,以确保它们的输出特征图具有相同的空间维度,以便沿着它们的信道维度被连接。由这 3 个扩展卷积层生成的特征图的逐通道级联的统一特征图结果是具有 3 个不同空间尺度的多尺度特征图,其对特征图的每个条目的局部和全局信息进行编码。
由 ASPP 表示的三个平行分支是 3×3 的扩张卷积层,扩张率为 6、12 和 18。
下一步
该项目的下一步是为更多数量的卷积和汇集层变体导出空间比例和重叠公式,并将它们添加到代码库中。
Billboard 下一首热门歌曲的分析与预测(上)
利用 Spotify 和 Billboard 的数据来理解是什么让一首歌成为热门。
图片来自https://www . max pixel . net/Circle-Structure-Music-Points-Clef-Pattern-Heart-1790837
每年有成千上万的歌曲在世界各地发行。有些在音乐界非常成功;其他人不太喜欢。事实上,在这个行业取得成功仍然是一项艰巨的任务。投资制作一首歌需要各种活动,会消耗大量资源。很少有唱片公司会资助研究,以发现他们即将发行的歌曲在多大程度上可能成为音乐热门。
我对音乐的好奇心促使我花一些时间研究这个课题。对许多人来说,德雷克近年来成功的秘诀是他作为艺术家的风格;对其他人来说,这主要是因为他的恶名。一般来说,在解释为什么一首歌很受欢迎,而另一首却不是的时候,观点并不是单向的;或者一个艺术家在创作一首歌的时候应该优先考虑什么,如果他想让这首歌红起来的话。
这篇由两部分组成的文章是我在过去几周一直从事的项目的快照。我使用数据科学技术来了解流行歌曲的特征,更准确地说,如何可能仅根据歌曲的音频特征和歌手的个人资料来预测歌曲的流行程度。我建立了一个机器学习模型,可以将一首歌归类为热门与否。
虽然社会因素,如歌曲播放的背景,听众的人口统计数据,以及营销活动的有效性,也可能在它的病毒式传播中发挥重要作用,但我假设歌曲的固有特征,如演唱它的艺术家的简介,它的持续时间,它的音频特征可能是相关的,也揭示了它的病毒式传播。
作者图片
我的数据
我不能从一个单一的来源得到一个包含所有变量的数据集。为了克服这个问题,我借助了数据丰富技术,使用了以下三个数据源:Billboard、Spotify 和 Genius。
先用美人汤收集了 2010-2019 年 Billboard 年终热门 100 首歌曲的列表,以每年 100 首的速度。然后,使用 Spotipy 包来恢复与歌曲音频特征相关的数据,例如可跳舞性、乐器性、活跃度等。,一方面;另一方面,与艺术家的简档相关的那些,例如追随者的数量、受欢迎程度等。对于先前恢复的同一时期的热门歌曲和其他非热门歌曲。
最后, Genius 将主要用于检索已经收集的所有歌曲的歌词。
在我们的数据集中,如果一首歌在报告期内的任何一年中至少一次出现在 Billboard 年终热门 100 强排行榜上,就被认为是热门歌曲。换句话说,我们的模型的任务是预测一首歌是否会进入 Billboard 的 100 首最受欢迎歌曲名单。
使用的工具:
- 从 Spotify 音乐平台获取数据的 Spotify 包
- seaborn 和 matplotlib 用于数据可视化
- 熊猫和 numpy 进行数据分析
- LightGBM 和 scikit-learn 库,用于构建和评估模型
特性
Spotify 是世界上最大的流媒体平台之一。像 Twitter 或脸书一样,它提供了一个 API(应用程序编程接口),以便开发者可以与它庞大的音乐数据库进行交互。通过这个 API 的端点,我能够收集超过 22,000 首歌曲的数据;每首歌都有二十多个变量。
API 返回的变量信息丰富多样。然而,我只选择了那些被认为与工作相关的。然后,使用特征工程技术对它们进行转换,以便为训练模型准备尽可能好的数据集。在这里,您将找到中使用的每个变量的描述。一般来说,项目的完整代码可以通过这个链接访问。
其中一些变量仅用于分析,其他变量则涉及整个流程的各个阶段。现在让我们看看数据集的前五个观察值是什么样的。
我们数据集的前五个观察值,包含来自 24 个变量的 19 182 个观察值。
数据可视化
就在构建模型之前,我想通过可视化来探索一下数据;尽管这项工作的主要目标不是进行全面的探索性分析。
图一
根据上面的图表,一月是发行更多热门歌曲的月份;七月是最少被要求的。我们还注意到,这段时间的大部分点击都发生在一周的第四天;也就是周四。最后,月初一多用来发表一首歌。
基于这一观察,我们可以推断出在 1 月 1 日发表一首歌可能是朝着优化其病毒式传播的机会迈出的一步。我们仍然必须小心:相关性不是因果关系。为了使这一结论更加准确,我们必须进一步分析。
我继续想象,想知道在这段时间里哪些艺术家录制了最多的热门歌曲。不出所料,下图显示,德雷克、蕾哈娜和泰勒·斯威夫特等艺术家在此期间的点击率比其他任何人都高。也就是说,如果一首歌包含这些艺术家之一的声音,它更有可能被广泛传播。
图 2
去理解是什么让一首歌成为热门;而另一个则不然,研究这两个类别的音频相关变量势在必行。这就是我想要得到的,关于这两类变量分布的想法。
图 3
这两个类别中的主要变量是相同的:能量,可舞性和化合价。唯一的区别是,对于热门歌曲类别,这些变量的平均值更高。这证明了热门音乐更快更响亮。他们更适合跳舞,更倾向于激发喜悦、欢乐和兴奋。
机器学习方法
到目前为止,我们已经发现了一些关于数据的有趣见解。为了缩短这篇文章,让我们直接进入关于使用的机器学习算法的部分。
我想建立一个模型,根据一组解释变量来预测一首歌最有可能属于哪个类别,热门还是非热门,正如本文开头所解释的那样。
在其原始状态下,收集的数据还不能用于训练机器学习模型。所以我治疗他们;首先,使用 SMOTE 技术,因为与非热门类别相比,热门歌曲类别的代表性不足,然后通过使用其他特征工程技术来标准化数据。
此外,我想要一个性能尽可能好的模型。为此,我训练了几个算法,并根据选定的评估标准比较了结果。结果表明,LightGBM 分类算法在训练时能够更好地检测出解释变量和待预测变量(hit)之间的模式。
混乱矩阵
对于模型的第一级性能分析,我们将使用混淆矩阵。混淆矩阵的可视化将允许我们理解我们的分类器与测试子集相比所产生的错误。
这个矩阵衡量一个分类系统的质量。在二元分类中,主对角线代表被模型正确分类的观察值;和次对角线,那些分类不正确的。因此,该模型最常犯的错误是将一首歌曲分类为非热门歌曲,而实际上它是热门歌曲(129 例),更准确地说是第二类错误。
第一类错误是模型把宋在非命中(误命中)的情况下归类为命中;而第二类错误,则相反;也就是说,它将一首音乐分类为未命中,但它却被命中(假未命中)的情况。如果我们试图理解一个音乐制作人的心理,第一类错误比第二类错误更不可接受。我们不想承担与制作和推广一首歌曲相关的所有费用,因为一个模特已经预测这首歌会很受欢迎,但最终却不会。类型 I 误差的值应该是最小的。
分类报告
分类报告显示从混淆矩阵中的数据计算出的统计数据。每个指标描述了分类的不同方面。我们将使用此报告对模型进行二级性能分析。
准确度是 96%,它全面衡量了模型执行的正确分类的百分比。由于测试子集是不平衡的,这个百分比被过度表示的类(在本例中为非命中类)拉伸。所以这个指标不是我们能使用的最好的。
召回衡量模型对每个类别正确分类的事件的百分比。当预测类别与实际类别匹配时,分类是正确的。一方面,从我们用来测试模型的 5484 首非热门歌曲中,98%被正确分类。另一方面,该算法只正确分类了我们提交给它的 271 首热门歌曲中的 52%。你就明白了:算法把一首热播的歌归类为热播(真热播)比把一首非热播的歌归类为非热播(真非热播)更难。
非命中类和命中类的精度级别分别为 0.98 和 0.55。这意味着模型归类为非热门的所有歌曲中的 98%实际上都是非热门的;而且,只有 55%它预测会成功的歌曲是真的。
当涉及到非热门歌曲时,我们的模型反应更好。这很可能是因为从一开始这个类就有更多的数据。因变量的非命中模态和其他解释变量之间的模式检测可能因此而受到青睐。
一旦对模型的表现感到满意,我就决心去了解在确定一首给定歌曲的类别时最有影响力的解释变量。这就是为什么我在下面使用了情节重要性。
图 4
我们可以看到,一首歌在 Spotify 上的受欢迎程度是预测它最有可能属于哪个类别的过程中最重要的变量。然后,艺术家在 Spotify 上的受欢迎程度、他的粉丝数量以及这首歌在哪些市场上销售,构成了这一过程中的第二波决定性变量。最后主要是与具有相对相似影响水平的歌曲的音频相关的变量。
这一分析引起了人们对一些重要问题的关注。从本质上来说,如果一首歌在 Spotify 上很受欢迎,由一位在 Spotify 上也很受欢迎并拥有大量粉丝的艺术家演唱,最后,如果这首歌在世界上最大数量的国家都能听到,那么这首歌就是热门歌曲。这个结论似乎是合乎逻辑的,而且……🙂我们的模型也验证了这一点。
为了更好地理解这一结论的相关性,应该记住,Billboard 的年终 100 首音乐排行榜主要基于商业方面。事实上,这个排名忠实地反映了美国的实物和数字销售、广播收听和音乐流媒体;所有直接或间接的创收活动。
这首歌在 Spotify 上越受欢迎,在线收听的次数就越多。;更多的流媒体可以转化为更多的收入,因为在用户听完每首歌曲后,流媒体平台会向艺术家或音乐公司支付费用。这位艺术家在 Spotify 上的受欢迎程度以及他在 Spotify 上的粉丝数量,这些渠道放大了流量和销售额,这将有助于增加他的音乐带来的收入。
音乐产生的收入越多,它就越有可能在年底登上 Billboard 的 100 首音乐排行榜;因此,它也越有可能被我们的模型排名命中,因为根据我们的重要性图,主要决定音乐收入水平的变量在排名过程中最有影响力(逻辑,不是吗😉?).
通常,歌曲还有一个我们还没有考虑到的重要特征:歌词。是否可以通过使用歌词来进一步增加模型的性能?这是我们将在文章的第二部分探讨的内容。
一如既往,我欢迎建设性的批评和反馈。你可以在 Twitter @ jbobym 上找到我。
路透社文章的文本数据分析和可视化
借助 K-Means、N-gram、Tf-IDF、条形图、单词云、NER 等工具研究路透社的文章。方法
被困在付费墙后面?点击这里阅读这篇文章和我的朋友链接。
资料来源:Jaredd Craig-Unsplash
当我要求你解释文本数据时,你会怎么做?你将采取什么步骤来构建文本可视化的故事?在这里,我不打算解释你如何创建一个可视化的故事。
但是本文将帮助您获得构建可视化故事和解释文本数据所需的信息。
从文本数据中获得的洞察力将帮助我们发现文章之间的联系。它将检测趋势和模式。对文本数据的分析将把噪音放在一边,并揭示以前未知的信息。
这个分析过程也被称为探索性文本分析(ETA)。借助 K-means、Tf-IDF、词频等。方法,我们将分析这些文本数据。此外,ETA 在数据清理过程中也很有用。
我们还使用 Matplotlib、seaborn 和 Plotly 库将结果可视化为图表、单词云和绘图。
在分析文本数据之前,请完成这些预处理任务。
从数据源检索数据
有大量的非结构化文本数据可供分析。您可以从以下来源获取数据。
1.来自 Kaggle 的 Twitter 文本数据集。
2.使用 API 的 Reddit 和 twitter 数据集。
3.使用 Beautifulsoup 从网站上抓取文章并请求 python 库。
我将使用 SGML 格式的 路透社的文章 。出于分析目的,我将使用 Beautifulsoup 库从数据文件中获取日期、标题和文章正文。
使用下面的代码从所有数据文件中获取数据,并将输出存储在一个 CSV 文件中。
1。您还可以使用 Regex 和 OS 库来组合或循环所有数据文件。
2。每篇文章的正文以<路透>开头,所以使用 find_all('reuters ')。
3。您还可以使用 pickle 模块来保存数据,而不是 CSV。
数据清理过程
在这一节中,我们将删除诸如空值、标点符号、数字等干扰。从文本数据中。首先,我们删除文本列中包含空值的行。然后我们处理其他列的空值。
import pandas as pd import rearticles_data = pd.read_csv(‘articles_data.csv’) print(articles_data.apply(lambda x: sum(x.isnull()))) articles_nonNull = articles_data.dropna(subset=[‘text’]) articles_nonNull.reset_index(inplace=True)def clean_text(text):‘’’Make text lowercase, remove text in square brackets,remove \n,remove punctuation and remove words containing numbers.’’’ text = str(text).lower()
text = re.sub(‘<.*?>+’, ‘’, text)
text = re.sub(‘[%s]’ % re.escape(string.punctuation), ‘’, text)
text = re.sub(‘\n’, ‘’, text)
text = re.sub(‘\w*\d\w*’, ‘’, text)
return textarticles_nonNull[‘text_clean’]=articles_nonNull[‘text’]\
.apply(lambda x:clean_text(x))
当我们删除文本列中存在的空值时,那么其他列中的空值也会消失。
我们已经使用 re 方法去除文本数据中的噪声。
数据清理过程中采取的步骤可能会根据文本数据增加或减少。因此,请仔细研究您的文本数据,并相应地构建您的 clean_text()方法。
随着预处理任务的完成,我们将继续分析文本数据。
先说我们的分析。
1.路透社文章的长度
我们知道所有文章的长度是不一样的。因此,我们将考虑那些长度等于或超过一个段落的文章。根据这项研究,一个句子的平均长度是 15-20 个单词。一个段落中应该有四个句子。
articles_nonNull[‘word_length’] = articles_nonNull[‘text’].apply(lambda x: len(str(x).split())) print(articles_nonNull.describe())articles_word_limit = articles_nonNull[articles_nonNull[‘word_length’] > 60]plt.figure(figsize=(12,6)) p1=sns.kdeplot(articles_word_limit[‘word_length’], shade=True, color=”r”).set_title(‘Kernel Distribution of Number Of words’)
来源:作者图片
我已经删除了那些长度小于 60 字的文章。
字长分布是右偏的。
大部分文章都在 150 字左右。
包含事实或股票信息的路透社文章字数较少。
2.路透社文章中的常用词
在这一部分,我们统计文章中出现的单词并分析结果。我们基于 N-gram 方法分析单词计数。N-gram 是基于其 N 值的单词的出现。
我们将从文本数据中删除停用词。因为停用词是噪音,在分析中没有多大用处。
1.最常见的单字单词(N=1)
让我们在条形图和单词云中绘制单词。
来源:作者图片
来源:作者图片
股票,贸易和股票是一些最常见的词,基于股票市场和金融部门的文章。
因此,我们可以说,大多数路透社的文章属于金融和股票类。
2.最常见的二元词(N=2)
让我们为 Bigram 单词绘制条形图和单词云。
article_bigrams = defaultdict(int)
for tweet in articles_word_limit[‘temp_list_stopw’]:
for word in generate_ngrams(tweet, n_gram=2):
article_bigrams[word] += 1df_article_bigrams=pd.DataFrame(sorted(article_bigrams.items(),
key=lambda x: x[1])[::-1])N=50# bar graph of top 50 bigram words
fig, axes = plt.subplots(figsize=(18, 50), dpi=100)
plt.tight_layout()
sns.barplot(y=df_article_bigrams[0].values[:N],
x=df_article_bigrams[1].values[:N],
color=’red’)
axes.spines[‘right’].set_visible(False)
axes.set_xlabel(‘’)
axes.set_ylabel(‘’)
axes.tick_params(axis=’x’, labelsize=13)
axes.tick_params(axis=’y’, labelsize=13)
axes.set_title(f’Top {N} most common Bigrams in Reuters Articles’,
fontsize=15)
plt.show()#Word cloud
wc = WordCloud(width=2000, height=1000, collocations=False,
background_color=”white”,
color_func=col_func,
max_words=200,
random_state=np.random.randint(1,8))\
.generate_from_frequencies(article_bigrams)fig, ax = plt.subplots(figsize=(20,10))
ax.imshow(wc, interpolation=’bilinear’)
ax.axis(“off”)
ax.set_title(‘Trigram Words of Reuters Articles’, pad=24,
fontdict=fd)
plt.show()
来源:作者图片
来源:作者图片
Bigram 比 unigram 提供了更多的文本信息和上下文。比如,股票损失 bigram 显示大多数人在股票上赔钱。
3.最常见的三元组单词
让我们为 Trigrma 单词绘制条形图和单词云。
article_trigrams = defaultdict(int)
for tweet in articles_word_limit[‘temp_list_stopw’]:
for word in generate_ngrams(tweet, n_gram=3):
article_trigrams[word] += 1
df_article_trigrams = pd.DataFrame(sorted(article_trigrams.items(),
key=lambda x: x[1])[::-1])N=50# bar graph of top 50 trigram words
fig, axes = plt.subplots(figsize=(18, 50), dpi=100)
plt.tight_layout()
sns.barplot(y=df_article_trigrams[0].values[:N],
x=df_article_trigrams[1].values[:N],
color=’red’)
axes.spines[‘right’].set_visible(False)
axes.set_xlabel(‘’)
axes.set_ylabel(‘’)
axes.tick_params(axis=’x’, labelsize=13)
axes.tick_params(axis=’y’, labelsize=13)
axes.set_title(f’Top {N} most common Trigrams in Reuters articles’,
fontsize=15)
plt.show()# word cloud
wc = WordCloud(width=2000, height=1000, collocations=False,
background_color=”white”,
color_func=col_func,
max_words=200,
random_state=np.random.randint(1,8)).generate_from_frequencies(article_trigrams)
fig, ax = plt.subplots(figsize=(20,10))
ax.imshow(wc, interpolation=’bilinear’)
ax.axis(“off”)
ax.set_title(‘Trigrams Words of Reuters Articles’, pad=24,
fontdict=fd)
plt.show()
来源:作者图片
来源:作者图片
大多数三元模型类似于二元模型。三元组单词比二元组单词更能帮助我们理解文本。但是不能提供更多的信息。所以这一节到此结束。
3.文本数据的命名实体识别(NER)标记
NER 是从文本数据中提取特定信息的过程。在 NER 的帮助下,我们从文本中提取位置、人名、日期、数量和组织实体。点击了解更多关于 NER 的信息。我们使用 Spacy python 库来完成这项工作。
来源:作者图片
从这个图表中,你可以说大多数文章包含了来自美国、日本、加拿大、伦敦和中国的新闻。
对美国的高度提及代表了路透社在美国业务的重点。
人物变量暗示 1987 年的著名人物是谁。这些信息有助于我们了解那些人。
这个组织变量包含了全世界最多提及的组织。
4.文本数据中的唯一单词
我们将使用 TF-IDF 在文章中找到独特的单词。词频(TF)是每篇文章的字数。逆文档频率(IDF)在考虑所有提及的文章时测量单词的重要性。
对于那些在一篇文章中具有高计数而在其他文章中很少或不存在的词,TF-IDF 得分很高。
让我们计算一下 TF-IDF 得分,找出独特的单词。
from sklearn.feature_extraction.text import TfidfVectorizertfidf_vectorizer = TfidfVectorizer(use_idf=True)
tfidf_vectorizer_vectors=tfidf_vectorizer.fit_transform(articles_word_limit[‘text_clean’])
tfidf = tfidf_vectorizer_vectors.todense()
tfidf[tfidf == 0] = np.nan#Use nanmean of numpy which will ignore nan while calculating mean
means = np.nanmean(tfidf, axis=0)# convert it into a dictionary for later lookup
Means_words = dict(zip(tfidf_vectorizer.get_feature_names(),
means.tolist()[0]))
unique_words=sorted(means_words.items(),
key=lambda x: x[1],
reverse=True)
print(unique_words)
来源:作者图片
5.使用 K-Means 聚类文章
K-Means 是一种无监督的机器学习算法。它帮助我们在一个组中收集相同类型的文章。我们可以通过初始化 k 值来决定组或簇的数量。了解更多关于 K-Means 和我们如何在这里选择 K 值。作为参考,我选择 k=4 组成四组。
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.metrics import adjusted_rand_scorevectorizer = TfidfVectorizer(stop_words=’english’,use_idf=True)
X = vectorizer.fit_transform(articles_word_limit[‘text_clean’])
k = 4
model = KMeans(n_clusters=k, init=’k-means++’,
max_iter=100, n_init=1)
model.fit(X)
order_centroids = model.cluster_centers_.argsort()[:, ::-1]
terms = vectorizer.get_feature_names()
clusters = model.labels_.tolist()
articles_word_limit.index = clusters
for i in range(k):
print(“Cluster %d words:” % i, end=’’)for title in articles_word_limit.ix[i
[[‘text_clean’,’index’]].values.tolist():
print(‘ %s,’ % title, end=’’)
它帮助我们将文章分类到不同的类别,如体育、货币、金融等等。K-Means 的准确率普遍较低。因此,这在低级分析中是有用的。
结论
NER 和 K 均值是我最喜欢的分析方法。其他人可能喜欢 N-gram 和独特的单词方法。在本文中,我介绍了最著名的、闻所未闻的文本可视化和分析方法。本文中的所有这些方法都是独一无二的,可以帮助您进行可视化和分析。
我希望这篇文章能帮助你发现文本数据中的未知。
作者的其他文章
NBA 暂停后比赛分析
你经常听到教练因为他们在暂停(ATO)比赛后的平局和执行能力而受到表扬,但是,我们将看看 ATO 比赛的成功实现和球队的胜率之间是否有任何关联。此外,我将看看谁是执行这些相同行动的最成功的玩家。
数据
这些数据是通过 NBA 的逐场比赛数据收集的。我找到了今年赛季所有的暂停,总计 10905 次暂停。之后的目标是找到下一个动作。以下是所有发生的“下一步行动”,我过滤掉了替换:
- 错过的镜头:3927
- 投篮次数:3030 次
- 犯规次数:1463 次
- 营业额:1106
- 罚球:1095
- 跳球:100
- 违反次数:71 次
- 超时:53
- 游戏结束:31
- 进攻犯规:29 次
如您所见,这是相当不理想的数据,我们可以在这里过滤掉更多的内容。所以我也跳过了罚球(因为 TO 是在犯规之后/罚球之间被叫的)、暂停、跳球(和罚球一样)、违例(因为那是比赛的某种延迟,不影响动作),把进攻犯规归为失误(事实就是如此)。我简单地删除了游戏结束的动作,因为我真的不能从它们中分辨出任何东西。其结果如下:
- 错过的镜头:4047
- 投篮次数:3121 次
- 营业额:1307
- 犯规次数:1136 次
团队成功
我想看的第一件事是这些团队在这些行动中有多成功。为了做到这一点,我看了看投篮不中/投篮命中和失误,以确定成功与否。我通过一个简单的条形图显示了这些动作的数量,见第一张图片。
作者图片
令我惊讶的是,奥兰多魔术队是迄今为止最成功的,其次是奇才队和雷霆队。排在第四位的尼克斯也相当令人意外。
鹈鹕队几乎是最后一名也让人有点意外。他们明显排在最后。
然而,所有其他数字都相对接近,没有人真正跳出来。
ATO 的成功会产生“更好的团队”(更好的胜率%)吗?
号码
两者之间没有相关性,实际上,r 值几乎为零,这意味着没有正相关或负相关。
作者图片
第二个图表显示了 ATO 游戏的成功率和获胜百分比。我把 ATO 剧的成功定义为made shots / (made shots + missed shots + turnovers)
。
到现在为止,你可能已经发现我完全忽略了犯规(除了进攻犯规,我把它归类为 TOs),原因是推断那场比赛是否成功是相当复杂的,我真的不想探究那么深(我将来可能会……)。
看看最成功的球员
暂停后,处理投篮最多的球员是球队的明星和领袖。
作者图片
前面的图表显示了一些投篮次数最多的球员。
对我来说,这个图表中的惊喜是朱利叶斯·兰德尔、马库斯·莫里斯和乔·哈里斯。前两次是在尼克斯队,所以我想他们只是等了一下,然后开车/停车准备投篮。另一方面,乔·哈里斯是一个 3 分专家,所以在视频上检查可能是一件有趣的事情。
don ici、Dinwiddie 和 Randle 再次成为此类行动中效率最高的人。Joki 和 Beal 是在 ATO 剧中拍摄大量镜头的“老黄牛”。
无辅助与辅助拍摄
作者图片
最后一个图表解释了为什么兰德尔和莫里斯都有这么多镜头。他们每个人都创造了他们得分的几乎所有投篮机会(我们可以假设他们也创造了自己的投篮失误)。
在光谱的另一端,有乔·哈里斯和布林·福布斯。他们在左上角,在“中心之地”。他们都是三分专家,这个分析显示他们在这方面相当擅长。我看了看为哈里斯准备的剧本,很多都是画动作的。
对他来说是双重掩护,由中锋掩护,由其他后卫切入/掩护,这让哈里斯可以拿下三分。
卢卡·东契奇也给我留下了深刻的印象,但他的 ATO 风格与哈里斯相反。他的大部分投篮都是在无人帮助的情况下完成的,他要么奔向篮筐,要么后退一步停下来。他以一种令人印象深刻的方式创造了他的镜头。
结论
这只是暂停播放后的一个快速预览,你可以越来越深入,并观看录像带产生一些其他的结论。如果有可能做以下事情之一,那将会非常酷:
- 检查每一个动作的拍摄时间(你不能通过一个接一个的播放来获得,因为动作并不总是在 24 秒开始)
- 检查暂停后的镜头是否比通常的镜头更“开阔”
- 检查一个人在暂停后是否在投篮中带了更多的运球(即使在暂停后,我们也可以假设休斯顿的进攻是哈登/威斯布鲁克的 Iso,但这将证实这一点)
- 还有更多…
如果你想看更多我的东西,请访问我的网站、脸书或 Instagram 个人资料。如果你想查看代码,可以在我的 Github 中找到。
新加坡 Airbnb 分析
做 Airbnb 主持人价格和地点最好?
帕特里克·帕金斯在 Unsplash 上的照片
随着共享经济中在线市场的兴起,许多人都想成为卖家或服务提供商。我将看看新加坡,新加坡允许普通房主出租部分或全部房屋至少 3 个月。在受欢迎的酒店网站中,Airbnb 被选中,因为它是可靠的数据提供商。它从他们自己的网站上收集了所有的列表和评论,多达约 90,000 行数据。这将增加结果的可靠性,即使在数据清理之后。此外,还收集了客户的评论数据。
Airbnb 的数据可以在这里找到:http://insideairbnb.com/get-the-data.html也可以在你自己国家的 Airbnb 上随意尝试分析一下!
为什么看评论?
当人们在网上购物或寻找酒店住宿时,他们会转向评论和推荐部分进行参考。以往顾客的评论通常被认为是可靠的,反映了他们对公司商品和服务的满意程度。因此,这引导他们决定是否应该资助一家公司。随着评论的访问变得容易,深入了解评论如何影响企业收入变得重要。在 Airbnb 的案例中,他们还根据审核分数将主机分为普通主机或超级主机。我们还将探讨普通主机与超级主机的主要区别。
U 最后,我们将研究潜在的新主机如何决定价格、位置、服务周期和主机类型,从而在新加坡实现收入最大化。
数据清理
回想一下,Airbnb 提供了两种不同类型的数据,即房源(包括价格、卧室、位置等)。)以及评论。
对于 listings.csv
1)删除所有 NaN 值(缺失数据)
2)用 1 和 0 替换 host _ is _ superhost 超级主机,0 =普通主机)
3)将价格从字符串转换为整数(例如$84 到 84)
4)将“id”重命名为“listing_id ”,以匹配 reviews.csv 中的列标题
查看评论. csv
1)将日期拆分为年、月和日列,只保留年和月,以便进一步选择数据和检查高峰期
合并 reviews.csv 和 listings.csv
1)仅保留 2019 年的最低住宿<=365, property type either apartment or condominium. This is to fix variables to minimise confounders.
2) Calculated revenue based on minimum nights * price and then summing the rows with the same listing id (i.e est_rev=minimum_ nights * price * number of reviews)
3) Removed all listings with only 1 review (i.e price*min nights=revenue, which might be pulling down the average)
4) Removed year, day, date columns since they are already fixed or are not useful variables
The final dataframe looks like this
Image by Author
****价格&基于位置的收入
先说 Airbnb 的位置。这对于打算购买租赁物业并需要知道哪个位置将产生最高收入的主机来说是有用的。
作者图片
大多数 Airbnb 都位于主干道附近,或者在南部/商业区。这可能是因为新加坡的 Airbnb 的最短停留时间为 3 个月,Airbnb 的客户预计是来新加坡工作的外籍人士,他们更喜欢住在工作地点附近。
让我们看看基于 Airbnb 位置的收入。由于价格和收入的巨大差异,每个待评估区都采用中间值。
作者图片
作者图片
使用上述每个地区的价格和收入中值,以及新加坡的上市公司,我们可以看到,商业区周围的集群中的价格最高。事实上,离商业区越远,价格中位数就越低。这一趋势也遵循了地区收入的中位数,反映了基于到商业区距离的定价策略的有效性。然而,人们预计商业区的房价也会更高。该成本没有反映在模型中,但仍应予以考虑。
为了规避我们不知道的成本问题,另一种方法是记录中值价格低于其他地区但收入中值相对较高的地区。这意味着可能会有更频繁的预订,使位置更有吸引力,同时可能有更低的房地产成本。
作者图片
根据排名值,排名的积极变化反映了该地区的中值价格低于其同行,但中值收入较高。在该图中,Holland Village 的价格和收入变化最大。这将使它成为一个值得注意的地区。
基于季节/月份的预订和收入
接下来,我们可以看看预订高峰期。这将使主人能够更好地安排他们的时间来维护房子,积极地寻找顾客,或者相应地改变他们的价格。然而,由于可用数据是在进行审查的当月(即客户曾入住 Airbnb,现在正准备离开),分析将围绕客户结束入住的时期进行。
作者图片
纵观 2019 年,高峰期为 7 月至 9 月。一个可能的理由是,7 月被认为是人们寻找新工作的黄金时期,也是公司财年结束的常见时期。这可能会导致更多的外籍人士结束他们在新加坡的生活,去寻找新的工作,或者因为他们的工作而被重新安置到另一个国家。因此,这将是主人为房子服务的好时期,可能会在 7 月前开始寻找新客户。
基于主机类型的收入
最后,在确定宿主如何成为超级宿主之前,检查宿主类型的重要性是至关重要的。
作者图片
特别是,超级主机的年平均收入为 11,180 美元,而普通主机的年平均收入为 3,135.50 美元。超级主机和普通主机赚取的收入之比为 3.57 (2dp),看起来差距巨大。因此,由于潜在的更高收入,这将为主机努力成为超级主机提供有效的理由。
普通主机和超级主机的主要区别
既然超级宿主的重要性已经确定,那么目标就是找出是什么因素使得宿主成为超级宿主。这是通过对顾客评论的情感分析来完成的。在删除了意义不大或没有意义的单词之后,正常主机和超级主机的结果单词云如下:
作者图片
两个词云看起来都差不多,常用词应该解释为对主机的基本要求。然而,主要的想法是超级主机应该有一些关键词来区别于普通主机。这是通过选择每个词云中的前 10 个关键词并找到区分因素来完成的。这个因素原来就是‘有益’二字。一种解释是,东道主与客户有更大的接触,即使在租赁/合同中没有说明,也可能免费提供帮助。
假设和限制:
一个假设是在估计收入的计算中。等式是 est _ rev =价格最低 _ 夜评论数。每位顾客的停留时间可能不完全是要求的最少住宿时间,也不是每位顾客在停留后都要写点评。这意味着计算出的收入严重低估了实际收入。此外,主办方的主要目标是实现利润最大化,但没有关于房产成本的信息,这使得很难确定在哪个地区购买房产最合适。
结论
在分析了地点、时期和东道主类型后,主办的最佳地点可能是商业区(收入最大化)或荷兰村(预订量最大化)。他们可以选择使用该地区 Airbnb 的中间价格,以确保更一致的预订。维护和服务的高峰期将在 7 月至 9 月,主机可以在 7 月前寻找新客户。最后,主机状态是收入的一个重要变量,应该是主机的目标。为了实现这一点,主人应该超越提供基本的便利设施,并试图在顾客眼中更“有帮助”。
双模态出行分析
在 上一篇文章 中,我分析了 BiciMAD 车站的位置和特征,现在是时候继续分析以了解用户要去哪里以及最受欢迎的路线是什么,根据他们的类别 user_type (订户、临时用户……)进行聚类。
请注意,本文中讨论的图表、数据集、Tableau 报告和 Python 笔记本可以在 GitHub 上找到(免费)。
资料组
为了对路线进行分析,我使用了马德里市交通局在其开放数据网站上提供的数据。从 2017 年 4 月到 2018 年 9 月,路线数据在 18 个存档中可用,JSON 文件也一样多。该文件的每一行都是一个首尾相连的 JSON,包含每次从底座上移除一辆电动自行车的信息(包括 EMT 雇主何时移除)。
总的来说,这些文件包含了超过 500 万次提款的详细信息,每个存档大小为 500 到 1500 Mb(压缩时),值得注意的一点是,不幸的是,有 17 个压缩存档和 1 个 RAR 存档,这并不好,因为整个数据集太大,无法解压缩并导入到单个 Pandas 数据帧中。
出于这个原因,我选择走一条不同的路:我确定了一些要提取的信息,然后编程 Python 来提取每个月的 JSON 文件,打开它们并一次保存想要的信息。该脚本一次处理 25,000 行,然后将这些行汇总到几个 CSV 文件中。
EMT 公司还提供了一个简短的指南来理解每个字段的含义,该指南有西班牙语版本,可从此链接下载。
缺失数据
乍一看,我们可以看到两个有趣的字段丢失了:自行车 ID 和用户 ID。缺少用户 ID 很可能是因为隐私原因,但我无法理解自行车缺少唯一标识符的原因。提取站点之间每辆自行车的使用信息(由用户和 EMT 雇主)会非常有趣。
分析目标
这项分析的目标是:
- 了解 BiciMAD 用户的习惯,特别是他们何时使用自行车以及出于何种目的;
- 了解用户是否有明显的细分;
- 了解 BiciMAD 用户骑自行车最频繁的旅行。
探索性数据分析
首先,我们评估我们所掌握的数据的数量和主要统计参数。
5478168
之后,我们验证插入和拔出工作站的 id 是否都存在于上一篇文章生成的注册表中。
一个显而易见的方面是,站点的最大值是 2008 年。从上一篇文章中,我们知道这些站是由一个从 1 到 175 的 ID 来标识的,所以 2008 是一个异常值。
2008 站
由于数据帧是由我制作的脚本生成的,我检查了 EMT 提供的原始数据中是否有转移到 2008 站的线路,以确保这不是我的错误。我取 2017 年 12 月的月份,因为(作为冬季月份)该文件肯定比其他月份小。
2008 年的值作为站点 ID 也出现在最初提供的数据中,因此它不是与我的数据汇总脚本相关的错误的结果。
直观地说,2008 可能是一个逻辑站的 ID,在那里放置有一些异常的自行车,例如,那些正在维修或被盗的自行车。对我来说,很难证实这一事实,但考虑到这些线只是总数中的几条,我可以将它们从数据框中删除,而不会对最终结果产生明显的伪造影响。
22 号站
路线中的另一个车站不在上一篇文章中创建的车站注册表中:车站编号 22。
通过两个简单的查询,我了解到该站可能仅在“2017-05-01”和“2017-12-01”之间活跃,现在它已经不存在了,但是 EMT 提供的关于该站的公开数据仅涵盖 2018 年 7 月至 9 月之间的几个月。
为了解决这个问题,我搜索了一些 BiciMAD 站的 2017 年地图,但没有获得有用的信息,因为地图上的站是用“数字”字段而不是“ID”标识的。
作为最后一次检查,我查看了 ID 为 22 的车站的上下两个车站。
从数据中,我们可以看到有一个站 20a。通常当 EMT 用字母表字母识别一个站时,这是因为至少有两个附近的站,但是在这种情况下,站 20b 丢失了:很可能我正在寻找的 ID=22 站实际上是数字 22b。
这些信息足以限制我的搜索范围:
- ID=20 之间的一个站
- 它从 2017 年 5 月 1 日到 2017 年 12 月 1 日一直在那里
从谷歌地图上,我终于可以找到 ID=22 的车站,这是 20b 车站,直到几个月前还位于卡莱阿尔卡兰 49 。
由于 22 号站确实存在于过去,我决定不从文件中删除它的台词。
trips 分析
在下图中,颜色红色标识年度会员用户,颜色蓝色标识临时用户,颜色绿色,最终标识 EMT 雇主。
首先,我将 EMT 提供的全部数据以月为粒度绘制在时间轴上,以了解自行车租赁数量是否存在季节性。
结果(如图所示)是这项服务有很大的季节性。我们可以看到,除了 8 月份红线(年度会员用户)下降之外,这两条线路在夏季都有一个高峰,这可能是因为在 8 月份,由于假期,许多办公室的工作量较轻,因此可以证明 user_type=1 使用自行车从家到工作场所往返。
从这个图表我们可以得出更多的结论:
- 在冬季,马德里的气温非常寒冷,因此两个用户类型都喜欢少骑自行车出行,而不喜欢其他交通工具;
- 从 user_type=1 到 user_type=2 的行程数之间有巨大的差距:它们是一起绘制的,但是检查 y 轴上左边和右边的刻度…它们有不同的数量级!
该图显示了 EMT 提供的整个月份中一周内每天的行程,因此从 2017 年 5 月到 2018 年 9 月。显然,年度用户在一周的第一个和最后一个工作日有一个使用高峰,而临时用户几乎有一个补充使用。
在这张图表中,我们可以看到一天中几个小时的行程变化。我认为红线支持这样的论点,即每年有很大一部分用户使用 BiciMAD 的电动自行车往返于家和办公室之间,我们可以很容易地看到用户从家通勤到工作场所(上午 7-9 点),出去吃午饭(下午 2-3 点),晚上 5-7 点回家。
在一系列的情节之后,我决定更进一步,看看 EMT 提供的整整一年半的时间,看看我是否能了解更多关于用户习惯的信息。出于这个原因,我决定制作 3 张地图图来了解工作日和整个时间线上的旅行分布。
这些图表向我展示了一些意想不到的数据,如果可能的话,这将是一个非常有趣的研究,可能会在未来的博客上发布:
- 在五月、六月和八月,有几天几乎没有来自 user_type=1 (年度订户)的旅行,以及 user_type=2(临时用户)和 user_type=3(雇主)的爆炸式增长。这是非常可疑的!这可能是数据收集过程中的一个错误,或者可能是一些技术问题,阻止了年度用户使用他们的卡来租赁自行车,所以他们不得不作为临时用户进行租赁(许多 EMT 雇主正在努力解决这个问题)。
- 在周末有一个令人惊讶的 EMT 雇主使用自行车的高峰,如果他们在即将开始的一周内维护自行车或移动车队,这将是很有意思的。
- 2017 年 5 月第一周的前几天,没有一个 user_type=2 次出行…对吗?
- 在 2017 年 10 月期间,在 user_type=2 的图表中有深蓝色的日子,这意味着在这段时间内有大量的旅行,比之前和之后的几周都多。了解这一高峰的原因会很有趣,这可能是一些关于 BiciMAD 服务的营销活动。
对于这个分析,我研究的最后一点是总的环行程数。环形旅行是在同一个车站开始和结束的旅行。考虑到租赁自行车的价格,用户不太可能拔掉自行车的插头,例如去超市而不把自行车插到另一个底座上,然后回来,除非这是一个非常快速的差事。在 user_type=2 之间进行环形旅行的可能性更大,因为他们可以骑自行车游览马德里市和一些有趣的景点(例如 Retiro park ),比步行更快。
user_type
0 5.336718
1 2.444495
2 10.882962
3 31.754358
Name: count, dtype: float64
正如我们可以看到的,组 2 的用户比组 1 的用户有更多的环行程。第三组(EMT 雇主)的环形行程也有令人惊讶的 31%,这可能表明大约 31%的“行程”是为了维护电动自行车,而不仅仅是为了移动车队!
如果我们看看 user_type=1 最频繁的旅行
并且用户类型=2
我们可以对环形旅行得出同样的结论。
恶意软件分类中的计算机视觉技术分析
恶意软件分类中使用的计算机视觉技术介绍
任何故意设计来对其所在系统造成损害的软件。主要类型有蠕虫、特洛伊木马和广告软件。如今,每年大约产生 350,000 个样本,这对于反病毒公司来说越来越困难,因为只有 50%的新恶意软件被报告,而在这 50%中,只有 20%能被现有的反病毒软件检测到。因此,快速计算会告诉 90%的新恶意软件不会被反病毒软件检测到。
用于对恶意软件进行分类的一些传统方法有
- 沙盒检测::在这里,任何可疑软件都在虚拟环境中运行,在虚拟环境中,它的行为可以被监控,并且基于它的行为,它可以反病毒,它将判断该软件是否是恶意的。但是这种方法可以被恶意软件绕过,恶意软件是如此之大以至于不能在虚拟环境中处理,恶意软件文件以不可识别的模糊文件格式保存,等等。沙盒检测属于基于行为的恶意软件检测。
- 基于签名的检测:这里反病毒公司为恶意软件创建一个签名,并在其数据库中更新它。因此,反病毒软件会将它扫描的软件的签名与反病毒公司数据库中的签名进行比较。如上所述,现在的问题是每天大约有 350000 个恶意软件被制造出来,公司很难为每个恶意软件创建签名。
来源:Reddit
所以现在反病毒公司正在使用深度学习技术来对抗恶意软件。在这里,我们将深入探究基于 CNN 的分类。
当归类为灰度图像时,特定类别的恶意软件图像的相似性首先见于恶意软件图像:可视化和自动分类。在本文中,他们展示了特洛伊病毒的样子。
。文本部分包含要执行的代码和。靠近结尾的文本部分是全黑的,表示结尾零填充。的。数据部分包含未初始化的代码和。rsrc 包含模块的所有资源,就像应用程序可能使用的图标一样。
上面的图片来自论文使用图像表示法进行恶意软件分类,他们展示了不同家族的恶意软件图片,对于一个家族,我们可以在图片中看到相似性。
在论文中,针对恶意软件分类的卷积神经网络展示了常见恶意软件家族的图片,如 Rammit、Gatak(木马版本)等
结果已发布
- 因此,论文恶意软件图像:可视化和自动分类,他们使用 GIST 来计算纹理特征,并使用欧氏距离的 K-最近邻来对它们进行分类。因此,本文的主旨是利用 Gabor 滤波器对图像进行小波分解。Gabor 滤波器是一种线性滤波器,主要在分析区域的特定方向上分析图像中的频率内容。它们用于边缘检测、纹理分析和特征提取。他们使用了来自 25 个家族的 9458 个恶意软件,准确率达到 98%
- 在论文用于恶意软件分类的卷积神经网络中,他们训练了三个模型。
- 1.CNN 1C 1D 频道、CNN 1C 2D 频道和 CNN 3C 2D 频道。CNN 1C 1D 由 NxN 像素(N=32)的输入层、卷积层(64 个大小为 11×11 的过滤图)、最大池层、密集连接层(4096 个神经元)、9 个神经元的输出层组成。结果是准确度:0.9857 和交叉熵:0.0968
- 2.CNN 1C 2D 由 NxN 像素(N=32)的输入层、卷积层(64 个大小为 3×3 的过滤图)、最大池层、卷积层(128 个大小为 3×3 的过滤图)、最大池层、密集连接层(512 个神经元)、输出层组成。9 个神经元。结果是准确度:0.9976 和交叉熵:0.0231
- 3.CNN 3C 2D 由 NxN 像素(N=32)的输入层、卷积层(64 个大小为 3×3 的过滤图)、最大池层、卷积层(128 个大小为 3×3 的过滤图)、最大池层、卷积层(256 个大小为 3×3 的过滤图)、最大池层、密集连接层(1024 个神经元)、密集连接层(512 个神经元)、输出层组成。9 个神经元。结果是准确度:0.9938 和交叉熵:0.0257
- 在论文使用图像表示的恶意软件分类中,他们使用了 2 个模型,一个 CNN 模型有 4 层(2 个卷积层和 2 个密集层)和一个 Resnet18。正常 CNN 的准确率为 95.24%,Resnet 的准确率为 98.206 %。
结论
如你所见,这些论文发布的结果显示,大约 95–98%的恶意软件被检测到,这表明计算机视觉技术比传统方法好得多。使用图像表示的恶意软件分类也显示了一个使用 CNN 和单词嵌入的模型,准确率约为 99.5%。
不仅是计算机视觉,一些研究人员也发表了一篇论文,使用了强化学习、自然语言处理等。
这些天来,攻击者也开始使用自动化,反病毒很难用过时的方法来保护我们的系统。
麦肯锡全球研究所的研究估计,人工智能和机器学习等技术驱动的自动化可以在未来半个世纪内以每年 0.8%至 1.4%的速度提高生产率。麦肯锡还估计,9 万亿至 21 万亿美元的全球经济价值创造取决于网络安全环境的稳健性。
深度学习能够实现非常好的准确性,而且与传统方法相比,它占用的硬件更少。所以也许这就是未来。
我希望这是一个很好的介绍,并将很快张贴我在这一领域的想法
再见,soon✌
参考:
[1] Ajay Singh ,使用图像表示的恶意软件分类 (2017),关键基础设施网络安全和网络防御跨学科中心
[2]丹尼尔·吉尔伯特,用于恶意软件分类的卷积神经网络 (2016), IEEE
[3] L. Nataraj,S. Karthikeyan,G. Jacob,B. S. Manjunath 恶意软件图像:可视化和自动分类 (2011), Vison 研究实验室
https://techbeacon . com/security/anti virus-dead-how-ai-machine-learning-will-drive-cyber security
务必查看我的个人资料:
https://github.com/rajanarasimhan
利用人均数据分析新冠肺炎
媒体报道通常不提供每百万居民的病例数,这改变了一切!
我们每天都被关于新冠肺炎病毒传播的表格、图表和文章轰炸;下表是一个典型的例子。
然而,简单地显示感染和死亡的总数并不能给我们提供太多的信息,因为我们是在比较完全不同的人群规模。中国人口是法国人口的 20 多倍。
如果我们想比较不同国家的行动,我们需要按照每百万居民的病例数来考虑疾病的传播。这个事实似乎是显而易见的,但是,它几乎从来没有被媒体或官方组织所应用。
此外,由于 80%以上的死者年龄在 65 岁以上,我们需要更进一步,检查每百万 65 岁以上居民的病例/死亡人数。当比较不同的国家,或者在同一个城市的不同社区时,这是正确的。
值得注意的是,还有其他一些问题难以彻底理解新冠肺炎传播。主要是,我们在获取可靠数据方面存在许多问题:
- 许多病例是无症状的,所以即使我们能检测所有的病人,我们也不能得到真实病例的可靠数字。
- 许多国家未能对所有患者进行检测,并且在获得结果方面存在滞后。因此,这些结果应追溯报告。
- 死亡人数没有同等统计,因为许多国家,如英国,只报告在医院的死亡人数
由于各国之间的数据质量差异很大,为了进一步改进我们的比较,有必要:
- 对一段时间内的数据进行平均,以减少数据中的噪音
- 在相同的时间基础上绘制数据,例如时间零点是检测到 100 个病例的时间。
我现在描述我用一些简单的数据工具得到的结果。数据最后更新于 2020 年 4 月 20 日;但是,您可以运行下面提到的笔记本来获取更新的图表。
图 1:每百万居民的平均死亡人数
最后一天 2020 年 4 月 20 日
我被图 1 的图表震惊了,它显示了 5 天内平均每天的死亡人数。比利时的死亡率最高,但你甚至不会在当地媒体上读到它。您可以访问https://www . statista . com/statistics/1104709/coronavirus-deaths-world wide-per-million-residents/来确认我的结果
图 2:65 岁以上每百万居民的平均死亡人数
最后一天 2020 年 4 月 20 日
图 2 显示了与图 1 相同的数据;然而,它只考虑 65 岁以上的人口。在这种情况下,我们可以看到意大利的老年人死亡率比西班牙低,尽管他们的人口中老年人的比例更高——正如媒体几周前试图解释意大利的死亡率一样。
图 3:每百万居民累计死亡人数
最后一天 2020 年 4 月 20 日
在图 3 中,我们可以看到比利时仍然处于糟糕的状态,尽管降低了增长率。
图 4:比利时:平均每日死亡/确诊病例数
比利时
在图 4 中,我们重点关注比利时的确诊病例和死亡病例。我们看到每天的死亡人数已经停止增加。请注意,这些图表是基于 5 天的移动平均线。
图 5:圣保罗市:每 10 万居民的死亡人数
在我看来,最重要的分析是在地方层面。
图 5 是巴西圣保罗市的街区地图,显示了每 10 万居民的死亡人数。这里我们可以看到,在地方一级,受影响的地区有很大的可变性。如果邻近地区的死亡率与其他因素相关,如卫生设施的可及性、人口密度和收入水平,我们可以更好地理解疾病传播的原因以及如何遏制它。
不幸的是,这张图表所依据的详细数据并未公开。它是向 Sistema eletronico de Informa ao cidado e-SIC 申请的,并且只给了我一次。
您可以通过访问https://rubens mau . github . io/Sao Paulo _ deaths _ neighborhood . html来访问此交互式图表
结论
我希望这篇文章能帮助媒体和其他组织理解报道每百万居民病例的必要性,从而提高他们的报道质量。此外,这种类型的分析可能对地方和国家一级的未来政策具有重要价值。不仅要提供图像,还要提供这些报告所依据的数据,这一点非常重要。
您可以访问生成这些图表的两个笔记本。它们可以通过 Kaggle 访问,您可以在线运行它们(参见下面的说明)并访问数据。不需要编程技能。
https://www.kaggle.com/rubensmau/covid-19-deaths-per-capita
https://www . ka ggle . com/rubens mau/新冠肺炎圣保罗城市数据
如何运行 KAGGLE 笔记本
- 在https://www.kaggle.com/account/login免费注册
- 点击以上链接
- 点击页面右上角的“复制和编辑”按钮
- 点击“全部运行”运行笔记本
- 您可以通过单击页面右侧的数据选项卡来访问数据。
使用 https://matplotlib.org 的和 https://altair-viz.github.io/的制作的图表
美国数据科学和 ML 职位空缺分析:EDA
在这篇文章中,我们将探索美国与数据科学和机器学习相关的工作。
简介:
对于那些在美国积极寻找工作的人来说,这篇文章是一个很好的概述。不幸的是,本文探讨的数据是基于 2018 年 8 月。但我认为,为特定角色招聘员工的公司不会随着时间的推移而发生显著变化。为了帮助求职者,我决定对这个数据集进行探索性数据分析。数据集可以从的这里的进入。
Trent Szmolnik 在 Unsplash 上拍摄的照片
在这篇文章中,我分析了每个州、公司和所需技能的主要职位(数据科学家、数据工程师、机器学习工程师、数据分析师等)的职位空缺数量。此外,我根据四个主要角色对数据集进行了划分,并分析了每个州中这些特定工作的职位数量。此外,根据这些工作的工作描述,我分析了对于特定的角色,哪些编程语言应该是最受关注的。
1-导入相关库:
2-数据清理和处理:
首先,我们将读取数据集并查看它的外观。仔细观察数据集后,它的列“positon,company,description”的 Nan 值很少,只有 11 个,所以可以删除这些行。对于评论栏,它有大量遗漏的评论,大多是针对初创公司的。这意味着这些公司刚刚成立,因此用 0 替换这些缺失值是合理的。
df=pd.read_csv("alldata.csv")
df.head()
df[df["reviews"].isnull()].head()
print(df.company.isnull().value_counts())
print(df.reviews.isnull().value_counts())
print(df.location.isnull().value_counts())
print(df.reviews.isnull().value_counts())
同样对于 location 列,我提取了一个表示美国各州的新列。在清理数据集并遵循下面给出的步骤后,我们得到了这些数据。
已清理数据
2-数据可视化:
职位空缺最多的公司:
在这一部分,我根据美国各州 2018 年 8 月的数据,筛选出了职位空缺数量最多的公司。
我们可以看到,华盛顿拥有亚马逊和微软等公司提供的最多职位空缺。而谷歌的大部分职位空缺都在山景城。谷歌在其他州也有职位空缺,但在这个图中,我显示了某个特定公司的最大职位空缺数。
空缺人数最多的职业:
在本部分中,我们可以看到空缺职位数量最多的是数据科学家职位,占总职位数的 60%。
此外,如果我们将这些职位的职位空缺与美国不同的州分开,我们可以看到纽约的数据科学家和分析师职位空缺数量最多。注意:这里我只显示了空缺数量最多的职位(前 20 名)
在下一节中,我们将把工作分为四类——数据科学家、数据工程师、机器学习工程师、数据分析师,我们将根据公司、地点和所需技能对他们进行单独分析。
数据科学家:
在这一部分,我们将首先筛选出与数据科学家相关的所有工作,如下所示:
Data_scientists=df[(df["position"]=='Data Scientist')|(df["position"]=='Senior Data Scientist')|(df["position"]=='Lead Data Scientist')|(df["position"]=='Sr. Data Scientist')]
Data_scientists.head()
df5=Data_scientists.groupby(by="city").size().reset_index(name="count").sort_values(by="count",ascending=False)
df5.head(10)
plt.figure(figsize=(10,7))
plt.yticks(size=20)
sb.barplot(y="city",x="count",data=df5.head(20))
plt.title("Data Scientist Jobs",size=20)
plt.xticks(size=15)
我们可以推断,纽约和旧金山的数据科学家职位空缺最多。接下来,我们将绘制单词 cloud 来描述为数据科学家发布的工作,并进一步评估这些工作所需的技能,主要是所需的编程语言。
首先,我们将创建一个函数,将这些描述的所有单词合并到一个列表中。然后这个列表将用于制作单词云图
我们可以看到,机器学习是数据科学岗位最需要的技能之一。现在,我们将发现大多数招聘职位要求的编程语言类型如下:
我们可以看到,几乎 90%的职位空缺都将 python 和 ML 列为最主要的技能,其次是 SQL,这在 70%的职位发布中出现。
机器学习工程师:
在本节中,我们将首先筛选出与机器学习工程师相关的所有工作,如下所示:
ML_engineer=df[(df["position"]=='Machine Learning Engineer')]ML_engineer.head()
我们可以看到大部分的 ML 工程师工作在旧金山和波士顿,其次是纽约和西雅图,与此形成对比的是数据科学工作主要在纽约。
我们可以看到大多数人工智能工程师工作需要的技能的区别,如计算机科学、人工智能、人工智能、算法和深度学习。这就是数据科学家不同于机器学习工程师的地方。
就所需技能而言,ML 和 python 是最主要的技能。我们不需要任何 ML 工程师职位的 SQL,但需要更深入的 ML 知识,因为它出现在所有的招聘信息中。
数据工程师:
在本节中,我们将首先筛选出所有与数据工程职位相关的工作,如下所示:
Data_engineer=df[(df["position"]=='Data Engineer')]Data_engineer.head()
我们可以看到,大多数数据工程工作都在纽约和旧金山,其次是波士顿。
对于数据工程师的招聘信息,我们可以看到出现频率最高的词是大数据、数据、开发、经验等。这意味着我们不需要任何机器学习知识来从事数据工程工作。
对于数据工程工作,我们可以推断 Python、SQL 和 Java 是最主要的编程语言。对这些工作略知一二就足够了。
数据分析师:
在这一部分,我们将筛选出与数据分析师职位相关的职位发布,如下所示:
data_analyst=df[(df["position"]=='Data Analyst')]
data_analyst.head()
我们可以推断,大多数数据分析师的工作都在纽约和剑桥提供。由于缺乏数据,这一数字相当小,但这仍然为 2018 年 8 月的职位发布提供了一个基本概念。
我们可以看到出现频率最高的关键词是——团队、SQL、经验、技能、业务。因此,我们可以得出结论,数据分析师的工作不需要太多的编程和机器学习技能,而是更注重团队管理和业务技能。
对于数据分析师职位,我们可以得出结论,最主要的语言是 SQL,其次是 python。ML 知识不是主要要求。
结论:
我们可以得出结论,美国的大部分职位空缺都是数据科学家的职位,而且大多在纽约和旧金山。在顶尖技能中,python 和机器学习知识是数据科学家和机器学习工程师最重要的要求。另一方面,SQL 是数据工程师和数据分析师职位最需要的编程语言。
完整代码可在这里获得。
参考资料:
https://www . ka ggle . com/sl 6149/data-scientist-job-market-in-the-us
感谢您的阅读!!!!
如果你喜欢我的工作并想支持我:
支持我的最好方式就是跟随我上 中级 。
2-在LinkedIn上关注我。
英超数据分析
“在英超联赛中很难做出预测,因为不可预测的事情会发生,我很清楚这一点:我以一种疯狂的方式赢得了冠军,却意外地失去了一个。”——乔·哈特
英超是迄今为止世界上最有趣的联赛之一。他们有一些最好的经理、球员和球迷!但是,使它真正有趣的是纯粹的不可预测性。有 6 支同样令人惊叹的球队,每个赛季都有不同的球队捧起奖杯。不仅如此,联盟还见证了前 6 名以外球队的胜利。所以,让我们来分析一些例子。
你可以在这里找到整个 jupyter 笔记本
数据收集
对于数据集,可以参考这个 Kaggle 链接。它包含了从 2015/16 赛季到 2019/20 赛季在英超比赛的每一名球员的详细信息。对于每个球员,有 54 个属性,其中一些是— 名字,进球,助攻,创造的重大机会,拦截,盖帽,清道夫解围,出拳,等。
现在,我们不会在此数据集中寻找 NaN 值并消除它们,因为 NaN 值有其用途。例如,扑救、清道夫解围、出拳、等属性是守门员特有的。因此,前锋的这些属性的值将为 NaN。
接下来,我们将使用 read_csv 方法将每个季节的数据读取到单独的数据帧中。然后,我们用。concat()方法。
莱斯特城
莱斯特城最终在 2015/16 赛季赢得了冠军,当时几乎没有人预料到这一点。他们在 2015/16 赛季开始时夺冠的赔率是 5000/1 。从这个数字来看,莱斯特城赢得联赛冠军的几率比圣雄甘地还活着的几率还要低!
然而,尽管所有人都相信,它还是发生了。让我们看看一些数字,评估一下他们是如何做到这一点的。
但是,在此之前,我认为了解球员是很重要的,因为他们的名字会在文章中反复出现。
现在,让我们从查看数据集及其属性开始分析。
开始分析的最好方法是查看最明显的属性——进球和助攻。
让我们从联赛最佳射手开始。
现在,类似地,让我们看看顶级组织者(助攻提供者)
从这两份名单中,我们可以看到莱斯特城队的两个名字——里亚德·马赫雷斯和杰米·瓦尔迪。
现在,我们可以看到里亚德·马赫雷斯在最佳得分手和最佳组织者名单中。显然,他是莱斯特城获胜的基础。从更大的角度来看,让我们看看进球情况(助攻+进球)。
杰米·瓦尔迪有 30 个进球,其次是里亚德·马赫雷斯有 28 个。这揭示了莱斯特城赢得英超冠军的一大原因。
但是,仅仅进球并不能为你赢得冠军。例如,在同一个赛季,曼城取得了惊人的 71 个进球,而莱斯特为 68 个,但最终以第四名结束。显然,还有更多。
让我们来看看一些数字作为辩护。我们将从另一个野兽般的球员开始——恩戈洛·坎特
从上面的输出可以看出,Kanté是
- 拦截次数联盟第一
- 铲球联赛第一
- 第二名在决斗中获胜
这是防守型中场的一些令人难以置信的数据。他的贡献由此可见一斑。
现在,让我们来看看防守队员
我们可以只看干净的床单,但它可能不会告诉我们整个故事。虽然更多的零失球确实意味着强大的防守表现,但它不会给你其他比赛中有多少失球的细节。比赛中失球多反映了防守差。
因此,我把“每场比赛的失球数”作为我的第一统计数据。但是,重要的是要确保后卫有足够的出场机会。例如,一个有 2 次出场 0 次失球的后卫将会有一个很大的“每场失球数”。不过这个后卫还没有打够比赛,不在考虑范围内。
上面的情节揭示了这些后卫的恒星性能。气泡的宽度表示干净纸张的数量。所以,我们可以看到克里斯蒂安·福赫斯和罗伯特·胡思在莱切斯特城的防守中起到了至关重要的作用,因为他们场均失球更少,并且保持了更多的零失球。
注意耶稣·纳瓦斯是如何丢了很少的球,却没有很多不失球记录的。尽管如此,这仍然是很好的防守。
现在,我们来简单看看莱斯特城的门将卡斯帕·舒梅切尔
我们可以看到他有 38 次出场。让我们把他和其他有着相似外貌的守门员进行比较。
很明显,舒梅切尔比其他人更胜一筹。虽然乌戈·洛里斯少丢了 2 个球,但他也少打了一场比赛。此外,除了少了一次出场,他也少了两次不失球。
因此,我们可以得出这样的结论:主教练克劳迪奥·拉涅利,凭借他令人难以置信的平衡和稳定的阵容,给了莱切斯特城他们的首个英超冠军,战胜了所有的困难!
利物浦的冠军之路!
任何英超球迷都可以证明自从尤尔根·克洛普到来后利物浦的表现有所改善。他们慢慢地,但是持续地进步,并且连续赢得了冠军联赛和英超联赛。让我们看看历年的一些数字,分析一下他们 2019/20 赛季的英超夺冠之路。
平衡攻击
利物浦队显然是进攻方。在克洛普的领导下,他们将压力提升到了一个不同的水平。像萨迪奥·马内、默罕默德·萨拉赫和罗伯托·菲尔米诺这样出色的攻击手在进球和助攻方面贡献巨大。但是,据说他们真正的冠军机会是在他们开始攻击‘聪明’之后才开始的。让我们利用我们掌握的数据来看看发生了什么变化。
我们将分析利物浦的“前锋 3”的数据,他们是进球的主要贡献者。
我们可以清楚地看到,进球数量在逐渐下降。仅仅两个赛季,他们的进球数就从 57 个增加到 46 个。然而,他们在这两年中上升了 3 个位置赢得了冠军。
据说这是因为利物浦在 2017/18 赛季后选择采用的平衡方法。
防御力量
2018 年 1 月,利物浦以 7500 万英镑的价格签下了维吉尔·范迪克,这使他成为当时世界上最昂贵的后卫。利物浦最近的成功很大一部分与他的转会有关,因为据说他极大地改变了利物浦的防守。与他一起,利物浦以阿利松·贝克尔的名义购买了一名门将,他最终结束了利物浦多年来的门将困境。让我们来看看分析他们表现的一些数字
利物浦的守门员
2016/17 — 洛里斯·卡里乌斯西蒙·米尼奥莱
2017/18 — 洛里斯·卡里乌斯西蒙·米尼奥莱
2018/19 — 阿利松·贝克尔
2019/20 — 阿利松·贝克尔阿德里安
上面的泡泡剧情讲述了《goal》中阿里森冲击的故事。在利物浦的第一个赛季,他有 21 场比赛没有失球,只丢了 22 个球!他也因此获得了金手套奖。
来到他的第二个赛季,他在 29 次出场中丢了 23 个球。阿德里安当守门员时,其余的球都被丢了。下面将进一步解释。
范迪克的进攻、传球、进球也在 2018 年加盟利物浦后有了明显的提升。然而,这并没有导致他的防守表现下降,他们始终保持一致。
从下面的数字可以明显看出 2017/18 赛季下半段本身(签下范迪克后)防守数字的提升。下半赛季的守门员是洛里斯·卡里乌斯,他比守门员西蒙·米尼奥莱少丢 10 个球,多 3 场不失球。
至于 2019/20 赛季,阿里森受伤了一段时间,利物浦的第二选择阿德里安不得不顶替他。这是大量失球的主要原因。每个人都会同意,在球门阿德里安是没有阿里森有效。事实上,在 2020 年 10 月 4 日,利物浦 2 比 7 输给了阿斯顿维拉。那天守门的是阿德里安。
结论
莱斯特城和利物浦赢得联赛冠军看起来令人惊讶,但对单个球员表现的分析让故事变得清晰。莱斯特城队在场上的每个位置都有强大的球员,他们的状态令人难以置信,他们的人数明显高于其他球队,而利物浦队在进攻心理上的变化以及他们新签下的维吉尔·范·迪克和阿利松·贝克尔慢慢地扭转了对他们有利的趋势。
问题
谁在所有 5 个赛季中进球和助攻数最高?
目标
助攻
Ans:最高得分手— 沙治·奥阿古路(102 球),最高助攻— 凯文·德布劳内(65 球)
2)哪个赛季的进球数最高,或者哪个赛季的得分最高?
Ans:2016/17 赛季进球数最高(983 球)
参考
- Kaggle 数据集—https://www . ka ggle . com/krishanthbarkav/English-premier-league EPL-player-statistics
- Jovian.ml 【零到熊猫】课程—https://jovian . ml/learn/data-analysis-with-python-零到熊猫
- NumPy 文档——https://numpy.org/devdocs/user/quickstart.html
- Seaborn 图书馆信息——https://seaborn.pydata.org/
就这样,我们到了文章的结尾。非常感谢你的阅读,我真诚地希望你喜欢它!请随时留下反馈或使用下面的链接与我联系。
联系我
推特 | Instagram | 脸书 | LinkedIn
美国历史上总统演讲的分析
自然语言处理从一开始就引起了我的兴趣。我第一次听说它是在一次基于单词模式的作者预测演示会上。后来用几十年的歌词解释给我听。所以我也试图从历史的角度来使用它。我在哪里可以得到大量的数据?总统:他们喜欢交谈!或者至少大部分是这样。所以我创建了一个关于美国历史上总统演讲的 NLP 项目。它包括了从乔治·华盛顿 1789 年的第一次就职典礼到 2020 年 4 月底关于冠状病毒的演讲的所有 44 位总统。是的,我说过像格罗弗·克利夫兰这样的 44 位总统有两个独立的任期。在你阅读的时候,给你一个合理的警告:我主修美国研究,教了 13 年历史。所以,不要介意我在介绍数据科学知识的同时,也介绍一些总统知识。尽情享受吧!
言语组织
我的大部分演讲都是从弗吉尼亚大学米勒中心获得的。他们收集的演讲和其他原始资料被认为是一流的,甚至被哈佛的数据库引用。当我开始整理和分析我的数据时,我意识到一些总统应该有比这本集子里更多的演讲。我可以从 NLTK 的语料库中添加杜鲁门和艾森豪威尔遗漏的国情咨文演讲来解决这个问题。这本文集里的每一位总统的演讲都已经被米勒中心收藏了。我的分析总共包括 1018 篇演讲,大约 2380 万字。我的数学方面确实需要看一些数字和统计数据。最短的演讲来自乔治·华盛顿的第二次就职演说,有 787 个单词。另一方面,最长的演讲是哈里·杜鲁门在 1946 年发表的国情咨文,演讲人数接近 17 万。他不得不讨论诸如战后经济、保护退伍军人、创建联合国、共产主义问题等历史性话题……而这还不到前半部分!
这些数据,每一个都是完整的演讲,有可以理解的不对称性。我可以从其他来源检索其他演讲,但这将使它极度偏向现代。像收音机和电视这样的技术导致了更多的演讲而不是写信。数据集中已经有这样的例子,包括对全国的电视讲话和罗斯福的炉边谈话。
我用颜色标记了我的条形图,来代表任职超过一届的总统和任职不超过四届的总统。林登·约翰逊(Lyndon Johnson)有很多历史事件要处理,比如民权法案和越南战争。另一方面,只有一篇演讲稿的两位总统在任期几个月后去世了。威廉·亨利·哈里森死得很特别,因为他在暴风雪中没穿外套就发表了两个小时的就职演说。
主题建模
我首先把每一篇演讲分开,检查所有单词的出现频率。在这里,我可以列出自己的停用词列表,为计数矢量化做准备。有些词我发现并不奇怪,比如“united”、“states”和“america”。一个让我措手不及但有意义的词是“谢谢”和“你”。想想有多少演讲是以这句话开始的,或者是在后来感谢人们的成就。另外两个值得注意的词是“掌声”和“文字记录”。这只是展示了演讲是如何被历史记录的,以及总统和他们的演讲稿撰写人是如何在演讲中做笔记的。
我用最大 df 为 40%的计数矢量化处理了数据。这使得许多随机的主题可以从我的主题建模中过滤掉。另一方面,我将 NLTK 的停用词与我的十几个单词列表结合起来,过滤掉出现过多的单词。我决定用非负矩阵分解(NMF)来建模。我试验了各种主题建模器和矢量器。利用我的历史知识,我不喜欢任何关于 LDA 发布的东西。在 NMF,TDIF 矢量创建了不匹配的主题。它有两个基于越南战争的不同类别,但错过了我在最终结果中发现的主要主题,我将在下面讨论。我还尝试了关注多少话题。NLP 的这一部分真的很像金发女孩和三只熊。我试了 5 次,太少了。我试了 15 次,太多了。我最初运行的 10 个最终是完美的数量。
当我第一次运行它时,我开始欣赏 NLP 全部功能。前两个话题是与国内和经济事务有关的词。好吧,有道理。然后我看了第 3 题。我意识到所有的词语都与奴隶制和内战前的妥协有关。我欣喜若狂。NMF 应该更适合短文本文档。然而,它的好处却大放异彩。NMF 通过直接分解术语-文档矩阵来学习主题,它降低维度来找到演讲的主要主题。在这里,它听取了所有的演讲,并意识到奴隶制是一个不仅笼罩了我们国家几十年导致内战的话题,而且在废除奴隶制几十年后仍是总统们讨论的话题。
我开始寻找与所有 10 个主题的相关性。主题建模让我看到了一些我不会想到的主题,比如公务员编制。我过去常常用大约 20 分钟来教这个,但是这表明老师应该更加重视这个。此外,还有一个我最喜欢的题目叫做“鼓励”。有些总统的竞选口号是积极的,这使他们成为总统,但这种情况已经持续了多年。这个话题在 20 世纪 50 年代随着电视的出现而出现,并证明电视对总统职位的塑造可能超过任何发明。有几个话题,不管我怎么修修补补,我都惊讶地从未作为主要话题出现过。我找不到与两次世界大战或新修正案的产生有关的词汇或话题。
我是一名视觉学习者,创建热图教会了我更多。总结每个主题的单词,你可以跨时间观察它们。
doc_topic_nmf = pd.DataFrame(doc_topic.round(3),
index =df.Year.astype(int),
columns = [“Domestic”,”Economy1", “Slavery”,”Economy2",”Mid_1800s_Politics”,
“Encouragement”,”Civil_Service”, “Cold_War”,”20th_Cent_Politics”, “Panama_Canal”])
dtn = doc_topic_nmf.groupby(doc_topic_nmf.index).sum()dtn.reset_index(level = 0, inplace = True)
graph_topics = dtn.groupby(dtn.Year // 10 * 10).sum()
graph_topics.drop([‘Year’], axis=1, inplace = True)
plt.figure(figsize = (25, 6))
sns.heatmap(graph_topics.T, annot=False, cbar=True, cmap=”Blues”)
plt.xlabel(‘Year’, fontsize = 20)
plt.xticks(fontsize = 14)
plt.yticks(fontsize = 16)
plt.title(‘Speech Topics Over The Years\n’, fontsize=25)
下图中最暗的方框属于 20 世纪 60 年代的冷战。这个时期无论是好的(太空竞赛)还是坏的(古巴导弹危机)都在许多方面包围着美国。19 世纪政治中的黑暗时期展示了这是一个不应该被缩短的时期。围绕国家银行的政治争论已持续多年。此外,美墨战争以及天定命运思想塑造了我们国家的形状和土地。
情感分析
我做的第二个主要分析是情绪分析。我小心翼翼地研究这个问题,因为我知道我的数据是预先写好的演讲稿。有一半的时间,它们不是由总统本人写的,而是由一组演讲稿撰写人写的。如果你想要真实的感受,去 YouTube 上听 LBJ 的磁带。或者你在推特上关注唐纳德·特朗普。然而,最终,我看到了与我们许多总统相匹配的情感结果。我利用了 NLTK 的 VADER 情感强度分析器和它的基本情感分析器。这些工具可以让你看到消极和积极的评价,但我决定关注他们的积极得分。在这两个方面,分数都很低,这是意料之中的。这些演讲是基于内容的,这是一件好事。即使当一位总统传达一些负面的东西,比如 20 世纪 50 年代的共产主义,情绪分析也不会注意到这一点。另一方面,看看著名的葛底斯堡演说的优美语言:
八十七年前,我们的先辈在这个大陆上创建了一个新国家,它孕育于自由之中,奉行人人生而平等的原则
也许现在你正在热情而模糊地读着那句经典的台词。是的,像“新”和“相等”这样的词会得到分数。但总的来说,这涉及到许多中性语言,当串在一起时,有着非常不同的含义。但这就是情绪分析的神奇之处。它能捕捉到细微的差别。此外,VADER 是专门为处理特定领域语言而设计的。
为了分解每个总统的情绪,我创建了以下函数:
def sentiment_analysis_graph(president):
filter1 = df.President.str.contains(president)
func_df = df.loc[filter1]
text = ‘’.join(str(func_df.Split[:]))
score = SentimentIntensityAnalyzer().polarity_scores(text)
return score[‘pos’]
然后我把他们的积极得分加到我的数据框中,这样我就可以用表格来描绘它了。如下图所示,德怀特·艾森豪威尔拥有最高的乐观情绪。这可以用 20 世纪 50 年代的繁荣、文化和良好的经济来解释。在过去的半个世纪里,这一数字总体上较高,这与“鼓励”的主题建模相关。令我惊讶的是,在大萧条、越南战争或其他战争的艰难时期,人们的积极性并没有降低。在我的负面情绪分析中,那个点也没有见顶。我想这又回到了美国总统在艰难时期使用的鼓励词汇,集会呐喊和安慰的语言。
总统积极情绪
有一个更好的方法来可视化这些信息。由于这些数值非常相似,所以条形图实际上并不适用于比较多位总统。很容易把艾森豪威尔看作是最积极的,或者把安德鲁·约翰逊看作是最不积极的,但是有太多的总统之间存在着千分之一的差异。然而,树形图显示了从最积极到最不积极的明显转变。为了创建树形图,我没有编写任何 Python 代码。我根据总统的情绪得分创建了一个 CSV 文件。然后我把这个和我的主要演讲一起上传到 Tableau。我喜欢这个可视化工具如何帮助组织数据,是交互式的,并让我对特性进行颜色编码。
我想指出的是,有两位总统排在了最积极的前十位。在我的美国历史课堂上,约翰·亚当斯被我戏称为“反弹总统”。他追随乔治·华盛顿,但却永远无法达到他的水平。这再加上 XYZ 事件,使他成为唯一一位只任职一届的开国元勋。这张树状图表明他是一位伟大的演说家。很久以后,在我们的历史上,你有吉米·卡特,另一个挣扎着当总统的人。我曾经听一位非常保守的大学教授说,卡特是最适合当总统的人。他的演讲体现了那种善意。
总统积极性树形图
然而右下角是最不积极的总统。使用内容知识,这与历史相关。安德鲁·约翰逊是第一个被弹劾的总统。他与国会激进的共和党人相处不好。他们通过了《任期法案》,该法案要求参议院批准任何文职官员的免职,但他很快就违反了该法案。这些关于重建计划的争论和分歧导致了较低的情绪得分。詹姆斯·布坎南和约翰·泰勒都被认为是最糟糕的总统。你认为唐纳德·川普治下的员工留任很糟糕……约翰·泰勒的整个内阁在他当选总统几个月后就辞职了!威廉·塔夫特不想当总统。塔夫脱从来不想处于唯一的权力位置。然而,他的妻子和泰迪·罗斯福对他有政治野心,这让他顺从了。这些数据显示了他的不快和他对最终最高法院首席大法官职位的渴望。
单词云
我做的最后一个 NLP 分析是比较不同总统使用的热门词汇。我使用了单词云来突出显示使用频率较高的单词。我不打算对所有 44 位总统都这样做,但我选择了华盛顿和林肯这样明显的人以及一些个人最喜欢的人。这些单词云中有许多词汇提到了政府及其特征,如参议院或宪法。我也观察了两位我个人认为不具备演讲技巧的总统。为了保持公正,我不想指名这些额外的主席。果然,数据显示个人观点并不总是正确的,因为其中一个人有一个词云,可以与我选择的“伟人”相媲美。另一个……无话可说。
告别演说
我希望你喜欢阅读我的项目,就像我喜欢创建它一样。我试图在整个项目中保持平衡。我没有包括基于一个政党的比较或分组演讲的分析,主要有两个原因。第一,我不想增加分裂文化。其次,共和党和民主党并非一直都在。像联邦党人这样的政党只存在了这个国家的前 50 年。我不想在计算中将老党派归入“其他”一类,因为这些党派的观点截然不同。我在一个我的政治信仰与我所教的家庭不匹配的地区教了很多年的历史。对学生来说,我最大的收获就是试图让他们看到事物的两面性。如果你有兴趣查看这个项目的代码和资料,请查看我的 Github:
[## nicolesemerano/Metis-Project-4-总统演讲-NLP
此存储库仍在更新中。现在,看看我的代码,关于我使用…
github.com](https://github.com/nicolesemerano/Metis-Project-4-Presidential-Speeches-NLP)
我在 https://nicolesemerano.github.io/还有其他作品。
我把乔治·华盛顿在他的告别演说中的想法留给你们。他对自己总统任期的看法与我对这个项目的看法一致。
“我的感情不允许我中止深深的感谢……因为我从那时起就享受到了机会,通过忠诚和坚持不懈的服务来表达我不可侵犯的感情,尽管它的用处与我的热情不相称。”
海德拉巴的学校分析
数据科学顶点项目
来源:罗恩·汉森在 Unsplash 上拍摄的照片
作为我在 IBM 关于 Coursera.org 的应用数据科学顶点课程的一部分,我使用 FourSquare API 分析了海德拉巴的学校分布。在本文中,我将讨论我分析数据并从中提取有意义信息的方法。
[## milindkesar/Coursera_Capstone
应用数据科学。通过创建……为 milindkesar/Coursera_Capstone 开发做出贡献
github.com](https://github.com/milindkesar/Coursera_Capstone)
简介
在这篇文章中,我分析了海德拉巴市的学校分布。这对于确定学校基础设施需要发展的领域具有重要意义。
为了获取海得拉巴的学校分布,我用过 FourSquare API。
背景
每个人都有机会在学校接受优质教育,这一点至关重要。这是教育的基础。海得拉巴有很多好学校,但是它们都集中在某些街区。
海得拉巴的几个街区缺乏学校等基础设施。为城市的发展确定这些区域并为每个人提供方便的受教育机会是很重要的。
问题
政府需要发展学校基础设施,要么在这些地区建造学校,要么支持在这些地区发展私立学校,以便向所有人提供容易获得的优质教育。然而,为了做到这一点,有必要确定这些街区。所以在这篇文章中,我分析了海得拉巴的学校分布,并确定了这些街区。
当人们搬到城市并打算买房或租房居住时,这些信息也很有用,因为他们肯定希望选择一个交通便利的街区,并为他们的孩子提供许多好学校。
世卫组织会感兴趣吗?
正如我先前解释的那样,目标受众将是希望建设学校基础设施的政府机构、希望在具有良好潜力的地区建设学校的私营部门机构,以及在不同社区寻找房屋以确定哪些房屋更接近好学校的人。
数据:采集和清理
数据来源
我用漂亮的汤刮过海德拉巴的各个街区,从这个来源。
然后我用 Python 中的地理编码器库获得了这些街区的纬度和经度。
然后,我使用 FourSquare API 获取每个街区各种学校的位置,将每个街区的限制设置为 100 个,半径为 1 公里。
为了绘制 choropleth 地图,我从这个源获得了海得拉巴的 geojson 文件。
数据预处理
我已经丢弃了数据集中一些不需要的条目。存在数据重复的情况,因为一所学校可能距离每个居民区不到 1000 米,因此,同一纬度和经度可能在这两个居民区出现两次。我已经删除了此类副本,并保留了此类数据的第一份副本。
所用数据的最终形式
这是所用数据帧的前 9 个条目的图像。
每行对应于一所特定的学校及其信息,即它所属的街区、类别、名称和位置。
数据帧中共有 235 个条目。
利用这些数据,我分析了海德拉巴的学校分布。
海德拉巴的学校
可以看出,学校更多地集中在市中心,这是可以预料的。
方法论
首先,如前所述,数据已经被检索和清理。数据包括每个街区半径 1 公里内的学校,限制为 100 所。
接下来,我们通过探索学校所属的各种类别来分析数据。
在此之后,我们使用可视化的 choropleth 图以更具解释性的方式探索每个邻域中的分布。这让我们对学校的分布有了一个很好的了解。
然后,对于那些没有学校的街区,我们通过在每次迭代中增加 100 米的半径来找到到最近学校的距离,直到使用叶找到一所学校。
在获得这些精确的数据后,包括每个街区到最近学校的距离和每个街区的学校数量,我们使用 K-Means 对这些数据进行聚类。这有助于我们确定哪些地区需要改善,哪些社区拥有良好的学校设施。
最后,我们将讨论和总结哪些社区需要改善学校设施,哪些地区拥有非常好的设施。
分析
基于从关于学校的叶获得的数据,我探索了学校所属的类别。
类别
各类学校如下:
正如我们所看到的,大多数学校都“没有提到”他们的类别。有趣的是,这些学校提供从幼儿园到高中的教育。因此,发现只有少数学校只提供小学/游戏水平的教育并不奇怪,因为大学校已经涵盖了这一点。此外,“学生中心”分类学校提供从幼儿园到高中的教育。
街区学校分布
使用地图,我们可以很好地了解学校的分布。
(注:这张地图不包括塞康德拉巴德的街区,因为我只能获得 GHMC 所覆盖的那些街区的地理空间数据。)
从地图上可以清楚地看到,大多数学校都集中在市中心,特别是在 Abids、Himayath Nagar、Basheerbagh 地区附近。事实上,这些街区有很多好学校,而且彼此距离很近。
从地图上可以清楚地看出,越靠近市郊,学校的密度越低。这是意料之中的,因为市中心附近的街区比郊区更拥挤。
此外,这些都是老地区,郊区正在开发。
聚集邻居
我们现在将使用 K-Means 聚类算法根据到最近学校的距离和每个街区的学校数量将街区聚类成 3 个聚类。
这些特征为确定需要改善的街区奠定了良好的基础。
离学校最近的距离在半径 1 公里到 2 公里之间。
数据帧的前 5 个元素
接下来,我们研究不同的集群。每个集群的平均特性如下。
每个聚类的平均值
显然,纬度和经度的平均值在这种情况下没有任何意义。
很明显,标记为 0 的街区不仅有 1 公里内的学校(让我提醒你这是最近距离的起点,不能再好了)而且有许多学校可供选择,平均 18.63 。因此,就学校水平而言,这些社区有机会获得优秀的教育设施。该集群中的一些街区是 Abids、Himayath Nagar 和 Basheerbagh,所有这些街区都靠近市中心。
标记为 1 的街区在半径近 1 公里范围内也可以方便地获得良好的学校教育设施,平均每个街区大约有 3 所学校。大多数居民区都属于这一类。
标记为 2 的街区是那些需要改善的,因为到最近学校的平均距离接近2 公里,而该街区 1 公里内没有学校。这些大多出现在城市的郊区。这一地区的一些街区有阿尔瓦尔、吉代梅特拉、切拉帕里、帕坦切鲁、ECIL X 路等。****
蓝色圆圈对应标签 0,绿色圆圈对应标签 1,红色圆圈对应标签 2。
结果和讨论
我们观察了海得拉巴学校所属的各种类别,其中大多数是提供从幼儿园到 12 年级教育的普通学校。
此外,我们注意到,仅提供初级教育的学校相对较少,这是意料之中的。
接下来,我们观察了学校的分布,发现大多数学校都集中在市中心,在郊区不太密集。这一点在 Choropleth 地图上很明显。
因此,当有人想找一个交通便利、设施完善的社区时,他们应该选择离市中心更近的社区。
最后,我们将居民区分为 3 组,并观察到大多数居民区属于标签 1 的类别,即这些居民区到最近学校的平均距离为 1025 米,这些居民区平均约有 3 所学校。
这些地区包括私营部门可以在其中建学校的潜在街区,因为他们没有很多学校,但同时会有很多人住在这些街区,因为他们可以使用良好的设施。
我们还确定了需要改善的社区,这也是本次分析的目的。
这些街区的学校到最近学校的平均半径接近 2km,这是为到最近学校要素的距离设置的上限。这一地区的一些街区有阿尔瓦尔、吉代梅特拉、切拉帕里、帕坦切鲁、ECIL X 路等。
这些都是需要在学校一级改善的领域。政府应该把注意力集中在这些领域。
在我附上的 jupyter 笔记本中可以找到每一个集群的完整列表。
结论
在这项分析中,分析了海得拉巴的学校分布。此外,各社区根据其对学校设施的访问情况进行了分组。已经确定了需要改善的街区以及那些有可能开办有利可图的学校的街区。此外,还观察了各类学校。
斯里兰卡犯罪分析——第一部分(入室盗窃)
作为这个分析系列的第一篇文章,我正在分析 2010-2018 年期间斯里兰卡的整体犯罪率变化、入室盗窃和盗窃。
图片由皮克斯拜的 Gerd Altmann 提供
数据收集和清理
我从斯里兰卡警方官方网站收集了过去 8 年的犯罪数据:警方犯罪统计
由于所有的数据都是 PDF 格式,它被转换成 CSV 使用 python Tabula 库。然后,在 PDF 到 CSV 的转换过程中丢失的数据和损坏的单元格值被 excel 修复。
from tabula import convert_intoconvert_into("distribution_of_grave_crime_abstract_for_the_year_2014.pdf", "distribution_of_grave_crime_abstract_for_the_year_2014.csv", pages="all")
整体犯罪率
尽管斯里兰卡的人口增加了 7.278 %,但过去 8 年斯里兰卡的总体犯罪率下降了 36.8398%。对所有斯里兰卡公民来说,这是个好消息。向斯里兰卡人民和警察部门致敬。
犯罪总数与年度。资料来源——vit Hulan
年对警察部门犯罪。资料来源——vit Hulan
你需要担心的城市
与所有其他警察部门相比,以下城市的犯罪率高于 95 %!
- 努格戈达
- 凯拉尼亚
- 拉维尼娅山
- 拉特纳普拉
- 甘帕哈
犯罪数量与年份。资料来源——vit Hulan
你不用担心就能放松的城市
与所有其他警察部门相比,以下城市的犯罪率低于第 10 个百分点!
- 哈顿
- 坎塔莱
- 基利诺奇
- 曼库勒姆
- 穆莱蒂武
- Kankasanthure
- 马纳尔岛
犯罪数量与年份。资料来源——vit Hulan
入室盗窃
入室行窃是指强行进入他人住宅的犯罪行为,例如打破门锁或窗户,以窃取他人财物。
我想到了分析破门而入和盗窃类别,因为与其他犯罪相比,这是斯里兰卡最严重的犯罪之一。2010 年,大约 32%的犯罪 是入室盗窃。
入室盗窃犯罪数量与年份。资料来源——vit Hulan
全岛平均每年发生 13818 起入室盗窃事件。那就是每天 38 次入室抢劫!😱
如果你住在下列城市之一,可以考虑买一只高德狗
以下城市的房屋破裂数量高于百分之 90!
- 努格戈达
- 凯拉尼亚
- 甘帕哈
- 拉特纳普拉
- 拉维尼娅山
- 康提
- 阿奴拉达普拉
一年中家庭破裂的次数。资料来源——vit Hulan
好奇的人们,
你可以在这里查看 Nugegoda、Mt.Laviniya、Gampaha 和 Kelaniya 警察局管辖的城市,在这里查看康提警察局管辖的城市。
离开家后,你可能不用太担心城市
与所有其他警察部门相比,以下城市的入室盗窃事件数量低于第 15 个百分点。换句话说,下面这些城市的房子被砸的概率很低。
- 坎塔莱
- 基利诺奇
- 曼库勒姆
- 瓦武尼亚
- 哈顿
- Kankasanthure
- 穆拉蒂武
- 马纳尔岛
是的,他们中的大多数都被列入了犯罪较少的城市名单!
一年中家庭破裂的次数。资料来源——vit Hulan
我们可以开心的事情
尽管 Nugegoda 在警方犯罪排行榜上名列前茅,但今年的犯罪数量呈下降趋势!不仅如此,Nugegoda 是犯罪率较高的城市。Weldone Nugegoda 警察!👏
Nugegoda 的犯罪率梯度为负 87.34,这意味着每年大约减少 87 起犯罪。
Nugegoda 的入室盗窃次数。资料来源——vit Hulan
令人担忧的城市
所有其他警察局的犯罪率都随着时间的推移而下降,但是下列警察局的犯罪率却在上升😱
- 基利诺奇
- 穆莱蒂武
Kilinochchi 和 Mullaitivu 的破屋数量趋势。资料来源——vit Hulan
所以我决定给穆莱蒂武和基利诺奇画一条线性回归线。Mullaitivu 的正梯度为 5.53,这意味着每年大约有 6 起新的犯罪,Kilinochchi 的正梯度为 3.5,这意味着每年大约有 4 起新的犯罪。
尽管基里诺奇和穆莱蒂武的犯罪和入室盗窃数量较少,但趋势图显示,犯罪率正在随着时间的推移而上升。为了避免未来的混乱,必须在上述城市采取某种预防措施!
预防胜于治疗— 来源
该分析的信息图
斯里兰卡犯罪分析——入室盗窃。资料来源——vit Hulan
感谢您的阅读。请随意分享你对这个分析的看法。让我们在本系列的第二部分继续讨论。
编码快乐!🍻
切尔诺贝利灾难对空气污染的影响分析
使用 Python 和 Pandas 库分析切尔诺贝利数据集。
前普里皮亚季市中心废弃的摩天轮(图片由罗伯特·阿姆斯特朗发自 Pixabay )。
这个项目是由 Aakash N. S .主讲,Jovian.ml 主办的课程用 Python 进行数据分析:从零到熊猫的一部分。
使用的完整笔记本和数据集可以在GitHub或者 威风凛凛中查看。
语境
切尔诺贝利灾难始于 1986 年 4 月 26 日,当时切尔诺贝利核电站反应堆着火,持续了 10 天,导致前所未有的放射性物质从核反应堆中释放出来。该发电厂距离基辅(乌克兰)100 公里,但这起事故的影响远远超出了乌克兰的国界。
受影响最严重的三个国家是白俄罗斯、俄罗斯联邦和乌克兰,但事故的后果并不限于这些领土。由于放射性物质大量进入大气,其他几个欧洲国家也受到了影响。直到今天,这一事件的真正影响仍在争议之中。
对通过食物和饮用水摄入放射性核素的评估主要基于在整个欧洲进行的几次 I-131、Cs-134 和 Cs-137 测量[1],这些是该数据集中报告的放射性同位素。
数据集内容
该数据集将碘-131 (I-131)、铯-134 (Cs-134)和铯-137 (Cs-137)的浓度呈现为在特定位置和日期测量的气溶胶粒子。
感谢
该数据集是从 CEC 联合研究中心 Ispra 的 REM 数据库中提取的。这些数据是从 Kaggle 的数据库下载的,也可以在 JRC 核安全和安保理事会上获得。
数据准备和清理
在第一部分中,我们将通过删除不相关的列和纠正/删除错误的值来执行数据清理,并通过处理缺失和无效的值来为将在后续部分中执行的分析准备数据集。
读取数据集后。csv 文件,我们删除了不会在分析中使用的列,重命名了国家的缩写,并修复了一些错误和缺失的值。
我们可以生成一个地图,显示在分析的数据集中报告值的所有位置。
全屏查看地图,体验更佳!
带有数据集中报告位置标记的交互式地图。
探索性分析和可视化
在这一节中,我们将对数字列执行计算,关注它们的统计数据,绘制图形以帮助可视化,同时在必要时调整数据框架。
每种同位素的最大活度浓度值。
数据集的总时间范围。
检查数据如何在数据集的同位素(I-131、Cs-134 和 Cs-137)之间传播。
原子能机构关于切尔诺贝利灾难的报告1证实了这一结论:"在事故发生后的早期,最令人担忧的放射性核素是 I-131;后来,重点转移到了 Cs-137。”
检查哪个国家在此期间的总体测量次数最多。
我们可以看到,法国、德国和瑞典分别是我们数据集中报告了最多测量值的地区。
在我们的数据集中,捷克斯洛伐克是距离乌克兰最近的国家,因此有理由假设捷克斯洛伐克的放射性同位素暴露水平最高。这个假设可以通过检查下面的柱状图来证实。
核实哪些国家报告的活动集中程度最高。
我们还可以可视化区域的条形图。
验证哪些区域报告了最高的活动浓度。
我们可以确认,对于我们的数据集,报告最高总活动集中度的国家和地区/地区分别是捷克斯洛伐克和维也纳(奥地利)。
为了更好地显示它,我们还生成了一个交互式热图,显示报告的值在我们的数据集中是如何分布的。
切尔诺贝利事故后 60 天放射性同位素活度浓度的交互式热图。
从使用我们数据集的报告位置生成的热图中,我们可以看到大多数放射性同位素的浓度是在中欧测得的,峰值位于奥地利和捷克斯洛伐克地区之间。
推论和结论
切尔诺贝利灾难的影响至今仍有争议。对动植物造成的损害不仅在发电厂附近可以看到,在欧洲的其他几个地区也可以看到。
通过我们的分析,我们能够评估放射性粒子在空气中扩散造成的污染的程度和速度,以及哪些国家和地区受到的影响最大。我们可以证实,在短短几天内,在离核电站所在地非常远的欧洲地区已经检测到高浓度的放射性同位素。
我们分析的另一个有趣的发现是,在奥地利(格拉茨)的一个位置,比数据集中的其他区域相对更远,已经测量到比那些区域高得多的活动浓度值。检查关于切尔诺贝利灾难的文献,以验证这种巨大的差异是否是由于数据集中报告的错误值,我们能够确认这些信息确实是所发生的事情。
国际原子能机构(IAEA)关于切尔诺贝利事故的一份报告[1]指出,尽管受影响最严重的三个国家是白俄罗斯、俄罗斯联邦和乌克兰,但由于湿沉降过程,在奥地利和其他邻近国家也有主要污染区。在这些地区,切尔诺贝利的放射性羽流与降雨同时发生,释放的放射性沉积物总量比其他国家多得多。
其他科学论文,如 2001 年发表的关于奥地利土壤被铯-137 污染的研究[2],也证实了这一信息。这些研究对这一分析有很大的价值,如果你想了解更多的细节,我们推荐你去阅读它们。
参考
[1]国际原子能机构(原子能机构),切尔诺贝利事故的环境后果及其补救:二十年的经验,2006 年,网址:https://www-pub . IAEA . org/MTCD/publications/PDF/pub 1239 _ web . PDF。
[2] Bossew,P. 等,奥地利土壤被铯-137 污染,2001 年,网址:https://doi . org/10.1016/s 0265-931 x(00)00192-2。
[3]放射性环境监测(REM),数据库,2020,网址:https://rem.jrc.ec.europa.eu/RemWeb/Browse.aspx?path =切尔诺贝利% 20 数据。
[4] Kaggle,2020,网址:https://www . ka ggle . com/lsind 18/Chernobyl-data-air-concentration。
德国足球联赛分析
使用 Pandas、Plotly 和 Matplotlib 进行数据分析
这篇文章是对德甲历史的一次旅行。分析历史数据(从 1963 年到 2020 年的所有分类),我们将能够回答很多关于德国联赛的问题。德国联赛有哪些球队夺冠?哪些球队差点赢得德甲冠军?拜仁的霸权是从什么时候开始的?哪些球队罚的比较多?…还有更多!继续读▶️
马里奥·克拉森在 Unsplash 上的照片
介绍
下面给没听说过德国联赛的人简单介绍一下。🙌
德国足球联赛通常被称为德甲联赛,是德国第一个国家足球联赛,是世界上最受欢迎的职业体育联赛之一。它成立于 1963 年,由西德的五个地区联赛合并而成,最初由 16 支球队组成。
在一场比赛结束时,获胜的队得到三分(在 1995-96 赛季之前得到两分),失败的队得零分。在平局的情况下,两个队都得 1 分。
在许多欧洲联赛中,倒数三名的球队自动降级到乙级联赛。相反,在德甲联赛中,只有倒数两名直接降级到德甲 2 强。德甲联赛第 16 名和德甲联赛第 3 名为争夺甲级联赛的一个席位进行了两回合的附加赛。
介绍做好了!现在,我们准备分析❤️的数据
Web 数据抽取
德甲联赛(从 1963 年到 2020 年)的历史数据是从 Bdfutbol.com 刮来的。该网站包含欧洲最佳联赛的足球排名。
1928 年的 BBVA 甲级联赛,1928-29 年的西班牙甲级联赛,1977-78 年的西班牙乙级联赛…
www.bdfutbol.com](https://www.bdfutbol.com/es/t/t.html#ger)
为了收集数据,我们使用了 BeautifulSoup,这是一个流行的 Python 库,用于从 HTML 页面中提取信息。在获得所有数据后,我们将它存储在一个 Pandas 数据框中以供进一步处理。
此处提供了分析中使用的编程代码。你可以边看文章边看。
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/amandaiglesiasmoreno/bundesliga/blob/master/Bundesliga.ipynb)
数据清理
数据清理是将原始数据转换为标准化形式的过程,这种标准化形式可以很容易地用数据分析工具进行分析。在这个特殊的例子中,在使用 Pandas 分析数据之前,我们执行一些清理操作。首先,我们删除不必要的列,并使用英语术语重命名剩余的列(请记住,这些数据是从一个西班牙语网站上搜集来的)。然后,我们修改错误的数据类型。由于星号的存在,列点数(球队在特定赛季中获得的点数)的数据类型是 object 而不是 integer。这些星号用于指网页底部的解释,它们与本分析无关。事实上,由于该列的某些条目中存在这些星号,数据类型没有被正确导入。因此,在将列指针转换为整数数据类型之前,我们必须删除它们。
在清理数据之后,我们获得了一个 Pandas 数据框架,可以很容易地对其进行处理以提取结论。如下图所示,数据框包含了从 1963 年到 2020 年参加德甲联赛的所有球队的胜、平、负场次、黄牌和红牌数量、积分以及排名等信息。
德国联赛冠军
德甲联赛在其 57 年的历史中(截至 2019-20 赛季),已经有 57 个不同的俱乐部参加过比赛;然而,他们中只有 12 个人拿到了奖杯。以下情节显示了从 1963-64 赛季到 2019-20 赛季的德国联赛冠军。
如上图,拜仁慕尼黑是德甲历史上最成功的俱乐部,拥有 29 个冠军,代表了超过 50%的联赛。接下来最成功的球队是门兴格拉德巴赫和五次获得德甲冠军的多特蒙德。除了他们,其他球队如云达不莱梅、汉堡、斯图加特、科隆和凯泽斯劳滕也多次举起德甲奖杯。
德国联赛亚军
有 6 支足球队从未赢得过联赛冠军,但他们在一个或多个场合获得亚军:阿亚琛,勒沃库森,柏林赫塔,梅德里奇,莱比锡和沙尔克 04。如下图所示,沙尔克 04 和勒沃库森特别倒霉,分别 7 次和 5 次获得德甲亚军。此外,我们还可以观察到拜仁慕尼黑是更多次获得德甲亚军的俱乐部(10 次)。
在 2016-17 赛季,RB Leipzig 在德甲联赛中获得第二名。该俱乐部成立于 2009 年,目前是德国领先的车队之一,这主要是因为红牛公司的重大投资。
甲级联赛总赛季数(前 10 名)
云达不莱梅保持着参加德国联赛赛季最多的记录。他们在德甲 57 个赛季中踢了 56 个赛季,只有一次被降级到乙级。拜仁慕尼黑从 1965 年开始不间断地在德甲踢球,汉堡从 1963 年到 2018 年,两人一共踢了 55 个赛季。除了前面提到的俱乐部,多特蒙德、斯图加特、门兴格拉德巴赫、沙尔克 04、法兰克福 Eintracht 也参加了 50 多个赛季的德国联赛。
在上个赛季(2019–20),上图中除了汉堡、斯图加特、凯泽斯劳滕之外的所有球队都在德甲打过球。
每个赛季德国联赛的球队数量
1963 年德甲联赛开始时有 16 支球队,1965 年扩大到 18 支。从那以后,除了 1991-92 赛季之外,德甲俱乐部的数量一直保持不变。在那个赛季,联盟被临时扩大(20 支球队)以容纳来自前东德的俱乐部。
目前,德国联赛有 18 支球队参赛。参加西甲联赛(葡萄牙)和荷甲联赛(荷兰)的球队数量相同。相反,有 20 支球队参加意甲(意大利)、西甲(西班牙)、法甲(法国)和英超(英格兰)。如今,人们仍在争论是否应该将两支球队纳入德甲联赛,以符合最重要的欧洲联赛。
联赛数量的演变
在整个德甲历史上,拜仁慕尼黑队明显占据了主导地位,赢得了超过一半的联赛冠军。自 2000 年以来,拜仁慕尼黑赢得了 20 场联赛中的 14 场,对于其他球队来说几乎不可能与红军竞争。但是德甲一直都是拜仁慕尼黑称霸的吗?拜仁的霸主地位是从什么时候开始的?让我们用一个简单的情节来澄清所有的问题。
下面的交互折线图展示了各队联赛数量的演变。为了正确地可视化结果,您可以停用一些跟踪,只可视化那些您感兴趣的跟踪。您可以通过单击相关的图例项来显示或隐藏轨迹。此外,您可以通过将鼠标悬停在数据点上来获取关于该数据点的信息(赛季和联赛数)。
德甲联赛的前七个赛季由七支球队赢得:科隆(1963-64)、云达不莱梅(1964-65)、1860 年慕尼黑(1965-66)、德国布伦瑞克(1966-67)、纽伦堡(1967-68)、拜仁慕尼黑(1968-69)和门兴格拉德巴赫(1969-70)。
在 70 年代,德国联赛由两家俱乐部主导,它们都不是 1963 年德甲联赛的创始成员:门兴格拉德巴赫和拜仁慕尼黑。从 1969 年到 1977 年,只有这两家俱乐部有幸举起了德甲冠军奖杯。
门兴格拉德巴赫的辉煌时期是在七十年代。在汉斯·维斯维勒(1964-1975)和乌多·拉特克(1975-1979)的执教下,小马驹乐队赢得了五座德甲冠军奖杯,两座联盟杯,甚至在 1977 年打进了冠军联赛决赛,但他们输给了利物浦。
从 80 年代中期开始,拜仁慕尼黑队完全统治了德甲联赛。到目前为止,他们赢得的冠军比所有其他队加起来还多。然而此后拜仁的霸主地位被数次打破。90 年代,凯泽斯劳滕两次捧起奖杯(1990-91 年和 1997-98 年),在从德甲 2 级升级后赢得了第二个联赛冠军。2008 年,在以 2 分之差击败拜耳后,沃尔夫斯堡赢得了他们的第一个德甲联赛冠军,并有史以来第一次获得了欧冠资格。上一支挑战拜仁霸权的球队是 2012 年在尤尔根·克洛普的魅力指导下的多特蒙德队,那是德甲联赛中最后一个不是拜仁的冠军。此后,拜仁慕尼黑连续八次获得德甲冠军。如今,拜仁慕尼黑是德国在国内和欧洲最成功的足球俱乐部。
所有上述情况也可以在下面的图表中观察到,该图表显示了球队和十年的联赛数量。
团队的历史表现
下面的互动图显示了所有在德甲比赛的球队的历史表现(历年排名)。要显示历史数据,我们必须使用位于左上角的下拉列表选择团队。我们会注意到,在一些赛季中没有可用的数据,这意味着被选中的球队在该特定年份没有参加过甲级联赛。请随意检查您更感兴趣的团队的表现💚
德甲联赛中的黄牌和红牌
有一样东西是全世界大多数足球迷认为理所当然的:使用卡。然而,直到 1970 年墨西哥世界杯,才在足球界首次使用了黄红卡制度。这个系统是由英国裁判肯·阿斯顿在 1966 年发明的,他注意到很多时候足球运动员不理解或者只是忽视裁判的警告,而这些警告在当时是口头传达的。然后,受交通灯颜色(红色和黄色)及其含义的启发,阿斯顿创造了一种颜色编码方案,以清楚地表明足球运动员已被警告或驱逐。
在 1970-71 赛季的德甲联赛中,使用了黄牌和红牌。几年后的 1991 年,德国联赛引入了黄/红牌。球员在同一场比赛中得到第二张黄牌后得到一张黄/红牌,这意味着他必须离开比赛,并被排除在下一场比赛之外。相反,当直接收到红牌时,该球员将被禁止参加比赛更长时间。此外,如果一名球员累积五张黄牌,我们也将被排除在下一场比赛之外。
下图显示了每个赛季的红牌总数。正如我之前说过的,在 1971 年之前,裁判口头向球员宣布他的罚款。在下图中,1971 年之前,红牌代表的是在比赛中仅用言语(不使用卡片)驱逐的足球运动员。在使用卡牌之前,玩家往往得不到惩罚。只有在特殊情况下(真的很强的犯规),足球运动员才被驱逐出场。
我们观察到一种增长趋势(特别是在 80 年代快速增长)直到 90 年代中期。从那一刻开始,红牌总数就在随着时间慢慢减少。
同样,下图显示了每个赛季的黄牌总数。
从 1971 年到 90 年代,每个赛季的黄牌总数一直在稳步增长。从这个时候起,卡片的数量几乎保持不变,每季大约 1200 张。
在之前的一篇文章中,我们已经分析过西班牙联赛(链接此处!)。对比结果后,我们可以观察到,在这两个联赛中,多年来红牌和黄牌数量的演变遵循相同的模式,如下所示。然而,西班牙联赛的球员比德甲联赛的球员收到的卡要多得多(尽管他们只多踢两场比赛)。
现在,也许你想知道:在过去的几个赛季中,哪些球队收到了更多的卡片?
下面的图表显示了从 2000 年到 2020 年球队的平均红牌和黄牌数量。如下图所示,拜仁慕尼黑是平均每个赛季收到较少卡片的球队之一。正如我们在以前的文章中分析的那样,西班牙的皇家马德里和巴塞罗那也是如此。
过去 10 年的表现(拜仁慕尼黑 vs 多特蒙德)
拜仁慕尼黑在过去的 10 年里完全统治了德甲联赛,连续赢得了 8 个冠军。那段时间,唯一挑战过拜仁霸主地位的球队一直是多特蒙德;然而,拜仁慕尼黑展示了比直接对手更强的防守技巧。
下面的图表显示了两个团队从 2010 年到 2020 年的目标。在多特蒙德夺冠的两个赛季(2010-11 和 2011-12),黑黄军团的防守和红军一样好,2011 赛季甚至好得多。然而,从那以后,拜仁慕尼黑在进攻和防守方面表现出了更大的平衡,这解释了它在过去八个赛季中的成功。
多分析!
如果你喜欢读这篇文章,并且想知道更多关于其他联赛的信息😃,看一眼西班牙联赛的分析:)
数据分析📝+历史记录🌐
towardsdatascience.com](/analysis-of-the-spanish-football-league-la-liga-7c636a9317b3)
感谢你阅读❤️
阿曼达
使用 R Shiny 对肯尼亚 2019 年人口普查的分析。
该项目为肯尼亚 2019 年住房和人口普查提供了可操作的见解。
肯尼亚一个选区的人口普查员。
引言。
独立后的第一次人口普查于 1969 年进行,对 1,090 万肯尼亚人进行了统计。此后,该国在 8 月 24 日/25 日午夜进行了十年一次的人口和住房普查。
使用 R Shiny 应用程序对 2019 年肯尼亚人口和住房普查第一卷报告进行的分析,提供了关于国家和县一级按性别、家庭数量、平均家庭规模分列的枚举人口分布的有用、可操作的见解。政府可以很容易地获得这些见解,并将其用于资源分配、政策制定、规划和预算,以提供基本的政府服务。
肯尼亚国家统计局(KNBS)是负责收集、分析和传播统计数据的政府机构。2019 年肯尼亚人口和住房普查于 2019 年 8 月进行,信息包括人口的人口统计和社会经济特征。人口普查的主题是“统计我们的人口以促进可持续发展和服务转移”。
国家一级普查统计概览。
R 闪亮概述。
Shiny 是一个真正强大的数据讲述工具,它结合了 R 的计算能力和现代网络的交互性,用于创建漂亮、有洞察力的应用程序。R shiny 有广泛的应用,包括在学术界作为统计概念的教学工具;数据分析师为高级分析创建指标仪表板。
对于初学者来说,一个很好的指南是 Hadley Wickham 的闪亮 R 工作室网站和掌握闪亮。
普查分析与洞察。
数据。
2019 年肯尼亚人口普查数据包括人口统计数据,如按性别分列的人口、家庭数量、平均家庭规模、人口密度、国家、县和县以下各级的土地面积。
数据可以从这里获取,pdf 格式。我分析过县级的数据;县级以下的数据仍在清理中。
这个互动的 R 闪亮的应用程序使人们能够与人口普查数据互动,并获得明智决策的洞察力。
人口。
据统计,全国总人口为 47,564,300 人,其中男性人口为 23,548,100 人,女性人口为 24,014,700 人,阴阳人人口为 1,500 人。
各县人口。
下面的地图显示了每个县的人口分布。显而易见,内罗毕、基安布和纳库鲁等县的人口较多,而拉穆等县的人口只有 143,920 人。
按人口分组的前 5 个县的条形图
男性人口。
内罗毕、基安布和纳库鲁的男性人口最多,而伊索洛等县的男性人口只有 139510 人。
按男性人口分组的前 5 个县的条形图
女性人口。
统计数字仍然相同,内罗毕、纳库鲁和基安布的女性人口最多。
按女性人口分组的前 5 个县的条形图
户数。
家庭数量最多的主要县包括内罗毕、基安布、纳库鲁、卡卡梅加和梅鲁。
按家庭数量分组的前 5 个县的条形图
平均家庭规模。
曼德拉、瓦吉尔、加里萨、马萨比特和图尔卡纳等北部大多数县的平均家庭规模较大。内罗毕,
Kiambu 和 Kirinyaga 的平均家庭规模最小。
按平均家庭规模分组的前 5 个县的条形图
互动地图。
闪亮互动应用概述
在 shiny app 上可以找到轻松显示上述地图的互动地图。闪亮应用的代码在我的 Github 上。请随意浏览地图,了解更多关于肯尼亚人口普查的信息。
下一步。
I)添加县级以下的人口普查数据(仍在清理数据)。
ii)用肯尼亚国家统计局发布的新数据更新应用程序(第 2 卷报告)。
iii)优化应用程序代码以获得更好的性能。
结论。
R shiny 是一款非常棒的工具,可以用来讲述数据故事和制作信息丰富的仪表盘。您已经能够获得对肯尼亚 2019 年人口普查的宝贵见解。快乐的 R 闪耀!更多讨论,我们可以通过 Linkedln 连线。
西班牙足球联赛分析
数据分析📝+历史记录🌐
西班牙足球联赛俗称西甲,是西班牙第一个国家足球联赛,是世界上最受欢迎的职业体育联赛之一。它成立于 1929 年,除了西班牙内战期间(1936-1939)之外,每年都举行。在他的基金会,只有 10 个团队。目前,它由 20 支球队组成,分布在全国各地,但主要来自最发达的地区:马德里、巴塞罗那和巴斯克地区。排名前四的球队有资格参加冠军联赛,而排名最低的三支球队(排名 18-20)被降级到乙级。像在大多数欧洲国家一样,比赛的获胜者得到三分,如果平局,两个队都得 1 分。
这篇文章介绍了西班牙联赛的历史。分析历史数据(从 1929 年到 2020 年的所有分类),我们将能够回答很多关于西甲的问题。有哪些球队差点拿到西甲冠军?裁判偏向皇马和巴萨吗?西甲是不是变得太软了?巴萨和皇马的争霸是从什么时候开始的?巴塞罗那什么时候开始追赶皇马了?
我们开始吧💜
韦斯利·廷吉在 Unsplash 上拍摄的照片
Web 数据抽取
西甲联赛(从 1929 年到 2020 年)的历史数据是从 Bdfutbol.com 刮来的。这个网站包含国家和国际足球排名。
1928 年的 BBVA 甲级联赛,1930-31 年的荷兰甲级联赛,1978-79 年的荷兰乙级联赛…
www.bdfutbol.com](https://www.bdfutbol.com/es/t/t.html)
为了收集数据,我们使用了 BeautifulSoup,这是一个流行的 Python 库,用于从 HTML 页面中提取信息。在获得所有数据后,我们将它存储在一个 Pandas 数据框中以供进一步处理。
此处提供了分析中使用的编程代码。你可以边看文章边看。
[## amandaiglesiasmoreno/西班牙联赛
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/amandaiglesiasmoreno/Spanish-League/blob/master/Spanish League.ipynb)
数据清理
数据清理是将原始数据转换为标准化形式的过程,这种标准化形式可以很容易地用数据分析工具进行分析。在这个特殊的例子中,在使用 Pandas 分析数据之前,我们已经执行了多次清理操作。我们已经删除了不必要的列,并使用英语术语重命名了剩余的列(请记住,数据是从一个西班牙语网站上搜集来的)。在探索性数据分析过程中,我们注意到在某些情况下,同一个足球队被用了多个名字。多年来,一些足球队已经改变了他们的名字,在大多数情况下是由法律规定的。例如,在西班牙第二共和国时期(1931-1939),不允许使用皇家标志。因此,许多足球队修改了包含“皇家”一词的名称,以避免因赞美君主政体而被定罪。皇家马德里不仅改名为公正的马德里,而且还失去了他的盾冠。随后,在佛朗哥政权期间,他们恢复了“Real”这个词,但一项新的法律影响了其他球队的名称。独裁政权从 1941 年到 1972 年禁止使用外来语。因此,竞技俱乐部、桑坦德竞技和希洪竞技等球队被迫将 30 年来的历史名称改为毕尔巴鄂竞技、桑坦德和皇家希洪。
在清理数据之后,我们获得了一个 Pandas 数据框架,可以很容易地对其进行处理以提取结论。如下图所示,数据框包含了从 1929 年到 2020 年参加西甲联赛的所有球队的胜、平、负场次、黄牌和红牌数、积分数以及在排名中的位置等信息。
现在,我们准备分析数据!😃
西班牙联赛冠军
西班牙联赛由 60 多个不同的俱乐部参加;然而,他们中只有 9 个人拿到了奖杯。以下情节显示了从 1928-29 赛季到 2019-20 赛季的西班牙联赛冠军。
如上图所示,皇马是西甲历史上最成功的俱乐部,拥有 34 个冠军,其次是巴塞罗那,拥有 26 个联赛冠军。然而,正如我们将在后面看到的,巴塞罗那正在迎头赶上。除了这两家俱乐部,西班牙甲级联赛还被其他 7 家俱乐部夺得,包括马德里竞技(10),竞技俱乐部(8),瓦伦西亚(6),皇家社会(2),贝蒂斯(1),塞维利亚(1),拉科鲁尼亚(1)。
西班牙联赛亚军
成为亚军是令人心碎的。对于皇家马德里和巴塞罗那来说,第二名是一个可耻的失败,很容易以解雇教练或下赛季签下多个千万富翁而告终。对于其他团队来说,只是一个几乎成真的梦想,但绝对不是失败。毕竟,失败只是期望的问题。
如下图所示,有 5 支足球队从未赢得过联赛冠军,但他们曾经获得过亚军:桑坦德竞技队(1930-31)、拉斯帕尔马斯队(1968-69)、萨拉戈萨队(1974-75)、希洪竞技队(1978-79)和比利亚雷亚尔队(2007-08)。
此外,我们还可以观察到,巴塞罗那在西甲联赛中获得亚军的次数比皇家马德里多。
甲级联赛总赛季数(前 10 名)
只有三支足球队从未降级到乙级:竞技俱乐部、巴塞罗那和皇家马德里。西班牙人和瓦伦西亚在乙级联赛踢了 4 个赛季,马德里竞技踢了 6 个赛季。
上图中的所有球队目前都在甲级,除了萨拉戈萨(自 2012 年以来-13 年在乙级)。
每个赛季西班牙联赛的球队数量
除了 1995-1996 和 1996-1997 赛季有 22 支球队参赛之外,西甲联赛的球队数量从 10 支稳步增长到 20 支。
目前,有 20 支球队参加西班牙联赛。同样数量的球队参加意甲(意大利)、法甲(法国)和英超(英格兰)。相反,有 18 支球队参加了德甲(德国)、西甲(葡萄牙)和荷甲(荷兰)。联赛数量的演变
联赛数量的演变
据说在西班牙,西甲由两支球队踢,剩下的就是装饰,在我看来,这是完全正确的😢。自 2000 年以来,皇家马德里和巴塞罗那赢得了 20 场联赛中的 17 场,其他球队几乎不可能与之竞争。但是西班牙联赛一直都那么无聊吗?一直以来都是马德里还是巴萨在主导?皇马和巴萨的争霸是从什么时候开始的?让我们用一个简单的情节来澄清所有的问题。
下面的图显示了球队的联赛数量的演变。
如剧情所示,在联赛的最初几年,虽然我们可以观察到竞技俱乐部的轻微突出,但西甲并不像现在这样一家独大,也没有被任何俱乐部明显主导。在 50 年代后期,随着迪斯蒂法诺的签约,我们开始看到皇家马德里统治地位的开始。这位阿根廷人彻底改变了皇马的命运,当时皇马只是一支普通球队,已经 20 年没有赢得联赛冠军了。
从 20 世纪 60 年代开始,皇家马德里控制了联赛,在短短 20 年内赢得了 14 个冠军。当时,“El Clásico”是马德里竞技队和皇家马德里队之间的比赛,因为马德里竞技队是梅林格队在 1960 年至 1980 年期间赢得 4 个联赛冠军的唯一强劲对手。
从 90 年代开始,巴塞罗那一直统治着西班牙联赛,赢得了 16 个冠军。在 20 世纪 90 年代,在约翰·克鲁伊夫(1988-1996)的管理下,巴萨在最后几年结束了对皇马的压倒性统治。约翰·克鲁伊夫创造了一种以控球为基础的足球风格,这种风格被巴萨后来的教练路易斯·范加尔、弗兰克·里杰卡尔德,尤其是瓜迪奥拉所模仿。从 2000 年开始,本土球员如梅西、伊涅斯塔、哈维、布斯克茨、普约尔或皮克继续称霸巴塞罗那。
所有上述情况也可以在下面的图表中观察到,该图表显示了球队和十年的联赛数量。
皇马和巴萨的联赛差异
下面的剧情展示了一段时间内皇马和巴萨的联赛差异。如下图所示,对巴塞罗那有利的最大差异出现在 1952-1953 赛季。当时巴萨比皇马多 4 个联赛。然而,在五十年代中期,皇马的运气即将改变。从这个时候到 90 年代,皇家马德里队明显统治了西甲,布兰科队和巴塞罗那队之间的联赛差距随着时间的推移不断扩大,在 1989-90 赛季达到最大值(15 个联赛)。从 20 世纪 90 年代开始,我们观察到由于巴塞罗那的霸权,联赛中的差异是如何随着时间的推移而减少的。目前皇马比巴萨多 8 个联赛。
西甲联赛中的黄牌和红牌
有一样东西是全世界大多数足球迷认为理所当然的:使用卡。然而,直到 1970 年墨西哥世界杯,才在足球界首次使用了黄红卡制度。这个系统是由英国裁判肯·阿斯顿在 1966 年发明的,他注意到很多时候足球运动员不理解或者只是忽视了当时口头传达的裁判的警告。然后,受交通灯颜色(红色和黄色)及其含义的启发,阿斯顿创造了一种颜色编码方案,以清楚地表明足球运动员已被警告或驱逐。
但正如海明威所说,西班牙是不同的。西班牙国家队没有参加 1970 年在墨西哥举行的世界杯,在那里首次使用了信用卡系统。西班牙足球联合会认为黄牌实际上是白色的,所以那是他们在当时黑白电视中的样子。1971 年 1 月,红白卡被引入西班牙联赛,直到 1976 年,罗卡最终取代了白卡。
下图显示了每个赛季的红牌总数。正如我之前说过的,在 1971 年之前,裁判口头向球员宣布他的罚款。在下图中,1971 年之前,红牌代表的是在比赛中仅用言语(不使用卡片)驱逐的足球运动员。
我们观察到一种增长的趋势,直到 90 年代中期。从那一刻起,红牌总数随着时间稳步下降。
同样,下图显示了每个赛季黄牌(包括白牌)的总数。
从 1971 年到 90 年代中期,每个赛季的黄牌总数一直在稳步增长。从那时起,卡的数量几乎保持不变,每季大约 2000 张。
在使用卡牌之前,玩家往往得不到惩罚。只有在特殊情况下(真的很强的犯规),足球运动员才被驱逐出场。
在西班牙,据说最近几年裁判偏向皇马和巴萨。但真的是这样吗?让我们看看数字:)
下面的图显示了从 1990 年到 2020 年球队的红黄牌平均数量。如上所述,皇家马德里和巴塞罗那平均收到的卡片比其他强队如马德里竞技、瓦伦西亚、塞维利亚或竞技俱乐部要少。也许他们的成功不仅仅是金钱和优秀球员的结合,还有一点点帮助😆
过去 10 年的业绩
以下图表显示了瓦伦西亚、皇家马德里、巴塞罗那、马德里竞技和竞技俱乐部在过去 10 年中的表现。如下图所示,皇家马德里和巴塞罗那的平均进球数比其他球队多。
然而,如果我们分析对手的进球,我们会发现马德里竞技是防守最强的球队,甚至比巴萨还要好,而这一切的罪魁祸首就是迭戈·西蒙尼。
这位阿根廷人自 2011 年 12 月以来一直是马德里竞技的经理。在他的指导下,马德里竞技在强大的防守风格基础上形成了鲜明的特征。在迭戈·西蒙尼的执教下,马德里竞技赢得了西甲冠军、国王杯冠军、两次欧联杯冠军、两次欧洲超级杯冠军,目前是皇马和巴萨唯一的劲敌。
摘要
长期以来,西班牙联赛明显由皇马和巴萨主导。一开始,这个联盟并不像今天这样具有霸权地位,也没有任何俱乐部明显地控制着它。从五十年代中期开始,皇家马德里队控制了联赛,成为他唯一的劲敌。在 1989-90 赛季,皇家马德里比巴塞罗那多 15 个联赛。然而,在 90 年代,在约翰·克鲁伊夫的监督下,巴萨以皇马的压倒性优势而告终。从那个时候开始,他们之间的联赛差距就在逐渐缩小。如今,皇家马德里,尤其是巴塞罗那,显然统治着西甲,其他球队很难与之竞争。
一个更多元化的联盟也会更有趣。然而,在我看来,这种情况不太可能很快改变。西班牙联赛高度货币化,人们对皇家马德里-巴塞罗那的霸权特别感兴趣,因为他们是产生最大利益的球队。
感谢
虽然我喜欢足球,但我从来不是它的狂热爱好者。我选择这个题目几乎是偶然的,没有想到会发现这么多有趣的东西。我希望你喜欢读这篇文章,就像我喜欢写它一样。
最后,我要感谢我的父母对我的支持。如果没有和他们关于足球的长时间交谈,就不可能写出这篇文章。谢谢你😊。是的,我们都支持❤️竞技
阿曼达🍀
用熊猫分析 1976-2010 年美国大选
实践熊猫,同时提供对过去选举的宝贵见解。
由 Unsplash 上的 Element5 数码拍摄
我最近在 Kaggle 上偶然发现了美国选举数据集。由于我们正处于对 2020 年选举的激烈讨论中,我认为对历届美国总统选举进行分析是一个好主意。
该数据集包含从 1976 年到 2020 年的选举。我将从各种不同的角度处理这些数据,并试图对人们的投票方式有所了解。
我将使用 Pandas 库进行数据分析和可视化,因此使用 Pandas 的功能和方法也是一个很好的实践。
让我们从导入库和将数据集读入 Pandas 数据帧开始。
import numpy as np
import pandas as pdpresident = pd.read_csv("/content/president-1976-2016.csv")
有一些用于分析的冗余列。我不确定 state_fips、state_cen 和 state_ic 代表什么,但它们可能是一个状态的指示器或唯一值。
我们可以通过检查和比较这些列中的值来确认。这三列有 51 个唯一值(每个州一个)。
president.state_fips.nunique()
51
对于特定的状态,这些列中的值是相同的:
president[president.state == 'Alabama'][['state_fips','state_cen','state_ic']].value_counts()state_fips state_cen state_ic
1 63 41 63
dtype: int64
由于数据集已经包含状态信息,这些列在分析中是多余的,因此可以删除。
office 列只表明这是总统选举,因此它包含一个唯一的值(美国总统)。版本和注释列也没有用。
我们可以使用 Pandas 的 drop 功能来删除这些列。
president.drop(['state_po', 'state_fips', 'state_cen', 'state_ic',
'office', 'version', 'notes'], axis=1, inplace=True)
我们准备开始分析,我将分析分为三个部分:
- 一段时间内的投票总数
- 每位获胜者的得票率
- 各缔约方的国别比较
一段时间内的投票总数
我们首先要检查的是每次选举的票数。“totalvotes”列显示特定州的投票总数。因此,下面的代码将创建一个 dataframe,其中包含每个州每次选举的总票数。
yearly_votes = president[['year','state','totalvotes']]\
.groupby(['year','state']).mean().reset_index()yearly_votes.head()
我们可以对“year”列应用 groupby 函数,并对“totalvotes”列中的值求和,这将给出每次选举的总票数。
yearly_votes.groupby('year').sum()\
.plot(figsize=(10,6), legend=False,title='Total Number of Votes in US Presendial Elections')
我使用了熊猫的绘图工具来绘制结果。它比使用 Matplotlib 的 pyplot 接口简单,但是对绘图的控制较少。
除了 1996 年和 2012 年,参加投票的人数一直在稳步增加。这很可能是由于人口增长,因此更好的衡量标准是每百万人口的投票数(有资格投票)。粗略比较一下,从 1970 年(2.03 亿)到 2010 年(3.08 亿),人口增长了约 50%。因此,多年来,投票人数的比例大致保持不变。
每位获胜者的得票率
有些选举非常接近,获胜者以微弱优势获胜。也有一些选举中获胜者以较大优势获胜。
我们可以计算出每个获胜者的得票率。我们将首先向我们的数据框架添加一个“winner”列。
这个维基百科页面包含了美国总统的名单。使用 read_html 函数可以很容易地将这些表读入 pandas 数据框架。它将网页中的表格转换成数据帧列表。
dfs = pd.read_html("https://en.wikipedia.org/wiki/List_of_presidents_of_the_United_States")winners = dfs[1][['Election','President.1']]
winners.head()
第二个数据帧包含美国总统的名单。我们只需要 1976 年到 2016 年的选举数据。
winners = winners.iloc[-12:-1, :]
winners.Election = winners.Election.astype('int64')
winners.rename(columns={'President.1':'winner'}, inplace=True)winners
我们需要和总统数据框中相同格式的名字。“吉米·卡特”需要格式化为“卡特,吉米”。我将使用 pandas 字符串操作来完成这项任务:
first_name = winners.winner.str.rsplit(' ', n=1, expand=True)[0]
last_name = winners.winner.str.rsplit(' ', n=1, expand=True)[1]
winners.winner = last_name + ', ' + first_namewinners
我们需要一些小的调整,以便总统的名字完全匹配。
winners.winner[73] = 'Bush, George H.W.'
winners.winner[78] = 'Obama, Barack H.'
winners.winner[79] = 'Obama, Barack H.'
winners.winner[80] = 'Trump, Donald J.'
我还将选举日期转换为整数,以便能够在下一步中使用 merge 函数。
我们现在可以根据选举年份合并“总统”和“获胜者”数据帧。
president = pd.merge(president, winners, left_on='year', right_on='Election')
我们将过滤总统数据帧,只包括获胜者的投票。
winner_votes = president[president.candidate == president.winner]winner_votes.head()
每一行都包含获胜者的票数和特定选举中特定州的总票数。一个简单的 groupby 函数将给出各个国家的值。
total_votes = winner_votes[['year','winner','candidatevotes','totalvotes']]\
.groupby(['year','winner']).sum()total_votes
我们可以通过简单的数学运算计算出中奖者的比例,并对结果进行排序。
(total_votes.candidatevotes / total_votes.totalvotes)\
.sort_values(ascending=False)
排名第一的是第二任期的罗纳德·里根。
各缔约方的国家比较
如果你对政治感兴趣,你就会知道每个州更可能支持哪个政党。让我们也用数字来核对一下。
这是获胜者投票数据框。我们将添加一个比率列,即候选人票数除以总票数。
winner_votes['ratio'] = winner_votes.candidatevotes / winner_votes.totalvotes
我们希望看到民主党和共和党的前十个州。下面的 groupby 操作将根据民主党的最高平均比率返回前十个州。
winner_votes[winner_votes.party == 'democrat'][['state','ratio']]\
.groupby('state').mean().sort_values(by='ratio', ascending=False)[:10]
下面是共和党方面同样操作的结果。
注:除非另有说明,所有图片均由作者创作。
结论
我们分析了美国总统选举随时间推移的票数,每位总统在选票方面的优势,以及民主党和共和党在各州的选票。结果可能不会让你吃惊,尤其是如果你对政治感兴趣的话。
这篇文章的另一个重点是练习如何在数据分析和操作中使用 Pandas。我们在数据分析和处理方面做了大量的熊猫运算。
感谢您的阅读。如果您有任何反馈,请告诉我。
波浪能分析
新罕布什尔州和罗德岛州近海浮标记录数据的波能分析。
作者图片
虽然大多数人不认为像新罕布什尔州和罗德岛这样的地方是冲浪的热门目的地,但从国家数据浮标中心获得的波浪能数据显示,有时会有显著的波浪能。这些波浪浮标放置在离海岸线大约 30 海里的地方,记录诸如有效波高、波浪周期和涌浪方向等数据。
作者图片
https://magicseaweed.com/help/forecast-table/swell
浮标记录的信息可以用来计算海浪的能量。这项研究的目标是发现哪个位置,罗德岛或新罕布什尔州,在 2019 年经历了更大的波浪发电。
如下图所示,NDBC 44098 和 NDBC 44097 的波浪功率频率,罗德岛的平均波浪功率略大于新罕布什尔。据计算,2019 年罗德岛每单位波峰的平均波功率约为 5265 瓦,而新罕布什尔州的平均波功率约为 4760 瓦。新罕布什尔州的最大波浪功率约为 40619 瓦,罗德岛州为 36980 瓦。
作者图片
由于地理位置略有不同,我希望根据 2019 年的月份进一步分析每个位置的波浪功率。对于新罕布什尔州和罗德岛州来说,7 月份观察到的海浪能量最低,10 月份观察到的海浪能量最高。九月两个州的波浪力量差异最大。这是典型的飓风季节,因为罗德岛更多的暴露在南方,而新罕布什尔面向东方。这两个州在秋季都显示出持续整个冬季的不断增长的海浪能量。
作者图片
用于推导单位波峰波浪功率的两个关键信息包括有效波高和波浪周期。如下图所示,波高和波周期的相关性(NDBC 44098),变量波高和波周期之间没有相关性。
这些数据可以用于多种目的。目前正在探索波浪能作为可再生能源的可能来源。如果研究人员将此扩展到更大的波浪浮标选择,他们将能够确定部署波浪能浮标的最可行位置。许多国家使用大型船只作为运输货物的工具。使用历史数据可以帮助确定一年中运输昂贵物品的最安全时间。这些近海浮标也收集海洋温度的数据,这些数据可用于分析全球变暖的影响。
总之,罗德岛决心拥有比新罕布什尔州更大的海浪能。
使用 Python 和 TWINT 分析推文
情感分析,建立单词云和更多…
听说过 Twint 吗?
Twint 是 Python 中内置的高级 web 抓取工具,它抓取 web,而不是像 tweepy 一样通过 twitter API 收集数据。它是推特智能工具的缩写。您可以通过以下方式下载:
pip3 install twint
twint 文档可以在这里找到。
收集数据
在本文中,我们将使用唐纳德·特朗普自 2019 年初以来的推文。我们可以在命令行中使用这个简单的命令下载给定用户的 tweets:
twint -u realDonaldTrump --since 2019-01-01 -o trump.csv --csv
这将把 2019 年以来@realDonaldTrump
的所有推文下载到一个单独的 csv 文件trump.csv
中。
这里,为了方便起见,我将 csv 文件转换为 xls 格式。让我们开始吧!
df=pd.read_excel('trump.xls')***added columns mentions, hashtags and length***
***added month, year and hour columns***
***added cleaned_tweetsnum_mentionsnum_hashtags***df.head()
一些有趣的分析
- 让我们来看看每小时的平均推文长度。
看起来总统的推特在一大早就很长了(凌晨 3 点到 10 点)。
- 每小时的平均提及次数。
再加上那些推文的情绪又如何呢?(后面显示的情绪计算。)
文本分析
首先,让我们清理推文。为此,我们将创建两个函数,一个用于删除 URL、提及和标签(将它们存储在单独的列中),另一个用于清理剩余的文本(删除停用词、标点符号)。
我将使用删除了内容、停用词和标点符号的推文的cleaned_tweets
列和删除了内容的tweet
列来计算情绪和主观性。
df['cleaned_tweets']=df['tweet'].apply(lambda x: process_text(x))
df['tweet']=df['tweet'].apply(lambda x: remove_content(x))
现在让我们建立一个单词云来了解常用短语。
WordCloud
**from** wordcloud **import** WordCloud, STOPWORDS
**import** matplotlib.pyplot as plttemp=' '.join(df['cleaned_tweets'].tolist())
wordcloud = WordCloud(width = 800, height = 500,
background_color ='white',
min_font_size = 10).generate(temp)plt.figure(figsize **=** (8, 8), facecolor **=** None)
plt.imshow(wordcloud)
plt.axis("off")
plt.tight_layout(pad **=** 0)
plt.show()
词云
更常用的单词/短语以更大的字体出现。
现在让我们定义一个函数来绘制给定 ngram 范围内出现次数最多的 n 个短语。为此,我们将使用CountVectorizer
功能。
大部分工作已经完成,现在让我们画出常用短语。
- 频繁出现的单字
plot_topn(tweet_list, ngram_range=(1,1))
- 频繁的二元模型
plot_topn(tweet_list, ngram_range=(2,2))
- 频繁三元模型
plot_topn(tweet_list, ngram_range=(3,3))
瞌睡虫乔·拜登?真的吗?
提及和标签
- 提及最多的用户:
- 最常用的标签:
情感分析
我们使用推文专栏来分析推文的情绪和主观性。为此,我们将使用TextBlob
。
给定一个输入句子,TextBlob 输出一个包含两个元素的元组:(sentiment, subjectivity)
from textblob import TextBlob
df['sentiment']=df['tweet'].apply(lambda x:TextBlob(x).sentiment[0])
df['subject']=df['tweet'].apply(lambda x: TextBlob(x).sentiment[1])
df['polarity']=df['sentiment'].apply(lambda x: 'pos' if x>=0 else 'neg')
我们来看看推文的情绪分布
大多数推文可能不是主观的。推文可能是事实,就像坏消息一样。让我们找出主观的推文的情绪分布。为此,让我们过滤掉subjectivity
大于 0.5 的推文,并绘制分布图。
fig=px.histogram(df[df['subject']>0.5], x='polarity', color='polarity')
fig.show()
看起来,当只分析主观推文时,负面情绪的比例增加了。
现在让我们来看看 20 个被提及最多的用户的主观推文的极性。
主题建模
主题建模是一种自动分析文本数据以确定一组文档的聚类词的机器学习技术。这被称为“无监督”的机器学习,因为它不需要预先定义的标签列表或之前由人类分类的训练数据。
我们将使用 gensim LDA 模型进行主题建模。
**#pre-process tweets to BOW**
from gensim import corpora
r = [process_text(x,stem=False).split() for x in df['tweet'].tolist()]
dictionary = corpora.Dictionary(r)
corpus = [dictionary.doc2bow(rev) for rev in r]**#initialize model and print topics** from gensim import models
model = models.ldamodel.LdaModel(corpus, num_topics=10, id2word=dictionary, passes=15)
topics = model.print_topics(num_words=5)
for topic in topics:
print(topics[0],process_text(topic[1]))
有一些明确的主题,如弹劾审判早期阶段的主题 5,包含与中国贸易协议有关的短语的主题 8,以及关于他修建隔离墙的计划的主题 6。
labels=[]
for x in model[corpus]:
labels.append(sorted(x,key=lambda x: x[1],reverse=True)[0][0])df['topic']=pd.Series(labels)
再来看话题分布。
我们来看看话题 5 和话题 6 的分布。
这些情节是有意义的,因为在举报人投诉发布的那个月,话题 5 中的推文显著增加,而在特朗普计划修建隔离墙的 2019 年第一个月,话题 6 中的推文更多。
你可以在这里找到更详细的分析。
如果你喜欢这篇文章,请留下你的掌声。感谢您的阅读!
参考
- Github Twint 文档:https://github.com/twintproject/twint
- https://medium . com/big panda-engineering/explorative-data-analysis-for-text-data-29 cf 7 DD 54 EB 8
- https://medium . com/@ b . terry jack/NLP-预训练-情绪-分析-1eb52a9d742c
分析、价格建模和预测:西雅图 AirBnB 数据,2016–17
本文为技术和非技术受众详细概述了 AirBnB 的西雅图数据分析 。分析完成后使用 CRISP-DM 流程、数据工程 & 机器学习技术。
图片来自 Pixabay 埃里克·帕拉西奥
商业理解
对于西雅图的所有 AirBnB 用户和主机,我将从以下几个方面分析和回答商业相关问题:
- 价格分析
- 清单计数分析
- 最忙时间分析
- 入住率和点评分析
- 价格预测建模
下面是问题和答案。
数据理解
这里我将对 Kaggle 上 Airbnb 内 提供的数据进行探索性数据分析,你可以在这里 ( zip 文件),zip 文件包含 3 个 csv 文件: listing.csv 、 calendar.csv 和
listing.csv 概述
使用 熊猫 读取 csv 文件,如下所示:
*#read listing.csv, and its shape
listing_seattle = pd.read_csv(‘listings_seattle.csv’)
print(‘Shape of listing csv is’,listing_seattle.shape)
listing_seattle.sample(5) #display 5 rows at random*
基本检查和高级数据分析
查看数据并进行一些健全性检查,如每列缺失值的百分比,listing _ ids 在整个数据集中是唯一的吗?,查看汇总的数值列等。
- 每列缺失值的百分比
每列缺失值的百分比
从上面的条形图中,我们得到了丢失值最少的重要列。像 牌 和 方 脚 这样的列有超过 95%的数据缺失,因此我们将删除这些列。
****Are the ids unique for each row?*** len(listing_seattle['id'].unique()) == len(listing_seattle)***Description of all numeric features***
listing_seattle.describe()*
Github 查看数字列摘要的依据
上面的 csv 文件中显示了所有数字列的摘要。使用
*df.describe()*
计算重要的数值参数,如计数、平均值、标准差、方差、最大值和分位数范围
calendar.csv 概述
使用pd.read_csv('calendar.csv')
读取“ calendar.csv ”并使用df.head(5)
显示 csv 概览。这将显示数据框中的前 5 行。
calendar.csv 数据的高级分析
让我们看看每列的类型和数据中缺失值的数量:
通过df.dtypes
得到每一列的类型,见下面的实现
每列的数据类型
每列中缺失值的百分比:
每列缺失值的百分比
因此,在价格一栏中只有 33%的男性。这也表明,在全年所有 365 天的列表中,平均只有 33%的列表被占用
检查两个数据集中的列表数量是否相同:
*len(listing_seattle) == len(calendar_seattle)//365
>> True*
因此,我们在两个数据帧中都有相同数量的列表 (属性),并且 calendar.csv 对于每个列表都有 365 个条目。现在我们可以通过listing _ id来 合并两个数据集,以获得一个数据帧用于进一步分析。合并代码:df = pd.merge(calendar_seattle, listing_seattle, on=’listing_id’)
数据准备
理解数据后,需要对其进行整理,以便为建模做好准备。我已经选择了一些商业话题来玩,回答相关的现实问题是下一个任务。为此,清理与所选任务相关的数据非常重要。以下各列是额外的负担(与分析无关),因此 删除 它们:
使用df = df.drop(columns = columns_to_drop)
删除所有此类列。
要永久删除的列的列表
执行下面给出的数据清理步骤(操作在注释中提到):
现在数据已经准备好,可以进行分析了。
对最终数据集的洞察和分析
从这里我回答了一些商业问题。
- 什么是
***minimum***
***maximum***
***average price***
的清单(楼盘)跨市?****
**#find minimum, maximum and average price for listing
min_price = df['price'].min()
>> $10.00
max_price = df['price'].max()
>> $1650.0
mean_price = df['price'].mean()
>> $137.94**
- 数据集中给定的每个清单的
***average price***
是什么?
**#get the average price for each listing
mean_price_for_listing = df.groupby('listing_id').mean()['price']
plt.hist(mean_price_for_listing, bins=20)**
从上面的直方图我们可以断定,
*majority of listings are concentrated around* ***$50-$150***
- 平均每个房源发布的点评数是多少?
**#get the average number of reviews per listing
avg_num_reviews = df.groupby('listing_id').mean()['number_of_reviews']
plt.hist(mean_price_for_listing, bins=30)**
大部分房源都是
***concentrated around 10-180 reviews***
- 登记了多少房源
***per month***
?
**#get number of registered listings, irrespective of available or unavailable for each month
grouped_month = df.groupby(['month'])
num__listing_per_month = [len(grouped_month.get_group(i)['listing_id']) for i in range(1,13)]plt.bar(np.arange(1,13,step=1), num__listing_per_month)**
每月列表数量的条形图表示
可以看到每月注册的列表数量的趋势。可以看出,上市数量在二月、三月、四月、八月和十一月较低,因为这几个月见
*surge in number of visitors*
。
***available***
***not available***
每个月有多少个清单?******
**#get number of available and not available listings per month
num_listing_per_month = df.groupby(['month','available'])['listing_id'].unique()plt.plot(num_listings_available_per_month)**
这说明夏季可用房源数量最少,也就是说夏季是最忙的时候大部分房源都被占了!****
**plt.plot(num_listings_not_available_per_month)**
- 什么是每月
***average price***
?
**#find average price per month
average_price_by_month = df.groupby(['month'])['price'].mean()
plt.plot(average_price_by_month)**
挂牌价格在夏季和冬季(12 月)明显上涨,可能是因为可供预订的房源较少。因此
***summer and winter holidays***
是参观西雅图的***busiest times***
。
- 价格视
***Neighbourhood***
基于邻域的价格变化趋势
可以看出, 的价格因地点 (街区)而异。最高均价在
***Downtown***
处。但是对于每个社区来说,价格在夏天都会上涨,就像我们之前看到的一样。**
- 每种可容纳类型有多少个列表?
***#get total number of listings for each accommodates type(number of accommodations)
num_listing_accommodates = [len(df.groupby(['accommodates']).get_group(i)['listing_id']) for i in sorted(df['accommodates'].unique())]plt.bar(sorted(df['accommodates'].unique()), num_listing_accommodates)***
可以看到,
***2 occommodates***
有个最大列表数。****
- 每种型号 的平均价格是多少?
***grouped_accommodate_mean_price = df.groupby(['accommodates'])['price'].mean()
average_price_per_accommodate = [grouped_accommodate_mean_price[i] for i in sorted(df['accommodates'].unique())]plt.bar(sorted(df['accommodates'].unique()), average_price_per_accommodate)***
每种住宿类型的平均价格
可以看出,随着 数量的增加 价格也随之提高。这是相当明显的,越多的数量容纳的财产的价格应该更大。这也暗示了预测价格的
***great influential feature***
。**
- 什么是全年的
***occupancy rate over the time***
?
***plt.plot_date(calendar_seattle['date'].unique(), occupancy_rate, linestyle='solid', marker='None')***
可以观察到占用率 高
***summer and winter***
(过年期间)。这再次证明了夏天和冬天是***vacations in seattle***
的***busiest times***
。**
***reviews.csv***
中随时间增加的评论数是多少?******
对于此任务,让我们阅读 reviews.csv 并查看 reviews 数据。
***plt.bar(list(reviews_df['date'].unique()), num_reviews, color=np.random.rand(len(list(reviews_df['date'].unique())),3))***
评论数从 2013 年开始
***exponentially increased***
,2016 年最高。
建模
数据集是干净的。它准备应用 ML 模型进行价格预测。以价格列为因变量。使用一键编码将所有分类特征转换为虚拟变量。下面给出了根据这些数据拟合模型的步骤:
估价
均方误差作为误差分析,以及 R2 平方作为精度矩阵。**
***Random Forest MSE on **train** data: **186.944**, **test**: **211.258**
Random Forest R^2 score on **train: 0.983**, **test: 0.981*****
- 获取特征重要性
上面给出的条形图显示了对价格影响最大的
*top 15 features*
。***Number of bedrooms***
是 最重要的特征 用于预测价格!
结论
这是一个很好的分析练习,最后得出结论
- 所有的商业问题都用适当的数字来回答
- 此外,随机森林回归方程适用于数据,以获得价格,这是作为因变量。
在我的Github页面上,查看本文 中使用的完整代码。****
马德里市政办公室针对外国人的 Pandas、Matplotlib 和 follow-Spanish 课程分析
并排条形图、堆积条形图、饼图和折线图
datos.madrid.es 是 Madrid s 数据服务,包含近 500 个数据集,涵盖商业、交通、旅游、文化等广泛话题。目前,越来越多的欧洲城市提供开放的数据门户,允许公司、市民、研究人员和其他公共机构使用这些数据。
在本文中,我们采用了包含 2018 年第一学期在市政办公室参加外国人西班牙语课程的学生信息的数据集。该数据集包括关于学生的信息,如他们参加的课程级别、性别、年龄、国籍、教育水平和行政地位。
数据集(2018-1er semestre)可通过以下链接下载:
马德里移民联盟的门户网站。西班牙语课程中的人物
datos . Madrid . es提供西班牙语的数据集。因此,在开始探索性数据分析之前,我们必须将数据集翻译成英语。下面的文章解释了我们如何通过使用 Googletrans 库来轻松翻译数据集。
** [## 使用 googletrans 库翻译熊猫数据框
Googletrans 是一个使用 Google Translate API 的免费 python 库。在这篇文章中,我们解释了如何使用…
towardsdatascience.com](/translate-a-pandas-data-frame-using-googletrans-library-fb0aa7fca592)
一旦数据帧被转换,我们就准备好开始探索性数据分析。👌
探索性数据分析和数据清理
探索性数据分析包括分析数据集的主要特征,通常采用可视化方法和汇总统计。目标是理解数据,发现模式和异常,并在我们执行进一步评估之前检查假设。
我们通过使用 pandas.read_csv 函数将翻译后的文件加载到 Pandas 数据框中,并使用 pandas 可视化前 5 行。DataFrame.head 方法。
数据集包含 8 列:(1)级别,(2)性别,(3)年龄,(4)行政地位,(5)国籍国家,(6)地理区域,(7)专业类别,和(8)级别研究。
数据类型不合适和缺少值是数据集最常见的问题。通过使用 熊猫,我们可以很容易地分析这两者。DataFrame.info 方法。该方法打印关于数据帧的信息,包括列类型、非空值的数量和内存使用情况。
数据集不包含空值,数据类型是预期的类型。正如我们所看到的,列 age 有一个数据类型 string。这种数据类型是正确的,因为年龄是以范围给出的。
正如我们所观察到的,列名有空格和大写字母。我们修改这些名字,用下划线代替空格,用小写字母代替大写字母,用 熊猫。data frame . rename方法。现在,不仅可以使用方括号,还可以使用点符号来访问列。
我们观察每一列中的独特元素,以发现不一致和重复的条目。
如上所示,对于同一元素(man 和 Man),列 sex 有两个命名。此外,使用 googletrans 翻译数据框后,一些条目以大写字母开头(例如,高中、小学或员工),而其他条目以小写字母开头(例如,学术、未受教育或学生)。
我们可以通过将每个条目的第一个字母转换成大写字母来一次性解决这两个问题,如下所示:
现在,数据帧中的每个条目都以大写字母开头。我们做了这个修改,因为我们不希望未来的可视化包含以大写字母和小写字母开头的标签。此外,我们希望用 man 替换 Man,这样数据帧的 sex 列中只包含两个唯一值:Man 和 Woman。
我们可以观察到列 age 包含条目 65。澄清这是指 65 岁的学生,还是 65 岁以上的学生(对我来说更有意义,因为年龄是以范围给出的)会很有意思。
数据清理完成!!😍现在,我们准备好回答问题,并使用我们的数据得出结论。
回答问题并得出结论
****探索性数据分析和数据清理是让我们对数据集有所了解的步骤,并让数据集准备好使用它轻松得出结论。现在!我们准备使用数据集回答以下问题。
2018 年第一学期,有多少学生在市政府办公室参加了外国人西班牙语课程?****
我们必须计算行数以获得学生数,因为数据框中的每一行都包含一个学生的信息。这可以通过 熊猫轻松实现。data frame . shape属性为:****
2018 年第一学期,2274 名学生参加了马德里市政办公室为外国人开设的西班牙语课程。
女生的比例是多少?
为了获得雌性的百分比,我们可以雇佣 熊猫。series . value _ counts函数。该函数返回包含唯一值计数的序列。如果我们想获得频率而不是计数,我们使用参数 normalize=True。
正如我们所观察到的,女性的比例大于男性。我们还可以通过以下方式使用条形图来可视化结果:
每个级别招收多少学生?性别之间有差异吗?地理区域之间有差异吗?
为了获得每个级别的注册学生人数,我们将使用 熊猫。Series . value _ counts的功能和以前一样,但是这一次,我们用 熊猫按字母顺序对返回的系列的索引进行排序。series . sort _ index函数,因为字母顺序匹配的难度越来越高(A1 比 A2 容易)。****
A2 DELE(获得西班牙国籍的考试)、B1 会话和识字(学习读写)等特殊课程的学生人数少于常规课程(A1、A2 和 B1)。然而,高级课程(B2)的参与者比其他常规课程少。
为了按级别和性别分析学生人数,我们使用函数 pandas。data frame . group byT15。该功能涉及分割对象、应用功能和组合结果的某种组合。我们可以根据在列表中提供名称的两个特征进行分组,如下所示:
我们获得了一个多索引数据框,因为按两列分组将得到两个索引。我们的目标是使用这个包含按级别和性别划分的学生人数的数据框,并使用函数 pandas 创建一个并排条形图。DataFrame.plot
我们选择一列(如年龄),因为所有列都提供相同的信息(计数)。然后,我们用 熊猫。data frame . un stack函数。该函数旋转一层(必须是分层的)索引标签,返回具有新一层列标签的数据帧,其最内层由旋转的索引标签组成。
现在,我们可以使用绘图功能轻松创建并排条形图。每一列都分配有不同的颜色,每一行都沿水平轴嵌套在一个组中。
正如我们所看到的,更多的妇女注册了正规课程(A1、A2 和 B1)。然而,参加 A2 DELE 和扫盲课程的男性人数更多。
为了按级别和地理区域分析学生人数,我们像以前一样创建一个并排的条形图。
在 A1、A2、B1、B1 会话和 B2 课程中,大多数学生都是亚洲人。相反,A2 DELE 和扫盲班有更多来自马格里布和撒哈拉以南非洲的学生。
学生的行政身份是什么?
我们创建了一个条形图,根据管理状态来可视化学生的数量。在这种情况下,我们采用一个水平条形图,用标签显示学生人数。
如上图所示,大部分学生处于不正常的行政状况(763)。略多于 500 名学生拥有居留和工作许可(条款:居留和工作许可);266 名学生拥有居留证(A R:autoriza ción de residencia)。寻求庇护的学生人数达到 91 人。****
如果我们希望标签显示百分比而不是学生人数,我们可以按以下方式修改图表:
方法熊猫。Series.round 将序列中的每个值舍入到给定的小数位数(默认为 0)。在这种情况下,我们提供一个标签,四舍五入到两位小数,代表每个管理状态的学生百分比。如上所示,这些标签以粗体显示。我们可以通过在matplotlib . py plot . text函数中包含参数 weight=bold 来轻松实现这一点。
到目前为止,我们只使用了条形图来获得结论,但是我们可以使用其他类型的可视化。其中一个选择是饼图。一个饼状图是一个圆形的图形,它被分成若干片来说明数字比例。在此图表中,切片的弧长与它所代表的数量(如条形图中的高度)成比例。
我们可以用熊猫来制作一个饼图。DataFrame.plot 函数,以如下方式提供参数 kind='pie' :
auto pct = ' % 1.1f % % '参数使用 Python 字符串格式显示百分比值。我们使用的另一个参数是 颜色。 该参数决定饼图循环的 matplotlib 颜色参数的顺序。在这种情况下,选择的色彩映射表是 Pastel2。
正如我们所观察到的,条形图和饼图可以传达相同的信息。然而,条形图是可视化的更好选择,因为沿一维(高度)比沿二维(面积)比较对象更容易。
现在!是时候继续用数据回答问题了。如上所示,33.6%的学生处于不正常的行政状况,只有 4%的学生处于庇护状态。让我们试着获得更多关于这两个群体的信息!
处于非正规行政状况的学生来自哪里?他们注册了哪些课程?还有精神病院的学生?
为了评估这两个组,我们必须根据列 administrative_status 的值过滤数据框。我们创建了两个数据框,包含以下信息:(1)处于非正常情况下的学生,(2)处于庇护中的学生。
我们用 熊猫。Series.unique 方法检查过滤是否正确进行。
我们做得对💪 💚!Df _ unregular仅包含处于非正常管理状态的学生的信息,而 df_asylum 包含处于庇护状态的学生的信息。**
首先,我们分析非正常学生和庇护学生的国籍。
如上所示,大多数处于非正常状况的亚洲学生是女性;然而,大多数撒哈拉以南非洲学生是男性。没有来自北美和欧洲联盟的非正常或处于庇护状态的学生。此外,在欧盟以外的欧洲避难的学生,和马格里布只有男性。
关于级别,大多数非正常情况下的学生注册参加 A1 和 A2 级别的低级别课程(58.72%),相比之下,寻求庇护的学生注册参加 A1 和 A2 级别的程度较低(38.46%)。参加扫盲班的学生比例几乎相等(大约 10% )。
学生们多大了?是层次之间的差异吗?
为了获得学生的年龄,我们可以使用 熊猫。Series.value_counts 这可以通过 熊猫来实现。series . reindex方法,传递一个带有新标签(索引)的列表作为参数。
可以看出,90%以上的学生年龄在 18-50 岁之间。不清楚 65 岁是指 65 岁以上的学生(这是有意义的,因为年龄是以范围提供的)还是确切的 65 岁。
根据级别,A2 DELE 课程(获得西班牙国籍的考试)主要由 31 至 50 岁的学生参加。在其他级别(A1 除外),18 至 30 岁和 31 至 50 岁学生的比例相当接近(见下图)。**
而现在!我们最后一个问题🍀
学生从哪里来?
为了回答这个问题,我们不打算像以前一样使用条形图,而是使用另一个有趣的可视化工具:cloropletes maps。****
choropleth 地图是一个专题地图,根据地图上显示的统计变量(如学生人数)对区域进行着色。这种可视化非常有助于通过使用连续颜色方案(测量值越高,颜色越强)来表示一个区域内测量值的可变性。
为了创建一个 choropleth 地图,叶子需要一个 Geo JSON 文件,包括该地区的地理空间数据。对于世界地图,我们需要一个 Geo JSON 文件来定义世界上所有国家的边界。您可以通过以下链接下载该文件:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/python-visualization/folium/blob/master/examples/data/world-countries.json)
将文件移动到当前目录后,我们可以使用 json.load() 方法从 json 库中读取 json 对象,如下所示:
如上图所示, json.load() 方法返回一个名为 data 的 python 字典。我们使用内置模块 pprint 以可读性更好的方式打印字典数据。正如我们所看到的,文件 world-countries.json 提供了多边形,定义了世界各国的边界。
我们正在读取并可视化 world-countries.json 文件,以便对数据的结构有所了解。然而,当使用flour,创建一个 cloropleth map 时,我们只需提供到 GeoJSON 文件的路径,这意味着不需要像上面那样使用 json 模块读取文件。
现在!我们准备用叶子了!💪 🌎
leav是一个 python 库,可以在传单地图上实现迭代可视化。在生成克洛普勒斯图之前,我们必须创建一个数据框,包含来自每个国家的学生人数,如下所示:
此外,要成功绑定数据框和 json 文件,数据框中的国家名称必须与 json 文件中的国家名称完全匹配。因此,我们必须分析数据框中的哪些名称没有包含在 json 文件中,并对其进行相应的修改。
如上所示,json 文件中没有下列名称:(1)尼泊尔联邦民主共和国,(2)阿拉伯叙利亚共和国,
(3)大不列颠及北爱尔兰联合王国,(4)撒哈拉,(5)摩尔多瓦共和国,(6)佛得角,(7)巴勒斯坦,(8)新加坡和(9)马耳他。现在,我们修改数据框,用 json 文件中可用的名称替换这些名称。
关于之前的修改,必须考虑以下方面:
- json 文件中没有马耳他和佛得角;因此,它们的名称不会被修改,也不会绘制在克洛普勒斯图上。
- 新加坡被马来西亚取代,因为在 json 文件中,新加坡边界包含在马来西亚多边形中。这是不准确的,因为他们是不同的国家!
- 撒哈拉被西撒哈拉取代。这也是不准确的,因为撒哈拉的面积比西撒哈拉大。
- 该修改适用于以下情况:尼泊尔、叙利亚、英国、摩尔多瓦和西岸。
现在!我们已经准备好创建克洛普勒斯图了!🙌 😄
首先,我们创建一个叶子地图对象,以[0,0]为中心(位置参数允许将地图居中在一个特定的位置)。我们还提供了一个初始缩放级别为 2 的来将地图缩放到中心。然后,我们使用来显示一个云图。cloropleth()** 法。此函数绑定包含在 Pandas 数据框和 GeoJSON 几何图形中的数据。**
要生成地图,将使用以下参数:
- geo _ data→JSON 文件的名称。该文件必须位于工作目录中。
- 数据→ 包含数据的数据帧的名称。
- 列→ 用于生成克洛普勒斯图的列。
- key _ on→JSON 文件中包含国家名称的 Key。
- 填充颜色→ 可视化中使用的颜色方案。
正如我们所看到的,图例显示了一个负边界(-3)。这个问题可以通过用 numpy.linspace()函数定义我们自己的边界来解决,如下所示:
学生主要来自菲律宾和摩洛哥,这是有道理的,因为这两个国家都是西班牙的殖民地,目前西班牙语不是该国的官方语言。我们也可以观察到,有相当数量的学生来自中国、尼泊尔和巴西。此外,没有来自澳大利亚、北欧国家和大多数拉丁美洲国家的学生。
我们不能用柱状图来直观地显示学生的数量,因为学生来自 74 个不同的国家。但是,我们可以显示前十个国家,如下所示:
最后,我们将绘制一张欧洲的克洛普勒斯地图🌐
首先,我们创建一个数据框,包含来自每个欧洲国家的学生人数,如下所示:
然后,我们分析数据框中有哪些名字是 europe.geojson 文件中没有的,并进行相应的修改。
我们可以通过以下链接下载 europe.geojson 文件:
permalink dissolve GitHub 是 4000 多万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/leakyMirror/map-of-europe/blob/master/GeoJSON/europe.geojson)
最后,我们创建一个树叶贴图对象,以【53.0,9.0】为中心,显示一个树叶贴图和。cloropleth() 方法和我们前面做的一样。
💪我们拿到了。
据我们观察,学生主要来自乌克兰、俄罗斯、罗马尼亚、格鲁吉亚和保加利亚。
根据性别或课程水平绘制克洛普勒斯图也将是有趣的。如你所见,分析可以是无止境的!我鼓励你生成更多的情节,利用这个公开的数据,尝试提取更多的结论!不过现在有些推荐:)
推荐
如果你想学习如何用 Python 创建有趣的可视化效果,请学习这门课程!它是完全免费的,你可以从基础的可视化学到高级的可视化。💪
编辑描述
courses.cognitiveclass.ai](https://courses.cognitiveclass.ai/courses/course-v1:CognitiveClass+DV0101EN+v1/info)
此外,您还可以阅读我以前的一些使用开放数据执行的文章😊 😉
[## 使用 Pandas、Matplotlib 和 lyum 分析巴塞罗那的车祸
巴塞罗那开放数据是巴塞罗那的数据服务,包含约 400 个数据集,涵盖广泛的主题,如…
towardsdatascience.com](/analysis-of-car-accidents-in-barcelona-using-pandas-matplotlib-and-folium-73384240106b) [## 啤酒节:使用 Pandas、Matplotlib 和 Plotly 进行快速分析
2019 啤酒节已经开始了!慕尼黑啤酒节是世界上最大的啤酒节,自…年起每年在慕尼黑举行。
towardsdatascience.com](/oktoberfest-quick-analysis-using-pandas-matplotlib-and-plotly-79778367a4c)
感谢阅读!!!🍀🍀🍀🍀🍀🍀🍀
阿曼达******
理解线性回归的解析和几何方法
从解析角度和几何角度深入研究线性回归
(图片由作者提供)镜子,镜子,在墙上,谁是所有人中最小的正方形?
什么是线性回归?
在一个实验中,我们观察一些特征或属性的值。我们希望根据观察到的特征预测一个目标变量的值。线性回归试图推测特征和目标之间的线性关系。
让我们借助一个分析天气的例子来理解线性回归试图解决什么问题。假设我们有日平均温度 T ,风向 W ,以及每天日照总分钟数 S 。这些将是我们的特色。我们想预测每天的降雨量。这将是我们的目标变量。
我们试图找到 P,T,W,S 之间的线性关系。也就是说,我们希望找到 θ ₀ ,θ ₁ ,θ ₂ ,θ ₃,以便
抽象出线性回归
假设我们有超过天的天气数据。对于第 i 天,我们将那天的特征值 T,w,S 收集成一个行向量 x ᵢ = ( x ᵢ, x ᵢ, x ᵢ)。当天的降水值成为目标值 y ᵢ.
抽象出这个设置,我们可以假设给定了数据点 x ₁ ,x ₂ ,… x_n ,其中每个数据点 x ᵢ具有kt52】特征并且具有目标 y ᵢ.也就是说,每个数据点 x ᵢ看起来像行向量**
我们感兴趣的目标变量的值为数据点 x ᵢ.的 y ᵢ
线性回归试图找到数据点 x ᵢ和它们的目标 y ᵢ.之间的线性关系也就是说,我们想要找到实数 θ ₀ ,θ ₁ ,θ ₂ ,θ₃……θ_ k,这样对于每个 i ,我们都有**
为一致性引入虚拟特征:₀θ在没有绑定特征 x ᵢ⁰的情况下非常突出,因此为了使其一致,我们为每个数据点 x ᵢ.引入虚拟特征 x ᵢ⁰= 1 也就是说,每个数据点 x ᵢ现在看起来像行向量**
所以我们想找到实数 θ ₀ ,θ ₁ ,θ ₂ ,θ₃……θ_ k,这样对于每个 i ,我们就有了**
矩阵方程
让我们把 θ ₀ ,θ ₁ ,θ ₂ ,θ₃……θ_ k捆绑成一个列向量 θ ,把 y ₁ ,y ₂ ,… y_n 捆绑成一个列向量 Y 和行向量**
那么同时求解上面的 n 线性回归方程就等同于求解矩阵方程 X θ = Y
使用最小二乘法的近似解
不幸的是,你可能并不总能准确地解决这个线性方程组。然后我们的目标是一个近似解,它在以下意义上是其他近似解中最好的:**
让xθ=ŷ_θ。也就是说,我们对目标变量的预测值是[]ŷ_θ。我们希望我们的预测尽可能接近真实情况。所以我们希望ŷ_θ尽可能的接近 Y 。也就是说,我们希望范数| |y-ŷ_θ||最小。**
因为这与要求| |y-ŷ_θ||最小化是一样的,我们想要最小化下面的平方和**
也就是说,我们想要矩阵方程 X θ = Y 的最小二乘解**
分析方法
如果你对多变量导数感到不舒服,直接跳到几何方法!
注意 Aᵀ是一个矩阵 a 的转置由于 θ ᵀ X ᵀ Y 是 a1×1 矩阵[ ],θᵀxᵀy=(θᵀxᵀy)ᵀ.因此**
由于 Yᵀ Y 不依赖于 θ ,我们不妨最小化以下函数
相对于 θ 取梯度,我们得到
请记住,我们希望梯度为 0,因为我们试图找到极值 f ( θ) 。所以我们想要 2xᵀy—2xᵀxθ= 0。****
也就是说,我们希望 θ 使得xᵀxθ= xᵀy .****
正规方程
矩阵方程xᵀxθ= xᵀy被称为xθ= y的 正规方程 从我们上面的讨论中,应该或多或少地清楚,正规方程的解 θ 给出了 Xθ = Y 的最小二乘解。**
这很好,但是我们如何知道正规方程的解实际上存在?我们如何检查我们得到的极值实际上是最小值?这些当然可以通过进一步的计算显示出来。相反,我们提出了一种几何方法,它完全避免了导数,并使用一些几何观点来推导正规方程,并显示最小二乘解的存在!**
几何方法
回忆..
让我们回到方程 Xθ = Y 。由于我们不能总是直接解这个方程,我们满足于一个近似解 θ 使得 Xθ ≈ Y 。如果我们定义ŷ_θ=xθ,那么在所有可能的近似解 θ 中,我们要挑选一个使得| |y-ŷ_θ||最小的。**
让我们考虑 θ所有可能值的空间。这只是 R ^{k+1},即 θ 可以是任意 k+1 列向量。现在让我们看看集合 V ,它包含了所有可能的预测ŷ_θ。也就是说,**
让我们将 X 视为一幅线性地图
即 X 是从可能的 θ s 的空间到目标变量所有可能值的空间的线性映射。
那么 V 就是 X 的形象。特别地,它是ⁿ.的子空间重申一下, R ⁿ是目标变量所有可能值的空间, Y 是我们试图达到的目标变量的特定值, V 是我们所有可能预测的子空间。
现在,如果 Y 位于 V 中,我们就能准确无误地找到解决 θ 的方法,它实际上解决了 Xθ = Y ..如果不能,我们就试着在 V 中找到距离 Y 最近的矢量ŷ_θ**。****
(图片由作者提供)几何方法
在最接近给定目标的子空间中寻找向量
V 是 R ⁿ的子空间,而 Y 是 R ⁿ.中的给定向量我们想在距离 Y 最近的 V 中找到ŷ_θ。我们如何做到这一点?
让我们想象一下这些矢量,还有矢量y-ŷ_θ。请记住,我们正努力使 y-ŷ_θ||的规范尽可能的小**
(图片由作者提供)可视化投影
由于点到子空间的最短距离是从点到子空间的垂线,我们的目标是使y-ŷ_θ垂直于 V !注意,这和说最接近的预测ŷ_θ简单来说就是 Y 到 V 的 正交投影 是一回事。**
图像、内核和转置
现在在线性地图的图像和它的转置ᵀ.的内核之间有了一个非常好的 relation[⁴垂直于图像的向量( X )实际上在 X ᵀ的内核中,反之亦然。在符号中,这写为
现在我们希望y-ŷ_θ垂直于 V = Image( X )。所以我们希望 y-ŷ_θ在ᵀ.的内核中也就是说,我们想要**
瞧啊。我们想要正规方程 X ᵀ Xθ = X ᵀ Y 的解 θ
正规方程的解
几何方法立即告诉你为什么法线方程xᵀxθ= xᵀy有解 θ 。这是因为(我们已经搞清楚了)当xθ=ŷ_θ是 Y 到 V =Image( X )的正交投影时, θ 就是精确解。**
于是回溯,取 Y ,投影到 V =Image( X )。对于某些 θ ,投影必须看起来像 Xθ ,因为投影在图像子空间 V 中。那个 θ 是正规方程的一个解,因此是我们正在寻找的方程 Xθ = Y 的最小二乘解!
最小二乘解的唯一性
有一点我们忽略了,即是我们所追求的 Xθ 的独特之处吗?使用我们的几何方法, Y 到 V (也就是ŷ_θ)的投影是独一无二的。但是可能有几个 θ 使得xθ=ŷ_θ.****
但进一步假设, X 是一个内射映射,即它有零核,那么我们得到的 θ 是唯一的。而且实际上,原来【⁵】如果 X 是内射的,那么 X ᵀ X 也是内射的。由于 X ᵀ X 是一个方阵,这意味着 X ᵀ X 是可逆的。因此,我们实际上可以求解 θ 如下:**
摘要
方程 Xθ = Y 的最小二乘解 θ 与 正规方程xᵀxθ= xᵀy .的解相同*
*正规方程总是至少有一个解。而进一步如果 θ 是一个解,那么 Xθ 这个最接近的预测就是 Y 到图像( X )的正交投影。
*法线方程可能有多个解,因此可能有多个最小二乘解。然而,如果 X 是内射的(即具有零核),则解是唯一的,并且由下式给出
脚注
[ ]:让
[]:θᵀxᵀy是 an (1 x (k+1))((k+1) x n)(n x 1) = 1 x 1 矩阵
[ ]:距离ŷ_θ和 Y 是| |y-ŷ_θ||*
【⁴和⁵]:关于这个事实请查阅你喜欢的线性代数教科书***
Oracle 中的分析功能
本文通过概念构建练习 帮助理解分析函数的工作和用法
斯蒂芬·菲利普斯-Hostreviews.co.uk 在 Unsplash 上的照片
分析函数用于对多行数据进行“分析”,并返回当前行的结果。 例如,分析函数可用于找出运行总数、对行进行排序、对前一行或即将到来的行进行汇总等。虽然通过使用标准聚合函数和使用连接和子查询的原生 SQL 可以实现相同的功能,但是分析函数使它更加简单和快速。Oracle 在 Oracle 8.1.6 中引入了 26 个分析功能。
我们将使用下面的脚本来创建样本数据:
CREATE TABLE DEPT
(
DEPTNO NUMBER(2),
DNAME VARCHAR2(14 CHAR),
LOC VARCHAR2(13 CHAR)
);Insert into DEPT
(DEPTNO, DNAME, LOC)
Values
(10, ‘ACCOUNTING’, ‘NEW YORK’);
Insert into DEPT
(DEPTNO, DNAME, LOC)
Values
(20, ‘RESEARCH’, ‘DALLAS’);
Insert into DEPT
(DEPTNO, DNAME, LOC)
Values
(30, ‘SALES’, ‘CHICAGO’);
Insert into DEPT
(DEPTNO, DNAME, LOC)
Values
(40, ‘OPERATIONS’, ‘BOSTON’);
COMMIT;CREATE TABLE EMP
(
EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR2(10 CHAR),
JOB VARCHAR2(9 CHAR),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7,2),
COMM NUMBER(7,2),
DEPTNO NUMBER(2)
)Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7369, ‘SMITH’, ‘CLERK’, 7902, TO_DATE(‘12/17/1980 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
800, NULL, 20);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7499, ‘ALLEN’, ‘SALESMAN’, 7698, TO_DATE(‘02/20/1981 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
1600, 300, 30);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7521, ‘WARD’, ‘SALESMAN’, 7698, TO_DATE(‘02/22/1981 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
1250, 500, 30);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7566, ‘JONES’, ‘MANAGER’, 7839, TO_DATE(‘04/02/1981 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
2975, NULL, 20);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7654, ‘MARTIN’, ‘SALESMAN’, 7698, TO_DATE(‘09/28/1981 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
1250, 1400, 30);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7698, ‘BLAKE’, ‘MANAGER’, 7839, TO_DATE(‘05/01/1981 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
2850, NULL, 30);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7782, ‘CLARK’, ‘MANAGER’, 7839, TO_DATE(‘06/09/1981 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
2450, NULL, 10);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7788, ‘SCOTT’, ‘ANALYST’, 7566, TO_DATE(‘12/09/1982 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
3000, NULL, 20);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7839, ‘KING’, ‘PRESIDENT’, NULL, TO_DATE(‘11/17/1981 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
5000, NULL, 10);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7844, ‘TURNER’, ‘SALESMAN’, 7698, TO_DATE(‘09/08/1981 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
1500, 0, 30);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7876, ‘ADAMS’, ‘CLERK’, 7788, TO_DATE(‘01/12/1983 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
1100, NULL, 20);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7900, ‘JAMES’, ‘CLERK’, 7698, TO_DATE(‘12/03/1981 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
950, NULL, 30);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7902, ‘FORD’, ‘ANALYST’, 7566, TO_DATE(‘12/03/1981 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
3000, NULL, 20);
Insert into EMP
(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
Values
(7934, ‘MILLER’, ‘CLERK’, 7782, TO_DATE(‘01/23/1982 00:00:00’, ‘MM/DD/YYYY HH24:MI:SS’),
1300, NULL, 10);
COMMIT;
分析函数和聚合函数的区别
威尔·弗朗西斯在 Unsplash 上拍摄的照片
聚合函数对行进行分组,并返回整个结果集的输出。但是,分析函数会返回聚合输出,但不会对结果集进行分组。它们返回结果集中每一行的值。
例如,如果我们必须从 employee 表中找出部门编号的计数,我们将使用聚合函数编写以下查询:
**SELECT deptno,COUNT(*) dept_cnt
FROM emp
GROUP BY deptno;**
结果如下:
因此,对于每一行(即每个部门),我们得到计数。
使用分析函数,查询将被写成:
**SELECT deptno,
COUNT(*) OVER (PARTITION BY
deptno) DEPT_COUNT
FROM emp**
输出如下所示:
这里,结果是 emp 表中的每一行。
因此,在使用聚合函数时,我们不能包含任何非分组依据列,但是在使用分析函数时,您可以这样做。例如,下面的查询将返回一个错误:
SELECT empno,deptno,COUNT(*) dept_cnt
FROM emp
GROUP BY deptno;
但是使用解析函数,就不会面临这种错误。
SELECT empno,deptno,
COUNT(*) OVER (PARTITION BY
deptno) DEPT_COUNT
FROM emp
输出将是:
语法:
分析函数的一般语法是:
函数(arg1,…,argn) OVER(【分区由< … >)【排序由< …)。>][
我们一部分一部分的解剖吧。
结束:
分析函数的范围是在 OVER 子句中定义的。对于所有分析功能,OVER 是强制的。如果您在 OVER 之后没有给出任何参数,它将假定范围为 ALL。因此,以下查询将计算整个表中部门的数量:
**SELECT deptno,
COUNT(*) OVER() DEPT_COUNT
FROM emp**
分区依据:
正如聚合函数使用 GROUP BY 对行进行分组一样,分析函数使用 PARTITION BY。例如,如果我们希望找出每个部门的最高工资和每个工作类型的最高工资,我们可以编写如下查询:
SELECT
ename,
sal,
job,
deptno,
max(sal) over (partition by deptno) max_sal_deptno ,
max(sal) over (partition by job) max_sal_job
FROM emp
在这里,我们按 deptno 进行了分区,以找出最高工资,并将其显示在 max_sal_deptno 列中。类似地,我们按职务进行了划分,以找出最高工资,并将其显示在 max_sal_job 列中
如果我们分析 emp 表的数据,很容易发现 10 部门的最高工资是 5000,20 部门是 3000,30 部门是 2850。
同样,对于工作类型的职员,最高工资是 1300,总裁是 500,经理是 2975,分析师是 3000,销售员是 1600。
排序依据:
它用于指定所选分区中记录的顺序。这不同于 WHERE 之后的主查询的 ORDER BY 子句。
窗口条款:
partition 子句不是限制分析函数范围的唯一方法。我们可以使用“ROWS BETWEEN”或“RANGE BETWEEN”子句来定义一个额外的范围。这在“窗口”一节中有明确的解释
一些常用分析函数的工作和用法:
一些常用的分析函数如下:
a .行数:
ROW_NUMBER 为一组记录提供一个连续的序列号。这里,ORDER BY 子句在枚举行时起着至关重要的作用。例如,如果您想返回每个部门中第二个被雇用的员工,您可以编写如下查询:
**select
ename, deptno,hiredate
from
(
SELECT
ename,
hiredate,
deptno,
row_number() over (partition by deptno order by hiredate) rn
FROM emp
) where rn=2**
输出是:
这里,我们按 deptno 对行进行了分区,并按 hiredate 进行了排序。函数的作用是:为所有的行分配一个序列号,从 1 开始,代表所有按 hiredate 排序的部门。对于新部门,编号将从 1 重新开始。内部查询执行此操作。内部查询的输出如下所示。(最后需要的行用红色标记)
外部查询现在选择 rn=2 的那些行,以给出我们想要的结果。
b. 等级:
等级分析函数还为一组以特定方式排序的行提供一个序列号,如 ROW_NUMBER。但是,不同之处在于:ROW_NUMBER 为每一行赋予一个唯一的编号,即使这些行是重复的。但是 RANK 对重复行给出相同的编号。
因此,在我们的 emp 表中,如果两个雇员有相同的雇佣日期,那么 RANK 函数将为每个重复的行给出相同的数字。查看以下查询的结果:
**SELECT
ename,
hiredate,
deptno,
row_number() over (order by hiredate) rn,
rank() over( order by hiredate) rank_num
FROM emp**
由于 JAMES 和 FORD 的雇佣日期相同,ROW_NUMBER 为他们指定了不同的编号,而 RANK 为他们指定了相同的编号。
c. 密 _ 秩
DENSE_RANK 的工作方式与 RANK 类似。唯一的区别是,在分配给重复行时,它不会跳过数字。检查以下查询的结果,了解 RANK 和 DENSE_RANK 函数之间的区别:
**SELECT
ename,
hiredate,
deptno,
rank() over(order by hiredate) rank_num,
dense_rank() over( order by hiredate) dense_rank_num
FROM emp**
詹姆斯和福特的雇佣日期相同。因此,对于等级和密集等级,两行都被分配编号 10。但是在等级的情况下,米勒的下一行被分配 12,而在密集等级的情况下被分配 11。
d .超前和滞后
LEAD 允许我们对下一行(当前行之后的行)应用任何计算。LEAD 函数的一般语法是:
LEAD( <表达式>,<偏移>,<默认> ) over( <解析子句> )
在哪里
<表达式> 是应用于前导行的表达式
<偏移量> 是相对于当前行的第一行的数量(可以是 1,2…..)
<默认> 是当<偏移量>指向分区范围外的行时返回的值
LAG 的语法完全一样。LAG 中的<偏移量>指向相对于当前行的前几行。
假设我们必须找出部门 10 先前较低的薪水和下一个较高的薪水,查询将是:
**SELECT
ename,
sal,
lead(sal,1,0) over(partition by deptno order by sal desc) next_low_sal,
lag(sal,1,0) over(partition by deptno order by sal desc) prev_high_sal
FROM emp
where deptno=10**
结果是:
e .第一个值和最后一个值
在由 partition 和 order by 子句定义的记录集下,如果我们必须选取第一条记录,可以使用 FIRST_VALUE 函数。同样,在由 partition 和 order by 子句定义的记录集下,如果我们必须挑选最后一条记录,可以使用 LAST_VALUE 函数。比方说,如果我们必须找出部门 10 的每个雇员的第一次雇用和当前雇用日期之间的天数,则查询可以写成如下形式:
**SELECT
ename,
sal,
hiredate-first_value(hiredate) over(order by hiredate) no_of_days
FROM emp
where deptno=10**
结果是:
窗口条款
partition 子句不是限制分析函数范围的唯一方法。我们可以使用“ROWS BETWEEN”或“RANGE BETWEEN”子句来定义一个额外的范围。
<window_clause>的一般语法是< start_expr >和
T28【行或范围】</window_clause>
< start_expr > 可以是以下任意一个
无界 PECEDING
当前行
< sql_expr >之前或之后。
< end_expr > 可以是以下任意一个
无界跟随或
当前行或
< sql_expr >之前或之后。
让我们编写一个查询,给出前几行相对于当前行的最高工资。
**SELECT
ename,
hiredate,
sal,
max(sal) over(order by hiredate,ename
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) max_before_sal
FROM emp**
这里,对于每一行,返回当前行之前的最高工资。这里的 ORDER BY 子句不用于排序,而是用于指定窗口。无界在前是最低的可能界限,即第一行。
检索当前行之前或之后的行,n 在前或 n 在后,其中 n 是相对于当前行的位置。在我们的例子中,n 是 1。
范围与行非常相似,但范围中的间隔不是行数。它们代表一定范围的值,可以是数字或日期值。
Oracle 的分析功能是非常强大的工具,可以在多个维度上汇总和分析数据。执行速度也比普通的聚合函数快得多。对于 Oracle 开发人员来说,了解这些功能无疑是额外的收获。
分析、数据科学和统计:
什么是分析?什么是数据科学?什么是统计学?
一朵玫瑰,不管它叫什么名字…
我想在数据科学、统计学或一般来说的分析媒体上发表另一种声音,以拓宽视角,增加关于这一主题的丰富对话。虽然我的意图是让这个充斥着数据和分析及其不同词汇的世界更加清晰,但毫无疑问,我也会给这个广阔的话题带来一些困惑和不和谐。这就是数据和分析领域的现状。如果没有别的,也许我可以带来一些更好的理解,或者至少是一个补充的理解,关于数据和分析的学科和实践的新兴多样性。
首先,我认为大多数对分析和数据科学的描述都过于狭隘,一种更具包容性的方法将有利于社区。事实上,由于大多数数据科学实际上是关于数据分析的,我们是否可以受益于一个更宽泛的名称——数据分析科学和数据分析科学家?第二,我认为统计学作为一门学科经常被视为数据科学之外的东西,只被归为严格的分析。此外,统计学家经常被描述为假设检验、产生 p 值的数据处理者。对于我为 Medium 写的第一篇文章,我将扩展第一个主题,并希望开始消除第二个主题,尽管后者将需要更多的文章。
那么,我从哪里开始呢?好吧,让我们从一些定义开始。
1。 分析放大
首先,对我来说,我认为术语“分析”是一个广泛的、包容的术语。分析是指使用数学来分析数据或建立模型来解决现实世界的问题。它包括使用数学方程式、算法、逻辑、计算机代码来工作的人。这是我作为礼来公司公司高级分析科学负责人的观点,直到我 2017 年退休。我雇佣、合作和管理具有各种分析学位的专业人士,包括统计学(数学统计、生物统计、商业统计)、数学、运筹学、计算化学、经济学、计算机科学和 ML/AI。这些技能和能力的互补性质鼓舞人心,当然“整体”大于“部分”的总和
在我们公司还有其他分析学科,我和其他人认为它们是“分析社区”的一部分,我对此没有直接责任,但与我们的高级分析团队合作。其中包括:
****流行病学家和健康结果研究人员,他们主要在观察数据空间工作,以评估疾病的自然史和药物/生物治疗的真实结果;
****药物计量学专家,他们建立药物与生物体(动物和人类)相互作用的药代动力学和药效学模型,以预测最佳给药方案、药物相互作用和治疗的临床效果;
****系统生物学家,他们在组织和细胞水平上创建疾病的数学模型,以阐明新分子实体的潜在积极和消极影响及其生物作用机制;
****生物信息学家,他们将遗传学、疾病和分子生物学数据库中的信息联系起来,寻找疾病过程中可能涉及的生化途径,以便其他科学家可以设计分子、抗体或其他治疗方法来阻止疾病;
****计量经济学家,他们建立微观和宏观经济模型来描述我们的世界并预测未来可能的结果。
分析领域既广又深!
(无摄影师署名)https://dlpng.com/png/6767898(仅供个人免费使用)
受过良好教育的专业人员执行这种广泛的数据分析工作,每个人都有一个特殊的工具集和知识库,不可避免地源于数学。有些人知道微分方程,有些人知道概率分布理论,有些人将他们的数学技能与深厚的生物或医学知识相结合,有些人知道商业,金融或市场营销,有些人知道优化算法,有些人知道建模和模拟,有些人知道各种深度学习方法,有些人拥有高超的编码技能。
旁注 1:我必须说,在制药行业工作并领导一个非常有才华的高级学位数据分析科学家团队是一次拓展思维的经历,也是一种真正的快乐。相信我,在这些队伍中,即使有,也是非常少的刻板的书呆子或后台数字处理者。这些人理解数学,参与科学/商业问题、策略和问题,解释他们的发现,并以商业伙伴可以理解的语言交流他们的结论。
旁注 2:我使用的短语是 数据 分析型科学家,因为在科学界,“分析型科学家”这个术语已经被生物/化学人群所采用。这些人执行复杂的化验,例如,确定流体的化学成分(例如,药物 X 在血浆中的浓度)。由于他们通常被称为分析化学家或生物分析化学家,我将使用术语 数据 分析科学家来区分上面在我的分析“大帐篷”中提到的学科。
旁注 2:在我早期涉足更广泛的分析领域时,我并没有意识到上述区别。当我第一次成为礼来公司高级分析部门的领导时,我开始接到猎头的电话(我们都是这样),告诉我其他制药公司领导化学部门的工作机会。我常常困惑地说:“你一定是打错电话了,或者找错人了。无论如何,我都不是化学家。”在打了几次这样的电话后(也许我学得很慢),我意识到发生了什么。
统计
现在,为了完全公开,我是一名训练有素的生物统计学家(伴随着数学),尽管在制药行业解决实际问题几十年,我认为我的知识和观点超越了统计或统计学家的传统或刻板印象。
好的。随着我的披露澄清和我对分析的定义到位,我将进入下一个重要的定义,因为它似乎在我们目前的数据和分析世界中产生了很多困惑和恐慌。什么是统计学?尽管其他人已经对这一古老的职业做出了新的定义,特别是在“数据科学”的背景下,但我将从不同的角度来看待统计学家几个世纪以来一直在做的事情。同样,我将统计学视为数学的一个分支,我用它来对比统计学和我在下面的对联中学到的数学知识。
数学是辨别真理的科学。
统计学是一门量化什么可能是真实的科学。
谁能忘记汤姆·克鲁斯对杰克·尼克尔森大吼:“我要真相!”
(《几个好人》);阿伦·索尔金编剧;https://pbs.twimg.com/media/DUWaGNnUQAAi9Up.jpg 罗伯·莱纳
虽然关于这两种说法可以说很多,但为了简洁起见,我只提出几点。简而言之,数学是关于证明,确定性,真/假。从这个意义上说,它存在于集 {0.1} 。统计学是关于不确定性、概率/可能性和存在于真假之间灰色阴影中的证据。在这个意义上,它存在于区间 (0,1) 。**
在单位区间上捕捉到的数学与统计学的根本区别。
统计学的标志是“不确定性的量化”,它可以表示为概率、可能性、置信度或其他类似的度量。这是所有数据分析科学的关键和挑战。我这样说是因为在我们的现代世界中,如果一个人有数据(谁没有访问大量数据的权限?!)和一台电脑(谁没有接触到不可思议的计算资源?!),然后你可以把数据输入计算机,它会给你一个答案。它必须给出一个答案。这就是它的作用。这很容易。难的是评估这个答案的质量。这需要理解数据的来源及其潜在的偏差,其中一些可能相当微妙。它需要理解分析中可能的混淆因素、模型拟合和过度拟合、多重性和虚假相关性等等。一个没有经过如此深思熟虑的答案只是一个留给人一个疑问的答案,“好吧,那我该怎么做呢?”
如果你能接触到数据,并且有一台电脑,得到答案是很容易的。
评估这个答案的质量是非常困难的。
根据我的经验(请记住,这直接发生在制药行业和整个医疗保健行业),无论是研究科学家和临床医生、销售和营销主管、财务总监,甚至是业务部门的总裁,他们都想知道,“你发现的东西有多大可能是真实的?”更具体地说,他们可能会问:
研究人员:“你有多确定这种基因变异实际上是区分有反应的患者和没有反应的患者的一个因素?我是否应该再投资 4000 万美元进行临床试验来调查或证明这一点?”
营销人员:“你有多大把握对营销活动 X 的投资真的会增加销售额?如果我把下一笔 10,000,000 美元投资在这些广告、口号或推销上,投资回报是多少?”
财务:“如果我们将 25,000,000 美元从项目 X 转移到项目 Y,我们增加总收入的可能性有多大?你的预测有多准确?”
所有这些问题都隐含着对量化不确定性的渴望——而不是消除不确定性,我的所有研究或商业伙伴都理解并接受了这一点。他们需要量化他们决策的利弊。
现在,并不是所有的决定都涉及数百万美元的投资或后果。当风险很高时,数据分析学科、方法和工具的全部力量应该用于量化研究/业务领导决策的可能后果。当投资规模较小、后果不太严重时,更快、更简单的方法可能就足够了,答案可能更具猜测性。然而,即使在这种情况下,也应该传达一些关于答案的合理性或可靠性的定性评估…比如“嘿,老板,这是一个真正的赃物,但这是我们在 24 小时内所能做的最好的了”或“鉴于我们过去的经验,我们认为这是一个非常好的答案…”**
这就是“符合目的”的概念。我在很多场合听到过这句话,它也适用于这里:“既不寻求也不回避复杂性。”如果一个简单的数据分析方法给出了一个好的答案,那就这样吧。但是,如果手头的问题很难,很复杂,有大量的变量,那么就开始进行全面、深入的分析。问题是当前者被认为是后者的一个简单的出路时…当它很容易得到一个答案并说,“这是我们的数据中一些可能的关系。我做了我的工作。你的工作就是把它弄清楚。”我的商业伙伴绝不会容忍这种事。他们指望我们提供某种程度的可靠性…某种不确定性的量化,以帮助指导他们的决策。
总结
我们都知道 数据科学不仅仅是数据 。事实上,大多数数据科学都是关于分析数据,而不仅仅是操纵它(尽管这可能是由于它的起源……请继续关注这个主题的更多内容)。所以,我更喜欢用一个更贴切的描述来描述我们所做的事情——数据分析科学。**
大部分数据科学都是关于分析数据。**
所以,让我们用一个更贴切的描述词——数据分析科学。
我们的工作有没有更贴切的名称?
我喜欢把数据分析科学想象成一个大帐篷。许多专业人士使用某种形式的数学来处理和分析数据。我指的是 专业人士——那些在数据分析方法和工具方面受过正规训练的人。让我们面对它,几乎每个人都可以声称他们分析数据。谁不把事实和数字放入电子表格,并以某种方式进行排序、总结或可视化呢?我认为数据分析科学家是那些专门从事某种形式的数据分析的人,这种数据分析超出了简单的描述性或初级统计(例如线性回归)。
把数据分析科学想象成一个大帐篷。
数学、统计、比较科学、OR、Epi、PK/PD、经济学、生物信息学。
最后,分析非常容易。解读很辛苦。如果我们要成为数据分析科学的专业人士,那么我们有责任为我们的科学/商业伙伴提供一些不确定性的量化,这些不确定性是我们的结论、建议或预测的基础。至少,一些定性评估应该是强制性的。
分析很容易。解读很辛苦。
在他著名的戏剧《罗密欧与朱丽叶》中,莎士比亚写到朱丽叶对她心爱的罗密欧说:“我们称之为玫瑰的东西/不管叫它什么名字,闻起来还是一样香。”所有涉及数据分析以解决问题的学科都有好处。这种甜蜜源自数学的美丽和多功能性,以及数据驱动决策的效用。
(无署名) bwallpapers (免费使用)
分析/数据科学学员实验室工具和技术
您在数据科学学习之旅中应该了解的工具和技术
照片由 holdentrils 在 pixabay 拍摄
每个人都想成为数据科学家。互联网上有大量的学习资源。每件好事都有副作用。当我遇到那些自称为数据科学家的数据从业者时,我并不感到惊讶。纠结于基础研究方法论或者概率概念。但那是另一天的话题。今天,我们将讨论您应该知道什么,以及在开始学习数据科学或分析时可能需要使用哪些工具。最后,您还会发现一些关于设置实验室的工具的建议。
1.计算机和互联网连接
由安德里亚·b·卢卡奇在 pixabay 拍摄的照片
任何想要踏上分析或数据科学之旅的人,他们首先需要的是一台运行良好、网速适中的电脑。该机可以是笔记本,台式机,甚至花式 2in1 平板电脑也行。有人提到 iPad/Android 平板了吗?如果你有覆盆子酱,你也可以从这个开始。这里的重点是,你不需要那些高配置的工作站或疯狂的计算与花哨的 RGB 灯光游戏装备。好吧!如果你想玩所有新的 AAA 评级游戏,你需要最新一代的英伟达 GTX 或 RTX GPU 和无尽的核心(!)处理器拥有大量内存(RAM),当然还有超高速存储(硬盘)。是的,数据科学家在某些时候也需要这些,但不是一开始就需要。让我们一致认为,一台可以正常上网的电脑足以让我们开始学习。哦,是的,我们需要互联网来下载我们将用来学习的所有工具(一切都是免费或开源的)。
因此,无论你打算用什么系统来学习,强烈建议你好好了解你的机器。请不要成为那种仅仅因为笔记本电脑和他的手机有相同的发光标志而购买笔记本电脑的人。赛前了解马匹尤为重要。尤其是不管是 x86 还是 x64 还是 ARM 架构。如果您还不知道它,请转到您的系统属性并检查它。把它记下来。当我们下载学习旅程所需的软件时,它会派上用场。如果你想了解更多关于这些平台之间的区别,你可以在维基百科上找到关于这些平台的详细文章。接下来我们需要知道我们的系统有多少内存。这些信息也可以在系统属性中找到,当然你需要了解你有多少空闲空间。我们将安装软件并带来样本数据。所以,你需要非常熟悉储物单元。感谢智能手机制造商,现在就连奶奶也知道她需要一部 5tb 的手机,因为她想用 4800 万像素的超宽手机摄像头给所有的孙子孙女拍很多照片。总之,您始终需要了解处理器架构及其速度、总内存和机器的可用空间,以便有效地设置整个学习实验室环境。
2.操作系统和用户帐户类型
现在,您已经了解了机器的主要硬件。在开始讨论我们将使用哪些工具之前,让我们熟悉另一个关键部分。
照片由openclipbart-Vectors在 pixabay 上拍摄
操作系统有很多种形式。当今世界上最流行的操作系统是 Android。10 台设备中有 4 台采用安卓系统。我们可以在 Android 中进行分析吗?为什么不呢?它并不意味着像 Windows 或 OS X 或 Linux 那样的桌面计算。它日益成熟。多窗口操作和越来越多的编码环境的支持,它是非常能干的。因此,如果你拥有一部高端智能手机或平板电脑,你也可以用这款设备开始你的数据科学之旅。如果你有一台 iPad,你也可以在你的 iPad 操作系统中进行类似的编码和分析。您不需要等待笔记本电脑或台式机。在我们的例子中,最有效的操作系统将是这三个微软视窗系统、苹果 OS X 系统或任何版本的 Linux。以 Linux 为例,我最喜欢的是 Ubuntu。一旦你知道你正在运行哪个操作系统,现在你需要知道它的变体是什么——32 位还是 64 位,是哪个版本?
一旦你熟悉了所有这些术语,接下来就是故事的下一部分——你在机器上使用的是什么类型的用户账户。如果您与任何人共享设备,或者这是由您的办公室或学校提供的,那么了解您的帐户类型尤为重要。如果没有正确的权限或帐户类型,您可能无法安装或配置自己需要的所有工具。在安装或设置所有工具时,最好拥有管理员或高级用户权限。一旦一切都启动并运行,那么常规用户帐户将是极好的。当您想要更新/升级工具时,您还需要特殊权限。
3.文字编辑器
其他操作系统都有默认的文本编辑器。你日常用的 windows 机器有经典的记事本应用,Mac OS 自带文本编辑。大多数 Linux 发行版都预装了 vi 或 vim。这些都是很有能力的编辑器,可以打开、浏览数据和编写代码。由于编码人员非常依赖他们的编辑器,他们也为他们构建了编辑器。如果你每隔一天谷歌一下,你不会惊讶地发现一个新的编辑。每个作家、程序员和开发人员都有一套最喜欢的工具,就像每个木匠都有一把最喜欢的锤子,每个艺术家都有一套最喜欢的画笔。有些编辑器在所有操作系统中都可用。有些是付费的,有些是免费或开源的。Atom,Sublime Text,Notepad++是目前流行的文本编辑器中为数不多的几个。
使用文本编辑器非常简单。开始时,只需打开一个新文件,写入并以所需的文件扩展名保存。在大多数情况下,如果你不给出任何扩展名,你的编辑器将把它保存为一个普通的。txt 文件。一旦你开始每天使用它,你就会找到有效处理它的方法。像使用一些键盘快捷键会非常方便。你就越会使用它;您将开始熟悉附加组件、宏和其他功能。我们将在后面详细讨论文本编辑器。在这种情况下,我们将在所有示例中使用 Notepad++。
4.基本 CLI
照片由openclipbart-Vectors在 pixabay 上拍摄
自第一代 iPhone 问世以来,世界已经发生了变化。一切不仅好到足以基于 GUI。它需要进行触摸优化。但是世界的这一部分还不是 100%真实的。对于初学者来说,您仍然需要掌握一些基本的文件管理 CLI 技能。像创建一个新的文件夹/文件或复制,粘贴,删除一个文件夹/文件,更重要的是,要知道当前的工作目录或改变目录,最后如何使用帮助文件。对于初学者来说,这已经足够好了。使用命令行一开始可能会很吓人,但是用得越多,就越不吓人。一旦你采用了它,你就掌握了!CLI 等待您的命令。我们将讨论与学习者数据专家相关的最常见的 CLI 命令。
5.基于 GUI 的工具
每隔一段时间,奇迹就会在每个领域发生,对于所有的数据专业人员来说,Microsoft Excel 就像是来自地球上天堂的祝福。很难找到一个和数据打交道的人,而且从来没有碰到过微软的 Excel。从数据分析的初学者到大师,每个人,如果不是经常,偶尔会使用这个工具。年复一年,情况越来越好。数据清理、可视化、基本统计建模或高级探索性数据分析一切皆有可能。一旦你开始使用 add on 或者开始构建你的宏,可能性是无限的。你可以不同意将 Microsoft Excel 视为一个合适的分析工具,但它拥有完成大多数分析步骤所需的所有功能。
SAS 和 IBM SPSS 在过去是非常流行和有影响力的分析工具。它们仍然很出色,可以很好地解决大多数高级分析或预测建模问题。当您想将这些工具用于所有现代大(!)高度可扩展的生态系统。在这种情况下,Knime 和 Rapid Miner 做得非常好。您可以从今天开始学习这些工具,但是学习曲线会非常平滑。但是并不是所有的商业组织都有能力使用所有这些工具。这些工具最棒的地方在于,你可以在所有这些工具中使用你最喜欢的 python 或 R 语言。如果不提 H2o、Dataiku、DataRobot、Orange、Alteryx,这些列表就不完整。
6.程序设计语言
约翰逊·马丁在 pixabay 上的照片
我们有微软 Excel 和一个基于图形用户界面的工具。我需要学习编码吗?是也不是。如果你在一个大型团队中工作,并且你的团队中有人可以通过编码快速完成工作,而这对于架子工具是不可用的,你可以从他们那里获得帮助。不过,最好还是学习必要的编码,这样沟通才能顺畅,你也会明白他们在实现你的要求时可能面临的挑战。重点是现在;市场上没有任何工具可以开箱即用,100%解决您的数据分析问题。这将需要一些特定于行业或问题的自定义功能。在这些情况下,编码是必不可少的。
现在我们一致认为,我们需要学习一种编程语言,以便在分析的世界中导航。那么问题就是哪种语言。让我们不要卷入这场辩论;相反,我们可以选择 Python 或 r。这两种语言都能够做类似的事情。你甚至可以学习 Java 或者 Julia。哪种语言都无所谓。一旦你熟悉了一个,切换到另一个就不会花太多时间,而且总有 google 和 StackOverflow 帮助你。但是最好从拥有最大社区的语言开始。最大的社区意味着大量的教程、例子和论坛。您还可以找到许多示例项目来跟进。
7.结构化查询语言
并非所有数据都能放入 Excel 电子表格。Excel 是一个很棒的工具,毫无疑问。但是你需要把你的数据存储在一个便于组织和快速访问的地方。这是一个非常拥挤的领域——针对不同类型的数据库有大量的解决方案。但是如果你熟记标准的 SQL,你可以在帮助文件或谷歌的帮助下使用任何解决方案。要么是 Microsft SQL Server 要么是 Oracle 要么是 Impala 要么是 Google Big Query 作为数据专业人士 SQL 应该是你的第二语言。数据库和 SQL 的概念可以帮助您通过 python 或 R 进行数据准备,即使您不在任何数据库之上工作。
8.多方面的
你就快到了。现在你知道了你的硬件和所需的软件。为了以后的效率,你需要更多的工具,比如版本控制,调度器;您需要熟悉文件压缩技术,当然,还有现代基于云的工具和技术。一旦你习惯了数据专家的生活方式,你就可以学到这些,这种生活方式只对合适的人有吸引力。
2020 年中期推荐的实验室工具和技术
电脑- > CPU:酷睿 i5 或 AMD 锐龙 5 级,RAM: 16GB,HDD: 1TB SSD
操作系统->Ubuntu LTS 64 位或 Windows 10 64 位带 WSL Ubuntu LTS
文本编辑器->-记事本++本
GUI 工具- > Knime &微软 Excel
编程语言- > Python 3 Anaconda 发行版
SQL - > MySQL
FIFA 2019 球员分析!
康纳·科因在 Unsplash 上的照片
CRISP-DM 数据科学足球赛
国际足联的足球分析和建模
在本帖中,我们将按照 CRISP-DM 流程对 FIFA 2019 完整球员数据集进行简单的数据分析和建模。数据集已经收集完毕 Kaggle 。数据集包含 1 个 CSV 文件。
FIFA 2019 是作为电子艺界的 FIFA 系列的一部分开发的足球模拟视频游戏。这是 FIFA 系列的第 26 部,销量超过 2000 万部。
让我们开始吧!
在足球这样的运动中,每个球员都为团队的成功增加了重要的价值。了解球员的技能很重要。年龄如何影响球员的潜力?哪个玩家最擅长哪个侧面?该研究还侧重于根据表现指标评估球员的整体表现,以及各种模型如何对准备好的数据进行评估。
数据理解
作为 CRISP DM 的第二阶段,使用数据可视化和查询来探索数据和解决数据挖掘问题是很重要的。数据集由 89 列组成,但我们将只限于以下几列:
Index(['Name', 'Age', 'Overall', 'Potential', 'Value', 'Wage', 'Special',
'Preferred Foot', 'International Reputation', 'Weak Foot',
'Skill Moves', 'Crossing', 'Finishing', 'HeadingAccuracy',
'ShortPassing', 'Volleys', 'Dribbling', 'Curve', 'FKAccuracy',
'LongPassing', 'BallControl', 'Acceleration', 'SprintSpeed', 'Agility',
'Reactions', 'Balance', 'ShotPower', 'Jumping', 'Stamina', 'Strength',
'LongShots', 'Aggression', 'Interceptions', 'Positioning', 'Vision',
'Penalties', 'Composure', 'Marking', 'StandingTackle', 'SlidingTackle',
'GKDiving', 'GKHandling', 'GKKicking', 'GKPositioning', 'GKReflexes'],
dtype='object')
- 各方面最好的选手?
可以看出,以下选手在各自领域被评为最佳。可以看出,K. Mbappé潜力最大,c 罗技术动作最好,内多头球准确性最高等。
图 1:基于表现得分的最佳球员
2。球员最喜欢的脚?
图 2:球员最喜欢的脚
3。足球脚对球员潜力的影响
图 3:脚对球员潜力的影响
从上面的图中可以看出,球员的潜力几乎不取决于他是左脚还是右脚。
3。年龄对潜力有影响吗?
图 4:年龄与潜力
从柱状图中可以看出,随着年龄的增长,球员的潜力有下降的趋势。
建模
表现指标是属性的组合,给出了选择的细节,球员的整体表现。热图用于发现绩效指标如何影响玩家的整体绩效。
图 3:整体与其他绩效指标的相关性
从热图中可以看出,总体绩效与大多数绩效指标正相关。
CRISP-DM 的第三阶段是数据准备。对数据进行清理(处理分类数据和缺失值以预测整体性能)并为实现结果做好准备。建立线性回归模型,根据表现得分预测选手的整体表现。
估价
此外,我们将数据拟合到各种模型中——随机森林回归、K 近邻和决策树回归,并使用以下指标评估模型:
- 绝对平均误差
- r 广场
- 均方误差
图 5:各种模型的评估
结论
在本文中,我们对 FIFA 2019 完整球员数据集进行了简单的数据分析。
- 我们观察了哪个玩家擅长某个特定的性能指标。比如:l .梅西最擅长整理。
- 然后,我们研究了年龄对球员潜力的影响,即随着年龄的增长,球员的潜力下降。
- 建立一个模型来预测一个球员的整体表现,给出他在每个表现指标上的技能得分。
- 最后,我们针对 KNearestRegressor、DecisionTreeRegressor、RandomForestRegressor 评估了我们的线性回归模型
这里的发现是观察性的,还有很多分析要做:
你将如何解决这个问题?
所有代码都在我的 Github 资源库 中。
用谷歌日历和熊猫分析和跟踪自由职业者的收入
将日历数据引入 Pandas,实现自由职业者收入跟踪任务的自动化。
介绍
作为一个住在西班牙的异乡人,我的收入来源之一是给私人上英语课。2016 年开始的时候,我在一个简单的 Google Sheets 文档中手工输入了所有的私有类。我的目标是跟踪工作时间和收入,并分析我的新职业的趋势和见解。
问题是
电子表格需要手工输入类别;日期,长度,学生姓名和收入。手动更新文档花了大约 5 分钟,我喜欢每周回顾我的时间表,反思所上的课和获得的收入。然而,记住每周做一次开始变得有点乏味,几年后,有了多种收入来源,电子表格膨胀成一个不稳定的庞然大物,有过多的选项卡、数据透视表和各种原始数据来源。是时候自动化解决方案了。
解决方案
我的生活和工作日程由谷歌日历管理——这包括我所有的私人课程、自行车/摄影之旅、学术工作、政府职位、翻译工作和随机的自由职业。每一个有偿工作的“单位”都在日历中;我只需要找到一种方法来直接访问谷歌日历数据,并将我的电子表格重建成一台可持续的分析机器。在我以前的公司生活中,我专门在 Pandas 笔记本(用于分析数据的 Python 框架)的世界中工作,因此利用这些工具从 Google Calendar 访问我的课程表并利用 Pandas 处理和分析收入数据是一个自然的解决方案。
第一步:在谷歌日历和熊猫世界之间架起一座桥梁
我偶然发现了一篇很棒的文章,它解决了我的问题。使用 Google Calendar API,我可以轻松地获取我的日历事件(使用特定的“英语类”日历)并将其转换成易于分析的形式。我建议查看这篇博文,逐步了解如何使用您的帐户设置 Google Calendar API 并创建 OAuth 客户端 ID。
下一步是执行代码,该代码将生成一个 URL,该 URL 需要 google 登录和授权,以使应用程序能够访问我们的日历事件。将生成一个授权码,我们需要将它粘贴回我们的熊猫笔记本。注意:“your_calendar_id”是我想要查看的特定日历(Google 提供了创建多个日历的选项)。
(以下所有代码也可在 GitHub repo 上获得)。
*#read calendar events from google*
*#requirement: pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib*
**from** **apiclient.discovery** **import** build
**from** **google_auth_oauthlib.flow** **import** InstalledAppFlow
**import** **pickle**
scopes = ['https://www.googleapis.com/auth/calendar']
flow = InstalledAppFlow.from_client_secrets_file("client_secret.json", scopes=scopes)
credentials = flow.run_console()
*#save credentials*
pickle.dump(credentials, open("token.pkl", "wb"))
credentials = pickle.load(open("token.pkl", "rb"))
service = build('calendar', 'v3', credentials=credentials)
result = service.calendarList().list().execute()
*#specify desired calendar to access*
your_calendar_id = 'YOUR_CALENDAR_ID'
登录我们的帐户(我们已经为其创建了一个日历 API 项目),并授予我们的应用程序访问日历的权限。
在点击各个确认框后,会生成一个授权码,我们需要将它粘贴回笔记本中。我们现在可以从我们的熊猫笔记本上直接访问您的谷歌日历。
第二步:在谷歌日历中访问所需的数据,并转换成熊猫数据框架
好了,现在我们有了谷歌日历和熊猫之间的链接——下一步是正确地获取数据并将其转换成可用的形式。
我们可以使用“service.events()直接访问事件。列表()。execute()"调用,如下面的代码所示——参考日历 API 文档,以便根据我们的需求进行定制是很有帮助的。
我决定过滤日历中从我开始从事自由职业到未来一年的日期(以便正确跟踪预定时间和工作时间)。
*# Call the Calendar API*
**from** **datetime** **import** datetime
**from** **datetime** **import** timedelta
**from** **dateutil.parser** **import** parse **as** parse_date
**import** **pytz**utc=pytz.UTC
*#specify max date of calendar events you would like to access (days in future)*
days_in_future = 365
now = datetime.utcnow()
date_final = (datetime.utcnow() + timedelta(days=days_in_future)).isoformat() + 'Z'
*#start_date - earliest date of calendar events needed*
start_date_str = '09/01/19'
start_date = datetime.strptime(start_date_str, '%m/**%d**/%y').isoformat() + 'Z'
events_result = service.events().list(calendarId=your_calendar_id,
timeMin=start_date,
timeMax=date_final,
maxResults=1000,
singleEvents=**True**,
orderBy='startTime').execute()
events = events_result.get('items', [])
我们现在有一个很好的字典列表,每个字典代表一个特定的日历事件,对应于一个特定的自由职业者事件,并包含重要的数据,如开始/结束时间和事件的描述。
让我们遍历字典列表,以便解析出有用的信息,并转换成一个整洁的字典列表,很好地放入 Pandas 数据框架。我决定获取活动的开始/结束日期、持续时间,并做一点逻辑分析,看看活动是仅仅被预订了还是已经完成/支付了。结果被保存到 pandas 数据框架中,以备进一步处理和分析。
event_list = list()
**for** event **in** events:
start = parse_date(event['start'].get('dateTime'))
end = parse_date(event['end'].get('dateTime'))
event_duration = end - start
event_duration_minutes = event_duration.seconds // 60
**if** end < utc.localize(now):
status = 'PAID'
**else**:
status = 'BOOKED'
cal_entry_dict={'date': start.strftime('%Y-%m-**%d**'),
'client': event['summary'],
'minutes':event_duration_minutes,
'status' : status}
event_list.append(cal_entry_dict)
*#Convert to Pandas Dataframe*
classes_df = pd.DataFrame(event_list)
生成的数据帧如下所示:
让我们施展一些熊猫魔法,引入价格、位置和一些其他数据点,以便正确地开始分析数据。
使用一点逻辑将定价数据与主数据框架连接起来,以根据活动的长度确定收入。此外,解析我们的“旅游”日历事件,这些事件应该与类区别对待。
产生的数据框架给我的信息与我的手动电子表格完全相同;我们的电子表格的数据输入部分已经自动化了!我们努力工作的结果:
第三步:分析数据
好戏开始了!我们将整理这些数据,以获得一些一般性的见解。
显然,这里有一些季节性趋势,因为我们看到夏季收入大幅下降。让我们引入更多的历史数据,看看这种趋势能否持续。
我们看到了一些严重的收入季节性趋势。夏季的几个月里收入大幅下降——天气晴朗的时候,没人想学英语!
让我们从另一个角度来看这个问题:每年作为一条线,x 轴仅仅是月——这将有助于我们直观地看到随着月份的推移,每年的轨迹。
明显的季节性:
这些图表显示了总收入,但缺乏任何关于收入来源的信息(私人课程、政府工作、自行车旅游、翻译等)。让我们调整代码以显示“client_type ”,这样我们可以更好地了解收入来自哪里。
结果显示了收入的良好多样化:
我们应该展望未来,我们对未来的收入有什么样的预订?(所有被定义为“有偿”的工作都被视为已完成/有偿工作,所有被“预订”的工作都是对未来工作和报酬的承诺。
我们将看到 2020 年的收入大幅下降!是时候开始预订了。
一年前的这个月,我在同一时间点做得怎么样?两年前?这里有一个漂亮的图表,显示了本月迄今为止的收入(当月)逐年减少的情况。我的想法是看看我目前的收入与前几年相比如何。
(由于各种新项目,2020 年将是收入增长缓慢但个人成长迅速的一年!)
这些是我用来洞察收入活动的一些基本图表。可能性是无穷无尽的;任何阅读这篇文章的人都可以很容易地定制他们的代码来满足他们的需求。
最后的想法
自动化解决方案已被证明是一个更加强大、自动化和有效的解决方案,让我能够洞察我的收入。Pandas 是一个快速和强大的操纵/可视化数据的极好资源。我鼓励任何在电子表格中跟踪收入(并使用谷歌日历)的人开始利用熊猫来达到同样的结果。这里有一些有用的资源可以让熊猫笔记本正常运行:
- Dataquest Jupyter 笔记本教程
- Jupyter 项目
- 笔记本必备快捷键
- 谷歌“如何[在此插入您的问题]熊猫 python”并扫描相关 StackExchange 问题。
受冠状病毒影响最严重的 10 个国家和墨西哥
深入了解新冠肺炎在墨西哥的传播情况,以及十大疫情最严重的国家
墨西哥确诊病例密度分布图(Diego Hurtado)
作者:迭戈·乌尔塔多
介绍
本说明的目的是描述墨西哥与受影响最严重的国家的总体现状,这可以为人们采取有益的社会和卫生措施以阻止新冠肺炎的传播服务。
自 2019 年 12 月下旬以来,一种新型冠状病毒疾病的爆发(新冠肺炎;此前被称为 2019-nCoV)在中国武汉被报道,随后影响了全球 210 个国家。一般来说,新冠肺炎是一种急性疾病,但它也可能是致命的,病死率为 29%。截至 2020 年 1 月 19 日,墨西哥已确诊约 1.03 亿病例,超过 224 万人死亡,5730 万人康复。
Covid 案例分布(Diego Hurtado)
症状
在出现症状之前,人们可能会感染病毒 1 至 14 天。冠状病毒疾病(新冠肺炎)最常见的症状是发烧、疲劳和干咳。大多数人(约 80%)无需特殊治疗即可康复[2]。
- 咳嗽
- 发热
- 疲劳
- 呼吸困难(严重病例)
推荐
阻断人与人之间的传播,包括减少密切接触者和医护人员之间的二次感染,防止传播放大事件,并防止进一步的国际传播[3]。
- 及早识别、隔离和护理患者,包括为受感染的患者提供优化的护理;
- 识别并减少动物源传播;
- 解决关于临床严重程度、传播和感染程度、治疗方案的关键未知问题,并加快诊断、治疗和疫苗的开发;
- 向所有社区传达关键风险和事件信息,并反驳错误信息;
- 通过多部门伙伴关系将社会和经济影响降至最低
数据
自 2020 年 1 月 22 日以来的新型冠状病毒(新冠肺炎)流行病学数据。从包括 DXY.cn 世界卫生组织(世卫组织)在内的各种来源的约翰·霍普斯金 CSSE 数据仓库加载数据。数据每天更新两次。
数据中可用的字段包括省/州、国家/地区、上次更新、确认、疑似、恢复、死亡。
2020 年 3 月 23 日,发布了新的数据结构。最新时间序列数据的现有资源有:
- 时间序列 _ covid19 _ 已确认 _ 全球. csv
- 时间序列 _ covid19 _ 死亡人数 _ 全球. csv
- 时间序列 _ covid19 _ 已恢复 _ 全局. csv
confirmed_df = pd.read_csv('[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv'](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv'))recovered_df =
pd.read_csv('[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv'](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv'))country_df = pd.read_csv('[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/web-data/data/cases_country.csv'](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/web-data/data/cases_country.csv'))
墨西哥概述🇲🇽
墨西哥🇲🇽科维德仪表板(迭戈乌尔塔多)
🇲🇽概览(迭戈·乌尔塔多)
🇲🇽墨西哥州(第三)在死亡案例中排名第三
Choropleth 图死亡率
墨西哥🇲🇽(第 3 位)死亡案例第三位(迭戈·乌尔塔多)
🇲🇽墨西哥(#3)死亡率第三(迭戈乌尔塔多)
墨西哥死亡病例的年龄分布
🇲🇽墨西哥州(第三位)在死亡率上排名第三
🇲🇽墨西哥(#3)死亡率第三(迭戈乌尔塔多)
🇲🇽墨西哥(#3)死亡率第三(迭戈乌尔塔多)
墨西哥🇲🇽(排名第三)在危急情况中排名第四
墨西哥🇲🇽(第四)在死亡病例中排名第三
🇲🇽墨西哥各州概览
墨西哥的新冠肺炎:各州确诊病例总数(迭戈·乌尔塔多)
墨西哥的新冠肺炎:各州死亡病例总数(Diego Hurtado)
死亡人数最多的州是墨西哥城
墨西哥分析🇲🇽
墨西哥霍乱地图死亡病例密度(迭戈·乌尔塔多)
墨西哥的移动🇲🇽
尽管感染人数激增,墨西哥总统在 5 月开始了“T2 新常态”以“重新激活”经济
在商店外面,顾客们在等待,没有注意到健康距离。Av。CDMX Eje Central 的华雷斯角。2020 年 5 月 21 日。图片:angelica Escobar/福布斯墨西哥版。
观察:
我们可以看到,5 月份确诊和死亡病例开始成倍增长!!
墨西哥确诊病例和死亡之间的关系(Diego Hurtado)
确诊病例:
时间序列确诊病例墨西哥(迭戈乌尔塔多)
死亡病例:
时间序列确诊病例墨西哥(迭戈乌尔塔多)
死亡案例最多的州(墨西哥州)的交通行为
我们可以看到,当新常态开始时,流动性在 5 月份开始增长
“新常态是一种幻觉,我们正处于流行病活动中,我认为在这个时候提议重启社会活动实际上是自杀行为,我认为这会以前所未有的水平重新激活患病和死亡人数。”——马拉奎亚斯·洛佩斯·塞万提斯
🇲🇽卫生部
由于大量肺泡损伤和进行性呼吸衰竭,严重疾病发作可能导致死亡。新冠肺炎疫情对长期血液透析患者来说是高风险的,因为他们处于免疫抑制状态,年龄较大,并且存在显著的共病,特别是心血管疾病、糖尿病等。同样值得注意的是,心血管风险因素在墨西哥人口中非常普遍,并以惊人的速度增长,心血管疾病是墨西哥的第一大死亡原因[2]。
墨西哥死亡病例的年龄分布
墨西哥死亡病例的年龄分布
死亡人数最多的州(墨西哥州)死亡病例的年龄分布
墨西哥死亡病例的年龄分布
墨西哥疫苗🇲🇽
我们可以观察到,像以色列这样的国家 58%有第一剂,而墨西哥只有 0.5 %
接种疫苗百分比最高的 10 个国家
今天,根据最保守的估计,大约有 9 亿人住在贫民窟。据估计,到 2030 年,地球上将有 1/4 的人生活在贫民窟或其他非正规居住区。让我们来参观一下世界上最大的贫民窟:
- 开普敦的哈耶利沙(南非):40 万人
- 内罗毕的基贝拉(肯尼亚):70 万人
- 孟买的达拉维(印度):100 万
- 内扎(墨西哥):120 万
- 卡拉奇的奥兰治镇(巴基斯坦):240 万人
墨西哥城
人口:110 万
虽然有些人认为内扎华尔科约特城,也被称为内扎,已经从一个贫民窟演变成了一个郊区,但砖砌的房子散布在临时搭建的棚屋中,即使以饱受毒品战争折磨的墨西哥的标准来看,这个社区也被认为是极其危险的。社区行动促使政府将土地所有权正式化,开始垃圾收集,并建设其他一些关键的基础设施。现在,大约 70%的居民在该地区工作,这是墨西哥人口最稠密的直辖市。
2016 年 9 月 30 日,墨西哥墨西哥州内扎华科约特尔(Nezahualcóyotl)的鸟瞰图。汤森路透基金会/约翰尼·米勒
观察:
显然,新冠肺炎在墨西哥的传播速度更快,死亡率更高,生活在贫民窟的人可能是这种情况下的一个关键因素。也许这就是墨西哥冠状病毒病例不断增加的原因。
墨西哥需要采取行动
对墨西哥新冠肺炎的预测性监控:新冠肺炎预测对于合理化规划和心态至关重要,但也具有挑战性,因为复杂、动态和全球化的新冠肺炎疫情作为一个典型的棘手问题。传统的预测或预报努力的目标是现在做出准确的预测,以便在未来实现,但在这种极端不确定的情况下,这种努力可能会产生误导
墨西哥与拉丁美洲国家的相互关系
我从约翰霍普金斯大学新冠肺炎数据库中提取了新冠肺炎每日新增病例和拉丁美洲死亡病例。我使用线性回归来分别检验墨西哥和拉丁美洲国家之间的相关性。相关性最强的国家是巴西。
墨西哥和巴西之间的数据关系(Diego Hurtado)
有趣的是,这两个国家由一个左翼国家执政。
强占
流行病学家和健康经济学家 Eric Feigl-Ding 将墨西哥的冠状病毒阳性病例与纽约、马德里和伦巴第等城市的病例进行了比较,并警告说,墨西哥将经历的新冠肺炎检测阳性百分比是前所未有的。
这是因为半数以上的检测对病毒呈阳性。
德雷克丁。(2020 年 6 月 21 日)
“我为墨西哥哭泣。超过 50%是阳性的百分比,超过一半的测试者是阳性的,”这位科学家在推特上谈到冠状病毒病例时说。
德雷克丁。(2020 年 6 月 21 日)
墨西哥人均病例和死亡率与美国的对比。在墨西哥很明显诊断不足,治疗也很差。56%的阳性率反映了这一点。所以是的,该死的,我们需要更多的测试。
催单
1918 年的疫情流感是近年来最严重的疫情。它是由带有禽类基因的 H1N1 病毒引起的。尽管对病毒的起源没有普遍的共识,但它在 1918-1919 年间在世界范围内传播。
全世界死亡人数估计至少为 5000 万,其中约 675,000 例发生在美国。
5 岁以下、20-40 岁和 65 岁及以上人群的死亡率较高。健康人群的高死亡率,包括 20-40 岁年龄组的人群,是疫情的一个独特特征。
流感疫情图表(Reeve 003143),国家健康和医学博物馆
疫情流感| 1918 年和 1919 年期间美洲和欧洲的死亡率。图表:“疫情流感。1918 年和 1919 年间美国和欧洲的死亡率每周因各种原因造成的死亡,以每年每 1000 人的死亡率表示。包括代表纽约、伦敦、巴黎和柏林的线条。
我们到了。
流感疫情图表(Reeve 003143),国家健康和医学博物馆
结论:
这篇文章详细分析了新冠肺炎是如何影响墨西哥和世界的,以及由此得出的见解如何用于下游分析。这些图表还可以应用于其他场景,以推断关键的数据洞察力。
我希望你们都喜欢这篇文章。所有的图表都是使用 Plotly 创建的。Plotly 是一个非常棒的可视化库,用于构建交互式的图形。他们有 Python 和 JavaScript 的图形库。
领英:【https://www.linkedin.com/in/diego-gustavo-hurtado-olivares/
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
参考
[1]徐,郑,石,李,王,杨,张,黄,李,张,陈,… &泰,杨(2020).急性呼吸窘迫综合征相关新冠肺炎的病理表现。柳叶刀呼吸内科, 8 (4),420–422。
[2]m .卡斯塞拉、m .拉杰尼克、m .科莫、a .杜勒博恩、S. C .、r .迪那不勒斯(2020 年)。冠状病毒的特征、评估和治疗(新冠肺炎)。在 Statpearls【互联网】。StatPearls 出版社。
[3]世界卫生组织。(2020).冠状病毒疾病 2019(新冠肺炎):情况报告,72。
[4]“世界上最大的贫民窟:达拉维、基贝拉、Khayelitsha & Neza。”人类家园 GB ,2018 年 9 月 7 日,www . habitatforhumanity . org . uk/blog/2017/12/the-worlds-larvi-kibera-khayelitsha-neza/。
[5]“拥有世界上最大贫民窟的 8 个城市。”美国新闻&世界报道,美国新闻&世界报道,www . us News . com/News/cities/articles/2019-09-04/the-worlds-largest-贫民窟。
[6]墨西哥。(未注明)。从 https://ddi.sutd.edu.sg/portfolio/items/448588取回
[7]美国和欧洲 1918-1919 年流感死亡率图表|奥的斯历史档案国家健康和医学博物馆(http://www . Flickr . com/photos/medical Museum/5857153474/in/set-72157614214049255),由 CC-BY-NC-SA(http://creativecommons.org/licenses/by-nc-sa/2.0/uk/)授权
[8]德雷克丁。(2020 年 6 月 21 日)。神圣的 moly-我为墨西哥哭泣。https://twitter.com/DrEricDing/status/1274816278197342209
在命令行中使用 SQL 查询 CSV
通过命令行对 CSV 文件运行 SQL 的快速指南
如果你熟悉 SQL 中的编码,你很有可能在 PgAdmin 、 MySQL 、 BigQuery 、 SQL Server 等中使用它。但是有时您只想使用您的 SQL 技能对中小型数据集进行快速分析。
使用csvkit
,您可以在命令行中对 CSV 文件运行任何 SQL。
[csvkit](https://csvkit.readthedocs.io/en/latest/)
是一套命令行工具,用于转换和使用 CSV,表格文件格式之王。一旦你安装了csvkit
,你就可以使用csvsql
来运行你的 SQL 命令。
1.装置
如果你没有安装csvkit
,点击 这里 并按照安装说明操作,或者如果你熟悉pip
你可以做以下操作。
pip install csvkit
您可以使用以下方式查看csvkit
文档。
csvsql -h
2.句法
现在您已经设置好了,您可以按照这个简单的结构来运行您的查询。需要注意的是,SQL 查询必须用引号括起来,并且必须在一行中。没有换行。
csvsql --query "ENTER YOUR SQL QUERY HERE"
FILE_NAME.csv
就是这样!遵循这个基本的代码框架,你就可以开始了。
确保您与 CSV 文件位于同一个工作目录中。
3.例子
下面是一个设置目录并启动和运行我们的第一个 SQL 命令的例子。
检查目录
pwd
设置工作目录
确保您计划使用的文件位于同一目录中。我的 CSV 文件在/Documents
文件夹中。
cd ~/Documents
运行查询
接下来,我们可以使用csvsql
运行查询
密码
输出
用 csvlook 格式化查询输出
使用| **csvlook**
管道可以改善输出的查询格式。
密码
输出
将查询输出保存到新的 CSV 文件中
使用带有**>**
的重定向,您可以将查询输出发送到一个新的文件/位置。注意运行下面的代码不会输出任何东西,因为我们将输出保存到一个新文件中。新的查询将输出保存到新的 csv 文件**store_sales.csv**
你都准备好了!现在,您可以对 CSV 文件运行 SQL,无需通过数据库就能快速了解情况。
如果您想了解更多关于 SQL 的知识,请查看我的其他文章。
使用 Python、Pandas 和 Plotly 构建的旭日图以正确的方式分析客户行为
旭日图,有时也称为环形图、多层饼图或径向树形图( Anychart,n.d. )是可视化和理解分层或顺序数据的一种极好的方式。
旭日图有两个主要用例:
- 理解整体的最大贡献者和这些组成部分的比例
- 理解流程中连续步骤之间的人员流动
为了说明旭日图的用例,我将使用我生成的数据集来模拟客户在网站上完成购买的简单路径。(如果你想复制我的例子,数据集可以在我的 Kaggle 数据集中找到)
在这个假设的用例中,我们希望了解我们的客户在我们的网站上完成购买的最常见途径是什么,并比较访问我们的客户的行为是否与通过广告平台到达的客户不同。
值得一提的是,旭日图对于时间序列或连续数据来说并不理想,但对于层次性或序列性数据来说更理想。
有了基本的方法,让我们把无聊的熊猫数据框变成一个互动的旭日图,让我们找到一些见解。
要学习本教程,您需要在当前环境中安装以下库:
- Numpy
- 熊猫
- Plolty
我的大部分工作都是在 Jupyter 笔记本和 Jupyter 实验室中完成的,但是您可以随意使用您喜欢的任何 IDE。请参考 Plotly 入门文档 ,尤其是如果你像我一样使用 Jupyter 工具的话。在 Jupyter 中第一次使用 Plotly 时,您必须运行几行代码,但我向您保证这并不复杂。
当您确信可以显示 Plotly 图形时,您可以通过导入上述带有常用别名的库开始,Plotly 提供了一个名为 Plotly Express 的高级 API,我们将使用它。
import numpy as np
import pandas as pd
import plotly.express as px
如果你正在使用我的数据集,并把它放在同一个工作目录中,你可以用下面的方法导入它,如果你正在使用其他数据集,请随意使用你最喜欢的方法把它作为一个熊猫数据框架。
df = pd.read_csv(‘path_to_purchase.csv’)
使用 Plotly Express 构建旭日图相当简单,尤其是从熊猫数据框架。我们必须指定的关键内容是使用 data_frame 参数的数据帧、使用的列以及使用 path 参数的它们的层次结构,以及将确定我们的 sunburst 图表中各部分的大小的列
fig = px.sunburst(
data_frame = df,
path = ['Segment', 'Customer Origin', 'First Click', 'Coupon Usage'],
values = 'Customer Count'
)
fig.show()
上面的代码生成了下面的图表:
还有一些格式改进的空间,我不会深入讨论这些参数的细节,但是这些关键字清楚地表明了它们的作用,所以它们对你来说不应该是一个问题。
通过添加以下代码行,我们可以生成一个更好看的图表:
fig =px.sunburst(
data_frame = df,
path = [‘Segment’, ‘Customer Origin’, ‘First Click’, ‘Coupon Usage’],
values = ‘Customer Count’,
title = ‘Paths to purchase’,
height = 700,
template = ‘ggplot2’
)
fig.show()
与 Matplotlib 不同,Plotly 的一个优点是它生成的图表是交互式的。这增加了一个可用性层,可以增强您的探索性分析,并在演示时提供令人惊叹的因素。想想 Tableau 或 Power BI,但可以通过 Python 获得。
通过利用这种可视化和交互性,我们现在可以在图表中看到以下内容:
- 大多数顾客都是有机地来到我们的网站
- 有机到达的顾客倾向于购买更多无折扣商品,但来自平台广告的顾客更喜欢有折扣的商品
- 最重要的是,来自广告平台并购买打折商品的顾客比其他类型的顾客更倾向于使用优惠券购物
当然,这将引发更多的问题,我们可以使用这些问题来推动进一步的分析,但旭日图使我们能够对数据进行快速探索。
分析数据并在 15 分钟内为一家电子商务初创公司提供可行的见解
这篇文章帮助你戴上数据科学家的帽子,分析一家电子商务初创公司的数据,提供可操作的见解。
由于有大量的在线资源可用于学习数据科学,本科生很难将自己与其他人区分开来,因为每个人都完成了相同的课程和类似的项目。在这种情况下,努力理解数据科学项目的典型工作流并在数据科学和机器学习之间划清界限就变得势在必行。一旦我们理解了其中的区别,学生就可以构建端到端的项目(对于数据科学概要文件来说更重要),而不仅仅关注 it 的数学方面(对于机器学习概要文件来说更合适)。
岗位描述
这篇博客展示了数据科学家的典型工作流程以及所有必须遵循的步骤。
我们将使用基本的 Python 库进行数据操作,使用基本的可视化库进行数据可视化,使用简单的机器学习库进行线性回归分析。
这不是最先进的(SoTA)实施,而是说明数据科学工作流基础的直观指南。
请注意,我们将为此使用Google Colab。请“”表示回购是你喜欢的。*
项目描述
在这篇博文的范围内,假设你是一名自由职业的数据科学家,你被纽约一家专门从事服装的在线电子商务公司聘为合同工。这家电子商务公司在网上销售服装,也有店内风格和服装建议会议。顾客来到店里,与私人造型师进行会谈/会面,然后他们可以回家,在手机应用程序或网站上订购他们想要的衣服。
从 UnSplash
该公司正试图决定是将精力集中在他们的移动应用程序体验还是他们的网站上。他们雇佣你来帮助他们解决这个问题!我们开始吧!
让我们试着分析一下客户数据(这是假的,不包含任何真实的信用卡号码或电子邮件)。
你也可以在 上关注这个我的 Github 这里 。
导入包
**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**import** **matplotlib.pyplot** **as** **plt**
**import** **seaborn** **as** **sns**
%matplotlib inline
下面是允许您将文件上传到 Colab 文件的代码片段。我们将在笔记本中使用的数据在一个 CSV 文件中。该文件位于名为“E-commerce . CSV”的同一文件夹中
**from** **google.colab** **import** files
**import** **os**
uploaded = files.upload()
all_files = [(name, os.path.getmtime(name)) **for** name **in** os.listdir()]
latest_file = sorted(all_files, key=**lambda** x: -x[1])[0][0]customers = pd.read_csv('Ecommerce Customers')
customers.head()
一旦你运行这段代码,你应该会看到这样的输出——
现在我们已经上传了数据,我们已经看到了数据的“头部”,我们将更多地使用它。
我们将使用“describe()”和“info()”函数。输出应该是这样的—
探索性数据分析
既然我们已经处理了数据,让我们来研究一下。
我们将使用“Seaborn”来创建一个联合图,并比较以下各列-“花在网站上的时间”和“每年花费的金额”
sns.jointplot(data=customers,x='Time on Website',y='Yearly Amount Spent')
相关性有意义吗?
让我们用“App 上的时间”一栏重复这个过程。
sns.jointplot(data = customers, x='Time on App', y = 'Yearly Amount Spent')
现在让我们创建一个 jointplot 来比较“在应用上的时间”和“会员的时间长度”。
sns.jointplot(x='Time on App',y='Length of Membership', kind='hex',data = customers)
我们可以选择创建一个 Pairplot 来一次执行多个比较,而不是逐个执行。
sns.pairplot(customers)
问:根据这张图,什么看起来是与每年花费金额最相关的特征?
Ans —隶属关系长度
现在,让我们也创建一个每年花费金额与会员资格时间的线性模型。
sns.lmplot(x='Length of Membership', y='Yearly Amount Spent', data = customers)
机器学习(基础部分)
现在我们已经对数据进行了一些探索,让我们继续将数据分成训练集和测试集。将变量 X 设置为客户的数字特征,将变量 y 设置为“每年花费的金额”列。
我们将使用来自 Scikit Learn 的简单线性回归来训练我们的模型。
customers.columns
y = customers['Yearly Amount Spent']
X = customers [['Time on App','Time on Website', 'Length of Membership', 'Yearly Amount Spent']]
**from** **sklearn.cross_validation** **import** train_test_split
**from** **sklearn.linear_model** **import** LinearRegression
X_train, X_test, y_train, y_test = train_test_split(
... X, y, test_size=0.4, random_state=101)lm = LinearRegression()
lm.fit(X_train,y_train)
X_trainpredictions = lm.predict(X_test)
plt.scatter(y_test,predictions)
plt.xlabel('Y Test (True Values)')
plt.ylabel('Predicted Values')
模型评估
让我们通过计算残差平方和以及解释方差得分(R)来评估我们的模型性能。
**from** **sklearn** **import** metrics
**import** **pandas** **as** **np**
print('MAE', metrics.mean_absolute_error(y_test,predictions))
print('MSE', metrics.mean_squared_error(y_test,predictions))metrics.explained_variance_score(y_test,predictions)
sns.distplot((y_test-predictions))
讨论:我们回答了问题吗?
我们还是想搞清楚原问题的答案,我们是把精力放在手机 app 还是网站开发上?或者这根本不重要,会员时间才是真正重要的。让我们看看我们是否能解释这些系数来得到一个想法。
cdf = pd.DataFrame(lm.coef_,X.columns,columns=['Coeff'])
cdf
解释这些系数
- 保持所有其他功能不变,平均增加 1 个单位。会话长度与 25.98 美元的总花费的增加相关联。
- 在所有其他功能不变的情况下,App 上的时间每增加 1 个单位,总花费就会增加 38.59 美元。
- 在所有其他特征不变的情况下,网站时间每增加 1 个单位,总花费就会增加 0.19 美元。
- 在保持所有其他特征不变的情况下,会员时间每增加 1 个单位,总花费就会增加 61.27 美元。
问:现在该公司应该更关注他们的移动应用还是网站?
这很棘手,因为有两种思考方式——你可以开发网站来赶上移动应用程序的性能。
或者你可以开发更多的移动应用程序,因为它运行得更好。
这个问题的答案不是二进制的。这取决于很多因素——资源的可用性是其中之一。
也许有一个大的节日销售即将到来,你想增加你的销售。
或者,你可能正在寻求新一轮融资,而投资者对该应用的下载量很感兴趣。
决定这些取舍并不是一件容易的事情,通常由产品经理/业务分析师来完成。这就是团队合作、业务目标和收入目标的由来。
结束语
本笔记本的目的是说明典型数据科学项目的工作流程,解释数据科学职能如何与产品管理/业务分析师等其他职能协同工作。
真实世界中的数据集不会那么完美,会大得多,甚至在准备好进行处理之前,也可能需要大量清理。
然而,除了所使用的工具之外,整个过程与此非常相似。
— — — — — — — — — —
在这篇文章中表达的观点是我个人的,并不代表我现在或过去的雇主的观点。
我喜欢简化技术,分解围绕它的术语。如果你喜欢阅读,你可以在媒体和 LinkedIn 上关注我。万一我犯了什么错误,请毫不犹豫地告诉我。
使用 Choropleth 图分析全球 COVID 19 数据
Python 中与 Plotly 和 Folium 的比较
亚当·尼西奥鲁克在 Unsplash 上拍摄的照片
新冠肺炎无需介绍——它是最近席卷全球的传染病。那么,你有没有想过在过去的几个月里世界发生了怎样的变化?我们能想象几个月内不同国家的这种变化吗?
太多的问题,但我们有一个简单的答案——我们可以很容易地使用 Choropleth 地图,我会用最少的编码要求使它变得简单。
所以事不宜迟,让我们开始吧:
这将是我们今天的议程:
- 什么是 Choropleth 地图
- 叶子简介
- 使用叶绘制的 Choropleth 图
- 关于 plotly 的简介
- 使用 plotly 绘制 Choropleth 地图
- choropleth 映射的一些限制
1.什么是 Choropleth 地图
Choropleth 是基于统计变量或数据变量划分不同地理区域的地图或显示。这是一种专题地图,根据所考虑的变量和该变量在一个区域中所占的比例,对不同的区域进行着色。例如:考虑下面的图 1,它显示了不同国家的人均 GDP:
图 1:人均 GDP:作者图片
该地图使用与人均 GDP 相关的色阶来表示上图中的不同国家。
因此,创建 choropleth 地图需要两件重要的事情:
a)具有地理边界的地理空间数据,如 geo json 文件和
b)颜色编码的变量或数据点
2.叶子简介
Folium 是 Python 中的一个库,可用于可视化地理空间数据。fleed . js 是一个用于创建地图的 java 脚本库,为了创建漂亮的交互式地图,它将 fleed 的功能与 python 的数据处理能力(即清理复杂的数据集并将其转换为简单的格式)相结合。
follow 有助于绑定数据以创建 choropleth 之类的地图,还支持 HTML 可视化的标记功能。
不同的地图投影也可以像正交,自然地球等和不同的地图瓷砖像地图框,雄蕊调色剂等。
现在让我们考虑全局 COVID 19 数据集来创建 choropleth 图。您可以在参考资料中获得数据集链接。
3.使用叶绘制的 Choropleth 图
a)首先,我们需要生成基本地图。以下代码可用于此:
m = folium.Map(tiles = 'Stamen Terrain',min_zoom = 1.5)
display(m)
我们将得到这样的输出:
图 2:作者的底图
b)我们必须从 this 链接获取地理数据,然后生成 choropleth 地图层,如下所示:
url = '[https://raw.githubusercontent.com/python-visualization/folium/master/examples/data'](https://raw.githubusercontent.com/python-visualization/folium/master/examples/data')
country_shapes = f'{url}/world-countries.json'folium.Choropleth(
geo_data = country_shapes,
min_zoom=2,
name='Covid-19',
data=df,
columns=['Country', 'Confirmed'],
key_on='feature.properties.name',
fill_color='OrRd',
nan_fill_color='black',
legend_name = 'Total Confirmed COVID cases',
).add_to(m)
m
c)现在,我们将为具有该代码的每个国家添加带有确诊病例详细信息的标记。标记可以定制,我们在这里使用圆形标记:
def plotDot(point):
folium.CircleMarker(location = (point.latitude, point.longitude),
radius = 5,
weight = 2,
popup = [point.Country, point.Confirmed, point.Recovered],
fill_color = '#000000').add_to(m)covid_df.apply(plotDot, axis = 1)
m.fit_bounds(m.get_bounds())
m
这是带有已确认和已恢复病例标记的最终输出。我们可以将鼠标悬停在标记周围,按国家查看确诊和恢复病例的数量。在下图中,突出显示了印度的标记:
图 3:带有标记的 Choropleth 叶地图:作者提供的图片
现在,我们可以使用 plotly 创建一个类似的地图。
4.关于 plotly 的简介
Plotly 是一个开源的 Python 可视化库。它也可以用来创建 html 可视化的伟大的动画。与 leav 一样,这些图形是交互式的,并带有动画特性。它构建在 plotly.js 之上,可视化也可以保存为图像。它还提供了许多定制和样式选项,实现非常简单。它还与 dash 兼容,这使得它很容易嵌入到博客或其他网络应用程序中。
Dash 是一个用于构建分析应用程序的开源框架,不需要 Java 脚本,并且与 Plotly 图形库紧密集成。点击了解更多。
随着更多的观察,plotly 可能会导致性能问题。建议离线使用。
5.使用 Plotly 绘制 Choropleth 地图
现在让我们用 plotly 来构造 choropleth 图。这可以通过使用具有相同数据集的简单代码来实现,如下所示:
fig = px.choropleth(df , locations = 'Country', locationmode = 'country names', color = 'Confirmed'
,animation_frame = 'Date')
fig.update_layout(title_text = 'Global spread of Covid19')
fig.show()
输出如下所示:
图 4: Plotly Choropleth 地图(作者图片)
在这里,我们可以看到按日期排列的动画窗格,它提供了几个月来确诊病例如何在不同国家传播以及病例增长率的视图。
动画冠状动脉分布图:数月来冠状病毒的全球传播(作者作者
地图的 HTML 可视化可以使用一行代码保存,您可以在这里访问地图的 HTML 版本。
import plotly.offline as py# html file
py.offline.plot(fig, filename='C:/plotlyplots/Global_covid.html')
总结:
我们今天学习了如何使用两个不同的 python 库来创建带有新冠肺炎数据的 choropleth 地图。Plotly 在地图中通过简单的缩放、过滤和动画选项在该领域真正得分。但是,没有添加自定义标记的选项。叶尤其有助于 choropleth 和其他地图。自定义选项,如自定义弹出窗口、自定义平铺、标记和其他功能,使 Folium 成为一个可行的竞争者。此外,Folium 是专为可视化地理空间数据而构建的,而 Plotly 的用途要广泛得多。
Choropleth 地图上最后几个字:
Choropleth 地图有利于整体观察,但一个国家/地区内的一些变化可能会被遗漏,因为它假设整个区域具有相同的值。很少有其他 限制 为好,比如:
a)使用绝对计数有时会产生误导,最好使用标准化的测量单位,如比例/比率
b)边界可能不连续,大面积可能会占据显示屏。
c)由于关于数据如何分类的分类问题,可能存在准确性问题。具有图形值的未分类 choropleth 图可以消除分类中的信息损失。
尽管有这些限制,但 choropleth 图仍是进行实证研究和地理空间分析的一种非常有用的方法。
如果你有任何问题,请联系我,并留下你的意见。
完整的代码可以在 Github 上获得。
可以通过媒体、 LinkedIn 或 Twitter 联系到我。
参考文献 :
[1] Jochen Schiewe,关于 Choropleth 地图中空间模式视觉感知的实证研究 (2019),Springer
[2] Jeffrey S. Torguson, Choropleth 地图 (2017),威利在线图书馆
[3]Robert G . Cromley 和 Ellen K Cromley, Choropleth 地图图例设计用于可视化社区健康差异 (2009 年),《国际卫生地理杂志》
[3]Python 中的 Choropleth 地图,Plotly 文档
[4]Python 中的 Choropleth 地图,leav 文档
[5]约翰·霍普斯金大学,新冠肺炎数据集参考文献
分析纽约时报新冠肺炎数据集
创建一个简单的 Python 类来分析和可视化来自纽约时报的新冠肺炎数据集。
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
介绍
自第二次世界大战以来最大的全球性危机和自 1918-1919 年西班牙流感以来最大的全球性疫情今天就在我们面前。
每个人都在关注死亡人数的每日上升,以及这种新型病毒的快速指数传播。
有一些非常丰富的数据可视化和分析仪表板来跟踪世界各地发生的事情。
仪表盘从 开始
然而,如果能够自己编写简单的 Python 代码,并为不断出现的所有这些数据绘制趋势线或条形图,岂不是很棒?你想并排比较美国各州的趋势吗?你如何验证华盛顿的封锁和社交距离措施是否奏效?
在本文中,我们将快速展示如何从易于访问的数据集中创建阳性病例和死亡人数的快速图表。
注意:这不是一个预测模型,将来也不会是。这个项目的目标是只做视觉分析。没有扎实的流行病学知识或没有合作,人们不应该仅仅从时间序列数据中建立任何预测模型。
纽约时报数据集
《纽约时报》是新闻业的一个神圣的名字,它正在做他们最擅长的事情——在新冠肺炎问题上带来高质量、数据驱动、客观的分析、事实和观点。 他们制作了所有与新冠肺炎相关的文章,供世界上的任何人免费阅读 ,也就是说,把它们从付费墙后面拿出来。
专注于美国各州和县,他们也一直维护一个简单而全面的数据集,用于他们的日常地图。
然而,如果能够自己编写简单的 Python 代码,并为不断出现的所有这些数据绘制趋势线或条形图,岂不是很棒?你想并排比较美国各州的趋势吗?
包含重要信息的简单数据集
NYT 数据集易于使用和探索,因为它只列出了大多数人感兴趣的数据片段,
- 案例数量
- 死亡人数
并且,它包含了自 1 月下旬以来的数据,即华盛顿州首次报告病例的时间。
但是,我们将会看到,利用这组简单的数据,可以创建相当多有趣的可视化效果。
没有恢复数据
你可能会问为什么它不记录恢复的次数。这听起来可能是明智之举,但要记录这个数字却非常困难。这是因为许多病例,甚至是未报告的病例,都属于这一类——人们无需去医院就能自动康复。在大多数这样的情况下,数据没有得到适当的维护(如果这个人住院的话就会这样)。
因此,我们不应该太担心没有这些数据,因为在没有适当控制的收集相关信息的方式的情况下,这些数据不应该用于简单的绘图和模型中。
只有累积数据
《纽约时报》数据集的一个缺陷是,它仅以累积的方式获取新冠肺炎病例和死亡数据。然而,当谈到可视化时,人们对累积的和每天的数据都感兴趣。
尽管累积数据提供了病毒总体影响/传播的感觉,但每天的新病例数据提供了传播速度的良好指示,并可以告诉我们它是否显示出任何放缓的迹象。
所谓的“疫情高峰”只能在新增病例或死亡的逐日图表中看到,因为累积图表只会显示单调增加的趋势。
因此,我们处理数据集来提取这些信息。
我们的 Python 脚本
简单的面向对象设计
为了保持面向对象软件设计的良好实践,我们决定编写一个 Python 类,它可以将原始数据和实用方法封装在一个容器中。
直接从纽约时报 Github 获取数据
这个想法是要与时俱进,因为全国的情况每天(事实上,每小时)都在变化。《纽约时报》的人似乎每天都在某个时间更新数据集,并在他们的 Github repo 上保持相同的文件名。因此,我们有一个简单的方法直接从他们的 Github repo 中提取数据并更新内部数据集。
查看数据集
一个简单的 peek 方法可以让我们在进一步处理之前快速查看原始数据。请记住,“病例”和“死亡”列仍然是此时的累积数据。
创建州级和县级数据集
《纽约时报》的默认数据集是一个平面 CSV 文件,其中有一列是州或县的名称,但它不适合绘制新冠肺炎病例或比率(按州或县)。
我们使用简单的 Pandas 过滤技术创建内部字典来存储每个州和县的数据。更重要的是,这是动态的,并且与最新版本的数据相关联。因此,如果某个县今天出现了第一例病例,那么该县只会在今天出现在我们的内部数据集中,而不会在此之前出现。
也是在这种州级和县级数据中,我们提取了每天的新增病例和新增死亡病例。第一行将显示 NaN,因为在此之前没有数据。
尽管累积数据提供了病毒总体影响/传播的感觉,但每天的新病例数据提供了传播速度的良好指示,并可以告诉我们它是否显示出任何放缓的迹象。
条形图
现在,是时候将这些州级或县级数据可视化为时间序列了。同样,Jupyter 笔记本中给出了函数的详细信息。用户可以简单地传递一个州的名称,
- 累积案例
- 累积死亡人数
- 每天新病例
- 每天新增死亡人数
仅最近 30 天的数据
用户还可以选择只绘制最近 30 天的数据,而不是绘制 1 月下旬以来的所有数据。
比较线图
统计数据中最受争议和关注的一个问题是,各州对新冠肺炎病例的处理情况如何。我们提供了一个简单的函数来并排绘制任意数量的状态。用户必须传递一个州名列表。
各州排名
尽管听起来很可怕,但毫无疑问,我们总是在辩论各州在阳性病例和死亡的严峻统计数据方面的排名。
一个简单的方法允许你绘制排名靠前的州的条形图。此外,您可以选择一个特定的日期来创建这个排名图,这样您就可以检查各州的相对位置是如何随时间变化的。
例如,我们在下图中绘制了 2020 年 3 月 22 日排名前 4 的州。
更多待添加
本文的主要目标是展示任何人,即使是对 Python 数据分析有初步了解的人,都可以快速完成一个小项目,从基于 web 的来源提取数据并创建方便的可视化。
又一个重要的提示。
这不是一个预测模型,将来也不会是。这个脚本的目标是只做可视化分析。没有扎实的流行病学知识或没有合作,人们不应该仅仅从时间序列数据中建立任何预测模型。
这是一项正在进行的工作,更多的可视化可以稍后添加。也欢迎其他数据科学家同事利用这种方法,使用我的代码并对其进行扩展。请让我知道你是否用它来进行分析和可视化。
再次, 演示 Jupyter 笔记本在这里 。
如果您有任何问题或想法要分享,请通过tirthajyoti【AT】Gmail . com联系作者。此外,您还可以查看作者的 GitHub 知识库,获取机器学习和数据科学方面的代码、思想和资源。如果你和我一样,对人工智能/机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
[## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…
通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和有趣…
www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)
分析医学背景下的线性分类器混淆矩阵。
Jules Bss 在 Unsplash 上的照片
构建分类模型时,最具挑战性的任务是评估性能。广泛使用的一个基本指标是混淆矩阵。在本教程中,我将尝试解释混淆矩阵和正确的阅读方法。
覆盖的是什么?
- 混淆矩阵结构和术语。
- 一类和二类错误。
- 准确性悖论。
- 精确度和召回率。
- 累积精度曲线— CAP 分析
- 受试者工作特征— ROC 分析
- 曲线下面积——AUC
- 延伸阅读—发表的学术论文。
1.什么是混淆矩阵?
它是一个维数为 N*N 的矩阵,允许从分类模型中提取有意义的度量,这有助于评估性能。它被视为预测质量的总结报告。
怎么读?
混淆矩阵的水平轴代表实际值,而垂直轴代表预测值。例如,在下面演示的 2X2 混淆矩阵中,有两个数据类;阳性病例(1)和阴性病例(0)。模型的阳性预测可能是真阳性或假阳性情况。真正的阳性预测(TP)定义为模型对阳性病例进行正确分类的次数。相比之下,假阳性预测(FP)是模型对阳性病例进行错误分类的次数。同样,真正的负面预测(TN)被定义为模型对负面情况进行正确分类的次数。相反,假阴性预测(FN)是模型对阴性病例进行错误分类的次数。
混乱矩阵解剖学
正如你可能注意到的,正确的预测落在矩阵对角线上。
FP 也被定义为 I 型错误,它表示我们的模型错误地预测了多少个阴性病例为阳性病例。FN 被认为是第二类错误,它表明我们的模型错误地预测了多少阳性病例为阴性病例。
从矩阵中提取度量
可以使用几个重要的度量来评估该模型。我们将一个一个地检查它们。让我们从基本的开始。
分类预测模型产生的混淆矩阵示例
- 准确性:分类器正确的频率。是对角线值之和与总例数之比:(TP+TN)/(TP+TN+FP+FN)—1500/1650 = 0.91。
- 错误率:所有错误预测与总案例之间的比率。误差率范围从 0 到 1;最好的是 0,而最差的是 1。(TN)/(TP+TN+FP+FN)—500/1650 = 0.30。
- 准确率:所有正面预测与总案例之间的比率。最好的准确率是 1,最差的是 0。(TP)/(TP+TN+FP+FN)—1000/1650 = 0.61。
- 特异性(阴性率):真阴性与真阴性和假阳性之和的比率。(TN)/(TN+FP) — 500/600 = 0.80。
然而,仅仅考虑准确性不足以恰当地评估模型。一个模型可能有很高的精确度,但在预测中并不可靠,这是由于类别不平衡造成的。因此,除了准确性之外,还有其他用于评估的方法,如精确度和召回率。
- 精确度:有多少被预测为阳性的结果是真正的阳性病例。要确定模型精度,请计算真阳性与真阳性和假阴性之和之间的比率。(TP) / (TP + FP) — 1000/1100 = 0.90。
- 回忆(敏感度):假设案例确实是阳性的,那么案例是阳性的频率。(TP) /(TP + FN) — 1000/1050 = 0.95。
在这种情况下,我们可以将结果解读为:预测类的 90% (精度)原来是 1(正)。而 95%的(回忆)阳性类别被模型成功预测。
精准与召回
使用哪一种取决于应用程序和您想要的结果类型。您可能已经注意到, Precision 使用 FP(第一类错误)而 Recall 使用 FN(第二类错误)。根据经验,当 FP 或 I 类误差比 II 类误差更重要时,使用 Precision。相反,当假阴性比假阳性更重要时,使用回忆,尤其是在医学研究中。
Precision 使用 FP(第一类错误)而 Recall 使用 FN(第二类错误)
如前所述,由于准确性悖论,我们需要更多的方法来评估我们的模型。累积精度曲线 CAP 和接收器工作特性曲线 ROC 就是这些方法中的一种。
2.累积精度曲线上限
通过将曲线与直接获得最大数量正面结果的完美上限和正面结果平均分布的随机上限进行比较,上限可用于评估模型。维基百科
准确率——曲线下的面积,定义为生成模型下的面积与完美模型下的面积之比(见下图)。该比率范围在 0 和 1 之间,越接近 1 的模型越精确。例如,下面的模型假设联系的客户数量和退货销售之间存在关系。计算返回最大购买量的最小顾客数是一个优化问题。如图所示,好的模型(绿线)越接近完美的模型(蓝线)就越好。
累积精度曲线— CAP
这些曲线可以根据下表进行评估:
评估上限时应遵循的假设规则
3.接收机工作特性曲线 ROC
累积精度曲线上限与接收器工作特性曲线 ROC不同。
受试者工作特征(ROC)曲线用于更广泛的领域,并经常用于医学研究。ROC 是一种基于两个因素评估模型性能的方法:特异性和敏感性。正如我们前面提到的,敏感性是真阳性率,特异性是假阴性率。ROC 曲线在 y 轴上代表灵敏度,在 x 轴上代表(1-特异性)。每个轴从 0 开始,到 1 结束。
ROC 曲线
更详细地说,假设有三个不同的模型。两个分布之间的重叠区域代表 FN 和 FP,如下图所示。第一个模型代表了一个完美的分类器(完美的分类——没有重叠)。
完美分类器
第二个模型也被认为是一个好模型。曲线下的面积(AUC)很小,且分布均匀。
好的分类器
然而,最后一个模型是预测模型的坏例子,并且被认为在区分 class_1 和 class_2 方面是弱的。
错误的分类器
曲线下面积或 AUC 是用于评估分类器的基本度量,特别是对于不平衡的类别,这是使用 ROC 的一个相当大的好处。
外卖食品
- 在敏感性和特异性之间应该有一个平衡;否则,模型会陷入过度拟合的陷阱。
敏感性和特异性的关系
- ROC 曲线的解释与累积精确度曲线(CAP)相同。只要模型处于向上的正确方向,它就表现得更好。
- 重要的是要注意,具有有意义的性能水平的分类器通常位于随机(基线)和完美线之间的区域。
- 帽子不摇。
- FN(假阴性)是第二类错误,而 FP(假阳性)是第一类错误。
- 如果第二类错误对你的模型更重要,使用召回措施;否则使用 type-I 错误。
- 正确的预测落在混乱矩阵的对角线上。
- 该模型不能仅基于准确性进行评估,它可能会由于类别不平衡而产生误导。例如,考虑 ROC AUC 曲线。
参考
最后,我希望我的帖子能帮助你理解模型评估的不同方法,以及你应该考虑哪一种。感谢阅读!!
分析 YouTube 话语并使用 Python 找到巨魔机器人
使用 YouTube 数据 API 分析 YouTube 评论中的政治话语并识别机器人
正如你在选举年可能会预料到的那样,社交媒体如今充斥着政治话语——其中一些合理且富有成效,许多具有煽动性。关于社交媒体的两极分化“回音室”效应,以及有针对性的虚假信息运动和假新闻,已经有大量文章发表。为了研究 YouTube 上的政治话语,我将解释如何使用免费的 YouTube 数据 API 将 YouTube 评论收集到一个有趣的数据集中。然后,我们将使用一些数据科学工具,如 Pandas 和 Plotly,来可视化这个数据集并寻找模式。YouTube 上的数据量是巨大的,所以我将这个项目的代码开源,以鼓励其他人也进行他们自己的分析。如果你愿意,请跟随代码!
由 Kon Karampelas 在 Unsplash 上拍摄的照片
使用 YouTube 数据 API 收集数据
YouTube 数据 API 允许每天多达 10,000 个请求免费检索 YouTube 视频、播放列表、评论和频道的信息。这些都可以在 YouTube 上公开获得,但是 API 使得检索变得更加容易。第一步是生成自己的个人 API 密匙。您将需要使用它来替换附带代码中的占位符,以便发出 API 请求。
在我的程序中,您指定要抓取的频道列表,每个频道要抓取多少个视频,每个视频要抓取多少页评论。(就我的分析而言,我想获得主流政治新闻频道与各种意识形态倾向的混合,如 CNN、MSNBC 和福克斯新闻频道。)程序然后处理 API 请求,这些请求返回包含所请求数据的 JSON 响应。经过一点解析后,这个数据可以附加到 Pandas 数据帧中,当最后一个 API 请求完成时,这个数据帧可以保存到 CSV 文件中。如果我们收集更多的数据,可以在以后更新这个 CSV 文件,并且当我们想要运行分析时,可以将它加载回数据帧。以下是运行一些收集后的示例(请注意,我们在这里筛选的唯一内容是频道,我们没有专门选择政治评论):
我们的数据库包含成千上万的评论和它们的元数据。我们希望确保每条评论都能追溯到发布它的视频、发布它的用户以及其他相关信息,如赞数和时间戳。如你所见,有很多政治性的内容。图片作者。
目前,我也在探索更多的小众政治渠道,看看它们与大网络有什么不同。我鼓励你尝试从各种渠道收集数据——可能是你订阅的渠道,也可能是 YouTube 算法向你推荐的渠道。
基本分析:关键字搜索和喜欢/不喜欢细分
让我们实现一个基本关键字搜索,它将调出包含给定搜索词的评论。Pandas 提供的 DataFrame 抽象使得按频道名称过滤变得非常容易,比如计数和其他特性。
# select the rows that contain the query string (case insensitive)
subset = df[df["textOriginal"].str.contains(query, case=False)]
以下是“covid”的两个不同结果,显示了对新冠肺炎疫情政治的高度分歧的世界观:
美国最大的威胁。Don the Con,双手沾满了 190,000 新冠肺炎人的鲜血,并谎称其对美国公众构成威胁。
疾控中心说,COVID 只杀了 9200 人。其他死于 COVID 的人都患有严重的疾病,或者死于完全不同的疾病,只是测试呈阳性。现在结束所有的封锁!
接下来,我们将生成一个按时间顺序排列的视频条形图,显示他们喜欢/不喜欢的细目分类。为此,我们必须返回到 YouTube 数据 API 来检索评论数据库中每个唯一视频的完整数据(这是因为 CommentsThread 请求的 API 响应提供了每个评论视频的 videoID,但没有提供附加信息,如喜欢和不喜欢的数量)。我确定的实现是创建一个单独的视频数据库,它有自己相应的数据帧和 CSV 文件,并给它一个同步功能,这将确保它有评论数据库中出现的所有视频的信息。
可视化一组最近的福克斯新闻频道视频的喜欢/不喜欢比率。我真的很好奇那个令人厌恶的视频是什么!图片作者。
为了制作如上图所示的条形图,我使用了 Plotly Express,它的bar()
功能使得创建美观的交互式图表变得非常容易:
# take video database's DataFrame: sort, filter, plot
df = vdb.df.sort_values(by="publishedAt")
if channelName:
df = df[df["channelName"] == channelName]
fig = px.bar(df, x="videoId", y=["likes", "dislikes"], hover_data=["channelName", "title", "publishedAt"])
fig.show()
中级分析:word2vec 和 t-SNE
关键词搜索很棒,但它应该会让你觉得我们几乎没有挖掘 10 万条评论的潜力。让我们用单词嵌入来提升我们的分析,特别是 word2vec 。
顾名思义,word2vec 将单词转换成高维向量。这样做的主要优点是,以相似方式使用的单词将被转换成相似的向量(具有高余弦相似度的向量)。这样,具有相似含义的不同词汇标记——像“GOP”和“Republicans”——就可以映射到 100 维超空间中的相似位置(听起来像科幻,我知道)。这个方法允许我们在数据集中找到更有趣的模式,幸运的是,gensim 中有一个 Python 实现。
虽然对人类来说,可视化高维多维空间是不可能的,但幸运的是,有一些方法可以将这些高维嵌入物投射到二维或三维空间中,这样我们就可以将它们包裹起来。 t-SNE 方法 将word 2 vec 向量转换成我们可以绘制和查看的东西,关键约束是它近似保持距离关系。所以超空间中距离较远的向量在 t-SNE 之后依然会很远,原本很近的向量依然会很近。
我们可以使用 word2vec 和 t-SNE 来绘制彼此相似的向量簇。关于这方面的一个很棒的教程,请查看这篇文章。给定一个单词列表,我们根据单词的嵌入性绘制出与它们最相似的单词。请注意,相似性是根据单词是否在相似的上下文中使用来定义的,因此聚类可能不总是包含语义同义词。
根据福克斯新闻频道视频的评论训练单词嵌入,使用 t-SNE 投影到二维空间。显示类似于“biden”和“blm”(即“黑人生命至关重要”)的单词。这表明评论区对 BLM 有相当负面的看法。图片作者。
根据 MSNBC 视频的评论训练单词嵌入,使用 t-SNE 投影到二维空间。显示类似于“trump”和“gop”的单词。图片作者。
矢量化并绘制整个注释
虽然绘制单个单词很有见地,但如果能够绘制整个评论,使相似的评论彼此靠近,那将会很有用。由于评论是一系列单词,我们可以尝试的一件事是对评论中所有单词的单词向量进行平均,然后绘制这个向量来表示整个评论。然而,这将使修辞学过分重视像“the”或“and”这样的普通词。为了解决这个问题,我们可以执行一个 Tf-Idf 矢量化,并在取平均值时使用逆文档频率来加权评论中的单词。这使得生僻字比普通字具有更高的权重,在 Scikit-Learn 中有一个易于使用的实现。这种方法有缺点,但它应该开始抓住 YouTube 评论的一些意义和主题。
密切相关的评论的群集(图中间的红点)。一查,都是类似“特朗普撒谎,美国人死了!”。重要的是,尽管在措辞上有一些小的不同,它们还是聚集在一起,所以评论矢量化工作正常。图片作者。
狩猎巨魔机器人
你可能听说过某些国家行为者试图通过巨魔军队和自动评论机器人来影响美国大选。我想看看是否有一种方法可以完全基于我们的评论数据库来自动检测可能的机器人活动。
有几件事我建议作为机器人活动的危险信号。一个是在短时间内发布大量评论。这要么表明一个人正在复制和粘贴评论,而不是逐字逐句地键入它们,要么表明一个自动化的机器人在工作。另一个危险信号是一个账户在多个不同的视频上发布了完全相同的评论。
使用我们的数据库,我们可以很容易地筛选给定频道上最多产的评论者,并绘制他们的评论活动。通过绘制以 10 分钟为增量的评论活动,我注意到一些帐户的活动对一个人来说非常不寻常——比如在五分钟内评论十几次多段评论。一个账号在 10 分钟内发布了 60 次完全相同的评论:
“全国范围内的内乱共和党下降 33%失业率增加两倍,19 万美国人死亡。特朗普让你的生活越来越糟糕”
有趣的是,该账户发布了同一条评论的细微变化,不同之处仅在于评论末尾多了几个标点符号。这让我怀疑该机器人被编程为逃避 YouTube 的机器人检测措施。在下面的可视化中,x 轴被分割成 30 分钟的时间增量,每个堆叠块代表同一帐户的一个评论。这些块通过视频进行颜色编码。
在短时间内(不到 90 分钟),福克斯新闻频道 YT 频道的各种视频中,一个账户有几十条反特朗普的评论。突出的评论是:“五次逃避兵役的骨刺学员,充满激情地憎恨美国军队……”作者图片。
在福克斯新闻频道 YT 频道的各种视频中,一个账户(不是上面的同一个账户)发表了几十条支持川普的评论。突出显示的评论是:“巴尔的摩马里兰州黑人和棕色人前伯尼·桑德斯的支持者在特朗普的火车上!!!!特朗普永远!!!!!"图片作者。
这类活动还有很多例子。机器人似乎有各种各样的策略。他们中的一些人只是在一个视频上重复发布相同的评论。有的在各种视频上发布各种评论。据我所知,每个机器人都保持一致的支持特朗普或反对特朗普的立场,但在其他方面似乎遵循非常相似的策略。我查阅了几个机器人的档案,没有一个一致的模式。有些只有很少的相关信息,并且是在过去几个月内创建的。有些人喜欢视频和播放列表,似乎曾经属于真人。
结论
根据我们的分析,我们注意到政治分歧的双方都有许多煽动性的言论。我们可以使用数据科学和计算语言学来寻找这种话语中的模式。使用该数据集,进一步的分析可以探索以下一些内容:
- 什么特征可以预测一条评论会获得多少赞?
- 我们能不能长期跟踪一个 YouTube 用户,看看我们能否根据他们的评论来衡量任何激进行为?
- 我们能否训练一个文本分类器(或许使用神经网络),能够准确区分支持特朗普和反对特朗普的情绪?
另一方面,CNN、福克斯新闻频道和 MSNBC 等主流新闻媒体似乎对巨魔机器人存在严重问题。许多账户在他们的视频上发布高度煽动性的评论,偶尔每分钟多次。有趣的是,政治光谱的两边都有机器人——支持和反对唐纳德·特朗普。根据一些理论,这可能是试图削弱人们对美国民主和即将到来的选举的合法性的信心。
我希望这篇教程能让你对如何在 Python 中使用 API、如何用 Pandas 组织数据库、如何用 Plotly 可视化以及如何在 Python 中使用单词嵌入有所了解。我鼓励你们收集自己的数据,并以代码为起点进行自己的调查。分析 YouTube 上的政治话语还有很多工作要做,更不用说整个社交媒体了。我很乐意听到您的反馈以及您的任何发现!
参考
[1] Gensim word2vec,【https://radimrehurek.com/gensim/models/word2vec.html】T2
[2] "sklearn.manifold.TSNE ",Sci-kit Learn 文档,https://Sci kit-Learn . org/stable/modules/generated/sk Learn . manifold . tsne . html
[3] YouTube 数据 API,https://developers.google.com/youtube/v3/docs/
[4]“普京正在偷下一次选举的路上”,The Atlantic,https://www . theatlantic . com/magazine/archive/2020/06/Putin-American-democracy/610570/。
[5]“t-SNE”,劳伦斯·范德马腾,https://lvdmaaten.github.io/tsne/
[6]“谷歌新闻和列夫·托尔斯泰:使用 t-SNE 可视化 Word2Vec 单词嵌入”,谢尔盖·斯梅塔宁,https://towards data science . com/Google-News-and-Leo-Tolstoy-Visualizing-Word 2 vec-Word-embedding-with-t-SNE-11558 D8 BD 4d
[7] "TfidfVectorizer ",scikit-learn,https://scikit-learn . org/stable/modules/generated/sk learn . feature _ extraction . text . TfidfVectorizer . html
基于 Python 的 WhatsApp 聊天分析器
以有趣的图表形式分析你的 WhatsApp 聊天
几周前,我和妻子开始查看我们去年在 Whatsapp 上的聊天记录。消息太多了,我们简直无法一一查看。我使用 Python 已经 3 年多了,我想创建一个非常简单的分析器,为我提供一些关于我们 WhatsApp 聊天的有用见解。生成的图表非常有趣。
在本文中,我将介绍我为分析 WhatsApp 聊天而创建的 GitHub 存储库。
分析在线演示:
要查看易于使用的在线演示,而不经历安装存储库和 Python 包的麻烦,请单击下面并按照说明进行操作。
什么是 AnalyzeTheChat?
AnalyzeTheChat 是一个基于 Python 的存储库,为你的 WhatsApp 聊天生成有用的统计数据。它会抓取提供的。txt 文件,并生成一个熊猫数据帧。然后对该数据帧进行处理,以绘制以下接触式和时间式统计数据
联系方式统计:
- 每个联系人的消息数量
- 每个联系人的字数
- 每个联系人每封邮件的平均字数
- 每个联系人的表情数量
- 每个联系人每条消息的平均表情数量
- 每个联系人的媒体数量
- 每个联系人的关键字数量
时间统计
- 每小时的消息数量
- 每个工作日的邮件数量
- 每月的邮件数量
- 每年的邮件数量
下面是一个生成统计数据的示例
图片:【https://github.com/aqeelanwar/AnalyzeTheChat
如何安装 AnalyzeTheChat?
建议为这个项目创建一个新的虚拟环境(使用 python 3.6)。创建虚拟环境的详细步骤可以在这里找到
1.克隆存储库
创建虚拟环境后,激活它,并使用以下命令克隆存储库。
git clone [https://github.com/aqeelanwar/AnalyzeTheChat.git](https://github.com/aqeelanwar/AnalyzeTheChat.git)
2.安装所需的软件包
cd AnalyzeTheChat
pip install -r requirements.txt
如何运行 AnalyzeTheChat?
1.导出 WhatsApp 聊天
使用以下步骤导出您想要分析的 WhatsApp 聊天
- 打开 WhatsApp 聊天
- 单击右上角的三个垂直点
- 点击更多
- 单击导出聊天
- 单击无媒体
- 保存生成的。可访问的 txt 文件
图片:https://github.com/aqeelanwar/AnalyzeTheChat
2.执行代码
# Generic
python main.py --path <path-to-chat> --save_as <save-type># Example
python main.py --path theoffice.txt --keyword 'jello' --save_as pdf
3.争论
图片:https://github.com/aqeelanwar/AnalyzeTheChat
查看结果
结果以用户通过参数 save_as 选择的格式保存在结果文件夹中。
总结:
AnalyzeTheChat 是一个基于 python 的 WhatsApp 聊天分析器,可以生成有趣的条形图。它可以用来分析一个人或一个群聊的活动,以推断出有用的结果。在线演示可以在这里找到
用 Python 代码分析 A/B 测试结果
照片由mārtiņš·泽姆利克斯在 Unsplash 上拍摄
A/B 测试的七个步骤,以及如何选择能给出 p 值的正确 Python 库。
所以你设计了你的 A/B 测试。现在您运行它,使用您在上一步中确定的样本大小(客户数量)和天数。
现在是关键时刻了。销售团队和网页设计团队都在急切地等待你的回答:你的公司为网站引入了一个新功能;这个特性是像销售团队预测的那样降低了销售额,还是像网页设计团队预测的那样保持了销售额不变?
基本上是销量减少了还是没有?
他们还可以问“网站上的新功能是减少了销售额还是增加了销售额?”。这是有区别的——第一个询问是否有变化,第二个询问变化是积极的还是消极的。我们稍后将讨论第二个问题。
我们在之前的帖子中讨论过 p 值。在那篇文章中,我们还研究了68–95–99.7 规则。p 值和 68–95–99.7 规则以一定的置信度回答了上述问题。
运行 A/B 测试的步骤
- 确定您将运行测试的天数
- 确定样本量——每天有多少客户
- 决定你的无效假设
- 决定你想要的自信程度
- 对 1 完全运行测试。第二。超过
- 获取 p 值
- 对零假设作出断言:要么拒绝,要么拒绝失败
问题设置示例
让我们来看看与前几篇文章相同的例子。我们的客户群平均购买价值 170 美元的产品。网站设计团队想要引入一项新功能,但是销售团队对此感到担忧。您运行 A/B 测试,看看新特性是否会改变平均订单值。你将有一个对照组,他们将看到旧的网站,还有一个目标组,他们将看到有新功能的新网站。
1.确定您将运行测试的天数
我们在之前的帖子中讨论过这个问题。让我们假设我们将运行测试 14 天。
2.确定样本量——每天有多少客户
我们在之前的帖子中也讨论过这个问题。假设我们的样本中有 10,000 名客户。
3.决定你的无效假设
在这种情况下,零假设是新特征不会改变平均阶数值。也就是说,对照组和目标组的平均订单价值都是 170 美元。换句话说,控制组和目标组将从相同的人群中抽取,就好像他们看的是同一个网站。这是我们将要检验的假设。
4.决定置信水平
通常,企业会告诉你他们对结果的信心水平。一般来说,大多数企业采用 95%的置信区间。也就是说,你要 95%确定控制组和目标组来自同一人群;也就是说,如果控制组和目标组在 5%的时间里看起来不像来自同一个群体,这是可以的。所以我们的临界 p 值将是 0.05。
5.运行测试
现在坐下来,对 1 中确定的参数进行测试。第二。没有峰值。如果你需要达到峰值,我们需要设计一个不同的 A/B 测试,比如 Bandit 测试。A/B 测试首先探索,然后在测试结束后利用。一个强盗同时探索和利用,或者学习和赚钱。
我们正在进行 A/B 测试,所以让我们探索整整 14 天。每天我们向对照组展示旧网站,在测试结束时,我们会有 14 个平均订单值。在这 14 天中的每一天,目标群体中的客户都会看到新网站,在测试结束时,我们还会看到他们的 14 个平均订单值。
像这样:
control means = cm = [169.84, 166.66, 170.5, 168.09, 168.36, 171.28, 169.53, 169.25, 171.66, 171.03, 168.89, 171.04, 171.20, 170.22]target means = tm = [174.54, 171.95, 177.06, 174.33, 174.85, 174.34, 176.89, 176.71, 172.81, 176.22, 177.45, 177.10, 175.23, 177.09]
6.获取 p 值
有许多方法可以从两个样本中获得 p 值。
在这种情况下,我们将比较两个样本,看它们是否相似。Kolmogorov-Smirnov 测试是最简单的方法之一,也在 Python 中实现。
import scipy.stats as stats
stats.ks_2samp(cm, tm)
给你:
Ks_2sampResult(statistic=1.0, pvalue=4.985467362637908e-08)
这个 p 值是什么意思?这意味着,给定上面给出的对照样本平均分布(cm 的数组),我们获得上面的目标样本平均分布(由数组 tm 给出)的概率是 5.0x10-⁶ %(来自上面的 pvalue 4.985467362637908 e-08 乘以 100)。也就是说,目标样本来自与对照样本相同的群体的概率非常非常低,约为十亿分之五十。
7.对零假设作出断言:要么拒绝,要么拒绝失败
5.0x10-⁶ %的 p 值比我们在上面第 4 步中设定的容差 5%要小得多。因此,看来我们必须拒绝目标样本和控制样本来自同一人群的假设。
让我们实际绘制上面 cm 和 tm 给出的控制和目标均值,看看它看起来像什么:
如果我们用蓝色绘制控制平均值(上面的 cm 阵列),用橙色绘制目标平均值(上面的 tm 阵列),我们会发现它们确实不同,与顶部的图不同。控制均值似乎以 170 美元为中心,而目标均值似乎以 175 美元为中心。如果您查看每对数组(对照减去目标)之间的差异,您会得到底部图,该图显示每天目标平均值都高于对照平均值(x 轴始终为负)。
所以目标均值始终不同于控制均值。这就是我们的 p 值所暗示的。
注意,目标平均值实际上一直高于控制平均值,但这不是我们在步骤 3 中试图发现的;我们试图发现对照样本和目标样本是相同还是不同,而不是更高或更低。所以我们无法对此做出具体的结论。如果这是一个真正的问题,我们将不得不运行另一个 A/B 测试来找出答案。比赛开始后不要移动球门柱!
示例 2
让我们看第二个例子:
cm = [169.84, 166.66, 170.5, 168.09, 168.36, 171.28, 169.53, 169.25, 171.66, 171.03, 168.89, 171.04, 171.20, 170.22]
tm = [169.66, 167.14, 172.11, 169.44, 169.95, 169.46, 171.94, 171.77, 167.97, 171.29, 172.49, 172.14, 170.33, 172.13]
stats.ks_2samp(cm, tm)
Ks_2sampResult(statistic=0.42857142857142855, pvalue=0.15493471530488623)
在这种情况下,由于 0.15 的 KS 检验 p 值大于 0.05 的临界 p 值,我们说我们未能拒绝零假设;我们不能否认对照样本和目标样本来自同一分布。
鉴于‘拒绝失败’是一个双重否定,难道它不意味着我们接受零假设吗?不,不是的。我们永远不能接受零假设,或者说两个样本来自相同的分布,有 100%的把握。为什么?因为我们一开始就给自己定了一个 95%自信的目标。再次声明,比赛开始后,不要移动球门柱。
你可能会问,我们能不能不把信心水平定在 100%呢?如果我们这样做,我们的尾部容差将是 0.0(从 100%–100%;之前,当我们要求 95%的置信度时,我们的容差是 5%)。也就是说,我们的临界 p 值是 0.0,无论我们做什么,实验的 p 值总是高于 0.0,我们必须始终拒绝零假设。
使用哪种算法来比较两个样本
Python 有许多用于计算 p 值的库。您可以使用它们中的任何一个,语法同上。
我们应该使用哪一个?这里有一个宽松的指导方针:
双样本 t-检验(学生 t-检验)如果您确信控制样本和目标样本均值呈正态分布
或
如果您测试超过 30 天(因为超过 30 天中央极限定理开始生效并保证常态— 30 不是一个神奇的数字,但在行业中被广泛接受。)
Kolmogorov-Smirnov 检验(KS 检验)你无法保证对照和目标均值呈正态分布
或者
你的测试中没有多少天(工业上公认 30 天左右就足够了,虽然这个数字背后并没有什么魔力。在任何情况下,没有企业会允许你运行 30 天的 A/B 测试。)
或
你认为两个样本的均值、方差和分布形状是一样的。
或
如果你想捕捉一天中控制样本和目标样本最大的不同,使用这个测试。KS 测试对测试中最大的差异很敏感。
Mann-Whitney 秩检验你无法保证控制和目标均值呈正态分布
或者
你的测试中没有多少天(工业上公认 30 天左右就足够了,虽然这个数字背后并没有什么魔力。在任何情况下,没有企业会允许你运行 30 天的 A/B 测试。)
或
你认为两个样本的均值、方差或分布形状不同。
如果您不确定使用哪一个,一个好的经验法则是使用 Mann-Whitney 秩检验。
这个故事的寓意
- 如果测试 p 值< critical p-value reject the null hypothesis
- if test p-value >临界 p 值未能拒绝零假设
两个重要的教训
- 假定零假设为真,p 值给出了我们观察到的现象的概率。它没有告诉我们零假设为真的概率。
所以在我们的第一个例子中,零假设是目标样本和对照样本都来自同一人群。那么我们可以说,假设目标和对照样本均值 tm 和 cm 都来自同一个总体,那么观察到它们的概率是 5.0x10-⁶ %。十亿分之五十的机会,非常小的概率。所以我们拒绝零假设:我们拒绝两个样本来自同一个分布的假设。
它没有告诉我们零假设本身为真的概率。
开车回家是一个很难的教训。但总的来说,在生活中,我们无法说出任何假设为真的概率——我们所能说的只是根据某人的假设进行观察的概率。
2.有了 p 值,我们要么拒绝零假设,要么无法拒绝零假设。你永远不能接受无效假设。
没有拒绝原假设不等于接受原假设。这是因为当我们设定置信水平时,我们总是将自己设定在 100%以下,这意味着我们永远不能 100%确定零假设是真的。
分析 NHL 曲棍球的十年
2010 至 2019 赛季
塞斯·赫夫曼在 Unsplash 上拍摄的照片
T4 我第一次穿溜冰鞋的时候,只有 6 岁。我的弟弟才 4 岁。9 岁时,我开始接受花样滑冰训练。一天,当冰球队到达时,我正试图做一个非常简单的跳跃,我正努力跟随溜冰场右边的圆圈。我不知道该怎么解释。他们停下来时溜冰鞋在溜冰场上的声音让我大吃一惊。车轮撞击瓷砖的声音。传球时球撞击球棍的微妙声音。那天我被卖了。训练结束后,我和我的教练谈了谈,当天我就换成了曲棍球。我整个业余生涯效力的那个俱乐部的主席给了我她儿子的球棍,是给初级球员用的小球棍。我这辈子再也没想过滑冰了。从那天起,我成了一名冰球运动员,并自己发出了那美妙的声音。这不是冰球。这是直排轮曲棍球,四个轮子平行。
这项工作的动机
今天我不再打冰球了,也没有机会打冰球了。在这项工作中,我结合了我的两个爱好:数据科学和曲棍球。
这项工作的主要动机是开始寻找一些关于过去十年曲棍球成绩的问题的答案。我将根据我在 Kaggle 中找到的数据回答以下问题。
- 联盟中最好的守门员有哪些?
- 联盟最佳得分手球员有哪些?
- 进球多的球队有哪些?
- 每支球队中罚分最多的球员是谁?
- 生产 NHL 球员最多的国家是哪个?
让我们开始分析。在我的 GitHub 存储库上可以找到关于几个 CSV 文件的细节和数据清理与合并的笔记本。
“出产更多 NHL 玩家的国家”图来源此处。该图被上传到 Tableau public 以便于访问。
联盟中最好的守门员有哪些?
我从守门员开始,因为当我在工作中接触到他们时,我发现了一个非常重要的关于扑救百分比的问题。如果我们根据扑救百分比得分按降序绘制前 10 名守门员的图表,我们会得到以下图表:
这里发生了什么?他们中没有一个是我们在每场比赛中经常看到的守门员,他们都有 100%的平均扑救率!答案是这些大多是“紧急守门员”。你还记得黑鹰队著名的签约紧急守门员斯科特·福斯特 吗?他在该队任职期间从未参加过正式比赛。直到 2017-2018 赛季的那个幸运的夜晚,所有黑鹰队的守门员都受伤了,他被叫出来(终于)穿上衣服。他打了“他一生中最长的 14 分钟曲棍球”,正如他在随后的无数次采访中描述的那样。他打了大约 14 分钟,没有进球,所以他的扑救率是 100%(在他的整个 NHL 职业生涯中!).为了解决这个问题,我考虑了两种选择:
以 100%的扑救率消灭所有守门员
这种选择对于经验丰富的守门员和球员来说是不公平的。经验丰富的守门员球员在已经进了 3-4 个球(或更多)时进入冰场代替首发守门员。所以在这种情况下,他们应该得到 100%的储蓄。
确定分析中需要考虑的最少季节数
这种方法也有一些警告,因为这产生了一个问题,即什么使最少季节数正确?尽管有这种担心,我还是选择了这个选项。我决定设定最少 5 个赛季,每个赛季 81 场比赛(41 个主场冰加 41 个客场)。
前 10 名守门员平均。保存百分比
现在我们看到了常见的嫌疑人。图克卡·拉斯克成为平均得分更高的守门员。拯救百分比其次是我的两个最爱:凯里·普莱斯和亨里克·伦德奎斯特。正如你在这里看到的,他们的数字非常接近。它被认为是一个 NHL 守门员!期望值非常高。
联盟最佳得分手球员有哪些?
让我们从总进球数的角度来看最好的球员。
这并没有真正告诉我们事情的全部。这不是 100%准确或公平的,因为有些球员比其他人打得更少,但每场比赛和/或每场冰上时间(每场比赛的时间)得分更多。让我们看看同样的指标,但现在考虑到玩的游戏。
前 10 名球员每场比赛的进球
每场比赛的进球数告诉我们亚历克斯·奥韦奇金保持着第一的位置,因为他打了很多比赛,也进了很多球!他几乎每隔一场比赛就进一个球。史蒂文·斯塔姆科斯以非常相似的数字紧随其后,但比奥韦奇金少打了 100 多场比赛。希尼·克罗斯比和叶夫根尼·马尔金已经跃居榜首,使得企鹅队成为一支非常危险的队伍!毫不奇怪,几乎所有人都是各自球队的队长和前锋/边锋。来自达拉斯明星队的泰勒·塞金(Tyler Seguin)出场次数明显更少,仅为 489 场,但占据第 5 位,因此他的进球非常有效。另一方面,帕特里克·凯恩在参加的比赛中排名第二,但进球很少,排名倒数第二。
让我们来看看那些花更多时间在冰上的球员,看看这是否与进球数有关。
十大防御平均值。冰上时间
按冰上时间排序(TOI)前 10 名都是防守队员。平均每场防守时间大约是 14-25 分钟。那几乎是游戏的一半!瑞安·萨特虽然没有出现在很多比赛中,但还是打了很多分钟。国王队的德鲁·多尔蒂在这十年中几乎一直打半边天比赛。
过滤掉防守球员,我们看到前锋平均 TOI。
前 10 名球员(无防守)平均。冰上时间
前锋在冰上的时间更少,因为他们倾向于滑得更多。安泽·科普塔尔、瑞恩·盖茨拉夫和希尼·克罗斯比位居榜首。亚历克斯·奥韦奇金并不在这张图表的首位,但他是一名非常有效率的球员,因为他每场比赛都有进球。
进球多的球队有哪些?
我计算了每队进球最多的 3 名球员的平均值,以此来透视每队的得分能力。下图显示了由于三名得分最高的球员,该队得分能力更强。
每支球队前 3 名得分手的总进球平均值
这里我们可以看到鲨鱼队前三名球员在过去十年中比其他球队进了更多的球。紧随其后的是最危险的队伍黑鹰和企鹅分别位居第二和第三。首都,然而,尽管亚历克斯·奥韦奇金的巨大的生产,只是在第四位。
令人惊讶的是,当看球队每场比赛的进球数时,星是每场比赛进更多球的球队(保证每 3 场比赛进 1 球!).紧随其后的是闪电、 黑豹和油工。企鹅队排在第五位,离每三场比赛进一球还差一点。
球队每场比赛的平均进球
每支球队中罚分最多的球员是谁?
令人惊讶的是这些都不是防御。他们是前锋。参议员克里斯·尼尔每 6 场比赛 10 次坐在罚球线上,高居榜首!。紧随其后的是科迪·麦克劳德和汤姆·威尔逊,他们每场比赛都坐在罚球点上。他们都以力量和身体著称。
前 10 名球员每场比赛的罚球时间
生产 NHL 球员最多的国家是哪个?
发现加拿大为国家冰球联盟提供的球员比其他任何国家都多,这并不奇怪。
从 2010 年到 2019 年生产更多 NHL 球员的国家
在过去的十年里,加拿大球员的总数达到了 1149 人。其次是美国带 651 然后是瑞典带 184 。加拿大玩家的数量几乎是美国玩家的两倍,而美国玩家的数量是瑞典玩家的四倍。
其余前 10 名的国家总共只有 380 名球员。
结论
这只是对 NHL 曲棍球十年的描述性分析。在这项工作期间,出现了很多问题,为了能够按时完成,我在这篇文章中忽略了这些问题。我计划在这篇文章的第二部分继续回答其他有趣的问题。例如,未来帖子中会出现的内容有:
- 球队如何将罚球时间与球队输掉比赛联系起来?
- 这和球队在主场还是客场比赛有关系吗?
- 在比赛的最后一节(第三节)或加时赛(加时赛)中,得分最高的球员有什么不同吗?
你最喜欢的球员出现在这部作品的排名中了吗?请在评论中告诉我。此外,让我知道你还有什么兴趣看到第二部分的分析。感谢您的阅读!
使用 Python 包分析 Babar Azam 的 ODI 统计数据-基础版
图片提供板球世界杯
要在巴基斯坦板球运动中留下印记,让你的名字出现在历史书上,你通常需要的不仅仅是几场精彩的场上表演。在这个 T20 疯狂的时代,你需要在你的游戏中充满活力,并拥有一种全力以赴的光环。你需要在媒体上喋喋不休,每隔一个月尝试不可思议的发型,放大你的运动性感度,以你的名字为名大赚一笔。
巴巴尔·阿扎姆(Babar Azam)在 2015 年出现,这个年轻、身材普通、看起来不那么大男子主义的家伙,很少有人想到他最终会重新定义和振兴巴基斯坦对蝙蝠人的看法。像巴基斯坦这样的国家,其体育历史上充满了快速保龄球现象,很少有机会珍惜这样的奇迹男孩的存在。
随着时间的推移,巴巴尔在各种形式的游戏中的表现越来越好。在他相当年轻的职业生涯中,这位 25 岁的球员已经提升到新的高度,在这个过程中打破了几项著名的击球记录。他赢得了被称为限量版一致性的新毕加索的权利,尤其是现代 ODI 板球比赛中的击球巨人。
在本文中,我使用 Python 包和工具对 Babar 的 50-over 格式的数字进行了基本的处理和分析。然而,就像这项运动本身一样,总是有增加赌注的空间,因此,更先进的数据分析技术肯定是适用的,值得一试。关于这一点的更深入的文章将紧随其后。
我首先导入所有必要的 Python 库,我将在本文中以这样或那样的方式使用它们。
然后,我使用 Cricpy 包中的函数‘getPlayerDataOD’从 ESPNCricinfo 的数据库中获取 Babar Azam 的 ODI 配置文件。传递函数参数的特定参数以提取所需的数据帧,该数据帧存储在名为“babar.csv”的. csv 文件中。我用的是熊猫的。read_csv 方法来读取和解释获取的数据。
这是我们手头的数据框架的一个快速预览。
标题为“HA”的最后一列不在从 ESPNCricinfo 楔入的原始数据帧中。我不得不使用一些基本的 MS Excel 技术手动添加它,以分析与主场和客场比赛相关的数据,我将在稍后深入研究这些数据。数据框总共有 74 行(这个片段只显示了前 20 行),指的是 Babar Azam 参与的所有 ODI 匹配。
在此之后,我执行了一些数据清理任务,其中包括清理属性名称以方便索引,检测并删除不必要的括号、逗号和破折号,去除对立列中的“相对”符号,并从击球手没有击球的数据框中删除那些匹配,即我们在跑垒列中有 DNB。我还必须考虑不同属性的错误数据类型,并使用 Pandas 函数改变它们。
Total ODI 与所有反对意见背道而驰
有了一个完善的数据框架,我现在开始探索性数据分析部分。首先,我绘制了巴巴尔在棒线图上所有对手的累计点数。
如上图所示,巴巴尔在与英国人的比赛中取得了突飞猛进的成绩。他参加了 16 场对阵 Poms 的比赛,其中 12 场是在英格兰举办的。在 2019 年对阵英格兰的六场 ODI 中,巴巴尔积累了过多的得分——340 分,平均得分为 56.67 分——包括在特伦特大桥的精彩世纪。如果这本身还不令人敬畏的话,那么他对抗温蒂家族的记录是超凡脱俗的。在巴巴尔面对他们的七场比赛中,他以惊人的平均低于 90 杆的成绩拿下了四吨。
第四次 ODI 的精彩部分,Babar 在那里得分一吨
对抗所有对手的平均打击率
在游戏的现代时代,击球率已经成为衡量板球运动员的击球能力和他对游戏的影响的重要指标,无论是在历史还是现在的背景下。巴巴尔是为数不多的在 T20Is 和 ODIs 中平均年龄超过 50 岁的著名板球运动员之一。只有少数其他击球手享受这样的壮举。
我创建了一个名为 avgOppFinder 的函数,它返回 Babar 相对于指定对手的平均值。我将该函数应用于对立列的各个组,即各个对立,并将结果序列对象转换为 Pandas 数据框。我还必须考虑到 Babar 没有出局的那几局,在清理数据时,我在 Runs 列中使用星号(*)符号来处理它。生成的数据框片段粘贴在下面:
我使用了一个散点图来显示巴巴尔的个人平均值,以递增的顺序,如气泡的大小所示。除了印度之外,巴巴尔一直保持着 40+的平均打击率,对抗所有八大 ODI 国家。鉴于他在比赛形式和标准方面的成就,他超越印度和新西兰的记录也只是时间问题。
巴巴尔·阿扎姆划定的边界的视觉表现
巴巴一直以优雅和简单的化身而闻名,并以最被低估的方式完成他的跑步。他累积分数的轻松程度是无与伦比的。他讲的不是牛角尖上的丑陋,他讲的是华丽的车道。他不是关于野外跋涉和滑雪者,他是关于交货和创造差距的巧妙机动。他不是那种把厨房的水槽扔向一切事物的人,相反,他是不祥的平静和冷静。
我试图通过描绘巴巴尔在 ODI 板球赛中所有局的界限来想象他平静的方式。上面的散点图描绘了他得到的 4 分与他达到的最高分之间的巨大反差。在他的整个职业生涯中,到目前为止,巴巴尔一局只有两次打出四个六分。事实上,大多数时候,他投了 0 或 1/6 局,但他仍然以他所拥有的好球率平均得分超过 50。巴巴尔·阿扎姆与众不同。
所有场馆的 ODI 总量
接下来,我使用另一种分组策略来根据地点总结巴巴尔的跑步记录。这里值得一提的是,Babar 在 2015 年津巴布韦对该国的历史性访问期间首次亮相巴基斯坦。尽管如此,这位右撇子还是在巴基斯坦的第二故乡阿拉伯联合酋长国打了很多比赛。正如剧情所示,他在阿联酋的沙丘上多次得分,就得分而言,阿布扎比是他得分最多的地方。巴巴尔对英国场地的热爱,尤其是对洛德桥和特伦特桥的热爱,在这些酒吧中也非常突出。然而,他在 2019 年世界杯上对阵新西兰的精彩比赛并没有在这两个场馆举行。那是在 Edgbaston(伯明翰),许多人认为这将是一个传奇人物职业生涯的转折点。
巴巴尔的职业生涯定义了 2019 年在 CWC 举行的 ton v New Zealand
每天运行的 ODI 总数
在玩巴巴尔的数字时,我偶然发现了一个有趣的统计数据,那就是他在不同的日子里积累的跑步记录的多样性。他在周二打了 7 场比赛,周日打了 17 场,周日他又跑了将近 926 次。周二,巴巴尔的最高分只有区区 22 分,还有几个个位数的分数。然而,在周日的 ODI 比赛中,巴巴尔变成了击球巨兽。在 17 场比赛中,他有四个世纪和五个半世纪的成绩,总成绩超过 1000 分。可以肯定的是,在周日的晚上,他的脚步有了额外的弹性,但是我们永远不会知道这个秘密背后的原因。下图显示了惊人的差异。
随着花费的分钟数和运行次数的变化而改变命中率
早些时候,我们讨论了 Babar 如何在折痕处保持冷静,并依靠计算的风险而不是艰苦奋斗和夹击来以更快的速度得分。尽管没有吹嘘自己的身材和体格,也没有以击球出界而闻名,巴巴尔还是设法保持了略高于 87 的职业生涯击球率,这与现代标准大致相当。
在这里,我试图描述他的命中率如何飙升到 100 分以上,以及当他花更多的时间在折痕上和面对更多的传球时,他的跑位得分能力如何进一步提高。下面,我绘制了两个散点图,它们有一个共同的 x 轴的打击率。
累积罢工率
为了进一步证明 Babar 的罢工率的一致性,我使用 Cricpy 的 batsmanCumulativeStrikeRate 函数绘制了他在整个 ODI 职业生涯中的累计罢工率。线图显示了他在职业生涯中期的击球率略有下降,但图表的后半部分显示了他在最近三场比赛中的击球率为 97.95,109.52 和 119.23,朝着顶峰不断回升。
巴巴尔的解雇
现在是时候深入研究 Babar 在 50 岁以上格式中的解雇模式了。我决定用一个饼状图来描述这一点,这个饼状图显示了到目前为止他被解雇的比例。不出所料,他已经被抓了无数次,几乎占他总解雇数的五分之三。
作为一个狂热的板球观察员,我确实意识到他出局的比例仍然偏高,但最终会下降。在他职业生涯的早期,Babar 在面对快速点击投球的投球手时,有一种发现自己的脚卡在折痕处的松散倾向。这使得他容易受到马可·伍德、乔希·黑兹伍德等保龄球手的冷不防的夹击。巴巴尔在技术上做得非常出色,以稳定他的平衡和保持稳定的形状。现在他是板球教科书认可的成品。
饼状图的另一个发现是巴巴尔对抗旋转保龄球的明显实力。在他的整个职业生涯中,他只被难住了一次,这显示了他在击球时的纪律性。这并不是说巴巴尔不用他的脚来对付旋转器,而是几乎一直呆在折痕里。通常情况下,当他不得不强行解决问题时,你会看到他在跑道上跳舞。这是他从投球手手中获得变化并相应地操纵或击打球的精确度。很少看到他被一个旋转手迷惑,然后扔掉他的三柱门。
跑步—国内和海外
巴巴尔的主客场表现有很大的反差,就像大多数打了这么多比赛的击球手一样。我尝试使用 Cricpy 中的 batsmanPerfHomeAway 函数对此进行分析,下面粘贴了一段摘录。它将击球手在国内和海外场地的得分绘制在盒须图上,以说明并排比较。如图所示,主场得分的四分位数范围比客场得分的四分位数范围大得多。得分的中位数在主场也相对较高。
预测巴巴尔的跑步
接下来,我试着制定一个基本水平的预测器,根据指定的球数和在折痕上花费的时间来预测巴巴尔的得分。我使用了 Cricpy 库中的 batsmanRunsPredict 函数,该函数拟合了击球累计次数和花费时间之间的线性回归平面。为了检索正确的数据,我不得不忽略 BF 和 Mins 列中有破折号(-)的那些比赛,这是指该信息对于特定游戏不可用的事实。我将输出的 Series 对象转换成数据帧并打印出来,如下所示:
我还利用 batsmanScoringRateODTT 函数的帮助,根据 Babar 面临的递送,在他进行的运行之间使用二阶多项式来进一步计算和绘制 Babar 的预测得分率。
巴巴尔与 Fab Four 的比较
很长一段时间以来,国际板球界谈论的话题是巴巴尔如何融入享有盛誉的 Fab Four 集团?他是第五个吗?他如何与优雅、高贵的乔·鲁特、稳重、镇定的凯恩·威廉姆森、潇洒、大胆的维拉特·柯利以及异端、无情的史蒂夫·史密斯正面交锋?他真的有能力吸引现代击球巨人的眼球吗?
为了进行这些比较,我必须首先从 ESPNCricinfo 中检索所有这四名球员的数据帧,方法与我在本文开始时使用的方法非常相似。然后,我使用名为 relativeBatsmanCumulativeAvgRuns 的函数的一部分来计算所有五个玩家的累积平均值,如上面的 for 循环所示。compRuns 函数是我自己定义的函数,用于执行所有这些计算并绘制结果,如下所示:
正如这个线图所示,巴巴尔的累积平均得分遥遥领先于威廉姆森和史密斯等人。他甚至在最初的 70 局 ODI 比赛中击败了庞大的 Virat Kohli。当然,大约就在这个时候,Kohli 的地位加速上升到了前所未有的高度。然而,这并不意味着我们可以忽视巴巴尔在其职业生涯早期所记录的怪异数据。
另一个证明巴巴尔符合精英击球手群体设定的标准的标准是巴巴尔在他的前 70 场比赛中的得分数,与所有四名击球手在各自的前 70 场比赛中的得分数相比。巴巴尔又一次以可观的优势击败了所有人。他是 ODI 跑 1000 次的第三名,ODI 跑 2000 次的第二名,ODI 跑 3000 次的第三名。这些数字充分说明了他的能力,也说明了为什么他是当今如此高评价的板球运动员。
巴巴尔·阿扎姆(Babar Azam)与印度次大陆流行、装饰和庆祝的板球品牌格格不入。他不是明星,也不是这个国家的宠儿,但他正尽力脱颖而出,以一种非典型的、非巴基斯坦的方式做出改变。随着他不断累积的得分和不断刷新的记录,巴巴尔很有可能成为巴基斯坦板球史上最伟大的击球手之一。
分析最佳黑客新闻帖子
有史以来最佳黑客新闻帖子的统计和文本分析。
每天我都会查看黑客新闻寻找有趣的信息,无论是文章、故事、软件还是工具。大多数登上头版的投稿都非常有趣和有用,而且社区驱动的帖子管理如此之好的事实让我着迷。
为了这篇文章的目的,我使用了黑客新闻 API 收集了大约 200 篇提交给 Hacker News 的最好的故事和他们的评论,并对数据进行了一些处理,以获得一点关于什么是一篇好的《HN 邮报》的见解。
在我们开始之前,我必须说,我毫不怀疑黑客新闻提交是好的,这要归功于所提供信息的质量和对该特定信息的兴趣程度。但是,可能还有其他因素,在很小的比例上,帮助 HN 提名登上头版。
记住这一点,让我们看看这篇文章的概述:
- 为我们的分析获取数据
- 数据可视化:单词云和分数分析
- 何时在 HackerNews 上发帖
- 问 HN vs 秀 HN
- 黑客新闻上的人们谈论谁:实体识别和关键词提取
- 结论
本文原载于 程序员背包博客 。如果你想阅读更多这类的故事,一定要访问这个博客。
对更多这样的故事感兴趣?在 Twitter 上关注我,地址是@ b _ dmarius,我会在那里发布每一篇新文章。
获取数据进行分析
我使用了 HackerNews API /beststories 端点收集了 188 个有史以来最好的故事。对于每个故事,我也收集了评论(但不是对评论的评论,只有主线)。这是我为每个条目存储的数据。
id - the id of the entry
parent - the id of the parent. For a story, it is the same as the id field. For a comment, it's the id of the story to which the commend was added
kids_number - only for stories, meaning the number of comments
score - only for stories: the number of points the submission got
time - UNIX timestamp of the time the entry was added
text - title of posts or texts of comments
type - 'story' or 'comment'
我用来获取数据的类的完整代码将在本文末尾提供。
然后,数据存储在 csv_file 中,并从那里加载到 Pandas 帧中。我还需要为我的分析创建另外 4 列: DayOfWeek,HourOfDay,isAsk,isShow。这些名字不言自明。
dataFetcher = DataFetcher("https://hacker-news.firebaseio.com/v0/", "data.csv")
dataFetcher.fetchData() df = pd.read_csv("data.csv") df['DateTime'] = pd.to_datetime(df['time'], unit='s')
df['DayOfWeek'] = df['DateTime'].dt.day_name()
df['HourOfDay'] = df['DateTime'].dt.hour
df['isAsk'] = df.apply(lambda x: x.type=='story' and x.text.lower().startswith("ask hn:"), axis=1)
df['isShow'] = df.apply(lambda x: x.type == 'story' and x.text.lower().startswith("show hn:"), axis=1)
数据可视化:单词云和分数分析
我首先对数据做了一些探索性的分析。首先,我从故事标题和评论中建立了两个独立的单词云,希望我能对 HackerNews 上常用的单词有所了解。我已经从标题中删除了“展示 HN”和“询问 HN”的标签。
stopwords = set(STOPWORDS)
stopwords.update(["Ask", "Show", "HN"])
titles_text = " ".join(df[df['type']=='story']['text'].unique())
titles_cloud = WordCloud(stopwords=stopwords, background_color='white').generate(titles_text)
plt.figure(figsize=(8, 8), facecolor=None)
plt.imshow(titles_cloud, interpolation="bilinear")
plt.axis("off")
plt.tight_layout(pad=0)
plt.show()
从故事标题构建单词云
除了大的、明显的 Covid 和冠状病毒词,大多数词都与软件、编程和技术有关。一个很好的观察是,视频似乎在黑客新闻上工作得很好(至少这个词云告诉我们)。
也来看看评论吧。
comments = " ".join(df[df['type'] == 'comment']['text'].unique())
comments_cloud = WordCloud(background_color='white').generate(comments)
plt.figure(figsize=(8, 8), facecolor=None)
plt.imshow(comments_cloud, interpolation="bilinear")
plt.axis("off")
plt.tight_layout(pad=0)
plt.show()
从评论中构建单词云
我有一点失望,因为我没有包括所有关于这个分析的评论,但是评论的数量非常大,我不确定它对我的这篇文章有多大帮助。但是我们都知道有时候我们花在评论区的时间比花在最初提交的帖子上的时间还多😀
然后我想看看最好的帖子的分数。我绘制了一个直方图来说明分数倾向于聚集的值,我还计算了分数的平均值和中值。
# Histogram of scores scores = df[df['type']=='story']['score']
scores.plot.hist(bins=12, alpha=0.5)
plt.show() # Average score
print ("Average score: ", df[df['type']=='story']['score'].mean()) # Median score
print("Median score: ", df[df['type'] == 'story']['score'].median())
黑客新闻最佳帖子得分直方图
我们可以看到,大多数故事的得分都低于 200 分,但也有一些异常值,至少有 1000 分。
我的数据集的平均得分为 194.80,但是这受到了异常值的巨大影响。这就是为什么我还计算了的中间值,它是 140.0。也就是说,黑客新闻上大约一半的最佳报道得分不到 140 分,而另一半得分超过了 140 分。
何时在黑客新闻上发布
这是很多人在网上问的问题。这篇文章绝不是寻找答案的捷径,但我仍然认为我找到了一些有趣的东西。
首先,我绘制了一周中每天的故事分布图。
daysOfWeek = df[df['type']=='story'].groupby(['DayOfWeek']).size()
daysOfWeek.plot.bar()
plt.show()
何时在 HackerNews 上发帖——按星期几发帖
大多数最好的故事都是在周末发布的。不知何故,我期待着这一点。但对我来说最有趣的事实是,没有一个最好的故事是在周二或周三提交的。周一似乎也是非常糟糕的一天,很少有成功的提交。
在做这个分析之前,我还会猜测星期五会获得最多的成功提交。我也不知道具体为什么,只是直觉。
我们还可以看看另一个时间维度,那就是一天中的某个时刻。让我们画出同样的分布。
hoursOfDay = df[df['type']=='story'].groupby(['HourOfDay']).size()
hoursOfDay.plot.bar()
plt.show()
何时在 Hackernews 上发帖——按星期几发帖
让我们的时间列以 UTC 时间显示,我们可以看到大多数成功的帖子是在下午提交的,最大的峰值出现在 UTC 时间下午 5 点。
我想检查的另一件事是,一篇帖子获得的点数和该帖子的评论数之间是否有任何关联。对我来说,这似乎很明显应该是真的:如果人们发现一些足够有趣的东西来投票,他们也可能会在那个帖子上开始讨论。
我还在这个关联矩阵中加入了一天中的某个小时,以检查一天中人们是否有更想参与对话的时候。
correlationsData = df[df['type'] =='story'][['score', 'kids_number', 'HourOfDay']]
print (correlationsData.corr(method='pearson'))
何时在黑客新闻上发表文章——相关性
分数和评论数量之间似乎有很强的相关性。正如我所说的,我多少预料到了这一点。但是我对分数和时间之间不存在的相关性有点失望。
问 HN vs 秀 HN
接下来,我想看看黑客新闻上有多少最成功的帖子是提问/展示提交的。
print ("Count of Ask HN stories: ", df[df['isAsk']==True].shape[0])
print ("Percentage of Ask HN stories:", 100 * df[df['isAsk']==True].shape[0] / df[df['type']=='story'].shape[0])
print ("Count of Show HN stories: ", df[df['isShow']==True].shape[0])
print ("Percentage of Show HN stories:", 100 * df[df['isShow']==True].shape[0] / df[df['type']=='story'].shape[0])
似乎只有 8 个帖子问 HN(占我的数据集的 4.30%),16 个帖子显示 HN(占数据集的 8.60%)。毕竟这里没什么可看的,只有几个提交的问题 HN/展示帖子。
黑客新闻上的人们谈论谁:实体识别和关键词提取
下一步是对黑客新闻上的最佳帖子的标题运行一个实体提取器,并从这里保存个人和组织实体,看看是否有任何东西冒出来。我用 spacy 进行实体提取 。
我得到了 175 个实体的名单。因为这是一个没有告诉我们任何事情的大列表,所以我只提取了出现不止一次的实体。
nlp = spacy.load('en_core_web_sm')
doc = nlp(". ".join(df[df['type']=='story']['text'].unique()))
entity_names = [entity.text for entity in doc.ents if entity.label_ in ["PERSON", "ORG"]]
freq = {entity_names.count(entity): entity for entity in entity_names}
for i in sorted (freq.keys()):
if i > 1:
print (freq[i])
# Prints: Amazon, Google, Apple
三家科技巨头是唯一三家在最佳黑客新闻帖子中出现不止一次的实体。
最后一步是 使用 gensim 从帖子的标题中提取关键词 。
print(keywords(". ".join(df[df['type']=='story']['text'].unique())).split('\n'))
这会产生一个巨大的关键字列表,其中前 3 个是:“covid”、“pdf”和“video”。除此之外,大多数关键词都与“生成器”、“应用程序”和“机器学习”有关。
我们不要忘记添加我用来从 Hacker News API 中提取数据的类的代码,正如我在本文开始时承诺的那样。
import csv
import requests
from bs4 import BeautifulSoup BEST_STORIES="beststories.json"class DataFetcher: def __init__(self, baseUrl, dataFile):
self.baseUrl = baseUrl
self.dataFile = dataFile def fetchData(self):
with open(self.dataFile, mode='w') as data_file:
data_writer = csv.writer(data_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
data_writer.writerow(['id', 'parent', 'kids_number', 'score', 'time', 'text', 'type']) # Best stories
r = requests.get(url=self.baseUrl + BEST_STORIES)
bestStoriesIds = r.json()
count = 0
for id in bestStoriesIds:
count = count + 1
print (str(count) + " / " + str(len(bestStoriesIds)))
story = requests.get(url=self.baseUrl + "item/" + str(id) + ".json")
storyJson = story.json()
data_writer.writerow([storyJson['id'], storyJson['parent'] if "parent" in storyJson else storyJson['id'],
len(storyJson['kids']) if 'kids' in storyJson else 0, storyJson['score'],
storyJson['time'], BeautifulSoup(storyJson['title'], features="html.parser").getText(), storyJson['type']]) # Getc
if "kids" in storyJson:
for kidId in storyJson["kids"]:
kid = requests.get(url=self.baseUrl + "item/" + str(kidId) + ".json")
kidJson = kid.json()
if kidJson and kidJson['type'] == 'comment' and "text" in kidJson:
data_writer.writerow(
[kidJson['id'], storyJson['id'],
len(kidJson['kids']) if 'kids' in kidJson else 0, 0,
kidJson['time'], BeautifulSoup(kidJson['text'], features="html.parser").getText(), kidJson['type'], '']) print ("Latest stories")
maxId = requests.get(url=self.baseUrl + "maxitem.json").json()
countDown = 1000
while countDown > 0:
print ("Countdown: ", str(countDown))
story = requests.get(url=self.baseUrl + "item/" + str(maxId) + ".json")
storyJson = story.json()
if storyJson["type"] == "story" and storyJson["score"] > 50:
countDown = countDown - 1
maxId = maxId - 1
data_writer.writerow(
[storyJson['id'], storyJson['parent'] if "parent" in storyJson else storyJson['id'],
len(storyJson['kids']) if 'kids' in storyJson else 0, storyJson['score'],
storyJson['time'], BeautifulSoup(storyJson['title'], features="html.parser").getText(),
storyJson['type'],
storyJson['url'] if "url" in storyJson else '']) # Getc
if "kids" in storyJson:
for kidId in storyJson["kids"]:
kid = requests.get(url=self.baseUrl + "item/" + str(kidId) + ".json")
kidJson = kid.json()
if kidJson['type'] == 'comment' and "text" in kidJson:
data_writer.writerow(
[kidJson['id'], storyJson['id'],
len(kidJson['kids']) if 'kids' in kidJson else 0, 0,
kidJson['time'], BeautifulSoup(kidJson['text'], features="html.parser").getText(),
kidJson['type'], ''])
结论
这就是我对有史以来最佳黑客新闻帖子的小小分析。我真的很喜欢摆弄这些数据。我希望你也喜欢这个,并从这个项目中获得一些有意义的见解。
本文原载于 程序员背包博客 。如果你想阅读更多这类的故事,一定要访问这个博客。
非常感谢您阅读本文!有兴趣了解更多吗?在 Twitter 上关注我,地址是@ b _ dmarius,我会在那里发布每一篇新文章。
分析公民个人的竞选捐款
r 的一项研究。
简介:
竞选捐款在美国政治体系中发挥着重要作用。当大多数人考虑竞选捐款时,他们通常会想到超级政治行动委员会,因为他们向候选人捐款最多。然而,这忽略了来自全国各地的个人贡献。
有了联邦选举委员会(FEC)的公开数据,我们可以从他们的网站观察个人捐款数据。要下载我将使用的数据,请执行以下操作:
- 点击个人捐款
- 下载 2019–2020 年数据。
探索性数据分析:
包含有问题数据的表格并不完美,需要采取一些步骤进行清理,最重要的注意事项是:
- 每个条目由竖线字符
|
分隔 - 列的标签不存在。
- 交易日期列需要重新格式化。
幸运的是,带有数据集的 CSV 文件包含列的标签。对于交易日期,还需要做一些工作。
如果自动读取,R 会假设交易日期是一个数字,因为它就是。日期的结构如下:MMDDYYYY。这个结构很重要。如果月份小于 10,日期的月份将以 0 开始,这意味着 R 决定忽略它,因为它将日期作为整数读入,这使得到 date 对象的转换很困难。
这个问题可以通过加载数据样本、操作交易日期的类,以及使用类集加载更大的数据子集进行探索来缓解,这与具有超过 3400 万个观察值的完整数据集相比,利用了 100 万个样本。在我的笔记本电脑上,这需要大约一分半钟。通过使用更多的行,装载时间会成倍增加。
即使有 100 万个样本,它仍然不能代表更大的图景——特别是考虑到这些数据可以被结构化为时间序列这一事实。通过从 34 个中取出第一个 100 万,我们只观察到捐款的一个小时间窗口。我们将在随后的章节中观察这些故障如何妨碍我们的分析。
时间序列分析:
如前所述,这些数据可以塑造成一个时间序列。然而,在本报告中,分析仅针对前 100 万个样本。在某个特定的日期之后,我们应该期待一个贡献计数的显著下降。有了足够强大的计算机,这个代码可以扩展到分析所有 3400 万次观察。
按作者分列的数字
从上面可以看出,我们的假设是正确的。这意味着前一百万次观察主要发生在 2019 年的前七个月。
状态分析:
一个自然的假设是分解并比较各州的个人贡献。当按每个状态分组并找到它们的相对频率时,需要注意的是有 62 个状态,其中 61 个有效,另一个为空。
但是,怎么会有 61 个有效的状态条目呢?除去我们已经知道的典型的 50 个州和 DC,剩下的 10 个州由联邦/领地、军队州、外国,当然还有空州组成。与 50 个国家和 DC 相比,这 10 个国家的捐款数量微不足道。正因为如此,这次探索的主要焦点将是美国的 50 个州和 DC。
按作者分列的数字
单纯的票数本身就表明了某些州之间的指数差距。然而,单纯的数量并不能代表捐款对选举的影响。事实上,应该预料到加利福尼亚和德克萨斯的投票人数最多,因为它们是最大的州。为了尝试解决这一问题,将使用可视化每个国家的人均捐款数量。
为了找出各州的人均收入,我们将我们的观察值除以各州的人口数。美国人口普查局提供了美国 50 个州的人口数据,这里将使用这些数据。不出所料,包含我们信息的 excel 表格也需要清理一下。关于 excel 文件的重要注意事项如下:
- 由于格式不规则,列名没有被读入。
- 五十个州名前面都包含一个句点(即。德克萨斯”而不是“德克萨斯”。)
- 贡献数据集使用州的缩写(TX ),而人口普查数据使用州的实际名称(德克萨斯州。)
按作者分列的数字
从上面的结果中我们可以看到,纽约和弗吉尼亚的人均捐款数最多,这可能使它们成为筹款的关键州。这进一步强化了这样一种观念,即捐款的数量本身并不能代表整个竞选过程。
谁在大厅里?
因为这个数据集的主要焦点是看个人的贡献,所以只适合分析个人本身。然而,在 100 万个投稿中,几乎有无限多种不同的名字。需要有一种直接的方法来判断谁作为个人对政治有着深厚的热情——甚至更深的口袋。为了找到我们家乡的游说者,我将所有的名字分组,并总结出代表捐款金额的那一栏。从那里,我们可以得到前 20 名贡献者,看看他们愿意付出多少。
然而,这一分析并不完美。我们应该记住,这些是 2019 年上半年最大的贡献者。此外,当查看左边的第三和第四个条时,我们看到这些贡献是由同一个人做出的。然而,在一个例子中,他的头衔(先生)在他的名字里,而在另一个例子中,却没有。基本正则表达式可以通过省略诸如先生、小姐等头衔来清除姓名。然而,这并没有忽视每个人所贡献的大量资金。即使是前 20 名贡献者,托马斯·f·施泰尔(贡献最大)和布鲁士·高富拿(贡献“最小”)之间也有超过 8 倍的显著差距!
结论:
有了一台更强大的计算机,上面进行的分析可以更深入地了解竞选活动在这个国家可以获得的资金种类。尽管超级政治行动委员会凭借其巨大的影响力和影响力主导着政治领域,但仅 2019 年第一阶段的前 20 名捐助者就贡献了超过 1000 万美元的捐款。我们的时间序列是受计算资源缺乏影响最大的分析。这是预料之中的,并在第 3 节中得到证实。正因为如此,假设各州的数据也可能与本报告中的结果不同也是安全的,因为我们无法使用 2019 年上半年来预测另一年的捐款价值。
用 Python 分析芝加哥法院数据
变更数据
从库克县公开法庭数据预测精神健康相关的处置和判决
*Note from the author: This article is based on a project and the report created by myself, Karmen Hutchinson, Kelsey Markey and Alene Rhea for our final project in the course DSGA1001 at NYU CDS. This article reflects my personal learnings, experiences, and opinions on our project and relies heavily on the work we did together as well as the project report that we all wrote and submitted together, but I am not by any means speaking for our group as a whole, or taking full credit for our project, which we did collaboratively and as a team. This article reflects my personal opinions and reflections only.*
D 在我读研的第一个学期,我与我的队友 Karmen Hutchinson、Kelsey Markey 和 Alene Rhea 在我们的数据科学导论课程中合作了一个机器学习项目。这是我与团队合作的第一批数据科学项目之一,我很感激有机会与上述人员一起工作。这是一次很棒的经历,这篇博文的发现是团队合作的结果。通过这篇文章,我希望与数据科学界的其他人分享我所学到的东西。特别是,尽管我们的团队没有找到结论性的结果,但我从寻找数据集、建立模型、评估模型以及与同行交流我们的发现的过程中学到了很多。让我们开始吧!
对于这个项目,我们的团队使用了来自 2019 年 12 月 2 日更新的数据集,这些数据集来自库克县开放数据门户上的[数据集](https://datacatalog. Cookcountyil.gov))。能够处理政府数据并理解政府机构跟踪心理健康的不同方法是很有趣的。该项目的目标是基于库克县的数据集,更好地了解和发现可能患有精神疾病的人。有趣的是,我们看到在这个数据集中,有精神疾病的个人在监狱中的人数据报道高达 30%,超过全国平均水平近 10%(行为健康创新,2015)。库克县在专业治疗法院和项目方面也处于领先地位,这些法院和项目可以及早识别符合条件的个人,并将他们与基于社区的服务联系起来,以增加成功的缓刑和重返社区的机会(TASC 健康与司法中心,2019 年)。然而,进入精神健康法院程序需要卫生部门的当前案例,并且发生在法律程序的相对较晚阶段。
这个项目之所以相关的一个重要原因是,患有精神疾病的人特别容易触犯法律。因此,他们在通过刑事司法系统时,往往需要专门的资源和周到的治疗。具体来说,当我们在这个项目中工作时,我们的团队旨在从一组司法和基于案例的特征中预测精神健康相关的倾向和判决,这些特征仅在初始阶段可用。早期发现可能患有精神疾病的人将使政府和其他机构能够尽早向这些人提供适当的支持。与普通人群相比,刑事司法系统涉及的个人中精神健康障碍的发生率要高三至六倍(Blandford & Osher,2012 年)。也有证据表明,患有精神健康疾病的人在监狱中度过的时间明显更长,并且在释放后一年内再次入狱的可能性接近两倍(Haneberg & Watts,2016 年;Eno Louden & Skeem 2011)。这为患有精神健康疾病的人创造了一个不利的环境,并形成了一个问题循环,他们被释放到社区,但很可能在未来又回到司法系统。该项目的目标是减少通过法律系统转移对精神健康障碍患者的有害影响,同时也最大限度地减少国家承担的费用。为了做到这一点,我们旨在预测一个人患有精神健康障碍的可能性,只要他们被引入法律系统(不需要医疗记录或人员)。审前识别个人允许迅速和适当的干预(即监狱转送干预)和资源(即强化案件管理方案,见 Loveland 等人,2007 年),以避免继续卷入法律系统。总的来说,我们的项目强调了在这样的系统中不同影响跟踪的需要。
本研究中使用的库克县法律数据集的描述。由项目团队成员创建的图像。
首先,让我们看看我们团队使用的数据集。库克县数据集包含多个标识号,这些标识号将它们之间的记录联系起来。因为我们想在个人层面上进行预测,所以我们使用了 case_participant_id。Case_participant_id 是库克郡分配给与案例相关的每个人的唯一内部标识符。每个 case_participant_id 可以与多个费用关联,每个费用在数据集中显示为单独的一行。如果发生了重新判决,一项指控可能会在判决数据集中显示为多行。此外,我们的团队还希望将我们的训练数据限制在 Initiation 中的 27 列,以便模拟用例。其中 14 列是分类的,6 列是基于时间的。
由于问题和数据集的性质,我们实际上创建了自己的目标变量。由于我们希望根据精神健康对个人进行分类,因此我们创建了一个二元目标变量“精神健康指标(MHI)”来表示个人是否被识别为患有精神健康残疾。我们查看了所有可能表明精神健康相关结果的量刑和处置的可能价值,并确定了 6 栏中的 15 个相关价值。我们将判决和处置数据集放在一起,以确定哪些行包含 MHI 的代理。例如,如果找到了这样的实例,则该个人有一个 sentence_type = "住院精神健康服务",则该行的 MHI 为 1,否则为 0。由于可能有多行属于 case_participant_id,我们创建了一个单独的数据集,其中包含每个唯一的 case_participant_id 的一行,以及相应的 MHI。如果对应于该 ID 的任何行的 MHI 为 1,则每个唯一 ID 都被赋予 1。最终,我们能够分配 1 到 2212 个唯一的 case_participant_id 的 MHI。
由于年龄、种族和性别等受保护的类别可能会在模型中引入偏见,我们检查了它们在阳性和阴性标签实例中的分布。我们发现,阳性病例的年龄偏高,女性 MHI =1 的可能性几乎是男性的四倍,被标记为“混血儿”或“亚裔”的人跨种族的 MHI 阳性率最高,被标记为“西班牙裔”的人跨种族的 MHI 阳性率最低。
接下来,我们清理了数据集。在数据清理期间,我们更改了一些数据类型,填充缺失的信息,验证列中的输入是否一致,应用 StandardScaler()等缩放方法,以及 one hot 编码分类变量。具体来说,我们做了以下工作:
- 所有字符串变量都被转换成小写。
- 数字列(如 charge_count)被转换为整数。
- 所有缺失或异常的数值都被替换为中间值。
- 所有缺失的非数字输入都被替换为“未知”(因为数据调查显示这是库克郡已经实施的常见填充符。)
- 除“男性”和“女性”(即空值或“男性姓名,未给出性别”)之外的所有性别值都被转换为“未知”
- 年龄被转换成整数,空值和外围值(大于 100)被中值年龄所取代。在我们的伪基线随机森林表明年龄是一个极其重要的因素后,我们考虑建立一个单独的模型来预测和估算缺失的年龄。鉴于项目的时间限制,这被认为是不可行的。
- 转换为日期时间的日期和缺失或未知的日期被赋予一个对应于 1900 年 1 月 1 日午夜的填充值
- 因为关联热图显示 ID 号与重要特征相关,所以所有 ID 号都从数据中去除,以防止潜在的数据泄漏。Case_participant_id 设置为索引,而 case_id、charge_id 和 charge_version_id 从数据集中完全删除。
我们将所有分类变量转换为二进制虚拟变量,以允许使用参数模型,并为行的聚合做准备。这就产生了一个稀疏的高维数据集。
有“402”部分的案例参与者的频率。作者创建的图表。
因为我们使用的数据集非常不平衡,所以我们应用了缩减采样。为了帮助我们的模型学习识别数据集中的阳性类,我们使用随机分层采样对训练集中的阴性案例进行了缩减采样。考虑到对更大计算资源的访问,我们也想尝试一下上采样。具体来说,我们使用 100%的正面实例,并且不替换负面实例进行采样。最初,我们对负面实例进行缩减采样,使得正面实例占训练集人口的 50%,假设这将是我们的数据和用例的理想比率。但是,验证集和测试集没有缩减采样以复制部署。
数据集总体中和缩减采样后的类概率。作者创建的图像。
接下来,我们将数据集分成训练集、测试集和验证集。特别是,我们选择将数据集分为 70%数据的训练集、15%数据的静态验证集和 15%数据的测试集,这一比例得到了许多数据科学家的认可(Shah,2017)。为了模拟部署环境,其中我们的模型将用于预测未来时间,我们根据 received_date 划分了我们的训练、验证和测试集。接收日期最早的案例成为我们的训练集,最后的案例成为我们的测试集。我们想要使用基于时间的分区的一个原因是为了防止数据泄漏。
跨数据集的 MHI 基本汇率
为了降低数据的维度,在实施虚拟变量后,数据的维度增长到近 5000 个特征,我们使用了主成分分析,因为它简单、有效且可用于从数据集提取相关信息的非参数应用(Shlens,2014)。我们在我们的规模训练集上使用了 PCA 的经典应用(尽管稀疏 PCA 应该在未来的工作中进行研究),这产生了解释的方差比。给定更大的计算资源,我们希望使用 500 个主成分来执行测试,因为我们在该点看到一个尖锐的弯头。
在评估我们的模型时,我们关注两个性能指标:(1)受试者工作曲线下面积(AUC ),和(2)灵敏度。我们对此的推理是因为我们认为在我们的用例中,假阴性的成本要比假阳性的成本高得多;错过一个精神疾病的例子可能对那个人有害,但是向一个没有特别需求的人提供支持和服务可能只会给国家带来边际运营成本。然而,在没有库克县可用资源和心理健康相关预算限制的具体知识的情况下,我们试图提供一个可以在不同阈值下表现良好的模型。因此,我们针对 AUC 优化了我们的模型,密切关注每次迭代对灵敏度的影响。这种选择是基于这样的认识,即由于我们的基础率低,准确性将是一个很差的指标,因为它可能非常高,即使少数民族阶层没有得到很好的预测。另一方面,AUC 更适合我们的业务目标,因为它对类别不平衡很敏感,因为它对少数类别和多数类别一样重视。
解释主成分分析的差异率
优化 AUC 提供了一个自然的基线,因为 0.5 的 AUC 代表随机分配类别概率的模型(Brownlee,2019)。使用 50%的概率截止值,这种模型的预期灵敏度也将是 0.5。将该阈值降低到 0%(即,将每个病例分配到阳性类别)将是最大化灵敏度的最简单方法;事实上,这种模型的灵敏度是 1。这进一步说明了在这种情况下优化 AUC 比优化敏感性更好的原因:我们的目标不是简单地识别阳性实例,而是以最小的 I 型错误来进行。
我们运行的第一个模型是一个随机森林模型,具有现成的参数,适合我们清理和缩减采样的训练集。我们称之为“伪基线”,因为在这个阶段我们已经在数据管理上投入了大量的时间。基于系综树的方法被选为基线,因为已知它们在分类变量上表现良好(Tutz & Berger,2017)。在特征工程和超参数调整之前,我们将该模型视为开始的基线。这种未精炼的模型产生了 0.78 的 AUC 和 0.78 的灵敏度。
特征相关性
在我们的伪基线随机森林中展示的特征重要性指导了我们大部分的初始特征工程。例如,“Section 402(c)”属于前十五个重要特征,进一步的研究表明,这对应于与毒品或持有毒品相关的法律部分(伊利诺伊州州务卿)。因此,研究人员设计了一个新的指示变量,以编码 section 列是否包含 402(c)以外的其他“402”部分。为了关联附近的区域,我们将事件城市地理编码为纬度和经度。地理编码还确保我们的位置代理在整个数据集中是一致的。还设计了许多日期时间特性,试图更好地表示我们假设的心理健康事件和时间之间的相关关系。最后,由于事件发生时的年龄有近 4%的缺失值和大约 40 个(不现实的)超过 100 的异常年龄,我们为事件发生时的年龄是否为空和年龄是否超过 100 创建了一个二元特征。
就我们想要应用于这个问题的算法而言,我们确定了五种算法来探索:逻辑回归、决策树、随机森林、梯度推进和支持向量机。在所有特征工程完成后,使用已清理、已缩放和已缩减采样的数据的现成参数来建立每个模型的初始性能。
由于数据集的高维数,我们选择不使用 k-最近邻模型(kNN)进行实验。在这种情况下,事实上可能相似的实例可能有很大的距离,因此 kNN 可能表现不佳(Brownlee,2016)。我们还决定不实现朴素贝叶斯分类器,因为使用哑变量来编码分类数据明显违反了算法的条件独立性假设。
使用现成参数的验证集的性能指标
由于数据集的高维数,我们选择不使用 k-最近邻模型(kNN)进行实验。在这种情况下,事实上可能相似的实例可能有很大的距离,因此 kNN 可能表现不佳(Brownlee,2016)。我们还决定不实现朴素贝叶斯分类器,因为使用哑变量来编码分类数据明显违反了算法的条件独立性假设。
支持向量机 通常被视为机器学习的通用算法,我们选择 SVM 作为我们的探索模型之一,因为它能够通过线性或非线性内核捕捉复杂的关系。然而,SVM 比我们的任何其他模型花费更长的时间来训练,可能是因为我们的大量功能和支持 SVM 的约束优化问题(Ragnar,2016)。此外,它没有产生证明长时间训练是合理的结果。研究人员确定,开箱即用的 SVM 模型的运行时间和极低的灵敏度(0.46)意味着它不会成为超参数调整的候选对象。
逻辑回归 逻辑回归因其稳健性、可靠性和直观解释而被选中。此外,使用随机梯度下降的方法,逻辑模型相对容易用新数据更新,并且可以容易地被正则化以避免过度拟合(李,2017)。在进行适当的转换之后和调整之前,当使用所有~4800 特性时,模型无法收敛。增加最大迭代次数、测试不同的解算器以及测试不同的非线性特征变换都无法使模型收敛。假设多重共线性可能是一个问题,我们从随机森林中减少了前十个要素重要性的列数,并发现模型(使用 solver = 'liblinear '和 C = 1e30)能够拟合 AUC 为 0.72 的数据。我们最终决定不进行逻辑回归,因为很难将逻辑回归拟合到我们的虚拟变量,并且我们已经使用树方法得到了令人印象深刻的结果。
决策树
虽然集成方法通常在关键指标上优于决策树,但是单一决策树可以提供有价值的透明性。我们决定尝试创建可解释的决策树,因为在 hand⁴.问题的背景下,透明度尤其重要
验证集上的随机森林调优和性能
政府用来辅助决策的模型要接受公众的审查,因此提取一套直观的规则来解释其决策的能力可能值得降低绩效指标。树是根据未缩放的数据训练的,因此数值是可以解释的。研究人员迭代了 max_depth (2,3,4)、min_samples_leaf (1,10,100,500)和 max_features (10,5,3,无)的值。超参数的最佳组合是 max_depth=4,min_samples_leaf=10,max_features=None,AUC 为 0.75,灵敏度为 0.86。
随机森林 经过特征工程,我们用默认参数评估了一个随机森林模型,发现 AUC 上升到 0.79,灵敏度下降到 0.75。考虑到模型的高性能,我们决定继续调整随机森林模型,包括超参数调整和特征提取。我们从调整超参数开始,测试了一系列 max _ depths(无、3、10、30)、min_samples_leaf (2、50、100、200)和 n_estimators (10、100、500、1000)。我们发现在这些条件下,AUC 优化为 0.82,灵敏度= 0.78(表 A4)。然后,我们决定使用各种 PCA 组件进行调优,并使用 1、3、100 和 1000 的 PCA 组件以及不使用 PCA 的组件测试了相同的树参数。最终,没有 PCA 成分和超参数的组合可以击败没有 PCA 的模型性能。
梯度推进 考虑到我们的树集成方法的表现,我们决定将梯度推进作为我们的探索性算法之一。我们发现现成的梯度增强模型的 AUC 为 0.82,灵敏度为 0.76,因此是进一步超参数调整的合理候选。同时调整基于树和基于学习的超参数被证明成本太高,因此我们选择首先优化基于树的参数,然后使用所选择的参数来调整基于学习的参数。我们首先通过遍历 max_depth = [None,3,10,30]和 min_samples_leafs = [1,2,10,500]的所有可能组合来调整基于树的超参数(表 A5)。我们在这些条件下优化了 AUC,max_depth = 3,min_samples_leafs = 10,AUC = 0.82,灵敏度= 0.78。然后,我们使用这些参数迭代 n_estimators = [10,100,500,1000]和 learning_rates = [0.25,0.1,0.01,0.0001]。我们对使用如此大量的估计量感到满意,因为我们知道这不会导致梯度推进集成方法过度拟合。我们发现,当 learning_rate = 0.01 和 n_estimators = 1000 时,AUC 在这里得到优化,AUC = 0.82,灵敏度= 0.79。这个灵敏度比我们使用优化的随机森林获得的稍好,所以我们决定进一步优化梯度增强模型。
我们决定探索不同数量的 PCA 组件如何影响我们的梯度增强模型的性能。我们再次循环通过所有超参数,也在 1、3 和 100 之间改变组件数量。在使用较少组件评估模型时,我们能够创建一个大循环来优化主组件、基于树的超参数和基于学习的超参数的数量。所有超参数保持不变,只是增加了一个额外的 min _ samples _ leafs 100,以提高 10 到 500 之间的分析粒度。在 100 个主成分时,发现最佳 AUC 为 AUC = 0.81,灵敏度为 0.73。1 种成分的灵敏度优化为 0.91,然而该模型只有 0.55 的 AUC。
我们选择梯度推进集成算法作为我们的最终模型,其中{max_depth = 3,min_samples_leafs = 10,learning_rate = 0.01,n_estimators = 1000}
调整我们的梯度增强模型的最后一步是试验各种级别的下采样。所有以前的测试都依赖于 50%的下采样比率,因此我们的训练集具有相等的正负标签出现率。首先,我们使用 20%的下采样比率(意味着 20%的训练集由阳性实例组成)测试优化的梯度增强模型,并发现 AUC 几乎保持不变,但灵敏度极低,为 0.28。当模型以 10%的下采样比率再次运行时,灵敏度再次恶化到 0.10,因此我们得出结论,小于 50%的比率恶化了我们的模型性能,下采样比率在 50%时被优化。这些结果与我们关于下采样对灵敏度的影响的假设一致。
在这一轮评估中,我们选择不缩放我们的任何功能,因为缩放不应影响树模型(李,丁等人,2017)。为了测试这个假设,我们在未缩放的数据集上以 50%的下采样比率重新运行最终模型。这产生了与我们在缩放数据中发现的相同的 AUC 和灵敏度,证实了缩放是对计算能力的不必要使用。
使用我们之前的调整实验的结果,我们在没有 PCA 或缩放的情况下训练最终的梯度增强模型,并且具有 50%的下采样比率。我们使用最高性能的超参数 max_depth = 3,min_samples_leaf = 10,learning_rate = 0.01,n_estimator = 1000,并根据组合的测试和验证数据评估模型。我们的最终模型实现了 0.84 的 AUC,同时仍保持 0.76 的高灵敏度。接收器操作特征曲线表明,该模型相当快地实现了超过 90%的召回率,然后变得平坦。此时的假阳性率刚刚超过 40%。这一点代表最适合业务案例的分类阈值。
在部署该模型之前,有许多与偏差相关的问题需要解决。首先,我们必须解决我们的模型从数据中学到的社会偏见。我们的特征重要性充满了歧视性特征,考虑到 MHI 在这些阶层中的分布,这并不奇怪。可以采用区分单元测试来确定问题所在(d'Alessandro 等人,2019)。验证哪些特征与受保护的属性直接或间接相关,将允许研究人员识别哪些特征要从模型中移除。
因为我们的模型只能从法院已经确定的精神疾病案例中学习,所以它有效地让法院完全控制什么被认为是精神健康残疾。这样,MHI 只是精神疾病的一个松散的代表,这些记录中可能存在对某些类型或表现的精神疾病的偏见。人口统计学也可能有一个缺点,要么通常负担不起精神保健,要么被保健提供者系统地误诊,因为他们不会有残疾记录。先前的研究表明,某些人口统计数据不太可能被医疗保健专业人员认真对待(Hoffman 等人,2016 年),因此属于受保护群体的一些个人可能与他们确实存在的心理健康问题无关。为了捕捉这些隐性偏见的影响,种族的条目被尽可能少的改动。我们没有合并群体或过滤特定条目,因为如何看待一个人的种族可能会让我们了解这个人如何能够在司法系统中导航(Maryfield,2018 年),特别是在他们的心理健康方面。
我们惊讶地发现,与家庭暴力相关的特征没有在我们的模型中得到反映,因为研究表明,库克县的家庭暴力和精神健康障碍之间有着密切的关系(Tsirigotis & Luczak,2017;行为健康创新,2015)。领域相关的特征工程有可能捕捉到这种关系;还有一种可能是,这些精神疾病的案例通常没有得到法院的确认。
验证集上的梯度增强模型超参数调整
我们的模型是仅使用公开可用的数据开发的。如果库克县对这个项目感兴趣,我们可以与他们合作开发一个公平公正的精神疾病早期识别系统。这种系统可以利用不公开的信息,例如个人在库克县司法系统中的历史和他们的卫生部门记录。此外,我们的模式对于那些希望在法律体系内为个人提供服务的非政府组织来说仍然有希望。这里使用的数据是特定于库克县的,因此不能将模型直接导出到另一个辖区;然而,这个项目很容易成为其他地方类似项目的蓝本。
参数调谐梯度增强模型的 ROC
此外,概念漂移可能是部署中的一个问题。随着库克县精神健康法院项目的继续扩大,我们可以预计随着时间的推移,基本利率会增加,这最终可能会降低模型的性能。因此,应该仔细监控 MHI 基本利率以及可能影响它的法律和政策因素。当模型过时时,可能需要定期重新训练。模型管理人也可能决定从训练中排除较旧的数据,以减轻概念漂移——这可以通过经验进行测试,并需要结合审查偏差的影响进行考虑。1 型审查偏倚可能对我们的模型产生相反的影响,要减轻这种影响,需要为纳入训练的病例年龄开发一个启发式截断点。在删截的情况下,监控部署中的模型敏感性可能被证明是具有挑战性的,但是开发上述启发式方法将会给保管人一个设定的时间来评估个人的 MHI。
我们的模型目前不可实现,因为它依赖于受保护的类别(种族、年龄、性别)进行预测。在删除这些受保护的类和能够预测它们的功能时,需要进一步努力来测试模型性能。我们决定在我们的最终模型中保留敏感的特性,以免模型被误解为公平的,并强调不同影响跟踪的需要。
我和我的团队在这个项目中学到了很多东西,我很高兴将这些新想法应用到我即将到来的项目中!感谢阅读!
[1]可以在我们的团队 Github 上查看该项目中使用的功能的完整列表:https://github.com/angelaaaateng/dsga1001_project
[2]完整列表可以在我们的团队 Github 和团队报告上查看
[3]有关我们的数据清理流程的更多详细信息,请参见我们的最终报告以及我们的团队报告
[4]有关完整的决策树,请参见我们最终报告的附录,此处https://Github . com/angelaaaateng/dsga 1001 _ project/blob/master/TERM
应阿伦·雷亚和凯尔西·马基的要求,我附上了他们对这个项目https://github.com/akrhea/mental-health-court-outcomes所做的另一项研究的链接。
参考资料:
阿布舍克·夏尔马,阿布舍克·夏尔马。"决策树介绍及实例."geeks forgeeks2019 年 11 月 25 日https://www . geeks forgeeks . org/decision-tree-introduction-example/。
a .布兰德福德和 f .奥谢尔(2012 年)。为有行为健康障碍的司法介入成年人实施循证实践和计划(EBPs)的清单。纽约州德尔玛市:SAMHSA 行为健康和正义转化增益中心。
行为健康创新。库克县保释法院的精神健康与司法重罪保释法院精神病患者管理的审查。为伊利诺伊州法院行政办公室编写的报告,2015 年 7 月。
博特夫、兹德拉夫科和阿德·里德。“方差缩减。” Wiley StatsRef:统计参考在线,2017,第 1–6 页。,doi:10.1002/9781118445112 . stat 07975。
布朗利,杰森。“机器学习的 K 近邻。”机器学习掌握2019 年 8 月 12 日https://machinelementmastery . com/k-nearest-neighbors-for-Machine-Learning/。
布朗利,杰森。"评估 Python 中机器学习算法的度量标准."机器学习掌握,2019 年 11 月 21 日https://machinelingmastery . com/metrics-evaluate-Machine-Learning-algorithms-python/。
" TASC 健康与正义中心:连接政策、研究与实践."TASC 健康与司法中心|连接政策、研究和实践。、【http://www2.centerforhealthandjustice.org/】和。
认真分类:一个数据科学家的歧视意识分类指南。ArXiv.org,2019 年 7 月 21 日,https://arxiv.org/abs/1907.09013。
Eno Louden,j .,& Skeem,J. (2011 年)。患有精神障碍的假释犯:走向循证实践。循证矫正中心公报,7(1),1–9。
Haneberg,r .,& Watts,k .,“站出来”战胜美国监狱中的精神健康危机。刑事司法/教养。纽约州纽约市:州政府委员会司法中心。从http://knowledgecenter.csg.org/kc/system/files/Haneberg瓦 2016.pdf 取回
疼痛评估和治疗建议中的种族偏见,以及关于黑人和白人之间生物学差异的错误信念。美国国家科学院学报,美国国家科学院,2016 年 4 月 19 日,https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4843483/。
艾萨克斯,迈克。"县心理健康法院选择罪犯治疗而不是监禁."chicagotribune.com。2019 年 12 月 9 日接入。https://www . Chicago tribune . com/suburban/sko kie/CT-skr-mental-health-court-TL-0526-2016 05 23-story . html。
约翰斯通,伊恩 m 和亚瑟鲁愚。"关于高维主成分分析的一致性和稀疏性."美国统计协会杂志,第 104 卷,第 486 期,2019 年,第 682–693 页。,doi:10.1198/jasa.2009.0121。
《隐含的种族偏见》法律中隐含的种族偏见,第 9-24 页。,doi:10.1017/CBO 9780511820595.002。
洛夫兰、大卫和迈克尔·博伊尔。"强化个案管理作为一种监狱转移计划,用于患有严重精神疾病的人."《国际罪犯治疗和比较犯罪学杂志》,第 51 卷,第 2 期,2007 年,第 130-150 页。,doi:10.1177/0306624x06287645。
李,惠,和 SAS 数据科学博客。“我应该使用哪种机器学习算法?”SAS 数据科学博客,2017 年 4 月 12 日,https://blogs . SAS . com/content/subconcious musings/2017/04/12/machine-learning-algorithm-use/# pretty photo。
李,丁,等.〈自适应标度〉. ArXiv:1709.00566v1【统计。ML]2017 年 9 月 2 日2017。
玛丽菲尔德贝利。“隐含的种族偏见。”司法研究与统计协会,2018。
“现代机器学习算法:优势和劣势。” EliteDataScience ,2019 年 1 月 25 日https://elitedatascience.com/machine-learning-algorithms。
纳格帕尔,阿努哈。"主成分分析-简介."中,走向数据科学,2017 年 11 月 22 日,https://towardsdatascience . com/principal-component-analysis-intro-61f 236064 b38。
萨朗·纳克赫德。“理解 AUC-ROC 曲线。”中,走向数据科学,2019 年 5 月 26 日,https://towardsdatascience . com/understanding-AUC-roc-curve-68b 2303 cc9 C5。
理解和使用敏感性、特异性和预测值。https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2636062/眼科杂志,Medknow 出版物,2008 年,印。
亚历山大·普拉里卡斯(1998 年 9 月)。信号处理公式和表格手册(第 1 版。).CRC 出版社。第 42–8 页https://en.wikipedia.org/wiki/Upsampling#cite_note-1
拉格纳。"什么样的学习问题适合支持向量机?"数据科学栈交换,2016 年 2 月 1 日https://Data Science . Stack Exchange . com/questions/9736/what-kinds-of-learning-problems-is-fitted-for-support-vector-machines。
" Sklearn.metrics.recall_score。" Scikit ,https://Scikit-learn . org/stable/modules/generated/sk learn . metrics . recall _ score . html。
塔朗·沙阿。"关于机器学习中的训练、验证和测试集."介质,朝向数据
科学,2017 年 12 月 10 日,https://towards data science . com/train-validation-and-test-sets-72 CB 40 CBA 9 e 7。
黄邦贤史伦斯。"主成分分析教程."ArXiv:1404.1100 v1【Cs。2014 年 4 月 3 日、https://arxiv.org/pdf/1404.1100.pdf。
伊利诺伊州国务卿。“在线服务。”伊利诺伊州国务卿、https://www.cyberdriveillinois.com/的官方网站。
Tsirigotis、Konstantinos 和 Joanna UC zak。“遭受家庭暴力的女性的复原力。”《精神病学季刊》,斯普林格美国,2018 年 3 月,https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5807488/。
图茨,格哈德和莫里茨·伯杰。"广义加性回归中分类预测因子的树形结构模型."数据分析与分类进展,第 12 卷第 3 期,2017 年,第 737–758 页。,doi:10.1007/S11 634–017–0298–6。
托尼,你好。“了解随机森林”中,走向数据科学,2019 年 8 月 14 日,https://Towards Data Science . com/understanding-random-forest-58381 e 0602d 2。
使用 Pandas 和 Plotly 分析冠状病毒(新冠肺炎)数据
透过总体数字来量化冠状病毒的传播
起源于中国的新冠肺炎病毒现已蔓延至全球,各国都在争相应对。这种病毒最初是一种医疗保健紧急情况,现在已经开始产生严重的经济后果。在这篇文章中,我试图用熊猫和情节来理解和想象新冠肺炎的传播。
我们从导入所有库和加载所有数据开始。这些数据由约翰·霍普斯金大学提供,可以在这里的链接中找到。有三个文件包含全部确诊病例、死亡和恢复情况。
运行上面的代码后,数据看起来是这样的。
我们有
- 日期(作为列)
- 确诊病例总数
- 省
- 国家
- 经纬度
尽管数据组织得很好,我们还是会对其进行一些修改,使其更适合绘图。我们可以使用 pandas melt 函数来改变一列中的日期,这样我们可以在以后将它设置为索引,这使得绘图更加容易。
有了日期和国家作为索引,数据集现在更清晰、更容易绘制。请看下面的快照。
出于本文的目的,我们将只查看国家级别的数据,而不是省/州级别的数据。让我们创建一个整合的数据集,将病例、死亡和恢复的数据集结合起来。我还创建了一个从累积数据中获取每日计数的函数。我们使用下面的代码进行处理。
我还创建了一些计算字段,如活动病例(没有死亡或康复结果的病例)和死亡病例比率,并使用 pandas 的合并功能合并了所有数据集。
活跃病例=确诊病例-康复-死亡
整合数据集的索引为国家和日期,每个指标为一列(参见下面的快照)
我们使用 plotly.graph_objects 进行所有的绘图。这是一个简洁的解决方案,不用很多代码就能做出漂亮的图形。我们使用下面的代码创建五个图表,显示全球确诊病例、活动病例、死亡、恢复、死亡与病例比率的数字。
全球 Covid19 案例的关键指标
我们可以看到,确诊病例、死亡和康复都在增长,但很难从这些数字中得出增长的程度,因为这些数字是累积的。死亡与病例的比率为 3.4%(这是世卫组织几天前报道的)。
“活动案例”作为一种衡量标准的效用是显而易见的,因为它提供了给定时间点的爆发快照。从图表中,我们可以看到,自 2 月中旬以来,活跃病例一直在下降,这是一个很好的指标,表明我们正在更好地控制疫情。然而,这张图表本身就有误导性,因为我们知道大多数病例发生在中国,这可能会扭曲数据。让我们比较一下中国以外地区的活跃案例。
上面的情节描绘了中国内外两种截然不同的情况。随着中国国内病例数量的下降,疫情似乎得到了控制,但在中国以外,疫情仍在强劲增长。
让我们进一步挖掘每个国家的数据。为了使数据有意义,让我们把自己限制在病例都大于 300 的前 10 个国家。让我们使用下面的代码,根据案例的数量来绘制这些国家的图表:
截至 2020 年 3 月 5 日的数据
现在让我们来看看前四个国家的病例是如何随着时间的推移而增长的。使用下面的代码,我们计算从“疫情开始”起的病例数,疫情开始是指报告第一例病例的那一天
例如,下面意大利的输出显示,第一个日期“2020-01-31”是两例确诊病例爆发的开始。该指数可以解释为“第 0 天”。
现在,让我们根据病例数绘制出前四个国家的数据,并使用以下代码查看疫情是如何随着时间的推移而增长的:
让我们看看下面的输出。请注意,一旦开始增长,数字增长得有多快。
这些国家的疫情都是逐渐开始的,但一旦达到“爆发”阈值,就会呈指数级增长。上面的图表是对自满的警告。如果不加以控制,病例会非常迅速地增加,增长几乎是指数级的,因此即使是少量的病例也可能迅速发展成全面爆发。
在韩国跨过 100 例用了 29 天,跨过 7000 例只用了 16 天!在意大利,跨过 100 用了 23 天,跨过 5000 只用了 13 天!
最后,由于不同国家的情况差异很大,因此创建一个视图来深入了解特定国家是值得的。在这里,我们可以使用 ipywidgets 库使我们的图表具有交互性,并使用下面的代码从下拉列表中选择国家:
下面的输出与上面的非常相似,但是我们现在有一个下拉菜单,可以从中选择国家(图表显示的是意大利)。
我们再次注意到,增长是突然的,而且相当迅速,尽管病例数量很高,但就病例总数而言,意大利仍未达到峰值!
全世界的病例和死亡人数一直在增长,但我们可以从中国的数据中看到,如果采取适当的措施,疫情是可以得到控制的。如果你想用我的代码自己分析数据,请在这里找到 jupyter 笔记本的链接。
让我们希望并祈祷疫情迅速结束!
分析用于图像分类的数据扩充
最新图像分类模型中使用的图像增强技术的主成分分析
图像分类是机器学习中研究最多、记录最完整的任务之一。有许多基准和大型公共数据集,如 ImageNet [1],可以将新的模型和算法与最先进的技术(SOTA)进行比较。每年都会有一些新算法问世,SOTA 的精确度也在快速提高。
近年来,改进的一个关键因素是数据扩充技术,特别是当人们试图在不使用外部数据的情况下改进排名时。数据扩充,对训练数据的微小修改有助于模型更好地概括未知的例子。数据增强处理图像的一个例子是镜像图片:猫也是镜子里的猫。
在这个故事中,我们分析了谷歌研究人员 2019 年的算法 RandAugment [2]中使用的图像增强技术。为此,我们将使用 Tensorflow 2.0 Keras 中提供的预训练 DenseNet [3]模型。为了说明模型输出,我们将对模型的最后一个隐藏层进行主成分分析。所有代码都可以在 Google Colab 上找到。
ImageNet 分类基准的改进由代码为的论文说明
图像分类
有了 Keras ,图像分类就是一个三步走的问题。1)加载图像,2)加载预训练的模型,3)解码输出。下面是使用 TensorFlow 2.0 预训练的 Keras DenseNet 模型来完成它的一个小片段。
Keras 中基于预训练模型的图像分类
如果我们用include_top
加载模型,分类的输出层有 1000 个类。decode_predictions
收集最有可能的类别,并添加类名。
猫图像来自维基百科并分类输出
对于 PCA 分析,我们将使用模型的最后一个隐藏层的输出(在 softmax 之前)。在 DenseNet 121 中,它意味着 1024 维的大向量空间。在 Keras,我们将使用以下方式获得新模型:
model_last_hidden = tf.keras.models.Model(inputs=model.input, outputs=model.layers[-2].output)
我使用这个实践来获得模型输出的良好表示,而没有 softmax 层的展平效果。
原始论文中 DenseNet 模型的一个例子
利用主成分分析子空间识别类别
主成分分析
正如我在前面的故事中所讨论的, PCA 是一种正交变换,我们将使用它来降低向量的维数【4,5】。PCA 以最大化降维数据的方差的方式找到投影的特殊基向量(特征向量)。使用 PCA 有两个重要的好处。一方面,我们可以将 1024 维向量投影到 2D 子空间,在那里我们可以将其绘制成数据。另一方面,它保持了最大可能方差(投影丢失了信息)。因此,它可能保持足够的方差,以便我们可以识别图片上的类。
最大化第一主成分的方差—来自维基百科的等式
使用带有[sklearn.decomposition.PCA](https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html)
的 PCA 是一行程序:
pred_pca = PCA(n_components=2).fit_transform(pred)
猫还是大象?
为了确定从 1024 维向量空间到 2D 向量空间的变换,我们将使用八幅图像,四只猫和四只大象。稍后,我们将在这个投影中展示数据增强的效果。图片来自维基百科。
维基百科上的猫和大象的图片
举例说明 2D 投影,我们可以看到猫和大象是完全分开的。
使用主成分分析的 DenseNet 最后隐藏层的 2D 投影
图像增强
数据扩充是训练机器学习模型的重要部分,尤其是在训练图像有限的情况下。对于图像增强,定义了许多增强算法。Python 开发者可以在imgaug
包中找到大量的方法。
对于此分析,我们将使用 RandAugment [2]中使用的方法的imgaug
实现,这是一种使用 EfficientNet 模型在 2019 年实现 ImageNet 上 SOTA 的增强,但许多其他算法也使用相同的基本方法。
对于数据扩充,最关键的部分是确定扩充方法的参数区间。例如,如果我们使用旋转这种简单的图像增强技术,很明显,将猫或大象的图像旋转几度不会改变图片的含义。然而,通常情况下,我们并不希望看到大象在自然界中旋转 180 度。另一个例子是当我们使用亮度或对比度操作时:过高的修改可能会导致无法识别的数据。
最近的工作,如基于人口的扩增[6]旨在适应训练时间的修改幅度,而其他人如 RandAugment [2]将其用作训练的超参数。自动增强研究表明,在训练期间增加增强的幅度可以提高模型的性能。
使用 imgaug 增强方法的默认间隔来增强大象图像
如果我们处理上面的增强图像,并将其投影到与之前的猫象图像相同的 2D 向量空间,我们可以看到新的点在原始图像的周围。这是图像增强的效果:
增强将分类空间中大象图像的单点扩展到大象图像的整个区域。
猫-大象投影中的增强大象图像
一次性方法
当一个标签类中只有很少的样本时,这个问题被称为少镜头学习,数据扩充是解决这个问题的一个重要工具。下面的实验试图证明这个概念。当然,这里我们有一个大数据集上的预训练模型,所以它不是在几次训练中学会的。然而,如果我们试图只使用一个原始的大象图像来生成投影,我们可以得到类似的东西。
对于这个投影,我们将使用一个新的 PCA,它使用原始的大象图像和它的增强图像。下图显示了该子空间中的增强图像。
增强图像的 PCA 投影
但是这个投影,仅仅使用一张大象图片,能把大象和猫分开吗?嗯,聚类不像前一种情况那样清晰(见第一个散点图),但猫和大象实际上在向量空间的不同部分。
从一幅大象图像生成的 PCA 投影中的大象和猫
摘要
在这个故事中,我们展示了在最先进的影像分类中使用的数据增强工具的效果。我们将猫和大象的图像以及大象的增强图像可视化,以更好地理解模型如何看待增强图像。
参考
[1]邓,李,李,,李(2009 年 6 月).Imagenet:一个大规模的分层图像数据库。在 2009 年 IEEE 计算机视觉和模式识别会议上(第 248–255 页)。Ieee。
[2] Cubuk,E. D .,Zoph,b .,Shlens,j .,& Le,Q. V. (2020 年)。 Randaugment:用缩小的搜索空间进行实用的自动数据扩充。在IEEE/CVF 计算机视觉和模式识别研讨会会议录(第 702–703 页)。
[3]黄,g .,刘,z .,范德马腾,l .,,温伯格,K. Q. (2017 年)。密集连接的卷积网络。IEEE 计算机视觉和模式识别会议论文集(第 4700–4708 页)。
[4]皮尔逊,K. (1901 年)。 LIII。在最接近空间点系统的直线和平面上。 《伦敦、爱丁堡和都柏林哲学杂志和科学杂志》, 2 (11),559–572 页。
[5]h .霍特林(1933 年)。将复杂的统计变量分析成主要成分。教育心理学杂志, 24 (6),417 页。
[6]何,d,梁,e,陈,x,,I .,& Abbeel,P. (2019 年 5 月)。基于人口的扩增:扩增策略时间表的有效学习。在机器学习国际会议(第 2731–2741 页)。
分析 Docker 图像安全性
Docker 容器并不像许多人认为的那样本质上是安全的。因此,使用工具和扫描仪来清除容器中的漏洞至关重要…
很多人认为 Docker 图像和容器在默认情况下是安全的,不幸的是,事实并非如此。有很多因素会影响 Docker 图像的安全性。无论是安装在映像中的包、应用程序使用的库,甚至是基本映像,所有这些组件都可能给应用程序带来漏洞。这些问题中有很多是很容易避免的,尽管…
安克雷奇-克莱尔公司
在 Docker 映像中查找漏洞的最简单方法是使用或等工具对其进行检查:
- Anchore Engine:Anchore是集装箱图像检查、分析和认证的集中服务。它使用来自操作系统供应商的漏洞数据(feeds)扫描图像,如 Red Hat 、 Debian 或 Alpine 。对于非 OS 数据,它使用 NVD(国家漏洞数据库),包括 RPM 、 Deb 、 APK 以及 Python (PIP) 、 Ruby Gems 等漏洞。
- Clair : Clair 是由 CoreOS 为码头工人和 APPC 集装箱开发的静态分析仪。它使用来自类似来源的漏洞元数据Anchore——红帽安全数据、NVD、Ubuntu CVE 追踪器、Alpine SecDB、Debian 安全漏洞追踪器等。
安装
现在我们知道了我们想要使用的工具,是时候旋转它们了。 Anchore 和 Clair 都包含各种集成,可以部署到 Kubernetes 或 OpenShift 上,但是为了演示的目的,我们将在本地机器上使用docker-compose
来设置它们:
要设置锚定器,运行以下程序:
要设置克莱尔运行以下程序:
这样我们就可以开始分析了!
注意:我们将在本文稍后回到 Clair。
检查图像的漏洞
让我们从 Anchore 和基本 Debian 镜像开始。为了分析我们的图像,我们需要做的是add
它和wait
来完成分析:
分析图像后,让我们看看发现了哪些漏洞:
我们首先运行带有all
标志的image vuln
命令,列出镜像中存在的操作系统和软件包漏洞。所有这些都是Negligible
或Unknown
,所以这很好。接下来,我们运行evaluate check
命令来查看这个映像是否通过了默认策略检查,正如您在上面所看到的(Status: pass
),它通过了。在这方面,这些类型的基本图像通常表现很好,因为它们被广泛使用,因此受到了大量的审查。
但是,使用 Python 3 Debian Buster 映像构建的简单的 Python 应用程序呢?让我们先看看 docker 文件:
没什么叫【脆弱】**【不安全】的吧?那么,让我们构建并分析它:
我首先使用上面的debian.Dockerfile
和简单的hello.py
构建图像。然后我把它推到 Docker Hub,从那里它被添加到 Anchore 并最终被分析。现在我们可以看看结果:
嗯,嗯,嗯…不再那么好了。我们所做的,就是切换到官方 Python Debian 映像,我们突然有了 1000 多个漏洞,包括一些Low
和Medium
严重性的漏洞,相比之下,只有几个Negligible
有普通的 Debian 映像。最重要的是,在运行映像评估后,我们可以看到它失败了(Status: fail
)。
所以,即使我们使用了官方的看似安全的图片,并且创建了没有明显漏洞的非常简单的应用程序,我们仍然有很多安全问题。那么,我们该如何改善这一点呢?
寻找卓越的形象
说到安全性,基本映像的最佳选择是scratch
——也就是空容器。然而,从零开始构建我们自己的基础映像是不太实际的,而且考虑到我们大多数人都不是安全专家,这可能会带来更多的安全问题。
在我看来,排在scratch
之后的第二个最佳选择是发行版,它是由谷歌制作的一组图像,创建这些图像的目的是为了安全。这些图像包含您的应用程序所需的最少内容,这意味着没有外壳、包管理器或任何其他工具会使图像膨胀,并为安全扫描仪(如 CVE )产生信号噪声,从而更难建立合规性。我已经在我之前的博客文章这里中更详细地介绍了发行版,所以如果你想知道更多,去看看吧。
好吧,那么distrolles现在是我们安全映像的选择,但是在我们分析任何东西之前,让我们先来看看新的Dockerfile
:
与 T21 的 Debian 版本相比,没有太大的变化。我们真的只是把赛跑运动员的图像换成了gcr.io/distroless/python3
。现在,我们可以继续构建它,推动它并将其添加到 Anchore Engine :
最后,是时候看看发行版是否比 Debian 版本表现得更好了:
的确如此!与第一个例子相比,我们只有 53 个漏洞和 2 个Low
严重性漏洞。还有,看政策评估——这个镜像通过了,而 Debian 那个失败了!
因此,我们可以有把握地得出结论,当谈到我们的容器化应用程序的安全性时,distroles是更好的选择。但是,我们还可以检查和改进一些东西,例如,我们可以尝试使用不同的评估策略:
上面的命令列出了我们可以用来检查图像的所有可用策略。默认情况下,它使用anchore_default_bundle
,这很好,但是如果我们想看到使用不同的白名单和规则执行检查,那么我们可以尝试,例如anchore_cis_1.13.0_base
:
从上面可以看到,我们首先通过运行policy hub get
来查看这个特定策略的描述。之后,我们安装它并运行policy list
命令,这表明我们现在有 2 个策略可用,新策略处于非活动状态。所以,我们用最后一个命令(policy activate
)激活它。
在我们对新政策进行检查之前,让我们先谈谈它包括哪些内容。考虑到是 Docker CIS 1.13.0 检查,将重点关注本文件提供的指导。举几个例子来说明它在寻找什么样的问题:
ADD
用于代替COPY
的命令- 未列入白名单的开放端口
- 失踪
HEALTCHECK
- 使用不可信的基础映像
- 使用
root
作为有效用户
您可以运行anchore-cli --json policy hub get anchore_cis_1.13.0_base
获得该政策中规则的完整列表。现在,我们知道了它将寻找什么,是时候运行它了:
在一些已安装的软件包的输出中有相当多的警告,但是特定于这个策略的是上面列出的那些。这些是使映像无法通过策略评估的问题/漏洞,应该进行分析。其中一个(第二个)是由于使用了发行版映像,因为它不在白名单中,所以可以忽略。至于其他两个——这些都是应该解决的实际问题,但它们都有简单明了的解决方案。
这向我们表明,根据我们的需求选择特定的策略,甚至使用多个策略来捕捉尽可能多的问题是一个好主意。
漏洞的类型/级别
然而,并非所有的漏洞都是相同的,其中一些甚至不适用于我们的应用程序/容器/环境。因此,我们不仅要看它们的严重程度,还要看计算严重程度的因素。这包括攻击媒介、攻击复杂性、保密性影响、完整性影响等。然后,这些因素会创建使用 CVSS 计算器生成的最终严重性分数。具体的括号有— None
、Low
、Medium
、High
和Critical
。关于他们的更多信息可以在 https://nvd.nist.gov/vuln-metrics/cvss 的 NIST 网站找到。
修复漏洞
上例中的漏洞很容易修复,但情况并非总是如此。您可能会遇到严重性分数较高漏洞,或者对于您的特定用例来说有问题的漏洞。当涉及到基础映像或其中包含的包的问题时,你不应该修复它们,因为那是所述工具的开发者和/或发行者的责任。也就是说,您应该通过移除攻击媒介来防止或至少减轻现有和未来漏洞的可利用性,例如通过使用没有任何外壳的发行版。最重要的是,使用构建/部署管道定期运行漏洞检查是一个好主意,以便在引入漏洞时尽快发现漏洞,最好使用多种扫描工具。
Anchore 对 Clair
说到运行多种扫描工具…那么克莱尔呢?它与主播相比如何?这就是我们如何针对我们的示例 Debian 和发行版映像运行它:
查看以上命令的输出,它看起来与我们从 Anchore 那里得到的非常相似——Debian 镜像有很多问题,而发行版没有任何问题。在第一次扫描的输出中,有一个我省略了的巨大的漏洞列表,但是我检查了所有的Low
和Medium
严重性漏洞,它们同时出现在 Anchore 和 Clair 扫描结果中,但是情况可能并不总是如此。因此,我建议运行多种扫描工具,最好是使用不同来源的漏洞元数据的扫描工具。
你可能想看看的一些其他工具包括 Docker Bench for Security 或 IBM Container Registry 中包含的漏洞扫描。
结论
对于与安全相关的东西,最好是积极主动,在漏洞变成实际问题之前尽量避免它们,本文中展示的工具可以在这方面提供很大帮助。我认为使用和实现这个工具非常容易,所以任何人都可以让它们成为日常工作流程的一部分,或者理想情况下,成为他们自动化管道/工作的一部分。在一定程度上,我们创建的应用程序的安全性是每个开发人员的责任,而不仅仅是安全专家或测试人员的责任,所以我们都应该参与到使它们足够安全的工作中来,也许只是通过不时地运行漏洞扫描。😉
本文最初发布于martinheinz . dev
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
通过 Python 中的可视化和机器学习分析电动滑板车活动
从数据收集到在热图上可视化聚类
根据最近发布的 2019 TomTom 交通指数报告,全球 416 个城市中有 239 个城市(57%)交通拥堵加剧。仅在美国,主要城市的交通拥堵率为+20%。这意味着,一次出行将比在城市基线不拥挤的情况下多花 20%的时间。洛杉矶以+42%高居榜首,然后是+37%的纽约市。更不用说由于更高的排放量而带来的环境影响了。
如上所述,人们正在使用替代的通勤方式,如拼车、骑自行车、公共交通或两者的结合。一个这样的选择是电动滑板车。电动滑板车对市场来说相当新,主要针对通勤的“最后一英里”部分。
伯德公司就是这样一家公司。对于那些不熟悉该公司的人,伯德在全球 100 多个城市经营无码头滑板车。有各种型号的滑板车,在我去华盛顿特区实地考察的时候,我就骑过其中的两种。骑滑板车不贵,除非你的平衡感很差,否则骑这种车应该很容易。
来源(左):CBINSIGHTS(右):NACTO
停放在华盛顿特区十字路口的小型摩托车
简介:
踏板车通常安装有大量传感器,这导致大量数据产生,因此有利于有趣的数据探索。
我带着以下问题出发:
1.电动滑板车在华盛顿特区及其周边的普及程度如何?
2.平均行程距离是多少?用法是否取决于一周中的日期和时间?后者看似直观但仍需证明。
3.我能从顾客使用滑板车的行为中了解到什么?
4.我可以用上面的发现来产生见解吗?
数据收集:
某些州要求公司制定开放数据政策。但是华盛顿特区没有,因此 Bird 没有一个面向华盛顿特区的公共 API,但是一个在 Github 上化名为 ubahnverleih 的人设法一起破解并开发了一个 API。ubahnverleih 已经为多个其他乘车共享公司开发了 API,所以如果你正在寻找任何这样的数据,请查看他的 Github。
华盛顿特区及其周边地区大约占地 100 平方英里。为了覆盖整个区域,我精心选择了 49 个不同的坐标点(大致 36 sq。这样,在 API 中 ping 这些点,将返回该地区所有小型摩托车的数据。我使用的方法可以在这里找到。
图片来源(右):波导手机 app
这是任务的第一部分。然而,它缺少一个要素:时间。我想研究一段时间内踏板车的使用情况,而不仅仅是踏板车在地理上是如何分布的。
为了捕捉一段时间内踏板车的使用情况,我编写了一个脚本,每隔 5 分钟运行一次,收集上面提到的所有坐标点的踏板车数据。我让这个程序运行了 1.5 个月(48 天),产生了大约 800 万个数据点。
数据收集挑战:
该项目的 API 争论阶段存在许多技术挑战,虽然我不会一一列出,但我认为特别提到其中一个是有帮助的,可以说明在野外收集数据时会出现的各种挑战:
- 我写了一个脚本,收集了一整天的数据。在启动收集过程后,我注意到程序已经连续两个早上崩溃了。
- 我的第一反应是认为这是由于代码中的一个错误,但即使在检查之后,也没有发现是什么导致了这个问题。
- 然后我检查了收集的数据,注意到一个模式,崩溃前每晚的最后一次 API 调用总是在【第二天】凌晨 12 点之前的某个时间。当时没有对这个问题提供任何见解,但这是了解问题原因的一个小线索。在对代码进行了大量修补和不成功的测试后,我决定通宵坐着亲自见证崩溃。
- 这种方法,以及随后的黑客侦探工作,让我发现 API 在每天晚上 12 点到凌晨 4 点之间不会返回任何东西,而是在凌晨 4 点以后开始工作。公司经常对他们的系统进行维护,有些比其他公司更频繁,这可能是一个原因。无论如何,在知道这一点后,我在脚本中添加了一个小部分来说明每晚的事件,这是一个简单的解决方法。但这无疑是一个具有挑战性的诊断。
有了现在定期收集的数据,我创建了一个 PostgreSQL 数据库来更好地组织和管理数据。从我的 Jupyter 笔记本中添加了另一个脚本部分来做同样的事情。
数据:
在经历了上述步骤并克服了挑战之后,下面是结果数据的样子。
每一行包含一个单独的踏板车的所有相关信息。
例如,在上面快照的第一行,小型摩托车‘3db0f8a8–72ed-4d4b-aff8-f0f2de53c875’
,型号为‘bd’
,位于4:00:53 AM
的10/3/19
上的(38.927739,-77.097905)
,电池电量为42
,这意味着它将运行另外5069
个单位(大约 6 英里,根据数据比例)。
使用数据发现的踏板车型号“bd”。(厂商网址:http://www.electisan.com/)
有一些空的和多余的字段,它们没有用,因此我的分析没有考虑它们。
分析策略:
以下是我回答上述问题的方法概述。
我已经在帖子的末尾浏览了结果。
- 数据清理。
- 从收集的数据中创建踏板车出行数据集,并使用它来研究使用和活动,同时也有助于进一步分析。
- 定义检测踏板车何时静止和何时移动的规则,以便分析和比较使用活动。
- 使用上述规则的特征工程和对踏板车位置的聚类来跟踪聚类中心。
为了这篇博文,我将更多地关注方法和结果,而不会过多地探究背后的代码。如果需要,我会展示某些代码部分。完整的代码可以在我的 GitHub 这里找到。
1.数据清理
双重:
A.修复数据类型。
B.创建一个 datetime 功能,以允许对数据进行切片和切块。
我创建了一个助手函数来为我们完成上述工作..
def fix_dtypes(df):
int_cols = [‘battery_level’, ‘estimated_range’]
float_cols = [‘latitude’, ‘longitude’]
df = df.astype({col: ‘int32’ for col in int_cols})
df = df.astype({col: ‘float32’ for col in float_cols})
#Combining date, time column to datetime
df[‘date_time’] = df[‘Date’].map(str) + “ “ + df[“Time”].map(str)
df[‘date_time’] = pd.to_datetime(df[‘date_time’])
return dfdf_scootsbydate = df_multiple_days.groupby(‘Date’ [‘id’].nunique()
df_scootsbydate.mean()[Out]: 5337.555555555556So, on any given day, there are about 5338 scooters spread throughout the D.C. region.
2.踏板车旅行:
原始数据实际上是每次 ping API 时拍摄的一系列快照。每次 ping 都会返回当时所有可用指示器的数据。
在一个非常简单的层面上,人们可以想到一本翻书动画。就像每个页面是一个快照,所有页面放在一起向我们显示从开始到结束的整个序列,第一页显示序列的开始,最后一页显示序列的结束。类似地,第一个 API 调用将显示一天开始时踏板车的时间和位置,最后一个 API 调用将显示一天结束时的时间和位置。
下面是结果数据的一个片段,以及我是如何完成的。
在不涉及太多技术细节的情况下,(‘latitude_first, longitude_first)
是在‘date_time_min’
日期&时间投入运行时的坐标,(‘latitude_last, longitude_last)
是在‘date_time_max’
日期&时间停止运行时的坐标。
‘time_diff_hrs’
:滑板车一天的总运行时间。其被计算为仅仅‘date_time_max’ — ‘date_time_min’
。
计算行驶距离( **‘distance_miles')**
:
‘distance_miles’
:滑板车一天行驶的距离(英里)。
从上面,我们有(‘latitude_first’, ‘longitude_first’)
和(‘latitude_last’, ‘longitude_last’)
为每辆踏板车。现在我们需要计算这两个位置之间的距离。有几种方法可以计算两点之间的距离。但是在这里,由于我们处理的是 GPS 坐标,我们使用 哈弗森距离 进行计算。哈弗辛考虑了地球的球形,而像欧几里德距离这样的公式却没有考虑,这就是为什么哈弗辛适合在这种情况下使用。
有一些好的 Python 包可以做到这一点。我使用这个资源来构建一个助手函数来为我完成这项工作。
3.平稳性和非平稳性的定义规则。
在这一点上,我们有了收集数据的 1.5 个月中每天的踏板车出行数据集。我们现在可以分析踏板车的用法和运动。但是这并不像仅仅根据距离特征过滤指示器那么简单,换句话说,子集化数据以只选择那些‘distance_miles’
是0
的指示器。
**Stationary**
:当满足【Cond _ 1】**和【Cond _ 2】时,认为 Scooter 是静止的。
**Non-stationary**
:如果不满足**'Cond _ 2】但满足【Cond _ 3】,则认为 Scooter 是非静止的(或在行程中)。也就是说,如果‘distance_miles’
大于 0.5 英里并且‘battery_diff’
小于 50 英里(下面给出解释)。**
有一些挑战,我解释了我用来识别踏板车是否静止的三个条件:
1.Cond _ 1:‘time_diff’
应该大于 4 小时。有很多情况下,滑板车会在白天出现一小段时间,然后消失几天。可能是由于各种原因,如维修、保养等。这篇文章在某种程度上证实了这一点。滑板车的消失并不真正算作滑板车的使用活动,因此没有计入我们的分析。这一规则使得重点放在“肯定”是静止的踏板车上。
2
2。 Cond_2 : ‘distance_miles’
应该小于 0.5 英里。人们可能会猜测,要将小型摩托车视为静止,您所需要的就是距离特征为零,对吗?好吧,数据有一些不一致的地方,我们注意到有些情况下滑板车移动了很小的距离,不到几码左右。几码并不真正算作“旅行”,所以我们将阈值保持在 0.5,以避免在我们的分析中采取这些滑板车运动。**
3. Cond_3 : ‘battery_diff’
应该小于 50。这是一个偷偷摸摸的方法,因为这是在分析的几次迭代之后实现的。有时候,滑板车被拿出来充电后,会被放回一个完全不同的地方。我们最初的分析认为这是踏板车运动,但在认识到这种不规则性后,使用这种条件有助于我们避免犯这种错误。50 是一个很好的阈值,因为在这种情况下,电池电量会急剧变化,例如,电池电量为 10 的小型摩托车被拿出来充电,然后电池电量为 100 时再放回去。在这种情况下,电池电量的差值将为 90。这种情况会正确地认识到这种不规则性,并且不会将这种踏板车计入我们的分析中。
工作日(左)和周末(右)出行最多的五种滑板车
4.特征工程和聚类。
Feature 使用上述规则将原始数据集设计成固定/非固定以及工作日/周末组合的子集。
下面是静态踏板车的一些统计数据..
平日的固定滑板车
周末的固定滑板车
正如你从上面所看到的,在某个特定的点上有一系列的滑板车。为了产生洞察力,我们需要了解踏板车的整体运动,而不是关注个人。我们使用 K-Means 和 HDBSCAN 聚类方法来实现这一点。
结果和结论:
我们已经做好了所有的准备工作,现在是公布结果的时候了…
1.滑板车在华盛顿特区的普及程度如何?
当然,踏板车的数量会随着时间的推移而变化,但我在这里的目的只是为了更好地了解 Bird 在该地区部署踏板车的程度。
所以,平均来说,整个华盛顿大约有 5338 辆小型摩托车,这比我最初预计的要多得多。
2.平均行程距离是多少?一周中的哪一天对使用有影响吗?
回答问题的第一部分..平均行程距离约为 1.88 英里
出于对验证我的发现的好奇,我开始在网上搜索任何报告或文章,结果发现,我的发现与网上发表的这篇报告非常接近(下面的链接)**
考虑到这只是基于 1.5 个月的数据,这是非常接近的。
第二部分 …比较不同日期的使用活动…
其中 0 —周一,1 —周二,以此类推。
正如我们从上面看到的,工作日的使用量似乎比周末多一点。
老实说,这让我很惊讶,因为我以为滑板车更多地是用于娱乐目的,因此在周末会有更多的活动。
但是从我上面的结果来看,工作日的活动似乎比周末多。这表明人们可能更多地使用滑板车作为通勤工具。也许上下班的时候。
考虑到华盛顿地区的交通状况,这是有道理的。走出地铁/公交车站后,人们可能会使用滑板车来覆盖他们的“最后一英里”。
当我看到伯德发表的关于其在华盛顿使用滑板车的报告时,我能够验证我的理论
“……50%的骑行者表示他们使用 Bird 上下班。但是乘客们也在使用公共交通工具——29%的乘客使用 Bird 来连接华盛顿地铁和公交车……”——Bird
3.我能从使用模式中学到什么?
有什么比想象更好的理解事物的方法呢?我在 Python 中使用了一个很酷的包,叫做“叶子”,通过它你可以在真实世界的地图上构建自定义的可视化效果。
由于存在大量的滑板车和它们的运动,绘制单个滑板车和它们的运动只会使地图拥挤,难以解释。为了实现这一点,我使用了叶子上很酷的热图和时间插件来绘制热图。你们可能都很了解热图,颜色越深,浓度越高,在这个例子中是指踏板车。**
可视化策略
平日(左)与周末(右)的固定滑板车活动
工作日(左)与周末(右)的非固定踏板车活动
非固定(左),固定(右)周末
4.我能利用上述问题的发现并产生见解吗?
为了做到这一点,我根据地理坐标将踏板车分组,然后通过不同的时间段将这些分组可视化。这将使我对整体动作有一个很好的理解。我使用 K-Means 和 HDBSCAN 聚类算法来实现这一点,然后我比较了不同情况下的结果,如下所示。
平日(左)与周末(右)的固定滑板车活动
工作日(左)与周末(右)的非固定踏板车活动
结论:
- 上面的图像代表了华盛顿的心跳模式。
- 工作日的上午 8 点至 10 点时段显示出较高的使用率,接近中午时段时有所下降,但在下午 4 点至 6 点时段又有所回升。
- 周末的活动比平日少,但使用模式与平日相似。
- 在任何一天,活动在一天的早些时候集中在市中心区域,在一天的晚些时候扩散到市中心周围的区域。代表用户的通勤行为。
来自上面的使用数据和见解可用于找到最常用的路线,并使用该路线,公共交通服务,如公共汽车、地铁等。可以改进。可以对路线进行聚类,然后根据受欢迎程度进行排名。
使用密度可以与基于人口统计的人口密度相互参照,并且资源可以集中于在这两个方面排名靠前的人。
评论或提问?请发邮件至:himanshu.agarwal20792@gmail.com 或联系LinkedIn