TowardsDataScience 博客中文翻译 2020(三百七十一)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

更快和更少限制的风格转移

原文:https://towardsdatascience.com/fast-and-less-restricted-style-transfer-50366c43f672?source=collection_archive---------51-----------------------

神经类型转移,进化

基于条件实例规范化的图像风格转换

介绍

仿制品是模仿另一件作品风格的艺术作品。 风格转移 可以定义为找到一个模仿图像 p 其内容与一个内容图像 c 相似但其风格与一个风格图像 s 相似。

背景

如果您熟悉基于优化的风格传递前馈风格传递网络,请随意跳过本节。

神经类型转移算法提出了以下定义:

  1. 内容相似度 :如果由训练好的分类器提取的两个图像的高级特征在欧几里德距离上接近,则这两个图像在内容上是相似的
  2. 风格相似度 :如果由训练好的分类器提取的两幅图像的低层特征共享相同的统计量,则这两幅图像风格相似。

缓慢而随意的风格转移

在其原始公式[R1]中,神经风格转移算法进行如下:从***【p】***(例如 c、 或一些随机初始化)的一些初始化开始,该算法调整 p 以最小化图 1 中描述的个体内容和风格损失函数。

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

**图一。**基于优化的神经式传递损失公式

而上面的算法是 灵活(+) ,运行起来就是 昂贵(-)

快速和受限风格转移

为了加速上述过程,引入了称为风格转移网络*【R2】的前馈卷积网络来学习转换。它将内容图像 c 作为输入,并直接输出仿作图像 p 。使用图 2 中描述的损失函数在许多内容图像上训练网络。在测试时,变换网络 T 变换 任何 内容图像以适应与前馈网络相关联的 单个 样式图像的样式。*

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

***图二。*前馈神经式传递损失公式

虽然推论是 快速(+) ,但它是 受限的(-) ,因为每种个人风格都需要单独的网络来训练

较少限制的前馈式传输网络

先前的为每种风格建立单独网络的前馈风格传递方法[R2]忽略了许多风格可能共享某种程度的计算的事实,并且当建立多风格风格传递网络时,这种共享被从零开始训练 N 个网络所丢弃。例如,许多印象派画作的笔触相似,但使用的调色板不同。那样的话,把一套 N 幅印象派的画当作完全独立的风格来看,似乎是非常浪费的。

杜谋林等人*【R3】训练单有条件 风格转移网络 T(c,s)N 风格 。他们不是学习单一的一组仿射参数 γ ( 缩放 )和 β ( 平移 ),而是提出了一种 条件 实例归一化*(CIN在训练期间,从一组固定的样式***【S ∈{ 1,2,…,S}*** 中随机选择一个样式图像及其索引 s 。然后,内容图像由风格传输网络处理,其中在*层中使用相应的 γsβs 。令人惊讶的是,网络在** 层中使用 相同的卷积参数但不同的仿射参数,可以生成风格完全不同的图像。*

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

****图 4。条件实例规范化。输入激活 x 在两个空间维度上被归一化,随后使用风格相关的参数向量 γs 和βs 进行缩放和移位,其中 s 表示风格标签。图片取自“[R3] 艺术风格的学术代表”

CIN (图 4)层的引入允许单个网络学习风格转移为 多个风格 。它具有以下特性:

  1. 这种方法 灵活 但可与单一用途的传输网络相媲美。一个额外的优势是,人们可以通过一个批量大小为 N 的前馈通道将单个图像风格化为 N 种绘画风格(图 5.a)。
  2. 该模型将每个风格图像简化为嵌入空间中的一个点( γs,βs ),从而简洁地捕捉到各种绘画的艺术风格。嵌入空间的表现允许人们以前所未见的新方式任意组合艺术风格(图 5.b)。

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

****图 5。由风格转移网络制作的模仿品,该网络根据为其多样性选择的 32 种风格进行训练。图片摘自“[R3]艺术风格的学术代表”

结论

以上做法是 然而 灵活 有一定程度。仍然存在的一个问题是,要包含一个新的样式,您需要将它包含在集合 S 中,并再次训练网络。

参考

  1. 利昂·A·加蒂斯、亚历山大·S·埃克和马蒂亚斯·贝奇。使用卷积神经网络的图像风格转换。在 CVPR ,2016。
  2. 贾斯廷·约翰逊,亚历山大·阿拉希和李菲菲。实时风格转换和超分辨率的感知损失。在 2016 年 ECCV
  3. 文森特·杜穆林,黄邦贤·史伦斯,曼朱纳斯·库德鲁尔。艺术风格的学术代表。在 ICLR, 2017。

快速和受限的风格转换

原文:https://towardsdatascience.com/fast-and-restricted-style-transfer-bbfc383cccd6?source=collection_archive---------45-----------------------

神经类型转移,进化

使用前馈网络的实时图像风格传递

在他们的开创性工作中,“使用卷积神经网络 的 图像风格转移,”Gatys 等人【R1】展示了 CNN 在分离和重新组合图像内容和风格以创建复合艺术图像方面的功效。使用从预先训练的 CNN 的中间层提取的特征,他们定义单独的 内容风格 损失函数,并将风格转换任务作为一个 优化 问题。我们从随机图像开始,并更新像素值,从而最小化各个损失函数。更多详情请参考 这篇 的文章。

这种方法的一个明显的警告是,它是 。调整随机图像需要几次 优化 迭代,以使其适应两个不同参考图像的 内容样式 。为了解决这种低效率,约翰逊等人*【R2】提出了一种 前馈 神经网络来 近似 求解风格转换优化问题【R1】。*

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

图一。概述“实时风格转换和超分辨率的感知损失”中提出的方法。图像取自同一张纸。

*本质上,他们提出了一种 图像变换网络 ( fw ),这是一种将输入图像 x 变换为输出图像 ŷ *的深度残差卷积神经网络。样式转移的目标是生成一个图像 ŷ 该图像将目标内容图像 y_c 的内容与目标样式图像 y_s 的样式相结合。

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

图二。风格传递损失。更多详情请参考前面提到的博客

训练时,对于一个 固定 样式的目标 y_s ,图像变换网络以一个 随机 目标内容图像 y_c ( x )作为输入,生成图像 ŷ. 然后调整变换网络,使风格传递损失最小化(参见图 2)。在几次迭代的过程中,网络看到多个内容图像,但是只有一个固定样式的图像。结果,图像变换网络学会将来自任何 参考图像的 的内容与特定参考图像的样式相结合。**

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

图三。每个网络一种样式的演示。图片由提供

总之,虽然这种方法以比每图像 优化 快三个数量级的速度执行样式转移,但是它们受限于每网络一种样式****

参考

  1. 利昂·A·加蒂斯、亚历山大·S·埃克和马蒂亚斯·贝奇。使用卷积神经网络的图像风格转换。在 CVPR ,2016。
  2. 贾斯廷·约翰逊,亚历山大·阿拉希和李菲菲。实时风格转换和超分辨率的感知损失。在 ECCV ,2016。

用 NumPy 实现快速鲁棒的滑动窗口矢量化

原文:https://towardsdatascience.com/fast-and-robust-sliding-window-vectorization-with-numpy-3ad950ed62f5?source=collection_archive---------2-----------------------

探究多元时间序列数据的 NumPy 矢量化技巧。

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

宾·福什Unsplash 上拍照

偶尔,你会和数据世界的失败者一起工作:时间序列(图像和自然语言最近很受关注!).我很幸运(或者说很不幸)在去年的大部分时间里不得不处理时间序列数据。在我在一维机器学习的古怪世界中的冒险中,我发现了一些非常有用的矢量化方法,使我能够通过 blaze 完成我的数据预处理阶段。我想分享这些有助于加速我的任务的技巧,希望它能对你有所帮助。

在本文中,我们将使用多元时域模拟。我们的目标是学习如何在高性能数据管道中开发组件。NumPy 是我执行矩阵运算的首选库。我们开始吧!

概述:多元时间序列

更常见的是,你会看到时间序列是一条单线,在向上或向下前进时穿过一个图。在水平轴上,时间优雅地前进,而在垂直轴上,测量值或数值被记录。横轴上的一个单位就是我们所称的**时间步长。**多变量时间序列是相似的,不同的是,现在孤独的线伴随着平行传播的其他线。

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

单变量时间序列和多变量时间序列,但是你已经知道了。图片作者。

多变量时间序列数据的一个常见例子是气象站定期测量温度、湿度、压力和环境的其他方面。另一个是脑电图,它使用多个电极捕捉大脑活动,并行产生许多读数。更抽象地说,活页乐谱可以被解释为多元时间序列:乐器是在乐曲的固定采样时间(节奏)内不同的信息通道。

电力系统暂态稳定中的电压

我的研究着眼于电力系统发生故障时的暂态稳定性。在电力系统故障期间,采取措施来减轻灾难。根据系统所处的状态、故障发生的位置以及清除故障需要多长时间,系统可以有两种方式:回到稳定或转向不稳定。确定这一点的一种方法是模拟一堆状态、故障位置和清除时间,然后从系统的动力学中学习,以预测系统是稳定还是爆炸(好吧,不是真的)。

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

一个简单的电力系统,有 3 台发电机、9 条母线和 9 条线路。图片来自郑等(2018)。综合动态 PMU 数据生成:生成对抗网络方法。

我们获取的数据来自电力系统中不同母线(粗实线)在一段时间内的相量测量。由于有许多总线,每个总线测量不同类型的数据,这自然有助于多变量时间序列数据。出于本文的目的,我们将使用其中的一些模拟数据。众所周知,可以通过取整个数据的一小部分来预测暂态稳定现象。大多数剩余的时间序列是多余的。

我们的目标是为训练数据集提取信号的重要区域。

在深入研究和扩展提取器的功能之前,我将首先介绍基本提取的核心概念。您可以在此链接或我的网站上找到 9 路公交车系统的数据集,它是一个包含 NumPy 矩阵文件和一些元数据的 gzip 文件夹。这里特别重要的元数据栏是清除时间。如果你愿意,可以花几分钟来消化这些数据。

用于绘制 9 总线数据集中的数据点编号 693 的代码。

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

693 号案件的所有信息。有 9 条电压母线和 3 条发电机母线。我们可以将所有这些组合成一个 24 通道的多元时间序列数据。图片来自作者。

开始简单:基本的滑动窗口提取

我们想要的信号部分是模拟的清除时间前后的。我们希望在结算时间之前和结算时间之后有一个信息窗口;叫做主窗口。清除时间后,主窗口可以跨越某个最大时间步长,我们称之为最大时间。在主窗口中,我们想要一堆更小的窗口,称为子窗口,它们将组成我们的训练示例。主窗口应该在清除时间之前提供子窗口大小的时间步长。这很难捕捉,但也许一个数字可以帮助我们理解这些窗口的结构。我们将使用案例 693 的电压幅度进行所有说明。**

基本的滑动窗口方案;我们的目标是提取右边的子窗口。图片来自作者。

本质上,我们希望在主窗口中一步一步地滑动子窗口,并在每个时间步长收集信息。第一子窗口必须包含清除时间之后的第一时间步。这里的基本原理是,我们只知道故障在系统中被清除的时间(清除时间)。因此,我们最早可以获得可用数据的时间是清除后的下一个时间步。

一个小例子

让我们捕获一个最大时间为 10 个时间步长的主窗口。在主窗口中,我们可以取 11 个大小为 5 个时间步长的子窗口。视觉上:

 *1st timestep after clearing --|           |-- max time
                                v           v
main_window = [..., 5, 6, 7, 8, 9, 10, ..., 19]
                             ^
       clearing time index --|sub_windows = [
    [ 5,  6,  7,  8,  9],
    [ 6,  7,  8,  9, 10],
    ...
    [15, 16, 17, 18, 19]
]*

因此,如果我有一个最大时间 T 和一个大小为 K 的子窗口,我可以从一个模拟中获得 T +1 个示例(包括最大时间的索引)。这个方案忽略了 K,因为我们可以将 K 增加到我们想要的大小,这反过来会增加主窗口左半部分的大小(假设我们没有下溢数据矩阵)。这意味着用大小为 5 或 8 的子窗口提取数据会得到相同数量的子窗口,但子窗口大小不同。

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

我们可以替代任何子窗口大小,只要左半部分的数据可以容纳。图片来自作者。

厉害!现在我们有了框架,我们可以大致规划提取功能。我们将输入信息作为一个二维(2D)矩阵,其中时间步长沿行向下传播,特征分布在列上。从视觉上看,具有 4 个特征和 6 个时间步长的样本输入矩阵如下所示:

 *Feature 1  Feature 2  Feature 3  Feature 4
  ------------------------------------------
[[ -5.29328 , 9.89139  , -2.79590 , -8.73531 ], Time=1 |
 [ -5.29345 , 9.89152  , -2.79595 , -8.73542 ], Time=2 |
 [ -5.29396 , 9.89200  , -2.79644 , -8.73593 ], Time=3 |
 [ -5.29416 , 9.89222  , -2.79671 , -8.73614 ], Time=4 |
 [ -5.29451 , 9.89257  , -2.79702 , -8.73649 ], Time=5 |
 [ -5.29479 , 9.89258  , -2.79732 , -8.73643 ]] Time=6 V*

我们的目标输出矩阵是一个类似于这样的 3D 矩阵(假设我们想要一个大小为 4 的滑动窗口):

 *Feature 1  Feature 2  Feature 3  Feature 4
   ------------------------------------------
[[[ -5.29328 , 9.89139  , -2.79590 , -8.73531 ],  Time=1 |
  [ -5.29345 , 9.89152  , -2.79595 , -8.73542 ],  Time=2 |
  [ -5.29396 , 9.89200  , -2.79644 , -8.73593 ],  Time=3 |
  [ -5.29416 , 9.89222  , -2.79671 , -8.73614 ],  Time=4 V [ -5.29345 , 9.89152  , -2.79595 , -8.73542 ],  Time=2 |
  [ -5.29396 , 9.89200  , -2.79644 , -8.73593 ],  Time=3 |
  [ -5.29416 , 9.89222  , -2.79671 , -8.73614 ],  Time=4 |
  [ -5.29451 , 9.89257  , -2.79702 , -8.73649 ],  Time=5 V [ -5.29396 , 9.89200  , -2.79644 , -8.73593 ],  Time=3 |
  [ -5.29416 , 9.89222  , -2.79671 , -8.73614 ],  Time=4 |
  [ -5.29451 , 9.89257  , -2.79702 , -8.73649 ],  Time=5 |
  [ -5.29479 , 9.89258  , -2.79732 , -8.73643 ]]] Time=6 V*

这应该是微不足道的:只需在时间步长上循环,并切割矩阵的行以获得子窗口。

(朴素的)滑动窗口提取器

用 for 循环提取主窗口的片段。很有效率吧?

该函数获取从中提取数据的数组*、作为我们清除时间索引的清除时间索引、最大时间步长 ( T )和子窗口大小 ( K )。首先,我们声明一个空列表来存储我们的输出子窗口。然后,我们定义开始索引,这是滑动窗口将开始的索引。使用前面解释的 T +1 规则,我们知道我们期望多少个数据点。剩下的就是一个 for 循环,使用良好的旧切片从数组中提取数据。*

因为我们的目标是收集一组 2D 矩阵,所以明智的做法是使用 3D 矩阵批量堆叠数据,其中第一维会告诉您有多少个 2D 矩阵可用。因此使用expand_dimsvstack来实现这一点。

这个解决方案有多好?

这看起来是个好办法,对吧?还不算太糟。或者是?嗯,Python for-loops 是出了名的慢,我们没有利用 NumPy 的花哨的索引功能。目前,我们确实没有什么可以与 for-loop 方法进行比较的,但要努力说服自己,它确实不好,我们可以做得更好。因此,让我们来看看一些有趣的索引技巧,它们将帮助我们实现极快的滑动窗口提取功能。

一些奇特的矢量化技巧

诀窍#1: 我们可以使用整数索引的 1D 矩阵任意索引 2D 矩阵的任意行。

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

10×3 矩阵 x 的一维行索引。图片来自作者。

我们所做的是通过使用一个索引数组从 2D 矩阵 X 中挑选出行索引 7、4、1 和 2。通过知道我们需要什么索引,NumPy 允许我们放弃循环,而是立即索引我们需要的行。

滑动窗口中单个子窗口的模拟是索引一组连续的数字。

但是,实际上,与我们在原始代码中使用的切片相比,这并没有更有用,因为您需要循环并创建连续的索引数组来提取所有的子窗口。然而,第一招只是一个更强大的招数的前奏。

诀窍#2: 我们可以使用整数索引的 2D 矩阵来索引 2D 矩阵的行的任何 2D 子矩阵(哇,这是一口 2Ds)。

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

矩阵 x 的二维行索引。图片来自作者。

这有点难以理解,但让我们了解一下发生了什么。首先,我们创建了一个矩阵, I,,这是一个 3×4 的整数矩阵。然后,我们使用 NumPy 的花式索引将多行 X 索引在一起,得到一个 3D 矩阵。输出 3D 矩阵的第一个索引是 2D 矩阵,就好像我们在矩阵 X 上使用了具有索引[7,4,1,2]的技巧#1 。类似地,3D 矩阵的第二个索引是对具有索引[5,6,8,9]的 X 应用技巧#1 的输出。能不能算出输出 3D 矩阵的第三个索引?

基本上,我们已经找到了在起始代码中向量化外部 for 循环的方法:我们可以创建一个包含模拟数据连续索引的 2D 整数矩阵,并应用技巧#2 快速提取包含这些子窗口的 3D 数组。相反,如果我们用下面的矩阵代替矩阵 I ,我们可以很快得到我们的滑动窗口子窗口。

*I = np.array([[0, 1, 2, 3],
              [1, 2, 3, 4],
              [2, 3, 4, 5])*

既然我们知道我们可以任意地索引任何 2D 矩阵,我们可以想出一种系统的方法来组成矩阵 I ,以便我们可以将这种索引推广到任何子窗口大小以及任何最大时间来矢量化滑动窗口提取。

滑动窗口索引器的数学

这部分有点重数学,有很多符号在飞来飞去,所以如果你不明白,请随意发表评论。

知道了第二招,我们想要提取的是一个连续索引的 2D 矩阵,它等于子窗口的宽度。主窗口将从清除时间加 1(C)减去子窗口大小( K )直到最大时间( T )。具体来说,我们希望使用以下( T+1) × K 索引器矩阵对我们的数据进行奇妙的索引:

 *[[C-K+1  , C-K+2  , C-K+3  , ..., C   ]
    [C-K+2  , C-K+3  , C-K+4  , ..., C+1 ]
I = [C-K+3  , C-K+4  , C-K+5  , ..., C+2 ]
    [                           ...,     ]
    [C+T-K+1, C+T-K+2, C+T-K+3, ..., C+T ]]*

好吧,我必须承认,我确实花了一些时间来理解这个矩阵(主要是因为 Python 的 0-索引方案)。但是,本质上,这是将技巧#2 应用到我们的滑动窗口提取中的一般情况。理想情况下,我们也可以在不使用 for 循环的情况下生成这个 2D 索引器矩阵:它们太慢了!实际上,我们可以通过计算起始指数来大大简化这个矩阵。起始指数( S )计算为S*=*C-K+*1 =*C-(K-1)。因此,我们可以用更简单易懂的方式来表示我们的指数矩阵:

 *[[0    , 1    , 2    , ..., K-1  ]
        [1    , 2    , 3    , ..., K    ]
I = S + [2    , 3    , 4    , ..., K+1  ]
        [                     ...,      ]
        [T    , T+1  , T+2  , ..., T+K-1]]*

*简单来说,我们将偏移量 *S、加到一个( T+ 1 ) × K 矩阵中。该矩阵具有跨越从 0 到 K - 1 的列的连续值行,并且每一行从从 0 到 T 的连续值行开始。我们知道我们将有 T +1 个子窗口,所以我们只需要有连续的索引,直到子窗口 T +1 次的大小。这将得到与上面相同的矩阵。事实上,我们可以用更简单的分解来表示这个矩阵:

 *[[0  , 1  , 2  , ..., K-1]    [[0, 0, 0, ..., 0] 
     [0  , 1  , 2  , ..., K-1]     [1, 1, 1, ..., 1]
S +  [0  , 1  , 2  , ..., K-1]  +  [2, 2, 2, ..., 2]
     [               ...,    ]               ...,
     [0  , 1  , 2  , ..., K-1]]    [T, T, T, ..., T]]*

你们中精明的人可能已经从第二个矩阵中看到了这一点,但是让我们来看一下。因为我们知道每个子窗口的大小为 K,我们只需要做一次连续索引的矩阵。同样,有了 T +1 个连续子窗口的信息,我们只需要将值【0,1,2,…】, T 一次一个地加到每个子窗口索引上。

使用一种称为广播的聪明的向量化技术,我们甚至不必构建加法的整个中间和右边的 2D 矩阵。相反,我们只需要创建一个 1× K 和一个( T +1)×1 矩阵,而不是两个( T+1) × K 矩阵:

 *[[0]
                                   [1]
S + [[0  , 1  , 2  , ..., K-1]] +  [2]
                                   ...
                                   [T]]*

通过广播中心行矩阵和右列矩阵的加法,就可以得到我们需要的原始( T+1) × K 矩阵。让我们看看代码。

矢量化滑动窗口提取器。多优雅啊。不再有 for 循环!

性能比较

如果优雅对你来说还不够有说服力,也许硬数字可以。为了测试性能,我首先使用 NumPy 的random.randn函数创建了两个矩阵, XY ,它们大小相等但数据不同。这确保了两个函数之间的任何计算不会在运行之间被缓存。然后我在 X 上运行基于循环的提取器,在 Y 上运行矢量化提取器。提取产生大小为 1201×10×200 的矩阵。

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

10.8 毫秒降低到 3.97 毫秒。这大约是 272%的加速!图片来自作者。

多么显著的速度提升啊!我们的矢量化实现绕过了基于循环的提取器。当您处理多个文件并希望从许多不同的文件中一次提取一个窗口时,这特别有用。然而,这种方法有一些注意事项。使用 for 循环,我们可以提取数据,而不必创建 2D 矩阵来索引原始矩阵。这在内存上肯定是“更容易”的,但是我认为由于我们的输出矩阵比索引器矩阵大得多,最终这是决定性的内存消耗者。

这几乎是它的核心。现在让我们探索如何充分利用这种矢量化来对时间序列数据执行其他操作。

使得滑动窗提取器更加坚固

好吧,让我们添加更多的功能到我们的窗口提取器。当然,我们将保持矢量化的风格。

大步走,不仅仅是滑行

如果我们想要滑动窗口超过一个时间步长呢?像这样:

请注意,每张幻灯片上的子窗口开始时间跳跃了两个时间步长。图片来自作者。

借用卷积神经网络滤波运算的术语,我们把这个叫做跨窗。你可以想象这是对我们索引矩阵的一个相对简单的扩充。具体来说,我们正在研究这样一个索引矩阵:

 *[[0 ] 
                                    [V ]
S + [[0  , 1  , 2  , ..., K-1]]  +  [2V]
                                    ...
                                    [T ]]*

我已经用完了聪明的符号名称,所以我将把空格数表示为 V 代表的步幅。当 V 为 1 时,这就是我们上面的基本滑动窗口代码。任何较大的整数值将决定它跳跃多少,从而产生一组较小的输出子窗口。我们需要小心:因为我们的最大时间( T )没有改变,我们需要考虑减少最右边向量的大小。有两种方法可以解决这个问题:

  1. 创建整个索引数组(就像我们之前所做的那样),并进行巧妙的索引以从该数组中选择每一个 V 行,或者,
  2. 创建最右边的向量,看起来像上面的块。

让我们对这两个实现进行编码。

以两种方式实现 windows。注意有一个新的参数“stride_size”。

不确定哪个更好?让我们像以前一样做一个类似的测试,并测量性能。

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

关于两种变体的同等性能。图片来自作者。

我现在传递给函数的参数中唯一的不同是步幅大小为 3。正如您所看到的,没有太大的区别,但是变体 1 比变体 2 稍微慢一点(但是可以忽略不计)。我将变体 1 中的这种缓慢归因于它必须生成一个完整的(T+1)×K矩阵,然后对其进行切片。相比之下,变体 2 立即创建步幅指数,从长远来看,这可以节省时间和内存。

缩减采样子窗口

在我的研究中,模拟器能够产生比实际可能频率高得多的信号。真实世界的设备通常以大约 50Hz 或 60Hz(每秒 50/60 时间步)进行采样,而模拟器可以生成 1kHz 以上的数据(>每秒 1000 时间步)。对模拟数据进行下采样对于训练可在生产环境中部署的模型非常有用。

除了创建一个跨越子窗口向量之外,我们可以使用前面跨越窗口部分中介绍的相同技术轻松地对子窗口进行下采样。但这只有在我们的下采样速率能被整除的情况下才能实现。例如,如果我们必须对 1kHz 到 100Hz 进行下采样,我们只需在子窗口中每 10 个时间步长进行一次(我们的下采样比率(R)为 10)。然而,如果我们对 1kHz 至 60Hz 进行下采样,我们需要每 16.667 个时间步长进行一次,这不是一个整数下采样比。

蓝色块是一个连续的阵列,只是以均匀间隔的时间步长进行采样。注意右边图中的时间跨度。图片来自作者。

我们可以通过舍入步骤乘以下采样比率( R )来作弊,但不会有太大问题。当 R 等于 1 时,这又是我们的基本滑动窗口。更重要的是,我们还需要考虑如何分隔数据窗口。我们想要一个特定的子窗口大小,它现在有一个采样率的间隔。此外,我们需要捕捉的最大时间步长也有类似的间隔。让我们看看我们的好朋友,黑客帝国:

 *[[0 ] 
                                         [R ]
S' + [[0  , R  , 2R  , ..., (K-1)R]]  +  [2R]
                                         ...
                                         [TR]]*

*这里有几点需要注意。*S’是考虑间隔开的子窗口的新的起点索引, R 是我们的下采样比率,并且相应地,我们必须调整间隔以捕捉期望的最大时间步长。注意: R 不应小于 1;否则,您将在单位时间步长之间采样数据,这需要插值。

计算 S’ 比较简单,我们只需要从清零时间( C )中减去子窗口的大小( K )减去一乘以采样率;数学上我们有S ’ = C-(K-1)R。这将确保清除后的第一个时间步长是第一个索引中的最后一个数据点。好了,数学够了,我们来编码吧。

滑动窗口和缩减采样一气呵成,你还想要什么?

下采样窗口保持与标准滑动窗口相同的输出窗口大小,但占用更大的时间比例。如果您希望保持数据大小相似,但覆盖间隔更大的时间步长,这将非常有用。

结论

我希望您已经找到了一些非常棒的技巧来帮助您矢量化滑动窗口预处理工作流。改变你的思维方式,在没有 for 循环的情况下进行矩阵操作可能会很困难,但是一旦你掌握了诀窍,就会感觉更自然。我最大的挑战是思考高维矩阵的输出,这感觉很陌生(有时仍然如此)。

我对这种技术的唯一不满是代码的可维护性降低了,因为您必须确保使用您代码的人能够理解矢量化在做什么。这意味着在函数旁边有可靠的文档是至关重要的,合理地命名变量对于其他人的理解是至关重要的。

对基本滑动窗口矢量化的扩展有望激发您尝试自己的复杂矢量化,以加速您的数据管道。当你启动它的时候,你会觉得自己像个忍者,真的!尽管如此,性能的提高将使您等待文件处理的时间大大减少。还有什么更好的方法来保持更多的工作,并尽量减少你的空闲时间。对吗?

使用 Presto 或 BigQuery 和 VerdictDB 快速计算大数据系统

原文:https://towardsdatascience.com/fast-counts-on-spatial-big-data-systems-using-presto-or-bigquery-and-verdictdb-ce2ac82b9b37?source=collection_archive---------40-----------------------

当用户可以定义自己的谓词时,如何一致快速地(不到 4 秒)获得数十亿行的计数估计值?

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

克里斯·贾维斯在 Unsplash 上的照片

问题是:

“创建一个系统,客户可以通过选择和组合不同的滤镜来设计自己的受众”

在本文中,我不会深入分析这个问题,但是我们最终找到了一个可以生成“查询”(不一定是 SQL)的系统,我们可以对我们的数据仓库运行该系统来产生受众。

其中棘手的部分是 “我们如何向客户展示对受众规模的估计”?

由于最终用户可以从 8 个过滤器的任意组合中设计受众(每个过滤器包含 100-1000 个选项,这些选项会随着新数据的进入而频繁变化),预缓存每个处理的计数实际上并不可行,特别是因为我们还提供了在特定日期之间进行过滤的功能,这意味着每个日期范围也需要预缓存!

早期实验

我们决定使用一个示例查询作为我们的基本基准测试用例,它看起来像这样:

示例查询

我们尝试了许多不同的方法来感受每个平台及其提供的功能。自然,我们从基础和众所周知的产品开始,但是,我们有许多来自每个数据库/数据仓库的不同需求,这在许多方面并不能真正与它们进行公平的比较(例如,我们需要地理空间功能,这排除了许多其他平台)。

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

为什么 count(distinct())是准确性之王—但肯定不公平。

大多数读者会理解 count(distinct())是做什么的,但许多人不理解(或想不到)的是它是如何做什么的。

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

非重复计数操作的查询计划

在一个巨大的数据集中计算不同的实体实际上是一个困难的问题,如果对数据进行排序会稍微容易一些,但是根据所使用的底层平台,在每次插入时对数据进行重新排序会变得非常昂贵。

通常,非重复计数执行非重复排序,然后对分组值的每个“桶”中的项目进行计数。

如果您需要 100%准确的计数,那么不幸的是,这几乎是您在随机数据集上获得计数的唯一方式,您可以在如何在平台中构造事物方面做一些技巧,以使事情更有效(例如,分区、聚类/分块),但它本质上仍然必须执行相同的操作。

权衡——精度与速度

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

卢克·切瑟在 Unsplash 上的照片

通常有一些用例**不要求 100%的准确性,**我们的就是其中之一,因为观众规模只是一个估计值——这给了我们一些额外的选择。

有许多现有的采样方法,但它们的精度对于我们的要求来说太低了——在这种情况下,我们需要一些具有正确平衡的方法。

使用 VerdictDB 的解决方案

在这个过程的早期,我们联系了 VerdictDB,他们发布了一个开源产品的早期测试版,声称完全符合我们的要求。VerdictDB 使用概率/统计理论在大型数据集上创建基数估计值。但对我们来说最重要的是,它允许在整个表上创建。

我们使用气流建立了一个管道来协调数据准备,以确保一切就绪

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

所有的错误!

VerdictDB 通过创建表的“扰码”来工作,这是一个预处理阶段,需要大量的处理能力,但只需要在添加新数据时进行一次。

我们在 Presto 和 BigQuery 上都执行了这一操作——big query 对于我们的特定用例来说更便宜,但这有许多原因(不适用于本文)。

决赛成绩

下表列出了每种方法的最终结果。作为后台数据仓库,BigQuery 脱颖而出有许多不同的原因,但是它的焦点实际上是 VerdictDB 在简单性和速度方面相对于传统方法(如 HyperLogLog)真正能提供什么。

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

结论

通过使用 VerdictDB,Presto 和 BigQuery 都提供了允许人类界面进入我们的数据仓库所需的速度,BigQuery out 在许多领域都表现出 Presto 的性能,特别是当 BigQuery BI 进入等式时,尽管这仍处于测试阶段,仅提供 10GB(应该足以缓存 1TB 数据的 1%加扰),但它在提供大数据的经济高效和快速界面方面具有巨大的潜力。

如果您想避免供应商锁定,那么 Presto 是一个很好的选择,但是需要考虑延迟和您用来确保足够快的分区模式!一旦在 Presto 上构建了扰码,还有其他几个选项可以用作查询接口。

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

快速离散弗雷歇距离

原文:https://towardsdatascience.com/fast-discrete-fréchet-distance-d6b422a8fb77?source=collection_archive---------22-----------------------

如何提高离散弗雷歇距离计算性能?

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

安德里·波迪尔尼克在 Unsplash 上拍摄的照片

一个人牵着一条狗在散步:这个人可以在一条曲线上走,狗在另一条曲线上走;两者都可以改变速度,但不允许回溯。足以穿过两条曲线的最短皮带长度是多少?[1]

上面的引用有助于发展两条曲线之间的弗雷歇距离的定义的直觉。它的离散对应物测量两条有向多边形线之间的相似性,定义为某个度量空间中的连接点集合。在定向的多边形线中,顶点序列是感兴趣的,并且描述了方向,就像车辆的轨迹。其他相似性度量,如 Hausdorff 距离,不考虑线的方向,并且对于顶点接近但方向相反的多边形线产生高相似性。

我已经在的另一篇文章中描述了这个相似性度量,在那里我讨论了基于动态编程的原始实现。我通过线性化算法(用两个嵌套循环代替递归)提供了一个速度优化版本,性能提高了近 10 倍。虽然新的升级算法运行速度更快,但它仍然消耗相同数量的内存,这对于非常大的折线是不可取的。

本文提供了同一个算法的两个备选实现,根据最近的一组论文[2,3],这两个实现包含了性能改进。第一种实现使用线性数组来存储数据,而第二种实现使用基于字典的稀疏数组来存储非常大的折线。所有代码都使用 Numba 包进行 JIT 编译,以获得最佳性能。

逻辑优化

如前所述,计算离散弗雷歇距离(DFD)需要构建一个矩形矩阵,其维数对应于每条折线中的点数。原始的动态规划算法通过对每个元素执行距离计算来填充整个数组。然后,它将该距离与左侧和顶部邻居的递归计算值进行比较。显然,折线越大,算法计算矩阵的时间就越长。

我们可以通过线简化算法减少每条折线中的点数,让算法运行得更快,比如著名的 Ramer-Douglas-Peucker 算法。我过去曾用这种算法帮助我在地图上显示非常大的轨迹。它的工作原理是从折线上移除点,同时保持其整体形状。用户获得相同的信息,而地图显示软件避免处理无用的顶点,从而提高性能和响应能力。我不会在这里探讨这种优化,将在以后的文章中探讨。

另一个优化隐藏在 DFD 计算数学中,并且类似于动态时间扭曲相关的“扭曲窗口”概念。我们只需要计算一些靠近主对角线的矩阵元素。通过不计算所有其他项目,我们不仅提高了速度,还可以在非常大的折线上节省内存。这种优化也意味着我们必须考虑不同的数据结构来存储矩阵,可能是一个稀疏的数组。除了避免计算不必要的数据,我们也不分配不必要的内存。

如果你看一个完全计算的矩阵,优化的想法变得明显。为了了解这一点,让我们看一个例子。我们将计算欧几里得空间中定义的两条折线的 DFD。

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

这是我们将用来说明快速 DFD 计算的两条示例折线。

多段线坐标如下。

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

上图显示了两条折线的笛卡尔坐标。

现在,我们可以计算两条折线之间的距离矩阵。注意,在算法执行期间,该步骤不会完全发生。我在这里使用它只是为了说明,因为它清楚地说明了当你远离对角线时,值是如何增加的。改进的算法利用这一特性来减少计算次数和所需的存储空间。

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

上面矩阵的每个单元对应于两条折线的边之间的欧几里德距离。

我们从只考虑对角线单元开始,但是尽管在正方形矩阵上定义对角线非常简单,但是矩形矩阵的对角线需要更多的工作。代替论文的方法,我决定重温一个老朋友, Bresenham 的画线算法。如果你把一个矩阵想象成一个光栅显示器,算法的有用性就变得显而易见了。我没有使用该算法来画线,而是使用它来生成矩阵索引对,以连接左上角和右下角。

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

在对角线确定之后,我们只得到那些单元的距离值。上图描述了这一步的结果。粗体显示的是最大对角线值,它对后面的内容很重要。

在计算对角线后,我们将它的最大值作为最终距离的上限。该算法从左到右遍历对角线,计算每一列的距离,如果它们小于参考最大值,则存储它们。同样的过程也适用于行。下图描述了与此案例相关的结果。为了便于阅读,我用浅蓝色背景突出了对角线。

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

上图显示了算法的第一步。我们计算对角线下方及其右侧的所有距离,直到估计的最大值( 2.64197 )。

相对容易看出我们节省了多少内存。我们只储存了其中的 26 件,而不是预期的 42 件。尽管如此,我们计算出的距离比我们保存的距离要多,这在下图中有所描述。

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

黄色背景的单元格表示计算出的距离没有存储在矩阵中,因为它们大于对角线最大值。

我们不能依靠传统的 NumPy 阵列来节省 RAM,因为这些阵列会分配不必要的内存。这里我们将使用基于字典的稀疏矩阵,我将在下面讨论它的实现细节以及代码优化。

我们现在准备进入第二步,进行最后的计算。首先,我们必须创建一个新的矩阵,弗雷歇矩阵,来存储最终的结果。该过程从将距离对角线数据复制到弗雷歇矩阵开始。接下来,我们从对角线开始迭代每个距离矩阵元素,并应用一个简单的算法来计算最终的弗雷歇像元值。

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

上面的公式基于距离矩阵 D 中的相应值以及左侧和顶部的三个相邻值来确定弗雷歇矩阵 F 中的值。如果其中任何一个缺失,我们用无穷大来代替它。D 矩阵的第一个对角线值被复制到 f。

最终计算沿着距离矩阵对角线进行。一旦完成,弗雷歇矩阵看起来像下面的图像。

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

最终的弗雷歇矩阵源自距离矩阵。与往常一样,两条折线之间的距离位于左下角的元素中。

请注意,由于计算是如何进行的,可以不使用第二矩阵(F ),而仅使用距离矩阵(D)来执行所有计算。与往常一样,最终距离值位于右下角的单元格中。

代码优化

您可以在其 GitHub 库中找到本文的所有代码。除了 DFD 最初的实现之外,代码现在还包含了另外两个基于论文见解的实现。对于较小的折线,可以使用名为 FastDicreteFrechetMatrix 的基于 NumPy 数组的版本。对于较大的折线,您可能应该使用稀疏数组版本,称为fastdiscrechetsparse。最后一个版本使用字典来模拟稀疏数组。

现在大部分代码都使用 Numba 进行了 JIT 编译,从而显著提高了性能。这个包的目标是科学计算代码,并且理解 NumPy 的大部分代码,让你的代码快如闪电。使用 Numba 时,有一些事情需要注意。

您将注意到的第一件事是编译后的代码首次执行速度很慢。这种延迟是由于编译的 JIT 阶段造成的,在这个阶段,Python 代码被转换成机器代码。所有后续运行将全速进行。

Numba 的第二个问题是,由于 Python 和 NumPy 的兼容性问题,它需要一些时间来适应。不是所有的代码都能工作,即使工作了,也不会提高性能。您应该通读软件包的文档以充分利用它。当你明白如何使用它时,Numba 就是一种乐趣。

表演

为了了解这些算法是如何执行的,我建立了一个 Jupyter 笔记本来比较两组轨迹(请参见附带的代码)。第一套比较小,91 和 107 分,第二套大一点,263 和 477 分。这些代码针对这两个集合运行所有四个算法,正如你在笔记本中看到的。

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

下表显示了作者的 MacBook Pro 上以毫秒为单位测量的执行时间。

如你所料,最初的递归算法总是慢很多。接下来是它的线性适应,运行速度要快得多(一个数量级)。然后,我们混合了改进算法的稀疏实现的结果。在较小的集合中,它比前两个运行得更快,但在较大的集合中运行得更慢。这种性能差异是由于基于字典的稀疏阵列实现造成的,它不能很好地扩展。这段代码的未来版本将集中于用一个更高性能的组件来替换这个组件,尽管还不清楚这可能是什么。最后,改进算法的基于阵列的实现始终更快。

看起来,对于当前的实现,我们将不得不在速度和大小之间达成妥协。不幸的是,对于非常大的折线,我们将不得不使用速度较慢的算法。希望这在未来会有所改善。

结论

本文使用最近的一篇论文的结果回顾了离散弗雷歇距离的性能改进。不用计算所有的距离对,我们可以集中在距离矩阵对角线周围的一组有限的单元上。这种方法不仅节省了空间,还提高了性能。

在以后的文章中,我将说明离散弗雷歇距离在轨迹聚类中的使用。要聚合的每个项目都是由可变数量的位置定义的地理空间轨迹,DFD 是这种情况下选择的距离度量。本文中提出的性能改进毫无疑问会在那里有用。

参考

[1]托马斯·海特和海基·马尼拉。**计算离散弗雷歇距离。**技术报告 CD-TR 94/64,克里斯琴·多普勒专家系统实验室,奥地利维也纳技术大学,1994 年。

[2]t . devo gele,Etienne,l . es nault,m .,& Lardy,F. (2017)。优化轨迹间的离散弗雷歇距离。 第六届 ACM SIGSPATIAL 大地理空间数据分析研讨会会议录——Big spatial’17https://doi.org/10.1145/3150919.3150924

[3]托马斯·德沃盖尔,马克森斯·埃斯瑙特,洛朗·艾蒂安。 距离 discrète·德·弗雷切特优化 空间分析和地理信息(SAGEO),2016 年 11 月,法国尼斯。

[4]小群林、安托万·皮特鲁和斯坦利·塞伯特。2015. **Numba:一个基于 LLVM 的 Python JIT 编译器。**在HPC 中 LLVM 编译器基础设施第二次研讨会会议录(LLVM’15)。美国纽约州纽约市计算机械协会,第 7,1–6 条。https://doi.org/10.1145/2833157.2833162

资源

GitHub 知识库

相关文章

[## 你的狗带应该有多长?

计算曲线间的离散弗雷歇距离。

medium.com](https://medium.com/iotransportation/how-long-should-your-dog-leash-be-ba5a4e6891fc) [## joo Paulo Figueira—数据科学家—TB . LX by Daimler Trucks & bus | LinkedIn

查看 joo Paulo Figueira 在全球最大的职业社区 LinkedIn 上的个人资料。圣保罗列出了 1 份工作…

www.linkedin.com](https://www.linkedin.com/in/joao-paulo-figueira/)

数据科学家匆忙进行变压器快速实验

原文:https://towardsdatascience.com/fast-experimentation-with-transformers-for-data-scientists-in-a-rush-da0f5240dce3?source=collection_archive---------34-----------------------

用 huggingface/transformers repo 创建低代码、有用的实验管道比你想象的要容易

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

杰克·吉文斯在 Unsplash 上的照片

用 NLP 快速实验让你产生很多价值

如果你正在读这篇文章,你可能在某个时候遇到了和我一样的问题:你有一个 NLP 数据集和任务要解决,需要执行快速实验来产生价值,并把一个模型投入生产。

你打开了拥抱脸/变形金刚,看到了很多例子——它们都起作用了。当它适应你自己的数据集和任务时,代码太长,太具体,不能用于你的目的。

这篇文章将帮助你利用 HuggingFace 预训练转换器和库,为你自己的 NLP 任务和数据集创建低代码、有用且易于适应的管道。今天我们将集中讨论分类,但是,如果你们都喜欢这个帖子,我可以继续这个系列的任务,如问答、翻译等…

所以让我们把手放上去!

开始之前

在你开始之前,确保你有所有的要求,在我们的回购上声明。我们将使用 Kaggle 的数据集,其中包含被标记为垃圾邮件或非垃圾邮件的电子邮件。为了对它进行预处理,我将 csv 文件作为 Pandas dataframe 导入,重命名列并将它分成两个 csv 文件,用于训练和测试目的。

我已经为您预处理过了,所以您可以在 repo 上访问它。无论如何,如果你愿意,这里是我对数据集做的操作:

为了运行我们将在这里构建的脚本,请确保将 text 列命名为“sentence ”,将 labels 列命名为“label”。

我们现在准备出发了。

实施路线图

对于本文,我们的实施路线图将是:

  • 导入我们将在这里使用的每个库,并解释我们为什么要使用它;
  • 在 hugging face/transformers auto model 类的顶部创建一个多标签序列分类器;
  • 创建一个辅助函数来标记文本数据集;
  • 从已训练的模型中创建辅助函数来训练、预测和度量;
  • 创建一个 optuna 目标函数来帮助自动超参数调整;
  • 将其包装成一个可参数化、可重用的脚本,以便在不同的 NLP 任务上进行快速实验。

进口

以下是我们今天使用的进口产品:

现在,我们如何使用它们:

  • 所有 PyTorch 导入都与创建数据加载器、操纵张量、创建可训练模型和损失函数有关。
  • 我们从 Transformers 导入 AutoModel、优化器、标记器和配置,以便能够从它们的 repo 加载任何预先训练的语言模型。这意味着我们可以使用不同的语言和数据集,只要文件符合我们之前所做的预处理。
  • 我们导入 nlp,HuggingFace 的另一个包来创建数据集。csv 文件。
  • Optuna 用于自动优化超参数,帮助我们实现更好的模型指标。
  • Sklearn.metrics 和 Numpy 是用来度量计算的,tqdm 只是用来把东西变漂亮的。

扩展用于多类分类的转换器

HuggingFace Transformers 内置了 AutoModelForSequenceClassification(FYI,这是实际名称),但它只支持二进制分类。因为我们想把它扩展到更多的类,我们必须自己创建这个模型。

那不会很难。正如你在下面看到的,我们将创建一个nn.Module对象,它创建一个自动模型基础,然后是一个 Dropout 和线性层,带有所需数量的输出节点。请注意,我们仅使用预训练模型的名称和标签数量对其进行参数化:

创建令牌化函数

使用训练模型的相同键(名称),我们可以从 HuggingFace repo 导入一个标记化器。我们现在将创建一个函数,根据给定的标记器对数据集进行标记。稍后,我们将使用 map 方法将这种标记化应用于整个数据集。

就这么简单:

培训、评估和度量功能

我们现在进入了本帖最重要的部分:训练和评估功能。

为此,给定数据集,我们使用一个非常简单的向前训练函数,只对 huggingface/nlp 数据集对象做了一些修改:

请注意,我们在每个训练时段创建数据加载器,它是一个生成器,并且我们为每个批次获得这个input_ids。这就是数据集的符号化,必须将其转换为 LongTensor,然后放入我们正在进行训练的设备中。

我们将评估该模型,并分两步获取指标。首先,我们将整个测试数据集通过模型并获得其预测,将一个张量和相应的张量保存在一边:

在我们得到标签和预测张量进行比较之后,我们就可以得到度量。在这个函数中,我决定让用户决定要计算的指标。请注意,在后面的内容中,我们将设置 optuna 来调整这个特定指标的超参数:

我们决定支持所有标签评估的准确性和平均精度,并支持二进制化+ f1,以及要调整的特定标签的召回和精度指标。

当我们将所有这些构建部分放在一起时,我们可以创建 optuna 目标函数。为了让您理解,这是一个使用一些超参数执行训练并获得客观指标的函数。Optuna 将使用此目标函数,根据我们想要的度量找到最佳超参数:

由于我们将使用上面设置的所有函数,我们将根据数据集的特性使其可参数化。这保证了你能够用你自己的数据集来测试我们正在构建的脚本。

参数化脚本

在创建我们的主脚本之前,我们将使用argparse为它的运行设置参数。这意味着通过命令行上的一些标志,你可以用你自己的文本分类数据集进行实验。让我们看看:

所以这里我们参数化为:

  • 模型名称,因此我们可以从 HuggingFace 预训练模型库中获取任何模型;
  • 训练和测试数据路径,只是为了决定文件的名称和路径;
  • 最大序列长度,所以我们不会浪费内存,如果工作与小文本大小;
  • 指标名称 optuna 将优化,支持准确性、average_precision_score、f1_score、precision_score、recall_score(最后三个上的标签相对于 reference-class 二进制化);和
  • 标签号,这样我们就可以设置模型的输出节点数。

最后,主要功能

设置好之后,我们就可以编写主函数了。它创建数据集和目标函数,从 optuna 设置一个研究来优化超参数,以最大化所选的度量。

使用默认参数,如果你喜欢使用它,你可以适应谷歌 Collab 的 GPU,它应该产生大约 0.9 的 F1 分数。这是:

注意,我们使用 HuggingFace 的 nlp 库创建数据集,然后将编码数据集函数映射到整个数据集。这就创建了input_ids属性,我们用它在训练和推理中获得标记化的文本。

结论

正如你所看到的,利用 HuggingFace 预训练的 transformers 库和库,创建一个可重复的、可参数化的脚本是非常可能的。有了正确形状上的数据,您可以用简单、易懂和易读的代码,以非常快速的方式运行实验并调整超参数和指标。

我希望 post 和 script 能帮助你快速地用 NLP 创造价值,产生良好可靠的结果,并在许多语言中使用最先进的预训练模型。

如果这篇文章对你有所帮助,如果你能在 Github 上发起回购,我会非常高兴,如果能让更多人看到并帮助消息传递给更多人。

如果你有任何评论、批评或者只是想谈谈 NLP、深度学习或者甚至和我一起写这个系列,在 LinkedIn 上联系我,以便我们可以交谈。

谢谢你的时间,我希望我已经帮助了你。

参考

[## piEsposito/变压器-低代码-实验

低代码预建管道,用于数据科学家匆忙进行的 huggingface/transformers 实验。这个…

github.com](https://github.com/piEsposito/transformers-low-code-experiments) [## LinkedIn 上的 Thomas Wolf:# NLP # ai # open source | 49 条评论

我们正在考虑添加非常明确和简单的例子🤗像这样的变形金刚。只有 45 行……

www.linkedin.com](https://www.linkedin.com/posts/thomas-wolf-a056857_nlp-ai-opensource-activity-6702500587939868672-YLmC/) [## 拥抱脸/变形金刚

PyTorch 和 TensorFlow 2.0 的最新自然语言处理技术🤗变形金刚提供了成千上万的…

github.com](https://github.com/huggingface/transformers) [## 垃圾短信分类

让我们用数据科学与恼人的垃圾邮件制造者战斗。

www.kaggle.com](https://www.kaggle.com/team-ai/spam-text-message-classification) [## Optuna -超参数优化框架

Optuna 是一个自动超参数优化软件框架,专门为机器学习而设计。它…

optuna.org](https://optuna.org/)

H3 的快速地理空间索引

原文:https://towardsdatascience.com/fast-geospatial-indexing-with-h3-90e862482585?source=collection_archive---------20-----------------------

H3 六角电力重装上阵!

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

安娜斯塔西娅·彼得罗娃在 Unsplash 上的照片

在本文中,我将继续前两篇文章中介绍的内容,即关于使用 H3 的地理空间索引和关于如何使用三角不等式查询地理数据的。我将使用这两种方法来说明两个最有用的地理空间查询的实现:半径和 KNN。我们使用这些查询通过参考点从地理空间数据库中检索位置。半径查询返回距离参考点预设距离内的所有点,而 KNN 查询返回最近的 K 个点。

我上一篇关于三角形不等式的文章讨论了索引过程的几何基础,并实现了一个简单版本的 radius 查询。虽然我暗示 KNN 实现起来很简单,但我把它作为一个练习留给了读者。在本文中,我给出了基于三角不等式的两个查询的完全修改和完整的实现。

在工作的时候,我想知道我是否可以使用 H3 地理空间索引方法进行同样的计算。一旦散列到它们的 H3 索引,所有的点都立即和快速可索引,但还有更多。由于其固有的几何形状,H3 六边形瓦片具有允许我们以令人印象深刻的性能执行半径和 KNN 查询的相关属性。

让我们先处理未竟的事业,然后再去看看 H3。

KNN 和三角不等式

让我们从完成未完成的工作开始,解释如何使用三角不等式实现 KNN 查询。我们回到上一篇文章的 GitHub 库并从那里构建它。

自代码上次发布以来,有一些变化值得注意。第一个变化与如何计算两个焦点有关。在 Python 代码的第一个版本中,这些是硬编码的。现在,它们的位置取决于输入位置的质心,输入位置位于纬度相差 90 度的另一个半球。焦点本身具有 90 度的经度差,以输入位置的质心为中心。

每个“辐条”的数据由排序距离数组和原始位置数据的排序索引组成。

半径查询

半径查询保持原来的设计,从参考点沿两条“辐条”计算给定半径内的所有位置,并将两个结果集相交。最后的强力距离计算确保我们将位置保持在给定的半径内。

如您所见,代码非常简洁,没有循环。

KNN 查询

KNN 查询建立在 radius 查询的基础上,但是逻辑相反。其思路是从小半径开始,查询其范围内的点。如果找到的点数小于 K ,代码增加搜索半径并重复。一旦超过了所需的位置数量,该算法就结束另一次强力距离计算,以保留最近的 K

我们如何计算初始半径值?我对此问题的解决方案是使用数据集的边界框来估算平均输入点密度(每平方米的位置数)。使用这个值,我们可以估计包含 K 个点的最小“正方形”的大小。为了得到半径的初始值,我们需要得到面积的平方根。我选择将这个值乘以 2,以补偿用边界框近似输入区域所引入的误差。

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

初始半径公式

在上面的公式中,字母“ d 是包围盒密度。

代码从沿着两条辐条定位查询点开始。接下来,它进入一个循环来搜索最近的位置。参考点周围的半径定义了以每个焦点为中心的扇形。通过相交这两个区域,我们找到查询点的最近位置。当没有足够的交点时,循环不断增加半径长度。

注意,该算法并不总是保证找到 K 个最近的位置。这个问题的原因在于相交区域类似于正方形而不是圆形。然后,有可能在正方形外面有一些点,但是仍然比正方形里面的其他点更靠近,就像靠近每个角的那些点。解决方案是添加一个额外的循环,以确保我们覆盖了所有内容,代价是性能损失。

进入 H3

H3 提供了几个智能特性,这使得它成为支持这两种查询类型的绝佳选择。首先是效率和速度。Cython 编译的包现在为您提供了几个如何表示六边形索引的选项。对于本文的代码,我选择使用无符号的 64 位整数,所有返回集合的函数都是通过 NumPy 数组返回的。软件包 API 也非常完整,配备了支持几种不同用例的特性。最后,六边形非常适合所处理的查询类型。

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

该图像描绘了近似圆形的六边形。六边形渲染级别为 11,围绕中心的“环”有两层。

半径查询

正如你从上图中看到的,我们可以很容易地用一组六边形来近似一个圆形。为了执行以图像的环岛为中心的半径查询,我们可以枚举覆盖所需圆的所有六边形。这个过程会生成一个 H3 散列列表,然后我们用它来查询数据集中所有的匹配点。最后,对结果位置的封闭强力查询产生结果。

请注意我是如何使用 NumPy 函数在一个排序数组中进行搜索来检索源数据集中的索引范围的。对同一服务有两个调用,不同之处仅在于“side”参数。在第一个调用中,我们获取范围的初始索引,而第二个调用提供结束索引。缺失值在起始和结束索引处获得相同的编号,因此它们很容易区分。这是它如何工作的一个例子。

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

上面的代码定义了范围搜索过程的源数据结构。我们希望找到键数组中值的范围。请注意,键“1”没有匹配项。

在上图中,您可以看到一些定义了三个数组的示例代码。第一个包含未排序的源数据集。第二个数组包含排序后的源数据集的索引,而第三个数组包含我们要查找其范围的值。请注意,第一个值(1)不存在,而其他两个值存在。对于这些,我们希望在排序的源数据集中收集它们的范围。

接下来的两幅图像显示了如何获得初始和最终范围索引。

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

初始范围索引的检索

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

检索结束范围索引。请注意丢失的值如何具有相同的初始和最终索引。

我们现在可以用一个简单的表达式来重建现有值的范围。

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

正在检索 2 和 3 的序列。请注意上面检索到的索引在这里是如何使用的。

与使用集合包含测试的替代方法相比,这种实现具有速度极快的优点。

不过,有一个问题。在初始化期间,您必须指定生成 H3 散列的级别。默认情况下,代码使用十级,这似乎适合城市环境。然而,您应该对您的数据集进行测试,以检查是否有性能下降。请记住,H3 级别的较小值对应于较大的六边形。

H3Index 构造函数显示了并行处理以提高性能。

请注意构造函数代码在处理大规模数组时如何使用并行处理来提高性能。H3 软件包未来版本的一个可能的改进是一些函数的矢量化。

KNN 查询

KNN 查询使用与三角不等式相似的方法。代码不是增加以查询点为中心的半径,而是添加以查询点为中心的六边形的同心层。然后,该算法使用相应的 H3 哈希来匹配源数据集并检索最近的位置。

我应该做一个与上面类似的笔记。这是可能的,虽然不太可能,这个算法可能会错过一些点。假设您要查询的位置靠近封闭六边形的一个顶点。这种倾斜可能会导致一些最近的点位于生成的“环”之外的情况不过,解决方案是一样的。一旦你有了 K 个最近的点,再迭代一次,你应该被覆盖了。

性能比较

为了比较两种方法和两种查询的性能,我使用来自Dublin bus 数据集的数据运行了一个基准测试。该数据集包含超过四千四百万个地理参考数据点。每一次基准测试都会从这些点中随机抽取 100 个样本,并使用两种方法运行两个查询。

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

100 个随机位置(10 个样本)的平均性能(秒)

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

100 个随机位置(10 个样本)的标准偏差(秒)

跑了十次,得到了上面的结果。虽然 H3 在初始化时损失了一点点,但它在查询时却把基于三角形不等式的算法打得落花流水。

请注意,里程可能会有所不同,具体取决于数据集和 H3 初始化参数。

结论

在本文中,我使用三角形不等式完成了 KNN 查询的实现。使用 H3 算法及其相关的 Python 包,我实现了 radius 和 KNN 查询,并展示了它们卓越的性能。

H3 在性能和功能方面很强大,如果您使用地理空间数据,请将它放在您的工具包中。

参考

GitHub 库

H3:优步的六边形层次空间索引

相关文章

[## 利用三角形不等式查询地理数据

一种快速简单的查询大量位置的方法。

medium.com](https://medium.com/iotransportation/using-the-triangle-inequality-to-query-geographic-data-7148a1b103a0) [## 优步 H3 的地理空间索引

六边形动力!

towardsdatascience.com](/geospatial-indexing-with-ubers-h3-766399b690c) [## 清理都柏林公交数据集-教程

使用运动学和地理标准清理数据

medium.com](https://medium.com/iotransportation/cleaning-the-dublin-buses-dataset-a-tutorial-2783ba2edab4) [## joo Paulo Figueira-数据科学家- tb.lx by 戴姆勒卡车和公共汽车| LinkedIn

查看 joo Paulo Figueira 在全球最大的职业社区 LinkedIn 上的个人资料。圣保罗列出了 1 份工作…

www.linkedin.com](https://www.linkedin.com/in/joao-paulo-figueira/)

TensorFlow Hub & Magenta 在 5 分钟内实现快速神经风格转换

原文:https://towardsdatascience.com/fast-neural-style-transfer-in-5-minutes-with-tensorflow-hub-magenta-110b60431dcc?source=collection_archive---------23-----------------------

深度学习案例研究

用 Magenta 的任意图像风格化网络和深度学习将梵高的独特风格转移到照片上

在我们开始教程之前:如果你正在阅读这篇文章,我们可能有相似的兴趣,并且正在/将要从事相似的行业。那么我们就通过 Linkedin 来连线吧!请不要犹豫发送联系请求!Orhan g . yaln—Linkedin

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

图一。用任意图像风格化网络制作的神经风格转移示例

我相信你一定遇到过将著名画家的风格转移到新照片的深度学习项目。嗯,我一直在考虑做一个类似的项目,但我意识到你可以在几分钟内完成神经类型的转换,如图 1 所示。我马上会告诉你怎么做。但是,让我们先介绍一些基础知识:

神经类型转移

N eural style transfer 是一种混合两个图像并通过复制另一个图像的样式从内容图像创建新图像的方法,称为样式图像。这个新创建的图像通常被称为风格化图像。

NST 的历史

图像风格化是非真实感渲染领域二十年的老问题。非照片真实感渲染与照片真实感相反,后者是尽可能逼真地再现图像的研究。神经风格转移模型的输出是看起来类似于内容图像但是以风格图像的风格的绘画形式的图像。

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

图二。原作莱昂·加蒂斯CV-基金会

神经风格转移(NST) 最早发表于 Gatys 等人的论文《一种艺术风格的神经算法,最初发布于 2015 年。NST 方法的新颖性在于使用深度学习将图像内容的表示与其描绘风格分离开来。为了实现这一点, Gatys 等人使用了 VGG-19 架构,该架构在 ImageNet 数据集上进行了预训练。尽管我们可以按照相同的方法构建自定义模型,但在本教程中,我们将受益于 TensorFlow Hub 中提供的模型。

形象类比

在 NST 推出之前,图像风格化最突出的解决方案是图像类比方法。图像模拟是一种根据训练数据自动创建非真实感渲染过滤器的方法。在这个过程中,学习照片(A)和非真实感拷贝(A’)之间的转换。在这个学习过程之后,该模型可以从另一张照片(B)产生一个非照片真实感拷贝(B’)。然而,由于难以找到图像类比模型的训练数据,NST 方法通常优于图像类比。因此,我们可以谈论 NST 在现实世界应用中相对于图像类比的优越性,这也是为什么我们将重点放在 NST 模型的应用上。

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

图 3。乔纳森·科森斯在 Unsplash 上拍摄的照片

是艺术吗?

嗯,一旦我们建立了模型,你会看到,创造非真实感图像与神经风格转移是一个非常容易的任务。你可以将漂亮的照片和天才艺术家的画作融合在一起,创造出很多样品。人们一直在讨论,这些输出是否被视为艺术,因为创作者只需在最终产品中添加很少的工作。请随意构建模型、生成样本,并在评论部分分享您的想法。

现在,您已经了解了神经类型转移的基础知识,我们可以继续学习 TensorFlow Hub,这是我们在 NST 工作中使用的存储库。

张量流集线器

TensorFlow Hub 是一组经过训练的机器学习模型,您可以轻松使用。TensorFlow 对该中心的官方描述如下:

TensorFlow Hub 是一个经过训练的机器学习模型库,可随时进行微调,并可部署在任何地方。只需几行代码就可以重用经过训练的模型,如 BERT 和更快的 R-CNN。

除了预训练模型,如 BERT 或更快的 R-CNN,还有大量预训练模型。我们将使用的是 Magenta 的任意图像风格化网络。我们来看看洋红色是什么。

洋红色和任意图像风格化

洋红色是什么?

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

图 4。上的洋红色标志上的洋红色标志

Magenta 是一个开源研究项目,由谷歌支持,旨在为音乐家和艺术家提供机器学习解决方案。Magenta 在 Python 和 Javascript 中都有支持。使用洋红色,您可以创作歌曲、绘画、声音等等。对于本教程,我们将使用 Magenta 团队训练和维护的网络进行任意图像风格化。

任意图像风格化

在观察到 NST 的原作对风格转换提出了缓慢的优化后,Magenta 团队开发了一种快速艺术风格转换方法,可以实时工作。尽管模型的可定制性有限,但使用 NST 执行非真实感渲染工作已经足够令人满意。TensorFlow Hub 下的任意图像风格化是一个可以对任意绘画风格进行快速艺术风格转换的模块。

到现在为止,你已经知道什么是神经类型转移了。你也知道,我们将受益于 Magenta 团队开发的任意图像风格化模块,该模块在 TensorFlow Hub 中维护。

现在是编码的时候了!

获取图像路径

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

图 5。Paul Hanaoka 在 Unsplash 上拍摄的照片

我们将从选择两个图像文件开始。我将直接从 URL 加载这些图像文件。你可以自由选择任何你想要的照片。只需在下面的代码中更改文件名和 URL。我为本教程选择的内容图像是一只猫盯着相机的照片,如图 5 所示。

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

图 6。阿尔勒的卧室作者文森特·梵高

我想转移梵高的风格。所以,我选择了他的一幅名画:阿尔勒的卧室,这是他 1889 年在法国罗讷河畔阿尔勒时画的。同样,你可以自由选择任何艺术家的任何作品。你甚至可以用你自己的画。

下面的代码设置了获取图像文件的路径,如图 5 和图 6 所示。

图像缩放的自定义功能

我注意到一件事,即使我们在模型定制方面非常有限,通过重新调整图像,我们可以改变照片的风格。事实上,我发现图像越小,模型越能更好地传递风格。如果你想尝试,只需使用 max_dim 参数。请注意,更大的 max_dim 意味着,生成风格化图像需要的时间稍长。

我们将在下面的 load_img 函数中调用 img_scaler 函数。

用于预处理图像的自定义函数

既然我们已经设置了要加载的图像路径和缩放已加载图像的 img_scaler 函数,我们就可以用下面的自定义函数加载图像文件了。

以下要点中的每一行都有注释。请仔细阅读。

现在我们的自定义图像加载函数 load_img 也创建好了。我们要做的就是调用它。

加载内容和样式图像

对于内容图像和样式图像,我们需要调用一次 load_img 函数,结果将是一个 4 维张量,这是我们下面的模型所需要的。下面几行是为这次行动准备的。

现在我们已经成功加载了我们的图像,我们可以用 matplotlib 来绘制它们,如下所示:

这是输出结果:

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

图 7。左边的内容图片(照片由 Paul HanaokaUnsplash 上拍摄)|右边的风格图片(阿尔勒的卧室文森特·梵高拍摄)

你不会相信的,但最困难的部分已经过去了。现在我们可以创建我们的网络,并传递这些图像张量作为 NST 操作的参数。

加载任意图像风格化网络

我们需要导入 tensorflow_hub 库,以便我们可以使用包含预训练模型的模块。导入 tensorflow_hub 后,我们可以使用 加载 函数加载 任意图像风格化 模块,如下图所示。最后,如文档所示,我们可以将内容和样式图片作为参数以TF . constant对象格式传递。该模块以数组格式返回我们的风格化图像。

我们要做的就是用这个数组,用 matplotlib 来绘图。下面几行创建了一个不受所有轴影响的图,足够大到可以让你查看图像。

…这是我们的风格化图像:

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

图 8。保罗·花冈神经风格转移后的照片

图 9 总结了我们在本教程中所做的工作:

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

图 9。用任意图像风格化网络制作的神经风格转移实例

恭喜

正如你所看到的,用最少的代码(我们甚至没有训练一个模型),我们用文森特·梵高的一幅画,在从 Unsplash 获得的随机图像上做了一个相当好的神经风格转移。尝试不同的照片画作来发现任意图像风格化网络的能力。此外,摆弄一下 max_dim 的大小,你会看到风格转移变化很大。

订阅邮件列表获取完整代码

如果你想在 Google Colab 上获得完整的代码,并获得我的最新内容,请订阅邮件列表:✉️

现在就订阅

喜欢这篇文章

如果你喜欢这篇文章,可以考虑看看我的其他类似文章:

[## 使用 MNIST 数据集在 10 分钟内完成图像分类

towardsdatascience.com](/image-classification-in-10-minutes-with-mnist-dataset-54c35b77a38d) [## TensorFlow 和 VGG19 可以帮助您将照片转换成美丽的波普艺术作品

神经风格转移基于安迪沃霍尔的门罗双联画与预训练的计算机视觉网络 VGG19,转移…

towardsdatascience.com](/tensorflow-and-vgg19-can-help-you-convert-your-photos-into-beautiful-pop-art-pieces-c1abe87e7e01) [## 利用生成性对抗网络在 10 分钟内生成图像

使用无监督深度学习生成手写数字与深度卷积甘斯使用张量流和…

towardsdatascience.com](/image-generation-in-10-minutes-with-generative-adversarial-networks-c2afc56bfa3b) [## 伯特和拥抱脸 10 分钟情感分析

学习预训练的自然语言处理模型的基础,伯特,并建立一个使用 IMDB 电影评论的情感分类器…

towardsdatascience.com](/sentiment-analysis-in-10-minutes-with-bert-and-hugging-face-294e8a04b671)

基于带代码的机器学习的快速房地产图像分类

原文:https://towardsdatascience.com/fast-real-estate-image-classification-using-machine-learning-with-code-32e0539eab96?source=collection_archive---------38-----------------------

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

RoomNet 是一个非常轻量级( 700 KB )和快速卷积神经网络,用于对一所房子/公寓的不同房间的图片进行分类,在 1839 张图片中具有 88.9 %的验证准确性。我用 python 和 TensorFlow 写了这个。

顺便说一句,我制作了这个艺术品,是的,我实际上不是三年级学生,尽管它引发了诱人的流行观点。

这是一个我设计的自定义架构,用于将输入图像分类为以下 6 个类别之一(按照类别 id 的顺序)

后院 -0、浴室 -1、卧室 -2、前院 -3、厨房 -4、客厅 -5

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

照片来源按顺时针方向从左至右依次为 Chastity CortijoUnsplash (浴室)拍照、 Roberto NicksonUnsplash (卧室)拍照、 Jason BriscoeUnsplash (厨房)拍照、 Shaun MonteroUnsplash (后院)拍照、 Roberto Nickson 拍照

建筑积木-

这些模块用于构建最终的神经网络。它们由基本的基本神经层组成,如卷积、平均池和批量标准化。

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

RoomNet 卷积块。这是最基本的块

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

RoomNet 剩余块。它由前面描述的卷积模块组成。

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

RoomNet 密集块。这将在最后从提取的图像特征中进行分类。

完整的网络架构-

使用上面描述的构建块,下面呈现的是具有相关参数的完整神经网络架构。

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

训练和部署它的代码可以在 GitHub 上找到

[## ironhide23586/RoomNet

一个卷积神经网络,以 88.9 %的验证准确率对房屋/公寓的不同房间的图片进行分类…

github.com](https://github.com/ironhide23586/RoomNet)

创新推理-

优化了 infer.py 中的推理代码。参考 main 方法中调用 classify_im_dir 方法的短代码。

培训-

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

验证准确性

  • 输入图像尺寸= 224 x 224(尝试了 300 x 300,600 x 600)
  • Softmax 交叉熵损失L2 权重归一化一起使用
  • 辍学从 0(最初)到 0.3(间歇地接近训练结束)不等。放置在每个块之后的漏失层。
  • 批量正常化移动手段&var 在中途退出训练时被冻结。
  • Adam Optimizer 用于指数学习率衰减。
  • 最初接受批量计算批量移动方法/变量的培训。接下来是训练网络,通过在训练期间禁用该计算和使用冻结的平均值/变量。导致验证准确度立即跃升约 20%**(在训练步长 150,000 附近明显)。我将很快发表另一篇深入研究这一现象的文章。
  • 批量大小从 8(开始时)到 45(接近训练结束时)不等,如-8-> 32-> 40-> 45
  • 异步数据读取器采用基于队列的架构设计,即使批量较大,也能在训练期间实现快速数据 I/O。

转换到推理优化版本-

  • 从张量流图中丢弃了所有与反向传播/训练相关的计算节点。
  • 模型大小从大约 2 MB 减少到大约 800 KB。
  • network.py 包含定义名为“RoomNet”的模型的类
  • 输出是一个 excel 文件,将每个图像路径映射到其标签。还提供了将输入目录分割成对应于类名的目录,并自动将相关图像填充到其各自的目录中。

培训环境-

  • 使用 Tensorlfow + CUDA 10.0 + cuDNN 在 NVIDIA GTX 1070 笔记本电脑级 GPU(带 8GB GPU 内存)上完成培训
  • 使用计算机系统是外星人 m17 r4 膝上型电脑。
  • 使用的 CPU 是英特尔酷睿 i7–6700 HQ 处理器,带有 8 个逻辑内核,基本速度为 2.6 GHz(睿频加速至约 3.3 GHz)
  • 从零开始到达到最佳模型的训练步骤数为 157,700。
  • 花在培训上的时间——大约 48 小时

以前的方法尝试过-

  • 尝试训练最后的密集 NASnet 移动,但准确率从未超过 60%。
  • 在 InceptionV3 中尝试了同样的方法,但是收敛时间太长了。

性能图-

验证班级 F 分数

F-Score 是精确度和召回率的调和平均值。

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

验证类级精度

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

验证类级召回

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

如果你觉得这很有帮助,请随时关注我的更多文章:)

我是以下出版物的编辑,该出版物发表了与 AI & ML 在地球数字地图绘制中的使用相关的技术文章。请随时关注以保持更新:)

[## 数字制图中的机器学习和人工智能

策划尖端人工智能和人工智能研究文章,来自从事设备、边缘、云和混合领域工作的行业科学家…

medium.com](https://medium.com/ai-ml-cv-in-enriching-digital-maps-navigation)

我的个人资料-

[## Souham (Sean) Biswas -高级数据科学家(深度学习/计算机视觉)- HERE Technologies…

我是芝加哥伊利诺伊理工大学的计算机科学毕业生。我感兴趣的领域包括机器学习、并行…

www.linkedin.com](https://www.linkedin.com/in/souham/) [## ironhide23586 -概述

HERE Maps(一家宝马、奥迪、奔驰公司)的高级数据科学家。北极代码库贡献者驳回注册…

github.com](https://github.com/ironhide23586)

临时演员—

Twitch 上直播我🤪🤡

我也是一名音乐家。这是我的音云简介中的一个声音封面。

谢谢:)

dplyr 和 data.table 之间的快速转换

原文:https://towardsdatascience.com/fast-transition-between-dplyr-and-data-table-c02d53cb769f?source=collection_archive---------15-----------------------

dplyr 和 data.table 的并行语法比较

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

照片由马体·米罗什尼琴科派克斯拍摄

在这篇文章中,我比较了 R 的两个最强大的数据操作库的语法:dplyr 和 data.table。我在这里不是要提倡任何包。然而,在处理一个具有异常大的数据集的项目时,为了速度和内存效率,我首选的包变成了 data.table。我在 dplyr 中使用了一个遗留项目,并在 data.table 中重新创建了它。

***data table***提供高性能版本的 base R 数据帧,增强了语法和功能,以提高易用性、便利性和编程速度根据数据表作者马特·道尔的说法

***dplyr*** 是一种数据操作语法,提供一组一致的动词,帮助您解决最常见的数据操作挑战根据《dplyr》的作者 Hadley Wickham 所说

库和数据集

我将使用 R 内置的汽车保险索赔的 AutoClaims 数据集。让我们安装和加载库,并为练习准备数据集。

#install.packages(“dplyr”)
#install.packages(“data.table”)
#install.packages(“insuranceData”)library(dplyr)
library(data.table)
library(insuranceData)data(“AutoClaims”) *#load the dataset*
data <- AutoClaims *#rename the dataset*
data <- data.table(data) *#convert it to data.table*

数据有 6773 行和 5 列。让我们看看数据是怎样的。

> head(data)
STATE CLASS GENDER AGE PAID
1 STATE 14 C6 M 97 1134.44
2 STATE 15 C6 M 96 3761.24
3 STATE 15 C11 M 95 7842.31
4 STATE 15 F6 F 95 2384.67
5 STATE 15 F6 M 95 650.00
6 STATE 15 F6 M 95 391.12

十大最常用的数据操作功能

  1. 按行过滤

让我们过滤 79 岁或更年轻的男性

data[AGE <= 79 & GENDER == “M”]*#datatable*data %>% filter(AGE <= 79 & GENDER == “M”) *#dplyr*

2。按列选择

让我们选择性别、年龄和薪酬列

data[, .(GENDER, AGE, PAID)] *#datatable*data %>% select(GENDER, AGE, PAID) *#dplyr*

3。添加新列

让我们用 0.85 美元/欧元的兑换率将美元兑换成欧元。产生的新变量被添加到数据集中

data[, PAID.IN.EURO := PAID * 0.85] *#datatable*data %>% mutate(PAID.IN.EURO = PAID * 0.85) *#dplyr*

4。删除栏目

让我们删除新创建的变量

data[, !c(“PAID.IN.EURO”)] *#datatable* data[, PAID.IN.EURO:= NULL] *#datatable (alternative way)*select(data, -PAID.IN.EURO) *#dplyr*

5。创建新列

现在创建一个新变量并删除现有的变量。因此,数据集将只有一个新变量

data[, .(PAID.IN.EURO = PAID * 0.85)] #datatabledata %>% transmute(PAID.IN.EURO = PAID * 0.85) #dplyr

6。按列汇总

平均赔付的保险理赔是多少?

以下代码聚合数据并返回名为 AVG 的单记录。有报酬的

data[, .(AVG.PAID = mean(PAID))] *#datatable*data %>% summarise(AVG.PAID = mean(PAID)) *#dplyr*

7。重命名变量

对于 data.table,我们使用 setnames 函数,它先引用旧名称,然后引用新名称。对于 dplyr,顺序正好相反

setnames(data, c(“GENDER”, “CLASS”), c(“gender”, “class”)) *#dt*data %>% rename(“gender” = “GENDER”, “class” = “CLASS”) *#dplyr*

8。按升序或降序排列数据

让我们使用 data.table 中的setorder函数和 dplyr 中的arrange函数对数据进行升序和降序排序。

setorder(data, PAID) *#datatable ascending order*
setorder(data, -PAID) *#datatable descending order*data %>% arrange(PAID) *#dplyr ascending* 
data %>% arrange(desc(PAID)) *#dplyr descending*

9。按列分组

单独对数据分组没有任何作用;您应该将它与另一个函数结合使用,例如,按州分组并汇总数据,或者筛选数据。

data[, .(mean.paid.by.state = mean(PAID)), by = "STATE"]data %>% group_by(STATE) %>%
  summarize(mean.paid.by.state = mean(PAID))

10。计数观察值

让我们通过对 dplyr 和使用 n()函数来计算每个类有多少个观察值。n 代表数据表

data[, .N, by= “class”] *#datatable*data %>% *#dplyr*
 group_by(class) %>%
 summarise(n())

现在让我们来看更多关于如何在 dplyr 和 data.table 中链接函数的例子。

链接功能

在 dplyr 中,我们使用%>%管道操作符来链接函数。在 data.table 中,可以在一行代码中简洁地编写几个函数,或者使用方括号进行更复杂的链接。

  • 让我们选择三个变量:STATE、AGE 和 payed,然后创建一个 20% payed 的新列,并根据列 AGE 对结果进行升序排序。
***#datatable***
data[, .(STATE, AGE, PAID)][, .paid.20 := PAID * 0.2, keyby = "AGE"]***#dplyr***
data %>% select(STATE, AGE, PAID) %>% 
  mutate(paid.20 = PAID * 0.2) %>%
  arrange(AGE)

结论

今天我们并排比较了dplyrdata.table的语法,使用了 10 个常用函数和链式函数。使用这两个库,您可以做更多的事情。

语法。 Data.table 使用比 dplyr 更短的语法,但通常更加细致和复杂。dplyr 使用管道操作符,对于初学者阅读和调试来说更直观。此外,许多其他库使用管道操作符,如 ggplot2 和 tidyr。虽然 data.table 和 dplyr 都在 R 社区中广泛使用,但 dplyr 的使用范围更广,提供了更多的协作机会。

内存和速度重要吗?在构建复杂的报告和仪表板时,尤其是在处理非常大的数据集时,data.table 具有明显的优势。

使用哪个库进行分析由您决定!

你可以在参考资料部分找到更多的资料。

感谢您的阅读!

参考文献

[## “数据帧”的扩展

data.table 提供了 base R 的 data.frame 的高性能版本,并增强了语法和功能,以便于…

rdatatable.gitlab.io](https://rdatatable.gitlab.io/data.table/index.html) [## 数据操作的语法

一个快速、一致的工具,用于在内存中和内存外处理类似数据帧的对象。

dplyr.tidyverse.org](https://dplyr.tidyverse.org/)

基于 PrototypeML.com 的快速视觉神经网络设计

原文:https://towardsdatascience.com/fast-visual-neural-network-design-with-prototypeml-com-ed83ef4f6f64?source=collection_archive---------52-----------------------

新的直观和强大的视觉神经网络设计平台,允许快速模型原型。

神经网络体系结构通常是从概念上设计并以视觉术语描述的,但通过编写容易出错的代码来实现。PrototypeML.com 是一个新的(目前在 alpha 中)开放神经网络开发环境,允许您(a)通过直观的可视化拖放和代码编辑界面快速原型化/设计任何神经网络架构,( b)基于社区驱动的网络构建块库进行构建,以及©导出完全可读的 PyTorch 代码用于培训。在PrototypeML.com尝试一下。

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

作者图片。

PrototypeML 如何工作

PyTorch 在研究界越来越受欢迎,它以概念简单、动态图形支持、模块化和面向未来的设计而闻名。PrototypeML 与 PyTorch 框架紧密耦合,支持普通 PyTorch 模型中可用的全部动态功能和任意代码执行。我们通过几个基本构件来实现这一点。

将神经网络表示为语法树代码图

首先,我们利用 PyTorch“作为常规 Python 程序的深度学习模型”设计范式,以静态语法树代码图的形式表示神经网络模型,而不是预定义的神经组件图。

变异体

其次,我们引入了“变异体”的概念。mutator 组件封装了普通 PyTorch 或任意 Python 代码的片段,并定义了一种标准化的格式,通过这种格式可以表示数据输入和输出以及参数。

PyTorch 模型使用nn 表示。模块 类范例,其中带有参数的神经网络层在 nn 中被实例化。模块init() 函数,并在网络正向传递期间调用 nn。模块forward() 函数。Mutators 通过将执行 init() 函数中的代码实例化和相应的 forward() 执行代码所需的代码封装到单个组件中来构建这个模式,该组件包含运行代码所需的一切,而不管它将在哪里使用。

赋值函数定义了以下字段:

  1. 必需的导入(如标准 PyTorch 库,或任何第三方 PyTorch 库或 Python 代码库)。如果 mutator 需要安装一个包,请在 Python 包部分中指定
  2. forward() 阶段流入和流出 mutator 的数据流是通过端口定义的
  3. init() 中初始化代码所需的参数在参数部分中定义
  4. nn 中初始化组件的代码。模块 init() 函数
  5. **执行 nn 内组件的代码。模块转发()功能
  6. 任何需要的附加功能

Mutators 实现了各种神奇的变量,允许通过代码中的可视化界面访问设置,具体来说:

  • ${instance} | 可用于 init()forward()|用于表示当前实例名(为了允许多次使用同一个赋值函数,init 中的变量名应该包括这个神奇的变量)**
  • $ {港口。<名称> } |仅在 forward() 中可用|用于表示输入或输出端口变量。<名称>应替换为您在可视界面中选择的名称
  • p a r a m s ∗ ∣ 仅在 ∗ i n i t ( ) ∗ 中可用 ∣ 为 ∗ i n i t ( ) ∗ 函数实例化生成逗号分隔的输入参数列表的快捷方式 ( 例如, ∗ {params}* |仅在 *init()* 中可用|为 *init()* 函数实例化生成逗号分隔的输入参数列表的快捷方式(例如, * params仅在init()中可用init()函数实例化生成逗号分隔的输入参数列表的快捷方式(例如,{params} 可能会变成 spam="eggs ")
  • * p a r a m s 。 < n a m e > ∗ ∣ 仅在 ∗ i n i t ( ) ∗ 中可用 ∣ 用于表示参数的内容 ( {params。< name > }* |仅在 *init()* 中可用|用于表示参数的内容( params<name>仅在init()中可用用于表示参数的内容({params.spam}可能会变成“eggs”)

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

ReLU Mutator 示例。图片作者。

阻碍

第三,我们实现“块”容器来封装子节点之间的关系。一个块组件代表一个nn。模块 类,并用一个可视化图形表示。通过从库栏拖放,可以将变异子和其他块作为节点添加到图形中,并且在各个节点之间绘制的边代表神经网络模型的数据流。

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

演示跳过连接的 ResNet 瓶颈层。作者图片。

代码生成

为了生成代码(可通过界面中的小下载按钮或块编辑器中的查看代码按钮访问),遍历块图,将 mutator 和块 init()forward() 代码段组合到它们各自的函数中,并解析各个组件之间的输入和输出依赖关系和参数。只需一次点击,您就可以下载您的模型的编译代码,包括所有依赖项、conda/pip 环境/需求文件等。

构建 MNIST 分类器

随着本质细节的方式,让我们看看所有这些如何帮助我们更快地原型神经网络!我们将构建一个基本的 MNIST 分类器,因为这几乎是神经网络的“Hello World ”(不过不要担心,生成一个类似的网络来处理 CIFAR-10,甚至 ImageNet 也一样容易!).下面详细介绍的项目可以在 https://prototypeml.com/prototypeml/mnist-classifier 的找到。继续前进,分叉它(在你创建了一个帐户之后),这样你就可以跟着走了。

  1. 签到 /R 注册MNIST 选粉机项目。
  2. 在项目页面上,单击右上角的 Edit Model 按钮。这将把您带到模型编辑器界面。在你的左手边是库栏,在那里你所有的组件被管理。中间是你编写变异函数和构建模块的地方。右侧是编辑 mutator、block 和 component 实例属性的位置。
  3. 首先,从包存储库中添加已经构建(并自动生成)的 PyTorch 库。在库栏中,点击“添加”按钮,选择“添加包依赖”。接下来,选择 PyTorch(它应该在顶部附近),然后单击“使用”按钮。这将把这个包作为一个依赖项添加到您的项目中(添加任何其他依赖项的过程也是一样的!).现在,您应该在库栏中看到一个包目录。如果您导航到 Packages 目录,并单击 PyTorch,您将找到整个 PyTorch 神经网络函数库。
  4. 返回到您的根目录(单击“添加”按钮下面的面包屑中的“/”),并通过“添加”按钮添加一个块(您可以随意命名)。点击块打开它,你会看到块编辑界面。如果再次导航到 Packages/PyTorch 目录,现在可以将其中一个子文件夹中的任何可用组件拖到项目中。
  5. 继续并开始构建您的模型:将组件从库栏拖到块编辑器中,并开始通过将边从输出端口拖到输入端口来连接它们(端口是组件实例顶部/底部的圆)。单击组件实例以查看和设置特定于该组件的参数。如果你想得到一些帮助来弄清楚要拖动什么,请随意查看示例项目。
  6. 在块编辑器中的任何时候,点击块编辑器工具栏中的>按钮,查看将要生成的代码——探索当您拖动组件并将它们连接在一起时,代码是如何变化的。请注意,当两条边进入单个输入端口时,代码将自动包含一个连接操作(对此进行配置,或通过单击输入端口将其更改为替代的组合函数)。
  7. 编辑完模型后,单击库栏中“添加”按钮旁边的下载代码按钮,您就可以开始培训了。

使用外部库&设计变异函数

到目前为止,我们一直使用 PyTorch 库中包含的 mutator,但是如果您发现您需要某个组件,而这个组件的 mutator 还没有在包存储库中编写(或者您想在您的网络中包含完全自定义的代码),那么您将需要自己设计。我们将构建一个 mutator,包装 EfficientNet 库的 PyTorch 实现。

  1. 首先,通过单击“add”按钮添加一个 mutator。
  2. 在编辑器右侧的属性栏中,通过单击 parameters 旁边的“+”按钮,添加这个 mutator 所需的两个参数(模型名称和输出类的数量)。
  3. 我们需要在 Imports 部分导入库,如下所示:
**from efficientnet_pytorch import EfficientNet**

4.接下来,让我们在 Init 部分编写初始化 EfficientNet 模型所需的代码,就像这样。注意我们如何使用神奇变量 i n s t a n c e ∗ 而不是变量名称,并使用 ∗ {instance}* 而不是变量名称,并使用 * instance而不是变量名称,并使用{params 填充参数。<名称> } 语法:

**self.${instance} = EfficientNet.from_pretrained(${params.model}, num_classes=${params.num_classes})**

5.最后,编写调用 Forward 部分中的 EfficientNet 模型所需的代码,就像这样(同样,注意我们是如何使用神奇变量 p o r t s 。 < 名称 > ∗ 引用输入 / 输出变量, ∗ {ports。<名称> }* 引用输入/输出变量, * ports<名称>引用输入/输出变量,{instance} 同上):

**${ports.output} = self.${instance}(${ports.input})**

6.我们完事了。当拖动到一个块中时(配置设置为:name='efficientnet ',model='efficientnet-b0 ',num_classes=10),这个 mutator 将产生以下代码(假设块的其余部分为空):

**import torch
from efficientnet_pytorch import EfficientNetclass EfficientNet_Classifier(torch.nn.Module):
    def __init__(self):
        super(EfficientNet_Classifier, self).__init__() 

        self.efficientnet = EfficientNet.from_pretrained('efficientnet-b0', num_classes=10)def forward(self, input):
        efficientnet_output = self.efficientnet(input)

        return efficientnet_output**

完整的 MNIST 的例子可以在 https://prototypeml.com/prototypeml/mnist-classifier 找到。

结论

PrototypeML 实现了一个强大而直观的接口和组件标准,允许快速原型化强大的神经网络架构和实验。我们希望听到您对平台的想法和反馈,并期待在不久的将来从 alpha 升级到 beta。你可以在 https://PrototypeML.com访问平台,在这里访问预印本,在 https://Docs.PrototypeML.com访问文档,在 https://discord.gg/zq8uqSf访问我们的 Discord 社区频道。

fastai 和 PyTorch Lightning 正在使人工智能民主化

原文:https://towardsdatascience.com/fastai-and-pytorch-lightning-are-democratising-ai-92318ff224b1?source=collection_archive---------11-----------------------

这两个框架如何使深度学习对从业者可用,同时对研究人员保持高度可攻击性。

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

图片由来自 PixabayFrancis Ray 拍摄

深度学习框架对推动该领域向前发展的突破性研究负有巨大责任。像 TensorFlowPyTorch 这样的大型项目,像 DL4J 这样的特定语言项目,以及像 Swift for TensorFlow 这样的实验项目,为从业者和研究人员提供了各种各样的选择。

然而,深度学习对于没有数学背景的软件工程师来说仍然太难,而像 TensorFlow 和 PyTorch 这样的框架对于没有扎实工程背景的数据科学研究人员来说又很复杂。

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

为此,像 KerasfastaiPyTorch Lightning 这样的库在完善的代码基础上提供了更高的抽象。Keras 大多使用 TensorFlow 作为后端,而 fastai 和 PyTorch Lightning 都是基于 PyTorch 构建的。在这个故事中,我们考察了后两者,它们提供了什么,以及新版本给我们带来了什么;fastai 2.0 和 PyTorch Lightning 0.7.1。

学习率是我每周给那些对 AI 和 MLOps 世界好奇的人发的简讯。你会在每周五收到我关于最新人工智能新闻、研究、回购和书籍的更新和想法。在这里订阅!

法斯泰

fastai 是一个深度学习库,主要由杰瑞米·霍华德西尔万·古格开发,由数百名贡献者维护。它使从业者能够毫不费力地获得最先进的结果,并促进研究人员的深入实验。该框架于 2017 年推出,以支持相关的课程第二版预计于 2020 年 7 月推出。

介绍

在这个故事中,我们主要谈论即将推出的 fastai 库的第二个版本。考虑到这一点,fastai 采用分层方法进行设计。它为实践者提供了可以快速交付最新成果的高级组件,为研究人员提供了可以以各种方式组合的低级模块,从而实现了对新的深度学习方法的实验**【1】**。

更高级别的 API 对初学者或主要想应用预先存在的深度学习技术的人工智能从业者很有用。 **fastai 默认支持四个应用领域:计算机视觉、自然语言处理、表格数据或时间序列、协同过滤推荐系统。**此外,fastai 是一个固执己见的框架,提供带有合理默认值的可定制模型。预定义的超参数遵循最佳实践,并参考了相关的最新研究成果。这种设计会产生清晰、易于理解的代码,即使有错误也很少。

另一方面,低级 API 通过优化的原语支持中级和高级功能。那些原语主要是在流行的 Python 库之上开发的,比如py torchnumpypandas或者PIL。然而,为了能够被黑客攻击,fastai 与每一个底层库无缝地互操作。例如,fastai 可以很容易地将其组件注入 PyTorch 模块或使用 fastai 的原始 PyTorch 功能。

简而言之,fastai 的目标是为初学者提供平坦的学习曲线,但对研究人员来说足够灵活。

代码示例

为了更好地理解每个库的设计选择,我们为 MNIST 数据集实现了一个最先进的分类器。毕竟,MNIST 可以说是深度学习的“ Hello world ”范例。

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

该框架的高级 API 允许我们用大约五行代码来解决 MNIST 挑战。尽管这只是一个玩具示例,但它突出了分层架构的可能性。再者,训练深度学习模型的几个关键要素对我们是隐藏的;最优学习速率、批量和其他超参数是自动设置的,而损失函数是由数据推断的。迁移学习可以轻松处理,ResNet 架构会自动根据手头的问题进行调整。

在 MNIST 数据集上,仅用了五行代码和不到五分钟的 GPU 训练就达到了 98%以上的准确率。面临 fastai 默认支持的挑战(例如,视觉、文本、表格数据或协同过滤)的从业者可能有类似的经历。在任何其他情况下,只需稍作调整就能取得很大成就。

2.0 版中的新功能

fastai 版是对第一版的完全重写。代码库中有许多突破性的变化,你可以在杰瑞米·霍华德的相关 YouTube 系列中浏览其中的大部分。

但是,最显著的修改总结如下:

  • 一种新的可黑客攻击的数据块 API,可以为深度学习准备任何数据集
  • 一种新的灵活回拨系统
  • 一种基于 GPU 的新型高性能数据增强系统
  • 一种通用的优化器设计,具有可以混合和匹配的块,允许您只需几行代码就可以实现任何优化器

你可以在去年的课程的第二部分中体验一下新的 API,而当 2020 年的课程可用于流媒体时,预计会有更多的示例。

PyTorch 闪电

PyTorch Lightning 是一款面向研究人员的轻量级 PyTorch 包装器,由威廉·法尔肯开发。然而,它很快被为主要组织工作的研究团队采用(例如 FAIR ),并获得了风险投资家的资助,一个全职团队就在我们说话的时候成立了。PyTorch Lightning 更像是一个风格指南,帮助你将科学代码从工程中分离出来。

介绍

PyTorch Lightning 是 PyTorch 上的一个灵活的轻量级包装器,它为如何构建深度学习代码设置了一个标准。这样,它可以处理大部分的工程工作,让你专注于科学。这种方法导致更少的样板代码,因此,更少的担忧和错误。

成为一个瘦包装器意味着研究人员或生产团队不需要学习另一个框架的额外好处。同时,它提供了极大的灵活性,可以在抽象工程细节的同时尝试尖端的想法。

PyTorch Lightning 的主要模块是LightningModuleTrainer。所有科学逻辑都进入了LightningModule;数据准备、优化器初始化、训练循环和正向传递。另一方面,所有的工程工作都隐藏在Trainer模块中;拟合、自动记录、检查点、提前停止等等。

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

正如其创建者所说,PyTorch lightning 的目标是在深度学习社区中推广最佳实践,并促进研究的可重复性。

代码示例

现在让我们看看如何使用 PyTorch 闪电解决 MNIST。我们需要使用相同的预训练模型来避免作弊。为此,继续前面的例子,我们将在训练之前从学习者(即 fastai 学习者)那里抓取模型。我们这样做是因为学习者已经根据 MNIST 挑战调整了模型。如果我们只是获得一个新的 ResNet-34 模型,它将被定制以解决 ImageNet 挑战,这意味着最后一层的输出数量不同。我们需要改变的一件事是告诉第一个卷积期望单通道输入。

我们现在准备实施一个MNISTSolver

为了适应这个模型,我们只需实例化Trainer就可以开始了。

PyTorch Lightning 默认提供 TensoBoard 日志记录功能。只需在 Jupyter 中运行下一个魔法命令。

%reload_ext tensorboard
%tensorboard --logdir lightning_logs/

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

新功能

PyTorch Lightning 的新稳定版本是 0.7.1。在那里,我们可以找到令人兴奋的新功能,总结如下:

请访问该项目的 GitHub 页面以获取更多信息,并访问文档页面以深入了解。

结论

在这个故事中,我们看到了 fastai 和 PyTorch Lightning 如何让从业者和研究人员轻松实现深度学习解决方案。

fastai 提供了更高层次的抽象,让您更快地获得最先进的结果。另一方面,PyTorch Lightning 对那些熟悉 PyTorch 的人来说有一个更平坦的学习曲线,提供 TPU 支持和与许多伐木工的集成。

最后,你选择什么取决于你面临的挑战。无论如何,你不会错的!

我叫 Dimitris Poulopoulos,是希腊比雷埃夫斯大学*BigDataStack的机器学习研究员和博士©。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲中央银行、经合组织和宜家等主要客户设计和实施人工智能和软件解决方案。如果你有兴趣阅读更多关于机器学习、深度学习、数据科学的帖子,在 twitter 上关注我 LinkedIn@ james2pl*****

参考

[1]霍华德、杰里米和西尔万·古格。" fastai:用于深度学习的分层 API . "信息 11.2 (2020): 108。

Fastai 锦囊妙计 Kaggle 数据集实验—第 1 部分

原文:https://towardsdatascience.com/fastai-bag-of-tricks-experiments-with-a-kaggle-dataset-part-1-135e46da72f2?source=collection_archive---------13-----------------------

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

图片来自 PexelsAnna Shvets

在这篇文章中,我将解释我使用 Kaggle 数据集"胸部 X 射线图像(肺炎)"进行的实验,以及我如何在这个过程中解决不同的问题,从而在验证集和测试集上获得完美的准确性。我的目标是向您展示在 fastai (v2)的帮助下您可以轻松使用的不同技巧,并分享我对这个数据集的实验,作为一种消融研究。我假设你了解深度学习的基础知识,熟悉 python 的 DL 框架,尤其是 PyTorch 和 fastai。所以让我们开始吧。

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

图片来自 Kaggle

下载数据集

您可以通过下面的命令轻松地获得数据集。在此之前,你需要创建一个 Kaggle 帐户,以防你还没有,并使用你自己的 API 令牌信息来运行代码。

入门指南

我首先看一下数据集的结构,并加载图像文件名。在这个数据集中,我们有机器学习数据集中常见的训练、验证和测试集。

这里我使用 get_image_files 来读取我们数据的三个分区的图像文件名,然后我使用 L 来映射三个文件名列表上的 len 函数,这是 fastai 的 Python 中 List 类的一个很好的替代。如您所见,我们分别有 5216、16 和 624 幅图像用于训练、验证和测试集。我们的验证集真的很小,我将在本文后面谈到它

让我们来看看一个微型 EDA。我想知道数据集是否平衡,也就是说,正常与肺炎类别的项目数量是否大致相同。

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

每个类别的项目数,按作者分类的图像

由于这在现实世界中很常见,特别是在医学数据集上,我们在这两个类别的项目数量上有很大差距(肺炎与正常病例的比例为 3:1)。所以我们要考虑的第一个问题是用某种技巧来解决这种不平衡。实际上,我不建议在处理这个问题之前花太多时间,我更愿意建议先用不平衡的数据建立你的初始模型,然后看看结果如何!

数据块和数据加载器

在这里,我将创建我的数据块和数据加载器,将数据输入到模型中。在 fastai 中,这真的很容易做到,然而,对于这篇文章,我不打算详细介绍每段代码做什么,我强烈建议在课程网站上免费阅读他们的书书的 Jupyter 笔记本。但是对于那些熟悉 PyTorch 和 fastai 的人来说,我在这里构建了我的训练和验证数据加载器以及数据扩充。

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

一批图像放大和调整大小后,由作者图像

即使在这一小组图像中,阶级不平衡也很明显!

我在这里使用数据扩充来缓解小数据集的问题。虽然它不会改变我们的正面与负面案例的比率,但它可以通过引入更多正面案例来帮助模型解决不平衡问题,这将有助于它更强有力地学习潜在模式。在医疗数据集的数据扩充中,请确保您添加了有意义的数据,并且不会在使数据与真实世界数据差异太大的情况下更改您的数据。在这里,我首先使用“squish”方法将图像的大小调整为 512,以便不丢失可能重要的数据部分(我在这里没有裁剪,但是在文章的下一部分,我们将看到裁剪是如何工作的)。之后, RandomResizedCropGPU 从那张 512 的图像中随机裁剪出大小为 224 的小块。fastai 一书的作者将这种技术称为“预先调整大小”。然后我们将进一步增加旋转缩放。我不会翻转或扭曲或改变我的图像的亮度和对比度(对于大多数计算机视觉任务来说,这些都是合法的数据增强类型),因为我认为这将不再代表实际的 X 射线图像。还要记住,在某些特定任务中(这里可能不多),甚至水平翻转在 X 射线图像中也会有问题,特别是当身体器官的位置很重要时。例如,右位心是一种罕见的情况,其中心脏位于胸部的右侧,翻转图像将使模型瘫痪,无法检测这些情况。

另外,我想在这里澄清一些事情。该数据集中的图像是单通道灰度图像。但是,我们将在本文后面使用的 ImageNet(以及 fastai 中其他现成模型架构的默认模式)上预训练的模型,预计模型会有一个 3 通道 RGB 输入。我们不必担心这一点,因为数据块和 PILImage 类通过重复我们的第一个通道 2 次以上来克服这一点,使其成为三通道图像,我们已经准备好在任何模型上正常训练它。

基线模型

我称之为基线,因为我们在这里没有使用花哨的技巧,但它不会是一个真正的基线模型,就像我们通过堆叠 Conv 和线性图层构建的模型一样。我先从 XResNet18 架构说起。XResNets 实际上很像香草 ResNets,但有一些调整,你可以在线搜索它们或阅读童和等人的论文 卷积神经网络图像分类锦囊 。艾尔。了解更多的不同之处。因为这将是一个基准模型,我将从头开始训练它,在这种情况下,我不会使用预训练模型。

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

lr_finder plot,图片由作者提供

正如情节所示和我所料,3e-3 的学习率在这里看起来不错。因此,让我们用一个周期策略训练它 10 个周期,然后看看效果如何。

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

基线模型性能,图片由作者提供

好吧!我们做得并不差,但我们远非完美!这些结果中有一些要点。如果你看看准确性和 f1 成绩的结果,他们似乎是不稳定的,这是由于一些原因。第一,我们是从零开始训练模型(甚至连数据都没有归一化!)这会导致这里的训练更加不稳定。其次,我们的验证集非常小!它只有 16 项可能不能很好地代表模型正在接受训练的数据。最后,我在这里使用一个循环训练,它增加了前 25%迭代的学习率,这可能会在训练的早期导致更高的 valid_loss。

让我们这样来思考我们的模型。我们有 3875 例肺炎和 1341 例正常病例。因此,如果我们的模型简单地为它在训练集中看到的每个项目输出“肺炎”,它可以轻松地达到大约 75%的准确率。我们的模型在这里没有做确切的事情(因为我们的 f1 分数表明它已经在某种程度上学会了区分这两个类别),但是我们应该知道最简单的基线是什么样的!

毕竟,我认为我们在这个相当小的数据集上只训练了 4 分钟就取得了很好的结果。但是,在这篇文章和下一篇文章中,我们将尝试很多很酷的东西来使它变得更好。

克服阶级不平衡问题

正如我在前面提到的,我们的问题之一是阶级不平衡问题。您可以在计算机视觉文献中找到许多方法来克服数据集的这个真正常见的问题。我强烈建议阅读 一篇系统研究卷积神经网络 中的类不平衡问题的论文,这篇论文在比较解决这个问题的不同方法方面做得非常好。在其摘要中,您可以找到以下内容:

基于我们的实验结果,我们得出结论:( I)类别不平衡对分类性能的影响是有害的;(ii)在几乎所有分析场景中占主导地位的解决类别不平衡的方法是过采样… (iv)与一些经典的机器
学习模型相反,过采样不会导致 CNN 的过拟合

真好看!我们刚刚得到了答案!让我解释一下。克服类不平衡最常用的方法是对具有较高比率的类进行下采样(使用较少的数据),或者对具有较低比率的类进行过采样。本文建议采取后者;在我们的例子中,通过简单地在训练数据集中重复它们来增加“正常”案例的数量。我们可以这样做:

我们需要做的就是这两行代码!在第一行中,我在一个列表中收集“正常”案例的文件名(实际上是 L!).在第二行中,我以某种方式堆叠了三个列表:一个列表包含我以前的训练文件名(不平衡的正常和肺炎病例),一个列表包含重复两次的“正常”文件名(normal_cases*2),一个列表包含 16 个验证文件(我们稍后将在数据块中分离训练和验证集,就像上一节中的代码一样)。现在我们有 3875 例肺炎和 4023 例正常病例,大致相当。确保将这个过采样列表与训练集和验证集的新索引一起提供给数据块。让我们在这个新数据集上再次训练我们的模型(从头开始构建模型,与之前完全相同):

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

获得 100%的准确率,图片由作者提供

哇!我们刚刚获得了 100%的准确率!据我所知,在撰写本文时,这是迄今为止在所提供的验证集上最好的结果,并且训练时间比其他人在这个数据集上建议的模型短得多。

我们的模型完美地对验证集进行了分类。通过进行这种过采样,训练过程似乎比以前的模型更稳定。我们的验证损失现在显著低于以前的模型,并且更接近于训练损失。因此,我们可以用这个来确认那篇论文的结果,因为我们没有过度拟合就得到更好的结果。

结果绝对很棒,但是不要太高兴!:)您可能记得我们的验证集非常小,只有 16 个样本。这个样本数量远远小于我们对模型性能得出的可靠结论。实际上,如果你尝试我在这里所做的,你可能会得到不同的结果,因为在这种低数量的样本中,随机机会有很大的作用!我在测试集上测试了这个模型(我知道现在使用这个部分还为时过早,但我还是做了!)我得到了 85%的准确率,这证实了我在这里所说的,该模型不能很好地概括(目前!).

因此,为了训练一个真正好的和健壮的模型,从现在开始,在本文中,我将数据集提供的测试集合并到验证集,以便我们可以在实现其他技巧时更准确地判断我们的模型的行为,并决定下一步如何处理这些信息。下面是如何合并验证集和测试集:

合并 val 和测试集

这是过采样数据集上的新基线模型结果,合并了验证和测试集以及两个新指标,即精度和召回率:

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

合并验证和测试集后的模型性能,图片由作者提供

如你所见,结果越来越稳定,不会从一个数字跳到另一个数字。在接下来的每一部分中,我会在我们的训练过程中增加一个技巧,看看它是如何影响训练的。

正常化

在本节中,我将通过减去平均值并除以标准差来标准化我的数据。首先,我需要从我的数据中获得这些统计数据。我执行以下操作来获得每个通道的平均值和标准偏差:

正如你看到的,均值或标准差的三个数字是相同的,因为通道是相同的,正如我在上一节中所说的。

通过将以下内容添加到用于创建数据块的代码中,您将使您的数据规范化:

当我从头开始再次训练同一个模型时,我得到了以下结果:

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

标准化后的模型性能,图片由作者提供

这并没有造成很大的差异,主要是因为我们是从零开始训练,模型也可以适应非标准化的数据。

迁移学习和预训练模型

通过使用迁移学习和预训练模型来开始你的项目(或者在一些基线模型之后)几乎总是一个好主意。它们比随机初始化你的权重更有帮助,帮助你的模型更容易更快地收敛。在迁移学习中,重要的是你的输入数据与模型被训练的数据具有相似的特征;因此,我们将对数据进行归一化处理,使每个通道的均值为零,标准差为一。还记得我们(其实是 fastai!)重复我们拥有的单个通道,以便用三个通道使我们的图像像自然图像一样。所以,我们现在准备微调我们的第一个模型!像以前一样构建您的数据块,在您的 batch_tfms 中包含 Normalize ,然后您可以像这样轻松地构建您的预训练模型:

这里有几件事需要注意。我已经将架构更改为 resnet18,这与前一个非常相似,我在这里使用 cnn_learner ,默认情况下,它会加载模型的预训练权重,并冻结大多数层(除了新的随机初始化的模型头部),以便它们的权重不会更新。可以找到学习率,像以前一样训练模型。请记住,在 fastai v2 中,您可以使用 fine_tune 方法轻松地微调预训练的模型,该方法首先训练冻结的模型,然后将其解冻并训练更多的时期。但在这里,我是手动完成这个过程的:

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

预训练 resnet18 性能,图片由作者提供

好吧!通过使用预训练的模型,精确度提高了大约 2%。在图中,你可以看到看起来最好的结果是在训练的中间(时期 6 ),我们可能有比需要更多的时期。正如杰瑞米·霍华德在 2020 fastai 课程中提到的,最好是根据所需的历元数重新训练模型(例如,在本例中为 6 个),而不是使用具有大量历元的 EarlyStopping 或 SaveModel 回调。原因是我们正在使用一个周期训练,并且我们在最后的迭代中显著降低了学习率,这可能导致在损失表面中找到更好的最优值,这可以帮助模型更好地概括,并且如果我们在学习率高时在迭代中途停止训练,我们会失去这个机会。

解冻

现在我们解冻模型,并通过对不同的层使用不同的学习率来训练所有的层。我们知道,在迁移学习中,模型的早期层不需要改变太多的权重,因为他们负责学习的东西在 CV 任务中几乎是常见的。另一方面,随着我们在模型中深入,我们对各层使用更高的学习速率,以使它们适应新的任务。但在此之前,我们先来看看应该使用哪些学习率:

这是 lr_find()的结果:

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

作者图片

lr_find 情节的解释有时会变得困难。但在这种情况下是相当简单的。我将给出 slice(1e-6,1e-4)作为模型不同层的学习速率范围(早期层将具有 1e-6 的最大 lr ,最深层将具有 1e-4 作为它们的 max_lr )。我发现这个范围工作得很好,即使 lr_find 图不是很有帮助。

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

解冻后的模型性能,图片由作者提供

我们的准确度提高了 1%。正如你可能已经注意到的,我在这里训练的次数较少,因为我在此之前训练过一次,我发现 5 次就足够了,根据我之前在上一节中所说的早期停止,我重新训练了它,而不是在程序的中途停止训练。在下一节中,我们将进一步增强模型的性能。

渐进调整大小

到目前为止,我们用 224 * 224 大小的图片来训练我们的模型,与超过 512 * 512 的原始大小的图片相比,这是一个相当小的图片。这里,我们将使用尺寸为 360 * 360 的较大图像对上一节中的模型进行微调,以向我们的模型引入更多数据,并帮助它学习模式。你唯一需要改变的是:

我就是这样把尺寸改成 360 的。我们需要再次冻结模型并对其进行一点训练,然后解冻并进行更多训练。为了减少文章的篇幅,我只给你看最后的结果:

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

最终结果,图片由作者提供

那真的太牛逼了!我们在合并的验证和测试集上获得了大约 95%的准确率,并且精确度和召回分数都非常高。

在下一节中,我们将更彻底地解释我们的模型的结果。

模型解释

在这里,我将向您展示如何使用 fastai 轻松地获得模型的解释。让我们看一下获取混淆矩阵的代码:

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

混淆矩阵,作者图片

很公平!让我们也来看看分类报告:

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

分类报告,按作者分类的图像

这些数字表明我们在这个相当小的数据集上做得很好。我们现在可以检查我们在初始验证集(这 16 张图片)上做得如何。我知道这很奇怪,因为这些图像已经在我们的合并验证集中,但这只是一个简单的检查,以确保我们的模型比以前更强大,并且在提供的验证集上具有相同的性能:

好极了。百分之百的准确率、f1_score、精度和召回率。正如你所记得的,在文章的开始,在做了过度采样后,我们得到了 100%的准确性,这里我们重复了一遍。但是这个模型更健壮,因为在我们制作的更大的验证集的帮助下,我们能够测试不同的技巧,并使用培训期间打印出来的损失和指标来决定我们下一步应该做什么以及如何调整我们的模型。但不利的一面是,我们不再有任何测试集,我们实际上不知道这个模型在真实数据上表现如何,因为我们可能在合并的验证集上过度拟合了模型。但是结果真的很有希望,我们以后可能不会有问题。

文章的下一部分

由于这篇文章很长,我将在另一篇文章中解释其他技巧和实验,作为本文的第二部分。我们将看到如何使用 Grad CAM 和简单的热图来可视化我们的模型在图像中所关注的内容,我们将尝试超参数调整(调整重量衰减学习速率),我想你会对此感到非常兴奋。之后,我们将尝试标签平滑混合半精度训练和其他模型架构数据增强方法,我们将看到它们中的每一个如何影响项目。

来源 :我用了《fastai 和 PyTorch 和 Fastai 课程的程序员 深度学习》这本书里的很多思想。我强烈建议给他们一个尝试。

关于我:我是一名医科学生,我喜欢深度学习和我们能够用它来改善我们生活质量的酷东西。我要用它的力量来克服我们在医学上面临的障碍。除了医学课程,我还花了很多时间研究深度学习,我的目标是在人工智能和医学相遇的跨学科领域工作:)

FastAI:用深度学习对布鲁克林九九演员进行分类

原文:https://towardsdatascience.com/fastai-classifying-brooklyn-nine-nine-actors-with-deep-learning-4b06a8ab3cab?source=collection_archive---------16-----------------------

他们看见我在跳舞——他们憎恨我

随着第七季的播出,毫无疑问,布鲁克林九九是一部受欢迎的电视剧。我不会去探究原因,但是如果你还没有看过这部电影,并且有时间,那就没有理由至少不去尝试一下。

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

修改后的图片来自维基共享资源

但这不是一篇电视节目文章——这是一篇深度学习文章。更准确地说,这篇文章旨在利用深度学习的力量对节目中演员的图像进行分类。

好吧,但是,你将从哪里得到这些图像呢?

好问题。基本上这个想法是从网上下载图片——这并不是说我的意图是在之后出售这个模型(谁会从中受益?)。下载后,我们只需要做基本的图像操作——裁剪**。**

本质上,所有的图像都被裁剪成正方形,并且没有做任何准备工作。原因是将使用一个复杂的深度学习库来处理训练过程— FastAI

我以前写过关于它的文章,如果您想继续学习,请确保正确安装和配置了它。这篇文章可能会派上用场:

** [## FastAI 简介:安装和构建我们的第一个分类器

提示:仅用 5 行代码就能在 MNIST 上达到 98%的准确率!

towardsdatascience.com](/intro-to-fastai-installation-and-building-our-first-classifier-938e95fd97d3)**

数据结构

以下是我设法找到一些质量不错的照片的角色列表:

  • 杰克·佩拉尔塔
  • 艾米·圣地亚哥
  • 特里·杰福兹
  • 雷蒙德·霍尔特
  • 罗莎·迪亚兹
  • 查尔斯·博伊尔

所以没有希区柯克和史高丽不幸的是,因为他们在大多数镜头中都在一起,所以我不想花几个小时在 Photoshop*里。无论如何,对于上面提到的 6 个演员中的每一个,都保存了 25 张质量不错的照片。***

以任何标准来看都不是很多,这就是为什么我们将使用 ResNet 预训练网络来帮助我们一点。如果您决定自己搜索图像,然后制作分类器,下面是您应该如何构建目录:

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

是的,你没看错。此时, FastAI 库需要这种结构——或者至少我还没有设法让它工作。如果有,请告诉我。

还跟着我?

很好,现在我们可以进行模型训练了!

吉菲

让我们做一个模型

首先,我们需要进行两次导入——并且都来自于 FastAI 库(如果没有安装,请参考上面的文章):

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

让我们现在做一点准备。我们将用以下参数创建一个ImageDataBunch对象:

  • path:根图像文件夹的路径
  • train:将用于训练的图像路径。如果图像不是在训练/测试文件夹中构建的,您可以使用.来代替
  • valid_pct:由于我们在训练/测试文件夹中没有图像,此参数指定了用于验证的图像百分比
  • size:每幅图像将要变换的尺寸
  • bs:批量大小

我还将随机种子设置为 42,这样读者就可以复制结果。用它给出的代码实现:

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

现在让我们看看来自单个批次的几幅图像看起来会是什么样子:

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

准备工作已经完成!

现在我们可以实例化一个cnn_learner:

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

请注意我是如何使用 ResNet101 网络的预训练权重的。我们只有一些图像,如果我们不从头开始,结果通常会更好。ResNet101 已经知道人类“长什么样”,建议用它来处理类似这样的案例。

很好,我们有开始训练模型所需的一切。让我们训练它 15 个周期,看看会发生什么:

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

最终,我们的准确率在 84% 左右,这对于训练数据如此有限的多类分类问题来说并不算太差。

但是接下来让我们更深入的探讨车型评测**。**

模型评估

对于这种类型的问题,查看一个混淆矩阵来看看我们的模型在哪里表现得好,在哪里表现得不好,这将是很好的。

因此,我们可以创建一个ClassificationInterpretation的实例来访问混淆矩阵:

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

很好,现在混乱矩阵本身:

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

似乎我们的模型在某些情况下对这两种组合有问题:

  1. 特里·杰福兹—雷蒙德·霍尔特
  2. 艾米·圣地亚哥—罗莎·迪亚兹

我的意思是,对于这有限数量的图像,可以解释为什么模型是混乱的,但它仍然表现得相当不错——如果你考虑到 FastAI 库需要的时间和精力是多么少的话。

FastAI 可以做的另一件很酷的事情是向你展示它最容易与混淆的图像——这种方法被称为.plot_top_losses():

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

在这里,除了第一条,我什么都能理解——对我来说,这似乎是一个清晰的镜头。

在你走之前

现在你知道了,利用如此有限的数据,只需几行代码,我们就可以开发出一种基于深度学习的多类分类算法,准确率约为 84%。

吉菲

我的目标是未来在这个问题上花更多的时间,收集更多的图像,也许在 PyTorch 中编码整个事情。如果你想看的话,请告诉我。

我希望这对你来说是有趣的。感谢阅读。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

** [## 通过我的推荐链接加入 Medium-Dario rade ci

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

medium.com](https://medium.com/@radecicdario/membership)**

用 ULMFiT 进行快速灾害预测

原文:https://towardsdatascience.com/fastai-disaster-prediction-using-ulmfit-4dd244d3889c?source=collection_archive---------66-----------------------

迁移学习在自然语言处理领域的应用

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

照片由来自 PexelsLucas 拍摄

上个月,我启动了fastaiMOOC(2019)——面向程序员的深度学习。它涵盖了各种主题,如计算机视觉、自然语言处理、协同过滤等。我发现最吸引人的部分是迁移学习在自然语言处理领域的应用。 fastai 使用的方法是通用语言模型微调(ulm fit),这是一种应用于自然语言处理领域的迁移学习方法论。

[## 面向编码人员的实用深度学习

如果你现在就准备好投入进去,下面是开始的方法。如果你想更多地了解本课程,请阅读…

course.fast.ai](https://course.fast.ai/)

根据 维基百科 的说法,迁移学习 (TL)是机器学习中的一个研究问题 (ML)侧重于存储在解决一个问题时获得的知识,并将其应用于另一个不同但相关的问题。例如,在学习识别汽车时学到的知识可以应用到识别卡车上。

为了展示 ULMFiT 的用例,我将同样应用在上真实与否?NLP 与灾难推文Kaggle 上竞争。为了让您对数据有个大概的了解,数据集包含两个 CSV 文件train.csvtest.csv分别代表训练数据集和测试数据集。训练集包含text列中的 tweet 数据和target列中的 target 值,如果是真正的灾难,则 target 值为1,如果不是真正的灾难,则 target 值为0。测试集只包含 tweet 数据,没有目标值。任务是预测一条推文是否代表一场真正的灾难。

以下段落摘自了解 ULMFiT 的构建模块:

ULMFiT 的高级思想是使用像 wiki text-103(1.03 亿个标记)这样的非常大的语料库来训练语言模型,然后采用这个预训练模型的编码器并将其与定制的头部模型相结合,例如用于分类,并在多个阶段中使用有区别的学习率仔细地进行良好的旧的微调。ULMFiT 用于其语言建模任务的架构是一个 AWD-LSTM 。这个名字是 ASGD 减肥 LSTM 的缩写。

如果你想了解更多关于乌尔姆菲特的信息,请参考杰瑞米·霍华德和塞巴斯蒂安·鲁德写的这篇论文。

在计算机视觉问题中,迁移学习用于直接帮助分类,但是在 NLP 的情况下,我们首先建立一个语言模型,该模型基本上预测句子的下一个单词(该模型必须理解书写文本的语言(例如,英语等)。))然后使用语言模型的编码器和词汇表构建我们的分类模型。

正如在的论文中提到的,我们将使用在维基百科上预先训练好的 AWD-LSTM 架构。我们可以直接使用这个预先训练的语言模型来建立我们的灾难推文分类器,但这里的要点是维基百科的英语语言将不同于推文的英语语言。因此,我们将使用推文数据微调我们预先训练的语言模型,然后在此基础上建立我们的分类器。正如《Fastai 和 PyTorch 的程序员深度学习》一书中所解释的,他们在 IMDb 评论数据集上使用了相同的预训练架构来分类评论是正面还是负面。他们解释说,IMDb 评论英语更不正式,包含电影、导演、演员等的名字。比普通的维基百科英语更好,架构是在维基百科英语上预先训练的。

我们开始吧!!

我们导入我们的test.csvtrain.csv来获得我们的训练数据集和测试数据集。我不能分享数据集,因为它来自一个 Kaggle 竞赛,你可以登录你的帐户并遵守竞赛规则自行下载。

# Importing Pandas
import pandas as pd# Importing fastai libraries for text and callbacks
from fastai.text import *
from fastai.callbacks import *train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')

我不会详细介绍语言模型是如何构建的,你应该去看看 MOOCFastai 和 PyTorch 的《程序员深度学习》这本书,做进一步的阅读。基本思想是文本数据不能直接输入到模型中,它需要被转换成数字,这样我们就可以应用我们的数学函数。这通过使用记号化数字化来完成。在记号化中,我们将文本转换成记号列表,在数字化中,我们根据它们的索引将它们转换成数字。如果你想潜得更深,你应该参考

我们将使用数据块 API 在幕后为我们完成上述工作,然后我们将把创建的数据块输入到我们的语言模型中。

data_lm = (TextList.from_df(pd.concat([train[['text']], test[['text']]], ignore_index=True, axis=0))
           .split_by_rand_pct(0.15)
           .label_for_lm()
           .databunch(bs=128))
data_lm.show_batch()

文本列显示标记化和数值化的数据

我们忽略标签,从训练和测试数据中提取文本语料库。请记住,我们现在正在制作一个语言模型,而不是一个分类模型。我们只是尽可能多地包含文本数据,以便我们的语言模型预测句子的下一个单词。接下来,我们使用我们的data_lm数据束来制作我们的语言模型。

learn = language_model_learner(data_lm, AWD_LSTM, drop_mult = 0.5)
learn.lr_find()
learn.recorder.plot(suggestion = True)

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

learn.fit_one_cycle(1, 1e-2, moms=(0.8,0.7))

我们将解冻模型,我们将适应更多。我们将使用回调来选择最佳模型。

Better model found at epoch 0 with accuracy value: 0.4097544550895691.
Better model found at epoch 1 with accuracy value: 0.4404464364051819.
Better model found at epoch 2 with accuracy value: 0.4609375.
Better model found at epoch 3 with accuracy value: 0.47495537996292114.
Better model found at epoch 4 with accuracy value: 0.48810267448425293.
Better model found at epoch 5 with accuracy value: 0.49515628814697266.
Better model found at epoch 6 with accuracy value: 0.4975222945213318.
Better model found at epoch 9 with accuracy value: 0.49756699800491333.

我们将选择 9 号纪元时的最佳精度。然后我们将保存语言模型和编码器。

learn.save('fine_tuned')
learn.save_encoder('fine_tuned_enc')

接下来,我们将制作分类器。为此,我们需要创建一个新的数据中心。我们将验证集设为 10%,我们将保持我们的词汇表与语言数据库中的词汇表相同。我们还将在单独的add_test参数中添加我们的测试数据。

data_clas = (TextList.from_df(df, vocab=data_lm.vocab)
             .split_by_rand_pct(0.1)
             .label_from_df('target')
             .add_test(TextList.from_df(test['text'], vocab=data_lm.vocab))
             .databunch(bs=128))

我们将使用与语言模型相同的编码器来构建分类器。

learn = text_classifier_learner(data_clas, AWD_LSTM, drop_mult=0.5, metrics=[accuracy, FBeta(beta=1)])
learn.load_encoder('fine_tuned_enc')

我们将进行lr_find()检查,然后绘制图表。

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

我们来拟合一个周期。我们看到我们得到了 77.66%的精度**。**

learn.fit_one_cycle(1, 1e-3, moms=(0.8,0.7))

让我们解冻最后 2 层,训练一个周期。我们的准确度提高到 79.5 %。

learn.freeze_to(-2)
learn.fit_one_cycle(1, slice(1e-3/(2.6**4),1e-2), moms=(0.8,0.7))

我们将解冻最后 3 层,然后再训练一个周期。我们的准确率提高到 81.73%

learn.freeze_to(-3)
learn.fit_one_cycle(1, slice(5e-3/(2.6**4),5e-3), moms=(0.8,0.7))

我们在这里使用的是在 ULMFiT 中引入的区别学习率。正如文章中所解释的,我从 fast.ai v3 中学到的 10 个新东西:

预训练模型的判别学习率 以超低学习率训练早期层,以较高学习率训练后期层。这个想法是不要剧烈地改变几乎完美的预训练权重,除了极少量的,并且更积极地教导输出附近的层。在 ULMFiT 中引入了判别学习率。

我们将解冻所有层,训练,并使用回调来选择我们的最佳模型。

callbacks = SaveModelCallback(learn,monitor="accuracy", mode="max", name="best_classification_model")
Better model found at epoch 0 with accuracy value: 0.8160315155982971.
Better model found at epoch 1 with accuracy value: 0.8173456192016602.
Better model found at epoch 2 with accuracy value: 0.822601854801178.
Better model found at epoch 9 with accuracy value: 0.8239158987998962.

我们得到的准确率为 82.39% !!

结论

在迁移学习中,我们使用来源的知识,并将其应用于我们的目标。在自然语言处理领域中同样的实现提供了非常先进的结果,因为我们使用了预先训练的网络,所以只需要最少的训练。如果你想看代码的运行,你可以看看我在 Kaggle 上的笔记本: NLP -灾难预测 ULMFiT

注:我在这里用的是法士泰 V1。fastai V2 和新的 MOOC 于 8 月 21 日发布。看看这里

参考

**[## 用于文本分类的通用语言模型微调

归纳迁移学习极大地影响了计算机视觉,但现有的自然语言处理方法仍然需要…

arxiv.org](https://arxiv.org/abs/1801.06146)** ** [## 利用 fastai 和 PyTorch 为编码人员提供深度学习

深度学习通常被视为数学博士和大型科技公司的专属领域。但是作为这个实践指南…

www.oreilly.com](https://www.oreilly.com/library/view/deep-learning-for/9781492045519/) [## 面向编码人员的实用深度学习

如果你准备好现在就开始,这里有一些方法。如果你想更多地了解本课程,请阅读…

course.fast.ai](https://course.fast.ai/) [## 视力

模块 fastai . vision . transform:get _ transforms(do _ flip:bool = True,flip_vert: bool…

fastai1.fast.ai](https://fastai1.fast.ai/vision.html) [## 了解 ULMFIT 的构建模块

上周,我有时间处理了一个 Kaggle NLP 竞赛:Quora 虚假问题分类。因为很容易…

medium.com](https://medium.com/mlreview/understanding-building-blocks-of-ulmfit-818d3775325b) [## 我从 fast.ai v3 中学到的 10 件新事情

参加课程 3 周后的学习要点

towardsdatascience.com](/10-new-things-i-learnt-from-fast-ai-v3-4d79c1f07e33)**

FastAPI + AWS =健壮的 API(第 1 部分)

原文:https://towardsdatascience.com/fastapi-aws-robust-api-part-1-f67ae47390f9?source=collection_archive---------0-----------------------

理解大数据

让我们用 FastAPI、AWS Lambda 和 API Gateway 构建一个可伸缩的无服务器的基于 Python 的 REST API

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

背景照片由斯潘塞·塞洛弗拍摄,来自Pexels——作者编辑

astAPI 彻底改变了开发现代基于 Python 的 REST APIs 的方式。从一开始,这个项目就被大公司采用,如微软、优步和网飞,而且它越来越受欢迎,我们可以通过每天增长的 Github 明星数量来观察。

能够构建快速、健壮、安全和可伸缩的 API 是任何后端(数据)工程师的必备技能。在本文中,我们将构建一个简单的 REST API,以您选择的货币(欧元、美元等)显示市场情绪和所选加密货币的当前价格。)。

我们将使用自顶向下的方法:从打包和部署 API 到深入了解它的细节。在第 1 部分中,我们将利用 Amazon Lambda 和 API Gateway 将 FastAPI 代码部署到 AWS。在未来的文章(第 2 部分)中,我们将确保通过使用 API 密钥来保护我们的 API。我们还将演示如何启用分布式跟踪和日志记录来跟踪应用程序的健康状况。让我们开始吧!

目录:

  1. 用虚拟环境创建一个 Pycharm 项目
  2. 安装所需的库
  3. 在本地测试 API
  4. 打包您的代码并准备部署管道(包括创建 Lambda 函数)
  5. 在 API 网关中创建 REST API
  6. 将 Lambda 函数配置为代理,将请求从 API Gateway 转发到 Amazon Lambda
  7. 将 API 部署到dev阶段
  8. 测试端点
  9. 深入探究这一切是如何协同工作的
  10. 使用 Swagger UI 演示加密货币 API
  11. 结论

1.用虚拟环境创建一个 Pycharm 项目

让我们从在 Pycharm 中创建一个具有虚拟环境的项目开始。你可以使用VirtualenvConda——随你喜欢。我一般在 macOS 上用Virtualenv,在 Windows 上用Conda

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

苹果电脑上 Pycharm 中的 Virtualenv 图片由作者提供

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

Windows 上 Pycharm 中的 Conda 虚拟环境—图片由作者提供

如果你想跟进,这个 Github 库包含了这个项目的代码。

2.安装所需的库

让我们将当前工作目录更改为api文件夹,并安装所需的包:

cd api && pipinstall -r requirements.txt

3.在本地测试 API

安装完所有的包依赖项后,我们可以在终端中启动 Uvicorn ASGI 服务器:

uvicornmain:app --reload

如果您配置了虚拟环境,并从 Github 下载(或克隆)了代码,那么您应该能够从浏览器访问交互式 Swagger UI:

http://localhost:8000/docs

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

我们正在构建并部署到 AWS 的简单 API 图片由作者提供

4.打包您的代码并准备部署管道

为了使我们的 API 可以从 API Gateway 访问,我们需要:

  • 将我们的 API 代码和所有的site-packages依赖项压缩成一个 zip 文件,这个文件将被我们的 Lambda 函数使用

  • 将这个 zip 文件上传到 S3 ( 理论上,我们可以将它直接上传到 Lambda,但是有一个 10MB 的 zip 文件大小限制为了准备我们的应用程序的增长,我们将把它直接上传到 S3,并且在 Amazon Lambda 创建期间,我们将确保 Amazon Lambda 使用这个来自 S3 的 zip 文件

注意:本部分要求您安装并配置 AWS CLI

  • 使用 Python 3.8 运行时创建 Amazon Lambda 函数,选择选项*“创建一个具有基本 Lambda 权限的新角色”,*,将 Lambda 处理程序配置为main.handler,如 GIF 所示:

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

创建一个 Lambda 函数+配置处理程序——图片作者

  • 更新函数以确保它使用来自 S3 的打包代码(我们也可以从管理控制台执行此操作):
*aws* lambda update-function-code --function-name medium-demo \
--s3-bucket $bucket_name --s3-key lambda.zip

5.在 API 网关中创建 REST API

从管理控制台,确保为 API Gateway 中的 API 选择与 Lambda 函数相同的区域。尽管 API 网关和 Lambda 函数可能位于不同的区域,但这可能会导致一些额外的延迟

然后:创建 API →选择 REST API ( 不是私有的 ) →构建→输入你的 API 的名字→创建 API。

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

创建 REST API—按作者分类的图像

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

为 API 选择一个名称。保留区域端点—按作者分类的图像

6.将 Lambda 函数配置为代理,将请求从 API Gateway 转发到 Amazon Lambda

现在我们需要为我们的请求方法配置集成点。使用 Lambda 函数作为ANY类型请求(即 GET、POST、PATCH、DELETE 等)的集成点。),我们将创建一个方法 ( 处理根路径)和一个子资源 ( 处理所有子路径)。我们将通过使用 Lambda 代理集成 [1]来配置它们,以处理对 API 网关的任何请求。

创建一个方法

  • 从下拉菜单中选择动作:
    1。创建方法
    2。选择ANY
    3。选择 Lambda 函数作为您的集成类型,并确保选中复选框*“使用 Lambda 代理集成”*
    4。添加您的 Lambda 函数的名称(及其对应的区域)并保留其他所有内容的默认值→保存

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

1.创建方法—按作者创建图像

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

2.选择任意→添加 Lambda 函数的名称→保存—按作者分类的图像

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

确认权限-按作者分类的图像

当弹出窗口询问您是否要授予 API 网关调用 Lambda 函数的权限时,请确认。没有它,API Gateway 将无权调用您的 Lambda 函数。

创建资源

类似于*“方法”配置,转到操作→创建资源。确保选中复选框“配置为代理资源”*,并保留默认设置以启用 Lambda 代理集成(与之前的),然后选择您的 Lambda 函数并保存。

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

创建资源-按作者分类的图像

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

将 Lambda 配置为代理—按作者排序的图像

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

从菜单中选择你的 Lambda 函数并保存——作者图片

再次确认您允许 API Gateway 代表您的 API 请求调用 Lambda 函数:

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

确认权限-按作者分类的图像

7.部署 API

既然我们的 Lambda 现在已经配置好了,我们就可以部署 API 了。我们可以把它命名为dev阶段。部署对于激活 Lambda 函数集成至关重要。

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

8.测试端点

将 API 部署到任何部署阶段都可以确保 API Gateway 创建一个 URL 作为 API 的前门。您可以点击这个 URL 并测试 API 是否已经正确配置。

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

在您的浏览器中,您应该会看到对应于 FastAPI 代码的根 GET 路径的响应:

{"Hello Medium Reader": "from FastAPI & API Gateway"}

我们可以继续直接从浏览器测试更多的端点:

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

边注: 如果端点dev/v1/prices/ETH不为您工作,并且您得到消息{"message": "Missing Authentication Token"},您应该重试创建资源代理并重新部署 API。

至此,我们可以看到任何人都可以公开访问我们的 API。在第 2 部分的中,我们将通过直接从 API 网关控制台创建一个 API 键来改变它。

9.深入探究这一切是如何协同工作的

现在,你可能有许多问题。我将试着猜测并以问答的形式回答这些问题:

1。我们如何让本地 FastAPI 代码与 Amazon Lambda 一起工作?

我们使用了Mangum库[5],它是运行在 AWS Lambda 和 API Gateway 内部的 ASGI APIs 的包装器。它提供了一种适配器,该适配器:

  • 将对 API 网关的请求路由到我们的 Lambda 函数,
  • 将 Lambda 函数响应路由回 API 网关。

我们只需添加两行(第 1 行和第 7 行)就可以将main.py中的 FastAPI 代码转换为 Amazon Lambda 处理程序:

2。API Gateway 中的方法和资源有什么区别?

ANY 方法将把请求路由到根路径/到执行 FastAPI 代码的 Lambda 函数。相比之下,子资源将以贪婪模式路由根路径/下的所有路径(贪婪路径参数: *{proxy+}* ) [7],即,它会将 FastAPI 代码中定义的所有其他端点路由到 Lambda,例如路径/v1/prices/BTC/.

3。为什么我们需要 **{proxy+}**

使用代理,我们不需要编写任何映射模板来将特定路径路由到不同的 Lambda 函数——相反,我们有一个服务于所有端点的 Lambda 函数[6]。然后,API Gateway 会将所有类型的请求( GET、POST、DELETE、PATCH、… )从 API Gateway 路由到FastAPI代码中定义的路径。由于有了Mangum适配器,FastAPI 代码可以在 Lambda 函数内部执行。

4。这种架构如何扩展?

每个对 API Gateway 的请求都会调用一个 Lambda 函数。这意味着我们可以有数以千计的对我们的 API 的并行请求,因为每一个都将由一个单独的 Lambda 函数调用来服务。

请注意,对于每个帐户可以有多少个并行 Lambda 执行,存在软并发限制(在撰写本文时为 1000 个)。如果你需要更多,你可以使用支持中心控制台请求增加这个限制【2】。

5。这种架构为什么有吸引力?

它提供了一个完全无服务器的 API 基础设施,有很多好处:

  • Python 和令人惊叹的FastAPI库的所有优势与无服务器架构的优势相结合
  • 可伸缩性 &无需管理后端服务器——API Gateway 将根据需要运行尽可能多的 Lambda 函数来处理对我们 API 的所有请求
  • 非常划算,尤其是对于那些可能还没有收到数百万次请求的小型 API
  • 性能:由于 Lambda 的上下文重用,连续的请求(从前一个请求起 15 分钟内的*)重用冻结的执行上下文,允许减轻无服务器功能的冷启动*
  • 如果启用,API 网关缓存允许进一步改善延迟
  • API 密钥的简单管理
  • API Gateway 提供与活动目录和第三方身份验证提供者的集成,例如通过 Cognito 使用“Google/Amazon 帐户登录”**
  • 所有 API 请求和响应的现成集中式日志**,以及通过CloudWatch的访问日志**
  • 通过启用 X 射线追踪的分布式追踪功能。

6。为什么我们使用虚拟环境中的站点包来安装包依赖项?

我们可以将库安装到某个特定的目录中(例如libs目录)添加标志-t,代表目标:

pip install -r requirements.txt -t ../libs/

然后我们可以将这个目录添加到我们的lambda.zip中。

然而,这样一来,我们的项目将会被安装到项目目录中的 Python 包弄得乱七八糟,并且这可能会使其他开发人员以后更难区分实际的 API 代码和它的依赖项。我们可能必须将libs目录添加到.gitignore中。总的来说,这会增加额外的工作,如果我们使用虚拟环境和它的site-packages,就不需要这样做。

7。我们是否可以使用无服务器框架或 AWS SAM 来创建部署管道?

是的,这种设置与无服务器框架配合得很好。下面是一个可能的例子:

** [## jordaneremieff/无服务器-mangum-示例

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/jordaneremieff/serverless-mangum-examples/tree/main/fastapi-example)

然而,我更喜欢最小化我的项目中的依赖性,并且serverless需要额外的组件,比如节点包管理器。

您也可以将此设置与 AWS SAM 一起使用。

8。这要花多少钱?

使用免费等级,您可以每月(免费)访问:

  • 100 万个 API 网关请求
  • 每月 100 万次 Lambda 调用,计算时间高达 320 万秒

除此之外,价格可能会根据您的 AWS 地区和您的请求数量而有所不同(批量折扣),但它们的范围是每一百万个请求 1-4.25 美元(在撰写时为*)。Lambda 的定价基于调用次数和代码运行时间,以毫秒为单位。你可以在这里找到更多,在这里找到更多***

10.使用 Swagger UI 演示加密货币 API

最后,这是 API 正在做的事情——所有功能都基于来自 CryptoCompare [4]的信息:

  • 我们正在获取交易信号,以获得关于特定加密货币的市场情绪的信息,即当前是上升还是下降趋势
  • 我们正在获取选定加密货币的实时价格,并可以用我们选择的特定货币显示它们。

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

我们的示例 API 的演示——作者制作的 GIF

11.结论

在本文中,我们讨论了利用 FastAPI、API Gateway 和 Amazon Lambda 将 REST API 部署到 AWS 的过程。在这个过程中,我们学习了如何打包代码和创建部署管道,并讨论了所有这些微服务组件如何协同工作。

在第 2 部分文章中,我们将继续构建这个 API,通过 API 密钥添加身份验证、分布式日志记录和跟踪,以及在对 FastAPI 代码进行更改后如何重新部署 API。

** [## FastAPI + AWS =安全 API(第 2 部分)

让我们用 FastAPI、AWS Lambda、API Gateway、CloudWatch 和 AWS X-Ray 构建一个安全且可观察的 Python REST API

towardsdatascience.com](/fastapi-aws-secure-api-part-2-1123bff28b55)

如果这篇文章有用, 关注我 看我下一篇文章。

参考文献:

肖恩·拜尔的博客

[2] 亚马逊 Lambda 文档

[3] API 网关文档

[4] CryptoCompare API 文档

[5] 曼古姆文档

[6]关于λ代理整合

【7】如何使用亚马逊 API 网关{proxy+}**

FastAPI + AWS =安全 API(第 2 部分)

原文:https://towardsdatascience.com/fastapi-aws-secure-api-part-2-1123bff28b55?source=collection_archive---------20-----------------------

让我们用 FastAPI、AWS Lambda、API Gateway、CloudWatch 和 AWS X-Ray 构建一个安全且可观察的 Python REST API

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

照片由斯潘塞·塞洛弗派克斯拍摄

在本文的第 1 部分中,我们讨论了如何使用 API Gateway 和 Amazon Lambda 为 AWS 构建和部署 FastAPI 应用程序。在第 2 部分中,我们将在此基础上确保我们的 API 是安全的、易于重新部署的,并且我们可以通过分布式日志记录和跟踪来监控它的健康状况。本文基于一种自上而下的方法:我们将首先创建所有的资源,然后我们将更深入地了解它们的细节,并讨论所有这些服务如何协同工作。

目录:

  1. 通过创建 API 密钥并为其分配使用计划来保护 API
  2. 在 Postman 中测试 API 键
  3. 对 API 进行更改并重新部署
  4. 通过 X 射线启用 CloudWatch 日志和分布式跟踪
  5. 深入探究这一切是如何协同工作的
  6. 结论

1.通过创建 API 密钥并为其分配使用计划来保护 API

需要 API 密钥

首先,在 API 网关中,我们需要为方法和资源代理设置选项“需要 API 密钥”为true:

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

作者图片

创建 API 密钥

转到左侧导航面板中的“API 密钥”部分:

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

作者图片

现在我们可以创建一个 API 键:操作→创建 API 键→保存:

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

作者图片

创建使用计划

然后,让我们创建一个使用计划[1]:转到使用计划(API 键上方左侧导航栏中的*)→创建:*

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

创建使用计划—按作者分类的图像

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

我输入的数字是任意的——可以根据您的需要随意调整。作者图片

一旦我们有了使用计划,我们可以将它与部署到dev阶段的 API 关联起来:

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

作者图片

让我们之前创建的 API 键与这个使用计划相关联:

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

作者图片

现在最重要的部分是:要激活对 API 密匙的更改,我们需要重新部署我们的 **dev** API 阶段:

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

作者图片

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

作者图片

2.测试 API 密钥

在我们的浏览器中,我们现在应该会看到一条消息“禁止”(可能需要 1-2 分钟,更改才会生效)。

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

作者图片

我们可以通过 Postman 用我们的 API 密匙测试使用情况:

  • 首先,在 API 键旁边,我们单击“Show ”,然后复制 API 键并将其粘贴到 Postman 中的请求头字段Value:

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

作者图片

  • Key必须设置为x-api-key,而Value是你从管理控制台复制的 API Key:

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

作者图片

单击“发送”后,您应该会看到正确的 API 响应。

3.对 API 进行更改和重新部署

您可以从 Github 库下载该项目的代码。

让我们对根路径的返回值做一个小小的改变:

为了对部署到 AWS 的 API 进行这些更改,我们重复打包代码的步骤,如本文第 1 部分所述:

[## FastAPI + AWS =健壮的 API(第 1 部分)

让我们用 FastAPI、Amazon Lambda 和 API Gateway 构建一个可伸缩的基于 Python 的 REST API

towardsdatascience.com](/fastapi-aws-robust-api-part-1-f67ae47390f9)

我们需要:

  • 压缩代码及其所有依赖项
  • 上传这个压缩文件到 S3
  • 更新 Lambda 函数。

这一切都可以通过以下几行实现:

在执行命令:bash package_and_update_lambda_code.bash之后,我们应该能够看到 API 中反映的更改(不需要重新部署 API stage,因为我们只对底层 Lambda 函数进行了更改,而没有对 API 网关资源进行更改):

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

4.通过 X 射线启用 CloudWatch 日志和分布式跟踪

为了利用集中式日志记录,我们需要做的就是选中 CloudWatch Logs 旁边的复选框。就是这样!我们可以选择所需的日志级别以及是否记录完整的请求/响应数据

最重要的是,我们可以启用访问日志,这有助于了解哪些用户或代理使用了特定的端点。这样的话,如果出了问题,我们就可以追踪访问记录。

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

x 射线:服务地图

在启用 X 射线跟踪并发出一些 API 请求后,我们应该能够看到收集到的跟踪和指标:

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

服务地图中可视化的 x 射线追踪-由作者提供的图像

上图中标记为黄色的错误是我试图在没有使用 API 密钥进行身份验证的情况下从浏览器访问 API 的结果。

跟踪 CloudWatch 中的 API 日志

为了为您的 API 找到正确的日志组,请查找以 API ID 开头的日志组。然后,您可以找到所有 API 请求和响应的日志:

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

云观察日志-按作者分类的图片

5.深入探究这一切是如何协同工作的

让我们更深入地了解这些服务是如何工作的,以及如何有效地使用它们。

1。什么是使用计划?

API Gateway 允许我们构建可以作为产品货币化的 API。使用计划以及相关的 API 密钥让我们能够以特定的请求率和速度向授权客户提供我们的 API:

“使用计划指定了 可以访问一个或多个已部署的 API 阶段和方法,以及 他们可以多快 访问它们。”[4]

这意味着通过在特定的 API 阶段将 API 键分配给特定的使用计划。dev 或 prod ,我们可以对不同的 API 阶段实现不同级别的权限和不同的节流限制。我们可以为每个使用计划分配许多 API 键,这允许细粒度的访问控制。

2。我们如何使用 API 键?

API 密钥是简单的字符串( 30-128 个字符长),可以分配给使用计划或 Lambda 授权者。它们允许我们在 API 阶段和请求类型级别分配权限。

例如,我们可能希望在dev阶段有更多的开放访问,而在prod阶段有更多的限制访问。这意味着一个特权用户可以访问两个阶段devprod,而其他一些用户可以获得一个 API 密钥,该密钥只分配给与dev API 阶段相对应的使用计划。

3。我们如何区分 Lambda 执行和 API 网关请求的 CloudWatch 日志?

CloudWatch 将日志存储在与每个服务相对应的独立日志组中(例如 API 网关)和服务内资源(您的特定 API)。您可以通过查找 API ID 来识别与 API 网关日志相对应的日志组。您可以在 URL 端点或管理控制台中找到它:

*https://<API-ID>.execute-api.<REGION>.amazonaws.com/<API_STAGE>*

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

如何找到你的 API ID——图片作者

API Gateway 中对应于您的 API 的日志组将类似于:

*API-Gateway-Execution-Logs_<YOUR_API_ID>/<YOUR_API_STAGE>*

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

API 网关日志—按作者分类的图片

Amazon Lambda 日志可以通过函数名来识别:

*/aws/lambda/<YOUR_FUNCTION_NAME>*

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

Lambda 日志—作者图片

4。X 射线是如何工作的?

x 射线是一种分布式跟踪服务。它跟踪诸如对我们的 API 的请求的延迟和成功率以及我们的服务中的不同组件如何相互依赖等指标。X-Ray 的主要好处是它生成了一个服务图,这让我们可以分析哪些请求被其他下游请求跟随,以及我们的 API 中有哪些潜在的瓶颈。

在内部,X-Ray 通过使用生成跟踪,即执行 API 请求的计算资源,如 API Gateway 和 Amazon Lambda。这些片段可以被分解成子片段以进行更细粒度的跟踪——例如,我们可以在 FastAPI 代码中使用 X-Ray 的 Python SDK 来添加新的子片段,进行注释,并整体上使我们的跟踪更细粒度。

单个跟踪收集由特定请求生成的所有段和子段。

5。X 射线会自动跟踪并记录每个请求吗?

简而言之:不。测量每一个请求将是昂贵的,并且很可能是不必要的(如果前 50 个相同类型的请求每个花费 200 毫秒,那么接下来的 500 万个后续请求很可能也是如此)。x 射线使用代表样本:默认情况下,它跟踪每秒的第一个请求,外加所有附加请求的 5%。这个采样规则可以根据您的特定请求的属性进行配置[2]。

还有两种不同类型的跟踪:主动被动。两者具有相同的效果,因为它们导致 X 射线对请求进行采样并收集跟踪。

当我们在调用我们的 Lambda 函数的 API 网关中启用 X 射线时,这意味着在这个 Lambda 函数上启用了被动跟踪,因为上游服务(即 API 网关)负责添加跟踪头,告诉 Lambda 是否发送跟踪。相反,如果我们直接从 Lambda 配置而不是从 API Gateway 启用跟踪,这将是主动跟踪

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

在 Lambda 配置中启用活动跟踪—按作者分类的图像

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

在 API 网关阶段配置中为 Lambda 启用被动跟踪—图片由作者提供

5。X 射线与 CloudWatch 和 CloudTrail 有什么不同?

X 射线让我们收集关于特定 API 或微服务的指标。 CloudTrail 拥有更广泛的“受众”——因为 AWS 中的一切都是 API 调用,所以我们的 AWS 帐户中的每个操作都可以用 CloudTrail 跟踪。有可能将 X 射线与 CloudTrail* 集成起来,以跟踪用户、IAM 角色或任何 AWS 服务所做的额外操作,并在 X 射线跟踪中分析它们[3]。*

相比之下, CloudWatch 允许我们跟踪执行日志、访问日志,甚至完整的请求和响应数据,并直接在 CloudWatch 控制台中或在 Kibana 或 Grafana 等工具中分析它们。

虽然 CloudWatch 为我们提供了详细的日志,但 X-Ray 只为我们提供了关于延迟和采样请求状态的指标。

6。这些服务的费用是多少?

价格根据您的 AWS 地区、API 类型( REST、HTTP )和您的请求数量(批量折扣)而有所不同。在撰写本报告时:

  • API 网关每 100 万次请求的成本在 1-4.25 美元之间。
  • AWS X 射线的价格大约是每一百万道 1 美元。
  • AWS Lambda 根据调用次数和代码运行时间收费,以毫秒为单位。
  • 最后, CloudWatch 日志的价格在每月收集的每 GB 日志 0.50-0.90 美元之间(同样,价格因地区而异)。

您可以使用 AWS 定价计算器来获得与您的用例相对应的更现实的估计。另外,请注意,使用免费层,您可以(有限的)免费访问 API Gateway、Amazon Lambda 和 CloudWatch 日志。

6.结论

在本文中,我们研究了如何使我们的 API 安全且易于维护。我们讨论了如何分配使用计划和 API 键,以及如何通过启用分布式日志记录和跟踪来监控 API 的健康状况。最后,我们深入研究了这些服务是如何工作的,以及如何有效地使用它们。

如果这篇文章有帮助, 关注我 看我下一篇文章。

参考文献:

[1] 关于使用计划的 API 网关文档

[2] AWS X 射线文件关于取样请求和追踪

[3] AWS Edx 课程在 AWS 上构建现代 Python 应用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值