TowardsDataScience-博客中文翻译-2020-九十五-

龙哥盟 / 2024-10-15 / 原文

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

主成分分析解释

原文:https://towardsdatascience.com/principal-components-analysis-explained-33e329cec1c4?source=collection_archive---------33-----------------------

用一些代数来理解 PCA 的工作原理🔧

蒂姆·莫斯霍尔德在 Unsplash 上的照片

P 主成分分析(PCA)是机器学习(ML)中最著名的算法之一,它旨在降低你的数据的维度或者执行无监督聚类。毫无疑问,五氯苯甲醚在世界范围内广泛使用🌍,在从金融到生物学的任何操纵数据的领域。

虽然有许多很好的资源给出了执行 PCA 的方法或对它所做的事情的很好的空间解释,但是很少有资源深入到它背后的数学概念的罩下。

虽然不需要理解数学就可以使用 PCA,但我坚信对算法的深刻理解会让你成为一个更好的用户,能够理解它在任何特定情况下的性能和缺点。此外,数学概念在 ML 中是相互联系的,理解 PCA 可以帮助你理解其他使用代数的 ML 概念(出于好奇,请查看图 3。在帖子末尾的后经文部分)。

这篇文章试图用背后的数学概念来解释不同的步骤。我假设读者已经熟悉代数基础。

首先,让我们回顾一下 PCA 方法,快速回顾一下不同的相关步骤:

  1. 规范化你的数据,我们称之为规范化数据集 XXN 行(示例)和 d 列(维度),是一个(N,d)矩阵
  2. 计算协方差矩阵σX
    σ是一个(d,d)矩阵
  3. 计算σ的特征向量和特征值
  4. 对特征值最大的 k 个特征向量进行排序(这是 k 个主成分),做 W ,这是一个(d,k)矩阵
  5. 将原始数据集 X 投影到由步骤 4 排序的 k 个特征向量构成的低维空间上,即W
    X’= XW……X’准备就绪👨‍🍳!X’现在是一个(N,k)矩阵

鉴于 kk<d,我们摆脱了之前袭击我们🗡️的维度诅咒🐉

太酷了!但是,采用协方差矩阵并以某种方式将其与特征向量分解混合,如何能够在低维空间中捕获我们的数据集呢!?

要回答这个问题,是时候把手弄脏,看看 PCA 发动机的引擎盖下到底是怎么回事了!🛠️

主成分分析的目标是将原始数据集投影到一个低维空间,该低维空间捕获原始数据集的大部分信息。因此,我们应该问自己的第一个问题是:

什么获取了数据集的大部分信息?

PCA 背后的基本关系是,方差捕获了数据集的大部分信息。方差(离差)越大,信息就越多。因此,PCA 旨在找到一个保持最大 T4 方差的低维空间。

因此,第一个归一化步骤旨在归一化原始数据集的每个维度的范围,使每个维度的方差具有可比性。这里没有什么太疯狂的🙏🏻

太好了!但是现在我们明白了最大方差是在低维空间中保留原始数据集的大部分信息的关键,我们可以问:

如何找到一个保持方差最大的低维空间?

为了实现这一点,我们可以简单地从寻找向量 u 开始,当我们的数据集被投影到该向量上时,该向量捕获了最大的方差。

图一。具有最大特征值的特征向量指向最大方差的方向

我们刚刚说明了协方差矩阵σ的最大特征值的特征向量指向最大方差方向并且这个方向的方差为 λ

我们现在可以将我们的原始数据集 X 投影到 1 轴上,即向量 u ,这保留了其原始方差的最大值。但是,也许我们想再找一个轴,或者 k 个轴..?

没关系!我们简单地重复图 1 所示的相同过程。以上 k 次,每次增加一个新的约束:先前最大的(关于它们相关的特征值)特征向量必须与新的候选向量正交

在这里,我们已经证明了协方差矩阵的特征向量指向最大方差方向,并且它们相关的特征值等于沿着这些方向的方差,正如图 2 所示。说明了它。

图二。协方差矩阵的特征向量指向最大方差方向[ 来源

最后,为什么我们选择具有最高特征值的 k 个特征向量来保留原始数据集的最大方差是显而易见的。

瞧啊!👌

资源:

  • 有用的主成分和特征向量的堆叠交换
  • 关于协方差矩阵的几何解释的帖子不错
  • 完成多伦多大学关于拉格朗日乘数和 PCA 用例的课程

PS :在神经网络优化中,计算损失函数的 Hessian 矩阵是有用的,以便帮助梯度下降步骤适应关于其方向的学习速率。简而言之,Hessian 展示了损失函数的梯度在任何方向上的变化有多快。

使用我们在 PCA 中看到的相同代数概念,现在有意义的是,Hessian 矩阵的特征向量指向最大曲率的方向,并且它们相关的特征值表示函数的曲率在该方向。因此,在梯度下降更新期间,高曲率(高特征值)方向需要较低的学习速率,因为梯度在该方向上变化更快。
反之亦然,低曲率方向的学习率更高。

图 3。特征向量或 Hessian 矩阵指向最大曲率方向[ 来源

主成分分析解释

原文:https://towardsdatascience.com/principal-components-analysis-explained-53f0639b2781?source=collection_archive---------21-----------------------

二维主成分分析;所有图片均由作者生成

它是什么,为什么有用,以及如何使用它

我们为什么需要 PCA?

在真实世界的数据集中,我们的许多变量是不重要的,或者是相互关联的。如果我们正在进行一项有监督的机器学习任务,留下与我们的目标变量无关的变量会降低我们训练数据中的信噪比,从而更难构建一个好的模型。在我们的训练数据中保留相关变量可能会导致多重共线性问题,具体取决于所使用的建模方法。

解决这些问题的一个可能的方法是去除不相关的变量。问题是如何决定一个变量是不相关的。您可以使用类似于通过 Akaike 信息标准的最佳子集选择或递归特征消除的技术(但不要使用逐步回归),但是使用您的训练数据来选择要保留的变量会将偏差引入我们对均方误差和其他重要模型质量估计值的估计中。

解决这个问题的另一种方法是降维;这涉及到寻找数据的低维表示。如果我们可以找到原始数据的子空间,它保留了几乎所有的相关信息,我们就可以更容易地估计模型。如果子空间足够小,它可以使像聚类或依赖于距离度量的模型这样的任务成为可行的选择,因为我们避免了维数灾难。

寻找数据集的较低维度表示的最流行的方法是主成分分析(PCA ),其在训练数据集中寻找变量的线性组合,该线性组合最大化由每个线性组合解释的方差,服从一些约束。我们将在下一节深入探讨。

什么是 PCA?

假设我们有一个矩阵,有 n 行(观察值)和 k 列(变量)。让我们称这个矩阵为, X 。我们希望找到以下形式的线性组合:

其中 𝑎 𝑖 是列向量,i = 1,2,…,k,其解释了 X 中的最大变化量,并且每个线性组合与其他线性组合正交(成直角)。我们希望线性组合是相互正交的,这样每个主成分都可以获得不同的信息。

为了找到最大化线性组合方差的 X 列的线性组合,我们需要求解:

最大化线性组合方差的一种方法是使每列的权重无穷大。为了保持【𝑎】1 中的每个元素都不为无穷大,我们需要对【𝑎】1 施加一个约束。我们在 PCA 中这样做的方法是强制1 中的平方元素之和为 1。因此,要找到第一个主成分,我们需要找到:

为了找到第二个主成分,我们需要附加一个约束条件,即 𝑎 2 与 𝑎 1 正交。

对于每个附加分量,直到我们达到 k,我们为所有前面的分量添加正交约束。

不需要迭代求解这些约束最大化问题,结果是数据的协方差矩阵的特征向量是主分量,所以我们可以直接求解。我们将样本协方差矩阵的特征向量按其对应的特征值(从大到小)排序,得到有序的主成分。特征值是由它们相应的特征向量解释的方差。

我假设你已经学过线性代数课程,所以我不会在这里介绍如何寻找特征向量和特征值,但是你可以在这里找到一个例子来复习如何手工计算。我也强烈推荐 3Blue1Brown 的视频进行图形化解读。如果你的线性代数课像我一样需要大量记忆,我推荐你观看 3Blue1Brown 的整个线性代数精华系列。这些视频中的视觉效果真的帮助我理解了我之前刚刚记住的概念。

我们如何执行 PCA?

使用标准化重新缩放 X 中的所有列非常重要,这样每个变量都在相同的刻度上。将所有变量放在同一个尺度上可以确保一个变量不会因其测量单位而主导一个主成分。

假设我们有一个矩阵, X ,有 n 行(观察值)和 k 列(变量),其中每一列的平均值为 0,标准偏差为 1。

肘部有直线的碎石图示例

我们现在准备使用 Z ,一个被称为主成分得分的矩阵,用于聚类、回归或我们对原始数据集所做的任何事情。

我在下面构建了一个 Python 类,它能够执行 PCA,设置组件数量,并转换数据。

为了帮助可视化 PCA 正在做什么,我生成了一些二维随机数据,其中变量之间存在线性关系。生成数据后,我将其标准化以便绘图,并使 PCA 对象适合数据。然后我绘制了标准化数据和两个主成分。第一个是紫色,第二个是蓝色。如您所见,第一个主成分指向数据中变化最大的方向。第二个与第一个正交,指向数据中第二大变化的方向。我画了一个单位圆来强调每个向量的长度是 1。现在让我们将主成分分析应用于一个实际问题。

二维主成分分析

我们在实践中如何使用 PCA?

为了给出 PCA 的实际例子,我使用了我从另一个项目中得到的一些数据。它包含 2015 年人口普查区域的人口统计数据,汇总到县一级。然后,我添加了希拉里·克林顿和唐纳德·特朗普在每个县的投票份额,并从中计算出谁赢得了该县。如果你想要我用来争论数据的原始数据和代码,给我发消息,我很乐意分享。

数据集中的变量包括总人口、性别比例、种族、民族背景、人们如何通勤和通勤持续时间,以及公开、私人、自营或失业人口的比例、各行业的就业比例和人均收入。

正如你可能会怀疑的那样,公共就业、私人就业、个体经营和失业的比例总和应该是 1。在这个数据集中有几组其他的变量符合同样的模式,这意味着一些变量是多余的。我们将在 PCA 中看到这一点。如果我们不做 PCA,我们将从每组线性相关列中删除一个变量,但我们将把它们留在这里。

我们将比较 K-Nearest Neighbors (K-NN)分类器对未转换数据和转换数据的性能,以预测特朗普或克林顿是否在该县赢得更多选票。这真的不是一个好问题,因为 2016 年美国大选已经结束,永远不会有新的观察结果可以预测。这个数据集将更适合于数据探索和确定什么样的人口特征与给定的选举结果相关联。也就是说,探索人口统计变量和 2016 年美国大选不是本文的重点;如何应用 PCA 是本节的重点。

我选择了 K-NN 分类器,因为它依赖于距离来找到离样本外观察值最近的点。随着维数的增加,数据点之间的距离越来越远(参见:维数灾难)。出于这个原因,我们应该期望在线性组合捕获有意义的关系的条件下,在少量数据的线性组合上训练的 K-NN 分类器优于在原始数据集上训练的分类器。

既然我们已经分离了所有的数据,我们可以对训练人口统计变量执行 PCA。使用碎石图的经验法则,我们将保留数据的前 6 个主要成分。

当一个成分解释的方差低于解释的平均方差时停止,将导致我们保留前 9 个主成分。因为数据是标准化的,有 31 个变量,所以总方差是 31。用总方差除以变量数,得到 1。第 10 个主成分解释了总方差 31 中的约 0.9,因此低于该临界值。

因为在更高的维度上点之间的距离更远,为了建模的目的,我将使用前 6 个主成分,而不是前 9 个。

解释县人口统计数据的 Scree 图和累积方差

我打印出了下面最后 6 个主成分解释的方差,以及解释的总方差的比率和该比率的累积和。上面我说过一些变量是其他变量的固有线性组合。这显示在最后 5 个主成分中。最后 5 个解释了大约 0 的方差,表明有 5 个变量是其他变量的线性组合。

这些总计为 1 的变量组包括性别比例、种族和民族背景比例、行业就业比例、主要通勤方式比例和就业状况。所以尽管在未转换的数据中有 31 个变量,实际上只有 26 个。

由最后 6 个主成分解释的差异

现在,让我们只保留前 6 个主成分,并转换测试人口统计变量。

虽然我们保留了 6 个主成分,但我们可以将前 3 个可视化,并添加颜色编码标签(蓝色代表克林顿获胜,红色代表特朗普获胜)。通过这样做,我们可以看到克林顿县和特朗普县在前 3 个主成分所跨越的空间中不是完全可分的,但是这些县之间在人口统计学上有明显的差异。

前 3 个主成分空间中的县图;红色是特朗普赢得更多选票的县,蓝色是克林顿赢得更多选票的县

现在是时候在未转换的数据上训练和测试 K-NN 分类器,并使用 PCA 对数据进行低维表示。

这里我们创建了 s klearn 的 K-NN 分类器的一个实例,使用 5 个最近的邻居来分类观察值。点与点之间的距离用欧几里德距离来衡量。我使用了反向距离加权,而不是均匀距离加权。

现在,让我们训练这两个模型,并获得对测试数据的预测。

现在让我们在测试集上比较每个模型的准确性。

这里我们可以看到,在前 6 个主成分转换的数据上训练的 K-NN 分类器具有比在未转换的数据上训练的模型高 4 个百分点的样本外准确度!

通过找到变量的一些线性组合,我们能够在数据点更接近的低维空间中捕捉重要信息,从而提高 K-NN 模型的准确性!

我希望你现在对 PCA 有一个直观的理解,为什么它有用,如何估计它(如果出于某种原因你不想使用来自像 scikit-learn 这样的来源的快速和稳定的实现),以及如何将它应用到一个实际问题中。感谢阅读到最后!

你可以在这里找到用来做这篇文章的笔记本。

主成分分析(PCA),行业的基本原理、优势和见解

原文:https://towardsdatascience.com/principal-components-analysis-pca-fundamentals-benefits-insights-for-industry-2f03ad18c4d7?source=collection_archive---------40-----------------------

了解为什么 PCA 不仅可以减少维度和节省计算时间,还可以避免多重共线性,更好地理解工业过程行为。

具有可能的 2D 缩减计划的三维空间

如果您已经探索数据科学有一段时间了,您可能会遇到使用降维的文章或案例,其最著名的方法是:主成分分析(又名 PCA)。

降维通常被视为减少大型数据集中的特征数量而不丧失其重要性(=方差)的一种实用方法。直接的好处是减少建模所需的计算能力和时间。我会在下面解释为什么这个比那个多得多!

如果你还不熟悉(还没有!)用这种方法,这里有一个小介绍让你入行。

降维背后的直觉

让我们从一个非常简单的例子开始,其中数据集的 3 个特征(x、y 和 z)显示在下面的 3D 空间中(代码如下):

围绕 x、y 和 z 轴显示的原始数据集。

你可以很容易地注意到,尽管有 3 个维度,散点图主要分布在“y”和“z”周围;围绕“x”轴的变化相当低。

如果我们必须对这个数据集建模,那么与“y”和“z”相比,“x”维度有多重要?大概没那么多吧!

因此,代替使用 3 个坐标[x,y,z]来识别这个 3D 空间中的一个点,[y,z]可能已经是这个点在哪里的良好指示。不是吗?

我们甚至可以更进一步,想象一个 2D 计划,按照这个计划,沿着 x 轴排列点,并用 2 个坐标指定点的位置!可能会是这样的:

带有可能的 2D 缩减计划的原始数据集

由于这个红色 2D 计划和它的两个相应的向量,我们只需要两个坐标来准确地确定每个点的位置。

显然,我们丢失了一些关于每个点根据原始 x 轴的“深度”的信息,但这是我们愿意冒的风险!

如果你对了这个例子,你就知道什么是降维了!

让我们深入研究代码并发现特征向量

我们使用 3 种略有不同的正态分布来创建 3 个要素的虚拟数据集:

Plotly Scatter3D 将以互动方式显示我们的数据集:

像往常一样,Scikit-Learn 库提供了一种实现主成分分析的实用方法:

我们可以注意到,缩减的数据集仍然保留了原始数据集方差的 97%!

让我们以二维和三维显示这个新数据集:

点分布在特征向量 1 和 2 周围

(请注意,这里的 x、y 和 z 轴与原始数据集中的轴无关)

关于特征向量,应该认为是原空间到降维空间的转换矩阵。

这个过程的美妙之处在于,出于可视化的目的,我们将这里的示例限制为 3 维,但它可以在 n 维中实现!

降维的额外好处是什么?

我们通常使用降维来对抗“维数灾难”,这可以用几个原则来概括:

  • 数据集包含的要素越多,模型就越复杂……导致所需的计算时间、功耗和存储空间越大。
  • 通过尝试包含数据集的整体复杂性,模型将更有可能过度适应训练示例。
  • 随着特征数量的增加,很难获得在整个可能性“宇宙”中均匀分布的代表性样本

但是等等,还有更多!

通常会在数据集中发现冗余特征:例如:年龄、年龄等级、出生年份等。

具有以非常接近的方式变化的特征被称为 多重共线性 并且它可以严重影响线性模型:系数将不能代表它们对目标的真实影响,并且最重要的是,训练数据中的微小变化可以显著改变分配给每个特征的系数的值,有时甚至导致符号转换!

为什么降维在工业中很重要?

当然,在对工业过程建模时,上面提到的所有原因仍然成立,但我想补充以下几点:

  • 使用主成分(如果您正在使用 PCA)将防止您创建与物理约束不匹配的模型。
    举个例子,我们可以假设一个产品的湿度和加热过程温度成反比(加热越多,得到的水分越少!).
    这两个原始特征将在同一个向量上对齐和相对,因此,通过从这个减少的维度中学习,您的模型无法推断出原始特征同时增加或减少的行为。
  • 如果您的测量系统不平衡,Principal Components 将使提供给模型的输入合理化。假设您在过程开始时有 6 个温度传感器,结束时只有 2 个。该模型会在数学上给你的过程的开始分配更多的权重,而它们应该被同等对待。假设上游和下游温度以不同的方式变化,将从这 8 个特征中仅提取两个主成分(上游- > PC1,下游->PC2);这也将防止引入多重共线性。
  • 它还能使你的过程中潜在的物理、机械或化学现象变得清晰。让我们拍一个真实的(但经过消毒的!)举例说明这一优势:

我正在处理的原始数据集由 13 个要素 x 5000+行组成。在应用主成分分析后,我发现只有 4 个主成分就足以保持 95%的原始方差!

对应的特征向量描述如下(注意:它们的值在-1 和 1 之间变化。它们离极端值越近,与原始特征的相关性就越强):

原始特征向量

我突出显示了主要组件与 pc1、pc2 和 pc3 上的原始功能紧密关联的坐标,但没有描述原始功能是什么:

我们注意到三组特征:

  • 5、6、7 和 8(蓝色)
  • 2、11 和 12(橙色)
  • 0、4 和 10(红色)

让我们来揭示一下原始特征所对应的内容:

在这里我们可以清楚地看到:

  • PC1 对应于过程中的物理流量,与储罐填充相关联
  • PC2 对应产品的物理特性变化。此外,我们注意到湿度与干物质和粘度相反。
  • PC3 对应产品温度变化。

除了上面提到的所有好处之外,降维显然可以带来关于工业过程中发生的现象的透明度,为团队带来有价值的见解!

像往常一样,我希望你喜欢发现什么是降维,它的好处,以及它可以为工业案例带来什么!

值得一提的是,除了 PCA 之外,还有很多降维技术:线性、非线性、自动编码器等。它们有据可查;选择权在你!

敬请期待!

[## 皮埃尔-路易·贝斯康德关于媒介的文章

数据科学、机器学习和创新

pl-bescond.medium.com](https://pl-bescond.medium.com/pierre-louis-besconds-articles-on-medium-f6632a6895ad)

使用 Python 创建可变因子图(PCA)图

原文:https://towardsdatascience.com/principal-components-analysis-plot-for-python-311013a33cd9?source=collection_archive---------15-----------------------

在本教程中,我将向你展示如何一步一步地使用 matplotlib 创建可变因子图

作者图片

一.导言

分析中最有趣的活动之一是使用漂亮的可视化工具。有了变量因子图,就可以轻松解释主成分 分析。一张图胜过千言万语

主成分分析(PCA)是一种降维方法,用于降低大型数据集的维数。它将多个要素转换为数量少得多的新要素,同时保留原始数据的大部分信息和可变性。

如果特征的数量是 2,我们可以将它们放入 2D 图中,并想象不同的特征如何影响每个新的组成部分。上图中,来自虹膜数据集四个特征(萼片宽度、萼片长度、花瓣宽度、花瓣长度)被压缩成两个。它们是组件 1 (y 轴)和组件 2 (x 轴),保持了原始数据集 97.77%的信息。四个向量表示这两个分量如何解释四个原始特征。

二。编码

代码是使用 Python 和matplotlib的最少知识创建的。我相信简单是所有真正优雅的基调。创建这个情节有三个重要步骤

  • 数据准备
  • PCA 分解
  • 情节

1)数据准备

我们首先从sklearn导入虹膜数据集

from sklearn import datasets
import pandas as pd
iris = datasets.load_iris()X=pd.DataFrame(data=iris.data,columns=iris.feature_names)
X

iris 数据集有 4 个特征,我们希望将这 4 个部分转换为之前讨论过的 2 个部分。

2) PCA 分解

scikit-learn包使得 PCA 方法变得非常方便,我们需要做的就是从sklearn分解库中导入 PCA。

from sklearn.decomposition import PCAcolumns=X.columns.values #Store the name of the columns for labeling
pca=PCA(n_components=2)
pca.fit(X)
pca_values=pca.components_
pca.components_

我们定义n_component=2,用fit的方法训练模型,存储 PCA components_。这些components_代表特征空间中的主轴。这里的两个数组表示 4 个特征的(x,y)坐标。稍后我们将在单位圆上用 4 个向量来画出这些点,这就是有趣的地方。

3)情节

a)圆圈

让我们首先调整字体和大小的阴谋

import matplotlib.pyplot as plt

plt.figure(figsize=(10,10))
plt.rcParams.update({'font.size': 14})

下一步是画一个圆。我们将使用圆形函数

#Plot circle#Create a list of 500 points with equal spacing between -1 and 1import numpy as np
x=np.linspace(start=-1,stop=1,num=500)#Find y1 and y2 for these points
y_positive=lambda x: np.sqrt(1-x**2) 
y_negative=lambda x: -np.sqrt(1-x**2)
plt.plot(x,list(map(y_positive, x)), color='maroon')
plt.plot(x,list(map(y_negative, x)),color='maroon')

作者图片

如果你不知道λ或 map 函数,你应该把这些有用的方法放进你的工具箱

我们将用同样的逻辑画一个更小的圆,只是为了更美观

#Plot smaller circle
x=np.linspace(start=-0.5,stop=0.5,num=500)
y_positive=lambda x: np.sqrt(0.5**2-x**2) 
y_negative=lambda x: -np.sqrt(0.5**2-x**2)
plt.plot(x,list(map(y_positive, x)), color='maroon')
plt.plot(x,list(map(y_negative, x)),color='maroon')

让我们也添加 x 轴和 y 轴,这也是完全可选的!

#Create broken lines
x=np.linspace(start=-1,stop=1,num=30)
plt.scatter(x,[0]*len(x), marker='_',color='maroon')
plt.scatter([0]*len(x), x, marker='|',color='maroon')

作者图片

如果你完成了这一步,你就完成了一半。给自己一个鼓励!

b)矢量

在绘制矢量之前,让我们定义将要使用的颜色。下面的代码为相应的特征定义了 6 种不同的颜色,如果特征多于 6 个,颜色列表将重复其循环。

#Define color list
colors = ['blue', 'red', 'green', 'black', 'purple', 'brown']
if len(pca_values[0]) > 6:
    colors=colors*(int(len(pca_values[0])/6)+1)

现在让我们画出向量并标记它们

add_string=""
for i in range(len(pca_values[0])):
    xi=pca_values[0][i]
    yi=pca_values[1][i]
    plt.arrow(0,0, 
              dx=xi, dy=yi, 
              head_width=0.03, head_length=0.03, 
              color=colors[i], length_includes_head=True) add_string=f" ({round(xi,2)} {round(yi,2)})"
    plt.text(pca_values[0, i], 
             pca_values[1, i] , 
             s=columns[i] + add_string )

函数plt.arrow取向量的起点和终点。这里,初始点是原点(0,0),端点是先前从 PCA 分量方法获得的。

最后,我们为剧情添加一些其他的化妆品。

plt.xlabel(f"Component 1 ({round(pca.explained_variance_ratio_[0]*100,2)}%)")
plt.ylabel(f"Component 2 ({round(pca.explained_variance_ratio_[1]*100,2)}%)")
plt.title('Variable factor map (PCA)')
plt.show()

作者图片

三.结论

您也可以通过执行以下操作来导入上述代码

pip install -i [https://test.pypi.org/simple/](https://test.pypi.org/simple/) variable-factor-map-Huy-Bui==0.0.3from variable_factor_map import pca_map 
from sklearn import datasets
import pandas as pdiris = datasets.load_iris()
X=pd.DataFrame(data=iris.data,columns=iris.feature_names)pca_map(X, figsize=(10,10), sup="Iris", print_values= False)

pca_map功能有 4 个输入:

  • X :熊猫数据框
  • figsize (float,float):输出的宽度和高度。默认值为(10,10)
  • sup (字符串):剧情标题。默认值为空字符串
  • 打印值(布尔):显示矢量值。默认值为 False

也可以访问我的 GitHub 看源代码。玩 Python 玩得开心!

主测地线分析

原文:https://towardsdatascience.com/principal-geodesic-analysis-2ec7ad1b2679?source=collection_archive---------24-----------------------

机器学习遇上黎曼几何

这是我写的第二篇关于黎曼流形中机器学习的文章。这次是将主成分分析推广到黎曼空间。希望读者对 PCA 有所了解。再次回忆一下 PCA,下面这篇文章可以帮助理解主成分分析背后的数学原理。我还推荐读者阅读我之前关于测地回归的文章,其中讨论了黎曼几何中必要的概念。

图 1:主要测地线分析(图片由作者提供)

PCA 一瞥

PCA 是一种众所周知的数据分析技术,它用数据的主要成分来表示数据。PCA 的两个众所周知的应用是降噪和降维。让我们用一个简单的降噪例子来回顾一下 PCA。

真实世界的数据是嘈杂的。噪声可以由我们收集数据的环境或收集过程本身引入。让我们讨论图 2 中的场景。

图 PCA 降噪(图片由作者提供)

左边的点状数据点是源的输出。正如我们所见,源可以用线 P1 完美地模拟,这意味着源的输出本质是一维的。P1 是这个案件中的主要角色。在右边,我们可以看到,当源输出被噪声污染时,仅用 P1 并不存在完美的拟合。数据点现在倾向于在垂直于直线的维度上延伸。为了在这里得到完美的拟合,我们需要另一个主分量 P2 垂直于 P1 。现在,我们可以将噪声数据点表示为 P1P2 的线性组合。

当我们要通过分析噪声数据来建模一个源时,我们需要找到一种方法来消除噪声的影响,以便更好地建模。常设仲裁院服务于这一目的。当我们将数据投影到主成分中时,我们可以清楚地看到每个成分的重要性。如图 2 所示,分量 P2 不如 P1 明显,我们可以推断 P2 是由噪声引起的,与数据源没有什么关系。在这种情况下, P2 可以作为噪声被丢弃,而 P1 可以用于对源进行建模。噪声分量不太明显的事实是因为噪声值之间的相关性较小或没有相关性,而源输出是高度相关的。

同样,像图像这样的数据,尽管有成千上万的维度,但大部分信息只包含在它们为数不多的几个主要成分中。因此,当我们对这些数据进行处理时,可以丢弃不重要的成分,只保留少数重要的成分,从而大大降低维度。这将提高数据处理的效率。

计算 PCA 的方法有很多,最有效的一种是计算数据矩阵的奇异值分解(SVD) 。从数学上讲,主要主成分是数据点投影方差最大的成分。

主测地线分析(PGA)

就像在以前的文章中我们将线性回归扩展到位于黎曼空间中的数据一样,我们现在将扩展 PCA 以寻找位于相同空间中的数据的主成分。这被称为主要测地线分析,我们将找出代表给定数据的主要测地线。

我们将利用上一篇文章中讨论的数学知识。因此,如果您还没有阅读,我再次建议您在继续阅读本文之前先浏览一遍。

在进入 PGA 之前,我们先定义一下黎曼空间中的均值概念,我们称之为内禀均值

内在均值

一组数据点的平均值是一个点,所有数据点到该点的距离之和最小。

在欧几里得空间中,这很容易通过将所有数据点的总矢量和除以数据点的数量来计算。但是,在一般流形中,不能保证平均的唯一存在。然而,如果我们有一个很好的本地化的数据集,均值是存在的,并且是唯一的。计算平均值需要求解函数的梯度下降优化:

其中梯度由下式给出:

既然我们已经定义了平均值,我们可以继续定义主测地线。请注意,定义测地线需要定义两个参数:一个点和该点切线空间中的一个向量,测地线由参数计算的指数图给出。

在 PGA 中,主测地线被定义为它们都通过中间点。既然我们已经算出了平均值,现在我们需要算出它的切空间中的一个向量。像在 PCA 中一样,主测地线是一条曲线,它具有数据点投影到其上的最高方差。数学上,(测地线的)矢量参数可定义为:

我们可以归一化 PCA 中的数据点,将它们的平均值转换为零,因为一组数据点在缩放、转换或旋转时携带相似的信息。然而,这样的事情在黎曼流形上是不可能的。上式中的主要挑战是求数据点在测地线 g 上投影的大小,我们来讨论一下投影的计算。

投影到测地线:

显而易见,测地线 G 中任意一点 x 的投影定义为:

我们现在将在中点处线性化流形,并在切空间中近似投影。测地线 G 穿过平均值。把流形线性化是指把流形的一个小空间看成是我们可以进行向量运算的欧氏空间。因此,投影的值可以通过近似 Log(x,y) 来近似为:

我们可以将投影的对数图表示为:

但是我们这里需要的实际上是平均值的投影长度,因此我们需要对数图的大小。

我们可以看到,在线性化流形时,投影简单地减少到最小化向量距离,并且投影的大小类似于我们在向量空间中所做的。因此,对于这种情况,我们可以将上述最小化的解写成类似于 PCA,即点积:

最后,PGA 问题归结为 PCA 问题:

PGA 作为 PCA 问题

我们所做的所有近似都是将 PGA 问题转化为 PCA 问题。万一事情变得混乱,我们可以用 3 个步骤来总结一切:

图 3:将数据点映射到切线空间(图片由作者提供)

  1. 计算数据点的平均值。
  2. 平均实现切空间,通过对数映射将每个数据点映射到切空间。图 3 是一个例子,其中红点是球形流形上的数据点,其平均值是最高点,极点。在极点处绘制切空间,通过对数映射将数据点从流形映射到切平面。映射的点用蓝点标记。

3.计算映射值{ vi }的 PCA。图 3 中的蓝点是切空间中的点,因此可以通过欧几里德运算找到 PCA。获得的 PCA 值和平均值的指数图将定义主测地线。

在球形流形上实现

让我们在球面流形上进行一个简单的 PGA 的例子。让我们像在测地线回归中一样定义一些函数:

(作者代码)

现在,我们将生成合成数据并对其进行 PGA。我们将获取位于两条测地线的数据点,切线向量 v1v2 以点 p 为中心,并向它们添加随机噪声以获得我们的数据点。此外,沿第一条测地线有 20 个点,沿第二条测地线有 10 个点。最后,我们将连接数据点以创建数据矩阵 y

(作者代码)

现在,计算主测地线相当简单。我们将只执行前一节中描述的 3 个步骤。

(作者代码)

我们可以看到,我们得到的两个主要主向量(按照大小递减的顺序)与我们在生成数据点时使用的向量 v1v2 具有相似的方向,并且平均值也接近于 p 。请注意,我们不需要将 v1v2 的大小与获得的主向量进行比较,因为我们感兴趣的是找出主测地线,重要的只是测地线方向的位置和方向。此外,主向量大小的变化会改变测地线的长度,但这种改变并不显著。

最后,我们可以定义测地线的指数地图的平均和两个主要的主向量获得。图 4 详细描述了示例中的场景:

图 4: PGA(图片由作者提供)

虚线点是沿两条测地线合成的数据点,两条红色曲线是与数据点拟合的测地线 G1G2 。数据点的交点就是中间点。因此,我们可以清楚地看到,我们已经用两个主测地线表示了数据点。

参考

  1. 形状非线性统计研究中的主测地线分析。http://www . cs . jhu . edu/~ misha/reading seminar/Papers/Fletcher 04 . pdf
  2. 流形值统计,精确主测地线分析,以及线性近似的影响。http://image.diku.dk/hauberg/sommeretal10.pdf

非主干专业的主成分分析

原文:https://towardsdatascience.com/principle-component-analysis-for-the-non-stem-major-a6080bb646bd?source=collection_archive---------41-----------------------

了解 PCA 背后的直觉

正如您可能已经知道的,数据可视化是一种非常有用的数据分析技术,可以帮助我们识别模式、趋势和群体。无论您是否是可视化学习者,数据可视化都可以在您未来的项目中很好地为您服务。通过这篇文章,我们将看到更高维数据集的局限性,并理解主成分分析(PCA)作为一种解决方案背后的直觉,而无需过于深入数学理论。

数据可能非常多样化,有各种各样的形状和大小,当我们面对一个从未见过的数据时,有时我们可能会感到害怕,尤其是当它的结构有点吓人时。在学校里,我们可能有机会分析用很少变量,也许是两三个变量清晰格式化的数据。在我们第一次看到真实世界时,我们面对的是一个包含 20 个变量的数据集(现在这很可怕)!因此,我将解释高维数据出现的问题,以及 PCA 如何解决这样的问题。

概念动机

考虑这种情况,我们有一个有 N 个观察值和单个变量的数据集。问题是:

我们能够可视化单个变量吗?

为了可视化 1 维的情况,我们可以用一个线形图来实现,该线形图为每个观察值绘制了一个点,该点对应于沿着数字线的特定变量的相应值。

绘制一维图(为简单起见,绘制了 5 个样本)

太好了!当只有一个变量时,我们能够将数据可视化。通过这个一维图,我们能够看到,有些观察结果倾向于低端,而其他观察结果倾向于高端(数据可视化的威力...我说的对吗?)

然而,这只是一维的情况。让我们再问一次这个问题:

我们能一起想象两个变量吗?

绘制二维图(为简单起见,绘制了 5 个样本)

看起来棒极了!同样,我们能够为 1 维和 2 维情况创建一个数据图。让我们再一次问这个问题:

我们能否将三个变量的数据可视化?

绘制三维图(为简单起见,绘制了 5 个样本)

那么有什么问题呢?

现在让我们试着一次可视化 4 个变量(等等……我们不能这么做)。然而,可视化 4 维和更高维度的空间实际上是不可能的( bummer )。因此,当涉及到高维数据集时,我们可以看到有两个问题:

  1. 我们无法想象大于 3 的维度
  2. 随着维度数量的增加,这产生了其他的复杂性

如何使用 PCA 来解决这个问题?

提到这个问题,现在我们可以开始看到 PCA 的使用了。在这种情况下,我们可以将这 20 列减少到 2 或 3 个变量。如果我们能以某种方式创建 2 或 3 个变量来很好地总结原始数据集的可变性(即很好地总结数据),这就可以做到。实际上,我们希望找到的这些变量,就是我们所说的主成分。我们说 PCA 是一种用于降低数据集维度的方法,即降维技术

对于这些主成分的高级表征,它们将是由不同权重的 20 个变量组成的值。这意味着这 20 个变量对每一个组成部分都有不同的重要性。换句话说,我们可以确定哪些变量对于给定的主成分是最重要的。

这样我们就可以找到一些主成分来很好地解释原始数据的总可变性。

因此,一旦我们确定了 2 或 3 个能很好地概括原始数据集的主成分,我们就可以提取这些成分并将数据可视化。

PCA 是如何工作的?

为了这个解释的目的,我将一步一步地解释 PCA。将 PCA 应用于更高维度的数学直觉将类似于将要解释的 1 维和 2 维。

第一步:计算平均值

求主成分 1 的第一步是求变量 1 和变量 2 的均值,得到数据的中心。假设我们这样做了,那么我们将确定变量 1 轴上的一个点和变量 2 轴上的一个点,它们都代表该变量所有样本的平均值。

接下来,我们可以画出穿过这两点的假想线。在某一点上,这两条线会有一个交点。这个交叉点是数据的中心。

第二步:转移数据

将数据置于原点中心

这里我们将数据集中在原点。请注意,当我们移动数据时,中心会发生变化,但数据点之间的距离保持不变。

第三步:找到最符合数据的直线

我们首先画一条穿过原点的线。最初,这条线不需要成为“最佳拟合线”这条线必须穿过原点。

这条线最初不需要成为最佳拟合线的原因是,这条线本身只是作为我们的“最佳拟合线”的候选线因此,接下来我们将检查该候选人是否确实是我们要找的人(是被选中的人吗?)

接下来,我们将原始数据点投影到直线上。

当我说投影时,你可以把它想成是数据点本身被扔在可能的最短路径的线上。而且这条路径永远是在投影点(即橙点)形成直角的路径。

通过原点和投影点画一条线

请注意,当我们投影这个点时,形成了一个直角三角形

从投影创建的距离

现在,我们可以开始确定这条线是否是最佳拟合线!

你可能会想,我们可以最小化 d₁…dₙ距离的平方和来确定它(即,原始紫色数据点到投影橙色点之间的距离),然后平方,这样负数就不会抵消正数。也许我们可以这样想,因为这类似于我们如何最小化直线和数据点之间的平方距离之和来确定线性回归线的最佳拟合直线。直觉上,这实际上是最容易想象的,也是正确的说法。

然而, PCA 实际上旨在最大化 d₁'…dn'距离的平方和(即从原点到投影点的距离)。

为什么我们要最大化距离?

直觉上,我们最大化距离以获得最佳拟合线没有太大意义。让我解释一下。

我们确定投影产生一个直角三角形。由于这个概念,我们能够应用勾股定理。

数学直觉

请注意,我之前说过,我们的目标是最小化 d₁…dₙ距离是正确的(在上面的图中,d₁表示为 b)。

现在我们可以说距离 a 是一个固定值,因为我们没有移动原始的紫色数据点本身。这意味着勾股定理方程的左边是固定的。我们移动的是穿过原点的红线。因此,如果 a 是固定值,并且我们正在降低/最小化距离 b,,那么距离 c 必须增加/最大化。所以最大化

我们可以通过等式看出这一点:a 是固定的。如果 b 减少,那么 c 必然增加。

我们可以用图形看到这一点:将直线移近数据点,使 b 最小化,但也使 c 最大化。

因此,可以通过最小化 d₁…dₙ或最大化 d₁'…dₙ'.来确定我们的最佳拟合线 PCA 选择后者,因为后者更容易计算。

选择最佳拟合的线检查所有 d₁'…dₙ'的平方距离之和是否最小。所以我们计算 SS(d₁'+d₂'+…+dₙ'的最大值)以获得最佳拟合线。

我们认为整个 d₁'+d₂'+…+dₙ'

总之,我们获得了最大 SS(d₁'…dₙ')得到我们的最佳拟合线。由此你实际上了解了什么是主成分 1,什么是主成分 1 的特征值。

最佳拟合的红线实际上是我们的主成分 1 或 PC1。

2.SS(d₁'…dₙ')实际上是 PC1 的特征值。特征值帮助我们确定在汇总数据时哪些成分是最重要的。

步骤 4:检查主成分 1 (PC1)

主成分 1

现在我们有了主成分 1,我们可以检查它的一些特征。其中之一是它的斜率。

例如,假设主成分 1(如上)的斜率为 0.25。

考虑的示例

如果我们考虑到这一点,那么这意味着沿 x 轴(变量 1)增加 4 将使 y 轴值(变量 2)增加 1 个单位。

步骤 5:正常化

当我们说“正常化”时这实际上是让斜边的值为 1。

常化

注意,我们现在有一个长度为 1 的向量,它的 x 分量向量的长度为(4/4.12 = 0.97),它的 y 分量向量的长度为(1/4/12 = 0.242)。

这个长度为 1 的“归一化”向量称为本征向量。

特征向量有什么重要的?

本征向量给出了两个向量,x 分量向量和 y 分量向量。这两个向量给了我们加载分数。在本例中,他们分别取值 0.97 和 0.242。这意味着对 PC1 来说,变量 1 比变量 2 重要 4 倍。

第六步:找到主成分 2

为了得到 PC 2,我们画一条与 PC 1 正交的线。也就是说我们通过 PC 1 画一条线,形成一个直角。

  1. 将点投影到 PC 2 上
  2. 然后我们可以得到直线的斜率
  3. 归一化向量以获得特征向量
  4. 并获得 PC 2 的加载分数

主成分 2

请记住,仍有数据投射到 PC 1 上。所以通过旋转轴,使得 PC 1 是 x 轴,PC 2 是 y 轴。我们得到一个新的坐标系,其中 PC 1 是 x 轴,PC 2 是 y 轴!

根据主成分创建的新坐标系

我们看到每个数据点都被投影到 PC 1 和 PC 2 上。我们取这两个投影点并获得新点(如上所示)。这给了我们 PC 图。

主成分图

超越两个变量

我们回顾了两个变量的情况,以便理解 PCA 的幕后发生了什么。如果我们有两个以上的变量。遵循类似的过程,因为后续分量必须与预先存在的主分量正交。

所以当我们有 N 列时,我们可以确定 N 个主成分。但是查看主成分占总变化的多少允许我们选择特定的主成分,直到我们获得令我们满意的总变化捕获阈值。

最后提醒

  1. 特征值的重要性在于它被用来确定一个主成分占总变化的多少
  2. 特征向量的重要性在于允许我们获得负载分数,这有助于我们确定变量相对于特定主成分的重要性

[1]饶彤彤。(2019 年 7 月 20 日)维度的诅咒https://towards data science . com/The-Curse-of-dimensional-50 DC 6 e 49 aa1 e

设定营销计划目标的原则

原文:https://towardsdatascience.com/principles-in-setting-goals-for-marketing-programs-ec7d206d988f?source=collection_archive---------27-----------------------

分析公司用来设定 Instagram 营销活动目标的七条原则。

来源:Pixabay,开放使用许可证

在 Instagram,我们非常重视目标。目标是重要的锚和焦点。他们确保每个人都是一致的,并对特定营销计划试图实现的目标设定预期。

作为一名分析主管,我有责任为营销计划设定目标。

然而,设定目标并不总是容易的。时间限制、复杂的组织结构、不同的意见和不清晰的策略是可能模糊目标设定过程的许多因素中的一些。

为了对抗这些并限制偏见,我依靠一套原则来为每个营销项目设定目标。

以下是我用来为 Instagram 营销分配目标的七条原则:

原则 1:目标必须是商业问题的自然延伸,是我们希望观众采取的行动和实现行动的策略。

从商业问题到行动,到战略,再到目标,应该有一条自然的线索。我们举个假设的例子。

商业问题是这样的——我们推出了故事贴纸来增加整体内容产量,但用户正在避免使用这些贴纸,因为他们认为它们太难使用了。

行动——我们希望用户尝试使用贴纸,提升整体内容生产。

策略——使用基于教程的广告向“非贴纸用户”展示在他们的 Instagram 故事中使用贴纸的简单方法。

因此,我们的目标是在“非贴纸用户”中提升新的内容制作。

原则 2:每个营销计划应该有两个目标——一种情感和一种产品。

这里的想法很简单。我们希望营销计划既能推动行动(根据我们的产品目标衡量)又能推动积极情绪(根据我们的情绪指标衡量)。

如果一个营销项目提供的是即时行动,而不是情感,那么从长远来看,它对我们没有帮助。如果一个营销项目提升的是情绪而不是行动,那么它就不能帮助我们推动直接的商业价值。

一个好的测量计划测量许多指标。但目标应该只有两个。所有其他指标都应构成学习日程的一部分。

原则三:要有主次目标。成功首先根据主要目标来判断,然后是次要目标。

与原则 2 相关——在这两个目标中,应该有一个主要和次要目标。

成功应该首先根据主要目标以及是否实现来判断。如果是,我们转到第二个目标。这个主要和次要目标层次结构的作用是帮助确定许多走向市场组件的优先级。

原则 4:目标应该在最高线,业务影响水平。

我们设定最高目标。这里我们的意思是,最终,我们所做的一切都应该推动整体业务向前发展。这可能意味着增加更多用户,提高整体参与度或其他。

我们需要避免过于细化的目标。总体而言,粒度目标并不能告诉我们是否在推动业务发展。

回到原则 1 的贴纸例子。我们可以设定提高贴纸使用率的目标,但这并不能告诉我们是否对整体业务做出了贡献。这是因为贴纸产品最终是为了提升整体内容生产,而不仅仅是贴纸的使用。贴纸使用量的上升可能只是意味着我们的营销正在蚕食业务的另一部分,并没有真正提高整体内容产量,也没有帮助整体业务。

因此,我们围绕整体内容产量的增长来设定目标。

原则 5:媒体指标、广告或产品认知度和信息传递指标都不是可接受的目标。

与原则 4 相关——媒体指标、认知度和信息传递指标不是可接受的目标,因为除非它们转化为业务影响,否则毫无意义。这些指标应该在衡量计划的学习议程部分,以便跟踪和用户学习。

原则 6:目标应该有一个数字指标和一个度量标准。

这就是语言的重要性。目标包括数字目标和指标。例如,一个好的目标可能是这样的:“故事内容生产率增加+20%”。

数字目标部分是“+20%的增量提升”,明确指出该营销计划的目标是在当前基线的基础上再增加+20%。衡量标准是“故事内容产出率”,这清楚地表明了该活动关注的具体衡量标准。

数字目标与指标相结合构成了一个目标。

原则 7:一旦发起运动,目标就不能改变。

启动后改变目标是不好的做法。然而,这种情况比人们想象的要多。

我偶尔看到的一种情况是营销活动没有提高目标。但对其中一项学习指标有明显的积极影响。在这一点上,活动所有者可能会改变他们的目标。但是任何目标转移都应该不惜一切代价避免。

一旦活动开始,目标就永远不应该改变。如果目标指标没有变化,但另一个指标明显变化,那么这是对下一个活动的学习和洞察。

现在你知道了。这是我用来为我们的营销计划设定目标的七条原则。如前所述,这些目标的作用是提供防护栏,减少意外偏差,建立一致性,并消除可能影响目标设定的外部因素。

我还向整个营销组织公开发布这些原则,并管理“办公时间”。我这样做是为了让每个人都知道我们用来锚定我们的目标的期望和护栏,以及延伸的营销计划。我发现,这些原则帮助我的营销同事写出强有力的商业案例,就像我帮助我设定客观目标一样。

这些原则让我们都脚踏实地。它们提供了重要的界限,并迫使项目保持专注,即使政治或复杂性威胁到我们的工作。不用说,在我从事分析和数据科学工作的 15 年中,我已经成为了原则的忠实粉丝。

打印我的外卖

原文:https://towardsdatascience.com/printing-my-takeout-7abfc28ce415?source=collection_archive---------36-----------------------

正如我们所知,3D 打印食品正在改变食品行业!

在 Unsplash 上由 amirali mirhashemian 拍摄的照片

这是一个周六的晚上,当你在看你最喜欢的电影时,电视上突然出现了一则美味披萨的广告。面包皮做得非常完美,中间覆盖着一些难以置信的番茄酱。它看起来味道很好,你可以说出一些配料的名字;罗勒、橄榄油和新鲜大蒜均匀分布在这道意大利美食中。最重要的是,人们可以欣赏马苏里拉奶酪在热量的帮助下融化,融合,形成浅棕色的水泡,就像交响乐一样。然后最好的部分是意大利香肠,它比通常的要厚得多,因为它们是直接从他们的祖国意大利进口的。你决定打开电视上的气味扩散器;柴火烤披萨的味道弥漫在房间里,到达你肺部的每一个角落。受够这种折磨了,你想要一个!所以你让 3D 食物打印机给你打印一份,你马上就能品尝到这种美味的食物了。

这听起来可能好得难以置信,但实际上,底层技术已经存在,而且今天就可以买到。今天的技术的唯一问题是它仍然非常粗糙,并且有一些限制,我将在下面解释。因此,我们还需要几年的时间,才能打印出与之前描述的场景类似的美味披萨。

照片由理查德·艾赛迪在 Unsplash 拍摄

气味印刷已经存在十多年了。索尼开发了一个系统,该系统使用电子鼻传感器,能够检测和捕捉气味。然后,它使用基于香味的墨水在特殊的明信片大小的照片纸上复制它们。然而,数字气味技术仍然带来许多挑战。我们仍然需要了解哺乳动物的嗅觉,房间里气味的分布是有问题的,合成气味的安全性也是有问题的。

照片由王思然·哈德森在 Unsplash 上拍摄

3D 打印食品是一个完全不同的故事。这些打印机能够使用不同的浆料和材料制作各种菜肴。这份清单包括巧克力、意大利面、糖果等等。使用这种系统的优点很多。

从美学的角度来看,食物可以做成任何想要的复杂形状和形式。事实上,这种打印机为厨师提供了设计的自由,这在传统烹饪技术中是闻所未闻的。食物的美学不仅仅在米其林星级餐厅中很重要。任何有孩子的人都知道,孩子更可能吃恐龙形状的西兰花,而不是传统而乏味的树状西兰花。

健康是另一个关键因素,因为实际食物的成分可以在打印菜肴之前决定。这将有助于人们通过用其他成分替代一些成分来做出更健康的选择,他们也可以插入新的成分来保持类似的味道。这台机器还会记录下生产了什么,并精确记录消耗的卡路里。一些保险公司已经奖励过健康生活方式的人,这种打印机可以为此做出贡献。

但是有些人选择吃特定的食物,而另一些人却没有选择。事实上,面筋的比率和无乳制品的条件(举几个例子)正在上升。有了 3D 打印的食物,对人体有害的成分可以很容易地被排除。这在医院里也是非常重要的,在那里他们每天要做成千上万的饭菜。有了这项技术,膳食可以适应病人的个人营养需求,这将有助于加快恢复。由于一些患者可能会在咀嚼方面遇到困难,因此可以使用更令人愉快的一致性来打印食物,从而提高患者的生活水平。此外,由于这些人中的大多数都在接受药物治疗,将药物融入他们消费的食物中可能更简单,尤其是在与儿童打交道时(他们发现吞咽药物有问题)。

印刷食品也可能有助于我们对抗气候变化。众所周知,大多数食物来源,如肉类、蔬菜等。需要大量的水来生产。正因为如此,我们可以去寻找其他来源,如高蛋白的昆虫,但许多人(尤其是西方人)不愿意尝试。3D 打印机可以迅速将一群蝗虫变成看起来像阿根廷牛排的东西。

食物浪费是这些打印机可能解决的另一个问题。有时,食物仍然适合消费,但只是不够“好”而不能出售。3D 打印将把这些剩菜改造成新的形状,从而使它们更有食欲,并让它们留在食物链中。

彼得·道恩在 Unsplash 上的照片

正如我们在上面看到的,实验性烹饪的时代正在进入一个全新的不同层次。然而,我们仍然有一些限制。打印效果很好,但食物需要在食用前单独烹饪。最大的挑战很可能是大众接受。3D 打印食品带来了一种新的范式转变,许多人仍然没有为这种行为变化做好准备。对于所使用的成分仍有很多怀疑,在大多数情况下,这些成分并不像天然产品。

这项技术就要问世了,我们在微波炉旁边看到 3D 打印机只是时间问题。一旦我们做到了,只需要下载一份杰米·奥利弗食谱,打印出来,然后在我们最喜欢的电影前吃。

【https://www.businesstoday.com.mt】本文最初发表于请在下面留下你的想法评论。如果你喜欢这篇文章,请跟我来🐦推特,🔗 LinkedIn 或者😊脸书

Alexei DingliProf 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他出版了几本同行评审的出版物,并且是马耳他的一员。由马耳他政府成立的人工智能工作组,旨在使马耳他成为世界上人工智能水平最高的国家之一。****

使用艾森豪威尔矩阵对请求进行优先级排序

原文:https://towardsdatascience.com/prioritizing-requests-using-the-eisenhower-matrix-2ffc8dba7c8c?source=collection_archive---------31-----------------------

数据科学家可以使用艾森豪威尔矩阵来避免简单地接受命令,而是将自己树立为战略顾问

数据科学家必须不断处理短期请求和长期项目之间的紧张关系。忽视长期项目,你可能会受到最小的影响。然而,忽视短期要求,你可能会发现自己失业了。

因此,最好的数据科学家是那些能够在短期需求和长期项目之间有效分配时间的人。在实践中,这可能相当困难,因为利益相关者可能会问很多问题。这些问题中有一些是紧迫而重要的,而另一些则既不重要也不紧迫。

美国前总统德怀特·艾森豪威尔(Dwight Eisenhower)提出了用紧急性和重要性来帮助他确定任务优先级的想法。利用艾森豪威尔矩阵,他能够毫不留情地优先安排自己的一天。

在本文中,我们将探讨这个想法,以及它如何帮助数据科学家专门处理利益相关者的请求。我们将通过有效的策略来处理下面四个象限中的每一个。

  1. 高重要性/高紧迫性

通常,当您收到这些请求时,其他所有事情都会被搁置。除了对这些类型的请求进行预测和规划之外,这里没有太多的余地。

例如,如果您知道在每个季度末,您负责提取关于业务绩效的数据和评论,您可能会发现自动完成这些工作会有所帮助。发现可自动完成的可重复工作,尤其是具有高度重要性和高度紧迫性的任务,将有助于你树立快速完成目标的信誉。

2。高重要性/低紧迫性

当涉及到高重要性和低紧迫性的请求时,你可能会发现自己想要一头扎进去。然而,更谨慎的方法是首先理解你被要求做什么。

通常你可以协商这种类型的要求,并把它们精简到更容易处理的内容。例如,营销主管可能会发送一份详细的数据清单,他们需要这些数据来了解同类相食的影响。现实情况可能是,只需要一两个数据就可以讲述他们想要讲述的故事。

一般来说,对于高重要性和低紧迫性的请求,你应该努力创造一个动态的战略顾问,而不是一个订单接受者。拥有独特的观点并在项目上留下你的印记将确保你在未来的项目中占有一席之地。

由于这是一个低紧急度的请求,您应该使用您的最佳判断来决定是否应该重新安排您当前工作队列的优先级(包括长期项目)。有时,尽管问题很重要,但你可能会发现推迟并设定未来的交付日期会更好。

3。低重要性/高紧迫性

仅仅因为事情紧急,并不意味着它很重要。

如果有人在某个日期前需要数据,你不应该为了满足他们的期限而放弃你正在做的一切。特别是当这个请求不重要的时候(与其他请求和你正在努力的长期目标相比较)。

处理这些请求的最好方法是获取更多的信息。有时候,只需要打个 15 分钟的电话,就能意识到提取数据所需的额外工作可能最终只是一张附录幻灯片,永远不会在会议上提出来。在这种情况下,您可以推迟到实际需要数据的时候。

在这种情况下,您可以探索一种轮换模式,在这种模式下,您团队中的每个成员对这些类型的请求“随叫随到”。

4。低重要性/低紧迫性

最后,也是最棘手的象限是那些低重要性和低紧急性的请求。在艾森豪威尔模型中,我们将简单地“消除”这些任务。在公司环境中,你必须更加小心地回应这类请求。

推迟这类任务的一个简单方法是让涉众先做一些工作。可能是一些尖锐的问题,要求他们在你开始提取任何数据之前做一些跑腿的工作。这要么会为你赢得时间,要么如果要求一开始就不那么重要,他们可能会失去动力。

你也可以尝试推迟工作的交付,传达你当前的优先事项列表,让利益相关者知道一旦事情稳定下来,他们应该在一两周内与你跟进。关键是永远不要直截了当地说不,而是传达你的优先事项列表,以帮助利益相关者理解此时你回答他们的问题可能会有困难。

从长远来看,这类问题可能会暴露出创建自助服务选项的需求。一个好的经验法则是,每当你被要求三次更新分析,或者提取数据来回答类似的问题时,你应该探索一种仪表板或自动化的解决方案。

原艾森豪威尔矩阵

所以下次你在邮件中收到请求时,考虑一下它属于四个象限中的哪一个。这样做之后,您就可以采取相应的措施了。你不可避免地会犯一些错误,但如果你只是做一名订单接受者,试图让所有的利益相关者都满意,那么你作为一名数据科学家的影响力就会减弱。

Python 中的优先级队列

原文:https://towardsdatascience.com/priority-queues-in-python-3baf0bac2097?source=collection_archive---------12-----------------------

优先级队列的堆实现

来源

优先级队列是一种类似于普通队列或堆栈的数据结构,但是每个元素都有一个相关的优先级。具有高优先级的元素在较低优先级的元素之前被服务。优先级队列通常使用堆数据结构来实现。

在本帖中,我们将讨论使用堆数据结构在 python 中实现优先级队列。

我们开始吧!

在构建‘priority queue’类之前,有必要熟悉一下 python‘heapq’模块。首先,让我们导入“heapq”模块:

import heapq

假设我们有一个 IBM 的历史价格列表:

ibm_prices = [108.68, 109.65, 121.01, 122.78, 120.16]

如果我们想得到 T2 的最低或最高价格,我们可以使用。nsmallest()'和'。nlargest()”方法。要获得三个最低价格,我们可以做以下事情:

print(heapq.nsmallest(3, ibm_prices))

对于三个最高的价格:

print(heapq.nlargest(3, ibm_prices))

让事情变得更有趣一点,假设我们有一个科技公司股票的投资组合:

portfolio = [
       {'name': 'IBM', 'shares': 200, 'price': 108.68},
       {'name': 'AAPL', 'shares': 75, 'price': 277.97},
       {'name': 'FB', 'shares': 40, 'price': 170.28},
       {'name': 'HPQ', 'shares':125, 'price': 17.18},
       {'name': 'UBER', 'shares': 50, 'price': 22.60},
       {'name': 'TWTR', 'shares': 95, 'price': 29.29}
]

我们可以使用。nsmallest()'和'。nlargest()'来分别拉最便宜和最贵的股票:

cheap_stocks = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])
expensive_stocks = heapq.nlargest(3, portfolio, key=lambda s: s['price'])

让我们打印结果:

print("Cheap Stocks: ", cheap_stocks)
print("Expensive Stocks: ", expensive_stocks)

这些函数提供了卓越的性能,尤其是当 N 元素(最大或最小)的大小与整个集合相比很小时。

现在我们可以构建我们的优先级队列类了。让我们使用“heapq”模块创建一个优先级队列类。首先,我们创建初始化方法:

class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0

让我们定义一个方法来检查队列是否为空:

class PriorityQueue:
    ...
    def is_empty(self):
        return not self._queue

接下来,让我们定义一个方法,允许我们将对象推入我们的优先级队列。我们采用“heappush”方法,该方法将获取优先级和项目值:

class PriorityQueue:
    ...
    def push(self, item, priority):
        heapq.heappush(self._queue, (priority, self._index, item))
        self._index += 1

最后,我们将添加一个方法,让我们使用“heappop”方法从优先级队列中删除元素:

class PriorityQueue:
    ...
    def pop(self):
        return heapq.heappop(self._queue)[-1]

接下来让我们定义一个名为 Stock 的类,我们将用它来演示优先级队列类的用法。该类将有一个“init”方法,让我们初始化股票价格、股份和报价器的值:

class Stock:
    def __init__(self, stock_ticker, stock_price, stock_share):
        self.stock_ticker = stock_ticker
        self.stock_price = stock_price
        self.stock_share = stock_share

我们还可以定义一个方法,允许我们打印类属性的表示:

class Stock:
    ...
    def __repr__(self):
        return 'Stock({}, {}, {})'.format(self.stock_ticker ,   self.stock_price,  self.stock_share)

现在我们准备初始化我们的优先级队列并添加项目:

q = PriorityQueue()

让我们将初始投资组合中的股票属性添加到优先级队列中。我们将优先考虑便宜的股票:

q.push(Stock('IBM', 108.68, 200), 4)
q.push(Stock('HPQ', 17.18, 125), 1)
q.push(Stock('TWTR', 29.29, 95), 3)
q.push(Stock('UBER', 22.6, 50), 2)
q.push(Stock('AAPL', 277.97, 75), 6)
q.push(Stock('FB', 170.28, 40), 5)

现在让我们打印优先级队列中的项目:

while not q.is_empty():
    print(q.pop())

我将在这里停下来,但是您可以随意使用优先级队列的堆实现。此外,您可以尝试使用普通列表或链表来构建优先级队列。您可以在这里找到 python 中其他优先级队列实现的一些例子。我希望你觉得这篇文章有用/有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

隐私图标和法律设计

原文:https://towardsdatascience.com/privacy-icons-4ca999a6f2db?source=collection_archive---------41-----------------------

数据生态系统正迅速向以用户为中心的模式转变。哪些因素会影响人们对个人数据价值的认知?

在 2020 年全球开发者大会期间,苹果花时间讨论了当今最热门的话题之一——隐私。在过去的几年里,苹果一直在推出各种公共活动,旨在将自己定位为一家尊重客户隐私的公司。今年的 WWDC 在苹果产品的隐私相关功能方面有一些引人注目的问题。

“苹果公司成立时,主张是,‘这是个人电脑。这是你自己的数据。…随着世界的发展,[我们]一直认为…您创建的数据,您用计算机做的事情,都是您的,应该在您的控制之下。您应该知道您的数据发生了什么。”—苹果公司的克雷格·费德里吉

首先,苹果重申了其立场,即隐私是一项基本人权,并从一开始就试图将用户隐私考虑纳入产品设计过程。此外,苹果公司的隐私有以下四个要素:

  • 数据最小化:苹果旨在确保苹果和其他任何人(即 app 开发者)能够接触到个人的最小量的个人数据;
  • On-device intelligence: 苹果旨在通过在用户设备上处理尽可能多的信息(而不是将其发送到中央服务器)来避免用户数据收集;
  • 安全性:苹果正在确保个人所做的一切都是安全的;
  • 透明和控制:苹果旨在帮助其用户更好地了解正在收集的数据,以便用户可以就如何使用这些数据做出自己的选择。

保利乌斯·尤尔西斯

除此之外,苹果还宣布了一些新的隐私功能,这些功能与未来几个月将推出的应用程序密切相关。

  1. 追踪。苹果让第三方应用更难追踪其用户。在其下一个移动操作系统 iOS 14(将于 2020 年秋季推出)中,苹果将要求所谓的第三方应用程序在开始跟踪之前要求获得用户许可。与 Safari 浏览器类似,应用程序用户将能够选择是否要分享他们的精确或大致位置。
  2. 隐私自报。苹果将开始要求应用程序开发者自我报告这些应用程序访问和利用应用程序用户个人数据的方式。例如,应用程序开发者必须向苹果披露他们是否只收集了“一点点”用户数据,以及这些数据是与谁共享的。
  3. 隐私图标。苹果旨在简化用户体验,帮助用户更容易、更快速地识别他们决定从 App Store 下载的每个应用的隐私设置。为了实现这一目标,该应用将在应用商店的应用描述中使用隐私图标。目前,在 App store 上发布的应用程序需要有自己的隐私政策。然而,众所周知,没有人会在下载之前或之后去阅读那些隐私政策。
  4. 透明和控制。为了便于更好地了解应用程序如何使用用户数据,隐私图标将显示在应用程序描述页面上。这些隐私图标将显示该应用程序能够访问哪些个人数据,以及它是否会跟踪你。大概是这样的:

截至 2021 年 9 月的 Facebook Messenger 应用隐私图标。

这种隐私相关的更新对苹果设备的用户来说绝对是有价值的改进。苹果团队努力让个人对自己的数据拥有更多控制权,这值得称赞。不言而喻,这将有助于更好的数据素养和更深入地了解第三方是如何使用个人数据的。与此同时,苹果公司的这一声明应该放在一个更广泛的背景下看待,即直接与客户在线互动的公司受到越来越严格的数据隐私法规的压力(GDPR 和 CCPA)。

隐私图标:回到未来

苹果建议使用图标来告知隐私问题,这既不是创新也不是新鲜事。Mozilla 率先向个人披露了互联网隐私设置。2011 年,Mozilla 提出了图标的“测试”版本,可以告知个人在线服务提供商如何使用他们的数据。

Mozilla 隐私图标的测试版解决了数据隐私的四个主要方面:

  • 保留期:公司将个人数据保留多长时间?
  • 第三方使用:个人数据仅用于预期目的,还是也用于其他目的(例如,数据是否与第三方共享,以及用于何种目的)?
  • 广告网络:个人数据是否与营销或广告公司共享。
  • 执法:公司是否向执法机构披露数据(有无搜查令)。

Mozilla wiki 。

Mozilla 隐私图标的第二次迭代

Mozilla 隐私图标的第二次迭代也是在 2011 年发布的。第二个版本是为了简化隐私政策与各种应用程序用户的沟通而准备的。图标的第二次迭代有点像门捷列夫的周期表,因为它们主要包含字母:

Mozilla 维基百科。

仔细观察 Mozilla 隐私图标的这个替代版本,可以发现一些事情。首先,关于个人数据的使用,可能会显示更多类别的信息。例如,第二次迭代区分个人和非个人信息以及更多的使用目的(例如,用于广告、地理定位、与第三方共享以及数据保留期限)。其次,该选项选择使用字母和符号来传达隐私政策。

这两种方法都为隐私图标的讨论奠定了基础。快进十年。虽然已经取得了一些进展,但是在如何向个人消费者传达隐私政策方面还没有达成共识。

《加州消费者隐私法》和《GDPR》对公司如何与消费者沟通提出了许多要求。他们要求每次公司的数据收集和处理实践发生变化时都必须发送通知。这些隐私相关的通知和获得消费者同意的要求导致点击疲劳,并导致用户完全忽略通知和警告。

另一个更近的尝试是:

达比斯。

有哪些食品标签可以教会我们隐私图标?

从历史上看,隐私图标的概念可以追溯到几十年前,当时各国政府开始要求食品制造商向消费者披露他们购买的食品中的成分。在 WWDC 的演示中,苹果首席软件专家 Craig Federighi 将食品标签和隐私图标的使用进行了对比,以解释应用程序将使用哪些用户数据。

食品标签的效率和有效性在社会科学学者中引起了广泛的讨论:消费者是否从这种标签中受益?食品标签证明了它们的成本吗?食品标签中提供的信息真的能影响消费者的行为吗?

在下面的段落中,让我们试着比较一下食品标签和隐私图标,看看它们之间有什么相似之处。

(a)隐私图标作为自下而上的解决方案

首先,食品标签和隐私图标之间最显著的区别与它们的起源有关。食品标签通常是由政府强加的,政府试图缓解信息不对称,帮助个人对他们消费的食品做出更好的选择。然而,负责创建标签的政府官员面临许多问题。也就是说,预测人们对食品标签的反应可能极其困难。此外,即使可以确定对人类行为的影响,也可能很难显示要求使用食品标签的法规的实际利益(以货币计算)。

这个问题在隐私图标领域似乎并不存在,因为,至少到目前为止,还没有使用“隐私标签”的明确监管义务。相反,我们可以看到这种创建隐私图标的举措是“自下而上的”:为客户提供服务的公司(如苹果公司)正在率先推出隐私图标,旨在帮助个人消费者更好地了解他们的个人数据。

市场参与者正在开发隐私图标,这一事实相当引人注目。

(b)隐私图标具有明显的经济价值

其次,引入新的监管要求,至少在美国,必须有经济上的合理性。在实践中,这意味着制定法律的政府机构必须表明,新措施创造的社会效益将大于实施该措施的成本。

就私隐权图标而言,政府无需进行任何经济影响评估研究;这是那些押注于隐私图标的公司所为。就苹果而言,推出隐私图标这一事实表明,苹果认为向用户提供个人数据透明度是有价值的。

(c)人们获取信息的四种可能方式

假设人们愿意接受信息,并且信息会给消费者带来好处,这是非常自然的。然而,最近在食品标签领域的学术研究表明,人们对提供给他们的信息有四种可能的反应方式:

  • 有大量的信息是人们不愿意接收的(因此,看不出有什么价值);
  • 有大量的信息是人们希望而不是接收的(因此视其为负值);
  • 在某些情况下,人们不想知道;
  • 在其他情况下,人们希望而不是知道。

这种“信息回避”的现象提出了一个问题:设置隐私图标到底有没有意义。

(d)决策效用与经验效用

此外,众所周知,消费者不仅受到信息匮乏的困扰,还受到各种行为偏见的困扰。例如,消费者可能会遭受当前偏见(即,人们倾向于高估眼前的回报,而不重视长期后果)或可能不切实际地乐观(即,认为个人自己不太可能经历负面事件)。

当我们看隐私图标时,还有两个行为偏差可能会变得很明显:(a)人们即将同意某个隐私相关选择时的效用(所谓的“决策效用”)和(b)实际体验的效用(所谓的“体验效用”)之间存在明显的差距。隐私图标的问题是,它可能不总是能够在未来提供具体和清晰的体验感。

隐私图标和走向以用户为中心的数据生态系统

快速发展的新技术,如机器学习、边缘计算和差分隐私,以及新的数据隐私法规(主要是 GDPR 和 CCPA),正在为以用户为中心的数据生态系统铺平道路。

以用户为中心的数据生态系统的构建前提是,个人能够集中来自各种不同来源的个人数据,并将这些数据保存在他们的个人数据云中。这些数据云完全由用户控制,用户可以根据什么条件访问这些数据。

隐私图标将在以用户为中心的数据环境中扮演越来越重要的角色。然而,这不是一家公司可以完成的任务。虽然苹果可以被视为趋势的引领者,但提高来自不同文化和不同大陆的人们的数据素养是一项可以由多个利益相关者共同行动来完成的任务。

保利乌斯·尤尔西斯

在创建用户友好的数据隐私图标和通知时,有四个主要考虑因素起着同等重要的作用:

  • 用户体验必须使个人用户能够快速浏览他们正在使用的应用程序和技术的主要功能,并能够了解哪些个人数据处于危险之中,以及这些数据是如何使用的;
  • 用户体验与软件工具密切相关。这两者必须平衡,并且需要 UX/UI 设计师和软件工程师之间的密切合作;
  • 隐私图标和通知等数据扫盲增强工具也应符合法律要求(例如,获得合法有效的同意);和
  • 创建隐私图标和其他数据素养增强解决方案时,应牢记行为和决策模式(例如,考虑选择加入和选择退出默认设置的影响)。

在 Prifina ,我们看到利用图标等工具来简化界面,通过它我们变得精通数据并理解我们的选择。我们相信这可以让消费者变得更有能力,我们可以和开发者一起构建应用和体验,用他们的数据提升个人。

此外,数据隐私图标可能会成为一个强大的工具,特别是如果 UX/UI 设计师、软件工程师、律师和消费者权益倡导者共同努力简化用户体验和用户界面的话。

如果你有一个想和我们社区一起开发的图标的想法,请联系我们。如果你有兴趣自己开发,你可以注册我们的开发者账户,然后开始。

与我们保持联系

Prifina 帮助个人从他们的个人数据中获得定制价值,并为开发者提供工具,在用户持有的数据基础上构建应用程序。

你可以在 Twitter 、 LinkedIn 、脸书关注普里菲娜,加入我们的 Slack:Liberty。平等。数据。

大数据中的隐私平凡化

原文:https://towardsdatascience.com/privacy-trivialization-accbcdbc163b?source=collection_archive---------61-----------------------

Zoom 是如何揭示一个更大的技术问题的

连浩曲在 Unsplash 上拍照

上周,我写了我们对死亡的恐惧,现在更具体地说是对新冠肺炎的恐惧,是如何被操纵来让我们相信我们的隐私是可以牺牲的和微不足道的。在前几周,我已经讨论了关于医疗数据和 GDPR 的伦理数据使用。在所有这些文章中,一个共同的主题是,总有人认为维护我们的隐私权将阻碍进步,在医疗数据的情况下,或者从互联网的集体体验中转移,在人们声称 GDPR 正在导致互联网的巴尔干化的情况下。

这些声音所做的是淡化隐私。他们声称,隐私是一个微不足道的问题,至少与其他利害攸关的问题相比是如此,比如医学科学的进步或任何基于数据的研究。通过这种方式来定义隐私,这个想法是,一个人将开始不重视他们的隐私,并且对于放弃隐私更加自满。反过来,这意味着那些建筑技术人员将花更少的时间关注维护用户隐私和保护用户数据,因为没有人会在乎他们是否会这样做。消费者不重视数据安全,因为他们被告知不要重视数据安全,或者期待数据安全是不现实的,这意味着为消费者制造产品的人也没有重视数据安全的动机,即使这些人正是应该关心用户安全的人,即使用户并不关心。

这种情况已经发生多年,其影响是显而易见的。有很多数据泄露,甚至更多的情况是用户没有意识到他们的数据的哪些部分是完全可以被公众访问的(同样,这些新冠肺炎地图制作者没有分享他们从哪里获得的用户数据可能是有原因的)。Zoom 是隐私平凡化及其后果的最新、最显著的例子之一。

不,不是 PBS 的那个(图片来自r/怀旧

在隔离的这个阶段,我认为大多数人至少使用过一次 Zoom 进行某种视频通话。如果人们不是用它来和朋友交谈,他们会用它来上课、举行商务会议,甚至是论文答辩。由于我们都被困在家里,它被使用得更多了,这意味着它突出的隐私问题已经占据了中心舞台。已经发生的一个大现象是 zoombombing ,有人会闯入一个 zoom 会议,做一些事情,包括大喊种族诽谤或暴露自己给会议中的人(在这种情况下是一群学生)。安全性的缺乏也没有随着 zoombombing 而停止。正如这篇 NPR 的文章所指出的:

曾在美国国家安全局(National Security Agency)工作的安全研究员帕特里克·沃德尔(Patrick Wardle)说,“你只是想在聊天和视频应用程序中拥有的东西——强大的加密、强大的隐私控制和强大的安全性——似乎完全缺失了。”。

他和其他研究人员发现了 Zoom 软件中的缺陷,这些缺陷可能会让黑客通过计算机的网络摄像头或麦克风进行间谍活动。Zoom 表示,它在周三发布了这些问题的修复程序。

Zoom 的问题已经变得如此糟糕,以至于联邦调查局发布了关于 Zoom 的警告,纽约市学校系统的教育工作者被告知不要再使用 Zoom。作为对这些问题的回应,或许更多的是,作为对公众对这些问题的愤怒的回应,Zoom 的首席执行官写了这条消息道歉,并描述了他和他的公司计划采取的措施,以解决用户隐私问题。我认为有一句话很能说明这款应用的发展,以及这款应用的创建文化:

首先,一些背景:我们的平台主要是为企业客户——拥有全面 IT 支持的大型机构而构建的。

对我来说,这听起来很像“用户应该关心并确保应用程序的安全性(通过一个专门的 IT 部门),所以我们创作者不必担心提供它。”这一点,在我看来,在上面链接的 NPR 文章中引用的前美国国家安全局特工帕特里克·沃德尔的话中得到证实:

该产品旨在优先考虑隐私和安全之外的事情

当 Zoom 声称为会议提供端到端加密时,我们再次看到了这种琐碎化,而事实上它并没有。正如 Oded Gal 在博客帖子中所写的:

虽然我们从未打算欺骗我们的任何客户,但我们认识到普遍接受的端到端加密定义与我们使用它的方式之间存在差异

因此,虽然有人从未“有意”欺骗,但他们使用了一个常用短语来描述他们实际上并没有的特征,你知道,就像谎言一样。哦,不好意思,一个“差异”

在我上周写的文章的结论中,我说:

我们对死亡的恐惧已经被操纵来损害我们的隐私权,现在我们的恐惧加剧了,这种操纵只会增加。这就是为什么我们需要对这些私营公司的要求以及他们为保护我们自己的权利而采取或不采取的措施提出更多的批评,因为很明显,如果不被强迫,他们无意保护我们的权利。

我想在这里强调的一点是,公司只有在我们迫使他们这样做时,才会以我们的最佳利益为重。Zoom 现在才开始关注安全性,因为每个人都对此感到非常愤怒。他们以前可以专注于它,但相反,我们现在(谢天谢地)有一个废弃的注意力跟踪器和改变背景的能力。公司不关心人,他们关心客户。事情就是这样。他们是资本主义社会的企业。不管他们说多少次让世界变得更美好,他们所关心的只是他们的底线。因此,激励他们关心你的唯一方法是做一些影响底线的事情。在这种情况下,提出一个关于安全问题的问题显然已经让 Zoom 的业务付出了代价,所以现在他们正在解决这个问题。事实是,Zoom 只是一种更大的技术文化的产物,这种文化轻视隐私,只关心通过酷的闪亮功能(如改变背景)吸引客户。再说一次,因为这是使用资本主义社会创造的产品的一个更大的症状,没有简单的解决办法,所以我要说的是:

永远不要假设一家公司关心你的利益,除非你给他们一个理由。

Python 中的私有成员🤔

原文:https://towardsdatascience.com/private-members-in-python-217baf02a162?source=collection_archive---------33-----------------------

蒂姆·莫斯霍尔德在 Unsplash 上的照片

如果你有其他编程语言(Java、C#、C++、Kotlin)的经验,并且已经开始学习 python,你肯定会寻找私有成员来提供封装,因为这是面向对象编程的一个关键原则。每个人都这样做,直到熟悉了“python”的编码风格。

通过查看互联网上的一些资源,我发现了一些非常有趣的想法,这些想法很有见地,也很幽默。你一定要看看这个我最喜欢的链接。

Python 不会阻止您访问私有的和受保护的属性和方法,因为它们在默认情况下是公共的😎。所以,实现的决定留给了开发者。

受保护的

字段和方法前的单下划线(_)用于表示受保护的访问修饰符。

class User:
    def __init__(self, username, password):
        self._username = username  # i act like a protected but you can change me
        self._password = password  # i act like a protected but you can change me

    def _login(self):
        print('i am like a protected method but you can access me')

私人

字段和方法前的双下划线(__)用于指示私有访问修饰符。

class User:
    def __init__(self, username, password):
        self.__username = username  # i act like a private but you can change me
        self.__password = password  # i act like a private but you can change me

    def __login(self):
        print('i am like a private method but you can access me')

访问私有修改器

class Doctor:
    def __init__(self,
                 name,
                 address,
                 specialities,
                 schedule,
                 degree):
        self.name = name
        self.address = address
        self.specialities = specialities
        self.schedule = schedule
        self.__degree = degree

    def __diagnose_patient(self):
        print(F'diagnosed patient bob by doctor {self.name}')

if __name__ == '__main__':
    doctor = Doctor('Dr. Bob', 'KTM', 'OPD', 'SUN: 7-8', 'MBBS')
    doctor._Doctor__diagnose_patient()

在上面的代码片段中可以看到,私有方法

def __diagnose_patient(self): # convention class name + method name

可以通过以下方式访问

doctor._Doctor__diagnose_patient()

只是约定俗成,虽然这些都可以访问。这是向其他开发者传达信息的一种清晰的方式。不要在不清楚它的确切作用的情况下使用它

参考文献

  • https://radek . io/2011/07/21/private-protected-and-public-in-python/
  • https://stack overflow . com/questions/2064202/private-members-in-python
  • https://mail . python . org/piper mail/tutor/2003-10 月/025932.html

Python 中的私有“受保护”属性——一劳永逸地去神秘化

原文:https://towardsdatascience.com/private-protected-attributes-in-python-demystified-once-and-for-all-9456d4e56414?source=collection_archive---------16-----------------------

照片由clément Hun splash

所有关于私有和“受保护”属性的知识都在 748 个单词中

永远不要使用两个前导下划线。这是令人讨厌的隐私。—伊恩·比金,pip、virtualenv 和许多其他软件的创作者

H 这些词你在 Python 的世界里遇到过多少次:公有私有受保护?有多少次,那些一个前导下划线_,两个前导下划线__让你困惑,试图理解它们?****

好吧,让我们一劳永逸地揭开它们的神秘面纱。私有和“受保护”的属性有什么用。以及它们在 Python 世界中的样子。

私有属性到底有什么意义?

考虑这个场景:你有一个名为Vehicle的类,它在内部使用一个名为 horn 的实例属性,并且不想公开它。现在,你想要子类化Vehicle并将你自己的类命名为MyCar.**

如果您在类MyCar中创建自己的horn实例属性,您将覆盖Vehiclehorn 实例属性。结果是,你将粉碎Vehicle类中所有使用horn 属性的方法。更糟糕的是,调试随之而来的问题将是一件令人头疼的事情。

为了防止这种情况发生,Vehicle类的开发人员会将horn属性设为私有属性,以防止这种意外事故。**

Python 中的私有属性

在 Python 的世界里,不像 Java,没有办法创建一个私有的修饰符。python 给你的是一个简单的机制,防止意外覆盖你的类中的属性,如果有人想从你的类继承。****

在前面的例子中,如果您想将horn属性设为 private,您需要在它前面加上两个下划线:__horn 这样,Python 将把这个属性名存储在实例__dict__中,以下划线和类名为前缀。这样,在Vehicle类中,你的__horn 属性就变成了_vehicle__horn *MyCar* 类中就变成了_MyCar__horn。python 的这个特性被冠以一个微妙的名字 名为 mangling 。下面是我们目前讨论的代码:**

示例 01 —私有属性,其中名称被篡改****

这里需要注意的是,名称篡改完全是关于 安全而不是安全。它不会保护你免受故意的错误行为;只是,偶然的超越。在上面的例子中,您可以简单地通过这样做来改变私有属性的值:v1._vehicle__horn = 'new value'****

Python 中的“受保护”属性

无论是名字的乱涂乱画,还是把名字写成self.__horn 的歪歪扭扭的样子,都不为皮达尼斯所喜爱。在公共存储库中,您会注意到开发人员通常更喜欢遵循这样的惯例:只给添加一个前导下划线(self._horn),以防止它们被无意中修改。****

批评者建议,为了防止属性混乱,只需简单地遵循在属性前加一个下划线的惯例就足够了。这是我在文章开头引用的伊恩·比金的话全文;

永远不要使用两个前导下划线。这是令人讨厌的隐私。如果担心名称冲突,请使用显式名称混淆(例如 _MyThing_balabla)。这和双下划线本质上是一样的,只是在双下划线模糊的地方是透明的。

我必须注意,带有单个前导下划线_的属性对于 python 解释器来说没有任何特殊意义。但是,这是皮托尼斯塔世界里的一个很强的惯例。如果您看到一个,这意味着您不应该从类外部访问这样的属性。您甚至可以观察到,甚至在官方 Python 文档的某些角落中,带有单个前导下划线_的属性也被称为“受保护的”

尽管使用单个前导下划线来“保护”属性的做法很常见,但很少听到它们被称为“受保护的”属性。有些人甚至称之为“私人”

总而言之

将属性设为私有的主要目的是防止子类意外覆盖该属性。在 python 中,使变量私有的官方方法是添加两个下划线,例如self.__privateattr.,但是,在 python 社区中,当使变量私有时,强烈倾向于只添加一个前导下划线。您可能经常听到或看到这样的属性被称为“受保护的”

因此,只需知道在 python 中将变量设为私有是为了安全,只需添加一个前导下划线就足以保护它们不被无意中覆盖:例如self._protected

如果你喜欢我的文章并想阅读更多,考虑注册成为一名媒体会员。每月 5 美元,你可以无限制地阅读媒体上的故事。通过使用下面的链接,你也将支持我作为一个作家。

******** [## 通过我的推荐链接加入 Medium-Amir AFI anian

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

7sapien.medium.com](https://7sapien.medium.com/membership)********

在 Colab 环境中下载自定义数据集的提示

原文:https://towardsdatascience.com/pro-tip-for-downloading-custom-datasets-in-colab-environment-5413896d14ec?source=collection_archive---------39-----------------------

萨姆·丹·张在 Unsplash 上的照片

通常,当数据科学家需要使用他们的自定义数据集进行深度学习或任何推理时,他们需要将数据下载到他们的环境中。这对任何使用 Colab 的人来说都特别有用。我基本上使用 Colab 来完成我的深度学习任务,因为我没有硬件来支持我的计算。

我想快速分享我是如何在 google Colab 环境中为我们工作和使用数据集的。事实上,这个过程应该是非常简单的,但是有时候,我们很难做到。实际上我花了一段时间才弄明白。因此,我写这篇文章的原因是。

实际上有几个选项可供选择。

  1. 把你的数据推送到 Github,克隆到 google。我个人不喜欢这样。此外,你仍然需要做一些调整,尤其是如果你有一个非常大的数据集,因为 GitHub 不会直接支持你推这些数据集(图像)
  2. 另一种选择是手动上传到 Colab。这本来很好,但上传时间太长。因此,如果你需要节省时间,我既不使用它也不建议它。
  3. 将您的数据上传到 google drive,并将文件夹安装到您的环境中。这也是一个很好的选择,除了第三方不能使用您的笔记本电脑,因为在安装过程中需要驱动器认证。
  4. 第四种选择是上传压缩版本的数据,不管有多少。在这种情况下,数据也可以是预训练的模型或任何其他形式的数据集(通常是图像)。在接下来的文章中,我会专注于此

怎么会?

Colab 以不同的方式处理大数据集和小数据集。在这种情况下,大型数据集通常是 100mb 以上的任何数据,小型数据集通常是 100mb 以下的数据。

基本步骤是:

  1. 在本地计算机上压缩文件,然后上传到 google drive
  2. 右键单击 zip 文件或文件夹(如果没有压缩),然后选择获取可共享链接
  3. 通过将链接的权限更改为任何人来公开:如果不公开,文件将不会被下载到 Colab。我在第一次尝试中错过了这一步。

4.您现在可以复制链接并提取 d 和视图之间的字母数字。这只是您需要的文件 ID。

比如这个链接:https://drive . Google . com/file/d/1 tjpao 4 hjqe 97 b 6 xddy 9 ZD 5 i5 xmu _ 2RJ/view?usp =共享,

1tjpao 4 hjqe 97 b 6 xddy 9 z D5 I 05 xmu _ 2RJ是文件 id

5.对于小型数据集,复制下面的命令并粘贴到您的 Colab 笔记本中。导入 Ipython display clear output 方法来清除下载的输出。显示的输出有时会很大,这会占用不必要的屏幕空间。

下载文件

下载小文件

对于大文件,请复制下面的命令。注意,有两个位置会替换文件 ID

下载大文件

提取文件

如果下载的文件是压缩的,您需要执行以下步骤。检查您合适的文件类型(zip、7z、tar)并复制合适的代码或命令来提取它们以供使用。对于 zip 文件,您只需将 zipfile 作为一个类导入并完成工作。对于其他文件类型,需要安装一个 p7zip

一旦你完成了这些,你就可以开始你的机器学习任务了。获取数据是第一步,也是最基本的一步。

使用上面的过程,你可以在 Colab 中使用你的文件。唯一的缺点是,每次重启运行时,你都需要下载。

希望这能帮助到某个人。干杯。

概率线性判别分析(PLDA)解释

原文:https://towardsdatascience.com/probabilistic-linear-discriminant-analysis-plda-explained-253b5effb96?source=collection_archive---------6-----------------------

入门

来源:图片由作者提供。具有不同平均值(中心)的高斯分布(椭圆)的等高线用不同的颜色表示。每个轮廓对应于不同类别。

简化的方式讲解概率线性判别分析(PLDA)** 的**概念和应用。

介绍

顾名思义,概率线性判别分析线性判别分析概率版本,能够处理更复杂的数据。尽管 PLDA 在包括计算机视觉、语音处理、自然语言处理(NLP)在内的许多研究领域有着广泛的应用,但它仍然没有以一种能够达到广泛受众的方式进行解释。PLDA 已被用于识别、验证、生成用于聚类的相似性分数、特定于类别的特征提取。

我这里的目的讨论介绍和应用了 PLDA** 的研究论文**。我将使用等式、图表和易于实现的代码来解释这些概念,以便所有数据科学领域的人都可以理解。

这里介绍的推导需要有基本概率线性代数的先验知识。可以参考参考文献中提到的来源。

为什么是 PLDA?

在我继续之前,我想给出使用 PLDA 而不是 LDA 的动机。

LDA 是一种监督降维技术。LDA 将数据投影到较低维度的子空间,使得在投影的子空间中,与每个类内的分布(最小化类内协方差 Sw )相比,属于不同类的点更加分散(最大化类间协方差 Sb )。下图展示了这一点。

来源:毕晓普著*模式识别与机器学习 。每种颜色代表一个阶层。m1 和 m2 分别是类别 1 和类别 2 平均值。左图显示了 m1 和 m2 连线上的数据投影。两个类别的样本有很多重叠。右图显示了使用 LDA 的数据投影,从而最大限度地减少了两个类别之间的重叠*

当我们有来自所见类的数据时,这对于分类很有用。但是,当观察到的数据来自看不见的类时,我们如何执行类似的任务呢?例如,考虑人脸识别的任务,我们使用不同的人脸图像训练模型,使得每个唯一的人脸代表一个类别。

现在给定两个图像,我们想要找出它们是否属于同一个人,即使模型以前没有见过那个人的任何图像。常见的方法是将两幅图像投影到低维空间,并找出它们之间的距离。如果距离很小,这意味着他们来自同一个班级。LDA 会将图像投影到从训练数据获得的子空间中,因此不是最佳的。因此,我们需要一个更灵活的模型来寻找投影的最佳方向。解决这个问题的一种方法是使用概率方法,而不像 LDA 是确定性的。它被称为概率 LDA。

PLDA 的优势

  • 我们可以使用连续的非线性函数来生成类中心,即使是从看不见的类的单个例子中。
  • 在假设检验中,我们可以比较以前从未见过的类中的两个例子,以确定它们是否属于同一类。
  • 对来自未知类别的样本执行聚类

什么是概率 LDA?

x={x₁,x₂,…,xₙ}D 维观测值或数据样本。概率 LDA 或 PLDA 是一个生成模型,它假设给定的数据样本是从分布中生成的。我们需要找到最能描述训练数据的模型参数。假设产生数据的分布的选择基于两个因素:(1)它应该代表不同类型的数据(2)参数的计算简单而快速。满足这些条件的最流行的分布是高斯分布。下图显示了高斯分布的概率分布函数(pdf)、等高线以及从中生成的样本。

来源:作者的情节

[**show code**](https://gist.github.com/prachiisc/a5f193212f90c8f82e84b5fe9dcf85d4)

为了将数据聚类成类,我们需要用单独的高斯分布来表示每个类,因此我们可以使用高斯混合模型(GMM)。GMM 是高斯的加权混合,每个高斯具有不同的均值和协方差,其中每个混合可以代表每个类别。

GMM 的概率分布函数(pdf)为:

来源:作者的情节。具有 πₖ、μₖ、φₖ的 GMM 的 pdf 为 k- 次高斯的权重、均值和协方差

[**show code**](https://gist.github.com/prachiisc/4668febcef55f6d857863ca9ffd920bd)

y 为潜在(隐藏)类变量代表 GMM 某类/混合的意思。现在给定这个类变量y,产生数据样本**x的概率为:******

其中φw 表示给定类的类内协方差。这表明,一旦我们知道了高斯的类参数,我们就可以生成这个类的样本。这里**类变量y本身假设是从单独分布中产生的。从假定的分布中产生代表一个类别的特定实例 y 的概率被称为先验概率。**

LDA 也被建模为 GMM,其中每个混合的高斯均值是属于各自类别的训练数据的样本均值,并且 y 的先验概率是离散的,其中 y 只能取离散值,给出如下

这将产生上面讨论的 GMM。最大化该模型关于参数的可能性{ πₖ,μₖ,φw }恢复标准 LDA 投影。但是,为了处理在训练期间没有看到的类,我们需要修改 prior 并使其连续,其中 y 可以取从给定的分布中生成的任何实数值

这表明,每个类别的潜在变量 y 可以使用高斯分布生成,具有**均值m类别间协方差φb .,因此它被称为概率 LDA。使用下图可以更好地解释这一点:**

来源:图片由作者提供。小椭圆代表每个类别的高斯分布等值线,平均值位于中心。数据点由十字标记表示。灰色椭圆根据高斯分布生成每一类的平均值。

来源:人物图片来自 LFW 数据集,由作者代表。情节是为了说明。

样本 y 1 和 y 2 由高斯分布 eq (2)生成,代表人物身份。我们对每个类(人)的示例 x 1 和 x 2 进行采样,用等式(1)以 y 1 和 y 2 为均值来表示人的不同取向。

潜在空间

PLDA的目标是将数据样本投影到潜在空间中,使得来自同一类的样本使用相同的分布建模。这些预测用潜在变量*表示,这将在本节中讨论。*

如前所述,isφb是类间协方差半正定矩阵而φw 是类内协方差正定矩阵。我们得到一个变换矩阵 V,它将φw 和φb 同时转换成对角矩阵,给出如下:

其中 I 是单位矩阵,ψ对角矩阵。因此,我们对数据样本的每个维度去相关。现在 PLDA 模型的参数是{ m ,A,ψ}。

你可以参考下面的推导来得到上面的方程。它需要了解线性代数概念,如矩阵的 特征值和特征向量特征值分解

[**show derivation**](http://leap.ee.iisc.ac.in/prachi/medium/Eigen_value_derivation.pdf)

u,v 是潜在空间中的高斯随机变量定义为,

我们可以发现数据样本* x类变量 y 与这些潜在变量之间的关系如下:***

因此 u 表示的实例,而 v 表示类变量投影空间中。等式(5)和等式(6)中的关系以流程图的形式表示,如下所示:**

来源:图片由作者提供。PLDA 在变量独立的潜在空间中对分类中心 v 和示例 u1、u2 进行建模。原始特征空间中的示例 x1、x2 通过可逆变换 A 与其潜在表示 u 相关联

有兴趣的可以参考下面的推导:

应用程序

PLDA 允许对训练中没有出现的课程进行推断。一个例子是说话人识别。模型参数从训练数据中学习,但是模型应该处理来自训练期间不在场的说话者的例子。这里讨论了可以使用 PLDA 的一些任务。

分类:

我们有一组示例 xg∈(x,x,…,x* M 每个 M 类一个。现在给出一个探针例子 x p,任务是找到它属于哪个类。这是通过最大化可能性来确定的。首先,使用等式(6)将示例投影到潜在空间中*****

当 u 的协方差为 I 时,对数据进行去相关。P(uPug)给出来自与已知集合中的样本相同类别的探针样本的概率。****

因此,分配给探针示例的 C 类为

[**Computation of P(up|ug)**](http://leap.ee.iisc.ac.in/prachi/medium/computation_of_p.pdf)

类推断:

PLDA 的一个优点是,我们可以从类的单个例子中找到类变量 y 。对于示例 x,我们计算给定 x 的 y 的后验概率,表示为 p(y|x),这将再次是高斯分布。y 的估计是通过将 p(y|x)相对于 y 最大化得到的。无非是高斯 p 的均值(y|x)。可以这样写:****

假设检验:

给定两个来自未知类的例子( u 1, u 2),如果我们需要判断它们是否属于同一类,那么我们基于两个假设计算 似然比 R

聚类:

PLDA 也用于将示例分组。基于 对数似然比 R PLDA 分数 ,我们将每个例子与所有其他例子进行比较。这将创建一个 PLDA 得分矩阵,类似于一个相似性得分矩阵,可用于使用 k-means、凝聚聚类等可用算法执行聚类。

例子

****说话者二分化:基于说话者源将输入音频流分割成片段的任务。

该过程如下

  1. 将音频分成小段,每个小段只包含一个扬声器。
  2. 提取每个线段的特征
  3. 使用预先训练的 PLDA 计算 PLDA 分数矩阵
  4. 使用分数矩阵执行聚类

来源:图片由作者提供。扬声器双音化管道。

我使用语音识别工具包 Kaldi 完成第 1 步和第 2 步,并训练 PLDA 如下。

以下代码涉及:读取特征->应用主成分分析-> PLDA 潜在空间项目->计算 PLDA 得分矩阵。带有特性和预训练模型的完整代码可以在 GitHub 中找到。

[**show code**](https://gist.github.com/prachiisc/81f1d845b02ae1a7103580c74f260a4b)

分析

  1. PLDA 潜在表象(u): 下图显示了将数据投射到 PLDA 潜在空间的效果。我们可以看到,当我们将数据投影到 PLDA 潜像中时,它就变成了可分离的扬声器,即使 PLDA 模型从未见过来自这些扬声器的音频。

128 维特征的 2d 投影。左侧图是 PCA 转化的嵌入。左侧情节是 PLDA 潜在的表述。每种颜色代表一个扬声器。由作者策划。

[**show code**](https://gist.github.com/prachiisc/5ec4c485c62a1b07eee65745b9d4621f)

****2。对数似然比或 PLDA 得分矩阵:我们可以通过找到从音频中提取的所有 I 和 j 片段的 x x 之间的相似性得分 S(i,j)来计算相似性得分矩阵 s。下图显示了标准化余弦得分矩阵和 PLDA 得分矩阵,通过除以矩阵中的最高得分进行标准化。它描绘了在 PLDA 分数中的较高对比,显示了在对相同和不同说话者做出决定时的较高信心。浅色(黄色阴影)表示高分,而深色(蓝色阴影)表示低分。我们可以看到光块和色块,这有助于轻松识别同一扬声器和不同的扬声器区域。

余弦亲和度矩阵和 PLDA 亲和度矩阵的比较。由作者策划。

[**show code**](https://gist.github.com/prachiisc/3519554beccf61275495940890c674b5)

****3。直方图:下图显示了 PLDA 分数的分布。更高的计数出现在极端情况下,这有助于更好的聚类。

x 轴:标准化的 PLDA 分数,y 轴:计数。由作者策划。

[**show code**](https://gist.github.com/prachiisc/0c0875217f50781735b0c734d4e72824)

总结

  1. PLDA 是一个生成模型,其中我们假设一个类的数据样本 X 是从高斯分布生成的。高斯平均值代表类别变量 y 是从另一个被称为先验的高斯分布生成的。
  2. 对于识别的任务,我们可以通过比较来自相同类别的样本的可能性与来自不同类别的样本的可能性,使用 PLDA 分数来比较两个未知类别的样本。
  3. 我们可以使用整组样本中所有样本对之间的 PLDA 分数将样本聚类成类。

参考

  1. 约夫,谢尔盖。"概率线性判别分析."在欧洲计算机视觉会议 ,第 531–542 页。施普林格,柏林,海德堡,2006。
  2. 普林斯、西蒙·杰狄和詹姆斯·埃尔德。"概率线性鉴别分析对身份的推断"2007 年 IEEE 第 11 届计算机视觉国际会议,第 1–8 页。IEEE,2007 年。
  3. 毕晓普,克里斯托弗 M. 模式识别与机器学习 。斯普林格,2006 年。
  4. 杜达,杰瑞克。"高斯自动编码器。" arXiv 预印本 arXiv:1811.04751 ,2018
  5. 斯特朗吉尔伯特。线性代数入门。第五版。韦尔斯利-剑桥出版社,2016 年。国际标准书号:9780980232776

权重不确定的概率线性回归

原文:https://towardsdatascience.com/probabilistic-linear-regression-with-weight-uncertainty-a649de11f52b?source=collection_archive---------18-----------------------

用张量流概率实现贝叶斯线性回归预测汽车的 MPG

韦斯利·廷吉在 Unsplash 上拍摄的照片

线性回归可能是你在学习数据科学和机器学习时遇到的第一种统计方法。所以,我会抓住机会猜测这不是你第一次处理线性回归。因此,在本文中,我想讨论概率线性回归,而不是典型/确定性线性回归。

但是在此之前,让我们简单地讨论一下确定性线性回归的概念,让我们快速了解本文的主要观点。

线性回归是一种基本的统计方法,用于模拟一个或多个输入变量(或自变量)与一个或多个输出变量(或因变量)之间的线性关系。

上式中,a称为截距,b称为斜率。x是我们的自变量,y是我们的因变量,也就是我们试图预测的值。

需要使用梯度下降算法来优化ab的值。然后,我们得到一条回归线,显示自变量和因变量之间的最佳拟合。有了回归线,我们可以用任何给定的x输入来预测y的值。这些是典型或确定性线性回归算法通常是如何构建的步骤。

确定性线性回归方法中最佳拟合线的典型图

然而,这种确定性的线性回归算法并不能真正说明数据和模型的全部情况。这是为什么呢?

实际上,当我们进行线性回归分析时,会出现两种类型的不确定性:

  • 随机不确定性,即由数据产生的不确定性。
  • 认知不确定性,这是由回归模型产生的不确定性。

在我们阅读这篇文章的时候,我将详细阐述这些不确定性。为了考虑这些不确定性,应使用概率线性回归代替确定性线性回归。

在本文中,我们将讨论概率线性回归以及它与确定性线性回归的区别。我们将首先看到如何在 TensorFlow 中构建确定性线性回归,然后我们将继续构建具有 TensorFlow 概率的概率性线性回归模型。

首先,让我们从加载我们将在本文中使用的数据集开始。

加载和预处理数据

本文将使用的数据集是汽车的 MPG 数据集。像往常一样,我们可以用熊猫加载数据。

下面是数据的统计汇总。

接下来,我们可以用下面的代码来看看数据集中变量之间的相关性。

现在,如果我们看看相关性,汽车的每加仑英里数(MPG)和汽车的重量有很强的负相关性。

在本文中,我将做一个简单的线性回归分析,以实现可视化。自变量将是汽车的重量,因变量将是汽车的英里数。

现在,让我们用 Scikit-learn 将数据拆分为训练数据和测试数据。拆分数据后,我们现在可以缩放因变量和自变量。这是为了确保这两个变量将在相同的规模,这也将提高我们的线性回归模型的收敛速度。

现在,如果我们将训练数据可视化,我们会得到以下可视化结果:

厉害!接下来,让我们继续用 TensorFlow 构建确定性线性回归模型。

张量流的确定性线性回归

用 TensorFlow 建立一个简单的线性回归模型是非常容易的。我们所要做的就是建立一个没有任何激活函数的单一致密层。对于成本函数,通常使用均方误差。在这个例子中,我将使用 RMSprop 作为优化器,模型将在 100 个时期内被训练。我们可以用下面几行代码来构建和训练模型。

在我们训练了模型之后,让我们看看模型的损失历史来检查损失收敛。

损失 v 历元数

损失似乎已经收敛了。现在,如果我们使用训练好的模型来预测测试集,我们可以看到下面的回归线。

仅此而已。我们完了!

正如我前面提到的,用 TensorFlow 建立一个简单的线性回归模型是非常容易的。有了回归线,我们现在可以在任何给定的汽车重量输入下近似汽车的 MPG。举个例子,假设汽车在特征缩放后的重量是 0.64。我们可以通过将此值传递给训练好的模型来获得汽车的 MPG 的相应值,如下所示。

现在你可以看到,模型预测汽车的 MPG 将是 0.21。简单地说,对于任何给定的汽车重量,我们得到一个单一的确定性的汽车的 MPG 值

然而,这个产值并不能真正说明全部情况。这里有两点需要注意。首先,我们只有有限的数据点。第二,从线性回归图可以看出,大部分数据点并没有真正位于回归线上。

虽然我们得到的输出值是 0.21,但我们知道实际汽车的 MPG 并不精确地是 0.21。可能略低于这个数字,也可能略高于这个数字。换句话说,有一种不确定性需要考虑进去。这种不确定性被称为任意不确定性。

确定性线性回归无法捕捉数据的这种任意不确定性。为了捕捉这种随机的不确定性,可以改为应用概率线性回归。

具有张量流概率的概率线性回归

得益于 TensorFlow Probability,建立概率线性回归模型也非常容易。但是,你需要先安装tensorflow_probability库。您可以使用 pip 命令进行安装,如下所示:

pip install tensorflow_probability

安装这个库的先决条件是需要有 TensorFlow 版本 2.3.0。因此,请确保在安装 TensorFlow Probability 之前升级您的 TensorFlow 版本。

建立随机不确定性的概率线性回归模型

在这一节中,我们将建立一个概率线性回归模型,将随机不确定性考虑在内。

该模型非常类似于确定性线性回归。然而,不是像以前一样只使用一个单一的致密层,我们需要增加一层作为最终层。最后一层将最终输出值从确定性分布转换为概率分布。

在本例中,我们将创建一个最终图层,将输出值转换为正态分布的概率值。下面是它的实现。

注意,我们在张量流概率层的最后增加了一层。该层将把先前密集层的两个输出(一个用于平均值,一个用于标准偏差)转换成概率值,该概率值正态分布有可训练的平均值( loc )和标准偏差(标度)。

我们可以使用 RMSprop 作为优化器,但是如果您愿意,也可以使用其他优化器。对于损失函数,我们需要使用负对数似然。

但是为什么我们使用负对数似然作为损失函数呢?

负对数似然作为成本函数

为了使分布符合某些数据,我们需要使用似然函数。利用似然函数,我们尝试根据我们在数据中看到的模式来估计未知参数 θ (例如,正态分布数据的平均值和标准差)。

在我们的概率回归模型中,优化器的工作是找到未知参数的最大似然估计。换句话说,模型被训练以从我们的数据中找到给定模式的最可能的参数值。

最大化似然估计与最小化负对数似然是一样的。在优化领域,目标通常是最小化成本,而不是最大化成本。这就是为什么我们使用负对数似然作为我们的成本函数。

下面是负对数似然作为我们的自定义损失函数的实现。

任意不确定性概率线性回归模型的训练和预测结果

既然我们已经构建了模型并定义了优化器和损失函数,让我们编译和训练模型。

现在我们可以从训练好的模型中抽取样本。我们可以用下面的代码来可视化测试集和从模型中生成的样本之间的比较。

测试数据 v 从概率线性回归模型生成的样本

从上面的可视化中可以看出,对于任何给定的输入值,模型都不会返回确定性的值。相反,它将返回一个分布,并根据该分布绘制一个样本。

如果将测试集的数据点(蓝点)与训练模型预测的数据点(绿点)进行比较,您可能会认为绿点与蓝点来自相同的分布。

接下来,在给定训练集中的数据的情况下,我们还可以可视化由训练模型生成的分布的均值和标准差。我们可以通过应用下面的代码来做到这一点。

我们可以看到,概率线性回归模型给我们的不仅仅是回归线。它还给出数据标准偏差的近似值。可以看出,测试集的大约 95%的数据点位于两个标准偏差内。

建立随机和认知不确定性的概率线性回归模型

到目前为止,我们已经建立了一个概率回归模型,它考虑了来自数据的不确定性,或者我们称之为随机不确定性。

然而,在现实中,我们还需要处理来自回归模型本身的不确定性。由于数据的不完善,回归参数的权重或斜率也存在不确定性。这种不确定性被称为认知不确定性。

到目前为止,我们建立的概率模型只考虑了一个确定性权重。正如您从可视化中看到的,该模型仅生成一条回归线,通常这并不完全准确。

在这一节中,我们将改进我们的概率回归模型,将任意的和认知的不确定性都考虑在内。我们可以使用贝叶斯观点来引入回归权重的不确定性。

首先,在我们看到数据之前,我们需要定义我们对体重分布的先验信念。通常,我们不知道会发生什么,对吗?为了简单起见,让我们假设权重的分布是正态分布,平均值等于 0,标准差等于 1。

因为我们硬编码了均值和标准差,这种先验信念是不可训练的。

接下来,我们需要定义回归权重的后验分布。后验分布显示了在看到数据中的模式后,我们的信念是如何改变的。因此,这个后验分布中的参数是可训练的。下面是定义后验分布的代码实现。

现在的问题是,上面后验函数中定义的这个VariableLayers是什么?这个可变层背后的想法是,我们试图近似真实的后验分布。通常,不可能得到真实的后验分布,因此我们需要近似它。

在定义了先验和后验函数之后,现在我们可以建立权重不确定的概率线性回归模型。下面是它的代码实现。

你可能注意到了,这个模型和之前的概率回归模型唯一的区别只是第一层。我们使用DenseVariational层,而不是普通的密集层。在这一层,我们将先验和后验函数作为自变量传递。第二层和前面的模型一模一样。

随机和认知不确定性的概率线性回归模型的训练和预测结果

现在是我们编译和训练模型的时候了。

优化器和成本函数仍然与之前的模型相同。我们使用 RMSprop 作为优化器,使用负对数似然作为成本函数。我们来编译训练或者建模。

现在是时候让我们可视化回归模型的权重或斜率不确定性了。下面是可视化结果的代码实现。

在上面的可视化中,您可以看到线性线(平均值)以及由训练模型的后验分布生成的标准偏差在每次迭代中都是不同的。所有这些线都是拟合测试集中数据点的合理解决方案。然而,由于认知的不确定性,我们不知道哪条线是最好的。

通常,我们拥有的数据点越多,我们将看到的回归线的不确定性就越小。

最后的想法

就是这样!现在,您已经看到了概率线性回归与确定性线性回归的不同之处。使用概率线性回归,可以考虑由数据(任意的)和回归模型(认知的)产生的两种不确定性。

如果我们想要建立一个深度学习模型,其中不准确的预测会导致非常严重的负面后果,例如在自动驾驶和医疗诊断领域,考虑这些不确定性是非常重要的。

通常,当我们有更多的数据点时,模型的认知不确定性会降低。

交易的概率机器学习方法+ MACD 商业理解

原文:https://towardsdatascience.com/probabilistic-machine-learning-approach-to-trading-macd-business-understanding-6b81f465aef6?source=collection_archive---------6-----------------------

在文章的最后,你会知道如何用概率的方式构造一个交易问题。此外,您将通过听取专家的意见来学习如何改进特征工程流程。最后,我们将用真实数据训练一个随机森林来应用这些概念!。(奖励音轨:很酷的可视化效果)。

0)我们的动机

故事是这样的:我们是投资者,我们有,比如说,1,199 美元(很快你就会明白为什么我用的是 1,199 美元而不是 1,000 美元),我们的目标是最大限度地利用它们(我们会想要别的吗?).我们决定进入加密市场,因为它的波动性。为了维持我们的合作关系,我们需要持续盈利。我们希望使用机器学习,同时不忘记交易者使用的业务理解。现在,我们唯一需要知道的是如何做到的(哇…我肯定会在我的下一场自由泳比赛中使用它)。我们能做到吗?我们来想办法吧!

0.a)我能从这里学到新的东西吗?

快速回答:是的,那是我的本意。我邀请你在接下来的 18 分钟里——根据中等估计——和我在一起。如果你现在没有时间,就把这个链接加到你的记事本上,但是为了充分利用这里,我希望你能集中所有的注意力。我知道我要求很多,但我向你保证这是值得的。那么,我为什么要写这个呢?:

第一个:我看过很多与交易相关的文章,这些文章用令人难以置信的模型训练,使用令人印象深刻的算法,很酷的可视化,以及出色的写作风格。但我没有找到更详细的解释,这是一个简单的例子,基本理解如何在现实世界中使用它们。

第二个:大量的这些文章可以归类如下:“用你自己的交易机器人设定你的策略”和“预测股票价格的最佳机器学习模型”

“交易机器人”类型很好理解能够充分反映指标和可观察图表行为之间的相互作用的逻辑:商业理解。另一方面,机器学习模型非常擅长使用指标作为变量来捕捉更广泛的市场场景:数据科学知识。

从夹住。

然而,我错过的是这些概念的融合。交易机器人的问题是,简单的刚性策略可能没有其他指标的支持。另一方面,“股票价格”类型关注指标,但它们缺乏背景,没有背景,它们通常是无用的,或者至少不太有效。

0.b)议程

正如你所看到的,我会试着给你我对如何解决这些问题的看法。为了将重点放在最近暴露的概念上,我将留下模型训练部分的一些细节(如模型选择或超参数调整)。测试的想法将是,如果我们设法抓住这些业务概念并将它们与我们的数据科学知识相结合,我们可以在多大程度上提高我们的准确性。我们的议程:

  1. 我将首先向你介绍一些必要的概念。在开始考虑训练我们的模型之前,只是一些基本的东西。
  2. 我们将讨论费用如何通过影响我们的预期回报来影响我们的决策。
  3. 我们将讨论捕获风险管理程序的候选模型的要求。
  4. 最后,我们将描述如何获取市场的商业解释,然后用它来增强我们的模型。这里是工作完成的地方,最令人兴奋的部分!如果你了解背景,你可以快速阅读其他部分,但重点是这里。你不会后悔的。
  5. 我们将简要回顾一下我们的主要观点。

1)风险管理

首先,让我们从它在交易环境中的定义开始。

风险管理 :“是用于减轻或保护您的个人交易账户免受失去所有账户余额的危险的过程。”

这个过程涉及不同的决策,如果你愿意,它可以获得难以置信的复杂性。目前,这超出了我们的范围,所以我们将只关注其中的两个:

  • 预期收益 : 是交易收益的期望值。
  • 最大风险:你愿意为一笔交易放弃的总资金的最大数额。

1.a)预期回报

要将我们的赌注转化为计算好的走势,我们需要评估这种情况,以了解我们的胜算。因为我们不是赌徒,我们需要定义我们的止损点 (S/L)和止盈点 (T/P)。这些是我们定义的结束我们交易的价值观。

想象一个乌托邦世界,新冠肺炎被根除,以太坊再次达到 1000 美元。那时,我们决定买一些。此外,我们认为,如果价格下跌超过 20%,我们可能处于危险的境地,所以如果价格超过 800 美元,我们将出售它。另一方面,如果价格上涨超过 25%,我们会很乐意卖掉它,获得 250 美元的利润。

情绪状态,S/L 红线和 T/P 绿线。此处代码。

如果我们忘记了时间变量,在每笔交易中,我们只有两种结果,我们可以赢,也可以输,取决于哪个价格先到达(S/L 或 T/P)。想象一下,我们认为我们有 45%的机会赢,55%的机会输。预期回报计算如下。

来自维基百科的公式。

这是我自己做的。

你可以看到,这是所有给定案例的概率和它们的回报的乘积之和。在我们的例子中,每笔交易的预期回报是 2.5 美元。这意味着,如果机会是正确的,我们重复这个过程,例如,100 次,我们将获得大约 250 美元的利润。

1.b)最大风险

另一个重要的任务是确定我们愿意在一次交易中损失的最大金额。这是因为,如果我们在一次交易中冒险投入 20%的资金,我们很有可能会输掉前三次交易。我们最终会拿走一半的钱,热泪盈眶,我们美好的友谊也可能就此结束。

Icons8 团队在 Unsplash 上的照片

为了避免这种情况,因为从这样的损失中恢复是困难的,也因为我非常珍惜我们的友谊,我建议你使用典型的 1%法则。这意味着,如果我们有 1,199 美元,我们不允许每笔交易损失超过 11.99 美元。

我是一个喜欢冒险的人,所以我强迫你在每笔交易中,我们的亏损场景将是定义的最大 1%的亏损(这是为了我们的例子简单起见,我没有那么糟糕)。在这样做的时候,有一些重要的事情需要考虑,独立于我们的结果,我们需要支付费用。多么痛苦的现实啊!

2)现实生活

假设我们为菜鸟交易者使用市场上最好的费用。我们选择币安。他们对接受者和制造者收取 0.1%的佣金。这意味着,如果我们用 1.000 USDT (这里是为什么 USDT 而不是美元)购买以太坊,我们需要支付 1 USDT 费用,仅仅是为了购买。

来自币安的费用表。

我们的 S/L 和 T/P 将分别为-1%和 1%(请记住,它可以是您想要评估的任何 S/L 和 T/P 点)。如果价值达到 990,我们有义务出售,但是不要忘记,我们需要为第二次交易支付 0.99 USDT。在这种情况下,我们损失了 11.99 USDT,这是我们 1,199 美元初始资本所能承受的最大金额,现在完全说得通了。

如果价格首先到达 T/P 点,我们得到 10 USDT 的利润和 2.01 USDT 的费用,这意味着我们将得到 7.99 USDT 的正结余。鉴于这种情况,我们需要在这方面投资的积极成果的可能性有多大?如果你快速回答了 60%,说明你拥有令人印象深刻的快速计算技能,下面是数学程序,假设 P(n)是负面结果的概率,P(p)是正面结果的概率,并且
1-P(n)=P(p)。

这也是我自己做的

我们需要我们的预期收益(1)大于或等于零。否则,我们将持续亏损。由此得出的一个重要结论是,如果我们提高 S/L 和 T/P 百分比,我们不需要 P(p)那么高。例如,如果我们用 3%和-3%来评估我们的最后一个场景,我们只需要 53.3%来进行交易。

这就是为什么我羡慕每一个能在 RobinHood 上创建账户的人。我不被允许,因为我“来自美国之外”如你所见,无费用交易让你处于更有利的位置。你不会开始输。不过,我已经抱怨够了,让我们去看看是什么让我们来到这里。

3)使用机器学习定义赔率

我们谈了很多关于预期回报的问题,所以我们肯定会使用这种方法,但这不是唯一的方法。事实上,我见过的最常见的方法是使用波动性的测量值(在这里有清楚的解释)来估计交易的风险。我告诉你这个是因为这是标准的近似值——这里不会用来维护结构——但也是一个很好的选择。

我们都很聪明,但在密码市场没有多少经验。所以我们明白,我们的勇气和我们曾经看过的布林线文章,不足以定义与我们的 S/L 和 T/P 点相关的概率。现在我们的目标是思考哪种机器学习算法最适合这个问题。

我们看到这个问题由一个积极的和一个消极的结果组成。因此,我们可以断言这是一个标准的二进制分类问题。此外,我们需要一个分类器,能够给出在特定情况下每种结果的概率。理想情况下是这样的:

在理想世界中,你的模型给出了每一点的 P(p)。这里的代码。

为什么那样?因为我们需要知道几率来检查我们交易的预期收益是否为正。对我们来说,一个简单的“将要上涨”的信号是不够的。这种类型的模型被归类为一类概率估计。交易不是赢得所有的进场。这是概率问题!

尽管我们可以出于不同的动机(KNN,SVM,所有不同的自回归模型,K-Means,以及许多其他模型)放弃许多选项,但我们仍然有一些优秀的候选人。

我们的一些选择是朴素贝叶斯分类器、逻辑回归、决策树、随机森林或不同类型的神经网络。候选人少了,工作量也就少了。测试他们所有人的结果将会是惊人的。正如我之前告诉您的,这超出了本文定义的范围。但是对于我们的例子,我们将训练一个随机森林。

4)如何捕捉交易逻辑作为机器学习问题的变量?

我想用一个例子让你们对此有所了解。主要的想法是理解我们的专家提供的见解:交易者!如果他们一整天都在做这些,我们需要保持谦卑,听听他们要告诉我们什么。这是这个问题中的关键过程,也是你愿意解决的任何问题中的关键过程。我们需要这样的商业环境。

来自img lip。上下文此处。

我们的目标是做最好的功能工程!。创建变量的过程需要基于商业概念。只有在这之后,我们才能应用所有常见的转换,如标准化或规范化(只有最后一部分才有意义!).

这一部分的目标是比较第一种简单方法的性能,然后是交易机器人近似方法的性能,最后,尝试将所有部分结合在一起。我们将假设我们只能持有多头头寸,正因为如此,我们只对正面结果的预测感兴趣。

PS:我会把这部分代码全部留在我的github上。尽管有一些例外,代码将是通用的,以获得流动性。此外,由于抽样的随机性,一些结果可能会发生变化(我测试过,变化不是很大)。

4.1)我们的数据

我们将从币安检索我们的数据,你可以阅读这个博客来创建你的 API-KEY。这里的是 python-币安的文档。我们将使用 5 分钟间隔的数据。下面是收集数据的代码(3 行数据,我正在转换成 Flash?).

来自币安的 5 分钟间隔数据。(我们的例外)。

4.2)我们如何标记我们的 0 和 1?

我做了一个方法,决定先发生什么:增加 0.5%还是减少 0.5%。逻辑如下:该方法寻找接下来的 100 个时间段(对于 5 分钟的数据,超过 8 小时)并检查价格是否超出我们定义的阈值,仅考虑第一个达到的值。

我只是使用了接近的价格,因为高值和低值可能同时高于或低于我们的目标,给我们带来一些麻烦。不出所料,并不是在所有的情况下,都有结果,但是百分比并不高,我们可以去掉那些数据。

技术说明:收集的数据涵盖了截至 2020 年 4 月 22 日的前 500 天。我用 1 标记+0.5%的结果,用 0 标记-0.5%的结果。如你所见,数据没有明显的不平衡。在总共 143,542 个数据点(120,245 个用于训练,23,297 个用于测试结果)中,数据点 49.85%为阴性,49.82%为阳性,1.26%没有结果。

4.3)指示器

TA 包有一个方法可以构造很多有用的指标。最棒的是,我们需要选择的所有参数都有自己的默认值。然而,如果我们愿意,我们可以改变它们。

import pandas as pd 
import numpy as np
import ta
df=pd.read_csv('Binance-ETHUSDT-22-04-2020')
df['timestamp']=pd.to_datetime(df['timestamp'],format='%Y-%m-%d %H:%M:%S')
df.set_index('timestamp',inplace=True)
df=df.astype(float)
df1 = ta.add_all_ta_features(
    df, open="open", high="high", low="low", close="close", volume="volume")

4.4) MACD

交易者是业务理解者,如果我们的模型仅仅基于技术分析——这可能反映了新闻——我们需要了解指标!。但是正如我之前告诉你的,这些人如此努力地将他们联系起来定义策略,以至于他们最终获得了对组合的直觉。我们的工作是将直觉转化为数学!。

作为一个例子,我想和你谈谈移动平均线收敛发散( MACD )指标。这是交易者之间最常见和广泛传播的方式之一。MACD 的计算方法是从短期均线中减去长期指数移动平均线(均线)。之后,你创建一条“信号线”,这是 MACD 的均线。最常用的参数分别是 26、12 和 9。

4 月 10 日和 11 日以太坊价格和指标。

使用 mplfinance 你可以像交易者一样实现可视化。上图中,你可以在主面板上看到一个普通的 OHLC 烛台。在下面的面板中,我们有两件事情正在进行,直方图上的量,以及用虚线表示的指标(灰色的 MACD 和青色的 MACD _ 信号)。

你可能会感到困惑,因为通常的表示法是用两根 MACDs 的差值来创建柱状图。但是不要觉得失落!直方图是体积。我只是将图表中的信息量最大化(我们不需要线条上包含信息的直方图,不是吗?).

4.5)我们能单独相处吗?

好吧,很酷的指示器,很酷的可视化,但是如何使用它们呢?这是我们必须尝试一些策略的部分。有了我们的数据科学,知识就足够了?我们来想办法吧!下面的部分是给你一些变量的背景。我把一些箱子里的指示器分开了。我们可以检查这些值本身是否在这些范围内给了我们积极或消极结果的线索。

MACD 宾斯,分开的结果。

MACD _ 信号仓,由结果分开。

MACD 信号和 MACD 的区别

在左侧的箱上出现正面结果而在右侧出现负面结果的概率似乎更高。但似乎没有什么是防弹系统。我们看到了这一点,并且我们确信我们能够有所作为。所以我们可以继续前进。

是时候训练我们的第一个模型了!假设我们认为结果只取决于我们刚刚看到的三个测量值(显然不是),但我们仍然可以训练我们的模型,看看它如何发展。首先,我们将平衡积极和消极的结果,然后,使用我们钟爱的标准标度转换我们的变量。培训数据将一直使用到 2020 年 2 月 1 日。其余的将用于测试结果。

技术说明:“初始”将是 2 月之前的指标数据框架,“指标”是整个数据框架,但对于[120245:]它只是测试数据。

Initial = Initial.sample(frac=1)
X_train = Initial[["trend_macd", "trend_macd_signal", "trend_macd_diff"]]
y_train = np.where(Initial["Outcome"] == "+0.5%", 1, 0)
X_test = indicator[120245:][["trend_macd", "trend_macd_signal", "trend_macd_diff"]]
y_test = np.where(indicator[120245:]["Outcome"] == "+0.5%", 1, 0)
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import confusion_matrix
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)Classifier1 = RandomForestClassifier(
    max_depth=2,
    min_samples_leaf=400,
    max_features=2,
    min_samples_split=4,
    n_estimators=1000,
    random_state=28,
)
Classifier1 = Classifier1.fit(X_train, y_train)
y_pred1 = Classifier1.predict(X_test)confusion_matrix(y_test, y_pred1)

混淆矩阵

垂直的数字代表真实的结果,水平的数字代表预测。例如,在这种情况下,我们预测了 9505 个积极的结果,其中 53.8%的预测是正确的。正确分配坏的结果有一些小麻烦,但是我们可以暂时忘记它。

你还记得我们讨论预期收益的所有前奏吗?现在是时候使用它了!。我们可以使用 predict_proba 来获取正面结果的概率。下图显示了给定某个 P(p)的成功概率,在这种情况下,我们知道 P(p)>0.5=0.538。理论上讲,预测概率越高,我们的胜算就越大。

在每个矩形的顶部,您可以看到满足该条件的案例数量。概率越大,涉及的案例越少。但总的来说,我们找到了我们所期望的!P(p)越大,成功率越大。如果我们每次都用这个策略进去,P(p)>0.6,我们最终会得到131235 的正确条目!。

4.6)贸易-Bot 战略方法

每个指标都有不同的使用方法,这取决于和你交谈的交易者。但是,有一个话题有一些共识。协议规定,当 MACD 越过信号线上方,也就是最后一条线低于零时,就是进场信号。如果你走得更远,他们也会告诉你这只是一个进场信号,如果市场的趋势和信号的方向一致。

还有多种方法可以检验市场趋势,我们会坚持其中一种。比较 200 周期均线和收盘价。如果价格高于均线,我们认为这是一个上升趋势。对于相同的测试数据,这是一个简单的过滤器,可以过滤出满足这三个条件的情况。

为了让这变得更有挑战性,我将向您展示我们测试数据的前 4 天(对于 GIF 大小来说不会更多)。下面你可以看到两个新的东西。首先是 200 期均线虚红线。另一个新的事情是,我会标记进场点,只要它们满足所有条件(如果交易结果是负面的,用红色表示,如果是正面的,用绿色表示)。

这—不太好— 4 天反映了整个期间最终发生的事情。204 次符合条件, 97 次符合正面结果。这不是我们所期望的,但我们不必忘记这只是硬性规定。在下一节中,我们将更深入地探讨这一战略的精神。

4.7)将所有功能整合在一起!

好吧,我们的近似有体面的结果,而交易机器人不是那么好。但是如果我们想用真正的费用投资,那些结果是不够的。我们能改进吗?这就是我们在这里的原因!我们的工作是了解正在发生的事情,也许如果我们停下来想一想,我们的结果会更好。

规则背后的直觉是什么?我听一些交易者说,预期 MACD 信号在零线后面的原因是因为他们预期有一个更高斜率的交叉。因此,如果我们加入一个变量来反映 MACD 上升的力度,我们可能会得到一些更好的结果。

这可以通过将指标与最近时期之间的差异作为一个变量来实现。为了反映这一点,我们将使用移位方法来减去实际值与之前的 1、3 和 5 个周期。但是这些概念也适用于其他两个组件。所以我们会对每个变量都这样做。这将为我们提供 9 个额外的变量,它们的任务是反映这些指标的来源。

同样,我们可以理解趋势也很重要,但也许没有必要把它作为一个二元变量。相反,我们可以用收盘价减去 200 均线,然后除以收盘价,得到它们之间的百分比差。让我们看看会发生什么!

indicator['trend_macd_diff1']=indicator['trend_macd_diff']-indicator['trend_macd_diff'].shift(1)
indicator['trend_macd_diff3']=indicator['trend_macd_diff']-indicator['trend_macd_diff'].shift(3)
indicator['trend_macd_diff5']=indicator['trend_macd_diff']-indicator['trend_macd_diff'].shift(5)
indicator['trend_macd_signal1']=indicator['trend_macd_signal']-indicator['trend_macd_signal'].shift(1)
indicator['trend_macd_signal3']=indicator['trend_macd_signal']-indicator['trend_macd_signal'].shift(3)
indicator['trend_macd_signal5']=indicator['trend_macd_signal']-indicator['trend_macd_signal'].shift(5)
indicator['trend_macd1']=indicator['trend_macd']-indicator['trend_macd'].shift(1)
indicator['trend_macd3']=indicator['trend_macd']-indicator['trend_macd'].shift(3)
indicator['trend_macd5']=indicator['trend_macd']-indicator['trend_macd'].shift(5)
indicator['trend']=(indicator['200MA']-indicator['Close'])/indicator['Close']
Initial = Initial.sample(frac=1)
X_train = Initial[
    [
        "trend_macd",
        "trend_macd_signal",
        "trend_macd_diff",
        "trend_macd_diff1",
        "trend_macd_diff3",
        "trend_macd_diff5",
        "trend_macd_signal1",
        "trend_macd_signal3",
        "trend_macd_signal5",
        "trend_macd1",
        "trend_macd3",
        "trend_macd5",
        "trend",
    ]
]
y_train = np.where(Initial["Outcome"] == "+0.5%", 1, 0)
X_test = indicator[120245:][
    [
        "trend_macd",
        "trend_macd_signal",
        "trend_macd_diff",
        "trend_macd_diff1",
        "trend_macd_diff3",
        "trend_macd_diff5",
        "trend_macd_signal1",
        "trend_macd_signal3",
        "trend_macd_signal5",
        "trend_macd1",
        "trend_macd3",
        "trend_macd5",
        "trend",
    ]
]
y_test = np.where(indicator[120245:]["Outcome"] == "+0.5%", 1, 0)
from sklearn.preprocessing import StandardScalersc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
from sklearn.ensemble import RandomForestClassifierClassifier = RandomForestClassifier(
    max_depth=11,
    min_samples_leaf=400,
    max_features=11,
    min_samples_split=4,
    n_estimators=500,
    random_state=28,
)
Classifier.fit(X_train, y_train)
y_pred = Classifier.predict(X_test)from sklearn.metrics import confusion_matrixconfusion_matrix(y_test, y_pred, normalize="true")

在不利结果方面,它似乎做得更好,但在积极结果方面,我们的表现稍好一些(53.98%的真阳性)。嗯……这可能会令人沮丧,但是嘿!不要在看 P(p)图之前就放弃。也许会给我们带来好消息,谁知道呢?

我就知道!!这个柱状图的出现是为了拯救世界!。不出所料,成功率越来越高!我们可以看到,与我们制作的第一个相比,这个模型有了明显的改进。为什么?因为它可以更好地分离出具有更高成功率的条目概率的情况。

假设我们选择策略:在 P(p)>0.62 时买入。我们的计划会成为一个炸弹!我们得到了 188 个信号,其中 124 个成功(有效 65.95% )。重要的是,我们利用所学的一切,设法制定出一个好的策略!。好了,我要放松了,今天太兴奋了。

我们做到了这一点,只用了一个指标!如果我们认为模型可以包含其他具有不同概念的基本指标,如交易量或波动性,这是有希望的。但是那个家伙,那是完全不同的故事。

5)后会有期!

我度过了一段美好的时光,并与你分享,我希望这对你有所帮助。如果你因为结束而高兴,给我你的最后一分钟!我喜欢仪式,用我们的主要外卖做一个结束仪式会提升我的精神:

  • 我们定义了风险管理程序的一小部分,理解了预期回报的重要性。
  • 我们遭受了费用对我们决策的影响。
  • 我们看到了为这项任务选择类别概率估计模型的重要性。
  • 我们知道如何根据业务概念改进我们的功能工程,在关键的地方获得更高的成功率。
  • 你现在可以做酷酷的动作可视化了!

这就是我给你的全部内容,我知道这是基本概念,但主要目的是即使你对交易了解不多,你也能理解这一点。现实生活中的系统也有很多方法可以使这些策略更加稳健。此外,我做的很多决定都会引发争论,这是我所期待的!我很乐意讨论你的不同想法,给我一个你的想法的回复!

如果我感受到你的热情支持,我会带着新鲜的内容回来!

由于你给了我很大的支持,我想出了一个延续:

[## 优化…目标变量(?)交易机器学习模型的例子

我们的目标是静态的吗?

towardsdatascience.com](/optimizing-the-target-variable-an-example-for-trading-machine-learning-models-48a1587d7b9a)

这是强制性的,你不要用这个策略投资或交易,因为这篇文章的主要目的是谈论商业理解。使用交易的想法:它只是一个工具,用来访问真实的问题和真实的数据。如果你遵循这个未经证实的系统,你很容易失去你的存款!。

如果你喜欢,就在 Medium 和 Linkedin 上关注我。如果你想给我写信,我最近在推特上。我很乐意与你交谈!

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

用于乳腺癌检测的概率深度学习

原文:https://towardsdatascience.com/probabilistic-neural-networks-for-breast-cancer-detection-2f1a6951e459?source=collection_archive---------27-----------------------

来源: Unsplash

在本文中,我将演示使用变分推理来量化深度神经网络权重的不确定性,并为乳腺癌分类数据集做出更明智的预测。

我将在 PyMC3 中构建一个概率神经网络,它使用 ADVI 来优化我们模型的参数。我们将更多地考虑神经网络权重的后验分布,以及我们可以从中获得的见解。

目标

这里的目标是建立一种算法,可以分析关于乳腺癌细胞的信息和指标,以预测细胞中的癌症是“良性”还是“恶性”

乳腺癌的分类是一个二元分类问题,其中我们将细胞分类为良性或恶性。良性肿瘤是一种不会扩散到身体其他部位的非侵袭性肿瘤。恶性肿瘤是一种侵袭性和癌性肿瘤,可以通过血液扩散到身体的其他部位。如果被确定为“恶性”,乳腺癌需要更有效的治疗。

犯假阴性的代价

在这个分类问题中,有两种错误——假阴性和假阳性。假阳性(良性癌症被归类为恶性癌症)将导致我们最终给患者服用更强的药物。虽然这会带来额外的成本和风险,但不会危及生命。任何假阴性(恶性癌症被错误地归类为良性)都可能是致命的,我们应该不惜一切代价避免它。

我们来量化一下这个损失。假阴性会危及生命。因此,假阴性的代价等于一个人生命的价值。虽然对生命的代价存在重大争议,但人类生命的代价大约是 1000 万美元。(注:我不完全同意给生命贴上价格标签,但你应该读一下的这篇文章。)与此同时,导致更多医疗费用的假阳性的成本约为 8 万美元。这两个错误的比例是 125。因此,提交一个假阴性与提交 125 个假阳性是一样的。

使用整体准确性作为衡量标准来微调算法是没有意义的,因为它掩盖了假阴性和假阳性的分布。因此,我们需要一种算法来将假阴性的数量减少到绝对最小值。因此,我们希望根据假阴性的数量来优化我们的模型。

在这个算法中有很多地方,我们可以改变参数来影响结果。在这种情况下,我们将微调算法中的一切,以减少假阴性的数量。

数据

我从加州大学欧文分校的机器学习库中获得了这些数据。在数据集中,科学家将肿瘤细胞的图像转换成九个基本指标:

  1. 半径,
  2. 纹理(灰度值的标准偏差),
  3. 周界,
  4. 面积,
  5. 平滑度,
  6. 紧凑性,
  7. 凹度,
  8. 凹点
  9. 对称。

因此,图像被简化以供我们使用。因此,我们需要更少的预处理来使我们的数据为分析做好准备。

数据清理

原始数据文件是未经处理的字符串数据,其中每个值都必须进行分离和处理。一些列有空值。我们清理数据,并在 NumPy 数组中将它转换成可供分析的格式。(注意:大多数 ML/AI 算法接受 NumPy 数组作为输入,因为 NumPy 数组作为矩阵工作。因此,对数据执行线性代数(如点积/投影/乘法)变得容易多了。)

下面是获取原始数据的代码。数据文件并将其合并到干净的 NumPy 数组中。请注意,我故意编写了比平时更长的代码,因为我想演示实际的处理和转换。通过 pandas/NumPy 内置函数,同样的过程更加简单,尽管它们可能不会更快。

*""" This section extracts and cleans all the data in the .data file  """***def** extraction(pathname):
    initial = open(pathname)
    image_data = []**for** line **in** initial:
        image_data.append(line.strip()) 
     *#Extracting data line by line*

    final_data = []
    target = []

*# Each line is a record that contains the attributes, delimited by a comma*

    **for** string **in** image_data: 
        string2 = list(string)
        bad_data = **False**
        indexes = [-1]
        **for** (index,element) **in** enumerate(string2):
            **if** element == ',':
                indexes.append(index)*# Finding the indexes where the string needs to be be cut*

        indexes.append(len(string))
        data = [] 

        **for** i **in** range(1,len(indexes)):
            *# For each split by a comma, we extract the element*
            element = string[indexes[i-1]+1:indexes[i]]

            **try**:
            *# If the data is float, we extract it*
                element = float(element)
                data.append(element)

            **except**:
            *# Otherwise it's bad data.*
            *# This includes inputs like missing data, 'NA' or 'nan'*
                bad_data = **True**

        **if** **not** bad_data:
            final_data.append(data[1:len(data)-1])
            target.append(data[-1])*# Appending the data and the class to the data list and target list*
    **return** np.array(final_data), np.array(target).reshape(len(target))

我们将继续把这段代码放在一个 Python 类中。python 类帮助我们将所有相关的函数和数据保存在一个对象中。

这里的输出是两个 NumPy 数组。一个是维数(或形状)为(683,9)的特征数组。因此,它有 683 条记录,每行有九个属性或维度。第二个是 shape (683,1)数组,这是我们的目标。在目标类别中,1 表示恶性,0 表示良性癌症。让我们来处理我们的实际数据:

特征工程和数据整合

在这一点上,有人可能认为我们应该投入到模型中,并尝试对其进行调整。但是这种方法的问题很简单:

输出结果中的偏差是数据和算法的函数。如果数据的结构、规模和清理不当,算法只能起到减少偏差的作用,但无法弥补数据缺乏一致性的问题。

所以让我们开始吧。首先,我们检查要素之间的多重共线性。我们将使用关联热图来检查:

使用上述代码生成的关联热图。来源:自己的作品。

在此热图中,重点关注任意两个变量之间过度相关的非对角线元素。我把极端相关度定义为 80%,但也要看问题的语境。在这里,纹理和参数似乎是极其相关的(91%)。但是我不会移除这个变量,因为这两个变量实际上都很重要。这两个参数在肿瘤细胞的生物学中是必不可少的,因此即使我们没有看到非常统计上的好处,因为 90%的变异是相同的,另外 10%可能有一种模式,这将提高我们算法的能力。

值得在没有任何参数的情况下重复分析(就像 A/B 测试实验一样),但是移除变量需要理论证明。我删除了凹度,因为它提高了我的模型的性能。

下一步是正常化。数据的比例不正确,一些参数的比例与其他参数的比例不同,这可能会使算法偏向一个要素。因此,我们使用标准缩放器来重新缩放所有特征,这将所有特征转换为均值为 0、标准差为 1 的新分布。

注:欢迎大家进一步进行数据整理和理解。这里没有限制!我还测试了一个 PCA 和一个 LDA ,试图减少我的数据集中的维数。有趣的是,它没有影响维度,这证明了一个事实,即每个特征都有其变化,不能组合成另一个。主成分分析确实重新排列了维度,这使我们在准确性和假阴性数量方面有了微小的提高。我们将在最后考虑这个问题,但是欢迎您在这里执行自己的 A/B 测试。你也可以在这里下载处理后的数据。

神经网络

如果你不知道什么是神经网络,你可以在这里了解更多。我们试图在多个层中构建“决策节点”,接受数据并进行转换。这些转换有助于对数据做出决策。多个层次做出越来越多的决定,共同导致最终的答案。这就像建立一个规则图,让算法用给定数据后有意义的法律来填补空白。每个节点都有一个激活函数,它采用输入的加权和并提供一个输出,该输出成为神经网络下一层的输入。本文的重点是构建网络并使用它来获得结果的过程。你可以在这里了解更多关于建立神经网络的想法。

概率神经网络

在上面链接的文章中, Marco Peixeiro 谈到了位于神经网络每一层的节点所使用的函数形式。这些“激活函数”在技术上是固定的,并且每个节点的输入权重在网络中被优化。但是简单的神经网络是确定性算法。它给了我们一个重量的估计,你可以用它来做预测。但是没有关于这些估计的不确定性或最终预测的不确定性的信息。这些估计以预测概率或我们估计的置信区间的形式出现。因此,探索贝叶斯推理和神经网络的结合来帮助我们识别这些算法中的不确定性是有价值的。

具体来说,我们希望提取以下信息:

  1. 我们预测的不确定性:这是以“恶性”对“良性”的概率的形式出现的,而不仅仅是二分法。
  2. 权重中的不确定性:对于神经网络的每一层,我们希望了解这些权重中的不确定性,并使用它来评估我们的神经网络的质量。
  3. 赋予权重先验的能力:还记得贝叶斯推理吗?我们将初始化参数的先验,并获得基于先验和给定先验的数据的似然性的后验样本/估计。这些估计将为我们提供不确定性估计。因此,将 a 置于神经网络中节点权重之前的能力将增加我们分析的价值。
  4. 分层建模:神经网络的一个重要方面是理解和汇集基于子群的参数的能力。例如,我们可以估计癌症样本的种族的不同权重(这可能非常重要,因为已经有大量研究证明种族影响乳腺癌的死亡率)。
  5. 建模的灵活性:贝叶斯推理带来了建模的灵活性和主观性。虽然这种灵活性可能会威胁到模型的可靠性,但如果您是专家,并且了解我们数据的不同输入之间的交互的本质细节,这将是有益的。

自动微分变分推理

如果你对 MCMC 或者变分推理(VI)不太了解,你应该看看这篇文章。总而言之,VI 对给定的参数进行分布,然后优化这些分布。例如,网络某一层的权重具有正态分布的先验,我们使用 VI 来找到该分布的最佳平均值和标准偏差。

VI 使用 KL-Divergence,这是一个成本函数,帮助我们了解我们的目标概率分布和当前分布之间的距离。但是 VI 不是全自动的,需要微调。因此,我们将使用一个称为自动微分变分推理(ADVI)的 VI 版本,它优化了一个不同的参数(类似于 KL-Divergence,但更容易优化)。该算法使用各种库来区分 ELBO(我们这里的度量)并找到最大值来更新参数。它使用坐标下降(沿坐标轴优化)来实现参数更新方程。我知道这是很多信息,但是我推荐你阅读这篇文章来熟悉它。

用 PyMC3 中的 ADVI 构建神经网络

对于这个实现,我们不会从头开始构建 ADVI 算法。相反,我们将使用 PyMC3 的内置特性来开发我们的模型,并指定我们想要实现的参数、先验和网络层。

对于这个特定的实现,我将构建一个具有三层的神经网络。最后一层是感知器,也是最后的决策层。我将为它使用一个 sigmoid 函数,这样它就像一个逻辑回归。内部的两个隐藏层将使用“双曲正切”函数。您可以在这里使用 PyMC3 文档中您喜欢的任何函数。我用‘tanh’是因为它的灵活性。在 3.14 弧度的旋转中,Tanh '可以从-无穷大到+无穷大,因此,它可以很容易地模拟不同种类的渐变。

对于每一层,我们必须对每个网络的权重进行先验分布。这些权重处理输入并帮助函数做出决策。我使用标准正态分布(均值为 0,标准差为 1)来构建权重矩阵。请注意,这是一个不知情的先验。如果您有相关的知识来支持您的选择,您可以使用不同的发行版。

对于我的网络架构:每一层接受输入并产生输出。输出的维度比前一个维度少一个。因此,层 1 与 9 维的整个数据集一致,并产生 8 维的隐藏和处理输出,该输出被馈送到第二层。第二层输出七个维度,然后由感知器(基础层)作为逻辑回归进行处理。使用伯努利可能性将最终输出建模为二进制结果。看看下面的代码,跟着注释走:(注意,这个实现的基本结构是受托马斯·威茨基的帖子这里的启发。我已经采取了骨架结构,并实现了一个新的,有组织的和知情的神经网络)

import numpy as np
floatX = theano.config.floatX
import pymc3 as pm
import theano.tensor as Tdef build_network(X_train, Y_train):

    **# We're initialising the weights here 
      (the parameters we need to optimise)****# Note that the shape of the distribution 
      should match the dimension of the layer.
    # So, first distribution should go from X.shape[1] = 9 to 8**initial_weights_1 = np.random.randn(X.shape[1],8).astype(floatX)
    initial_weights_2 = np.random.randn(8, 7).astype(floatX)
    initial_weights_p = np.random.randn(7).astype(floatX)**# Initialising a model**
    with pm.Model() as neural_network:**# Denoting input data** features = pm.Data('ann_input', X_train) 
        output = pm.Data('ann_output', Y_train) **# Denoting targets**

       ** # We're now taking the set of parameters and 
          assigning a prior distribution to them.
        # The pm.Normal assigns a Normal distribution 
           with mean 0 and standard deviation 1**

        prior_1 = pm.Normal('w_in_1', 0 ,  **#mean**
                  sigma=1, **# standard deviation**
                  shape=(X.shape[1], 8), **#shape of set of parameters**
                  testval=initial_weights_1) **#initialised parameters**

        prior_2 = pm.Normal('w_1_2', 0, sigma=1, shape=(8, 7),
                            testval=initial_weights_2)prior_perceptron = pm.Normal('w_3_out', 0, sigma=1, 
                            shape=(7,), testval=initial_weights_p)

        **# Now, we'll assign the functional form of each layer
        # tanh for the first three and sigmoid for the perceptron**layer_1 = pm.math.tanh(pm.math.dot(features, prior_1))
        layer_2 = pm.math.tanh(pm.math.dot(layer_1, prior_2))
        perceptron = pm.math.sigmoid( pm.math.dot(layer_2, 
                                      prior_perceptron))

        **# A bernoulli distribution as the likelihood 
          helps model the 0,1 target data as pass/fails**likelihood = pm.Bernoulli('out', output, observed=output,
                                  total_size=Y_train.shape[0])return neural_network

让我们现在构建网络,并在其上放置一个随机种子,以消除任何起始偏差。

**from** sklearn.model_selection **import** train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=        .5)neural_network = build_network(X_train, Y_train)from pymc3.theanof import set_tt_rng, MRG_RandomStreams
set_tt_rng(MRG_RandomStreams(101))

网络权重的含义

神经网络中每个连接的权重示例。来源 : 黑客月

简单地说,每个节点都有一个处理数据的激活函数(就像我们使用的 tanh 函数一样)。该数据然后被加权,然后提交给下一层中的每个节点。这些权重决定了一个节点对下一层中每个节点的影响。通过提取每个权重的不确定性,我们可以了解总体预测不确定性的根源,并将其追溯到数据特征。因此,这些不确定性在用户和神经网络之间提供了急需的透明度,神经网络的隐藏层(节点前后的垂直堆叠变换)更难解释。

优化时间!

我们将使用内置的 ADVI 算法来优化神经网络的权重分布。PyMC3 使它的实现变得非常简单:

with neural_network:inference_method = pm.ADVI()
    approx = pm.fit(n=30000, method= inference_method)**# n is the number of iterations for ADVI**
**# method is where we denote the ADVI() from PyMC3**plt.figure(figsize=(12,6))
plt.plot(-inference.hist, label='new ADVI', alpha=.3)
plt.plot(approx.hist, label='old ADVI', alpha=.3)
plt.legend()
plt.ylabel('ELBO')
plt.xlabel('iteration');

尽管 PyMC3 屏蔽了 ADVI 代码,但还是有必要查看一下后端代码来理解这个过程。您将在 PyMC3 Github 存储库的这个 python 文件中找到 ADVI 代码。复习第 323 行的 ADVI 类。ADVI 职能部门的以下文件至关重要:

ADVI 代码进一步依赖于从推理. py 文件导入的平均场推理函数。它执行简单的平均场推断。同时,它分析输入参数并相应地采取行动。在这种情况下,MeanField()的* *参数还包括一个 ELBO 自动优化的注释。默认为 KL-Divergence。

ELBO 随迭代次数的变化。来源:自己的作品

ELBO 的优化在 19 秒内完成。但是关于这个模型有一些事情会导致 ELBO 收敛的问题,包括我们在 500 次迭代后观察到的收敛中的噪声。首先,它是一种神经网络,不总是能很好地处理小数据集。训练数据集只有大约 342 个数据点。因此,网络发现在只有 342 个数据点的情况下训练自己并解释所有的复杂性是一项挑战。因此,ELBO 的优化并不简单。

其次,神经网络很难建立。要知道创建正确网络所需的隐藏层数并不容易。因此,模型规范中也存在不确定性。让我们试着解决这些问题:

微调 ELBO 的优化

有多种方法可以确保模型的 ELBO 优化不会发散。这些指标定义了每个神经元处理的不确定性和方差的数量。值得注意的是,模型的收敛取决于数据变化的精确建模。很有可能,您对神经网络的第一次尝试将导致对数据变化的过度建模或建模不足。网络的结构及其参数必须相应地调整。我们可以对该模型的两个主要特性进行微调,以获得更好的结果:

微调神经网络

我们可以控制两个主要指标:隐藏层的数量和每个网络中神经元(节点)的数量。

  1. 隐藏层数:在较小的数据集(比如我的)中,较高的层数会导致数据中方差的损失,从而影响模型的准确性。在我的实验中,我发现两个隐藏层最适合这个数据集。该指标随着数据集的大小和结构而变化。
  2. 神经元数量:每个隐藏层有几个在初始权值部分指定的神经元。您可以选择这些数字来减少、增加或保持层的数量不变。目标是以尽可能好的方式解包数据。因此,这一步取决于每个特征所代表的数据的变化。对于我的数据集,不同特征之间存在高度相关性,每层神经元数量的减少会导致整体准确性的增加。

使用微型批次进行可扩展优化

为了使推断更快,我们将在 PyMC3 中使用迷你批处理。迷你批次减少了训练数据集的大小。在初始设置中,参数更新将要求参数查看整个训练数据集。他们创建一个小批量的训练数据集(大小为“b”),每次更新的训练都在小批量上进行。每次迭代后,批次都会更新。

经过大量的迭代,微型批次在优化 ELBO 方面变得非常高效,因为更新方程可以查看几乎每一个数据点,但不是同时查看所有数据点,这使得该过程更具可扩展性。

X_new = pm.MiniBatch(X_train, b=50)
Y_new = pm.MiniBatch(Y_train, b=50)neural_network = build_network(X_train, Y_train)with neural_network:
    inference = pm.ADVI()
    approx = pm.fit(n=30000, method=inference, callbacks=
                                [CheckParametersConvergence()])

要使用迷你批次检查结果的收敛性,我们使用相同的绘图算法:

使用小批量优化的 ELBO 变量。来源:自己的工作

使用迷你批处理,我们在 12 秒内达到收敛,但优化似乎不太顺利(初始收敛后发散更多)。我使用了来自大小为 340 的训练数据集的批量大小 50。因此,大小是一个限制,训练批次的减少导致了权重收敛的不稳定性。在结果部分,我们将比较假阴性的实际数量,以确定这种方法在乳腺癌检测中的有效性。

结果的概率

为了预测结果,我们首先生成后验样本,这些样本可用于构建预测测试结果的函数。注意,给定模型权重的估计,这些样本对应于结果的后验概率。这些样本不是参数的后验样本,因为我们没有进行 MCMC 采样。

PyMC3 没有给我们提供预测类。对于每一行,它为我们提供了结果为“1”的概率。我们必须定义一个决策边界。完成这项任务的代码如下:(这段代码的灵感来自 Thomas Wiecki 的博客,虽然我已经简化了代码,减少了一些技术术语)。

对于计算优化,我不会使用内置的 sample_posterior_predictive 函数,因为它很慢,并且不允许我们初始化预测的先验,这是我们可以手动完成的事情,以实现测试预测的加速。

**# Setting initial values**x = T.matrix('X') **# create symbolic input**
n = T.iscalar('n') **# number of samples**
x.tag.test_value = np.empty_like(X_train[:10]) 
n.tag.test_value = 100 **#initialising test values****# We now have to generate samples from our nodes 
# that'll help us make the test predictions**_sample_proba =approx.sample_node(neural_network.out.distribution.p,
                                   size=n,
                                   more_replacements=         
                                   {neural_network['ann_input']: x})**# Converting the samples into a workable function**
sample_proba = theano.function([x, n], _sample_proba)**# The function for prediction of posterior probabilities:****# Predicts the outcomes (True/False) given a decision boundary**
def predict(decision_boundary):
    pred = sample_proba(X_test, 500).mean(0) > decision_boundary
    return pred**# Compares the outcome to the Y_test values and checks for false-negatives/ false-positives**def false_results(pred):
    false_neg = 0
    false_pos = 0

    for i in range(len(pred)):
        if pred[i] == 0 and list(Y_test)[i] == 1:
            false_neg+=1
        elif pred[i] == 1 and list(Y_test)[i] == 0:
            false_pos+=1return false_neg, false_pos

在收集了测试预测之后,我们处理它们以收集总错误数、总假阴性和总假阳性。

boundaries = np.linspace(0,1,101)
false_negative_num = []
false_positive_num = []
total_errors = []for i in boundaries:
    pred = predict(i)
    n, p = false_negatives(pred)
    false_negative_num.append(n*100/len(pred))
    total_errors.append((n+p)*100/len(pred))
    false_positive_num.append(p*100/len(pred))plt.figure(figsize=(20,10))
plt.plot(boundaries, false_negative_num, label='False Negative Rate(%)', color='red')
plt.plot(boundaries, false_positive_num, label='False Positive Rate(%)')
plt.plot(boundaries, total_errors, label='Total Error Rate(%)', color='orange')
plt.xlabel('Decision Boundary', fontsize=20)
plt.ylabel('Percentage Cases', fontsize=20)
plt.legend(fontsize=20)
plt.show()

优化决策边界

误差百分比随决策边界的变化。来源:自己的作品

这里的决策边界是结果被分类为恶性和非良性的结果的概率。

对于非常低的决策边界,假阳性的数量非常高(这很直观,因为我们将一切都归类为恶性)。随着决策边界的上升,我们在 0.3 的决策边界处看到最初的几个假阴性。随着我们进一步深入,上升是缓慢的,直到 0.6 的决策边界,在那里我们看到大约 2%的假阴性率,在那之后急剧上升(如预期的)。因此,理想的决策边界位于 0.3 和 0.6 之间,尽管它可能因训练数据集的不同片段而改变。从这个网络中,对于 0.4 的判定边界,我们实现了大约 97.3%的准确度。

如果我们只考虑假阴性的数量,很容易说我们应该将决策边界设为 0,但这将不再有用,因此我们将告诉每个人他们患有恶性癌症,这将使算法无用。因此,我们需要小心我们整体预测的质量以及关注的指标。

解释模型的权重

生成重量分布图的一种简单方法是构建参数的轨迹图。

trace = approx.sample(draws=5000)
pm.traceplot(trace)

参数样本的轨迹图。来源:自己的工作

请注意,这不是一个非常清晰的可视化,但是我们可以从中获得一些见解:(在下一节中,我们将更深入地研究权重,并通过每个节点对它们进行剖析)

大多数权重被建模为高斯分布,这与我们之前的假设和初始分布非常吻合。

最后一组权重(w_2_out)是一组较小的分布,因为这是映射到感知器节点(做出最终决策的 sigmoid 曲线)的七个权重(来自最终层的七个神经元)。权重有一个平衡分布,这意味着对最终概率有正面和负面影响的分量数量相等。这些是经过两个隐藏层后的转换组件,所以很难谈论它们的“实际”意义,但可以认为它们是一个中间结果。

这些分布中的大多数在 w_2_out 中似乎与 0 有统计上的显著差异,除了在中间的几个。这意味着有一些特定组件的变换在统计上没有显著的权重,因此,它们对我们最终结果的影响并不显著。(作为一项带回家的任务,读者应尽量减少最后一层的神经元数量,以观察变化。)

w _ 1 _ 2 分析:这些权重代表了从第一层到第二层的成果映射。第一层有八个神经元,第二层有七个神经元。因此,这里的神经元总数是 8*7 = 56。(权重聚类的原因)。这些权重中的大部分似乎在统计上不显著(基于分布与 0 的重叠),这表明第二层对于模型来说不像我们想象的那样信息丰富。

另一个重要的注意事项是,这里的权重分布更广。这意味着这些权重存在很大的不确定性。(这是在确定性神经网络中永远无法分辨的事情)

w _ in _ 1 分析:这些权重表示数据到第一层八个节点上的映射。数据中有九个维度,第一层有八个神经元。因此,这里的神经元总数是 9*8 = 72。(权重聚类的原因)。在这种情况下,还存在权重统计不显著的问题。

但是这个分析需要更多的深度。让我们按每个节点分解权重并绘制它们。我们将使用以下代码获得每个重量的平均值和标准偏差:

means = approx.bij.rmap(approx.mean.eval())
sds = approx.bij.rmap(approx.std.eval())

解释每个节点的权重

对于第一个映射(w_in_1):

从数据到第一层映射的模型权重的分割分布。来源:自己的作品

我们可以从上图中获得以下见解:

  1. 特征 2、3、4 和 5 具有大量统计上不显著的权重(平均值接近于 0),因此,它们不会持续地影响模型中的方差。(这意味着它们的影响在某些情况下是积极的,在其他情况下是消极的)
  2. 特征 1、6、7 和 8 的权重具有更大的可变性和更小的不重要权重。因此,它们以更大的一致性(更可能停留在正面或负面)对模型的方差做出贡献。
  3. 虽然大多数分布都一样宽(平均标准偏差为 1),但特征 6 和 7 的分布似乎更宽。相反,特征 4 和 5 具有最平坦的曲线,具有较小的标准偏差。

对于第二个映射(w_1_2):

从第一层到第二层映射的模型权重的分割分布。来源:自己的作品

我们可以从上图中获得以下见解:

  1. 节点 2-6 具有大量统计上不显著的权重(平均值接近于 0),因此,它们不会持续地影响模型中的方差。
  2. 其余节点的权重具有更大的可变性和更小的无关紧要的权重。因此,它们以更大的一致性(更可能停留在正面或负面)对模型的方差做出贡献。
  3. 特征 7 和 8 似乎是变化的最佳贡献者,而节点 4 似乎是最不相关的贡献者,大多数平均权重为 0。

根据此信息采取行动:

通过理解第一层对数据建模的影响较小,而第二层的影响较大,我们可以得出两个结果:

  1. 减少一层网络以观察对权重一致性的影响是值得的。这可能有助于将差异合并到较少数量的更重要的节点中。
  2. 减少节点的数量也是值得的,看看它是否有助于将差异合并到更少的节点中。

最终要点:

  1. 使用该模型,我们能够在测试数据集上实现大约 97%的准确率。我们还能够了解这种准确性随不同决策边界的变化,并确定最适合我们目标的决策边界范围。
  2. 我们能够仔细检查神经网络中的每一个权重,以及每个节点权重的不确定性。这些信息有助于优化网络并增加模型的可靠性。

未来的改进:

  1. 值得收集更大的数据集来提高我们模型的质量。如果首先没有足够的数据来分析,神经网络只能增加这么多的价值。
  2. 我们可以用多种激活函数和大小来增强神经网络,作为 A/B 测试,以找到最佳匹配。

如果你想探索这个模型,我已经在这里的笔记本中将整个工作流程构建成一个易于使用的 Python 类。

如果您有任何问题或想要联系,我的 LinkedIn 个人资料是这里。在推特上联系我这里。

概率预测

原文:https://towardsdatascience.com/probabilistic-predictions-fe04214bde48?source=collection_archive---------29-----------------------

拥抱不确定性,做出更好的决策

安妮·斯普拉特在 Unsplash 上的照片

在数据科学中,处理预测错误的传统方法让我想起了冰山的比喻。我们的模型不能完美地预测未来,所以我们优化它们,尽可能地降低预测误差。更好的模型有望导致更小的误差。但是有一个下限是任何模型都无法超越的:贝叶斯误差。贝叶斯误差是潜在问题固有的随机性的表现,这种随机性通常是相当大的。

一旦我们接近了这种贝叶斯表现,我们就很想宣布胜利并结束我们的工作。通过这样做,我们处理了冰山的可见部分。但是,我们可以做得更好,通过深入研究并建立一个模型来解决问题的不确定部分,即我们看不到的冰山区域。量化不确定性将允许我们用偏差估计修正点预测(=最佳猜测),并最终导致我们可以信赖的更好、更稳健的模型。

在本文中,我将讨论概率预测,它将点预测和不确定性建模统一在一个一致的框架中。使用概率预测模型,我们可以计算最佳猜测预测,并推导出“安全缓冲区”,共同形成明智的决策和我们的想法。让我们开始吧!

俄罗斯轮盘赌和概率论

这可能是一个有点极端的机会游戏的例子,但它是解释我将在本文中使用的概率论的一些基本概念的理想场所。如果你不熟悉这个“游戏”,我建议你参考下面的维基百科文章。

给枪装上一发子弹,旋转圆筒,扣动扳机的动作就是随机实验的一个例子。随机实验的定义属性是这样一个事实,即这种实验的每次重复可能会导致不同的结果,但结果集是预先知道的。

在俄罗斯轮盘赌中,实验有两种可能的结果:枪是否开火。将一个数学对象 Y 分配给一个随机实验的结果是很方便的。y 称为结果集的一个随机元素。(有时人们称 Y 为随机变量。)这意味着 Y =‘枪发射了’,如果那是我们扣动扳机后观察到的事件,否则,Y 的值就是‘枪没有发射’。如果你是一个程序员,你可能会认为 Y 是一个没有参数的函数,如果对它求值,它会返回实验的结果。

如果我们给枪装上一发子弹,旋转枪管,试着射击,它可能不会开火。更准确地说,枪开火的概率是⅙.让我们庆祝这个罕见的时刻:我们的直觉与事物的数学定义完全吻合。事件的概率是一个介于 0 和 1 之间的数字。零表示“不会发生”。我们给一个确定的事件分配一个。严格介于 0 和 1 之间的数字表示不同程度的“可能性”。

一个概率分布,通常用 F 表示,编码了随机实验结果的概率,或者,等价地,一个随机元素 Y 的可能值的概率。所以你可能会问 F,Y =“枪开火”的概率是多少。而 f 会给你答案:F(Y =“枪火”)= ⅙.因为 F 回答这些问题太靠谱了,所以人们有时会把 F 叫做 y 的定律

数学的任务是归纳思想并将结果应用于新问题。它通常是这样工作的:现在我们几乎知道了关于经典和古老的俄罗斯轮盘赌的一切,让我们更进一步,定义一下广义俄罗斯轮盘赌的游戏。

不如这样,我们可以用 n 发子弹,而不是只用一发子弹,然后把这 n 发子弹放进一把有 m 膛的枪里。显然,我们必须要求 n 在 0 和 m 之间,m 是正整数。(通常 m=6)。

给定一把 m=6 的枪,Y 的概率分布由我们放入枪中的子弹数 X 决定。如果 X=2(我们用两轮)呢?什么是 F(Y = "炮火")?

如果 X=2(我们用两发子弹),那么 F(Y =“枪响”)= ⅓.

换句话说,不同的 X 值产生不同的 y 定律。

广义俄罗斯轮盘赌游戏是概率分类问题的一个例子。对于输入参数 X 的不同值,我们询问结果 Y 作为 X 的函数的概率分布。结果集是固定的,对于所有 X 值都是相同的,只是这些结果的概率不同。

通常,在一个概率分类问题中,Y 的概率分布是不给出的,我们被要求以某种方式猜测或估计它。例如,给定某人签名的照片(X),我们被要求估计该签名是真实的(Y=“真实签名”)或伪造的(Y=“伪造签名”)的概率。

对于刚刚描述的两个分类问题,产生不同结果的概率比简单地给出一个最可能的结果作为答案要有用得多,典型的分类算法就是这样做的。设想一个为检查签名而建立的业务流程。初始处理步骤可能涉及概率分类算法。如果算法几乎确定签名 X 不是伪造的,即 F(Y=“真实签名”)> 0.95,我们可以将其标记为真实的。对于任何低于 0.95 的值,我们采用进一步的、更昂贵的检查来调查签名的有效性。

俄罗斯轮盘赌的例子更加清楚地阐明了这一点。任何一个“枪会开火”/“枪不会开火”的答案都不能说明问题。我们真正想知道的是那些结果概率。

战略投标

几年前,我在易贝购买了目前的笔记本电脑。这是一台二手的联想 Thinkpad,我支付的价格远远低于同类新机型的价格。二手商用笔记本电脑的市场很大,因为许多公司定期购买新硬件并淘汰旧机器。这个市场提出了一个有趣的问题。假设我们想买一台硬件参数在一定范围内的笔记本电脑。拍卖投标的最佳策略是什么,它会导致较低的购买价格?

我们可以把这种情况描述为一个回归问题。给定一台笔记本电脑的硬件参数 X(可能结合了关于笔记本电脑状态的数据和卖家的信誉评分),我们可以说这台机器的价格 Y 是多少?y 是一个随机量:它不仅由特征值 X 驱动,还由随机和不可预测的因素驱动,如用户对特定拍卖的兴趣、可能的其他正在进行的类似模型的拍卖、机器的感知价值、拍卖结束的时间等。

要想出一个最佳的投标策略,我们需要具体说明我们购买一台笔记本电脑的迫切程度。如果我们急需一台新机器,那么我们应该愿意出高价,因此出价高于 EY 的最佳猜测价格。另一方面,如果我们可以坐在那里观察市场几个星期,等待一个“异常”价格,我们应该出价大大低于点预测价格 EY。

但出价明显低于 EY 的价格意味着什么呢?要回答这个问题,我们需要了解 Y 的预测分布,并根据特定价格范围的概率重新表述我们的问题。例如,异常价格可能是以 1%的概率低于价格 q0 的价格。阈值价格 q0 是 Y 分布的分位数,也就是说,对于给定的概率 p0=0.01,我们预计平均只有 1/100 售出的笔记本电脑的价格低于 q。这个陈述相当于公式 F(Y < q0) = 0.01,其中 F 是 Y 的法则。按照同样的思路,我们可以以价格 q1 投标,这样,以概率 0.9,购买价格低于 q1。这种方法会很快导致问题的解决。

让我们强调,分位数 q0 和 q1 取决于 Y 的分布 F(其取决于特征向量 X),以及置信概率水平 p0 = 0.01 和 p1= 0.9。同样,我们可以把计算分位数 q0 和 q1 的问题看作是估计单侧预测区间 (-∞,q0】和(-∞,q1)的问题。

一旦我们有了对分布 f 的估计,这就很容易了。

许多批发市场使用拍卖作为价格发现机制,因此上述讨论也适用于许多公司。例如,在德国电力批发市场,买方和卖方都参与拍卖,拍卖的结果是前一天的价格计算。电力生产商指定价量对(p,v ),并通过这样做,设置他们愿意以不低于 p 的价格出售的电量 v(MW)。类似地,电力消费者指定价量对(p,v ),指示他们愿意以不高于 p 的价格购买的电量 v。使用拍卖机制找到一个用于所有结算交易的价格,可确保交易尽可能多的电量。符合该价格的所有订单(p,v)都被结算,其余订单被丢弃。

“M5 预测—不确定性”竞赛

Makridakis 竞赛是由预测研究人员 Spyros Makridakis 组织的一系列竞赛,旨在评估和推动适用于现实世界问题的预测方法的研究。最近,比赛的第五部分正在 Kaggle 平台上进行,ka ggle 平台在数据科学研究人员和爱好者中都很有名。

其中提出的问题是预测未来连续 28 天在 10 个选定的沃尔玛商店中三个产品类别(食品、家庭和爱好)的各种产品的销售数量。训练数据由几年来所有产品和商店组合的历史销售数字的时间序列组成。

今年比赛的一个有趣的方面是它有两种变体:预测预期的销售数量(M5 预测-准确性)和估计销售数量 50%,67%,95%和 99%的预测区间(M5 预测-不确定性)。

今年的问题似乎非常困难,不仅因为涉及的时间序列数量巨大(约 30,000),还因为提供的训练数据非常“嘈杂”。让我们来看看训练数据集中的一个时间序列示例:

商店层面的购买行为似乎非常不稳定,难以预测。很有可能是一些季节性因素(每周、每年、节假日)推动了销售数字的强度。在大多数情况下,销售数字的峰值无法用所提供的数据来解释。这是有道理的:我们的生活充满了我们不公开分享的细节。比方说,我们和我们所在地区的大约 20 个人最近看了一个烹饪节目,决定尝试烤香橼馅饼。一家出售制作这种馅饼所需原料的零售商对我们的计划一无所知,也没有任何有用的数据来解释柠檬需求的突然飙升。

从零售商的角度来看,更有用的是尽可能精确地知道未来销售数字的分布,而不是试图计算点预测。上面的例子说明了预期的销售数量对于处理不可预测的需求高峰毫无帮助。

作为零售商,我们希望我们的货架上有足够的商品来应对这些意想不到的需求高峰,并防止客户不得不在其他地方寻找他们需要的产品。另一方面,每家店的展示空间都是有限的,有些产品容易腐烂,不可能无限期保存。此外,储存易腐产品的成本通常不可忽略——想想超市里的巨型冰箱。

因此,最终,最大化客户满意度(和我们的收入)的问题是对我们提供的每种产品的需求的概率回归问题。我们可以为不同的需求场景分配概率(例如柠檬的需求高峰),并将这些场景与结果的成本影响联系起来。成本的例子包括:由于对产品的需求得不到满足而导致的收入减少,或者失去一个客户的成本。

这是一个典型的不确定情况下的决策问题。我们关注不同的有利或不利事件,将收入或成本因素与它们相关联,并优化反映业务成果的指标。

结论

在本文中,我们讨论了通过概率预测获得对数据科学问题更全面的理解。我们已经表明,许多现实世界问题的潜在部分,即不确定性,与可见的贝叶斯性能元素一样重要。揭示这种不确定性可以带来更稳健、更可信的模型,并为开发能够应对各种未来情景的战略决策系统开辟了一条至关重要的道路。

非常感谢 Sarah Khatry 阅读了这篇博文的草稿,并提供了无数的改进意见和更正。

Python 中时间序列分析和预测的概率规划和贝叶斯推理

原文:https://towardsdatascience.com/probabilistic-programming-and-bayesian-inference-for-time-series-analysis-and-forecasting-b5eb22114275?source=collection_archive---------7-----------------------

Python 中时间序列数据分析和预测的贝叶斯方法

作者照片

如[1][2]所述,时间序列数据包括来自金融、医学、科学研究(如全球变暖、语音分析、地震)等不同领域的多种真实实验数据。时间序列预测在各个领域都有很多实际应用,例如商业预测(如销售、股票)、天气、死亡等[2]。统计建模和推理(如 ARIMA 模型)[1][2]是时间序列分析和预测的流行方法之一。

有两种统计推断方法:

  • 贝叶斯推断
  • 频率主义者的推论

贝叶斯推理的哲学是将概率视为事件可信度的度量[3][4][5],并使用贝叶斯定理随着更多证据或信息变得可用来更新概率,而频率主义推理的哲学将概率视为事件的长期频率[3]。

一般来说,只有在大量数据样本可用的情况下,我们才能使用 Frequentist 推断。相比之下,贝叶斯推理可以应用于大数据集和小数据集。

在本文中,我使用 Kaggle [6]的一个小的(只有 36 个数据样本)洗发水销售时间序列数据集来演示如何使用概率编程来实现贝叶斯分析和推理,用于时间序列分析和预测。

文章的其余部分安排如下:

  • 贝叶斯定理
  • MCMC 基础知识(马尔可夫链蒙特卡罗)
  • 概率规划
  • 时间序列模型和预测[3]
  • 摘要

1.贝叶斯定理

H 为事件将发生的假设, D 为新观察到的数据(即证据),而 p 为概率,贝叶斯定理可描述如下[5]:

p(H | D) = p(H) x p(D | H) / p(D)

  • p(H):在我们看到任何数据之前,假设的先验概率
  • p(H | D):我们观察新数据后假设的后验概率
  • p(D | H):似然,假设下数据的概率
  • p(D):任何假设下数据的概率

2.MCMC 基础

MCMC 由一类算法组成,用于从概率分布中取样。广泛使用的算法之一是Metropolis–Hastings 算法。基本思想是随机生成大量代表性样本,以逼近多维连续参数空间上的连续分布[4]。

Metropolis 算法的高级描述可以表示如下[3]:

  • 步骤 1:从 n 参数空间中的当前位置(即,n 参数值的向量)开始
  • 步骤 2:建议移动到新位置(n 参数值的新向量)
  • 步骤 3:基于先前位置的先验概率、数据以及根据贝叶斯定理[3]从数据及其先验分布计算的后验概率,接受或拒绝提议的移动。
  • 第四步:如果提议被接受,那就去新的职位。否则,不要动。
  • 步骤 5:如果尚未达到预先指定的步骤数,请返回步骤 1 重复该过程。否则,返回所有接受的位置。

MCMC 的基础是贝叶斯定理。从假设和数据的给定先验分布开始,上述 Metropolis 过程的每次迭代都会积累新数据,并使用它来更新假设,以随机行走的方式选择下一步[4]。接受的步骤是假设的后验分布的样本。

3.概率规划

有多个 Python 库可用于编程贝叶斯分析和推理[3][5][7][8]。这种类型的编程称为概率编程[3][8],相应的库称为概率编程语言。PyMC [3][7]和张量流概率[8]就是两个例子。

在这篇文章中,我使用 PyMC [3][7]作为概率编程语言来分析和预测洗发水的销售[6]作为演示目的。

4.时间序列模型与预测

本节描述了如何使用 PyMC [7]对时间序列预测的贝叶斯分析和推理进行编程。

4.1 数据加载

一旦 Kaggle [6]三年洗发水销售的数据集下载到本地机器上,数据集 csv 文件就可以加载到 Pandas 数据帧中,如下所示:

df = pd.read_csv('./data/sales-of-shampoo-over-a-three-ye.csv')
df.head(12)

数据框架中的销售列可以提取为时间序列数据集:

sales = df['Sales of shampoo over a three year period']
sales.plot(figsize=(16,5))

下面这个图是三年(36 个月)洗发水的销量:

图 1: 三年(36 个月)洗发水销量。

4.2 建模

贝叶斯建模的良好开端[3]是考虑一个给定的数据集可能是如何生成的。以图 1 中洗发水时间序列数据的销售为例,我们可以从思考开始:

  • 由于数据集从左下角到右上角大致形成一条直线,因此数据集可能是由销售中带有随机误差的时间线性函数生成的。
  • 随机误差可能遵循均值为零且标准偏差未知的正态分布 std

我们知道一个线性函数由两个参数决定:斜率β和截距α:

销售 = 贝塔 x t + 阿尔法 + 误差

为了估计时间的线性函数可能是什么,我们可以将线性回归机器学习模型拟合到给定的数据集中,以找到斜率和截距:

import numpy as np
from sklearn.linear_model import LinearRegressionX1 = sales.index.values
Y1 = sales.values
X = X1.reshape(-1, 1)
Y = Y1.reshape(-1, 1)
reg = LinearRegression().fit(X, Y)reg.coef_, reg.intercept_

其中 reg.coef_ = 12.08 为斜率, reg.intercept_ = 101.22 为截距。

Y_reg = 12.08 * X1 + 101.22def plot_df(x, y, y_reg, title="", xlabel='Date', ylabel='Value', dpi=100):
    plt.figure(figsize=(16,5), dpi=dpi)
    plt.plot(x, y, color='tab:blue')
    plt.plot(x, y_reg, color='tab:red')
    plt.gca().set(title=title, xlabel=xlabel, ylabel=ylabel)
    plt.show()plot_df(x=X1, y=Y1, y_reg=Y_reg, title='Sales')

上面的代码在蓝色销售曲线上绘制了红色回归线:

图 2: 三年(36 个月)洗发水销量,回归线为红色。

回归线的斜率和截距只是基于有限数据的估计。考虑到不确定性,我们可以将它们表示为正态随机变量,将确定的斜率和截距表示为平均值。这在 PyMC [7]中实现如下:

beta = pm.Normal("beta", mu=12, sd=10)
alpha = pm.Normal("alpha", mu=101, sd=10)

同样,为了处理不确定性,我们可以使用 PyMC 将误差的标准偏差表示为在[0,100]范围内的均匀随机变量:

std = pm.Uniform("std", 0, 100)

有了随机变量 stdbetaalpha ,具有不确定性的回归线可以用 PyMC [7]表示:

mean = pm.Deterministic("mean", alpha + beta * X)

利用具有不确定性的回归线,洗发水销售时间序列数据的先验分布可以在 PyMC 中编程:

obs = pm.Normal("obs", mu=mean, sd=std, observed=Y)

使用上述先验分布作为参数(即αβstd )空间中的起始位置,我们可以使用 PyMC 中的Metropolis–Hastings 算法执行 MCMC:

import pymc3 as pmwith pm.Model() as model:
    std = pm.Uniform("std", 0, 100)

    beta = pm.Normal("beta", mu=12, sd=10)
    alpha = pm.Normal("alpha", mu=101, sd=10)

    mean = pm.Deterministic("mean", alpha + beta * X)

    obs = pm.Normal("obs", mu=mean, sd=std, observed=Y)

    trace = pm.sample(100000, step=pm.Metropolis())
    burned_trace = trace[20000:]

总共有 100,000 个被接受的步骤,称为跟踪。我们忽略前 20,000 个可接受的步骤,以避免收敛前的磨合阶段[3][4]。换句话说,我们只使用磨合期后的公认步骤进行贝叶斯推断。

4.3 后验分析

以下代码描绘了老化期后 stdalphabeta 的轨迹:

pm.plots.traceplot(burned_trace, varnames=["std", "beta", "alpha"])

图 3:STD、alpha、beta 的痕迹。

stdalphabeta 的后验分布可以绘制如下:

pm.plot_posterior(burned_trace, varnames=["std", "beta", "alpha"])

图 4:STD、alpha、beta 的后验分布。

stdalphabeta 的个别痕迹可以提取进行分析:

std_trace = burned_trace['std']
beta_trace = burned_trace['beta']
alpha_trace = burned_trace['alpha']

我们可以用任何指定的步数(如 1000)放大 std 的轨迹细节:

pd.Series(std_trace[:1000]).plot()

图 5: 放大 std 的痕迹。

同样,我们可以分别放大 alphabeta 的轨迹细节:

pd.Series(beta_trace[:1000]).plot()

图 6: 放大贝塔的踪迹。

pd.Series(alpha_trace[:1000]).plot()

图 7: 放大 alpha 的痕迹。

图 5、6 和 7 显示 stdalphabeta 的后验分布具有良好的混合频率,因此自相关性较低,这表明 MCMC 收敛【3】。

4.4 预测

可以计算出 stdalphabeta 的后验分布的平均值:

std_mean = std_trace.mean()
beta_mean = beta_trace.mean()
alpha_mean = alpha_trace.mean()
  • 标准平均值 = 79.41
  • beta_mean = 12.09
  • alpha_mean = 101.03

洗发水销售的预测可以建模如下:

Sale(t)=beta _ meanxt+alpha _ mean+误差

其中误差服从正态分布,均值为 0,标准差为 std_mean

使用上面的模型,给定任意数量的时间步长(例如 72),我们可以生成销售的时间序列:

length = 72
x1 = np.arange(length)
mean_trace = alpha_mean + beta_mean * x1
normal_dist = pm.Normal.dist(0, sd=std_mean)
errors = normal_dist.random(size=length)
Y_gen = mean_trace + errors
Y_reg1 = mean_trace

给定 36 个月的数据,下面的代码绘制了未来 36 个月(从第 37 个月到第 72 个月)的销售预测。

plot_df(x=x1, y=Y_gen, y_reg=Y_reg1, title='Sales')

图 8: 预测未来 36 个月(从第 37 个月到第 72 个月)的销售额。

5.摘要

在本文中,我使用来自 Kaggle [6]的小型洗发水【6】时间序列数据集来展示如何使用 PyMC [3][7]作为 Python 概率编程语言来实现时间序列预测的贝叶斯分析和推理。

概率编程语言的另一种选择是张量流概率【8】。我在本文中选择 PyMC 有两个原因。一个是 PyMC 比张量流概率更容易理解。另一个原因是 Tensorflow probability 正在从 Tensorflow 1.x 迁移到 Tensorflow 2.x 的过程中,缺少 Tensorflow 2.x 的 Tensorflow probability 文档。

参考

  1. Python 中常用的时间序列数据分析方法和预测模型
  2. R.H. Shumway 和 D.S. Stoffer,时间序列分析及其应用,第 4 版,施普林格,2017 年
  3. C.戴维森-皮隆,《黑客的贝叶斯方法,概率编程和贝叶斯推理》,艾迪森-韦斯利,2016 年
  4. J.K. Kruschke,《做贝叶斯数据分析》,与 R、JAGS 和斯坦合著,学术出版社,2015 年
  5. A.B .唐尼,思考贝氏,奥赖利,2013
  6. 三年内洗发水的销售额
  7. PyMC3
  8. 张量流概率
  9. Github中的 Jupyter 笔记本

用 Pyro 和厨房秤进行概率编程

原文:https://towardsdatascience.com/probabilistic-programming-with-pyro-and-kitchen-scale-f8d6a5d9ae0f?source=collection_archive---------21-----------------------

照片由来自 Pexels 的 Lum3n 拍摄

最近感兴趣的技术之一是概率规划的使用。如果你以前从未听说过概率编程,你可能会认为它只是用概率编程。这是正确的,但只是故事的一部分。

在其核心,概率规划是关于寻找潜在的分布,影响感兴趣的过程。你定义一个过程和它是如何工作的,然后让你选择的概率编程语言(PPL)来推断影响你的过程的因素的可能值,以及它们的可能性有多大。

最好用一个例子来解释这一点,对于这个例子,我将使用 Pyro 作为 PPL 的选择,以及一个简单的案例研究,主要灵感来自官方的 Pyro 示例。

构建我们的过程——神奇的厨房秤

想象你有一个厨房秤,你把一个物体放在上面,秤告诉你它的重量。但是想象的尺度相当古老,而且不是很准确。每次你把同样的物体放在上面,它会给你一个稍微不同的测量值。然而,您观察到,这种秤以某种神奇的方式产生误差,在物品的真实重量周围形成正态分布,标准偏差为 0.1 千克

让我们来描述这个过程(我们将使用 PyTorch,Pyro 使用它作为底层张量计算引擎)。

首先,我们将导入我们需要的库

让我们来定义我们的厨房秤,或者更具体地说,它用来给我们观察的过程

现在让我们问自己一个简单的问题;

“如果我们将一件 0.5 千克的物品放在秤上,我们会得到哪些可能的值?”

tensor(0.6541)
tensor(0.4707)
tensor(0.2821)

我们得到了 3 个值的集合。每次我们要求我们的秤给出答案,我们都会得到一个稍微不同的值。有时值会非常接近 0.5(大多数情况下会出现这种情况),有时会非常远。虽然这很容易实现,但就编程而言并不新鲜。

我们来试试稍微难一点的问题;

“如果我将一件重 0.5 千克的物品放在磅秤上,观察到高于 0.63 千克的值的概率是多少?”

我们也可以通过编程来回答这个问题。我们将只生成许多值,统计我们生成的所有值,统计所有大于 0.63 的值,并找出它们的比率:

rough estimate: 0.097
reasonable estimate: 0.101
good estimate: 0.09691
true estimate: 0.0968004845856103

如果我们运行这个过程足够多次,我们将得到一个对所有意图和目的都好的估计。这需要更多的工作和时间,但是总的来说这个工作流程也不是太难。

让我们试试一个更难的问题:

“我观察到一个 0.63 千克的值,该物品最可能的真实重量是多少?”

这可能会让你大吃一惊,但稍加思考后,你可能会想起你神奇的不准确但性能良好的秤报告了该物品真实重量的正态分布,因此在没有进一步信息的情况下,最有可能的重量实际上是 0.63 千克

然而,这在很大程度上是容易的,因为我们知道围绕秤的真实重量的分布是正态的。如果不正常呢?如果它甚至不是预先内置到 Python 中的东西呢?

现在让我们尝试一个难题,它将激励我们使用概率规划:

“让我们想象一下,从我们的秤中得到以下一组观察值:0.74 千克、0.98 千克、0.66 千克、0.75 千克、0.84 千克和 0.74 千克,物体最可能的真实重量是多少?”

我用来生成这些值的真实重量是 0.8 千克,但是让我们看看如何才能发现它

在 Pyro 中构建我们的流程

上一节中的问题正是概率规划要回答的问题。一般的形式是“给定一些观察,以及对过程的良好理解,我能推断出一些关于我的过程中隐藏的值或初始条件吗?”

现在我们想知道,我们的产品最可能的重量是多少。我们现在将使用 Pyro 来回答这个问题。

The mean of the observations is: 0.7850000262260437.

首先,让我们再次定义我们的过程,但是有一些变化。我们还会将函数从process重命名为model,因为这通常是 Pyro 代码的编写方式:

这可能看起来很多,所以让我们解开这个函数是如何工作的。

给定我们的观察值,我们试图找到一个可能的权重值的分布。

  • 我们首先定义这些值的先验分布,这是我们对概率分布的最佳猜测,在(1)。
  • 然后,我们从(2)的分布中取样。然而,现在这是一个命名的发行版(我们将其命名为"weight1")。这是我们告诉 Pyro 优化权重来源分布的方式。在幕后,Pyro 将修改这个分布,使之更符合我们的观察。
  • 在(3)中,我们定义了秤的工作方式。回想一下,为了进行测量,秤返回以重量为中心的正态分布值,标准偏差为 0.1。
  • 最后,在(4)中,我们从我们在(3)中定义的分布中取样。请注意,这些也是命名样本,但它们取决于观察结果。这就是我们告诉 Pyro 我们的"weight1"值与观察值的关系。

使用抽样技术估算我们的体重

现在,我们将使用我们的模型来找到一个合适的估计重量的项目,给我们的测量。我们将使用一个称为马尔可夫链蒙特卡罗(MCMC)的算法家族,以及一个称为哈密顿蒙特卡罗(HMC)的特定实例。关于 MCMC 和原始 Metropolis 采样算法的深入解释(HMC 就是建立在这个基础上的),我鼓励你去看看扎克·安临来的演讲

本质上,该算法将基于我们定义的分布影响的观察值(我们命名为"obs_{i}"的变量),构建我们命名的分布“weight1”的概率分布。

Sample: 100%|██████████| 20100/20100 [02:03, 163.05it/s, step size=1.55e+00, acc. prob=0.902]

让我们看看这里发生了什么:

  • 在(1)处,我们从我们的 Pyro 存储器中清除所有命名的样本。Pyro 使用一个特殊的、内置的、类似字典的对象来跟踪我们请求的项目的估计值。清楚这一点很重要,这样如果我们多次运行这段代码,前面的运行就不会扭曲我们的结果。
  • 在(2)和(3)中,我们定义了一种 MCMC 算法,该算法使用 HMC 实现来估计命名变量"weight1"的分布。MCMC 算法运行一定次数的迭代,在本例中为 20,100 次迭代。然而,它得出的前几个估计值对初始随机条件非常敏感,所以我们倾向于丢弃这些估计值(我们将丢弃前 100 个)。所有剩余的 20,000 个样本将用于构建我们对"weight1"的后验估计
  • 最后在(4)中,我们运行我们的 MCMC 算法。注意,我们必须将我们的观察结果发送到model函数中(因为我们之前定义它接受一系列观察结果)。这是我们将所有变量发送给model函数的地方。

现在,让我们画出估算"weight1"时得到的所有样本,将这些样本转换成一个 NumPy 数组(它们作为 PyTorch 张量返回),并绘制成直方图。

array([0.8106951 , 0.77260906, 0.79576313, ..., 0.86141765, 0.7857265 , 0.7469458 ], dtype=float32)

具有正态先验的 HMC 算法生成的权重值的样本分布

我们还可以绘制摘要,并查看该分布的平均值,以找到最可能的值以及 90%的可信区间。

 mean  std   median  5.0%    95.0%     n_eff     r_hat
weight1  0.78  0.04  0.79    0.72    0.85   29855.87     1.00Number of divergences: 0

因此,我们看到平均值约为 0.78 千克,我们 90%确信该物品的重量值在 0.72 千克到 0.85 千克之间(这也是我们判断是否对这 90%范围满意的空间)。

你现在可能会说 “嗯,你有一个很好的先验,你的平均值非常接近 0.8 公斤的真实值。如果你使用一个信息量较少的先验呢?”

让我们也来探索一下这个场景。这一次我们将使用 0.0(重量不能为负)和 2kg(看起来是一个很好的上限)之间的均匀分布。

Sample: 100%|██████████| 20100/20100 [03:20, 100.21it/s, step size=8.57e-01, acc. prob=0.978]
 mean   std   median      5.0%     95.0%     n_eff     r_hat
weight2  0.78  0.04     0.78      0.72      0.85   1059.35      1.00

Number of divergences: 0

有这样一个信息不丰富的先验并没有造成多大的不同。该算法 90%确信体重在 0.72 千克和 0.85 千克之间,并且这些值的平均值仍然集中在 0.78 千克(非常接近使用的 0.8 千克)。

我们可以再次获取这个新近似值的样本,再次将它们转换为 NumPy 数组,并将结果绘制成分布图。你会看到分布重叠得非常厉害,即使使用了两个非常不同的先验。

由具有正态先验的 HMC 算法以及具有均匀先验的 HMC 算法生成的权重值的样本分布

使用随机变分推断来近似我们的重量

如果您运行上面的代码,您会注意到使用 MCMC 方法绘制所有的样本需要相当多的时间。Pyro 提供了一种评估隐藏参数的替代方法,这种方法更快,并且可以为一些问题提供同样好的结果:随机变分推断(SVI)。

SVI 方法把这个推理问题当作一个最优化问题。在 SVI 方法中,我们选择由一些参数定义的另一种分布(例如,正态分布由其均值和标准差定义),并优化这些参数,直到我们选择的分布提供“足够接近”我们观察结果的结果。

这种评估后验概率的替代方法需要一个额外的函数,它被称为引导函数。这个函数定义了我们的参数,以及我们建议的与观察值相匹配的分布。

让我们再次定义我们的模型:

现在,让我们定义我们的向导函数:

  • 首先,向导和模型函数必须接受相同的输入,即使向导根本不使用它们中的任何一个。
  • 在(2)和(3)中,我们说取一个正态分布,并调整它的参数(平均值和标准偏差),以便它更有可能产生观察到的观察值。在(2)中,我们必须提供这些参数的初始猜测(注意pyro.param语句,它与pyro.sample不同,因为它注册的是参数,而不是分布)。
  • 在(4)中,我们从(3)中定义的分布中提取一个权重。我们实际上不需要将该值存储到 python 变量中,我们只需要与模型函数中的名称完全相同的pyro.sample语句。这只适用于未观察到的样本(没有obs=附加参数的样本)

现在这变成了一个优化问题,我们只需要优化"mu""sigma",使它们定义的正态分布更接近我们观察到的值。

iter: 9900, loss: -2.031

在执行优化之后,我们可以向 Pyro 请求找到的"mu""sigma"的值

"mu" is 0.7845805883407593
"sigma" is 0.040342673659324646

我们还可以要求与之前相同的关于“weight3”的统计数据,例如 90%的可信区间,但是我们必须为此做更多的工作。

我们需要使用我们发现的值来生成新的样本(MCMC 通过生成样本来工作,因此在算法运行之后我们不需要额外的步骤):

 weight_mean  weight_5%  weight_95%
0     0.784121   0.717712    0.850685
Run time for SVI algorithm and result extraction: 19.51 seconds

我们可以看到,我们得到的结果与使用 MCMC 模型时观察到的结果非常相似,但只是运行时间的一小部分。

SVI 方法旨在提高执行速度。但是,由于它们需要预定义的配送作为指导,因此对于某些配送(例如多式联运)来说,可能很难选择这些配送。对于可以由预定义分布近似的分布,它们是理想的,因为它们提供了实质性的性能提升。

我们还可以将通过 SVI 算法采样获得的结果分布与之前的样本进行比较:

由两种 HMC 算法生成的权重值的样本分布,以及由 SVI 算法生成的样本分布,

使用自动导向装置

我想在这里介绍的最后一个功能是在 Pyro 中使用自动引导。当构建你自己的指南是一项费力的任务时,Pyro 提供了使用预建自动指南功能的能力。

Optimizing...
iter: 9900, loss: -1.88
Parameters:
"mu" is [0.77290195]
"sigma" is [0.04055462]
Predicting...
   weight_mean  weight_5%  weight_95%
0     0.773199   0.706324      0.8403
Run time for SVI algorithm and result extraction: 23.17 seconds

我们还可以绘制这些结果,并比较两种 SVI 方法的分布:

具有自定义向导和自动分类的 SVI 算法生成的权重值的样本分布

这篇文章展示了 Pyro 在推断模型中隐藏的参数值时提供的基本功能。

我鼓励大家探讨扎克·安临来 的 演讲,讨论概率编程应用(示例使用 PyMC3 进行探讨,但现在应该更容易翻译成 Pyro),以及 Chi Nhan Nguyen 的演讲,展示如何使用 Pyro 为过度自信的神经网络引入不确定性(演讲使用 Pyro 的旧版本)。

在以后的文章中,我将探索如何将 Pyro 用于更真实的应用程序,但是当开始使用任何新的库时,一个容易理解的简单示例对于解释库的工作方式非常有用。

这篇文章的笔记本版本,请访问 这里

知识图上的概率推理

原文:https://towardsdatascience.com/probabilistic-reasoning-on-knowledge-graphs-d510269f5cf0?source=collection_archive---------36-----------------------

知识图表和推理

希望,感谢‘神话般的五人组’,会有事情发生!

戴恩·托普金在 Unsplash 上的照片

不加推理地使用知识图表就像吃了一块诱人的蛋糕,然后把它留在那里欣赏:美学上很吸引人,但浪费了美味的配料,从长远来看,毫无意义!

推理使知识图的“知识部分”成为可能,如果没有它,可以更像是一个数据库而不是知识模型。

简而言之,区别就在这里。

虽然关系数据库的中心点是用关系对现实建模、存储到表中以及用 SQL 查询感兴趣的领域,但是知识图更多的是关于类似图形的数据(而不仅仅是图形数据库中的数据)。

有了知识图,你就可以为你拥有图状数据的感兴趣的现实建模(所谓的地面扩展组件)。你可以抽象地描述这样的现实是如何运作的,即:底层业务的规则是什么,人类知道的东西是什么,但程序和数据库都不知道。最后,通过推理过程,你可以为你的图生成新的节点和边形式的新知识,即派生的外延组件,又名推理组件【1】。

关于知识图表推理的简单例子,你可以在 Medium 上查看。

到目前为止,一切顺利。

但是现实是不确定的,数据是不确定的,领域知识是不确定的,甚至我们的人脑推理过程也是被设计成不确定的。所以推理需要包含和处理各种不确定性。

因此,如果你想在知识图上进行尖端的推理,如果你想对现实进行更合理和可靠的描述,而不是一种机器人/木偶版的人类推理,你需要考虑不确定性,并将其纳入你的推理

如何在 KGs 上进行概率推理

照片由 Calum Lewis 在 Unsplash 上拍摄

在使用 KGs 的概率推理中,我们当然需要执行“概率部分”。然而,坏消息是,如果我们想明智地实现它,我们需要同时满足标准对 KGs [2]推理的要求

例如,我们不希望能够处理空值,但不能遍历图形,对吗?因此,我们需要的四种关键成分作为基本配方:

  1. 全递归

如果你想探索图形结构,至少你会期望遍历这些图形!当然不仅仅是遍历:您希望用多种算法探索图形数据,其中路径的范围和形式事先并不知道。

对于图形数据库,您可能习惯于像 Neo4J 中那样对语言进行模式匹配。这里的世界是不同的:知识图通常不做模式匹配,而是依赖于一种更强大的工具:递归。

所以,我很抱歉地告诉你,因为你想在 kg 上推理,你需要递归。

而且它必须是完全的,也就是说,我们不能摆脱许多现有形式的部分递归,因为我们想要一个我们可以编写的图形算法的完整选择。

让我们以一个基本的图问题为例,如ST-连通性(在一个有向图中询问 t 是否从 s 可达的决策问题)。它可以通过左递归来表达。但是有许多基本但重要的问题是不可能陈述的,即使用线性递归也不行。这就是为什么完全递归是必须的。

我认为仅仅了解递归是远远不够的,所以如果你同意我的观点,也读读这个或者这个,或者回到计算机科学的第一年,重读一本像这个一样精彩的书!

2。归纳(不,这不是递归了…也读成分 2!)

一种语言,或者如果你想更非正式和轻松,一个旨在推理(在知识图上)并准备进行概率推理的系统必须能够表达非基础归纳定义【3,4】。

归纳定义是就其本身给出的定义,它必须是合理的。必须有一个或多个非递归基础案例+一个或多个递归案例,最终导致回到基础案例。

非常著名的归纳定义的例子是斐波那契数列和阶乘。归纳定义最简单的例子可能是传递闭包。如果一个系统连一个二元关系的非地(仅用基格)传递闭包都做不到。这是推理的本质,因为:

如果一个系统甚至不能计算出传递闭包,你可以肯定它不会帮助你进行推理!

3。语义

推理过程必须追溯到特定的语义,即赋予内涵成分和查询答案意义的成分。

对于语义,您有许多不同的选择,在这种情况下,语言语义:稳定模型语义、有根据的语义、最少模型语义以及它们的所有变体,等等。就性能而言,它们提供了或多或少有效的推理过程。

在这种情况下,合理的选择是使用有理有据的语义

让我们来回答一个连接查询。使用稳定模型语义,解决方案的构造需要考虑满足您的内涵组件和查询的所有可能解释中出现的事实。相反,在有充分根据的语义学中,对查询的正确回答包含了任何真实解释的所有事实。就性能而言,节省是不言而喻的。

这个和其他理论基础[5]是这样的,你可以使用良好的语义开发更快的推理机,因此它是一个更好的选择!

4。本体推理

我们正在谈论推理 ok,但是它有点模糊,哪种推理?我希望有一个强大的推理版本,当然,它允许我查询我的知识图表,以获得意想不到的、新的和重要的见解!

所以,至少我们希望有本体推理,用哲学术语来说,可以被看作是“对现存事物”进行推理的能力。而在数学术语中则意味着特定运算符的存在,如包含、泛量化和存在量化等。

在计算机科学中,本体推理通常对应于系统在推理规则下支持 SPARQL (查询语言)的能力,这种推理规则被称为‘蕴涵机制’, OWL 2 QL 概要**** (语义 web 社区中一种众所周知的语言中的概念和推理规则的复合体)。

这个“轮廓”是一种工具箱,包含了推理的所有要素:只要想想它包括对称的、自反的和非自反的属性,不相交的属性,或者简单地定义类和子类。

这种模式下的本体推理也提供了出色的性能,在表达能力和计算复杂性之间有一个很好的平衡;例如,当假设查询是固定的时,在 AC0 复杂性类中。

准备工作:

由aaron Blanco Tejedor在 Unsplash 上拍摄的照片

我们刚刚看到的四种成分是基础配方:推理。但是对于高级配方,概率推理,你将需要所有'神话般的五'的共同努力。你至少需要另一个关键因素,第五个因素:现在,你必须决定你希望如何管理不确定性。

科学家们想出了最不同的方法来处理涉及不完善或未知信息的各种情况:概率论、模糊逻辑、主观逻辑、证据理论等。

如果把它保持在地面上,参考不确定性的概率论,我们可以用什么样的模型/系统对 KGs 进行概率推理?

很多人都在研究概率推理。涉及的人如此之多,以至于至少存在 三个主要的相关研究领域:概率逻辑编程、概率编程语言、统计关系学习。

为了这个目标,我花了一段时间去钻研不同的科学分支。毫无疑问,很多时间去真正理解在知识图上概率推理的最新技术水平。现在我可以向你报告我的发现了。

概率逻辑编程是一组非常好的语言,允许你定义非常紧凑和优雅简单的逻辑程序。此外,他们使用 Sato 语义,这是一种定义语义的简单而紧凑的方法。

概率编程语言是优雅的,因为它们让你可以自然地处理所有的统计分布,这对统计学家来说是如此的有吸引力和舒适。

统计关系学习允许我们使用像马尔可夫逻辑网络这样的概率图形模型,因此人们在机器学习环境中拥有的所有能力都可以立即投入使用(例如 PGM 中的概率推理)。您可以创建非常接近您感兴趣的现实的 PGM,并以最小的努力对实体和关系进行建模。

所有愉快和积极的点,没有缺点!那么,我应该追求什么呢?

所有这些技术都只关注配方的第五个成分:如何管理不确定性。但是他们几乎完全避开其他四个。

换句话说,它们提供了一种处理不确定性的特定方法,但没有知识图上推理的所有其他基本特征。

它们不适用于知识图上的概率推理。

这就好像他们研究并开发了最好的咖喱粉,有时忘记了蔬菜、鸡肉甚至火。那你怎么做咖喱呢?

图片:照片由恩里科·曼泰加扎在 Unsplash 上拍摄

注意到这一点后,我试图为绘制概率知识图做出自己的贡献,付出额外的努力,研究什么是必需的,并去杂货店购买所有必需的原料。这是我在知识图上进行概率推理的秘方。

我渴望听你的!

结论

没有推理,知识图是半生不熟的(在这里了解更多信息),处理不确定性对于原则性推理是至关重要的。然而,要做到这一点,有五个基本原则。分别是全递归、归纳、语义、本体推理、概率论。更多的现有方法忽略了这五个令人难以置信的因素中的大部分,只关注其中的一个“成分”。然而有人尝试过:这里用了所有的'神话般的五'

如果您想通过金融情报行业的真实案例了解更多关于知识图上的概率推理:

[## 金融情报推理

如何使用人工智能帮助打击有组织犯罪。

towardsdatascience.com](/reasoning-on-financial-intelligence-3e40db6c2b5)

关注我的 Medium 了解更多信息。

让我们也在 Linkedin 上保持联系吧!

参考

[1] L. Bellomarini 等人,知识图和企业人工智能:使能技术的承诺 (2019),ICDE

[2] L .贝洛玛里尼等,知识图中不确定性下的推理 (2020),RuleML+RR 2020

[3] D. Fierens 等,概率逻辑程序设计中的推理与学习加权布尔公式 (2015),《逻辑程序设计理论与实践》

[4] J. Lee 和 Y. Wang,稳定模型语义下的加权规则 (2016),KR。第 145-154 页。AAAI 出版社

[5] M. Denecker 等著,逻辑程序再探:作为归纳定义的逻辑程序 (2001),美国计算机学会译。计算机。日志。

概率导论

原文:https://towardsdatascience.com/probability-79b00c69a0e6?source=collection_archive---------45-----------------------

统计 101

通过圆周率实验定义

照片由 D 伊兰·诺尔特在 Unsplash 上拍摄

概率是一个多方面的概念;在一个小实验的帮助下,我们将尝试对他的方面给出一个完整的解释。

实验

想象一个 1x1 的盒子,里面有四分之一的圆(图 1)。半径是 1,所以面积当然是π/4。我们将尝试通过概率的不同定义来估计这一领域,提供概念的可视化和理论结论的经验证据。

图 1 —实验(作者)

经典解释

概率的一个定义,被称为经典,是从概率游戏(即轮盘赌、掷骰子、掷硬币等)的理论发展而来的。).该理论指出,在没有任何随机事件信息的情况下,或者当我们知道所有机会都是均等分布的(就像我们掷骰子一样)时,将所有事件简化为所有可能积极结果的基数是正确的,概率是比率:

一个典型的例子:我们掷一个公平的骰子,我们想知道这个数字是质数的可能性。我们知道 2、3、5 是质数,所以我们总共有 6 次机会中有 3 次“赢”(有利事件发生)。所以:

在实验中,我们建立了一个点的网格,在 0 和 1 之间均匀分布在 xy 中。这样,我们可以模拟任何事件的等效发生。什么时候一个事件是有利的?我们要估计曲线下的面积,所以任何对 E 中的 (x,y) ,这样:

是有利的事件。这个想法就是简单地计算点在 E 和点在ω。它们的比率是概率(根据定义)和曲线下面积的估计值。

在 Python 中,我们可以定义一个简单的函数:

def classic_ex(n):
    xl = []
    yl = []
    color = []
    e = 0
    for i in range(n+1):
        for j in range(n+1):
            x = 1/n * i;
            y = 1/n * j;
            if ((x**2 + y**2) <= 1):
                e = e + 1;
                color.append('blue')
            else:
                color.append('lightgray')
            xl.append(x)
            yl.append(y)

    return e/(n**2), xl, yl, color;

用 matplotlib plt 函数散点调用函数 end graph it:

e1, x1, y1, c1 = classic_ex(n);
plt.scatter(x1,y1,color=c1)
plt.set_title('p=' + str(e1))

通过用 n = (10,33,100,333)重复这个过程,我们得到了下图中的结果(图 2):

图 2-该区域的经典概率估计(作者)

可以看到,当 n 越来越大时,E(曲线下面积)的概率越来越接近 pi/4 的预期结果,这就导致了冯米塞斯的假设:

如果我们尝试的次数足够多,实验比会收敛到概率。

概率的经典定义在以下条件下成立:

  1. 这些事件是互斥的
  2. 事件的并集是可能事件ω的总和
  3. 每一个结果(事件)都被认为是同样可能的

条件 3 在某种程度上是“循环的”,因为可能性既是一种假设,也是概率度量的对象。在我们的实验中,我们强迫事件平均分布(均匀分布);在没有任何其他数据信息的情况下,在实际情况下,这并不总是一个有效的假设;我们需要概率的另一个定义。

频繁主义

在频率主义下,我们对事件的等可能性没有任何假设。相反,我们认为概率是一个随机事件的总体趋势,它会发生很多次。我们测量有利事件(计数发生)的频率,没有任何概率分布的假设。

在实验中,我们假设点是均匀分布的,但不是事件的均匀分布。这是因为我们想要模拟随机选择点的情况,这些点有助于概率的估计(曲线下的面积)。随着 N 变大,我们陷入了冯·米塞斯的假设:

在 Python 中:

def freq_ex(n):
    xl = []
    yl = []
    color = []
    e = 0
    for i in range(n):
            x = np.random.uniform(0,1)
            y = np.random.uniform(0,1)
            if ((x**2 + y**2) <= 1):
                e = e + 1;
                color.append('blue')
            else:
                color.append('lightgray')
            xl.append(x)
            yl.append(y)

    return e/n, xl, yl, color;

再次为了形象化:

e1, x1, y1, c1 = classic_ex(n);
plt.scatter(x1,y1,color=c1)
plt.set_title('p=' + str(e1))

运行 n = (100,1000,10000,100000)的实验,最后可视化我们得到的结果(图 3):

图 3——该地区的常客概率估计(按作者)

同样,估计的概率趋向于π/4 的预期结果。

为了实证检验这种集中趋势,让我们尝试另一个实验:重复频率测试 a 1000 次,并查看估计区域的分布。

在 Python 中:

ex = []
for i in range(1000):
    e1, x1, y1, c1 = freq_ex(1000);
    ex.append(e1)fig = plt.figure(figsize=(15,15))
plt.hist(ex, bins=20)
plt.vlines(np.pi/4,0,150)

我们得到(图 4):

图 4——区域估计的主要趋势(按作者)

我们看到这个奇怪的钟形曲线,它定义了概率的预期估计的分布。这条曲线决定了一个高斯正态分布,但这也是后话。现在,我们看到我们概率的中心趋势对应于π/4 曲线下的期望面积。

Kolmogorov 和公理化定义

俄罗斯数学家安德烈·尼古拉耶维奇·科尔莫戈罗夫(Andrej Nikolaevič Kolmogorov)定义了现在所谓的概率公理化解释的基础。

(来自维基百科):

设(ω, FP )为测度空间,其中 P 为某事件 E 的概率,记为 P(E)P(ω)= 1。那么(ω, FP )就是一个概率空间,样本空间ω,事件空间 F,和概率测度 P.

Kolmogorov 理论基于三个公理。让我们在实验中使用它们。

第一公理

这个公理说明事件 E 的概率总是一个正实数。

第二公理

整个样本空间的概率等于 1(这意味着至少有一个基本事件肯定发生)。

第三公理

当我们有可计数数量的互斥事件 E1E2 ,…那么事件联合的概率等于每个事件的概率之和。这个性质被称为σ-additivity,,对于有限数量的事件,他的解释很简单。对于无限多的事件来说并不相同,但这超出了本文的范围。

回到我们的实验,我们有:

E1 和 E2 是互斥的,E1 和 E2 的和等于整个ω。从 Kolmogorov 公理出发,利用集合代数,在下一篇文章中,我们将定义概率的一些基本性质。

我希望你喜欢这篇文章,并随时留下评论,关注我未来在 Medium 上的帖子。感谢大家,很快再见。

数据科学家必须知道概率分布

原文:https://towardsdatascience.com/probability-distribution-19a51fe188ab?source=collection_archive---------33-----------------------

常见的概率分布:二项式分布和正态(高斯)分布。

照片由威廉·胡克在 Unsplash 拍摄

我是一名移动应用程序的数据科学家。作为一名数据科学家,您经常会从总体中随机抽取一个样本来进行实验或分析。有了随机样本,你就可以对更大的群体进行统计推断。

例如,作为一名移动应用程序数据科学家,在一次 AB 测试中,我将随机抽取所有安装了该移动应用程序的用户,并量化用户在安装该应用程序一周后回来的概率。

我用的这个概率很可能是一个期望值,也就是一个随机变量的平均值。理解这个叫做随机变量的术语很重要。简单地说,随机变量意味着量化随机过程的结果。那么这和一篇关于概率分布的文章有什么关系呢?

一个随机变量的所有可能值的列表,以及它们的概率,称为概率分布。——假人统计要点

概率分布会因分布类型的不同而不同。我不会涵盖所有类型的发行版,但我会涵盖我认为最常见的发行版。有两种主要类型,称为离散型和连续型。我将介绍属于每种类型的概率分布。

  • 离散->-二项分布
  • 连续 - >正态分布

二项式分布

让我们首先从二项分布开始。要知道一个分布是否是二项式的,你需要确保它满足以下条件。

  • 固定数量的试验/事件—固定(n)
  • 每个试验/事件有两种可能的结果——0(失败)或 1(成功)
  • 概率 P(假)/P(真)对于每次试验都是相同的
  • 每个试验/事件都是相互独立的

注:事件和审判这两个术语可以互换。

对于二项式分布,有一个公式可以用来预测随机变量的概率,通常用变量 X. 表示

公式是:

由 Kenny Kim 在 PowerPoint 中创建的图像

回到上面陈述的条件,这里是公式的分解。

  • n =固定数量的试验/事件
  • ×成功次数= 。因此, n -x 为失败次数
  • p = 成功的概率。因此,1- p = 故障概率

另一个可能令人困惑的关键部分是公式的左边部分。

由 Kenny Kim 在 PowerPoint 中创建的图像

这意味着在 n 次试验中安排 x 次成功的方法的数量。F

让我们通过一个例子来说明这一点。

问题:

四个用户安装一个应用程序并在一周后回来的概率分布会是什么样的?

注意:我们假设每个用户一周后回来的概率是相同的。不现实。

  • p = 0.40
  • 4

回答:

为了找到概率分布,你要使用公式计算所有可能的 x (0,1,2,3,4)。

由 Kenny Kim 在 PowerPoint 中创建的图像

例子的概率分布。由 Kenny Kim 在 PowerPoint 中创建的图像

通常情况下,你永远都不需要手动计算这些,所有的工具都可以帮助你。然而,对于一名优秀的数据科学家来说,掌握您正在使用的工具的基础知识并了解其背后发生的事情是很好的。

正态分布又名高斯分布

正态分布可能是你会看到的最常见的分布之一。它有你所说的钟形分布,如下所示。实际的分布可能看起来不完全相同,但您会看到分布有一个主峰,两边是圆滑的曲线。

标记为重复使用,图片由 Kenny Kim 在 PowerPoint 中修改

它是最重要的分布之一,因为许多真实世界的实验都使用正态分布,无论是企业中的 AB 测试还是研究机构中的实验。这很大程度上是由于 中心极限定理所假设的随着样本量变得越来越大,分布将呈现正态分布。

现在让我们通过一个例子来更好地理解这种分布。我相信分布是非常简单的。

下面是正态分布的一些重要特征

  • 平均值将代表曲线的中间(峰值)
  • 这种分布通常用标准差来表示
  • 分布是对称的

注意:如果您不理解上面的一些概念,我建议您查看我的另一篇文章,它涵盖了基本的统计概念:

  • 数据科学家必须了解统计学

下图对理解正态分布的工作原理非常有帮助。

标记为可从维基共享资源中重复使用

就像二项式分布一样,正态分布也有一个公式来计算 x 的概率,但我不确定这在现实世界中有多大帮助…如果你真的想看,就去看这个视频,但我真的相信所有读者需要知道的是,在正态分布中:

  • 68.3%的数值在 1 个标准偏差内
  • 所有值的 95.4%在 2 个标准偏差内
  • 所有值的 99.7%在 3 个标准偏差内

许多公司利用两个标准差来表示一个值在统计上是显著的。我将在下一篇文章中介绍一个使用标准化正态分布公式的 z 检验或 t 检验的例子。

资源

  • 可汗学院的随机变量
  • 通过机器学习掌握概率分布

如果您有任何问题或反馈,请随时在下面留下您的问题或反馈,或者在 LinkedIn 上联系我。

中:https://medium.com/@测试操作学习

领英:https://www.linkedin.com/in/kennyk1m/

概率:从苹果到黑天鹅

原文:https://towardsdatascience.com/probability-from-apple-to-black-swan-1a8c2c6b42c0?source=collection_archive---------43-----------------------

你认为宇宙总是混乱的,难以预测的,并且“估计”在实践中是没有用的吗?

赫梅尔森·科埃略在 Unsplash 拍摄的照片

直到 20 世纪初,人们还认为宇宙是在一定的规则下运行的。大多数科学家为决定论辩护,认为一切都是可以预测的。随着牛顿的发展,许多支持决定论的观点被提出,也许直到爱因斯坦之前,这一观点从未受到质疑。其中之一是皮埃尔·西蒙·拉普拉斯在 19 世纪初提出的理论。

拉普拉斯说:“我们可以把宇宙现在的状态看作是过去的结果和未来的原因。一个在任何给定时刻都知道驱动自然的所有力量和组成自然的生物的相互位置的智力,如果这个智力足够大,足以提交数据进行分析,可以将宇宙中最大的物体的运动和最轻的原子的运动浓缩成一个公式;对于这样的智力来说,没有什么是不确定的,未来就像过去一样呈现在眼前”。

举例说明;一枚硬币的尾部或头部是一种假设,即考虑到它将出现的所有变量,它可以被找到。这些变量是钱离地面的高度,硬币的翻转速度,旋转的角度,空气中的摩擦力,风的方向和力量等。如果计算成千上万个变量,就可以知道这笔钱是有头还是有尾。这个理论后来被称为拉普拉斯恶魔。这些类型的思想是常见的,并被接受,直到爱因斯坦的物理学。

随着爱因斯坦物理学带来的新理论,牛顿物理学变得过时,在某种程度上说,决定论的方法远离了一切都是可预测的观点,概率观点开始传播。在薛定谔的实验中,他通过用他的名言“量子猫可以既是活着的也是死了的,并且可以同时在两个地方”的表达来支持概率方法,从而得到了发展。然而,一个新的时代已经进入,科学的基础已经改变。

认为用决定论者的方法预测未来是不可能的,但用概率方法预测未来的观点已经开始流行。概率方法已被用于许多科学领域,并开始进入全盛时期。到 20 世纪中后期,反对概率方法的新论点开始出现。

我们经常听到的名字就是混沌理论。混沌理论认为宇宙具有不规则(混沌)的结构。认为它在这种无序中有自己的顺序,但不可能找到这种顺序。这个理论与蝴蝶效应紧密交织在一起;“根据混沌理论,真正改变世界的是那些微小的事情。一只蝴蝶在亚马逊丛林中扇动翅膀,随后一场风暴蹂躏了半个欧洲”。它因这个例子而出名。

混沌理论的主要观点是,它试图解释由于概率方法,结果可能是不可预测的,具有非常非常小的偏差。他试图指出,被概率方法忽略的小错误实际上非常重要。

纳西姆·尼古拉斯·塔勒布在 2007 年出版的《黑天鹅:极不可能事件的影响》一书中,他强烈反对概率方法,并用黑天鹅的例子来解释。在澳大利亚被发现之前,所有的天鹅都被认为是白色的。简而言之,“所有的天鹅都是白色的”这个命题被接受了。澳大利亚被发现后,几个世纪以来被接受的所有天鹅都应该是白色的命题被颠覆了。他认为,不能用过去的信息预测的未来是完全不确定的。他想说,任何事情都可能在任何时候发生,即使是最不可能的事情也可能发生。当然,在这样做的时候,他严厉批评了发展概率方法并将其应用于现实生活问题的统计学家,甚至更进一步,暗示不需要统计学家。

从决定论到《黑天鹅》做了一个大概的讨论后,我想以我自己的看法来结束。当然,从统计学角度来看,做出完美的预测是不可能的。然而,估计近似结果在实践中是有用的。因为“生活是相似性的总和,而不是同一性的总和,没有哪一种观察是普遍的完美例子。”每个观察值都有各自独立的特征。然而,统计学关注的是相似性而不是差异,尽管存在一定的误差,但它能找到近似的结果。

由于未来是不确定的和混乱的,并不意味着它不能以可接受的误差被预测。为了给未来做一些计划,需要从今天开始做一个决定。我想用艾萨克·阿西莫夫的一句话来结束我的演讲;“当人们认为地球是平的时,他们错了。当人们认为地球是球形的时候,他们错了。但是如果你认为认为地球是球形的和认为地球是平的是一样错误的,那么你的观点比两者加起来还要错误”。

概率学习:蒙特卡罗方法

原文:https://towardsdatascience.com/probability-learning-monte-carlo-methods-6ea4f35c49c6?source=collection_archive---------24-----------------------

用三个简单的例子学习蒙特卡罗方法

图片来自 Unsplash

朋友们你们好! 欢迎来到概率学习! 在本帖中我们将看到什么是蒙特卡罗方法,它们不同的用例,以及它们在现实世界中是如何应用的。我们开始吧!

*Awesome Machine Learning Resources:**- For* ***learning resources*** *go to* [***How to Learn Machine Learning***](https://howtolearnmachinelearning.com/books/machine-learning-books/)*!* *- For* ***professional******resources*** *(jobs, events, skill tests) go to* [***AIgents.co — A career community for Data Scientists & Machine Learning Engineers***](https://aigents.co/)***.***

蒙特卡洛不是一个城镇吗?这是怎么回事?

来自 Unsplash 的蒙特卡洛图像

你问这个问题是对的。蒙特卡洛是摩纳哥的一部分,以其令人惊叹的世界级豪华赌场而闻名。如果你在这个地方走一走,你会看到数以千计的船只和令人惊叹的汽车,还有一些漂亮的酒店和顶级餐厅。

然而,这不是我们今天在这里的原因。 蒙特卡洛方法或蒙特卡洛实验 是计量经济学、机器学习和统计学中使用的工具,目的是为了获得某些问题的数值结果。为此,蒙特卡罗方法使用了我们世界的一个关键特征:R 和记忆。

啊?你这话是什么意思?我们一会儿就会看到它,但在本文的其余部分请记住这一点:

蒙特卡罗方法利用随机性获得特定问题的数值解

很棒吧?让我们看看他们是如何做到这一点的。

什么是蒙特卡罗方法?

这是一种使用推理统计来估计未知量的值的方法。蒙特卡洛的主要元素包括:

  • 总体:所有的选择或可能性。
  • 样本:该人群的子集。

蒙特卡罗背后的主要思想是,如果我们随机选择一个样本,它将表现出与从中抽取样本的总体相同的特性。如前所述,这里的关键是随机性。如果我们不采取随机抽样,就没有理由假设这个小的子集将具有与初始群体相同的性质。

此外,为了表示初始群体的属性,样本需要足够大。让我们用一个简单的例子来看看我的意思。

抛硬币模拟

来自平面图标的图标。

想象一下,我们正在向一个从未见过硬币的人解释正面和反面的游戏。游戏的目标是预测硬币落地时是正面还是反面。然而,这个游戏有一个快速捕捉:我们永远不会在硬币落地前给他们看,只会在它落地后才给他们看。

他挑尾巴,我们挑头。

我们抛一次硬币,它正面朝上。我们再扔一次,这次也是正面。我们扔第三次,它又露出了头。现在,我们这位不寻常的朋友可能认为硬币只有一个头。我们不断重复这个过程,到第 10 次翻转时,我们得到了 8 个正面和 2 个反面,如下图所示。

10 次投掷后正面和反面数量的演变。来自 Shutterstock 的硬币。

我们的朋友已经看到了尾巴也能出现,但是他相当厌烦,因为他认为硬币落在头上的机会比落在尾巴上的机会大。他不想继续玩了。我们告诉他,这只是一个运气的例子,这一切都是随机的,但他走开了,留下我们一个人。如果他能多扔几次,比如说 990 次,那么正面和反面的数量就会持平,让他对比赛更加满意…

为了说服他回来,我们编写了一个抛硬币的模拟器,向他展示正面和反面的概率完全相同,他只是运气不好。

我们准备代码,并对 2、5、10、20、50、100、500、1000、10000、100000 和 1000000 次投掷进行仿真。

结果如下面的代码片段所示:

硬币仿真笔记本

在我们 10 次投掷的模拟中,我们得到了与现实生活中我们的朋友完全相反的结果:2 个正面和 8 个反面。我们 80%的投掷都显示了同样的结果。这是否意味着如果我们投掷 10 次,有 80%的概率是正面或反面?当然不是!

正如我之前所说的,我们模拟一个事件的次数(或者人口样本的大小)必须足够大,才能真实地反映现实。在前面的片段中,我们可以看到,随着模拟次数的增加,实验结果越来越接近我们所知道的结果:50%的时间是正面,50%的时间是反面。

我们带着这个代码去找我们的朋友,给他看结果,他同意再玩一次。被蒙特卡洛救了!

前面的例子强调了蒙特卡罗是怎么一回事:对某一特定情况进行大量模拟,以便能够预测其最可能的结果。因为我们的朋友从来没有玩过正面或反面,也没有见过硬币,他可能不知道 1/2 和 1/2 的真实概率,但是,通过详尽地模拟正面和反面,我们向他证明了这一点!

让我们看看另一个例子:著名的轮盘赌。

轮盘赌游戏

来自 Flaticon 的图标。

你听过典型的短语 【赌场常胜】 ?在这个例子中,我们将使用蒙特卡罗方法解释为什么这是真的。

我们的轮盘赌游戏将按以下方式进行:我们将从 1 到 36 中选择一个数字(在我们的例子中是 7),并模拟 3 种不同的场景,在特定的旋转次数下,每次旋转持续下注 1 美元。我们将针对 2、5、10、20、100、10000 和 1000000 次旋转进行此操作。我们的轮盘没有 0 口袋,我们从不玩黑或白,只玩 7 号。

注: 如果我们也随机生成我们下注的号码,结果将是相同的,但为了简单起见,我们选择始终下注相同的号码

再一次,我们使用蒙特卡罗的优势进行解释:随机模拟游戏的结果特定次数,以了解其性质。让我们看看下面的代码片段会发生什么!

轮盘模拟

这段代码实现了我们上面描述的内容。它模拟了我们在不同的场景下对 7 号下注 1 美元。我们从 2 次旋转开始,然后到 5 次旋转,然后到 10 次,以此类推…每次模拟我们做 3 次。

正如我们所见,对于低次数的旋转,我们几乎总是输掉所有的钱。然而,在 10 次旋转中,我们幸运地获得了 260%的回报。这表明,对于少量的旋转,结果是相当不稳定的:我们可以失去一切或赢得很多。结果变化很大。

这是赌一晚上的乐趣之一,结果完全出乎意料,你可能会输(这很可能会发生),但你也可能会赢!

然而,需要观察的重要事情是随着我们旋转次数的增加,预期收益开始收敛到 0 。如果我们仔细观察,我们会发现现在结果几乎没有变化。结果不仅更接近 0,而且更接近在一起。

这才是赌场在乎的。他们不关心 20 次、50 次甚至 100 次旋转会发生什么。他们关心一百万次旋转会发生什么。他们关心每天晚上什么时候有很多人去玩和下注。

赌场总是赢。来自平板图标的图标

这里重要的一点是,对于单个玩家来说,投掷的次数很少,结果是高度可变的:他的回报率可以从-100%到非常高的数字,如 260%甚至更高。然而,随着许多玩家聚在一起玩游戏,在几天、几周、几个月的时间里,上亿次的投入,所有玩家的预期回报将是高度可预测的,并且非常非常接近于零:赌场确切地知道长期会发生什么。

所以即使一个玩家赢了,也是可以的。他们知道所有玩家的复合平均回报非常接近于零:他们不会损失任何钱,而你可能要支付门票、饮料、演出的费用,并在其他游戏上输掉你的钱。

让我们看最后一个最后一个例子如何使用蒙特卡罗来估算某个平面形状的面积。

周长的面积:

我们要用蒙特卡罗方法的最后一件事,是估计某个形状内部的面积,在我们的例子中是一个圆周。

来自平板图标的图标。

具体来说,我们要用它来计算一个正方形和一个圆形的面积之间的关系。我们得到了下图:

我们有一个边长为 L 的正方形,周长为 L/2

我们知道正方形的面积是 L 乘以 L,但是,我们完全不知道圆的面积。然而,我们听说过蒙特卡罗方法,并设计了一个程序来使用这个统计工具计算它!

我们要做的是在正方形内随机生成点,在模拟结束时,计算我们在圆内得到的点的总数,以及生成的点的总数,并用它来计算圆内的面积。为了简单起见,我们将使用一个大小为 L = 1 的正方形。

以下代码显示了为发现圆的面积而实现的蒙特卡罗模拟:我们随机生成形状右上象限的点,并使用已知的正方形面积、落入圆内的点数以及生成的总点数,精确计算圆的面积。

模拟计算圆的面积

在下图中,您可以看到一个接一个生成的图像。它展示了蒙特卡洛的魔力。使用随机生成的点,我们画一个圆,随着我们运行更多的模拟,我们变得越来越精确。我们生成的随机点越多,我们的模拟就越好。我们可以在前面的代码中看到,随着模拟次数的增加,圆的估计面积变得越来越接近真实面积。

随着我们进行越来越多的模拟,圆的形状也在演变。

酷吧?蒙特卡罗可用于获得令人惊叹的数值结果的另一种情况。这也可以用来计算我们想要的任何奇怪形状的面积。

结论

通过三个非常简单的例子,我们对蒙特卡洛方法或蒙特卡洛实验有了一种直觉。这些方法的关键要素,被一遍又一遍地重复:随机抽样。这篇文章中展示的例子是这些统计方法的非常简单的应用,然而它们可以用于许多其他领域,如物理学、人工智能或市场营销。

点击这里查看我的其他概率学习帖子:

  • 概率学习:贝叶斯定理
  • 概率学习:贝叶斯定理如何应用于机器学习
  • 概率学习:最大似然
  • 概率学习:贝叶斯背后的数学
  • 概率学习:朴素贝叶斯
  • 概率学习:隐马尔可夫模型

我强烈建议你阅读它们,因为它们很有趣,充满了关于概率机器学习的有用信息。

就这些,我希望你喜欢这个帖子。请随时在 Twitter 上关注我,地址: @jaimezorno 。还有,你可以在这里 看看我在数据科学、统计学、机器学习的帖子。好好读!

概率必备

原文:https://towardsdatascience.com/probability-must-haves-f5e44e2bf88d?source=collection_archive---------93-----------------------

由安卡在 pixabay.com

理解随机事件

客户和您的应用

假设你有一个用户点击行动号召的随机可能性(从现在开始我称之为 CTA,但这是你邀请读者购买、购物、发送电子邮件等的任何时候。)在您的应用程序中。一旦他们点击了行动号召,随后他们可能会点击提交按钮发送他们的电子邮件信息(在这种情况下)。

现在让我们分配一些概率…点击 CTA: 50%的可能性和提交按钮:10%的可能性。

现在我们的问题是,在这些事件发生之前,两个 T2 事件发生的可能性有多大?

重温经典的概率例子:骰子

现在你可能已经看过了,所以至少这是一个很好的复习。

首先,让我们回答以下问题:掷出两个连续的 6 的概率是多少。

对于你的第一次掷骰子,你可以用以下方式掷骰子:1–2–3–4–5–6。总的来说,你有六个选择。

明显?是的,是的,但是现在我们在这一点上思考得更为关键。如果你掷 1,你的下一个选择是什么?嗯,它是下列任何一个数字:1–2–3–4–5–6。如果你掷了一个 2,你在第二次掷骰子时会有同样的 6 个选项。在这种情况下,你的第二次投掷有 6 个选项。总之,这给了我们 36 (6*6)种不同的结果。

那么回到问题…你连续掷出两个 6 的可能性有多大?

如果我们掷骰子,第一次落在 6 点的可能性是 1/6。一旦发生这种情况,我们又有 1/6 的可能性。在所有 36 种不同的两次掷骰子的组合中,只有一种是连续掷出两次 6。这个问题的数学方法是简单地将两个概率相乘,给你 1/36 的可能性,你会连续掷出两个 6。

回到应用程序示例

让我们将刚刚学到的知识应用到我们最初的例子中。如果用户有 1/2 的机会点击 CTA,并且有 1/10 的机会点击提交按钮;然后我们可以把我们的概率相乘,说有 1/20 或 5%的几率他们会同时按下两个按钮。

抛开理论,让我们写一些代码

在此作序;如果你没有看过我关于统计推断的中型帖子,我详细介绍了rbinom函数:https://towardsdatascience . com/an-introduction-to-binomials-inference-56394956 E1 a4。为了让您快速了解这一点的重要性,您可以使用这个函数来模拟随机发生的二项式事件。

让我们要求两者都使用…和

我们有 5000 张该事件的抽签图,以及相应的概率。我们将看到 5000 个 1 或 0 的平局。当我们指定&时,我们实际上是在说两者都必须为真。当我们对这两种情况的发生率取平均值时,就给出了这两种情况都发生的概率。

CTA <- rbinom(5000, 1, .5) 
SUBMIT <- rbinom(5000, 1, .1) 
mean(CTA & SUBMIT)

我们可以重复这个过程,无论需要多少步骤。从上面我们可以看到,有 5%的时间两种行为同时发生。

从和到或

让我们回到骰子的例子。假设不是两次都是 6 的可能性,而是我们想要计算两次掷骰中任何一次都是 6 的概率。

概念方法

思考这个问题的方法是从它们的独立可能性开始。任何一个都有 1/6 的几率被碾压。我们把这两个 1/6 的可能性加起来。差不多了…但是有一个问题…1/6+1/6 也隐含着一组事件,其中都会发生- 都是这里的关键词。那些事件必须被揭露出来!

这就是我们迄今为止所学知识的汇集之处。

我们将把概率加在一起,然后我们将减去两者的概率。也就是 1/6*1/6。

数学方法

这给了我们一个公式 1/6+1/6–1/6 * 1/6

纲领性方法

让我们像之前一样复制这个。

roll_1 <- rbinom(5000, 1, .17) 
roll_2 <- rbinom(5000, 1, .17)round(mean(roll_1 | roll_2),2) .17 + .17 - .17*.17

上面你会看到一些和我们第一次看到的非常相似的东西——唯一的区别是OR或者|操作符。我们可以看到,当我们生成许多随机事件时,我们在随机生成的数据集中有 31%的发生率。我们能够通过执行我们刚刚得出的简单等式来复制这个数字,验证这两种方法是一致的。

从条件句到条件句

假设你要模拟五个人来到你的网站,点击或者不点击 CTA,两种结果都有 50%的可能性。与我们之前所做的类似,我们将模拟 5 人组整整 50,000 次。

CTA <- rbinom(50000, 5, .5) 
mean(CTA)

您可以看到每次试验或模拟中点击 CTA 的次数。当我们取 CTA 的平均值时,我们看到每个试验的平均值为 2.5,这代表了每个试验中 5 的 50%。

既然我们已经走到这一步,假设您想了解 5 个用户中至少有 2 个会点击 CTA 的概率,那么让我们对 5 个中的 3 个,然后 5 个中的 4 个做同样的事情。

mean(CTA >= 2) 
mean(CTA >= 3) 
mean(CTA >= 4)

当你插入这个值为真或假的条件语句时。我们的 mean 函数将 TRUE 视为 1,将 FALSE 视为 0,这样我们就可以获取语句为真时的平均出现次数。

我们现在可以用 OR 和 and 来利用这个想法。

结论

我们在很短的时间内访问了许多想法,我希望这个概率基础的分解是有帮助的!请务必查看我在 datasciencelessons.com 的博客,了解更多信息!

一如既往,祝数据科学快乐!

彩票中奖概率

原文:https://towardsdatascience.com/probability-of-winning-the-lottery-9331080952c4?source=collection_archive---------4-----------------------

使用 Python 来确定你的成功几率

图片由来自皮克斯拜的杰奎琳·马库拍摄

你有没有想过如果你中了彩票,你的生活会有多大的不同?彩票似乎是许多人梦寐以求的快速致富计划。据 ABC 新闻报道,强力球在 2016 年达到了惊人的【15.86 亿美元(强力球)

显然,要赢得最终的百万或十亿美元的头奖,你必须挑战巨大的赔率。据评论期刊报道,以下事件发生的几率比你中彩票的几率高。

  • 被陨石压碎
  • 成为下一个沃伦·巴菲特
  • 热自来水致死
  • 成为美国总统

在 Unsplash 上由 Srikanta H. U 拍摄的照片

假设我们的彩票结构是每次从 1-49 的数字池中抽取 6 个数字。如果你不熟悉彩票的工作原理,选择六个号码的顾客必须得到与中奖号码完全相同的号码。如果有一个数字不同,他们就不会赢得大奖。

首先,我们需要创建一些函数。

阶乘函数:

正整数 n 的阶乘,用 n 表示!,是所有小于等于 n 的正整数的乘积:比如 0 的值!是 1,按照惯例为空产品。

def **factorial**(n):
    final_product = 1
    for i in range(n, 0, -1):
        final_product *= i
    return final_product

组合功能:

组合 区域从集合中选择项目,这样选择的顺序就无关紧要了。如果你想了解更多,这里的是一本好书。

def **combinations**(n,k):
    numerator = factorial(n)
    denominator = factorial(k) * factorial(n-k)
    return numerator / denominator

单张彩票功能:

现在我们来计算一下购买的单张票的中奖概率。

def **one_ticket_probability**(numbers):
    total_outcomes = combinations(49, 6) 
    successful_outcome = 1 / total_outcomes 
    probability_winning = (successful_outcome / total_outcomes) *100
    print(f"You're chances of winning are {probability_winning}%!")

需要注意一些重要的事情,

  1. total_outcomes —使用我们之前制作的组合公式,传入可能的数字总数 49 和选项数量 6
  2. successful_outcomes —正如前面提到的,只有一个赢家,所以只有一张票赢。

正好有 13,983,816 个赢的机会(total_outcomes),

如果我们在为一张票选择的 6 个数字样本上运行这个函数,我们将得到以下结果。

test_ticket = [1,4,32,38,5,18] #random numbers
**one_ticket_probability**(test_ticket)

输出:

"你赢的几率是 0.00000000005113857220%!"

“选择乐观,感觉更好。”

达丨赖喇嘛

买多张票会怎么样?如果你批量购票,你的胜算会大多少?

来自 Pixabay 的 Alejandro Garay 的图片

多张彩票功能:

def **multi_ticket_probability**(n_tickets_played):
    total_outcomes = combinations(49, 6)
    successful_outcome = n_tickets_played / total_outcomes
    probability_n_tickets = (successful_outcome / total_outcomes) *100
    **combinations_simplified = round(total_outcomes / n_tickets_played)   
    print('''*Your chances to win the big prize with {:,} different tickets are 1 in {:,} chances to win.*'''.format(n_tickets_played,combinations_simplified))**

如您所见,我保留了与 single_ticket 函数相同的主要代码块,但是现在我添加了代码来简化组合。我还在末尾添加了字符串格式,以帮助生成更具可读性的输出。

让我们使用各种票金额和一个 for 循环来测试代码。

ticket_quantity = [1, 10, 100, 10000, 1000000, 6991908, 13983816]for tickets in ticket_quantity:
    multi_ticket_probability(tickets)
    print("""
    ----------------------
    """)

输出如下所示。

Your chances to win the big prize with **1** different tickets are **1 in 13,983,816** chances to win. ----------------------

Your chances to win the big prize with **10** different tickets are **1 in 1,398,382** chances to win. ----------------------

Your chances to win the big prize with **100** different tickets are **1 in 139,838** chances to win. ----------------------

Your chances to win the big prize with **10,000** different tickets are **1 in 1,398** chances to win. ----------------------

Your chances to win the big prize with **1,000,000** different tickets are **1 in 14** chances to win. ----------------------

Your chances to win the big prize with **6,991,908** different tickets are **1 in 2** chances to win. ----------------------

Your chances to win the big prize with **13,983,816** different tickets are **1 in 1** chances to win.

不出所料,我们可以看到随着购票数量的增加,中奖几率也在增加。最后一行显示,如果我们购买 13,983,816 的股票,我们有 100%的机会获胜,因为我们之前计算过,可能的结果总数是 13,983,816

理解计算彩票概率的过程和代码结构是深入数据科学世界获得无限可能性的垫脚石。

使用概率的其他令人兴奋的方法是什么?

"一个行为的后果影响着它再次发生的可能性."

  • B. F .斯金纳

用 Python 解释概率抽样方法

原文:https://towardsdatascience.com/probability-sampling-methods-explained-with-python-4c0a19a59456?source=collection_archive---------18-----------------------

概率和统计用 PYTHON

所有数据科学家都必须知道的四种采样方法

丘拉斯奎拉·马丁斯在拍摄的照片

为什么我们需要取样?

当我们试图在不知道总体的情况下得出结论时,就会用到抽样。总体指我们想要研究的观测值的完整集合,而样本是目标总体的子集。这里有一个例子。去年 7 月 15 日至 31 日进行的盖洛普民意调查发现,42%的美国人认可唐纳德·特朗普作为总统处理工作的方式。结果是基于对大约 4500 个电话的随机抽样的电话采访(假设每个电话有一个成年人)。约 4500 名成年人),年龄在 18 岁及以上,居住在美国。该民意调查是在特朗普的社交媒体评论引发争议期间进行的。对于这项调查,人口是所有 18 岁以上的美国公民,样本是 4500 名成年人。

如果取样不当,将会导致偏差,影响您的研究/调查结果的准确性。为了避免选择偏差,我们必须仔细选择一个能够代表整个群体的子集。

概率抽样的类型

简单随机抽样

作者使用 Powerpoint 制作的图片

简单随机抽样是指我们从总体中随机选择样本,其中每个单元被选中的概率相同。

优点:在随机选择群体成员之前,没有必要将群体分成子群体或采取任何其他额外的步骤。

缺点:样本可能不具有代表性,对于大量人群来说,这可能很耗时。

用例:在我们不太了解人群的情况下使用。

#let's create a dataframe first!
import numpy as np
import pandas as pd
from numpy.random import randn
# Define total number of customers
number_of_customers = 10
# Create data dictionary
data = {'customer_id':np.arange(1, number_of_customers+1).tolist(),
       'customer_life_time_value':randn(10)}
# Transform dictionary into a data frame
df = pd.DataFrame(data)
# View data frame
df

创建了数据框(图片由作者提供)

#only using random(), we can generate 4 samples from this dataset
# Obtain simple random samplesimple_random_sample = df.sample(n=4).sort_values(by='customer_id')
simple_random_sample

随机选择的客户(图片由作者提供)

分层抽样

作者使用 Powerpoint 制作的图片

对于分层抽样,人口被分成若干小组(称为阶层),然后从每个阶层中随机选择样本。

优点:它捕捉了关键的人口特征,因此样本更能代表人口。

缺点:如果不能形成子群,就无效。

用例:它通常用于地理采样,其中层可以是州、国家或生态区域。

#Let's add subgroup labels to the datasetdf['strata']=[0, 0, 0, 1, 1, 1, 1, 1, 2, 2]sss = StratifiedShuffleSplit(n_splits=5, test_size=0.5, random_state=0)for x, y in sss.split(df, df['strata']):
    stratified_random_sample = df.iloc[y].sort_values(by='customer_id')
stratified_random_sample

从每个阶层中随机选择的客户(图片由作者提供)

巢式抽样法

作者使用 Powerpoint 制作的图片

对于整群抽样,总体被分成不同的群。然后随机采样固定数量的群,并且每个所选群内的所有单元都包括在样本中。

优点:它减少了可变性,并且易于实施。

缺点:采样时有可能引入偏差。

用例:当每个聚类中的所有个体都可以代表总体时使用。

#create 4 different clusters based on customers' lift time valuesdf['cluster'] = pd.cut(df['customer_life_time_value'], bins=4, labels=False) +1

增加了“集群”栏(图片由作者提供)

# predefine which clusters/groups we want to select samples fromn=[2,4]def clustering_sampling(df,n):
    df_list=[]
    for i in range(len(n)):
        df1=df[df['cluster']==n[i]]
        df_list.append(df1)
    final_df=pd.concat(df_list, ignore_index=True)

    return final_dfclustering_sampling(df,n)

从样本中的聚类 2 和聚类 4 中选择所有客户(图片由作者提供)

系统抽样

从人群中选择每一个人(图片由作者使用 Powerpoint 制作)

通过从样本框架中系统地选择单元来抽取系统样本。(即每隔一个单位包括在样本中)

优点:可以消除聚类选择,执行起来很简单。

缺点:我们需要预先确定估计的人口数量。如果人口有一种标准化的模式,那就不好用了。

用例:当相关数据不呈现模式时使用。

def systematic_sampling(df, step):

    indexes = np.arange(0,len(df),step=step)
    systematic_sample = df.iloc[indexes]
    return systematic_sample

systematic_sampling(df, 1)

示例中包含所有其他 customer_id(图片由作者提供)

参考

  1. https://news . Gallup . com/poll/262694/latest-trump-job-approval-rating . aspx
  2. https://www.investopedia.com/

用 Python 进行概率采样

原文:https://towardsdatascience.com/probability-sampling-with-python-8c977ad78664?source=collection_archive---------7-----------------------

概率和统计用 Python

了解取样方法

图片由国家癌症研究所提供,可在 Unsplash 获取

介绍

什么是抽样?

抽样是从已知总体中选择随机数量单位的过程。它允许基于这些单位(即样本)的统计数据获得关于群体的信息并得出结论,而不需要研究整个群体。

为什么要用抽样?

执行采样有多种原因,包括:

  • 由于人口规模而无法研究全部人口的情况
  • 取样过程涉及样品破坏性试验的情况
  • 有时间和成本限制的情况

取样技术

有两种类型的采样技术:

  • 概率抽样:给定人群中的每个单位被选中的概率相同的情况。这种技术包括简单随机抽样、系统抽样、整群抽样和分层随机抽样。
  • 非概率抽样:来自给定群体的单位不具有相同的被选中概率的情况。该技术包括方便抽样、定额抽样、判断抽样和滚雪球抽样。与概率抽样相比,这种技术更倾向于以不具有代表性的样本组结束,从而导致关于总体的错误结论。

对于以下示例,让我们使用概率抽样从一组 10 个产品中获取样本,以确定感兴趣的特定度量的总体均值。让我们来看看 Python 代码:

产品数据框架

简单随机抽样

顾名思义,简单随机抽样方法从过程或总体中选择随机样本,其中每个单元被选中的概率相同。这是最直接的概率抽样方法。

简单随机抽样

简单随机样本

系统采样

系统采样方法根据固定的采样间隔选择单元(即每第 n 个单元从给定的过程或总体中选择)。这种抽样方法往往比简单的随机抽样方法更有效。

系统抽样

系统抽样

整群抽样

整群抽样方法将人口分成大小相等的群 n 并每 T 次选择一个群。

巢式抽样法

聚类样本

分层随机抽样

分层随机抽样方法将人口划分为子群(即阶层),并选择随机样本,其中每个单元被选中的概率相同。

分层随机抽样

产品数据框架

分层随机样本

衡量每个产品组的平均值

每种取样方法的测量平均值比较

使用每种抽样技术获得样本后,让我们将样本平均值与总体平均值(通常是未知的,但在本例中并非如此)进行比较,以确定能够获得总体测量平均值最佳近似值的抽样技术。

每个取样方法表的测量平均值比较

根据每个抽样方法表的测量平均值比较,通过简单随机抽样技术获得的样本的测量平均值最接近真实平均值,绝对误差为 0.092 个单位。

总结想法

抽样是从样本中得出总体结论的一种有用而有效的方法。然而,分析师和工程师必须定义具有足够样本量的采样技术,能够减少采样偏差(例如,方便采样选择偏差、系统采样选择偏差、环境偏差、无响应偏差),以获得给定人群的代表性样本。

如果你觉得这篇文章有用,欢迎在 GitHub 上下载我的个人代码。也可以直接发邮件到rsalaza4@binghamton.edu找我,在LinkedIn找我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 简介 来探索我以前的文章。感谢阅读。

——罗伯特

数据科学是关于概率的

原文:https://towardsdatascience.com/probability-theory-in-data-science-bacb073edf1f?source=collection_archive---------11-----------------------

与数据科学数学混淆?这里是一个开始的好地方

数据科学中最常用的 4 种概率分布

卢克·切瑟在 Unsplash 上的照片

P 概率分布是各种现实生活应用中最常用的数学概念之一。从天气预测到股票市场,再到机器学习应用,不同的概率分布是所有这些应用以及更多应用的基本组成部分。如果你想进入数据科学的神奇世界,或者你已经在这个领域,了解概率论的基本知识和最常见的概率分布是必备的知识。

从统计学上来说,我们中的任何一个人出现在这里的概率是如此之小,以至于你会认为仅仅存在的事实就能让我们所有人都沉浸在惊喜的喜悦中——刘易斯·托马斯

概率论基础

概率论是一门成熟的数学分支,研究我们生活中的不确定性。在 PT 中,一个 实验 是任何可以通过实验重复的过程,并且有一组众所周知的不同结果。一个例子是掷骰子;我们可以重复这个实验,骰子可以落在六个不变的面上。每个实验都有一个 样本空间 代表该实验所有可能的结果。在掷骰子的情况下,我们的样本空间将是{1,2,3,4,5,6}。最后,实验的每一次尝试都被称为一个 事件

理论概率与实验概率

理论上,我们可以使用以下公式计算每种结果的概率:

如果我们考虑掷骰子的例子,骰子落在六个面中任何一面的概率是 0.166。如果我想知道骰子落在偶数上的概率,那么它将是 0.5,因为在这种情况下,期望的结果是{2,4,6}在整个样本空间{1,2,3,4,5,6}之外。

所有可能结果的概率总和应该总是等于 1。

从外部来看,任何结果的概率都可能与理论上的略有不同;然而,如果我们将实验重复足够的次数,那么实验概率将接近理论概率。

我们可以编写简单的 Python 代码来证明理论概率和实验概率之间的差异。

运行这段代码的结果将接近:

probability of 1 is 0.16
probability of 2 is 0.15
probability of 3 is 0.18
probability of 4 is 0.12
probability of 5 is 0.18
probability of 6 is 0.21
 — — — — — — — — — — — — — — — 
probability of 1 is 0.16
probability of 2 is 0.179
probability of 3 is 0.168
probability of 4 is 0.162
probability of 5 is 0.154
probability of 6 is 0.177

如你所见,我们的试验越多,我们就越接近理论概率值。

随机变量

随机变量(RV)的值由随机实验的结果决定。回到我们掷骰子的例子,如果我们定义一个随机变量 X 为任何结果的概率,那么 P(X=5) = 0.166。

随机变量有两种类型:

  • 离散随机变量:可以取可数个不同值的随机变量,如可能的结果或掷骰子。
  • 连续随机变量:在一个区间内可以取无穷多个值的随机变量,如东京八月任何一天的温度。

概率分布

迈克尔·迈耶在 Flickr 上的任务估计/概率分布

概率分布只是特定随机变量的数据或分数的集合。通常,这些数据集合是按照一定的顺序排列的,并且可以用图形显示。每当我们开始一个新的 DS 项目时,我们通常会获得一个数据集;该数据集代表来自更大数据集人群样本。使用这个样本,我们可以尝试在数据中找到独特的模式,这些模式可以帮助我们对主要的查询主题做出预测。例如,如果我们想从股票市场购买一些股票,我们可以从特定公司的最近 5~10 年中获取一个样本数据集,分析该样本并预测股票的未来价格。

分布特征

数据分布有不同的形状;这些形状是根据用于绘制分布的数据集定义的。每个分布都可以用三个特征来描述:均值、方差和标准差。这些特征可以告诉我们关于分布的形状和行为的不同事情。

  • 的意思是:

作者使用 Canva

平均值(μ)就是一组数据的平均值。例如,如果我们有一组离散数据{4,7,6,3,1},则平均值为 4.2。

  • 差异

作者使用 Canva

方差(var(X))是平均值的平方差的平均值。例如,如果我们有来自{4,7,6,3,1}之前的相同数据集,那么方差将是 5.7。

  • 标准偏差

作者使用 Canva

标准差(σ)是对数据集数量分布程度的一种度量。因此,较小的标准偏差表示值彼此更接近,而较大的标准偏差表示数据集值分散。

均值、方差和标准差的属性

  1. 如果数据集中的所有值都相同,则标准差等于 0
  2. 如果数据集的值已经移位(从所有值中增加或减去一个常数),则均值增加或减少移位量,而方差将保持不变。例如,如果我们将数据集移动 3,那么平均值将增加 3。
  3. 如果数据集的值已经被缩放(乘以一个常数),则均值将被缩放相同的因子,而方差将被缩放因子的绝对值。例如,如果我们将数据集缩放 3 倍,那么平均值也将缩放 3 倍。然而,如果我们将它缩放-3,则在两种情况下,平均值将缩放-3,而方差将缩放 3。

4 种最常见的分布

有许多不同的概率分布。其中一些比另一些更常见。在本文中,我们将讨论数据科学中最常用的五种。

正态分布

作者使用 Canva

高斯分布(正态分布)以其钟形而闻名,是数据科学中使用最多的分布之一。此外,许多现实生活中的现象遵循正态分布,如人的身高、机器生产的东西的大小、测量误差、血压和考试分数。

正态分布特征

作者使用 Canva

正态分布的主要特征是:

  • 该曲线在中心对称,这意味着它可以围绕平均值分成两个对称部分。
  • 因为正态分布是一种概率分布,所以分布曲线下的面积等于 1。

当处理正态分布时,有一个重要的规则。这叫做68,95,99 法则。该规则规定,正态分布中 68%的数据在-σ和σ之间,95%的数据在-2σ和 2σ之间,99.7%的数据在-3σ和 3σ之间。

各种机器学习模型被设计成在遵循正态分布的数据集上工作,例如高斯朴素贝叶斯分类器、线性和二次判别分析以及基于最小二乘的回归。此外,我们可以将非正态分布的数据集转换为正态分布的数据集,使用一些数学转换算法,如对原始数据求平方根、求逆或自然对数。

使用 Python 生成正态分布。

指数分布

指数分布是正态分布的推广。因此,它也被称为广义正态分布。然而,指数分布还有两个因子λ,它代表正的比例参数(挤压或拉伸分布)和κ,它代表正的形状参数(改变分布的形状)。此外,指数分布不考虑不对称数据,因此,它更像是一种偏斜的正态分布。

二项分布

作者使用 Canva

二项式实验是一种统计实验,其中二项式随机变量是二项式实验的 n 次重复试验的成功次数 x。二项随机变量的概率分布称为二项分布。

二项分布的条件

  1. 它是由独立试验组成的。
  2. 每次试验可以分为成功或失败,其中成功的概率是 p ,而失败的概率是 1-p
  3. 它有固定的试验次数(n)。
  4. 每次试验成功的概率是不变的。

现实生活中二项分布的例子是:如果一种全新的药物或疫苗被引入来治愈一种疾病,它要么治愈该疾病(成功),要么不治愈(失败)。再比如:买彩票,要么中奖,要么不中奖。基本上,任何你能想到的有两种可能结果的事情都可以用二项分布来表示。

考虑二项分布的一种方式是,它们是有限正态分布的离散版本。正态分布是二项分布的多次连续试验的结果。

使用 Python 生成二项分布。

伯努利分布

伯努利分布是二项式分布的一个特例。这是一个只有一次试验的二项分布。

均匀分布

作者使用 Canva

均匀分布,也称为矩形分布,是具有恒定概率的概率分布,例如掷硬币或掷骰子。这种分布有两种类型。基本统计中最常见的类型是连续均匀分布(形成矩形)。第二类是离散均匀分布。

用 Python 生成均匀分布。

泊松分布

作者使用 Canva

泊松随机变量满足以下条件:

  1. 两个不相交时间间隔内的成功次数是独立的,成功次数的平均值是μ。
  2. 在小时间间隔内成功的概率与时间间隔的整个长度成比例。

泊松分布存在于许多现象中,如先天性残疾和基因突变、车祸、交通流量以及页面上的打字错误数量等。此外,泊松分布被商人用来预测一年中某一天或某一季节的购物者人数或销售额。在商业中,如果产品没有售出,库存过多有时会意味着损失。同样,库存不足也会导致商业机会的损失,因为您无法最大限度地提高销售额。通过使用这种分布,商界人士可以预测需求何时会很高,这样他们就可以购买更多的股票。

使用 Python 生成泊松分布。

还有更多的发行版;然而,了解这四个发行版会让你更顺利、更舒服地进入数据科学。

概率与赔率

原文:https://towardsdatascience.com/probability-vs-odds-f47fbc6789f4?source=collection_archive---------3-----------------------

有什么区别?用一个简单的例子来学习它,永远不要忘记它!

图片来自 Unsplash

许多人认为他们知道什么是概率,也认为他们对什么是赔率有完美的理解:他们一直被用于赌博。

但他们真的这样吗?这两个术语很容易混淆。

在这篇文章中,我们将很快阐明它们是什么,它们的区别,以及它们之间的关系。

我们走吧!

什么是概率?

在我们的日常语言中,当我们说“我不这么认为”或“这不太可能”时,我们总是会用到概率。概率,在一个不严谨的描述中,可以定义为我们对世界事物的相信程度的度量

我们可以通过计算事件的结果来计算概率。例如,如果我们考虑一个掷硬币游戏,其中我们选择正面,因此想要计算有利结果的概率,即预期结果可能出现的次数除以可能结果的总数。

对于我们的例子,这可以用下面的术语来描述。

获得正面的概率。图片作者。

在某些情况下,统计事件的结果既有用又简单,就像前面的例子一样。然而,很容易看出,当有许多多重组合和可能的结果时,这种技术变得不可行,因为它不适用于大范围的现实生活问题

例如,你能用前面的方法来回答下面的问题吗?

  • 明天下雨的可能性有多大?
  • 你认为皇家马德里赢得冠军联赛的机会有多大?
  • 你认为我们会有时间停下来买个冰淇淋吗?

正如你所看到的,如果跳过二元选项(是或否,或 0 和 1),并试图在两者之间选择一些东西(一种可能性),准确回答这些问题就不那么容易了。然而,我们可以通过使用赔率并将概率表示为信念的比率来做到这一点。

让我们看看如何!

使用赔率来计算概率

正如我们刚刚看到的,我们需要一种有效的方法来计算更一般情况下的概率。为了展示我们如何利用 odds 做到这一点,考虑下面的例子:

想象一下,你和一个朋友正在讨论谁是更好的跑步者。你最近训练很多,过去你总是击败他,老实说,自从他开始频繁外出后,他的状态不是很好。

你如何量化你在比赛中一定会赢他的信念?很多时候,我们通过打赌来做到这一点:我跟你赌 5 美元,我会在一周内的比赛中打败你。如果你赢了,我给你 10 英镑。你说。

从概率上讲,这意味着什么?由于这是一场只有两种可能结果的比赛,你要么赢,要么输,赢和输的概率总和必须始终为 1,如下图所示:

所有概率的总和必须始终为 1。图片作者。

此外,你的声明说,如果你赢了,你会得到 5 美元,如果你输了,给 10 美元,表达了打赌的赔率。

赔率是一种表达对一个事件的信念的方式,它是一个比率,即如果你是错的,你愿意付出多少,如果你是对的,你会得到多少。它们可以用以下方式量化:

赌注的赔率。

现在,我们如何将它转化为概率呢?容易。由于所有概率的总和必须为 1,我们使用上图中的等式,得到:

最后,如果我们代入我们得到的概率:

计算我们认为我们赢的概率是多少。

正如我们所看到的,我们认为我们会赢的概率是 0.66%或 66%。当我们决定赌两倍我们会得到的权利时,似乎更多?

根据赔率计算概率的过程可以用下面的等式来概括,其中 H 是某个假设,O(H)是支持该假设的赔率(赌赢与赌输的比率):

概率和赔率之间的一般关系。

结论和更多资源

就是这样!概率是牛逼的。一如既往,我希望你喜欢这篇文章,并且通过这个简单的日常例子,你已经了解了概率和赔率之间的区别。

如果有,那就看看我其他关于概率、数据科学和机器学习的帖子 这里 。好好读!

如果你想深入了解这个话题,可以看看 StatQuest 的视频:

此外,你可以在这里查看我的其他概率学习文章:

  • 概率学习:贝叶斯定理
  • 概率学习:贝叶斯定理如何应用于机器学习
  • 概率学习:最大似然
  • 概率学习:贝叶斯背后的数学
  • 概率学习:朴素贝叶斯
  • 概率学习:隐马尔可夫模型
  • 概率学习:蒙特卡罗方法

我强烈建议你去读读,因为它们很有趣,充满了关于概率机器学习的有用信息。

如果你想了解更多关于机器学习和人工智能的知识 关注我上媒 ,敬请关注我的下期帖子!还有,你可以查看 这个资源库 获取更多关于机器学习和 AI 的资源!

可能是关于 SQL Server 中的连接、交叉应用、联合、交叉连接等的最佳介绍

原文:https://towardsdatascience.com/probably-the-best-introduction-about-join-cross-apply-union-cross-joins-and-more-in-sql-server-f2ee8f8af957?source=collection_archive---------16-----------------------

在这个故事中,我们将从零开始理解在 SQL Server 中组合两个或多个表的大部分方法。我们将使用 SQL Server 2019,但几乎下面描述的每个查询都可以在旧版本的 SQL Server 上执行,甚至可以在 Oracle 或 MySQL 等其他 SQL 数据库上执行,只需做很小的调整。

在开始之前,一定要知道本文中的结构、数据和所有查询都可以在这个页面上找到<>。你会发现它非常有用,因为它们都是可编辑和可执行的,所以你可以随意尝试你想到的任何东西。

设置环境

我们将在所有查询中使用下面的表格和示例数据。想象一下,你正在查看像 Bird、Lime、Dott 这样的电动滑板车租赁服务的数据仓库(一个非常非常简化的版本)。

我们有以下表格:

  • 表【dbo】。【Trip】:包含所有行程的事务表。它在每次旅行中都有一行,换句话说,每次用户解锁踏板车、使用它通勤并再次锁定它时都会生成一行。

  • 表【dbo】。【用户】:用户的维度表。

  • 表【dbo】。【踏板车】:踏板车尺寸表。

  • 表【dbo】。[RepairedScooter] :这是一个表格,包含至少一次通过维修区的滑板车列表。

您可以查看从 db <> fiddle 创建和填充数据的代码,但也可以查看预览。

查找不同列的组合

我们可以在不同的情况下使用交叉连接(或笛卡尔连接),但是,它最常用的范围可能是当您想要从一个或多个表中选择两个或多个字段的所有组合时。

在下面的示例中,您可以使用交叉连接对指示器和用户的每种组合进行选择。例如,如果您希望制作第一个表来分析用户是否不止一次租用同一辆小型摩托车,这可能会很有用。

—查询 A001
从【用户】A、【代步车】B
中选择 DISTINCT A【ID】、A【用户名】、B【ID】、B【品牌】、B【型号】
排序按 A【ID】、B【ID】

使用不同表的列

当您想要将另一个表(表 B)中的一列或多列添加到表(表 A)中时,可以使用联接。如果您想使用基于 SQL 的数据库,这可能是需要掌握的最重要的构造。

语法介绍

在理解不同类型的连接之前,让我们快速浏览一下在表之间进行连接时使用的语法。

以下查询是表Trip和表Scooter的基本连接。连接的类型是内部连接,我们将在文章的这一部分的后面理解它的含义。ON 子句后列出了连接条件。这里,列之间有一个简单的等式,但它们可以不止一个(在这种情况下,您应该使用 AND、OR,而不是运算符),或者可以是更复杂的等式,如 between 或 like。在连接条件中,您还可以找到应用于列的函数(例如 LEFT ),但这是一个介绍,因此我们不会找到这些情况。

—查询 B001
选择 A.[ID],A.[DateTimeStart],A.[TripDuration],B.[Brand],B.[Model]
从[Trip] A
内联[Scooter] B
上 A.[ID_Scooter]=B.[ID]

我们在查询中使用了一些别名,但是,我们也可以重复表的完整名称,得到相同的结果。

—查询 B003
选择【行程】。[ID],[Trip]。[日期时间开始],[行程]。[旅行持续时间],[踏板车]。[品牌],[滑板车]。【车型】
从【行程】
内加入【踏板车】
上【行程】。[ID_Scooter]=[Scooter]。[ID]

如果列名只存在于其中一个表中,则指定表名或别名不是强制性的(但建议这样做)。此外,这个查询给出的结果与其他两个相同。

—查询 B002
选择 A.[ID],[DateTimeStart],[TripDuration],[Brand],[Model]
从[Trip] A
内联接[Scooter] B
上[ID_Scooter]=B.[ID]

当然,您可以通过连接三个或更多的表来扩展所有这些规则,这方面没有限制。

—查询 B004
选择 A.[ID],A.[DateTimeStart],A.[TripDuration],B.[Brand],B.[Model],C.*
从[Trip] A
内联接[Scooter]B
ON A .[ID _ Scooter]= B .[ID]
内联接[User]C
ON A .[ID _ User]= C .[ID]

最后,您可能会发现一些具有不同语法的连接子句(例如,如果您正在使用 SAP Business Objects suite),类似于交叉连接。这也是一种有效的语法,称为 ANSI-92,但在本文中,我们不使用它,所以可以在互联网上找到许多关于它的文章。

完全外部连接

完全外部连接的结果将包括表 A 中的至少一行和表 B 中的至少一行,即使不满足连接条件,在这种情况下,一行空值将来自不匹配的行。

参见下面的例子来阐明这个概念。

—查询 C001
SELECT *
FROM[Trip]A
FULL OUTER JOIN[User]B【T33]ON A .[ID _ User]= B .[ID]

左外部连接

左外部联接类似于完全外部联接,但不对称。这意味着结果中至少有一行来自左边的表(下例中的表 A),但是右边的表(下例中的表 B)中不满足连接规则的行不会显示出来。

—查询 D001
SELECT *
从【行程】A
左加入【用户】B
ON A.[ID_User]=B.[ID]

请注意,我们可以使用 LEFT OUTER JOIN 构造来查找左边表(表 A)中根据连接规则在右边表(表 B)中没有对应行的行。这是一个非常有用的应用程序,您只需在查询下添加一个 WHERE 子句,如下例所示。

—查询 D002
SELECT A . *
FROM[Trip]A
LEFT JOIN[User]B
ON A .[ID _ User]= B.[ID]
其中 B .[ID]为空

右外部联接

正如您可能期望的那样,我们对左外连接的所有考虑可以对称地用于右外连接。

在理解了上一节中的左外连接之后,可以随意看一下下面的两个例子来确认或否定您对右外连接的期望。

—查询 E001
SELECT *
FROM[Trip]A
RIGHT JOIN[User]B
ON A .[ID _ User]= B .[ID]

—查询 E002
SELECT B . *
FROM[Trip]A
RIGHT JOIN[User]B
ON A .[ID _ User]= B .[ID]
其中 A.[ID]为空

内部连接

从概念上讲,内部连接是左外部连接和右外部连接的组合,因此该连接的结果将只包含符合连接规则的行。

—查询 F001
SELECT *
FROM[Trip]A
INNER JOIN[User]B
ON A .[ID _ User]= B .[ID]

反连接

相反,反连接将只显示左侧的表行(表 A)和右侧的表行(表 B ),它们不符合连接规则。

—查询 G001
SELECT *
FROM[Trip]A
FULL OUTER JOIN[User]B
ON A .[ID _ User]= B.[ID]
其中 A.[ID]为空或 B .[ID]为空

交叉应用

交叉应用类似于内部连接,但是当您想要指定一些关于连接中的数量或顺序的更复杂的规则时,可以使用它。交叉应用最常见的实际应用可能是当您希望在两个(或更多)表之间建立连接,但您希望表 A 的每一行都是 math,并且只有表 B 的一行是 math。在下面的示例中,更详细地说,每个用户(表 A)将与其最长的行程(表 B)匹配。请注意,没有进行任何旅行的用户不会包括在结果中,因为我们已经说过交叉应用在某种程度上类似于内部连接。

—查询 H001
SELECT A.*,B.[TripDuration],B .[ID]
FROM[User]A
CROSS APPLY(
SELECT TOP 1 *
FROM[Trip]C
其中 C .[ID _ User]= A .[ID]
ORDER BY C .[Trip duration]desc
)B

外部应用

外部应用与我们刚刚讨论的交叉应用非常接近。主要区别在于,外部 APPLY 还会在结果中包括表 A 中不符合 WHERE 子句中定义的匹配规则的行。

下面的例子类似于我们在交叉应用部分中的例子,但是,正如您可以很容易地看到的,没有任何旅行的用户也包括在结果中。

—查询 I001
SELECT A.*,B.[TripDuration],B .[ID]
FROM[User]A
OUTER APPLY(
SELECT TOP 1 *
FROM[Trip]C
其中 C .[ID _ User]= A .[ID]
ORDER BY C .[Trip duration]desc
)B

在连接中使用 WHERE 条件

在继续之前,理解使用连接时 WHERE 子句的用法是很重要的。

我们将考虑四个例子,有四个完全不同的结果,我希望这些例子有助于理解如何正确地编写连接和 WHERE 规则。

在查询 L001 中,您可以看到一个关于连接的重要事实,因为数据库将首先根据连接规则在表之间建立连接,然后才使用 WHERE 子句进行过滤。因此结果将只包括 b .[用户名]='Brenda '的行。

—查询 L001
SELECT *
FROM[Trip]A
LEFT JOIN[User]B
ON A .[ID _ User]= B .[ID]
其中 B.[Username]='Brenda '

关于连接的另一个重要事实是,您可以在连接规则中指定一些过滤规则。如果考虑在 WHERE 子句之前应用连接规则,那么这是一个好主意,这样可以限制数据库在筛选之前必须提取的行数。

硬币的另一面是,您必须知道并始终注意,在左出连接中,只有应用于右表(表 B)的过滤规则才会被考虑。

—查询 L002
SELECT *
FROM[Trip]A
LEFT JOIN[User]B
ON A .[ID _ User]= B .[ID]AND B .[Username]= ' Brenda '

—查询 L003
SELECT *
FROM[Trip]A
LEFT JOIN[User]B
ON A .[ID _ User]= B .[ID]
其中 A.[ID_Scooter]='SR001 '

正如我们在查询 L002 的示例中已经说过的,在左出连接中,只考虑应用于右表(表 B)的过滤规则。在本例中,您可以看到过滤规则 A.[ID_Scooter]='SR001 '被忽略,所有指示器都被提取到结果中。请花一些时间来理解查询 L003 和 L004 的结果之间的差异。

—查询 L004
SELECT *
FROM[Trip]A
LEFT JOIN[User]B
ON A .[ID _ User]= B .[ID]AND A .[ID _ Scooter]= ' Sr 001 '

使用不同表格的行

在组合了不同表中的列之后,您可能会问是否有可能组合不同表中的行。答案是肯定的,但是你必须掌握不同的结构。

联合和联合所有

关于组合不同表中的行的第一个重要假设是列名和类型必须相同。例如,如果您尝试将表 Scooter 和 RepairedScooter 与 UNION ALL 组合在一起,您将会得到一个错误,因为它们有不同的列。

—查询 M001
从【代步车】
中选择*
从【维修代步车】中选择*

Msg 205 Level 16 State 1 Line 2 所有使用 UNION、INTERSECT 或 EXCEPT 运算符组合的查询在其目标列表中必须有相同数量的表达式。

无需修改表的结构,只需选择两个表中都存在的列,就可以轻松地合并这两个表。

—查询 M002
从【代步车】
中选择【ID】、【品牌】、【型号】、【制造年份】
从【维修代步车】中选择【ID】、【品牌】、【型号】、【制造年份】

UNION 和 UNION ALL 的区别在于,前者只在结果中包含不同的值,因此,它比后者稍慢。

—查询 M003
从【代步车】
中选择【ID】、【品牌】、【型号】、【制造年份】
从【维修代步车】中选择【ID】、【品牌】、【型号】、【制造年份】

除...之外

如果我们希望提取第一个表中的行而不是第二个表中的行,我们可以使用 EXCEPT。

—查询 N001
从【代步车】
中选择【ID】、【品牌】、【型号】、【制造年份】
除了
从【维修代步车】中选择【ID】、【品牌】、【型号】、【制造年份】

横断

如果我们想提取第一个表和第二个表中的行,我们可以使用 INTERSECT。

—查询 O001
从【代步车】
中选择【ID】、【品牌】、【型号】、【制造年份】
从【维修代步车】中选择【ID】、【品牌】、【型号】、【制造年份】

使用流程图进行简单回顾

我们看到了很多构造,我希望这个故事能帮助你更好地理解它们之间的区别。在下图中,您可以找到一个流程图,您可能会发现在 SQL Server 中组合不同来源的数据的第一步很有帮助。

[## SQL Server 2019 |数据库小提琴

免费的在线 SQL 环境用于实验和分享。

dbfiddle.uk](https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=bb54aaea7e0a2527a7e5b14b6dc922e6)

可能是面向对象 Python 的最佳实践— Attr

原文:https://towardsdatascience.com/probably-the-best-practice-of-object-oriented-python-attr-d8c26c0e8a4?source=collection_archive---------6-----------------------

由 davisco 在 Unsplash 上拍摄的照片

让 Python 面向对象编程变得更加容易

众所周知,Python 非常灵活,可以用函数式、过程式和面向对象的方式编写。老实说,除非万不得已,我很少用 Python 写类,只是因为大多数时候我不想过度设计问题。例如,当我们使用 Python 执行一些特定的数据分析时,使用面向对象编程可能没有太大意义。

然而,当我知道这个名为“Attrs”的图书馆时,事情发生了变化。它让 Python 用面向对象模式编程变得更加容易(我觉得 Python 的面向对象编程已经非常简洁和容易了)。在本文中,我将介绍这个库如何促进 Pythonic 面向对象编程。

[## 属性

版本 19.3.0()。是 Python 包,它将把您从……

www.attrs.org](https://www.attrs.org/)

简单的开始

照片由丹妮尔·麦金尼斯在 Unsplash 上拍摄

像大多数 Python 库一样,我们可以使用pip简单地安装attrs

pip install attrs

现在,让我们用 Python 编写一个没有任何库的类。

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

p1 = Person('Chris', 32)
p2 = Person('Chris', 32)

请注意,我还用相同的属性值实例化了两个实例。

当我们输出实例时,我们只能得到类名。此外,属性值相同的两个实例不会被视为相等,因为它们没有指向相同的内存地址。

那么,attrs能为我们做些什么呢?让我们在这里做同样的事情。

from attr import attrs, attrib[@attrs](http://twitter.com/attrs)
class Person(object):
    name = attrib()
    age = attrib()

p1 = Person('Chris', 32)
p2 = Person('Chris', 32)

我想有些事情需要一个简单的解释。首先,@attrs是一个注释,它告诉我们这个类将要用attrs库来声明。然后,对于每个属性,我们只需要将它们定义为attrib(),而不需要有一个__init__()方法。之后,我们可以简单地实例化这个类,就像有一个__init__方法一样。

我们也来试试输出和相等测试。

显然,我们有一个非常有意义的对象输出,以及我们可以测试对象之间的相等性。

非初始化属性

照片由诺德伍德主题在 Unsplash 上拍摄

你现在可能有一个问题。如果有这样一个属性,我们不想在实例化过程中初始化它,但可能在以后给它赋值,那该怎么办?当然,如果你还是用下面的attrib()就不行了。

使用attrs,您可以通过用False传递init参数来实现这一点。

[@attrs](http://twitter.com/attrs)
class Person(object):
    name = attrib()
    age = attrib()
    skills = attrib(init=False)

p1 = Person('Chris', 32)

如图所示,我们不必一开始就给出skills的值,但是我们可以在以后赋值。

默认值

由 Kelly Sikkema 在 Unsplash 上拍摄的照片

你可能还会问,我想给属性赋予默认值怎么样?是的,有了attrs,你可以轻松做到。

[@attrs](http://twitter.com/attrs)
class Person(object):
    name = attrib(default='Chris')
    age = attrib(default=32)

p1 = Person()
p2 = Person('Chris', 32)

如图所示,我们为这两个属性都提供了默认值。然后,没有传入任何参数的实例与另一个用参数显式初始化的实例完全相同。

如果我们希望将一个空集合的属性作为默认值,该怎么办?通常,我们不想传入一个[]作为参数,这是 Python 著名的陷阱之一,可能会导致许多意想不到的问题。别担心,attrs为我们提供了一个“工厂”。

[@attrs](http://twitter.com/attrs)
class Person(object):
    name = attrib(default='Chris')
    age = attrib(default=32)
    skills = attrib(factory=list)

如图所示,属性skills最初是空的,但是后来,我们可以向它追加值。

验证属性

马库斯·温克勒在 Unsplash 拍摄的照片

现在,我们想给属性添加一些验证,以确保我们传入的值是有效的。使用attrs也很容易实现。

[@attrs](http://twitter.com/attrs)
class Student(object):
    name = attrib()
    age = attrib()
    student_id = attrib()

    [@student_id](http://twitter.com/student_id).validator
    def check_student_id(self, attribute, value):
        if len(str(value)) != 6:
            raise ValueError(f'student_id must be 6 characters! got {len(str(value))}')

在上面的例子中,我们用属性“student_id”声明了一个“Student”类。假设我们要验证学生 id,它的长度必须是 6 个字符。

注意,我们需要定义一个函数来完成这项工作。该函数需要注释为@<attribute_name>.validator。所以,在我们这里,这个应该是@student_id.validator。然后,我们可以在这个验证函数中引发一个异常,如上所示。

让我们做一个简单的测试。

第一个实例s1没有任何问题,因为它的student_id长度为 6,但是第二个实例s2不会通过,因为长度为 5,并且正确显示了带有预定义错误消息的异常。

子类

照片由Clker-Free-Vector-Images在 Pixabay 上拍摄

在普通 Python 中,我们必须使用__init__()函数中的super()函数来实现继承。当我们需要多重继承时,这将会非常复杂。使它变得极其容易。

[@attrs](http://twitter.com/attrs)
class Person(object):
    name = attrib()
    age = attrib()

    def get_name(self):
        return self.name

[@attrs](http://twitter.com/attrs)
class User(object):
    user_id = attrib()

    def get_user_id(self):
        return self.user_id

[@attrs](http://twitter.com/attrs)
class Student(Person, User):
    student_id = attrib()

    def get_student_id(self):
        return self.student_idstudent = Student(name='Chris', age=32, user_id='ctao', student_id=123456)

在上面的例子中,Student继承了PersonUser。在Student类中,我们只需要定义它的特定属性student_id,来自PersonUser的其他属性将直接自动继承,无需任何详细定义。

如上所示,函数被继承也没有问题。

连续编入词典

Pixabay 上 libellule789 的照片

attrs库还可以帮助我们轻松地将实例序列化到字典中。之后,你可以在 JSON 中使用它,做任何你想做的事情。

attr.asdict(student)

摘要

乔安娜·科辛斯卡在 Unsplash 上拍摄的照片

在这篇文章中,我已经介绍了库attrs和一些基本用法。我喜欢这个库,因为它使 Python 更加简单和简洁。如果你以前没有用过,强烈建议你试用一下。希望你也会喜欢。

[## 通过我的推荐链接加入 Medium 克里斯托弗·陶

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@qiuyujx/membership)

如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和其他成千上万的作者!(点击上面的链接)

大概是 2020 年学习深度学习最好的资源

原文:https://towardsdatascience.com/probably-the-best-resource-to-learn-deep-learning-in-2020-66d13a8ab1f1?source=collection_archive---------8-----------------------

并且学好它。

网上有这么多的书籍和课程,大部分都是免费的,新人很难选择一本好的,尤其是理论和实践部分。其中的 95%会让你在看完 50%的材料之前就想换一下,这是有原因的——它们的结构不合理。

照片由莫里茨·金德勒在 Unsplash 拍摄

糟糕的结构不会让你保持动力——正如理论书籍需要实用的部分只是为了打破单调,而实用的书籍恰恰需要相反的东西。

在我深度学习之旅的大部分时间里,我看的课程或读的书要么是:

  • 到理论:意思是几乎没有或根本没有实际工作,如果两个领域都没有很好地涵盖,就不可能对这个主题有所了解
  • 实用:意思是理论部分缺乏,因为这是事先知道的先决条件,即使书/课程一开始没有说明

我对大多数课程和书籍的另一个大问题是过早地进入图书馆——我说的过早是指立即。如果你不手动操作,至少在开始时,你就没有办法真正了解正在发生的事情。

好了,到目前为止,我们已经讨论了大部分网上可用的东西有什么问题。在下一节中,我们将介绍这本书和这门课程,它可能会改变游戏规则,我还会给出几个原因。

NNFS——从零开始的神经网络

免责声明: 我与球场所有者没有任何方式、形状或形式的关联,我个人并不了解他,您阅读的所有内容将纯粹基于个人经验。

如果你一直在研究 YouTube 上任何与数据科学相关的话题,你可能知道频道[sentdex](https://www.youtube.com/channel/UCfzlCWGWYyIQ0aLC5w48gBQ)。我喜欢看他以前关于基本机器学习,甚至是 Go 编程语言的视频。

今年早些时候(我想是在一月份),他宣布了一本即将出版的名为《从头开始的神经网络》的书和课程。

他声称该课程的目的是完全从零开始编码神经元、层、激活函数、优化器、梯度、反向传播——几乎所有的东西—,甚至一开始没有 Numpy。后来代码会被“翻译”成 Numpy,因为纯 Python 对于数学来说不够强大和方便。

你可以看下面完整的介绍视频,虽然我只是给了你两句话的总结:

所以经过一番考虑,我上了这本书的官方网站,买了电子书格式的,我现在正在读。

我必须说,提供了

如果你不想花 30 美元买书,你仍然可以完全免费观看 YouTube 播放列表。它跟随着这本书,但这本书走得更详细——所以记住这一点。

当前状态

现在这本书仍然是草稿格式,如果你问我的话,那就太好了。作为一名读者,你可以对你认为不是 100%清楚的任何部分发表评论,你的评论会得到回应,或者整本书的部分会得到更好的解释。

即使是草稿格式,仍然有大约 250 页供你阅读,因为深度学习是一个复杂的主题,它将需要多次阅读。所以不,你不会很快用完材料。

在陈述了所有的优点之后,我仍然有一些让我担心的事情,如果你决定走这条路的话,可能会让你担心。让我们在下一节讨论它们。

可能的缺点

现在这部分只是我在大声思考,下面列出的事情可能不会影响到你,但是你要意识到。

  1. ****没有 CNN 和 RNNs——据我所知,整本书/课程完全基于人工神经网络,所以你必须在别处学习 CNN 和 RNNs。可能以后会盖,但我不确定。
  2. 无库使用 —这既是有利的一面,也是不利的一面。有利的一面是,你将通过从头开始开发东西来更深入地理解底层机制,但在课程结束时,你将不会知道如何使用 TensorFlow 或 py torch——尽管我认为一旦你理解了基础知识,它们将非常容易掌握。

同样,这些对你来说可能不是真正的缺点——也许你不关心卷积或递归神经网络,或者也许你已经知道如何使用 PyTorch 或 TensorFlow,但理论部分是底部的痛苦。

自己判断,但要记住这两点。

判决

好的,我们讨论了这本书和这门课的好的和坏的方面。

所以,我会推荐吗?

简短的回答是——绝对是的。但是先别掏出你的钱包。你很可能不喜欢这门课程——因为我们都是不同的,有不同的学习方法——所以在购买这本书之前,请查看一下 YouTube 播放列表,看看它是否是你想要的。

谁知道呢,也许 YouTube 上的视频对你来说已经足够了,你不想再深究下去了——这也没关系。

但是如果你想更深入地从头开始,我强烈推荐这本书。

感谢阅读。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

** [## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)**

数据科学项目中的问题识别

原文:https://towardsdatascience.com/problem-identification-f7db429af6e0?source=collection_archive---------26-----------------------

问自己三个问题来获得聪明的成功。

图片由皮克斯拜的 Gerd Altmann 提供

解决正确的问题!

你们中的许多人都会熟悉 Kaggle,它是机器学习竞赛的发源地。这是一个可以磨练数据科学技能的地方,对吗?不对。这是你可以磨练机器学习技能的地方。至少以前是这样的。将会有一个包含一列标签的训练数据集和一个缺少所述标签的测试数据集。你训练和改进你最好的机器学习模型,预测测试集上的标签,提交,然后等着看你的名字/团队在排行榜上上升!

抱歉,这不是数据科学。反正不是数据科学的全部。事实上,真的只是最小的部分。一个有趣的部分,当然。可以说是关键部分。但绝对不是全部和终结。如果你最好的机器学习模型预测错了事情,或者只是对业务没有直接用处的事情,那就毫无价值。事实上,正如微软的 Bing 团队(最终)发现的那样,确定一个对你的业务非常不利的问题(或者更确切地说,一个指标)是可能的。你的业务问题是建立一个伟大的搜索引擎。一个好的搜索引擎是用户想更经常使用的,对吗?所以你正确地认识到业务问题是提高用户搜索量的问题之一,对吗?没有。你对搜索引擎的正确问题识别是优化搜索结果,而不是搜索!

有了上面的例子,我鼓励你阅读链接的博客,我几乎想在这里结束这篇文章,因为它是如此伟大的一课,简洁地概括了关键信息。识别错误的问题真的会把你引向错误的方向,任何后续的优化尝试只会让你更快地犯更多的错误。但是,撇开有益的战争故事不谈,有什么建设性的技巧可以引导你走向成功呢?

放聪明点!

起草问题陈述时,一个很好的清单是 SMART :

  • 具体,不笼统
  • 可测量的
  • 面向行动
  • (与关键问题)相关
  • 受时间限制的

如果你发现自己写的问题陈述中有诸如“提高销售额”或“减少客户流失”这样的短语,你应该抓住自己并查看智能清单。提高多少?到什么时候?第二季度末?第三?明年?什么是“销售额”——售出的单位或收入?什么是“流失”?当管理“现收现付”客户的团队关注离开他们系统的客户时,如果客户升级到与您公司的 12 个月合同(因此转移到另一个团队的账本),这真的应该被称为流失吗?也许你的公司真的会喜欢更多这样的东西!

够聪明吗?可以说,正如上文所强调的,必应团队认为他们很聪明。不幸的是,他们选错了“具体的”。你可以开始解构一个聪明的问题陈述。你可以开始谈论商业背景、利益相关者、制约因素和风险……如果你是新手,开始头晕,我不能责怪你。当你觉得需要考虑的因素太多时,我会给你三个简单的问题,帮助你找到方向:

  1. 是给谁的?
  2. 他们想要什么?
  3. 你怎么知道你得到了他们想要的东西?

对于所有关于智能措施、环境和利益相关者的花哨说法,这就是它的意义所在。还有“保持真实”。在需要后一周交付一个好的解决方案是没有意义的——及时交付一个足够好的解决方案会更好吗?当你创建一个模型来预测一个月前的客户流失时,你真的考虑清楚了吗?了解什么是想要的,以及如何在满足这种需求的背景下,以一种现实的方式来衡量您的解决方案,这确实是成功建立数据科学项目的关键。

关于这篇文章

这是一个链接系列的第二篇文章,旨在简单介绍如何开始数据科学过程。你可以在这里找到介绍,在这里找到系列的下一篇文章。

问题:过度拟合,解决方案:正则化

原文:https://towardsdatascience.com/problem-overfitting-solution-regularization-b466d3d1f4da?source=collection_archive---------21-----------------------

什么使模型过度拟合,我们如何解决这个问题

我们都有这样的朋友,他们讲述的故事极其详细。当你问他们最近看的一部电影时,你可能不仅会知道这部电影,还会知道电影院卖爆米花的那个人的手表。另一方面,我们有沉默寡言的朋友,他们只会告诉你这部电影是“好”还是“坏”。

就细节的数量而言,过度适应和欠适应与那些不同类型的朋友相似。过度拟合的机器学习模型试图提取训练数据的细节,而欠拟合的模型过于笼统,往往会错过训练数据中的重要趋势。

一个更像机器学习的例子是预测图像中的对象。假设我们正在尝试构建一个模型来预测图像中的西红柿:

照片由 Soya Soong 在 Unsplash

  • 模型 A:红色,圆形,顶部是绿色的星形,有一些水滴
  • B 型:红色,圆形

A 型的问题是,并不是所有的番茄上都有水滴。这个模型太具体了,很可能会挑湿番茄。它不能很好地推广到所有的番茄。它会寻找水滴,所以无法预测图像中的干番茄。是过拟合

另一方面,B 型认为所有红色圆形的东西都是番茄,这是不正确的。该模型过于一般化,不能检测番茄的关键特征。是欠配合

这些例子并不完全是机器学习模型如何学习和预测的,而是给出了过度拟合和欠拟合的概述。在这篇文章中,我将详细介绍以下概念:

  • 偏差和方差
  • 过度拟合和欠拟合
  • 正规化

偏差和方差

偏差和方差对于理解过度拟合和欠拟合是至关重要的。

偏差衡量平均预测值与实际值的差距。如果我们试图用一个非常简单的模型来模拟一个复杂的关系,就会产生偏差。高偏差模型的预测非常相似。由于它对数据内的变化不敏感,因此该模型在训练数据和测试数据(以前未见过的数据)上的准确性都很低。

高偏差模型

蓝点是训练集中的观察值,红线是我们的有偏模型,它不关心观察值的两个特征内的波动,并进行相同的预测。

方差是偏差的反义词,对数据内的变化敏感。具有高方差的模型对训练数据中甚至很小的变化都非常敏感。它试图捕捉每一个小细节,因此训练数据的微小变化也会改变模型。具有高方差的模型也倾向于捕捉数据中的噪声。异常值将在模型的范围内。

高方差模型

如您所见,该模型试图根据数据中的所有变化进行调整。具有高方差的模型的预测被广泛传播。很明显,该模型在训练集上有很高的准确率。然而,它在新的、以前看不到的观测中表现不佳。

机器学习模型是为以前看不到的观察结果而建立的,因此方差很大的模型是不可接受的。我们也永远不能依赖高偏差的模型。因此,找到偏差和方差之间的界限是至关重要的。偏差和方差之间总是有一个权衡。我们很容易找到一个高偏差低方差或者低偏差高方差的模型。然而,你的模型的成功取决于在偏差和方差之间找到最优的方法。例如,下面的模型似乎很适合。

过拟合和欠拟合

  • 具有高偏差的模型往往会欠拟合。
  • 方差高的模型往往会过度拟合。

当模型试图很好地拟合训练数据,以至于不能推广到新的观察结果时,就会出现过度拟合。广义模型在新的观察上表现得更好。如果一个模型比需要的更复杂,我们很可能会过度拟合。欠拟合模型不能很好地推广到训练和测试数据集。

在监督学习任务中,我们可以通过比较训练和测试数据集上的模型精度来检测过拟合。如果训练数据集(模型看到的观察值)数据集的精度远远高于测试数据集(看不到的观察值)的精度,则模型过度拟合。

损失表示实际价值和我们的预测之间的差异

损失与实际目标值和预测值之间的差异成比例。监督学习模型执行多次迭代,通过更新特征权重来最小化这种损失。然而,在某个点之后,模型在测试和训练数据上表现不同。损失在训练数据上持续减少,但是在某个点之后在测试数据上开始增加。检测这一点对于创建出色的机器学习模型至关重要。

过度拟合是机器学习模型的一系列问题,但我们如何防止模型过度拟合?答案是正规化。

正规化

过度拟合的主要原因是使模型比必要的更复杂。如果我们找到降低复杂度的方法,那么过拟合问题就解决了。

正则化不利于复杂的模型。

正则化增加了对模型中较高项的惩罚,从而控制了模型的复杂性。如果增加一个正则项,该模型试图最小化损失和模型的复杂性。

正则化减少了方差,但不会导致偏差显著增加。

两种常见的正则化方法是 L1 正则化和 L2 正则化。模型的复杂性取决于:

  • 特征总数(由 L1 正则化处理),或
  • 特征的权重(由 L2 正则化处理)

L1 正规化

它也被称为稀疏正则化。顾名思义,它用于处理稀疏向量。如果我们有高维特征向量空间,模型就变得很难处理。

L1 正则化强制无信息特征的权重为零。L1 正则化的作用类似于在每次迭代中从权重中减去少量的力,从而最终使权重为零。

L1 正则化惩罚|权重|。

L2 正规化

为简单起见,它也被称为正则化。如果我们把模型的复杂度作为权重的函数,那么特征的复杂度与它的权重的绝对值成正比。

L2 正则化迫使权重趋向于零,但并不使它们完全为零。L2 正则化就像在每次迭代中去除一小部分权重的力。因此,权重永远不会等于零。

L2 正则化惩罚(权重)

有一个额外的参数来调整 L2 正则化项,称为正则化率(λ)。正则化率是一个标量并乘以 L2 正则化项。

注意:选择λ的最佳值很重要。L2 正则化的目标是简单。然而,如果 lambda 太高,模型就会变得太简单,从而可能会不足。另一方面,如果λ太低,调节的效果变得可以忽略不计,模型可能会过拟合。如果 lambda 设置为零,那么正则化将被完全移除(过度拟合的高风险!).

注: 岭回归使用 L2 正则化,而拉索回归使用 L1 正则化。弹性网回归结合了 L1 和 L2 正则化。

结论

过度拟合是机器学习模型的一个关键问题,需要小心处理。我们使用我们已经知道的数据建立机器学习模型,但在新的、以前看不见的数据上尝试或测试它们。我们希望模型了解训练数据中的趋势,但同时不希望模型过于关注训练数据。模型的成功取决于在过度拟合和欠拟合之间找到最佳点。

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

作为数据科学家解决问题:案例研究

原文:https://towardsdatascience.com/problem-solving-as-data-scientist-a-case-study-49296d8cd7b7?source=collection_archive---------2-----------------------

我对数据科学家如何解决问题的想法,以及分享我在第一份工作中使用一个最喜欢的项目的案例研究

沃洛季米尔·赫里先科在 Unsplash 上的照片

关于数据科学家如何解决问题,有两个神话:一个是问题自然存在,因此数据科学家面临的挑战是使用算法并将其投入生产。另一个神话认为数据科学家总是试图利用最先进的算法,更好的模型等于更好的解决方案。虽然这些并非完全没有根据,但它们代表了对数据科学家工作方式的两种常见误解:一种过于强调“执行”方面,另一种夸大了“算法”部分。

显然,这些神话并不是我们实际解决问题的方式。在我看来,数据科学家解决问题的方式是:

  • 更多关于“如何将问题从商业背景中抽象出来”,而不仅仅是“被交给一个具体的任务”
  • 更多的是“用算法解决问题”,而不仅仅是“用最好的算法解决问题”
  • 更多的是“迭代地交付商业价值”,而不仅仅是“实现代码并收工”。

说到这里,我注意到解决问题的过程通常包括四个阶段,我想分享一下这四个阶段是什么,以及它如何通过案例研究发挥作用,然后我们如何以正确的心态实现这四个阶段。

故事开始于,从前…

我的第一份工作是在一家经营汽车定价和信息网站的公司,该公司于 2014 年 5 月进行了首次公开募股(IPO)。这是一次很棒的经历,我清楚地记得那天周围的每个人都在为一家上市公司的诞生欢呼。作为一家上市公司,我们的收入开始受到很多关注,尤其是在 8 月份发布了第一份季度收益报告。7 月初,税收部门的主管来到数据科学家的座位区,看起来他没有好消息要分享。

“我们有麻烦了,销售收入的一个百分比不能适当地记入贷方;我们需要你的帮助。”

这里有一些相关的背景:公司的收入是基于它向汽车经销商介绍更多的销售这一事实而产生的。为了获得应得的佣金,我们需要将车辆的销售与正确的客户相匹配。如果我们的数据提供者可以告诉我们哪个客户买了哪辆车,那么匹配就完成了,不需要额外的努力;然而,问题是一个数据提供商决定不提供一对一的销售记录:它必须批量完成(如下所示的“批量”的可视化),那么要知道哪个客户买了哪辆车就更加困难和不确定了。

收入团队对这一变化感到惊讶,在花了一个月的时间试图解决该问题后,该数据提供商只有 2%的销售额可以手动恢复。这对第一个盈利电话来说是个坏消息,所以他们开始向数据科学家寻求帮助。这显然是一个急需解决的问题,所以我们马上着手处理。

第一阶段。理解问题,然后用数学术语重新定义它

这是数据科学中解决问题的第一阶段。关于“理解问题”部分,一个人需要清楚地识别痛点,这样一旦痛点被解决,问题就应该消失了;关于“重新定义”问题部分,这通常是问题需要数据科学家帮助的原因。

对于我们的收入团队询问的具体问题,问题是:我们不能将每辆售出的车辆分配给一个客户,这样我们就失去了收入。

痛点是:在给定的批次中查找谁购买了车辆是手动的且不准确,考虑到有数千个批次需要匹配销售,这非常耗时且不可持续。

这个“重新定义”的问题用数学术语来说就是:给定一批有客户 C1、C2、..,Cn,以及售出车辆信息,V1,V2,…,Vm,我们需要一个自动化的解决方案来准确识别正确的匹配对(Ci,Vj ),以反映实际的购买活动。

第二阶段。分解问题,确定一个逻辑算法解决方案,然后构建出来

对于重新定义的问题,我们可以看到这是一个在约束条件下的“匹配”练习,给定客户和批量车辆。所以我把问题进一步分解成两步:

  • 第一步。给定车辆 P(C|V ),计算客户的购买可能性
  • 第二步。根据可能性,将汽车归属于该批中最有可能的客户

现在,我们可以进一步确定每个问题的解决方案。

第一步。概率计算

为了简单起见,让我们假设在这个批次中有三个客户(c1、c2、c3),并且提供一个车辆(v1)信息作为销售。

  • P(C=c1)代表 c1 购买任何一辆车的可能性。假设没有关于每个客户的先验知识,他们购买任何汽车的可能性应该是相同的:P(C=c1) = P(C=c2) = P(C=c3),这等于一个常数(例如,在这种情况下是 1/3)
  • P(V=v1)是 v1 被出售的可能性,假设它显示在该批次中,这应该是 1 (100%被出售的可能性)

由于只有一个顾客进行购买,这种概率可以扩展为:

P(V=v1) = P(C=c1,V=v1) + P(C=c2,V=v1) + P(C=c3,V=v1) = 1.0

对于每一项,给出以下公式

P(C=c1,V = v1)= P(C = C1 | V = v1)* P(V = v1)= P(V = v1 | C = C1)* P(C = C1)

我们可以看到 P(C=c1|V=v1)与 P(V=v1|C=c1)成正比。所以现在,我们可以得到概率计算的公式:

P(C = C1 | V = v1)= P(V = v1 | C = C1)/(P(V = v1 | C = C1)+P(V = v1 | C = C2)+P(V = v1 | C = C3))

关键是得到每个 P(V|C)的概率。这样的公式可以口头解释为:特定客户购买车辆的可能性与该客户购买该特定车辆的可能性成比例。

上面的公式可能看起来太“数学”了,所以让我把它放到一个直观的上下文中:假设三个人在一个房间里,一个是音乐家,一个是运动员,一个是数据科学家。有人告诉你这个房间里有一把属于他们其中一个人的小提琴。现在猜猜,你认为谁是这把小提琴的主人?这很简单,对吧?鉴于音乐家拥有小提琴的可能性很高,而运动员和数据科学家拥有小提琴的可能性较低,小提琴更有可能属于音乐家。“数学”思维过程如下图所示。

现在,让我们把概率放到业务环境中。作为一个在线汽车定价平台,每个客户需要生成至少一个车辆报价,因此,我们假设客户可以合理地表示为他/她报价的车辆。然后,这种 P(V|C)概率可以从公司在历史中已经积累的现有数据中获知,包括谁在何时生成了车辆报价,以及他们最终购买了什么车辆。细节我就不进一步细说了,关键是我们可以学习 P(V|C),然后计算每一批需要的概率 P(C|V)。

第二步。车辆属性

一旦我们获得了每辆车销售给客户的预期概率,第二步就是归属过程。假设该批中只有一辆售出的车辆,这样的过程是琐碎的;但是,如果该批次中有多辆售出的车辆,则以下任一方法都适用:

  • (直接归因)仅使用计算出的概率 P(C|V),始终将车辆归因于可能性最高的客户。根据这种方法,可以将两辆车归属于同一个客户。
  • (循环法)假设每个客户最多购买一辆车:一旦一辆车被分配给一个客户,在下一轮车辆分配之前,两辆车都被删除。

现在我们已经设计了两步算法来解决关键挑战,是时候测试性能了!给定历史报价和销售数据,直接模拟“创建随机批次”、“将销售附加到批次”的过程,并尝试“从给定的批次信息中恢复销售”。这种模拟提供了一种评估模型性能的方法,我们估计超过 50%的销售额可以以高精度(> 95%)恢复。我们为真实数据集部署了该模型,结果与我们的预期非常匹配。

收入团队对上述解决方案非常满意:与 2%的回收率相比,50%超过了 25 倍!从业务影响的角度来看,这一收入直接增加了我们第一份季度收益报告的底线,数据科学团队贡献的价值是巨大的。

第三阶段。深入思考,寻求进一步改进的机会

我们将上述解决方案再运行一个月,看到性能相当稳定,现在是时候考虑下一步了。我们收回了 50%的销售额,但剩下的 50%呢?有没有可能进一步改进算法才能达到?

通常,我们作为数据科学家,有过于关注算法细节的倾向;在这种情况下,围绕如何更好地对 P(V|C)建模进行了一些讨论:我们是否应该使用深度学习模型来使这个概率变得更好,等等。然而,根据我的理解,这些纯粹的算法改进通常只会带来性能的提升,而我们不太可能缩小剩下的 50%的差距。

然后,我开始与收入团队进行更深入的交谈,试图找出我们对问题的理解中缺少的东西,结果是我们可以控制如何将客户分组到一个批次中!虽然有一些限制(例如,客户必须从同一家经销商处生成报价),但这给了我们进一步优化的自由,我认为这是缩小其余 50%销售差距的方向。

为什么我对这个方向充满信心?想一下这个情况:如果你有 4 个人要分批,每批有 2 个人。最好的批处理策略是将最不同的人放在同一个批处理中,这样一旦返回一个项目,归属将更加准确。下面的可视化展示了这个概念。在左边,如果你把两个音乐家放在同一个批次,两个运动员放在同一个批次,很难知道谁拥有小提琴或篮球。而在右边,如果你有一个音乐家和一个运动员的每一批,它更容易告诉音乐家 A 拥有小提琴,运动员 D 拥有篮球,有很高的信心。

要实现上述概念,需要两个步骤:

  • (相似度定义)如何定义客户对客户的相似度?然后把一批的熵作为优化的目标函数?
  • (批次优化)基于以上相似性,如何设计一个优化策略来达到最优批次?

第一步。相似性定义

在第一阶段解决方案中,我们已经找到了一种计算 P(V|C) 的方法,在这里,我将做一个直接的概括:两个客户之间的相似性与双方客户购买对方报价车辆的平均可能性成正比。如果每个客户只对一辆车报价(c1 对 v1 报价,c2 对 v2 报价),则简化版本如下:

相似度(C1,C2)= 0.5 *(P(V = v1 | C = C2)+P(V = v2 | C = C1))

一旦我们有了两个客户之间的成对相似性,我们就可以将一个批次的熵定义为该批次中客户之间的相互成对相似性的总和。现在,我们有一个优化的目标函数:我们想要最大熵的批次

第二步。批量优化

在看了一些类似的研究后,我决定使用 2-opt 算法,这是一种用于解决旅行商问题的简单局部搜索算法。

2-opt 算法的基本概念是:在每一步中,随机选取两条边并尝试“交换”,如果交换后目标函数更好,则执行交换;否则,重新选择两条边。该算法继续进行,直到目标函数收敛或达到最大迭代次数。下图说明了拾取两条边(红色)并将其交换到新边(蓝色)中,从而缩短距离的情况。

为了在我的例子中应用 2-opt 算法,我对旅行推销员问题(TSP)进行了类比:

  • 在 TSP 中,随机选择两条边;在我的案例中,随机选择了两批,然后每批随机挑选一名顾客进行交换
  • 在 TSP 中,总距离作为目标函数,越短越好;在我这里,所有批次的熵就是目标函数,越高越好。

太好了,我们拥有优化批次的所有要素!在实现算法后,我们进一步对现有数据进行回测,发现:85%以上的销售额可以恢复。在接下来的一个月中,当我们将此应用于真实数据集时,发现恢复率处于类似的水平。这种方法果然有效!

第四阶段。设计解决方案,使其具有可扩展性和可维护性

我上面描述的主要是算法设计部分;与此同时,还有工程开发部分,简单地编写代码并期望它具有可扩展性和可维护性并不容易。

在项目发展过程中,我们逐渐注意到在所需的模块之间存在一种依赖模式。车辆由多个特征表示,客户由一组车辆表示,批次由一组客户表示。有了这种高级表示,我们可以将依赖关系构建为 Vehicle -> Customer -> Batch。

与此同时,作为一个数据产品,我们需要确保系统可以不断发展,以更新所需的参数,并始终评估沿途的性能。因此,该架构是按照以下方式设计的

使用这种体系结构,数据科学家需要定期做的事情有:

  • 重新训练 P(V|C)模型,以确保它包含最近的客户购买行为
  • 对整个过程进行模拟,包括批次优化和销售归属,以确保系统性能高于阈值
  • 每月批量优化,为我们的收入团队和销售归属准备数据,以将客户与销售匹配

现在,我们已经构建了一个可维护的可持续数据产品。鉴于数据科学团队建立了良好的声誉,在接下来的一年中,我们大量参与了销售匹配系统的重新设计,这进一步扩大了数据科学在公司的足迹。由于这种架构的卓越运营,我们可以腾出更多资源来应对下一个挑战。

用正确的心态解决问题的一般流程

数据科学领域非常广泛,设计算法数据产品只是许多潜在项目的一部分。其他常见的数据科学项目有实验设计、因果推理、推动战略变革的深度分析等。尽管他们可能没有严格遵循或者甚至不需要我上面列出的所有阶段,四阶段流程仍然有助于展示一种思考解决问题的方法:

  • 第一阶段(问题识别)是帮助你专注于关键问题,而不是在深入研究数据时迷失方向
  • 第二阶段(第一个合理的解决方案)是让你快速取胜,并保持与业务伙伴建立信任的势头
  • 第三阶段(迭代改进)是帮助您将解决方案向前推进,并成为该领域的所有者
  • 第 4 阶段(卓越运营)是帮助您消除技术债务,将您从日常维护工作中解放出来

四阶段流程不一定是一个应该遵循的严格规则,但如果数据科学家在面对任何即将到来的挑战时拥有正确的心态,它更像是一个自然的结果。在我看来,这些心态是:

  • 业务驱动,而不是算法驱动。纵观全局,了解数据科学在业务中的位置,理解为什么需要数据科学以及它如何提供价值。不要太执着于任何特定的算法:“如果你只有一把锤子,那么一切看起来都像钉子”。
  • 拥有问题,而不仅仅是接受订单。成为问题的主人意味着一个人会积极主动地思考如何现在就解决它,更好地解决它,用更少的努力解决它。人们不会停留在一个次优的解决方案,并认为它已经完成。
  • 虚心,永远在学习。作为一个跨学科的领域,数据科学与统计学、计算机科学、运筹学、心理学、经济学、市场营销、销售等学科重叠!提前了解所有领域几乎是不可能的,所以要虚心学习,一路走来不断学习。总会有比你已经知道的更好的解决方案。

希望以上分享对你有所帮助:快乐解决问题,数据科学之道。

— — — — — — — — — — — — — —

如果你喜欢这篇文章,通过点赞、分享和评论来帮助传播。潘目前是 LinkedIn 的数据科学经理。可以看以前的帖子,关注他上 LinkedIn

之前有两篇分享潘数据科学经验的文章:

我的第一个数据科学项目

数据科学如何创新

多元线性回归的问题,R

原文:https://towardsdatascience.com/problems-with-multiple-linear-regression-in-r-bef5940518b?source=collection_archive---------17-----------------------

如果你以任何形式滥用数学,它就不会站在你这边

小心直线…图片由 Unsplash 上的阿塔瓦·图尔西拍摄

线性回归是一种流行的、古老的、充分发展的方法,用于估计测量结果和一个或多个解释(独立)变量之间的关系。例如,线性回归可以帮助我们建立一个模型,代表心率(测量结果)、体重(第一个预测因素)和吸烟状况(第二个预测因素)之间的关系。在这篇博客中,我们将了解如何进行参数估计,探索如何使用基于美国人口普查局数据创建的数据集进行多元线性回归,并讨论在我们试图简化模型时,由于删除“坏预测因素”而出现的一些问题。

线性模型的典型表示方式可能是人们所熟悉的:

这里, y 表示由斜率为 m 且截距为 b 的直线估计的测量结果。我们可以重新排列等式,得到:

我们可以进一步改变变量,用贝塔系数来表示:

这是线性回归模型的典型表示方式。注意,我们使用 y_hat 来表示估计,而不是观察。我们可以扩展该模型,使其包含多个预测变量:

其中 x_1,x_2,…,x_p 为预测值(其中有 p )。在这种情况下,可以调用线性代数中的一个概念——线性组合!请注意,β和预测值 x_i ( i 是预测值的索引)可以表示为单独的向量,为我们提供了模型的一般矩阵形式:

假设我们有N个结果,我们想找出结果和单个预测变量之间的关系。除了N结果,我们还会有单个预测因子的N观察。此外,假设结果和观察结果都存储在矩阵中。由于结果是一个单一的数字,并且有N个,我们将有一个N x 1矩阵来表示结果— Y (在本例中是一个向量)。此外,观察值将存储在一个N x (p + 1)矩阵中,其中p是预测值的数量(在我们的例子中是一个)。我们将一列 1s 添加到观察矩阵中,因为它将帮助我们估计与模型截距相对应的参数——矩阵 X 。请注意,我们添加了一个误差项——epsilon,它表示预测值( Y_hat )和实际观测值( Y )之间的差异。

术语 β 是包含线性模型的参数/系数的(p + 1) x 1 向量。附加项 ε 是一个表示测量误差的n x 1 矢量。

假设

与大多数(如果不是全部)统计工具类似,线性回归有几个必须满足的假设,以便使用其原理对问题建模:

  1. 线性(duh)——特征和结果之间的关系可以线性建模(如果数据是非线性的,可以进行转换以使其线性,但这不是本文的主题);
  2. 同方差——误差项的方差是常数;
  3. 独立性——观察相互独立,即结果 i 不会影响结果I+1
  4. 正态性——对于 X 的任意固定值, Y 呈正态分布。

如何获得β

拟合模型时,目标是最小化测量观察值和该观察值的预测值之间的差异。在线性回归中,我们通常会尝试最小化均方误差,即独立观察值与其预测值之间的平方差总和的平均值:

我们可以通过获取关于β(参数)的梯度并将其设置为 0 来最小化 MSE,从而得到β的公式:

了解了β是如何得出的,我们就可以开始练习了。

我们将使用一个由美国人口普查局收集的不同类型指标汇总而成的数据集。我们将尝试基于 7 个预测因素来预测预期寿命——人口估计、文盲率(人口百分比)、每 10 万人口中的谋杀和非过失杀人率、高中毕业生百分比、平均气温为 32 华氏度的天数以及按州分组的土地面积(平方英里)。请注意,该数据集来自 1975 年左右,不代表当前趋势,并且用于练习如何创建线性模型:

在众多统计工具中,r 是一个很好的工具(Python 也很好),所以我们将在这里利用它。首先,我们可以创建一个简单的回归模型,并检查每个预测变量的显著性:

语法很有趣,所以让我们来看一下:

  1. lm —创建线性模型的命令;
  2. Life.Exp~. —我们正在预测的变量Life.Exp,由(~)所有预测者(.)解释;
  3. data —我们用来创建模型的数据矩阵。

我们得到以下总结(仅显示系数的显著性):

创建模型时,R 为我们执行显著性检验,并报告与每个预测值的相应检验相关的 p 值。如果我们假设 p 值截止值为 0.01,我们会注意到,考虑到模型中包含的其他预测值,大多数预测值都是无用的。在这种情况下,我们可以通过创建一个仅使用预测器子集的模型来执行类似于手动降维的操作(逐步回归)。我们可以按 p 值降序丢弃预测值,从最没用到最没用:

强烈建议在每次模型更新后执行一次summary调用——在其中一个特征被删除后,再次执行每个系数估计的显著性测试,这会影响最终的 p 值,从而决定我们是否继续删除特征。为了节省空间,我在这里跳过了它。该模型的最终总结为我们提供了:

我们设法将功能的数量减少到只有 3 个!然而,这种方法存在一些问题。

意义

与我们在本练习中所做的类似,执行变量的反向消除,只会帮助我们简化模型以实现计算目的,并有可能提高通过残差平方和等指标衡量的性能。从模型中剔除的变量并不意味着该变量在现实生活中不重要。例如,我们剔除了收入,这可能是一个人预期寿命的“重要”因素。这个世界非常复杂,一个简单的模型,比如我们创建的这个,有几个缺点:

  1. 由 R 执行的显著性测试本质上是有偏差的,因为它们是基于创建模型所依据的数据。这与测试有关,与 R 本身无关;
  2. 有多种指标可以用来衡量一个模型有多“好”。例如,R(决定系数)是一个度量标准,通常用于解释预测变量的变化比例(范围 0 到 1 ),如预测因子所解释的。调整后的 R 值考虑了模型使用的变量数量,因为它表示模型的复杂性。然而,一个模型有可能显示出作为其一部分的变量的高显著性(低 p 值),但是具有表明较低性能的 R 值。根据下表,我们可以认为,我们应该选择第三个模型是“最好的一个”,并接受平衡“无关紧要”的变量和较高的 R 值之间的折衷;

然而,请注意,添加一个无关紧要的变量将始终增加 R 值并减少 MSE。尽管不重要,变量的增加仍然可以解释响应变量中的一小部分变化,这导致 R 更高,MSE 更低;

3.正如已经提到的,像这样的模型可能是对现实世界的过度简化。有许多因素可以影响一个人的整体生活,从而影响预期寿命。我们必须留意这些因素,并始终以怀疑的态度解读这些模型。这特别适用于这个模型,因为它试图模拟一个代表人们生计的因素。然而,这可以扩展到我们构建的任何通用模型;无论是模拟气候、制造过程中化学物质的产量等等。此外,怀疑主义原则适用于任何模型架构,而不仅仅是回归。

多重共线性

回想一下我们在开始时提到的线性组合,它们在多重共线性中也发挥了作用。当数据集显示多重共线性时,一个或多个测量特征可以用同一数据集中的其他特征来表示。这意味着关于特征(列向量)的信息由其他特征编码。从技术上讲,矩阵没有满秩,这意味着并非所有列都是线性独立的。其结果是数值不稳定和潜在的膨胀系数——即β!让我们集中讨论 X 的转置与 X 本身相乘所得到的矩阵的逆矩阵。

求矩阵 A的逆涉及计算矩阵的行列式。然后将行列式的倒数乘以另一项,得到倒数。注意我提到了“行列式的逆”;也就是1/determinant(A)。当矩阵不是满秩时,行列式通常是比 1 小得多的值,导致行列式的倒数是一个巨大的值。这是求逆的要素,最终导致系数膨胀!在 R 中,我们可以通过自己写出矩阵乘法来检查行列式是否小于 1。给定我们在练习中使用的数据集,我们可以写出:

让我们来分解命令:

  1. cbind命令用data的指定特征列创建一个矩阵,并将该矩阵存储在mtx
  2. t(mtx)mtx的转置;
  3. %*%是 r 的矩阵乘法运算符。

事实证明,对于我们在示例中使用的数据集,行列式约为 3e+41,因此我们得到TRUE作为输出!在执行多元线性回归时,这是一个需要检查的重要元素,因为它不仅有助于更好地理解数据集,而且还表明应该后退一步,以便:(1)更好地理解数据;(2)潜在地收集更多数据;(3)或者使用主成分分析或岭回归进行维数减少。

线性回归仍然是一种非常流行的建模方法。像任何统计工具一样,应该注意:(1)理解数据,以避免虚假的参数估计;(2)开发如何执行参数估计的意识,以便能够在潜在问题发生之前对其进行诊断;(3)解释为什么一个系数很重要,而另一个可能不重要,以及这如何反映我们试图模拟的世界现象。下面是最终的代码示例:

NBA 中与 PER 的问题

原文:https://towardsdatascience.com/problems-with-per-in-the-nba-fa0e611543e2?source=collection_archive---------16-----------------------

您可以轻松避免的 3 个常见数据科学错误

在 Unsplash 上由棕柽柳拍摄的照片

如果你是 NBA 篮球的粉丝,也是分析的粉丝,那你一定听说过 PER。

PER 是霍林格开发的一种综合统计。约翰目前为《运动报》撰稿,曾是孟菲斯灰熊队的篮球运营副总裁,也是《ESPN》和《体育画报》的专栏作家。他是四本篮球分析书籍的作者,是 NBA 分析社区的巨人。

根据霍林格的说法:

玩家效率等级(PER)是玩家每分钟生产力的等级。

PER 被正确地称为篮球高级分析运动的教父级统计数据之一。这是第一个调整比赛节奏、调整比赛时间和跨赛季标准化数据的篮球测量方法之一(该测量方法为每个赛季分配了 15%的平均球员)。《公共关系条例》仍然经常在广播和媒体中被引用。

它也有很大的缺陷。

有人说 PER 过于复杂。有人说它不足以解释防御。其他人说它高估了得分。

虽然上述说法可能是正确的,但真正的问题在于方法——这与数学无关,而与导致其不完善的数据分析方法有关。今天,我想把重点放在霍林格的 PER 研究方法上,希望我们所有人——作为数据科学家——在未来避免类似的错误。

方法学

在研究中,科学家遵循几个一般步骤:

  1. 观察一种现象。你看到了世界上的一些东西,想知道更多关于它是如何运作的。
  2. 开发研究问题。基于你所看到的,你提出你想要得到答案的问题。
  3. 寻找现有理论,必要时发展一种理论。对于大多数研究领域,有人已经做了一些工作。通过找到现有的理论,你就有了一个理解你所观察到的现象的很好的起点。有时候,你只需要现有的理论,但是——如果你找不到任何适合这种情况的理论——你可以发展自己的理论来恰当地描述世界上正在发生的事情。
  4. 创造一个可证伪的假设。这通常是最难的一步。为了测试一个理论,你必须找到一种表达方式,这样你就可以证明这个理论是错误的。例如,如果你的假设是“披头士是有史以来最伟大的乐队”,就没有办法证明或反驳这一说法。然而,如果你说“披头士是有史以来最畅销的乐队”,你可以看看实际的衡量标准,看看这种说法是否正确。确保你的假设遵循这个公式。
  5. 确定措施。现在,您已经创建了一个可证伪的假设,您可以确定哪些可观察的测量将有助于您测试该假设。
  6. 收集数据。前进并测量那边的变量。
  7. 分析数据。分析这些测量值,看看你的理论是否能准确解释观察到的数据,如果它们确实有解释力,你可以看看它们对你的数据集有多大的影响。
  8. 更新你的信念。如果你的数据符合某个理论,你现在就有了该理论的工作证据。如果你的数据不符合某个理论,那么你应该改变你对该理论真实性的信念(如果你不直接拒绝它的话)。
  9. 如果需要,运行更多测试。进行一次测试很少足以证实你的信念,而且你最终会根据你的发现提出更多的问题,这些问题可以在未来的分析中得到解答。

现在我们已经对研究方法有了基本的了解,让我们从理论上来看一下如何计算 NBA 的每分钟生产率。

我们理论上的 NBA 生产力研究项目

  1. 我们观察到一些 NBA 球员帮助他们的球队比其他人赢得更多。
  2. 我们想知道我们是否可以用一个单一的指标来衡量 NBA 球员每分钟的生产率。我们想看看我们是否能根据这个标准预测他们的团队有多成功。换句话说,我们想要创建一个预测团队胜利的玩家指标。
  3. 迪安·奥利佛斯有一个篮球成功的四因素理论。但是,它由四个因素组成,而不是一个,而且与团队成功更相关。因此,我们发展了一个理论,即个人球员的生产力可以通过基于我们对篮球运动的一系列信念的 boxscore 统计的综合测量来衡量。
  4. 我们陈述了我们的假设,玩家的生产力可以用一个单一的指标来衡量。如果这是真的,我们假设我们创建的玩家指标将显著预测玩家团队的生产力(即,玩家在我们的指标上的分数将预测他们的团队赢了多少场比赛)。
  5. 我们使用 boxscore 统计数据和我们对篮球的信念创建了一个我们的指标版本。这是我们的独立变量。我们用团队获胜的数量来衡量生产率,这是我们的因变量。
  6. 我们收集衡量指标和团队胜利的数据。
  7. 我们分析数据,看看我们的指标是否能预测团队获胜,以及我们的度量的效果大小(即,它预测实际团队获胜的“多少”),如果它确实能预测团队获胜的话。
  8. 我们根据指标与数据的吻合程度对指标进行修改,或者因为指标不符合数据而完全停止使用。
  9. 我们对我们的指标进行了更多的测试,并开发了更多的研究问题来回答我们的指标作为感兴趣的变量。

让我们把这个和我们看到的霍林格和佩尔的作品进行比较。

霍林格 PER 法

  1. 约翰观察到一些球员帮助球队比其他人赢得更多。
  2. 约翰想看看是否一个单一的指标可以预测球员的生产力。
  3. 约翰的工作基于迪安·奥利弗的四个因素,同时也根据他对篮球的信念增加了自己的权重。
  4. John 提出了一个关于单个衡量标准的假设——后来成为 PER——但没有对此做出可证伪的陈述(例如,PER 预测团队获胜)
  5. John 创建了他的 PER measure。他没有具体说明任何结果变量。
  6. 约翰收集他的测量数据。
  7. John 没有提供任何统计分析来验证 PER 是否能有效地预测生产率,因为他没有具体说明结果变量。我们也没有任何规定的 PER 效果大小。
  8. 尚未根据分析更新 PER。
  9. 那些仍然使用 PER 作为衡量球员生产力的标准的人没有对 PER 进行额外的测试。

霍林格写道:

然而,PER 能做的是用一个数字总结一个球员的统计成绩。这让我们能够统一我们试图在头脑中跟踪的每个球员的不同数据[……],这样我们就可以继续评估统计数据中可能缺少的东西。

本质上,霍林格着手:

  • 用一种方法总结 NBA 球员的统计成绩
  • 确保该方法能够有效地测量每分钟的生产率

他用 PER 实现了前一个目标,但在这个过程中,他未能进行基本的科学分析,以确保他的指标在实现后一个目标时在统计上是有效的。

数据科学需要遵循科学的方法

为霍林格说句公道话,他可能不认为自己是数据科学家。见鬼,他可能认为 PER 主要是他用来写作的工具,他可能已经更新了他对 PER 的个人信念。

但是他用 PER 所做的工作肯定属于数据科学的范畴,并且 PER 还没有作为一种统计方法被更新。如果他从一开始就遵循了基本的科学方法原则,那么他就可以很容易地避免一些错误。

此外,因为 PER 如此受欢迎,篮球分析社区的许多其他数据科学家也在犯霍林格犯的同样的错误。

让我们试着阻止它。以下是如何轻松地从 PER 中学习(并避免)数据科学错误的方法。

你应该避免的 3 个数据科学错误

1.不够具体

在数据分析中,非常重要的一点是要明确项目的各个方面。确保您:

  • 对你的假设有一个可证伪的陈述
  • 记住具体的因变量和自变量,以便进行有效的分析

如果你在开始提取数据之前不这样做,你基本上是在瞎跑,浪费很多时间。

如果霍林格对他的 PER 方法有更具体的描述,我们将很容易看到 PER 是否是一个有效的度量。就目前情况而言,我们不知道约翰所说的“生产力”在 PER 的上下文中是什么。我们都有自己的想法——我的想法是生产率应该以团队的胜利来衡量——但这都是基于我们个人的定义,而不是进行研究的科学家的明确定义。

2.未报告显著性和效应大小

这与前一点有联系——因为霍林格没有具体的结果变量,所以没有报道的发现。仍然使用 PER 的网站不报告 PER 是否能有效预测胜率,它预测胜率的百分比,或者任何其他关于潜在结果变量的发现。

对于你做的任何项目,必须报告你感兴趣的任何因变量的显著性和影响大小。

3.不基于数据更新

Basketball-Reference.com 和 ESPN 网站的 PER 值保持不变——这个指标从一开始就没变过。如果你打算做数据科学,你必须准备好基于你的发现进行迭代。

仅仅因为你以前对某件事有信念,并不意味着如果你发现了与此相反的证据,你就不应该更新这些信念。让数据引导你找到更好的理论和模型。

为什么 PER 仍然如此受欢迎?

尽管有缺陷,PER 仍然是一个被大量使用的 NBA 数据。这是为什么呢?

嗯,首先,我很确定它确实预测了团队胜利中的一些数量的差异(即使效果大小还没有明确说明)。还有文化相关性的问题——PER 现在已经深深地融入了 NBA 文化。

它的文化相关性归结为两件主要的事情:

  1. 这是第一个试图回答所有 NBA 球迷都感兴趣的问题的综合指标之一:谁是联盟中最有生产力的球员?
  2. 它以一种能引起普通 NBA 球迷共鸣的方式抓住了人们的兴趣。

15——平均每分——是一个相关的篮球得分。如果有人在篮球比赛中得了 15 分,我们认为他是一个好球员。如果有人得分在 20 多或 30 多,我们认为他们是伟大的球员。

从这个意义上说,PER 是聪明的。霍林格了解 NBA 球迷的心理,并确保他的测量是他的读者很容易认同的。

你应该在研究中使用 PER 吗?

见鬼。是的。

同样,PER 不是一个完美的衡量标准。但是通过将它包含在你的研究中,我们可以更好地理解它作为一种衡量标准的有效性——由于我们上面提到的问题,这是目前所缺乏的。您还可以将其他指标的功效与 PER 进行比较,为我们提供一个指标效率的基线。

解决 PER 问题的唯一方法是在数据科学环境中实际观察 PER——即使我们发现它不是我们所依赖的指标。

结论

就像乔治郝佳不应该被认为是有史以来最伟大的篮球运动员一样,我们也不应该被认为是篮球分析的目标。聪明的球队似乎已经不再用它来衡量球员的评价。希望广播公司和媒体成员也会远离它,因为我们对篮球比赛应该如何用统计方法来衡量有了更多的了解。

同时,PER 是篮球分析的文化基石。当我说我认为它应该被载入奈史密斯篮球名人堂时,我不是在开玩笑。

它可能不符合一些简单的科学原理,但如果没有它,我们可能仍然停留在篮球统计的黑暗时代。

作为数据科学家,我们应该尊重霍林格的所作所为,然后学会做得更好。

来源

根据 Basketball-reference.com 计算

霍林格,什么是 PER? (2007),ESPN

四大因素、Basketball-reference.com

开始 ML 项目前你需要知道的 8 件事。

原文:https://towardsdatascience.com/process-of-creating-an-effective-machine-learning-pipeline-815ecce30e98?source=collection_archive---------30-----------------------

从心中的目标开始。斯蒂芬·科维

由弗兰基·查马基在 Unsplash 上拍摄的照片

尝试为你的 ml 项目创建一个管道,这样其他人就可以从你的工作中获益。

为什么管道这个词有误导性,因为它意味着单向的,但是让我们看看如何以循环的方式思考 ML 管道。

注意:- 本文旨在指导您思考过程(Python 模块)以及创建有效管道所需回答的正确问题。 这是一篇更高级的文章,提供了创建生产级管道的示例技术 ,但是我建议您在开始之前浏览一下。

要以互动的方式了解 ML 管道,请查看资源管理器

🌀有一段时间,我认为 ML 管道是这些复杂的设计架构,只能由具有高编码和系统设计技能的软件工程师来完成,但在最近的技术如亚马逊 SageMaker 、 Apache Kafka 、微软 Azure 等的帮助下,这完全不是事实。管道可以以简单且经济的方式实现自动化和维护。🌀

管道是一种组织和自动化你的代码的方式,这样不仅你未来的自己,而且其他人也可以很容易地理解和集成它。ML 管道的一些目标是:

新错误 *⦿实时处理。 *****计算工作量 平衡 ⦿可扩展消息驱动 ******

在你开始深入研究、建立模型和预测未来之前,问自己这些问题。

① ML 问题框架:

你想解决的商业问题是什么?

你真的需要机器学习的方法来解决这个问题吗?

这里有一些提示,让你知道你是否需要一种机器学习方法。

  • 有没有你想了解的重复模式?
  • 您有理解这些模式所需的数据吗?
  • 了解要进行的预测类型,无论是二元/多分类问题,还是需要预测连续值(回归),如股票价格。

现在是时候询问领域期望并测试您的假设了。

在这个阶段,你问的问题越多,你的模型就越好。

  • 影响你预测的重要特征是什么?
  • 它们有重叠的特征吗?
  • 如何测试你的模型(这个不像拆分数据那么简单)?
  • 可以帮助您理解您正在解决的领域和问题的问题。

让我们继续无聊的部分,开始预测未来吧。

②数据收集与整合:

无论你或你的团队在哪里收集数据,都可能存在一些干扰。因此,您应该配备能够帮助您正确清理和集成数据的工具,并且应该能够处理所有类型的数据。

虽然这样做并不有趣,但却能产生有趣的结果。因为真实数据不是由数字和分类特征组成的,而是由垃圾和其他特征组成的。

便捷的数据清理工具:制表Scrubadubftfy更多链接

获取您的数据状态:

  • 加载数据pd.read_{filetype}('filename')
  • 获取数据的形状data.shape
  • 得到数据的统计信息data.describe()
  • 了解数据类型和信息data.info()data.dtypes
  • 了解缺失值的数量data.isnull().sum()

呜呜!我的数据看起来惊人,我迫不及待地运行我的模型并得到预测。没那么快!

③资料准备:

这就是数据科学家的真正技能发挥作用的地方。

从你的训练数据中随机抽取一个样本(任何不需要太多时间的大小),你需要深入挖掘,并且应该能够回答你的所有问题,例如。

  • 有什么特点?
  • 它符合你的期望吗?
  • 有足够的信息做出准确的预测吗?
  • 你应该删除一些功能吗?
  • 有没有什么特征没有被恰当地表现出来?
  • 标签在训练数据中分类正确吗?
  • 数据不正确会发生什么?
  • 是否有任何缺失值或异常值等。

如果你做了适当的功课,你将能够建立你的模型,而不用担心错误的预测。

我们如何通过编程来回答这些问题?这将带我们进入下一步👇

④数据可视化与分析:

我喜欢可视化,当你在图表上绘制你的数据时,它揭示了看不见的模式、异常值和我们直到现在才能够看到的东西。直方图和散点图等基本图可以告诉您许多关于数据的信息

你需要知道的一些事情是:

  • 试图理解标签/目标摘要。
  • 检测比例和分布的直方图: Data.plot.hist()
  • 散点图了解方差/相关性和趋势: Data.plot.scatter()
  • 检测异常值的盒式图: Data.boxplot()
  • 通过 Data.corr() (默认为 Pearson)获取相关系数,并通过 sns.heatmap(Data.corr()) 绘制这些值的热图,以便更好地理解特征和目标列之间的关系
  • 在 FacetGrid 上绘制分类图: sns.catplot()

你不想伤害你的模特吧。如果您的数据包含缺失值或异常值是不正确的数据类型,您的模型将受到影响。为了顺利运行您的模型,您需要承担清理它的负担。

需要考虑的事项:

  • 用均值、众数输入缺失值或使用非缺失值预测缺失值或深挖、链接、链接
  • 通过移除或深挖 链接、链接来处理异常值
  • 寻找相关特征等..

现在是你期待已久的部分。选择要运行的模型。

选择一个模型并不容易,因为模型的范围很广,而且所有的模型都有自己的基本假设。选择符合数据集假设的模型也是数据科学家的工作。

机器学习模型

下一步是什么?我现在可以运行我的模型了吗?是的,如果你不想要更好的结果(你不愿意冒任何代价的风险)。下一个部分可以说是机器学习管道中关键且耗时的部分。这只是经验之谈,但我会尽可能多的解释来帮助你开始。准备好!

雷切尔·亨宁在 Unsplash 上的照片

⑤特征选择和工程:

特征工程的主要思想来自于提问和你从上面的可视化过程中学到的东西。

值得问的问题有:

  • 这些特征有意义吗?
  • 我如何设计基于可视化的新特性?
  • 我可以通过合并旧特征来创建新特征吗?

特征工程技巧:

  • 将相似的列组合成一列。
  • 将分类转换为数字变量,如一个单词中的字母计数或一键编码、LabelEncoder 等。
  • 将时间转换成天数或月数。
  • 缩放数字特征,以便模型容易找到局部最小值。
  • 宁滨把数据列成组。(它对于处理异常值也很有用)

深挖——ML 精通、中等、 Kaggle 、精英、 Elite2

终于……哇哦!终于准备好接受训练了吗? 排序 :

⑥模型训练:

训练模型的步骤:

1.将数据分成训练、开发、测试:

  • 运行模型时,确保随机化数据以克服偏差。
  • 创建一个测试集,该测试集接近地代表训练集(分层测试集,相同的日期范围,等等..)
  • 使用交叉验证。

2.偏差方差:

  • 拟合不足=低方差和高偏差=简单模型
  • 过度拟合=低偏差和高方差=复杂模型
  • 超参数调整帮助您平衡模型偏差和方差。

万岁,你做到了……..!

该领工资了。运行模型。

库: Mxnet , Scikit-Learn , TensorFlow , PyTorch , Cloud AutoML , Pycaret , Theano , Keras , SciPy , NLTK , MLlib ,xgboos

抱歉!还没完成。有一些细节需要评估和解释,让你脱颖而出,例如:

⑦模型评估:

有不同的指标来评估你的模型,有时你可能必须想出你自己的指标来评估模型的性能。无论如何,这里有一些通用的度量标准,可以帮助你理解模型中哪里出错了,或者模型对于现实世界的准确性如何,或者理解为什么模型会在第一时间工作。选择正确的指标

不要只运行单个模型,运行多个回归/分类模型,并根据这里的指标选择最佳模型。

回归度量:

RMSE,MSE,调整后的挖深,视角

分类指标:

混淆矩阵、精确度、召回率、F1 分数、ROC、AUC 深入挖掘

结尾:

面对它你已经框定了问题,清理了数据,做了数据可视化,选择了重要的特性,做了特性工程。你一次又一次地通过调整超参数和在开发设备上测试来训练你的模型,还剩下什么?

⑧预测:

**Model.Predict(Test_Data)**和部署(这是一个完全独立的主题)

你的脑海中仍然会有一个疑问。

一切都很好,但这一切都只是理论,我该如何实施?

答:正如我之前所说,管道只是一个以系统方式解决问题的思考过程,以便将来易于调试:有一些工具,如*Amazon SageMaker这些工具在高层次上处理所有这些步骤,并为您提供额外的功能和工具来组织、监控和跟踪您的模型***

技巧

  • 当您想要测试多个模型时,建议在小数据集上测试模型,而不是在整个数据集上运行。
  • 检查对模型有帮助的重要特征,并继续在这些特征上进行工程设计。
  • 删除与目标变量没有任何关联的特征。
  • 使用最大投票或百分比集成不同的模型以实现更好的预测和随机化。
  • 建模不仅仅是一个一次性的步骤,你需要正确的可执行代码来重新运行你的模型,以适应当前的需求。

查看这个博客(即将发布),在这里这些步骤被用来解决一个真实世界的例子。

参考:

  1. 如何构建你的代码
  2. Github 给你的必备文件

👏在链接下方评论你的最佳项目。👏

带 R 的过程稳定性分析

原文:https://towardsdatascience.com/process-stability-analysis-with-r-9ec41ec5fc0d?source=collection_archive---------22-----------------------

r 代表工业工程师

解释质量控制图

图片由 Lukas 拍摄,可在 Pexels 获得

质量控制图

质量控制图是工程师监控一个过程是否在统计控制下的重要工具。它们有助于可视化变化,发现并纠正出现的问题,预测预期的结果范围,并分析特殊或常见原因导致的流程变化模式。

通过注意控制图上出现的某些类型的模式,可以在控制图上发现变化的特殊原因。为了真正抓住控制图的好处,必须认识到这种模式——以及它们在给定过程中所代表的东西——以找到变异的特殊原因背后的原因。为此,评估 8 个控制图规则来分析它们。

控制图区域

为了识别给定测量中的变化程度,控制图被分成平均值上下三个相等的区域。

  • 中线:对应被分析测量的平均值。
  • A 区:对应于中心线以上/以下 2 sigma 到 3 sigma 的区域。
  • B 区:对应于中心线以上/以下一个西格玛到两个西格玛的区域。
  • C 区:对应于从中心线到中心线上下一个西格玛的区域。
  • UCL(控制上限):对应于平均值以上的最大公差。
  • LCL(控制下限):对应于平均值以下的最大公差。

为了在统计控制下考虑一个过程,它的大部分点必须在中心线附近,而一些点可以更接近控制极限——全部没有模式——但是没有超出控制极限。

控制图规则

以下控制图规则用于识别给定过程中出现变化的特殊原因(即模式):

  • 规则#1 —超出限值:一个或多个点超出控制限值。
  • 规则# 2——A 区:A 区或更远的连续 3 分中的 2 分。
  • 规则# 3—B 区:B 区或 B 区以外的 5 个连续点中的 4 个。
  • 规则# 4—C 区:平均值一侧的 7 个或更多连续点(在 C 区或 C 区以外)。
  • 规则 5——趋势 : 7 个连续的向上或向下的点。
  • 规则 6 —混合物 : 8 个连续点,c 区没有点。
  • 规则#7 —分层:c 区 15 个连续点。
  • 规则# 8——超控:上下交替的 14 个连续点。

规则关联模式和可能的原因

  • 规则 1 和规则 2 :偏离平均值很大。 可能 c 原因 :执行工作的新操作员;错误的设置;测量误差;跳过了流程步骤;流程步骤未完成;停电;设备故障。
  • 规则#3 和#4 :平均值的小偏移。 可能 c 原因 :原材料变更;工作指令的变更;不同的测量设备/校准;不同班次;工人获得了更多的工作经验;维护计划的变更;安装程序的变更。
  • 规则五:趋势。 可能的 c 原因 :工装磨损;温度影响(例如冷却、加热)。
  • 规则 6 :混合物。 可能的 c 原因 :存在多个流程(如班次、机器、原材料)。
  • 规则 7 :分层。 可能的 c 原因 :存在多个流程(如班次、机器、原材料)。
  • 规则#8 :过度控制。 可能 c 原因 :操作员篡改;交替原材料。

虽然列出每种模式的可能原因很复杂,因为特殊原因高度依赖于过程的类型,但是上面列出的原因可以作为质量保证工程师进行头脑风暴会议的参考,以找出变化的特殊原因背后的原因。

对于下面的例子,让我们使用 R 软件分析 31 个随机点的过程稳定性控制。将对 8 条控制图规则中的每一条进行评估,以确定是否存在可归因于特殊原因引起的变化的趋势。我们来看看 R 代码!

首先,让我们从构建包含所有必要信息的数据框开始:

数据框如下所示:

接下来,让我们建立相应点的控制图:

作为第一印象,这个过程似乎在统计控制之下;所有点都位于控制上限和下限内。但是,有必要评估控制图规则,以确定数据中是否有任何趋势。

在接下来的步骤中,让我们将每个控制图规则的布尔值初始化为 true。 注意 :规则#1 到#5 被分成“上”和“下”规则,这取决于被分析的图表的哪一侧。

现在让我们构建每个控制图规则逻辑背后的代码。每个数据点的每个规则评估结果(即)将存储在一个新列中。

  • 规则一:

  • 规则二:

  • 规则三:

  • 规则四:

  • 规则五:

  • 规则六:

  • 规则 7:

  • 规则八:

最后一步,让我们创建控制图摘要数据框架,从最近日期开始按降序排列规则评估:

最终结果如下所示:

正如最初建议的那样,可以说这个过程是在统计控制之下的;所有数据点都位于控制范围内,并且不存在由于特殊原因导致的变化趋势。

总结想法

不受监控的流程无法改进。能够解释和理解质量控制图提供的信息是质量和工业工程师的一项重要任务,以识别由特殊原因产生的变化趋势。只有在它们被确定之后,过程改进的想法和项目才能在头脑风暴会议和质量圈里被计划,并最终被执行。

基于控制图规则评估数据点可能是检测过程中变化的最佳策略之一。然而,即使控制图规则在不同行业和统计学家之间可能略有不同,但它们几乎是相同的。质量和工业工程师必须精通阅读和解释质量控制图,以确保向客户交付符合其要求和规格的高质量产品。

— —

如果你觉得这篇文章有用,欢迎在GitHub上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的介质 简介 来探索我以前的文章。感谢阅读。

-罗伯特

用 Python 处理和可视化多个分类变量——NBA 的赛程挑战

原文:https://towardsdatascience.com/processing-and-visualizing-multiple-categorical-variables-with-python-nbas-schedule-challenges-b48453bff813?source=collection_archive---------6-----------------------

使用平行分类图和树形图来可视化、识别和比较数据中多个输入变量的影响:NBA 中的休息、旅行和主场。

可视化多个分类变量

今天,我想讨论处理、可视化和回顾分类变量的各种方法。当有多个分类变量时,处理和可视化数据可能会很棘手。

你可能见过有多种颜色和标记形状的交叉线条图,或者可能是支线剧情的网格。这些解决方案可以工作(并且工作得很好),但是它们远不是这个特定任务的唯一可用的绘图类型,今天我们将探索一些其他的方法。

至于数据,我们将使用篮球(NBA)输赢数据。更具体地说,我们将着眼于三个据说影响篮球比赛结果的关键外部因素;主场优势,旅行,休息日。

一如既往,虽然这篇文章利用了篮球数据,但它首先是一篇数据分析和可视化的文章。因此,专门针对篮球的讨论保持在相对最小的范围内,之前的篮球/NBA 知识是不必要的(尽管欣赏鼓励😉).

在开始之前

数据

我将代码和数据包含在我的 GitLab repo here (在 nba_travel_impact 目录中)中,如果您愿意,您应该能够通过下载/克隆 repo 来轻松跟进。

包装

我假设您熟悉 python。即使你相对来说是新手,这个教程也不应该太难。(请在 twitter 上找到我,并告诉我您是否想要更多指导。)

你需要pandasplotly。用一个简单的pip install [PACKAGE_NAME]安装每一个(在你的虚拟环境中)。

显然,你可以使用任何图形包,但我个人更喜欢你用 Plotly 得到的简单和强大。

NBA 赛程—影响

每个 NBA 常规赛在十月和四月之间进行。(例如,2019-20 赛季将在 10 月 22 日至 4 月 15 日之间举行。)在这段时间里,每支球队打 82 场比赛,平均每场比赛只有 2.15 天。比赛之间勉强算一天休息。

不仅如此,NBA 球场遍布美国和多伦多。为了平衡赛程,他们有一半的比赛要在客场进行,球队必须像乘地铁一样往返于两地之间。

所有 29 个 NBA 球场都在一张地图上

事实上,NBA 球队每年的行程大约在 60,000 到 85,000 公里(37,000-53,000 英里/年)之间,他们的飞行总的来说是这样的:

所有 30 支 NBA 球队的旅行日程-可视化

(我关于可视化旅行数据的文章,以及一个交互式的 html 版本的地图)

所有这一切的结果是,旅行,比赛和休息的场地是 NBA 日程的重要组成部分。

82 场比赛中,每支球队有一半在主场进行,另一半在客场进行。甚至许多主场比赛也不总是需要休息——可能需要旅行一夜才能回来,他们甚至可能为了下一场比赛而马上离开。

对于我们这些不得不乘坐商业航班的凡人来说,这将是一场噩梦。然而,现代 NBA 球员乘坐私人团队飞机,他们的健康和福祉管理得如此之好,以至于旅行不会对他们产生重大影响。让我们找出答案。

加载/获取数据

在我们分析休息、比赛和主场优势的影响之前,我们需要收集或加载我们的数据。为了方便起见,我用上一季的,但是(你也可以用这一季的,或者几季的。

虽然您可以简单地加载我已经预处理过的数据(如果您愿意,可以跳到我加载box_df的地方),但是如果您感兴趣的话——我是这样编译数据的:

我从basketball-reference.com获得了时间表数据,你可以简单地从我的回购中加载如下数据:

schedule_df = pd.read_csv('srcdata/2019_nba_schedule.csv', index_col=0)

该数据包括 EST ( est_time)中的游戏提示时间,因此我创建了一个 date 列。

schedule_df = schedule_df.assign(game_date=schedule_df.est_time.dt.date)

然后,game_dates = schedule_df.game_date.unique()获得一个独特的比赛日期列表,之后用basketball_reference_web_scraper包下载我们每个日期的数据。如果你想尝试这段代码,你需要用pip来安装它。

我在这里做的是下载数据,将每场比赛标记为主场比赛或客场比赛,并保存数据帧。

无论如何,让我们加载一个我之前为保持一致性而准备的文件:

box_df = pd.read_csv('srcdata/2019_nba_team_box_scores.csv', index_col=0)

看一下box_df,你会看到它包含 2460 行,与 30 支球队的 82 场比赛相匹配,因为每一行都显示一支球队的盒子分数。

简单的故障

我在这里处理了数据,以包括布尔列,表示球队是否在home比赛,他们是否有travelled,以及他们是否赢了(win)。我还为休息日的数量创建了一个分类变量(rest_cats),任何超过 2 天的都被归在一起,包括开幕日。

对于我们的第一次可视化,让我们看看有多少游戏属于休息日和旅行的每一个类别。我会跳过主客场平分,这是 50:50。

import plotly.express as px

# How many games in each category?
temp_grp_df = box_df.groupby('rest_cats').count().reset_index(drop=False)

fig = px.bar(temp_grp_df, y='rest_cats', x='outcome', orientation='h')
fig.show()

2018-19 赛季,按休息日

# How many games in each category? Rest days & travel.
temp_grp_df = box_df.groupby(['rest_cats', 'travelled']).count().reset_index(drop=False)
temp_grp_df = temp_grp_df.assign(travelled=temp_grp_df.travelled.astype(str))
fig = px.bar(temp_grp_df, y='rest_cats', x='outcome', orientation='h', color='travelled', barmode='group')
fig.show()

2018-19 赛季,按休息日&是否涉及旅行

这很简单,分类变量在这里可以简洁地表示为成组的条形。

至于产出,有几个观察要做 NBA 的时间表是这样的,大多数比赛有 1 天的休息,没有多少背靠背(0 天休息)的比赛。

即使有,也似乎主要是主场比赛(因为不涉及旅行),这对球队来说是好事。

对成功百分比的总体影响

现在,让我们来看看休息和旅行对胜利的影响。这样做的代码与前面的基本相同,除了现在为每个组创建一个WIN%列,它成为我们的因变量。

travel_cats = ['rest_cats', 'travelled']
travel_grp_df = box_df.groupby(travel_cats).sum()
travel_grp_df = travel_grp_df.assign(games=box_df.groupby(travel_cats)['minutes_played'].count())
travel_grp_df['WIN%'] = travel_grp_df.win/travel_grp_df.games * 100
travel_grp_df.reset_index(drop=False, inplace=True)
travel_grp_df = travel_grp_df.assign(travelled=travel_grp_df.travelled.astype(str))fig = px.bar(travel_grp_df, y='rest_cats', x='WIN%', orientation='h', color='travelled', barmode='group')
fig.show()

趋势正如所料——旅行不利于获胜,多休息更好。但是,有趣的是——旅行过的队伍(红色)在休息 2 天以上的情况下赢得了几乎一半的比赛!

现在,增加这些图表的复杂性是分析开始变得具有挑战性的地方。

我们有三个分类变量,我们试图分析,我们需要选择如何可视化它们,同时也表明因变量(例如,win %)。对于条形图,一种选择是使用上面提到的支线剧情:

travel_cats = ['home', 'rest_cats', 'travelled']
...
fig = px.bar(travel_grp_df, y='rest_cats', x='WIN%', facet_col='home', orientation='h', color='travelled', barmode='group')

作为支线剧情

这很好,但是它仍然缺少相当多对我们有用的信息。例如,它没有向我们展示这些分类变量是如何重叠或相互作用的。此外,支线剧情并不容易沿着轴线进行比较。

相反,让我们探索一个平行的类别图表。

平行类别图

创造

因为它们有些不寻常,所以让我们画一个,然后讨论它们包含的内容。幸运的是,用 Plotly 绘制平行分类图相对容易。事实上,Plotly Express 只是将原始的 box score 数据帧作为参数,并根据我们传递的类别来编译数据。

看看这个简单的例子,用二进制类别表示hometravelled

# PARALLEL CATEGORIES - THREE CATEGORIES AND WIN %
box_df = box_df.assign(win_num=box_df.win.astype(int))
travel_cats = ['home', 'travelled']
fig = px.parallel_categories(box_df, dimensions=travel_cats, color='win_num')

平行类别图—显示“家庭”和“旅行”

你可能以前没有见过很多平行分类图表。它们看起来很复杂,但是一旦你掌握了窍门,它们就非常简单。

每个垂直柱代表一个类别,每个带显示了沿着每个柱的分类变量的排列。上面的图表代表两个分类变量,我也根据结果(赢或输)将它们分开,代表三个变量。

平行类别图—显示“家庭”和“旅行”

在这里,它显示有 329 场比赛(乐队)球队在主场(左栏),在比赛前旅行(右栏),并取得胜利(彩色)。

图表的本质是,每增加一个类别都会增加图表的复杂性,潜在地呈指数增长。看看下面的图表,增加了休息日长度的类别。

平行类别图—显示“家”、“旅行”和“休息 _ 猫”变量。

下面的示例显示了两条高亮显示的路径。

最上面的深色路径显示了球队在客场(home==false)、前往比赛(travel==true)以及休息 2 天或更长时间(rest_cats == 2+ Days)的比赛失败的次数。

下方的黄色路径显示了相同标准的比赛数量,但是球队赢得了比赛。

平行类别图—显示鼠标悬停弹出窗口

(这里有一个互动版的这个给你试试&玩一玩。)

一旦我们习惯了这种格式,通过平行类别图表探索多维分类关系会令人耳目一新。在这里,每一个竖线显示了总的胜率,简单地跟随粗线揭示了强共现的位置。

举例来说,让我们来看看球队没有休息,并且旅行的比赛。这张截图突出显示了在客场比赛的球队的记录。

团队记录—出门在外,没有休息日

已经很清楚的是,损失远远大于收益。客队在这些比赛中只赢了大约 32%(总共 237 场)。

另一方面,反过来说,一个主场球队在无休日赢得了 83 场比赛中的 69%(我将把它作为一个练习——你自己看看这里)。

我发现平行分类图非常有用,尤其是对于数据探索。例如,我发现这张图表非常有用,视觉效果也很突出(我为本文准备了这张图表)。

我早些时候创建的一个——通过区域和助攻显示克莱的投篮(灰色:无帮助)

这张图表显示了克莱·汤普森的所有射门,按照射门位置,以及助攻来自谁。虽然最初看起来很复杂,但看看找出类别的主要组合是多么容易。如图所示,平行分类图可以很容易地发现趋势和共现。

诚然,虽然平行类别图表在某些情况下很有用,但它也有其局限性。根据我的经验,它可能需要读者做一些工作来理解正在发生的事情,并且对许多人来说,它可能是视觉上的对抗和恐吓。

另一个很好的、可能更简单的可视化这类数据的方法是树形图。

树状图

树形图是探索分级、分类数据集的一种奇妙方式。看一看这个例子,就知道它有多容易理解了。

一个树形图的例子( Plotly )

尽管树形图通常用于评估分层数据结构的影响,但它也是一个很好的工具,适用于像这样的多变量情况。

我们可以在这里生成树形图,方便地显示每个组的大小,以及随着我们越来越深入地研究每个类别,胜率的变化。

因为树状图需要层次结构,所以我们在这里通过绘制两种不同的树状图来探索:

首先,层级基于回家/离开旅行/不旅行休息日

树状图 1:回家->旅行->休息

在第二种情况下,层级被更改为基于回家/离开休息日出差/未出差

树状图 2:回家->休息->旅行

树形图布局很好地显示了每个子集样本大小的差异,以及颜色百分比的变化。

在这两个图中,很明显,对胜率的更大影响通常来自于休息的时间,以及仅仅是在家还是在外,而不是来自于他们是否旅行。

看看上面的图表,在第二层的方框中(标有“旅行/停留”),是主场比赛。主队在比赛前回家(即旅行)的比赛的总赢/输百分比与他们没有旅行的比赛非常相似。

在第二张图中,所有盒子在休息日的总体胜率有很大不同,例如休息日为 0 的客场比赛是最差的(正如我们前面在平行类别图中看到的)。

让我们再探讨一点,结束今天的分析。到目前为止,我们是从一个球队的角度来看这些数据的(除了主客场数据,这是一个补充)。如果对手的休息数据也是会怎么样?

出于这个原因,我得到了另一个数据集——对手的休息日被添加到opp_rest_cats列中。

box_df = pd.read_csv('srcdata/2019_nba_team_box_scores_2.csv', index_col=0)travel_cats = ['home', 'rest_cats', 'opp_rest_cats']
travel_grp_df = box_df.groupby(travel_cats).sum()
travel_grp_df = travel_grp_df.assign(games=box_df.groupby(travel_cats)['minutes_played'].count())
travel_grp_df.reset_index(drop=False, inplace=True)

chart_cats = ['home_str', 'rest_cats', 'opp_rest_cats']
home_away = pd.Series(['Home ' * i for i in travel_grp_df.home.values]) + pd.Series(['Away ' * (1-i) for i in travel_grp_df.home.values])
travel_grp_df['home_str'] = home_away
travel_grp_df['rest_cats'] = travel_grp_df['rest_cats'] + "' Rest"
travel_grp_df['opp_rest_cats'] = 'Opponent: <BR>' + travel_grp_df['opp_rest_cats'] + "'<BR>Rest"
travel_grp_df['WIN%'] = travel_grp_df.win/travel_grp_df.games * 100

fig = px.treemap(
    travel_grp_df, path=['home_str', 'rest_cats', 'opp_rest_cats'], values='games', color='WIN%', color_continuous_midpoint=50, color_continuous_scale=px.colors.diverging.Portland
)
fig.show()

树状图 3:主场->休息->对手休息

看那个!最佳和最差的赢/输百分比发生在其余差异最大的时候。

看看左边的“客场”统计,我们的球队休息 0 天,对手休息 2 天以上,相反,我们的球队休息 2 天以上,对手休息 0 天。他们代表了极端的对立面。这种模式一直存在,休息的差异是获胜几率的一个重要因素。

即使主队背靠背,他们平均也能击败其他背靠背的球队,显示了家常菜的价值。最中立的安排似乎是让主队背靠背,而客队长时间休息。

那不是很有趣吗!?事实证明,旅行是一个相对较小的因素,赢/输百分比的最大因素是休息差和主场/客场。通过这些树形图很容易发现这一点。

总而言之,我希望以上展示了一些有用的例子和技术,用于钻取包含多个分类变量的数据集。

在我看来,平行分类图和树形图是这样做的有用工具,也是潜在未被充分利用的工具。

当数据被细分时,树形图在可视化数据方面是有效的,在属性的向下钻取和变化方面,而平行类别图在识别数据点的同现和流动方面是极好的。用你自己的数据集来尝试这些,我很乐意听到更多关于它们的信息。

如果你喜欢这个,请说👋/关注 twitter ,或点击此处获取更新。我还写了这篇关于使用 Plotly 绘制 NBA 旅行数据的文章,如果你以前没有读过的话:

[## 交互式和动画旅行数据可视化—绘制 NBA 旅行地图

了解如何使用 Python 和 Plotly 创建位置和路径数据的精彩互动和动画可视化。

medium.com](https://medium.com/swlh/interactive-animated-travel-data-visualizations-mapping-nba-travel-a154a2e7c18d)

还有这篇关于我最喜欢的数据可视化书籍的文章。

[## 用这些书创建有影响力的数据可视化

如果没有交流,好的分析没有什么意义。数据可视化会有所帮助。以下是我对…的建议

towardsdatascience.com](/create-impactful-data-visualizations-with-these-books-ca9fbfecfde5)

谢谢,下次再见!

作为社会科学程序员处理不同的数字数据

原文:https://towardsdatascience.com/processing-different-digital-data-as-a-social-science-programmer-d5dc33629bb1?source=collection_archive---------27-----------------------

照片由 @gemasaputera 拍摄

文本、声音、数字、代码、图像、视频等等

昨天我和一个社会数据科学的同学进行了讨论,我们问自己为什么社会科学家经常处理数字或文本数据。我没有量化社会科学家的数量。然而,这是我目前所看到的印象。如果你是一名经济学家,处理数字数据似乎更直接,而且有可能通过合作来处理法律,特别是在涉及政治利益和政治政策考虑的情况下(可能是这种情况)。例如,如果考虑税收政策。

就我所见,音频、图像和视频数据减少的原因可能很容易解释。在社会科学家经历的教育经历中,他们经常被教导通过文本交流。我想不出有哪种社会科学教育会在很大程度上利用图像、视频或音频中的训练。这些无疑是表达的媒介,是交流或传播研究的场所。因此,也许奇怪的是,他们没有在更大程度上考虑研究和教育。

出现了几个与这次讨论有关的问题。按出现的顺序:

  • 有可能量化社会科学家在传播研究、记录和处理中使用的数据吗?
  • 如果你尝试,你会如何分类研究论文?
  • 社会科学领域总共有多少篇研究论文?
  • 哪些学科可以被认为是社会科学的一部分?
  • 如果研究是以一种形式进行的,它可能被用于其他形式的交流,人们如何能够发现这是否可能是事实呢?
  • 为什么这会有价值?

当这些问题出现在我的脑海中时,我将试图简要地回答这些问题,当然是临时性的,以引发可能的讨论。

为什么这会有价值?

我觉得最后一个问题可能先回答比较容易。研究进行的方式和涉及的方法——材料研究是研究团体感兴趣的。它还可以说明某一科学学科的整体研究方法或途径。

如果研究是以一种形式进行的,它可能被用于其他形式的交流,人们如何能够发现这是否可能是事实呢?

这似乎几乎不可能。如果一个人要这样做,那么他可能必须首先这样做。成功分类数百万份文档,然后尝试跟踪介质中的部分文档。如果一个研究项目以某种方式保留了它被设计的格式,并且从未传播到其他格式,这是非常值得怀疑的。这就变成了一个问题,是应该只考虑收集的材料还是研究交流的形式。大多数已经完成的研究是否会列出其他类型的工作表现/文档/表达?这是一个不同的问题,很难回答。

哪些学科可以被认为是社会科学的一部分?

根据《大英百科全书》:“社会科学包括文化(或社会)人类学、社会学、社会心理学、政治学和经济学。还经常包括社会和经济地理以及那些处理学习的社会背景和学校与社会秩序的关系的教育领域如果要进行这样的研究(如果可能的话),那么就有可能考察这些学科或其中的几个学科。在这一过程中,必须认识到,其他人可能对社会科学的范围有不同的定义。

社会科学领域总共有多少篇研究论文?

这似乎很难回答。这似乎也不是一个富有成效的问题。一方面,为什么一个人要试图从一段时间里收集该领域所有可能的知识。另一方面,如果将这一数据限制在过去五年内每个领域中最大的五种期刊上,就会出现问题。这可能是一个开始,而且似乎更有可能,如果一个人应该决定。在这种情况下,作为一种思想出现的是数据类型的差异,甚至是数据的基本概念。

如果你尝试,你会如何分类研究论文?

政治学家、经济学家和人类学家对数据有什么不同的看法。这种理解可能并不普遍,但简单地将其归类为文本、图像、视频等可能会令人困惑/无益。如果要找到专门处理【数字】数据的文章,研究每个领域中什么被认为是【数字】可以是一种分类方式。来自研究的数据可能在不同的领域中遵循一定的标准,至少在最常见的叙述中。从某种程度上来说,收集大量信息并进行分类只会强化叙述或偏见。也许更有建设性的做法是,问问对数字方法更感兴趣的社会科学家如何处理不同类型的数据。此外,这些类型的探索性研究如何与该领域现有的方法或从业者相结合。分类是否足够有用,以至于需要收集大量的研究来尝试分类?

有可能量化社会科学家在传播研究、记录和处理中使用的数据吗?

是的,这是可能的。我认为这是可以做到的。研究研究人员如何研究很有趣。另一个方面是通过搜索模式——引用模式——引导或管理的整体知识生产的治理变化。搜索模式似乎已经发生了变化,研究的管理方式也值得考虑。我之前写过这个问题,因为研究的方式正在发生变化,在某种程度上不可避免地会受到一系列不同算法的影响。

[## 人工智能和学术搜索引擎

人工智能正在改变研究的方式

medium.com](https://medium.com/dataseries/ai-academic-search-engines-acf971717fbf)

当我与我的同学交谈时,我的第一个想法是,更多地分析视频数据可能会很有趣,然后一个大的隐约出现的问题击中了我。如何切实可行地做到这一点?通过将视频数据与其他来源相结合,可以更好地探索哪些社会科学主题?会出现哪些伦理问题?

你怎么想呢?

PS:当我提到社会科学程序员时,它涉及到将 编程作为社会科学 的讨论。越来越多的社会科学家不仅在研究编程人员,还在学习编程语言并将其融入他们的方法中。

这里是#500daysofAI,您正在阅读的是第 459 条。500 天来,我每天都在写一篇关于或与人工智能相关的新文章。

用 Python 多线程处理大型数据文件

原文:https://towardsdatascience.com/processing-large-data-files-with-python-multithreading-dbb916f6b58d?source=collection_archive---------8-----------------------

在左侧车道加速行驶。

2020 年 zapalote.com

我们花费大量时间等待一些数据准备任务完成——你可能会说,这是数据科学家的命运。我们可以加快速度。这里有两种技术会派上用场:内存映射文件和多线程

数据

最近,我不得不从 Google Books Ngram corpus中提取术语和术语频率,我发现自己在想是否有办法加快这项任务。语料库由 26 个文件组成,总数据量为 24GB。我感兴趣的每个文件都包含一个术语和其他元数据,用制表符分隔。将这些文件作为熊猫数据帧读取的暴力方法非常慢。因为我们只需要唯一的术语和它们的匹配计数,所以我想我会尽量让它更快:-)

内存映射文件

这种技术并不新鲜。由来已久,起源于 Unix(Linux 之前!).简而言之,mmap通过将文件内容加载到内存页面中来绕过通常的 I/O 缓冲。这对于内存占用量大的计算机非常适用。对于今天的台式机和笔记本电脑来说,这基本上没问题,因为 32GB 的内存不再是一个深奥的问题。Python 库模仿了大多数 Unix 功能,并提供了一个方便的readline()函数来一次提取一行字节。

# map the entire file into memory
mm = mmap.mmap(fp.fileno(), 0)# iterate over the block, until next newline
for line in iter(mm.readline, b""):
    # convert the bytes to a utf-8 string and split the fields
    term = line.decode("utf-8").split("\t")

fp 是一个文件指针,之前用r+b访问属性打开过。这就对了,通过这个简单的调整,你已经使文件读取速度提高了一倍(好吧,确切的改进将取决于许多因素,如磁盘硬件等)。

多线程操作

下一个总是有助于提高速度的技术是增加并行性。在我们的例子中,任务是 I/O 绑定的。这非常适合于扩展— 即添加线程。你会发现关于什么时候在搜索引擎上横向扩展(多处理)更好的讨论。

Python3 有一个很棒的标准库,用于管理线程池并动态地给它们分配任务。所有这一切都通过一个极其简单的 API 实现。

# use as many threads as possible, default: os.cpu_count()+4
with ThreadPoolExecutor() as threads:
   t_res = threads.map(process_file, files)

ThreadPoolExecutormax_workers默认值是每个 CPU 内核 5 个线程(从 Python v3.8 开始)。map() API 将接收一个应用于列表中每个成员的函数,并在线程可用时自动运行该函数。哇哦。就这么简单。在不到 50 分钟的时间里,我已经将 24GB 的输入转换成了一个方便的 75MB 的数据集,可以用 pandas 来分析——瞧。

完整的代码在 GitHub 上。随时欢迎评论和意见。

PS:我给每个线程加了一个带tqdm的进度条。我真的不知道他们是如何设法避免屏幕上的线条混乱的…它非常有效。

更新:两年后,这个上来了:-)

在 Python 中用 Unicode 处理文本

原文:https://towardsdatascience.com/processing-text-with-unicode-in-python-eacc226886cb?source=collection_archive---------22-----------------------

数据科学家的最佳实践

照片由 Kayla Kozlowski 在 Unsplash 上拍摄

我们能够阅读这些文本行,因为我们熟悉英语中使用的 26 个字符的拉丁字母。其他语言有他们自己的字符,他们都需要被编码,这样他们就可以被我们的计算机所代表。几十年来,计算机能够根据 ASCII 码表来表示字符。

ASCII 表

ASCII 是一种在 8 位代码的 256 个可用位中分配字母、数字和其他字符的标准。对于不使用拉丁字母的语言,如汉语、希腊语、日语,ASCII 无法表示这些文本,我们需要一个新的字符集。它们是 Unicode。

Unicode 表

Python 中的文本可以用 unicode 字符串或字节表示。

编码 unicode 字符串

让我们在 Python 中定义一个string,看看它的类型。

它确实是一个str类型的对象或者一个字符串。如果我们定义一个字节。(我们可以用 *bytes* 函数将字符串转换成字节对象)

我们尝试定义一个包含非 ASCII 字符的 byte 对象(中文“Hello,World】)。

我们可以用前缀 b 定义一个字节

它显示了一个错误,告诉我们需要先将包含非 ASCII 字符的字符串转换成 bytes 对象。

我们将需要提供和编码来做到这一点如下。

这部分代码的结果如下图所示。

处理编码的一个更好的方法是使用encode()函数。

正如你所看到的,我们得到了和以前一样的结果。

请记住,默认情况下,Python 3 使用 utf-8 编码。

因为 Python 3 默认使用utf-8,所以我们应该如何使用不同的编码,我们简单地把它传递给函数。例如,我们可以如下编码utf-16中的‘hello world’字符串。

解码字节

Unicode 字符串可以用一些预定义的编码方式编码成字节,比如utf-8utf-16等。字节可以解码为 unicode 字符串,但这可能会失败,因为在特定的编码中,并非所有的字节序列都是有效的字符串。

没有简单的方法来确定在字节串中使用什么类型的编码。

unicode 和字节之间的转换通过encode()decode()函数完成。我们尝试做相反的操作,解码字节对象,如下所示。

没有简单的方法来确定在字节串中使用什么类型的编码。

因此,我们需要提供正确的编码(utf-8、utf-16 等。)到解码方法

正则表达式模式

请记住,正则表达式模式也适用于非拉丁字符。在这里,我们如何删除 US-ASCII 字符范围之外的字符?

这部分代码的结果如下图所示。

从 csv 文件中读取 UTF 8 编码的数据

下面的例子演示了如何用 Python 从 csv 文件中读取“utf-8”编码的数据。

很简单,对吧?这完全是关于用 Python 中 Unicode 处理文本。

参考

[1]https://www.ascii-code.com

[2]https://home.unicode.org

机器学习中未标记数据的处理

原文:https://towardsdatascience.com/processing-unlabeled-data-in-machine-learning-2552e3fdf7c1?source=collection_archive---------52-----------------------

构建机器学习概念

引入混合处理,并将其与主动学习和直推式和归纳式半监督学习结合起来

在专栏“构建机器学习概念”中,我试图从机器学习(ML)空间中提取概念,并将它们投射到新的、可能不寻常的框架中,以提供新的视角。该内容面向数据科学社区的人们,以及对 ML 领域感兴趣的精通技术的个人。

由作者创建。包括由 Vectra AI 和 taviphoto 通过 iStock 制作的图形。

介绍

T 他在“构建机器学习概念”的最后一部分中致力于提出一个新的框架来映射监督、自我监督、非监督和强化学习。我认为这些才是我们在 ML 中应该考虑的真正“纯粹”的学习风格。

写这篇文章的触发点是我的公司在现实世界场景中自动化人类标签任务的工作。我总是渴望将我们正在尝试做的事情与研究的行话相匹配,但从未真正对那里提出的概念感到满意。让我们详述一下。

混合处理、主动学习以及直推式和归纳式半监督学习

混合处理的概念

当我谈到人工标记任务时,我指的是人工完成 SL 问题的业务流程。这可以是对媒体公司中的图像进行内容审核(例如,在“可安全发布”和“不可安全发布”之间做出决定),通过组织路由传入的电子邮件和文档(“部门 1”、“部门 2”、…),或者从传入的 PDF 订单中提取信息(“name”、“IBAN”,...).对于其中的许多人来说,现在通常只有人工流程,这可以从自动化中受益。

理想情况下,你不要试图实现 1 比 1 的替换,而是开始使用算法将明显的情况自动化,并将剩下的工作留给人类。在我的公司 Luminovo ,我们一直在思考如何构建一个 ML 系统,当用于一步一步地自动化纯人工智能过程时,它真正实现了持续学习的承诺。我们称之为混合处理,因为我们正在使用人类-人工智能混合来实现处理数据的目标。

我们通常要么从零知识开始,要么从预先训练好的基础模型开始。一开始,我们的模型没有足够的信心来自动化任何事情,所以所有传入的数据点都由人来标记。因此,她不仅完成了任务,还以新的输入输出对的形式向模型提供了反馈,该反馈可用于重新训练。

两个数据集的故事&人在回路中

当向 ML 社区的朋友解释这个概念时,它经常被比作主动学习 (AL)。抛开大多数自动化任务的“在线性质”(相对于在正常的人工智能设置中批量消耗数据),我从来没有完全热衷于这种比较,因为人工智能的首要目标是用“尽可能少的数据”创建“尽可能好的模型”。另一方面,混合处理不关心模型的质量,至少不是它的主要目标。相反,我们的目标是给尽可能多的数据点贴上自己的标签,只把不确定的数据点发送给人类。

当试图概括这一点时,我意识到在“结构化机器学习概念”系列的最后一部分中解释的半监督学习 (SemiSL)的整个概念非常符合这些考虑。请记住,在 SemiSL 中,我们试图在训练期间将少量(通常很少)已标记的数据与大量未标记的数据结合起来。这类似于我们想要在人工智能和混合处理中实现的目标,但是,我们缺少一个重要的元素:人在回路中。对于 SemiSL,我们无法访问“oracle ”,而是被给定的带标签的数据所困。此外,这个过程不是“在线”的,这意味着时间的概念不是一个关键的驱动因素。

当研究 SemiSL 理论时,我确实找到了我一直在寻找的分裂:SemiSL 可以是直推式的,也可以是归纳式的。对于直推 SemiSL,目标是为未标记的数据推断正确的标记;对于归纳 SemiSL,我们希望推断出从 X 到 Y 的正确映射,或者换句话说:尽可能构建最佳模型。

轻量级定义

  • 混合处理:ML 模型根据人类获得的数据,按照他们正常的标记程序,不断地进行训练。随着模型的每一个改进版本,其置信阈值都被重新校准,允许随着时间的推移自动处理越来越多的数据点。
  • 艾尔:我们正试图通过不断地决定我们应该如何使用我们的“标签预算”来改善一个潜在的 ML 模型,例如,支付一名受过训练的医生来诊断/分类一些 x 射线扫描。有各种形式的人工智能,区分在给定时间我们可以访问未标记数据的哪些部分(场景)以及我们如何决定标记哪些实例(查询策略)。
  • 直推 SemiSL: 我们的目标是在第一个数据集中的少量标签的帮助下,为未标记的数据集提供标签。此外,我们期望三个假设中的至少一个成立:连续性(接近的点共享一个标签)、聚类(聚集的点共享一个标签)和流形(位于低维平面上的点共享一个标签)。
  • 归纳 SemiSL: 我刚刚解释的 SemiSL 的一般假设仍然成立,但我们现在试图推断数据和标签的真实输入输出关系,而不关心将标签分配给特定的、潜在的噪声数据点。因此,我们的模型不仅关心手边未标记的例子,还关心即将到来的新例子。

2x2 矩阵

2x2 矩阵,用于混合处理、AL 以及直推式和感应式半固态。由作者创建。

再一次,我提出一个简单的 2x2 矩阵,具有以下维度:

目标:处理数据还是改进模型?

处理数据

改进模型 还是我们只关心改进模型,即找到从输入到输出的真实映射?

有没有人在回路中?

是的 我们能接触到能给我们提供标签的“神谕”吗?

还是我们只剩下已经收集到的信息?

关于所有这些象限,尤其是关于 AL 及其场景和查询策略,您可以写得更多。我将把这个留给另一篇博文。

关闭

在这篇文章中,我终于找到了关于人工智能如何转化为现实世界场景的个人结论。我介绍了混合处理作为一种新的范式,我们的目标是尽可能高效地解决人类标记任务。结合已知的 AL 和直推式&感应式 SemiSL 概念,我们能够建立一个 2x2 矩阵,询问我们是否旨在改进基础模型,以及我们是否能够接触到人在回路中。

如果你有任何其他非常规的映射,对此事的想法,或者对我们在 Luminovo 的工作感兴趣,我很乐意收到你的来信。你可以在 Linkedin 上留言或联系我。

构建机器学习概念的第三部分是关于迁移学习的新观点。请随意查看。

产品直觉和数据叙事

原文:https://towardsdatascience.com/product-instinct-and-data-storytelling-ce0a216249e6?source=collection_archive---------28-----------------------

苹果 | 谷歌 | SPOTIFY | 其他

内特·尼科尔斯在 TDS 播客

编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris、Edouard Harris 和 Russell Pollari 主持。他们一起经营一家名为sharpes minds的数据科学导师创业公司。可以听下面的播客:

如果说有一个趋势是,在进入 2020 年之前,似乎没有足够多的数据科学家关注,那就是:数据科学家正在成为产品人。

五年前,情况完全不是这样:数据科学和机器学习风靡一时,经理们对花哨的分析和过度设计的预测模型印象深刻。今天,一剂健康的现实已经到来,大多数公司都将数据科学视为达到目的的手段:它是改善真实用户和真实付费客户体验的方式,而不是一种冷静自圆其说的神奇工具。

与此同时,随着越来越多的工具不断让非数据科学家的人构建和使用预测模型变得越来越容易,数据科学家将不得不擅长新事物。这意味着两件事:产品本能和数据故事。

这就是为什么我们想与 Nate Nichols 聊天,他是一名数据科学家,后来成为叙事科学公司(Narrative Science)的产品架构副总裁,该公司致力于简化数据通信。内特也是《让你的人成为人》的合著者,这是一本关于数据故事的(免费)书。他有很多很棒的见解要分享,以下是几个重要的亮点:

  • 大学不是学习如何解决产品问题的地方,因为学术研究倾向于强调工具而不是理解用例。你可能从硕士毕业时就有了预测建模的坚实基础,但是根本不知道如何决定你应该首先做什么样的。
  • 数据叙事是一项至关重要的技能。你可以对你的数据进行出色的分析,但是如果你不能向你的经理解释你的结果,你就不能为公司增加价值。
  • 例如,招聘经理注重讲故事,通常看重你描述自己思维过程的能力,以及用高于之前工作附加值的客观指标的数据进行论证的能力。这很重要。
  • 好的讲故事能力不是任何人与生俱来的;这需要练习。写博客,在当地会议上做报告,或者在 youtube 上录制一段讲解视频——然后,寻求反馈。训练和验证不仅仅针对机器学习模型😉
  • 你不能把交流和解释分开。如果你发现你很难向其他人解释你的最新项目,注意他们在哪里感到困惑:很有可能,你自己的想法中也有需要填补的漏洞。

你可以在 Twitter 这里关注内特,或者在 LinkedIn 这里关注他。

夹子

youtube.com

我们正在寻找能与我们的观众分享有价值的东西的客人。如果你碰巧知道谁是合适的人选,请在这里告诉我们:publication@towardsdatascience.com。

基于关联规则学习的产品布局、定价和促销策略

原文:https://towardsdatascience.com/product-placement-pricing-and-promotion-strategies-with-association-rule-learning-d37f2b70d29e?source=collection_archive---------20-----------------------

实体店中的产品植入在购买量中起着重要的作用

使用 Apriori 算法提供产品推荐、产品放置、定价和捆绑策略

想象一下,如果我们能够了解客户的下一次购买会是什么!想象一下,如果我们能够发现购买行为的模式,并将其用于我们的优势!未来的钥匙在历史中!

市场购物篮分析有助于零售商根据大量交易确定目录中各种产品之间的关联。这些信息可用于推动产品定价、捆绑和投放。

想象一下,你有一家超市,你想增加产品的销量。您希望根据顾客购物车中的商品或他们之前购买的商品,为顾客提供购买商品的建议。你甚至可能想推荐随产品一起购买的最受欢迎的商品。

交易数据可能是洞察的金矿

分析的第一步是收集数据。所以你在你的商店里找出了过去一年的大量交易记录。每笔交易的兴趣点是购买的物品。

有些交易可能非常罕见。例如,有多少人会在一次交易中购买面包和一把剪刀?我敢说没几个人值得麻烦。另一方面,一起购买面包和黄油的交易数量肯定是一个非常大的数字,因为人们很有可能会购买黄油和面包一起吃。因此,我们可以这样把面包和黄油联系起来:

如果一个人买面包,那么一个人可能会买黄油

在交易历史中可能会出现许多这样的产品组合。

然而,要使产品之间有很强的关联,这些组合必须经常被购买。为了不在罕见的组合上浪费时间,可以设置截止频率、 、f 、。算法中不考虑出现次数少于 f 的任何项目组合。这个最小频率 f 叫做 支持

支持=项目组合在所有交易中出现的次数/交易总数

在根据项目组合的频率过滤事务之后,我们剩下的是具有更高频率的事务。在这些交易中,如果你想在两个项目之间建立一个关联规则,比如说面包和黄油,你还想确定在所有面包和黄油的组合中至少出现了一定的次数。这个频率叫做 信心

置信度= i1 和 i2 在所有事务中出现的次数/i1 出现的事务数

注意:如果两个项目同时出现的置信度很低,那么任何包含这两个项目的组合的置信度也会很低。

如果面包和剪刀不是很频繁的一起买,那么直觉上剪刀、面包和鞋子也不会买的那么频繁。这是根据子集频率消除许多组合的基础。

现在,您有了一组事务,其中只有那些具有足够大的支持度和置信度的项目组合才会出现。

让我们看看这在实践中是如何工作的。让我们看看下面的 12 笔交易:

交易清单样本

从上面的列表中,我们看到蔬菜和葡萄,以及意大利面和肉丸被频繁购买(分别是 12 次中的 4 次和 12 次中的 3 次)。

让我们通过 Apriori 算法找出这样的产品关联。
首先要设置的是支撑。假设只考虑那些在交易中至少出现 3 次的项目。让我们用 S(item)来表示对一个项目的支持。

S(虾)= 4
S(杏仁)= 2
S(牛油果)= 4
S(蔬菜)= 7
S(葡萄)= 4
S(汉堡)= 4
S(肉丸)= 4
S(意大利面)= 6
这就排除了杏仁,因为杏仁的支持度只有 2。

让我们试着在意大利面和肉丸之间建立一种联系。为此我们需要树立信心。让我们把它设为 0.35。这意味着至少 35%有意大利面的交易必须有肉丸。让我们定义两个项目 C(项目 1,项目 2)的置信度。

我们知道 C(item1,item2) = S(item1,item2)/Support(item1)

C(意大利面、蔬菜)= 3/6 = 0.5
C(意大利面、汉堡)= 2/6 = 0.33
C(意大利面、牛油果)= 3/6 = 0.5
C(意大利面、葡萄)= 2/6 = 0.33
C(意大利面、肉丸)= 3/6 = 0.5
C(意大利面、虾)= 2/6 = 0.33

基于我们选择的信心,意大利面似乎与蔬菜、鳄梨和肉丸有很强的联系。

但是我们能说置信度越高,产品之间的关联就越强吗?

置信度可能是一个有偏差的度量,因为它只考虑一个组成项目的支持度。为了解释膨胀的信心,我们使用 Lift。升力是指物品组合的支撑与组合中单个物品支撑的乘积之比。

升力=支撑(i1,i2)/((支撑(i1)*支撑(i2))

很自然,项目组合的提升越高,项目之间的关联就越高。

现在让我们重新考虑意大利面与其他项目的关系。让我们将两个项目的提升表示为提升(项目 1、项目 2)。

L(意大利面、蔬菜)= 3/(76) = 0.071
L(意大利面、汉堡)= 2/(4
6) = 0.083
L(意大利面、牛油果)= 3/(46) = 0.125
L(意大利面、葡萄)= 2/(4
6) = 0.083
L(意大利面、肉丸)= 3/(46) = 0.125
L(意大利面、虾)= 2/(4
6)

基于 Lift,我们看到意大利面和蔬菜之间的关系并不像信心所显示的那样紧密。意大利面和鳄梨、意大利面和肉丸之间的联系最为紧密。
类似地,可以在任意数量的项目之间建立关联。

根据我们的计算,我们如何改进我们的营销工作?

  1. 植入式广告:植入式广告有两种方式。放置相关产品的一种方法是将这些产品放在彼此靠近的位置,这样顾客就不需要看其他地方了。
    如果你想让顾客在拿到想要的商品之前冲动购物,那么就让这两件商品在商店里尽量远离。
    比如尽量保留意大利面和肉丸,让顾客穿过所有其他过道从意大利面过道走到肉丸过道。当他们经过不同的通道时,顾客可能想要购买他们以前没有计划购买的物品。
  2. 产品促销和定价:从上面的练习中,我们发现意大利面与肉丸和鳄梨有着密切的联系。为了推广这种组合,可以提供意大利面和肉丸/意大利面和鳄梨组合的促销优惠。可以对相关联的商品进行捆绑定价,这样客户就会有兴趣购买产品捆绑包,而不是单个商品。

摘要

Apriori 算法用于确定在多次交易中购买的商品之间的潜在关系。用于建立项目-项目关联的三个关键指标是:
1 .支撑
2。信心
3。电梯

举例来说,已经使用了 2 项组合,但是如果它们通过了最低支持和置信水平,也可以建立更大的组合(3 项及以上)。

参考文献:

阿格拉瓦尔河和斯里坎特河(1994 年 9 月)。挖掘关联规则的快速算法。在过程中。第 20 国际。糖膏剂超大型数据库,VLDB (第 1215 卷,第 487–499 页)。

机器学习模型的生产和部署——III

原文:https://towardsdatascience.com/production-and-deployment-of-machine-learning-models-iii-66e2bff419bb?source=collection_archive---------34-----------------------

为执行端到端预测而实施的架构框架。

为了建立一个不折不扣的机器学习系统,在这里我们获取数据,训练我们的模型,然后部署模型为客户服务,我们需要一个适当设计的架构。我们应该直接探索一些重要的设计架构。

我们将触及所有的结构,并详细阐述我工作的那个。但首先我想直观地解释一下这个操作。

假设总的来说,人们现在已经对模型构建过程有了一个公平的理解。我假设我们已经训练和测试了我们的模型,结果是模型(M)。这是我们将坚持的模式。

你说的模型持久性是什么意思?

模型持久性意味着将模型保存到磁盘上。

简单地说,模型持久化意味着将你的模型保存到磁盘上。

技术定义:模型持久性是保存和加载机器学习模型的能力。希望有一种方法来保持模型以供将来使用,而不必重新训练。

Pickle 和 Joblib 是您在模型持久化过程中经常会听到的术语。

您可以将您的模型称为持久 python 对象。您可以将此文件存储到硬盘或固态驱动器中。

此时,模型保存在磁盘上。下一步是部署模型。

简单来说,部署的意思是您的模型如何与公司或组织架构中的其余系统进行交互,这听起来很模糊!坚持住…

绿色的大圆圈是公司已经实施的系统架构。两个深灰色圆圈代表该架构中的对象。这些对象可以是运行不同服务的单独的盒子,其中一个特定的盒子是存储我们的模型的地方,用红色表示。

没有什么比一个例子更能让人们参与到这个主题中来了。

今天,你厌倦了那些恼人的自助餐厅谈话(他们总是关于谁在做什么,左对右和上帝!人们确实有自己的看法,坦白地说,我对几乎所有事情都不感兴趣。你回到家,坐在床边舒适的椅子上休息,几分钟后,你决定去看电影。你打开浏览器,输入网飞。当它打开你想看的电影时,你会在底部看到 5-6 部类似电影的推荐。页面除了推荐你的电影还有很多东西。

我不能使用实际的网飞页面来举例说明。但我会尽力给你足够的见解,让你开始明白这一切。

你打开浏览器,输入了网飞的地址。当网飞打开你选择的电影时,页面也有其他细节(它有一个加入和订阅,它在侧边栏上有另一个菜单和一些更多的选项。这是当你点击网站时发生的事情,网站连接到它的服务器,服务器上运行着许多服务,这些服务对页面有贡献。服务器将连接到一种服务类型的数据库,加入和订阅将通过不同类型的服务来执行,类似地,您将在底部获得的类似电影(作为推荐)将通过连接到服务器的 ML 服务盒来执行。所有这些服务同时运行,为您提供结果。

在上图中,你可以认为一个星形或三角形是不同的服务,在页面底部也是相似的电影,尽管系统上运行着 ML 服务。一个页面有许多部分,对于每个部分,它将调用不同的服务并获取数据。web 服务器将从各种服务中提取数据,并对其进行整理以生成页面。在我们的例子中,将有一个 m1 的这样的服务,它是推荐相似电影的服务(推荐系统)。

这个服务像其他服务一样运行在不同的机器上,它不会在实际的服务器上。它将位于运行模型“M”的系统中。服务器从盒子中调用类似的电影服务。它将向该服务发送一个请求(向它所在的框发送,考虑图中的蓝色框),该服务将使用类似的电影进行响应,以占据页面上的特定空间。这更像是面向服务的架构。

设计方法

这是一种方式,我们部署我们的模型。该模型在一个盒子上运行,我们将带有数据的请求(我们称之为特征化数据的数据,前面讨论过)推送到盒子,它将响应一个结果(可能是类似产品、电影、预测价格等的推荐)。).

对于请求,服务器;发送请求的服务器和给出输出的 ML 服务器就数据的格式达成一致(格式对流程至关重要)。

这就是所发生的事情,目的是给你直觉,我将在后面详述这些部分。

我讨论的方法是一个 Web API 方法。在这种方法中,模型被离线训练和持久化,然后被上传到一个 web 应用程序中,当客户端将关于给定电影的细节发布到 rest API 时,该应用程序可以给出类似电影的实时预测。这是一种类型的架构,它需要更多的细节,但目前重要的是理解这个想法。

一种方法是离线训练你的模型,然后作为一个请求,例如,客户将上传一个包含输入细节的电影 CSV 文件,然后等待一段时间,等待一封电子邮件或一条消息告诉他们检查网站的结果。这个应用程序将使用异步任务队列执行批量预测,这些结果将保存到一个共享数据库中,然后 web 应用程序可以访问该数据库来显示结果。

您也可以创建自己的示例,尝试使用 amazon 页面,该页面有如此多的服务,从订单详细信息按钮到产品详细信息,再到购买此产品的人也购买了这些产品,并尝试围绕它构建部署理念,我相信您能够理解。

请在评论中给出一些有价值的反馈,以便我改进。谢谢你。

生产级 R 闪亮假人:原型制作

原文:https://towardsdatascience.com/production-grade-r-shiny-with-golem-prototyping-51b03f37c2a9?source=collection_archive---------17-----------------------

使用假人软件包从头开始制作一个健身应用程序

本教程结束时您的仪表板|作者图片

这是一个激动人心的时代,成为一名开发者——R Shiny 正被越来越多地采用,让数据科学家制作快速、漂亮的 web 应用程序来共享数据,甚至提供面向公众的数据产品和仪表板访问。R Shiny 让非 web 开发人员快速启动并运行应用程序,但也让数据科学家和数据分析师在依赖性管理、可再现性、测试和部署责任方面成为 web 开发人员或软件工程师。随着 R Shiny 在各个领域的采用,一个全新的 production Shiny 工具已经开发出来,以帮助应对开发由数据科学家和非 web 开发人员创建和维护的健壮、可持续和可复制的 R Shiny 应用程序的挑战。事实上,我认为即使你不认为你的应用程序是真正的产品软件,你也可以从在你的开发工作流程中使用闪亮的产品工具中获益。

在本教程中,我将介绍使用一个名为假人的新包在开发中启动并运行 R Shiny 应用程序的基础知识,该包是专门为开发生产就绪的 R Shiny 应用程序而设计的自以为是的框架。出于本教程的目的,我们的客户是我,我们将专注于构建一个举重应用程序的原型。

在本教程中,您将学习:

  • 用户访谈和原型制作的基本思想
  • 基本线框绘图
  • 如何使用 shinipsum 包让 R 中的工作原型充满填充文本和演示图形

第 1 部分:需求收集和线框图

用户访谈

您可能想知道为什么这个部分在这里——来吧,看看代码!好吧,在我们开始在 R 中混日子之前,我们可能应该花点时间弄清楚我们要做什么!这可能是所有开发步骤中最被低估的一步:实际定义我们想要构建什么。幸运的是,假设这个应用程序的用户是我(或我们),这应该是一个非常简单的用户访谈!

核心功能

  • 从 Fitbod 上传更新的导出数据(我在那里生成并跟踪我的锻炼)
  • 记录我在一段时间内提升了多少重量,让我有成就感
  • 跟踪我在不同锻炼中每次锻炼的总运动量
  • 追踪我在不同训练中预计的 1 次重复最大值
  • 追踪我每个肌肉群举起了多少

线框

在我们开始编码之前的最后一步,我保证。我们将快速(手动)勾画出我们要建造的东西,这样我们就知道我们要做什么了。如果你愿意的话,有很多很酷的交互模型工具,但是我们现在要保持简单,只是把它画出来。我在平板电脑上画出了这个,但是笔和纸也可以。

首先,让我们画出我们想要的主仪表板页面和数据上传的样子:

带有数据上传弹出框以及仪表板页面上的图表和列表的仪表板的绘图。作者照片。

我们还可以绘制另外两个选项卡,以包含在我们的用户访谈中概述的特定运动统计数据和肌肉群统计数据的内容。

(顶部)一个选项卡的绘图,允许选择一个练习,最大投影 1 个重复和两个图形。| ( 底部)允许用图形和表格选择肌肉群的标签的绘图。作者照片。

第 2 部分:假人入门

创建和设置应用程序

与假人一起启动一个项目看似简单。首先,确保你已经用你的老朋友install.packages('golem')安装了它。

安装 golem 后,你应该可以在 RStudio 菜单中进入“文件”->“新目录”->“使用 golem 打包闪亮的应用程序”。

您也可以通过在 RStudio 控制台中键入golem::create_golem("projectName")在命令行上创建您的项目。

从这里,假人将打开大量的文件,让你去!让我们从编号为 1.1 的评论处的dev/01_start.R开始。继续操作,在golem::fill_desc()函数中填写您的姓名、包名等。我更喜欢提前设置我的回购,所以我将在 GitHub 上创建一个空的回购,并在这里输入 URL。

现在让我们打电话给golem::set_golem_options()来安排这一切。我们还将保留注释“1.2-设置公共文件”中的所有内容,就像现在一样。

我们现在将运行golem::use_recommended_tests()来为单元测试添加一个文件夹,稍后我们可以使用 testthat 来添加。测试允许您自动化您用来确保您的代码正确工作的过程。为什么应该使用单元测试?嗯,这个说的很好:

我开始使用自动化测试,因为我发现我花了太多的时间重新修复我以前已经修复过的 bug。在编写代码或修复错误时,我会执行交互式测试以确保代码正常工作。但是我从来没有一个系统可以存储这些测试,这样我就可以在需要的时候重新运行它们。我认为这是 R 程序员的普遍做法。不是你不测试你的代码,而是你不自动化你的测试。

由哈德利·韦翰和詹妮弗·布莱恩创作

现在我们运行golem::use_recommended_deps()来添加假人推荐的依赖项。这些是您在开发过程中几乎肯定会用到的包。

我还将运行golem::use_utils_ui()golem::use_utils_server(),因为我从来不会拒绝一些我以后可能需要的很好的预写函数。这些并不是绝对必要的,但是它们为一些常见的任务增加了一些功能,可能会帮到我们。

这样,我们就可以开始原型制作了!

使用 shinipsum 构建 UI 原型

还记得我们想画的画吗?好了,现在是时候看看当我们实际上试图使它闪闪发光时,它是否看起来很好!

原型是一种很好的方式,可以在你完成构建之前检查你的用户需求。当人们可以看到一个应用程序的样子并玩它时,即使它还没有最终的信息,他们也会澄清他们想要什么,因为他们意识到应用程序缺少一些东西,或者他们不喜欢或不想要他们认为必不可少的功能。

我们将尝试傀儡世界的一个有趣的新部分来做我们的原型:{shinipsum}

像往常一样,我们将开始安装它:install.packages('shinipsum'),我们会让傀儡知道我们将使用它与usethis::use_package("shinipsum")

让我们开始原型制作吧!

如果我们回头看看我们的图表,我们会看到我们实际上有三个选项卡(我没有计算让我们的用户上传数据的初始弹出窗口)。

这意味着有三个模块,每个页面一个,可能是一个好的开始。

让我们使用 golem 创建我们的第一个模块!在您的 R 终端中,您可以使用 golem 的功能直接添加模块基础设施:

golem::add_module(name = 'Home')

现在让我们添加其他模块:

golem::add_module(name = 'Exercises')

golem::add_module(name = 'MuscleGroup')

酷-我们有两个模块!让我们按照新创建的模块中所说的那样做,并在主 UI 和主服务器中添加对这些模块的引用,这样应用程序就知道要调用它们。一旦你将这些块粘贴到了R/app_ui.RR/app_server.R文件中的正确位置,就可以随意删除模块文件底部的注释块。

现在让我们回头看看第一页的绘图,开始制作我们的模块。

显示占位符文本、图形和表格的仪表板线框。|作者图片

嘿,导航部分看起来很重要,所以让我们先关注它。我们希望这看起来很漂亮,所以我们要拿出华丽闪亮的 UI 设计的大枪:

install.packages("shinydashboard")
install.packages("shinydashboardPlus")
usethis::use_package("shinydashboard")
usethis::use_package("shinydashboardPlus")

我们将把侧边栏放在我们的主R/app_ui.R文件中,因为我们希望它在我们所有的页面上都可见。现在请听我说,因为这将会是一段疯狂的 UI 代码之旅。

app_ui <- function() {
  tagList(
    # Leave this function for adding external resources
    golem_add_external_resources(), # Define this page as a dashboard page to signal we're using the     dashboard page format
    shinydashboardPlus::dashboardPagePlus(

      header = shinydashboardPlus::dashboardHeaderPlus(
        title = "Fitbod Tracking Dashboard",
        enable_rightsidebar = FALSE
      ), # Create our navigation menu that links to each of the tabs we defined
      sidebar = shinydashboard::dashboardSidebar(
        shinydashboard::sidebarMenu(
          # Setting id makes input$tabs give the tabName of currently-selected tab
          id = "tabs",
          shinydashboard::menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
          shinydashboard::menuItem("Muscle Group View", icon = icon("th"), tabName = "mg"),
          shinydashboard::menuItem("Exercise View", icon = icon("bar-chart-o"), tabName = "ev"
          ))
      ),# Show the appropriate tab's content in the main body of our dashboard when we select it
      body = shinydashboard::dashboardBody(
        shinydashboard::tabItems(
          shinydashboard::tabItem("dashboard", mod_Home_ui("Home_ui_1")),
          shinydashboard::tabItem("mg", mod_MuscleGroup_ui("MuscleGroup_ui_1")),
          shinydashboard::tabItem("ev", mod_Exercises_ui("Exercises_ui_1")
          )
        ) 
      ),
      rightsidebar = NULL,
      title = "FitBod App Monitoring Dashboard"
    )
  )
}

只是为了好玩,让我们也添加一些东西到我们的每个模块页面,这样我们就可以知道我们的导航是否正常工作。

在每个R/mod_TABNAME_ui.R文件中,添加一条线来表示哪个标签显示在tagList(之后

例如:

mod_Home_ui <- function(id){
  ns <- NS(id)
  tagList(
  h1("Welcome HOME!")
  )
}

现在让我们看看这是否可行!如果你是一个更有经验的 Shiny 开发者,你可能已经注意到我们没有在任何地方采购我们的模块,并且在我们的任何脚本上都没有“运行应用”按钮。这些部分都集成到了假人的基础设施中!那么,我们如何运行我们的应用程序呢?让我们导航到dev/run_dev.R脚本。

哎,那个run_app()命令好眼熟啊!因为我们在 golem 中将我们的应用构建为一个包,所以我们在自己的包之外运行run_app()函数。让我们继续运行这个脚本吧!

假设一切正常,我们应该会看到这样的内容出现:

带有侧边栏和文本“嗨,我是肌肉群标签”的仪表板|作者照片

太棒了。让我们现在开始充实这些页面。

所以让我们使用{shinipsum},这样我们现在就不用担心数据了。我们将需要好的旧的{ggplot2},所以如果你没有安装它,请安装它,并记住在你的 R 终端使用命令usethis::use_package("ggplot2"),这样 golem 知道当它运行我们的应用程序时加载这个包。

在我们的R/mod_Home.R文件中,我们可以改变占位符文本,使其看起来更像我们期望看到的,并添加占位符图形和表格。

一些注意事项:

  • 当你在 golem 应用程序中调用函数时,你需要确保使用::符号附加包。这无论如何都是一个好的实践,因为它确保了当函数名称冲突时,您使用的是正确包中的正确函数。
  • 我们使用了shinydashboard::box()函数以最少的工作给我们提供了漂亮的格式化盒子——这是这些包的一大优点!
  • Shinipsum 为我们提供了自动的假数据来绘制图表,因此我们还不必担心我们的数据。
  • 我们正在使用模块,所以我们需要在输出标签周围使用ns(),这样我们的命名空间才能正常工作。
mod_Home_ui <- function(id){
  ns <- NS(id)
  tagList(
    fluidPage(
      fluidRow(
        column(width = 5,
          h2("Welcome!")),
          br(),br(),br()
        ),
      fluidRow(
        column(width = 10,
          shinydashboard::box(
            background = "blue",
            h2("You lifted XYZ xx times!"),
            title = "Congrats!"),
              br(), br(), br(), br()
          )),
      fluidRow(
          shinydashboard::box(
                 title = "Top Exercises",
                 width = 6,
                 DT::dataTableOutput(ns('data_table'))),
          shinydashboard::box(
            title = "Total Weight Lifted",
            width = 6,
            plotOutput(ns("plot"))
      )
    )
  )
  )
}mod_Home_server <- function(input, output, session){
 ns <- session$ns

 output$data_table <- DT::renderDT({
   shinipsum::random_DT(5, 3, "numeric")
 })

 output$plot <- renderPlot({
   shinipsum::random_ggplot(type = "line")
 })
}

现在,如果您再次运行您的应用程序(记住,我们现在从dev/run_dev.R脚本中执行此操作),它应该看起来像这样:

一个仪表板,带有一个包含占位符文本的框、一个包含随机数据的占位符表格和一个包含随机数据的占位符图形。|作者照片

那看起来好多了!是时候完成另外两个标签的原型了。记住,我们的运动和肌肉群选项卡应该是这样的(根据我们的线框):

显示占位符文本、图形和表格的“锻炼”选项卡和“肌肉群”选项卡的仪表板线框。|作者图片

幸运的是,我们可以重用仪表板页面中的大量代码。所以在R/mod_Exercises.R我们将充实这个演示界面!

一些注意事项:

  • 我们现在已经对输入框中的选项进行了硬编码,但是稍后我们会用我们的数据填充它!
  • 你会注意到我们再次使用了框,以及一个闪亮的功能,为我们的用户创建一个基于他们想看什么练习的过滤点。
mod_Exercises_ui <- function(id){
  ns <- NS(id)
  tagList(
    fluidPage(
      fluidRow(
          h2("Exercise Progress for "),
          selectizeInput(
            inputId = ns("exercises"), 
            label = "",
            # Hard coded for now, but we'll deal with this later!
            choices = c("Dumbell Bicep Curl", "Deadlift"),
            selected = "Dumbell Bicep Curl",
            width = '50%',
            multiple = FALSE)
      ),
      fluidRow(
        column(width = 10,
               shinydashboard::box(
                 background = "blue",
                 h2("Your current projected 1 rep max is x!"),
                 title = "Congrats!")
        )),
      fluidRow(
        shinydashboard::box(
          title = "Total Weight Per Workout",
          width = 6,
          plotOutput(ns("plot2"))),
        shinydashboard::box(
          title = "Max Weight Per Workout",
          width = 6,
          plotOutput(ns("plot3"))
          )
      )
      )
    )
}mod_Exercises_server <- function(input, output, session){
  ns <- session$ns

  output$plot2 <- renderPlot({
    shinipsum::random_ggplot(type = "line")
  })

  output$plot3 <- renderPlot({
    shinipsum::random_ggplot(type = "line")
  })
}

太好了!如果您运行您的应用程序,您的“练习”选项卡现在应该是这样的:

带有占位符选择输入框、占位符文本和两个占位符图形的仪表板。|作者图片

我打赌你能猜到我们要在肌肉群选项卡上做什么!试着根据我们已经写好的东西自己做一个,但是如果你需要帮助,我的代码在下面。

R/mod_MuscleGroup.R中:

mod_MuscleGroup_ui <- function(id){
  ns <- NS(id)
  tagList(
    fluidPage(
      fluidRow(
        h2("Muscle Group Progress for "),
        selectizeInput(
          inputId = ns("muscles"), 
          label = "", 
          choices = c("Back", "Hamstrings"),
          selected = "Back",
          width = '50%',
          multiple = FALSE)
      ),
      fluidRow(
        shinydashboard::box(
          title = "Max Weight Over Time",
          width = 6,
          plotOutput(ns("plot4"))),
        shinydashboard::box(
          title = "Top Exercises",
          width = 6,
          DT::dataTableOutput(ns('data_table2'))
          )
        )
    )
  )
}mod_MuscleGroup_server <- function(input, output, session){
  ns <- session$ns

  output$plot4 <- renderPlot({
    shinipsum::random_ggplot(type = "line")
  })

  output$data_table2 <- DT::renderDT({
    shinipsum::random_DT(5, 3, "numeric")
  })
}

最终结果应该是这样的:

带有占位符选择输入框、占位符图形和占位符表格|按作者排序的图像的仪表板

现在我们已经有了一个功能完整的原型,可以展示给我们理论上的用户(在这里是我们)了!我们可以使用原型图更容易地根据用户的反馈进行修改,而不是处理我们所有的数据争论,当我们不必在用户看到任何东西之前让整个应用程序工作时,我们可以更快地向用户提供原型。一旦我们的用户批准了最终的线框,我们将准备好以正常的方式构建我们闪亮的应用程序的其余部分,我们都设置好了使用假人基础设施的自动化测试和基于 Docker 的部署。

如果你有任何问题,本教程的所有代码都在我的 Github 库里。

使用 Google BigQuery 和 PySpark 生产 ML 项目:预测酒店取消

原文:https://towardsdatascience.com/productionising-ml-projects-with-google-bigquery-and-pyspark-predicting-hotel-cancellations-8bf94fdc4af?source=collection_archive---------35-----------------------

数据科学家经常陷入数据科学的探索阶段,即在特定数据集上运行多个模型并优化准确性。

机器学习的探索阶段无疑是重要的。在生产过程中投入大量时间和资源之前,确保模型正确运行并具有预测能力是必要的。

然而,总是有在这个阶段花费太多时间而在生产上花费不够的风险。也就是说,整理来自多个来源的数据,并确保基础设施适合处理大型数据流。

这是一个使用梯度推进分类器预测酒店取消的 ML 管道示例。在这个例子中,为两个不同的酒店(H1 和 H2)构建并运行了两个模型。

管道

具体来说,管道设置如下:

  1. 从酒店取消表中选择的列从 Google BigQuery 数据库下载到带有 pythonbq 的 Jupyter 笔记本中,Python bq 是 BigQuery 的 Python 客户端。
  2. 使用 pyspark 初始化 Spark 会话。进行相关的数据转换是为了让 GBTClassifier 能够处理相关的数据。
  3. 进行 80/20 训练测试分割,以允许模型评估训练集的不可见部分的性能。
  4. 模型预测从 Spark 转换为 pandas 数据框架,然后导出为 CSV。然后,这些预测被读回 Jupyter 笔记本,并生成一个混淆矩阵来评估模型的准确性。

谷歌大查询

首先,H1 的相关 CSV 文件可以上传到 Google BigQuery 并存储为表格。

来源:谷歌大查询

在这种情况下,选择了模式的“自动检测”选项,并生成了表。

下面是 Google BigQuery 中显示的表格:

来源:谷歌大查询

与 PySpark 的相互作用

Spark 专为处理“大数据”而设计。虽然本例中数据集的大小仍然适合使用 Python 本身固有的模型运行,但是我们假设随着更多的数据添加到数据库中,最终将需要使用 Spark 来高效地处理这些大数据批次。此外,Spark 更适合处理不断流动和更新的数据。

Spark 会话用 pyspark 初始化,pythonbq 用于从 BigQuery 加载数据:

import pyspark
conf = pyspark.SparkConf()conf.set('spark.local.dir', 'path')
sc = pyspark.SparkContext(conf=conf)from pythonbq import pythonbqmyProject=pythonbq(
  bq_key_path='json_file',
  project_id='project_id'
)

以下是 Jupyter 笔记本中所选功能的表格显示:

加载相关特征和输出标签:

from pyspark.ml import Pipeline
from pyspark.ml.feature import OneHotEncoderEstimator, StringIndexer, VectorAssembler
categoricalColumns = ["Country", "MarketSegment", "ArrivalDateMonth", "DepositType", "CustomerType"]stages = []
for categoricalCol in categoricalColumns:
    stringIndexer = StringIndexer(inputCol=categoricalCol, outputCol=categoricalCol + "Index")
    encoder = OneHotEncoderEstimator(inputCols=[stringIndexer.getOutputCol()], outputCols=[categoricalCol + "classVec"])
    stages += [stringIndexer, encoder]label_stringIdx = StringIndexer(inputCol="IsCanceled", outputCol="label")
stages += [label_stringIdx]numericCols = ["LeadTime", "ArrivalDateYear", "ArrivalDateWeekNumber", "ArrivalDateDayOfMonth", "RequiredCarParkingSpaces"]
assemblerInputs = [c + "classVec" for c in categoricalColumns] + numericCols
assembler = VectorAssembler(inputCols=assemblerInputs, outputCol="features")
stages += [assembler]

gbt 分类器

现在可以加载 gbt 分类器(或梯度增强分类器)来用相关数据进行训练。

from pyspark.ml.classification import GBTClassifier

partialPipeline = Pipeline().setStages(stages)
pipelineModel = partialPipeline.fit(dataset)
preppedDataDF = pipelineModel.transform(dataset)gbtClassifier = GBTClassifier()
trainedModel = gbtClassifier.fit(preppedDataDF)

在将数据分成 80%训练和 20%测试时,可以训练分类器。

gbtModel = gbtClassifier.fit(trainingData)
predictions = gbtModel.transform(testData)
selected = predictions.select("label", "prediction", "probability")

我们来评价一下模型。

from pyspark.ml.evaluation import BinaryClassificationEvaluator
evaluator = BinaryClassificationEvaluator(rawPredictionCol="rawPrediction")
evaluator.evaluate(predictions)

该模型返回的评估值为 0.9131。

预测现在可以转换成熊猫数据帧并导出到 CSV:

selected.toPandas().to_csv('h1predictions.csv')

再次导入预测时,这里有一个包含结果的混淆矩阵。

f1 得分的总体准确率为 84%,而召回率为 66%表明该模型正确识别了 66%取消酒店预订的客户。

对 H2 表运行相同的程序——下面是混淆矩阵结果。

f1 分数的准确率为 94%,而回忆率为 79%。

结论

在本例中,我们看到:

  • 如何在 Google BigQuery 中填充表格
  • 将 Jupyter 笔记本与 BigQuery 数据库进行交互
  • 使用 pyspark.ml 实现梯度增强分类器

非常感谢您的时间——非常感谢您的任何想法或反馈!

这个例子的相关 GitHub 库可以在这里找到,你也可以在 michael-grogan.com找到更多我的数据科学内容。

免责声明:本文是在“原样”的基础上编写的,没有担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。

使用 Pytorch Lightning 和 Torchtext 对 Python 进行高效的自然语言处理实验

原文:https://towardsdatascience.com/productive-nlp-experimentation-with-python-using-pytorch-lightning-and-torchtext-256a4d00a26b?source=collection_archive---------35-----------------------

如何使用 Pytorch Lightning 和 Torchtext

Pytorch 是我主要的深度学习框架。然而,有些部分我觉得可以改进。Pytorch Lightning 已经回答了这个问题[1]。

William Falcon 展示了 Pytorch Lightning [2]中的一些核心功能。这些功能包括构建您的代码以准备数据、进行训练、验证和测试,以及使用 Tensorboard 进行日志记录。

他对 Pytorch Lightning、Pytorch Ignite、fast.ai 做了客观的比较[4]。他强调指出,Ignite 并不是每个模型都有一个标准的接口,需要更多的代码来训练模型,并不直接与 Tensorboard 集成,也不像 Lightning 那样具有额外的高性能计算。而 fast.ai 比其他两个有更高的学习曲线,用例可能与 Pytorch Lightning 和 Pytorch Ignite 不同。

在本文中,我想强调 Pytorch Lightning 提高我的工作效率的一些特性,以及如何将 Pytorch Lightning 与 Torchtext 集成。

照片由🏴󠁵󠁳󠁴󠁸󠁿·廷德尔在 Unsplash 上拍摄

为什么使用 Pytorch 闪电

减少样板文件

除非万不得已,不要再进行写作训练。您可以将您的培训定义为

from pytorch_lightning import Trainertrainer = Trainer(
    gpus=1, 
    logger=[logger],
    max_epochs=5
)
trainer.fit(model)

一个Trainer的工作是做你的日常训练。

  • 不再有写循环。正如你所看到的,不再有通常在 pytorch 教程中看到的循环。
  • 不要将你的模型转换成 gpu。您不必担心忘记将您的型号转换为cuda
  • 没有定制打印对您造成的损失。你看到logger那里的变量了吗?你可以使用 Tensorboard 来管理你的日志,我推荐你使用它。在本地使用之前,请执行pip install tensorboard

Pytorch 闪电产生的张量板样本

在这个截图中,我将logger变量定义为

from pytorch_lightning.loggers import TensorBoardLoggerlogger = TensorBoardLogger('tb_logs', name='my_model')

Pytorch Lightning 会创建一个名为tb_logs的日志目录,你可以参考你的 Tensorboard 的日志目录(如果你在 Jupyter notebook 之外单独运行你的 Tensorboard)。

tensorboard --logdir tb_logs/

组织代码

除了构造函数和forward之外,你还可以定义更多的函数

  • configure_optimizer。期望从torch.optim包中返回 Pytorch 优化器。
def configure_optimizers(self):
    return Adam(self.parameters(), lr=0.01)
  • train_step。给定一个批次和批次号,定义我们将如何输入到模型中。
def training_step(self, batch, batch_idx):
    x, y = batch.text[0].T, batch.label
    y_hat = self(x)
    loss = self.loss_function(y_hat, y)
    return dict(
        loss=loss,
        log=dict(
            train_loss=loss
        )
    )

在这个例子中,注意我用转置做了一点变换。在输入到模型中之前,可以进行各种转换,但是我建议您在这个函数之外进行大量的转换,这样会比较干净。

我还将loss_function定义为模型的一部分,并使用交叉熵对其进行“硬编码”。如果你不想这样,你可以使用torch.functional as F然后调用你的功能损失函数,比如F.log_softmax()。你可以做的另一件事是让模型构造器接受损失函数作为参数。

  • train_dataloader。定义希望如何加载培训数据加载器。

Pytorch Dataloader 是一个 API,可以帮助你批处理输入。不过,据我所知,Pytorch Lightning 将运行for batch_idx, batch in enumerate(train_dataloader)(不完全是这样,但类似)。这意味着你可以自由定义任何可迭代的东西。

  • test_step。给定一个批次和批号,定义我们如何将输入馈送到模型进行测试。值得注意的是,在这一步中,我们不需要输入损失函数,因为我们是在没有梯度的情况下运行的。
  • test_dataloader。定义您希望如何加载您的测试数据加载器
  • test_epoch_end。给定所有的测试输出,定义您想要对测试输出做的一些动作。如果您不想定义它,那么您可以定义,但是当您定义了test_steptest_dataloader之后,它会显示警告,因为这样您基本上对您的测试数据没有做任何事情。

使用 Pytorch Lightning 和 Torchtext

之前,我已经描述了我对使用 torchtext 的探索[4]。现在,我想在实验部分进一步提高我的生产力,包括培训、测试、验证、度量记录。所有这些都可以通过 Pytorch 闪电来实现。

我将采用 IMDB 情感分类数据集,它已经在 Torchtext 包中可用。

正在加载数据集

IMDB 情感分类数据集是文本分类任务,给定评论文本预测它是正面评论还是负面评论。有一个来自torch text【5】的官方简短教程,然而那个教程并没有涵盖训练部分。我将使用一些教程代码,并使用 Pytorch Lightning 将它们与培训联系起来。

该数据集包含 3 个类别:未知、阳性(标记为“阳性”)、阴性(标记为“阴性”)。因此,我们知道我们将需要定义一个可以预测 3 个类的输出。这是一个分类任务,所以我将使用交叉熵损失。

现在加载数据你可以做什么

from torchtext.data import Field 
from torchtext.datasets import IMDBtext_field = Field(sequential=True, include_lengths=True, fix_length=200)
label_field = Field(sequential=False)train, test = IMDB.splits(text_field, label_field)

由于 IMDB 审查的长度不一致,使用固定长度参数将有助于填充/修剪序列数据

您可以使用train.examples[i]访问您的样本数据,以查看训练和测试变量中的内容。

构建词汇

预训练单词嵌入通常针对我们使用的不同数据进行训练。因此,它将使用不同的“编码”从令牌到整数,我们目前有。build_vocab将使用预先训练的编码重新映射来自当前数据集(在本例中为 IMDB 数据集)的当前整数编码。例如,如果我们词汇表中的标记2eat,但是eat是预训练单词嵌入中的标记号15,那么它将被自动映射到正确的标记号。

from torchtext.vocab import FastTexttext_field.build_vocab(train, vectors=FastText('simple'))
label_field.build_vocab(train)

IMDB 数据集中的标签字段将采用posneg<unk>的形式,因此它仍然需要构建自己的 vocab,但不嵌入单词。

拆分并生成迭代器

迭代器的工作方式有点像数据加载器,它有助于在一个时期内批处理和迭代数据。我们可以使用 BucketIterator 来帮助我们迭代特定数量的批处理,并将所有这些向量转换成一个设备,其中设备可以是cpucuda

from torchtext.data import BucketIteratordevice = 'cuda' if torch.cuda.is_available() else 'cpu'
batch_size = 32train_iter, test_iter = BucketIterator.splits(
    (train, test), 
    batch_size=batch_size, 
    device=device
)

现在我们准备定义我们的模型。

模型定义

用 Pytorch Lightning 定义模型就像 William 解释的那样简单[2]。

  1. LightningModule而不是 Pytorch 的模块加载。
  2. 定义构造函数并转发。
  3. 现在添加上一节提到的属性

在进行完整的训练之前,最好确保您的模型可以正确地接受传递的输入,就像这样。

sample_batch = next(iter(train_iter))
model(sample_batch.text[0].T)

让我解释一下我为什么要做这些转换。

迭代器中的每个批处理对象都有textlabel 字段。text字段实际上是一个评论的真实单词向量和实际长度向量的元组。真实字向量的大小为固定长度 x 批量大小,而实际长度向量的大小为批量大小。为了给模型输入单词 vector,我需要:取第一个元组并旋转它,这样它将产生batch _ size x fixed _ length

我们现在准备训练我们的模型!

from pytorch_lightning import Trainer
from pytorch_lightning.loggers import TensorBoardLoggermodel = MyModel(text_field.vocab.vectors)
logger = TensorBoardLogger('tb_logs', name='my_model')
trainer = Trainer(
    gpus=1, 
    logger=logger,
    max_epochs=3
)
trainer.fit(model)

完成了!它会自动显示进度条,这样你就不用再做 tqdm 了。

for batch_idx, batch in tqdm(enumerate(train_loader)):

经过培训,您可以通过 1 行进行测试

trainer.test()

如果你在想为什么这个测试方法只返回一个对象?那么你可能会想到 scikit-learn 的训练和测试分离。在 Pytorch 中,“测试”部分通常被定义为“验证”。所以你可能想定义validation_stepval_dataloader,而不是test_*

结论

在我看来,使用 Pytorch lightning 和 Torchtext 确实提高了我试验 NLP 深度学习模型的生产率。我认为这个库非常吸引人的一些方面是向后兼容 Pytorch,Torchtext 友好,以及利用 Tensorboard。

向后兼容 Pytorch

如果你犹豫不决,因为你认为使用一个新的库会是一个开销,那么不要担心!你可以先安装,用LightningModule代替nn.Module并编写普通的 Pytorch 代码。它仍然可以工作,因为这个库不会引起任何额外的麻烦。

友好的火炬文本

与 Pytorch Lightning 一起使用 Torchtext 相当容易。这两个库都运行在 Pytorch 上,并且与本机 Pytorch 有很高的兼容性。两者都有额外的特征,这些特征并不相交,而是互补的。例如,Torchtext 具有加载数据集的简单接口,如 IMDB 或 YelpReview。然后,您可以使用 Pytorch Lightning 来训练您想要定义的任何模型,并登录到 Tensorboard 或 MLFlow。

利用 Tensorboard 的使用

使用 Tensorboard 代替手动打印你的损失和其他指标,帮助我消除了在训练循环中打印损失时不必要的错误。它还将消除在培训结束时可视化损失与时期图的需要。

你最好现在就在 google colab 中进行实验,这是链接

Google Colab 的笔记本

参考

[1] Pytorch Lightning 文档。https://py torch-lightning . readthedocs . io/en/stable/introduction _ guide . html

[2] Falcon,w .从 PyTorch 到 py torch Lightning——一个温和的介绍。https://towards data science . com/from-py torch-to-py torch-lightning-a-gentle-introduction-b 371 b 7 caaf 09

[3] Falcon,w . py torch Lightning vs py torch Ignite vs fast . ai .https://towards data science . com/py torch-Lightning-vs-py torch-Ignite-vs-fast-ai-61dc 7480 ad8a

[4] Sutiono,Arie P .用 PyTorch 和 Torchtext 进行 NLP 的深度学习。https://towardsdatascience . com/deep-learning-for-NLP-with-py torch-and-torch text-4f92d 69052 f

[5] Torchtext 数据集文档。https://pytorch.org/text/datasets.html

生产力助推器:复合估算器和管道的交互式可视化

原文:https://towardsdatascience.com/productivity-booster-interactive-visualisation-of-composite-estimator-and-pipeline-407ab780671a?source=collection_archive---------75-----------------------

内部 AI

Scikit-Learn 0.23 版本中的前处理步骤的可视化是生产力的助推器。

管道和估计器可视化——文章中讨论的代码的输出

根据我的经验,在现实生活中的机器学习项目中,最大的工作份额是数据预处理。使用适当的预处理数据训练模型是稍后获得准确预测的先决条件。

通常,由于连续的预处理和转换,它变得非常复杂,以至于解开它变得非常繁琐和耗时。如果您的同事已经完成了部分预处理逻辑,而您需要完成剩余的部分,这将变得更具挑战性。

Scikit-Learn 在 2020 年 5 月的 0.23 版本中引入了丰富的复合估值器和管道结构的交互式可视化。

在本文中,我将说明如何使用这个主要的新特性来改进我们对复杂的顺序预处理步骤的理解,并在出现任何问题时指出错误的步骤。

在本文中,我们将使用 Seaborn 包中著名的“Titanic”数据集。现实世界中大多数收集的数据都有缺失值。这里,我们将使用 SimpleImputer,KNNImputer 来填充样本 Titanic 数据集中缺失的值。我们需要 ColumnTransformer 对不同的列执行一组不同的转换。

**import seaborn as sns
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer ,KNNImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestClassifier**

首先,我们将下载样本 titanic 数据集,并从完整的可用要素集中选择一些要素作为自变量。
如下面的代码所示,大写的“X”通常用于表示自变量,小写的“y”表示因变量。

**TitanicDataset=sns.load_dataset("titanic")****X=TitanicDataset[["sex","age","fare","embarked","who","pclass",
"sibsp"]].copy()
y=TitanicDataset[["survived"]].copy()**

因为特性“fare”没有任何记录的空白值,所以我们不需要估算器。在下面的代码中,根据要应用的一组预处理和变换对功能进行了分组。

**numeric_independent_variables1= ['fare']
numeric_independent_variables2= [ 'age', 'pclass','sibsp']****categorical_independent_variables=["who","embarked","sex"]**

我们为三组特征定义了三种不同的管线。第一个管道只涉及缩放,而在第二个管道中依次提到输入和缩放。对于分类特征,使用最频繁策略填充缺失值,然后使用 OneHotEncoder 将分类值转换为数值。

**numeric_pipeline1=Pipeline([('scaler', StandardScaler())])****numeric_pipeline2=Pipeline([('imputer', KNNImputer(n_neighbors=7)),('scaler', StandardScaler())])****categorical_pipeline=Pipeline([('imputer',SimpleImputer(strategy='most_frequent')),('onehot', OneHotEncoder(handle_unknown='error'))])**

我们将使用 column transformer,因为我们将对不同的列组使用一组不同的预处理和转换。

**consolidated_pipeline= ColumnTransformer([('num1', numeric_pipeline1, numeric_independent_variables1),('num2', numeric_pipeline2, numeric_independent_variables2),('cat', categorical_pipeline, categorical_independent_variables)])**

在前面的步骤中,在一个列变压器中,提到了三条管线。

最后,我们有一个嵌套的管道,将更早的“合并 _ 管道”、“ pca ”、和“分类器”放入新的管道“clf”。

**clf = Pipeline([('consolidated_pipeline', consolidated_pipeline),('pca',PCA(n_components=5)),('classifier',RandomForestClassifier(max_depth=5))])**

解释转换的顺序已经变得相当复杂,即使与实际项目相比,预处理和转换顺序相对简单

在 0.19 版本中,Scikit-Learn 引入了 set_config 包。在 2020 年 5 月发布的 0.23 版本中,添加了“显示”参数,以实现复合估算器和管道的交互式可视化。

**from sklearn import set_config
from sklearn.utils import estimator_html_repr****set_config(display='diagram')
diaplay(clf) # for** **Jupyter Notebook and Google Collab**

管道和估计器可视化——文章中讨论的代码的输出

如果你正在运行 Jupyter 笔记本和 Google Collab 中的代码,那么上面的代码将带来管道的结构和其他复合估算器。点击各个方框显示参数。

如果你正在使用 IDLE,那么你可以用下面的代码在你的本地机器上下载完整的结构。由于我们没有在下面的代码中提供任何文件夹路径,因此 HTML 文件将保存在与主 python 程序相同的位置。

**with open('estimator.html', 'w') as f:
    f.write(estimator_html_repr(clf)) # for saving the HTML file**

我们不需要浏览所有的预处理和转换编码,只需看一眼,就可以通过这种树形结构的可视化来了解管道和转换序列。对于冗长复杂的嵌套管道和预处理步骤,它有助于我们快速确定问题区域,是真正的生产力助推器。

用 PyTorch 编写一个简单的图形网

原文:https://towardsdatascience.com/program-a-simple-graph-net-in-pytorch-e00b500a642d?source=collection_archive---------10-----------------------

几何机器学习简介

费迪南·斯托尔在 Unsplash 拍摄的照片

介绍

机器学习中一个非常新且快速发展的领域是图神经网络。顾名思义,它们能够学习任何网络中节点之间的关系。这在很多领域都很有用,例如预测分子结构的有用性,了解社交网络中的人,或者构建购物推荐系统。在这篇短文中,我将解释图网背后的理论,并用 PyTorch 实现一个简单的理论。

概观

在深入图网之前,让我们首先回答一个重要的问题:图究竟是什么?基本上,图是由两个元素组成的结构:

  • 节点:通常具有一组特定属性的实体
  • 边:连接两个节点。边可以是单向的,也可以是双向的

图形数据和我们在其他机器学习任务中遇到的“正常”数据之间的主要区别在于,我们可以从两个来源获得知识:

  1. 就像在其他机器学习应用中一样,每个节点都有一组特征。例如,当我们看一个社交网络时,每个节点都可以是具有特定年龄、性别、兴趣、政治观点等的人。
  2. 信息也编码在图的结构中。通过观察一个人的朋友,通常可以对这个人有所了解。

那么,所有这些是如何组成一个神经网络的呢?让我们继续我们的社交圈的例子。我们可以首先只看一个人本身。然后我们可以收集一个人的朋友的信息。然后是朋友的朋友的信息等等。这基本上是一个图形网络的想法:我们聚集邻居的信息,邻居的邻居,等等。一个节点。让我们看一个简单的例子,让事情更清楚。下图显示了一个小型朋友组,其中两个节点之间的边表示这两个人是彼此的朋友。

图 1:一个简单的图表

我们现在将关注人物 a。首先,我们只看一下深度为 0 的朋友圈,例如,只有人物本身

图 2:深度为 0 的朋友圈

那不太有意思。我们只能从这个人的特征来推断。现在看看深度 1(图 3)。

图 3:深度为 1 的朋友圈

现在我们还可以分析朋友们的特征。最后,深度为 2 的网(图 4):

图 4:深度 2 的朋友圈

哇,最后一张图看起来已经很像神经网络了!这就是我们在这些神秘的灰色盒子中所做的事情:我们以某种方式聚集相邻节点的所有特征,将它们乘以权重,并应用激活函数。注意:我们称聚集的特性为嵌入

让我们仔细看看这些盒子里发生了什么。看看下面的两个等式(图 5)。

图 5:图形网络的基本方程

我们定义没有前趋的节点在第 0 层。这些节点的嵌入只是它们的特征。为了计算层 k 的嵌入,我们对层 k-1 的平均嵌入进行加权,并将其放入激活函数中。注意这里的两件重要事情:首先,所有相邻节点的权重是相同的,它们没有单独的权重。第二,当我们计算一个节点 v 的嵌入时,我们也想包括这个节点的特征,所以我们给每个节点添加自循环。这在直觉上也是有意义的:当描述一个节点的特征时,邻居确实扮演了一个重要的角色,但是节点本身也很重要。

到目前为止,我们已经了解了普通图网络是如何工作的。在我们开始实现之前,我想介绍一个轻微的修改,它已经显示出经常优于正常的图网。这种邻域聚合被称为图卷积网络 (GCN,看这里有很好的介绍)。有两个主要区别(图 6):

  1. 每层只有一组权重,所以 W 和 B 不再不同。因此,节点本身的特征乘以与其所有邻居相同的权重。
  2. 所有节点的归一化因子并不相同,而是取决于它们各自的邻居数量。

图 6:差分正态和 GCN 邻域聚合

履行

好在 PyTorch 已经有了一个惊人的几何深度学习库,它叫 PyTorch 几何。务必仔细通读安装说明,因为我在这里搞砸了。这里的陷阱是 PyTorch 几何需要不同版本的库,这取决于您是否有 GPU。

首先,我们要定义我们的 GCN 层(清单 1)。

清单 1: GCN 层

让我们一行一行地看一下:

add_self_loops 函数(清单 2)是 PyTorch Geometric 提供的一个方便的函数。如上所述,在每一层中,我们都希望聚合所有的相邻节点以及节点本身。为了确保包含节点本身,我们在这里添加了自循环。

清单 2:添加自循环

接下来我们要做的是用我们的权重乘以嵌入值(清单 3)。

清单 3:乘以权重

最后,我们计算归一化因子(清单 4)。

清单 4:计算规范化

重要:不要惊讶我们这里没有激活功能,我们会在网本身添加。

接下来我们可以使用我们的层定义创建一个图形网(清单 5)。这里没有太多特别需要注意的地方。我们创建了一个香草火炬网使用我们的 GCN 层。注意:从数据中我们可以得到节点(x)和它们之间的边(edge_index)。

清单 5:整个图形网

当然,我们想测试我们的网络在一些真实数据上的表现。上面实现的网络是一个非常简单的网络,所以它在大数据集上表现不好。一个不错的选择是 21 世纪初收集的 Cora 数据集。这里我们有来自七个不同领域的机器学习论文,并希望对哪篇论文属于哪篇进行分类。每篇论文的特点是经常出现的单词。两个节点之间的边表示一篇论文引用了另一篇论文。通过查看数据集(图 7 ),我们已经可以看到同一区域的论文形成了一个集群。

图 7: Cora 数据集可视化

在这里,我将省略我们为了训练模型而需要的常见 PyTorch 样板代码。完整的代码可以在我的 GitHub(链接)中找到。仅仅几个时期之后,我们就获得了 100%的训练准确率和大约 80%的验证准确率。

图 8:简单图形网络的性能

结论

这是我第一次涉足图形神经网络领域,总体来说是一次非常有趣的经历。图网的想法是几年前的事了,所以直到今天,就像在快速发展的机器学习世界的其他领域一样,无数的修改和改进已经出现了。所以有很多要发现的!

全部代码都在我的 GitHub 里。

来源

[1] PyTorch 几何文档https://py torch-Geometric . readthedocs . io/en/latest/index . html

[2]斯坦福教程http://snap . Stanford . edu/proj/embeddings-www/files/nrl tutorial-part 2-gnns . pdf

像 1970 年一样编程!

原文:https://towardsdatascience.com/program-like-its-1970-6708df2ed101?source=collection_archive---------49-----------------------

有点回到人工智能过去的样子

洛伦佐·埃雷拉在 Unsplash 上的照片

机器学习现在风靡一时!CNN、GANs 和 LSTMs 是所有酷孩子现在都在做的事情。很多人忘记了人工智能!= Machnine learning,在 2010 年深度学习热潮之前,人工智能已经存在了很长时间。我想带你回去,用一个简单的例子来说明过去的人工智能方法。

地图着色

“地图着色”是制图学中一个著名的玩具问题,我们希望以两个相邻国家总是有不同颜色的方式给地图着色(图 1)。

图 1:解决地图着色问题

为了便于说明,我们将在下面的部分中尝试给澳大利亚的州着色(因为只有八个州)。

有趣的是,在很长一段时间里,人们“知道”解决这个问题至少需要四种颜色。但是直到 90 年代末,还没有一个关于 T4 的数学证明。

约束满足问题

地图着色问题属于一类特殊的问题,简称为“约束满足问题”。这些类型的问题由三个不同的部分组成:

  1. 变量:我们要查找其值的占位符。在我们的案例中,这些是澳大利亚的州和地区:新南威尔士州、昆士兰州、维多利亚州、西澳大利亚州、南澳大利亚州、北部地区、澳大利亚首都直辖区和塔斯马尼亚州
  2. 域:这些是变量的可能值。在这种情况下,所有变量的定义域都是相同的。每种状态都可以用红、绿、蓝、黄四种颜色中的一种来着色。
  3. 约束:变量不能违反这些约束。例如,维多利亚和新南威尔士的颜色必须不同,因为这是两个相邻的州。

一般来说,解决 CSP 有两种不同的策略:

  1. 推理
  2. 搜索

重要的是,CSP 通常只能通过推理部分解决,因此需要搜索。简而言之,如果我们不需要进行某种随机猜测来寻找答案,那么 CSP 就是完全可以通过推理来求解的。一个典型的例子是数独游戏。我们有自己的变量(空字段)、域(1 到 9 之间的数字)和几个不能违反的约束(在一行、一列或一个正方形中不能有相同的数字)。在这里,我们不必随机选择一些数字,但我们可以通过以正确的顺序应用约束来解决整个难题。不幸的是,对于我们的地图着色问题,我们没有那么幸运:为了找到一个合适的解决方案,我们不可避免地要做一些猜测。

通常的方法:回溯

解决类似 CSP 的常见方法是使用回溯算法。这是用 Python 实现的算法:

回溯算法

我们现在将逐行检查代码,以确保我们理解这里发生了什么:

如上所述,我们的 CSP 由变量、域值和约束组成。重要的是要注意,如果可能的话,约束通常被转换成二元约束,以使事情变得更容易。二元约束描述了两个变量之间的关系。在我们的 Python 实现中,它们的形式是[('NSW ',' V '),(' NSW ',' Q '),(' NSW ',' SA '),…,(' T ',' V')]。

如果我们有和变量一样多的赋值,那就意味着我们已经给每个变量赋值了,从而解决了问题!

我们现在必须选择一个仍然未赋值的变量,我们现在想找到它的值。如何选择这个值将在下面进一步讨论。

在选择了一个未赋值的变量后,我们还必须选择一个顺序来测试这个变量的值。

如果我们为变量选择的值与我们的二元约束一致,我们就把它添加到我们所有赋值的列表中。现在真正酷的部分是:我们再次调用回溯函数,所以这是一个递归函数。我们找到了一个变量的有效赋值,所以现在是时候为下一个变量找到一个值了。

可能发生的情况是,递归调用的结果是‘None’。这意味着我们赋给变量的值在这个时候是局部一致的,但是不可能用这个值找到一个整体一致的解。所以我们把这个值从赋值列表中去掉了。如果我们不能找到一个单一的一致的解决方案,我们返回 None 给上面的递归函数。如果所有的递归调用都没有返回 None,这意味着问题是不可解决的。

哦,这个理论说够了。让我们看看这个算法如何执行,如果我们让它运行在我们的地图着色问题:

图 2:天真的回溯

嗯…我们的算法似乎没有任何进展。剧透:它最终会找到一个解决方案,但这需要很长时间,这在上面的 gif 中没有显示。这是为什么呢?因为我们仍然没有回答上面的一个重要问题:我们如何选择下一个变量来赋值?在上图中,算法只是随机选择一个未赋值的值。显然这不是最好的方法。要选择一个变量,我们应该选择一个更好的启发式。我们实现了最小剩余值试探法或者 MRV 试探法。这一点是不言自明的:我们选择的下一个变量总是剩下最少有效值的变量。这在直觉上也是有道理的。例如,如果我们只能将新南威尔士州涂成红色,但我们仍然可以将西澳大利亚州涂成红、绿和蓝色,那么我们应该首先将新南威尔士州涂成红色,因为如果我们将另一个州涂成红色,可能就不会再有任何有效的颜色留给新南威尔士州了。所以让我们用这个启发法再试一次:

图 3:MRV 的原路返回

哇,这个好用多了!

比较随机选择和 MRV 启发式(图 3 ),我们可以看到后者通常更省时。

图 4: MRV(左)与随机(右)选择下一个变量

但是说实话,给澳大利亚涂色并不有趣,因为澳大利亚只有 8 块领土。所以,为了好玩,让我们试着给德国涂上颜色,这个国家有两倍多的州:

图 5:给德国上色

这个也很管用!

捷径:序言

因此,到目前为止,整个过程都相当繁琐:我们需要编写所有这些回溯代码(递归函数有时会很棘手!)甚至想出一个好的启发式。没有更好的解决办法吗?介绍:序言。

很可能,作为一个普通的程序员(就像我一样),你已经接触过相当多的编程语言:Java、Python、C、C#、JavaScript 等等。它们可能完全不同,但它们都属于同一类编程语言:命令式编程。然而,Prolog 属于声明性编程语言,或者更确切地说,属于逻辑编程语言。那么有什么区别呢?在“普通”编程语言中,你指定事情应该如何完成。在 Prolog 中,你指定应该做什么。看看下面的例子:

简单的序言示例

Prolog 中最重要的两个构造是事实规则。在节目的开始,我们陈述了一些事实,例如,亨利是男性,玛丽是迈克尔的父母。再往下我们有一些规则。例如,我们声明,如果 Y 是男性,Y 是 X 的父,重要的是:所有变量都必须以大写字母开头。小写名称是固定的常数。

当我们进入 Prolog 控制台时,我们可以问我们的 Prolog 程序一些问题。我们可以找出迈克尔的母亲是谁:

?- mother(michael, X).
X = mary.

或者谁是迈克尔的祖父:

?- grandfather(michael, X).
X = henry ;

现在让我们写一个程序给澳大利亚上色:

这真是直截了当!首先,我们定义哪些状态应该用不同的颜色。Diffx 只是一个帮助函数,它帮助我们定义如果颜色 A 不同于 B,那么 B 也不同于 A。最后,我们只是声明所有的颜色都彼此不同(显然)。就是这样!15 行代码,我们只需要陈述规则和事实,不需要算法。

让我们加载这个程序,要求变量赋值:

?- map_coloring(WA, NT, SA, NSW, V, Q, T, ACT).
WA = NSW, NSW = T, T = blue,
NT = V, V = ACT, ACT = red,
SA = green,
Q = yellow

将这些值放入地图如下所示:

图 6:由 Prolog 程序确定的颜色

的确,我们得到了一个有效的解!

结论

当我通常处理人工智能时,它必须用神经网络做一些事情,所以对我来说,看看几十年前人们对“人工智能”这个术语的理解是非常有趣的。尤其是用 Prolog 编程对我来说非常独特。解决 CSP 和类似的问题显然是非常容易的。我对这种语言的主要问题是,我从来不知道到底发生了什么。我只是陈述一些事实和规则,但从不明确告诉程序该做什么。因此,如果任务失败,跟踪错误和调试问题几乎是不可能的。

掌握正则表达式 1 的唯一指南

原文:https://towardsdatascience.com/programmers-guide-to-master-regular-expression-f892c814f878?source=collection_archive---------12-----------------------

清晰、简明、循序渐进的指南

了解语言类比

照片由 Fotis Fotopoulos 在 Unsplash 上拍摄

正则表达式(Regex)是最强大、最灵活、最有效的文本处理方法之一。Regex 有自己的术语、条件和语法;从某种意义上说,它是一种迷你编程语言。Regex 可用于添加、删除、隔离和操作所有类型的文本和数据。它可以用作简单的文本编辑器命令,例如搜索和替换,或者作为它自己强大的文本处理语言。正因为如此,Regex 在今天的技术中有如此多的应用,例如:用网络爬虫提取有用的信息、数据抓取和网络抓取、数据争论和机器学习——即自然语言处理和语音识别。

Regex 不是特定于编程语言的应用程序;事实上,它可以用在今天所有的编程语言中。编程语言支持正则表达式的使用,但是所有的魔力和力量都来自正则表达式本身。

使用正则表达式可以为程序员节省宝贵的时间,这些时间可能会浪费在平凡的任务上。任务,如在文件夹中查找电子邮件,从一堆文本文件中删除重复内容,分析特定语言的语法,突出显示文件中的某些上下文,等等。对于那些以前从未使用过 Regex 的人来说,这听起来很神奇,但也很吓人!第一次阅读正则表达式可能——不,可能,肯定——会感到困惑和复杂。我是说,看看这个例子:

我向您保证,在本文结束时,您将很快理解您遇到的任何正则表达式,包括上面的这个。

然而,第一次看到一门新的语言总是令人困惑。然而,当你开始学习形成语言的小块时,它看起来就不再复杂或令人困惑了。

所以,让我们开始破译正则表达式…

正则表达式语言类比

完整的正则表达式通常由两种基本类型的字符组成:元字符文字元字符是赋予正则表达式权力的特殊字符,而文字是所有其他标准文本字符。Regex 与文件名模式的不同之处在于,文件名模式为有限的应用程序提供了有限的选项。相比之下,Regex 提供了丰富的元字符,允许更高级的应用程序。

作者使用 Canva

考虑元字符文字的一种方式是,因为 Regex 是它自己的语言,我们可以说文字是该语言的单词,而元字符是它的语法。单词和语法可以在一套特定的规则下结合在一起,形成无数的表达式,能够表达你能想到的任何可能的模式。

你意识到正则表达式的力量了吗?

没有吗?只要继续读下去…

首先,我们将涵盖正则表达式的基本概念,然后我们将举一些例子,我们将看到如何构造一个正则表达式,以及我们如何使用 Python 来提取匹配。

元字符

元字符有三种基本类型,每一种都用来表示我们正在搜索的模式的一个方面。这三种类型是元字符类、量词和位置元字符。

元字符类

这些类型的元字符用于匹配单个字符,它们都以\开头,以区别于文字。下面是六种可能的元字符类的表格:

量词

这些类型的元字符用于指示我们试图匹配的模式中某个字符出现的次数。假设我们希望匹配“鞠波”和“杰西”,我们将使用其中一个量词来表示这两个选项都是可接受的。量词有四种类型:

位置元字符

位置元字符用于指示我们正在寻找的字符的位置。是在正文的开头,行尾,还是一个词?为了实现这一点,我们使用位置元字符。

超级演员

这只是我对他们的称呼——绝对不是正式的名字😄—这些是一些额外的元字符,用于连接其他元字符和文字。

文字

文字是所有不是元字符的单词和字符。例如,“从”,“到”,“你好:”所有这些都是文字。如果我想匹配一个元字符,例如,我想匹配*^字符,我应该怎么做呢?

在这种情况下,我们使用转义字符来正则表达式,以明确表示我们想要匹配该字符。所以我们输入\^\*,而不仅仅是^*

Python 中的正则表达式

要在 Python 中使用 Regex,我们需要使用一个名为***re***的库。这个库是 Python 内置库的一部分,这意味着您不需要为了使用它而安装它。你只需导入它并得到匹配。这个库包含许多函数,允许我们有效地使用 Regex。在本文中,我们将讨论基本的五个功能:*compile**search**match**findall**sub*

编制

正则表达式基本上是我们定义并要求代码寻找的模式。在 Python 中,这些表达式是作为字符串或原始字符串的句柄。普通字符串和原始字符串之间的区别在于,在原始字符串中,转义字符不被处理,即它们将按原样打印。例如:

usual_str = "Hello\nWorld!" #This will print Hello and World! in different linesraw_str = r'Hello\nWorld!' #Will print the string as it is Hello\nWorld!

在 Python 中,可以使用字符串来表示表达式,也可以使用compile 函数将正则表达式模式计算成正则表达式对象。如果您计划在代码中多次使用相同的模式,最好将它作为编译对象;因为将模式存储为正则表达式对象以便重用比将其保存为字符串更有效。

比赛

我们可以使用match函数在给定的字符串中搜索模式。如果搜索成功,该方法将返回一个 match 对象。如果不是,则返回None

搜索

search函数在扫描字符串时寻找给定模式的第一次出现。如果找到匹配,将作为 match 对象返回,否则返回None

**search()** VS **match()**

match函数只在字符串的开头检查匹配,而search函数在字符串的任何位置检查匹配。

芬达尔

findall函数搜索一个字符串,找到所有可能的匹配,并将它们作为一个字符串列表返回。每个返回的字符串代表一个匹配。

潜水艇

sub是替代功能。它接受一个原始字符串和一个模式,并返回通过用替换 repl 替换该字符串中最左边的非重叠模式获得的字符串。如果找不到模式,则返回字符串,不做任何更改。

subn类似于sub。但是,它返回一个包含新字符串值和对原始字符串执行的替换次数的元组。

注意所有这些方法都有一个额外的属性叫做flag

该属性用于微调模式的搜索和匹配,这些标志是:

  1. IGNORECASE or (I): 允许不区分大小写的匹配。
  2. DOTALL or (S): 允许。匹配任何字符,包括换行符。
  3. 多行 or (M): 允许插入符号(^)和美元($)元字符匹配换行符。
  4. VERBOSE or (X): 允许您在表达式中写入空白和注释,使其更具可读性和易于理解。

好了,这已经很多了,让我们举一些例子来帮助我们阐明不同元字符的用法。

我们将从小处着手,然后逐步构建更复杂的示例。😉

例子一

创建一个正则表达式,匹配以大写字母开头的任意长度的单词。例如,在句子中:

侧栏包括备忘单、完整参考和帮助。您还可以保存与社区的共享,并在我的模式中查看您创建或喜爱的模式。

我们希望匹配所有以大写字母开头的单词。

步骤:

  1. 匹配单词中的第一个字符(在[A-Z]大写字母中)。
  2. 匹配下列任意数量的字母。

匹配模式的 Python 代码:

执行这段代码将打印[‘The’, ‘Cheatsheet’, ‘Reference’, ‘Help’, ‘You’, ‘Share’, ‘Community’, ‘My’, ‘Patterns’]

例子二

创建一个正则表达式来匹配 xxxx-xxxx-xxx 格式的电话号码。例如,在这句话中:

昨天在办公室聚会上,我遇到了东海岸分公司的经理,她的电话号码是 202-555-0180。我还和招聘人员交换了我的电话号码 202-555-0195。

我们将匹配202–555–0180 和 202–555–0195。

步骤:

  1. 匹配 4 个数字,后跟一个连字符。
  2. 重复步骤 1。
  3. 匹配三位数。

匹配模式的 Python 代码:

执行代码打印[‘202–555–0180’, ‘202–555–0195’]

例子三

让我们加大难度吧!

我们想创建一个正则表达式来匹配 DD 格式的任何日期。年月日或年月日或年月日。此外,我们希望年份只在 19s 或 20s 之间。

Python 3.0 于 2008 年 3 月 12 日发布。这是对该语言的一次重大修改,它并不完全向后兼容。它的许多主要特性都被移植到了 Python 2.6。以及分别于 2008 年 10 月 3 日和 2010 年 7 月 3 日发布的 2.7 版本。

我们希望匹配该句子中的所有三个日期。

步骤:

  1. 匹配。我们可以将日正则表达式分为三部分。0[1–9],表示从 01 到 09 的日期。接下来,我们有【12】【0–9】;这个表示 1 或 2,后面跟一个 0~9 之间的数。最后,3【01】,这是针对 3 后面跟着 bt 0 或者 1。所以,30 或者 31。
  2. 匹配分隔符()。|-|/).这符合-或/或。注意,在点之前我们添加了一个\来告诉 Python 我们想要匹配一个点,我们不是指点元字符。
  3. 匹配月份。月份可以分为两部分:小于 10 的月份和小于 10、11 和 12 的月份。第一部分可以用0[1–9],匹配,第二部分是 1[012]
  4. 最后,我们需要匹配年份。对于年份,我们希望它以 19 或 20 开始,然后后面跟着另外两个数字。

匹配模式的 Python 代码:

执行代码打印[‘03–12–2008’, ‘03.10.2008’, ‘03/07/2010’]

唷…

那很有趣——我希望如此!。

Regex 是一个很大的话题,我们可以花很多时间来讨论它,这就是为什么我决定把这篇文章分成两篇。在这一篇中,我介绍了基础知识,在下一篇中——下周开始——我将进入更高级的形式,我们将讨论如何在 Python 中创建高效的正则表达式以及更多的re方法…

参考和工具

[1] Tonkin,e .,& Tourte,G. J. L. (2007 年)。掌握正则表达式。阿里阿德涅53

[2]练习正则表达式的一个有用工具是 regexr.com。

给量子计算机编程

原文:https://towardsdatascience.com/programming-a-quantum-computer-21baf506bdc4?source=collection_archive---------7-----------------------

奇点研究

量子逻辑门软件

一个普遍的误解是,量子计算机还没有为应用做好准备,这项技术还需要很多年才能变得有用。在这篇文章中,我们将看看量子计算机编程的一些基本原则,并解决这个误解。我们将关注免费的开源软件,如 IBM 的 QISKit ,以及量子机器学习软件 PennyLane 。我们还将解释如何在 IBM 云中的实际量子计算机上运行你的程序。在后续文章中,我们将讨论机器学习中的一些应用,这些应用目前可供任何有一点好奇心的人使用。

什么是量子计算机?

首先,让我们谈一谈量子计算,以及你可以从这项技术中期待什么。你可以在手机、笔记本电脑或平板电脑中找到的当前计算机芯片架构是由硅制成的。最常见的技术之一是使用一种特殊的基于光的光刻技术在硅片上蚀刻出微小的图案。这些微小的图案使我们能够制造出硅芯片,以可控的方式在芯片中传输电子(电流)。目前,我们已经达到了这些微小图案可以有多小的物理极限。它们可以有效地大量制造,具有纳米级的精度,典型的结构大约为 10 纳米,直径在 20 到 50 个原子之间。

更精确的技术已经存在,可以操纵单个原子,我们目前可以创造出比你通常在电脑或电话中看到的还要小的结构。这种制造过程有点慢,因此大规模生产这些更小、原子级精确的芯片有点困难。在构造具有如此小特征的计算机芯片时,我们遇到的一个困难是电子和原子的量子行为。电子有一种叫做波粒二象性的东西。这意味着,在某些情况下,电子的行为像波而不是粒子,因此当蚀刻图案太小时,将它限制在硅片上的微小蚀刻图案变得更加困难。电子“扩散”并发生电子泄漏,导致电流流经硅片中的这些微小通道时出现问题。这种泄漏意味着芯片不能按预期运行,电子的波动行为成为一个问题。这通常被称为“摩尔定律的死亡”,代表着过去几十年来我们所期待的计算机性能增长的停止。如果你押注于一个建立在持续不断增长的假设之上的市场,这将是一个大问题,因为你能制造的电脑芯片有多小多高效,实际上是有物理限制的。

量子计算旨在将量子力学行为的这一“问题”作为一种计算优势,通过使用它以一种与我们手机和笔记本电脑中常见的二进制 1 和 0 完全不同的方式处理信息。一种有用的方式认为量子计算机是一个专用集成电路。不完全是这样,但这是个不错的类比。可以把它想象成一种特殊的计算机芯片,设计用来执行特定种类的计算,比标准的硅芯片更有效。我们来看看 QISKit 中的基本计算单位是如何表示的。

QISKit 中的量子比特态

首先,你需要下载一个免费分发版的 Anacond,这样你就可以使用 Jupyter Lab 了。下载 Anaconda 之后,打开 Anaconda navigator 并打开 Jupyter Lab 的一个实例。如果你想从 Github 下载笔记本,你可以在这里找到。如果你想看活页夹上的互动版本,你可以在这里找到。要安装 QISKit,只需使用 Jupyter 笔记本或 Jupyter Lab 中的 pip 即可。

接下来,您需要导入 qiskit 和 matplotlib。

现在,如果您想在 Bloch 球体上绘制“自旋”状态,您可以键入以下命令。

我们可以用下面的命令画出量子位的“自旋下降”状态。

总的来说,量子位状态不再像经典的二进制信息位那样局限于简单的 0 或 1。量子位可以有无限多种状态。每个状态被表示为布洛赫球面上的一个点。自旋向上对应于状态 0,自旋向下对应于状态 1,但是量子位也可以是这两种状态的组合。布洛赫球上的每一个点,就像地球表面的坐标一样,代表一个独特的量子位元状态。一个量子位可以处于无限多种不同状态的这种能力,与量子物理中的“叠加”概念有关。例如,布洛赫球面上的以下状态是状态 0 和状态 1 的均匀混合,因此它是这两个状态的叠加。

这个“右旋”位置被表示为“叠加”,

或者 0 状态和 1 状态的“线性组合”。如果你不懂线性代数参考,没关系。现在,如果我们想对自旋向上状态(或状态 0)的单个量子位进行操作,并将其翻转到自旋向下状态(或状态 1),我们可以使用非门。非门或“泡利 X 门”是一个量子逻辑门。量子逻辑门在概念上类似于经典逻辑门,但又不完全相同。它们对量子比特进行操作,就像经典逻辑门对比特进行操作一样,但是它们总是可逆的,并且用(酉)矩阵乘法来表示。我们可以在 QISKit 中创建一个量子电路,如下所示:

现在,如果我们想使用非门对单个量子位进行操作,我们可以在 QISKit 中使用下面的代码来完成。

这向我们表明,我们已经翻转了量子位状态,使其自旋向下。这是量子算法背后的基本思想。在下一篇文章中,我们将看看这些量子逻辑门是如何在实际硬件上使用超导量子位实现的。这也可以用 IBM 软件来完成,相当于对应用于量子计算机芯片的微波脉冲进行编程。如果你想看一些介绍量子算法背后的数学的教程,可以看看我的 Github 知识库,里面有用 Python 实现的量子计算背后的数学。如果你有问题或评论,或者想讨论量子计算及其应用,请随时联系。

算法中的编程公平性

原文:https://towardsdatascience.com/programming-fairness-in-algorithms-4943a13dd9f8?source=collection_archive---------17-----------------------

理解和解决监督学习中的公平问题。

"做好事容易,难的是做公正。" 维克多雨果

"我们需要捍卫那些我们从未谋面、也永远不会谋面的人的利益。" 杰弗里·萨克斯

注:本文旨在让普通读者尝试并阐明机器学习算法中不公平性的复杂本质。因此,我试图用简单易懂的方式解释概念,尽量少用数学,希望每个人都能从阅读中有所收获。

有监督的机器学习算法天生具有歧视性。它们是歧视性的,因为它们使用嵌入在数据特征中的信息将实例分成不同的类别——事实上,这是它们生活中的指定目的。这反映在这些算法的名称中,这些算法通常被称为判别算法(将数据分成类别),与生成算法(从给定类别生成数据)相反。当我们使用监督机器学习时,这种“区分”被用来帮助我们将数据分类到数据分布中的不同类别,如下图所示。

判别式与生成式算法的图解。请注意,生成算法从限制于特定类别的概率分布(例如,蓝色分布)中提取数据,而判别算法旨在辨别这些分布之间的最佳边界。来源: 堆栈溢出

虽然当我们对任何数据集应用判别算法(如支持向量机、各种形式的参数回归(如香草线性回归)和非参数回归(如随机森林、神经网络、boosting))时会出现这种情况,但结果不一定有任何道德含义。例如,使用上周的天气数据来尝试预测明天的天气,这并不具有道德价值。然而,当我们的数据集基于直接或间接描述人(个体)的信息时,这可能会无意中导致基于群体关系的歧视。

显然,监督学习是一种两用技术。它可以为我们带来好处,例如用于信息(例如预测天气)和保护(例如分析计算机网络以检测攻击和恶意软件)。另一方面,它有可能被武器化,以便在几乎任何层面上进行歧视。这并不是说算法这样做是邪恶的,它们只是在学习数据中存在的表示,这些表示本身可能已经嵌入了历史不公正的表现,以及个人的偏见和倾向。数据科学中的一个常见格言是“垃圾输入=垃圾输出”,指的是高度依赖于提供给它们的数据质量的模型。这可以在算法公平性的上下文中类似地表述为“偏入=偏出”。

数据原教旨主义

有些支持者信奉 数据原教旨主义 ,也就是说,数据通过经验观察反映了世界的客观真相。

"有了足够的数据,数字就能说明一切。" —前《连线》主编克里斯·安德森(数据原教旨主义者)

数据和数据集不客观;它们是人类设计的产物。我们赋予数字它们的声音,从中得出推论,并通过我们的解释来定义它们的意义。收集和分析阶段的隐藏偏差带来了相当大的风险,对于大数据等式来说,这与数字本身一样重要。 —凯特·克劳福德,微软研究社交媒体集体 首席研究员

表面上看,这似乎是一个合理的假设,但凯特·克劳福德在《哈佛商业评论》的一篇文章中提供了一个很好的反驳:

波士顿有坑洞的问题,每年修补大约 20,000 个。为了帮助有效地分配资源,波士顿市发布了优秀的 StreetBump 智能手机应用程序,它利用加速度计和 GPS 数据来帮助被动检测坑洞,并立即向城市报告。虽然这无疑是一个聪明的方法,但 StreetBump 有一个信号问题。在美国,低收入群体不太可能拥有智能手机,尤其是老年居民,他们的智能手机普及率只有 16%。对于像波士顿这样的城市来说,这意味着智能手机数据集缺失了相当一部分人口的输入——通常是那些资源最少的人。——微软研究院首席研究员凯特·克劳福德

本质上,StreetBump 应用程序从富裕社区获得了大量数据,而从贫困社区获得的数据相对较少。很自然,你可能从中得出的第一个结论是,较富裕的社区有更多的坑洞,但实际上,贫穷社区的数据很少,因为这些人不太可能有智能手机,因此下载了 SmartBump 应用程序。通常,我们的数据集中没有的数据会对我们的结果产生最大的影响。这个例子说明了一种微妙的收入歧视形式。因此,当从可能遭受“信号问题”的数据中得出这样的结论时,我们应该谨慎。这种信号问题通常被表征为 采样偏差

另一个值得注意的例子是“替代性制裁的惩教罪犯管理概况”算法,简称 COMPAS。美国许多州都使用这种算法来预测累犯率,即前罪犯再次犯罪的可能性。调查性新闻机构 ProPublica 对该算法的分析引发了争议,因为它似乎表明该算法是基于种族的歧视——种族在美国是一个受保护的阶层。为了让我们更好地了解正在发生的事情,用于预测累犯的算法看起来像这样:

累犯风险评分 =(年龄w) +(首次被捕年龄w) +(暴力史* w)+(职业教育* w)+(违规史* w)

应该清楚的是,种族不是用作预测的变量之一。然而,根据美国历史上的不公正以及人口统计、社会和执法统计数据(这通常是另一个批评的目标,因为他们经常使用算法来确定哪些街区需要巡逻),对于这些变量中的一些变量,如“暴力历史”和“职业教育”因素,两个给定种族之间的数据分布可能有很大不同。这些数据分布之间的不匹配可以被算法利用,导致种族之间的差异,从而在某种程度上导致适度偏向或反对某些种族的结果。这些根深蒂固的偏见将被算法操作化,并因此继续存在,导致进一步的不公正。这个循环本质上是一个自我实现的预言。

历史不公→训练数据→生产中的算法偏差

这导致了一些困难的问题——我们去除这些有问题的变量了吗?我们如何确定一个特征是否会导致歧视性的结果?我们需要设计一个度量标准来提供“歧视”的阈值吗?人们可以将这种方法发挥到极致,去掉几乎所有的变量,但这样算法就没用了。这描绘了一幅暗淡的画面,但是幸运的是,有一些方法可以解决这些问题,这些问题将在本文的后面讨论。

这些例子不是孤立的事件。甚至乳腺癌预测算法也显示出一定程度的不公平歧视。从乳房 x 光片预测乳腺癌的深度学习算法对黑人女性的准确性远远低于白人女性。这部分是因为用于训练这些算法的数据集主要基于白人女性的乳房 x 光片,但也因为黑人女性和白人女性之间的乳腺癌数据分布可能有很大差异。根据疾病控制中心(CDC)黑人女性和白人女性患乳腺癌的几率差不多,但是黑人女性死于乳腺癌的几率比白人女性高

动机

这些问题引发了关于算法开发人员动机的问题——设计这些模型的人是故意这样做的吗?他们是否有一个他们试图推动的议程,并试图将其隐藏在灰色盒子机器学习模型中?

虽然这些问题不可能有把握地回答,但在问这类问题时,考虑一下汉隆剃刀是有用的:

永远不要把可以用愚蠢来充分解释的事情归咎于恶意——罗伯特·j·汉伦 T3

换句话说,世界上没有那么多邪恶的人(谢天谢地),世界上邪恶的人肯定比无能的人少。一般来说,我们应该假设当事情出错时,更可能是因为无能、幼稚或疏忽,而不是纯粹的恶意。虽然可能有一些恶意的行为者想要推动歧视性议程,但这些可能是少数。

基于这种假设,可能会出现什么问题呢?有人可能会说,统计学家、机器学习从业者、数据科学家和计算机科学家没有被充分地教授如何开发监督学习算法来控制和纠正偏见倾向。

为什么会这样呢?

事实上,实现这一点的技术并不存在。机器学习公平性是机器学习的一个年轻的子领域,在过去几年中,随着机器学习与社会领域的快速融合,它越来越受欢迎。与医生不同,计算机科学家不一定受过考虑其行为的道德含义的训练。直到最近(可以说是社交媒体出现以来),计算机科学家的设计或发明才具备了伦理维度。

这表现在大多数计算机科学期刊不要求对提交的稿件进行伦理陈述或考虑。如果你有一个包含数百万真实人物图像的图像数据库,这无疑会有伦理上的影响。由于物理距离和数据集的大小,计算机科学家与数据主体相距甚远,以至于对任何一个人的影响都可能被认为是微不足道的,从而被忽视。相比之下,如果社会学家或心理学家对一小群人进行测试,就会成立一个完整的伦理审查委员会来审查和批准实验,以确保实验不会超越任何伦理界限。

从好的方面来看,这种情况正在慢慢开始改变。越来越多的数据科学和计算机科学项目开始要求学生参加数据伦理和批判性思维的课程,期刊也开始认识到通过 IRB 和手稿中的伦理陈述进行伦理审查可能是同行评审过程的必要补充。对机器学习公平性话题的兴趣不断上升,只是在强化这一立场。

机器学习中的公平性

在过去的几年里,机器学习的公平性已经成为一个热门话题。图片来源: CS 294:机器学习中的公平性 加州大学伯克利分校教授的课程。

如前所述,监督机器学习算法的广泛采用引发了对算法公平性的担忧。这些算法被采用得越多,它们对我们生活的控制力越大,只会加剧这些担忧。机器学习社区很清楚这些挑战,算法公平现在是机器学习的一个快速发展的子领域,有许多优秀的研究人员,如 Moritz Hardt,Cynthia Dwork,Solon Barocas 和 Michael Feldman。

尽管如此,在我们能够实现真正公平的算法之前,仍有一些重大障碍需要克服。在算法中防止不同的处理是相当容易的——一个群体对另一个群体的显式区别对待,例如通过从数据集中删除对应于这些属性的变量(例如种族、性别)。然而,要防止不同的影响——一个群体相对于另一个群体的隐性差别待遇,通常是由数据中被称为冗余编码的东西引起的,要容易得多。

不同影响的图示-在此图中,两组的数据分布非常不同,这导致了算法输出的差异,而没有任何组的显式关联。来源: KdNuggets

一个冗余编码告诉我们关于一个受保护属性的信息,比如种族或性别,基于我们数据集中与这些属性相关的特征。例如,在线购买某些产品(如化妆品)可能与性别高度相关,某些邮政编码可能具有不同的种族人口统计数据,算法可能会发现这些数据。

尽管算法并不试图沿着这些路线进行区分,但不可避免的是,在模式识别任务中取代人类表现的数据驱动算法可能会发现这些嵌入数据中的关联,无论它们可能有多小。此外,如果这些关联是非信息性的(即,它们不会增加算法的准确性),则算法将忽略它们,这意味着一些信息显然嵌入在这些受保护的属性中。这对研究人员提出了许多挑战,例如:

  • 公平和准确之间是否存在根本性的权衡?我们是否能够从受保护的特征中提取相关信息,而不会以歧视的方式使用它们?
  • 在算法中嵌入“公平”概念的最佳统计方法是什么?
  • 我们如何确保政府和公司产生保护个人公平的算法?
  • 我们的训练数据中有哪些偏见,我们如何减轻它们的影响?

我们将在文章的剩余部分触及其中的一些问题。

数据的问题

在上一节中,提到了冗余编码会导致与受保护属性相关的特性。随着我们的数据集规模的扩大,这些相关性出现的可能性也相应扩大。在大数据时代,这提出了一个大问题:我们访问的数据越多,我们可用于辨别的信息就越多。这种歧视不一定是纯粹基于种族或性别的,它可以表现为对粉发者、网络开发者、星巴克咖啡饮用者或所有这些群体的组合的歧视。在本节中,将介绍训练数据和算法中存在的几种偏差,这些偏差使公平算法的创建变得复杂。

多数偏向

算法对任何特定的群体都没有亲和力,然而,由于它们的统计基础,它们确实倾向于大多数群体。正如 Moritz Hardt 教授在 Medium 的文章中所概述的,分类器通常会随着用于训练它们的数据点的数量而提高,因为误差与样本数量的平方根成反比,如下所示。

分类器的误差通常随着样本大小的平方根的倒数而减小。四倍的样本意味着误差率减半。

这导致了一个令人不安的现实,因为根据定义,关于少数群体的可用数据总是较少,我们的模型在这些群体中的表现往往比在多数群体中的表现差。只有当多数群体和少数群体来自不同的分布时,这个假设才是正确的,如果他们来自单一的分布,那么增加样本量对两个群体都同样有利。

这方面的一个例子是我们之前讨论过的乳腺癌检测算法。对于这个由麻省理工学院研究人员开发的深度学习模型,在用于训练神经网络的数据集中的 6 万张乳房 x 光照片中,只有 5%是黑人女性的乳房 x 光照片,她们死于乳腺癌的可能性增加了 43%。因此,在对黑人女性和少数族裔群体进行测试时,该算法的表现更差。这可能部分是因为乳腺癌通常在有色人种妇女中较早出现,这表明了不同的影响,因为有色人种妇女的概率分布未被充分代表。

这也提出了另一个重要的问题。准确性是公平的合适代表吗?在上面的例子中,我们假设少数群体的较低分类准确度对应于不公平。然而,由于公平的定义差异很大,性质有些模糊,有时很难确保我们衡量的变量是公平的良好代表。例如,我们的算法对于黑人和白人女性可能都有 50%的准确性,但是如果对于白人女性有 30%的假阳性,对于黑人女性有 30%的假阴性,这也将指示不同的影响。

从这个例子中,几乎可以直观地看出这是一种歧视形式,因为存在基于群体隶属关系的差别待遇。然而,有时这种群体关系对我们的预测是有益的。例如,对于一个试图决定向用户展示什么内容的电子商务网站来说,了解个人的性别、年龄或社会经济地位非常有帮助。这意味着,如果我们仅仅从数据中删除受保护的字段,我们将降低模型的准确性(或其他一些性能指标)。类似地,如果我们有足够的黑人和白人女性的乳腺癌模型数据,我们可以开发一种算法,将种族作为输入之一。由于种族间数据分布的差异,很可能两组的准确性都有所提高。

因此,理想的情况是拥有一个包含这些受保护特征的算法,并使用它们来进行算法概括,但受到公平性度量的约束,以防止算法进行区分。

这是由莫里茨·哈特和埃里克·普莱斯在“监督学习中的机会均等”中提出的想法。与其他指标相比,这有几个优点,如统计奇偶和均等优势,但我们将在下一节讨论所有这三种方法。

公平的定义

在这一节中,我们分析了机器学习公平研究人员提出的一些公平概念。即统计上的均等,然后是统计上的均等的细微差别,如机会均等和机会均等。

统计平价

统计均等是最古老也是最简单的实施公平的方法。在 arXiv 文章 " 算法决策和公平成本 " 中对此进行了详细阐述。统计奇偶校验的公式如下所示。

统计奇偶性公式。换句话说,这说明结果 y 独立于参数 p——它对结果概率没有影响。

对于统计奇偶校验,结果将独立于我的团体从属关系。这直观上意味着什么?这意味着每组的相同比例将被归类为积极或消极。出于这个原因,我们也可以将统计上的均等描述为人口上的均等。对于包含在 p 内的所有人口统计群体,将实施统计均等。

对于尚未应用统计奇偶校验的数据集,我们可以通过计算如下所示的统计奇偶校验距离来衡量我们的预测与统计奇偶校验的偏差程度。

统计奇偶距离可用于量化预测偏离统计奇偶的程度。

这个距离可以为我们提供一个度量标准,来衡量一个给定的数据集基于群体关系的公平或不公平程度

使用统计奇偶校验的利弊是什么?

统计上的均等并不能确保公平。

你可能已经注意到了,统计奇偶性并没有说明这些预测的准确性。一个组可能比另一个组更有可能被预测为阳性,因此我们可能获得每个组的假阳性率和真阳性率之间的巨大差异。这本身会造成完全不同的影响,因为一个组的合格人员( p=0 ) 可能会被另一个组的不合格人员( p=1 )漏掉。从这个意义上说,统计上的均等更类似于结果的均等。

下图很好地说明了这一点。如果我们有两个组,一个有 10 个人(A 组=1),一个有 5 个人(A 组=0),我们确定 A 组=1 中的 8 个人(80%)获得了 Y=1 的分数,那么 A 组=0 中的 4 个人(80%)也必须获得 Y=1 的分数,而不考虑其他因素。

统计奇偶性图解。来源:杜克大学隐私&数据科学中的公平讲义

统计奇偶性降低算法准确性

统计奇偶性的第二个问题是,受保护的类可能提供一些对预测有用的信息,但是由于统计奇偶性强加的严格规则,我们无法利用这些信息。性别对于预测人们可能购买的物品可能非常有用,但如果我们被阻止使用它,我们的模型就会变得更弱,准确性也会受到影响。一种更好的方法将允许我们考虑这些组之间的差异,而不会产生完全不同的影响。显然,统计奇偶校验与机器学习的基本目标不一致——完美的分类器可能无法确保人口统计奇偶校验。

由于这些原因,一些机器学习公平性研究人员不再认为统计奇偶性是一个可信的选择。然而,统计上的均等是一个简单而有用的起点,公平的其他定义都建立在这个起点上。

统计奇偶性有稍微更细微的版本,例如真正奇偶性、假正奇偶性和正比率奇偶性。

真正的正均等(机会均等)

这仅适用于二元预测,并对真值执行统计奇偶校验(预测输出为 1,而真值输出也为 1)。

机会均等与均等几率相同,但重点在于 y=1 的标签。

这确保了在两组中,在所有合格的人(Y=1)中,相同比例的个人将被归类为合格(C=1)。当我们只对正面结果的均等感兴趣时,这是有用的。

真实正宇称的图解。注意,在第一组中,所有 Y=1(蓝框)的都被归类为阳性(C=1)。类似地,在第二组中,所有被分类为 Y=1 的人也被分类为阳性,但有一个额外的假阳性。在统计奇偶性的定义中没有考虑这种假阳性。来源:杜克大学隐私&数据科学中的公平讲义

假阳性奇偶校验

这也仅适用于二进制预测,并侧重于误报(预测输出为 1,但真实输出为 0)。这类似于真阳性率,但是提供了跨假阳性结果的奇偶性。

正比率平价(均等赔率)

这是同时针对真阳性和假阳性的统计奇偶性的组合,也称为均衡赔率**

正比率平价图解(均等的赔率)。注意,在第一组中,所有 Y=1(蓝框)的都被归类为阳性(C=1)。类似地,在第二组中,所有归类为 Y=1 的也归类为阳性。在获得 Y=0 的 A=1 的群体中,其中一个被分类为 C=1,给出 50%的假阳性率。类似地,在第二组中,这些个体中的两个被给予 C=1,对应于 50%的假阳性率。来源:杜克大学隐私&数据科学中的公平讲义

请注意,对于机会均等,我们放宽了均等赔率的条件,即在 Y=0 的情况下赔率必须相等。均等机会和均等机会也更加灵活,能够纳入受保护变量的一些信息,而不会产生完全不同的影响。

请注意,虽然所有这些都提供了某种形式的解决方案,可以说是公平的,但没有一个是特别令人满意的。其中一个原因是,对于公平的内涵有许多相互冲突的定义,很难用算法的形式来捕捉它们。这些都是很好的起点,但仍有很大的改进空间。

增加公平性的其他方法

统计均等、均等的机会和机会均等都是很好的起点,但我们还可以做其他事情来确保算法不会被用来过度歧视个人。已经提出的两种这样的解决方案是人在回路中和算法透明。

人在回路中

这听起来像某种过山车,但它只是指一种人类监督算法过程的范式。人在回路通常在算法出错的高风险情况下实施。例如,当检测到导弹时通知军方的导弹检测系统允许个人审查情况并决定如何做出反应——如果没有人类的互动,算法不会做出反应。想象一下,当 AI 检测到威胁时,允许它开火,运行核武器系统的灾难性后果——一个假阳性,整个世界都将毁灭。

另一个例子是针对累犯的 COMPAS 系统——该系统不会将你归类为累犯并做出法律判决。取而代之的是,法官审查 COMPAS 的分数,并将此作为他们评估情况的一个因素。这提出了新的问题,例如人类如何与算法系统交互。使用亚马逊 Mechanical Turk 的研究表明,一些人会全心全意地遵循算法的判断,因为他们认为它比人类可能拥有的知识更多,其他人则对其输出持保留态度,有些人则完全忽视它。对人在回路中的研究相对来说比较新颖,但随着机器学习在我们的社会中变得更加普遍,我们可能会看到更多这样的研究。

另一个重要且相似的概念是人在回路中。这类似于人在回路中,但不是人主动参与过程,而是被动参与算法的监督。例如,数据分析师可能负责监控石油和天然气管道的各个部分,以确保所有传感器和流程正常运行,并且没有相关信号或错误。该分析师处于监督位置,但不积极参与流程。“人在回路”比“人在回路”本质上更具可扩展性,因为它需要更少的人力,但在某些情况下它可能站不住脚——例如照看那些核导弹!

算法透明性

公平在法律文献中的主导地位是通过算法的可解释性和通过透明度的可解释性。论点是,如果一个算法能够被公开查看和仔细分析,那么它就可以在很大程度上确保模型中没有完全不同的影响。虽然这在许多层面上显然是可取的,但算法透明也有一些缺点。

专有算法根据定义不能是透明的

从商业角度来看,这种想法在大多数情况下是站不住脚的——如果算法和业务流程被提供给所有人看,商业秘密或专有信息可能会被泄露。想象一下,脸书或 Twitter 被要求向世界发布他们的算法,以便他们可以被仔细检查,以确保没有偏见问题。最有可能的是,我可以下载他们的代码,然后很容易地开始我自己版本的 Twitter 或脸书。完全透明只是公共服务中使用的算法的一个选项,例如政府(在某种程度上)、医疗保健、法律系统等。由于法律学者主要关心的是法律制度,这在目前仍然是共识是有道理的。

在未来,对私人公司来说,对算法公平性的监管可能是一个比算法透明度更站得住脚的解决方案,因为私人公司有既得利益让他们的算法远离公众的视线。Andrew Tutt 在他的论文“a FDA For Algorithms”中讨论了这一想法,该论文专注于开发一个类似于 FDA 的监管机构来监管算法。可以将算法提交给监管机构,或者第三方审计服务,并对其进行分析,以确保它们适合使用而不会产生完全不同的影响。

显然,这样的想法需要大量的讨论、资金和专业知识来实现,但从我的角度来看,这似乎是一个潜在可行的解决方案。要确保我们的算法不受不同的对待和不同的影响,还有很长的路要走。通过将法规、透明度、人在回路、人在回路以及新的和改进的统计奇偶性变化结合起来,我们是实现这一目标的一部分,但这一领域仍然年轻,还有许多工作要做——请关注这一领域。

最终意见

在本文中,我们详细讨论了由于收集和分析数据的方式而导致的训练数据中存在的多重偏差。我们还讨论了几种方法来减轻这些偏见的影响,并帮助确保算法对少数群体和受保护的阶层保持不歧视。

虽然机器学习就其本质而言总是一种统计歧视,但当它将某些特权群体置于系统优势而将某些非特权群体置于系统劣势时,这种歧视就会变得令人反感。由于标签中的偏见或欠采样/过采样,训练数据中的偏差会产生带有不需要的偏差的模型。

有些人可能会说,这些决定是由人在较少的信息下做出的,这可能会有许多隐含的和认知的偏见影响他们的决定。自动化这些决策提供了更准确的结果,并在很大程度上限制了这些偏差的程度。算法不需要完美,只要比以前存在的算法更好就行。历史的弧线朝着正义弯曲。

有些人可能会说,算法被赋予了自由,允许不平等被系统地实例化,或者数据本身存在固有的偏见。应该从数据中删除与受保护属性相关的变量,以帮助缓解这些问题,并且删除或限制与变量相关的任何变量。

这两组都是部分正确的。但是,我们不应该满足于不公平的算法,还有改进的空间。类似地,我们不应该浪费我们拥有的所有数据并删除所有变量,因为这将使系统性能更差,并使它们变得不那么有用。话虽如此,归根结底,这些算法和监督机构的创造者以及负责收集数据的人有责任确保这些偏见得到妥善处理。

数据收集和抽样程序在统计学课堂上经常被掩盖,并且不被公众所理解。在监管机构出现之前,机器学习工程师、统计学家和数据科学家有责任确保机会平等嵌入到我们的机器学习实践中。我们必须注意我们的数据来自哪里,我们用它做什么。谁知道我们的决定将来会影响到谁?

“世界是不公平的,卡尔文。”“我知道爸爸,但是为什么从来没有对我有利的时候呢?”
【比尔·沃特森】, 加尔文与霍布斯:一个加尔文与霍布斯的国库

时事通讯

关于新博客文章和额外内容的更新,请注册我的时事通讯。

*** [## 时事通讯订阅

丰富您的学术之旅,加入一个由科学家,研究人员和行业专业人士组成的社区,以获得…

mailchi.mp](https://mailchi.mp/6304809e49e7/matthew-stewart)

进一步阅读

【1】大数据:关于算法系统、机会和公民权利的报告。白宫。2016.

【2】计算机系统中的偏差。巴特娅·弗里德曼,海伦·尼森鲍姆。1996

【3】大数据中隐藏的偏见。凯特·克劳福德。2013.

【4】大数据的不同影响。索隆·巴罗卡斯,安德鲁·塞尔伯特。2014.

【5】博文:大数据有多不公平。莫里茨·哈特。2014

【6】从语言语料库中自动导出的语义包含类人偏见。艾林·卡利斯坎,乔安娜·j·布赖森,阿尔温德·纳拉亚南

研究生招生中的性别偏见:来自伯克利的数据。比克尔,哈默尔,奥康内尔。1975.

****【8】辛普森悖论。珍珠(第六章)。技术报告

****【9】验证并移除不同的影响。迈克尔·费尔德曼,索雷尔·弗雷德勒,约翰·默勒,卡洛斯·沙伊德格,苏雷什·文卡塔萨布拉曼尼安

****【10】监督学习中的机会均等。莫里茨·哈特,埃里克·普莱斯,内森·斯雷布罗。2016.

****【11】博文:接近机器学习中的公平。莫里茨·哈特。2016.

****【12】机器偏差。Julia Angwin,Jeff Larson,Surya Mattu 和 Lauren Kirchner,ProPublica。代码审查:github.com/probublica/compas-analysis,github.com/adebayoj/fairml

****【13】COMPAS 风险等级:展示准确性、公平性和预测性平价。诺斯波因特公司。

刑事司法风险评估中的公平性:最新技术
Richard Berk,Hoda Heidari,Shahin Jabbari,Michael Kearns,Aaron Roth。2017.

****【15】法院和预测算法。安格尔·克里斯汀、亚历克斯·罗森布拉特和丹娜·博伊德。2015.讨论稿

****【16】用机器学习减轻司法偏见的局限性。克里斯蒂安.卢姆。2017.

****【17】支持向量机的概率输出以及与正则化似然方法的比较。约翰·c·普拉特。1999.

****【18】公平确定风险分值的内在权衡。乔恩·克莱因伯格,森迪尔·穆莱纳坦,马尼什·拉加万。2016.

****【19】影响迥异的公平预测:累犯预测工具偏差研究。亚历山德拉·乔尔德乔娃。2016.

****【20】用更智能的机器学习攻击歧视。Martin Wattenberg,Fernanda Viégas 和 Moritz Hardt 的交互式可视化。2016.

****【21】算法决策与公平成本。山姆科比特-戴维斯,艾玛·皮尔森,阿维费勒,沙拉德戈埃尔,阿齐兹胡克。2017.

****【22】歧视性结果检验中的次边际问题。卡米莉亚·西莫伊,萨姆·科比特·戴维斯,沙拉德·戈埃尔。2017.

****【23】监督学习中的机会均等。莫里茨·哈特,埃里克·普莱斯,内森·斯雷布罗。2016.

因果推论的要素。彼得斯、扬金、舍尔科夫

****【25】关于调整混杂和中介变量的回归中种族的因果解释。泰勒·j·范德威尔和惠特尼·r·罗宾逊。2014.

【反事实公平】。马特 j .库斯纳,约书亚 r .洛夫特斯,克里斯拉塞尔,里卡多席尔瓦。2017.

【27】通过因果推理避免歧视。尼基·基尔伯图斯、马特奥·罗哈斯-卡鲁拉、詹巴蒂斯塔·帕拉斯坎多罗、莫里茨·哈特、张秀坤·扬金、伯恩哈德·舍尔科夫。2017.

【28】对结果的公平推断。伊利亚·施皮泽尔·拉齐埃·纳比

【29】通过认知实现公平。辛西娅·德沃克,莫里茨·哈特,托尼安·皮塔西,奥马尔·莱因戈尔德,里奇·泽梅尔。2012.

【30】论公平的可能性。Sorelle A. Friedler,Carlos Scheidegger,Suresh Venkatasubramanian。2016.

【31】为什么不应该使用倾向评分。理查德·尼尔森·Gary King。2016.

【32】原始数据是一种矛盾修饰法。莉萨·吉特曼编辑。2013.

【33】博文:统计中最重要的有哪些是课本上没有的。安德鲁·吉尔曼。2015.

【34】解构统计问题。大卫. j .汉德。1994.

【35】统计学和计量理论。大卫. j .汉德。1996.

【36】计量理论与实践:通过量化看世界。大卫. j .汉德。2010

【调查方法论】第二版。罗伯特·格罗夫斯、小弗洛伊德·j·福勒、米克·p·库帕、詹姆斯·m·莱普考斯基、埃莉诺·辛格、罗杰·图兰盖。2009

男人对于电脑程序员就像女人对于家庭主妇一样?去偏置词嵌入。托尔加·博卢克巴斯、张开伟、詹姆斯·邹、文卡特什·萨利格拉玛、亚当·卡莱。2016.

【39】男性也喜欢购物:利用语料库级约束减少性别偏见放大。、王天禄、马克·亚茨卡、维森特·奥多涅斯、张开伟。2017.

【40】大数据的不同影响。索隆·巴罗卡斯,安德鲁·塞尔伯特。2014.

【41】这不是隐私,也不公平。辛西娅·德沃克迪尔德丽·k·穆里根。2013.

【42】算法决策的麻烦。塔尔·扎斯基。2016.

【43】版权法如何修复人工智能的隐性偏见问题。阿曼达·莱文多夫斯基。2017.

【44】FDA 对算法的。安德鲁·塔特。2016***

每个数据工程师都应该知道的 ML 编程技巧——第 1 部分

原文:https://towardsdatascience.com/programming-hacks-that-every-data-engineer-should-know-part-1-fb7cd436c40?source=collection_archive---------37-----------------------

现实世界中的 DS

数据科学家和机器学习从业者的更广泛的备忘单。

纳赫尔·阿卜杜勒·哈迪在 Unsplash 上的照片

让我们马上开始。

1.省略号对象(…):

它是 Python 中的一个对象,可以用于 Numpy 包中的矩阵切片,也可以用于一般的列表切片。这个对象的主要目的是使多维数组处理更容易。Numpy 数组中的多个索引可以替换为…(省略号对象)。

同样,它也可以用来代替 Python 中的 pass 命令,在定义空函数时实现“无操作”。

>>> import numpy as np
>>> a = np.array([[[i + 2*j + 8*k for i in range(3)] for j in range(3)] for k in range(3)])
>>> arr = np.array(a)
>>> arr
array([[[ 0,  1,  2], [ 2,  3,  4], [ 4,  5,  6]],
[[ 8,  9, 10], [10, 11, 12], [12, 13, 14]],
[[16, 17, 18], [18, 19, 20], [20, 21, 22]]])
>>> **arr[1,...]** array([[ 8,  9, 10], [10, 11, 12], [12, 13, 14]])
>>> **arr[...,1]** array([[ 1,  3,  5], [ 9, 11, 13], [17, 19, 21]])

2.* & @速记运算符:

两个主要的 numpy 矩阵运算是 np.multiply(A,B)np.matmul(A,B) ,它们分别计算元素乘法和矩阵乘法。np.multiply(A,B)可以实现为 A*B ,np.matmul(A,B)可以实现为 A@B

>>> import numpy as np
>>> A = np.random.rand(2,2)
>>> B = np.random.rand(2,2)
**>>> np.multiply(A,B)**
array([[0.69938897, 0.08791922], [0.23572921, 0.04930693]])
**>>> A*B**
array([[0.69938897, 0.08791922], [0.23572921, 0.04930693]])
**>>> np.matmul(A,B)**
array([[0.75990246, 0.74811588], [0.49980481, 0.39179465]])
**>>> A@B**
array([[0.75990246, 0.74811588], [0.49980481, 0.39179465]])

3.样本/混洗数据集:

熊猫数据帧对象可以用一只熊猫随机洗牌。DataFrame.sample()函数。

>>> import pandas as pd
>>> df = pd.DataFrame({'num_legs': [2, 4, 8, 0],
                       'num_specimen_seen': [10, 2, 1, 8]},
                       index=['falcon', 'dog', 'spider', 'fish'])
>>> df
        num_legs  num_specimen_seen
falcon         2                 10
dog            4                  2
spider         8                  1
fish           0                  8
>>> df.sample(frac=1, random_state=2)
        num_legs  num_specimen_seen
spider         8                  1
fish           0                  8
dog            4                  2
falcon         2                 10

4.LP 规范:

范数是从复数或实数上的向量空间到正实数的一种度量。LP 范数是有限维 p 范数的推广形式。p-范数定义为向量的和的幂 p,进一步幂为 p 的倒数,公式如下:

当 p=1 时,其 L1 范数(也称为曼哈顿距离)和用于 Lasso 回归的绝对值范数(称为 L1 损失(MAE))。

当 p=2 时,其 L2 范数,也称为欧氏距离,在岭回归中用作 L2 损失(MSE)。

类似地,p=3,4,…可用于计算不同水平的范数,并可在不同的机器学习算法中用作损失函数。

5.处理等级不平衡:

在所有 scikit learn 的机器学习算法实现中,有一个名为“class_weight”的参数,需要设置为“balanced”或 Python 字典对象,其中包含所有样本的权重。

>>> rfc = RandomForestClassifier(class_weight='balanced')
>>> rfc.fit(df_train_pca,y_train)

6.正在加载 ARFF 数据集:

大多数情况下,当我们使用数据集时,我们被提供了。csv 或。xls 文件,可以用 pandas.read_csv()pandas.read_excel() 函数直接读取。但是,有些时候。arff 文件也用于分析,也用于记录一组属性的实例,如。但是对性能和内存使用更敏感。我们可以使用熊猫数据帧中的 arff 库在熊猫中阅读它,如下所示:

>>> import arff
>>> df = pd.DataFrame(arff.loadarff('./Training Dataset.arff')[0])
>>> df = df.select_dtypes([np.object])
>>> df = df.stack().str.decode('utf-8').unstack()

7.PIL 图像:

PIL 是 Python 图像库,它提供了使用 Python 解释器操作和显示图像的能力。

# importing Image class from PIL package
>>> from PIL import Image
# creating a image object
>>> im = Image.open(r"/Users/killerHack/Desktop/Hackint.jpg")
>>> im.show()

8.用熊猫制图。Series.map():

当操作 pandas 数据框架中的列值时,例如将分类值转换为数值。熊猫。Series.map()函数可用于 Series 或 DataFrame 列,将不同的值替换为另一组值,如下所示:

>>> s = pd.Series(['cat', 'dog', np.nan, 'rabbit'])
>>> s.map({'cat': 'kitten', 'dog': 'puppy'})
0   kitten
1    puppy
2      NaN
3      NaN
dtype: object

9.数据透视表:

大多数人都有在 Excel 中使用数据透视表的经验,并且可以在 Python 中使用相同的 pandas.pivot_table()函数。数据透视表用于汇总大型扩展表中的一些列的数据。

>>> import pandas as pd
>>> df = pd.DataFrame({"A": ["foo", "foo", "foo", "foo", "foo",
...                           "bar", "bar", "bar", "bar"],
...                     "B": ["one", "one", "one", "two", "two",
...                           "one", "one", "two", "two"],
...                     "C": ["small", "large", "large", "small",
...                           "small", "large", "small", "small", "large"],
...                     "D": [1, 2, 2, 3, 3, 4, 5, 6, 7]})
>>> df
     A    B      C  D
0  foo  one  small  1
1  foo  one  large  2
2  foo  one  large  2
3  foo  two  small  3
4  foo  two  small  3
5  bar  one  large  4
6  bar  one  small  5
7  bar  two  small  6
8  bar  two  large  7
>>> table = pd.pivot_table(df, values='D', index=['A', 'B'],
...                      columns=['C'], aggfunc=np.sum)
>>> table
C        large  small
A   B                
bar one    4.0    5.0
    two    7.0    6.0
foo one    4.0    1.0
    two    NaN    6.0

10.Matplotlib 样式参数:

matplotlib 是用于在 Python 中创建静态和动态可视化的绘图库。使用 matplotlib 绘图时,可以根据绘图要求使用 matplotlib.rcParams 对象更改样式的一些重要参数。

**import** **matplotlib.pyplot** **as** **plt**
%**matplotlib** inline
plt.style.use('ggplot')
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.serif'] = 'Ubuntu'
plt.rcParams['font.monospace'] = 'Ubuntu Mono'
plt.rcParams['font.size'] = 10
plt.rcParams['axes.labelsize'] = 12
plt.rcParams['axes.titlesize'] = 12
plt.rcParams['xtick.labelsize'] = 8
plt.rcParams['ytick.labelsize'] = 8
plt.rcParams['legend.fontsize'] = 12
plt.rcParams['figure.titlesize'] = 14
plt.rcParams['figure.figsize'] = (12, 8)

目前就这些。在接下来的几部分中,我将介绍更多这些每个数据工程师都应该了解的重要技巧/功能。敬请关注。

【更新】
下面继续下一部分..

[## 每个数据工程师都应该知道的 ML 编程技巧——第 2 部分

数据科学家和机器学习从业者的更广泛的备忘单。

towardsdatascience.com](/ml-programming-hacks-that-every-data-engineer-should-know-part-2-61c0df0f215c) [## 机器学习中最常见的损失函数

每个机器学习工程师都应该了解机器学习中这些常见的损失函数,以及何时使用…

towardsdatascience.com](/most-common-loss-functions-in-machine-learning-c7212a99dae0)

照片由豪伊·R在 Unsplash 拍摄

感谢阅读。你可以在这里找到我的其他机器学习相关的帖子。

希望这篇帖子有用。我感谢反馈和建设性的批评。如果你想谈论这篇文章或其他相关话题,你可以在这里或在 LinkedIn 给我发短信。

[## 数据可视化的重要性——Anscombe 的四重奏。

四个数据集欺骗了线性回归模型。

towardsdatascience.com](/importance-of-data-visualization-anscombes-quartet-way-a325148b9fd2)

没有技术术语的逻辑回归+与树模型的比较

原文:https://towardsdatascience.com/programming-journal-3-logistic-regression-cbf68f01bf7d?source=collection_archive---------68-----------------------

没有术语的机器学习

如果你喜欢披萨,你就会明白逻辑回归和随机森林的区别!

尼克·欧文斯在 Unsplash 上的照片

概述

  • 什么是逻辑回归,它有什么好处
  • 理解这个算法和随机森林(我们上周提到的那个)的区别,用一个意大利辣香肠披萨来说明使用哪个更好!
  • 本周我这边的更新

逻辑回归非常常用于告诉我们一个事件是 T 还是 F,例如,这个客户会留下还是离开,这是垃圾邮件还是非垃圾邮件,有人会不会得这种病,等等。我几次看到人们声称这是最常用的算法。所以就来说说吧。

假设我们的漏斗中有 1000 名新客户作为潜在客户。我们知道有些客户比其他人更有可能和我们在一起。换句话说,一些客户更符合我们的特征,或者需要我们付出更少的精力来达成交易。我们想确认他们是谁。

图片 1

由于这是一个相互排斥的事件,客户越有可能留在我们这里,客户就越不可能离开我们。那么让我们在这里陈述我们的目标:我们想要一个模型,这样如果客户 A 可能会和我们呆在一起,它会告诉我们“呆”的概率很高,或者“不呆”(1-呆)的概率很低,反之亦然。(记住这一点,我们以后再来讲这个!)

图片 2

我们有三个变量,它们是合同的大小(价值),客户的类型(B2C 对 B2C),以及他们了解我们的渠道。我们非常直观地开始思考,我们需要看看我们以前的客户,看看这三个变量与结果之间有什么关系。这是正确的方向,除了我们这里有一个问题。

在我们初中或高中学过的传统线性方程中,它不代表概率;它给了我们一个明确的答案。为了向您展示我的意思,在图 3 等式 1)中,我们可以使用一些以前的数据,并有一个函数来计算 A、B 或 C 的“停留”百分比……我们将需要另一个函数来计算 A、B 或 C 的“未停留”百分比。这两个百分比不一定相加为 1,因为它们不代表概率。

因此,一些聪明的家伙开始思考,如果,我升级 Y,使它直接产生一个比较事件“停留”的概率和事件“不停留”的概率的结果,换句话说,它告诉我哪个事件比另一个更可能发生(图 4) 。这就是我们如何从功能 1)到功能 2)!函数 2)直接给我们“停留”的概率和“不停留”的概率之比

图 3

图 4

那么木头为什么会在哪里出现呢?现在就不能解决关系吗?

原因很简单。这是因为当我们在比较 A 比 B 多多少时间时,这个数字可以从 0 到无穷大。你想想,你比你不喜欢的人牛逼 100 倍、1000 倍、10000 倍……牛逼。“时代”可以有多大是没有限制的(当然!).另一方面,如果我们想表达更少的可能性,我们没有办法做到,因为我们的等式 2)的分子的最小值,事件 A 的概率是 0。不存在负概率。

为了解决这个问题,我们通过记录 y 从等式 2)移至等式 3)。如果您需要一些关于对数如何工作的提示,我在下面附上了基于 10 的对数标度与线性标度的图像。简而言之,这只是一种不同的测量方式,比如从英尺到厘米。现在,我们准备使用我们的数据,并解决这些系数!

图 5

来源

我相信学校里没有多少人喜欢解这些系数的作业。这就是为什么我们要使用算法!!没什么花哨的。在逻辑回归中,当你输入数据后,你的计算机会告诉你系数,而不是一个神奇的答案。

我们的计算机将通过尝试一系列不同的线来为我们获得最佳系数!我们如何定义最好的一个?记得我们的目标是什么吗?

我们需要一个模型,这样如果客户 A 很有可能和我们呆在一起,它会告诉我们“呆”的概率很高,或者“不呆”(1-呆)的概率很低,反之亦然。

因此,最佳系数的定义是使最大数量的情况能够满足我们定义的目标。

现在,计算机已经给了我们系数。我们已经解决了三个变量和结果之间的关系!现在我们想从我们的函数中获得洞察力。然而,记住我们改变了我们的 Y,所以解释起来有点棘手。让我们编造一些准确的数字来说明这一过程。

图 6

第一个系数是指 x1 增加 1 个单位(其他一切不变),将增加概率 x 与概率(1-x) 的比值在对数标度上增加 0.005;另一方面,x2 增加 1 个单位,将会使在对数标度上使比率降低 0.65。

既然在生活中,我们用的是线性标度而不是对数标度,那么我们可以用 e 将其转换回线性标度,在 x2 的例子中,之前,事件“停留”发生的可能性是事件“不停留”发生的可能性的 1.17 倍。然而,在 x2 发生 1 个单位的变化后,尽管“停留”仍然更有可能发生,但该比率现在降低到只有 0.52 倍的可能性。

图 7

图 8

嘿,我知道这不是最简单的事情,但是如果你能接受这个,你知道有什么好处吗?

你不仅知道谁有可能留下来,你应该把精力放在哪里,而且在那些有可能留下来的人中,你甚至知道谁最有可能留下来!所以现在,您可以对您的客户进行排名,或者为不同的客户制定不同的预期时间表!!

例如,对于不太可能的客户,预留更多的时间,因为这将是一场漫长的战斗,如果你没有在第一次尝试中获得它,不要觉得自己不好:)对于那些已经获得的客户来说,更有可能是“不留下来”,然后留下来,我们现在甚至不需要麻烦!!

你如何整合你发现的例子

好吧,但是上周的帖子显示,随机森林也可以告诉我们一个客户是否会留下来或离开,为什么要用另一种方法呢?

我们可以(或许应该)用很多角度来解决这个问题,但我只想在这里给出最直观的答案。

(来源)

想象一下,你的室友让你把比萨饼平均分成两份,因为你喜欢意大利辣香肠,所以你正在考虑如何切它,以便最大限度地获得意大利辣香肠。在逻辑回归中,你只能选择一条线来切断,尽管你仍然有很多选择,然而,在决策树中,没有这样的规则。

这种差异的原因是,在树模型中,我们使用一组逻辑陈述(是或否问题)来得出我们的结论,而对于逻辑回归,我们定义一组数字关系。当我们用一组数字来表达一种关系时,我们已经预先确定了一个等式,一个预先确定的结构来表达这种关系。例如,我们有等式 1)、2)和 3),我们只想找到系数。当我们使用一组逻辑语句时,我们不会指定这种关系是什么样的结构。

所以你可能会问,哪个更好?

谨记“如果一个模型是好的?”或者“应该使用哪个模型?”可以扩展成一个巨大的主题模型评估,我打算写一个单独的博客。对于每个人来说,了解我们应该或者能够如何评估一个模型是至关重要的,因为很多时候,在生产中使用哪个模型不仅仅是由具有坚实技术背景的人决定的。现在,让我们只讨论基础知识。

继续披萨的类比,第一个方法是计算哪一个给我们的辣香肠最多。然而,大多数时候事情并不那么清楚。如果你仔细观察比萨饼,通过使用逻辑回归划分,我们可以得到 7–7.5 个意大利辣香肠,而树模型给我们 8 个意大利辣香肠。没有明显的区别。考虑到每块披萨上意大利香肠的位置略有不同,逻辑回归有时可能会优于树形模型。这就是为什么你看到一个数据科学家有时使用 2 或 3 个模型,看看哪一个做得最好。

思考这个问题的另一种方法是问:除了模型的准确性,什么样的信息将最有助于解决您的业务问题?正如我在以前的文章中提到的,树模型(包括随机森林)最好的部分是它告诉你哪个逻辑语句最重要。在我们的比萨饼例子中,如果每个矩形都是一个逻辑陈述,那么它应该是最左边的那个,因为它给了我们三个意大利香肠。对于逻辑回归来说,最好的部分是它不仅给了我们意大利辣香肠,还告诉我们哪个意大利辣香肠最大,并为我们排序。

因此,在商业环境中,如果我正在开发一个产品并希望改进功能,树模型将帮助我们确定哪个功能是最重要的,因为该功能将为我们带来最多的客户,但如果我希望在月底前尽可能多地签订合同,逻辑回归将告诉我们首先瞄准哪些客户,因为他们最有可能从一开始就与我们合作。

每周更新!!上周不是最有成效的一周。

从周一到周二,在我周一晚上发布了我的上一篇文章后,我经历了一场几乎是恐慌的袭击,因为我意识到了我在文章中犯的一些错误(已经修复)。虽然我知道这是一个学习的过程,我知道作为一个新作家,可能没有人会仔细阅读这篇文章,但我仍然感到非常尴尬。因此,我花了两天时间来确保我对这个模型了如指掌。

周三和周四,我在准备两份工作申请,周四我有一个第一轮面试。不幸的是,我的推荐人告诉我,虽然面试的人力资源给了我一个通过,但我未来的老板让我失望了,因为我在☹之前没有任何相关的工作经验

在经历了这些情绪紧张的日子后,我开始感到有点疲惫,我觉得这一周我没有完成任何事情。我也开始质疑自己在数据领域找工作的能力(我看了一段时间不同的工作岗位)。所以我放慢了自己的节奏,出去散步,做一些烘焙,花一些时间读一本名为《商业数据科学》的书。阅读是我的自理活动之一。此外,这是一本令人惊叹的书,我打算在读完之后分享一些见解。

除此之外,我还在以下方面取得了一些进步:

  • 模型选择和正则化:像所有的降维方法一样,ROC,AUC
  • 关于树模型算法的更多信息:Ada 增强、梯度增强和 XGboost
  • 总结所有监督模型并了解如何使用它们。为了准备这篇文章,我比以前更深入地理解了逻辑回归、LDA 和朴素贝叶斯。
  • 我确实开始了一个项目,但我决定做一个预测客户流失的项目,而不是客户细分。我没有取得多大进展,但我计划下周完成它。我的目标是同时使用随机森林和逻辑回归。

仅此而已。我想用一句令人愉快的话来结束这篇文章,来提醒我自己和其他所有感觉有点精疲力尽的人。

“生活中的大事只有在你花时间做一些照顾自己的小事时才有可能实现。”—香奈儿·米勒

下周见!

为什么我们必须谈论第一类错误和第二类错误?

原文:https://towardsdatascience.com/programming-journal-4-why-do-we-have-to-talk-about-type-1-error-and-type-2-error-41b3ae68bb96?source=collection_archive---------54-----------------------

艰难的教训,真正的秘诀

从模型评估到商业决策…

在 Unsplash 上由 nousnou 岩崎拍摄的照片

你听说过 1 型错误和 2 型错误吗?还是假阳性,真阴性等?当我们研究假设检验时,通常会引入这些概念。这是推断统计学中的一个基本概念。然而,每个人都应该理解这一点,因为当我们想要评估使用哪个模型来进行更好的业务决策时,这也是至关重要的。我想告诉你为什么。

因为解释这个直截了当的概念有点枯燥,所以我将在这里使用一个类比来添加一些果汁,这样你就永远不会忘记这个概念🤓

想想你的男朋友/女朋友/想象中的伴侣。在一段关系中,我们知道有不同类型的谎言。其中一种是善意的谎言,意思是你问了一些信息,但是你的伴侣告诉了你一些不真实的事情,因为他/她想让你感觉更好。另一种谎言是隐藏信息。你询问一条信息,但你的伴侣只是否认。

对于这个类比,你可以把算法想象成测谎仪。与另一种类型的谎言相比,一些算法更擅长检测一种类型的谎言。我们需要知道这种算法擅长检测哪种类型的谎言。为什么?因为不同类型的谎言或者同一类型的谎言,在不同的情境下,会有不同的代价。

比如,对于善意的谎言来说,“我爱你做的菜”的谎言和“我爱你”的谎言不知道的代价是完全不同的(当然对于骗子来说,两个谎言被识破的后果也是很不一样的)。所以在第二种情况下,你会想要使用能够最好地检测善意谎言的算法!因为这个谎言会让你付出很大代价。

来源:makeameme.org

隐藏信息也一样。你的伴侣隐瞒了他/她吃了一个培根芝士汉堡的事实,而你们两个承诺一起节食,这和隐瞒他/她看到另一个人也就是欺骗你的事实有着不同的代价。因此,为了检测这一点,你需要选择一种对这类谎言特别敏感的算法。

现在你已经理解了不同类型的谎言以及它们的重要性。我们把技术术语带回来,连起来。

在一个模型中,我们有预测值(我们的模型给我们的值)和实际值(或观察值,我们从现实中观察到的值)。衡量我们的模型有多好的最直接的方法是看他们对实际值的正确次数。当实际值为时,我们希望我们的预测说,当它为时,我们希望我们的预测说因此,有两种类型的准确答案,模型也有两种出错的方式。

来源: mrzepczynski ,经由 blogspot.com

对于假阳性、真阴性等术语,如果你觉得它们难以记忆,可以这样想:如果这是一个错误的预测,那么这个术语将以“假”开头,如果它是正确的预测,则以“真”开头。

联系到我们在关系中撒谎的类比,我想把“假阴性”理解为否认事实,因为它是否认,把“假阳性”理解为善意的谎言,因为这个人主动给了我一条新的信息。

现在我们知道了技术术语。让我们来谈谈为什么我们需要在商业环境中谈论它们。

原因是一样的,因为在不同的情况下,与每种错误相关的成本是不同的。

例如,上周,我谈到了如何使用逻辑回归来预测哪些客户更有可能沿着漏斗向下移动,以便您可以集中精力锁定最有可能的客户。我们的逻辑回归有 98%的准确率,我们有 1000 个潜在客户。因此,200 个客户会有错误的分类,换句话说,我们的模型“欺骗”了我们。

比方说,我们有一些营销材料要邮寄给我们的潜在客户,我们只发送给那些我们希望重点锁定的客户,因为每份材料的制作成本为 100 美元。因此,如果所有的 200 名客户从未对我们感兴趣,但我们的模型告诉我们他们会感兴趣(假阳性:说谎让我们感觉更好),我们将材料邮寄给他们,那么公司的成本将是 20,000 美元。另一方面,如果所有 200 个错误分类的客户都是假阴性(对我们隐藏信息),换句话说,我们没有对那些本来会对我们感兴趣的客户采取任何行动,财务成本将是 0 美元。

尽管如此,尽管其中一个成本更高,但这并不一定能让一个比另一个更好。我试图反复强调这种情况的重要性,因为成本不仅仅是数字上的,我们还有机会成本和其他隐性成本。例如,如果你是一家 B2B 公司,与 B2C 公司相比,你的考虑应该是不同的,因为每笔交易的规模可能不同,所以损失 20,000 美元意味着不同的东西;或者对你的公司来说,首先很难让客户感兴趣,或者你通常每年只有 50 个客户,或者每个漏斗的成功率不同,等等。等。

如果你用谷歌搜索 1 型和 2 型错误,许多材料使用癌症检测来证明为什么知道类型会有所不同。该示例的重点是显示与不同类型相关的不同成本。明确地说,治疗一个健康病人的成本与不知道某人患有癌症的成本。在这里,我想强调在不同的情况下,即使是同一类型的错误也会产生不同的影响。

这里的要点是,记住同一类型的谎言在不同的情况下会有非常不同的代价。做生意也是一样。同一类型的错误对于不同类型的企业来说,成本是不同的,更不用说不同类型的错误了。

所以下一次,当你的数据团队向你展示一个模型和准确性时,问问他们,这个模型对哪种类型的错误更敏感?然后,在选择模型之前,了解与您的业务问题相关的成本!

我这边每周更新一次:

我选择这个主题来写这个星期,因为我花了大部分时间在模型评估、选择和特征工程上。我意识到,数据工程师的职位需要对业务和公司试图解决的业务问题有非常透彻的理解。我也开始怀疑在工作场所,许多公司将数据收集员(其他部门)、数据工程师和数据科学家的职位分开,这种设置有多容易引发问题。

我还在做上周帖子中提到的客户流失率项目。我希望在下面的帖子中,我可以完成这个项目,并以它作为一个真实的例子来演示两个模型如何具有相同的准确性,但由于不同类型的误差,对业务产生非常不同的影响。

在非技术方面。我申请了一些工作。我意识到我焦虑和缺乏信心的原因是由于缺乏这方面的经验,这直接影响了我的工作效率。

例如,我不确定我现在拥有的技术技能是否足以胜任数据分析师或数据工程师的工作;与其他候选人相比,我有竞争力吗?我可以花更多的时间准备、自学、做项目,直接开始做数据科学家吗?所有知识的缺乏让我不安,因为我觉得我没有足够的针对性。

所以,我决定向人们伸出援手,找到答案,而不是坐在那里,用我的想象力让自己冷静下来。我总结了我最关心的三个问题,并对它们的优先级进行了排序。我也愿意参加一般性的谈话,这样我可以更好地了解整个领域的生态系统,并对我的职业发展道路有一个想法。你可以看下面的截图。

我给每个问题都涂了颜色,这样在我列出我打算联系的人的其他页面上,我可以在他们的名字旁边加上不同的颜色。因此,对我来说,识别缺少哪种颜色是很容易的。

我最初是通过我学校的校友网络在 LinkedIn 上找人的。然而,因为我的学校是一所商学院,符合我条件的人非常有限。猜猜我做了什么?我开始通过 向数据科学 筛选人哈哈。

我的结论是,在 TDS 上写作的人更有可能是喜欢分享的人,这将给我一个更好的机会去结识那些非常规进入这个领域的人。我已经确认了下周的两个电话!

我真的很感激有陌生人帮助我。我等不及有一天我会成为帮助别人的人了!

向梅致以最美好的祝愿!希望这个月一切都会变好:)

参考:

  • 教务长,福斯特,1964-和汤姆。Fawcett,【关于数据挖掘和数据分析思维,你需要知道什么】。加利福尼亚州塞瓦斯托波尔:2013 年,奥赖利。

量子信息编程

原文:https://towardsdatascience.com/programming-quantum-information-8f251ec6770?source=collection_archive---------46-----------------------

奇点研究

使用 Python 和 Qiskit 的熵

在本文中,我们要来看看如何使用 Python 和 IBM 的免费开源量子计算软件 Qiskit 来理解量子系统中的信息的概念。我们将看看熵的经典版本,以展示它与量子熵或冯诺依曼熵的关系。我们会提供代码,最后会有一些免费的交互式 Jupyter 笔记本的链接,你可以在你的浏览器中运行,以更好地理解概念。

量子电路

概率分布

在信息研究中,我们首先遇到的概念之一是概率分布。有限概率分布是一个函数,

概率分布

从某个有限集𝑋到区间[0,1]。𝑥2,…,𝑥𝑛} 𝑋={𝑥1 的有限集通常被认为是可能发生的事件的集合,值𝑓(𝑥𝑖)∈[0,1]是𝑥𝑖事件发生的相关概率。函数𝑓必须满足以下条件

概率之和必须为 1

所以所有的概率总和为 1。举个例子,如果我们有一枚硬币可以抛,我们可以把事件集合定为𝑋={ℎ,𝑡} (" 正面"或"反面"),概率是𝑓(ℎ)=1/2 和𝑓(𝑡)=1/2.显然𝑓(ℎ)+𝑓(𝑡)=1,所以函数𝑓:𝑋→[0,1]是集合𝑋.上的概率分布如果我们有一个六面骰子,我们可以把事件集合看作是𝑌={1,2,3,4,5,6},概率是

六面骰子的概率

函数𝑔:𝑌→[0,1]也是一个概率分布(在事件集𝑌).上现在,我们可以有联合概率分布,它是由像(𝑓×𝑔):𝑋×𝑌→[0,1].)这样的函数描述的在这种情况下,我们可以写出概率表

联合概率分布

在这种情况下,𝑋X 组的结果与𝑌Y.组的结果在本质上是独立的。掷硬币对掷骰子没有影响,掷骰子对掷硬币也没有影响。然而情况并非总是如此。有时我们有相互依赖的联合概率。在这种情况下,我们有条件概率,其中𝑦∈𝑌事件发生的概率取决于𝑥∈𝑋.事件

香农熵

在教科书中,可能发生的𝑋X 事件集通常被称为随机变量香农熵给出了我们通过学习随机变量的值平均获得多少信息的精确定义。𝑋的定义了在得知结果值之前,我们对𝑋的不确定性。因此,假设我们有一些有限的事件集(或随机变量)𝑋={𝑥1,…,𝑥𝑛},相关的概率分布𝑓:𝑋→[0,1]取值{𝑓(𝑥1),…,𝑓(𝑥𝑛)}.香农熵定义为

香农熵

这里,对数以 2 为底。每个概率都是一个 0≤𝑓(𝑥𝑖)≤1.值让我们来看看抛硬币的例子。在这种情况下,香农熵就是

抛硬币的香农熵

现在,让我们看看六面骰子的情况。这种情况下的香农熵为

六面模具的香农熵

为了计算这一点(以及其他),让我们用 Python 导入一些东西。首先,运行以下命令导入必要的库。

Python 导入

我们可以很容易地在 Python 中得到-log(1/6)的十进制近似值,如下所示。

Python 中的计算日志(1/6)

作为另一个例子,让我们以随机变量𝑋为例,它可以取值{𝑥1,𝑥2,𝑥3,𝑥4}.设相关的概率分布为

{𝑓(𝑥1)=1/8, 𝑓(𝑥2)=1/4, 𝑓(𝑥3)=1/8, 𝑓(𝑥4)=1/2}.让我们用 Python 来定义这些概率。

用 Python 定义概率

现在,让我们计算香农熵。

X 的香农熵

冯·诺依曼熵

香农熵测量与经典概率分布相关的不确定性。我们在之前的笔记本中讨论过密度算子。回想一下,密度算符是一种描述量子系统可能状态的方式,或者等效地说,是一种描述可能测量结果的方式,与概率分布非常相似。量子态ρ(其中ρ是密度矩阵)的冯诺依曼熵定义为

冯·诺依曼熵

这里的对数现在是一个矩阵对数,也取为底数 2。如果我们让{𝜆𝑘}是矩阵ρ的特征值的全集,那么我们也可以将冯诺依曼熵定义为

冯·诺依曼熵

使用scipy.linalg.logm()可以在 Python 中计算矩阵对数。我们已经从 SciPy 导入了linalg作为la。让我们看一个例子。拿着矩阵

密度矩阵

在 Python 中,我们可以使用下面的代码来定义密度矩阵,

Python 中的密度矩阵

为了得到合适的基数 2,我们需要使用一个转换,

对数的底数变化

所以,我们真正需要的是,

矩阵对数

我们可以使用这个矩阵的迹来计算冯·诺依曼熵,如下所示,

冯·诺依曼熵

正如所料,这是一个 1×1 矩阵,即标量值。让我们为密度矩阵定义一个计算冯·诺依曼熵的函数。

Python 中的冯诺依曼熵函数

现在,让我们在矩阵rho上测试这个函数。

测试功能

状态演化

在量子物理学中,状态很少保持不变。在量子计算的电路和门模型中,状态根据酉矩阵运算演化,状态向量的演化相当于线性代数。在其他模型中,我们可以使用哈密顿量来模拟状态的演化。有两种重要的状态叫做混合态和纯态。纯状态总是可以表示为状态向量与其自身的“外积”。混合状态通常表示为正交状态向量的和。在纯态的情况下,冯·诺依曼熵总是零。在混合态的情况下,熵可以是整个范围的值。让我们看一个例子,一个系统从纯态演化到混合态,然后又回到纯态。我们将看到冯·诺依曼熵逐渐增大,然后减小回到零。首先,我们来定义自旋向上和自旋向下的状态向量,以及外积给出的纯态。

定义纯态

我们可以使用下面的代码来绘制进化图,

情节演变

我们得到的图表如下,

我们可以将其与经典的香农熵进行比较

香农熵

看到它们实际上是一样的。

香农熵图

使用 Qiskit

在 Qiskit 中,我们可以对下面的量子电路进行编程,

GHZ 状态

接下来,我们可以使用 Qiskti 的Statevector()函数来打印状态向量。这将有助于使用 Qiskit 中的函数entropy()计算相应密度矩阵的冯诺依曼熵。

状态向量

接下来,我们使用 Qiskit 的DensityMatrix()函数,将上面定义的GHZ_state ket-vector 传递给它。

Qiskit 中的密度矩阵

现在我们可以使用 Qiskit entropy()函数来计算熵。我们可以通过StatevectorDensityMatrix。在第二种情况下,我们得到有效的零熵,在第一种情况下,我们得到精确的零熵。这是有意义的,因为态是纯态,密度矩阵是按𝐷=|𝜓⟩⟨𝜓|.计算的

齐斯基特中的冯·诺依曼熵

最后,让我们使用 Qiskit 函数random_density_matrix()生成一个随机密度矩阵𝜌ρ。该函数的第一个参数是所需密度矩阵的维数,它不必是 2 的幂。然而,在具有量子位的量子电路的情况下,我们手动做出这种限制是很重要的。当然还有更一般的系统,包括像“ qudits 这样的东西,它们可能产生任意维的密度矩阵。

随机密度矩阵

我们可以使用 Qiskit entropy()函数来计算熵。

冯·诺依曼熵

让我们画出从 GHZ 态的密度矩阵𝐷给出的态演化到密度矩阵ρ描述的系统的熵。

绘图熵

我们得到的情节是,

如果你想了解更多,可以考虑支持 Github 。有超过 20 个免费的,关于量子计算和量子机器学习的交互式笔记本,你可以在你的浏览器中运行。有关熵的笔记本请点击链接。如果你想为这个项目做贡献,或者如果你需要在你正在做的事情中加入量子计算方面的咨询,请联系

thesingularity.research@gmail.com

一定要包括“黑客宇宙”这个主题,这样邮件才不会丢失。

使用 tqdm 的 Python 的进度条

原文:https://towardsdatascience.com/progress-bars-for-python-with-tqdm-4dba0d4cb4c?source=collection_archive---------9-----------------------

使用智能进度条跟踪 Python 迭代的执行

在 Unsplash 上由zdenk macha ek拍摄的照片

在我开始从事 Python 中的机器学习项目后不久,我遇到了需要很长时间才能运行的计算密集型任务。通常这与某种可重复的过程有关。我立即想到的两个例子是:( 1)在 p、d 和 q 订单上运行网格搜索,以在大型数据集上拟合 ARIMA 模型,以及(2)在训练机器学习算法时网格搜索超参数。在这两种情况下,您可能会花费数小时(或更长时间!)等待您的代码运行完毕。我迫切需要某种指标来显示这些任务的进展,于是我找到了 tqdm

什么是 tqdm?

tqdm 是一个 Python 库,允许你通过环绕任何 iterable 来输出一个智能进度条。一个 tqdm 进度条不仅显示了已经过去的时间,还显示了可迭代的估计剩余时间。

安装和导入 tqdm

由于 tqdm 是 Python 包索引( PyPI )的一部分,因此可以使用 pip install tqdm 命令进行安装。

我倾向于经常在 IPython/Jupyter 笔记本上工作,而 tqdm 为此提供了出色的支持。要开始在笔记本上玩 tqdm ,您可以导入以下内容:

例子

为了清楚起见,我不会在这篇文章中进行计算密集型的网格搜索——相反,我将使用几个简单的例子来演示 tqdm 的用法。

For-loop 进度

假设我们想在跟踪结果的同时模拟投掷一枚硬币 100,000,000 次,我们还想看看这些迭代在 Python 中运行需要多长时间。我们可以围绕 iterable(范围(100000000))包装 tqdm 函数,这将在 for 循环运行时生成一个进度条。我们也可以使用 desc 关键字参数给进度条指定一个名称。

产生的 tqdm 进度条为我们提供信息,包括任务完成百分比、完成的迭代次数、经过的时间、估计的剩余时间以及每秒完成的迭代次数。

在这种情况下, tqdm 允许通过使用 trange(100000000) 代替 tqdm(范围(10000000))进行进一步优化。

嵌套 for 循环进度

如果您遇到需要嵌套 for 循环的情况, tqdm 允许您在多个层次上跟踪这些循环的进度。例如,让我们以抛硬币为例,但这次我们想玩三个独立的 10,000,000 次抛硬币的“游戏”,同时跟踪结果。我们可以为“整体进度”创建一个 tqdm 进度条,以及三个游戏中每一个的进度条。

熊猫集成

tqdm 的一个稍微不同的实现涉及到与 熊猫 的集成。 tqdm 可以为提供额外的功能。应用()方法的一个熊猫数据帧。熊猫。必须首先使用下面的代码向 tqdm 注册 progress_apply() 方法。然后,是。使用 progress_apply() 方法代替传统的。apply() 方法——不同之处在于,我们现在在方法的输出中包含了一个智能进度条。

Processing Dataframe: 100%|██████████| 1000/1000 [00:02<00:00, 336.21it/s]

其他 tqdm 集成

除了与 IPython/Jupyterpandastqdm 提供与 Keras 和实验模块的集成,用于 itertools并发不协调电报这篇文章仅仅触及了 tqdm 功能的表面,所以请务必查看文档以了解更多关于如何在 Python 代码中包含智能进度条的信息!

参考

[## tqdm/tqdm

tqdm 源自阿拉伯语 taqaddum (تقدّم),意思是“进步”,是“我如此爱你”的缩写

github.com](https://github.com/tqdm/tqdm/tree/f4b172f7ec7598d75df094eb713c5be5370033bc#ports-to-other-languages) [## tqdm 文档

tqdm 在阿拉伯语(塔卡杜姆,تقدّم)中是“进步”的意思,在西班牙语中是“我非常爱你”的缩写(特…

tqdm.github.io](https://tqdm.github.io/)

渐进神经网络:解释与实现

原文:https://towardsdatascience.com/progressive-neural-networks-explained-implemented-6f07366d714d?source=collection_archive---------25-----------------------

学习使用 PyTorch 和 Doric 库创建渐进式神经网络。

目录

• [Introduction & Background](#b575)
    ∘ [Transfer Learning](#2f8f)
    ∘ [Progressive Neural Networks](#0d70)
• [Doric](#a6bc)
• [Simple Example](#a1b0)
• [Complex Example](#9e99)
    ∘ [Autoencoders & VAEs](#4b35)
    ∘ [Experimental Design](#50ba)
    ∘ [Results](#4088)
    ∘ [Analysis](#81c7)
• [Conclusion](#b78d)
• [Acknowledgments](#5f5d)
• [Links & References](#8e8d)

简介&背景

学习新的东西需要你建立在你已经知道的基础上。就像一把简单的锤子可以被用来将金属塑造成更加动态和复杂的工具一样,先前的知识可以成为形成想法和创造新知识的基础。研究只不过是这种想法一遍又一遍地应用于自身。

迁移学习是指将在一项任务中学到的知识应用到另一项相关任务中。许多神经网络转移学习技术已经被成功地使用。然而,网络的拓扑通常是固定的,旧任务中使用的参数很可能被破坏性地覆盖。这些不需要的品质由渐进式神经网络解决,这种网络可以扩展其拓扑结构——用它来传输重要的知识——同时保留原始参数供以后使用。

本文将讨论迁移学习、灾难性遗忘和渐进式神经网络。在这本书中,我们将学习使用 Doric 库和 PyTorch 来创建程序网;以及遍历它背后的代码,并检查它如何实现渐进式神经网络论文中讨论的功能。最后,我们将使用 Doric 运行两个 prognet 实验,并分析它们的结果,以更好地理解使用渐进式神经网络进行迁移学习的好处和缺点。

转移学习

国际象棋是一种有趣而复杂的游戏,像许多伟大的游戏一样,它的复杂性可能需要花一生的时间来掌握——然而它的基本机制可以在一个下午就被教授和理解。每个象棋新手最终都会遇到类似下图的情况,他们会很快学会白棋的最佳走法:移动骑士同时攻击黑棋的两个车。

通过同时威胁两个目标,白棋迫使一个有利的交易。

这种策略被称为“叉”,将黑方置于两败俱伤的境地,他们必须用自己的一辆车交换白方的骑士。熟练的棋手将会知道迫使对手下叉是非常有利的。

国际象棋并不是唯一出现这种简单战术的游戏。Connect-4 是一种游戏,其中两名玩家将瓷砖扔进一个 6×7 的直立网格中,目标是在对手之前完成 4 个瓷砖。下图是一个 connect-4 板。红色有机会以这样一种方式连接三个瓷砖,蓝色只能阻止一边的运行,让红色在下一轮获胜。

Connect-4 战略在很大程度上基于这一策略。

国际象棋和 Connect-4 是非常不同的游戏,但它们都包括从两个方向同时进攻的相同策略,迫使敌人陷入无赢的局面。事实上,叉子战术可以在许多游戏中找到。通过学习叉子的概念,并通过不同游戏的机制应用该概念,我们能够跨不同领域传递知识。学象棋可以教我们一些关于 Connect-4 的知识。

亲爱的读者,这就是迁移学习的本质。

迁移学习是将从一项任务中获得的知识应用到另一项独立但相关的任务中的过程。近年来,迁移学习在语言和图像处理领域得到了广泛的应用。在自然语言处理中,预训练的嵌入模型如埃尔莫、伯特和 GPT-2 已经成功地学习了英语的基本结构,从而可以应用于许多任务。在这种情况下,模型通常被冻结,优化只在连接到嵌入器头部的任务模型上执行。虽然这种方法对于语言任务来说是理想的,但它依赖于遵循语言结构的一致输入。在图像处理中,完全训练卷积神经网络来完成复杂的任务已经变得罕见。相反,通才预训练网络,如 ResNet-50 、 GoogLeNet 和 VGG-19 会根据新数据进行再训练。这个过程被称为微调。虽然微调是使网络适应新数据的有效方法,但它也不是没有缺点。

灾难性遗忘是一种有害事件,在微调过程中可能发生在经过训练的神经网络中。当网络中的重要参数被更改以适应新数据时,就会发生这种情况,从而损害网络处理旧数据的能力。理想情况下,网络可以通过在很少使用的参数中编码新信息,或者通过改变重要参数以推广到其他任务而不是完全切换到其他任务,来保持其在先前任务中的能力。使用标准的基于梯度的学习方法,这通常是不可能的。已经提出了许多对抗灾难性遗忘的方法,但这里讨论的算法不止于此:它完全消除了灾难性遗忘,同时仍然允许有效的一般迁移学习。

渐进神经网络

渐进神经网络(prognets)是 Deepmind 在他们的论文 渐进神经网络 (鲁苏等人,2016)中开发的一种神经算法。程序网是一种简单、强大和创造性的迁移学习的解决方案——引用论文摘要,它们“不会遗忘,并且可以通过与先前学习的特征的横向连接来利用先前的知识”。

程序网开始存在时只有一个单列的神经网络,它将在一个初始任务上被训练。每列由 L 个块组成,每个块包括一层神经元 W ,一组用于每个父列的侧神经元 U ,以及一个激活函数 f 。由于初始列没有传入的横向连接,它将与标准神经网络的行为相同。这第一列学习任务 1,然后它的参数被冻结。对于任务 2,将生成一个新列,并添加横向连接。这些横向连接将所有先前列中的先前块的输出作为输入。然后将侧层添加到主层上,最后进行活化。

k 的块 I 的方程。

第一列(k = 0)。

下面是一个 prognet 的插图,在 progressive neural nets 论文中发现了 K = 3 个任务和 L = 3 个块。请注意,任何给定的块都是其自身参数、其自身列中的前一个块的输出以及所有先前列中的前一个块的输出的函数。

渐进式神经网络

理解程序网的另一种方式是把每个程序块看作一个计算的黑盒,它需要决定哪些信息源对完成它的任务最有效。例如,在上图中, output₃ 可以访问先前的隐藏层 h₂ 。但是,它还可以访问每个父列的 h₂ 层,并可以使用其横向参数在本地微调它们的输出。如果 output₃ 模块发现 h₂ 拥有它需要的所有信息,它可以“清零”其他输入。如果它发现 h₂h₂ 各自提供了所需的部分信息,它可以忽略 h₂ ,充当 h₂h₂ 的函数。通过建立这些横向连接,我们允许网络轻松地在任务之间传递信息,同时也允许它忽略不重要的信息。

作者在一组强化学习环境中测试了他们的算法,包括 pong 变体、迷宫变体和 Atari 游戏。他们对各种基线模型进行了测试,发现程序网优于每种基线。在发表之后,其他几篇论文已经展示了跨不同领域的程序网的成功使用;例如, 渐进式神经网络用于情感识别中的迁移学习 (Gideon et al .,2017)发现,在给定一组积木式任务的情况下,渐进式神经网络可用于情感检测。类似地, 用渐进网络 (鲁苏等人,2018)从像素学习的模拟到真实机器人表明,渐进神经网络可以用于在不完美的机器人模拟和真实硬件之间进行转换。

用机械手将 Sim 传送到机器人。

虽然上述渐进式神经网络出版物在各种强化学习任务上测试其算法时产生了令人信服的结果,但程序网并不是迁移学习的灵丹妙药。主要是它们是参数浪费的:每个侧化的块需要一个完整的侧层用于它从中提取的每个父列。目前形式的程序网也仅限于对每个记录都有相应任务标签的数据起作用。为了允许冻结,每个任务必须按顺序学习,而顺序会极大地影响最终网络的质量。这通常只是一个较小的限制,但仍然是一个限制。此外,由于冻结,如果任务改变,程序就不灵活。因此,这意味着色谱柱应该在冻结前非常熟练地完成任务。

总之,渐进式神经网络不受灾难遗忘的影响,因为它们冻结了每个完成的列,但它们也允许通过与新列的横向连接进行有效的迁移学习。他们牺牲了增加的模型复杂性(即,在每个额外的列中训练更多的参数)和改变任务的灵活性来实现这一点。许多先前的出版物和实验支持这种算法作为有效的迁移学习平台的可信度。

多利安

Doric 是我开发的工具,用于实现和扩展渐进式神经网络。这是一个建立在 PyTorch 之上的免费开源库。在本文的剩余部分,我们将遍历 Doric 背后的代码,用它运行一个简单的实验来分析正在训练的 prognet,最后,在一组困难的图像处理任务上测试 Doric。

注意:这里显示的 Doric 版本是简化的。完整版带示例代码这里。

首先,我们的库需要块的定义。每个块必须包含一个激活函数,一个充当块的主层的模块,以及一个实现 U 参数的横向层列表。Doric 使用下面的抽象类。

通过扩展这个类和实现未实现的方法,用户可以很容易地为任何可以想象的用途创建他们自己的程序块。再补充几个简单的。

现在我们有了简单密集层、批量标准化密集层和 2D 卷积层的模块。注意,在我们的对象中,任何包含 PyTorch 模块的列表都被实现为 nn.ModuleLists,这是因为它允许 PyTorch 正确地注册这些子模块。另外值得注意的是,因为 ProgBlocks 是 nn 的一个子类。模块,它们可以像任何其他 PyTorch 模块一样运行。但是,我们没有在它们上面实现 forward 方法,所以我们仍然需要调用 runActivation 和 runBlock。

tensor([
[0.0000, 0.0000, 1.8789, 0.0000, 0.0000],
[0.0138, 0.0000, 2.9942, 0.0000, 0.0000],
[1.5449, 0.0000, 2.8891, 0.0000, 0.0000]], 
grad_fn=<ReluBackward0>)

现在我们有了一个 block 对象,我们需要将它们组织成列网络。每次指定新任务时,都需要添加这些列网。然而,由于我们有一个很好的可扩展的块结构,我们不需要依赖用户来实现单独的列——至少不直接。

最后,我们需要整个渐进式神经网络。该对象将包含一个列网列表,并将运行每个必要的列,以产生给定任务的结果。

有几件重要的事情需要注意。首先,在 addColumn 中,Doric 允许用户直接传递列网,或者用户可以通过扩展 ProgColumnGenerator 类来创建列生成器。

这允许用户在 generateColumn 方法中定义每个列的体系结构,这样 prognet 就可以添加列,而无需传递列。msg 参数还允许用户通过 addColumn 方法传递信息来生成 Column。

第二件特别重要的事是向前的方法。这实际上是渐进神经网络算法的核心。prognet 按顺序运行每一列,直到到达与给定任务相关联的列。这允许后面的列访问每个分支的输入。

就其本身而言,这足以为任何简单的顺序体系结构创建渐进式网络,但当我们需要更复杂的体系结构时,它就会崩溃。举个例子,这张 Q 函数评论家网络图是我在另一个项目中作为 DDPG 代理的一部分而写的:

为这样的网络设计渐进式系统的最简单方法是允许使用多通道模块。这些砌块还必须允许某些非横向通道上的直通通道。

除此之外,我们还需要解决 Doric 的一个特性:惰性和 lambda 块。惰性块是可以被侧化的块——不在初始列中,也不在第一行中——但是故意不被侧化。这些允许我们在我们的网络中包括特殊的操作,或者减少那些没有从迁移学习中受益的块中不必要的参数。

要实现这两个更改,我们只需要定义它们,并对我们的列网络类做一些小的更改。

仅此而已。截至本文发表时,这是 Doric 的(简化的)核心功能。使用这些工具,我们可以将大多数神经网络架构实现为一个 prognet。

简单的例子

对于第一个 Doric 示例,我们将创建一个双任务 prognet。具体来说,我们将教会我们的列模拟 xor 和 nand 函数。回想一下,xor 和 nand 的真值表如下。

在这个简单的实验中,我们的第一篇专栏文章将解决 xor 任务,第二篇将利用第一篇文章解决 nand 问题。要明确的是,这不是一套需要迁移学习的任务。具有这种结构的单柱网络可以毫不费力地解决任一任务。这个实验的价值在于,它将允许我们深入分析这些网络,并观察横向连接如何传递知识。这是我们将在实验中使用的代码。

运行该程序后,我们会收到这些结果。

Testing Xor.
Input: [0, 0].  Target: 0\.  Predicted: 0\.  Error: 0.
Input: [0, 1].  Target: 1\.  Predicted: 1\.  Error: 0.
Input: [1, 0].  Target: 1\.  Predicted: 1\.  Error: 0.
Input: [1, 1].  Target: 0\.  Predicted: 0\.  Error: 0.Testing Nand.
Input: [0, 0].  Target: 1\.  Predicted: 1\.  Error: 0.
Input: [0, 1].  Target: 1\.  Predicted: 1\.  Error: 0.
Input: [1, 0].  Target: 1\.  Predicted: 1\.  Error: 0.
Input: [1, 1].  Target: 0\.  Predicted: 0\.  Error: 0. Xor and Nand params:
columns.0.blocks.0.module.weight
Parameter containing:
tensor([[-3.2474,  3.2474],
        [-2.0008,  2.0429],
        [-0.5795,  0.0801]])
columns.0.blocks.0.module.bias
Parameter containing:
tensor([-1.7442e-05,  2.0007e+00, -3.0051e-01])
columns.0.blocks.1.module.weight
Parameter containing:
tensor([[ 4.5644, -3.4079,  0.1078]])
columns.0.blocks.1.module.bias
Parameter containing:
tensor([3.0512])
columns.1.blocks.0.module.weight
Parameter containing:
tensor([[-0.2739, -0.1766],
        [ 0.5853,  2.8434],
        [-0.6689,  0.3338]], requires_grad=True)
columns.1.blocks.0.module.bias
Parameter containing:
tensor([-0.3227, -0.5853, -0.3339], requires_grad=True)
columns.1.blocks.1.module.weight
Parameter containing:
tensor([[-0.1367, -2.9894, -0.4210]], requires_grad=True)
columns.1.blocks.1.module.bias
Parameter containing:
tensor([1.9972], requires_grad=True)
columns.1.blocks.1.laterals.0.weight
Parameter containing:
tensor([[1.9479, 0.2868, 0.1236]], requires_grad=True)
columns.1.blocks.1.laterals.0.bias
Parameter containing:
tensor([1.8058], requires_grad=True)

这些日志显示网络学习了 xor 和 nand 功能,但是如果我们想知道它是如何完成的,我们需要更仔细地观察。让我们从 xor 列开始。在一个图形结构上绘制出所有的参数后,我们可以构建下图。

注意事项:

  • 最右边的神经元将总是输出 0。这意味着学习这个函数是不必要的。
  • 如果 X1 和 X2 相同,它们将抵消,并且偏移参数将确定隐藏层的输出。结果是 sigmoid(-3.6),或~0.02。
  • 如果 X1 是 1,X2 是 0,隐藏层输出[0,0,0]。结果是 sigmoid(3.2),或~0.96。
  • 如果 X1 是 0,X2 是 1,隐藏层输出[3.2,4,0]。结果是~0.98。

所有这些都是值得了解的,但也不足为奇。让我们看看当我们添加 nand 列时会发生什么。

现在,我们列举所有的输入组合。

X = [0,0]

X = [0,1]

X = [1,0]

X = [1,1]

需要注意的事项:

  • 这一次,两个隐藏层神经元被置零。这是因为 nand 比 xor 容易得多(nand 是线性可分的)。
  • 隐藏层中仍然活跃的神经元将输出 0、2.8 或 2.2。
  • 当主动隐藏神经元输出 2.2 时,外侧层出现尖峰,以补偿非外侧输入的-4.6 值。
  • 如果横向层被归零,给定[0,1]输入,答案将是不正确的。
  • 当给定输入为[0,0]或[1,1]时,分支输出相同的值。对于这些输出,分支并不重要。

复杂示例

自动编码器&阀门

自动编码器是一种功能强大的架构,可以应用于许多任务并产生良好的结果(尤其是图像处理任务)。它们也是演示渐进式网络的理想选择。这有两个原因:

  1. 编码器部分的任务之间可能有很多共享信息。
  2. 自动编码器通常是非常深的网络,这一特性允许我们展示一个具有大量分支的网络。

可变自动编码器(VAEs)是自动编码器的一种变体,其中网络学习数据的平均值和标准偏差的抽象,而不是数据本身。这给了解码器部分强大的生成能力!这篇文章很长,没有深入解释自动编码器和 VAEs,所以我推荐阅读 Irhum Shafket 撰写的这篇关于数据科学的文章。

实验设计

对于这个实验,我们将使用 Doric 构建一个渐进变分自动编码器。该网络将能够在图像处理领域执行四种不同的任务。下面列出了这些操作。

  1. 简单重构—将输入重构为输出,通过瓶颈层保留重要信息。
  2. 去噪-从输入中移除椒盐噪声。
  3. 着色-向输入的灰度版本添加颜色。
  4. 修复—在图像中被随机游走的黑色像素遮挡的部分进行绘画。

我们将使用名人数据集进行实验,这是一个大规模的名人脸部图像集。这个数据集适合我们实验的参数,因为它的大小,难度,以及容易注意到人脸的不一致。

运行这个实验的完整代码可以在示例目录中的 Doric 存储库中找到。

我们的图像处理 VAE 柱的结构。

结果

下面是进步 VAE 的三个实验柱的结果。所有格式都是原始/输入/输出。列 0(简单重建)未显示,因为它不包含分支。

第 1 列(去噪)

第 2 列(着色)

第 3 列(修复)

分析

为了开始我们对结果的分析,我认为首先解决 autoencoder 的奇怪之处是很重要的——虽然有些图像翻译得很好,但有些却不是。然而,当 VAE 失败时,它很少通过创建错位或不现实的人脸来实现。相反,它过度概括,创造了一个新的人类面孔,更类似于以前见过的面孔。这些种类的错误,以及其他奇怪的错误,都不是由 prognet 引起的,在独立的 VAE 中也会发生。

在这张图片中,网络做了很好的重建工作,甚至匹配了大部分被随机行走覆盖的头发梯度。

另一方面,这个人完全被取代了。也有很多照片中的脸没有被替换,但是眼镜被拿掉了。

背景极有可能变得模糊,因为 VAE 知道背景并不重要。

也就是说,我们可以开始分析与 prognet 相关的结果。从降噪专栏开始,我们看到了我们对任何正常的 VAE 降噪师的期望。网络在去除噪声和保持图像质量方面做得很好(模糊是可以预料的,因为瓶颈只有 128)。值得注意的是训练时间;如果您运行代码,您可能会发现,作为一个 prognet,网络学习去噪要比作为一个独立的网络快得多。

在彩色栏中,我们可以看到结果又一次和我们预期的一样。更值得注意的任务是由第三列执行的修复。在之前专栏知识的帮助下,我们能够得到惊人的结果。即使图像的一小部分通过掩模被损坏的像素曝光,网络也可以重建图像,几乎与简单的重建一样好。

由于只能看到她嘴的一小部分,VAE 能够重现她口红的颜色。

即使重要的面部特征被遮挡,VAE 也能够利用现有的信息重建出合理的相似度。

生成高质量的结果图像对 prognet 来说是一个好兆头,但要了解横向参数的影响,我们需要找到一些方法来测试它们如何影响结果。一种方法是在移除横向参数的情况下运行正向通道。如果结果仍然是可识别的,分支没有做太多。如果结果是明亮的但不可识别的,则分支与主网络参数一起工作来创建结果。如果结果是暗的或完全黑的,则该列仅使用或主要使用分支进行计算。这是那次向前传球的结果。

无侧边去噪。

无侧边着色。

无侧边修补。

这些结果表明,在列 1 和列 2 中,大部分计算是由分支完成的。在最后一栏中,几乎所有的工作都是由分支完成的。这是迁移学习正在发生的一个强有力的标志。

结论

渐进神经网络是迁移学习和连续学习的有力工具。虽然它们受到浪费内存使用、需要标记和明确定义的任务以及无法适应先前学习的任务变化的限制,但它们完全不受灾难性遗忘的影响,并且它们为持续学习神经系统的宽度方向增长提供了新的模板。在 progressive neural net 论文中进行的实验,以及其他论文和本文中提出的实验,显示了强有力的证据,表明 prognets 是迁移学习的可行工具。

同样,Doric 是一个用于程序开发和实验的有用的轻量级库。借助用户创建的模块以及多通道模块和惰性模块,几乎任何标准架构都可以作为渐进式网络实施。

感谢

感谢 Case Wright 在开发 Doric 和编写我们所有的 autoencoder 测试中的帮助,感谢 David Stucker 的帮助编辑,感谢 Gustavo Rodriguez-Rivera 博士的指导和学术支持,感谢 Purdue 大学。

链接&引用

  • 渐进式神经网络论文—
  • **全多利安库—https://github.com/arcosin/Doric
  • **CelebA 数据集—http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html
  • **自动编码器和 VAEs 解释—https://towards data science . com/直观-理解-变分-自动编码器-1bfe67eb5daf
  • **用于情感识别中迁移学习的渐进式神经网络—https://arxiv.org/pdf/1706.03256.pdf
  • **虚拟现实机器人用渐进网络从像素学习—https://arxiv.org/pdf/1610.04286.pdf
  • **棋图制作人—http://SVG _ experimenten . DEDS . nl/棋盘/Chess _ diagram _ maker . html

除非另有说明,所有图片和其他版权材料均由作者创作。

数据科学家基于项目的学习

原文:https://towardsdatascience.com/project-based-learning-for-data-scientists-df6a8f74e4a1?source=collection_archive---------9-----------------------

成为一名数据科学家变得简单多了

要成为一名数据科学家,需要学习很多东西。一个真正优秀的数据科学家候选人不仅要具备良好的技术技能,还要能够批判性地思考和解决业务相关问题,以指导业务决策。

从本质上说,培养如何解决不同业务问题的敏锐感觉,会让你在面试过程中从潜在雇员中脱颖而出。

那么,如何才能培养你的数据直觉?在本文中,我将与您分享我最喜欢的培养关键批判性思维技能的策略之一,通过基于项目的学习,让您走上发展数据直觉的道路。

什么是基于项目的学习?

基于项目的学习(PBL)是通过实际工作和应用来发展你的技能。在数据科学的背景下,这意味着使用您已经掌握或正在掌握的各种技能对许多不同种类的数据进行数据分析。本质上,要发展你的数据感觉和直觉,你需要练习使用它们。

但是怎么做?

随着您处理越来越多的数据分析,或项目,您将会接触到越来越多来自不同领域的数据,这些数据将会有独特的业务相关问题需要您去寻找和解决。

你能够完成的项目越多,你接触不同种类的数据、业务问题和发展数据感觉的机会就越多。

不仅如此,这里还有一些基于项目的学习的额外好处:

  • 练习编写复杂的代码来解决与特定行业数据相关的特定问题
  • 当不同的错误出现时,发展你解决问题的技巧(也就是成为一个更好的谷歌人)
  • 练习/学习你从未接触过的技能
  • 增强对自己作为数据科学家能力的信心
  • 你可以把个人项目放在简历上展示给雇主看

听起来很棒,对吧?让我告诉你如何开始。

建立你的第一个数据科学项目

  1. 选择您的数据集

这里有一个免费的数据集存储库列表,你可以仔细阅读并下载你喜欢的数据集。我会选择你真正感兴趣的主题的数据集,而不是你认为雇主想看到的。

  • 卡格尔
  • 来自 GitHub 的令人惊叹的公共数据集
  • 改头换面星期一
  • 谷歌的测试数据集搜索引擎
  • Reddit
  • UCI 机器学习知识库
  • 美国政府
  • 数据是复数
  • 我在这里汇总了上面的库和更多的库。

不确定选哪个?新手的话从 Kaggle 开始。您将可以访问其他用户的笔记本,这样您就可以获得灵感开始工作。

2。你想解决什么问题?

选择数据后,您需要将其加载到 Python 中,并执行探索性数据分析(EDA)来了解您的数据。如果你以前从未做过 EDA,或者需要复习,请随意参考这本方便的书。

完成 EDA 后,问问自己“如果一家公司带着这些数据来找我,他们可能想了解更多什么?我可以找到哪些关键信息来帮助公司改进?”

例如,如果你有亚马逊这样的在线零售公司的时间序列数据,寻找季节性趋势可能是个好主意。也许你的数据有很多连续变量。创建一个相关矩阵来开始研究数据中不同变量之间可能存在的不同关系可能是明智的。

3。你有足够的数据吗?

根据您在分析中提出的问题,您可能需要找到更多的数据添加到您的分析中,以获得更多的见解。您可能还需要获得额外的数据集来扩展原始数据的时间范围。

例如,Airbnb 的公共数据集只能以 1 个月为增量。这并不坏,是一个开始的地方,但是如果你有几年的数据,你可能能够创建一个更彻底的分析。

4。开始你的项目

组织你的项目来回答你在步骤 2 中提出的各种问题,并从你所拥有的数据中提取尽可能多的有意义的信息。

这就是奇迹发生的地方。您现在处于真实的实践场景中,需要解决数据和重要的行业相关问题。你可以访问万维网,获得大量的资源来帮助你,你得到了这个。

这是你学习新技能和加深对他人理解的绝佳机会。当你遇到错误和其他问题时,Google 和文档将成为你最大的资产。您还可以访问网络上许多数据科学家论坛,如 Stackoverflow 和数据科学堆栈交流。

随着您创建和完成越来越多的项目,作为一名真正的数据科学家,您将获得越来越多的真实世界实践。这将缓慢但肯定地让你的数据感觉成长为数据杀手的本能。

5。写下你的发现,并与观众分享

在我看来,一份关于你的项目的好的期末报告是展示你的沟通和写作技巧的好方法。通过你的分析,你发现了哪些真知灼见?你会建议客户/经理做哪些事情?

对于你放在简历上的任何项目来说,最后的总结都是必须的。这让招聘经理有机会快速审视你的技能和思维方式,看看你是否适合这个团队。你肯定会想包括不同的视觉效果和你使用的统计模型,并仔细解释你的业务问题是什么,以及你的工作如何解决这些问题。

但是,唉,这将是另一天的话题:)

你的第一个项目和第十个项目会是什么感觉:)

基于项目的学习是培养你的数据意识以及技术和沟通技能的最有效的方法。有些技能你只能在工作中学习,而基于项目的学习将让你掌握这些关键的数据意识。

非常感谢您花时间阅读我的文章,如果您有任何问题,请随时联系我。下次见!

我叫 Kishen Sharma,是一名数据科学家,在旧金山湾区工作。我的使命是教授和激励全世界有抱负的数据科学家。

请随时在 Instagram 上与我联系,并在这里查看我的附加内容。你也可以在这里查看我的其他文章。

数据科学中的项目管理

原文:https://towardsdatascience.com/project-management-in-data-science-11d059bcb265?source=collection_archive---------10-----------------------

来自前项目经理的建议,告诉你如何在事情出错时也能让自己保持在正轨上

在 Unsplash 上插入佩佩·西尔维娅来自《费城永远阳光灿烂》的 meme 照片由阿尔瓦罗·雷耶斯拍摄

当讨论转向数据科学家应该具备的辅助技能时,项目管理有时会被当作一种不错的软技能。但是关于如何将项目管理技术具体应用于数据科学的资源很少,并且建议通常是油嘴滑舌的。每当这个问题出现时,“只要看看现有的项目管理资源”就是标准答案。

作为公司范围内数百万美元项目的项目经理,我可以从经验中告诉你,项目管理不仅仅是制定一个计划和在清单上打勾。任何实际参与过数据科学项目的人都知道,由于不可预见的情况,您的计划经常被搁置。事情花费的时间比预期的长,出现了意想不到的问题。事实上,丹尼尔·卡纳曼和阿莫斯·特沃斯基为这种低估完成任务所需时间的倾向创造了术语“计划谬误”。

项目管理实际上是关于解决交付中人的易犯错误。这就是为什么我想根据有效的项目管理技术给出坦率的建议——而不是列出昂贵的软件工具,也不是概述 CRISP-DM 流程的每一步要花多长时间。

为什么要使用项目管理工具?

有大量的项目经理工具用于监控和报告项目进展。虽然这些工具的存在似乎只是为了创造忙碌的工作,并证明项目经理的薪水是合理的,但事实并非如此!您不仅可以使用这些工具来让高级管理层了解信息,还可以帮助您和您的利益相关者记录假设和项目依赖关系。

敏捷宣言说我们应该总是优先考虑人和交互,而不是过程和工具。同样,对于一个数据科学项目,你应该优先回答业务问题,而不是无关紧要的华而不实的东西。虽然你可以说项目管理工具是附带的,但你会惊讶于这些工具是如何帮助你以一种结构化的方式处理和思考问题的。

正如敏捷宣言所坚持的,这些工具的使用和形式化应该与项目规模成比例。因此,举例来说,如果你只是在为你的投资组合做一个周末数据科学项目,你不需要创建一个花哨的甘特图。但是创建一个 RAID 日志(风险、假设、问题和依赖性)可能是值得的,以便在您进行建模时将您的假设放在心上。即使在项目结束后,几个月或几年后继续提醒你你的假设也是一个很好的资源。所以当你继续读下去的时候,请记住你可以并且应该根据你的需求扩展这些工具。

数据科学项目管理工具的类型

你的项目管理工具包里有什么工具?…由托德·夸肯布什在 Unsplash 上拍摄的照片

  1. 结构化思考问题:RAID 日志 — RAID 代表 R isks、 A 假设、 I 问题、 D 依赖。RAID 日志不是我们倾向于想到的用于项目管理的第一类工具,但是我认为它们是最重要的。不管项目大小如何,我都建议保留一个 RAID 日志。每当你着手解决一个问题时,当你制定方法时,总会有一些假设。当你制定收集数据的计划时,可能会有风险阻碍你的计划。当你列出你需要做的事情的步骤时,依赖关系可以帮助你计划处理项目的顺序。将这些记录在一个地方是消息灵通和看起来对你的项目一无所知的区别。
  2. 确定你需要做什么:WBS — WBS 代表WworkB分解 S 结构。它本质上是一个花哨的术语,指需要完成的所有任务的列表。虽然数据科学流程框架(如 CRISP-DM、KDD 和 OSEMN)总结了数据科学项目中的步骤,但将这些框架应用于您的问题非常重要。例如,在 OSEMN 框架中(Ob ain, S crub, E xplore, M odel,I N terpret),你期望做什么样的数据擦洗?你打算使用什么样的模式——如果第一种模式不起作用,你随后会尝试什么样的模式?如果你和团队一起工作,WBS 甚至可以帮你分配任务。
  3. 计划每个任务或阶段的顺序和持续时间:甘特图 —结合 RAID 日志中的依赖关系和 WBS 中的任务,甘特图有助于计划任务的时间和顺序。它可以相当详细——在 WBS 上绘制出每个单独的任务——或者它可以是高层次的,以便只绘制高层次的流程。在这种情况下,它通常被称为“路线图”,是与高级管理层沟通的最佳方式之一。

RAID 日志

RAID 日志的创建是反映业务问题、评估您的数据科学问题是否能解决业务问题的一种方式,并让您与利益相关方保持联系以解决问题。

假设日志示例。在 techno-pm.com 找到更多的例子和模板

思考业务问题

从记录项目的风险、假设和依赖性开始。我强烈建议在收到利益相关者的业务问题后,尝试将它转化为数据科学问题,并思考如何回答它。这自然会引出问题和假设,您可以记录下来,然后与业务部门一起审查。

假设

假设通常是那些隐藏的、没有说出来的东西,让我们认为一个项目会比它实际上要简单。可以从多个方面进行假设,包括:

  1. 数据:作为数据科学家,我们最容易出错的地方——尤其是考虑到数据清理经常被认为是数据科学家 80%的工作。您可能会对数据做出一些假设,包括我们希望数据如何格式化,我们可以使用哪些功能,数据的范围有多广,某个功能作为某种事物的代理的适用性,等等。
  2. 模型:所有的模型都有自己的假设。例如,K-均值聚类假设聚类内的方差本质上是球形的,并且聚类的大小是相同的。我们的模型可以强加给我们的另一个假设是没有空值,这可能需要我们在 WBS 中包括一个插补步骤。这些假设和任何违反假设的情况都必须记录下来,以确保我们完全理解使用任何模型的利弊(并在 WBS 中包括满足假设的任何必要步骤)。
  3. 工作流或数据管道:虽然我们倾向于不去想在部署我们的模型后事情会发生变化,但是如果将来发生变化,记录关于工作流的假设是很重要的。例如,我们可能假设地理位置仅作为一个分类城市/州可用,但我们的数据管道可能会在未来改变以获取纬度/经度数据,并导致我们在生产中调整我们的模型。

属国

依赖性可以是数据科学项目自然遵循的顺序,例如在尝试任何建模之前完成数据清理。依赖关系还可以说明一些团队欠其他团队什么,例如数据工程师向数据分析师或机器学习团队提供的干净数据文件。这可以让你跟踪项目可能被延迟的原因,而不是把它归咎于最后一个接触项目的团队。

风险

风险可能难以识别,并且经常与其他 RAID 日志项目混淆。假设和依赖有助于揭示风险所在。风险通常是实际问题的前兆(事实上,如果意识到风险,它可以被关闭,新的问题应该在它的位置打开)。

问题

记录问题是一个只有在项目开始后才能完成的步骤。那么,为什么要这么做呢?项目管理不仅仅是项目规划,还包括持续的监控和文档记录。这看起来像是在浪费时间,但是就像任何好的实践一样(咳咳评论代码),它在未来会有回报。了解在过去的项目中遇到了什么问题——特别是对于一个数据基础设施不经常改变的公司——可能是低估潜在工作和准确估计项目时间表和收益的区别!

利益相关方联系人

最佳实践是让您的利益相关者定期签署 RAID 日志。或者,如果这看起来太官僚主义,只要检查任何新的项目或变化就可以让每个人都了解情况并负责任。您的 IT 和业务利益相关者可以轻松地确认假设或风险,他们的意见将有助于您保持正确的方向。

工作分解结构(WBS)

带有预计任务持续时间的工作分解结构示例。在pmwares.com了解更多关于使用 Microsoft Project 创建 WBS 的信息

WBS 将项目从主要的可交付成果分解成越来越小的组成部分,直到你达到单个任务级别。列出你的个人任务有很多好处:

头脑风暴一下你需要做什么

在我们对实际解决问题的过度热情中,我们可能低估了我们的任务,没有为我们的项目分配足够的时间。或者,更糟糕的是,我们可以跳过简单但必要的步骤(检查和输入丢失的值!标准化数字特征!一次性编码分类变量!)而没有意识到我们的模型结果表明了基本的特征转换问题。通过强迫自己将高级数据科学项目阶段分解成任务,你开发了一个标准的、可重复的方法。

最棒的是,你可以在未来的项目中重用 WBS 的一部分。还有一个问题可以通过集群解决吗?只需从上一个集群项目中抽出 WBS,它已经列出了必要的步骤和检查!

估计每一步需要多长时间

WBS 是计算一个项目需要多长时间的好方法。因为你已经列出了每一个单独的任务,添加一个时间估计是很简单的。与高层次估计时间表不同(例如,数据清理需要 2 天),如果发现某项任务没有必要,或者违反了模型的假设,表明它不太适合您的数据,您可以立即确定节省的时间。

由于我们很难估计事情需要多长时间,所以最好用历史作为例子。如果您记录了过去项目中每项任务实际花费的时间,就可以更好地预测未来项目的时间长度。

确定依赖关系

虽然一些任务之间的依赖关系很明显(在通过特定的机器学习模型运行您的要素之前对空值进行插补),但还有其他一些更微妙的依赖关系。特别是当我们考虑到数据科学过程可以在特征工程和建模步骤中迭代时,仔细考虑任务之间的依赖关系可以帮助您有效地规划模型管道。

例如,您可能希望对刚刚标准化的要素运行线性回归模型,然后您可能会回过头来查看各种变换如何影响模型结果。因此,虽然标准化可能是线性回归两次迭代的依赖项,但对数转换可能只在第二次迭代中需要。记录任务之间的顺序和依赖关系可以帮助您创建一个可重用和干净的管道。

线条图

甘特图是一种将 WBS 可视化的方式。通常情况下,任务是垂直列出的,时间是水平跨越的,一个水平条显示每个任务跨越多长时间。任务也可以分组到工作流中,特别是当项目很大并且跨越整个组织中的许多功能组时。

更高层次的甘特图,也可以称为“路线图”图片来源:如何在 Powerpoint 中制作甘特图

确定粒度级别

这是一个项目管理工具,如果你正在做一个单独的项目,你可以跳过它。但是如果你在一个组织中,我认为高层次的“路线图”是有用的。我认为更多的人是视觉学习者,而不是我们所认为的那样。或者至少,事情变得有意义更快当我们看到它们的时候。这就是为什么手头上有一个项目进展的路线图这样的视觉图像——特别是在一个长期项目中——可以帮助减轻高级管理层的恐惧,并让他们继续投资。

一个需要大型组织中不同团队参与的项目很容易在较低的任务级别上创建甘特图。但通常在这种情况下,会有一个专门的项目经理来监控和管理项目。

结论

虽然在您的下一个数据科学项目中使用这些工具可能无法防止意外延迟,但持续使用这些工具可以让您更好地感知风险,帮助您更好地估计任务的持续时间,并迫使您与利益相关者保持更密切的联系。我建议在您的下一个项目中实施这些工具的简单版本,看看您如何处理和规划您的数据科学项目,以及如何改进!

在我的下一篇博客文章中,我将带你看看我的个人项目中没有按计划进行的例子。

TL;博士

在项目正式开始之前和项目进行过程中,使用 RAID 日志来确定假设、依赖性、风险和问题。根据项目的复杂程度和规模,在 WBS 中列出所有必要的任务,包括预期的开始和结束日期、任务之间的相关性以及任务负责人。甘特图采用工作分解结构,并用图表显示每项任务或工作流预计需要多长时间。高级甘特图也被称为项目路线图,可用于让高级管理层了解进展情况。虽然你可以使用花哨的软件来应用这些工具,但好的 Excel 或 Google Sheets 可以做到这一点。

[1]:规划谬误,https://en.wikipedia.org/w/index.php?title=Planning_fallacy&oldid = 914560670(2019 年 11 月 18 日最后一次访问)。

每个数据科学家都应该知道的项目管理工作流

原文:https://towardsdatascience.com/project-management-workflows-every-data-scientist-should-know-89bbf0d625e4?source=collection_archive---------52-----------------------

Jo Szczepanska 在 Unsplash 上拍摄的照片

管理数据科学项目的主要流程以及为什么您应该了解它们

介绍

我们中的许多人开始自学数据科学,参加 Kaggle 比赛和在线阅读教程。即使我们最终在编码和算法方面学到了很多,但在开始时,我们对处理数据所需要的其他东西了解不多,比如项目管理。

即使你不是经理,了解公司采用的不同方法也很重要,因为你可能会发现自己被迫在这些框架中的一个框架内工作。在这篇文章中,我将为您介绍主要的几种。

瀑布

尽管瀑布是最传统的项目管理方法之一,但由于它的线性方法,通常不适合数据科学。

来源:微软

它的名字来源于它生成的甘特图,类似瀑布并说明了它的线性。

它通常从定义最终产品要求和详细步骤开始,以线性时间表组织,其中任务通常取决于前面的任务,并附属于负责执行任务的人。所以,当你开始一个项目时,你希望确切地知道它什么时候结束,最终产品是什么。

将这种方法应用于数据科学项目的问题是,它假设项目需求在未来不会改变,这可能是一些其他类型项目的情况,但通常不会在数据中发生,在数据中,随着我们在执行中的进步,我们会积累知识,初始需求可能会发生很大变化。

混乱

根据 Scrum 的说法,“Scrum 本身是一个简单的框架,用于复杂产品的有效团队协作”。

资料来源:Scrum.org

它是一个敏捷框架,广泛用于软件开发,有时也用于数据项目,尤其是当数据团队以某种方式被插入开发团队时。

团队从一个产品待办事项清单开始,这是要做的事情的列表,根据它们的重要性排序。从这个列表中,构建了一个新的列表:T2 sprint planning T3,其中包含了将在下一个 sprint 中处理的高优先级项目。顺便说一下,一个冲刺,是团队专注于冲刺计划中列出的任务的一小段时间。因此,每隔 2-4 周,团队会聚在一起设定下一次会议之前要完成的目标,在下一次会议期间,还会有一个 sprint 回顾,参与者会回顾上一次 sprint 的目标,看看已经实现了什么,还没有实现什么,以及为什么。

它倾向于面向产品的项目,这并不总是数据项目的最佳选择,因为数据科学有时由长时间的探索性分析组成,这不一定会转化为产品特性或需求。另一方面,Scrum 可能会将这些分析推向一个更加面向结果的道路,减少有时浪费在智力分歧上的时间。

CRISP-DM

数据挖掘的跨行业标准流程,也称为 CRISP-DM,自 1996 年以来一直存在,是数据挖掘流程中使用最广泛的模型之一。它不像瀑布模型那样是线性的,瀑布模型为每一步之间的迭代增加了很多灵活性。

肯尼斯·詹森

它始于业务理解步骤,在这里你开始系统地阐述你想要回答的问题,第一假设,等等。一旦你有了这些,你就开始寻找你需要的数据,进入数据理解阶段,在那里你检查你有什么样的可用数据,寻找异常值、缺失值等等。下一阶段是数据准备,您将决定如何处理那些缺失值和异常值,如何导入和清理您的数据,等等。一旦完成,你将开始建模,尝试不同的算法,然后评估它们以及它们的表现,通常与基线进行比较。最后一步是部署选定的模型,将其投入生产。

请注意,虽然这些步骤是以线性顺序呈现的,但在此过程中,您通常会在它们之间移动很多次。例如,在建模阶段,您可能需要更改准备数据和处理要素的方式,具体取决于您使用的模型。一旦你评估了你的模型,有时结果可能不令人满意,促使你去理解为什么,也许回到第一步,重新思考你理解业务问题的方式。

IBM 人工智能工作流

IBM 对于 AI 项目的工作流程基本上是受设计思维的启发,所以每一步都与一个设计思维流程步骤相关。它也是基于迭代的思想,每一步都可以导致下一步,但也可以让你回到以前的步骤,这取决于你的结果。

来源:交互设计基金会

数据收集 ( 移情),是数据科学家与最接近数据的人交谈,以阐明商业机会,并将其转化为可测试的假设。它包括定义时间表、成本、可行性等。最后,您继续为项目收集数据。

探索性数据分析 ( 定义)是您尝试可视化您的数据、检查缺失值(并决定如何处理它们)以及潜在测试假设的地方。

然后您移动到转换 ( ideate )步骤,这里的目标是转换您的数据,以便它可以被模型使用。这是所有特性工程魔法发生的地方。

建模 ( 原型)是下一步,在这里您定义一个评估标准,并针对您的问题比较不同的模型。从简单的模型开始,然后逐步建立。

最后一步是测试,这里的目标不仅仅是对你的代码进行单元测试,还包括批评你之前所做的选择,如果需要的话再回去(通常是这样)。它以所选解决方案的部署而告终,这也要经过测试:即使是运行的模型也要经过审查和持续的性能测试。

顺便说一下,IBM 在 Coursera 上有一个专门研究这种方法的项目,我强烈推荐这个项目。

结论

每种方法都有自己的优点和缺点,正确的方法取决于你的公司、你的团队以及项目的规模和范围。瀑布式工作流最适合范围已经明确的项目,比如改进已经实现的模式,而当项目涉及更多的数据工程而不是数据科学时,Scrum 会工作得更好,并且最终的可交付物本身就是一个产品。CRISP-DM 和 IBM AI 工作流在需要不断迭代和彻底探索性分析的项目中工作得更好。

更新

要进行回顾和更深入的分析,可以查看海王星博客的文章2021 年的数据科学项目管理。他们概述了这里没有提到的一些其他方法,这些方法也可以作为您处理数据科学项目的参考。

项目:用回归机器学习算法预测红酒成分的完美比例

原文:https://towardsdatascience.com/project-maximizing-red-wine-profits-with-regression-machine-learning-algorithms-8caad2a10a08?source=collection_archive---------52-----------------------

来源

目录

1。简介:场景&目标,特性&预测器

2。数据争论:缺失值,用 Z 值检测/处理异常值

3。探索性数据分析:相关性、配对图、特征工程、核密度估计(KDE)、回归联合图、条形图、小提琴&盒图

4。机器学习+预测分析:为建模准备数据,建模/训练,R 值,预测,k 重交叉验证‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍

5。结论

1。简介

场景:

你走进 T21 北部的一家酒吧。你点了伏特加,并对坐在你旁边的人说你是一名数据科学家。酒吧的老板,碰巧是一个葡萄酒商,让你知道他正在雇佣一名数据科学家。他说他正在失去顾客 &需要帮助为他的红酒系列想出一个新配方。葡萄酒商把这些数据交给你,让你进行数据分析预测配料的完美比例最大化他的利润

目标:

  • 预测红酒配料的完美比例。这是一个数值连续的结果
  • 用各种回归模型&探索,看哪个产生最大精度
  • 检查我们数据中的趋势 & 相关性
  • 确定哪些特性品质红酒品质重要

:由于我们是预测一个数值连续值,我们将训练各种回归模型。回归分析监督学习的子领域。

特征和预测:

我们的预测器 (Y,葡萄酒质量)由 11 个特征 (X)决定:

1.固定酸度(g/L)——大多数与葡萄酒有关的酸或固定的或不挥发的(不容易挥发)
2。挥发性酸度(g/L)——乙酸的含量(含量过高会导致不愉快的醋味)
3。柠檬酸(摩尔/升)——少量存在的柠檬酸可以增加葡萄酒的“新鲜度”和风味
4。残糖(克/升)——发酵停止后剩余的糖量
5。氯化物(克)—盐量
6。游离二氧化硫(mg/L)——游离形式 SO 存在于分子 SO(溶解气体)和亚硫酸氢根离子
7 之间的平衡。总二氧化硫( mg/L ) —游离态和结合态 SO 的量
8。密度(克/厘米 ) —水的密度接近于水的密度,取决于酒精和糖的百分比含量
9。pH——描述葡萄酒的酸性或碱性程度,范围从 0(非常酸性)到 14(非常碱性);大多数葡萄酒在 3–4
10 之间。硫酸盐(g)——可增加二氧化硫气体(SO)水平的添加剂,作为抗菌剂
11。酒精——酒精含量百分比

:我们的数据只有一种数据:****(#);这是可以测量的定量数据

**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**import** **matplotlib** **as** **plt**
**import** **seaborn** **as** **sns**
**import** **matplotlib.pyplot** **as** **plt**

2.数据争论

**filePath = '/Users/jarar_zaidi/Downloads/wineQuality.csv'

data = pd.read_csv(filePath)

data.head()**

帮助我们了解我们正在处理的数据。

**print("(Rows, columns): " + str(data.shape))
data.columns**

显示行数和列数。以及列名

**data.nunique(axis=0)** *# returns the number of unique values for each variable.*

返回每个变量的唯一值的数量。

*#summarizes the count, mean, standard deviation, min, and max for numeric variables.*
**data.describe()**

汇总数字变量的计数、平均值、标准差、最小值和最大值。

平均质量为 5.6,其最大 ( 最佳质量得分)为 8.0 &其最小 ( 最差质量得分)为 3.0。现在,让我们看看是否有任何缺失值需要处理。

缺少值

*# Display the Missing Values*

**print(data.isna().sum())**

显示每列缺失值的数量。幸运的是我们没有。

使用 Z 分数检测/处理异常值

一个 Z 值是对位置的测量,它表示一个数据值偏离平均值标准偏差的数量。任何 z 分数小于 -3大于 3 ,都是异常值****

:从经验法则我们看到我们数据的 99.7% 应该在均值的 3 个标准差以内。

**from scipy import stats
import numpy as np
z = np.abs(stats.zscore(data))
print(z)**

获取 Z 分数

接下来,我们想要获取 Z 值大于 3 的行和列。这些被认为是异常值。

**threshold = 3
print(np.where(z > 3))**

第一个数组号&的列表第二个数组异常值对应的号。例如,第一个异常值在第 13 行第 9 列。一旦我们计算出Z 值 Z 值,我们就可以移除离群值清理我们的数据,方法是执行下面的操作。

**Newdata = data[(z < 3).all(axis=1)]
Newdata**

我们现在已经成功地 移除了 148+ 行,这些行是异常值

注意:其他异常值指标也可以使用,如 IQR 得分散点图箱线图

让我们看看我们的新清理的数据。

**Newdata.describe()**

3.探索性数据分析

相关

相关矩阵又名热图 -让你看到所有变量之间的相关性

内,你可以看到某件事是还是 与我们的预测器(目标)相关。****

*# calculate correlation matrix*

**corr = Newdata.corr()
plt.subplots(figsize=(15,10))
sns.heatmap(corr, xticklabels=corr.columns, yticklabels=corr.columns, annot=True, cmap=sns.diverging_palette(220, 20, as_cmap=True))
sns.heatmap(corr, xticklabels=corr.columns,
            yticklabels=corr.columns, 
            annot=True,
            cmap=sns.diverging_palette(220, 20, as_cmap=True))**

我们可以看到在酒精我们的预测因子之间有一个 相关。事实上,这是我们数据集中最相关的特征,其值为 0.5

注意:我们的酒精特征是饮料中的酒精含量百分比。对于购买红酒的顾客来说,酒精含量的百分比越高就会产生越大的满意度

接下来,我们可以看到第二** 最强的正相关0.39硫酸盐 &我们的质量预测值。似乎当饮料中添加了添加剂时,人们对质量的评价会更高。硫酸盐 充当抗菌剂。**

最后,负相关性最强的挥发酸度,相关性为 -0.35 !这是意料之中的,因为过高的醋酸含量会导致令人不愉快的 T42 醋味道!

配对图

****成对图也是一种很好的方式,可以让立即看到所有变量之间的相关性

因为我们有 11 特征,所以让我们只选择关联到我们的预测显著特征,以进一步检查它们在配对图上的相关性

**subData = data[['volatile acidity','citric acid','sulphates','alcohol']]
sns.pairplot(subData)**

该图支持热图中所述的相关性

:选择制作一个较小的配对图,其中只有最强的预测值,以便深入关系中。这也是一个很好的方法来看看他们的关系是还是 相关

特征工程

我们现在将进行特征工程的一种形式,其中我们创建一个新的 根据其质量分数进行分类!****

这个新列将是一个二进制分类数据,其中 01 表示该葡萄酒是否被认为是“美味的”。

**Newdata['tasty'] = [0 if x < 6 else 1 for x in Newdata['quality']]**

我们现在有一个新列带有011s。

核密度估计(KDE)

一个核密度估计(KDE)** 估计一个连续随机变量的**概率密度函数(PDF)****

**g = sns.jointplot("quality", "volatile acidity", data=Newdata,
           kind="kde", space=0, color="red")**

一个内核密度估计允许我们可视化数据在连续区间上的分布。从这个图中,我们可以得出结论:质量较低的红酒是严重倾向于挥发酸度水平较高的。这正如我们所料因为,大量醋酸产生难闻的醋味!****

回归联合图

**g = sns.jointplot(x= 'fixed acidity',y= 'pH', data=Newdata,
             kind = 'reg',height=15,color='blue')

plt.xlabel('Fixed acidity',size=30)
plt.ylabel('pH',size=40)
plt.title('Fixed acidity vs. pH',size=30)**

从上面解释的回归联合图中,我们可以看到 pH 水平&固定酸度之间存在强负相关。换句话说,当其中一个增加时,另一个减少。根据热图,这两个特性有一个相关性系数 -0.71

条形图

**sns.catplot(x="quality", y="volatile acidity", hue="tasty", kind="bar", data=Newdata);

plt.title('Tasty & Non-Tasty Wine with Volatile Acidity Level',size=19)
plt.xlabel('Wine Quality',size=16)
plt.ylabel('Volatile Acidity Level',size=16)**

这幅图说明了高挥发性酸度水平产生一款糟糕的品酒。这正如我们所料,因为大** 醋酸产生一种难闻的醋味!**

小提琴和盒子图

显示框&小提琴图的优点在于它显示了基本数据的统计,以及其 分布 。这些图通常用于比较给定变量在某些类别中的分布。

显示的是中位IQR 、&图基的栅栏。(最小值、第一个四分位数(Q1)、中值、第三个四分位数(Q3)和最大值)。此外,它可以为我们提供数据中的异常值。

**plt.figure(figsize=(12,8))
sns.boxplot(x="quality", y="sulphates", hue="tasty", data=Newdata )
plt.title("Tasty & Non-Tasty Wine with Sulphate Level", fontsize=20)
plt.xlabel("Wine Quality Level",fontsize=16)
plt.ylabel("Sulphate Level", fontsize=16)**

接下来,我们检查这个方框图,这有助于进一步得出结论,即好喝的红酒显示出硫酸盐水平的中位数升高。****

如果我们回想一下我们的化学课,我们记得硫酸盐是一种添加剂,可以增加二氧化硫气体(SO)的水平,这是一种抗菌剂!

:一种抗菌剂是一种杀死微生物 & 阻止其生长 h 的药剂。****

我们现在明白了为什么这些高硫酸盐含量会增强顾客的偏好!

**plt.figure(figsize=(12,8))
sns.violinplot(x="quality", y="alcohol", hue="tasty", inner='quartile',data= Newdata )
plt.title("Tasty & Non-Tasty Wine with Percent alcohol content",fontsize=20)
plt.xlabel("Wine Quality Level", fontsize=16)
plt.ylabel("Percent alcohol content ", fontsize=16)**

分析完这个小提琴剧情我们可以得出好酒&不好酒的整体形态& 分布差异巨大好喝的红酒显示出一个剩余中值为百分比酒精含量&因此他们的数据的一个大分布在 10 & 13 之间,而不好喝的红酒由一个低中值酒精含量在 9.5 & 11 之间。

L et 的比较好喝&不好喝红酒之间的平均值****

**yummy = Newdata[Newdata['tasty']==1]
yummy.describe()**

**notYummy = Newdata[Newdata['tasty']==0]
notYummy.describe()**

**print("(Tasty Wine Sulphates level): " + str(yummy['sulphates'].mean()))
print("(Non-Tasty Wine Sulphates level): " + str(notYummy['sulphates'].mean()))**

更美味的葡萄酒表现出更高的硫酸盐水平

**print("(Tasty Wine Alcohol content level): " + str(yummy['alcohol'].mean()))
print("(Non-Tasty Wine Alcohol content level): " + str(notYummy['alcohol'].mean()))**

更好喝的葡萄酒表现出更高的酒精含量水平

**print("(Tasty Wine Total Sulfur Dioxide level): " + str(yummy['total sulfur dioxide'].mean()))
print("(Non-Tasty Wine Total Sulfur Dioxide level): " + str(notYummy['total sulfur dioxide'].mean()))**

更好喝的葡萄酒展示了更低的二氧化硫水平

L 很快,好喝&与不好喝之间的平均值相差极大****。例如,美味的红葡萄酒包含总量二氧化硫最小化水平。此外,美味的红葡萄酒含有的硫酸&酒精水平要高出很多。********

如果我告诉葡萄酒商每种成分的完美比例能让最大化他的红酒销量,我会告诉他包括低水平的二氧化硫和高水平的 T11 硫酸盐酒精 T15。************

4.机器学习+预测分析

为建模准备数据

为建模准备数据,只需记住 ASN ( 赋值、拆分、规格化)。

AT22 将 11 个特征赋值给 X,&最后一列给我们的预测值,y

**X = df.iloc[:, :-1].values
y = df.iloc[:, -1].values**

SSplit:数据集分为训练集和测试集

**from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X,y,test_size = 0.2, random_state = 1)**

N 标准化:标准化数据将转换数据,使其分布的平均值为 0,标准差为 1。

**from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
x_train = sc.fit_transform(x_train)
x_test = sc.transform(x_test)**

建模/培训

现在,我们将在训练集&上训练各种回归模型,看看哪个产生最高的精确度。我们将比较的准确性 多元线性回归 多项式线性回归 SVR(支持向量回归) 决策树回归 随机森林这些都是监督学习模型,用于预测连续值。**

:对于回归模型,有几个度量用于测量精度,如均方根误差(RMSE)残差标准差(RSE)平均绝对误差(MAE) 。但是我们将用 R . 来测量我们的模型

模型 1:多元线性回归

*# Train model on whole dataset*
**from** **sklearn.linear_model** **import** **LinearRegression
regressor = LinearRegression()
regressor.fit(x_train,y_train)**

*#Predicting Test Set Results*
**y_pred = regressor.predict(x_test)** 
*# Evaluating Model Performance*
**from** **sklearn.metrics** **import** **r2_score
r2_score(y_test,y_pred)**

准确率 75%

模型 2:多项式线性回归

**from sklearn.model_selection import train_test_split x_train2, x_test2, y_train2, y_test2 = train_test_split(X2,y2,test_size = 0.2, random_state = 1)****from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression poly_reg = PolynomialFeatures(degree = 4) x_poly = poly_reg.fit_transform(x_train2) lin_reg_2 = LinearRegression() lin_reg_2.fit(x_poly,y)****y_pred2 = lin_reg_2.predict(poly_reg.transform(x_test2))****from sklearn.metrics import r2_score r2_score(y_test2,y_pred2)**

准确率 80%

模型 3: SVR(支持向量回归)

*#assign*
**X3 = df.iloc[:, :-1].values
y3 = df.iloc[:, -1].values**

*#split*
**from** **sklearn.model_selection** **import** **train_test_split
x_train3, x_test3, y_train3, y_test3 = train_test_split(X3,y3,test_size = 0.2, random_state = 1)**

**from** **sklearn.svm** **import SVR
regressor3 = SVR(kernel='rbf')
regressor3.fit(x_train3,y_train3)** *# replace by x_train , y_train if we split*

**regressor3.predict(x_test3)

from sklearn.metrics import r2_score
r2_score(y_test3,y_pred3)**

准确率 74%

模型 4:决策树回归

*# Assign*
**X4 = df.iloc[:, :-1].values
y4 = df.iloc[:, -1].values**

*# Split*
**from** **sklearn.model_selection** **import** **train_test_split
x_train4, x_test4, y_train4, y_test4 = train_test_split(X4,y4,test_size = 0.2, random_state = 4)**

**from** **sklearn.tree** **import** **DecisionTreeRegressor
regressor4 = DecisionTreeRegressor(random_state = 0)
regressor4.fit(x_train4,y_train4)** *# replace by x_train , y_train if we split*

**y_pred4 = regressor4.predict(x_test4)** 
**from** **sklearn.metrics** **import** **r2_score
r2_score(y_test4,y_pred4)**

准确率 74%

模型 5:随机森林回归🏆

*# Assign*
**X5 = df.iloc[:, :-1].values
y5 = df.iloc[:, -1].values**

*# Split*
**from** **sklearn.model_selection** **import** **train_test_split
x_train5, x_test5, y_train5, y_test5 = train_test_split(X5,y5,test_size = 0.2, random_state = 6)** 

**from** **sklearn.ensemble** **import RandomForestRegressor
regressor5 = RandomForestRegressor(n_estimators = 10, random_state=0)
regressor5.fit(x_train5,y_train5)** *# replace by x_train , y_train if we split*

**y_pred5= regressor5.predict(x_test5)**

**from** **sklearn.metrics** **import r2_score
r2_score(y_test5,y_pred5)**

准确率 83%!🏆

83%,的一个 R 揭示了数据83% 符合回归模型

型号 6: XGboost

**from** **xgboost** **import** XGBClassifier

**model7 = XGBClassifier(random_state=1)
model7.fit(x_train, y_train)
y_pred7 = model7.predict(x_test)
from sklearn.metrics import r2_score
r2_score(y_test5,y_pred7)**

准确率 82%

解释 R 值

R (又名拟合优度决定系数)是统计测量数据与拟合回归线的接近程度。R ,比。最佳 R 值为 1.0

通过比较 6 个回归模型,我们可以得出结论:模型 5:随机森林回归产生的精度最高,其精度的 83%🏆

注意:一个好的经验法则是任何高于 70%的精度都被认为是好的,但要小心,因为如果你的精度极高,它可能好得不真实(过度拟合的一个例子)。因此,83%是理想的精确度!

预言

S cenario :让我们预测一家公司酿造的一款红酒的质量是根据其每种成分比例。我们现在将输入每种成分比例到我们的机器学习算法中。

红酒的成分由…

7.9 g/L固定酸度

0.59 克/升挥发酸度

柠檬酸的 0.004 摩尔/升,

发酵停止后残糖1.9g/L

0.062 克氯化物盐

49.0 毫克/升游离二氧化硫

33.0 毫克/升总二氧化硫

密度为 0.9915 克/厘米的水,

pH3.21 (酸性),

0.53 克硫酸盐

8.9 %酒精含量

根据这些信息,你能预测这款红酒质量分数吗?

**print(regressor5.predict(([[7.9,0.59,0.004,1.9,0.062,49.0,33.0,0.99513,3.21,0.53,8.9,1]])))**

产量红酒质量分数6.5

P.S 。如果你看不出来,我以前是 生物专业 ,转行之前是 数据科学

k 倍交叉验证

K 倍交叉验证是一种统计方法,确保我们对我们的模型性能有更好的测量。我们在数据的不同子集上运行我们的建模过程,以获得模型质量的多个度量。我们我们的数据除以特定的数量的

K 重交叉验证允许原始数据集中的每个观察值出现在我们的训练&测试集中。

当我们创建 20 个不同的测试折叠时,我们降低了获得幸运 风险最终 精度我们得到的将是平均值20 倍测试

**from sklearn.model_selection import cross_val_score
accuracies = cross_val_score(estimator = regressor5, X = x_train5, y = y_train5, cv = 20)**
**print("Accuracy: {:.2f} %".format(accuracies.mean()*100))** *# float w 2 decimals after comma*
**print("Accuracy: {:.2f} %".format(accuracies.std()*100))** *# float w 2 decimals after comma*
*# the 20 accruaceis lie within  % , we have a high std.* 
*#(Mean - Std, Mean + Std)*

20 个准确度位于(80.44–4.48,80.44+4.48)% = (75.96,84.92)%置信区间内。我们有一个高标准差,这意味着我们的数字展开的。

结论

  1. 在我们研究的 11 个特征中,帮助葡萄酒商酿造美味红酒的前 3 个重要特征是低水平的二氧化硫和高水平的硫酸盐&酒精。
  2. 我们的随机森林算法产生了最高的 R 值,83%!任何超过 70%的 R 都被认为是好的,但是要小心,因为如果你的精确度非常高,它可能好得不真实(过度拟合的一个例子)。因此,83%是理想的精确度!
  3. 我们的机器学习算法现在可以根据成分比例预测红酒的质量。通过检测这些重要的特征,我们可以防止我们的葡萄酒商倒闭或损失任何利润!生产一种没有人会喜欢的葡萄酒成本很高,会给我们公司带来收入损失。这是非常强大的,因为现在我们可以正确地看到人们更喜欢葡萄酒的哪些成分&,从而最大化我们的利润!

这里是从我的 GitHub 页面对数据集 & 代码访问:

[## jzaidi 143/Project-用回归机器学习预测红酒成分的完美比例…

预测红酒成分的最佳比例。这是一个数字离散结果。探索各种…

github.com](https://github.com/jzaidi143/Project-Predicting-the-Perfect-Ratio-of-Red-Wine-Ingredients-with-Regression-Machine-Learning-Algor)

https://archive.ics.uci.edu/ml/datasets/wine+quality

欢迎推荐和评论!

承认

页(page 的缩写)科尔特斯、塞德伊拉、阿尔梅达、马托斯和雷伊斯。
通过物理化学特性的数据挖掘建立葡萄酒偏好模型。在决策支持系统中,爱思唯尔,47(4):547–553,2009。

项目潘德雷肯+唐克斯:农业命运大订单的多任务特征提取

原文:https://towardsdatascience.com/project-pendragon-tonks-multi-task-feature-extraction-for-farming-fate-grand-order-af077b7aafd2?source=collection_archive---------60-----------------------

不写数据科学博客时,我在一家名为 ShopRunner 的电子商务公司担任高级数据科学家。在过去的一年里,我们的团队一直在构建大型多任务深度学习集成,以使用图像和文本来预测我们产品目录中产品的相关时尚属性和特征。最近,我们的团队开源了我们内部构建的主要培训管道和框架,以在一个名为 Tonks 的包中培训我们的多任务学习者。Tonks 可以安装在 pypi 上,源代码可以在 GitHub 这里获得。

在我们讨论开源 Tonks 的过程中,我意识到一个潜在的早期用例可能是升级我的一个辅助项目,我正在构建一系列强化学习(RL)代理来玩手机游戏《命运大订单(FGO)》,我给它起了个绰号叫“潘德雷肯项目”。

潘德雷肯项目有两个主要部分,特征提取管道,它将输入发送到 RL 代理,这些代理做出决策并将命令发送回游戏。虽然我扮演 FGO 的 RL 代理已经反复升级,但我的特征提取管道基本上还在一年前的位置。

这篇文章将介绍我如何替换我的原始特征提取管道,该管道使用三个大型卷积神经网络(两个 ResNet 50 和一个 ResNet 34),并用一个用多个数据集训练的 Tonks 多任务 ResNet 50 替换这三个模型。

早期版本的多个 RL 代理通过多任务网络从 FGO 手机游戏中提取信息来玩 FGO 内容。

唐克斯

我们的 ShopRunner 团队构建了基于 PyTorch 的 Tonks 库,帮助我们使用图像和文本构建大型多任务网络集合。在大多数用例中,我们关心的是能够根据提供的图像、描述、标题和其他信息返回产品的相关属性。

当你培养多任务学习者时,你通常是抱着这样的心态来解决问题的,即在一个任务中学到的特性可能对另一个任务有益。对于电子商务领域的我们来说,像这样的两个任务可能是服装长度和袖子长度,其中两个单一的任务模型可能会学习寻找线条和长度,而不担心颜色、图案和背景。当任务满足这些标准时,这意味着我们可以将任务组合成多任务网络,在 tanks 中,我们通过拥有一个核心模型(如图像的 ResNet 或文本的 Bert 模型)来实现这一点,并将这些核心模型的输出连接到我们各自的任务头

当你的任务都在同一个领域时,多任务学习是有用的,因为它让你建立和维护一个单一的模型,而不是使用多个单一任务的学习者。在我目前的管道中,我训练和使用 3 个大型 CNN,在那里我为以前的每个任务建立了定制的数据集。Tonks 旨在处理您使用定制数据集进行个别任务训练的情况,因此它可以帮助我减少需要维护的模型数量,并让我使用以前使用的数据集进行训练。

在构建多任务模型时要考虑的一点是,当任务不在相似的域内时,多任务模型可能会遭受破坏性干扰、,其中来自不同任务的冲突信号将模型拉向不同的方向。关于如何处理这种破坏性干扰的讨论可能是一个很好的后续帖子或讲座,但超出了本文的范围。对于我的 FGO 用例,我的直觉是这个问题是相当可行的,因为所有的任务都使用了 FGO 截图、类似的文本、调色板等等。所以我可能不会有破坏性干扰的问题。

更多关于唐克斯的细节请看我们的发布会帖子。

首先,CNN 检测到攻击按钮,Python 向它发送了一个点击。在下一个屏幕上,另一个 CNN 检测到 5 种命令卡类型,RL 机器人根据该输入做出决定。

潘德雷肯项目

2018 年秋天,我开始制作一些基本的机器人来玩 FGO,但在我进入机器人的细节之前,我会快速概述一下 FGO 到底是什么。命运大令是一个回合制手机游戏,你可以选择 3 到 6 个不同属性和能力的角色。然后你用这支队伍去对抗一波又一波的敌人,直到所有的敌人或队伍被击败。

我建造这些机器人的主要动机是,作为 FGO 常规活动的一部分,玩家经常被要求数十次(如果不是数百次的话)重复游戏关卡。在最近的一次活动中,我在一周的时间里进行了 100 次农业操作,每一关花费 3-5 分钟(总共 5-8 小时)。因此,考虑到这一点,我认为建立一个机器人能够为我做这个重复性的任务将是一个伟大的附带项目!这个曾经简单的“副业”已经变成了一个有趣的分分合合长达一年的兔子洞,增加了许多有趣的东西,如多个强化学习代理和各种定制游戏环境。

尽管对围绕机器人的代码库以及如何做出决定进行了许多升级,但我真的没有接触过我的特征提取管道来为我的 RL 游戏机器人获取信息。

特征提取器一:现在轮到谁了?

FGO 是一个回合制游戏,为了让机器人玩这个游戏,我需要能够检测到什么时候该轮到他们了。我决定检测机器人何时开始行动的方法是在挑选指挥卡之前寻找出现在主战斗屏幕上的“攻击”按钮。

下面是一个主战斗界面的例子,攻击按钮在右下角突出显示。

右下角的攻击按钮,高亮显示。

我把这个网络分成两类,“攻击”和“不攻击”,基本上就是说这个网络被训练来检测攻击按钮是否出现在游戏屏幕的那个部分。如果是,那么这意味着轮到机器人了,你可以做一些有用的事情,比如在当前屏幕上采取行动/使用技能,或者继续前进,调出命令卡屏幕,在那里你可以选择 5 张卡中的哪一张来玩。

挑选指挥卡是 FGO 的主要战斗技巧。因此,一旦我能够检测到该轮到谁了,就该构建一个分类器来帮助我识别那一轮发了什么命令卡。我的第一批机器人使用这些信息进行算法上的游戏,而后来的机器人通过强化学习来训练选择要玩的牌,但作为特征提取过程的关键部分,它们都需要能够识别哪些牌已经被处理。

特征提取二:发了什么命令牌?

FGO 的主要战斗机械师在你的回合中挑选“指挥卡”。有三种类型的牌:“艺术”、“克星”和“快速”,每种类型的牌做的事情略有不同。每回合发 5 张牌,玩家必须从其中选择 3 张来玩该回合。下面是展示的 5 张卡片和挑选的 3 张卡片的样本。

样本命令卡和正在挑选的卡。特征提取模型预测 5 张卡中每一张的类型。这些预测随后被发送到一个“拣卡者”模型,该模型决定玩哪一个 3。

虽然我可以构建一个检测器来在幕后找到卡的位置,但我找到了一个更简单的解决方案。这些屏幕相对一致,卡片放在同一个位置,所以我选择做的是硬编码五个命令卡的位置,并从命令卡屏幕的截图中裁剪出来(见下面的示例)。然后,我将五张卡中的每一张都通过一个经过 PyTorch 训练的 CNN 来确定卡的“类型”。

彩色部分是发出的 5 张命令牌。

然后,可以将这些牌类型分类提供给各种 RL 代理,并用于决定在给定的回合中使用哪些牌。很长一段时间,这两个网络(攻击按钮和卡类型检测器)是我的第一个 FGO 强化机器人的核心特征提取器,昵称为潘德雷肯·阿尔特。他们让我做了一个机器人,可以在 FGO 进行主要的战斗,也可以以自动化的方式玩完整个游戏。从这一点开始,我真的只需要考虑玩游戏还需要哪些信息,以及如何从游戏中提取这些信息。

特征提取器三:我们在敌人的哪一波?

我添加到我的框架中的最后一个网络实际上是一个波计数器,我用它作为我的几个不同版本的机器人的输入。我添加这个的原因是 FGO 等级几乎总是有 1 到 3 个回合的敌人,你必须通过战斗,一个代理人可能想采取的行动可能取决于回合。例如,第一波敌人可能相对较弱,但第三波可能相当强,所以为第三波保留技能通常是一个好策略。

我在下面截图的顶部用红色突出显示了圆形柜台。

回合计数器显示当前回合和总回合数

虽然我可以使用某种光学字符识别来获得数字,但我真正关心的是告诉它是第 1 轮、第 2 轮还是第 3 轮,所以我训练 CNN 将三个类别映射到这些数字,每次检测到攻击按钮时,我都会检查当前是哪个回合数。

这三个网络实现了我需要的基本特征提取,但需要同时运行三个大型 CNN 会增加相当多的 GPU 或 CPU 计算开销和额外的存储(2 个 Resnet 50s 约为 220MB,1 个 Resnet 34 约为 84Mb)。

唐克斯培训管道

我们的 Tonks 管道遵循 Fastai 建立的通用框架,其中管道被组织成数据加载器、模型和学习器。我们最终使用各种帮助记账的字典来管理多个任务和多个数据集。

以下部分将显示出现在下面链接的培训笔记本中的代码片段,并讨论其中发生的事情。

我培训用的笔记本放在这里

Tonks 数据集和数据加载器

我们的自定义 Tonks 数据集(第 26 行)FGOImageDataset 遵循相当标准的 PyTorch 数据集布局,其中我们需要提供一种方法来索引适当的值,作为数据生成器的一部分(第 58-59 行),应用变换(第 61 行),并返回图像数据和标签(第 65 行)。

第 11–24 行的应用取决于我们是否在查看验证集的训练。我喜欢以这种格式保存转换,但这只是个人偏好。

fgo_tonks 笔记本的 14 号单元格

一旦我们创建了自定义的 Tonks 数据集类,我们就可以开始为我们的三个任务创建训练和验证数据集。流程的这一部分也非常类似于标准的 PyTorch 培训管道,您必须将培训和验证分割放入数据集,然后最终放入数据加载器。这里唯一的区别是我们有三个数据集,而不是普通的一个。

第 1–26 行显示了我们如何为这三个任务中的每一个准备训练和验证分割。第 28–37 行显示了我们如何创建一个数据加载器字典,我们将在接下来的步骤中使用它来创建 Tonks 的多任务多数据集数据加载器。

在上面这段代码中,我们使用我之前展示的自定义数据集类为每个类创建训练和验证数据集。这包括指定 x 和 y 输入(图像及其标签的文件路径)以及我们想要应用的转换。在这个管道中,我只是在训练集中使用了 ImageNet 标准化的随机裁剪,在验证集中只使用了标准化。一旦创建了数据集,我们就创建了一个基本 PyTorch 数据加载器的字典,其中键是任务的名称,值是与这些任务相关联的数据加载器。这里的想法是,我们可以跟踪我们应该为哪个数据集生成批次,作为我们多数据集训练管道的一部分。

下面的代码片段显示了我们如何将 PyTorch 数据加载器的两个字典放入两个 Tonks MultiDatasetLoaders 中。这些 Tonks 数据加载器是我们用来集成我们的多任务多数据集培训管道的。

Tonks 多数据集加载器

Tonks 网络架构示例

管道的下一个主要部分是模型。虽然我们提供了一些示例图像和文本模型架构,但是根据您的需求定制这些架构可能是有意义的。对我来说,我只是做了一个简单的基于 ResNet50 的架构,并将其连接到各个任务层。在 Tonks 中,我们用两个 PyTorch 模块指令来处理这一部分,称为pretrained_classifiersnew_classifiers。我们在这里的想法是,第一次训练网络时,我们将任务发送到new_classifiers字典,当我们保存训练好的网络时,这些任务将被移动到pretrained_classifier字典进行保存。然后在随后的运行中,我们可以将预先训练的任务头加载到pretrained_classifier字典中。这有助于我们跟踪在哪里应用学习率(因为您可能希望根据任务头之前是否进行过微调来获得不同的学习率)

加载 Tonks 模型

当我们加载一个 Tonks 模型的实例时,主要的输入在task_dictionary中。有两个潜在的选项:第一个是new_task_dict,这是您第一次训练模型时应该使用的选项,而第二个是pretrained_task_dict,这是您可以将任务放置在已经存在 Tonks 预训练权重的位置。对于我们在 ShopRunner 的人来说,这很有用,因为我们现在可以轻松地向现有模型添加新任务。

对于这个 FGO 的例子,我有三个全新的任务。我将把一个包含任务名称和每个任务中类别数量的字典放入一个名为new_task_dict的字典中,并在初始化模型类时将其输入到模型类中。这告诉 Tonks 模型创建三个任务头,每个任务头有一定数量的节点。

培养

一旦我们初始化了模型,在开始训练之前,我们需要做的就是为各种任务定义一个损失函数,指定一个优化器,分配学习率,创建我们的学习器,并调用 fit 函数。

对于这个管道,每个任务都是一个多类问题,所以我们使用交叉熵损失。当我们指定学习率时,我们可以为模型的不同部分指定不同的学习率。对于主要的 ResNet 部分,我们指定一个低的1e-4学习率,但是对于新的部分,我们指定一个更积极的1e-2学习率。这背后的主要思想是,我们并不真的想大幅改变 ResNet50 核心模型中的 ImageNet 权重,但由于新的分类器层是随机初始化的,所以我们可以更积极地调整它们。然后我们定义了一个调度器来降低每两个时期的学习率。

一旦完成,我们可以使用 Tonks MultiTaskLearner类定义我们的学习者。该类包含我们训练模型所需的所有功能,并接受我们之前加载的模型架构、训练和验证 Tonks 数据加载器以及任务字典,后者包含我们所有任务的映射,用于从我们的数据加载器中检索批处理。

最后,我们可以在我们的学习器上调用fit()。关于不同论点的细节,你可以查看我们的阅读文件。

结果

一旦我完成了三任务 Tonks 网络的训练,我就必须用新的多任务网络替换我的项目潘德雷肯回购中的三个网络。由于 Tonks 是建立在 PyTorch 之上的,为了使用一个模型,您需要跟踪的只是模型架构和权重文件,因此您不一定需要安装 Tonks 及其所有依赖项来在新项目中使用经过训练的模型。

Tonks 模型在所有任务中表现强劲,到目前为止,我在 FGO pendragon 游戏界面的部署中没有遇到任何问题。在我继续改进我的 RL 代理人时,我一直在用 Tonks 模型进行我最近的其他开发。最近的部分是让代理使用协调的策略。

代理协调清除困难的内容。代理和机器人的特征提取基于这里训练的多任务 tonks 模型。

因此,虽然这个基于手机游戏的例子很可爱,但是在这里使用 Tonks 这样的框架的原因与我们研究工业规模问题的原因是一样的。它消除了我维护多个单一任务学习者网络的需要,并且我能够快速轻松地进行训练,因为我能够使用我之前构建的三个现有数据集。

Tonks 是一个库,我们的 ShopRunner 数据科学团队一直在使用它来构建工业规模的多任务深度学习集成,使用经过多个数据集训练的图像和文本。对我们来说,这使得我们的团队创建多任务模型来满足新的和变化的需求变得相对简单。由于培养多任务学习者是一个非常现实的需求,但目前还没有得到支持,我们开源了我们的工作,以帮助回馈数据科学社区。

项目:用分类机器学习算法预测心脏病

原文:https://towardsdatascience.com/project-predicting-heart-disease-with-classification-machine-learning-algorithms-fd69e6fdc9d6?source=collection_archive---------5-----------------------

你刚刚被聘为数据科学家

来源

目录

1。简介:场景&目标,特性&预测器

2。数据角力

3。探索性数据分析:相关性,小提琴&箱线图,按阳性&阴性心脏病患者筛选数据

4。机器学习+预测分析:为建模准备数据,建模/训练,混淆矩阵,特征重要性,predictions‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

5。结论

1.介绍

场景:

你刚刚被一家医院聘为数据科学家,这家医院有数量惊人的患者报告各种心脏症状。心脏病专家测量生命体征&将数据交给进行数据分析预测某些患者是否患有心脏病。我们想做一个机器学习算法,在那里我们可以训练我们的 AI 学习&从经验中改进。因此,我们想将患者分为心脏病阳性或阴性。

目标:

  • 预测病人是否应该被诊断为心脏病。这是一个二元结果。
    (+)= 1,患者诊断为心脏病
    阴性 (-) = 0,患者未诊断为心脏病
  • 用各种分类模型** &做实验,看看哪一个产生最大的精确度。**
  • 检查我们数据中的趋势** & 相关性**
  • 确定哪些特征对阳性/阴性心脏病诊断最重要****

特征和预测:

我们的预测因子** (Y,心脏病的阳性或阴性诊断)是由 13 个特征 (X)决定的:**

1.年龄** (#)
2。性别 : 1=男,0=女(二进制 )
3。( cp )胸痛类型(4 值- 序数):值 1:典型心绞痛,值 2:不典型心绞痛,值 3:非心绞痛性疼痛,值 4:无症状
4。( trestbps )静息血压(#)
5。( chol )血清胆固醇以毫克/分升计(#)
6。( fbs )空腹血糖> 120 mg/dl( 二进制 )(1 =真;
0 =假)7。( restecg )静息心电图结果(值 0,1,2)
8。( thalach )达到的最大心率(#)
9。( exang )运动诱发心绞痛(二元 ) (1 =是;
0 =否)10。( oldpeak ) =运动相对于休息诱发的 ST 段压低(#)
11。最大运动 ST 段的(斜率)(序数)(值 1:上坡,值 2:平,值 3:下坡)
12。( ca )透视着色的主要血管数(0–3,序数)13。( thal )达到的最大心率— ( 序数 ): 3 =正常;6 =修复缺陷;7 =可逆缺陷**

注:我们的数据有 3 种类型的数据:

****(#):可以测量的定量数据

****顺序数据:有顺序的分类数据(0,1,2,3 等)

****二进制数据:其单元只能呈现两种可能状态的数据(0 & 1)

2.数据争论

**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**import** **matplotlib** **as** **plt**
**import** **seaborn** **as** **sns**
**import** **matplotlib.pyplot** **as** **plt**filePath = '/Users/jarar_zaidi/Downloads/datasets-33180-43520-heart.csv'

data = pd.read_csv(filePath)

data.head(5)

帮助我们了解我们正在处理的数据。

**print("(Rows, columns): " + str(data.shape))
data.columns**

显示行数和列数。以及列名

**data.nunique(axis=0)***# returns the number of unique values for each variable.*

返回每个变量的唯一值的数量。

*#summarizes the count, mean, standard deviation, min, and max for numeric variables.*
**data.describe()**

汇总数字变量的计数、平均值、标准差、最小值和最大值。

*# Display the Missing Values*

**print(data.isna().sum())**

显示每列缺失值的数量。幸运的是我们没有。

让我们看看在我们的正&负二元预测器之间是否有一个好的比例。****

**data['target'].value_counts()**

看起来我们在两个二进制输出之间有一个很好的平衡。

3.探索性数据分析

相关

相关矩阵 -让我们看看所有变量之间的相关性

几秒钟之内,你就能看出某样东西与我们的预测器(目标)是正相关还是负相关。

*# calculate correlation matrix*

**corr = data.corr()
plt.subplots(figsize=(15,10))
sns.heatmap(corr, xticklabels=corr.columns, yticklabels=corr.columns, annot=True, cmap=sns.diverging_palette(220, 20, as_cmap=True))
sns.heatmap(corr, xticklabels=corr.columns,
            yticklabels=corr.columns, 
            annot=True,
            cmap=sns.diverging_palette(220, 20, as_cmap=True))**

我们可以看到胸痛(cp) &目标值(我们的预测值)之间存在正相关。这是有道理的,因为胸痛越严重,患心脏病的几率就越大。Cp(胸痛),是具有 4 个值的顺序特征:值 1:典型心绞痛,值 2:不典型心绞痛,值 3:非心绞痛性疼痛,值 4:无症状。

此外,我们发现运动诱发的心绞痛(exang) &与我们的预测因子呈负相关。这是有道理的,因为当你运动时,你的心脏需要更多的血液,但狭窄的动脉会减缓血液流动

Pairplots 也是一种很好的方式,可以立即看到所有变量之间的相关性。但是你会看到我只用我们的数据中的连续列来制作它,因为有这么多的特征,很难看到每一个。因此,我将制作一个只有连续特征的配对图。

**subData = data[['age','trestbps','chol','thalach','oldpeak']]
sns.pairplot(subData)**

选择用连续的变量制作一个较小的 pairplot,以便更深入地研究这些关系。这也是一个很好的方法来看看他们之间是正相关还是负相关!****

**sns.catplot(x="target", y="oldpeak", hue="slope", kind="bar", data=data);

plt.title('ST depression (induced by exercise relative to rest) vs. Heart Disease',size=25)
plt.xlabel('Heart Disease',size=20)
plt.ylabel('ST depression',size=20)**

ST 段压低的发生是因为当心室处于静止状态并因此复极时。如果 ST 段中的迹线异常地低于基线,此可导致此心脏病。这支持了上面的图表,因为低 ST 段抑郁会使人们有更大的患心脏病的风险。而高度 ST 段压低被认为是正常的&健康的。斜率色调,指运动 ST 段峰值,取值:0:上升,1:平缓,2:下降)。两个阳性&阴性心脏病患者都表现出 3 个斜率类别的均等分布

小提琴和盒子图

显示方框&图的优点是显示基本数据的统计,以及其分布。这些图通常用于比较给定变量在某些类别中的分布。

它显示了中值,IQR,&图基的栅栏。(最小值、第一个四分位数(Q1)、中值、第三个四分位数(Q3)和最大值)。

此外,它可以为我们提供数据中的异常值。

**plt.figure(figsize=(12,8))
sns.violinplot(x= 'target', y= 'oldpeak',hue="sex", inner='quartile',data= data )
plt.title("Thalach Level vs. Heart Disease",fontsize=20)
plt.xlabel("Heart Disease Target", fontsize=16)
plt.ylabel("Thalach Level", fontsize=16)**

我们可以看到,阴性和阳性患者的总体形状和分布差别很大。阳性患者表现出较低的 ST 段压低水平中位数&,因此他们的数据分布在 0 & 2 之间,而阴性患者在 1 & 3 之间。此外,我们看不出男性&女性目标结果之间有多大差异。

**plt.figure(figsize=(12,8))
sns.boxplot(x= 'target', y= 'thalach',hue="sex", data=data )
plt.title("ST depression Level vs. Heart Disease", fontsize=20)
plt.xlabel("Heart Disease Target",fontsize=16)
plt.ylabel("ST depression induced by exercise relative to rest", fontsize=16)**

阳性患者表现出增高的 ST 段压低水平中位数,而阴性患者的水平较低。此外,我们看不出男性&和女性的目标结果有什么不同,除了男性的 ST 段下降幅度稍大。

按阳性和阴性心脏病患者过滤数据

# Filtering data by POSITIVE Heart Disease patient
**pos_data = data[data['target']==1]
pos_data.describe()**

# Filtering data by NEGATIVE Heart Disease patient
**pos_data = data[data['target']==0]
pos_data.describe()**

**print("(Positive Patients ST depression): " + str(pos_data['oldpeak'].mean()))
print("(Negative Patients ST depression): " + str(neg_data['oldpeak'].mean()))**

**print("(Positive Patients thalach): " + str(pos_data['thalach'].mean()))
print("(Negative Patients thalach): " + str(neg_data['thalach'].mean()))**

对比阳性和阴性患者我们可以看到在我们的 13 特征的很多手段上有巨大的差异。通过检查细节,我们可以观察到阳性患者的最大心率增加,达到了** (thalach)平均值。此外,阳性患者表现出运动诱发的 ST 段压低相对于静息(oldpeak)约 1/3 的量。**

4.机器学习+预测分析

为建模准备数据

为建模准备数据,只需记住 ASN(赋值,拆分,规格化)。

AT22 将 13 个特征赋值给 X,&最后一列给我们的分类预测值,y

**X = data.iloc[:, :-1].values
y = data.iloc[:, -1].values**

SSplit:数据集分为训练集和测试集

**from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X,y,test_size = 0.2, random_state = 1)**

N 标准化:标准化数据将转换数据,使其分布的平均值为 0,标准差为 1。

**from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
x_train = sc.fit_transform(x_train)
x_test = sc.transform(x_test)**

建模/培训

现在,我们将在训练集&上训练各种分类模型,看看哪个产生最高的准确度。我们将比较逻辑回归、K-NN(K-最近邻)、SVM(支持向量机)、Naives Bayes 分类器、决策树、随机森林和 XGBoost 的准确性。

注:这些都是监督学习模型

模型 1:逻辑回归

**from** **sklearn.metrics** **import** classification_report 
**from** **sklearn.linear_model** **import** LogisticRegression

**model1 = LogisticRegression(random_state=1)** *# get instance of model*
**model1.fit(x_train, y_train)** *# Train/Fit model* 

**y_pred1 = model1.predict(x_test)** *# get y predictions*
**print(classification_report(y_test, y_pred1))** *# output accuracy*

准确率 74%

模型 2:K-NN(K-最近邻)

**from** **sklearn.metrics** **import** classification_report 
**from** **sklearn.neighbors** **import** KNeighborsClassifier

**model2 = KNeighborsClassifier()** *# get instance of model*
**model2.fit(x_train, y_train)** *# Train/Fit model* 

**y_pred2 = model2.predict(x_test)** *# get y predictions*
**print(classification_report(y_test, y_pred2))** *# output accuracy*

准确率 75%

模型三:SVM(支持向量机)

**from** **sklearn.metrics** **import** classification_report 
**from** **sklearn.svm** **import** **SVC**

**model3 = SVC(random_state=1)** *# get instance of model*
**model3.fit(x_train, y_train)** *# Train/Fit model* 

**y_pred3 = model3.predict(x_test)** *# get y predictions*
**print(classification_report(y_test, y_pred3))** *# output accuracy*

准确率 75%

模型 4: Naives 贝叶斯分类器

**from** **sklearn.metrics** **import** classification_report 
**from** **sklearn.naive_bayes** **import** GaussianNB

**model4 = GaussianNB()** *# get instance of model*
**model4.fit(x_train, y_train)** *# Train/Fit model* 

**y_pred4 = model4.predict(x_test)** *# get y predictions*
**print(classification_report(y_test, y_pred4))** *# output accuracy*

准确率 77%

模型 5:决策树

**from** **sklearn.metrics** **import** classification_report 
**from** **sklearn.tree** **import** DecisionTreeClassifier
 **model5 = DecisionTreeClassifier(random_state=1)** *# get instance of model*
**model5.fit(x_train, y_train)** *# Train/Fit model* 

**y_pred5 = model5.predict(x_test)** *# get y predictions*
**print(classification_report(y_test, y_pred5))** *# output accuracy*

准确率 69%

****模式六:随机森林🏆

**from** **sklearn.metrics** **import** classification_report 
**from** **sklearn.ensemble** **import** RandomForestClassifier

**model6 = RandomForestClassifier(random_state=1)***# get instance of model*
**model6.fit(x_train, y_train)** *# Train/Fit model* 

**y_pred6 = model6.predict(x_test)** *# get y predictions*
**print(classification_report(y_test, y_pred6))** *# output accuracy*

****准确率 80%!🏆

型号 7: XGBoost

**from** **xgboost** **import** XGBClassifier
 **model7 = XGBClassifier(random_state=1)
model7.fit(x_train, y_train)
y_pred7 = model7.predict(x_test)
print(classification_report(y_test, y_pred7))**

准确率 69%

通过比较这 7 个模型,我们可以得出结论:模型 6:随机森林产生的精确度最高。准确率高达 80%。🏆

****精度、召回、F1-得分支持:

****精度:是“该类中有多少被正确分类”

****回想一下:“你在这个类的所有元素中找到了多少个这样的元素”

**F1-得分**:调和表示精度和召回值的
F1 得分在 1 时达到最佳值,在 0 时达到最差值。
F1 得分= 2 x((精度 x 召回)/(精度+召回))

支持:响应的样本数,即位于该类中。**

制作混淆矩阵

**from sklearn.metrics import confusion_matrix, accuracy_score
cm = confusion_matrix(y_test, y_pred6)
print(cm)
accuracy_score(y_test, y_pred6)**

注意:一个好的经验法则是任何高于 70% 的精度都被认为是好的,但是要小心,因为如果你的精度非常高,它可能好得不真实(一个过度拟合的例子)。因此,80%是的理想精度!****

如何解读混淆矩阵:

21 是我们数据中真阳性的数量,而 28 是真阴性的数量。****

9 和 3 是错误的数量。

有 9 个类型 1 错误(假阳性)** -你预测阳性,它是假的。**

有 3 个类型 2 错误** 【假阴性】——你预测阴性,是假的。**

因此,如果我们计算准确度,它的#正确预测/ #总数。
换句话说,其中 TP、FN、FP 和 TN 代表真阳性、假阴性、假阳性和真阴性的数量。

精度 = (TP + TN)/(TP + TN + FP + FN)。
精度=(21+28)/(21+28+9+3)= 0.80 =**80%精度
**

特征重要性

****特性重要性提供了一个分数,表明每个特性在我们的模型中有多有用

特征得分越高,用于做出关键决策的特征越多&因此越重要。****

*# get importance*
**importance = model6.feature_importances_**

*# summarize feature importance*
**for i,v in enumerate(importance):
    print('Feature: %0d, Score: %.5f' % (i,v))**

**index= data.columns[:-1]
importance = pd.Series(model6.feature_importances_, index=index)
importance.nlargest(13).plot(kind='barh', colormap='winter')**

从上面的特征重要性图中,我们可以得出结论,前 4 个显著特征分别是胸痛类型( cp )、达到的最大心率( thalach )、主要血管数量( ca )以及运动相对于休息诱发的 st 段压低( oldpeak )。

预言

S cenario :一个病人出现心脏症状&你把他的生命体征输入机器学习算法。

他是一名 20 岁男性,胸痛值2(非典型心绞痛),静息血压110。****

此外,他的血清胆固醇水平为 230 毫克/分升。

他是空腹血糖> 120 mg/dl。****

他有一个 1 的静息心电图结果。****

**患者达到的最大心率**是 140。

还有,他是运动诱发的心绞痛。****

他的运动诱发的 ST 段压低**相对于休息值为 2.2。**

峰值运动 ST 段的坡度

他的没有透视着色的大血管,此外他的达到的最大心率是可逆的缺陷。

根据这些信息,你能这个心脏病患者分类吗?

**print(model6.predict(sc.transform([[20,1,2,110,230,1,1,140,1,2.2,2,0,2]])))**

****输出二进制 1 - >意为阳性心脏病诊断

预测测试集结果:

第一个值代表我们的 预测值第二个值**代表我们的实际值。

如果值匹配,那么我们正确预测了****

*****y_pred = model6.predict(x_test)
print(np.concatenate((y_pred.reshape(len(y_pred),1), y_test.reshape(len(y_test),1)),1))*****

**********

可以看到我们的结果非常准确(80%)****

结论

1。在我们检查的 13 个特征中,有助于我们在阳性&阴性诊断之间进行分类的前 4 个显著特征是胸痛类型(cp)、达到的最大心率(thalach)、主要血管数量(ca)和运动相对于休息诱发的 st 段压低(oldpeak)。

2。我们的机器学习算法现在可以对心脏病患者进行分类。现在我们可以正确地诊断病人,给他们康复所需的帮助。通过早期诊断和检测这些特征,我们可以防止以后出现更糟糕的症状。

3。我们的随机森林算法产生最高的准确率,80%。任何超过 70%的准确度都被认为是好的,但是要小心,因为如果你的准确度非常高,可能好得不像真的(过度拟合的一个例子)。因此,80%是理想的准确度!

以下是从我的 GitHub 页面获得的数据集和代码:

https://github . com/jzaidi 143/Project-Predicting-Heart-Disease-with-class ification-Machine-Learning-Algorithms

欢迎推荐和评论!

致谢

创作者:

  1. 匈牙利心脏病研究所。布达佩斯:医学博士安朵斯·雅诺西
  2. 瑞士苏黎世大学医院:威廉·斯坦布伦医学博士
  3. 瑞士巴塞尔大学医院:马蒂亚斯·菲斯特勒医学博士
  4. 弗吉尼亚医疗中心,长滩和克利夫兰诊所基金会:罗伯特·德特拉诺,医学博士,哲学博士。

捐赠者:
大卫·w·阿哈(阿哈' @ ' ics.uci.edu)(714)856–8779

数据科学编码练习项目报告

原文:https://towardsdatascience.com/project-report-for-data-science-coding-exercise-9a9c76a09be8?source=collection_archive---------13-----------------------

Benjamin O. Tayo 的图片

数据科学带回家的编码挑战问题的示例项目报告

一.导言

带回家的挑战问题或编码练习是数据科学家面试流程中最重要的一步。这通常是一个数据科学问题,例如机器学习模型、线性回归、分类问题、时间序列分析等。一般来说,面试团队会给你提供项目方向和数据集。

一些编码挑战问题会指定一个正式的项目报告与一个 Jupyter 笔记本或 R 脚本文件一起提交。这篇文章将提供一些关于如何为带回家的编码挑战问题写一份正式的项目报告的指南。

本文组织如下。在第二部分中,我们描述了项目陈述和项目目标。在第三章中,我们描述了一个问题的示例解决方案,包括数据集、代码和输出。在第四部分,我们提交了一份关于带回家挑战问题的项目报告样本。一个简短的总结结束了这篇文章。

二。项目说明

在这个问题中,你将预测贷款组合的结果。每笔贷款计划在 3 年内偿还,结构如下:

  • 首先,借款人收到资金。这个事件被称为起源。
  • 然后,借款人定期还款,直到发生以下情况之一:

(i)借款人在 3 年期限结束前停止付款,通常是由于财务困难。这一事件被称为销账,然后贷款被称为已销账。

(ii)借款人继续还款,直到发放日之后 3 年。至此,债务已全部还清。

在附加的 CSV 中,每行对应一笔贷款,列的定义如下:

  • 标题为“自发起以来的天数”的列表示发起和数据收集日期之间经过的天数。
  • 对于在收集数据之前已经销账的贷款,标题为“从发起到销账的天数”的列表示发起和销账之间经过的天数。对于所有其他贷款,此栏为空白。

目标 :我们希望您估计这些贷款在全部 3 年期限结束时将会被冲销的比例。请包括你如何得到你的答案的一个严格的解释,并且包括你使用的任何代码。你可以做出简化的假设,但是请明确地陈述这些假设。 请随意以您喜欢的任何格式提交您的答案;特别是 PDF 和 Jupyter 笔记本都不错 。此外,我们希望这个项目不会占用您超过 3-6 个小时的时间。

三。项目数据集、代码和示例输出

这个问题的数据集和建议的解决方案(包括代码和输出)可以从下面的链接下载:

贷款状况的蒙特卡洛模拟

: 以上给出的建议解决方案是我对该问题的解决方案版本。请记住,数据科学或机器学习项目的解决方案不是唯一的。欢迎你自己尝试这个问题,提出你自己的预测模型。

四。项目报告

完成项目的编码部分后,是时候整理一份正式的项目报告了。下面是该项目的样本报告。

利用蒙特卡罗模拟预测贷款状况

摘要:使用所提供的数据集,我们建立了一个简单的模型,使用蒙特卡罗(MC)模拟来预测贷款在 3 年期限后违约的比例。对于 N = 1000 个数据集复制副本的蒙特卡洛模拟,我们的模型显示了 14.8% +- 0.2%的 95%置信区间。

关键词:贷款状态、贷款发放、贷款核销、蒙特卡洛模拟、预测分析

引言:预测贷款的状况是风险评估中的一个重要问题。银行或金融机构在向客户发放贷款之前,必须能够估计所涉及的风险。数据科学和预测分析技术可以用来预测贷款违约的概率。在本项目中,我们获得了包含 50000 个数据点的loan _ timing . CSV数据集。每个数据点代表一笔贷款,提供两个特征如下:

  • 标题为“自发起以来的天数”的列表示从发起到收集数据的日期之间经过的天数。
  • 对于在收集数据之前销账的贷款,标题为“从发起到销账的天”的列表示发起和销账之间经过的天数。对于所有其他贷款,此栏为空白。

项目目标:这个项目的目标是使用数据科学的技术来估计这些贷款在所有三年期限结束时已经注销的部分。

探索性数据分析:数据集在 R 中很重要,使用 R 进行计算。我们绘制了下图:

图 1 :当前贷款自发放以来的天数直方图。

图 2 :违约贷款销账天数柱状图。

图 3 :违约贷款发放以来天数柱状图。

图 1 显示了当前(活跃)贷款的直方图,该直方图具有很好的近似性,自发放以来在几天内均匀分布。

图 2 中,我们看到从发放到核销的贷款比例随着天数的增加而减少。这说明越年轻的贷款违约概率越大。它还显示,100%的贷款在自发放日起的 2 年内(730 天)违约。

图 3 显示了从发放贷款到收集贷款状态数据期间的违约贷款分布情况。违约贷款中有很大一部分(71%)是一年或一年以上的贷款。

我们进行了蒙特卡洛模拟,以研究违约贷款的核销天数和发放后天数之间的关系,并将结果与原始样本数据进行比较,如图图 45 所示。由于贷款核销存在随机性(随机过程),我们看到蒙特卡罗模拟为违约贷款的分布提供了合理的近似。

图 4 :违约贷款的核销天数与发放后天数的关系图。

图 5 :违约贷款的核销天数与发放后天数的蒙特卡洛模拟。

模型选择:我们的数据集只有 2 个特征或预测因子,并且避开了流行性问题:93%的贷款具有活跃(当前)状态,而 7%具有违约状态。使用线性回归来预测 3 年贷款期限后将被注销的贷款部分,将产生一个偏向于活跃贷款的模型。

图 45 表明,可以使用蒙特卡罗方法模拟违约贷款的核销天数和发放后天数之间的关系。因此,我们选择蒙特卡洛模拟作为我们预测贷款违约比例的模型。

预测:由于我们已经证明,在最初 2 年(即 0 至 730 天)中,可以使用蒙特卡罗模拟来近似计算待核销天数和自发放以来的天数之间的关系,因此我们可以使用相同的方法来预测在所有 3 年期限结束时将被核销的贷款比例。

我们数据集中冲销贷款的总数是 3,305。这意味着目前有 46,695 笔贷款处于活跃状态。在这些活跃的贷款中,一定比例的贷款将在 3 年内违约。为了估计违约贷款的总比例,我们模拟了涵盖整个贷款期限(即 0 至 1095 天)的冲销和自发放以来的天数的违约贷款,然后通过适当的缩放,我们计算了将在 3 年期限(即 1095 天)后冲销的贷款比例。

通过创建 1000 个随机试验,我们获得了 3 年贷款期限内违约贷款比例的以下分布(见图 6 ):

图 6 :使用 N = 1000 个样本的 3 年期后冲销贷款比例直方图。

根据我们的计算,3 年贷款期限后将被冲销的贷款部分的 95%置信区间相应地为 14.8% +- 0.2%。

结论:我们提出了一个基于蒙特卡罗模拟的简单模型,用于预测在 3 年贷款期限结束时将违约的贷款比例。可以使用不同的模型,例如逻辑回归、决策树等。这将是一个好主意,尝试这些不同的方法,看看是否结果是可比的蒙特卡洛模拟结果。

附录:用于执行数据分析的 R 代码

***# R CODE FOR PREDICTING LOAN STATUS*** *#author: Benjamin O. Tayo
#Date: 11/22/2018****# IMPORT NECESSARY LIBRARIES*** library(readr)
library(tidyverse)
library(broom)
library(caret)***# IMPORTATION OF DATASET*** df<-read_csv("loan_timing.csv",na="NA")
names(df)=c("origination","chargeoff")***#partition dataset into two: default (charged off ) and current*** index<-which(!(df$chargeoff=="NA"))
default<-df%>%slice(index)
current<-df%>%slice(-index)***# EXPLORATORY DATA ANALYSIS*****# Figure 1: Histogram of days since origination for current loans**current%>%ggplot(aes(origination))+geom_histogram(color="white",fill="skyblue")+ xlab('days since origination')+ylab('count')+ ggtitle("Histogram of days since origination for current loans")+ theme(plot.title = element_text(color="black", size=12, hjust=0.5, face="bold"),axis.title.x = element_text(color="black", size=12, face="bold"),axis.title.y = element_text(color="black", size=12, face="bold"),legend.title = element_blank())***# Figure 2: Histogram of days to charge-off for defaulted loans***default%>%ggplot(aes(chargeoff))+geom_histogram(color="white",fill="skyblue")+ xlab('days to charge-off')+ylab('count')+ ggtitle("Histogram of days to charge-off for defaulted loans")+ theme(plot.title = element_text(color="black", size=12, hjust=0.5, face="bold"), axis.title.x = element_text(color="black", size=12, face="bold"), axis.title.y = element_text(color="black", size=12, face="bold"), legend.title = element_blank())***# Figure 3: Histogram of days since origination for defaulted loans***default%>%ggplot(aes(origination))+geom_histogram(color="white",fill="skyblue")+ xlab('days since origination')+ylab('count')+ ggtitle("Histogram of days since origination for defaulted loans")+ theme(plot.title = element_text(color="black", size=12, hjust=0.5, face="bold"),axis.title.x = element_text(color="black", size=12, face="bold"),axis.title.y = element_text(color="black", size=12, face="bold"), legend.title = element_blank())***# Figure 4: Plot of days to charge-off vs. days since origination for defaulted loans***default%>%ggplot(aes(origination,chargeoff))+geom_point()+ xlab('days since origination')+ylab('days to charge-off')+ ggtitle("days to charge-off vs. days since origination")+ 
theme( plot.title = element_text(color="black", size=12, hjust=0.5, face="bold"), axis.title.x = element_text(color="black", size=12, face="bold"), axis.title.y = element_text(color="black", size=12, face="bold"),legend.title = element_blank())***# Figure 5: Monte Carlo Simulation of Defaulted Loans***set.seed(2)
N <- 3*365 ***# loan duration in days***
df_MC<-data.frame(u=round(runif(15500,0,N)),v=round(runif(15500,0,N)))
df_MC<-df_MC%>%filter(v<=u)
df_MC<-df_MC%>%filter(u<=730 & v<=730) ***#select loans within first 2 years***df_MC[1:nrow(default),]%>%ggplot(aes(u,v))+geom_point()+ xlab('days since origination')+ylab('days to charge-off')+ ggtitle("MC simulation of days to charge-off vs. days since origination")+ theme(plot.title = element_text(color="black", size=12, hjust=0.5, face="bold"),axis.title.x = element_text(color="black", size=12, face="bold"),axis.title.y = element_text(color="black", size=12, face="bold"),legend.title = element_blank())***# Predicting fraction of these loans will have charged off by the time all of their 3-year terms are finished***set.seed(2)
B<-1000
fraction<-replicate(B, {
df2<-data.frame(u=round(runif(50000,0,N)),v=round(runif(50000,0,N))) df2<-df2%>%filter(v<=u) 
b2<-(df2%>%filter(u<=730 & v<=730))
total<-(nrow(df2)/nrow(b2))*nrow(default)
100.0*(total/50000.0)})***# Figure 6: Histogram for fraction of charged off loans after 3-year term using N = 1000 samples***fdf<-data.frame(fraction=fraction)
fdf%>%ggplot(aes(fraction))+geom_histogram(color="white",fill="skyblue")+ xlab('fraction of charged off loans after 3-year term')+ylab('count')+ ggtitle("Histogram of total fraction of charged off loans")+ 
theme( plot.title = element_text(color="black", size=12, hjust=0.5, face="bold"),axis.title.x = element_text(color="black", size=12, face="bold"),axis.title.y = element_text(color="black", size=12, face="bold"),legend.title = element_blank())***# Calculate Confidence Interval for Percentage of Defaulted Loans After 3-year Term***mean<-mean(fraction)
sd<-sd(fraction)
confidence_interval<-c(mean-2*sd, mean+2*sd)

动词 (verb 的缩写)摘要

总之,我们已经描述了如何撰写数据科学带回家挑战的项目报告。一些数据科学家的工作面试会要求申请人提交一份正式的项目报告以及一个 Jupyter 笔记本或 R 脚本文件。这里提供的指导方针可以用来为带回家的编码练习准备正式的项目报告。

参考

  1. 贷款状况的蒙特卡洛模拟。
  2. 数据科学家编码练习。
  3. 数据科学家面试流程——个人经历。

数据科学初学者项目时间表

原文:https://towardsdatascience.com/project-timeline-for-data-science-beginners-83b7106e44e1?source=collection_archive---------33-----------------------

并回答这个问题:我该从哪里开始呢?我如何进步???

由布鲁克·卡吉尔在 Unsplash 拍摄的照片

整整两个月前,我决定开始我的编码之旅。我发现很少有文章给出初学者友好的编程管道。是时候分享了!

如何利用数据分析来回答棘手的问题?

在这篇文章中,你会发现:

  • 从哪里开始?用于编程的编码平台/环境
  • 初学者项目哪里找灵感。如何从每个项目中学习而不被卡住
  • 当我们遇到卡住时该怎么办

如果您还不是会员,请在此获得您的中级会员资格!

人们实际上在哪里编码?

在线课程很少提到数据科学过程中第一步也是最关键的一步。想开始编码的时候下载哪些工具!为此,我推荐两种可能的集成开发环境(ide):

皮查姆

Pycharm: 计算机编程中使用的集成开发环境,专门针对 Python 语言。它是由捷克公司 JetBrains 开发的。

Pycharm 太棒了!有很多视频解释如何设置软件和运行代码。对于初学者来说,这个 IDE 提供了您需要的一切,而不会使用户界面过于复杂。随着你越来越有经验,它提供了专业人员将用于机器学习、模型训练等的所有功能。

显然,生活中没有免费的东西。该软件允许 30 天的试用期,对学生完全免费。你不会因为尝试而失去任何东西,如果你在几个项目后看到了编码的未来,那么这是你可能做出的最好投资

朱皮特

Jupyter:一个开源的网络应用程序,允许你创建和分享包含实时代码、公式、可视化和解释文本的文档。用途包括:数据清理和转换,数值模拟,统计建模,机器学习等等。

Jupyter 很容易使用,对初学者友好,但当你尝试做更高级的事情时,它不会为你工作。然而,这是一个很好的起点。现在好消息来了,它完全免费了!

去哪里找项目的灵感?

作为一个完全的初学者,很难评估一个项目的难度。许多东西会使项目变得更加困难:函数、库、数据集或弃用。你怎么知道该去做哪个项目?

选择适合您的项目:

  1. 选择一个你感兴趣的话题,比如电影收视率,离婚率,销售,流浪狗...任何事!
  2. 找一个数据集(真正好的网站包括 KaggleDataWorld 等等)
  3. 找一个做过类似项目的人
  4. 复制项目,对其进行改进,并使用类似的数据集进行同样的尝试。

你可以在 Kaggle 上的内核标签下找到好的示例项目。Medium 的走向数据科学出版物拥有数百名作家,他们分享他们的项目,并带你走过每一步。

当心几件可能让你的生活变得困难的事情:

  • 导入的库数量:单个项目中超过 6 或 7 个库可能对初学者不友好。库允许我们为特定的数据类型或数学应用程序使用函数和执行子程序。例如 Seaborn 执行绘图, xlrd 处理 excel 文件, Numpy 允许数学计算等。库越多,你需要学习/理解的东西就越多,项目就越复杂。
  • 带注释的代码:写代码的时候,注释会添加关于代码的信息,让代码更容易理解。如果别人的项目得到了很好的评论,他们会花时间解释和思考每一行代码,然后再把它发布到互联网上。
  • 发布年份:寻找不超过现在 2 年的项目实例。函数、库和编程语言每隔几年就会更新或被弃用,你需要确保你使用的是最新的。

面向初学者的数据分析项目时间表:

1.探索性数据分析和可视化:

酒评

学到的技能:熊猫数据集

这个示例项目将向您介绍如何在编码环境中创建和导入数据集。然后,它将引导您完成探索性数据分析的早期阶段。完全新手的绝佳起点!

每个城市的婚姻数量

已学技能:绘图入门

这个项目将以非常详细和初学者友好的方式向你介绍绘制条形图。这些数据来自电视节目《一见钟情》的数据集,它是数字和分类数据的健康组合。

《权力的游戏》收视率

学到的技能:更多的初学绘图技术

这个数据集提供了从 IMDb 网站提取的信息,包括每集的名称,收视率,观看次数和值得注意的人物死亡数。该项目示例将带您浏览条形图和散点图。

美国致命枪击案(2015–2020)

所学技能:探索性数据分析(EDA)

这个项目示例将让您对深度探索性数据分析有一个很好的了解。变量,如年,天,种族,年龄,地区,性别,背景进行了比较和对比,以得出关于美国致命枪击事件的见解。

新西兰战胜冠状病毒

学到的技能:首先浏览一个 数据集

谷歌移动性报告发布了世界所有国家的数据,跟踪药店、零售店、公园和办公室的访问量。这个项目使用的数据集特别大,可以让你解决诸如速度效率等问题。按国家、地区或日期过滤将是针对该数据集使用的主要工具。

澳大利亚房地产价格

学到的技能:地理空间绘图(很酷的地图!)和高级图表

这个项目将向你介绍一个基于澳大利亚房地产价格的非常大的数据集。它将向你介绍空间绘图(非常令人兴奋!)等高级剧情使用了强大的 Seaborn 库。

2.回归模型

回归是一种用于金融、投资和其他学科的统计方法,试图确定一个因变量(通常用 Y 表示)和一系列其他变量(称为自变量)之间关系的强度和特征。

温度影响啤酒消费吗?

学到的技能:你的第一个回归模型项目

该数据集收集了巴西圣保罗学生社区的天气和啤酒消费变化。

所有的绘图基础都包括在这个项目中,包括小提琴图,饼图,线图和条形图一步一步地解释。这个例子中还包含了一个非常简单的线性回归模型,使用著名的 sklearn 库来预测啤酒消费量。

Strava 活动追踪应用

学到的技能:完整的机器学习项目工作流程

对于那些想看看完整的 ML 管道的人来说,这是一个很好的项目。使用的数据来自应用程序“Strava ”,它记录体育活动并与社区共享。它使用均方根误差(rmse)来设置回归模型的参数。

这个项目比较了多个模型的表现,并选择了最适合的模型来回答这个问题:我们能预测一项锻炼将获得的点赞数吗?

普查收入数据

学到的技能:主成分分析

降维是将数据从高维空间转换到低维空间。使得分析更快更容易。主成分分析(PCA)是一种用于主成分分析的方法。

这个非常详细记录的项目将带你通过清洁和减少过程。

医疗保险费用

学到的技能 : 高级绘图和线性回归

这个项目将为您提供先进的绘图可视化的例子,也将提供另一个线性回归模型的例子。最终目标是准确预测病人的医疗费用。此回归模型使用了 RandomForestRegressor 算法。

自然语言处理

自然语言处理是语言学、计算机科学、信息工程和人工智能的一个分支,涉及计算机和人类语言之间的交互,特别是如何对计算机进行编程以处理和分析大量自然语言数据。

WhatsApp 聊天分析是

学到的技能:自然语言处理(NLP)数据清理。

非常适合从未接触过文本文件的初学者。在这个项目中,您将导入您的 WhatsApp 对话,并执行深入的数据清理。这是数据分析中至关重要的一步,尤其是当我们谈论“语言数据”的时候。在计算机的眼里,单词和数字是非常不同的…

姜懿翔·川普发推文

学到的技能:全面的自然语言处理项目

自然语言处理初学者的一个非常好的项目。该工作流将引导您完成数据清理和探索。然后,它会使用“【nltk】【自然语言工具包】 库,这将允许你应用机器学习来训练唐纳德·特朗普的推文模型。

网络

莎士比亚戏剧

学到的技能:网络可视化

这个项目将引导你在绘制和可视化莎士比亚剧目中的戏剧和角色网络之前,进行深入的数据探索。这是一个很好的网络介绍,也是戏剧爱好者的理想选择!

利用网络,它会找到最有影响力的人物以及这些人物拥有的联系数量。

爱尔兰天气每小时数据

学到的技能:数据随季节变化

该数据集包含来自爱尔兰 15 个县的 25 个站点的数据。从开始记录到 2018 年底,这些气象站可以获得每小时的数据。所有数据来源于爱尔兰气象局。该数据集可与自行车使用数据集结合使用。

当我们陷入困境时该怎么办

  • 检查您的数据:确保您正在分析的数据集的列中没有无效值。检查是否有缺失值或错误的数据类型。
  • 打印出错误之前的所有内容:确保整个过程没有出错。有时当使用函数或子程序时,我们没有预料到的事情会修改我们的数据。
  • 改变库:如果你在使用 Matplotlib 绘制条形图时遇到问题,可以使用 Seaborn 库计算出等价的结果。这是一个简单的方法,但是尝试不同的库并看看什么适合你并不可耻。
  • 求助,网络社区是你的朋友!我最喜欢的网站是 Stack Overflow。如上所述,当使用在线资源时,确保考虑到出版年份。

非常感谢你的阅读!

更多类似的文章,请点击这里在 Medium 上找到我!

如果你有任何关于如何改进的问题建议想法,请在下面留下评论或通过 LinkedIn 这里取得联系。

使用 Python 和 Tableau 可视化基础设施增长

原文:https://towardsdatascience.com/projecting-and-visualizing-infrastructure-growth-trends-with-python-1e578d9e4260?source=collection_archive---------31-----------------------

Python 如何逐月汇总数据消耗,并避免数小时的手动计算

unsplash.com

当进行项目规划时,了解您的数据库或专用网络共享是否能够处理增加的数据负载对于避免性能故障至关重要。虽然后端管道开发、数据工程和基础设施维护不像如今的数据科学、机器学习或分析那样“热门”,但它确实是公司数据需求的核心。如果没有坚实的基础或实施策略来处理来自不同来源和系统的大量数据,就很难对数据进行任何转换。

这是一种很自然也很频繁出现的查询——我们在优化我们的基础设施吗?

令人欣慰的是,我们不必手动整理过去三年中成千上万的文件,我们可以让 Python 来完成繁重的工作。当面对我们的应用程序数据需要如何随时间变化的问题时,我创建了一个方便的脚本来按月汇总数据量。一旦这样做了,就很容易绘制出一段时间内的趋势。

在这里的使用案例中,我想知道的是,在一个公共的 Windows 网络连接共享上,每个应用程序的逐月流量是如何增加的。由于许多服务使用同一个位置,因此首先按应用程序,然后按文件夹位置分离报告非常重要。这个脚本最好的部分是它是可重用的,并且可以很容易地为任何其他应用程序或网络位置进行配置,因为这个函数是通用的。

问题:

逐月确定 Windows 位置上文件的数据量

解决方案:

解析每个文件的时间戳和大小,然后按月合计总数据量

第一步:加载所需的库——pandas、datetime、os、os.path、time

步骤 2: 命名输出文件(您想要保存报告的地方)

appService = "abc_service"
writer = pd.ExcelWriter(r"C:\\scripts\\output\\" + appService + ".xlsx", engine='xlsxwriter')

步骤 3: 创建一个函数,返回所提供的网络位置在一个月间隔内的总流量

或者,您可以选择添加一个额外的以 MB 或 GB 为单位的列,因为 Python 返回的默认值是以字节为单位的。

def getFileSummaryByMonth(directory, path):
 folder = path
 filepaths = [os.path.join(folder, f) for f in os.listdir(folder)]stats = {}
 i = 0for file in filepaths:
  # Get the unique date for each file
  file_name = file
  last_Mod = os.stat(file).st_ctime
  size = os.stat(file).st_size
  str1 = time.ctime(os.path.getmtime(file_name)) 
  datetime_object = datetime.datetime.strptime(str1, '%a %b %d %H:%M:%S %Y')
  date = datetime_object.strftime("%Y-%m") # 06/07/2013
  # Add values to dictionary
  stats = {'Index': i, 'file_name': file_name, 'date': date, 'size': size}
  print(stats)
  i = i+1
  dict_obj.add(i, stats)# Create duplicate file info dictionary
 filestats = stats# Convert to dataframe
 filestats = pd.DataFrame.from_dict(dict_obj,orient='index')
 print(filestats)# Aggregate files by unique month and filesize
 filestats["date"] = pd.to_datetime(filestats["date"])
 grouped_by_month_stats = filestats.groupby(filestats['date'].dt.strftime('%Y-%m'))['size'].sum().sort_values()
 print(grouped_by_month_stats)
 df = pd.Series.to_frame(grouped_by_month_stats)
 df.sort_values(by='date', inplace=True, ascending=False)# Write each filtered dataframe to a different worksheet in the same Excel file
 df.to_excel(writer, sheet_name=directory)

第四步:更新脚本包含所有路径,调用上面提到的 getFileSummaryByMonth 函数

getFileSummaryByMonth('reporting_service', 'C://first_path//')
getFileSummaryByMonth('archive_service', 'C://second_path//')
getFileSummaryByMonth('search_service', 'C://third_path//')

步骤 5: 执行脚本后查看结果——每个文件夹将在输出 Excel 电子表格中保存为不同的选项卡。根据您的需要,您可以选择更新脚本以相应地显示结果。

为了形象化成长,你可以根据你的最终目标来创造 Tableau。我的目标是每月观察过去三年的交易量增长。如果您知道预期的文件大小,您可以相应地调整电子表格的容量,并再次绘图以预测所需的总存储量。

希望这个 Python 脚本能帮助您踏上数据科学和数据工程之旅!

地心的证明(P > 0.05):正确解释统计检验

原文:https://towardsdatascience.com/proof-of-a-hollow-earth-p-0-05-properly-interpreting-statistical-tests-dca154c90ffe?source=collection_archive---------48-----------------------

误解这个统计测试的圣杯,P 值,会导致错误的结论

露丝·齐默曼在 Unsplash 上拍摄的照片

许多科学实验的关键在于测试两个独立抽样组的平均值之间是否有显著差异。这些统计测试产生一个概率值,如果该值低于某个预定阈值,则认为差异是显著的。这个价值观有很多包袱和误解。如果我们使用一个假想的数据集进行统计测试,以确定地球是否有一个核心,我们可能会得到一个不重要的 P- 值。那么地球是空心的吗? 肯定不是!

近年来,P 值的误用成为复制危机的一个来源。很多心理学和生物科学的研究都无法重现一些所谓的重大成果。通常本科和研究生教育不足以让科学家们做好严格理解如何解释巨大价值的准备。

无论是优化网站流量、广告相关数据还是生物相关数据,您都需要可操作的数据描述符。

当临床医生测试一种新药治疗的疗效时,仅仅一个显著的 P 值就可能产生误导或危险。我们必须首先理解它在实验的上下文中意味着什么。

P- 值能告诉我们影响的大小吗?还是各组之间有差异的概率?它能证实一个实验假说吗?

P- 值的定义

P- 值的字面定义如下:

如果零假设为真,观察结果的概率,加上更极端的结果。

零假设 ( H₀ )断言从两组中独立采样的独立采样变量的均值/排序没有差异。例如,这些组可以是治疗组或对照组。这些群体中的个体是从一个更大的群体中抽取的,这个群体被称为群体。

因此,概率告诉我们,如果两组之间没有真正的差异,获得某个测试结果的机会。

P -没有告诉我们零假设为真的概率。

一个 P- 值为 0.03 并不意味着有 3%的零假设是真的。回想一下,统计测试是在假设原假设已经成立的情况下进行的!因此, P- 值并没有告诉我们关于类型 I假阳性错误的信息。毕竟,当我们假设 H₀ 为真时,我们怎么能得出一个假阳性的结论呢?这就是为什么文章标题中的说法是假的!它违背了这个假设!

如果我们的 P 值高于我们设定的阈值,这并不意味着两组之间没有真正的差异。

回想一下,我们是从总体中抽取值。有了这样一个样本,在你的样本群体中总是有可能得出一个不重要的结论,尤其是当他们很小的时候。我们完全有可能错误地应用了假设或统计测试,而没有得出正确的结论。因此,如果我们在测试后没有发现显著差异,这并不意味着我们两组之间没有差异。

此外,评估同一实验的两项研究可能会收到不同的 P- 值,因为它们是不同的样本。即使一项研究显示了显著性,而另一项没有,说这两项研究不一致也是不准确的。

统计上显著的结果是有意义的和重要的

仅仅一个统计测试不能告诉我们数据意味着什么。如果我们在进行许多统计测试时没有对此进行适当的修正,我们很容易产生虚假的相关性。如果我们发现了一个重要的值,它并没有告诉我们任何关于影响的大小,或者我们对这个影响的信心。如果可能,P 值的相关性应通过评估实验问题、效应大小和置信区间来确定。

我们不能曲解一个 P 值的定义,得出地球是空心的结论。

参考资料和进一步阅读

  1. 古德曼,史蒂文。《十二个肮脏的:十二个 p 值误解》血液学研讨会。第 45 卷。№3.WB 桑德斯,2008。
  2. 林肯·j·科林和德内斯·szűcs."统计推断和复制危机."哲学与心理学复习(2018):1–27。

大数定律的证明第一部分:弱定律

原文:https://towardsdatascience.com/proof-of-the-law-of-large-numbers-part-1-the-weak-law-daf412178d3a?source=collection_archive---------9-----------------------

有限和无限方差情形下 WLLN 的证明

照片来自 Adobe Stock Images

背景和动机

大数定律(LLN)是概率论中最重要的定理之一。尽管这个定理远远超出了概率和统计的范畴。实际上,LLN 是一种手段,通过这种手段,科学努力甚至有可能被复制,允许我们用科学方法研究我们周围的世界。

LLN 实际上有两个主要版本:弱大数定律(WLLN)和强大数定律(SLLN)。它们之间的区别在于它们依赖于不同类型的随机变量收敛。弱定律处理概率收敛,强定律几乎必然收敛。

在本文中,我们将关注有限和无限方差情况下的标准 WLLN。证明 SLLN 几乎肯定是收敛的有点复杂;关于 SLLN 的证明,请看我的后续篇“大数定律的证明第二部分:强定律”。

弱大数定律的定义(WLLN)

标准 WLLN 的数学定义如下:

注意上面的定义没有对随机变量 Y 的方差做任何假设。而是随机变量是独立同分布的,并且有一个确定的有限的期望值。下面我提供两个证明:

  1. 对于有限方差的情况
  2. 对于有限或无限方差的情况

有限方差情况的证明非常简单,而且广为人知。然而,由于有限方差不是 WLLN 的必要条件,为了完整性,知道无限方差情况的证明是有用的。

1.WLLN 的证明:有限方差情形

让我们稍微碰碰运气我们开始的条件:

在这些条件下证明 WLLN 是非常简单的。在我之前的文章概率论和数理统计中的统计不等式中,我讨论了统计不等式如何以及在哪里有用。这是其中的一个例子。回想一下切比雪夫不等式:

WLLN 的证据直接来自切比雪夫:

2.WLLN 的证明:有限或无限方差情况

如上所述,WLLN 不需要定义随机变量nY 的方差。然而,在没有定义和有限方差要求的情况下证明 WLLN 有点复杂,需要一些关于特征函数的知识,以及一些关于不同类型的随机变量收敛之间关系的定理。不过,让我们开始吧:

首先,让我们定义一个任意随机变量的特征函数,并提供一些可能对我们有用的独立同分布随机变量的性质:

以及泰勒定理对指数函数展开的一些注记:

我们现在准备好证明了。让我们从随机变量 n i.i.d. Y 的样本平均值的特征函数开始,以展示样本平均值以概率收敛于μ结束。

最终想法:

上面我们用两种不同的方法证明了标准 WLLN。值得一提的是,LLN 的一些变体允许放宽 i.i.d .要求。关于 SLLN 的证明,请看我的后续篇“大数定律的证明第二部分:强定律”。

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在 LinkedIn 上与我联系,并在 Medium 上 关注我的更新!

大数定律的证明第二部分:强定律

原文:https://towardsdatascience.com/proof-of-the-law-of-large-numbers-part-2-the-strong-law-356aa608ca5d?source=collection_archive---------28-----------------------

SLLN 的证据

照片来自 Adobe Stock Images

背景和动机

大数定律(LLN)是概率论中最重要的定理之一。尽管这个定理远远超出了概率和统计的范畴。实际上,LLN 是一种手段,通过这种手段,科学努力甚至有可能被复制,允许我们用科学方法研究我们周围的世界。

LLN 实际上有两个主要版本:弱大数定律(WLLN)和强大数定律(SLLN)。它们之间的区别在于它们依赖于不同类型的随机变量收敛。弱定律处理概率收敛,强定律几乎必然收敛。

在我之前的文章中,我们提供了弱大数定律(WLLN) 的证明。作为后续,正如所承诺的,本文作为第 2 部分,强大的大数定律(SLLN)的证明。

强大数定律(SLLN)的定义

SLLN 的数学定义如下:

我发现几乎可以肯定的衔接会有点难以把握;比其他类型的随机变量更难收敛。因此,让我们试着在 SLLN 的背景下对其进行一点解构:

SLLN 的证据

最终想法:

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在 LinkedIn 上与我联系,并在 Medium 上 关注我的更新!

适当的多线程——让我们再次提醒自己它是什么

原文:https://towardsdatascience.com/proper-multithreading-have-perfect-multithreading-in-your-program-4cbbf8270af3?source=collection_archive---------27-----------------------

这听起来很理想,但是如何才能拥有真正的多线程,并使用适当的锁来保护您的程序,使它可以平稳运行,而不用担心是否会出现死锁或竞争情况呢?只是一些锁、信号量和大量的思考时间。

我是说,还能怎样?要求它自己做多线程安全是疯狂的。我们可以从如何锁定程序和防止死锁开始。

什么是适当的多线程以及如何做?

为了使程序工作时不出现死锁和数据丢失,必须达到某个特定的程序流。当您同时从多个线程访问共享资源时,可能会发生死锁或竞争情况。当你用多线程运行一个程序时,很难调试到底什么时候发生了什么,以及哪个线程比其他线程更优先访问共享资源。这就是锁发挥作用的地方,我们用它来防止同样的死锁。

还有一点要提的是上下文切换,其中是计算机的 CPU(中央处理器)在保证任务不冲突的情况下,从一个任务(或进程)切换到另一个任务(或进程)所遵循的程序。如果计算机要提供用户友好的多任务处理,有效的环境切换是至关重要的。

让我们更详细地讨论锁。

有几种不同的锁:

M 执行程序和条件变量

互斥体

代表互斥并保护正在被多个线程使用的共享资源。共享资源需要受到保护,以确保正在写入/读取的数据得到正确处理。

简单地说,可以有一个全局变量,并且可以被多个线程访问。你锁定它是因为一个线程可以写,其他线程可以读,但这需要以一定的顺序发生。

这就是互斥体简化的工作方式

例子

C 语言中的互斥示例

有许多与互斥控件相关的函数,你可以在这里的中查看所有的函数。锁的大多数功能在所有语言中都是相似的。

条件变量

条件变量允许任意数量的线程等待另一个线程发出条件信号,然后它们可以开始工作。

当它的一个等待函数被调用时,它使用一个 unique_lock(通过互斥锁)来锁定线程。该线程保持阻塞状态,直到被另一个线程唤醒,该线程在同一个 condition_variable 对象上调用通知函数

它沿着互斥体工作,你可以在这里查看所有的特性。

结论

这是一个简短的概述,并提醒您使用互斥锁和条件变量来锁定程序,以便实现完美的多线程。

时间序列模型的适当验证

原文:https://towardsdatascience.com/proper-validation-of-a-time-series-model-5c1b54f43e60?source=collection_archive---------13-----------------------

关于典型错误以及如何避免它们

在本文中,我将通过几个设置来评估机器学习模型在时间序列数据上的性能。有几种方法可以正确地做这件事。但是也有很多方法是错误的。两者我都举几个例子。对于这里的所有例子,我将使用我以前的文章中描述的时间序列和模型,关于用基于树的模型处理时间序列的,但是这里描述的方法是通用的,也适用于其他模型。

由 patricia serna 在 Unsplash 上拍摄的照片

所以我们有了一个时间序列预测模型,现在想看看它的表现有多好。常见的方法是使用验证集。该集合不用于训练,仅用于评估预测的质量,这种方式提供了一种可信的方法来评估模型对未知未来数据的性能。

对于简单的表格数据,一种典型的方法是随机选择验证维持集,或者使用几个折叠的交叉验证。然而,对时间序列这样做可能不是我们想要的。原因是,通过选择随机数据点进行验证,我们可能最终得到比验证更新的训练数据。基本上,我们会根据未来的数据进行训练,并预测过去。这并不是我们在实践中对模型的预期。

因此,时间序列更典型的方法是按时间进行选择,将最新的数据作为验证集,如下图所示。

到目前为止,一切看起来简单明了,但是,让我们更仔细地看看验证部分。

验证数据的差距

在给定的例子中,我们有一个月的验证数据。在验证期的第一天,一切都很清楚。我们有以前数据点的完整连续历史数据,可以像计算训练数据一样计算所有特征。但是现在我们来看看验证期的第二天。如果我们想预测两天前的值,这意味着我们错过了一天的真实值。为了更好地理解这个问题,请看下面的可视化图。

历史中的验证期间隔(由作者创建)

训练数据是连续的,但现在在验证集中,我们有一个缺口。在真实/测试数据中,如果我们想提前 2 步或更多步预测值,我们也会有这种差距。对于验证数据,我们实际上知道该数据点的真实值,但是如果我们不能对真实的未来数据做同样的事情,那么使用它是一个好主意吗?为了使模型准确,为了使验证可信,我们需要使训练、验证和真实/测试数据尽可能相似。

对此,基本上有 3 种可能的解决方案:

  • 我们可以通过用真相填充来消除验证数据中的缺口;
  • 我们可以用预测来填补验证数据中的空白;
  • 我们可以引入训练数据的差距。

让我们把这些都过一遍。

用真值填补验证数据中的空白

这意味着我们使用部分验证数据(预测当前点之前的数据点)来生成特征。这反过来意味着我们假设我们在预测时知道这些真值。对于真实的未来数据,只有我们提前一步做出预测,这才有可能。

如果我们使用历史验证集数据点来计算特性,这将模拟一种情况,即我们的模型总是只提前步预测值。

在验证中使用先前数据点的真实值(由作者创建)

这种方法是否有效,实际上取决于业务。如果我们的真实模型只提前一步预测值(例如,每天只预测明天的访问者数量),那么这样的验证设置是非常好的。

但是,如果在现实中,我们想要获得下一个整月的预测,这样的验证方案将会过拟合,并且估计的模型准确性将会过于乐观。

用以前的预测填补验证数据中的空白

在这种情况下,我们在循环中进行预测。首先,我们预测验证集第一天的值。然后,我们预测第二天的值,使用我们的第一个预测作为真实值来填补空白。以类似的方式,我们遍历所有的验证集,使用前几天的预测作为真实值,一天一天地预测。

使用以前对历史的预测(由作者创建)

好消息是,我们可以对真实/测试数据进行完全相同的处理。因此验证分数将代表真实的模型性能。

然而,有一个明显的问题——通过使用以前的预测作为真实值,我们使模型相信它们是正确的。但是它们绝对不会是完美的。因此,通过这种方式,我们引入了验证数据与训练数据之间的差异。在训练数据中,所有的历史值都是真实的,但在验证数据中,部分历史值实际上不是真实的,而只是带有一些误差的预测。

当预测进一步的值时,使用以前数据点的预测可能会导致预测误差累积,从而导致以后验证日的性能非常差。

如果我们使用相同的方法来预测真实的未来数据,这种方法可以作为一种验证方法。在这种情况下,验证分数将与真实模型性能相匹配,从验证的角度来看,这是可以接受的。但是我们必须意识到,对于更远的未来预测,预测的准确性会显著降低。

在训练数据中引入相同的差距

这意味着我们对每天的预测使用不同的模型和特征。为了预测验证集的第一天,我们使用了基于完整训练数据训练的模型。为了预测验证集的第二天,我们在特征上训练模型,从训练数据中跳过一天进行计算。对于接下来的每一天,我们使用一个模型,该模型根据在训练中跳过的相应天数的特征进行训练。

第二个验证日预测的独立模型(由作者创建)

在此架构中,数据模型接受训练,与用于进行预测的数据一致。此外,验证分数将代表未知的未来数据预测。这种方法的主要缺点是需要许多模型,这需要更多的时间来准备多个特征集和训练多个模型。

对每个验证日预测使用不同的模型和特征集可能是最方便的方法,但就计算资源而言也是最昂贵的。

典型错误

最后,我想列出一些典型的错误,以及在进行时间序列验证时应该注意和避免的事情:

  • 在预测超过一个时间步长的值时,忘记了之前数据点的间隔,导致验证设置失败。
  • 计算验证集的要素与计算真实/测试数据的要素不同,导致验证估计精度与真实模型性能不匹配。
  • 将未来数据包括在用于训练和/或验证数据的特征中,从而导致数据泄漏和对真实/测试数据的更差的模型性能。示例:在预测一周的第一天时,计算所有工作日的“每周”特征的统计数据。
  • 对比验证中使用的数据点更新的数据点进行训练,这在某些情况下可能会导致数据泄漏,因为训练数据特征实际上包括验证数据目标。

对于如何进行时间序列验证,有几种方案。它们中的每一个都有一些细节,在每种情况下,最佳选择可能取决于问题本身和业务细节/需求。

感谢您的阅读,希望这篇文章能让您对时间序列模型验证以及如何避免一些典型错误有更好的直觉。

Python 中的属性:数据科学家的基础

原文:https://towardsdatascience.com/properties-in-python-fundamentals-for-data-scientists-43071e6be580?source=collection_archive---------23-----------------------

用一个具体的例子来理解基础!

戈兰·艾沃斯在 Unsplash 上的照片

在许多面向对象的编程语言中,通过使用特定的关键字,如 privateprotected ,一个对象或一个类结构中的数据可以被显式地隐藏起来,不被外部访问。这通过不允许从类结构外部访问数据来防止误用。

相比之下,Python 类中的所有属性(存储在类或实例中的数据)都是公开的。因此,您没有对数据访问的显式控制,但是您有两个主要的隐式选项来限制数据访问& Python 类中的操作;

  • 使用命名约定,用一个下划线作为受保护属性的前缀,用两个下划线作为私有属性的前缀。因为它只是一个显示意图的命名约定,所以即使正确应用了命名约定,用户仍然可以从外部访问属性。
  • 使用 Python property 函数或 @property decorator 来定义 setter 和 getter 方法。这些特殊的方法规定了其他人应该如何以可控的方式设置和获取属性。

这篇文章将向你介绍 Python 中属性的基础知识。

让我们编写一个 Python3 代码,其中包含实现 @property decorator 的简单示例:

import pandas as pd*class* **CSVGetInfo**(*object*):
 **""" This class displays the summary of the tabular data contained 
 in a CSV file """***def* **__init__**(*self*, *path*, *file_name*):
  self._path = path
  self._file_name = file_name**@*property*** *def* **path(*self*):**
  """ The docstring for the path property """
  print("Getting value of path")
  return self._path**@path.setter**
 *def* **path(*self*,*value*):**
  if '/' in value:
   self._path = value
   print("Setting value of path to {}".format(value))
  else:
   print("Error: {} is not a valid path string".format(value))**@path.deleter**
 *def* **path(*self*):**
  print('Deleting path attribute')
  del self._path**@*property*** *def* **file_name(*self*):**
  """ The docstring for the file_name property """
  print("Getting value of file_name")
  return self._file_name**@file_name.setter**
 *def* **file_name(*self*,*value*):**
  if '.' in value:
   self._file_name = value
   print("Setting value of file_name to {}".format(value))
  else:
   print("Error: {} is not a valid file name".format(value))**@file_name.deleter**
 *def* **file_name(*self*):**
  print('Deleting file_name attribute')
  del self._file_name*def* **display_summary(*self*):**
  data = pd.read_csv(self._path + self._file_name)
  print(self._file_name)
  print(data.info())if __name__ == '__main__':data_by_genres = CSVGetInfo("/Users/erdemisbilen/Lessons/", 
 "data_by_genres.csv") ***(1)***print(data_by_genres.path)
 ***(2)***print(data_by_genres.file_name) ***(3)***data_by_genres.path="lessons"
 ***(4)***print(data_by_genres.path)
 ***(5)***data_by_genres.path="/Users/"
 ***(6)***print(data_by_genres.path)
 ***(7)***del data_by_genres.path ***(8)***data_by_genres.file_name="datacsv"
 ***(9)***print(data_by_genres.file_name)
 ***(10)***data_by_genres.file_name="data.csv"
 ***(11)***print(data_by_genres.file_name)
 ***(12)***del data_by_genres.file_name**Output:**
air-MacBook-Air: **python PropertyExample.py** ***(1)***Getting value of path
 ***(1)***/Users/erdemisbilen/Lessons/
 ***(2)***Getting value of file_name
 ***(2)***data_by_genres.csv ***(3)***Error: lessons is not a valid path string
 ***(4)***Getting value of path
 ***(4)***/Users/erdemisbilen/Lessons/
 ***(5)***Setting value of path to /Users/
 ***(6)***Getting value of path
 ***(6)***/Users/
 ***(7)***Deleting path attribute ***(8)***Error: datacsv is not a valid file name
 ***(9)***Getting value of file_name
 ***(9)***data_by_genres.csv
 ***(10)***Setting value of file_name to data.csv
 ***(11)***Getting value of file_name
 ***(11)***data.csv
 ***(12)***Deleting file_name attribute

照片由 Waranya Mooldee 在 Unsplash 拍摄

@property Decorator 来定义 Setter 和 Getter 方法

我们可以使用 property() 函数或者 @property decorator 来定义属性。他们做同样的工作,但后者被认为更直观,更容易阅读。

*class* **CSVGetInfo**(*object*):*def* **__init__**(*self*, *path*, *file_name*):
  self._path = path
  self._file_name = file_name

在我们的 CSVGetInfo 类中有 _path_file_name 私有属性。为了控制其他人如何从外部获取和设置这些属性,让我们使用@propertydecorator 来定义属性的 getter 和 setter 函数。

**@*property*** *def* **path(*self*):**
  """ The docstring for the path property """
  print("Getting value of path")
  return self._path

@属性 装饰器被添加到路径( self ) 方法的开始处。这表明 path(self) 方法被用作 getter 函数。

**@file_name.setter**
 *def* **file_name(*self*,*value*):**
  if '.' in value:
   self._file_name = value
   print("Setting value of file_name to {}".format(value))
  else:
   print("Error: {} is not a valid file name".format(value))

同理,@ < property_name >。setter decorator 帮助定义 setter 方法。在我们的例子中, @file_name.setter 被添加到了 file_name( selfvalue ) 方法之前,以将其定义为 setter 方法。注意,在我们的 setter 方法中,我们在将值赋给 _file_name 属性之前对其进行了验证。

**@path.deleter**
 *def* **path(*self*):**
  print('Deleting path attribute')
  del self._path

除了 setter 和 getter 方法,我们可以用@ < property_name >定义 deleter 方法。删除器装饰器。

我们不必为每个属性定义所有三个方法,因为有时属性只能在创建实例时设置。对于这种情况,我们可以通过包含一个 getter 方法来定义只读属性。

 data_by_genres = CSVGetInfo("/Users/erdemisbilen/Lessons/", 
 "data_by_genres.csv") print(data_by_genres.path)
 print(data_by_genres.file_name) data_by_genres.path="lessons"
 print(data_by_genres.path)
 data_by_genres.path="/Users/"
 print(data_by_genres.path)
 del data_by_genres.path

既然我们已经定义了我们的属性,现在我们可以使用它们来设置和获取包含在我们的data _ by _ genders实例中的数据。

请注意,我们可以随意使用 setter 和 getter 方法并修改它们,而不会影响代码结构中的实现。

T S 在 Unsplash 上拍照

关键要点

  • @property decorator 被认为是定义 getters、setters 和 deleters 方法的首选方式。
  • 通过定义属性,我们在类中创建了一个中间层,通过不影响已开发的代码结构来控制其他人如何访问数据。

结论

在这篇文章中,我解释了 Python 中属性的基础知识。

这篇文章中的代码可以在我的 GitHub 库中找到。

我希望这篇文章对你有用。

感谢您的阅读!

预言家和 R:预测航空乘客数量

原文:https://towardsdatascience.com/prophet-and-r-forecasting-air-passenger-numbers-193097184422?source=collection_archive---------35-----------------------

预言者和时间序列预测

来源:来自 Pixabay 的 Kim_R_Hunter 的照片

这是上一篇文章的后续文章,该文章展示了使用 Python 进行时间序列预测,其中构建了一个 Prophet 模型,以便使用 Python 预测航空乘客数量。有问题的数据来自旧金山开放数据。

在本例中,将进行相同的分析,但使用 r。

背景

数据集来源于旧金山国际机场关于航空公司月度客运量统计的报告,该报告可从 data.world(原始来源:旧金山开放数据)获得,如下文参考资料部分所示。

具体来说,对航空公司荷航 (enplaned)调整后的乘客人数进行过滤,作为从 2005 年 5 月到 2016 年 3 月期间的时间序列进行分析。

资料来源:RStudio

使用 Prophet 的目的是:

  • 识别数据中的季节性模式
  • 模型“变化点”——或数据中重大结构变化的时期
  • 使用季节和变点参数预测未来航空乘客数量

在这方面,Prophet 通过识别时间序列中的结构突变,并通过考虑变化点和季节性模式进行预测,可能会产生优于 ARIMA 等更传统的时间序列模型的结果。

模型结构

为了让 Prophet 分析相关数据,必须确保其格式正确,即标题为 ds 的列表示日期,标题为 y 的列表示时间序列值。

将加载 prophet 库,并导入相关数据。

library(prophet)
mydata<-read.csv("klm.csv")ds<-mydata$Date[1:115]
y<-mydata$Adjusted.Passenger.Count[1:115]train<-data.frame(ds,y)
train

在这种情况下定义的 Prophet 模型将自动检测季节模式。但是,我们也想指出模型中的相关变化点。

四个变化点规定如下:

m <- prophet(train, n.changepoints = 4)
m

然后举例说明已确定的变化点:

$changepoints
[1] "2007-06-01 GMT" "2009-04-01 GMT" "2011-03-01 GMT"
[4] "2013-02-01 GMT"

然后,使用该模型预测未来 14 个月,并将预测值与测试集(实际值)进行比较。

future <- make_future_dataframe(m, periods = 14, freq = 'month')
tail(future)forecast <- predict(m, future)
tail(forecast[c('ds', 'yhat', 'yhat_lower', 'yhat_upper')])plot(m, forecast) + add_changepoints_to_plot(m)

这是一个变化点间隔图:

资料来源:RStudio

以下是趋势图和年度构成图:

prophet_plot_components(m, forecast)

资料来源:RStudio

我们可以看到,总体而言,春季和夏季的乘客数量较高,冬季的乘客数量较低。

此外,我们发现,虽然航空旅客人数在 2010 年前呈强劲增长趋势,但此后人数开始缓慢但稳步下降。

使用指标库,可以计算均方根误差,然后与月平均值进行比较:

> ds<-mydata$Date[116:129]
> y<-mydata$Adjusted.Passenger.Count[116:129]
> 
> test<-data.frame(ds,y)
> test
           ds     y
1  2015-02-01  5012
2  2015-03-01  6327
3  2015-04-01 10831
4  2015-05-01 11745
5  2015-06-01 11633
6  2015-07-01 10562
7  2015-08-01 11510
8  2015-09-01 11669
9  2015-10-01 10221
10 2015-11-01  7366
11 2015-12-01  7321
12 2016-01-01  5930
13 2016-02-01  5338
14 2016-03-01  7726
> 
> library(Metrics)
> rmse(forecast$yhat[116:129],test$y)
[1] 587.1803
> 
> mean(test$y)
[1] 8799.357

RMSE 为 587,与月平均值 8799 相比相对较低。这表明我们的 Prophet 模型在预测航空乘客数量方面做得相当好。

然而,值得注意的是,在 R 中选择的变化点与 Python 略有不同。具体来说,R 将其中一个变更点标识为2009 年 4 月,但是 Python 将变更点标识为2009 年 5 月

如果我们用 2009 年 5 月来手动定义 R 中的变更点会怎么样?这会提高预测模型的准确性吗?

m <- prophet(train, changepoints=c("2007-06-01", "2009-05-01", "2011-03-01", "2013-02-01"))

以下是预测结果:

> ds<-mydata$Date[116:129]
> y<-mydata$Adjusted.Passenger.Count[116:129]
> 
> test<-data.frame(ds,y)
> test
           ds     y
1  2015-02-01  5012
2  2015-03-01  6327
3  2015-04-01 10831
4  2015-05-01 11745
5  2015-06-01 11633
6  2015-07-01 10562
7  2015-08-01 11510
8  2015-09-01 11669
9  2015-10-01 10221
10 2015-11-01  7366
11 2015-12-01  7321
12 2016-01-01  5930
13 2016-02-01  5338
14 2016-03-01  7726
> 
> library(Metrics)
> rmse(forecast$yhat[116:129],test$y)
[1] 496.1832
> 
> mean(test$y)
[1] 8799.357

我们现在看到,RMSE 进一步减少到 496,与月平均值 8,799 相比仍然很低。这表明变化点的手动配置导致了更高的预测准确度。

结论

在这个例子中,您已经看到了如何在 r 中运行 Prophet 模型。

具体来说,本文研究了:

  • 如何正确设置时间序列的格式以便使用 Prophet 进行分析
  • 变更点的自动和手动配置
  • 如何使用指标库测量预测准确性

非常感谢您的阅读,非常感谢您的任何问题或反馈。

免责声明:本文是在“原样”的基础上编写的,没有任何担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。

参考

  • cran-r-project . org:prophet
  • data.world:空中交通乘客数据(原始来源:旧金山公开数据)
  • facebook.github.io
  • GitHub:Facebook/prophet

使用 scipy.signal.butter 组装 Prophet/ SARIMA 模型

原文:https://towardsdatascience.com/prophet-sarima-model-ensembling-using-scipy-signal-butter-1fb721eb98ef?source=collection_archive---------33-----------------------

案例研究:通过使用 scipy.signal.butter 集成 FB Prophet & SARIMA 模型,提高每日预测准确性并降低 RMSE

在 Unsplash 上万圣业拍摄的照片

你见过两个伟大的音乐家同时和谐地演奏他们自己的乐器吗?结果比看他们单独比赛要好得多。这是我们预测公司每日收入的方法。虽然有许多模型可以解决这一挑战,但在我们的案例中,集合不同的模型可以产生最准确的结果。

挑战是什么?

我们比较了两种不同的模型:脸书的先知和萨里玛。

Prophet 是脸书创造的一种预测方法,它能够创建每日销售预测。Prophet 的主要好处是可以让你输入和分析周期长的数据(365 天的周期,至少需要 2 年的数据)。对我们来说,不利的一面是,在我们监测其表现的 10 个月里,预言者的预测准确率很低。

SARIMA 是另一种预测方法,在过去的 10 个月里,它对月度预测非常准确。然而,使用 365 天周期的输入数据计算 SARIMA 模型需要大量资源,并且在大多数机器上可能会失败。

什么是 FB 先知?

Prophet 是一个开放的 Python/R 库,用于基于加法模型的时间序列预测,其中非线性趋势符合每年、每周和每天的季节性。它最适用于具有强烈季节效应的时间序列和几个季节的历史数据。

在这个案例研究中,我们将从我公司的数据库中随机抽取一组产品,为模型提供 2.5 年的每日在线销售数据(出于数据匿名的目的)。

让我们加载数据和库:

import pandas as pd
from fbprophet import Prophetdf = pd.read_csv('Random_Products_SALES.csv')
df.head()

我们现在可以运行模型,并为未来 84 天(或 12 周)创建预测:

m = Prophet()
m.fit(df)
future = m.make_future_dataframe(periods=84)
forecast = m.predict(future)
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()

输出的可视化:

fig1 = m.plot(forecast)

萨里玛是什么?

SARIMA 将季节性添加到超参数:自回归(AR)、积分或差分(I)和移动平均(MA)中,以创建一种最受欢迎的单变量时间序列数据预测方法。

让我们使用我们的数据尝试 SARIMA 进行 30 天的周期计算,我们可以从加载库开始:

import warnings
import itertools
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
import matplotlib

我们必须调整数据集以将 ds 设置为索引:

y = df.set_index([‘ds’])

SARIMA 需要趋势元素的配置:

p:趋势自回归顺序。
d:趋势差序。
问:趋势移动平均线下单。

和季节因素:

p:季节性自回归序列。
D:季节性差异订单。
问:季节移动平均订单。
m:单个季节周期的时间步数。

让我们找出 P,D,Q,P,D,Q 任意组合的最佳 AIC:

p = d = q = range(0, 2)
pdq = list(itertools.product(p, d, q))
seasonal_pdq = [(x[0], x[1], x[2], 30) for x in list(itertools.product(p, d, q))]for param in pdq:
    for param_seasonal in seasonal_pdq:
        try:
            mod = sm.tsa.statespace.SARIMAX(y,order=param,seasonal_order=param_seasonal,enforce_stationarity=False,enforce_invertibility=False)
            results = mod.fit()
            print('ARIMA{}x{}30 - AIC:{}'.format(param,param_seasonal,results.aic))
        except: 
            continue

ARIMA(0, 0, 0)x(0, 0, 0, 30)30 — AIC:23755.302023704375
ARIMA(0, 0, 0)x(0, 0, 1, 30)30 — AIC:22717.295494658476
ARIMA(0, 0, 0)x(0, 1, 0, 30)30 — AIC:22483.193953066246
ARIMA(0, 0, 0, 0, 1, 30)30 — AIC:21435.565748542045
ARIMA(0, 0, 0)x(1, 0, 0, 30)30 — AIC:22383.511004484564
ARIMA(0, 0, 0)x(1, 0, 1, 1, 30)30 — AIC:22164.97784280904
ARIMA(0, 0, 0, 0, 0, 0 30)30 — AIC:23131.646912989316
ARIMA(0, 0, 0, 1)x(0, 1, 30)30 — AIC:22281.513637258548
ARIMA(0, 0, 1, 0, 30)30 — AIC:21950.950544055235
ARIMA(0, 0, 1, 1, 30)30 — AIC:21027.22720284167
ARIMA(0, 0, 1, 0, 1, 0, 30)30 — AIC:22291.20146896413
ARIMA(0, 0, 1, 0, 1, 30)30 — AIC:22196.6257289
ARIMA(0, 0, 1, 1, 0, 30)30 — AIC:21140.70479338173 【T】 30)30 — AIC:20701.342066955454
ARIMA(0, 1, 0)x(0, 1, 0, 30)30 — AIC:21322.37708503959
ARIMA(0, 1, 0, 30)30 — AIC:20086.59997264333
ARIMA(0, 1, 0, 0)x(1, 0, 30)30 — AIC:20723.00369864943
ARIMA(0, 1, 0, 0)x(1, 0, 1, 30)30 — AIC:20702.784158890106
ARIMA(0, 1, 0, 0, 0)x(1, 0, 30)30 — AIC:20378.827165586816
ARIMA(0, 1, 1, 0, 0)30 — AIC:2006 30)30 — AIC:21199.715947455446
ARIMA(0, 1, 1) x(0, 1, 1, 30)30 — AIC:20053.5642980343
ARIMA(0, 1, 1, 0, 30)30 — AIC:20605.04579611025
ARIMA(0, 1, 1, 1, 0, 30)30 — AIC:20558.518359458823
ARIMA(0, 1, 1, 1, 0, 30)30
AIC:20318.704493510733 ARIMA(0, 1, 1, 1, 1, 1, 30)30 — AIC:20052.683141618152 ARIMA(1, 0, 0, 0, 0, 30)30 — AIC:2 1, 1, 30)30 — AIC:20153.52687638274
ARIMA(1, 0, 0)x(1, 0, 0, 30)30 — AIC:20711.50592060887
ARIMA(1, 0, 0)x(1, 0, 1, 30)30 — AIC:20713.27590112759
ARIMA(1, 0, 0)x(1, 0, 30)30 — AIC:20352.991087769
ARIMA(1, 0, 0)x(1, 1, 1, 1, 30)30 — AIC:20154.2263185353
ARIMA(1, 0, 0, 0, 0, 0, 30)30 — AIC:21284.027618019507
ARIMA(1, 0, 0, 1, 0, 1, 30)30 — AIC:20579.42678 0, 0, 30)30 — AIC:20603.300227055624
ARIMA(1, 0, 1)x(1, 0, 1, 30)30 — AIC:20580.575096299734
ARIMA(1, 0, 1)x(1, 0, 30)30 — AIC:20294.59890330388
ARIMA(1, 0, 1)x(1, 1, 1, 30)30 — AIC:20052.39937573138
ARIMA(1, 0, 0, 0, 30)30 — AIC:21339.144939704944
ARIMA(1, 0, 0, 0, 1, 0, 30)30 — AIC:20633.488277537876 【T51) ARIMA(1, 0, 0, 0, 0, 30)30 — AIC:21267 0, 1, 30)30 — AIC:20634.703230420448
ARIMA(1, 1, 0)x(1, 1, 0, 30)30 — AIC:20327.151794423327
ARIMA(1, 1, 0, 30)30 — AIC:20104.25721828914
ARIMA(1, 1, 1)x(0, 0, 0, 30)30 — AIC:21260.535839126904
ARIMA(1, 1, 1, 1)x(0, 1, 30)30 — AIC:20554.5720707192
ARIMA(1, 1, 1, 1)x(0, 0, 30)30 — AIC:21194.875022056338
ARIMA(1, 1, 1, 1, 1, 1, 1, 1, 30)30 — AIC:20053.7153

我们还可以打印最佳组合(0,1,1,1,1,1)的统计数据摘要,并创建一个包含同一时间段(84 天)预测的图表:

mod = sm.tsa.statespace.SARIMAX(y,
                                order=(0, 1, 1),
                                seasonal_order=(1, 1, 1, 30),
                                enforce_stationarity=False,
                                enforce_invertibility=False)
results = mod.fit()
print(results.summary().tables[1])

import datetime as dt
pred_uc = results.get_forecast(steps=84)
index_date = pd.date_range(y.index[-1], periods = 84, freq = ‘D’)forecast_series = pd.Series(list(pred_uc.predicted_mean), index = index_date)pred_ci = pred_uc.conf_int()
ax = y.plot(label=’observed’, figsize=(14, 4))
#print(pred_uc.predicted_mean)
forecast_series.plot(ax=ax, label=’Forecast’)
ax.fill_between(forecast_series.index,
 pred_ci.iloc[:, 0],
 pred_ci.iloc[:, 1], color=’k’, alpha=.1)
ax.set_xlabel(‘Date’)
ax.set_ylabel(‘Sales’)
plt.legend()
plt.show()

我们现在可以放大到预测期,黄线代表 SARIMA 的结果,红线代表 FB Prophet 的结果,蓝线代表预测的 84 天中前 43 天的实际销售额。我们可以看到,萨里玛的数字更接近真实值(94%的准确率),但线看起来是平面的。另一方面,Prophet 呈现了一种趋势,这种趋势随着日常销售和谐地变化,但规模不同(61%的准确率)。

在一个完美的场景中,我们希望萨里玛的比例每天都有变化,类似于先知的模型:

什么是黄油?

scipy.signal.butter 是 Python 上的一个库,用于过滤信号,我们将使用频率 11(我尝试了其中的几个,但我想保持这篇文章简短),我们将把这个过滤器应用于 prophet 的结果(prophet_df)。

然后,该过滤器的输出将被添加到 SARIMA 的结果中,并与真实数据(data_df)进行比较。

filter_freq = 11
sos = signal.butter(10, filter_freq, 'high', fs=91, output='sos')
filtered = signal.sosfilt(sos, list(prophet_df.yhat))

sarima_df['ensembled'] = sarima_df.sales + filtered

ensembled_list = np.array(sarima_df.loc[(sarima_df['date'] >= data_df['Date'].iloc[0]) & ((sarima_df['date'] <= data_df['Date'].iloc[-1])),'ensembled'])

real_list = np.array(data_df.Real

结果

如下图所示,萨里玛和先知的组合比萨里玛(更好的 RMSE)更符合真实趋势,比萨里玛或先知(95%)更准确:

最终注释

像新冠肺炎这样的特殊情况迫使我的公司调整每日预测,以提高准确性并减少 RMSE。这并不意味着这种组合将提高您的特定数据集的性能,如果您的 SARIMA 月度数据更准确,但 Prophet 显示更好的每日变化,这可能会有所帮助。

当你试图将你的预测拟合到如此接近一个特定的时间段时,你也应该考虑到过度拟合的风险。我做了 6 个月同样的练习,尝试了不同周期的萨里玛和不同频率的黄油,以确保我选择的组合对所有月份都有益。

马里奥·卡马戈
mario.andres.camargo@gmail.com

随机网络稳定性

原文:https://towardsdatascience.com/proposing-a-new-effect-of-learning-rate-decay-network-stability-c4b4ef3bae5e?source=collection_archive---------54-----------------------

揭示学习率是随机梯度下降中的一种正则化形式

摘要

现代文献表明,学习速率是调整深度神经网络的最重要的超参数。[1]如果学习率太低,梯度下降在一个长而陡的山谷或鞍点会很慢。学习率太高时,梯度下降有超过最小值的风险。[2]已经开发了自适应学习速率算法,以考虑动量和累积梯度,从而对非凸优化问题的这些情况更加稳健。[3]

一个常见的主题是,在一定数量的时期后,通过允许权重设定为更精确的尖锐最小值,衰减学习率可以帮助模型收敛到更好的最小值。这个想法是,在一个给定的学习速率下,你可能会不断地错过实际的最小值。因此,通过降低学习率,我们允许我们的权重固定在这些尖锐的最小值上。

随着深度学习社区不断改进和建立调整学习率的新方法,如循环学习率计划,我相信我们更深入地了解学习率对我们的优化问题有什么影响是很重要的。

在这项研究中,我想提出一个被忽略的学习率衰减效应:网络稳定性。我将在不同的环境中实验学习率的衰减,并展示网络稳定性是如何产生的,以及网络稳定性如何在训练过程中使子网受益。

我认为学习率衰减对优化问题有两个影响:

  1. 允许重量停留在更深的最小值
  2. 在训练过程中提供正向传播激活和反向传播损耗信号的网络稳定性

首先,我想通过一些数学符号来建立我所说的网络稳定性。

然后,我将通过在 CIFAR-10 数据集上对 ResNet-18 架构进行的实验来展示这两种影响是如何发生的。

理论

什么是网络稳定性?更重要的是,它如何影响损失情况?

让我们从概率的角度来看待我们的损失情况。

对于单个例子 x,给定网络 w 的当前权重,我们可以计算损耗 L,

从所有图像空间上的分布 D 中选取一个例子 x。

然后,我们可以从概率上来看损失情况

对于给定的一组权重 w,为单个图像 x 计算的损失函数通过反向传播产生每个权重的梯度阵列,即,

我们从上面的概率损失图中观察到这个梯度的概率是相应的

使用批量样本对给定数据集执行随机梯度下降的过程可以被视为通过点估计在概率损失场中导航。

在一批图像中,权重保持不变。在时间步长 t 的每次更新都经过以下条件场景,

通过对足够大的 n 批进行平均,我们希望

因此,对于给定的一组权重,我们采用的梯度步长是一个预期步长。

然后,在以下条件下执行每个步骤 t:

通过降低网络上的学习速率,我们减少了 w 的变化。

现在,批量梯度下降的后续迭代在与前一次迭代更加相似的概率损失场上操作。这在训练期间在我们的网络中加强了某种程度的稳定性,对于足够小的 w 变化,

通过降低学习率,我们强制随机梯度下降在权重上的更严格的条件概率上操作,而不是在权重机制和它们相应的条件概率场之间跳跃。这就是我对网络稳定性的看法。

学习率衰减的经典观点是能够收敛到尖锐的极小值,这是对随机过程的过度简化,并将损失情况视为常数。

从概率的角度来看,我建议将学习率视为随机难题的一部分。我们应该随机地对待随机梯度下降的过程。

我对这一概率过程中稳定性影响的假设是深层和早期两方面的:

  1. 当深层经历前向传播信号的不稳定性时,它们被迫推广到变化的收敛的早期子网。当我们引入早期层的稳定性时,深层可以依靠稳定的正向传播信号来发展稳定的等级特征。
  2. 当早期层经历反向传播损耗信号的不稳定性时,它们不能获得损耗的清晰静态图像。相反,随着梯度下降的每次迭代,通过深层呈现给他们的损失图像发生变化。当我们引入更深层的稳定性时,早期的层可以通过 SGD 更有效地收敛到一个解决方案。

实验

对于我们的实验,我们将在 CIFAR-10 数据集上考虑 ResNet 架构。

通常,在一定数量的时期之后应用学习率衰减,这结合了稳定到急剧最小值和提供网络稳定性的效果。

在一系列的 4 个实验中,我想单独分开这些影响,展示它们是如何结合的,并最终表明它们都是学习速度衰减的一部分。

实验 A:没有网络稳定性的尖锐极小值

在我们的第一个实验中,我们将研究学习速度衰减对单个模块的影响。

ResNet 架构由大小为 64、128、256 和 512 的四个滤波器模块组成。

每个尺寸为 64、128、256、512 的滤光块都有不同的颜色[4]

在这个实验中,我们将训练一个前哨模型,其中学习率在整个网络范围内衰减,然后是只在某个过滤器块中衰减学习率的模型。这个实验应该揭示单个块在多大程度上稳定到更尖锐的最小值,以及它在不给网络的其余部分增加更多稳定性的情况下这样做的能力,因为我们为网络的其余部分保持更高的学习速率。

实验 B:没有尖锐最小值的网络稳定性

在第二个实验中,我们将研究冻结块的效果,以加强稳定性,同时在未冻结的块上保持恒定的学习速率。通过保持一个恒定的学习速率,我们不会引入陷入更尖锐的最小值的影响。我们希望在冻结块时看到更快的收敛以减少损失,就像我们对网络范围的 LR 衰减所做的那样。

实验 C:结合稳定性和尖锐的最小值

在本实验中,我们将结合上述两个实验的效果,对单个模块采用学习速率衰减,然后完全冻结其他模块。这将允许腐烂的石块沉淀成更尖锐的极小值,然后通过冻结其他石块来进一步获得稳定性的好处。

实验 D:无复合效应

在这个实验中,我们将衰减整个网络的学习速率,然后尝试通过冻结除一个块之外的所有块来引入稳定性效应。如果网络范围的 LR 衰变没有发现进一步的稳定性效应,我们已经有效地证明了 LR 衰变替代并提供了由冻结效应实现的增益。

实验 A:尖锐的最小值

我们将培训以下 5 个模型:

  1. 具有逐步 LR 衰减的前哨模型

LR 从 0.1 开始。在时期 60 衰减到 0.01,然后在时期 120 衰减到 0.001。

2.滤波器模块 64 LR 衰减

3.滤波器模块 128 LR 衰减

4.滤波器模块 256 LR 衰减

5.滤波器模块 512 LR 衰减

我们的假设是,每一个区块应该能够解决一些较低的最小值。随着学习率的下降,我们应该会看到训练损失的减少,并且 top-1 验证的准确性会增加。

结果如下:

放大前 1 名训练准确度图和前 1 名验证准确度图,

我们观察到以下情况:

  • 在我们的前哨模型中,60 个时期和 120 个时期的 LR 衰减允许模型收敛到训练集上的较低损失和验证集上的较高精度。
  • 在我们的滤波器块衰减模型中,我们看到 LR 衰减点有助于滤波器块进入更深的最小值。
  • 前哨模型收敛到一个稳定的验证精度,在 SGD 迭代中的方差小于滤波器衰减对应模型。

从该实验中,我们看到每个块上的 LR 衰减能够有助于潜在地将权重设置为更尖锐的最小值。前哨模型显示了由于整个网络学习速率的衰减而引起的网络稳定性的特性。验证准确度的高方差表明,对于其他块,将学习速率保持在 0.1 会导致我们学习的网络的逐时不稳定性。

实验 B:网络稳定性

对于这个实验,我们保持任何正在训练的块的学习率为 0.1,没有衰减。这样,我们就避免了由于陷入更尖锐的极小值而模糊我们的结果。

为了模拟网络稳定性的影响,我们将在每个实验中冻结除一个以外的所有滤波器模块。这应该有助于加强我们前面提到的网络稳定性的属性,

我们将培训以下 5 个模型:

  1. 无 LR 衰减的基线模型
  2. 用 LR 0.1 过滤块 64,其他块在时期 60 被冻结
  3. 用 LR 0.1 过滤块 128,其他块在时期 60 被冻结
  4. 用 LR 0.1 过滤块 256,其他块在时期 60 被冻结
  5. 用 LR 0.1 过滤块 512,其他块在时期 60 被冻结

通过比较网络不同深度的影响,我们可以确定稳定效应是一种网络范围的效应。它不应该只对较深的区块或较早的区块更好。

我们的假设是,持续训练的每个块应该获得网络稳定性的好处,并在下面的情况下收敛到更好的最小值

其中 jk 是给定滤波器块中的权重指数。

我们的期望是每个实验都应该取得比基线更好的结果。此外,所得到的网络应该具有更稳定的解决方案,在随机梯度下降的时期上具有更低的训练/验证损失和准确性的方差。

结果如下:

放大前 1 名验证准确性图表,

通过简单地在时期 60 冻结网络的其余部分,我们看到验证准确性的明显提高。

没有混淆我们的结果与尖锐的最小值的影响,我们在这里建立了网络稳定性是收敛的一个重要因素。

此外,我们对这些模型的验证精度高于实验 A 模型的精度。这表明,在帮助网络收敛方面,稳定性可能比尖锐的极小值效应起着更大的作用。

实验 C:结合尖锐最小值和网络稳定性

在这个实验中,我们希望证实,在没有网络范围的 LR 衰减的情况下,我们能够组合急剧最小值和网络稳定性的影响。我们将通过在时期 60 仅衰减给定块的学习速率来做到这一点,然后在时期 90 冻结网络的其余部分。我们将培训以下 6 个模型:

  1. 无 LR 衰减的基线模型
  2. 具有 LR 衰减的前哨模型
  3. 用 LR 衰减过滤块 64,其他块在时期 90 被冻结
  4. 用 LR 衰减过滤块 128,其他块在时期 90 被冻结
  5. 用 LR 衰减过滤块 256,其他块在时期 90 被冻结
  6. 用 LR 衰减过滤块 512,其他块在时期 90 被冻结

结果如下

放大前 1 名训练准确度图和前 1 名验证准确度图,

通过将 LR 衰减的效果组合在单个块上,然后冻结网络的其余部分,我们复制了具有网络范围 LR 衰减的前哨网络的特征。正如所料,网络范围的 LR 衰减模型仍然比我们的滤波器块模型表现更好。然而,我们的组合方法能够很好地模拟 LR 衰减的影响,就稳定性、有效性和训练准确性/损失而言。

当在时期 90 ( 3.5 * 10⁴迭代)应用块冻结时,我们使得深度滤波块模型 256 和 512 能够收敛到 100%的训练精度。继续训练早期块的模型,如 64 和 128,没有达到相同的训练精度水平,并且它们在验证集 top 1 精度上击败了其他模型。这给了我们一些证据,表明随着训练的进行,过度拟合在更深的层中发生得更多。

如果我们看看验证损失,这也向我们展示了网络深度和过度拟合之间的有趣关系。

在前哨站模型的 LR 在第 60 纪元衰减之后,验证损失处于最低。随着训练进展超过时期 60,训练集上的损失减少,但是与我们预期的相反,对于网络范围的衰减模型,验证损失增加,而验证前 1 名的准确度也增加。

我们使用交叉熵损失来训练我们的模型,这意味着对于增加的损失,我们必须观察以下两种情况之一:

  1. 正确预测的可信度较低
  2. 对错误预测更有信心

由于训练损失持续减少,而训练前 1 名的准确性已经达到 100%,这表明该模型通过输出更有把握的预测来最小化训练损失。

我们会认为有把握的预测是过度拟合的,不能很好地推广到验证集。然而,验证前 1 名的准确性随着训练而增加,但是我们注意到验证前 5 名的准确性降低。这意味着随着训练随着网络范围的 LR 衰减而进行,当模型是错误的时,在预测的前 5 个标签中找到真正的标签会更加困难。这可以归因于其他标签的信心增强,因此验证损失增加。

看一下块冻结模型,过滤块中更深的层被连续训练,像在 256 或 512 中,我们观察到与前哨模型相同的过度拟合效应。随着训练的进行,这些模型增加了它们的验证损失,并且收敛到与网络范围的 LR 衰减模型相似的验证损失。

然而,在早期层被训练而较深层被冻结的滤波器块模型中,如模型 64 或 128 中,我们观察到验证损失没有以同样的方式随着训练而增加。前 5 名的验证准确性也没有受到影响。

当我们冻结早期层时,保持训练的深层能够更好地适应来自早期子网的稳定信号。这表明了高学习率实际上是一种通过给随机过程添加噪声的正则化形式。通过设置权重转移的速率,我们定义了我们转移损失的条件概率云的多样性。从我们的实验中,我们看到,在深层冻结时保持训练的早期层在过度适应训练集的复杂性方面有更艰难的时间。它们对验证集损失的改善最大。

当我们冻结深层时,早期层在验证损失和准确性方面立即改善最多。这表明早期层具有反向传播损耗的稳定图像以收敛到更好的特征是多么重要。

这两个观察都支持我在摘要中详述的关于早期地层、深层和稳定性之间关系的两个假设。

实验 D:无复合效应

在我们的最后一个实验中,我想要展示的是,一旦我们将 LR 衰减应用到整个网络,稳定性就不再能够通过冻结块来实现。这将表明 LR 衰变产生了这些稳定性效应,而进一步冷冻实际上没有任何有益的效应。

我们将培训以下 6 个模型:

  1. 具有 LR 衰减的前哨模型
  2. 过滤跨网络具有 LR 衰减的块 64,其他块在时期 140 被冻结
  3. 过滤跨网络具有 LR 衰减的块 128,其他块在时期 140 被冻结
  4. 过滤跨网络具有 LR 衰减的块 256,其他块在时期 140 被冻结
  5. 过滤跨网络具有 LR 衰减的块 512,其他块在时期 140 被冻结

在时期 140,在我们应用网络范围的 LR 衰减之后,我们应用块冻结。如果网络稳定性是 LR 衰减的结果,那么块冻结的收益将不再是可实现的。

结果如下:

正如预期的那样,我们在我们的模型中没有看到 epoch 140 的额外增益。因此,我们有效地证明了网络稳定性的影响确实是由学习率衰减引起的。

结论

我们发现学习率衰减存在两种效应:

  1. 在优化领域达到更清晰的极小值
  2. 前向传播信号和后向传播信号的稳定性

不稳定源于不断的变化。梯度下降更新每批的所有权重,有效地将噪声添加到向前和向后传播的信号中。通过冻结层和提高准确性,我们显示了网络稳定性的优点,作为学习率衰减的积极影响。

按照这种观点,更高的学习率是一种正规化的形式。降低学习速率类似于降低模拟退火优化器的温度。这影响了概率损失情况。与吉洪诺夫正则化影响先验概率以支持较小权重的方式相同,我们选择的学习率应用影响随机优化过程中可发现的最小值的先验概率。

引文

[1] Smith,Leslie N .“训练神经网络的循环学习率” 2017 年 IEEE 计算机视觉应用冬季会议(WACV) 。IEEE,2017。

[2] Dauphin,Y. N .等人,“RMSProp 和非凸优化的平衡自适应学习速率”。arXiv 2015。” arXiv 预印本 arXiv:1502.04390

[3]古德费勒、伊恩、约舒阿·本吉奥和亚伦·库维尔。深度学习。麻省理工学院出版社,2016 年。

[4]李、雍、曾、、张、解、戴、安波、阚、美娜、山、、陈、西林.(2017).KinNet:用于亲属关系验证的由细到粗的深度度量学习。13–20.10.1145/3134421.3134425.

各种机器学习算法的利弊

原文:https://towardsdatascience.com/pros-and-cons-of-various-classification-ml-algorithms-3b5bfb3c87d6?source=collection_archive---------1-----------------------

来源:Pixabay

机器学习中有很多分类算法。但是曾经想知道哪种算法应该用于什么目的和什么类型的应用。如果是,那么请阅读分类中使用的各种机器学习算法的利弊。我还列出了它们的用例及应用。

SVM(支持向量机)

优点

  1. 在更高维度表现出色。在现实世界中有无限的维度(不仅仅是 2D 和 3D)。例如图像数据、基因数据、医学数据等。有更高的维度,SVM 在这点上很有用。基本上,当特征/列的数量较高时,SVM 做得很好

2.类可分时的最佳算法。(当两个类的实例可以很容易地用直线或非线性分开时)。为了描述可分离的类,让我们举一个例子(这里以线性分离为例,类也可以是非线性可分离的,例如通过画一条抛物线等)。在第一张图中,你很难判断 X 是属于第一类还是第二类,但是在第二种情况下,你很容易判断出 X 属于第二类。因此,在第二种情况下,类是线性可分的。

首先是不可分的类,其次是可分的类。

3.离群值影响较小。

4.SVM 适合极端情况下的二元分类。

缺点:

1.慢:对于较大的数据集,需要大量的时间来处理。

2.重叠类的性能不佳:在重叠类的情况下性能不佳。

3.选择合适的超参数很重要:这将考虑到足够的泛化性能。

4.选择合适的内核函数可能很棘手。

应用:

单词包应用(许多特征和列)、语音识别数据、图像分类(非线性数据)、医学分析(非线性数据)、文本分类(许多特征)

朴素贝叶斯

赞成者

  1. 实时预测:非常快,可以实时使用。

2.可扩展大型数据集

3.对无关特征不敏感。

4.在朴素贝叶斯中有效地完成了多类预测

5.高维数据的良好性能(特征数量大)

缺点

  1. 特征的独立性不成立:基本的朴素贝叶斯假设是每个特征对结果做出独立且相等的贡献。然而,这个条件在大多数情况下并不满足。

2.不好的估计量:【predict _ proba 的概率输出不要太认真。

3.训练数据应能很好地代表总体:如果某个类别标签和某个属性值没有同时出现(例如 class="No ",shape = " govern "),那么后验概率将为零。因此,如果训练数据不代表总体,朴素贝叶斯就不能很好地工作。(这个问题可以通过平滑技术来解决)。

应用:

朴素贝叶斯用于文本分类/垃圾邮件过滤/情感分析。它用于文本分类(它可以对多个类别进行预测,并且不介意处理不相关的特征)、垃圾邮件过滤(识别垃圾邮件)和情感分析(在社交媒体分析中,用于识别积极和消极的情感)、推荐系统(用户接下来会购买什么)

逻辑回归

优点

  1. 简单的实现

2.有效

3.不需要要素缩放:不需要缩放输入要素(也可以处理缩放后的要素,但不需要缩放)

3.不需要调整超参数。

缺点

  1. 非线性数据的性能不佳(例如图像数据)

2.不相关和高度相关特征表现不佳(使用博鲁塔图去除相似或相关特征和不相关特征)。

3.不是很强大的算法,很容易被其他算法超越。

4.高度依赖数据的正确呈现。所有重要的变量/特征都应该被识别,以使其工作良好。

应用:

任何分类问题,最好是二进制的(它也可以执行多类分类,但二进制是首选)。例如,如果你的输出类有两个结果,你可以使用它;癌症检测问题,学生是否会通过/失败,在客户贷款的情况下违约/不违约,客户是否会流失,电子邮件是否是垃圾邮件等。

随机森林

优点:

1.随机森林可以去相关树。它挑选训练样本,并给每棵树一个特征子集(假设训练数据是[1,2,3,4,5,6],因此一棵树将得到训练数据的子集[1,2,3,2,6,6]。注意,训练数据的大小保持不变,两个数据都具有长度 6,并且特征‘2’和特征‘6’在给予一棵树的随机采样的训练数据中重复。每棵树都根据它所具有的特征进行预测。在这种情况下,树 1 只能访问特征 1、2、3 和 6,因此它可以基于这些特征进行预测。其他一些树将访问特征 1、4、5,因此它将根据这些特征进行预测。如果特征高度相关,那么问题可以在随机森林中解决。

2.减少误差:随机森林是决策树的集合。为了预测特定行的结果,随机森林从所有树中获取输入,然后预测结果。这确保了树的单个误差被最小化,并且总体方差和误差被减少。

3.在不平衡数据集上表现良好:也可以处理不平衡数据中的错误(一个类是多数,另一个类是少数)

4.海量数据的处理:可以处理变量维度更高的海量数据。

5.很好的处理缺失数据:可以很好的处理缺失数据。因此,如果你的模型中有大量的缺失数据,它会给出很好的结果。

6.离群值的影响很小:由于最终结果是通过咨询多个决策树得出的,因此离群值的某些数据点不会对随机森林产生很大影响。

7.没有过拟合的问题:在随机森林中只考虑特征的子集,最终的结果取决于所有的树。所以泛化多,过拟合少。

8.对提取特征重要性有用(我们可以用它来进行特征选择)

缺点:

1.特性需要有一些预测能力否则它们不会工作。

2.树的预测需要不相关

3.以黑匣子的形式出现:很难知道发生了什么。您最多可以尝试不同的参数和随机种子来改变结果和性能。

应用:

信用卡违约,欺诈客户/不是,容易识别病人的疾病与否,电子商务网站的推荐系统。

决策树

优点

1.不需要数据的标准化或缩放

2.处理缺失值:缺失值影响不大。

3.便于向非技术团队成员解释

4.轻松可视化

5.自动 特征选择:无关特征不会影响决策树。

缺点

1.容易过度拟合。

2.对数据敏感。如果数据稍有变化,结果可能会发生很大变化。

3.训练决策树所需的时间更长。

应用:

确定产品的购买者,预测违约的可能性,哪种策略可以使利润最大化,找到成本最小化的策略,哪些特征对吸引和留住客户最重要(是购物的频率,是频繁的折扣,是产品组合等),机器的故障诊断(持续测量压力、振动和其他措施,并在故障发生前进行预测)等。

XGBoost

赞成者

1.需要较少的特征工程(不需要缩放、归一化数据,也可以很好地处理缺失值)

2.可以求出特征重要性(它输出每个特征的重要性,可以用于特征选择)

3.快速解读

4.离群值影响最小。

5.很好地处理大规模数据集

6.执行好速度

7.良好的模特表现(赢得大部分卡格尔比赛)

8.不易过度拟合

缺点

1.难解读,可视化难

2.如果参数调整不当,可能会出现过拟合

3.由于超参数太多,更难调整

应用

任何分类问题。如果您有太多的要素和太大的数据集,存在异常值,有许多丢失的值,并且您不想进行太多的要素工程,这将非常有用。它赢得了几乎所有的比赛,所以这是一个你在解决任何分类问题时必须牢记在心的算法。

K 近邻

优点

1.简单的理解和实现

2.没有关于数据的假设(例如,在线性回归的情况下,我们假设因变量和自变量线性相关,在朴素贝叶斯中,我们假设特征彼此独立,等等。,但是 k-NN 对数据不做任何假设)

3.不断进化的模型:当它暴露于新数据时,它会改变以适应新的数据点。

4.多类问题也可以解决。

5.一个超参数: K-NN 在选择第一个超参数时可能会花费一些时间,但在此之后,其余的参数会与之对齐。

缺点

1.慢速用于大型数据集。

2.维数灾难:在具有大量特征的数据集上效果不佳。

3.数据绝对必须的缩放

4.不适用于不平衡数据。因此,在使用 k-NN 之前,要么欠采样多数类,要么过采样少数类,并拥有一个平衡的数据集。

5.对异常值敏感。

6.无法很好地处理缺失值

应用:

当数据集较小且具有较少数量的特征时,可以将其用于任何分类问题,因此 k-NN 花费的计算时间较少。如果您不知道数据的形状以及输出和输入相关的方式(类是否可以由直线、椭圆或抛物线等分隔)。),那就可以用 k-NN 了。

结论

随着模型的出现,它们变得越来越先进。因此,如果你严格从性能的角度来看一个模型,那么通常是神经网络、XGBoost 等。是最好的模型,因为它们相对较新。然而,不同的模型更适合不同的数据。

例如,如果特征是高度独立的,那么朴素贝叶斯将非常有用。如果有太多的要素并且数据集是中等大小的,那么 SVM 就不错。如果因变量和自变量之间存在线性关系,那么线性回归、logistic 回归、SVM 都是好的。如果数据集很小,并且您不知道因变量和自变量之间的关系,那么您可以使用 k-NN。因此,在你决定使用哪种最大似然算法之前,你必须了解并分析数据。如果您无法专注于一种机器学习算法,那么您可以评估所有模型,并在训练和测试集上检查它们的准确性,然后最终确定一个模型。

用机器学习探测洛杉矶的后院房屋

原文:https://towardsdatascience.com/prospecting-las-backyard-houses-with-machine-learning-8fdc191e1cf?source=collection_archive---------25-----------------------

一个端到端的数据科学管道,解释了如何使用公开可用的 AirBnB 数据和 LA Geo 数据集来学习预测后院房屋的夜间收入。你可以在 YouTube 上找到我解释这个项目的视频。你可以在GitHub上找到这个项目的文件。你可以在Heroku找到我的测试版应用 YIMBYme。

后院房屋预制单元承蒙封面

动机

这个项目着眼于如何用一个由数据科学驱动的工具来影响洛杉矶的住房(因为我真的很想尽快租房/买房)。

很多 LA 房主都有这样的疑问: 该不该建后院房子?

LA Mayor Garcetti 最近签署了许多简化后院房屋建设的措施,反映出目前这些房屋通常是出租的,通常是供家庭成员使用。然而,一些出租作为被动收入,特别是对年轻家庭或老年人。我想知道这些房子在哪里能赚大钱。

目标

创建一个工具来确定:

  • 后院房子的潜在收入
  • 它在房主后院的可行性

工具演示

房主只需输入他们的地址:

Anupama Garla 制作的工具主页模型,带有来自住宅的法恩斯沃思住宅的背景图像

并输出他们潜在后院房屋的预期夜间收入、单元类型和容量:

Anupama Garla 的夜间收入预测输出模型

Anupama Garla 输出的单元类型和批量生产能力,以及加州大学洛杉矶分校城市实验室 ADU 指南的样本计划

方法学

为了进行这种预测,我首先建立了一个预测房产收入的模型。然后,我建立了一个可以容纳任何大小后院房子的房产数据库。然后,我使用迁移学习将我的后院房屋数据库插入到我的价格预测模型中,以获得每个房产的潜在后院房屋的预测夜间收入。

下面将详细介绍数据管道。

Anupama Garla 的方法图

第一部分:建立模型预测夜间收入

我用 AirBnB LA 的数据来代表收入。这个数据集有大约 100 个特征,我选择了最重要的设施以及位置和大小细节。我还将我的数据集限制为超级主机状态,以确保我的目标特性的质量:夜间价格。

为了评估位置质量,我比较了该物业与各种地理要素数据集的接近程度,包括文化景点、由地铁站和高速公路入口组成的交通、公园,以及最重要的,最近的房屋销售价格中位数。

平均来说,房子是 142 美元/晚,我的模型是 51 美元。

第二部分:生成潜在后院房屋数据库

为了确定潜在的后院房屋,我使用了洛杉矶县评估办公室的地块数据,这些数据提供了地址、坐标、地块面积和该地产上主要房屋的面积。

为了找到可以容纳后院房屋的房产以及该房屋的大小,我根据洛杉矶市政后院房屋建筑规范处理了地块数据。该法规定义了地产线的 5 '后退,现有房屋的 10 '后退,将一块土地的整个可建筑面积限制在 50%,并将后院房屋的最大面积设定为 1200 平方英尺或主房屋面积的一半。

我确定了 160 万块土地,这些土地可以根据最大面积合法建造一到三间卧室的后院房屋。

这些地块创建了我的后院房屋数据库,其中包括查找地址、卧室和浴室的数量以及经度和纬度坐标位置。我把这个后院房子数据库插入我的模型来预测他们的收入。

特征工程

我用这个模型来确定哪个后院的房子会赚更多的钱。我发现越密集、浴室越多、越稀有的房子越有价值。我设计了密度和稀有特征。

三大预测特征图片由 Anupama Garla 提供

密度特征偏爱声称可以容纳很多人的房产,实际上为这些人提供了很多空间,卧室和浴室的数量证明了这一点。浴室的数量是原始数据,它本身就表明了容量,但也表明了建造年份,因为越老的房子往往浴室越少。稀有特征偏好高价值位置的房产——由最近的房屋销售价格中值确定,如果它们在该位置是唯一的——由该社区中具有相同数量卧室可供出租的房产数量确定。

结论

对于一个住在有空间容纳一个大单元的高价值社区的个人来说,出租你的后院的收益会更高。对于一个居住在空间较小、不太令人向往的社区的人来说,你的收益会更低。然而,仍然会有可量化的收益。

使用我们的后院房屋数据库,并通过 Tableau 将其可视化,我们可以确定潜在后院房屋市场的三个不同细分市场——高、中、低价值。

由 Anupama Garla 划分为三层的预期洛杉矶后院住宅区地图

许多不同的初创企业已经进入后院房屋建筑领域,并可能在该数据集中找到用途。通常,后院住宅项目的生命周期有几个阶段,从最初的融资到最终出租。虽然单个建筑师会提供一个非常具体的设计,只涵盖生命周期的一部分,价格高度可变,但进入该领域的初创公司正在简化建筑流程,并提前提供价格。例如,Cover 旨在通过房主最少的努力生产一个高端后院房屋,在 3 天内提供他们工厂建造房屋的 3 个定制设计,包括可行性、设计和建造的所有专业知识。而 La Más 为没有资金的房主提供服务,并提供端到端的资金,此外还设计和建造后院房屋,以换取向无家可归者或第 8 节住房券持有者出租至少 5 年的承诺。

Anupama Garla 的后院住宅的生命周期与后院住宅的启动有关,图片由 Propel Studio 、 COVER 和 La Más 提供

对于 COVER 这样的初创公司来说,这个高价值物业密集的地区是一个值得关注的好市场。对于像 La Más 这样的非盈利初创企业来说,这个低价值物业密集的地区将是一个值得关注的好市场。1.最后,中等价值的财产介于两者之间,难以预料。对于根据特定需求定制解决方案的个人建筑师来说,这可能是一个很好的市场。

不同初创企业发展接受型客户群的战略方法阿努帕马·加拉(Anupama Garla)的作品,带有由画出的圆圈图像,涵盖、 Propel 工作室和 La Más

这个由机器学习驱动的数据库对于 ADU 的初创企业和房主来说都是一个有用的工具。我也从规划的角度看到了潜力。该城市能够针对城市不同区域的不同人群调整其激励措施。

通过 Python 3 数据类中的输入验证来保护您的 API

原文:https://towardsdatascience.com/protect-your-api-via-input-validation-in-python-3-data-class-edefa5e280df?source=collection_archive---------9-----------------------

将 json 输入反序列化为 Python 3 数据类,并验证输入值以保护您的 API

照片由 Masaaki Komori 在 Unsplash 上拍摄

介绍

在构建 web API 时,我们不可避免地需要保护它,否则它可能会被恶意用户利用。一种方法是对 API 接收的请求体进行输入验证。如果这是一个错误的输入,例如,我们的 API 期望一个电子邮件地址,但是却给了一个地址,那么,我们的 API 将(或者应该)拒绝该数据并返回一个状态代码400 — BAD REQUEST

服务器端的输入验证必须在客户端的输入验证之上完成。原因是来自客户端的数据不可信,因为在数据到达服务器之前,任何事情都可能发生,例如,中间人(MITM)攻击。此外,请记住,请求可能来自任何地方,例如,Postman 或 curl,而不仅仅是来自您的 web 和/或移动应用程序。

你会学到什么

您将学习如何使用 Python 3 的dataclass对 API 请求体建模,并使用marshmallow-dataclass包对其进行输入验证。

我们将在本教程中介绍的用例是一个 API,它接受一个电子邮件地址作为输入,如果用户数据库中不存在该电子邮件地址,它将基于该电子邮件地址创建一个新的用户帐户。

本教程的系统详细信息:

  • Python: 3.8.1
  • 皮普:19.3.1
  • 虚拟人:16.7.9
  • 马科斯·卡特琳娜:10.15.2

安装依赖项

需要安装两个依赖包:

  • 棉花糖-数据类:7.2.1
  • dataclass-json: 0.3.6

让我们继续将它们安装在您的 Python 项目的虚拟环境中。

使用 pip 安装 marshmallow-dataclass

编写请求体模型

如前所述,我们将使用 Python 3 的dataclass来建模我们的 API 请求体。输入是一个电子邮件地址。继续创建基本的dataclass,不需要任何输入验证。

没有输入验证的初始数据类

接下来,我们还将添加@dataclass_json decorator,以便能够将 json 请求体反序列化到CreateUser数据类。

创建用 dataclass_json 修饰的用户

现在,如果我们试图向CreateUser传递任何类型的输入,它都会接受。

示例显示 CreateUser 接受任何类型的输入

这不太好,是吗?😰

让我们在下一节看看如何改进它。

添加输入字段验证

我们将为CreateUser数据类的emailAddress字段添加一个验证器。

使用电子邮件地址验证创建用户

现在,继续尝试通过传递不同的输入值来创建CreateUser的对象。

CreateUser 对象仍然接受任何类型的输入

不幸的是,我们的CreateUser数据类仍然接受任何类型的输入。😦

使用模式去序列化和验证

输入验证的工作方式是通过一个代表我们感兴趣的dataclass模式。在前面的部分中,我们还没有创建模式,这就是验证没有工作的原因。

为了创建CreateUser的模式,我们需要使用marshmallow_dataclass

添加 CreateUserSchema

同样,我们初始化一个CreateUser对象的方式需要调整,以利用我们刚刚生成的CreateUserSchema模式。

创建 CreateUser 对象的模式示例

我们的输入验证与CreateUserSchema一起工作。这样,我们的 API 将受到保护,不会收到不是有效电子邮件地址的垃圾输入。🙂

使用模式进行输入验证的更简单方法

最后,我想向您展示我们如何从dataclass中自动创建模式。

为此,我们需要使用由marshmallow_dataclass包提供的@dataclass装饰器,它的行为就像 Python 3.x 的标准dataclasses库中的@dataclass装饰器一样。

让我们修改我们的CreateUser数据类并删除CreateUserSchema,因为它的创建将是自动的。

使用 marshmallow_dataclass 自动创建模式

让我们看看如何使用修改后的CreateUser数据类创建一个CreateUser对象。

使用自动化模式创建 CreateUser 对象的示例

我们的代码现在简单多了,输入验证也像预期的那样工作。我们成功了,伙计们!💪

照片由 Unsplash 上的雅弗桅杆拍摄

通过 AWS 控制台用户更改的实时通知来保护您的基础架构

原文:https://towardsdatascience.com/protect-your-infrastructure-with-real-time-notifications-of-aws-console-user-changes-3144fd18c680?source=collection_archive---------15-----------------------

您已经接受了基础设施即代码(IoC ),并煞费苦心地创建了 Terraform 或 CloudFormation 来建模您的 EC2 实例、自动扩展组、ECS 集群和其他一切。devops 和开发团队承诺只使用您选择的 IoC 工具来修改和创建基础设施——但是,令人惊讶的是,有些人就是不遵守。也许有人在特性开发过程中偷懒,或者在事件响应过程中走捷径。也许你已经外包了你的一级支持,但你还没有完全信任那个团队。无论是什么原因,您都想知道用户何时登录 AWS 控制台网站并手动更改内容。

围绕这个话题的担忧是有可信的理由的。环境漂移是一个术语,通常用来描述期望状态(在您的基础设施中用代码表示)和您的基础设施的实际、实时状态之间的差异。这种漂移最终会导致部署失败、影响客户的扩展问题、安全漏洞,或者最糟糕的是数据泄露。

在本文中,我们将构建一个系统来监控您的 AWS 基础设施,并在用户直接从 AWS 控制台做出更改时发送通知。我们将利用 CloudTrail 来记录事件,并将其写入 S3。S3 触发器将调用 Lamba 函数。该功能将过滤事件,并将相关事件发布到您的团队可以订阅的 SNS 主题中。如果这听起来很吓人,不要担心;AWS 完成了繁重的工作,我们只需要连接各个部分。下面详细介绍了每个步骤,让我们开始吧。

启用 CloudTrail

CloudTrail 是这个项目中关键的 AWS 服务。您也许可以用功能等同的组件替换其他组件,但是 CloudTrail 会监控整个 AWS 帐户的变化,并将数据发布到 S3 的日志文件中。

CloudTrail 通常用于安全调查、合规性和审计目的。您可以使用它的 web 界面来搜索它记录的事件。需要知道是谁启动了那个闲置的昂贵实例吗?查看 CloudTrail 日志。追踪谁修改了启动配置以找出原因?云迹。CloudTrail 的基本搜索功能就在它的 AWS web 界面上,您还可以使用 AWS Athena 对事件日志执行 SQL 风格的查询。

默认情况下,CloudTrail 会在您的帐户中保留过去 90 天活动的事件日志。但是这些日志在 S3 是无法获取的;为此,我们需要创建一个新的线索。AWS 允许为免费创建一个管理事件的踪迹。

导航到 CloudTrail 控制台并选择“创建轨迹”提供一个名称,并为事件过滤器选择“只写”,因为这是我们唯一感兴趣的。

向下滚动到存储位置部分,选择或创建一个 S3 存储桶来存储您的日志。

现在,为了测试这一点,继续在您的 AWS 环境中进行一些更改——启动一个 t.2 微实例,创建一个空的 Lambda 函数,任何事情都可以。然后看看应该包含我们的 CloudTrail 日志的 S3 桶:

如果您从这个 bucket 下载一个日志文件,您将看到一个事件数组(“记录”)。每个事件都有大量的元数据——下面是一个示例事件(简称),它是在启动一个新的 EC2 实例时生成的:

创建一个 Lambda 来处理 CloudTrail 日志

既然对 AWS 基础设施的每次修改都记录到了 S3,我们需要编写一个函数来解析数据。我们将在 Lambda 中这样做,因为它是无服务器的,这符合我们只在记录新事件时调用函数的需求。

导航到 Lambda 控制台并创建一个新函数。选择空函数和 Python 3.8 作为运行时环境。

该功能需要从 S3 读取和向 SNS 发布通知的权限。选择“从 AWS 策略模板创建新角色”,并从策略模板下拉列表中选择“S3 对象只读”和“SNS 发布”。为您的角色提供一个名称,然后选择创建功能。

创建函数后,向下滚动找到内联代码编辑器和一个非常基本的 Python 函数。

继续复制下面的所有代码,并将其粘贴到编辑器中,替换所有现有的代码:

让我们回顾一下代码。向下滚动找到lambda _ handler——这是我们应用程序的入口点。因为 Lambda 是由 S3 触发器调用的,所以参数“event”包含 S3 事件的列表。每个事件都包含一个对象的键,该对象是在我们的 CloudTrail 日志写入的 S3 桶中创建的。我们遍历列表,对于每个事件,我们从 S3 下载指定的文件并解压。

在每个文件中,我们都有一个 JSON 格式的 CloudTrail 事件列表。我们不希望每个 CloudTrail 事件都被通知;这个练习的目的是只捕捉用户通过 AWS 控制台触发的事件。Amazon 没有提供一种简单的方法来区分手动用户更改和由 SDK 或命令行调用的用户更改。Arkadiy Tetelma 写了一个很棒的博客在这里,他在其中致力于解决同样的问题。我们将按照 Arkadiy 在 Lamda 中描述的方式过滤 CloudTrail 事件。

为了执行过滤器,我们使用 Python list comprehension 对日志中的每个项目运行 filter_user_events ,并创建仅包含匹配项的 output_dict

filter_user_events 函数根据我们指定的过滤器检查事件中的相关字段。首先,它查看用户代理,并尝试匹配一系列模仿 AWS 控制台 URL 的正则表达式。然后,它筛选只读事件,如以“Get”或“Describe”开头的事件。第三项检查是针对一组我们忽略的特定事件名(比如 AWS 控制台登录。)最后检查事件是否由“AWS 内部”调用

在我们得到感兴趣的事件子集后,我们想要发送实际的通知。我们将使用亚马逊的简单通知服务(SNS),这是一个非常简单的服务,允许您创建一个主题,然后发布/订阅它。发布到 SNS 主题的代码在我们的 sns_publish 函数中,有两个包装器方法( post_to_sns 只发布用户名和 eventName,而 post_to_sns_details 发布整个 JSON 事件。)

注意这里引用的 sns_arn 变量,它是在文件顶部附近定义的;您需要将它替换为您想要发布到的 SNS 主题的 ARN。单击屏幕右上角附近的 save,用您粘贴的代码更新您的 Lambda 函数;此更改将立即生效。然后导航到 AWS 控制台的 SNS 部分,选择主题,并创建主题。

适当地命名主题,并对所有其他部分使用默认设置。或者,您可以编辑访问策略设置;默认策略是只允许主题所有者发布和订阅该主题。对于本演示来说,这很好,但是如果您想在一个更大的组织中使用它,您需要根据自己的喜好来定制策略。选择“创建主题”以完成设置过程。

在这个屏幕上,你可以复制你的主题的 ARN,然后返回 Lambda 来更新代码(替换变量 sns_arn 的值)。)您还会注意到这个主题没有订阅;选择“创建订阅”,选择电子邮件作为协议,输入您的电子邮件地址,然后再次选择“创建订阅”。

请务必检查您的电子邮件并确认订阅,否则您将不会收到任何发布到该主题的消息。

在 S3 事件上触发 Lambda

所以,快速回顾一下。启用了 CloudTrail 日志记录,存在一个 SNS 主题并且我们订阅了它,我们的 Lambda 函数是活动的(并且 sns_arn 变量被更新。)剩下要做的就是创建触发器,以便每当在 S3 桶中创建新的 CloudTrail 日志时调用我们的 Lambda 函数。

导航回 Lambda 控制台,点击您的函数详细信息,并选择靠近设计器窗口顶部的“添加触发器”选项。

选择写入 CloudTrail 日志的 S3 存储桶。对于事件类型,选择“所有对象创建事件”,以便每当在存储桶中创建新对象时调用我们的函数。确保选择“启用触发器”以立即激活此触发器,然后单击“添加”

创建触发器后,您应该会在设计器视图中看到它。

测试一下

现在来测试一下吧!一个简单(且免费)的方法是创建一个新的 Lambda 函数来触发我们的警报。如果一切正常,在函数创建后不久,您将会收到如下电子邮件:

由于代码设置为将消息的简短和详细版本发布到 SNS,您应该会收到另一封包含完整 JSON 消息的电子邮件。如果一切正常,您就万事俱备了!请随意更改代码或设置以满足您的需求。如果您对脚本进行了任何改进,请向 GitHub repo 发送 PR。如果有些地方不太对劲,请查看下面的故障排除提示。

解决纷争

  • 检查 CloudTrail S3 桶;是否正在创建日志?
  • 检查 Cloudwatch 日志中的 Lambda 函数。每次你期望 Lambda 被触发时,日志应该存在。在日志中查找写消息。
  • 检查 Lambda 函数的 S3 触发器;它在监控正确的桶吗?
  • 检查分配给 Lambda 的 IAM 角色;它有适当的权限从 S3 读取内容并发布到社交网站吗?
  • Lambda Python 代码中的 sns_arn 变量和你的 sns 话题匹配吗?
  • 你用你的邮箱地址订阅了 SNS 话题,并确认订阅了吗?
  • 如果所有这些都失败了,您可以在本地机器上取消注释并运行 Python 代码中的单元测试。您还可以向代码中添加更广泛的 print()日志记录,并查看 Cloudwatch 日志,以便更好地了解函数执行时发生了什么。

资源

检测手动 AWS 控制台动作— Arkadiy Tetelman

PyCloudTrailProcessor GitHub Repo

抗议时保护和加密您的数据

原文:https://towardsdatascience.com/protecting-and-encrypting-your-data-while-protesting-c8b54f26c58f?source=collection_archive---------84-----------------------

努力实现社会变革和进步是一个正常运转的社会的当务之急,但数据隐私权也是如此

席卷美国的关于警察暴行和种族不平等的抗议活动一直遭到警察发起的暴力以及联邦调查局(FBI)等各种机构的恐吓。

照片由 NASA 在 Unsplash 上拍摄

穿戴合适的装备对于确保一个人的安全无疑是至关重要的,但保护隐私和你的隐私权也同样重要,尤其是在与同伴组织、与官员交谈以及广泛保留你的匿名权时。为了保护自己和他人的健康,也为了避开各个城市的面部识别措施,不要忘记戴上口罩。

鉴于面部识别技术在纽约等城市和 NYPD 等部门使用的主要问题,以各种形式遮住你的脸有助于规避它从你的面部特征提取生物特征数据的方式。

无数的公司实体一直站在推进面部识别技术使用的最前沿,包括但不限于以下公司:

  1. Face-Six " 希望通过承诺帮助医院"通过希望"在必要时识别患者,无论是有意识还是无意识"来减少医疗差错和欺诈
  2. 根据卫报的一篇文章,ISM Connect 在泰勒·斯威夫特的演唱会上使用面部识别来“根除跟踪者
  3. Clearview AI 已经被"超过 600 家执法机构使用…据该公司称,该公司拒绝提供基于纽约时报的一篇文章的名单

随着大型社交媒体平台、反恐国家监控法案等的出现,监控达到了前所未有的高度,保护您的隐私、数据和身份变得越来越必要。

这里有 5 个绝对必要的预防措施,你应该在参加抗议之前采取。

1.把你的手机留在家里

当你在街上行进时,最不需要技术来确保你的数字隐私的方法可能就是把你的手机留在家里。虽然有些人可能需要他们的手机与他人沟通,但你可能没有必要去任何地方都带着手机。

照片由马丁·巴拉科夫提供

然而,如果你决定带着你的手机去参加抗议,确保你采用了下面列出的建议。如果没有必要使用您的手机,请确保将其留在家中,因为官员可能会要求搜索您的设备,以获取他们可能会用来攻击您或您认识的人的信息。默认情况下,大多数智能手机都开启了基于位置的跟踪功能,这可能会妨碍你保持匿名在线的能力。

此外,如果你绝对有必要拥有一部手机,但你不希望通过大量的措施来确保你的隐私,那么至少试着拿起一部便宜的一次性手机,你可以在抗议期间使用它来保持联系,同时不会有任何个人信息与你直接相关。

2.保护您的设备

在离开家之前,请确保积极保护您的设备。如果你不使用密码,没有比今天更好的开始时间了。最好的选择是使用强密码,而不是标准的 4 位数密码,但这两种密码都适用于基本的先发制人措施。

然而,不要使用面部识别来解锁手机,也不要使用指纹。虽然一名联邦法官在 2020 年 1 月裁定警察无权强迫你使用指纹或面部生物特征解锁你的设备,但为了确保你的隐私权安全起见,这并无大碍。

此外,让你的手机关机或处于飞行模式可以帮助你保护你的隐私和匿名。

KOBU 社在 Unsplash 上拍摄的照片

如果您的设备上有敏感信息,包括但不限于特定人员的机密数据、警察暴行的证据等,加密您的数据也是一种有价值的先发制人措施。加密也已经成为大多数设备的核心功能。

对于 Android 设备,您需要按照以下顺序导航(取决于设备的型号和品牌):

设置→安全→高级→加密&凭证→加密手机

对于 iPhone 等苹果设备,这与在安卓设备上的操作方式极其相似:

设置→触控 ID 和密码→打开密码

3.创建有价值信息的备份

备份您的数据可以让您安全地删除重要和机密的信息,或者在您的设备被盗或被当局拦下时不会引起您的恐慌。确保您的备份也是安全的,因为执法不是您应该警惕的唯一数字,因为云备份(取决于提供商)可能容易受到具有恶意目的的第三方的影响。

重要的是要说明,备份您的数据不仅应该在参加抗议活动时进行,而且应该作为一项常规工作来进行,以确保一切都是最新的,并且您在未来的任何给定时刻都不会有风险。

4.使用安全应用程序

使用 Facebook Messenger、WhatsApp 或默认短信与抗议者交流并不是确保数字隐私的最安全方法。除此之外,在不影响易用性的同时,还有 Signal 等应用程序。

蒂姆·班尼特在 Unsplash 上拍摄的照片

Signal 是一款适用于 Android 和 iOS 设备的消息应用,提供非常强大的加密级别,以确保短信和电话的安全。此外,该平台最近宣布为应用程序内发送的照片添加面部模糊功能,以确保匿名性,而不仅仅是语音和文本消息,这是一个非常有用的发展。

此外,该平台零广告,消除了“联盟营销人员”和“信号中令人毛骨悚然的跟踪”的可能性。Signal 提供的端到端加密是开源的,并声明“我们不能阅读你的消息或监听你的电话,其他任何人也不能”,建立在隐私对他们的应用程序是永久的概念上。

5.安全浏览

除了通过使用 Signal 进行安全通信之外,不要低估使用安全浏览器(如 Tor )的重要性。虽然窃听者可能会看到您正在使用 Tor 浏览器,但他们无法区分您和 Tor 网络上的其他用户,这使得该浏览器无疑是最安全的。

Tor 浏览器特别棒是因为很多不同的原因。首先,它完全匿名化了你的浏览,以至于浏览习惯甚至无法追溯到你的具体会话。Tor 旨在使网络上的所有用户看起来彼此相同,以消除各种行为者的指纹识别和监视威胁。

其次,它阻止可能与广告商或黑客有关联的追踪者。这意味着这些实体不能跟随你从互联网上的一个地方到另一个地方。

所有通过 Tor 网络的流量都经过三次加密,根据您的会话和位置提供完全匿名。流量总是通过所谓的 Tor 中继,这些中继最容易被描述为网络上的志愿者运行的服务器。

Tor 始终拥有 150 万至 300 万的强大用户群(截至 Q1-Q2 2020 年)。

洋葱浏览器可在 App Store 上获得,而官方的 T2 Tor 浏览器可在 Google Play 上获得。

如果您决定继续使用标准浏览器,如 Google Chrome、Mozilla Firefox 和其他浏览器,以下工具有助于查看您的浏览器和设备组合发出的独特指纹:

  1. BrowserLeaks 让你超越以你的 IP 地址和 cookies 为中心的常规工具,看到你的数字指纹。它提供的信息从画布指纹到你的浏览器是否支持地理定位权限。
  2. AmIUnique 提供了一个界面,可以让你量化自己在互联网上的独特性。它根据浏览器类型、操作系统、时区、HTTP 头属性、JavaScript 属性等常见标识符显示您的唯一性百分比。
  3. 设备信息在提供基于标识符的信息方面类似于 AmIUnique,但在指纹内容方面提供更多信息。它不会将你与其他用户进行比较,也不会量化你的指纹,但它提供了无数的隐私测试工具。
  4. Panopticlick 是由电子前沿基金会(EFF)创建的一个研究项目,该项目在有或没有跟踪公司的情况下进行测试(根据你的决定),并提供有关你的指纹的信息,包括与你的结果相似的浏览器数量(“十个浏览器中有一个有这个值”)。

EFF 还有一个非常有组织的网站,通过各种文章、指南和工具来帮助相关的平民保护他们的数据、隐私和在线通信,这些不仅对动乱时期的保护有用,而且对整体也有用。

关于去抗议,最重要的是确保你的安全。这样做的结果是你未来在个人和网络上的幸福。

保护 PII 和实现地理准确性

原文:https://towardsdatascience.com/protecting-pii-and-achieving-geographic-accuracy-97bebc99ac14?source=collection_archive---------40-----------------------

创建等级优步 H3 六边形以实现最大的地理精度,同时保护个人隐私。

疫情冠状病毒揭示了对地理精确位置信息的突出需求,以及对保护确诊病例的个人可识别信息(PII)的同样突出的需求。优步的 H3 是一个分层的六边形宁滨库,可用于基于最小计数阈值创建多分辨率六边形镶嵌。这种基于密度的多分辨率镶嵌在保持 PII 的同时实现了可能的最大地理精度。

使用优步 H3 为西雅图建造的六边形,使用 1,000 人的人口阈值

准确的位置信息对于流行病学建模至关重要。当我写这篇文章的时候,在纽约市这个 800 多万人口的城市,有超过 13000 例确诊病例。遗憾的是,当你读到这篇文章时,这个数字可能要大得多。随着疾病的传播,当务之急是利用现有的数据来预测这种疫情的传播。世界上最伟大的建模头脑正在全力支持创建一个流行病学模型。甚至还有一个 Kaggle 竞赛,试图向大众征集最佳解决方案。然而,病例数据仅在美国的县一级被报道,这使得在社区内传播建模极其困难。对地理位置准确的病例信息的需求从未像现在这样迫切。

这种对地理上准确的病例信息的需求必须与保护这种高度传染性疾病的感染者身份的同样突出的需求相平衡。在这次疫情中,保护 PII 比仅仅为了保护个人尊严要重要得多。正如早期对全球亚裔的种族主义攻击所表明的那样,轻易保护 PII 也可能是一个突出的个人安全问题。

使用优步 H3 的分层六边形镶嵌

所有点并非生而平等-西雅图的人口加权块点

优步的 H3 图书馆可用于聚合地理上分布的可测量现象,方法是将指定位置的观测结果组合成包含不少于指定阈值计数的六边形。为了保护 PII,这种现象典型的是人口。使用群体作为可测量的现象,可以使用 H3 创建多分辨率六边形镶嵌。在镶嵌中,没有单个六边形区域包含任何小于指定群体阈值的区域。

使用 1,000 人的人口阈值创建的多分辨率六边形镶嵌

在本文顶部的西雅图图和上面的德克萨斯州图中,这两个多分辨率镶嵌都使用块点,即美国人口普查块的质心点,每个点都有一个关联的人口计数字段。此人口权重字段用于计算 1,000 人的数量,并根据每个六边形面的阈值进行评估。如果六边形不满足阈值,则使用下一个更高的分辨率。如果在达到最大六边形级别时没有达到阈值,则该区域就不会被使用。结果是一个多分辨率的六边形镶嵌,其中一些区域只是为了保护 PII 而被显示出来。

使用的资源

谢天谢地,特别是对于数据科学家来说,在 h3-py 库中有 Python 绑定可以轻松利用 H3 库。由于编译依赖,从源代码安装确实需要一些配置。谢天谢地,特别是对于我们这些使用 Windows 的人来说,有一个 Conda 包可以简化安装。

优步的 H3 等级六边形镶嵌系统

为了进一步简化在 ArcGIS Pro 中使用 H3 的过程,我构建了 h3-arcgis 。H3-arcgis 提供了基于点计数或每个点的权重因子创建多分辨率 H3 镶嵌的功能,从而解决了平衡地理精度和 PII 的难题。

如何应用它

这适用于优步 H3 图书馆中指定的缩放级别的指定范围。在上面西雅图的例子中,这些缩放级别从 5(最大区域)到 9(最小区域)。

创建六边形是一个两步过程。首先,如果六边形在最大缩放级别(最小区域)包含最小阈值,则评估并创建六边形。任何不符合阈值的区域都在下一个较小的缩放级别(递增的较大区域)进行评估。重复该过程,直到评估了最后(最大区域)的缩放级别。任何未达到此阈值的区域都不会包含在最终输出中。

解除冲突前重叠的六边形

由于 H3 的等级性质,每个父六边形包含七个更小的子六边形。通常,虽然父区域中的一些子六边形符合阈值并被创建,但并非所有子区域都符合阈值。因此,创建父六边形时,父六边形中包含一些子六边形,但不是所有子六边形。这种重叠在第二步中得到解决,在第二步中,包含在较大六边形中的任何六边形被累加到较大六边形中,以创建最终的输出镶嵌。

北卡罗来纳州夏洛特的 H3 六边形镶嵌—再次使用 1000 人阈值

为什么选择 Python 和 ArcGIS?

H3-arcgis 是用 Python 实现的,因为我懂 Python。它设计用于 ArcGIS Pro,因为我每天都在使用它,并希望在这个前所未有的时代帮助 Esri 的客户应对这一挑战。

请用我的作品!

创建等级镶嵌的逻辑不依赖于 ArcGIS 的使用。它主要使用 H3 的能力来分配一个六边形地址给一个坐标对,查找父 H3 地址,并使用熊猫数据帧评估计数。因此,任何有专业知识的人都有可能在任何数量的平台上实现这种方法,包括在 H3 图书馆中,或者在 Scala 中使用大数据。

参考资料和资源

  • 优步·H3
  • H3-py
  • H3-py 康达套餐
  • H3-ArcGIS
  • Joel McCune 在 GitHub 、 LinkedIn 和 GeoNet 上

保护自己免受 P 值操纵

原文:https://towardsdatascience.com/protecting-yourself-from-p-value-manipulation-bc0412ad801b?source=collection_archive---------52-----------------------

为什么调查研究失去了可信度,你如何通过问这些简单的问题来建立你的可信度

由 Unsplash 上的 Taras Chernus 拍摄的照片

如果你认为你看到了有趣的事情,你需要证据来证明这不是一次性事件。

我有一手幸运牌,最近,我赢了很多。我赌的每一个数字都是轮盘赌上的中奖号码。我发现了什么有趣的事情吗?假设我和以前一样是个失败者,那么我最近的所有胜利有多少可能是随机幸运的呢?

在统计学中, p 值是最后一个问题的答案。好了,现在疼了!我如何证明我的获胜直觉不仅仅是纯粹的运气?当然,我开始尝试和赌博。我赌得越多,赢得越多,我就建立了对我有利的证据。“p 值”越低,证据越有力。

我真的可以操纵 p 值让自己在朋友面前好看,而不伪造结果吗?如果你发现我所有的赢钱赌注都放在同一个赌场,你会怎么想?你有我在其他赌场下注的信息吗?我在那里赢了同样多的钱吗?

不幸的是,p 值很容易被操纵。此外,这在现实生活中经常发生,包括科学研究和商业研究。例如, p-hacking 指控导致研究报告发表后遭到进一步质疑,因为它们的结果不可复制。随着越来越多如此高调的例子发生,p-hacking 甚至找到了进入流行文化的途径。

“科学是扯淡吗?不,但是现在有很多伪装成科学的胡说八道”——约翰·奥利弗

无论你以哪种方式操纵 p 值,都会导致糟糕的决策和昂贵的结果,更不要忘了研究者可信度的损失。如果我们正在测试一个假设,高于某个统计显著性水平的 p 值表明没有足够的证据来拒绝对假设的反驳。这并不意味着我们自己的假设是错误的。然而,这确实在解释 p 值时创造了一个巨大的灰色区域,这在研究和商业中被广泛操纵。

我们如何躲避 p 值子弹?

我们需要明白,作为数据科学家和研究人员,我们的工作是提出问题和提出建议,而不是冒险证明给定的假设是正确的。在你进一步阅读之前,我强烈推荐你浏览一下关于测试和实验的基础知识。

没有足够的证据来验证一个假设并不意味着这个假设是错误的。然而,这一事实被扭曲了很多,以发布来自学术界和商界的误导性研究结果。

在从我们自己的研究或其他工作中得出结论之前,我们应该经常问自己这些问题。

我们接受一个结果仅仅是因为它符合我们自己的偏见吗?

p-hacking 发生的一个常见原因,不管是有意还是无意,是利用了研究人员的自由度。这个术语指的是研究人员在设计统计实验时使用的灵活性,以便他们想要发表的结果具有统计学意义。通常,这些设计决策可归结为一些因素,如实验中包含的变量、决定何时停止收集数据、数据采样方法等。

作为数据科学家,我们的工作是客观地验证我们的假设,而不是为它们辩护。

假设我们拥有一家连锁超市,注意到在我们的一家店中,啤酒和尿布总是一起购买。这是否意味着啤酒和尿布销售之间的相关性是真实的?相关性在统计上有意义吗?如果我们操纵实验来强迫一个有统计学意义的结果,不管是有意的还是无意的。举个例子,

  • 我们只选择了那些包含购买婴儿用品的交易。
  • 我们只在一个社区的少数几家商店里进行了研究,这些商店碰巧有很多刚生完孩子的年轻夫妇。

相反,作为优秀的数据科学家,我们实际上希望采取进一步的措施来确保我们正在进行一个可靠的实验。除了啤酒和尿布的销售,还有更多变数在起作用。举个例子,

  • 我们应该在其他市场进行实验,并验证结果是否可重复。
  • 为实验选择数据时,要随机抽样。这是黄金标准。

根据我们认为可靠的虚假结果得出结论可能会被证明是极其昂贵的。我们当然不希望这些美元白白浪费掉。

我们愿意在什么样的显著性阈值上接受结果?

换句话说,我们愿意去维加斯的几率有多大?我们的假设是啤酒和尿布相伴而行,相反的观点是它们并不相伴。这个反驳论点就是零假设。拒绝零假设需要什么?p-value 意在成为诚实直率、不带偏见的导师。我们如何解读它的建议来做出理性的决定?我们制定一个计划。我们在沙地上画了一条线,如果 p 值越过这条线,我们就不能拒绝零假设。沙子上的这条线被称为显著性水平,或 alpha。

保守的显著性阈值不一定使测试可靠。它只表明我们在做决定前愿意接受的风险水平。

那么,更低、更保守的显著性阈值是否意味着我们的测试有可靠的结果?不,这只是我们愿意承担风险的一个指标。它不是我们研究质量的指标。根据领域的不同,显著性级别可以更保守或更宽松。

拒绝无效假设的阈值可以从一个域到另一个域变化,并且可以是保守的或宽松的,这取决于情况的优点。这不会改变研究的质量,也不会改变观察到的 p 值本身的可靠性。

例如,与新药的临床试验相比,市场研究的显著性水平可以更宽松。然而,收紧或放松这个阈值不会改变研究的价值和 p 值统计本身的可靠性。我们的判断应该基于研究的质量,改变显著性水平以使结果看起来更好不会改变它实际上有多好。

有些东西看起来很好,并不意味着它就是好的,或者一定是正确的。

当然,在建立一个实验时,需要考虑很多事情。我们需要做好一些基本的事情,比如弄清楚我们想要测量什么指标,测试的规模是多少,或者我们需要进行多长时间的实验。米尔恰·达维德斯库博士在这篇的精彩文章中详细解释了其中的一些。然而,一旦我们弄清楚了基础,作为数据科学家,我们的工作就是客观地对待结果,而不是操纵它们。

毕竟,我们不欠任何人任何实验的结果。我们观察我们所看到的,并推荐前进的方法。

把蛋白质变成音乐(三)——递归神经网络

原文:https://towardsdatascience.com/protein-music-with-python-part-3-applying-a-recursive-neural-net-c841aee25126?source=collection_archive---------52-----------------------

从 RNN 产生的蛋白质序列中创造音乐

作者用 NN SVG 创建的图像

在之前的两篇文章中,我演示了如何将蛋白质转换成音乐。的第一篇文章解释了组成蛋白质的分子——单个氨基酸的分子振动是如何转变成音符的。第二篇介绍了和声和节奏;蛋白质结构中相邻的氨基酸可以一起弹奏产生和弦,氨基酸的二级结构分类可以决定其音符长度。在这里,我展示了如何通过在一组相似的蛋白质上训练 RNN 来创建一种蛋白质音乐的流派,然后使用它来生成新的序列,这些序列可以被转换成音乐。

蛋白质发音背景

麻省理工学院马库斯·布勒的原子和分子力学实验室的一篇论文是我对蛋白质发音的介绍。作者使用我在以前的文章中描述的技术对蛋白质进行超声处理,然后在产生的音乐序列上训练一个递归神经网络 (RNN)。一旦经过训练,RNN 就被用来生成新的音乐序列。重要的是,这些新序列将包含训练中使用的序列的特征。这在应用于蛋白质结构研究时有着有趣的含义。要了解原因,了解 RNNs 的基础知识是很有用的。

作者图片

递归神经网络

rnn 是多种类型的神经网络架构中的一种。它们通常与顺序信息一起使用,因为它们有一种记忆形式,,它们可以在执行计算时回顾以前的信息对于序列,这意味着 rnn 通过考虑序列中的下一个字符之前的内容来预测它。有许多方法可以实现这一点,我推荐阅读迈克尔·菲的这篇优秀文章来了解更多。Buehler 论文的作者使用 TensorFlow 提供支持的 Magenta 库来构建他们的 RNN,其中包括 LSTM 和注意力层。我的模型基于一个由 tensor flow生成文本的模型。

数据集

蛋白质的功能是由其结构决定的,而结构又是由其序列决定的。蛋白质执行许多功能,如运输分子、识别抗原或发送应答信号,这些不同的功能是由不同的结构实现的。由此可见,有几类蛋白质结构具有相似的功能。为了让 RNN 生成有趣的序列,它需要接受某种信息类别的训练。我所说的有趣,是指生成的序列包含一些训练数据中存在的信息或特征。这就是 RNNs 研究蛋白质序列的潜力。

新型冠状病毒主蛋白酶含抑制剂 N3(白棍代表)【1】

这些是我用来建立数据集的资源:

  • uni prot【2】是一个包含蛋白质序列和功能信息的数据库。截至 2020 年 5 月 15 日,它目前包含 560,000 个人工审查的序列。
  • 蛋白质数据库 (PDB)[3]是一个包含蛋白质结构的数据库。截至 2020 年 5 月 15 日,它目前包含约 160,000 个。
  • BLAST【4】是一个用来寻找相似生物序列的工具。蛋白质 BLAST ( blastp )是该工具用于蛋白质序列的版本。

我需要一套相似的蛋白质结构来训练 RNN。我选择了 SARS 冠状病毒主要蛋白酶, PDB ID 1Q2W ,作为我的出发点。我使用 blasp 在 PDB 搜索类似的结构,我的训练数据包含 26 种蛋白质结构。

准备数据

我之前描述了蛋白质结构的 3D 空间中的氨基酸邻居如何被用来构建蛋白质音乐中的和声。对于创作音乐来说,这很好,但对于训练 RNN 来说,这就产生了一个问题。按照德劳内镶嵌的定义,蛋白质中的一个氨基酸通常有大约 8 个邻居。因为有 20 个标准氨基酸,这意味着有超过 250 亿个 20⁸,可能的邻居组合。我不想丢弃谐波信息,而是想找到一种方法来描述邻居组的整体特征。这是疏水性进入的地方。

被水吸引的分子称为亲水分子,被水排斥的分子称为疏水分子。20 种氨基酸中的每一种对水都有不同的亲和力,有不同的尺度来衡量这一点。Kyte 和 Doolittle【5】量表为每种氨基酸指定一个数字。在这个标度上,数字越大,越疏水,数字越小,越亲水。使用 Kyte 和 Doolittle 标度,可以计算每个邻居的疏水性得分的总和。这个和保存了关于邻居集合的信息,例如,如果它非常正,那么大多数邻居是疏水的。为了进一步简化该分数,使用了以下转换函数;它将邻居集疏水性分值定义为-1、0 或 1。

邻居集疏水性得分转换函数

准备数据的 Python 代码

数据收集

我选择了蛋白质 1Q2W,SARS 冠状病毒的主要蛋白酶,作为我的数据集的目标蛋白质,并使用 blastp [4]寻找类似的蛋白质。下面是 blastp 结果的几行结果。粗体文本包含相似蛋白质的 PDB id。

1Q2W:A|PDBID|CHAIN|SEQUENCE **4RSP_A** 51.792 307 140 4 3 ... 67.75
1Q2W:A|PDBID|CHAIN|SEQUENCE **4YLU_A** 51.792 307 140 4 3 ... 67.75
1Q2W:A|PDBID|CHAIN|SEQUENCE **5WKJ_A** 51.792 307 140 4 3 ... 67.75

为了建立数据集,下载了相似蛋白质的 PDB 文件。下面的代码分两步完成。首先,它从 blastp 结果中提取相似的蛋白质 id,然后,它下载这些蛋白质的 PDB 文件。

接下来,可以检索蛋白质序列、坐标和二级结构分类。这些数据存储在 PDB 文件的特定行和位置。你可以在这里了解更多关于 PDB 格式的信息,但是下面的代码提取了相关的数据。首先,从标题行获得蛋白质 ID,然后收集二级结构信息。螺旋线和片线包含所有二级结构元素的起始和结束位置。因此,对于每个螺旋线或表线,代码填充每个元素的内部位置,并将所有位置分别添加到helicessheets。接下来,从原子线中提取每个原子的序列位置和坐标。在这种情况下,c-α碳的坐标用于每个氨基酸。最后,检查每个位置,看它是否存在于helicessheets中。如果是,那么一个 H 螺旋片或 E 片被添加到二级结构(SS)序列中。如果没有,则增加一个 C 线圈。下面的代码将这些信息存储在data字典中。

下面是通过 Delaunay 镶嵌定义氨基酸邻居的函数。它接受一组坐标,在这种情况下是蛋白质中每个氨基酸的 c-α碳的位置,并返回一个字典,其中每个键是序列中的一个位置,每个值是邻居的集合。

数据收集的最后一部分是创建一个包含数据集中蛋白质所有相关信息的长序列。下面的代码遍历每个蛋白质,并为序列中的每个位置创建一个entryentry包含一个由三个元素组成的字符串。第一个是氨基酸单字母符号。接下来,是二级结构分类。最后一部分是邻居集疏水性得分,如上所述。每种蛋白质的所有序列条目加在一起形成一个长序列。

数据准备

有了sequence,我们现在可以建造和训练 RNN。我使用本教程中描述的模型作为我的模板。首先,我们将alphabet定义为sequence中的唯一条目。然后,我们为序列中的每个条目创建一个到唯一整数的映射,并使用这个映射来创建int_sequence,它包含整数形式的序列。

为了训练,sequence需要分解成更小的序列。我任意选择了 100 的seq_length,但是最佳值可以通过实验来确定。使用这个长度,数据集可以被分割成输入示例和目标。首先,数据被分成长度为seq_length + 1的块。输入示例将包含前 100 个条目,目标将包含从 1 到 101 的条目。给定一个输入示例,RNN 尝试预测下一个条目。

接下来,将训练数据集中成批。批量大小决定了在更新权重之前要为 RNN 提供多少训练样本。基于多个训练实例更新权重使得训练过程更加稳定。你可以在这里了解更多关于这个概念的信息,这里有一个很好的可视化效果。

模型架构

现在我们可以建造 RNN 了。我使用了这里的架构T2,它有三层。有一个嵌入层,为字母表中的每个条目创建一个给定大小的密集向量。嵌入的概念一开始可能很难理解。我发现考虑嵌入将每个条目映射到 N 维空间中的一个位置是有帮助的,其中 N 是你选择的向量的大小。这很有用,因为在这个 N 维空间中,您可以使用余弦相似度或欧几里德距离来计算条目之间的关系。你可以在这里或者通过研究 word2vec 模型来了解关于主题的更多信息,其中嵌入是核心概念。

GRU 层使这个网络成为 RNN。它为网络提供了短期记忆。有一篇关于 GRUs 和类似架构的优秀文章,叫做 LSTMs,这里。最后是密集层;这个就是模型的输出层。它是生成字母表大小的向量的层,该向量包含逻辑或预测概率。下面的代码是构建网络的一个方便的函数。

以下代码使用上述函数来构建模型。前几行是模型的参数,除了前面定义的batch_size。为了训练,模型需要损失函数和优化器。损失函数将预测值与真实值进行比较,并计算误差的严重程度。这里,使用了稀疏分类交叉熵。Adam 用于优化学习速率。你可以在作者的论文中读到更多关于 Adam 优化器的内容。

训练前的最后一步是告诉模型在哪里保存检查点。这些用于在训练过程中从不同点加载模型权重。

训练模型

我对这个模型进行了 100 个时期的训练,花了不到一个小时,产生了令人惊讶的好结果。

生成序列

下面的代码是生成序列的函数;它基于这里描述的张量流函数。

有了上面的函数,我们就可以为序列生成准备模型了。使用相同的体系结构重新构建模型,只是批量大小设置为 1,并且加载来自上一个检查点的权重。

现在,RNN 可以用来生成新的序列。在下面的代码中,随机选择一个种子序列,然后将其输入网络。

结果

这是 RNN 产生的两个氨基酸序列:

  1. vkmshpsgdveacmvqvtcgsmtlngwldntvwcprhvmccpadql sdpnydallismtnhsfsvqkhigapanlrvvghamqgtllkkltvdvanpttvnlvlkvnqvnpntpehkfksvrpgesfnilacyegccpgsvygvnmrsqgtikgsfiagcgsvgyvlengtlyfvyvyvymhllgngsgngsglegemyggyed qpsmqmqlegtnvmssdnvvalyayangerwvtntsmslessynt
  2. glrwgdvekfngytvssvdafsylaaktvsveqmlgvkglrkmqpsvgvpecivrvaygnngwlgdevcprhviasdsrvinyenelssvrlhnfsiaknnavlgvvsakygvnlvlkvnqvnpntpehkfksvrpgesfnilacyegcpgsvygvnmrsqgtikgsfiagacgspgynnggtvefcylhqlelgsgsgchvgsdldgvmygeqptlqvegasslftenvlaflyaal

与生成序列相似的蛋白质

为了看看 RNN 是否了解了数据集中蛋白质的特征,我对生成的序列运行了 blastp。这两个序列的大多数热门都是针对病毒蛋白酶或蛋白酶的。并且,前 100 个命中中大约有 90 个是冠状病毒蛋白质回想一下,RNN 是在 SARS 冠状病毒的主要蛋白酶上被训练的,所以这些结果表明网络确实学习了冠状病毒蛋白酶的关键特征。

蛋白质结构预测

瑞士模型【6】生成序列的蛋白质结构预测 1。

蛋白质结构预测模型进一步支持了这一观点。上面报道的第一个序列使用瑞士模型 [6]建模,该模型使用同源建模的技术。在这个过程中,一个目标序列被提交给服务器,SWISS-MODEL 将该序列与具有已知结构的其他蛋白质序列的数据库进行比较。数据库包含蛋白质结构是关键,因为一旦发现一组相似的序列,与这些序列相关的结构就可以用作模板。模板用于构建提交序列的结构预测。上图和下图分别显示了第一个生成序列和第二个生成序列的瑞士模型预测。

SWISS-MODEL【6】蛋白质结构预测生成序列 2。

上述结构和新型冠状病毒主蛋白酶结构之间的相似性,如文章顶部所示,是显而易见的。这进一步支持了 RNN 捕获了病毒蛋白酶的序列特征。有像 FATCAT 这样的工具可以用来定量比较这些结构,但是我将把它留到另一篇文章中。

蛋白质音乐和未来的工作

我下载了生成结构的 PDB 文件,并使用我之前描述的技术来创建蛋白质音乐。你可以听下面的旋律,和声,以及两者的结合。我对未来的工作有两个目标。第一个目标是创建一个更大的相似蛋白质数据集用于训练;这里的数据集很小,但是可以使用更大的蛋白质家族。第二个目标涉及使用和生成的数据类型。在这里,我使用蛋白质序列数据进行训练,并将生成的序列转换成音乐。在未来,我打算增加一个抽象层;我想用品红直接在蛋白音乐上训练一个 RNN,这样输出的就是音乐。如果你喜欢我的作品,请继续关注并鼓掌!

参考

  1. 插图来自 PDB-101,作者:大卫·古德塞尔和 RCSB·PDB
  2. UniProt 联盟
    UniProt:全球蛋白质知识中心
    核酸研究 47:D506–515(2019)
  3. H.M. Berman,J. Westbrook,Z. Feng,G. Gilliland,T.N. Bhat,H. Weissig,I.N. Shindyalov,P.E. Bourne。
    (2000)蛋白质数据库 核酸研究,28:235–242。
  4. Altschul,S.F .,Gish,w .,Miller,w .,Myers,E.W. & Lipman,D.J. (1990)“基本局部比对搜索工具。”J. Mol。生物。215:403–410.考研
  5. J.摩尔。生物。157:105–132(1982)
  6. 瑞士车型参考:
  • SWISS-MODEL Workspace/GMQE
    water house,a .,贝尔托尼,m .,Bienert,s .,Studer,g .,Tauriello,g .,Gumienny,r .,赫尔,F.T .,de Beer,T.A.P .,Rempfer,c .,Bordoli,l .,Lepore,r .,Schwede,T. SWISS-MODEL:蛋白质结构和复合物的同源性建模。核酸研究第 46 号,W296-W303 (2018 年)。
  • 瑞士模式库
    Bienert,s .、Waterhouse,a .、de Beer,T.A.P .、Tauriello,g .、Studer,g .、Bordoli,l .、Schwede,t .瑞士模式库—新特性和功能。核酸第 45 号决议,D313-D319 (2017 年)。
  • Swiss-PdbViewer/ DeepView 项目模式
    Guex,n .、Peitsch,M.C .、Schwede,t .使用 SWISS-MODEL 和 Swiss-PdbViewer 进行自动比较蛋白质结构建模:历史观点。电泳 30,S162-S173 (2009)。
  • QMEANDisCo
    Studer,g .、Rempfer,c .、Waterhouse,A.M .、Gumienny,g .、Haas,j .、Schwede,t . qmean disco——应用于模型质量估计的距离约束。生物信息学 36,1765–1771(2020)。
  • Benkert,p .,Biasini,m .,Schwede,t .对单个蛋白质结构模型绝对质量的估计。生物信息学 27,343–350(2011)。
  • 四级结构预测/ QSQE
    贝尔托尼、m .、基弗、f .、比亚西尼、m .、博尔多利、l .、施韦德、t .通过同源性模拟同源和异源寡聚体的蛋白质四级结构。科学报告 7 (2017)。

蛋白质,蟒蛇和骨头,天啊!

原文:https://towardsdatascience.com/proteins-python-and-bones-oh-my-27d49f071ba5?source=collection_archive---------38-----------------------

在考古学领域内,近几十年来生物技术有了相当大的发展。一开始,对一些人来说,这似乎是科幻小说的领域。关于从永冻层克隆猛犸象、重建灭绝人类物种的面孔的可能性的报道频频见诸报端,等等。考古科学的进步是惊人的,但随之而来的是大量的数据需要被处理、消化并形成一种可理解的形式。蛋白质组学是生物学研究的一个例子,在考古学中有很大的用途。

在这篇博文中,我打算向你展示这个术语的确切含义,它如何改变了我们看待过去的方式以及编程在其中的地位。在我们开始讨论古代蛋白质的研究之前,有一件事要提一下,很抱歉,侏罗纪公园是不可能的。虽然这可能很悲伤,但琥珀(保存昆虫的树脂)不能保持柔软的有机物质新鲜,所以没有恐龙的血液(https://www . nhm . AC . uk/discover/could-scientists-bring-恐龙-back.htm) 。

羞愧

蛋白质组学,作为我自己为我的理学硕士研究的东西,是生物学信息对学术研究的效用的一个迷人的例子。它被简单地定义为对蛋白质的研究,但这掩盖了它的复杂性。我将尝试从我自己的经历中展示一个蛋白质组学的实际例子。

在考古学中,有一种非常神奇的技术叫做 ZooMS,或者叫做“质谱动物考古学”。细分来说,动物考古学是对与人类有过互动的古代动物的研究。在这种情况下,“人类”的定义可以从智人智人(即我们)到其他物种,如智人尼安德特人(尼安德特人)。“动物考古学”的一个例子是一块古老的鹿骨,上面有石器工具的划痕,在那里一个原始人(对“人属物种”的别称)刮掉了肉。质谱是一个化学术语,意思是测量一个原子或其他这样的粒子在磁场中偏转的程度。简单来说,想象一下,如果你在风洞里扔两个球,一个是岩石做的,一个是泡沫做的,后者会被风推得(偏转)更多。

它处理骨头的方式有点复杂,但需要理解的是,你可以通过分析当你将骨头分解成其组成成分胶原蛋白(一种蛋白质)时发现的蛋白质片段(肽)来测量骨头属于什么动物。蛋白质结晶,然后激光折射(反弹)通过它。折射角给出了碎片的长度。下面是我在大学参与的项目的信息图

骨头碎片(左)被溶解到液体蛋白质(胶原蛋白)中,然后被修剪成更小的“肽”(蛋白质碎片)。http://www.palaeochron.org/zooms

这将产生一组如下所示的结果:

碎片结果显示在左侧,称为光谱。“峰”对应右边的动物。http://www.palaeochron.org/zooms

所以亚历克斯的

我能听到你说。

“这与数据科学和分析有什么关系?”

很高兴你问了!当我写论文的时候,我要切下大约 2000 块骨头碎片,最终要分析 900 个光谱。现在有一个软件,叫 Mascot,可以用来搜索这类结果。当时,作为一名学生,我无法接触到这些。话虽如此,但是,如果我用现在的知识回到过去,我怎么能让我的 900 个结果更容易清理、研究和可视化呢?

回到 2017 年那段令人热血沸腾的日子!

事实上,有几种方法可以让我的蛋白质组学研究变得更容易、更漂亮、更有用。我将在这里介绍一些。

  1. 根据我的结果制作一个熊猫数据框架,并在上面执行功能

如果我能够轻松地计算出我生成的数据的各种统计元素,我的生活将会得到很大的改善,Pandas 使这比用 Excel 甚至(恐怖地)用笔和纸写我糟糕的笔迹容易得多。

我的数据看起来像什么的一个基本例子

使用 Pandas 和 Seaborn,我能够在很短的时间内做出更好的可视化效果,尽管是基本的可视化效果,而不需要使用 Excel。

当然,这是从我的数据集的汇总总数的基本重建。进一步的改进可以通过使用熊猫来创建总数、平均数等,以查看我发现的各种潜在的个体数量。

2.快速轻松地从我的数据中剔除噪音。通过使用。替换和。是空函数,我可以排除那些我不能识别任何特定属的结果(属的复数)。有上百个这样的东西!

3.将来也许可以用机器学习来识别模式,这样我就不用全靠眼睛了!

机器学习的基本工作方式

我的计划是利用其他人用同样的技术产生的大量数据,然后把我自己的数据加入其中。我想,这最终会让我避免大约三周的眼睛疲劳。

4)任何科学考古学家的终极梦想——潜在地创造一个能帮我切割骨头碎片的机器人。这是一项需要非常小心的任务,正确完成这项任务极其重要。大多数合适的古老股票的骨头碎片是非常罕见的,所以如果你的机器人咀嚼它并把它变成灰尘,没有太大的希望找到另一个。真正锤这个家——丹尼索瓦人的物种是通过分析一个手指骨发现的!

当然,事情远不止如此。我基本上只使用了我在熨斗的课程中不到一个月学到的技术和战术。尽管如此,即使是基本的观想。sum()命令和其他 python 函数会让我的生活变得简单很多。像 Biopython 这样的库使得生物分析进行起来更加顺利,甚至可以对基因组数据进行操作!

谁知道呢,也许再过几个月,我就能制作一个模型来再次检查我所有的数据点,并发现我在那些年前漏掉了一个人类。

我真的真的希望我没有…

原型神经网络从胸部 X 线诊断新冠肺炎

原文:https://towardsdatascience.com/prototyping-a-cnn-to-diagnose-covid-19-from-chest-x-ray-e1224a8e7795?source=collection_archive---------30-----------------------

胸部 x 光显示肺炎

想象一个患有严重肺炎的病人走进急诊室。你(护士、医生)担心是新冠肺炎。你取一个鼻拭子,送去化验。根据您所在医院的位置,结果将在大约 12-24 小时内返回。在漫长的等待中,出于谨慎,患者被隔离,占用宝贵的空间,每次互动都需要戴上 N95 口罩,使用或许更昂贵的个人防护设备。这种长时间的等待是低效率的,并且卫生保健提供者需要信息来支持他们的决策。

我读过一些文章,讨论 AI 如何在胸透(CXR)上准确区分新冠肺炎的肺炎和其他形式的肺炎。这篇文章的目的是试图复制这一发现。如果这是真的,给病人一个 CXR 并用人工智能进行分析可能有助于医疗保健提供商更快地识别新冠肺炎,并促进资源的合理使用。

数据集:

该数据集包括来自新冠肺炎患者的 73 张后-前(PA)胸部 x 光片和来自非 Covid 肺炎患者的 73 张 PA 胸部 x 光片,总共 146 幅图像。

新冠肺炎的图像取自多个来源,包括一个意大利放射学网站,讨论 60 个新冠肺炎病例和在 Pubmed 上发现的研究文章。非 covid 肺炎图像取自 Kaggle 上的 RSNA 肺炎检测挑战赛中的训练图像。请注意,Kaggle 上还有另一个标签很好的肺炎数据集,但我认为在这种情况下使用它是一个错误,因为它的儿科人群。成人和儿童的 cxr 非常容易区分,特别是在胸腔的模式中,并且该算法可能使用该特征而不是疾病固有的特征来区分类别。

让我们来看一些样本数据。

正如你所看到的,这两个类看起来非常相似。

样本图像

迁移学习 ResNet34:

迁移学习用于适应小数据集。ResNet34 被选为模型架构的基础,并被训练了 7 个时期,结果如下:

7 个时期的训练结果

验证准确率约为 86%。

验证集的混淆矩阵显示在 29 张图像上只出现了 4 个错误!

对于这么小的数据集来说,这已经很不错了。

仔细看看错误,下面和左边是一个肺炎病例的例子,模型确定是新冠肺炎,右边是一个新冠肺炎病例,模型确定是肺炎:

左:肺炎被归类为新冠肺炎。右图:新冠肺炎被归类为肺炎

接下来,我们来试试微调。

微调:

我们解冻网络的层,并允许它们以非常小的梯度变化。这允许更新参数以更好地适应数据集,同时有望防止过度适应。

我们微调了 2 个时期,我们的准确率从 86%到 89.7%!

在这篇文章中,我们已经建立了一个卷积神经网络的原型,它可以在胸部 x 射线上区分新冠肺炎和老式肺炎,准确率接近 90%!

最令人印象深刻的是这是用很少的数据完成的,只有 146 张图片。对于 500 或 1000 张图像,我怀疑准确率可以达到 95%以上。

小数据集是这项研究的最大弱点,因为它可能会发生一些过度拟合。鉴于数据匮乏,这可能是不可避免的。此外,只要验证损失大于训练损失,我们就不能过度拟合。

已经发表的研究表明,人工智能可以区分新冠肺炎和肺炎。使用 CT 扫描,似乎比 CXR 更能够可视化新冠肺炎,研究人员开发了一个人工智能系统,它可以区分新冠肺炎和肺炎,灵敏度为 90%,特异性为 96%!

这些是非常令人印象深刻的结果,并有望刺激医疗保健界考虑将放射图像与人工智能结合作为诊断新冠肺炎的潜在方法,直到更快速的诊断技术变得普遍。

像往常一样,在评论中留下你的想法。谢了。

用 Streamlit 构建机器学习模型原型

原文:https://towardsdatascience.com/prototyping-machine-learning-models-with-streamlit-1134c34e9620?source=collection_archive---------38-----------------------

使用 Streamlit 在不到 5 分钟的时间内设置好 GPT-2 演示

照片由在 Unsplash 上的拍摄

GitHub Repo:ml-streamlit-demo

在笔记本电脑环境之外引入机器学习模型,并将其转化为漂亮的数据产品,过去需要做大量工作。幸运的是,在这个领域有很多工具正在开发中,以使原型制作更容易。不久前,我偶然发现了 Streamlit ,这是一个用于构建定制 web 应用的开源 Python 库。

它的入门既快速又简单,我用了不到 30 分钟的时间就用一个预先训练好的模型构建了一个应用程序。从那以后,我一直在使用 Streamlit 进行模型原型制作,并展示它们的功能。与使用我的控制台进行预测相比,漂亮的用户界面是一个令人耳目一新的变化。

我将在本文中分享这个过程,以 GPT-2 为例。

在本文中,我们将:

  • 从 HuggingFace 的变压器库加载 GPT-2
  • 使用 Streamlit 在一个简单的 web 应用程序中提供文本生成器

从变压器加载 GPT-2

GPT-2 是在非常大的英语语料库上训练的变形金刚模型,用于预测短语中的下一个单词。它最近的继任者, GPT-3 ,用它的能力震惊了世界。

让我们从安装所有 Python 先决条件开始。这就是我的requirements.txt的样子。虽然代码中没有提到,但 GPT-2 要求安装 TensorFlow 2.0 或 PyTorch。

streamlit==0.56.0
tensorflow==2.2.0
transformers==3.0.2

在本例中,我们将使用一个 Python 脚本。这是加载 GPT-2 的类,当给定一个起始短语时,用它来生成文本。max_length属性表示生成文本的最大长度。

用 Streamlit 服务模型

我将定义另一个函数来实例化生成器。这个函数的目的是帮助缓存load_generator方法,以便更快地进行后续预测。

st.cache decorator 告诉 Streamlit,如果函数已经执行了,就跳过执行。

这个文件的入口点定义了 UI 的布局。

快速演示

要启动应用程序,请运行streamlit run filepath.py。如果你使用我的库,这将是streamlit run models/gpt_demo.py

该应用程序应该会在浏览器中自动启动。如果没有,就在 http://localhost:8501/ 。加载生成器后,预测应该会快得多!

我还没有使用过这个,但是如果你点击汉堡菜单(右上角的 3 条水平线),有一个使用 Streamlit 录制你的演示的选项。相当整洁。

让 GPT-2 完成一些想法!

我渴望…

建造时间机器的秘密…

这就是你所拥有的——一个在 5 分钟内构建的漂亮的网络应用程序。

如果你有兴趣学习更多关于自然语言处理的知识,可以看看这个 Coursera 课程。

[## 自然语言处理

本课程涵盖了从基础到高级的自然语言处理的广泛任务:情感分析…

click.linksynergy.com](https://click.linksynergy.com/link?id=J2RDo*Rlzkk&offerid=759505.11503135394&type=2&murl=https%3A%2F%2Fwww.coursera.org%2Flearn%2Flanguage-processing)

感谢您的阅读!

通过 Medium 关注我的最新动态。😃

作为一个业余爱好项目,我还在www.dscrashcourse.com建立了一套全面的免费数据科学课程和练习题。

再次感谢您的阅读!📕

我的视频搜索引擎原型

原文:https://towardsdatascience.com/prototyping-my-video-search-engine-d6fb03c9bcd1?source=collection_archive---------57-----------------------

在的上一篇文章中,我评估了我的物体探测器的准确性,它在一场视频录制的比赛中发现了一个乒乓球。平均精度为 0.57,模型的例子在以前从未见过的镜头上推广得很好,我鼓起勇气组装了这个原型:

概括地说,我分享了这个问题和关于走向数据科学的建议:

制作视频很容易,但是谁有时间看完呢?我提出一个视频搜索引擎来寻找相关的时刻。。。。我的目标是建立一个原型,它将视频记录乒乓球比赛,当球在比赛时提取视频剪辑,并向用户显示相关剪辑。

这篇文章展示了我的视频搜索引擎的端到端原型。

系统设计

我喜欢从最终结果开始,然后反向工作来规划整个系统。我的目标是提供一个简单的浏览器体验,播放完整长度的视频,并为用户提供观看精彩片段的选项。

我制作了一个系统图,这样我就可以理解我将要编码的每个组件。总体而言,我的系统包括三大要素:

  1. 函数获取视频文件,解析它的帧,在每帧上调用我的机器学习算法,并存储每个剪辑的相关时间戳;
  2. 一个剪辑时间戳的数据库,当用户点击“观看精彩片段卷”按钮时,可以从浏览器调用该数据库;和
  3. 根据用户输入播放全长视频或精彩片段的 web 体验。

以下部分包括 Python 代码和对每个元素的解释。

1.用我的物体检测算法处理视频

我首先导入相关的包并初始化变量:

import boto3
import cv2
import datetime
import json
import pytz
from pytz import timezone
import os

dynamodb = boto3.resource('dynamodb', region_name=os.environ["AWS_DEFAULT_REGION"],                          aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"],
aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"])ddb_table = dynamodb.Table("pp-video-clips")runtime_client = boto3.client('sagemaker-runtime')
endpoint_name = 'pp-ball-detector-endpoint'test_video_file = 'tt-video-1080p.mp4' # from local in example to save time & money
crop_x1 = 710
crop_x2 = crop_x1 + 512
crop_y1 = 183
crop_y2 = crop_y1 + 512
timestamps = [0.0]
detection_threshold = 0.50
lookback_frames = 30
last_n_detections = [0] * lookback_frames
nth_iteration = 0
shouldSaveTimestamp = 0
last_n_shouldSaveTimestamp = [0, 0]
nth_iteration_shouldSaveTimestamp = 0
ith_frame = 0
clip_id = 0
clip_start_time = None
clip_end_time = None

在这个例子中,我使用 2018 年美国国家乒乓球锦标赛视频作为test_video_file:

我用 CV2 打开视频文件,并把它放在一个cap变量中。然后,我存储视频中的最后一帧,因为它将帮助我处理剪辑没有其他结束时间戳的边缘情况。(详见下一节。)

cap = cv2.VideoCapture(test_video_file)
cap.set(cv2.CAP_PROP_POS_AVI_RATIO,1) # fast forward to video end
last_frame = cap.get(cv2.CAP_PROP_POS_FRAMES) - 1 # get final frame
cap.set(cv2.CAP_PROP_POS_AVI_RATIO,0) # rewind to beginning

接下来,我在一个while循环中处理每个视频帧。虽然有许多摄像机角度,但大多数相关内容都出现在桌面周围。由于我的 ResNet-50 对象检测器需要一个 224 x 224 像素的输入图像,因此我简化了这个原型,在每一帧中裁剪一个固定的正方形来检测正在运动的球。

while (cap.isOpened()):
    frame_exists, frame = cap.read()
    if frame_exists == False:
        break
    if frame_exists:
        timestamp = cap.get(cv2.CAP_PROP_POS_MSEC)
        crop_frame = frame[crop_y1:crop_y2, crop_x1:crop_x2]

例如,大多数匹配都是从这个摄像机角度发生的:

我的代码使用带有crop_frame = frame[crop_y1:crop_y2, crop_x1:crop_x2]的绿色方块,并将其传递给我的 Sagemaker 模型端点:

height = crop_frame.shape[0]
width = crop_frame.shape[1]
success, encoded_frame = cv2.imencode('.png', crop_frame)

response = runtime_client.invoke_endpoint(EndpointName=endpoint_name, ContentType='image/png', Body=encoded_frame.tobytes())result = response['Body'].read().decode('ascii')detections = json.loads(result)

detections结果包括按置信度降序排列的 N 次检测。我选择列表中的(第一个)最佳检测,因为我的领域特定的应用程序假设在任何给定时间只能有一个乒乓球在运动。我还获取最佳检测的置信度得分,并计算边界框的 x,y 坐标:

best_detection = detections['prediction'][0]
(klass, score, x0, y0, x1, y1) = best_detection
xmin = int(x0 * width)
ymin = int(y0 * height)
xmax = int(x1 * width)
ymax = int(y1 * height)

接下来,我通过比较best_detection得分和detection_threshold来确定是否检测到球。我尝试了各种阈值,我发现 0.5 到 0.7 之间的值效果最好,前提是我们使用 30 帧的缓冲区(下面的将详细介绍)。

if score > detection_threshold:
    ball_detection = 1
else:
    ball_detection = 0

到目前为止,一切顺利。我们现在有了视频中每一帧的检测输出!

2.将剪辑存储在数据库中

但是有一个问题。鉴于视频压缩模糊和球的高速度,在frame-n中,球检测器可能会错过球(得分刚好低于 detection_threshold),在frame-n+1中找到球,然后在frame-n+2中错过球。如果我们从这个信号中创建视频剪辑,它将导致短暂、不连贯的突出显示。这个信号处理问题被称为去抖。

为了解决这个问题,我创建了一个缓冲区来确定是在当前帧还是在上一个n-frames中检测到球。目标是获得变量shouldSaveTimestamp的输出模式:

这个帧缓冲器允许球检测器偶尔出错,否则有一个总的肯定信号表明有球在运动。

使用shouldSaveTimestamp变量,我们可以通过在shouldSaveTimestamp从 0 → 1 时保存start_timestamp和在shouldSaveTimestamp从 1→ 0 时保存end_timestamp来进一步识别剪辑。

# create n-Frames buffer; feed latest detection back one position
for nth_frame in range(len(last_n_detections)):
    if nth_frame < len(last_n_detections) - 1: # if not the last element, then:
        last_n_detections[nth_frame] = last_n_detections[nth_frame+1]
    else:
        last_n_detections[nth_frame] = ball_detection# identify when the ball is in play using the buffer
if (ball_detection > 0 or sum(last_n_detections) > 0 ):
    shouldSaveTimestamp = 1
else:
    shouldSaveTimestamp = 0# create a buffer to identify 0->1 and 1->0 clip conditions
last_n_shouldSaveTimestamp[0] = last_n_shouldSaveTimestamp[1]
last_n_shouldSaveTimestamp[1] = shouldSaveTimestamp# if shouldSaveTimestamp goes from 0 to 1, save "start timestamp"
if last_n_shouldSaveTimestamp[0] == 0 and last_n_shouldSaveTimestamp[1] == 1:
    clip_start_time = timestamp

# if shouldSaveTimestamp goes from 1 to 0, save "end timestamp"
if last_n_shouldSaveTimestamp[0] == 1 and last_n_shouldSaveTimestamp[1] == 0:
    clip_end_time = timestamp# handle some edge cases:
if ith_frame == last_frame and clip_start_time is not None:
    # take the last timestamp as the end time
    clip_end_time = timestamp

if ith_frame == last_frame and clip_start_time is None:
    # take the whole video as a clip :(
    clip_start_time = 0
    clip_start_time = timestamp

如果我们有有效的开始和结束时间戳,剩下的就是在数据库中保存一个剪辑。我选择 DynamoDB 是因为它具有无模式的设计,以及与前端框架(如 React)的简单、有据可查的连接。

if (clip_start_time is not None and clip_end_time is not None):
    # Persist clip to DynamoDB
    clip_start_time = round(clip_start_time/1000, 1)
    clip_end_time = round(clip_end_time/1000, 1)
    ddb_item = {
        'video_filename': str(clip_id),
        'start_end_times': '{},{}'.format(clip_start_time, clip_end_time)
    }
    ddb_table.put_item(Item=ddb_item)
    # reset clip start/end times
    clip_start_time = None
    clip_end_time = None
    clip_id += 1# increment the frame counter before looping back to the top
ith_frame += 1

就是这样!下面是代码处理一个示例视频时我的日志输出:

然后,验证数据的甜蜜喜悦传到了 DynamoDB:

我应该提到,出于诊断目的,我在主while循环中添加了以下代码:

draw_bb_on_frame(ith_frame, crop_frame, score, xmin, ymin, xmax, ymax)# where this function is defined earlier:
def draw_bb_on_frame(ith_frame, image, score, x0, y0, x1, y1):
    cv2.rectangle(image, (x0,y0),(x1,y1), (0, 0, 255), 1)
    cv2.putText(image, "Confidence: {:.4f}".format(score), (10, 30),
                cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
    if not cv2.imwrite('cv2-test-' + str(ith_frame) + '.jpg', image):
        raise Exception("Could not write image")

该代码片段在每个视频帧上绘制分数和边界框。不需要或不建议在最终原型中包含这一步骤,因为(1)它通过为每一帧写入一个图像来限制运行速度,并且(2)产生 21,000 多个图像(1.35 千兆字节!)同时处理一个 12 分钟的视频。但是当我调试系统和调整detection_threshold值时,这个函数对于诊断发生了什么非常有用。

3.为 Web 浏览器构建精彩片段卷

接下来,我将展示如何加载视频,并使用获取的时间戳从浏览器调用数据库,以便在用户单击“highlight reel”按钮时对剪辑进行排序和自动播放。

我从一个基本的 React 应用程序npx create-react-app pp-web-ui && cd pp-web-ui开始。然后,我添加一个视频播放器。虽然有许多选项可用,但我还是推荐 Video.js ,因为:

  • 它支持媒体片段协议使用开始/结束时间戳标记剪辑,并且
  • 它支持一个播放列表插件来排序和自动播放多个这样的剪辑。

我运行npm install video.js && npm install videojs-playlist,在 web 应用程序中实例化一个视频播放器,并加载完整的视频剪辑。为此,我在 React 应用程序的/components目录中创建了一个新组件VideoPlayer.js

import React from 'react';
import videojs from 'video.js'
import 'video.js/dist/video-js.css';
import './VideoContainer.css';export default class VideoPlayer extends React.Component {

  componentDidMount() {
    // instantiate Video.js
    this.player = videojs(this.videoNode, this.props.vidOptions, function onPlayerReady() {
      console.log('onPlayerReady', this)
    });
  }// destroy player on unmount
  componentWillUnmount() {
    if (this.player) {
      this.player.dispose()
    }
  } render() {let playerStyle = {      
            margin: '10px auto',      
          }return (
      <div> 
        <div data-vjs-player>
          <video  ref={ node => this.videoNode = node } 
                  className="video-js"
                  style={playerStyle}
          >        
          </video>
        </div>
      </div>
    )
  }
}

然后,我将那个VideoPlayer.js组件放在一个单独的容器组件中,在那里我处理数据库逻辑:

import React, { Component } from 'react';
import VideoPlayer from './VideoPlayer';
import './VideoContainer.css';const videoJsOptions = {
          autoplay: true,
          controls: true,
          height: 480, 
          sources: [{
                        src: '[http://localhost:3000/tt-video-1080p.mp4'](http://localhost:3000/tt-video-1080p.mp4'),
                        type: 'video/mp4'
                    }]
        }class VideoContainer extends Component {
    constructor(props) {
        super(props);
    }componentDidMount(){

    } render() {
         return (
                <div>
                    <VideoPlayer className="center" vidOptions={videoJsOptions} />;
                </div>
            </div>
        )
    }
}export default VideoContainer;

然后,我将VideoContainer.js组件添加到主 App.js 文件中,以在浏览器中显示视频:

import React from 'react';
import logo from './logo.svg';
import './App.css';
import VideoContainer from './components/VideoContainer';
import 'bootstrap/dist/css/bootstrap.min.css';function App() {
  return (
    <div className="App">
      <VideoContainer />
    </div>
  );
}export default App;

简单——源视频现在可以在网络浏览器上播放了!另外,上面的三个组件代表了前端体验的整个框架。在下面的剩余部分中,我更新了VideoPlayer.jsVideoContainer.js来获取时间戳,对它们进行排序,并在用户单击“highlight reel”按钮时自动播放剪辑。

从 DynamoDB 获取时间戳 onClick

在本节中,我添加了 AWS-SDK 包并调用 DynamoDB 的.scan函数来获取数据库中的所有时间戳。

首先,我执行npm install aws-sdk,导入包,并初始化VideoConainer.js中的变量:

import * as AWS from 'aws-sdk';AWS.config.update({
  region: 'us-east-1',
  endpoint: 'dynamodb.us-east-1.amazonaws.com',
  accessKeyId: 'USE-YOUR-OWN',
  secretAccessKey: 'USE-YOUR-OWN'
});

注意:我在这个例子中硬编码了 DynamoDB 凭证,只是出于教学目的。accessKeyIdsecretAccessKey 不应该硬编码在应用程序或浏览器脚本中。

接下来,我更新componentDidMount来初始化 DynamoDB:

componentDidMount(){
        this.dynamodb = new AWS.DynamoDB();
        this.docClient = new AWS.DynamoDB.DocumentClient();

    }

然后,我添加了一个 click handler 函数,它从 DynamoDB 获取时间戳,按照剪辑 ID 的升序对剪辑进行排序(在我的代码中称为video_filename,并创建一个videojs-playlist插件所期望的sources数组:

onClickHandler(){
        var params = {
          TableName: 'pp-video-clips',
         };this.dynamodb.scan(params, (error, result) => {
            if (error) {
                console.log(error);
            } const allVideosObjects = result.Items const sortedVidObj = allVideosObjects.sort((a, b) => (a.video_filename.S > b.video_filename.S) ? 1 : -1) const videosObjects = sortedVidObj.map(item => { return {
                    sources: [{
                         src: '[http://localhost:3000/tt-video-1080p.mp4#t='+item.start_end_times.S](http://localhost:3000/tt-video-1080p.mp4#t='+item.start_end_times.S),
                        type: 'video/mp4'
                    }]
                }      
            })

            this.setState(videosObjects);
        })            
    }

您会注意到src键/值对包括这个特殊的标记#t='item.start_end_times.S',它表示一个媒体片段。这告诉视频播放器只播放来自time = {start_time},{end_time}的一个片段,然后暂停。

然后,我更新了VideoContainer.js组件的render()块,以(1)获取状态变量(在那里我存储了sources的数组),(2)根据视频播放器应该播放完整长度的剪辑还是高亮剪辑的数组,有条件地呈现视频播放器,以及(3)如果单击了“观看高亮卷”按钮,则调用 onClickHandler 函数:

render() {        
        let videosObjects = this.state; 
        var videoSourcesArray = Object.values(videosObjects);let videoBlock;
        if (videoSourcesArray && videoSourcesArray.length) {
          videoBlock = <VideoPlayer className="center" vidOptions={videoJsOptions} vidSources = {videoSourcesArray} />;
        } else {
          videoBlock = <VideoPlayer className="center" vidOptions={videoJsOptions}/>;
        }return (
            <div>
                <h2 className="center big">Rod's Video Search Engine</h2>
                <div className="pad20">
                    <button className="btn_reel" onClick={() => { this.onClickHandler() }}>
                        Watch Highlight Reel
                    </button>
                </div>
                <div>
                    {videoBlock}
                </div>
            </div>
        )
    }

使用 Video.js 播放列表自动播放剪辑

在这一节中,我将演示如何使用 Video.js 播放列表来自动播放剪辑。

首先,我导入包并在VideoPlayer.js中注册插件:

import videojsPlaylistPlugin from 'videojs-playlist';
videojs.registerPlugin('playlist', videojsPlaylistPlugin);

然后我修改componentDidUpdate来接收来自 DynamoDB 的视频源数组,并开始自动播放剪辑,每个剪辑之间间隔 0 秒:

componentDidUpdate() {
     this.player.playlist(this.props.vidSources);
     this.player.playlist.autoadvance(0);    
  }

一个挑战是媒体片段在每个剪辑的结尾“暂停”视频,而不是使用“结束”事件。因此,为了让播放列表前进到下一个视频剪辑,我必须创建一个onPause处理程序:

onPause(){
    if(this.props.vidSources && this.props.vidSources.length > 0) {
      this.player.playlist.next();
    }
  }

这种方法的一个缺点/优点是点击视频算作一个onPause事件,它会自动快进到下一个剪辑。让我们把它记为一个特性,而不是一个 bug 😉

最后,我更新了render()块中的return语句来监听onPause事件,该事件调用onPause处理函数:

return (
      <div> 
        <div data-vjs-player>
          <video  ref={ node => this.videoNode = node } 
                  className="video-js"
                  style={playerStyle}
                  onPause={() => { this.onPause() }}
          >        
          </video>
        </div>
      </div>
    )

转眼间。完整长度的视频在加载网络应用程序时播放,当用户点击“观看精彩片段卷”按钮时,球在剪辑帧视频剪辑自动播放。以下是完整视频(左)和高亮显示的视频片段(右)的对比:

在未来的版本中,我应该改进一些东西:

  • 这些剪辑并不完美,有时这个原型在不到 2 秒的时间内就能剪辑好一个剪辑。我应该考虑一个更长的帧缓冲区来防止这种情况。
  • 我用clip_idstring而不是integer创建了 DynamoDB 表,因此对剪辑的排序是不正确的(例如,剪辑 99 在剪辑 10 之前播放)

在真实场景中评估原型

虽然上面的精彩镜头感觉很神奇,但它的工作应该不会令人惊讶,因为我在来自同一视频源的 2000 帧上训练了我的算法。

真正的问题是:

这个系统与真实世界的录音相比表现如何?

幸运的是,我的朋友保留了记录的比赛,供他的教练训练他。

哦,哦…一个白色的球在白色的墙上…🤦‍♂️

我没有被吓住,处理了视频。但该系统产生的剪辑非常短,可能是由于摄像机角度和白墙上的白球的置信度较低。该图绘制了相对于视频时间戳的置信度得分:

在 0.30 的detection_threshold处有很多好的(真阳性)检测,但是也有同样多的假阳性,如果不是更多的话。将阈值提高到 0.40(橙色虚线)消除了大多数假阳性,尽管我留下了一些真阳性(参见时间戳 27.9 秒处的红色标记)。).我觉得这是一个可以接受的权衡,我重新处理了视频,耗时 4.76 小时。

以下是我的“集锦卷”(右)与完整视频(左)的对比:

我的模型删除了大约 4 分钟的无趣内容(当球不在时,36%的录制时间)。在给 Sandeep 看了“精彩片段”之后,他点了点头,笑了笑,并感叹道“太棒了!”

未来方向

有许多问题值得探讨。举个例子,

  • 如果玩家使用橙色乒乓球,模型会失败吗?
  • 对于探测比赛中的球来说,一些摄像机角度更差吗?
  • 我可以升级前端体验,允许用户上传他们自己的视频并识别“感兴趣的领域”吗?
  • 我可以通过使用 PyTorch 或 Keras 滚动我们自己的卷积神经网络来提高模型精度吗?
  • 我可以加快视频处理时间吗?(剧本花了 6 个小时处理了 12 分钟的视频!)
  • 我能多快多容易地将这个原型推广到其他运动,比如击剑或网球?
  • 如果我们需要预测多个类别(例如,“比赛中的球”与“比赛中的球”或“发球中的球”),性能会如何变化?

在未来的几个月里,我将继续探索这些问题。如果你对我的结对编程感兴趣,请在评论区留言,我们可以在周末找到时间!

通过免费服务提供和绘制数据非常简单

原文:https://towardsdatascience.com/providing-and-plotting-data-with-free-services-is-easy-c3176f4323f7?source=collection_archive---------58-----------------------

从开放数据提供商那里收集和提取数据,将它们放在一个新的数据集中,通过使用免费服务来发布和可视化数据?这比你想象的要容易。

照片由艾萨克·史密斯在 Unsplash 拍摄

由于科罗纳疫情提供了大量免费的可访问数据,我有了将我在德国居住的农村地区的 7 天发病率可视化的想法。罗伯特-科赫研究所 (RKI)提供了一个开放数据集,包含德国每个县的所有数字。对于可视化部分,我想尝试一些易于使用的服务。最近,我在德国新闻网站上偶然发现了一些很棒的可视化效果。他们(以及更多人)正在使用德国一家名为 Datawrapper 的初创公司提供的服务。他们还提供一些免费服务——太好了,让我们使用它们吧!最后,我想使用一个用于发布数据的开放平台 Qri 来发布我收集的数据。

让我们看看这些步骤,直到我可以创建和发布可视化。

  1. 定期收集和保存数据
  2. 将数据推送到存储库中
  3. 连接数据并创建可视化效果

定期收集和保存数据

不幸的是,RKI 没有公布我想要使用的数字的时间序列数据。只有实际日期的数字。我创建了一些 Python 脚本来收集实际数据,提取我想要使用的数字,添加并保存到我的 CSV 文件中。该脚本每天在我的家庭办公室的一个简单的 Raspberry Pi 上使用 cronjob 运行。我正在使用熊猫打开远程 CSV 的内置功能。这个脚本非常小,几乎不言自明。

import pandas as pd
import os.path

# Get Data
df = pd.read_csv("https://opendata.arcgis.com/datasets/917fc37a709542548cc3be077a786c17_0.csv")

# Get desired row (128 - Rheingau-Taunus)
rtk = df.loc[[128], ['last_update', 'cases','cases_per_100k', 'cases7_per_100k', 'deaths']]

# Update data type
rtk['last_update'] = pd.to_datetime(rtk['last_update'], format="%d.%m.%Y, %H:%M Uhr")

# Add row to CSV
use_header = False if os.path.isfile('rtk.csv')  else True
rtk.to_csv('rtk.csv', mode='a', header=use_header, index=False)

我算出我的县的 ID 是 128。现在很容易提取数据。由于数据集使用了奇怪的德国日期格式,我用熊猫to_datetime转换了它们。

最后,我将我的数据添加到 CSV 中。就是这样!下一步是使用 Qri 提供数据。

将数据推送到存储库中

Qri 是一个开源项目,旨在为数据集同步、版本控制、存储和协作构建软件。有点像数据集的 GitHub。它们提供了 GUI 客户端和 CLI 工具。我正在使用 CLI 工具来进行版本控制,并定期将我的数据集推送到他们的(免费)云空间,我可以将我的数据集作为开放的免费资源分享给其他对做酷的事情感兴趣的人。您可以提供一个自述文件,并为您的数据集添加一些元信息(字段描述等)。).关于设置说明,我参考了他们的 CLI 快速入门指南。使用 CLI 工具初始化和发布数据后,您的数据将可在其云空间中访问。我的数据就在这里。

当我得到我的数据的更新版本时,我只需保存新版本并将它推到云中。

$ qri save --body ../inzidenz-rtk.csv
$ qri push

这个过程仍然是手动的,因为 CLI 工具不能在 Raspberry Pi 上工作。我的计划是将这些步骤添加到我的 cron 作业中,以实现完全自动化的发布。到目前为止,手动就足够了。

我不会深入 Qri 的细节,并参考他们的文档来获得更多的见解。上面的过程对我来说有效,但可能不是最好的。如果有什么我可以改进的,请评论!

Qri 最棒的是集成部分。您可以获得最新.csv的链接,以便在您最喜欢的数据分析工具中使用。此外,其他 Qri 用户可以派生您的数据集。

最后,我使用数据集通过 Datawrapper 创建一个图。

连接数据并创建可视化效果

Datawrapper 是一个非常棒的可视化工具。它不像 Tableau、Mode 或 Datorama 那样用于构建复杂的仪表板。Datawrappers 主要关注的是制作干净漂亮的可视化效果本身。您可以使用标准的图表,如条形图、折线图、饼图、圆环图等。他们专注于创建独特的图表。每个情节看起来都棒极了。Datawrapper 还提供了几个非常棒的地图绘图。有了免费帐户,你可以使用所有这些,但你在风格上受到限制。但是它们的默认样式和模板已经很棒了,随时可以使用。

最好的功能是,您可以链接一个外部数据集,为您的数据提供一个 URL。当然,我使用的是我的数据集在 Qri 的 URL。

在 Datawrapper 中使用 CSV 的 URL

下一步是检查和描述您的数据集,以便以后在图中使用

选择要在可视化中使用的字段

在我的例子中,我使用了两列:last_updatecases7_per_100k。现在我们可以创建可视化。

在 Datawrapper 中设计和注释可视化

您可以细化、注释和设计可视化。使用免费版本,设计仅限于选择一个布局。您可以为某些部分选择颜色,如线条或注释,但您无法使用您公司的 CI 创建可视化效果。那是他们付费产品的一部分。对我来说,默认值已经足够了。

使用 Qri(或任何其他服务)连接数据的最大好处是:

如果您的数据已经更新,您只需重新发布您的图表,它就是最新的!

因为我使用了一些注释,比如日期和突出显示的范围,所以我需要做一些手工工作。其他一切都已经存在了。无需复制新数据、选择字段等。

我最终的可视化看起来是这样的(是的,Medium 可以嵌入 Datawrapper 可视化!)

嵌入媒体的最终可视化

结论

收集数据、为他人提供数据以及创建可视化效果比看起来容易。你不需要成为数据科学、数据工程或设计师方面的专家。即使不是开发人员,也可以使用许多很棒的工具。你专注于好的视觉化吗?关注数据包装器。它能很好地帮助你创建可嵌入的图表,将它们作为图片下载,甚至允许在他们的服务 River 中重用。有了 Qri ,你可以为大量受众提供数据集。使用他们的桌面客户端可以帮助那些不喜欢命令行界面的人。您关注的是结果,而不是创建结果的过程!

免责声明:我既没有参与 Datawrapper 也没有参与 Qri

[1]: 7 天发病率是每 100,000 名居民在 7 天内新感染的人数。
【2】:数据许可:数据许可德国—归属—版本 2.0/dl-de/by-2–0

证明伯努利幂和

原文:https://towardsdatascience.com/proving-bernoullis-sum-of-powers-22f50df188e9?source=collection_archive---------22-----------------------

如何计算 n 个第一整数的 p 次方之和

图片来自皮克斯巴伊的加里克·巴尔塞吉安。

在他的众多重要贡献中,著名的瑞士数学家雅各布·伯努利(1655–1705),他的家族(伯努利家族是总共八位世界著名数学家的起源)中的众多著名数学家之一,在 1713 年提供了一个关于第一个整数 np 次方之和的表达式(他称之为 Summae Potestatum )。他的解的形式是一个次数为( p + 1)的多项式函数,其中包含的系数涉及无处不在且现在著名的伯努利数(一个出现在数学和理论物理众多领域的分数序列)。

图 1:1713 年,杰出的瑞士数学家雅各布·伯努利(来源)发表了 Summae Potestatum,第一个整数的p次方之和的表达式(来源)。

这个和被称为福尔哈伯公式(以德国数学家约翰·福尔哈伯(1580–1635)的名字命名),他的结果伯努利以标题SummaePotestatum**,发表,是由下面的表达式给出

等式 1:第一个 n 个正整数的 p 次方之和,称为 Faulhaber 公式。

图 2:德国数学家约翰·福尔哈伯(1580-1635)。Faulhaber 是一个博学的人,他被训练成一个纺织工人,在几个城市的防御工事中工作,为军队建造水车和几何仪器,还有其他的事情(来源)。

正如这些关于数论的特殊讲座所指出的,如果把从索引 m =0 开始到索引 m = n -1 结束的总和写出来,计算会变得更加简洁。有了这种可供选择的指数,总和就变成了:

等式 2:等式。1 写入的和从索引 m =0 零开始,到索引 m = n -1 结束。选择这组新的指数“整理”了计算。

现在考虑所谓的母函数 S ( nt ),一个幂级数,它具有方程中的和。1 和 2 作为系数:

等式 3:生成函数具有等式 3 给出的和。1 和 2 作为系数。根据维基百科的说法,生成函数“是一种通过将数字视为幂级数的系数来编码无限序列的方式”。

代入等式。等式中的 2。3 我们得到双和:

等式 4:等式。3 在等式的替换之后。2.

其中 k 为整数。经过几个代数步骤用来重新排列总和,我们可以重新表达方程。4 由以下两个函数的乘积得出:

等式 5:等式。4 重写为两个函数的乘积。这个表达式是在重新排列和并执行一些简单的(但不是很有启发性的)代数运算后得到的。

情商。5 是通过重新排列等式中的双和得到的。并执行一些简单的(但不是很有启发性的)代数操作。现在, S ( nt )的第一个因子可以用指数函数的泰勒展开式写成一个幂级数:

等式 6:指数函数的幂级数展开。

(你只要从 Eq 的左边减去 1 就可以了。6 并将两边除以 x )。要写出 S ( nt )的第二项,就必须引入前面提到的伯努利数。等式中的函数 t /(e -1)。5 变成了:

等式 7:为了写出等式中 S ( nt )的第二个因子。5 一个介绍伯努利数。

跳过几个步骤(为了避免混乱),生成函数 S ( nt )变成下面这个错综复杂的表达式:

等式 8:等式 8 最初给出的生成函数。3 使用指数函数时间序列和 Eq。7(包含伯努利数)。

现在,下一步是定义所谓的伯努利多项式:

等式 9:下面图 3 所示的伯努利多项式的定义。

下图显示了对应于不同伯努利数值的伯努利多项式的几个示例。

图 3:伯努利数的几个值的伯努利多项式(来源)。

将母函数 S ( nt )的原始表达式与等式进行比较。8 和使用伯努利多项式的定义,我们得到:

等式 10:我们所追求的第一个整数的 p 次幂之和的最终表达式。

请注意,生成函数可以优雅地写成:

等式 11:生成函数的最终表达式,用伯努利多项式和伯努利数表示。

在之前的一篇文章(见下文)中,我推导出了前五个伯努利数。它们由以下各项给出:

等式 12:在这篇文章中导出的前五个伯努利数。

图 4:左边,日本数学家小和田硕。右边是他的作品胜代山保(1712)中的一页,在那里他将二项式系数和伯努利数制成表格。

* [## 关于倒数级数的和

伟大的数学家欧拉和他的伟大发现

towardsdatascience.com](/on-the-sums-of-series-of-reciprocals-6711437ad893)

使用 Eq。9 我们得到一些伯努利多项式(见图 3):

等式 13:第一个伯努利多项式。

现在我们有了所有需要的工具!下面是两个简单的例子,我们的总和后,但所有其他情况下可以平凡地获得:

等式 14:第一个整数的 p 次方之和的两个简单例子。*

我的 Github 和个人网站 www.marcotavora.me 有一些关于数学和其他主题的有趣材料,如物理、数据科学和金融。看看他们!

如何证明不等式

原文:https://towardsdatascience.com/proving-inequalities-aab03b0588d5?source=collection_archive---------12-----------------------

照片由 Antoine Dautry 在 Unsplash 上拍摄

帮助证明一个< b

When you develop an interest in mathematics and start working with material that takes proof seriously, sooner or later you’ll be trying to find proofs of inequalities.

Proving that something is 等于另一个的技术通常更容易一些。你以同样的方式操纵两边,直到你得出有问题的等式。你可能需要做一些巧妙的替换,但是你能做的事情也就这么多了。

由于传递性,不等式可能有点棘手。如果你想让某些人ab看到那个 a < b,那看起来可能会非常困难。如果没有显而易见的解决方案,可能有必要想出一些c,为此你可以显示a < c < b,从而暗示a < b

让我们看看这两种情况的例子,我们将从一个“简单”的例子开始,我们不需要发明中间产品。

例中所有的数字都是实数。

简单的例子

给定实数rs,显示如下:

发展直觉

让我们先花点时间对它说的话发展一种直觉。让我们为rs挑选一些数字,看看会发生什么:

1/2 < 2/3 < 3/4 < 9/10 < 99/100

好吧,我明白了。我可以接受。

现在我们如何证明它总是正确的呢?

扩展到相同的分母

为了比较分数,它有助于扩展分数,使它们具有相同的分母。我们必须用(1+s)延长左边,用(1+r)延长右边

让我们这样做,看看我们的立场。

现在分母相等了,原来我们可以把它们去掉。我们知道(1+r)(1+s)都是正数,所以我们知道它们的乘积(1+r)(1+s)是正数。逆1/((1+r)(1+s))也是如此。我们可以把两边都乘以倒数,有效地去掉分数。

我们不需要翻转不等式的方向,因为我们要乘的数是正数。

我认为这是进步。让我们开始吧。我们只剩下:

简化括号中的总和

将总和相乘,我们发现我们最终得到了两边的一个共同项:rs。我们两边都减去它,根据我们的给定得到一个真实的陈述。

颠倒您的步骤,提供易于遵循的证据

为了给出一个正式的证明,我们只需颠倒我们的探索步骤,所以从上到下阅读时,推理是有意义的。

我们的证明,吉文斯证明的每一步都是我们探索步骤的逆过程

从某种意义上说,这个证明很简单,因为它不需要我们在任何中间表达上有创造性。我们可以像处理等式证明一样处理这个证明。

让我们继续做一些更难的事情。

棘手的案子

给定任意两个实数xy,表明如下

发展直觉

哦天啊。那个看起来要求更高一点。首先,让我们对它所说的有一个直觉。让我们挑选x = y = 2,我们得到:

4/5 <= 2/3 + 2/3

好吧,让我们试试另一双:x = 2, y = -3

-1/2 <= 2/3 + 3/4

好的,看起来我们会一直保持在 1 以下,甚至低于 0。右边可以增长到 1 以上,永远不会低于 0,因为单个项永远不会变成负数。

注意,当我们选择x = 0y = 0时,左右两边变得相等。

好的,我们对正在发生的事情有一点直觉。让我们看看是否能证明这一点。

扩展到相同的分母

右边是分数的和。我们可以尝试形成总和,看看它如何与左边的相比较。我们需要用1+|y|展开左边的项,用1+|x|展开右边的项

好吧。所以这就是我们总结右手边时的样子。要证明的不等式变成了:

寻找已知的不平等

证明不等式时,你经常需要引入一个或多个额外的术语,这些术语介于你已经看到的两个术语之间。这通常意味着拿走或增加一些东西,这样第三个术语就滑了进来。

经常检查你的课本,寻找你应该知道的不等式,看看它们是否有用。练习也会经常建立在彼此的基础上。有时练习 a)的结果在练习 b)中很关键。所以不要“忘记”你之前的成绩。

在我们的例子中,我们看到两边看起来都类似于我们在第一个证明中处理过的熟悉的something/(1+something)模式。

让我们看看怎样才能让双方都符合我们已证明的不等式,这样我们就可以利用它了。

左边越来越长

让我们看看我们的左手边。

如果我们取分子x+y的绝对值,我们可以用r=|x+y|代替,我们的左手边将是r/(1+r)的形式。这样做肯定会增加期限。x+y的绝对值在x+y<0的情况下更大,或者在x+y≥0的情况下相等。

所以我们有:

看起来我们在左侧完成了。

收缩右手边

让我们看看我们的右手边。

为了达到我们想要的s/(1+s)形式,我们必须做些什么?

如果我们用s=|x|+|y|+|x||y|代替,我们会得到(s+|x||y|)/(1+s)。我们的分子中多了一个|x||y|。如果我们放弃它,我们的项要么保持不变——如果xy0就会是这种情况——要么收缩。因为如果xy都不是0,那么|x||y|就是正的,所以我们要减少分子的值。

因此,我们有:

我们已经达到了我们想要的形式s/(1+s)

把我们的鸭子排成一排

我们已经将两边分别转化为r/(r+1)s/(s+1)形态。这些是我们想要在我们最初的左手边和右手边之间滑动的术语。

如果我们能证明0 ≤ r < s,我们可以用我们的第一个结果

r/(r+1) < s/(s+1)

我们替换了r=|x+y|s=|x|+|y|+|x||y|。我们立即看到0≤r,因为它是一个绝对值。通过三角形不等式我们知道|x+y|≤|x|+|y|是真的,所以我们可以证明:

太好了!我们知道0 ≤ r ≤ s,可以用r/(r+1) ≤ s/(s+1)。我们可以把所有的条款都整理好。

我们做到了!

我们最初的左侧和右侧术语很难直接比较。但是我们可以在它们之间加入一些我们知道如何比较的术语,从而形成一个证明我们最初陈述的链。

结论

当证明不等式时,寻找以可控方式收缩或增长项的方法是有用的,这样它们就符合已知的不等式并形成传递链。

如果你觉得你已经记下来了,为什么不测试一下自己,从头开始证明这两个不等式呢?你刚刚读了解答,所以…这能有多难?

他们又来了。

第一个不等式:

第二个不等式:

你能行的!

用初等微积分证明素数的无穷性

原文:https://towardsdatascience.com/proving-the-infinity-of-primes-using-elementary-calculus-3386699801f4?source=collection_archive---------14-----------------------

图片由来自皮克斯拜的皮特·林福思拍摄

如何用一个简单的积分证明有无穷多个素数

为了正式定义素数,我将使用 G. H. Hardy 和 E. M. Wright 的经典数论著作《数论导论》中的定义的“改编”版本

图 1:英国数学家 G. H .哈代(来源)和 E.M .莱特(来源),著有名著*(*来源 )。

让我们只考虑正整数。其中,有一个特别重要的子类,即素数类。一个数 p 被称为质数,如果:

  • p > 1:数字 1 被认为既不是质数也不是合数。T4 不称 1 为质数的一个很好的理由是为了避免修改算术基本定理。这个著名的定理说“除了因子重排,一个整数只能用一种方式表示为质数的乘积*。”考虑到 1 是质数,这种因式分解的唯一性将会丢失(例如,我们可以将 3 写成 1×3,1×1×1×3,1⁴⁷⁴⁷⁵×3,等等)。*
  • p 除了 1p 之外,没有正约数

图 2:与合数相反,质数不能排列成矩形(来源)。

素数的无穷大

素数的数目是无限的。第一组是:2,3,5,7,11,13,17,19,23,29,31,37 等等。这个重要定理的第一个证明是由古希腊数学家欧几里德提供的。他的证明被称为欧几里德定理。

在这篇文章中,我将描述伟大的瑞士数学家莱昂哈德·欧拉只用基本微积分做的一个简单证明。我会看艾格纳和齐格勒的书。

图 3:下面等式定义的 π ( x )的值。1 为前 60 个整数(来源)。

让我们首先考虑小于或等于某个 xR 的素数的个数,其中 R 表示实数的集合:

等式 1:小于或等于某 x ∈ R. 的素数个数

这个函数被称为素数计数函数。我们可以随意给质数编号,但让我们按升序编号:

等式 2:以递增顺序编号的素数。

现在考虑下面举例说明的函数 f( x )=1/ x

图 4:函数 f(x)= 1/x(*来源 )。*

这个函数在区间[1,∞)上的积分是 x 的对数

等式 3:1/x 从 1 到 x 的积分等于 x. 的对数

现在将 1/ x 下方的区域与图中所示阶跃函数下方的区域进行比较。我们稍后将更仔细地验证,对于整数

等式 4:x 的区间。下面的 5 是服从的。

遵循以下两个不等式:

等式 5:证明所需的不等式。最后的和扩展到所有的mN只拥有小于或等于 x 的素数。

其中最后的总和延伸到所有的mN只拥有个质因数 p 使得:

为了清楚起见,让我们考虑一个例子,比如说 n =6。在这种情况下,等式中的间隔。4 是x∈【6,7】,不等式变成:

等式 6:等式的例子。5 代表 n=6。

第一个不等式可以从图 4 中读出。第二种呢?在这种情况下,上面不等式中的mN有哪些值?

  • 数字 2、3 和 5 只有一个素数。因为它们是素数,所以它们唯一的除数小于 6。
  • 合数 4 = 2 和 6 = 2 x 3 只有 2 和/或 3 作为质因数,并且都小于 6

加上项 1,刚刚列出的数(即 2、3、4、5 和 6)的倒数之和已经等于等式(1)中不等式之间的和。6 既然有无限多的 m s(即调和级数发散到∞),那么等式中的第二个不等式。6 是服从。更正式的演示见这个链接。

等式 7:调和级数→ ∞

现在,算术基本定理陈述“除了因子的重排,一个整数只能用的一种方式表示为质数的乘积所以情商里的每一个 m 。5 可以用以下形式的乘积来唯一地表示:

等式 8:等式中的每一个 m 。5 可以唯一地表示为形式的乘积。

其中 k s 是每个素数因子在 m 的因式分解中出现的次数。因此,等式中的总和超过了 m。4 可以表示为:

等式 9:等式中 m 的和。6.

(读者可以通过一个例子来验证这一点)。现在,括号内的和是一个简单的几何级数:

等式 10:等式括号内的几何级数。9.

图 5:比值= 1/2,第一项= 1 的收敛几何级数(来源)。

等式中的乘积。9 是所有小于或等于 x 的质数。因此,比较等式。9 带情商。1,我们为 Eq 获得。5:**

等式 11:等式。1 使用等式。9.

因为通常遵守下面的不等式

我们获得:

这意味着:

由于 log( x )是无界的,如下所示,

图 log x 函数(来源)。

素数计数函数π( x )也是无界的。因此,我们得出结论,存在无穷多个素数。

感谢您的阅读,再见!一如既往,我们随时欢迎建设性的批评和反馈!

我的 Linkedin 、个人网站 www.marcotavora.me 、以及 Github 都有一些关于数学以及物理、机器学习、深度学习、金融等其他话题的其他有趣内容!看看他们!

证明π的不合理性

原文:https://towardsdatascience.com/proving-the-irrationality-of-π-10bc5d84ea11?source=collection_archive---------13-----------------------

一个显著结果的简单证明

图片由来自 Pixabay 的 Gerd Altmann 提供。

根据定义,无理数是不能由整数的分数(或比率)构成的实数。像 1/2、3/5 和 7/4 这样的数字被称为有理数。像所有其他数字一样,无理数可以用小数来表示。然而,与实数的其他子集(如图 1 所示)相比,无理数的十进制扩展永远不会终止,也不会像循环小数(例如 1/3 = 0.333……)那样,以重复自身的序列结束(参见此链接)。在这组无理数中有π,它是圆的周长与直径的比值(如图 2 所示)。

图 1:这个图展示的是实数 R 的集合,它包括有理数 Q、Q 内部的整数 Z、Z 中包含的自然数 N 和无理数 R\Q(无理数集合不像其他的那样有一个符号)(来源)。

π的值已经被几个古文明用数值估算过了(见此链接)。然而,在 17 世纪,艾萨克·牛顿和戈特弗里德·莱布尼茨 T20 发现微积分之后,无穷级数开始被用来获得更好的近似。一个例子是:

它是由印度数学家桑加玛格拉玛的马达瓦首先发现的。对于 x =1,它变成了所谓的莱布尼茨π 公式:

其缺点是收敛非常慢。

图 2: π是无理数的一个例子。它是圆的周长与直径的比值。

无理数的另一个著名例子是 2 的平方根,它是由传奇哲学家萨摩斯的毕达哥拉斯的追随者发现的。据说最初,他们隐瞒了他们的发现,并根据传说,谋杀了梅塔蓬图姆的哲学家希帕索斯,因为他最终揭示了这个发现。

图 3:2 的平方根是无理数的一个例子(来源)。

我们在这里的目标是提供一个简单的证明π的无理数。为了做到这一点,我们将遵循尼文并从定义一个辅助函数 f ( x )开始。

引入辅助功能

让我们首先考虑以下(显然不相关的)函数:

等式 1:这个函数 f(x)将用于π的无理数的证明。

其中 n 为整数。这个函数可以写成幂展开式。例如,对于 n = 1、2 和 3,我们有:

等式 2:等式 2 给出的 f(x)展开的例子。1 表示 n =1、2 和 3。

一般来说,人们有以下等式:

等式 3:等式中的函数。1 写成幂展开。

这些系数很容易确定。例如对于 n =1,

并且对于 n= 3:

f(x)的性质

对于 0< x1,我们有:

等式 4:f(x)的第一性质。

这是 f ( x )的第一个重要性质。这是因为:

我们将需要 f ( x )的其他三个属性。其中两个是:

等式 5:f(x)服从的另外两个性质。

其中( m )是 m 阶导数。

我们需要的最后一个属性是:

这是一个整数。因此请注意, f ( x )的所有导数都是整数。同样,因为如果我们互换 x 和 1- x,函数本身及其导数在 x =1 时也是整数,所以 f ( x )保持不变。

这些特性可以通过一个简单的例子来说明。设 n =4。然后我们有:

从这里我们可以读出 c 系数的值:

我们可以看到所有的属性都被遵守(为了避免过度混乱,省略了情况 m =6 和 m =7):

证明π的不合理性

这个证明是由加拿大裔美国数学家伊凡·尼文提出的。人们从假设与我们想要证明的相反的情况开始。更具体地说,我们假设π是有理的:

等式 6:π有理的假设,和我们要论证的正好相反。

然后,我们构建以下函数:

其二阶导数(下面需要用到)是:

其中 Eq。5 用于消除比 2 n. 高的 f ( x )的导数

图 4:加拿大裔美国数学家伊万·m·尼文(来源)。

正如我们刚刚看到的, f ( x )及其所有导数在 x =0 和 x =1 时都是整数。这意味着 F (0)和 F (1),因此 F (1) + F (0),也是整数。我们现在使用以下标识:

其中 Eq。6 被用来消除 b 。综合双方,我们得到:

使用 Eq。4 我们得到:

但是对于足够大的 n :

这与我们之前发现的 F (1) + F (0)是整数相矛盾。最初的假设 Eq。6 因此是假的,π一定是无理数。如果π是理性的,π也会是理性的。因此π也一定是无理数,这就结束了证明。

这个证明的优雅和简单是不可否认的。它们让我们意识到纯数学可以有多美好。

我的 Github 和个人网站 www.marcotavora.me 有一些关于数学和其他主题的有趣材料,如物理、数据科学和金融。看看他们!

证明 e 的超越性

原文:https://towardsdatascience.com/proving-the-transcendence-of-e-65aaa2de69c3?source=collection_archive---------23-----------------------

欧拉数超越性的初等证明

图片由来自皮克斯拜的皮特·林福思拍摄

欧拉数eT7 是一个数学常数~2.718,定义如下:

等式 1:欧拉数 e 的一个可能定义。

这个常数是瑞士数学家雅各布·伯努利发现的。初等函数

等式 2:指数函数,唯一等于其导数的函数。

被称为指数函数,它等于它自己的导数(它是唯一具有这种性质的函数)。

图 1:方程 y = 1/ x 的绘图欧拉数 e 是唯一使阴影面积等于 1 的数(大于 1)(来源)。

超越数

实数可以是代数的,也可以是超越的。根据定义,n 次代数数 n 满足具有整系数的多项式方程,例如:

方程 3:整系数多项式方程。它由代数数来满足。

一个代数数为 n 次的事实意味着 xⁿ的系数非零。超越数是满足等式等方程的实数。3.

e 的超越

我们在这篇文章中的目标是证明 e 是一个超越数。这个证明的最初版本是由法国数学家查尔斯·埃尔米特提供的,但这里给出的版本是由德国数学家戴维·希尔伯特简化的。

图 2:法国数学家查尔斯·埃尔米特(来源)和德国数学家戴维·希尔伯特(来源)。

我们首先假设与我们试图证明的相反的情况,即 e 次数为 n: 的代数数

等式 4:如果 e 在 n 次代数数中,它满足这个等式,其中第一个和最后一个 a 系数非空。

我们开始证明用有理数逼近 e 的幂。我们定义了以下对象:

等式 5:用有理数逼近 e 的幂。

在哪里

对于等式中 e 的每个功率。5 我们有:

对于非常小的ϵ来说,这个等式意味着所有的 eᵗ都非常接近于一个有理数。我们现在用等式代替。5 转换成等式 4 并抵消因子 M 。我们获得:

等式 6:代入等式的结果。情商 5。4.

注意等式中的 n 。4 和 Eq。6 是相同的数量。情商。6 有两个明显的特点:

  1. 第一个括号内的表达式是一个整数,并且选择了 M 个整数,使得表达式不为零
  2. 在第二个表达式中, ϵ's 将被选择得足够小,使得表达式的绝对值为< 1

等式 7:等式中第二项所服从的性质。6.

我们的证明将包括证明那个等式。6 不可能是真的,它构成了一个矛盾。这是因为一个非零整数和一个带绝对值的表达式的和< 1 cannot vanish.

Defining the M’s and ϵ's

埃尔米特从定义 m 和ϵ开始。首先,他将 m 定义为:

等式 8:定义 m 的积分。

其中 p 被选为素数,这将在后面确定。质数 p 可以取我们想要的那么大(但是 M 对于 p 的任意值都是整数)。其他 m 和 ϵ 定义如下:

等式 9:定义等式中引入的 Ms 和ϵs 的积分 6.

我们现在通过选择 p 来继续,以便满足上面的属性 1 和 2。

让我们首先计算积分 M. 乘以分子中的二项式并将结果提升到 p,我们得到

等式 10:将等式分子中的二项式相乘。9

其具有整系数。将其代入 M 并使用

等式 11:阶乘 m 的积分表达式。

我们得出:

等式 12:等式。8 限制 p 大于 n。

将我们自己限制为大于 n 的素数,我们立即看到这个等式的第一项是而不是可被p整除,然而,我们可以很快看到第二项 展开阶乘:

方程式 13:方程式中的第二项。12 能被 p 整除。

由于 M 不能被 p 整除,等式中的第一个括号。6 也不能被 p 整除。现在考虑等式中的顶部积分。9.引入变量 y:

积分变成:

分子中括号内的多项式具有整系数,其项从

几步之后,我们到达:

对于整数 c s(其中等式使用了 11)。每个 M( k )是一个可被 p 整除的整数,因此等式中的第一个括号。6 不能被 p 整除,因此我们得出结论,等式第一个括号中的项。6 是非零整数。如果它是零,它会被 p 整除,我们只是得出结论,它不是。

剩下的最后一块就是展示那个情商。假设我们选择足够大的 p 值,则 7 为真。使用 Eq。9、经过几个步骤后我们发现:

如果二项式乘积的绝对值对于 x ∈ [0, n )有一个上界 B,我们得到:

由于 RHS → 0 as p →∞,证明结束。

我的 Github 和个人网站 www.marcotavora.me 有一些关于数学和其他主题的有趣材料,如物理、数据科学和金融。看看他们!

TensorFlow 2.x 的近似策略优化(PPO)

原文:https://towardsdatascience.com/proximal-policy-optimization-ppo-with-tensorflow-2-x-89c9430ecc26?source=collection_archive---------10-----------------------

理解 PPO 强化学习算法并用 TensorFlow 2.x 实现

Neenu Vimalkumar 在 Unsplash 上拍摄的照片

在本文中,我们将尝试理解 Open-AI 用于强化学习的近似策略优化算法。在一些基础理论之后,我们将使用 TensorFlow 2.x 实现 PPO。在你进一步阅读之前,我建议你看一下来自的演员-评论家方法,因为我们将为 PPO 修改那篇文章的代码。

为什么选择 PPO?

  1. 不稳定的策略更新:在许多策略梯度方法中,由于较大的步长,策略更新是不稳定的,这导致坏的策略更新,并且当这个新的坏策略用于学习时,它导致甚至更坏的策略。如果步子迈得小,就会导致学习速度变慢。
  2. 数据低效:很多学习方法是从当前经验中学习,在梯度更新后丢弃经验。这使得学习过程缓慢,因为神经网络需要大量的数据来学习。

PPO 可以很方便地克服上述问题。

PPO 背后的核心理念

在早期的政策梯度方法中,目标函数类似于LPG(θ)= Et[logπθ(At | ST)ˇAt]。但是现在我们将采用当前策略和旧策略的比率,而不是当前策略的日志。

照片经由https://arxiv.org/abs/1707.06347

我们还将削减比率,并将削减和不削减两者中的最小值,即 b/w。

照片经由https://arxiv.org/abs/1707.06347

如下所示,这个缩减的目标将限制大型策略更新。

照片经由https://arxiv.org/abs/1707.06347

因此,最终目标包含 3 个部分,第一个是 Lclip,第二个是我们的 critic net 的 MSE,即预测的和目标的状态值的平方损失。第三部分是鼓励探索的熵。

照片经由https://arxiv.org/abs/1707.06347

算法步骤

  1. 玩游戏 n 步,存储状态,行动概率,奖励,完成变量。
  2. 将广义优势估计方法应用于上述经验。我们将在编码部分看到这一点。
  3. 通过计算它们各自的损失来训练一些时期的神经网络。
  4. 测试这个训练好的模型的“m”次发作。
  5. 如果测试集的平均奖励大于您设定的目标奖励,则停止,否则从第一步开始重复。

密码

神经网络:

  1. 在导入了所需的库并初始化了我们的环境之后,我们定义了我们的神经网络,类似于 Actor-Critic 文章中的神经网络。
  2. 行动者网络将当前状态作为输入,输出每个动作的概率。
  3. 批评家网络输出一个州的价值。

动作选择:

  1. 我们定义我们的代理类,并初始化优化器和学习率。
  2. 我们还定义了一个 clip_pram 变量,它将在演员损失函数中使用。
  3. 对于动作选择,我们将使用 TensorFlow 概率库,它将概率作为输入,并将其转换为分布。
  4. 然后,我们使用该分布进行动作选择。

测试模型知识:

  1. 这个函数将用于测试我们代理的知识,并返回一集的总奖励。

训练循环:

  1. 我们将循环“步骤”时间,即我们将收集“步骤”时间的经验。
  2. 下一个循环是代理与环境交互的次数,我们将体验存储在不同的列表中。
  3. 在上述循环之后,我们计算并添加最后一个状态旁边的状态的值,用于广义优势估计方法中的计算。
  4. 然后,我们处理广义优势估计方法中的所有列表,以获得回报,优势。
  5. 接下来,我们为 10 个纪元训练我们的网络。
  6. 培训结束后,我们将在测试环境中对我们的代理进行五集测试。
  7. 如果测试集的平均奖励大于您设定的目标奖励,则停止,否则从第一步开始重复。

广义优势估计:

  1. 我们定义了一个预处理函数,它实现了计算回报和收益的 GAE 方法。
  2. 将变量“g”初始化为零,将 lambda 初始化为 0.95。
  3. 我们通过颠倒奖励列表从后面循环奖励。
  4. 将 delta 计算为(当前动作的回报+ gamma 下一状态的值对于终端状态为零的 done 变量-当前状态的值)。
  5. 将变量“g”计算为(delta + gamma * lambda * done 变量* g)。
  6. 将返回计算为(当前状态的 g +值)。
  7. 反转返回列表,就像我们从后往前计算一样。
  8. 优势的计算方式为(returns-values)。这里我们使用值[:-1]。毕竟,我们的值列表比所有其他列表大一个,因为为了计算的目的,我们添加了紧挨着最后一个状态的状态的值。

学习功能:

  1. 学习函数将(在与环境交互期间存储或计算的状态、动作、优势、概率、回报的数组)作为输入。
  2. 我们计算当前的概率和损失。评论家的损失是 MSE。
  3. 该函数使用渐变抽头执行渐变更新。

演员流失:

  1. 行动者损失将当前概率、行动、优势、旧概率和批评家损失作为输入。
  2. 首先,我们计算熵并计算平均值。
  3. 然后,我们循环遍历概率、优势和旧概率,计算比率、裁剪比率,并将其添加到列表中。
  4. 然后,我们计算损失。注意这里的我们采取了负损失,因为我们想执行梯度上升,而不是梯度下降。

这就是关于编码的全部内容。现在让我们看看您的代理没有学习的原因和一些技巧。

实施时需要注意的事项:

在编写 RL 代码时,要记住以下几点。

  1. 神经元的数量、隐藏层数、学习速率对学习有巨大的影响。
  2. 张量和 NumPy 数组的形状应该是正确的。很多时候,实现是正确的,代码也是有效的,但是代理没有学到任何东西,仅仅是因为张量的形状不正确,并且当对这些张量进行运算时会给出错误的结果

你可以在这里找到这篇文章的完整代码。敬请关注即将发布的文章,我们将在 TensorFlow 2 中实现更多 RL 算法和深度学习算法。

所以,本文到此结束。谢谢你的阅读,希望你喜欢并且能够理解我想要解释的内容。希望你阅读我即将发表的文章。哈里奥姆…🙏

参考资料:

[## 近似策略优化算法

我们提出了一种新的强化学习策略梯度方法

arxiv.org](https://arxiv.org/abs/1707.06347)

修剪卷积神经网络

原文:https://towardsdatascience.com/pruning-convolutional-neural-networks-cae7986cbba8?source=collection_archive---------23-----------------------

机器学习是各行各业的新流行语,是 21 世纪的精灵。它承诺了一切,从在繁重的体力工作中代替人类劳动,到为决策提供高水平的见解和分析。当与物联网(IoT)结合时,这种魔力将进一步增强,并可能创造一个世界,在这个世界中,我们的环境是我们大脑的延伸,并对我们的突发奇想和愿望做出智能响应。

然而,精灵越强大,它所需要的神灯就越大。换句话说,机器学习软件通常计算量非常大,因此不适合轻量级物联网设备。在这里,我们探讨卷积神经网络的想法,这是图像识别和对象检测中机器学习的一个关键方面,以及它们为什么不需要像现在这样庞大。

图 1:CNN 层如何将过滤通道应用于输入张量的图示

卷积神经网络(CNN) 通过将 N 个滤波器通道应用于输入图像(以下称为张量)来工作。假设一个输入张量在形状中(高度、宽度、先前通道的数量)。每个滤波器通道都可以看作是一个小权重盒,它围绕输入张量的高度和宽度,对该位置的值执行元素级乘法,并将它们相加,以在该位置输出单个值。根据过滤器通道盒的大小及其在输入张量周围移动的方式,单个盒将输出形状的张量(new_height,new_width,1)。通过应用 N 个过滤通道,输出张量将具有(新高度,新宽度,N)的形状。因此,这构成了单一的 CNN 层。

图像分类和对象检测模型通常具有大量 CNN 层(在 MobilenetV2 中超过 50 层),并且每个 CNN 层可以具有从 10 到 100 以上的滤波器通道数量。因此,模型中存储了大量参数(权重),使得模型使用起来复杂且计算量大。这促使我们想出在不影响模型功能的情况下减小模型大小的方法。

我们在这里讨论的方式是通过移除被认为对模型不必要的参数来修剪训练的模型。剪枝的方法是受郝力等人的论文“高效神经网络的剪枝过滤器”的启发。

图 2:来源: GDJ ,via pixabay ( Pixabay 许可)

当我们查看一个完全训练好的神经网络时,我们可以看到它的许多权重非常接近于零。这表明这些权重在确定神经网络的输出中没有起重要作用。如果我们将神经网络视为大脑,这意味着只有一小部分大脑实际上用于解决给定的问题,而大部分大脑处于非活动状态。

应用这一思想,我们遍历模型中的 CNN 层,检查哪些滤波器通道具有非常接近于零的权重,并从该层中完全移除这些通道。此后,我们适当地重新连接各个 CNN 层(在需要的地方使用一个层来用零填充输入/输出张量以获得正确的形状),以确保信息仍然可以正确地通过模型流动。结果是一个更加精简的模型,仍然可以执行它被训练要做的图像分类/对象检测。

图 3:对目标检测模型的精确度进行修剪的结果(mAP)

我们在 SSDnet 的一个版本上实现了修剪思想,以查看修剪如何影响模型的能力(由 mAP 表示,这是一种对检测对象的准确度的测量)。如图 3 所示,我们可以删除大约 76%的 CNN 频道,该模型仍然具有足够的弹性,可以对剩余的 24%的频道进行操作,并保持原来的精度水平。它还告诉我们,该模型基本上需要大约 24%的通道才能有效运行,任何进一步的减少都会严重影响其能力。代码可在网上获得。

对于一个模型在停止工作之前可以承受的信道丢失百分比,似乎没有硬性规定,这个数量因模型而异。然而,这告诉我们的结论是,卷积神经网络中的大部分参数并没有真正发挥重要作用。这个概念可能扩展到其他形式的神经网络,如前馈神经网络和递归神经网络,肯定值得进一步探索。这个概念在设计用于轻量级物联网设备的机器学习模型方面可能有潜在的价值。

参考资料:

[1]马克等, MobileNetV2:反演残差和线性瓶颈,2018,CVPR 2018

[2]郝力等,高效神经网络的剪枝滤波器,2016,2017

[3]刘威等, SSD:单次多盒探测器,2016,ECCV 2016

修剪神经网络

原文:https://towardsdatascience.com/pruning-neural-networks-1bb3ab5791f9?source=collection_archive---------5-----------------------

通过移除连接或节点,神经网络可以变得更小更快

深度学习的大部分成功来自于建立越来越大的神经网络。这使得这些模型能够更好地执行各种任务,但也使它们的使用成本更高。较大的型号需要更多的存储空间,这使得它们更难分发。较大的模型也需要更多的时间运行,并可能需要更昂贵的硬件。如果您正在为真实世界的应用程序生产一个模型,这是一个特别值得关注的问题。

模型压缩旨在减少模型的大小,同时最大限度地降低准确性或性能的损失。神经网络修剪是一种压缩方法,包括从已训练的模型中移除权重。在农业中,修剪是剪掉植物不必要的枝或茎。在机器学习中,修剪是删除不必要的神经元或权重。我们将回顾神经网络修剪的一些基本概念和方法。

移除重量或神经元?

有不同的方法来修剪神经网络。(1)可以修剪权重。这是通过将单个参数设置为零并使网络稀疏来实现的。这将减少模型中的参数数量,同时保持架构不变。(2)您可以从网络中删除整个节点。这将使网络架构本身更小,同时旨在保持初始较大网络的准确性。

修剪权重/突触与节点/神经元的可视化(来源

基于权重的修剪更受欢迎,因为它更容易做到而不会损害网络的性能。然而,它需要稀疏计算才能有效。这需要硬件支持和一定程度的稀疏性才能有效。

修剪节点将允许更优化的密集计算。这允许网络在没有稀疏计算的情况下正常运行。这种密集计算通常在硬件上得到更好的支持。然而,移除整个神经元更容易损害神经网络的准确性。

修剪什么?

修剪的一个主要挑战是决定修剪什么。如果要从模型中移除权重或节点,您希望移除的参数不那么有用。有不同的试探法和方法来确定哪些节点不太重要,可以在对准确性影响最小的情况下删除。您可以使用基于神经元的权重或激活的试探法来确定它对模型性能的重要性。目标是删除更多不太重要的参数。

最简单的修剪方法之一是基于权重的大小。移除重量实质上是将其设置为零。您可以通过移除已经接近于零的权重来最小化对网络的影响,这意味着量值较低。这可以通过移除低于某个阈值的所有权重来实现。要根据权重大小修剪神经元,可以使用神经元权重的 L2 范数。

不仅仅是权重,训练数据上的激活可以用作修剪的标准。当通过网络运行数据集时,可以观察到激活的某些统计数据。您可能会观察到一些神经元总是输出接近零值的值。这些神经元可能会被移除,而对模型几乎没有影响。直觉是,如果一个神经元很少以高值激活,那么它很少用在模型的任务中。

除了权重或激活的大小之外,参数的冗余也意味着神经元可以被移除。如果一层中的两个神经元具有非常相似的权重或激活,这可能意味着它们在做同样的事情。通过这种直觉,我们可以移除其中一个神经元,并保留相同的功能。

理想情况下,在神经网络中,所有神经元都有独特的参数和输出激活,这些参数和激活在数量上是显著的,并且不是冗余的。我们希望所有的神经元都在做一些独特的事情,并去除那些不独特的。

什么时候修剪?

修剪中的一个主要考虑是将其放在训练/测试机器学习时间线中的什么位置。如果您使用基于权重大小的修剪方法,如前一节所述,您可能希望在训练后进行修剪。但是,在修剪之后,您可能会发现模型性能受到了影响。这可以通过微调来解决,即在修剪后重新训练模型以恢复准确性。

迭代剪枝流程(来源

修剪的用法会根据应用程序和使用的方法而变化。有时微调或多次重复修剪是不必要的。这取决于网络被修剪了多少。

如何评价剪枝?

评估修剪方法时需要考虑多个指标:准确性、大小和计算时间。需要准确性来确定模型如何执行其任务。模型大小是模型占用多少字节的存储空间。要确定计算时间,您可以使用 FLOPs(浮点运算)作为度量。这比推理时间更容易衡量,并且不依赖于模型运行的系统。

通过修剪,在模型性能和效率之间有一个折衷。你可以大量修剪,得到一个更小更有效的网络,但也不太准确。或者,您可以稍微精简一下,拥有一个高性能的网络,但它也很大,运营成本也很高。对于神经网络的不同应用,需要考虑这种折衷。

结论

剪枝是提高神经网络效率的有效方法。在这个领域有很多选择和研究领域。我们希望继续在深度学习方面取得进展,同时保持我们的模型在能源、时间和空间方面的效率。

参考

[1] Blalock,Davis,等.神经网络剪枝是什么状态?。arXiv 预印本 arXiv:2003.03033 (2020)。

[2]韩,宋等.【学习权值和连接的高效神经网络】。神经信息处理系统的进展。2015.

[3] PyTorch 修剪教程https://py torch . org/tutorials/intermediate/Pruning _ Tutorial . html

[4] Keras / Tensorflow 剪枝教程https://www . tensor flow . org/model _ optimization/guide/Pruning/Pruning _ with _ Keras

[5] Molchanov,Pavlo,等.“修剪卷积神经网络以进行资源高效的推理。arXiv 预印本 arXiv:1611.06440 (2016)。

6 Babaeizadeh、Mohammad、Paris Smaragdis 和 Roy H. Campbell。 Noiseout:一种修剪神经网络的简单方法。arXiv 预印本 arXiv:1611.06211 (2016)。

PS4 vs XBone vs Switch——第八代主机谁赢了?

原文:https://towardsdatascience.com/ps4-vs-xbone-vs-switch-who-won-the-8th-console-generation-1e8520ba474?source=collection_archive---------32-----------------------

使用假设检验一劳永逸地决定…

作者图片

随着索尼准备推出 PS5,微软集思广益,想出更多的方法将字母“X”包含在下一款游戏机的名称中,任天堂做任天堂在周末做的任何事情,这是一个回顾第八代视频游戏机的好时机,并决定其中哪一款(如果有的话)可以被描述为“最好的”。

索尼当然可以为转移的设备加冕,自 2013 年推出以来,已售出超过 1.1 亿台 ps4(据估计,XBox One 在同一时间内售出了令人失望的 4700 万台,而 Switch 自 2017 年发布以来售出了 5500 万台)。当然,这些统计数据对消费者来说无关紧要,我们只能假设,消费者更关心的是游戏质量,而不是游戏机的商业性能。但是我们如何判断一款游戏的品质?正如一句谚语所说:一个人的垃圾是另一个人的 使命召唤

克服主观性是我以前在钻研专辑评论的黑暗世界时尝试过的,这是一个将在这里重复的技巧。特别是,我们将依靠游戏的'元批评 T13 分数'来衡量它的“内在质量”。提醒一下,MetaScore 是给定书名的所有可用评论家分数的加权平均值,并“根据[他们的]质量和整体地位”给予某些评论家额外的权重。因此,我们用于此分析的数据集是通过抓取 MetaCritic 网站生成的(这个过程在之前的博客中有深入介绍)。

对于收集到的数据,我们可以马上说一些事情:

  • 我们在三个控制台(PS4、XBox One 和 Switch)上有 13,334 个条目。
  • 许多游戏没有分配元分级。当没有足够的评论家评论来聚集一个时,就会发生这种情况。
  • 相同的标题在不同的平台上有不同的条目。此外,给定标题的 MetaScores 可能变化很大,这取决于评论是针对哪个控制台的。

kill all zombies——PS4 比 XBox One 高 10 分

让我们进一步研究这最后一点。有人可能会说,衡量两个游戏机中哪一个最好的最公平的方法是只检查在两个游戏机上都出现的游戏。事实上,如果我们看看每个平台上可用游戏数量的文氏图,我们会发现有很大的重叠——特别是在 PS4 和 XBox One 之间(它们在技术上更相似,并且大约在同一时间推出)。

使用 Matplotlib-Venn 创建的图表

让我们假设我们想要调查,对于 PS4 和 XBox One 上都可用的给定游戏,哪个版本更有可能拥有更好的 MetaScore。为了做到这一点,我们首先分离出至少在这两个平台上有 MetaScores 的游戏,然后在一个游戏接一个游戏的基础上,从另一个游戏中减去一个游戏的分数(在这种情况下,从 XBox One 中减去 PS4)。

XBox One MetaScore,每个游戏减去 PS4 MetaScore

让我们在 KDE 图上形象化这些分数差异…

我们可以看到,与 PS4 相比,这两个平台上的游戏在 XBox One 上的平均 MetaScores 略高。话虽如此,但差别似乎很小(平均仅超过 1 分),均值两边的范围都相当宽。综合考虑所有因素,我们是否可以得出平台之间的平均差异显著的结论?这听起来很像假设检验的基础,所以让我们想想这样的检验会是什么样子。

如果我们试图证明一款游戏在不同主机上的 MetaScore 之间存在显著差异,那么我们需要拒绝它们之间没有差异的假设。

一个稍微微妙的点将有助于我们了解如何继续进行——尽管我们已经收集了整个 MetaCritic,但我们仍然在处理一个游戏的样本,而不是一个群体(如果没有其他情况,有一些没有 MetaScores 的游戏我们已经从我们的分析中排除了,因此根据定义,我们正在处理两个控制台上可用的所有游戏的子集)。

想象一下,在人口水平上,任何两台游戏机上游戏的 MetaScore 之间的平均差异实际上为零。那么人口分布的平均值当然是 0。为了证明两个控制台之间存在显著差异,我们需要证明我们的样本极不可能来自这个假设的零均值总体。

当然,这是几乎任何单样本假设检验的逻辑基础,但是当我们解释我们的结果时,从基本原则(而不是仅仅盲目地将数字插入公式)考虑这些事情会很有用,并将有助于确保我们得出正确的结论。回到手头的问题——我们现在可以陈述我们的无效假设和替代假设:

  • H₀: 控制台之间的平均差异= 0
  • Hₐ: 表示控制台之间的差异≠ 0

下一步是定义我们的 α (当我们不应该拒绝 H₀时,我们可以接受的概率)。0.05 对大多数人来说已经足够好了 α ,所以对我们来说已经足够好了。换句话说,如果我们真的拒绝 H₀,那么只有 5%的可能性我们这样做是错的。

为了确定我们是否可以拒绝 H₀,我们现在需要创建“t 统计量”,它由以下公式给出:

其中 x-bar 是样本均值,μ是总体均值,s 是样本标准差,n 是样本大小

我们可以将其与 T 分布(具有适当的自由度)进行比较,并绘制 T 统计量,这里显示为一条垂直红线。该 T 统计生成一个 p 值,该值等于红色 T 统计右侧的 T 分布下的面积。

XBox One vs. PS4。蓝色曲线下总共有 5%的区域是粉红色阴影,反映了我们选择的 α=0.05

我们可以从可视化中看到,我们的 p 值将远低于阿尔法阈值 0.05。由此,我们可以拒绝零假设,并得出结论,对于同时出现在 PS4 和 XBox One 上的游戏,XBox One 版本更有可能拥有更高的元批评分数。

顺便提一下,我们可以按照完全相同的过程来说明:

  • 游戏在 XBox One 上比在 Switch 上更有可能获得更高的分数。

XBox One 与 Switch

  • 与 Switch 相比,游戏更有可能在 PS4 上获得更高的分数(尽管在这种情况下,对零假设的拒绝更加微不足道)。

PS4 与开关

游戏机独占怎么样?

那么我们能得出 XBox One 是最好的第八代游戏主机的结论吗?你们当中的游戏爱好者(和集合论者)会正确地注意到,通过只考虑跨多个控制台可用的游戏,我们基本上忽略了数据集中一半的游戏。事实上,如果我们调查 PS4 的十大 MetaScores,我们会发现其中七个是平台专有的(因为它们在 XBox 或 Switch 上不可用)。

MetaCritic PS4 十大,截至 2020 年 5 月

与此同时,任天堂 Switch 十大游戏中有一半在 XBox 或 PlayStation 上找不到…

截至 2020 年 5 月的十大

而且,为了完整起见,XBox One 的十大游戏中只有一款是主机独占的。

当我们分析整个数据集时,PS4 和 Switch 具有最佳排他性的观察似乎得到了证实——Switch 的排他性具有最高的平均 MetaScore,XBox One 最差。

怎样才能用更严谨的统计得出这个结论?同样,我们需要记住,我们处理的是样本,而不是总体。虽然我们的数据集包含许多现有的平台专有游戏,但有一些没有元得分,因此被排除在分析之外。

因此,我们应该再次采取假设检验的方法。如果我们想证明控制台 A 独占比控制台 B 独占有显著更高的元得分,我们需要以某种方式拒绝陈述相反情况的无效假设:

  • H₀: 表示控制台 a 独占≤控制台 b 独占的 MetaScore
  • Hₐ: 表示控制台 a 独占的 metascore>控制台 b 独占

请注意,尽管前面测试中的零假设检验了两个总体均值是否相同,但这里我们假设了一些稍微不同的东西—一个总体均值与另一个相同或小于另一个总体均值。这意味着我们将执行“单尾”测试。

当我们考虑我们的主机独占样本时,我们需要记住一些其他的事情:

  • 样品有个不同的尺寸(例如 PS4 有 1675 个独占,而 XBox 只有 854 个)
  • 样本的元得分具有不同的标准偏差
  • 样本是否来自正态分布并不明显——它们的 KDE 图似乎都有一个负偏斜

我们如何进行在某种程度上取决于这最后一点。韦尔奇的 T 检验是我们常规 T 检验的一种变体,它能更好地处理不同大小和差异的样本。但是,它仍然假设数据呈正态分布。如果我们得出结论,我们的样本是从正态分布的总体中抽取的,那么我们应该转向非参数方法,如排列测试(在之前的博客中详细讨论过)。

如果我们在专业环境中处理这个问题,我们可以运行一个Kolmogorov-Smirnov 测试来明确地决定我们样本的正态性。为了便于说明,我们暂时忽略这一点,尝试两种方法,看看会得到什么结果。

有点不寻常的是,我们看到参数和非参数检验在每种情况下都返回几乎相同的 p 值。这远非显而易见——事实证明,对我们的样本进行Kolmogorov-Smirnov 测试表明,它们确实极不可能来自正态分布的人群(这有可能使参数测试不可靠)。

从假设测试中我们可以得出的结论是,XBox One 绝对是三台游戏机中平台独占游戏最差的。虽然交换机的 exclusives 平均比 PS4 的 MetaScores 高,但这种差异在统计上似乎并不显著。

因此,决定“获胜”的第八代游戏机取决于你作为一个游戏玩家看重什么,尤其是你看重哪些游戏。作为一个在 2018 年花了很多时间在 Persona 5 上的人,我很难选择 PS4 以外的任何东西。

感谢一路看完博客!我很乐意听到任何关于以上的评论,或者这篇文章涉及的任何概念。如果你还有其他的 Matplotlib 小技巧和窍门,欢迎在下面留言,或者通过LinkedIn联系我。

PSA: EDA 很重要。

原文:https://towardsdatascience.com/psa-eda-is-important-7d3ce6e3fc3c?source=collection_archive---------70-----------------------

EDA 初学者指南

我的第一个数据科学项目的演练和 EDA 初学者指南。

这张照片的相关性很快就会变得清晰——继续读下去!(图片由作者提供)

这是我通过 Flatiron 的在线数据科学训练营完成我的第一个项目后学到的第一课。您可以获得许多有意义的见解,回答相关的业务问题,而无需构建单一的模型!当然,如果你正在建立一个模型,如果你花时间去了解你的数据,你将会建立一个更明智、更有效的模型。

这是我在 Flatiron 完成的第一个“项目”,但回想起来,这实际上只是整个生命周期中的“EDA”部分。啊,再次年轻。

没关系——我仍然从这个项目中学到了很多,并且在我继续更复杂的项目之前,它帮助我理解了一个重要的事实:

EDA 很重要。

项目概述

我们的任务是回答这样一个问题:“什么类型的电影票房最好?”

我最后一次演讲的幻灯片

数据

数据由 Flatiron 提供,主要来自四个来源(如上所示):

  • 票房魔咒
  • IMDB
  • 烂番茄
  • TheMovieDB.org

特征包括:release_datepopularityproduction_budgetdomestic_grossworldwide_grossruntimegenre以及与每部电影所涉及的演员/导演相关的其他特征。

请记住,这是本课程的第一个专题,因此不会建立模型。这是一个纯粹简单的 EDA,然后被打包成一个简洁的、面向业务的演示。

清理数据

也许我是少数不介意清理数据的人之一。我也不介意打扫我的公寓,所以也许这之间有联系…

我必须清理数据:

1️⃣

  • strings转换为datetime对象,例如:

df['release_date] = pd.to_datetime(df['release_date'])

很简单。Pandas 有一个内置的方法来实现这一点,而datetime对象给了我们更多的选项来探索数据——这就引出了我的下一个观点…

2️⃣

  • 基于release_date列创建一个release_day特征:

df['release_day] = df['release_date].map(lambda x: x.weekday())

好玩!将release_date转换成一个datetime对象允许我们调用它的.weekday()方法来给出电影上映的日期。

我还创建了一个release_month列用于以后的分析。

3️⃣

  • 将所有数字转换成一个integer。令人惊讶的是,许多包含数字的列将它们存储为strings。不,谢谢你!

df['domestic_gross'] = df['domestic_gross].str.replace('$','').str.replace(',','').astype('int')

您可以看出这些数字实际上是以$45,986,233格式作为字符串存储的。在我将每个记录转换成一个int之前,我需要先移除$,

4️⃣

  • 添加几个计算列。例如:

df['worldwide_net'] = df['worldwide_gross'] — df['production_budget']

这不一定是“清理”过程的一部分,但我喜欢在清理时添加我能想到的任何计算列,以便它们已经存在。

对于这个数据集来说,这就差不多了——没什么太复杂的。我也删除了一些我知道不会有帮助的功能,只是为了保持紧凑。

探索数据

我从这个项目中学到的一件重要事情是,你不能‘搞砸’数据探索。这是不可能的。

至少,这是我学到的重要一课。出于某种原因,当我第一次开始表演 EDA 时,我以为我会以某种方式做一些“错误”的事情。这是你应该尝试任何事情的时候!

如果你认为有值得探索的关系,那么你就自动对了。可能发生的最糟糕的事情是你找不到相关性,或者找到一种与你期望相反的关系。

但即使如此!那还是在告诉你一些你的数据!!

所以我不知道谁需要听这个,但是再一次为后面的人:

你不能搞砸数据探索。

好吧,现在我已经一吐为快了,让我告诉你我探索了什么。

1.R untime

我想看看runtime是否会影响电影的popularityworldwide_gross

这是我为runtimepopularity找到的

使用 Seaborn 创建的图表——这是我最后一次演示的幻灯片。

我发现runtimeworldwide_gross有些类似

使用 Seaborn 创建的图表——这是我最后一次演示的幻灯片。

虽然我们不一定会找到特别高的相关系数,但如果我们看看前 100 名和后 100 名电影的平均运行时间,我们可以看到电影在 120 分钟左右徘徊,而不是 90 分钟。

2.预算

我想看看更大的预算是否总是意味着更有利可图/更受欢迎的电影。让我们来看看。

budgetpopularity

使用 Seaborn 创建的图表——这是我最后一次演示的幻灯片。

再次为budgetworldwide_gross

使用 Seaborn 创建的图表——这是我最后一次演示的幻灯片。

当谈到预算与运行时间时,我们肯定会看到更强的相关性。然而,数字很清楚——预算很重要!

3.发布的日期/月份

还记得我们如何将我们的release_date列转换成一个datetime对象,然后用它来计算release_dayrelease_month吗,即使它们没有被显式地给出?

现在是使用它的时候了!

让我们来看看一周中的某一天或者一年中的某一个月对一部电影的表现有什么影响。

release_day & release_monthpopularity

使用 Seaborn 创建的图表——这是我最后一次演示的幻灯片。

release_day &同release_month``worldwide_gross

使用 Seaborn 创建的图表——这是我最后一次演示的幻灯片。

我肯定会期待周五和周六是电影发行的高峰期——不!

周五是popularityworldwide_gross最好的一天,但是根据这个数据,周六和周日实际上是上映电影最差的两天。

12 月在这两个类别中也有相当大的领先优势。

又名——在 12 月的一个星期五发行一部电影!

4.类型

最受欢迎的流派有哪些?让我们看看!

我们先根据popularity来看。

使用 Seaborn 创建的图表——这是我最后一次演示的幻灯片。

而现在worldwide_gross

使用 Seaborn 创建的图表——这是我最后一次演示的幻灯片。

酷!我们可以看到,动作片、冒险片在这两项指标上都名列前茅,科幻片和奇幻片也榜上有名。

喜剧在票房最高的电影中排名前五,戏剧在最受欢迎的电影中排名前五。

结论

总而言之:

这是我最后一次演讲的幻灯片。

这就是全部了!想出一些你想探索的想法,然后…探索它们。

有时你的假设会被证明是正确的,有时会被证明是错误的——没有一个比另一个更好。

两个都会告诉你一些关于你的数据的有用信息。

我希望这对某人有帮助!或者至少,让某人知道他们不是独自开始他们的数据科学之旅。

更多内容即将推出。

PSI 和 CSI:前 2 个模型监控指标

原文:https://towardsdatascience.com/psi-and-csi-top-2-model-monitoring-metrics-924a2540bed8?source=collection_archive---------2-----------------------

建模基础

种群稳定性指数和特征稳定性指数

作者图片

一旦一个模型被投入生产,需要定期的监控以确保这个模型仍然是相关的和可靠的。我写了一篇关于模型验证和模型监控以及这两个阶段的重要性的文章,你可以看看这篇文章的前传。

[## 为什么模型验证如此重要,它与模型监控有什么不同

模型开发过程的支柱

towardsdatascience.com](/why-is-model-validation-so-darn-important-and-how-is-it-different-from-model-monitoring-61dc7565b0c)

继续这篇文章的主题,我们将了解 PSI 和 CSI,即群体稳定性指数和特征稳定性指数,它们是在许多领域特别是信用风险领域使用的最重要的监控策略之一。

PSI 和 CSI,这两个指标都关注人口分布的变化。

这两个监控指标基于这样一个前提,即当开发和验证/OOT(超时)样本在经济条件、基本假设、活动风格和关注点等方面没有显著差异时,预测模型效果最佳。

例如:如果我们建立一个预测模型来预测正常经济环境下信用卡客户的流失率,然后根据经济衰退时期的样本进行测试,该模型可能无法准确预测,因为不同收入阶层的人口分布可能发生了显著变化,这可能会导致实际流失率非常高,但该模型可能无法捕捉到它,从而预测出错误的结果。但是,正如我们现在理解的,如果我们继续检查 DEV 时间和当前时间之间的人口分布变化,我们可以得到一个公平的想法,如果模型结果是可靠的或不可靠的。这是通过 PSI 和 CSI 作为重要的监控指标来实现的。

人口稳定指数

这是一种度量标准,用来衡量一个变量在两个样本之间的分布随着时间推移发生了多大的变化。它被广泛用于监控人口特征的变化,以及诊断模型性能中可能存在的问题-很多时候,如果模型由于人口分布的重大变化而停止准确预测,这是一个很好的指示。

在这篇研究论文中,上述定义已经得到了非常恰当的解释。我也在这篇文章的末尾给出了一个参考链接。

最初,开发群体稳定性指数(PSI)是为了监控 OOT 和信贷风险记分卡分析中开发时间段样本之间的分布变化。PSI 的使用现在在本质上已经变得有些灵活,可以检查模型相关属性以及总体样本总体的分布变化,包括因变量和自变量- CSI ,我们将在下一节讨论这一点。

PSI 倾向于总体人口转移,而 CSI 倾向于关注所使用的单个模型变量。

来源:链接

人口分布的变化可能是由于:

  • 经济环境的变化,如经济衰退、新冠肺炎等
  • 数据来源的变化
  • 直接或间接影响人口分布的内部政策变化
  • 数据集成中可能导致错误数据的问题
  • 编程/编码时的问题,例如模型实现或缺少评分代码的一些关键步骤

由于分布变化不一定涉及因变量,PSI 也可用于检查任何样本之间的相似性/相异性,例如,在社会人口学研究中比较两个或多个人口的教育、收入和健康状况。

计算 PSI 的步骤(参考: 链接)

  1. 在评分样本中按降序对评分变量进行排序
  2. 将数据分成 10 或 20 组(决定)
  3. 根据评分样本计算每组中记录的百分比
  4. 根据开发样本计算每个组中记录的百分比
  5. 计算步骤 3 和步骤 4 之间的差异
  6. 取(步骤 3 /步骤 4)的自然对数
  7. 将步骤 5 和步骤 6 相乘

PSI 的 EXCEL 制表:

作者图片

解释规则(参考: 链接)

  1. PSI < 0.1 :无变化。您可以继续使用现有模型。
  2. PSI > =0.1: 但小于 0.2——需要轻微改变。
  3. PSI > =0.2: 需要重大改变。理想情况下,我们不应该再使用这种模式。应该重新校准/重新开发。

我们也可以使用条件格式范围,红色-琥珀色-绿色区域,红色是 PSI 超过 20%的警报状态,琥珀色是 10–20 %,模型应处于观察状态,绿色是模型被视为 fir 使用的阶段,即< 10%。

现在,根据用例,这些阈值根据业务相关性进行调整,但保持观察人口变化的想法是相同的。

特征稳定性指数

它回答了哪个变量导致了人口分布的变化。它将评分数据集中的独立变量的分布与发展数据集中的分布进行比较。它检测随时间推移提交评分的输入变量分布的变化。

它有助于确定哪个变化的变量是导致模型得分变化的主要原因。

当模型性能下降时,检查模型变量的分布变化有助于确定可能的原因。这是一个通常在检查了 PSI 并且它不在绿色区域之后采取的步骤(<0.1 in general) to check that the overall population distribution can be attributed majorly to which variables.

At least one variable that has changed significantly or if several variables have moved to some extent, it might be time to recalibrate or to rebuild the model.

CSI invariably has the same steps as PSI while calculating it. Just that the deciding is done on the dev sample values of a particular variable by binning it and setting those limits as hard cutoffs. Then, while calculating the frequency values for any validation/OOT sample, apply those same cutoffs to the data and calculate the frequency values and apply the same formula as we did while calculating PSI.

CSI 的 EXCEL 表格:

作者图片

因此,PSI 可以帮助我们确定总体人口分布与 DEV 样本的比较,如果它显示出显著的变化,那么 CSI 可以帮助我们进一步将其缩小到导致波动的几个变量。

参考文献:

[## 人口稳定性指数及特征分析

本教程描述了人口稳定性指数和特征分析的含义和用途。简单来说…

www.listendata.com](https://www.listendata.com/2015/05/population-stability-index.html)

https://www.lexjansen.com/wuss/2017/47_Final_Paper_PDF.pdf

如果你想知道更多关于等级排序的信息,这是信用风险建模中的一个基本概念,请查看下面的帖子:

https://juhiramzai . medium . com/why-rank-ordering-is-so-important-BC 1 ff 8a 48764

观看此空间,了解更多关于数据科学、机器学习和统计学的信息!

快乐学习,快乐成长!

使用 GeoPandas 可视化菲律宾的人口密度

原文:https://towardsdatascience.com/psvisualizing-the-philippines-population-density-using-geopandas-ab8190f52ed1?source=collection_archive---------35-----------------------

地理可视化/菲律宾。

使用 GeoPandas 可视化 2015 年菲律宾人口密度

塞巴斯蒂安·赫尔曼在 Unsplash 上的照片

人口密度是城市规划中的一个重要概念。关于它如何影响经济增长的理论存在分歧。一些人,如 Rappaport 所说,认为经济是一种形式的【空间均衡】 : 即居民和就业的净流动逐渐趋于彼此平衡。

密度与经济增长有某种关系的想法早已被多项研究所证实。但同样的理论是否适用于菲律宾以及先于什么的事物(密度跟随城市发展或城市发展跟随密度)是一个经典的数据科学问题。

然而,在我们测试任何模型之前,让我们做一个有趣的练习并可视化我们的数据集。

2015 年菲律宾人口数据集

菲律宾统计局每五年公布一次人口数据。在撰写本文时,仅发布了 2015 年的数据集,因此我们将使用该数据集。

导入包

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors as colors #to customize our colormap for legendimport numpy as np
import seaborn as sns; sns.set(style="ticks", color_codes=True)import geopandas as gpd
import descartes #important for integrating Shapely Geometry with the Matplotlib Library
import mapclassify #You will need this to implement a Choropleth
import geoplot #You will need this to implement a Choropleth%matplotlib inline

我们将使用的许多软件包都需要安装。对于那些安装 GeoPandas 有困难的人,请查看我关于这个的文章。请注意,geoplot 需要 cartopy 包,并且可以作为我文章中讨论的任何依赖项进行安装。

加载 shape file

需要 Shapefiles 来创建地理或政治边界的“形状”。

下载 shapefile 并使用 GeoPandas 加载它。

解压 zip 包时需要注意的一点是:所有内容都应该放在一个文件夹中,即使您只是简单地使用。shp”文件,否则它将无法工作。(这意味着”。cpg“,”。dbf“,”。prj”等应与您的“在同一位置”。shp "文件。

你可以在 gadm.org 下载菲律宾的 shape file(https://gadm.org/)。

注意:你同样可以从菲尔吉斯(http://philgis.org/)下载形状文件。菲律宾的数据可能会更好,虽然其中一些来自 GADM,但还是用 GADM 吧,因为我在这方面更有经验。

#The level of adminsitrative boundaries are given by 0 to 3; the details and boundaries get more detailed as the level increasecountry = gpd.GeoDataFrame.from_file("Shapefiles/gadm36_PHL_shp/gadm36_PHL_0.shp")
provinces = gpd.GeoDataFrame.from_file("Shapefiles/gadm36_PHL_shp/gadm36_PHL_1.shp")
cities = gpd.GeoDataFrame.from_file("Shapefiles/gadm36_PHL_shp/gadm36_PHL_2.shp")
barangay = gpd.GeoDataFrame.from_file("Shapefiles/gadm36_PHL_shp/gadm36_PHL_3.shp")

此时,您可以查看 shapefiles 并检查边界。您可以通过绘制形状文件来实现这一点。

#the GeoDataFrame of pandas has built-in plot which we can use to view the shapefilefig, axes = plt.subplots(2,2, figsize=(10,10));#Color here refers to the fill-color of the graph while 
#edgecolor refers to the line colors (you can use words, hex values but not rgb and rgba)country.plot(ax=axes[0][0], color='white', edgecolor = '#2e3131');
provinces.plot(ax=axes[0][1], color='white', edgecolor = '#2e3131');
cities.plot(ax=axes[1][0], color='white', edgecolor = '#2e3131');
barangay.plot(ax=axes[1][1], color='white', edgecolor = '#555555');#Adm means administrative boundaries level - others refer to this as "political boundaries"
adm_lvl = ["Country Level", "Provincial Level", "City Level", "Barangay Level"]
i = 0
for ax in axes:
    for axx in ax:        
        axx.set_title(adm_lvl[i])
        i = i+1
        axx.spines['top'].set_visible(False)
        axx.spines['right'].set_visible(False)
        axx.spines['bottom'].set_visible(False)
        axx.spines['left'].set_visible(False)

较暗的填充意味着更多的边界

加载人口密度数据

每平方公里的人口数据和密度通常由菲律宾统计局(PSA)收集。

你可以通过其他人口统计或宏观经济数据来做到这一点,因为菲律宾一直在提供这些数据。(好样的菲律宾!)

因为我们想增加挑战,所以让我们从最详细的开始:城市和自治市级别。

我们首先加载数据并检查它:

df = pd.read_excel(r'data\2015 Population Density.xlsx',
                  header=1,
                  skipfooter=25,
                   usecols='A,B,D,E',
                  names=["City", 'Population', "landArea_sqkms", "Density_sqkms"])

清理数据

在我们继续之前,我们必须清理我们的数据。我们应该:

  • 删除值为空的行
  • 删除名称后的非字母字符(*表示脚注)
  • 删除每个城市名称后的“(首都)”和“不包括”字样
  • 删除前导和尾随空格
  • 还有更多…

在将数据与 shapefiles 合并时,清理确实会占用大量工作。

菲律宾就是如此,该国的一些城市以彼此相似的名字命名。(如圣依西多禄、圣胡安、圣佩德罗等)。

让我们跳过文章中的这一部分,但是对于那些想知道我是如何做到的人,请访问我的 Github 库。该代码将适用于自治市/城市级别的任何 PSA 数据。

探索性数据分析

我最喜欢的实现 EDA 的方法之一是通过散点图。我们这么做只是为了以图表形式看看哪些城市密度高。

Matplotlib 是可行的,但我喜欢 seaborn plots 的风格,所以我更喜欢经常使用它。

#First sort the dataframe according to Density from highest to lowest
sorted_df = df.sort_values("Density_sqkms", ascending=False,ignore_index=True )[:50]fig, ax = plt.subplots(figsize=(10,15));
scatter = sns.scatterplot(x=df.index, y=df.Density_sqkms)#Labeling the top 20 data (limiting so it won't get too cluttered)
#First sort the dataframe according to Density from highest to lowest
sorted_df = df.sort_values("Density_sqkms", ascending=False)[:20]#Since text annotations,overlap for something like this, let's import a library that adjusts this automatically 
from adjustText import adjust_texttexts = [ax.text(p[0], p[1],"{},{}".format(sorted_df.City.loc[p[0]], round(p[1])),
          size='large') for p in zip(sorted_df.index, sorted_df.Density_sqkms)];adjust_text(texts, arrowprops=dict(arrowstyle="->", color='r', lw=1), precision=0.01)

菲律宾城市和自治市密度散点图。你可以直观地看到有些城市在密度上是异常值。注意,我使用了库 adjust_texts 来确保标签清晰易读。

从这张图表中,我们已经可以看出哪些城市高于“首都地区”的平均水平,即曼达卢永帕赛卡洛坎纳沃塔斯马卡蒂马拉邦马里基纳

同样在前 20 名中,我们可以看到这些城市大多位于“国家首都地区”和附近的省份,如拉古纳。还要注意马尼拉市对于这个数据集来说是一个异常值。

地质公园可视化

根据瓦尔多 T26 托布勒 T27 的说法,地理第一定律 T25 是“一切事物都与其他事物相关,但近的事物比远的事物更相关。”

这就是为什么在房地产中,检查和想象邻近性如何影响价值是很重要的。最终,地理可视化是我们可以做到这一点的方法之一。

我们已经可以使用 GeoPandas 的内置绘图方法来可视化我们的数据。

k = 1600 #I find that the more colors, the smoother the viz becomes as data points are spread across gradients
cmap = 'Blues'
figsize=(12,12)
scheme= 'Quantiles'ax = merged_df.plot(column='Density_sqkms', cmap=cmap, figsize=figsize,
                          scheme=scheme, k=k, legend=False)ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)#Adding Colorbar for legibility
# normalize color
vmin, vmax, vcenter = merged_df.Density_sqkms.min(), merged_df.Density_sqkms.max(), merged_df.Density_sqkms.mean()
divnorm = colors.TwoSlopeNorm (vmin=vmin, vcenter=vcenter, vmax=vmax)# create a normalized colorbar
cbar = plt.cm.ScalarMappable(norm=divnorm, cmap=cmap)
fig.colorbar(cbar, ax=ax)
# plt.show()

使用 GeoPandas 的内置绘图方法进行可视化

一些分析师更喜欢单调的颜色图,如蓝色或绿色,但当数据高度倾斜(有许多异常值)时,我发现使用发散的颜色图更好。

发散的色彩映射表以可视化数据分散

使用发散色图,我们可以可视化密度值的分散。即使查看颜色条图例也可以看出菲律宾的密度值包含了偏高的异常值。

使用 Geoplot 绘图

除了 GeoPandas 的内置绘图功能之外,您还可以使用 geoplot 进行绘图。

k = 1600
cmap = 'Greens'
figsize=(12,12)
scheme= 'Quantiles'geoplot.choropleth(
    merged_df, hue=merged_df.Density_sqkms, scheme=scheme,
    cmap=cmap, figsize=figsize
)

在下一个系列中,让我们尝试更互动地绘制这一点,或者使用一些机器学习算法来提取更多见解。

完整代码,请查看我的 Github 库。

对自治市和城市级别的数据进行预处理的代码也适用于其他 PSA 报告的统计数据。

让我知道你想让我们在未来尝试和可视化什么数据集。

公共交通服务范围:识别印度尼西亚雅加达的无服务市民

原文:https://towardsdatascience.com/public-transportation-range-of-service-identifying-the-unserved-citizens-in-jakarta-city-eaf8f3446fce?source=collection_archive---------36-----------------------

现实世界中的 DS

由于耐力有限,人们只能走一段时间或一段距离。为了促进公共交通的使用,公共交通服务的可及性应该在这个距离之内。使用地理信息系统,我们能够识别哪些区域不在步行距离内,并推断出未得到服务的市民。

概要:雅加达市是世界上最拥挤的城市之一。必须首先扩大对居民的服务覆盖面,以促进公共交通的使用。基于标准步行距离,该覆盖距离应该在 700 米以内,因为人类行走的耐力有限。所以,

雅加达 700 米的公共交通服务范围是否覆盖了所有居民?

答案是否定的。大约有(近似值) 827.594 (一千万人中的市民 居住在现有公共交通步行距离之外。64,752 公顷土地中的 9160.16 公顷(约 14%)不在服务范围内。为了减少数量,需要规划新的路线并产生一个空间规划,该空间规划或者包含该路线,或者被新路线包含。

介绍

如果我们谈论拥堵问题,雅加达是最糟糕的城市之一;它徘徊在世界十大拥堵城市中。由于拥堵而损失的时间可能在早上超过 19 分钟,在晚上超过 26 分钟。以至于每年每个雅加达市民有 7 天 6 个小时是花在交通拥堵上( Tomtom,2019 )。此外,拥堵导致空气污染激增,也就是说,不用说,慢慢地毒害着市民。尽管许多机构进行了各种衡量标准和排名,但这并没有减少问题的紧迫性,这个问题仍然需要解决。

当然,必须采取措施来减少这种使用:将私人汽车消费转向公共交通。这可以通过降低公共交通的成本来实现,我说的成本不是指货币价值。成本的组成部分可以由经验、舒适性、感觉、便利性、票价和许多影响人们使用公共交通决策的因素组成(尽管使用一些统计方法的计算可能会将这些变量转换为货币单位)。我认为,人们使用公共交通的最根本变量是交通服务的范围;一个人乘坐公共交通工具应该步行的距离。

(想象一下:即使有最好的火车或公共汽车,美丽的人行步道;你不会仅仅为了使用这项服务而步行 10 公里吧?)

嗯,10 公里只是夸张。重点是,步行距离要短。这种说法有许多理由,但它将深入一些学术论文,将涉及大量的统计数据,我不希望这篇文章变得沉重。所以,让我们保持轻松(如果你想寻找论据,见这个,和这个)。注意,我没有忽略其他导致变量。我的论点是,在我们实现其他变量之前,服务的范围应该是优先的。

在步行能力有限的情况下,服务范围必须在步行距离内:即 700 米。该数字由雅加达省法规设定,作为指定公交导向开发(TOD)区域的标准。超过这个数字,预计人们会使用其他交通工具因为走路太累了!因此,我们必须确保雅加达的每个公民都在这 7 亿人口的范围内。

该范围是二维的,并产生一个区域,该区域定义了服务的运输范围。 在我的另一篇文章中,我使用了其他命名法:行人汇水区(PCA),但本质上是一样的。

行人聚集区(PCA),一个人行走的最大距离。PCA 确定服务的经验范围(作者的分析,2020 年)

目标

本文旨在确定不在 700 米交通服务范围内的市民数量。为此,使用了一些地理数据:

  • 每个公共交通站的位置(交通设施)
  • 道路几何;
  • 人口分布

一些分析使用 700 米的距离作为圆形半径,但根据经验,人们不会飞。人走着转着;道路有交叉路口和弯道,所以这 700 m 的步行距离肯定在 700 m 半径内。

数据

本节解释输入数据:交通设施、道路几何和人口分布。

数据#1:交通设施

雅加达有许多运输供应商,包括私营和国有企业。虽然目前公布的交通服务清单可以在官方开放数据网站中找到,但 Trafi 已经收集并提供了全面的数据收集,我必须承认这一点。圆点是设施的停靠点;在那里,你可以登上汽车或公共汽车。

所有雅加达的交通站有昂科特站、米克洛莱站、杰克林科站、雅加达站、火车站等等( Trafi,2020 )。从 OpenStreetMap 中收集道路几何图形

数据#2:道路几何形状

从 OpenStreetMap (OSM)中检索道路几何图形。注意地图上的点。圆点是从 Trafi 中检索到的公共交通站点。道路几何包括所有道路等级(高速公路、一级公路、二级公路、住宅区、人行道等)。).放大可以看到雅加达道路设计的复杂程度。

道路几何和公共交通站(来源:开放街道地图和交通,2020)

数据#3:人口分布

我无意中发现了我的学长的文章,该文章讨论了印度尼西亚的城市化程度(就建筑区域和密度而言)和区域城市系统。其中一个论点是,为了定义和分析大都市区域,我们需要网格中的人口数据。我完全同意,幸运的是,这篇文章提到的全球人类居住层(T21)提供了这样的数据。

栅格数据的连续性为分析提供了灵活性。它忽略了聚集到行政边界的地理数据的离散性质(例如可以通过 choropleth 地图。作为数据分析师,这种连续不断的数据,迸发出喜悦的火花!本文的分析需要连续的数据,而不是离散的序数数据。

GHSL,通过双线性插值显示的人口密度(GHSL,2015 年)。实际数据是像元大小为 250x250m 的栅格。

分析

对于每个交通设施站点,我将行人集水区(PCA)确定为服务范围(PCA 和服务范围可以互换),并排除了已经被行人集水区覆盖的区域。这导致了行人聚集区没有覆盖的区域,但是一些区域是 PCA 没有覆盖的,例如机场、空地、湖泊。

因此,我通过将人口数据与没有交通设施的区域(超过 700 米的区域)叠加来提取。这就是为什么需要连续的人口数据,因为提取离散的地理数据(例如从行政边界进行空间提取)没有意义!

我想如果读者只看下面的图会更容易。

分析,未获得服务的市民的空间分布(作者的分析,2020 年)

结论

分析结果是一个栅格,其中包含当前公共交通服务范围之外的市民的值。正如目标所述,本文试图确定未得到服务的公民人数。

合计所有小区的值,大约有 827,594 个市民没有得到服务。请注意,我使用“大约”,这是因为人口数据的规模太小,需要根据当地情况进行重新评估。

此外,64,752 公顷土地中有 9,160.16 公顷(约 14%)没有这项服务。然而,这 14%中的一部分不应该被覆盖或者不需要被覆盖。这些部分是无人居住的区域:湖泊、机场、空地等。因此,总有一些地区没有交通服务。

一些评论和建议

本节阐述了建议以及整合交通规划和城市/空间规划的重要性。

交通城市规划与城市设计一体化

交通与城市规划/设计密不可分。土地利用影响交通,交通影响土地利用。由于这些相互作用,交通规划必须与城市空间规划相结合;交通规划不能孤立存在,因为交通是由周围的建筑环境定义和编制的。

与直觉相反,我们可以说,为了改善我们的交通,我们可以干预我们的城市环境,而不干预交通本身。举个例子,

  • 修建更好更宽的人行道减少了私人车辆的需求,导致公共交通需求增加;
  • 建设新的行人网络改善了行人聚集区,使车站服务于更多的居民,增加了车站的交通量;
  • 混合土地使用提供了附近的服务,减少了前往城市的另一部分的需求。
  • 减小城市街区的大小缩短了步行距离

建议

将它放入上下文中;对于目前居住在 700 米交通服务范围之外的雅加达市民,我们应该怎么做

显然,计划新的路线为没有得到服务的居民服务。但是!确保路线周围的步行网络包含新路线,提供直达服务或更短距离的线路。这可以通过为一些优先地区制定新的城市设计计划来实现。

另一个相当激进的想法是重组建筑体量,以产生更高的渗透性。整合土地和重新组织空间,将没有得到服务的市民转移到附近已经得到服务的社区。感觉这个可能性比较小,但是哎!日本人就是这么干的!

该机构

为了实现该建议,运输机构(规划路线)、规划机构(规划空间规划)或任何其他实体必须合作。

至少以我的经验来看,(我也希望并需要了解更多这方面的知识)我们印尼机构实体(政府或非政府)的现实是,这些实体有时是独立运行的。例如,开发商正在开发他们自己私人获得的土地,旅行社正在规划他们自己的路线;同时需要协同这些独立的活动。如果土地开发商也是运输服务商岂不是很厉害?嘿!日本人就是这么干的!(我从日本人身上学到了很多!)

我并不是说这种努力不存在(我的意思是,这就是我们政府的目的)。我的信息是作为一个城市规划专业的毕业生,我认为我们必须意识到这种现象;交通和空间规划是相互依赖的。

使用 Sphinx 在 Confluence/HTML 上发布 Python 项目文档

原文:https://towardsdatascience.com/publish-python-project-documentation-on-confluence-html-using-sphinx-fad3a98b8eeb?source=collection_archive---------18-----------------------

代码文档在每个项目中都是必不可少的。代码文档可以分成多个部分。第一个是注释块,对程序员最有帮助;这些可以在每个解释类、方法、参数、可能的错误的文件中找到。然后是档案文件。这些通常是通过一个脚本生成的,该脚本将解析一个文件,并基于文档字符串中的描述,创建一个显式的 PDF。事后,应该有关于代码库的位置的信息;此外,应该有如何运行项目的详细说明。

在本文中,我们将研究由 Sphinx 生成的文件文档。这个文档生成器可以用来创建。pdf,。或者将技术文档页面发布到一个 Confluence 实例。

为什么选择技术文档的融合?

Confluence 是一个在一个地方创建、协作和组织所有工作的好地方。

  1. 可在公司范围内使用
  2. 允许你吸引同事和读者
  3. 基于网络,无需下载任何软件
  4. 敏捷环境的理想选择

创建一个 confluence 帐户,并创建一个存储文档的空间

Sphinx 入门

Sphinx 是一个工具,它使得为 Python 项目创建智能和漂亮的文档(或由多个 reStructuredText 源组成的其他文档)变得容易,由 Georg Brandl 编写。它最初是为新的 Python 文档而创建的,并为 Python 项目文档提供了出色的工具,但也支持 C/C++,并且计划开发更多的语言。

Sphinx 使用 reStructuredText 作为其标记语言,它的许多优势来自于 reStructuredText 及其解析和翻译套件 Docutils 的强大和直接。

创建文档所涉及的步骤;

GitHub 代码

  1. 转到 python 项目的根目录。在小项目的情况下,转到包含所有。py 文件
  2. 创建一个 Python 3 虚拟环境。在我的例子中, venv 是虚拟环境的名称

打开 cmdshift +右键,在此打开命令窗口

virtualenv -p python3 venv

3.激活虚拟环境。

cd venv/Scripts
activate.bat

确保您在整个项目过程中都处于虚拟环境中

4.安装所有项目需求

pip install -r requirements.txtORpip install Sphinx
pip install rinohtype# The recommended method of installation is using [pip](https://pip.pypa.io/) for confluencepip install sphinxcontrib-confluencebuilder

Sphinx 和 Rinohtype 已经在 requirements.txt 文件中。

5.创建一个 docs 目录并将 cd 放入该目录。这是所有文档文件将出现的地方。

mkdir docs
cd docs

6.设置 Sphinx

sphinx-quickstart

初始配置

用于 Sphinx 文档的 Docstring 格式;

文档字符串格式

7.开源/conf.py

  • 配置根目录的路径

取消第 15–17 行的注释,并粘贴以下代码

import os
import sys
sys.path.insert(0, os.path.abspath('../..'))

路径应该指向项目的根目录,查看项目结构,从 conf.py 我们应该通过向上两个父目录到达根目录。

主目录

  • 在 conf.py 中添加这些扩展名
extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.intersphinx',
    'sphinx.ext.ifconfig',
    'sphinx.ext.viewcode',
    'sphinx.ext.githubpages',
    'sphinxcontrib.confluencebuilder'
]# 'sphinxcontrib.confluencebuilder' is for confluence
  • 在 conf.py 中添加 latex 元素
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
    'papersize': 'letterpaper',# The font size ('10pt', '11pt' or '12pt').
    'pointsize': '10pt',# Additional stuff for the LaTeX preamble.
    'preamble': '',# Latex figure (float) alignment
    'figure_align': 'htbp',
}
  • 在配置文件中包含一系列与发布相关的设置:(*可选,仅当您希望在 confluence 中发布时)
confluence_publish = True
confluence_space_name = 'TEST'
*# (for confluence cloud)*
confluence_server_url = 'https://example.atlassian.net/wiki/'
confluence_server_user = 'myawesomeuser@example.com'
confluence_server_pass = '[myapikey](https://confluence.atlassian.com/cloud/api-tokens-938839638.html)'
*# (or for confluence server)*
confluence_server_url = 'https://intranet-wiki.example.com/'
confluence_server_user = 'myawesomeuser'
confluence_server_pass = 'mypassword'

例如:

confluence_publish = True
confluence_space_name = 'SPEC'
*# (for confluence cloud)* confluence_server_url = '[https://spectrra.atlassian.net/wiki/'](https://spectrra.atlassian.net/wiki/')
confluence_server_user = '[email@gmail.com](mailto:shravan@osiopt.com)'
confluence_server_pass = '[jhfgjsdfjhasdjfg](https://confluence.atlassian.com/cloud/api-tokens-938839638.html)'

如何为你的项目获取 confluence _ server _ pass:获取 API Key

详细安装: [斯芬克斯](http://Atlassian Confluence Builder for Sphinx) 的亚特兰蒂斯合流建造者

8.打开 index.rst,将内容更改为以下内容。(点击 index.rst 链接查看完整内容)

Documentation for the Code
**************************
.. **toctree::
   :maxdepth:** 2
   **:caption:** Contents:codename1
===================
.. **automodule::** codename1
   **:members:**codename2
=====================
.. **automodule::** codename2
   **:members:****# In case of many modules;**main
===================
.. **automodule::** app
   **:members:**controller
=====================
.. **automodule::** main.controller
   **:members:**models
=================
.. **automodule::** main.models
   **:members:**

9.创建文档文件。

在 docs 目录中键入命令

  • 创建 HTML
make html

如果您的 Python 版本≥3.7.0,构建 pdf 文件将会失败( Github 问题参考)

HTML 页面的快照;

文档的快照;index.html

文档的快照;index.html

这会在 docs/build/HTML/index . HTML中产生 HTML 文件

  • 在汇合处发布
make confluence

注意:如果合流失败,在合流前运行 make clean。

IMP:您可以将 confluence 页面导出为 PDF 格式

从 Confluence 页面导出到 PDF

合流页面的快照;

汇合页面的快照

一旦一切就绪;如果您对代码的文档进行了任何更改,请打开 cmd 并运行以下命令:

命令

要了解更多信息,请参考以下链接;

  • 编写文档字符串:https://sphinx-RTD-tutorial . readthedocs . io/en/latest/doc strings . html和https://python hosted . org/an _ example _ pypi _ project/sphinx . html
  • 斯芬克斯:https://www.sphinx-doc.org/en/master/index.html
  • 斯芬克斯的 atlassian Confluence Builder:https://sphinxcontrib-Confluence Builder . readthedocs . io/en/latest/index . html
  • GitHub 回购的链接:https://GitHub . com/shravankumarihregoudar/sphinx documentation

谢谢你的时间。希望这篇文章对你有帮助。

使用基于标准的 REST API 发布您的模型

原文:https://towardsdatascience.com/publish-your-models-with-a-standard-rest-api-94de1e1da682?source=collection_archive---------21-----------------------

使用 DEEPaaS API 公开您的模型的逐步指南

无论您是在开发一个成熟的应用程序,还是只想与您的同事共享模型,您都可能面临这样的情况:您需要与其他人共享您新开发的模型。在这个简短的分步教程中,我们将展示如何使用 REST API 轻松共享您的模型,而无需从头开始开发。

构建机器学习模型的数据科学家没有一种简单而通用的方法来与他们的同事或任何有兴趣使用他们的人共享他们开发的应用程序。整个模型(即代码和任何需要的配置资产)可以共享,但是这要求模型的接收者需要有足够的知识来执行它。在大多数情况下,我们只是想分享模型以展示其功能(向其他同事或对我们的预测模型感兴趣的公司),因此没有必要分享整个实验。

在我们工作的互联世界中,最直接的方法是通过 HTTP 端点公开模型,以便潜在用户可以通过网络远程访问它。这听起来可能很简单,但是开发一个合适且正确的 REST API 并不是一件容易的事情。首先,正如在其他帖子中所展示的,数据科学家需要从头开始开发 API,这项任务需要 API 编程、网络、REST 语义、安全性等方面的知识。第二(可能是一个不太明显的问题),如果每个科学家都提出一个实现,我们最终会有无数不同的、不可互操作的 API 做或多或少相同的工作,导致一个支离破碎的生态系统,我们需要知道如何与所有这些端点交互。

DEEPaaS API:一个公开机器学习模型的 REST API

进入 DEEPaaS API :使用 aiohttp 搭建的机器学习、深度学习和人工智能 REST API 框架。DEEPaaS 是一个软件组件,它允许通过 HTTP 端点公开 Python 模型(使用您选择的框架实现)的功能。它不需要对原始代码进行修改,并有方法根据科学家的选择(输入参数、预期输出等)对其进行定制。)

DEEPaaS API 遵循 OpenAPI 规范(OAS) ,因此它允许人类和计算机发现并理解底层模型的功能、其输入参数和输出值,而无需检查模型的源代码。

使用 DEEPaaS API 公开的测试模型的 Swagger web 用户界面。

让我们通过一个走过的例子来看看它是如何工作的。

使用 DEEPaaS 逐步发布模型

将模型插入 API

为了更好地说明如何将模型与 DEEPaaS 集成,我们将使用来自 scikit-learn 的一个最著名的例子:一个针对 IRIS 数据集训练的支持向量机。在这个简单的例子中,我们定义了两个不同的函数,一个用于训练,一个用于执行预测,如下所示:

from joblib import dump, load                                                      
import numpy                                                                       
from sklearn import svm                                                            
from sklearn import datasets                                                       

def train():                                                                       
    clf = svm.SVC()                                                                
    X, y = datasets.load_iris(return_X_y=True)                                     
    clf.fit(X, y)                                                                  
    dump(clf, 'iris.joblib')                                                                                                                                          

def predict(data):                                                                 
    clf = load('iris.joblib')                                                      
    data = numpy.array(data).reshape(1, -1)                                        
    prediction = clf.predict(data)                                                 
    return {"labels": prediction.tolist()}

如您所见,按照 scikit-learn 的教程,训练函数将训练好的模型保存到磁盘中。下一步是为您的培训和预测呼叫定义输入参数。因为这个例子非常简单,所以我们只为预测调用定义输入参数。通常你需要把它放在一个不同的文件中,这样它就不会干扰你的代码,但是为了简单起见,我们在 IRIS SVM 旁边添加了这个特殊的函数:

from joblib import dump, load                                                      
import numpy                                                                       
from sklearn import svm                                                            
from sklearn import datasets                                                       
from webargs import fields, validate                                                                                                                                 

def train():                                                                       
    clf = svm.SVC()                                                                
    X, y = datasets.load_iris(return_X_y=True)                                     
    clf.fit(X, y)                                                                  
    dump(clf, 'iris.joblib')                                                                                                                                     

def predict(data):                                                              
    clf = load('iris.joblib')                                                   
    data = numpy.array(data).reshape(1, -1)                                     
    prediction = clf.predict(data)                                              
    return {"labels": prediction.tolist()}                                      

def get_predict_args():                                                         
    args = {                                                                    
        "data": fields.List(                                                    
            fields.Float(),                                                     
            required=True,                                                      
            description="Data to make a prediction. "
                        "The IRIS dataset expects "  
                        "four values containing the "
                        "Sepal Length, Sepal Width, " 
                        "Petal Length and Petal Width.",                        
            validate=validate.Length(equal=4),                                  
        ),                                                                      
    }                                                                           
    return args

最后一步,为了将它与 DEEPaaS API 集成,你需要使它可安装(你应该这样做),并使用 Python 的 setuptools 定义一个入口点。DEEPaaS 将使用这个入口点来了解如何加载以及如何将不同的函数插入到已定义的端点。我们目前使用的是deepaas.model.v2入口点名称空间,因此我们可以如下创建setup.py文件:

from distutils.core import setup                                                   

setup(                                                                             
    name='test-iris-with-deepaas',                                                 
    version='1.0',                                                                 
    description='This is an SVM trained with the IRIS dataset',                    
    author='Álvaro López',                                                         
    author_email='aloga@ifca.unican.es',                                           
    py_modules="iris-deepaas.py",                                                          
    dependencies=['joblib', 'scikit-learn'],                                       
    entry_points={                                                                 
        'deepaas.v2.model': ['iris=iris-deepaas'],                                 
    }                                                                              
)

安装、运行 DEEPaaS 并展示您的模型

一旦您准备好代码,您只需要安装您的模块和 DEEPaaS API,这样它就可以检测到它并通过 API 公开它的功能。为了以一种简单的方式做到这一点,让我们创建一个 virtualenv 并在其中安装所有内容:

$ virtualenv env --python=python3
    (...)
$ source env/bin/activate
(env) $ pip3 install .
    (...)
(env) $ pip3 install deepaas
    (...)
(env) $ deepaas-run

         ##         ###
         ##       ######  ##
     .#####   #####   #######.  .#####.
    ##   ## ## //   ##  //  ##  ##   ##
    ##. .##  ###  ###   // ###  ##   ##
      ## ##    ####     ####    #####.
              Hybrid-DataCloud  ##

Welcome to the DEEPaaS API API endpoint. You can directly browse to the
API documentation endpoint to check the API using the builtint Swagger UI
or you can use any of our endpoints.

    API documentation: http://127.0.0.1:5000/ui
    API specification: http://127.0.0.1:5000/swagger.json
          V2 endpoint: http://127.0.0.1:5000/v2

-------------------------------------------------------------------------

2020-02-04 13:10:50.027 21186 INFO deepaas [-] Starting DEEPaaS version 1.0.0
2020-02-04 13:10:50.231 21186 INFO deepaas.api [-] Serving loaded V2 models: ['iris-deepaas']

访问 API,触发训练和预测

如果一切正常,现在你应该能够将你的浏览器指向控制台中打印的 URL(http://127.0.0.1:5000/ui)并得到一个好看的 Swagger UI ,这将允许你与你的模型进行交互。

因为这是一个简单的例子,我们还没有提供一个经过训练的模型,所以首先要做的是进行一次训练。这将调用train()函数并保存训练好的 SVM 以备后用。您可以通过用户界面或命令行来完成:

curl -s -X POST "http://127.0.0.1:5000/v2/models/iris-deepaas/train/" -H  "accept: application/json" | python -mjson.tool
{
    "date": "2020-02-04 13:14:49.655061",
    "uuid": "16a3141af5674a45b61cba124443c18f",
    "status": "running"
}

训练将异步完成,这样 API 就不会阻塞。您可以从 UI 中检查其状态,或者使用以下调用:

curl -s -X GET "http://127.0.0.1:5000/v2/models/iris-deepaas/train/" | python -mjson.tool
[
    {
        "date": "2020-02-04 13:14:49.655061",
        "uuid": "16a3141af5674a45b61cba124443c18f",
        "status": "done"
    }
]

既然模型已经定型,我们就可以进行预测了。鸢尾数据集由 3 种不同类型的鸢尾(Setosa、Versicolour 和 Virginica)花瓣和萼片长度组成。样本有四列,分别对应于萼片长度、萼片宽度、花瓣长度和花瓣宽度。在我们的示例中,让我们尝试获取[5.1\. 3.5, 1.4, 0.2]观察的结果,并获取结果。同样,您可以从 UI 或命令行进行设置,如下所示:

curl -s -X POST "http://127.0.0.1:5000/v2/models/iris-deepaas/predict/?data=5.1&data=3.5&data=1.4&data=0.2" -H  "accept: application/json" | python -mjson.tool
{
    "predictions": {
        "labels": [
            0
        ]
    },
    "status": "OK"
}

如您所见,结果包含了我们的 SVM 执行的预测。在这种情况下,输入数据的标签是0,这确实是正确的。

整个代码示例可以在这个要点中找到。

结论

在这个简单的例子中,我们展示了机器学习实践者如何通过依赖于 DEEPaaS API 的 REST API 来公开任何基于 Python 的模型,而不是开发他们自己的自制 API。通过这样做,数据科学家可以专注于他们的工作,而不用担心编写和开发复杂的 REST 应用程序。此外,通过使用一个通用的 API,不同的模块将共享相同的接口,这使得它更容易在生产中部署和被不同的程序员使用。

承认

DEEPaaS API 已在DEEP-Hybrid-data cloudh 2020 项目(授权协议号 777435)中开发,该项目旨在为欧洲分布式电子基础设施上的机器学习和深度学习构建一个平台。

注:本帖原帖于KD nuggets

应用和数据接收流的发布者/订阅者模型

原文:https://towardsdatascience.com/publisher-subscriber-model-for-apps-and-data-ingestion-flows-b8ba7e85e992?source=collection_archive---------23-----------------------

探索实时数据流应用模型中的 Google Cloud 发布/订阅

约纳斯·勒普在 Unsplash 上拍摄的照片

在本文中,我将向数据工程师和应用程序开发人员展示发布者/订阅者模型的特征。我将首先解释概念的定义及其架构,什么是 Google Cloud 发布/订阅云服务,最后以一个简单的演示作为使用示例。

议程

  • 流式编程模型的概念和特征
  • 发布者/订阅者模型的一般架构
  • 谷歌云发布/订阅的概念和特征
  • 谷歌云发布/订阅架构
  • 演示

流式编程模型

编程模型是基于由一个名为主题的频道记录传输系统组织的工作流程编排。

在这个模型中有两个不同的角色,生产者消费者(稍后将被称为发布者和订阅者)。生产者负责发布关于主题的记录,其中通常由分布式集群组成的数据中心接收记录,存储记录,并使消费者可以通过访问主题的记录队列来获得记录。

使用 Apache Kafka 集群的示例。出自阿帕奇卡夫卡

当代理同时扮演两种角色时,就会出现实时流,通常从消费者接收发送到主题的记录开始,对接收到的信息应用某种处理或任务,最后在不同的主题上再次发布。

传输系统具有以下基本特征:

  1. 允许发布和订阅记录流,类似于消息队列或企业消息传递系统。
  2. 它有一个数据中心,以容错的持久方式存储记录流。
  3. 进程在流发生时记录流。

然后,流编程模型封装数据管道和应用程序,这些数据管道和应用程序对它们接收的记录流进行转换或做出反应。

发布者/订阅者模型的体系结构

首先,让我们解决模型的主要抽象层次:主题

主题是记录发布到的类别或提要名称。它可以被理解为通过某种协议(FTP、TCP/IP、UDP、HTTP、SMTP 等)接收信息的通信信道,并且其信息按照到达的顺序被保留,并且可以被一个以上的咨询源(多订户)访问。

阿帕奇卡夫卡主题剖析。来自阿帕奇卡夫卡

主题的结构可以根据我们实现的流系统而变化,如果您使用 Apache Kafka,您将有多个分区来确保复制并增加主题信息的可用性。

所有系统的共同点是,主题是由有序的、不可变的记录序列组成的,这些记录被不断追加到结构化提交日志中。主题中的每个记录都被分配了一个称为偏移量的顺序 id 号,它唯一地标识了主题中的每个记录。

另一方面,发布者和订阅者是流媒体系统的外部实体,它们可以通过上述相同的协议与之通信。该模型的一个优点是,发布者和订阅者可以是云系统,可以是用任何语言编写的作业,甚至可以是授权的第三方应用程序。如果需要,这种类型的大多数系统公开库和模板来构建定制客户机。

发布/订阅通用架构。来自亚马逊网络服务

介绍谷歌云发布/订阅

Google 云平台提供 Pub/Sub 作为异步消息服务,将产生事件的服务与处理事件的服务分离开来。基本上,它允许我们创建主题和订阅渠道,而不必担心存储和分发所需的数据中心基础架构。

来自谷歌云平台 YouTube 频道

使用 Google Cloud SDK,我们可以为订阅的发布和消费构建我们的客户端,依靠与平台其余服务的原生集成,这显然增加了我们系统在流模型下的潜力。

在 Google Cloud Pub/Sub 中,发布者应用程序创建消息并将其发送给主题。订阅者应用程序创建一个对主题的订阅,以接收来自主题的消息。通信可以是一对多(扇出)、多对一(扇入)和多对多。

使用 Google Cloud 发布/订阅的发布者和订阅者关系。来自谷歌云平台

谷歌云发布/订阅架构

谷歌云发布/订阅架构流程示例。来自谷歌云平台

Google Cloud Pub/Sub 通过其 API 使用 HTTP 协议通过互联网发送流量,允许灵活地发送记录(批量或在线)和接收记录(异步或同步)。

谷歌云发布/订阅内部架构。来自谷歌云平台

使用此服务的任何解决方案的架构都必须通过 HTTP 将 base 64 格式的记录(称为消息)发送到主题(因此它可以是任何类型的数据),一旦接收到记录,它将在创建主题后的可配置时间内被存储和复制。然后,主题的订阅者接收消息,直到达到最大存储时间,或者直到订阅者用 ack 确认了消息,以先发生的为准。

演示

为了用一个应用程序的例子来解释应用程序和数据流的发布/订阅模型的功能,我将构建一个简单的架构,包含一个主题和一个 Google Cloud 发布/订阅。

演示架构

演示将包括通过以下步骤构建解决方案:

  1. Google Cloud 发布/订阅主题和订阅创建。
  2. API 连接的设置。
  3. 使用 GCP API 定制 Python 发布者和订阅者编码。
  4. 通过云功能扩展连接可能性。
  5. 面向第三方出版商的 Salesforce Lightning 应用程序示例。

最后,我将展示如何使用 Google Cloud Dataflow 和 Tableau 扩展该架构,以包括数据接收流和实时分析。

Google Cloud 发布/订阅主题和订阅创建。

使用 GCP 控制台创建主题和订阅是一个非常简单的过程。首先,在菜单中查找 Pub/Sub。

截图来自 GCP 控制台

创建一个提供主题 ID 的主题(您可以使用自己的 AES 256 密钥加密主题)。

截图来自 GCP 控制台

当主题准备好时,为它创建一个简单的订阅。

来自 GCP 控制台的截图

仅此而已。记下主题和订阅名称,因为稍后会用到它们。

API 连接的设置

为了将我们的应用程序与我们的 Google Cloud 项目连接起来,需要进行身份验证。在这种情况下,为了简化过程并确保安全性,我们将创建两个服务帐户,以 JSON 格式获取它们的凭证,并将它们用作身份验证方法。

第一个服务帐户将用于发布者,它只允许发布到主题权限。转到 IAM >服务帐户。

截图来自 GCP 控制台

创建新的服务帐户,并提供名称和描述(服务帐户 ID 将自动创建)。

来自 GCP 控制台的截图

在角色部分中,搜索发布/订阅发布者。

截图来自 GCP 控制台

最后创建一个密钥,并以 JSON 格式下载它。

截图来自 GCP 控制台

这就是发布者服务帐户,对于订阅者重复这些步骤,但是将选择的从发布/订阅发布者更改为发布/订阅订阅者。

来自 GCP 控制台的截图

两个服务帐户现在都可以使用了。

截图来自 GCP 控制台

使用 GCP API 定制 Python 发布者和订阅者编码。

为了构建这两个定制的客户端,需要一个安装了 google-cloud-pubsub 库的 python 环境。

此外,我们必须创建环境变量 GOOGLE_APPLICATION_CREDENTIALS,它的值将是带有我们之前下载的凭证的 JSON 文件的路径。

在我的例子中,我使用 Anaconda 创建了一个环境,并使用 pip 安装了库。官方安装文件可以在链接中找到。

本地 Pyhton 环境设置。我将 JSON 文件重命名为一个有意义的名称。

现在环境已经准备好了,我们可以开始为我们的客户编码了。

出版者

使用库和文档编写了一个简单的发布脚本,它将从系统参数中发布一条消息,或者在没有提供参数的情况下发布一条默认值。最后,它将打印消息 ID 作为成功的确认。确保将 topic_name 替换为您的 Google Cloud 发布/订阅主题的名称。

订户

订阅者获取其他 JSON 凭证,并简单地一个接一个地遍历主题的消息,打印其数据,并对收到的每条消息用预期的 ack 进行响应。

现在,我们已经准备好使用控制台运行我们的客户端进行测试。

Python 客户端演示

可以看出,在发布者客户端发送其消息时,订阅者客户端响应打印该消息。

通过云功能扩展连接可能性

目前,我们有本地客户,他们完成了发行商和订户的基本功能。然而,使用任何类型的客户机来扩展我们的选择将是有趣的,因为我们目前受限于存在连接 API 的编程语言。

由大卫·维尔德霍在媒体上拍摄的照片

为了解决这个问题,我们将使用 Google Cloud Functions,这是一个无服务器的解决方案,允许我们将发布客户端作为一个 web 服务公开,该服务通过 HTTP 协议接收消息,并使用 API 将它们发送到主题,就像我们刚刚构建的客户端一样。

首先,在 GCP 控制台中寻找云函数。

截图来自 GCP 控制台

创建一个新函数,键入名称,选择适当的内存分配,并选择 HTTP 作为触发器。此外,出于测试目的,您可以允许未经身份验证的调用,在生产环境中,您会期望每个 HTTP 触发器中都有一个身份验证头。

来自 GCP 控制台的截图

对于源代码,您可以压缩一个完整的环境,并上传为直接文件、云存储中的文件或云源代码中的存储库。对于这个演示,内联编辑器就足够了,选择 Python 3。x 为运行时。

截图来自 GCP 控制台

大体上。考虑到参数将在 JSON 请求中接收,我们将提供我们的函数代码。我们的本地 publisher 客户端的准确转换如下所示。

main.py

对于另一个选项卡,我们需要提供执行代码所需的库的名称。在这个演示中,我们只需要 google-cloud-pubsub 库。

来自 GCP 控制台的截图

在高级选项中,不需要在 JSON 文件中提供凭证,因为我们可以直接在 GCP 控制台中设置将在每个触发器执行期间使用的服务帐户。

来自 GCP 控制台的截图

另外,不要忘记在要执行的函数字段中提供正确的函数名。就这样,当函数准备就绪时,我们可以使用函数的 url 测试与任何 REST 消费者的连接,在这种情况下,我将使用 SOAP UI。

SOAP UI 测试

如您所见,我们的客户端订户能够接收使用 Google Cloud Functions web 服务的 SOAP UI 发送的消息。确保媒体类型为应用程序/json。

面向第三方出版商的 Salesforce Lightning 应用程序示例

为了演示我们与任何系统集成的能力是如何扩展的,我决定使用 Salesforce CRM 并在其中构建一个 lightning 应用程序,该应用程序由一个简单的文本字段和一个按钮组成,当按下该按钮时,通过 HTTP 将文本发送到 web 服务。

Salesforce publisher Lightning 应用。截图来自通过 Trailhead 提供的免费 Saleforce 组织

为了避免深入研究这个工具的构造,我将简单地展示当您单击按钮时执行的源代码。

Apex 中的按钮 onClick 方法,Salesforce 编程语言

如你所见,这是创建一个对象,向 Google Cloud Function URL 发送一个 PUT 类型请求,其主体是一个 JSON,内容类型应用程序/json。

Salesforce 演示

如何包含数据摄取流

通过当前的架构,我们可以将我们的发布者和订阅者连接到任何应用程序,但我们没有考虑到需要对收到的记录进行一个或多个清理过程的情况,也没有及时存储记录。

使用谷歌云数据流,我们可以通过从模板创建一个清理流(或从头创建我们自己的)来扩展我们当前的架构,以将数据存储在数据仓库中,如 BigQuery,该数据仓库可由 Tableau 等分析客户端访问。

在 GCP 控制台的主题详细信息页面中,我们可以创建一个作业,使用 Google Dataflow 将主题的消息导出到 Google BigQuery。

为 Google Cloud 发布/订阅主题创建数据流。截图来自 GCP 控制台

来自 GCP 控制台的截图

使用对 BigQuery 模板的云发布/订阅,我们可以创建一个管道,从发布/订阅获取 JSON 编码的消息的云发布/订阅流,通过用户定义的 JavaScript 函数执行转换,并写入预先存在的 BigQuery 表。

然后,在 BigQuery 中,我们可以使用 Google data studio 或 Tableau 等第三方客户端构建实时报告和仪表板。

完整的架构:流发布/订阅应用+数据流

结论

本文解释了基于流的编程模型的架构和概念,解释了它的架构和与 Google Cloud 发布/订阅工具的使用,最后展示了一个演示,在这个演示中可以证实该模型提供的集成功能,无论是用于创建从流数据中心提供的应用程序,还是用于数据工程和实时报告的 ETL 流。

文献学

  • https://cloud.google.com/pubsub/docs/concepts
  • https://kafka.apache.org/documentation/#gettingStarted
  • 【https://aws.amazon.com/pub-sub-messaging/
  • https://googleapis.dev/python/pubsub/latest/index.html
  • https://Google APIs . dev/python/pubsub/latest/publisher/index . html
  • https://Google APIs . dev/python/pubsub/latest/subscriber/index . html #异步拉取订阅
  • https://cloud . Google . com/functions/docs/writing/http # sample _ usage

发布模型以从 Rest API 获得对新数据的预测

原文:https://towardsdatascience.com/publishing-the-model-to-get-predictions-on-new-data-from-rest-api-3083cf81c45?source=collection_archive---------57-----------------------

通过使用 TensorFlow 服务托管的模型从 Rest API 获取数据预测。

所以,你有一个漂亮的模型,它在数据上非常有效。现在,您希望将该模型投入生产,并根据新数据进行预测。

让我向您介绍 TensorFlow 服务系统,该系统旨在为生产中经过培训的模型提供服务。默认情况下,它与 TensorFlow 模型无缝集成,但功能也可以扩展到其他模型。

保存模型

所以,让我们说,在遵循了这篇文章中的步骤之后,你有了一个训练有素的模型,并且你正在使用 Google Colab。

TensorFlow 服务的模型必须与版本和变量一起保存,这可以通过下面的代码来完成:

检查我们刚刚保存的模型

如果在 TF 服务中有几个模型,而我们不知道这些模型的细节,这是很有帮助的。这段代码变得非常有价值,在这种情况下,它将显示已保存模型的内容。

为模型服务并获得预测

服务使我们能够管理模型的版本,并确定使用哪个版本的优先级。这对于重新训练模型或者在不损害平台架构完整性的情况下促进迁移学习特别有用。

现在让我们使用 TensorFlow Serving 的 REST API 进行预测:

本主题到此结束,它涵盖了前面提到的文章中所涵盖的构建模型的端到端过程,然后托管模型以使用 Rest API 获得新数据的预测。

使用服务有多种方式,这个主题本身扩展并联系了使用 Google Cloud 服务模型。

从 Jupyter 笔记本发布到媒体

原文:https://towardsdatascience.com/publishing-to-medium-from-jupyter-notebooks-53978dd21fac?source=collection_archive---------33-----------------------

约翰·马特丘克在 Unsplash 上拍摄的照片

在媒体上创建技术职位的更有效方法

程序员们,当我们写一篇技术文章时,我们都知道写一个笔记本然后不得不将代码复制并粘贴到介质中的困难…头痛!让我高兴的是,可能也是你高兴的是,我发现了一个包,我相信它是我们关于媒体灾难的编程的拯救之恩。

Jupyter-to-Medium是由一位媒体作家同行 Ted Petrou 创造的。Ted 将这种挫折感转化成了我认为非常有创意的方案——点击此处 阅读更多。

我在这篇文章中的动机很简单。我的目标是演示并测试 Jupyter-to-Notebook 包的全部功能,然后添加我对该包的想法以及对那些决定将它作为其博客工作流程一部分的人的建议。

免责声明:我不是付费推广人,也没有被要求以任何方式在 Jupyter-to-Medium 上写这个故事——我只是觉得这是个很酷的想法。

概观

那些精通 Jupyter 笔记本的人会知道 LaTex 是一个内置功能——如果你不知道,现在你知道了。我经常发现自己不得不在谷歌上搜索数学表达式的图像(这不违反任何版权协议),或者在最糟糕的情况下,我不得不在将它作为图像导入 Medium 之前,自己动手设计它。

这一过程可能极其费力,更不用说它有多乏味了。有很多帖子我不得不推迟一个小时发表,因为我正在创建我的数学表达式的图像——不将 LaTex 纳入媒体的想法是一场灾难,但如果有合理的理由说明为什么不这样做(或者如果我不知道如何做),那么我就收回。

如前所述,LaTex 是 Jupyter 笔记本的一个特性,所以我希望当我在笔记本中实现 LaTex 时,它会在导入到介质中时自动解析为图像。但是—

$ $ \ hat { y } = \ theta _ { 0 }+\ theta _ { 1 } X _ { 1 }+\ theta _ { 2 } X _ { 2 } $ $

显然事实并非如此(上面的是我在 Jupyter 笔记本中写的 LaTex 代码的一个例子)。

尽管如此,每当我打开 Jupyter 笔记本环境时,通常不是为了在 markdown 单元格中编写 LaTex 代码。相反,我通常使用笔记本来执行一些类型的原型制作、可视化、分析等。因此,这个属性不符合我最初的期望,无论如何不会损害这个包的前景。

在 Medium 上写技术故事的一个非常恼人的壮举是,当你不得不将你在 Jupyter 笔记本上写的所有代码复制并粘贴到 Medium 上时——想想它就让我更加恼火!

Jupyter-to-Medium 将我们写在笔记本上的代码单元翻译成 Medium 中的代码块,然后发布到其他地方。

*# example of code cell being translated to code block on medium

print("Hello World")Hello World*

挺酷的吧!

进一步来说,当在我们的 Jupyter 笔记本环境中工作时,我们经常有一些我们试图探索的数据。我不知道其他人如何将他们的数据框架整合到他们的技术博客中,但我必须对每个单独的数据框架进行截图并裁剪,以便我可以将其作为图片上传到我的媒体故事中——这又是一个花费不必要时间的过程!

必须截图,然后在上传前保存也是相当漫长和繁琐的。当数据框有很多列时,笔记本会在数据框和滚动条上添加省略号,以显示更多的列……我想看看 Jupyter-to-Medium 如何处理这一壮举,令我高兴的是,我被深深打动了。

图 1* 中,您可以看到省略号是存在的,但是解析器提取了表格并以合适的大小将其粘贴到介质上。*

演示数据来自 Kaggle 分类特征工程竞赛— 点击此处 访问数据集。

*import pandas as pd 

df = pd.read_csv("../data/categorical_feature_engineering_raw/train.csv")
df.head()*

图 1

我经常使用 Plotly 来实现我的可视化,然而当我最初试图在这篇博客文章中使用它时,我的文章导致了 60 分钟的阅读,内容与我当前的文章完全相同。经过进一步的检查,我意识到我所有的 Plotly 代码都被转换成了一长串数字(我也不小心把这个发表到了《走向数据科学》上— 对不起,伙计们)。

长话短说,我用 Matplotlib 做这个概述。

合并 Plotly 的失败可能会让那些已经从静态情节完全转换到交互情节的人,以及那些甚至没有体验过 matplotlib 的人感到不安。但是,如果你对框架不是那么挑剔,你会做得很好,而且 matplotlib 非常容易学习!

:我没有测试 Seaborn,所以如果你使用它,请让我知道结果 t.

*# https://matplotlib.org/api/pyplot_api.html

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 5, 0.1);
y = np.sin(x)
plt.plot(x, y)
plt.show()*

图 2

*# https://matplotlib.org/3.1.1/gallery/images_contours_and_fields/image_annotated_heatmap.html

vegetables = ["cucumber", "tomato", "lettuce", "asparagus",
              "potato", "wheat", "barley"]
farmers = ["Farmer Joe", "Upland Bros.", "Smith Gardening",
           "Agrifun", "Organiculture", "BioGoods Ltd.", "Cornylee Corp."]

harvest = np.array([[0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0],
                    [2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0],
                    [1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0],
                    [0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0],
                    [0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0],
                    [1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1],
                    [0.1, 2.0, 0.0, 1.4, 0.0, 1.9, 6.3]])

fig, ax = plt.subplots(figsize=(8, 10))
im = ax.imshow(harvest)

# We want to show all ticks...
ax.set_xticks(np.arange(len(farmers)))
ax.set_yticks(np.arange(len(vegetables)))
# ... and label them with the respective list entries
ax.set_xticklabels(farmers)
ax.set_yticklabels(vegetables)

# Rotate the tick labels and set their alignment.
plt.setp(ax.get_xticklabels(), rotation=45, ha="right",
         rotation_mode="anchor")

# Loop over data dimensions and create text annotations.
for i in range(len(vegetables)):
    for j in range(len(farmers)):
        text = ax.text(j, i, harvest[i, j],
                       ha="center", va="center", color="w")

ax.set_title("Harvest of local farmers (in tons/year)")
fig.tight_layout()
plt.show()*

图 3

那些关注我的故事的人会知道我喜欢给我的照片贴标签。如果你想知道我是在 Jupyter 笔记本上还是在 Medium 上标注数字,答案是“我在 Medium 上做的”。

最后但并非最不重要的,动画。我以前从未用过动画,所以我想尝试一下可能会很酷。

*# http://louistiao.me/posts/notebooks/embedding-matplotlib-animations-in-jupyter-as-interactive-javascript-widgets/

from matplotlib import animation
from IPython.display import Image
%matplotlib inline

fig, ax = plt.subplots()

ax.set_xlim(( 0, 2))
ax.set_ylim((-2, 2))

line, = ax.plot([], [], lw=2)

def init():
    line.set_data([], [])
    return (line,)

def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return (line,)

anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=100, interval=20, 
                               blit=True)

anim.save('animation.gif', writer='imagemagick', fps=60)print("Static plot")
Static plot*

图 4

*anim.save('animation.gif', writer='imagemagick', fps=60)Image(url='animation.gif')*

图 5

注意:我确实不得不手动导入 gif,但这可能只是因为我对使用 gif 不熟悉,因为在 Ted done 的主要文章中有一个完整的 gif。

图 6:我的文章从 Jupyter 笔记本上发表的确认

要获得完整的代码,请点击下面的链接,但请注意,从我的 Jupyter 笔记本上最初上传的是我的第一份草稿,因此你可能会注意到笔记本上的大幅修改。

* [## kurtispykes/演示

github.com](https://github.com/kurtispykes/demo/blob/master/notebook/kpy_jupyter_to_medium_test.ipynb)*

我的概述

我想我已经清楚地表达了我的观点——我认为这个软件包非常有创意,我真诚地建议每个在 Medium 上写技术文章的人应该避免使用这个软件包。尽管如此,我还是要警告任何决定采用这种包装的人,要小心 Jupyter 笔记本和介质的用途形成了明显的对比,这一点应该被考虑在内。

媒体上的共享被优化以使写作更像样,Jupyter 笔记本是用来做整洁的探索的。当我们从笔记本中发布到 Medium 时,这一点变得非常明显,因为要让您的 Medium 故事看起来像样,至少在我看来是这样的。我不认为直接从 Jupyter 笔记本发布是一个好主意,你几乎总是想要编辑格式和样式(例如,首字下沉)。

我最好的建议是利用这两个平台的优势,这样你就可以对你最初的 Jupyter 笔记本进行调整,但同时,重要的是要意识到大部分繁重的工作已经为你完成了!

如果你想和我联系,最好的方式是通过 LinkedIn

* [## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn

在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)*

在网络上发布您自己的数据科学文档/书籍

原文:https://towardsdatascience.com/publishing-your-own-data-science-documentation-book-on-the-web-d859caa07b46?source=collection_archive---------27-----------------------

关于如何使用免费的 MkDocs 和 GitHub 页面在线发布您自己的项目文档/书籍的指南。

帕特里克·托马索在 Unsplash 上的照片

介绍

你有没有想过图书馆通常如何在线发布他们的文档?在线发布项目文档最常见的方式之一是使用 MkDocs 。

MkDocs 是一个静态站点生成器,它只使用一个 Markdown 文件列表和一个 YAML 配置文件来立即生成自己的网站,然后可以使用 GitHub 页面在一行代码中免费部署。

如果你正在寻找一个使用 MkDocs 生成的网站的例子,你可以在这里找到我写的关于我的研究项目“通过游戏和机器学习缓解儿童健康问题”的书,我在我的上一篇文章中谈到过它(图 1)。

图 1: 使用 Mkdocs 创建的示例文档项目。

在本文中,我将带您快速了解如何生成您自己的在线项目文档。

创建项目

首先,我们需要安装 MkDocs Python 库。

pip install mkdocs

一旦安装了这个库,我们就可以为我们的项目创建一个文件夹,并从这个位置打开一个命令提示符。运行以下命令,将自动为我们创建一个 Mkdocs 项目。

mkdocs new my-project-name

该项目将具有如下所示的结构:

-- my-project-name
  -- mkdocs.yml
  -- docs
     -- index.md

将使用 mkdocs.yml 文件来设计我们网站的结构,而 docs 文件夹中的所有 Markdown 文件将用于创建网站每个不同页面的内容。如果你不熟悉如何使用 Markdown 创建文本文件,你可以在这里找到介绍指南。

通过创建 mkdocs 项目自动生成的一个简单的 mkdocs.yml 文件如下所示:

site_name: MkLorum 
nav:     
  - Home: index.md

然后我们可以修改它来选择我们想要的网站名称(而不是 MkLorum ),并在网站导航栏上添加多个页面,只需在导航标签下添加新页面即可(在左侧指定导航按钮名称,在右侧指定 docs 文件夹中的文件名)。最后,也可以使用预装的主题(例如 readthedocs )或者从 Mkdocs 社区中选择一个主题来设计我们的网站。

下面是一个更加个性化的 mkdocs.yml 文件示例。

site_name: my_website_name
nav:     
  - Home: index.md     
  - About: about.md
  - Contacts: contacts.md
theme: readthedocs

docs 文件夹中,我们可以找到一个自动创建的 index.md 文件,然后我们可以为自己的网站定制这个文件。然后,我们可以通过在 docs 文件夹中添加新的 Markdown 文件,然后在 mkdocs.yml 文件中引用它们,向网站添加任意多的页面。

在开发阶段的每一点,我们都可以通过在命令行中从我们的项目位置运行以下命令来观察我们网站的外观:

mkdocs serve

这将激活一个本地服务器,然后我们就可以在这个地址看到我们的网站: http://127.0.0.1:8000 。一旦我们的本地服务器运行,如果我们修改任何文件(并保存更改),它们将自动显示在网站上。

将所有内容添加到网站并检查其显示是否正确后,我们可以通过运行以下命令来构建 HTML 和 CSS 文件:

mkdocs build

至此,我们已经准备好用 GitHub 库初始化我们的项目了。之后,我们可以从命令运行我们的最后一个命令,然后我们的项目将在线部署:

mkdocs gh-deploy

在命令提示符下,将会显示我们的网站将被激活的链接。或者,我们可以通过访问我们的存储库设置并查找 GitHub pages 选项来找到相同的链接(运行上面显示的命令,实际上会自动生成一个名为 gh-pages 的新分支,GitHub 将使用它来托管我们的文档网站)。

联系人

如果你想了解我最新的文章和项目请关注我的媒体并订阅我的邮件列表。以下是我的一些联系人详细信息:

  • 领英
  • 个人博客
  • 个人网站
  • 中型型材
  • GitHub
  • 卡格尔

使用简单的 Python 包提取和分析金融数据

原文:https://towardsdatascience.com/pull-and-analyze-financial-data-using-a-simple-python-package-83e47759c4a7?source=collection_archive---------7-----------------------

我们演示了一个简单的 Python 脚本/包来帮助您提取财务数据(所有您能想到的重要指标和比率)并绘制它们。

图片来源: Pixabay(免费商业使用)

介绍

股票市场分析和良好的投资(为了长期增长)需要仔细检查财务数据。各种指标和比率经常在这种分析中使用,即评估股票的内在质量。你可能在金融和投资专家的谈话中听说过其中一些。

比如 市盈率 或者市盈率。它是股价与年收益/每股的比率。

或者, 每股账面价值 。它是一家公司的普通股除以其发行在外的股票数量的比率。当一只股票被低估时,它的每股账面价值相对于它在市场上的当前股价会更高。

[## 用市盈率和钉住率评估股票的未来

市盈率(P/E)是投资者和分析师用来确定股票价格的最广泛使用的指标之一

www.investopedia.com](https://www.investopedia.com/investing/use-pe-ratio-and-peg-to-tell-stocks-future/)

通常这些数据可以从雅虎财经这样的网站上获得。但是,除非您使用某种付费的注册服务,否则您不能以编程方式下载或抓取数据。

[## 雅虎财经-股市直播,报价,商业和金融新闻

在雅虎财经,你可以获得免费的股票报价、最新新闻、投资组合管理资源、国际市场…

finance.yahoo.com](https://finance.yahoo.com/)

然而,有许多微服务通过简单的 API 调用提供这样的数据。为了利用这一点,我们将在本文中展示,如何编写一个简单的 Python 类脚本来与 金融数据微服务 进行交互。

图片来源:作者截屏(网站)

使用这个 Python 类,您可以通过调用一系列简单的方法来提取数据并构建一个包含几乎所有重要财务指标和比率的 Pandas 数据框架。

我们还提供简单的图表方法(条形图和散点图)来图形化分析数据。

注意,你需要从网站获取自己的秘密 API key(免费)并在实例化类对象后注册。

也就是说,让我们研究一下 Python 包/类和它附带的各种方法。

Python 类和各种内置方法

核心 Python 类在我的 Github repo 上可用 。请随意开始和叉回购,并对其进行改进。您可以简单地克隆存储库,并开始在您自己的笔记本中使用脚本。

**> mkdir My_project
> cd My_Project
> git clone** [**https://github.com/tirthajyoti/Finance-with-Python.git**](https://github.com/tirthajyoti/Finance-with-Python.git) **> cd financeAPI** 

为了保持代码的整洁,在本文中,我们在一个测试 Jupyter 笔记本中展示了该类的用法。

我们从导入常规库和类对象开始。

从文件中读取秘密 API 密钥并注册它

注意,您需要在与代码文件相同的目录中有一个名为Secret_Key.txt的文件。没有它,你就不能进步。

在这里报名:https://financialmodelingprep.com/login

创建一个类实例

它有一个描述

不注册密钥,我们无法访问数据

我们肯定想现在就开始提取数据。假设我们想为苹果公司(股票代码为“AAPL”)构建一个数据字典。我们可以尝试,但不会成功,因为我们还没有向类对象注册密钥。

所以,我们注册了密钥

现在让我们建立一个数据字典

对于这个类中的所有方法,我们必须传递公司的股票代码(在美国金融市场上)。对苹果公司来说,这是“AAPL”。

如果我们检查这个字典,我们会注意到大量的数据是从 API 端点提取的。下面提供了部分截图。

用多家公司的数据构建一个数据框架

使用 Python 字典很好,但是对于大规模数据分析,我们应该考虑构建一个 Pandas 数据框架。我们提供了一个内置的方法来做到这一点。构建一个数据框架就像传递一个股票代码列表一样简单,代码会为您完成所有的数据搜集和结构化工作。

假设我们想下载以下公司的所有财务数据,

  • 推特
  • 脸谱网
  • 微软
  • 英伟达
  • 苹果
  • 销售力量

一个格式良好的数据帧已经准备好供您使用了!

究竟什么样的数据是可用的?

我们可以很容易地检查从 API 服务中提取的数据类型。注意,我们传递一个参数“profile”、“metrics”或“ration”,并获取相应数据项的列表。

开始绘图—可视化分析

在这个包中,我们已经包含了对数据进行简单可视化分析的代码。

在简单的条形图中检查各种指标和财务比率通常很有帮助。为此,只需传递您想要绘制的变量的名称。您还可以包含常见的 Matplotlib 关键字参数,如颜色和透明度(alpha)。

您还可以绘制简单的散点图,直观地分析财务指标之间的相互关系。

您还可以传递第三个变量,用于缩放散点图中标记的大小。这有助于以一种间接的方式,在一个二维图中可视化两个以上的变量。例如,我们在下面的代码中将股价参数作为第三个变量传递。

使用底层数据框架进行自定义分析

通常,投资者可能希望利用现有数据创建自己的过滤器和投资逻辑。

例如,我们可能只想考虑那些市值超过 2000 亿美元的公司,然后在条形图中查看企业价值相对于 EBIDTA 的度量。

我们可以访问底层数据帧,创建自定义数据帧,然后将该自定义数据帧分配给新的financeAPI()对象,以利用现成的图表方法。

这样,我们就不需要再向 API 请求数据了。我们要尽量避免数据读取,因为 free API key 读取数据的数量有限制。

然后我们根据这个自定义数据框架(嵌入在自定义类对象中)绘制一个条形图。

摘要

我们展示了一个简单 Python 类/包的实现和用法,该类/包可用于从微服务中提取各种财务指标和比率。

需要向服务注册才能获得免费的 API 密钥。当然,就免费帐户读取的数据数量而言,这种使用是有限的。该网站还有无限使用的付费计划。

请注意,这项工作侧重于年度财务报表中可用的静态财务数据,而不是动态时序股票市场定价数据。它应该被用来衡量一家公司的长期财务实力,以进行增长型投资。

作为一名数据科学家,您可能经常需要编写定制的类/包来从微服务 API 中提取和分析数据,希望本文(以及相关的代码库)能够为您提供简单而有效的知识介绍。

图片来源: Pixabay(免费商业使用)

答另外,你可以查看作者的 GitHub 知识库中机器学习和数据科学的代码、思想和资源。如果你和我一样,对人工智能/机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。

[## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…

通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和有趣…

www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)

将金融时间序列数据引入 Python:一些免费选项

原文:https://towardsdatascience.com/pulling-financial-time-series-data-into-python-some-free-options-dbc2df67d9b7?source=collection_archive---------16-----------------------

将股票价格数据直接导入 Python 进行下一步分析

获取金融时间序列数据集可能会很麻烦。幸运的是,互联网上有很多方法可以将金融时间序列数据直接导入 Python 进行分析。更好的是,这些选项中有许多是免费的。在本教程中,我们将使用以下免费 API 选项将金融时间序列数据导入 Python:

  • 阿尔法优势
  • Quandl

在这两个 API 之间,我们应该能够访问绝大多数金融数据集,包括每日和当天的股票价格数据。

使用 Alpha Vantage API 提取数据

总部位于马萨诸塞州波士顿的 Alpha Vantage 是历史和实时股票数据、实物货币数据和加密货币数据的免费 API 的领先提供商。获得一个免费的 API 密钥来访问它的数据库很简单。进入该网页,按照提示填写您的联系方式:

填写您的联系方式,申领您的免费 API 密钥

一旦你完成了,Alpha Vantage 会在它的网页上打印一个 API 密匙供你个人使用。您可以使用这个键将数据直接拉入 Python 进行分析。

下载所需的库

Alpha Vantage 有一个专门针对其 API 的 Python 库。进入命令提示符并输入以下内容来下载 Alpha Vantage 的 API 包:

pip install alpha-vantage

当天时间序列数据

通过 Alpha Vantage 的 API 提取时间序列数据有几个选项,这取决于您想要的数据频率级别。我们将介绍的第一种方法是日内数据,我们希望提取数据频率为 1 小时或更少的时间序列。

我们使用以下代码提取 Google 股票的时间序列数据,数据频率为 15 分钟:

谷歌股价(高位),15 分钟间隔数据

返回的当天 Google 股票时间序列数据快照。数据包括开盘价、最高价、最低价、收盘价和成交量信息。

我们使用pull _ intraday _ time _ series _ alpha _ vantage()函数提取时间序列数据。该功能允许 1 分钟、5 分钟、15 分钟、30 分钟和 60 分钟的采样频率。

我们将 API 键、股票代码名称(' GOOGL ')和期望的采样频率作为参数传入。该函数以 15 分钟的数据采样频率返回包含股票数据(包括开盘价、最高价、最低价、收盘价和成交量数据)的数据帧,以及与时间序列相关联的元数据数据帧。

每日时间序列数据

除了日内数据之外,Alpha Vantage 的 API 还允许您提取每日时间序列数据。提取每日数据的调用方法类似于提取当天数据的调用方法,如下面的代码片段所示:

伯克希尔·哈撒韦公司股价(高位),每日数据

返回的每日伯克希尔哈撒韦股票数据的快照。数据包括开盘、盘高、盘低、收盘、调整收盘和成交量信息。

在上面的代码块中,我们提取了伯克希尔哈撒韦公司股票的每日时间序列数据,追溯到 100 天前。我们在 main() 块中调用pull _ daily _ time _ series _ alpha _ vantage()函数。该函数接受我们的 API 键,股票代号(在本例中是“BRK。b”)和 output_size 作为参数。 output_size 变量与我们希望返回多少数据有关。默认设置“compact”返回股票过去 100 天的每日数据。如果我们将 output_size 设置为“full ”,则返回完整的时间序列。这可能是二十多年的日常数据!

上面的例子只是对 Alpha Vantage 的 API 功能的简单介绍。有关使用他们的 API 的更多信息,请查看完整的 API 文档:https://www.alphavantage.co/documentation/

使用 Quandl API 提取数据

Quandl 位于加拿大多伦多,拥有超过 400,000 名用户,并提供对开放、商业和替代数据集的访问。数据以易于理解的格式提供,非常适合数据分析。

就个股数据而言,Alpha Vantage 胜过 Quandl,因为 Quandl 对访问大多数日内数据集收费(不过,每日股价数据是免费的)。然而,Quandl 免费提供了大量其他数据集。快速浏览他们的“免费”数据集页面会发现一个免费数据集的宝库,包括:

  1. Wiki 连续期货数据,其中包含 600 个期货的连续合约。基于芝加哥商品交易所、洲际交易所和伦敦国际期货交易所的数据。
  2. Zillow 房地产数据,包括房屋供求数据。该数据集还包括按大小、类型和层级划分的住房和租金数据,这些数据可以是按邮政编码、社区、城市和州划分的子集。
  3. 美联储经济数据,包括美国的增长、就业、通胀、劳动力和制造业数据。

出于本教程的目的,我们将通过 Quandl 的 API 提取美联储数据,以及每日股票价格数据。

获取您的 Quandl API 密钥

要获得免费的 Quandl API 密匙,在这里注册一个 Quandl 账户。

Quandl 报名页面

一旦您成功创建了一个帐户,您应该会收到一封来自 Quandl 的电子邮件来验证您的帐户。验证并激活您的帐户后,请访问您的个人资料页面,该页面清楚地显示了您的 API 密钥:

Quandl 个人资料页面,其中包含您的 API 密钥

下载所需的库

Quandl 有一个特定的 Python 包来处理它的 API。转到命令提示符并输入以下内容来下载 Quandl API 库:

pip install quandl

提取时间序列数据

美联储经济数据

在我们编写任何代码之前,让我们通过其 Quandl 文档页面查看一下美国美联储经济数据(FRED)下可用的不同时间序列集:

FRED 数据集中可用的一些时间序列的快照,可通过 FRED 文档页面 获得

正如您在上面的快照中看到的,有许多时间序列集可供使用。为简单起见,我们来拉一下国内生产总值(GDP)的时间序列。在下面的代码片段中,我们将季度美国 GDP 时间序列数据放入 Python:

季度 GDP 数据

返回的 GDP 时间序列快照

我们将 Quandl API 键定义为 quandl。ApiConfig.api_key 参数。我们使用 quandl 的 get() 函数调用 GDP 数据。“FRED/GDP”作为数据集名称传递——这是我们的时间序列的特定标识符。我们首先通过它所属的主数据存储库引用一个特定的数据集名称—在本例中是‘FRED’—后跟一个斜杠,然后是特定的数据集名称(这里是‘GDP’;该值可在主数据集的文档页面中找到。

日终股价数据

尽管 Quandl 不像 Alpha Vantage 那样提供免费的当日股价数据,但它确实提供每日收盘时的股价数据。我们可以使用以下代码获取微软股票的每日价格数据:

每日微软股票价格,开盘价

上面的代码与前面的例子略有不同,因为我们使用了 quandl 的 get_table() 函数,而不是它的 get() 函数。函数的作用是:返回一个包含多列的熊猫数据帧。相比之下, get() 返回单个时间序列。由 get_table() 调用返回的数据集快照如下所示:

每日微软股票数据,通过 quandl 的 get_table()函数返回

如您所见,返回的 Microsoft stock dataframe 包含股票的开盘价、最高价、最低价、收盘价、成交量和调整值的时间序列数据。

除了上面列出的两个例子,Quandl API 还提供了许多其他功能。有关 Quandl 的 Python API 插件的更多信息,请查看他们在 这个 Github repo中的文档。

结论

本文中涉及的两个 API 都免费为您的下一个时间序列分析提供了广泛的财务数据(如果您正在寻找一个特定的数据集,可以使用高级选项)。获取高质量的数据是数据科学中最大的挑战之一。幸运的是,像 Quandl 和 Alpha Vantage 这样的 API 服务使得获取用于数据探索和算法开发的金融时间序列集变得前所未有的容易。

我关于使用免费 API 将金融时间序列数据导入 Python 进行分析的教程到此结束!关于本教程中使用的完整代码,请查看 Github repo 。

查看我的其他时间序列分析教程:

[## 使用季节性 ARIMA 模型的时间序列预测:Python 教程

时间序列预测中研究最广泛的模型之一是 ARIMA(自回归综合移动…

techrando.com](https://techrando.com/2020/01/04/time-series-forecasting-using-a-seasonal-arima-model/) [## 使用 Python 分析电价时间序列数据:时间序列分解和价格…

欢迎来到科技兰多博客!本教程涵盖了时间序列分解和向量自回归(VAR)…

techrando.com](https://techrando.com/2019/07/19/analyzing-electricity-price-time-series-data-using-python-time-series-decomposition-and-price-forecasting-using-a-vector-autoregression-var-model/) [## 时间序列中离群点检测的无监督机器学习方法

在这篇文章中,我将介绍一些我最喜欢的检测时间序列数据中异常值的方法。有许多不同的…

techrando.com](https://techrando.com/2019/08/23/unsupervised-machine-learning-approaches-for-outlier-detection-in-time-series/)

原载于 2020 年 1 月 12 日【https://techrando.com】

将推文拉入 R

原文:https://towardsdatascience.com/pulling-tweets-into-r-e17d4981cfe2?source=collection_archive---------17-----------------------

链接 Twitter 的 API 的教程

Kon Karampelas 在 Unsplash 上拍摄的照片

在本教程中,我将向您展示建立 Twitter 开发者帐户所需的步骤,这样您就可以利用他们的 API,然后将 tweets 直接拉入您的 R Studio 环境中。

1.申请一个 Twitter 开发者账户

你需要一个 Twitter 开发者账户,因为它可以让你访问一个个性化的 API 密匙,这是我们以后需要的。这个密钥对每个帐户都是唯一的,所以你不能共享它。

访问 Twitter 开发者并创建一个账户。如果你愿意,你可以使用相同的登录凭证登录你的个人 Twitter 账户。

您将需要申请一个帐户,所以请确保按照步骤操作。设置帐户可能需要一些时间,因为您需要回答几个问题。大多数问题需要大量的输入,所以尽你所能回答它。

如果你被卡住了,这是一个关于如何申请的极好的视频。

设置 Twitter API 开发者账户

申请开发者账号

2.创建 Twitter API 应用程序

开发人员帐户可能需要几个小时或几天才能获得批准。这取决于你对申请的回答有多好。有时他们可能会联系你以获取更多信息。

批准后,前往导航栏的右上角,选择应用程序。在这里,您将希望创建一个应用程序,它是生成 API 密钥的一部分。

如果你迷路了,这是一个很好的 API 密匙后续视频。

创建 Twitter API 应用

现在你已经设置好了,让我们从 R Studio 开始吧!

创建应用程序后,您应该会在仪表板上看到您的第一个应用程序。

3.安装/加载 twitteR 包

twitteR 是一个 R 包,提供对 Twitter API 的访问。支持 API 的大部分功能,偏向于在数据分析中比日常交互更有用的 API 调用。

install.packages("twitteR") #install package
library(twitteR) #load package

4.将 API 链接到 R Studio

对于这一步,您需要访问您的 Twitter 开发者帐户,并导航到您创建的应用程序。如果您还没有这样做,请生成新的 API 密钥和访问令牌。

Twitter 应用程序密钥(为了隐私,我的密钥被隐藏了)

consumer_key <- 'XXXXXXXXXXXXXX'
consumer_secret <- 'XXXXXXXXXXXXXX'
access_token <- 'XXXXXXXXXXXXXX'
access_secret <- 'XXXXXXXXXXXXXX'

使用 R,复制上面的代码并将你的键粘贴到它们各自的变量中。(包括引号)

5.设置身份验证

使用函数 setup_twitter_oauth() 将您的键链接到 twitter 的 API。

setup_twitter_oauth(consumer_key, consumer_secret, access_token, access_secret)

运行上面的代码后,您会得到一个提示。您可以选择是否使用本地文件来缓存访问,但我通常不这样做。如果不想使用本地文件,请输入数字 2 并按 enter 键。

6.拉推文

既然我们已经完成了设置 API 的所有步骤,现在我们可以拉推了。下面我们来分解一下功能。

virus <- searchTwitter('#China + #Coronavirus', n = 1000, since = '2020-01-01', retryOnRateLimit = 1e3)virus_df = twListToDF(virus)

第一行代码使用了 searchTwitter 函数。我们传递尽可能多的与我们的搜索相关的#标签,在这个例子中,是#中国和#冠状病毒。

目前是 2020 年 2 月 4 日,此时, 冠状病毒 已经引起世界恐慌,因为它蔓延到中国以外的更多国家。

  • n 参数是我们想要获取的推文数量。
  • 因为— 是您想要推文的时间段
  • retryOnRateLimit —指示当速率受限时是否等待并重试。仅当期望回报(n)超过可用请求的剩余限制时,此参数才有意义

最后一行代码使用了 twListToDF 函数,该函数将推文保存到数据帧中。

所有推文的数据框架

查看所有的推文,我们可以看到,有一个独特的列可以帮助识别他们的推文活动。

7.后续步骤

现在你已经把你的推文保存在一个数据框中,最好开始分析和发现任何模式或趋势。一个很好的开始方式是将推文标记化,并从文字中提取见解。如果你有兴趣了解更多,请查看我的符号化教程。

通过引导获取您的数据

原文:https://towardsdatascience.com/pulling-your-data-up-by-the-bootstraps-3f9d2a904bec?source=collection_archive---------41-----------------------

什么是自举,我们为什么要使用它?

沙哈达特·拉赫曼在 Unsplash 上拍摄的照片

如果你使用任何大型数据集,你可能听说过 bootstrapping。如果你是一名新兴的统计学家或生物信息学家,这是你计算工具集的一部分。使用这个功能有什么意义?更重要的是,自举到底是什么?

布拉德利·埃夫隆在 1979 年首次发表了自举的观点。随着计算能力变得越来越便宜和可用,这种计算机密集型技术变得越来越流行和有用。事实上,研究人员已经引用了 bootstrapping 方法超过 2 万次。

当处理大型数据集时,我们的目标是对从中提取数据的总体进行推断。虽然我们可以计算平均值或中位数,但我们不知道这种估计的确定性。如果我们增加样本量,我们可以减少误差,接近总体参数。然而,如果我们正在进行 RNA 测序或收集大量数据,增加样本量是昂贵的,甚至是不可能的。Bootstrapping 是一种重采样方法,可以帮助我们确定误差和置信区间。无论你是在看股票市场数据、系统进化树还是基因转录本丰度,来自后来的自举的结果都会告诉你结论。

定义引导

自举是一种使用替换进行重采样的方法。我们将通过一个例子来解释这是如何工作的,以及这种方法的假设。

假设我们有一个数据集,显示篮球运动员在生日时露面的费用。但是,你很难联系到 8 个以上的玩家,所以你的数据集,本例中的 D,包含 8 个值。因为我们与各种不同的篮球运动员交谈,从冷板凳队员,以确保你的样本足够类似于整个群体的球员。

这就是我们的统计假设:我们的数据样本接近总体分布。

*D* = {100, 200, 200, 300, 500, 1000, 1000, 750}

这里我们样本的平均值是 506.25。如果我们对这个样本进行几次引导,我们将对这个数据集中的方差有一个更好的了解。引导包括替换重采样。我们重新采样的引导程序每个将有 8 个值,但是由于它们是用替换重新采样的,相同的值(即 100)可能会出现多次。这样,引导每次运行时都会生成不同的估计值。然而,有了足够的引导,我们可以生成数据中方差的近似值。请注意以下事项:

  1. 我们不会向数据集添加任何新点。
  2. 每个重新采样的 bootstrap 都包含与原始样本相同数量的值。
  3. 由于我们使用替换进行重采样,因此在整个引导过程中,对任何值进行重采样的概率都是相同的。每个值都被绘制为独立的事件。如果我们重新采样的第一个值是 200,这不会改变该引导中第二个值也是 200 的概率。
*D₁* = {100, 1000, 500, 300, 200, 200, 200, 100}
*D₂* = {300, 1000, 1000, 300, 500, 100, 200, 750}
*D₃* = {750, 300, 200, 200, 100, 300, 750, 1000}

D₁、D₂、D₃的平均值为 325,518.75,450。然后,我们可以使用这些值来生成标准误差、置信区间和其他感兴趣的度量。使用 Python、R 或其他语言,很容易生成 50、100 甚至 1000 个自举样本。了解样本的偏差、方差和分布有助于我们对样本总体做出更好的推断。它有助于你将样本的稳健性融入到其余的推理中。

为了这个例子,我们使用了一个小的数据集。一般来说,自举不适用于小数据集、有许多离群值的数据集或涉及相关数据度量的数据集。

如果你在可视化这个方法上仍然有困难,我已经在下面展示了在一个软糖数据集上的引导过程。

由西蒙·斯皮切克创作

使用 Bootstrap 进行生物信息学研究

例子 1:系统进化树

Bootstrapping 帮助我们确定系统发育树中特定分支的置信度。我们可能正在寻找蛋白质的氨基酸序列或基因的核苷酸序列。我们的原始样本可以快速重采样 1000 次,重建 1000 棵自举树。如果你的原始树显示一个特定的蛋白质或基因序列分支,你可以检查你的引导树,看看这个分支出现的频率。如果它出现超过 950 次,您可以相当确定您的数据是健壮的。如果它只出现 400 次左右,那么它可能是由异常值引起的。

实施例 2:估计基因转录丰度

Sleuth 软件使用 bootstrap 方法估计基因转录丰度。通过重新采样我们的下一代测序读数,我们可以计算出一个更可靠的转录丰度估计值。重新采样让我们了解了数据中的技术可变性。当估计特定基因或转录物在数据集中是否增加时,技术变异与生物变异一起使用。

自举的其他用途包括为集成机器学习进行聚合。基本上,我们的数据集被多次重采样。每个自举样本然后通过我们的分类器或机器学习模型运行。我们可以一起使用所有的输出来生成更准确的分类器。这可以防止我们根据有限的样本过度拟合数据。

参考文献

  1. 自助方法:对折刀法的另一种看法。安。统计学家。第 7 卷(1979 年),第 1 号,第 1 至 26 页。doi:10.1214/aos/1176344552。https://projecteuclid.org/euclid.aos/1176344552
  2. 埃夫隆,布拉德利,伊丽莎白哈洛兰和苏珊·霍尔曼。"种系发生树的引导置信水平."美国国家科学院学报93.23(1996):13429–13429。
  3. https://hbctraining . github . io/DGE _ workshop _ salmon/lessons/09 _ sleuth . html

常用 Viz 的用途—数据科学和分析

原文:https://towardsdatascience.com/purpose-of-frequently-used-viz-data-science-analytics-6b0ec8d2c2ad?source=collection_archive---------30-----------------------

在数据分析领域工作了 3 年多,我可以说数据可视化在提供有见地的建议方面发挥了巨大的作用。

无论是参加面试还是招聘分析师,我总是希望在准备面试时能有快速笔记。我走上前,提出了一些我多年来工作过的地块的集体信息。

以下是数据分析和数据科学领域中一些最广泛使用的图。这些只是对它们何时被广泛使用的快速注释。

散点图:

  • 双变量分析
  • 两个变量之间的趋势和模式
  • 理解两个变量之间的关系

结对剧情:

  • 多个散点图显示两个以上变量之间的关系
  • 稍微调整一下,可以帮助我们了解变量之间的回归程度

热图:

  • 基于该措施的彩色视觉效果
  • 配对图—了解正相关和负相关
  • 混淆矩阵,用于根据 TP、TN 指标确定模型执行的好坏

条形图:

  • 双变量和多变量分析
  • 比较分类变量的数字、频率
  • 例如:活动前与活动后的表现

计数图:

  • 从组中找到最常用的类别
  • 单变量分析(年龄或性别频率)

堆积条形图:

  • 对整体的各个部分进行分类和比较
  • 例子:在男性和女性群体中,有多少人幸存?

折线图:

  • 分析一段时间或特定变量的趋势和模式
  • 例如:时间序列分析图

方框图:

  • 数据准备的许多重要步骤之一
  • 找出数据中的异常值
  • 为我们提供四分位数范围(IQR)

直方图:

  • 允许我们分析数据分布
  • 找出偏斜度——正偏斜度还是负偏斜度

仪表图:

  • 主要用作目的/目标指标
  • 提供关于目标是否实现或指标绩效如何的见解

饼图:

  • 变量占总数的比例
  • 饼图的视觉变体是圆环图

左图是“甜甜圈图”,右图是“饼图”

漏斗图:

  • 了解一段时间内的数据流
  • 最广泛用于分析活动和网站绩效

带指标的表格图:

  • 简单显示带有 KPI(关键绩效指标)指标的数据
  • 帮助我们显示绩效比率(例如,下图表示每周运动-开盘价)

树状图:

  • 数据的层次结构,由具有父子层次结构的嵌套矩形组成
  • 根据颜色和大小提供深刻的分析

奖励:

热图和树状图的区别:

在热图中,一个度量可以分配给颜色,另一个度量可以分配给大小。布局类似于值被编码为颜色的表格

在树形图中,使用 1 个或多个维度&最多 2 个度量来创建。节点越大,值就越大。这些嵌套矩形的大小从图表的左上角到右下角,最大的位于左上角,最小的位于右下角。

将显卡视觉效果提升到 Power BI 的新水平

原文:https://towardsdatascience.com/push-card-visuals-to-a-new-level-in-power-bi-174db7deaa7?source=collection_archive---------18-----------------------

为传统的 Power BI 视觉效果注入新的活力,并了解如何通过简单的变通方法实现扩展/折叠功能

照片由 Nati Torjman 在 Pexels 上拍摄

我喜欢 Power BI,因为它提供了一整套可视化和开箱即用的解决方案来将几乎每一个业务请求转换成一个闪亮的报告。不要误解我的意思,Power BI 不仅仅是一个数据可视化工具,它可以作为一个全面的 ETL 解决方案在许多场景中使用。

然而,当涉及到特定的用户请求时,Power BI 当然有一些限制。在这些情况下,为了实现期望的功能,一些变通方法和调整是必要的。

展开/折叠功能

其中之一是扩展/折叠矩阵之外的视觉功能。即使在 Matrix visual 中,在 2019 年 11 月更新之前,也无法使用“+”符号进行扩展。

对于来自 SSRS 世界的我们来说,这是如此的奇怪和出乎意料。好了,矩阵已经包括在内了,但是如果我们想把同样的功能应用到其他视觉效果上,比如卡片视觉效果。

请继续关注,我将向您展示一个解决方法,这样您就可以实现这个目标。像往常一样,我将使用 Contoso 示例数据库进行演示。

方案

假设我有一个报表页面,在中间显示一个堆积柱形图,在右上角显示两个卡片图像,显示销售数量和销售金额:

现在,假设我想让我的用户有可能更深入地了解这些数字的细节。使用工具提示页面,我在这篇文章中描述过,是一个简单快捷的解决方案。但是,工具提示是静态的,它们只显示底层数据,没有提供与之交互的机会。

因此,我决定用书签来模拟展开/折叠功能。书签是 Power BI 中非常有用的技术,我经常使用它们。

简而言之,书签捕获报告页面的当前状态(所有 可见 视觉效果都在上面),您可以通过将 Action 属性设置为 bookmark,使用按钮/图像在不同的书签之间导航。

关于书签的更广泛的解释超出了本文的范围,所以请记住,书签是一种非常有用的技术,可以定制您的报告并改善整体用户体验。

步骤 1 —插入图像并创建书签

我们需要做的第一件事是给我们的用户一个提示,告诉他们可以用卡片视觉效果做什么。我已经为“+”和“-”符号导入了两个透明图标,我相信这足够直观了。

将两个图标一个放在另一个上面,如下图所示:

对销售数量卡片视觉效果做同样的操作,我们也将在卡片中间放另一对。该图标将使用户能够同时展开/折叠两张卡片,而小图标将处理特定的卡片。

现在,真正的魔法需要被创造出来。在“视图”选项卡下,启用书签和选择窗格。我们将需要为每一个单独的场景两个书签:展开/折叠销售数量卡只;仅展开/折叠销售金额卡片;展开/折叠两张卡片。

这是我创建的书签窗格的屏幕截图:

步骤 2-设置书签内的可见性

现在,我们需要定义每个书签的外观。这意味着,当我打开报告页面时,只有“+”图标应该是可见的(这意味着我需要隐藏“-”图标)。

之后,您需要根据用户的选择设置所有视觉效果的显示/隐藏属性。说明每一个步骤需要花费大量的时间和图片,但是让我们只显示销售数量(销售金额的逻辑保持不变)。

打开“操作”字段,选择“类型”下的“书签”,然后选择“扩展书签数量”。这样,我们“告诉”这个图标将我们导航到一个专门创建的书签,该书签显示了我们需要显示的报告页面的捕获状态。

一旦您按住 CTRL 键并单击“+”号,您将看到报告页面发生了变化:

您首先会注意到的是一个新的折线图,它显示了每月的销售数量。此外,符号“+”消失了,取而代之的是“-”图标,提示用户一旦决定折叠这个扩展视图,就可以点击它。

第三步——摆弄书签

现在,如果用户点击销售金额“+”图标,会发生以下情况:

视觉已经改变,以显示每月的销售额数字!此外,同步“+”和“-”图标以跟随用户选择。

最后,如果用户想要通过一次点击来扩展两个卡片的视觉效果,他可以通过点击卡片之间的大“+”号来实现:

很酷吧,哈?

最后,这是最终的解决方案:

结论

正如我之前提到的,你可以通过工具提示页面给用户更多的洞察力,这也是一个合理的解决方案,但是它们是静态的。通过对书签的巧妙使用,你可以设置不同类型的额外视觉效果来满足用户的要求。此外,这些图像可以像常规图像一样用于交叉过滤或向下钻取,这是这种技术的最大优势。

成为会员,阅读 Medium 上的每一个故事!

订阅这里获取更多有见地的数据文章!

用 Pytorch 中的数值变量转换提高机器学习模型的精度

原文:https://towardsdatascience.com/push-the-accuracy-of-machine-learning-model-with-numerical-variable-transformation-in-pytorch-9f56c56203fd?source=collection_archive---------38-----------------------

这个故事提供了在 Pytorch 中实现转换技术和提高代码准确性的完整指南

概观📙

任何机器学习的实践者都陷入了提高模型预测性能的困境。他们主要着眼于使用更强大的 SOTA 模型和更长的训练时间进行权衡。然而,在机器学习中,时间是宝贵的,模型的性能可以通过简单的一步,即数据再处理,以更快的速度达到更好的结果。这一步往往被遗忘或低估。

数据预处理的一些例子包括用插补技术【1】填充缺失值编码【2】转换或编码分类变量,通过标准化规格化【3】转换为数值变量。因此,本文旨在为转换数值变量提供强大的方法论,以帮助机器学习模型捕捉数据中有意义的信息。

转化技术📄

的确,当变量的分布是正态分布时,许多机器学习算法(如线性回归和逻辑回归)会表现得更好,换句话说,对于非标准概率分布的变量,性能会下降。

钟形的正态分布是一个连续随机变量的概率函数,它出现在现实生活中的各种场合:人的身高、血压或考试成绩。其他非线性算法可能没有这一事实,但当数值变量具有高斯分布时,通常表现更好。

本文中介绍的各种有用的技术可以用来将变量转换成高斯分布,或者更可能是高斯分布。这些方法是分位数变换幂变换离散化变换。

  • 分位数变换【4】是一种非线性变换,它用同一等级或分位数的所有其他特征值的平均值替换某个特征值。这听起来很奇怪,但实际上非常简单。如下图所示,首先,数据按值排序。然后计算排序数据集所有列的平均值,并用平均值替换原始值。最后,将数据集返回到原始顺序,但保留规范化的值。

分位数标准化示意图(图片由作者提供)

  • 幂变换【5】属于参数单调变换家族,用于稳定方差和最小化与异方差(非恒定方差)相关的偏度问题,或其他需要正态性的情况。另一方面,当回归线周围的方差对于预测变量的所有值都不相同时,就会出现异方差。这种自动功率变换有两种流行的方法: Box-Cox 变换Yeo-Johnson 变换。λ是一个超参数,用于控制幂变换的性质,也是将变量变换为高斯概率分布的最佳方法。以下是 lambda 的一些常见值:

Lambda(图片由作者提供)

  • 离散化转换【6】过程将定量
    数据转换为定性数据,也就是说,从数值属性
    转换为具有有限数量
    间隔的离散或名义属性,从而获得连续域的非重叠划分。对于用户和专家来说,离散的特性更容易理解、使用和解释。在实践中,离散化可以被视为一种数据简化方法,因为它将数据从大量的
    数值映射到一个大大减少的离散值子集,从而使学习更加准确和快速。离散化技术包括许多方法,如
    宁滨、直方图、聚类、决策树、相关性等..
    注意:在线性不可分数据集上,特征离散化提高了线性分类器模型的性能。然而,在线性可分的数据集上,特征离散化会降低线性分类器模型的性能(更多信息可以查看此处****

波士顿住房数据集实验

在本教程中,我将使用波士顿住房数据集,其中包含波士顿各种房屋的信息。有 506 个样本和 13 个特征变量。目标是使用给定的特征来预测房子的价格。首先是导入和加载数据

**import pandas as pd DATASET_URL = "https://raw.githubusercontent.com/selva86/datasets/master/BostonHousing.csv"# read data
DATA_FILENAME = "Boston_Housing.csv"
TARGET_COLUMN = 'medv' 
dataframe = pd.read_csv(DATASET_URL)
dataframe.head()**

数据集信息

检查输入要素的分布

**dataframe.drop('medv', axis=1).hist();**

输入要素的分布呈偏态和非正态分布

基线模型

接下来,我将创建一个简单的线性模型来预测房价。

然后,我将输入和输出数据加载到 PyTorch 数据集并训练模型。

训练 10 个周期后,结果显示如下。

分位数变换

接下来,我将使用分位数转换来使数字变量更加高斯化。我可以使用 sklearn 中的 QuantileTransformer 类应用分位数转换,并将“ output_distribution ”参数设置为“ normal ”。我还必须将“ n_quantiles ”参数设置为小于训练数据集中观察值的值,在本例中为 100。

**from sklearn.preprocessing import QuantileTransformer transformer = QuantileTransformer(n_quantiles=100, output_distribution='normal')
inputs = transformer.fit_transform(inputs_raw)**

通过分位数转换将输入变量转换为正态概率分布后,输入分布如下图所示。

通过分位数变换变换后输入特征的分布

然后,我用上面同样的线性模型来预测波士顿的房价。

注意:在用变换技术变换输入数据后,我可以设置更高的学习率(在这种情况下学习率= 1e-2)以加速收敛到全局最小值。对于原始数据,如果学习率设置得太高,我们将面临不收敛误差。

训练 10 个周期后,结果显示如下。

电力转换

在这个演示中,我使用了功率变换的 Box-Cox 变换技术。

注意: Box-Cox 变换假设它所应用的输入变量值严格为正**。这意味着不能使用 0 和负值(在这种情况下,我可以使用 Yeo-Johnson 变换)。在输入数据集中,我有负数据,因此,我必须在馈入 Box-Cox 变换之前使用 MixMaxScaler 变换**

from sklearn.preprocessing import PowerTransformer, MinMaxScaler transformer = PowerTransformer(method='box-cox')
pipeline = Pipeline(steps=[('s', scaler),('t', transformer)])
scaler = MinMaxScaler(feature_range=(1, 2)) 
inputs = pipeline.fit_transform(inputs_raw)

现在,输入分布如下图所示。

通过功率变换变换后的输入特性分布

同样,我将使用上面 10 个时期的相同线性模型

离散化变换

最后但同样重要的是,我将应用强大的转换技术,离散化转换。统一的离散化变换将保持每个输入变量的概率分布,但会使其离散于指定数量的有序组或标签。我可以使用 KBinsDiscretizer 类应用统一离散化转换,并将“策略”参数设置为“统一”我还将通过“ n_bins ”参数设置的箱数设置为 10。

from sklearn.preprocessing import KBinsDiscretizer transformer = KBinsDiscretizer(n_bins=10, encode='ordinal', strategy='uniform')
inputs = transformer.fit_transform(inputs_raw)

输入数据的分布会像这样变化

通过离散化变换变换后的输入特征分布

最后,我用 10 个时期运行上面相同的线性模型

最终想法📋

本文想展示一些将数字输入数据转换成类高斯分布的技巧。但是,如果输入数据已经近似于正态分布,这种技术将不会提高模型的性能。这个实验只使用默认的 hyper 参数,你可以自由地改变并应用到你的数据中以获得最优的结果。要进一步阅读,你可以参考下面的参考部分。最后,我想总结一下本文中所有实验的结果。

和平!

作者图片

参考

[1] Stef vanBuuren,缺失数据的弹性插补,第二版,CRC 出版社,2018。

[2]Suresh Kumar Mukhiya Usman Ahmed,使用 Python 进行探索性数据分析:执行 EDA 技术以理解、总结和调查您的数据,Packt Publishing Ltd,2020 年。

[3]彭春燕,利用 SAS 进行数据分析,第七章|数据转换,2009。

[4] Amaratunga,d .,Cabrera,j .对来自病毒 DNA 微芯片的数据的分析。美国统计学家协会,2001 年,第 96 期。

[5] S. Gluzman,V.I. Yukalov,外推问题中的自相似幂变换,统计力学,2006。

[6]刘欢、法尔哈德·侯赛因、丘里姆·谭和马诺兰詹·达什,《离散化:一种使能技术》,2002 年。

[7]萨尔瓦多·加西亚;朱利安·卢恩戈;何塞·安东尼奥·塞斯;维多利亚·洛佩斯;弗朗西斯科·埃雷拉,离散化技术调查:监督学习中的分类和实证分析,2013 年。

用熊猫挑战极限

原文:https://towardsdatascience.com/push-the-limits-with-pandas-3132675c6ff2?source=collection_archive---------42-----------------------

熊猫的能力超乎你的想象。

Pandas 是一个非常强大和通用的 Python 数据分析库,可以加速项目的预处理步骤。Pandas 不仅用于预处理,还用于探索数据。你可以也应该挑战极限,看看熊猫有什么能力。在这篇文章中,我将重点讲述如何过滤数据帧,但更重要的是,我将努力传达这样的信息:

你在数据分析中使用熊猫越多,它就越有用。

Photo by 贝莉儿 DANIST on Unsplash

一如既往,我们从进口熊猫开始:

import pandas as pd
import numpy as np

我将使用 Kaggle 上的电信客户流失数据集的一部分。

df.head()

熊猫的好处是有多种方法来完成一项任务。Pandas 核心数据结构 DataFrame 由带标签的行和列组成。Pandas 在行和列上可以做什么方面非常灵活,这使得它非常容易处理存储在 DataFrame: data 中的内容。

尝试挑战极限,你会惊讶于熊猫的能力。

在这一节中,我将写下您在处理数据时可能会遇到的一些问题。然后用熊猫展示一个寻找答案的方法。请记住,几乎总是有其他方法来做同样的事情。所以请随意用不同的方式寻找答案。我认为这将是一个很好的练习。

注意:我还将把代码放在文本中,以防你想容易地修改或尝试不同的东西。

  • 成为客户不到 10 个月的客户的互联网服务类型分布是什么?
df[df.tenure < 10]['InternetService'].value_counts()

任期变量显示客户持有合同的时间,以月为单位。

  • 使用电子支票付款的客户每月平均费用是多少?
df[df.PaymentMethod == 'Electronic check']['MonthlyCharges'].mean()

  • 有多少客户使用电子支票或邮寄支票付款,这些客户的平均月费用是多少?
method = ['Electronic check', 'Mailed check']
df[df.PaymentMethod.isin(method)].groupby('PaymentMethod').agg(['count','mean'])['MonthlyCharges']

  • 入住不到三个月,使用 DSL 上网服务的客户流失率是多少?

注意:我们需要首先将 Churn 列中的值转换成数字值,以便能够计算聚合。“是”将转换为 1,“否”将转换为 0。然后我们可以应用聚合函数。

churn_numeric = {'Yes':1, 'No':0}
df.Churn.replace(churn_numeric, inplace=True)df[(df.tenure < 3) & (df.InternetService == 'DSL')].Churn.mean()

  • 7 个月前 DSL 合同出现问题,持续了三个月。我想看看这个问题对流失率的影响。在此期间,未签订合同的客户流失率是多少?
df[(~df.tenure.isin([7,6,5])) & (df.InternetService == 'DSL')]['Churn'].mean()

注意:波浪号(~)运算符用作 NOT。

  • 我想根据客户成为客户的时间长短将他们分为 3 类,并找出每一组的平均流失率。
df['tenure_cat']= pd.qcut(df.tenure, 3, labels=['short','medium','long'])df[['tenure_cat','Churn']].groupby('tenure_cat').mean()

  • 我想大致了解一下流失率是如何根据性别、合同类型和是否是高管而变化的。
df.pivot_table(index=['gender','SeniorCitizen'], columns='Contract', values='Churn', aggfunc='mean', margins=True)

  • 在该任期月份内,根据客户数量,属于前三名任期值的客户的互联网服务分布情况如何?
df[df.tenure.isin(df.tenure.value_counts().index[:3])]['InternetService'].value_counts()ORdf[df.tenure.isin(df.tenure.value_counts().nlargest(3).index)]['InternetService'].value_counts()

这只是你能为熊猫做的一小部分。你用它做得越多,你就会发现越多有用和实用的方法。我建议用不同的方法处理问题,永远不要给自己设限。

熟能生巧。

当你努力寻找问题的解决方案时,你学到的东西几乎总是比手头问题的解决方案多。您将逐步提高自己的技能,以建立一个强大而高效的数据分析流程。

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

利用部分卷积推进深度图像修复的极限

原文:https://towardsdatascience.com/pushing-the-limits-of-deep-image-inpainting-using-partial-convolutions-ed5520775ab4?source=collection_archive---------11-----------------------

基于部分卷积的不规则孔洞图像修复

图一。使用部分卷积的一些修复结果。图片来自刘桂林等人的论文 [1]

你好。今天我想讲一个好的深度图像修复纸,它打破了以往修复工作的一些局限。简而言之,以前的大多数论文都假设缺失区域是规则的(即一个中心缺失矩形孔或多个小矩形孔),本文提出了一个部分卷积(PConv) 层来处理不规则孔。图 1 显示了使用建议的 PConv 的一些修复结果。他们好吗?大家一起来把握 PConv 的主旨吧!

动机

首先,先前的深度图像修复方法将丢失像素和有效像素视为相同的,在这种意义上,它们将固定像素值(归一化之前/之后为 255 或 1)填充到图像中的所有丢失像素,并将标准卷积应用到输入图像以完成修复任务。这里有两个问题。 i) 将缺失像素的像素值固定为预定义值是否合适? ii) 不管像素是否有效,是否适合对输入图像进行卷积?因此,仅对有效像素执行操作可能是一个好的选择。

图二。使用规则掩蔽图像和提出的部分 Conv 训练的先前深度修复方法的视觉比较。图片来自刘桂林等人的论文 [1]

其次,现有方法假设缺失区域是规则的/矩形的。其中一些采用本地鉴别器来区分生成内容和真实内容。对于固定大小的中心缺失孔的情况,他们将填充的中心孔输入到局部鉴别器以增强局部纹理细节。但是不规则的缺失区域呢?有没有可能在不使用鉴别器的情况下获得精细的局部细节?如果您尝试使用现有的方法来处理不规则的蒙版图像,您会发现修复结果并不令人满意,如图 2 所示。对于实用的修复方法,它们应该能够处理不规则的掩蔽图像。

介绍

与我以前的帖子类似,我假设读者对深度图像修复有基本的了解,如网络架构、损失函数(即 L1 和对抗性损失),以及相关术语(即有效像素、缺失像素等)。).如果你需要或者想要,请快速回忆一下我以前的帖子。在这一节中,我将简要介绍我认为不太重要的内容,因此我们可以有更多的时间来深入本文最重要的思想,部分卷积。

本文的作者采用了一个具有跳跃连接的类似于 U-Net 的网络,其中所有标准卷积层都被提议的部分卷积层所取代。如果你对他们的网络架构感兴趣,你可以参考的论文,他们提供了他们模型的详细表格。

有趣的是,在这项工作中没有使用鉴别器。除了标准的 L1 损失和全变差损失(TV 损失)之外,作者采用了两种高级特征损失来完成具有精细纹理的掩蔽图像。后面我会详细介绍这两个损耗。

解决方案(聚焦)

正如在 Motivation 中提到的,关键思想是在卷积过程中从有效像素中分离出丢失的像素,使得卷积的结果只取决于有效像素。这就是所提出的卷积被命名为部分卷积的原因。基于可以自动更新的二进制掩码图像,对输入执行部分卷积。

方法

部分卷积层

让我们定义 Wb 为卷积滤波器的权重和偏差。 X 表示被卷积的像素值(或特征激活值), M 是相应的二进制掩码,表示每个像素/特征值的有效性(0 表示缺失像素,1 表示有效像素)。计算建议的部分卷积,

其中,⦿表示逐元素乘法,而 1 是一个与 M 形状相同的 1 的矩阵。从这个等式可以看出,部分卷积的结果只取决于有效的输入值(如 X ⦿ M )。sum(1)/sum(M)是一个比例因子,用于调整结果,因为每个卷积的有效输入值的数量是变化的。

在每个部分卷积层后更新二进制掩码。所提出的更新二进制掩码的规则非常简单。如果当前卷积的结果以至少一个有效输入值为条件,则相应的位置将被视为对下一个部分卷积层有效。

正如您在上面看到的,更新规则很容易理解。

图 3。提议的部分卷积的图解说明。作者图片

图 3 给出了一个简单的例子来说明所提出的部分卷积。我们考虑一个简单的 5×5 输入及其相应的 5×5 二进制掩模图像(1 代表有效像素,0 代表孔洞像素)和一个具有固定权重的 3×3 W 。假设我们希望保持与输入大小 5×5 相同的输出大小,因此我们在进行卷积之前执行零填充。我们先考虑左上角(橙色有界)。该卷积的 XM 在图中清楚示出,有效输入值的数量为 3。因此,这个位置的输出是-9+ b 。此外,更新后的二进制掩码中相应位置的值为 1,因为有 3 个有效输入值。

考虑中间(紫色有界)的框,这一次,如您所见,对于这个卷积没有有效的输入值,所以结果是 0+ b 并且更新的掩码值也是 0。右下角(蓝色边框)是另一个卷积示例,用于显示比例因子的作用。通过缩放因子,网络可以区分由 3 个有效输入值计算的-3 和由 5 个有效输入值计算的-3。

为了方便读者,图 3 的右上角显示了部分卷积层之后的更新二进制掩码。可以看到更新后的二进制掩码中的零更少了。当我们执行越来越多的部分卷积时,二进制掩码将最终更新为全 1。这意味着我们可以控制信息在网络内部传递,而不管缺失区域的大小和形状。

损失函数

总的来说,在它们的最终损失函数中有 4 个损失项,即 L1 损失、感知损失、风格损失和电视损失。

L1 损失(每像素损失)

该损失是为了确保逐像素重建精度

其中 I _ outI _ gt 分别是网络和地面真实的输出。 M 是二进制掩码,0 代表孔洞,1 代表有效像素。NIgt是一幅图像中像素值的总数,等于C×H×WC 是通道大小(RGB 图像为 3), HW 是图像的高度和宽度 I 可以看到 L _ L _ 有效分别是孔像素和有效像素的 L1 损失。

感知损失(VGG 损失)

感知损失是由 Gatys 等人[2]提出的,我们之前已经介绍过这种损失。简单地说,我们希望填充图像和地面真实图像具有由像 VGG-16 这样的预训练网络计算的相似特征表示。具体来说,我们将地面真实图像和填充图像馈送给预训练的 VGG-16 来提取特征。然后,我们计算所有层或几层的特征值之间的 L1 距离。

上式中, I _ compI _ out 相同,只是有效像素直接被地面真实像素代替。ψ^Ip是预训练的 VGG-16 在给定输入 I 的情况下计算出的第 p 层的特征图。nψ**I**_*p*是*ψ*I_p中元素的个数。根据 Gatys 等人[2],当完整的图像在语义上接近其基础真实图像时,这种感知是小的。也许,这是因为更深的层(更高的级别)提供了图像的更多语义信息,并且相似的高级特征表示表示完成的更好的语义正确性。供读者参考,VGG-16 1、 2、 3 层用于计算感知损失。

风格丧失

除了感知损失,作者还采用了如上所示的风格损失。你可以看到,风格损失也是使用预先训练的 VGG-16 给出的特征图来计算的。这一次,我们首先计算每个特征图的自相关性,它在[2]中被称为 Gram 矩阵。根据[2], Gram 矩阵包含图像的风格信息,如纹理和颜色。这也是这种损失被命名为风格损失的原因。因此,我们计算完整图像和地面真实图像的格拉姆矩阵之间的 L1 距离。注意ψ^Ip的大小为(hp×wp×cp,其克矩阵的形状为c_p×*c K _ p 是一个归一化因子,它取决于第 p 层特征图的空间大小。*

总变异损失

最终损失函数中的最后一项损失是电视损失。在我之前的帖子中,我们已经讨论过这种损失。简单来说,采用这个损失是为了保证完成图像的平滑度。这也是很多图像处理任务中常见的损失。

其中NIcompI _ comp 中像素值的总数。

最终损失

这是训练建议模型的最终损失函数。用于控制每个损失项的重要性的超参数是基于对 100 幅验证图像的实验来设置的。

消融研究

图 4。使用不同损失项的修复结果。(a)输入图像(b)没有风格损失的结果(c)使用完全损失的结果(d)背景事实(e)使用小风格损失权重的输入图像(f)结果(g)使用完全损失的结果(h)背景事实(I)没有感知损失的输入图像(j)结果(k)使用完全损失的结果(l)背景事实。请放大以便看得更清楚。图片来自刘桂林等人的论文【1】

作者做了实验来显示不同损失项的影响。结果如上面的图 4 所示。首先,图 4(b)展示了不使用风格损失的修复结果。他们发现在他们的模型中使用风格损失是必要的,以生成精细的局部纹理。然而,风格损失的超参数必须仔细选择。正如您在图 4(f)中看到的,与使用完全损失的结果(图 4(g))相比,样式损失的小权重会导致一些明显的伪像。除了风格上的失落,感性上的失落也很重要。他们还发现知觉损失的雇佣可以减少网格状的人工制品。请参见图 4(j)和(k)了解使用感知损失的效果。

事实上,的高级功能损失的使用还没有被充分研究过。我们不能 100%说感知损失或风格损失一定对图像修复有用。因此,我们必须自己做实验来检查不同损失项对于我们期望的应用的有效性。

实验

图 5。掩模图像的一些例子。1、3、5 具有边界约束,而 2、4、6 没有边界约束。图片来自刘桂林等人的论文

在他们的实验中,所有的掩模、训练和测试图像的尺寸都是 512×512。作者将测试图像分为两组, i) 边缘附近有孔的掩模。 ii) 靠近边框无孔口罩。具有距离边界至少 50 个像素的所有孔洞的图像被分类到第二组。图 5 显示了这两组掩码的一些示例。此外,作者根据孔与图像的面积比生成了 6 种类型的掩模:(0.01,0.1),(0.1,0.2),(0.2,0.3),(0.3,0.4),(0.4,0.5),和(0.5,0.6)。这意味着最大的蒙版将遮蔽 60%的原始图像内容。

训练数据。与之前的工作类似,作者在 3 个公开可用的数据集上评估了他们的模型,即 ImageNet、Places2 和 CelebA-HQ 数据集。

图 6。ImageNet 上不同方法的视觉比较。(a)输入图像(b) PatchMatch (c) GLCIC (d)上下文注意(e) PConv (f)地面真实。图片来自刘桂林等人的论文

图 7。不同方法在场所上的视觉比较 2。(a)输入图像(b) PatchMatch (c) GLCIC (d)上下文注意(e) PConv (f)地面真实。图片来自刘桂林等人的论文

图 6 和图 7 分别显示了 ImageNet 和 Places2 上不同方法的可视化比较。PatchMatch 是最先进的传统方法。 GLCIC 和上下文注意是我们之前介绍过的两种最先进的深度学习方法。如你所见,GLCIC (c)和上下文注意(d)不能提供具有良好视觉质量的修复结果。这可能是因为这两种先前的深度学习方法是针对规则屏蔽图像而不是不规则屏蔽图像训练的。如果您感兴趣,请放大以更好地查看修复结果。

图 8。CelebA-HQ 上不同方法的视觉比较。(a)输入图像(b)上下文注意(c) PConv (d)背景事实。图片来自刘桂林等人的论文 [1]

图 8 显示了 CelebA-HQ 数据集上的修复结果。您可以放大以更好地查看结果。

表 1。各种方法的定量比较。6 列代表 6 种不同的掩模比率。n 表示没有边界(即孔可以靠近边界),B 表示有边界(即没有孔靠近边界)。刘桂林等人的数据来自他们的论文

表 1 列出了几个客观的评估指标,供读者参考。显然,所提出的 PConv 在几乎所有情况下都提供了最佳数字。注意,IScore 是用作视觉质量估计的初始分数,并且越低,估计的视觉质量越好。

除了定性和定量的比较,作者还进行了人类主观研究,以评估不同方法的视觉质量。感兴趣的读者可以参考论文进行研究。

限制

图 9。当缺失孔洞越来越大时,通过 PConv 进行修复。图片来自刘桂林等人的论文 [1]

图 10。一些失败的案例,尤其是当场景非常复杂的时候。图片来自刘桂林等人的论文【1】

在文章的最后,作者还指出了现有深度图像修复方法的一些局限性。首先,很难完成如图 9 右侧所示的大面积缺失的图像。第二,当图像包含复杂的结构时,也很难完成如图 10 所示的具有良好视觉质量的图像。目前还没有一种综合的方法来处理超大尺寸的复杂图像。因此,你可以尝试提出一个好的解决方案来解决这个极端的图像修复问题。😃

结论

显然,部分卷积是本文的主要思想。希望我这个简单的例子能给大家解释清楚,部分卷积是怎么进行的,每一个部分卷积层之后,一个二值掩码是怎么更新的。通过使用部分卷积,卷积的结果将仅取决于有效像素,因此我们可以控制网络内部的信息传递,这对于图像修补任务可能是有用的(至少作者提供了部分卷积在他们的情况下是有用的证据)。除了图像修复,作者还试图将部分卷积扩展到超分辨率任务,因为它与图像修复有相似性。强烈推荐感兴趣的读者参考他们的论文。

外卖食品

毫无疑问,我希望你能明白什么是部分卷积。从本文开始,后来的深度图像修复方法可以处理规则和不规则掩模。再加上我之前跟图像修复相关的帖子,也希望你能对图像修复这个领域有更好的了解。你应该知道一些常见的技术和图像修复的挑战。例如,膨胀卷积、上下文注意层等。当图像中的孔太大并且图像具有复杂的结构时,填充图像也是困难的。

下一步是什么?

下一次,我们将看另一篇论文,它利用额外的信息来帮助填充蒙版图像。希望你喜欢!让我们一起学习吧!😃

参考

[1]刘桂林、菲特瑟姆·a·瑞达、凯文·j·施、廷-王春、安德鲁·陶和布赖恩·卡坦扎罗,《利用部分卷积对不规则孔洞进行图像修复》、 Proc .2018 年欧洲计算机视觉会议 ( ECCV )。

[2] Leon A. Gatys,Alexander S. Ecker,and Matthias Bethge,《艺术风格的一种神经算法》, arXiv 预印本 arXiv:1508.06576 ,2015。

感谢您阅读我的帖子!如果您有任何问题,请随时给我发电子邮件或在这里留言。欢迎任何建议。再次非常感谢,希望下次再见!😃

把你的数据分析放在一个 R 包里——即使你不发表它

原文:https://towardsdatascience.com/put-your-data-analysis-in-an-r-package-even-if-you-dont-publish-it-64f2bb8fd791?source=collection_archive---------14-----------------------

如何利用 R 的软件包开发环境来组织、记录和测试您的工作

一个数据分析项目由许多不同的文件组成:原始数据、脚本、降价报告和闪亮的应用程序。我们需要一个合理的项目文件夹结构来保持有序。为什么不利用 R 已经建立的包开发工作流程呢?

在 R 包中进行分析有四个好处:

  1. r 包提供了一个标准化的文件夹结构来组织你的文件
  2. r 包提供功能给文档的数据和功能
  3. r 包提供了一个框架来测试你的代码
  4. 将精力放在第 1-3 点可以让你重用共享你的代码

在本文中,我们将一步一步地在一个 R 包中完成一个数据分析例子。我们将看到这些好处几乎不需要任何开销。

对于数据分析示例,我们将:

  1. 下载和保存数据文件
  2. 编写一个脚本和一个 R 函数来处理数据
  3. 创建一个最小的探索性数据分析报告
  4. 用 Shiny 开发一个最小交互 R flexdashboard

最终结果可以在 GitHub 上找到。

要求

我假设你用 RStudio。建议有 R 包开发经验,但不是必需的。我们需要以下 R 包:

  • r 包开发: devtools,usethis,roxygen2
  • r 代码测试: assertive,testthat
  • 数据分析:gg plot 2,dplyr
  • R Markdown 和闪亮:针织机、rmarkdown、flexdashboard、闪亮**

1.创建 R 包

在 RStudio 中,导航到计算机上要创建包的文件夹。以下命令将打开一个新的 RStudio 会话,并创建一个名为“WineReviews”的准系统包。

*devtools::create("WineReviews")*

请注意附加选项卡构建是如何变得可用的。

R 包开发的附加工具

如果您在 RStudio 中配置了版本控制,导航至工具、版本控制、项目设置,并从下拉菜单中选择您的版本控制软件。我们将选择 Git,它用一个初始化一个本地 Git 存储库。gitignore 文件。

为此项目启用 Git

我们将使用 R 包 roxygen2 为我们的函数和数据自动生成文档。导航到工具、项目选项、构建工具,勾选“用 Roxygen 生成文档”前的复选框。我们将使用以下配置:

配置 Roxgen

描述文件中,我们写入项目的基本信息:

*Package: WineReviews
Title: Your data analysis project belongs in an R package
Version: 0.1.0
Authors@R:  person("Denis", "Gontcharov", role = c("aut", "cre"), 
                  email = "[gontcharovd@gmail.com](mailto:gontcharovd@gmail.com)")
Description: Demonstrates how to leverage the R package workflow to organize a data science project.
License: CC0
Encoding: UTF-8
LazyData: true*

我们最初的包结构如下所示:

***.** ├── .gitignore
├── .Rbuildignore
├── .Rhistory
├── DESCRIPTION
├── NAMESPACE
├── **R**
└── WineReviews.Rproj*

让我们检查一下我们的包构建,看看是否一切正常。我们将定期这样做,以确保我们整个工作项目的完整性。

*devtools::check()*

我们的初始包结构通过了检查

2.使用数据

保存和访问原始数据

在本例中,我们使用了来自 Kaggle 上葡萄酒评论数据集的两个 csv 文件。我们创建了一个文件夹 inst/ ,其中包含一个子文件夹 extdata/ ,我们在其中保存了两个 csv 文件。(包构建时, inst/ 的子文件夹是安装的。)

***.** ├── .gitignore
├── .Rbuildignore
├── .Rhistory
├── DESCRIPTION
├── **inst**
│   └── **extdata**
│       ├── winemag-data-130k-v2.csv
│       └── winemag-data_first150k.csv
├── NAMESPACE
├── **R**
└── WineReviews.Rproj*

为了使这些文件可用,我们必须清理并重建这个包。这将在您的计算机上安装 R 包。

清理并重建以访问 inst/文件夹中的文件

为了在 inst/ 中检索文件的路径,我们使用system.file()如下:

*system.file(
  "extdata",
  "winemag-data-130k-v2.csv",
  package = "WineReviews"
)*

操纵数据

我们现在将把这些原始数据处理成有用的形式。葡萄酒评论分为两个 csv 文件。假设我们要把这两个文件合并成一个数据框,里面有四个变量:“国家”、“积分”、“价格”、“酒厂”。让我们称这个数据框架为“葡萄酒 _ 数据”

下面的代码用脚本 wine_data 创建了 data_raw/ 文件夹。R

*usethis::use_data_raw(name = "wine_data")*

下面的代码创建了我们想要的数据框。我们把它加到 wine_data 里吧。R 脚本并运行它。

*## code to prepare `wine_data` dataset goes here# retrieve paths to datafiles
first.file <- system.file(
  "extdata",
  "winemag-data-130k-v2.csv",
  package = "WineReviews"
)second.file <- system.file(
  "extdata",
  "winemag-data_first150k.csv",
  package = "WineReviews"
)# read the two .csv files
data.part.one <- read.csv(
  first.file,
  stringsAsFactors = FALSE,
  encoding = "UTF-8"
)data.part.two <- read.csv(
  second.file,
  stringsAsFactors = FALSE,
  encoding = "UTF-8"
)# select 4 variables and merge the two files
wine.variables <- c("country", "points", "price", "winery")
data.part.one <- data.part.one[, wine.variables]
data.part.two <- data.part.two[, wine.variables]
wine_data <- rbind(data.part.one, data.part.two)# save the wine_data dataframe as an .rda file in WineReviews/data/
usethis::use_data(wine_data, overwrite = TRUE)*

最后一行创建了 data/ 文件夹,数据帧存储为 wine_data.rda 。在我们清理并再次重建之后,该数据可以像任何其他 R 数据一样加载到全局环境中:

**data(“wine_data”, package = "WineReviews")**

记录数据

记录您创建的数据是一个很好的做法。数据的所有文档应保存在一个单独的 R 脚本中,该脚本保存在 R/ 文件夹中。让我们用下面的内容创建这个脚本,并将其命名为 data。R :

**#' Wine reviews for 51 countries.
#'
#' A dataset containing wine reviews.
#'
#' [@format](http://twitter.com/format) A data frame with 280901 rows and 4 variables:
#' \describe{
#' \item{country}{The country that the wine is from.}
#' \item{points}{The number of points rated by WineEnthusiast
#' on a scale of 1–100.}
#' \item{price}{The cost for a bottle of the wine.}
#' \item{winery}{The winery that made the wine.}
#' }
#' [@source](http://twitter.com/source) \url{[https://www.kaggle.com/zynicide/wine-reviews](https://www.kaggle.com/zynicide/wine-reviews)}
"wine_data"**

为了基于这个脚本创建文档,我们运行:

**devtools::document()**

Roxygen 将上面的代码转换成一个 a wine_data。Rd 文件,并将其添加到 man/ 文件夹中。我们可以通过在 R 控制台中键入?winedata在帮助窗格中查看该文档。

我们的包结构现在看起来像这样:

****.** ├── .gitignore
├── .Rbuildignore
├── .Rhistory
├── **data**
│   └── wine_data.rda
├── **data-raw**
│   └── wine_data.R
├── DESCRIPTION
├── **inst**
│   └── **extdata**
│       ├── winemag-data-130k-v2.csv
│       └── winemag-data_first150k.csv
├── **man**
│   └── wine_data.Rd
├── NAMESPACE
├── **R**
│   └── data.R
└── WineReviews.Rproj**

3.中间检查

通过运行以下命令来定期检查我们的包的完整性是一个很好的做法:

**devtools::check()**

我们得到一个警告和一张便条。

定期检查你的包裹,尽早发现问题

关于 R 版本依赖的警告是在调用usethis::use_data(wine_data, overwrite = TRUE)之后引入的,并通过在描述文件中添加Depends: R (>= 2.10)来解决。

将第 14 行添加到描述文件中

因为 inst/extdata 中的数据超过 1 MB,所以该注释警告我们关于包的大小。我们不想在 CRAN 上发布这个 R 包,所以我们可以忽略它。但是,我们将通过将 inst/extdata/ 文件夹添加到来解决这个问题。Rbuildignore** 。**

**^WineReviews\.Rproj$
^\.Rproj\.user$
^data-raw$
^inst/extdata$**

现在devtools::check()显示一切正常:

第二次检查完美地通过了

4.插图中的数据分析

现在我们可以探索处理过的数据。我喜欢用 R 包插图写报告,因为它们有 R 用户熟悉的简洁布局。如果你不喜欢使用简介,你可以在一个标准的 R Markdown 文档中执行这些步骤,而不是简介,如第 7 章所示。

下面的函数用 wine_eda 创建了一个 vignettes/ 文件夹。我们将用于探索性数据分析的 Rmd 插图。

**usethis::use_vignette(name = “wine_eda”, title = “Wine Reviews EDA”)**

我们将使用流行的 dplyr R 包来操作数据。在描述文件中声明我们使用的每个 R 包很重要。别担心:如果你忘了这个devtools::check() 会丢一张纸条。用以下内容申报包裹:

**usethis::use_package(“dplyr”)**

让我们向小插图添加一些代码来加载数据并显示摘要:

**---
title: “Wine Reviews EDA”
output: rmarkdown::html_vignette
vignette: >
 %\VignetteIndexEntry{Wine Reviews EDA}
 %\VignetteEngine{knitr::rmarkdown}
 %\VignetteEncoding{UTF-8}
---```{r, include = FALSE}
knitr::opts_chunk$set(
 collapse = TRUE,
 comment = “#>”
)
``````{r setup}
library(WineReviews)
``````{r}
# load the previously created wine_data data frame
data(wine_data)
``````{r}
summary(wine_data)

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b8603884c238d0646463bb4d67a9929b.png)**

**winedata 缺少 22691 个价格值**

**葡萄酒价格缺少 22691 个值。让我们转换数据来填充这些缺失的值。r 是一种函数式编程语言:我们应该通过应用函数来转换我们的数据。**

> **要理解 R 语言中的计算,有两个口号很有帮助:存在的一切都是对象。发生的一切都是函数调用。”**
> 
> **—约翰·钱伯斯**

**这是我们将分析放在 R 包中的决定将会得到回报的部分:包开发使得编写、记录和测试函数的过程变得非常顺利。**

# **5.使用函数**

**让我们用那个国家葡萄酒的平均价格来代替缺失的价格。从统计学的角度来说,这不一定是个好主意,但它将有助于证明这一点。**

## **编写和记录函数**

**替换将由一个名为“fill_na_mean”的函数来完成。我们创建一个新的 R 脚本**变量 _ 计算。R** 并将其保存在 **R/** 文件夹中。请注意,我们可以如何方便地将函数的文档写在其代码之上。(保留@export 标签,否则@examples 将不起作用。)**

**#' Replace missing values with the mean

'

' @param numeric.vector A vector with at least one numeric value.

'

' @return The input whose NAs are replaced by the input's mean.

'

' @export

'

' @examples fill_na_mean(c(1, 2, 3, NA, 5, 3, NA, 6))

fill_na_mean <- function(numeric.vector) {
ifelse(
is.na(numeric.vector),
mean(numeric.vector, na.rm = TRUE),
numeric.vector
)
}**


**为了创建文档,我们再次运行:**

devtools::document()


**与记录数据的情况一样,Roxygen 将把这个文档转换成一个文件 **fill_na_mean。Rd** 并将其保存在 **man/** 文件夹中。我们可以通过在 R 控制台中键入`?fill_na_mean`在帮助窗格中查看该文档。**

**如果您希望在关闭或重启 R 会话后恢复工作,运行以下命令来加载您的函数以及在**描述**文件中声明的包:**

devtools::load_all()


**接下来,我们将为新创建的函数编写两个测试:**

1.  **每次调用函数时运行的**运行时测试**警告*用户*输入错误。**
2.  **一个**开发时** **测试**,它根据命令运行以警告*开发者*在编写或修改函数时的错误。**

## **运行时测试**

**R 包*断言*提供运行时测试*的功能。***

usethis::use_package(“assertive”)


**我们的简单测试由一行代码组成,它检查输入是否是一个数字向量,如果不是,就抛出一个错误。注意,运行时测试不依赖于我们的包开发环境,因为它们是函数的一部分。**

fill_na_mean <- function(numeric.vector) {
assertive::assert_is_numeric(numeric.vector) # -> the run-time test
ifelse(
is.na(numeric.vector),
mean(numeric.vector, na.rm = TRUE),
numeric.vector
)
}


## **开发时测试**

**与运行时测试相反,使用*测试的开发时测试表明* R 包需要一个活动的包开发环境。让我们为函数编写一个单元测试,测试`fill_na_mean(c(2, 2, NA, 5, 3, NA))`是否返回向量`c(2, 2, 3, 5, 3, 3)`。**

**首先我们建立了*测试和*框架:**

usethis::use_testthat()


**以下命令创建脚本 **test-variable_calculations。R** 包含对 **variable_calculations 中定义的函数的单元测试。R** :**

usethis::use_test("variable_calculations")


**我们修改了**测试变量计算中的代码。R** 代表我们的测试:**

context(“Unit tests for fill_na_mean”)
test_that(“fill_na_mean fills the NA with 3”, {
actual <- fill_na_mean(c(2, 2, NA, 5, 3, NA))
expected <- c(2, 2, 3, 5, 3, 3)
expect_equal(actual, expected)
})


**下面的命令运行所有的测试并返回一个漂亮的报告:**

devtools::test()


**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/45a7452b53d934b85b80ed7778bc31e3.png)**

**我们的单元测试成功通过**

# **6.(重新)组织你的代码**

**现在,我们可以填充我们的数据分析中缺少的值 **wine_eda。Rmd** 。但是如果我们想在其他报表或应用程序中做同样的事情呢?我们应该在每个文件中重复这个过程吗?**

**事实上,这个功能处理的是数据处理,而不是探索性分析。因此,它属于**葡萄酒数据。生成 **wine_data.rda** 的 R** 文件。将此代码放入 **winedata。R** 而不是 **wine_eda。Rmd** 有两个优点:**

1.  **我们的代码变得模块化:用于数据处理的代码与我们的数据分析报告明显分离。**
2.  **只有一个脚本生成所有其他文件使用的已处理数据。**

**填充缺失值后,六个观察值仍然没有葡萄酒价格,因此我们选择删除它们。这是最终脚本的样子:**

**## code to prepare wine_data dataset goes here

retrieve paths to datafiles

first.file <- system.file(
"extdata",
"winemag-data-130k-v2.csv",
package = "WineReviews"
)
second.file <- system.file(
"extdata",
"winemag-data_first150k.csv",
package = "WineReviews"
)

read the two .csv files

data.part.one <- read.csv(
first.file,
stringsAsFactors = FALSE,
encoding = "UTF-8"
)
data.part.two <- read.csv(
second.file,
stringsAsFactors = FALSE,
encoding = "UTF-8"
)

select 4 variables and merge the two files

wine.variables <- c("country", "points", "price", "winery")
data.part.one <- data.part.one[, wine.variables]
data.part.two <- data.part.two[, wine.variables]
wine_data <- rbind(data.part.one, data.part.two)# fill missing prices with the mean price per country
wine_data <- wine_data %>%
dplyr::group_by(country) %>%
dplyr::mutate(price = fill_na_mean(price))# some countries don't have any non-missing price

we omit these observations from the data

wine_data <- wine_data %>%
dplyr::filter(!is.na(price))# save the wine_data dataframe as an .rda file in WineReviews/data/
usethis::use_data(wine_data, overwrite = TRUE)**


**因为我们改变了原始数据的处理方式,所以我们必须在**数据中记录这些变化。 **data-raw/** 文件夹中的 R** 文件:**

**#’ Wine reviews for 49 countries.

’ A dataset containing processed data of wine reviews.

’ Missing price values have been filled with the mean price for

’ that country

’ six observations coming from countries with no wine price were

’ deleted.

’ @format A data frame with 280895 rows and 4 variables:

’ \describe{

’ \item{country}

’ \item{points}{The number of points WineEnthusiast

’ rated the wine on a scale of 1–100}

’ \item{price}

’ \item{winery}

’ }

’ @source \url{https://www.kaggle.com/zynicide/wine-reviews}

“wine_data”**


**并更新文档:**

devtools::document()


**让我们编织我们的小图案。请注意,即使我们没有更改插图中的代码,也不再有丢失的值。在 **wine_data 中删除缺失的值。R** 脚本。在插图中,我们只是加载处理过的 **wine_data.rda** 。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f3bd37e1d3c7bfd3d879a4c6e7c495a4.png)**

**wine_data 摘要不包含缺失值**

# **7.使用 R Markdown**

**我们可以将任何 R Markdown 文件添加到我们的包中。类似于原始数据,我们在 **inst/** 文件夹中创建一个子文件夹 **rmd/** 。让我们创建一个简单的仪表板来查看每个国家的葡萄酒价格分布。我们创建一个 R Markdown 文件 **wine_dashboard。 **rmd/** 中的 Rmd** 内容如下:**

**---
title: "Wine dashboard"
output:
flexdashboard::flex_dashboard:
orientation: columns
runtime: shiny
---```{r setup, include=FALSE}
library(flexdashboard)
library(ggplot2)

data(wine_data, package = "WineReviews")
```Inputs {.sidebar data-width=150}
-------------------------------------
```{r}
shiny::selectInput(
 "country",
 label = "select country",
 choices = sort(unique(wine_data$country))
)
```Column
-------------------------------------### Wine points versus price

```{r}
shiny::renderPlot(
 ggplot(wine_data[wine_data$country == input$country, ],
 aes(points, log10(price), group = points)) +
 geom_boxplot() +
 labs(x = "points scored by the wine on a 100 scale",
 y = "Base-10 logarithm of the wine price") +
 theme_bw()
)
```Column
-------------------------------------
### Wine price distribution

```{r}
shiny::renderPlot(
 ggplot(wine_data[wine_data$country == input$country, ], aes(price)) +
 geom_density() +
 labs(y = "Price density function") +
 theme_bw()
)
```
```

**让我们用*运行文件*查看仪表板:**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/bc90d5219f9c3ff207fe78c59b9023be.png)**

**按“运行文档”查看仪表板**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3383cf389337873d43e948006b8d3c11.png)**

# **8.使用版本控制**

**我们的数据分析示例现在已经完成。这是我们最终项目结构的样子:**

```
****.** ├── .gitignore
├── .Rbuildignore
├── .Rhistory
├── DESCRIPTION
├── **data**
│   └── wine_data.rda
├── **data-raw**
│   └── wine_data.R
├── **inst**
│   ├── **extdata**
│   │   ├── winemag-data-130k-v2.csv
│   │   └── winemag-data_first150k.csv
│   └── **rmd**
│       └── wine_dashboard.Rmd
├── **man**
│   ├── fill_na_mean.Rd
│   └── wine_data.Rd
├── NAMESPACE
├── **R**
│   ├── data.R
│   └── variable_calculation.R
├── **tests**
│   ├── **testthat**
│   │   └── test-variable_calculations.R
│   └── testthat.R
├── **vignettes**
│   └── wine_eda.Rmd
└── WineReviews.Rproj**
```

**这种结构是合适的版本控制。跟踪有代码的文件,而不跟踪 **inst/extdata** 中的原始数据和 **data/** 中的已处理数据。我们可以使用 **data-raw/** 中的 R 脚本从(重新)下载的原始数据中生成经过处理的数据。我建议将以下条目添加到**中。gitignore** :**

```
**.Rproj.user
.Rhistory
data/
inst/extdata/
inst/doc**
```

# **概述**

**下面是我们如何利用 R 包组件的:**

*   ****描述:**给出了项目及其依赖项的概述**
*   ****R/** :包含 R 脚本,其函数在整个包中使用**
*   ****测试/** :包含我们函数的开发时测试**
*   ****inst/extdata/** :包含我们的原始数据文件**
*   ****data-raw/** :包含将原始数据处理成整齐数据的 R 脚本**
*   ****数据/** :包含整齐的数据存储为。rda 文件**
*   ****man/** : 包含我们的对象和函数的文档**
*   ****vignettes/** :包含数据分析报告作为包 vignettes**
*   ****inst/rmd** :包含报告或应用程序的 R Markdown 文件**

**我希望你喜欢这篇文章。你会考虑用 R 包来存储你的作品吗?你喜欢如何组织你的项目?
在评论里告诉我吧!**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/031a4c7b10e04603b62c56059f0ac153.png)**

**照片由 chuttersnap 在 Unsplash 上拍摄**

# 结束不可靠的分析

> 原文:<https://towardsdatascience.com/putting-an-end-to-unreliable-analytics-386431bb4e56?source=collection_archive---------55----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/565933822e17ecd845ed58552cd7723c.png)

来源:Pixaby 的 TheToonCompany

当构建一个产品或服务时,知道输入数据将是预期的是必要的。如果信息来自另一个部门,依靠他们不改变它不可避免地以失望告终,因为他们可能甚至不知道他们的数据正在被使用,当然也不知道如何被使用。

优秀的工程师知道这一点,并测试一切以确保他们能捕捉到任何变化或错误。从本质上来说,人类容易犯错误,一个好的工程师有一种谦逊的感觉。通过质量测试,您可以在错误进入生产服务器之前发现它们。

代码现在相对容易测试。编译器和测试套件有助于确保代码在单一环境中正常运行。不幸的是,在集成点发生错误仍然很常见,而且代价非常高——一个系统将数据或任务交给另一个系统。

集成点无处不在。每当使用不同的技术时,或者当服务在团队之间移交时,就会发生这种情况。在移交过程中确保准确性和一致性的最流行的方法之一是通过构建良好记录的 API,这些 API 被维护并直接向其他团队公开。这实质上是亚马逊 2002 年的微服务战略。

API 有助于实现跨技术/团队的交流,因为它们为每个服务提供了一个框架来验证它们发送或接收的数据。如果出现问题,可以快速返回错误,从而实现可靠性和健全性,因为问题会导致失败,因此可以快速修复。不幸的是,实现和维护它们的成本很高。每个 API 都需要有文档记录和支持的持续可用的服务。因此,企业[花费数万](https://medium.com/yourapi/how-much-does-it-cost-to-build-an-api-925b1bf90da9#:~:text=Making%20some%20assumptions%20about%20average,integration%20is%20between%2020%E2%80%9330)来持续实施和维护终端。

分析工作负载通常会集成来自许多不同来源的数据,而不进行任何运行时验证,这会导致运行时崩溃或更糟的错误结果。许多组织中的“数据产品”依赖于集成来自各种来源的信息,经常利用复杂的转换来将各个部分组合在一起。但是这些“数据产品”通常具有非常弱的测试覆盖率,并且测试它们的最先进技术是非常新的或者是刚刚建立的。 [JSON schema](https://json-schema.org/) 可以是一种通过验证集成来自任何来源的数据的轻量级方法,而不需要重量级 API。它本质上是一个框架,用于确保传输中的数据呈现出预期的形状和结构。因此,在数据进入系统之前,可以通过在系统边缘验证有效性来捕捉运行时错误。可以编写更简单的测试来确保坏数据不会离开或进入。

我们已经在 Protobuf 和 OpenAPI 等其他技术中看到了这种趋势。它们都已经发展到至少提供一些现成的模式检查和验证,解除了开发人员进行请求/响应验证的责任。虽然两者都不完美,但通过[完全采用](https://swagger.io/specification/) JSON 模式,OpenAPI 似乎正朝着正确的方向前进。

主要问题是这些框架走得还不够远。我们需要一个更全面的管道,将 OpenAPI 风格的输入和输出预期引入数据管道,在 API 服务完成后,数据管道负责事件。我们应该能够拥有一个既可以用来针对 OpenAPI 构建 API,又可以深入数据管道、服务和存储的 schematic truth 来源。

使用这些原则并结合 JSON schema 等工具,我们将走向一个未来的世界,不仅在一个团队维护的代码中进行端到端测试,而且跨越边界。在某种程度上,具有前瞻性思维的企业会将模式集中化,以便更改可以简单地过滤到使用它的所有产品和服务。数据集成和产品开发将变得更快、更可靠;开发它们看起来更像是构建软件,而不是搭建技术基础设施。

分析是一个包含大量低级点解决方案的空间,这些解决方案需要连接在一起,而不需要在它们之间进行原生错误检查。它的主要焦点是集成,而不是处理。我们应该从基本原则后退一步,想想我们需要什么样的数据分析框架来帮助我们做到这一点。一个可用的系统不仅应该在测试中验证数据,还应该在生产中验证数据,并在每个系统的边界进行检查。

# 用人工智能把病人放在第一位

> 原文:<https://towardsdatascience.com/putting-patients-first-with-artificial-intelligence-751c49ab97a0?source=collection_archive---------32----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/689189269b60a9d5a731e316796d1a5a.png)

克里斯蒂安·鲍文在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

我们总有一天会用到医疗保健系统。然而,即使在过去的几十年里有了巨大的飞跃,仍然有几个缺点。健康信息系统与人工智能(AI)相结合,可以极大地改变患者的生活,同时帮助卫生从业人员开展日常工作。

重要的是要认识到情况并不总是像今天这样。在世纪之交,医学研究所报告说,在美国,每年大约有 100,000 人由于医疗失误而丧生。这一事实的可悲之处在于,许多这样的错误是很容易避免的。

已经有几例医生给对药物过敏的病人开了药。在这些案例中,医生没有注意到患者记录中的过敏记录,这一错误导致了患者的最终死亡。计算机化的系统有助于在系统内精确地建立类似的制衡机制,从而减少人为错误,使整个过程对病人来说更加安全。

如今,大多数现代医院已经有了这样的系统,但随着人工智能的最新进展,它们现在可以进入下一个阶段。以下是我们医院目前正在开发或使用的人工智能系统的一些例子。它们涉及三个非常不同的方面;第一个帮助医院管理,第二个帮助病人护理,第三个支持护理人员。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3b9784e238135724c93985a92326186c.png)

freestocks.org 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上[拍照](https://unsplash.com/@freestocks?utm_source=medium&utm_medium=referral)

医院一直在努力提高效率,同时不牺牲给病人的服务。他们中的许多人正在部署医用机器人,旨在帮助医生和护士开出正确的药方。这种机器人能够追踪他们提供给病人的所有药物;他们可以准备准确的剂量,并仔细检查病人档案中指定的任何条件。一辆智能手推车能够自己在医院导航,然后将药物送到特定的病房。这种系统消除了处方错误,为医院节省了大约 30%的库存,并消除了与过期药物相关的所有损失。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/797d3ac07e097f1b8778d85d75b699f2.png)

由 [Jesper Aggergaard](https://unsplash.com/@aggergakker?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片

病人是医疗保健系统的核心。正因为如此,组织努力提高他们的服务,特别是当年轻的人参与进来的时候。许多医院正在使用[虚拟现实(VR)头戴设备来帮助年轻患者转移注意力](https://researchtrustmalta.eu/research-projects/virtual-reality-in-healthcare/);从他们正在接受的治疗到娱乐性的东西,如电脑游戏。这种方法被称为注意力分散疗法,效果出奇的好;在某些情况下,患者报告疼痛减轻了近 50%。注意力分散疗法的伟大之处在于,患者不需要服用任何药物,从而降低了过敏、止痛药成瘾和其他许多风险。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/36943cf166ef6e3bf0967aa0b1386aae.png)

照片由 [Jesper Aggergaard](https://unsplash.com/@aggergakker?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄

护理人员做得很好,但我们都知道他们的工作很有挑战性,在某些情况下很乏味。正因为如此,人工智能正被用来促进那些可以自动化的任务。AI 的使用并不意味着它将取代护理员,远非如此。护理职业中人的因素仍然至关重要,而且短期内不会有任何变化。然而,人工智能将接管那些需要重复分析的任务,并帮助护理人员加快整个过程。一个恰当的例子是对人体运动的研究,通常称为“步态分析”。在这种情况下,一个摄像机跟踪系统拍摄病人的移动镜头。物理治疗师然后分析获得的大量数据。这一过程通常持续数小时;然而,人工智能系统可以将时间缩短到几秒钟。当然,人类的直觉对于验证自动化分析仍然非常重要,但是至少,对于护理人员来说,总体上节省了时间。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ae9ab14048d80e8cc65f1ea1b48421f5.png)

贾法尔·艾哈迈德在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片

> 重要的是要记住,这种转变的核心是病人

在本文中,我们只选择了三个在许多医院都能找到的简单用例,但我们仅仅触及了冰山一角。医疗保健行业在许多应用中使用人工智能,例如在识别癌细胞、药物研发过程中、指导机器人外科医生、健康监测和许多其他方面。重要的是要记住,这种转变的核心是病人。人工智能是人类创造的最强大的工具,它的医疗应用将在未来几年拯救更多的生命。

【https://www.businesstoday.com.mt】本文原载于[](https://www.businesstoday.com.mt/people/people/517/interview__alexiei_dingli_malta_ideal_place_to_launch_and_deploy_ai_solutions)

*[**阿列克谢·丁力教授**](http://www.dingli.org/) 是马耳他[大学](https://www.um.edu.mt/)的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他出版了几本同行评审的出版物,并且是马耳他[的一部分。由马耳他政府成立的人工智能工作组,旨在使马耳他成为世界上人工智能水平最高的国家之一。](https://malta.ai/)*

# PyCaret 2.0 已经发布了,有什么新内容吗?

> 原文:<https://towardsdatascience.com/pycaret-2-0-is-here-whats-new-34baa87a951e?source=collection_archive---------37----------------------->

## 机器学习爱好者的 3 大新功能

毫无疑问,PyCaret 是我最喜欢的机器学习库。它比 Scikit-Learn 对开发人员更友好,并提供了内置功能来轻松处理主要的机器学习任务。*那么,这个版本有什么新内容?*读一读就知道了。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/fac60a8157e3f7b458ba739b8b8c99f6.png)

[粘土银行](https://unsplash.com/@claybanks?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 拍摄的照片

如果你以前没有使用过这个库,请随意查看下面的文章。它们是分类和回归任务的良好起点。

*   [PyCaret:用 Python 实现更好的机器学习](/pycaret-better-machine-learning-with-python-58b202806d1e)
*   [用 PyCaret 回归:一个更好的机器学习库](/regression-with-pycaret-a-better-machine-learning-library-e02762a0615c)
*   [用 PyCaret 分类:一个更好的机器学习库](/classification-with-pycaret-a-better-machine-learning-library-cff07a10a28c)

几天前发布了 2.0 版本,并带来了一些新功能。大多数都是次要的,但仍然值得一提,因为它们会节省您的时间或为您提供一些额外的信息。

这是完整的变更日志。

我们将在下一节看到如何安装这个库。

# 库安装

首先,打开终端/CMD 并执行下面一行:

```
pip install pycaret==2.0
```

我假设您已经安装并配置了 *Python* ,无论是作为独立安装还是通过 *Anaconda* 。由于大量的依赖项,安装将需要一分钟左右的时间才能完成。

完成后,您可以打开笔记本环境,导入库,并检查版本。

```
import pycaretpycaret.__version__ **>>> ‘2.0.0’**
```

这就是安装的基本内容。接下来我们将讨论最有用的新特性。

# 1.训练时间

这个特性无论如何都不是突破性的,但是拥有它很好。例如,在调用`compare_models()`函数时,您现在会得到一个表示训练时间的附加列:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/6587792d40cc1c0d1f7c77a115474040.png)

这是原始虹膜数据集的性能。我们可以看到用明显的黄色标记的最佳算法,以及在最右边添加的以秒为单位的训练时间,作为一个新列。

这是一个很好的功能,因为它显示了体面的 QDA 速度训练速度的改善,而不是额外的树分类器算法,同时提供相同的性能。如果速度是一个问题,这些功能可能是有用的。

# 2.保存可视化效果

我在 PyCaret 上的前几篇文章展示了根据您的模型性能制作好看的可视化效果是多么容易。缺少的一件事是把情节保存到你的设备上。

使用 2.0 版,很容易将各种图保存到您的设备中。这里有一个例子:

```
plot_model(model, plot=’confusion_matrix’, save=True)
```

如您所见,这里唯一的新参数是`save`参数。当设置为`True`时,绘图保存在您的设备上。让我们快速浏览一下:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1021ea0c8bf3eb979d7620f963abb9c1.png)

# 3.MLFlow UI

对于那些不知道的人来说, *PyCaret* 2.0 嵌入了一个 *MLflow* 跟踪组件,作为日志记录的后端 API 和 UI。你可以在这个链接上阅读更多关于 MLFlow [的内容,但总而言之,这是一个管理机器学习生命周期的很好的 GUI,在这种情况下,比较模型性能。](https://mlflow.org)

下面是导入数据、比较模型和启动后端服务的完整代码:

```
from pycaret.classification import * 
from pycaret.datasets import get_datairis = get_data(‘iris’)clf = setup(
    iris, 
    target=’species’, 
    session_id=42, 
    **log_experiment=True, 
    experiment_name=’exp1'**
)compare_models()!mlflow ui
```

这两行粗体字对于在应用程序中选择适当的实验特别重要,稍后您会看到原因。

执行完这段代码后,只需进入`[http://localhost:5000](http://localhost:5000)`查看应用程序:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/50cd215e1063c25fd80ff2a62624e03c.png)

# 在你走之前

根据我目前使用该库的经验,这是一篇相当快速的文章,展示了 PyCaret 2.0 最有用的新特性。你的答案可能会有所不同,所以请记住这一点。对于完整的变更日志,[请访问此链接](https://github.com/pycaret/pycaret/releases/tag/2.0)。

此外,你可以自由地自己进一步研究官方文档,因为这是最好的文档之一。

感谢阅读。

*喜欢这篇文章吗?成为* [*中等会员*](https://medium.com/@radecicdario/membership) *继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。*

[](https://medium.com/@radecicdario/membership) [## 通过我的推荐链接加入 Medium-Dario rade ci

### 作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership) 

[**加入我的私人邮件列表,获取更多有用的见解。**](https://mailchi.mp/46a3d2989d9b/bdssubscribe)

# PyCaret 2.1 已经发布了,有什么新内容吗?

> 原文:<https://towardsdatascience.com/pycaret-2-1-is-here-whats-new-4aae6a7f636a?source=collection_archive---------8----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3c68ba7ee153a65dbc070dc6e51ace86.png)

PyCaret 2.1 现在可以使用 pip 下载。[https://www.pycaret.org](https://www.pycaret.org)

我们很高兴宣布 py caret 2.1—2020 年 8 月的更新。

PyCaret 是一个用 Python 编写的开源、**低代码**机器学习库,可以自动化机器学习工作流。它是一个端到端的机器学习和模型管理工具,可以加快机器学习实验周期,让您的工作效率提高 10 倍。

与其他开源机器学习库相比,PyCaret 是一个替代的低代码库,可以用来替换数百行代码。这使得实验快速有效。

如果你以前没有听说过或使用过 PyCaret,请查看我们的[之前的公告](/announcing-pycaret-2-0-39c11014540e)快速入门。

# 正在安装 PyCaret

安装 PyCaret 非常容易,只需要几分钟。我们强烈建议使用虚拟环境来避免与其他库的潜在冲突。参见下面的示例代码,创建一个 ***conda 环境*** 并在该 conda 环境中安装 pycaret:

```
**# create a conda environment** 
conda create --name yourenvname python=3.6 **# activate environment** 
conda activate yourenvname **# install pycaret** 
pip install pycaret**# create notebook kernel linked with the conda environment** python -mipykernel install --user --name yourenvname --display-name "display-name"
```

如果您已经安装了 PyCaret,您可以使用 pip 更新它:

```
pip install --upgrade pycaret
```

# **PyCaret 2.1 功能概述**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/42cb027a6784a8d3205cf6ca84dfb9a9.png)

由[paweczerwiński](https://unsplash.com/@pawel_czerwinski?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片

# 👉GPU 上的超参数调整

在 PyCaret 2.0 中,我们宣布了针对某些算法(XGBoost、LightGBM 和 Catboost)的支持 GPU 的培训。2.1 中的新功能是现在你还可以在 GPU 上调整这些模型的超参数。

```
**# train xgboost using gpu**
xgboost = create_model('xgboost', tree_method = 'gpu_hist')**# tune xgboost** tuned_xgboost **=** tune_model(xgboost)
```

在 **tune_model** 函数中不需要额外的参数,因为它自动从使用 **create_model** 函数创建的 xgboost 实例中继承 tree_method。如果你对小比较感兴趣,这里是:

> **100,000 行,88 个特征,8 个类的多类问题**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c7cc550598a3e212763a92ea7d178674.png)

GPU 上的 XGBoost 培训(使用 Google Colab)

# 👉模型部署

自从 2020 年 4 月 PyCaret 的第一次发布以来,您可以简单地使用笔记本上的中的 **deploy_model** 在 AWS 上部署训练好的模型。在最近的版本中,我们增加了一些功能来支持在 GCP 和微软 Azure 上的部署。

## **微软 Azure**

若要在 Microsoft Azure 上部署模型,必须设置连接字符串的环境变量。可以从 Azure 中您的存储帐户的“访问密钥”中获取连接字符串。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f41dd16b324137b12e105441e3dec242.png)

https:/portal . azure . com-从存储帐户获取连接字符串

一旦复制了连接字符串,就可以将其设置为环境变量。请参见下面的示例:

```
**import os** os.environ['AZURE_STORAGE_CONNECTION_STRING'] = 'your-conn-string'**from pycaret.classification import deploy_model**
deploy_model(model = model, model_name = 'model-name', platform = 'azure', authentication = {'container' : 'container-name'})
```

嘣!就是这样。只需使用一行代码**,**你的整个机器学习管道现在就装在微软 Azure 的容器里了。您可以使用 **load_model** 函数来访问它。

```
**import os** os.environ['AZURE_STORAGE_CONNECTION_STRING'] = 'your-conn-string'**from pycaret.classification import load_model** loaded_model = load_model(model_name = 'model-name', platform = 'azure', authentication = {'container' : 'container-name'})**from pycaret.classification import predict_model** predictions = predict_model(loaded_model, data = new-dataframe)
```

## 谷歌云平台

要在 Google Cloud Platform (GCP)上部署模型,您必须首先使用命令行或 GCP 控制台创建一个项目。创建项目后,您必须创建一个服务帐户,并以 JSON 文件的形式下载服务帐户密钥,然后用它来设置环境变量。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/80c8afb7b72f587769c4034b3d89bdb3.png)

创建新的服务帐户,并从 GCP 控制台下载 JSON

要了解更多关于创建服务账户的信息,请阅读[官方文档](https://cloud.google.com/docs/authentication/production)。一旦创建了服务帐户并从 GCP 控制台下载了 JSON 文件,就可以开始部署了。

```
**import os** os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'c:/path-to-json-file.json'**from pycaret.classification import deploy_model** deploy_model(model = model, model_name = 'model-name', platform = 'gcp', authentication = {'project' : 'project-name', 'bucket' : 'bucket-name'})
```

模型已上传。现在,您可以使用 **load_model** 函数从 GCP 存储桶访问模型。

```
**import os** os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'c:/path-to-json-file.json'**from pycaret.classification import load_model** loaded_model = load_model(model_name = 'model-name', platform = 'gcp', authentication = {'project' : 'project-name', 'bucket' : 'bucket-name'})**from pycaret.classification import predict_model** predictions = predict_model(loaded_model, data = new-dataframe)
```

# 👉MLFlow 部署

除了使用 PyCaret 的本地部署功能,您现在还可以使用所有 MLFlow 部署功能。要使用这些,您必须使用**设置**功能中的 **log_experiment** 参数记录您的实验。

```
**# init setup**
exp1 = setup(data, target = 'target-name', log_experiment = True, experiment_name = 'exp-name')**# create xgboost model** xgboost = create_model('xgboost')..
..
..# rest of your script**# start mlflow server on localhost:5000**
!mlflow ui
```

现在在你喜欢的浏览器上打开 [https://localhost:5000](https://localhost:5000) 。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c6f5dfacbf6cc8779e3891e9d6302da5.png)

[https://localhost:5000](https://localhost:5000) 上的 MLFlow UI

点击**【运行名称】**左侧的**【开始时间】**,可以看到运行的详细信息。你在里面看到的是一个训练模型的所有超参数和评分指标,如果你向下滚动一点,所有的工件也会显示出来(见下文)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d091796efeca521dc153fdba0095490d.png)

MLFLow 伪影

经过训练的模型以及其他元数据文件存储在“/model”目录下。MLFlow 遵循包装机器学习模型的标准格式,这些模型可用于各种下游工具中——例如,通过 REST API 或 Apache Spark 上的批处理推理进行实时服务。如果您愿意,您可以使用 MLFlow 命令行在本地为该模型提供服务。

```
mlflow models serve -m local-path-to-model
```

然后,您可以使用 CURL 将请求发送给 model 以获得预测。

```
curl [http://127.0.0.1:5000/invocations](http://127.0.0.1:5000/invocations) -H 'Content-Type: application/json' -d '{
    "columns": ["age", "sex", "bmi", "children", "smoker", "region"],
    "data": [[19, "female", 27.9, 0, "yes", "southwest"]]
}'
```

*(注意:Windows 操作系统尚不支持 MLFlow 的这一功能)。*

MLFlow 还提供与 AWS Sagemaker 和 Azure 机器学习服务的集成。您可以使用 SageMaker 兼容环境在 Docker 容器中本地训练模型,或者在 SageMaker 上远程训练模型。要远程部署到 SageMaker,您需要设置您的环境和 AWS 用户帐户。

**使用 MLflow CLI 的示例工作流**

```
mlflow sagemaker build-and-push-container 
mlflow sagemaker run-local -m <path-to-model>
mlflow sagemaker deploy <parameters>
```

要了解有关 MLFlow 所有部署功能的更多信息,[请单击此处](https://www.mlflow.org/docs/latest/models.html#)。

# 👉MLFlow 模型注册表

MLflow 模型注册组件是一个集中式模型存储、一组 API 和 UI,用于协作管理 MLflow 模型的整个生命周期。它提供了模型沿袭(MLflow 实验和运行产生了模型)、模型版本化、阶段转换(例如从阶段转换到生产)和注释。

如果运行您自己的 MLflow 服务器,您必须使用数据库支持的后端存储来访问模型注册表。[点击此处](https://www.mlflow.org/docs/latest/tracking.html#backend-stores)了解更多信息。然而,如果你使用的是 [Databricks](https://databricks.com/) 或者任何托管的 Databricks 服务,比如 [Azure Databricks](https://azure.microsoft.com/en-ca/services/databricks/) ,你不需要担心设置什么。它配有你所需要的所有铃铛和哨子。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/27ab54e7016ad97922df9824515fc127.png)

[https://data bricks . com/blog/2020/06/25/announcing-ml flow-model-serving-on-data bricks . html](https://databricks.com/blog/2020/06/25/announcing-mlflow-model-serving-on-databricks.html)

# 👉高分辨率绘图

这并不是突破性的,但对于使用 PyCaret 进行研究和发表文章的人来说,确实是一个非常有用的补充。 **plot_model** 现在有一个名为“scale”的附加参数,通过它您可以控制分辨率并为您的出版物生成高质量的绘图。

```
**# create linear regression model**
lr = create_model('lr')**# plot in high-quality resolution** plot_model(lr, scale = 5) # default is 1
```

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/dd58173a94e3f8b6e0d517927ea000ca.png)

PyCaret 的高分辨率残差图

# 👉用户定义的损失函数

这是自第一版发布以来最受欢迎的特性之一。允许使用自定义/用户定义的函数调整模型的超参数为数据科学家提供了巨大的灵活性。现在可以通过使用 **tune_model** 函数中的 **custom_scorer** 参数来使用用户自定义损失函数。

```
**# define the loss function**
def my_function(y_true, y_pred):
...
...**# create scorer using sklearn**
from sklearn.metrics import make_scorermy_own_scorer = make_scorer(my_function, needs_proba=True)**# train catboost model** catboost = create_model('catboost')**# tune catboost using custom scorer** tuned_catboost = tune_model(catboost, custom_scorer = my_own_scorer)
```

# 👉特征选择

特征选择是机器学习中的一个基本步骤。您丢弃了一堆特征,并且希望只选择相关的特征,而丢弃其他的特征。目的是通过去除会引入不必要噪声的无用特征来简化问题。

在 PyCaret 2.1 中,我们介绍了用 Python 实现 Boruta 算法(最初用 R 实现)。Boruta 是一种非常智能的算法,可以追溯到 2010 年,旨在自动对数据集执行特征选择。要使用它,你只需在**设置**函数中传递**特征选择方法**。

```
exp1 = setup(data, target = 'target-var', feature_selection = True, feature_selection_method = 'boruta')
```

要阅读更多关于 Boruta 算法的内容,请点击这里。

# 👉其他变化

*   `compare_models`功能中的`blacklist`和`whitelist`参数现更名为`exclude`和`include`,功能不变。
*   为了在`compare_models`功能中设置训练时间的上限,增加了新参数`budget_time`。
*   PyCaret 现在与 Pandas 分类数据类型兼容。在内部,它们被转换成对象,并以与处理`object`或`bool`相同的方式进行处理。
*   在`setup`功能的`numeric_imputation`中添加了数字插补新方法`zero`。当方法设置为`zero`时,缺失值被常量 0 替换。
*   为了使输出更易于阅读,由`predict_model`函数返回的`Label`列现在返回原始值,而不是编码值。

要了解 PyCaret 2.1 中所有更新的更多信息,请参见[发布说明](https://github.com/pycaret/pycaret/releases/tag/2.1)。

使用 Python 中的轻量级工作流自动化库,您可以实现的目标是无限的。如果你觉得这有用,请不要忘记给我们 GitHub repo 上的⭐️。

想了解更多关于 PyCaret 的信息,请关注我们的 LinkedIn 和 Youtube。

# 重要链接

[用户指南](https://www.pycaret.org/guide)
[文档](https://pycaret.readthedocs.io/en/latest/)
[官方教程](https://github.com/pycaret/pycaret/tree/master/tutorials) [示例笔记本](https://github.com/pycaret/pycaret/tree/master/examples)
[其他资源](https://github.com/pycaret/pycaret/tree/master/resources)

# 想了解某个特定模块?

单击下面的链接查看文档和工作示例。

[分类](https://www.pycaret.org/classification)
[回归](https://www.pycaret.org/regression) [聚类](https://www.pycaret.org/clustering)
[异常检测](https://www.pycaret.org/anomaly-detection) [自然语言处理](https://www.pycaret.org/nlp)
关联规则挖掘