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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

撰写备兑看涨期权以保护你的股票投资组合

原文:https://towardsdatascience.com/writing-covered-calls-to-protect-your-stock-portfolio-76f37b1c9da1?source=collection_archive---------7-----------------------

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

Photo by Adrianna Calvo from Pexels

通过出售看涨期权来降低投资组合的风险,保护自己免受不测

尽管欧洲经济摇摇欲坠,与中国的贸易战时断时续,但他的牛市仍在继续。没有人知道接下来会发生什么,也不知道市场最终是否会在某个时候经历一场长期低迷。

但当股价仍接近历史高点时,从桌上拿走一些钱不会有什么坏处。这里有一个相当安全的方法,可以获取一些利润,降低风险,同时还能保留一些上行风险。

对你的股票做看涨期权

比方说,我们投资苹果公司已经有一段时间了,并获得了可观的收益。我们相信该公司,认为与其他大型科技股相比,目前的估值有些偏高,但还是合理的。

我们可以通过卖出(金融人士称卖出期权的行为为“卖出”)看涨期权来保护自己,对冲我们的苹果股票头寸。当我们这样做时,**我们是在用上涨来换取保护——我们因为卖出看涨期权而获得了一些钱,但作为回报,如果苹果公司的股价超过了我们期权的执行价,我们就会失去所有本可以赚到的钱。**我们来看一个例子:

  • 撰写本文时,苹果的当前价格为 208.74 美元。假设我们拥有 100 股股票,这意味着我们在苹果股票上投资了 20,874 美元,这是一笔相当大的数目。
  • 三年前,价格是 107 美元。三年后的回报率是 95%,不包括股息。所以假设我们已经拥有它一段时间了,那么我们应该坐拥可观的利润。
  • 2019 年 11 月 15 日到期的苹果看涨期权的最后报价为 630 美元,行权价为 220 美元。这是溢价,或者说,如果我们卖出这个看涨期权,我们会得到的金额。

这是一大堆金融术语,尤其是最后一点。让我们看一下这一切意味着什么。当我们持有股票时,比如 100 股苹果股票,我们的收益图如下图所示。

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

Payoff diagram for being long (owning) Apple stock (Y axis is profit or loss)

Y 轴是我们投资的利润或损失,X 轴是股票的当前价格。蓝线显示我们的利润或损失是股票价格的函数(在我们的例子中,是苹果)。

由于我们拥有 100 股苹果股票,当股价上涨时(在 X 轴上向右移动),我们的利润也增加了(在 Y 轴上向上移动),因此蓝线向右上方的方向是有意义的。从数学上来说,我们的苹果股票价格每上涨 1 美元,我们的头寸利润就会增加 100 美元(因为我们拥有 100 股股票)。

垂直的灰色虚线表示我们购买苹果股票的价格。如果当前股价高于我们的买入价,那么蓝线的 Y 轴值在蓝色“0”上方,表示盈利。如果不是,那么我们就有损失了。

看涨期权快速介绍

现在让我们来看看当我们在组合中加入看涨期权时会发生什么。首先,让我快速介绍一下期权如何运作的本质:

  • 期权是一种金融工具,它授予你以预定的执行价格购买或出售 100 股金融资产(如苹果股票)的权利,而不是义务。
  • **期权有到期日。**这意味着在到期日之后,它们将不复存在,噗(例如,我们的苹果期权将在大约 2 个半月后于 2019 年 11 月 15 日到期)。
  • 但在到期前的任何时候,如果你拥有看涨期权,你可以选择支付执行价购买相关股票的股份。一般来说,只有当股价高于执行价时,你才希望这样做(如果是,你实际上是在以折扣价买入股票)。
  • 如果你在科技行业工作,你可能已经拥有了一些雇主股权的长期期权。你真幸运!

让我们看看买入并持有看涨期权在我们的收益图上是什么样子的(如下)。请注意,现在我们的蓝色收益线有一个扭结。当我们在图上向左移动时,线在执行价格处变平,这意味着我们的损失在溢价(我们为看涨期权支付的价格)处封顶。这是投资期权的一个吸引人的方面——不管发生什么,我们的损失都在溢价范围内。投资者喜欢的看涨期权的另一个方面是无限的上涨空间。请注意,当我们在图上向右移动时,我们的蓝色收益线以同样的方式上升,就像我们拥有标的股票一样。这意味着,通过支付溢价,我们最终获得的经济风险敞口与我们直接购买标的股票的风险敞口相同(当股价高于执行价时)。

另一方面,拥有看涨期权的一个缺点是,与购买股票不同,如果基础股票价格根本不动,你仍然会亏损,因为你已经超出了溢价(另外,即使基础股票支付股息,看涨期权也不支付股息)。

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

Payoff diagram for buying and holding a call option (Y axis is profit or loss)

此外,还增加了到期时间的因素,即你的期权价格变化的速率本身并不是常数,而是许多因素的函数(例如,如果我们的履约价格远高于当前市场价格,期权即将到期,那么即使标的股票价格大幅上涨,也不会对我们期权的价值产生太大影响)——这些因素使得期权投资比乍看起来要复杂得多。如果你打算全力投入期权投资,你必须在这么做之前了解所有这些额外的因素是如何起作用的。

如果你卖了一个看涨期权,这就是我们在例子中想要做的,一切都是相反的。在这种情况下,我们向某人(有偿)出售了让我们以执行价格购买 100 股标的股票的权利。由于一切都在逆转,如果股票价格超过我们出售的看涨期权的执行价格,我们现在被迫承受损失 —在这种情况下,从我们这里购买期权的人将迫使我们以低于股票市价的价格向他或她出售 100 股相关股票(因此我们被迫折价出售)。

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

Payoff diagram for selling a call option (Y axis is profit or loss)

左边的图表显示了卖出看涨期权的收益图。这和上一个几乎完全相反。请注意,蓝色的收益线现在从 0 美元以上开始,代表低股价一直到我们的执行价。这意味着,只要当期权到期时,标的股票的市场价格低于我们期权的执行价格,我们就可以保留所有的期权溢价(我们出售期权得到的钱)。还要注意的是,溢价是我们可以从卖出看涨期权中获得的最大金额。

现在,如果股票价格在到期时上涨到高于我们的执行价,我们就会亏损,因为我们被迫以折扣价将股票卖给我们期权的买方——这就是为什么蓝色收益线在扭结后向下倾斜。请注意,潜在损失是无上限的——如果股票价格持续上涨,那么我们的损失也会随之上涨。因此,卖出看涨期权提供了有限的上涨空间,同时让我们面临无限的下跌空间(可怕!).

是的,这很可怕,但我绝对不建议你写裸看涨期权(在没有首先拥有标的股票的情况下卖出看涨期权,以及 是的,它确实被称为 **)因为在错误的股票上这样做可能是毁灭性的。**例如,想象一下,如果你以 1940 美元的执行价格出售一份 2019 年 11 月 15 日(到期日)的亚马逊看涨期权。这比目前的市场价格高出 10%左右。卖出看涨期权,你会得到整整 3300 美元。很不错吧?但如果亚马逊股价回到 2050 美元的 52 周高点,你将被迫以 1940 美元的价格卖出 100 股亚马逊股票。因为你卖出了一个无担保看涨期权,你需要以 2050 美元买入 100 股,然后立即以 1940 美元卖出——亏损 11000 美元。所以你的总 P & L(损益)是:

  • 因卖出期权而获得 3300 美元的溢价。
  • 损失了 11000 美元。
  • 净亏损 7700 美元……哎哟!

我们不想冒这种风险,所以写裸辞是不可能的。**但是,在高估值的股票市场中,卖出备兑买入期权(当你已经拥有股票时卖出买入期权)可以降低风险,对于风险厌恶型投资者来说,这是一项具有潜在吸引力的交易。**让我们在下一节看看如何。

对我们的苹果股票写看涨期权

由于我们不想裸卖看涨期权,我们想做的是只卖出(记住,卖出意味着在金融市场上卖出)我们已经持有至少 100 股的股票的看涨期权。我个人认为撰写备兑买入期权的方式是这样的:

承诺如果你的股票达到一定的价格(或上涨一定的数量)就卖出,并因做出这一承诺而获得报酬。

在进行任何交易之前,我们需要确定以下事项:

  • **我们可以接受(由我们期权的买方)以什么价格赎回股票——这决定了我们选择什么样的执行价格。**执行价越高,我们卖出期权的收入就越少。这类似于决定“如果股票从当前价格上涨 10%,我将卖出它”以及赚取期权溢价(卖出看涨期权的钱)的额外甜头。
  • 在多长时间内我们可以放心承担这一风险。我们的期权到期日越远,我们承担的风险就越大,我们卖出期权得到的钱也就越多。我们的风险更高,因为对苹果来说,一年内上涨 10%比一个月内上涨 10%更容易。从几天后到期的期权到两年后到期的期权,有很多选择。

认识到这两个决定是相关联的,这一点很重要。如果你卖出一个 2 年后到期的看涨期权,那么你会希望将你的执行价格设定在当前市场价格以上至少 20%,否则你的股票将被赎回。另一方面,如果你写了一个一周内到期的看涨期权,你不希望将执行价格定得比当前市场价格高太多,因为那样你几乎不会因为你的麻烦得到任何溢价。

你卖出看涨期权得到的溢价是一个函数,它取决于在到期时,股票的市场价格高于你的期权的执行价格的可能性。

不太可能赚钱的看涨期权(当基础股票的市场价格高于执行价格时,看涨期权就赚钱了)价值很低,而很可能赚钱的看涨期权价值很高。下面是总结这一点的 2×2 矩阵。不幸的是,没有一个神奇的公式来决定在哪里设置你的罢工,以及在多长时间内写下期权。相反,你需要自己决定如何在你获得的溢价和你的股票被赎回的可能性之间找到平衡点。还要记住(稍后将详细介绍)你获得的溢价越多,你的投资组合在市场低迷时受到的保护就越多——如果市场崩盘,那么你卖出的期权就会贬值(这对你有利,因为你做空它),你可以等待它变得一文不值,或者以低价回购(回购可以平仓)。所以在这种情况下,因为你相信看涨期权的价格在未来会下跌,你会想卖出一个更有价值的期权,从而获得更多的溢价。

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

哇,当我开始写这篇文章的时候,我并没有想到要深入到写看涨期权的机制和复杂性中去。但在做之前,理解我们在做什么,尤其是风险,是至关重要的。

最后让我们回到苹果的例子。回想一下,我们持有 100 股苹果股票,我们决定在 2019 年 11 月 15 日(离到期还有 2 个半月)买入 220 美元的股票(比当前市场价格高出 5%)。作为回报,我们将获得 630 美元的溢价。让我们看看我们的总头寸(我们的苹果股票加上我们卖出的看涨期权)在收益图上的样子:

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

The payoff diagram for our Apple covered call position

这张图表比其他图表稍微复杂一点,所以让我们一步一步来看:

  • 首先,注意蓝色的收益线是如何开始的,就像你只是做多苹果股票一样(如果你做多股票,你就拥有股票)。这意味着,当市场价格低于我们卖出的看涨期权的执行价格时,我们头寸的盈亏与苹果的价格一致(当苹果上涨时,我们赚钱,当它下跌时,我们赔钱)。
  • 在我们卖出的看涨期权的执行价格上,我们的利润达到上限(蓝色的收益线变平并水平)。以高于执行价的市场价格,我们卖出看涨期权的人将向我们支付 100 股苹果股票的执行价。这意味着无论苹果的价格有多高,只要我们写的看涨期权没有到期,我们就只能收到我们股票的执行价。然而,这并不是世界末日——回想一下,我们设定的执行价格比当前市场价格高出大约 5%。这意味着,即使我们的股票被赎回,到那时,我们的股票还会有 5%的收益,加上我们因出售看涨期权而获得的 630 美元的溢价(额外的 3%)。总回报率为 8%。最重要的是,因为我们拥有股份,我们也收到任何支付的股息。
  • 我把最精彩的部分留到了最后。记住我们进入这个位置是为了降低我们的风险。**风险的降低来自于我们因卖出期权而获得的 630 美元的溢价。不管发生什么,只要我们持有到到期日,我们就能保留那 630 美元。**这意味着,如果市场崩盘,或者苹果报告糟糕的收益和亏损,**我们的损失会因为口袋里已经有的 630 美元而减少。**这就是为什么在我们的收益图上,我们头寸的盈亏平衡价格已经下降到低于我们的原始购买价格(在 X 轴上)。
  • 如果苹果的市场价格保持不变,那也没问题。我们在股票上既不赚钱也不赔钱,但我们可以保留 630 美元的溢价和任何股息。然后我们可以在几个月后卖出另一个看涨期权,再获得 600 到 700 美元的溢价。酷!

结论

很抱歉我写了这么长的帖子,但是期权是复杂且有风险的,我想在推荐一个策略之前确保涵盖所有的基础知识。最后,我应该强调的是,保修电话并不适合所有人。如果你是以下类型的投资者,它们可能适合你:

  • 担心你的股票或整体市场的估值。
  • 有点厌恶风险。
  • 渴望一些现金收入,但不想卖掉你的股票。

投资愉快,干杯!

更多由我讲述金融、投资和金钱:

用 Tableau 可视化股市

做空波动率的危害

我做的一个关于投资 Lending Club 贷款的数据科学项目

股市低迷之际

股票是否提供正的预期回报?

你有足够的钱退休吗?

为迈向数据科学而写作:不仅仅是一个社区

原文:https://towardsdatascience.com/writing-for-towards-data-science-more-than-a-community-6c9f0452b280?source=collection_archive---------21-----------------------

介绍如何开始撰写《走向数据科学》以及我迄今为止的经历。

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

Photo by Patrick Fore on Unsplash

“没有真正的结局。它只是你停止故事的地方。”

―弗兰克·赫伯特

介绍

我现在即将开始为期八个月的《走向数据科学》(Towards Data Science,TDS)作家生涯,今天我决定回顾一下我迄今为止的旅程。

如今,拥有博士学位以便从事数据科学工作,尤其是研究工作,似乎越来越有必要了。因此,今年年初,我也考虑到这个机会,我决定写一份研究提案,并申请一个职位。

一个月后,我得到了这个角色。

此时,我开始思考这是否是我的正确选择,我决定拒绝这份工作。我想一定有其他方法可以继续我在数据科学方面的研究,并与更多的人分享我的成果。

在我申请博士职位之前的几个月里,《走向数据科学》一直是旅行的一个有价值的伙伴,它帮助我总是更深入地研究这个主题。因此,我决定试着给社区出版一份我关于媒介的研究提案的修订版。从那以后,多亏了卢多维克·贝尼斯坦特,我成为了《走向数据科学》的作者。

在过去的几个月里,促使我坚持写作的一些主要原因是:

  • “如果你不能简单地解释它,你就理解得不够好”( 阿尔伯特·爱因斯坦 )。
  • 记录我的旅程。
  • 建立新的联系。
  • 每天挑战自己学习新的东西。
  • 回馈社会。

现在,我将向您介绍一些关于写什么样的数据科学文章以及如何最好地编辑它们的建议。

作家的瓶颈

当考虑开始写作时,一个主要的顾虑是:

  • 我的写作技巧是否足以让我的故事出版?
  • 我这篇文章的题目值得发表吗?

为了回答第一个问题,我想引用理查德·巴赫的一句话:

“专业作家是不放弃的业余作家.”

—理查德·巴赫

因此,只有写作并从编辑和读者那里获得反馈,我们才能提高自己和我们的沟通能力。

每篇提交给《走向数据科学》的文章在出版前都要经过编辑的审核。通过这种方式,出版物可以确保只发布最好的内容,作家可以收到关于如何改进他们的故事的反馈。此外,TDS 还提供一般支持,以防作者寻求任何关于如何提高写作的一般建议。

为了回答第二个问题,我总是在开始写故事之前问自己 3 个问题:

  • 我的故事如何能让我的读者受益?(赋予他们权力)
  • 如果我在网上研究这个话题,找到好的相关内容会有多难?
  • 我的故事能让不太懂技术的观众也能接触到基于研究的内容吗?

如果我能找到这三个问题的好答案,我就会开始写我的文章。

事实上,我的大部分文章想法都是在做一个项目的时候产生的,当时我很难在网上找到好的和最新的资料。

“如果有一本书你想读,但它还没有被写出来,那么你必须写出来。”

―托尼·莫里森

最后,如果你的内容是原创的,并为他们的读者带来价值,你总会找到有兴趣阅读它的读者。

“如果这本书是真的,它会找到一个注定要阅读它的读者。”

沃利·兰姆

一般准则

我现在给你一些建议,告诉你如何写一篇准备发表的好文章。

语法上

Grammarly 是一个 AI power 写作助手,通过安装它们的 web 扩展,可以在撰写中型文章时轻松使用。使用语法将使你的文章几乎不可能有拼写或习惯性错误。

GitHub Gists

《走向数据科学》文章的很大一部分都包含代码。通过在 Windows 或 Mac 上同时按下 Control + Alt + 6,代码片段可以很容易地集成到 Medium Markdown 界面中。

This type of code snippet is commonly used to diplay code outputs

另一个选择是使用 GitHub Gists 。git 非常容易创建,并且具有突出语法和更大格式灵活性的优势。如果你从未使用过 GitHub Gists,GitHub 文档是从开始的好地方。为了在中型文章中嵌入要点,只要确保选择可共享链接选项而不是嵌入即可。

免费开放数据源

解释数据科学主题的一个很好的方法是提供易于重复的演练示例。为了做到这一点,使用开源数据集可能是一个好主意。通过这种方式,读者将能够自己尝试代码是如何工作的,以及改变它会如何影响整体结果。

寻找开源数据集和共享输出代码的最佳地方之一是 Kaggle 。其他可以下载免费数据集的网站还有 UCI 机器学习库data.world

交互式数据可视化

添加交互式图表和 GIF 动画是为你的文章增加价值的另一种方式,因为读者可以自己改变动画的一些参数。

下面的 GIF 就是一个有趣的数据可视化的例子。事实上,从图 1 中我们可以看到 PCA(主成分分析)图中 3 个主成分的方差是如何分布的。使用静态图,不可能在所有三个不同的轴上看到如此详细的结果。

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

Figure 1: PCA variance plot

下面显示了一个交互式数据可视化的例子。在图 2 中,我们可以检查(使用滑块)在考虑所选的 min_splitmin_leaf 参数的情况下,改变随机森林分类器中估计器的数量会如何影响我们模型的整体精度。

通过更改 n_estimators 参数,放大和缩小图表,更改其方向,并将鼠标悬停在单个数据点上以获得关于它们的更多信息,您可以随意摆弄下面的图表!

Figure 2: Interactive Data Visualization

如果你想知道我是如何制作这两个动画的,更多信息可以在我的交互式数据可视化超参数优化文章中找到。

策展人指南

每次一篇文章在 Medium platform 上发表,都会被策展人审核,以决定是否应该在 Medium 上和文章标签的任何主题中做广告。因此,满足策展人的指导方针是写一篇成功文章的非常重要的一步。

如果你有兴趣了解更多关于媒体的指导方针,这些可以在这里找到。此外,也朝着数据科学写了自己的提交您的文章-清单

TDS 提交

为了向《走向数据科学》提交你的第一篇文章,你所要做的就是在 Medium 上写一篇草稿,并阅读此处提供的指南。然后刊物会审核你的文章,再回来找你。

此外,走向数据科学最近还推出了一个 YouTube 频道,你可以在上面为创建自己的视频教程做出贡献(就像我为我的 GPU 加速数据分析&机器学习文章所做的那样)。更多信息请点击这里。

感谢阅读!

联系人

如果你想了解我最新的文章和项目,请在媒体上关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

使用 Python 将 Google Sheets 数据写入 MySQL

原文:https://towardsdatascience.com/writing-google-sheets-data-to-mysql-using-python-9cabe2ed88cd?source=collection_archive---------11-----------------------

在数据作业中,我们经常使用不同的方法来编写和分析数据。Google sheets 是一个协作输入和共享数据的好方法。对于较大的数据集,Google sheets 处理起来非常慢,一种解决方法是在行数太多时创建一个新的工作表。我的团队正在进行的一个项目每周创建 3000 行,这对于大多数标准来说并不是太多的数据,但是几周后就陷入了困境。团队成员开始归档工作表,这使得对数据进行汇总变得非常困难。我认为将我们所有的数据写入 MySQL 表是一个更好的主意,这也允许其他团队将我们的数据加入到他们正在处理的其他表中。我将带您了解使用 Python 完成这一过程。对于这个项目,我将在 Windows 机器上使用 Jupyter Notebook、Python 3.7.1 和 MySQL Workbench 8.0。

谷歌工作表中的数据

我用 Google sheets 为这个项目创建了一个小数据集。我包含了两个工作表,第一个看起来像:

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

请注意,我故意在第 2 列中留出了两个单元格空白。这将是后面的一个例子。第二个工作表(底部的第二个选项卡)如下所示:

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

将 Google Sheets 连接到 Python

我们需要做的第一件事是使用 链接访问 谷歌开发者控制台。点击页面顶部的“创建项目”链接,创建一个新项目:

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

给项目起一个相关的名字,如下所示。

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

接下来,我们需要为项目创建一个服务帐户。点击页面左上角的导航菜单(3 条水平线,通常称为汉堡),选择“服务账户”:

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

您需要从页面顶部选择您的项目(a),然后点击“创建服务帐户”(b)。

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

为服务帐户取一个有意义的名称,然后单击“创建”。接下来,我们将服务帐户权限角色设置为所有者,并单击“继续”。在下一页,我们将跳过“授予用户对此服务帐户的访问权限”部分,转到下面的“创建密钥”部分。这将打开一个侧栏,允许我们选择一个键类型。选择“JSON”并点击“创建”。这将把 JSON 文件保存到您的计算机上,我们将使用这个文件从。

使用类似 Notepad++的工具打开 JSON 文件。找到包含“客户电子邮件”的行,并将整个电子邮件地址(在引号之间)复制到剪贴板。接下来,回到您的 Google sheet,它包含了您想要写入 MySQL 表的数据。点击电子表格右上角标有“Share”的绿色按钮。将 JSON 文件中的电子邮件地址粘贴到字段中,然后单击“发送”。这将允许我们的 Python 程序访问这个 Google 工作表。

设置 Jupyter 笔记本

现在一切都设置好了,我们可以继续学习 Python 了!对于本教程,我使用的是 Jupyter 笔记本和 Python 3.7.1。如果您的机器上没有安装 Python,您将需要这样做。Jupyter Notebook 自带 Anaconda,这是 Python 的一个很棒的包。您可以通过在搜索栏(在 Windows 中,在任务栏上)中键入“Jupyter Notebook”来启动 Jupyter Notebook,或者您可以启动 Anaconda 提示符,提示符打开后,键入不带引号的“Jupyter Notebook”,但我们稍后将需要 Anaconda 提示符,所以我建议使用所描述的第一种方法。

Jupyter 笔记本将在您的浏览器中启动。您将被引导至您的工作目录。您可以导航到不同的文件夹,但现在我们将通过单击页面右上角的“新建”并选择 Python 3 笔记本来创建一个新笔记本:

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

让我们通过点击页面顶部的笔记本名称(无标题)将笔记本重命名为“GoogleSheetsToMySQL”。接下来,我们需要将下载的 JSON 文件移动到我们的工作目录中。我相信默认目录在“C://users//your_username”下。

在我们开始编码之前,我们需要安装一些模块。要安装我们需要的模块,打开 Anaconda 提示符(您可以在任务栏的 Windows 搜索栏中找到它)。在 Anaconda 提示符下,您需要安装以下模块。通过键入以下命令并在每个命令后按 enter 键来使用 pip:

  1. pip 安装 gspread
  2. pip 安装 oauth 2 客户端
  3. pip 安装 mysql 连接器

我已经安装了这些,如命令提示符的输出所示(当试图安装 gspread 时):

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

因为我们将访问一个 MySQL 数据库,所以不要在代码中暴露我们的登录凭证是很重要的。我们将创建一个 Python 文件(。py)并将这些凭证存储在那里。然后,我们可以轻松地将它们导入我们的 Jupyter 笔记本脚本。创建您的。py 文件是用 Notepad++写的。为此我使用了 PyCharm,但也可以使用您喜欢的 IDE。打开 IDE 并创建一个名为“MySQLCredentials.py”的文件。在这个文件中,我们只需要输入 4 行代码并保存到我们的工作目录中。我们需要:

user = (your username)password = (your password)host = (hostname)database = (database schema you will be using)

保存文件并将其放入您的工作目录。

Jupyter 笔记本中的编码

现在,回到你的笔记本上。我们需要通过在第一个单元格中输入以下内容来导入将要使用的模块:

# import libraries**import** gspread**import** MySQLCredentials as mc**import** mysql.connector**from** oauth2client.service_account **import** ServiceAccountCredentials

运行单元,如果你没有得到任何错误,太好了!接下来,我们需要初始化一些变量来使用 gspread:

# initialize variables for gspreadscope **=** [‘[https://spreadsheets.google.com/feeds'](https://spreadsheets.google.com/feeds%27),[‘https://www.googleapis.com/auth/drive'](https://www.googleapis.com/auth/drive%27)]creds **=** ServiceAccountCredentials.from_json_keyfile_name(‘GoogleSheetsToMySQL.json’, scope)client **=** gspread.authorize(creds)

如果您将 JSON 文件命名为不同的名称,只需确保上面代码中的名称是正确的。现在我们需要定义一个从 Google 工作表中提取数据的方法:

# define method to pull data from spreadsheet**def** GetSpreadsheetData(sheetName, worksheetIndex): sheet **=** client.open(sheetName).get_worksheet(worksheetIndex) **return** sheet.get_all_values()[1:]

我们正在定义一个带有两个参数的方法。我们需要告诉它我们引用的工作表名称和工作表索引。工作表索引是指我们所引用的工作表标签。第一个选项卡的索引为 0,第二个选项卡的索引为 1,依此类推。在我们调用这个方法之前,我们不需要这些值,所以我们很快就会回来。该方法的返回类型是一个列表,它将返回该表上的所有值。然后我们使用[1:]分割列表,这将删除列表的第一个元素。因为 Google 工作表有一个包含列名的标题,所以我们只从工作表中提取数据。

在我们继续之前,让我们检查一下这个方法是否可以从工作表中获取数据。

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

在笔记本的新单元格中,输入

data = GetSpreadsheetData(‘GoogleSheetData’, 0)

您可能会得到一个错误,提示您需要启用驱动器 API。它将提供一个链接,您可以单击该链接来启用驱动 API。现在,重新运行该单元,并确保不会出现任何错误。我不得不运行它几次来启用两个独立的 API,并且在它没有给我一个错误之前必须等待一分钟。您应该不需要再次这样做。好了,现在检查你有你期望的数据。您可以检查列表的第一行,以及列表的长度(在本例中,有多少行数据):

print(data[0])
print(len(data))

应该会回来

[‘1’, ‘a’, ‘2019–01–01 1:00:00’]
10

现在我们需要设置一个方法来将这些数据写入 MySQL。使用 try-except-finally 块在这里会很有用。有几个注释块,前面用#表示,只是为了澄清:

# define method to write list of data to MySQL table**def** WriteToMySQLTable(sql_data, tableName):# we are using a try/except block (also called a try/catch block in other languages) which is good for error handling. It will “try” to execute anything in the “try” block, and if there is an error, it will report the error in the “except” block. Regardless of any errors, the “finally” block will always be executed. **try**:# Here we include the connection credentials for MySQL. We create a connection object that we pass the credentials to, and notice that we can specify the database which is ‘sys’ in the MySQLCredentials.py file because I’m using since I’m using the default database in MySQL Workbench 8.0. connection **=** mysql.connector.connect( user **=** mc.user, password **=** mc.password, host **=** mc.host, database **=** mc.database )# This command will drop the table, and we could just have the table name hardcoded into the string, but instead I am using the name of the table passed into the method. {} is a placeholder for what we want to pass into this string, and using .format(blah) we can pass the string name from the variable passed into the method here. sql_drop **=** “ DROP TABLE IF EXISTS {} “.format(tableName)# Now we will create the table, and the triple quotes are used so that when we go to the next line of code, we remain in a string. Otherwise it will terminate the string at the end of the line, and we want ALL of this to be one giant string. When injecting data into VALUES, we use the placeholder %s for each column of data we have. sql_create_table = “””CREATE TABLE {}( 
            Column1 INT(11),
            Column2 VARCHAR(30),
            Column3 DATETIME,
            PRIMARY KEY (Column1)
            )”””.format(tableName)

        sql_insert_statement = “””INSERT INTO {}( 
            Column1,
            Column2,
            Column3 )
            VALUES ( %s,%s,%s )”””.format(tableName)# Here we create a cursor, which we will use to execute the MySQL statements above. After each statement is executed, a message will be printed to the console if the execution was successful. cursor **=** connection.cursor() cursor.execute(sql_drop) print(‘Table {} has been dropped’.format(tableName)) cursor.execute(sql_create_table) print(‘Table {} has been created’.format(tableName))# We need to write each row of data to the table, so we use a for loop that will insert each row of data one at a time **for** i **in** sql_data: cursor.execute(sql_insert_statement, i)# Now we execute the commit statement, and print to the console that the table was updated successfully connection.commit() print(“Table {} successfully updated.”.format(tableName))# Errors are handled in the except block, and we will get the information printed to the console if there is an error **except** mysql.connector.Error as error : connection.rollback() print(“Error: {}. Table {} not updated!”.format(error, tableName))# We need to close the cursor and the connection, and this needs to be done regardless of what happened above. **finally**: cursor.execute(‘SELECT COUNT(*) FROM {}’.format(tableName)) rowCount **=** cursor.fetchone()[0] print(tableName, ‘row count:’, rowCount) **if** connection.is_connected(): cursor.close() connection.close() print(“MySQL connection is closed.”)

为了测试这一点,让我们运行下面的命令(您将需要运行 GetSpreadsheetData()方法,否则您将没有“数据”定义。

WriteToMySQLTable(data, ‘MyData’)

输出应该是:

Table MyData has been dropped 
Table MyData has been created 
Table MyData successfully updated. 
MyData row count: 10 
MySQL connection is closed.

在 MySQL Workbench 中检查数据看起来很成功,但是有一个问题需要解决。以下是 MySQL Workbench 中的表格:

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

请注意,我们有两个可能的问题。最后一行全部为空,我们很可能不希望这一行包含在内。但更重要的是,Column2 中缺失的值不为 NULL!这是因为 Python 正在读取工作表数据,并看到一个空值,它很可能被解释为空字符串。我们可能不希望这里有空字符串,而是期望空值。因此,让我们编写一个方法来清理空字符串值,并将它们作为空值写入。

def PreserveNULLValues(listName):
    print(‘Preserving NULL values…’)
    for x in range(len(listName)):
        for y in range(len(listName[x])):
            if listName[x][y] == ‘’:
                listName[x][y] = None
    print(‘NULL values preserved.’)

这样做的目的是检查空字符串值(“”),并用 Python 关键字“None”替换它们,这将作为空值写入 MySQL。让我们看看这个:

data = GetSpreadsheetData(‘GoogleSheetData’, 0)
PreserveNULLValues(data)
WriteToMySQLTable(data, ‘MyData’)

让我们在 MySQL Workbench 中查看一下这是什么样子的:

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

好多了!我通常不会在最后得到一个空行,但是如果需要的话,我们可以删除它。

现在,假设我们想用第二个工作表更新表,工作表索引= 1。这次我们不想掉表,只想插入表中。我们可以定义一个名为 UpdateMySQLTable 的新方法。我们将使用上述相同的方法(WriteToMySQLTable ),只是我们将删除以下代码行:

sql_drop = …
sql_create_table = …

使用新的工作表索引运行此方法:

data = GetSpreadsheetData(‘GoogleSheetData’, 1)
PreserveNULLValues(data)
UpdateMySQLTable(data, ‘MyData’)

现在,您将拥有一个包含 20 行的表格,每张表格包含 10 行。MySQL Workbench 中的结果表如下所示:

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

只要确保列名和顺序匹配即可,否则您将不得不重新排列它们。对于我的团队的数据,如果我们的方法发生变化,有时我们会在一个新的列中写入数据,我会返回并将空列插入到旧的选项卡中,然后重新导入所有数据。现在您可以利用 MySQL 中的数据库和 Google sheets 的功能了!下面是我的代码在 Jupyter Notebook 中的样子。编码快乐!

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

写作让我成为一名更好的工程师

原文:https://towardsdatascience.com/writing-is-making-me-a-better-engineer-619d6b1819d3?source=collection_archive---------27-----------------------

一篇文章对我职业生涯的影响

2015 年夏天,我走出了自己的舒适区,做了一些新的事情:我写了一篇文章。对,就是这样。如果你仔细想想,也没那么令人印象深刻。但是,尽管这一步是微小的,这一大步的涟漪却是我通向进步和机遇的大海的门票。

写作是我们可爱的老师从小就试图向我们灌输的一项技能。这是有道理的,对吗?毕竟,每个人都应该学习如何写和读。所以,非常感谢,亲爱的老师们。但是当我们不断地被诸如“写一篇关于你最喜欢的食物的文章”或“描述你的狗”这样的陈词滥调所推动时,老实说,在那个年龄我只想玩口袋妖怪,你会把写作的想法与一些敌对的东西联系起来。但是这种感觉并没有就此结束,或者至少对我来说没有结束!不,那种感觉和痛苦一直伴随着我,直到上大学,随着成年人的架子(好吧,我已经是个成年人了,但你明白我的意思)和责任的逼近,我知道我必须改变。

幸运的是,没有什么是永恒的,因此,我决心改变我的“eww 写作”观点。因此,四年前,我坐下来,想出一个我真正喜欢的话题,并写了一个技术教程。你猜怎么着?我越来越喜欢它,直到今天,在我写下那场灾难的几年后,我还在这样做。

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

My trusty Pokemon notepad.

我是一名软件工程师,主要与数据打交道。您可能已经听说过,数据已经成为(不管我们喜欢与否)我们生活中不可或缺的一部分。我们采取的许多行动,我们输入的点击,我们行走的步伐,以及我们甚至无法想象的事情,都被记录和记录在某个地方。但是,尽管这些数据具有革命性并被大肆宣传,但关键的细节是,这些数据本身并不多;它只是一堆数字、字符和比特,坐在某处等待被抓住和拥抱。幸运的是,有像我这样的人愿意为它发声。

每隔一天,我都会摘掉软件工程师的名牌,称自己为“数据故事讲述者”简单地说,我收集数据,分析数据,然后写下我的发现。很好玩!仔细检查和嗅一排又一排的数据感觉就像扮演一个寻找线索和渴望答案的侦探。然而,尽管我喜欢穿上我的白大褂,研究我今天走了多少步,但我的满足感来自于写下我的发现。

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

Custom titles are the best.

随着时间的推移,我意识到,在点击“发布按钮并获得一些我通常会得到的赞/掌声/观点后,我新发现的爱好并没有结束。没有。经过一些思考,我注意到我在这次扫盲之旅中获得的技能不仅影响了我的创造性,也影响了我的职业生活。

首先,如我所说,我是一名软件工程师。因此,我的大部分任务是在文本编辑器中输入指令,告诉计算机应该做什么。尽管这种写作与编写数据故事有很大的不同,但最近,我注意到我正在编写的代码在某种程度上更加优雅、流畅和可读。在写散文的时候,我们,或者至少是我,把我们的文章分成三部分:引言、主旨和结论。此外,每一部分都有其结构,其中的句子也有其形状。这种在头脑中思考如何设计一篇连贯的文章也成了我写代码的方式。

现在,我把我的节目看作一个故事,一个有开头、主旨和结尾的东西。在每段代码的开头,我都列出了我的“故事”的基本原则,同时向我自己(和未来的读者)解释在接下来的几行中我应该期待什么。然后,在文章的实质部分,我更加强调内容的可读性,而不是炫耀语言所有闪亮的特性。最后,在文章的结尾,我想对我刚刚写的内容做一个总结,简要地提一下结果应该是什么,并且在某些情况下,为任何未来的工作打下基础。因此,我愿意说写作提高了我写代码的能力。

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

Not much to tell here, though.

有时候,写一个话题需要事先研究我们将要讨论的主题。我遇到的每个数据集和问题都比前一个有一千倍的不同。因此,为了解决我将要承担的任务,这在大多数情况下意味着写下我将要剖析的数据集,首先,我需要学习、理解和研究一组适合我的问题的最佳工具和算法。我应该用 R 吗?Python?无监督学习?也许描述性统计就够了?现在,想象一下每年做几次,你知道我学到了多少吗?在我看来,所有这些技能、框架、算法和编程语言,我在那些漫长的文字之夜中遇到的,无疑使我成为了一名更好的工程师。

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

Data, yes!

我真诚地相信,一个工程师的“伟大”或“能力”不能仅仅用他知道多少或有多少生产力来衡量。一个高效的工程师,在我看来,就是拥抱所谓的软技能的人;你与同事相处的方式,办公室内的沟通方式,当然还有你回复那些早上第一件事就是问候你的不受欢迎的电子邮件的方式。正如你可能已经猜到的那样,写作,以及我在尝试通过我的短文、文章和教程进行非语言交流时学到的技能,极大地提高了我在“现实生活”中与他人通信和联系的能力。

但是,让我们做得更激烈些。如果你在这篇文章的顶部看到我的名字,你可能会认为我的母语不是英语。如果是这样,你是正确的。我来自加勒比海,我的母语是西班牙语(hola!),而且我有我所谓的芭蕉口音。但这里有一个重要的细节,我提出这个问题的原因是,我的大部分职业生涯都是在我的祖国之外的非西班牙语环境中度过的。所以我必须加紧提高我的英语水平!哇,我向你发誓,写作让我的词汇量增加了十倍。每隔一天,在谈话中,我会说“尽管”、“前面提到的”和“然而”(喜欢这个),人们会说“胡安,你刚才真的用了那个词吗?”“是的,我做到了。”所以再次,写作,此外(见?),把每一个术语都输入词库,努力想出一个花哨的、不重复的表达一个想法的方式,也提高了我的沟通能力。因此,我感到更加自信,因此,希望这能让我成为一名更好的工程师。

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

Plantains (not bananas!). Photo by Holger Link on Unsplash

最后,我想说,写作和它的教导,让我发现了一项我从来不知道自己会如此感兴趣的活动:演讲。在我写作过程中的某个时刻,我想知道把这些信带给真正的读者会是什么样。我照做了!但是哇说话其实挺难的。演讲日不是在公园散步。你流汗,紧张,忘词,等等。但是你知道吗?每次我站在数百双看着我的眼睛前,我都觉得自己做好了准备,因为我从生活中的每一个单词中学到的规则——连贯性、过渡、词汇等等——使我总体上成为一个更好的沟通者。虽然我不确定演讲是否会直接让我成为一名更好的工程师,但你遇到的人、学到的技能和教授的课程肯定会让我成为一名更好的工程师。

所以,谢谢你,写作。我迫不及待地想知道你接下来会带我去哪里。

现在你告诉我,写作对你有什么好处?

感谢阅读。

为超级计算机编写程序

原文:https://towardsdatascience.com/writing-programs-to-super-computers-edf3da4f2b8c?source=collection_archive---------26-----------------------

何时、何事以及如何改变你的代码。

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

Server Racks (Image Source)

抽象而不精确的印象

为了给超级计算机一个概念,想象一整套强大的机器,你可以把它们作为一个整体来使用。够奇怪吗?它不一定是一台拥有大量内存或 CPU 能力的机器。事实上,它们的确拥有强大的计算能力,但不仅仅是通过提高速度或内存。让我们来看看 NCI (我目前正好与之合作)。这些是在 NCI 的规格。

  • 4,500 个英特尔至强 Sandy Bridge、Broadwell 和 Skylake 节点中的 89,256 个内核
  • 32 个 NVIDIA Tesla K80 和 P100 节点中的 128 个 GPU
  • 32 个节点中的 32 个 64 核英特尔至强融核处理器
  • 4 个 IBM Power8 节点中的 64 个内核
  • 300 兆字节的内存
  • 8pb 的操作磁盘存储
  • 混合 FDR/EDR Mellanox Infiniband 全胖树互连(高达 100 Gb/秒)

由于这是一个完整的计算设施,澳大利亚各地成千上万的用户使用,程序被接受以作业的形式运行,在特定的项目拨款(通常由研究机构资助)下提交给队列。不同的队伍收费不同。但是基本上是按 CPU 小时收费,乘以队列成本(由队列规格和优先级决定)。如果你有 1 个 CPU 程序运行 1 小时;你消耗 1 个服务单位乘以排队成本(如果你喜欢可以阅读更多)。通常授权数量级为数千或数百万 CPU 小时。

规格的含义

提交工作时,您可以指定所需的资源。这里最重要的事情是,系统架构对于 CPU 总是 x64,对于 GPU 总是 CUDA。所以当你为 Linux 操作系统编译时,你可以在超级计算机上运行它们。您的职位提交将如下所示。

#!/bin/bash
#PBS -P ch35
#PBS -q biodev
#PBS -l ncpus=28
#PBS -l mem=512GB
#PBS -l jobfs=1GB
#PBS -l walltime=100:00:00
#PBS -l wdmodule load java/jdk1.8.0_60module use -a /short/qr59/aw5153/modules/
module load canu/1.8java_path=$(which java)canu -p meta -pacbio-raw cluster-0cluster-0.fastq -d canu-cluster-0cluster-0/ maxMemory=512 maxThreads=28 useGrid=false java=$java_path genomeSize=50m

这是我用来组装宏基因组样本的真实脚本(有数百万次读取。或者像一些程序一样思考)。我已经从 project ch35 申请了 28 个内核/CPU,内存为 512GB,运行时间为 100 小时。所以我会消耗28 * 100 * 1.5 = 2800 * 1.5 = 4200服务单位。1.5 是biodev作业队列的成本。通常内存是不收费的,因为当你要求 28 个 CPU 时,它们会分配一个完整的节点,所以我们基本上每个节点都有576GB的 RAM。

您可以看到,我们在 4500 个节点中有 89,256 个内核。这些节点可以被认为是通过 infiniband(超高速网络)连接的独立计算机。这些节点可以通过消息传递接口(MPI)共享数据,但它们没有共享内存。这意味着如果您要求 56 个核心,我将得到 2 个节点,每个节点 28 个核心,每个节点 576GB 最大 RAM(总共 1152GB 或 1TB RAM)。但是你不能加载一个超过 576GB 的程序。这是因为这些节点是 NUMA 节点,代表非统一内存访问。一个节点中的一个进程不能访问另一个节点的 RAM。所以如果你的程序更大,你就完了!还是你?

让我们用一个示例程序来看看这个场景

假设您想要计算一个巨大数据集(数百万个基因组读数——每个约 100k 个字符的字符串)的所有可能的 n 元文法。然后有一个每个 n 元文法计数的查找表。然后,对于每个字符串,您希望用它们在整个语料库中的 n-gram 计数来注释它们。最有效的方法是在内存中保存一个巨大的哈希表,并将其用作查找表,迭代每个 100k 字符串的 n 元语法并进行注释)。查找表将占用 25GB(假设)。按顺序做这件事需要很多时间,所以我们想并行处理它们。

什么时候改?

在我们的示例场景中,每个节点最多可以有 28 个线程(这个特定场景的 RAM 不是大问题)。但是仅用 28 个内核运行这个需要几天时间。现在,我们需要使用 28 个以上的内核,更有可能是 100 个甚至更多的内核。

**现实:**如果我只要求 1000 个(这会自动挑选 36 个节点)核心并提交我的作业,它会因颠簸而停止。这是因为尽管我要求 1000 个内核,但我的程序将在 1 个节点上运行,因为一个进程只能在一个节点上运行。

这时我们知道我们的程序必须改变以适应超级计算环境或网格系统。

要改什么?

如果我们能运行 1000 个并行进程,我们就能克服上述挑战。这是因为独立的进程可以在独立的节点上运行,因为操作系统(或网格系统)可以有效地调度它们。但是现在我们的 RAM 需求会立刻增加,需要我们25*1000GB,因为我们必须为每个进程准备单独的查找表。我们只需要 25TB 的内存。但是对于 36 个节点,我们只有36*576GB = 20TB。这就是我们需要多处理和多线程的地方。因此,我们需要改变线程和进程管理方面,以获得对服务单元的最佳利用。让我们看看该怎么做。

怎么改?

由于我们正在努力提高性能,我将从科学计算中经常使用的 C++和 Python 编程的角度进行解释。对于多线程,我们可以使用 OpenMP (C++)或者 python 的多处理库(你必须使用共享内存架构)。否则,您将再次丢失内存)。对于多重处理,您可以使用Open-MPI(c++和 Python 变体都可用)。现在,我们可以简单地部署每个进程有大约 28 个线程的进程。现在,每个进程将只使用驻留在单个节点上的 25GB RAM。同样,我们可以一次将更多的 100k 字符串加载到 RAM 中,用 28 个线程进行处理(因为在加载查找表后,每个节点中还有大量 RAM)。这个程序运行得快多了。

您将需要一些预处理和后处理来将初始数据集分成 36 个部分,并收集所有 36 个输出,这些输出可以是作业队列之外的简单的split and cat命令。以下是来自 MPI 教程的修改代码。

#include <mpi.h>
#include <omp.h>
#include <iostream>
#include <vector>
#include <string>int main(int argc, char** argv) {
    MPI_Init(NULL, NULL);

    // Get the number of processes
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);

    // Get the rank of the process
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

    // Print off a hello world message
    vector<string> data; // Load data set of rank to run with 28 threads
    #pragma omp parallel for num_threads(28)
    for(string s: data)
        // process // Finalize the MPI environment.
    MPI_Finalize();
}

你真正的程序会比这复杂得多。如果您正在使用 python 工作,请确保您已经阅读了文档,以确保线程化时不会出现冗余内存共享(否则它将克隆所有共享变量,包括查找表)。

我打算分享完整的实现,但不是在这一点上,因为我打算介绍许多优化,你可以在未来的写作。

希望这是一本好书,至少对初学者来说是这样。

干杯!

用 pytest 为白蛋白库编写测试

原文:https://towardsdatascience.com/writing-test-for-the-image-augmentation-albumentation-library-a73d7bc1caa7?source=collection_archive---------26-----------------------

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

https://github.com/albu/albumentations

我的名字是弗拉基米尔·伊格洛维科夫。我是 Lyft 的高级计算机视觉工程师,Level5,将深度学习应用于自动驾驶汽车的问题。

我也是 Kaggle 特级大师和图像增强库相册的作者之一。这个库是从 Kaggle Masters 的一系列计算机视觉竞赛的获奖解决方案中脱颖而出的: Alexander BuslaevAlex ParinovEugene Khvedchenya 和我。

大约一年前,我们发布了该库的 alpha 版本。从那以后,它被工业、学术界的机器学习工程师和研究人员采用,当然也被竞争激烈的机器学习社区采用。在过去的八个月中,Kaggle 计算机视觉挑战赛中的所有或几乎所有顶级解决方案都使用了我们的图书馆。

在某个时候,Alex Parinov 写了一篇关于单元测试的文本,以及我们如何使用它们来检查我们实现的 60 多个不同的转换。目前,我们需要通过 4470 个单元测试,才能合并每个拉取请求。问题是如何编写这些测试来增加覆盖率并减少重复代码的数量。

在那篇文章中,Alex 向读者展示了一组例子,解释了如何编写测试。他从一个简单的用例开始,然后是更高级的夹具和参数化。

我认为该文档没有得到数据科学界的足够重视。因此,我把它复制到这个平台上,对原文做了一些修改。

我将假设读者熟悉这个库。如果没有,您可以查看一套 Jupiter 笔记本,其中涵盖了不同计算机视觉任务的应用:

写作测试

第一次测试

我们使用 pytest 来运行白蛋白的测试。包含测试的 python 文件应该放在albumentations/test文件夹中。文件名应该以test_开头。例如,test_bbox.py。测试函数的名称也应该以test_开头。例如def test_random_brightness()

假设我们要测试brightness_contrast_adjust函数。该函数将 NumPy 数组作为输入,将所有值乘以指定的参数alpha并返回结果数组。

让我们为这个函数编写第一个测试。测试将检查如果您向函数传递一个所有值都等于128且参数alpha等于1.5的数组,该函数将产生所有值都等于192的数组。(128 * 1.5 = 192)

在文件夹albumentations/test中,我们创建一个新文件test_sample.py

在文件的顶部,我们添加了所有必需的导入:

**import numpy as np****import albumentations.augmentations.functional as F**

测试本身:

**def** test_random_contrast():
    img = np.ones((100, 100, 3), dtype=np.uint8) * 128
    img = F.brightness_contrast_adjust(img, alpha=1.5)
    expected_multiplier = 192
    expected = np.ones((100, 100, 3), dtype=np.uint8) * expected_multiplier
    **assert** np.array_equal(img, expected)

为了运行来自test_example.py的测试,此时它只包含一个测试,我们执行以下命令:

pytest tests/test_example.py -v .

-v标志告诉 pytest 产生更详细的输出。

pytest 将显示测试已成功完成:

tests/test_example.py::test_random_brightness PASSED

测试参数化和@ pytest . mark . parameter ize 装饰器

上例中的函数很简单,它没有考虑到 8 位图像不能包含超过 255 =(2⁸-1)的值。

因此,我们希望函数brightness_contrast_adjust来处理这个问题,并截取超出[0,255]范围的值。

让我们写一个测试:

**def** test_random_contrast_2():
    img = np.ones((100, 100, 3), dtype=np.uint8) * 128
    img = F.brightness_contrast_adjust(img, alpha=3)expected_multiplier = 255
    expected = np.ones((100, 100, 3), dtype=np.uint8) * expected_multiplier
    **assert** np.array_equal(img, expected)

接下来,我们将从test_example.py开始运行测试:

pytest tests/test_example.py -v

输出:

tests/test_example.py::test_random_brightness PASSED
tests/test_example.py::test_random_brightness_2 PASSED

功能test_random_brightnesstest_random_brightness_2看起来几乎一样。唯一不同的是alphaexpected_multiplier的值。为了消除代码重复,我们可以使用@pytest.mark.parametrize装饰器。有了这个装饰器,我们可以描述哪些值应该作为参数传递给测试, pytest 将多次运行测试,每次都从装饰器传递下一个值。

我们可以使用参数化将之前的两个测试重写为一个测试:

**import** **pytest****@pytest.mark.parametrize**(['alpha', 'expected_multiplier'], [(1.5, 192), (3, 255)])
**def** test_random_brightness(alpha, expected_multiplier):
    img = np.ones((100, 100, 3), dtype=np.uint8) * 128
    img = F.brightness_contrast_adjust(img, alpha=alpha)
    expected = np.ones((100, 100, 3), dtype=np.uint8) * expected_multiplier
    **assert** np.array_equal(img, expected)

该测试将运行两次,在第一次运行中,alpha将等于1.5,而expected_multiplier将等于192。在第二次运行中,alpha将等于3,而expected_multiplier将等于255

让我们进行测试:

tests/test_example.py::test_random_brightness[1.5-192] PASSED
tests/test_example.py::test_random_brightness[3-255] PASSED

正如我们所见, pytest 在每次运行时打印测试参数值。

使用辅助函数简化对图像和遮罩都有效的函数的测试

假设我们想要测试vflip函数。此函数垂直翻转作为输入传递的图像或遮罩。面具的形状是(height, width)

**def** test_vflip_mask():
    mask = np.array(
        [[1, 1, 1],
         [0, 1, 1],
         [0, 0, 1]], dtype=np.uint8)
    expected_mask = np.array(
        [[0, 0, 1],
         [0, 1, 1],
         [1, 1, 1]], dtype=np.uint8)
    flipped_mask = F.vflip(mask)
    **assert** np.array_equal(flipped_mask, expected_mask)

测试的结果:

tests/test_example.py::test_vflip_mask PASSED

下一步,我们将测试相同的函数如何处理 RGB 图像,RGB 图像是具有形状(height, width, 3)的三维 NumPy 数组。

**def** test_vflip_img():
    img = np.array(
        [[[1, 1, 1],
          [1, 1, 1],
          [1, 1, 1]],
         [[0, 0, 0],
          [1, 1, 1],
          [1, 1, 1]],
         [[0, 0, 0],
          [0, 0, 0],
          [1, 1, 1]]], dtype=np.uint8)
    expected_img = np.array(
        [[[0, 0, 0],
          [0, 0, 0],
          [1, 1, 1]],
         [[0, 0, 0],
          [1, 1, 1],
          [1, 1, 1]],
         [[1, 1, 1],
          [1, 1, 1],
          [1, 1, 1]]], dtype=np.uint8)
    flipped_img = F.vflip(img)
    **assert** np.array_equal(flipped_img, expected_img)

在这个测试中,img的值与分配给test_vflip_mask中的mask变量的 NumPy 数组相同,但是这次它重复了三次(三个通道各一次)。expected_img也是一个重复三次的 NumPy 数组,它被分配给test_vflip_mask函数中的expected_mask变量。

让我们进行测试:

tests/test_example.py::test_vflip_img PASSED

test_vflip_img中,我们手动定义了imgexpected_img的值,分别等于重复三次maskexpected_mask的值。

为了避免不必要的重复代码,我们可以创建一个 helper 函数,它将一个形状为(height, width)的 NumPy 数组作为输入,并沿着一个新的轴重复这个值三次,以生成一个形状为(height, width, 3)的 NumPy 数组:

**def** convert_2d_to_3d(array, num_channels=3):
    **return** np.repeat(array[:, :, np.newaxis], repeats=num_channels, axis=2)

接下来,我们可以使用该函数将test_vflip_img重写如下:

**def** test_vflip_img_2():
    mask = np.array(
        [[1, 1, 1],
         [0, 1, 1],
         [0, 0, 1]], dtype=np.uint8)
    expected_mask = np.array(
        [[0, 0, 1],
         [0, 1, 1],
         [1, 1, 1]], dtype=np.uint8)
    img = convert_2d_to_3d(mask)
    expected_img = convert_2d_to_3d(expected_mask)
    flipped_img = F.vflip(img)
    **assert** np.array_equal(flipped_img, expected_img)

让我们进行测试:

tests/test_example.py::test_vflip_img_2 PASSED

通过使用参数化来简化对图像和遮罩都起作用的函数的测试

在上一节中,我们为vflip编写了两个单独的测试。第一个检查了vflip如何使用蒙版,第二个检查了vflip如何使用图像。

这些测试共享大量相同的代码。因此,我们可以将公共部分移动到单个函数中,并使用参数化将关于输入类型的信息作为参数传递给测试:

**@pytest.mark.parametrize**('target', ['mask', 'image'])
**def** test_vflip_img_and_mask(target):
    img = np.array(
        [[1, 1, 1],
         [0, 1, 1],
         [0, 0, 1]], dtype=np.uint8)
    expected = np.array(
        [[0, 0, 1],
         [0, 1, 1],
         [1, 1, 1]], dtype=np.uint8)
    **if** target == 'image':
        img = convert_2d_to_3d(img)
        expected = convert_2d_to_3d(expected)
    flipped_img = F.vflip(img)
    **assert** np.array_equal(flipped_img, expected)

该测试将运行两次,第一次运行时target将等于'mask``。条件if target == ‘image’:将不被执行,测试将检查vflip如何与屏蔽一起工作。在第二次运行中,target将等于’image’。将执行条件if target == ‘image’:,测试将检查vflip`如何处理图像:

tests/test_example.py::test_vflip_img_and_mask[mask] PASSED
tests/test_example.py::test_vflip_img_and_mask[image] PASSED

我们可以通过将if target == 'image'下的逻辑移到一个单独的函数中来进一步减少代码量:

**def** convert_2d_to_target_format(*arrays, target=None):
    **if** target == 'mask':
        **return** arrays[0] **if** len(arrays) == 1 **else** arrays
    **elif** target == 'image':
        **return** tuple(convert_2d_to_3d(array, num_channels=3) **for** array **in** arrays)
    **else**:
        **raise** ValueError('Unknown target {}'.format(target))

该函数将把形状为(height, width)的 NumPy 数组作为输入,并根据target的值,要么原样返回它们,要么将它们转换为形状为(height, width, 3)的 NumPy 数组。

使用这个助手函数,我们可以如下重写测试:

**@pytest.mark.parametrize**('target', ['mask', 'image'])
**def** test_vflip_img_and_mask(target):
    img = np.array(
        [[1, 1, 1],
         [0, 1, 1],
         [0, 0, 1]], dtype=np.uint8)
    expected = np.array(
        [[0, 0, 1],
         [0, 1, 1],
         [1, 1, 1]], dtype=np.uint8)
    img, expected = convert_2d_to_target_format(img, expected, target=target)
    flipped_img = F.vflip(img)
    **assert** np.array_equal(flipped_img, expected)

pytest 输出:

tests/test_example.py::test_vflip_img_and_mask[mask] PASSED
tests/test_example.py::test_vflip_img_and_mask[image] PASSED

使用夹具

假设我们想测试这样一种情况,我们将一个数据类型为np.uint8的图像和蒙版传递给VerticalFlip增强,我们希望它不会改变输入的数据类型,并将产生一个数据类型为np.uint8的图像和蒙版作为输出。

这种测试可以写成如下形式:

**from** **albumentations** **import** VerticalFlip**def** test_vertical_flip_dtype():
    aug = VerticalFlip(p=1)
    image = np.random.randint(low=0, high=256, size=(100, 100, 3), dtype=np.uint8)
    mask = np.random.randint(low=0, high=2, size=(100, 100), dtype=np.uint8)
    data = aug(image=image, mask=mask)
    **assert** data['image'].dtype == np.uint8
    **assert** data['mask'].dtype == np.uint8

我们生成随机图像和随机遮罩,然后将它们作为输入传递给 VerticalFlip 转换,之后,我们检查输出值的数据类型。

如果我们希望对其他增强也执行这种检查,我们将不得不编写代码来在每次测试开始时生成随机图像和遮罩:

image = np.random.randint(low=0, high=256, size=(100, 100, 3), dtype=np.uint8)
mask = np.random.randint(low=0, high=2, size=(100, 100), dtype=np.uint8)

为了避免这种重复,我们可以将生成随机值的代码移到 fixture 中。夹具的工作原理如下:

tests/conftest.py e 中,创建用@pytest.fixture装饰器包装的函数:

**@pytest.fixture**
**def** image():
    **return** np.random.randint(low=0, high=256, size=(100, 100, 3), dtype=np.uint8)**@pytest.fixture**
**def** mask():
    **return** np.random.randint(low=0, high=2, size=(100, 100), dtype=np.uint8)

在我们的测试中,我们使用夹具名称作为可接受的参数:

**def** test_vertical_flip_dtype(image, mask):
    ...

pytest 将使用参数的名称来查找具有相同名称的 fixture,然后它将执行这些 fixture 函数,并将输出作为参数传递给测试函数。

我们可以使用夹具重写test_vertical_flip_dtype,如下所示:

**def** test_vertical_flip_dtype(image, mask):
    aug = VerticalFlip(p=1)
    data = aug(image=image, mask=mask)
    **assert** data['image'].dtype == np.uint8
    **assert** data['mask'].dtype == np.uint8

夹具和参数化的同时使用

假设我们想要检查两个转换是否正确地处理了输入和输出数据类型,例如, VerticalFlipHorizontalFlip

从技术上讲,我们可以为每个转换编写一个单独的测试。我们在上一节为 VerticalFlip 写了一个。现在我们为水平的写几乎相同的:

**from** **albumentations** **import** HorizontalFlip**def** test_horizontal_flip_dtype(image, mask):
    aug = HorizontalFlip(p=1)
    data = aug(image=image, mask=mask)
    **assert** data['image'].dtype == np.uint8
    **assert** data['mask'].dtype == np.uint8

这种方法可行,但我们可以做得更好。在测试中消除不必要的代码复制会很棒。为此,我们可以使用参数化,并将一个类作为参数传递。

检查垂直翻转水平翻转的测试可以写成如下:

**from** **albumentations** **import** VerticalFlip, HorizontalFlip**@pytest.mark.parametrize**('augmentation_cls', [
    VerticalFlip,
    HorizontalFlip,
])
**def** test_multiple_augmentations(augmentation_cls, image, mask):
    aug = augmentation_cls(p=1)
    data = aug(image=image, mask=mask)
    **assert** data['image'].dtype == np.uint8
    **assert** data['mask'].dtype == np.uint8

该测试将运行两次。在第一次运行中,augmentation_cls参数将等于VerticalFlip。在第二次运行中,augmentation_cls参数将等于HorizontalFlip

pytest 输出:

tests/test_example.py::test_multiple_augmentations[VerticalFlip] PASSED
tests/test_example.py::test_multiple_augmentations[HorizontalFlip] PASSED

结论

现在,如果您克隆这个库并运行 **pytest,**您将会看到 60 多个转换被 4470 个测试所覆盖。每次合并拉取请求时,它们都应该通过。而且测试的数量还在增长。

当我们添加新的功能或修复在 https://github.com/albu/albumentations/issues报告的问题时,我们会编写新的测试。

单元测试并不容易涵盖机器学习管道中的所有内容。但是管道的某些部分,那些具有确定性的部分,我们肯定能够也应该涵盖。

遗憾的是,数据科学家低估了机器学习的这一部分,他们更关注过程的炼金术部分,如超参数或网络架构。

我希望通过这篇博客,我们至少激励了一些数据科学家,他们不会编写测试来实现一些简单的功能来检查一些东西。这可能是养成高质量代码的好习惯的第一步。

附注:所有文字归功于亚历克斯·帕瑞诺夫

用 Python 编写探索人类遗传学的有用函数

原文:https://towardsdatascience.com/writing-useful-functions-to-explore-human-genetics-with-python-3e135540ea0?source=collection_archive---------20-----------------------

简单的 Python 函数有助于深入了解人类疾病

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

Image Courtesy of National Cancer Institute Via Unsplash

Python 和序列数据示例

许多人类遗传性神经退行性疾病,如亨廷顿氏病(HD ),与特定基因中三核苷酸重复数量的增加有关。在遗传学中,密码子,一种三核苷酸重复,编码氨基酸,蛋白质的组成部分。具体而言,在亨廷顿氏病中,病理严重性与 CAA 或 CAG 密码子重复的数量相关。这些密码子指定了氨基酸谷氨酰胺,它是 20 个小构件之一。因此,HD 属于统称为多聚谷氨酰胺(polyQ)疾病的一组疾病。

超过 35 个串联重复序列实际上就确定了这种疾病,而这种基因的健康变体有大约 6-35 个串联重复序列。

幸运的是,Python 可以用来编写简单的函数来研究 mRNA 转录物,组装蛋白质所需的指令模板,并确定 CAA/CAG 密码子串联重复的数量。

目标:

在生物学领域,我们很幸运,我们可能感兴趣的许多文件都是基于文本的文件,这些文件来自 NCBI 等数据库。这意味着我们可以将它们视为普通的 Python 字符串。

对于我将在这里演示的函数,我希望输出内容尽可能丰富。

具体来说,我想分析一个典型的编码亨廷顿蛋白的 mRNA 转录本的 FASTA 文件。在遗传学中,FASTA 文件是一个简单的文件,文件头包含序列的唯一标识符,序列本身位于文件头之下,如下所示:

FASTAheader

AGCTCGATACGAGA

我想检索并计算出该文件的登录号或标识符,序列的 DNA 长度。重要的是,我希望用户为要在文件中搜索的 CAA/CAG 密码子选择他们自己的串联重复数,并让输出通知用户 CAA/CAG 密码子在输入串联数以上的连续运行次数,这些串联序列是什么,以及每次运行中发现多少重复。

入门指南

首先让我们在一小段 DNA 序列上练习。我特意截取了这个带有“X”的 DNA 序列,以中断连续的 CAG/CAA 密码子运行。

首先,我使用。upper()方法。然后我使用 regex 模块,在这里我搜索出现三次或更多次的 CAG 或 CAA 密码子。管道字符|代表 or,花括号给出了需要查找这些序列的次数限制(在这里,逗号后面的上限被去掉了)。

因此,在这个例子中,我想找到在 DNA 串中出现三次以上的 CAA/CAG 序列,这意味着如果满足这个要求,应该找到长度至少为 9 的 DNA。然后,我遍历找到的匹配,保存在变量 pattern_match 中,并打印满足这个标准的序列。为了清楚起见,我还将这些序列附加到一个新列表中,并打印它们的长度。

找到 2 次运行,并且两次运行都高于至少 9 次运行的最小阈值。

使用文件

为了打开文件,我使用 open 函数,使用 with 语句。然后我将文件切片,因为我不希望 FASTA 文件的登录名称(头)影响我的 DNA 计数。这意味着我需要在元素 0 处对文件进行切片,这将删除文件头,然后读取切片后的文件 f,小心地删除任何新的行字符。

-下图显示了不删除新行字符的影响。这些字符会破坏 CAG/CAA 的连续运行,并给 DNA 增加额外的长度,这将不能代表序列数据。

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

The impact of forgetting to remove new-line characters; the sequence is artificially longer and not representative of the sequence data.

然后我使用如上所述的 re.finditer 方法。为了让这个代码片段工作,有必要导入 islice 和 re。

从 itertools 进口 islice
进口 re

下面显示的是脚本和控制台输出。如图所示,显示了登录名称,随后是序列长度,发现了多少个大于 3 的 CAA/CAG 游程,这些游程的序列及其各自的长度和串联重复数。

然而,这段代码可以提供更多的信息,也更容易解释。例如,在每一部分之前打印一条消息,告知用户输出代表什么。此外,这段代码有点不灵活,因为它只适用于“test.fasta ”,并检查 CAA/CAG 的连续运行 3 次或更多次。为了改进这个脚本,最方便的选择是将它转换成一个函数。

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

The output in the console is hard to interpret, and could include informative text beside.

功能创建

现在代码的主体已经写好了,创建一个函数不需要太多额外的工作。按照规定,用户应该能够自己选择的两个参数应该是要分析的 DNA 文件和串联重复的限制。

我定义了函数 huntington_tandem_repeat_dna,并在括号内给了函数两个参数。dna 参数是打开的文件,tri_nucleotide_repeat_num 的默认值为 3,以防用户决定不指定串联重复编号。

为了测试这个函数,让我们测试两种情况。一个是我创建的虚拟测试文件,用扩展名. fasta 保存。我已经在这个文件中包含了 2 个连续的 CAG/CAA 密码子。一个是 24 个碱基对长,另一个是 12 个。我已经包含了这个文件来验证函数是否按预期工作。

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

Boxed: The boxed section refers to a a 24 base pair segment, comprised of 8 tandem runs of CAA/CAG codons.

我正在运行的文件在我的本地目录中,因此我只指定了它们的相对路径。

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

我运行的另一个 DNA 样本是 mRNA 序列。在这里,我想确保在分析文件时,碱基对的数量是匹配的。NCBI 数据库告诉我序列长度应该是 13,498bp,当用这个 dna 文件调用Huntington _ tandem _ repeat _ DNA函数时,这确实得到了确认。除此之外,两种情况下的登录名称都匹配,这证明一切都按预期进行。

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

The output in the console is explicit.

摘要

兜了一圈,原来的目的已经达到了。该函数读取文件并给出清晰易懂的有用输出。

选择上图所示的第二个示例,我们可以清楚地看到,DNA 长度为 13,498 bps,用户已经搜索了 23 次或更多次 CAG/CAA 连续运行,但只找到一次符合该标准的运行。匹配的序列被打印出来,连同它的长度,以及包含该运行的串联重复的数目。

该功能现在完全可以扩展,例如处理多个文件并将输出写入任何特定的目的地,如果用户想要添加这种额外的功能。

我希望这篇文章展示了用 Python 编写函数是如何洞察人类遗传疾病的。更多代码示例,请关注我的 linkedIn 和 M edium

深度学习完全初学者指南:卷积神经网络和图像分类

原文:https://towardsdatascience.com/wtf-is-image-classification-8e78a8235acb?source=collection_archive---------0-----------------------

在几分钟内攻克 CNN 和图像分类的基础知识

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

Image by VislazFotosas via Pixabay

“我很早就注意到的一件事是,你不会把将要拍出来的东西放进照片里。或者反过来,出来的不是你放进去的。”

黛安·阿勃斯

你最喜欢的社交网络上弹出通知,有人发布了一张可能有你的照片。

没错。

这是你有史以来最差的照片。

GIF via GIPHY

那是怎么发生的?

图像分类

卷积神经网络(CNN)是深度学习神经网络的一类。CNN 代表了图像识别的巨大突破。它们最常用于分析视觉图像,并且经常在图像分类的幕后工作。从脸书的照片标签到无人驾驶汽车,它们都是一切事物的核心。从医疗保健到安全,他们都在幕后努力工作。

他们又快又有效率。但是它们是如何工作的呢?

图像分类是获取一个输入(像一张图片)并输出一个(像“猫”)或一个概率输入是一个特定的类(“这个输入有 90%的概率是一只猫”)。你可以看着一张照片,知道你正在看一张你自己的可怕的照片,但是计算机怎么能学会这样做呢?

用卷积神经网络!

美国有线电视新闻网

  • 卷积层
  • ReLU 层
  • 池层
  • 完全连接的层

一个经典的 CNN 架构应该是这样的:

输入- >卷积- > ReLU - >卷积- > ReLU - >汇集- >
ReLU - >卷积- > ReLU - >汇集- >全连接

CNN 卷积(非卷积…)学习输入数据的特征,并使用 2D 卷积层。这意味着这种类型的网络是处理 2D 图像的理想选择。与其他图像分类算法相比,CNN 实际上很少使用预处理。这意味着他们可以学习其他算法中必须手工制作的过滤器。CNN 可以用于大量的应用,从图像和视频识别、图像分类和推荐系统到自然语言处理和医学图像分析。

CNN 受到生物过程的启发。他们基于 Hubel 和 Wiesel 在 60 年代对猫和猴子的视觉所做的一些很酷的研究。CNN 的连接模式来自他们对视觉皮层组织的研究。在哺乳动物的眼睛中,单个神经元只在感受野对视觉刺激做出反应,这是一个受限制的区域。不同区域的感受野部分重叠,从而覆盖整个视野。这就是 CNN 的工作方式!

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

Image by NatWhitePhotography on Pixabay

CNN 有输入层、输出层和隐藏层。隐藏层通常由卷积层、ReLU 层、池层和全连接层组成。

  • 卷积层对输入应用卷积运算。这将信息传递到下一层。
  • 汇集将神经元簇的输出组合成下一层中的单个神经元。
  • 完全连接的层将一层中的每个神经元连接到下一层中的每个神经元。

在卷积层中,神经元仅接收来自前一层的子区域的输入。在完全连接的层中,每个神经元接收来自前一层的每个元素的输入。

CNN 的工作原理是从图像中提取特征。这消除了手动特征提取的需要。特征没有经过训练!它们是在网络对一组图像进行训练时学习的。这使得深度学习模型对于计算机视觉任务来说极其准确。CNN 通过几十或几百个隐藏层学习特征检测。每一层都增加了所学特征的复杂性。

GIF via GIPHY

美国有线电视新闻网

  • 从输入图像开始
  • 对其应用许多不同的过滤器以创建特征地图
  • 应用 ReLU 函数来增加非线性
  • 将池化图层应用于每个要素地图
  • 将合并的图像展平为一个长矢量。
  • 将向量输入到完全连接的人工神经网络中。
  • 通过网络处理要素。最后的全连接层提供了我们所追求的类的“投票”。
  • 通过前向传播和后向传播训练很多很多个时代。这一过程一直重复,直到我们拥有一个定义明确的神经网络,该网络具有经过训练的权重和特征检测器。

这意味着什么呢?

在这个过程的最开始,输入图像被分解成像素。

GIF via GIPHY

对于黑白图像,这些像素被解释为 2D 阵列(例如,2x2 像素)。每个像素的值都在 0 到 255 之间。(零全黑,255 全白。灰度存在于这些数字之间。)基于这些信息,计算机可以开始处理这些数据。

对于彩色图像,这是一个包含蓝色层、绿色层和红色层的 3D 阵列。每一种颜色都有自己的值,在 0 到 255 之间。可以通过组合三层中每一层的值来找到颜色。

CNN 的基本组成部分是什么?

卷积

卷积步骤的主要目的是从输入图像中提取特征。卷积层总是 CNN 的第一步。

您有一个输入图像、一个特征检测器和一个特征图。你把滤镜一个像素一个像素地应用到输入图像上。你可以通过矩阵相乘来实现。

假设你有一个手电筒和一张气泡纸。你的手电筒照亮了一个 5 个泡泡 x 5 个泡泡的区域。要查看整张纸,你可以用手电筒扫过每个 5x5 的正方形,直到看到所有的气泡。

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

Photo by stux on Pixabay

手电筒发出的光是你的滤镜,你滑过的区域是感受野。滑过感受野的光是你的手电筒回旋。您的过滤器是一组数字(也称为权重或参数)。手电筒发出的光在行进过程中滑动的距离(你是在一次一排气泡上移动滤镜吗?两个?)被称为步幅。例如,步幅为 1 意味着您一次移动一个像素的滤镜。大会是一步两个脚印。

滤镜的深度必须与输入的深度相同,所以如果我们看的是彩色图像,深度应该是 3。这使得该滤波器的尺寸为 5x5x3。在每个位置,滤镜将滤镜中的值与像素中的原始值相乘。这是元素式乘法。将乘法相加,得到一个数。如果您从气泡包装的左上角开始,这个数字代表左上角。现在你移动你的过滤器到下一个位置,重复这个过程。你最终得到的数组叫做特性图或者激活图!您可以使用多个过滤器,这样可以更好地保留空间关系。

GIF via GIPHY

您将指定过滤器数量、过滤器大小、网络架构等参数。CNN 在训练过程中自己学习滤波器的值。您有许多选项可以用来为您的任务制作最佳的图像分类器。您可以选择用零填充输入矩阵(零填充),将过滤器应用于输入图像矩阵的边界元素。这也允许您控制特征地图的大小。加零填充是宽卷积。不加补零是窄卷积

这基本上就是我们检测图像的方式!我们不会查看图像的每一个像素。我们看到像帽子、红色连衣裙、纹身等特征。每时每刻都有如此多的信息进入我们的眼睛,我们不可能处理其中的每一个像素。我们允许我们的模型做同样的事情。

这样的结果就是卷积后的特征图。它比原始输入图像小。这使得处理起来更加容易和快速。我们会失去信息吗?一些,是的。但同时,特征检测器的目的是检测特征,这正是它的作用。

我们创建了许多特征地图来得到我们的第一个卷积层。这允许我们识别程序可以用来学习的许多不同的特征。

可以用不同的值设置特征检测器,以获得不同的结果。例如,可以应用能够锐化和聚焦图像或者模糊图像的过滤器。这将对所有的价值给予同等的重视。您可以进行边缘增强、边缘检测等操作。您可以通过应用不同的特征检测器来创建不同的特征地图。计算机能够确定哪些过滤器最有意义并应用它们。

这里的主要目的是找到图像中的要素,将它们放入要素地图中,并仍然保留像素之间的空间关系。这一点很重要,这样像素才不会变得混乱。

让我们想象一下这个东西!

向我的小朋友问好:

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

Photo by Kirgiz03 on Pixabay

我们要用这个家伙作为我们的输入图像。

我们会让他黑白分明

import cv2
import matplotlib.pyplot as plt
%matplotlib inlineimg_path = 'data/pixabay_Kirgiz03.jpg'# Load color image 
bgr_img = cv2.imread(img_path)# Convert to grayscale
gray_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2GRAY)# Normalize, rescale entries to lie in [0,1]
gray_img = gray_img.astype("float32")/255# Plot image
plt.imshow(gray_img, cmap='gray')
plt.show()

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

让我们定义并可视化我们的过滤器

import numpy as npfilter_vals = np.array([[-1, -1, 1, 1], [-1, -1, 1, 1], [-1, -1, 1, 1], [-1, -1, 1, 1]])print('Filter shape: ', filter_vals.shape)

滤镜形状:(4,4)

# Define four different filters, all of which are linear combinations of the `filter_vals` defined abovefilter_1 = filter_vals
filter_2 = -filter_1
filter_3 = filter_1.T
filter_4 = -filter_3
filters = np.array([filter_1, filter_2, filter_3, filter_4])# Print out the values of filter 1 as an example
print('Filter 1: \n', filter_1)

我们看到:

**Filter 1: 
 [[-1 -1  1  1]
 [-1 -1  1  1]
 [-1 -1  1  1]
 [-1 -1  1  1]]**

这是我们的四个过滤器的可视化

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

现在让我们定义一个卷积层(我现在很喜欢 PyTorch,所以这就是我们在这里使用的。)

import torch
import torch.nn as nn
import torch.nn.functional as F

# Neural network with one convolutional layer with four filters
class Net(nn.Module):

    def __init__(self, weight):
        super(Net, self).__init__()
        # Initializes the weights of the convolutional layer to be the weights of the 4 defined filters
        k_height, k_width = weight.shape[2:]
        # Assumes there are 4 grayscale filters
        self.conv = nn.Conv2d(1, 4, kernel_size=(k_height, k_width), bias=False)
        self.conv.weight = torch.nn.Parameter(weight)def forward(self, x):
        # Calculates the output of a convolutional layer pre- and post-activation
        conv_x = self.conv(x)
        activated_x = F.relu(conv_x)

        # Returns both layers
        return conv_x, activated_x

# Instantiate the model and set the weights
weight = torch.from_numpy(filters).unsqueeze(1).type(torch.FloatTensor)
model = Net(weight)# Print out the layer in the network
print(model)

我们走着瞧

**Net(
  (conv): Conv2d(1, 4, kernel_size=(4, 4), stride=(1, 1), bias=False)
)**

再多加一点代码

def viz_layer(layer, n_filters= 4):
    fig = plt.figure(figsize=(20, 20))

    for i in range(n_filters):
        ax = fig.add_subplot(1, n_filters, i+1, xticks=[], yticks=[])
        # Grab layer outputs
        ax.imshow(np.squeeze(layer[0,i].data.numpy()), cmap='gray')
        ax.set_title('Output %s' % str(i+1))

然后再多一点

# Plot original image
plt.imshow(gray_img, cmap='gray')# Visualize all of the filters
fig = plt.figure(figsize=(12, 6))
fig.subplots_adjust(left=0, right=1.5, bottom=0.8, top=1, hspace=0.05, wspace=0.05)
for i in range(4):
    ax = fig.add_subplot(1, 4, i+1, xticks=[], yticks=[])
    ax.imshow(filters[i], cmap='gray')
    ax.set_title('Filter %s' % str(i+1))# Convert the image into an input tensor
gray_img_tensor = torch.from_numpy(gray_img).unsqueeze(0).unsqueeze(1)# Get the convolutional layer (pre and post activation)
conv_layer, activated_layer = model(gray_img_tensor)# Visualize the output of a convolutional layer
viz_layer(conv_layer)

我们可以在应用 ReLu 激活函数之前可视化卷积层的输出!

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

现在让我们使用 Sobel 算子作为边缘检测滤波器来创建一个自定义内核。Sobel 滤波器非常常用于边缘检测。它在寻找图像中的强度模式方面做得很好。对图像应用 Sobel 滤波器是一种在 x 或 y 方向上分别对图像的导数进行近似的方法。

我们将把我们的小家伙转换成灰度进行过滤

gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)plt.imshow(gray, cmap='gray')

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

开始了。

# 3x3 array for edge detection
sobel_y = np.array([[ -1, -2, -1], 
                   [ 0, 0, 0], 
                   [ 1, 2, 1]])sobel_x = np.array([[ -1, 0, 1], 
                   [ 0, 0, 0], 
                   [ 1, 2, 1]])

filtered_image = cv2.filter2D(gray, -1, sobel_y)plt.imshow(filtered_image, cmap='gray')

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

想看看数学吗?看看 卷积神经网络简介 作者吴建新

ReLU 层

ReLU(校正线性单位)层是我们卷积层的另一个步骤。您正在将一个激活 函数应用到您的特征地图上,以增加网络中的非线性。这是因为图像本身是高度非线性的!它通过将负值设置为零来从激活图中移除负值。

卷积是一种线性运算,包括元素间的矩阵乘法和加法。我们希望 CNN 了解的真实世界数据将是非线性的。我们可以用 ReLU 这样的操作来说明这一点。您可以使用其他操作,如 tanhsigmoid 。然而,ReLU 是一个受欢迎的选择,因为它可以更快地训练网络,而不会对泛化精度产生任何重大影响。

查看 C.-C. Jay Kuo 用数学模型理解卷积神经网络

想深入挖掘?试试何等 深究整流器:在 ImageNet 分类上超越人类水平的表现

如果你需要更多关于 激活函数的基础知识,你可以在这里找到

这是我们的小伙伴在 ReLU 激活功能将所有负像素值变成黑色后的样子

viz_layer(activated_layer)

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

联营

您最不希望看到的是网络在确切位置的确切阴影中查找某个特定要素。那对一个好的 CNN 来说没用!您想要翻转、旋转、挤压等的图像。您想要同一事物的大量照片,以便您的网络可以在所有图像中识别一个对象(比如说,一只豹子)。无论大小或位置如何。无论光线如何,无论斑点数量多少,无论豹子是在熟睡还是在撕咬猎物。你要空间方差!你需要灵活性。这就是联营的意义所在。

池逐渐减小输入表示的大小。这使得检测图像中的物体成为可能,无论它们位于何处。池有助于减少所需参数的数量和所需的计算量。这也有助于控制过度拟合

过度拟合有点像你在没有理解信息的情况下,在考试前记忆超级具体的细节。当你记住细节的时候,你可以在家里用你的抽认卡做得很好。但是,如果给你提供新的信息,你将无法通过真正的测试。

(另一个例子:如果你的训练数据中的所有狗都有斑点和深色眼睛,你的网络将认为,对于要被分类为狗的图像,它必须有斑点和深色眼睛。如果你用同样的训练数据来测试你的数据,它将会对狗进行惊人的正确分类!但是,如果你的输出只有“狗”和“猫”,而你的网络呈现的新图像包含,比如说,一只罗威纳犬和一只哈士奇犬,它很可能会把罗威纳犬和哈士奇犬都归类为猫。可以看出问题了!)

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

Photo by Hybrid on Unsplash

如果没有方差,对于与训练数据不完全匹配的图像,您的网络将毫无用处。永远,永远,永远把你的训练和测试数据分开!如果你用你训练过的数据进行测试,你的网络会记住这些信息!当引入任何新数据时,它会做得很糟糕。

过度合身并不酷。

因此,对于这一步,你采取特征地图,应用池层,结果是池特征地图

最常见的池例子是最大池。在 max pooling 中,输入图像被划分为一组不重叠的区域。每个区域的输出是每个区域的最大值。这使得尺寸更小,参数更少。

最大池化就是获取图像中每个点的最大值。这去掉了 75%的非特征信息。通过取像素的最大值,你就考虑到了失真。如果要素向左或向右旋转一点点,合并后的要素将保持不变。你在减少尺寸和参数。这很好,因为这意味着模型不会过度适应这些信息。

你可以使用平均池总和池,但它们并不是常见的选择。在实践中,最大池往往比两者都表现得更好。在 max pooling 中,您将获得最大的像素值。在平均池中,取图像中该点所有像素值的平均值。(实际上,现在有一种趋势是使用更小的过滤器或完全放弃池层。这是对代表人数大幅减少的回应。)

想多了解一下为什么你会选择最大池,为什么你会喜欢两个像素的步长?看看张秀坤·舍雷尔等人。a1, 用于对象识别的卷积架构中的池操作评估

如果你去这里你可以看到一个非常有趣的卷积层的 2D 可视化。在屏幕左侧的框中画一个数字,然后真正地浏览输出。您可以看到卷积和汇集层以及猜测。尝试将鼠标悬停在单个像素上,以便可以看到应用滤镜的位置。

现在我们有了一个输入图像、一个应用的卷积层和一个应用的池层。

让我们来看一看池层的输出!

我们在这里:

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

汇集图层将上图中的要素地图作为输入,并减少这些地图的维度。它通过构建一个新的、更小的图像来实现这一点,该图像仅包含给定内核区域中的最大(最亮)值。

看到图像是如何改变大小的了吗?

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

很酷,对吧?

变平

这是一个非常简单的步骤。您将汇集的要素地图展平为一列连续的数字(一个长向量)。这使得该信息成为人工神经网络的输入层,用于进一步处理。

全连接层

在这一步,我们将一个人工神经网络添加到我们的卷积神经网络中。(不确定人工神经网络?你可以在这里了解他们!)

人工神经网络的主要目的是将我们的特征组合成更多的属性。这些将更准确地预测类别。这结合了可以更好地预测类的特征和属性。

在这一步,计算误差,然后反向传播。权重和特征检测器被调整以帮助优化模型的性能。然后这个过程一次又一次的发生。我们的网络就是这样训练数据的!

当有一个以上的神经元时,输出神经元是如何工作的?

首先,我们必须了解什么样的权重应用于连接输出的突触。我们想知道哪些先前的神经元对输出是重要的。

例如,如果您有两个输出类,一个是猫的,一个是狗的,则读取“0”的神经元绝对不能确定该特征属于猫。一个读到“1”的神经元绝对确定这个特征属于一只猫。在最终完全连接的层中,神经元将读取 0 和 1 之间的值。这意味着不同层次的确定性。值 0.9 表示 90%的确定性。

当一个特征被识别出来时,猫的神经元就知道这个图像是一只猫。他们说数学上相当于,“这些是我的神经元!我应该被触发了!”如果这种情况发生多次,网络就会知道当某些特征被激活时,这个图像就是一只猫。

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

Photo by Linnea Sandbakk on Unsplash

通过大量的迭代,猫神经元知道当某些特征被激活时,图像就是一只猫。例如,狗的神经元知道当某些其他特征被激发时,这个图像就是一只狗。例如,狗神经元再次了解到,“大湿鼻子”神经元和“软耳朵”神经元对狗神经元有很大的贡献。它赋予“大湿鼻子”神经元和“软耳朵”神经元更大的权重。狗神经元学会或多或少忽略“胡须”神经元和“猫虹膜”神经元。猫神经元学会给予像“胡须”和“猫虹膜”这样的神经元更大的权重。

(好吧,实际上并没有“大湿鼻子”或“胡须”神经元。但是检测到的特征确实具有特定类别的区别特征。)

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

Photo by Noémi Macavei-Katócz on Unsplash

一旦训练好网络,你就可以传入一幅图像,神经网络将能够非常确定地确定该图像的图像分类概率。

全连接层是传统的多层感知器。它在输出层使用一个分类器。分类器通常是 softmax 激活函数。完全连接意味着前一层中的每个神经元都连接到下一层中的每个神经元。这一层的目的是什么?使用来自前一层的输出的特征来基于训练数据对输入图像进行分类。

一旦你的网络建立并运行,你可以看到,例如,你有 95%的可能性你的图像是一只狗,5%的可能性你的图像是一只猫。

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

Photo by Alexas_Fotos on Pixabay

为什么这些数字加起来都是 1.0?(0.95 + 0.05)

没有任何东西表明这两个输出是相互联系的。是什么让他们联系在一起?本质上,它们不会,但是当我们引入 softmax 函数时,它们会。这使值介于 0 和 1 之间,并使它们相加为 1 (100%)。(你可以在维基百科上阅读所有相关内容。)softmax 函数获取分数向量,并将其压缩为 0 到 1 之间的值的向量,这些值的总和为 1。

应用 softmax 函数后,可以应用损失函数。交叉熵通常与 softmax 密切相关。我们希望最小化损失函数,以便最大化网络性能。

在反向传播的开始,你的输出值会很小。这就是为什么你可能会选择交叉熵损失。梯度会非常低,神经网络很难开始向正确的方向调整。使用交叉熵有助于网络评估甚至一个微小的错误,并更快地达到最佳状态。

想要更多吗?检查

现在怎么办?

在这一点上,一切都是通过许多许多时代的向前和向后传播来训练的。我们最终得到了一个定义非常明确的神经网络,所有的权重和特征都经过了训练。现在我们有了可以识别和分类图像的东西!(不确定正向传播和反向传播?查看这里的绝对基础知识!)

刚刚发生了什么?

我们从输入图像开始,应用多种不同的特征来创建特征图。我们应用了 ReLU 来增加非线性,并对每个特征地图应用了汇集层。(我们这样做是为了确保我们的图像中有空间差异,减少图像的大小,避免模型过度适应数据,同时仍然保留我们想要的特征。)我们将所有汇集的图像展平成一个长向量。我们将向量输入到完全连接的人工神经网络中。这是通过网络处理所有要素的地方。这给了我们最终的全连接层,它提供了我们所追求的类的“投票”。所有这些都是通过前向传播和反向传播来训练的,直到我们最终得到了一个定义良好的神经网络,其中训练了权重和特征检测器。

现在我们可以识别和分类图像了!

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

Photo by Lucas Sankey on Unsplash

您正在朝着能够做到这一点的方向前进:

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

(你想那样做吗?这里有一个清晰完整的蓝图,可以用 PyTorch 创建一个极其精确的图像分类器!你可以创建一个图像分类器,它可以非常确定地告诉你你正在看的是哪种花!)

想了解更多?结账

感谢关注 新手、新手和新手深度学习 系列的第 3 部分!

你可以在这里找到第一部分: 深度学习简介

[## 深度学习简介

新手、新手和新手的神经网络。

towardsdatascience.com](/intro-to-deep-learning-c025efd92535)

和这里的第二部分: 人工网络完全初学者指南

[## 深度学习完全初学者指南:人工神经网络

深度学习入门!在 15 分钟内攻克人工神经网络的基础知识

towardsdatascience.com](/simply-deep-learning-an-effortless-introduction-45591a1c4abb)

如果你对这些信息做了什么了不起的事情,请在下面的回复中告诉我,或者发推特 @annebonnerdata

数据科学的 WW(什么和什么时候)

原文:https://towardsdatascience.com/ww-what-and-when-of-data-science-dc4cc0bfd7b?source=collection_archive---------23-----------------------

学员系列

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

Source: themorgan.org

在深入研究数据科学之前,首先我想让你问自己一个问题:你真的对数据科学感兴趣吗?还是仅仅因为它是当前的趋势,有更多的机会(你可能在网上或通过某人听说过)或一个人可能会认为是因为花哨的工资!

在知道它是什么之前,我希望你花一些时间自己,并了解为什么你认为你需要了解数据科学。为什么要让自己意识到这样一个领域?你真的想在这个领域做出一番事业吗?或者只是你的一个朋友在这个领域,说他们赚的是花里胡哨的钱;所以现在你也对它感兴趣了!把你的头弄直。明白。让自己明白。试着记下原因。

现在,让我们考虑你实际上对这个领域感兴趣(如果你真的对这个领域感兴趣,对你有好处!).如果你不感兴趣,请继续阅读,不要担心,我会让你觉得有趣的!

如果你想在这个领域有所作为,那么你应该既感兴趣又有点担心(有点担心是好的;它有助于你能够知道如何让你确信某些事情。这是因为这是一个非常广阔的领域,它包含了太多的东西。它包括数学(更具体地说是统计学)。是的,你没看错,它包括数学;他们中的大多数人要么害怕,要么无缘无故地讨厌这个科目,这可能是因为他们表现不好或者不感兴趣。

在进入数据科学领域之前,在走这条路之前,你需要让自己意识到它是什么,它由什么组成,它对你有什么期望等等。这些问题应该引起重视。

  • 你必须知道你在所有这些方面的位置。这将有助于你坚持自己的立场,有助于你了解自己缺乏什么,需要改进什么。
  • 你必须知道进入这个领域的基本要求是什么。
  • 你必须意识到事情在某个时候会变得多么困难,但是既然你对这个领域感兴趣,你就不必担心。人们倾向于努力做自己感兴趣的事情。你也会的!一旦你掌握了这些东西,你前进的道路就会变得更加容易。
  • 你必须了解这些领域的职位名称/机会。你必须知道这些头衔意味着什么,这些工作需要什么样的技术,他们的角色是什么。
  • 看看哪个角色最适合你,哪个角色更适合你。
  • 不要只想着钱,因为他们说权力越大,责任越大。在这里,你也可以运用同样的思想,因为高薪职位意味着更多的工作/任务/责任。

你现在担心吗?如果没有,那好吧,那太好了,你是一个坚强的人。如果你是,还是不要担心;因为在本文的剩余部分,我将解释一些你需要了解的关于数据科学的基本知识。我们会明白它是什么,它是什么时候产生的,为什么它会存在?我们将一起探索这一切。

现在,我已经让你做好了心理准备,让我们开始研究数据科学。

数据科学到底是什么?

你一定想,“*哦,上帝已经告诉我了”。*从过去的几个句子中,你可能会多次遇到“数据科学”这个词。最后,现在是时候揭示它是什么了。

首先,我们来看看数据科学的定义。

根据某些网站:

  • 数据科学是一个多学科领域,使用科学方法、流程、算法和系统从结构化和非结构化数据中提取知识和见解——维基百科
  • 获取数据的能力——能够理解数据、处理数据、从中提取价值、可视化数据和交流数据——将是未来几十年非常重要的技能。” - 哈尔·瓦里安,谷歌首席经济学家,加州大学伯克利分校信息科学、商业和经济学教授
  • "数据科学基于大量复杂数据或 大数据 提供有意义的信息。数据科学,或数据驱动的科学,结合了统计和计算的不同领域的工作,以解释决策目的的数据。 " - Investopedia

因此,根据某些网站或某些人,这些是数据科学的某些逐字逐句的含义。

因此,如果现在让你定义数据科学,你会如何定义?哇,我知道您可能刚刚阅读了数据科学的各种定义,现在我要求您立即自己定义它。如果你要定义它,那么它是伟大的!你正在取得进步。如果你仍然不明白,不要担心;我们将一起理解其中的含义。

让我们以维基百科的第一个定义为例。根据定义*‘数据科学是一个多学科领域’***。**那么你所说的多学科是什么意思?别担心,我知道这个词很长。但是相信我,意思很简单。它意味着多个学科或专业或主题。它仅仅意味着它由来自各个领域的主题组成。

通过定义,它指出*“它使用科学方法、流程、算法和系统从结构化和非结构化数据中提取知识和见解”。*利用:科学方法,这意味着它是一种研究方法,在这种方法中,确定问题,收集所需/必要的数据,从数据中得出假设,并对假设进行检验;过程意味着以一定的顺序执行一定的步骤或动作,以达到特定的目的;算法意味着机器(主要是计算机)需要遵循的一组规则或一组指令或操作;系统基本上可以定义为作为机制的一部分一起工作的某些事物或一组事物;我们所知道的知识是通过经验获得的某些事实或信息或技能;洞察力是指对某事物获得准确或深刻理解的能力。

现在我们知道了某些术语的含义,并且在应用了维基百科规定的数据科学的定义后,我们可以说,这些方法、过程、算法系统用于数据科学中,以从结构化和非结构化数据中提取知识或信息并获得理解,这意味着数据类型是关系型或非关系型的,其中关系型是表格数据,数据以行和列的形式存储, 例如,关于学生的数据、非关系数据或非结构化数据是不以特定表格格式存储的数据,这些数据可以包括任何类型的数据,从文本数据到电影、图像、音频等。

所以现在我们已经弄清楚了数据科学的第一个定义。现在你的大脑面临一个挑战!试着自己找出其余的定义。没有那么难,如果你理解了第一个,我相信你也会理解剩下的一个!这对你的大脑将是一次健康的锻炼!

数据科学时间轴:

既然我们知道了数据科学实际上是什么,现在是时候让我们知道它是什么时候出现的了。

1962 年:

  • 约翰·图基写了一篇关于统计世界的转变的文章,他说,“……当我看到数理统计的发展时,我有理由感到惊奇和怀疑…我开始觉得我的主要兴趣是在数据分析方面……”。Tukey 实际上指的是统计和计算机的融合,当时统计结果可以在几个小时内呈现,而不是手工完成的几天或几周。

1974 年:

  • 彼得·诺尔是《计算机方法简明概览》一书的作者,他在书中反复使用了数据科学这个术语。诺尔提出了自己对这一概念的定义:
  • 一旦数据被建立,处理数据的科学,而数据与它们所代表的关系则委托给其他领域和科学

1977 年:

  • IASC(国际统计计算协会)成立。
  • 其第一阶段的任务说明是,“IASC 的任务是将传统的统计方法、现代计算机技术和知识结合起来”。
  • 图基写了第二篇论文,题目是探索性数据分析,,论述了使用数据选择“哪些”假设需要测试的重要性,并证实了数据分析和探索性数据分析应该携手合作。

1989:

  • ACM SIGKDD 知识发现和数据挖掘会议组织了第一次研讨会

1992 年:

  • 数据科学的第一个现代定义是在蒙彼利埃第二大学(法国)组织的日本-法国统计研讨会上提出的。

1994:

  • 《商业周刊》曾刊登过数据库营销的封面故事,揭露了不祥的新闻公司已经开始收集大量个人信息,并计划开始奇怪的新营销活动。

1996 年

  • IFCS(国际船级社联合会)成员在神户举行两年一次的会议。
  • 在这里,数据科学一词第一次被纳入会议的标题——“数据科学、分类和相关方法”。
  • 后来,Chiko Hayashi 在一次圆桌讨论会上引入了这个术语。

1997 年:

  • 吴振伟院士做了题为“统计学=数据科学?”在密歇根大学。
  • 在讲座中,他将统计工作描述为数据收集、数据建模和分析以及决策三部曲。
  • 他后来主张把统计学命名为数据科学,把统计学家命名为数据科学家。
  • 后来,他做了“统计学=数据科学?”,作为他 1998 年{.C. Mahalanobis,纪念演讲的第一篇,作为对 Prasanta Chandra Mahalanobis(印度科学家和统计学家,印度统计研究所的创始人)的敬意。

1999 年:

  • Jacob Zahavi 指出,在挖掘数据以获取知识时,需要新的工具来处理业务中存在的大量信息。他写道:
  • “可扩展性是数据挖掘中的一个大问题……传统的统计方法适用于小数据集。然而,今天的数据库可能涉及数百万行和数十列数据…另一个技术挑战是开发能够更好地分析数据、检测非线性关系和元素之间的交互的模型…可能必须开发特殊的数据挖掘工具来处理网站决策。”

2001 年:

  • William S. Cleveland 将数据科学作为一门独立的学科引入。
  • 他制定了培训数据科学家以满足未来需求的计划。他还介绍了一项名为数据科学的行动计划:一项扩大统计领域技术领域的行动计划
  • 软件即服务(SaaS)应运而生。

2002:

  • ICS(国际科学理事会)、CODATA(科学技术数据委员会)创办了数据科学杂志——该杂志关注的问题包括数据系统的描述、应用、法律问题等。

2003:

  • 哥伦比亚大学开始出版《数据科学杂志》,这是所有数据工作者表达观点、交流思想等的平台。

2005 年:

  • 国家科学委员会出版了长期数字数据收集:21 世纪的研究和教育。
  • 它将数据科学家定义为:“信息和计算机科学家、数据库和软件程序员、学科专家、管理员和专家注释员、图书馆员、档案员和其他人;他们对数字数据收集的成功管理至关重要。

2006 年:

  • Hadoop 0.1.0,这是一个开源的非关系数据库;被释放了。

2008 年:

  • 数据科学家曾风靡一时,后来也成为语言的一部分。

2009 年

  • 约翰·奥斯卡森重新引入了 NoSQL 这个术语。

2011 年:

  • 数据科学家的工作列表增加了 15,000%。这也导致了专门针对数据科学和大数据的研讨会、讲习班、会议等的增加。

2012 年:

  • 在《哈佛商业评论》的文章— 数据科学家:21 世纪最性感的工作中, D.J. Patil 声称在 2008 年和 Jeff Hammerbacher 一起创造了这个术语来分别定义他们在 LinkedIn 和脸书的工作。

2013:

  • IEEE 数据科学和高级分析工作组成立。
  • 第一届 ECDA(欧洲数据分析会议)在卢森堡召开,成立了 EuADS(欧洲数据科学协会)。
  • IBM 向世界展示了 90%的数据是在过去两年中创建的。

2014:

  • 第一届国际会议:组织了 IEEE 数据科学和高级分析国际会议
  • 大会发起了学生付费训练营。
  • 数据孵化器推出了竞争性的免费数据科学奖学金。
  • 美国统计协会关于统计学习和数据挖掘的版块将其期刊更名为统计分析和数据挖掘:美国统计协会数据科学期刊,并于 2016 年将其版块名称变更为统计学习和数据科学。

2015:

  • 斯普林格推出了国际数据科学和分析期刊来发表关于数据科学和大数据分析的原创作品。
  • 随着深度学习算法/方法的使用,谷歌的语音识别、谷歌语音等的性能跃升至 49%。

这是数据科学的历史。每个人都应该意识到事物的起源,因为这有助于我们理解事物是如何产生和为什么产生的,这进一步有助于我们理解如何使用它。

快进到今天,我们可以看到有这么多的工作机会,但更少的人有资格做同样的事情。对数据科学家的需求非常大。据说缺乏具有数据科学技能的人,但对他们的需求正在迅速增长。

希望你喜欢。😃

参考资料:

维基百科,福布斯,数据大学

XᵀX、协方差、相关和余弦矩阵

原文:https://towardsdatascience.com/xᵀx-covariance-correlation-and-cosine-matrices-d2230997fb7?source=collection_archive---------19-----------------------

几种常见关联矩阵的计算方法

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

Below, we’ll unpack the calculations underlying plots like these

有没有遇到过这样的情况,您需要在没有函数帮助的情况下为动态数据得出成对的协方差、相关性或余弦矩阵?大概不会。

尽管如此,还是有必要看看这些矩阵是如何计算的,因为它们各自的计算有一些明显的共性。这一切的中心是 XᵀX 矩阵。在这里,您可以将 X 视为您收集的一些数据,其中每一列是不同的度量,每一行是不同的主题。

  • 取 X 的转置并将其乘以自身,得到平方和叉积矩阵(ssCP),其中 SS 落在对角线上,叉积落在非对角线上。
  • 将 X 居中,将其转置与其自身相乘,然后除以 n-1(其中 n = X 中的行数)得到方差-协方差矩阵,其中方差在对角线上,协方差在非对角线上。
  • 将 X 标准化,将其转置乘以自身,然后除以 n-1(其中 n = X 中的行数)得到变量对之间的皮尔逊相关。
  • 单位缩放 X 并将其转置与其自身相乘,导致变量对之间的余弦相似性

下面,我们将通过创建一个基于用户输入输出上述矩阵之一的函数来说明刚才查看的内容。

现在,我们可以通过创建一些数据并计算前面提到的关联来测试它。

平方和叉积

方差-协方差

皮尔逊相关

余弦相似度

我们将加载库“philentropy”来检查我们的工作,因为它包含许多有用的距离函数。请注意,我们正在转置
我们的数据,因为该函数的默认行为是对所有进行成对
比较。

总之,我们已经展示了 XᵀX 可以被操纵来导出许多我们日常使用的常见关联矩阵。希望你下次运行相关性或检查数据集中变量之间的余弦距离时,记住这一点!

X-AI,黑盒和水晶球

原文:https://towardsdatascience.com/x-ai-black-boxes-and-crystal-balls-fd27a00752ec?source=collection_archive---------24-----------------------

内部人工智能

可信人工智能之路

在我们通往可信人工智能的道路上,我在我的上一篇博客中讨论了偏见的问题,它如何从人类传播到机器,它如何被人工智能应用放大,在现实世界中对个人和企业的影响,以及主动解决这个问题的重要性。今天,我将讨论所谓的“黑箱”模型的可解释性和透明性问题。

在可解释性和准确性之间做出选择?

要信任,你必须理解。人与人之间的关系就是如此。当涉及到采用增强人类能力的系统来产生洞察力和做出决策时也是如此。这是人类和机器之间的合作关系。像所有的伙伴关系一样,信任是关键。

也许毫不奇怪,人工智能和机器学习(ML)算法的可解释性已经成为该领域中讨论和研究最多的主题之一。

一个算法是可解释的意味着什么?这意味着该系统可以传达关于其内部工作方式、其学习的模式和其提供的结果的有用信息。可解释性是可解释性的一个更柔和、更轻松的版本。如果我们可以看到正在发生的事情,如果我们可以根据输入变量合理地预测结果,即使我们不一定知道系统是如何做出决定的,那么系统就是可解释的。

一些模型类型,如决策树和线性回归,非常简单、透明且易于理解。我们知道改变输入将如何影响预测的结果,我们可以证明每个预测。

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

Photo by Alina Grubnyak on Unsplash

不幸的是,赋予深度神经网络、随机森林或梯度推进机器等“黑盒”模型非凡预测能力的复杂性也让它们非常难以理解(和信任)。任何人工智能技术的运作本质上都是不透明的,即使对计算机科学家来说也是如此。从本质上来说,深度学习是一个特别暗的黑匣子。

用于训练这些模型的大量数据使问题变得更糟,很难找出哪些数据点对结果的影响比其他数据点更大。ML 算法随着时间的推移而发展的事实也使事情变得困难,因为算法不断地从新数据中学习。

归根结底,这是准确性和可解释性之间的权衡。问题是我们准备在这两个问题上做出多大的妥协。不幸的是,我们还没有达到既高度准确又完全透明的模型,尽管我们正在朝着这个方向前进。

总是很重要吗?

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

The number 42 is, in The Hitchhiker’s Guide to the Galaxy by Douglas Adams, the “Answer to the Ultimate Question of Life, the Universe, and Everything”, but what good is knowing the answer when it’s unclear why it is the answer?? — Photo by Mark König on Unsplash

对黑箱模型的怀疑和不信任越来越多。因此,工程师和数据科学家正在努力解决可解释性问题。监管机构也在调查此事。2018 年,《欧盟一般数据保护条例》( GDPR)引入了个人的一些基本权利,即被告知自动决策,反对这些决策的输出,以及获得有关所涉逻辑的一些有意义的信息。然而,它没有引入可解释的权利。最近,欧盟任命了一个专家小组来解决这个复杂的问题。这一努力已经导致了可信人工智能的高级指南的发布。

可解释性肯定是最重要的,但是它真的总是那么重要吗?

在这篇精彩的文章中,Elizabeth A. Holm 以一种更平衡的观点为黑盒模型辩护,至少在三种情况下:

  1. 当错误答案的成本相对于正确答案的价值较低时(例如,针对目标广告)
  2. 当它产生最佳结果时(从提供医疗诊断帮助到驾驶自动驾驶汽车)
  3. 当它激发和引导人类探究时(例如通过带来以前没有预料到的洞察力和提出新的问题)

人工智能采用的必要条件

然而,在大多数其他情况下,可解释性是确保采用人工智能应用的必要条件。

如果你不知道它是如何工作的,你怎么能相信它呢?

实现预测的高度准确性不足以证明最大似然算法缺乏可解释性。

让我们以医疗保健行业为例。

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

Photo by National Cancer Institute on Unsplash

人工智能在医疗保健等领域的潜在好处是巨大的。例如,计算机视觉可以用来帮助医生从扫描中识别肿瘤,提高诊断的准确性。类似的技术可以用来在任何症状出现之前预测疾病。然而,如果这些系统不能向医生和患者提供某种程度的解释,它们注定会失败。毕竟,谁会在意仅仅依靠计算机预测就开始具有挑战性副作用的侵入性手术或治疗呢?

2015 年,纽约西奈山医院(Mount Sinai Hospital)的一个研究小组将深度学习技术应用于该医院拥有 70 万份患者记录的庞大数据库。数百个变量被用来训练一个名为“深度病人”的系统。事实证明,它在预测癌症或精神疾病等疾病方面非常有效。在没有任何专家指导的情况下,Deep Patient 发现了隐藏在医院数据中的模式,这些模式似乎表明人们何时会出现这些情况。挑战在于这个工具不能提供任何关于它如何得出结论的线索。如果没有基本原理,系统做出的预测根本就不可用。

许多人和组织都在忙于人工智能和人工智能的实验,推动这项技术能够实现的边界。然而,我预测只有能够提供某种程度的可解释性和透明性的系统才能生存。

打开黑盒

幸运的是,有办法让黑盒更加透明,算法技术可以提高 ML 的可解释性。

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

Photo by Justin Clark on Unsplash

最基本的方法是使用代理方法。通常难以解释的 ML 模型被用作更易解释的模型类型的基准。

更复杂的方法包括应用建模后诊断技术,例如:

  • 变量重要性 (VI),了解顶级输入变量。
  • 部分相关图 (PDP),用于测量特性对 ML 模型预测结果的边际影响。
  • 个体条件期望 (ICE),类似于 PDP,但针对个体数据实例,并在本地级别提供更多粒度。
  • 局部可解释的模型不可知解释 (LIME),为特定预测提供解释。这是一种与模型无关的技术,用于通过改变输入并观察预测如何变化来理解模型。
  • 沙普利重视 (SHAP),这是一种在博弈论中使用的技术,用于确定合作游戏中的每个玩家对其成功做出了多大贡献。在建模过程中,每个 SHAP 值测量模型中每个要素对预测的负面或正面贡献。

我突然发现,为了解决复杂性问题,我们最终增加了另一层复杂性。然而,这似乎是让黑匣子变得更加透明和可信所需的代价,因此也更有用。也许主要的挑战不是技术,而是数据科学和工程团队的文化和实践。一切都取决于他们是否愿意和准备好将可解释性需求融入到人工智能应用的设计、开发和部署中。

透明,不可解释

在人工智能中创造透明和信任超越了黑盒模型的解释能力。这只是从数据、发现、部署到决策的端到端分析生命周期的一个方面。

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

Traceability & Lineage across the entire analytics life-cycle

过程和工具需要能够建立数据、模型和决策的可追溯性和谱系。这是建立对 AI 信任的先决条件。这通常也是 It 合规性或法规要求。

致力于可信人工智能的组织必须能够回答许多问题。

关于数据

  • 我们用什么数据来训练模型?
  • 它是从哪里来的?
  • 我们能相信它吗?
  • 我们有法律依据来处理这些数据吗(尤其是当它包含个人或敏感数据时)?
  • 数据有多好?质量够好吗?
  • 它对人工智能应用程序的目的有代表性吗?它能包含多少偏见?我们是否发现了任何歧视性变量或可能与歧视性变量相关联的变量(例如,邮编有时可能与种族相关联)?

关于分析模型

  • 模型是否有完整的文档和版本控制?
  • 在这些模型的设计和开发过程中做了哪些假设?
  • 我们有受控的环境和自动化的过程来部署和测试模型吗?
  • 模型在整个分析生命周期中具有完全的可追溯性吗?
  • 我们是否有一个正式的流程来度量模型的准确性和性能?

关于人工智能驱动的决策

  • 使用模型的输出做出了什么决定?
  • 什么数据被用来做决定?我们能相信这些数据吗?
  • 这些决策对业务成果和客户有什么影响?
  • 我们有从使用点(在现实世界中做出决策的地方)到数据科学和工程团队的反馈回路吗?

构建可信的人工智能应用远远超出了模型的可解释性。它要求我们在所使用的技术、组织和业务流程中遵循透明原则。这必须是一项深思熟虑、积极主动的努力,以确保数据驱动的创新伴随着有效的商业成果和人工智能技术的道德使用。

更多信息,请阅读我关于这个主题的另外两篇博客:

播客的 x 射线

原文:https://towardsdatascience.com/x-ray-for-podcasts-65289a36d9e4?source=collection_archive---------21-----------------------

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

Photo by Priscilla Du Preez on Unsplash

如何在没有标签的情况下识别不同的扬声器

亚马逊为 Kindle 和视频提供了一个工具,它称之为“X 射线”,让你获得关于手边场景的额外信息。这些信息包括出现的角色,并有助于在一本书的各个部分之间导航,或者深入到一个模糊熟悉的演员的电影记录中。

人们可能会想象,生产这样一种服务的需求需要某种形式的标记(要么完全用手工,要么用分类器)。然而,如果我们可以完全不用任何标签劳动就能推断出分裂,这不是很酷吗?有了这个,我们就可以计算出角色抢尽风头的程度、时间和持续时间,以及不断变化的对话动态。

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

X-Ray for Video on Amazon Prime. Pretty pretty good

我选择看音频——比视频简单,但也是类似视频任务的一个组成部分。为了测试一个简单的基本情况,我选择了一个包含两个人之间缓慢交替对话的播客,并在# 123-识别&诚实中看到了山姆·哈里斯和以斯拉·克莱恩的聊天——两个不同的男性声音,我们的耳朵可以毫不费力地分辨出来。最终产品应该是这样的:

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

The final audio X-Ray

1。创建“块”来标记

scipy 读入音频是一件轻而易举的事——单声道音频只是一个按时间顺序排列的 1D 数组。我们现在考虑改变用于存储我们将标记的数据“块”的窗口大小的权衡。这里的采样频率 Fs 是标准的 44.1 kHz,这意味着我们的数组大小为 44,100 * N,块时间 N 秒。窗口越小,时间位置就越精确,并且语音相互干扰的可能性就越小。

但是更长的时间窗也有助于识别声音——而不仅仅是尖锐的元音。我们可能会怀疑这涉及到在足够长的时间内观察某种平均音色。基于这次讨论中冗长的发言时间,五秒钟最终给出了良好的结果(如果有更多的中断,这可能是太大了)。

在频率分辨率上也有更基本的妥协(认为更短的时间窗给出更宽的谱峰)。但是这种现象只有在我们为整个组块提取频谱时才是重要的。如果我们分析共同告知组块标签的子组块,我们可以避开这一点(这正是我所做的)。

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

Chunking audio has the same effect as applying a rectangular window — it changes the green peak to the blue peaks. The frequency resolution in a discrete Fourier transform is proportional to Fs/N. Source http://saadahmad.ca/fft-spectral-leakage-and-windowing/

傅立叶变换是连接“倒易坐标”的数学。它的缩放特性抓住了我们在许多物理现象中观察到的折衷,例如在频谱分析中(频率分辨率与时间精度);夫琅和费衍射(狭缝间距越小,衍射图样越宽);量子力学中的不确定性(我们确定的位置越精确,动量的不确定性就越大)。

2。音频功能

信号的时间成分并不能揭示声音的本质特征。声波只是空气中的压力扰动,这些扰动的周期性确实揭示了频域中的某种特征。每个块的快速傅立叶变换( FFT )完成了这个任务,并产生了下面描述的频谱。

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

Frequency spectra for Ezra Klein (left) at 30:00–30:05 and Sam Harris (right) at 16:40–16:45. We actually only need the positive terms since for purely real input the output coefficients are “Hermitian-symmetric” i.e. every complex conjugate appears and these correspond to redundant negative-frequencies

这些频谱显然是非常密集和高维的,因此我们可以使用男性音域的带宽来进行粗略的截止。

fs/N represents the unit element change in frequency as we move between elements in the FFT spectrum

这降低了频谱的维数,但回想一下,每个频率分量实际上有两个值,一个实部和一个虚部。当我们观察光谱时,我们看到的是两部分的数量级。然而,傅立叶变换中的相位(两部分的比率)承载了图像和音频的大部分信号。

我们可以通过交叉 Ezra 和 Sam 剪辑之间的幅度和相位来测试这一点,下面是一些(未标准化的)突变剪辑。

Doing naughty things with audio

Original and mutant clips of crossed real/imaginary parts and magnitudes/phases between two chunks

此时,我们可以将幅度和相位的结构传递给一个降维算法(见第 4 节)来可视化输出。这是我最初做的产生两个非常模糊的组,它也不是很快。

librosa 库有多个函数用于从频谱中提取特征(如“质心”、能量分布等)。)或时间序列(如过零率)。我们也可以考虑使用 scipy.signal 来检测频率峰值和峰值宽度。然而,我们选择的特征必须是特定于通过音色以音高不变的方式分离声音的任务。如果问题集中在音高检测上,我们会选择区分音高而不是音色的特征。

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

Examples of audio features as described in Eronen, Antti & Klapuri, Anssi. (2000), Musical instrument recognition using cepstral features and temporal features

换句话说,我们必须确保选择的特征不会精确地“指纹化”数据——我们需要更模糊的东西。我们转向在这方面证明最成功的特性——Mel 频率倒谱系数(MFCCs)。

3。提取梅尔频率倒谱系数

MFCCs 最初被开发用来表示人类声道发出的声音。它利用 Mel 标度,即频率的对数变换,旨在捕捉人类对声音的非线性感知,从而降低对较高频率差异的敏感度。这意味着 MFCC 向量之间的较大距离与较大的感知变化相关,因此可以更稳健地捕捉音色,而不仅仅是音高。比我能更好地深入他们的计算机制,所以我将避免在这里这样做。

自动语音识别任务通常查看 12–20 个倒谱系数,第 0 个系数可以被丢弃,因为它仅传达平均功率的恒定偏移,与整体频谱形状无关。通过选取 15 个系数并去掉 0 阶,我的结果还不错。

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

MFCC spectrogram for Ezra Klein (left) at 30:00–30:05 and Sam Harris (right) at 16:40–16:45. Removing the 0th order coefficient in the top row gives the bottom row which exhibits a smaller range between the coefficients

MFCC 提取涉及“成帧”或“开窗”,在输入上应用滑动窗口,很像短时傅立叶变换,以产生几百组 15 个系数(在每个音频块内),每个连续帧一个。这里的基本原理是,我们希望保留信号在暂时稳定时出现的频率轮廓。如果我们对整个块进行傅立叶变换,这些可能会丢失(正如我最初所做的)。

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

Framing within a single “chunk” of audio being identified. Consecutive frames are often set to overlap partially

当分析音频的小窗口时,一些附加的傅立叶理论在这里是值得考虑的。模拟不连续性,如方波的尖角,需要许多高频项。如果我们在整个音频中创建尖锐的仓,我们可以预期边缘处的不连续性会产生杂散高频成分以及频谱泄漏,因此使用窗口函数使边缘逐渐变细是有意义的。

从光谱计算 MFCCs 的过程具有大大降低输入维数的额外好处。在每一帧中,我们采集大量样本(这里是 2048 个),将这些样本减少到每帧 15 个系数。最终的特征向量是从所有这些帧的系数的平均值建立的。增加方差并不能改善结果。

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

The process for extracting MFCCs. Mel filter banks have a triangular bandwidth response on a Mel-scale and there are typically 40 of them. Source: https://www.ijser.org/paper/Performance-analysis-of-isolated-Bangla-speech-recognition-system-using-Hidden-Markov-Model.html

4。维度缩减

PCA 是事实上的降维主力——一种快速、确定性的线性变换,当沿着最大方差的特征向量分离数据时,它可以保留数据的全局结构。例如,如果我们对 MNIST 数字进行分组,我们将会看到 1 的聚类的质心远离 0,而 4,7,9 的聚类相对较近。然而,我们不能假设在高维空间中邻近的邻居也是紧密的。

一种更现代的方法是 tSNE ,这是一种受益于保留局部结构的随机技术——它将邻居放置在高维空间中彼此靠近,但以一些全局结构为代价。例如,分组 MNIST 数字时,我们看到干净孤立的簇,而 PCA 产生连续的拖尾。

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

UMAP and tSNE on different datasets. The global structure in the MNIST dataset is apparent

UMAP 是一种较新的技术,能够捕捉全局结构(à la PCA)和局部结构(à la tSNE)。它也比最好的多核 tSNE 实现快得多(在 MNIST 上快 13 倍),并且还可以提供定制的距离函数。在这个双音问题中,降维技术的决策可能不太重要,但获得一些实践经验也是很好的。一旦 MFCCs 进行第一阶段的缩减,对 3600 个块 x 15 个系数的处理时间非常快。

5.结果

下图显示的不是两个不同的集群,而是三个!每个点的颜色表示进入播客的时间,边连接连续的块。因此,深蓝色的点表示这段介绍可能是在不同的时间,用不同的设备或在不同的环境下录制的。这里好看的是 Sam 打开的介绍集群(深蓝色)更接近他的对话集群。如果我们移除一些较高的 MFCC 系数(8+)的话,这两个集群实际上可以被包含在内,尽管代价是 Sam 和 Ezra 之间的全局分离。

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

The three distance metrics I saw perform the most reliably for this task of the many UMAP has built in were manhattan, braycurtis and cosine. Silhouette scores above each plot were used for light guidance on clustering performance. A small dark blue cluster appears sometimes given different MFCC parametric configurations

在这里,我们可以对 k=3 个聚类应用 kmeans,通过监听每个聚类中的点,将每个点映射到三个标签中的一个。但是将每个点链接到它的音频块以便点击播放不是很好吗?这将有助于聚类的验证,并回答诸如“一个聚类中最接近另一个聚类的点是否代表具有两种声音的组块”之类的问题。使用破折号和 plotly 以及一些 javascript 和一个第三方库,这被证明是令人惊讶的挑战,但不是不可克服的。

总之…结果!

Dash app with plotly and some javascript. Note the final point selected that is being tugged by both clusters features both Ezra and Sam (braycurtis distance metric used)

不会太寒酸吧?现在我们有了我们的 kmeans 标签,我们可以计算经常引用的辩论统计数据,发言持续时间。

**Sam Harris**    365 chunks
**Ezra Klein**    272 chunks
**Intro**          85 chunks

除了介绍之外,Sam 讲了 57%的时间!毕竟这是他的播客。再加上每个数据块的时间成分,这是一个相当令人满意的最终产品:对话的 X 射线时间线。在 2500s 的 Sam 阶段的交换频率表明这个部分特别有趣/激烈。

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

The final audio X-Ray, again

密码

我整理了我的笔记本,可以在这个要点中找到

参考文献

[## mfcc

信号的 mel 倒谱系数(MFCCs)是一个很小的特征集(通常大约 10-20 ),它…

musicinformationretrieval.com](https://musicinformationretrieval.com/mfcc.html) [## 机器学习的语音处理:滤波器组,梅尔频率倒谱系数(MFCCs)

语音处理在任何语音系统中都起着重要的作用,无论是自动语音识别(ASR)还是语音识别系统

haythamfayek.com](https://haythamfayek.com/2016/04/21/speech-processing-for-machine-learning.html) [## 使用 Wavenet、MFCCs、UMAP、t-SNE 和 PCA 进行比较音频分析

这篇文章是关于一个探索二维音频数据集的项目。我涵盖了一些有趣的算法,如…

medium.com](https://medium.com/@LeonFedden/comparative-audio-analysis-with-wavenet-mfccs-umap-t-sne-and-pca-cb8237bfce2f) [## 在 ARM 系统上计算 MFCCs 语音识别特征

我在 Linagora 的 R&D 部门做 LinTO 项目的实习生。你认识林托吗?如果没有,你应该!林托…

medium.com](https://medium.com/linagoralabs/computing-mfccs-voice-recognition-features-on-arm-systems-dae45f016eb6)

x 射线图像分类:简单的方法

原文:https://towardsdatascience.com/x-ray-image-classification-the-easy-way-69665448604a?source=collection_archive---------20-----------------------

使用谷歌云 AutoML

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

Chest x-ray of a healthy child

“人工智能将比人类历史上任何东西都更能改变世界。不止电。”—人工智能甲骨文和风险投资家李开复博士,2018

随着人工智能(AI)机器学习(ML) 的快速进步,以及我未婚夫自愿分享的人工智能每日文摘,我认为是时候深入了解并亲自看看到底是怎么回事了。我尤其感兴趣的是,如何巧妙地将人工智能融入产品开发对话,以及如何应用它来打造人们喜爱的产品。毕竟,如果你不知道某样东西有什么能力,你怎么能真正用它来创新呢?

虽然我获得了计算机科学学士学位,但我不是人工智能、人工智能或深度学习方面的专家。你也不需要成为一个专家来开始。在这篇文章中,我将分享如何使用神经网络进行图像分类的“简单方法”。注意,图像分类不同于图像检测和图像识别[1]。我将从如何创建数据集开始,然后这将被用作建立机器学习模型的输入。请记住,这不是唯一的方法,而是学习如何用神经网络进行图像分类的起点,特别是如果你是人工智能领域的新手。

你知道吗?深度神经网络最适合进行图像分类。

在我们开始之前,这里有一些我们将使用的例子的背景。下面使用的 x 光图像是儿童的。这个图像分类项目的目的是帮助医疗专业人员快速识别患有肺炎的儿童。

创建数据集

数据集是数据的集合。这是正确的关键部分,因为它是你的模型建立的基础。如果它不在数据中,模型就不会学习它不知道的东西。为了训练机器学习模型,高质量的数据集是必不可少的,因为数据定义了模型的行为和性能。

数据定义了模型

仅仅拥有大量数据并不等于拥有高质量的数据集。归结起来就是拥有“正确的数据”。这意味着数据必须:

  • 反映真实世界的例子
  • 捕捉模型可能遇到的所有变化/场景示例— 常见、罕见以及介于两者之间的所有情况。
  • 使用多样化的例子*(例如,不要只使用背景中有雪的狗的图片,因为模型可能会将雪背景与狗联系起来,但实际上我们希望模型检测的是狗而不是雪)*
  • 保持平衡— 如果一个类/类别的例子比另一个多,那么训练好的模型表现会很差。
  • 随着新的例子或变化的出现而定期更新,以便模型也知道这些。

数据拟合

我们还需要确保数据集涵盖所有必要的用例。缺乏足够的用例可能会导致模型训练不足。创建数据集时应该问自己的问题:

  • 我需要多少数据?
  • 我需要什么类型的数据?
  • 数据集中有足够的变化来涵盖所有的例子吗?
  • 数据是否准确完整地反映了所有相关的用例?

回到我们的儿童 x 射线图像数据集示例,它应该包含以下内容:

  • 每个儿童年龄(有或没有肺炎症状)的 x 光片数量均衡
  • 曝光时间范围不同的均衡数量的 x 射线图像(有和没有肺炎症状)
  • 包含可能与肺炎相混淆的其他诊断的 x 射线图像

除了有一个多样化的数据集,有各种各样的正面和反面的例子,我们还需要有与每个例子相关联的标签。如果数据集尚未被标注,则需要先对其进行标注,然后才能将其用作构建模型的输入。你可以自己给数据集贴标签,也可以付费完成。

“在现代人工智能中,数据决定一切。人工智能软件的智能取决于用来训练它的数据。如果系统中白人男性比黑人女性多得多,那么识别黑人女性的能力就会更差。”— 《纽约时报》

一定要注意不平衡的数据集,它们会在你的模型中引入不必要的偏差。不平衡数据集是指一个或多个标签的示例明显多于或少于其他标签的数据集。给数据集加标签后,检查与每个标签相关联的示例数量,以确保每个标签都有相同数量的示例。如果你看到一个特定的标签只有几个例子,而其他的有十几个,那么当这个模型用于现实世界时,你很可能会观察到一些偏差。一旦您对数据集的覆盖范围感到满意,就该构建模型了。

建立模型

有两种方法可以建立模型:(1)自动 ML 和(2)定制建模。“自动化 ML”是一项付费服务,这意味着它很容易上手,并且对于快速开发或模型原型制作来说很便宜。然而,它很难扩展,并且提供商可以访问敏感数据。另一方面,“定制建模”对于无限的用例是完全可定制的,并且可以完全控制用于调整模型的参数。但缺点是入门成本高,需要机器学习专业知识。在线自动化 ML 服务,如谷歌云和 IBD 沃森,使任何人都可以通过简单地提供高质量的标签数据集来快速创建模型。

在我们开始构建我们的模型之前,定义我们期望从这个模型中得到的业务目标和结果是很重要的。还要考虑你希望你的模型具有的性能水平。作为一个开始的基准,我们可以在这项任务中使用人的表现。如果模型能比人类做得更好,那么我会说模型处于一个不错的状态。现在,让我们建立一个模型。

1.训练模型

如前所述,数据定义了模型的行为和性能,包括其功效和准确性。因此,坏数据会导致坏模型。例如,如果你给一个模型输入一个训练数据中没有的图像,它将不会被正确分类。

对于我们的 X 射线示例,我们将使用 Google Cloud AutoML Vision 来训练模型。我们将使用 Kaggle [2]中已经准备好的数据集。首先,点击“新建数据集”上传带标签的数据集:

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

1.0 Look for the “New Dataset” button in dotted blue circle

数据上传后,您的屏幕应该如下所示:

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

1.1 A data set uploaded successfully

接下来,我们将使用此数据集训练模型,方法是转到“train”选项卡,然后单击“Train model”。

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

1.2 Look for “Train Model” button within the “Train” tab.

请注意,该数据集将被自动划分为用于训练、测试和验证模型的数据集,因为用于训练模型的数据不应用于测试或验证模型。

在完成模型训练后,我们需要了解这个模型“有多好”。我们将深入研究分析模型结果的方法,也就是输出

2.评估模型

为了理解我们模型的质量,我们需要测量它的性能。为此,通常使用以下指标:

  • 精度是正确预测占预测总数的百分比。
  • Recall 是实际实例总数中正确预测的百分比(又名真实标签,基本事实正面)。

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

2.0 Example of precision and recall for an unbalanced data set

  • F1 得分是准确率和召回率的加权平均值;这既考虑了的误报又考虑了的漏报。请注意,F1 分数也可以从下面的混淆矩阵中计算出来。

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

2.1 F1 Score Equation

  • 混淆矩阵是描述模型的性能,特别强调模型哪里是正确的(见蓝色)和/或失败的(见橙色)。

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

2.2 The confusion matrix for the same unbalanced data set from above

回到我们停止使用 AutoML Vision 训练模型的地方,转到数据集的“评估”选项卡,查看模型的性能。它应该是这样的:

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

2.3 Model evaluation

如果您向下滚动,您将看到更多指标(如混淆矩阵),还可以看到每个特定标签的绩效指标。

没有训练一个模型一次就得到“完美模型”的说法。这是一个反复的过程。因此,如果您对结果不满意,您有两个选择:1)改进数据,2)实现自定义模型。我强烈建议您首先考虑改进数据,一旦您无法获得任何更好的结果,才考虑实现您自己的模型。在这一点上,您将会更好地理解为什么您的模型没有达到预期。尽管如此,如果有一个高质量的数据集,AutoML 提供的模型可能会让您达到一个不错的水平。

3.模型预测

最后,让我们看看模型在新图像下的表现。转到“预测”选项卡,上传未在训练/测试数据集中使用的图像。

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

3.0 Look for “Upload images” button within the “Predict” tab

一旦做出预测,您的屏幕应该看起来像这样:

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

3.1 A model’s prediction on a new child x-ray image

恭喜你,你已经完成了你的第一个模型!

你自己试试

您现在已经准备好亲自尝试图像分类。没有比亲自尝试更好的学习方法了。

请注意,谷歌云提供价值 300 美元的免费试用,帮助您入门。因此,它不会花费你任何东西。

这里有一些资源可以帮助你开始:

欢迎在下面的评论中分享你的想法。

XGBoost:直观的解释

原文:https://towardsdatascience.com/xgboost-an-intuitive-explanation-88eb32a48eff?source=collection_archive---------23-----------------------

我们都知道 XGBoost 是如何凭借性能和速度在 Kaggle 比赛中称霸的。这个博客是关于理解 XGBoost 是如何工作的(试着解释一下研究论文)。这篇博客不是关于如何编码/实现 XGboost 或者如何调优它的超参数。

XGBoost 代表 eXtremeGradientBoosting。首先,回顾一下图 1 中的装袋和增压。它解释了 bagging(引导聚合)和 boosting(自适应 Boosting)。更准确地说,助推是如何添加到装袋的想法。在装袋过程中,随机选择不同袋子的数据点,并以相等的概率进行替换。在 boosting 中,基于迄今为止的模型性能来选择数据点。当创建一个新的包时,表现为的数据点被赋予更多的权重。基于该重量,拾取数据点(轮盘赌类型选择)。XGBoost 基于类似的 boosting 思想(非随机地构造新的树)。

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

Figure 1. Bagging vs Boosting

类似于 boosting,我们在 XGBoost 中基于模型到目前为止的性能构建一个新的树。图 2 给出了构建新树背后的符号和数学。

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

Figure 2. Building a new Tree in XGBoost

上面的步骤显示了当树按顺序构建时(像在 boosting 中),如何计算新的树的权重。如果我们知道树的结构 q ,我们就可以在方程(3)中获得根的权重和得分函数。但是我们不知道 q 并且不可能枚举和尝试每一个树形结构。在寻找树的过程中,在树性能和计算工作量之间有一个折衷(取决于算法)。论文中提到的算法的要点如图 3 所示。

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

Figure 3. Finding the tree structure q

这是本文的前三部分。第 4 节涉及系统设计(更多的是从数据工程师的角度,我个人没有这方面的专业知识)。第 5 节讨论以前的工作,第 6 节显示 XGBoost 性能评估。

XGBoost 的开发者做了大量的工作超越了仅仅是开发一个新的算法来构建树。其中包括:

  1. 他们使它们在计算上高效(这使得扩展 XGBoost 和在非花哨的计算设备上实现成为可能)。
  2. XGBoost 可以处理缺失和稀疏的数据
  3. 它基于并行和分布式计算(可以在短时间内处理数百万个数据点,允许快速的模型探索)

参考文献:
XGBoost:一个可扩展的树提升系统(原文)
机器学习掌握(解释 XGBoost 的优点)
谈 XGBoost 陈(XGBoost 的主要作者)
打包 (Udacity 视频)
提升 (Udacity 视频)

我希望这篇博客对理解 XGBoost 背后的逻辑有所帮助。如果有错误或不清楚的地方,请写信给 ucdavis.edu 的 ashnayak

原载于 2019 年 12 月 17 日 https://medium.com**的T22。

亚马逊 SageMaker 中的 XGBoost

原文:https://towardsdatascience.com/xgboost-in-amazon-sagemaker-28e5e354dbcd?source=collection_archive---------6-----------------------

SageMaker 中 XGBoost 分类的完整演练

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

什么是 SageMaker?SageMaker 是亚马逊网络服务(AWS)的机器学习平台,在云中工作。它是完全托管的,允许用户在平台上执行整个数据科学工作流。在这篇文章中,我将向您展示如何从 AWS S3 调用您的数据,将您的数据上传到 S3 并绕过本地存储,训练模型,部署端点,执行预测,以及执行超参数调整。

数据清理和特征工程代码来源于 这篇 的博文,作者是 Andrew Long,他给出了使用其代码的完全许可。数据集可以在 这里找到

启动您的笔记本实例

前往你的 AWS 仪表板,找到 SageMaker,在左侧栏,点击“笔记本实例”。要创建实例,请单击橙色按钮“创建笔记本实例”。在这里,您可以选择实例名称、实例类型、弹性推理(根据需求和使用情况调整实例大小)以及其他安全特性。除非您的公司有特定的安全需求,否则我倾向于不考虑这些,只填写实例名。启动需要几分钟时间,在成功托管实例之后,AWS 为您提供了两个选项来编写代码;朱庇特笔记本或朱庇特实验室。

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

导入包

一旦您选择了其中一个选项,您将需要运行一些代码来准备好您的笔记本。

由您来决定是否导入前半个包,但是您需要导入后四个包才能开始。

从 S3 读取数据

从 S3 读取数据有几种不同的方法,为了尽可能简单,我们将使用pd.read_csv

请注意,如果数据集位于没有文件夹的桶中,则不需要前缀。

数据清理和特征工程

由于这是一个 SageMaker 演练,而不是一个功能工程帖子,我将简要说明我采取了哪些步骤来准备数据集来训练我们的模型。

问题陈述

我们试图预测糖尿病患者是否会在最后一次就诊后 30 天内再次入院。这里的OUTPUT_LABEL将是我们的readmitted专栏。我们将那些有<30的标记为阳性,其余的标记为阴性。我们还:

  • 放弃discharge_dispositon_id,因为有些价值观与死亡或临终关怀有关
  • 删除了encounter_idpatient_nbr,因为它们是患者标识符
  • 重新标记了age并将weight变成了一个二进制变量
  • 仅取medical_specialty中的前 10 个值,并将其余值分组为Other
  • racepayer_codemedical_specialty变量中填入 NaN 作为UNK
  • 使用pd.dummies()对所有分类变量进行一键编码

我们最终得到 143 个特征,8 个数字特征和 135 个分类特征。

SageMaker 中 XGBoost 的一个非常重要的地方是,你的 **OUTPUT_LABEL** 必须是训练和验证数据集中的第一列。

我发现了一个非常有用的代码,将您的OUTPUT_LABEL移动到数据集的第一列,它是这样的:

培训/验证/测试

我们将数据集分成 70/15/15。一个好的做法是上传这些。csv 文件到 S3,分别在培训和验证文件夹下。您将需要培训和验证文件。

如果因为文件太大而耗尽了本地笔记本实例存储,可以使用以下代码绕过本地存储,直接上传到 S3。

接下来,您需要用导入的sagemaker库指定您的培训和验证文件。如果没有前缀(桶内文件夹),可以删除第二个{}

模型

培养

注意到我们没有安装和导入 XGBoost 吗?这是因为我们将使用 SageMaker 提供的预构建 XGBoost 容器。我们将导入包,设置我们的训练实例,并设置超参数,然后使模型适合我们的训练数据。

就是这样!恭喜你,如果你正确完成了以上步骤,你的模特应该正在训练!

估价

如果你不关心探索你的模型中的顶级特性(坏主意!),可以跳过这第一段。在 SageMaker 的预构建 XGBoost 中绘制特性重要性不像在 XGBoost 库中那样简单。

首先,您需要找到培训作业名称,如果您使用上面的代码来启动培训作业,而不是在仪表板中手动启动,培训作业将类似于xgboost-yyyy-mm-dd-##-##-##-###。你可以在这里找到:

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

SageMaker 中可能有一行代码,您可以运行它来返回最新的作业名称,这将省去您去仪表板查找它的麻烦。如果你找到了,请告诉我!

在您找到培训工作名称之后,您将需要运行下面的代码来从 S3 下载模型工件到笔记本实例,然后使用tarfile.open()打开工件,提取它,然后使用pickle加载它。在 AWS SageMaker 研讨会上呆了三天后,这是我们找到的最好的解决方法。

然后,由于 XGBoost 使用无头数据帧,我们必须将特性名称追加回各个列。要绘制顶部特征,使用以下代码(cols_input是输入变量,不包括OUTPUT_LABEL):

我们现在将部署一个端点,它是您传递新的和看不见的数据(测试集)以获得预测的网关。

你的预测现在被存储为predictions数组。

使用您选择的阈值创建混淆矩阵:

您将阈值设置在第二行,高于该阈值的任何内容都将被归类为阳性。上面的代码会返回类似这样的结果。

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

最后但同样重要的是,让我们绘制你的 AUC!

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

超参数调谐

超参数调优工作也可以从 SageMaker 仪表板启动,但我喜欢在笔记本上做任何事情。从笔记本中启动超参数调整工作有许多不同的方法,但是在尝试了许多代码之后,我相信这是最简单的方法。

上面单元格的输出应该返回InProgress,这意味着您已经成功启动了一个贝叶斯超参数调优作业。请注意,max_parallel_jobs 设置为 10,在运行贝叶斯优化算法时,不应该超过这个值。我相信最大值是 30,但是设置在 10 以上会导致很多失败的工作,这是浪费时间和金钱。您也不需要指定 XGBoost 模型中的每个参数,如果您删除了一个参数,作业仍然会运行。

您将再次需要通过找到您的最佳执行模型的名称来下载模型工件。您可以通过转到仪表板中的“Hyperparameter tuning jobs ”,单击相应的调优作业,然后按客观指标(在本例中为 AUC)排序,复制最佳模型的名称,并使用您下载模型工件时使用的代码。下面是代码:

为了托管一个端点,您将需要附加到模型上,这是我们在第一次训练迭代中没有做的事情。我不确定为什么会出现这种情况,但是您需要运行这行代码,然后才能托管用于预测的端点。

请注意,该模型的名称与您找到的优化模型的名称相同。

结论

在本文中,我向您展示了:

  • 如何启动您的笔记本实例
  • 导入相关包
  • 如何从 S3 读取数据
  • 如何上传本地文件到 S3,如何上传到 S3 而不保存在本地
  • 如何开始培训工作
  • 如何下载您的模型工件,加载它,并提取模型中的顶级特性
  • 如何部署端点并在测试集上获得预测
  • 如何绘制混淆矩阵,获得模型度量和 AUC
  • 如何启动超参数优化作业并获取优化后的模型

这是我第一次使用 SageMaker 进行这样的项目,我想分享一下我的工作流程和体验。感谢您阅读本文!

谢谢你看我的文章!

如果你觉得这篇内容很有帮助,并想阅读我的其他内容,请随时关注我: Twitter
insta gram
脸书
我发布了一些你可能会觉得有用的数据科学技巧和窍门!

XGBoost 简介:使用监督学习预测预期寿命

原文:https://towardsdatascience.com/xgboost-predicting-life-expectancy-with-supervised-learning-1f61e0222f5f?source=collection_archive---------4-----------------------

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

A beautiful forest. So random! Source: Pixabay

今天,我们将使用 XGBoost Boosted 树对官方人类发展指数数据集进行回归。谁说监督学习就是分类的?

XGBoost:是什么?

XGBoost 是一个 Python 框架,它允许我们利用多核并行来训练增强树。它在 R 中也是可用的,尽管我们不会在这里讨论它。

任务:回归

提升树是一种用于回归的机器学习模型。也就是说,给定一组输入和数字标签,他们将估计在给定相应输入的情况下输出标签的函数。

与分类不同,我们对标签感兴趣的是连续的值,而不是一组离散的类。

例如,我们可能希望根据一个人的体重和年龄来预测他的身高,而不是给他们贴上男性、女性或其他的标签。

对于每个决策树,我们将从根开始,根据决策的结果移动到左边或右边的子树。最后,我们将返回到达的叶子的值。

XGBoost 的模型:什么是梯度增强树?

提升树类似于随机森林:它们是决策树的融合。然而,在我们预测的空间中,每片叶子将返回一个数字(或向量)。

对于分类,我们通常会返回落在每片叶子上的训练集元素的类的平均值。在回归中,我们通常会返回标签的平均值。

然而,在每个非叶节点上,树将做出决定:某个特征值和阈值之间的数字比较。

到目前为止,这只是一个退化森林。区别在哪里?

增强树与随机森林的区别

与随机森林不同,在训练增强树时,我们每次添加新树时都会更改标签。

对于每一棵新树,我们通过减去先前树的预测之和,再乘以一定的学习速率来更新标签。
这样,每棵树都将有效地学习纠正先前树的错误。

因此,在预测阶段,我们将简单地返回所有树的预测总和,乘以学习率。

这也意味着,与随机森林或袋装树木不同,如果我们任意增加树木的数量,这种模型过度适应。然而,我们将学习如何解释这一点。

要了解更多关于助推树的知识,我强烈推荐你阅读 XGBoost 的官方文档。他们教了我很多,并且用更好的图片更好地解释了基础知识。

如果你想更深入地研究这个模型,这本书介绍统计学习是我最终发现这些概念的书,我怎么推荐它都不为过。

结合 Python 使用 XGBoost

XGBoost 的 API 非常简单,但是我们还将了解一些它的超参数。然而,首先我将向你展示今天的任务。

今天的数据集:人类发展指数公共数据

人类发展指数数据集包含许多关于大多数国家几十年来发展水平的信息,涉及许多指标和领域。

对于今天的文章,我决定只看最近一年的数据:2017 年。这只是为了让事情保持最新。

我还必须执行一些数据整形和清理,以使原始数据集更易于管理,尤其是更易于使用。

本文的 GitHub 资源库是,可以在这里找到,我鼓励您跟随 Jupyter 笔记本。然而,我会一直在这里添加最相关的片段。

用熊猫预处理数据

首先,我们将数据集读入内存。因为它包含一整列的年份,以及一行的国家和指标,所以管理起来相当麻烦。

我们将按照以下思路重塑它:

{country: {metric1: value1, metric2: value2, etc.}
   for country in countries }

这样我们就可以把它输入到 XGBoost 模型中。此外,由于所有这些指标都是数字的,因此在训练之前不再需要预处理。

这个片段去掉了具有 NaN 值的行,还告诉我们有 195 个不同的国家。

如果这些操作中的任何一个对你来说是新的,或者你在继续之前有任何困难,试着阅读我的熊猫介绍

为了查看数据集提供的所有可用的指标(指标),我们将使用 unique 方法。

df['indicator_name'].unique()

有很多(97 个),所以我不会在这里列出来。有些与健康有关,有些与教育有关,有些与经济有关,还有一些与女权有关。

我认为我们标签中最有趣的是预期寿命,因为我认为这是一个非常能说明一个国家的指标。

当然,您可以随意用不同的标签尝试相同的代码,并告诉我结果!

同样,从庞大的指标列表中,我只是手动选择了一些我认为与我们的标签相关(或不相关)的指标,但我们也可以选择其他指标。

下面是将我们形状怪异的数据集转换成更可口的东西的代码。

最后,在将我们的字典转换成数据帧后,我意识到它被调换了——它的列应该是它的行,反之亦然。我是这样解决的。

final_df = pd.DataFrame(indic).transpose()

特征相关性分析

我假设我选择的特征对回归有好处,但是这个假设仅仅是基于我的直觉。

所以我决定检查一下它是否符合统计数据。我是这样做相关矩阵的。

这是结果:

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

不出所料,出生时的预期寿命与疫苗接种高度相关。),缺乏弱势就业,以及教育。

我希望模型使用这些相同的特征(显示最高或最低相关性的特征)来预测标签。

幸运的是,XGBoost 甚至为我们提供了 feature_importance 方法,来检查模型的预测基于什么。

这是增强树相对于神经网络的一个巨大优势,在神经网络中,向某人解释模型的决定可能非常困难,甚至说服我们自己模型是合理的也很困难。但稍后会详细介绍。

为 XGBoost 模型定型

终于要训练了!在所有这些处理之后,你会认为这部分会很复杂,对吗?但事实并非如此,这只是一个简单的方法调用。

我们将首先确保我们的训练和测试数据之间没有重叠。

现在,这就是你所期待的。这是训练 XGBoost 模型的代码。

您会注意到,实际训练模型的代码和生成预测的代码都非常简单。然而在此之前,有一点设置。您在那里看到的那些值是模型的超参数,它们将在训练或预测时指定某些行为。

XGBoost 超参数初级读本

max_depth 指集合中每棵树允许的最大深度。如果此参数较大,树往往会更复杂,并且通常会更快地过度拟合(所有其他条件相同)。

eta 是我们的学习率。正如我前面所说的,在拟合下一棵树之前,它将乘以每棵树的输出,并且在之后做预测时也乘以总和。当设置为默认值 1 时,它不执行任何操作。如果设置为较小的数字,模型将需要更长的时间来收敛,但通常会更好地拟合数据(可能会过度拟合)。它的行为类似于神经网络的学习速率。

colsample_bytree 表示在生成分支时,每棵树有多少列可用。

它的默认值是 1,表示“全部”。潜在的,我们可能想把它设置成一个较低的值,这样所有的树就不会一遍又一遍地使用最好的特征。通过这种方式,模型对数据分布的变化变得更加稳健,并且过拟合也更少。

最后, num_rounds 指的是训练轮数:我们检查是否添加新树的实例。如果目标函数在多次迭代中没有改进,训练也将停止。

评估我们的结果

现在来看看模特有没有学会!

2017 年,预期寿命的标准差略高于 7(我检查了熊猫的描述),所以 4 的均方根没有什么可嘲笑的!训练也非常快,尽管这个小数据集并没有真正利用 XGBoost 的多核能力。

然而,我觉得这个模型仍然不合适:这意味着它还没有发挥出全部潜力。

超参数调优:让我们迭代

既然我们认为我们不足,让我们尝试允许更复杂的树( max_depth = 6),降低学习率( eta = 0.1),并将训练轮数增加到 40。

这一次,使用相同的指标,我对结果非常满意!我们将测试集中的错误率降低到了 3.15!这还不到我们标签标准偏差的一半,在统计上应该是准确的。

想象一下,根据某个国家的一些统计数据,预测某人的预期寿命,误差幅度为 3 年。
(当然,这种解读是错误的,因为一个国家内预期寿命的差异肯定不为零。)

理解 XGBoost 的决策:特性的重要性

这个模型似乎相当准确。然而,它的决定是基于什么?为了帮助我们,XGBoost 给了我们 plot_importance 方法。它将制作一个图表,按照重要性排列我们所有的特性(或者前 N 个最重要的特性,如果我们传递一个值给它的话)。

但是重要性是如何衡量的呢?

默认算法将测量我们的树的决策使用每个特征的百分比(使用某个特征的节点总数),但是还有其他选项,并且它们都以不同的方式工作。

直到我读了这篇非常清晰的关于媒体的文章,我才真正理解了这一点,我只是将它链接起来,而不是试图对同一件事提出另一种解释。

在我们的例子中,第一个模型给出了这个图:

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

这意味着我们的假设是正确的:具有较高或较低相关性的特征也是最重要的特征。

这是性能更好的第二个模型的特征重要性图:

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

因此,这两个模型都是使用前三个特征最多的,尽管第一个模型似乎过于依赖预期受教育年限。干净利落。这种分析对其他模型来说有点困难。

结论

XGBoost 为我们提供了一个非常好的回归,甚至帮助我们理解它的预测是基于什么。

特征相关性分析帮助我们理论化哪些特征是最重要的,而现实与我们的期望相匹配。

最后,我认为重要的是要注意这种模型的训练速度有多快,尽管这个特殊的例子并不能很好地证明这一点。

将来,我想在更大的数据集上尝试 XGBoost。如果你能想到任何,让我知道!此外,这个数据集看起来对一些时间序列分析很有趣,但我对这些主题没有太多经验。在这方面,有什么书、文章或其他资源可以推荐给我吗?请在评论里告诉我!

关注我上 推特 就知道下一篇文章什么时候出了。如果你今天学到了什么,请考虑在我的 个人网站 查看我正在做的事情和我最近的文章和笔记。

标题“51单片机通过MPU6050-DMP获取姿态角例”解析 “51单片机通过MPU6050-DMP获取姿态角例”是一个基于51系列单片机(一种常见的8位微控制器)的序示例,用于读取MPU6050传感器的数据,并通过其内置的数字运动处理器(DMP)计算设备的姿态角(如倾斜角度、旋转角度等)。MPU6050是一款集成三轴加速度计和三轴陀螺仪的六自由度传感器,广泛应用于运动控制和姿态检测领域。该例利用MPU6050的DMP功能,由DMP处理复杂的运动学算法,例如姿态融合,将加速度计和陀螺仪的数据进行整合,从而提供稳定且实时的姿态估计,减轻主控MCU的计算负担。最终,姿态角数据通过LCD1602显示屏以字符形式可视化展示,为用户提供直观的反馈。 从标签“51单片机 6050”可知,该项目主要涉及51单片机和MPU6050传感器这两个关键硬件组件。51单片机基于8051内核,因编简单、成本低而被广泛应用;MPU6050作为惯性测量单元(IMU),可测量设备的线性和角速度。文件名“51-DMP-NET”可能表示这是一个与51单片机及DMP相关的网络资源或代码库,其中可能包含C语言等适合51单片机的编语言的源代码、配置文件、用户手册、示例序,以及可能的调试工具或IDE项目文件。 实现该项目需以下步骤:首先是硬件连接,将51单片机与MPU6050通过I2C接口正确连接,同时将LCD1602连接到51单片机的串行数据线和控制线上;接着是初始化设置,配置51单片机的I/O端口,初始化I2C通信协议,设置MPU6050的工作模式和数据输出速率;然后是DMP配置,启用MPU6050的DMP功能,加载预编译的DMP固件,并设置DMP输出数据的中断;之后是数据读取,通过中断服务序从DMP接收姿态角数据,数据通常以四元数或欧拉角形式呈现;再接着是数据显示,将姿态角数据转换为可读的度数格
MathorCup高校数学建模挑战赛是一项旨在提升学生数学应用、创新和团队协作能力的年度竞赛。参赛团队需在规定时间内解决实际问题,运用数学建模方法进行分析并提出解决方案。2021年第十一届比赛的D题就是一个典型例子。 MATLAB是解决这类问题的常用工具。它是一款强大的数值计算和编软件,广泛应用于数学建模、数据分析和科学计算。MATLAB拥有丰富的函数库,涵盖线性代数、统计分析、优化算法、信号处理等多种数学操作,方便参赛者构建模型和实现算法。 在提供的文件列表中,有几个关键文件: d题论文(1).docx:这可能是参赛队伍对D题的解答报告,详细记录了他们对问题的理解、建模过、求解方法和结果分析。 D_1.m、ratio.m、importfile.m、Untitled.m、changf.m、pailiezuhe.m、huitu.m:这些是MATLAB源代码文件,每个文件可能对应一个特定的计算步骤或功能。例如: D_1.m 可能是主要的建模代码; ratio.m 可能用于计算某种比例或比率; importfile.m 可能用于导入数据; Untitled.m 可能是未命名的脚本,包含临时或测试代码; changf.m 可能涉及函数变换; pailiezuhe.m 可能与矩阵的排列组合相关; huitu.m 可能用于绘制回路图或流图。 matlab111.mat:这是一个MATLAB数据文件,存储了变量或矩阵等数据,可能用于后续计算或分析。 D-date.mat:这个文件可能包含与D题相关的特定日期数据,或是模拟过中用到的时间序列数据。 从这些文件可以推测,参赛队伍可能利用MATLAB完成了数据预处理、模型构建、数值模拟和结果可视化等一系列工作。然而,具体的建模细节和解决方案需要查看解压后的文件内容才能深入了解。 在数学建模过中,团队需深入理解问题本质,选择合适的数学模
以下是关于三种绘制云图或等高线图算法的介绍: 一、点距离反比插值算法 该算法的核心思想是基于已知数据点的值,计算未知点的值。它认为未知点的值与周围已知点的值相关,且这种关系与距离呈反比。即距离未知点越近的已知点,对未知点值的影响越大。具体来说,先确定未知点周围若干个已知数据点,计算这些已知点到未知点的距离,然后根据距离的倒数对已知点的值进行加权求和,最终得到未知点的值。这种方法简单直观,适用于数据点分布相对均匀的情况,能较好地反映数据在空间上的变化趋势。 二、双线性插值算法 这种算法主要用于处理二维数据的插值问题。它首先将数据点所在的区域划分为一个个小的矩形单元。当需要计算某个未知点的值时,先找到该点所在的矩形单元,然后利用矩形单元四个顶点的已知值进行插值计算。具体过是先在矩形单元的一对对边上分别进行线性插值,得到两个中间值,再对这两个中间值进行线性插值,最终得到未知点的值。双线性插值能够较为平滑地过渡数据值,特别适合处理图像缩放、地理数据等二维场景中的插值问题,能有效避免插值结果出现明显的突变。 三、面距离反比 + 双线性插值算法 这是一种结合了面距离反比和双线性插值两种方法的算法。它既考虑了数据点所在平面区域对未知点值的影响,又利用了双线性插值的平滑特性。在计算未知点的值时,先根据面距离反比的思想,确定与未知点所在平面区域相关的已知数据点集合,这些点对该平面区域的值有较大影响。然后在这些已知点构成的区域内,采用双线性插值的方法进行进一步的插值计算。这种方法综合了两种算法的优点,既能够较好地反映数据在空间上的整体分布情况,又能保证插值结果的平滑性,适用于对插值精度和数据平滑性要求较高的复杂场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值