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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

鲜为人知的 Python 特性

原文:https://towardsdatascience.com/lesser-known-python-features-f87af511887?source=collection_archive---------4-----------------------

Python 中经常不为人知和被低估的功能示例

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

Markus SpiskeUnsplash 上拍摄的照片

时不时地,当我了解到 Python 中的一个新特性,或者我注意到其他一些人不知道这个特性时,我会记下来。

在过去的几周里,有一些有趣的特性是我自己最近了解到的,或者意识到了其他一些特性——例如,在堆栈溢出方面,我以前并不知道。

下面是对其中一些特性的快速浏览,以及每个特性的概要。

divmod

非常有用的功能。divmod()函数对两个数执行模数除法%,然后返回商和余数。例如:

divmod(5, 2)

**[Out]:** (2, 1)

这只是简单地找出我们可以将2放入5的次数,而不用拆分这个数,这给了我们2,即商。在此之后,我们还有1剩余,这是我们的余数。

这对于返回进程运行所用的时间(以小时、分钟和秒为单位)特别有用。像这样:

start = datetime.datetime.now() ...  # process code goes hereend = datetime.datetime.now()# we get the total runtime in seconds
runtime = (end - start).seconds  # we will assume 30000# how many hours are in these secs, what are the remaining secs?
hours, remainder = divmod(runtime, 3600)# now how many minutes and seconds are in our remainder?
mins, secs = divmod(remainder, 60)print("{:02d}:{:02d}:{:02d}".format(hours, mins, secs))

**[Out]:** "08:00:08"

*args,**kwargs

有时,您可能会注意到函数定义包含这两个参数,比如def func(x, y, *args, **kwargs)

它们实际上都非常简单。两者都允许我们向一个函数传递多个值,然后将这些值打包到一个生成器中。

如果我们将一个列表/生成器传递给一个标准参数,结果是相似的,就像这样:

def func(values):
    for x in values:
        print(x, end=" ")func(**[1, 2, 3]**)

**[Out]:** '1 2 3 '

现在,让我们使用*args——这将允许我们将每个值作为一个新的参数传递,而不是将它们都包含在一个列表中。

def func(*values):
    for x in values:
        print(x, end=" ")func(**1, 2, 3**)

**[Out]:** 1 2 3

注意,我们不需要输入*args,相反,我们输入了*values。我们使用的变量名无关紧要。由于只有一个星号*,它被定义为*args

*args简单地从我们传递给函数的参数中创建一个元组。

**kwargs另一方面,创造了字典。因此得名,key-wordarguments。我们像这样使用它:

def func(**values):
    for x in values:
        print(f"{x}: {values[x]}")func(x=1, y=2, z=3)**[Out]:** x: 1
       y: 2
       z: 3

同样,我们可以随意调用变量,在本例中我们使用了**values。使用双星号**将其定义为**kwargs

(听力或阅读)理解测试

这绝对是 Python 最有用的特性之一。理解表达是不可错过的。最常见的是列表理解,我相信你们中的绝大多数人都见过这些:

vals = [1, 2, 3, 4, 5][i**2 for i in vals]

**[Out]:** [1, 4, 9, 16, 25]

但是我们不限于这些方括号。我们可以用几乎完全相同的语法定义一个生成器表达式:

(i**2 for i in vals)

**[Out]:** <generator object <genexpr> at 0x7f0281730fc0>

当然,生成器中的每个元素只有在被调用时才会被输出,我们可以用list()来实现:

list((i**2 for i in vals))

**[Out]:** [1, 4, 9, 16, 25]

语法上的另一个小变化是,我们甚至可以使用字典理解来构建字典:

{i: i**2 for i in vals}**[Out]:** {1: 1,
        2: 4,
        3: 9,
        4: 16,
        5: 25}

文件夹

一个特别有意思的字符串方法。其功能与lower相似。然而,casefold试图更积极地标准化更广泛的字符。

在大多数情况下,lowercasefold的行为是相同的,但偶尔也会有不同:

"ς".casefold()  # both ς and σ are the Greek letter sigma**[Out]:** "σ"

相比之下,使用lower:

"ς".lower()  # however, lower recognizes them as different**[Out]:** "ς"

**[Out]:** False

这里,两个 sigmas 都已经是小写了。这取决于用例,可以如预期的那样运行。

然而,如果我们打算比较两个等价的希腊单词,一个使用σ,另一个使用ς.尽管相同,但只有casefold能让我们准确地比较它们:

"ἑρμῆσ" == "ἑρμῆς"**[Out]:** False"ἑρμῆσ".lower() == "ἑρμῆς".lower()**[Out]:** False"ἑρμῆσ".casefold() == "ἑρμῆς".casefold()**[Out]:** True

希望你从这篇文章中有所收获。特别是,divmodcasefold都是非常有趣的功能,我个人直到最近才使用过。

如果你有任何独特的、有趣的或者相对不为人知的 Python 特性想要分享,请告诉我,我很乐意看到它们!欢迎通过 Twitter 或在下面的评论中联系我们。

感谢阅读!

如果您喜欢这篇文章,您可能会对我之前关于另外四个鲜为人知的 Python 特性的文章感兴趣:

[## 4 个非常有用的 Python 特性

四个不太知名但非常有用的 Python 功能

towardsdatascience.com](/4-super-useful-python-features-993ae484fbb8)

从 Kaggle —孟加拉影像分类竞赛中得到的启示

原文:https://towardsdatascience.com/lesson-learnt-from-kaggle-bengali-image-classification-competition-39c1ed79adb1?source=collection_archive---------43-----------------------

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

https://www.kaggle.com/c/bengaliai-cv19/?utm_medium=email&UTM _ source =对讲机&UTM _ campaign =孟加拉语-电子邮件-发射

我用 Github Page + fastpages 创建了一个 新博客 ,因为它对编码更友好,我基本上只是从那里复制页面到 Medium,它工作得很好!你可以订阅 RSS ,我仍然会在媒体上发布,但可能会在新博客上发布更多关于编码的内容。

介绍

我和一个朋友组队参加了孟加拉图片分类比赛。在整个比赛中,我们努力在公共排行榜上获得高排名。最后,结果让所有人都大吃一惊,因为排行榜震动很大。

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

https://www.kaggle.com/c/bengaliai-cv19/leaderboard

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

【https://www.kaggle.com/c/bengaliai-cv19/leaderboard】

最终私信分数远低于公信分数。这表明大多数参与者都过度适应公共排行榜。

分类任务

这是一场图像分类比赛。我们需要预测孟加拉文字的 3 个部分rootconsonantvowel。像 MNIST 数据集一样,这是一个典型的分类任务。

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

孟加拉语。艾https://www.kaggle.com/c/bengaliai-cv19/data

评估指标

竞赛使用宏观回忆作为评价标准。一般来说,人们在训练中的回忆率超过 96%,最优秀的人回忆率甚至超过 99%。

模型(越大越好)

我们从xresnet50开始,这是一个比较小的型号。因为我们假设这个分类任务是一个非常标准的任务,因此模型的差异将不是最重要的。因此,我们选择 xresnet50,因为它在准确性方面有很好的性能,并且训练相对较快。

比赛快结束时,我们换了一个更大的型号se-resnext101。它需要三倍的训练时间,加上我们必须缩小批量,因为它不适合 GPU 的内存。令人惊讶的是(可能不是每个人都惊讶),更大的模型确实比我预期的更好地提升了性能,召回率约为 0.3-0.5%。这是一个很大的改进,因为召回率非常高(0.97),换句话说,仅仅通过使用一个更好的模型,它就减少了10%的误差,不错!

增大

深度学习永远没有“足够”的数据,所以我们总是尽力收集更多的数据。由于我们无法收集更多的数据,我们需要数据扩充。我们从旋转+缩放开始。我们还发现 MixUp 和 CutMix 对提高性能非常有效。从 0.96 到 0.964 的召回率,它也给了我们大约 10%的提升。

CutMix&mix

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

CutMix:训练具有可本地化特征的强分类器的正则化策略

Mixup 很简单,如果你懂摄影的话,对你的照片进行双重曝光也差不多。它通过采样权重来覆盖两幅图像(在本例中为猫+狗)。因此,不是预测 P(狗)= 1,新的目标可以变成 P(狗)= 0.8 和 P(猫)= 0.2。

CutMix 也有类似的想法,不是叠加两张图像,而是裁剪出图像的某个比例,用另一张替换。

令我惊讶的是,这些增加的数据对人类来说没有多大意义,但它对提高模型准确性和减少经验上的过度拟合非常有效。

实验记录

我通常只是用一个简单的 CSV 和一些打印消息来记录我的实验。当有一个以上的人工作时,这就变得很乏味了。传达实验结果是很重要的。我在这场比赛中探索了Hydrawandb,它们非常有用。

九头蛇

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

https://hydra.cc/九头蛇

让你的实验可配置通常是个好主意。我们使用Hydra来实现这个目的,这有助于组成不同的配置组。通过使您的超参数可配置,您可以通过配置文件定义一个实验并运行多个实验。通过记录带有训练统计信息的配置,很容易进行跨模型比较,并找出哪个配置对您的模型有用。我已经写了一个简短的例子,介绍如何在普通的 ML 实验中使用 Hydra。

Wandb

wandb(Weight & bias)做了一些事情。它提供了自动记录所有模型统计数据的内置函数,您也可以用简单的函数记录您的自定义指标。

  • 比较不同实验的配置,找出性能最好的型号。
  • 用于记录模型权重和梯度的内置函数,用于调试目的。
  • 记录您想要的任何指标

所有这些结合在一起,使协作体验更好。经常同步进度真的很重要,让每个人都在一个平台上获得结果会让这些对话更容易。

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

截图取自我实验的 wandb

随机加权平均

这是一个简单而有效的技术,可以给我的模型带来 0.3-0.4%的提升。简而言之,它在训练期间拍摄模型权重的快照,并在最后取平均值。当你只训练一个模型时,它提供了一个廉价的方法来做模型集合。这对这个比赛很重要,因为它让我保持足够短的训练时间,以便在几个小时内得到反馈,并减少过度拟合。)

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

https://py torch . org/blog/random-weight-averaging-in-py torch/

越大越好(图像尺寸)

在整个比赛过程中,我们将图像尺寸缩减为 128x128,因为这使得模型训练更快,我们相信大多数技术应该可以转移到更大的图像尺寸。保持你的反馈回路足够短是很重要的(几小时,如果不是几天)。您希望训练数据尽可能小,同时保持它们可转移到整个数据集。一旦我们将我们的图像放大到全尺寸,训练一个模型需要将近 20 个小时,在比赛结束之前,我们几乎没有机会调整超参数。

调试和检查点

曾经有一段时间,我们分开开发模型,有一段时间我们没有同步代码。我们在此期间重构了我们的代码,这是一个巨大的错误。事实证明,我们的预重构代码训练了更好的模型,我们引入了一些未知的错误。因为我们改变了很多东西,所以几乎不可能找到答案。调试一个神经网络是如此困难,彻底测试它是很重要的。注入大量代码可能有助于您更早地运行实验,但是您可能会在之后花费更多的时间来调试它。

我认为这是适用的,即使你是独自工作。

  • 保持你的变化小。
  • 尽早建立基线,在引入新特性后(尤其是代码重构后)总是进行回归测试
  • 创建随时回滚的检查点,尤其是如果您不是每天都在处理它。

实施是 Kaggle 竞赛的关键(在现实生活中也是如此)。不管你的模型有多好,一个小小的错误可能会悄悄地破坏你的模型

使用辅助标签

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

来自https://www.kaggle.com/c/bengaliai-cv19/的样本数据

如前所述,这个比赛需要预测rootvowelconsonant部分。在训练数据中,他们实际上也提供了grapheme。很多人说,如果你用grapheme训练,它会极大地改进模型,并且很容易获得 98%的召回率。

这是我们在整个比赛中无法重现的,我们在最后一刻尝试过,但似乎并没有改善我们的模型。结果是很多人过度拟合数据,因为测试数据集有更多看不见的特征。

但这仍然是一个很好的注解,带着不是你最终想要的输出的标签训练仍然是非常有用的。

减肥课程

训练数据集的分布很不平衡,但是为了得到一个好的结果,我们需要准确地预测每一个类(宏观召回)。为了解决这个问题,我们选择使用类别权重,其中较高的权重将应用于稀有样本。我们对此没有消融研究,但它似乎有助于缩小准确性和回忆之间的差距,并允许我们稍微更好地训练模型。

找个队友!

最后,如果可以的话,请去找一个队友。开始一场 Kaggle 竞赛是很常见的,但要完成它们却不那么容易。由于工作原因,我在比赛期间停了一个月。在你停下来这么久之后,重新回到比赛中来真的很难。有一个队友有助于激励你,最终,这对我们双方来说都是一次很好的学习经历。

预训练模型

我们还尝试使用预训练模型,因为它允许更短的训练,并通过迁移学习(使用从大型数据集学习的权重作为初始权重)提供更好的性能。它也给了我们的模型一点改进。

  • 微调模型头部,同时保持其他层冻结(除了 BatchNorm 层)。
  • 解冻模型,一起训练所有层。

我还尝试了在完全不冻结任何层的情况下,直接用区分学习率来训练模型。它的表现类似于冻结微调,所以我最后只是从头开始训练整个模型。

如果代码有效,就不要碰它

这可能不是一个好习惯,但我建议不要为了一场比赛而这样做。在代码重构之后,我们花了大量的时间来调试我们的代码,最终只是回滚到一个旧的提交并挑选新的特性。在比赛中,你没有足够的时间去测试所有的东西。你不需要一个漂亮的抽象类来容纳你的所有特性,可能需要一些重构来保持你的函数/类的整洁,但是不要在这上面花费太多时间。在框架之间跳转甚至很常见(你可能会发现别人的内核很有用),所以不可能完美地构建你的代码。

  • 如果有人已经创建了一个工作提交脚本,使用它!
  • 如果有人已经创建了一个工作的预处理函数,使用它!

除非有必要,否则不要花时间去优化这些代码,因为在竞争环境中这样做通常是不值得的。你应该专注于增加新的功能,尝试新的模型,测试新的增强技术。

摘要

这是一次很棒的学习体验,刷新了我一些过时的计算机视觉模型知识。如果你从未参加过比赛,找个朋友开始吧。如果你刚刚完成了一个,试着写出来,分享你的经验。😉

来自深度学习大师的教训

原文:https://towardsdatascience.com/lessons-from-a-deep-learning-master-1e38404dd2d5?source=collection_archive---------16-----------------------

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

瓦伦丁·b·克雷默在 Unsplash 上的照片

Yoshua Bengio 是深度学习的传奇人物,与 Geoff Hinton 和 Yann LeCun 一起获得了 2018 年的图灵奖

在这个简短的帖子中,我想为你强调一下 Yoshua 和他的合作者从 381 个参赛团队中赢得一场机器学习比赛的一些聪明的事情。也许这些想法会对你自己的工作有用。

在一个强大的深度学习框架(例如 TensorFlow、PyTorch)可以免费下载的世界里,他们的竞争获胜方法很好地证明了你的优势可能来自于你对你的问题的细节建模的好坏。

(说明:这项工作是在 2015 年完成的。鉴于自那时以来深度学习和计算硬件的所有进步,如果比赛在今天举行,Yoshua 和他的团队可能会以不同的方式解决这个问题)

参加比赛的团队得到了一个数据集,其中包含了在葡萄牙波尔图市一整年的所有出租车行程。

训练数据集中有 170 万次旅行,对于每次旅行,重要的数据元素是:

  • 从旅程开始到结束,每 15 秒测量一次出租车位置的 GPS 坐标(纬度和经度)。第一个经纬度对是旅行的起点,最后一个经纬度是旅行的目的地。例如,行程开始时、15 秒后和 30 秒后的出租车位置如下所示:[-8.578719,41.156271],[-8.578629,41.157693],[-8.578521,41.159439]。
  • 旅行开始时的时间戳
  • 出租车 ID
  • 客户 ID(如果客户通过电话要求出租车)或出租车停靠站 ID(如果他们在出租车停靠站进入出租车)

参与者面临的挑战简单来说就是:

给定一个的部分行程(即起点和接下来几个连续点的经纬度)和时间/ID 元数据,预测最终目的地的经纬度。

例如,假设一次出租车旅行从圣本托站开始,在 Jardins do Palacio de Cristal 结束,如下所示。

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

部分行程将包括起点,可能如下所示:

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

测试数据集有 320 次部分行程。评估指标是预测目的地和实际目的地之间的距离,是测试数据集中行程的平均值。

但是预测和实际的目的地都是地球表面上的点(而不是平面上的点),所以它们之间的距离不是用欧几里德距离来计算,而是用一个叫做 哈弗辛距离 T5 的东西来计算:

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

https://arxiv.org/abs/1508.00021

看起来很简单,对吧?😃

这是一个结构化数据问题(即,没有图像、音频等),因此如果您想要使用神经网络方法,一个合理的起点将是一个基本网络(一个 MLP ),具有一个隐藏层和两个输出节点,一个用于目的地的纬度,一个用于目的地的经度。

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

但是并发症马上出现了:

  • 由于不同的旅行可能具有不同的持续时间,因此每次旅行中纬度-经度对的数量会有所不同,因此每个训练示例都有一个变量数量的输入。例如,10 分钟的车程将有大约 40 个经纬度对,而 30 分钟的车程将有三倍长的输入。我们如何处理不同数量的输入?
  • 那个哈弗辛函数看起来很吓人。它可微的,所以也许优化它就可以了?我们会看到的。
  • 我们的两个输出节点预测纬度和经度。也许这可以很好地工作,但是在测试数据集中只有320 个观察值,所以即使一些不好的预测也会破坏评估指标。此外,直接预测纬度和经度没有考虑到热门目的地(例如,Sao Bento 站)在数据中出现的频率更高,因此正确预测非常重要。**

让我们来看看 Yoshua 和他的团队是如何解决这些问题的。

问题:变长输入

(如果你熟悉递归神经网络 (RNNs),你会立刻意识到它们对这个问题的适用性。事实上,在他们的论文中,Yoshua 和合作者探索了几种不同的 RNNs 变体来解决这个问题,但是他们的竞争获胜模型没有使用 RNNs;它使用了下面描述的简单思想)

解决方案:

最有效的解决方案非常简单。

连接输入的前 5 个坐标和后 5 个坐标。如果输入的坐标少于 10 个,仍采用前 5 个和后 5 个坐标,它们重叠是可以的。最后,如果部分行程少于 5 个坐标,只需重复第一个或最后一个坐标,直到达到 10 个坐标。

例如,从这个“原始”输入…

[[-8.611794,41.140557],[-8.611785,41.140575],[-8.612001,41.140566],[-8.612622,41.140503],[-8.613702,41.140341],[-8.614665,41.140386],[-8.615844,41.140485],[-8.61561,41.140683],[-8.614566,41.141088],[-8.614395,41.141979],[-8.613936,41.142942],[-8.612793,41.143851],[-8.611488,41.144787],[-8.610543,41.144391],[-8.610282,41.143536],[-8.610255,41.143401],[-8.608824,41.143239],[-8.608419,41.143149],[-8.606565,41.142348],[-8.605179,41.143446],[-8.604549,41.144796],[-8.604297,41.1453],[-8.603505,41.145561],[-8.602488,41.145633],[-8.601039,41.145759],[-8.600436,41.146443],[-8.599977,41.147289],[-8.598681,41.14827],[-8.598303,41.148423],[-8.598618,41.149467],[-8.597529,41.151294],[-8.596161,41.153679],[-8.594838,41.155983],[-8.594163,41.157135],[-8.593002,41.159187],[-8.591454,41.161608],[-8.589924,41.163453],[-8.589402,41.163309]]

…仅使用粗体的坐标:

[-8.611794,41.140557],[-8.611785,41.140575],[-8.612001,41.140566],[-8.612622,41.140503],[-8.613702,41.140341] ,[-8.614466]

如果你想知道为什么他们选择 5 而不是另一个数字,我怀疑他们认为这是一个超参数 k 并尝试了一些不同的值;k = 5 可能是最好的。

吸取的教训:

在具有可变长度输入的问题中,精心选择的固定长度输入子集可以捕获输入的本质*。***

对于一次出租车出行,知道部分行程的起点和终点,大概就是你需要的关于部分行程的全部信息;知道出租车在这两点之间的确切路线可能是不必要的。

但在其他问题中,知道开头和结尾可能还不够;以某种方式表示整个路径可能是必要的。在这些情况下,定期对整个路径进行采样可能会奏效。或者更频繁地对路径中更感兴趣的部分进行采样,而不太频繁地对路径中不太感兴趣的部分进行采样可能是正确的方法。

这些想法并不是万无一失的:如果输入的是一个句子,我们不能只看开头的几个词或最后的几个词。从每个句子中抽取固定数量的单词也不行;省略单个单词(例如单词‘not’)可能会改变句子的意思。

尽管如此,Yoshua 的解决方案表明,如果你仔细思考,你可能能够想出一个简单的方法,对你的具体问题来说足够好。**

问题:我们如何处理令人生畏的哈弗森距离函数?

解决方案:

事实证明,我们对距离函数的担心是有道理的。Yoshua 和他的团队在使用哈弗辛函数时确实遇到了麻烦,所以他们必须找到一个更简单的替代方法。

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

https://arxiv.org/abs/1508.00021

吸取的教训:

同样,这是一个针对特定问题思考的好例子。

他们没有试图设计一个通用的哈弗森距离近似值。鉴于问题发生在波尔图,他们只是需要在那个城市的规模下运作良好的东西。它不需要在更大的距离上工作。

一旦你意识到这一点,稍微搜索一下就能把你带到等矩形距离,这看起来比哈弗斯简单多了。

如果你熟悉机器学习,你可能已经知道确保你的损失函数准确地捕捉你关心的问题的真实世界目标的重要性。

但是你可能没有学到的是,当你的损失函数很复杂时(通常如此),你不需要到处寻找一个好的近似。只要在你的问题范围内足够好就行了。**

问题:有两个简单的输出节点——一个用于纬度,一个用于经度——可以工作吗?

由于我们要预测的目的地由两个标量值(纬度和经度)组成,因此自然会有两个输出神经元。然而,我们发现很难训练这样一个简单的模型,因为它没有考虑任何关于数据分布的先验信息。 (重点地雷)来源:【https://arxiv.org/abs/1508.00021】T4

通过“关于数据分布的先验信息”,Yoshua 和他的团队指的是不同目的地的不同受欢迎程度(例如,Sao Bento 火车站将比特定的住宅地址更受欢迎)。

让我们看看他们做了什么!这是他们论文中我最喜欢的部分。

解决方案:

他们对训练集中的所有最终目的地运行聚类算法,并将它们分成几千个集群(准确地说是 3392 个)。

从概念上讲,他们从这个…

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

…变成这样。

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

(这只是为了举例说明。实际的簇可能不都是相同的大小和形状)

现在,我们不是直接预测最终目的地的经纬度,而是可以将此视为一个多类分类问题,任务是将输入分类到 3392 个聚类中的一个。

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

多类分类问题的最后一层通常是 softmax 层,它给出了所有可能输出类的概率分布。在我们的示例中,softmax 层将为 3,392 个聚类中的每一个聚类生成一个概率。

多类分类中的标准做法是挑选概率最高的类作为预测输出。相应地,我们可以挑选概率最高的聚类,并使用其中心点的经纬度作为预测目的地。

请注意这种转换是如何巧妙地考虑到数据分布的’先验信息’:包含热门目的地的分类将在训练集中更频繁地出现,因此平均而言,具有更高的预测概率。

这听起来不错,对吧?

但是如果一个实际的目的地在一个集群的角落,远离集群中心呢?因为我们使用聚类中心作为预测,所以我们的预测和实际目的地之间的距离肯定是非零的,并且可能相当大。

解决这个问题的一个方法是增加我们使用的集群数量。通过生成(比方说)5000 个集群,每个集群变得更小,并且集群中的每个点都将更接近其中心。但是我们现在有一个多类分类问题,有更多的输出类。如果没有每个聚类的足够训练数据,我们将无法训练出一个好的模型。

Yoshua 和他的团队设计了一个更好的方法。

他们将预测的聚类概率(即 softmax 的输出)乘以聚类中心的坐标,并将它们相加以计算加权平均纬度…

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

预测纬度

…和加权平均经度。

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

预测经度

这个(概率加权的)纬度-经度对是预测的目的地。

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

这意味着,例如,如果模型认为两个相邻的聚类同样可能是最终目的地,则它们中心的中点将被预测为最终目的地。

值得注意的是,这个最终加权平均步骤是而不是后处理步骤。它必须是网络的一部分— 只有这样,预测的经纬度对才能输入损失函数,进而优化网络训练。

为了制作网络的这一部分,他们在 softmax 层之后添加了一个单一的线性层。在我看来,这是一步妙棋:-)**

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

这个线性层的权矩阵就是聚类中心…

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

…但有一个重要的转折:训练期间,重量保持不变。

毕竟,我们已经知道它们是什么(也就是说,它们不是随机初始化的权重,它们来自聚类算法),不需要学习它们。

总之,Yoshua 和他的团队:

  • 首先将问题从双输出回归问题转化为多类分类问题
  • 然后通过添加最后一个线性图层和两个输出节点,将其改回双输出回归问题
  • 通过将聚类中心作为线性层的权重矩阵,但冻结该层的权重,他们在网络中引入了加权平均步骤,使网络的端到端训练成为可能。

整洁,对不对?

顺便说一句,如果你想知道使用了哪种聚类算法:

使用均值偏移聚类算法对所有训练轨迹的目的地计算聚类,返回一组 C = 3392 个聚类。来源:https://arxiv.org/abs/1508.00021

经验教训:

  • 考虑输出图层时,考虑输出值的先验分布非常重要。对于分类问题,这通常是简单的(甚至是自动的),但是对于像这样的回归问题,它需要比我们通常做的更多的关注。
  • 如果问题的细节需要特定类型的计算,则定义一个层来执行该计算,并将其包含在网络中(而不是在网络外以特别的方式执行),以便您可以在训练过程中了解其参数。只要能计算出 的导数,就值得一试
  • 如果上面的教训让你想知道为什么 Yoshua 和他的团队在网络之外进行聚类,而不是在网络中为其定义一个层,并作为训练网络的一部分学习最佳聚类:**

我们基于聚类的输出层的一个潜在限制是最终预测只能落在聚类的凸包中。一个潜在的解决方案是将聚类作为网络的参数来学习,并随机或从均值漂移聚类中初始化它们。(强调我的)

来源:https://arxiv.org/abs/1508.00021

我希望你喜欢这种对深度学习大师如何思考的窥视。如果这些课程对你来说都不陌生,那么恭喜你——你正在向深度学习大师迈进!

(如果您觉得这篇文章有帮助,您可能会发现这些感兴趣的

建立人工智能公司的经验

原文:https://towardsdatascience.com/lessons-from-building-an-ai-company-feb7c8302795?source=collection_archive---------61-----------------------

用科幻小说来理解机器学习产品的市场

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

Unsplash 上由 Franck V. 拍摄的照片

作为第一次创始人,我发现自己经常问*“我们试图解决什么问题”,很少问“技术的最终目标是什么,我们正在做的事情如何与之相适应。”虽然你只问第一个问题肯定能找到适合产品市场的答案,但如果不问第二个问题,我真的无法回答个人问题我为什么要这么做。我还认为,能够回答第二个问题的公司有更高的增长上限——几乎所有最大的科技公司都遵循这一模式。*

首先让我们考虑第二个问题的第一部分,人工智能技术的最终目标是什么;然后我们可以考虑一家公司如何融入其中。我喜欢通过科幻小说来想象这种“某一天”的可能性。阅读、写作或观看关于我们未来的故事,并注意我们在乌托邦、甚至反乌托邦中的想象,可以提供一个详细的起点;然后我们可以反向工作来理解一个人工智能公司的一部分。

写起来似乎很傻,但首先影响我对未来 AI 愿景的故事之一是钢铁侠。工程师的超级英雄托尼·斯塔克成为了我们这一代仁慈的天才发明家的原型,他的虚拟助手则是不那么过时的哈尔。

在《钢铁侠》中,我们的主角构建了一个能够提供他想要的一切的人工智能,所以让我们分解他构建的每个功能,并将其与当今存在的人工智能产品相关联,以及仍然存在的障碍:

  • 大规模索引信息,为神经 QA 和信息检索提供结构化和非结构化数据表示的无缝支持— Google
  • 基于一组公理合成答案,本质上是一种具有自然语言接口的可扩展语言— Wolfram
  • 自动建模物理和数字系统的接口,然后测试并综合或部署它们— CAD/3D 打印和 API 设计、无代码软件产品、代码/文档生成器
  • 通过虚拟人工智能界面有效地实现物理对象的移动。— 亚马逊机器人、Alexa、 AI 物流解决方案。
  • 任何地方的一切都被连接起来,以提供基于人工智能的实时可观察性和控制— 物联网、可穿戴设备、iPhone、Android、微型边缘神经网络、脸书的无人机互联网基础设施、智能汽车
  • 自我修复技术— 可观察性/测试框架/机器学习异常检测
  • 永不中断的技术,因此您可以在生活中依赖它,它是安全的,但却是分布式的——以其最简单的形式 CI +测试,但最终是 CoqPL 和基于证据的“不可破解的”形式化可验证系统
  • 个性和乐趣— 生成文本网络,例如拥抱脸、人工智能地牢、语法

**这些人工智能特性中的每一个都对应着一个或多个公司目前正在争夺的一块市场。**通过了解人工智能公司试图解决的整个组合问题,我们可以确定共同的障碍和相应的合作机会,如机器学习产品,这将有助于其他机器学习产品的创建。只有采取这种宏观观点,我才能开始说服自己,今天市场上的哪些人工智能产品实际上会让世界变得更好。

虽然这种分析可能为个人能够从今天开发的一些人工智能技术中获得什么提供了一个有趣的背景,但它缺乏人工智能能够为社会提供什么的细节。在我的下一篇文章中,我将提供更多的例子,让我们探索人工智能和现有社会结构之间的关系。

从我第一次卡格尔比赛中得到的教训。

原文:https://towardsdatascience.com/lessons-from-my-first-kaggle-competition-f51b61444115?source=collection_archive---------23-----------------------

我是如何选择参加我的第一个 Kaggle 比赛的,我从比赛中学到了什么。

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

图片来自皮克斯拜约翰逊·马丁

一点背景

我发现在一个新的编程领域开始有点令人畏惧的经历。我从事编程已经有 8 年了,但是直到最近我才对数据科学产生了浓厚的兴趣。我想分享我的经验来鼓励你也去冒险!

我开始用几门 Kaggle 迷你课程涉足这个庞大主题的海洋。我不需要学习如何用 Python 来写,但是我需要用工具来装备自己,以完成我想要的编程。首先是机器学习简介——这似乎是一个很好的起点。作为这门课的一部分,你要参加一个课程竞赛,但是即使完成了,我也没有准备好参加公开竞赛。提示中级机器学习,在那里我学会了使用一个新的模型,以及如何更深入地思考一个数据问题。

选择比赛

我花了一些时间来选择合适的比赛。我不想只是尝试用数据集做一些事情,因为我想看到我的进步并评估我的成功,但我也不想因为无法实现任何目标而感到难过。有了目标指引,感觉也像是一张不错的安全毯。

有一场比赛使用的数据与课程中的比赛相同,但我想要一些不同的东西,但使用了我学到的技能,主要围绕数字数据来预测结果。《泰坦尼克号:灾难中的机器学习》看起来不错,它的标签是“入门”。我没有因为做得好而赢得任何东西,这可能会令人厌烦。但是,你必须评估:你为什么要参加比赛?在我的数据科学旅程的这一点上,我希望提高我的知识并应用我所学的知识。

我学到了什么?

*简答:*相当多。既有关于自己的,也有关于如何思考一个数据科学问题的。

长答案:

  1. 我可以应用我所学的知识 —这可能是一个显而易见的问题,但是能够向自己证明我可以做到这一点,而不需要遵循一步一步的指导,这很好。
  2. 我能发现错误并利用我的技能解决它们——我提交的第一份报告得了 0.0000 分,也就是说,它没有正确预测任何事情。我的第一反应是沮丧和不安。我真的以为我会有所成就。结果是,我的输出是浮点类型,而不是整数。一个小小的改变,突然间我有了大约 70%的成功率。
  3. ka ggle 社区充满了知识 —一开始我不想看其他已经分享的笔记本,我想先自己尝试一下。我仍然认为这是一个好方法,但是在我自己提交了几个解决方案后查看它们,让我了解了我还不知道的东西,包括数据和新算法的方法。我甚至公开分享了我的笔记本,以防它对其他人有用,或者我收到了关于改进的反馈/建议。
  4. 在下一次开始之前,一些计划可能会有所帮助——我是如此热衷于投入其中,以至于我看了看给出的数据,做了一些快速观察,然后就开始编写代码。看过其他解决方案/教程笔记本后,我开始更多地了解在数据中寻找什么以及解决问题的不同方法(以及为什么!)我发现的事情与我做过的事情没有太大的不同,但它们是更深入的解决方案;下一步是从我所做的开始。
  5. 我喜欢解决这类问题,并想做得更多——如果这是我正在考虑从事的职业,这一点很重要。我只打算在上面花一个小时,当我再次抬头时,已经过了 4 个小时。

后续步骤

展望未来,我渴望发展我的数据技能,我认为 Kaggle 是一个开始的好地方。我还没有完善我的泰坦尼克号比赛的解决方案,但是我从这次经历中学到了很多。

我想在 Kaggle 上尝试另一场比赛,但速度要更有分寸。我会先拿起笔和纸坐下来,决定每列数据是如何相关的,以及我可以有效和高效地处理数据缺口的方法。

我也想扩大我的知识面,不仅深入研究数字数据和预测的方法,而且深入研究文本分析和图像识别。这将为我打开更多的大门,无论是探索新事物还是尝试更多的比赛。

如果你正在考虑进入数据科学领域,或者也许你已经进入了这个领域,并且想要更多的实践,我真的建议试试 Kaggle 竞赛。

从打击暗网市场中吸取的教训

原文:https://towardsdatascience.com/lessons-from-scraping-a-darknet-market-63e4ca546c18?source=collection_archive---------40-----------------------

我从研究一个垂死的市场中学到了什么

伦理学笔记

在写这篇文章的时候,我试着坚持一些原则,试图平衡分享这些信息的好处和风险——我把它们列在下面:

  • 本文不会教你如何选购药品。我故意没有详细描述任何访问 DNMs 的步骤。非法药物是危险的,不好的,你在这里不会学到如何得到它们。
  • 我对数据进行了匿名处理,删除了可能与其他平台或个人相关联的用户名——卖家用户名已被替换为唯一的号码。除此之外,我使用的所有数据和代码都可以在这篇文章的底部访问和链接
  • 任何访问大同协会的人都可以访问我使用的任何数据——我没有使用任何隐蔽的方法或花哨的代码来访问任何东西

我知道有些人可能会有不同的看法——我觉得这些讨论最好在公开场合进行,而且遮遮掩掩不是保护人们安全的特别好的方式。

4 月 20 日,我决定通过搜集和分析暗网市场(DNM)的内容,来尝试和使用我那生疏的数据科学工具集。我希望分析随着社会距离措施的放松(例如,被大肆吹捧的与暴力的联系),波动的药品价格的影响,但是,正如很快将变得清楚的那样,情况合谋破坏了我的狡猾计划。

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

来自 darknetstats.com 的大同协会截图

这不是一篇期刊文章,我不是统计学家/数据科学家,我的数据集可能不能代表黑暗网络的其余部分——我肯定我犯了很多错误,请在评论中告诉我(建设性地)这些错误……但这是一次有趣的经历,我希望值得分享。

访问 DNMs 在技术上并不复杂,但它是迟钝和不直观的——晦涩和摩擦是访问的真正障碍。你必须运行 TOR,你不能只点击你找到的第一个谷歌链接…但这也不会花费太多的努力,因为有很多网站会收集现有市场的信息以及如何访问它们。在探索了几个选项之后,我选定了 Pax Romana(Pax Romana )( Pax Romana )( T15 ),它被描述为“一个新的黑暗网络市场,具有许多创新功能,可以减少网络钓鱼和退出欺诈”,它显然是从 3 月初开始出现的,但由于新手友好的流程和安全功能,以及在登录时迎接你的马库斯·奥勒留(Marcus Aurelius)令人放心的照片,它已经积累了大量的客户基础。

它的结构也很好,有一个明确的“药物”类别,包含大约 200 页的产品。在稍微调整了一下我的代理设置后,我让 Web Scraper 忙碌地浏览了几百个页面,从 4 月 21 日到 25 日我每天都在运行这些页面。

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

darknetstats.com 大同协会的现状

4 月 25 日,大同协会被黑了。当我在 26 号试图登录时,我得到了一个错误 404,网站再也没有回来。

我分析不断变化的药品价格的计划被毁了,但我也无意中记录了罗马的末日。

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

来自 darknetstats.com 的用户评论

聚集和清理

考虑到这一点,我开始清理和分析我的数据集,它由 10930 行组成,代表每天的广告运行,其中 3149 个是独特的广告(分成每天的 CSV 文件)。

我的主要挑战是将每个广告归类到特定的物质类型——大同协会没有被归类到“毒品”之外,所以我必须有点创造性才能获得有用的数据。我使用 FuzzyWuzzy python 库迭代广告中的每个单词,寻找常见的药品名称。

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

摘自我的药物词典

然后,我使用各种痛苦的正则表达式字符串来提取视图、销售额、来源国和目的地、价格、卖家详细信息,以及我能找到的几乎所有东西,而又不会让我太紧张。

我在这里学到了我的第一课:毒品市场一片混乱。 Pax Romana 的设计实际上非常有用,它具有列出单位重量价格的功能,使顾客能够快速找到值得购买的产品。

剧透:大多数毒贩不喜欢清晰的定价结构。

在绝大多数的列表中,不是使用这个功能列出它们的价格,而是围绕产品的信息被打包到标题中,这导致了折衷的和几乎难以理解的产品数量、描述和定价——我已经强调了几个特别惊人的例子。

15 重新启动销售!PAX 上最便宜的 20 x 3mg Xanax 绿巨人(+20%免费)!

大量药丸的单一广告也很常见——当你计算药丸的数量和每颗药丸的重量时,享受测量每卷价格的乐趣。我想这就是试图理解板球的感觉。

’ SALESALE’’ 2000 x ‘XTC’BENTLEY 药丸’’ 240 毫克’ '跟踪

尽我所能,我试图从所有这些广告中提取价格信息、重量和药丸数量。最终,我有了 6193 个条目,其中我对药物名称(定义为与我预先定义的名称之一相似超过 85%)有信心,并有了每重量的价格(理想状态,或者如果不是从描述中提取的),从 1800 个独特的广告中创建。

分析

我首先想知道一个广告会有多少浏览量,所以我计算了一个广告每天的平均浏览量。

每条广告每天不到 10 次浏览。考虑到网站上的广告数量,这表明有一个不错的客户群。然而,有多少客户群转化成了销售呢?

显然没有那么多——平均每天的广告销售额不到 0.1。

使用简单的线性 OLS 回归,浏览量似乎是销售的一个很强的预测因素(如我们的 R 为 0.6 所示,这意味着浏览量似乎占销售方差的一半以上),但系数仅为 0.015 左右,这表明需要额外的 66 次浏览才能产生额外的销售。

第二课?在网上卖毒品看起来很难。 也就是说,平均值掩盖了极端值,我相信我们都想知道是谁购买了互联网上绝大多数的垃圾广告……如果你有足够多的广告,谁会在乎转化率低呢?

考虑到这一点,我接下来调查了个人卖家:你友好的网上邻居经销商有多少广告,有多少真正成交了?

事实证明,就像在现实世界一样,大多数毒品交易者并没有赚那么多钱。在平台上的 95 个卖家中, 50%没有卖出一单— 无论他们设定什么价格。几个大玩家在争夺大钱,而其他人都在争夺残羹剩饭。

第二个有趣的发现是,大多数经销商不仅销售一种产品,事实上,有些经销商销售十种以上不同的物质。这甚至不是不同股的大麻:这是卖家出售医用阿片类药物,安非他明,苯并,类固醇…这里有一些认真勤奋的演员。与此同时,还记得我是如何强调平均值隐藏了极端值的吗?上面的 3d 散点图突出了一些最成功的卖家,即使他们的销量不多,但营业额也很高。例如,一个卖家卖出了 62 笔,平均价格为 5407 美元,而另一个卖家卖出了 136 笔,平均价格约为 1730 美元。

这些钱从哪里来,去了哪里?显然,我没有能力(或意图)跟踪用户,但大量的广告列出了产品将从哪里发出。虽然我们显然不能确认这些有多准确,但它们描绘了一幅有趣的画面。

美国、荷兰、德国、英国和西班牙代表了绝大部分的销售,并且考虑到卖家可以通过列出“全球”来模糊他们的位置,这些可能是最准确的。有趣的是,尽管所有这些国家都陷入了更深的封锁,但供应在一周内飙升,增长了近三分之一。

不过,总趋势再次掩盖了独特的趋势。许多国家在本周开始时下降,在周中达到平台期,然后随着周末的临近而攀升——在英国,整体供应萎缩,尽管没有更多数据,很难说这是自然变化还是由于封锁影响了更广泛的市场。然而,总的来说,供应量大幅增加——我认为这是由于季节变化(可能在月底或周末前),尽管社交距离可能是一个因素。

通过检查物质的市场细分,看起来这种增长不是由任何一种产品驱动的——虽然增长不是均匀的,但多种产品在一周内的供应量都有所增加。

为了试图理解这些变化,我更详细地考察了各个国家的市场。

我原以为可卡因、大麻或海洛因会是我们的首选药物,但可卡因只是被各种苯二氮卓类药物(通常用于治疗焦虑或恐慌发作,并以其商业名称出售,如 Xanax)所取代。

查看美国的图表,处方阿片类药物是一个明显的突出问题——这里的供应规模令人震惊,特别是与其他药物相比。

检查荷兰和德国的广告,我不禁认为这些差异可能是由大卖家造成的——尽管数量相当大,但这似乎太明显了,不可能是自然差异。

接下来,我研究了药品定价。正如我在上面提到的,这些数据非常混乱,我怀疑是由大量广告驱动的,这些广告旨在将流量导向其他地方,而不是实现真正的销售(例如,描述中给出的 Whatsapp 数字)。也就是说,通过只关注那些只卖出过一次的广告,我可以关注 760 个左右的独特广告的价格信息,这些广告实际上以规定的价格卖出了一些东西。

我们再次注意到难以置信的差异和大型玩家的影响——虽然大多数销售倾向于在 100 美元左右,但一些极端销售正在接近 1000 美元的价位。我希望绘制每克的价格能让数据更清晰,但坦白地说,这只是增加了混乱。

也就是说,往往会有一个一致的平均值,我相信,随着时间的推移,随着更多的数据,我们可以绘制出价格的变化。

那么,我的主要收获是什么?

  • 在线药品市场故意不透明和混乱——绝大多数广告并不推动销售,事实上可能被用来推动流量到更有效的平台。
  • 就像实体领域的交易商一样,大多数人可能并没有赚到多少钱。也就是说,上层的生活是美好的,重要的玩家可能会获得巨额财富,并经营几种不同的毒品。
  • 价格和购买数量相差很大,甚至在同类产品中也是如此。也就是说,大多数销售是在较小的价格范围内进行的,一个更大的数据集可能能够产生围绕药品市场波动的真实预测。

如果你想知道更多关于这些可视化背后的代码或数据本身,它们可以在我的 Github 上以 Jupyter 笔记本格式获得。Github 不能很好地运行可视化,所以我也把它们上传到了下面的 Google Collab。

## 可乐闪现

无服务器堆栈中使用 NLP 阻止未经请求的销售电子邮件的课程

原文:https://towardsdatascience.com/lessons-in-serverless-stacks-using-nlp-to-block-unsolicited-sales-emails-8fda116273e8?source=collection_archive---------46-----------------------

在本系列的第一部分和第二部分中,我描述了一个通过应用自然语言处理来阻止不请自来的销售邮件的系统。在培训和部署模型之后,我使用无服务器基础设施构建了整个应用程序,以了解开发这样一个系统的相对成本和工作量。这篇文章强调了我在旅途中学到的各种教训。如果你正在读这篇文章,我希望它能帮助你避免一些看手相的错误!

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

在整篇文章中,我使用“无服务器”来表示不需要永久基础设施的托管。图片由 Kewl@Pixabay ,CC0。

首先,我的系统概述

下面是我的应用程序的概述,为下面的部分设置上下文。

用户首先授权服务访问 Gmail。该授权使 Gmail 向 Google 发布/订阅主题发送新邮件。订阅者接收每条主题消息,并调用 API 端点来处理电子邮件(预测它是否是销售垃圾邮件)。如果 NLP 模型预测该电子邮件是垃圾邮件,那么该应用程序会让用户的 Gmail 回复发件人,提示他们通过求解验证码来解锁该电子邮件。如果销售人员解答了验证码,那么他们的电子邮件将被标记为未读,并被发送到用户的主收件箱。

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

下图提供了引擎盖下的更好视图:

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

我使用无服务器基础设施实现了上述所有模块,利用了 DynamoDB、Lambda 函数、SQS 队列和 Google Pub/Sub。

基于 Zappa 的无服务器机器学习模型

在这里,“无服务器”意味着不需要永久基础设施的托管。在这方面,“Zappa 使得构建和部署无服务器、事件驱动的 Python 应用程序变得非常容易。。。在 AWS Lambda + API 网关上。

这意味着无限扩展、零停机、零维护,而成本只是您当前部署的一小部分!

@ Gun.io

简单和多功能是 Zappa 最大的优势。虽然你可能会读到许多关于人们使用 Django web 应用程序的博客帖子,但 Zappa 也提供了通过 API 访问无服务器机器学习模型的交钥匙方法。

配置 Zappa

我强烈推荐阅读 Gun.io 的文档。在这里,我将把重点放在基础上,以突出 Zappa 优雅的简单性,同时提出一些教训。

首先,也是最重要的,导航到您的项目根文件夹,配置一个虚拟环境,其中包含您需要的所有库、依赖项等等。如果你不仅仅是在练习,考虑为你的 Zappa 应用建立一个 Docker 环境,因为“越接近(你的 Zappa 与 AWS lambda 环境相匹配),调试问题就越少。”重要的是,虚拟环境名称不应该与 Zappa 项目名称相同,因为这可能会导致错误。

$ mkdir zappatest
$ cd zappatest
$ virtualenv ve
$ source ve/bin/activate
$ pip install zappa

然后运行init为您的应用配置各种初始设置:

$ zappa init

打开zappa_settings.json文件来编辑或配置其他设置,比如确定哪个 S3 桶将存储 Lambda 函数工件。以下是我用过的:

{
    "dev": {
        "app_function": "api.app.app",
        "aws_region": "us-east-1",
        "profile_name": "default",
        "project_name": "serverless-ML",
        "runtime": "python3.6",
        "s3_bucket": "MY_BUCKET_NAME",
        "slim_handler": true,
        "debug": true
    }
}

注意,“app_function”: “api.app.app”行调用一个带有app.py文件的模块(文件夹)api,其中app = Flask(__name__)在这个目录树中:

~env$my_project_name
.
|- api
     |- app.py
|- ... 

最后,在您的环境中进行初始部署:

zappa deploy YOUR_STAGE_NAME

就是这样!如果您的应用程序已经被部署,并且您只需要上传新的 Python 代码,而不需要接触底层的路径,那么您可以简单地“调用zappa update YOUR_STAGE_NAME

加载模型和调用。Zappa 应用中的 Predict()

训练完我的模型后,将工件腌制成model.pkl文件,存放在 S3 桶里。然后使用 Boto3 库将模型加载到 Zappa 应用程序中。接下来,将输入 JSON 转换成符合模型的格式,并返回响应:

调用zappa update YOUR_STAGE_NAME,模型可以通过 API 访问。用 cURL 请求点击模型来测试它:

$ curl -F 'file=@payload.json' https://YOUR_ENDPOINT.execute-api.us-east-1.amazonaws.com/dev/handle_data_from_app

在您的 CloudWatch 日志中观察神奇的事情:

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

在您的无服务器 ML 模型中包含助手模块

上面设置中最棘手的部分突出显示在第 63–66 行,在这里我在__main__名称空间中调用我的助手模块preprocess。没有第 66 行,model.pkl文件执行各种转换,调用我的preprocess模块,但是产生错误,无法找到那个模块名。

这是因为,在酸洗我的模型之前,我使用了一个本地模块from helper import preprocess作为从.predict()内部调用的管道的一部分。所以当我想要重用那个模型时,调用它的环境并不相同。我花了几个小时试图找出如何让环境匹配。这是关键的一课:Zappa 将安装在虚拟环境中的依赖项和库打包成一个 zip 文件,然后上传到 S3,这就形成了 Lambda 函数的内容。本质上,

如果您不能或者没有将您的本地模块打包到虚拟环境中,那么它们就不存在于您的 Zappa Lambda 环境中。

此外,如果您的模型的.predict()有一个它正在使用的特定名称空间,那么您也必须完全复制它。这就是为什么我必须在应用程序的‘__main__’块中实例化from helper import preprocess。将它放在其他地方会导致路径与我的 pickled 模型.predict()中的管道所期望的不匹配。

通过无服务器网络应用程序将 Gmail 连接到我的 ML 模型

我创建了第二个 Zappa 应用程序来连接用户和我的 ML 模型(“服务”)。其核心是,该服务连接到用户的 Gmail 帐户,获取邮件,并将它们传递给模型,以便它可以预测内容是否是销售垃圾邮件。概括一下:

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

这个应用程序的内容超出了这篇文章的范围,所以我将把重点放在学到的东西上。

30 秒:支持 API 的 Lambda 函数的一个重要限制

在我的应用程序的第一个版本中,我从一个用户的 Gmail 帐户中取出一批 50 封邮件,并在 中运行.predict()一个函数调用 。尽管在我的 AWS Lambda 中尝试了 15 分钟的超时时间,但该功能仍然超时。我也尝试扩展 Zappa 设置中的timeout_seconds参数,但也无济于事。

瓶颈不是 Zappa 或 Lambda 函数,而是 Zappa 使用的 API 网关。如 AWS 文档中所述,“最大集成超时”为“30 秒”,不能根据要求增加。显然,函数继续在后台运行,但是在我的例子中,我需要一个响应。

另外,这个问题帮助我认识到我没有遵循无服务器技术的原则,这意味着利用并行、水平扩展。

提示 SQS!(懂了吗?;)

与其在一次 Lambda 调用中预测 50 多条消息,不如将这些消息在 SQS 中排队。然后 Zappa 可以使用 SQS 事件流触发.predict() 功能(例如,每条消息一次)。boom --水平扩展,无超时!

使用 SQS 事件触发 Zappa 函数

第一次,我手工配置了一个 Lambda 函数,通过 UI 控制台接受 SQS 事件。

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

然后我编写了 Lambda 事件来解析 SQS 事件,并调用 Zappa URL 端点:

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

虽然这相当简单,但它缺少 git 版本控制和命令行重新部署!幸运的是,Zappa 允许你通过 AWS 事件触发应用程序中的功能

首先,我将 Lambda 函数作为另一个 Zappa 函数移植到主app.py文件中:

def get_sqs_msg_and_call_predict(event, context):    try:
        for record in event['Records']:
            body = record["body"]
            resp = sqs_predict_label(body)
    except Exception as e:
        # Send some context about this error to Lambda Logs
        print(e)

然后我重新配置了zappa_settings.json来包含events:

"events": [
   {
       "function": "api.app.get_sqs_msg_and_call_predict",
       "event_source": {
            "arn":  "arn:aws:sqs:us-east-1:XXXXXX:YYYYY",
            "batch_size": 1, // Max: 10\. Use 1 to trigger immediate processing
            "enabled": true // Default is false
       }
   }
]

我花了几个小时试图为"function": "xxx"诊断合适的咒语。Zappa 官方文档提到"function": "your_module.process_upload_function".打算调用我的 Zappa 应用程序的主app.py部分的一个函数,我尝试了:

  • "function": "get_sqs_msg_and_call_predict"
  • "function": "app.get_sqs_msg_and_call_predict"
  • "function": "api.get_sqs_msg_and_call_predict"

所有这些都给了我这个错误的变体:

Traceback (most recent call last):
  File "/var/task/handler.py", line 609, in lambda_handler
  return LambdaHandler.lambda_handler(event, context)
  File "/var/task/handler.py", line 243, in lambda_handler
  return handler.handler(event, context)
  File "/var/task/handler.py", line 418, in handler
  app_function = self.import_module_and_get_function(whole_function)
  File "/var/task/handler.py", line 235, in import_module_and_get_function
  app_function = getattr(app_module, function)
AttributeError: module 'api' has no attribute 'get_sqs_msg_and_call_predict'
[123123] You are currently running on staging
[123123] module 'api' has no attribute 'get_sqs_msg_and_call_predict': AttributeError

重要提示:您必须考虑模块,因为它与您的根应用程序文件夹相关。如果您有这样的文件夹结构:

~env$project_name
.
|- api
     |- app.py
     |- templates
|- ...

正确的设置包括"function": "api.app.some_function_therein"。亲爱的读者,我希望这个细节能为你节省时间,减少麻烦。

事件触发 Zappa 函数中的“return”语句

在主app.py文件中处理 SQS 事件导致了一个不寻常的场景。这又是函数:

def get_sqs_msg_and_call_predict(event, context):    try:
        for record in event['Records']:
            body = record["body"]
            resp = sqs_predict_label(body)
    except Exception as e:
        # Send some context about this error to Lambda Logs
        print(e)

你会注意到上面的函数不包括一个return语句。尽管我尽了最大努力,我还是无法生成一个可接受的 return 语句。幸运的是,我的代码不需要,所以我决定跳过这一步,而不是纠结于处理这种情况的正确方法。

简而言之,问题是这样的:

**[1231231**] Result of zappa.asynchronous.route_lambda_task
[**1231232**] <Response 192 bytes [**200 OK**]>
[**1231233**] An error occurred during JSON serialization of response: <Response 192 bytes [**200 OK**]> is not JSON serializable
Traceback (most recent call last):
File "/var/lang/lib/python3.6/json/__init__.py", line 238, in dumps **kw).encode(obj)
File "/var/lang/lib/python3.6/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True)
File "/var/lang/lib/python3.6/json/encoder.py", line 257, in iterencode return _iterencode(o, 0)
File "/var/runtime/awslambda/bootstrap.py", line 145, in decimal_serializer
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <Response 192 bytes [**200 OK**]> is not JSON serializable

StackOverflow 提供了使用jsonify(response)使响应输出 JSON 可序列化的解决方案。不幸的是,在这种情况下这不起作用:

This typically means that you attempted to use functionality that needed to interface with the current application object in some way. To solve this, set up an application context with app.app_context().  See the documentation fo
r more information.: RuntimeError Traceback (most recent call last):
  File "/var/task/handler.py", line 609, in lambda_handler
  return LambdaHandler.lambda_handler(event, context)
  File "/var/task/handler.py", line 243, in lambda_handler
  return handler.handler(event, context)
  File "/var/task/handler.py", line 419, in handler
  result = self.run_function(app_function, event, context)
  File "/var/task/handler.py", line 282, in run_function
  result = app_function(event, context)
  File "/tmp/push-email-hand/api/app.py", line 1216, in get_sqs_msg_and_call_predict
  raise e
  File "/tmp/push-email-hand/api/app.py", line 1205, in get_sqs_msg_and_call_predict
  sqs_predict_label(body)
  File "/tmp/push-email-hand/api/app.py", line 1249, in sqs_predict_label
  return make_response(jsonify(response), status)
  File "/tmp/push-email-hand/flask/json/__init__.py", line 358, in jsonify
  if current_app.config["JSONIFY_PRETTYPRINT_REGULAR"] or current_app.debug:
  File "/var/task/werkzeug/local.py", line 348, in __getattr__
  return getattr(self._get_current_object(), name)
  File "/var/task/werkzeug/local.py", line 307, in _get_current_object
  return self.__local()
  File "/tmp/push-email-hand/flask/globals.py", line 52, in _find_app
  raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.

我怀疑这是因为我使用from zappa.asynchronous import task调用了一个异步任务,这不知何故改变了应用程序上下文。如果你解决了这个问题,我很想听听你的意见!

通过 Zappa 配置环境变量

zappa_settings.json中设置环境变量并传入代码环境非常容易,就像这样:

{
    "prod": {
        "app_function": "api.app.app",
        # . . . #
        "environment_variables": {
            "code_env": "prod"
        }
    }
}

注意一个重要的细微差别 : environment_variables对于你的应用来说是本地的,在运行时被注入到 Lambda 处理程序中。换句话说,environment_variables不会设置 AWS Lambda 环境变量:

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

然而,这些变量有时是必需的,例如当您想要设置凭证时。解决这个问题的一个方法是导航到 UI 控制台并在那里设置它们。这种方法对于部署多个环境(例如,staging-branch1、staging-branch2、测试、生产等)并不理想。).更好的方法是使用 Zappa 的aws_environment_variables配置设置:

{
    "prod": {
        "app_function": "api.app.app",
        # . . . #
        "**aws_**environment_variables": {
            "GOOGLE_CLIENT_ID": "XXX"
            "GOOGLE_CLIENT_SECRET": "YYY"
            "GOOGLE_REFRESH_TOKEN": "ZZZ"
            "code_env": "prod"
        }
    }
}

解析 Gmail 邮件

许多人写过关于从 Gmail 邮件中解析电子邮件内容的复杂主题。长话短说,电子邮件有多种形状和大小(text/plaintext/htmlmultipart等)。).如果我只解析了text/plain邮件,我会错过大量的信息。因此,我包含了下面的代码,希望能帮助那些不想从头开始重写的读者。此外,令人沮丧的是各种 Python 库不能很好地协同工作。所以我把我用过的版本包括在下面:

注意:上面的功能并不完美,但是它完成了任务。如果你最终实现了这个,请随时给我发送你的想法。

处理“至少一次交货”

我从谷歌的发布/订阅系统中调试了一个与“至少一次交付”相关的问题,获得了很多乐趣。作为后台,我的应用程序在用户的 Gmail 帐户上调用[.watch()](https://developers.google.com/gmail/api/reference/rest/v1/users/watch),它将“邮箱当前历史记录的 ID”发送到一个 Google Publisher 主题。然后,一个连接的订户向我的 Zappa 端点发送推送通知,该端点处理获取最新消息并将其排队到 SQS 所需的historyId

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

在我的控制台上玩 Gmail API 时,我得到的印象是订阅者推送通知提供了一个historyId,用于检索自上次推送通知以来的邮件*。换句话说,我认为在time=2接收historyId意味着我可以检索从time=1time=2的所有消息。所以我在这个假设的基础上建立了我的应用程序的逻辑,它看起来很有效…*

然后我发疯似的调试为什么系统有时会从一个historyId获取 0 条消息,而其他时候会莫名其妙地获取几条消息。

至少一次传递意味着“消息有时可能不按顺序传递或者传递多次。”

几天后,在用记录器和跟踪器测试了这个应用程序后,它给了我很大的启发。当订户第一次发送消息时,它提供的是最新的historyId,没有新消息要获取。但是由于至少一次递送,订户可能会无序地或多次重新递送消息。如果订阅者重新发送了一条消息并且用户在第一次订阅者推送后收到了新邮件,那么系统将获取新邮件— 给我一个错误的印象,即我之前的逻辑工作正常。#facePalm

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

Alex E. Proimos 提供的图像,cc-by-2.0。

我的解决方案是为每个用户构建一个historyId缓冲区,使用 (n-1) historyId获取消息,然后用最新的historyId替换第二个最新的值:

构建幂等服务

这是 Google 发布/订阅文档中的另一个亮点:

通常,发布/订阅会按照消息发布的顺序将每条消息传递一次。但是,消息有时可能会不按顺序传递或传递多次。一般来说,支持多次传递要求您的订户在处理消息时是等幂的

简而言之,一个函数是幂等的,如果它可以根据需要重复或重试,而不会造成意想不到的影响。考虑到 Gmail 的推送消息可能会重复到达,这种方法很有用。因此,我没有一次又一次地重新处理相同的消息——浪费资源——而是建立了一个 DynamoDB 表,存储每个 msg_id 以供查找。如果找到,该消息将被丢弃,不再进一步处理。

使用 AWS SAM 模板部署资源

无服务器开发的最大好处之一是能够从命令行部署多个互连的资源。假设一个应用程序需要六个 Lambda 函数、四个 DynamoDB 表、两个 SQS 队列和一个 API 网关。使用 AWS CLI 或 UI 控制台会令人厌倦。由于 AWS 无服务器应用程序模型(AWS SAM ),这项任务非常简单。但是如果你不熟悉 serverless、CloudFormation 或 SAM,那么管理这些资源的模板文件读起来就像天书一样。因此,让我们从快速剖析 SAM 模板开始。

AWS SAM 模板剖析

"模板是一个 JSON 或 YAML 格式的文本文件,描述您的 AWS 基础设施。"以下代码片段显示了一个 SAM 模板及其各个部分:

SAM 模板包含一个Transform:来标识要使用的 AWS 无服务器应用程序模型(AWS SAM)的版本。然后模板为无服务器应用设置Globals:设置。例如,我为我的 API 资源设置了 CORS 策略。接下来,模板标识在运行时通过命令行传递到模板中的Parameters:。之后,模板有了Resources:,这里定义了 Lambda 函数、DynamoDB 表和其他资源。

解包 Lambda 资源

Lambda 函数有一个逻辑 ID,它是模板文件中资源的唯一名称。在下面的例子中,逻辑 ID 是SomeLambdaFunction:

Path: /your_path标识调用这个函数的 API 路径,而RequestParameters:告诉模板预期的变量。Variables:是 Lambda 函数的本地环境变量,它被证明对管理数据库连接等非常有用。Policies:部分标识了该功能的权限。例如,如果该函数要将项目放入 DynamoDB 表中,那么您必须指定相关表的动作和 ARN。最后,行CodeUri: functions/your_event/将您的资源映射到项目文件夹中的 Lambda 处理程序代码。例如,上面的 Lambda 函数应该具有这样的文件夹结构:

*~env$my_SAM_project
.
|- functions
     |- your_event 
          |- __init__.py
          |- app.py
          |- requirements.txt
|- ...* 

文件app.py然后执行您需要的任何功能。举例来说,在我的应用程序中,app.py使用查询字符串参数来更新 DynamoDB 表:

注意这一行: table = ddbclient.Table(os.environ['DDBTableName'])因为它展示了如何使用通过模板文件传递给 Lambda 函数的环境变量。在下面的一节中,您将看到这个强大的特性如何使用单个模板文件来帮助管理多个环境和表。

完成 Lambda 函数的编码后,必须使用 AWS CLI 构建 SAM 模板:

*$ sam build*

如果您仍然在对app.py文件进行更改,那么我建议您删除 AWS SAM 构建工件,以便您的代码更改立即生效:

*$ rm -rf .aws-sam/**

否则,您必须在每次代码更改后重新构建 SAM 模板。这很快就会变得很烦人。如果您对模板文件进行了任何更改,请不要忘记重新构建 SAM 模板!

最后,在本地测试您的功能后,您可以部署您的 SAM 模板,如下所示:

*sam deploy --template-file .aws-sam/build/template.yaml --stack-name YOUR_STACK_NAME --s3-bucket YOUR_S3_BUCKET --capabilities CAPABILITY_NAMED_IAM --region us-east-1 --parameter-overrides ParameterKey=DDBTableName,ParameterValue=MyUserTable*

鉴于部署 SAM 模板需要多长时间,您应该在本地测试您的功能和资源。这超出了这篇(已经很长的)文章的范围,所以我把这篇优秀的指南留给你。

从单个 SAM 模板管理多个环境

使用模板文件非常简单,但是当您利用多种环境,比如stagingtestingproduction时,会有些复杂。有人建议为此维护多个模板文件甚至多个 AWS 账户。我认为这些建议没有说服力,因为它们会引起其他问题,例如:

  • 确保多个模板实际上是相同的,或者
  • 管理由于使用多个 AWS 帐户而产生的计费、用户和安全问题。

更好的方法需要一点设置,但是提供了一个使用单个模板文件管理多个环境和资源的优雅解决方案。

第一步是在模板文件中引入一些参数:

然后,您可以在模板文件中使用这些参数来动态构建每个 Lambda 函数、DynamoDB 表等等。以下是我的 SAM 模板中的一个示例:

然后我更新了我的~/.bash_profile来包含这个脚本:

现在,我可以像这样部署整个无服务器堆栈:

*$ deploy_sam "staging"*

由于使用了Resource: > Environment: > Variables:!Sub命令,每个部署都为我提供了名称不同但完全相同的资源——比如staging_master_sales-spam-blocker_MyUserTable——在表和 Lambda 函数之间自动、正确地路由:

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

用 SAM 事件在 DynamoDB 中实现聚合表

对于上下文,我的应用程序有一个“信用”的概念,用于解除销售人员向用户发送电子邮件的封锁。如果发件人的信用点数超过零,则发件人的电子邮件将被自动解锁,他们的信用点数将减少。但是如果一个发送者没有积分,那么他们会被发送一个新的验证码来获得更多的积分。因此,知道给定发送者在某个时间点有多少信用是至关重要的。

在典型的关系数据库中,我会用datetimesender_id数据插入每个 Captcha 事务。然后,我将查询该表,以获得给定日期时间的sender_idSUM(credits)。我在 DynamoDB 中寻找一个类似的函数,但结果是不支持聚合——像SUM()MAX()

于是开始寻找答案。幸运的是,我在聚合表上找到了彼得·霍奇金森的这篇优秀的文章。以下是关键的见解:

使用 DynamoDB Streams 将数据库事件发送到下游的 Lambda 函数,该函数动态执行聚合。

以下步骤演示了如何使用 AWS SAM 和 Python 3.6 实现这一点。对于额外的上下文,此图有助于可视化下面描述的交互:

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

虽然我的应用程序有许多其他资源,但本节主要介绍计算聚合表的要点。

首先,用两个 DynamoDB 表和一个 Lambda 函数配置一个 SAM 模板,如下所示:

请密切注意第 41–46 行,它授权 Lambda 函数访问目标表上的流。

与使用 API Events:类型的其他 Lambda 函数不同,例如:

*Events:
   YourEvent:
      Type: Api
      Properties:
      Path: /your_path
      Method: post
      RequestParameters:
         - method.request.querystring.userId
         - method.request.querystring.credentials
      RestApiId: !Ref MyApi*

您必须配置 Lambda Events:来使用 DynamoDB 流,如下所示:

*Events:
  DDBEvent:
    Type: DynamoDB
    Properties:
      Stream:
        !GetAtt UserTable.StreamArn StartingPosition: TRIM_HORIZONBatchSize: 1
      Enabled: true*

现在,每当数据被插入到 DynamoDB 中时,您的 Lambda 函数将接收这样的事件:

Pro 提示:将上述事件保存在一个 JSON 文件中,比如dynamodb-event-update-user-msg-id.json,通过命令行在本地测试您的设置:

*$ sam local invoke AggDailyCreditsPerSender --event dynamodb-event-update-user-msg-id.json --parameter-overrides ParameterKey=Environment,ParameterValue=localhost ParameterKey=paramAggDailyCreditTable,ParameterValue=AggDailyCreditTable --docker-network sam-demo*

接下来,您必须配置 Lambda 函数处理程序来执行聚合计算。在下面的代码片段中,我查询聚合表以获取当前余额,计算新的运行余额,并更新聚合表:

转眼间。每次用户表记录一个新的msg_id,Lambda 函数都会计算一个给定发送者的当前余额。

现在要访问这些数据,我们需要另一个 Lambda 函数来从聚集表中get_item:

为了完整起见,并且为了突出您可能遇到的问题,这里有一个附带的 Lambda 函数来从聚合表中获取数据:

DynamoDB 对所有数字数据类型使用通用的'N'名称,而不是指定“Integer”或“Float”类型。因此,尽管在聚合计算中使用了整数,{k: deserializer.deserialize(v) for k,v in low_level_data.items()}还是输出了Decimal('X')对象。在 GitHub 上,这个问题已经闹得沸沸扬扬,但是将 Decimal 对象强制转换成 integer 也很好(如上面第 44 行所示)。

这样,应用程序可以在毫秒级内检索任何发送者的当前累积信用余额。此外,与 SQL 聚合查询不同,尽管发送者或事务记录的数量在快速增长,查询性能也不应下降。

无服务器聚合函数的替代解决方案

一个诱人的替代方法是使用 AWS Aurora 无服务器来维护 SQL 逻辑,同时利用无服务器技术。来自 AWS:

Amazon Aurora Serverless 是针对 Amazon Aurora (兼容 MySQL 和 PostgreSQL 的版本)的按需自动扩展配置,其中数据库将根据您的应用程序需求自动启动、关闭和扩展容量。

最终,我更喜欢 DynamoDB 的闪电般快速查询,该应用程序主要需要对潜在的数百万条msg_idsender_id记录执行简单的查找。也就是说,我很想在以后的文章中对这两种技术进行基准测试!

未来的方向和离别的思绪

我希望这篇文章能帮助你诊断、调试或避免无服务器 ML 项目中的问题。尽管对这项新兴技术了解很多,但我很清楚,我只是触及了皮毛。以下是我未来想探索的一些领域:

  • 监控我的 ML 模型的正常运行时间、偏差和漂移;
  • 配置 A/B 测试框架,其中我可以将实时数据发送到当前模型(A)和第二模型(B ),以测量比较 F1 分数;和
  • 为审计和再现性建立管道。

如果您感兴趣,请联系我,这样我们可以一起合作和学习!

最后,我要指出的是,虽然我拥有电气工程学位,但我的职业生涯主要集中在产品领导上。在那个角色中,经常很容易要求这个或那个功能加上紧张的截止日期。设计、编码和测试这个应用程序迫使我“穿着开发人员的鞋子走了一英里”,我的脚很痛(以一种好的方式)!所以,我将以一个提醒结束我的演讲——对我未来的自己和其他产品负责人—我们应该尊重和钦佩我们的工程团队成员

只要有机会,就为开发人员的努力鼓掌,尤其是当他们预见到未来的麻烦或者解释为什么看似“简单”的请求并非如此时。

让这个帖子成为可能,要感谢的人太多了。这里有几个人极大地指导了我的旅程: Gun.io (关于Zappa的精彩文档);Sanket Doshi(关于用 Python 阅读电子邮件);Fran ois Marceau(关于在 AWS Lambda 上部署 ML 模型);Lorenz Vanthillo(关于使用 AWS SAM 部署本地无服务器应用)谢谢大家!

“如果我看得更远,那是因为我站在巨人的肩膀上.”
——艾萨克·牛顿1675 年

部署我的第一个 ML 项目的经验教训

原文:https://towardsdatascience.com/lessons-learned-deploying-my-first-ml-project-80e8b44bcd21?source=collection_archive---------23-----------------------

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

弗兰基·查马基在 Unsplash 上拍摄的照片

启动我的第一个生产就绪 ML 项目后的五点收获

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

来源: Xkcd

背景

我是一名软件工程师,为小说家工作,为公共图书馆制作软件。读者咨询也就是书籍推荐是我们的饭碗。想想网飞,但对于书籍!我们有两级推荐:A 级,我们的内部专业人员,如图书管理员等。为最受欢迎的书籍创建手工推荐,B 级推荐由推荐系统使用我们关于书籍的专有元数据生成。

我们的专有元数据是一个宝库:数十万本有吸引力的术语、流派和主题标签的书籍。我们的内部编目员已经花了数年时间对书籍进行编目并添加元数据。但这也是一个瓶颈,因为他们必须手动阅读书籍摘要和评论,以便添加适当的元数据。

元数据的例子:appealpacing.fast .快节奏,appealstory.issue .面向问题,appearl character . lgbtqia _ diversity,appearl tone .发人深省等。

我的项目很简单:给定我们的标签书评宝库,训练一个多标签分类器,它将预测上诉条款。这将加快我们的编目过程,消除我们的瓶颈。

五个外卖

1.理解数据的重要性

我的机器学习教育包括三年前在大学期间学习的两门课程,加上通过观看吴恩达和阅读来自媒体/数据科学的文章进行的自学。一言以蔽之,没有正规的 ML 教育。作为一名初学机器学习的实践者(我不敢称自己为机器学习工程师),我做了初学者做的事情:先编码,后思考。

我开始研究(阅读谷歌)各种多标签文本分类解决方案,并逐一实现,比较结果,并对缺乏准确性感到沮丧。在尝试了第六个或第七个分类器后,我踩下刹车,后退了一步。然后我做了我之前应该做的事情:了解我的数据的前景。在做了一些基本的数据探索后,我发现我的数据集严重不平衡。在我可能的 158 个标签中,只有 20 个有相当数量的样本。还有,158 个独特的标签!

在将数据集分成单独的组(即 appealtone、appealwritingstyle 等)后,我使用 k-nearest neighborhood(ml KNN)的改编版本获得了最佳结果(性能+训练速度)。分而治之!下一步是使用 BERT 训练一个。

2.创建模型只是工作的一半

所以你创造了这个模型,得到了最佳的性能和很高的精确度。现在怎么办?你跟踪的朱庇特笔记本没有提到那之后的生活。以下是我和我的团队为完成这个项目必须做的事情:

  • 创建一个 Flask API 端点,这样我们就可以发送一个包含新书评论的 POST 请求,并检索预测标签的列表。
  • 将 API 部署到 AWS,这样我们就可以使用它了。
  • 将模型工件保存到 AWS S3 (AWS4?).创建一个云形成模板来自动旋转实例。
  • 为 API 编写自动化测试。
  • 创建一个 React tester 应用程序,以便我们的编目员可以玩分类器,并对有效性进行手动 QA。
  • 部署 React 应用程序。
  • 为一切创建自主部署流程( CI/CD )。

Protip: 使用 Cortex 为您的模型实现 CI/CD 自动化。

创建模型/分类器是工作的一半。可能是四分之一。老实说,取决于你的项目。当你做计划时,确保你考虑到所有这些辅助工作。

Protip: 用 Python 脚本编写你的 ML 代码,而不是直接在 Jupyter 笔记本上写。否则,审查笔记本中的代码变更几乎是不可能的。此外,这使得测试更加容易。

3.你不需要成为一个 ML 专家

让我以这样一句话开始这一部分:如果你是一名专家,那就更好了。显然。但是如果你不是,这并不意味着你不能创造一个 ML 驱动的产品!正如我之前所说,我没有受过正规的 ML 教育。诚然,学习曲线非常陡峭,但并非不可逾越。我每天都觉得自己像个冒名顶替者,但当我看到我们的编目员使用我们的上诉预测器时,我感觉好了一点。

ML 生态圈太神奇了!像熊猫,scikit-learn,pytorch,huggingface 等图书馆。让机器学习大众化。您可以用不到 20 行代码创建自己的模型!有大量的教程会在整个过程中帮助你。如果你有毅力和决心,你可以很容易地创造自己的 ML 动力产品。它可能不是最尖端的型号,但它是你的型号!你边做边学。没有什么能打败它。

记住,只要你在解决一个问题,并且有人从中受益,就有价值。最终用户并不关心你的模型的 F1 值是 88%还是 90%。

4.敏捷开发的重要性

软件工程是解决问题:你有一个需要解决的商业问题。对于我来说,我们希望减少编目瓶颈,加快过程,节省时间和资源。永远让问题引导你找到解决方案。而不是相反。

你想尽快得到你的产品的实际反馈,然后利用反馈对它进行迭代。对我们来说,就是把一些东西交给我们的编目员,这样他们就可以利用他们的领域专业知识来验证预测器的结果。然后,我们使用他们的反馈来调整模型。

5.数据为王

你的模型和你的数据一样好。这是没有办法的。在我看来,ML 中最困难的事情之一是管理一个全面的数据集。幸运的是,我已经准备好了。这加快了整个过程,让我的生活更轻松。此外,我们的数据由领域专家标记,这意味着它们非常准确,这反过来使我们能够创建一个相当准确的模型。

在开始自己的项目之前,请确保您的数据是干净的。了解您的数据环境。不要重蹈我的覆辙。先做一些数据探索。看看你是否可以使用像 SMOTE 这样的工具来增强它。记住,即使你的模型不像你希望的那样精确,你也能在这个过程中学习到一些新的东西。从长远来看,这是有回报的。

从(几乎)未能在云中部署简单的机器学习模型中吸取的教训

原文:https://towardsdatascience.com/lessons-learned-from-almost-failing-to-deploy-a-simple-machine-learning-model-in-the-cloud-69f041704f03?source=collection_archive---------49-----------------------

了解在启动人工智能和云项目时应该避免犯的主要错误。

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

萨姆·穆格迪钦在 Unsplash 上拍摄的照片

通过这篇文章,我们将向您展示我们在一个旨在云中部署年龄猜测神经网络模型的简单项目中所犯的主要错误。

令人欣慰的是,我们能够发布一个足够好的项目版本,可以在这里访问。它的源代码可以在专用的 GitLab 链接中找到。

项目背景、目标和方法

作为一名网络安全顾问和一名为大公司工作的初级软件工程师,我们一直对云感兴趣,并希望了解这项技术如何用于开发简单的人工智能应用程序。

有了新冠肺炎和洛克德斯,我们开始有了许多想法,这些想法结合了我们在短暂的职业生涯中学到的技能。然而,我们决定在进入一个更复杂的项目之前,先从一个非常简单的想法开始:部署一个简单的、可用于生产的 web 应用程序,该应用程序将通过一个训练有素的神经网络来猜测人们的年龄。

我们专注于创造过程,学习做事的“最佳方式”。我们定义了以下约束条件:

  • 遵循“最先进的”实践来训练我们的模型和部署我们的产品;
  • 每月的运营成本为 0€;
  • 由于无服务器服务,有一个可以“无限”扩展的产品(在这种情况下,我们知道 0€/月运行成本只有在很少或没有流量的情况下才有可能);
  • 构建一个用户友好的“最终产品”,让人们从中获得乐趣;和
  • 享受建造过程。

基于我们的项目背景和目标,我们的方法是遵循以下步骤:

  1. 获取大量图像及其相关年龄的数据集
  2. 选择最先进的卷积神经网络(CNN)来训练(在云上)功能年龄预测器
  3. 将这个训练好的神经网络模型移植到 AWS SageMaker 中免费服务
  4. 创建一个有角度的前端应用程序,并通过 S3 桶为其服务
  5. 使用 API Gateway 创建一个 API,并使用 lambda 函数将用户图片上传到 SageMaker 并检索结果
  6. 瞧啊。0€运行成本快速和可扩展的年龄识别服务

这个项目看起来很容易构建和部署,不是吗?

四大错误

在审视这种方法时,我们低估了一些关键词的潜在难度,并且没有问自己一些相关的问题,例如:

  • 第一步 —“获取”:数据集质量如何?数据是否平均分布且平衡良好?其他用户测试过数据集吗?
  • 第二步 —“选择”:选择神经网络模型就这么简单吗?我们如何训练它?我们如何知道我们走的是正确的道路?
  • 步骤 3 —“迁移”:将一个模型移植到 SageMaker 有多容易?培训脚本是否与当地使用的脚本相似?主持一个训练有素的模特是免费的吗?

在思考如何写这篇文章时,我们意识到我犯的大多数错误可以归纳为四大错误。如果你是人工智能和/或云的新手,我们希望我们在该领域非常短的经验可以帮助你避免犯同样的错误。

I .根据流行词汇指导您的技术选择

在过去的几年里,我们听到了很多关于完全托管的 PaaS(平台即服务)和 SaaS(软件即服务)产品的精彩世界。对于我们的项目,我们希望使用一种服务,这种服务允许我们部署经过训练的模型,而无需担心基础设施或成本。

多亏了快速的谷歌搜索,我们了解到目前最时尚和最便宜的(通过免费层优势)服务叫做 AWS SageMaker。我们选择这项服务的决定是基于产品页面上的第一句介绍:“Amazon SageMaker 是一项完全托管的服务,它为每个开发人员(…)提供了快速构建、训练和部署机器学习(ML)模型的能力”。

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

来源: SageMaker 主页

如前所述,我们的目标是“快速”开发一个 TensorFlow Python 项目,并将该项目迁移到 SageMaker,以便在模型运行后对其进行训练。我们相信将源代码迁移到 SageMake 只需要很小的重构。

然而,在开发了我们的训练脚本之后,我们意识到迁移是一个重要的过程,需要对我们的代码进行重大的重构。事实上,我们发现我们的预处理根本无法遵循 SageMaker 的训练工作流程。为了训练我们的模型,我们必须完全重写我们的训练脚本。

我们主要的(也是明显的)错误是在验证我们对 SageMaker 如何工作的理解和假设之前就直接进入代码开发。最重要的是,我们没有考虑 SageMaker 的定价模型。尽管我们知道 SageMaker 在前两个月是免费的(这应该足以训练我们的模型),但我们发现 SageMaker 只是依赖 EC2 实例。我们知道 Jupyter 笔记本必须持续运行才能与 API gateway 配合使用。这将打破我们的两个主要要求:

  • 没有运行成本;和
  • 无服务器且可扩展。

很快,我们意识到这可以通过简单地阅读 SageMaker 的文档和定价模型来避免。“咄!”你可能会想。然而,我们盲目地相信这样一个受欢迎的服务将为我们提供成功所需的一切。

TL;DR:如果你不了解这项技术,不要根据它的流行程度来假设它会符合你的工作方式。在我们的上下文中,我们应该简单地修改我们的训练脚本以适应 SageMaker 的需求,而不是希望该工具可以导入任何训练脚本。

二。重新发明轮子

这第二个主要错误与第一个有关联,因为它实际上是第一个错误的原因。在这一节中,我们将讨论一个经典的错误,那就是试图构建专家在过去已经构建好的东西。在我们的项目中,我们意识到我们花了太多时间试图重新设计一个众所周知的高效解决方案:提供年龄识别的神经网络模型。

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

艾伦·奥洛克的图片。来源: Flickr

开源社区是很棒的,大多数时候,人们很可能已经建立了很棒的工具来做你正在寻找的事情。

即使你感觉——像我们一样——对这个项目非常兴奋,你想自己构建一切,盲目地开始编码可能是个坏主意。你可能知道,强烈建议你对你想解决的话题做一些研究。

起初这听起来很明显,但是当你尝试并承受不这样做的后果时,你会明白这些话的重要性。在我们的案例中,我们立即开始研究我们的神经网络,因为我们相信我们可以不费吹灰之力就训练和部署这样的模型。

事实上,即使我们不相信我们的训练脚本或数据质量,我们也试图通过 GPU 优化的实例在 AWS 上尝试一下。结果呢?在花费了 10 次€和无数次调整之后,我们的最高结果是在训练数据集上有 20%准确率的模型。尽管我们对这个过程了如指掌,但结果却是一场灾难。

你可能会想:“如果你不想学习如何训练一个模型,为什么不直接使用一个公共 API,比如 AWS Rekognition 或者 Google Cloud Vision?”。这个问题的答案相当简单:我们项目的主要目标是学习如何将一个人工智能模型部署到云上,并使其可扩展和生产就绪。

在构建本地项目失败后(其原因将在下一节解释),我们面对现实,开始寻找替代方案。我们开始做一些研究,我们找到了我们想要的: DEX:对单一图像的表观年龄的深度期望

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

来源:https://data.vision.ee.ethz.ch/cvl/rrothe/imdb-wiki/

拉斯穆斯·罗斯、拉杜·蒂莫夫特和吕克·范·古尔发表了一个数据集,其中包含超过 50 万张带有年龄和性别标签的图像,以及他们各自的训练模型。蛋糕上的樱桃是这篇论文是 2015 年 NVIDIA 表观年龄竞赛的获胜者。我们从试图自己构建一切到拥有一个最好的随时可用的年龄识别模型👏。

在这一点上,我们面临的事实是,这份文件比我们能够建立的任何东西都好,而且远远好于任何东西。事实上,我们意识到这不是一件坏事,因为我们不是数据科学家,我们的目标从来不是改善预测面部年龄的艺术方法。虽然我们很难过看到我们不能实现我们自己的训练模型,我们知道更好的人已经建立了一个令人敬畏的模型。因此,对我们来说,显然我们应该重用这个模型。

我们的问题是,我们开始着手项目中我们不一定感兴趣的部分,因为我们认为它们是微不足道的。这意味着我们最终重建了一个更差、性能更差的神经网络模型。

从积极的方面来看,通过阅读论文,我们了解了很多关于深度学习的知识,更具体地说,训练模型不是一项简单的任务。最重要的是,我们的大部分约束(边做边学,玩得开心,构建一个真正的产品)仍然完好无损,这意味着我们仍然有动力继续前进!

三。两次被同一块石头绊倒

在放弃开发和训练我们自己的 ML 模型的希望后,我们开始致力于后端工作,一旦上传一张照片,就可以向用户提供他们的年龄。

我们开始开发一个简单的 Flask API,以便确认我们能够理解如何使用经过训练的模型。结果是一个大约 90 行长的简单 python 脚本:

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

摘录我们的源代码 Flask API。用生成的截图。

一旦我们验证了这个 API 可以在本地工作,我们的下一个目标就是将它迁移到一个“免费使用”和“无限可扩展”的 AWS 服务。考虑到这一点,我们选择了使用 AWS API Gateway 和 AWS Lambda 函数。由于我们以前有过使用这些工具的正面经验,我们甚至懒得检查任何限制,因为我们“知道”如何去做。

我们在尝试使用 OpenCV 和其他依赖项启动 Python Lambda 函数时遇到了第一个问题。我们了解到这可以通过 Lambda 层以及将我们的 Lambda 函数与其依赖项打包来实现。经过大量故障排除后,您会发现以下经验教训:

  • 为了正确下载和打包 lambda 函数,你应该从亚马逊 Linux 兼容系统下载依赖项(即从 MacOS 运行pip install-t . opencv-python会下载不兼容的二进制文件);
  • 运行在 Python 3.8 上的 Lambda 函数不能导入和运行 OpenCV,因为诸如 libgthread-2.0 之类的系统文件不包含在运行时环境中。应该用 Python 3.7 来运行 OpenCV。

在学习了如何正确下载我们的脚本依赖项并打包它们之后,我们将脚本上传到 lambda 环境,并注意到剩下的步骤是导入并使用我们训练好的 ML 模型。

我们又一次面对残酷的现实:Lambda 函数有严格的存储限制。通过阅读 Lambda 的官方文档,我们注意到每个功能部署包的最大大小是 250 MB,而我们的 ML 模型是 500 MB 和 600 MB。

请注意,这可能不再准确,因为 Lambda 现在支持 EFS

我们又一次被同一块石头绊倒了:我们没有花时间去阅读和了解我们想要使用的产品的局限性。我们再一次被这种“功能即服务”产品所带来的宣传和伟大的用例所盲目引导。在这种情况下,我们高估了自己的技术知识,因为我们从以前的经验中获得了巨大的成果。

在尝试移植我们的代码之前应该做些什么?做一些基础研究,了解产品是否适应我们的需求。似乎选择最受欢迎的产品有时意味着做出一个非常糟糕的技术选择。例如,我们应该在开始之前阅读的内容“为什么我们不使用 Lambda 进行无服务器机器学习”

四。低估难度,高估自己的知识

这个项目是由这样一种信念驱动的,即我们知道如何“正确地”做事情,即使我们在我们处理的领域(即人工智能和云)经验很少。第四个也是最后一个主要错误实际上是我们其他错误的原因:我们低估了交付生产就绪产品的难度,同时过于自信地认为,根据我们对每一种底层技术的阅读和听说,我们对应该如何做事情有足够的了解。

我们从网上的大型数据集开始了我们的项目。我们主要是通过 Kaggle 搜索,找到了一个有 10000 张脸的模型,上面标注了年龄。“太好了!”我们认为——但当我们开始深入研究数据时,我们意识到创造一个好的预测器的道路并不像我们想象的那样平坦。

首先,我们低估了免费获得合适数据集的难度:

**数据量:**虽然我们从来不认为自己是人工智能领域的专家,但我们知道,只有来自 100 个不同人的 10,000 张人脸不足以训练一个准确的模型。在这种情况下,我们意识到数据量是不够的。此外,当我们分析每个年龄的人脸数量时,我们意识到数据集完全不平衡。尽管我们试图通过年龄范围对人脸进行分组来平衡数据集,但结果仍然非常不平衡。我们注意到 90%的可用图片来自 30 到 50 岁的人。

**数据质量:**除了上一期,我们发现数据有偏差。我们注意到大多数照片都是名人的照片。我们知道我们不能用山谬·里维的照片,希望普通人看起来像他一样年轻。最重要的是,我们注意到一些图像被裁剪,会显示出面部相当不完整的部分。

经验教训:在开始用数据集训练神经网络之前,请花时间确保您下载的数据具有足够的样本质量和数量。

然后,我们高估了我们对 AI 和云以及目标解决方案的了解。

作为非常好奇的人,我们总是试图在最短的时间内了解尽可能多的东西。在这种情况下,云和人工智能的概念是我们花了大量时间阅读公司和创业公司所做的伟大事情的两个主题,但用于理解和深入研究所用技术的时间非常有限。

本质上,我们可以说我们对想要使用的技术的了解非常少,尽管我们觉得自己知道的很多。这可以用下面的图表来解释,我们相信你们很多人对此都很熟悉:

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

邓宁-克鲁格效应(来源

不用花太多时间分析这个图表,我们就可以确认,在这个项目开始时,我们感觉到了“愚蠢山的顶峰”附近的某个地方,随着时间的推移,我们能够进入迪塞普山谷。这个项目帮助我们认识到我们对机器学习知之甚少。

我们学到了重要的一课,即选择正确的技术和正确的数据并不总是简单的。在创建一个可行的概念验证和部署一个用户友好的“最终”产品之间存在着巨大的差距。

结果呢?谷歌云,虚拟机和 Docker!

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

我们项目的自制图形描述

从上面的图片中,你会看到我们对现实的期望。我们多次错误和改变的结果导致了下面的“最终”结果:

  • 我们没有用自己的数据集来训练模型,而是用一个更好的数据集来训练模型;
  • 我们没有将后端移植到 SageMaker,然后移植到 Lambda,而是使用 docker 容器来服务 Flask API
  • 我们没有在 AWS 上托管我们的后端,而是最终使用了谷歌云和作为账户免费层一部分提供的 300€。

通过对照我们的主要目标进行自我评估,我们得出了以下结论:

  • 遵循“最先进”的实践来训练我们的模型并部署我们的产品: 虽然我们的解决方案不是我们所期望的,但我们尝试使用最健壮、最相关的技术。从这个意义上说,我们决定使用一个流行的、健壮的训练过的模型,而不是我们自己的模型。关于前端,它存储在由 CloudFront CDN 提供服务的 S3 桶中。这意味着成千上万的用户可以访问前端,而不必扩展我们这边的任何东西。看看后端,为了使我们的应用程序可复制和可移植,我们决定将 flask API 容器化,并用 NGINX 容器来服务它。我们认为自己对结果十分满意!
  • **每月运行成本为 0€😗*我们实际上在这一点上作弊了,因为我们的后端运行在 Google Cloud 的虚拟机中。然而,由于免费层帐户,我们将能够免费运行它至少 1 年。我们会说,我们部分验证了这一点。
  • 有一个产品可以“无限”扩展,这要感谢无服务器服务: 我们在这一点上非常失败。但我们相信,无服务器解决方案仍能满足我们未来的需求。我们将很快在以后的文章中记录下我们的后续步骤!
  • 打造一款人性化的“最终产品”,让人乐在其中,无需任何解释: 我们会让你自己决定!欢迎访问https://www . face 2 age . app,告诉我们 UX 是否适合您!
  • 享受建造过程: 谢天谢地,这是我们最成功的一点!我们强烈建议和你的朋友或同事一起参加一个小项目,学习新的东西!

遗言和下一步

在这个项目的构建过程中,我们注意到我们不断犯的错误越来越少,花费的时间也越来越少,因为我们找到实用解决方案的能力增强了。下面我们列出了从这个项目中吸取的经验教训:

  • 在直接进入编码之前,进行多次谷歌搜索,将其他解决方案与你想要的进行比较;
  • 起草或设计解决方案后,花些时间考虑可能出现的限制和问题。通常,每当你在没有可靠经验的情况下做出假设时,这些问题就会出现;和
  • 如果你以前从未做过某事,避免对你的计划过于自信,将你的时间期望值乘以 3。

那么下一步是什么?

尽管我们对我们的解决方案结果和该项目取得的成果非常满意,但我们意识到,该解决方案离“生产就绪”还很远,因为我们目前在单个(性能不是很好的)虚拟机中托管我们的模型。这意味着如果我们的项目突然流行起来,基本上就崩溃了。可以使用多种解决方案来确保项目以非常有限的成本进行扩展。以下是我们的一些想法:

  • 用现有的解决方案替换后端。例如,我们可以使用 AWS Rekognition,并有 5000 个免费的每月预测。
  • 将后端迁移到 PaaS 产品,如 AWS ECS 或 Fargate,这将允许我们根据需求进行扩展。然而,这种解决方案会转化为更高的成本,感觉有点“大材小用”。

关于我们

我是 Jonathan Bernales ,在 Deloitte Luxembourg 工作的网络安全顾问,我主要为金融服务行业工作,我对技术和安全如何随着时间的推移改变行业并创造商业机会充满热情。

我是曼努埃尔·库比洛,一名软件工程师,热爱科技以及科技对我们生活的影响。我对人工智能、云和软件开发充满热情。我一直在寻求学习新的东西。在我的空闲时间,我喜欢运动和阅读。

请随时与我们联系,如果你有任何问题或想有一个关于这个项目的教程!

应用机器学习研究的经验教训

原文:https://towardsdatascience.com/lessons-learnt-working-on-applied-machine-learning-research-1a7a5059aa75?source=collection_archive---------36-----------------------

初学者在处理机器学习问题时提高工作效率的技巧

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

尼克·莫里森在 Unsplash 上拍摄的照片

在台北医科大学实习期间,我致力于开发慢性肾病的预测模型。该项目是一次教育体验,面临着数据集的复杂性和庞大规模带来的挑战。在这篇文章中,我将分享我学到的关键经验,这些经验帮助我提高了初任研究员的工作效率。这些想法非常普遍,适用于大多数机器学习工作流。其中一些是我们选择忽略的明显问题。

记录一切

将你的每日(定期)进展记录到日志中是被低估的。记下几行每天取得的进展。我们中的一些人有时会不确定我们是否完成了心中的某项任务,或者我们是如何完成的。有时我们会重复我们犯过的错误。如果你是这些人中的一员,日志会帮助你解决这些问题,而且它们不需要花很多时间来维护。

当你回顾文献时,记录你的搜索和结果可以帮你节省大量时间,并以系统的方式进行回顾。使用门德利这样的参考经理,收集你的资料,并在上面做适当的注释。这些笔记也会对你以后的手稿有所帮助。参考经理也有助于合作审查文献。

使用实验跟踪器记录实验中的超参数和其他参数。MLFlow,wandb,tensorboard,neptune 是一些流行的选项。它们简化了模型调试和调整,尤其是当您负担不起超参数优化时。

构建您的代码

它不仅可以节省时间,还可以减少可能的挫折。将您的代码模块化为可重用的组件,并使用适合您和您的团队的直观项目结构。避免过度使用笔记本。与脚本相比,它们更难维护。将核心代码移动到脚本中,并将笔记本主要用于可视化和检查数据——在需要时导入核心代码。记住,在研究中过度的代码设计也会损害你的生产力。

有效使用版本控制

经常提交适当的信息。使用分支来执行实验,并在找到可行的方法时将它们合并到主分支中。不要删除失败实验的分支——以后可能需要它们。分支也允许你回顾和讨论你的合作者的代码。不要担心维持一个像样的公共回购。如果你想让人们使用你的实现,最好创建一个单独的面向公众的回购协议。也有像 DVC 这样的项目在数据集上使用 VCS。

尽可能多地记录

记录代码是另一个重要的方面。虽然任何公共代码都应该包含一些关于实现和接口的信息,但是您的研究代码也可以包含一些有用的注释,当您重新访问某段代码时,很可能会忘记这些注释。你还应该把你的项目作为一个整体来记录:如何设置它,不同的组件做什么,到你的数据集的链接,以及关于实现的重要注释。项目级别的文档将帮助您的团队和其他想要利用您的想法的人。当你中断一段时间后回到你的项目时,他们是你的救星。

测试您的代码

我知道机器学习工作流使得测试和调试你的代码变得困难。很多时候,我们将模型表现不佳归因于数据中缺乏信息。但不,这几乎总是你的代码。这是一个即使是有经验的研究人员也会警告的问题。比起数据,更要怀疑你的代码。

尽可能地编写单元测试——尤其是对于数据处理。大多数数据预处理流水线通常是确定性的,并且可以容易地测试。使用一些单元测试工具来确保在试验新方法时不会引入错误。数据处理过程中的错误会耗费您大量时间,尤其是在处理大型复杂数据集时。

在调试模型时,可视化是你的朋友。您无法通过直接检查来识别数据处理或功能转换/聚合中的所有问题。使用可视化技术来确保数据在数据处理操作后看起来像您想要的样子。根据问题的类型,在较低维度上可视化您的数据也会有所帮助。可视化/评估(特征重要性、权重、梯度、假设检验等。)你的训练有素的模型,以确保没有任何奇怪的事情发生。

定期讨论

如果你在一个团队中工作,与你的团队定期讨论是有益的。让彼此了解手头任务的最新进展。它不仅有助于跟踪项目的进展,而且你还可以从他们的实验中学习,并为其贡献你的一些想法。相反,你也可能从别人那里得到克服任何心理障碍的想法,或者在你的方法中有你忽略的错误被他们指出。定期更新你的研究指南并获得他们的反馈也有助于你坚持下去。

感谢您的阅读!如果我错过了一些重要的东西,或者如果你想补充你自己的经历,请随时留下回复。

你可以在 Linkedin 上联系我,在 GitHub 上关注我。

自动博客简介

原文:https://towardsdatascience.com/let-ai-write-your-blog-autoblog-6c4ad840eecf?source=collection_archive---------57-----------------------

让艾写你的博客吧!

从视频演示中半自动创建博客帖子

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

AutoBlog 是一款免费软件,支持让视频演示更容易理解。下的图像 CC BY 4.0

这是AutoBlog视频&匹配幻灯片的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。 自己试试吧! 另外,如果您发现错误,请告诉我们!

欢迎大家!我叫安德里亚斯·梅尔。我是弗里德里希-亚历山大-埃尔兰根-纽伦堡大学的计算机科学教授。今天我想和你们谈谈研究视频和研究报告。我知道你们中的许多人正在制作像我现在正在制作的这样的视频,以突出他们的研究。所以,我想你可能会感兴趣,你可以很容易地将这些视频转换成博客帖子,这就是为什么我今天想向你展示 AutoBlog。所以,这是我在过去几个月里创建的一个小工具集,可以用来从研究视频中快速生成博客帖子。让我们看看我为你准备了什么。

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

这篇文章的概要。下的图像 CC BY 4.0

这是我演讲的大纲。你为什么想这么做?事实上,我想告诉你如何准备演讲以及如何录制和编辑演示文稿。最后,在录制完演示文稿后,我想向您展示如何使用 youtube 及其自动语音识别(ASR)功能来提取口语文本。然后,我想给你介绍一下 AutoBlog 工具链。我将用一些总结和未来的工作来结束这次演讲。

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

你为什么想使用自动博客?图像在 CC 下由 4.0

那么,为什么我们真的需要这样的自动博客呢?嗯,你看,在日冕危机期间,我们已经记录了许多这样的视频演示。我觉得很多真的很精彩。如果你看看像 YouTube 这样的平台,你可以看到它们,它们真的是非常精彩的展示。然而,视频的效用可能有限。所以,你可以听他们,你可以在家里听,或者如果你在路上,你可能需要耳机。如果你现在想让你的研究报告更容易理解,有一个相应的博客帖子会很好。此外,如果你有你在整个视频中一直在说的文本,那么你也可以很容易地在内进行全文搜索。这也可以在您使用自动博客后完成。因此,总之,我们可以说,如果你能够从视频演示中生成博客帖子,那么你就可以增加你的研究的影响,当然还有它的可见性。

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

就像你习惯的那样做幻灯片。图像在 CC 下由 4.0

所以,如果你想使用这样的功能,你必须准备好你的幻灯片。当你实际做演示的时候,你会遵循同样的规则。所以,你要保持你的幻灯片简单,并遵循演示指南。你知道你需要遵守 5x5 或 7x7 规则,这样幻灯片才不会太满。它们应该看起来有吸引力。如果您想使用 AutoBlog,请确保每张幻灯片最多有一个动画,因为我们想使用导出到 pdf 功能,以便以后在创建博客文章时使用它。所以,如果你想使用我今天在这里展示的软件,这是你应该记住的一件事。

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

用您最喜欢的设置录制您的演示文稿。下的图像 CC BY 4.0

好吧,接下来呢?您录制并编辑演示视频。你们大多数人已经这样做过很多次了。你可以通过画外音录制屏幕来使用简单的截屏。也有像我在这里使用的高级策略。我使用 OBS 这样我就可以演示幻灯片,并在演示时记录自己。然后,在你完成录制后,你可以根据自己的喜好编辑视频。你可以去掉所有的“嗯”,“啊”,以及所有你没有确切说出你想说的话的东西。最后,您希望将视频导出为可以上传到 YouTube 的格式。我推荐 mp4 格式。我现在最喜欢的视频编辑工具是 iMovie ,因为它是我的 mac 电脑自带的,但也有很多其他东西可以用来制作视频。所以,一旦你完成了所有这些,你就可以把你的视频上传到 YouTube,以便使用自动语音识别。

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

YouTube ASR 极其强大,支持多种语言。图像在下 CC BY 4.0

Youtube 有一个很棒的自动语音识别功能,用于自动字幕系统。现在,如果你真的不想与外界分享你的演示文稿,你可以在“未公开”选项下分享。这意味着只有您可以访问此视频,并且您上传它只是为了运行自动语音识别。在你完成上传并将你的视频设置为“未列出”后,youtube 将使用自动速度识别,这实质上意味着在上传后半小时或一小时后,你可以访问自动字幕系统。这实际上是自动语音识别系统对您的视频的输出。

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

下载视频的自动字幕。图像在下 CC 乘 4.0

所以,一旦你有了这些说明,你就可以下载了。进入你的 YouTube 工作室,选择你喜欢的视频,进入“编辑”,然后“更多选项”。在那里,你可以找到自动字幕系统的结果,你可以简单地下载它们。我们将在进一步加工中使用它们。现在,一旦您录制了视频并下载了自动字幕的结果,您就可以实际使用自动屏蔽工具链了。

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

自动博客工具概述。图像在下 CC BY 4.0

自动博客有几个非常有用的功能。首先,字幕是所谓的 SBV 格式,它本质上包含了识别的文本和时间戳。

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

将 SBV 字幕文件转换为纯文本。下的图像 CC BY 4.0

我们有这个小网站在这里,在这里你可以拖放你的 SBV 文件到我们的小工具上,它会从那个文件生成相应的文本。

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

将您的 pdf 幻灯片转换成单张图像。图像在 CC 下由 4.0

接下来,你还想在你的博客文章中使用你的幻灯片。这就是为什么我们有这个非常小的工具来将 pdf 幻灯片转换成单个图像。同样,这也是通过拖放来实现的。您只需将您的 pdf 文档放在我们网站的相应字段中。这将上传 pdf 文件到我们的服务器。然后我们会把它转换成 jpeg 文件,然后你就可以下载包含所有 JPEG 文件的 zip 文件了。请不要为此花费太多时间。大约六个小时后,我们将删除所有生成的文件。所以,请务必尽早下载文件。此外,对转换有一定的限制。目前文件大小限制为 200 兆字节。它可能会比我在视频中显示的时间稍长,因为我对视频进行了延时处理,以便准确地匹配我在这里告诉你的内容。

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

使用图像到 GIF 转换回收您的动画。下的图像 CC BY 4.0

然后,我们有几个高级功能。它们是给你的博客文章增加一些趣味的基本要素。我们有两个额外的功能。一个是为了制作动画 gif。假设你的幻灯片里有动画。你从生成的 jpegs 文件中选择相应的文件,然后在我们的网站上再次拖放它们,它会很快生成一个动画 gif。您可以简单地将它拖放到保存文件的文件夹中,然后在您的博客文章中使用它。

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

不需要安装 avi/mov/mp4 到 gif 转换的软件。下的图像 CC BY 4.0

此外,我们还提供将小电影转换成动画 gif的机会。所以这非常类似于 giphygifify 以及其他工具。因此,在这里您选择您的电影文件拖放到我们的网站上。这需要一些时间。再一次,我花时间向你们展示这是可以做到的。文件大小限制为 200 兆字节,下载也要快,因为文件会在六个小时后被删除。然后,您还可以将它拖放回来,供以后在您的博客文章中使用。所以,一旦你做了所有的准备工作,你就可以开始写博客了。

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

最后,在一篇博文中汇集一切。图像在下 CC BY 4.0

我通常在 WordPress 中这样做。然后你准备你的网站。你输入文本。然后,添加图像和刚刚生成的动画,并将它们插入正确的位置。最后,您浏览了整个文档,并纠正了其中所有的错别字。字幕系统不提供任何句号或句子边界。所以,这还是需要一点努力的。我个人建议用拼写纠正系统来做这件事。我在语法上使用的是免费版的。在这个视频中,您可以看到它还增加了相当多的支持,以纠正 ASR 输出。所以,一旦你这样做了,你基本上就完成了,你可以发表你的博客文章了。

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

快进 45 分钟修正。下的图像 CC BY 4.0

所以,你看这其实很简单。我个人花了大约 45 分钟来制作一个 15 分钟的视频。所以,你再次看到这是一个时间推移。你可以很容易地把它放在你的网站上,与世界其他地方分享。我认为 WordPress 和 Medium 的界面非常好,因为它支持拖放功能,这使得编辑非常容易。

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

自动博客摘要。下的图像 CC BY 4.0

所以,我希望我能让你相信这是一个有用的工具。您可以使您的视频演示更容易理解,对于依赖文本的人也是如此。他们可以非常简单地访问您的研究内容,并获得与您在视频中提供的基本相同的信息。做起来简单快捷。这并不需要太多的努力,最酷的是,如果你使用它,你就可以增加知名度和影响力。请注意,我是在我们大学的服务器上提供的。所以现在整个服务是完全免费的。我不打算在任何时候对这项服务收取任何费用。我想做的是帮助你们提高研究的知名度!

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

未来工作清单。图像在下 CC BY 4.0

当然,还有相当多的未来工作需要完成。我目前正在用这个工具链从我所有的演讲视频中生成博客帖子。所以,我基本上是从讲课视频中生成课堂笔记。我已经做了大约一半,我很快就会做完整堂课。这样的话,我们就有了一套完整的由博客文章组成的课堂笔记。我们打算做的下一件事可能是在 9 月份左右,我们实际上想将博客帖子转换成我们深度学习讲座的教科书。如果你遵循这个工作流程,我认为我们可以比以前更快地生成教科书。所以,我认为这对其他研究人员来说是一个非常有吸引力和有用的服务。

当然,我们需要在未来改进 AutoBlog。有一件事很容易做到,那就是自动幻灯片对齐。因此,我们可以获取视频以及生成的文本和时间戳,然后尝试检测我们也可以访问视频内部的幻灯片。一旦我们检测到它们,我们还可以自动对齐它们,这样它们就会自动生成到博文的正确位置。因此,这是我们希望在未来某个时候解决的一个扩展。另一件事是,我们想在拼写纠正工作。所以,你可以看到 YouTube ASR 输出的问题是你错过了所有的句号等等。这实际上花费了相当多的时间。如果我们有足够的训练数据,我们将能够自动做到这一点。因此,我们也在考虑创建一个服务来真正做到这一点,这让我想到了未来工作的最后一点。我建立了一个叫做自动博客画廊的东西。如果您感兴趣,我们还会在此图库中列出您的日志和视频。当然,你可以免费使用 AutoBlog。如果您在相应的博客帖子中链接了相应的视频和相应的幻灯片,我们会将您列在那里。所以,我们会看看你的博客文章,检查信息是否在那里,如果在那里,我们也会把你放入画廊。你的好处是你的博客帖子变得更加可见,我们的好处是我们可以收集更多的训练数据,以建立上述两个服务。好吧,我希望你喜欢这个小视频,你会发现这个自动博客功能很有用。所以我认为,这可以帮助你让你的研究更容易接近,更容易被看到。我非常期待在我们的 AutoBlog Gallery 中看到关于酷的研究项目的有趣的博客帖子。所以,非常感谢大家的收听,再见!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTubeTwitter脸书LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中获得文字记录,试试自动博客

链接

AutoBlog 网站
AutoBlog 视频
AutoBlog 幻灯片

让电脑说话

原文:https://towardsdatascience.com/let-computers-talk-b840978cc94e?source=collection_archive---------63-----------------------

起初是这个词

H 人类在所有物种中是独一无二的,就像电脑在所有手工制作的东西中一样;他们都配备了语言。语言是文明最基本的基石,是思维和交流的要求。人类创造了计算机,并用语言武装它们,以便于解决问题。这到底是怎么发生的?这个过程很简单:人类思考,与计算机对话,并通过算法向它们发出命令,然后计算机可以做一些工作,并与自己对话来解决问题(图 1)。语言是这个过程的基础,并提供了人机和计算机之间的交流方式。

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

图一。人机&计算机与计算机的互动。(上图:来自名词项目的 Kidaha 的人类,下图:来自名词项目的 Vector Market 的计算机机器人。)

什么是语言?

语言是通过信息进行交流和传递信息的工具。语言的基石是字母表,是一组符号。有了字母表,我们可以通过把符号放在一起创造出单词——简单概念的原子引用。一个有效的句子——对更复杂概念的引用——可以被认为是一个具有正确语法的单词序列(在自动机理论中句子被称为字符串,在通信中称为消息)。语言是所有语法正确的句子的集合。因此,我们可以将语言 L 定义为三元组 (A,W,G) ,其中 A 是字母表, W 是单词集, G 是指定句子有效性的底层语法。让我们看看不同语言的例子。

  1. 洞穴绘画
  • 字母表:{马的形象,人的形象,…}
  • 单词:字母表的每个符号也是一个单词(1 个符号的序列)
  • 句子:一幅男人猎鹿的画(图 2)

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

图二。洞穴绘画。

2.英语书面语言

  • 字母表: {a,b,c,…,1,2,3,…}
  • 单词:苹果(a-p-p-l-e)(5 个符号的序列)
  • 句子:“把苹果放在桌子上”(6 个单词的序列)

3.莫尔斯电码

  • 字母表:{破折号➖,点号}
  • 单词(代码字):

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

图 3。詹姆斯·坎乔的摩斯代码字。

  • 句子:代码字的任意序列。

4.汇编语言

  • 字母表: {a,b,c,…,1,2,3,…}
  • 词语:添加换挡$s1 ,…
  • 句子:"添加 s 1 , s1, s1s2,$s3"

5.编程语言

  • 字母表: {a,b,c,…,1,2,3,…}
  • 词语:如果,瓦尔纳姆斯,…
  • 句子:"打印(‘此处’)"

如你所见,不同的语言有不同的用例;例如,书面语言不适合盲人,他们可能会使用盲文代码。另一个方面是创建(编码)和理解(解码)消息的难度。例如,洞穴绘画很容易创作和理解,而为了使用书面语言,你应该先去上学。然而,书面语言比岩画更有力量,因为你不能说“请等等!”仅仅通过绘画。

一起解决

人类和计算机如何一起解决问题?首先,我们需要知道计算机到底能做什么。物理上它们是由电和导线构成的,粗略来说,它们只能感知电流的存在(存在与否)。由于这种二进制的性质,它们可以处理二进制序列:在它们的门中接受二进制输入并处理它们。这样,我们就可以为它们提供指令,并通过数字电路实现一些基本操作:对内存(寄存器、RAM 或磁盘)的读写、加法、移位等。因此,我们可以收集所有盖茨的输入,以预定义的格式(语法)对它们进行排序,并构建一种具有{0,1}字母表的语言。这种语言叫做机器码。例如,R 型 MIPS 指令具有以下格式:首先是 6 位操作码,然后是三个 5 位寄存器名称(总共 15 位),然后是 5 位移位码,最后是 6 位功能码,这使得它成为总共 32 个符号的序列。

机器代码是计算机理解的语言,尽管我们不能直接使用它,因为它很难使用。我们使用另一种叫做汇编语言的语言,这是一本用英语写的计算机手册。例如*“add $ S1, s 2 , s2, s2 S3”*表示将寄存器 s1s2 的内容相加,并将结果放入 MIPS 汇编中的寄存器 s3 。现在的问题是,我们如何将汇编语言翻译成机器代码?

假设 L1 是汇编语言 L2 是机器码。为了将 L1 翻译成 L2 (编码),我们可以简单地通过分配一些预定义的码字(例如*‘add’映射到 000000 )将 W1 (add,shift,$s1,…) 映射到 W2 (二进制序列),并将这些码字与正确的语法放在一起,这很容易由汇编器完成因此,有了机器代码和汇编语言,我们就可以和计算机对话。但是你能把你的想法翻译成汇编语言吗?答案是否定的。需要一种更高级的编程语言,更类似于人类语言。诸如 Java 和 Python 之类的编程语言以及它们的编译器和解释器就是为此目的而设计的。因此,语言的层次结构构建了我们与计算机的交互。*

沟通

现在,我们已经解决了我们的问题,是时候交流了!假设艾丽西娅想通过他们计算机之间的网络与鲍比通话。但是使用计算机网络,我们只能传输比特,这是计算机语言的字母表。因此,解决方案是首先将我们的语言翻译成一些比特(编码),然后传输这些比特,最后再将它们翻译回来(解码)。因此,我们应该设计一种带有二进制字母表的语言,并指定如何将我们的语言翻译成二进制字母表。莫尔斯电码是一个很好的研究案例。

假设 L1 是英语,我们想通过设置 A2W2G2 来建立 L2 (莫尔斯码)。我们可以简单设置 A2={dot,dash} ,这是一个二进制字母表。但与汇编语言不同,英语有很多单词,我们不能简单地在 W1W2 之间建立一对一的映射。莫尔斯电码的解法是先将 A1 中的每个符号映射成一个码字(如*“A”→“点-划”),然后将它们串联起来,达到 W2 中的单词表示(如“AS”→“点-划点-点”*)。 G2 也没那么难,几乎任何码字序列在 L2 中都有效。这样,我们可以把我们的语言翻译成莫尔斯电码,并通过计算机进行交流。

沟通的成本是多少?考虑一下这个问题:为什么我们不把*“A”赋给“破折号-破折号-点破折号”而在莫尔斯电码中不赋给“Q”?因为 AQ 要常见得多,而且使用“点划线”会导致消息长度短得多。因此,我们可以将通信成本定义为传输消息的长度(#符号*),并定义最佳编码:平均来说导致更短消息的编码。这是信息论偏好的答案。

信息论研究通信的潜在限制,并试图找到对消息进行编码所需的最少比特数,其基础是假设信息源正在生成具有已知概率分布的单词序列(随机过程)。假设我们有在其上具有离散概率分布的 k 个字和一个源,Shannon 表明对于最佳码字分配,具有 N 个 T21 字的消息将被编码为至少 N 个比特,其中 H§是不确定性的度量事实上,在最佳码字分配中,我们试图将较短的码字分配给更可能的结果,并且如果看到字 wi 的概率是 pi ,我们试图将其分配给具有非整数长度 log(1/pi) 的码字(例如,通过霍夫曼编码),并且当 N 趋于无穷大时,具有非整数长度的码的问题逐渐消失。

能力

哪类问题可以通过计算机解决?用什么成本?这些问题被称为可判定性和复杂性,并在自动机理论领域找到了答案。对于一个是/否 problem⁴,我们可以把所有正面实例的表示放在一个集合中,并建立一种语言。所以我们应该决定一个表示是否是这种语言的成员。由机器来做这个决定,可能是可能的,也可能是不可能的,问题的难点就在这里。

一些语言,像由正则表达式(正则语言)和上下文无关文法(上下文无关语言)生成的语言,很容易分别由有限自动机和下推自动机决定。但是一些语言可能有更复杂的隐藏结构(语法),可能更难决定或识别,即使是通过图灵机。例如,所有有效 C++代码的集合是可判定的,因为它是一种上下文无关的语言,并且 C++编译器可以判定它。然而,具有整数根的多元多项式的集合是不可判定的;这意味着没有保证的算法来批准多元多项式是否有整数根。

即使一种语言是可判定的,判定它的时间复杂度也是一个重要的问题。时间复杂度通过达到长度为 n(例如,它可以是 n)的输入的答案所需的最大操作数来测量。通常我们需要多项式时间复杂度的解,指数解不适用。具有多项式判定器的问题建立了 P 类,而具有多项式检验器的问题建立了 NP 类。这些概念在复杂性领域讨论。

笔记

  1. 在这份文件中,我将坚持一词的概念。许多定义像自动机理论中使用的那样,不包含单词。在那些定义中,假设每个符号都是一个有意义的原子引用,所以它相当于本文档中的一个单词。
  2. 参见“封面,T. M .,&托马斯,J. A. (2012)。信息论的要素。约翰·威利的儿子们。
  3. 参见*“Sipser,M. (2012)。计算理论导论。Cengage 学习。”*
  4. 我们可以通过考虑答案的二进制表示,并为每个位建立一个是/否问题,将一个问题简化为一些是/否问题,并并行求解它们。因此,我们可以只关注接受/拒绝问题。

让数据提高你的网球水平

原文:https://towardsdatascience.com/let-data-improve-your-tennis-game-37f346377663?source=collection_archive---------22-----------------------

如何使用机器学习模型,通过基于从数据中提取的最重要的指标构建更有效的游戏策略,来提高一个玩家赢得游戏的机会

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

达米恩·桑德斯,ESRI“数据转储”了 2012 年奥运会金牌得主罗杰·费德勒和安迪·穆雷之间的每一个球的反弹和击球。

我是个网球爱好者。我喜欢每周打网球,看网球,甚至打梦幻网球。尽管梦幻网球不像梦幻足球那样普及,但世界各地仍有相当多的人参与其中。有多种格式,但最常见的是括号。在括号格式中,幻想的网球运动员试图预测谁将是锦标赛中所有网球比赛的获胜者。我也经常打网球,从童年开始,我就一直想知道是否可以通过专注于比赛中更重要的部分来提高我的比赛,我试图询问许多人对比赛中最重要的技能的看法,但没有一个答案对我来说足够有说服力。幸运的是,我发现了近 6000 场比赛的数据,决定看看这些数据是否不仅能提高我的比赛水平,还能提高我在比赛中获胜的几率。

数据集

数据集从 ATP 的网站上收集,初始格式包括从 1968 年到 2018 年部分时间的几乎所有 ATP 比赛。该数据包括许多有趣的特征,如选手排名、比赛时累积的点数、比赛统计、比赛中每位选手击中的 ace 球数、选手发球和回球率等。不幸的是,有许多特征数据没有包括在内,比如正手统计,而且,许多早期的观察没有包括所有的特征。我决定缩短数据并从数据中删除所有 2000 年以前的比赛,主要有两个原因,首先是比赛的性质和 ATP 比赛的形式从 2000 年开始发生了变化,其次是为了节省时间,因为数据太大了,在我的本地计算机或谷歌 Colab 上处理需要太多时间。

所有使用的数据集和预测建模笔记本可以在这里找到。

图 1:为获胜的游戏提供的第一个服务

数据清理

预处理的第一步是处理包含空值和零值的列,然后将所有单个数据集合并成一个大数据集。因为所有的数据集都包含一些相同的特征,所以这很简单。

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

图 2:带有缺失值或高基数的一些列的 Pandas 概要分析报告

第二步是消除数据集中的泄漏和一些偏差。由于原始数据根据数据是属于获胜玩家还是失败玩家,用列名“赢得的总点数”和“赢得的组数”来标记所有数据,因此有必要删除一些列以防止泄漏,并重新标记一些相关列以避免使用数据构建模型时可能导致的偏差。为此,我将玩家 1 随机分配给赢家或输家,将玩家 2 分配给另一个玩家。随机分配的结果是玩家 1 大约有一半时间是赢家。

第三步是过滤数据集,以避免零或空值,并只包括那些两个球员的排名都可用的观察,因为我直觉地认为这将是最强的预测。这将观测数量从大约 10k 减少到大约 6k。尽管这是一个巨大的减少,但事实证明大多数被丢弃的数据缺少重要的信息。

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

图 3:一些列中的空值。原来在那些年里,他们没有被记录下来

特征工程

一些先前的机器学习模型仅使用两个玩家的排名来预测比赛结果。这是有意义的,因为排名捕捉了玩家在过去一年中的表现,并且很可能是玩家当前战胜低评级玩家的能力的强有力的预测器。然而,还有许多其他类型的信息可能有助于预测比赛的结果,在某些情况下,它们可以用于预测直播形式的比赛结果。例如,两个玩家过去的对决可能非常相关,尤其是最近的比赛,或者在部署我的模型后,我发现赢得第一盘是比赛结果的强有力指标。球员发球和回球的质量也很重要。

图 4:两个特征工程柱之间的关系

为了更好地捕捉每个球员的细微差别,我决定计算每个球员在每场比赛中的一对一比赛,以及双方球员在过去比赛中的发球得分。这些数据是 1991 年以后才有的。为了确保过去有足够的数据可用,我决定进一步限制数据集以匹配 2000 年以后的数据。这样,我就有了大约 19 年的比赛数据来计算这些统计数据。

我计算的特征包括:每分的得分率,每分的双误率,两个球员之间的正面结果,第一发球的百分比,第二发球的百分比等等。我逐点调整发球数据,以避免出现偏差,例如,如果我使用 ace 的数量,因为一名球员可能比他的对手有更多的机会击中 ace。出现的一个问题是,一些观察包括新的球员,没有以前的表现记录。一种选择是将该玩家的所有统计标记为 0,但这可能会产生有偏差的结果,因为 0 是最低的度量,并且仅仅因为玩家在记录中没有先前的匹配,并不意味着他应该被分配最差的分数。我最终决定删除所有带有 0 的观察值,这似乎不是最好的解决方案。这是将来要研究的问题。

最后,过去的大多数建模将玩家 1 特征和玩家 2 特征组合成单个特征。例如,对于等级特征,减去两个等级会将两个特征合并成单个特征。这具有产生对称模型和将特征空间减少一半的优点。但是,它有消除信息的缺点。我决定不将任何特性合并成一个单一的特性。

预测建模

既然这是一个分类问题(玩家胜利=真/假)。为了测试模型,我首先将数据分成 80% — 20%的训练测试部分,并使用网格搜索交叉验证来选择最佳超参数,将最佳超参数重新调整为完整的训练集,并通过 5 重交叉验证在验证和测试集上测试模型。

这个问题的基线是 0.51 的多数类准确度分数,这意味着仅仅通过猜测我们就可以预测一个玩家在 51%的时间里赢得了比赛。我使用了各种线性和基于树的模型,如逻辑回归、单决策树(用于查找漏洞)、随机 forrest 和 XGboost 来预测获胜者。XGboost 比其他模型高出约 1%,其结果是验证准确率达到 96%。

然后,我使用排列重要性来找出哪些特征对我的模型贡献最大,并发现预测赢家的最重要特征是玩家的服务等级,然后是玩家是否赢了第一盘。对我的模型有贡献的其他一些重要特征是回报率、破发点和抢七获胜。

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

图 5:排列的重要性

我还绘制了一个单一特征部分相关性图(图 6)以进一步探索服务评级特征,有趣的是,我发现当服务评级超过约 230 分时,服务评级在预测获胜者方面开始变得重要,并逐渐提高获胜的机会,直到它达到约 330 分。值得注意的是,对于发球得分超过 330 分的玩家来说,发球得分在预测比赛结果时失去了重要性,因为他们都有超过 60%的机会赢得比赛。

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

图 6:服务等级的单一特征部分相关图

然后,我想弄清楚服务等级和断点如何有助于更准确地预测比赛结果。为此,我使用了多特征部分依赖图(图 7 ),只要服务等级超过 297,并在游戏中获得 3 个以上的破发点,玩家就有大约 90%的机会赢得游戏。了解这一点对我来说是非常有见地的,无论是在提高我的比赛还是预测网球比赛的获胜者方面。

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

图 7:我的模型中两个最重要特性的多特性部分依赖图

我还使用了 Shapley 图来简要探索哪些特征对模型中的单个匹配有积极或消极的影响,以及它们在预测特定匹配时的影响有多强。如下图 8 所示,如果一名球员的发球得分是 178 分或更低,他只发了一个破发点就输掉了第一盘,我们几乎可以 100%肯定地预测他会输掉比赛。

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

图 8:沙普利图

结论

在所有基于线性和树的模型中,使用 XGboost 表现最好,在预测匹配结果时提供 96%的准确性。在这个过程中,我了解到预测网球比赛获胜者的一些最重要的指标是对球员的发球和接发球的评分、制造的断点、抢七局获胜以及球员是否成功赢得第一盘。

我想扩展这个模型,通过使用从第一盘和球员之间的直接比赛历史中获得的数据,计算出预测第一盘获胜者的重要参数,我将在这里和我的文件夹中公布结果。在那之前,我会把我的钱用在我的嘴上,并尝试用我在这里的发现预测一场比赛,并通过专注于获得更好的服务,提高我的回报,获得更多的断点,赢得抢七局,并尽最大努力赢得第一盘来提高我的比赛。

我来告诉你 Docker 在数据科学中的用例吧!

原文:https://towardsdatascience.com/let-me-tell-you-about-the-use-of-docker-in-data-science-a47c8710f5f7?source=collection_archive---------52-----------------------

“永远要像有东西要学一样走过一生,你会学到的。”——弗农·霍华德。

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

来源:凯奎·罗查的《Pexels》

我们总是努力学习生活中的新事物,无论是从经验中学习还是学习新技术以跟上时代。考虑到这一点,我们今天会学到一些新的东西。别担心,我不会下线的。你们中的许多人可能会想,在数据分析和模型建立之后会发生什么?。因此,足够的数据分析和机器学习模型的建立,今天我们将学习一些新的东西,但很多相关的东西。

在本文中,我们将了解 Docker 在数据科学中的使用及其在该领域的应用。

你们中的许多人将第一次和 docker 一起工作。别担心,我会从头开始。

讨论要点:

  1. Docker 是什么?
  2. 我们为什么需要 docker?
  3. 它在数据科学中的用例。
  4. 结论。

docker 是什么?

Docker 是一种开源技术,可以帮助我们实现操作系统级的虚拟化。它由一组工具组成,帮助我们将任何软件或应用程序打包到一个名为 container 的包中,这样它就可以在任何主机系统上运行。

没有什么东西像它只用于软件行业,它可以用在代码转移的地方。

它有时被视为虚拟机的替代品。我们可以说,如果虚拟机是一家酒店,那么码头就是那家酒店的一个房间。

它由三样东西组成命令行、docker 服务器docker hub。

它从命令行向发出构建、运行和发布映像的指令。 Docker 服务器控制图像及其资源,而 docker hub 是一个存储平台,用户可以在其中托管其容器。

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

来源:像素

我们为什么需要 Docker?

你们都经历过一件事,如果任何软件或应用程序运行在一个平台上(我指的平台是操作系统),没有必要运行一个所有其他的。这是由于低级硬件体系结构或软件不兼容性的差异造成的。为了解决这个问题,出现了虚拟机的概念。虚拟机只不过是一个离散的隔离环境,包含运行应用程序的所有必要要求。它们位于操作系统的顶层,操作系统在一个称为管理程序的软件层的帮助下控制它们。但这里的问题是,分配给一个虚拟机的内存和计算能力不能被其他虚拟机共享,并且单个虚拟机对内存和计算能力有很高的需求。因此,这消耗了大量的计算机资源,使我们的电脑注定要完蛋。

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

Docker 和虚拟机的对比:来源:我的图库

因此,为了应对这种影响,出现了 Docker 的概念。Docker 可以被看作是一个轻量级虚拟机,但与它有很多不同。它占用更少的空间,并且一个容器的内存可以在不使用时由另一个容器共享。这减少了 PC 的大量负载,并导致一切顺利运行。

现在你可能会想什么是容器?

我有一个的例子来让它变得容易理解。假设你买了一栋新房子,你需要把你的家具和东西从旧房子搬到新房子。你会做什么?。你不能一次拿一件东西,然后改变。这将花费很多时间,而且你可能会忘记一些事情。所以你有了一个想法,把所有的东西都装在一个盒子里,然后一次全部转移,没有忘记任何东西的机会。现在把这个盒子当作一个容器,里面包含了所有的代码和依赖项,并作为一个操作系统。不,我可以把所有东西都带走。

数据科学中 Docker 的用例。

我给你打个比方。假设你和你的朋友正在做一个数据科学项目。你的朋友开发了一些模型,想让你看看。现在你会怎么做?我很确定您会查看项目的依赖项(库)是否安装在您的系统中。如果没有,你可以安装所有的程序,然后运行代码。

码头工人的魔力不在这里。使用 docker 你的朋友可以分享使用 Docker 创建的项目的图像。你可以在你的电脑上运行它,你只需要直接在你的电脑上运行它,不需要安装任何东西。

此外,如果你对 Flask 不太熟悉,你可以先创建一个具有所有功能的 web 应用程序,并创建它的映像。现在,如果你运行它的图像,它会自动托管在你的电脑上,只需一个命令,不需要做任何其他事情。

在大多数情况下,在数据科学家的模型训练和开发周期之后,模型被传递给软件工程师用于部署目的,而没有 docker,软件人员必须在新环境中安装模型测试所需的每个依赖项,这使得任务看起来相当乏味。这就是 docker 的救援方式,数据科学家只需分享预测模型及其依赖关系已经存在的图像。部署人员只需在安装了 docker 的测试环境中运行它。

容器图片,有什么不同?

现在把容器作为 docker 映像的一个运行实例。

很少有术语与这个 Docker 相关联。

1。ddocker 文件: 该文件包含创建 docker 图像的逐步命令。

**2。requirements . txt😗*该文件包含创建和运行项目所需的所有依赖项。

3。 images : 这是一个包含所有依赖项和代码的项目的独立实例。这是一个你可以分享的东西。

**4。c*ontainers:***这是你的 docker 镜像的一个运行实例。

要安装 docker 请访问 这里的

Docker 的基本和最常用命令。

  1. ***启动:*启动任何停止的容器。
*$: Docker start <image_id>*

2。 停止:停止任何正在运行的容器。

*$: Docker stop <image_id>*

3。构建:从 docker 文件构建一个图像。

*$: Docker build <Docker file name>*

***4。拉:*从托管平台拉任何映像或存储库。

*$ docker pull ubuntu:14.04  # ubuntu is a image at docker run*

***5。推送:*将图像推送到 docker hub。

*$ docker push user_name/image_name*

***6。提交:*根据容器的变化创建一个新的图像。

*# docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
$ docker commit c3f279d17e0a  user_id/repo_name)*

7.图像:显示系统上所有图像的列表。

*$ docker images # Followed by # -q for only image id and -a for each   details of image*

结论…

在本文中,我们讨论了 Docker,它们在数据科学领域的需求,如何使用它们,以及它与任何虚拟机的不同之处。除此之外,我们还学习了一些基本的和最常用的 docker 命令。在下一篇文章中,我们将致力于数据科学项目中 Docker 的实现。所以请关注我,敬请期待!

如果你想和我联系,请访问我的 LinkedIn 个人资料。

谢谢你的合作。

让死者说话——一种更可靠的观察新冠肺炎感染率的方法

原文:https://towardsdatascience.com/let-the-dead-speak-a-more-reliable-way-to-look-at-covid-19-infection-rates-38ee43121a5?source=collection_archive---------59-----------------------

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

照片由摩根莱恩Unsplash 拍摄

我在美国看到的大多数关于新冠肺炎的报道和政府声明都集中在两件事上:每天新增感染人数和死亡总数。问题是,就目前而言,这两个数字在决定州政府应该做什么方面都没有真正的意义,更重要的是,我们每个人现在有多大的感染风险。

在我们得到强有力的测试,阳性率下降到总数的 3%左右之前,我们应该关注每日死亡的趋势。

为什么我们不能依赖“新感染”

联邦政府和州政府谈论的“新感染”数字实际上是“某一天返回的阳性检测数字”。阳性测试的数量会受到一系列因素的影响:有多少测试可用,人们实际上寻求测试的频率,以及医生选择谁来实施这些测试。

如果我们在 4 月份放眼整个美国,我们会发现我们每天都在进行 107k 到 305k 之间的测试。这些测试的阳性率徘徊在 10%到 32%之间,产生的“新感染”从 21,000 到 36,000 不等。现在,这可能是那些日子里新感染的实际数字,但是一些(真正的)简单的数学和一点点理性表明,情况几乎肯定不是这样。

举个例子:4 月 15 日真的感染了多少人?

再来看 4 月 15 日(来源)。基于检测的官方“新感染”人数为 30,317 人。但是这有一个问题。我们知道,死于新冠肺炎病毒的患者一般会在感染后三到四周内死亡。当我完成自己的建模时,我用了 23 天,是的,人们很容易认为价值应该更长。尽管无论是 23 天还是 28 天,情况都会有所变化,但方法和趋势结果是相同的。这意味着,在我们知道有多少人死于这种疾病的任何一天,我们都可以平均地说出 23 天前有多少人被新感染。

使用《T2 柳叶刀》上 研究中的数字,即 0.66%的真实感染病死率(注意,这是而不是 CFR,并尝试将无症状病例包括在内),我们将从 4 月 15 日起的 23 天作为预测日,并将该日的死亡人数除以 0.0066。5 月 8 日,美国有 1760 人死亡。这意味着仅在 4 月 15 日这一天就有大约 260000 例新感染病例。即使死亡率或死亡时间不完全正确,这两个数字甚至不在同一个区号内。在计算机科学中,我们称之为几乎一个数量级的差异。

因此,通过测试检测到的“新感染”数量可能相差甚远。但至少趋势给了我们有用的信息,对吗?没那么多。

如果我们看看 4 月份每天通过检测检测到的新病例数,这个数字波动很大

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

在这么大的一个国家,感染根本不是这样的。新感染的人数不能像那样激增。这意味着新的阳性检测结果对像我上面提到的那些其他因素比对新感染的实际人数更敏感。

在目前的感染与检测水平下,虽然政府可能会利用这些信息做出重要决定,但我认为我们不能依靠它们来衡量我们自身的风险。目前,阳性检测或“新病例”是一个糟糕的指标。

一旦阳性率降至 3%以下,并且这些结果开始与回溯死亡的数字一致,我们就可以开始寻找“新感染”作为指导。不过,在此之前,谈论并依赖这些数字的政府都是在用本质上毫无意义的数据做出决定。

如何用每天的死亡人数来计算我们可能在哪里

如果我们用这种方法来看死亡人数,并除以我们对实际死亡率的猜测,我们可以在过去的三到四周内找到任何一天。更有用的是,在我们有数据的过去的所有天里使用这种方法。这样,我们就可以绘制出每天发生多少新感染的图片。

但首先,让我们绕道进入流行病学领域。我发誓这只是个加油站,不是四人晚餐和过夜。

每种病毒都有一个 R0 值,它代表在“正常”条件下,每个感染者会感染多少新的人。这里面有大量的数学计算(见来自循证医学中心的这个好的解释者)。一般来说,研究人员已经确定新冠肺炎的 R0 约为 2.65。对于每一个感染的人,如果我们什么都不做,他们会在他们仍然具有传染性的时候把病毒传染给另外 2 到 3 个人。

还有另一个密切相关的值,叫做“有效 r”或 Rₑ.它是指给定人口在给定时间内的 R 值。假设我们把肯塔基的每个人都锁在家里(对不起肯塔基),让每个人住在单独的房间里,让消毒机器人给每个人送饭,一个月没人见人。将疾病传染给其他人变得不可能。在这种状态下,即使 R0 可能是 2.65,Rₑ也变成了 0。没有人会传染给其他人。在流行病学中,目标是通过多种方法的结合使 Rₑ低于 1,因为这意味着疾病会随着时间的推移而自然消失。Rₑ病毒低于 1 的人仍会被感染并(可能)死亡,但人数会逐年减少。

重要的一点是:R0 和 Rₑ不是疾病的固有属性——它们是根据我们在现实世界中观察到的事实计算出来的,它们的主要目的是测量、比较和预测。

还有……我们从基础流行病学课回来了。

假设我们有一份每日新增感染的清单,从死亡人数回溯 23 天。看看下表,看看纽约会是什么样子。作为快速参考,4 月 1 日的病例数是通过 23 天后(4 月 24 日)的死亡人数除以 0.0066 计算的。我们没有 4 月 16 日以后新增病例的数字,因为在本文撰写之时,我们只有 5 月 10 日至 23 天后的死亡数字。

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

4 天移动平均纽约死亡人数和他们暗示的新感染人数

然后,我们可以使用这些数字来确定任何一天的感染人数,并计算 rₑ——有效 r。但问题是:它只在回顾过去时有效。我们对这种方法的洞察力在今天之前大约 23 天就停止了,就像我们在纽约的例子一样。但不代表没用。

看看这两张密苏里州和爱达荷州每日死亡人数的图表:

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

密苏里州——图表的顶部是每天 44 人死亡

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

爱达荷州——图表的顶部是每天 6 例死亡

在密苏里州的图表中,我们可以看到,尽管每天的死亡人数有起有落,但趋势明显是上升的。对爱达荷州来说,连续三周每天的死亡人数稳步下降,有几天没有死亡。这些图表暗示了三到四周前这些州的 Rₑ值是多少?对密苏里号来说,它表明 Rₑ高于 1,而且可能相当高。

让我们来看看一些不同的 Rₑ价值观对死亡的影响。这是当你把 Rₑ从 5 点左右降低时会发生的事情(野火蔓延!)到一个更好的数字,比如 1.6。

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

大约 1.6 的 Rₑ仍然导致每天死亡人数的增加

这里的关键是强烈的红线。是每天的死亡人数。请注意,即使在我们将 R 降低到 1.6 之后,随着传染性水平的平稳,每日死亡人数会有短暂的下降,但随后会开始稳步上升。这看起来很像密苏里。我们可以假设,只要看看他们的死亡趋势,三到四周前,密苏里州的 Rₑ大约为 1.6。如果他们从那时到现在没有做任何事情来改变这一点…它可能没有改变,我们将继续看到每天死亡人数的攀升。

如果我们看到一个州在攀升后保持平稳,这实际上意味着 Rₑ可能在 1.35 之间。为什么?随着我们经历一波又一波的感染,受感染人群迅速增加。即使死亡人数持平——这意味着我们在过去新感染的人数持平——也意味着 Rₑ必须大幅下降,这样不断增长的感染人群中的每个人实际感染的人数就比以前少得多。看看 1.35 时的红色“每日死亡人数”线:

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

1.35 左右的 Rₑ会在某个水平找到一个稳定点,随着时间的推移缓慢但真实地上升。

似乎稳定下来了。在短时间内,事情看起来很平淡。如果你延长时间线,你可以看到事情仍在上升,但在对数尺度上的增长很小。

如果我们看到一个州的每日死亡人数持续下降,这意味着 Rₑ在三到四周前低于 1。对于有明显下降趋势的国家,这些趋势可以与人口采取的行动联系起来,这描绘了一幅美好的画面。以下是 0.8 的 Rₑ看起来是什么样子,再次关注每日死亡率:

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

在我自己的模型中,像宾夕法尼亚州这样的州封锁和死亡率下降之间的因果关系——这意味着 Rₑ低于 1——是非常非常清楚的。

现在,用同样的数学方法,做一些假设,你可以预测到今天。如果我们假设 Rₑ停留在我们所知的过去的最后一天,我们可以计算出在任何给定的状态下感染个体的合理数量(上面的浅绿线)。

这就是事情变得可怕的地方。

对于人数增长甚至更慢的州,这意味着三周前,他们仍然有 Rₑ值,这意味着越来越多的感染者四处走动。如果从那时到现在没有采取任何干预措施,那么从那时起,感染人群的数量可能增加了约 4 倍。

如果死亡人数相当稳定,你的 Rₑ在 1.35 左右,即使稍微提高一点(比如通过缩短距离提高到 1.6),传染病和每日死亡人数也会再次攀升。

如果你看到一个下降的趋势,Rₑ低于 1,根据你等待放松限制的时间,你可以将感染个体的数量降低到“跟踪和追踪”可以工作的水平。

那么,现在各州的情况如何?

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

上面是截至 2020 年 5 月 10 日所有州的快照。快速浏览一下,注意你看到的下降趋势。注意你看到的上升趋势。重新开放的州用红色列出,那些即将开放的州用橙色标出。这让你想知道这些政府是如何做决定的吗?

我找不到一个容易使用的可视化的按州划分的每天死亡人数,所以我做了一个你在上面看到的。如果你有兴趣实时查看这组图表,你可以点击这里的非常简单的工具。

区域差异

即使从国家层面来看,也可能不够细致入微。让我们以宾夕法尼亚州为例。首先,帕多的公开报道非常糟糕。他们不断修正死亡数字,这是好的,也是必要的,但当他们这样做时,他们只是报告了一个新的有史以来的累计死亡总数。如果你遵循了上面的建议,你会立刻明白为什么这是有问题的。你需要读一读死于什么时候,才能知道我们今天可能在哪里。

下面是宾夕法尼亚州每天死亡人数的图表。虽然我们看到了下降,但这只是在过去几天,该数据的趋势线现在充其量是水平的,甚至可以被解释为略有上升。

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

PA 每天的死亡人数—图表的峰值为 554 人

也就是说,宾夕法尼亚州绝大多数的死亡都发生在费城地区。宾夕法尼亚州是一个大地方,因此整个州的情况可能与其最大城市的情况有所不同。看看每天死亡人数的完整图表,人们可以很快得出结论,新冠肺炎只是在控制宾夕法尼亚州的边缘。然而,当我们逐县分析时,一幅不同的画面出现了。

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

阿勒格尼县每天的死亡人数

看看上面的阿勒格尼县——那里有着精彩的报道,当他们修正数据时做了正确的事情——我们看到了一些不同的东西。这个县的人口大约有 120 万,所以这个数字并不小。使用上述县数据的方法,数学预测到一周后部分重新开放时,整个县的感染人数将少于 800 人。周围的县更加乡村化,受新冠肺炎的影响更小。所以看起来,一个随机去商店并遵守规则(距离,面具)的人在那里被感染的几率几乎为零。与费城地区大不相同。

我怀疑大多数州都处于这种状态,但我还没有深入研究到足以完全充实它的程度。他们有一个或两个大型感染中心,而大多数人口相对安全。

这是否意味着人们不应该遵守规则?绝对不行。除非有疫苗、有效的治疗方法或足够的测试和结构来实施跟踪和追踪,否则事情真的可能随时失控,而我们唯一的真正指标——死亡——将在三到四周的滞后时间内检测出来。

人们希望我们的州政府能比我们普通大众获得更多更好的数据。PA 卫生部可能会为其内部模型分配适当的死亡日期。他们可以查看新冠肺炎的入院情况,这比死亡情况更能引起注意,因为我们现在对住院率有了一个很好的了解。他们可以查看医生关于先决条件的报告,看看是否有可靠的模式发展成为新冠肺炎诊断和入院。看看各州如何报告他们的数据,以及他们似乎仍然相信通过检测发现的“新病例”是一个有效的指标……我并不感到鼓舞。

重要的是

从国家层面来看,这些数字并不是很有帮助。美国是一个巨大的国家,很明显,爱达荷州的人应该有多担心可能与费城的人没有太多相似之处。在州一级,死亡不仅是每次死亡前 3-4 周新感染的良好预测指标,也是过去感染总体趋势的良好预测指标。我们现在有足够的数据来谈论封锁的效力,并可以用它来预测一个州今天的感染人数。也就是说,即使从州的层面来看问题,也会忽略相关的地方差异。

让它变得超级简单:听听死亡。如果你所在的州的死亡率有持续下降的趋势,那很好。如果你的死亡人数持平或增长,而你所在的州即将放开限制,那么请三思而后行。几乎可以肯定的是,麻烦正在酝酿之中,而当你发现的时候已经太晚了。

让机器接着写…!

原文:https://towardsdatascience.com/let-the-machine-write-next-16ba1a0cbdda?source=collection_archive---------48-----------------------

使用香草 LSTM、注意力和 GPT-2 的文本生成

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

劳拉·乔伊特在 Unsplash 上拍摄的照片

**目的:**在给定输入句子的基础上自动生成新句子。

路线图:

  1. 商业问题
  2. 数据讨论
  3. 电子设计自动化(Electronic Design Automation)
  4. 数据管道
  5. 模型架构
  6. 推理
  7. 比较
  8. 结论
  9. 未来的工作
  10. 参考

介绍

时光飞逝,从 17 世纪哲学家如莱布尼茨笛卡尔提出了将语言之间的单词联系起来的代码建议,到 1950 年艾伦图灵发表了一篇题为“计算机器和智能”的文章,NLP(自然语言处理)开始被探索。NLP 经历了从复杂的手写规则集(1980 年)到统计模型、机器学习模型到深度学习模型的演变。今天,自然语言处理的任务,如文本分类、文本摘要、问答系统、语言建模、语音识别、机器翻译、字幕生成、文本生成,都利用了最新的模型,如 Transformer、BERT、Attention。虽然螺母和螺栓是“神经元”,但它们的连接、训练、学习和行为取决于模型与模型,如 RNNs、seq2seq、编码器-解码器、注意力、变压器等。让我们来研究其中一项任务—文本生成。

1.商业问题

如果不是手动记下句子,而是假设我们精心设计和学习的系统生成或建议下一段或下一句话,会怎么样?这会让写作变得更容易。它会暗示一个句子的延续。它会产生新的标题或故事或文章或一本书的章节。Gmail 在自动回复和智能撰写中也利用了这一概念。

  • 问题描述

开发一个模型,它可以学习在延续中生成下一个句子或单词,并可以完成段落或内容。

  • 深度学习的作用

众所周知,人工神经网络从生物系统的信息处理和分布式通信节点中获得灵感,而数字逻辑也有从数据中学习的能力。

因此,我们可以将这个问题作为 DL 任务来提出,在这个任务中,我们将为模型提供数据,并以这样一种方式训练它,使它能够预测接下来的序列。我们将使用 DL 的所有工具和技术来使我们的模型自我学习。

2.数据讨论

我使用了从的太空和天文新闻数据。我已经从网站上删除了近 3700 篇文章。你也可以在这里找到的剧本。

因为所有的文章都是从网上搜集来的,所以它们包含了一些额外的信息,比如添加、弹出窗口、视频链接、在各种社交平台上分享的信息等等。因此,最好适当地清理数据,因为我们的模型将从收集的数据中学习。

3.电子设计自动化(Electronic Design Automation)

现在轮到探索和理解数据了。在数据科学领域经常有人说‘你越了解数据,你的模型就越能从中学习’!所以我们来试着探索一下。

3.1 清洁

我们的主要目标是使我们的文本数据清晰明了,以便我们的模型可以学习和理解英语句子的模式和行为。

  • 正如我前面提到的,我们的刮擦文章有一些额外的不必要的信息,我们必须删除。
  • 我们将把我们的文本转换成小写字母,这样我们的单词大小就会变小。
  • 我们将用“数字标签”替换所有数字,用“字母数字”标签替换字母数字单词,以减少我们的 vocab 大小。
  • 我们将删除所有标点符号,除了(。,?!)来生成有意义的句子。

数据清理

3.2 数据分析

我们将从文本数据中分析单词和字符。让我们从我们的文章中分析总单词和总字符的各种情节。

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

单词的 PDF 和 CDF

观察:

  • 大多数文章的长度在 1000 到 2000 字之间。很少有文章内容很长。几乎 95%到 98%的文章少于 2000 字。

分割训练集和验证集后,我们现在将分别分析每个集中的文本数据。

我们从训练部分来分析一下单词。

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

训练数据中单词的直方图

  • 从上面的柱状图中,我们可以看到,‘the’,‘the’,‘the .’、’ of ‘、’ and ‘、’ numtag '是在所有培训文章中最常见的单词。

来自训练和验证集的字符分析:

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

观察:

  • 上面的图包括关于训练和验证数据集中字符数的信息。
  • 训练数据中的大多数文章的字符数在 10 到 50 之间。内容的字符数在 10k 到 15k 之间。
  • Val 数据文章标题中的字符数在 10 到 70 之间,而内容中的字符数在 10.5k 到 11.5k 之间。

来自训练和验证集的词的分析:

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

观察:

  • 上面的图包括关于训练和验证数据集中字数的信息。
  • 训练文章在标题中具有从 5 到 15 字数,且在内容中具有大约 2k 的字数。
  • 来自验证数据的文章在标题中的字数在 5 到 15 之间,在内容中的字数在 1.9k 到 2k 之间。

结论:

  • 一些文章每周都有关于太空视频的更新和讨论,字数很少。所以从这类文章中得到的信息几乎是相似的,比如主机名、剧集名等等。
  • 视频内容不包括在文章中,所以除此之外手头没有多样性的内容。所以我们不会考虑那种文章。
  • 有些文章字数很少,我们也不会考虑。

3.3 数据预处理

我们可以使用基于字符或基于单词的方法来解决这个问题。基于字符的方法可能会导致句子拼写错误,所以让我们专注于基于单词的方法,在这种方法中,我们将用某个固定的数字替换每个单词,因为模型只理解数字,而不是单词!(我们将从预训练的 300 维手套向量中创建嵌入矩阵(此处为),用于我们训练数据集中出现的单词)。

下面的功能是将文本数据转换成数字。

让我们只为训练数据集中出现的单词创建一个嵌入矩阵。这是为了避免数据泄露问题。其向量不存在于手套模型中的单词,我们将为它们生成随机向量,而不是给它们分配零值。如果我们再次执行代码片段,我们将使用 random.seed()再次生成相同的随机向量。

正如我们所分析的,我们的文章有不同的字数,所以让我们决定固定数据长度并填充它们。

4.数据管道

我们的任务是处理序列数据,我们将使用递归神经网络(更准确地说是 LSTM!).主要方面是抓取数据,通过模型。

  • 我们有 1700 字的文章,一起传递会导致内存崩溃问题。因此,我们将把每篇文章分成固定大小的块以及一些序列长度。为了实现这一点,我们将使用 tf.data API,它使我们能够从简单的、可重用的部分构建复杂的输入管道。
  • 我们将构建 batch_generator,它根据给定的文章以固定的批量生成输入数据和相应的标签。
  • 它将首先生成一个具有固定数量序列的水平方向的批次,然后它将垂直生成一个固定数量的批量大小的文章。这种方法将保持每篇文章中单词序列的流动,因此我们的模型可以学习有意义的句子。
  • 我们将建立两个模型:简单的 LSTM 模型和基于注意力的编解码模型。对于每个模型,我们将创建一个单独的生成器。这里,我们将使用多对多模型,这样我们的输入数据及其标签的大小相同。

简单 LSTM 的批处理生成器

基于注意力的编解码器的批处理生成器

5.模型架构

我们将用三种模型进行实验:1)。LSTM 2)。注意 3)。GPT-2(生成式预训练变压器)。其中,我们将构建前两个模型。所以让我们开始一个一个的建造。

一、LSTM 模式

LSTMs 在记忆序列信息和状态方面更加强大。Christopher Olah 写了一篇很棒的博客来了解 LSTM,你可以在这里找到。我们将使用有状态 LSTM 和 return_state 来维护训练和推理阶段的序列信息。因此,不再拖延,让我们开始使用子类和 tf.keras.Model API 构建模型。

上述类将实现 LSTM 功能,并返回模型生成的输出以及隐藏状态,我们将在预测中使用。

损失函数和优化器

我们将使用稀疏分类交叉熵作为损失函数。使用它的原因是为了减少一些计算时间,因为不需要在一次热编码中编码标签。我们可以只对我们的标签进行二维编码,这样可以加快这个过程。我们也将设置from_logits=True,因此没有必要将我们的逻辑转换成概率,这将导致输出层没有激活函数。

在各种优化器中,我们将使用 RMSprop ,因为它为我们的数据集提供了更好的性能。

培训

我们将使用 TensorFlow 的急切执行进行训练,因为它可以立即评估操作,而无需构建图形,并帮助我们调试我们的模型。我们将为 tensorboard 写下我们的损失和梯度,并为推断阶段保存我们的模型。

让我们训练模型

我们将在下一节做预测和一些实验。

二。注意力模式

Bahdanau 在的这篇论文中讨论了基于注意力的方法。它基本上是在序列中给单词更多的权重。这些权重是通过另一个神经网络学习的。在这里,在这个博客里,你可以找到关于各种注意力算法的细节。在我们的模型中,我们将实现 Bahadanau 风格的注意。代码的灵感来自这里的任务是语言翻译,但在我们的任务中,我们可以试验它。

所以不要再拖延了,让我们深入研究一下。

编码器

编码器将获取输入的单词序列,并通过嵌入穿过 LSTM 层,然后返回其输出和隐藏状态。

关注层

  • 注意层用于根据编码器输出和解码器状态生成分数。Softmax 将应用于这些分数,以获得 0 到 1 之间的权重值。权重通过网络学习,并与编码器输出相乘。
  • 最后,重要的编码器输出被赋予更大的权重。

解码器

解码器用于将上下文向量与其输入连接起来,并生成输出。

培训

我们将使用相同的损失函数和优化器。训练将如上所述进行,但是这里我们将向编码器提供第一个字序列,向解码器提供下一个字序列。所以我们的批处理生成器和第一个有点不同。在解码机制中,我们将使用“教师强制”机制。

训练步骤

验证步骤

让我们训练模型。

使用注意力模型的推理将在下一节讨论。

三。GPT-2

  • 当 Vaswani 和来自 Google Brain 的团队提出标题为“注意力是你所需要的”的论文时,NLP 感觉就像是一个瞬间。我们可以使用变压器解决尖端解决方案。你可以阅读这篇很酷的博客了解更多细节。
  • GPT-2 是一个基于大型 transformer 的语言模型,拥有 15 亿个参数,在 800 万个网页的数据集上进行训练。GPT-2 训练有一个简单的目标:预测下一个单词,给定一些文本中的所有以前的单词。你可以从这里阅读更多内容。了解 GPT-2 再爽博客等着你!
  • 我们将使用预训练的 GPT-2(小型-124 米)和微调我们的文章数据。这就像 NLP 中的迁移学习。该模型非常强大,我们需要直接传递文本数据来训练它,它将完成所有的标记化、预处理并从中学习。
  • 太好了!!所以不要再耽搁了,让我们继续吧。代码摘自这里和上一篇博客

上述函数将根据我们的数据进行微调,并从中学习。对于实验,我们必须跳到推论部分,它就在下面:)

6.推理

对于推理部分,我们将使用来自检查点的最佳权重。所以我们来预测一下,看看吧。

一、LSTM 模式

我们将从 logits 的随机分类分布中抽取样本。并把它们转化成文字。

我们将使用 batch_size=1 初始化我们的模型,并从检查点恢复训练好的
权重。

这里,我们还从 LSTM 传递隐藏状态,以根据单词的顺序维护状态信息。来看看成果吧!

# Prediction
seed = 'In the history of spaceflight , only one nation'
temperature = 1.0
temp = predicttion_fun_using_disb(seed, stacked_model, temperature, 20)
print(seed + ' ' + temp)# input : 'In the history of spaceflight , only one nation'
# Output:
In the history of spaceflight , only one nation accord happy rubins
attainable accelerates writing violating contract topography finder
child walking concerns whitish barren equuleus generates undertakin
gs parasites femalesseed = 'Next to actually sending another spacecraft there'
temperature = 0.5
temp = predicttion_fun_using_disb(seed, stacked_model, temperature, 50)
print(seed + ' ' + temp)# input: 'Next to actually sending another spacecraft there'
# output: Next to actually sending another spacecraft there occasional noam famines scenic magnification mandated elliptic glow satellites scribbled permit tre warmer phases amateurs quotes meantime hooks loss lambda negatively appendages teams entailing terminate refrangibilities pella tarantula andrian selection ark dataset utterly mx enabled robot surya bands hangar sarah distinguishing etnos thunder jhuapl analogous interfering mathematicians tuesday writings uniting
  • 从上面的结果中,我们可以看到,当给定一些输入种子词时,我们的模型正在生成句子,尽管所有生成的词都与句子的意思无关。但是这个模型是理解动词和形容词的位置。

二。注意

让我们看看输出。

# Predictionseed = 'In the history of spaceflight , only one nation'
temperature = 1.0
final_string = predict_function_attention(seed, 20, temperature)
print(final_string)# input : 'In the history of spaceflight , only one nation'
# output: In the history of spaceflight , only one nation infall deadly subsy
stems atkinson moderate himalayan lance abrahamic improve construct
ing scistarter streak insufficient viking east deistic earthguide s
hellfish especially repurposed megalodon pressures vac definition i
nstantaneously komsomol zingers astrobee effect propane cancelled p
rematurely icesheetmike sandstones application volcanoes cephalopod
s misty send combes

从结果来看,可以说它能理解动词、名词、形容词的一点点排列。

但是有意义的句子呢?我们的 GPT 2 号会处理好的。

三。GPT-2

# restore from drivegpt2.copy_checkpoint_from_gdrive(run_name='run1')
sess = gpt2.start_tf_sess()
gpt2.load_gpt2(sess, run_name='run1')# Generateprefix = 'In the history of spaceflight , only one nation'
gpt2.generate(sess, length=50, temperature=0.5, prefix=prefix,
nsamples=5, batch_size=5 )# input : 'In the history of spaceflight , only one nation'
# output :In the history of spaceflight , only one nation has achieved the fe
at: the Soviet Union. But the Soviet Union did it. It was the first
nation to launch a rocket from a launch pad. It was the first natio
n to launch a rocket from a launch pad. It was the first to launch
====================
In the history of spaceflight , only one nation has managed to colo
nize another planet: the Soviet Union. The Soviets launched their f
irst lunar lander in November of 1972, and by the time it landed, t
he Moon was still in lunar orbit. They also made several attempts t
o colonize the Moon
====================
In the history of spaceflight , only one nation has held the title
of sole superpower – the United States. The Soviet Union, who were
the first nation to achieve space flight, was the only nation to ac
hieve space flight. And although they were technically still in the
process of achieving space flight, they
====================
In the history of spaceflight , only one nation has been able to la
unch satellites into space. The Soviet Union, for example, was able
to launch satellites into space on two separate occasions. However,
the Soviet Union was not able to carry out their first lunar base u
ntil the mid-1970s.
====================
In the history of spaceflight , only one nation has been able to ac
hieve the feat: the Soviet Union. Their first attempts were in Febr
uary of 1961, when the Soviet Union launched their first interconti
nental ballistic missile (ICBM) at New York City. They successfully
launched their ICBM on March 8
====================

呜!正如我们所见,它生成的句子就像它真的了解空间一样!!再来看看其他一些结果。

gpt2.generate(sess, length=50, temperature=0.7,
prefix="ISRO has launched Chandrayaan II", nsamples=5,
batch_size=5)# input  :'ISRO has launched Chandryaan II'
# Output : 
ISRO has launched Chandrayaan II at an altitude of only about 20 km
(15 miles) at a time from the launch pad in Chandrayaan, India. The
lander and its two-stage lander will be launched in the evening of
March 18th at 13:03
====================
ISRO has launched Chandrayaan II on September 18, 2019\. This missio
n will launch from the Vastal Pad, the Space Launch Complex 41 (SLC
-41) in Chandrayaan, India. The satellite was launched by the India
n Space Research Organization (ISRO) under
====================
ISRO has launched Chandrayaan II as it reaches its second mission l
aunch from Pad 39A at the end of this month.This comes just a week
after the probe launched from its command module on April 18, and w
ill launch on Pad 39A at the end of this month. And
====================
ISRO has launched Chandrayaan II to its orbit earlier this month. C
handrayaan II is the third mission to orbit the Earth from home and
the first space mission to orbit the Moon. The probe’s main goal is
to study the Moon’s interior structure, analyze
====================
ISRO has launched Chandrayaan II mission on the orbit of DSO on Jul
y 5, 2019.The maiden blastoff of this mission on the Salyut-2 (D-2)
mission is slated for July 5, 2019\. The launch window for DSO runs
from July
====================

我们可以看到,它也能够连接 ISRO-印度空间研究组织的完整形式。它还可以关联 2019 年 7 月,因为这是发布月。我们可以看到它真的很强大。

现在让我们给出一个与空间无关的句子,看看它会做什么。

gpt2.generate(sess, length=50, temperature=0.7,
prefix="Shah rukh khan has been offered a film",
nsamples=5, batch_size=5)# input : 'Shah rukh khan has been offered a film'
# output :Shah rukh khan has been offered a film called “Liftoff of Light“. I
n the film, a group of mission controllers (the crew members and th
e scientists) are shown how the probe will be launched en route to
the Moon. The mission team is also shown how
====================
Shah rukh khan has been offered a film about the events of the tim
e, and the circumstances leading up to it. In it, the filmmaker ask
s the reader to “walk on the Moon.” It’s a happy-couple film, for s
ure, but it�
====================
Shah rukh khan has been offered a film in the form of an interestin
g documentary film. “Khan’s ‘film’ is about the issues facing the
Asian people and the cause of human rights,” said Shah rukh, in rep
ly to a
====================
Shah rukh khan has been offered a film about the first lunar landin
g, called The Moon Under the Moon. This year sees the first opport
unity for Moon tourism in 2019, when the launch of the China Lunar
Exploration Program (CLEP) is scheduled to happen. The Chinese Luna
r Exploration Program (
====================
Shah rukh khan has been offered a film titled “Mysteries of the Uni
verse” that includes a holographic image of a star that is also the
subject of the film. The film will be released on May 29th, 2019.
A cow’s head has
====================

它还可以生成与空间相关的电影标题,并且可以包括关于电影的细节,而无需教导。是不是很神奇?

7.比较

我们用不同的批量大小、序列长度、lstm 单位、时期和学习率对前两个模型进行了实验。我们在 GPT-2 模型中损失最小,关于生成的句子,我们已经看到 GPT-2 是最好的。下面是对比表。

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

8.结论

  • 当我们为更多的时期训练 LSTM 和注意力模型时,由于我们的数据较少,它开始过度拟合。
  • 当我们提高学习率时,损失就会增加,这表明我们可能会超出最优解空间。当我们降低学习速率时,损失会非常缓慢地减少,这意味着学习进行得非常缓慢。
  • 如果我们保持较高的序列长度,我们的模型影响消失梯度问题。
  • 在 GPT-2 的情况下,它已经用大量的数据进行了训练。GPT-2 有更多的参数(124 米),这是非常大的比我们以上两个模型。它还使用了自我关注的概念,这有助于关注相邻的单词序列。
  • 由于强大的架构,GPT-2 提供了比其他型号更好的性能。也收敛的更快。

9.未来的工作

  • 我们可以训练大量的数据来得到更好的结果。

10.参考

  • 论文:

[1]陆,朱 Y,张 W,王 J,于 Y .【神经文本生成:过去、现在与超越】。2018 年 3 月 15 日。

[2]陈 MX,李 BN,班萨尔 G,曹 Y,张 S,陆 J,蔡 J,王 Y,戴 AM,陈 Z,孙 T. Gmail 智能撰写:实时辅助写作。第 25 届 ACM SIGKDD 知识发现国际会议论文集&数据挖掘 2019 年 7 月 25 日(第 2287–2295 页)。

  • 博客:
  1. http://karpathy.github.io/2015/05/21/rnn-effectiveness/
  2. https://www.tensorflow.org/tutorials/text/text_generation
  3. https://www . tensor flow . org/tutorials/text/NMT _ with _ attention
  4. https://openai.com/blog/better-language-models/
  5. http://jalammar.github.io/illustrated-transformer/
  6. http://jalammar.github.io/illustrated-gpt2/
  7. https://minimaxir.com/2019/09/howto-gpt2/
  • 平台:
  1. https://colab.research.google.com/
  • 课程:
  1. https://www.appliedaicourse.com/course/11/Applied-Machine-
    学习-课程

感谢您的关注。如果你有任何想法,可以留下评论、反馈或任何
建议。

你可以在我的 Github repo 上找到完整的代码(这里)。

很高兴在 LinkedIn :)上与您联系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值