TowardsDataScience 博客中文翻译 2019(三百三十六)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

教计算机理解推文的情感

原文:https://towardsdatascience.com/making-computers-understand-the-sentiment-of-tweets-1271ab270bc7?source=collection_archive---------16-----------------------

因为我们真的不想读唐纳德·特朗普写的所有东西

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

Donald Trump is well-known for many things, like his extensive use of Twitter and changing opinions faster than he breathes. What if we could get computers to read his tweets and understand his and his followers opinions towards a given topic? Photo credit: NICHOLAS KAMM/AFP/Getty Images

理解一条推文是正面的还是负面的是人类很少会遇到的问题。然而,对于计算机来说,这是一个完全不同的故事——复杂的句子结构、讽刺、比喻性的语言等等。让计算机很难判断一句话的意思和情绪。然而,自动评估一条推文的情绪将允许人们对各种问题进行大规模的意见挖掘,并有助于理解为什么某些群体持有某些观点。

在更基本的层面上,理解文本的情感是自然语言理解的关键部分,因此,如果我们希望计算机能够与我们有效地交流,这是一项必须解决的任务。

在这篇博文中,我将展示一个小型研究项目的成果,该项目是谢菲尔德大学 SoBigData 项目的一部分。我们测试了处理文本的不同方法,并分析了它们能够提取多少情感。请继续阅读,全面了解该项目及其成果!

介绍

该项目的目的是测试计算机使用机器学习能够在多大程度上理解文本的情感。为了做到这一点,我们给电脑输入了大量的推文,每条推文都被人类标记为积极、中立或消极的情绪。每条推文也有一个相关的主题,这一点很重要,因为根据讨论的主题,一个句子可以有非常不同的情感。例如,如果我们谈论质量,“高”这个词是肯定的,但如果我们谈论价格,这个词就是否定的。“绿色”在讨论环境问题时是积极的,但在讨论艺术时可能是中性的。现在,计算机的任务是预测给定推文和相关主题的情绪。

计算机如何阅读文本?

如果你没有机器学习的经验,这可能看起来是一个奇怪的问题。但机器学习是基于统计的,所以机器学习系统要处理的任何东西都必须用数字来表示。将文本转换成数字发生在所谓的 嵌入模型 中,开发这些本身就是一个主要的研究领域。嵌入模型将一个单词或一个句子变成一个向量,这个向量在训练过程中不断调整,使得具有相似含义的单词和句子以相似的向量结束。理想情况下,向量应该捕捉含义、上下文、情感等。但是这并不是一件容易的事情,这也是为什么许多不同的嵌入模型被开发出来的原因。一般来说,新型号性能更好,但它们也可能针对特定任务进行调整。

成熟的机器学习系统能够在情感分析方面达到最先进的水平,这是一种野兽。它们由多个组件组成,文本嵌入只是其中之一,而且通常很难评估系统的哪些部分是性能瓶颈。由于任何文本都需要表示为一个向量,以便机器学习系统能够处理它,所以任何分析,包括预测推文的情绪,都严重依赖于所选择的嵌入模型。但这并不是说系统的其他部分可能同样重要。

为了使文本嵌入的作用和贡献更加透明,我们开始用一个设计为最小模糊的系统来测试它们预测情感的性能。

我们如何预测情绪?

我们预测情感的方法非常简单,并且受到了协同过滤的启发。每条推文都有一个相关的主题,根据主题评估情绪是非常重要的(因为一个陈述很容易对一个方面持肯定态度,而对另一个方面持否定态度)。因为 tweet 和相应的主题都由相同维度的向量表示,所以我们可以取两者的内积,给我们一个表示情感的数字。没有理由认为这应该与“原始”嵌入一起工作,所以在取内积之前,我们学习并应用一个变换(稍后将详细描述)到主题向量空间。这样,即使之前没有看过题目,也能得到感悟。

我们希望能够预测三种不同的情绪(积极、中立、消极),所以我们实际上学习了话题空间的三种不同变换:一种预测积极情绪,一种预测中立情绪,一种预测消极情绪。当将推文与三个转换后的主题向量中的每一个进行内积时,我们会得到三个数字,可以理解为模型对每一种情绪的押注——数字越高,模型越相信这就是推文的情绪。

项目摘要

我们想测试不同的单词嵌入为一条推文的情感带来了多少信息。为了预测情绪,我们训练了一个模型,该模型学习主题向量的三种转换,使得推文和三个主题向量中的每一个的内积将是模型对三个情绪中的每一个的投票。

我们有几个不同的选择。首先,我们必须选择要测试的嵌入模型。其次,我们需要决定如何转换主题向量。第三,我们需要一个已经被人类贴上情感标签的推特数据集,这样我们就有东西来训练和测试这个模型。

决定设置

数据集

我们使用了为 SemEval-2017 任务 4 提供的英语数据集。这由大约 26k 条不同主题的推文组成,所有推文都被人工标注了情绪。我们保持任务组织者定义的划分,大约 20k tweets 用于训练,6k tweets 用于测试。

嵌入模型

我们选择测试以下四种嵌入模型:

  1. 【2003 年的神经网络语言模型 (NNLM),这是用神经网络学习单词嵌入的最早尝试之一。该模型构建了 128 维的单词向量,并将作为一种单词嵌入基线,这是更高级的模型应该明显胜过的。
  2. 如上所述的神经网络语言模型,但现在使用了标准化的单词向量,这有时会产生更好的结果。
  3. 来自 2018 年初的语言模型 (ELMo)的嵌入,已被证明在许多不同的任务中实现了最先进的结果。构建 1024 维单词向量。
  4. 通用句子编码器(使用)来自 2018 年初,一个经过训练的模型,可以在许多任务中找到有用的单词嵌入。构建 512 维单词向量。

所有四种嵌入模型都可从 TensorFlow Hub 方便地获得。

转换模型

选择转换主题向量空间的模型是很棘手的。一方面,我们希望尽可能保持原始向量空间不变。另一方面,我们希望转换足够灵活,使得单词嵌入中的信息实际上可以用于预测情感。因此,我们决定测试两种不同的转换模型:

  • 一个简单的仿射变换。这种转换只能表示最基本的转换,如缩放、旋转、剪切和平移,因此,在某种意义上,这将测试“原始”嵌入捕获了多少信息。
  • 由神经网络表示的更复杂的转换。我们使用具有两个隐藏层的神经网络,每个隐藏层具有 8 倍的嵌入维数、ReLU 激活函数和丢失。网络将主题向量作为输入,并输出转换后的主题向量。这种变换可以以高度非线性的方式扭曲主题空间,因此应该能够获得更高的精度。然而,它将更难训练,并且可能更容易过度适应训练集。

最终的模型将学习上述每种类型的三种转换,对应于我们想要预测的三种情绪。

纠正数据集中的不平衡

处理真实数据总是具有挑战性。特别是,如果单个情绪或主题被过度表达,模型可能会在训练过程中完全专注于此,这将使其他情绪或使用其他主题的预测远离。相反,我们希望确保该模型对所有主题和观点给予同等的权重,无论它们出现的频率如何。做出这些修正的效果是相当戏剧化的,也是值得记住的一课,所以让我们花几分钟来讨论这个问题。

数据集中的不平衡

绘制每个情绪的推文数量,数据集显示了巨大的阶级不平衡。

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

Distribution of sentiment classes for both the training and the test set.

特别是积极的情绪在训练数据中表现得非常突出——事实上,几乎 73%的训练推特都有积极的情绪。这意味着该模型将从学习预测积极情绪中比其他任何模型受益更多。另一方面,中性情绪与不到 10%的推文相关,如果有助于预测积极情绪,模型可能会简单地学会忽略这种情绪。

测试集中的分布明显不同。负面情绪比正面情绪更丰富,没有一条推文有中性情绪。这使得让模型平等地对待所有情绪变得更加重要。

事实上,对 NNLM 的仿射变换模型的测试表明,由于积极情绪在训练数据中普遍存在,训练的模型明显倾向于积极情绪。在这个测试中,训练数据中的主题被分成分别包含 90%和 10%主题的训练集和评估集。

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

A confusion matrix showing the actual sentiment of the tweets versus what the model predicted. The percentages show how often a specific, actual sentiment was predicted to be any of the three sentiments by the model. A perfect model would have 100% along the diagonal, meaning that the predictions are always correct. Here, however, it is seen that the model often chooses to predict positive sentiment, regardless of what the actual sentiment is.

该图示出了情绪预测的混淆矩阵,其中每一列对应于一个预测的情绪。每一行都显示了实际的情绪,对于每一行,每个矩阵元素的数量和颜色显示了具有这种实际情绪的推文的百分比,这些推文被预测为具有列中显示的情绪。

理想情况下,对角线应该接近 100%,这意味着预测的情绪对于几乎所有的推文都是正确的,但即使对于训练集来说,也有大量的非对角线元素。这意味着,即使模型知道正确的情绪,它也更倾向于默认预测积极的情绪。43%的负面情绪推文和超过 55%的中性情绪推文被预测为正面情绪。这对于分别为 39%和 78%的评估集来说更糟糕。

然而,在训练集和测试集中,每个主题的 tweets 数量也有很大差异。

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

Number of tweets associated with each topic for both the training and the test set. The topics have been sorted from left to right based on the amount of associated tweets and the their names have been omitted for clarity.

特别是对于训练集,我们看到每个主题的推文数量有明显的差异-一些主题有超过 100 条推文,而大约一半的主题只有大约 20 条或更少。

回到仿射模型的测试,查看给定主题的推文的情绪预测的平均准确性,显示推文越多的主题通常准确性越高。

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

The average accuracy of sentiment prediction for tweets in a given topic. There is a clear tendency in that topics with more associated tweets generally achieve a higher average accuracy.

这种趋势是有道理的:模型更多地受益于学习一种转换,这种转换对于有更多 tweets 的主题很有效。但这实际上并不是我们想要的,因为这意味着模型可能无法很好地概括。我们希望模型即使在看不见的主题上也能表现良好,在这方面过度适应几个主题可能没有帮助。

处理此类类别不平衡的一种方法是通过类别频率的倒数来衡量模型因错误预测而受到的惩罚。这意味着,对于频率较低的数据,模型会收到较大的误差,因此会更加关注这些数据。让我们看看这对模型的训练有什么影响。

纠正情绪失衡

仅用情感频率的倒数来重新训练模型和惩罚错误,我们已经获得了一个好得多的模型。

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

Confusion matrices for the affine model on NNML, correcting for sentiment imbalances in the training set.

对于训练集,所有情感的对角线接近 100%。评估集上的预测也有所改进,尽管还有很大的改进空间。

我们还看到训练集的每个主题的准确性有所提高,尽管这不是明确鼓励的。

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

Average topic accuracy for the affine model on NNML, correcting for sentiment imbalances in the training set.

有趣的是,评估集上的性能似乎有所下降。一种解释可能是,评估集中的大多数推文都有积极的情绪,因此该模型现在牺牲了一些准确性,以更好地表现消极和中性的情绪。

纠正主题不平衡

接下来,让我们看看当只使用话题频率的倒数来惩罚错误时会发生什么。这也导致了对训练集更好的情绪预测,这可能是因为不管与主题相关的推文数量如何,对主题进行同等加权会使模型暴露于更多种多样的情绪。

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

Confusion matrices for the affine model on NNML, correcting for topic imbalances in the training set.

但是真正的效果是在查看每个主题的准确性时看到的。对于训练集来说,准确率现在基本上与一个主题中的推文数量无关,大多数主题都接近 1。

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

Average topic accuracy for the affine model on NNML, correcting for topic imbalances in the training set.

修正情绪和主题的不平衡

最终的模型将基于情绪和主题的频率来衡量错误预测的惩罚。这是通过简单地将主题频率和情感频率的倒数相乘,并使用结果数量作为权重来完成的。这应该鼓励模型在训练期间平等地对待所有情绪和所有主题。

由此产生的模型确实看起来是情感和主题不平衡之间的一个很好的权衡。情绪预测相当准确,在评估集上的性能没有受到影响。

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

Confusion matrices for the affine model on NNML, correcting for both imbalances in the training set.

每个主题的平均准确率再次独立于与该主题相关的 tweets 的数量。

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

Average topic accuracy for the affine model on NNML, correcting for both imbalances in the training set.

虽然校正类不平衡对训练集明显有帮助,但在评估集上的性能仍然没有明显变化。该模型似乎不能很好地推广到新的主题,这可能意味着仿射变换限制性太强,或者训练集不能很好地代表评估集。当我们看最后的实验时,我们将回到这一点。

把所有的放在一起

现在,已经考虑了数据集中的类别不平衡,并且已经决定了嵌入和转换模型,我们准备测试模型,并且查看单词嵌入已经能够拾取多少情感信息。

设置遵循标准的机器学习方法:我们使用 10 折交叉验证 (CV)训练模型,并在测试集上评估每个折的最佳模型。这为我们提供了一种方法,当在(稍微)不同的数据集上训练时,我们可以预期模型的性能会有多大的变化。

包含一些基线实验总是一个好主意。这些应该是你能想象到的最简单的方法,如果你的高级模型不能战胜它们,你就知道有问题了。我们选择了两个简单的基线:1)使用来自训练集的最频繁的情感(这将是“积极的”)作为任何推文的预测,以及 2)使用来自训练集的随机情感作为预测。

下图显示了对所有八个模型和两个基线进行训练以及对未知测试集进行评估的结果。穿过数据点的垂直线表示穿过 10 个 CV 倍的一个标准偏差。

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

这里有许多有趣的观察要做。首先,任何嵌入模型都比基线有很大的改进。因此,正如预期的那样,单词嵌入捕捉到了可用于推导推文情感的信息。其次,转向 NNLM 嵌入,与仿射模型相比,当使用非线性模型时,似乎没有任何改进。这是有趣的,因为它表明嵌入空间足够简单,以至于仿射模型能够使用嵌入中可用的所有情感信息。这与较新的嵌入(ELMo 和 USE)形成对比,在 ELMo 和 USE 中,当使用非线性模型时,我们确实观察到改进,这表明这些模型学习的嵌入空间更复杂。对于 NNLM 来说,标准化的向量确实有比非标准化的向量表现更好的趋势,但在我们的实验中,这种影响并不显著。最后,虽然 ELMo 和 USE 都包含比 NNLM 嵌入更多的信息,但它们在这些实验中的表现非常相似。USE 包含的信息似乎比 ELMo 稍多,但并不多。然而,这仍然是有趣的,因为使用嵌入空间的维数比 ELMo 空间低得多,因此,模型的训练要快得多。

我们到了吗?

不,绝对不行。关于单词嵌入的信息内容,有许多有趣的问题需要回答。

例如,我们用三分制(消极、中立、积极)来处理情绪。扩展到更细粒度的情感,比如五分制,将需要更多的嵌入。嵌入包含这么多信息吗?

询问巨大的嵌入空间是否必要也是合理的。ELMo 嵌入是 1024 维的,但是信息可能嵌入在更低维的空间中。嵌入空间的维数减少如何影响情感的预测?

当测试主题空间的两种不同转换时,我们发现只有较新的嵌入需要非线性转换。扩展转换的类型,包括创建一些更复杂的神经网络,以及测试哪些嵌入受益于哪些转换,这将是很有趣的。这可能会让我们深入了解不同嵌入空间的复杂性。

外卖

在这个项目中,我们想测试不同的单词嵌入携带了多少关于推文情感的信息。我们通过构建两个模型来预测尽可能无干扰的情感,使我们能够看到原始单词嵌入包含多少情感信息。

结果显示,新旧单词嵌入确实携带了情感信息,并且新的嵌入比旧的嵌入包含更多信息,这并不奇怪。结果还表明,对于较新的嵌入,主题向量的非线性变换比仿射变换表现得好得多,这表明这些空间比较旧的嵌入更复杂。

总之,单词嵌入通常包含很多关于推文情感的信息,新的嵌入包含更多的信息。虽然并不令人意外,但它强调了高级嵌入模型对预测推文情绪的重要性。

承认

该项目是谢菲尔德大学计算机科学系 SoBigData 2017 短期科学任务(STSM) 的一部分,与 Diana Maynard 博士合作完成。非常感谢 Isabelle Augenstein 博士在整个项目过程中提供的大量讨论和建议。

让数据科学面试变得更好

原文:https://towardsdatascience.com/making-data-science-interviews-better-f6bba15d02df?source=collection_archive---------19-----------------------

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

Photo by Kaleidico on Unsplash

关于如何改进数据科学面试流程的一些未经请求的建议

我从求职者的角度思考并写了不少关于招聘过程的文章。但最近,在观察了我的朋友们(和其他新兵训练营的毕业生)一次又一次的面试后,我对公司如何更好地面试有了一些建设性的反馈。

面试官没有提前解决的商业案例问题

商业案例面试的实际目标是什么?这是为了测试应聘者在面对开放式问题时批判性思维和创造性思维的能力。

但是作为面试官,你如何评估这些事情呢?批判性思考部分没有那么难——如果这个人在基本的商业战略问题上磕磕绊绊,或者提出没有意义的建议(根据上下文),那么很可能是不行的。

创造性思维和为问题制定新颖解决方案的能力更难评估。我认为面试官(和一般公司)目前在这个方面做得不好——尽管事实上案例面试的主要目的是衡量这种能力。

在我看来,问题在于面试官在进行面试时更喜欢使用已知的、已解决的商业案例(通常是他们自己曾经做过的)。原因很明显:

  • 由于已经做过,对面试官来说相对来说并不费力——他或她已经知道答案以及如何处理这个案例。
  • 不存在不确定性(也没有看起来愚蠢的风险)。一般来说,包括面试官在内的人都会回避不确定性和风险。

但这些好处也是为什么案例面试没有公司普遍认为的那么有效的原因。

什么时候人们最容易接受新的和新奇的建议?答案是——当他们自己不确定答案是什么的时候。如果他们心中已经有了一个答案,特别是如果这个答案是他们自己想出来的,那么这些人就会被固定下来,可能会有偏见。在这些情况下,如果候选人提出了一个与你不同的解决方案,你可能会花时间解释为什么你的方法更好,为什么他们的方法是错的,而你实际上应该客观地评估候选人的答案。

如果面试官事先不知道答案,面试就变成了一个来回的头脑风暴会议——更准确地模拟了两个人一起工作的情形。与现在相反,案例面试往往会变成面试官坐在那里等着听到某个特定的关键词或概念,而候选人拼命地唠叨,试图检查所有的方框。

所以,公司和面试官们,我恳求你们试试我的建议。如果你带着一个未解决的问题去面试,并且向解决方案迈近了 5%,这难道不是一个强有力的证据,证明雇佣这个候选人会带来互惠互利的工作关系吗?

关注候选人提出正确问题的能力

我个人认为,如果你能提出正确的问题,那么你就成功了 80%。如果你知道如何对数据提出正确的问题并设计正确的实验(来回答这些问题),我会比你记住 OLS 的推导印象更深刻。

是的,花式数学隐含着一定程度的知识和教育。将您的想法合理快速地映射到 Python 代码的能力也很重要。但是我们生活在一个谷歌、维基百科、YouTube 教程和堆栈溢出的世界里。

想想你如何解决工作中的实际问题:

  • 首先,你将复杂的开放式问题转化为一系列不太开放的问题,这些问题可以通过你已经拥有或能够收集的数据来解决。
  • 然后你收集数据并进行实验。
  • 在这样做的时候,如果有你不确定如何写的代码或者一个你不熟悉的算法,你就失去了你的搜索技巧,很可能以栈溢出而告终。

因此,在你的头脑中已经有一个端到端的解决方案几乎是不可能的。因此,你不应该期望你的候选人也有。更确切地说,是评估他们提出正确问题的能力,以及他们足智多谋和快速学习的能力— 因为这些是候选人为你的组织增加价值的能力的更好的长期指标。

感谢阅读,干杯!

我最近的一些帖子,希望你能看看:

您的公司真的是数据驱动的吗?

数据科学家面临自动化的风险吗

数据科学家挣多少钱?

数据科学家赚多少钱第二部

软件工程师挣多少钱?

技能提升的更好方法

利用 OpenVINO toolkit,让深度学习模型为最坏的情况做好准备,并为跨平台做好准备。

原文:https://towardsdatascience.com/making-deep-learning-models-ready-for-the-worst-case-scenario-and-cross-platform-ready-with-c62284f87808?source=collection_archive---------29-----------------------

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

Photo by Fatos Bytyqi on Unsplash

随着 2020 年的到来,深度学习专家和爱好者社区期待着该领域创新的重要一年。随着世界各地每天都在构建越来越多的深度学习模型,人类对云和网络(尤其是 TCP)的依赖日益扩大。你可能会想,云依赖有什么问题吗?

最坏的情况:

估计你家里有一个面部检测锁,但建造不当,因为开发人员将模型安装在云上,设备必须使用云服务进行推理。现在,突然有一天,当你面对一个非常糟糕的网络连接,并且没有配置任何安全覆盖方法时,你将成为你的安全系统的受害者。

这种情况的另一个真实例子是位于印度奥里萨邦 Bhuvneshwar 的一家著名多专业医院的故事。他们训练有素地拥有一个深度学习网络,经过适当的训练和领域专业知识的调整,但它的实现方式是,它必须通过 TCP 将患者每秒的心率作为流发送到 web 服务器,以确定心肌梗死。在一场毁灭性的飓风袭击了沿海的奥里萨邦后,这个系统就没用了,因为根本没有手机连接。

如果不采取适当的步骤来部署在任何时刻做出关键决策所需的深度学习模型,该模型可能会面临最糟糕的考验。随着深度学习模型在关键决策操作中的快速发展,如果不考虑边缘情况进行配置,它可能会面临相同的抖振情况。如果安全监控或医疗保健系统突然失灵,可能会发生巨大的问题。

为了使这些模型免受这些问题的影响,我们需要以这样一种方式实现这些模型,即这些模型可以执行实时决策,而不需要连接到任何其他云服务或互联网。事实证明,这种方法更加安全,因为部署的模型在互联网范围之外,因此需要最高安全级别的工作负载可以直接在设备中实施。爱好者称这些 AI 模型为 Edge AI。在这个方案中,模型被直接放置在设备中,并且它们不需要网络连接来进行推理。我们现在将了解这是如何实现的。

中间代表:

我们使用 Tensorflow、Caffe、Pytorch、ONNX 等不同框架构建和训练的模型。可能非常大、资源匮乏,也可能依赖于架构,例如受限于特定平台或 CPU/GPU 内核。为了使这些模型能够成功地从任何设备或任何地方提供推理,我们需要将模型转换为中间表示格式,这包括模型在。xml 格式以及。bin 格式。

使用 OpenVINO toolkit 获取不同的模型并将其转换为 IR 格式:

OpenVino Toolkit ( 开放视觉推理和神经网络优化工具包 ) 是OpenCV 团队最初开发的一个开源深度学习工具包,包括不同的工具,使用模型优化器工具将不同的深度学习模型转换成 IR 格式。在转换由不同框架组成的模型的过程中,模型优化器工具只是作为一个翻译器,它实际上只是翻译经常使用的深度学习操作,如我们看到的 Tensorflow、Conv2D、Conv3D、Dropout、Dense、BatchNormalization 等。对于 Caffe,我们使用卷积、dropout_layer 等。并使用来自训练模型的相关权重和偏差来调整它们。英特尔发布的 OpenVINO toolkit 在以下网站上提供了大量不同的预训练模型,您可以将其部署到不同的设备上。这些预先训练好的模型可以通过模型下载器工具直接下载。使用模型下载器工具下载的预训练模型已经以具有不同精度级别的中间表示格式出现。这些精度水平实际上是模型的保存的权重和偏差的精度水平。不同的精度级别包括 FP32(32 位浮点)、FP16(16 位浮点)、INT16(16 位整数)、INT8(8 位整数,仅适用于预训练模型)等等。这些精度级别实际上很重要,因为它们易于部署到不同的平台上。精度越低,结果越不准确,但模型运行所需的资源少得多,因此可以完全部署到边缘设备中,而不会严重影响设备和模型的性能。让我们看看如何使用模型下载器从英特尔 OpenVINO toolkit 网站下载预先训练好的模型,以及如何使用它们对给定输入进行推断。

以下是预训练模型的链接,包含在输入模型之前对输入进行预处理的文档。

** [## 车辆-属性-识别-障碍-0039-open vino 工具包

该模型提出了一种用于交通分析场景的车辆属性分类算法。颜色平均…

docs.openvinotoolkit.org](https://docs.openvinotoolkit.org/latest/_models_intel_vehicle_attributes_recognition_barrier_0039_description_vehicle_attributes_recognition_barrier_0039.html)

假设在您的本地机器上安装并正确配置了 OpenVINO toolkit,那么让我们直接进入下载上述模型的过程。转到您的 OpenVINO 安装目录,使用管理员权限打开终端或命令提示符。现在,要下载上述模型,发出以下命令:

python C:/<OPENVINO_INSTALLATION_DIRECTORY>/openvino/deployment_tools/tools/model_downloader/downloader.py --name vehicle-attributes-recognition-barrier-0039 --progress_format=json --precisions FP16,INT8 -o \Users\<USER_ID>\Desktop

上述命令使用 downloader.py python 程序来解析命令行参数:

  1. — name:用于提供模型名称(如果用“— all”代替— name,将下载所有可用的预训练模型)。
  2. —精度:用于提供不同的精度级别(如果没有提供,将下载模型的所有可用精度级别)
  3. — progress_format=json:将进度报告的格式设置为 json 格式,程序可以对其进行分析。

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

Downloading pre-trained models from OpenVINO toolkit already in Intermediate Representation format.

中检查上述模型的中间表示。它是模型的架构模式。bin 文件包含权重和偏差。在。xml 文件,你可以在 XML 标签之间看到深度学习模型的不同层和属性可以在上面的格式中感知。

<layers>
............
<layer >  .......... </layer>
<layer> ...........</layer></layers>

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

.xml file of the pre-trained model

使用中间表示进行推理:

使用 IR 模型格式进行推理非常简单。对于上面的这个模型,我们需要根据输入尺寸对图像进行预处理,并恢复颜色通道。对于推理网络,我们需要使用。load_model()函数与模型。xml 文件

from inference import Network
inference_network = Network()
inference_network.load_model("/<MODEL_DOWNLOAD_FOLDER>/vehicle-attributes-recognition-barrier-0039.xml","CPU",   "/<OPENVINO_INSTALL_DIRECTORY>/openvino/deployment_tools/inference_engine/lib/intel64/libcpu_extension_sse4.so")
inference_network.sync_inference(preprocessed_image)
output = inference_network.extract_output()

现在需要处理推理网络的输出,并且需要使用 argmax 函数选择最大值。因此,我们需要以下面的方式处理输出,以确定汽车的类型及其颜色,并将文本叠加到输入图像上,作为推断的结果。

def handle_car(output, input_shape):
    color = output["color"]
    color_class = np.argmax(color)
    car_type = output["type"]
    type_class = np.argmax(car_type)
    return color_class, type_class

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

Input Image in the left. After the inference, the output is printed on top of the image.

将张量流模型转换为中间表示;

为了将 Tensorflow 模型转换为 IR 格式,我们需要获取保存在中的 Tensorflow 中训练的模型。pb 格式。剩下的非常非常简单,很容易实现。为了使用 OpenVINO 模型优化器将模型转换为 IR 格式,需要冻结张量流图。冻结 Tensorflow 模型意味着删除模型的预处理和训练相关元数据,以减小模型的大小,从而更容易部署。Tensorflow 提供了冻结和解冻深度学习图的内置功能。*.ckpt 文件包含冻结张量流模型的元图。

from tensorflow.python.tools import freeze_graph
freeze_graph.freeze_graph('Model.pbtxt', "", False,                           './Model.ckpt', "output/softmax",                           "save/restore_all", "save/Const:0",                           'Model.pb', True, "")

由于模型现在被冻结,所以它现在可以被直接转换成中间表示。以管理员权限进入终端或命令提示符,键入以下命令:

python C:/<OPENVINO_INSTALL_DIRECTORY>/openvino/deployment_tools/model_optimizer/mo_tf.py --input_model= /<MODEL_DOWNLOAD_DIRECTORY>.pb --tensorflow_use_custom_operations_config C:/<OPENVINO_INSTALL_DIRECTORY>/openvino/deployment_tools/model_optimizer/extensions/front/tf/ssd_v2_support.json --tensorflow_object_detection_api_pipeline_config /<MODEL_DOWNLOAD_DIRECTORY>/pipeline.config --reverse_input_channels

我们将使用reverse _ input _ channels反转颜色通道顺序,因为 OpenCV 使用 BGR 通道而不是 RGB 格式。为了调用对象检测 API 管道,我们需要将 pipeline.config 文件作为命令行参数传递给标志tensor flow _ object _ detection _ API _ pipeline _ config,以便正确配置模型的 IR。在上面和下面的示例中,我们将使用一个实际上是单次多盒检测器(SSD)的模型,因此我们需要使用tensor flow _ use _ custom _ operations _ config参数进一步指定命令,并传入一个 JSON 格式的配置文件。我们指定模型的。pb 文件使用 input_model 自变量。根据网络的深度,转换过程需要很长时间。

例如,我们使用 curl 下载一个预训练的 Tensorflow 模型,并使用tar -xvf提取 tarball

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

The Details of the Conversion Procedure can be seen in the image above.

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

On successful execution, the file location of the Intermediate representation of the Tensorflow model can be seen above.

将 Caffe 模型转换为中间表示:

为了将 Caffe 模型转换为 IR 格式,我们不需要像在 TensorFlow 模型中那样通过冻结它们来进行任何特殊类型的预处理。要转换成 IR,我们只需要在*中指定模型文件的位置。caffemodel 使用 input_model 参数,如果它包含一个名称与模型名称不同的 protobuf 文本文件,我们需要使用 input_proto 参数指定它的位置。

对于这个例子,下面我们将 GitHub 中的一个预先训练好的 Caffe 模型下载到我们的 Linux 机器中。并发出了以下命令:

python <OPENVINO_INSTALL_DIRECTORY>/openvino/deployment_tools/model_optimizer/mo.py --input_model <NAME_OF_MODEL>.caffemodel --input_proto <NAME_OF_DEPLOYMENT_PROTOBUF_TEXT>.prototxt

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

Conversion Procedure into IR from a model trained in Caffe.

因此,在上文中,我们讨论了如何通过 OpenVINO toolkit 的帮助,使用直接部署到设备中,以简单的方式将大型资源饥渴的深度学习模型转换为小型自治系统。在这种部署方式下,模型的数据流变得更加安全、快速和轻便。我们可以轻松降低在云系统的服务器上处理敏感信息的成本,我们可以通过每台设备提供超级敏捷的人工智能体验。

祝大家新年快乐!

真理可以有一千种不同的表达方式,但每一种都可能是真实的~斯瓦米·维威卡难达。**

让深度神经网络绘画来理解它们是如何工作的

原文:https://towardsdatascience.com/making-deep-neural-networks-paint-to-understand-how-they-work-4be0901582ee?source=collection_archive---------12-----------------------

深度学习的效果如此之好,这是一个谜。尽管有一些关于为什么深度神经网络如此有效的暗示,但事实是没有人完全确定,对深度学习的理论理解是一个非常活跃的研究领域。

在本教程中,我们将以一种不寻常的方式触及问题的一个微小方面。我们将让神经网络为我们描绘抽象的图像,然后我们将解释这些图像,以发展对引擎盖下可能发生的事情的更好的直觉。另外,作为奖励,在本教程结束时,您将能够生成如下图像(所有内容都少于 100 行 PyTorch 代码。点击查看陪同朱庇特的笔记本:

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

My neural network wants to be a painter when it grows up.

这个图像是怎么产生的?

这张图片是由一个叫做组合模式产生网络 (CPPN)的简单架构生成的,我是通过这篇博文了解到这个架构的。在那篇博文中,作者通过用 JavaScript 编写的神经网络生成了抽象图像。我的代码在 PyTorch 中实现了它们。

通过神经网络生成图像的一种方法是让它们一次输出完整的图像,比如说类似下面的内容,其中称为“生成器”的神经网络将随机噪声作为输入,并在输出层中生成完整的图像(宽度*高度)。

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

Image via A Short Introduction to Generative Adversarial Networks

与输出整个图像相反,CPPNs(我们将要探索的架构)输出给定位置像素的颜色(作为输入提供给它)。

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

Image via Generating Abstract Patterns with TensorFlow

忽略上图中的 z 和 r,注意网络正在接收像素的 xy 坐标,并输出该像素应该是什么颜色(由 c 表示)。这种网络的 PyTorch 模型如下所示:

注意,它有 2 个输入,3 个输出(像素的 RGB 值)。生成整个图像的方法是输入所需图像(特定大小)的所有 x,y 位置,并将这些 x,y 位置的颜色设置为网络输出的颜色。

神经网络实验

我第一次尝试运行你在上面看到的神经网络时,我最终生成了这些图像。

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

If I had buyers for this art, I’d sell it in a jiffy.

我花了好几个小时挠头,想知道为什么网络输出的是灰色,而不管我输入的是什么 x,y 位置。理想情况下,这是不应该发生的,因为对于这样一个深度网络。改变输入值应该改变输出值。我还知道,每次初始化神经网络时,它都有可能生成一个全新的图像,因为它的参数(权重和偏差)是随机初始化的。但是很明显,即使经过几次尝试,我从我的神经网络得到的只是这种灰色的粘性物质。为什么?

我的怀疑集中在所使用的特定激活功能上: tanh 。也许后续层中的多个 tanh 序列将所有输入数字压缩到接近 0.5。在输出层(代表灰色)。然而,我关注的博客帖子也使用了 tanh。我所做的只是把用 JavaScript 编写的博客神经网络转换成 PyTorch,没有任何改动。

我终于找到了罪魁祸首。这就是 PyTorch 在初始化新的神经网络时初始化权重的方式。根据他们的用户论坛,他们用一个从-1/sqrt(N)到+1/sqrt(N)范围内随机抽取的数字初始化权重,其中 N 是一层中输入连接的数量。因此,如果隐藏层的 N=16,权重将从-1/4 到+1/4 初始化。我的假设是为什么这会导致一种灰色的粘性物质,因为重量来自一个很小的范围,并且变化不大。

如果网络中的所有权重都在-1/4 到+1/4 之间,当乘以任何输入并加在一起时,也许会发生类似于中心极限定理的效应。

中心极限定理(CLT)证明,在某些情况下,添加独立的随机变量时,即使原始变量本身不是正态分布的,它们的正态和也趋向于正态分布(非正式的“钟形曲线”)

回想一下后续图层上的值是如何计算的。

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

Image via For Dummies — The Introduction to Neural Networks we all need !

在我们的例子中,第一个输入层有 2 个值(x,y ),第二个隐藏层有 16 个神经元。因此,第二层上的每个神经元得到 2 个乘以从-1/4 到+1/4 的权重的值。这些值相加,然后在它从激活函数 tanh 出来后,变成新值,传递给第三层。

现在,从第二层开始,有 16 个输入要传递给第三层中 16 个神经元的每个。假设这些值中的每一个都由 z. 表示,那么第三层中每个神经元的值是:

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

这里我们再做一个猜测。因为权重的方差更小(-1/4 到+1/4),z 的值(输入 x,y 乘以权重,然后通过 tanh 函数)也不会有很大变化(因此会很相似)。因此,该等式可以被视为:

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

并且对于每个神经元,从-0.25 到+0.25 抽取的 16 个权重之和的最有可能的值是零。即使在第一层,总和不接近零,网络的八层给了上述等式足够的机会最终产生接近零的值。因此,不管输入值(x,y)如何,进入激活函数的总值(权重之和*输入)总是接近零值,其 tanh 映射为零(因此,所有后续层中的值保持为零)。

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

X-axis is inputs to TanH, and Y-axis is output. Note that 0 is mapped to 0.

颜色灰暗是什么原因?这是因为 sigmoid(最后一层的激活函数)将这个传入值 0 映射到 0.5(表示灰色,0 表示黑色,1 表示白色)。

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

Note how Sigmoid maps 0 input value to 0.5

灰色粘稠物怎么修?

因为罪魁祸首是重量的小偏差,我的下一步是增加它。我更改了默认的初始化函数,将权重从-100 分配到+100(而不是-1/4 到+1/4)。现在运行神经网络,这是我得到的:

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

Voila! Grey goo is now some blobs of color.

这是一个进步。我的假设是正确的。

但是生成的图像仍然没有太多的结构。太简单化了。

这个神经网络正在做的是将输入乘以权重,推动它们通过 tanh 并最终通过 sigmoid 输出颜色。既然我固定了权重,我可以固定输入以使输出图像更有趣吗?嗯。

请注意,上面的图像是在我输入 X,Y 作为原始像素坐标时生成的,从 0,0 开始,到 128,128 结束(这是图像的大小)。这意味着我的网络从未将负数视为输入,而且由于这些数字很大(比如 X,Y 可能是 100,100), tanh 要么得到一个非常大的数字(它挤压成+1),要么得到一个非常小的数字(它挤压成-1)。这就是为什么我看到原色的简单组合(例如,0,1,1 的 R,G,B 输出代表你在上面的图像中看到的青色)。

如何让图像更有趣?

就像在最初的博文中一样(这是我一直在关注的),我决定将 X 和 y 归一化,所以我将输入(X/image_size)-0.5,而不是输入 X。这意味着 X 和 Y 的值将在-0.5 到+0.5 的范围内(与图像大小无关)。这样做,我得到了下面的图像:

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

Some more progress!

有趣的是,在前面的图像中,线条在右下方增长(因为 X,Y 值在增加)。在这里,由于 X,Y 值是归一化的,并且现在包括负数,所以线条均匀地向外增长。

但是,图像仍然不够漂亮。

如何让图像更加有趣?

如果你仔细观察,你会发现在图像的中间,似乎比边缘有更多的结构。这是数学之神给我们的暗示,我们应该放大那里去发现美。

有三种向图像中心放大的方法:

  • 产生大图像。由于像素坐标是归一化的,我们可以简单地运行神经网络来产生更大的图像。之后,我们可以通过图像编辑工具放大中间,看看我们发现了什么。
  • 将 X 和 Y 输入乘以一个小数值(缩放因子),这将有效地实现与前面的方法相同的事情(并避免我们在其余不感兴趣的区域上运行浪费的计算)
  • 由于输出是由输入*权重决定的,我们也可以通过将权重值从-100、+100 减少到+3、-3(记住不要减少太多)来缩放,而不是减少输入值。还记得重量在-0.25 到+0.25 之间时出现的灰色粘性物质吗?)

当我采用第二种方法,将 X 和 Y 乘以 0.01 时,我得到的结果如下:

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

I call it the Neural-Mondrian!

当我采用第三种方法并将权重初始化为-3 到+3 之间时,我得到了下面的图像。

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

Is your mind blown yet?

更多实验

我将权重初始化更改为正态分布(平均值为 0,标准偏差为 1),并生成了多个图像(来自随机初始化)。

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

当我删除所有隐藏层(只是输入到输出映射):

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

0 hidden layers

当我只保留一个隐藏层(而不是默认的 8 个隐藏层)时:

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

1 hidden layer

当我将隐藏层的数量增加到 16 层时:

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

16 hidden layers, 16 neurons per hidden layer

正如你所想象的,随着我增加隐藏层的数量,图像变得越来越复杂。我想知道,如果不是将层数增加一倍,而是保持层数不变(8),但每层的神经元数量增加一倍(从 16 到 32),会发生什么情况。这是我得到的:

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

8 hidden layers, 32 neurons per hidden layer

注意,尽管在上述两种情况下,网络中的总权重数是相似的,但是具有双层的网络比每层具有双层神经元的网络更加像素化。像素表明,在这些区域中,函数急剧变化,因此如果我们进一步放大,就会发现更多的结构。而对于具有原始层数但每层神经元加倍的网络,函数相当平滑,因此“可缩放性”较低。

当然,所有这些都是深度使神经网络更具表现力的另一种说法。正如关于深度神经网络表达能力的论文所建议的:

计算函数的复杂度随着深度呈指数增长

这正是我们所看到的。通用逼近定理说理论上,一个足够大的神经网络,即使只有一个隐层,也可以表示任何函数。但是,在实践中,网络越深,输入- >输出映射就越复杂,这是能够表现出来的。

毫无意义的实验,但是很有趣

如果我们将每层的神经元数量从 8 个增加到 128 个(一个数量级的增加)会怎么样。

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

Neuro-pollock!

如果我们从每个隐藏层 128 个神经元开始,但在每个后续层中逐渐减半,如下所示。

这是我得到的:

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

This one looks more “natural” than others.

还有 更多的实验可以做,并获得有趣的图像,所以我会把它留在这里给你玩的代码 (Jupyter 笔记本)。尝试更多的架构、激活和层。如果你有什么有趣的东西,在 Twitter 上给我加标签,或者在 Medium 上评论,我会在我的网络上分享。

或者你可以把神经网络生成的图像与神经网络生成的哲学结合起来,做出这样的东西:

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

My neural network is a stoic.

就是这样。希望你有兴趣生成漂亮的图像。

喜欢这个教程吗?也看看我以前的作品:

在 Twitter 上关注我

我定期发关于人工智能、深度学习、创业公司、科学和哲学的推特。跟着我上https://twitter.com/paraschopra

[## Paras Chopra (@paraschopra) |推特

Paras Chopra 的最新推文(@paraschopra)。@Wingify |的创始人兼董事长写道…

twitter.com](https://twitter.com/paraschopra)

用不到 15 行代码在 R 语言中制作交互式地图

原文:https://towardsdatascience.com/making-interactive-maps-in-r-with-less-than-15-lines-of-code-bfd81f587e12?source=collection_archive---------3-----------------------

如果你有地理数据,你会想把它显示在地图上。只用几行简单的代码,我们就可以用 r 语言制作一个漂亮的地图。我假设你的电脑上已经安装了 R and R 工作室。

我强烈建议您在自己的计算机上跟随。我在这个项目中使用的数据可以在这个链接获得,它显示了我在过去几年中参观过的所有博物馆。我建议要么下载它,要么找到你自己的地理空间数据来玩。你应该查看我的数据,虽然检查我在做什么。

我还将在 R 中使用管道操作符,这有时会令人困惑,看起来像这样%>%。管道运算符将左边的对象作为右边函数的第一个参数。因此,以下几行 R 代码是等价的:

print(sum(c(1,2,3,4,5)))c(1,2,3,4,5) %>% sum() %>% print()

我们将使用 2 个外包装,传单和 tidyverse。传单构建在 JavaScript 之上,对映射很有用(使用它不需要 JavaScript 知识)。tidyverse 是一个超级包,包含许多其他包,用于读取、组织和清理数据。知道 tidyverse 有很高的投资回报,我建议学习它。

步骤 1:安装软件包

我们在 R Studio 的控制台中运行这些代码行来安装所需的包。

install.packages("tidyverse")install.packages("leaflet")

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

步骤 2:加载包

从现在开始,我们将在一个新的脚本文件中运行我们的代码。我们现在用 library()函数加载包。

library("tidyverse")
library("leaflet")

步骤 3:加载数据

接下来,我们使用 tidyverse 中的 read_csv()函数读入数据。您可能需要在 read_csv()函数中更改 csv 的文件路径。

library("tidyverse")
library("leaflet")museum <- read_csv("museum.csv")

步骤 4:添加瓷砖

步骤 4A:首先,我们必须使用管道将数据传递给传单函数。光靠这个是做不出地图的。
第 4B 步:在这个链接处挑选出图块(地图的样子)。
步骤 4C:将传单函数的输出传递给 addProviderTiles()函数,唯一的参数是您在步骤 4B 中选择的图块。我选了雄蕊。

library("tidyverse")
library("leaflet")museum <- read_csv("museum.csv")museum %>% 
leaflet() %>%
addProviderTiles(providers$Stamen.TonerLite)

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

从现在开始,我建议在每一步结束时运行所有代码,看看地图是否合你的意。

步骤 5:添加多个图块

步骤 5A:选择另一组要添加的图块。
步骤 5B:使用组参数为每个切片命名,我选择了 ESRI . world imagery。
步骤 5C:添加图层控制(这使您可以看到两个切片)。您可以在右上角选择想要查看的互动程序

library("tidyverse")
library("leaflet")museum <- read_csv("museum.csv")museum %>% 
leaflet() %>%
addProviderTiles(providers$Esri.WorldImagery, group = "World Imagery") %>%
addProviderTiles(providers$Stamen.TonerLite, group = "Toner Lite") %>%
addLayersControl(baseGroups = c("Toner Lite", "World Imagery"))

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

步骤 6:使用数据向地图添加标记

步骤 6A:使用 addMarkers()函数,如果你的数据集有纬度和经度(或它们的缩写),你不需要填写纬度和液化天然气的参数。
步骤 6B:您可以选择设置标签和弹出参数,以便当您将鼠标悬停在标记上或单击它时显示信息。

library("tidyverse")
library("leaflet")museum <- read_csv("museum.csv")museum %>% 
leaflet() %>%
addProviderTiles(providers$Esri.WorldImagery, group = "World Imagery") %>%
addProviderTiles(providers$Stamen.TonerLite, group = "Toner Lite") %>%
addLayersControl(baseGroups = c("Toner Lite", "World Imagery")) %>%
addMarkers(label = museum$museum, 
           popup = ifelse(museum$`Presidential Library`=="Yes",
                          "A Presidential Library", # Value if True
                          "Not a Presidential Library")) # Val False

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

步骤 7:添加集群

如果你有很多很多的数据点,这是一件很好的事情,这样你的地图就不会被淹没。如果你们有非常接近的点,这也很好。我们需要做的就是用 clusterOptions 参数更新我们的 addMarkers()函数。

library("tidyverse")
library("leaflet")museum <- read_csv("museum.csv")museum %>%
leaflet() %>%
addProviderTiles(providers$Esri.WorldImagery, group = "World Imagery") %>%
addProviderTiles(providers$Stamen.TonerLite, group = "Toner Lite") %>%
addLayersControl(baseGroups = c("Toner Lite", "World Imagery")) %>%
addMarkers(label = museum$museum,
           clusterOptions = markerClusterOptions(),
           popup = ifelse(museum$`Presidential Library`=="Yes",
                          "A Presidential Library",
                          "Not a Presidential Library"))

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

步骤 8:设置开始缩放

这一步并不是必需的,但是如果您想将地图集中在一个特定的位置,您可以使用 setView()函数。我会关注亚特兰大。

library("tidyverse")
library("leaflet")museum <- read_csv("museum.csv")museum %>%
leaflet() %>%
addProviderTiles(providers$Esri.WorldImagery, group = "World Imagery") %>%
addProviderTiles(providers$Stamen.TonerLite, group = "Toner Lite") %>%
addLayersControl(baseGroups = c("Toner Lite", "World Imagery")) %>%
addMarkers(label = museum$museum,
           clusterOptions = markerClusterOptions(),
           popup = ifelse(museum$`Presidential Library`=="Yes",
                          "A Presidential Library",
                          "Not a Presidential Library")) %>%
setView(lat = 33.736309, lng = -84.388298, zoom = 11)

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

步骤 9:添加小地图

要添加一个小地图到我们的地图,我们只需要使用 addMiniMap()函数。您可以使用 addMiniMap()调整的两个参数是更改图块(这允许您更改地图背景,就像在主视图中一样)和 toggleDisplay(这允许您隐藏地图)。

library("tidyverse")
library("leaflet")museum <- read_csv("museum.csv")museum %>%
leaflet() %>%
addProviderTiles(providers$Esri.WorldImagery, group = "World Imagery") %>%
addProviderTiles(providers$Stamen.TonerLite, group = "Toner Lite") %>%
addLayersControl(baseGroups = c("Toner Lite", "World Imagery")) %>%
addMarkers(label = museum$museum,
           clusterOptions = markerClusterOptions(),
           popup = ifelse(museum$`Presidential Library`=="Yes",
                          "A Presidential Library",
                          "Not a Presidential Library")) %>%
setView(lat = 33.736309, lng = -84.388298, zoom = 11) %>%
addMiniMap(
    toggleDisplay = TRUE,
    tiles = providers$Stamen.TonerLite
    )

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

我们完了!您可能已经注意到这比 15 行稍微多一点,我选择通过将函数分成多行来优化可读性。祝你所有的地理空间工作好运!

用机器学习制作音乐

原文:https://towardsdatascience.com/making-music-with-machine-learning-908ff1b57636?source=collection_archive---------4-----------------------

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

Image from https://www.maxpixel.net/Circle-Structure-Music-Points-Clef-Pattern-Heart-1790837

音乐不仅仅是一门艺术,音乐是人类状态的一种表达。当一个艺术家创作一首歌的时候,你经常可以听到他们在那一刻的情感、经历和能量。音乐将世界各地的人们联系在一起,并在不同文化间共享。所以计算机不可能和它竞争,对吗?这是我和我的小组在为我们的机器学习课选择学期项目时问的问题。我们的目标是创造一些东西,让听众相信他们正在听的东西是由人类创造的。我认为我们个人取得了成功,但我会让你来评判(见本文底部的结果)。

方法

为了创作音乐,我们需要某种方法来学习现有歌曲的模式和行为,以便我们能够再现听起来像真实音乐的东西。我们所有人都对深度学习感兴趣,所以我们认为这是探索这项技术的绝佳机会。首先,我们研究了这个问题的现有解决方案,发现了来自sigur skúLi的关于如何使用 Keras 生成音乐的精彩教程。读完他们的教程后,我们对自己想做的事情有了一个很好的想法。

文件格式很重要,因为它将决定我们如何处理这个问题。教程使用了 midi 文件,所以我们照着做了,并决定也使用它们,因为它们很容易解析和学习(你可以在这里了解更多)。使用 midi 文件给了我们几个好处,因为我们可以很容易地检测音符的音高和持续时间。但是在我们一头扎进去,开始建立我们的网络之前,我们需要更多的关于音乐是如何构成的以及需要考虑的模式的信息。为此,我们去找了我的好朋友米奇·伯迪克。他帮助我们确定了一些关于我们方法的事情,并给我们上了一堂简单音乐理论的速成课。

在我们的谈话之后,我们意识到时间步长和序列长度将是我们网络的两个重要因素。时间步长决定了我们何时分析和产生每个音符,而序列长度决定了我们如何学习歌曲中的模式。对于我们的解决方案,我们选择 0.25 秒的时间步长和每个时间步长 8 个音符。这相当于 4/4 的拍号,对我们来说意味着 4 个音符的 8 个不同序列。通过学习这些序列并重复它们,我们可以生成一个听起来像真正音乐的模式,并以此为基础进行构建。作为起点,我们使用了 Skúli 的教程中提到的代码,但是最终我们的实现在几个方面与最初的有所不同:

  • 网络体系结构
  • 仅限于单键
  • 可变长度音符和休止符的使用
  • 歌曲结构/模式的使用

网络体系结构

对于我们的架构,我们决定主要依靠双向长短期记忆(BLSTM)层。下面是我们使用的 Keras 代码:

model = Sequential()
model.add(
    Bidirectional(
        LSTM(512, return_sequences=True),
        input_shape=(
            network_input.shape[1], network_input.shape[2]),
    )
)
model.add(Dropout(0.3))
model.add(Bidirectional(LSTM(512)))
model.add(Dense(n_vocab))
model.add(Activation("softmax"))
model.compile(loss="categorical_crossentropy", optimizer="rmsprop")

我们的想法是,通过使用歌曲中特定位置前后的音符,我们可以生成听起来像人类的旋律。通常在听音乐的时候,之前的音乐有助于听者预测接下来的音乐。有很多次,当我在听一首歌的时候,我可以随着特定的节拍摇摆,因为我可以预测接下来会发生什么。这正是在一首歌中逐渐形成一个落差时会发生的情况。这首歌变得越来越强烈,这使得听众在期待下降时产生紧张感,并在最终下降时产生解脱和兴奋的时刻。通过利用这一点,我们能够产生听起来自然的节拍,并带来我们已经习惯于在现代音乐中期待的同样的情感。

对于 BLSTM 层中的节点数量,我们选择 512,因为这是 Skúli 使用的数量。然而,我们确实对此做了一点试验,但是由于时间限制,我们最终坚持使用原来的数字。30%的辍学率也是如此(点击阅读更多关于辍学率的信息)。对于激活函数,我们选择了 softmax,对于损失函数,我们选择了分类交叉熵,因为它们很适合多类分类问题,如音符预测(你可以在这里阅读更多关于它们的信息)。最后,我们选择 RMSprop 作为我们的优化器,因为这是 Keras 为 RNNs 推荐的。

关键限制

我们做的一个重要假设是,我们将只使用来自同一个调的歌曲:c 大调/A 小调。这样做的原因是,通过让我们制作的每首歌曲都保持同一个调,我们的输出听起来会更像歌曲,因为网络永远不会学习会导致歌曲跑调的音符。为了做到这一点,我们使用了一个脚本,我们发现在这里尼克凯利。这部分真的很简单,但给我们的结果带来了巨大的改善。

可变长度音符和休止符

音乐的一个重要部分是动态和创造性地使用可变长度的音符和休止符。吉他手敲击的一个长音符,随后是一个平静的停顿,当我们听到演奏者的心和灵魂向这个世界溢出时,这可以向听者发出情感的波动。为了抓住这一点,我们研究了引入长音符、短音符和休止符的方法,这样我们就可以在整首歌中创造不同的情感。

为了实现这一点,我们研究了一个音符的音高和持续时间,并将其作为一个独立的值输入到我们的网络中。这意味着播放 0.5 秒的 C#和播放 1 秒的 C#将被网络视为不同的值。这使我们能够了解哪些音高比其他音高演奏得长或短,并使我们能够结合音符来制作一些听起来自然且适合歌曲该部分的东西。

当然,休止符是不能被遗忘的,因为它们对于引导听众进入期待或兴奋的状态至关重要。一个缓慢的音符和一个停顿,然后是一连串快速的音符,可以创造出一种不同于几个长音符之间长时间停顿的情感。我们认为这一点很重要,这样才能复制听众在听一首轻松的周日下午歌曲或周五晚上的派对歌曲时的体验。

为了实现这些目标,我们必须关注我们的预处理。这里,我们再次从 Skúli 教程中的代码开始,并根据我们的需要进行了修改。

for element in notes_to_parse:
    if (isinstance(element, note.Note) or
        isinstance(element, chord.Chord
    ):
        duration = element.duration.quarterLength
        if isinstance(element, note.Note):
            name = element.pitch
        elif isinstance(element, chord.Chord):
            name = ".".join(str(n) for n in element.normalOrder)
        notes.append(f"{name}${duration}") rest_notes = int((element.offset - prev_offset) / TIMESTEP - 1)
    for _ in range(0, rest_notes):
        notes.append("NULL") prev_offset = element.offset

为了详细说明上面的代码,我们通过将音符的音高和持续时间与一个“$”相结合来创建音符,以馈入我们的网络。例如“A$1.0”、“A$0.75”、“B$0.25”等。都将被单独编码以供我们的网络使用(通过将每个唯一的音符/持续时间映射到一个整数,然后将所有的整数除以唯一组合的数量,从而将每个编码为 0 和 1 之间的浮点数,来对输入进行编码)。更有趣的部分是计算插入多少休止符。我们查看当前音符的偏移,并将其与我们查看的上一个音符的偏移进行比较。我们用这个间隙除以我们的时间步长来计算我们可以容纳多少个休止符(减 1,因为这实际上是计算间隙中可以容纳多少个音符,但其中一个是我们实际的下一个音符,所以我们不想重复计算)。例如,如果一个音符从 0.5 秒开始,而下一个音符直到 1.0 秒才开始。时间步长为 0.25(每个音符以 0.25 秒的间隔播放),这意味着我们需要一个休止符来填补空白。

歌曲结构

最后,写一首歌最重要的部分之一是结构,这是我们发现现有解决方案中缺乏的东西之一。据我所见,大多数研究人员都希望他们的网络能够自己了解这一点,我不认为这是一种被误导的方法。然而,我认为这增加了问题的复杂性,并导致进一步的困难。这可能是我们解决方案的一个改进来源,尽管我们对此采取了更多的手动方法,并假设了一个恒定的模式。

我们做出的一个关键假设是,我们将只制作遵循特定模式 ABCBDB 的歌曲,其中:

  • a 是第一节
  • b 是合唱
  • c 是第二节
  • D 是桥

最初,我们尝试了 ABABCB,但这感觉太公式化。为了解决这个问题,我们决定引入第二节,它不同于第一节,但仍然相关。我们从一个随机的音符中生成了第一节,然后在第一节的基础上生成了第二节。实际上,这是生成一个两倍长的单个部分,并将其一分为二。这里的思考过程是,如果我们创作一首诗,第二首应该仍然符合同样的氛围,通过使用第一首作为参考,我们可以实现这一点。

def generate_notes(self, model, network_input, pitchnames, n_vocab):
    """ Generate notes from the neural network based on a sequence 
        of notes """
    int_to_note = dict(
        (
            number + 1,
            note
         ) for number, note in enumerate(pitchnames)
    )
    int_to_note[0] = "NULL"def get_start():
    # pick a random sequence from the input as a starting point for 
    # the prediction
    start = numpy.random.randint(0, len(network_input) - 1)
    pattern = network_input[start]
    prediction_output = []
    return pattern, prediction_output# generate verse 1
verse1_pattern, verse1_prediction_output = get_start()
for note_index in range(4 * SEQUENCE_LEN):
    prediction_input = numpy.reshape(
        verse1_pattern, (1, len(verse1_pattern), 1)
    )
    prediction_input = prediction_input / float(n_vocab) prediction = model.predict(prediction_input, verbose=0) index = numpy.argmax(prediction)
    result = int_to_note[index]
    verse1_prediction_output.append(result) verse1_pattern.append(index)
    verse1_pattern = verse1_pattern[1 : len(verse1_pattern)]# generate verse 2
verse2_pattern = verse1_pattern
verse2_prediction_output = []
for note_index in range(4 * SEQUENCE_LEN):
    prediction_input = numpy.reshape(
        verse2_pattern, (1, len(verse2_pattern), 1)
    )
    prediction_input = prediction_input / float(n_vocab) prediction = model.predict(prediction_input, verbose=0) index = numpy.argmax(prediction)
    result = int_to_note[index]
    verse2_prediction_output.append(result) verse2_pattern.append(index)
    verse2_pattern = verse2_pattern[1 : len(verse2_pattern)]# generate chorus
chorus_pattern, chorus_prediction_output = get_start()
for note_index in range(4 * SEQUENCE_LEN):
    prediction_input = numpy.reshape(
        chorus_pattern, (1, len(chorus_pattern), 1)
    )
    prediction_input = prediction_input / float(n_vocab) prediction = model.predict(prediction_input, verbose=0) index = numpy.argmax(prediction)
    result = int_to_note[index]
    chorus_prediction_output.append(result) chorus_pattern.append(index)
    chorus_pattern = chorus_pattern[1 : len(chorus_pattern)]# generate bridge
bridge_pattern, bridge_prediction_output = get_start()
for note_index in range(4 * SEQUENCE_LEN):
    prediction_input = numpy.reshape(
        bridge_pattern, (1, len(bridge_pattern), 1)
    )
    prediction_input = prediction_input / float(n_vocab) prediction = model.predict(prediction_input, verbose=0) index = numpy.argmax(prediction)
    result = int_to_note[index]
    bridge_prediction_output.append(result) bridge_pattern.append(index)
    bridge_pattern = bridge_pattern[1 : len(bridge_pattern)] return (
        verse1_prediction_output
        + chorus_prediction_output
        + verse2_prediction_output
        + chorus_prediction_output
        + bridge_prediction_output
        + chorus_prediction_output
    )

结果

我们能够通过这种方法获得令人惊讶的结果。我们可以始终如一地创作独特的歌曲,这些歌曲属于我们训练各自网络的适当流派。以下是我们各种网络的一些示例输出。

Ragtime

Christmas

Rap

结论

机器生成音乐确实是可能的。它比人类创作的音乐更好还是可能更好?只有时间能证明一切。从这些结果来看,我认为这是完全可能的。

未来的工作

可以进行一些改进,使之更接近真正的音乐。一些可能的想法/实验包括:

  • 学习歌曲中的模式,而不是手动拼凑部分
  • 将音符持续时间作为网络的单独输入,而不是单独处理每个音高/持续时间
  • 扩展到多种仪器
  • 远离 midi 文件,制作/学习真正的 MP3
  • 学习时间步长、序列长度和拍号
  • 引入随机性来模拟“人为错误/实验”
  • 允许多个键
  • 学习如何使用介绍和结尾

感谢

我要感谢我的队友 Izaak Sulka 和 Jeff Greene 对这个项目的帮助,以及我的朋友 Mitch Burdick 对音乐的专业知识,使我们能够取得这些伟大的成果。当然,我们要感谢 sigur ur skúLi 的指导,因为它为我们提供了一个很好的起点和一些参考。最后但同样重要的是,我要感谢尼克·凯利的剧本,他把歌曲转到了 c 大调。

这个项目的代码可以在这里找到:https://github.com/tylerdoll/music-generator

声明:我们项目中使用的音乐不属于我们,来自各种公共网站。

使 PATE 双向私有

原文:https://towardsdatascience.com/making-pate-bidirectionally-private-6d060f039227?source=collection_archive---------19-----------------------

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

Photo by Dayne Topkin on Unsplash

PATE,即教师集合的私有聚合,是 Papernot 等人在论文 中提出的一种机器学习框架,用于从私有训练数据 *进行深度学习的半监督知识转移。*该框架允许使用私有数据进行半监督学习,同时保留直观和强大的隐私保证。

PATE 基于这样一种思想,即如果在不相交的数据上训练的多个模型同意一个输入,那么关于它们的训练示例的私有数据不会泄露,因为所有模型都得出了相同的结论。通过只检索不同*“教师”*模型之间有很大相关性的输出,我们提供了直观的隐私。另一方面,当没有达成共识时,检索随机化的输出提供了强有力的隐私保证。这种随机选择可以通过噪声的聚集来获得,因此可以通过这种方式实现(ε,δ)-差分隐私。

此外,PATE 框架包含一个额外的步骤,以确保不会对教师的私人数据进行攻击,无论是通过多次查询还是通过模型的参数检查。为此,添加了一个*“student”*模型,该模型根据教师之前标记的公共数据进行学习。这样做消除了教师在后续查询中的需要,并确保学生模型只学习教师提供的概括。

该框架已经显示出实现了最先进的隐私/效用权衡,同时还具有灵活且广泛适用的实现。然而,在某些情况下,PATE 会陷入困境。这是指无法访问公共数据,或者学生的数据必然是私有的。PATE 要求学生与所有教师共享其数据,因此在此过程中无法保证隐私。这种情况的一个例子是,当一家医院想要训练一个神经网络进行诊断,并使用其他医院作为“老师”来标记其数据集。在这种情况下,PATE 可能是不可行的,因为“学生”医院可能有义务(在道德上或法律上)保持其数据集的私密性。

因此,提出了一个额外的步骤,其中教师集合被视为*“机器学习即服务”(MLaaS)* ,并且添加了加密来为学生的数据集提供保密性。在这里,我们将探讨如何应用这些变化,以及它如何影响 PATE 框架程序。

用 Pytorch 和 Pysyft 实现 PATE

本指南基于本回购。为了文章的可读性,代码的某些部分将被跳过或修改。

初始设置

首先,我们需要导入必要的库。本指南假定所有库都已安装在本地。

We’re declaring the necessary libraries and hooking Syft with Torch.

为了演示 PATE 的工作原理,我们将构建如下所示的示例:

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

Diagram of the scenario.

一家医院 S 拥有一些关于其患者的未标记数据,并希望使用这些数据来训练一个分类器。由于它的数据是无标签的,所以不足以训练一个学习算法。为了解决这个问题,医院考虑使用来自其他医院的标记数据来训练一个学习算法,并使用该算法来标记其数据。尽管其他医院愿意提供帮助,但出于隐私考虑,他们无权与第三方分享自己的数据。

让我们应用 PATE 框架。我们会把 S 医院当做我们的学生,把其他医院当做我们的老师。教师被要求使用他们的私人数据集来训练他们的学习算法。

1.宣布每个医院的工作人员

Syft 利用工人来识别和连接其他设备。在我们的情况下,我们有学生的机器(我们将认为是本地工作人员)和其他医院的设备(将被称为教师)。

Declaring the workers. The local worker is automatically declared when hooking Syft.

在本例中,我们仅使用了 10 名教师,但请记住,使用教师的数量在技术上没有限制,最好使用更大的团队

2.为教师定义和加载模型

PATE 框架的众多优势之一是它是模型不可知的,这意味着它不局限于特定的学习算法家族。尽管我们对所有教师使用相同的模型架构,但请记住这不是必需的。

This is the model for all the teachers.

本指南假设所有教师的模型都已经过培训。我们只需要加载它们并把它们发送到它们的机器上。在现实生活中,学生在这个过程中没有角色;相反,每个老师将负责实例化他们的模型。

Creating the models, loading them and sending them to each worker.

3.准备学生数据

现在所有的老师都准备好了,让我们从学生那里加载未标记的数据集。对于这个例子,我们使用 MNIST 测试集作为未标记数据集。

Load MNIST’s test dataset. This dataset will be used as the student’s unlabeled data.

在本例中使用已经标记的数据集的优点是,我们可以稍后将结果标签与真实标签进行比较。

至此,我们已经具备了 PATE 框架的所有要求。我们有一个未标记的数据集和多个模型,这些模型先前是在私有的、不相交的数据上训练的。现在,我们只需要将所有教师的意见汇总在一起,就可以得到数据集的标签。

4.将数据发送给每位教师进行分析

作为学生,我们希望从老师那里获得许多关于数据集中每个数据点的意见。从教师的角度来看,为了保护隐私,学生不能访问他们的模型。相反,它必须将其数据发送给每个老师,并等待分析。

Create a secure worker and send the unlabeled data for analysis.

注意,我们已经创建了另一个名为secure_worker 的工作者。 PATE 要求所有的意见都可以在一个点上获得,以生成投票最多的标签。因为我们不希望任何老师或学生看到原始意见,所以我们添加了第三方来负责汇总过程。

一旦完成,secure_worker将有一个形状为(data_size, num_teachers的矩阵。该矩阵包含来自数据集中数据点的所有教师的所有预测标签。

5.汇总意见

让我们考虑一下意见矩阵现在是什么样子。对于数据集的每一行,我们都有一些可能的标签,这些标签是由每个老师分配的。

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

An example of how the opinions matrix may look like. In some cases, there’s a clear consensus, while others require further processing.

通过为每个数据点选择投票最多的标签,我们获得了数据的广义分类。然而,如果存在没有明显标签的情况,那么我们就有选择一个由于过度拟合而被错误分类的标签的风险。这是一个隐私问题,为了减轻它,我们在所有投票计数中添加了一个仔细测量的拉普拉斯噪声。这样,我们增加了似是而非的可否认性,同时也保持了高准确性。

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

Previous scenario but with added noise. A high correlation between teachers leads to higher accuracy, while a low consensus with added noise leads to stronger privacy guarantees.

让我们来定义这个函数,我们将称之为*“嘈杂的 Argmax 机制”。*该函数将接收意见矩阵和ε值。这样,我们可以控制添加的噪声量。

Implementation of the noisy argmax mechanism.

记住意见矩阵在安全工作者的机器里。正因为如此,我们还必须发送要添加的噪声。

6.获得结果标签

既然定义了聚合查询,我们就可以获得结果并与真正的标签进行比较。

Getting the labels and comparing them to the true labels from the MNIST test set.

请注意,当将生成的标签与 MNIST 数据集中分配的标签进行比较时,我们获得了 90%的准确率。考虑到我们使用的ε的数量,这是一个很高的精度。这是迄今为止所做工作的完整图表。

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

Diagram of the implementation. Orange: unlabeled data sent. Red: predictions obtained. White: noisy labels returned.

在这一点上,学生可以利用这个数据集来训练他们的学习算法,并且没有从教师的私人数据中泄露隐私。

现在已经解释了 PATE 框架,让我们来看看为什么它不适合这个场景,以及应该做哪些改变。

使 PATE 双向私有

仔细观察前面的图表以及 PATE 实现,很明显学生的数据必须发送给所有教师进行分析。当这些数据公开时,这不是问题。但是,在某些情况下可能并非如此。我们医院的例子就是其中之一。在这种情况下,如果教师能够在不直接访问数据的情况下分析数据,那将是更好的。为了实现这一点,我们可以使用 附加秘密共享 对未标记数据集和教师模型进行加密。这意味着一些额外的步骤,并增加了对 PATE 框架的某些要求。

1.确保教师模型是可加密的

添加加密层意味着对数据进行的所有操作都必须兼容(并且安全)。在撰写本文时,仍有许多操作尚未在 PySyft 的库上实现。最重要的是,log_softmax()目前不兼容。这意味着每一个在最终层使用它的模型都必须被修改以允许加密。幸运的是,这种改变不需要重新训练模型。

Adapted model for encryption compatibility. Note that only one line changed.

2.加密模型

既然模型与附加秘密共享兼容,它们就可以被加密。这种加密需要多方共享数据。尽管我们可以使用这个例子中已经初始化的任何一个工人,我们还是要添加两个工人,分别叫做alicebob。他们唯一的工作就是保存所有的加密值。

create alice and bob

由于附加秘密共享只适用于整数,我们必须将权重和偏差转换为固定的精度值。另外,从 PySyft 0.1.23a1 开始,似乎有一个 bug 在试图加密远程模型的模型参数时会引发异常。这里有一个解决方法。

Encrypting the long way.

3.加密数据集并获取意见

理想情况下,我们只需加密整个数据集,并执行与之前相同的程序来获得预测。遗憾的是,加密计算需要很长时间,而且计算量很大,所以我们必须批量处理。这个想法是,我们从我们的数据集中取出一小批,加密后发给所有老师进行分析。产生的标签被发送到secure_worker进行解密。一旦它们被解密,noisy _ argmax 机制就会被使用,并且生成的一批标签会被发送给学生。最后,学生将每一批连接在一起,以获得所有的标签。

Obtaining noisy labels with an encryption layer.

这个过程需要很长时间才能完成。在我的例子中,获得整个数据集需要大约 7 个小时。这是一个主要缺点,如果要使用这种技术,必须考虑到这一点。

现在我们可以用真正的标签做同样的比较。

Checking the accuracy of our noisy labels obtained through encryption of PATE.

得到的精度与没有加密时一样。现在,学生可以使用这些数据来训练其神经网络,因为他们知道数据集在这个过程中没有受到损害。

结论

PATE 是一个令人惊叹的框架,它提供了良好的结果,同时实现了高隐私保证。然而,在没有公共数据的情况下,传统的 PATE 可能是不可行的。当这种情况发生时,可以添加一层加密,允许数据在不损害其隐私的情况下被处理。尽管如此,实现这一点所需的额外复杂性和时间使它对于日常场景来说是一种不合理的方法。此外,由于学生模型是用私有数据训练的,它仍然容易受到攻击,这些攻击可能会泄露有关数据集的更多信息。因此,当学生数据集的隐私不相关或不必要时,应首选传统 PATE。

附加注释

这篇文章是 Udacity 的安全和私人人工智能纳米学位项目的一部分。这篇文章的目的是呈现和解释我在这门课的期末专题,它应该被视为如此。

文献学

使用键盘宏简化编程—视频

原文:https://towardsdatascience.com/making-programming-easier-with-keyboard-macros-video-b3c2303a7881?source=collection_archive---------7-----------------------

Linus Tech Tips 最近的一个视频介绍了他们的一个编辑器如何使用宏进行视频编辑。这让我开始思考;可以很容易地创建宏来改进我的编程吗?

此视频演示了如何创建代码宏及其用途:

背景

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

Source: Linus Tech Tips — Can your Keyboard do THIS?? — Make ANY key a MACRO!

如前所述,这个想法是在观看 Linus 技术提示视频后产生的。现在,他可能在 3 个专用于宏的键盘上走得有点远了(如上图所示)。然而,我已经碰巧使用了一个有一些宏按键的,所以为什么不利用它。

我的键盘是罗技 G910,它有 9 个宏按键,3 个轮廓,总共有 27 种可能的组合。

它是如何工作的

幸运的是,罗技软件使这变得非常容易,但用其他设备复制也应该很简单。我只是分配每个宏来创建一个文本块,粘贴一些预定义的代码。

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

我为总共 10 个宏分配了 5 个键和 2 个配置文件。这些显示在下图中,并在视频中充分展示。

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

每个宏都粘贴预定义的代码,从而可以快速轻松地执行一些任务,例如:

  • 导入包/依赖项
  • 导入/导出数据
  • 使用设置的格式创建图
  • 创建 for 循环
  • 定义函数
  • 为减价单元格创建 LaTeX 方程

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

这些只是我发现的主要用例,但我相信每个人都会根据自己的需求有自己的想法。

我希望这对您自己的数据科学任务有用

谢谢

作为一名数据科学家,坚持提出建议

原文:https://towardsdatascience.com/making-recommendations-stick-as-a-data-scientist-b1124d489b0b?source=collection_archive---------16-----------------------

用这六个原则让推荐脱颖而出

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

你有没有向观众介绍过你的推荐,却让他们无处可去?如果你像大多数数据科学家一样,很可能你以前也遇到过这种情况。

数据科学家的部分工作是能够将您的工作转化为对利益相关者可行的建议和见解。这意味着让你的想法令人难忘,易于理解和有影响力。

在本文中,我们将探索《让 贴上 这本书背后的原理,并在数据科学的背景下应用它。这本书提出,最好的想法遵循六个主要原则:简单、出乎意料、具体、可信、情感和故事(成功)。读完这篇文章后,你将能够把这些原则融入到你的工作中,并增加你的建议和见解的影响力。

简单的

让一个想法变得简单就是把这个想法剥离到它的核心。不是要变笨,而是要创造一些优雅的东西。这意味着你应该避免用想法压倒你的听众,当你试图说三件事时,你什么也没说。使想法简单的另一个关键因素是避免埋没线索。如果在您的分析过程中,您发现 10%的客户贡献了 80%的收入,请以这一关键见解为线索!你应该遵循一个倒金字塔的方法,最初的几分钟传达最多的信息,随着你越走越远,你可以得到更多的细微差别。类比和隐喻也是简单简洁地表达你的想法的好方法。能够使用你的观众能够理解和联系的模式,会使它更容易理解。例如,一个一句话的比喻,比如优步代表 X,可以抓住你想要传达的核心信息。

意想不到的

意想不到的想法是违背人们的期望,利用惊喜的想法。你可以通过几种方式做到这一点,其中之一是让人们承诺一个答案,然后伪造它。例如,在透露真实答案之前,要求猜测员工在完成一项你希望自动化的任务上花费了多少时间。另一种激发兴趣和利用意外原理的方法是使用神秘事物,因为它们会带来“啊哈”时刻。这可能会以一个小故事开始你的陈述,直到最后你才决定。

混凝土

对于非专家来说,抽象是理解的敌人。作为数据科学家,您的工作是让您的建议和见解更加具体。理解的关键是使用具体的图像,并根据人类的行为和感觉来解释想法。具体性的天敌是知识的诅咒。作为数据科学家,我们需要抵制用不必要的技术信息淹没受众的冲动。例如,报告一个模型的均方根误差,可能没有把语言分解成任何人都能理解的更具体的术语有用。

可信

给你的推荐增加可信度有三种形式。当我们想到可信度时,第一个是最常见的,即利用专家来支持声明或断言。另一种方法是使用反权威人士,他们是有着强大故事的真实人物。例如,如果你在谈论吸烟的危害,一个患肺癌的人的故事将比一个无菌的统计数据更有影响力。给你的故事增加可信度的第三种方法是把你观点的可信度外包给你的听众。这意味着创建一个可测试的声明,让受众可以尝试。例如,声称来自区域 A 的客户比来自任何其他区域的客户多花费 80%的客户支持时间。在提出这一主张时,您的受众可以确认这一主张,从而更容易引导您进行推荐。

情绪

在你的想法中加入情感因素是为了让人们关心你。人类天生就能感受人类,而不是抽象概念。因此,一个人往往胜过一个综合统计数据。情绪的另一个组成部分是挖掘你的观众所认同的群体身份。记住这些特征,你就可以把相关的联想联系起来,并唤起你的听众最容易接受的某些图式。例如,如果你知道你的一个听众是一个坚持数字的人,并且想要看到你是如何得出某些结论的详细分类,那么添加一个附录可能是有帮助的。

故事

几个世纪以来,人类一直在讲故事,事实证明这是最有效的教学方法之一。如果你反思过去 5 年读过的书,你更可能记住有趣的故事,而不是客观事实。当把故事编织到你的推荐中时,一定要营造紧张气氛,不要一下子把所有东西都泄露出去。另一个有用的策略是讲故事,作为其他想法的跳板。创造开放式的故事,让你的观众可以在此基础上发展,这是让他们获得主人翁感的好方法。

下一次,当你需要提炼你的见解或推荐时,请记住这六条原则,你将很快创造出简单、意想不到、具体、可信的情感故事!

用 Jupyter 让远程服务器上的深度学习变得可容忍

原文:https://towardsdatascience.com/making-remote-deep-learning-tolerable-with-jupyter-7a754184e67c?source=collection_archive---------22-----------------------

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

Image credits

TL;DR 如何用 Jupyter 和远程服务器设置一个基本的深度学习环境,而不会发疯。

我最近开始从事深度学习,每当我想改变一个超参数时,我几乎疯狂地使用 vim 打开我的 5000 多行代码库。在习惯了 jupyter 之后,我希望能够使用 Jupyter 处理远程服务器上的文件。

如果你不熟悉 Jupyter,这里有一个的好帖子让你开始。熟悉之后,您现在可以继续阅读,将 Jupyter 配置为从本地浏览器运行,并在服务器上处理文件。

  1. 到远程服务器的 SSH
  2. 使用终端管理器,它允许我们在终端内创建多个会话。如果与远程服务器的连接丢失,它还可以防止代码被截断。因此,如果我们有需要长时间运行的代码,并且您可能想让它一直运行,那么这是非常有用的。我个人用 byobu 但是你可以用 tumx 。在 Ubuntu 18 中,这些都是预装的。如果您运行的是旧版本,并且没有看到 byobu,您只需使用
sudo apt-get install byobu 

在那之后,你可以跑路了

 byobu

我们使用终端管理器的主要原因是,当我们运行 Jupyter 笔记本时,终端会被用完。通过 byobu,我们可以为 jupyter 创建一个会话,并在另一个选项卡上运行测试/培训。

3.接下来,我们需要将浏览器上的“localhost”链接到我们第一次启动 Jupyter 的终端上

jupyter notebook -- no-browser -- port=8889

这将迫使 Jupyter 不打开浏览器,而使用端口 8889。我们可以随心所欲地改变它。

接下来,我们将这个端口从我们的服务器链接到本地机器上的“localhost”。我们通过打电话

ssh -N -f -L localhost:8888:localhost:8889 username@remote-server

请用您的用户名替换用户名,用服务器地址替换远程服务器。我们应该会看到这样的提示

The Jupyter Notebook is running at: [http://localhost:8889/?token=57cba986153f10a08c0efafa91e91e3299358a287afefaafa](http://localhost:8889/?token=57cba986153f10a08c0ebb91e91e3299358a287a08a5fd61)

现在我们可以跑了

localhost:8888 

这将在浏览器中启动链接到远程服务器的 Jupyter 会话。

页(page 的缩写)启动本地主机时,系统可能会提示您输入代码或令牌。为此,只需从终端复制粘贴令牌 id (/'后的字符串?token= )

你已经准备好了!

感谢阅读!

在 googleVis 中制作桑基图

原文:https://towardsdatascience.com/making-sankey-diagrams-in-googlevis-f9cabf433ffc?source=collection_archive---------19-----------------------

统计程序 R 可用于强大的数据可视化。

我用一个 R 包创建了一个 Sankey 图,展示了在一次大选中,从召回 2016 年欧盟公投投票到当前投票意向的流程。

制作桑基图

英国民意调查委员会成员民意调查的数据表显示了不同部分对问题(如投票意向)的回答。使用 2019 年 8 月 8 日至 9 日通过互联网小组对 2003 名英国成年人进行的 Opinium 民意调查。这项民意调查是由《观察家报》发起的。

这些数据表提供了受访者的准确人数:

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

This is an edited part of the Opinium/Observer data tables. (Image: Opinium/Observer)

然后,我们可以创建表格,显示主要政党(保守党、工党、自由民主党、英国退出欧盟党)和其他政党的留欧和脱欧投票。

准备好的数据表显示源变量和目标变量及其值:

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

使用 googleVis

googleVis 包允许 R 与 Google 图表工具接口。创建 Sankey 图的函数称为 gvisSankey,其选项的结构有些复杂。

要为节点输入正确的颜色,需要按照它们在表中的原始顺序进行排序:第一个源、目标和后续源。这一点还不清楚,需要反复试验。

opinium_sankey_gv <- gvisSankey(opinium_sankey_df, options = list(height = 500, width = 500, tooltip = "{isHtml:'True'}", sankey = "{link: { colorMode: 'source' }, node: { colors: ['#FFC010', '#0069B5', '#DC241F', '#FAA61A', '#12B6CF', '#DDDDDD', '#0087DC'] }, iterations: 1}"))

该图显示了从 2016 年召回欧盟公投投票到当前大选投票意向的流程。以下是 Opinium 民意调查的主要估计:

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

The interactive version of the Sankey diagram may be viewed. (Image: R/googleVis)

创建有效的数据可视化需要时间。使用 googleVis 也有局限性,比如无法为情节设置标题。

Jen Thompson 还提供了使用 gvisSankey 的指南。Google Sheet 文件可能下载了,并且我的 RPubs 文章可供阅读。

理解 Shapley 值

原文:https://towardsdatascience.com/making-sense-of-shapley-values-dc67a8e4c5e8?source=collection_archive---------3-----------------------

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

Image credit: Iker Urteaga at https://unsplash.com/photos/TL5Vy1IM-uA

我第一次听说 Shapley values 是在研究模型可解释性的时候。我遇到了 SHAP,这是一个可以更好地理解为什么你的机器学习模型会这样的框架。事实证明,Shapley 值已经存在了一段时间,它们最初起源于博弈论领域,可以追溯到 1953 年,目的是解决以下情况:

一群不同技能的参与者为了集体奖励而互相合作。奖励应该如何在团队中公平分配?

有趣的是,当一个“旧”的概念应用到另一个领域如机器学习时,它可以获得新的生命。在机器学习中,参与者是你输入的特征,集体支出是模型*预测。*在这种情况下,Shapley 值用于计算每个特征对模型输出的贡献。

沙普利值是如何计算的?大多数时候,你会在文学作品中看到这个等式:

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

让我们把它分解一下。在联盟游戏(之前描述的场景)中,我们有一组 Nn 玩家。我们还有一个函数 v ,它给出这些玩家的任何子集的值(或支出),即让 SN 的子集,然后 v( S )给出该子集的值。因此,对于一个联盟博弈( N ,v)我们可以用这个等式来计算玩家 i 的支付,即沙普利值。

我不知道你是怎么想的,但当我第一次看到这个等式时,我的第一反应是类似于*“这到底是什么???"*

我很难理解为什么它看起来是这样的。这花了一些时间,但在尝试了一点之后,它终于开始变得有意义了。所以,让我们开始吧!

好的,我们要做的第一件事是稍微改写一下初始方程

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

乍一看,我们似乎并没有使我们的处境变得更好,但是请耐心听我说。很快我将分解等式的不同部分,以便理解它们,但是让我们也定义一个玩具场景,我们可以使用它来使它不那么抽象。

假设我们经营一家生产砖的工厂。我们的一个制作团队由四个人组成: A 曼达、 B 恩、 C 莱尔和 D on(从现在开始我会用他们名字的第一个字母来称呼他们)。每周他们一起设法生产出 X 数量的砖。因为我们工厂进展顺利,我们有一笔奖金想分发给团队成员。但是,为了让我们以公平的方式做到这一点,我们需要找出每个人每周为生产 X 数量的砖做出了多少贡献。

这里的困难之处在于,我们有几个影响因素,它们都会影响团队能够生产的砖块数量。其中一个是团队规模,因为团队越大,生产的砖块就越多。另一个可能是团队成员之间合作的好坏。问题是我们无法以有意义的方式量化这些影响,但幸运的是,对我们来说,Shapley 值可以用来回避这个问题。

我们现在已经定义了我们的玩家( ABCD )以及他们正在参与的游戏(生产砖块)。让我们首先决定生产的 X 砖块中有多少可以归因于 D on,即计算 D 的沙普利值。如果我们将其与 Shapley 值公式的参数联系起来,我们就可以得到

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

所以 D 就是我们的选手 i 而整个团 N 由全部四名队员组成, ABCD 。有了这些,让我们开始仔细看看 Shapley 值公式的这一部分

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

它说我们需要把我们的一群人和排除我们现在关注的人。然后,我们需要考虑所有可能形成的子集。因此,如果我们从组中排除 D ,我们就剩下 {A,B,C} 。从这个剩余的组中,我们可以形成以下子集(即这些是 S 可以接受的集合)

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

总的来说,我们可以构建剩余团队成员的 8 个不同子集。这些子集中的一个是集,即它没有任何成员。现在让我们把注意力转向这一部分

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

这就是沙普利价值的一个基本概念开始发挥作用的地方:将玩家 i 加入游戏的边际价值。因此,对于任何给定的子集 S ,我们将把它的值与当你把参与人 i 包括在内时的值进行比较。通过这样做,我们得到了将参与人 i 添加到该子集的边际值

如果我们把它与我们的例子联系起来,我们想看看如果我们把 D 加到我们的 8 个子集中,每周生产的砖的数量会有什么不同。我们可以将这 8 个边际值直观地表示为

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

您可以将这些视为不同的场景,我们需要观察这些场景,以便公正地评估 D 对总体产量的贡献。这意味着我们需要观察如果没有人工作(即空集)会生产多少砖块,并将其与只有工作时的情况进行比较。我们还需要观察 AB 产生了多少砖块,并将其与 ABD 一起产生的砖块数量进行比较,以此类推,我们可以形成所有 8 个星座。

好了,我们现在已经知道我们需要计算 8 个不同的边际值。沙普利值方程中的求和告诉我们,我们需要把它们加在一起。然而,在我们这样做之前,我们还需要缩放每个边际值,这是等式的这一部分告诉我们的

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

当我们用除了玩家 i 之外的所有剩余团队成员构建子集时,它会计算每个子集大小的排列数。或者换句话说:如果你有 |N|-1 名选手,你能和他们组成多少组大小 |S| 的队伍?然后我们用这个数字来划分玩家 i 对所有大小为 |S| 的组的边际贡献。

对于我们的场景,我们有 |N|-1 = 3 ,也就是说,当计算 D 的 Shapley 值时,我们剩下的团队成员。在我们的例子中,我们将使用等式的这一部分来计算我们可以组成多少个大小为 0、1、2 和 3 的组,因为这些只是我们可以与剩余玩家一起构建的组大小。因此,举例来说,如果我们有那个 |S|=2 ,那么我们得到我们可以构造这个大小的 3 个不同的组: ABBCCA 。这意味着我们应该将以下比例因子应用于 8 个边际值中的每一个:

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

让我们思考一下为什么我们要这样做。我们想知道 D 对团队总产量的贡献有多大。为了做到这一点,我们计算了他对我们能组成的团队的每个星座的边际贡献。通过添加这个比例因子,我们平均出团队其他成员对每个子集大小的影响。这意味着当加入到规模为 0、1、2 和 3 的团队中时,我们能够获得 D平均边际贡献,而不管这些团队的构成

好了,我们现在差不多完成了,我们只剩下 Shapley 值方程的最后一部分需要分解,这一点也应该很容易理解

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

我们还有最后一个比例因子,需要应用于所有的边际值,然后才能对它们求和。我们必须将它们除以参与游戏的玩家数量,即我们总共拥有的团队成员数量。

再说一遍,我们为什么要这么做?好吧,如果我们看一下我们的砖厂例子,我们已经平均了其他团队成员对每个子集大小的影响,允许我们表达 D 对大小为 0、1、2 和 3 的组的贡献。谜题的最后一块是平均出团队规模的影响,也就是说 D 贡献了多少而不考虑团队的规模。对于我们的场景,我们通过除以 4 来实现这一点,因为这是我们可以考虑的不同组大小的数量。

我们现在已经到了可以最终计算出 D 的 Shapley 值的时候了。我们已经观察到他对团队中不同星座的贡献有多大。我们还计算了团队成员构成和团队规模的平均影响,最终使我们能够计算

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

I’m playing it fast and loose when it comes to using mathematical notation here, but this is more of a graphical illustration of what we’re doing than a mathematical one (it’s how I visualize it in my head).

我们有了,D 的沙普利值。在我们完成这项工作后,团队的其他成员就会知道每个人对每周生产的砖块数量的贡献,这样我们就可以在所有团队成员之间公平地分配奖金。

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

至此,我希望您已经更好地理解了沙普利价值观是如何运作的。如果你考虑到我们不需要知道任何关于价值函数 v 的内部工作原理,我们只需要观察它给不同子集的值就可以了,我们可以从参与游戏的玩家中制定出这些值。

这是沙普利价值观背后真正的力量和吸引力。然而,这是有代价的。对于一组参与游戏的 n 名玩家,您将拥有需要分析的 2^n 子集,以便计算沙普利值。

有一些方法可以使计算更实际可行,在介绍中我提到了 SHAP 框架,它的主要优势是当应用于机器学习时,它能够更有效地计算 Shapley 值(你可以在这里阅读更多信息)。

非常感谢Albin remng对本文初稿的宝贵反馈。

用 Python 建模新闻报道。第 1 部分:导言

原文:https://towardsdatascience.com/making-sense-of-the-news-part-1-introduction-f171d1da65a8?source=collection_archive---------11-----------------------

有很多新闻媒体有很多不同的观点。从某种意义上说这很好,但从另一种意义上说,任何人都不可能每天都阅读所有的东西,更别说那些忙碌几天的人了。然而,新闻只是随着时间的推移发生的一系列事件,所以这表明有一种方法可以对它进行建模,这样我们就可以了解正在发生的一些事情。

预测新闻趋势可以被认为是类似于人们已经试图在股票市场上做的事情,我们知道有一系列影响股票价格的因素,如果你得到了正确的因素,你就可以根据今天发生的事情预测出股票的未来价格。同样,如果我们真正理解了新闻中正在发生的事情以及影响新闻制作的因素,那么我们应该能够利用这种理解来预测未来的新闻制作。虽然不一定有经济效益,但了解事件的报道如何随着时间的推移而变化,可能有助于我们理解为什么人们会以不同的方式看待事件,以及事情是如何发展到现在这个地步的。

这是探索新闻报道建模系列文章中的第一篇博文。每篇文章都包含独立于其他文章运行分析的代码。它使用 60 天的数据来写博客(刚好够 SARIMA 以后使用),使用更长的时间会表现得更好。

迄今为止撰写的帖子:

  • 第 1 部分:简介(This)随机生成时间序列数据,然后查看一些真实的 Twitter 数据,然后查看一些新闻报道的时间序列,并通过向量自动回归来运行它们,以显示有模式可寻。
  • 第 2 部分:用有限的数据开始新闻预测提供了使用现成的神经网络和使用几个新闻报道的时间序列预测报道的基础,然后用 SARIMA 模型做同样的事情。
  • 第三部分:新闻网站与谷歌搜索趋势的互动继续使用 SARIMA 模型来研究新闻网站报道与谷歌搜索趋势之间的互动。它使用新闻数据和搜索数据来预测搜索率和新闻报道。

玩时间序列(随机数据)的快速复习

我正在用 python 做这件事,代码全部提供。您应该能够将代码粘贴到启用 python 的笔记本中(例如https://colab . research . Google)并运行它,它应该能够工作。当我有时间的时候,我会回去修复一些东西,但是我想我会把这篇博客文章放在那里,以防有人在寻找开始这种分析的地方。

所以让我们开始吧!使用 index 代表时间,我们可以使用 numpy 的 random 函数在 Python 中创建一个随机的外部(来自外部模型的输入)时间序列:

import pandas as pd
import numpy as np
exogenous = np.random.uniform(size=100)
df = pd.DataFrame(exogenous)
df.plot()

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

然后,我们可以创建一个内生时间序列,也就是说……我们的外生时间序列的 1.5 倍。

endogenous = 1.5 * exogenous
df =  pd.DataFrame([endogenous, exogenous]).T
df.columns = ["endogenous", "exogenous"]
df.plot()

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

我们现在可以运行 OLS,看到内生的是外生的 1.5 倍

import statsmodels.api as smmodel = sm.OLS(df.endogenous,df.exogenous)
results = model.fit()
results.summary()

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

OLS Regression Summary on Endo/Exo Series

万岁!我们得到了 1.5 的系数,关于内生导致外生。然而,我们真正想做的是能够提前预测将要发生的事情。由于这些值是随机的,我们不会有任何滞后,但我们可以通过将所有内生值下移一个单位并删除第一个时间序列来改变这一点…

df.endogenous = df.endogenous.shift()
df = df[1:]
model = sm.OLS(df.endogenous,df.exogenous)
results = model.fit()
results.summary()

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

OLS on shifted series

嗯,我们有一个系数,但是 R 平方和其他指标都不好。这很好,因为现在每个都是随机值。然而,我们希望看到以前的值,所以让我们尝试一个向量自回归模型,为了好玩,加入一些滞后值。

from statsmodels.tsa.api import VARmodel = VAR(df)
results = model.fit(maxlags=3)
results.summary()

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

VAR results

万岁!该模型估计,内生因素与外生因素的差距仅为 1.5 倍,而外生因素是 0.43±一些噪声,尽管这些噪声在统计上是显著的(应该是 0.5 倍,它也从滞后中获得了一些随机性)。

哦,只是为了好玩,我们可以很容易地说,我们可以用外生来预测内生,但不能用内生来预测未来的外生。为了测试这种情况有多严重,我们可以使用格兰杰因果关系,这基本上是对每个序列分别运行 OLS,然后看看在第二个时间序列中添加是否有助于我们获得更好的数字。因此,运行测试检查第二个时间序列是否有助于预测第一个时间序列。(也就是说,h_0 将是第二个变量不会导致第一个变量,所以如果我们可以否定 h_0,这意味着第二个变量不会导致第一个变量,尽管否定 h_0 只是表明存在相关性,而不是实际的因果关系)。

from statsmodels.tsa.stattools import grangercausalitytestsgc = grangercausalitytests(df[["endogenous", "exogenous"]], 2)

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

Granger causality of exogenous on endogenous

在滞后 1 运行从外生到内生的格兰杰因果关系会给我们一个比滞后 1 和滞后 2 更好的检验结果(因为滞后 2 只是噪声)。现在我们可以检查另一个方向。

gc = grangercausalitytests(df[[“exogenous”, “endogenous”]], 2)

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

Granger causality of endogenous on exogenous

我们从结果中看到,在内生->外生方向上没有统计上的显著关系,所以不能拒绝 h0。

太酷了,我们记住了什么是时间序列,并可以对它们稍加修改。还有其他重要的东西,如正常化趋势和季节性,以及扰乱自相关,但我们可以稍后再担心,现在让我们来看看新闻。最终,在训练数据之外的任何更好的预测都将是我们所关心的,加入不同的函数只是提高了我们用来判断模型是否好的准确性。

新闻时间系列《荒野》(推特)

在进入新闻之前(这是一件痛苦的事情,除非你手头正好有一份新闻文章的档案,我将在稍后介绍一种变通方法),让我们看看一些随机的有新闻价值的推文。谢天谢地,有一个很好的有新闻价值的特朗普推文档案可供查看。

所以我们可以去http://www.trumptwitterarchive.com/archive然后去“下载”——>“JSON”抓取川普所有推文的档案。我们将把弹出的结果复制/粘贴到一个实际的。json 文件在我们的工作目录中;我把它叫做“trump_tweets.json”。

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

Going here, downloading Trump’s tweets

所以我们可以把它移植到熊猫身上。

df = pd.read_json(“trump_tweets.json”)
df.head()

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

Head of the json file

所以我们看到我们有一堆推文的数据。我们有一堆 created_at 的时间戳,每条推文有多少赞,id 字符串(通过追加到 https://twitter.com/realDonaldTrump/status/)的末尾链接到原始推文)。最重要的是,我们得到了文本。

所以让我们忽略除了 text 和 created_at 之外的一切。现在,有很多方法可以篡改文本,但是我不知道如何在博客文章的这一点上做好自然语言编程。那么看看他发的微博有什么有趣的呢?

嗯,发生了很长时间的事情是俄罗斯勾结和穆勒报告的整个事情。因此,让我们看看他从 2017 年初开始通过 2019 年 3 月的巴尔备忘录使用一些基本的字符串匹配来发布关于俄罗斯和勾结的推文的频率。我们将从他的文本开始,并使其小写

#convert created_at to datetimeimport datetime
df.created_at = pd.to_datetime(df.created_at)df = df[(df["created_at"] < datetime.datetime(2019,3,1)) & (df["created_at"] > datetime.datetime(2017,1,1))]# create a column for lower case
df[“text_lower”] = df.text.apply(lambda x:x.lower())len(df)
>>> 41420

太好了,我们已经有 41000 条推文了。现在让我们做一些标记

df[“russia”] = df.text_lower.apply(lambda x: x.find(“russia”) > -1)df[“collusion”] = df.text_lower.apply(lambda x: x.find(“collu”) > -1)

我们可以只选择那些提到这两个词的推文

#create df where the previous rows had either russia or collusion labelrc_df = df[df["russia"] | df["collusion"]].set_index("created_at")

我们可以重新采样,得到每天的计数,然后继续绘制

rc_df_d = rc_df[["russia", "collusion"]].resample("d").sum()rc_df_d.plot(figsize=(12,8)

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

我们可以运行我们的风险值模型

模型= VAR(rc_df_d)
结果=模型.拟合(maxlags=5)
结果.总结()

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

因此,我们看到,到目前为止,我们为我们的模型计算的大系数是他之前是否在推特上发布过关于这个主题的消息,至少在日常水平上。

但是我们不需要只处理每日粒度,我们也可以查看每周粒度。

rc_df_w = rc_df[[“russia”, “collusion”]].resample(“w”).sum()
rc_df_w.plot(figsize=(12,8))

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

运行 VAR,我们得到几乎没有关系,除了勾结推文可能与俄罗斯推文 2 周前。

model = VAR(rc_df_w)results = model.fit(maxlags=3)results.summary()

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

因此,在每周水平上,我们开始看到俄罗斯的推文有一个轻微的系数(. 18),导致在 2 周的滞后期内关于勾结的推文。所以我们也可以加入更多的变量。让我们随便找个东西,比如,哦,中国,扔进去,重新算一遍。

df[“china”] = df.text_lower.apply(lambda x: (x.find(“china”) > -1) or (x.find(“chinese”) > -1))rcc_df = df[df[“russia”] | df[“collusion”] | df[“china”]].set_index(“created_at”)rcc_df_d = rcc_df[["russia", "collusion", "china"]].resample("d").sum()rcc_df_w.plot(figsize=(12,8))

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

Oh, wait, I think there’s a trend there ish. and a seasonality.I should have covered stationarity and decomp.

所以我们可以检查我们的风险值

model = VAR(rcc_df_d)results = model.fit(maxlags=5)results.summary()

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

所以在前两者的每日水平上看不到太多,但是看到有一个 0.12 的系数在 4 天的共谋滞后上。

我们可以在那里运行我们的每周 VAR,看看会有什么结果。

model = VAR(rcc_df_w)results = model.fit(maxlags=3)results.summary()

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

因此,对于这个模型,到目前为止,俄罗斯推文的中国系数有 2 周的滞后,俄罗斯串通有 2 周的滞后,中国串通有 1 周的滞后。所以这里有更多的东西需要挖掘(这涵盖了整个时间段),以检查这些关系何时成立以及多久一次,但现在我们将转而实际查看新闻。因为这个帖子是关于新闻的,不是关于推文的。但现在你看到了如何从 tweets 中提取一些文本,将其转换成时间序列,并运行任何你想在其上运行的模型。

所以终于有了真正的新闻

预标记集合:GDELT

GDELT[https://www.gdeltproject.org]是一个非常酷的项目,它每天检查大约 10 万个新闻网站,给所有文章贴上标签,并使它们可用。有一个版本 1 每天拉和版本 2,每 15 分钟拉一些更好的标签。这些标签包括主题(他们自己编的)、人物、地点和其他一些我一时想不起来的东西。

我们将通过下载过去 60 天的数据来了解这一点。如果你知道你在做什么,你可以继续从他们的 BigQuery 数据库中提取你想要的东西,这个数据库可以追溯到 2014 年(尽管早期的文章很糟糕)。

因此,这将是一个有点内存密集型(15gb 左右),因为我要保持一切在内存中,而不做任何偷偷摸摸的事情。因此,如果你正在使用谷歌 Colab(【https://colab.research.google.com】T2),你会想切换到一个 GPU,并运行你的内存真正快速使用免费的 25GB 内存升级。如果没有,嗯,你真的可以把所有这些都贴上标签,实际上只需选择相关的出版商,但这只是让你开始拥有你想要的一切。

所以让我们开始吧。

首先,让我们确保安装了 gdelt 的 python 包

!pip install gdelt
import gdelt
gd = gdelt.gdelt(version=1)

现在,我们将提取最近 60 天的 CSV,并将其保存为 python pkl,为什么不呢

#re-importing stuff from earlier in case skipped
from statsmodels.tsa.api import VAR
import pandas as pdimport osos.makedirs(“data”,exist_ok=True)import datetime
cur_date = datetime.datetime(2019,10,7)-datetime.timedelta(days=60)
end_date = datetime.datetime(2019,10,7)
while cur_date < end_date:
  print(cur_date) year = cur_date.year
  month = str(cur_date.month)
  day = str(cur_date.day)
  if cur_date.month < 10:
    month = “0”+month
  if cur_date.day < 10:
    day = “0”+day
  results = gd.Search([‘%s %s %s’%(year, month, day)],table=’gkg’,coverage=True, translation=False) results.to_pickle(“data/%s-%s-%s.pkl”%(cur_date.year, cur_date.month, cur_date.day)) cur_date+=datetime.timedelta(days=1)

所以现在 dir“data”应该包含 60 个 pkl 文件,每个文件都有一天。我们可以通过从每个文件创建一个大的 DF 来加载它们

df = pd.DataFrame()
k = os.listdir(“data”)
for i in k:
  print(i)
  if i.endswith(“.pkl”):
    df = pd.concat([df, pd.read_pickle(“data/”+i)])

现在,万一我们弄坏了东西,我们可以把这个大 df 保存到磁盘上。我认为在这一点上看起来我占用了 6.5gb 左右的内存,保存到 PKL 会崩溃。你也可以保存为 CSV 或任何你喜欢的格式来最小化它所占用的内存,但实际上这一步只是为了加速重置,而不必再次加载所有单独的文件。

df.to_pickle(“first_60_days.pkl”)

好,让我们看看我们有什么。

print(len(df))
>>> 5250547df.head()

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

我们已经得到了日期,即文章的日期,NUMARTS,如果它为同一个实体提取了多个位置(现在不用担心这个),COUNTS(现在不重要),

  • 日期:日期
  • NUMARTS: > 1 如果多篇文章(不用担心)
  • 计数:与数字相关的术语(例如 50 抗议者)
  • 主题:来自 SML 大地中海的一般主题的 NLP 标签
  • 位置:地点
  • 人:人+人喜欢的东西
  • 组织:组织
  • 语气:情绪
  • CAMEOEVENTIDS:用于随时间跟踪事件的一致 ID 值
  • 来源:网站文章来自
  • SOURCEURLS:实际文章的原始 URL

让我们快速地看一下 SOURCEURLS。这实际上是用分号分隔的,但总的来说,我们有 262,171 个不同的来源组合。

df.SOURCES.nunique()
>>>262171

我们可以把它更好的分解成一个字典

df.fillna(“”, inplace=True)from collections import Counter
def join_col(x):
  big_string = “;”.join(x).split(“;”)
  myCount = Counter(big_string)
  return dict(zip(myCount.keys(), myCount.values()))x = join_col(df.SOURCES)
x=pd.DataFrame([x]).T.sort_values(by=0, ascending=False)
x

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

所以我们可以看到一些出版商。如果您希望有一个电子表格版本来标记出版商,而不是使用一个静态数组(就像我马上要使用的一样),您可以很容易地将其导出到 excel 表中:(然后您可以导入带有标记的 excel 表)

x.to_excel(“sources.xlsx”)

无论如何,我们可以选择一些随机的网站,并确保他们得到刮除

mySources = [“nytimes.com”, “washingtonpost.com”, “foxnews.com”, “cnn.com”]for source in mySources:
  print("{} is {}".format(source, "good" if source in x.index else "bad"))

因此,一旦我们知道我们的网站是好的,让我们摆脱这个占据我们所有内存的巨大数据框架的大部分,只看那些我们关心的来源。

df = df[df[“SOURCES”].apply(lambda x: x in mySources)]
len(df)
>>> 44112

一个非常易管理的 44k 文章!

因此,GDELT 数据的一个问题是,有时日期被解释为 int,有时被解释为 string,所以我们将所有内容快速转换为 string,然后将其转换为 datetimes。(很容易忽略这一点,我刚刚花了一个小时试图找出为什么我的数据透视表被搞乱了,这是因为类型)。

df.DATE = df.DATE.apply(lambda x: str(x))
df.DATE = pd.to_datetime(df.DATE)

因此,现在我们可以快速查看每个出版商每天有多少文章。我们可以通过按源分组,然后忘记为什么使用数据透视表来做到这一点。

ax = df.groupby([“SOURCES”, “DATE”])[[“SOURCEURLS”]].count().unstack().T.droplevel(level=0).plot(figsize=(12,8))
ax.legend(loc=2)

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

Coverage over Time

我们可以立即看到出版物有一些季节性,工作日的文章量较高,周末的文章量较低。

df.groupby([“SOURCES”, “DATE”])[[“SOURCEURLS”]].count().unstack().T.droplevel(level=0).plot.box(figsize=(12,8))

我们可以看看箱线图,看看东西是如何分布的。

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

Boxplots

所以让我们看看不同的出版物都写了些什么!因此,如果我们想记住它们是以“;”的形式存储的,我们可以遍历并提取各个位置不连续的

我们可以在 LOCATIONS 中查找特定的国家,方法是尝试查找单个国家,如下所示:

df[df[“LOCATIONS”].apply(lambda x: x.find(“Syria”) > -1)].LOCATIONS.to_list()[0]

但是实际上不需要知道国家代码(不像主题或人物有一些 NLP 规范化);我们可以搜索一下。

所以让我们看看这些组织多久写一次关于不同国家的文章。我们可以对它们进行编码,如果它们包含我们能想到的地方:

df[“dprk”] = df[“LOCATIONS”].apply(lambda x: x.find(“North Korea”) > -1)
df[“ukraine”] = df[“LOCATIONS”].apply(lambda x: x.find(“Ukraine”) > -1)
df[“russia”] = df[“LOCATIONS”].apply(lambda x: x.find(“Russia”) > -1)
df[“iran”] = df[“LOCATIONS”].apply(lambda x: x.find(“Iran”) > -1)
df["china"] = df["LOCATIONS"].apply(lambda x: x.find("China") > -1)loc_df = df.groupby([“SOURCES”, “DATE”])[[“dprk”, “ukraine”, “russia”, “iran”]].sum()

然后我们可以继续绘制它们

fig, ((ax1, ax2, ax5), (ax3, ax4, ax6)) = plt.subplots(nrows=2, ncols=2)
fig.set_size_inches(12,8)
x=0
subplots = [ax1, ax2, ax3, ax4, ax5]
for column in loc_df.columns:
  loc_df[[column]].unstack(level=0).plot(ax=subplots[x])
  x+=1
  plt.tight_layout()

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

正如我们之前看到的,我们可以对这些时间序列运行 VAR,以初步了解这些时间序列之间的相互作用。我们只看天,因为如果我们看周,我们只有 8 个数据点,不会那么好。

因此,让我们看看国家的覆盖范围是如何从一个出版商转移到另一个出版商的!一家出版商是否在某些国家领先于其他出版商?

loc_df = loc_df.unstack(level=0)
countries = ["dprk", "ukraine", "russia", "iran", "china"]for country in countries:
  model = VAR(loc_df[[x for x in loc_df.columns if x.startswith(country)]], freq="d")
  results = model.fit(maxlags=3)
  display(results.summary())

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

Part of results

太酷了,所以我们看到很多出版商倾向于以这种模式效仿华盛顿邮报对朝鲜的报道。同样,他们也关注《纽约时报》关于乌克兰的报道。当然,我们还没有开始评估一个模型是好是坏,但是现在我们开始看到一些模式从数据中显现出来。

现在让我们来看看每份出版物是如何覆盖不同国家的。

for source in mySources: model = VAR(loc_df[[x for x in loc_df.columns if x.endswith(source)]], freq=”d”)
  results = model.fit(maxlags=3)
  display(results.summary())

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

Part of results

所以我们可以看到,这里也有一些相互作用。

这应该足以让人开始摆弄 GDELT 数据集了。你可以利用地点、主题和人物的互动来识别不同种类的文章,看看随着时间的推移会有什么结果。在下一篇文章中,我将看看我是否能涵盖分解,一点关于模型评估,并尝试 SARIMA 和神经网络。

抓取您自己的集:

因此,GDELT 数据很好,但它缺少文章的实际文本。它还缺少一些功能,比如作者姓名和文章在网站上的位置。对于这种事情,你可能想要维护你自己的文章来分析自己。

新闻文章可能有点难得到,但是这样做有不同的困难。守护者是。最简单的方法是使用一个 API,允许你请求每一篇文章。纽约时报也有一个 API,但是它返回所有文章的 URL 和一些标签。但是,您可以根据 URL 回到原始 URL,自己抓取文本。这类似于使用 GDELT SOURCEURLS 字段返回并获取原始文本,您也可以对其他出版物这样做。然而,有了 GDELT SOURCEURLS,出版商可以更改旧文件的 URL,所以不能保证你会得到文章。

抓取文章的一个方法是每天抓取新闻网站主页(这是可行的)。但是如果你想要过去文章的档案,你需要能够找出它们在哪里。你可以创建一个谷歌自定义搜索引擎,在白天搜索出版物中的文章,但这需要一段时间。另一种方法是在新闻网站上使用内部搜索引擎。例如《华盛顿邮报》和《福克斯新闻频道》都有内部搜索引擎,你可以搜索特定日期发表的文章,找到需要搜集的文章。

一些新闻网站就是不允许按日期搜索,在这种情况下,你可能想走自定义搜索引擎的路线。其中包括 Breitbart News、Huffington Post 或 CNN。

如果你认为你可能想要一份好的新闻报道档案,那么至少开始每天抓取主页文章是值得的,这样你就可以很好地了解新闻网站在宣传什么。新闻报道变化很快,并不总是很容易回去,找出什么是过去的报道。希望这足以让你开始!

使文本上升

原文:https://towardsdatascience.com/making-text-ascent-1ee428b7a13d?source=collection_archive---------27-----------------------

我如何构建和部署机器学习 web 应用程序

我经常发现自己在阅读一篇文章,比如说关于数据科学的文章,并且想知道,在哪里可以读到关于这个主题的更简单的文章?当一个朋友在 LinkedIn 上发布类似问题时,我意识到我不是唯一一个。她问如何在最简单和最复杂之间的特定范围内找到文章。我意识到我们没有一个简单的系统来进行这种类型的搜索,除了手动阅读来寻找合适的信息。

商业理解

基于我对网络搜索的兴趣,我创建了 Text Ascent,这是一个网络应用程序,它使用无监督的 ML 来帮助用户基于文本复杂性发现内容。我希望 Text Ascent 可以成为一种工具,用于在我们学习旅程的所有阶段搜索内容。我为 Text Ascent 设定的核心目标是让人们之间更容易接触到感兴趣的小众话题。

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

Photo By Ted Bryan Yu from Unsplash

数据理解

我使用了 Wikipedia-API ,这是一个为 Wikipedia 的 API 设计的 python 包装器,用来收集从艺术到科学等主题的文章标题。然后,我运行了一个数据收集函数(scrape_to_mongodb.py ),该函数将这些标题和 11k+文章的摘要、全文和 URL 收集到一个 mongodb 数据库中。我排除了全文少于 300 个单词的文章,因为维基百科中有像“音乐文件”这样的条目不符合我的模型的目的。
参见数据采集笔记本 & 数据探索笔记本

数据准备

从 Wikipedia-API 包装器返回的内容不需要进一步清理。我确实需要确保当内容显示在 web 应用程序上时,html 被读取为 JSON,以避免向用户显示回车。我使用 textstat 包的 Flesch-Kincaid 等级给每个文档的全文打分。

这些文件保存在 AWS S3 存储桶中,以允许访问 web 应用程序。参见数据准备笔记本

建模

当前模型使用语料库向量和用户输入向量中的前 20 个重要特征之间的余弦距离来将相似内容从库中返回给用户输入。使用 TF-IDF 矢量器创建模型特征。TF-IDF 矢量器拆分语料库文档中的单词,删除停用词,并计算每个文档中每个单词的词频,根据单词在语料库中出现的频率进行调整。换句话说,不常用的词比常用的词更重要。

复制这个模型

  • 获取感兴趣的文档列表,并格式化成类似于clean_df的数据帧。使用 TextStat 获得文本难度分数。我在 AWS S3 上的例子: clean_df
  • 使你的语料库适合你的矢量器(从训练集中学习词汇和 idf),它是你的 df 中的文本系列我在 AWS S3 上的例子: 矢量器
  • 使用矢量器转换功能(将文档转换为文档术语矩阵)来创建您的语料库向量我在 AWS S3 上的示例: 语料库向量
  • 克隆此存储库
  • traverse_flask目录中,创建一个名为data的空子目录。
  • $ export FLASK_APP=app $ flask run 在终端运行traverse_flask中的 flask,实现 flask app。这个瓶子app.py接受functions.py的功能。调整函数以改变后端的数据管道。调整static/templates/index.html中的 brython,改变数据反映给用户的方式。

参见模型功能

估价

如果用户能够发现与他们已经阅读的内容相关的不同阅读难度的内容,那么这个产品就是成功的。用户满意度、重复使用、网络应用流量和应用分享是我用来评估 Text Ascent 成功的指标。在使用部署在 web 应用程序上的模型之前,我评估了 4 个模型:

  • 模型 1:使用 TextStat、Gensim 和 Spacy。
  • 模型 2:使用具有 10 个主题的潜在狄利克雷分配(LDA)主题建模,然后将用户内容分类到一个主题中。
  • 模型 3:使用 2000 维的 TextStat 和 TF-IDF 矢量器。
  • 模型 4:使用具有前 20 个特性的 TextStat 和 TF-IDF 矢量器。

每一次迭代都是为了使结果内容更类似于用户输入的内容。

未来建模

我还想将预训练的神经网络与我当前的 TFIDF 矢量化进行比较,看看返回内容的质量是否有所提高。改进将通过一个简单的手动评分系统添加到网络应用程序的用户反馈来衡量。参见评测笔记本

部署

Text Ascent 已经作为一个支持 flask 的 web 应用【traverse.sherzyang.com 部署在 EC2 实例上(目前没有运行)。该应用程序使用 brython 在 python 函数和 html 之间进行交互。下面是来自网络应用的两张图片。给定任何用户输入文本,该模型将从库中输出相关文章,标题中有链接到完整长度的文章。用户可以从较简单的内容滚动或遍历到较复杂的内容,表格会相应地更新。

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

未来迭代

作为我对搜索和我们的一次性答案新世界——谢谢 Alexa、Siri 和 Google Home——的兴趣的一部分,我计划将文本提升部署为亚马逊 Alexa 的一项技能。这项技能将允许用户“滚动”或“遍历”某个主题从简单到复杂的摘要,就像告诉 Alexa 将歌曲播放得更大声或更小声一样。我相信在内容上创造选择会以积极的方式让我们超越一次性答案的世界。

此外,我渴望扩大语料库,以包括来自古滕贝格项目和其他项目的书籍。如果你想看到一些内容被添加到当前的维基百科文章库中,请在 LinkedIn 上给我发消息。我在亚马逊或 Goodreads 上见过几个给一本书的阅读难度打分的网络扩展( Read Up 就是一个很好的例子)。这些产品激励我为将来的文本提升开发一个无语料库的搜索功能。我认为当 Text Ascent 可以返回 Google 或 Bing web search API 支持的内容时,它会变得更加有用。

信用

使用 OCR 和 Elasticsearch 搜索穆勒报告

原文:https://towardsdatascience.com/making-the-mueller-report-searchable-with-ocr-and-elasticsearch-4e73e55de341?source=collection_archive---------9-----------------------

4 月 18 日标志着穆勒报告的全面发布——这份文件概述了对俄罗斯可能干预 2016 年总统选举的调查。像大多数政府文件一样,这份文件很长(448 页),读起来会非常乏味。

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

Source

更糟糕的是,实际下载的 PDF 基本上只是一张图片。您不能复制/粘贴文本,或者如果您想在文档中搜索更有针对性的信息,可以使用 ctrl+f 查找文本的特定部分。

然而,我们可以很容易地使用两种伟大的技术来搜索这个文档:光学字符识别(OCR)和弹性搜索。

光学字符识别

OCR 允许我们对文本进行拍照、识别,然后将其转换为实际文本——参见维基百科上的这一描述。幸运的是,在当今时代,有许多开源库/产品来完成这项任务。

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

Source

宇宙魔方就是这样一个引擎。它最初开发于 80 年代,自 2006 年以来一直是谷歌的项目,是最受欢迎的 OCR 引擎之一。今天,我们将使用 Python 包装器:pytesserac。我从这篇文章中获得了我最初的 PDF-OCR 灵感——看看吧!

弹性搜索

Elasticsearch 是一个可扩展的搜索平台,它使用类似于 TF-IDF 的算法,TF-IDF 代表词频逆文档频率。

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

Source

本质上,它是一个简单的函数,经常在搜索/相似性空间中使用,根据关键字定位文档。它也不太强调频繁出现的单词。例如,因为单词“the”出现在如此多的文本中,我们不希望它被认为是我们搜索查询的重要部分。TF-IDF 在将您的查询与文档进行比较时会考虑这一点。对于它的基本概述,只需查看维基百科。

装置

你可以从网站或者你的操作系统各自的包管理器下载并安装 elastic。然后你只需要我们将要使用的所有 Python 包。

pip install elasticsearch
pip install pdf2image
pip install pytesseract

OCR 文本提取

首先,将穆勒报告下载到您的主机。然后,我们可以创建一个快速函数,使用 pytesseract 和 pdf2image 库从 PDF 中逐页提取文本。

注意,我设置了默认值num_pages=10。这是因为这份报告真的很长,在你的个人电脑上,从每一页提取文本可能要花很长时间。此外,如果您不打算将本地 Elasticsearch 索引部署到云上,那么它也是大量数据。不过,您可以随意将该参数更改为您选择的任何值。

但是不管怎样,当我们在 PDF 上运行这个函数时,我们现在有了所有 PDF 页面的文本和页码!这是一个字典列表(json ),对于 elastic 来说,这是一个很好的入口,可以让它被搜索到。

弹性研究索引

你需要做的第一件事是确保 elastic 运行在正确的端口上。打开一个终端,启动 elastic(如果在你的$PATH里面,应该就是elasticsearch)。默认情况下,这将在端口 9200 上启动服务。

之后,我们可以很容易地使用 Python 客户机与我们的实例进行交互。如果 elastic 在端口 9200 上运行正常,下面的代码应该创建索引mueller-report,它有两个字段:textpage(它们对应于我们在前面函数中的字典键)。

搜索我们的索引

我不会深入细节,但是 elastic 使用一种叫做 query DSL 的语言来与索引交互。您可以对它做很多事情,但我们在这里要做的只是创建一个将我们的查询矢量化的函数,并将其与我们的索引中的text进行相似性比较。

res将是一个 json,包含我们搜索的一系列信息。实际上,我们只想要相关的结果。所以一旦我们实际调用了这个函数,我们就可以解析 json 来获得最相关的文本和页码。

这样,我们的搜索功能在页面文本中查找“司法部”,并返回结果。上面语句中的[0]只是为了查看第一个最相关的页面文本和编号。但是,您可以定制解析,以便它返回您喜欢的少/多的结果。

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

使用基巴纳前端

实际上,我们可以使用另一个弹性工具来更好地查看我们的结果,而不是查看我的 jupyter 笔记本中记录不佳的 gif。Kibana 是 elastic 的开源前端,非常适合可视化。首先,从这个链接安装 kibana。

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

Source

一旦你安装了 Kibana,在终端中运行kibana启动服务,然后在你最喜欢的浏览器中导航到localhost:5601。这将允许您与应用程序进行交互。

在与索引交互之前,我们唯一要做的事情是创建一个索引模式。转到 Management > Create Index Pattern,然后输入“mueller-report”——ki Bana 应该会让您知道该模式与我们之前在 elastic 中创建的索引相匹配。

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

就是这样!如果你转到左边的 Discover 标签,你可以用一种比我们在 elastic 更容易(也更美观)的方式搜索你的索引。

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

后续步骤

把它放在 AWS 上可能会很酷,这样任何人都可以使用它(有一个更好的前端),但我现在真的不想把我的信用卡绑定到那个实例上。如果其他人想,请自便!我将很快更新 docker 容器和 github 链接。

更新

2019 年 4 月 21 日—Mueller Report 上有很多关于 OCR 和后续 NLP 的帖子/工作。似乎主要关注的是 OCR 文本的实际质量,因为由于格式或一般的不准确性,结果可能是混乱的。虽然可能没有简单的方法来解决这个问题以供未来分析(除了政府发布了一份有用的文件),但我们至少可以通过在我们的搜索功能中添加一个fuzziness参数来弹性补偿我们搜索中的任何拼写错误。

这是一种粗略但通用的方法,可以解释我们可能在 OCR 后的文本中发现的一些错误。

使用机器学习的恶意软件分类

原文:https://towardsdatascience.com/malware-classification-using-machine-learning-7c648fb1da79?source=collection_archive---------14-----------------------

实施微软恶意软件分类挑战(BIG)的收获

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

Image Source : Kaggle

如果你喜欢探索大型和具有挑战性的数据集,那么也许你应该试试微软的恶意软件分类。在深入探讨这个问题之前,让我们先来看看你能从中学到什么:

  1. 如何处理大规模数据? 列车总数据集由 200 GB 数据组成,其中 50 GB 数据为。字节的文件和 150 GB 的数据。asm 文件。
  2. 应该做什么特色工程?如果到目前为止你一直只处理文本和图像数据,这肯定会提高你对特征工程的直觉。
  3. 在没有领域知识的情况下,如何逼近一个机器学习问题? 用本次挑战赛第一名获奖者的话说:“交叉验证比领域知识更值得信任”。

业务问题

在过去几年中,恶意软件行业发展非常迅速,辛迪加在技术上投入大量资金来规避传统保护,迫使反恶意软件团体/社区构建更强大的软件来检测和终止这些攻击。保护计算机系统免受恶意软件攻击的主要部分是识别给定的文件/软件是否是恶意软件。

机器学习问题、KPI 和约束

我们可以将业务问题映射为多类分类问题,其中我们需要预测九个类别( Ramnit、Lollipop、Kelihos_ver3、Vundo、Simda、Tracur、Kelihos_ver1、Obfuscator)中每个给定字节文件的类。ACY,加塔克

KPI:多类日志损失,混淆矩阵

约束:我们需要提供分类概率,错误分类的分类标签应该受到惩罚(这就是为什么 log loss 被选为 KPI)并且应该有一些延迟限制。

处理大尺寸

考虑到数据的规模,建议使用云平台,如 GCP、AWS 或 IBM Cloud。我们在 GCP 完成了这个案例研究,使用基于 Linux 的 1vCPU 机箱,配备 30 GB RAM 和 500 GB HDD。点击此链接了解如何借助 CurlWidget 在 GCP 直接从 jupyter 笔记本上下载数据。下载数据后,下一个挑战将是使用 python 提取这些文件,因为 python 对 7z 文件的支持是有限的。使用名为“p7zip”的软件包,它提供了一个 Linux 命令行工具来提取 7z 文件。

# command to install the package in Linux
sudo apt-get install p7zip-full
# Sample Command to extract the data from terminal
7za x yourfile.tar.7z

数据的关键点

  1. 总数据集由 10,868 个组成。字节文件和 10,868 个 asm 文件总共有 21,736 个文件。字节文件由 256 个十六进制数字(十进制值范围为 0 到 255)和一个特殊字符(??).Asm 文件是使用智能编译器获得的汇编文件。
  2. 数据集不平衡。

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

Distribution of malware classes

关键特性

这个案例研究的好处是,它需要大量的耐心和实验来获得有用的特性。基于我们的直觉和之前在这个领域的工作,我们尝试了以下特性

  1. **字节文件的 n-gram 特性:**我们尝试了单字、双字和三字特性。虽然这些特性的性能很好,但是主要的挑战在于处理它们的大维数。一元语法的特征数是 256,二元语法的特征数是 65531,三元语法的特征数留给你的练习。即使有 30 GB 的 RAM,也不可能加载 65531 个特性的全部数据,所以我们选择了块中的 SVD。首先,我们使用随机样本和 3000 个特征尝试了 elbow 方法,以检查保持方差所需的组件数量,我们发现 1000 是一个好数字。

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

Elbow method to choose number of components

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

Code to extract bi-gram features using SVD in chunk

2.**字节和 asm 文件的大小:**字节和 asm 文件的大小被证明是很好的特性。让我们来看看文件大小的箱线图

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

3.**字节数组的大小:**正如我们前面提到的,字节文件由十六进制数字组成。对于每个文件,我们都有一个数组,并将每个元素添加到数组中,并使用这些数组的长度作为一个特征。

4.**ASM 文件的段计数和 n-grams:**ASM 文件由不同的段组成,如前缀(例如。标题、文本)、操作码(例如 jmp,hlt),关键词(例如。。dll,std:😃,寄存器(例如。edx、epi)等。我们将片段的计数作为一个特征。我们还考虑了 asm 文件的一元、二元和三元模型作为特征。

5.**像素强度的字节和 asm 特征:**这可能是本案例研究中最具创新性的特征。我们借用了第一名获胜者解决方案的概念。正如我们前面提到的,字节文件中每个元素的值在 0 到 255 之间。我们可以很容易地将这些字节文件和 asm 文件一起转换成灰度图像。据观察,asm 文件的前 800 个像素密度对最终结果有显著影响。

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

Code to convert asm files to image files

让我们看一下随机 asm 文件在转换后的样子

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

Random image from converted asm files

降维和特征选择

到目前为止,您一定已经观察到了特征的维度,并对用于训练的最终特征的维度有所了解。为了解决这个问题,我们使用随机森林来选择重要的特征。重要特性的数量是一个超参数。根据我们的经验,我们尝试了各种数字,显然还有改进的余地。让我们看一个样例代码,看看我们是如何选择最好的三元语法 asm 特性的。我们还尝试了 t-SNE 多变量分析。

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

系统模型化

我们已经尝试了各种线性机器学习模型,如 KNN、多类逻辑回归和具有各种功能组合的集成,如随机森林、XGBoost 和 LightGBM。我们用单一特征以及字节特征和 asm 特征的组合来训练模型。我们还在从 byte 和 asm 文件获得的图像上尝试了各种 CNN 架构,但与微调的机器学习模型相比,获得的结果较差。由于我们没有恶意软件行业的任何领域知识,我们完全依赖交叉验证。由于特性和文件的数量很大,我们选择了 RandomizedCV 进行交叉验证,并且还有改进的余地。你可能会想到另一个问题,为什么我们同时使用 XGBoost 和 LightGBM?实际上,我们已经从 XGBoost 开始,但是发现 LightGBM 的训练延迟比 XGBoost 低得多,并且性能相似或更好。我们从一个随机模型开始,然后在关注性能后逐渐增加模型的复杂性。

结果

最后,如果一个用例不能提供令人满意的结果,它就没有任何价值。在这里,我们只列出校准最终 LightGBM 模型后得到的结果。

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

Confusion Matrix

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

Precision Matrix

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

Recall Matrix

引文

  1. http://arxiv.org/abs/1802.10135
  2. https://www.kaggle.com/c/malware-classification/overview
  3. https://www . Kaspersky . co . in/resource-center/threats/malware-classification
  4. https://ieeexplore.ieee.org/document/8553780

使用深度学习的恶意软件检测

原文:https://towardsdatascience.com/malware-detection-using-deep-learning-6c95dd235432?source=collection_archive---------13-----------------------

fast.ai 中使用卷积神经网络的恶意软件检测

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

Photo by Markus Spiske on Unsplash

什么是恶意软件?

恶意软件是指恶意软件犯罪者派遣感染个人计算机或整个组织的网络。它利用目标系统的漏洞,如合法软件(如浏览器或 web 应用程序插件)中可能被劫持的漏洞。

恶意软件的渗透可能是灾难性的——后果包括数据盗窃、勒索或网络系统瘫痪。

为什么检测恶意软件很重要?

恶意软件是当今互联网上最严重的安全威胁之一。事实上,大多数互联网问题,如垃圾邮件和拒绝服务攻击,都有恶意软件作为其根本原因。也就是说,受到恶意软件危害的计算机通常联网在一起形成僵尸网络,许多攻击都是利用这些恶意的、攻击者控制的网络发起的。

为了应对新产生的恶意软件,需要新的技术来检测它们并防止它们造成的任何损害。

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

为什么要深度学习?

如今,深度学习已经主导了各种计算机视觉任务。这些深度学习技术不仅使这场比赛取得了快速进展,甚至在许多比赛中超过了人类的表现。这些任务之一是图像分类。

与更传统的机器学习技术方法不同,深度学习分类器是通过特征学习而不是特定于任务的算法来训练的。这意味着机器将学习呈现给它的图像中的模式,而不是要求人类操作员定义机器应该在图像中寻找的模式。简而言之,它可以自动提取特征,并将数据分类到各种类别中。

早期层学习如何检测边缘等低级特征,后续层将早期层的特征组合成更全面和完整的表示。

我们可以使用后面描述的方法将恶意/良性文件转换成灰度图像。然后我们可以对生成的图像应用这些深度学习技术,将它们分类为恶意软件或良性软件。

如何创建恶意软件映像?

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

为了使用深度学习模型对图像进行分类,我们需要来自良性和恶意文件的图像。我们只做二元分类(恶意类和良性类)。多类分类也可以使用这种技术来完成,其思想是恶意软件文件的变体将具有不同于其他的图像。

准备好数据集后,我们将通过对每个图像执行以下步骤,将每个文件转换为 256x256 灰度图像(每个像素的值在 0 到 255 之间):

**Step 1:** Read 8 bits at a time from the file.
**Step 2:** Treat the 8 bits as a binary number and convert it to its    corresponding integer.
**Step 3:** Enter the number as the pixel value.

最大 64 KB 的文件可以容纳 256 x 256 的图像。任何大于 64 KB 的文件,其剩余内容都将被删除。
另一方面,如果文件的大小小于 64 KB,剩余的图像将用 0 填充。

由于恶意软件检测是实时进行的,我们需要在几秒钟内将图像分类为良性或恶意软件。因此,保持图像生成过程简单而简短将有助于我们节省宝贵的时间。

数据集的准备

这一步极其简单。所有图像生成后,将它们分成两个文件夹——训练和验证。这些文件夹中的每一个都包含两个文件夹,即恶意软件文件夹和良性文件夹。
将这两个文件夹存储在另一个名为“dataset.tar”的文件夹中,压缩生成一个. tar 文件。

所以最终的目录结构将是→
dataset.tar 包含验证和训练。验证将有恶意文件夹和良性文件夹。火车将有恶意和良性的文件夹。

将压缩文件夹移动到包含代码的 Jupyter 笔记本所在的目录中。

实施模型

** 这个问题使用的模型是按照 fast.ai 课程的第 1 课(宠物分类)创建的。 **

要从 Google Drive 中读取数据集,请添加以下代码行

!pip install PyDrive #import os
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentialsauth.authenticate_user()
gauth=GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)

一旦你运行了上述代码的最后 4 行,Google SDK 会要求你输入一个验证码。它会提到一个链接,一旦你点击它,你会得到你的安全代码。

link = '1sL4I4xNh657AhrIOOwbr6TX58ahyC'(add the link here )

创建一个变量,该变量包含到。tar 文件包含的数据存储在您的谷歌驱动器。要获取网址,请打开。tar 文件并获取该文件的可共享链接。你不需要整个 URL,只需要它的一部分。所以比如你的可分享链接是“https://drive . Google . com/File/d/1 sl 4 i4 xnh 657 ahrioowbr 6 tx 58 ahyc/view?你只需要粗体部分。

获取数据路径

downloaded = drive.CreateFile({'id':link}) 
downloaded.GetContentFile('dataset.tar')
import tarfile
tar = tarfile.open("dataset.tar")
path = tar.extractall('DS/')
tar.close()
path = Path.cwd().joinpath("DS/dataset/")
path.ls()data = ImageDataBunch.from_folder(path, ds_tfms=get_transforms(), size=224)## To view data in a batch
data.show_batch(rows=3, figsize=(7,6))
## To know the number of classes in a dataset
print(data.c)
## To know the names of the classes in a dataset
print( data.classes)

创建模型

learn = create_cnn(data, model.resnet34, metrics = error_rate)## To know the model architecture
learn.model## Training the model
learn.fit_one_cycle(4)
learn.fit_one_cycle(10)

下面是我运行上述代码后得到的输出截图:

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

Output for 4 and 10 epochs.

interp = ClassificationInterpretation.from_learner(learn)
losses,idxs =  interp.top_losses()
interp.plot_top_losses(9,figsize=(9,6))

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

The images with maximum losses.

如何找到并设定一个好的学习率?

到目前为止,我们还没有告诉我们的模型在训练模型时使用什么学习率,我们都知道这是训练时最重要的超参数之一。
为了找到一个好的学习率,请执行以下操作:

learn.lr_find()
learn.recorder.plot()

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

Finding an optimal learning rate.

learn.fit_one_cycle(5, max_lr=slice(1e-6,1e-4))## Saving the weights of the model
learn.save('stage-1-malware-detection')

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

Losses are much less compared to before.

注意:每次调用 fit_one_cycle()函数时,权重都不会重新初始化。因此,如果您一个接一个地调用该函数,则历元会累加,这意味着如果您调用 fit_one_cycle(5)然后调用 fit_one_cycle(10 ),则该模型已经被训练了大约 15 个历元。

完整的代码可以在我的 GitHub 账户上找到,链接这里。这些只是代码的一小部分,仅仅遵循它们不会给出可行的代码。

如有任何建议/改进/讨论,请随时联系我们。😄

未来的工作

  • 我们可以尝试将数据分为不同类型的恶意软件或良性类别,而不是执行二元分类。
  • 我们可以尝试不同的技术来创建一个验证集。在这个阶段,不同类别中的图像以及验证集和训练集中的图像数量是随机选择的。
  • 在我们的训练数据集中,尝试恶意软件文件数量与良性文件数量的不同比率。(几乎 1:1 使用)
  • 尝试不同的维度来生成恶意软件图像。(使用 256x256)

我认为你会喜欢:D 的其他文章

我很高兴你坚持到了这篇文章的结尾。🎉我希望你的阅读体验和我写这篇文章时一样丰富。💖

请在这里查看我的其他文章。

如果你想联系我,我会选择推特。

管理地理数据:ISO3166、联合国/地方编码和地名

原文:https://towardsdatascience.com/managing-geographical-data-iso3166-un-locode-and-geonames-8306ce4aa474?source=collection_archive---------16-----------------------

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

最近,我需要定义一个数据模型来处理国际级别的地理数据,即,当您的潜在地址在全球任何一个地方时,如何正确管理有关邮政地址的数据。下面是我在处理将地理数据整合到应用程序和数据库时发现的挑战和备选方案的结果。

地区混乱的挑战

当你研究国家是如何组织起来的,你会发现不同的标准,有时地区是相当无形的,很难证明,尤其是在欧洲国家。

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

仅举一个例子来说明两个国家之间的方法有多么不同:

让我们先来关注一下美利坚合众国,人口 3.25 亿,面积 9525067 平方公里,GDP 20.513 万亿美元。用户使用简单有效模式:

一个国家,27 个州。

第一个和第二个行政命令之间有明确的划分。

现在我们来看看欧元区第四大经济体西班牙,既不是主要国家之一,也不是小国家。人口 4600 万,面积 505990 平方公里,GDP 1.864 万亿美元。这是一个过度复杂的组织的例子:

一个国家,17 个自治区,2 个自治市,50 个省,8124 个直辖市。

由于一些人可能会立即指出,这两个国家决不是可比的(尽管它们是国家,所以它们应该是可比的),我们将只分析美国的一个州。

我们会选择德克萨斯州:它在外延上略大于西班牙,拥有 2600 万人口,GDP 与西班牙相似(1.639 万亿美元)。

得克萨斯州在行政上划分为 254 个县。

同样,这并不复杂,这是一个基本而简单的管理。

美国的邮政地址不需要二级行政级别。他们只是使用国家,因为国家被认为是基本的主要行政单位,这就相当于在西班牙不使用自治区(更不用说省了)。

在某些欧洲国家,这种过于复杂且昂贵的地区行政管理模式很常见。分析的例子并不是唯一的,你可以找到其他国家,如法国有类似的情况。

协调邮政数据

如果您需要处理国际数据,了解一些有用的国际标准可能会有所帮助。

一般来说,每当你必须处理大量参考数据时,最好先检查是否有国家或国际标准。您不仅会找到协调数据的最佳方式(我说的是最佳,而不是完美),而且还会更容易找到主数据来填充和更新信息。

如果有人抱怨数据,你还可以争辩说使用了国际标准。通过这种方式,你只需要为用户提供一种方法,让他们可以将自定义数据与自己的想法混淆起来,即如何在地图上放置或命名重要的本地区域。

这里的要点是,处理邮政数据是一个永远不会让所有人都满意的场景。考虑到这一点,遵循国际公认的标准并实现一个允许用户进行更改的接口,就大功告成了。用户现在是数据的所有者(理应如此)。

在这个前提下,我们将研究您可以使用的标准,并回顾每种标准的优缺点。

ISO 3166–1 国家

如果你需要一个编码系统和一个国家列表,不用再找了:ISO 3166–1是你的朋友。

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

Alpha-2 Codes ISO3166–1

由于世界上没有那么多国家,除了少数有争议的名字,这是一个独特的、确定的名单。

我喜欢使用 Alpha-2 代码来查找和填充列表。请记住,一旦您在合并记录中使用国家(如已开具的发票),您应包括代码和名称,因为将来可能会有变化。

提示:在用户界面中总是使用表格查找的代码,而不是存储代码本身。在最终文档中存储永久值将反映文档或注册发布时的当前名称;这将使您的数据库对未来的变化具有鲁棒性,并将您从处理历史数据中解放出来。

另一种选择是为条目使用 GUIDs/uuid/IDs,并让一个活动的列反映该特定记录是否停止。在这个列表上维护潜在的更新和保持对过去变化的准确跟踪是相对容易的。但是,我不喜欢这种方法,因为最终您会保留旧信息,并使主数据维护和迁移变得更加困难。

对于信息本身,实际的标准可以在这里买到,虽然信息可以从不同的来源免费获得,比如维基百科

提示:如果您正在处理一个涉及历史数据集(如宏观经济学)的数据分析项目,并且由于某种原因,您必须包括关于已灭绝国家的信息,请记住,ISO3166–3 为您提供了一个现已灭绝国家的列表,如苏联或南斯拉夫。

ISO 3166–2 个州/省

如导言中所述,对于第二级行政机构来说,情况并不那么容易(有些国家确实有第三级行政机构,即使没有实体或扩展机构要求这样做)。

这里的最佳选择还是 ISO3166-2。您将在这里找到第二和第三个管理级别。

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

ISO3166–2:FR

同样,你可以购买官方标准,也可以免费使用维基百科中的信息。

为了正确地处理信息,您可以使用这个 PHP 解析器轻松地删除信息。

Python 和 Java 对 ISO-3166 的支持

如果你使用 Python,有一个名为 PyCountry 的非常好的包,它已经包含了为你解析的信息。

在 Java 中,我没有发现任何类似的东西,尽管我个人认为这种信息应该在数据库级别进行管理,所以您可以使用上面的 Python 包创建相关的 CSV,并将它们导入到您的 Java 应用程序中。

UN/LOCODE

一种替代方法是处理来自欧洲经委会的信息。这不仅包括 ISO3166 的分支机构和国家,还包括世界上许多城市的地理位置(包括坐标)。虽然它并不完整(你不会发现每个城市都有一对一的任务),但它提供了额外的信息。它侧重于运输,因为它包括码头、火车站和国际航空运输协会代码等运输设施的可用性信息。

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

UN/LOCODE Provides information about trading/transportation locations

[## ISO 3166-2 -贸易-欧洲经委会

该表按字母顺序列出了…的国家名称(英语中的官方简称,如 ISO 3166)

www.unece.org](http://www.unece.org/cefact/locode/subdivisions.html)

城市和邮政编码

州和省有点困难(试着弄清楚在法国用什么),所以屏住呼吸,现在考虑如何处理城市和邮政编码。可用城市的数量激增,但在您开始恐慌或考虑使用城市和邮政编码的空文本字段之前,请注意有一个非常体面和简单的解决方案:GeoNames 项目。

[## 地名

GeoNames 地理数据库涵盖所有国家,包含超过 1100 万个可用的地名…

www.geonames.org](https://www.geonames.org/)

GeoNames 是一个广泛使用的、完全免费的全球位置数据库,包括它们与 ISO3166-2 的第二/第三行政级别和邮政编码的关系。

在不集成其他外部服务的情况下,这是您所能做到的最大限度。

要探索的其他选项

经过我的研究,我想知道谷歌地图 API 是否可以成为集成地址搜索功能的一个选项。如果你不得不在街上交易,这可能是一个好的选择。在我的特定场景中,这不是一个需求,所以我决定继续使用 GeoNames(它可以提供不需要与外部系统在线集成的功能)。

在这种情况下,一个好的选择可能是查询国家数据库。大多数发达国家和半发达国家将依靠免费信息,无论是在线服务还是可下载的数据库。

使用 pyenv 管理虚拟环境

原文:https://towardsdatascience.com/managing-virtual-environment-with-pyenv-ae6f3fb835f8?source=collection_archive---------0-----------------------

大多数 Python 开发人员和数据科学家都已经听说过虚拟环境。然而,管理为不同项目创建的数十个环境可能会令人望而生畏。pyenv 将帮助您简化虚拟环境的创建、管理和激活。

过去,在 virtualenv 流行之前,我会为所有 Python 项目保留一个全局工作空间。每当我安装或升级其中一个库时,它就可以立即用于所有的项目。通常情况下,它会破坏其中的一些项目…

虚拟环境的主要优点是它们为您的每个项目构成了一个单独的工作空间(virtualenv)。安装在这些工作区中的包不会互相干扰,因此您可以安全地安装、升级或删除库,而不会影响其他项目。

pyenv 是 virtualenv 的扩展,增加了一些好处:

  • 有可能相邻安装几个 Python 解释器版本(例如 2.7 和 3.8 甚至 PyPy),
  • 用户安装的解释器和系统 Python 的和平共存,
  • 用于管理虚拟环境的集中式系统,
  • 切换到项目文件夹时自动激活虚拟环境。

安装 Python 解释器📜

让我们先来看看主要特性。如果你想亲自尝试一下,请阅读博文末尾的安装指南。

要创建一个虚拟环境,首先需要确保安装了合适的解释器。您可以从列出的可用解释器中进行选择:

pyenv install --list

(你可以用cd $(pyenv root) && git pull更新这个列表)然后安装其中一个:

pyenv install 3.8.0

要激活新环境并开始使用 Python 3.8.0:

pyenv shell 3.8.0
python

这将打开 Python 提示符,并显示熟悉的欢迎屏幕:

Python 3.8.0 (default, Oct 20 2019, 18:15:07) 
[GCC 9.1.0] on linux
Type “help”, “copyright”, “credits” or “license” for more information.
>>>

这些都很好,但是除非你还停留在 90 年代,否则你会更喜欢像 notebook 或 IPython 这样的现代 Python 接口。如果有,请继续读下去!

创建虚拟环境💻

到目前为止,我们已经安装了基本的 Python 解释器和标准库。然而,为了让我们的数据科学环境完全发挥作用,我们需要安装数据科学堆栈中的基本包,如 Jupyter、matplotlib 或 pandas。

通常情况下,您的项目将依赖于特定版本的包(这不是最佳实践,但是一些 Python 库比我们的项目运行得更快)。为了隔离一个项目所使用的包,我们可以使用虚拟环境。您可以使用pyenv-virtualenv扩展创建一个(参见下面的安装说明):

pyenv virtualenv 3.8.0 my-data-project

你可以给环境命名(这里,my-data-project),因为它适合你。要激活环境类型:

pyenv shell my-data-project

现在您已经准备好安装您想要使用的库了。您可以从标准 Python 包存储库(PyPi 也称为 cheese shop)中提取它们,并使用pip命令安装在当前环境中:

pip install jupyter notebook matplotlib pandas

最好只安装您将在项目中使用的库。如果以后你意识到少了什么,你仍然可以用pip install添加包。现在,让我们启动笔记本服务器:

jupyter notebook

这应该会在浏览器中打开 Jupyter 笔记本界面。干得好!您刚刚安装了运行在最新最棒的 Python 版本中的 Jupyter🎉!一定要尝试它的一些新特性,比如 Walrus 运算符f 字符串表达式

您还可以使用pyenv versions列出您的系统上安装的所有 Python 版本和环境,它应该会打印出如下列表:

system
3.8.0
3.8.0/envs/my-data-project

system环境是您的默认系统 Python(随您的操作系统一起安装)。另外两个是用 pyenv 创建的。

自动激活环境🚀

没有什么比在安装了额外的库之后才意识到没有激活正确的虚拟环境更令人沮丧的了。这肯定会覆盖当前激活的环境中安装的旧版本的包,并可能破坏您的项目代码。pyenv 的独特优势在于它可以为每个项目自动激活正确的环境。假设您的主目录中有一个名为predict-prices的项目目录。要为项目类型选择虚拟环境:

cd ~/predict-prices pyenv local my-data-project

(以项目命名环境是很常见的,为了避免混淆,我在这里对项目目录和环境使用了两个不同的名称)。

下一次,当您在 shell 中切换到包含项目文件的目录(或其中一个子目录)时,pyenv 将为您激活正确的环境!

请注意,如果您之前使用pyenv shell.激活了环境,自动激活将不起作用

在 IDEs 中使用您的环境

如果你不喜欢,你也可以在你喜欢的 IDE 中使用 pyenv。许多编辑器和 ide 都知道 pyenv 环境,并将为您检测它们。然后,您将能够从下拉菜单中选择当前工作区的环境。

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

Selecting virtual environment in VS code

但是 pip 只针对 Python 包…

虽然pip主要针对安装 Python 包,但也可以安装其他语言的软件。许多 Python 库包含一些用 C 或类似语言编写的代码。例如,numpy 中的数组在 c 中实现了性能关键的操作。在你的机器上安装这些包时,pip可以编译这样的扩展,但是它需要开发者工具(编译器、连接器、构建工具、头文件)的可用性。然而,现在大多数库也为您的平台(Linux、OSX、Windows)提供二进制文件(编译的代码),打包成一种叫做wheel的格式,可以直接从包库中取出,不需要任何编译。

为什么不是康达?🐍

conda 是数据科学家喜欢的另一个伟大的 Python 包管理器。在很多方面类似于 pyenv + virtualenv + pip combo。它提供了一个丰富的官方软件包库和一个名为conda-forge的用户贡献软件包库。如果这些存储库中没有某些包,您仍然可以使用pip来安装它们。conda 的优势在于它是多平台、语言无关的,并且提供所有必要的构建工具和共享库。缺点是它需要安装一个名为miniconda的独立库。好消息是,在 pyenv 中安装 miniconda 就像在基于 pip 的环境中一样容易:

pyenv install miniconda3-latest

装置

要安装 pyenv,只需遵循几个简单的步骤。首先,将 pyenv git 存储库克隆到您的主目录(pyenv 仅支持 OSX 和 Linux,在 Windows 上您需要使用 Windows 子系统 for Linux ):

git clone https://github.com/pyenv/pyenv.git ~/.pyenv

然后将 pyenv 添加到您的系统路径中:

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile

复制粘贴以上几行应该就可以了,但是如果你需要更详细的解释,请查阅官方指南。

我还使用 pyenv 的扩展来管理虚拟环境,称为 pyenv-virtualenv。要安装它,只需克隆 git 存储库:

git clone [https://github.com/pyenv/pyenv-virtualenv.git](https://github.com/pyenv/pyenv-virtualenv.git) $(pyenv root)/plugins/pyenv-virtualenv

要启用自动激活,请将此命令复制到您的终端:

echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bash_profile

现在,您可以从您的会话中注销,然后再次登录,以便将所有内容设置到位。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值