TowardsDataScience 博客中文翻译 2020(八百零八)
图 1:脉冲神经网络方案[1]脉冲神经网络已被证明是模拟大脑行为和学习潜力的最成功的方法之一,并利用它们来承担实际的在线学习任务[1]。由蒂姆·莫斯霍尔德在Unsplash上拍摄的照片S是一个 python 模块,适用于任何正在寻找使用云计算的简单方法的程序员。最初是为机器学习项目开发的,使得使用 Amazon Web Services 和 EC2 实例变得很容易。AWS 提供的服务和设置帐户的步
点云的球面投影
大家好,这是我的第一个媒体帖子,我希望让大家参与到最后。在这篇文章中,我将谈论如何使用球面投影将 3D 点云投影到图像中。我也写了同样的代码,可以在我的 GitHub 库这里找到。所以让我们开始吧!!!
球形投影或前视图投影只不过是将 3D 点云数据表示成 2D 图像数据的一种方式,因此本质上,它也充当降维方法。球面投影越来越多地用于不同的深度学习解决方案中,用于处理点云。
语义分割(作者: SemanticKitti
应用最广泛的领域之一是对点云中的物体进行分类和分割。这可以在各种出版物中看到,如 PointSeg 、squeeze g、 SalsaNet 等等。将点云表示为图像的最大优点是,它将过去十年中对 2D 图像所做的所有研究都开放给了 3D 点云。例如,不同的最先进的网络,如 FCN 、 U-Net 、 Mask-RCNN 、和 fast-RCNN现在可以扩展到点云数据,这是许多研究人员正在努力实现的目标,特别是在自动驾驶领域。
直观解释
为了理解这一点,让我们深入了解激光雷达是如何形成一点云扫描的。让我们考虑下图所示的 16 激光雷达的情况。
左图显示了由 16 个激光器组成的激光雷达。由激光雷达的第一个和最后一个激光器形成的最大和最小视角由 FOV _ 上和 FOV _ 下指示。右边的矩形是当我们将激光雷达形成的空心圆柱体投影到平面上时得到的。(作者:阿尼鲁德·托皮瓦拉)
16 个激光器中的每一个都以固定的角度定向,这取决于垂直角分辨率,FOV _ 上(上部视场)和 FOV _ 下(下部视场)。每个激光雷达都有一个发射和接收单元。这些点是通过计算每个激光从物体反射后的飞行时间而形成的。这 16 束激光旋转 360 度形成一个点云。
因此,这将导致的几何形状是一个空心圆柱体,激光雷达位于其中心。当我们从一个垂直于圆柱体主轴的轴将这个空心圆柱体投影到一个平面上时,我们得到一个图像。这种图像称为球面投影图像。
现在让我们用一些数学来解决技术问题吧!!
(作者:阿尼鲁德·托皮瓦拉)
我们的目标是找到所有(x,y,z)点的投影图像的像素坐标。这可以通过使用球面坐标系来实现。看上图,我们可以看到,如果+ive x 轴是激光雷达的前视图,那么云的每个点都会与 xy 平面形成一个倾角角度 ,俯仰 和角度 ,偏航 与 xz 轴。这里我们要把空心圆柱体投影到 zy 平面上形成图像。利用基本的三角学,我们可以得到每个点的俯仰和偏航值。由于原点位于图像的中心,这些偏航和俯仰值构成了投影图像的每个像素位置。因此,通过计算每个点的偏航和俯仰,我们可以完整地形成投影图像。在这一点上,我还想指出,俯仰值的范围将从[FOV 向上,FOV 向下],因为它是激光指向的最大和最小角度,偏航值的范围将从[-π,π],因为这是由 atan2 函数给出的范围。
虽然我们现在有了投影图像,但是由于两个问题,我们仍然不能使用它。首先,我们需要将原点平移到图像的左上角,如下所示。这是因为,在计算机视觉中,标准是原点在图像的左上角。第二,我们需要根据使用的激光雷达的类型来缩放图像。这两个步骤如下所示:
(作者:阿尼鲁德·托皮瓦拉)
1.翻译原文
这是一个简单的翻译起源问题。查看上图,我们可以通过向偏航轴添加π角来将原点移动到图像的左边缘,而通过从 FOV_Up 中减去俯仰角来将原点移动到图像的顶部。因此,新方程变成:
2.标准化和缩放
这一步骤是必要的,因为对于不同类型的激光雷达,投影图像的大小会有所不同,主要目的是在投影图像中拟合尽可能多的点。
正如我们在这篇博文中观察到的,整个过程是关于降维的,因此,我们会丢失数据是事实。这里的想法是以这样一种方式形成图像维度,即我们能够从图像中的云中捕捉最相关的点。因此,我们可以从逻辑上看到,激光雷达的个激光应该相当于投影图像的宽度。这样,图像的每一行将与从激光雷达的每个激光器获得的点相关。该值称为 row_scale 因子,乘以归一化的俯仰轴。例如,威力登 HDL 64-E 激光雷达有 64 个激光器,因此,投影图像的宽度应该通过将该值乘以俯仰轴来设置为 64。
图像的长度构成了偏航角分辨率。该参数可以调整以适应尽可能多的点。图像的这个长度也称为 col_scale,乘以归一化的偏航轴,得到最终的图像尺寸。同样,对于 HDL 64-E,最大水平分辨率为 0.35 度。因此,在最坏的情况下,我们将至少得到每个激光器(360/0.35 = 1028)个点。在深度学习和卷积网络中,图像大小优选为 2 的幂。因此,1024 的长度将适合图像中的最大点数,我们将把这个值乘以偏航轴。
因此,64X1024 的图像尺寸对于 HDL 64-E 来说是理想的。可以对威力登 VLP-16 进行类似的计算,其中最佳图像尺寸为 16x1024。
归一化等式现在可以重写为:
如果总的 FOV = FOV _ 上+ABS(FOV _ 下),那么(u,v)的最终方程通过一些值的重新排列可以写成:
对于威力登 HDL 64-E 激光雷达,同样的方程可以改写为:
这样,借助上面的方程,我们就可以把云的每个点(x,y,z)投影到它对应的球面投影(u,v)上。
将点信息编码到图像中
一旦我们获得了云的每个点的(u,v)像素,我们需要对其进行舍入以获得最接近的整数,并将点信息编码到其中。通常,在每个像素处添加 5 个关键值,即 X、Y、Z、R 和 I。这里,(X,Y,Z)是点的坐标,R 是该点与激光雷达的欧氏距离或范围,I 是强度。Range 是我们计算的唯一值,因为对于激光雷达形成的云的每个点,X、Y、Z 和 I 值已经存在。因此,我们得到的最终图像尺寸是:
图像尺寸=激光雷达的激光数量投影图像的长度 5(五个通道是 X、Y、Z、R、I)
现在是你期待已久的部分…结果!!!
使用上面得到的公式,我写了一个 c++代码,可以在这里找到。这段代码使用 PCL 库来加载点云,使用 openCV 来可视化所形成的球面图像的每个维度。为了测试我的实现,我使用了来自 SemanticKitti 的数据集。下面 gif 的上半部分显示了由下半部分显示的点云形成的球形图像的亮度值。
概括地说,由于该数据集中使用的激光雷达是威力登 HDL 64-E,形成的球形图像的尺寸是 64 * 1024* 5。
上半部分是形成的球形图像的强度维度,下半部分是输入点云。(作者:阿尼鲁德·托皮瓦拉)
一些重要观察结果:
1.球形图像的每一行对应于从激光雷达的每个激光器获得的点。这里,图像中最低的一行对应于激光雷达中最低的激光,这是激光雷达附近最近的环,如上面的 gif 所示。
2.形成的球形图像本质上是圆形的,这意味着你将能够观察到当物体从左侧离开图像时,它们可能会在图像的右侧重新出现。
3.图像中的物体可以用人眼识别。意思是,如果你看图像,很容易区分汽车、自行车、建筑物、道路等等。如果它可以被人眼区分,那么在这样的图像上训练的深度网络就有很大的机会能够给出良好的分割和分类结果。
4.此投影中丢失的点是那些与激光雷达中心具有相同俯仰角和偏航角但距离值不同的点。因此,只有连接激光雷达中心和该点的射线上的一个点会在投影图像中被捕获。
结果的清晰视频可以在这里找到。
总之,球面投影是以图像形式表示点云数据的一个非常强大的工具。使用它可以帮助我们将过去十年在图像空间所做的所有研究扩展到点云数据,因此在机器人和自动驾驶汽车领域有着各种各样的应用。
我对这个主题以及计算机视觉和深度学习领域的其他主题的任何建议或头脑风暴会议都持开放态度,所以请随时与我联系!!!
辛辣的浓缩咖啡:热磨,冷捣以获得更好的咖啡
在研磨和准备过程中找到温度技巧,释放美味
多年来,人们已经尝试在研磨咖啡豆之前对其进行预热。他们发现了一些对味道和提取的影响,但不是一个确定的更好的味道。一些人也尝试过冷冻豆子,但是对其中的机制还没有了解。之前的实验都有不足之处,因为它们没有完全捕捉到一个关键变量:温度。
以前的实验没有记录研磨后的温度;他们主要关心的是研磨前的豆子温度。我开始记录研磨前、研磨后和预冲咖啡的温度。我发现在研磨之前预热咖啡豆,如果之后将粉末冷却到室温,会大大提高命中率,这个过程我称之为辛辣研磨。它是辣的,因为它是热的,但不会像辛辣的食物一样留在你的舌头上。我们可以通过冷却冰箱里的粉末来让它变得更有趣。
在这项工作中,我将展示以前的工作和其他有助于这项技术的发现。我相信这很简单,任何人都可以轻松地尝试,我希望他们会找到类似的结果。
以前的工作
关于研磨温度,在商用机器中努力保持研磨机冷却,因为已知热研磨机会对咖啡豆产生影响。研磨机越热,研磨出来的东西就越热。这种变化将导致咖啡师不得不整天调整他们的饮料,以适应温度的变化。
关于提取,已经进行的工作表明,较冷的咖啡渣比较热的咖啡渣提取得更多,并且较冷的咖啡渣比较热的咖啡渣流动得更快。通常,咖啡师会通过调整时间、音量或研磨来达到一致性。
2007 年,一位家庭咖啡师偶然将咖啡豆放在了他温热的咖啡机上,并发现了研磨前预热咖啡豆的影响。他发现浓缩咖啡比没有预热咖啡豆时味道更顺滑。
2019 年, James Hoffman 在观察了 2015 年锦标赛中使用的一种真空罐预热豆子后,尝试了微波加热豆子,认为这一过程可以增加提取量。
2020 年,YouTube 上的Sprometheus对研磨前冷冻或加热的咖啡进行了多次 TDS 和提取测量。然而,他在拍摄之前没有记录地面的温度,因此他混淆了预研磨温度和预拍摄温度这两个变量。他没有使用无底的过滤器,所以不知道不同的温度是否会导致流量和通道的不同。他的实验是一致的,但是没有发现味觉的巨大变化。
2018 年,复合咖啡研究了研磨机温度如何影响提取,虽然他们的结果无法进行统计显著性测试(样本量< 30),但他们的结果很有趣。我不是说较小的尺寸不好,但我不认为它们应该用于零假设检验。作者没有用图表表示他们的数据,但为了方便起见,我在下面列出了:左边是未排序的样本,右边是每个样本的最佳提取进行了比较。考虑到每个样本彼此不相关,比较的最佳方式是最好与最好、第二好与第二好。
即使缺少足够大的样品尺寸,结果也表明在研磨机上没有加热元件的情况下提取率更高。然而,这个故事还有更多;复合咖啡还收集了咖啡渣的温度,因此绘制萃取温度与咖啡渣温度的关系图给出了不同的观点。较低的温度似乎可以提供更好的提取,但他们在酿造前没有冷却粉末,所以不知道哪个变量会导致更多的提取。
此外,复合咖啡研究了冷冻咖啡豆对萃取的影响。他们冷冻咖啡豆,然后磨碎,用几种方法煮出浓缩咖啡。同样,这是一个小样本,但如果我们将它们制成图表并进行分类,那将会非常有趣。
排序后在一个图表上绘制所有样本表明,冷冻对提取有轻微的好处,但不清楚它是否真的有统计学意义或只是一个暂时现象。
绩效指标
我使用了两个指标来评估过滤器之间的差异:最终得分和咖啡萃取。
最终得分是 7 个指标(强烈、浓郁、糖浆、甜味、酸味、苦味和余味)记分卡的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难确定。
使用折射仪测量总溶解固体量(TDS ),该数值与咖啡的输出重量和输入重量相结合,用于确定提取到杯中的咖啡的百分比。
地面温度的初步调查结果
换了一种新的烤肉后,我发现了冷却研磨的窍门。我磨了 90g 咖啡,立马拉了一个镜头,也没那么爽。提取有相当多的通道和喷雾。出于某种原因,我测量了地面的温度,因为我读到过地面的温度。我拍摄的下一张照片非常好,但唯一的差异是 2.3 摄氏度。第一张照片是在 26 摄氏度,第二张是在 23.7 摄氏度,因此我开始记录拍摄前的地面温度和拍摄前的温度。
上午对下午
我很好奇地面温度是否对味道有影响。查看过去一年的所有数据,我没有体温,但我有一天中时间的记录。所以我拿着恒机咖啡、烘焙咖啡和断续(或普通)浓缩咖啡,对比了上午和下午最好的照片。还涉及到其他变量,但这为理论提供了一个有趣的窗口,即下午的地面比早上更温暖,因此拍摄也不会提取。在过去一年的大部分镜头中,我的研磨和酝酿之间有一段时间让研磨物冷却。
至少根据我的数据,我下午的投篮更好。我怀疑这是由于温度差异,但变量没有被跟踪,所以它是未知的。
实验
我计划做这个咖啡豆加热实验已经有一段时间了,有了合适的避难所,我有时间和耐心,因为我知道测试会很长。我对新测试的疑问总是这样的技术是否会改善拍摄,是否会改善我最好的拍摄,即断奏咖啡拍摄。
辣磨:微波至 60C 左右,立即研磨,静置至室温。我这样做是没有计划的。我通常会研磨咖啡,然后过一段时间再冲泡,因为通常我会筛滤咖啡来制作一个断续的镜头。我所有的咖啡渣都储存在密封的容器里,我没有发现用这种方式研磨会降低质量,尽管这与普通咖啡的想法相反。我没有足够大的数据集来知道预热咖啡豆的最佳温度。
我叫它辣磨是因为和辣一样,刚开始是辣的,放在柜台上慢慢凉下来。目的是不使用磨床上的热磨粒。
加热豆类预研磨
关于加热豆,以前的工作没有分开温度,所以我有。我用微波炉将咖啡豆加热到 60 到 90 度。然后我用研磨机研磨它们,我让咖啡豆在密封的罐子里冷却到室温。我用了一辆金快车来拉镜头。
此外,我测量了拉后的温度,并在拉后四分钟喝了酒。我在喝酒前搅拌一下,以确保没有东西沉淀下来。我发现等几分钟让饮料冷却会改善味道,在这些实验完成后,我会让饮料冷却到相同的温度,而不是设定的时间。
为了准备拍摄,我做了一个的断奏浓缩咖啡镜头,中间有一个纸过滤器。我用纸过滤器(PFF)在精细层和粗糙层之间做了一些断续的浓缩咖啡照片。我知道这些镜头比普通的浓缩咖啡镜头更复杂,但它们都比普通镜头好。这种温度处理减少了断续捣实浓缩咖啡和断续浓缩咖啡之间的味道差异。
关于准备的最后一点,我没有把便携式过滤器放入机器,直到我拉起镜头之前,这样机器的温度将在提取之前最低限度地提高咖啡渣的温度。
我目前的数据集涵盖了三次烘烤,我发现味道有了很大的改善。然而,我没有显示统计显著性所需的样本数量,因为我只有不到 30 个。似乎并不依赖于投入产出比。
从提取上来说,更高的提取和辣磨似乎没有什么联系。两种分布都是相互混合的。对于输出与输入的比率,提取已经非常高了。对于更高的比率,还有第二组提取数字,这是因为我完成了第一次 1:1 拍摄,然后我加权并测量第二位出来的 TDS。然后,我计算了 3:1 的比例拍摄,因为许多人拉更长的镜头。
因为我在记录温度,所以我观察了消费时的拍摄温度,以及这个变量是否对我的味觉体验有影响。至少对于这个小样本来说,温度与味道没有关联。即使被烘焙分解,味道和饮料温度之间似乎也没有明显的联系。
R1 =烤 1,R2 =烤 2,R3 =烤 3
辣味分布
我定期筛选咖啡来制作不连续的浓缩咖啡,通过筛选,我可以获得完整颗粒尺寸分布的小样本。中档有所改变,更多的研磨料留在了粗档。通常我一次筛 45 到 60 克,速度是 3g/分钟(重量除以总筛时间)。
研磨前预热咖啡豆只是改变了颗粒分布还是做了更多的事情?如果我们从加热过的咖啡豆中取出过筛后的粉末,然后将它们混合在一起,形成和原来未加热的咖啡豆一样的分布,会怎么样呢?如果弹丸味道类似于未加热的豆丸,该测试将表明加热豆仅改变颗粒分布,而没有其他变化。
我发现不管颗粒分布如何,味道都是一样的,这意味着加热不仅仅是不同的地面分布。这不是一个决定性的测试,但结果不是我所期望的。我想知道,不管怎样,仅仅用同样的研磨筛选和改造一个镜头是否会给出一个更好的镜头。筛选和加热是两个变量,在下面的小样本中,我不清楚哪一个导致了味道的改善。
这里主要的洞穴是:
- 每个变体只有 2 个样品。
- 仅使用了三个筛子,并且粉末分布比这更复杂。然而,其他研究表明,当涉及热量时,颗粒分布的主要变化是从 400 微米到 500 微米的颗粒向更粗的颗粒转移。我在上面看到过类似的。
克里斯蒂安·克拉特 2015 演示:https://speakerd . S3 . Amazon AWS . com/presentations/e 0019999d 9224146 BF 3 f 9 f 9 DFD 483679/BC15 _ CK . pdf
冷冻豆子
我把一些豆子冷冻到零下 17 度,然后把它们从冰箱里直接磨碎。研磨后的温度为 26 摄氏度(当时的室温为 23 摄氏度),因此研磨机在研磨过程中对它们进行了预热。我发现味道并不比基线好,也没有提取更高。然而,一个奇怪的发现是,如果我在拍摄前在冰箱里冷却咖啡渣,味道会有所改善。
特辣:热豆,冷磨
那么,为什么不用热的豆子研磨,用冷的地面冲泡呢?我开始用普通温度的咖啡豆研磨,我发现冷却咖啡豆可以改善味道。以下是我遵循的步骤:
- 用微波炉将咖啡加热到 60 度到 90 度之间(对于 80 克左右的咖啡豆,这是在微波炉上加热 1 分钟)。
- 立即研磨(研磨后的温度为 36℃)。
- 将粉末和过滤器放入冰箱的密封容器中。
- 让我们冷静一两个小时。人们可以用冰箱来加速这个过程。
- 启动浓缩咖啡机。
- 取出研磨物,准备好一杯咖啡(普通咖啡、不连续浓缩咖啡、不连续浓缩咖啡,有或没有纸质过滤器(PFF))。
- 将准备好的篮子放回冰箱,直到机器准备好(这反映了我使用没有温度控制的 Kim Express)。
- 开枪吧。
我注意到味道有所改善。提取没有太大的变化。提取似乎是最大限度的,但一些不同的东西正在被提取。也许咖啡中不好的部分没有被提取出来,更多好的部分被提取出来,我不知道。按化合物对杯子里的东西进行分解将有助于回答这个问题,但我没有气体色谱仪或光谱仪。
我的样本大小对于我的数据需求来说不够大,但是我觉得我正在推动可能的边界。回顾过去的工作,它们都是足够简单的实验,但轻微的调整,如跟踪地面温度,似乎是发现惊人的浓缩咖啡的关键调整。
我喜欢辣磨的原因是,任何有微波炉和冰箱的人都可以相对轻松地尝试一下。所以我希望听到任何尝试一些辣磨的人。
如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。
我的进一步阅读:
脉冲神经网络
是什么让这些生物现实神经元对计算感兴趣?
在硬件神经形态计算中,脉冲神经网络是最广泛采用的脑启发计算模型。然而,它们在软件人工神经网络中没有遇到很大的兴趣,所述软件人工神经网络使用以单一、静态和连续值激活为特征的神经元。是什么让这些生物现实神经元对计算感兴趣?
脉冲神经网络(SNN)首先出现在计算神经科学中,作为模拟生物神经元行为的一种尝试。这导致了泄漏积分点火(LIF)模型,将神经元活动描述为接收到的尖峰电压的积分和对环境的微弱耗散(泄漏)。当它的电压达到一个阈值时,神经元会自己发出一个尖峰信号。随着大脑的进一步启发,神经元的输入和输出可以被编码为它接收和发出的尖峰脉冲的时间或速率。这种类型的信息编码对错误非常鲁棒,因为检测不到一两个尖峰不会导致平均尖峰率的显著错误。
尽管他们已经在那里呆了一段时间,但 SNN 并没有在深度学习社区中遇到很大的兴趣。这最初是由于缺乏有效的训练算法来进行监督学习。事实上,为了应用通常使用的学习算法,例如具有反向传播的梯度下降,需要为神经元输出定义连续值的可微分变量(尖峰不是)。虽然这可以通过计算尖峰到达时间或其速率来实现,但这增加了计算复杂性,从而使它们在深度神经网络中的实现不太吸引人。
另一方面,脉冲神经元广泛用于神经形态计算,其中 SNN 已经使用电子和光学系统实现。神经形态计算包括在硬件中构建神经网络,其中物理设备神经元通过物理设备突触连接。神经形态计算的主要动机是由分布式架构提供的能量效率,该架构避免了存储器和 CPU 之间的能量贪婪的数据洗牌。尖峰神经元的使用方向相同,并促使 IBM (TrueNorth)、Intel (Loihi)和清华天极(Tsinghua Tianjic)建造了第一台由数百万个尖峰神经元组成的神经形态计算机。
脉冲神经网络的优势
脉冲神经网络之所以有趣,有几个原因。首先,由于速率编码对噪声非常鲁棒,因此可以使用非常弱的信号来传输信息。第二,他们为无监督学习带来新的学习算法。事实上,尖峰神经元允许生物启发的局部学习规则的实施,如赫比学习和尖峰时间相关可塑性 (STDP)。如果突触连接的两个神经元的活动似乎相关,这些学习规则就会恢复到增强突触的权重,否则就会降低权重。因此,它允许网络实时学习和自我学习。使用电子神经形态硬件的无监督学习的首次演示可以追溯到 2012 年,获得了 MNIST 数据库的最先进的识别率[1]。最近,使用全光学神经形态平台实现了无监督学习,证明了对简单模式的识别,从而证实了尖峰神经元的兴趣[2]。
尖峰时间相关可塑性学习规则。如果突触后神经元(紫色)在接收到来自突触前神经元(红色)的锋电位后出现锋电位,那么这些事件之间很可能存在因果关系,它们之间的突触(红紫色)得到加强。相反,如果突触前神经元的锋电位(绿色)在突触后神经元的锋电位之后到达,则突触(绿色-紫色)权重降低。(自己的工作)
最后,由于他们使用的时空信息编码,脉冲神经网络为利用网络动力学进行学习提供了可能性。例如,脉冲串的同步允许从同步模式中解码网络输出。这种动态现象存在于大脑中,并允许它用较少数量的神经元进行计算。使用同步的高效学习的首次演示已经在使用自旋电子神经元**【3】的神经形态计算中得到演示,从而证明了人工神经网络的动态神经元模型的重要性。**
神经形态平台现在面临着扩大规模的挑战。他们将不得不应对设备的可变性,同时保持设备的紧凑性和低能耗。
[1] D. Querlioz 等人,结合无监督和有监督学习方法的具有纳米尺度忆阻设备的生物激励网络, *IEEE/ACM 纳米尺度架构国际研讨会,*203–210(2012)。
[2] J. Feldmann 等,具有自学习能力的全光脉冲神经突触网络。性质, 569 ,208–215(2019)。
[3] M. Romera,P. Talatchian 等人,使用四个耦合的自旋扭矩纳米振荡器进行元音识别。性质, 563 ,230–234(2018)。
流学习场景中的脉冲神经网络
在综合概述中合并两个字段
图 1:脉冲神经网络方案[1]
脉冲神经网络已被证明是模拟大脑行为和学习潜力的最成功的方法之一,并利用它们来承担实际的在线学习任务[1]。
流学习
在流学习(SL)中,也称为数据流挖掘或数据流的机器学习,应用程序(如移动电话、传感器网络、工业过程控制和智能用户界面等)以快速流的形式生成大量数据,随着 大数据 和 物联网 时代的到来,这些应用程序获得了特殊的相关性。在这些情况下,算法无法显式访问所有历史数据,因为为此目的所需的存储容量变得无法管理。事实上,数据流既快又大(可能是无限的),所以必须实时从中提取信息,因此有必要以在线方式学习[2]。
此外,这些场景中的一些会产生越来越普遍的非平稳数据流,并且生成数据的过程可能会随着时间而改变,从而产生要建模的模式的改变(概念漂移)。这导致在这些流数据上训练的预测模型变得过时,然后它们不能适应新的分布。因此,迫切需要新的算法来尽可能快地检测和/或适应这些变化,同时保持良好的性能分数[3]。
脉冲神经网络
仿生系统的计算能力越来越受到研究界的关注。尽管对大脑中涉及的信息处理缺乏共识,但生物过程已经成为最近计算模型的参考。如今被认为是第三代人工神经网络,SNNs 的出现是由更好地理解
哺乳动物大脑的信息处理技能的需要推动的,为此,社区致力于开发更复杂的生物学连接主义系统。
图 2:生物神经元及其与人工脉冲神经元的关联[4]
SNNs 包含一组计算单元(神经元),它们通过有向边(神经元之间的突触)相互连接,根据一组指定的规则和方程(神经回路中的信息处理模型)处理信息。对其连通性或动力学的不同选择已经产生了大量不同类型的模型(如 Izhikevich、Hodgkin–Huxley 或 Leaky integrat-and-Fire 模型),这些模型在过去几十年中已经在计算机科学中得到彻底研究,并且由于
深度学习的成功,近年来又重新引起了人们的兴趣[5]。
在将输入数据提供给 SNN 之前,必须将其编码成尖峰序列,以便应用神经元模型。编码部分旨在生成代表输入刺激的尖峰模式,这在神经科学中仍是一个未决问题(这样的尖峰时空模式包含什么信息?神经元用来传递信息的代码是什么?或者其他神经元如何解码信号?).产生棘波序列使得输入刺激的任务相关信息内容被保留变得至关重要。因此,决定什么信息被丢失,什么信息被保留,以及编码有多有效,这些都不是无关紧要的[6]。
在运动控制、基于机器人控制、轨迹跟踪、金融市场决策应用、空间导航和路径规划、决策和行动选择、康复、图像和气味识别、空间导航和环境的精神探索等领域,可以找到 SNNs 的许多实际应用。
用于流学习目的的脉冲神经网络
一些 snn 在第二语言研究社区中特别出名,因为它们具有持续和增量学习的能力,这解释了它们对不稳定和不断发展的环境的持续适应性。此外,他们还展示了捕捉流数据中时间变量之间的时间关联的能力。此外,snn 具有硬件实现的最佳特性,这是一个有趣的主题,因为可以实现在线操作和嵌入式硬件系统,从而扩大了 snn 可以应用的应用数量(例如,定制的 VLSI 芯片)。
数据流可能表现出类标签之间的时间依赖性,这有助于确定输入要素如何随着时间的推移而相互关联。SNNs 利用尖峰信息表示来构建尖峰时间学习规则,这些规则已经显示出捕捉流数据中时间变量之间的时间关联
的能力。在 SL [8]中使用一些 snn(例如,进化的 snn[7])允许非常快速的实时性,并降低了学习过程的计算复杂度,这是因为其局部性非常适合并行实现。就适应漂移而言,如果在变化的环境中使用,大多数现成的分类模型需要重新训练,并且不能适当地缩放。一些 snn 可以克服这一缺点,例如,eSNNs 的进化性质(基于相似神经元的合并过程)使得在数据可用时积累知识成为可能,而不需要存储和
用过去的样本重新训练模型。
工具
对于 SL :
- MOA :可能是用于这些目的的最流行的开源 Java 框架。
- Scikit-Multiflow :受 MOA 启发,用 Python 实现,包含一系列机器学习算法、数据集、工具和用于 SL 评估的指标。
- Scikit-Learn :虽然它主要专注于批量学习,但这个框架也为研究人员提供了一些 SL 方法(多项式朴素贝叶斯、感知器、随机梯度下降分类器、被动积极分类器等)。
- Spark streaming:Apache 项目,致力于构建可伸缩的容错流应用程序。
- 其他兴趣:弗林克,风暴,梁,萨姆扎,萨摩亚等。
对于 SNNs :
- Brian :这是一个针对 SNNs 的开源 Python 模拟器
- Cypress : ut 是一个 C++仿真环境,可以对 SNNs 进行高效的
离散事件仿真。特别推荐用于涉及具有复杂解剖和
生物物理特性的细胞的
模拟。 - Nest :这是一个模拟环境(C++,Python,Cython ),最适合关注神经系统的动态、大小和结构的模型,而不是关注单个神经元的详细形态和生物物理
属性 - PyNN :神经元
网络模型的模拟器无关规范。Python 实现。 - 其他兴趣:Neuron,NeuCube,PCSIM,ANNarchy。我们还可以在 SpiNNaker 和 BrainScaleS 中找到硬件规格。
结论
由于基于流数据的大量实际应用,特别是在数据受到非平稳事件影响的场景中,引发了所谓的概念漂移,因此 SL 是研究界的一个非常热门的话题。SNNs 被认为是第三代神经网络,并且已经表明它们是模拟大脑行为和学习潜力的最成功的方法之一,允许对大型网络进行非常快速的实时模拟,并且计算成本低。在漂移检测[9]和漂移适应[8]情况下,它们也表现出非常好的行为,这通常出现在 SL 场景中。所有这些让我们考虑这两个领域的一个非常有趣的交集。尽管如此,在这两个领域都必须取得很大进展,以应对各自的公开挑战,但我们应该意识到融合 SL 和 snn 的重要性,以便用这些生物启发系统的计算能力解决实际问题。
承认
我要感谢研究团队的其他成员(TECNALIA 的 Javier Del Ser、巴黎电信和怀卡托大学的 Albert Bifet 以及奥克兰理工大学的 Nikola Kasabov)。
参考
[1] Lobo,J. L .,Del Ser,j .,Bifet,a .,& Kasabov,N. (2020)。脉冲神经网络和在线学习:概述和展望。神经网络,121,88–100。
[2] 输,v,汉默,b .,&沃辛,H. (2018)。增量在线学习:最新算法的回顾和比较。神经计算,275,1261–1274。
[3] 陆,j,刘,a,董,f,顾,f,伽马,j,&张,G. (2018)。概念漂移下的学习:一个综述。IEEE 知识与数据工程汇刊。
[4]郭士纳,w .,&Kistler,W. M. (2002 年)。脉冲神经元模型:单个神经元,群体,可塑性。剑桥大学出版社。
[5] 塔瓦纳伊,a .、古德拉蒂,m .、赫拉德皮谢,S. R .、马斯克利尔,t .、&迈达,A. (2018)。脉冲神经网络中的深度学习。神经网络。
[6] Petro,b .,Kasabov,n .&Kiss,R. M. (2019)。脉冲神经网络时间脉冲编码方法的选择和优化。神经网络和学习系统汇刊。
[7]施里布,s .,&n .卡萨博夫(2013 年)。进化中的脉冲神经网络–综述。进化的系统,4(2),87–98。
[8] Lobo,J. L .,laa,I .,Del Ser,j .,Bilbao,M. N .,& Kasabov,N. (2018)。用于漂移数据流在线学习的进化脉冲神经网络。神经网络,108,1–19。
[9] Lobo,J. L .,Del Ser,j .,laa,I .,Bilbao,M. N .,&n . Kasabov .(2018 年 10 月)。基于进化脉冲神经网络的非平稳数据流漂移检测。智能和分布式计算国际研讨会(第 82-94 页)。斯普林格,查姆。
注意
本文基于 2020 年发表在神经网络*期刊上的科学手稿。可登陆https://www . science direct . com/science/article/pii/s 0893608019302655获取。
新冠肺炎的无自旋数据
在一个对健康和经济都有深远影响的疫情,获取及时、可理解的数据应该是普遍的。
总结:您有权获得可理解的数据
关于新冠肺炎的数据并不缺乏。但呈现的通常是旋转第一,数据第二。这在任何时候都没有用,尤其是在疫情时期,当赌注如此之高时,这尤其令人沮丧。
对于与您最相关的数据,您知道您所在的州在抗击新冠肺炎方面做得有多好吗?各州在提供给居民的数据和提供数据的清晰程度上有很大差异。
我认为你有权知道——用你能理解的话来说——你的国家在抗击新冠肺炎的战斗中做得有多好。你也有权知道你的国家在做什么。
自二月份以来,我一直在参加一个数据科学讨论组,该讨论组研究了新冠肺炎数据的每个实际方面。该小组的任务是深入理解我们看到的数据。我们小心翼翼地避免政治讨论,因为我们首先寻求不带偏见地理解数据。每个成员都可以自由地得出他们自己的政治结论——但不是在我们的讨论组里。
为了让任何想要的人都可以获得数据(在我们小组讨论的大力支持下),我为每个州创建了新冠肺炎开放准备评估。这是我所在州的一个例子。
图 1 —华盛顿州的开放就绪性评估
这些开放就绪性评估面向 50 个州和哥伦比亚特区,每周更新 2 到 3 次。你可以在我的新冠肺炎信息中心看到他们。
我们小组对新冠肺炎的数据得出了一些结论。
累积图几乎毫无价值
显示阳性检测和死亡累计总数的图表,像这样的,除了震惊值之外,没有什么价值。
图 2 —累积阳性测试的典型图表。图片来自 Buzzfeed 新闻。
像这样的图表只是说阳性测试或死亡的数量随着时间的推移而增加。它没有描述情况是变好了还是变坏了。很难看出曲线的轨迹是否在变化。当我研究一个图表时,我会想,“这个图表向我暗示了什么问题?”对于这种类型的图表,答案是“没有”
热图也好不到哪里去
约翰霍普金斯大学提供了宝贵的服务,使新冠肺炎的数据随时可用。但是像无处不在的 JHU·新冠肺炎仪表盘这样的图像并不能提供太多信息。
图 3——JHU 无处不在的阳性检测热图。图片来自约翰·霍普金斯大学系统科学与工程中心。
如果整个地图不是红色的,它可能会提出这样的问题,“为什么这个地区比那个地区受影响更大?”但是由于每个居住区都完全饱和,这是另一个没有提示任何问题的图表。
像这样的累积图相当于一辆汽车有里程表,但没有速度计。我们不经常需要里程表,但我们经常需要速度计。这些图表和地图提供了过去发生的事情的历史,但对现在发生的事情却鲜有说明。
增量(每日、每周)图更能提供信息
显示增量数据和趋势的图表更有意义,即显示每日或每周测试或死亡的图表。图 4 中的图表显示了每天的测试和死亡人数,经过平滑处理以弥补报告中每天的变化。图表清楚地表明,截至 6 月 16 日,阳性检测略有增加,但死亡人数仍在下降。它提出了这样一个问题,“为什么当阳性检测增加时,死亡却在减少?”它以一种热图和累积图所不具备的方式讲述了疫情的故事。
图 4 —增量(每日)阳性检测和死亡图表示例
显示一段时间内的增量(变化)的图表提供了大量信息
类似地,考虑如图 5 所示的疫情的故事。此图表跟踪与前 7 天相比,连续 7 天的阳性测试总数。
该图显示,病毒在 4 月初达到一个明显的拐点,在 4 月中旬迅速下降,此后经历了一系列起伏。从图 4 的增量图中不容易看出这个故事,从图 2 或图 3 的图像中也不可能看出。
图 5 —显示阳性测试趋势的图表示例
底线是增量数据和趋势数据比累积数据提供更多的信息。
基于人均数字的图表信息丰富
我们的数据科学小组还了解到,人均数字通常比总数更有用。对总数的共同关注意味着关于人口最多的州如纽约和德克萨斯的报道占据了新闻周期。但是当你检查人均数字时,你会看到各州表现的不同画面。
考虑图 6 中的图表,它显示了各州阳性测试的趋势。
图 6 —阳性测试的州级趋势数据
带有州缩写的标记显示了过去 7 天每个州每 1,000 名居民中阳性检测的数量。实线表示 7 天前的状态,透明线表示 7 天前的状态。
与 JHU 热图不同的是,该图可以方便地比较各州目前的状况,以及它们随时间变化的趋势。这张图表引发了许多问题:“哪些州正在恶化,哪些州正在好转?哪些州的变化最大?有没有什么模式可以说明哪些变得越来越差,哪些变得越来越好?”
目前,新闻报道强调得克萨斯州创造了每日新冠肺炎病例的记录。但上面的图表清楚地表明,最应该担心的州是亚利桑那州、阿肯色州和阿拉巴马州,其次是路易斯安那州和南卡罗来纳州。总数不能传达这一信息;人均数字确实如此。
动画可以提供特别多的信息
动画可以用静态图像无法做到的方式突出显示随时间的变化。上图的动画版本提供了对疾病传播的额外了解。
图 7 —阳性测试的动态状态级趋势数据
你可以看到这种疾病在华盛顿和密歇根慢慢开始。然后看到它在纽约及其周围的东北部各州强劲起飞。你可以看到,整个 4 月,病毒活动集中在东北部,但到了 5 月中旬和 6 月,病毒在全国各地显著下降。随后,在 6 月初,当早先遭受疫情的东北部各州将病毒控制住的时候,几个南部州却出现了疫情。目前,受影响最大的州在南部。
当数据被很好地呈现时,它可以提供令人难以置信的信息。
我的背景和数据来源
我的个人背景是,20 年来我一直专注于理解软件开发的数据分析,包括质量、生产率和评估。我从处理噪音数据、坏数据、不确定性和预测中学到的技术都适用于新冠肺炎。
用于创建本文图表的数据可从 Covid 跟踪项目和 JHU 获得。虽然数据很容易访问,但它的原始形式不太容易理解。这就是我创建这些数据展示的原因。
为什么这对我个人很重要
我对新冠肺炎的看法很简单:我想知道事实,这样我才能做出自己的决定。这在华盛顿州很难实现。我对我所在州的数据透明度(或缺乏透明度)的不满促使我向我的华盛顿同胞提供更好的数据,当我这样做时,其他州也很容易这样做。
请到我的新冠肺炎信息中心查看内容,并随时与我在 stevemcc@construx.com 联系。
非常规神经网络的特征提取
机器学习
尺度置换网络代替尺度递减网络
当你谈到任何一种图像分类或一种特征提取方法时,你脑海中浮现的是哪种神经网络?大概是这样的:给一个图像作为大小为 512x512 的输入,得到一个 10x1 的分类器输出。在这两者之间,有卷积和最大池层,它们会慢慢地降低图像分辨率,同时保留重要的特征。
现在,在 **CVPR-2020 期间,**谷歌研究和大脑团队提出了一个非常规的网络——spine net,而不是上面解释的典型神经网络。该网络由尺度置换的中间特征和交叉连接组成,这可能是许多需要特征提取的应用(如对象检测或图像分类)的可能解决方案。
结果
让我展示一下,谷歌不仅从一开始就重新定义了我们构建神经网络的方式,而且还改善了结果。
图一。Pic 鸣谢:SpineNet 研究论文
图一。显示了采用 SpineNet、ResNet-FPN 和 NAS-FPN 作为主干的 RetinaNet 模型(在 COCO 数据集上)的比较。红线代表论文中解释的当前 SpineNet 模型(参数不同),蓝色虚线代表与 SpineNet 模型对应的参数不同的 ResNet 网络。
乍看之下,它显示红色线比蓝色虚线具有更好的 AP(%)和更少的翻牌。头版的这个结果让我第一时间看到了方法。
他们还以表格形式显示了不同数据集的结果,并将它们与 ResNet 模型进行了比较。你可以仔细看看这些,我在这个博客的末尾附上了论文链接。
想法和动机
一般来说,目标检测的一个基本架构如图图 2 所示。
图二。基本编解码网络(自制)
其中,编码器用于提取特征(也可用于图像分类),解码器用于恢复这些特征以提供边界框的定位。编码器和解码器主要通过残差连接(ResNet)来使用不同分辨率的特征来保留重要信息。
这种编码器是一种比例递减网络,类似于在 YOLOv3 、 Faster-RCNN 等中使用的网络。,也就是通常所说的模特的脊梁。 LeCun 等人解释了这种规模缩小的架构设计背后的动机:“可能需要高分辨率来检测特征的存在,而不需要以同样高的精度来确定其确切位置。”
为了在模型变得更深时保留空间信息并促进多尺度特征融合,本文提出了这种尺度置换网络。人们可以用图 3 中的来捕捉这个想法。
图三。来源: SpineNet 研究论文截图
从图 3 开始。,可以观察到传统的神经网络(比例缩小网络)在左侧。右边是一个规模置换网络的例子,各层和连接之间没有特定的顺序。
这种方法可能会产生许多理论和问题,本文试图回答其中的大部分。然而,为了使这篇文章简短扼要,我将把重点放在阅读摘要后想到的前两个问题上。
- 我们如何提出这样的架构或连接?不幸的是,还没有定义好的方法或规则来做到这一点。在论文中,他们使用了神经架构搜索(NAS) 作为一种方法来寻找类似这样不同的可能架构。在过去,许多不同的公司和实验已经展示了 NAS 的使用,但是主要衍生了规模减小的网络。在没有 NAS 的情况下构建这种网络的可能性仍然不清楚,但人们可能会使用他们的最终网络输出(这将在后面显示)。
- 既然没有顺序,输入层的输出分辨率和特征尺寸如何匹配目标层的输入分辨率和特征尺寸? 它们执行特征和空间重采样以匹配模型中目标层的特征和分辨率。从图 4 的可以观察到。对于较小的图像,它们使用最近邻插值进行上采样,而它们使用步长(值为 2)、3×3 卷积进行下采样,以匹配模型的目标层。
图 4。来源: SpineNet 研究论文截图
模型
图五。SpineNet-49,来源: SpineNet 研究论文截图
为了进行公平的比较,他们声称使用相同的 ResNet 架构层,并使用 NAS 来找到完美的置换组合。他们最终架构的一个版本(AP 最高,为 40.8%)如图图 5 所示。此外,如前所示,与原始 ResNet 网络相比,此版本使用的计算参数和触发器更少。
图六。通过块重复增加模型深度(来源: SpineNet 研究论文
为了增加模型深度,如 ResNet-100、ResNet-150,它们重复了相同的网络或顺序地组合网络,分别产生 SpineNet-96 或 SpineNet-143,如图 6 所示。
优势和可能的未来
- 在这种方法的帮助下,可以创建一个更深的网络,可以增加或减少中间特征图的比例,而不会丢失空间信息。
- 特征地图之间的连接应该能够跨越特征比例,从而有助于保留不同比例或分辨率的特征信息。
- 它显示了以不同顺序连接层的可能性,这可能是研究和实验的新方向的开端。
可能的缺点
- 该网络目前的一个缺点是,它是在 NAS 的帮助下建立的。由于不同连接背后的逻辑仍然不清楚,我们仍然不确定如何自己创建另一个类似的置换网络。
- 虽然在论文中,他们已经表明它在对象检测和图像分类应用的情况下增强了性能。我们需要通过对不同网络的更多实验进行比较来确认 SpineNet-49 在其他情况下的表现。
希望这为您提供了这种有趣方法的一个很好的概述。如果您有任何疑问或想与我进一步讨论,请通过 LinkedIn 联系我。
你也可以在这里 访问全文 。
参考文献
- 杜先智-林逸, SpineNet:用于识别和定位的学习标度-置换骨干网,CVPR 2020
- 约瑟夫·雷德蒙,阿里·法尔哈迪,约洛夫 3:增量改进,CVPR 2018
- Ren,s .,He,k .,Girshick,R.B .,,Sun,J. (2015),更快的 R-CNN:使用区域提议网络实现实时目标检测, IEEE 模式分析和机器智能汇刊,39 ,1137–1149。
- Yann LeCun,Bernhard Boser,易小轩·登克,Donnie Henderson,Richard E Howard,Wayne Hubbard,和 Lawrence D Jackel,应用于手写邮政编码识别的反向传播,神经计算,1989
使用 Terraform 在 AWS 中将 Jupyter 笔记本电脑升级为 ECS 服务
我们团队中的数据科学家需要经常运行耗时的 Python 脚本。根据任务的重复,我们决定是否将它 Dockerize 并在 AWS 上运行它。例如,如果一个脚本需要运行多次,我们会努力重写/重构代码,并将其封装到一个容器中,然后将其部署到 ECR,并将其调度为 Fargate 任务。如果这是一次性的,那么在本地运行脚本有时会更容易,但也有一些额外的缺点。
在本地运行(繁重的)脚本会消耗内存和 CPU,结果是在脚本运行时,您无法真正做其他对笔记本电脑要求很高的事情。我们长期使用的一个解决方案是启动 EC2 实例并在这些实例上运行脚本。在我看来,这不像是一个可维护的解决方案,但它是可行的,我们没有任何其他解决方案。
Jupyter 笔记本
团队大量使用 Jupyter 笔记本(本地)。有 Docker 容器可用,像 jupyter/scipy-notebook ,预装了很多依赖项,比如 pandas 和 scikit-learn。我们想出的一个主意是,基于该图像在 AWS 上轻松地旋转 Docker 容器,然后团队成员可以使用它。
因此,我们希望能够在没有太多麻烦的情况下在云中运行 Jupyter 笔记本,如果可能的话,甚至为每个人创建一个单独的实例,这样依赖关系、资源和文件就不会共享或混淆。笔记本应该或不应该与其他 AWS 资源交互。
我偶然发现了 jupyterhub Git 仓库的 wiki,在那里我找到了一个关于产卵者的页面。有一个 FargateSpawner ,但是说实话,我错过了让它正常工作的文档。
【2020 年 6 月 9 日更新:你可能也会对我最近发布的一篇关于旋转 Polynote 笔记本的新文章感兴趣,这篇文章解决了我在 Jupyter 上遇到的一些问题。
[## 在 AWS Fargate 上使用 Terraform 进行基本身份验证的主机 Polynote 笔记本
本文将帮助您使用 Terraform 在 ECS 上轻松部署安全的 Polynote 环境。
towardsdatascience.com](/host-polynote-notebooks-with-basic-authentication-on-aws-fargate-with-terraform-65d4ff3ba730)
将(行星)地球化(以适合人类居住)
Terraform 是一个安全有效地构建、更改和版本控制基础设施的工具。Terraform 可以管理现有的和受欢迎的服务提供商以及定制的内部解决方案。
— 地形
在过去的几个月里,我们对地形做了很多实验。我们心中有一个理想的情况,我们所有的资源和基础设施都通过 Terraform 以代码的形式建立和维护,但这还有很长的路要走。虽然它给了我们面对的问题一个新的视角。在对 Terraform 文件进行了一两个小时的工作后,我得到了一个可行的解决方案,目前正在我们的团队中进行测试!
旋转笔记本的地形脚本
我已经建立了一个 Git 存储库来共享我创建的脚本。你可以在这里找到 Git 库,我会一路解释。在本文中,我不会在一个代码片段中提供整个 Terraform 脚本,为此,我想参考 Git 存储库。我将把脚本分成几块,并提供每个片段的信息。
先决条件
这需要一些先决条件(参考 main.tf 脚本中的数据块)。我们已经在 AWS 中设置了以下服务:
- ECS 集群
- 应用程序负载平衡器
- Route53 内的托管区域和域
如果您没有这些东西,您可以选择通过 Terraform 来设置它们(我肯定会建议您在其他地方进行设置,在您定义和维护您的基础架构的地方)。但是当然,您也可以在 AWS 控制台中手动设置这些,就像我们之前所做的那样。
我尽可能地使用了变量。这是因为我们有多个 AWS 环境,我们希望能够在这些不同的环境中轻松运行笔记本电脑。我们还希望能够调整内存和 CPU,而不必更改 terraform 脚本。我的 vars.tfvars 和 vars.tf 看起来如下:
vars.tfvars (替换所有大写字母并重新访问其他变量值) :
vpc_id = "VPC_ID_HERE"
region = "REGION_HERE"
profile_name ="PROFILE_NAME_HERE"
ecs_cluster_name = "ECS_CLUSTER_NAME_HERE"
loadbalancer_arn = "LOAD_BALANCER_ARN_HERE"
hosted_zone_id = "ROUTE_53_HOSTED_ZONE_HERE"
fargate_subnets = [
"SUBNET_1_HERE",
"SUBNET_2_HERE",
"SUBNET_3_HERE"]
jupyter_docker_tag = "latest" #Update July 2021: change this to "dc9744740e12"
cpu = 1024
memory = 2048
domain = "ROUTE_53_DOMAIN_NAME_HERE"
vars.tf
variable "vpc_id" {}
variable "region" {}
variable "profile_name" {}
variable "ecs_cluster_name" {}
variable "loadbalancer_arn" {}
variable "hosted_zone_id" {}
variable "fargate_subnets" {
type = list(string)
}
variable "token" {}
variable "jupyter_docker_tag" {}
variable "memory" {}
variable "cpu" {}
variable "domain" {}
使用这个脚本
首先,如果你还没有安装 Terraform。安装完成后,可以在保存了 main.tf 、 vars.tfvars 和 vars.tf 的文件夹中运行以下命令(运行terraform init
后):
terraform apply -var-file=vars.tfvars
它会要求您提供一个令牌,您可以使用它来访问笔记本,并要求您批准在您的 AWS 云环境中进行更改。几秒钟后,它会输出一个您可以用来访问环境的 url。Docker 映像真正运行并可访问可能需要几分钟时间,所以如果没有立即得到预期的响应,也不用担心。最初几分钟,您可能会收到 HTTP 503 响应。
撕下笔记本
当您使用完 Jupyter 环境后,只需运行下面的命令。提供您在设置环境时使用的相同令牌,不要键入“yes”来批准该命令。所有创建的资源都将被删除。如果您希望以后再次运行 Jupyter 笔记本,可以选择先将其保存在本地计算机上。
terraform destroy -var-file=vars.tfvars
在这里,我将进一步解释存储库中的内容,并将为每个代码片段提供额外的信息,说明脚本实际上是做什么的。
这个脚本是做什么的?
假设你已经有了一些 Terraform 的经验或者愿意自己去查阅,我想告诉你这个脚本在做什么。有了数据块,我们就可以检索关于已经存在的 AWS 资源的信息。正如您在第一个数据块中看到的,我想检索已经存在的 ECS 群集的信息。
data "aws_ecs_cluster" "ecs_cluster" {
cluster_name = var.ecs_cluster_name
}
我正在创建一个随机的字符串,稍后将被几个资源使用。这个随机字符串是这个脚本中的关键元素,它允许多个用户同时启动笔记本电脑。
resource "random_string" "random_string" {
length = 8
special = false
}
我们需要创建一个任务执行角色,该角色具有附加的策略,例如允许我们写入 CloudWatch。AWS 已经提供了该策略(参见下面的data “aws_iam_policy" “amazon_ecs...."
块,但是我们仍然需要一个附加了该策略的角色。
resource "aws_iam_role" "ecs_task_execution_role" {
name = "ecsTaskExecutionRole-jupyter-${random_string.random_string.result}"
assume_role_policy = <<ASSUME_ROLE_POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
ASSUME_ROLE_POLICY
}data "aws_iam_policy" "amazon_ecs_task_execution_role_policy" {
arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}resource "aws_iam_role_policy_attachment" "policy_role_attachment" {
role = aws_iam_role.ecs_task_execution_role.name
policy_arn = data.aws_iam_policy.amazon_ecs_task_execution_role_policy.arn
}
出于日志记录的目的,我创建了一个 CloudWatch 组,当然,你可以随意设置。
resource "aws_cloudwatch_log_group" "jupyter_ecs_log_group" {
name = "/aws/ecs/jupyter-${random_string.random_string.result}"
}
ECS 上的每个 Fargate 或 EC2 服务/任务都需要一个任务定义,定义使用什么 Docker 容器,需要多少 CPU 和内存等等。你可以把它想象成一个蓝图。正如您在下面看到的,我将 jupyter/data science-notebook 指定为图像。我还更改了入口点,因此可以设置自定义令牌,否则它将生成一个随机令牌,不太容易从系统中检索到。
resource "aws_ecs_task_definition" "jupyter_task_definition" {
family = "jupyter-${random_string.random_string.result}"
requires_compatibilities = [
"FARGATE"]
network_mode = "awsvpc"
cpu = var.cpu
memory = var.memory
execution_role_arn = data.aws_iam_role.ecs_task_execution_role.arn
container_definitions = <<TASK_DEFINITION
[
{
"entryPoint": ["start-notebook.sh","--NotebookApp.token='${var.token}'"],
"essential": true,
"image": "registry.hub.docker.com/jupyter/datascience-notebook:${var.jupyter_docker_tag}",
"name": "jupyter-${random_string.random_string.result}",
"portMappings": [
{
"containerPort": 8888,
"hostPort": 8888
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-region": "${var.region}",
"awslogs-group": "${aws_cloudwatch_log_group.jupyter_ecs_log_group.name}",
"awslogs-stream-prefix": "${random_string.random_string.result}"
}
}
}
]
TASK_DEFINITION
}
正如我提到的,我们已经有了一个带有 HTTPS 监听器的负载平衡器,所以我们希望从它那里检索信息,以便以后使用(连同我们的 VPC 的信息)。当然,您也可以使用端口 80,但我的建议是使用端口 443。
data "aws_vpc" "vpc" {
id = var.vpc_id
}
data "aws_lb" "lb" {
arn = var.loadbalancer_arn
}
data "aws_lb_listener" "lb_listener" {
load_balancer_arn = var.loadbalancer_arn
port = 443
}
此设置还需要一个目标组,负载平衡器侦听器规则将指向该目标组。该目标组稍后将在aws_ecs_service
资源块中使用。
resource "aws_lb_target_group" "jupyter_target_group" {
name = "jupyter-${random_string.random_string.result}"
port = 80
protocol = "HTTP"
vpc_id = data.aws_vpc.vpc.id
target_type = "ip"
health_check {
matcher = "200,302"
}
}
我们还需要将容器中的端口 8888 暴露给负载平衡器。我将端口 8888 暴露给连接到负载平衡器的安全组。
resource "aws_security_group" "jupyter_security_group" {
name = "jupyter_${random_string.random_string.result}"
vpc_id = data.aws_vpc.vpc.id
ingress {
description = "Incoming 8888"
from_port = 8888
to_port = 8888
protocol = "tcp"
security_groups = data.aws_lb.lb.security_groups
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [
"0.0.0.0/0"]
}
tags = {
Name = "jupyter_${random_string.random_string.result}"
}
}
有了所有这些资源,我们终于可以定义我们的 ECS 服务了。
resource "aws_ecs_service" "jupyter_service" {
name = "jupyter-${random_string.random_string.result}"
cluster = data.aws_ecs_cluster.ecs_cluster.id
task_definition = aws_ecs_task_definition.jupyter_task_definition.id
desired_count = 1
launch_type = "FARGATE"
network_configuration {
subnets = var.fargate_subnets
security_groups = [
aws_security_group.jupyter_security_group.id]
}
load_balancer {
target_group_arn = aws_lb_target_group.jupyter_target_group.arn
container_name = "jupyter-${random_string.random_string.result}"
container_port = 8888
}
depends_on = [
aws_lb_target_group.jupyter_target_group]
}
然后,在负载平衡器中添加转发规则。假设我们有以下域:company.com
,随机字符串为123
。如果主机头是jupyter-123.company.com
,它将转发到 Jupyter 目标组。【2021 年 7 月更新: field = "host-header"
仅适用于版本 2.41.0 之前的 AWS 提供程序,使用[required_providers](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)
锁定 AWS 提供程序或更新条件块,使其适用于最新版本。
resource "aws_lb_listener_rule" "jupyter_lb_listener_rule" {
listener_arn = data.aws_lb_listener.lb_listener.arn
priority = null
action {
type = "forward"
target_group_arn = aws_lb_target_group.jupyter_target_group.arn
}
condition {
field = "host-header"
values = [
"jupyter-${random_string.random_string.result}.${var.domain}"]
}
depends_on = [
aws_lb_target_group.jupyter_target_group]
}
然后在 Route53 中添加指向负载平衡器的 CNAME。继续前面的例子,CNAME 将是jupyter-123.company.com
,它将指向我们的负载平衡器 url。
resource "aws_route53_record" "jupyter_cname" {
zone_id = var.hosted_zone_id
name = "jupyter-${random_string.random_string.result}.${var.domain}"
type = "CNAME"
records = [
data.aws_lb.lb.dns_name]
ttl = 300
}
现在一切就绪,我们当然想知道如何访问笔记本,因为一些字符串是随机生成的,我们在开始时已经设置了一个令牌。我们可以通过一个输出变量来实现。
output "url" {
value = "${aws_route53_record.jupyter_cname.name}?token=${var.token}"
}
后续步骤
目前,Jupyter 笔记本无法访问其他 AWS 资源。因此,您必须在任务定义中提供一个任务角色。此外,当您想要访问 VPC 中的数据库时,您必须在数据库的安全组中添加入站/入站规则,该规则允许来自附加到 ECS 服务的安全组的传入流量。
状态现在被设置为本地,因此使用此脚本旋转笔记本的人也要负责销毁它们。
问题和反馈
如果您对本文有任何问题或反馈,请随时联系我或留下您的评论。
2021 年 7 月更新
由于 Jupyter docker 图像的版本在发布时并没有固定到本文中的特定版本,所以我在 vars.tfvars 中添加了一个注释。评论中的图片标签是在写这篇文章时 docker 图片的最新版本。当你想使用 docker 镜像的最新版本时:GitHub 用户 mvtango 在我的存储库中创建了一个 pull 请求。据我了解,最新的图片默认使用的是 Jupyter Lab。
精彩的计算机视觉项目使你的照片三维!!!!!
你的照片在和你说话!
作者照片,在通往班夫的路上,2018 年 11 月
作者照片,班夫的 Yoho 国家公园,2018 年 11 月
作者的照片,我在蒙特利尔的合作伙伴,2019 年 8 月
太棒了,对吧?我和你们一样惊讶。这个神奇的项目是由四位伟大的研究人员施孟丽、施、约翰内斯·科普夫和贾在2020 年 IEEE 计算机视觉与模式识别大会(CVPR)上完成的。
想在你的照片上试试吗?如果你对计算机视觉和 CNN 完全没有概念也没关系,只要按照我在下面 设置 部分的步骤运行这个链接中的所有代码就可以了!我建议在 Colab 中设置,因为它需要一定数量的计算机资源来训练,并且 Colab 会为您缓存。
设置:
导入图像代码块
用于图像导入的文件夹
- 运行该代码块之前的所有代码,将所有要制作 3D 的照片拖动到高亮显示的图像文件夹中,然后运行该代码块导入您上传的图像。
- 然后只需运行下面的最后一个代码块:
!python main.py --config argument.yml
根据您的计算机规格和图片属性,每个训练批次需要等待 2-5 分钟。
3.然后你得到结果!
输出结果
您可以在指定区域找到您的结果。它将输出五个输出视觉效果,其中包括由 MiDaS 估计的深度图,修复的 3D 网格,以及在圆周、摆动和缩放运动中的 3D 视频演示。够简单了吧?想知道背后的逻辑就继续看下去吧!
理论:
一台机器如何从一张 2D 的照片中预测出 3D 视图?我的意思是,对于照片中的每个物体,如果你想“看到”它背后的东西,你必须以某种方式想象它是一个人。当人们看到一张照片时,他们不仅只是将它视为一个静态的图像,还会将它感知为一个有生命的 3D 物体,甚至会虚构一个想象的场景或回忆一些记忆。但是机器如何处理如此复杂的概念呢?它能不能“ 想象 ”??
嗯,一台机器无法想象,但它可以“ 学习 ”到“ 想象 ”,或者换句话说,它可以像人类一样处理数据和输出。基本上,机器只是做他们擅长的事情:计算。
通常人工智能学习 RGB-D 图像,其中 D 代表“深度”,以重温 3D 效果。目前,市场上大多数智能手机都有两个摄像头来分别捕捉颜色和深度。但是,没有深度的普通 RGB 图片怎么办?机器预测!通过一些标准的图像预处理步骤,我们可以很容易地找到深度图(a 到 d)
有了预测的深度,机器可以找到深度不连续的地方,然后分类,并分组到不同的颜色部分(e 到 f)。
有了所有的预处理准备,我们将从我们的 2D 照片修复三维视觉。我们正在使用的最重要的工具叫做***【LDI】***
在边缘上,像素由两边通过一个锐降(a)连接。该程序首先将拖放连接切割成绿色和红色区域(b),我们称它们为前景轮廓和背景轮廓,基于背景轮廓或上下文区域©生成一个合成区域,然后合并到模型中。
现在,由于我们已经分离了两个区域(上下文区域和合成区域),科学家使用三个修复代理来完成修复任务:边缘修复网络、颜色修复网络和深度修复网络。你可以查看下面的参考资料,详细了解这些修复网络是如何工作的。
边缘修复网络修复上下文区域和合成区域之间的轮廓,以预测被阻挡的边缘。然后机器使用颜色修复网络和深度修复网络分别想象被遮挡的颜色和深度。在这之后,我们将结果反馈给 LDI 模型,就这样!我们有结果了!
没有进一步的到期,玩模型,重温你的记忆!
参考和资源:
相关项目:
论文和参考文献:
在 Python 中分割重叠的边界框
从问题公式化到创建 PyPI 包,使用来自全球小麦检测 Kaggle 竞赛的数据进行测试,分 5 步完成教程。
在对象检测中,通常使用包围盒目标来识别图像中的对象。这些边界框有时可能会重叠。在一些像 Mask RCNN 的模型中,边界框被直接预测,边界框的重叠不成问题。另一种可能的方法是将边界框转换为遮罩,并使用语义分割模型,如 U-Net 。在这种情况下,如果最后你想分离单独的对象,重叠的遮罩可能是一个问题。
在这个故事中,我将讲述如何用 Python 开发一个算法来分离重叠的边界框,并在它们之间设置边距。我将使用来自全球小麦检测竞赛的数据。
请注意,我并不是说这种方法是小麦检测竞赛的最佳方法。将来,我可能会写另一个关于这个主题的故事。
目录
- 问题定式化
- 写数学
- 用 Python 编写算法代码
- 在现实问题中测试代码
- 用 fastai nbdev 创建一个 Python 包
1.问题定式化
让我们从考虑两个重叠边界框的情况开始。我们想要分开边界框,在它们之间留一些空白,如下图所示。
将两个边界框分开并留有一定边距的示例。图片由作者提供。
定义余量的程序如下:
- 考虑由点 A 和 B 定义的线——每个边界框的质心——我们称之为 AB。
- 然后考虑一条垂直于 A 和 B 之间中点的直线——设它为 ABp。
- 最后,上图中的两条线平行于 ABp,其距离由我们选择的边距值给出。
在第 4 节的后面,我将展示该代码可以很容易地应用于多个相交边界框的情况。
2.写数学
考虑下面的图像和等式,其中粗体符号表示向量。矢量 AB 就是在第一个等式中定义的从 A 到 B 的矢量。然后我们可以考虑一个垂直于 AB 的向量——我称之为ABp——使用第二个等式。最后,盒子 A 的边缘线上的点 M 可以由第三个等式定义。
边缘线的形成。图片由作者提供。
基本原理是:1)你从 A 开始;2)你向 AB 方向移动,但只到了中点的一半;3)你以因子 m 乘以 AB 方向的单位矢量,向同一个方向稍微向后移动;4)你到达的点就是我定义的 m 点。
使用点 M 和矢量 ABp it 直接定义边缘线,我将在下一节展示。
3.用 Python 编写算法代码
下面的函数接收两个边界框,并返回框 a 的切片区域。输入框为形状良好的多边形以及该函数返回的输出。现在让我们一行一行地深入代码。
- 第 1 行:输入是两个包围盒——类型为形状多边形的 box_A 和 box_B 。边距设置框之间的距离应该有多大,而 line_mult 只需要足够高,以保证线条完全穿过多边形。
- 第 3 行:向量 AB ( vec_AB )是用盒子的质心定义的。
- 第 4 行:类似于第 3 行,但垂直向量( vec_ABp )遵循第 2 节中的等式。
- 第 5 行:计算矢量 AB 的范数,因为稍后会用到它。
- 第 6 行:根据第 2 节的等式定义分割点(点 M)。
- 线 7:使用 shapely LineString 类定义线,该类允许定义给定两点的线。请注意,这些点也是形状优美的几何图形。因此,该线被定义为从点 M 减去矢量 ABp 的倍数直到点 M 加上矢量 ABp 的倍数。
- 第 8 行:一个 shapely 效用函数被用来将多边形一分为二。
- 第 10 行:对于第 8 行获得的每个多边形,检查是否包含中心点 a。
- 第 11–15 行:在这几行中,我分离了包含中心点的多边形(与此目的相关的一个),并将其与另一个多边形(不包含中心点)和用于切片的线一起返回。额外返回的对象只是以防将来的应用程序会用到它。
4.在现实问题中测试代码
第 3 节中定义的代码仅适用于两个边界框。为了将它应用于几个边界框,我定义了下面的代码,现在我将简单解释一下。
- intersection _ list-一个函数计算列表中所有多边形的交集。
- slice_all —该函数接收包含图像所有边界框的地理数据框(见下表)作为输入,并为每个边界框调用 slice_one 。 slice_one 简单地对给定的 box_A 应用切片框功能,并考虑与之相交的所有框。当有几个相交的盒子时,使用 intersection_list 函数获得最终的多边形。
输入地理数据框的示例。图片由作者提供。
slice_all 的结果是一个类似的地理数据框,但带有切片框。下图显示了原始边界框(左)和 slice_all 的结果(右)。如您所见,原始数据中有几个重叠区域,但应用刚刚开发的方法后没有重叠区域。
原始边界框(左)和应用所述方法后的结果(右)。图片由作者提供。
5.用 fastai nbdev 创建一个 Python 包
fastai nbdev 可以说是创建 Python 包并将其上传到 PyPI 的最简单、最用户友好的方式。
- 当您开始一个新项目时,请转到 nbdev instructions,并使用该链接为模板创建一个存储库。这会让你很容易开始。
- 然后你应该为你的本地机器克隆这个库,pip install nbdev并在项目目录下运行nbdev _ install _ git _ hooks。
- 现在你可以像往常一样打开 jupyter 笔记本了。 settings.ini 文件包含您需要填写的设置信息,例如项目名称、您的 github 用户名以及您的软件包要求。
- nbdev 模板包括一个 index.ipynb 和一个00 _ core . ipynb。这个索引将是 GitHubreadme . MD文件。
- 然后在 00_core.ipynb 上,你可以像往常一样开发你的代码,但是要记得在你的包 core.py 文件中的单元格顶部添加 #export 注释——这个文件是 nbdev 从笔记本上生成的。你可以在他们的文档 中详细阅读如何使用 nbdev。我强烈推荐!它将改变你编码的方式。
- 准备就绪后,您可以在终端上运行nbdev _ build _ lib和nbdev _ build _ docs。然后,您可以提交您的更改并推送到 github repo。检查回购,看看是否所有测试都通过了。导入外部包时,一个常见的错误是 ModuleNotFoundError。您需要将它们包含在 settings.ini 中的要求下,这样软件包将与所有需要的依赖项一起安装。
- 当一切正常时,你可以通过运行命令 make pypi 将你的包上传到 PyPI 。但是,如果您以前没有这样做过,您需要在 PyPI 中创建一个帐户并设置一个配置文件(详细说明在 nbdev 页面上,这里是)。
就是这样!我的包现在在 PyPI at https://pypi.org/project/splitbbox上,可以 pip 安装了。
结束语
- 生成上面图片的代码可以在这个 Kaggle 内核或者 GitHub 库中找到。
- 如果你对未来关于使用 fastai2 进行全球小麦检测 Kaggle 竞赛的故事感兴趣,请通过突出显示这句话让我知道!
关于我
[## 我的 3 年历程:从零 Python 到深度学习竞赛高手
自从 2017 年开始学习 Python 以来,我一直遵循的道路是成为一名独自参加 Kaggle 比赛的大师…
towardsdatascience.com](/my-3-year-journey-from-zero-python-to-deep-learning-competition-master-6605c188eec7)
感谢阅读!祝您愉快!
分割数据集
简要说明如何使用 sklearn 对数据集进行训练测试分割
作者图片
为了训练任何机器学习模型,无论使用哪种类型的数据集,都必须将数据集分为训练数据和测试数据。因此,让我们看看如何做到这一点?
在这里,我将使用 iris 数据集,并使用 sklearn 的“train_test_split”库对其进行分割
from sklearn.model_selection import train_test_splitfrom sklearn.datasets import load_iris
然后我将虹膜数据集加载到一个变量中。
iris = load_iris()
然后我用它将数据和目标值存储到两个独立的变量中。
x, y = iris.data, iris.target
在这里,我使用“train_test_split”以 80:20 的比例分割数据,即 80%的数据将用于训练模型,而 20%的数据将用于测试由此构建的模型。
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=123)
正如您在这里看到的,我在“train_test_split”中传递了以下参数:
- 我们之前定义的 x 和 y
- test_size:设置为 0.2,因此定义测试大小为数据集的 20%
- random_state:它控制在应用分割之前应用于数据的混洗。将 random_state 设置为固定值将保证每次运行代码时生成相同的随机数序列。
当分割数据集时,有两个相互竞争的问题:
-如果你有较少的训练数据,你的参数估计有较大的方差。
-如果您的测试数据较少,您的性能统计就会有较大的差异。
数据应该这样划分,两者都不要太高,这更取决于你拥有的数据量。如果你的数据太小,那么没有分割会给你满意的方差,所以你必须做交叉验证,但是如果你的数据很大,那么你是选择 80:20 分割还是 90:10 分割真的没有关系(实际上你可以选择使用较少的训练数据,否则,它可能需要更多的计算)。
Splunk 和 SQL,终于走到一起了?
photo-1501743411739-de 52 ea 0 ce 6a 0
过去几年,我一直参与 Splunk 工程。我觉得这有点讽刺,因为我已经很久没有用 Splunk 了。出于各种原因,我从来都不是 Splunk 查询语言(SPL)的粉丝,其中一个主要原因是我不想花时间去学习一种专有语言,这种语言就像 1974 年的福特 Pinto 一样优雅。多年来,我参与了几个项目,涉及对 Splunk 中的数据进行机器学习。这是一个重大的挑战。虽然 Splunk 确实有一个机器学习工具包(MLTK),它基本上是 scikit-learn 的包装器,但在 SPL 进行功能工程是一场噩梦。
那么,如何在 Splunk 中进行机器学习呢?
你不知道。
不,真的 Splunk 怎么做机器学习?
好吧…人们实际上在 Splunk 中进行机器学习,但我认为这不是最好的方法,原因有几个。我在 Splunk 中看到的大多数 ML 工作都涉及到从 Splunk 中获取数据。在这种情况下,我向任何试图在 Splunk 中进行 ML 的人推荐的第一件事是看看 huntlib(【https://github.com/target/huntlib】)这是一个 python 模块,有助于从 Splunk 中获取数据。Huntlib 使这变得相对容易,你可以将 Splunk 中的数据直接放入 Pandas 数据框架中。但是,你仍然必须知道 SPL,或者你做一个基本的 SPL 搜索,用 Python 做你所有的数据辩论。还有更好的方法吗?
SQL/Splunk 连接器
我一直在做的一个项目是 Apache Drill 到 Splunk 的连接器,它允许用户使用 ANSI SQL 查询 Splunk。这种方法有几个优点:
- SQL: 面对现实吧。SQL 可能是表达复杂查询的最佳语言之一。自 20 世纪 80 年代以来,它被广泛使用,并在无数系统中实现。从技能的角度来看,学习 SQL 比学习一种可能在几年内过时的专有查询语言更划算。总而言之,SQL 对于定义表来说也是极具表现力和高效的。我的想法是,如果你可以用 SQL 查询 Splunk,这意味着不懂 SQL 的数据科学家现在可以访问 Splunk 中的数据。
- **查询优化:**当您开始使用 Splunk 时,您首先会了解到 Splunk 不会优化查询。这意味着这个任务落在了作为查询作者的您身上。这里的问题是,这需要您了解 Splunk 的实际工作方式。这与大多数为您做这种优化的 SQL 数据库相反。此外,许多 SQL 引擎可以提供如何改进查询的建议。因此,Drill/SQL 连接器将为您执行这些优化,因此您不必学习如何优化 Splunk 查询。
- **外部数据集:**Splunk 的一个大问题是,当您的一些数据在 Splunk 中,而另一些不在时,该怎么办。现在,Splunk 的人会说,“简单…放入 Splunk。问题解决了。”但在企业中,就没这么简单了。在企业中,用户很可能永远没有权限这样做,用户必须让工程团队参与进来,才能将外部数据导入 Splunk。由于 Splunk 按接收的数据量收费,企业不能让用户将随机的、未经验证的数据放入生产系统,因为这会影响预算。这也需要时间。据我观察,企业通常需要数周时间才能将数据源导入 Splunk。借助 Drill 和 SQL,您可以通过简单的 SQL JOIN 语句轻松地将外部数据集与 Splunk 中的数据连接起来。
这一切和机器学习有什么关系?
任何 ML 项目的第一阶段都是收集数据和提取特征。完成后,您就可以研究数据了。Splunk 非常擅长数据探索,但是在我看来,使用 Splunk 提取特征是一场噩梦。也有很多效率低下的地方,但我们会把它留到下次再讲。无论如何,当你把 Splunk/Drill 和 John Omernik 的棒极了的 Jupyter 笔记本集成用于 Drill (我将在以后的博客文章中讨论)时,你可以简单地:
- 在 Jupyter 笔记本单元格中键入 SQL 查询
- 集成将查询钻取和管道您的数据直接进入一个数据框架!
搞定了。你要去比赛了!
Drill/Splunk 连接器如何工作?
在 pull request 中可以获得完整的文档,但是它相当简单。您需要配置 Drill 安装以连接到 Splunk。Splunk 使用端口 8089 进行编程访问,因此该端口必须打开。总之,要配置 Drill,只需导航到存储插件页面,单击添加新插件,将其命名为 splunk,然后粘贴到以下配置中:
{
"type":"splunk",
"username": "admin",
"password": "changeme",
"hostname": "localhost",
"port": 8089,
"earliestTime": "-14d",
"latestTime": "now",
"enabled": false
}
单击提交后,您现在应该能够通过钻取来查询 Splunk。
Drill/Splunk 数据模型
Drill 将 Splunk 索引视为表。Splunk 的访问模式似乎不会限制对目录的访问,但会限制对实际数据的访问。因此,您可能会看到您无权访问的索引的名称。您可以通过SHOW TABLES IN splunk
查询查看可用索引的列表。
apache drill> SHOW TABLES IN splunk;
+--------------+----------------+
| TABLE_SCHEMA | TABLE_NAME |
+--------------+----------------+
| splunk | summary |
| splunk | splunklogger |
| splunk | _thefishbucket |
| splunk | _audit |
| splunk | _internal |
| splunk | _introspection |
| splunk | main |
| splunk. | history |
| splunk | _telemetry |
+--------------+----------------+
9 rows selected (0.304 seconds)
要从 Drill 查询 Splunk,只需使用以下格式:
SELECT <fields> FROM splunk.<index>
Drill 将执行查询,并在一个漂亮干净的表中返回结果!
限制您的查询
当您学习通过 Splunk 的界面查询 Splunk 时,您首先要学习的是绑定您的查询,以便它们查看尽可能最短的时间跨度。当使用 Drill 来查询 Splunk 时,建议执行相同的操作,Drill 提供了两种方法来完成此操作:通过配置和在查询时。
在查询时绑定查询
绑定查询最简单的方法是在 querytime 通过WHERE
子句中的特殊过滤器来完成。有两个特殊的字段,earliestTime
和latestTime
,可以设置它们来绑定查询。如果没有设置它们,查询将被绑定到配置中设置的默认值。
您可以在此处使用 Splunk 文档中指定的任何时间格式:
https://docs . Splunk . com/Documentation/Splunk/8 . 0 . 3/search reference/search time modifiers
因此,如果您想查看过去 15 分钟的数据,可以执行以下查询:
SELECT <fields>
FROM splunk.<index>
WHERE earliestTime='-15m' AND latestTime='now'
查询中设置的变量会覆盖配置中的默认值。
向 Splunk 发送任意 SPL
您可能有一个 Splunk 查询没有映射到该模型,对于这些情况,有一个名为spl
的特殊表,您可以使用它向 Splunk 发送任意 SPL 查询。如果使用该表,必须在spl
过滤器中包含一个查询,如下所示:
SELECT *
FROM splunk.spl
WHERE spl='<your SPL query>'
这在很大程度上是一项正在进行的工作,所以如果你尝试这个,我将欢迎反馈它如何为你工作。文档解释了如何处理来自 Splunk 的嵌套数据等。祝你好运!
原载于 2020 年 7 月 24 日 https://thedataist.com。
剧透警告:康纳·麦格雷戈 vs 牛仔?谁会赢?
应用 Elo 评级系统预测 UFC 246
资料来源:ufc.com
2020 年 1 月 18 日,格斗运动中最大的赛事之一将在 UFC 246 举行。
综合格斗(MMA)历史上最受欢迎的拳手——康纳·麦格雷戈,将与粉丝最喜欢的——“牛仔”唐纳德·塞罗恩进行期待已久的对决。对于拳手、UFC 和下注的粉丝来说,将会有大量的金钱。
谁会赢?
更新:这场战斗的结局符合我们的预测!
观看赛后采访视频。
来源:ufc.com
与其随机下注,不如做一些数据科学的工作来预测赢家。
你准备好了吗?
是时候隆隆作响了!
Elo 评级系统
Elo 评分系统是一种计算零和游戏中玩家相对技能水平的方法。它主要用于国际象棋。但许多人已经在足球、篮球和拼字游戏等其他竞技游戏中应用了相同的算法。
在本文中,我们将使用 Python 基于 Elo 评级来预测这场 UFC 大战的获胜者。
收集数据
根据 Elo 评级系统,我们需要收集过去与 Conor 和 Cowboy 相关的所有打斗数据。我从 sherdog.com 那里搜集了历史资料。
这个过程从第页开始,第页有康纳的战斗史。所有过去与他有关的打斗信息都被收集起来。此外,对于他的每个对手,所有与他们相关的战斗信息都是以类似的方式收集的。
资料来源:sherdog.com
鉴于康纳的一个对手(内特·迪亚兹)曾与牛仔打过仗,这些数据也包括了与牛仔有关的信息。最终我们会有康纳的对手,牛仔的对手,他们对手的对手等等的数据。
虽然 MMA 已经成为一项运动几十年了,但要收集整个数据集需要很长时间。所以当数据达到 36503 架,93778 架的时候我就停止了进程。对于我们的目的来说,这些数据应该足够了。
最后的数据如下所示:
来源:作者
应用 Elo 算法
Elo 算法的细节可以在这里找到。
简而言之,该算法根据每个新的匹配更新战斗机的评级。下面的简单数学公式描述了这一过程:
资料来源:eloratings.net
- 基本参数:K
要调整的最重要的参数是 k。它决定在一场比赛后增加或减少多少评分点。更高的 K 值意味着更不稳定的评级。
举个例子,我们假设两个战士 A 和 b。
战斗机 A 当前等级= 1500
B 战斗机当前等级= 1500
假设他们之间的新一轮比赛以 A 获胜结束。我们需要相应地更新这两个拳手的评分。
当 K = 10 时:
战斗机 A 的新等级= 1500+10 *(1–0.5)= 1505
*战斗机 B 的新等级= 1500+10 (0–0.5)= 1495
当 K = 100 时:
*战斗机 A 的新等级= 1500+100 (1–0.5)= 1550
*战斗机 B 的新等级= 1500+100 (0–0.5)= 1450
我们可以看到,当 K 较大时,当新的信息进来时,战斗机的收视率变化快得多。
- 额外参数:为 MMA 格斗定制
一场 MMA 格斗有不同的结局。打架会以三种方式结束:
- 结束——胜者在时间限制前通过击倒或提交来“结束”败者。
- 一致决定——时限已过。三位评委一致认为获胜者是同一个拳手。
- 分裂决策—时间限制已过。三位评委对获胜者的选择意见不一。占多数的战士获胜。
从胜利者的角度来看,一个完整的决定比一致的决定更令人印象深刻,而一致的决定比分裂的决定更令人印象深刻。
为了整合这些信息,我们在 K 中增加了三个乘数,关系如下:
完成乘数≥一致决策乘数≥分裂决策乘数
这些乘数有助于进一步区分不同战士的评级(基于他们结局的感人程度)。
例如,如果甲在终点击败了乙:
战士 A 的新等级=战士 A 的当前等级+终结乘数 K (1–We)
战士 B 的新等级=战士 B 的当前等级+完成乘数 K (0–We)
这样一来,战斗机 A 的收视率会比其他两种类型的结局上升更多。而战斗机 B 的收视率会比其他两种类型的结局下沉更多。
- 参数选择
首先,我们将参数的可能值范围设置如下:
10 ≤ K ≤ 300
完成乘数≥ 1.0
一致决定乘数= 1.0
分割决策乘数≤ 1.0
使用交叉验证方法测试了三个未决定参数 *(K、结束乘数、分割决定乘数)*的不同组合。
我们发现,就预测准确性而言,最佳值如下:
K = 200*
终点乘数= 1.05
一致决定乘数= 1.0
拆分决策乘数= 0.5
*棒球、足球和象棋等运动的 K 值通常在 10 到 30 之间。K = 200 表明混合武术的收视率波动比其他运动大得多。
既然我们已经完成了“无聊”的部分。我们可以简单地将参数值插入到 Elo 公式中,并用每个新的匹配更新战士的等级。
我们已经准备好看到结果了!
结果
- 根据 Elo,谁是顶级拳手?
根据算法,下面是我们的前 10 名战士:
名字后面的数字是战斗机的唯一标识符。来源:作者
尽管我们的数据包括所有组织的战士。排名前十的拳手都活跃在 UFC。这与 UFC 吸引最优秀的拳手的普遍观点不谋而合。
- 那么谁会赢得这场战斗呢?
现在我们也可以回答我们一开始问的问题了。康纳 vs 牛仔,谁会赢?
下图显示了两种战斗机的 Elo 等级:
来源:作者
尽管牛仔在过去更强大。康纳近年来的评分较高。
截至今天,康纳的收视率为 2791,而牛仔的收视率为 2529。康纳赢的几率是 82%!
来源:giphy.com
玩得开心!
更多金钱和数据科学相关文章来自 Lianne & Justin:
很多人年纪轻轻就有辞掉工作的梦想,活在世上没有经济上的牵挂。怎么…
towardsdatascience.com](/how-much-do-you-need-to-retire-at-age-30-based-on-simulation-424fa9e0922b) [## 买彩票的最佳时机是什么时候?
根据理性(或统计)分析
towardsdatascience.com](/when-is-the-best-time-to-buy-lottery-tickets-7735191b3c76) [## 我将如何在我的狗身上花费 6 万多美元
我以前从未试图给我们的狗贴上价格标签。但是根据简单的分析,我最后会花…
medium.com](https://medium.com/@liannewriting/how-im-going-to-spend-over-60-000-on-my-dog-4860e5d8935c)
熊猫的体育分析
如何计算足球比赛的赔率?这比你想象的要容易。不需要编码技能!
托马斯·塞勒在 Unsplash 上的照片
你有没有想过足球比赛的赔率是如何计算的?那些 2.2 vs 3.1 的赔率是基于什么?我原以为这是一个复杂的过程,但令我惊讶的是,不用写任何代码就可以计算出概率和赔率。我在下面的例子中使用熊猫是因为我精通它,但是你也可以在 Excel 中甚至用计算器做同样的事情。
我写了大量关于熊猫数据分析的文章。看看我的熊猫系列:
从提示和技巧,如何不指南到与大数据分析相关的提示,熊猫文章的精选列表。
medium.com](https://medium.com/@romanorac/pandas-data-analysis-series-b8cec5b38b22)
如何计算概率?
一定数量的目标的概率用泊松分布计算,泊松分布以法国数学家西蒙·丹尼斯·泊松命名。
泊松分布是一种离散概率分布,它表示在固定时间间隔内发生的给定数量的事件的概率,如果这些事件以已知的恒定平均速率发生,并且与自上次事件以来的时间无关。
让我们用通俗的语言来解释这一点。离散概率分布给出了离散事件在 0 和 1 之间的概率,如足球示例中的进球数。一场足球比赛有一个固定的时间间隔(90 分钟的比赛),进球以一个已知的恒定平均速率出现(我们可以计算出预期的进球数量)。一个目标也独立于前一个目标。
下图是泊松分布的概率质量函数(PMF ),显示了预期发生次数为 1、5 和 10 的事件的概率。简单来说,一支平均进 1 球的足球队,有一个:
- 36%的概率没有进球,
- 1 球 36%的概率,
- 18%概率 2 球等。
λ1、5 和 10 的泊松分布。
El Clásico -谁有望获胜?
维也纳·雷耶斯在 Unsplash 上拍摄的照片
让我们来计算一下永远的对手巴塞罗那和皇家马德里之间潜在对决的概率。这场比赛将在圣地亚哥伯纳乌进行,这意味着皇家马德里将在主场作战。
在我们可以使用泊松分布来估计概率之前,我们需要计算每支球队在比赛中可能得分的预期数量。
通过确定球队的进攻实力和防守实力来计算每支球队可能得分的预期目标数。
我根据 2019/2020 赛季西班牙 LaLiga 的在线统计数据组成了数据集。有两个数据集,一个用于主场比赛,一个用于客场比赛,其中:
- p——玩游戏的次数,
- GF——进球数,
- GA——失球数。
拉利加 2019/2020 赛季主场统计。
拉利加 2019/2020 赛季客场数据。
攻击强度
计算进攻强度的第一步,我们计算联赛主客场球队的平均进球数。这是总进球数除以主客场比赛总数。
主场平均进球数:1.50。
平均客场进球数:1.02。
第二步,我们需要确定一支球队的进攻实力有多强。我们计算每支球队的平均进球数,然后除以赛季的平均进球数。
记住这场比赛是在圣地亚哥伯纳乌,所以皇马主场作战,巴塞罗那客场作战。皇马进了 27 个球,打了 13 场主场比赛。Real 的攻击强度是 1.37。
real attack strenght = 27 / 13 / 1.50
巴萨进了 18 个球,打了 13 场客场,所以攻击强度是 1.34。
barca attack strenght = 18 / 13 / 1.02
防御力量
进攻实力重在进球,防守实力重在失球。平均值是从上面的攻击强度简单倒置而来的:
主场平均失球数:1.02 个。
平均失球数:1.50 个。
竞争对手在 13 场主场比赛中对皇家马德里队进了 9 个球。皇马的主场防守强度为 0.67,巴萨的客场防守强度为 0.96。
real defense strenght = 9 / 13 / 1.02
barca defense strenght = 19 / 13 / 1.50
皇马有可能进多少球?
Gif 来自 giphy
把这些数字放在一起,我们可以计算出皇马的预期进球数。我们只是简单地将皇马的主场进攻实力与巴萨的客场防守实力乘以在拉利加主场作战时的平均进球数。
expected goals for real = 1.37 * 0.96 * 1.50
皇马有望进 2.01 球。
巴萨有可能进几个球?
Gif 来自 giphy
使用与上述相同的程序,只是改变家与客场。我们用客场打拉利加时的平均进球数乘以巴萨的客场进攻实力和皇马的主场防守实力。
expected goals for barca = 1.34 * 0.67 * 1.02
巴萨有望进 0.93 球。
使用泊松分布预测结果
泊松分布在线计算器
您可以使用在线计算器计算泊松分布,以确定事件的概率。将巴萨的 平均发生率 设置为 0.93 目标,然后将 发生次数 设置为 0 到 5。我用熊猫来计算多种结果的概率。
下表显示皇马有 26%的机会进 2 球。
上表中的概率是独立的,这意味着我们可以将它们相乘,并计算多个结果的概率。横排的进球是皇马的,横排的是巴萨的。结果 2:0 对皇马有 10%的机会。
计算赔率
为了计算概率,我们需要计算每一个平局的结果(0:0,1:1,等等。)然后将这些概率相加。平局的几率很简单:
平局结果用蓝色标记,真正的胜利用红色标记,巴塞罗那获胜用绿色标记。
odd for draw = 1 / sum( all draw outcomes)
为了计算真实获胜的几率,我们对真实获胜的每一个结果重复这个过程(1:0,2:0,等等。)巴萨也一样。
最终的可能性是:
- 真实胜率:1.6
- 平局:4.85
- 巴萨获胜:6.14
请注意,这些赔率没有博彩保证金。
在你走之前
如果你想自己运行这些例子,你可以下载这个 Jupyter 笔记本。
在 Twitter 上关注我,在那里我定期发布关于数据科学和机器学习的消息。
康特尼·赫格尔在 Unsplash 上拍摄的照片
使用 HuggingFace 的 GPT-2 模块生成体育文章
自然语言处理(NLP)将机器学习的应用扩展到了一个全新的领域。谁会想到统计模型可以应用于我们每天看到的文本,以产生商业见解和预测?在过去的两年里,NLP 经历了前所未有的复兴。
在 NLP 的先进方法中,人们对语言生成模型产生了极大的兴趣。Open AI 的 GPT-2 模型中的自动回归功能使得新的文本序列能够非常接近地代表人类思维的想法、说法和文字。这些基于变压器的神经网络模型显示出在提出令人信服的人类长篇文本方面的前景。
在这篇文章中,我们看看如何使用 HuggingFace 的 GPT-2 语言生成模型来生成体育文章。为了满足这个计算密集型任务,我们将使用来自 Spell.ml MLOps 平台的 GPU 实例。
法术入门
如上所述,语言生成模型在计算上可能变得很昂贵,并且对于具有 CPU 的普通机器来说不可能处理它们。为了解决这个问题,我们使用了 Spell 的 GPU 支持的 Jupyter 笔记本。Spell 是一个强大的机器学习和深度学习的 MLOps 平台。它负责基础设施,从而使开发人员和企业能够专注于简单、快速和有组织地执行他们的机器学习模型。
使用 Spell 进行设置非常简单。只需访问https://spell.ml/并创建一个新账户。Spell 的每个新用户都可以获得 10 美元的免费使用积分。
在本练习中,我们将使用 UCI 机器学习库中的体育文章数据集。它包含 1000 个文本文件,每个文件中都有一篇体育文章。要上传文本文件,请在您的终端或命令提示符窗口中登录到 Spell,并导航到您解压缩文件的父文件夹,然后键入:
spell upload ‘Raw data’
这将把所需的文本文件上传到 Spell 的参考资料部分。在这里了解更多关于上传文件到法术资源的信息。
要打开 Jupyter 笔记本,请登录到拼写 web 控制台,然后单击工作区>创建工作区。
给这个新工作区起一个您自己选择的名字,然后点击 Continue。
在下一个屏幕中,Spell 为您提供了多个选项来定义您想要在其中运行代码的环境。例如,在“机器类型”下,您可以根据您的用途和预算从各种 CPU 和 GPU 选项中进行选择。此外,您可以在设置 Jupyter 之前选择要安装的框架、环境变量和库。
就本项目而言,我们在机器类型下选择“V100 ”;朱庇特名下的笔记本。
在下一个屏幕中,让我们单击“启动服务器”开始。完成后,我们会发现一个 Jupyter 基础架构,类似于我们在本地机器上的基础架构。点击新建> Python3。
语言生成算法概述
让我们从 HuggingFace 安装“变形金刚”并加载“GPT-2”模型。
!pip install -q git+https://github.com/huggingface/transformers.git!pip install -q tensorflow==2.1import tensorflow as tf
from transformers import TFGPT2LMHeadModel, GPT2Tokenizer
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
# add the EOS token as PAD token to avoid warnings
model = TFGPT2LMHeadModel.from_pretrained("gpt2", pad_token_id=tokenizer.eos_token_id)
这两个对象让你使用预先训练的 GPT-2。一般来说,我们利用 GPT-2 或 transformers 的方式是指定一个输入字符串/短语,这基本上是您文章的开头。然后,算法预测下一组单词,使它们与给定的初始字符串一致。
让我们试着理解不同类型的算法,以及 GPT-2 如何能够得出最像人类的文本段落。
先说贪婪搜索算法,这是单词预测的简单化方法之一。基于初始字符串,该算法贪婪地搜索最可能的下一个单词。使用这个新字符串,它基本上是初始字符串加上预测的单词,预测下一个单词。这个过程不断重复,直到我们得到想要的单词数。这种方法的缺点是,在文本的几行/几个单词之后,单词开始重复。这是因为它错过了隐藏在低概率单词后面的高概率单词。
波束搜索通过每次保持预定义数量的假设,并最终选择具有总体最高概率的假设来减轻这种情况。但是经过几次实验,发现它仍然存在可重复性的问题。
语言生成的最佳算法之一是采样算法。使用采样的语言生成是不确定的,因为它根据条件概率分布随机选取下一个单词。但是,据观察,考虑到随机性,采样有时会产生听起来不像人类的文本段落。
解决这个问题的一个技巧是在给定前一个 i 单词的情况下,锐化下一个单词的预测分布。在锐化的同时,我们还在绘制随机样本;但是另外,我们增加了高概率单词被选取的可能性,并且降低了低概率单词被选取的可能性。
另一个转变是引入 Top-K 采样,其中 K 个最可能的下一个单词被过滤,并且概率质量在这 K 个下一个单词中重新分配。这一简单而强大的概念被纳入 GPT-2 模型,是其成功的主要原因之一。GPT-2 模型的另一个补充是原子核取样。该模型不是只从最可能的 K 个单词中取样,而是从累积概率超过预定义概率 p 的最小可能单词集中进行选择。这个特性的引入确保了单词集的大小可以根据下一个单词的概率分布动态地增加和减少。
使用 GPT-2 模型生成体育文本的示例
了解了它的内部工作原理后,让我们深入了解 GPT-2 模型的工作原理和性能。请注意,在这一点上,我们使用的是 GPT-2 模型,而不是使用我们之前下载的体育数据。当我们在下一节中微调模型时,我们将更多地研究如何使用这些数据。
下面的代码演示了 GPT-2 采用的采样技术。“input_ids”是指给予模型的初始字符串。通过将’ do_sample '指定为 True,我们告诉模型使用采样技术。“最大长度”对应于物品的期望长度。‘top _ K’和‘top _ p’分别对应于 K 个单词和核概率 p。最后,我们将名为“num_return_sequences”的参数指定为 2。这使用相同的初始字符串生成了两个不同的段落,并给了我们一个选项来选择我们更喜欢的输出。
#initial string
input_ids = tokenizer.encode('Manchester City agree deal to sell Leroy Sane', return_tensors='tf')
# set seed to reproduce results. Feel free to change the seed though to get different results
tf.random.set_seed(0)
# set top_k = 50 and set top_p = 0.95 and num_return_sequences = 3
sample_outputs = model.generate(
input_ids,
do_sample=True,
max_length=100,
top_k=50,
top_p=0.45,
num_return_sequences=3 )
print("Output:\n" + 100 * '-')
for i, sample_output in enumerate(sample_outputs):
print("{}: {}".format(i, tokenizer.decode(sample_output, skip_special_tokens=True)))
以下是输出结果:
0: Manchester City agree deal to sell Leroy Sane
The Gunners are ready to sign Leroy Sane, who has been on loan at Tottenham for the past three seasons, from Chelsea.
The 21-year-old, who is in his first season at the club, has scored five goals in 14 games for the Blues this season.
The former Arsenal and Chelsea striker has been a target for Chelsea since he joined from Southampton in January 2013.
The deal is
1: Manchester City agree deal to sell Leroy Sane
Manchester City have agreed a £30million deal to sell Leroy Sane to Manchester United for £30million.
The move was confirmed by City sources.
Sane, 24, has scored nine goals in 20 Premier League appearances for the club since joining from Manchester United in January 2014.
He has scored seven goals in 16 Premier League appearances for United since joining from Manchester United in January 2014.
定制 GPT-2:体育文章数据微调
看了输出,我们可以说 GPT-2 已经能够把一个有凝聚力的文本放在一起。然而,它产生的事实陈述缺乏准确性。还有,整个段落没有给我们很运动的感觉。为了解决这些问题,我们试图训练和微调 GPT-2 特别是体育文章,而不是使用它。我们将使用我们之前上传的运动数据集。
我们的第一项工作是将文章整理成一个文本文件。为了做到这一点,我们启动了一个新的 Jupyter 笔记本。单击“文件”选项卡,然后单击“添加装载”。转到上传并选择您刚刚上传的“原始数据”文件夹。
回到笔记本,执行下面的代码来阅读文本文件并整理它们。
mypath = 'Raw data/'
import os
from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]article_list = ''
for i in range(len(onlyfiles)):
if onlyfiles[i][-3:] == 'txt':
try:
with open('Raw data/' + onlyfiles[i], 'r') as file:
data = file.read()
article_list = article_list + '\n' + data
except:
pass
完成后,我们需要使用字符串包中的’ printable '函数过滤掉所有不属于 ASCII 的字符。
import string
article_list_str = ''.join(filter(lambda x: x in string.printable, article_list))
一旦数据达到所需的格式,让我们继续构建模型。我们安装“transformers”包并导入所需的包。
!pip install transformersimport logging
import os
import pickle
import random
import torch
import torch.nn as nn
import transformers
from torch.utils.data import DataLoader, Dataset, RandomSampler, SequentialSampler
from transformers import (
GPT2Config,
GPT2LMHeadModel,
GPT2PreTrainedModel,
GPT2Tokenizer,
PreTrainedModel,
PreTrainedTokenizer,
)
MODEL_CLASSES = {"gpt2": (GPT2Config, GPT2LMHeadModel, GPT2Tokenizer)}
logger = logging.getLogger(__name__)
接下来,我们定义一个类“SportsData”来微调体育数据集并获取其中的令牌。
class SportsData(Dataset):
def __init__(
self,
tokenizer: PreTrainedTokenizer,
#file_path: str,
block_size=512,
overwrite_cache=False,
):
#assert os.path.isfile(file_path)
block_size = block_size - (
tokenizer.max_len - tokenizer.max_len_single_sentence
)
# change if args are added at later point
cached_features_file = os.path.join(
"gpt2" + "_" + str(block_size) + "_file.txt"
)
if os.path.exists(cached_features_file) and not overwrite_cache:
logger.info(
f"Loading features from your cached file {cached_features_file}"
)
with open(cached_features_file, "rb") as cache:
self.examples = pickle.load(cache)
logger.debug("Loaded examples from cache")
else:
logger.info(f"Creating features from file")
self.examples = []
text = article_list_str
tokenized_text = tokenizer.convert_tokens_to_ids(tokenizer.tokenize(text))
for i in range(0, len(tokenized_text) - block_size + 1, block_size):
self.examples.append(
tokenizer.build_inputs_with_special_tokens(
tokenized_text[i : i + block_size]
)
)
logger.info(f"Saving features into cached file {cached_features_file}")
with open(cached_features_file, "wb") as cache:
pickle.dump(self.examples, cache, protocol=pickle.HIGHEST_PROTOCOL)
def __len__(self):
return len(self.examples)
def __getitem__(self, item):
return torch.tensor(self.examples[item], dtype=torch.long)
最后,我们启动定制模型的训练并保存模型。
device = 'cpu'
if torch.cuda.is_available():
device = 'cuda' tokenizer = GPT2Tokenizer.from_pretrained('gpt2-medium')
model = GPT2LMHeadModel.from_pretrained('gpt2-medium')
model = model.to(device)
dataset = SportsData(tokenizer= tokenizer )
article_loader = DataLoader(dataset,batch_size=1,shuffle=True)
BATCH_SIZE = 1
EPOCHS = 1
LEARNING_RATE = 0.0002
WARMUP_STEPS = 5000
from transformers import AdamW, get_linear_schedule_with_warmup
model = model.to(device)
model.train()
optimizer = AdamW(model.parameters(), lr=LEARNING_RATE)
scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=WARMUP_STEPS, num_training_steps=-1)
script_count = 0
sum_loss = 0.0
batch_count = 0
for epoch in range(EPOCHS):
print(f"EPOCH {epoch} started" + '=' * 30)
for idx,script in enumerate(article_loader):
outputs = model(script.to(device), labels=script.to(device))
#outputs = torch.tensor(tokenizer.encode(script)).unsqueeze(0).to(device)
loss, logits = outputs[:2]
loss.backward()
sum_loss = sum_loss + loss.detach().data
script_count = script_count + 1
if script_count == BATCH_SIZE:
script_count = 0
batch_count += 1
optimizer.step()
scheduler.step()
optimizer.zero_grad()
model.zero_grad()
if batch_count == 200:
model.eval()
print(f"sum loss {sum_loss}")
sample_outputs = model.generate(
bos_token_id=random.randint(1,30000),
do_sample=True,
top_k=50,
max_length = 1000,
top_p=0.95,
num_return_sequences=1
)
print("Output:\n" + 100 * '-')
for i, sample_output in enumerate(sample_outputs):
print("{}: {}".format(i, tokenizer.decode(sample_output, skip_special_tokens=True)))
batch_count = 0
sum_loss = 0.0
model.train()output_dir = 'Raw data/'
from transformers import WEIGHTS_NAME, CONFIG_NAME
output_model_file = os.path.join(output_dir, WEIGHTS_NAME)
output_config_file = os.path.join(output_dir, CONFIG_NAME)
torch.save(model.state_dict(), output_model_file)
model.config.to_json_file(output_config_file)
tokenizer.save_vocabulary(output_dir)
现在,我们已经准备好了微调的模型,我们导入它并测试它如何针对我们之前使用的相同输入字符串工作。
model = GPT2LMHeadModel.from_pretrained(output_dir)
tokenizer = GPT2Tokenizer.from_pretrained(output_dir)
input_ids = tokenizer.encode('Manchester City agree deal to sell Leroy Sane', return_tensors='pt')
sample_outputs = model.generate(
input_ids= input_ids,
do_sample = True,
#num_beams= 5,
max_length = 100,
top_k = 50,
top_p=0.85,
num_return_sequences=1
)
print("Output:\n" + 100 * '-')
for i, sample_output in enumerate(sample_outputs):
print("{}: {}".format(i, tokenizer.decode(sample_output, skip_special_tokens=True)))
以下是输出结果:
Output:
----------------------------------------------------------------------------------------------------
0: Manchester City agree deal to sell Leroy Sane to Liverpool
Leroy Sane was among three players who were sold this summer and Liverpool boss Brendan Rodgers admitted he felt the need to replace the former Manchester City winger.
"We sold four players last year and I know I had to get another player in to improve our squad," Rodgers told Sky Sports News HQ.
"We had to sell players and a few of them we did but it was Leroy Sane.
我们注意到这段文字不仅听起来像人类,而且更流畅。经理的引语尤其给了这段文字一种更加真实的感觉,使它看起来非常类似于一篇真正的手写文章。请注意,增加“max_length”的值将允许我们获得更长的文本。
请注意,事实仍然不是完全正确的,但这些可以用我们的知识迅速纠正。重要的是,我们已经能够摆脱手工书写的过程。只要运行这个命令,编辑一些可能存在的事实差异,瞧,你就完成了。
要试用本教程,请使用此链接登录 Spell 的 MLOps 平台,并在创建帐户后获得 10 美元的免费 GPU 点数。另外,请随时在这个链接上发布您的问题和疑问。
参考文献:
https://github . com/cdpierse/script _ buddy _ v2/tree/master/script _ buddy
体育参考 API 简介
如何建立令人敬畏的体育数据集
照片由 JC Gellidon 在 UnSplash 拍摄
这是我每周体育主题系列的第二部分。每周,我都会展示以体育为中心的数据科学应用。
上周,在我的文章战胜困难中,我展示了如何使用体育参考 API 建立一个关于 NBA 球队的数据集,然后使用该数据集找到那些超过常规赛积分差距的球队。本周我想深入探讨如何使用这个 API 为您的项目构建全面的数据集。
当我在网上浏览体育数据项目时,我看到很多人求助于从不同的来源下载表格,手动或通过网络搜集。然后通常需要将这些表连接起来,这是一个非常繁琐的过程,高度依赖于数据的质量。以这种方式构建大型数据集可能需要几天甚至几周的时间。不要成为那个人!令人欣慰的是,Sports Reference 的出色工程师构建了一个 API,可以方便快捷地访问 Sports Reference 关于 MLB、NBA、NFL、NHL、NCAAF、NCAAB 和世界各地许多足球联盟的海量数据库。
要开始使用 Sports Reference API,您需要使用pip install sportsreference
像安装任何其他 python 包一样安装它。
Sports Reference API 的基本思想是使用模块来实例化类对象,这些类对象包含类属性中的相关数据。所有运动中常见的基本模块是团队、时间表、比分、花名册和运动员。NCAAB 和 NCAAF 也有排名和会议的模块。Football(英式足球)使用稍微不同的命名约定,但是一般的 API 结构是相同的。在后端,这些模块通过发送 HTTP 请求从 Sports Reference 的服务器上查询相关数据来创建类对象。没有必要担心把 100 年的棒球赛比分数据塞满你的硬盘(尽管我认为如果你真的想的话,你可以用 API 来做这件事)。
在接下来的部分中,我将展示 NBA API 的特性。如果你对另一项运动感兴趣,我鼓励你继续下去,因为基本的特征和过程本质上是一样的。该代码旨在在 Jupyter 笔记本上执行,但也可以很容易地适用于其他环境。
组
让我们从团队模块开始。以下命令创建 Teams 类的一个实例,并打印出它的所有方法和属性。
from sportsreference.nba.teams import Teamsteams2020 = Teams(year = '2020')
print(dir(teams2020))
团队类方法和属性
Teams 类的唯一公共属性是“dataframes”。该属性是一个 30 x 47 的数据帧,其中 2020 年的每个 NBA 球队都由一行表示。栏目包括得分、罚球次数、对手进攻篮板等。“dataframes”属性通常是访问高级团队信息的最简单方法。然而,也可以使用 Teams 类的实例作为迭代器。例如,下面的代码打印出每个队的名称和得分。团队数据框架的每一列也可以作为团队属性以这种方式访问。
for team in teams2020:
print(team.name, 'Points Scored:', team.points)
日程安排
顾名思义,Schedule 模块用于访问关于团队日程的信息。这非常有用,因为 Teams 模块不包含关于赢/输记录的信息。让我们为密尔沃基雄鹿队 2019 赛季创建一个类的实例,并使用它返回一个包含每场比赛基本信息的数据帧。
from sportsreference.nba.schedule import Schedulemil2019 = Schedule('MIL', year = '2019')
mil2019.dataframe.head()
密尔沃基雄鹿队 2018-2019 赛季的前 5 场比赛
注意 boxscore_index 列,这些 boxscore 索引可以与 boxscore 类一起使用,以获得更详细的游戏信息。与 Teams 模块类似,Schedule 类的实例也可以用作迭代器。最后,Schedule 类有一个“dataframe_extended”属性,它返回一个 dataframe,其中每一行都是 Boxscore 类的一个实例。这为每个游戏提供了更丰富的数据,但由于构建了许多 Boxscore 类的实例,每个实例都需要单独的服务器请求,因此处理时间要长得多。
Boxscore
让我们仔细看看密尔沃基雄鹿队 2019 年东部决赛第一场对阵多伦多猛龙队的比赛。从我们的时间表数据框架中,我们可以发现这场比赛的 boxscore_index 是“201905150MIL”。
from sportsreference.nba.boxscore import Boxscoregame_data = Boxscore('201905150MIL')
通过调用print(dir(game_data))
,我们可以看到 Boxscore 类比 Teams 和 Schedule 类有更多的属性。命令game_data.dataframe
将把这些属性编译成数据帧。
Boxscore 数据框架
嗯,这并不完全是我们习惯看到的 boxscore 类型,但这里仍然有很多有用的数据。为了构建更类似于传统 boxscore 的东西,我们需要使用 Boxscore 类属性‘home _ players’和‘away _ players’。通过执行game_data.home_players
,我们看到这返回了一个 BoxscorePlayer 类对象的列表。此外,我们可以执行print(dir(game_data.home_players[0]))
来查看这个子类所有可用方法和属性的列表。由于 BoxscorePlayer 类具有“dataframe”属性,因此可以通过连接每个单独的 BoxscorePlayer 数据帧来构建更传统的 boxscore 数据帧。下面的代码就是这样做的。
home_df = game_data.home_players[0].dataframefor player in game_data.home_players[1:]:
home_df = pd.concat([home_df, player.dataframe], axis = 0)home_df['name'] = [x.name for x in game_data.home_players]
home_df.set_index('name', inplace = True)
home_df
2019 年密尔沃基雄鹿队主场迎战多伦多猛龙队 ECF 队第一场比赛的比分
通过检查该数据帧的列,我们可以看到,我们不仅获得了所有传统的 boxscore 统计数据,还获得了一些高级统计数据。这总结了 Boxscore 模块的基本用例。
花名册
花名册模块用于获取球队球员花名册的信息。让我们为 2007 年“我们相信”的勇士队创建一个花名册类的实例。
from sportsreference.nba.roster import Rostergsw2007 = Roster('GSW', year = '2007')
正如我在上面展示的,我们可以检查这个类对象的方法和属性,并看到只有一个属性,“players”。与我们刚刚为 Boxscore 模块查看的“home_players”属性非常相似,“players”属性是 Player 类实例的列表。我们稍后将更深入地讨论播放器模块。现在,让我们使用下面的代码片段简单地打印出名册上每个球员的姓名和球员 id。
for player in gsw2007.players:
print(player.name, ':', player.player_id)
由于花名册类为花名册上的每个球员创建一个球员类的实例,并且构造每个实例需要向 Sports Reference 的服务器发出请求,所以使用花名册类来完成这样一个简单的任务会非常慢。如果我们想用这种方法打印某个赛季联盟中每个球员的名字,我们可能需要等待 5 分钟以上来创建所有球员类实例。作为替代,我们可以使用关键字参数slim = True
调用花名册类。这将创建一个花名册类的实例,其中“players”属性只是一个字典,键是 player _ ids,值是名称。下面的代码演示了这一功能。
gsw2007slim = Roster('GSW', year = '2007', slim = True)
gsw2007slim.players
2006-07 赛季“我们相信”金州勇士队的名单
运动员
不足为奇的是,玩家模块用于获取单个玩家的信息。参考 API 文档,我们可以看到播放器模块包含一个抽象类 AbstractPlayer,它由我们已经在 Boxscore 和花名册模块中看到的 BoxscorePlayer 和 Player 类继承。因此,获取球员数据的正确方式实际上是通过花名册和 Boxscore 模块。让我们使用为拜伦·戴维斯提取的 player_id 来获取他的统计数据。
from sportsreference.nba.roster import Playerbaron_davis = Player('davisba01')
baron_davis.dataframe
拜伦·戴维斯职业生涯和赛季统计
这段简单的代码为我们提供了拜伦·戴维斯职业生涯和每个赛季的 89 列数据。除了“dataframe”属性及其所有相关列之外,Player 类还包含诸如“birth_date”、“height”、“weight”、“nationality”等属性。此外,可以使用命令baron_davis.points
查询单个职业统计数据,例如分数。类似地,我们可以使用命令baron_davis('2007').points
查询拜伦·戴维斯在 2006–07 赛季的总积分。根据用例,以这种更直接的方式访问玩家统计数据可能更容易,并且避免处理数据帧。
创建 NBA 球员数据集
在这篇文章的结尾,我将演示如何使用球队、花名册和球员模块来构建一个庞大的 NBA 球员统计数据集。这个数据集将会在我的下一篇文章中使用,我将会在这篇文章中关注 NBA 职业生涯中球员的发展和最终的衰落。
第一步是导入相关的模块并定义一个函数,该函数创建一个带有一些我手动定义的额外字段的播放器数据帧。最重要的是球员在各自赛季的 1 月 1 日的年龄。
# Function to get player info from Player class object.def get_player_df(player):
# helper function to get player age during each season.
def get_age(year, bd):
if year[0] == "Career":
return None
else:
year_dt = datetime(int(year[0][0:4]) + 1, 1, 1)
age_years = relativedelta(year_dt, bd).years +
relativedelta(year_dt, bd).months/12
return age_years
# helper function to get year for each row and denote
# rows that contain career totals.
def get_year(ix):
if ix[0] == "Career":
return "Career"
elif ix[0] == "1999-00":
return "2000"
else:
return ix[0][0:2] + ix[0][-2:]
# get player df and add some extra info
player_df = player.dataframe
player_df['birth_date'] = player.birth_date
player_df['player_id'] = player.player_id
player_df['name'] = player.name
player_df['year'] = [get_year(ix) for ix in player_df.index]
player_df['id'] = [player_id + ' ' + year for player_id,
year in zip(player_df['player_id'],
player_df['year'])]
player_df['age'] = [get_age(year, bd) for year,
bd in zip(player_df.index,
player_df['birth_date'])]
player_df.set_index('id', drop = True, inplace = True)
return player_df
接下来,我使用上面定义的函数来收集过去 20 年中在 NBA 打球的每个球员的整个职业生涯的球员数据。数据分为两个数据框架,一个在季节级别聚合数据,另一个在职业级别聚合数据。这是通过使用球队和花名册模块来迭代从 2000 年到 2020 年的每个 NBA 花名册来完成的。注意,我使用关键字变量slim = True
调用花名册类。如果没有这个设置,我将不得不为一个 NBA 球员的每个赛季创建一个球员实例,增加大约 10 倍的运行时间。
# initialize a list of players that we have pulled data for
players_collected = []
season_df_init = 0
career_df_init = 0
season_df = 0
career_df = 0# iterate through years.
for year in range(2020, 1999, -1):
print('\n' + str(year))
# iterate through all teams in that year.
for team in Teams(year = str(year)).dataframes.index:
print('\n' + team + '\n')
# iterate through every player on a team roster.
for player_id in Roster(team, year = year,
slim = True).players.keys():
# only pull player info if that player hasn't
# been pulled already.
if player_id not in players_collected:
player = Player(player_id)
player_info = get_player_df(player)
player_seasons = player_info[
player_info['year'] != "Career"]
player_career = player_info[
player_info['year'] == "Career"]
# create season_df if not initialized
if not season_df_init:
season_df = player_seasons
season_df_init = 1
# else concatenate to season_df
else:
season_df = pd.concat([season_df,
player_seasons], axis = 0)
if not career_df_init:
career_df = player_career
career_df_init = 1
# else concatenate to career_df
else:
career_df = pd.concat([career_df,
player_career], axis = 0)
# add player to players_collected
players_collected.append(player_id)
print(player.name)
最后一步是将生成的数据帧保存为您喜欢的文件格式。
season_df.to_csv('nba_player_stats_by_season.csv')
career_df.to_csv('nba_player_stats_by_career.csv')
总之,这个脚本应该在大约 30 分钟内编译并保存您的数据集。如果你理解了最后一节的所有代码,那么你应该已经准备好开始使用体育参考 API 构建你自己的数据集了。
下周当我使用这个数据集分析 NBA 职业生涯轨迹时,请务必关注我的文章,也请查看我上周的文章战胜困难。
我希望你喜欢这本书,保重。
运动数据—分析我的 Strava 活动
我的斯特拉瓦体育活动的编辑分层立面图。
作为一个数据和体育迷,我在过去已经多次使用过 T2 的 Strava API。例如,制作精美的绘图或构建交互式仪表盘。最近,我还研究了我的综合体育活动数据。在这个博客中,我将分享我的一些发现。
制造奇特的情节
你可以用不同的方式绘制你的体育活动数据。例如,分层高程图,就像这篇博客标题中使用的那样,或者像下面所示的小倍数(归功于马库斯·沃尔茨)。对我来说,制作花哨的情节只是享受我的活动的结果(和生成的数据)的一种有趣的方式😁。
我所有体育活动的地图都被绘制成小倍数。
构建交互式仪表板
使用闪亮的,我制作了一个交互式仪表盘,它使我能够更详细地研究不同功能的相关性。比如距离和平均速度的关系。对于跑步来说,这显然可以归结为:跑步时间越长,你会越慢,但是用交互式图表分析这一点有助于理解慢了多少。这可以作为建立未来起搏方案的参考。我还在仪表板中放入了我的活动热图。除了美学,它帮助我刷新了我去跑步和骑车的地方的记忆(就像一本相册😉).我在我的城市(荷兰埃因霍温)周围的活动热图如下所示。而且,正如你清楚地看到的,当你骑自行车时,你会走得更远🚴♀️.
我在我的城市(荷兰埃因霍温)附近跑步(红色)和骑车(蓝色)的热图。
汇总数据
这些年来,我喜欢不同的运动。作为主要运动,我以前打曲棍球,之后我开始更频繁地打壁球。我总是将这些运动与跑步和骑自行车结合起来。在过去的一年里,当我决定参加少女峰马拉松比赛时,我把跑步作为一个优先事项。随着跑步成为我最近的主要运动,我很想看看过去几年的表现趋势。为了找到答案,我研究了不同变量随时间的分布。下面列出了一些图表和我的一些观察。有些是我预料到的,有些是我以前没想过的。
我的平均速度密度曲线。
首先,平均速度曲线变平了💨。
这可能是因为训练中的变化较多,例如恢复跑和门槛跑。我特别喜欢 2020 年密度曲线的右侧,显示我更经常达到更高的平均速度😁。
我的平均心率密度曲线。
其次,我的平均心率下降了不少💗。
我就知道(max。)心率随着年龄的增长而降低。而且,我还记得“回到过去”(< 2017)每次跑步都感觉像一场比赛,而现在更多的是放松。这个图表清楚地说明了这两者😉。
我的距离密度曲线。
第三,更多的距离变化。回顾这篇博客的第一个情节,你可以看到在开始的时候我喜欢一遍又一遍地走同样的路线。缺乏变化并没有困扰我,因为我并不经常跑步。现在,我试着变得更多样。不仅仅是速度不同,还有路线和距离。一开始,我决定要么进行“短”跑,要么进行“长”跑,结果是+/- 5 公里或 10 公里。如今,它可以是“短”或“长”跑,基本上意味着 5k 或以上的任何东西。
我的节奏密度曲线。
第四,更多步骤🏃♀️! 看着抑扬顿挫密度图很明显我的抑扬顿挫上去了。高节奏有多种好处,所以我很高兴看到这种增长趋势💪。
每种鞋的平均速度密度。
**第五个也是最后一个,选哪双鞋👟。**在 Strava 上,你可以追踪你的装备。提醒我买双新的很有用(尽管我倾向于在旧的还没穿破的时候就买双新的)😬).接下来,你可以用数据来看看鞋的类型是如何影响速度的。我通常和 Asics Kayano 一起跑步。图中有不同的型号,当我没有跟踪时,我也穿着这双鞋。当我想跑得更快更短时,我倾向于切换到 New Balance Vongo 。对于试车,我使用新百伦耶罗(这里也有两种不同的型号)。在小路上,我通常会走得慢一点,如图所示!
这就是对体育和数据都感兴趣时会发生的事情😎。希望您获得了一些有趣的见解,或者受到启发,以类似的方式分析您的数据!如前所述,我使用了 Strava API 并使用了 rStrava 包来访问数据。
在 AWS 上进行深度学习,成本很低
PYTHON 库简介
python 的点连接模块简介
S pot-connect 是一个 python 模块,适用于任何正在寻找使用云计算的简单方法的程序员。
最初是为机器学习项目开发的, spot-connect 使得使用 Amazon Web Services 和 EC2 实例变得很容易。
AWS 提供的服务和设置帐户的步骤包含在旧文章的了解 AWS 和设置您的 AWS 帐户部分。
如果您计划尝试点连接,并且尚未安装和配置 AWS 命令行( *pip install awscli*
、 *aws config*
),或者如果您尚未为 AWS 帐户创建访问密钥,请阅读参考章节。
spot-instance 运行在 AWS 无法出租的硬件上。从来没有足够的需求来出租亚马逊的所有机器,所以他们以原价的一小部分出租多余的容量,以弥补他们的一些成本。
唯一的问题是,如果需求增加,你可能会被踢出实例,这在高端实例中更有可能发生(在你被踢出之前,你会得到 2 分钟的警告,以便你可以保存/转移你的工作)。
定点连接模块允许您创建和管理定点实例。它可以从命令行、脚本或 jupyter 笔记本中使用。它专注于管理 EC2 资源(AWS 的云计算服务),但提供了额外的功能来与弹性文件系统和 S3 等存储选项进行交互。
接下来是如何使用该模块的演练。
装置
pip install spot-connect
使用 python 3。*
命令行用例
一旦你安装了模块,你可以在提示符下使用它
spot_connect -n instance_1 -p t2.micro -a True
在命令提示符下使用 spot_connect 还可以让您将提示符直接连接到实例。
使用 spot-connect 启动一个实例,然后使用链接提示符(个人屏幕截图)直接在实例上运行 linux 命令。
上面的例子用“t2.micro”概要文件创建了一个名为“instance_1”的实例。它连接到一个名为“stockefs”的弹性文件系统,并将提示符连接到新创建的实例。
gif 已经被加速了。启动一个实例通常需要几分钟或更长时间,这取决于规格。 如果您使用现有实例的名称进行连接,您将立即重新连接到该实例。
命令提示符下对spot_connect
最有用的参数是:
- 名称 (
-n
):现货实例的名称 ***** - 配置文件 (
-p
):配置文件的名称(指定实例类型、最高投标价格等的预设配置……更多信息请见下文)。 ****** - 文件系统 (
-f
):要连接的弹性文件系统。如果它不存在,将创建一个(不必与实例名相同)。 - 脚本 (
-s
):一旦准备好就在实例上运行的脚本(如果在实例上使用 linux 操作系统,这必须是一个 bash 脚本……)。 - 上传 (
-u
):上传你想要的任何文件到实例中(对于小上传有用,否则使用 S3 传输,更多内容见下文)。 - 远程路径 (
-r
):上传将上传到实例上的这个路径。 - 主动提示 (
-a
):如果为真,将提示连接到实例(只能从命令提示符完成)。 - 实例概要 (
-ip
):实例的访问角色(不同于概要)。这授予实例访问其他 AWS 资源的权限,如 S3 。 ******
***** = 必需 ****** = 仅在创建实例时必需(不重新连接)
能够将提示直接连接到实例对于排除脚本故障或运行任何其他检查非常有用。
选择实例类型
要用 spot-connect 启动一个实例,您只需给该实例一个名称和一个概要文件。
概要文件是预设的实例规范,它定义了诸如实例类型、最高投标价格、区域和其他连接选项等内容。这些可以在安装模块时随模块一起下载的 profiles.txt 文件中找到。
可用实例类型、 定价 、图片/AMI id 均随地区变化。Spot-connect 附带了从 AWS 网站获取的区域实例数据和 AMI id 数据。
您可以使用点连接模块更改默认的配置文件设置:
from spot_connect import sutils
sutils.reset_profiles()
reset_profiles()
方法将向您显示一个区域列表,然后是一个 ami 列表,每次都要求您选择一个。然后您的本地副本 profiles.txt 将被更新以使用该区域和 AMI。
笔记本使用案例
对于笔记本和脚本来说,SpotInstance
类相当于在命令提示符下使用spot_connect
。
from spot_connect.spotted import SpotInstance
instance = SpotInstance('instance1', profile='t2.micro', price=0.01)
该命令创建或连接到“实例 1”实例。一个 SpotInstance 对象可以用与spot_connect
相同的参数进行实例化。此外, SpotInstance 还允许您指定配置文件参数,允许您覆盖像price
这样的配置文件中的任何默认设置,这将允许您直接提交自定义的最高出价。
使用SpotInstance
您可以下载和上传文件,
instance.upload('test_run.py') # script creates a test.txt file
运行脚本,
instance.run('run_test.sh') # bash script is: "python test_run.py\n"
直接在实例上运行命令,
instance.run('ls', cmd=True) # use the cmd option to pass commands
甚至终止实例。
instance.terminate() # terminate the instance
instance.refresh_instance() # update the instance status
使用run(<command>, cmd=True)
方法直接在实例上运行命令。但是,请注意,这些命令总是在主目录中运行,这意味着在一次运行中更改目录并不意味着您在下一次运行中从该目录开始。
幸运的是,您可以使用\n
一起运行连续的命令
instance.run('cd**\n**rm test.txt', cmd=True)
这可以很容易地将复杂的脚本存储为可以在 python 中直接使用的函数。例如:
def transfer_script(bucket, efs_path):
'''Download S3 data and place it in the EFS folder''' # The first command is the download
# Use "nohup" to run the job in the background of the instance
script ='nohup aws s3 sync '+bucket+' '+efs_path+'**\n**'
# Use "curpid=$!" to get the job-id for the sync job
script +='curpid=$!**\n**' # Three part command in linux
# 1) In the background, wait for all jobs to finish
# 2) when finished, run command to shutdown the instance,
# 3) place all the output from the sync job in transfer.txt
script +="nohup sh -c 'while ps -p $0 &> /dev/null;
'do sleep 10; done && sudo shutdown -h now'
$curpid &> transfer.txt &**\n**"
return script script = transfer_script("s3://data", "/home/ec2-user/efs/")
instance.run(command, cmd=True)
实例管理器
启动一个实例很好,但是 spot-connect 的目标是便于在多个实例之间分配工作负载。这就是InstanceManager
类出现的原因。
实例管理器允许您一次启动并跟踪多个实例。它还提供了在实例和 S3 之间传输文件、运行分布式工作负载等功能。
下面是如何跨多个实例组织执行任务的示例:
1。 用efs='data'
实例化一个实例管理器,这样管理器创建的实例自动链接到名为“数据”的 EFS
from spot_connect.instance_manager import InstanceManager
im = InstanceManager(efs='data')
2。使用launch_instance
方法启动一个实例。用im
创建的实例可以在im.instances
中找到。
im.launch_instance('monitor', profile='t2.micro')
3。向clone_repo
方法提交“monitor”实例,以将项目的 Github repo 克隆到 efs 中。
im.clone_repo(im.instances['monitor'],
'[https://github.com/FlorentF9/DeepTemporalClustering.git](https://github.com/FlorentF9/DeepTemporalClustering.git)',
directory='/home/ec2-user/efs/') # default path
4。运行cd efs
命令,然后运行mkdir results
命令,在 EFS 中创建一个结果文件夹。
im.instances['monitor'].run('cd efs**\n**ls', cmd=True)
5。设计一个方法,它可以接受每个作业的参数,并返回一个可以在每个实例上运行的脚本。
def runDTC(n_clusters):
'''Train a DTC model on the package data with n_clusters''' # Change the directory to the project directory
script = 'cd /home/ec2-user/efs/DeepTemporalClustering/**\n**' # Train the DTC algo in the background of the instance
script+= 'nohup python DeepTemporalClustering '+str(n_clusters)+' **--savedir** **/home/ec2-user/efs/results\n**' # Get the job ID for the training job
script +='curpid=$!**\n**' # Shut down the instance once that job is done
script +="nohup sh -c 'while ps -p $0 &> /dev/null; 'do sleep 10; done && sudo shutdown -h now' $curpid &> transfer.txt &**\n**" return script
6。为一系列“n_cluster”值训练模型。使用run_distributed_jobs
方法在单独的实例上训练每个模型。
# Get a list of scripts to run, one for each instance
scripts = [runDTC(i) for i in range(10, 61, 10)]im.run_distributed_jobs(
"DTC", # prefix given to each instance name
len(scripts), # number of instances to launch
scripts, # the scripts to run on each instance
'p2.xlarge' # use this instance type for each instance
)
7。检查实例的状态,等待直到所有实例都终止(完成它们的作业)。
In [7]: im.show_instances()
Out[7]: {'monitor': 'running',
'DTC_1': 'terminated',
'DTC_2': 'terminated',
'DTC_3': 'terminated',
'DTC_4': 'shutting-down',
'DTC_5': 'running',
'DTC_6': 'running'}
8。使用instance_s3_transfer
方法将结果上传到 S3。必须提供实例配置文件才能让实例访问 S3。
im.instance_s3_transfer("/home/ec2-user/efs/results",
"s3://bucket_data",
"s3access") # my instance profile
在 S3,您可以直接通过控制台或使用命令提示符下的awscli
下载结果:
aws s3 sync "s3://bucket_data/results" "<local folder>"
在结束本节之前,有必要介绍一些有用的 bash 命令:
nohup
:当放在命令的开头时,即使用户退出,命令也会完成。&
:当放置在您的命令之后时,会将命令发送到后台,以便您可以继续使用提示。> something.txt
:在命令的末尾,将命令生成的任何输出指向所需的文本。在.txt
后添加另一个&
来隐藏整行并继续使用提示。
总结
这就是 spot-connect 模块的基本功能。这里是这个项目的 Github 回购,在这里你可以找到一个走查笔记本(仍然需要更新以包括本文中的 DTC 示例)以及我用来从 AWS 收集价格和图像数据的笔记本。
我根据自己的时间表开发模块,但是本文中介绍的基本功能对我来说只是暂时的停止。非常欢迎投稿。以下是我认为值得追求的特性:
- 2 分钟关机警告处理
- 使用 boto3 的 AWS spot-fleet 功能
- 扩展存储管理功能(S3、EFS、EBS)
- 提供运行和协调数据同步代理的能力
- 提高代码的整体优雅性
感谢阅读!
😃
更多推荐
所有评论(0)