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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

如何使用成对相关性进行鲁棒的特征选择

原文:https://towardsdatascience.com/how-to-use-pairwise-correlation-for-robust-feature-selection-20a60ef7d10?source=collection_archive---------3-----------------------

将久经考验的方法添加到您的武器库中

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

照片由 Pixabay 像素

相关系数是多少?

在我上一篇关于特性选择的文章中,我们关注了一种基于特性的移除技术。在本帖中,我们将探讨一种更可靠、更稳健的方法,让我们看到特性之间的联系,并决定它们是否值得保留。正如你从标题中所看到的,这种方法使用成对相关。

首先,让我们简单的接触一下皮尔逊相关系数——通常表示为 r 。该系数可用于量化单个指标中两个分布(或特征)之间的线性关系。它的范围从-1 到 1,-1 是完全负相关,+1 是完全正相关。

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

作者图片

例如,身体测量通常有很强的正相关性。你可以预期高个子会有更长的胳膊和腿,或者宽肩膀的人会更重。还有,冰淇淋的销量和温度负相关,或者跑得越远越慢等等。

关于如何使用、解释和理解相关系数的深入指导,请参考我的另一篇文章

但是相关系数和机器学习或者特征选择有什么关系呢?嗯,假设两个特征之间的相关系数是 0.85。这意味着在 85%的情况下,您可以仅使用特性 1 的值来预测特性 2。换句话说,如果数据集中有要素 1,则要素 2 不会带来太多新信息。这就是为什么保留特征 2 没有意义,因为它只会在训练模型时增加复杂性。

使用成对相关进行要素选择就是这么回事-识别高度相关的要素组并仅保留其中一个要素,以便您的模型可以使用尽可能少的要素获得尽可能大的预测能力。

https://ibexorigin.medium.com/membership

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

https://alphasignal.ai/?referrer=Bex

绘制完美的相关矩阵

识别高度相关特征的最快且通常是最好的方法是使用相关矩阵。该矩阵显示了数据集中每一对数值要素之间的相关性。

让我们来看一个使用墨尔本住房数据集的例子,该数据集包含 13 个数字特征:

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

计算矩阵很容易通过调用 DataFrame 上的.corr()方法来完成。接下来,我们将它传递给 Seaborn 的热图函数,通常这样做是为了生成漂亮的视觉效果:

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

是的,默认热图没有那么好。让我们给它补个妆:

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

首先,我们创建一个定制的发散调色板(蓝色->白色->红色)。然后,我们将颜色条以 0 为中心,使注释能够看到每个相关性,并使用 2 个小数点。

如您所见,矩阵将每对之间的相关性显示两次,因为 A 和 B 之间的相关性与 B 和 A 之间的相关性相同。此外,对角线由 1 组成,表示特征与其自身的相关性。所有这些额外的信息会让人分心。这就是为什么我们要去掉矩阵的上半部分:

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

在上面代码片段的第 4 行,我们创建了一个 2D 布尔掩码。首先,np.ones_like创建一个 2D numpy 数组,其形状与填充了True值的相关矩阵相同。然后,将这个数组传递给np.triu,将它转换成适合我们需要的布尔掩码。我们只是将这个面具传递给heatmapmask论证,这给了我们上面美丽的情节。

下面是一个绘制这些完美相关矩阵的小函数:

即使我们可以通过编程找到所有高度相关的特性,我们仍然应该直观地探索它们。因为像上面这样的热图有助于我们了解相关性是否有意义。例如,新生婴儿的数量可能与附近鹳的数量高度相关,尽管这没有任何意义。这就是为什么要进行视觉探索,以查看各组特征是否实际上相互关联,以及寻找它们之间的联系是否有意义。

如何移除高度相关的特征

现在,让我们看看我们如何实际删除高度相关的功能。这次我们将使用不同的数据集— Ansur 数据集。它包含了 6000 名美国陆军人员的所有可以想象的身体尺寸,还包含了 98 个数字特征。这是一个练习要素选择技能的绝佳数据集,因为该数据集中有许多相关的要素:

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

我们将只处理数字特征,因此,我们将隔离它们:

顺便说一句,试图用这么多特征来绘制数据集的相关矩阵是没有用的。

我们的目标是消除强烈的相关性,无论是负面的还是正面的。因此,我们这次将通过在.corr()上链接.abs()方法来构建具有相关性绝对值的矩阵:

接下来,我们再次创建一个布尔掩码,用于矩阵的子集化:

使用熊猫数据帧的mask方法(相关矩阵是一个数据帧)将 NaN 值放在矩阵的上半部分和对角线上:

>>> reduced_matrix.iloc[:5, :5]

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

接下来,我们需要设置一个阈值来决定是否删除某个特性。应该仔细选择这个阈值,并且只有在彻底了解数据集的情况下才能选择。对于我们的例子,我们将选择阈值 0.9:

上面的列表理解找到了满足阈值 0.9 的所有其他列。使用any可以让我们不使用嵌套的 for 循环,就像这样:

列表理解无疑是一个更好的解决方案。注意,如果我们没有将NaN放在矩阵的上半部分和对角线上,我们将丢失所有相关的特征,而不是保留其中的一个。

下面是一个函数,它对任意阈值执行上述操作,并返回要删除的列的列表:

现在,让我们实际删除这些列:

现在,让我们看看放弃这么多特性是否是正确的选择。我们将通过训练两个RandomForestRegressor来检查这一点:一个在完整数据集上,一个在缩减的、特征选择的数据集上。目标重量以磅为单位- Weightlbs:

我们得到了一个非常好的结果,即使有这么多的功能。现在,让我们在特征选择的数据帧上重复上述内容:

我们的测试分数只降低了 2%,而运行时间却减少了两倍。

结论

总之,使用成对相关允许我们检测高度相关的特征,这些特征不会给数据集带来新的信息。因为这些特性只会增加模型的复杂性,增加过度拟合的机会,并且需要更多的计算,所以应该去掉它们。

然而,在使用这种技术之前,通过做适当的 EDA 来彻底理解你的数据集。总是寻找没有意义的相关性,例如,没有联系的随机相关特征。

如果你不知道接下来要读什么,这里我为你挑选了一些:

</11-times-faster-hyperparameter-tuning-with-halvinggridsearch-232ed0160155> https://towardsdev.com/intro-to-object-oriented-programming-for-data-scientists-9308e6b726a2

如何使用排列测试

原文:https://towardsdatascience.com/how-to-use-permutation-tests-bacc79f45749?source=collection_archive---------1-----------------------

排列测试及其如何应用于时序数据的演练。

排列检验是非参数检验,只需要很少的假设。所以,当你不太了解你的数据生成机制(总体)时,排列测试是确定统计显著性的有效方法。

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

图 1:排列测试分布的例子。红色垂直线是我们的观测数据测试统计。这里,98.2%的排列分布在红线以下,表明 p 值为 0.018。图片作者。

斯坦福大学研究人员最近发表的一篇论文将排列测试框架扩展到了时间序列数据,这是一个排列测试通常无效的领域。这个方法非常数学化,而且是全新的,所以几乎没有支持,也没有 python/R 库。然而,它非常高效,可以大规模实施。

在本帖中,我们将讨论排列测试的基础,并简要概述时间序列方法。

让我们开始吧。

技术 TLDR

置换检验是非参数检验,只依赖于可交换性的假设。

为了得到 p 值,我们随机抽样(没有替换)我们感兴趣的变量的可能排列。p 值是检验统计量大于观测数据的样本比例。

时间序列数据很少可以交换。考虑到缺乏可交换性,我们将检验统计量除以标准误差的估计值,从而将检验统计量转换为 t 统计量。这个“学生化”过程允许我们对不可交换的数据进行自相关测试。

但是,排列测试实际上是如何工作的呢?

让我们慢一点,真正理解排列测试…

排列测试 101

排列测试非常简单,但是惊人的强大。

排列检验的目的是估计总体分布、**、**我们的观察值来自的分布。从那里,我们可以确定我们的观察值相对于总体是多么稀少。

在图 2 中,我们看到了排列测试的图形表示。有 5 个观察值,由每一行和两个感兴趣的列表示,风险死亡

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

图 2:排列测试的框架。图片作者。

首先,我们开发了我们感兴趣的变量的许多排列,标记为 P1,P2,…,P120。在这一步的最后,我们将从我们的总体中获得大量的理论数据。然后将这些图结合起来估计人口分布。

请注意,我们永远不会看到重复的排列— 排列测试对所有可能的排列进行采样,而不进行替换。

其次,我们可以计算我们的 p 值。使用中位数作为我们的测试统计量(尽管它可以是从我们的数据中得到的任何统计量),我们将遵循以下步骤:

  1. 计算观察数据的中位数(死亡数列)。
  2. 对于每个排列,计算中间值。
  3. 确定比我们观察到的中位数更极端的排列中位数的比例。这个比例就是我们的 p 值。

如果你喜欢代码,这里有一些计算 p 值的 pythonic 伪代码:

permutations = permute(data, P=120)observed_median = median(data)
p_medians = [median(p) for p in permutations]p_val = sum(p > observed_median for p in p_medians) / len(p_medians)

既然我们理解了这个方法,让我们决定什么时候使用它。

排列检验的假设

排列测试之所以吸引人,是因为它们是非参数的,并且只需要假设可交换性。让我们依次讨论这两个概念。

参数方法假设了一个潜在的分布。非参数方法不会。就这么简单。

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

图 3:参数化和非参数化可视化。图片作者。

现在使用参数方法要求我们对数据的分布有信心。例如,在 A/B 测试中,我们可以利用中心极限定理得出结论,观察到的数据将呈现正态分布。从那里我们可以运行 t 检验,并获得 p 值。

然而,在其他情况下,我们无法知道分布,所以我们必须利用非参数方法。

出于测试目的,参数和非参数方法都估计总体分布。主要区别在于参数测试利用假设来创建分布,而非参数测试利用重采样。

太好了。让我们继续讨论可交换性。

可交换性指的是一系列随机变量。从形式上讲,如果一个序列的任意排列具有与原序列相同的联合概率分布,则该序列是可交换的。

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

图 4:一枚有偏见的硬币的形象化。图片作者。

因此,在图 4 中我们可以看到两枚硬币。左边的硬币是公平的,有 50%的正面(H)和 50%的反面(T)。正确的硬币有 60%的机会正面朝上。

如果我们多次抛硬币,我们会有一个可交换的序列。同样,如果我们多次投掷不公平的硬币,我们会有一个可交换的序列。然而,如果我们在公平和不公平硬币之间交替,我们将没有一个可交换的序列。

如果我们的数据生成机制(硬币)的分布发生变化,我们的序列不再可交换。

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

图 5:互换性的定义。图片作者。

在数学上,我们定义可交换性,如图 5 所示。左边的序列是原始数据,右边的序列是原始数据的排列。如果它们具有相同的分布,它们是可交换的。

时间序列相关性的排列检验

通常,时间序列数据是不可交换的——以前的值可能是未来值的决定因素。如果你有强有力的证据证明你的时间序列数据确实是可交换的,那么你可以运行一个常规的排列测试,但是如果没有,你需要利用下面的方法。

论文讨论了在时间序列数据集上运行自相关测试的方法,但是概念可以推广到其他测试。还要注意,对于所有值,自相关只是一个值和它的前一个值之间的相关性。

我们将简单地介绍一下这个方法,因为它非常非常复杂。但是,方法如下:

  1. 估计我们的自相关值的标准误差。
  2. 通过除以标准误差,将我们的统计转换为 t 统计。
  3. 做个 t 检验。

第 2 节概述了标准误差的计算,特别是等式 2.9 和 2.12。不幸的是,我们不打算在这里讨论它们,因为它们实在太长了。

摘要和实施说明

现在,您已经了解了置换测试的步骤,以及如何将它们应用于不可交换的时间序列数据的一些信息。

总而言之,排列测试很棒,因为它们是非参数的,并且只需要可交换性的假设。排列测试对我们的数据进行多种排列,以估计我们人口的分布。从那里,我们可以给我们观察到的数据分配一个 p 值。对于不可交换的时间序列数据,本文概述了一种方法。

最后,这里有一些关于实现的注意事项:

  • 当有许多行时,您不能开发所有可能的排列。取而代之的是,对那些没有替换的排列进行抽样,以估计分布。
  • 当样本量很小或者参数假设不满足时,排列检验是有效的。因为我们只要求可交换性,所以它们非常健壮。
  • 排列检验往往比参数检验给出更大的 p 值。
  • 如果你的数据在实验中是随机的,你可以使用一个简单的随机测试。
  • 时间序列自相关方法需要平稳数据。如果您的数据不稳定,请查看差异

感谢阅读!我会再写 34 篇文章,把学术研究带到 DS 行业。查看我的评论,链接到这篇文章的主要来源和一些有用的资源。

如何在 React 中使用 Plotly.js 来可视化您的数据并与之交互

原文:https://towardsdatascience.com/how-to-use-plotly-js-in-react-to-visualize-and-interact-with-your-data-ab4c2c67e8f6?source=collection_archive---------13-----------------------

简单易懂的教程

在 React 中使用 Plotly.js 的简短教程

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

卢卡斯·布拉塞克在 Unsplash 上的照片

几个月前,我写了一篇关于如何用 Python Plotly 可视化交互式 3D 网络(或数据)的教程,我想为 Plotly.js 再写一篇可能是个好主意

有人可能更喜欢 Plotly.js 而不是 Python Plotly 的原因之一可能是因为加载速度——我曾经编写过一个 React + Flask 应用程序(其中数据集和 Plotly 图形都在 Flask 上),当我将其与我的 React + Plotly.js 应用程序进行比较时,Plotly.js 的交互性和加载速度要好得多。

所以这里有一个快速教程,教你如何用 React 来使用 Plotly.js!ʕ•́ᴥ•̀ʔっ♡

本教程的最终代码可以在这个 GitHub 资源库中找到:https://GitHub . com/reine 0017/mini-Tutorials/tree/master/React-Tutorials/visualize-data-plot ly

让我们从一个基本的 React 应用程序开始。在所需的项目目录中,运行:

npx create-react-app .

然后运行:

npm start

来打开网页。

接下来,我们要安装 Plotly.js 库。您可以参考此链接获取安装说明。但是基本上,你只需要运行(从上面链接的 npm 包页面):

npm install react-plotly.js plotly.js

好了,现在安装已经完成,让我们开始写一些代码吧!

有大量不同的情节,地图和图表,你可以玩 Plotly。在本教程中,我们将了解如何使用 Plotly.js 创建一个简单的螺旋形交互式 3D 散点图。

让我们首先创建 Plotly 组件,然后导入 react-plotly 库。之后,只需像这样键入组件:

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

一旦我们将其导入到 App.js 文件中,

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

这是它带来的结果:

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

只是一个没有数据的空图(因为我们没有输入任何数据)

现在,让我们用一些数据填充图表。你可以去他们的官方网站看看你能用 Plotly 创建什么样的可视化效果。

由于我们想在本教程中创建一个螺旋 3D 图形,我们将首先获得该 3D 图形的 x、y 和 z 数据坐标:

接下来,让我们用这些数据填充我们的组件。

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

对于您想要的图表,您可以使用更多的参数。但在这种情况下,我只对它做了一些小的修改。下面是最终结果:

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

这个 3D 散点图是完全交互式的,当用户点击它时,您也可以配置某些动作。出于演示的目的,我将只让它在控制台记录它的坐标 onClick。

要注册用户的点击(在图中的坐标点上),我们可以写如下内容:

onClick={(data) => { console.log(data.points[0])}}

在组件内部。

下面是最终结果:

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

今天的教程到此为止!希望这是有帮助的,如果你有任何问题,请随时评论或给我发信息。谢谢你们读了这篇文章,很高兴

阴谋诡计!ʕ•́ᴥ•̀ʔっ♡

我真的不喜欢无耻的插头,但如果你已经在考虑每月 5 美元获得中等会员资格,如果你能使用我的推荐链接来注册,我会非常感激——https://reine-ran.medium.com/membership😃

如何在工业环境中使用 PointNet 实现 3D 计算机视觉

原文:https://towardsdatascience.com/how-to-use-pointnet-for-3d-computer-vision-in-an-industrial-context-3568ba37327e?source=collection_archive---------18-----------------------

我们如何使用来自工业 3D 传感器的数据测试 PointNet

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

来自 revopoint3d 的图像

三维计算机视觉

3D 计算机视觉是一个迷人的领域!

我们可以用多种形式在 3D 中表示 2D 的场景,而不是用一组像素值。

一些著名的形式:

  • 深度图像,也称为 RGBD,其中 D 代表深度。
  • 3D 点云,其中有一组在 3D 参考框架中表示的点。
  • 体素,我们将 3D 场景表示为一组立方体。
  • 网格,我们对 3D 点云进行三角剖分,以获得连接 3D 点的平滑三角形。

有很多经典算法使用 3D 图像来做各种很酷的应用,如增强现实。

但是深度学习已经在这个领域掀起了风暴(就像它在许多其他领域一样!).现在,我们有了神经网络,它正在取代经典算法,并大幅超越其性能。

3D 计算机视觉的深度学习

已经有几种方法将深度学习应用于 3D 图像。

一种著名的方法是名为 PointNet 的神经网络,它将 3D 点云作为输入。

这个网络可以用于几个任务:分类,语义分割和部分分割,如下图所示。

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

图片来自 PointNet paper [1]

网络的架构出奇的简单!

它将 N 个点作为一组无序的 3D 点。

它应用一些变换来确保点的顺序无关紧要。

然后,这些点通过一系列 MLP(多层感知器)和 max pooling 层,最终获得全局特征。

为了分类,这些特征然后被馈送到另一个 MLP,以获得代表 K 个类别的 K 个输出。

对于分割,添加另一个子神经网络以获得逐点分类。

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

图片来自原始纸张[1]

工业背景下的点网

PointNet 可以处理原始格式的 3D 点云。

这意味着许多行业可以将它与 3D 传感器结合使用。

我们和一些前同事一起对此进行了实验,并发表了一篇论文[2]概述了我们所做的一些实验。

实验的目标是尝试和分类 4 种不同类型的“工业支持”。这些“工业支架”可以在飞机底盘内找到。下图显示了 4 种类型的支架。

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

图片来自我们的论文[2]

我们学到了什么

我们做了几次实验来实现我们对这些点云进行分类的目标。我们没有太多的数据,所以我们必须找到允许我们利用有限数据集进行深度学习的方法。下文提到了一些重要的调查结果。

1.具有不完美三维点云的点网

我们发现,即使点云远非完美,也可以对使用工业 3D 传感器获得的点云应用 PointNet。例如,在下图中,您可以在左侧看到某个场景的 2D 图像,在右侧看到表示同一场景的 3D 点云,这些点云是使用 3D 工业传感器获取的。正如你可以清楚地看到,收购远非完美。但即使是这样的收购,我们也能得到一些非常有趣的结果。

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

图片来自我们的论文[2]

2.迁移学习可以用在 3D 点云上,就像在 2D 图像上一样

由于我们的数据量有限,我们尝试对 3D 点云使用迁移学习,就像对 2D 图像一样。

我们使用了一个名为 ModelNet40 的数据集,它由 12000 多个 CAD 模型组成,分为 40 个类。我们首先在这个数据集上训练 PointNet,然后在我们的小数据集上对它进行微调。下表显示了我们利用迁移学习获得的一些结果。我们实现了一些非常高的精度!

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

图片来自我们的论文[2]

3.影响点网性能的重要因素

当涉及到性能时,输入点云中包含的点数可能是一个重要因素。由于我们可以控制输入点云的大小,我们用几个值进行了实验,我们发现根据这个数字,精度可以变得非常高或非常低。这是有意义的,因为我们的点云已经不完美,所以当我们对它们进行缩减采样时,我们会丢失更多信息,而这些信息对于通过点网学习良好的特征可能是有价值的。

我们发现另一个非常重要的因素是用于获得 PointNet 最终输入的采样算法的类型。

从点的数量来看,来自 3D 传感器的原始点云可能非常大,因此我们总是需要对它们进行下采样。为此,我们使用了 2 种不同的算法:随机采样和 f *最优点采样(FPS)。*后一种算法擅长保留对结果产生积极影响的有意义的云结构。

结论

在本文中,我们介绍了 PointNet,一种用于 3D 点云的深度神经网络,如何用于来自工业传感器的 3D 数据。我们看到了它是如何用于将点云分成 4 个不同的类别,即使它们是不完美的。我们还看到了一些因素,如输入点的数量和采样算法的类型如何影响结果。

参考

[1]查尔斯·r·齐,,凯春莫,列奥尼达·j·吉巴斯." PointNet:用于三维分类和分割的点集深度学习"

[2]伊万·米哈伊洛夫、伊戈尔·约万切维奇、努尔·伊斯拉姆·莫赫塔里、让-何塞·奥尔特乌。“在结构化工业环境中使用三维传感器进行分类

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

作者制作的图像

我是一名机器学习工程师,致力于解决具有挑战性的计算机视觉问题。我想帮助你学习应用于计算机视觉问题的机器学习。以下是方法。

  1. 通过帮助您了解该领域的最新动态。我几乎每天都在 、LinkedIn、Twitter****上分享小型博客帖子。那就跟我去吧!
  2. 每周给你一份我的 时事通讯 上那些琐碎帖子的摘要。所以订阅吧!
  3. 通过在 Medium 上写关于机器学习不同主题的文章。所以跟我来吧!
  4. 给你一份免费的机器学习工作清单,帮助你检查你需要学习的所有要点,如果你计划在 ML,特别是在计算机视觉方面的职业生涯。你可以在这里 获得核对表

5.最后但同样重要的是,通过与你分享我的 免费入门张量流课程 ,它有超过 4 小时的视频内容,你可以在那里问我任何问题。

此外,如果您有任何问题或者您只是想聊聊 ML,请随时在 LinkedIn 或 Twitter 上联系我!

如何使用泊松分布像你知道你在做什么

原文:https://towardsdatascience.com/how-to-use-poisson-distribution-like-you-know-what-you-are-doing-c095c1e477c1?source=collection_archive---------15-----------------------

幸运的是,这些情况下有泊松分布

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

照片由 安德里亚·皮亚卡迪奥 发自 像素

故事

你从事自由职业已经 10 年了。到目前为止,你的平均年收入大约是 80,000 美元。今年,你觉得自己停滞不前,决定达到 6 位数。为了做到这一点,你想从计算这个令人兴奋的成就发生的概率开始,但你不知道如何去做。

事实证明,你并不孤单。在这个世界上,有许多情况下,某个随机事件的发生率是已知的,而企业希望找到该事件在未来发生的几率是高于还是低于这个发生率。

例如,已经知道自己平均销售额的零售商会试图猜测他们在黑色星期五或网络星期一等特殊日子会多赚多少钱。这将帮助他们储存更多的产品,并相应地管理他们的员工。

在本帖中,我们将讨论泊松分布背后的直觉,泊松分布用于模拟上述情况,如何理解和使用它的公式,以及如何使用 Python 代码模拟它。

https://ibexorigin.medium.com/membership

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

https://alphasignal.ai/?referrer=Bex

离散概率分布

这篇文章假设你对概率有基本的了解。如果没有,请查看这篇伟大的文章。

在我们开始这篇文章的真正内容之前,我们将对离散概率分布有所了解。

首先,让我们定义什么是离散的。在描述统计学中,离散数据是通过计数记录或收集的任何数据,即整数。例如考试成绩、停车场的汽车数量、医院的分娩数量等。

然后,有随机实验,有离散的结果。例如,掷硬币有两种结果:正面和反面(1 和 0),滚动骰子有 6 种不连续的结果,等等。如果一个随机变量 X 被用来存储一个离散实验的可能结果,它将有一个离散的概率分布。

概率分布记录了随机实验的所有可能结果。

举一个简单的例子,让我们建立一次抛硬币的分布:

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

那很容易。如果我们想以编程的方式记录分布,它应该是 Python 列表或 Numpy 数组的形式:

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

然而,你可以想象,对于有许多可能结果的大型实验来说,以这种方式构建分布并找到概率变得不可能。值得庆幸的是,每一个发明的概率分布都有自己的公式来计算任何结果的概率。对于离散概率分布,这些函数被称为概率质量函数(PMF)。更详细的解释,请阅读我在上一篇关于离散分布的文章

泊松分布

我们将通过案例研究开始理解泊松分布。说你真的很喜欢在医院里看新生儿。根据您的观察和报告,您知道医院平均每小时观察 6 名新生儿。

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

照片由米哈尔·巴尔·哈伊姆Unsplash 拍摄

你发现你明天要出差,所以在去机场之前,你想最后一次去医院。因为你要离开几个月,你想看到尽可能多的新生儿,所以你想知道在飞机起飞前一小时看到 10 个或更多婴儿的可能性。

如果我们将观察新生婴儿视为随机实验,结果将遵循经典的泊松分布。原因是它满足泊松分布所需的所有条件:

  • 有一个已知的事件发生率:平均每小时 6 个新生儿
  • 事件独立发生:一个婴儿的出生不影响下一个的时间
  • 已知的比率是不变的:每小时婴儿的平均数量不会随着时间而改变
  • 两件事不会在完全相同的时刻发生
  • (提醒:每个结果都是独立的)

泊松分布有许多重要的商业含义。企业通常使用它来预测特定一天的销售额或客户数量,因为他们知道平均日费率。做出这样的预测有助于企业在生产、调度或人员配备方面做出更好的决策。例如,库存过多意味着低销售活动的损失,或者没有足够的货物意味着失去商业机会。

简而言之,泊松分布有助于发现事件在固定时间间隔内发生的概率大于或小于已经记录的比率(通常表示为 λ (lambda) )。

其概率质量函数由以下公式给出:

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

在哪里

  • k 是成功的次数(期望事件发生的次数)
  • λ是给定的速率
  • e 是欧拉数:e = 2.71828…
  • *k!*是 k 的阶乘

如果你仍然对 PMFs 感到不舒服,请阅读我的上一篇文章

使用这个公式,我们可以发现看到 10 个新生婴儿的概率,知道平均比率是 6:

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

不幸的是,只有 4%的机会看到 10 个婴儿。

我们不会详细讨论这个公式是如何推导出来的,但是如果你好奇,可以看看汗学院的这个视频。

仍然有一些要点你必须记住。尽管有一个已知的比率,但它只是一个平均值,所以事件发生的时间完全是随机的。例如,你可以连续观察两个婴儿的出生,或者你可能要等半个小时才能看到下一个。

此外,在实践中,速率λ可能不总是恒定的。这甚至可以适用于我们的新生儿实验。即使这个条件不成立,我们仍然可以将分布视为泊松分布,因为泊松分布足够接近来模拟情况的行为。

模拟泊松分布

使用numpy从泊松分布中模拟或抽取样本非常容易。我们首先导入它并使用它的random模块进行模拟:

import numpy as np

为了从泊松分布中抽取样本,我们只需要速率参数 λ 。我们将它插入np.random.poisson函数,并指定样本数:

poisson = np.random.poisson(lam=10, size=10000)

这里,我们模拟一个比率为 10 的分布,有 10k 个数据点。为了看到这种分布,我们将绘制其 PMF 的结果。虽然我们可以手工完成,但是已经有一个非常好的库叫做empiricaldist,作者是 Allen B. Downey,他是著名书籍的作者,比如 ThinkPythonThinkStats 。我们将在我们的环境中安装并导入它的Pmf函数:

from empiricaldist import Pmf  # pip install empiricaldist

Pmf有一个名为from_seq的函数,它接受任意分布并计算 PMF:

poisson = np.random.poisson(lam=10, size=10000)pmf_poisson = Pmf.from_seq(poisson)
pmf_poisson

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

回想一下,PMF 显示了每个独特结果的概率,所以在上面的结果中,结果在probs下作为指数和概率给出。让我们使用matplotlib来绘制它:

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

正如所料,最高概率是平均值(速率参数,λ)。

现在,让我们假设我们忘记了泊松分布的 PMF 公式。如果我们正在做观察新生儿的实验,我们将如何发现看到 10 个新生儿的概率为 6?

首先,我们用给定的利率作为参数来模拟完美的泊松分布。此外,我们确保抽取大量样本以提高准确性:

我们正在对一个比率为 6、长度为 100 万的分布进行抽样。接下来,我们发现他们中有多少人生了 10 个孩子:

所以,我们在 41114 次试验中观察了 10 个婴儿(每个小时可以认为有一次试验)。然后,我们将这个数字除以样本总数:

>>> births_10 / 1e60.041114

如果你记得,使用 PMF 公式,结果是 0.0413,我们可以看到,我们的手动编码解决方案是一个非常接近的匹配。

结论

关于泊松分布还有很多要说的。我们讨论了基本用法及其在商业世界中的含义。泊松分布仍然有有趣的部分,例如它如何与二项式分布相关。为了全面理解,我建议阅读这些高质量的文章,它们也有助于我对该主题的理解:

如何使用 py caret——低代码 ML 的库

原文:https://towardsdatascience.com/how-to-use-pycaret-the-library-for-lazy-data-scientists-91343f960bd2?source=collection_archive---------3-----------------------

入门

用最少的代码训练、可视化、评估、解释和部署模型

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

Armando ArauzUnsplash 上拍摄的照片

当我们处理有监督的机器学习问题时,很容易看到随机森林或梯度推进模型的表现,如果我们对结果满意,就停止实验。如果只用一行代码就能比较许多不同的模型,会怎么样?如果您可以将数据科学过程中从功能工程到模型部署的每一步都减少到只有几行代码,那会怎么样?

这正是 PyCaret 发挥作用的地方。PyCaret 是一个高级的低代码 Python 库,只需几行代码就可以轻松比较、训练、评估、调优和部署机器学习模型。在其核心,PyCaret 基本上只是许多数据科学库的大型包装器,如 Scikit-learn、Yellowbrick、SHAP、Optuna 和 Spacy。是的,您可以使用这些库来完成相同的任务,但是如果您不想编写大量代码,PyCaret 可以为您节省大量时间。

在本文中,我将演示如何使用 PyCaret 快速轻松地构建一个机器学习项目,并为部署准备最终模型。

正在安装 PyCaret

PyCaret 是一个有很多依赖项的大型库。我建议使用 Conda 专门为 PyCaret 创建一个虚拟环境,这样安装不会影响任何现有的库。要在 Conda 中创建和激活虚拟环境,请运行以下命令:

conda create --name pycaret_env python=3.6
conda activate pycaret_env

要安装默认的较小版本的 PyCaret,并且只安装所需的依赖项,可以运行以下命令。

pip install pycaret

要安装 PyCaret 的完整版本,您应该改为运行以下命令。

pip install pycaret[full]

安装 PyCaret 后,停用虚拟环境,然后使用以下命令将其添加到 Jupyter。

conda deactivate
python -m ipykernel install --user --name pycaret_env --display-name "pycaret_env"

现在,在您的浏览器中启动 Jupyter 笔记本后,您应该能够看到将您的环境更改为您刚刚创建的环境的选项。

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

改变 Jupyter 中的 Conda 虚拟环境。

导入库

您可以在这个 GitHub 资源库中找到本文的完整代码。在下面的代码中,我简单地导入了 Numpy 和 Pandas 来处理这个演示的数据。

import numpy as np
import pandas as pd

读取数据

对于这个例子,我使用了 Kaggle 上的加州房价数据集。在下面的代码中,我将这个数据集读入一个数据帧,并显示该数据帧的前十行。

housing_data = pd.read_csv('./data/housing.csv')
housing_data.head(10)

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

住房数据集的前十行。

上面的输出让我们了解了数据的样子。数据主要包含数字特征,其中一个分类特征表示每栋房屋与海洋的距离。我们试图预测的目标列是 median_house_value 列。整个数据集总共包含 20,640 个观察值。

初始化实验

现在我们有了数据,我们可以初始化一个 PyCaret 实验,它将预处理数据并为我们将在这个数据集上训练的所有模型启用日志记录。

from pycaret.regression import *reg_experiment = setup(housing_data, 
                       target = 'median_house_value', 
                       session_id=123, 
                       log_experiment=True, 
                       experiment_name='ca_housing')

如下面的 GIF 所示,运行上面的代码预处理数据,然后生成一个带有实验选项的数据帧。

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

Pycaret 设置函数输出。

比较基线模型

我们可以一次比较不同的基线模型,用下面的代码所示的 compare_models 函数找到实现最佳 K 倍交叉验证性能的模型。出于演示的目的,我在下面的例子中排除了 XGBoost。

best_model = compare_models(exclude=['xgboost'], fold=5)

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

不同模型的比较结果。

该函数生成一个数据框,其中包含每个模型的性能统计数据,并突出显示性能最佳的模型的指标,在本例中是 CatBoost 回归器。

创建模型

我们也可以用 PyCaret 只用一行代码训练一个模型。create_model 函数只需要一个与您想要训练的模型类型相对应的字符串。您可以在这个函数的 PyCaret 文档页面上找到可接受字符串和相应回归模型的完整列表。

catboost = create_model('catboost')

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

c reate_model 函数生成上面的数据帧,其中包含已训练的 CatBoost 模型的交叉验证指标。

超参数调谐

现在我们有了一个训练好的模型,我们可以通过超参数调整进一步优化它。只需一行代码,我们就可以调整这个模型的超参数,如下所示。

tuned_catboost = tune_model(catboost, n_iter=50, optimize = 'MAE')

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

10 倍交叉验证的超参数调整结果。

最重要的结果,在本例中是平均指标,用黄色突出显示。

可视化模型的性能

我们可以使用 PyCaret 创建许多图表来可视化模型的性能。PyCaret 使用另一个名为 Yellowbrick 的高级库来构建这些可视化。

残差图

默认情况下, plot_model 函数将为回归模型生成残差图,如下所示。

plot_model(tuned_catboost)

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

调整后的 CatBoost 模型的残差图。

预计误差

我们还可以通过创建预测误差图,将预测值与实际目标值进行对比。

plot_model(tuned_catboost, plot = 'error')

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

调整后的 CatBoost 回归器的预测误差图。

上面的图特别有用,因为它为我们提供了 CatBoost 模型的 R 系数的可视化表示。在理想情况下(R = 1),预测值与实际目标值完全匹配,该图将只包含沿单位虚线的点。

特征重要性

我们还可以可视化模型的特征重要性,如下所示。

plot_model(tuned_catboost, plot = 'feature')

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

CatBoost 回归器的特征重要性图。

根据上面的图,我们可以看到中值收入特征是预测房价时最重要的特征。由于这一特征对应于房屋所在区域的中值收入,因此这一评估非常合理。建造在高收入地区的房子可能比低收入地区的房子更贵。

使用所有地块评估模型

我们还可以用 evaluate_model 函数创建多个图来评估一个模型。

evaluate_model(tuned_catboost)

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

使用 evaluate_model 函数创建的接口。

解释模型

解释模型函数是解释模型预测的有用工具。这个函数使用一个名为 SHAP 的可解释机器学习库,我在下面的文章中提到过。

只用一行代码,我们就可以为模型创建一个 SHAP 蜂群图

interpret_model(tuned_catboost)

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

通过调用解释模型函数生成的 SHAP 图。

根据上图,我们可以看到中值收入字段对预测的房价影响最大。

AutoML

PyCaret 还有一个运行自动机器学习(AutoML)的函数。我们可以指定想要优化的损失函数或度量,然后让库接管,如下所示。

automl_model = automl(optimize = 'MAE')

在这个例子中,AutoML 模型碰巧也是一个 CatBoost 回归器,我们可以通过打印出模型来确认这一点。

print(automl_model)

运行上面的 print 语句会产生以下输出:

<catboost.core.CatBoostRegressor at 0x7f9f05f4aad0>

生成预测

predict_model 函数允许我们通过使用来自实验的数据或新的未知数据来生成预测。

pred_holdouts = predict_model(automl_model)
pred_holdouts.head()

上面的 predict_model 函数为用于在交叉验证期间验证模型的维持数据集生成预测。该代码还为我们提供了一个数据框架,其中包含由 AutoML 模型生成的预测的性能统计数据。

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

AutoML 模型生成的预测。

在上面的输出中,标签列表示 AutoML 模型生成的预测。我们还可以对整个数据集进行预测,如下面的代码所示。

new_data = housing_data.copy()
new_data.drop(['median_house_value'], axis=1, inplace=True)
predictions = predict_model(automl_model, data=new_data)
predictions.head()

保存模型

PyCaret 还允许我们用 save_model 函数保存训练好的模型。该函数将模型的转换管道保存到 pickle 文件中。

save_model(automl_model, model_name='automl-model')

我们也可以用 load_model 函数加载保存的 AutoML 模型。

loaded_model = load_model('automl-model')
print(loaded_model)

打印加载的模型会产生以下输出:

Pipeline(memory=None,
         steps=[('dtypes',
                 DataTypes_Auto_infer(categorical_features=[],
                                      display_types=True, features_todrop=[],
                                      id_columns=[], ml_usecase='regression',
                                      numerical_features=[],
                                      target='median_house_value',
                                      time_features=[])),
                ('imputer',
                 Simple_Imputer(categorical_strategy='not_available',
                                fill_value_categorical=None,
                                fill_value_numerical=None,
                                numer...
                ('cluster_all', 'passthrough'),
                ('dummy', Dummify(target='median_house_value')),
                ('fix_perfect', Remove_100(target='median_house_value')),
                ('clean_names', Clean_Colum_Names()),
                ('feature_select', 'passthrough'), ('fix_multi', 'passthrough'),
                ('dfs', 'passthrough'), ('pca', 'passthrough'),
                ['trained_model',
                 <catboost.core.CatBoostRegressor object at 0x7fb750a0aad0>]],
         verbose=False)

从上面的输出中我们可以看到,PyCaret 不仅在管道的末端保存了训练好的模型,还在管道的开始保存了特征工程和数据预处理步骤。现在,我们在单个文件中有一个生产就绪的机器学习管道,我们不必担心将管道的各个部分放在一起。

模型部署

既然我们已经有了准备生产的模型管道,我们也可以使用 deploy_model 函数将模型部署到云平台,比如 AWS。在运行此功能之前,如果您计划将模型部署到 S3 存储桶,则必须运行以下命令来配置 AWS 命令行界面:

aws configure

运行上面的代码将触发一系列信息提示,比如您需要提供的 AWS Secret Access Key。一旦这个过程完成,您就可以使用 deploy_model 函数部署模型了。

deploy_model(automl_model, model_name = 'automl-model-aws', 
             platform='aws',
             authentication = {'bucket' : 'pycaret-ca-housing-model'})

在上面的代码中,我将 AutoML 模型部署到 AWS 中名为py caret-ca-housing-model的 S3 桶中。从这里,您可以编写一个 AWS Lambda 函数,从 S3 获取模型并在云中运行。PyCaret 还允许您使用 load_model 函数从 S3 加载模型。

MLflow UI

PyCaret 的另一个很好的特性是,它可以用一个名为 MLfLow 的机器学习生命周期工具来记录和跟踪你的机器学习实验。运行以下命令将从本地主机在您的浏览器中启动 MLflow 用户界面。

!mlflow ui

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

MLFlow 仪表板。

在上面的仪表板中,我们可以看到 MLflow 为您的 PyCaret 实验跟踪不同模型的运行。您可以查看性能指标以及实验中每次运行的运行时间。

使用 PyCaret 的利弊

如果您已经读到这里,那么您现在已经对如何使用 PyCaret 有了基本的了解。虽然 PyCaret 是一个很棒的工具,但是如果您计划将它用于您的数据科学项目,您应该了解它的优缺点。

赞成的意见

  • 低代码库。
  • 非常适合简单的标准任务和通用机器学习。
  • 为回归、分类、自然语言处理、聚类、异常检测和关联规则挖掘提供支持。
  • 使得为模型创建和保存复杂的转换管道变得容易。
  • 使可视化模型的性能变得容易。

骗局

  • 到目前为止,PyCaret 对于文本分类并不理想,因为 NLP 实用程序仅限于主题建模算法。
  • PyCaret 对于深度学习并不理想,并且不使用 Keras 或 PyTorch 模型。
  • 你不能用 PyCaret(至少在 2.2.0 版本下)执行更复杂的机器学习任务,比如图像分类和文本生成。
  • 通过使用 PyCaret,您为简单和高级代码牺牲了一定程度的控制。

摘要

在本文中,我演示了如何使用 PyCaret 来完成机器学习项目中的所有步骤,从数据预处理到模型部署。虽然 PyCaret 是一个有用的工具,但是如果您计划将它用于您的数据科学项目,您应该了解它的优缺点。PyCaret 非常适合使用表格数据的通用机器学习,但从 2.2.0 版本开始,它不是为更复杂的自然语言处理、深度学习和计算机视觉任务而设计的。但它仍然是一个节省时间的工具,谁知道呢,也许开发者将来会增加对更复杂任务的支持?

正如我之前提到的,你可以在 GitHub 上找到这篇文章的完整代码

加入我的邮件列表

你想在数据科学和机器学习方面变得更好吗?您想了解数据科学和机器学习社区的最新图书馆、开发和研究吗?

加入我的邮件列表,获取我的数据科学内容的更新。当你注册时,你还会得到我免费的解决机器学习问题的逐步指南

来源

  1. 米(meter 的缩写))Ali, PyCaret:一个用 Python 编写的开源低代码机器学习库,(2020),PyCaret.org。
  2. 南 M. Lundberg,S. Lee,解释模型预测的统一方法,(2017),神经信息处理系统进展 30 (NIPS 2017)。

如何使用 Python 和 Tableau 分析数码照片元数据

原文:https://towardsdatascience.com/how-to-use-python-and-tableau-to-analyze-digital-photo-metadata-e4d4a744b6a4?source=collection_archive---------26-----------------------

本文分享了一个 Python 程序,它使用 exifread 模块读取数字图像文件中的元数据,并使用 Tableau Public 分析细节

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

成熟的秃鹰。图片由作者提供。

介绍

假设你是一名专门拍摄猛禽的野生动物摄影师,比如老鹰、老鹰和猎鹰。你更喜欢捕捉飞行中的鸟的图像(BIF),尤其是当它们捕获猎物的时候。今天,你站在密西西比河明尼苏达州一侧的河岸上,在佩平湖的下游,紧接着穿过 T2 奇普瓦河口的海峡,在那里流入浩瀚的密西西比河。当秃鹰在水下捕鱼时,你的超长焦镜头对准了它们。

现在,假设您想要分析您在过去十年中拍摄的鸟类照片。不久以前,当被摄对象用胶片拍照时,关于每张照片的信息都是以模拟的形式被记录在胶片上,记录在摄影师的头脑中,也许还被摄影师记录在纸上。相比之下,今天,专用数码相机或智能手机相机记录丰富详细的数字化图像和关于它们的各种元数据。

本文向您展示了如何编写一个 Python 程序,从数码照片文件中提取元数据。然后,它会查找每张照片拍摄日期的日出和日落时间。最后,它将数据写入 CSV 文件,每张照片一条记录。本文还描述了一个 Tableau 公共工作簿,它使用 CSV 文件来组织、查看和分析其中包含的照片元数据。

数码照片元数据

当你点击数码相机或智能手机上的快门按钮时,该设备会将来自照片传感器的图像的详细数据写入数字媒体上的文件,如相机的 SD 卡或智能手机的内存。该文件包含在显示器上重建图像所需的数据和元数据,元数据是关于图像的数据。照片编辑软件,如 Adobe Lightroom 和 Photoshop、Microsoft Photos 或 Google Photos,使用图像数据和元数据。用 Python 和其他语言编写的自定义程序也可以读取这些类型的数据。

数码照片元数据以一种标准格式存储,这种格式称为可交换图像文件格式,通常称为 Exif。有关 Exif 结构中包含的字段列表,请参阅由 CIPA 相机和成像产品协会出版的 Exif 标准的第 42 页。

存储在每个照片文件中的元数据包括与图像相关的值,如日期和时间、相机的品牌和型号以及镜头的品牌和型号。它还包括曝光信息,包括快门速度、感光度(ISO)和光圈(F 档)。

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

大白鹭。图片由作者提供。

本文的案例

当我想象这篇文章时,我想象它将描述一个数据分析项目,它将帮助我确定一天中拍摄鸟类的最佳时间。但它变得更多了。它帮助我理解和反思我的鸟类摄影习惯、技巧和偏好。这可能会支持我拍摄更好的鸟类照片并经常拍摄的目标。

照片

为了获得 1,000 多张鸟类照片供该程序处理并与 Tableau Public 一起分析,我在 Adobe Lightroom 中搜索了超过 30,000 张照片的目录,以找到符合这些标准的图像文件:

  • 星级 2/5—每次拍照后,我会将相机 SD 卡上的照片导入 Lightroom。下一步是后处理,包括检查照片,删除那些模糊、构图不佳或其他不理想的照片,编辑其余的照片,并给每张照片打分。评级是主观的,基于我对照片的喜欢程度,从 1 星到 5 星,其中 1 是可接受的,5 是优秀的。对于这个项目,我选择了评分为 2 或更高的照片。
  • RAW 的图像类型——用我的 DSLR 或无反光镜相机,我以 RAW 模式拍摄所有照片,这从传感器捕捉了尽可能多的图像细节。另一种方法是将图像捕获为 JPEG 文件。JPEG 文件是可以接受的,但就其性质而言,相机已经处理并试图优化每张照片,并将其压缩为 JPEG 格式。
  • 鸟的关键词 —在一张鸟的照片之后,我的意图是给每张饲养员的照片加上关键词“鸟”。如果时间允许,我会添加其他关键词,如物种、性别和颜色。这些关键字将帮助我以后搜索和找到鸟类图片。

在这个项目中,我排除了那些我认为是在离家很远的地方拍摄的照片。因为我的相机中设置的日期和时间是当地时区(在我的情况下是美国中部时间),该时区的日期和时间值被写入每个图像文件。包含我所在时区以外的图片可能会扭曲数据分析的结果。

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

过滤要从 Lightroom 导出的鸟类照片图像文件。图片由作者提供。

本项目中使用的软件

我为这个项目使用了下面列出的软件。

  • Windows 10 操作系统——我在大部分专业和个人电脑工作中使用 Windows。
  • Adobe Lightroom —我的照片存储在 Adobe Lightroom 的云中(Creative Cloud 版本)。图像 JPEG (*。jpg)文件从 Lightroom 导出,由稍后描述的 Python 程序进行处理。你使用的任何照片编辑软件都可以正常工作。
  • Python 3.9.2 编程语言—Python 3 的任何最新版本都应该可以工作。
  • Visual Studio 社区 —我用过很多版本的微软 Visual Studio。社区版免费。
  • Tableau Public —我在 Tableau Public 工作簿的两个仪表板中创建了这个项目中显示的图表。Tableau Public 是流行且强大的 Tableau 商业智能和数据可视化工具的免费版本。公共版本在这个项目中运行良好。但是它的主要限制是只能从有限的文件类型中读取数据,并且只能将工作簿保存到 Tableau 公共服务器。这意味着世界上的任何人都可以查看您使用 Tableau Public 创建的可视化效果。
  • Windows 记事本 —我用记事本查看 Python 程序创建的 CSV 文件。任何文本或代码编辑器都可以。

关于软件和操作系统的说明:

Python 语言应该可以在任何现代操作系统上工作,包括 Mac OS、Linux 和 Windows。Lightroom 和 Tableau Public 版本适用于 Mac OS 和 Windows。虽然微软发布了一个版本的 Visual Studio for Mac OS,但它不支持 Python。但是几乎任何代码编辑器或集成开发环境(IDE)都可以工作。记事本是特定于 Windows 的,但每个操作系统都支持工具来读取文本文件,如程序创建的 CSV 文件。

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

沙丘鹤。图片由作者提供。

程序中使用的 Python 模块

以下是程序中使用的 Python 模块的列表,以及如何使用它们的描述:

  • 星体 —获取日期和时区的日出和日落。
  • csv—从每个图像文件的 Exif 数据结构中选择元数据写入 CSV 文件。
  • 日期时间 —从日期时间值中提取日期。
  • Exif Read—从保存为 JPEG 格式的图像中读取 Exif 数据(。JPG)文件。****
  • os —获取一个目录下的镜像文件的名称。
  • pytz—将日出和日落日期时间值从协调世界时(UTC)转换为美国中部时区。这允许相对于拍摄每张照片的日期和时间来确定日出和日落的日期时间值。

代码

该程序的代码分为两个模块。控制器模块运行程序,一个名为 c_photo_exif 的类完成这项工作。这些模块将在以下章节中介绍和显示。

控制器模块

用 C 语言编写的程序有一个 main()函数作为它们的入口点。在 Python 中,我喜欢把入口点称为控制器。这是因为它控制着程序的整体流程。photo_exif_controller.py 文件作为这个程序的入口点和控制器。

为了读取图像文件,控制器使用以下值调用 c_photo_exif 类的构造函数(init()):

  • 包含要读取的图像文件的目录的名称。
  • 程序将为每个图像文件写入记录元数据的 CSV 文件的名称。
  • 离照片拍摄地最近的城市。
  • 照片拍摄地的时区。

编写这个程序时假设输入目录中的所有照片都是在大致相同的位置拍摄的。稍后将描述克服这一限制的潜在增强。

c_photo_exif Python 类

文件 c_photo_exif.py 中的 c_photo_exif Python 类是程序的引擎。它执行以下任务:

  1. 创建一个 CSV 输出文件,并写入其列名。
  2. 遍历指定目录中的图像文件。
  3. 从每个文件的 Exif 结构中获取图像元数据。
  4. 获取每张照片拍摄当天的日出和日落日期时间值。
  5. 将数据写入 CSV 文件。

注意: 由于 c_photo_exif 类的内容大约有 150 行长,所以显示在下面的附录 a 中。

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

CSV 文件中的照片 Exif 数据。图片由作者提供。

潜在的计划改进和增强

潜在的改进

与大多数概念验证(POC)程序一样,这个程序只执行满足特定需求所需的基本任务。在本例中,它从一组图像文件中读取 Exif 数据,获取与每张照片拍摄日期相关的日出和日落日期时间值,并将数据写入 CSV 文件供以后使用。以下是可对程序进行的潜在改进,以使其为生产做好准备:

  • 添加错误处理,这样当出现严重错误(如磁盘故障)时,程序可以正常关闭或重试。
  • 将消息写入日志文件以捕获重要事件,如程序开始时间、结束时间、错误消息和处理的图像文件数量。

潜在的改进

虽然该程序执行其预期的功能,但它可以被增强以服务于额外的用途。以下是一些想法:

  • 将输出数据写入关系数据库表,而不是 CSV 文件。根据需要,将数据写入数据库而不是 CSV 文件可以提供一些优势,例如性能和消除创建重复记录的可能性。
  • 从图像文件中获取附加数据。在本例中,写入输出 CSV 文件的所有内容都是从操作系统(文件名)、每个图像文件中的 Exif 数据结构以及 Astral Python 模块中的日出和日落数据时间值中捕获的。其他有用的数据,如关键字、评级、标题和说明,可能存在于每个图像文件中。我打算学习如何获得这些数据,并在下一篇文章中介绍它们。
  • 将输出数据写入 Tableau 超文件。在这个项目中,Tabeau Pulic 工作簿从 CSV 文件中读取图像元数据,而 Tableau Creator 桌面工作簿可以直接从以 Tableau 专有的 hyperfile 格式编写的文件中获取数据。
  • 为上下文添加其他数据。例如,如果每个鸟类图像文件在标题或关键字字段中包含物种的名称,则可以从单独的数据存储库中获得物种的描述,并将其写入 CSV 文件。

Tableau 公共工作簿

我在这个项目的数据分析部分使用了 Tableau Public。Python 程序编写的 CSV 文件充当 Tableau 工作簿的数据源。使用 Tableau 创建工作表、视觉效果和仪表板的说明超出了本文的范围。但是这两个仪表盘被公布在 Tableau 公共网站上的一个名为鸟类摄影数据分析的工作簿中。请随意下载工作簿,修改它,并将其与您的数码照片的元数据集成在一起。

鸟类照片概览仪表板

这个仪表盘显示了我自 2012 年以来拍摄鸟类的相机的使用数据。它还按镜头长度、快门速度、光圈和 ISO 显示照片数据。

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

Tableau 公共照片图表。图片由作者提供。

按月份和小时显示的鸟类照片

这显示了相机在这些时间段拍摄的照片数量:

  • 一年中的月份
  • 一天中的某个时刻
  • 相对于日出的拍摄时间
  • 相对于日落的拍摄时间

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

Tableau 公共照片图表。图片由作者提供。

我学到了什么教训?

摄影和拍摄好照片是我生活中重要的组成部分。和大多数追求一样,我希望随着时间的推移提高自己的技能和成果。以下是我从这个项目中学到的一些经验,或者直接通过观察数据,或者间接地作为催化剂来反思我多年来的鸟类摄影经历。我想提高我的技术来增加我的守门员比例和图像质量。

  • 在相机中设置当地时间 —因为当我离家旅行时,我已经将相机中的日期和时间重置为当地时间,所以我不能总是可靠地确定特定照片是何时拍摄的。从现在起,每当我离开我的时区时,我打算将相机的时间设置为当地时间。幸运的是,有了智能手机,时间会自动改变。
  • 在 Lightroom 中或通过智能手机应用程序为每张照片添加位置信息——直到我进行了这项分析,我才意识到时间和位置数据可以如此紧密地联系在一起。从现在开始,我会在导入后立即将位置信息记录到 Lighroom 中的 keeper photos。我还会尝试使用智能手机上的尼康 SnapBridge 应用程序来自动捕捉每张照片的拍摄位置。
  • 为更多的守护者使用最高合理的快门速度 —摄影的一个经验法则是将快门速度设置为镜头焦距的倒数或更高。使用这个规则,700 毫米的焦距保证了 1/700 秒的快门速度。但是设置快门速度涉及到许多变量。例如,相机或镜头可能具有图像稳定功能,这有助于在较低的快门速度下捕捉清晰的图像。另一方面,在鸟类摄影中,拍摄对象通常很远且在移动,因此可能需要更快的快门速度来获得清晰的图像。为了获得更清晰的鸟类照片,我会尝试将快门速度提高到经验法则的倒数以上,无论是使用图像稳定、三脚架还是单脚架。

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

雌性红翅乌鸫。图片由作者提供。

下一步是什么?

也许,通过这篇文章,您已经想到了将摄影元数据用于个人或商业项目的方法。以下是我可能会探索的想法:

  • 使用 Exif 数据研究其他类型或主题的摄影模式,如昆虫、哺乳动物、风景和建筑。或者,我可能会按鸟类研究数据。
  • 了解如何以编程方式从照片文件中获取不是以 Exif 格式存储的额外数据。例如,也许我对 Lightroom 目录中的许多照片应用的星级和标题可以在应用程序导出的每个 JPEG 文件中找到。有了这些数据点,照片的特征就可以在不同的评级中进行比较和对比。
  • 使用存储在每个图像文件中的日期和时间、关键字和潜在位置(GPS) 来确定每年何时何地返回特定地点,以便有机会拍摄特定种类的鸟类。

结论

到目前为止,您可能对每个数码照片文件的 Exif 文件中存储的元数据有所了解。您还应该了解如何编写 Python 程序来获取元数据并在数据分析项目中使用它。像我一样,也许你可以使用图像元数据来了解你的摄影习惯和技术,并尝试在未来拍出更好的照片。

关于作者

Randy Runtsch 是一名数据分析师、软件开发人员、作家、摄影师、自行车手和冒险家。他和妻子住在美国明尼苏达州东南部。

关注 Randy 即将发表的关于公共数据集的文章,以推动数据分析解决方案、编程、数据分析、摄影、自行车旅行、啤酒等。你可以在 shootproof.com和 shutterstock.com看到他的一些照片。

附录 A — Python c_photo_exif 类

c_photo_exif 类在文章的正文中有描述。

**"""
Name:           c_photo_exif.py
Author:         Randy Runtsch
Date:           March 20, 2021
Description:    The c_photo_exif class opens all image files in the specified 
                folder, reads the Exif data from each file. It then gets the sunrise
                and sunset times of the day the photo was taken. It then writes a subset
                of the Exif data, and the sunrise and sunset times, as a row in a CSV file.
"""import csv
import exifread
import os
import datetime
from pytz import timezone
from astral.geocoder import lookup, database
from astral.sun import sunclass c_photo_exif:def __init__(self, input_photo_folder, output_csv_file_nm, city, time_zone):# Create the output CSV file with headers and process all of the 
        # photo files.# Set astral location as Minneapolis and time zone as US/Central.
        astral_db = database() 
        self._astral_city = lookup(city, astral_db)
        self._time_zone = time_zoneself._rows_processed = 0csv_writer = self.init_csv_file(output_csv_file_nm)self.process_photos(input_photo_folder, csv_writer)def process_photos(self, input_photo_folder, csv_writer):# Process all of the image files contained in the input folder.rows = 0for subdirs, dirs, files in os.walk(input_photo_folder):

            for photo_file_nm in files:# Process only files with a .jpg extension.if photo_file_nm[-4:] == '.jpg':self._rows_processed += 1photo_file_nm_full = input_photo_folder + '/' + photo_file_nm
                    self.process_photo(photo_file_nm, photo_file_nm_full, csv_writer)def process_photo(self, photo_file_nm, photo_file_nm_full, csv_writer):# Get a subset of EXIF values from the photo file. Call function write_csv_file_row()
        # to write the values as a row to a CSV file.photo_file = open(photo_file_nm_full, 'rb')tags = exifread.process_file(photo_file)camera_make     = tags['Image Make']
        camera_model    = tags['Image Model']
        photo_date_time = tags['EXIF DateTimeOriginal']
        focal_length    = tags['EXIF FocalLength']
        shutter_speed   = tags['EXIF ExposureTime']
        f_stop          = tags['EXIF FNumber']
        exposure_bias   = tags['EXIF ExposureBiasValue']
        white_balance   = tags['EXIF WhiteBalance']
        iso             = tags['EXIF ISOSpeedRatings']# Exif date-time values contain colons in the date part (for example, 2021:01:20). Replace
        # the first two colons with hyphens (-) so that they will be treated as date-time values
        # in other programs, such as Tableau. This will leave the colons in place in the time portion
        # of the value.photo_date_time = photo_date_time.values.replace(':', '-', 2)# Get sunrise and sunset date-time values.sunrise_date_time   = self.get_sun_date_time(photo_date_time, 'sunrise')
        sunset_date_time    = self.get_sun_date_time(photo_date_time, 'sunset')self.write_csv_file_row(csv_writer, photo_file_nm, photo_date_time, sunrise_date_time, sunset_date_time, \
            camera_make, camera_model, focal_length, shutter_speed, f_stop, exposure_bias, iso, white_balance)def init_csv_file(self, output_csv_file_nm):# Open the CSV output file for write (create a new file and overwrite
        # the existing file), write its header, and return its handle.headers = ['File Name', 'Photo Date Time', 'Sunrise Date Time', 'Sunset Date Time', 'Camera Make', 'Camera Model', \
            'Focal Length', 'Shutter Speed', 'F Stop', 'Exposure Bias', 'ISO', 'White Balance']csv_file = open(output_csv_file_nm, 'w', encoding='utf-8', newline='')csv_writer = csv.DictWriter(csv_file, headers)
        csv_writer.writeheader()return csv_writerdef write_csv_file_row(self, csv_writer, file_name, photo_date_time, sunrise_date_time, sunset_date_time, \
        camera_make, camera_model, focal_length, shutter_speed, f_stop, exposure_bias, iso, white_balance):# Assemble the record of Exif values by column and write it to the CSV file.row = {'File Name' : file_name, 'Photo Date Time' : photo_date_time, 'Sunrise Date Time' : sunrise_date_time, \
                  'Sunset Date Time' : sunset_date_time, 'Camera Make' : camera_make, 'Camera Model' : camera_model, \
                  'Focal Length' : focal_length, 'Shutter Speed' : shutter_speed, \
                  'F Stop' : f_stop, "Exposure Bias": exposure_bias, 'ISO' : iso, 'White Balance' : white_balance}csv_writer.writerow(row)def get_sun_date_time(self, date_time_in, date_time_type):# Get the sunrise or sunset date and time in UTC, convert it to the local
        # timezone, and return it as a string in this format: YYYY-MM-DD HH:MM:SS.date_in = datetime.datetime(int(date_time_in[0:4]), int(date_time_in[5:7]), int(date_time_in[8:10]))astral_sun = sun(self._astral_city.observer, date_in)
        astral_date_time = astral_sun[date_time_type]astral_date_time_local = astral_date_time.astimezone(timezone(self._time_zone))
        date_time_out = astral_date_time_local.strftime('%Y-%m-%d %X')return date_time_outdef print_exif_values(self, photo_file_nm):# Print most of the human-readable Exif values for the specified photo file.file = open(photo_file_nm, 'rb')# Return Exif tags
        exif_tags = exifread.process_file(file)for exif_tag in exif_tags.keys():
            if exif_tag not in ('JPEGThumbnail', 'TIFFThumbnail', 'Filename', 'EXIF MakerNote'):
                print("Key: %s, value %s" % (exif_tag, exif_tags[exif_tag]))def get_rows_processed(self):return self._rows_processed**

如何使用 Python 的新匹配语句

原文:https://towardsdatascience.com/how-to-use-pythons-new-match-statement-d81981f8adc4?source=collection_archive---------16-----------------------

快速浏览 Python 的新匹配语句以及如何使用它。

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

(src =https://pixabay.com/images/id-20237/

介绍

Python 3.10 已经发布了一段时间,并带来了一些新的额外特性。与许多版本一样,语言的许多变化并不太显著,也没有中断。要明确的是,这不是传统意义上的破坏,旧代码将被破坏,但这是说,未来使用该语法的代码不能使用旧版本的 Python。

然而,Python 的一个新变化是全新的,意义重大。这种变化就是匹配语句。这个语句肯定是 Python 早期版本中所缺少的,它确实可以帮助语言的控制流。今天,我想讨论一下这句话的用法,并更详细地介绍一下。

匹配语句是什么?

如果你是一个 C 或 C++程序员,很可能你使用过或者至少听说过使用 match 语句,只是它被重命名为 switch 语句。该语句用于控制代码执行的流程。该语句可以接受一个值,并将其与多个可能条件中的一个完美匹配。这也被称为模式匹配,这是 Rust 程序员可能熟悉的一个术语。该语句可以像条件语句一样使用,并且基本上遵循与以下语句非常相似的语法:

**from** **enum** **import** **Enum**
**class** **Command**(**Enum**):
    QUIT = 0
    RESET = 1

match command:
    **case** **Command**.QUIT:
        quit()
    **case** **Command**.RESET:
        reset()

我们可以匹配任何条件,并快速将控制流移入或移出块。虽然使用简单的条件语句当然可以做到这一点,但 match/case 方法要漂亮得多,甚至优于使用传统的条件语句。虽然这是一个简单的特性,但是对于 Python 程序员来说,这是一个非常受欢迎并且非常酷的特性。

重要注意事项

现在我们已经使用了 match 语句,让我们再多谈一点。您可能已经意识到,当我们将 match 语句与其他具有相似表达式类型的编程语言进行比较时,它们都是系统/低级、命令式编程语言。match 语句本身属于一个非常必要的计算领域。这就提出了一个非常有趣的问题,为什么它现在出现在所有语言的 Python 中?

我们应该考虑到很多 Python 程序员也可能写 C++或 C,这可能是来回切换的一个有效原因,在某些情况下可能会被忽略。但是我想提出的问题是,这是否意味着 Python 在未来会变得更加必要。当然,我们可以预期 Python 将保持相当高的声明性和高级别,但是推测 Python 在未来是否会更适用于较低级别的事物将会很有趣。当然,没有办法知道,但是我希望看到更多类似这样的迭代特性在未来实现,因为我认为它真的可以使语言更加通用。

一些人可能会担心的一个问题是命名。Python 3 中编写的许多遗留函数都使用 match 和 case 作为变量名,那么这两者的增加是否是对代码的重大改变呢?简单的回答是肯定的,你仍然可以使用 match 和 case 作为变量名。匹配和大小写已经成为所谓的软关键字。这意味着大多数时候,它们没有特殊的含义,但是当在某些应用程序中使用时,比如 a case 块,它们就成为 Python 解释器使用的关键字。

关于匹配和大小写需要注意的另一件奇怪的事情是它不能处理下划线。下划线是 Python 中通配符变量的另一个软关键字,但在这种情况下,我们可以通过 case/match 语句传递它,但它不会改变匹配的值。

最后一个问题也许是最重要的,这是一个范围问题。Python 中的代码块有自己的作用域是很常见的,那么如果我们在匹配块中使用一个变量,那么它是在什么作用域中声明的呢?Python 中的 Case 块没有自己的作用域。这意味着变量将被应用到最近的可用局部作用域。换句话说,我们可以在没有初始化的情况下在这些块中定义变量,并在函数周围使用它们,这可能是您所不希望的,因为在大多数其他情况下不会发生这种情况。

结论

match 语句无疑是 Python 编程语言中一个很酷的新特性。至于这是否暗示了这种方法可能会带来更多的特性,我真的很期待看到结果。该语句当然是一个受欢迎的补充,尽管它不一定提供那么多新功能。我们可以做的另一个假设是,一旦 Python 4 准备好做出突破性的改变,这可能会成为 Python 4 中的一个常规关键字。不管怎样,我认为这是一个有趣的附加功能,我将来会不时地使用它。感谢您的阅读,我希望您对 Python 的最新特性有所了解!

如何使用 Pytorch 作为通用优化器

原文:https://towardsdatascience.com/how-to-use-pytorch-as-a-general-optimizer-a91cbf72a7fb?source=collection_archive---------4-----------------------

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

图片作者。

Pytorch 真的很有趣,如果你正在寻找一个框架来开始学习神经网络,我强烈推荐它——在 Pytorch 这里可以看到我关于如何使用基本神经网络的简短教程。

然而,许多人没有意识到 Pytorch 可以用于一般的梯度优化。换句话说,您可以使用 Pytorch 找到任意复杂优化目标的最小值或最大值。但是,你为什么要这样做呢?我能想到的理由至少有三个(还有很多)。

  1. 您已经熟悉 Pytorch,不想再学习另一个优化框架
  2. 您希望对 Pytorch 模型的结果进行优化,即,您希望对 Pytorch 神经网络的预测进行优化(例如,第一阶段神经网络可能会预测客户参与特定高价值活动的倾向,优化器用于确定在给定一些约束条件(如营销预算)的情况下哪个活动是最佳的)。
  3. 您希望使用 Pytorch 中定义的高级优化器,比如 Adam。

实现通用优化器

嗯……你实际上不需要实现任何东西,如果你已经熟悉 Pytorch,你只需要简单地写一个 Pytorch 自定义模块,就像你写神经网络一样,Pytorch 会处理好所有其他的事情。让我们看一个成功的例子。

为了演示,我们将定义一个简单的函数——指数衰减函数。让我们定义数据——标量浮点值a, k, b是函数的未知参数,优化的目标是估计这些参数。

import numpy as np
import torch
import matplotlib.pyplot as plt
from torch import nn
from torch.functional import F
from copy import copyimport seaborn as snssns.set_style("whitegrid")n = 1000
noise = torch.Tensor(np.random.normal(0, 0.02, size=n))
x = torch.arange(n)
a, k, b = 0.7, .01, 0.2
y = a * np.exp(-k * x) + b + noiseplt.figure(figsize=(14, 7))
plt.scatter(x, y, alpha=0.4)

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

指数衰减函数——作者图片。

接下来,让我们定义模型和训练循环:

class Model(nn.Module):
    """Custom Pytorch model for gradient optimization.
    """
    def __init__(self):

        super().__init__()
        # initialize weights with random numbers
        weights = torch.distributions.Uniform(0, 0.1).sample((3,))
        # make weights torch parameters
        self.weights = nn.Parameter(weights)        

    def forward(self, X):
        """Implement function to be optimised. In this case, an exponential decay
        function (a + exp(-k * X) + b),
        """
        a, k, b = self.weights
        return a * torch.exp(-k * X) + b

def training_loop(model, optimizer, n=1000):
    "Training loop for torch model."
    losses = []
    for i in range(n):
        preds = model(x)
        loss = F.mse_loss(preds, y).sqrt()
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        losses.append(loss)  
    return losses

如果你熟悉 Pytorch,这里没有什么特别的东西。我们在这里要做的关键事情是定义我们自己的权重,并手动将它们注册为 Pytorch 参数,这就是这些行要做的事情:

weights = torch.distributions.Uniform(0, 0.1).sample((3,))
# make weights torch parameters
self.weights = nn.Parameter(weights)

下面几行确定了要优化的功能。你可以用你想要最小化的函数的定义来代替它们。

a, k, b = self.weights
return a * torch.exp(-k * X) + b

通过调用nn.Parameter,我们定义的权重将以与标准 Pytorch 参数相同的方式运行——即,它们可以计算梯度并根据损失函数进行更新。训练循环简单地在n历元上迭代,每次估计均方误差并更新梯度。

运行模型的时间到了,我们将使用 Adam 进行优化。

# instantiate model
m = Model()
# Instantiate optimizer
opt = torch.optim.Adam(m.parameters(), lr=0.001)losses = training_loop(m, opt)
plt.figure(figsize=(14, 7))
plt.plot(losses)
print(m.weights)

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

超过 1000 个时代的损失—作者图片…

上面的图显示了超过 1000 个时期的损失函数——你可以看到,在大约 600 年后,它没有显示出进一步改善的迹象。a、k、b 的估计权重为 0.697、0.0099、0.1996,非常接近定义函数的参数,我们可以使用训练好的模型来估计函数:

preds = m(x)
plt.figure(figsize=(14, 7))
plt.scatter(x, preds.detach().numpy())
plt.scatter(x, y, alpha=.3)

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

蓝线是估计的指数衰减曲线——图片由作者提供。

您可以看到,通过优化参数,我们现在可以拟合数据的指数衰减。虽然你可以用来自scipycurve_fit做同样的事情,但是我认为 Pytorch 更大的灵活性来适应更复杂的功能是值得花时间去学习的。

总结

虽然大多数人会使用 Pytorch 来构建神经网络,但该框架的灵活性使它非常通用。在这篇文章中,我们拟合了一条由指数衰减函数定义的简单曲线,但是没有理由为什么相同的构建块不能扩展到任意复杂的优化函数。

希望这是有帮助的,如果你有任何想法,评论或问题,请告诉我。

感谢阅读!

如何使用 Q-Q 图检查数据的分布

原文:https://towardsdatascience.com/how-to-use-q-q-plot-for-checking-the-distribution-of-our-data-c798d0577369?source=collection_archive---------28-----------------------

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

作者图片

数据科学家通常需要检查他们的数据集的统计数据,特别是针对已知的分布或与其他数据集进行比较。我们可以为此目标运行几个假设测试,但我通常更喜欢使用简单的图形表示。我说的是 Q-Q 情节。

什么是 Q-Q 情节?

Q-Q 图通常被称为分位数图。这是一个 2D 图,我们在其中将分布的理论分位数与数据集的样本分位数进行比较。如果数据集是根据该分布生成的,我们预计该图表将接近 45 度线,因为样本分位数将与理论分位数相似。如果样本是从不同的分布中生成的,我们就不会得到 45 线。

通过这种方式,我们可以很容易地想象数据集是否类似于理论分布。我们甚至可以使用 Q-Q 图来比较两个数据集,只要它们具有相同的点数。

Python 中的一个例子

现在让我们看看 Python 中的 Q-Q plot 是如何工作的。你可以在我的 GitHub repo 上找到完整的代码。

首先,让我们导入一些库,并设置随机数种子,以使我们的模拟可重复。

from statsmodels.graphics.gofplots import qqplot 
from matplotlib import pyplot as plt plt.rcParams['figure.figsize'] = [10, 7] 
plt.rc('font', size=14) 
from scipy.stats import norm, uniform 
import numpy as np 
np.random.seed(0)

现在,让我们模拟 0 和 1 之间的 1000 个均匀分布的点,并将该数据集与具有相同均值和方差的正态分布进行比较。我们期望得到一个与 45 度线非常不同的 Q-Q 图,因为这两个分布非常不同。

x = np.random.uniform(1,2,1000)

为了根据最佳拟合正态分布绘制该数据集的 Q-Q 图,我们可以编写以下代码:

qqplot(x,norm,fit=True,line="45") 
plt.show()

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

作者图片

fit=True 参数试图根据最大似然来拟合数据集的正态分布。正如我们所见,样本分位数与理论分位数有很大不同,因为蓝点离红线非常远,红线是 45 度线。

现在让我们尝试使用正态分布的数据集。

x = np.random.normal(1,2,1000) 
qqplot(x,norm,fit=True,line="45") 
plt.show()

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

作者图片

现在结果大不一样了。样本分位数与理论分位数非常相似(即蓝色点靠近红线)。有一些异常值会在此图表的下限和上限产生一些噪音,但这不是一个大问题,因为样本分布的最大部分与理论值非常吻合。

当然,改变 qqplot 函数的第二个参数,我们可以将我们的样本数据集与另一个分布进行比较。例如,我们可以将正态分布的数据集与均匀分布的数据集进行比较。

qqplot(x,uniform,fit=True,line="45") 
plt.show()

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

作者图片

正如预期的那样,结果不太好,因为生成数据集的分布与最佳拟合的均匀分布非常不同。

两个数据集的 Q-Q 图

Q-Q 图甚至可以用于 2 个数据集,只要它们具有相同的点数。为了获得两个数据集的样本分位数,我们只需对它们进行升序排序并绘制它们。

让我们从两个正态分布生成两个正态分布数据集,具有相同的均值和相同的方差。

x1 = np.random.normal(1,2,1000) 
x2 = np.random.normal(1,2,1000)

现在我们可以对数据进行排序:

x1.sort() 
x2.sort()

然后我们可以画出来:

plt.scatter(x1,x2) 
plt.plot([min(x1),max(x1)],[min(x1),max(x1)],color="red") 
plt.xlabel("1st dataset's quantiles") 
plt.ylabel("2nd dataset's quantiles") 
plt.show()

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

作者图片

如我们所见,尾部仍有一些噪声,但分布的中心部分匹配得相当好。

结论

在本文中,我展示了如何使用 Q-Q 图来检查样本分布和理论分布之间或两个样本之间的相似性。尽管可以执行一些假设检验来实现这一目标(例如 Kolmogorov-Smirnov 检验),但我更喜欢使用数据可视化,以便对我们的数据集中的现象进行可视化表示。这样,我们的解释不会受到任何假设检验的影响,甚至对非技术人员来说也更加清晰。

原载于 2021 年 6 月 21 日【https://www.yourdatateacher.com】

如何通过 python 脚本使用 QGIS 空间算法

原文:https://towardsdatascience.com/how-to-use-qgis-spatial-algorithms-with-python-scripts-4bf980e39898?source=collection_archive---------7-----------------------

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

显示土地价格的日本东京地图。作者照片

QGIS 是您学习 GIS 和空间分析时最先接触到的工具之一。使用这个开源软件包,您可以处理空间数据及其处理的几乎所有方面。尽管它有大量的 GUI 特性可以使用,但有时有一种处理脚本的方法是很重要的。尤其是对于构建工作流的数据科学家和数据工程师来说,他们非常需要可扩展的自动化脚本。QGIS 为此提供了一个名为 PyQGIS 的 Python API。您可以通过 python 脚本自动执行大多数与 QGIS 相关的操作和空间算法。让我们深入了解这个 Python API,并了解如何在 Python 上使用 QGIS 空间算法。

如果你想了解更多关于位置(地理空间)数据如何变得越来越重要,以及它是数据分析的前进方向,请查看我关于这个主题的文章。

https://www.samashti.space/articles/why-geospatial-data-is-the-way-forward-in-data-analytics https://www.samashti.space/articles/why-you-need-to-use-geopackage-files-instead-of-shapefile-or-geojson

作为其 python API 的一部分,QGIS 在其软件上提供了一个 python 控制台。您可以使用它来访问几乎所有内容,从 QGIS 菜单和图层到在数据图层上运行一些算法。控制台很好地处理了一些小规模的功能执行。但是,如果目标是处理复杂的工作流和更大的数据集,这个控制台就失去了光泽。它具有基本的功能,但缺乏复杂工作流程所需的复杂性。

不能从默认 python 环境中导入 QGIS 库。QGIS 安装了 python 版本来处理运行软件所需的所有模块。因此,如果您需要从 python 控制台/jupyter 笔记本中使用 QGIS 库,您需要确保您的 python 可以找到 QGIS 库路径。或者,您可以在 python 环境中安装 QGIS 库。让我们更详细地看看这些选项。

使用 Conda 安装 QGIS 库

如果您使用 Anaconda 来管理 python 库,并从事数据科学项目,那么您将主要了解 conda 。类似于 pip ,conda 是一个 Python 和其他一些语言的包管理系统。使用 conda,您可以像在 Python 上安装任何其他库一样安装 QGIS 包。你可以直接在你默认的 python 环境中安装这个包。但是由于 QGIS 通常对依赖模块有其特定的要求。因此它可能会升级或降级关键包,这可能会为您的其他项目创建依赖模块版本冲突。

理想情况下,如果您将 Python 用于不同的项目,请为每个项目设置一个环境,或者至少为数据科学工作流设置一个环境。通过将这些从全局 python 环境中分离出来,您将使您的系统避免与包依赖相关的错误。因此,安装 QGIS 库的最佳选择是在虚拟环境中进行。它有助于将 QGIS 包与全球 Python 环境隔离开来。

要在活动 Python 虚拟环境中从 conda 安装 QGIS,请在活动 Python 虚拟环境中的终端上运行以下命令。该命令安装必要的 QGIS 库。

conda install -c conda-forge qgis

从虚拟 Python 环境映射 QGIS 桌面软件库。

上述方法可能会安装几个核心 QGIS 库,用于 python 脚本。但这仍无法让您访问桌面软件包中使用的所有 QGIS 空间算法。例如,如果您想要使用 QGIS 的处理工具箱中提供的 GRASS 或 SAGA 处理算法,仅安装 QGIS 核心库是不可能的。如果您经常使用桌面软件,您可能会发现安装工作量很大,而且占用大量存储空间。每次创建项目环境时,安装这么大的包会占用很多存储空间。

相反,您可以使用更简单的解决方案。通过从默认虚拟 Python 环境映射系统环境路径,可以使用 QGIS Desktop 及其库的现有安装(甚至是使用 QGIS 插件安装的 GRASS、SAGA 和其他算法)。您可以将一个现有的 QGIS 安装用于多个 Python 环境,而不存在依赖包的问题,同时不仅仅使用 QGIS 的核心库。

在这种情况下,我将在 Mac OS 上演示这个过程。但是对于 Linux 和 windows,您可以遵循类似的步骤,只需稍加修改。

步骤 1:从 QGIS Python 控制台获取和导出系统路径和操作系统环境变量

打开 QGIS 桌面 app ,打开 Python 控制台。然后首先运行下面几行,将系统路径导出到 CSV 文件。

import sys
import pandas as pd
paths = sys.path
df = pd.DataFrame({'paths':paths})
df.to_csv('./qgis_sys_paths.csv', index=False)

一旦导出了系统路径,就需要导出 QGIS 中的环境变量。

import os
import json
env = dict(os.environ)
rem = ['SECURITYSESSIONID', 'LaunchInstanceID', 'TMPDIR']
_ = [env.pop(r, None) for r in rem]with open('./qgis_env.json', 'w') as f:
    json.dump(env, f, ensure_ascii=False, indent=4)

理想情况下,您使用的 python 版本应该与 QGIS 安装中使用的版本相同或更早。要查找随 QGIS 一起安装的 python 版本及其路径,请运行以下代码,并在 Mac OS 的路径/Applications/Qgis.app/Contents/MacOS/bin/中查找相应的 Python 可执行文件。

from platform import python_version
print(python_version())

步骤 2:在使用算法之前,用 Python 脚本初始化 QGIS 库

在 python 脚本中使用 QGIS 库及其空间算法之前,我们需要设置刚刚导出的环境变量和路径。此外,我们需要初始化 QGIS 的处理模块。

首先,我们导入一些必要的 python 库来处理环境的设置。

# necessary imports
import os
import sys
import json
import pandas as pd

导入这些库后,我们需要设置环境变量和系统路径。

# set up system paths
qspath = './qgis_sys_paths.csv' 
# provide the path where you saved this file.
paths = pd.read_csv(qspath).paths.tolist()
sys.path += paths# set up environment variables
qepath = './qgis_env.json'
js = json.loads(open(qepath, 'r').read())
for k, v in js.items():
    os.environ[k] = v# In special cases, we might also need to map the PROJ_LIB to handle the projections
# for mac OS
os.environ['PROJ_LIB'] = '/Applications/Qgis.app/Contents/Resources/proj'

然后,我们实际上可以从 python 导入 QGIS 库。

# qgis library imports
import PyQt5.QtCore
import gdal
import qgis.PyQt.QtCore
from qgis.core import (QgsApplication,
                       QgsProcessingFeedback,
                       QgsProcessingRegistry)
from qgis.analysis import QgsNativeAlgorithms

在下一步中,我们通过将 QGIS 的本地算法添加到处理注册表来初始化处理模块及其算法。

feedback = QgsProcessingFeedback()# initializing processing module
QgsApplication.setPrefixPath(js['HOME'], True)
qgs = QgsApplication([], False)
qgs.initQgis() # use qgs.exitQgis() to exit the processing module at the end of the script.# initialize processing algorithms
from processing.core.Processing import Processing
Processing.initialize()
import processingQgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())

通过这一步,您可以从 python 访问所有 QGIS 库及其空间算法。您可以通过运行以下代码来检查您有权访问的所有算法。

algs = dict()
for alg in QgsApplication.processingRegistry().algorithms():
    algs[alg.displayName()] = alg.id()
print(algs)

目前,这些步骤解决了从 QGIS native algorithms & GRASS 等提供商处导入算法的问题。我仍在致力于启用佐贺和其他插件,如 Orfeo 工具箱等。,用于 Python。继续查看这个博客的更新,或者如果你知道如何更新,请告诉我。

运行算法

你可以从图书馆找到很多算法。您可以运行算法来帮助查看每个算法的描述。提供给算法的参数也显示在帮助输出中。要查看帮助,只需通过提供算法 id 来运行以下代码:

processing.algorithmHelp("native:centroids")# which would print this on the console.
"""
Centroids (native:centroids)This algorithm creates a new point layer, with points representing the centroid of the geometries in an input layer.The attributes associated to each point in the output layer are the same ones associated to the original features.----------------
Input parameters
----------------INPUT: Input layer Parameter type:	QgsProcessingParameterFeatureSource Accepted data types:
		- str: layer ID
		- str: layer name
		- str: layer source
		- QgsProcessingFeatureSourceDefinition
		- QgsProperty
		- QgsVectorLayerALL_PARTS: Create centroid for each part Parameter type:	QgsProcessingParameterBoolean Accepted data types:
		- bool
		- int
		- str
		- QgsPropertyOUTPUT: Centroids Parameter type:	QgsProcessingParameterFeatureSink Accepted data types:
		- str: destination vector file, e.g. 'd:/test.shp'
		- str: 'memory:' to store result in temporary memory layer
		- str: using vector provider ID prefix and destination URI, e.g. 'postgres:…' to store result in PostGIS table
		- QgsProcessingOutputLayerDefinition
		- QgsProperty----------------
Outputs
----------------OUTPUT:  <QgsProcessingOutputVectorLayer>
	Centroids
"""

因此,我们知道,对于在任何矢量层上运行质心算法的情况,我们知道我们必须提供 3 个参数及其可接受的数据类型。让我们对包含几个多边形的矢量文件运行一个简单的质心算法。

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

包含洛杉矶市网格多边形的矢量文件示例。作者照片。

对于算法,我们需要创建一个参数字典,一旦完成,我们运行质心算法。

parameters = {
    'ALL_PARTS': 1,
    'INPUT': './grid-polygons.geojson',
    'OUTPUT': './grid-centroids.geojson'
}
processing.run("native:centroids", parameters)# this would print out the output, once the algorithm is run.
"""
{'OUTPUT': './grid-centroids.geojson'}
"""

我们可以在 QGIS 桌面应用程序上看到网格质心的最终输出。

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

为洛杉矶市上空的每个网格多边形创建一个质心。作者照片。

需要注意的事项

  • 理想的做法是让虚拟环境的 Python 版本与 QGIS 安装的版本或更早版本保持一致。否则,这可能会给为早期版本的 Python 构建的一些模块带来问题。
  • 不要忘记通过运行qgs.exitQgis()退出您初始化的 QGIS 模块,其中 qgs 是您用来初始化模块的变量。
  • 对于 windows 用户,由于有一个 OSgeo4W shell,整个过程的处理方式略有不同,这里不做介绍。
  • 对于使用 M1 macbook 的用户,QGIS 使用 Rosetta 安装在英特尔架构中。而全球安装的 python 是建立在 arm64 架构上的。即使你使用 Anaconda Python 和 intel 架构,仍然有库(esp。数据科学&空间数据科学)。匹配模块安装的架构非常重要,这样您就可以在 python 中使用 QGIS 和其他库。
  • 如果您发现您的全局 python 安装与 QGIS 上的不匹配,esp。在 M1 macbook 中,您可以将 QGIS python 本身用于数据科学工作流。因为它是为空间数据科学需求而构建的,所以没有太多东西可以添加到项目中。您可以按照上面的步骤 1 获得这个 python 路径。
    macOS: /Applications/Qgis.app/Contents/MacOS/bin/python[version] Linux: /usr/share/qgis/python
  • 如上所述,您可以使用 QGIS Python 安装 spyder & jupyter 笔记本,使用 pip 在日常工作流程中使用。

我希望这有助于在日常 python 工作流中设置和使用 QGIS 库。当我找到更多的信息时,我会继续更新这部分,我很高兴收到任何进一步改进的建议。

如果你喜欢这篇文章,请订阅我的博客,并获得关于未来博客文章的通知。如有任何疑问或讨论,您可以在 LinkedInTwitter 上找到我。看看我以前的博客,关于如何免费对地址进行地理编码。

https://www.samashti.space/articles/how-to-geocode-addresses-for-free https://www.samashti.space/articles/how-alternative-data-helping-companies-invest-big

如何利用强化学习推荐内容

原文:https://towardsdatascience.com/how-to-use-reinforcement-learning-to-recommend-content-6d7f9171b956?source=collection_archive---------9-----------------------

谷歌的研究人员开发了一个新的 RL 框架。

强化学习理论上是最有效的深度学习方法之一。然而,实际上它并不处理复杂的问题。谷歌开发的 RL 框架 RecSim ,允许优化复杂的推荐系统。

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

图 1:强化学习框架。图片作者。

谷歌和 UT 奥斯汀的研究人员创建了一个更强大的 RL 框架,允许动态用户功能,并处理一些 RL 的技术问题。虽然这种方法计算量很大,但它提供了一个允许优化或推荐引擎的离线开发环境。

让我们深入了解一下这种方法是如何工作的…

技术 TLDR

RecSim 是一个利用强化学习(RL)的模拟环境构建器。该方法由“模拟器”模块控制,该模块负责对用户/文档进行采样,并迭代地训练推荐代理。该方法支持与用户的顺序交互,并允许工程师对环境进行大量定制。

这篇论文和其他一些有用的资源在评论中有链接。

好的,很多了。它实际上是如何工作的?

让我们慢一点,真正理解这个方法是如何工作的。

强化学习的背景

强化学习(RL)是一个框架,它涉及通过重复模拟来训练代理人做出决策。简而言之,代理做出决定,从模拟器获得反馈,调整其决定,然后再次尝试。重复这个过程,直到损失函数被优化。

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

图 2:雅达利突围:2013 年第一款 RL 游戏。图片作者——src

现代 RL 算法首次应用于雅达利游戏《突围》(图 2)。代理人控制底部的桨,并通过用球打破障碍来最大化得分。仅仅通过大量的尝试,RL 就可以成为一个近乎完美的玩家。从那以后,由于 RL 能够掌握定义良好的任务,如游戏和 NLP,因此受到了很多关注。

但是,与任何机器学习算法一样,它也有其局限性:

  • **RL 不好概括。**如果引入了新的功能或决策,it 部门通常很难适应。
  • RL 在组合决策空间上不能很好地扩展。因此,如果我们有很多可能的决定,比如在网飞的主屏幕上推荐很多电影,RL 会努力处理大量可能的配置。
  • RL 不处理低信噪比数据。 RL 是一个非常强大的模型,可以从数据中学习错综复杂的规则和关系——如果有噪声特征,RL 将拟合噪声。
  • **RL 不处理长时间范围。**与上面的要点类似,如果我们想要优化一个长期决策,有很多机会去适应噪声,所以如果给 RL 一个复杂的优化任务,它可能会过度适应。

所以,RL 在明确定义的问题空间中确实很强大,但是我们如何让它推广到更复杂的问题呢?

RecSim 框架

由谷歌和 UT 奥斯汀的研究人员开发的 RecSim 可能会解决我们在推荐引擎方面的问题。在这里,推荐包括向用户提供内容——想想 Spotify、网飞、YouTube 等。

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

图 3:简化的 RecSim 框架。图片作者——src

如图 3 所示,RecSim 中有两种类型的组件:模型(蓝色)和数据(黑色)。从第一个代理-环境周期开始,我们…

  1. 创建用户和文档样本(内容)。这些样本来自工程师指定的分布。
  2. 获得代理的推荐。推荐代理从前面的步骤中获取用户和文档,并且产生一个 策略 —一个例子是向给定用户显示一组电影。
  3. **模拟用户的决策。**用户选择模型接受来自代理的推荐,并基于先前的例子,将估计用户的行为——假设 45%的用户开始看电影。
  4. **向代理和用户传递反馈。**在确定了用户的行为之后,我们将这些信息传递给代理,这样它就可以改进它的预测。我们还将信息传递给用户数据,这样我们就可以更新长期的用户偏好,比如最喜欢的流派。
  5. 重复步骤 1-4,直到停止标准。常见的停止标准是固定的迭代次数或最低精度。

注意,推荐代理用户选择模型都可以是复杂的神经网络。对于文中的例子,推荐代理是一个深度神经网络,用户选择模型是一个多项式逻辑。

个案研究

RecSim 在各种使用案例中都取得了成功,但本文中引用了三个核心示例。

第一个是使用 RecSim 为用户发现潜在的(隐藏的)状态,并优化长期点击率(CTR)。潜在状态的一个例子是电影类型偏好。

这是一个典型的探索与利用的权衡。我们需要获得一些关于用户的数据来提供建议,但我们也希望尽快做出明智的决定来帮助我们的用户。对于有强烈内容偏好的用户,RecSim 能够显示出比贪婪算法提高 51%的点击率。

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

图 4:单一文档与候选文档推荐。图片作者。

研究人员解决的第二个问题是处理候选推荐,即组合决策空间(图 4)。

虽然没有给出准确性分数,但通过使用一些基本假设,作者能够证明 RecSim 框架的有效性。他们还注意到,“最优”算法的计算量非常大,并且大部分增益可以通过使用时间差异学习来获得,而不是完全成熟的 RL 算法。

因此,虽然我们没有解决组合决策空间的问题,但 RecSim 提供了一些比普通 RL 计算效率更高的解决方案。

最后,在第三个案例研究中,研究人员试图解决长时间跨度的问题。为了解决这个问题,作者反复向一组用户给出相同的建议,并观察他们偏好的变化。通过隔离单个建议的影响,该模型甚至能够在低信噪比的环境中估计功能的真实影响。

摘要

现在你知道了!

总之,RecSim 创建了一个模拟框架来优化推荐代理。它允许组合决策空间和长时间的视野。

如果您从事为用户生成推荐的业务,并且有足够的数据和计算资源,RecSim 可能是 RL 最健壮的推荐框架。

实施说明

  • RecSim 框架被封装在 OpenAI gym 中,以利用当前的 RL 库。
  • 该方法是有效的,但仍可从未来的开发中受益。
  • RecSim 附带了几个默认的学习环境,但是因为这些环境可能是特定于领域的,所以鼓励开发人员构建自己的环境。
  • RecSim 允许可配置的用户状态,比如主题关联性。
  • 虽然这不是 RecSim 的直接贡献,但该库支持动态用户特性,这是 RL 的一个相对较新的特性

感谢阅读!我会再写 38 篇文章,把学术研究带到 DS 行业。查看我的评论,链接到这篇文章的主要来源以及一些有用的资源。

如何使用 Roboflow 和 Streamlit 可视化对象检测输出

原文:https://towardsdatascience.com/how-to-use-roboflow-and-streamlit-to-visualize-object-detection-output-672ba11b2f7c?source=collection_archive---------24-----------------------

构建用于血细胞计数检测的应用程序

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

正在运行的应用程序。(图片由 RoboflowStreamlit 提供;授权使用。)

大多数技术都是为了让你的生活或工作更轻松。如果您的工作涉及将计算机视觉构建到您的应用中,使用 Roboflow 平台可以满足您的一切需求。

Streamlit 是一个开源平台,使您能够将 Python 脚本转换为应用程序,并立即部署它们。Streamlit 和 Roboflow 可以携手合作,让您处理计算机视觉问题并可视化您的输出,以便您可以更快地做出更好的决定。

在本帖中,我们将带您了解如何使用 Roboflow 并简化它,向您展示如何:

  1. 在 Roboflow 中拟合对象检测模型
  2. 使用 API 访问模型及其预测
  3. 创建和部署 Streamlit 应用程序

具体来说,我们将使用一个通用的血细胞计数和检测数据集。如果你想直接玩它,这里有一个互动应用这是代码

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

红细胞、白细胞和血小板。(图片由 RoboflowStreamlit 拍摄;授权使用。)

我们将构建一个检测血小板、白细胞和红细胞的对象检测模型。然后,我们共同开发的应用程序将允许您使用您的对象检测模型进行预测,以给定的置信度可视化这些预测,并根据您首选的置信度编辑这些预测,并提供即时视觉反馈。

如何在 Roboflow 中拟合对象检测模型

您以前是否拟合过对象检测模型?

即使你没有,Roboflow 也可以帮助你完成计算机视觉的所有方面,从上传、注释和组织你的图像到训练和部署计算机视觉模型。

我们认为,你不需要成为一名数据科学家,或者需要丰富的编码背景才能使用计算机视觉。你现在已经拥有了你需要的一切。

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

计算机视觉工作流程。(图片由 RoboflowStreamlit 提供;授权使用。)

如果你还没有一个 Roboflow 账户,你需要前往 Roboflow 并创建一个。如果你想从公共数据集开始训练你的模型,Roboflow 有一个很棒的教程,描述了如何更快地改进你的模型。(或者,可以上传自己的数据集!)

一旦你有了一个账户,就去我们的计算机视觉数据集页面。我们已经公开了 30 多个不同类型的数据集,并且还在继续增加。

我们今天要介绍的是血细胞计数和检测数据集。

在您决定使用哪个数据集之后,就可以开始使用它了。这将创建您现在可以使用的数据集的副本。

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

派生公共数据集。(图片由 RoboflowStreamlit 拍摄;授权使用。)

此时,可以直接拟合一个模型。但是,我们建议您预处理和增强您的图像。

  • **图像预处理。**在将图像输入模型之前,对所有图像执行确定性步骤。例如,你可以调整你的图像的大小,使它们都一样大,或者将你的图像转换成灰度
  • **图像增强。**通过扭曲您的输入图像来创建更多的训练示例,以便您的模型不会过度适应特定的训练示例。例如,您可以翻转旋转模糊,或者为您的图像添加噪声。目标是在您部署模型时,让您的模型更好地概括“真实世界”。

对于我正在使用的血细胞计数数据集,我选择了以下预处理和增强选项:

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

图像预处理图像增强技术。(图片由 RoboflowStreamlit 拍摄;授权使用。)

当决定是否使用特定的增强选项时,我问自己一个问题“对于我的模型来说,增强图像是一个合理的图像吗?”在这种情况下,我给我的图像添加了 90 度、180 度和 270 度的旋转,因为细胞幻灯片可以合理地旋转 90 度,并且仍然有意义。

它对所有应用程序都没有意义。例如,我可能不包括自动驾驶汽车的那种旋转,因为停车标志应该用伸入地面的杆子来看。将图像旋转 180 度会使停车标志颠倒,而地面应该是天空——这对我的模型来说可能不是一件非常有用的事情。

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

培训、验证、测试拆分 (图片由 RoboflowStreamlit 拍摄;授权使用。)

我对数据进行了拆分,70%的数据在训练集中,20%在验证集中,10%在测试集中。正如你可能知道的,将你的数据分成个训练、验证和测试集真的可以帮助避免过度拟合。

我决定创建三个增强版。这意味着,对于每个训练图像,我们将创建该图像的三个副本,每个副本都应用了随机增强技术。这将为我提供总共 874 张生成的图像:

  • 765 个增强的训练图像(765 = 255 * 3)
  • 加上 73 张验证图像
  • 加上 36 张测试图片。

一旦你完成了你的预处理和增强,点击右上角的“生成”。*有用的提示:*确保给你的数据集起一个令人难忘的名字!

现在您已经准备好构建一个模型了

要建立一个模型,就像点击“使用 Roboflow Train”一样简单

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

两次点击来训练一个计算机视觉模型。(图片由 RoboflowStreamlit 提供;授权使用。)

一般来说,你需要一个 Roboflow Train 信用来做到这一点。联系我们,我们会帮您设置好

你可以选择从头开始训练或者从一个关卡开始。

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

从零开始建立模型或者使用 迁移学习 (图片由 RoboflowStreamlit 拍摄;授权使用。)

  • 从零开始培养。这是更容易的选择。只需点击并运行!您的模型将从零开始构建,仅使用您提供给它的数据。
  • **从一个关卡开始。**这个选项稍微复杂一点,需要一个相关的现有模型。如果您已经构建了一个适合相关数据的模型(或者有一个公共模型),那么从一个检查点开始允许您使用现有的模型作为起点。模型还会根据您的图像进行额外训练。这样做的两个好处是你的模型将会训练得更快,而且你会经常看到性能的提高!这就是所谓的迁移学习。然而,这确实需要一个相关的现有模型,而我们并不总是有这样的模型。

在我的例子中,我从零开始构建我的模型,因为我还没有一个相关的模型。

这就是在 Roboflow 中适合一个模型所需要的一切。说到底,如果你的数据已经被注释,并且你没有对增强做很多改变,那么只需要点击几下鼠标,就可以从你的图像转到一个训练有素的计算机视觉模型。我们还将注释图像变成了一个非常快速的过程——特别是有了模型辅助标签

如何使用 API 访问模型和预测

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

我们模型性能的总体结果,包括 平均精度 (图片由 RoboflowStreamlit 拍摄;授权使用。)

在深入研究这个问题之前,您需要确保您的模型运行良好。

我们的模型似乎表现得很好。通常,我们使用平均精度 (mAP)来评估目标检测模型。你的地图越接近 100%越好!按类别查看您的模型的性能也是有帮助的,以确保您的对象检测模型对于一个对象子集的性能不会明显更差。

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

看着 模特逐班表演 (图片由 RoboflowStreamlit 拍摄;授权使用。)

如果您的模型没有按照您想要的方式执行,您可能希望在继续之前对其进行改进。当人们采取以下两种行动中的一种(或两种)时,我们通常会看到模型的显著改进:

  1. 完善自己的标注 **。**围绕整个对象放置边界框,但尽可能靠近对象的边缘,可以提高模型的性能。
  2. https://blog.roboflow.com/handling-unbalanced-classes/为不平衡的阶级进行矫正。有一个或多个严重代表不足的类会使您的模型更难正确识别那些代表不足的类。一个基本的例子是,如果你给一个孩子看 5 张狗的图片和 100 张猫的图片,这个孩子可能不能很好地识别狗。

现在我们已经拟合了一个模型,我们可以使用该模型对新图像进行预测。Roboflow 推断 API 是进行推断的几种方法之一,这就是我们将要使用的。

  • 型号名称:这个要以rf开头。
  • 访问令牌/API 密钥:这应该是一个 12+字母的代码。

为了使用这个 API,我们需要来自 Roboflow 的一些信息。确保这些都是私人的。这些都是针对你的!

这些信息可以在很多地方找到。我喜欢从示例 Web 应用程序中检索这些,因为我还可以轻松地上传一张图片,并从那里测试我的模型。一旦你有了这些信息,你会想要储存它们——你会随时需要它们。

如何创建和部署 Streamlit 应用程序

部署 Streamlit 应用程序非常简单。即使你以前没有花很多时间专注于部署应用程序。(这里是我写的构建 app 的代码。)

紧紧跟随 Streamlit 的 API 文档,我能够构建一个应用程序:

  • 从我的电脑导入了一个图像文件
  • 允许用户调整我们的计算机视觉模型的参数
  • 显示了用模型的预测注释覆盖的导入图像
  • 计算并显示有关图像和预测的汇总统计数据
  • 为边界框生成了一个置信度直方图

我选择将它分为两个物理组件:侧边栏和主区域。

  • ****边栏。在侧边栏中,用户可以选择从本地计算机导入文件。在这里,用户可以选择一幅图像放入应用程序,并编辑为图像生成预测边界框时使用的置信度和重叠阈值。

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

应用侧边栏,让你能够快速改变你的预测参数。(图片由 RoboflowStreamlit 拍摄;授权使用。)

  • ****主要区域。在主区域,我们有我提到的所有其他东西。包含预测的图像、关于图像和预测本身的一些统计数据、显示所有边界框置信度的直方图,以及存储边界框注释的 JSON 的打印输出。

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

主应用区域,可视化预测输出、汇总统计和边界框置信度。(图片由 RoboflowStreamlit 拍摄;授权使用。)

如果你想看完整的代码,你可以在这里找到。最有帮助的三个工具是:

  • 如果我想在我的屏幕上打印任何东西,st.write()让我可以轻松做到。它支持 Markdown ,所以我可以用##来控制标题的大小。在显示汇总统计数据时,我还使用了 f 字符串,以便更好地控制这些数据的呈现方式。例如,在小数点后四位四舍五入平均置信水平,而不是一长串尾随小数。
  • 我绝对不是一个网络开发人员。定义侧边栏就像st.sidebar()一样简单,而不是花费我的时间去计算如何为用户留出屏幕的左侧和争论尺寸。想在侧边栏上添加一些东西,比如滑块或者上传文件的方式?试试st.sidebar.slider()或者st.sidebar.file_uploader()。Streamlit API 的设置使您的组件停留在您想要的位置。
  • st.image()st.pyplot() : Streamlit 的 API 很直观。如果你想在你的应用程序中插入图像,你可以使用st.image()功能。来自 pyplot 的剧情?st.pyplot()。如果你想把一张图片放到侧边栏,你可以把它从st.image()改成st.sidebar.image()

你明白了。如果你想做某件事,你可能只需要输入st.that_thing_you_want_to_do()!如果你想让那个东西出现在你的侧边栏里,把它改成st.sidebar.that_thing_you_want_to_do()

在编写完我的 Python 脚本并推送到 Github 之后,我按照 Streamlit 的指示部署了我的应用——点击这里查看应用

想了解更多关于开发人员使用 Streamlit 开发的令人惊叹的应用程序吗?查看他们的应用程序库社区论坛,为你的下一个项目寻找一些灵感。

原载于 2021 年 2 月 23 日https://blog . streamlit . io**

如何使用 Seaborn 进行数据可视化

原文:https://towardsdatascience.com/how-to-use-seaborn-for-data-visualization-4c61fc488ec1?source=collection_archive---------34-----------------------

数据可视化是以图形的形式表示数据的艺术。对于处理数据的专业人员,例如金融分析师、业务分析师、数据分析师、数据科学家等,这是一个非常有用的工具。在本教程中,我们将使用 Python 库 Seaborn。

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

卢克·切瑟在 Unsplash 上的照片

目录

  1. 介绍
  2. 先决条件
  3. 安装 Seaborn
  4. 导入 Seaborn 并加载数据集
  5. 不同类型的图表
  6. 可视化口袋妖怪数据集
  7. 结论

介绍

Seaborn 是一个基于 matplotlib 构建的开源 Python 库。它用于数据可视化和探索性数据分析。Seaborn 很容易使用 dataframes 和 Pandas 库。创建的图表也可以轻松定制。下面是数据可视化的一些好处。

图表可以帮助我们找到在任何机器学习或预测项目中有用的数据趋势。

  • 图表使得向非技术人员解释数据变得更加容易。
  • 视觉上吸引人的图表可以使演示和报告更吸引读者。

本教程可以分为三个主要部分。第一部分将讨论安装 seaborn 和加载我们的数据集。在第二部分中,我们将讨论 Seaborn 中的一些常见图形。最后,我们将使用 seaborn 和口袋妖怪数据来创建一些很酷的图表。

我将把我所有的代码写在一个 Google colab 文件中。你可以在这里找到。

先决条件

  • 很好的理解 Python。
  • 在熊猫图书馆工作的一些经验。
  • 使用 Matplotlib 库的一些经验。
  • 对数据分析的基本理解

安装 Seaborn

如果您正在使用 Google Colab,您可以跳过安装步骤。但是,如果您在本地机器上工作,您将需要安装 Seaborn。我强烈建议创建一个虚拟环境来更好地管理您的包。

python -m venv venv
venv/Scripts/activate
pip install pandas, matplotlib, seaborn

导入 Seaborn 并加载数据集

import seaborn as sns
import pandas
import matplotlib.pyplot as plt

Seaborn 有 18 个内置数据集,可以使用以下命令找到它们。

sns.get_dataset_names()

我们将在本教程中使用泰坦尼克号数据集。

df = sns.load_dataset('titanic')
df.head()

不同类型的图表

计数图

在处理分类值时,计数图很有帮助。它用于绘制不同类别的频率。性别列包含泰坦尼克号数据中的分类数据,即男性和女性。

sns.countplot(x='sex',data=df)

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

计数图 1

  • 数据 —数据帧。
  • x —列的名称。

我们可以从图表中观察到,男性乘客的数量明显高于女性乘客的数量。

我们可以根据另一个分类变量进一步分解计数图中的条形。也可以自定义绘图的调色板。

sns.countplot(x='sex', hue = 'survived', data = df,
palette = 'Set1')

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

计数图 2

  • 色调 —拆分条形的分类列的名称。
  • 调色板 —要使用的调色板。要获得调色板列表,请点击查看 matplotlib 的文档

KDE 图

核密度估计(KDE)图用于绘制连续数据的分布。

sns.kdeplot(x = 'age' , data = df , color = 'black')

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

KDE 图

  • 数据 —数据帧。
  • x —列的名称。
  • 颜色 —图形的颜色。你可以在这里找到颜色列表

上图的峰值在 20 到 40 岁之间,因此我们可以得出结论,大多数乘客的年龄在 20 到 40 岁之间。

分布图

分布图类似于 KDE 图。它用于绘制连续数据的分布。

sns.displot(x = 'age',kde=True,bins = 5 , data =df)

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

分布图 1

  • kde —默认设置为假。但是,如果您希望在条形图顶部绘制 KDE 图,可以将其设置为 True。
  • —箱/条的数量。数字越小,条形越宽,间隔越宽。

上面的情节告诉我们,泰坦尼克号上的大多数人都是 25 岁左右。

sns.displot(x ='age',kde=True,bins = 5 ,
hue = df['survived'] , palette = 'Set3', data=df)

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

分布图 2

您还可以将色调和调色板作为参数传递来定制图形。

大多数幸存的乘客都是二十多岁。

散点图

对于这个图和下面的图,我们将使用 iris 数据集。虹膜数据集包含与花的花瓣大小(花瓣长度和花瓣宽度)和萼片大小(萼片长度和萼片宽度)相关的数据。

这些特征用于分类鸢尾的类型(刚毛鸢尾、杂色鸢尾和海滨鸢尾)。下面我们将尝试研究这些特征之间的关系。

首先,我们需要加载虹膜数据集。

df = sns.load_dataset('iris')
df.head()

散点图有助于理解数据之间的相互关系,

sns.scatterplot(x='sepal_length', y ='petal_length' ,
data = df , hue = 'species')

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

散点图

散点图需要 x 轴和 y 轴的数据。我们还可以为 hue 参数传递一个值,根据分类列给点着色。

在上图中,我们可以观察到萼片长度< 6cm and petal length >2 厘米的鸢尾花最有可能是刚毛鸢尾。虽然在杂色点和海滨点之间没有明显的界限,花瓣长度在 2 厘米和 5 厘米之间的鸢尾花最有可能是杂色类型,而花瓣长度大于 5 厘米的鸢尾花最有可能是海滨类型。

联合地块

联合图也用于绘制数据之间的相关性。

sns.jointplot(x='sepal_length' , y ='petal_length',
data = df , kind = 'reg')

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

联合地块

  • 种类 —要绘制的地块的种类。它可以是下列之一。

'scatter', 'hist', 'hex', 'kde', 'reg', 'resid'

配对图

Seaborn 让我们绘制多个散点图。当您想快速浏览数据时,这是一个不错的选择。

sns.pairplot(df)

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

配对图

它将所有连续数据配对,并绘制它们的相关性。它还绘制了数据的分布。

如果不希望将所有列配对,可以再传入两个参数 x_vars 和 y_vars。

热图

热图可用于可视化混乱、矩阵和关联。

corr = df.corr()
sns.heatmap(corr)

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

热图 1

我们可以自定义配色方案、最小/最大值和注释。

根据热图,我们可以得出结论,萼片长度与花瓣长度和花瓣宽度高度正相关,而萼片宽度与花瓣长度和花瓣宽度负相关。

sns.heatmap(corr, cmap=['red','green','blue'],
vmin = -.5 , vmax = 0.6,annot = True)

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

热图 2

可视化口袋妖怪数据集

你可以从这里下载口袋妖怪数据集。

将文件上传到 google drive。

from google.colab import files
files.upload()

如果您在本地机器上工作,可以跳过上述步骤。确保下载的文件与 Python 文件位于同一个文件夹中。

pokemon_df = pd.read_csv('pokemon.csv')
pokemon_df.head()

口袋妖怪类型分布

plt.figure(figsize=(15,8))
sns.countplot(x = 'type1' , data = pokemon_df,
hue = 'is_legendary')

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

口袋妖怪剧情 1

因为 Seaborn 是建立在 matplotlib 之上的,所以我们可以使用 matplotlib 的函数来增加图形的大小。查看图表,我们可以得出结论,水和正常是主要的口袋妖怪类型。我们还可以得出结论,传奇口袋妖怪的主导类型是精神。

进攻和防守的关系

sns.pairplot(x_vars=['attack' , 'defense','sp_attack','sp_defense'] ,
y_vars=['attack' , 'defense','sp_attack','sp_defense'] ,
data = pokemon_df)

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

口袋妖怪剧情 2

你也可以选择传递色调参数来获得更多的洞察力。

身高和体重的关系

sns.jointplot(x = 'weight_kg', y = 'height_m',
data = pokemon_df,hue = 'is_legendary')

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

口袋妖怪剧情 3

根据上面的图表,我们可以得出结论,口袋妖怪的身高和体重没有任何相关性。

你可以尝试一些其他的情节。

  • 身高/体重分布。
  • 传奇口袋妖怪 vs 非传奇口袋妖怪的数量。
  • 特攻特防回归图。
  • 显示功能之间相关性的热图。

结论

数据可视化是呈现数据的好方法,Seaborn 是您工具箱中的有用工具。因为它是建立在 matplotlib 之上的,所以您可以像使用 matplotlib 自定义绘图一样自定义您的绘图。

编码快乐!

我最近用 WordPress 创建了一个博客,如果你能看看的话,我会很高兴的😃

在 LinkedIn 上与我联系

https://www.linkedin.com/in/rahulbanerjee2699/

原载于 。2021 年 1 月 29 日木卫一

如何使用模拟进行假设检验

原文:https://towardsdatascience.com/how-to-use-simulations-for-hypothesis-tests-6f0ac53a9c8f?source=collection_archive---------17-----------------------

实践教程

如何用 Python 中的例子使用两种不同的模拟技术进行假设检验

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

照片由 ChuttersnapUnsplash 上拍摄

假设检验是统计学的重要组成部分。它们帮助我们在医疗保健、商业、伦理和许多其他领域做出重要决策。有许多很棒的资源解释了如何进行这些测试,以及如何使用像正态分布和 t 分布这样的分布来获得这些测试的结果。

本文将关注如何使用模拟为假设检验生成我们自己的分布。模拟允许我们用很少的假设来进行假设检验,并且有一个直观的结果,可以很容易地解释。

我们要看的第一个模拟技术是使用一个已知概率分布的随机变量随机生成数据。当您知道您有兴趣进行统计分析的事件结果的潜在概率分布时,这是一个非常有用的概念。

我们将使用的第二种模拟技术被称为置换假设检验。当您试图测试变量之间的相关性时,这是一个特别有用的工具。

对于这两种技术,我们将使用一个示例来计算在六面骰子上滚动的 1 的数量。我们以此为基础来描述这些模拟是如何工作的。到本文结束时,您应该了解如何将模拟应用到您感兴趣的更高级的假设测试中。

假设检验简介

在我们开始模拟之前,让我们快速回顾一下假设检验。如果您已经对此感到满意,请随意跳到下一部分。

假设检验的基本目标是了解某种治疗对结果变量的影响。例如,如果一家制药公司在一项研究中给一些参与者一种他们正在测试的新药,而另一些人收到一种安慰剂,该公司将有兴趣了解实际药物的表现是否比安慰剂更好。举个例子,这是一种减肥药,服用这种药的人比服用安慰剂的人平均多减了 10 磅。

你首先假设一个无效假设,即你在研究中观察到的结果是由于偶然。这相当于假设整个人群(除了参与研究的样本之外)的真实体重减轻了 0 磅。然后,我们需要收集足够的证据来否定这个假说,支持另一个药物有效的假说。

然后,我们将观察到的结果与 t 分布(如果我们不知道标准偏差,并且人口较少)或正态分布进行比较。我们会考虑在假设的分布下,我们多久会观察到一个和我们在实验中观察到的一样大的结果;观察到极值或比观察值更极值的概率称为 p 值。如果该概率足够低(通常为 5%),我们可以拒绝我们的零假设,即我们观察到的结果仅仅是由于机会(因为零分布不太可能代表基于我们实验的真实总体反应)。

方法 1:已知概率分布的模拟

我们将使用 Python 编写所有的代码,但是这些概念在没有 Python 知识的情况下应该很容易理解。让我们从导入一些库开始。

import numpy as np
import pandas as pd
import random
import seaborn as sns

对于第一个例子,我们想进行一个假设检验,看看一个六面骰子的权重是否相等(如果所有 6 个数字的概率相等)。我们对这个测试的零假设是所有的数字被掷出的可能性是相等的。

我们假设一个骰子有 20%的未知概率掷出 1,有 16%的概率掷出其他 5 个数字。

random.seed(100)
pop = [1, 2, 3, 4, 5, 6]
weights = [.2, .16, .16, .16, .16, .16]
skewed = random.choices(pop, weights=weights, k=200)

在观察了 200 次掷骰子(由上面的代码生成)之后,我们使用下面的函数来计算每个被掷出的数字的个数:

def count_occurences(data, minimum=1, maximum=6):
    counter = {num: 0 for num in range(minimum, maximum + 1)}
    for roll in data:
        counter[roll] += 1
    return counter

我们观察每个数字出现的次数如下:

skewed_dist = count_occurences(skewed)Out: {1: 46, 2: 29, 3: 27, 4: 39, 5: 29, 6: 30}

如果骰子的重量相等,那么当我们掷骰子 200 次时,我们预计每次掷骰子的数字约为 32,每个数字出现的概率为 16.67% (1/6)。我们注意到 1 的数量特别大,想测试一下这是否是偶然的。

由于我们已经知道每个数字在公平骰子中出现的潜在概率,我们可以模拟成千上万次掷骰子,看看在一组 200 次掷骰子中观察到 46 个 1 的可能性有多大。

我们可以使用下面的代码生成 100 次 200 个公平骰子滚动的试验:

rolls_dist_100 = [[random.randint(1, 6) for rolls in range(200)] for num_trials in range(100)]

我们应该模拟多少次试验?100 次试验够吗?这是一件需要考虑的重要事情。让我们看看在不同次数的试验中,我们看到的 1 的数量分布。

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

正如我们所看到的,更多的试验似乎能更好地去除我们结果中的随机噪声。运行更多试验的时间成本很小。因此,你应该进行的试验次数取决于你试图探索的问题。一般来说,试验越多越好。

我们将使用 100,000 次试验来获得我们的统计结果。这是我们在零假设下观察到的一的数量分布,假设每个数字的概率相等。

现在,让我们将实际观察到的 46 个结果与 100,000 组 200 个骰子滚动的结果进行比较。

# Create a list of dictionaries for the counts
roll_counts_100000 = list(map(count_occurences, rolls_dist_100000))# Store results in dataframe
counts_df_100000 = pd.DataFrame(roll_counts_100000)# Find the times where we observe a larger value
counts_df_100000['bigger'] = counts_df_100000[1] > skewed_dist[1]# Get the probability
sum(counts_df_100000['bigger']) / 100000Out: 0.0082

我们看到观察到我们所做的结果的概率大约是 0.0082(我们的 p 值)。这是非常低的,所以我们将拒绝我们的零假设,即骰子在所有 6 个面上着陆的可能性相等。我们已经知道这是预期的结果,因为我们知道倾斜骰子的真实概率分布。

方法 2:排列假设检验

现在我们将讨论排列测试。这里有一个很棒的可视化,如果你想了解更多关于这个过程的信息,你应该去看看。排列测试背后的想法是,我们给变量赋值,我们想看看这些赋值是否有意义。为了测试这一点,我们多次随机打乱赋值的顺序,看看旧的赋值与新的赋值分布相比如何。

让我们假设一个有 1000 名参与者的锦标赛正在进行,每个参与者互相掷骰子 200 次,最低的数字获胜。玩家 0 赢得锦标赛,与其他玩家相比,他有大量的零。我们想知道他是否作弊了。

我们使用以下代码生成数据:

pop = [1, 2, 3, 4, 5, 6]
weights_skewed = [.2, .16, .16, .16, .16, .16]
random.seed(100)
rolls_vs = [random.choices(pop, k=200) if person != 0 else random.choices(pop, weights=weights_skewed, k=200) for person in range(1000)]

我们使用下面的代码为每个玩家的所有掷骰子创建一个数据框。

df_vs = pd.DataFrame(list(map(count_occurences, rolls_vs)))

我们注意到参与人 0 掷出了 46 个 1,远远超过了预期的 200 个 1 的数量。我们在 200 掷的锦标赛中生成 100,000 个千位玩家的 1 的排列分布,并查看该玩家的 1 是否明显多于排列分布。

perms = [np.random.permutation(df_vs[1])[0] for i in range(100000)]

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

每个排列中玩家 0 的 1 的数量(来源:作者)

在给定分布的情况下,我们发现观察值的 p 值为 46 或更高。

sum([1 if 46 <= x else 0 for x in perms]) / 100000Out: 0.01746

我们得到 p 值为 0.017。这是一个相当低的概率,但并非完全不可信。我们期望看到这种类型的表演大约是 100 次中的 1 次。我们应该对这种表现持怀疑态度,并可能认为该球员可能在这场比赛中作弊。如果这是研究环境中的另一个测试,我们将有足够的证据来拒绝零假设,即我们观察到的结果是由于机会而支持我们的替代假设,即玩家使用倾斜的骰子。

结论

作为数据科学家,我们现在又多了两个工具来进行假设检验。只需几行代码,我们就可以用很少的假设来测试这些假设。我们不需要假设检验中经常需要的关于数据正态性的典型假设。

除了分析掷骰子之外,这些工具还有一些有趣的应用。我们现在有了分析这些问题的基本构件。这些类型的测试已经被应用到一些有趣的问题中,比如评估奥运会跳水比赛中的裁判偏差,以及评估篮球比赛中的“T2”是否存在。

感谢您阅读本文,祝您下次假设检验顺利。

Python 中如何使用奇异值分解进行图像分类

原文:https://towardsdatascience.com/how-to-use-singular-value-decomposition-svd-for-image-classification-in-python-20b1b2ac4990?source=collection_archive---------3-----------------------

用一个简单的例子揭开 SVD 背后的线性代数概念

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

Marcel strau 在 Unsplash 上拍摄的照片

线性代数中最难理解的主题之一是奇异值分解 (SVD)方法。它也是最基本的技术之一,因为它为理解主成分分析(PCA)、潜在狄利克雷分配(LDA)和一般矩阵分解的概念铺平了道路。

奇异值分解之所以难以捉摸,是因为虽然这种方法需要大量的数学和线性代数知识才能掌握,但实际应用却常常被忽视。有很多人以为自己掌握了 SVD 的概念,其实不然。这不仅仅是一种降维技术:本质上,SVD 的神奇之处在于任何矩阵 A 都可以写成秩 1 矩阵的和!这一点以后会变得明显。

本文的目的是通过将 SVD 应用于一个众所周知的例子:手写数字分类,展示 SVD 的用途和基本机制。

快速提醒(高级可选)

奇异值分解的基本关系是

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

其中:
U 和 V 是正交矩阵,
S 是对角矩阵

更具体地说:

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

其中显示了前述的权利要求,任何矩阵 A 都可以写成秩 1 矩阵的和

奇异值分解的一些有用特性:

  1. u 矩阵和 v 矩阵分别由aᵀa的特征向量构成。
  2. 任何矩阵都有 SVD 分解。这是因为 AAᵀAᵀA 矩阵有一个特殊的性质(以及其他性质):它们至少是半正定的(这意味着它们的特征值要么是正的,要么是零)。
  3. S 矩阵包含正特征值的平方根。这些也被称为奇异值。
  4. 在包括 Python 在内的大多数编程语言中,U 和 V 的列的排列方式是特征值较高的列在特征值较小的列之前。
  5. u,u …向量也被称为左奇异向量,它们形成了一个正交基*。相应的, v,v …向量称为右奇异向量。*
  6. 矩阵 A 的秩是 S 矩阵的非零奇异值的个数。
  7. 埃克哈特-杨-米尔斯基定理 : 一个秩的最佳 k 秩逼近 k < r 一个矩阵在 2-范数和 F-范数下是:

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

换句话说:

如果你想用一个较低秩的 k 来逼近任何矩阵 A,最佳的方法是对 A 应用 SVD,只取前 k 个具有最高 k 个奇异值的基向量。

Python 中的 SVD

对于这个例子,我们将使用手写数字 USPS(美国邮政服务)数据集。该数据集包含 7291 个训练和 2007 个[0–9]之间的手写数字测试图像。图像是 1616 灰度像素。首先,我们加载数据:*

*import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.linalg import svd, norm
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
import h5py
import os# define class labels
labels = {
    0: "0", 
    1: "1", 
    2: "2", 
    3: "3", 
    4: "4", 
    5: "5", 
    6: "6", 
    7: "7", 
    8: "8",
    9: "9"
}# load the dataset
with h5py.File(os.path.join(os.getcwd(), 'usps.h5'), 'r') as hf:
        train = hf.get('train')
        test = hf.get('test') x_train = pd.DataFrame(train.get('data')[:]).T
        y_train = pd.DataFrame(train.get('target')[:]).T
        x_test = pd.DataFrame(test.get('data')[:]).T
        y_test = pd.DataFrame(test.get('target')[:]).Tprint(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)#Output:
#(256, 7291)
#(1, 7291)
#(256, 2007)
#(1, 2007)*

数据的加载方式与上面快速提醒部分的尺寸相匹配。 x_trainx_test 的列包含作为向量的数字,这些数字被展平成大小等于 256 的数组(因为每个数字的大小都是 16x16)。另一方面, y_trainy_test 是行向量,分别包含训练和测试数据集的每个数字(0 到 9 之间的值)的实际类。

图 1 显示了训练数据集中的第一幅图像:

*digit_image=x_train[0]
plt.imshow(digit_image.to_numpy().reshape(16,16),cmap='binary')*

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

图 1:来自训练数据集的图像

数字分类的方法由以下步骤组成:

  1. 我们将 x_train 数据帧分成 10 个矩阵(按列),每个矩阵对应一个数字[0–9]。这些是之前提到的 A 的矩阵。目标是将 SVD 分别应用于它们中的每一个。例如,A0 矩阵仅包含数字 0 的图像,其形状为(256,1194),因为数据集中有 1194 个 0。
  2. 接下来,我们将 SVD 应用于[A0,A1…A9]矩阵。对于每个 A 矩阵,我们存储相应的 U、S 和 V 矩阵。我们将主要使用 U 矩阵。
  3. 用一个数字表示的每个数据矩阵 A 都有一个“独特的特征”。这种区别反映在前几个左奇异向量 (u,u …)。由于这些特征向量本质上是基向量,如果一个未知数字可以用另一个数字(例如数字 3)的基更好地近似,那么我们可以假设该未知数字被分类为那个数字(如 3)。这将在后面的编程示例中变得更加明显。

第一步

这相当容易。我们只是创建了[A0,A1…A9]矩阵,并将它们存储在名为 alpha _ matrices 的字典中:

*alpha_matrices={}for i in range(10):
    alpha_matrices.update({"A"+str(i):x_train.loc[:,list(y_train.loc[0,:]==i)]})print(alpha_matrices['A0'].shape)
#(256, 1194)*

第二步

这一步也很简单。我们将 U、S 和 V 矩阵分别存储在左奇异*、奇异 _ 矩阵右奇异字典中:*

*left_singular={}
singular_matix={}
right_singular={}for i in range(10):
    u, s, v_t = svd(alpha_matrices['A'+str(i)], full_matrices=False)
    left_singular.update({"u"+str(i):u})
    singular_matix.update({"s"+str(i):s})
    right_singular.update({"v_t"+str(i):v_t})print(left_singular['u0'].shape)
#(256, 256)*

让我们展示一下这些矩阵中包含了哪些信息。我们将使用数字 3 的 U、S 和 V 矩阵作为示例,在我们的示例中,它们对应于以下变量:

*#left_singular[‘u3’]
#right_singular[‘s3]
#singular_matix[‘v_t3]plt.figure(figsize=(20,10))
columns = 5
for i in range(10):
   plt.subplot(10/ columns + 1, columns, i + 1)
   plt.imshow(left_singular["u3"][:,i].reshape(16,16),cmap='binary')*

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

图 2:U3 矩阵的前 10 个奇异向量

图 2 显示了前 10 个左奇异向量[u,u … u ⁰](共 256 个)。它们都描绘了数字 3,其中第一个(u1 向量)最为清晰。

图 3 以对数标度显示了 S 矩阵中数字 3 的奇异值:

*plt.figure(figsize = (9, 6))
plt.plot(singular_matix[‘s3’], color=’coral’, marker=’o’)
plt.title(‘Singular values for digit $3$’,fontsize=15,weight=”bold”,pad=20)
plt.ylabel(‘Singular values’ ,fontsize=15)
plt.yscale(“log”)
plt.show()*

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

图 3:数字 3 的所有奇异值

给定奇异值排序,前几个是最高的(就值而言),并遵循“陡峭的曲线模式”。

通过考虑图 2图 3 ,我们可以图形化地确认 3 位 SVD 的矩阵逼近性质(记住 Eckart-Young-Mirsky 定理):第一个左边的奇异向量代表矩阵 A3 的固有属性值。事实上,在图 2 的中,第一个奇异向量 u1 看起来像数字 3,随后的左奇异向量代表 u1 周围的训练集的最重要的变化。

问题是我们是否可以只使用第一个 k 个奇异向量,并且仍然有一个很好的近似基。我们可以通过实验来验证。

第三步

给定一个由(1256)个向量表示的未知数字称为 z ,给定左奇异向量的集合 u1,u2… uk ,其中每个集合表示对应的数字矩阵/A 矩阵,那么 z 的目标值是多少?注意我们的索引是 k (第一主奇异特征向量)而不是 n (全部)。要解决这个问题,我们要做的就是以下几点:

目标是计算测试集中的一个数字在 10 个不同的标准正交基中的表现程度。

这可以通过计算以下类型的最小二乘问题中的剩余向量来实现:

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

最小二乘问题的解是

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

记住 U 矩阵是正交的。剩余范数向量变成:

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

就是这样!现在我们需要的东西都有了。使用最后一个公式,我们继续计算不同 k 值的测试精度:

*I = np.eye(x_test.shape[0])
kappas=np.arange(5,21)
len_test=x_test.shape[1]predictions=np.empty((y_test.shape[1],0), dtype = int)for t in list(kappas):
    prediction = []
    for i in range(len_test):
        residuals = []
        for j in range(10):
            u=left_singular["u"+str(j)][:,0:t]
            res=norm( np.dot(I-np.dot(u,u.T), x_test[i]  ))
            residuals.append(res)
        index_min = np.argmin(residuals)
        prediction.append(index_min)

    prediction=np.array(prediction)
    predictions=np.hstack((predictions,prediction.reshape(-1,1)))scores=[]for i in range(len(kappas)):
    score=accuracy_score(y_test.loc[0,:],predictions[:,i])
    scores.append(score)data={"Number of basis vectors":list(thresholds), "accuracy_score":scores}
df=pd.DataFrame(data).set_index("Number of basis vectors")*

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

表 1:不同 k 值的测试准确度得分

我们也可以用图形显示这个结果:

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

图 4:不同 k 值的测试准确度分数

表 1图 4* 都显示了不同数量的基向量的准确度分数。使用 k=12 可以获得最好的分数。*

接下来,显示混淆矩阵:

*pd.set_option(‘display.max_colwidth’,12)
confusion_matrix_df = pd.DataFrame( confusion_matrix(y_test.loc[0,:],predictions[:,7]) )confusion_matrix_df = confusion_matrix_df.rename(columns = labels, index = labels)
confusion_matrix_df*

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

f1 分数(宏观平均值和每节课的分数) :

*print(classification_report(y_test.loc[0,:],predictions[:,7]))*

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

*点评: *数字 0、1、6、7 在 f1-score 方面表现最好。
数字 5 和 3 在 f1 得分方面表现最差。

让我们来看一些分类错误的图片的例子:

*misclassified = np.where(y_test.loc[0,:] != predictions[:,7])plt.figure(figsize=(20,10))
columns = 5
for i in range(2,12):
    misclassified_id=misclassified[0][i]
    image=x_test[misclassified_id]

    plt.subplot(10/ columns + 1, columns, i-1)
    plt.imshow(image.to_numpy().reshape(16,16),cmap='binary')
    plt.title("True label:"+str(y_test.loc[0,misclassified_id]) + '\n'+ "Predicted label:"+str(predictions[misclassified_id,12]))*

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

显然,其中一些数字写得非常糟糕。

结论

实际上,A 数据矩阵本质上是一个低秩矩阵加噪声:A = A’ + N。通过应用 Eckart-Young-Mirsk 定理,我们用一个正确秩为 k 的矩阵来逼近数据矩阵 A。这具有保持矩阵固有属性完整的效果,同时去除了额外的噪声。但是我们如何找到正确的秩 k 呢?

在我们的案例中,我们通过对第一个主要奇异值进行实验,根据测试精度经验地找到了 k。然而,应该注意的是,当然还有其他算法优于这种技术。然而,本案例研究的重点是通过调整一种众所周知的矩阵分解技术来展示手写数字分类的另一种方法。有关这个例子的理论技术和原理的更多信息,请查阅本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值