TowardsDataScience-博客中文翻译-2020-一百零八-

TowardsDataScience 博客中文翻译 2020(一百零八)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

从新冠肺炎恢复的股票。机器学习来解释。

原文:https://towardsdatascience.com/stocks-that-recovered-from-covid-19-machine-learning-comes-to-explain-ba712f62456d?source=collection_archive---------61-----------------------

图片凯文·卡登拍摄

亨尼投资

使用机器学习来识别新冠肺炎崩盘后恢复正常的股票中的共同因素。

编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

在这篇文章中,我使用机器学习来研究像所有其他公司一样受到新冠肺炎打击的公司,这些公司现在已经恢复正常,而不像其他许多公司。为了更好地说明发生了什么,让我们来看看最近市场最动荡时期的标准普尔 500 指数。

这场新冠肺炎崩盘结束了长达十年的牛市,股价在 2020 年 2 月 20 日至 3 月 23 日之间下跌了 33%。虽然这次衰退对股票市场有整体的负面影响,但并不是所有的公司都受到同样的影响。以下是 1500+ 美国上市公司在此期间的股票市场回报率分布。

源代码

在 X 轴上,我显示了 2020 年 2 月 20 日至 2020 年 3 月 23 日之间的价格增长。在 Y 轴上,我显示了报告增长的公司的百分比。

我们可以看到大多数公司出现负增长。分布看起来正态,平均值在 -33% 左右,在正回报范围内有一些异常值。一个的好机会出现在识别那些受到不公正打击的公司上。随着投资者开始恐慌并从市场上撤资,几乎所有公司的股价都下跌了。一旦恐慌结束,市场开始逐渐自我修正(一如既往),在新冠肺炎骚乱之前定价合理的公司开始回到它们最初的价格水平,把那些应该修正的公司留在后面。

下图描绘了新冠肺炎危机下降复苏阶段(截至 2020 年 5 月 1 日)的回报率。

源代码

直方图中的下降数据来自之前的图。恢复数据显示了 2020 年 3 月 23 日至 5 月 1 日市场触底后的回报率。与 2020 年 3 月 23 日相比,报告了恢复回报。这一点很重要,因为下降返回 -50%恢复返回 50% 是不一样的。例如,下降50%可能代表价格从二月份的 200 美元下降到三月份的 100 美元。在这种情况下,50%的回报率意味着从 3 月份的 100 美元涨到 5 月份的 150 美元,可以弥补一半的损失。

财务数据

在这项研究中,我使用的是来自 www.vhinny.com 的阿尔法数据集,它提供了 T42 的基本财务数据,包括过去八年的资产负债表、损益表和现金流量表。我还使用免费的 alpha vantage API 来访问每日股票价格。

问题陈述

在这项研究中,我希望找出那些在价格被新冠肺炎修正的压低迅速恢复的公司背后的驱动因素。了解这些驱动因素会为那些希望在未来保护自己并利用这一机会的投资者增加价值。更具体的问题陈述如下:

找出在 2020 年 2 月 20 日至 3 月 23 日期间股价下跌至少 25%,在 3 月 23 日至 5 月 1 日期间股价上涨至少 25%的公司。

方法学

有很多方法可以解决这个问题,从无监督聚类预测建模。我在这里使用的方法利用了预测建模的优势。我的目标不是训练一个预测未来衰退的模型。相反,我的目标是了解过去。带着这个目标,我发现简单的决策树分解是这项工作的最佳方法。

决策树因过度拟合训练数据而臭名昭著。由于这一特性,它们几乎从未用于预测建模,从而产生了随机森林XGBoost 。然而,与其他算法不同的是,决策树提供了对其决策过程的准确可见性,向研究人员展示了决策是如何做出的。

我把这个问题框定为一个分类任务,把那些价格下跌至少 25%的公司贴上标签,然后 T21 上涨至少 25%。数据中只有 10% 的公司符合这个条件。然后,我用以下参数拟合一个决策树:

  • 最大深度:10
  • 一片叶子上的最小样本数:5
  • 最大叶节点数:10

因为我的目标是解释过去而不是预测未来,所以我没有像在典型的预测机器学习问题中那样将数据分成训练和验证组。我使用的参数也不是区分正反例的最佳参数。相反,我为选择的参数将问题限制在易于解释的范围内。这样,稍微牺牲一下性能,我就可以确定并可视化数据中的基本趋势,这正是我所寻找的。

实施情况和结果

下图显示了一个决策树,适合识别在 2 月 20 日至 3 月 23 日期间股价下跌至少 25%且在 2020 年 3 月 23 日至 5 月 1 日期间股价上涨至少 25%的公司。

源代码

这个决策树适合 1500 多家美国上市公司基本财务数据。每个节点都有一个标签(类),根据该节点上的大多数示例,将每个节点分类为正节点或负节点。我使用红-白-蓝的配色方案来帮助形象化每个节点上积极和消极的平衡。纯红色表示绝大多数例子都是正面的。纯蓝色表示大多数示例都是负面的。随着正面和负面例子的比例趋于相等,颜色变得更加淡化。如果正例的数量等于负例的数量,a 变成白色(全透明)。箭头表示基于节点本身记录的条件的分割。左箭头将符合条件的示例分开,不符合条件的示例留给右箭头

全球趋势

源代码

该模型确定的最重要的分割是市值。它的第一个决定是隔离市值≥1 . 2 亿美元的公司。值得注意的是,它没有进一步追踪中盘 中盘大盘股票,只留下了右盘的 990 个负面例子和 77 个正面例子(150 个中)。虽然模型已经决定在第一次分割时将 65%的数据标记为阴性,但这并不意味着没有办法正确地识别右边叶子上的那些 77 阳性样本。这意味着,考虑到我在决策树(参数)上设置的限制,识别它们并不是最佳选择。相反,给定左叶中的约束,它有更好的机会优化目标。

正叶

源代码

左分支有六(6)个正节点。这些节点中的每一个都有自己独特的路径(一组条件),投资者必须应用这些路径才能到达那里。通过阐述每条道路背后的故事,可以推断出总体趋势。

国际风险和资本负债的变化

源代码

一旦公司被缩小到小盘股,汇率的效应就被确定为下一个分割点。鉴于数据的性质,汇率赚了多少钱损失了多少钱可能并不重要,重要的是一家公司是否在国际化经营,是否受到汇率的影响。在有汇率风险(国际化经营)并报告营运资本负债增加超过400 万美元的公司中,发现了小盘股中的正叶营运资本负债的变化是现金流量表营运现金流部分的一部分。它本身并不具有很强的指示性,因为它通常由算法未识别的运营资产的变化来平衡。从这里我唯一能得出的结论是公司的资产负债表上有些变化。

债务

源代码

沿着上一节开始的道路,跟踪营运资本负债变化≤ 、400 万美元、的公司,我们发现自己处于评估公司债务偿还的节点。虽然在不知道一家公司有多少债务的情况下评估债务偿还具有挑战性,但是评估债务与股本比率更加简单。债转股节点有 11 家公司,11 家中有 6 家为正。在这些积极的公司中,有五(5) 家公司的资产负债率超过 5%。这是一个有些违反直觉的结论,因为好公司通常被描述为负债较少的公司。然而,5%可能好得令人难以置信,因为它表明该公司几乎完全由股权出资,或者在其报告中有不寻常的事情。追求 5%+ 的负债权益比率,在这个节点上,我们得到了 6 个正面例子中的 5 个。

超越破产

源代码

另一个正叶标识没有有形国际风险且具有负Z1破产分数的公司(例如,财务状况不佳)。在这种情况下,11 家库存增长至少达到 28 万美元的公司中,有 8 家被正确标记为积极。这一观察表明,投资者可能会将不断增长的库存视为新业务的迹象,尽管财务表现不佳,但仍会支持该公司。

另一个 leaf 列出了在上一个财政年度已经出售价值超过价值33 亿美元证券的公司。由于没有关于他们购买了什么的信息,因此很难合理解释它产生了什么样的净效应。鉴于这一条件正确地识别了 6 个正面例子中的 4 个,一种假设可能是这些公司在新冠肺炎让 T21 贬值之前抛售了证券,使得这些公司有足够的现金来获得投资者的信任。****

结论

在这篇文章中,我分析了 1500 多家美国上市公司的财务状况,这些公司在 2 月 20 日至 3 月 23 日期间股价至少下跌了 25%,在 2020 年 3 月 23 日至 5 月 1 日期间股价至少上涨了 25%。我的发现表明,在小盘股中可能会发现相对简单的关系。小盘股中的无负债表现出违反直觉的关系,在 5%左右划出一个负债权益比的界限。几乎所有低于 5%** 负债权益比的公司的股价都没有那些高于 5%负债权益比的公司恢复得快。尽管财务表现不佳,但在上一个财年增加库存的公司能够迅速恢复股价。从上一财年出售证券中获得有形收益的公司也表现出快速复苏。**

请在此找到支持本研究的代码。

感谢阅读我的文章!如果你喜欢,你可能想看看这个:

** [## 新冠肺炎在股票市场上横冲直撞。机器学习来解释。

使用机器学习来识别新冠肺炎期间受打击最大的股票中的共同因素。

towardsdatascience.com](/covid-19-rampage-on-the-stock-market-machine-learning-comes-to-explain-3332707954af)

我们连线吧!

我很高兴与和我有共同道路的人联系,这是对财务独立的追求。如果你也在寻求经济独立,或者你想和 T2 合作,交流想法,请随时联系我们!以下是一些可以找到我的地方:

  • 【www.vhinny.com——投资研究平台,为您自己的分析提供金融数据
  • https://www.linkedin.com/company/vhinny——加入我们在 LinkedIn 上的社区,在那里我和其他贡献者分享与投资相关的内容

干杯!**

“通用”数据科学生命周期

原文:https://towardsdatascience.com/stoend-to-end-data-science-life-cycle-6387523b5afc?source=collection_archive---------5-----------------------

逐步分析:从业务理解到模型监控

安特·罗泽茨基在 Unsplash 上的照片

为了使数据科学生命周期成功,很好地理解每个部分并区分所有不同的部分非常重要。具体来说,理解 开发阶段部署阶段 之间的区别非常重要,因为它们在业务方面有不同的需求需要满足。

大多数数据科学项目都有类似的工作流/结构,您可以使用它们来构建您的项目。下面的生命周期概述了数据科学项目通常经历的主要阶段。它从来都不是一个线性的过程,尽管它会反复运行多次,以试图获得尽可能好的结果,一个既能满足客户又能满足业务的结果。

数据科学生命周期(图片由作者提供)

水平线代表典型的机器学习生命周期看起来像是从数据收集开始,到特征工程到模型创建: 模型开发阶段 。左边的竖线代表任何类型项目的初始阶段:问题识别和业务理解,而右边的竖线代表 模型部署阶段 的所有方面。现在,事不宜迟,让我们去找出每个阶段。

问题识别:

像任何问题一样,首先要讨论的是所有业务场景的问题识别,这是我们:

  1. 通过识别真正的潜在问题,清楚地识别问题的根本原因。
  2. 制定详细的问题陈述,包括问题对目标客户/顾客的影响。

你是如何发现问题的?

我们通过收集信息,然后与利益相关者和行业专家交谈来确定问题的根本原因。接下来,合并现有的研究和来自利益相关者的信息可以提供一些对问题的洞察和可能的高级解决方案。考虑可以帮助您更清楚地定义问题的数据源。从做文献回顾开始,如有必要,在数据科学界进行调查。

问题识别总结(图片由作者提供)

业务理解:

这是定义业务问题的地方,理解业务问题是提出一个好模型的关键,因为它使你理解业务目标。

例如,如果您是信用卡客户,您希望确保我承保可能付款的客户,或者另一个客户可能会发现欺诈客户,因此目的可以是降低风险,同时增加收入。

现在我们已经有了业务理解,我们可以定义 ML 项目的成功标准,成功标准可以基于我们当前正在做的事情。你需要看看这个项目从长远来看是否可行,它是否能给你带来业务优势,让你真正向前推进。

现在有一件事非常明显,但仍然非常重要的是,进入互联网市场的门槛很低,任何人都可以获得大量信息,从商业角度来看,这使得整个市场竞争非常激烈。我们每个人都面临着竞争,因此只有通过不断衡量和跟踪正确的指标,并思考如何移动这些指标来提高您的绩效,我们才能增加脱颖而出的机会。

这就是我们需要正确指标的地方:

KPI(关键绩效指标)

KPI 代表关键绩效指标:根据关键业务目标衡量您的绩效。企业利用这一点来衡量他们的业绩目标和整体健康的业务。为每个企业商定正确的 KPI 非常重要,不要陷入追逐看起来很棒但没有意义的虚荣指标的陷阱。

SLA(服务水平协议)

一份服务水平协议(SLA)定义了客户对供应商的期望服务水平,列出了衡量服务的标准。例如,如果您正在创建一个非常复杂的管道,您需要满足 100 毫秒的 SLA,并且您必须每秒处理 2000 个事务。您必须确保您将满足您的 SLA 和 KPI 需求,否则,该模型将不会对您有任何好处。

指标不一致会对交易定价、服务交付质量、客户体验、整体业务目标和声誉产生负面影响。最好的方法是监控这些 KPI 和 SLA,例如使用 KPI 仪表板来监控关键结果。

同样,需要记住的一个非常重要的区别是算法目标和业务目标之间的区别。大多数时候,他们可能会被混淆,商业目标必须简单明了。

不应该是:

“降低模型 ecc 的均方误差…”

相反,应该是:

“将我的收入提高 5%”

“吸引更多客户,并将客户数量减少 10%”

业务理解摘要(图片由作者提供)

数据采集

一旦我们了解了业务及其目标。我们需要了解数据和所有不同的需求。首先,我们去收集数据。后者可能已经被订购或集中,或者我们可能不得不去单独的源系统并收集我们的模型所需的数据。确定是否有足够的数据推进下一个建模步骤。同样,这个过程经常是迭代的。这是数据采集阶段。这通常是通过 ETL 管道完成的,ETL 代表提取、转换和加载。

抽取、转换、加载至目的端(extract-transform-load 的缩写)

在这一步中,数据被提取、处理并加载到数据仓库中,这通常是通过 ETL 管道完成的,ETL 代表提取、转换和加载。

ETL 是一个 3 步流程:

  • 从单个或多个数据源中提取 数据。
  • 按照业务逻辑转换 数据。转换本身是一个两步过程——数据清理和数据操作。
  • 之前转换的数据加载到目标数据源或数据仓库中。

在数据的转换部分,我们可能需要处理不同的问题,例如缺失值的插补。数据经常包含缺失值或空值,导致模型潜力降低。所以我们试图估算缺失的值。

  1. 对于连续值,我们根据需要使用平均值、众数或中位数填充空值。
  2. 对于分类值,我们使用最频繁出现的分类值。

此外,数据几乎从来没有正确的格式,因此预处理步骤总是必须的,所以识别这些预处理规则例如:日期-时间数据。

数据采集和 ETL 总结(图片由作者提供)

EDA(探索性数据分析)

探索性数据分析部分是我们理解数据、模式等一切的部分...这是通过采用统计和数据可视化来完成的。在这里,我们研究如下信息:

  • 不同的变量是如何相互关联的,它们的分布是什么样的?
  • 变量之间的相关性是什么,寻找数据与目标变量有多好联系的证据?

统计数据

  1. 我们使用 描述性统计 来获得数据的更大图像,这基于数据的属性来描述数据。

描述性统计的四种主要类型是:

  • 测量频率
  • 集中趋势的度量
  • 离差或变化的度量
  • 位置测量

2.我们使用 推断统计 来验证数据集和模型输出的分布,最常用的方法有:

3.最后,我们采用 单变量和多变量分析 来识别从属和独立特征之间的相关性和趋势:

来源:https://crumplab.github.io/statistics/gifs.html

数据可视化

来源:靴板

数据可视化在数据科学生命周期中发挥着重要作用,它被用于从数据理解到部署,再到与利益相关者交流业务洞察力的每一个部分。

数据可视化能够生成所有方面的可见见解,只需在图表上绘制一个简单的模式,这使得模式和趋势的识别变得容易得多,而不是只查看电子表格上的数千行和只使用统计数据。

即使从统计数据中提取信息,如果没有良好和适当的可视化,来自没有可视化的数据的洞察力也很难交流,上图是不同类型的可视化的示例。

EDA 摘要(图片由作者提供)

特征工程:

特征工程是利用领域知识通过数据挖掘技术从原始数据中提取特征的过程。这些特征可以用来加强机器学习模型的性能。特征工程可以认为是应用机器学习本身。

“机器学习只占整个数据科学生命周期的 20%到 30 %”

最有意义的特征工程技术用于将数据转换为模型可以更好理解的形式,并处理数据和模式异常:

  • 数据变换技术: 对数变换、平方根变换、分类编码、幂函数和缩放。
  • 处理: S kewed 数据、偏差缓解、宁滨、异常值检测后者识别偏离数据集正常行为的数据点或观察值。异常值数据可以指示关键事件,如技术故障或潜在危险,因此需要相应地处理,否则会误导我们的最终模型。

在将数据转换为正确的格式并处理潜在的数据危险之后,大多数时候,特别是对于高维数据集,我们最终会得到许多特征,我们不能将所有特征输入到机器学习模型中,这不是它的工作方式,这将极大地过度拟合模型。相反,我们必须选择正确数量的功能。这在前面的步骤中,在数据分析或 EDA 中部分完成:然而,当研究变量的相关性时,有一种适当的方法可以做到这一点,这被称为特征选择。

这是三种主要方法:

  • 基于过滤方法: w e 指定一些度量并基于过滤特征,例如:C orrelation、卡方、ANOVA
  • 基于包装器的方法: 我们把一组特征的选择看作一个搜索问题,例如:递归特征消除,向前/向后选择
  • 嵌入方法: 我们使用内置特征选择方法的算法,例如拉索(L1)和岭(L2)回归

特征工程总结(图片由作者提供)

模特培训

一旦首先准备好对特征进行建模,我们就创建一个基线模型,然后我们进行模型训练,然后我们不断增加模型的复杂性,增加各种算法的测试,看看这个特定的数据集如何响应这个算法,然后你进行超参数调整来设置模型的正确超参数,然后我们应用技术来防止过度拟合,例如交叉验证

来源:奥雷利作者:爱丽丝郑

我们需要在数据集上评估训练模型的性能,这发生在测试集上,因为模型可能会过度拟合,不能很好地概括,所以我们必须确保我们消除了模型中的任何偏差,这就是为什么这一部分非常重要。

模型训练总结(图片由作者提供)

模型部署

一旦我们训练了模型,模型部署就不是简单的了,我们需要提前考虑。

模型开发很难,但模型部署更难— Srivatsan Srinivasan

在部署之前,我们必须确保测试以下内容:

  • 部署的模型是否符合原始模型的预期。通过使用在开发阶段确定的测试输入集,产生经过验证的结果。
  • 确保数据是干净的,这样它就可以被下游的机器学习组件处理,这样我们就可以通过数据的一致性和质量来加强流程之间的预期和事务。
  • 正在部署的模型是否足够健壮,能够通过测试这些输出的极端值来接受不同范围的输入。

通过在将模型部署到生产环境之前进行持续的定期检查和运行测试,我们可以最大限度地降低和防止模型崩溃的风险,以及影响其下游消费者的风险。

将模型投入生产的不同方式

选择如何将预测模型部署到生产中是一个相当复杂的问题,有不同的方式来处理预测模型的生命周期管理,不同的格式和存储方式,多种方式来部署它们,以及非常广阔的技术前景可供选择。

通常有不同的方法将训练和服务器模型投入生产:

  • 训练:一次性、批量、实时
  • 服务:批处理,实时(数据库触发器,发布/订阅,网络服务,inApp)

一次性培训

机器学习模型不一定需要不断地训练才能生产,它可以只是训练并推向生产,直到它的性能足够恶化,然后它们被刷新和重新训练。

这种类型的模型部署是进行原型开发和机器学习的数据科学家的首选,典型的模型格式有:

批量训练

批量训练允许具有基于最新训练的模型的不断更新版本。

实时训练

当实时部署这种类型的模型时,需要足够的支持和监控,因为模型可能对新数据和噪声敏感,并且需要不断监控模型性能,这种类型的培训可以通过“在线机器学习模型”来实现,具体来说:

  • k 均值(通过小批量)
  • 线性和逻辑回归(通过随机梯度下降)
  • 朴素贝叶斯分类器

批量 vs 实时预测

在预测/发球方面,在看是设置批量还是实时预测的时候,了解关键的区别是非常重要的。

批量预测的例子 :

批处理作业通常按照某种循环计划生成(例如每小时、每天)。这些预测然后被存储在数据库中,并可以提供给开发者或最终用户。批量推断有时可能会利用 Spark 等大数据技术来生成预测。这使得数据科学家和机器学习工程师可以利用可扩展的计算资源来一次生成许多预测。

实时预测或在线推理的例子:

每当用户通过该服务订购食品时,就会生成 UberEats 估计交付时间。不可能生成一批这样的评估,然后提供给用户。想象一下,在食物到达之后的之前,你不知道要多久才能收到你的订单。其他可以受益于在线推理的应用例子包括增强现实、虚拟现实、人机界面、自动驾驶汽车以及任何允许用户实时查询模型的面向消费者的应用。

模型部署摘要(图片由作者提供)

模型监控

一旦模型被部署,在一些极端的情况下,模型可能是非性能的,它可能只是抛出垃圾分数,这将影响业务目标等等,因此我们需要持续地监控模型,这部分经常被初学者忽略。

(图片由作者提供)

这里有两个重要的组成部分:

数据漂移分析:我们将来自真实世界的传入数据分布与被评分的数据分布进行比较,如果我们注意到它们之间的一些差异,我们需要选择一个阈值。但是,如果差异很大,则传入的数据会发生漂移。在这种情况下,我们需要回过头来分析差异。

模型漂移分析:我们将现实世界模型分布的分数与已评分的模型分布的分数进行比较,因此在这里,这被输入到一个系统中,该系统持续地向业务用户报告并给出输出。同样,业务部门不会理解准确性、召回率和精确度,如之前在业务理解部分中所述,因此这里的最佳指标是通常在仪表板中找到的 KPI:作为可视化和报告,它会说明例如我们获得了多少客户、我们赚了多少美元以及这在收入流中意味着什么等等。

就数据漂移而言,原因可能是:

  • 上游过程改变,例如传感器被更换,改变了测量单位,损坏的传感器读数总是 0。
  • 数据的自然漂移,如平均温度随季节变化。
  • 特征之间关系的变化。

如何介入?

  • 清除错误的标签
  • 重新训练/校准模型
  • 尽早发现并纠正上游数据问题

如果出现概念或数据漂移,并且您的机器学习模型变得陈旧,如下面左侧图表所示,我们可以在右侧看到,通过随着时间的推移刷新模型,我们可以防止模型随着时间的推移变得陈旧。

资料来源:数据报告

模型监控/警报摘要(图片由作者提供)

结论

这是对数据科学项目流程和整体组织结构及其交互的建议。显然,这个周期有许多变化——出于复杂性的考虑,我没有深入研究模型构建和评估的某些方面,因为这些方面在所有数据科学和 ML 平台中都经常讨论,所以我更喜欢坚持研究其他部分。总结一下:

当采用时,确保选择最适合您的问题的方法,理解具体的用例,并从业务角度出发选择正确的指标:KPI 和 SLA,这将有助于从开发到将 ML 模型部署到生产的正确方法。机器学习不是万能的,如果你可以用更简单的方式解决问题而不采用 Ml,你应该选择它,越简单的解决方案越好。希望你发现这篇文章内容丰富!感谢您的阅读!

你有什么想法?我错过了什么或者我可以改进的吗?请在下面随意评论。我欢迎任何反馈。

参考文献

[## 在生产中部署机器学习模型的不同方法概述

将模型投入生产的方法有很多种,不同的方法会带来不同的好处

www.kdnuggets.com](https://www.kdnuggets.com/2019/06/approaches-deploying-machine-learning-production.html) [## 什么是 KPI?定义、最佳实践和示例

根据关键业务目标衡量您的绩效。关键绩效指标是一个可衡量的值,它…

www.klipfolio.com](https://www.klipfolio.com/resources/articles/what-is-a-key-performance-indicator) [## 模型:从实验室到工厂——硅谷数据科学

在我们的行业中,很多重点放在开发分析模型,以回答关键的业务问题和预测…

www.svds.com](https://www.svds.com/models-lab-factory/) [## 批量推理与在线推理——生产中的 ML

过去几周你一直在训练一个新的机器学习模型。在与产品团队合作定义…

mlinproduction.com](https://mlinproduction.com/batch-inference-vs-online-inference/)

斯多葛派哲学——由算法构建

原文:https://towardsdatascience.com/stoic-philosophy-built-by-algorithms-9cff7b91dcbd?source=collection_archive---------10-----------------------

冥想计划

再现历史上最有权势的人之一所写的斯多葛派哲学

马尔科·奥雷里奥半身像——Saiko的“芝加哥艺术学院的古罗马雕塑”由 3.0CC 授权

使用机器学习来生成一个或几个古代文本风格的语言是那些经常给我留下深刻印象的常见应用之一。

马库斯·奥勒留的《沉思录》是斯多葛派哲学的巅峰之作,受到世界各地运动员、企业家和领导人的称赞。

向内看。不要让任何事物的特殊品质和价值逃离你。第六卷

令人难以置信的是,我们可以从像罗马皇帝马可·奥勒留这样的人的内心思想中阅读和学习这门古老的学科,他被广泛认为是有史以来最伟大的斯多葛派哲学家之一。

在写这篇文章的前几天,我读了几页这本书,这很快让我的思绪回到那些迷人的 ML 生成的古代文本的摘录。

与计算机生成雄辩的文本段落看似复杂的本质相反,这实际上是一个相当简单的过程。

我们将从包含在冥想中的所有书籍的在线文本格式开始。本语料库由麻省理工学院主持【1】

宇宙是变化的:生活是观点。第四卷

卡洛斯·伊瓦涅斯在 Unsplash 上的照片

数据

首先,我们必须导入并对《沉思》的原文做一些小的改动,例如:

  • 页眉和页脚部分
  • 装饰文字(如分册“— — —”)
  • 书名(“第一册”、“第二册”等)
  • 《末日》

我们用requests.get导入,用split / replace函数和一些小的正则表达式清理数据,如下所示:

char2idx

字符>索引>向量

计算机处理数字,而不是语言。

为了将冥想翻译成计算机可以理解的东西,我们必须将我们的语料库分解成更小的输入实体。其然后可以被转换成索引(并且稍后被转换成独热编码或向量)。

这通常在两个粒度级别上完成。级嵌入,或级嵌入。

在这两种情况下,所有单独的实体(单词或字符)被用来创建一个词汇表——语料库中包含的所有语言实体的集合。冥想的字符级词汇表如下:

['\n', ' ', '!', '"', "'", '(', ')', ',', '.', ':', ';', '?', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', ']', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

由此我们可以将每个独特的字符转换成一个索引。我们用char2idx字典来做这件事,反之亦然,使用idx2char数组:

然后我们可以将人类的思考转换成机器的思考:

我们看到的一切都是视角,不是真相。

16 61 44 57 64 59 47 48 53 46 1 62 44 1 58 44 44 1 48 58 1 40 1 55 44 57 58 55 44 42 59 48 61 44 7 1 53 54 59 1 59 47 44 1 59 57 60 59 47 8

就我个人而言,我更喜欢阅读《人类的沉思》。幸运的是,机器到人类冥想训练后的翻译将由我们的idx2char阵列负责。

无论理性和政治(社会)能力发现什么既不聪明也不社会,它正确地判断不如自己。第七卷

达里奥·维罗内西在 Unsplash 上拍摄的照片

配料和切片

我们使用SEQ_LEN为每个训练示例分配序列长度。更长的SEQ_LEN似乎以短期语言结构为代价改善了长期语言结构。例如:

SEQ _ LEN = 100——“与许多人在一起,更加安静或更加自由,不会损害灵魂中的元素本身”

SEQ _ LEN = 300——“来自我的世界;但是,让这种规定成为一种政治,而不是生活,记住你自己,然而,他们关心穷人,祝福社会。”

我们可以通过增加训练历元的数量来避免这种情况。从而产生更好的短期和长期语言结构——然而,平衡这一点与过度拟合可能会变得困难。

张量流数据集

我们使用以下方法将索引数据转换成一个 Tensorflow 数据集对象[2]:

这允许我们在数据集上执行有用的内置操作,比如.batch().shuffle()

因为我们打算预测序列的下一个字符,所以我们的目标值应该是向前移动一个字符的输入。例如,如果我们的输入"Hello worl" ,我们的目标将是 "ello world"

为此,每个序列必须包含SEQ_LEN + 1字符。我们使用.batch()将数据集分割成这个长度的序列:

现在我们有了长度SEQ_LEN + 1的序列,我们把它们分成输入/输出对:

现在,我们必须重组数据集并创建训练批次。注意,我们在这里再次使用了 batch。之前,我们使用.batch()将我们的 241'199 字符长的索引语料库分割成许多长度为SEQ_LEN + 1的序列。这一次,我们使用它将我们的序列分成 64 个一组(BATCH_SIZE=**64**)。

你的习惯性想法是什么,你的思想性格也将是什么;因为灵魂被思想所染。第六卷

定义模型

该模型非常简单,由嵌入层、GRU 层和致密层组成。

tf.keras.layers.**Embedding**()层是一个可训练的数组,我们用它将单个索引字符值转换成密集的浮点向量。这个过程叫做嵌入[4]。每个字符索引映射到该层中的特定向量。

下面的tf.keras.layers.**GRU**()层包含我们的递归神经网络(RNN)。由于在计算中增加了“时间”维度,rnn 是 NLP 应用中的常见选择。这意味着我们不仅根据输入的内容进行预测,还根据这些内容的顺序进行预测。以下列陈述为例:

【原文】:我们看到的一切都是一种视角,而不是真相

【重新排序】:我们看到的一切都是真相,而不是一个视角

一个不考虑顺序的方法看不出这两个语句有什么不同。显然,顺序在语言中特别重要。请参阅 Andrej Kaparthy 的“递归神经网络的不合理有效性”文章,了解更多关于 RNNs 的信息。

RNN、GRU 和 LSTM 单位的比较。在 GRU 和 LSTM,消失梯度问题是通过信息门(绿色突出显示)解决的。

GRULSTM 单元都是对原始 RNN 的改编,旨在通过使用信息门控[6][7]来解决消失梯度问题。两者共享相似的架构和性能(在大多数情况下)。

GRU 对 LSTM 的单个历元的训练时间——这在 128 个历元上产生了显著的差异

对于这个模型,我注意到两者之间没有明显的质量差异。因为 GRUs 需要更少的训练时间,我继续这样做。

最后,我发现dropout=0.1对提高泛化能力产生了巨大的影响。这随机屏蔽了 10%的输入。导致复制文本的大段显著减少,同时仍然保持正确的语言结构和可理解的陈述。

最后的tf.keras.layers.**Dense**()层产生我们的预测。GRU 输出被传递到一个密集连接的神经网络,该网络生成对 66 个字符中的一个的预测。

不再谈论一个好男人应该是什么样的人,而是成为这样的人。第十本书

培养

使用adam优化器和sparse_categorical_crossentropy损失函数编译该模型。

在训练过程中,我们用以下方式保存模型重量:

checkpoint然后在model.fit()期间被传递给callbacks自变量。在每个训练时期结束时,模型权重保存在./training_checkpoint目录中。

装货

训练后,我们可以从文件中加载训练好的模型权重,并使用它们来重建我们的模型。关键的区别在于,我们使用批量大小1而不是训练期间使用的64来重建模型。我们这样做是为了传递一个输入(例如"From")来产生一个输出。

这一切都是通过以下方式完成的:

我常常想,为什么每个人爱自己胜过爱所有的人,但却不重视自己对自己的看法,而重视别人的看法。第十二卷

尼尔斯在 Unsplash 拍摄的照片

文本生成

一旦加载了模型,我们就可以轻松地开始生成文本了:

我们从一些非常奇怪的文本开始——它真的很像字母e。不过,普通标点的用法很快就学会了:

"From eeeeereeeeeseeceeeeeeeceeeeeeee,eeieeeeee. Leeeeeeeeeedeeepeeeeeeeeeeeeeeeereee;,eveeeeeeeeeeceeeeeeceeeeeeeepenesneee,eeeee."

该模型在很少的训练期后很快就能计算出单词:

"For the veppering doul to shod. Bubeeg if not it discoreor theselly alo hace."

再过几个时代,我们就会得到真正的单词——到处都有一些错误:

"Thou art dods thee from the deadgh of impuety by habour of mecrating, and oter coused by doing with gaves indifected, if thou hass serdect to him at a think. The way only not ando, nothing is compousted the that happoness; and de to be exturn and I he another suchivisicis inforaition with its Iw all vellected with does at all things, how sefull: and kill not the beact?"

最终模型会产生一些可理解的陈述,这看起来非常酷:

"Eudaemonia (happiness) is a good daemon, or a good thing. What then dost thou think of him who ave in harmony with what is really good.""Constantly contemplate the whole morals of those who live with us and present themselves in abundance, as far as is possible. Wherefore we must keep them before us."

进一步训练,我们倾向于复制大部分几乎冥想文本的副本:

"Remember that as it is a shame to be surprised if the figtree produces figs, so it is to be surprised, if a man has a fever"

结论

通过训练一个简单的关于冥想的 RNN 建筑,产生了一些令人惊讶的精彩的文本部分。它设法精确地组织句子,正确地产生真实的单词,并把它们合并成大部分实际上可读的东西。

虽然结果很酷,但进一步发展这一点需要的不仅仅是冥想。在 ML 中,数据为王。在这个项目中,独自坚持冥想是最大的限制因素。简而言之,我们需要更多的数据。

我的思路是,随着更多数据的纳入,我们将建立更大的词汇量。从那以后,我们将有更多的词供我们使用,所以词级嵌入似乎是合乎逻辑的下一步。使我们能够维护由单词提供但在字符级嵌入过程中丢失的语义。

目前,我对构建偶尔看起来很有见地的东西是多么容易印象深刻。我期待着在未来用更多的数据、词向量和其他工具进行更多的试验。

让我留给你一些我最喜欢的算法思考。

“你忍受这一点是理所应当的;但另一个问题是,人们为了获得快乐而工作,这本身就是一种瘟疫,但无论如何,每个人的善与他为之忙碌的事情的价值是一样的。”

“所有的事情都是一样的,在经历中是熟悉的,在时间上是短暂的,在物质上是没有价值的。现在的一切就像过去一样,时间是一个点,物质在流动,感知是应该的,然后不要让你的欲望找到它的终点。”

请记住,理性这个词的本意是表示分散,或者分解成原子,或者湮灭,它要么消失,要么改变。

这里的代码是这里你可以找到一个 100K 长的输出这里

感谢阅读!

参考

[1] M. Aurelius,《沉思录》(公元前 170-180),麻省理工学院网络经典档案

[2] 文本生成与 RNN ,Tensorflow 核心教程

[3] td.data.Dataset ,TensorFlow 核心文档

[4] 单词嵌入,Tensorflow 核心教程

[5] A. Karpathy,递归神经网络的不合理有效性 (2015),Andrej Karpathy 博客

[6] S. Hochreiter,J. Schmidhuber,长短期记忆 (1997),神经计算 9(8):1735–1780

[7] S. Hochreiter,递归神经网络学习和消失梯度 (1998),国际不确定性、模糊性和基于知识的系统杂志 6(2):107–116

[8] J. Chung,C. Gulcehre,K. Cho,Y. Bengio,门控递归神经网络对序列建模的实证评估 (2014),NIPS 2014 深度学习和表征学习研讨会

如果你喜欢这篇文章,你可能会喜欢冥想项目的下一篇文章——我在那里介绍了使用多个竞争的 rnn 来产生更高质量的文本,请在这里查看:

[## 集成学习的增压预测

利用竞争神经网络提高文本生成质量

towardsdatascience.com](/recurrent-ensemble-learning-caffdcd94092)

停下来,协作和倾听:在家与微软团队一起工作

原文:https://towardsdatascience.com/stop-collaborate-and-listen-working-from-home-with-microsoft-teams-60166258565e?source=collection_archive---------36-----------------------

迈克尔·索莱达在 Unsplash 上的照片

对许多人来说,在家工作将是一件新鲜事。我写这篇文章的时间是 2020 年 3 月,在那里,在家工作是一种新常态。因此,我们将介绍一些一般的远程工作技巧,然后继续浏览一些快速的电源技巧,然后浏览微软团队界面。

一、远程工作者生存指南

对于很多人来说,你可能是第一次在家工作,这里有一些有用的提示让你在远程工作时保持高效和理智。

有规律可循

晚起床,穿着睡衣,甚至在床上或沙发上工作,真的很容易。应该避免这种情况。常规在工作和非工作之间建立了清晰的界限。例行公事不仅对良好的心理健康至关重要,而且由于从未真正有过休息时间,工作的模糊边缘也会产生压力。常规和精神健康研究(L . M . Lyle 等人,Lancet 2018 )。我总是确保在 8:30 左右开始工作之前洗完澡,穿好衣服。

晒晒太阳

因为你没有每天 2 小时的通勤时间,很可能你不会得到额外的 2 小时日光照射你的视网膜。季节性情感障碍的问题是众所周知的,但是远离屏幕看远处和白天也是有好处的,包括减少头痛,减少疲劳和通常更高的生产力。除了看到一些真正的日光,我建议买一个日光温度台灯。

有一些界限

正如我之前说过的,有一个开始和结束工作的常规对于描绘你工作日的边界是很重要的,但是如果可能的话,试着在你家的特定区域工作。如果可能的话,这应该是分开的和不同的,你家里的任何其他成员都知道,当你在那里的时候,你在工作,不被打扰。对你们中的许多人来说,一个单独的房间是不可能的,但是如果你能使用台灯或盆栽植物来使你的工作环境与众不同,那么这将有助于区分它。

打招呼

如果你在远程工作,有理由假设你的同事也在远程工作。试着养成早上 9 点左右对他们说早上好的习惯,这会让你感觉不那么孤独。

设置您的环境

你可能会在公司的笔记本电脑上工作,从长远来看,这对你的姿势和工作效率非常不利。如果可以的话,准备一把合适的椅子、鼠标、键盘和显示器。你会在那里坐很长时间,你需要保持健康。使用提升器确保您的显示器或笔记本电脑屏幕接近眼睛的高度。

协同工作

当你远程工作时,很容易感到自己置身事外,不知道团队内部发生了什么。这是正常的,这将成为你的团队中的一个问题。为了解决这个问题,尽量让帖子、文件、会议和状态更新共享。将他们链接到团队频道可让您的团队成员通过 chatter 和更新了解正在发生的事情。

虚拟会议

虚拟会议将成为你一天中的一大部分,这是一个公平的赌注,所以要学会做好它们。质量好的耳机是必不可少的,甚至一些不太花哨的耳机也不错。拥有一个网络摄像头并不是必须的,但它确实能帮助你感受到自己是团队的一员,并迫使你穿好衣服,注意自己的外表,不管怎么说,是你的上半身。如果你不习惯戴着耳机工作,你说话的声音会比平时大得多,试着以正常的音量说话,摘下一只耳朵的耳机可以让你听到自己的声音并调节音量。如果你们中有一个以上的人同时在家工作,并且必须共享空间,这一点就变得非常重要。如果你和世界各地的团队交谈,根据交谈对象的时区使用早上好或下午好是一种礼貌的习惯。这有助于你在协调会议时留意其他人的工作时间。对于几个人以上的会议,在不发言时将麦克风静音是一种良好的礼仪。周围的背景噪音往往比你意识到的要高得多,这使得你更难听到别人说话。最后一点,我再怎么强调也不为过,不要在麦克风开着的时候喝咖啡或吃东西。如果需要喝水或者吃饭,就把自己静音,不然真的让通话中的其他人都不愉快。****

太久没有阅读—团队力量提示

安排会议

组织会议时,最好是通过团队在日历标签中预订,而不是通过 Outlook。你可以使用调度助手来避开人们的空闲和忙碌时间。向会议添加一个频道,以便会议结束后可以在该频道上看到任何消息或录音。

我们需要谈谈!

如果每个人都应该就某件事召开临时会议,请使用立即开会按钮。这通常被认为是有点粗鲁的做法,会议应该安排在日历中,并附加到频道上。

屏幕共享

如果没什么可看的,人们往往会在会议中走神,所以在你的屏幕上显示一份会议议程,并在会议期间与分享你的屏幕,这通常是一个不错的做法。

一幅画胜过千言万语

除了屏幕共享,你还可以共享一个白板。对于一些讨论来说,能够快速勾画出一些东西是非常有用的。我用一个便宜的 Wacom 平板电脑来快速地画东西。

文件不仅仅是用来分享的

如果在频道的“文件”部分有 MS Office 文档。它们不仅可以上传、下载和共享,而且还可以协同工作。您可以让多个用户同时处理同一个电子表格。

对重要消息使用增强型帖子

发布消息时,点击格式按钮打开格式选项。这将允许你创建具有主题行、完全格式化的文本、列表、表格、图像的帖子,并且重要的是将帖子标记为重要!

赞同

如果您只想肯定地确认一条消息,只需点击喜欢按钮。它可以防止消息窗口变得过于混乱。

抄送给频道

理想情况下,您希望确保所有聊天和讨论都在一个频道上,以跟踪历史和决策。这并不总是如此,电子邮件将会被使用。在这些情况下,使用渠道获取电子邮件地址功能,并将其添加到您的电子邮件抄送。

微软团队是一个很好的合作软件。它不仅仅是一个会议工具,而是一个完全集成的协作套件。我没有从微软获得报酬,我只是使用了许多系统,微软团队已经成为我的首选工具。团队中有很多工具可以帮助协作,但首先我们将介绍一些基础知识。

主视图

主面板可能相当吓人,但我们将分解重要的部分,以及它们的作用。

主接口

  1. 活动—这是诸如“提及”和重要更新将被列出的地方。如果你有很多团队,这是开始你一天的好地方。
  2. 聊天——这是一对一或小组对话。如果你想和一个人或一小部分人交谈。
  3. 团队——大部分协作发生的地方,也是你大部分互动应该发生的地方。这是上面截图中选择的视图。
  4. 日历—用于预订会议、检查日程和修改回复。这一切都与您的 Outlook 日历视图同步。
  5. 新聊天—快速开始新图表按钮,开始与新朋友聊天。
  6. 搜索栏—搜索您的联系人、团队、频道和日记。还有一大堆快捷命令可以在这个工具条中供高级用户使用。
  7. 帐户设置—您可以在这里设置您的在线状态,并配置应用程序设置,包括网络摄像头和耳机。

团队和渠道

团队视图

  1. 这是你的团队。你可以加入很多不同的团队,他们都有不同的权限和成员。
  2. 团队内部有渠道。把频道想成话题。通过这种方式,你可以按主题领域组织讨论和文件。所有队伍都以默认的通用频道开始。
  3. 通过单击您的团队名称旁边的(…),您可以调出团队管理菜单。通过添加和删除团队成员并设置他们的权限来管理团队。向您的团队添加新渠道。向您的团队添加人员。离队。编辑团队名称、描述和可见性。获取一个链接来打开团队,以便在电子邮件中发布。在团队中添加和删除标签。
  4. “帖子”选项卡是显示消息和渠道会议的地方。
  5. “文件”选项卡是协作共享文件和文档的地方。
  6. 频道维基用于协作整理信息,有点像内部维基百科(维基百科 —维基)

频道设置

  1. 渠道通知允许您对群组中发生的事情的通知进行静音,这对高 chatter 渠道至关重要。
  2. 管理频道用于设置谁可以发帖以及邮件是否被审核的权限。
  3. 获取电子邮件地址是为了让您可以将该频道的电子邮件地址添加到电子邮件中,并且该消息的副本将被记录在该频道中。
  4. Connectors 是一个非常强大的用户工具,大多数用户根本不会使用它,但是它可以用来将通道与外部服务和应用程序连接起来。

文件

在团队中处理文件是它非常有用的特性之一,尽管很少使用。它将 Office365 的协作工具变成了一种非常有用的形式。可以使用“文件”选项卡共享文件,但也可以协作处理文件。在团队中打开文档进行编辑时,多人可以同时处理、审阅和评论文档。

使用文件

  1. 在频道文件中创建新文件夹或文档(Word、Excel、Powerpoint 等)。
  2. 从本地电脑上传文件。
  3. 将文件从团队下载到您的本地 PC。
  4. 以小组方式(通常首选)、Word Online(浏览器中的 Word)或 Word(电脑上的 Word 应用程序)打开文件,进行查看或编辑。
  5. 对文件执行操作,如重命名、删除、复制等。

帖子、消息和聊天

聊天窗口有很多选项,隐藏了很多强大的工具,这可以让你的团队体验更加有用。

发布消息

  1. 文章的格式选项,类似于 Word 中的基本格式选项。
  2. 底部工具栏。
  • 格式/折叠撰写框—在基本帖子和更丰富的格式选项之间切换。
  • 从“文件”标签、你的本地电脑或一个硬盘中给帖子附加一个文件
  • 给帖子添加表情符号(笑脸)。
  • 给帖子添加动画 Gif 图片。这对于一对一的消息来说很好也很有趣,但是对于频道帖子来说通常是不好的形式。因为它们很快就会变得很烦人。
  • 添加一个贴纸,类似于 gif,如有必要,请谨慎使用。
  • 立即开会,立即在频道上开始会议,并提醒频道的所有成员会议已经开始。将此用于任何临时会议。
  • ,除非你知道自己在做什么,否则不要使用。
  • 是你可以分配给别人的俗气贴纸。我不会用它,但这取决于你的团队动态。

3.发送,将您的消息发布到频道

日历

大多数有组织的讨论应该安排在日程表部分。创建新事件时,您可以管理 Outlook 中的许多功能,尽管功能不是很强大。

日历详细信息

  1. 会议名称
  2. 添加必需和可选的与会者
  3. 会议的开始和结束时间,有一个确定的会议开始和结束时间是非常重要的,因为它决定了你的忙/闲信息如何显示给其他人。
  4. 重复选项,如每个工作日、每周、每月等。
  5. 会议应附加到的渠道。非常重要。
  6. 地点如果您的一些与会者在会议室,您可以在此处添加这些地点。
  7. 会议的描述。重要的是在这里添加议程项目,以保持对主题的讨论,并让人们做好准备。
  8. 调度助手选项卡(见下文)

日程安排助理

“日程安排助手”有许多与前一个窗格相同的细节,但布局方式不同。它还有一个主要的区别,空闲和忙碌视图。“忙/闲”视图向您显示所有与会者何时安排了其他事情,让您找到一个让每个人都开心的时间,这几乎与 Outlook 中的“日程安排助手”相同。

  1. 会议的开始和结束。
  2. 管理必需的与会者。
  3. 管理可选与会者。
  4. 管理其他地点,如房间预订。

会议

可以使用聊天系统开始会议,使用日历或使用频道中的“立即开会”安排会议,但无论以哪种方式开始,工具都几乎相同。

会议界面

  1. 启用和禁用您的摄像头。
  2. 静音和取消静音您自己的音频。
  3. 调出共享面板(用于屏幕共享)。
  4. 调出设置菜单。
  5. 显示会议聊天。这应在同一频道、事件或群组的聊天之间保存。
  6. 显示已加入或被邀请加入聊天的人。
  7. 断开连接并关闭会议。

共享面板

  1. 共享您的整个屏幕。如果您有多个显示器,您可以选择要共享的显示器。
  2. 共享窗口以共享单个应用程序,而不是整个屏幕。
  3. 在会议中播放 PowerPoint 幻灯片。对于这些类型的文档,比屏幕共享好得多。
  4. 共享白板为所有参与者提供了一个协作的绘图空间。如果你的电脑上没有绘图板,那就没什么用了。

会议设置

  1. 显示和隐藏仪器设置(如图所示)
  2. 显示和隐藏会议笔记(记录会议纪要的一种方式)
  3. 一个并非所有平台都提供的新功能,允许你模糊相机的背景,这样人们就看不到你身后的东西。壁纸背景即将推出,所以你甚至可以假装在海滩上。
  4. 开始录制,这在预定的会议和立即开会中可用。它将会议录制为视频文件,在会议结束后提供给可能错过会议的人。
  5. 选择音频输出设备。
  6. 选择麦克风设备。
  7. 选择用于视频的摄像机。

停止复制粘贴笔记本,拥抱 Jupyter 模板!

原文:https://towardsdatascience.com/stop-copy-pasting-notebooks-embrace-jupyter-templates-6bd7b6c00b94?source=collection_archive---------9-----------------------

jupytemplate 简介:Jupyter 的可配置模板

Jupyter 笔记本很牛逼。它们结合了代码、输出和文本,实现了快速原型开发、早期调试和有效的故事讲述。

尽管如此,笔记本电脑也有其自身的局限性,最令人讨厌的是有限的可扩展性、促使开发人员重复代码的倾向以及缺乏标准结构。

许多文章、帖子和讲座都涉及这些话题。其中两个与本文特别相关。Joel Grus 在我不喜欢笔记本 中指责笔记本给开发人员和数据科学家灌输坏习惯。在回答 Joel 关于 Medium 的问题时,Will Koehrsen 建议谴责罪恶而非罪人,并提出了一个有趣的解决方案。

笔记本的模板

一个模板。适用于各种数据科学笔记本的标准而灵活的框架。威尔认为,如果给人们提供一个合适的结构来填充他们的内容,他们就会被推动去实施最佳实践。

这种方法的好处是它改变了默认值。

当我们阅读 Will 的帖子时,x team 的数据科学团队和我立即寻找实施该解决方案的包。不幸的是,我们发现 PiPy 或 conda 上没有这种东西。

然后,我们决定构建自己的:我们开发了一个 Jupyter 扩展,它有两个主要特性。

首先,它允许你从一个模板创建每一个新的笔记本。模板本身就是一个笔记本,这样可以方便用户编辑,适应不同的需求。我们还提供了在现有笔记本中插入模板的可能性。

扩展附带的默认模板由 6 部分组成:

  1. 摘要:笔记本的快速总结,包括其目的、方法、结果和建议的后续步骤
  2. 设置:包和本地模块导入,最常见的数据科学库已经用它们的标准别名导入
  3. 参数:影响笔记本的参数定义
  4. 数据导入:报表加载笔记本中要使用的所有数据
  5. 数据处理:核心处理,通常需要进一步细分
  6. 参考资料:对文献或其他笔记本有用的参考资料

需要注意的是,这只是一个默认的模板。每个数据科学家都可以创建自己的数据。如果您碰巧这样做了,请告诉我,以便我们可以改进我们的存储库。

第二,每保存一个笔记本为无标题,要求用户重命名。

当然,这两种功能都可以通过扩展的配置来启用或禁用。

利益

当我们在工作流中引入扩展的用法时,显著的改进变得显而易见。

有了共同的框架,其他团队成员的笔记本变得更容易阅读和共享。特别是摘要,为我们提供了 2 分钟的总结,让读者决定是深入研究代码还是查看其他地方。

随着部分准备好被填充,当肤浅地记录我们的代码时,我们开始感到内疚。这导致了更长更深刻的评论,从而提高了笔记本的整体可读性。

配置好本地导入并准备好使用后,就没有借口阻止相关代码从笔记本中重构到公共模块中。

有了模板中明确的命名约定,没有人会忘记它们。

最后,通过模板中嵌入的标准导入,我们能够节省一些时间来搜索正确导入模块的方法。

快速入门

我们的扩展可以在包jupytemplate中获得,开源并发布在 GitHub 上:https://github.com/xtreamsrl/jupytemplate

虽然不是严格要求,但我们建议开始下载整套 jupyter 扩展,目前还不包括 jupytemplate。

然后,通过运行以下命令安装 jupytemplate:

pip install jupytemplate

最后,在本地 Jupyter 实例中启用扩展:

jupyter nbextension install --py jupytemplate --sys-prefix
jupyter nbextension enable jupytemplate/main --sys-prefix

关于 GitHub 的文档中有更多的细节。

就是这样。您现在应该能够做这样的事情了。

我的读者,感谢你来到这里!

欢迎任何评论、问题或总体反馈。你可以在 LinkedIn 上和我联系(下面的链接)。

如果你喜欢这篇文章,你可能会感兴趣:

如果你对 me 或者xtream有什么好奇的话,上 LinkedIn 看看吧!

使用 Amazon EBS multi-attach 停止复制深度学习训练数据集

原文:https://towardsdatascience.com/stop-duplicating-deep-learning-training-datasets-with-amazon-ebs-multi-attach-d9f61fdc1de4?source=collection_archive---------24-----------------------

使用单个训练数据集 EBS 卷在多达 16 个 EC2 实例和 128 个 GPU 上进行分布式训练!

(20 年 2 月 26 日编辑:AWS 支持团队发布警告不鼓励使用标准文件系统,比如带有 EBS 多重连接的 xfs。xfs 不是一个支持集群的文件系统,可能会导致多重访问集群设置中的数据丢失。在我的实验中,这篇博文中的两个例子都没有出现问题,但是要小心生产工作负载。点击此处阅读更多。)

你们中的一些做深度学习的人足够幸运,他们有基础设施团队来帮助你设置 GPU 集群,安装和管理作业调度器,并为训练数据集托管和管理文件系统。

其余的人,你们必须管理好自己的装备。在开发过程中的某个时候,您将开始探索分布式训练,并运行并行模型和超参数搜索实验。当您考虑扩展选项时,您会发现使用 EC2 添加更多 GPU 非常容易。不容易的部分?—复制和管理数据集。

如果您熟悉云,您可以完成为您的训练数据集创建和管理 Amazon EBS 卷快照的过程,或者您可以为您的所有训练 EC2 实例托管一个网络附加文件系统。但让我们面对它,这比你报名参加的工作更多,当你想做的只是回去开发机器学习模型。

在我看来,AWS 最近宣布了自 12 月 re:invent 2019 以来最令人兴奋的 AI/ML 更新之一——亚马逊 EBS 的新多附加功能。现在,您可以将单个 EBS 卷附加到多个 EC2 实例,最多 16 个 EC2 实例!对于深度学习,翻译过来就是一个单个 EBS 卷向多达 128 个 GPU 提供训练数据!您可以从已经使用的 EBS 卷中获得所有网络文件系统的好处。

在这篇博文中,我将展示在多个 EC2 GPU 实例上运行分布式训练的一步一步的演练。我将向您展示如何使用单个 EBS 卷来存储整个训练数据集,并将其附加到多个 EC2 实例。不再拷贝和复制数据集!

这篇博文包含两个使用 EBS 多附加的深度学习示例:

  1. 第一个示例是设置两个 GPU EC2 实例的分步演练,两个实例都连接了一个公共 EBS 卷,并在 CIFAR-10 数据集上运行分布式培训
  2. 第二个例子是一个更现实的场景,展示了如何使用 16 个 GPU 在 ImageNet 数据集上进行训练。ImageNet 数据集消耗 144 GB 的磁盘空间,使用 EBS 多重连接,您不再需要在多个实例之间复制它。

GitHub 上的所有代码和示例都在这里:https://GitHub . com/shashankprasanna/distributed-training-EBS-multi-attach . git

如果您对管理集群和存储的替代方法感兴趣,请向下滚动到“替代方法和建议”部分。

示例 1:在 Amazon EC2 和 Amazon EBS multi-attach 上使用 TensorFlow 和 Horovod 进行分布式深度学习训练

为了演示使用 EBS 多附加功能进行分布式深度学习培训的过程,我使用了一个简单的双节点设置,其中,g4dn.xlarge EC2 实例中的每个节点都有一个 NVIDIA T4 GPU。接下来,我假设您有一个 AWS 帐户,并且在您的主机上安装了 AWS CLI 工具。您将主要使用 AWS CLI 来创建和管理资源,但是,您也可以使用 AWS 控制台来执行其中的大多数步骤。

步骤 1:启动 EC2 实例

首先启动 2 个类型为g4dn.xlarge的 EC2 实例。对于深度学习训练,G4 实例不如 P3 实例强大,但价格低廉,非常适合原型开发。G4 实例在推理工作负载方面非常出色,您可以在 G4 产品页面上了解更多信息。

aws ec2 run-instances \
 --image-id ami-07728e9e2742b0662 \
 --security-group-ids <SECURITY_GROUP_ID> \
 --count 2 \
 --instance-type g4dn.xlarge \
 --key-name <KEYPAIR_NAME> \
 --subnet-id <SUBNET_ID> \
 --query “Instances[0].InstanceId”

image-id 对应深度学习 AMI Ubuntu 镜像,预装深度学习框架,如 TensorFlow、PyTorch、MXNet 等。指定您的security-group-idskey-namesubnet-id并启动您的实例。您应该在输出中看到每个实例的实例 id。

输出:

[
“i-<INSTANCE_ID>”,
“i-<INSTANCE_ID>”
]

确保您的安全组允许消息传递接口(MPI)工作的所有端口上的 TCP 流量。本例用来进行分布式训练的 Horovod 库依靠 MPI 通信协议与所有其他 EC2 实例对话,并在训练期间分担工作负载。

显示安全组允许所有端口上的 TCP 通信的屏幕截图

为新创建的 EC2 实例添加标记。让我们将它们命名为gpu-instance-1gpu-instance-2,以便在 AWS 控制台中容易识别和搜索。在这篇文章的剩余部分,我将引用这些名字的实例。

aws ec2 create-tags --resources <INSTANCE_ID> --tags Key=Name,Value=gpu-instance-1aws ec2 create-tags --resources <INSTANCE_ID> --tags Key=Name,Value=gpu-instance-2

AWS EC2 控制台显示 gpu-instance-1 和 gpu-instance-2

步骤 2:创建一个启用了多重连接的 EBS 卷,用于存储训练数据集

在与启动 EC2 实例的SUBNET_ID相同的可用性区域中创建一个 100G 的卷。即****EBS 卷必须与 EC2 实例在同一个可用区(AZ)中,它将被附加到。在本例中,我的 EC2 实例和 EBS 卷都在us-west-2a可用性区域和相应的subnet-id中,如 AWS VPC 控制台所示。

确保 EC2 实例子网 id 对应于 EBS 卷可用性区域(us-west-2a)

要在us-west-2a中创建一个带有名称标签Training Datasets的 100G 卷,请运行以下命令:

aws ec2 create-volume --volume-type io1 --multi-attach-enabled --size 100 --iops 300 --availability-zone us-west-2a --tag-specifications 'ResourceType=Name,Tags=[{Key=Name,Value=Training Datasets}]'

显示在 us-west-2a 可用性区域中新创建的 EBS 卷的屏幕截图

步骤 3:将 EBS 附加到多个 EC2 实例

在本例中,您只使用 2 个 EC2 实例,因此您将使用正确的实例 ID 调用aws ec2 attach-volume两次,将 EBS 卷连接到两个 EC2 实例。如果有其他 EC2 实例需要访问该 EBS 卷,请重复此步骤。

aws ec2 attach-volume —-volume-id vol-<VOLUME_ID> —-instance-id i-<INSTANCE_ID> --device /dev/xvdfaws ec2 attach-volume —-volume-id vol-<VOLUME_ID> -—instance-id i-<INSTANCE_ID> --device /dev/xvdf

输出:

{
“AttachTime”: “2020–02–20T00:47:46.563Z”,
“Device”: “/dev/xvdf”,
“InstanceId”: “i-<INSTANCE_ID>”,
“State”: “attaching”,
“VolumeId”: “vol-<VOLUME_ID>”
}

步骤 4:将代码和数据集下载到 EBS 卷

获取实例 IP 地址,以便我们可以 SSH 到实例中

aws ec2 describe-instances --query 'Reservations[].Instances[].{Name:Tags[0].Value,IP:PublicIpAddress}' --filters Name=instance-state-name,Values=running

输出:

[
 {
  “Name”: “gpu-instance-1”,
  “IP”: “<IP_ADDRESS>”
 },
 {
  “Name”: “gpu-instance-2”,
  “IP”: “<IP_ADDRESS>”
 }
]

使用您的密钥对 SSH 到第一个实例 gpu-instance-1

从您的主机上,使用 EC2 密钥对 SSH 到gpu-instance-1

ssh -i ~/.ssh/<key_pair>.pem ubuntu@<IP_ADDRESS>

运行 lsblk 来识别要装载的卷

lsblk

输出:

…
…
nvme0n1 259:2 0 95G 0 disk
└─nvme0n1p1 259:3 0 95G 0 part /
nvme1n1 259:1 0 116.4G 0 disk
**nvme2n1 259:0 0 100G 0 disk**

****注意:不能保证卷的顺序,请检查以确认您的卷的确切名称。应该是 nvme1n1 或者 nvme2n1。如果您附加了额外的 EBS 卷,它可能会有不同的名称。

创建新的文件系统

因为这是一个新的 EBS 卷,所以它还没有文件系统。如果没有文件系统,您应该会看到如下输出:

sudo file -s /dev/nvme2n1

输出:

/dev/nvme2n1: data

让我们创建一个文件系统:

sudo mkfs -t xfs /dev/nvme2n1

确认文件系统已创建:

sudo file -s /dev/nvme2n1

输出:

/dev/nvme2n1: SGI XFS filesystem data (blksz 4096, inosz 512, v2 dirs)

在 home 下创建一个数据集目录,并挂载 EBS 卷

mkdir ~/datasets
sudo mount /dev/nvme2n1 ~/datasets

将 CIFAR10 培训数据集下载到卷中

cd ~/datasetsgit clone [https://github.com/shashankprasanna/distributed-training-ebs-multi-attach.git](https://github.com/shashankprasanna/distributed-training-ebs-multi-attach.git)source activate tensorflow_p36python ~/datasets/distributed-training-ebs-multi-attach/generate_cifar10_tfrecords.py --data-dir ~/datasets/cifar10

验证数据集是否已下载(使用sudo apt install tree安装树包)

tree ~/datasets/cifar10

输出:

/home/ubuntu/datasets/cifar10
├── eval
│ └── eval.tfrecords
├── train
│ └── train.tfrecords
└── validation
  └── validation.tfrecords

步骤 5:授权 gpu-instance-1 和 gpu-instance-2 EC2 实例之间的 SSH 通信

第一个 EC2 实例gpu-instance-1应该被授权建立到gpu-instance-2的 SSH 连接。在gpu-instance-1上运行以下步骤

在 gpu-instance-1 上创建新的密钥对

运行ssh-keygen并按两次回车键来创建一个新的密钥对。

ssh-keygenls ~/.ssh

输出:

authorized_keys id_rsa id_rsa.pub

选择公钥并将其从终端复制到剪贴板

cat ~/.ssh/id_rsa.pub

将复制的公钥添加到 gpu-instance-2 中的 authorized_key

从您的主机(不是gpu-instance-1)建立到gpu-instance-2的 SSH 连接,并将gpu-instance-1的公钥添加到gpu-instance-2的授权密钥列表中。使用步骤 4 中的说明获取 IP 地址。

ssh -i ~/.ssh/<key_pair>.pem ubuntu@<IP_ADDRESS>cat >> ~/.ssh/authorized_keys

在提示符下粘贴你的剪贴板内容并按 Ctrl+d 退出(或者你可以使用你最喜欢的文本编辑器打开~/.ssh/authorized_keys并在文件末尾粘贴密钥,保存并退出)

确认密钥已被添加

cat ~/.ssh/authorized_keys

确认您可以建立从 gpu-instance-1 到 gpu-instance-2 的 SSH 连接

从你的主机 SSH 到gpu-instance-1。并从gpu-instance-1建立到gpu-instance-2的 SSH 连接,以确保它们两个实例可以通信。

gpu-instance-1上,运行:

ssh <IP_GPU_INSTANCE_2>

您应该可以成功登录gpu-instance-2

步骤 6:在 gpu-instance-2 上挂载多附加 EBS 卷

从您的主机 ssh 到gpu-instance-2,按照与步骤 4** 相同的步骤 SSH 到gpu-instance-2,挂载 EBS 卷。**

ssh -i ~/.ssh/<key_pair>.pem ubuntu@<IP_ADDRESS>
mkdir ~/datasets
lsblk

输出:

…
…
nvme0n1 259:2 0 95G 0 disk
└─nvme0n1p1 259:3 0 95G 0 part /
nvme1n1 259:1 0 116.4G 0 disk
**nvme2n1 259:0 0 100G 0 disk**

如果您不打算在培训期间将元数据或其他调试信息写入该卷,请将 EBS 卷挂载为只读。如果您确实希望在培训期间使用相同的卷来保存其他信息,请移除下面的-o ro选项。请确保在卷上创建一个专用位置来保存您的信息,以避免由于多个实例写入同一个卷而导致潜在的数据丢失。

sudo mount -o ro /dev/nvme2n1 ~/datasets

验证您可以看到数据集(使用 sudo apt install tree 安装树包)

tree ~/datasets/cifar10

输出:

/home/ubuntu/datasets/cifar10
├── eval
│ └── eval.tfrecords
├── train
│ └── train.tfrecords
└── validation
└── validation.tfrecords

执行 TensorFlow 环境的一次性激活,以初始化~/.keras中的 keras 配置文件

source activate tensorflow_p36

步骤 7:运行分布式培训

通过运行以下命令获取gpu-instance-2的私有 IP

aws ec2 describe-instances --query 'Reservations[].Instances[].{Name:Tags[0].Value,IP:PrivateIpAddress}' --filters Name=instance-state-name,Values=running

或者在 AWS EC2 控制台上查找。

AWS EC2 控制台的屏幕截图,显示了 gpu-instance-2 的私有 IP 地址

从您的主机 SSH 到gpu-instance-1 EC2 实例,并使用您喜欢的编辑器在run-dist-training-cifar10脚本中将<PRIVATE_IP_ADDR>替换为私有 IP 地址gpu-instance-2

vim ~/datasets/distributed-training-ebs-multi-attach/run-dist-training

如果tensorflow_p36环境仍处于活动状态,则将其停用

source deactivate

开始分布式训练

sh datasets/distributed-training-ebs-multi-attach/run-dist-training-cifar10

培训应该开始了。您将在终端输出中看到,每个时期有两个条目,对应于以分布式方式在两个 EC2 实例上运行的训练。您可以通过运行nvidia-smi来监控每个实例上的 GPU 利用率。在下面的例子中,我提供了一个截图。

…
Epoch 25/30
156/156 [==============================] — 7s 46ms/step — loss: 1.2140 — acc: 0.5605 — val_loss: 1.3709 — val_acc: 0.4946
Epoch 25/30
156/156 [==============================] — 7s 47ms/step — loss: 1.2073 — acc: 0.5665 — val_loss: 1.2615 — val_acc: 0.5337 ETA: 0s — loss: 1.2065 — acc: 0.5670
Epoch 26/30
156/156 [==============================] — 7s 47ms/step — loss: 1.2005 — acc: 0.5665 — val_loss: 1.2615 — val_acc: 0.5337
Epoch 26/30
156/156 [==============================] — 7s 46ms/step — loss: 1.2034 — acc: 0.5677 — val_loss: 1.2524 — val_acc: 0.5239 ETA: 0s — loss: 1.1819 — acc: 0.5729
Epoch 27/30
156/156 [==============================] — 7s 46ms/step — loss: 1.1850 — acc: 0.5677 — val_loss: 1.2524 — val_acc: 0.5239
Epoch 27/30
156/156 [==============================] — 7s 46ms/step — loss: 1.1833 — acc: 0.5769 — val_loss: 1.1436 — val_acc: 0.5825 ETA: 0s — loss: 1.1798 — acc: 0.5774
Epoch 28/30
156/156 [==============================] — 7s 46ms/step — loss: 1.1797 — acc: 0.5769 — val_loss: 1.1436 — val_acc: 0.5825
Epoch 28/30
…

示例 2:在 16 个 GPU 上使用 144 GB Imagenet 数据集的分布式培训,使用单个 EBS 卷作为培训数据集

遵循示例 1 中的步骤 1、2 和 3,对步骤 1 进行以下更改——在 instance-type 下将 GPU 实例从g4dn.xlarge更新为**p3dn.24xlarge**p3dn.24xlarge实例包括 8 个 NVIDIA V100 GPUs。

在步骤 4 中,不下载 CIFAR10 数据集,而是下载 144 GB ImageNet 数据集,如“准备 ImageNet 数据集”一节下的文档中所述。继续执行示例 1 中的步骤 5 和 6。

完成所有设置后,运行以下脚本启动分布式培训:

cd ~/datasetsgit clone [https://github.com/shashankprasanna/distributed-training-ebs-multi-attach.git](https://github.com/shashankprasanna/distributed-training-ebs-multi-attach.git)sh datasets/distributed-training-ebs-multi-attach/run-dist-training-cifar10

显示训练期间 gpu-instance-1 和 gpu-instance-2 上 GPU 利用率的屏幕截图

限制

特性文档页面列出了多附加特性的注意事项和限制,我建议浏览一遍以避免将来可能出现的问题:https://docs . AWS . Amazon . com/AWS ec2/latest/user guide/EBS-volumes-multi . html #注意事项

机器学习工作负载的主要考虑因素是:

  • 避免让多个实例写入多附加 EBS 卷。对于数据覆盖,您没有任何保护措施。我建议以一次写入多次读取的方式使用它。
  • 该功能仅在基于硝基的实例上可用。Nitro 系统依赖于 AWS 构建的硬件和软件,通常提供更好的性能。缺点是可供选择的实例较少。对于深度学习训练,你可以选择基于 G4 的实例和p3dn.24xlarge实例。
  • 您只能将一个 EBS 卷多重连接到同一可用性分区中的实例。

分布式培训的替代方案和建议

上面的设置非常适合不想处理与容器技术和网络文件系统相关的复杂性的开发人员和数据科学家的小团队。然而,在机器学习开发过程的某个时刻,开始容器化您的工作负载并利用集群编排服务来管理大规模机器学习会有所帮助。

对于 AWS 上的集群管理培训,您有几个选择:Amazon Elastic Kubernetes Services(EKS),Amazon Elastic Container Service(ECS)。您将不得不深入 devops 领域,学习管理生产 EKS 和 ECS 集群的神秘艺术。作为机器学习的实践者,你可能不喜欢这样做。

在完全管理的一端,有 Amazon SageMaker,在我看来,这是扩展您的培训工作量的最简单和最容易的方法之一。此外,它还与亚马逊 S3 无缝集成,因此您不必管理数据集迁移。

在存储方面,您可以考虑托管一个 Amazon 弹性文件系统(EFS),并将其安装到您的所有实例中。EFS 的一个好处是它是多可用性区域(AZ ),您可以将文件系统挂载到同一区域的多个子网中的 EC2 实例。为了获得更高的性能,您可以考虑 Amazon FSx for Lustre 文件系统。FSx 给 Lustre 带来的好处是,它可以链接到现有的亚马逊 S3 桶。如果您的数据首先位于 S3,那么您就不必将数据集从 S3 迁移到 FSx 以用于 Lustre,也不必担心同步更改,这是自动为您完成的!

如果你对以上任何一种方法感兴趣,你可以按照这里的说明亲自尝试一下:distributed-training-workshop.go-aws.com/

在你走之前,另一个小建议:在你横向扩展之前总是纵向扩展****

纵向扩展是将更多的计算打包到一台机器上的过程。换句话说,从一个 EC2 实例开始,使用一个更小的 GPU,比如 G4。如果你的实验进行得很顺利,那就换一个更强大的 GPU,比如 p3.2xlarge 上的 V100。如果您想要更大的马力,那么在单个实例上获得额外的 GPU,并且您可以通过 p3.16xlarge 和 p3dn.24xlarge 获得最多 8 个 GPU。纵向扩展的优势是您不会跨越网络障碍来与其他 CPU 和 GPU 通信,这可能会增加通信延迟。一旦达到纵向扩展的极限(每个 EC2 实例 8 个 GPU),就可以开始横向扩展,即添加额外的实例。例如,如果您需要 8 个 GPU,请始终首选单个具有 8 个 GPU 的 EC2 实例,如 p3.16xlarge,而不是两个各具有 4 个 GPU 的 EC2 实例,如 p3.8xlarge。

感谢您的阅读,GitHub 上的所有代码和示例都在这里:

https://github . com/shashankprasanna/distributed-training-EBS-multi-attach . git

如果你有问题,请在推特( @shshnkp )、 LinkedIn 联系我或者在下面留言。尽情享受吧!

停止寻找借口,开始记录你的代码。现在。

原文:https://towardsdatascience.com/stop-finding-excuses-and-start-documenting-your-code-now-1c53da69eb5e?source=collection_archive---------47-----------------------

学习如何记录你的代码,并帮助他人自然地完成它

记录代码是一门艺术还是仅仅是一个简单的程序?我过去和现在都在听同样的老故事。他们没有给我们足够的时间做记录。我们太忙了,没有时间记录代码。这可能是一个方便的借口。事实是很多项目都没有文档记录,大部分代码也是如此。这将我们带到了一个危险的境地,只有在开始时做过的人才会去做,因为只有他知道事情是如何运作的。我认为这种情况对于所有中型\大型项目来说都是不可容忍的。项目和代码需要被很好地记录,所有的知识必须被编写并在团队中共享。这是幻想?我知道这可能很难实现。我知道我们在压力下工作,顾客总是匆匆忙忙。但是我们有两个选择:做正确的事情或者承受未记录代码的后果。

在本文中,我将揭示一些我在开发生涯中经历过的技巧和最佳实践。我不能保证时间会停止,在你离开办公室之前,你会有时间记录代码。我不能保证每个人都能理解你所有的代码。我不是骗子,我不能创造奇迹😄。我可以肯定的是分享我的经验,帮助您更有效地编写文档,并让这些实践与业务请求共存。我希望这有所帮助。

福图迪像素像素

在代码中记录,在编码时记录

文档例行程序的第一个目标是消除任何摩擦。传统的方法需要复杂的上下文切换,并且使文档不舒服。想想你开始创建代码,然后(可能几天后)完成它并开始记录的流程。这样做的精神压力很大。你需要记住所有的东西,找到合适的 postman 样本添加到文档中,查看代码找到片段…这需要大量的时间和精力。

我的建议是边编码边记录。当你在做某件事的时候,你会把它写下来。这意味着没有上下文切换。这样可以节省时间,让你一步步“冲洗”思路。它还能在您工作时帮助您,因为您正在构建的文档也会对您有所帮助。

许多 IDE 允许你编写混合了代码的文档,并用一些魔法(或工具……)自动创建文档。

我不相信你需要把大脑放在哪里的自动化。我更喜欢在需要的地方使用常规的代码注释,并使用单独的文档来解释代码是如何工作的。

在“代码本身内部”记录代码是有帮助的,因为它减少了工具之间的摩擦(你不需要在工具之间切换)。在大多数情况下,您的文件可以用 markdown 编写,并以人的形式查看,因此这是一个好的解决方案。

不要把今天能做的事情推迟到明天

在我的 IDE 上,我总是找到一种方法来管理代码附近的文档,并且在我处理它的时候记录我正在做的事情。例如,如果我准备了一个 API,并且我正在用 Postman 测试它,我将把这个例子复制粘贴到 markdown 文件上,因为它是稳定的,注释输入和输出。当我开发它的时候,我会花一分钟来做这件事。如果我在那之后几天做,我可能会花半个小时来仔细检查 API 调用,记住我对这样的输入和输出的意思…这种实践将帮助你和你的团队保持文档更新。

更好的评论是没有写出来的

当我们谈论代码本身时,第一条规则是,如果你需要对一行代码进行注释,那就有问题了。理论上,每一行代码、每一个过程名、每一个变量名都应该被选择成不言自明的。在现实世界中,这并不总是可能的,或者我们有违反直觉的要求。这就是我们被迫注释部分代码的原因。你解释得越少,读者就会越清楚。任何时候你打算评论一段代码,你都会问自己“为什么”如果是因为有害代码,那就改吧。

PS:这并不意味着你不必对代码进行评论😄。我的意思是,第一个选项是写不需要注释的好代码,第二个选项是对它进行注释。编写不可理解的代码并且不做注释是不可取的。

一张图胜过千言万语

有可能(成千上万)的情况下,事情太复杂,无法用语言来解释。即使你能,难以解释的事情往往也难以理解。如果可以的话,在你的解释中添加一张图。这很有帮助。这对你很有用,因为它有助于修正想法,并且对将来阅读文档的人来说是纯金(你可能就是其中之一!).

我们不需要艺术品。我们只需要一幅画。所以,尽可能少花时间在审美问题上,把注意力放在你放入图表的信息上。信息很重要,只有这个。我经常使用 draw.io 平台,这个平台简单易用,免费,只需要一个浏览器就可以工作。这是一个很好的解决方案,但需要一点努力。您需要将图表保存到云中并下载图像,或者将图表作为文件保存到您的代码库中。在任何情况下,您都需要手动步骤和摩擦(打开文件、绘制、保存、重新绘制、修复…)。另一个可以使用的解决方案是一种图表的 markdown(Mermaid,PlantUML,但是还有其他的),它可以直接集成到 markdown 文件中。下面仅举一个例子:

graph TD;     
A-->B;     
A-->C;     
B-->D;     
C-->D;

会产生这样一个自上而下的流程:

用美人鱼制作的一个例子

要呈现图表,您需要您的 markdown 呈现支持这种语法,或者您可以安装一些 web 浏览器扩展。

带什么回家

我们可以用一句话来总结记录代码的必要性:

Verba volant,scripta manent

这个拉丁句子的意思是,你所写的保持不变,所讲述的……是不稳定的。我们为他人,也为我们自己记录代码。想想你,“明天的你”,当你在那个棘手的功能上工作的时候。或者对自己说,插手你同事的工作。你更愿意开始做逆向工程来满足功能需求(如果功能端有写的话)还是干脆看个解释?

记录不是一个选项。你用书面交流的越多,留下的痕迹就越多。开始写而不是说是连续记录的第一步。下一步是找到一个过程和一些工具来帮助我们利用每天的每一个小贡献。

要有好的文档,你需要合适的工具,合适的规则,但最重要的是。你需要培养正确的习惯。

如果做得正确,记录代码是一项投资,它会让你节省更多的时间\金钱。如果只是因为我们需要去做而去做,它并不会带来结果,它只是一种成本。

停止置换功能

原文:https://towardsdatascience.com/stop-permuting-features-c1412e31b63f?source=collection_archive---------14-----------------------

众所周知,荷马·辛普森是一个头脑简单的人,时不时会做出一些愚蠢的事情。在这里,他决定用煤气炉烹饪面包、熏肉和鸡蛋,因为这是一堆篝火;不适合这种用途的工具。我们发现看起来很有趣,但同时,我们倾向于在数据科学中做类似的事情。不要像荷马那样,使用适当的工具。《辛普森一家》(《荷马史诗》第七季第 17 集)中的这个镜头被认为是合理使用

数据科学家需要为各种任务进行特征重要性计算。重要性可以帮助我们了解我们的数据是否有偏差,或者模型是否有缺陷。此外,重要性经常用于理解底层流程和制定业务决策。事实上,该模型最重要的特性可能会给我们进一步的特性工程带来灵感,并对正在发生的事情提供见解。

现在有很多方法可以计算特征的重要性。它们中的一些基于模型的类型,例如,线性回归的系数、基于树的模型中的增益重要性、或者神经网络中的批量范数参数(BN 参数通常用于 NN 修剪,即神经网络压缩;例如,这篇论文描述了 CNN 网络,但是同样的逻辑也适用于全连接网络。虽然其他方法是“通用的”,但它们可以应用于几乎任何模型:如 SHAP 值、排列重要性、丢弃-再学习方法等方法。

虽然模型的黑盒拆箱是模型开发流程中不可或缺的一部分,但 Harmanpreet 等人进行的一项研究(解读可解释性:理解数据科学家对机器学习可解释性工具的使用)表明,并非所有的数据科学家都知道如何正确地完成这项工作。这些方法的可用性和简单性使它们成为“金锤”。事实上,如果一个人可以运行“pip install lib,lib.explain(model)”,为什么要为背后的理论费心呢?

在这篇文章中,我想提出一个在寻找有影响的特征时过度使用排列重要性的偏见。我将说明在某些情况下,排列重要性会给出错误的、误导性的结果。

排列重要性

排列重要性是一种常用的特征重要性类型。它显示了用随机排列的值替换该特征时得分的下降。它是通过几个简单的步骤计算出来的。

  1. 带训练数据的训练模型 X_trainy _ train
  2. 对一个训练数据集X _ trainy _ hat进行预测,并计算得分— score (得分越高越好);
  3. 为了计算每个特征的置换重要性 feature_i ,执行以下操作:
    (1)置换训练数据集中的 feature_i 值,同时保持所有其他特征“原样”——X _ train _ permuted
    (2)使用 X_train_permuted 和之前训练的模型— y_hat_permuted 进行预测;
    (3)计算置换数据集上的得分—score _ permuted
    (4)特征的重要性等于 score_permuted — score 。delta 越低,特征越重要。
  4. 该过程被重复几次以减少随机排列的影响,并且分数或等级在运行中被平均。

说明计算的代码片段:

排列重要性易于解释、实现和使用。尽管计算需要对训练数据进行 n 次预测,但与模型再训练或精确的 SHAP 值计算相比,这不是实质性的操作。此外,排列重要性允许您选择要素:如果排列数据集的得分高于正常得分,这是移除该要素并重新训练模型的明显信号。由于这些原因,排列重要性被广泛应用于许多机器学习流水线中。

问题

虽然对于模型解释来说,排列重要性是一个非常有吸引力的选择,但它有几个问题,尤其是在处理相关要素时。贾尔斯·胡克和卢卡斯·门奇在他们的论文《请停止置换特征的解释和选择》中将它们结合起来:

  1. 施特罗布尔等人(2007) 调查分类并注意到,基于购物车构建树中置换出袋(OOB)误差的重要性测量偏向于与其他特征相关和/或具有许多类别的特征,并进一步表明自举夸大了这些影响;
  2. Archer 和 Kimes (2008) 探索了类似的设置,并注意到当真实特征(实际上与响应相关的特征)与噪声特征不相关时,性能得到改善;
  3. Nicodemus 等人(2010) 在大规模模拟研究中调查了这些特征偏好的主张,并再次发现 OOB 测量高估了相关预测因子的重要性。

对此可能的解释是模型的外推。假设,该模型使用两个高度正相关的特征 x1x2 进行训练(下图左边的图)。为了计算特征 x1 的重要性,我们对特征进行混洗,并对“混洗”后的点(中心图上的红点)进行预测。但是模型没见过左上角和右下角有 x1 的训练例子。因此,为了进行预测,它必须外推至以前未见过的区域(右图)。所有模型的推断都很糟糕,因此做出了意想不到的预测。这些“来自新区域的点”强烈影响最终得分,并因此影响排列重要性。

图一。排列重要性问题的直观说明——未知区域

Giles Hooker 和 Lucas Mentch 提出了几种替代排列重要性的方法:

  1. 条件变量重要性-根据剩余要素的值有条件地置换要素,以避免“看不见的区域”;
  2. 丢弃变量重要性—相当于雷等人在中探讨的留一个协变量的方法:丢弃特征、重新训练模型、比较分数。
  3. 置换和重新学习的重要性——该方法在 Mentch 和 Hooker 中采用:置换特征、重新训练模型、比较分数。

实验

为了理解特征相关性如何严重影响排列重要性和其他特征重要性方法,我进行了以下实验。

实验设置

首先,我生成了一个具有指定数量的特征和样本的正态分布数据集( n_features =50,n _ samples= 10000)。所有特征的平均值等于 0,标准偏差等于 1。所有数据集特征通过 max_correlation 关联相互关联。

生成数据集后,我给每个特征添加了均匀分布的噪声。每个特征的噪声幅度从[-0.5 噪声幅度最大值,0.5 噪声幅度最大值]噪声幅度最大值=变量之间的均匀分布中随机选择。这样做是为了降低特征相关性。任务的特性已经准备好了!

现在我们需要创建一个目标。对于每个特征,我生成了一个权重,它是从具有指定伽马和比例参数的伽马分布中采样的(伽马 =1,比例 =1)。选择伽马分布是因为它看起来非常类似于典型的特征重要性分布。然后将每个特征权重除以权重之和,使权重之和等于 1。这样做是为了减少随机权重生成对最终结果的影响。

图二。左侧为随机森林要素重要性(旋转)的示例。每个条形显示了 ML 模型中一个特性的重要性。右边是排序的总和比例伽马分布的条形图。每个条显示了特征在目标代的线性组合中的权重,这本身就是特征重要性。左图来源

然后,目标的 logit 被计算为特征和相应特征权重的线性组合(随机选择特征权重的符号)。sigmoid 函数应用于目标的标准标度 logit。为了得到标签,我对结果进行了四舍五入。目标准备好了!

对于生成的数据集和目标,我使用以下参数训练了一个 LightGBM 模型:

learning_rate: 0.01
n_estimators: 100
random_state: 42

所有其他参数都是默认值。我使用内置的增益重要度、SHAP 重要度和排列重要度(排列重复五次,求增量分数的平均值)来计算每个特性的重要度。

然后,我计算了计算的重要性和特性的实际重要性之间的 Spearman 等级相关性。实际重要性等于等级(-权重)。最可能的相关性是 1.0,即要素重要性与实际重要性(要素权重)处于同一顺序。

每个实验的数据(数据集相关性统计、内置增益重要性的模型重要性和特征的实际重要性之间的 Spearman 等级相关性、SHAP 重要性和排列重要性)被保存用于进一步分析。使用不同的种子和 max_correlationnoise_magnitude_max 的不同组合,实验运行五十次。我还用“丢弃并重新学习”和“置换并重新学习”的方法进行了相同的实验,但是由于需要大量的计算,只进行了五次。

实验的代码和分析可以在项目的资源库中找到:

[## DenisVorotyntsev/StopPermutingFeatures

这个库包含了我在关于置换重要性的博客文章中描述的实验的代码——停止置换…

github.com](https://github.com/DenisVorotyntsev/StopPermutingFeatures)

例子

为了让你熟悉正在发生的事情,我将举例说明一个实验。实验图解笔记本可以在这里找到:实验图解。实验的参数是:

TASK = "classification"
OBJECTIVE = "binary"
METRIC = roc_auc_scoreMU = 0
VAR = 1
N_FEATUES = 50
N_SAMPLES = 10_000NOISE_MAGNITUDE_MAX = 1
SEED = 42

生成的数据集的相关矩阵的一部分:

图 3。要素数据集 R2 相关矩阵的一部分

我们可以看到,这些特征彼此之间高度相关(平均绝对相关系数约为 0.96)。相关性统计:

图 4。特征数据集相关性的统计。abs_*前缀代表相关度的绝对值(注意:数据集中的要素可能相互负相关或正相关)

生成要素权重的分布:

图 5。实际特征权重分布。只有几个特性是重要的,其余的都不重要。ML 任务中的常见情况

特征的计算重要性和实际重要性之间的计算 Spearman 等级相关性:

Model's score [train data]: 0.9998
Permutation spearman corr: 0.5724
SHAP spearman corr: 0.4721
LGB gain spearman corr: 0.4567

以及预期和计算功能重要性等级的说明:

图 6。预期和计算的等级(排列重要性),NOISE_MAGNITUDE_MAX=1

我们可能会在这里看到几个问题(用绿色圆圈标记):

  1. 最重要和第二重要的功能等级不匹配
  2. 根据排列重要性,第三最重要的特征应该是第九;
  3. 如果我们相信排列的重要性,那么实际的第 8 个重要特性会下降到第 39 位。

以下是相同实验参数的预期和计算的特征重要性等级的图示,除了噪声 _ 幅度 _ 最大值,其现在等于 10(ABS _ 相关性 _ 平均值从 0.96 下降到 0.36):

Model's score [train data]: 0.9663
Permutation spearman corr: 0.6430
SHAP spearman corr: 0.7139
LGB gain spearman corr: 0.6978

图 7。预期和计算的等级(排列重要性),噪声 _ 幅度 _ 最大值=10

仍然不完美,但即使视觉上更好,如果我们谈论的是十大最重要的功能。

结果

我进行了描述的实验和绘图结果,这在本节中介绍。“排列对 SHAP 对增益”实验总共进行了 1200 次,而“排列对再学习”实验进行了 120 次。

置换 vs SHAP vs 增益

在这一小节中,我比较了使用排列重要性、SHAP 值和内置增益计算的特征重要性排名。

从下面的图中,我们可以看到,实际特征重要性之间的相关性以及使用排列、SHAP 值和增益计算的相关性与预期的特征相关性的平均值和最大值负相关。排列重要性受高度相关特征的影响最大。使用内置增益的 SHAP 计算的重要性没有区别。

此外,我们可以看到,实际特征重要性和计算值之间的相关性取决于模型的分数:分数越高,相关性越低(图 10-Spearman 特征等级相关性= f(模型的分数))。不清楚为什么会发生这种情况,但我可以假设,更多的相关特征导致更准确的模型(从图 11 可以看出,模型的得分= f(特征相关性的平均值)),因为更密集的特征空间和更少的“未知”区域。

图 8——Spearman 特征等级相关性= f(特征相关性平均值)

图 9-Spearman 特征等级相关性= f(最大特征相关性)

图 10——Spearman 特征等级相关性= f(模型得分)

图 11 —模型得分= f(特征相关性平均值)

置换与重新学习

在这一小节中,我比较了排列的重要性和再学习的方法。

令人惊讶的是,在所有相关性中,重新学习方法的表现明显比排列差,这可以从下面的图中看出。此外,重新学习方法花费了大约 n_features 倍的时间来运行。

图 12——Spearman 特征等级相关性= f(特征相关性平均值)

图 13-Spearman 特征等级相关性= f(最大特征相关性)

结论

  1. 不要使用排列重要性来解释基于树的模型(或任何在看不见的区域内插得不好的模型)。
  2. 请改用 SHAP 值或内置增益重要性。
  3. 不要使用“置换并重新学习”或“丢弃并重新学习”的方法来寻找重要的特性。

摘要

在这篇文章中,我描述了排列重要性方法和与之相关的问题。我展示了高度相关的特性如何以及为什么会影响排列的重要性,这将给出误导性的结果。我进行了一个实验,实验表明排列重要性受高度相关特征的影响最大(在使用 SHAP 值和增益计算的重要性中)。我还表明,尽管重新学习的方法有望成功,但它们的表现不如排列重要性,并且需要更多的时间来运行。

我希望这篇文章能帮助数据科学家正确地解释他们的模型。

承认属实

帖子的主题和进行的实验受到了贾尔斯·胡克和卢卡斯·门奇所做的“请停止置换功能的解释和替代品”的启发。

附加链接

如果你喜欢这个,你可能会有兴趣阅读我的另一篇关于石灰重要性问题的文章:

[## 酸橙有什么不好

虽然是解释任何分类器预测的最流行的方法之一,石灰有几个主要的…

towardsdatascience.com](/whats-wrong-with-lime-86b335f34612)

停止在 CSV 中保存 pandas 数据帧

原文:https://towardsdatascience.com/stop-persisting-pandas-data-frames-in-csvs-f369a6440af5?source=collection_archive---------3-----------------------

pickle、parquet 和其他产品的优势——更快、更可靠、更高效

CSV 是一种很好的数据交换格式。它在世界各地都可以理解,并且可以在普通记事本中编辑。这并不意味着它适合持久化所有数据帧。CSV 的读写速度很慢,它们占用更多的磁盘空间,最重要的是 CSV 不存储关于数据类型的信息。

CSV 的优势:

  • 普遍可以理解
  • 大多数编程语言都支持解析和创建

CSV 的缺点:

  • 更大的磁盘使用率
  • 读写速度较慢
  • 不要存储关于数据类型的信息

伊利亚·扎依采夫对各种熊猫坚持方法的速度和内存使用做了很好的分析。当我们编写自动化性能测试程序时,我会在最后谈到性能。首先,我想关注一件不同的事情——这些文件格式如何处理各种数据类型。

熊猫数据类型

Pandas 支持丰富的数据类型,其中一些数据类型具有多种子类型,以便更有效地处理大数据框。基本数据类型包括:

  • object —字符串或混合类型
  • string自熊猫 1.0.0
  • int —整数
  • float —浮点数
  • bool —布尔值真和假
  • datetime —日期和时间值
  • timedelta —两个日期时间之间的时间差
  • category —有限的值列表存储在高效内存查找中

由于 pandas 使用 numpy 数组作为其后端结构,int s 和float s 可以区分为更高效的内存类型,如int8int16int32int64unit8uint16uint32uint64以及float32float64

CSV 不存储关于数据类型的信息,您必须用每个read_csv()来指定它。在没有告知 CSV 阅读器的情况下,它将推断所有整数列为效率最低的int64,浮点为float64,类别将作为字符串和日期时间加载。

# for each loaded dataset you have to specify the formats to make DataFrame efficientdf = pd.read_csv(new_file,
                 dtype={"colA": "int8",
                        "colB": "int16",
                        "colC": "uint8",
                        "colcat": "category"},
                 parse_dates=["colD","colDt"])

**TimeDeltas**作为字符串存储在 CSV-5 days +18:59:39.000000中,你必须编写一个特殊的解析器将这些字符串转换回熊猫的 timedelta 格式。

Timezones看起来像2020-08-06 15:35:06-06:00,在read_csv()中也需要特殊处理。

使用不带参数的 read_csv()比较原始数据类型和自动推断的类型

CSV 替代方案

幸运的是,csv 不是持久存储数据帧的唯一选择。阅读熊猫的 IO 工具你看到一个数据帧可以写成多种格式,数据库,甚至剪贴板。

你可以用这个 GitHub 笔记本自己运行代码。最后,我将详细描述数据是如何创建的,并使用一个真实的数据帧指导您完成性能测试和健全性检查。

在本文中,我们用几个参数测试了许多类型的持久化方法。由于 Plotly 的交互功能,您可以探索任何方法的组合,图表将自动更新。

Pickle 和 to_pickle()

Pickle 是用于对象序列化的 python 原生格式。它允许 python 代码实现任何类型的增强,如pep 574pickle 带外数据缓冲区中描述的最新协议 5。

这也意味着在 Python 生态系统之外进行酸洗是困难的。然而,如果你想存储一些预处理过的数据以备后用,或者你不想在没有直接使用这些数据的情况下浪费掉几个小时的分析工作,就把它们保存起来。

# Pandas's to_pickle method
df.to_pickle(path)

.to_csv() .to_pickle()相反,方法只接受 3 个参数。

  • path —数据将存储在哪里
  • compression —允许选择多种压缩方式
  • [protocol](https://docs.python.org/3/library/pickle.html#data-stream-format) —更高的协议可以更高效地处理更广泛的数据

泡菜的优点:

  • 比 CSV 快(CSV 写入的 5–300%,CSV 读取的 15–200%,具体取决于压缩方法)
  • 生成的文件较小(约为 csv 的 50%)
  • 它保留了关于数据类型的信息(100%)
  • 不需要指定过多的参数

泡菜的缺点:

  • 原生于 python,所以它缺乏对其他编程语言的支持
  • 即使跨不同 python 版本也不可靠

Pickle 能够序列化 100%的 padnas 数据类型

当您读取在 python 的新版本中创建的 pickle 时,您会得到一个错误:

**ValueError**: unsupported pickle protocol: 5

拼花和 to_parquet()

Apache Parquet 是 Hadoop 生态系统中使用的压缩二进制列存储格式。它允许序列化复杂的嵌套结构,支持按列压缩和按列编码,并提供快速读取,因为它不需要读取整个列,因为您只需要部分数据。

# Pandas's to_parquet method
df.to_parquet(path, engine, compression, index, partition_cols)

.to_parquet()方法只接受几个参数。

  • path —存储数据的位置
  • engine — pyarrow 或 fastparquet 引擎。pyarrow通常更快,但它与timedelta格式斗争。fastparquet可以明显变慢。
  • compression —允许选择多种压缩方式
  • index —是否存储数据帧的索引
  • partition_cols —指定列分区的顺序

拼花地板的优点:

  • 比 CSV 快(从 10 行开始,pyarrow 大约快 5 倍)
  • 生成的文件更小(约为 CSV 的 50%)
  • 它保存关于数据类型的信息(pyarrow 不能处理 timedelta,而较慢的 fastparquet 可以)
  • Hadoop 生态系统中的广泛支持允许在许多分区中进行快速过滤

拼花地板的缺点:

  • 不支持重复的列名
  • pyarrow 引擎不支持某些数据类型

更多细节请访问熊猫 IO 页面

Excel 和 to_excel()

有时候,将数据导出到 excel 中很方便。它以最慢的读写速度为代价,增加了易于操作的优势。它还忽略了许多数据类型。Timezones根本无法写入 excel。

# exporting a dataframe to excel
df.to_excel(excel_writer, sheet_name, many_other_parameters)

有用的参数:

  • excel_writer —熊猫 excel writer 对象或文件路径
  • sheet_name —将输出数据的工作表的名称
  • float_format — excel 的原生数字格式
  • columns -别名数据框列的选项
  • startrow —向下移动起始单元格的选项
  • engineopenpyxlxlsxwriter
  • freeze_panes —冻结行和列的选项

excel 的优势:

  • 允许自定义格式和单元格冻结
  • 人类可读和可编辑的格式

excel 的缺点:

  • 非常慢的读/写速度(慢 20/40 倍)
  • 限制为 1048576 行
  • 带时区的日期时间序列化失败

更多关于熊猫 IO 页面的信息。

excel 的性能测试结果。只有 54%的列保留了原始的数据类型,它占用了 CSV 的 90%的大小,但是写的时间多了 20 倍,读的时间多了 42 倍

HDF5 和 to_hdf()

使用内部文件式结构的压缩格式,适用于巨大的异构数据。如果我们需要随机访问数据集的各个部分,这也是非常理想的。如果数据存储为table (PyTable),您可以使用store.select(key,where="A>0 or B<5")直接查询 hdf 存储

# exporting a dataframe to hdf
df.to_hdf(path_or_buf, key, mode, complevel, complib, append ...)

有用的参数:

  • path_or_buf —文件路径或 HDFStore 对象
  • key—商场内的团体标识
  • mode —写入、附加或读取-附加
  • formatfixed用于快速写入和读取,而table允许仅选择数据的子集

HDF5 的优势:

  • 对于某些数据结构,其大小和访问速度可能非常惊人

HDF5 的缺点:

  • 数据帧可以非常大(甚至比 csv 大 300 倍)
  • HDFStore 对于写入不是线程安全的
  • fixed格式无法处理分类值

SQL 和 to_sql()

将数据持久存储到数据库中通常很有用。像sqlalchemy这样的库致力于这项任务。

# Set up sqlalchemy engine
engine = create_engine(
    'mssql+pyodbc://user:pass@localhost/DB?driver=ODBC+Driver+13+for+SQL+server',
    isolation_level="REPEATABLE READ"
)# connect to the DB
connection = engine.connect()# exporting dataframe to SQL
df.to_sql(name="test", con=connection)

有用的参数:

  • name —SQL 表的名称
  • con —通常由sqlalchemy.engine连接引擎
  • chunksize —可以选择按 chunksize 批量加载数据

SQL 的优势:

  • 比在磁盘上持久存储慢(读取 10 次/写入 5 次,但这可以优化)
  • 所有程序员都能理解数据库

SQL 的缺点:

  • 有些数据格式没有保留——类别、整数、浮点和时间增量
  • 根据数据库的不同,性能可能会很慢
  • 在某些情况下,您可能很难建立数据库连接

如果你想增加.to_sql()的写时间,试试 Kiran Kumar Chilla 在加速批量插入文章中描述的方法。

[## 使用 Pandas 和 Python 加速 SQL db 的批量插入

本文详细介绍了:1 .使用 pandas 和 pyodbc 将数据帧写入数据库的不同方法 2。如何…

medium.com](https://medium.com/analytics-vidhya/speed-up-bulk-inserts-to-sql-db-using-pandas-and-python-61707ae41990)

羽化和羽化()

Feather 是一种轻量级格式,用于存储数据框和箭头表。这是如何存储数据的另一种选择,相对较快,文件较小。它没有包括在测量中,因为引擎在相当长的时间内锁定文件,很难重复几次性能测试。如果您计划将数据框持久化一次,feather 可能是一个理想的选择。

其他方法

熊猫提供了更多的坚持和阅读方法。我省略了 json 和 fix-width-file,因为它们具有类似 csv 的特征。可以尝试用.to_gbq()或者stata格式直接写到谷歌大查询。新的格式肯定会出现,以满足与各种云提供商通信的需求。

多亏了这篇文章,当我把一行程序复制到电子邮件、excel 或 google doc 时,我开始喜欢上了.to_clipboard()

特性试验

许多方法都比 CSV 有优势,但是当 CSV 在世界范围内如此容易理解时,是否值得使用这些不寻常的方法。让我们来看看表演。

在性能测试期间,我关注 4 个关键指标:

  • data type preservation —读取后有多少%的列保持原始类型
  • compression/size —文件有多大,以 csv 的百分比表示
  • write_time —编写这种格式需要多长时间,占 csv 编写时间的%
  • read_time —读取此格式需要多长时间,占 csv 读取时间的%

为此,我准备了一个包含 50K 随机数、字符串、类别、日期时间和布尔值的数据集。数值范围来自 numpy 数据类型概述

data = []
for i in range(1000000):
    data.append(
        [random.randint(-127,127),  # int8
         random.randint(-32768,32767),  # int16
        ...

产生随机样本是几乎每个测试都要用到的技巧。

你可以在 GitHub 笔记本中查看生成随机字符串和日期的支持功能,这里我只提一个:

def get_random_string(length: int) -> str:
    """Generated random string up to the specific lenght"""

    letters = string.ascii_letters
    result_str = ''.join([random.choice(letters) for i in range(random.randint(3,length))])
    return result_str

生成数据帧的完整代码描述如下:

生成随机数据,并在 7 次迭代中测量读/写速度

一旦我们有了一些数据,我们希望通过不同的算法反复处理它们。您可以分别编写每个测试,但是让我们将测试压缩成一行:

# performance test
performance_df = performance_test(exporting_types)# results
performance_df.style.format("{:.2%}")

performance_test 函数接受一个带有测试定义的字典,如下所示:

d = { ..."parquet_fastparquet": {
        "type": "Parquet via fastparquet",
        "extension": ".parquet.gzip",
        "write_function": pd.DataFrame.to_parquet,
        "write_params": {"engine":"fastparquet","compression":"GZIP"},
        "read_function": pd.read_parquet,
        "read_params": {"engine":"fastparquet"}
    }
... }

字典包含应该运行的功能,例如pd.DataFrame.to_parquet和参数。我们迭代字典,一个接一个地运行函数:

path = "output_file"
# df is our performance test sample dataframe# persist the df
d["write_function"](df, path, **d["write_params"])# load the df 
df_loaded = d["read_function"](path, **d["read_params"]

我将结果存储到一个数据帧中,以便利用。Express 用几行代码显示结果的能力:

# display the graph with the results
fig = pe.bar(performance_df.T, barmode='group', text="value")# format the labels
fig.update_traces(texttemplate='%{text:.2%}', textposition='auto')# add a title
fig.update_layout(title=f"Statistics for {dataset_size} records")
fig.show()

性能测试结果。数据格式保存测量成功百分比以及大小和速度与 csv 进行比较。

[## 用 Plotly 可视化。快递:综合指南

一个数据集和 70 多个图表。交互性和动画通常只需一行代码。

towardsdatascience.com](/visualization-with-plotly-express-comprehensive-guide-eb5ee4b50b57)

健全性检查

在随机样本上测试东西对于获得你的应用程序或工具有多好的第一印象是有用的,但是一旦它必须符合现实。为了避免任何意外,您应该在真实数据上尝试您的代码。我选择了我最喜欢的数据集——美国证券交易委员会季度数据转储——并对其进行性能测试。我已经获得了非常相似的结果,这使我相信我的假设不是完全错误的。

对 SEC 季度数据转储的 8 列进行健全性检查的结果证实了性能测试的结果。

[## 股票基本面分析:SEC 季度数据汇总的 EDA

大熊猫 2020 SEC 申报的探索性数据分析

towardsdatascience.com](/stock-fundamental-analysis-eda-of-secs-quarterly-data-summary-455e62ff4817)

结论

尽管 pickle 显然赢得了性能竞赛,但在一些用例中,您可能更愿意选择另一种格式。我们还有一个非常特殊的数据集,在真实数据上,性能可能会有所不同。

请随意使用代码(GitHub) ,并在您喜欢的数据集上尝试性能。对我个人来说,当我存储预处理数据集时,.to_pickle()很棒,因为我不必担心数据格式,我只需将read_pickle()和工作时间具体化到我的笔记本上。

[## python 交叉验证的完整指南及示例

sklearn 交叉验证的示例和使用案例解释了 k 折叠、洗牌、分层以及它如何影响…

towardsdatascience.com](/complete-guide-to-pythons-cross-validation-with-examples-a9676b5cac12) [## 当数据集符合内存时,是否有比熊猫更好的东西?

探索 Vaex,Dask,PySpark,摩丁和朱莉娅

towardsdatascience.com](/is-something-better-than-pandas-when-the-dataset-fits-the-memory-7e8e983c4fe5)

canva.com 制造

If you want to create inspiring infographics like the one above, use [canva.com](https://canva.7eqqol.net/WnbXZ) (affiliate link, when you click on it and purchase a product, you won't pay more, but I can receive a small reward; you can always write canva.com to your browser to avoid this). You can do more than infographic and some features are available for free.

基于逻辑回归的停车标志检测——第一部分

原文:https://towardsdatascience.com/stop-sign-detection-using-logistic-regression-part-i-315f7c0c8636?source=collection_archive---------37-----------------------

在本教程中,我们将使用二进制逻辑回归来训练 Python 中的红色分类器。

为了保持教程相对简短,我将它分为两部分——第一部分:使用逻辑回归创建颜色分类器。第二部分:使用从颜色分类器获得的二值掩码检测停车标志。

照片由免费使用声音Unsplash

任何机器学习问题的第一步都涉及到访问一个好的训练数据集——在我们的例子中,我们需要仅由红色组成的图像(正样本),以及包含除红色之外的其他颜色的图像(负样本)。我能够创建一个数据集,它有一个不同的红色图像池,这些图像是在不同的照明条件下从停车标志中提取的。这些光照变化将允许我们训练相对健壮的颜色分类器。除了红色之外的颜色被包括在训练集中作为负样本。你可以在我的 GitHub 上找到数据集:https://github.com/MariaHarris24/StopSign_detection

在我说明本教程的编码部分之前,我们首先需要理解逻辑回归的基本原理和训练它所涉及的数学。

作为分类问题的颜色分割

逻辑回归是一种判别模型,即,它模拟条件概率分布P(y | x;w) 使用 Sigmoid 函数:

这里,' x 是指单个像素值,而' y '是标量(-1 或 1),是与像素 x 相关联的标签,' ω '是训练时需要学习的权重参数。

下面您可以看到 sigmoid 函数的数学和图形表示:

Sigmoid 函数——作者图片

sigmoid 函数具有将连续值转换为伯努利(离散)分布的特性,而伯努利分布又可用于分类目的。从上图中我们可以看到,对于 k 的较大值,该函数将产生 1,对于 k 的较小值,该函数将产生 0。需要注意的是,当我们处理两个类之间的分类时,即二元分类(这是我们的情况)时,使用 sigmoid。对于两个以上/多类分类,使用 softmax 函数。

现在,我们已经对 sigmoid 如何工作有了直观的了解,我们现在需要估计权重参数“ω”,以便我们能够最大化条件概率 P(y | x;ω) —从数学上讲,这可以写成如下形式:

上面的等式是 MLE 版本,我不会在文章中涉及这个主题。我只是想提一下,这样你就可以验证这个等式的来源了。

对于上面的等式,可以通过使用梯度下降来获得‘ω’的最佳值。由于梯度下降涉及到 最小化 一个函数;因此,我们将使用 log p 的 (y | x;ω)作为最小化的函数,这在数学上等同于上面的等式。我们现在可以为我们的问题写出梯度下降方程如下:

给出梯度下降的快速入门;这是一种优化技术,可用于迭代寻找函数的最小值。这个最小值可能是/可能不是全局最小值。梯度下降背后的直觉是,我们对我们试图寻找最小值的函数求导。这个导数本质上是函数的切线/斜率,我们的目标是向与此相反的方向移动,即负梯度的方向,直到我们达到最小值。收敛速度由称为学习速度"α"-的参数决定,这决定了每次迭代过程中的步长(移动量)。

太好了!我们已经奠定了这一切背后的基础数学,现在我们可以实际编写代码来训练我们的颜色分类器。

导入数据集:

首先,我们需要加载和重塑我们的训练数据。下面你可以找到一个函数的代码,这个函数将从指定的文件夹中读取图像,并将它们堆叠成一个 Nx3 矩阵。这里,单独的三个通道(RGB)将用作特征,三个 RGB 通道中每个通道的像素值将填充特征空间,这就是为什么我们有一个 Nx3 矩阵。此外,该函数还将为每个像素值生成适当的标签:红色为 1,其他颜色为-1。请确保为“label_val”参数传入正确的值,因为这决定了对应于像素的标签将占用什么值。

培训:

一旦我们加载了训练数据,下一步就是使用梯度下降来训练颜色分类器(参考下面的代码)。该函数返回参数“ω”的向量(3x1)。我们将使用这个参数来描述我们在测试部分中解释的分类边界。您可以更改学习率和迭代次数。为了检查收敛性,我绘制了以前的ω和现在的ω之间的差异。如果它们之间的绝对差异在几次迭代中非常小,这表明我们很可能已经获得了最小值。但是,一定不要通过大量迭代训练分类器来过度拟合数据。

还有一点要澄清的是,梯度下降的代码实现与我之前引用的公式不同;这是因为代码是矢量化的格式(效率要高得多),而不是前面提到的基于元素的公式。

测试:

逻辑回归生成一个线性决策边界,由等式x .ω= 0(x 和ω的点积)描述。因此,对于 x.ω≥0,即位于或高于线性边界的像素值将被预测为红色正像素,而对于 x.ω < 0,该像素将被预测为红色负像素。这可以通过参考下图的两个特征来更好地理解:

使用 x.w=0 的点分类示例-按作者分类的图像

这一步的代码非常简单。我们将测试图像和ω发送到一个函数,该函数执行两者之间的点积,然后根据前面提到的点积标准对像素进行分类。对于分类步骤,我们将为预测为红色的像素分配值 255,为预测为非红色的像素分配值 0,这样我们将获得二进制掩码。该函数的代码如下所示:

原始图像及其二进制遮罩如下所示。

左图:原图(照片由威尔·波拉达Unsplash 上拍摄)。右图:二进制掩码

正如你所看到的,我们的分类器能够分割红色像素。接下来,我们需要使用某种形状检测标准来辨别停车标志的形状。这将在第二部分讨论。感谢您的阅读!

停止测试正常性

原文:https://towardsdatascience.com/stop-testing-for-normality-dba96bb73f90?source=collection_archive---------18-----------------------

拉斐尔·比斯卡尔迪在 Unsplash 上拍摄的照片

常态测试是误导和浪费你的时间!

我看到许多数据科学家使用诸如夏皮罗-维尔克测试和科尔莫戈罗夫-斯米尔诺夫测试来检验正态性。别这样。别说了。如果你还不相信(我不怪你!),让我告诉你为什么这些是浪费你的时间。

我们为什么要在乎常态?

我们应该关心常态。这是一个重要的假设,支撑着各种各样的统计程序。我们应该始终确信我们的假设,并努力检查它们是否正确。然而,正态性检验不是我们这样做的方式。

然而,在大样本(n > 30)中,我们作为数据科学家的大部分工作都基于通常适用的中心极限定理,我们无需担心数据的正态性。但是在它不适用的情况下,让我们考虑如何在一系列不同的样本中检验正态性。

小样本的正态性检验

首先让我们考虑一个小样本。假设 n=10。让我们看看这些数据的直方图。

x 的直方图(n=10)。(图片由作者提供)

这是正态分布吗?看起来不太像,是吗?希望你和我一样,接受这不是正态分布。现在让我们对这些数据进行夏皮罗-维尔克检验。

哦。p=0.53。没有证据表明 x 不是正态分布的。嗯。那么你的结论是什么?当然,不是 x 不服从正态分布的证据并不意味着 x 服从正态分布。实际情况是,在小样本中,测试不足以检测偏离正态的情况。

x 的正常 Q-Q 图(n=10)。(图片由作者提供)

评估正态性的最佳方法是使用分位数-分位数图,简称 Q-Q 图。如果数据呈正态分布,我们会看到一条直线。这个数据显示了一些偏离常态的情况,这条线不是很直。尾部似乎有些问题。诚然,没有更多的数据很难说。

有了这些数据,我会担心假设正态性,因为在 Q-Q 图和直方图中似乎有一些偏差。但是,如果我们仅仅依靠我们的正态性测试,我们就不会发现这个。这是因为该测试在小样本中能力不足。

大样本的正态性检验

现在我们来看看大样本(n=5000)的正态性检验。让我们来看一个直方图。

x 的直方图(n=5000)。(图片由作者提供)

我希望你们都同意这看起来是正态分布的。好吧,夏皮罗-维尔克测试怎么说。巴赞加!p=0.001。有非常有力的证据表明 x 是正态分布的。哦亲爱的。让我们快速看一下 Q-Q 图。只是为了再确认一下。

x (n=5000)的正常 Q-Q 图。(图片由作者提供)

哇哦。这看起来是正态分布的。事实上,不应该有任何怀疑这是正态分布。但是,夏皮罗-维尔克测试表明并非如此。

这是怎么回事?夏皮罗-维尔克检验(和其他正态性检验)是设计来检验理论正态性(即完美的钟形曲线)的。在小样本的情况下,这些测试不足以检测出与正态分布相当大的偏差,而这种偏差可以通过图解法很容易地检测出来。在较大的样本中,这些测试甚至可以检测出与理论正态性极小的偏差,而这些偏差并不具有实际意义。

结论

希望我已经向你展示了正态性检验对数据科学家来说没有实际效用。不要使用它们。别管他们了。充其量,它们是无用的;最糟糕的是,它们会误导人。如果你想评估一些数据的正态性,使用 Q-Q 图和直方图。他们会给你一个关于数据正态性的更清晰的图像。

停止训练更多的模型,开始部署它们(使用 WebAssembly)

原文:https://towardsdatascience.com/stop-training-more-models-start-deploying-them-using-webassembly-49a3f178569e?source=collection_archive---------46-----------------------

(图片来源:迈克尔·帕尔多)

我们很难兑现人工智能在医疗保健领域的承诺。不是因为我们的训练,是因为我们的部署。

关于 AI (和 ML )将彻底改变医疗保健的传言已经有一段时间了。是的,我们已经看到了人工智能在医疗保健领域的一些惊人应用[例如,参见 2,3]。但是,根据我的个人经验,大多数在医疗保健领域接受过培训的模型都没有付诸实践。让我们看看为什么(或者,向下滚动,看看我们如何解决它)。

注:这句话“大多数在……接受培训的模型从未付诸实践”可能适用于所有学科。医疗保健恰好是我确信的一个领域。

开发医疗保健模式

在过去十年里,我开发了人工智能方法,让计算机学习“什么对谁有效”。我研究过 Bandit 问题[例如,4]以及在线营销中的应用[5],因此学会了“向谁展示哪个产品”。最近,我对“哪种治疗方法对哪个病人有效?”产生了兴趣;部分使用相同的数据科学方法,但这一次产生了积极的影响。

例如,在过去的两年里,我和沈凌杰一起与荷兰癌症登记处(T13)合作。伟大的人在 NCR 保持详细的记录包含荷兰癌症病例的进展。该登记包含患者的背景特征、他们的治疗(例如,化疗是或否)和结果(2 或 5 年死亡率)。从各个医院获取这些数据需要大量的整理工作,但 NCR 最终提供了一个干净的、记录良好的病例集合。我们从包含超过 50,000 名结肠癌患者且其肿瘤被手术切除的注册中摘录了一段内容。肿瘤切除后,关于是否进行化疗存在争议;虽然大多数随机对照试验(RCT)显示了积极的效果,但这似乎因患者和肿瘤类型而异[6]。

我们开始研究是否能知道哪些病人应该接受辅助化疗。一个简单的方法是拟合一个灵活的监督学习模型来预测 5 年生存率。因此,我们使用贝叶斯加法回归树[7]。然而,很明显,这还不够:NCR 的数据描述了在医院接受治疗的真实病例:治疗任务很可能会被严重混淆。我们可能混淆了因果关系。为了解决这个问题,我们研究了控制这种混杂的各种方法。我们最终将我们的估计与一个大 RCT 的估计进行了比较。这使我们能够验证我们的“校正模型”。

最后,这些步骤允许“输入反事实”[8]。我们创建了一个数据集,包含我们对每一位患者在治疗和不治疗下的预期结果。这允许生成个性化的治疗规则[9]:我们终于可以说哪种治疗对谁有效。**

上面的三个段落花了一年多的时间,需要我们的团队,NCR 和许多参与的肿瘤学家之间的协调。最终,该项目给了我们一个人工智能(或我们应该叫它什么)模型,给定一个特征向量,确定最佳治疗选择。然而,这个惊人的结果引出了下一个合乎逻辑的问题;我们如何确保这个模型被医疗专业人员实际使用?

模特从不离开他们的笔记本

为了找到答案,我决定和那些曾经经历过这个问题的人谈谈。所以,大约一年前,我开始和 NCR 大学的杰出人士交谈:“你如何部署你和使用你的数据的研究人员训练的模型?”简而言之,关于公共 API、监管、隐私以及文化和组织障碍,他们几乎不会这么做。事实证明,部署模型极其困难。

而且,不仅仅是 NCR;我和不同健康保险公司的数据科学家谈过。同样的问题。他们训练模型并验证它们,但很难将它们部署到医疗实践中。我与荷兰科学基金来源进行了交谈:是的,他们定期为各种医疗保健应用的模型培训提供资金。但是,实际部署这些模型是具有挑战性的,并且大多数项目都没有通过“笔记本阶段”:模型的有效性和有用性的良好演示,但是在实践中没有影响。

这里的底线是,不仅仅是我,一个研究人员,未能将训练好的模型投入生产。它无处不在,损害了我们真正改善患者生活的能力。

训练和部署是不同的

因此,我们面临一个问题:我们如何将模型投入生产?这个问题的答案会很复杂。这需要的不仅仅是技术解决方案。但是,我碰巧发现技术问题很有趣,所以现在让我们把重点放在这些问题上。

在我看来,部署模型的一个主要障碍是由我们对模型训练和模型部署的巨大不同的需求造成的。让我们来看几个:

  • 数据收集和管理:在培训期间,我们喜欢使用从主要流程导出的管理数据集。这在 NCR 的例子中很明显:涉及的数据已经通过手术从各个医院的电子病历中删除(没有双关语的意思)。然而,在生产中,我们面对的是收集的数据。我们需要能够处理来自单个患者的(原始)数据。
  • 试验和探索:在培训期间,我们喜欢能够让我们快速探索和预处理数据的工具。我们喜欢轻松地绘制图表,创建新的特征向量,并可视化我们的结果。在生产中,我们不需要这些工具;我们只需要确保快速可靠地生成推论。
  • 内存使用和计算性能:在训练期间,我们喜欢访问整个数据集来训练我们的模型。我们喜欢确保模型参数被快速学习(例如使用 GPU)。我们需要大容量的存储空间和快速的机器来解决我们的问题,但我们通常有几分钟的空闲时间。然而,在生产中,我们只需要评估当时的单个示例,但是这种评估需要快速完成(导致低延迟和低计算成本)。在生产中,我们需要精简高效的代码。
  • 可移植性:在培训期间,我们真的只需要在我们自己的机器上工作的东西。在部署方面,情况大不相同;我们希望大量的消费者使用我们的模型,很可能使用各种不同的系统。因此,我们应该使用标准化的接口提供对模型的访问,或者我们应该确保我们的模型可以随时随地运行。后者在健康上下文中非常重要,因为我们经常希望将模型发送到数据源,而不是将数据发送到某个外部服务器。

因此,虽然大多数数据科学家可以理解地乐于使用他们的 jupyter 笔记本(或各种其他工具),但无论在他们的本地机器上发生什么,都太不适合在医院运行。实际上,我们需要一种方法来弥合从培训需求到部署需求之间的差距。

当前部署解决方案失败

显然,我不是唯一发现这个问题的人;近年来,已经提出了许多潜在的解决方案。大多数解决方案属于以下三类之一,每一类都有其缺点。

  1. 原样容器化:从数据科学家的角度来看,一种相对简单的部署模型的方法是只取(例如)“python”笔记本代码,将其全部包装到一个(Docker)容器中,并公开一个 REST API。如果你不认真考虑,这听起来很不错。但事实并非如此:容器通常非常臃肿,结合大多数模型的底层c代码的python接口,这种方法导致部署比需要的大数量级(内存方面)和慢数量级。
  2. 从头开始重建:除了将现有内容容器化,另一种方法是将经过训练的模型从头开始重建为独立的高性能应用程序。在crust中重做模型,强大的打字和内存管理将使它变得小而快。您可能仍然需要对可执行文件进行容器化,或者针对不同的目标进行重新编译,但是本质上,您最终得到了一个可以在任何地方运行的小而快速的模型。然而,重建会消耗大量宝贵的开发时间。
  3. 存储和检索:我遇到的容器化或重建模型以进行部署的替代方法是将协变量空间中多个点的模型生成的推理存储到数据库中,该数据库在生产中充当查找表。这非常快,但是容易出错,而且对于较大的协变量空间几乎不可能。

实际上,如果我们能在上面的方法 1 和 2 之间找到平衡点,那就太好了:我们能让数据科学家太容易地将一个合适的模型转换成一个可以在任何地方运行的小而有效的应用程序吗?

使用 WebAssembly 快速部署

自动重建一个模型,让它可以在极小而高效的容器中运行,这听起来似乎不可能,但仔细想想,事实并非如此。我们使用 WebAssembly 、由我们在的朋友提供的运行时 wasmer 解决了这个问题,并且,不可否认的是,对c代码底层(例如)sklearn和各种编译器指令进行了大量的修改。所有这些导致了一种使用单行代码将存储的模型对象编译(或传输到 WebAssembly 的全自动方式。结果是一个惊人的快速,超级小的“可执行文件”,可以在几乎任何环境下运行;我们可以在服务器上运行该任务,并使用简单的 API 来公开它,但我们甚至可以在浏览器或边缘上运行它。WebAssembly(或.wasm)可执行文件可以被运送到医院,并在他们的系统中运行,直接基于 EPD 数据,而无需将数据运出医院。

简单的例子

为了说明这一点,让我们看一些简单线性回归模型的代码。下面的代码使用sklearn拟合一个简单的回归模型,随后使用[sclblpy](https://pypi.org/project/sclblpy/)包将它上传到可伸缩的:

几秒钟内,模型就完成了。为了让事情变得超级简单,我们甚至在我们的服务器上托管生成的.wasm可执行文件。这种特定的模型上传可以在 id 7d4f8549-a637–11ea-88a1–9600004e79cc下获得,并且可以在这里进行测试。

或者,一个简单的 cURL 调用,如下所示:

curl - location - request POST '[https://taskmanager.sclbl.net:8080/task/7d4f8549-a637-11ea-88a1-9600004e79cc'](https://taskmanager.sclbl.net:8080/task/7d4f8549-a637-11ea-88a1-9600004e79cc') - header 'Content-Type: application/x-www-form-urlencoded' - data-raw '{"input":{"content-type":"json","location":"embedded","data":"{\"input\": [[10]]}"},"output":{"content-type":"json","location":"echo"},"control":1,"properties":{"language":"WASM"}}'

立即提供结果模型推断。

试试看!

我们认为,我们将模型投入生产的方法可以弥合医疗保健等领域从培训到部署的差距。这很容易,结果是高性能和可移植的。然而,我们确实需要人们去尝试它,给予反馈,并帮助我们改进。所以,如果你想试一试,就在www.scailable.net获得自己的账户。

任何评论都非常感谢!

结论

让我们结束这一切。我认为我们开发有用模型的速度快于我们使用它们的速度。我认为模型部署是医疗保健领域(以及其他领域)的一个问题。我认为,部分原因是我们在训练模型和部署模型时有着非常不同的需求。我认为自动将模型传输到 WebAssembly 解决了这个问题:这很容易,它是高性能的,并且产生的可执行文件是可移植的。我们期待看到您的反馈。

参考

  1. https://doi . org/10.1016/s 0140-6736(17)31540-4
  2. https://www . science direct . com/science/article/ABS/pii/s 0040816619300904
  3. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6616181/
  4. https://journals . sage pub . com/doi/ABS/10.1177/2158244019851675
  5. https://www . emerald . com/insight/content/doi/10.1108/EJM-08-2016-0485
  6. https://www . the lancet . com/article/s 0140-6736(07)61866-2
  7. https://arxiv.org/abs/0806.3286
  8. https://amstat . tandfonline . com/doi/ABS/10.1198/016214504000001880
  9. https://arxiv.org/abs/1709.07498

放弃

值得一提的是我自己的参与:我是 Jheronimus 数据科学院的数据科学教授,也是 Scailable 的联合创始人之一。因此,毫无疑问,我对 Scailable 有既得利益;我有兴趣让它成长,这样我们就可以最终将人工智能投入生产并兑现它的承诺。这里表达的观点是我自己的。

推荐系统并不总是你的朋友

原文:https://towardsdatascience.com/stop-trusting-recommendation-systems-blindly-e8f52937034c?source=collection_archive---------45-----------------------

多个利益相关方意味着最终用户的偏好不是唯一的目标

图片来自 Unsplash

在这个网络狂热的时代,每个人肯定都遇到过推荐系统。约会应用并不是这类系统的唯一用例。它们被用于各种不同的领域,以帮助用户找到与其个人喜好相关的项目/信息。你可能倾向于认为这些系统的主要目标是最大限度地满足用户(即你)的兴趣。尽管这很重要,但用户肯定不是唯一希望从这些系统中受益的人。换句话说,有多个利益相关者。我将使用更一般的例子来解释这些。

多利益攸关方建议

多利益相关者推荐系统是一个有多个商业利益相关者的系统,这些利益相关者通常有相互冲突的利益,在生成推荐时需要考虑他们的偏好[1]。

假设你是一家大型在线零售商,在网上销售数百万件产品。像每一个主要的在线零售商一样,你有一个推荐系统,根据顾客的喜好向他们推荐产品。在这种情况下,至少有 3 个利益相关者:

  1. 客户
  2. 交货伙伴
  3. 你们

客户肯定是这个系统中最重要的利益相关者之一,因为客户满意是你的目标。这个目标反过来会让你受益,因为它增加了销售额和客户保持率。但与此同时,你的送货伙伴也在根据你卖的产品赚钱。因此,他们在任何决策过程中也很重要。这构成了多利益相关方推荐系统的基础。

为什么推荐系统不总是友好的

在许多业务场景中,由于利益相关者的利益冲突,向用户提供最佳推荐并不总是正确的方法。我们来看看网恋。

在线约会推荐系统(又名互惠系统)的主要目标是匹配两个有相似兴趣的人。如果一个在线约会应用程序没有让你和你感兴趣的人匹配,你就不会使用它。但是平台的最终用户是系统的唯一利益相关者吗?这可能会让你吃惊;不要!

平台所有者和最终用户的偏好之间会产生冲突。最好的用户体验将是在最短的时间内找到一个好的匹配,并且不再回来。另一方面,企业主希望通过拥有重复用户和更高的保留率来增加利润。这些相互冲突的最终目标就是为什么推荐系统并不总是你最好的朋友。

图 1: 图像

因此,如果你看看在线约会应用的商业模式,他们会更喜欢你继续回来,原因有两个。推荐的内容刚好能满足你的喜好,但不能完全满足你的喜好。

再比如零售。想象一下,有人向你推荐两种不同品牌的麦片,如图 1 所示。假设两者在客户偏好方面没有差异,由于与谷物 b 相比的相关成本,零售商可以向您出售谷物 A,实际上可能会获得更大的利润。这可能不是恶意意图,但在另一种情况下,零售商可能会以您为代价获得利润。

这是一场公平的比赛吗?

你可能会倾向于相信所有的企业都试图削弱你来实现他们的最终目标。然而,这并不完全正确。许多研究表明,根据用户偏好定制的个性化推荐会增加商业价值,例如提高销售额。这意味着客户仍然是推荐系统的重要驱动力。这个问题只出现在这样的系统中:利润不仅是从满足客户需求中获得的,而且是从企业的利润中获得的,而不一定能最大化用户满意度。所以并非都是坏消息。

资源

[1]https://www . research gate . net/publication/338516177 _ multi stakeholder _ recommendation _ Survey _ and _ research _ directions
【2】https://arxiv.org/pdf/1907.13158.pdf

关于作者

Usman Gohar 是一名数据科学家,明尼阿波利斯数据科学的共同组织者,也是一名技术演讲人。他非常热衷于最新的数据科学研究,机器学习,并通过帮助和授权年轻人在数据科学中取得成功而蓬勃发展。你可以在 LinkedInTwitterMediumT21【关注 Github 上与他联系。

停止使用 Excel 进行数据分析:升级到 Python

原文:https://towardsdatascience.com/stop-using-excel-for-data-analytics-upgrade-to-python-46b5963fb036?source=collection_archive---------18-----------------------

2017 年,估计全球有 7.5 亿人使用 Excel。2017 年世界人口约为 76 亿。这意味着大约 10%的人在使用 Excel,我猜主要是为了数据分析。这太疯狂了。

毫无疑问,Excel 对于公司来说是一个极其重要的工具,并且仍然在每个数据分析师和科学家的工具包中占有一席之地,但是对于你的大部分工作来说,你需要停止使用 Excel 并升级到 Python。我会告诉你为什么。

所以,如果你还没有开始学习 Python,并把你的数据分析和可视化技能提高到一个新的水平,我给你提供了 5 个你现在需要学习 Python 的理由。最后,我相信你会期待用 Python 取代你的大部分 Excel 工作。

规模和自动化

当你想对小数据进行快速、特别的分析时,Excel 是很好的工具,但是一旦你想进行更大规模的分析,它就不起作用了。Excel 最多可以支持 1,048,576 行 16,384 列的数据。另一方面,Python 可以扩展到内存大小,并且有许多工具支持内存外计算。

例如,Dask 库允许您将计算扩展到在一个机器集群上运行,而不仅仅是在您的笔记本电脑上。事实上,如果你熟悉熊猫,在 CSV 中阅读几乎完全相同的代码:

import dask.dataframe as dd

# Load the data with Dask instead of Pandas.

df = dd.read_csv(<file_path>)

一行代码,你现在读入的数据就超过了你电脑的内存。我会告诉你如何在 Excel 中做到这一点,但这甚至是不可能的。

如果这段代码看起来很奇怪,看看这个 课程 ,它会教你入门熊猫所需要知道的一切。

此外,Python 可以扩展到多个数据源。虽然 Excel 既是数据存储又是计算引擎,但是 Python 完全是数据不可知的。如果您能找到将数据读入 Python 的方法,您就可以使用它。由于 Python 有这么多优秀的库,从 CSV、Excel、JSON 和 SQL 数据库等许多来源读入数据是很容易的。

最后,就自动化而言,Python 是一种令人惊叹的编程语言。因为您可以将 Python 直接连接到任何数据源,所以很容易安排一个作业,该作业将使用任何更新重新提取您的数据,运行您的计算,甚至创建报告或动态仪表板,从而节省您大量的时间。另一方面,Excel 需要太多的手工劳动,并且不能自动更新。

Python 可以直接连接到数据库进行自动更新。来源:NobleDesktop

再现性

可再现性是这样一个概念,即你创建的任何分析或可视化都应该简单明了地为他人再现。不仅需要有人能够重新运行您的过程并以相同的结果结束,而且他们还应该能够通过您的步骤来确保准确性。当你开始依赖自动化时,这个概念是极其重要的。当工作正常时,自动化是惊人的,但当不正确时,自动化报告可能是一场噩梦。

Excel 的重现性非常具有挑战性。单元格中的 Excel 计算几乎不可能在任何规模下进行检查。数据类型非常令人困惑,因为你看到的并不总是原始数据中所表示的,虽然 VBA 使再现性稍微好一点,但在这一点上,你最好投资学习 Python。

看看这个 Excel 文档:

你知道sum列应该是 a 和 b 的和,但是你怎么确认呢?您可以检查其中一个公式,并看到它实际上是总和,但由于每个单元格都可以是自己的公式,如果它们都不正确呢?如果你没有注意,你可能会错过 x 行是错误的。

但是在 Python 中,您求和将如下所示:

a = [1,2,3,4]
b = [5,6,7,8]
sum = []
for i in range(a):
    sum.append(a[i] + b[i])

这段代码很清楚,很容易确认总和总是计算正确。

有了 Python,你可以获得为软件工程师更好地实现再现性和协作而开发的所有工具。最重要的是,Python 在数据连接方面更胜一筹,允许我们在云端分析数据,并立即重复一个过程。Git、单元测试、文档和代码格式标准在 Python 社区中非常流行。使用 Python 3,您甚至可以添加静态类型,使您的代码更加清晰。所有这些工具都使得确保你的代码写得又好又正确变得更加容易。这样下次你看你的代码或者别人拿起它的时候,就很容易复制和理解了。

可转移的技能

懂 Excel 就懂 Excel。虽然你学到的技能是有用的,但它们不能转移到其他任何东西上。我最喜欢 Python 的一点是,它不仅是一个令人惊叹的数据分析和可视化工具,而且是一种可靠的编程语言,可以用于许多其他事情。

想做机器学习甚至深度学习?使用 Python 可以做到这一点。想建个网站?Python 可以做到这一点。想让你的智能家居自动化吗?Python 也可以这样做。

此外,Python 比 Excel 更接近于其他编程语言。这使得你更容易学会沿途可能遇到的其他语言。学习 Python 比 Excel 打开了更多的大门。

最后,对 Python 的需求非常高。根据 StackOverflow 的数据,2019 年,它在专业软件开发人员中被评为世界第四大最受欢迎的编程语言,也是第一大最受欢迎的编程语言。事实上,据说 2020 年美国 Python 开发人员的平均年薪是 12 万美元。还不错。

高级功能

Excel 有很多内置公式,但与 Python 的功能相比就相形见绌了。Python 不仅提供了数百个库来简化高级统计和分析,还可以将您的可视化提升到另一个层次。使用 Matplotlib、Plotly、Streamlit 和 Seaborn 等工具,您可以创建漂亮的数据可视化以及交互式仪表盘和绘图。

Numpy 和 scipy 对科学计算、线性代数和矢量化计算有惊人的支持。而 scikit-learn 可以让你训练从决策树到梯度推进机器的机器学习算法。我觉得 xkcd 说的最好:

Python 很容易学

鉴于 Python 相对于 Excel 的所有惊人优势,它一定很难学,对吗?不!查看 Java 版的Hello World,最简单的程序:

class HelloWorld { public static void main( String args[] ) { System.out.println( "Hello World!" ); }}

Python 字面上就是一行:print(“Hello World!”)。没有比这更简单的了。Python 是最容易掌握的编程语言之一,并且拥有最活跃的社区之一,尤其是在数据分析领域。Python 是最直观的编程语言之一,即使对计算机科学没有多少背景知识的人也能理解!虽然学习曲线 Excel 可能看起来更好,但另一端的回报要少得多。 Python 的学习曲线值得花费时间和精力,这是 Excel 因其一刀切的设计而永远无法比拟的。

Python 很容易使用,而且有一个巨大的支持社区,学习它从来没有这么容易过。

为了向您展示 Python 有多简单,在下一节中,我将向您介绍 Python 中数据分析和可视化的一些基础。

开始使用 Python 进行数据分析

为了让您入门,我想带您了解 Python 中的一些基本命令和操作,这对您的数据分析技能至关重要。让我们从基础开始。

你会注意到的第一件事是 Python 使用了空格,而不像其他语言那样使用分号;。这里有一个非常简单的例子:

x = 5y = 10print(x+y)

导入功能

我们将利用许多库,有些是 Python 预装的,有些我们必须自己安装。使用 import 语句获取库:

from collections import Counter

这个命令从集合库中导入类计数器。计数器对于数据科学家来说是非常有用的工具;它可以计算项目在列表等集合中出现的次数。例如,在下面的代码中,我们将创建一个结婚年龄列表。使用计数器,我们可以快速计算每个独特的年龄出现的次数。

Python 中的列表

列表是存储数据的一种有用的数据结构。我们将在下一课中更详细地研究它们。例如:

from collections import Countermarriage_ages = [22, 22, 25, 25, 30, 24, 26, 24, 35]value_counts = Counter(marriage_ages)print(value_counts.most_common())

您可以看到,我们在第 2 行使用[]创建了一个包含结婚年龄的列表。然后,我们在第 4 行将该列表输入到Counter函数中,在第 5 行将最常见的值作为元组列表打印出来。

元组是()内部的集合。这些元组包含两个元素:值和该值在列表中出现的次数。频率对元组列表进行排序。出现次数最多的值最先出现。

Python 中的函数

函数也很有用。Python 中的函数以关键字def和函数名开始,后面是函数在括号中期望的输入。下面是一个函数,它接受两个输入,xy,并返回sum:

def add_two_numbers(x, y):  # function header """ Takes in two numbers and returns the sum parameters x : str first number y : str second number returns x+y """ z = x + y return z  # function returnprint(add_two_numbers(100,5))  # function  call

函数也可以是匿名的,这意味着你不必用上面的结构来声明它们。相反,您可以使用lambda关键字。下面是与上面相同的函数,但作为匿名函数:

y = lambda x, y: x + yprint(y(100,5))  # call the function

包扎

是时候转换到 Python 了。再也没有借口了!我希望这篇文章能帮助你看到学习 Python 的好处,并打破一些学习的障碍。

快去用 Python 把你的技能 更上一层楼吧!

停止使用 p=0.05

原文:https://towardsdatascience.com/stop-using-p-0-05-4a059e622c75?source=collection_archive---------24-----------------------

布雷特·乔丹在 Unsplash 上的照片

停止使用任意的统计显著性临界值

你们中有多少人用 p=0.05 作为绝对临界值?p ≥ 0.05 表示不显著。没有证据。没有。然后 p < 0.05 great it’s significant. This is a crude way of using p-values, and hopefully I will convince you of this.

What is a p-value?

A lot of us use p-values following this arbitrary cut off but don’t actually know the theoretical background of a p-value. A p-value is the probability, under the null hypothesis, of observing data at least as extreme as the observed data. It is not, for example, the probability that some population parameter x = 0. x either equals 0 or it does not (in a frequentist setting).

So, the smaller the p-value, the more unlikely it is that this data would have been observed under the null hypothesis. In essence, the smaller the p-value, the stronger the evidence against the null hypothesis.

What affects p-values?

Two things mainly. The first is the strength of effect. The greater the difference from the null hypothesis. The smaller the p-value will be.

The second is the sample size. The larger the sample, the smaller the p-value will be (if in fact the null hypothesis is false).

So, this means that if p ≥ 0.05, it could be because the effect isn’t that strong (or doesn’t exist) or that our sample is too small, resulting in our test being 动力不足检测差异。

一些例子

致命的药物

假设我们正在研究一种新药的副作用。现在假设药物增加死亡率的证据 p=0.051。现在,如果我们用 p=0.05 作为临界值,那就太好了。没有证据表明这种药物会增加死亡率——让我们把它投入生产吧。现在想象死亡率增加的 p=0.049。哦不!有证据表明这种药物有害。我们不要把它投入生产。

从数学上来说,这两者没有什么区别。它们本质上是一样的。但是通过使用这个任意的截止值,我们得到了非常不同的结论。

这种药有效吗

现在想象另一种药物。我们有一个非常大的样本(n=10,000),我们想知道这种药物是否能治愈癌症。所以我们得到 p=0.049,它能治愈癌症。太好了!这种药物治愈癌症的重要证据。给大家看看吧。

不过,这是一个大样本。难道我们不会期望 p 更小吗?这不是反对无效假设的有力证据。我们的结果有大约二十分之一的概率是偶然的。现在假设这种药真的很贵。我们真的要根据一些相当薄弱的证据就开始把它分发给每个人吗?大概不会。

当然,如果 p=0.001,这将是百分之一的几率,我们的结果是偶然的。这将是证明药物有效的更有力的证据。

那么我们应该如何解读 p 值呢?

作为一个连续的音阶。p 值越小,证据越强。但是,你应该考虑样本大小和效应大小。你也应该考虑你正在看的东西是积极的还是消极的。如果看看像我们的致命药物例子,我们应该关注,即使证据非常薄弱。然而,就像想知道一种药物是否有效一样,我们可以对我们的结果持更加怀疑的态度。

因此,希望在未来,你将不再使用 p=0.05 作为从阈值中挑选出来的某个阈值,而是考虑它的真实情况——反对零假设的证据权重。当然,如果你没有你需要的证据,这不一定是因为它不存在,这可能是因为你缺乏统计能力来检测一个影响。

停止使用熊猫,开始使用 Spark 和 Scala

原文:https://towardsdatascience.com/stop-using-pandas-and-start-using-spark-with-scala-f7364077c2e0?source=collection_archive---------7-----------------------

为什么数据科学家和工程师应该考虑使用 Spark 和 Scala 作为 Pandas 的替代方案,以及如何开始

来源:https://unsplash.com/photos/8IGKYypIZ9k

用 Scala 从 Pandas 迁移到 Spark 并不像你想象的那样具有挑战性,因此你的代码会运行得更快,你可能会写出更好的代码。

在我作为一名数据工程师的经历中,我发现在 Pandas 中构建数据管道通常需要我们定期增加资源,以跟上不断增长的内存使用量。此外,我们经常会看到由于意外的数据类型或空值而导致的许多运行时错误。将 Spark 与 Scala 结合使用的结果是,解决方案感觉更健壮,更容易重构和扩展。

在本文中,我们将浏览以下内容:

  1. 为什么你应该在 Scala 中使用 Spark 而不是 Pandas
  2. Scala Spark API 和 Pandas API 并没有太大的不同
  3. 如何开始使用 Jupyter 笔记本或您最喜欢的 IDE

什么是火花?

  • Spark 是一个 Apache 开源框架
  • 它可以作为一个库,在“本地”集群上运行,或者在 Spark 集群上运行
  • 在 Spark 集群上,代码可以以分布式方式执行,一个主节点和多个工作节点分担负载
  • 即使在本地集群上,你仍然会看到性能比 Pandas 有所提高,我们将在下面解释原因

为什么要用 Spark?

Spark 因其快速处理大型数据集的能力而广受欢迎

  • 默认情况下,Spark 是多线程的,而 Pandas 是单线程的
  • Spark 代码可以在 Spark 集群上以分布式方式执行,而 Pandas 运行在单台机器上
  • Spark 是懒惰的,这意味着它只会在你收集(即。当你真的需要返回一些东西的时候),同时它建立一个执行计划并找到执行你的代码的最佳方式
  • 这与熊猫不同,熊猫很急切,每走一步就执行一步
  • Spark 也不太可能耗尽内存,因为当它达到内存限制时,它将开始使用磁盘

关于运行时间的直观比较,请参见下面来自 Databricks 的图表,从中我们可以看到 Spark 明显比 Pandas 快,并且 Pandas 在较低的阈值下耗尽了内存。

https://databricks . com/blog/2018/05/03/benchmarking-Apache-spark-on-a-single-node-machine . html

Spark 拥有丰富的生态系统

  • 数据科学库,比如内置的 Spark ML,或者图形算法的 Graph X
  • 实时数据处理的火花流
  • 与其他系统和文件类型(orc、parquet 等)的互操作性。)

为什么要用 Scala 而不是 PySpark?

Spark 提供了一个熟悉的 API,所以使用 Scala 而不是 Python 不会感觉是一个巨大的学习曲线。以下是您可能想要使用 Scala 的几个原因:

  • Scala 是一种静态类型语言,这意味着你会发现你的代码比 Python 有更少的运行时错误
  • Scala 还允许您创建不可变的对象,这意味着当引用一个对象时,您可以确信在创建它和调用它之间,它的状态没有发生变化
  • Spark 是用 Scala 编写的,所以 Scala 中的新特性比 Python 早
  • 对于一起工作的数据科学家和数据工程师来说,使用 Scala 有助于协作,因为 Scala 代码具有类型安全性和不变性

Spark 核心概念

  • 数据帧:spark 数据帧是一种与熊猫数据帧非常相似的数据结构
  • 数据集:数据集是一种类型化的数据帧,对于确保数据符合预期的模式非常有用
  • RDD :这是 Spark 中的核心数据结构,数据帧和数据集就是建立在这个基础上的

一般来说,我们会尽可能地使用数据集,因为它们是类型安全的,更有效,并且提高了可读性,因为我们可以清楚地看到数据集中的数据。

数据集

为了创建数据集,我们首先需要创建一个 case 类,它类似于 Python 中的数据类,实际上只是一种指定数据结构的方法。

例如,让我们创建一个名为 FootballTeam 的案例类,它有几个字段:

**case class FootballTeam(** name**: String,** league**: String,** matches_played**: Int,** goals_this_season**: Int,** top_goal_scorer**: String,** wins**: Int
)**

现在,让我们创建这个 case 类的一个实例:

**val** brighton: **FootballTeam** =
    **FootballTeam**(
      "Brighton and Hove Albion",
      "Premier League",
      matches_played = 29,
      goals_this_season = 32,
      top_goal_scorer = "Neil Maupay",
      wins = 6
    )

让我们创建另一个名为 manCity 的实例,现在我们将创建一个包含这两支足球队的数据集:

**val** teams: **Dataset**[**FootballTeam**] = spark.createDataset(***Seq***(*brighton*,  
      *manCity*))

另一种方法是:

**val** teams: **Dataset**[**FootballTeam**] = 
      spark.createDataFrame(**Seq**(*brighton*, *manCity*)).as[**FootballTeam**]

第二种方法在从外部数据源读取数据并返回 DataFrame 时非常有用,因为您可以转换为数据集,这样我们现在就有了一个类型化的集合。

数据转换

Spark 中提供了大多数(如果不是全部)可以应用于 Pandas 数据帧的数据转换。当然,在语法上有所不同,有时还需要注意一些额外的东西,其中一些我们现在就来看看。

总的来说,我发现 Spark 在符号上比 Pandas 更一致,而且因为 Scala 是静态类型的,所以你通常可以只做myDataset.然后等待你的编译器告诉你什么方法是可用的!

让我们从一个简单的转换开始,我们只想向数据集添加一个新列,并为它赋予一个常数值。在熊猫身上,这看起来像是:

**Pandas**df_teams['sport'] = 'football'

除了语法之外,spark 还有一个小的不同,那就是向这个新字段添加一个常量值需要我们导入一个名为 lit 的 Spark 函数。

**Spark****import** org.apache.spark.sql.functions.lit**val** newTeams = teams.withColumn("sport", lit("football"))

注意,我们已经创建了一个新对象,因为我们最初的团队数据集是一个 val,这意味着它是不可变的。这是一件好事,因为我们知道无论何时使用我们的团队数据集,我们总是得到相同的对象。

现在让我们添加一个基于函数的列。对熊猫来说,这看起来像是:

**Pandas****def** **is_prem**(league):
    **if** league == 'Premier League':
        **return** **True**
    **else**:
        **return** **False** df_teams['premier_league'] = df_teams['league'].apply(**lambda** x: 
                                    is_prem(x)) 

为了在 Spark 中做同样的事情,我们需要序列化函数,以便 Spark 可以应用它。这是通过使用名为 UserDefinedFunctions 的东西来完成的。我们还使用了大小写匹配,因为这是 Scala 中比 if-else 更好的实现,但是两者都可以。

我们还需要导入另一个有用的 spark 函数, col,用于引用列。

**Spark****import** org.apache.spark.sql.functions.col**def** **isPrem**(league: **String**): **Boolean** =
    league **match** {
      **case** "Premier League" => **true**
      **case** _                => **false**
    } **val** isPremUDF: **UserDefinedFunction** =
    udf[**Boolean**, **String**](isPrem) **val** teamsWithLeague: **DataFrame** = teams.withColumn("premier_league",                                                            
          isPremUDF(col("league")))

现在我们已经添加了一个不在 case 类中的新列,这将把它转换回 DataFrame。所以我们要么需要向我们的原始 case 类添加另一个字段(并允许它为空,使用选项),要么创建一个新的 case 类。

Scala 中的一个选项仅仅意味着该字段是可空的。如果值为空,我们使用None,如果值为空,我们使用Some("value")。可选字符串的示例:

**val** optionalString : **Option[String]** = Some("something")

要从中获取字符串,我们可以调用optionalString.get(),这将返回"something"。注意,如果我们不确定它是否为空,我们可以使用optionalString.getOrElse("nothing"),如果为空,它将返回字符串"nothing"

过滤数据集是另一个常见的需求,这是 Spark 比 Pandas 更一致的一个很好的例子,因为它遵循与其他转换相同的模式,我们在那里进行数据集“点”转换(即dataset.filter(...))。

**Pandas**df_teams = df_teams[df_teams['goals_this_season'] > 50] **Spark****val** filteredTeams = teams.filter(col("goals_this_season") > 50)

我们可能需要在数据集上执行一些聚合,这在 Pandas 和 Spark 中非常相似。

**Pandas**df_teams.groupby(['league']).count() **Spark**teams.groupBy("league").count()

对于多重聚合,我们可以再次做一些类似于 Pandas 的事情,使用一个字段到聚合的映射。如果我们想做自己的聚合,我们可以使用 UserDefinedAggregations。

teams.agg(**Map**(
    "matches_played" -> "avg",
    "goals_this_season" -> "count"))

通常,我们还希望组合多个数据集,这可能需要 union:

**Pandas**pd.concat([teams, another_teams], ignore_index=**True**) **Spark**teams.unionByName(anotherTeams)

…或者使用连接:

**val** players: **Dataset[Player]** = spark
        .createDataset(**Seq**(*neilMaupey*, *sergioAguero*)) teams.join(players,
        teams.col("top_goal_scorer") === players.col("player_name"),
        "left"
      ).drop("player_name")

在这个例子中,我们还创建了一个新的数据集,这次使用了一个名为 Player 的 case 类。注意,这个案例类有一个字段 injury,可以为空。

**case** **class** **Player**(player_name: **String**, goals_scored: **Int,** injury: **Option[String]**)

请注意,我们已经删除了 player_name 列,因为这将是 top_goal_scorer 的副本。

我们可能还希望部分代码只使用 Scala 原生数据结构,如数组、列表等。要将我们的一列作为数组,我们需要映射到我们的值并调用.collect()

**val** teamNames: **Array[String]**  = teams.map(team => team.name)
      .collect()

请注意,我们可以使用 case 类的内置 getters 来返回 name 字段,如果 name 不是我们的类 FootballTeam 中的字段,这将无法编译。

顺便说一下,我们也可以在 case 类中添加函数,当使用 IntelliJ 或 vs code with Metals plugin 等 ide 时,值和函数都会作为自动完成的选项出现。

为了根据数据集是否存在于这个数组中来过滤我们的数据集,我们需要通过调用 _* 将它视为一个 args 序列。

**val** filteredPlayers: **Dataset[Player]** = players
      .filter(col("team").isin(teamNames: _*))

运行一些代码

在这一点上,希望你热衷于写一些 Spark 代码,即使只是为了看看我的说法是否站得住脚,它与熊猫没有太大的不同。

首先,我们有几个选项。我们可以使用笔记本,这是一种快速获取一些数据并开始到处玩的方法。或者,我们可以建立一个简单的项目。无论哪种方式,你都需要安装 Java 8。

笔记本

对于这个例子,我们将在 Jupyter 笔记本中使用 spylon 内核。https://pypi.org/project/spylon-kernel/。首先运行以下命令来设置您的笔记本,这将在浏览器中打开您的笔记本。然后从可用的内核中选择 spylon 内核

 pip install spylon-kernel
 python -m spylon_kernel install
 jupyter notebook

让我们通过向一个单元格添加以下内容来检查我们是否有正确的 Java 版本:

!java -version

输出应该是:

java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)

如果没有,检查 bash 概要文件中的 JAVA_HOME ,确保它指向 Java 8。

下一步是安装一些依赖项。为此,我们可以将以下代码片段添加到一个新的单元格中。这将设置一些 spark 配置,并允许您添加依赖项。这里我添加了一个可视化库,名为 vegas。

*%%init_spark*
launcher.num_executors = 4
launcher.executor_cores = 2
launcher.driver_memory = '4g'
launcher.conf.set("spark.sql.catalogImplementation", "hive")
launcher.packages = ["org.vegas-viz:vegas_2.11:0.3.11",
                    "org.vegas-viz:vegas-spark_2.11:0.3.11"]

为了连接到我们的数据源,我们可以定义一个函数,可能是这样的:

**def** **getData**(file: **String**): **DataFrame** = 
        spark.read
        .format("csv")
        .option("header", "true")
        .load(file)

这是一个到 csv 文件的连接,但是我们可以连接到许多其他数据源。这个函数返回一个 DataFrame,我们可能想把它转换成一个数据集:

**val** footballTeams: **Dataset[FootballTeam]** = 
      getData("footballs_teams.csv").as[FootballTeam]

然后,我们可以开始处理这些数据,并尝试我们讨论过的一些数据转换,以及更多。

设置项目

既然您已经尝试了一些数据,您可能想要建立一个项目。

两个主要的东西包括:

  • build.sbt——之前我们在笔记本的一个单元格中添加了依赖项,现在我们需要将它们添加到 build . SBT 文件中
  • SparkSession -在笔记本中我们已经有了一个 SparkSession,这意味着我们可以做诸如spark.createDataFrame之类的事情。在我们的项目中,我们需要创建这个 spark 会话

示例 build.sbt:

name := "spark-template"
version := "0.1" 
scalaVersion := "2.12.11"val sparkVersion = "2.4.3"
**libraryDependencies** += "org.apache.spark" %% "spark-core" % sparkVersion
**libraryDependencies** += "org.apache.spark" %% "spark-sql" % sparkVersion

示例 SparkSession:

**import** org.apache.spark.sql.SparkSession **trait** SparkSessionWrapper { val spark: SparkSession = SparkSession
           .builder()
           .master("local")
           .appName("spark-example")
           .getOrCreate()
}

然后我们可以用这个包装器扩展对象,这给了我们一个 spark 会话。

**object** RunMyCode **extends** SparkSessionWrapper { //your code here
}

然后,您就可以开始编写您的 spark 代码了!

总之,Spark 是一个非常好的快速数据处理工具,并且在数据领域越来越受欢迎。因此,Scala 也正在成为一种更受欢迎的语言,由于它的类型安全性,对于数据工程师和数据科学家来说是一个很好的选择,他们可能更熟悉 Python 和 Pandas。Spark 是对该语言的一个很好的介绍,因为我们可以使用熟悉的概念,如 DataFrames,所以感觉不像是一个巨大的学习曲线。

希望这已经给了你一个快速的概述,也许能让你开始探索 Spark,无论是在你的笔记本中,还是在你的新项目中。祝你好运!

在 Python 中停止使用分号

原文:https://towardsdatascience.com/stop-using-semicolons-in-python-fd3ce4ff1086?source=collection_archive---------6-----------------------

它们很少有用,看起来也不漂亮

照片由纳丁·沙巴纳Unsplash 拍摄

来自 C/C++背景的我,习惯了在代码中看到很多分号;。它们用来代表 语句终止

但是,Python 并不强制 使用分号来分隔语句。然而,我经常遇到充斥着分号的 Python 代码。

最近,我参加了一个关于 Python 的数据科学课程。讲师正在介绍条件语句并编写了以下代码:

temp = 10;if temp <12: print('It is cold'); cold = True;

我的反应:纯恐怖!

来源: Giphy

在 Python 中,分号只在非典型情况下使用。因此,我准备了一个小指南,解释为什么不应该在 Python 中使用分号,并指出少数例外。

语句终止符

在许多流行的编程语言中,你需要在每个语句的末尾添加一个分号。例如,在 C++中:

int c = 10;
int a = 5;printf('In C++, semicolon at the end is must');

但是对于 Python 来说,这是不成立的。

Python 是一种不废话的编程语言。它远离不必要的字符和语法

在 Python 中,语句在行尾结束(左括号、引号或圆括号除外)。例如:

c = 10
a = 5print('No semicolons in Python')

报表分隔符

Python 中的分号表示 分隔 ,而不是终止。它允许你在同一行写多条语句。

print('Statement 1'); print('Statement 2'); print('Statement 3')

这种语法也使得在单个语句的末尾放置分号是合法的:

print('Why God? WHY?');

这个语句的意思是打印(“…”),然后什么都不做。所以,它实际上是两个语句,其中第二个是空的。

尽管这种语言允许用分号来分隔语句,但大多数 Python 程序员都不会在他们的代码中使用它。

这是为什么呢?它不是

来源: Giphy

Python 应该是干净可读的。像分号这样的语法字符增加了不必要的混乱。

如果你把这样的代码发给一个有经验的 Python 程序员,你将永远听不到它的结尾。

将多条语句放在一行会使琐碎的代码更难阅读。

什么时候使用分号?

因此,这里的一个逻辑问题是:为什么 Python 中允许使用分号?

我相信这样做是为了使从其他编程语言的过渡稍微容易一些。有 Java、C++和 PHP 背景的程序员习惯性地在每一行的末尾加上一个(无用的)终止符

尽管如此,在某些情况下分号会派上用场。

从 Shell 运行脚本

最常见的一种情况是使用python -c '<script>'从 shell 运行一个简短的脚本。

我们需要键入许多用分号分隔的表达式,因为我们在这里不能使用缩进。看一看:

python -c 'import math; t = math.pi;print(int(t))’

另一个用例是 exec 语句 :

exec('for i in [100,200,300]: print(i);print(i*2)')

评估表达式的副作用

在类似 Jupyter 笔记本 的交互环境下工作时,最后一个表达式返回的值以字符串的形式打印出来。

在我们评估一个函数的副作用的情况下,这可能很烦人。我们来看[matplotlib](https://matplotlib.org/)中副作用是剧情的这一期。

我会在我的 Jupyter 笔记本里创建一个 简单直方图

如下图所示,运行这个脚本在输出:Text(0.5, 1.0, ‘Histogram’)中添加了一个多余的行

来源:作者

这其实就是对.set_title(...)调用的返回值

为了抑制输出,我们在最后一条语句的末尾添加了一个分号:

axis.set_title('Histogram', size=10);

结论

像许多 Python 程序员一样,我认为我们应该在编写代码时避免添加任何多余的字符。

分号是合法的。但这并不意味着你应该使用它。

只有在必要时才使用它。

我希望你发现这个故事信息丰富和有用!你可以在这里阅读更多关于 Python 哲学的内容:

[## 思考 Python 的禅

浅析 Python 设计的 19 条指导原则

medium.com](https://medium.com/better-programming/contemplating-the-zen-of-python-186722b833e5)

停止使用奥卡姆剃刀原理

原文:https://towardsdatascience.com/stop-using-the-occams-razor-principle-7281d143f9e6?source=collection_archive---------17-----------------------

你想知道如何用奥卡姆剃刀证明地球是平的吗?你想证明上帝是宇宙万物的原因吗?除了高中物理什么都不懂就想反驳爱因斯坦的理论?

好吧,我不会告诉你如何做这些事情,因为除非你错误地引用奥卡姆剃刀,否则这些事情是做不到的——这似乎是几乎任何引用它的论点中不可避免的。我将进一步表明,即使奥卡姆剃刀被正确引用,它在实践中也是不可操作的,因此应该从任何一种理性论证中放弃。这可能是它在应用时经常被错误引用的原因。

在此基础上,我将主张完全禁止在任何诚实的争论或辩论中使用所谓的奥卡姆剃刀。

TLDR:大多数人错误引用和误用了所谓的奥卡姆剃刀。即使正确引用,这个概念也只有有限的抽象价值,而且完全不可操作。它在现实世界中的应用几乎为零,所以请不要再把它作为你论点的一部分。

首先,让我们来看看奥卡姆的威廉究竟说了什么,他提出了偏好简单解释或解决方案的“规则”。

奥卡姆的威廉到底说了什么?

奥卡姆的威廉(又名奥卡姆或奥查姆)被归因于各种不同的“报价”,这些报价与基于简约/简单的问题解决原则有关。他们通常陈述类似于:简单的解决方案比复杂的更好;简单的解释比复杂的更好。

然而,这种想法并不是奥卡姆的威廉所独有的,实际上没有直接引用他的话来支持他甚至在作品中提出这样的主张。最接近的是这两句话:

“Entia non sunt 被乘数 da praeter necessitem”,翻译为“实体不得超过必要性而增加”和“Frustra fit per plura quod potest fieri per pauciora”,翻译为“用更少的资源做更多的事情是徒劳的”鉴于进化的力量驱使所有生物走向极简主义和认知痛苦,这几乎不是什么有启发性的东西:花费不必要的能量来实现给定的结果往往会受到自然的惩罚,通过个体层面的死亡和物种层面的灭绝。

这里需要注意的关键词是“超出需要”和“可以用更少的资源完成”。注意“必要性”在第一个引语中没有定义,而在第二个引语中暗示我们得到相同的最终结果。我们将在下一节回到这些。

在奥卡姆之前和之后很久,许多思想家都提出了这个原则的其他表述,包括亚里士多德、托马斯·阿奎那、牛顿、伯特兰·罗素和卡尔·波普尔。例如,亚里士多德的表述是“在其他条件相同的情况下,我们可以假设从更少的假设或假说中得出的论证更优越。”。更简单地说:

“在其他条件相同的情况下,简单的解释通常比复杂的解释更好”

撇开作者身份或原创性的问题不谈,我认为这种非常常识性的想法在用于实际后果的实际争论时,经常而且几乎不可避免地被曲解。

错误引用原理证明地球是平的

最常见的错误引用以及由此而来的对奥卡姆简单性原则的误用是简单地放弃了其他条件不变限定词,即该原则的“其他条件相同”部分。

没有它,事情就简单了:

“简单的解释通常比复杂的好”

因此是误用的时机

例如,对于在海平面上观测者的眼睛看来地平线是平的这一事实的一种解释是,地球是一个平面。这是一个非常简单的解释,因为只涉及到一个平面,因此需要计算一些相关的距离、角度、轨迹等。相对来说简单。更复杂一点的解释是,地球是一个球体,表面上平坦的地平线是由于它巨大的直径和我们的有利位置。然而,更复杂的是高斯提出的涉及大地水准面的解释。甚至更复杂的是以旋转椭球为参考椭球的三轴椭球的大地水准面梨形图形的现代概念。

应用被错误引用的奥卡姆剃刀理论,基于其简单性,高斯大地水准面概念应优先于现代大地水准面概念,球面概念应优先于大地水准面概念,平面概念应优先于所有其他概念。因此,奥卡姆剃刀的这个错误陈述的应用将导致我们接受平面假说,并因此得出地球是平的结论。

一个更极端的例子是上帝。至少从表面上看,上帝是对几乎所有事物的简单解释,所以我们应该更喜欢“上帝做的”或“上帝让它如此”的解释,而不是其他任何解释。

当然,这纯粹是无意义的。

因为奥卡姆公式和其他公式中的原则都明确指出“其他一切都是平等的”。我们不能简单地假装这一条款不存在,然后不管不顾地适用它的其余部分。

一旦这一条款生效,我们可以看到上述做法是徒劳的。作为平面的地球模型并不能像假设球体的模型一样很好地解释所有相关现象。事实上,它在一些至关重要的测试中失败了,如驾驶飞机、发射卫星或全球定位系统(GPS)。同样,球面模型不如大地水准面模型,大地水准面模型本身不如更复杂的椭球面模型,椭球面模型允许我们解释更多的现象,并预测物理力及其对地球上或近地轨道上运动的物体的影响。

因此,基于其解释和预测质量,更复杂的模型实际上是更可取的模型,即使它在简单性方面较差。

奥卡姆剃刀实际上是不可行的

让我们说,一个人知道实际的原则,并在他们的论点中足够诚实,不会错误地引用它。该原则能否应用于实际?

我认为,即使你没有错误引用该原则,你也很可能误用了它,因为它实际上是不可操作的。我相信,其他条件不变条款是造成这种情况的原因。我想不出在任何实际情况下,两种解决方案或假设会涵盖完全相同的现象,并导致关于它们的相同结论和预测

即使对于几乎相同的假设,一个假设或另一个会涉及更多或更少的现象,一个或另一个会涵盖另一个没有的情况。如果情况不是这样,那么其中一个肯定会导致与另一个稍微不同的预测。这意味着,即使我们忽略了奥卡姆剃刀缺乏逻辑支持(这是另一篇文章的主题),它对于大多数(如果不是所有)实际情况也是不可操作的。

这一点在我们对地球形状的不同模型的讨论中已经有所暗示:提出的解释并没有以同样的方式解释同样的现象,有些解释不能完全解释某些现象,并且基于每一种解释的预测在许多情况下会有所不同。“其他条件相同”的要求证明是不成立的。

另一个关于行星运动的情况是:比较牛顿和爱因斯坦的运动定律。两者都解释了物体如何相互作用和相对运动,并且都可以用来预测不同尺度上运动物体的位置或速度。在某些条件下,它们甚至会产生相同的结果。

由于牛顿理论无疑比爱因斯坦的简单,如果我们天真地相信“其他条件相同”的奥卡姆剃刀成立,我们应该采用牛顿的理论,抛弃爱因斯坦的工作。

然而,奥卡姆剃刀的其他条件不变的要求很容易被证明是不可行的,因为牛顿物理学在行星尺度上导致更不精确的测量和预测,以及其他差异。“其他一切”都不平等!因此,即使理论表面上看起来相似,即使一个理论实际上是另一个理论的特例,这个关键要求也不成立

在争论中避免使用奥卡姆剃刀

鉴于以上所述,我的建议是在辩论中避免使用所谓的奥卡姆原理的任何变体。即使表面上被认为是真的(尽管缺乏逻辑证明),奥卡姆剃刀也是不可操作的,除非你在看两个假设,它们在完全相同的情况下,以完全相同的预测准确度解释完全相同的一组现象,这实际上是不可能的。

如果你偶然发现这样一个有实际意义的场景,请随时联系我,让我知道!

需要明确的是,无论是在统计建模还是在日常生活中,简约和简单都是值得追求的。然而,一个人不应该欺骗自己,简单是唯一的,甚至是主要的衡量标准,适合,等等。或者说,把事情变得更简单并不需要付出任何代价,因为最终的结果是方向、准确性和总体质量。

不要使用统一的前科

原文:https://towardsdatascience.com/stop-using-uniform-priors-47473bdd0b8a?source=collection_archive---------24-----------------------

它们在统计学上没有意义

这是一个微不足道的咆哮,但却是必要的。我们需要让从业者不再使用统一的前科。概率编程发展很快,这很好,但这意味着有些人学习了 MCMC,却从未学习过 ANOVA。

贝叶斯统计学家一致认为,统一的先验知识是愚蠢的。标准文件不鼓励统一的前科。它们出现在教科书中是为了简化计算——我们不想让学生在交流概念时陷入繁琐的计算中。然而,统一的先验知识在教科书之外几乎没有位置。

在解释了原因之后,我将在文章的后半部分提供选择更好先验的方法,记住实际应用,比如 A/B 测试。

无信息的前科?更像是荒谬的前科

一篇的前一篇文章解释了附在不具信息性的前文中的所有不合理的陈述。我们应该使用先前的预测检查来诊断我们的病史,最好是通过可视化。贝叶斯模型是可生成的,我们可以模拟一些数据来评估我们假设的合理性。

我会编造一个愚蠢的对话来说明我对统一先验的反对。在这种情况下,我们希望用大 n 进行单侧假设检验。

爱丽丝:“什么是 95%的置信区间?”

鲍勃:“参数有 95%的概率在区间内。”

爱丽丝:“不!别开玩笑了!例如,如果我们知道参数为 0,那么它包含在这个 95% CI 中的概率为 0:"

鲍勃:“哦,对了。如果我们从总体中随机抽取大小为 n 的样本,那么 95%的区间将覆盖真实参数。”

来源

艾丽斯:“是的!什么是 p 值?”

鲍勃:“零假设正确的概率。”

爱丽丝:“不!不好!”

来源

鲍勃:“嗯,我的意思是,假设零假设是真的,这是观察测试统计的概率或更极端的东西。”

爱丽丝:“对!重要的是要精准!”

鲍勃:“但是这太令人困惑和不直观了!我们如何向外行人解释?哦,我知道了!我们在那上面打一个制服 prior 怎么样?”

爱丽丝:“你什么意思?”

鲍勃:“那么 95%可信区间与 95%置信区间相同,但我们可以说参数有 95%的概率在区间内!”

爱丽丝:

来源

鲍勃:“忘记令人困惑的 p 值!我们可以给人们零假设为真的概率!在这里,我放置一个均匀的β(1,1)先验,在抛一次硬币并得到正面后,我得出结论,有 75%的概率 P(H) > 0.5!”

爱丽丝:“但是那个结论完全是荒谬的!你真的认为世界上大多数硬币都是极不公平的吗?”

鲍勃:“这叫做贝叶斯。你没听说过所有的流行吗?这比 i n t e r p r e t a b l e 要多得多。我们改变几个词,然后以前不正确的陈述神奇地变成了正确的。将军,常客!”

选择更好的前科

统一先验不提供任何正则化,尽管这是贝叶斯的主要优势之一。更糟糕的是,如果你选择一个均匀的(0,10)先验,那么你就是在这个区间之外放置了 0 质量,并且 Bernstein-von Mises 定理不成立。换句话说,即使你有无限的数据,你仍然可能在这些先验知识上犯严重的错误。

在缺乏知情先验信念的情况下,我们仍然可以做得比一致先验更好。正如 Stan 文档所建议的:

不要使用统一的先验或更一般的硬约束,除非界限代表真正的约束(例如比例参数被限制为正,或相关性被限制为-1 和 1 之间)。一些例子:

您认为参数可以是从 0 到 1 的任何值,因此您将 prior 设置为 uniform(0,1)。请改用 normal(.5,. 5)。

经验贝叶斯

经验贝叶斯利用你的数据得出先验。我们将忽略“从数据中估计出来的先验值是先验值吗?”在实践中,经验贝叶斯非常有效。詹姆斯-斯坦估计量的表现让人们困惑了一段时间,但我们已经接受了这一点,就像许多药物一样,重要的是它是有效的。

最简单的方法是使用矩量法。假设您正在测试 50/50 分割的转换率。结合你所有的观察,计算转换的均值和方差,并用它们来估计你将用作先验的贝塔分布的α和β。假设均值和方差分别为 0.2 和 0.01。然后:

因此,根据经验贝叶斯,我们的先验应该是 Beta(3,12)。

如果您对每个用户有多个观察值或没有观察值,例如购买量,那么您希望在使用矩量法之前按用户进行汇总(例如总购买量、购买次数)。请记住,有些用户购买了 0 次,我们需要将他们包括在估算中。我们假设参数因人而异,而不是因购买而异。

贝叶斯分层模型

分层模型可以解释为从数据中学习先验知识。您可以尝试对此运行 MCMC,其中 x_i 是我们的第 I 个观察值,β_ j 是该组的平均值(例如,对照组与治疗组):

选择的先验是一般性的,但是你应该根据你的历史数据得到更多的信息,特别是对于 mu。此外,您可以根据您在实验中评估的指标做出更好的分布假设。即使超参数的先验非常弱,在部分汇集之后,我们仍然应该得到β的合理分布。

N(0,1)

可笑的是,你总是可以重新调整你的数据,使 N(0,1)先验有意义。例如,如果我们认为 1%的变化是合理的,但 20%的变化是不可能的,那么重新调整你的数据(或正常的先验)来反映这一点。如果你害怕离群值的影响,尝试使用 t 分布作为先验。正如本节开始时提到的,正态先验几乎总是比均匀先验好。

最后

每当你想使用制服优先,记住:只是不要

停止浪费你的时间,咨询一个主题专家

原文:https://towardsdatascience.com/stop-wasting-your-time-and-consult-a-subject-matter-expert-f6ee9bffd0fe?source=collection_archive---------51-----------------------

在从事数据科学项目时,请一位主题专家来审查您的工作可能会有所帮助。

来自像素像素的照片

当您开始为您的公司从事数据科学项目时,您可能会发现一个需要关注的问题,接收数据,清理数据,计算一些统计数据,并构建一个模型。但是,如果您不完全理解您正在使用的数据,您如何知道您是否在为公司提供有价值的见解呢?帮助理解数据并验证您的分析是主题专家(SME)发挥作用的地方。

什么是中小企业,谁是中小企业?

根据文章什么是主题专家?主题专家是对“特定工作、流程、部门、职能、技术、机器、材料或设备类型”有深刻理解的人这些人花了数年时间在他们的学科中发展自己,并在他们的领域中发展了专业知识。SME 保持对其特定领域的最新和完整的知识,并拥有多年的工作经验。当常识不足以解决问题时,你可以找这些人。

何时何地利用中小企业?

当您开始从事数据科学项目时,借助 SME 来更好地理解您正在分析的数据以及如何最好地看待问题可能会有所帮助。如前所述,如果一般知识不足以用数据集得出分析结论,那么就停止。为了给公司提供价值以及后续的行动项目,你需要退后一步考虑,这是一个我需要向 SME 寻求帮助的项目吗?

例如,如果您正在查看与公司特定领域相关的数据,如人力资源(HR),但您没有过去的人力资源经验,那么与拥有这些数据的中小型企业人力资源专业人员交谈可能会有所帮助。此人将能够更好地解释您正在查看的信息,理解您在尝试创建模型时可能需要考虑的领域,并能够通读和验证您的结果是否有意义。

这句话的最后一个方面是我认为最重要的。SME 可以通读您的分析和模型结果,并验证您的结果是否有意义。让别人看一下你的分析会对你接下来的步骤有所帮助。SME 可以根据他们对数据的理解,判断您的工作是否在正确的轨道上,或者您的分析是否没有意义。

考虑为计算机收集数据,然后分析这些数据。如果你的模型显示你的电脑屏幕不亮的原因是你的键盘上的 L 键坏了,这个输出对你来说有意义吗?大概不会。但是,如果你看着数据,它似乎是合理的,但你不确定,因为你没有系统作为一个整体的知识,会发生什么?理解你的结论是否有意义是 SME 能够有所帮助的原因。他们可以查看输出,并告诉你,不,这没有意义,因为你的键盘不能输入字母 L 不应该影响为什么你的显示器没有打开。

为什么需要中小企业?

当您从事数据科学项目并开始接触许多不同的数据类型时,问问自己,我对这些数据的理解是否足以对我的工作结果做出准确的预测或采取行动,还是没有?如果答案不是肯定的,那么你应该考虑咨询一个 SME,他可以坐下来和你一起看你的作品。与他们讨论手头的问题,你如何分析数据和你的输出。让别人检查你的工作可以为你提供有价值的反馈,让你知道你的分析是朝着正确的方向进行还是毫无意义。SME 在他们的领域有深入的知识,将帮助你根据你的数据设计有意义的结论,从而推动有价值的行动。

摘要

不是每个项目都需要你和主题专家交谈。你可能有足够的领域知识来得出结论并展示你的发现。但是如果你没有,不要为此担心。找一家你可以联系的中小企业,和你一起查看你的数据和分析。与他们讨论你的发现或问题,并询问他们的想法。这些人可以为您提供关于如何改进流程的宝贵反馈,以推动您正在寻找的有价值的行动。

你是否发现与中小企业合作有益?你如何在工作中利用它们?

如果你想了解更多,可以看看我下面的一些文章!

[## 每位数据科学工程师的前三本书

我放在书架上的伟大资源,我喜欢介绍给软件工程师和数据科学家。

towardsdatascience.com](/top-3-books-for-every-data-science-engineer-e1180ab041f1) [## 在数据科学中我们需要面向对象编程吗?

让我们讨论一下作为一名数据科学家转向面向对象编程的利弊。

towardsdatascience.com](/do-we-need-object-orientated-programming-in-data-science-b4a7c431644f) [## 清理数据时要问的 25 个问题

我在数据清理之前问这些问题,所以我知道开始时会遇到什么。

towardsdatascience.com](/25-questions-to-ask-as-you-clean-data-a8024537341b)

不要担心,在 30 分钟内创建您的深度学习服务器

原文:https://towardsdatascience.com/stop-worrying-and-create-your-deep-learning-server-in-30-minutes-bb5bd956b8de?source=collection_archive---------23-----------------------

对于所有的安装和环境

图片来自 PixabayBessi

每当我开始一个新项目时,我都发现自己一次又一次地创建深度学习机器。

您从安装 Anaconda 开始,最后为 Pytorch 和 Tensorflow 创建不同的环境,因此它们不会相互干扰。在这个过程中,你不可避免地会把事情搞砸,然后从头开始。而且这种情况经常发生多次。

这不仅仅是大量浪费时间;这也是强大的(试图避免亵渎这里)令人恼火。检查所有的堆栈溢出线程。经常想知道哪里出了问题。

那么有没有更有效的方法呢?

原来是有的。 在这篇博客中,我将尝试以最小的努力在 EC2 上建立一个深度学习服务器,以便我可以专注于更重要的事情。

这个博客明确地由两部分组成:

  1. 设置预装深度学习库的亚马逊 EC2 机器。
  2. 使用 TMUX 和 SSH 隧道设置 Jupyter 笔记本。

不用担心;这并没有听起来那么难。只需按照步骤操作,然后单击下一步。

设置 Amazon EC2 机器

我假设你有一个 AWS 帐户,并且你可以访问 AWS 控制台。如果没有,你可能需要注册一个亚马逊 AWS 账户。

  1. 首先,我们需要转到 Services 选项卡来访问 EC2 仪表板。

2.在 EC2 仪表板上,您可以从创建实例开始。

3.亚马逊提供预装深度学习软件的社区 AMIs(亚马逊机器映像)。要访问这些 ami,你需要在社区 ami 中查找,并在搜索选项卡中搜索“Ubuntu Deep Learning”。你可以选择任何其他的 Linux 版本,但我发现 Ubuntu 对我的深度学习需求最有用。在目前的设置中,我将使用深度学习 AMI (Ubuntu 18.04)版本 27.0

4.一旦选择了 AMI,就可以选择实例类型。您可以在这里指定系统中需要的 CPU、内存和 GPU 的数量。亚马逊根据个人需求提供了很多选择。您可以使用“过滤方式”过滤器来过滤 GPU 实例。

在本教程中,我用的是 p2.xlarge 实例,它为 NVIDIA K80 GPU 提供了 2496 个并行处理核心和 12GiB 的 GPU 内存。要了解不同的实例类型,您可以在这里查看文档,在这里查看定价

5.您可以在第 4 步中更改连接到机器的存储器。如果您没有提前添加存储,也没关系,因为您也可以在以后添加。我将存储从 90 GB 更改为 500 GB,因为大多数深度学习需求都需要适当的存储。

6.这就是全部,您可以在转到最终查看实例设置屏幕后启动实例。一旦你点击启动,你会看到这个屏幕。只需在密钥对名称中键入任意密钥名称,然后单击“下载密钥对”。您的密钥将以您提供的名称下载到您的计算机上。对我来说,它被保存为“aws_key.pem”。完成后,您可以单击“启动实例”。

保持这个密钥对的安全,因为每当您想要登录到您的实例时,都将需要这个密钥对。

7.现在,您可以单击下一页上的“查看实例”来查看您的实例。您的实例将如下所示:

8.要连接到您的实例,只需在本地机器上打开一个终端窗口,浏览到保存密钥对文件的文件夹,并修改一些权限。

chmod 400 aws_key.pem

一旦你这样做了,你将能够通过 ssh 连接到你的实例。SSH 命令将采用以下形式:

ssh -i "aws_key.pem" ubuntu@<Your PublicDNS(IPv4)>

对我来说,命令是:

ssh -i "aws_key.pem" ubuntu@ec2-54-202-223-197.us-west-2.compute.amazonaws.com

另外,请记住,一旦关闭实例,公共 DNS 可能会发生变化。

9.您已经启动并准备好了您的机器。这台机器包含不同的环境,其中有您可能需要的各种库。这台机器有 MXNet、Tensorflow 和 Pytorch 以及不同版本的 python。最棒的是,我们预装了所有这一切,因此开箱即可使用。

设置 Jupyter 笔记本

但是你仍然需要一些东西来充分使用你的机器。其中之一是朱庇特笔记本。要在您的机器上设置 Jupyter 笔记本,我建议使用 TMUX 和隧道。让我们一步一步地完成 Jupyter 笔记本的设置。

1.使用 TMUX 运行 Jupyter 笔记本

我们将首先使用 TMUX 在我们的实例上运行 Jupyter 笔记本。我们主要使用这一点,以便即使终端连接丢失,我们的笔记本仍然可以运行。

为此,您需要使用以下命令创建一个新的 TMUX 会话:

tmux new -s StreamSession

一旦你这样做了,你会看到一个新的屏幕,底部有一个绿色的边框。您可以使用常用的jupyter notebook命令在这台机器上启动您的 Jupyter 笔记本。您将看到如下内容:

复制登录 URL 是有益的,这样当我们以后尝试登录我们的 jupyter 笔记本时,我们将能够获得令牌。对我来说,就是:

[http://localhost:8888/?token=5ccd01f60971d9fc97fd79f64a5bb4ce79f4d96823ab7872](http://localhost:8888/?token=5ccd01f60971d9fc97fd79f64a5bb4ce79f4d96823ab7872&token=5ccd01f60971d9fc97fd79f64a5bb4ce79f4d96823ab7872)

下一步是分离我们的 TMUX 会话 ,这样即使您离开 SSH shell,它也能继续在后台运行。为此,只需按 Ctrl+B,然后按 D(按 D 时不要按 Ctrl ),您将返回初始屏幕,显示您已从 TMUX 会话中分离的消息。

如果需要,您可以使用以下命令再次重新连接到会话:

tmux attach -t StreamSession

2.通过 SSH 隧道在本地浏览器上访问笔记本

第二步是隧道进入 Amazon 实例,以便能够在本地浏览器上获得 Jupyter 笔记本。正如我们所看到的,Jupyter 笔记本实际上运行在云实例的本地主机上。我们如何访问它?我们使用 SSH 隧道。别担心,填空很简单。只需在您的本地机器终端窗口上使用以下命令:

ssh -i "aws_key.pem" -L <Local Machine Port>:localhost:8888 [ubuntu@](mailto:ubuntu@ec2-34-212-131-240.us-west-2.compute.amazonaws.com)<Your PublicDNS(IPv4)>

对于这种情况,我使用了:

ssh -i "aws_key.pem" -L 8001:localhost:8888 [ubuntu@](mailto:ubuntu@ec2-34-212-131-240.us-west-2.compute.amazonaws.com)ec2-54-202-223-197.us-west-2.compute.amazonaws.com

这意味着如果我在本地机器浏览器中打开 localhost:8001,我将能够使用 Jupyter 笔记本。我当然可以。现在,我们只需输入在之前的某个步骤中保存的令牌即可访问笔记本。对我来说令牌是5 CCD 01 f 60971d 9 fc 97 FD 79 f 64 a5 bb 4 ce 79 F4 d 96823 ab 7872

您只需使用您的令牌登录,瞧,我们就能获得这款荣耀的笔记本电脑。

现在,您可以通过选择任何您想要的不同环境来选择一个新项目。你可以来自 Tensorflow 或 Pytorch,或者可能愿意同时拥有两个世界的优势。这款笔记本不会让你失望。

解决纷争

一旦机器重新启动,你可能会遇到一些 NVIDIA 显卡的问题。具体来说,在我的例子中,nvidia-smi命令停止了工作。如果遇到这个问题,解决方法是从 NVIDIA 网站下载显卡驱动。

以上是我选择的特定 AMI 的设置。点击搜索后,您将看到下一页:

只需右键点击复制链接地址即可复制下载链接。并在您的机器上运行以下命令。您可能需要更改此中的链接地址和文件名。

# When nvidia-smi doesnt work:wget [https://www.nvidia.in/content/DriverDownload-March2009/confirmation.php?url=/tesla/410.129/NVIDIA-Linux-x86_64-410.129-diagnostic.run&lang=in&type=Tesla](https://www.nvidia.in/content/DriverDownload-March2009/confirmation.php?url=/tesla/410.129/NVIDIA-Linux-x86_64-410.129-diagnostic.run&lang=in&type=Tesla)sudo sh NVIDIA-Linux-x86_64-410.129-diagnostic.run --no-drm --disable-nouveau --dkms --silent --install-libglvndmodinfo nvidia | head -7sudo modprobe nvidia

停止您的实例

仅此而已。你已经拥有并运行深度学习机器,你可以随心所欲地使用它。请记住,无论何时停止工作,都要停止实例,这样当您不在处理实例时,就不需要向 Amazon 付费了。您可以在实例页面上右键单击您的实例来完成此操作。请注意,当您需要再次登录到这台机器时,您需要从实例页面获取公共 DNS (IPv4)地址,因为它可能已经更改。

结论

我一直觉得建立深度学习环境是一件很大的苦差事。

在这篇博客中,我们通过使用深度学习社区 AMI,TMUX 和 Jupyter 笔记本的隧道,在最短的时间内在 EC2 上建立了一个新的深度学习服务器。该服务器预装了您工作中可能需要的所有深度学习库,并且开箱即用。

你还在等什么?用自己的服务器开始深度学习就行了。

如果你想了解更多关于 AWS 以及如何在生产设置和部署模型中使用它,我想在 AWS 上调出一个优秀的课程。一定要去看看。

谢谢你的阅读。将来我也会写更多初学者友好的帖子。在媒体关注我,或者订阅我的博客来了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系到我

此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。

用误导的图表阻止新冠肺炎

原文:https://towardsdatascience.com/stopping-covid-19-with-misleading-graphs-6812a61a57c9?source=collection_archive---------1-----------------------

阿根廷、俄罗斯和格鲁吉亚媒体如何在新冠肺炎期间操纵图表来推动他们的议程。

自新冠肺炎疫情爆发以来,全世界的媒体都在争相制作关于疫情的最漂亮、最翔实的图表。图表在向普通观众传达复杂的统计数据方面非常出色。图表还擅长误导人们对世界做出错误的结论。一些媒体因其在统计方面的无能而误导,而另一些媒体则故意操纵数据来描绘他们国家更好的图景。在这篇文章中,我们将看看阿根廷、俄罗斯和格鲁吉亚媒体是如何通过操纵图表来“抗击”疫情的。

阿根廷的新冠肺炎测试次数

如果你需要证明你的国家在测试人方面很棒,只需向阿根廷媒体寻求建议,他们在下图中做得很好:

阿根廷电视频道 C5N 操纵 y 轴来隐藏新冠肺炎测试的可怕数字。来源: Reddit 。原文来源: C5N

图表显示了每百万人中新冠肺炎测试的数量。对于不讲西班牙语的人来说,EEUU 是美国,Alemania 是德国,Noruega 是挪威。现在,看看那些柱状图:阿根廷测试的人数几乎和美国一样多!至少在你看数字之前看起来是这样。阿根廷每百万检测 330 人,而美国检测 7000 人。这是 20 倍多,但美国的标准只有 1.2 倍高。这张图表让阿根廷在测试人方面看起来还不错,但事实显然并非如此。电视频道任意操纵条形的大小,完全不考虑逻辑或缩放规则。这是未经处理的图形外观:

阿根廷的新冠肺炎图表做对了。作者的数据可视化。

这种可视化描绘了一幅完全不同的画面,表明阿根廷远没有美国和其他国家那样多的测试。但是谁想看到坏消息呢,对吧?

俄罗斯使曲线变平

把曲线拉平是每个国家都痴迷的事情,并不是一件容易的事情。但不是这个俄罗斯电视频道:

俄罗斯 3 月 5 日至 3 月 31 日的新冠肺炎病例数。来源: Reddit 。原文来源:今日俄罗斯

图表显示了从 3 月 5 日到 3 月 31 日新冠肺炎病例的增长情况。病例开始快速增长,但自 3 月 26 日以来,增长似乎放缓,并接近曲线的顶部。然而,正如我们从阿根廷图表中了解到的那样,外表可能具有欺骗性。

在 3 月 26 日之前,条形的高度与数字相对应。例如,您可以通过查看包含 495 个案例的 3 月 24 日棒线是包含 253 个案例的 3 月 20 日棒线的两倍来验证这一点,视觉上的增加对应于数字上的增加,其中 495 几乎是 253 的两倍。然而,从 3 月 26 日开始,条形的缩放变得与数字差异不一致。如果你看看这些数字,增长率保持不变:

  • 3 月 28 日新增病例+228 例(增长 22%)
  • 3 月 29 日+270(增长 21%)
  • 3 月 30 日+302(增加 20%)
  • 3 月 31 日+500(增长 27%)

然而,这些变化并没有用柱状图准确地描述出来。3 月 31 日病例增加 500 例并不对应于视觉上的增加,视觉上的增加显示了大约 50 例的增加。电视频道给上周的酒吧指定了任意的高度。下图应该是这样的:

新冠肺炎案例的俄罗斯图表做对了。作者的数据可视化。

在这个图表中,视觉上的差异与数字上的差异相对应,并描绘了一幅准确的画面:病例呈指数增长,这是一个不好的迹象。此外,如果你想知道,俄罗斯的图表也不是对数图。

更糟糕的是,由于这些图表是在电视上播放的,它们只显示了几秒钟,这对于任何人来说都太短了,无法详细检查图表并评估其标签、单位以及视觉元素与数值的对应关系。大多数人只会花几秒钟时间看一下柱状图,然后得出结论:情况正在好转。我们中很少有人会努力暂停电视,批判性地关注图表,一些媒体利用它来欺骗我们。

格鲁吉亚消灭了病毒

虽然对于前两张图,你仍然可以想出一些借口,如节省空间或使条形更明显,但来自佐治亚州公共卫生部的这张图没有留下原谅的余地:

来源: Reddit 。最初来自佐治亚州公共卫生部

图表显示了从 4 月 28 日到 5 月 9 日新增病例数量的下降。然而,看看 x 轴上的日期顺序:4 月 28 日,回到 4 月 27 日,现在是 4 月 29 日,4 月 26 日一直在 5 月 7 日和 5 月 3 日之间。人们不可能不小心把日期排列成如此奇怪的顺序。它需要手动和有意识的重新洗牌。

格鲁吉亚人很快就发现了操纵行为,并表达了他们的不满。一天后,图表被撤下,州长发言人坎迪斯·布罗斯为这个奇特的数字道歉:

提供的借口并没有使图表更有信息量,我不认为有任何方法来证明这样的错误。格鲁吉亚政府本可以利用这张图表来说服其公民支持早日重新开业。如果你想了解更多关于此案的信息,亚特兰大宪法日报有一篇很棒的文章。

结论

正如我们所见,有时媒体利用公众缺乏关注来推动他们的议程。我们对这些图表的误导性解释可能会影响我们投票、行为和决策的方式。因此,在如此多的图表中,停下来问一些关键问题是很重要的:

  • 视觉效果和数字相符吗?
  • y 轴和 x 轴的顺序和比例是否正确?
  • 图表是夸大了某件小事的重要性,还是相反?

核对每一张图表并不总是容易的,但这是不被数据操纵所误导的必要条件。因此,让我们留意我们消费的新闻,并仔细思考我们相信的信息。

谢谢你看我的文章!如果你有任何意见、担忧或问题,我很乐意在评论中讨论!

启发我写这篇文章的书:达雷尔·赫夫的《如何用统计数据撒谎》。

你可以在 Reddit 上的 r/dataisugly 找到更多误导性和糟糕的图表。

在 CouchDB 中存储 Hyperledger 结构证书和密钥

原文:https://towardsdatascience.com/store-hyperledger-fabric-certificates-and-keys-in-couchdb-43c8f91a61b0?source=collection_archive---------20-----------------------

Hyperledger Fabric 是关于权限的。这些权限以证书和密钥的形式提供。从广义上讲,它被称为身份。

照片由迈卡·威廉姆斯Unsplash 上拍摄

当应用程序与 Hyperledger Fabric 网络交互时,它使用此身份来验证自己。结构网络验证身份并授权应用程序进行交互。

简而言之,身份是非常重要的,如果你不妥善保存,那么它可能会变成一个令人头痛的问题。😩

最初发布于https://schadokar . dev

我可以在哪里存储身份?💼

在 Hyperledger 结构中,这种存储被称为 钱包

钱包有三种类型:

文件系统

这是一个简单的文件夹。本地存储钱包。对于钱包来说,这是一个不错的默认选择。在fabric-samples/balance-transfer中,file system是默认的钱包。当你运行balance-transfer时,它会创建一个fabric-client-kv-orgName文件夹并保存所有的身份。这个配置是在orgname.yaml链接中定义的。

内存中

应用存储中的钱包。当您的应用程序在不能访问文件系统的受限环境中运行时,请使用这种类型的 wallet 通常是网络浏览器。值得记住的是,这种类型的钱包是不稳定的;应用程序正常结束或崩溃后,身份将会丢失。— 文档

CouchDB

用 couchdb 当钱包。此选项最适合生产。

在本教程中,我们将把CouchDB配置为钱包。👨🏻‍💻

为了演示,我使用了Fabric Node SDKfabric/samples/balance-transfer

钱包使用 2 个存储来保存证书和密钥:

1.州商店:

状态存储用于存储注册身份的证书。它存储了身份的基本信息:

{
  "name": "test",
  "mspid": "org1",
  "roles": null,
  "affiliation": "",
  "enrollmentSecret": "<ENROLLMENT_SECRET>",
  "enrollment": {
    "signingIdentity": "<PRIVATE_KEY_NAME>",
    "identity": {
      "certificate": "<SIGN_CERT>"
    }
  }
}

❗️ 注意:签名标识是存储在加密存储中的私钥和公钥的指针或地址。

2.加密存储:

加密存储用于存储身份的公钥和私钥。

要将 couchdb 配置为 wallet:

第一步

导入由Node SDK提供的CouchDBKeyValueStore库。

**const CDBKVS = require("fabric-client/lib/impl/CouchDBKeyValueStore.js");**

请务必阅读《T4 》,它值得一读。

第二步

设置state store

**let stateStore = await new CDBKVS({
  url: "https://<USERNAME>:<PASSWORD>@<URL>",
  name: "<DB_NAME>"
});

const Client = require("fabric-client");

const client = Client.loadFromConfig("path of network.yaml");

client.setStateStore(stateStore);**
  • <USERNAME>是 couchdb 的用户名。
  • <PASSWORD>是 couchdb 的密码。
  • <URL>是 couchdb 的 URL。
  • <DB_NAME>(可选)是用作状态存储的数据库名。默认的 dbname 是userdb。如果数据库不存在,它会创建它。

客户端 是用户和光纤网络之间的接口。

第三步

设置crypto store

**const cryptoSuite = Client.newCryptoSuite();

let cryptoKS = Client.newCryptoKeyStore(CDBKVS, {
  url: "https://<USERNAME>:<PASSWORD>@<URL>",
  name: "<DB_NAME>"
});

cryptoSuite.setCryptoKeyStore(cryptoKS);

client.setCryptoSuite(cryptoSuite);**

您必须根据上述步骤更新客户端,使其使用 couchdb。
在下一节中,我们将在balance-transfer fabric 示例中实现上述步骤。

CouchDB 在平衡传递中的实现

我使用平衡转移织物样品作为参考。

我假设你知道如何进行余额转移。

启动余额转移网络

按照余额转移说明启动网络。

它将通过以下方式启动网络:

  • 2 CAs
  • 单独订购者
  • 4 个同行(每个组织 2 个同行)

为钱包启动 couchdb

如果您使用基于云的 couchdb,这一步是可选的。

基于 Docker 的 Couchdb

**docker run --name couch-userdb -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=password -p 5984:5984 -d couchdb**

如果不存在,上述命令将从 docker hub 中提取couchdb的 docker 图像。

CouchDB 详细信息:

  • 容器名称:couch-userdb
  • CouchDB 用户名:admin
  • CouchDB 密码:password
  • 网址:localhost:5984

CouchDB 连接 URL 是

https://<USERNAME>:<PASSWORD>@<URL> [**https://admin:password@localhost:5984**](https://admin:password@localhost:5984)

在余额转移中更新客户

打开app/helper.js,更新getClientForOrg

在下面的代码中,我们只是用上面的 couchdb 配置步骤替换了await client.initCredentialStores();

我们所做的改变,

  • 第 13 行: 导入CouchDBKeyValueStore。从上面开始。
  • 第 31–52 行: 设置状态存储和加密存储。第二步& 3。

上面的代码有一个小的变化。

**// Client variable is used as hfc
var hfc = require("fabric-client");

// Instead of Client
const Client = require("fabric-client");**

状态存储和加密存储的 db(dbname)不必相同。两家商店都可以有各自独立的数据库。这取决于要求。您可以将状态存储和加密存储 db 分别命名为 ***orgName-state-store*** ***orgName-crypto-store*** 每个组织必须有自己的状态存储和加密存储 db,否则会抛出认证错误。

**Error: fabric-ca request register failed with errors [[{"code":20,"message":"Authentication failure"}]]**

在余额转移中注册新用户

一旦注册了用户,就可以使用 couchdb apis 检查状态存储和加密存储。

例如:注册一个用户

我使用下面的参数来注册一个用户。对于org1,我对state-storecrypto-store使用了相同的 db org1db

  • 名称:alice
  • 组织:org1
  • 数据库名:org1db
  • CouchDB URL: [**http://admin:password@localhost:5369**](http://admin:password@localhost:5369)

打开浏览器,转到**http://localhost:5369/org1db/_all_docs**。返回保存在org1db中的所有文档。

指标0, 1, 2admin的证书。

索引3是存储在state-store中的alice证书。
索引4-5crypto-store中存储的alice的公钥和私钥。

转到http://localhost:5369/org1db/alice。它返回存储在状态存储中的alice的所有细节。

检查signingIdentity

**"signingIdentity":"d37a97a8c2377c21537801ec1a929d81905ae57963a2f6c8ba0308931a7fc791"**

现在,检查上图中索引4 & 5的 id。两者是一样的。

如果您还记得,signingIdentity字段是存储在加密存储中的身份的私钥和公钥的引用。

结论

CouchDB wallet 是生产用例的绝佳选择。您可以尝试使用其他数据库,但是在这种情况下,您必须像CouchDBKeyValueStore.js一样编写相应的库。

以下是我觉得有用的参考资料。如果您发现任何您认为可以添加到此处的资源,请不要羞于分享。😉

参考📌

原载于https://schadokar . dev

基于 NLP 和时间序列的特朗普竞选策略分析

原文:https://towardsdatascience.com/strategic-analysis-of-trump-rallies-with-nlp-and-time-series-618615daec20?source=collection_archive---------23-----------------------

主题建模、聚类和时间序列预测的案例研究

马特·史密斯快门上拍摄的照片

美国总统选举将于 2020 年 11 月 3 日决定,对美国和世界产生巨大影响。虽然一些人认为特朗普是一位好总统,但其他人认为他是一位民粹主义者。不管一个人的政治倾向是好是坏,2020 年大选的后果可能会是惊天动地的。

尽管如此,在这篇文章中,我将向你展示特朗普集会的战略分析,作为拜登-哈里斯竞选团队事实上的数据科学家。我将尝试使用自然语言处理(NLP)对反弹进行主题建模,然后在提供策略分析之前,我将使用时间序列识别反弹中的主题趋势。首先,我从 https://factba.se/transcripts那里获得了川普集会的记录。

1.文本预处理

从 2017 年特朗普的第一次集会(佛罗里达州墨尔本)到 2020 年 10 月 12 日特朗普从新冠肺炎恢复后的第一次集会(佛罗里达州桑福德),我总共获得了约 100 份特朗普集会记录的数据。此后,我将数据放入 Pandas 数据框,以地点、日期和记录为列。以下是特朗普在佛罗里达州桑福德的集会摘录,我们立即看到了文本处理的必要性:

大家好。你好,奥兰多。你好,桑福德。和你在一起真好。谢谢你。回来真好。[观众唱“美国”]这是很多人。你知道我们的竞争对手,瞌睡虫乔,他今天有个集会,但几乎没人出席。我不知道这是怎么回事。昏昏欲睡的乔,但回到我的家乡佛罗里达州进行我的正式竞选活动真是太棒了。你们的祈祷让我充满活力,你们的支持让我谦卑。我们得到了难以置信的支持,现在我们在这里。你知道,我们在这里。但是我们会完成的,我们会让这个国家比以往任何时候都更伟大。[观众高呼“我们爱你”]谢谢。谢谢你。谢谢您们。

使用正则表达式,我从文字记录中删除了观众输入(在方括号中)。我还使用 NLTK 的 RegexpTokenizer 对包含 3 个或更多字母的单词进行标记,并删除带有任何标点符号的单词,然后再将它们连接到一个经过处理/分割的抄本中。

2.EDA——特朗普的 50 大词汇

有了一套“干净”的抄本,我开始着手建模。在探索性数据分析中,我使用 WordCloud 生成了特朗普在他的前两次集会和我获得的后两次集会中经常使用的前 50 个词:

前两场拉力赛:佛罗里达拉力赛,2017 年 2 月(左)和田纳西拉力赛,2017 年 3 月(右)-作者图片

对于 WordCloud 图片,单词越大意味着该单词在抄本中出现的频率越高。通过上面的可视化,我们可以看到为什么特朗普对他的支持者如此有影响力,频繁使用诸如“去”、“伟大”、“人民”和“国家”等词,激发情绪和不断呼吁采取行动。我们还看到“奥巴马医改”的出现,显示了特朗普在总统任期早期的执着。

最近的两场拉力赛:2020 年 9 月的明尼苏达拉力赛(左)和 2020 年 10 月的佛罗里达拉力赛(右)——图片由作者提供

在最近两次集会中,我们看到特朗普的用词没有太大变化。“去”、“人民”和“伟大”等词继续是热门词汇,而“拜登”和“中国”等词出现在特朗普开始在大选临近时攻击政治对手之际。

3.NLP —主题建模

谈到主题建模,我们通常使用 Scikit-Learn 的计数矢量器或 TFIDF 矢量器将转录本中的所有单词量化为特征。此后,我们通过潜在语义分析(LSA)、非负矩阵分解(NMF)或潜在狄利克雷分配(LDA)将所有特征简化为组件(特征的线性组合)。因此,可以通过过滤组件的顶部单词来识别主要主题。

经过反复试验,我认为 NMF 的 Count Vectorizer(总共 11353 个单词)是特朗普集会的最权威工具。通过仔细的分析和辨别,我从 NMF 的组成部分中找出了 3 个主题(使用了 90 个热门词汇):

  • 话题一:吹捧成绩
know, said, **right**, people, like, **great**, got, think, **going**, want, **good**, **lot**, **years**, **president**, guy, time, thing, look, **won**, sir, **trump**, love, **way**, **big**, billion, remember, come, let, money, million, went, **deal**, better, tell, little, year, new, mean, guys, world, things, came, democrats, **thank**, bad, win, state, **best**, country, **beautiful**, hell, times, ago, **believe**, actually, michigan, true, took, somebody, party, crazy, obama, american, **incredible**, fake, getting, job, place, happened, day, **greatest**, man, long, china, away, saying, number, news, america, election, night, nice, wouldn, states, care, **history**, wanted, everybody, texas, maybe
  • 主题 2:计划和寻求支持
**going**, great, **want**, **people**, country, **thank**, **vote**, know, **america**, **american**, **right**, like, years, president, got, democrats, way, **good**, **jobs**, time, lot, **need**, think, said, come, **new**, state, **job**, let, love, incredible, **care**, states, americans, tell, united, **believe**, history, **tax**, **borders**, look, **election**, democrat, big, working, republicans, military, **wall**, **coming**, **happen**, world, percent, **law**, republican, **border**, **taxes**, won, billion, **protect**, trump, work, things, man, governor, **happening**, thing, pay, **win**, **deal**, ice, beautiful, day, remember, party, veterans, **help**, folks, **voted**, **passed**, everybody, greatest, strong, florida, called, bad, women, illegal, hard, **unemployment**, today
  • 话题 3:攻击政治对手
**going**, know, **said**, people, got, **biden**, great, like, right, want, think, years, **joe**, good, way, thank, **china**, **remember**, america, lot, country, let, thing, look, tell, **win**, guy, time, job, **big**, **world**, **left**, president, american, mean, **police**, **law**, **bad**, won, states, happen, called, things, deal, **history**, better, love, state, **hell**, ago, new, took, end, **little**, wants, half, **ballots**, happened, **vote**, open, year, everybody, come, wall, jobs, went, **crazy**, **news**, second, **terrible**, **governor**, day, **sleepy**, **bernie**, **order**, pennsylvania, peace, north, military, energy, seen, watch, saw, suburbs, gave, closed, war, **fake**, trump, saying

采用新组件作为模型的特征(而不是来自计数矢量器的量化单词),NMF 能够将主题相关性分数归因于每个集会。随后,我继续绘制各次集会的主题相关性时间序列:

集会中主题相关性的时间序列(按连续的时间顺序绘制)-作者图片

从时间序列中,我们可以看到,虽然“吹捧成就”的主题没有显示出明显的趋势,但“计划和呼吁支持”的主题似乎在接近选举时呈下降趋势。关于“攻击政治对手”的话题显示出明显的上升趋势,接近选举的平台期。因此,特朗普在竞选集会上的语气似乎有所转变——特朗普似乎对自己的计划不太乐观,正在更多地攻击他的对手。这也可以通过余弦相似性热图清楚地观察到:

2020 年 10 月 12 日以来特朗普最后 20 场集会的余弦相似性热图。(图片由作者提供)

查看热图的第一列(与 10 月 12 日的集会相比),特朗普在 2020 年 3 月 2 日集会上的语气似乎发生了突然转变。美国新冠肺炎的突然爆发会不会让川普缺乏安全感,从而促使他更多地攻击对手?

此外,我们在 2020 年 9 月 18 日的集会上观察到另一种语气的转变——根据时间序列,特朗普似乎对他的成就感到欢欣鼓舞。巧合的是,这也是最高法院大法官金斯伯格(民主党人)去世的日子。这是否也导致了特朗普语气的转变?

4.进一步 EDA:K-均值聚类

为了进一步分析特朗普集会,让我们探索一下是否可以根据其主题相关性将其分为几组。结果是,在绘制了总惯性与聚类数的关系以及剪影系数与聚类数的关系之后,我们可以:

总惯性与聚类数的关系图(左)和剪影系数与聚类数的关系图(右)-作者提供的图片

尽管我们无法在总惯性对聚类图中清楚地识别出一个弯头(弯头方法),但轮廓系数图清楚地表明,聚类的最佳数量是两个!轮廓系数通常在 1 和-1 之间评分,并量化一个点到聚类质心和远离其他聚类质心的接近程度。

接下来,我们用 Plotly 制作了一个特朗普集会的三维图,其中我们看到了两种类型的特朗普集会,他主要攻击政治对手或主要吸引选民:

特朗普集会与主题相关性的三维图。(图片由作者提供)

5.用 SARIMA 进行时间序列预测

回到我们的时间序列图,我们注意到一些有趣的事情——特朗普集会中似乎有一种主题相关性的周期性暗示。此外,关于“计划和呼吁支持”和“攻击政治对手”的主题似乎也有趋势成分。因此,时间序列是非平稳的,我们可以使用季节性自回归综合移动平均(SARIMA)模型进行预测分析。

集会上的主题相关性时间序列(按连续顺序),显示周期性。(图片由作者提供)

沿着探索的道路,我通过以 90:5:5 的比例将数据集分为训练集、验证集和测试集,进行了简单的正向验证

简单的验证模式。验证和测试集在时间上向前验证。(图片由作者提供)

使用 SARIMA 对最佳超参数进行简单的网格搜索后,我获得了以下平均绝对误差(MAE)分数:

使用最佳超参数,我将训练和验证集与 SARIMA 模型一起重新训练,然后在测试集上进行评估。我发现下面的错误分数还是很合理的:

跨集会的主题相关性时间序列及其在最近 6 次集会中的预测。(图片由作者提供)

6.模型与策略一起使用

时间序列预测模型可用于发现未来特朗普集会主题的潜在波峰和波谷。虽然拜登-哈里斯竞选团队可能有自己的一套对抗特朗普竞选团队的策略,但人们也可以参考中国古代战略手册《孙子兵法》,该手册提倡与对手反其道而行之。

“强的时候,避开他们。如果士气高昂,就让他们沮丧。似乎卑微到让他们充满自负。如果放心,就把它们耗尽。如果团结,就把他们分开。攻击他们的弱点。让他们大吃一惊。”
孙子

例如,拜登可以在特朗普被预测不那么咄咄逼人的时候更多地攻击他。相反,拜登可以吸引人群,并在特朗普预计会更具侵略性时谈论他的计划。因此,一个可以预测特朗普在竞选中的气质和语气的模型对拜登-哈里斯阵营非常有用。

7.结论

综上所述,我已经完成了对特朗普集会的颇有见地的探索性数据分析,也创建了对特朗普话题趋势的预测模型,作为案例研究。

这份仔细的分析是 Metis 数据科学训练营(新加坡)的项目 4,我要感谢所有人,特别是我的导师尼奥·韩伟,他迄今为止一直在指导我。这是一次令人兴奋的经历,也是一次惊人的学习之旅。谢谢大家!

这里是到我的 GitHub 的链接,它包含了这个项目的所有代码和演示幻灯片。也可以通过我的 LinkedIn 联系我或在下面评论来讨论!

支持我! —如果你没有订阅 Medium,并且喜欢我的内容,请考虑通过我的推荐链接加入 Medium 来支持我。

[## 加入我的介绍链接媒体-谭师鹏阿尔文

阅读谭·师鹏·阿尔文(以及媒体上成千上万其他作家)的每一个故事。您的会员费直接…

tanpengshi.medium.com](https://tanpengshi.medium.com/membership)

提高客户分析成熟度的战略方法

原文:https://towardsdatascience.com/strategic-approach-to-advance-your-customer-analytics-maturity-a873bd761988?source=collection_archive---------49-----------------------

客户分析成熟度级别和不同成熟度级别公司的战略路线图

Unsplash 上由 Austin Distel 拍摄的照片

根据麦肯锡的一项研究,广泛利用客户分析的公司更有可能在关键绩效指标上超越竞争对手,无论是利润、销售额、销售增长还是投资回报

如今,企业已经意识到,客户分析是在当今市场中获得竞争优势的必备能力。近年来,客户数据的泛滥为企业更好地了解他们的客户并在战略决策中占据中心位置提供了一系列机会。然而, research 表示,虽然企业拥有本地化分析能力,但不到 15%的企业拥有根深蒂固的分析能力,或者认为这是他们组织内的一种差异化能力。

企业正在努力组织和构建大量的消费者数据,努力从多个接触点获取高质量的数据,并建立一种包含洞察力驱动的决策的组织文化。 Forrester 的客户分析成熟度评估为企业提供了涵盖六项关键能力的基准客户分析成熟度水平:战略、结构、数据、分析、流程和技术。根据客户分析成熟度报告,公司可以分为三个成熟度等级——初级、中级和高级。

初学者:有时使用基于汇总数据的后视镜报告分析,但不使用它来收集和分析有用的客户信息的公司属于初学者类别。这些公司没有投资专门的资源来处理消费者数据并推断出有价值的见解,而是基于假设和预感做出不科学的决策。对于这些公司来说,数据是在小仓库中获得的,并且数据提取源没有被缝合在一起以创建客户的单一视图。这些公司采用免费的分析工具或部分集成的 martech 平台来管理和组织数据。

中级:这些公司正处于从报告向洞察和注重行动的分析转变的过程中。这些公司将拥有专门的资源或团队(分析专家或数据科学家),他们正在学习将数据和见解转化为行动。团队努力创造一种数据驱动的文化,这种文化基于消费者的洞察和智能来支持协作决策。数据源被缝合在一起,集中于创建客户的单一视图,并且还促进了强大的归因能力。

高级:高级公司正在利用分析技术实时释放消费者意图信号和情感,在多个接触点提供有意义的个性化体验。这些公司采用人工智能驱动的分析和见解,专注于提供显著的投资回报率和 CX 改善。这些公司将有数据分析师和数据科学家团队与业务团队合作,共同致力于为消费者提供下一个最佳体验。团队能够处理非结构化数据,并将受众数据无缝地推送到集成的 martech 和 business tech 平台。这些公司通常采用完全集成的体验平台,包括营销云。

下面提到的是不同成熟度的公司的战略路线图。

一旦团队评估了他们当前的分析成熟度并确定了战略路线图,下一个任务就是确定实现客户分析成功的关键驱动因素。对于每一个公司来说,要将他们的成熟度等级提高到高级,团队必须努力建立实现关键业务目标所必需的能力。这些能力不仅将推动营销的改进,还将为客户服务、入职、保留和其他职能团队提供有意义的见解。

客户分析成功的战略方法

Unsplash 上由 Adeolu Eletu 拍摄的照片

  1. 能够创建客户的单一视图:

数据驱动型企业的口头禅是客户情报和可操作见解的重要性。在客户体验时代,领先的企业确保在各种不同的接触点和设备上最大限度地了解他们正在接触的客户和潜在客户。这成为满足多个跨职能团队需求的客户智能的基石。创建单一客户视图的能力使多个业务职能部门能够在正确的时间和地点做出最合适的决策,以提供增强的无缝客户体验。

客户分析必须从整体层面来看,考虑通过自有、付费和盈利媒体跟踪的消费者情绪和行为。从搜索引擎上的查询中捕获的消费者意图信号可以传递到统一的客户数据平台,该平台可以进一步推送到活动工作流,以实时触发定制的直接渠道活动。事实上,捕捉意图层面的数据甚至可以触发一线员工在各种线下接触点向消费者传达相关信息,并促成令人印象深刻的结果。

这将进一步导致消费者以特定的方式做出响应,并且数据必须再次传递回统一数据平台,以便为特定消费者的购买漏斗提供更多行为洞察。创建客户的单一视图不仅包括实时交付上下文体验,还将允许分析平台不断学习、优化各种底层流程,并向相关利益相关方推荐规范的见解。

2。能够进行预测性和规范性分析:

推动实时决策和触发沟通事件不仅是可能的,而且越来越有望成为卓越客户体验的基础组成部分。另一项能力是执行预测和说明性分析的能力,这是由客户交互的完整视图和技术的有效使用支撑的。

预测分析有助于企业根据历史消费者数据了解最有可能的未来情景及其影响。预测分析可以展示在“假设”场景中可能发生的情况,使企业能够预测任何给定流程中的哪些变化最有可能成功或失败。在营销领域利用预测分析的一个最成功的用例是线索评分。营销人员通常利用数据管理平台或客户数据平台上的潜在客户评分功能。这使得品牌能够为不同类别的潜在客户(热销售线索、温销售线索或冷销售线索)提供差异化的处理方式。

说明性分析利用人工智能和人工智能,使企业能够从消费者洞察中学习,并在整个消费者旅程中自动指定行动。说明性分析的用例可以在个性化、受众细分、内容管理等领域找到。Adobe Test and Target 使用说明性分析,根据历史用户行为向消费者推荐跨自有资产的下一个最佳体验。

3。建立归因模型的能力:

斯蒂芬·道森Unsplash 上拍摄的照片

随着洞察能力系统的出现,尤其是在自动化营销领域,营销人员和分析师必须建立模型,确定如何将任何形式的转化的信用分配给转化路径中的接触点。对于企业来说,了解哪些渠道在多大程度上促成了特定的转化是至关重要的。企业可以从付费搜索或自然搜索结果中获得巨大的流量转换率。但这是否意味着以多种频率展示给消费者的展示广告活动对整体转化率没有贡献呢?

在大多数潜在客户开发或客户获取案例中,都有涉及帮助渠道的流程,如呼叫中心、触发式电子邮件、短信等,以将离开的访问者带回购买之旅。在这种情况下,营销人员考虑多渠道渠道来比较不同归因模型如何影响不同接触点的价值变得至关重要。为了比较线下和线上渠道对推动在线转化的影响,企业必须认识到平台集成和自动化的重要性。

捕捉消费者时刻并根据分析生成的消费者情报触发行动的能力在很大程度上取决于如何将内部应用程序和 martech 平台缝合在一起,从而无缝地摄取离线数据。

建立餐馆的战略集群

原文:https://towardsdatascience.com/strategic-location-for-establishing-an-asian-restaurant-c3aecf2496b1?source=collection_archive---------22-----------------------

使用 k-Means 聚类实现在加拿大多伦多开设亚洲餐馆的最佳位置

加拿大多伦多蕾切尔安娜贝尔

多伦多街区根据它们的集群标签进行颜色编码

1。简介

1.1 背景

建立一家新餐馆的成功取决于几个因素:需求、品牌忠诚度、食物质量、竞争等等。在大多数情况下,一家餐馆的地理位置是其成功的决定性因素。因此,为了最大化商业利润,确定最具战略意义的建立地点是有利的,也是最重要的。

1.2 业务问题

一位客户寻求在多伦多附近建立一家专营东南亚美食的亚洲餐厅。哪个社区似乎是企业运营的最佳和最具战略意义的位置?

这个顶点计划的目标是为操作定位最佳邻域。我们推理的基础是基于消费能力、种族群体的分布和每个社区的竞争。我们将主要利用 Foursquare API 和来自多伦多开放数据门户的大量地理和人口普查数据。

1.3 利益

寻求建立一个特定领域的新餐馆或计划扩大其特许餐馆的企业家伙伴们会对这一发现可能带来的竞争优势和商业价值非常感兴趣。

2。数据采集和清理

2.1 数据来源

他们各自的邮政编码和行政区旁边的街区是从维基百科上搜集来的。每个街区的地理坐标都是从这里提取的。至于多伦多的人口普查数据——家庭收入中值、总人口和每个街区的东南亚人口——多伦多的开放数据门户在这里提供了所有这些数据

为了返回每个街区附近亚洲餐馆的数量,我们将利用 Foursquare API,更具体地说,它的 explore 函数。你必须注册一个 Foursquare 开发者账户才能访问他们的 API 证书。

2.2 数据清理

从多个来源下载或搜集的数据被合并到一个表中。由于缺乏记录,某些街区有很多缺失值。为实现图 1 中所示的数据帧,进行了一些假设:

  • 只会处理具有指定区的像元;未分配的行政区被忽略。
  • 丢失两个以上普查数据值的邻域被删除。
  • 通过将东南亚人口统计的人口数除以每个街区的总人口数,计算出东南亚人口在每个街区的分布百分比;后两列是多余的,被删除了。

图 1:数据清理后的数据帧

3。探索性数据分析

3.1 树叶映射

该图书馆被称为帮助可视化,从地理上来说,每个以多伦多为中心的街区的位置。

图 2:用叶子在多伦多地图上标出的街区

3.2 亚洲餐厅的频率分布

使用 Foursquare API 的 explore 函数,我们可以返回位于每个街区的亚洲餐馆的数量。通过分别计算平均值,它可以让我们更好地了解每个邻域的发生频率。使用亚洲餐馆频率的理由是,我假设亚洲餐馆的数量和竞争之间存在相关性。一个街区中所述餐馆的数量越多,竞争就越激烈。我们分析的假设是,在竞争激烈的市场中建立一家新餐厅的进入壁垒很高,因为现有的亚洲餐厅可能具有品牌忠诚度的竞争优势。

虽然,与直觉相反,这些餐馆的存在可能是对亚洲美食需求的一个指标;竞争的存在甚至可能激励创新以降低成本和提高生产率。

因此,在一个由大约中等价值的餐馆组成的街区建立商业经营是合理的。

图 3:每个街区亚洲餐馆的平均频率分布

3.3 东南亚人口分布

我假设在一个特定的种族群体的人口和对其各自文化的需求之间也存在着线性关系。因此,对我们的客户来说,在东南亚人相对更密集的社区开展业务活动才是明智之举。

图 4:东南亚人在各街区的百分比分布

3.4 家庭收入中位数的分布

由于特许经营的亚洲餐厅可以归类为休闲餐饮,其目标受众更多地面向中产阶级收入者。从下面的柱状图可以推断出,平均家庭收入附近的居民区很容易负担得起并享受上述亚洲美食。

这项研究还假设,在这项研究中,所有社区的生活费用在决定其各自的消费能力方面是相对平等的。

图 5:各街区家庭收入中位数分布

4。预测建模

4.1 数据预处理

为了帮助基于数学的算法——就像我们在这种情况下的 k-Means 算法——同等地解释具有不同量值和分布的特征,我们必须归一化我们的数据;由于这些特征列的比例不同,我们将把这些值标准化为一个共同的比例。数据标准化的一种方法是标准定标器

图 6:具有所有特征的标准化值的数据帧片段

4.2 k 均值聚类

在我们将特征值放入模型之前,我们必须预先分配算法应该标记的聚类数。为了确定要使用的最佳数目的集群,使用了 3 至 10 个集群,然后分别计算的平方误差被用作其性能的度量。

图 7:k 个簇的数量与其对应的平方误差之间的关系

图 8:使用 K 弯头可视化工具确定最佳 K 值的弯头点

使用 K 肘可视化器和每个 K 值的平方误差的分析表明,k = 6 将是最佳值。

在确定了聚类的数量之后,我们将把标准化的特征值拟合到我们的 k-Means 算法中;从而形成 6 个具有相似特征的聚集社区。

4.2.1 集群标签

多伦多的街区根据它们的集群标签进行颜色编码

图 9.1:聚类标签 0

集群 0:

  • 消费能力高
  • 中期目标客户的百分比
  • 中期竞争者数量

图 9.2:集群标签 1

集群 1 :

  • 消费能力低
  • 中期目标客户的百分比
  • 竞争者数量少

图 9.3:集群标签 2

集群 2 :

  • 消费能力低
  • 目标客户比例高
  • 竞争者的数量

图 9.4:集群标签 3

第三组:

  • 消费能力低
  • 目标客户比例高
  • 中期竞争者数量

图 9.5:集群标签 4

集群 4:

  • 中期消费能力
  • 中期目标客户的百分比
  • 竞争者数量少

图 9.6:集群标签 5

集群 5 :

  • 中期消费能力
  • 目标客户比例高
  • 竞争者的数量

4.2.2 集群摘要

总之,集群 0 的居民区拥有最高的相对消费能力,因为他们的家庭收入中位数明显高于其他集群。相当数量的东南亚人和亚洲餐馆表明对东南亚菜肴有足够的需求;和能够比其他人更有规律地消费膳食的顾客。

第 1 类消费能力低,同类餐馆数量少,这意味着消费能力指数低,需求不足,因此这类餐馆是最不理想的选择。

集群 2 在该地区拥有大量东南亚人口或目标客户,因此前景看好。然而,它的低消费能力和类似利基的大量竞争对手可能表明进入的高壁垒-与竞争对手提供的更便宜的选择相比,它的人口统计可能要求我们客户的更昂贵的菜单更少。

集群 3 ,尽管在人口统计和最佳竞争者数量方面有利,但其低消费能力将不幸地证明消费不足。

集群 4 在该地区的竞争者数量较少,这表明该地区对该美食的需求较低,尽管该地区拥有足够的消费能力水平和人口分布。

聚类 5 仅由一个小区组成,这是因为其竞争对手的数量非常多,并且分布在东南亚。尽管竞争对手众多,但这显示了前景。如果客户的特许经营餐厅已经建立,那么“集群标签 5”中的社区也可以考虑,因为该餐厅具有品牌忠诚度的竞争优势,可以对抗竞争对手的密度。

5。结论

在这项研究中,我根据他们的特征——消费能力、目标客户的百分比和竞争对手的数量——对社区进行了标记。最有希望开一家亚洲餐馆的社区群,以东南亚美食为利基,似乎是“集群标签 0”。

这个集群中的居民区的较高消费能力使他们很容易负担客户的亚洲餐馆菜单的稍微升级的价格。

目标顾客百分比的平均分布——东南亚人口统计——表明对亚洲美食的需求相对合理。

竞争者的数量并不多,但足以成为亚洲美食需求的良好指标。

我们的客户可以更具体地考虑 Guildwood 作为最佳结果的建立地点。然而,每当商业需求的动态发生变化时,我们总是可以瞄准不同的社区集群。举例来说,如果客户计划扩展一家知名的特许经营餐厅,那么“集群标签 5”中的社区将是最佳位置;这是基于一种假设,即上述餐馆相对于该地区的众多竞争者而言,具有品牌忠诚度的竞争优势。

总之,以上广泛的分析将大大增加餐馆成功的可能性。同样,我们可以用这个项目来分析可互换的场景,比如开一家不同菜系的餐厅。

6。未来方向

我认为这个模型可以在捕捉餐馆的个性特征方面做更多的改进。例如,两家餐馆可能有相似数量的竞争对手,但其中一家的地理半径可能较小,而另一家的地理半径较大。另一个例子是,东南亚人口更密集的餐馆可能不会比他们的民族同行更渴望他们的亚洲美食。

这项研究中的消费能力属性过于无知地假设所有上述社区的生活成本相对相等。更精确地计算购买力的生活成本账户将极大地改善研究结果。更多的数据,尤其是不同类型的数据,将有助于显著提高模型性能。

7。参考文献

[1]我这个项目的 Github:【https://github.com/TheClub4/Coursera_Capstone

[2]维基百科关于多伦多街区的信息收集页面:https://en.wikipedia.org/w/index.php?title =加拿大邮政编码列表:_M & oldid=945633050

[3]多伦多人口普查数据开放数据门户:

[## 幸福多伦多

最小值和最大值之间的数据值范围被划分为等长的类。例如,如果 5…

bit.ly](https://bit.ly/2Ja4v81)

[3]多伦多街区的地理坐标:https://cocl.us/Geospatial_data

[4] Foursquare 开发者 API:https://developer.foursquare.com

用数据科学赢得后新冠肺炎时代的战略举措

原文:https://towardsdatascience.com/strategic-moves-to-win-post-covid-19-with-data-science-cf1c1c2d1fe5?source=collection_archive---------41-----------------------

在您的数据科学团队中或与您的数据科学团队一起讨论的五个可行行动

图片来源:Mumemories via iStock

对许多人来说,新冠肺炎疫情撼动了 2020 年。今年标志着一个时期,不确定性突然变得比确定性更常见,而且似乎还会持续下去。在商业中,我们看到,尽管一些企业在不确定性中茁壮成长,但更多的企业需要彻底重新校准,以适应新常态的许多可能变体。在数据科学领域,我们在不确定性中茁壮成长,同时我们依赖统计学和人工智能作为黄金罗盘来穿越迷雾。在迷雾中,我们面对的是不断变化、充满活力的消费者需求,而实体客户比以往任何时候都更加遥远。这对许多行业和市场都很重要:供应链将以不同的速度运作,医院的产能管理与以前完全不同。拥有强大的数据科学能力将有助于企业的适应和发展。对一些人来说,这意味着从绝对零度开始,对所有人来说,这意味着采取正确的行动至关重要。

这篇文章将带你了解在后新冠肺炎时代赢得比赛的五个关键战略步骤。此外,它还列出了几个必须知道的技术和数据科学术语,可以帮助您与首席数据科学家展开正确的对话。

1。 集结部队进入队形

图片来源:Georgijevic via iStock

为了能够量化不确定性,并尽可能远离它,您将需要一个数据科学团队。您的数据科学团队将在所有后续步骤中发挥至关重要的作用。它们对于利用正确的数据、预测接下来会发生什么、帮助实现自动化以及在远程建立高质量客户关系方面发挥决定性作用至关重要。通常,表现良好的数据科学团队包括具有互补技能的人员,这些技能至少包括统计建模、AI / ML、数据工程以及项目和人员管理方面的知识。如果你缺少人才,即将到来的经济衰退可能会增加数据科学领域的人才。

即使你已经有了一个团队,现在也是时候重新审视他们的定位了。通常,当团队的位置靠近进行战略决策的董事会会议室时,团队的影响力是最佳的。从那里,他们可以部署到高影响力的项目中,在这些项目中,除了传统的分析师和 BI 角色之外,数据科学还将具有额外的价值。

最后但并非最不重要的一点是,对公司内的所有人进行不同层次的数据素养教育。鉴于内部和外部需求的转变,在公司内部寻找任何可以接受再培训的人。利用规模和现有资源,MOOCs 以小投入创造大价值。通过要求将洞察力作为决策的关键因素(而不仅仅是调味品),建立一种以数据和数学推理为基础的文化。后新冠肺炎时代的世界将与我们所知的不同,所以确保你的人现在就利用数据采取行动,而不是在一个不再相关的前新冠肺炎时代的经验。

2。 插上数据排气

图片来源:Jag_cz via iStock

越来越依赖数据和活跃的数据科学团队将使您的公司对数据如饥似渴。尽管应该保护敏感数据,并且应该实施正确的策略,但是您应该克制对数据仓库的某些部分应用锁定的冲动。相反,让创造力茁壮成长,让不敏感的数据大众化。

那么这意味着什么呢?这意味着今天的跨部门数据应该可供您的数据科学团队和组织的其他部门使用。您已经拥有的数据的民主化将增加透明度并增强跨部门的协作。为了在技术上实现这一点,将(部分)数据转移到云中,并考虑像 Apache Cassandra 或 MongoDB 这样的 NoSQL 解决方案,使您的数据可用于许多接口。此外,积极搜索和发现“黑暗”数据,这些数据只对某些人可用,或者尽管非常有价值却从未被挖掘。最后但同样重要的是,测量数据基础架构的质量并针对速度进行优化,以便应用程序和数据科学模型能够及时产生影响深远的见解。

此外,我们看到新冠肺炎教改变了社会和个人的价值观和规范。为了保持领先,你需要重新考虑在公司内部消费和记录哪些数据,并进行相应的实验。不要为非作歹,而是重新思考和调整你在数据收集方面的道德方法,不断改进你的产品和服务,以适应“新常态”。

3。 拨开迷雾

图片来源:AscentXmedia via iStock

更完整的数据将允许你对你的成功进程进行精确的测量。但是你的大部分预测和(在产)AI / ML 模型都会被目前的情况搞糊涂。他们都是在 COVID19 之前的数据上接受培训的,更不用说 COVID19 之后的数据(还)几乎不可用。尽管如此,你还是需要透过迷雾来避开危险。有哪些最佳实践?

首先,确保您的模型得到了正确的实现。企业和您的数据科学团队需要尽快知道准确性何时会出现偏差。建议您的首席数据科学家使用 Kubeflow、Azure ML 或 AWS Sagemaker 等解决方案来实现模型的自动化再训练。尽管有时可能需要一些人工干预,但它可以确保使用最新数据定期更新您的模型。

第二,实现和应用需要较少数据或不需要任何数据的模型。对于低数据,使用简单的机器学习模型来避免不准确的模型,例如过度拟合。过度拟合的模型非常适合小型训练数据集,但也会表现出现实世界中不存在的关系。与您的数据科学团队讨论 RidgeRegression、KNN 或朴素贝叶斯,以便使用更少的数据。

第三也是最后一点,考虑生成可能复制未来的场景数据。与业务部门一起,您的数据科学团队可能能够生成几个未来场景。如果您的数据科学能力更先进,请通过使用生成式深度学习技术(GANs)生成数据来支持这些场景。以前 GAN 驱动的合成数据似乎只适用于可再生能源领域,但新冠肺炎导致的数据缺乏将推动这一新的应用。展望未来,你可以利用机器学习来确定哪种场景类似于你公司的当前状态,从而对未来做出最准确的预测。

4.自动化提高效率

图片来源:AscentXmedia via iStock

尽管后新冠肺炎时代最明显的挑战似乎是在不确定性中取胜,但在不确定时期也不应忽视提高运营效率。虽然市场在短时间内波动、萎缩和增长,但赢家可能是那些擅长规模游戏的人。在这种情况下,我们可以从以前的经济衰退中吸取教训,专注于技术和数据科学驱动的自动化的参与者将在衰退期间和之后获胜。

数据科学驱动的决策通过将全职员工从重复性任务转移到他们更有价值的更多领域来帮助削减成本。此外,它允许您更快地扩展运营,这可能有利于需要超越竞争对手的销售和运营团队。自动化是技术和数据科学的结合,但是要小心复杂的怪物。机器学习不是银弹,大多数自动化问题 90%是通过简单的数据工程或使用简单的业务规则评估决策来解决的。如果您正在寻找在工作流自动化方面强大的工具,请讨论气流的实现,或者研究一下新的 kid-on-the-block: Prefect。

如果专注于低挂的果实,自动化可能是一个安全的赌注,在那里商业案例是强有力的。复杂之处通常在于这些病例的公开鉴定。此外,确保您教育了您的员工,并且共享了最佳实践。最后,确保人们在自动化他们自己的责任方面获胜。只有这样,他们才不会害怕失去影响力和工作的乐趣,这是后新冠肺炎时代让自动化发挥作用的必要条件。

5。 建立高质量的远程客户服务和关系

图片来源:ZargonDesign via iStock

对社会而言,在后新冠肺炎时代,保持距离似乎仍将是一个重要的价值观。我们看到消费者被迫远距离满足他们的需求,这造成了可能难以改变的客户习惯和期望。这些更新的期望很可能会传播到其他行业,你可能要为此做好准备,即使是在 2B。

借助数据科学,您可以在更私人的层面上与客户互动,从而加强您的数字关系。实际上,这可能意味着预测哪些服务和产品将符合个人需求,或者优化特定时间和地点的可用性。或者,用最吸引客户的语言交流。通过插入客户数据的排气(步骤 2),您的数据科学团队将能够使用聚类技术对客户进行细分。今后,您可以应用精心设置的 A / B 实验来快速了解和优化在线服务。

让这一点发挥作用意味着在实时电子商务等条件下查询数据科学模型。速度是至关重要的。为了做到这一点,您将需要流分析来处理和评估运动中的数据,而事件是 happening⁴.流分析开辟了在环境中应用数据科学模型的途径,以前我们在等待数据到来或模型生成答案时速度太慢。虽然今天的流分析设置比传统设置更复杂,但这无疑是一个值得关注和应用的领域,没有其他解决方案可以发挥作用。

你下一步应该做什么

总之,评估五个步骤中的每一个如何与你的公司和职位相关,会对你度过这个充满挑战的时期有很大的帮助。每一步都应该以某种方式激励你,并为公司内部的讨论提供素材。我们写这篇文章是为了提出更多的问题,尤其是为了促进讨论。作为第一步,您可能需要重新联系您的首席数据科学家,以探索后续步骤。如果你需要帮助,我们很乐意帮忙。

此外,我们期待听到您在后新冠肺炎时代利用数据科学推动成功的经历。祝你好运!

[1] C .蒋等,基于生成对抗网络的日前可再生能源情景预测 (2020),TechrXiv

[2]沃尔特·弗里克,如何度过衰退并在衰退后繁荣发展 (2019),《哈佛商业评论》2019 年 5-6 月刊

[3] Jasper van Rijn,作为新标准的网购的突破 (2020),IG & H 博客系列:零售商如何从电晕危机中反弹

[4] Databricks,流分析(2020 年查看),Databricks 词汇表

跟上人工智能研究的策略

原文:https://towardsdatascience.com/strategies-for-keeping-up-with-ai-research-7861037c7247?source=collection_archive---------70-----------------------

原始图像由 OpenClipart-Vectors 在 Pixabay 上生成

帮助您掌控一切的 7 个技巧

人工智能的速度

对于任何关注人工智能(AI)、深度学习(DL)或机器学习(ML)领域的人来说,研究有时会像赛车一样从你身边飞驰而过。在 arXiv.org 上快速搜索显示,今年(2020 年)4 月 1 日至 5 月 1 日期间,宣布了 2683 篇与 AI、DL 或 ML 相关的新文章。研究社区不断被新的工作(好的和坏的)淹没,跟上似乎是不可能的。媒体对大赦国际的报道进一步加剧了这种情况。无论是自动驾驶汽车的即将到来,自然语言处理的进步,自动化医疗诊断,还是对控制论机器人起义的恐惧,人工智能都受到了广泛关注。

当然,人工智能接受的无数曝光有许多好处;然而,对于那些在实地工作的人来说,也有一些负面影响。首先,来自新应用程序、更好的体系结构、新兴子领域等的大量信息会分散注意力。随时都有数不清的兔子洞可以跳下来。虽然探索可能提供更好解决方案的新的和新兴的解决方案很重要,但如果我们把所有的时间都花在追逐闪亮的物体上,那么我们将永远不会取得任何进展。

其次,大量新研究和不断增长的人工智能行业可能会产生不必要的焦虑。成功和快速成功的压力甚至会动摇最有经验的研究人员和开发人员的信心。似乎其他研究人员的发布速度是他们的两倍,或者公司开发的应用程序也是他们的两倍。这可能导致糟糕的设计决策和浪费时间,从而破坏我们有效应用人工智能的能力。此外,这可能会使我们容易受到群体思维的影响,并限制我们用新颖和创造性的解决方案处理问题的能力。

最后,如果你想保持相关性,跟上与你的应用领域或行业相关的研究是必要的。诀窍是找到不消耗你所有时间并且最适合你的方法。本文的其余部分确定了实现这一目标的策略。同样重要的是,我们要让最先进的研究启发我们,而不仅仅是影响我们,但这将是未来文章的主题。

跟上的策略

所以好消息是有大量的资源可以帮助我们跟上与我们兴趣相关的研究。在这篇文章中,我分享了一些我使用的资源,并讨论了我的一些保持与人工智能研究同步的策略。下面的项目是根据我个人的优先顺序排列的,但是每个人的学习方式都不一样,所以我鼓励你尝试一下,看看哪些适合你。

0。实事求是,始终如一

我们所有人花在跟上人工智能上的时间都是有限的,所以要现实和一致。在你的时间表中留出固定的时间。认识到你的时间限制会帮助你选择最适合你的策略。聪明努力地工作。

1.看报纸

因此,尽管听起来很明显,但花点时间阅读论文是非常重要的。这将为你提供学习新的和正在出现的工作的明显好处,但它也将加强你提炼和理解复杂概念的能力。阅读技术论文是一项对工程和科学至关重要的技能,就像所有其他技能一样,熟能生巧。奖励:批判性阅读论文也是一种很好的方式,通过真正挑战作者提出的一切来提出新的研究/算法想法。

以下是我的一些读报小技巧。

1A。保持有条理。

所以我的第一个建议是保持你的文件有条理。就我而言,我的云驱动器上有一个“ReadMe”文件夹,里面有我想阅读的所有论文。所以,当你有一点时间的时候,你可以直接去你的文件夹,开始阅读。一旦你阅读了这篇论文,你可以把它移到你的数字图书馆的其他地方,或者简单地删除它。

1B。聪明阅读。

正如我在博士期间很快了解到的那样,阅读论文会花费很多时间,如果你没有一个好的策略,你将永远不会看完你需要的所有论文。就我个人而言,我发现三阶段方法对我非常有效。每个阶段都有特定的目的,随后的阶段建立在前一个阶段的基础上。这可以大大加快这个过程,因为你经常会发现,在许多情况下,完成第二阶段就足够了。

这是我的一般做法。

  • 第一阶段:阅读摘要和结论。
  • 第二阶段:通读整篇论文,但是跳过任何需要大量脑力劳动的技术细节。
  • 第三阶段:批判性阅读,质疑作者的假设和主张。
  • 第四阶段(奖金!):码起来!这显然不仅仅是阅读,而是最终真正理解新概念的最佳方式。

在不久的将来,我将发表一篇关于我的方法的更详细的文章。我也鼓励你去读一些其他的策略,找到适合你的。

1C。设置提醒。

谷歌学术是一个了不起的资源,原因有很多,但自动提醒是跟上新潮流的好方法。可以基于作者或搜索字符串创建通知。作者提醒对于关注该领域的重量级人物非常有用,搜索字符串提醒对于寻找新作者非常有用。

要创建作者提醒:

  1. 搜索一个作者,点击他们的名字,进入他们的谷歌学术简介。
  2. 选择个人资料右上角的“关注”按钮。
  3. 输入您的电子邮件地址并选择提醒选项。

作者图片

要创建搜索字符串警报:

  1. 登录谷歌学术,从侧面菜单中选择“提醒”。
  2. 点击“创建提醒”。
  3. 输入您的电子邮件地址、应该查询的搜索字符串以及应该包含的结果总数。

作者图片

专业提示:如果你使用 GMail,那么你可以利用这些奇特的过滤技巧来自动组织收件箱中的提醒。你可以在这里阅读花式过滤。

2.观看 YouTube

YouTube 是最令人兴奋的地方之一,我开始看到真正好的内容。有很多非常聪明的人正在发表论文评论、在线讲座和教程。所有这些都是快速了解新主题和获得直觉的极好来源。我发现这些视频为我节省了时间,并让我意识到了一些我以前不会看到的新话题。

我没有提供一个长长的潜在频道列表,而是只列出了三个 YouTube 频道,我建议从它们开始。我对每个频道都做了一些简介,并解释了为什么我认为这是值得的。检查完这些频道后,我会鼓励你检查更多的频道,找到适合你需要的频道。

  • 扬尼克·基尔彻:扬尼克发表了非常好的论文评论。他浏览新发表的论文,并提供大部分必要的背景材料,以便很好地理解论文的贡献。他的视频直截了当,这使得他可以发布大量视频,其中大多数不到 30 分钟。如今,如果有我感兴趣的新论文,我会快速搜索一下,看看 Yannic 是否已经覆盖了它。
  • 亨利人工智能实验室(Henry AI Labs):该频道由康纳·肖恩(Connor Shorten)运营,同时提供大量论文综述和讲解视频。像扬尼克一样,康纳非常博学,在解释人工智能概念方面做得非常出色。这个频道真正的金块(至少对我来说)是“AI 每周更新”系列。Connor 每周都会对人工智能研究的最新消息进行高水平的回顾。更新视频不到 30 分钟,包含大量内容。
  • 两分钟论文:这个频道由 Karoly Zsolnai-Feher 运营,已经积累了超过 60 万的订户。Karoly 制作了制作精良的短视频(约 5 分钟)。这些视频通常水平很高,但非常清楚地说明了主题。这些视频很容易观看,而且可能会上瘾(从好的方面来说)。

专业提示:YouTube 设置允许你以高达 2 倍的速度播放视频,这对浏览人工智能内容非常有帮助。我发现 2 倍的速度是可以忍受的,只要你习惯了。为了更好的控制,你也可以使用插件,比如 YouTube 的增强器

3.订阅新闻信件和子编辑

另一个很好的资源是使用新闻信件和子编辑来帮助过滤内容。诚然,我没有订阅很多新闻信件,但我发现 deeplearning.ai 的批次非常有用。吴恩达是人工智能领域最著名的人物之一,这是有充分理由的。每周他都会提供一份人工智能热门话题的精选列表,以及相关的背景和为什么这项研究可能很重要。我个人也认为 Andrew 涵盖了研究人员和应用程序开发人员都感兴趣的主题。我强烈推荐订阅这封新闻信,并寻找其他符合你兴趣的新闻信。

多年来,我一直是 Reddit 的忠实粉丝。我一直认为 Reddit 是一个基于社区的互联网过滤器。Reddit 拥有许多子社区 can Subreddits,这些子社区致力于特定的主题或主题。成员可以张贴内容,可以根据内容的接收情况进行投票表决。希望最有用和信息最丰富的内容被提升到列表的顶部。有几个不同的子主题与 AI 和 ML 相关,但我建议从深度学习开始。这个社区有不到 5 万名成员,Subreddit 非常活跃。

作为题外话,Reddit 不仅是一个很好的信息来源,也是一个与志同道合的人工智能爱好者互动的地方。我认为这对于该领域的新手和希望得到一些反馈的人,或者那些不经常与人工智能专家互动的人来说特别有用。我个人目前并没有在这些子栏目中发表文章,但希望在不久的将来会有所改变。

4.回到基础

我发现花点时间复习基础知识是很有用的。巩固你的基础会让你在阅读你所在领域的论文时更有效率。我也试着根据我一直在读的东西来选择这些话题。例如,假设您正在尝试学习语音识别算法,那么回顾一下您的基本信号处理和频谱分析是值得的。这将会给你一个优势,让你更好地理解和提高你正在阅读的内容。它还会帮助你挑战那些你可能信以为真的假设。

虽然不可能涵盖每个人的兴趣,但我会推荐以下几类作为考虑的主题。

  • 结石
  • 线性代数
  • 最佳化
  • 编程;编排
  • 数字信号处理
  • 随机过程、统计学和信息论
  • 领域知识(取决于你的兴趣领域)

有很多免费和付费的在线资源可以学习这些类型的主题。我会推荐你看看 CourseraedX斯坦福在线麻省理工学院开放课件快速入门。

5.阅读技术博客

这年头绝对不缺 AI 和 ML 博客。基于博客的站点和目的,内容可以有很大的不同。当我试图寻找某个特定主题的信息时,我通常会通过谷歌搜索进入大多数博客。然而,有一些博客我会定期浏览,寻找新的内容。这里是我发现的前三个信息,但通常这将取决于你的兴趣。

专业提示:你可以使用新闻阅读器工具,如 in reader 或 Feedly 将你所有的博客内容收集到一个地方。

6.听播客

播客可能成功也可能失败,这取决于你是谁。有许多不同的人工智能和人工智能相关的播客,其中许多遵循相当相似的格式。其中大多数包括对研究人员和开发人员的采访,谈论新出现的问题,并涵盖这些领域的基础知识。我发现自己最近花在播客上的时间越来越少,但我仍然认为它们是很好的资源,值得一读。有些播客可能会很长,所以最好选择几个,坚持一段时间。

与 YouTube 上的部分类似,我没有提供一长串的可能性,而是在下面提供了一些建议。

  • 线性题外话:这个播客提供了极少量的技术机器学习内容。剧集很短(不到 20 分钟),涉及的话题很广。
  • 会说话的机器:这个播客的特点是更长的剧集(大约一个小时),比线性题外话更没有技术含量。这种形式是基于采访正在工作的人工智能从业者,并在非常实际的意义上讨论相关话题。
  • 人工智能播客:该播客完全基于采访,每集时长 1 至 3 小时。完全透明,这个播客涵盖了广泛的主题,其中许多都是非技术性的,甚至是哲学性质的。我个人觉得很多剧集都很有趣,而且很多嘉宾都是人工智能社区中非常受尊敬的研究人员和开发人员。

7.监控社交媒体

现在,我承认这个建议有点虚伪,因为我几乎完全放弃了社交媒体。然而,我认识到它可以是一个很好的工具,用来跟踪你最喜欢的作者发生了什么,或者在你的领域发生了什么。许多研究人员和开发人员会经常在 Tweet 上发布关于行业新论文或发展的消息。这可以作为过滤掉重要信息的另一个来源。所以,如果你喜欢社交媒体,那就想办法让它为你服务。

结论

人工智能(和相关领域)正在经历一个前所未有的增长时期,这对这个领域来说是梦幻般的,但它肯定会势不可挡。每时每刻都有这么多事情发生,很容易分心,这可能会对你的工作造成损害。知道你并不孤单,这让你得到一些安慰。最重要的是认识到你有多少时间,并尽可能明智地使用它。

这篇文章介绍了一些我用来继续研究的策略。从列表中选择一些策略,并尝试一下。不要试图一次实现太多,否则它会很快变得难以承受。当你慢慢找到自己的学习方法时,看看哪些有用,哪些没用。最终,你需要找到最适合你的方式,这可能会随着时间而改变。不断探索,不断学习,增长见识。

学习数据科学的策略

原文:https://towardsdatascience.com/strategies-for-learning-data-science-47053b58c19f?source=collection_archive---------5-----------------------

数据科学之旅可能起点的卡通插图。(由 Chanin Nantasenamat 绘制)

数据科学

进入数据科学的实用建议

你想进入数据科学领域吗?但就是不知道怎么做?如果是这样,那么继续读下去,因为这篇文章是为你而写的。

去年年底,也就是 2019 年 12 月,我发布了一个 YouTube 视频,名为2020 年学习数据科学的策略 ,这是我最近开设的 YouTube 频道,名为 数据教授 ,在那里我分享了我作为一名自学数据科学的学术教授学习数据科学的策略,自 2004 年以来一直活跃在该领域长达 16 年。

在本文中,我将讨论如何通过与您分享我用来学习数据科学的一些学习策略,让您也走上成为数据科学家的类似道路。

闯入数据科学需要什么背景?

为了成为一名数据科学家,你应该拥有计算机科学学位吗?或者,如果你来自一个非技术背景,你也可以做一个类似的转变到数据科学吗?

首先,我不是计算机科学家,你可能还记得我的第一篇关于媒体的文章( 生物学家如何成为数据科学家:我如何从非技术背景过渡到数据科学 ),我的本科学位是生物科学。而且因为对计算机和数据的迷恋,我一直在自学做数据科学所必须的概念和技能。

数据科学是一个多学科领域,包括几个学科,如信息学、计算机科学、统计学、科学、数学、数据可视化以及最重要的问题解决。如果你查看 LinkedIn 上数据科学家的职位描述,你会注意到数据科学家可能拥有各种第一学位。如你所见,背景相当多样化。事实上,许多人不是计算机科学毕业生。然而,如果你有计算机科学学位,你可能会有优势。如果你没有,那也没关系(我也是生物专业的)。

拥有学习数据科学并将其应用于任何领域的热情,我相信这是成为数据科学家的关键。由于生物学中的大量数据,这刺激了我成为一名数据科学家的转变。特别是,通过应用机器学习来分析大生物数据,以努力(1)发现和发现新药,(2)理解药物的作用机制,以及(3)创建诊断工具,该工具将能够帮助临床医生和卫生专业人员诊断患者的特定感兴趣的疾病。

从哪里开始?

这是一个棘手的问题。当您想要进入数据科学领域时,实际上应该从哪里开始呢?答案可能会非常不同。如果你问一百个数据科学家,你可能会得到一百个不同的答案!

如果你问我,我是从生物学领域的知识开始的。我在生物学上遇到了一些数据问题,需要解答。在我最终成为一名数据科学家的过程中,我慢慢地一项一项地学会了必要的技能。这不是在 3 个月或 1 年内完成的,而是从 2004 年开始的。在数据科学这个术语被创造出来之前,我已经做了 16 年,发表了 100 多篇研究文章,从 2006 年开始教授数据科学(当时是数据挖掘),我能说我已经掌握了数据科学吗?绝对不行!我每天都在继续学习数据科学的新概念。数据科学的前景如此广阔,以至于可能需要花一生的时间来掌握(甚至可能不掌握整个领域,而只是其中的一个子集)。

正如您将在下面的漫画插图中看到的那样,闯入数据科学的起点相当灵活。无论你来自哪种背景,你都可以进入数据科学领域,只要投入必要的努力、时间和实践,你就会成为一名数据科学家。

数据科学之旅可能起点的卡通插图。在这里,您将看到无论您从哪里开始,您都可以继续学习数据科学中使用的其他技能。(由 Chanin Nantasenamat 绘制)

成为一名数据科学家需要多少时间?

另一个你可能想知道的流行问题是成为一名数据科学家需要多少时间。您可能从某个地方听说过,您可以在 3 个月或更短的时间内学习数据科学。

但是说真的,这可能吗?答案是有也没有,迷茫?你看,3 个月后,你可能会对数据科学提供的东西有所了解。你也许能获得数据科学的初步介绍。你甚至可能获得数据素养或成为一名公民数据科学家。

比方说,如果你有一个计算机科学学位,成为一名数据科学家所需的时间不会太长,因为你已经具备了计算的基础,你已经有了技术背景,你已经知道如何编程(如果没有,那也没关系!).所以你所拥有的这些技术技能会让你的转变更快。

比方说,如果你是一名 web 开发人员,你将学习 R 或 Python,那么你将比一个来自生物学等领域的非技术人员更有能力学习这两种语言或其中任何一种语言(没错,就是我!).

对于一个生物学专业的学生来说,学习 R 或 Python 所需要的时间可能会更长。然而,我相信如果你有学习的心态和热情,那么我认为这是必要的。我在某处读到过,如果你花 10,000 个小时,你就能掌握技能或知识。

比方说,你每天花大约两个小时学习编程和数据科学的概念,所以我相信在一两年内,你将能够学到足够的知识,成为一名数据科学家。既然你也在练习。我认为数据科学家是一种生活方式。成为其中一员需要奉献和终身学习来获得新的技能,这将使你在这个领域中处于循环之中。这是一个使用它或失去它的哲学。因此,除了终身学习,我还强烈建议将新获得的知识和技能应用到数据科学项目中。

就我个人而言,我作为生物信息学副教授的日常工作要求我跟上该领域的最新发展,以促进创新和开发新的生物信息学工具,以及应用现有的机器学习算法来提取知识,提供对疾病潜在机制的见解,以及寻求发现潜在治疗应用的新药。

我需要学习如何编码吗?

因此,你可能会有下一个问题,你是否需要学习如何编码,以便成为一名数据科学家?这真的取决于环境,所以是和不是。在我学习如何编码之前,我会使用这个叫 WEKA 的软件。它是一个点击式图形用户界面(GUI)软件,用于执行数据挖掘,我依靠它来分析我在博士研究期间收集的数据。

随着时间的推移,我开始注意到通过点击式界面进行数据分析并不是一个高效的过程。主要原因是它需要大量的手动工作,我将不得不实际使用鼠标点击并执行软件中的各种任务:(1)导入数据,(2)指定输入参数,(3)启动模型的训练,(4)收集数据,(5)将其放入 Excel,(6)将其合并,因此所有这些都非常繁琐。

在我读博期间,有一段时间我记忆犹新。就是我在大学机房控制 40-50 台电脑的时候。因此,在每台计算机上,我会运行一些计算(使用 WEKA 软件建立模型),然后我会手动从 40-50 台计算机中的每一台收集数据,然后将结果汇集在一起,以便在 Microsoft Excel 中进行后续分析和绘图。

在我的博士研究过程中,我从未学习过编码,而我只是依靠 WEKA 软件的数据挖掘功能,使用线性回归、J48(c 4.5 算法的 Java 实现)、反向传播神经网络和支持向量机等算法来完成所有的机器学习模型构建。在我的博士研究接近尾声时,我遇到了另一个伟大的基于 GUI 的多变量分析软件,称为 Unscrambler,它允许我运行另外两个机器学习算法,即主成分分析和偏最小二乘回归。

因此,在我 4 年的博士学习结束时,由于使用了两个基于 GUI 的软件:WEKA 和 unbrowser 软件,我能够以 13 篇论文(研究文章)毕业。我有没有提到,在我读博士的过程中,我确实尝试过学习 C++和 Java,但是没有成功。很大程度上停留在 Hello World 示例上,并没有真正获得任何进一步的进展。

那么我是什么时候学会编码的呢?你可能想知道。在透露答案之前,我先给你讲一下背景。于是在拿到博士学位后,我被同一所大学聘为讲师(快进到今天,我刚刚庆祝了我在学术界的 14 年+ 4 年读博= 18 年研究)。

好了,现在是我学习如何编码的时候了。在我担任讲师大约一年后,我遇到了一位研究助理(我将在下文中称为 RA ),他加入了我的研究实验室,帮助我将一些现有的工作流转换成编程工作流,即 Python 中的工作流。于是 RA 给我看了他一直用来学习 Python 的这本书叫做 Python Power!这是我第二次(也是成功的)尝试学习如何编码。那么为什么第二次尝试成功了呢?让我在下一节解释一下。

所以说了这么多,不编码做数据科学有可能吗?可以使用基于 GUI 的软件,如 WEKARapid MinerOrange 或其他类似软件(在现代称为无代码 AI)来执行机器学习模型构建。

但是,整个数据挖掘项目的整个端到端工作流程并不完全可能仅通过使用一个软件,如 WEKA 。所以我最终使用了名为 Ultra Edit 的文本编辑器,它允许我应用录制的宏来半自动完成一些所需的数据预处理。

绘图主要是使用 Microsoft ExcelPowerpoint 创建的(用于添加图内面板标签和设计多绘图图的布局)。我还使用了另一个软件来制作更复杂的图,比如等高线图,这是通过使用适马图软件实现的。挑战在于手动将第一个软件的输出转换为第二个软件的输入。这个过程反复重复,由此第二软件的输出被用作第三软件的输入,等等。

如您所见,通过基于 GUI 的软件来执行整个数据挖掘模型构建的整个端到端工作流确实是可能的,但代价是需要手工操作。

所以回想起来,如果我能重新开始我的博士学位,我肯定会在学习如何编码上投入更多的努力(事实是,我确实试图学习如何编码,但没有成功;几年后的第二次尝试成功了,因为心态的改变,我将在接下来的章节自学程序员中与你分享?)。

你看,如果你知道如何编码,即使只是一点点,它将有助于大大加快你的工作流程。想象一下用 R 或 Python 代码自动化整个端到端项目,而不是必须手动做所有事情。那么有什么区别呢?答案是时间和可靠性。特别是,自动化方法更不容易出现人为错误,同时计算和完成速度明显更快。

学什么语言?r 还是 Python?

所以现在非常重要的问题是你应该学习什么语言如何编码。如果你一直在谷歌搜索或者在 YouTube 上看视频,你可能会遇到两种在数据科学领域非常流行的语言。所以第一个是 R,第二个是 Python。一个经常被问到和争论的流行问题是,是学 R 还是 Python?

R 或 Python 有令人信服的理由吗?

所以答案真的取决于是否有令人信服的理由选择 R 或 Python。例如,您可能想要使用 Bio3D R 包或 shiny 包,因此如果是这种情况,那么就选择 R。或者,您可能真的想要使用 python 中的 Biopython 库,那么无论如何都要使用 Python。

你有学习伙伴或导师吗?

所以就我个人而言,我首先学习 Python 并不是因为语言本身的任何特殊原因。所以决定学习 Python 是因为我在前面提到的 RA 已经使用 Python 为我们正在进行的项目编写了工作流程。这或多或少地限制了使用 Python 的选择,因此我学习编码的旅程从这里开始。

所以我要求 RA 逐行解释 Python 源代码的意思。第一个解释对我来说没有意义。所以在一张纸上画一些漫画来描述每一行执行时实际发生了什么。不久之后,他离开了这个团队去攻读博士学位。所以我继续学习编码。

自学编码员?

因此,我得出结论,按照书中的例子编写代码并没有真正点燃我的学习过程。那么究竟是什么推动了我的学习呢?它框定了我自己的数据问题,并基于这个问题(这是最终的激励),我会寻找如何有计划地解决数据问题并产生必要结果的方法。这个小任务的完成会给我带来小小的胜利,有助于激发我的学习动力。通过寻找解决数据问题的方法,我实际上做了什么?

答案很简单。我发现了 栈溢出 。这是一个神奇而强大的资源,它允许我通过学习别人如何解决编码问题的例子来自学编码。有时,一些问题有多个答案,最终导致相同的结果。特别是,一些答案获得了更多的支持,而另一些可能获得了更少的支持,这实际上是一个关于它是否也帮助了其他人的学习旅程的主观问题。通过比较和学习这些多重答案,这帮助我认识到,为了完成工作(解决数据问题),我不需要记住语法(几年前当我试图学习 C++或 Java 但没有成功时,我盲目地试图这样做)。

所以这一次,我被解决数据/编码问题的愿望和达成最终解决方案所需任务的逻辑所引导。那么,我是如何得出需要完成哪些任务的逻辑的呢?我会简单地查看数据/编码问题,并尝试在纸上列出所有步骤,如果我必须手动完成,我会如何做。然后,我会一个接一个地对每一步进行顺序编码,直到所有问题都得到解决。在你知道之前,已经被分解成一口大小的馅饼被一个接一个地抓住并完成。

了解您的 Python 库和 R 包

因此,成为数据科学家的下一步是,你需要熟悉 Python 的标准库或 R 的标准包和模块。特别是,你需要知道 R 或 Python 中的哪些包或库可用于处理数据、预处理数据以及创建预测模型。

数据帧

例如,如果你在 Python 中处理数据帧,你将使用 pandas,因此, 你将不得不学习 pandas,以便你可以将不同的数据帧合并在一起。在 R 中,可以使用 dplyr 以及 R 中的 数据帧内置函数。

数据可视化

如果你想在 Python 中创建图形,你可以使用 matplotlibseabornaltairplotlyplotnine ,而在 R 中你可以使用 R 基本绘图函数 ggplot2

机器学习

为了在 Python 中进行机器学习和建立预测模型,你需要使用 scikit-learn 或者你可以使用tensor flowkeraspy torchfast。

在 R 中你会用到拨浪鼓 以及 张量流keras

部署

在您已经构建了模型并且想要部署它之后。您可以从两种方法中选择一种:(1)作为应用程序编程接口(API)部署,或者(2)作为 web 应用程序部署。

在 Python 中,您可以使用 flask 部署您的 scikit-learn 模型(参见本教程 将机器学习模型部署为 REST API 作者 Nguyen Ngo )。来自 Google 的 云 ML 引擎 也是另一种选择(参见本教程 部署 scikit-大规模学习模型 作者高玉峰)。在 R 中,您可以使用plumber包来创建 web API(参见本教程 如何使用由 Shirin Elsinghorst 编写的 plumber 包 将您的机器学习模型作为 API 使用,以及本教程 R 可以 API,您也可以! 作者希瑟·诺利斯

要将机器学习模型部署为 web 应用程序,建议您首先通过 Python 中的 pickle 函数和 R 中的 saveRDS 函数将模型保存到一个文件中。然后可以使用flaskStreamlit来提供实际的 web 应用程序

我还制作了一个视频系列教程,讲述如何使用 Streamlit 库用 Python 创建数据科学 web 应用程序。

* [## 如何用 Python 构建数据科学 Web 应用程序

第 1 部分:您的第一个 Web 应用程序,只有几行代码

towardsdatascience.com](/how-to-build-a-data-science-web-app-in-python-61d1bed65020)

如果您想用 R 语言创建数据科学 web 应用程序,那么请使用 闪亮 包查看下面的教程视频系列。*

掌控您的数据科学之旅

成为一名数据科学家最重要的部分是你必须坚持不懈。你必须努力尝试。你必须拥有自己的数据科学之旅。这段旅程并不容易,所以你必须付出额外的努力来完成它。

我的数据科学之旅非常了不起。我学到了很多东西。我见过很多有才华的人。我有机会做我真正喜欢的事情并获得报酬。所以我从来没有厌倦这份工作,总是有新的数据要收集,要分析,我们有持续的合作,真的有新的数据和新的机会不断流入学习生物学,所以这是一个非常非常令人满意的工作。如果我能让时光倒流,重新决定我想做什么,我会坚持同样的道路,成为一名数据科学家。我相信数据科学非常适合我自己的 Ikigai(查看令人敬畏的文章 Ikigai:过有意义生活的秘密 ,作者 Ketaki Vaidya )。

如果您想获得更多关于开始学习数据科学的建议和路线图,请不要忘记查看我之前在《走向数据科学》中的文章 关于学习数据科学我希望知道的 10 件事:开始数据科学之旅的终极路线图

* [## 关于学习数据科学,我希望知道的 10 件事

开始数据科学之旅的终极实用建议

towardsdatascience.com](/10-things-i-wish-i-knew-about-learning-data-science-7a30bfb91759)*

最终带回家的信息

最重要的是,你必须编码。你必须做数据科学项目。如果您能从这篇文章中获得 2 个关键信息,请获得 2 个:(1)学习编码和(2)将您的编码技能应用到您自己的数据科学项目中。

“学习数据科学的最好方法是做数据科学。”
— Chanin Nantasenamat,数据教授

订阅我的邮件列表,获取我在数据科学方面的最佳更新(偶尔还有免费内容)!

关于我

我是泰国一所研究型大学的生物信息学副教授和数据挖掘和生物医学信息学负责人。在我下班后的时间里,我是一名 YouTuber(又名数据教授)制作关于数据科学的在线视频。在我制作的所有教程视频中,我也在 GitHub 上分享 Jupyter 笔记本(数据教授 GitHub 页面)。

* [## 数据教授

数据科学、机器学习、生物信息学、研究和教学是我的激情所在。数据教授 YouTube…

www.youtube.com](https://www.youtube.com/dataprofessor?sub_confirmation=1)

在社交网络上与我联系

✅YouTube:http://youtube.com/dataprofessor/
♇网站:http://dataprofessor.org/(在建)
♇LinkedIn:https://www.linkedin.com/company/dataprofessor/
♇Twitter:https://twitter.com/thedataprof
♇Facebook:http://facebook.com/dataprofessor/
♇github:https://github.com/dataprofessor/
♇insta gram:*

优化企业级数据消费的策略

原文:https://towardsdatascience.com/strategies-for-optimising-enterprise-level-data-consumption-7e2c95b6ba96?source=collection_archive---------54-----------------------

geraltPixabay 上拍摄的照片

中间件服务,使用 ETL/ELT 和 MASA(网格应用和服务架构)的数据仓库

作为一名顾问,经常会遇到这样的客户需求:

  • 我们需要消费多个信息系统的数据,所以要从它们调用多个 API 来获取所有的数据,这是一个很大的痛苦。
  • 我们确实在一个数据库中有所有的数据,但是我们需要查询几十个表来将它们连接在一起以获得预期的结果。
  • 我们相信我们有一个非常好的数据架构。DB 实例包含用于不同目的的多个数据库,我们以 3-norm 设计一切。然而,当我们想要跨多个数据库对整个系统进行一些统计时,这仍然是令人痛苦的。

用例

KOBU 机构Unsplash 拍摄的照片

通常,三种类型的需求会导致上述问题。

BI(商业智能)仪表板

这可能是最常见的达到限制的用例。

虽然该公司仍处于初创阶段,但很快获得任何类型的数据可能都相对容易。在这个阶段,即使是 Microsoft Excel 也足以满足大多数需求。此外,不建议采用复杂的数据架构,因为这对初创企业来说成本太高。

然而,假设公司发展良好,可能会建立越来越多的部门,以及扩展更多的业务领域,数据持久层将会更加复杂。例如,财务、运输、IT 部门有多个独立的数据库。如果业务是 B2b,也可能有不同客户的多个数据库。当然,每个数据库中的表数量也可能很大。

现在,该高管希望拥有 BI 仪表板来支持决策制定。可以看出,一些高级报告可能需要涉及几个数据库中的大量表格。

业务流程中需要

同样常见的是,一些业务场景需要复杂的 SQL 查询作为流程的一部分,比如验证。

例如,公司依赖多个信息系统。在一些特定的业务场景中,我们需要根据几个信息系统来验证客户的请求。

在这种情况下,优化公司范围的数据架构会更有帮助,因为性能会影响正常的业务流程。

高级分析

如果公司是“数据驱动”的,或者其业务交易产生大量高速数据,则通常会涉及高级分析,如机器学习技术,以提高业务效率,识别潜力等。

在这种情况下,从多个系统中提取数据来训练机器学习模型或向部署的模型输入正确的数据可能是一场噩梦。

原因和可能的解决方案

塞萨尔·卡利瓦里诺·阿拉贡在 Unsplash 上拍照

主要困难/原因是:

  • 查询本身可能非常复杂,包括各种技术,如连接和连接表、IF-ELSE 判断和大量条件过滤。
  • 由于涉及的表太多,性能根本无法保证。
  • 对于某些 DBMS,跨多个数据库运行查询可能并不容易。

根据我的经验,对于这种企业数据架构问题,有 3 种典型的解决方案。

中间件服务

经济性:★★★☆
维修性:★☆☆☆
灵活性:★☆☆☆

照片由 Unsplash 上的 zibik 拍摄

这个解决方案指的是构建一个中间件服务来与多个系统通信,并在返回到数据消费实体之前连接/聚合结果。

实现这一点的技术可以是多种多样的,可以是 Python、Java、Node。JS,C#,PHP 等。基于不同的前端数据消费实体,这些技术各有利弊。

这个解决方案可能是花费最少资源的一个,因为它是强烈的需求驱动的。也就是说,每当您需要另一个复杂的查询时,您要么需要向现有的中间件服务添加更多的组件,要么甚至从头开始开发一个新的组件(这可能是因为 DBMS 使用了完全不同的接口)。

因此,这种解决方案的可维护性和灵活性是最差的,尽管有时如果可以预见需求在短期内不会扩展,它仍然是最好的解决方案。

优点:

  • 需求导向,只为你需要的东西开发
  • 成本相对较低

缺点:

  • 没有建立“平台”,因此未来新的类似需求将需要几乎相同的努力。
  • 这个解决方案没有标准。如何实现完全取决于开发者。
  • 对数据的每个请求都会触发对所有系统的查询,因此增加了所有现有系统/数据库的负担。
  • 难以维持。

企业数据仓库

经济性:★★★☆
维修性:★★★☆
灵活性:★★★☆☆

emyUnsplash 上拍照

数据仓库可能是目前业界最流行的解决方案。基本思想是建立一个系统,可以从多个信息系统中提取数据,然后将所有符合数据仓库标准(星型或雪花型模式)的数据存储在一个数据仓库中。

企业数据仓库通常包括以下组件:

  • ETL/ELT 数据管道,其从各种数据源提取数据,然后转换数据到加载到数据仓库。随着大数据概念的发展,ELT 在业界越来越受欢迎,比 ETL 更受欢迎的还有 Azure 等一系列云提供商和 Apache Spark 等一堆分布式/并行计算引擎。
  • 数据仓库是关于数据如何存储在 DBMS 中的另一个标准。与关注于提高插入/更新/删除性能的常规事务数据库不同,数据仓库是面向报告的,为阅读而优化。因此,从多个数据源提取数据并在存储到数据仓库之前对其进行预聚合是非常常见的,因此可以通过简单地查询几个表而不是几十个表来消耗数据。

优点:

  • 这是一种“非侵入性”的解决方案。也就是说,消费请求由数据仓库来满足,因此事务系统没有额外的负担。
  • 无论数据源的类型如何,在 ETL/ELT 过程中,都必须有相应的技术来从中提取数据。
  • 数据可以预先转换。例如,不同的系统可能使用不同的用户性别指标(男/女、男/女、0/1 等。),但我们可以在转换中统一它们。
  • 数据可以预先汇总。例如,可以在 ETL/ELT 过程中生成每日/每周/每月报告,因此消费者可以非常高效地读取可操作的数据。
  • 使用 SCD(渐变维度)设计,数据仓库可以捕获数据源评估的历史。例如,如果有一个产品被移动到一个新的类别,它在数据仓库中是完全可追踪的,但是您可能会在事务数据库中丢失这个更改。

缺点:

  • 数据仓库中的数据会延迟一段时间才可用。例如,如果 ETL/ELT 过程每天都在运行,那么数据每天都是最新的,直到“昨天”。
  • 如果一个数据源改变了它的数据结构,ETL/ELT 需要相应地改变,这可能会导致大量的工作,以及在应用改变期间潜在的数据差异。
  • 依赖于数据源特性。例如,如果原始数据源没有可靠的时间戳,ETL/ELT 过程就不能以优雅的方式实现增量加载(只加载自上次加载以来新的/更改的记录)。

MASA(网状应用和服务架构)

经济性:★☆☆☆
维护性:★★★★
灵活性:★★★★

阿德里安·施瓦茨Unsplash 上拍摄的照片

MASA 是 Gartner 提出的一个相对较新的概念。它是从大量数据密集型企业(如优步[1])的经验中总结出来的。

令人惊讶的是,MASA 的想法更接近于第一种解决方案——中间件服务。然而,MASA 架构的重点是在企业后端系统(不面向客户)和前端系统(面向内部/外部客户)之间建立一个完整的综合 API 中介层。因此,MASA 和中间件服务之间的主要区别在于,前者旨在为不同粒度的后端系统构建统一的、系统的和可管理的服务。

MASA 架构由 3 个主要层组成[2]:

  • 多粒度服务,包括所有的企业后端服务。“多粒度”意味着后端服务具有不同的规模,因此它们支持外部数据消费的能力也不同。例如,ERP/CRM 系统通常包含许多子组件,这些子组件被设计为在内部彼此紧密合作,而不是向外部提供数据。因此,确定后端服务的粒度以应用不同的策略非常重要。
  • API 中介,负责将请求从外部 API(数据消费者的接口)映射到内部 API(后端服务的接口)。在两个 API 层之间的委托过程中,it 部门还需要实时转换数据,确保安全性,并监控使用情况和性能。
  • 多体验应用,也称为“适合用途”应用。无论数据的最终用户是谁,目的是什么,前端的设计都应该满足他们的需求,并以期望的表示形式提供数据。

优点:

  • MASA 是真正的“真实的单一来源”,因为它不像数据仓库那样以另一种形式复制数据。
  • 最大限度地提高企业级所有数据消费的灵活性和敏捷性。比如可以在全公司范围内实现“自助式”数据消费。
  • 理论上,数据可用性没有延迟。

缺点:

  • 昂贵的
  • 昂贵的
  • 昂贵的

摘要

Unsplash 上拍摄的

在这篇文章中,我解释了我对企业数据平台优化的看法。事实上,在一家数据驱动型公司的发展过程中,这三种解决方案都有可能被利用。也就是说,当一家公司仍处于初创阶段时,可能根本没有任何“优化”的解决方案。随着一些需求的提出,由于资源有限,公司可能会开始使用更简单的解决方案来解决这些问题。然后,随着公司越来越成熟,可能会引入数据仓库。我相信大多数公司可能只需要这种解决方案,并在很长一段时间内使用数据仓库。最后,如果该公司成为其行业的巨头,MASA 将成为最终的解决方案。

[## 通过我的推荐链接加入 Medium 克里斯托弗·陶

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

medium.com](https://medium.com/@qiuyujx/membership)

如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)

参考:

[1] Searle 等人【2017 年十大战略技术趋势:Mesh App 和服务架构。高德纳研究公司。https://www . Gartner . com/en/documents/3645328/top-10-strategic-technology-trends-for-2017-mesh-app-和

[2] B .戴利。MASA: 如何用应用、API 和服务创建一个敏捷的应用架构。高德纳研究公司。https://www . Gartner . com/en/documents/3980382/masa-how-to-create-a-agile-application-architecture-wit

Spark 加盟战略——方式和内容?

原文:https://towardsdatascience.com/strategies-of-spark-join-c0e7b4572bcf?source=collection_archive---------0-----------------------

Spark 加盟的内涵& Spark 的加盟策略选择

在处理数据时,我们都处理过不同种类的连接,可能是innerouterleft或(可能是)left-semi。本文介绍了 Spark 用来执行join操作的不同连接策略。了解 spark join 的内部机制有助于优化复杂的 join 操作,找到一些内存不足错误的根本原因,并提高 spark 作业的性能(我们都希望如此,不是吗?).请继续阅读,找出答案。

Russ Ward 在 Unsplash 上拍摄的照片

Spark 加盟策略:

广播哈希连接

在开始广播 Hash join spark 之前,让我们先了解一下 Hash Join,一般来说:

散列连接

顾名思义,散列连接是通过首先基于较小关系的 join_key 创建一个散列表,然后遍历较大关系以匹配散列 join_key 值来执行的。此外,这仅支持“=”联接。

在 spark 中,散列连接在每个节点级别起作用,该策略用于连接节点上可用的分区。

现在,来广播散列连接。

广播散列连接

在广播散列连接中,其中一个join关系的副本被发送到所有工作节点,这节省了混洗成本。当您将一个大关系与一个小关系连接时,这很有用。这也称为映射端连接(将工作节点与映射器相关联)。

当其中一个join关系的大小小于阈值(默认为 10 M)时,Spark 部署这个连接策略。定义该阈值的火花属性是spark.sql.autoBroadcastJoinThreshold(可配置)。

使用 BitTorrent 协议在执行者之间共享广播关系(在这里阅读更多)。这是一种对等协议,其中文件块可以由对等方彼此共享。因此,它们不需要依赖单个节点。对等协议是这样工作的:

对等协议

需要注意的事项:

  • 广播的关系应该完全适合每个执行者和驱动程序的记忆。在驱动程序中,因为驱动程序将开始数据传输。
  • 仅支持“=”联接。
  • 支持除完全外部联接之外的所有联接类型(内部、左侧、右侧)。
  • 当广播大小较小时,它通常比其他连接策略更快。
  • 关系的副本在网络上广播。因此,当广播大小很大时(例如,当明确指定使用广播加入/更改默认阈值时),作为网络密集型操作可能会导致内存不足错误或性能问题。
  • 广播后,您不能更改广播的关系。即使您这样做了,它们对工作节点也是不可用的(因为副本已经发布)。

洗牌哈希加入

无序散列连接

Shuffle Hash Join 涉及在同一个 executor 节点中移动具有相同连接键值的数据,然后进行 Hash Join(如上所述)。使用连接条件作为输出键,数据在执行器节点之间混洗,在最后一步,使用散列连接合并数据,因为我们知道相同键的数据将出现在同一个执行器中。

需要注意的事项:

  • 仅支持“=”联接。
  • 连接键不需要是可排序的(这在下面会有意义)。
  • 支持除完全外部联接之外的所有联接类型。
  • 在我看来,这是一种代价很高的连接方式,既涉及到洗牌又涉及到散列(如上所述的散列连接)。维护哈希表需要内存和计算。

混洗排序合并连接

让我们首先了解排序-合并连接

排序合并联接

排序连接包括,首先根据连接键对关系进行排序,然后合并两个数据集(考虑合并排序的合并步骤)。

现在,让我们来理解 spark 中的 shuffle 排序-合并连接策略:

无序排序合并连接

混洗排序-合并连接涉及混洗数据以获得相同工作者的相同 join_key,然后在工作者节点中的分区级别执行排序-合并连接操作。

需要注意的事项:

  • 从 spark 2.3 开始,这是 spark 中默认的连接策略,可以用spark.sql.join.preferSortMergeJoin禁用。
  • 仅支持“=”联接。
  • 连接键需要是可排序的(显然)。
  • 支持所有连接类型。

笛卡尔连接

在这个策略中,计算两个关系的笛卡尔积(类似于 SQL)来评估 join。

广播嵌套循环连接

请将此视为两种关系的嵌套循环比较:

for record_1 in relation_1:
  for record_2 in relation_2:
    # join condition is executed

如你所见,这可能是一个非常缓慢的策略。这通常是在无法应用其他连接类型时的后备选项。Spark 使用广播查询适当部分的[BroadcastNestedLoopJoinExe](https://jaceklaskowski.gitbooks.io/mastering-spark-sql/spark-sql-SparkPlan-BroadcastNestedLoopJoinExec.html)c 操作符来处理这个问题,因此您可以认为至少会广播一些结果来提高性能。

需要注意的事项:

  • 支持“=”和非等值联接(“≤=”、“
  • 支持所有连接类型

spark 如何选择加盟策略?

直接取自 spark 代码,让我们看看 spark 是如何决定加入策略的。

如果是“=”连接:

按照以下顺序查看连接提示:
1。广播提示:如果加入类型受支持,选择broadcast hash join
2。排序合并提示:如果连接键是可排序的,选择sort-merge join
3。无序散列提示:如果连接类型受支持,选择shuffle hash join
4。shuffle replicate NL 提示:如果连接类型是 inner like,则选择cartesian product

如果没有提示或提示不适用
1。如果一边足够小可以广播,并且支持加入类型,则选择broadcast hash join
2。如果一边足够小,可以构建本地哈希映射,并且比另一边小得多,则选择shuffle hash join,并且spark.sql.join.preferSortMergeJoin为假。
3。如果连接键可排序,选择sort-merge join
4。如果连接类型是内部,选择cartesian product
5。选择broadcast nested loop join作为最终解决方案。它可能会爆炸,但没有其他选择。

如果不是' =' join:

看看加入提示,按以下顺序:
1。广播提示:挑broadcast nested loop join
2。shuffle replicate NL 提示:如果连接类型是 inner like,选择cartesian product

如果没有提示或提示不适用
1。如果一边足够小,可以播放,则选择broadcast nested loop join
2。如果连接类型是内部相似,选择 cartesian product
3。选择broadcast nested loop join作为最终解决方案。它可能会爆炸,但我们别无选择。

再见。

能源物联网系统中的流学习

原文:https://towardsdatascience.com/stream-learning-in-energy-iot-systems-11f6ef089390?source=collection_archive---------28-----------------------

联合循环电厂的案例研究

图片来自https://www.pxfuel.com/en/free-photo-ebrro并获得了知识共享零许可——CC0

联合循环电厂发电量的预测是电力和能源系统领域的一个关键挑战。这种发电量会随着环境变量而变化,例如温度、压力和湿度。因此,商业问题是如何预测作为这些环境条件的函数的电力生产,以便最大化利润。研究团体已经通过应用机器学习技术解决了这个问题,并且与传统的热力学分析相比,已经设法减少了计算和时间成本。到目前为止,这一挑战一直是从批量学习的角度来解决的,在批量学习中,假设数据是静止的,并且模型不会不断地将新信息集成到已经构建的模型中。本文介绍了一种更接近大数据和物联网范式的方法,在这种方法中,数据不断到达,模型以增量方式学习,在数据处理(时间、内存和计算成本)方面实现显著增强,并获得有竞争力的性能。本文比较和检查了几个流式回归器的每小时电功率预测,并讨论了在时间处理和预测性能方面应用于该流式场景的最佳技术。

介绍

联合循环发电厂(CCPPs)的效率是该技术在电力组合中渗透的一个关键问题。最近的一份报告[1]估计,在未来十年,涉及联合循环技术的项目数量将增加 3.1%,这一估计主要是基于 CCPPs 的高效率。CCPPs 中的电力生产预测包含许多因素,应考虑这些因素以实现准确的估计。电网运营商通常基于历史数据和环境因素(例如温度、压力和湿度)来预测电力需求。然后,他们将这些预测与可用资源进行比较,如煤、天然气、核能、太阳能、风能或水力发电厂。发电技术(如太阳能和风能)高度依赖于环境条件,所有发电技术都要进行计划内和计划外维护。因此,电网运营商面临的挑战是如何处理可用资源与实际需求之间的缺口。调峰电厂的发电量因环境条件而异,因此业务问题是预测作为气象条件函数的调峰电厂的发电量,因为这将使电网运营商能够就开启调峰电厂的数量(或是否从另一个电网购买通常昂贵的电力)进行经济权衡。

本文中提到的 CCPP 使用两台燃气轮机(GT)和一台蒸汽轮机(ST ),用同样的燃料比传统的简单循环发电厂多发电 50%。来自 GTs 的废热被输送到附近的两个 STs,产生额外的电力。在这个真实的环境中,热力学分析迫使数以千计的非线性方程的解几乎不可行,占用了太多的计算内存和时间成本。通过使用基于机器学习的方法来克服这一障碍,这是一种代替热力学方法的常用方法[2]。对其电力生产的正确预测对于电厂的效率和经济运行非常重要,并且最大化来自可用兆瓦时的收入。GTs 的可持续性和可靠性在很大程度上取决于电力生产预测,主要是在受到高盈利能力和
合同责任的约束时。

我们的观点接近真实系统,在真实系统中,快速数据可能是巨大的,它处于运动中,它是紧密相连的,并且只有有限的资源(例如时间、内存)来处理它。虽然每次有新实例可用时(批处理中发生的情况),重新训练学习算法似乎并不合适,但流观点在数据处理(更少的时间和计算成本)、算法训练(每次新实例出现时都会更新)方面引入了重大增强,并呈现了 CCPP 的现代化愿景,将其视为物联网应用,以及工业 4.0 范式的一部分。

流学习方法的相关性

大数据范式在过去十年获得了发展势头,因为它承诺为许多现实世界的应用提供有价值的见解[3]。随着这种新兴模式的出现,不仅可用数据量增加,而且数据到达速度的概念也随之增加,即这些现实世界的应用程序实时生成数据的速度比传统系统处理数据的速度更快。大数据范式的一个特例是实时分析或流学习(SL),其中可能无限的项目序列(数据流)连续到达,并且每个项目都有时间戳,因此有时间顺序。数据流一个接一个地到达,我们想要实时地建立和维护这些项目的模型(例如,预测器)。

这种情况使我们认为,我们必须处理潜在的无限且不断增长的数据集,这些数据集可能以批量实例或逐个实例的方式连续到达,这与传统系统(批量学习)形成对比,在传统系统中可以自由访问所有历史数据。这些传统的
处理系统假设数据是静态的,同时被访问。例如,数据库系统可以存储大量数据,并允许用户运行查询或事务。基于批处理的模型不会不断地将新信息集成到已经构建的模型中,而是定期从头开始重建新模型。然而,由 SL 执行的增量学习通过不断地将信息结合到它的模型中,为这种特定的流处理提供了优势,并且传统上旨在最小化处理时间和空间。由于其连续大规模和实时处理的能力,增量学习最近在大数据背景下获得了更多的关注。SL 也带来了许多新的挑战和严峻的条件:

  • 在每个时刻只有单个样本(或小批量的实例)被提供给学习算法,
  • 非常有限的处理时间,
  • 有限的内存,以及
  • 每次扫描数据流时都需要训练模型。

此外,这些数据流可能会随着时间的推移而演变,并可能偶尔受到其数据分布变化的影响(概念漂移 ) [4],迫使系统在非平稳条件下进行学习。

我们可以找到许多真实世界的 SL 应用示例,例如移动电话、工业过程控制、智能用户界面、入侵检测、垃圾邮件检测、欺诈检测、贷款推荐、监控和流量管理等。在这种背景下,物联网(IoT)已经成为 SL [5]的主要应用之一,因为它正在持续实时地产生大量数据。因此,流数据分析正在成为从每时每刻发生的事情中提取有用知识的标准,允许人们或组织在出现不便或新趋势时快速做出反应,帮助他们提高绩效。

系统描述

提议的 CCPP 由两台燃气轮机、一台蒸汽轮机和两台余热蒸汽发生器组成。在 CCPP 中,电力由 GTs 和 STs 产生,它们在一个循环中结合,并从一个涡轮机传输到另一个涡轮机。CCPP 捕捉燃气轮机的废热,以提高效率和
电力生产。基本上,CCPP 的工作原理可以描述如下(见图 1):

  • 燃气轮机燃烧燃料:燃气轮机压缩空气,并将其与加热到很高温度的燃料混合。热空气燃料混合物穿过燃气轮机叶片,使它们旋转。快速旋转的涡轮驱动发电机,将一部分旋转能量转化为电能
  • 热回收系统收集废气:热回收蒸汽发生器收集燃气轮机中的废气热量,否则这些热量会通过排气管逸出。热回收蒸汽发生器利用燃气轮机的废热产生蒸汽,并将其输送至蒸汽发生器
  • 蒸汽轮机提供额外的电力:蒸汽轮机将其能量传送到发电机传动轴,在那里转化为额外的电力

这种类型的 CCPP 安装在世界各地越来越多的工厂中,这些工厂可以获得大量的天然气。如[3]中所述,拟建 CCPP 的设计额定发电能力为 480 兆瓦,由 2 × 160 兆瓦
ABB 13E2 燃气轮机、2 ×双压热回收蒸汽发生器和 1 × 160 兆瓦 ABB ST .燃气轮机组成。负荷对环境条件敏感;主要是环境温度(AT)、大气压力(AP)和相对湿度(RH)。然而,ST 负荷对排汽压力(或真空,V)很敏感。GTs 和 STs 的这些参数用作输入变量,GTs 和 STs 产生的电力用作本研究数据集中的目标变量。所有这些都在表 1 中进行了描述,并且对应于由图 1 中所示的传感器从测量点接收的平均每小时数据。

图一。基于[6]的联合循环发电厂的布局。HP 是高压,LP 是低压
压力,D 是汽包,G 是发生器,SH 是过热器,E 是 Evapo,EC 是 Eco,HRSG 是余热
回收蒸汽发生器。AT、AP、RH、V 和 PE 是表 1 中描述的变量。该图片属于我们在 https://www.mdpi.com/1996-1073/13/3/740/htm的开放获取出版物。

表 1。数据集的输入和目标变量。

我们的流学习方法

当设计 SL 算法时,我们必须考虑几个算法和统计因素。例如,我们必须面对这样一个事实,即由于我们不能存储所有的输入,我们不能撤销根据过去的数据做出的决策。在批量学习处理中,我们可以自由访问过程中收集的所有历史数据,然后我们可以应用准备技术,如预处理、变量选择或对数据集的统计分析等(见图 2)。然而,流处理的问题是无法访问整个过去的数据集,我们不得不
选择以下策略之一。

第一种是在每次接收新的一批实例或一个实例时执行准备技术,这增加了计算成本和时间处理;可能会出现这样的情况:由于新的实例不断出现,流程流无法停止以执行这一准备过程,这可能是一项具有挑战性的任务。第二个是存储第一组实例(预备实例)并执行那些预备技术和数据流分析,将结论应用于到来的实例。后一种情况在流应用于真实环境时非常常见,并且已经被本作品采用。本文稍后将展示选择第一组实例的大小(这可能取决于可用内存或我们收集或处理这些数据所花费的时间)对于在其余流中实现有竞争力的性能是如何至关重要的。

图二。本工程 SL 工艺方案。该图片属于我们在 https://www.mdpi.com/1996-1073/13/3/740/htm 的开放获取出版物。

一旦收集了这些第一批实例,在本文中,在流处理开始之前,将应用三种常见的准备技术来准备我们的流回归算法(SRs):变量选择、超参数调整和预训练。

我们通过使用测试-然后-训练评估,仅用到达的实例训练和测试我们的算法(参见图 3)。数据流回归通常在在线设置中进行评估,如图 3 所示,其中数据没有被分成训练集和测试集。相反,每个模型随后预测一个实例,该实例随后用于构建下一个模型。

图三。采用先测试后培训评估的流学习(在线学习)方案。该图片属于我们在 https://www.mdpi.com/1996-1073/13/3/740/htm的开放获取出版物。

问题的定义

产生的电功率的预测作为回归问题来处理。像每一种机器学习方法一样,SL 算法从数据集中估计独立输入变量和从属目标变量之间的未知依赖性。在我们的文章中,SRs 根据由电偶(xt,yt)(即实例)组成的数据集预测 CCPP 的发电量,并且它们建立了一个映射函数:

yˇt =(XT,yt)

利用这些夫妇。他们的目标是选择最佳函数,使系统的实际产量(yt)和基于数据集实例(训练实例)的预测产量(yˇt)之间的误差最小。
本文提供了流学习者的比较,因为在这些实时机器学习条件下,我们需要增量学习的回归方法。然后,本文确定了在当前场景中应用的最佳技术,即 CCPP 的实时电力生产预测。本文考虑了以下 SRs:

  • 被动-主动回归方程
  • 随机梯度下降回归器(SGDR)
  • 多层感知器回归器(MLPR)
  • 回归赫夫丁树
  • 回归赫夫丁适应树(RHAT)
  • 蒙德里安树回归器
  • 蒙德里安森林回归量

实验

本文设计了一个广泛的实验基准,通过从误差度量和时间处理方面比较 7 种广泛使用的随机共振方法,找出最适合于 CCPPs 中电功率预测的随机共振方法。实验基准被分成 4 个不同的实验(见表 2 ),考虑了两个预备尺寸和两个变量选择选项。这样做的目的是在流式处理结束时,观察为准备阶段选择的实例数量的影响,并测试变量选择过程在此流式处理场景中的相关性。每个实验已经运行了 25 次,实验基准遵循了图 2 所示的方案。

表二SRs 比较的实验基准。

结果呢

数据探索性分析

输入变量(AT、V、AP、RH)对目标变量(PE)的影响不同。图 4 显示了输入和目标变量之间的相关性。一方面,我们观察到 AT 的增加如何导致 PE 的减少,散点的最小垂直分布表明它们之间有很强的反比关系。众所周知,温度升高导致的性能下降源于进气密度的降低。

图 4。散点图,用于可视化特征之间的相关性,以及拟合数据的线性回归模型。该图片属于我们在 https://www.mdpi.com/1996-1073/13/3/740/htm的开放获取出版物。

另一方面,我们可以看到随着 V 的增加如何产生 PE 的减少,也可以说它们之间有很强的反比关系。在这种情况下,价差略大于变量 AT,这暗示关系稍弱。这一结论也得到图 5 中相关值-0.87 的支持。从图 1 中可以看出,CCPP 使用了一个 ST,这大大提高了总的电气效率。并且当所有其他变量保持不变时,已知 V 对冷凝型涡轮机效率具有负面影响。

图五。热图,用于可视化特征之间的相关性。该图片属于我们在 https://www.mdpi.com/1996-1073/13/3/740/htm 的开放获取出版物。

在 AP 和 RH 的情况下,尽管 PE 随着它们的增加而增加,图 4 描绘了分散点的大的垂直分布,这表明弱的正相关关系,这也在图 5 中得到证实,其中 0.52 和 0.39 分别显示为这些变量的相关值。AP 还负责进气密度,当所有其他变量保持不变时,PE 随着 AP 的增加而增加。在 RH 的情况下,增加 GTs 的废气温度,导致 st 产生的功率增加。

SRs 比较

表 3-6 分别显示了实验 1、2、3 和 4 中每个服务请求的误差指标(MSE、RMSE、MAE、R2)和时间处理(时间),单位为秒。

表 3。实验 1 的结果:具有 5%预备实例的变量选择。注意,
RMSE =梅,因为所有的差异都是相等的。

表 4。实验 2 的结果:没有变量选择,具有 5%的预备实例。注意
RMSE =梅,因为所有的差异都是相等的。

表 5 。实验 3 的结果:具有 20%预备实例的变量选择。注意,
RMSE =梅,因为所有的差异都是相等的。

表 6。实验 4 的结果:没有变量选择,有 20%的预备实例。注意
RMSE =梅,因为所有的差异都是相等的。

现在,文章在表 7 中显示了实验 1 和 3 中变量选择过程的结果。

表 7。每个实验中的变量选择结果。那些选择的特征用 y
(是)表示,其余的用 n(否)表示。

讨论

讨论首先强调了在 SL 流程中具有代表性的预备实例集的相关性。如前所述,在流式场景中,不可能访问所有历史数据。然后,需要应用一些策略来对输入数据进行假设,除非发生漂移(在这种情况下,需要适应新的分布)。这些策略之一包括存储流的第一个实例(准备实例),以执行一组准备技术,使流算法为流处理做好准备。我们在工作中选择了这一战略。

预备技术有助于提高 SRs 的性能。理论上,通过选择对预测变量贡献最大的变量/特征子集(变量或特征选择),我们避免了可能对模型性能产生负面影响的不相关或部分相关的特征。通过选择最合适的算法参数(超参数调整),我们获得更好地适应数据的 SRs。并且通过在流式传输过程开始之前训练我们的 Sr(预训练,我们获得了为流式传输过程准备的具有更好性能的算法。缺点在于,我们在过程开始时收集的实例越多,就需要执行准备技术的时间越多。除了前面提到的限制之外,这是我们在每个场景中都应该考虑的一个权衡。

关于准备实例的数量,正如机器学习技术经常发生的那样,用于训练(或其他目的)的可用实例越多,SRs 的性能就越好,因为用更多的数据可以更好地表示数据分布,并且 SRs 被更多地
训练和调整以适应数据分布。但另一方面,这种情况通常会在内存大小、计算能力或流式传输过程必须开始的时刻等方面造成限制。将实验 1 和 3(见表 3 和表 5,其中执行了选择
过程,准备实例分别为数据集的 5%和 20%)与实验 2 和实验 4(见表 4 和表 6,其中未执行变量选择过程,准备实例也分别为数据集的 5%和 20%)进行比较,我们观察到在几乎所有情况下(除了 MTR 和 MFR,当执行变量选择时)当准备实例的数量较大时,误差度量如何改善。因此,通过留出一组实例用于准备目的,我们通常可以为这些流学习者获得更好的结果。

变量选择过程的情况下,我们从表 3 和表 4 的比较中推断出,这种预备技术提高了 RHT 和 RHAT 的性能,同时也减少了它们的处理时间。对于 PAR、SGDR 和 MLPR,它实现了类似的性能,但也减少了处理时间。因此,当预备尺寸为 5%时,除了 MTR 和 MFR 之外,对它们都是推荐的。在比较表 5 和表 6 的情况下,这种预备技术提高了 PAR 和 RHAT 的性能,并且还减少了它们的处理时间。对于 SGDR、MLPR 和 RHT,性能和处理时间非常相似。因此,除了 MTR 和 MFR(当预备尺寸为 20%时)之外,它也适用于所有制造商。在关于在实验 1 和 3 中已经为流过程选择了哪些特征的内容中,我们在表 7 中看到 at 和 V 如何通过超参数调整方法优于其余的,这也在第 5.1 节中得到证实,因为它们与目标变量(PE)相关。

最后,关于最佳 SR 的选择,表 3-6 显示了在变量选择过程中,MLP 和 RHT 如何显示两种准备尺寸的最佳误差指标。当没有变量选择过程时,那么最佳误差度量是由 MFR 实现的。然而,就处理时间的
而言,SGDR 和 MTR 是最快的 stream 学习者。由于我们必须在误差度量结果和时间处理之间找到平衡,我们推荐 RHT。值得一提的是,如果我们检查性能指标(MSE、RMSE、MAE 和 R 2),RHT 显示出比 RHAT 更好的结果
,然后我们可以假设数据集中没有发生漂移。在漂移的情况下,RHAT 应该表现出比 RHT 更好的性能指标,因为它是为非稳定环境设计的。

结论

这项工作为这种场景提供了一种新的方法,在这种场景中,数据
不断到达,回归模型必须增量学习。这种方法更接近于新兴的大数据和物联网范式。所获得的结果显示了当将 SL 方法应用于该特定场景时,如何实现有竞争力的错误度量和处理时间。具体来说,这项工作已确定 RHT 为实现 CCPP 电力生产预测的最值得推荐的技术。该文章还强调了准备技术的相关性,以使流式算法为流式处理做好准备,同时强调了正确选择准备实例数量的重要性。关于特性的重要性,正如以前从批量学习角度解决相同问题的案例一样,我们建议对所有 Sr(除了 MTR 和 MFR)执行变量选择
过程,因为它减少了流处理时间,同时由于性能提升,它是值得的。

最后,作为未来的工作,我们希望将这种 SL 方法转移到联合循环电厂的其他过程中,甚至转移到其他类型的电厂中。

承认

我要感谢研究团队的其他成员(来自 UPV/EHU 的伊戈尔·巴列斯特罗斯,来自泰克纳利亚的伊萨孔·奥雷吉和哈维尔·德尔·塞尔,以及来自阿尔卡拉大学的桑丘·萨尔塞多·桑斯)。

参考

[1] 黑色和维奇。布莱克和维奇战略方向:电气报告:技术报告;布莱克和维奇:堪萨斯州,密苏里州,美国,2018。在线提供:https://www.bv.com/resources/2018-strategic-directions-电力-工业-报告(2020 年 1 月 28 日访问)

[2] 凯斯金,美国;使用软计算技术模拟热力系统。里面的 j .能源决议 2005,29,581-611。

[3] 周,周振华;北卡罗来纳州舒拉;金;Williams,G.J .大数据机遇和挑战:从数据分析角度进行讨论[论坛]。IEEE Comput。智能。玛格。2014, 9, 62–74.

[4]陆,j;刘;董,女;顾,女;伽马,j;概念漂移下的学习:一个综述。IEEE Trans。知道了。数据工程。2018, 31, 2346–2363.

[5] 德·弗朗西斯·莫拉莱斯;比费特公司;汗湖;伽马,j;物联网大数据流挖掘。2016 年 8 月 13 日至 17 日在美国加利福尼亚州旧金山举行的第 22 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集;第 2119-2120 页。

[6] Tüfekci,p .使用机器学习方法预测基本负荷运行的联合循环发电厂的全负荷电力输出。里面的伊莱克特。动力能源系统。2014, 60, 126–140.

注意

本文基于 2020 年发表在能源*期刊上的开放获取科学手稿。可在https://www.mdpi.com/1996-1073/13/3/740/htm处进入。

使用 Debezium、Kafka 和融合的 JDBC Sink Connector 将 MySQL 中的数据更改导入 ElasticSearch

原文:https://towardsdatascience.com/stream-your-data-changes-in-mysql-into-elasticsearch-using-debizium-kafka-and-confluent-jdbc-b93821d4997b?source=collection_archive---------21-----------------------

如何使用 Debezium 将 MySQL 中的数据变化一步一步地导入 Elasticsearch

杰罗姆·普拉克斯在 Unsplash 上的照片

快速搜索能力,实时综合数据,现在是必要的,如果我们想建立像电子目录或电子商务。我们不希望我们的用户生气,因为他们花费大量时间只是为了从我们的门户网站获取信息。我们还希望我们的产品团队在不同的应用程序中输入的产品信息能够立即被我们的用户或客户搜索到。

比方说使用 MySQL 作为主要数据源的产品团队。我们将在门户网站中使用 ElasticSearch 作为搜索引擎服务。我们需要 MySQL 的每一个变化都会立即影响到 ElasticSearch 索引。如何达到那个要求?

在我的第一篇文章中,我将展示如何使用 Debezium、Kafka 和融合 JDBC Sink Connector 将 MySQL 中的数据更改流式传输到 ElasticSearch 中,以实现上述用例需求。感谢我的主人 Erfin Feluzy ,他把我介绍给 Debezium,并给了我写第一篇关于媒介的文章的灵感。

解决方案高级图表

解决方案 HLD 图

关于技术的简短介绍

Debezium

Debezium 是一个分布式平台,它将您现有的数据库转换成事件流,因此应用程序可以对数据库中的每个行级更改做出快速反应。Debezium 构建在 Kafka 之上,提供 Kafka Connect 兼容的连接器来监控特定的数据库管理系统。Debezium 在 Kafka 日志中记录数据更改的历史,因此您的应用程序可以在任何时候停止和重新启动,并且可以轻松地消耗它在不运行时错过的所有事件,确保所有事件都得到正确和完整的处理。

Debezium 是在 Apache 许可下的开源软件,版本 2.0

卡夫卡

Apache Kafka 是由 LinkedIn 开发的开源 流处理软件平台,捐赠给 Apache 软件基金会,用 ScalaJava 编写。该项目旨在为处理实时数据馈送提供一个统一、高吞吐量、低延迟的平台。

汇流 JDBC 水槽连接器

Kafka Connect Elasticsearch 接收器连接器允许将数据从 Apache Kafka 移动到 Elasticsearch。它将 Apache Kafka 中一个主题的数据写入 Elasticsearch 中的一个索引中,一个主题的所有数据都是相同的

让我们开始教程

在本教程中,我们将为每个服务使用一个单独的容器,不使用持久卷。ZooKeeper 和 Kafka 通常将它们的数据本地存储在容器中,这需要您在主机上将目录挂载为卷。因此,在本教程中,当容器停止时,所有持久化的数据都会丢失

第一步运行 Zookeeper

使用 debezium/zookeeper 映像在容器中启动 zookeeper。容器将以名称 zookeeperdbz 运行

> docker run -it — name zookeeperdbz -p 2181:2181 -p 2888:2888 -p 3888:3888 debezium/zookeeper:1.1

检查运行日志以验证 zookeeper 运行成功并监听端口2181

Starting up in standalone modeZooKeeper JMX enabled by defaultUsing config: /zookeeper/conf/zoo.cfg
.
.
.
020-05-13 17:18:28,564 - INFO  [main:NIOServerCnxnFactory@686] - binding to port 0.0.0.0/0.0.0.0:2181

第二步运行卡夫卡

使用 debezium/kafka docker 映像在容器中启动 Kafka。该容器将以名称 kafkadbz 运行

> docker run -it — name kafkadbz -p 9092:9092 --link zookeeperdbz:zookeeperdbz debezium/kafka

验证 Kafka 服务器已启动

卡夫卡开始了

第三步运行 MySQL

在这个演示中,我将使用一个预配置的 Docker 映像,它也包含 Debezium 提供的样本数据。

使用 debezium/example-mysql image 在容器中启动 MySQL。容器将以名称 mysqldbz 运行

> docker run -it -d --name mysqldbz -p 3306:3306 -e MYSQL_ROOT_PASSWORD=debezium -e MYSQL_USER=mysqluser -e MYSQL_PASSWORD=mysqlpw debezium/example-mysql

上面的命令将创建一个名为 mysqldbz 的容器。

接下来,让我们执行容器,并在容器上输入交互式 bash shell。

> docker exec -it mysqldbz /bin/bash

要在 MySQL 上使用 capture CDC,Debezium 需要在我们的 MySQL 中启用 bin_log 配置。多亏了 Debezium,因为我们使用的是预配置的 MySQL Docker 映像,所以我们不再需要配置它了。让我们检查一下配置。

# more /etc/mysql/conf.d/mysql.cnf

MySQL bin_log 已启用

如您所见,bin_log 是启用的,默认情况下是禁用的。

检查样本数据库

# mysql -u root -p 
Enter password: <enter your password>mysql> use inventory
Database changedmysql> show tables;
+---------------------+
| Tables_in_inventory |
+---------------------+
| addresses           |
| customers           |
| geom                |
| orders              |
| products            |
| products_on_hand    |
+---------------------+6 rows in set (0.00 sec)mysql> select * from customers;+------+------------+-----------+-----------------------+
| id   | first_name | last_name | email                 |
+------+------------+-----------+-----------------------+
| 1001 | Sally      | Thomas    | sally.thomas@acme.com |
| 1002 | George     | Bailey    | gbailey@foobar.com    |
| 1003 | Edward     | Walker    | ed@walker.com         |
| 1004 | Anne       | Kretchmar | annek@noanswer.org    |
+------+------------+-----------+-----------------------+4 rows in set (0.00 sec)

步骤 4 启动弹性搜索服务

这里我们将使用单节点弹性和弹性版本 7.7。容器将以名称 elasticdbz 运行。

> docker run -it --name elasticdbz -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.7.0 

步骤 5 启动 Debezium Kafka 连接服务

该服务公开 REST API 来管理 Debezium MySQL 连接器。容器将以名称 connectdbz 运行。

> docker run -it --name connectdbz -p 8083:8083 -e GROUP_ID=1 -e CONFIG_STORAGE_TOPIC=my_connect_configs -e OFFSET_STORAGE_TOPIC=my_connect_offsets -e STATUS_STORAGE_TOPIC=my_connect_statuses **--link zookeeperdbz:zookeeperdbz --link kafkadbz:kafkadbz --link mysqldbz:mysqldbz --link elasticdbz:elasticdbz** debezium/connect

不要忘记将该容器与 kafkadbz zookeeperdbz、elasticdbz 链接,因为该服务需要与 kafkadbz zookeeperdbz、elasticdbz 服务进行通信。

使用 CURL 检查 Debezium Kafka Connect 服务的状态,从响应中我们会看到我们使用的是 2.4.0 版本

> curl -H "Accept:application/json" localhost:8083/
{"version":"2.4.0","commit":"77a89fcf8d7fa018","kafka_cluster_id":"XcbUOTN_TNG4hCftkY_j3w"}

让我们注册 MySQL 连接器来监视库存数据库中的 CDC

> curl -i -X POST -H "Accept:application/json" -H "Content-Type:application/json" localhost:8083/connectors/ -d '
{
"name": "inventory-connector",
"config": {
"connector.class": "io.debezium.connector.mysql.MySqlConnector",
"tasks.max": "1",
"database.hostname": "**mysqldbz**",
"database.port": "3306",
"database.user": "debezium",
"database.password": "dbz",
"database.server.id": "184054",
"database.server.name": "dbserver1",
"database.whitelist": "inventory",
"database.history.kafka.bootstrap.servers": "kafkadbz:9092",
"database.history.kafka.topic": "schema-changes.inventory"
}
}'

验证连接器是否在连接器列表中注册

> curl -H "Accept:application/json" localhost:8083/connectors/
["inventory-connector"]

现在,inventory-connector 已注册到连接器列表中

步骤 6 启动 Kafka 控制台消费者观察数据库上的变化

这一步只是为了观察数据库上的变化,如果你想消费主题,你必须写你的卡夫卡消费

部署 Debezium MySQL 连接器后,它开始监控inventory数据库的数据变更事件。

要观看dbserver1.inventory.customers主题,我们需要启动 Kafka 控制台消费者。容器将以名称 watcher 运行。

> docker run -it --rm --name watcher --link zookeeperdbz:zookeeperdbz --link kafkadbz:kafkadbz debezium/kafka watch-topic -a -k dbserver1.inventory.customers

运行观察器后,我们可以看到 Debezium 开始监控库存数据库,并将结果作为dbserver1.inventory.customers主题。

Debezium 启动监视器

"payload":{"before":null,
      "after":{"id":1004,
         "first_name":"Anne",
         "last_name":"Kretchmar",
         "email":"annek@noanswer.org"
},
      "source":{"version":"1.1.1.Final",
         "connector":"mysql",
         "name":"dbserver1",
         "ts_ms":0,
         "snapshot":"true",
         "db":"inventory",
         "table":"customers",
         "server_id":0,
         "gtid":null,
         "file":"mysql-bin.000003",
         "pos":154,
         "row":0,
         "thread":null,
         "query":null
},
      "op":"c",
      "ts_ms":1589504913171,
      "transaction":null}

让我们与表库存进行比较。客户

mysql> select * from customers;+------+------------+-----------+-----------------------+
| id   | first_name | last_name | email                 |
+------+------------+-----------+-----------------------+
| 1001 | Sally      | Thomas    | sally.thomas@acme.com |
| 1002 | George     | Bailey    | gbailey@foobar.com    |
| 1003 | Edward     | Walker    | ed@walker.com         |
| **1004 | Anne       | Kretchmar | annek@noanswer.org   ** |
+------+------------+-----------+-----------------------+

它看起来像是 Kafka 主题中与客户库存表中的记录相匹配的最后一个事件

让我们尝试更新客户表。

mysql > UPDATE `inventory`.`customers` SET `last_name` = 'Kretchmar Kretchmer' WHERE `id` = 1004;

这是观察器中的结果

...
"payload":{
"before":{
         "id":1004,
         "first_name":"Anne",
         "last_name":"Kretchmar",
         "email":"annek@noanswer.org"
},
      "after":{
         "id":1004,
         "first_name":"Anne",
         "last_name":"Kretchmar Kretchmer",
         "email":"annek@noanswer.org"
},
...

到这一步我们刚刚取得了什么?

至此,我们已经实现了 MySQL-Debezium-Kafka 的集成。当 MySQL 中有新的或更改的数据时,我们将从 Kafka 的主题中获得流式数据。

下一步是什么?

让我们开始与 ElasticSearch 整合

为了与 Elastic Search 集成,我们需要在 Debezium Kafka connect 容器上安装 Kafka Connect Elastic Sink 连接器。

步骤 7 下载 Kafka Connect 弹性汇连接器https://www . confluent . io/hub/confluent Inc/Kafka-Connect-Elastic search

步骤 8 提取下载的 zip 文件

解压缩的 zip 文件

第九步将 lib 文件夹重命名为 kafka-connect-jdbc

重命名为 kafka-connect-jdbc 后的 lib 文件夹

步骤 10 将 kafka-connect-jdbc 复制到 kafka-connect 的容器 debezium 中

> docker cp /**path-to-file**/confluentinc-kafka-connect-elasticsearch-5.5.0/kafka-connect-jdbc/* connectdbz:/kafka/connect/

步骤 11 验证所有依赖关系都已复制

> docker exec -it connectdbz /bin/bash
$ cd connect/kafka-connect-jdbc/
$ ls -all

ls-所有结果

步骤 12 重启 Debezium Kafka 连接容器

我们需要重新启动 Kafka connect 服务,使 Kafka connect 可以检测新安装的连接器插件

> docker stop connectdbz
> docker start connectdbz

步骤 13 注册 ElasticsearchSinkConnector

> curl -i -X POST -H "Accept:application/json" -H "Content-Type:application/json" localhost:8083/connectors/ -d '
{
"name": "elastic-sink",
"config": {
"connector.class":
"io.confluent.connect.elasticsearch.ElasticsearchSinkConnector",
"tasks.max": "1",
"topics": "**dbserver1.inventory.customers**",
"connection.url": "http://**elasticdbz**:9200",
"transforms": "unwrap,key",
"transforms.unwrap.type": "io.debezium.transforms.UnwrapFromEnvelope",
"transforms.key.type": "org.apache.kafka.connect.transforms.ExtractField$Key",
"transforms.key.field": "id",
"key.ignore": "false",
"type.name": "customer"
}
}'

验证 ElasticsearchSinkConnector 连接器是否已在连接器列表中注册

> curl -H "Accept:application/json" localhost:8083/connectors/
["elastic-sink","inventory-connector"]

步骤 14 检查 MySQL ElasticSearch 同步

让我们检查数据库和搜索服务器是否同步。

> curl ‘[http://localhost:9200/](http://localhost:9200/customers/_search?pretty)dbserver1.inventory.customers[/_search?pretty](http://localhost:9200/customers/_search?pretty)'{
  "took" : 12,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "dbserver1.inventory.customers",
        "_type" : "customer",
        "_id" : "1001",
        "_score" : 1.0,
        "_source" : {
          "id" : 1001,
          "first_name" : "Sally",
          "last_name" : "Thomas",
          "email" : "sally.thomas@acme.com"
        }
      },
      {
        "_index" : "dbserver1.inventory.customers",
        "_type" : "customer",
        "_id" : "1004",
        "_score" : 1.0,
        "_source" : {
          "id" : 1004,
          "first_name" : "Anne",
          "last_name" : "Kretchmar Kretchme",
          "email" : "annek@noanswer.org"
        }
      },
      {
        "_index" : "dbserver1.inventory.customers",
        "_type" : "customer",
        "_id" : "1002",
        "_score" : 1.0,
        "_source" : {
          "id" : 1002,
          "first_name" : "George",
          "last_name" : "Bailey",
          "email" : "gbailey@foobar.com"
        }
      },
      {
        "_index" : "dbserver1.inventory.customers",
        "_type" : "customer",
        "_id" : "1003",
        "_score" : 1.0,
        "_source" : {
          "id" : 1003,
          "first_name" : "Edward",
          "last_name" : "Walker",
          "email" : "ed@walker.com"
        }
      }
    ]
  }
}

正如我们所看到的,现在 MySQL 中的所有数据都是同步的。MySQL 中的所有数据都可以在上面的弹性索引中找到。

让我们将新数据插入到 Customers 表中,看看弹性索引中会发生什么。

mysql> insert into customers values(default, 'Rizqi', 'Nugrohon', 'rizqi.nugroho@example.com');
Query OK, 1 row affected (0.05 sec)mysql> select * from customers;
+------+------------+--------------------+------------------------+| id   | first_name | last_name          | email                     |+------+------------+--------------------+-----------------------+|| 1001 | Sally      | Thomas             | sally.thomas@acme.com  |
| 1002 | George     | Bailey             | gbailey@foobar.com     |
| 1003 | Edward     | Walker             | ed@walker.com          |
| 1004 | Anne       | Kretchmar Kretchme | annek@noanswer.org     |
| 1005 | Rizqi      | Nugrohon           | rizqi.nugroho@example.com |+------+------------+--------------------+---------------------------+

检查弹性指数

> curl ‘[http://localhost:9200/](http://localhost:9200/customers/_search?pretty)dbserver1.inventory.customers[/_search?pretty](http://localhost:9200/customers/_search?pretty)'{
  "took" : 1476,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "dbserver1.inventory.customers",
        "_type" : "customer",
        "_id" : "1001",
        "_score" : 1.0,
        "_source" : {
          "id" : 1001,
          "first_name" : "Sally",
          "last_name" : "Thomas",
          "email" : "sally.thomas@acme.com"
        }
      },
      ...
      {
        "_index" : "dbserver1.inventory.customers",
        "_type" : "customer",
        "_id" : "1005",
        "_score" : 1.0,
        "_source" : {
          "id" : 1005,
          "first_name" : "Rizqi",
          "last_name" : "Nugrohon",
          "email" : "rizqi.nugroho@example.com"
        }
      }
    ]
  }
}

插入带有名字 Rizqi 的 Viola 新数据

更新语句怎么样

mysql> UPDATE `inventory`.`customers` SET `last_name` = 'Adhi Nugroho' WHERE `id` = 1005;
Query OK, 1 row affected (0.05 sec)mysql> select * from customers;
+------+------------+--------------------+------------------------+| id   | first_name | last_name          | email                     |+------+------------+--------------------+-----------------------+|| 1001 | Sally      | Thomas             | sally.thomas@acme.com  |
| 1002 | George     | Bailey             | gbailey@foobar.com     |
| 1003 | Edward     | Walker             | ed@walker.com          |
| 1004 | Anne       | Kretchmar Kretchme | annek@noanswer.org     |
| 1005 | Rizqi      | Adhi Nugroho           | rizqi.nugroho@example.com |+------+------------+--------------------+---------------------------+

再次检查弹性指数

> curl ‘[http://localhost:9200/](http://localhost:9200/customers/_search?pretty)dbserver1.inventory.customers[/_search?pretty](http://localhost:9200/customers/_search?pretty)'...
      {
        "_index" : "dbserver1.inventory.customers",
        "_type" : "customer",
        "_id" : "1005",
        "_score" : 1.0,
        "_source" : {
          "id" : 1005,
          "first_name" : "Rizqi",
          "last_name" : "Adhi Nugroho",
          "email" : "rizqi.nugroho@example.com"
        }
      }
    ]
  }
}

妈妈咪呀,数据更新!!!

摘要

感谢我的师父Erfin Feluzyarticlehttps://medium . com/@ Erfin . Feluzy/tutorial-streaming-CDC-MySQL-ke-Kafka-dengan-debezium-3a1ec 9150 cf 8写的文章启发了我创作这篇文章。

最后,我们使用 Debezium 实现了 MySQL 和 ElasticSearch 的集成。我希望这个演示可以帮助您解决 MySQL DB 和 ElasticSearch 之间的数据延迟问题。现在 MySQL DB 中的所有改变都会立即影响到弹性索引。可以试着用另一个 DB 比如 PostgreSQL,Oracle,DB2,MSSQL 等。

参考:

https://medium . com/@ erfin . feluzy/tutorial-streaming-CDC-MySQL-ke-Kafka-dengan-debezium-3a1ec 9150 cf 8

https://debezium . io/documentation/reference/1.1/tutorial . html

https://docs . confluent . io/current/connect/Kafka-connect-elastic search/index . html

使用数据仓库进行流数据分析

原文:https://towardsdatascience.com/streaming-data-analytics-with-data-warehouses-583422140311?source=collection_archive---------21-----------------------

使用 Amazon Kinesis Data Firehose、Amazon Redshift 和 Amazon QuickSight 来分析流数据

音频介绍

数据库非常适合存储和组织需要大量面向事务的查询处理的数据,同时保持数据的完整性。相反,数据仓库是为对来自一个或多个不同来源的大量数据执行数据分析而设计的。在我们这个快节奏、高度互联的世界中,这些来源通常采用 web 应用程序日志、电子商务交易、社交媒体源、在线游戏活动、金融交易交易和物联网传感器读数等连续流的形式。必须近乎实时地分析流数据,但通常首先需要清理、转换和浓缩。

在下面的帖子中,我们将演示如何使用 Amazon Kinesis Data Firehose、Amazon Redshift 和 Amazon QuickSight 来分析流数据。我们将模拟时间序列数据,从一组物联网传感器流向 Kinesis 数据消防软管。Kinesis Data Firehose 将把物联网数据写入亚马逊 S3 数据湖,然后近乎实时地复制到 Redshift。在 Amazon Redshift 中,我们将使用 Redshift 数据仓库中包含的数据来增强流式传感器数据,这些数据已经被收集并反规格化为星型模式。

邮政示范建筑

在 Redshift 中,我们可以分析数据,提出一些问题,例如,在给定的时间段内,每个传感器位置的最低、最高、平均和中值温度是多少。最后,我们将使用 Amazon Quicksight,使用丰富的交互式图表和图形来可视化红移数据,包括显示地理空间传感器数据。

特色技术

本文将讨论以下 AWS 服务。

亚马逊 Kinesis 数据消防软管

根据亚马逊的说法,亚马逊 Kinesis Data Firehose 可以捕获、转换和加载流数据到数据湖、数据存储和分析工具中。直接 Kinesis 数据消防软管集成包括亚马逊 S3、亚马逊红移、亚马逊弹性搜索服务和 Splunk。Kinesis Data Firehose 利用现有的商业智能 (BI)工具和仪表盘实现近实时分析。

亚马逊红移

根据亚马逊的说法,亚马逊红移是最流行和最快的云数据仓库。借助 Redshift,用户可以使用标准 SQL 在您的数据仓库和数据湖中查询数 Pb 的结构化和半结构化数据。Redshift 允许用户在数据湖中查询和导出数据。Redshift 可以联合查询来自 Redshift 的实时数据,也可以跨一个或多个关系数据库进行查询。

亚马逊红移光谱

据亚马逊介绍,亚马逊红移光谱可以高效地从亚马逊 S3 的文件中查询和检索结构化和半结构化数据,而无需将数据加载到亚马逊红移表中。红移光谱表是通过定义数据文件的结构并将它们注册为外部数据目录中的表来创建的。外部数据目录可以是 AWS GlueApache Hive metastore。虽然红移光谱是将数据复制到红移中进行分析的替代方法,但在本文中我们不会使用红移光谱。

亚马逊 QuickSight

据亚马逊称, Amazon QuickSight 是一种完全托管的商业智能服务,可以轻松地向组织中的每个人提供见解。QuickSight 允许用户轻松创建和发布丰富的交互式仪表盘,其中包括Amazon quick sight ML Insights。然后,可以从任何设备访问仪表板,并将其嵌入到应用程序、门户和网站中。

什么是数据仓库?

据亚马逊称,数据仓库是一个中央信息库,可以对其进行分析以做出更明智的决策。数据从事务系统、关系数据库和其他来源流入数据仓库,通常是有规律的。业务分析师、数据科学家和决策者通过商业智能工具、SQL 客户端和其他分析应用程序访问数据。

示范

源代码

这篇文章的所有源代码都可以在 GitHub 上找到。使用以下命令 git 克隆项目的本地副本。

云的形成

使用项目中包含的两个 AWS CloudFormation 模板来构建两个 CloudFormation 堆栈。请查看这两个模板并了解资源成本,然后继续。第一个 CloudFormation 模板 redshift.yml ,提供了一个新的亚马逊 VPC 以及相关的网络和安全资源、一个单节点红移集群和两个 S3 桶。第二个 CloudFormation 模板 kinesis-firehose.yml ,提供了一个 Amazon Kinesis 数据 firehose 交付流、相关的 IAM 策略和角色,以及一个 Amazon CloudWatch 日志组和两个日志流。

更改REDSHIFT_PASSWORD值以确保您的安全。或者,更改REDSHIFT_USERNAME值。在创建第二个堆栈之前,请确保第一个堆栈成功完成。

查看 AWS 资源

要确认所有 AWS 资源都已正确创建,请使用 AWS 管理控制台。

Kinesis 数据消防软管

在 Amazon Kinesis 仪表板中,您应该会看到新的 Amazon Kinesis Data Firehose 交付流,redshift-delivery-stream。

新的 Amazon Kinesis Firehose 交付流的 Details 选项卡应该类似于下图。请注意 IAM 角色 FirehoseDeliveryRole,它是由 CloudFormation 创建并与交付流相关联的。

我们不对传入的消息执行任何转换。注意新的 S3 桶,它是由云形成产生并与气流联系在一起的。存储桶名称是随机生成的。这个桶是传入消息将被写入的地方。

请注意 1 MB 和 60 秒的缓冲条件。每当传入消息的缓冲区大于 1 MB 或时间超过 60 秒时,消息就会使用 GZIP 压缩以 JSON 格式写入 S3。这些是最小的缓冲条件,也是我们所能得到的最接近红移的实时流。

请注意COPY命令,该命令用于将消息从 S3 复制到 Amazon Redshift 中的message表。Kinesis 使用由 CloudFormation 创建的 IAM 角色 ClusterPermissionsRole 作为凭证。我们使用一个清单将数据从 S3 复制到红移。据 Amazon 称,清单确保COPY命令加载所有必需的文件,并且只加载数据加载所需的文件。清单由 Kinesis 消防软管交付流自动生成和管理。

红移星团

在 Amazon 红移控制台中,您应该看到一个新的单节点红移集群,由一个红移 dc2.large 密集计算节点类型组成。

请注意 CloudFormation 创建的新 VPC、子网和 VPC 安全组。此外,观察到红移星团可以在新 VPC 之外公开访问。

红移入口规则

单节点红移群集被分配到美国东部(N. Virginia) us-east-1 AWS 地区的 AWS 可用性区域。该群集与 VPC 安全组相关联。该安全组包含三个入站规则,都适用于红移端口 5439。与三个入站规则相关联的 IP 地址提供对以下内容的访问:1)美国东部-1 中亚马逊 QuickSight 的/27 CIDR 块,美国东部-1 中亚马逊 Kinesis Firehose 的/27 CIDR 块,以及对您而言,具有您当前 IP 地址的/32 CIDR 块。如果您的 IP 地址发生变化或者您不再使用美国东部-1 地区,您将需要更改这些 IP 地址中的一个或全部。Kinesis Firehose IP 地址列表在这里是。QuickSight IP 地址列表在这里是这里是

如果您无法从本地 SQL 客户端连接到 Redshift,最常见的情况是,您的 IP 地址已经更改,并且在安全组的入站规则中不正确。

红移 SQL 客户端

您可以选择使用红移查询编辑器与红移进行交互,或者使用第三方 SQL 客户端以获得更大的灵活性。要访问红移查询编辑器,请使用在Redshift . ymlcloud formation 模板中指定的用户凭据。

红移控制台和红移查询编辑器中有许多有用的功能。然而,在我看来,红移查询编辑器的一个显著限制是不能同时执行多个 SQL 语句。而大多数 SQL 客户端允许同时执行多个 SQL 查询。

我更喜欢使用 JetBrains py charm IDE。PyCharm 具有与 Redshift 的现成集成。使用 PyCharm,我可以编辑项目的 Python、SQL、AWS CLI shell 和 CloudFormation 代码,所有这些都可以在 PyCharm 中完成。

如果您使用任何常见的 SQL 客户端,您将需要设置一个 JDBC (Java 数据库连接)或 ODBC(开放式数据库连接)连接到 Redshift 。ODBC 和 JDBC 连接字符串可以在红移星团的 Properties 选项卡或 CloudFormation 堆栈的 Outputs 选项卡中找到。

您还需要之前执行的aws cloudformation create-stack AWS CLI 命令中包含的 Redshift 数据库用户名和密码。下面,我们看到 PyCharm 的项目数据源窗口包含一个红移dev数据库的新数据源。

数据库模式和表

CloudFormation 在创建红移星团的同时,也创建了一个新的数据库,dev。使用红移查询编辑器或您选择的 SQL 客户机,执行以下一系列 SQL 命令来创建一个新的数据库模式sensorsensor模式中的六个表。

星形模式

这些表表示从一个或多个关系数据库源获取的非规范化数据。这些表格形成了一个星形模式。星型模式被广泛用于开发数据仓库。星型模式由一个或多个引用任意数量的维度表事实表组成。locationmanufacturersensorhistory表是尺寸表。sensors表是一个事实表。

在下图中,外键关系是虚拟的,而不是物理的。该图是使用 PyCharm 的模式可视化工具创建的。注意模式的星形。message表是流式物联网数据最终将被写入的地方。message表通过公共的guid字段与sensors事实表相关联。

S3 的样本数据

接下来,将项目中包含的样本数据复制到用 CloudFormation 创建的 S3 数据桶中。每个 CSV 格式的数据文件对应于我们之前创建的一个表。由于 bucket 名称是半随机的,我们可以使用 AWS CLI 和 jq 来获取 bucket 名称,然后使用它来执行复制命令。

AWS CLI 的输出应该如下所示。

样本数据红移

关系数据库,如亚马逊 RDS,是为在线交易处理(OLTP)而设计的,而亚马逊 Redshift 是为在线分析处理(OLAP)和商业智能应用而设计的。为了将数据写入红移,我们通常使用COPY命令,而不是频繁的单独的INSERT语句,就像 OLTP 一样,这会非常慢。据亚马逊称,Redshift COPY命令利用亚马逊 Redshift 大规模并行处理(MPP)架构,从亚马逊 S3 上的文件、DynamoDB 表或一个或多个远程主机的文本输出中并行读取和加载数据。

在下面的一系列 SQL 语句中,用您的 S3 数据存储桶名称替换五处的占位符your_bucket_name。存储桶名称将以前缀redshift-stack-databucket开头。可以在 CloudFormation 堆栈redshift-stack的 Outputs 选项卡中找到 bucket 名称。接下来,用 ClusterPermissionsRole 的 ARN (Amazon 资源名称)替换占位符cluster_permissions_role_arn。ARN 的格式如下,arn:aws:iam::your-account-id:role/ClusterPermissionsRole。ARN 可以在云生成堆栈redshift-stack的输出选项卡中找到。

使用 Redshift 查询编辑器或您选择的 SQL 客户端,执行 SQL 语句将样本数据从 S3 复制到 Redshift dev数据库中的每个相应表中。TRUNCATE命令保证表格中没有以前的样本数据。

数据库视图

接下来,创建四个红移数据库视图。这些视图可能用于分析 Redshift 中的数据,以及稍后在 Amazon QuickSight 中的数据。

  1. sensor_msg_detail :使用 SQL 连接中的sensors事实表和所有五个维度表,返回聚合的传感器详细信息。
  2. sensor_msg_count :返回每个传感器红移收到的消息数。
  3. sensor_avg_temp :根据从每个传感器收到的所有信息,返回每个传感器的平均温度。
  4. sensor _ avg _ temp _ current:视图与前一视图相同,但仅限于最近 30 分钟。

使用红移查询编辑器或您选择的 SQL 客户端,执行以下一系列 SQL 语句。

此时,在 Redshift 中的dev数据库的sensor模式中,您应该总共有六个表和四个视图。

测试系统

有了所有必需的 AWS 资源和创建的红移数据库对象以及红移数据库中的样本数据,我们就可以测试系统了。包含的 Python 脚本kine sis _ put _ test _ msg . py将生成一条测试消息,并将其发送到 Kinesis Data Firehose。如果一切正常,这条消息应该会从 Kinesis Data Firehose 传送到 S3,然后复制到 Redshift,并出现在message表中。

安装所需的 Python 包,然后执行 Python 脚本。

运行下面的 SQL 查询,确认记录在数据库devmessage表中。至少需要一分钟消息才会出现在红移中。

一旦确认消息出现在message表中,通过截断该表删除记录。

流式数据

假设测试消息有效,我们可以继续模拟流式物联网传感器数据。包含的 Python 脚本,kinesis _ put _ streaming _ data . py,创建六个并发线程,代表六个温度传感器。

模拟数据使用一种算法,该算法遵循振荡的正弦波或正弦曲线,代表上升和下降的温度。在脚本中,我已经将每个线程配置为以任意偏移量开始,以给模拟数据添加一些随机性。

可以调整脚本中的变量,以缩短或延长传输模拟数据所需的时间。默认情况下,六个线程中的每一个都会为每个传感器创建 400 条消息,增量为一分钟。包括每个进行线程的偏移开始,脚本的总运行时间约为 7.5 小时,以生成 2,400 个模拟物联网传感器温度读数并推送到 Kinesis 数据消防软管。确保您能够保证在脚本的整个运行时间内保持与互联网和 AWS 的连接。我通常从一个小的 Amazon EC2 实例中在后台运行这个脚本。

要使用 Python 脚本,请执行以下两个命令之一。使用第一个命令将在前台运行脚本。使用第二个命令将在后台运行脚本。

查看output.log文件,您应该看到在每个线程上生成的消息被发送到 Kinesis Data Firehose。每条消息都包含传感器的 GUID、时间戳和温度读数。

这些信息被发送到 Kinesis Data Firehose,后者再将信息写入 S3。这些消息是使用 GZIP 压缩以 JSON 格式编写的。下面,我们看到一个 S3 GZIP 压缩 JSON 文件的例子。JSON 文件按年、月、日和小时进行分区。

确认数据流向红移

从 Amazon Kinesis Firehose 控制台的 Metrics 选项卡,您应该可以看到传入的消息流向 S3 和 Redshift。

执行下面的 SQL 查询应该会显示越来越多的消息。

有多接近实时?

之前,我们看到了亚马逊 Kinesis Data Firehose 交付流是如何配置为以 1 MB 或 60 秒的速率缓冲数据的。每当传入消息的缓冲区大于 1 MB 或时间超过 60 秒时,消息就会被写入 S3。message表中的每条记录都有两个时间戳。第一个时间戳 ts 是记录温度读数的时间。第二个时间戳是使用COPY命令将消息写入 Redshift 时创建的。我们可以在 Redshift 中使用以下 SQL 查询来计算两个时间戳之间的差值(以秒为单位)。

使用红移查询的结果,我们可以在 Amazon QuickSight 中可视化结果。在我自己的测试中,我们看到在大约 7.5 小时内,对于 2,400 条消息,最小延迟是 1 秒,最大延迟是 64 秒。因此,在这种情况下,接近实时的时间大约为一分钟或更短,平均延迟大约为 30 秒。

用红移分析数据

我建议至少等待 30 分钟,让大量消息复制到 Redshift 中。随着数据流进入 Redshift,执行我们之前创建的每个数据库视图。在 Redshift 中,您应该看到流消息数据与现有的静态数据相结合。随着数据继续流入 Redshift,视图将根据当前的message表内容显示不同的结果。

在这里,我们看到了sensor_msg_detail视图的前十个结果。

接下来,我们看看sensor_avg_temp视图的结果。

亚马逊 QuickSight

在最近的一篇文章中,开始使用 AWS Glue、Amazon Athena 和 QuickSight 在 AWS 上进行数据分析:第 2 部分,我详细介绍了 Amazon QuickSight 的入门。在这篇文章中,我假设你熟悉 QuickSight。

亚马逊最近增加了全套aws quicksightAPI,用于与 QuickSight 交互。不过,在演示的这一部分,我们将直接在亚马逊 QuickSight 控制台中工作,而不是在 AWS CLI、AWS CDK 或 CloudFormation 中工作。

红移数据集

为了可视化来自 Amazon Redshift 的数据,我们首先在 QuickSight 中创建数据集。QuickSight 支持大量数据源用于创建数据集。我们将使用红移数据源。如果您还记得,我们为 QuickSight 添加了一个入站规则,允许我们连接到 us-east-1 中的红移星团。

我们将选择sensor模式,这是本演示的表和视图所在的位置。

我们可以在 Redshift dev数据库中选择任何想要用于可视化的表或视图。

下面,我们将看到两个新数据集的示例,显示在 QuickSight 数据准备控制台中。请注意 QuickSight 如何自动识别字段类型,包括日期、纬度和经度。

形象化

使用数据集,QuickSight 允许我们创建大量丰富的可视化效果。下面,我们看到来自六个温度传感器的模拟时间序列数据。

接下来,我们看一个 QuickSight 显示地理空间数据能力的例子。该图显示了每个传感器的位置以及该传感器记录的平均温度。

清理

要删除为此帖子创建的资源,请使用以下一系列 AWS CLI 命令。

结论

在这篇简短的帖子中,我们了解了如何使用 Amazon Kinesis Data Firehose 在 Amazon Redshift 中近乎实时地分析流数据。此外,我们还探索了如何在 Amazon QuickSight 中可视化这些分析的结果。对于依赖数据仓库进行数据分析但也有流数据源的客户来说,使用 Amazon Kinesis Data Firehose 或 Amazon Redshift Spectrum 是一个很好的选择。

本博客代表我自己的观点,不代表我的雇主亚马逊网络服务公司的观点。

如何用亚马逊 Kinesis Firehose 将实时数据流式传输到雪花中

原文:https://towardsdatascience.com/streaming-real-time-data-into-snowflake-with-amazon-kinesis-firehose-74af6fe4409?source=collection_archive---------10-----------------------

若昂·布兰科在 Unsplash 上的照片

如今,企业可以从各种数据源不断产生的大规模、高速度数据中实时获益。无论是来自网站的点击流数据、来自物联网设备的遥测数据还是来自应用程序的日志数据,持续分析这些数据可以帮助企业了解他们的客户、应用程序和产品目前正在做什么,并迅速做出反应。

在本文中,我们希望探索如何使用 Amazon Kinesis Firehose 在雪花数据仓库中实时提供新数据,而不是在长时间间隔内使用传统的批处理。其动机是帮助企业了解如何为强大的实时应用和分析用例奠定基础。

对于那些可能不熟悉这些技术的人,我们将提供一个非常快速的总结,但我们这篇文章的主要重点是演示如何编写一个简单的应用程序来发送数据到雪花。在这次演示中,我们将使用 Twitter API 来传输实时推文。

雪花云数据仓库

雪花是一个云原生的、完全关系的 ANSI SQL 数据仓库服务,在 AWS 和 Azure 中都可用。它提供了一种基于消费的使用模式,具有无限的可扩展性。它能够加载结构化和半结构化数据,如 JSON、Avro 或 XML。

亚马逊 Kinesis 消防软管

亚马逊 Kinesis Firehose 是将流数据加载到 AWS 的最简单方法。它可以捕捉、转换流数据并将其加载到亚马逊 Kinesis Analytics、AWS S3、AWS Redshift 和 AWS Elasticsearch 服务中。这是一项完全托管的服务,可自动扩展以匹配您的数据吞吐量。它还可以在加载数据之前对数据进行批处理、压缩和加密。

我们的场景

推文持续发布在 Twitter 上,因此它是我们用作实时流的一个很好的来源。在这个例子中,我们将使用 Twitter 的流媒体 API 从 Twitter 获取新发布的推文。要做到这一点,我们必须创建一个到 Twitter API 的持久连接,并增量读取每个连接,然后快速处理每个 tweet,这样我们的程序就不会出现备份。

我们将构建一个简单的 python 程序来调用 Tweets。在此之前,您必须设置您的 Twitter 开发者帐户并创建一个应用程序。首先去 Twitter 开发者中心创建一个开发者账户。然后转到应用控制台并创建一个新的 Twitter 应用。这将让您获得应用程序连接到 API 的特定凭证。

接下来,让我们编写一个简单的应用程序,用持久会话调用 Twitter API。流式 API 不同于 REST API,因为它将消息推送到持久会话,而 REST API 用于提取数据。这允许流式 API 在数据可用时实时推送数据。

为了设置我们的应用程序,我们将安装一个名为 Tweepy 的 python 库。

pip install tweepy

然后,我们像这样设置对 API 的调用:

要使用 Twitter 验证您的应用,请使用您的应用凭据选项卡中的信息替换上面的凭据信息。为了设置我们的流,我们首先配置一个监听器类,它告诉我们应该如何处理数据。目前,侦听器只是打印数据。我们稍后将替换这部分逻辑,以便将数据发送到我们的 AWS Kinesis Firehose。track 变量是 Twitter 将返回相关推文的关键字列表。对于这个例子,我使用了“篮球”作为关键字。

设置 Kinesis 消防软管和 AWS S3

API 返回我们希望流式传输并存储在临时区域中的消息。通常情况下,雪花从 S3 加载数据,所以我们会将我们的消息作为文件存储在 S3,供雪花摄取。

在你设置 Kinesis 消防水管和 S3 水桶之前,你需要一个有权限创建 S3 和 Kinesis 资源的用户。请确保还创建了 aws 访问密钥和 aws 秘密密钥,用于编程访问,因为我们稍后会用到它们。

设置消防水管服务

  1. 转到亚马逊 Kinesis 控制台,创建一个交付流。选择一个流名称,并选择“直接上传或其他来源”作为您的来源。这将允许我们通过 API 调用将记录直接发送到我们的 Kinesis 流。为了简单起见,我们不会在本演示中设置任何数据转换。单击下一步,直到到达目标部分。
  2. 选择 S3 作为您的目的地,然后单击创建一个新的存储桶,并为您的存储桶选择一个唯一的名称。
  3. 接下来,我们将选择缓冲区大小和缓冲区间隔。Kinesis 缓冲输入数据流,直到达到缓冲区大小或缓冲区间隔。在本演示中,我们将积极地将两者分别设置为最小 1 MB 和 60 秒。
  4. 在本次演示中,我们不会设置数据压缩或加密。对于 IAM 角色部分,保留默认选择,允许 AWS 创建具有必要权限的 IAM 角色。这个角色将允许 Kinesis 与 S3 交流。
  5. 最后,检查您的设置并创建您的交付流。

修改 python 应用程序

现在我们的 AWS 服务已经设置好了,我们可以在 python 应用程序中修改 listener 类,这样每个新消息不仅可以打印到标准输出,还可以发送到我们的 Kinesis 交付流。我们可以使用 AWS 的 Boto3 库向我们的流发送数据。

pip install boto3

我们是这样做的:

要使用 AWS 对您的客户端进行身份验证,请在 credentials 变量中替换您的凭据。在这里,我们简单地设置一个函数,在设置资源的区域使用 Boto3 创建 Kinesis 客户端,并调用 put_record 函数将数据写入我们的交付流名称。我们还将数据的字符串数据类型转换为字节。为了将每条消息写入传递流,我们可以从侦听器类中调用我们的函数,以便在新消息到达时将它们传递给我们的函数。

现在,您可以运行您的 python 脚本,并在 Twitter 将消息推送到您的 standard out 时查看新消息。还要监控您的 S3 时段以查看传入的数据。当我们的交付流中的每个缓冲区都完成时,它将使用新的微批处理向 S3 写入一个新文件。

设置雪花

现在,我们有了实时进入 S3 的数据,我们可以设置我们的雪花数据仓库来接收可用的数据。通常,将数据加载到雪花中时,首选方法是将大量数据收集到 S3 存储桶中,并通过复制命令从外部阶段加载。然而,为了持续加载数据,雪花建立了一个名为 Snowpipe 的数据摄取服务。Snowpipe 在外部阶段一有可用的新数据,就以微批处理的方式加载新数据。

要设置我们的雪花资源,首先登录到您的雪花 Web UI 并切换到工作表标签。

对于此演示,我们需要以下雪花资源;一个用于执行 SQL 查询的计算资源的仓库,一个存储我们的 tweets 的数据库,一个将数据加载到 Snowflake 的外部阶段和一个持续加载数据的管道。

执行以下 SQL 来配置这些资源

  1. 创建仓库

2.创建数据库和表

我们使用 variant 数据类型,因为我们接收的数据是半结构化的。

3.接下来,我们为 S3 存储桶创建一个外部阶段

4.创建从外部阶段复制到 tweets 表的管道

现在我们差不多完成了。我们的管道将从它为我们创建的 AWS 队列中读取数据。我们需要将这个队列连接到我们的 S3 存储桶,以便每当一个新文件被添加到 S3 存储桶时,存储桶将把它推到队列中,然后由我们的管道读取。这就是管道如何知道文件可以被实时接收的原因。

要为队列配置 S3 存储桶,我们需要队列的 AWS 资源 Id。运行以下 SQL:

show pipes

在结果中,为您创建的管道检查名为 notification channel 的列,并复制资源 ID。

回到 AWS,转到 S3,点击你的桶进行演示,切换到属性,进入高级设置。然后点击事件并添加新事件。

为您的活动命名。并选择“所有对象创建事件”。选择“发送到 SQS 队列”,并在“SQS 队列 ARN”字段中添加您的资源 ID。然后保存您的活动。

现在你完成了。运行 python 脚本,并在 S3 存储桶接收新文件时对其进行监控。这些文件现在将作为我们创建的雪花表中的新行被接收。通过运行 SQL select 查询进行确认。

select count(*) from twitter_stream.public.tweets;

每隔几分钟运行一次查询,您会注意到表中的行数在增加。这意味着设置工作正常。你可以实时从 Twitter 直接接收数据到 Snowflake。

运行下面的查询来查看进入雪花的每个新批次的时间窗口。

就这样…

一旦数据进入您的数据仓库,就会有许多强大的用例,但是这些讨论超出了本文的范围。我们向您展示了一个非常简单的设置,让您更好地理解将数据实时发送到您的仓库所涉及的服务。

除了亚马逊 Kinesis,还有其他流处理平台,如 Apache Kafka。每种方法都有其优缺点,这取决于您想要构建的解决方案。此外,大多数使用情形都有更复杂的要求,例如在设计解决方案时需要考虑多个数据源、延迟规格和不断变化的数据量。

如果您有实时分析用例,请通过 Waterfront Analytics 联系我们,我们可以帮助您确保您的用例获得高价值的业务成果。

简化设计,最大限度地提高测试和学习的成功率

原文:https://towardsdatascience.com/streamlining-design-and-maximizing-success-for-agile-test-and-learn-443156d9b2f1?source=collection_archive---------39-----------------------

如何使用 R 一次性权衡所有的 A/B 测试设计选项

克里斯蒂娜@ wocintechchat.com 在 Unsplash 上的照片

测试设计繁琐

测试和学习分析作为一种定量了解零售商客户群偏好的方法,在整个行业广泛使用。成功的测试需要准确的假设(响应率、变量之间的预期差异)以及微调的执行参数(受众规模、测试/控制划分、测试迭代和时间)。

可以说,测试设计阶段是最关键的,需要营销策略师、统计学家、数据分析师和运营专家之间的及时合作,以就成功执行的正确参数达成一致。本文详细介绍了一种易于实现的方法来加速这个设计阶段,并使所有关键利益相关者保持一致。在本帖中,我们将介绍:

1.计算测试功效和效果大小的函数

2.可视化展示所有可能的设计选项

这种方法提高了任意数量场景中效果大小计算的速度和简易性,允许营销策略师快速排除注定失败的测试设计,并专注于正确的参数,以最大化成功测试的机会。

背景

从形式上讲,A/B 测试用于比较一个变量的两个或多个版本。最近与一家大型零售商的合作让我们的团队采用 A/B 测试来比较不同电子邮件活动在吸引现有客户回店方面的有效性。我们的目标是让每个活动尽可能个性化,以满足目标受众的需求(并一如既往地快速执行)。例如,我们可能希望锁定在过去 3 个月内购买了第一套西装的 20-30 岁男性,并将定制服务的报价与正装鞋的折扣进行比较。我们需要尽快将这个测试投入市场,因为假期很快就要到了,一旦这个测试完成,我们就会有更多的测试想法。

当营销策略师构思创意内容时,数据科学家的目标是评估提议的测试是否有很好的机会在 A 和 b 之间产生可检测的差异。如果设计不可能产生结果,整个团队需要迅速转向不同的设计,评估将重新开始。

问题

许多因素使得设计阶段成为数据科学家的一项复杂任务:

1 每个测试都是为表现出非常特殊行为的顾客设计的,所以我们总是被 s mall 观众数量所束缚

2 在高度个性化的测试中,基于独特的客户群,基线响应率 存在 大的可变性

3 测试通常会带来额外的实施成本(例如促销),这意味着我们需要正确的 测试和控制组拆分

4 敏捷框架被设计为每周启动多个测试,这意味着 有限的设计时间

现在,在给定特定的输入值(例如:https://www.evanmiller.org/ab-testing/sample-size.html)的情况下,许多很棒的资源可用于确定所需的观众规模或效果规模。然而,将 30 种输入组合输入到这些计算器中并比较结果是非常麻烦的(高管们也不想在电话会议上看着你插上插头就喝)。

解决办法

为了使设计阶段对每个人来说都更容易,我们想出了一个流程来查看在任意数量的输入场景 下,我们需要自信地确认或拒绝一个测试假设

设置参数

我们评估潜在设计所需的主要输入很简单:

1。受众规模:符合测试条件的客户(例如,刚买了一套西装的 20-30 岁男性)

2。试验比例:试验组和对照组之间的划分(试验组接收 A 内容,对照组接收 B 内容)

3。基线回应:历史回应率(例如,客户购买的典型比率)以 0 到 1 之间的概率来衡量

我们的测试设计评估应该量化 A 和 B 之间的差异,以便确认或拒绝我们的测试假设,即一个版本比另一个版本更好。

执行

让我们继续西装的例子。我们希望在我们的商店推广一项新的定制服务,因此我们定义了我们的假设,即服务的 15%折扣促销会比纯粹的信息性电子邮件推广服务吸引更多的客户使用定制服务。测试组将获得 15%的优惠促销,而控制组将收到一封标准的电子邮件,通知他们如何裁剪。

定义输入

受众规模:我们理想的目标受众是 10,000 名顾客,他们在过去的一年里只购买了一套西装。如果需要,我们可以放宽标准,将去年购买西装和鞋子的额外 10,000 名顾客包括在内,或者甚至将购买了正装衬衫但没有购买西装的额外 55,000 名顾客包括在内。因此,对于我们的评估,我们将着眼于从 10k 到 75k 的受众规模。

测试比例:测试活动包括 15%的促销活动,这降低了利润率,因此我们倾向于不平衡测试,以尽可能减少接收测试促销内容的客户数量。在我们的评估中,我们将考察各种比例:10/90、20/80、30/70、40/60 和 50/50。

基线回应:最后,我们知道现有购物者使用类似服务的总体基线回应率为 12%。虽然我们知道促销通常会将回复率提高 1-3 个百分点,但我们希望在这个测试中保持保守,因为定制服务是一项新服务,所以我们将这个常数保持在 12%。

定义功能

效应大小计算:由于我们的测试是比较两个概率(我们的响应变量将在 0 和 1 之间),我们需要使用两个比例的测试设计。我们使用科恩的 h 公式计算影响大小,因为我们正在比较两个比例之间的差异(https://en.wikipedia.org/wiki/Cohen%27s_h)。因为我们的测试/控制分割可能不是 50/50,所以我们的测试被认为是不平衡的。请注意,我们使用 80%的功率。因为发送一封电子邮件的成本可以忽略不计,我们可以承受比标准的 90%或 95%阈值更大的误差空间。

科恩的 h 衡量两个概率之间的距离

应用于给定概率(p)的反正弦变换

第一个函数使用 R 中的 pwr 包来计算检验我们的假设所需的效应大小。第二个函数求解确认或拒绝我们的假设所需的测试响应率的效应大小公式。

【效应大小公式:h = 2 * asin(sqrt(p2))-2 * asin(sqrt(P1))
求解测试响应率(p2)给出:sin((h + 2*asin(sqrt(p1)))/2)】

注意:这种方法适应了观众规模、测试比例和基线反应率的主要效应规模参数的可变性,并且是为两个比例的不平衡测试而建立的。其他测试类型,如连续结果的比较,在这里没有探讨,但可以容纳在同一框架内。

设置输入参数

现在我们设置输入参数并应用函数。根据测试设计选项调整这些参数。

audience_size <- c(10000,20000,75000)
test_proportion <- c(0.1,0.2,0.3,0.4,0.5)
baseline_rate = c(0.12)

使用所有可能的测试设计创建一个数据集,并将效果大小计算应用于数据集的每一行

电梯需要证明不同。显示每个可能的测试设计输入。

现在我们有了一个清晰的表格,显示了测试受众规模(test_n),以及确认或拒绝假设所需的基线响应率的百分比提升(lift_needed)。从技术上来说,这是我们需要的所有信息,但是没有人喜欢阅读一个无聊的旧表格…

为所有可能的设计创造一个互动的情节

使用 ggplotplotly 可视化软件包,我们可以创建一个具有交互性的所有测试选项的图示,让我们悬停在不同的选项上以查看所有相关的细节。

结果

看着由此产生的情节,我们可以很快看到每个设计方案的利弊。利用这 10,000 名只买西装的顾客,我们的活动将需要以 50/50 的测试和控制比例推动至少 9%的增长。鉴于我们对过去活动的了解,这种类型的提升是不太可能的,而且由于促销优惠,我们宁愿将测试接受者限制在 50%以下的观众。因此,我们可能会建议放宽受众标准,以包括额外的 65,000 名西装+鞋子和礼服衬衫购物者,从而达到 75,000 名受众,测试和控制比例为 20/80,我们需要更合理的 5%提升来确认或拒绝假设。

让我们走远一点

我们刚刚看了一个使用基于三组初始标准的特定受众规模的示例。但是,如果我们更进一步,看看在广泛的观众规模和不同的基线率下,所需的提升是如何变化的呢?我们可以调整输入并观察。注:在本练习中,我们将保持测试比例恒定在 50/50。

解释

正如所料,基线速率越小,你需要看到的提升量就越高,才能发现差异。营销策略师感兴趣的是受众规模和提升需求之间的非线性关系。在设计针对小规模受众的极其个性化的活动时,考虑这种关系非常重要。例如,基线响应率为 10%,受众为 1,000 名客户,您需要看到至少 34%的提升才能证实您的假设。但是,增加 5,000 名客户会将需要的提升降低到 13%。在同样的 10%基线和 20,000 名客户的情况下,您将需要 7%的提升,而额外 5,000 名客户的好处是 0.7 个百分点的相对较小的差异。

结论

本文展示了一种用于 A/B 测试设计的方法,该方法可以在任意数量的设计场景中加速样本和效应大小的计算,并提供了所有可能设计的交互式可视化。这种方法大大提高了我们的测试和学习团队的速度,可以排除注定失败的测试设计并专注于正确的参数以最大化成功测试的机会

密码

使用 R 3.5.3 生成

用特征引擎简化特征工程管道

原文:https://towardsdatascience.com/streamlining-feature-engineering-pipelines-with-feature-engine-e781d551f470?source=collection_archive---------25-----------------------

入门

找出在开发用于部署的机器学习管道时遇到的挑战,并了解开源软件如何提供帮助。

简化特征工程管道—图片来自 Pixabay,无需注明出处

在许多组织中,我们创建机器学习模型来处理一组输入变量,以输出预测。例如,这些模型中的一些预测贷款偿还的可能性、申请欺诈的可能性、汽车在事故后是否应该修理或更换、客户是否会流失等等。

由组织收集和存储的原始数据几乎从不适合于训练新的机器学习模型,或者被现有模型消费来产生预测。相反,在变量可以被机器学习算法利用之前,我们执行大量的转换。变量转换的集合通常被称为特征工程。

在本文中,我们将描述在构建和部署特征工程和机器学习管道时遇到的最常见的挑战,以及如何利用开源软件和名为特征引擎的新 Python 库来帮助缓解这些挑战。

什么是特征工程?

特征工程是使用数据的领域知识来创建使机器学习算法工作的特征的过程。原始数据中有几个方面需要解决。例如,数据经常丢失,或者变量值采用字符串而不是数字的形式。许多机器学习库,如 Scikit-learn,无法处理丢失的值或字符串,因此我们需要将它们转换成数值。此外,当变量显示某些特征时,如正态分布或类似的尺度,一些模型往往会工作得更好。因此,我们试图转换变量,使它们具有这些特征。

特征工程包括处理所有这些方面的数据转换程序,包括缺失数据的插补、分类变量的编码、数值变量的转换或离散化,以及在相似尺度中设置特征。此外,特征工程还涉及通过将现有特征组合成新变量,或通过从日期中提取信息,汇总交易数据,或从时间序列、文本甚至图像中导出特征来创建特征。

总之,特征工程包括数据转换和新数据创建的每个方面,以返回适合训练并被机器学习模型使用的数据集。我在别处广泛描述了不同的特征工程技术。更多细节和代码实现可以在课程“机器学习的特征工程”和书籍“ Python 特征工程食谱”中找到。

特征工程是重复且耗时的

根据福布斯的调查,数据科学家和机器学习工程师花费大约 60% 的时间清理和组织数据以供分析和机器学习,或者换句话说,用于数据转换和特征工程

特征工程可能非常重复,数据科学家倾向于对各种数据源执行相同类型的转换,这些数据源将用于创建不同的机器学习模型。大多数数据源都显示出相同的挑战:缺乏信息或缺失数据,变量以字符串而不是数字的形式存在,分布对于我们打算建立的机器学习模型的性能不是最佳的,或者不同的规模。因此,我们发现自己一遍又一遍地做着相同类型的数据转换,一个模型接一个模型。如果我们每次都这样做,我们从头开始编码,整个过程会变得非常低效。

我们应该努力减少重复和重复代码,优化可靠性,以提高性能和效率,同时减少数据科学家在数据处理上花费的时间。如果数据科学家花更少的时间清理和预处理数据,他们将能够花更多的时间来创建创新的解决方案,应对更有趣的挑战,并在其他领域进行学习和发展。

团队工作时的特色工程

特征工程是非常重复的,我们倾向于对几个数据源进行相同的转换。每次从头开始编码这些转换,或者将代码从一个笔记本复制粘贴到另一个笔记本是非常低效和糟糕的做法。

在这样的场景中,团队工作带来了额外的复杂性,我们可能会在研究和生产环境中以相同技术的不同代码实现而告终,每个代码实现都是由不同的团队成员开发的。这不仅效率低下,而且很难跟踪团队中做了什么。我们最终得到相同代码的多个来源或版本,几乎没有任何代码标准化、版本化和测试。

通常最好创建或使用可以在团队中共享的工具。公共工具有几个优点:首先,我们不需要在每个项目中从头开始重写我们的管道,而且,它们促进了知识共享。当所有成员都可以阅读和使用现有的图书馆时,他们可以互相学习,更快地发展自己和同事的技能。

同样值得考虑的是,随着数据科学家研究和开发机器学习模型,代码测试和单元测试经常被忽略或遗忘。在 Jupyter 笔记本中经常使用的程序编程期间,从以前的命令中获得的输入往往会一遍又一遍地重新设计和重新分配,然后用于训练机器学习模型。这个过程使得很难跟踪转换和代码依赖,这本身就可能包含错误,从而导致错误传播和调试困难。

功能工程的特别流程不可复制

再现性是精确复制机器学习模型的能力,使得给定相同的原始数据作为输入,两个模型返回相同的输出。这是我们在研究环境中开发的模型和在生产环境中部署的模型之间的最终目标。

重构在研究环境中开发的特征工程管道以在生产环境中添加单元测试和集成测试是非常耗时的,这提供了引入错误或发现在模型开发期间引入的错误的新机会。更重要的是,重构代码达到相同的结果,但由不同的开发人员编写,是非常低效的。最终,我们希望在我们的研究和生产环境中使用相同的代码,以最小化部署时间并最大化可重复性。

面向特征工程的开源库的激增

在过去几年中,越来越多的开源 Python 库开始支持作为机器学习管道一部分的特征工程。其中,库 Featuretools 支持一系列详尽的函数来处理事务数据和时间序列;库分类编码器支持对分类变量编码方法的全面选择;库 Scikit-learn特征引擎支持广泛的转换,包括插补、分类编码、离散化和数学转换等。

开源项目简化了机器学习管道的开发

使用开源软件,帮助数据科学家减少他们在功能转换上花费的时间,提高团队之间的代码共享标准,并允许使用版本化和测试良好的代码,最大限度地缩短部署时间,同时最大限度地提高可重复性。换句话说,开源允许我们在研究和开发环境中使用相同的代码,有清晰的版本,因此消除或最小化了需要重构才能投入生产的代码量。

为什么使用成熟的开源项目更有效?出于多种原因,第一个开源项目往往会被完整地文档化,所以每段代码想要达到的目的是很清楚的。第二,完善的项目已经被社区广泛采用和批准,这让我们放心,代码是高质量的,并且将在未来几年得到维护和改进。第三,开源包经过了广泛的测试,以防止引入错误并最大化可再现性。第四,包有明确的版本,所以我们可以导航到更现代的,或者以前的代码实现,以获得想要的结果。第五,开源包可以共享,促进知识的采用和传播。最后,利用开源包消除了我们手中的编码任务,极大地提高了团队绩效、可重复性和协作性。

关于我们为什么应该使用开源的广泛讨论可以在本文中找到。

特征引擎有助于简化我们的特征工程流程

Feature-engine 是一个开源 Python 库,我创建它是为了简化和精简端到端功能工程管道的实现。Feature-engine 最初是为机器学习的课程Feature Engineering而设计的,但现在已经被社区采用,并且有越来越多的贡献者加入到代码库中。

Feature-engine 保留了 Scikit-learn 功能,使用 fit()和 transform()方法从数据中学习参数,然后转换数据。请记住,许多特征工程技术需要从数据中学习参数,如统计值或编码映射,以转换数据。Scikit-learn like 功能与 fit 和 transform 方法使特征引擎易于使用。

特征引擎包括多个转换器,用于估算缺失数据、编码分类变量、离散化或转换数值变量以及移除异常值,从而提供最详尽的特征工程转换组合

特征引擎转换器的一些关键特征是:I)它允许选择变量子集直接在转换器上进行转换,ii)它接收数据帧并返回数据帧,促进数据探索和模型部署,iii)它自动识别数字和分类变量,从而对正确的特征子集应用正确的预处理。

功能引擎转换器可以在 Scikit-learn 管道中组装,从而可以将整个机器学习管道存储到单个对象中,该对象可以在稍后阶段保存和检索以进行批量评分,或者放置在内存中以进行实时评分。

Feature-engine 正在积极开发中,欢迎用户的反馈和社区的贡献。关于如何使用功能引擎的更多细节可以在它的文档和本文中找到:

[## Feature-engine:一个新的用于特征工程的开源 Python 包

Feature-engine 是一个开源 Python 库,提供了最全面的转换器来设计特性…

trainindata.medium.com](https://trainindata.medium.com/feature-engine-a-new-open-source-python-package-for-feature-engineering-29a0ab88ea7c)

参考资料和进一步阅读

Streamlit 还不能取代 Flask

原文:https://towardsdatascience.com/streamlit-can-not-yet-replace-flask-the-streamlit-2020-roadmap-64840564acde?source=collection_archive---------12-----------------------

Streamlit 2020 路线图

我讨论了 Streamlit 的发展方向以及 Flask目前的优势。 Streamlit 1.0 于 2019 年 10 月公布。烧瓶发布于 2010 年 4 月 1 日。对于五年后的机器学习生产部署, Streamlit 会比 Flask 更好吗?

仪表板示例;资料来源:联合国人类住区规划署

介绍 Streamlit

Streamlit 是一个为机器学习科学家或工程师创建基于 Web 的前端的工具。具体来说, Streamlit 使用 HTMLCSSJavascript 但不需要开发者知道 HTMLCSSJavascript

Streamlit 团队正在使机器学习科学家能够在不使用 Flask、Django、或其他工具的情况下进行部署。

来自https://www . streamlit . io

“Streamlit 是一个面向机器学习和数据科学团队的开源应用框架……全部免费。

Streamlit 是一个开源但封闭的框架,因为:

  1. 机器学习科学家的目标是快速推出基于 Python- 的 Web GUI 前端(仪表板)。
  2. Streamlit 为第三方插件提供了一个框架,这是未来 Streamlit 版本的次要考虑因素。

在这篇文章中,我讨论了 Streamlit 的路线图,它似乎将走向何方,并将其与现在的 Streamlit和 Streamlit进行比较。

引入烧瓶

当建立网站时,你应该有一个健壮的框架来处理所有类型的功能。在 Python Web 前端软件工程师中最流行的微服务框架之一是 Flask

扩展、工具、插件

烧瓶发布于 2010 年 4 月 1 日。它开始是围绕 WerkzeugJinja 的包装。

Flask foundation 是一个插件架构。大多数插件都是大型 Python 包。我们的开发人员使用超过七个烧瓶扩展。例子包括 BootstrapSQLAlchemyFlask8 等等。

我发现 Flask 是一个健壮的框架。所有的扩展使它更加强大。更重要的是,它通过提供适合您的包扩展来适应您的编程风格。

来自https://palletsprojects.com/p/flask/

“由开发人员来选择他们想要使用的工具和库。社区提供了许多扩展,使得添加新功能变得容易”。

Streamlit 是一个封闭框架目前,任何定制功能的唯一解决方案都是克隆Streamlit****Githubrepo 并放入您的定制更改。

蒸汽点燃的路线图承诺了什么:

来自https://discuse . streamlit . io/t/the-streamlit-roadmap-big-plans-for-2020/2054

“Streamlit 插件系统将让你能够编写任意 React 或 Javascript 代码,并将其插入到你的应用程序中。”

用于 Streamlit 的插件架构正处于社区讨论阶段。

网络安全

在前一篇帖子中,我写道:

我们还没有遇到一个基于 ML 或 DL 的 Flask 的微服务不能被重构为Streamlit服务。

我能说什么呢?那是早期。我们为在 ML 应用程序中部署漂亮的交互式 Web GUI 前端而感到兴奋。我们成了上层管理的典型代表。然后,他们展示了一个基于 Streamlit 的客户端,这个客户端在我们的防火墙之外并且想要它。

好吧…?没问题。我们问 Web 应用人员( WA-dev)什么是好的解决方案?他们告诉我们,如果用 烧瓶 ,我们有很多选择

我们决定为Streamlit开发一个(小型)安全登录插件。****

Streamlit 开发的安全登录插件变成了一个兔子洞。三个版本之后,我们仍然没有获得通过验收测试 ( AC-Test )的安全登录。

我们被上层管理人员拉出了兔子洞,他们建议(命令)我们等待 团队 beta 的精简。

Streamlit for Teamsbeta 将免费(暂时?)并在几个月后上市。它承诺认证,我们希望这意味着安全登录。Streamlit 也承诺日志记录和自动缩放(不确定那是什么)。****

贮藏

在这一点上,未来的 Streamlit 版本不会帮助我们解决st.cache 生产问题。

来自https://discuse . streamlit . io/t/the-streamlit-roadmap-big-plans-for-2020/2054

接下来是对其他函数类型的高速缓存的更多改进,以及一些使高速缓存更加简单的魔法。

烧瓶也有缓存。 Web 应用程序开发 ( WP-dev )使用主烧瓶缓存werkzeug。他们告诉我还有其他 Flask 附件可以缓存。****

背景(不想看长毛狗的故事就跳过):

我们中的一些人喜欢在早上 6:00 到 6:30 之间早点来。我们注意到,大约在三月初,管理员启动了分析师的计算机。分析师在上午 8:00 到 8:30 之间到达为什么要采用这一新程序?**

我们问管理员— 为什么是?因为他们仪表板中的一个画面需要 30 到 45 分钟才能出现。分析师需要启动他们的计算机,所以当他们到达时,仪表板已经准备好了。

啊?为什么我们必须向管理员询问分析师仪表板的问题?首先,好消息。分析师非常喜欢这个新仪表板。现在,坏消息是。它没有被打破(在他们的思维模式中),分析师相信我们会把它拿走或者打破框架。(可能是我们偏执吧。他们实际上并没有这么说。)**

Dev 知道从现在起三个月后,当画框花费一个小时或更多时间时,它将是【不可接受】。从现在起的 9 到 12 个月内,这个框架将被正式打破。

我们是怎么知道的?

该框架对时间序列数据进行了深度学习训练和预测。列车数据集在清晨从测试数据集实际值更新。我们中的一个人精心编写了逻辑,只在周末训练。然而,st.cache导致训练发生在星期二到星期六的清晨,或者每当训练数据集更新时。****

有两种直接的补救措施:

  1. 训练数据集调整为三个月的每日数据(2000 万行)。它还没有三个月的数据,但在 4 月中旬之后,它将拥有超过三个月的数据。
  2. st.cache被注释掉了。

从长远来看,为了加快速度,我们正在考虑修剪神经网络和/或重写 Swift 中的部分。我们中的一个人正在看 cPython ,而首席技术官说,“云”(我说——“目前无可奉告。”).读者可能有任何想法,请告诉我。

(结束背景)

AC-Test 禁止在生产代码中使用st.cache。我们使用st.cache进行开发实验、调试和单元测试。我们认为st.cache是为研究员和卡格勒设计的。如果我们对st.cache.的理解有误,请告诉我**

在 Streamlit 应用程序之间传递状态

我们希望在 Streamlit 微服务(页面)之间传递状态数据。

Flask 没有这个问题,因为他们使用加密的 cookies 或者调用 URL 中的 args 来传递状态。

Streamlit 路线图称之为“可编程状态”:

现在,让一个 Streamlit 应用程序存储内部状态,比如用户在表单中输入的信息,简直太棘手了。..我们希望给你…可编程的状态,这样你就可以构建具有顺序逻辑的应用程序,具有多个页面的应用程序,不断要求用户输入的应用程序,等等。

我们等待未来版本的Streamlit在页面间传递状态。

美术馆

Streamlit 的 画廊展示了 Streamlit 用户创建的赏心悦目的仪表盘式应用程序(有些相当聪明)。注意:所有应用都是数据工程或者机器学习或者深度学习。毕竟,AI 2.0 Web GUI 开发者和他们的用户是目标市场。

如果你想展示你的应用,只需发推特给我们 @streamlit!

烧瓶有很多画廊。下面是一些包含了 Flask-Python 源代码的例子。

为 Streamlit 提供更多资源

不确定参考的是不是极致,但是顾名思义就是牛逼。

Awesome Streamlit 资源

**** [## Streamlit 101:深入介绍

利用 Airbnb 数据深入了解 Streamlit

towardsdatascience.com](/streamlit-101-an-in-depth-introduction-fc8aad9492f2)

牛逼图库

Flask 的更多资源

很好的参考:托盘项目

摘要

我们希望 Streamlit 的未来版本能够为我们提供以下功能:

  1. 安全登录;
  2. 在基于 Streamlit 的网页之间传递状态;
  3. 一个提供精简扩展、工具和插件的第三方生态系统。

最后一项不在简化 it 的路线图中,但在我们的简化 it 路线图中。

我收回我之前关于烧瓶的一些说法。

[## Streamlit 会导致 Flask 灭绝吗?

可能对于机器学习(ML)和深度学习(DL)来说。对于其他全栈应用,大概不会!

towardsdatascience.com](/part-2-will-streamlit-cause-the-extinction-of-flask-395d282296ed)

Flask 拥有我们现在生产部署一个 Web 微服务所需要的一切。细流

但是,我仍然坚持这个主张:

  1. 一个好的全栈烧瓶程序员有多年的经验。他们需要知道 JavascriptHTMLCSS 等..、和堆栈中不同的 POST/GET URL
  2. 黑客(就像机器学习科学家)只需要几周的经验就可以设计、开发和部署一个 Streamlit 生产就绪的基于网络的仪表板。

我们发现, Flask 是一个成熟的开放框架,拥有一个健壮的扩展生态系统。

Streamlit 目前是一个封闭的框架,我们依赖于它的未来版本。我们最大的希望是 Streamlit 成为一个具有插件架构解决方案的开放框架。****

Streamlit + Heroku = Magic?

原文:https://towardsdatascience.com/streamlit-heroku-magic-5e4a7192929a?source=collection_archive---------62-----------------------

照片由瑞德·卫斯理Unsplash

如何轻松地在 Heroku 上部署您的 streamlit 应用程序。

我不知道你怎么想,但在过去的几天里,我一直在玩 streamlit ,我不得不说我对它印象深刻。

它速度快,反应灵敏,易于掌握。但最棒的是,您可以编辑您的 python 脚本,并看到您的 streamlit 应用程序实时自动更新。在我看来,与 streamlit 一起工作是非常愉快的。

然而,一旦你构建了你的应用程序,你为什么不部署它,让全世界都能看到它呢?这是为您的数据科学或数据分析产品组合添加交互性的绝佳方式。

本教程将逐步介绍如何在 Heroku 上部署您的 streamlit 应用程序。

目录

  1. 第 1 部分:您需要哪些文件?
  2. 第 2 部分:通过 Heroku CLI(终端)使用 Heroku。
  3. 要避免的常见陷阱
  4. 第 3 部分:通过 Github 库使用 Heroku。

注意:我假设您已经安装了 streamlit,并且已经知道一点如何使用它。

第 1 部分:您需要哪些文件?

在 Heroku 上启动 streamlit 应用程序需要四个基本组件。

  1. setup.sh
  2. requirements.txt
  3. Procfile
  4. 你的应用程序

setup.sh —不需要凭据

注意:您不需要将这个文件命名为 setup.sh,它可以是任何名称,但是必须以。sh 文件扩展名。然而,将其命名为 setup.sh 似乎是一种规范。

requirements.txt

这个文件基本上列出了我们将在 streamlit 应用程序中使用的所有特定 python 插件。可能看起来是这样的。

newspaper3k==0.2.8
streamlit==0.61.0
nltk==3.4.5

在您的终端上简单使用 pip 冻结功能可能很有诱惑力。

pip freeze > requirements.txt 

然而,我发现当你上传你的申请到 heroku 时,有时会引起很多不必要的问题。

注意:我在我的基本环境中测试了这个 pip 冻结功能,因此一个 提示 将为您的新 streamlit 应用程序创建一个新的 python 环境,然后安装所需的 python 插件。

Procfile

注意:将该文件命名为 Procfile,不要在其后添加任何扩展名。这是一个标准的文本文件。

web: sh setup.sh && streamlit run your_application.py

你的应用程序

耗时的部分是构建您的 streamlit 应用程序,这是作为 python 脚本存储的。

对于本教程,我基于我在网上抓取文章上的上一篇文章制作了一个简单的 python 应用程序。

[## 网上搜集文章的简单方法

在我的朋友 newspaper3k 插件的一点帮助下,我们可以把来自不同新闻渠道的文章集合起来…

towardsdatascience.com](/the-easy-way-to-web-scrape-articles-online-d28947fc5979)

在我们继续之前,确保所有这些文件都在一个我们可以在终端中导航到的特定文件夹中。

第 2 部分:通过 Heroku CLI(终端)使用 Heroku。

我想你们知道如何注册一个 Heroku 账户。

注意:在我们开始在终端上使用 Heroku 之前,我建议导航到本教程第 1 部分的文件所在的文件夹。

第一步:通过你的终端登录 Heroku。

$ heroku login

您将被重定向到您可以登录的网页,或者如果您已经登录到您的 web 浏览器,它将自动登录到您创建的帐户。

步骤 2:创建一个新的 Heroku 实例

运行下面的代码将自动创建一个带有随机名称的全新 Heroku 应用程序。

$ heroku create

或者你可以给它起自己的名字…

$ heroku create name_of_heroku_instance

第三步:将你的文件推送到新的 Heroku 应用程序中。

$ git push heroku master

这一部分可能需要一点时间,因为 Heroku 应用程序正在设置并在服务器上安装所需的 python 插件。一旦完成,它应该输出这个消息:远程:验证部署…完成。

步骤 4:启动你的应用程序

$ heroku open

瞧,这就对了!如果你按照上面所有的步骤复制了所有的代码。您在 heroku 上的 streamlit 应用程序应该如下所示。

我的 Streamlit 应用程序是什么样子的。

要避免的常见陷阱

有时您可能会忘记已经在您正在处理的文件夹中创建了一个远程 heroku 应用程序。

要进行检查,请运行以下代码。

$ git remote -v

如果不同,请删除此远程连接。

$ git remote rm heroku

然后添加正确的 heroku 地址,您希望您的应用程序托管在这个地址上。

$ git remote add heroku (git.heroku.com/heroku_application.git)

第 3 部分:通过 Github 库使用 Heroku。

也许,你并不是真的想通过你的终端推送你的应用文件。另一种方法是通过 Github。但是,这需要通过您选择的 web 浏览器上的 Heroku 仪表板来完成。

步骤 1:通过仪表板创建一个新的应用程序

第二步:点击应用程序

步骤 3:单击部署选项卡

步骤 4:选择 Github 作为部署方法

第 5 步:搜索 GitHub 存储库,其中存储了第 1 部分中的文件。

步骤 6:连接到存储库。

步骤 7:在手动部署部分部署分支

在这里,您可以点击“查看”来查看您的应用程序。

我还建议在自动部署部分启用自动部署。这将自动从你的 GitHub 推送最新的主分支,只要它有新的版本更新。

这就是在 Heroku 上部署 streamlit 应用程序的两种方法。

Streamlit 是您所需要的一切

原文:https://towardsdatascience.com/streamlit-is-all-you-need-9202763c174?source=collection_archive---------36-----------------------

苹果 | 谷歌 | SPOTIFY | 其他

Adrien Treuille 和 Tim Conkling 在 TDS 播客

背景图片由詹姆斯·哈里森

编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:

YouTube | 音频

我们已经在播客上谈论了很多关于“全栈”数据科学的内容。对许多人来说,全押是我们永远无法实现的长期目标之一。有太多的算法、数据结构和编程语言需要了解,而没有足够的时间来找出围绕部署和构建应用前端的软件工程最佳实践。

幸运的是,新一波数据科学工具现在让没有软件工程背景的人能够快速轻松地构建数据应用,从而使全栈数据科学变得更加容易获得。可以说,没有一家公司比 Streamlit 在构建这种工具方面取得了如此巨大的成功,这就是为什么我想与 Streamlit 创始人 Adrien Treuille 和游戏化专家 Tim Conkling 坐下来谈谈他们的旅程,以及构建灵活的全栈数据科学应用程序的重要性。

以下是我在对话中最喜欢的一些观点:

  • Streamlit 面临的问题是从根本上减少与部署和应用程序构建相关的学习曲线。虽然 AWS、Flask、Heroku 或 Django 等工具在用于制作引人注目的东西之前需要一段时间才能掌握,但 Streamlit 通过痴迷地将入职流程游戏化,让其用户在几分钟内就能制作出真正的产品。
  • 构建全栈应用如此重要的原因之一是可访问性。大多数人不知道如何使用 Jupyter 笔记本(笔记本也是有状态的,所以更难确保你传递的笔记本会按照你想要的方式使用!).拥有一个人们可以使用的实时应用程序,而无需自己启动服务器或学习如何编码,这使得数据科学家更有可能分享见解,并说服关键决策者采取行动。
  • 减少与应用部署相关的开销非常重要,因为它允许您(数据科学家)更多地尝试算法和可视化,因为它不需要花费大量时间来重新部署系统和跟踪服务器端的错误。因此,即使您已经掌握了软件工程技能,抽象出数据科学问题的软件工程层的工具也可能会使您工作得更快,并提高工作产品的质量。

你也可以在 Twitter 上关注 Streamlit 这里,你也可以在 Twitter 上关注我这里

Streamlit 使用数据应用程序更好地测试您的模型

原文:https://towardsdatascience.com/streamlit-use-data-apps-to-better-test-your-model-4a14dad235f5?source=collection_archive---------49-----------------------

了解如何使用 Streamlit 制作快速数据应用程序来测试您的模型

https://www . Reddit . com/r/wallpaper/comments/8of B1 d/natural _ architectural _ bridge _ at _ night _ scene _ HD/

介绍

我们使用各种技术,从创建非常可靠的验证集到使用 k-fold 交叉验证或提出各种奇特的指标来确定我们的模型执行得有多好。然而,没有什么比查看原始输出更好的了。当您查看样本输出时,您会发现其他方法无法告诉您的事情。

例如,如果您正在对作物执行对象检测,您可能会看到,由于风的原因,当作物以某种方式对齐时,我们的边界框没有正确封装作物。

然而,查看样本输出是一项单调乏味的任务。假设我们想测试各种 NMS 值,我们还想在一堆图像上测试它。我们总是可以为此编写一个函数,但是一次又一次地运行它是令人厌烦的。

如果有一个应用程序,我们可以上传图像,并使用滑块来调整 NMS 值,这不是很好吗?欢迎光临,史崔特。

什么是 Streamlit?

根据他们的网站,Streamlit 是一个开源的 web 框架,供数据科学家和机器学习工程师在短短几个小时内创建漂亮、高性能的应用程序,全部用纯 Python 编写。

装置

pip install streamlit

入门指南

在这个演示中,我将使用我训练的模型,通过快速 CNN 检测小麦目标。您可以回到那篇文章,培训或者下载我的模型,然后继续学习。

Streamlit 只是一个自顶向下运行的标准 python 文件。我们将首先创建一个名为 app.py 的文件,并在其中编写以下代码。

我们将按如下方式运行:

streamlit run app.py

它将打开我们的浏览器,输出如下。

注意,我们在 st.write()中使用了#号。这表明我们正在里面写 markdown。我们首先需要的是一个文件上传器来上传图像到 Streamlit。同样,这很简单:

我们传递允许的文件类型(本例中是 jpg 和 png ),当我们附加一个文件时,我们使用 PIL 读取它。现在保存 app.py 时:

我们看到 Streamlit 识别出源文件已经更改,并询问我们是否要重新运行。我们有。因此,我们选择“总是重新运行”来自动反映更改。现在我们的浏览器看起来像这样:

为了显示图像,我们可以使用 st.image()。然而,在生成预测之后,我们想要用我们的预测图像替换输入图像。为此,我们创建一个空容器并显示其中的所有内容。

我喜欢使用容器的另一个原因是你可以设置use_column_width = True,并且你不用担心图像的大小。现在,我们可以将图像拖放到我们的应用程序中。

最后,我们可以将图像转换为张量,加载模型,生成输出,并将其写入容器。

要改变 NMS 值,我们可以使用滑块或输入框来输入值,或者使用“+”和“-”按钮来增加或减少值。我要用滑球。我们的代码变成了。

仅此而已。只用大约 50 行代码,我们就可以创建这个超级有用的应用程序来测试我们的模型。您还可以为图像分类、分割、对象检测等各种问题创建模板,并在每次训练新模型时使用它们。

最后,当我们使用滑块更改 NMS 值时,如果我们已经为特定值生成了预测,我们就不想再生成它们了。因此,您可以在函数的顶部添加一个简单的装饰器:

它会为你缓存结果。这样,它不会每次都重新运行相同的阈值,而只是使用缓存的结果。很酷,不是吗?

结论:

这就是本文的全部内容。我真的会推荐大家使用 Streamlit,创建数据应用。它适用于所有类型的数据,缓存有助于处理昂贵的操作,如处理大型数据框。试试看。

如果你想了解更多关于深度学习的知识,请查看我的深度学习系列。

[## 深度学习系列

我所有关于深度学习的文章的系统列表

medium.com](https://medium.com/@dipam44/deep-learning-series-30ad108fbe2b)

~快乐学习

参考资料:

https://docs.streamlit.io/en/stable/main_concepts.html

streamlit vs . Dash vs . Shiny vs . Voila vs . Flask vs . Jupyter

原文:https://towardsdatascience.com/streamlit-vs-dash-vs-shiny-vs-voila-vs-flask-vs-jupyter-24739ab5d569?source=collection_archive---------11-----------------------

比较数据仪表板工具和框架

来源:作者

在过去的三年里,Dash 和 Streamlit 作为一体式仪表板解决方案越来越受欢迎。来源:作者

数据仪表板—工具和库

几乎每个公司都拥有内部团队需要访问和分析的宝贵数据。非技术团队通常需要工具来简化这一过程。这些团队不需要为每个请求都找一位数据科学家,而是需要动态仪表板,在那里他们可以轻松地运行查询并查看定制的交互式可视化。

数据仪表板可以让您的非技术团队更容易访问数据。来源:作者

数据仪表板由许多不同的组件组成。它需要:

  • 分析:使用后端库(如 Pandas)操作和汇总数据。
  • 可视化:使用像散景这样的图形库创建数据的图表。
  • 交互:使用 React 等前端库接受用户输入。
  • Serve: 使用 Flask 等 web 服务器监听用户请求并返回网页。

在过去,您不得不浪费大量的时间来编写所有的“粘合”代码,以便将这些组件连接在一起。但是对于像 Streamlit 和 Dash 这样的新库,这些组件都在一个包中。

尽管如此,确定使用哪个库仍然具有挑战性。以下是它们之间的比较,以及如何选择最适合您的项目的一些指导。

[您是否想要更详细的、贯穿营销语言的工具对比?注册我们的每周简讯。]

告诉我用哪一个

和往常一样,“视情况而定”——但是如果你在寻找一个快速的答案,你可能应该使用:

  • 破折号如果您已经使用 Python 进行分析,并且想要为更大的公司构建生产就绪的数据仪表板。
  • Streamlit 如果您已经使用 Python 进行分析,并且希望尽快建立并运行您的仪表板原型。
  • 闪亮如果您已经使用 R 进行分析,并且您希望让非技术团队更容易获得结果。
  • Jupyter 如果你的团队技术含量很高,并且不介意安装和运行开发者工具来查看分析。
  • 如果您已经有了 Jupyter 笔记本,并且希望让非技术团队也能使用它们。
  • 如果你想从头开始构建自己的解决方案,那就试试烧瓶。

快速概述

并不是所有的库都可以直接比较。比如 Dash 是建立在 Flask 之上的,Flask 是一个更通用的 web 应用开发框架。类似地,每个库关注稍微不同的领域。

  • StreamlitDash 是完整的仪表板解决方案,专注于基于 Python 的数据分析,分别运行在 TornadoFlask web 框架上。
  • Shiny 是一款完整的仪表板解决方案,专注于使用 r。
  • Jupyter 是数据科学家用来分析和操作数据的笔记本。您还可以使用它来可视化数据。
  • 这是一个将个人 Jupyter 笔记本变成交互式网页的库。
  • Flask 是一个用于构建网站和应用的 Python web 框架——不一定专注于数据科学。

这些库有些已经存在了一段时间,有些还是全新的。有的比较死板,有自己的结构,有的比较灵活,能适应你的。有些侧重于特定的语言。下表显示了这些权衡:

来源:作者

我们在以下方面比较了这些库:

  • 成熟度:基于项目的年限和稳定程度。
  • 人气:基于领养和 GitHub 明星。
  • 简单:基于开始使用这个库的容易程度。
  • 适应性:基于库的灵活和固执程度。
  • 焦点:基于本库解决什么问题。
  • 语言支持:本库支持的主要语言。

这些不是严格或科学的基准,但它们旨在让您快速了解这些工具是如何重叠的,以及它们彼此之间有何不同。更多细节,请看下面的头对头对比。

Streamlit 与 Dash

Streamlit 和 Dash 是这个集合中最相似的两个库。它们都是使用 Python 构建的完整仪表板解决方案,并且都包括用于数据分析、可视化、用户交互和服务的组件。

虽然它们都是开源的,但 Dash 更专注于企业市场,并不包括开源版本中的所有功能(如作业队列)。相比之下,Streamlit 是完全开源的。

Streamlit 更加结构化,更加注重简单性。它只支持基于 Python 的数据分析,并且有一组有限的小部件(例如滑块)可供选择。

Dash 的适应性更强。虽然它是用 Python 构建的,并把用户推向自己的绘图库(Plotly),但它也兼容其他绘图库,甚至其他语言,如 R 或 Julia。

  • 如果你想尽可能快地开始,并且没有强烈的意见或许多定制需求,使用 Streamlit
  • 如果你需要更灵活、更成熟的东西,并且不介意花费额外的工程时间,就用 Dash

流线型与闪亮

Streamlit 是基于 Python 的仪表盘工具,而 Shiny 使用的是 r,这两个工具都专注于将数据分析脚本转化为完整的交互式 web 应用。

因为 Python 是一种通用语言,而 R 只专注于数据分析,所以用 Streamlit(基于 Tornado web 服务器)构建的 web 应用程序比用 Shiny 构建的更强大,也更容易扩展到生产环境。

Shiny 与 R 生态系统中的绘图库(如 ggplot2)集成良好,而 Streamlit 与 Python 绘图库(如 Bokeh 或 Altair)集成良好。

  • 如果你更喜欢在 R 中做数据分析,并且已经投资了 R 生态系统,请使用 Shiny
  • 否则使用 Streamlit (或破折号——见上文)。

Streamlit 对 Voila

Streamlit 是一个完整的数据仪表板解决方案,而 Voila 是一个更简单、更有限的工具,允许您将现有的 Jupyter 笔记本电脑转换为基本的数据仪表板,并作为 web 应用程序提供给非技术用户。

像 Streamlit 一样,Voila 是建立在 Tornado web 框架之上的,所以你可以使用 Jupyter 笔记本和 Voila 来获得与 Streamlit 大致相似的东西。但是 Streamlit 更灵活(它不需要你使用 Jupyter),而 Voila 可以更简单(前提是你已经有了你想要呈现的 Jupyter 笔记本)。

Voila 使用 Jupyter 的小部件库,而 Streamlit 使用自定义小部件——所以如果你已经熟悉 Jupyter,你会发现 Voila 更容易使用。

  • 如果您正在寻找一体化解决方案,请使用 Streamlit
  • 如果你已经有了 Jupyter 笔记本,并且正在寻找一种服务它们的方式,请使用 Voila 。

Streamlit 与 Jupyter 笔记本电脑

Streamlit 是一个完整的数据仪表板解决方案,而 Jupyter 笔记本主要是对想要开发软件和可视化的工程师有用。工程师使用 Streamlit 为非技术用户构建仪表板,他们使用 Jupyter 笔记本开发代码并与其他工程师共享。

与 Voila 等插件相结合,Jupyter 笔记本可以类似地用于 Streamlit,但数据仪表板不是他们的核心目标。

  • 如果您需要非技术人员也能使用的仪表盘,请使用 Streamlit
  • 如果你的团队主要是技术型的,并且你更关心功能而不是美观,那么‍ Jupyter 笔记本是最好的选择。

Streamlit 与 Flask

Streamlit 是一个数据仪表板工具,而 Flask 是一个 web 框架。向用户提供页面是数据仪表板的一个重要但很小的组件。Flask 没有任何数据可视化、操作或分析功能(尽管因为它是一个通用的 Python 库,所以它可以与执行这些任务的其他库很好地协作)。Streamlit 是一个集 web 服务和数据分析于一体的工具。

  • 如果您想要一个结构化数据仪表板,其中包含许多您需要的组件,请使用 Streamlit 。如果你想用通用组件构建一个数据仪表板,并且不想重新发明轮子,那么使用 StreamlitT3。
  • 如果你想从头开始构建一个高度定制的解决方案,并且你有工程能力,就使用 Flask

破折号 vs .闪亮

Dash 和 Shiny 都是完整的数据 dashboarding 工具,但 Dash 主要生活在 Python 生态中,而 Shiny 则是 r 的专属。

Dash 比 Shiny 有更多的功能,尤其是在其企业版中,它更加灵活。Python 是一种通用编程语言,而 R 只专注于数据分析。一些数据科学家更喜欢 R,因为它有成熟的库和(通常)更简洁的代码。工程师通常更喜欢 Python,因为它更符合其他语言。

  • 如果你的团队更喜欢 Python,使用破折号。
  • 如果你的团队更喜欢 r,使用闪亮的。

Dash vs. Voila 和 Jupyter 笔记本

Dash 是一个一体化的仪表板解决方案,而 Voila 可以与 Jupyter 笔记本电脑结合使用,以获得类似的结果。Dash 更加强大和灵活,它是专门为创建数据仪表板而构建的,而 Voila 是建立在 Jupyter 笔记本电脑之上的一个薄层,用于将它们转换为独立的 web 应用程序。

  • 如果你想构建一个可伸缩的、灵活的数据仪表板工具,使用 Dash
  • 如果您希望您的非技术团队能够使用现有的 Jupyter 笔记本电脑,请使用 Voila

Dash vs. Flask

Dash 构建在 Flask 之上,使用 Flask 作为其 web 路由组件,所以将它们进行正面比较意义不大。Dash 是一个数据仪表板工具,而 Flask 是一个极简的通用 web 框架。Flask 没有包含数据分析工具,尽管它可以与其他进行分析的 Python 库一起工作。

  • 如果您想要构建数据仪表板,请使用破折号
  • 如果你想构建一个更通用的 web 应用程序并选择其中的每个组件,请使用 Flask

闪亮与 Voila + Jupyter 笔记本电脑

Shiny 是 R 的数据仪表板解决方案,虽然你可以在 R 上使用 Voila 和 Jupyter 笔记本,但这些工具主要关注 Python 生态系统。

  • 如果你已经在 r 中做了数据分析,就用闪亮的
  • 如果你已经有了 Jupyter 笔记本,并想让它更容易使用,那么就使用 Voila 。

闪亮与烧瓶

Shiny 是一个内置在 r 中的数据仪表板工具,Flask 是一个内置在 Python 中的 web 框架。Shiny 与 R 绘图库配合得很好,比如 ggplot2。默认情况下,Flask 没有内置任何数据分析工具。

  • 如果你正在构建一个数据仪表板,并且想用 r 进行数据分析,那么就使用 Shiny
  • 如果你想从头开始构建一个通用的 web 应用程序,使用 Flask

瞧,这就是烧瓶

Voila 是一个将 Jupyter 笔记本转换为独立网络应用程序并使用 Tornado 为其提供服务的库。像 Tornado 一样,Flask 是一个通用的 web 框架。虽然可以使用 Flask 为 Jupyter 笔记本提供服务,但是您必须重新实现大部分 Voila 库——所以除非您有非常具体的原因,否则最好简单地使用 Voila。

结束语

我们在这里介绍的所有工具都可以帮助您访问锁定在现有数据中的价值。我们看到团队犯的一个常见错误是,在选择使用哪些工具时过于纠结,而不是关注数据本身。虽然使用错误的工具肯定会阻碍你的分析,但团队陷入所谓的自行车脱落更常见:花太多时间争论不太重要的细节。

如果您想聊聊探索您的数据并将其转化为更多收入,请与我们的首席执行官预约免费通话。

街头霸王 2 很难,所以我训练了一个人工智能来帮我打败它

原文:https://towardsdatascience.com/street-fighter-ii-is-hard-so-i-trained-an-ai-to-beat-it-for-me-891dd5fc05be?source=collection_archive---------23-----------------------

训练一个人工神经网络玩街霸 II 冠军版

瑞安·昆塔尔在 Unsplash 上拍摄的照片

我先说我不擅长打游戏。在成长过程中,我总是在大多数游戏中失败,直到我想出了扣杀的策略,直到我赢了。尽管如此,作为一个年轻的成年人,我决定接受街头霸王 II 的挑战,这是一款卡普空钟爱的游戏。这是 90 年代的一款游戏,它激发了一代人酷炫的战斗动作和惊人的关卡主题。

虽然砸按钮策略很有效,但我需要一个不同的策略来完成这个活动。然后,突然意识到,我想出了一个主意,训练一个强化剂来帮我打败它。所以,舞台设置好了,我决定开始训练我自己的模特来击败这场运动!

健身房复古和整合工具

首先,我们需要一种方法将《街头霸王 2》实际实现到 Python 中。有几种方法可以做到这一点,但为了节省时间,最简单的方法是健身房复古。Gym-retro 是一个 Python 包,可以将我们的游戏数据转化为可用的环境。Gym-retro 带有超过 1000 种不同游戏的预制环境。这个工具很棒,因为它使得在游戏中实现一个人工代理变得非常简单。这也使得提取每次跑步的行动和奖励变得非常简单。

开 AI 健身房复古

最初的包中唯一缺少的是每个级别的保存状态。但是,他们也发布了自己的集成工具,您可以在这种情况下使用!

你首先需要把它安装到你的健身房复古文件和游戏文件所在的文件夹中。开始后,你只需要把你的角色带到你想要保存状态的关卡开始,然后输出。短小精悍!

最后,过了一段时间,我获得了我们将要用来训练代理人的所有等级。接下来,我们需要决定使用什么强化算法。

稳定的基线和培训

我决定采用 A2C(演员优势评论家)模型的算法。

A2C 算法

这个模型背后的基本思想是,预测一个近乎无限量输入的行动几乎是不可能的。因此,我们将使用一个神经网络“演员”来探索当前环境并执行一个动作。另一个神经网络“批评家”获取当前状态和行为,并输出评估。“行动者”然后根据“批评者”的建议调整执行某些动作的概率。改变执行动作的方式是优势所在。它比较了执行某个动作的代理人与在该状态下采取的平均动作之间的回报。

稳定基线是 Open AI 的初始基线 Python 包的延续,对原始包进行了改进。它包括许多强化学习模型,所以一定要去看看!他们的 A2C 模型是我们将使用的模型,有了它,我们就有了所有的运动部件来训练我们的模型!

[## 丘陵/稳定基线

稳定基线是一组基于 OpenAI 基线的强化学习算法的改进实现…

github.com](https://github.com/hill-a/stable-baselines)

我们将使用 Google Colab 作为我们的 Python 环境。使用免费版的 Colab,我们可以在谷歌的云平台上运行 Python 笔记本,并利用他们的 Tesla K80 GPU 进行我们的培训。安装完所有的包之后,是时候创建我们的模型了。首先,我们验证我们的 Google Drive,并使用 Gym-Retro 包中的 Python 脚本导入我们的游戏文件。

!pip install stable-baselines[mpi]==2.10.0
!pip install gym-retro
!pip install tqdmfrom tqdm import tqdm
import time
import retrofrom stable_baselines.common.policies import MlpPolicy,MlpLstmPolicy, MlpLnLstmPolicy, CnnLnLstmPolicy, CnnPolicy, CnnLstmPolicyfrom stable_baselines.common.vec_env import SubprocVecEnv, DummyVecEnvfrom stable_baselines import PPO2, A2Cfrom google.colab import drive
drive.mount('/gdrive')
!python -m retro.import /gdrive/"My Drive"/"Where you Keep your Game Files"

接下来,我们将创建我们的模型。我们将使用我们之前在 CNN 政策中引入的 A2C 模型(最适合 2D 游戏)。我们还需要通过提供我们正在使用的游戏以及我们希望代理从什么状态开始来初始化我们的环境。

#Create and Train Model on SFII Engine
gamename = 'StreetFighterIISpecialChampionEdition-Genesis'
modelname = 'Fighter_a2c_pt2' #whatever name you want to give it
env = DummyVecEnv([lambda: retro.make(gamename ,state='Champion.Level1.RyuVsGuile')])model = A2C(CnnPolicy,env,n_steps=128, verbose=1)
#model = A2C.load('/gdrive/My Drive/ROMS/Fighter_a2c_pt2.zip')
model.set_env(env)
model.learn(total_timesteps=1000)#Saves Model into
model.save("/gdrive/My Drive/"#"Whatever Your File Name is/" + modelname)env.close()

现在是有趣的部分。我们将训练我们的模型来击败这场运动!街头霸王 II 战役中,Ryu 是唯一可玩的角色,所以我们会用他来训练我们的模型。我们的模型将在每一关运行 100,000 次,并在每一关后保存。我们的最终结果基于 10 个训练周期(每个级别 100 万次迭代)。我很好奇的一件事是培训需要多长时间?通过利用 Python 中的时间包,我能够看到每个训练周期大约需要 2 个小时。

#Training and Saving Your Model#Use whatever you called your states without the .state extension
sts = ['RyuVsGuile','RyuVsBlanka','RyuVsRyu','RyuVsKen','RyuVsChunLi','RyuVsZangief','RyuVsDhalsim','RyuVsHonda','RyuVsBalrog','RyuVsVega','RyuVsSagat','RyuVsBison']start_time = time.time()
for st in tqdm(sts, desc='Main Loop'):
  print(st)
  env = DummyVecEnv([lambda: retro.make('StreetFighterIISpecialChampionEdition-Genesis', state=st, scenario='scenario')])
  model.set_env(env)
  model.learn(total_timesteps=500000)
  model.save(modelname)
  env.close()
end_time = time.time() - start_time
print(f'\n The Training Took {end_time} seconds')

训练完我们的模型后,我们将需要计算代理获得的奖励金额。我们可以通过让代理人玩一个关卡并计算代理人获得的奖励金额(赢得一场比赛后获得的点数)来实现这一点。这个模型在一个比训练更容易的难度上被测试,仅仅是因为它产生了最好的结果。我们还将利用 Gym-Retro 中的一个伟大功能,它允许你记录你的代理人在游戏中的表现!录制的素材是 BK2 文件,可以使用 Gym-Retro 附带的另一个 Python 脚本将其转换为 MP4。

env = DummyVecEnv([lambda: retro.make('StreetFighterIISpecialChampionEdition-Genesis',state='RyuVsHonda-Easy', record='/gdrive/My Drive/'#"Wherever you put file")])model = A2C.load(modelname)
model.set_env(env)
obs = env.reset()
done = False
reward = 0while not done:
  actions, _ = model.predict(obs)
  obs, rew, done, info = env.step(actions)
  reward += rew
print(reward)### Convert BK2 to MP4 File!python /usr/local/lib/python3.6/dist-packages/retro/scripts/playback_movie.py "/gdrive/My Drive/Level16.RyuVsHonda-Easy-000000.bk2"

经过漫长的旅程,我们终于制造出了一个能够打败街霸 II 的人工智能!下面是 Ryu_Bot 打完战役的视频。

模仿和未来的设计

虽然这个项目给出了令人满意的结果,但这个设计有一些限制。首先,这个模型只适用于 Ryu。当切换到一个单独的角色时,比如 Guile,模型的表现并不好,因为他们的特殊动作有单独的输入。对于未来的设计,我会考虑使用单独的角色来训练模型,或者比较和对比不同的强化学习算法,看看哪种表现最好。

在一天结束时,如果你对开始使用机器学习感到好奇,构建一个 RL 代理会非常有趣和有意义。除了视频游戏,强化学习还有许多用途,比如在优化问题或机器人方面。还有大量很棒的文章和视频系列可以帮助你开始。

感谢您的阅读!

街头霸王拳头撞 GIF

完整代码可以通过 Google Colab 找到:

[## 谷歌联合实验室

龙 _ 机器人

colab.research.google.com](https://colab.research.google.com/drive/1cbyrrfqgc2mUu6ZyfYeB20A7-Khksq5-?usp=sharing)

参考

  1. https://retro.readthedocs.io/en/latest/getting_started.html
  2. https://stable-baselines.readthedocs.io/en/master/
  3. https://www.youtube.com/watch?v=NyNUYYI-Pdg&t = 547s
  4. https://www.youtube.com/channel/UCLA_tAh0hX9bjl6DfCe9OLw
  5. https://www.youtube.com/watch?v=O5BlozCJBSE

使用 DCGAN 生成街景门牌号

原文:https://towardsdatascience.com/street-view-house-number-generation-using-dcgan-8cc5222408f3?source=collection_archive---------32-----------------------

深度学习

用 DCGANs 生成新的门牌号图像

卡拉·亚历山大Unsplash 上拍摄的照片

在本文中,我将带您完成一个有趣的项目,在这个项目中,您将实现一个用于街景门牌号生成的 DCGAN。

我们将利用街景门牌号(SVHN)数据集来训练我们的对抗网络。

如果你不熟悉 GANs 及其工作方式,请阅读这篇关于走向数据科学的文章。

[## 生成对抗网络

用解读甘博弈

towardsdatascience.com](/generative-adversarial-networks-6a17673db367)

街景门牌号(SVHN)数据集

您将在街景门牌号码(SVHN)数据集上训练 DCGAN。这些是从谷歌街景收集的门牌号的彩色图像。SVHN 图像是彩色的,比 MNIST 图像更加多变。

数据可以从这里下载。

我们将使用深度卷积 GANs。如果你想了解 DCGANs,可以看看这篇文章。

[## 深度卷积生成对抗网络

生成对抗网络最有趣的部分之一是生成网络的设计。的…

towardsdatascience.com](/dcgans-deep-convolutional-generative-adversarial-networks-c7f392c2c8f8)

预处理和数据加载

我们只需要将数据转换成张量,并准备好数据加载器。

作者代码。

可视化我们的训练数据

我们现在将生成一批数据,并将其可视化。请注意,np.transpose 函数按照指定的顺序转换图像尺寸。例如,在调用以下函数时,形状 3x32x32 的 RGB 图像将转换为 32x32x3:

np.transpose(img,(1,2,0))

作者代码。

图片由作者提供。

我们的批次大小是 128,所以在这种情况下,我们只绘制 20 个图像,而不是绘制一个批次的所有 128 个图像。

缩放图像

缩放图像是很重要的,因为 Tanh 函数的值在-1 到 1 的范围内,所以我们需要将我们的训练图像重新缩放到-1 到 1 的范围。(目前,它们在 0-1 的范围内。)

作者代码。

辅助函数—卷积和转置卷积

为了简化我们的代码,我们将定义帮助函数来定义我们的鉴别器和生成器网络。

这些助手功能的原因是什么?回答——干!😅

卷积辅助函数

注:要了解 CNN,请查看下面的斯坦福笔记。

[## 用于视觉识别的 CS231n 卷积神经网络

斯坦福 CS231n 课程材料和笔记:视觉识别的卷积神经网络。

cs231n.github.io](https://cs231n.github.io/)

作者代码。

转置卷积辅助函数

注意:如果你想了解转置卷积,可以看看下面的文章。

[## 转置卷积去神秘化

转置卷积对于图像分割、超分辨率等应用来说是一个革命性的概念

towardsdatascience.com](/transposed-convolution-demystified-84ca81b4baba)

作者代码。

鉴别器架构

我们现在将定义我们的鉴别器网络。正如我们所知,鉴别器负责将图像分类为真或假。因此这是一个典型的分类器网络。

作者代码。

发电机架构

生成器网络负责生成假图像,这些假图像可以欺骗鉴别器网络将其归类为真实图像。随着时间的推移,生成器在欺骗鉴别器方面变得相当不错。

作者代码。

参数初始化

我们将通过从正态分布中抽取随机值来初始化网络的权重和偏差。这导致更好的结果。我们为其定义了一个函数,将一个层作为输入。

对于权重,我使用 0 均值和 0.02 标准差。

对于偏差,我使用 0。

现在这应该被替换,所以函数后面的 _(下划线)也是如此。

作者代码。

损失函数和优化器

我们将使用学习率为 0.002 的 Adam 优化器。这与 DCGANs 的原始研究论文一致。你可以在下面查看一下。

[## 深度卷积生成对抗网络的无监督表示学习

近年来,卷积网络的监督学习(CNN)在计算机视觉领域得到了广泛应用…

arxiv.org](https://arxiv.org/abs/1511.06434)

作者代码。

我们使用 BCEwithLogitsLoss(),它结合了一个 sigmoid 激活函数(我们希望鉴别器输出一个 0–1 的值来指示一个图像是真的还是假的)和二进制交叉熵损失。

Binar 交叉熵损失方程。图片由作者提供。

培训阶段

为了更好的结果,我们将训练 50 个时代。

作者代码。

策划损失

作者代码。

图片由作者提供。

样本生成

现在让我们生成几个样本。重要的是,我们要将这些值重新调整回像素范围(0–255)。

作者代码。

最后,下面是我们生成的街景小时数。👀

图片由作者提供。

结论

我们已经看到了如何在 SVHN 数据集上使用 DCGAN 实现来生成街景门牌号。通过调整超参数,可以进一步改善生成的图像。你也可以选择比这里更深的层次。然而,这样做将导致参数数量的增加,这又将花费大量时间来训练。现在打开你的 Jupyter 笔记本,执行同样的操作。在下一篇文章中,我将带您完成 CycleGANs 的图像到图像转换。干杯!

谢谢你。

街道,邮政编码…都是关于瓷砖的,傻瓜。(地理空间探险续)

原文:https://towardsdatascience.com/streets-postcodes-its-all-about-the-tiles-silly-geospatial-adventures-continued-8a01e3e230c3?source=collection_archive---------44-----------------------

图片由布鲁诺·马丁斯通过 Unsplash 提供

一个简单的过程中的道路/邮政编码匹配,以帮助您的地址匹配需求。

这篇文章扩展了我的地理空间探险系列中讨论的一些方法,并着眼于一种相对快速的方法,将英国的邮政编码质心与其邻居和附近的道路进行匹配。因此,我们将尝试在笔记本电脑上匹配 3.9 米长的道路和 1.7 米长的邮编质心…

首先,让我们先快速看一下为什么值得这么做。

我在处理商业、房地产相关数据时经常遇到的一个问题是处理方式的不一致。至少可以说,这通常意味着不同相关数据集之间的数据协调很困难,多家公司试图创建一个良好的系统来匹配它们。我不打算在这方面讲太多细节,但我想说的是,在大多数情况下,这些系统都依赖于使用某种形式的主地址列表,这种列表为它们提供了一个真实的基础来源,其他一切都与之匹配。这些地址列表中的不一致确实是个问题,尤其是在邮政编码有问题的情况下。因此,尝试将道路与附近的邮政编码进行匹配的一个很好的理由是验证您的地址列表的完整性。您可以简单地检查您的每个地址是否可信,并标记出需要进一步检查的地址(在某些情况下,甚至可以自动更正)。

你也可以用它来优化邮政编码系统,例如,提高递送效率。尽管为此你也需要添加建筑多边形。

或者你可以用它来规划你的自行车/跑步路线。我肯定还有很多很多。

我之所以使用邮政编码质心而不是它们的多边形形状,是因为我坚持使用免费的可用数据。这在一定程度上限制了精确度,但您仍然可以走得很远。

数据集

是时候看看数据集了。第一——英国道路网。事实上,我将坚持英格兰,但你可以很容易地将框架扩展到整个英国或其他国家。我们将使用 OSM 的数据,可以在这里找到。下载形状文件,解压,我们在里面寻找 gis_osm_roads_free_1.shp 文件。让我们把它加载进来,快速地看一下内部(我们也把主要的导入放在这里)。

import geopandas as gpd
import pandas as pd
import numpy as nproads = gpd.read_file(
    'england-latest-free.shp/gis_osm_roads_free_1.shp'
)
roads = roads.to_crs(epsg=27700)roads.head()

这里有大量非常有用的信息——街道名称、分类(A/B 号)、道路是否是单行道、速度限制、是桥梁还是隧道。“层”指的是城市中心的复杂结构,那里的道路可能一条接一条堆叠在一起。对于我们的目的来说,最重要的是 final-geometry 列,它包含描述道路位置和形状的 LineString 对象。还要注意,默认的 CRS 是 epsg:4326,所以我们还需要转换为 Northings/easting(因为我更喜欢后者,也因为邮政编码数据使用 epsg:27700)。如果你是几何对象或 GeoPandas 的新手,或者可能想重温一下 CRS 是怎么回事——看看我的地理空间冒险系列的前两篇文章这里这里

这里可以找到的邮政编码数据。你可以从那个页面下载很多产品。我们在代码点开放之后。我正在使用它的 CSV 版本。您需要注册才能下载,并将通过电子邮件收到下载链接。它将作为一个 zip 文件夹——codepo _ GB,它本身将包含许多文件夹,我们需要遍历这些文件夹来加载整个数据集:

import os
ppc=[]
for f in os.listdir('codepo_gb/Data/CSV'):
    if type(pc) == list:
        pc = pd.read_csv('codepo_gb/Data/CSV/'+f, header=None)
    else:
        pc = pd.concat(
            [
                pc,
                pd.read_csv('codepo_gb/Data/CSV/' + f,
                            header=None)
            ], 
            ignore_index=True
        )

我在这里向 Python 纯粹主义者道歉,因为我有点作弊,只是在这里做了一个快速和肮脏的版本,所以请不要告诉任何人。不过说真的,我们所做的只是读入 csv 文件并将它们连接到我们的数据帧。理想情况下,我应该创建一个正确维度的空数据框架,而不是一个空列表,但这是 Python 的一大优点——您可以在某种程度上不受类型约束。不过,我不会在制作中这样做。

请注意,这些文件都是没有头文件的,带有头文件的文件可以在 DOC 文件夹中找到。让我们去掉那些我们不需要的,并重新命名其他的:

pc = pc[[0, 2, 3, 8]].rename(
    columns={
        0:'Postcode',
        2:'Eastings',
        3:'Northings',
        8:'District_code'
    }
)
pc.head()

瓷砖,瓷砖,瓷砖

现在我们已经加载了数据集,让我们来讨论一下策略。我们显然不是在寻找一个精确的匹配,没有邮政编码实际上会直接位于代表道路的线上。我们需要找到彼此相对接近的事物。理想情况下,我们还希望能够灵活地定义我们准备看多远。显而易见的强力方法是计算每个邮政编码质心和每条道路之间的距离,然后返回符合每个邮政编码(或每条道路)标准的集合。这将花费很长时间,所以更好的方法是使用磁贴,就像我们从光栅文件中提取建筑物高度的信息一样。

对于点来说,这是微不足道的,非常快。我们将使用 1km 乘 1km 的图块,因此我们所要做的就是将我们的坐标捕捉到最近的、更小的、圆形的 1km 数字(我们想要边界图块的左下角),并根据得到的坐标为我们的图块创建一个 12 位 id。一个长整数就足以识别和重建相关的图块,所以我们已经成功了一半。

pc['grid'] = (
    pc['Eastings'] // 1000
) * 1000000000 + (
    pc['Northings'] // 1000
) * 1000

道路会变得更加棘手。首先,我们将有多个瓷砖。同样,这个策略与我们以前构建多边形的策略非常相似。我们将找到每条线的边界框。将它捕捉到 1 公里的圆形标记(确保我们增加了它的大小,以免在这个过程中不小心切断了线串),然后根据生成的边界框的大小创建网格。最后一步——我们遍历生成的网格单元,验证它们与我们的线串相交,然后将它们转换为 id,就像我们对待点一样。下面是结果函数:

def road_to_tiles(rd):
    bounds = rd.bounds
    X, Y = np.mgrid[
        int(
            bounds[0] // 1000 * 1000
        ): int(
            bounds[2] // 1000 * 1000
        ) + 1000 : 1000,
        int(
            bounds[1] // 1000 * 1000
        ): int(
            bounds[3] // 1000 * 1000
        ) + 1000: 1000
    ]
    grid = list(
            map(
                list,
                list(
                    zip(
                        list(
                            zip(X.flatten(), Y.flatten())
                        ),
                        list(
                            zip(X.flatten(), Y.flatten() + 1000)
                        ),
                        list(
                            zip(X.flatten() + 1000, Y.flatten() + 1000)),
                        list(
                            zip(X.flatten() + 1000, Y.flatten())
                        )
                    )
                )
            )
        )
    res=[
        a[0][0] * 1000000 + a[0][1] for a in grid if rd.intersects(Polygon(a))
    ]

    return res

如果这令人困惑——我在本系列的上一篇文章中一步一步地讲述了它,所以请检查一下。

接下来,我们将把它应用到我们的每一行字符串中,使用 swifter(和 swifter 下的 Dask)来加速。

import swifter
roads['grid'] = roads['geometry'].swifter.apply(
    lambda x: road_to_tiles(x)
)

在我的笔记本电脑上,这导致了 16 个分区,运行时间刚刚超过 10 分钟。

结果如下所示:

roads.head()

现在,为了将我们的邮政编码与附近的道路进行匹配,我们需要做的就是检查哪些道路属于相同的区块。

例如,如果您只关心是否在同一个图块中,而不关心确切的距离,您应该如何匹配它们:

  1. 为 roads 创建一个新的 DataFrame,在这里,我们不是将每条道路的唯一记录和多个 id 存储为列表,而是将所有内容展开为简单的长数组:
roads_flat = pd.DataFrame(
    {
        'osm_id':np.repeat(
            np.array(roads['osm_id']),
            np.array(roads['grid'].swifter.apply(len))
        ),
        'grid': np.concatenate(roads['grid'])
    }
)

2.使用“网格”列合并邮政编码数据框架和我们的新 roads_flat 数据框架:

pc_w_roads = pd.merge(
    pc,
    roads_flat,
    on='grid',
    how='left'
)

瞧:

pc_w_roads.head():

如果您想查看每个邮编的道路集合,您只需按邮编对结果进行分组,然后将 osm_ids 发送至列表:

pc_w_roads.groupby('Postcode').agg(
    {'osm_id':list}
).reset_index().head()

注意-这将需要很长时间来计算,因为数据帧非常大。相反,您可能希望专门针对您要查找的邮政编码进行汇总,而不是使用一揽子方法。

以类似的方式,您可以将 OSM id 与行字符串本身或它们的名称联系起来。

例如,如果我们想对“W1S 1HN”进行聚合:

w1s1hn = roads[
    roads['osm_id'].isin(
        pc_w_roads[
            pc_w_roads['Postcode'] == 'W1S 1HN'
        ]['osm_id']
    )
].reset_index(drop=True)

让我们快速浏览一下结果集:

import matplotlib.pyplot as plt
%matplotlib inlinew1s1hn.plot(figsize=(15,15))

如果你想在一个特定的半径范围内拥有一些东西呢?

假设您要搜索的是您的邮政编码周围 3 公里半径内的所有道路(或者类似地,某条道路 3 公里范围内的所有邮政编码)。或者您只是希望结果以邮政编码为中心。在我们上面的例子中,“W1S 1HN”,顺便说一下,是汉诺威广场,出现在右下角。不是很有用。

最简单的方法是在你的邮政编码周围增加图块的数量,然后用它们来匹配。只需修改我们创建的 id,加上或减去 1000*1000,000 来修改东距,加上或减去 1000 来修改北距,就可以做到这一点。在每个方向上添加足够的图块以获得足够的距离,然后将数据帧与我们的 roads_flat 数据帧进行匹配。如果你想在那之后得到精确的 3 公里距离,你可以使用 shapely 的迭代结果。距离法,丢弃任何最终在 3 公里以外的东西。将所有内容缩小到一小组相关道路之后,这就成了一项非常容易管理的任务。

可以采用类似的方法来寻找最近的邻居。为此,我们可以将 pc 数据帧与其自身进行匹配,而不是与 roads 数据帧进行匹配,以识别所有落在相同图块(或相邻图块)中的邮政编码。

今天到此为止。感谢您的阅读。如果您对此感兴趣,请查看地理空间探险系列(在我的个人资料中),如果您有任何问题或有趣的用例,请告诉我。

SQL 中的字符串函数

原文:https://towardsdatascience.com/string-functions-in-sql-9f08fabfa60e?source=collection_archive---------30-----------------------

分析 SQL 中的字符串远不止像“%…%”这样简单

使用 SQL 解开字符串看起来很困难,但是通过了解正确的函数会变得更容易

虽然 SQL 有时在功能更丰富的分析环境(如具有丰富功能库的 R 或 Python)旁边有一个“永久伴娘”的名声,但在过去几年中,处理字符串的标准函数越来越多地被采用,这大大增加了在 SQL 中处理字符串的可能性。

翻译和替换是许多数据库系统中都有的另外两个功能。它们已经存在很多年了,但是一些数据库,比如 SQL Server,只是最近才添加了它们;MySQL 仍然没有添加翻译。

这两个函数都用来替换字符串。REPLACE 用另一个字符串替换整个字符串,而 TRANSLATE 一次交换一个字符。

因此,您可以像这样使用 REPLACE,将一个完整的姓名或单词替换为另一个完整的姓名或单词:

SELECT REPLACE('I''m Bruce Wayne','Bruce Wayne', 'Batman');

结果:

I'm Batman

另一方面,as TRANSLATE 用其他特定字符替换字符,这对于克服数据中的可重复问题非常有用。例如,如果少量的字母或符号字符与数字数据混合在一起,妨碍了它们被正确地视为数字,那么这是一个很好的函数——只需使用 translate 来删除这些字符。另一个用途是,如果要导出为 csv 格式的表格中的文本数据中使用了逗号。如果您保留逗号并尝试导出,则很有可能无法正确检测到列,因为新列将被插入到不应该插入的位置。

例如,想象一个国家名称列表,其中,例如,朝鲜被列为“朝鲜,民主主义人民共和国”,而中国被列为“中国,人民共和国”——它们的官方英文名称被呈现,以便能够在朝鲜和中国下进行索引。

如果保留逗号,国家名称列有时会被拆分,破坏列与数据的对应关系。因此,您需要删除逗号。尝试以下方法:

SELECT TRANSLATE('China,Peoples Republic',',',' ')China Peoples Republic

TRANSLATE 函数的诀窍在于,要替换的字符列表和将要替换它们的列表需要顺序相同,这样 SQL 就知道如何处理它们。然而,总的来说,这是一个非常灵活的功能。

近年来标准中引入的另一个主要函数是 LISTAGG 函数。SQL Server 中也有此函数,语法与 STRING_AGG 类似。此函数将一列中不同单元格的字符串值连接成一个字符串,分隔符由用户指定。

使用此函数的一种方法是,如果您以组件形式存储姓名和地址数据(名、姓、门牌号码、街道名称等的单独列),这样可以更容易地搜索特定属性,然后您可以将组件组合成完整的姓名和地址,并采用您喜欢的格式。尝试以下方法:

CREATE TABLE Names
(Names varchar(10));INSERT INTO Names Values
('John')
,('Paul')
,('George')
,('Ringo');SELECT STRING_AGG(Names,' and ')
FROM NamesResult: 
John and Paul and George and Ringo

知道如何在 SQL 中处理字符串似乎很困难。然而,这在很大程度上是因为那些帮助你正确处理字符串的函数并不像它们应该的那样广为人知。掌握上面讨论的功能会给你额外的灵活性来处理弦乐。

罗伯特·德格拉夫的书《管理你的数据科学项目》》已经通过出版社出版。

在 Twitter 上关注罗伯特

用 FuzzyWuzzy 进行字符串匹配

原文:https://towardsdatascience.com/string-matching-with-fuzzywuzzy-e982c61f8a84?source=collection_archive---------1-----------------------

使用 FuzzyWuzzy 库匹配序列的教程

约尔根·哈兰Unsplash 上拍照

本教程将介绍如何通过相似性来匹配字符串。FuzzyWuzzy 通过提供诸如 Levenshtein 距离计算等工具,可以在数据科学过程中为您节省大量时间。除了例子之外,我还将包括一些有用的提示来充分利用 FuzzyWuzzy。

字符串匹配在各种情况下都很有用,例如,当两个表中运动员姓名的拼写或标点不同时,可以将两个表连接起来。这就是 FuzzyWuzzy 来拯救世界的时候了!Fuzzywuzzy 使用两个序列之间的某种相似性比率,并返回相似性百分比,而不是为了匹配而尝试格式化字符串。更详细的描述,请看一下 文档 。让我们从导入必要的库开始,并查看一个简单的示例。虽然不是必需的,但是强烈推荐使用 FuzzyWuzzy 使用python-Levenshtein。它使字符串匹配过程加快了 4-10 倍,但结果可能与 difflib 不同,difflib 是一个提供用于比较序列的类和函数的模块。

**#Installing FuzzyWuzzy**
pip install fuzzywuzzy**#Import** import fuzzywuzzy
from fuzzywuzzy import fuzz
from fuzzywuzzy import processStr_A = 'FuzzyWuzzy is a lifesaver!'
Str_B = 'fuzzy wuzzy is a LIFE SAVER.' ratio = fuzz.ratio(Str_A.lower(), Str_B.lower())
print('Similarity score: {}'.format(ratio))**#Output** Similarity score: 93

我们使用上面的ratio()函数来计算两个字符串(序列)之间的 Levenshtein 距离相似性比率。这里的相似率百分比是 93%。当两者都是小写时,我们可以说Str_BStr_A有 93%的相似度。

部分比率

FuzzyWuzzy 还有更强大的函数来帮助在更复杂的情况下匹配字符串。partial ratio()函数允许我们执行子串匹配。这是通过获取最短的字符串并将其与所有长度相同的子字符串进行匹配来实现的。

Str_A = 'Chicago, Illinois' 
Str_B = 'Chicago'ratio = fuzz.partial_ratio(Str_A.lower(), Str_B.lower())
print('Similarity score: {}'.format(ratio))**#Output** Similarity score: 100

使用上面的partial ratio()函数,我们得到的相似度为 100。在ChicagoChicago, Illinois的场景中,这很有帮助,因为两个字符串都指向同一个城市。这个函数在匹配姓名时也很有用。例如,如果一个序列是某人的名字和中间名,而您试图匹配的序列是此人的名字、中间名和姓氏。partial_ratio()函数将返回 100%匹配,因为这个人的名字和中间名是相同的。

令牌排序比率

FuzzyWuzzy 还有一些标记函数,可以标记字符串,将大写字母改为小写字母,以及删除标点符号。token_sort_ratio()函数按字母顺序对字符串进行排序,然后将它们连接在一起。然后,计算fuzz.ratio()。当您比较的字符串拼写相同,但顺序不同时,这就很方便了。让我们用另一个名字的例子。

Str_A = 'Gunner William Kline' 
Str_B = 'Kline, Gunner William'ratio = fuzz.token_sort_ratio(Str_A, Str_B)
print('Similarity score: {}'.format(ratio))**#Output** Similarity score: 100

令牌集比率

token_set_ratio()函数类似于上面的token_sort_ratio()函数,除了它在计算新字符串之间的fuzz.ratio()之前取出公共标记。当应用于一组长度差异很大的字符串时,这个函数是最有用的。

Str_A = 'The 3000 meter steeplechase winner, Soufiane El Bakkali' 
Str_B = 'Soufiane El Bakkali'ratio = fuzz.token_set_ratio(Str_A, Str_B)
print('Similarity score: {}'.format(ratio))**#Output** Similarity score: 100

过程模块

FuzzyWuzzy 还附带了一个方便的模块 process,它返回字符串以及字符串向量的相似性得分。你所需要做的就是在进程之后调用extract()函数。

choices = ["3000m Steeplechase", "Men's 3000 meter steeplechase",                    "3000m STEEPLECHASE MENS", "mens 3000 meter SteepleChase"] process.extract("Men's 3000 Meter Steeplechase", choices, scorer=fuzz.token_sort_ratio)**#Output** [("Men's 3000 meter steeplechase", 100),
 ('mens 3000 meter SteepleChase', 95),
 ('3000m STEEPLECHASE MENS', 85),
 ('3000m Steeplechase', 77)]

类似于extract函数,您也可以通过调用extractOne()函数,使用流程模块只提取一个具有最高相似性得分的字符串。

choices = ["3000m Steeplechase", "Men's 3000 meter steeplechase",                    "3000m STEEPLECHASE MENS", "mens 3000 meter SteepleChase"]process.extractOne("Men's 3000 Meter Steeplechase", choices, scorer=fuzz.token_sort_ratio)**#Output** ("Men's 3000 meter steeplechase", 100)

用 FuzzyWuzzy 替换字符串

看看下面的数据框,左边的df_1和右边的df_2``df_1包含了参加夏季奥运会的运动员。这个数据帧有一个name列,其中运动员的名字是字符串。如果我想得到这些运动员参加的项目的结果,我会把表格刮下来,放入数据框中。从那里,我可以将事件的结果与下面的数据框架(左)进行左连接。为此,我需要指定要连接值的列或索引级别。

东风 _1(左)|东风 _2(右)(图片由作者提供)

这里,我们遇到的问题是,第一个数据帧中的一些名称与第二个数据帧的格式不同。如果我尝试将第二个数据帧连接到 name 列的第一个数据帧,这些值将不会找到匹配,因此,这些值不会在我们需要的位置。在这里,我们可以将每个数据帧中的名称转换成一个列表,然后用 FuzzyWuzzy 创建一个函数来返回一个字典,其中包含我们需要替换的字符串,以便找到值的匹配。

**#Casting the name column of both dataframes into lists**df1_names = list(df_1.name.unique())
df2_names = list(df_2.name.unique()) **#Defining a function to return the match and similarity score of the fuzz.ratio() scorer. The function will take in a term(name), list of terms(list_names), and a minimum similarity score(min_score) to return the match.** def match_names(name, list_names, min_score=0):
    max_score = -1
    max_name = ''
    for x in list_names:
        score = fuzz.ratio(name, x)
        if (score > min_score) & (score > max_score):
            max_name = x
            max_score = score
    return (max_name, max_score) **#For loop to create a list of tuples with the first value being the name from the second dataframe (name to replace) and the second value from the first dataframe (string replacing the name value). Then, casting the list of tuples as a dictionary.** names = []
for x in doping_names:
    match = match_names(x, athlete_names, 75)
    if match[1] >= 75:
        name = ('(' + str(x), str(match[0]) + ')')
        names.append(name)
name_dict = dict(names)
name_dict**#Output**{'Abdelatif Chemlal': 'Abdelatif Chemlal',
 'Abdelkader Hachlaf': 'Abdelkader Hachlaf',
 'Abderrahim Goumri': 'Abderrahim Al-Goumri',
 'Abraham Kiprotich': 'Abraham Kipchirchir Rotich',
 'Abubaker Ali Kamal': 'Abubaker Ali Kamal',
 'Adil Kaouch': 'Adil El-Kaouch',
 'Adrián Annus': 'Adrin Zsolt Annus',
 'Ahmad Hazer': 'Ahmad Hazer',
 'Ahmed Faiz': 'Ahmed Ali',
 'Ahmed Mohamed Dheeb': 'Mohammed Ahmed',
 'Ak Hafiy Tajuddin Rositi': 'Ak Hafiy Tajuddin Rositi',
 'Aleksandr Bulanov': 'Aleksandar Rakovi',
 'Aleksey Lesnichiy': 'Aleksey Lesnichy',
 'Alemayehu Bezabeh': 'Alemayehu Bezabeh Desta',
 'Alemitu Bekele': 'Alemitu Bekele Degfa',
 'Alex Schwazer': 'Alex Schwazer',
 'Alicia Brown': 'Alicia Brown',
 'Alissa Kallinikou': 'Alissa Kallinikou',
 'Allison Randall': 'Allison Randall',
 'Amaka Ogoegbunam': 'Amaka Ogoegbunam',
 'Amantle Montsho': 'Amantle Montsho',
 'Amina Aït Hammou': 'Amina "Mina" At Hammou',
 'Amine Laâlou': 'Amine Lalou',
 'Anastasios Gousis': 'Anastasios "Tasos" Gousis',
 'Anastasiya Soprunova': 'Anastasiya Valeryevna Soprunova',
 'Antonio David Jiménez': 'AntonioDavid Jimnez Pentinel',
 'Anzhelika Shevchenko': 'Anzhelika Viktorivna Shevchenko}**#Using the dictionary to replace the keys with the values in the 'name' column for the second dataframe**df_2.name = df_2.name.replace(name_dict)

从上面的输出可以看出,当将元组列表转换为字典时,我们可以很容易地用新的字符串替换原来的字符串。这样做时,当我将数据帧连接在一起时,这些值将位于匹配的name上的正确位置。

combined_dataframe = pd.merge(df_1, df_2, how='left', on='name')

结论

这篇文章介绍了 Python 中用于字符串匹配的 FuzzyWuzzy 库。FuzzyWuzzy 有许多不同的用例,在查找字符串匹配时,它肯定能节省您的时间。我建议花些时间尝试不同的函数和方法,找到解决问题的最佳方案。非常感谢你花时间来看我的博客!

参考

Python 中的字符串和文本

原文:https://towardsdatascience.com/strings-and-text-in-python-50be0452e0d3?source=collection_archive---------41-----------------------

拆分字符串和匹配文本

来源

文本处理在许多有用的软件程序中起着重要的作用。文本处理的应用包括网页抓取、自然语言处理、文本生成等等。在本帖中,我们将讨论一些基本的文本处理操作。具体来说,我们将讨论如何在多个分隔符上拆分字符串,以及如何将文本匹配到特定的模式。

我们开始吧!

使用“re.split()”拆分字符串

假设我们有一个包含几个编程语言名称的字符串:

my_string = 'python java sql c++ ruby'

我们可以使用字符串方法“split()”来分隔该字符串中的名称,并将它们存储在一个列表中:

print(my_string.split())

虽然对于这个例子很有用,但是“split()”方法主要用于非常简单的情况。它不处理具有多个分隔符的字符串,也不考虑分隔符周围可能存在的空白。例如,假设我们的字符串有几个分隔符:

my_string2 = 'python java, sql,c++;             ruby'

这可以是在抓取网站时接收文本数据的形式。让我们尝试对新字符串使用“split()”方法:

print(my_string2.split())

我们看到字符串中的“sql”和“c++”部分没有被正确分割。要解决这个问题,我们可以使用“re.split()”方法在多个分隔符上拆分字符串。让我们导入正则表达式模块“re”,并将“re.split()”方法应用于我们的字符串:

import re
print(re.split(r'[;,\s]\s*', my_string))

这非常有用,因为我们可以为分隔符指定多种模式。在我们的例子中,我们的字符串有逗号、分号和空格作为分隔符。每当发现一个模式时,整个匹配就成为位于匹配模式两侧的任何字段之间的分隔符。

让我们看另一个使用不同分隔符' | '的例子:

my_string3 = 'python| java, sql|c++;             ruby'

让我们将“re.split()”应用于新字符串:

print(re.split(r'[;|,\s]\s*', my_string3))

我们看到我们得到了想要的结果。现在,让我们讨论如何匹配文本开头和结尾的模式。

匹配文本

如果我们需要以编程方式检查特定文本模式的字符串的开头或结尾,我们可以使用“str.startswith()”和“str.endswith()”方法。例如,如果我们有一个指定 url 的字符串:

my_url = 'http://kaggle.com'

我们可以使用“str.startswith()”方法来检查我们的字符串是否以指定的模式开头:

print(my_url.startswith('http:'))

print(my_url.startswith('www.'))

或者我们可以检查它是否以特定的模式结束:

print(my_url.endswith('com'))

print(my_url.endswith('org'))

一个更实际的例子是,如果我们需要以编程方式检查目录中的文件扩展名。假设我们有一个包含不同扩展名的文件的目录:

my_directory = ['python_program.py', 'cpp_program.cpp', 'linear_regression.py', 'text.txt', 'data.csv']

我们可以使用“str.endswith()”方法检查多个文件扩展名。我们只需要传递一组扩展值。让我们使用 list comprehension 和' str.endswith()'方法来过滤我们的列表,使它只包含'。cpp '和'。“py”文件:

my_scripts = [script for script in my_directory if script.endswith(('.py', '.cpp'))]
print(my_scripts)

我就讲到这里,但是我鼓励你自己去研究代码。

结论

总之,在这篇文章中,我们讨论了如何使用“re.split()”方法沿着多个分隔符拆分字符串。我们还展示了如何使用“str.startswith()”和“str.endswith()”方法来检查特定文本模式的字符串的开头和结尾。我希望你觉得这篇文章有用/有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

在 Python 中剥离字符串

原文:https://towardsdatascience.com/stripping-python-strings-6635cbc1b501?source=collection_archive---------34-----------------------

探索 Python 字符串方法

来源

在计算机科学中,字符串数据类型是由一系列字符定义的。字符串通常由字符、单词、句子和/或数字信息组成。在 python 中,字符串对象可以访问几个方法,这些方法支持文本剥离、清理、搜索等操作。对这些方法有一个很好的理解是任何数据科学家的自然语言处理工具包的基础。在本帖中,我们将讨论如何使用 strip 方法来移除不需要的字符和文本,strip 方法可用于 python 中的字符串对象。

我们开始吧!

假设我们想从一个字符串的开头、结尾或起点删除不想要的字符,比如空格,甚至是损坏的文本。让我们定义一个带有多余空格的示例字符串。我们将引用 python 编程语言的作者吉多·范·罗苏姆的一段话:

string1 = '     Python is an experiment in how much freedom programmers need. \n'

我们可以使用' strip()'方法删除不需要的空白和新行,' \n '。让我们在应用“strip()”方法之前和之后打印:

print(string1)
print(string1.strip())

如果我们只想去掉字符串开头不需要的字符,我们可以使用' lstrip()'。让我们来看看 Guido 的另一首弦乐:

string2 = "    Too much freedom and nobody can read another's code; too little and expressiveness is endangered. \n\n\n" 

让我们使用' lstrip()'来删除左边不需要的空白:

print(string2)
print(string2.lstrip())

我们还可以使用“rstrip()”删除右边的新行:

print(string2)
print(string2.lstrip())
print(string2.rstrip())

我们看到在最后一个字符串中,三个新行被删除了。我们也可以用这些方法去掉不想要的字符。考虑以下包含不需要的' # '和' & '字符的字符串:

string3 = "#####Too much freedom and nobody can read another's code; too little and expressiveness is endangered.&&&&"

如果我们想删除字符串左边的' # '字符,我们可以使用' lstrip()':

print(string3)
print(string3.lstrip('#'))

我们还可以使用' rstrip()'删除' & '字符:

print(string3)
print(string3.lstrip('#'))
print(string3.rstrip('&'))

我们可以使用' strip()'方法去掉这两个字符:

print(string3)
print(string3.lstrip('#'))
print(string3.rstrip('&'))
print(string3.strip('#&'))

值得注意的是,strip 方法不适用于字符串中间的任何文本。考虑以下字符串:

string4 = "&&&&&&&Too much freedom and nobody can read another's code; &&&&&&& too little and expressiveness is endangered.&&&&&&&"

如果我们应用' srtip()'方法,将' & '作为我们的参数传入,它将只移除它们的左边和右边:

print(string4)
print(string4.strip('&'))

我们看到不需要的' & '仍然在字符串的中间。如果我们想删除文本中间不需要的字符,我们可以使用' replace()'方法:

print(string4)
print(string4.replace('&', ''))

我就讲到这里,但是我鼓励你自己去研究代码。

结论

总之,在这篇文章中,我们讨论了如何在 python 中从字符串中删除不需要的文本和字符。我们展示了如何使用' lstrip()'和' rstrip()'分别删除字符串左边和右边不需要的字符。我们还展示了如何使用“strip()”删除左侧或右侧的多个不需要的字符。最后,我们展示了如何使用“replace()”方法删除字符串中间不需要的文本。我希望你觉得这篇文章有用/有趣。这篇文章中的代码可以在 GitHub 上找到。感谢您的阅读!

透过《纽约时报》的镜头看强势女性

原文:https://towardsdatascience.com/strong-women-through-the-lens-of-the-new-york-times-f7f7468a2645?source=collection_archive---------35-----------------------

Python 中的 API 数据收集和文本分析

历史版画中的性别平等与表现研究

照片由贾科莫·费乐理Unsplash 上拍摄

这个项目的目标是通过情感分析、频繁术语可视化和主题建模的方式,调查过去 70 年间纽约时报中女性的代表性。

为了这次调查,我通过纽约时报开发者门户的归档 API 搜集了纽约时报的数据。首先,你必须在这里获得 API 密匙。免费的!NYT 只是喜欢调节防洪闸门的概念。由于这种类型的 API 适合批量数据收集,它不允许有效的预先过滤。如果您希望重新创建实验,请遵循 Github 上发布的 Jupyter 笔记本中的说明。如果你喜欢这篇文章的视频版本,你可以点击进入

分析管道。图片作者。弗里皮克的图标。

所有的指令、代码笔记本和结果也可以通过GitHub 上的 my project repository 进行访问,以实现更流畅的复制。

通过归档 API 收集数据,并使用 SpaCy 和 Gensim 进行主题建模

在我进一步进行分析之前,我决定对 2019 年 1 月至 2020 年 9 月期间《纽约时报》的大部分文章运行主题建模,以分析标题、关键词和前导段落。我的目标是区分最普遍的问题和持久的话题,以确保我的研究符合 NYT 的使命宣言,我没有歪曲他们的新闻风格。

这部分分析的数据收集蓝图受到了布蕾娜·赫罗尔德教程的启发。

让我们导入必要的工具和库:

**import** **os**
**import** **pandas** **as** **pd**
**import** **requests**
**import** **json**
**import** **time**
**import** **dateutil**
**import** **datetime**
**from** **dateutil.relativedelta** **import** relativedelta
**import** **glob**

确定分析的时间框架:

end = datetime.date.today()
start = datetime.date(2019, 1, 1)
print('Start date: ' + str(start))
print('End date: ' + str(end))

将数据按月分组:

months_in_range = [x.split(' ') **for** x **in** pd.date_range(start, end, freq='MS').strftime("%Y %-m").tolist()]

下面一组辅助函数(参见教程)通过 API 提取 NYT 数据,并保存到特定的 csv 文件中:

**def** send_request(date):
    *'''Sends a request to the NYT Archive API for given date.'''*
    base_url = 'https://api.nytimes.com/svc/archive/v1/'
    url = base_url + '/' + date[0] + '/' + date[1] + '.json?api-key=' + 'F9FPP1mJjiX8pAEFAxBYBg08vZECa39n'
    **try**:
        response = requests.get(url, verify=**False**).json()
    **except** **Exception**:
        **return** **None**
    time.sleep(6)
    **return** response

**def** is_valid(article, date):
    *'''An article is only worth checking if it is in range, and has a headline.'''*
    is_in_range = date > start **and** date < end
    has_headline = type(article['headline']) == dict **and** 'main' **in** article['headline'].keys()
    **return** is_in_range **and** has_headline

**def** parse_response(response):
    *'''Parses and returns response as pandas data frame.'''*
    data = {'headline': [],  
        'date': [], 
        'doc_type': [],
        'material_type': [],
        'section': [],
        'keywords': [],
        'lead_paragraph': []}

    articles = response['response']['docs'] 
    **for** article **in** articles: *# For each article, make sure it falls within our date range*
        date = dateutil.parser.parse(article['pub_date']).date()
        **if** is_valid(article, date):
            data['date'].append(date)
            data['headline'].append(article['headline']['main']) 
            **if** 'section' **in** article:
                data['section'].append(article['section_name'])
            **else**:
                data['section'].append(**None**)
            data['doc_type'].append(article['document_type'])
            **if** 'type_of_material' **in** article: 
                data['material_type'].append(article['type_of_material'])
            **else**:
                data['material_type'].append(**None**)
            keywords = [keyword['value'] **for** keyword **in** article['keywords'] **if** keyword['name'] == 'subject']
            data['keywords'].append(keywords)
            **if** 'lead_paragraph' **in** article:
                data['lead_paragraph'].append(article['lead_paragraph'])
            **else**:
                data['lead_paragraph'].append(**None**)
    **return** pd.DataFrame(data) 

**def** get_data(dates):
    *'''Sends and parses request/response to/from NYT Archive API for given dates.'''*
    total = 0
    print('Date range: ' + str(dates[0]) + ' to ' + str(dates[-1]))
    **if** **not** os.path.exists('headlines'):
        os.mkdir('headlines')
    **for** date **in** dates:
        print('Working on ' + str(date) + '...')
        csv_path = 'headlines/' + date[0] + '-' + date[1] + '.csv'
        **if** **not** os.path.exists(csv_path): *# If we don't already have this month* 
            response = send_request(date)
            **if** response **is** **not** **None**:
                df = parse_response(response)
                total += len(df)
                df.to_csv(csv_path, index=**False**)
                print('Saving ' + csv_path + '...')
    print('Number of articles collected: ' + str(total))

让我们仔细看看助手函数:

  • send_request(date) 在给定的日期将请求发送到存档中,转换成 json 格式,返回响应。
  • is_valid(article,date) 检查文章是否在请求的时间范围内,确认标题的存在,并返回 is_in_rangehas_headline 结论。
  • parse _ response(response)将响应转换成数据帧。 data 是一个字典,它包含我们的数据帧的列,这些列最初是空的,但是会被这个函数追加。该函数返回最终的数据帧
  • get_data(dates) ,其中date对应于用户指定的范围,利用 send_request()parse_response() 函数。将标题和其他信息保存到。csv 文件,范围内每年每月一个文件。

一旦我们获得了该范围内每年的每月 csv 文件,我们就可以将它们连接起来供将来使用。glob 库是一个很好的工具。确保到 headlines 文件夹的路径与代码中的路径匹配。我使用了相对路径,而不是我的绝对路径。

*# get data file names*
path = "headlines/"
filenames = glob.glob("*.csv")

dfs = []
print(filenames)
**for** filename **in** filenames:
    dfs.append(pd.read_csv(filename))

*# Concatenate all data into one DataFrame*
big_frame = pd.concat(dfs, ignore_index=**True**)

big_frame 是一个数据帧,它将标题文件夹中的所有文件连接成一个帧。这是预期的输出:

拉了 135954 篇文章及其数据。

现在,我们为主题建模做好准备。以下分析的目的是对过去一年半《纽约时报》文章的标题、关键词和前导段落进行主题建模。我想确保标题与介绍性段落和关键词一致。

导入工具和库:

**from** **collections** **import** defaultdict  
**import** **re**, **string   #regular expressions**
**from** **gensim** **import** corpora # this is the topic modeling library
**from** **gensim.models** **import** LdaModel

让我们仔细看看:

  • defaultdict 用于统计唯一单词及其出现的次数。
  • restring 在我们寻找文本中的匹配时很有用,无论是完整的还是模糊的。如果你对文本分析感兴趣,正则表达式会经常出现;这里有一个方便的工具来练习这些。
  • gensim 是我们要用来做主题建模的库。一旦你把必要的依赖关系整理出来,它就是用户友好的。

因为我们正在查看数据帧的三个不同列,所以将实例化语料库的三个不同实例:保存标题的语料库、关键字的语料库和引导段落的语料库。这意味着是一个健全的检查,以确保标题和关键字和引导段落与文章的内容一致。

big_frame_corpus_headline = big_frame['headline']
big_frame_corpus_keywords = big_frame['keywords']
big_frame_corpus_lead = big_frame['lead_paragraph']

为了使文本数据可用,需要对其进行预处理。一般来说,它看起来像这样:小写和标点符号删除,词干,词汇化和标记化,然后停用词删除和矢量化。前四个操作显示为一个群集,因为这些操作的顺序通常取决于数据,在某些情况下,交换操作的顺序可能是有意义的。

文本预处理步骤。图片作者。Freepik 的图标

先说预处理。

**from** **nltk.corpus** **import** stopwordsheadlines = [re.sub(r'[^\w\s]','',str(item)) **for** item **in** big_frame_corpus_headline]keywords = [re.sub(r'[^\w\s]','',str(item)) **for** item **in** big_frame_corpus_keywords]lead = [re.sub(r'[^\w\s]','',str(item)) **for** item **in** big_frame_corpus_lead]stopwords = set(stopwords.words('english')) 
# please note: you can append to this list of pre-defined stopwords if needed

更多预处理:

headline_texts = [[word **for** word **in** document.lower().split() **if** word **not** **in** stopwords] **for** document **in** headlines]keywords_texts = [[word for word in document.lower().split() if word not in stopwords] for document in keywords]lead_texts = [[word for word in document.lower().split() if word not in stopwords] for document in lead]

删除不常用的单词:

frequency = defaultdict(int)
for headline_text in headline_texts:
    for token in headline_text:
         frequency[token] += 1
for keywords_text in keywords_texts:
    for token in keywords_text:
         frequency[token] += 1
for lead_text in lead_texts:
    for token in lead_text:
         frequency[token] += 1

headline_texts = [[token for token in headline_text if frequency[token] > 1] for headline_text in headline_texts]
keywords_texts = [[token for token in keywords_text if frequency[token] > 1] for keywords_text in keywords_texts]
lead_texts = [[token for token in lead_text if frequency[token] > 1] for lead_text in lead_texts]dictionary_headline = corpora.Dictionary(headline_texts)
dictionary_keywords = corpora.Dictionary(keywords_texts)
dictionary_lead = corpora.Dictionary(lead_texts)headline_corpus = [dictionary.doc2bow(headline_text) for headline_text in headline_texts]
keywords_corpus = [dictionary.doc2bow(keywords_text) for keywords_text in keywords_texts]
lead_corpus = [dictionary.doc2bow(lead_text) for lead_text in lead_texts]

让我们决定我们案例的最佳主题数量:

NUM_TOPICS = 5  
ldamodel_headlines = LdaModel(headline_corpus, num_topics = NUM_TOPICS, id2word=dictionary, passes=12)
ldamodel_keywords = LdaModel(keywords_corpus, num_topics = NUM_TOPICS, id2word=dictionary, passes=12)
ldamodel_lead = LdaModel(lead_corpus, num_topics = NUM_TOPICS, id2word=dictionary, passes=12)

结果如下:

topics_headlines = ldamodel_headlines.show_topics()
for topic_headlines in topics_headlines:
    print(topic_headlines)topics_keywords = ldamodel_keywords.show_topics()
for topic_keywords in topics_keywords:
    print(topic_keywords)topics_lead = ldamodel_lead.show_topics()
for topic_lead in topics_lead:
    print(topic_lead)

让我们将它们组织成数据帧:

word_dict_headlines = {};for i in range(NUM_TOPICS):
    words_headlines = ldamodel_headlines.show_topic(i, topn = 20)
    word_dict_headlines['Topic # ' + '{:02d}'.format(i+1)] = [i[0] for i in words_headlines]
pd.DataFrame(word_dict_headlines)for i in range(NUM_TOPICS):
    words_keywords = ldamodel_keywords.show_topic(i, topn = 20)
    word_dict_keywords['Topic # ' + '{:02d}'.format(i+1)] = [i[0] for i in words_keywords]
pd.DataFrame(word_dict_keywords)for i in range(NUM_TOPICS):
    words_lead  = ldamodel_lead.show_topic(i, topn = 20)
    word_dict_lead ['Topic # ' + '{:02d}'.format(i+1)] = [i[0] for i in words_lead]
pd.DataFrame(word_dict_lead)

请记住:即使算法可以将单词分类到相应的主题中,仍然要靠人类来解释和标记它们。

话题建模结果。图片作者。弗里皮克的图标。

出现了各种各样的话题。它们在我们的社会中都是非常严肃和重要的。在这项特殊的研究中,我们将调查性别表征。

1950 年至今:数据收集和关键词分析。

我们将使用前面提到的助手函数来获取从 1950 年 1 月 1 日到现在(即 2020 年 9 月)的数据。我建议使用较小的时间增量,例如十年,以防止 API 超时。

数据将被收集到 headlines.csv 中,然后使用上述方法连接成一个数据帧。一旦你得到了你辛辛苦苦得到的数据框架,我建议把它腌制一下以备后用:

import pickle
with open('frame_all.pickle', 'wb') as to_write:
    pickle.dump(frame, to_write)

以下是您提取腌制文件的方法:

with open('frame_all.pickle', 'rb') as read_file:
    df = pickle.load(read_file)

发现的文章总数与 70 年时间范围内的相关文章。图片作者。Slidesgo 模板。

让我们将日期列转换成日期时间格式,这样就可以按时间顺序对文章进行排序。我们也将删除空值和重复。

df['date'] = pd.to_datetime(df['date'])df = df[df['headline'].notna()].drop_duplicates().sort_values(by='date')df.dropna(axis=0, subset=['keywords'], inplace = True)

查看相关关键词:

import ast
df.keywords = df.keywords.astype(str).str.lower().transform(ast.literal_eval)keyword_counts = pd.Series(x for l in df['keywords'] for x in l).value_counts(ascending=False)len(keyword_counts)

58298唯一关键字。

我用自己的个人判断来确定哪些关键词与强势女性及其代表性的话题相关:政治、社会活动、企业家精神、科学、技术、军事成就、体育突破和女性领导力。这种分析绝不意味着将任何群体或个人排除在女强人的概念之外。我乐于接受补充和建议,所以请不要犹豫,如果你认为有什么事情可以做,使这个项目更加全面。快速提醒如果您发现单元格中的代码由于格式问题难以复制,请参考我的项目资源库中的代码和说明。

project_keywords1 = [x for x in keyword_counts.keys() if 'women in politics' in x 
                 or 'businesswoman' in x  
                 or 'female executive' in x 
                 or 'female leader' in x 
                 or 'female leadership' in x 
                 or 'successful woman' in x 
                 or 'female entrepreneur' in x
                 or 'woman entrepreneur' in x 
                 or 'women in tech' in x 
                 or 'female technology' in x 
                 or 'female startup' in x 
                 or 'female founder' in x ]

上面是一个相关关键字的示例查询。关于相关关键词搜索和文章标题提取的更详细说明可以在本笔记本中找到。

现在,让我们来看看与从政女性有关的头条新闻。

首先,我们通过小写来规范化它们:

df['headline'] = df['headline'].astype(str).str.lower()

检查包含诸如女性、政治和权力等词汇的标题:

wip_headlines = df[df['headline'].str.contains(('women' or 'woman' or 'female')) & df['headline'].str.contains(('politics' or 'power' or 'election'))]

‘WIP’代表‘从政的妇女’。

我们的搜索只返回了 185 个标题。让我们看看关键字来补充这一点。

df['keywords'].dropna()
df['keywords_joined'] = df.keywords.apply(', '.join)
df['keywords_joined'] = df['keywords_joined'].astype(str)
import re
wip_keywords = df[df['keywords_joined'].str.contains(r'(?=.*women)(?=.*politics)',regex=True)]

妇女参政:结果数据框架

上面的数据框架包含了基于相关关键词的 2579 篇文章。我们将对关键字和标题数据帧执行外部连接,以获得更全面的数据:

wip_df = pd.concat([wip_headlines, wip_keywords], axis=0, sort = True)

利用同样的技术,我们将能够获得更多关于女性在军事、科学、体育、创业和其他领域成就的数据。例如,如果我们要寻找关于女权主义的文章:

feminist_keywords = df[df['keywords_joined'].str.contains(r'(?=.*women)(?=.*feminist)',regex=True)]

基于关键词搜索的文章:女权主义

metoo 机芯:

metoo_keywords = df[df['keywords_joined'].str.contains(r'(?=.*women)(?=.*metoo)(?=.*movement)',regex=True)]

正则表达式和模糊匹配允许几乎无限的可能性。您可以在本笔记本中查看更多查询。

所有查询完成后,最终的数据框架将在 GitHub 和本文的代码笔记中被进一步称为 project_df

我们来看一下历年文章分布:

ax = df.groupby(df.date.dt.year['headline'].count().plot(kind='bar', figsize=(20, 6))
ax.set(xlabel='Year', ylabel='Number of Articles')
ax.yaxis.set_tick_params(labelsize='large')
ax.xaxis.label.set_size(18)
ax.yaxis.label.set_size(18)
ax.set_title('Total Published Every Year', fontdict={'fontsize': 24, 'fontweight': 'medium'})
plt.show()

ax = project_df.groupby('year')['headline'].count().plot(kind='bar', figsize=(20, 6))
ax.set(xlabel='Year', ylabel='Number of Articles')
ax.yaxis.set_tick_params(labelsize='large')
ax.xaxis.label.set_size(18)
ax.yaxis.label.set_size(18)
ax.set_title('Articles About Strong Women (based on relevant keywords) Published Every Year', \
             fontdict={'fontsize': 20, 'fontweight': 'medium'})
plt.show()

如果我们把这两张图叠加起来,蓝色的几乎消失了:

与随着时间的推移而发表的大量文章相比,基于关键词和标题的相关出版物几乎是不可见的。

对妇女问题的报道似乎不多。我认为这可能是由于这些关键字并不总是正确编码的事实:有些不是丢失了就是误导了,因此使得研究人员更难通过 Archive API 找到想要的资料。

通过我的分析,我有了一个有趣的发现。根据对 n-grams 的分析,在 20 世纪 50 年代初,多次提到妇女的职业机会。他们中的许多人从大学毕业成为医生,以便加入海军。我把这种宣传的激增归因于第二次世界大战的后果:妇女被鼓励加入劳动大军,以补充军队的努力。还记得铆钉工罗西的海报吗?

这些剪报是通过 NYT 出版物档案馆获得的。作者利用这些剪报创作了这幅图像。

尽管在那个没有太多机会向女性敞开的时代,看到女性可以获得这样的机会令人温暖和振奋,但我真的希望这不是因为战争。

N-grams,WordCloud 和情感分析。

要了解标题中的总体术语频率:

from sklearn.feature_extraction.text import CountVectorizerword_vectorizer = CountVectorizer(ngram_range=(1,3), analyzer='word')
sparse_matrix = word_vectorizer.fit_transform(corpus)
frequencies = sum(sparse_matrix).toarray()[0]
ngram_df_project = pd.DataFrame(frequencies, index=word_vectorizer.get_feature_names(), columns=['frequency'])from wordcloud import WordCloud, STOPWORDS
all_headlines = ' '.join(project_df['headline'].str.lower())stopwords = STOPWORDS
stopwords.add('will')
# Note: you can append your own stopwords to the existing ones.wordcloud = WordCloud(stopwords=stopwords, background_color="white", max_words=1000, width = 480, height = 480).\
generate(all_headlines)plt.figure(figsize=(20,10))
plt.imshow(wordcloud)
plt.axis("off");

上面的代码创建的 WordCloud:最常用的术语以更大的字体显示。

我们还可以根据各种时间框架或特定关键字等特征创建单词云。参考笔记本获取更多视觉效果。

先说情绪分析。我们将使用 NLTK 的 Vader 库来分析与标题相关联的情感 。我们真的能在写文章的时候了解记者们对某个问题的感受吗?

import nltk 
nltk.download('vader_lexicon')from nltk.sentiment.vader import SentimentIntensityAnalyzer as SIAsia = SIA()
results = []for line in project_df.headline:
    pol_score = sia.polarity_scores(line)
    pol_score['headline'] = line
    results.append(pol_score)print(results[:3])

输出:

[{'neg': 0.0, 'neu': 0.845, 'pos': 0.155, 'compound': 0.296, 'headline': 'women doctors join navy; seventeen end their training and are ordered to duty'}, {'neg': 0.18, 'neu': 0.691, 'pos': 0.129, 'compound': -0.2732, 'headline': 'n.y.u. to graduate 21 women doctors; war gave them, as others, an opportunity to enter a medical school'}, {'neg': 0.159, 'neu': 0.725, 'pos': 0.116, 'compound': -0.1531, 'headline': 'greets women doctors; dean says new york medical college has no curbs'}]

作为数据框架的情感:

sentiment_df = pd.DataFrame.from_records(results)

dates = project_df['year']
sentiment_df = pd.merge(sentiment_df, dates, left_index=True, right_index=True)

上面的代码允许我们为自己的情绪设定一个时间表。为了简化情感分析,我们将为积极、消极和中立创建一些新的类别。

sentiment_df['label'] = 0
sentiment_df.loc[sentiment_df['compound'] > 0.2, 'label'] = 1
sentiment_df.loc[sentiment_df['compound'] < -0.2, 'label'] = -1
sentiment_df.head()

要可视化整体情绪分布:

sentiment_df.label.value_counts(normalize=True) * 100

图片作者。Slidesgo 模板。

要可视化情绪随时间的变化:

sns.lineplot(x="year", y="label", data=sentiment_df) 
plt.show()

由于问题的复杂性,情绪波动很大

如你所见,情绪波动。这一点都不意外,因为女性问题通常包含沉重的主题,如暴力和虐待。在这些情况下,我们预计市场情绪会偏向负面。

我创建了一个 Tableau 仪表板 ,观众可以在那里与可视化互动。可通过我的 Tableau 公众号获取。这个仪表板展示了几十年来关键词的分布情况。

图片作者。

结论

多年来,《纽约时报》在性别平等代表性方面取得了显著进步。如果让我提一个建议,我会推荐增加关键词列表。当我们进一步探究存档 API 的过去时,更全面、更强大的关键字会有助于搜索。

重要的是继续展示女性领导力,直到它变成正义领导力。想象一下这个世界,不再需要形容词“女性”来描述成就,因为它变得多余了。想象一下这个世界,没有“女医生”或“女工程师”:只有医生和工程师。创始人和政治家。企业家、科学家和开拓者。作为一个社团,我们的目标是为不同群体持有的这些头衔建立一个坚实的心智模型。通过不断提醒我们自己和我们周围的社会,任何性别或国籍都不能被排除在这些机会之外,我们可以共同实现这一目标。

基于张量流概率的结构时间序列预测:铁矿产量

原文:https://towardsdatascience.com/structural-time-series-forecasting-with-tensorflow-probability-iron-ore-mine-production-897d2334c72b?source=collection_archive---------9-----------------------

张量流概率结构时间序列的贝叶斯结构时间序列预测

图片:https://unsplash.com/photos/-subrrYxv8A

介绍

IRon 矿石 是世界上交易量最大的商品之一。作为钢铁生产的主要投入,它为全球最大的金属市场的交易提供了基础,并在全球干散货贸易中占据最大份额。

不出所料,铁矿石生产始于矿山。作为实物或金融交易商,了解铁矿石市场的基本供需性质至关重要。铁矿石等级(质量)差异不仅对现货和远期合约定价有显著影响,而且对工厂的杂质罚款也有显著影响。基本供求关系的失衡可能导致铁矿石价格大幅上涨。预测最大铁矿石出口国的铁矿石产量以便预测全球铁矿石供应,这在投机现货、期货和污染物罚款价格变动时非常有用。

问题

在本文中,我们将使用 TensorFlow Probability 的结构时间序列 (STS)框架开发一个预测模型,以预测巴西主要铁矿的总产量。

巴西是全球第二大铁矿石出口国。如上所述,巴西供应的重大变化会对铁矿石价格产生影响。此外,巴西铁矿石通常品位很高,杂质含量很低。因此,巴西铁矿石的相对供应会对钢厂收取的杂质罚款价格产生影响。如果由于巴西矿山供应短缺,高污染铁矿石主导了全球供应,污染物的价格惩罚可能会急剧上升。因此,预测巴西的产量有助于理解上述动态。

本文中使用的代码遵循类似于 tensor flow Probability tutorial(tensor flow 作者版权所有 2019)中的结构时间序列建模中概述的逻辑。

为什么要张量流概率 STS?

当处理一个时间序列预测问题时,投入时间去理解你想要预测的变量的复杂性是至关重要的。在设计任何模型的架构之前,平稳性、季节性、分布和外生特征关系只是要记住的许多考虑因素中的一小部分。

结构时间序列模型(有时称为贝叶斯结构时间序列)表示为趋势、季节模式、周期和残差等组件的总和:

这些单独的组成部分本身是由结构假设定义的时间序列。在时间序列中配置每个组件的能力使得 TFP 的 STS 库在我们的时间序列预测问题的上下文中特别相关,因为它使我们能够将特定领域的知识编码到我们的模型中,例如交易者和采矿操作员的专业知识以及已知事件。

这对我们的问题有什么帮助

矿山产量通常表现为系统行为,可以建模为结构时间序列。就我们的问题而言,我们知道许多矿井在 12 月会关闭两周进行定期维护。这种可重复的模式可以作为季节性组件添加到结构化时间序列模型中。我们还知道,铁矿石和其他露天采矿呈现出明显的季节性模式,与降雨量密切相关,在暴雨期间,排水泵不堪重负,导致产量减少。

在我们的问题的背景下,结构时间序列模型特别有用的是,它们采用概率方法来模拟时间序列问题,即,它们返回后验预测分布,我们可以对其进行采样,不仅提供预测,还提供量化模型不确定性的方法。

STS 模型的另一个令人兴奋且非常有用的特性是,最终的模型可以被分解为多个独立组件的集合。然后可以绘制这些组件,让我们深入了解它们各自对因变量(Y-hat)的影响,并更深入地了解全局时间序列问题:

时间序列分解示例摘自https://blog . tensor flow . org/2019/03/structural-time-series-modeling-in . html

先决条件

在我们开始之前,值得注意的是张量流概率有一组特定的依赖关系。此外,张量流作为张量流概率库的依赖项,需要单独安装:

[## 释放张量流/概率

今天就创建您的免费 GitHub 帐户,订阅这个新版本库,并与 50…

github.com](https://github.com/tensorflow/probability/releases)

pip install --upgrade tensorflow-probability

或者,你可以使用谷歌的合作实验室 (Colab),他们友好地在 Colab 中完全免费地提供托管运行时(CPU、GPU 和甚至 TPU!)受制于内存限制。

结构时间序列模型

让我们开始吧。

数据

我们首先检查我们的矿山负荷(产量)数据,其观察值是每个矿山的每周总产量(百万公吨),汇总了所有主要的巴西铁矿石生产商:

# Imports
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns
import tensorflow_probability as tfp
import tensorflow as tffrom statsmodels.tsa.seasonal import seasonal_decomposedf = pd.read_excel(
    '/content/bloomberg_weekly_io_output_brazil.xlsx',
    header = 1, 
    index_col = 0,
    parse_dates = True)# Loadings
df.plot(figsize=(16, 8))
plt.title(‘Weekly Iron Ore Output, Metric Tonnes’)
plt.ylabel(‘Loadings, Mt’)

每周矿山装载量(百万吨)

如果我们仔细检查观察到的输出时间序列,我们可以隐约看到本文前面提到的一些结构组件,我们可以尝试在 STS 模型中进行编码:

  • 明显的季节性模式。从每个周期的振幅和频率来判断,有理由认为这是加性季节性(定义如下)。
  • 2018 年末/2019 年初除外,呈线性趋势。
  • 在圣诞节期间,当矿井通常关闭进行定期维护时,产量明显下降。
  • 噪音程度,可能与天气、罢工、设备故障等相关。

时间序列分解

我们可以通过尝试将时间序列分解成其组成部分来验证时间序列中的某些上述成分。我们将使用 statsmodels 时间序列分析库来执行分解,并根据我们的时间序列图中观察到的行为选择一个“附加”模型作为季节成分。作为参考,附加季节性估计为:

将“iron _ ore _ Brazil”Pandas 系列传递给我们从 statsmodels 导入的 seasonal_decompose 方法会生成以下图形:

tsa = seasonal_decompose(
    df[‘iron_ore_brazil’],model=’additive’
).plot()

铁矿石产量吨—季节性分解

通过检查,我们可以立即识别(大部分)线性趋势和季节性成分。如果我们仔细观察频率和幅度,你可以看到在冬季期间每年的矿井产量减少。

通过对残差的检验,很明显,在这个时间序列中存在其他关系,这些关系不能仅由季节和趋势元素来解释。然而,残差中的方差保持相当恒定,并且在定义的界限内。在定义我们的结构组件时,这是需要牢记的有用信息。

“啊哈!”我听到你在这一刻哭泣。“如果这是 STS 模型的,为什么要分解时间序列?”。有两个原因:

  1. 它有助于识别和理解时间序列中的各种基本成分:趋势、季节性、周期和无法解释的方差,这反过来可以告诉我们如何配置 STS 模型先验的输入参数。
  2. TFP 的 STS 模型通过变分推理 (VI)或哈密顿蒙特卡罗(HMC) 方法对数据进行训练;
# Fit model to observed data with HMC
tfp.sts.fit_with_hmc(
    model, observed_time_series, num_results=100, num_warmup_steps=50,
    num_leapfrog_steps=15, initial_state=None, initial_step_size=None,
    chain_batch_shape=(), num_variational_steps=150, variational_optimizer=None,
    variational_sample_size=5, seed=None, name=None
)# Or, fit model to data with VI
tfp.sts.build_factored_surrogate_posterior(
    model, batch_shape=(), seed=None, name=None
)

一般来说,这两种方法在高维问题上都是计算密集型的(特别是在 HMC 的情况下),并且对调整非常敏感。在配置 STS 组件时,明智地选择输入参数有助于节省时间和资源,并提高后验分布的准确性。

解释 HMC 和 VI 背后的数学原理超出了本文的范围,但是你可以在这里找到更多关于 HMC 和 VI 的信息。

定义我们的结构组件

我们现在可以定义 STS 模型的各种组件,并根据我们对数据生成过程的了解来配置它们。让我们从季节性因素开始:

季节性:

铁矿石产量(吨):季节性因素

我们将结构时间序列模型的季节性输入定义如下:

# Create train dataset
_train = df[‘iron_ore_brazil’][df.index < ‘2018–01–01’]
_dates = train.index# Test data
test = df[‘iron_ore_brazil’][df.index >= ‘2018–01–01’]# TensorFlow requires an an (N, 1) float tensor
train = _train.to_numpy().reshape(-1, 1))# Seasonal effect 1: weekly cycle as identified in decomp.
weekly_cycle = tfp.sts.Seasonal(
    num_seasons=52, # 52 weeks in year
    observed_time_series=train,
    allow_drift=True,
    name=’weekly_effect’)# Seasonal effect 2: month of year to capture winter drop in output.
monthly_affect = tfp.sts.Seasonal(
    num_seasons=12, # 12 months in year
    num_steps_per_season=4, # assumed 4 weeks in every month
    observed_time_series=train,
    name=’month_of_year_effect’)

tfp.sts.Seasonal 模型提供的一个有价值的特性是能够将【漂移】添加到季节性影响中。此参数允许每个季节的影响按照高斯随机游走从一个事件演变或“漂移”到下一个事件(具体来说,样本取自由平均值和方差加上一些漂移项定义的正态分布)。如果我们对季节成分的先验分布的均值和方差有信心,我们可以在模型中自己配置它:

monthly_effect = tfp.sts.Seasonal(
    num_seasons=12, # 12 months in year
    num_steps_per_season=4, # assumed 4 weeks in month
    observed_time_series=train,
    drift_scale_prior=tfd.Normal(loc=1., scale=0.1), # define priors
    initial_effect_prior=tfd.Normal(loc=0., scale=5.),
    name=’month_of_year_effect’)

现在,通过设置参数“allow_drift=True ”,我们可以让模型为我们处理这个问题。

趋势分量

铁矿石产量(吨)趋势成分

对我们铁矿产量的目测显示(2018 年末/2019 年初除外)一致的线性趋势。我们可以用一个localineartrend模型来模拟这种行为。

局部线性趋势模型将时间序列趋势表示为某个量级(level)和slope.的组合,这些元素中的每一个都通过高斯随机游走随时间演变:

level[t] = level[t-1] + slope[t-1] + Normal(0., level_scale)
slope[t] = slope[t-1] + Normal(0., slope_scale) 

在我们的问题中,局部线性趋势组件的实现非常简单:

# Add trend
trend = tfp.sts.LocalLinearTrend(
    observed_time_series=train,
    name='trend')

在选择如何对趋势组件建模时,需要牢记的一个重要考虑因素是模型的选择,这取决于问题的性质。在我们的时间序列问题的情况下,观察到的趋势随着时间的推移相对稳定,并逐渐演变,即它没有显示任何强烈的非线性行为。因此,我们选择代表这种趋势的模型是合理的,但是这种模型可以在更长的预测期内产生高度不确定性的预测。

替代方案是什么?

众所周知,大多数时间序列都具有固有的时间结构,其中后续观测依赖于时间上的前 n 个观测,即自相关。因此,明智的选择可能是使用 TFP STS 的SemiLocalLinearTrend模型来模拟趋势。在半局部线性趋势模型中,slope分量按照一阶自回归过程演化。因此,AR 过程可以解释时间序列中的自相关(数量级为 n )效应,并且通常会导致更长时间内更确定的预测。

残差:

铁矿石产量(吨)剩余部分

如前所述,在我们检查季节分解图的过程中,我们的时间序列中的残差看起来相对一致,表明它们可能是稳定的,即它们在一段时间内保持恒定的方差,不表现出偏差或异方差等。因此,我们可以在 sts 中表示剩余行为。 自回归 模型:

*# Residuals
residuals = tfp.sts.Autoregressive(
    order=1,
    observed_time_series=train,
    coefficients_prior=None,
    level_scale_prior=None,
    initial_state_prior=None,
    name='residuals_autoregressive')*

与其他组件一样,对于完全贝叶斯方法,应该指定先验coefficients_priorlevel_scale_priorinitial_state_prior。由于我们没有指定先验,tensor flow Distributions(tfd)MultivariateNormalDiag 实例用作系数的默认先验,并基于输入时间序列为级别和初始状态构建启发式先验。

定义模型

我们现在可以使用 tfp.sts.Sum 类来定义我们的结构化时间序列模型。这个类使我们能够从上面定义的组件中定义结构化时间序列模型的组合规范:

*model = tfp.sts.Sum(
    components=[
        trend,
        weekly_cycle,
        monthly_effect,
        residuals],
    observed_time_series=train)* 

拟合模型

我们现在将我们的模型拟合到观察到的时间序列,即我们的铁矿石产量。不同于传统的时间序列预测架构,例如线性回归模型,其通过最大似然估计来估计系数,或者,在规模的更强大的一端,LSTM 学习将一系列过去的观察值作为输入映射到输出观察值的函数,STS 模型学习 分布 即后验分布。

我们将使模型与数据相匹配,并使用变分推理建立后验预测分布。简而言之,VI 拟合了我们定义的模型参数的一组近似后验分布(针对每种成分),并通过最小化称为负证据下限(ELBO)的变分损失函数来优化这些分布:

*# VI posterior 
variational_posteriors = tfp.sts.build_factored_surrogate_posterior(
    model=loadings_model)# Build and optimize the variational loss function (ELBO).
@tf.function()
def train_sts_model():
  elbo_loss_curve = tfp.vi.fit_surrogate_posterior(
      target_log_prob_fn=loadings_model.joint_log_prob(
      observed_time_series=training_data),
  surrogate_posterior=variational_posteriors,
  ptimizer=tf.optimizers.Adam(learning_rate=.1),
  num_steps=200)
  return elbo_loss_curve# Plot KL divergence
elbo = train_sts_model()()
plt.plot(elbo_loss_curve)
plt.show()*

证据图下限优化(ELBO 最小化 Kullbeck-Leibler 分歧)

我们当中精明的人可能已经注意到了装修工。它接受一个函数,在这个例子中是我们的 STS 模型,作为一个参数,并将它编译成一个可调用的 TensorFlow 图。关于 TensorFlow 如何工作和通过使用图形处理操作的有趣介绍可以在这里找到。

预测

现在是有趣的部分。在检查损失函数收敛后,我们可以进行预测。我们从变分后验数据中提取轨迹(样本),并通过将这些作为参数传递给[tfp.sts.forecast(](https://www.tensorflow.org/api_docs/python/tf/function))来构建预测。给定我们的模型、观察到的时间序列和我们的采样参数, forecast() 会针对所需数量的预测步骤返回未来观察值的预测分布:

*# Draw traces from posterior
traces__ = variational_posteriors.sample(50)# No timesteps to forecast
n_forecast_steps = len(test)# Build forecast distribution over future timesteps
forecast_distribution = tfp.sts.forecast(
    loadings_model,
    observed_time_series=train,
    parameter_samples=traces__
    num_steps_forecast=n_forecast_steps)# Draw fcast samples
num_samples=50# Assign vars corresponding to variational posterior
fcst_mu, fcast_scale, fcast_samples=(
    forecast_distribution.mean().numpy()[..., 0],
    forecast_distribution.stddev().numpy()[..., 0],
    forecast_distribution.sample(num_samples).numpy()[..., 0])*

然后我们可以想象我们的预测:

铁矿石产量预测值与观察值(吨)

验证模型性能

乍一看,我们可以观察到该模型(除了 2019 年的不可抗力)在预测我们的矿山产量方面表现相当合理。通过计算平均绝对误差,我们可以根据观察到的数据点验证我们预测的准确性。然而,从商业角度来看,考虑到标签的规模,即以百万吨为单位,计算和呈现平均百分比误差(MAPE)更有意义,因为这对非数据科学人员来说更具可解释性和意义:

*# Remember to check for div by zero errors first
print(np.mean(np.abs((test- fcast_mu) / test)) * 100)>>> 13.92*

在 13.92% MAPE 的情况下,很明显,我们的铁矿石产量模型在模拟数据生成分布方面做得很好,尤其是在我们没有完全调整模型参数的情况下。

验证结构组件贡献

我们可以进一步了解我们的模型的拟合,并通过将其分解为各自的时间序列(再次)来验证我们的单个结构组件的贡献。我们使用[tfp.sts.decompose_by_component](https://www.tensorflow.org/probability/api_docs/python/tfp/sts/decompose_by_component)来执行该操作,该操作返回单个分量后验分布的collections.OrderedDict,映射回其各自的观察模型:

*# Dist. over individual component outputs from posterior (train)
component_dists = tfp.sts.decompose_by_component(
    loadings_model,
    observed_time_series=train,
    parameter_samples=traces__)# Same for fcast.
forecast_component_dists = tfp.sts.decompose_forecast_by_component(
    loadings_model,
    forecast_dist=loadings_model_distribution,
    parameter_samples=traces__)*

经过一点处理后,我们可以绘制分解时间序列的输出,得到下面的图表:

按成分、训练和预测分布的铁矿石结构时间序列分解

观察、批评&进一步分析

对我们的分解模型的检查为进一步分析提出了一些要点:

  1. 我们预测后验分布的均值和标准差为我们提供了每个时间步的边际不确定性。考虑到这一点,我们可以观察到,我们的模型对我们的趋势成分对时间序列的贡献充满信心,展示了直到 2018 年模型不确定性复合的稳定轮廓。为了应对这一点,我们可以通过将其建模为 半对数趋势 模型来提高趋势分量的准确性,这允许slope分量作为自回归过程发展。**
  2. 我们的模型对每周每月的季节性成分贡献有信心,在每个时间步显示一致的输出,表明我们的配置是正确的。虽然一致,但我们的月度部分的不确定性明显更高。我们有可能通过增加知情的先验知识(即initial_state_prior等)来改进这些组件。**
  3. 有趣的是,我们的自回归成分贡献很小。我们的模型对此也相当有信心,表明残差不能用 AR 过程来解释。我们可以探索使用 sts 添加外部特征,如当地天气/降水模式和铁矿石现货价格作为线性协变量。线性回归 **
  4. 我们可以通过使用马尔可夫链蒙特卡罗(MCMC)方法(即[tfp.sts.fit_with_hmc()](https://www.tensorflow.org/probability/api_docs/python/tfp/sts/fit_with_hmc),而不是使用 VI)将模型拟合到数据,从而获得更准确的后验概率。

结论

在本文中,我们看到了如何使用 TensorFlow Probability 的结构化时间序列库来开发贝叶斯结构化时间序列模型。此外,我们还探索了:

  • 如何定义和配置结构化时间序列模型组件?
  • 如何训练 STS 模型建立后验预测概率分布?
  • 如何对后验分布进行采样以进行时间序列预测?
  • 如何分解结构时间序列模型,以检查其各个组成部分的个别贡献。
  • 通过 TensorFlow Probability STS 提供的其他一些令人惊叹的模型,简要了解一些改进我们的 STS 模型的替代方法。

感谢您的阅读!

参考

在数据科学面试中组织您对案例研究问题的回答

原文:https://towardsdatascience.com/structure-your-answers-for-case-study-questions-during-data-science-interviews-a14a02d21e6c?source=collection_archive---------10-----------------------

Clem Onojeghuo 在 Unsplash 拍摄的照片

办公时间

自信地完成数据科学面试,第 4 部分

在我之前的文章中,我已经谈到了机器学习、统计和概率中需要准备的面试问题:

[## 准备面试的 20 个机器学习相关问题

自信地完成面试

towardsdatascience.com](/20-machine-learning-related-questions-to-prepare-for-interviews-93bcba72f911) [## 为数据科学面试做准备的 22 个统计问题

自信的钉钉数据科学访谈,第 2 部分

towardsdatascience.com](/22-statistics-questions-to-prepare-for-data-science-interviews-d5651a8b3c56) [## 数据科学面试的 12 个概率练习题

自信地完成数据科学面试,第 3 部分

towardsdatascience.com](/12-probability-practice-questions-for-data-science-interviews-2ec5230304d9)

我将在下一篇文章中讨论行为问题:

[## 为数据科学面试准备行为问题

自信地完成数据科学面试,第 5 部分

towardsdatascience.com](/prepare-behavioral-questions-for-data-science-interviews-96e97f13be15)

在本文中,我将重点介绍案例研究问题的准备工作。

在数据科学面试中,有时面试官会提出一系列业务问题,并讨论使用数据科学技术的潜在解决方案。这是数据科学面试中案例研究问题的一个典型例子。面试官可以根据候选人的表现,透彻了解候选人在批判性思维、商业智能、用模糊的商业问题解决问题的能力,以及数据科学模型和基本面的实际运用等方面的能力。相比之下,这里问的大多数问题都是开放式问题,没有一个正确的答案。了解回答这类问题的模式并组织你的答案是很有用的。本文将讨论帮助您在数据科学面试之前和面试期间更好地准备回答案例研究问题的策略。

面试前的方式

1、培养商业意识

如果你在面试前还有很多时间,或者如果你想提高你对商业智能的总体认识以及数据科学在商业环境中的应用,请关注科技公司的博客帖子,并开始定期阅读这些帖子。例如,我在微软、沃尔玛全球技术insta cart等公司学习数据科学。,中等。除了 Medium,一些公司喜欢拥有自己的博客网站或 YouTube 频道,如谷歌数据科学博客优步工程等。作为一名没有全职数据科学行业经验的应届毕业生,我发现自己从阅读这些博客帖子中受益匪浅。它指导我理解某些方法的应用,以解决现实世界的业务问题。它开阔了我的眼界,让我了解数据科学中最新的前沿研究技术。

除了特定公司的博客,你还可以研究特定的主题和阅读相关的文章。例如,如果您对计算客户终身价值感兴趣,Medium 上有许多很棒的文章,在不同的商业环境中讨论这个问题。此外, StellarPeers 是一个很棒的出版物,它发布文章讨论不同产品和业务问题的解决方案。

阅读博文时,不要在技术细节上浪费太多时间,试着通过回答以下问题总结你所学到的东西:

  • 这篇文章解决的商业问题是什么?
  • 有哪些方法?这些方法对我来说是新的吗?
  • 他们如何评价他们方法的性能?
  • 你怎么能把它推广到其他类似的商业问题呢?

2、知道正确的术语

熟悉业务指标、关键绩效指标(KPI):

轻松讨论常用解决方案:

  • 分类变量的正确处理:一键编码
  • 维度缩减:PCA
  • 处理缺失数据
  • 处理异常值
  • 随意推断技巧
  • 机器学习模型
  • 评估模型性能
  • 试验设计

了解常见问题:

  • 样本偏差:选择偏差,反应偏差
  • 内生性
  • 相关性和因果关系的区别
  • [统]多重共线性
  • 适配过度,适配不足

面试前

当你准备案例研究问题的时间有限时,做以角色为导向的研究来练习面试中可能被问到的潜在问题是很有用的。

1。对公司做调查:

面试官通常会问一些他们每天都会遇到的问题。在进行研究时,重点关注以下几个方面:

  • 关于公司的一般信息:浏览公司网站、Linkedin 页面等。,对公司有一个透彻的了解:比如,他们在什么行业?他们的产品有哪些?他们的产品可能存在哪些业务问题?
  • 浏览该公司的博客帖子,了解他们的数据科学家每天都在解决的问题以及他们的方法。总结一些他们经常用于解决特定业务问题的技巧。

2。对公司的技术团队进行研究:

  • 他们的数据科学家正在解决的问题:关注公司的技术博客文章。许多公司让他们的数据科学家、工程师分享他们的项目,讨论他们用技术细节解决的问题。阅读这些博客帖子将有助于您了解这些公司的业务挑战以及数据科学技能的现实应用。
  • 他们希望你加入团队后解决的问题:通读你所申请职位的职位描述。具体来说,通过分析工作资格,试着列出他们需要和渴望的所有技能。
  • 即使在同一家公司,不同团队的数据科学家的日常任务也可能大相径庭。如果你知道谁将是你的面试官,试着通过在 LinkedIn 上搜索来找出你的面试官现在在哪个团队工作,或者之前在哪个团队工作。然后问自己他们解决了什么业务问题,你的解决方案是什么。

面试的时候

在面试中,组织你的回答以最好地展示你解决问题的技巧和批判性思维能力是很重要的。

1、首先,在开始任何解决方案之前,先问清楚问题!

用数据科学技术解决业务问题通常是模糊的问题,如如何预测需求?如何通过市场活动增加收入等。首先问清楚问题是很重要的。根据您被问到的确切问题,您可以澄清:

  • 假设是什么?例如,如果你被问及如何降低客户流失率,从询问你正在评估的流失率的时间段开始。
  • 对可用的数据做出合理的假设:为了预测过去的订单,问面试官我们是否有过去一个月订单的历史数据。
  • 定义问题中的模糊词语:这非常重要,因为它将设定你答案的方向。比如问你 app 的这个新功能好不好,你首先要定义什么是“好”。“好”可以定义为吸引更多的客户、更高的用户参与度、更高的收入等。,视上下文而定。“好”在短期或长期可以是不同的。在开始解决这个问题之前,我们需要确保设定合理的目标。在其他情况下,我们可以在几个场景中阐述潜在的解决方案,而不是只关注一种情况。
  • 定义问题中的指标:如果问题中没有定义业务指标,您需要定义对目标具体而敏感的自己。例如,当我们在用户应用程序中评估新功能的性能时,我们可以将指标定义为用户转化率、用户参与时间等。
  • 重复你对问题的理解,问面试官你对问题的理解是否正确。你确保你走在正确的方向上,你将为自己赢得一些额外的时间来思考解决方案。

2、提出你的解决方案,从简单开始

明确问题后,你就可以开始提出你的解决方案了。展示您对数据科学工具包的了解:什么、如何以及为什么。总是从最简单的解决方案开始,并在更多的条件下改进它。例如,您可以从线性回归模型开始了解数据,对您正在解决的问题有一个模糊的印象,然后转向更复杂的模型,讨论功能的选择等。

3、总是解释你的解决方案背后的原因

答案本身并不是你答案中最重要的部分,你选择它的原因才是。总是陈述你为什么选择你的方法,为什么不选择其他可能的方法。比如在回答价格暴涨时你如何选择暴涨乘数的时候,你可以说我想用合成控制是因为网络效应,像 AB 测试这样的实验设计在这里不适用。陈述你选择的原因,验证你的答案,向面试官展示你对这个话题有透彻的理解。

4、评估你的解决方案:技术性和非技术性

如何评价你的提案?从技术指标开始,如模型准确度、精确度、分类模型的召回率、R 分数、回归模型的 MSE。将技术指标与旧模型或基线模型进行比较,看看这是否是一个改进。比较非技术指标,如上面讨论的业务指标,您的模型是否增加了收入。此外,讨论其他指标,如我们解释模型的难易程度,这一新功能如何影响用户体验,以及将模型部署到生产中的难度。

5、讨论权衡

  • 永远要意识到你的方法的潜在缺点。尝试讨论某些方法的利弊,并在彻底调查的基础上做出最终决定。
  • 讨论短期和长期利益之间的权衡。例如,一个市场活动是否会在短期内增加订阅量,并在长期内增加收入。设定一个短期或长期偏好不同的目标,可能会产生不同的解决方案。
  • 讨论不同小组之间的权衡。例如,三方使用优步饮食,即餐馆、承运人和食客。试着讨论你的提议对三方的影响。
  • 讨论在计算复杂性和可解释性、更快的结果、更精确的模型、进行实验的更高成本、更可靠的结果等方面的权衡。

6、知道你在说什么

面试官喜欢根据你的回答提出后续问题。例如,如果你提到我想在我的线性回归模型中加入正则化,他们可能会问你为什么?L1 正规化和 L2 正规化有什么区别,你会选择哪个?这是面试官了解你对模型或技术的基本理解的一种方式。

7、接受暗示

如果你偏离了他们想要的答案,好的面试官会给你提示。例如,如果你在谈论解决问题的方法 A,面试官可能会说,使用方法 A 可能会带来问题 B,你认为方法 C 怎么样?当你得到提示时,接受它!!!他们不是想骗你。

8、树立正确的心态

面试不是考试,尤其是当你面对没有一个正确答案的开放式问题时。向面试官展示你将广泛的商业问题转化为可操作的分析的思维过程是很重要的。如果您向他们展示您如何提炼业务问题、提出数据科学技能,并展示这些项目将如何影响您期望的目标,将会有所帮助。你可以想想你自己已经在公司工作了,你正在和你的同事讨论你所面临的问题的潜在解决方案。设置正确的心态有助于你减轻压力,展现你的真实表现。

9、面试时不要默默思考

这条规则适用于面试中提出的任何问题。永远在你的面试官面前展示你的想法和你的思考过程,即使一开始这并不是一个完美的解决方案。你可以根据提示或你的进一步思考来修改你的答案。面试时沉默从来都不是好事。如果你完全不知道如何回答一个问题,就从问一些澄清性的问题开始。

以上是我在准备数据科学面试案例研究问题时的所有提示。如果你有其他建议,请在下面留下评论。感谢您的阅读!

这是我所有博客帖子的列表。如果你感兴趣的话,可以去看看!

* [## 我的博客文章库

我快乐的地方

zzhu17.medium.com](https://zzhu17.medium.com/my-blog-posts-gallery-ac6e01fe5cc3) [## 阅读朱(以及媒体上成千上万的其他作家)的每一个故事

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

zzhu17.medium.com](https://zzhu17.medium.com/membership)*

构建您的数据科学项目

原文:https://towardsdatascience.com/structure-your-data-science-projects-6c6c8653c16a?source=collection_archive---------6-----------------------

数据科学项目结构

开发协作和可复制的数据科学项目

费利佩·费塔多在 Unsplash 上的照片

与软件开发相比,数据科学有一些关键的区别。例如,数据科学项目侧重于探索和发现,而软件开发通常侧重于实现一个明确定义的问题的解决方案。在定义软件产品的需求、理解客户需求的过程中,很少会出现不明确的地方,尽管对于数据驱动的解决方案来说,范围可能会发生变化。

您可以发现数据科学和软件开发之间的许多其他差异,但是这两个领域的工程师需要致力于一致且结构良好的项目布局。毕竟,数据科学项目像任何其他软件系统一样包含源代码,以构建模型本身的软件产品。结构化源代码和与项目相关的数据有很多好处。构建数据科学工作的主要优势包括:

  1. 跨数据科学团队的协作变得更加容易。当团队中的每个人都遵循相同的项目结构时,发现其他人所做的变更并促成这些变更就变得非常容易。
  2. 再现性。 模型应该是可再生的,不仅是为了跟踪模型版本,也是为了在模型失败的情况下容易地恢复到旧版本。以可重复的方式记录您的工作,可以确定新模型是否比以前的模型执行得更好。
  3. 效率。 我已经多次检查过旧的 jupyter 笔记本,以便为新项目重用一些功能。我可以凭经验告诉你,假设你有很好的记忆力,平均迭代十个笔记本,找到一段 20 行的代码可能会令人沮丧。以一致的结构提交我写的代码避免了自我重复和复制。
  4. 数据管理。原始数据应与中间数据和处理过的数据分开。这将确保从事该项目的任何团队成员都可以轻松地重现所构建的模型。找到在模型建立阶段之一中使用的各个数据集所花费的时间大大减少。

虽然要成功实现数据科学项目的可再现性,还需要许多其他的依赖因素,例如,如果您没有覆盖用于模型构建的原始数据,在下一节中,我将分享一些工具,它们可以帮助您开发一致的项目结构,从而促进数据科学项目的可再现性。

烹饪刀

Cookiecutter 是一个命令行工具,它从项目模板中创建项目。您可以创建自己的项目模板,也可以使用现有的模板。让这个工具如此强大的是,您可以轻松地导入模板,并且只使用最适合您的部分。

在这篇文章中,我将更多地谈论 cookiecutter 数据科学模板。安装简单明了。要安装,请运行以下命令:

pip install cookiecutter

要处理模板,只需使用命令行获取它:

cookiecutter https://github.com/drivendata/cookiecutter-data-science

该工具会询问一些配置选项,然后您就可以开始了。

项目结构如下所示:

├── LICENSE
├── Makefile           <- Makefile with commands like `make data` or    `make train`
├── README.md          <- The top-level README for developers using this project.
├── data
│   ├── external       <- Data from third party sources.
│   ├── interim        <- Intermediate data that has been transformed.
│   ├── processed      <- The final, canonical data sets for modeling.
│   └── raw            <- The original, immutable data dump.
│
├── docs               <- A default Sphinx project; see sphinx-doc.org for details
│
├── models             <- Trained and serialized models, model predictions, or model summaries
│
├── notebooks          <- Jupyter notebooks. Naming convention is a number (for ordering),the creator's initials, and a short `-` delimited description, e.g.
│                         `1.0-jqp-initial-data-exploration`.
│
├── references         <- Data dictionaries, manuals, and all other explanatory materials.
│
├── reports            <- Generated analysis as HTML, PDF, LaTeX, etc.
│   └── figures        <- Generated graphics and figures to be used in reporting
│
├── requirements.txt   <- The requirements file for reproducing the analysis environment
│
├── setup.py           <- makes project pip installable (pip install -e .) so src can be imported
├── src                <- Source code for use in this project.
│   ├── __init__.py    <- Makes src a Python module
│   │
│   ├── data           <- Scripts to download or generate data
│   │   └── make_dataset.py
│   │
│   ├── features       <- Scripts to turn raw data into features for modeling
│   │   └── build_features.py
│   │
│   ├── models         <- Scripts to train models and then use trained models to make
│   │   │                 predictions
│   │   ├── predict_model.py
│   │   └── train_model.py
│   │
│   └── visualization  <- Scripts to create exploratory and results oriented visualizations
│       └── visualize.py
│
└── tox.ini            <- tox file with settings for running tox; see tox.testrun.org

文件夹

生成的项目模板结构允许您为数据科学流程组织源代码、数据、文件和报告。这种结构简化了跟踪项目变更的过程。我将详细介绍五个文件夹:

  • 数据。数据应分段,以便将来重现相同的结果。你今天用来建立机器学习模型的数据可能与你将来拥有的数据不一样,也就是说。数据可能被覆盖,或者在最坏的情况下丢失。为了拥有可再生的机器学习管道,保持原始数据不变非常重要。原始数据的任何进展都应该被适当地记录下来,这就是数据文件夹发挥作用的地方。您不再需要将文件命名为 final_17_02_2020.csv、final2_17_02_2020.csv 来跟踪更改。
  • 车型。模型是机器学习管道的最终产品。它们应该存储在一致的文件夹结构下,以确保将来可以复制模型的精确副本。
  • 笔记本。许多数据科学项目都是在 Jupyter 笔记本上完成的,这让读者可以了解项目的流程。这些笔记本很可能充满了大量的功能和代码块,这使得创作者甚至忘记了代码块的功能。将您的功能、代码块和结果存储在单独的文件夹中,可以让您进一步细分项目,并便于在笔记本中遵循项目逻辑。
  • 报道。作为数据分析流程的一部分,数据科学项目不仅会生成模型,还会生成数字和图表。这些可以是平行线、条形图、散点图等。您应该存储生成的图形和数字,以便在需要时能够轻松地报告它们。
  • Src。 Src 文件夹是放置管道中使用的函数的地方。这些功能可以像软件产品一样根据它们在功能上的相似性来存储。您可以轻松测试和调试您的功能,而使用它们就像将它们导入笔记本一样简单。

为了演示如何使用这个工具,我修改了我之前参与的一个项目。存储库并不是为机器学习流程而优化的,尽管你可以很容易地理解按照链接组织你的数据科学项目的想法。

Makefile

GNU make 是一个控制程序的可执行文件和非源文件生成的工具。它利用 makefiles 列出所有要构建的非源文件,以便产生程序的预期结果。Makefiles 极大地帮助数据科学家建立他们的工作流程。在数据科学项目交付后的大部分时间里,开发人员很难记住构建最终产品所采取的步骤。Makefiles 帮助数据科学家记录管道,以重现构建的模型。因此,这个工具应该放在数据科学家的工具箱里。

Makefile 不仅提供了可再现性,还简化了数据科学团队的协作。一个团队成员,他将使用多个命令设置环境和安装需求,现在可以在一行中完成:

#old
virtualenv ex
source ex/bin/activate
pip install -r requirements.txt
#new
make requirements

水印

Watermark 是一个 IPython 扩展,可以在任何 IPython shell 或 Jupyter 笔记本会话中打印日期和时间戳、版本号和硬件信息。它提供了一种简单的方法来跟踪项目中涉及的工具、库和作者。对于大型项目,使用像 watermark 这样的工具来跟踪所做的更改是一种非常简单且低效的方法。

要安装和使用 watermark,请运行以下命令:

pip install watermark
%load_ext watermark

这里演示了如何使用它来打印库版本。您可以在他们的文档中找到更多信息:

%watermark -d -m -v -p numpy,matplotlib,sklearn,pandas

最终想法

凭经验我可以说,数据科学项目一般没有标准化的结构。然而,我在这篇文章中描述的工具可以帮助您创建可重复的数据科学项目,这将提高您的数据团队的协作、效率和项目管理。

如果你对这个帖子有任何疑问,或者对数据科学有任何疑问,你可以在Linkedin上找到我。

感谢阅读!

来自非结构化语料库的结构化食谱

原文:https://towardsdatascience.com/structured-recipe-from-an-unstructured-corpus-5710ee869505?source=collection_archive---------53-----------------------

信息检索

基于食物的知识图驱动的信息检索和自然语言处理项目概述

Unsplash 上由S O C I A l C U T拍摄

本文简要介绍了一个信息检索(和自然语言处理混合)项目的素质和标志,并强调了所获得的结果和推论。

该项目的目标是:

  • 从食谱数据的非结构化语料库中导出结构。
  • 利用这种结构来获得知识图。
  • 从获得的知识图中提取和检查推论。
  • 建立信息检索和可视化系统。

接下来的工作可以作为烹饪分类、推荐系统、基于知识图的语义推导等的基础。

什么是非结构化数据?

  • 在数据收集中缺乏定义良好的结构使其非结构化
  • 图像、文本、歌曲、视频是这种数据的一些例子。
  • 大多数生成的数据是非结构化的。

虽然事实上没有数据是完全非结构化的,但我们的机器发现这种形式的数据平淡无奇;除非我们无能为力。

无法对非结构化数据执行信息提取和分析。由于大多数数据是非结构化的,这是一个广泛面临的问题,因此我们的问题定义。

问题定义

许多烹饪网站提供各种烹饪和方法的食谱。尽管存在大量的食谱数据,但几乎没有结构。任何结构,如果存在的话,都不能从中导出有用的模式。

因此,我们的任务是从基于非结构化配方的数据中导出一些结构和有意义的关系,并能够在其上运行信息检索系统。

数据集

我们使用的数据集具有以下结构。

单一配方 JSON 分解。(图片作者)

这是一个食谱的 JSON 分解。食谱的标题、配料列表和说明列表是我们在这个项目中唯一关心的条目。配料表描述如下。即我们的非结构化数据:

一个配方的成分列表。(作者图片)

相邻的图像显示了配方配料数据是如何存储在配料列表中的。可以看出,这些数据是非结构化的。

这个列表是我们要构建的输入。

结构化数据

非结构化成分数据可以使用 NYTimes 的 CRF 成分短语标签进行结构化。

这个问题是一个结构化的预测问题,其中我们需要识别一系列标签,而不是识别单个标签。为此,CRF 成分短语标记器使用线性链条件随机场,这在诸如词性标记和命名实体识别(NER)的任务中经常是成功的。

成分的各种标签包括数量、单位、名称和注释。该模型通过在一种成分的所有可能标签序列中找到最高概率来找到最佳的可能标签序列。这描述如下:

如果我们的配料短语是“2 茶匙盐”然后我们需要给所有可能的标签序列打分。(图片作者)

生成的结构由附在配料上的标签组成。

该模型对 20000 种成分进行训练,并生成中间模型文件,该文件进一步用于测试目的。

评估标准是模型预测的准确性:

  • 句子级:模型预测成分句中每个单词的实际值。如果句子中的一个单词被错误地识别,则该句子被添加到错误指定的句子中。
  • 单词级:在单词级的情况下,检查每个单词,而不管句子是什么。

对 2000 种成分的测试在句子级别产生了大约 74%的准确度,而在单词级别产生了 90%的准确度。句子级别的较低准确度可归因于句子中存在多个单词,并且并非所有单词都被正确识别,因此降低了句子级别的整体准确度。

在构造阶段获得的单词级图表和句子级图表的准确度。(图片作者)

将模型应用于对应于食谱数据集的配料,我们可以构造其数据,从而暗示模型的稳健性和准确性。

现在我们已经从语料库中准备好了一个结构,我们可以从这里开始构建知识图了。

知识图构建

下一步是构建三元组来制作知识图。

如果你是知识图表的新手,看看叶戈尔·德芝克的快速阅读:

[## 理解知识图表

首先,人工智能系统严重依赖数据库中的手工知识。典型的专家系统使用这个…

medium.com](https://medium.com/@Dezhic/understanding-knowledge-graphs-5cb05593eb84)

在创建三元组之前,我们需要做一些快速的预处理步骤:

  1. 词汇化
  2. 删除标点符号
  3. 停用词删除
  4. 移除前导和尾随空格
  5. 小写转换

这清理了我们的数据,并为以后在本文的查询部分使用提供了一致性。

要构建的三元组的形式为:( ) — — ( 目标)。每个源值和目标值成为一个节点,第三个三元组将它们连接成一个

为每个(食谱,结构化烹饪步骤)对创建一个三元组集合。对于每一对,''节点是结构化 JSON 的'标题'列,'目标'节点是从获取的结构化数据中的'名称'和'注释字段中的'边缘'。

简而言之,每个菜谱标题都是一个源节点,通过在菜谱中应用的处理连接到它的配料。

我们的收集产生了这样一个知识图表:

10 种食谱的知识图表。(图片作者)

如果你认为这 10 个食谱的知识图表是密集的,那么看看下面 100 个食谱的图表。

100 种食谱的知识图表。(图片作者)

为了清楚起见,让我们来看一个来自单个配方的知识图:

单一配方的知识图表。(图片作者)

所以我们有一个图表。但是从这里去哪里呢?

查询图表

让我们查询这个图,这样我们就可以从中获得任何想要的信息。

为在三元词库中找到的每个关键词建立一个倒排索引。每个关键字指向该关键字所在的节点或边。倒排索引看起来像:

倒排索引的一个例子。这里,花括号内的元素是知识图中的节点或边。(图片作者)

对于每个查询词,候选集包含该词在倒排索引中指向的节点或边的集合。这个候选集用于从我们的原始知识图中绘制输出子图。

因此,包含查询词及其紧邻的任何节点都将显示在图中。任何包含术语“胡萝卜”的边都会出现它所连接的两个节点。互连得到了处理。

考虑查询— 胡萝卜。该查询的输出是:

查询的子图输出:胡萝卜。(图片作者)

这个图稀疏得多,可以清楚地观察到节点和边。

让我们考虑另一个查询— 菠菜丁。对于多个查询术语,输出知识图可以是连接的或断开的,这取决于查询术语从图中带来的启示。该查询的结果是:

查询的子图输出:菠菜丁。(图片作者)

我们得到了一个稍微多一点的连通图。甚至一些连接到它们各自成分的配方节点也出现在图中。

还有几个问题:

罐头豆蔻作为查询。(图片作者)

查询部分到此结束。让我们谈谈从我们的全知识图中可以得出的推论。

结论

构建的知识图用于进行推论以找出重要信息。

评估的措施:

程度中心性:

程度中心性是受欢迎程度的度量。它确定连接到最多节点的节点。该度量确定了图中可以在局部区域中快速传播信息的节点。

对于食谱数据的上下文,具有高度中心性的配料节点是受欢迎的配料,并且在许多食谱中使用或者与许多其他配料一起使用。

中间中心性:

介数中心性是一种度量,它提供了关于哪些节点重要的感觉,不是因为它们具有大量的连接,而是因为它们提供了网络的连通性和内聚性。

这些节点是食谱的重要组成部分,它们具有较高的介数中心性和较低的度中心性。

特征向量中心性:

特征向量中心性有助于理解哪些节点可以快速获得大量节点的信息。

也可以看做是相关的影响力或者说是在幕后发挥权力作用的节点。本质上,是知识图中重要节点的邻居的节点。

这些成分可以看做是最本质的成分。

连接组件:

可以看出,大多数配方构成了图中最大的连通部分,其余的包含一个或两个配方。这暗示了一些食谱是非常独特和不同的,因为它们的成分或制备方法不同。

这些食谱就像样本空间中的离群值,因为它们的制备方法和/或配料设置与大多数食谱非常不同。

社区检测:

社区检测是一种以最佳方式划分知识图的方法。可以看到,这些配方组合在一起。这些分组被称为社区

社区暗示了基于成分或准备方法的食谱的分离。

可以看出,在从 100 个食谱的语料库构建的知识图中,具有 2 个连接的组件,其中具有 9 个社区。

社区暗示了可以执行的食谱的可能分类。这些集群有同类的配方。

汇总推论:

从所描述的测量中得到的推论。(图片作者)

如果您想了解更多关于用于推断的测量方法,以下是一些有用的链接:

[## 图形分析——中心性的介绍和概念

社交网络、大数据和电子商务的出现再次强调了分析一种独特类型的…

towardsdatascience.com](/graph-analytics-introduction-and-concepts-of-centrality-8f5543b55de3) [## 图形和网络中的社区检测入门

今年,“社区”一词进入了世界各地的主流对话,这在很大程度上要归功于…

www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2020/04/community-detection-graphs-networks/)

未来工作:

未来的工作可能包括包含具有不同规则的三重映射的架构上不同的知识图的几个副本。不同结构的组合可能能够更好地表示复杂的关系。可以进一步查询该图以得出更多的推论。

贡献:

这个项目的开发是一个共同的努力。这个团队在这个项目的大部分时间里密切合作。我们面临的困难是,我们改进业绩的想法效果不佳,这是一次高度团结的合作。虽然项目的内聚结构是众所周知的,但工作分配细分如下。

(坦莫·查克拉博蒂)坦莫·查克拉博蒂博士——全程指导。

知识图和子图查询系统的实现和设计。结构到三层结构的设计和转换。

罗斯·维尔马( 罗斯·维尔马 ) —从知识图中提取推理。结构到三层结构的设计和转换。

普拉蒂克·阿加瓦尔( 普拉蒂克·阿加瓦尔 ) —从非结构化数据和数据预处理技术中创建结构化数据。

这个项目是为 IIITD 的课程信息检索 2020 做的。

MATLAB/Octave 中的结构

原文:https://towardsdatascience.com/structures-in-matlab-octave-96145b0b3f9f?source=collection_archive---------67-----------------------

图片由作者提供。图片来源于https://pixabay.com/

帮助您的数据保持完整!

结构,或结构,是 MATLAB/Octave 中的一种基本数据类型,可用于将多个属性组织和组合成一个公共数据结构。结构上的属性也称为字段,可以是不同的类型和不同的大小。然后,可以像平常一样访问和操作结构上的每个属性。结构在 MATLAB/Octave 中有多种用途,对于那些更熟悉 Python 的人来说,它非常类似于字典。

在本文中,我将介绍结构的基础知识,然后分享一些我认为最有用的使用它们的“技巧”。特别是,我涵盖了以下主题:

  • 动态属性访问和 filednames() 函数
  • 使用结构数组
  • 使用结构编写高效代码的注意事项

所有例子的源代码都可以在 GitHub 库中找到。需要注意的是,MATLAB 和 Octave 显示结构的方式非常不同,因此根据运行代码的应用程序,您可能会看到一些差异。在本教程中,我用 Octave 运行了所有的例子,以尽可能地使事情变得容易理解。

基础知识

MATLAB/Octave 中的结构是动态管理的,所以我们可以随时添加和删除新的属性。创建结构最简单的方法是使用 struct() 命令创建一个空结构,并使用点操作符填充它。这里有一个简单的例子。

s = struct(); % create an empty struct
s.val1 = 100; % add a scalar
s.val2 = 0 : 25 : 100; % add a vectorize
s.val3 = randn( 2, 3, 5 ); % add an ND array
s.char1 = 'This is a character string'; % add a character string
s.cell1 = { 100, 300, '5', 'abc' };  % add a cell array
disp( s );scalar structure containing the fields:val1 =  100
    val2 =0    25    50    75   100val3 =ans(:,:,1) =-0.49715   0.32621  -0.81624
      -0.34628   1.85946   0.29556ans(:,:,2) =-0.32521   0.44471   2.40743
      -0.97223  -0.24240   0.39241ans(:,:,3) =-1.63085  -0.34078   0.46239
       0.48026  -0.45361   1.62214ans(:,:,4) =

       0.523431  -0.576770  -0.028377
      -1.035780   0.093593  -2.001485ans(:,:,5) =0.30492  -2.05388   0.13755
      -0.98662  -1.36354  -0.43432char1 = This is a character string
    cell1 =
    {
      [1,1] =  100
      [1,2] =  300
      [1,3] = 5
      [1,4] = abc
    }

我们现在可以使用相应的字段名称来访问任何新添加的属性。例如,让我们访问“val2”的第 2 个元素。

>> disp( s.val2(2) );25

或者我们可以访问“单元格 1”的最后一个元素。

>> disp( s.cell1{end} );abc

事实上,我们现在可以访问和修改所有的属性,就像它们不在结构上一样。让我们给“单元格 1”添加一个新值。

>> s.cell1{ end+1 } = 'I am new!';
>> disp( s.cell1 );{
  [1,1] =  100
  [1,2] =  300
  [1,3] = 5
  [1,4] = abc
  [1,5] = I am new!
}

或者让我们从“val2”中删除一些值。

>> disp( s.val2 );0    25    50    75   100>> s.val2( 2:3 ) = [];>> disp( s.val2 );0    75   100

最后,使用 rmfield() 函数,我们可以从一个结构中完全删除字段。例如,让我们创建一个名为“s2”的新结构,并删除除“val1”之外的所有字段。其语法是: sOut = rmfield( s,{ 'name1 ',' name2 ',etc… } ) ,其中如果我们想要覆盖原始结构,则“sOut”可以是“s”,并且单元格数组包含我们想要移除的所有字段的名称。

>> s2 = rmfield( s, { 'val2', 'val3', 'char1', 'cell1' } );
>> disp( s2 );scalar structure containing the fields:val1 =  100

这是对结构的最基本用法的快速介绍。如果你是一个结构新手,花点时间浏览一下 MATLAB 文档可能是值得的。本文的其余部分将涉及一些更高级的,或者可能不太明显的使用结构的方法。

动态访问属性和 fieldnames()函数

结构的另一个非常有用的特性是你可以构建它们的数组。这些数组的行为与任何其他数组非常相似,但是,在填充它们时还需要额外的注意。特别是,结构数组中的每个元素都必须具有相同的属性。它们可以是空的,但是在将多个结构连接成一个数组之前,所有的属性都必须存在。

从一个简单的例子开始,让我们将“s3”的第二个元素设置为其自身的另一个副本。

>> s3(2) = s3;
>> disp( s3 );1x2 struct array containing the fields:noodles
    dexter
    ron
    greg

现在我们可以看到有一个 1x2 的结构数组。请注意,这是可行的,因为两个结构具有完全相同的属性。

结构数组的行为就像任何其他数组一样,可以使用 () 来访问。例如,让我们将第一个结构上的“面条”字段更新为等于当前值的两倍。

>> s3(1).noodles = s3(1).noodles * 2;
>> disp( s3(1).noodles );62
>> disp( s3(2).noodles );31

我们还可以通过将元素设置为空值来从结构中移除元素。

>> s3(1) = [];
>> disp( s3 );scalar structure containing the fields:noodles =  31
    dexter =  11
    ron =  46
    greg =  28

请注意,上面的输出显示我们再次拥有了一个标量结构。因为我们已经移除了结构数组的第一个元素。

最后,跨结构数组收集值也很方便。例如,假设我们有一个包含带有地理标签的图像的结构数组,我们对查看所有图像的位置感兴趣。我们可以通过捕获方括号 [] 之间的结构输出将这些值收集到一个数组中。

让我们用另一个例子来证明这一点。首先,我们将构建 10 个结构,每个结构都有“img”、“lat”和“lon”属性。请注意,在循环中,临时变量用于在将每个结构添加到数组之前完全填充该结构。在这种情况下,这实际上是不必要的,因为我是通过向后循环来预分配结构内存的;但是,一般来说,这是一个很好的做法,因为这将确保在您尝试连接结构之前所有的字段都存在。

% - Build a fake array of structs.
for iS=10 : -1 : 1
    tmp = struct();
    tmp.lat = randi( [-89, 90], 1 );
    tmp.lon = randi( [-179, 180], 1 );
    tmp.img = randn( 16, 16, 3 );
    img( iS ) = tmp;
end

结构的结果数组将如下所示。

>> disp( img );1x10 struct array containing the fields:lat
    lon
    img

接下来,我们可以将结构数组中的所有纬度和经度值收集到单独的数组中。

% - Collect all of the lat and lon values into separate arrays
lat = [ img(:).lat ];
lon = [ img(:).lon ];>> disp( lat );5   48  -36  -29   45   49  -68  -62   34  -31
>> disp( lon );28   -62    60    80  -130   125   -68     2    33   177

方便的是,我们现在可以访问所有的 lat/lon 值,而不必遍历结构。当你想绘制图表或计算统计数据时,这是非常方便的。它还可以节省大量的运行时间,我将在下一节演示这一点。

令人惊讶的是,当您收集具有不止一个非单例维度的属性时,甚至可以做更奇妙的事情。在这种情况下,技巧是使用 cat() 函数来明确说明数据应该如何分组。例如,我们可以将所有的像素数据从结构中收集到一个大小为 16 x 16 x 3 x 10 的新 ND 数组中,其中第四维对应于每个结构。

>> pixelData = cat( 4, img(:).img );
>> disp( size( pixelData ) );16   16    3   10

现在你可以看到我们有一个 4 维数组,它是高乘宽乘通道乘图像。我发现这是一种非常优雅的方法,可以同时访问一个结构中多个元素的数据。这个“技巧”起初对我来说也不是很明显,但现在我经常使用。

性能呢?

尽管结构很棒也很灵活,但当然也有一些代价。在这种情况下,代价是运行时间的增加,这主要是由于数据在内存中的存储方式。好消息是,使用我们刚刚介绍的技巧,您可以解决大多数问题。如果您有兴趣了解更多关于数组顺序和在 MATLAB 中编写高效循环的知识,请务必查看详细讨论该主题的以前的文章

让我们以前面的图像为例,但是现在我们将创建 50,000 个伪图像结构。

for iS=50000 : -1 : 1
    tmp = struct();
    tmp.lat = randi( [-89, 90], 1 );
    tmp.lon = randi( [-179, 180], 1 );
    tmp.img = randn( 16, 16, 3 );
    img( iS ) = tmp;
end

接下来,我们可以编写一些代码来对每个图像执行一个简单的任务。在这种情况下,我们将计算每个图像的平均像素强度,并将其保存在一个 1x10,000 元素的数组中。如果我们直接从结构中访问数据,代码看起来就是这样。

a = tic();% Loop over each struct
avgPixelInt = nan( 1, numel( img ) );
for iS=1 : numel( img )
  avgPixelInt( iS ) = mean( img( iS ).img(:) );
endt1 = toc( a )

或者,如果我们使用上一节中的 cat() 技巧,我们实际上可以编写相同的代码,而不必遍历数据。

a = tic();% Capture all of the images into an ND array
pixelData = cat( 4, img(:).img );% Reshape so we can take the mean over the entire image
sz = size( pixelData );
pixelData = reshape( pixelData, [ prod( sz(1:3) ), sz(4) ] );% Calculate the mean for all images at once
avgPixelInt = mean( pixelData, 1 );t2 = toc( a );

现在,如果我们运行两组代码,并使用 tic()toc() 对执行进行计时,这就是我们得到的结果。

>> t1 = toc( a )t1 =  9.8469>> t2 = toc( a )t2 =  1.9880>> disp( t1/t2 );
 4.9531

在这种情况下,使用 cat() 技巧使代码运行速度提高了近 5 倍!现在,在这个例子中,节省实际上来自于消除环路;但是,通常情况下,最好不要在循环中访问或设置结构的属性。几乎在所有情况下,由于结构中的数据存储在内存中的方式,这将导致代码变慢。所以,当有疑问时, cat() 它出来了。

摘要

这篇文章介绍了 MATLAB/Octave 中的结构,并介绍了一些基本的用法。一些更高级的用法基于使用变量来访问结构上的特定属性。这些技术确实给了程序员很大的能力来以编程方式解析和生成结构。最后,讨论了结构数组的使用,以及一些有助于编写高效代码的技巧。

以下是一些需要记住的关键事项:

  • 结构可以包含不同类型的数据作为属性
  • 可以随时添加或删除结构属性(或字段)
  • 结构可以连接成数组;但是,结构数组的每个元素必须包含完全相同的属性
  • 函数可以用来将所有结构中的特定属性收集到一个数组中
  • 虽然本文没有讨论,但是结构也可以包含其他结构作为属性
  • 尽管结构很棒,但是在使用它们的时候你应该小心,以避免编写低效的代码

编码快乐!

为快速迭代机器学习实验构建 Jupyter 笔记本

原文:https://towardsdatascience.com/structuring-jupyter-notebooks-for-fast-and-iterative-machine-learning-experiments-e09b56fa26bb?source=collection_archive---------13-----------------------

这是为那些需要在整洁的 Jupyter 工作空间中快速运行大量建模实验的忙碌的 ML 实践者准备的备忘单。

“模块化”你的代码在机器学习项目中很难

与软件世界不同,术语“可重用组件”可能很难应用于建模世界。实验通常是一次性的,没有多少代码被重用。如果你是一个干净的代码倡导者,喜欢花时间重构每一行代码来遵循“不要重复自己”(DRY)的原则,你很容易花太多时间这样做。

然而,我并不是建议去“不要重复自己”原则的对立面。我见过非常杂乱无章的 Jupyter 笔记本目录。然而,我们应该努力理解我们应该重用哪些组件。在本文中,我将根据我两年多来使用 Jupyter 笔记本对数据进行预处理和建模的经验,重点介绍机器学习项目中倾向于重用的组件。

首先,我们为什么要用 Jupyter?

我们在建模项目中使用 Jupyter 的主要原因是我们希望速度更快。我们想快速实验,快速失败,快速学习。数据处理需要时间,机器学习训练更需要时间。不像软件世界里“热重装”是一个东西,我们在建模世界里通常没有它。准备一个实验和实验本身都要花很多时间。为了更快,我们需要使用 Jupyter,它让我们能够只在一小部分代码上测试运行,而不是整个脚本。

这是一个迭代的过程。你越快完成这个循环,你的进步就越快。

—吴恩达,机器学习向往

现在,知道我们不应该在一开始就写脚本,而是应该使用 Jupyter 笔记本,让我们看看我们应该如何组织我们的项目。

概观

以下是我们将在这篇文章中涵盖的内容的概述:

  1. 拥有“小数据”有助于 —为什么以及如何在编写代码时拥有小数据集。
  2. 使用 git —如何使用 git 对你的笔记本进行版本控制。
  3. 关注点分离——如何构建你的 Jupyter 文件目录。
  4. 预处理、建模笔记本&报告笔记本 —这里我们讨论如何构建 3 个笔记本以及笔记本中包含的内容
  5. 主笔记本 —如何从一个笔记本调用其他笔记本以及如何记录输出

拥有“小数据”有助于

首先,在我们开始为我们的数据处理和数据模型编写代码之前,我们应该有一组“小数据”作为我们的数据。主要的直觉是有一个非常小的数据集,可以快速处理。通过这样做,当我们第一次运行我们的代码时,我们不必等几个小时才知道我们的代码中有一个简单的 bug。

例如,如果我们希望在 1000 万张图片上训练一个模型,那么试着每类只采样 50 张图片来编写代码。或者,如果我们正在训练 1 亿行销售数据,我们可以尝试采样 2000 行销售数据作为我们的“小数据”。

“小数据”应该有多大取决于样本的代表性和处理它的时间。就样本而言,每节课至少要有 5 个样本。就时间而言,经验法则是“小数据”从数据处理到完成模型训练所需的时间应该在 10 分钟以内。

你可以在笔记本的开头使用下面的代码来打开和关闭SMALL_DATA_MODE

SMALL_DATA_MODE = Trueif SMALL_DATA_MODE:
    DATA_FILE = "path/to/smallData.csv"
else:
    DATA_FILE = "path/to/originalData.csv"

使用 git

随着您运行越来越多的实验,很可能会删除旧代码并用新代码替换它们。仅仅为了代码上的一个小变化而创建一个新的笔记本是不好的,因为我们将来可能甚至不需要它们,它会占用我们的工作空间。

使用 git 有助于我们在保持工作场所整洁的同时对笔记本进行版本控制。如果需要,您可以通过返回到之前的 git 提交来恢复到旧版本。此外,如果我们定期将代码推送到远程存储库,我们就不必担心代码丢失。如果你独自做这个项目,你可以把所有的事情都推到主分支,如果你在一个团队中,你可以推到不同的分支。

安装 git,

在 Windows 上,转到https://git-scm.com/download/win

在 macOS 上,在终端中运行git --version。如果您还没有安装 git,它会提示您进行安装。

在 Linux Ubuntu 上,运行sudo apt install git-all

安装后,在项目目录中运行以下命令

git init

同样,让我们指定不想用 git 跟踪的文件。创建一个名为.gitignore的新文件,并将以下文本放入该文件。我们将忽略 Jupyter 检查点、python 缓存和数据目录。

.ipynb_checkpoints/
data/
__pycache__/

要提交,请使用以下内容(如果您以前加入过软件项目,您应该对这些内容很熟悉)。如果没有,我建议查看 git 教程。

git add .
git commit -m "Give a clear message here on what's changing compared to last time you commit"# remember to set a remote named `origin` for this:
git push origin master

关注点分离

图中显示了机器学习项目的推荐结构

一个机器学习项目通常会有多个使用相同数据和相同模型的实验。与其把所有东西都封在一个目录里,一个好办法是把数据预处理建模实验输出(exp) 分开。

这是我最喜欢的文件结构:

  • data/ —各种数据(原始数据、预处理数据等)的存储桶
  • exp/ —这里是实验的输出(保存的模型+实际和预测的标签)
  • logs/ —只是放置我们预处理数据和建模的日志文件
  • a_MASTER0.ipynb —“主”Jupyter 笔记本,可以调用其他“从”笔记本(预处理、建模、报告)。我们将在下一节展示如何从一个笔记本中调用另一个笔记本。
  • a_MASTER1.ipynb —只是另一个并行运行另一个实验的“主”笔记本。您可以根据需要添加任意数量的主笔记本。
  • b_preprocess.ipynb —预处理笔记本,接收来自data/raw的原始数据,并将数据输出到data/{dir}
  • c_model_svm.ipynb —该笔记本接收预处理的输出,稍加修改以适应 SVM 模型,然后将建模结果(如学习的模型参数、预测等)输出到exp/
  • c_model_randomForest.ipynb —如果你有另一个型号,就这样命名。
  • d_reporting.ipynb —这将从exp/中读取并为您的报告绘制表格或图像。

预处理笔记本

在这里,我将展示当我们第一次在笔记本中运行代码时应该做什么,我们应该用笔记本的参数启动笔记本。

# PARAMETER
#-------------# check if IS_MASTER exists, this variable will only exist if it's being called by MASTER notebook.
# if it does not exist, set it to False
try: IS_MASTER
except: IS_MASTER = False# The code below will only run if it's NOT being called from MASTER notebook
if IS_MASTER:
    DATA_DIR = './data/temp/' # 
    RAW_FILE = f'/path/to/smallData.csv' # use "small data" here
    PROCESSED_FILE = f'{DATA_DIR}processed.pkl' # always use pickle for fast I/O!
    OTHER_PREPROCESS_PARAMETER = ... # e.g. batch size, sliding window size, etc

上面的代码为我们的笔记本设置了默认参数。我们将只使用一个临时目录TMP_DIR(在data/目录下)来存储我们的输出。这是为了确保快速迭代。当我们写代码时,我们应该总是使用“小数据”。

您可以继续编写预处理部分。既然您在这个“开发”阶段使用“小数据”,那么您应该很快!当你完成预处理后,记得使用pickle库输出一个 Pickle 文件:

import pickle
with open(PROCESSED_FILE, 'wb') as f:
    pickle.dump(python_object, f)

或者,使用pandas快捷键:

df.to_pickle(PROCESSED_FILE)

我们使用 Pickle 而不是 CSV 格式来实现持久性和快速读写。这个PROCESSED_FILE将在下一部分的建模笔记本中读到。

建模笔记本

从这个开始我们的模型笔记本:

# PARAMETER
#-------------# check if IS_MASTER exists, this variable will only exist if it's being called by MASTER notebook.
# if it does not exist, set it to False
try: IS_MASTER
except: IS_MASTER = False# The code below will only run if it's NOT being called from MASTER notebook
if IS_MASTER:
    DATA_DIR = './data/temp/'
    EXP_DIR = './exp/temp/'
    PROCESSED_FILE = f'{DATA_DIR}processed.pkl'
    MODEL_FILE = f'{EXP_DIR}model.pkl'
    PREDICTION_FILE = f'{EXP_DIR}ypred.pkl'
    OTHER_MODEL_PARAMETERS = ... # like N_ESTIMATOR, GAMMA, etc

请注意,DATA_DIRPROCESSED_FILE与之前预处理笔记本的输出相同,并与之相连。

在本建模笔记本中,您应该做 3 件事(此处未显示,因为每个模型都不一样):

  1. 读取处理过的数据,并做一点小小的修改,使数据适合模型。
  2. 训练和评估模型
  3. 将模型的学习参数MODEL_FILE和预测PREDICTION_FILE输出到EXP_DIR目录。对于预测输出,将实际标注和预测标注放在同一个数据框中(便于报告)。

报告笔记本

报告笔记本是一个快捷的笔记本,它只需要从exp/目录中读取。其输入通过EXP_DIRMODEL_FILEPREDICTION_FILE连接到造型笔记本的输出。

# PARAMETER
#-------------# check if IS_MASTER exists, this variable will only exist if it's being called by MASTER notebook.
# if it does not exist, set it to False
try: IS_MASTER
except: IS_MASTER = False# The code below will only run if it's NOT being called from MASTER notebook
if IS_MASTER:
    EXP_DIR = './exp/temp/'
    MODEL_FILE = f'{EXP_DIR}model.pkl'
    PREDICTION_FILE = f'{EXP_DIR}ypred.pkl'

在这里,您可以将预测的标签与实际标签进行比较。在这里,您可以使用精度、召回率或 ROC AUC 等指标。您还可以在这里运行图表和绘图的代码。

主笔记本

最后,大师笔记本!

主笔记本是调用所有其他笔记本的笔记本。在这个笔记本中,您将监督整个数据管道(从原始数据预处理到建模和报告)。

主笔记本也是您调用其他(经过良好测试的)预处理和建模笔记本来运行实际“大数据”的地方。我还将介绍一个日志技巧(因为如果“大数据”出错,我们想知道原因)。

我们也将在这里使用 Jupyter 魔法命令%run

首先,创建一个名为print_n_log.py的文件,并将下面的代码粘贴到其中:

"""
Returns a modified print() method that returns TEE to both stdout and a file
"""
import loggingdef run(logger_name, log_file, stream_level='ERROR'):
    stream_level = {
        'DEBUG': logging.DEBUG,
        'INFO': logging.INFO,
        'WARNING': logging.WARNING,
        'ERROR': logging.ERROR,
        'CRITICAL': logging.CRITICAL,
    }[stream_level]

    # create logger with 'logger_name'
    logger = logging.getLogger(logger_name)
    logger.setLevel(logging.DEBUG)
    # create file handler which logs even debug messages
    fh = logging.FileHandler(log_file)
    fh.setLevel(logging.DEBUG)
    # create console handler with a higher log level
    ch = logging.StreamHandler()
    ch.setLevel(stream_level)
    # create formatter and add it to the handlers
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)
    # add the handlers to the logger
    logger.addHandler(fh)
    logger.addHandler(ch)
    def modified_print(*args):
        s = ' '.join([str(a) for a in args])
        logger.info(s)
    return modified_print

上面的代码将创建一个修改过的print()方法,该方法将输出(stdout)和错误(stderr)重定向到主笔记本单元的输出和日志文件。

接下来,将此模块导入您的主笔记本:

import print_n_log

在您的下一个单元格中,让我们尝试调用预处理笔记本:

# Parameters for Preprocessing Notebook
#---------------------------------------------
IS_MASTER = True # Remember this? We need to set this to True in MASTER Notebook so that it does not use the default parameters in processing notebook.
RAW_FILE = f'/path/to/smallData.csv' # use "small data" here
PROCESSED_FILE = f'{DATA_DIR}processed.pkl' # always use pickle for fast I/O!
OTHER_PREPROCESS_PARAMETER = ... # like batch size, sliding# Let's save the original print method in ori_print
#---------------------------------------------------
ori_print = print# Now we set the print method to be modified print
#--------------------------------------------------
print = print_n_log.run('preproc', './logs/preprocess.log', 'DEBUG')# Now, we run the Preprocessing Notebook using the %run magic
#-------------------------------------------------------------
%run 'c_preprocess.ipynb'# Finally, after running notebook, we set the print method back to the original print method.
#-----------------------------------------------------
print = ori_print

注意,我们使用%run魔法来运行预处理笔记本。这是一个 IPython 魔术,让我们从当前的笔记本运行其他 Python 文件和 Jupyter 笔记本。我们使用这个命令来运行预处理笔记本中的所有代码。

通过调用print_n_log.run('preproc', './logs/preprocess.log', 'DEBUG'),我们修改了原始的 Python 内置print()方法,将输出重定向到屏幕和日志文件。'preproc'只是我们记录器的一个名字,你可以使用任何其他名字。运行后,您可以转到'./logs/preproc.log'来查看运行预处理笔记本记录的输出。最后一个参数'DEBUG'只是说“打印每个输出到屏幕上”。如果您只想在屏幕上看到错误(无输出),也可以使用'ERROR'

是的,就是这样!您可以使用相同的模板来调用建模笔记本和报告笔记本。但是,提示一下,您可能不希望记录报告笔记本的输出,所以您可以对它使用原始的 print()方法。

结论

这里的关键思想是将 Jupyter 笔记本中与其他部分没有太多纠缠的部分“模块化”,同时对整个数据管道有一个概览。

与封装的软件哲学不同,我们实际上并不想将代码封装在 python 文件中,然后再也看不到它们(尽管我们可以对一些实用程序方法这样做)。我们希望将大部分代码保存在笔记本中,因为在设计实验时,每个部分都应该是可变的。当一个部分被改变时,我们也想让它们可测试。通过留在 Jupyter notebook,我们知道我们的代码在用“小数据”运行时是可测试的。通过遵循这些指导方针,我们将拥有一个组织化和模块化的 Jupyter 项目,然而每个部分都是易于编辑和测试的。

要获得我帖子的通知,请在 Medium、 Twitter脸书上关注我。

构建机器学习项目

原文:https://towardsdatascience.com/structuring-machine-learning-projects-be473775a1b6?source=collection_archive---------7-----------------------

图 1:自由女神像周围的脚手架——照片由纽约公共图书馆Unsplash 拍摄

构建 ML 项目的模板指南

“分层方法被认为是比作为一个整体块实现协议更好的实践,因为分别实现概念上不同的问题有几个好处”Buschmann 等人(1996)[1]。在发表的时候,Buschmann 等人被认为是软件开发的一种新方法。自从 POSA 第一卷发布以来已经过去了 20 多年,有趣的是,设计的思想仍然非常适用于现代软件开发。

那么,软件开发与构建机器学习项目到底有什么关系呢?实际编写的机器学习代码只是机器学习系统的一小部分。基于前述的基础,我相信将大规模的机器学习项目视为一个软件项目是非常公平的——当然,不要忽视实践者的能力。在本文中,我将详细说明拥有良好结构布局的好处,然后我将提供一个模板结构布局,详细描述每个目录中可能包含的内容。

资料来源:霍尔特,加里&戈洛文,丹尼尔&达维多夫,尤金&菲利普斯,托德&埃布纳,迪特马尔&乔德里,维奈&杨,迈克尔&丹尼森,丹。(2015).机器学习系统中隐藏的技术债务。乳头。2494–2502.

注:拟议的结构仅作为一个框架,可能会发生变化。没有一种方法可以设计一个项目,所以最好的方法是选择并采用符合您的偏好和项目需求的实践。

“风格指南是关于一致性的。与本风格指南保持一致非常重要。项目内部的一致性更重要。一个模块或功能内的一致性是最重要的。

然而,要知道什么时候不一致——有时候风格指南的建议并不适用。当有疑问时,使用你最好的判断。看看其他例子,决定什么是最好看的。不要犹豫地问!"

——吉多·范·罗森[2]。

W hy 在意结构?

你未来的自己会感激:

在某些时候,我们会想要复制我们的工作。就我接触过的许多人而言,在我们工作的时候,很少考虑未来会发生什么对我们最有利。当构建预测模型时,我们更关心的是获得洞察力,从而构建一个强大的工作预测模型——我们希望把事情做好!快速测试、可视化和分析并不罕见,但这种环境并不适合考虑结构,因此很难返回代码并理解您当时得出的某些结论或您当时的思维过程。

回到过去的项目,如果你不得不考虑是否应该执行make_column.pynew_make_column.pyfixed_make_column.py来完成工作,那么这就是我称之为 HDW(高度无组织工作)的症状。无法重现结果不仅令人尴尬,对灵魂来说也是相当痛苦的,因此,从长远来看,通过预先制定项目结构,我们为自己做了一件好事。好的项目结构鼓励那些让回到过去的工作充满快乐的实践。

别人会感激:

当一个项目组织良好时,它往往是自文档化的。出于各种原因,有人可能想要参观你的作品来扩展它、展示它或者仅仅是从中学习。可能想要访问您的工作的人是不熟悉您的项目的人,所以通过维护良好的结构,您为他们节省了大量的时间,因为他们可以通过简单地查看结构来对您所做的事情有一个大致的了解,而不必解析大量的文档或代码来找到他们正在寻找的特定功能——也就是说,这也意味着协作过程将更加容易,这在任何团队活动中总是高效团队的一个有用特征。

再现性:

我们简要地谈到了这个话题,但是由于它是 ML 中的一个至关重要的因素——在数据科学、深度学习、计算机视觉和自然语言处理等领域也是如此——所以必须明确地提到可再现性。在 Sugimura,P. Hartl,F. 2018[3]中,提供了阻碍模型再现能力的各种无意方式以及修复这些问题的解决方案。这类问题的例子有数据起源、特征起源、模型起源等等。此外,Sugimura,P. Hartl,F. 2018[3]指出,用于构建具有系统架构的可再生管道的方法从一开始就将该概念视为一等公民[4],为了使该架构实现通用性和可扩展性,该项目分为多个部分。拥有良好的项目结构有助于实现这个目标!

图二。整体系统架构示例。资料来源:杉村,P. Hartl,F. 2018。建立一个可复制的机器学习管道。arXiv。[3].

为了进一步扩展再现性的话题,值得注意的是,你做的每件事,你可能都要再做一遍——这就像墨菲定律的版本。出于各种原因,你的工作可能需要复制,无论是你意识到有一个缺陷,还是你离开公司,有人想延长你的工作。因此,无论你做了什么都可能需要重做,如果有一个组织良好的结构,那么知道从哪里开始就会简单得多。

注:请参阅 Ericson 等人 2020[6]关于标准化项目结构的更多信息。

拟建结构布局

图 3:目录布局

数据

外部:这是从第三方来源提取的数据(不可变数据)。如果没有提取第三方数据,则该文件夹过时。

过渡:在事件外部数据可用时,该数据将是我们通过使用src/data目录中的脚本为特征工程加载的数据。该数据集是通过执行各种连接和/或合并来组合外部和原始数据而生成的。

已处理:这是使用各种机器学习技术转换的数据。我们将在src文件夹中进入的 features 文件夹对数据执行各种转换,以使其为建模做好准备。为了缩短模型的训练时间,保存处理过的数据不失为一个好主意。

Raw: 拥有数据的本地子集副本可以确保您有一个静态数据集来执行任务。此外,这克服了由于网络延迟问题导致的任何工作流故障。这个数据应该被认为是不可变的。如果没有外部数据,那么这是由src\data中的脚本下载的数据。

车型

我们使用src\models中的脚本来训练我们的机器学习模型。我们可能需要将该模型与其他模型一起恢复或重用,以构建一个集合或进行比较,并且我们可以决定要部署的模型。为此,我们将训练好的模型保存到一个文件中(通常是 pickle 格式),该文件将保存在这个目录中。

笔记本

Jupyter 笔记本电脑非常适合制作原型、探索和交流发现,但是它们不太适合长期发展,并且在可重复性方面效率较低。笔记本可以进一步分为Notebooks\explorationsNotebooks\PoC等子文件夹。使用良好的命名约定有助于区分每个笔记本中填充了什么——一个有用的模板是<步骤> - <用户> - <描述>。ipynb(即 01-kpy-eda.ipynb ),其中步骤用作排序机制,创建者的名字首字母、姓氏的前两个字母以及笔记本内容的描述。

Src

数据:在这个目录中,我们有脚本,这些脚本从数据生成的任何地方接收数据,并转换这些数据,使其处于可以进行进一步特性工程的状态。

特性:在这个目录中,我们有一个脚本来处理数据,并将其转换成一种可以被我们的机器学习模型使用的格式。

模型:包含用于构建和训练我们的模型的脚本。

结论

拥有一个结构化的目录布局对于组织 ML 项目中数据科学团队的思维非常有用。在项目开始时花一些时间思考你将如何规划未来的工作并将其记录为你的标准化项目结构是很有用的(Ericson et al 2020。)[6].如果在项目过程中需要重命名、添加或删除某个目录,这是没有问题的,因为结构不是严格的,但是应该有一种方法向团队的其他成员提出这一点,以便您可以批准这一更改。在你独自进行一个项目或者作为一个单独的实践者的情况下,记录变化仍然是一个好主意,这样你就可以在你进行项目的过程中跟踪你的思维过程。

在这篇文章中,我没有提到其他重要的东西,如 README.md、environment.yml/requirements.txt 和测试。在以后的文章中,我会深入探讨这些问题。我还将在以后的文章中构建一个自定义管道。在 Medium 或 Twitter 上关注我吧 @kurtispykes 关注我的下一篇文章。

其他有用资源:

马志威 - 前期管理你的数据结构

Mateusz Bednarski - 机器学习项目的结构化和自动化工作流第一部分

Mateusz Bednarski - 机器学习项目的结构化和自动化工作流第二部分

Semi Koen - 成为数据科学家并不能让你成为软件工程师

Semi Koen - 构建机器学习管道

FloydHub - 如何计划和执行你的 ML 和 DL 项目

参考文献

[1] Buschmann 等人(1996 年)。建筑模式,在布希曼,F(编辑。)面向模式的软件架构。约翰·威利的儿子们。第 32 页

[2]范·罗森,G .华沙,B .科格兰,N. 2001 年。PEP 8——Python 代码风格指南。查看 2020 年 3 月 25 日,<https://www.python.org/dev/peps/pep-0008/>

[3]杉村,p .哈特尔,F. 2018。建立一个可复制的机器学习管道。arXiv。

[4]《一等公民》(2020)维基百科。可在:https://en.wikipedia.org/wiki/First-class_citizen(访问日期:2020 年 3 月 26 日)

[5]《墨菲定律》(2020)维基百科。可在:https://en.wikipedia.org/w/index.php?title=Murphy%27s_law&行动=历史(访问时间:2020 年 3 月 25 日)

[6]埃里克森等人 2020。团队数据科学流程是什么?。微软。查看 2020 年 3 月 25 日,<https://docs . Microsoft . com/en-us/azure/machine-learning/team-data-science-process/overview #标准化-项目-结构 >

构建 ML 管道项目

原文:https://towardsdatascience.com/structuring-ml-pipeline-projects-97c16348be4a?source=collection_archive---------19-----------------------

一个有组织的代码库使你能够更快地实现变化,犯更少的错误,最终导致更高的代码和模型质量。阅读更多内容,了解如何使用 Tensorflow Extended (TFX)构建您的 ML 项目,这是一种简单明了的方法。

图片由来自 Pixabay 的 Francis Ray 拍摄

项目结构:需求

  • 启用multiple管道实验
  • 支持local执行模式和deployment执行模式。这确保了创建两个独立的运行配置,第一个用于本地开发和端到端测试,第二个用于在云中运行。
  • Reuse code如果这样做有意义的话,跨管道变量
  • 提供一个易于使用的CLI interface来执行具有不同configurations和数据的流水线

一个正确的实现还可以确保测试很容易被整合到您的工作流程中。

项目结构:设计决策

  • 用 Python。
  • 使用 Tensorflow Extended (TFX)作为管道框架。

在本文中,我们将演示如何以最少的麻烦在本地和 Kubeflow 管道系统上运行 TFX 管道。

设计决策引起的副作用

  • 通过使用 TFX,我们将使用tensorflow。请记住,tensorflow 支持更多类型的模型,如增强树
  • Apache Beam 可以在本地、kubernetes 运行的任何地方以及所有公共云提供商上执行。例子包括但不限于:GCP 数据流,Azure 数据砖。
  • 由于 Apache Beam,我们需要确保项目代码很容易被 python 的sdist打包,以获得最大的可移植性。这体现在项目的顶层模块结构上。(如果您使用外部库,请确保通过向 apache beam 提供一个参数来包含它们。阅读更多关于 Apache Beam:管理 Python 管道依赖关系 )。

【可选】在继续之前,花点时间阅读一下提供的 TFX CLI 。目前,运行起来非常慢,而且目录结构比它需要的要冗长得多。它也不包括任何关于可再现性和代码重用的注释。

目录结构及其背后的直觉

  • $project-name是项目的根目录
  • $project-name/ml包括机器学习相关的东西。
  • $project-name/ml/pipelines包括实际的 ML 管道代码
  • 通常,您可能会发现自己需要管理多个 ML 管道,例如$project-name/ml/pipelines/predict-sales$project-name/ml/pipelines/classify-fraud或类似的管道。
  • 下面是一个简单的tree视图:

$project-name/ml/pipelines包括以下内容:

  • data →少量代表性培训数据在本地运行,用于测试和 CI。如果您的系统没有专门的组件来从某个地方提取数据,那就是真的。如果是这样的话,请确保包含一个带有少量有限项目的抽样查询。
  • util →跨$pipeline-name重复使用和共享的代码。不需要包含input_fn_utils.pymodel_utils.py。在这里使用任何有意义的东西。以下是一些例子:

在我自己的项目中,在实用模块上抽象一些部分是有意义的,比如为 keras 模型构建命名的输入和输出层。

使用张量流变换输出构建服务签名元图。

使用关键字将特征预处理成组。

以及其他常见的重复性任务,如使用 Tensorflow 数据集 api 构建输入管道。

  • cli.py →管道的入口点和命令行界面。以下是使用 TFX 时需要考虑的一些常见问题。

通过使用[abseil](https://github.com/abseil/abseil-py),你可以声明和访问全局标志。每个模块都定义了特定的标志。这是一个分布式系统。这意味着常见的标志,如--data_dir=...--hparam_tuning--pipeline_root--ml_metadata_url--use_cache--train_epochs可以在实际的cli.py文件中定义。另外,可以在子模块上为每个管道定义更具体的参数。

这个文件充当系统的入口点。它使用pipeline.py中的内容来设置管道的组件,并根据某些标志(如--pipeline_name=$pipeline-name或其他配置)提供用户提供的模块文件(在树形示例中为constants.pymodel.pytraining.py)。

最后,对于组装好的管道,它通过使用一个--runner=标志来调用某个_runner.py文件。

  • pipeline.py →参数化管道组件声明和接线。这通常只是一个声明一堆 TFX 组件并返回一个tfx.orchestration.Pipeline对象的函数。

  • local_beam_dag_runner.py →使用便携式光束运行器进行本地运行的配置。这通常几乎不需要配置,只需使用BeamDagRunner

  • kfp_runner.py →在 Kubeflow 管道上运行的配置。这通常包括不同的数据路径和管道输出前缀,并自动绑定 ml-metadata 实例。

注意:你可以有更多的运行者,像在 GCP 上运行的东西,只是配置更多的供应资源,如 TPU 实例,并行人工智能平台超参数搜索等。

$管道名称

这是用户提供的代码,用于制作不同的模型,安排不同的实验,等等。

由于有了util子模块,每个管道下的代码应该更精简。不需要把它分成 3 个以上的文件。但是这并不禁止将你的代码分割成更多的文件。

从实验中,我收敛到一个constantsmodeltraining分裂。

  • constants.py →申报。要跟踪的训练参数、超参数键和声明、特性键、特性组、评估配置和指标的合理默认值。这里有一个小例子:

  • model.py →模型定义。通常包含一个build_keras_model函数,并使用来自util$pipeline-name.constants的导入。这是我最近一个项目中的一个例子:

  • 最后,training.py包括训练模型所需的所有细节。这通常包括:预处理定义、超参数搜索、设置训练数据或模型——并行策略和张量板日志,以及保存用于生产的模块。

就是这样。谢谢你看完!

我希望你喜欢读这篇文章,就像我喜欢写它一样。

纠结于数据不平衡?半监督和自我监督学习帮助!

原文:https://towardsdatascience.com/struggling-with-data-imbalance-semi-supervised-self-supervised-learning-help-4de8b8f23490?source=collection_archive---------6-----------------------

(图片由作者提供)

入门

反思标签对改善班级不平衡学习的价值

给大家介绍一下我们最新的作品,已经被 NeurIPS 2020 接受: 反思标签对于改善班级不平衡学习的价值 。这项工作主要研究一个经典但非常实用和常见的问题:数据类别不平衡下的分类问题(也称为数据的长尾分布)。通过理论建模和大量实验,我们发现半监督自监督学习都能显著提高不平衡数据下的学习性能。

源代码(和相关数据,> 30 个预训练模型)可以通过这个 GitHub 链接找到:https://github.com/YyzHarry/imbalanced-semi-self

首先,我想用一句话来总结本文的主要贡献:我们已经从理论和经验上验证了,对于具有不平衡数据(类别)的学习问题,使用

  • 半监督学习 —即使用更多未标记数据;或者,
  • 自监督学习——即不使用任何额外的数据,只需先做一步自监督预训练对已有不平衡数据没有标签信息

都可以大大提高模型性能。它们的简单性和通用性也使得它们很容易与不同的经典方法相结合,以进一步增强学习效果。

接下来,我们将进入正文。我将首先介绍数据不平衡问题的背景和目前的一些研究现状。那我就介绍一下我们的思路和方法,省略不必要的细节。

背景

数据不平衡的问题在现实世界中非常普遍。对于真实数据,不同类别的数据量一般不会是理想的均匀分布,而往往会不平衡;如果按照样本数量从高到低对类进行排序,会发现数据分布有一个【长尾】,也就是我们所说的长尾效应。大规模数据集通常呈现这样的长尾标签分布:

大规模数据集通常呈现长尾标签分布(图片由作者提供)。

当然,不仅对于分类任务,对于物体检测或实例分割等其他任务,在很多常用的数据集中也存在类别不平衡的情况。除了视觉领域的数据,对于涉及安全或健康的关键应用,如自动驾驶和医疗/疾病诊断,数据本身就严重失衡。

为什么会出现不平衡?一般的解释是,特定类型的数据难以收集。以物种分类为例(例如,大规模数据集 iNaturalist),某些物种(如猫、狗等。)都很常见,但有些品种(如胡兀鹫)非常罕见。对于自动驾驶,正常行驶的数据会占大部分,而实际发生异常情况/车祸的数据很少。就医疗诊断而言,与正常人口相比,患有某些疾病的人数也极其不平衡。

那么,不平衡或长尾数据有什么问题呢?简单地说,如果你直接将不平衡样本扔给模型用 ERM 学习,很明显,模型在主要类别的样本上会学习得更好,但在次要类别上概括得很差,因为它看到的主要类别的样本远远多于次要类别。

那么,目前有哪些解决学习不平衡问题的方法呢?我总结的目前主流的方法大致分为以下几类:

  1. 重采样:具体来说,可以分为对少数样本过采样,或者对多数样本欠采样。然而,过采样容易过度适应小类,并且不能学习更鲁棒和可概括的特征,并且它通常在非常不平衡的数据上表现不佳;另一方面,欠采样会导致主类中严重的信息丢失,从而导致欠拟合。
  2. 合成样本:即生成与少数样本相似的“新”数据。经典方法 SMOTE 对随机选取的少数样本使用 K 近邻选取相似样本,通过线性插值得到新样本。
  3. 重新加权:给不同的类别(甚至不同的样本)分配不同的权重。注意,这里的权重可以是自适应的。这种方法有许多变种。最简单的就是按照类别数量的倒数来加权。
  4. 迁移学习:这类方法的基本思想是将多数类和少数类分别建模,将多数类的学习信息/表征/知识迁移给少数类。
  5. 度量学习:本质上是希望学习更好的嵌入,更好的建模少数类附近的边界/边距。
  6. 元学习/领域适应:可以使用头部和尾部数据的不同处理来自适应地学习如何重新加权,或者将问题公式化为领域适应问题。

至此,大致总结了背景和常用方法;然而,即使有数据重采样或类平衡损失等专门算法,在极端数据不平衡的情况下,深度模型性能的退化仍然普遍存在。因此,了解不平衡数据标签分布的影响是非常重要的。

我们的动机和想法

与以前的方法不同,我们考虑如何平衡这些不平衡数据标签的“价值”。然而,与平衡数据不同,不平衡学习环境中的标签扮演着令人惊讶的争议角色,这导致了对其价值的持续困境:(1)一方面,有标签监督的学习算法通常会比无监督的学习算法产生更准确的分类器,证明了标签的值;(2)然而,另一方面,不平衡的标签自然会在学习过程中强加“标签偏差”,其中决策边界可以由多数类显著驱动,这表明了标签的负面影响。结果,不平衡的标签就像一把双刃剑;一个很重要的问题是如何最大限度地挖掘标签的价值来改善类不平衡学习

因此,我们试图对上述两种不同的观点分别进行系统的分解和分析。我们的结论表明,对于视角,不平衡标签的值可以被充分利用,从而大大提高最终分类器的准确性:

  • 正面我们发现,当有更多的未标注数据时,这些不平衡的标注提供了稀缺的监管信息。通过使用这种监督,我们可以使用半监督学习来显著改善最终的分类结果,即使未标记数据也具有长尾分布。
  • 然而,我们认为不平衡的标签并不总是有用的。标签失衡几乎肯定会导致标签偏差。所以在训练时,我们首先想到的是“抛弃”标签信息,通过自监督学习学习一个好的初始表征。我们的结果表明,通过这种自我监督的预训练方法获得的模型也可以有效地提高分类的准确性。

具有未标记数据的不平衡学习

我们首先研究了一个简单的理论模型,并对原始不平衡数据和额外数据的不同成分如何影响整个学习过程建立了直觉。我们考虑这样的场景,其中我们有一个在不平衡训练集和一定量的未标记数据上获得的基本分类器,并且我们可以使用这个基本分类器来伪标记这些数据。这里,未标记的数据也可能是(高度)不平衡的。我在这里省略了细节,有兴趣的读者可以参考我们的论文。简而言之,我们展示了几个有趣的观察结果:

  • 训练数据的不平衡影响了我们估计的准确性;
  • 未标记的数据不平衡影响获得如此好的估计的概率。

半监督不平衡学习框架:我们的理论发现表明使用伪标签(因此训练数据中的标签信息)可以帮助不平衡学习;这种方法的有用程度受到数据不平衡的影响。受此启发,我们系统地探索了未标记数据的有效性。我们采用最简单的自训练半监督学习方法,在无标签数据上生成伪标签,然后一起训练。准确地说,我们首先在原始不平衡数据集上进行正常训练,以获得中间分类器,并应用它来生成未标记数据的伪标记。通过组合两部分数据,我们最小化联合损失函数来学习最终模型。

值得注意的是,除了自训练,其他半监督算法也可以很容易地纳入我们的框架,只需修改损失函数;同时,由于我们没有指定最终模型的学习策略,因此,半监督框架也可以很容易地与现有的不平衡算法相结合。

实验:现在进入激动人心的部分——实验:!让我们先谈谈实验的设置——我们选择了人工生成的长尾版本的 CIFS-10 和 SVHN 数据集,因为它们都有自然的对应的无标记部分,具有相似的数据分布:CIFS-10 属于 mini-Images 数据集,而 SVHN 本身有一个额外的数据集,可以用来模拟无标记数据。本部分设置详见本公司论文;我们也开源了相应的数据供大家使用和测试。对于未标记数据,我们还考虑了其可能的不平衡/长尾分布,并明确比较了来自不同分布的未标记数据的影响。

典型的原始不平衡数据分布和可能的未标记数据分布(作者提供的图像)。

实验结果见下表。我们可以清楚地看到,使用非标记数据时,半监督学习能够显著提高最终的分类结果,并且在不同的(1)数据集、(2)基本学习方法、(3)标记数据的不平衡比率、(4)非标记数据的不平衡比率之间,能够带来一致的改进。此外,我们还在附录(5)中提供了不同半监督学习方法的比较,以及不同数据量的消融研究。

(作者图像)

最后给出了定性实验结果。我们在训练集和有/无未标记数据的测试集上绘制 t-SNE 可视化。从图中可以直观地看出,使用未标记数据有助于建立更清晰的类边界模型,并促进类之间更好的分离,尤其是对于尾部类样本。这个结果也符合我们的直觉理解。对于尾部样本,这些区域的数据密度较低,模型在学习过程中无法很好地模拟这些低密度区域的边界,导致模糊性和泛化能力较差。相比之下,未标记数据可以有效增加低密度区域的样本量,而更强正则化的加入使得模型更好地对边界进行再建模。

(作者图像)

关于半监督不平衡学习的进一步思考

虽然半监督学习可以显著提高不平衡数据的性能,但半监督学习本身存在一些实际问题,这些问题在不平衡的情况下会进一步放大。接下来,我们将通过设计相应的实验系统地阐述和分析这些情况,并激发下一步对不平衡标签的负值的思考和研究。

第一,未标记数据与原始数据的相关性对半监督学习的结果影响很大。比如对于 CIFAR-10 (10 类分类),得到的未标注数据可能不属于原来的 10 类中的任何一类(比如胡兀鹫……)。在这种情况下,未标记的信息可能是不正确的,并且对训练和结果有很大的影响。为了验证这一观点,我们将未标记数据和原始训练数据固定为具有相同的不平衡比例,但改变未标记数据和原始训练数据之间的相关性,以构建不同的未标记数据集。从图 2 可以看出,未标记数据的相关性需要达到 60%以上,才能对不平衡学习有积极的帮助。

(图片由作者提供)

由于原始训练数据是不平衡的,未标记的数据也可能是高度不平衡的。例如,在医疗数据中,您构建了一个自动诊断某种疾病的数据集。其中,阳性病例极少,仅占总数的 1%;但是,由于现实中的发病率在 1%左右,即使已经收集了大量未标记的数据,其中真正患病的数据数量仍然很少。然后,在考虑相关性的同时,如图 3 所示,我们首先使未标记集合具有足够的相关性(60%),但是改变未标记数据的不平衡比例。在这个实验中,我们将原始训练数据的不平衡比例固定为 50。可以看出,对于未标记数据,当未标记数据过于不平衡时(在这种情况下,不平衡比例高于 50),使用未标记数据实际上可能会使结果变得更糟。

上述问题在某些实际的不平衡学习任务中可能非常普遍。例如,在医疗/疾病诊断应用中,可以获得的未标记数据大多是从正常样本中采集的,这首先造成了数据的不平衡;其次,即使是有疾病的样本,也很可能是由许多其他混杂因素引起的,而这将降低疾病本身的相关性。因此,在一些难以使用半监督学习的极端情况下,我们需要一种完全不同但也有效的方法。自然,我们就从 的角度出发,解释另一个思路——自我监督学习。

来自自我监督的不平衡学习

同样,我们从另一个理论模型开始研究不平衡的学习如何受益于自我监督。我们得到的结果也是鼓舞人心和有趣的:

  • 以高概率,我们使用通过自监督任务学习的表示获得满意的分类器,错误概率在特征维度上指数衰减;
  • 训练数据不平衡影响我们获得这样一个令人满意的分类器的概率。

自监督不平衡学习框架:为了利用自监督克服固有的“标签偏向”,我们提出在第一阶段抛弃标签信息,进行自监督预训练 (SSP)。该过程旨在从不平衡数据中学习独立于标签的更好的初始化/特征信息。过了这个阶段,我们可以用任何标准的训练方法来学习最终的模型。由于预训练与正常训练阶段使用的学习方法无关,因此该策略与任何现有的不平衡学习算法兼容。一旦自我监督产生良好的初始化,网络可以从预训练任务中受益,并最终学习更一般的表示。

实验:激动人心的实验部分又来了;)这次我们不需要额外的数据。除了在长尾 CIFAR-10/100 上验证算法之外,我们还在大规模数据集 ImageNet 的长尾版本上进行验证,以及在 Naturalist 中的一个真实基准上进行验证。对于自监督算法,我们采用经典的旋转预测和最新的对比学习方法 MoCo 。在附录中,我们还提供了更多的消融研究,比较了 4 种不同的自我监督方法的效果。

实验结果显示在下面的两个表中。简而言之,使用 SSP 可以在不同的(1)数据集,(2)不平衡率,和(3)不同的基本训练算法之间带来一致的和大的改进。

(图片由作者提供)

(图片由作者提供)

最后,我们还展示了自我监督的定性结果。和以前一样,我们分别绘制训练集和测试集的 t-SNE 投影。从图中我们不难发现,正常 CE 训练的决策边界会被头类样本大大改变,导致测试时尾类样本大量“泄漏”,不能很好的泛化。相比之下,使用 SSP 可以保持清晰的分离效果,并减少尾部样品的泄漏,尤其是相邻头尾类之间的泄漏。这个结果也可以直观的理解:自监督学习使用额外的任务来约束学习过程,更好的学习数据空间的结构,提取更全面的信息。因此可以有效缓解网络对高层语义特征的依赖和对尾部数据的过拟合。学习到的特征表示将更加健壮且易于概括,从而在下游任务中表现得更好。

(图片由作者提供)

结束语

总结这篇文章,我们首先尝试通过两种不同的观点来理解和利用不平衡数据(标签),即半监督自监督学习,并验证了这两种框架都可以改善不平衡学习问题。它有非常直观的理论分析和解释,用非常简洁通用的框架来改进长尾数据分布下的学习任务。这些结果可能会引起更广泛的不同应用领域的兴趣。最后,我附上了几个与本文相关的链接;感谢阅读!

https://github.com/YyzHarry/imbalanced-semi-self】代号 : 代号

网站 / 视频:https://www.mit.edu/~yuzhe/imbalanced-semi-self.html

呆在家里?为什么不造一个 GPU 盒子!

原文:https://towardsdatascience.com/stuck-at-home-why-not-build-a-gpu-box-ac93bee21786?source=collection_archive---------31-----------------------

构建定制计算机以适应深度学习模型(或玩 GTA V:)

作者图片

在使用机器学习应用程序工作了一段时间后,我很兴奋地尝试了一些深度学习模型。可能我在开始时面临的最大障碍是工作流,特别是找到一个可访问的、流动的 GPU 驱动的工作环境。我的 Mac Pro(被亲切地称为垃圾桶型号)没什么用。我开始使用云服务,但怀念在没有仪表运行的情况下拥有自己的存储数据和运行代码的地方。所以我决定自己造一个 GPU 盒子。起初,这是相当令人生畏的(大写 I),但事情进行得相当顺利,最终结果是非常令人满意的。万一我的冒险对你有意思或有帮助,就在这里!

作者图片

母板

华硕 ROG Strix B360-I

我从移动电话开始。让我先说一下,如果你想使用多个 GPU,这个版本不会在没有修改的情况下适用于你的情况。我决定用单个 GPU 构建一个迷你 ITX 外形(即小型)的机器,因为这是我的第一次构建,我认为这将具有足够的挑战性。此外,我喜欢我的房子有一种装饰和组装的感觉,包括我的办公室。我并不是想创造一个拥有巨大霓虹灯塔的人类洞穴游戏天堂。但是我可以说,我爱这块板!对于游戏玩家来说,这是我为该系统购买的唯一一个 RGB 项目,它非常完美。但是在实际的构建中,真正的好处是内置的 I/O 屏蔽。正如一个有用的 youtube 游戏电脑组装先生指出的,安装防护罩可能是最具挑战性的部分。你已经是建造自己钻机的英雄了;你可以抓住机会而不会感到内疚。

情况

Thermaltake Core V1 雪景版

我在过程的早期就决定了这个案例,因为它决定了其他一些组件可能的大小。这也很有趣,因为有很多选择。我选择核心 V1 是因为,虽然它肯定是一个迷你,但它不是超级小,所以仍然有足够的空间来放置电缆等。一些需要注意的事情是:CPU 冷却器的高度,GPU 的长度,以及 3)电源的长度(PSU)。这个箱子设计得非常好。我喜欢这一事实,即董事会坐在垂直而不是侧面,所以你的组件不是“挂在亲爱的生活”作为一个评论家指出。

中央处理器

英特尔酷睿 i7–8700k

我想我可能在处理器上买多了。我必须有第 8 代才能适应主板,但型号中的“K”意味着处理器没有锁定,因此可以“超频”这是推动处理器比正常速度更快的游戏语言;然而,我的主板无论如何都不支持这个功能(它是 B 系列而不是 Z 系列)。

CPU 冷却器/散热器

配备 NF-A9 92 毫米风扇的 NOC tua NH-U9S

冷却器可能是一台小机器上的一个地方,在那里你会多付一点钱,但这是我列表中评价最高的项目(评论者星级)。它仍然比许多液体冷却器便宜(尽管没有那么可爱)。另外,谁会因为东西太便宜而不愿意多花 30 美元就把它们烧掉呢?你会学会爱这个孩子的。

随机存取存储

海盗船复仇 LPX 32GB(2x16GB)DDR 4 DRAM 2666 MHz

对 RAM 没有太多评论。我决定最大限度地发挥董事会的作用。这些棍子位置很低,因此将风扇安装在散热器上清理它们并不困难。

储存;储备

三星 860 EVO 1TB 2.5 英寸 SATA III SSD

目前我有一个固态硬盘。箱子里有专门的空间,如果需要的话可以再加一秒钟。

到目前为止建筑

作者图片

作者图片

供电设备

EVGA Supernova 650 G3,80 Plus Gold 650W,完全模块化

对于 PSU,我使用了 GPU 指定的推荐功率(“完全模块化”意味着没有预先连接电缆,所以您只使用您需要的)。PSU 是我最担心能不能装进箱子里的部分,但它还是进去了。

作者图片

作者图片

国家政治保卫局。参见 OGPU

微星 GeForce RTX 2070

最后,也是最重要的部分。我选择 RTX 2070 是因为它的性价比。定制机器的另一个好处是,如果需要,你可以在未来相对容易地更新你的 GPU。

作者图片

作者图片

作者图片

成品

只要有一点计划和运气,这一切都非常适合!现在你已经完成了硬件,你可以开始安装软件,将你的机器变成一台深度学习机器。

作者图片

学生在 R 和手工中的 t 检验:如何在不同场景下比较两组

原文:https://towardsdatascience.com/students-t-test-in-r-and-by-hand-how-to-compare-two-groups-under-different-scenarios-5ad79fce2130?source=collection_archive---------32-----------------------

学生对两个样本的 t 检验用于检验两组是否不同,基于从这两组中抽取的两个样本的比较。我们展示了如何在 r 中手工计算它。

照片由杰森·登特拍摄

介绍

推断统计学分支中最重要的测试之一是学生的 t-测试。 1 学生对两个样本的 t 检验用于检验两组(两个群体)在一个定量变量方面是否不同,基于从这两组中抽取的两个样本的比较。换句话说,一个学生对两个样本的 t 检验可以确定你的两个样本所来自的两个群体是否不同(这两个样本是在一个定量连续变量上测量的)。 2

这种统计检验背后的推理是,如果你的两个样本明显不同,可以假设从中抽取样本的两个总体是不同的。相反,如果两个样本相当相似,我们就不能拒绝两个群体相似的假设,所以在手头的数据中没有足够的证据可以得出样本从中抽取的两个群体是不同的结论。请注意,这种统计工具属于推断统计学的一个分支,因为从样本研究中得出的结论可以推广到总体,即使我们没有整个总体的数据。

为了比较两个样本,通常要比较每个样本的集中趋势。在学生 t 检验的情况下,均值用于比较两个样本。然而,在某些情况下,平均值不适于比较两个样本,因此通过威尔科克森检验使用中值来比较它们。这篇文章已经很长很完整了,Wilcoxon 测试在另一篇文章中有所涉及,同时还有一些关于何时使用其中一种测试的说明。

这两种检验(Student’s t 检验和 Wilcoxon 检验)具有相同的最终目标,即比较两个样本,以确定从中抽取样本的两个群体是否不同。请注意,学生的 t 检验比 Wilcoxon 检验更有效(即,如果存在真正的差异,它更经常检测到显著差异,因此学生的 t 检验可以检测到较小的差异),但学生的 t 检验对异常值和数据不对称很敏感。此外,在这两种测试的每一种中,都存在几个版本,每个版本使用不同的公式来得出最终结果。因此,有必要了解两种测试之间的差异以及使用哪种版本,以便根据问题和手头的数据进行适当的分析。

在本文中,我将首先一步一步地详细说明如何手工执行独立样本和配对样本的所有版本的学生 t 检验。为了说明和方便起见,将对一小组观察值进行分析。然后,我将展示如何用完全相同的数据在 R 中执行这个测试,以便验证手工发现的结果。还将介绍假设检验背后的推理、p 值和结果的解释以及该检验的假设。

请注意,本文的目的是展示如何用 R 手工计算学生的 t 检验,因此我们避免测试假设,并假设在本练习中所有假设都满足。为了完整性,我们仍然提到假设,如何测试它们,以及如果有一个不满足,还有什么其他测试。感兴趣的读者可以看看文章的结尾,了解更多关于这些假设的信息。

无效假设和替代假设

在开始手动计算学生的 t 检验之前,让我们回顾一下该检验的无效假设和替代假设:

  • H0: μ1=μ2
  • H1: μ1≠μ2

其中μ1 和μ2 是从中抽取样本的两个总体的平均值。

如简介中所述,虽然从技术上讲学生的 t 检验是基于两个样本的均值比较,但这种检验的最终目标实际上是检验以下假设:

  • H0:这两个群体很相似
  • H1:这两种人群是不同的

这是在一般情况下,我们只想确定两个群体是否不同(就因变量而言)。从这个意义上来说,我们事先并不认为某个特定群体比另一个群体大或小。这种测试被称为双边或双边测试。

如果我们对一个群体比另一个群体大或小有一些先验信念,学生的 t 检验也允许检验以下假设:

  • H0: μ1=μ2
  • H1: μ1>μ2

或者

  • H0: μ1=μ2
  • H1: μ1

In the first case, we want to test if the first population is significantly larger than the second, while in the latter case, we want to test if the first population is significantly smaller than the second. This type of test is referred as a 单边或单边测试。

一些作者认为,在实践中不应该使用单边检验,原因很简单,如果一个研究人员如此确信一个群体比另一个群体大(小),并且永远不会比另一个群体小(大),为什么她还需要检验显著性呢?这是一个相当哲学的问题,超出了本文的范围。感兴趣的读者被邀请去看 Rowntree (2000)中的部分讨论。

假设检验

在统计学中,许多统计检验是以假设检验的形式进行的。假设检验用于根据手头的数据(即样本)确定某个信念是否为真(似是而非)。大多数假设检验可以归结为以下 4 个步骤: 3

  1. 陈述无效假设和替代假设。
  2. 计算测试统计量,表示为 t-stat。计算检验统计量的公式在不同版本的学生 t 检验中有所不同,但它们具有相同的结构。请参见下面的场景 1 至 5,了解不同的公式。
  3. 给定测试的理论统计分布、分布参数和显著性水平α,找出临界值。对于一个学生的 t 检验及其扩展版本,要么是正态分布,要么是学生的 t 分布( t 表示学生分布, z 表示正态分布)。
  4. 通过比较 t-stat(在步骤 2 中找到)得出结论。)与临界值(在步骤中找到。3).如果 t-stat 位于拒绝区域(由临界值和测试方向决定),我们拒绝零假设,否则我们不拒绝零假设。这两个选项(拒绝或不拒绝零假设)是仅有的两个可能的解决方案,我们从不“接受”一个假设。总是根据最初的问题来解释决定也是一个好的做法。

学生 t 检验的不同版本

根据样本是独立的还是成对的,以及根据总体的方差,两个样本的学生 t 检验有几种版本:

一方面,独立样本是指在不同的实验单位或不同的个体上采集的两个样本,例如当我们分别对女性和男性进行研究,或者对被随机分配到对照组和治疗组的患者进行研究时(一个患者只属于一个组)。另一方面,当测量是在相同的实验单元、相同的个体上收集时,我们面对成对的样本。例如在医学研究中,当在两个不同的时间测试治疗的效率时,经常会出现这种情况。在治疗前和治疗后,对相同的患者进行两次测量,在计算检验统计数据时,必须考虑两个样本之间的相关性,对每个受试者的测量值进行差异处理。成对样本通常是两个不同时间的测量结果,但不排除其他情况。假设我们要测试 50 名运动员左右眼的视力差异。虽然测量不是在两个不同的时间(之前-之后)进行的,但是很明显,每一个对象的双眼都是相互依赖的。因此,应该使用学生对成对样本的 t 检验来说明两个样本之间的相关性,而不是标准的学生对独立样本的 t 检验。

选择合适的学生 t 检验版本的另一个标准是总体的方差(不是样本的方差!)是已知的或未知的,是相等的或不相等的。这个标准相当简单,我们要么知道总体的方差,要么不知道。无法计算总体的方差,因为如果您可以计算总体的方差,这意味着您有整个总体的数据,那么就没有必要再进行假设检验了…所以总体的方差要么在语句中给出(在这种情况下使用它们),要么没有关于这些方差的信息,在这种情况下,假设方差是未知的。在实践中,总体的方差在大多数情况下是未知的,为了选择合适的测试版本,唯一要做的就是检查方差是否相等。然而,在假设检验的 4 个步骤之后的下一节中,我们仍然说明了如何手工和在 R 中做这个检验的所有版本。

如何手工计算学生的 t-test?

请注意,这些数据是人为的,并不代表任何真实的变量。此外,提醒可能满足也可能不满足假设。本文的重点是详细说明如何手工和在 R 中计算不同版本的测试,所以所有的假设都被假定为满足。此外,假设所有测试的显著性水平α=5%。

如果你对手工应用这些测试感兴趣,而不需要自己做计算,这里有一个闪亮的应用程序可以帮你做。你只需要输入数据,并通过侧边栏菜单选择合适的测试版本。还有一个图形表示,帮助您可视化测试统计和拒绝区域。希望你会觉得有用!

场景 1:具有 2 个已知方差的独立样本

对于第一个场景,假设下面的数据。此外,假设两个样本是独立的,两个总体的方差都等于 1,并且我们想检验两个总体是否不同。

所以我们有:

  • 每个样本中的 5 个观察值:n1=n2=5
  • 样本 1 的平均值= 0.02
  • 样本 2 的平均值= 0.06
  • 两个总体的方差= 1

按照假设检验的 4 个步骤,我们有:

  1. H0: μ1=μ2,H1:μ1μ2≠0。(≠因为要测试两种手段是否不同,所以在测试中不强加方向。)
  2. 测试统计:

3.临界值:z(α/2)= z(0.025)= 1.96(如果你很难找到临界值,请参见如何阅读统计表的指南)

4.结论:因此,拒绝区域从∞到-1.96 和从 1.96 到+∞。检验统计量在拒绝区域之外,所以我们不拒绝零假设 H0。就最初的问题而言:在 5%的显著性水平上,我们不排斥两个总体相同的假设,或者数据中没有足够的证据可以得出所考虑的两个总体不同的结论。

场景 2:具有 2 个相等但未知方差的独立样本

对于第二种情况,假设下面的数据。此外,假设两个样本是独立的,两个总体中的方差未知但相等,并且我们想测试总体 1 是否大于总体 2。

所以我们有:

  • 样本 1 中的 6 个观察值:n1=6
  • 样本 2 中的 5 个观察值:n2=5
  • 样本 1 的平均值= 1.247
  • 样本 2 的平均值= 0.1
  • 样本 1 的方差= 0.303
  • 样本 2 的方差= 0.315

按照假设检验的 4 个步骤,我们有:

  1. H0: μ1=μ2,H1:μ1-μ2 > 0。(>因为我们要检验第一个总体的均值是否大于第二个总体的均值。)
  2. 测试统计:

在哪里

因此

(请注意,由于假设两个总体的方差相等,因此会计算一个混合(公共)方差,表示为 s_p。)

3.临界值:t(α,n1+N2 2)= t(0.05,9)=1.833

4.结论:拒绝区域因此从 1.833 到+∞(只有一个拒绝区域,因为它是单侧测试)。检验统计量位于拒绝区域内,因此我们拒绝零假设 H0。就最初的问题而言:在 5%的显著性水平上,我们得出的结论是,总体 1 大于总体 2。

场景 3:具有 2 个不相等且未知方差的独立样本

对于第三种情况,假设下面的数据。此外,假设两个样本是独立的,两个总体中的方差都是未知且不相等的,并且我们想要检验总体 1 是否小于总体 2。

所以我们有:

  • 样本 1 中的 5 个观察值:n1=5
  • 样本 2 中的 6 个观察值:n2=6
  • 样本 1 的平均值= 0.42
  • 样本 2 的平均值= 1.247
  • 样本 1 的方差= 0.107
  • 样本 2 的方差= 0.303

按照假设检验的 4 个步骤,我们有:

  1. H0: μ1=μ2,H1:μ1-μ2 < 0。(
  2. 测试统计:

3.临界值:t(α,υ)其中

因此

自由度 8.28 在标准学生分布表中是不存在的,那就简单的取 8,或者用qt(p = 0.05, df = 8.28)在 R 中计算。

4.结论:因此,拒绝区域从∞到-1.851。检验统计量位于拒绝区域内,因此我们拒绝零假设 H0。就最初的问题而言:在 5%的显著性水平上,我们的结论是总体 1 小于总体 2。

场景 4:差异方差已知的配对样本

成对样本的学生 t 检验与独立样本的稍有不同,它们实际上更类似于单个样本的学生 t 检验。这是它的工作原理。我们实际上计算每对观察值的两个样本之间的差异,然后我们通过计算这些差异的检验统计量来处理这些差异,就像我们在做单样本学生 t 检验一样。

如果不清楚的话,这里有第四个场景作为说明。假设下面的数据。此外,假设两个样本是相关的(匹配的),总体差异的方差已知且等于 1,并且我们想测试总体差异是否不等于 0。

首先要做的是计算所有观测值对的差异:

所以我们有:

  • 对数:n=5
  • 差异的平均值= 0.04
  • 总体差异的方差= 1
  • 总体差异的标准偏差= 1

按照假设检验的 4 个步骤,我们有:

  1. H0: μD=0,H1: μD≠0
  2. 测试统计:

(这个公式与一个样本学生的方差已知的 t 检验公式完全相同,只是我们处理的是方差的平均值。)

3.临界值:z(α/2)= z(0.025)= 1.96

4.结论:因此,拒绝区域从∞到-1.96 和从 1.96 到+∞。检验统计量在拒绝区域之外,所以我们不拒绝零假设 H0。就最初的问题而言:在 5%的显著性水平上,我们不拒绝两个总体的差异等于 0 的假设。

场景 5:差异方差未知的配对样本

对于第五个也是最后一个场景,假设下面的数据。此外,假设两个样本是相关的(匹配的),总体差异的方差是未知的,并且我们想测试一种治疗在增加跑步能力方面是否有效(数值越高,跑步能力越好)。

首先要做的是计算所有观测值对的差异:

所以我们有:

  • 对数:n=5
  • 差异的平均值= 8
  • 样本差异的方差= 16
  • 样本差异的标准偏差= 4

按照假设检验的 4 个步骤,我们有:

  1. H0: μD=0 和 H1: μD>0(>因为我们想测试治疗是否有效,所以治疗是否对跑步能力有积极影响。)
  2. 测试统计:

(这个公式与一个样本学生的方差未知的 t 检验公式完全相同,只是我们处理的是方差的平均值。)

3.临界值:t(α,n1)= t(0.05,4)=2.132 ( n 是对数,不是观测数!)

4.结论:拒绝域从 2.132 到+∞。检验统计量位于拒绝区域内,因此我们拒绝零假设 H0。根据最初的问题:在 5%的显著性水平,我们得出结论,治疗对跑步能力有积极的影响。

这里总结了如何手工对两个样本执行不同版本的学生 t 检验。在接下来的小节中,我们将详细介绍如何在 r 中执行完全相同的测试。

如何计算学生在 R 中的 t 检验?

在 R 中进行 t-tests 之前,一个好的实践是借助箱线图(或者密度图,或者最终两者都有)按组可视化数据。两个方框相互重叠的箱线图给出了两个样本相似的第一个指示,因此,可以不拒绝相等平均值的零假设。相反,如果两个框不重叠,则表明两个样本不相似,因此,群体可能不同。然而,即使箱线图或密度图能很好地显示两组之间的比较,只有可靠的统计测试才能证实我们的第一印象。

在按组可视化数据后,我们在 R 中复制手工发现的结果。我们将看到,对于 t-test 的某些版本,R 中没有内置默认函数(至少就我所知,如果我弄错了,请不要犹豫让我知道)。在这些情况下,编写一个函数来手动复制结果。

请注意,我们对所有 5 个场景使用了相同的数据、相同的假设和相同的问题,以便于比较手工测试和 r。

场景 1:具有 2 个已知方差的独立样本

对于第一个场景,假设下面的数据。此外,假设两个样本是独立的,两个总体的方差都等于 1,并且我们想检验两个总体是否不同。

dat1 <- data.frame(
  sample1 = c(0.9, -0.8, 0.1, -0.3, 0.2),
  sample2 = c(0.8, -0.9, -0.1, 0.4, 0.1)
)
dat1##   sample1 sample2
## 1     0.9     0.8
## 2    -0.8    -0.9
## 3     0.1    -0.1
## 4    -0.3     0.4
## 5     0.2     0.1dat_ggplot <- data.frame(
  value = c(0.9, -0.8, 0.1, -0.3, 0.2, 0.8, -0.9, -0.1, 0.4, 0.1),
  sample = c(rep("1", 5), rep("2", 5))
)library(ggplot2)ggplot(dat_ggplot) +
  aes(x = sample, y = value) +
  geom_boxplot() +
  theme_minimal()

注意,如果你想用 [{ggplot2}](https://www.statsandr.com/blog/graphics-in-r-with-ggplot2/)画一个方框图而不自己写代码,你可以使用[{esquisse}](https://www.statsandr.com/blog/rstudio-addins-or-how-to-make-your-coding-life-easier/#esquisse) RStudio addin 。如果你喜欢默认图形,使用boxplot()功能:

boxplot(value ~ sample,
  data = dat_ggplot
)

这两个方框似乎重叠,说明这两个样本非常相似,因此我们倾向于认为我们无法拒绝两个总体相似的零假设。然而,只有正式的统计测试才能证实这一观点。

由于 R 中没有使用已知方差来执行 t 检验的函数,因此这里有一个函数,其参数接受两个样本(xy)、总体的两个方差(V1V2)、零假设下均值的差异(m0,默认为0)、显著性水平(alpha,默认为0.05)以及备选项(alternative"two.sided"(默认)、"less""greater"之一):

t.test_knownvar <- function(x, y, V1, V2, m0 = 0, alpha = 0.05, alternative = "two.sided") {
  M1 <- mean(x)
  M2 <- mean(y)
  n1 <- length(x)
  n2 <- length(y)
  sigma1 <- sqrt(V1)
  sigma2 <- sqrt(V2)
  S <- sqrt((V1 / n1) + (V2 / n2))
  statistic <- (M1 - M2 - m0) / S
  p <- if (alternative == "two.sided") {
    2 * pnorm(abs(statistic), lower.tail = FALSE)
  } else if (alternative == "less") {
    pnorm(statistic, lower.tail = TRUE)
  } else {
    pnorm(statistic, lower.tail = FALSE)
  }
  LCL <- (M1 - M2 - S * qnorm(1 - alpha / 2))
  UCL <- (M1 - M2 + S * qnorm(1 - alpha / 2))
  value <- list(mean1 = M1, mean2 = M2, m0 = m0, sigma1 = sigma1, sigma2 = sigma2, S = S, statistic = statistic, p.value = p, LCL = LCL, UCL = UCL, alternative = alternative)
  # print(sprintf("P-value = %g",p))
  # print(sprintf("Lower %.2f%% Confidence Limit = %g",
  #               alpha, LCL))
  # print(sprintf("Upper %.2f%% Confidence Limit = %g",
  #               alpha, UCL))
  return(value)
}test <- t.test_knownvar(dat1$sample1, dat1$sample2,
  V1 = 1, V2 = 1
)
test## $mean1
## [1] 0.02
## 
## $mean2
## [1] 0.06
## 
## $m0
## [1] 0
## 
## $sigma1
## [1] 1
## 
## $sigma2
## [1] 1
## 
## $S
## [1] 0.6324555
## 
## $statistic
## [1] -0.06324555
## 
## $p.value
## [1] 0.949571
## 
## $LCL
## [1] -1.27959
## 
## $UCL
## [1] 1.19959
## 
## $alternative
## [1] "two.sided"

以上输出概括了执行测试所需的所有信息:测试统计量、p-值、所用替代方案、两个样本平均值和总体的两个方差(将 R 中的结果与手工找到的结果进行比较)。

p-值可以照常提取:

test$p.value## [1] 0.949571

p-值为 0.95,因此在 5%显著性水平下,我们不拒绝相等平均值的零假设。数据中没有足够的证据拒绝这两种方法在人群中相似的假设。这个结果证实了我们手工发现的东西。

关于 p 值和显著性水平α的注记

对于那些不熟悉p-值概念的人来说,p-值是一个概率,和任何概率一样,它是从 0 到 1。p-值是在零假设为真的情况下,观察结果与我们测量的结果(通过样本)一样极端的概率。换句话说,假设零假设是真的,它是测试统计量和我们计算的一样极端的概率。如果观察结果不那么极端——如果零假设是真的,也不太可能发生——我们不会拒绝这个零假设,因为它被认为是可信的。如果这些观察结果被认为过于极端——在零假设的情况下不太可能发生——我们会拒绝零假设,因为它被认为太不可信而不真实。请注意,这并不意味着我们 100%确定这种可能性太大,有时会出现零假设被拒绝的情况,尽管它是真的(参见后面的显著性水平α)。

在上面的例子中,观察结果并不极端,两个平均值之间的差异也不极端,因此检验统计量也不极端(因为检验统计量部分基于两个样本平均值的差异)。拥有一个非极端的检验统计量并非不可能,这就是为什么 p 值很高的原因。p-0.95 的值实际上告诉我们,假设群体中的平均值差异为 0(零假设),则两个样本的平均值差异为-0.04(= 0.02–0.06)的概率等于 95%。95%的概率被明确认为是合理的,因此我们并不拒绝总体均值相等的零假设。

人们可能会想,“对于一个测试统计来说,什么太极端了?”大多数时候,我们认为,假设零假设为真,当出现这种极端检验统计量的概率低于 5%时,检验统计量过于极端,不可能偶然发生。你在统计学课程或教科书中非常经常看到的 5% (α=0.05)的阈值是许多领域使用的阈值。当一个p-值低于 5%的阈值时,我们认为如果零假设为真,观察值(以及测试统计量)是不太可能偶然发生,因此零假设被拒绝。当一个p-值高于 5%的阈值时,我们认为,如果零假设是真的,面对我们所得到的观察结果并不是不合理的,因此我们不拒绝零假设。

注意,我写的是“我们不拒绝零假设”,而不是“我们接受零假设”。这是因为有可能零假设事实上是错误的,但我们无法用样本证明这一点。假设一个嫌疑犯被指控谋杀,而我们不知道真相。一方面,如果我们收集了足够的证据证明嫌疑犯犯了谋杀罪,他就被认为有罪:我们拒绝他是无辜的无效假设。另一方面,如果我们没有收集到足够的对嫌疑犯不利的证据,尽管他可能实际上犯了罪,他还是被假定是无辜的:我们不能拒绝他是无辜的无效假设。即使他被释放了,我们也不能确定他没有犯罪,我们只是没有找到足够的证据来反对嫌疑人无罪的假设。这就是为什么我们不拒绝零假设,而是接受它的原因,也是为什么你会经常读到“数据中没有足够的证据来拒绝零假设”或“基于样本,我们无法拒绝零假设”之类的话。

显著性水平 α,来源于前面提到的阈值 5%,是当零假设事实上为真时拒绝零假设的概率。在这个意义上,为了能够得出结论,我们接受处理的是一个误差(5%)。如果我们不接受任何误差(0%的误差),我们将无法得出关于总体的任何结论,因为我们只能通过样本访问有限部分的总体。因此,在解释假设检验的结果时,我们永远不会有 100%的把握,除非我们可以获得整个群体的数据,但这样就没有理由再做假设检验了,因为我们可以简单地比较两个群体。我们通常允许这种误差(称为 I 型误差)为 5%,但为了在得出我们拒绝零假设的结论时更加确定,alpha 水平也可以设置为 1%(在一些罕见的情况下甚至可以设置为 0.1%)。

总结一下关于 p 你需要记住的——值和显著性水平α:

  • 如果 p 值小于预定的显著性水平α(通常为 5%),那么如果 p 值<为 0.05,我们拒绝零假设
  • 如果 p 值大于或等于预定的显著性水平α(通常为 5%),那么如果 p 值≥ 0.05,我们不拒绝零假设

这毫无例外地适用于所有的统计测试。当然,无效假设和替代假设会随着测试的不同而变化。

经验法则是,对于大多数假设检验来说,替代假设是你想要检验的,而无效假设是现状。带着这个极度谨慎(!)因为,即使它适用于所有版本的学生 t 检验,它也不适用于所有的统计检验。例如,当测试正态性时,您通常希望测试您的分布是否遵循正态分布。根据这条建议,你可以写出另一个假设 H1:分布遵循正态分布。然而,对于正态性检验,如夏皮罗-维尔克或科尔莫戈罗夫-斯米尔诺夫检验,情况正好相反;另一个假设是 H1:分布不遵循正态分布。所以对于每个测试,确保使用正确的假设,否则你的测试的结论和解释将是错误的。

场景 2:具有 2 个相等但未知方差的独立样本

对于第二种情况,假设下面的数据。此外,假设两个样本是独立的,两个总体中的方差未知但相等,并且我们想测试总体 1 是否大于总体 2。

dat2 <- data.frame(
  sample1 = c(1.78, 1.5, 0.9, 0.6, 0.8, 1.9),
  sample2 = c(0.8, -0.7, -0.1, 0.4, 0.1, NA)
)
dat2##   sample1 sample2
## 1    1.78     0.8
## 2    1.50    -0.7
## 3    0.90    -0.1
## 4    0.60     0.4
## 5    0.80     0.1
## 6    1.90      NAdat_ggplot <- data.frame(
  value = c(1.78, 1.5, 0.9, 0.6, 0.8, 1.9, 0.8, -0.7, -0.1, 0.4, 0.1),
  sample = c(rep("1", 6), rep("2", 5))
)ggplot(dat_ggplot) +
  aes(x = sample, y = value) +
  geom_boxplot() +
  theme_minimal()

与前面的场景不同,这两个框没有重叠,这说明这两个样本彼此不同。从这个箱线图中,我们可以预期该检验会拒绝总体均值相等的零假设。尽管如此,只有正式的统计测试才能证实这一预期。

R 里面有一个函数,简单来说就是t.test()函数。这个版本的测试实际上是“标准”学生对两个样本的 t 检验。请注意,假设两个总体的方差相等,因此我们需要在函数中用参数var.equal = TRUE(默认为FALSE)指定它,另一个假设是 H1:μ1-μ2>0,因此我们还需要添加参数alternative = "greater":

test <- t.test(dat2$sample1, dat2$sample2,
  var.equal = TRUE, alternative = "greater"
)
test## 
##  Two Sample t-test
## 
## data:  dat2$sample1 and dat2$sample2
## t = 3.4113, df = 9, p-value = 0.003867
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
##  0.5304908       Inf
## sample estimates:
## mean of x mean of y 
##  1.246667  0.100000

上面的输出概括了执行测试所需的所有信息:测试的名称、测试统计、自由度、p-值、使用的备选项和两个样本均值(将 R 中找到的这些结果与手动找到的结果进行比较)。

可以照常提取 p 值:

test$p.value## [1] 0.003866756

p-值为 0.004,因此在 5%的显著性水平上,我们拒绝相等平均值的零假设。这个结果证实了我们手工发现的东西。

与第一个场景不同,这个场景中的p-值低于 5%,因此我们拒绝零假设。在 5%的显著性水平上,我们可以得出人口 1 大于人口 2 的结论。

在 R 中报告学生 t-test 结果的一种简单而又好的方法是使用{report}包中的report()函数:

# install.packages("remotes")
# remotes::install_github("easystats/report") # You only need to do that once
library("report") # Load the package every time you start Rreport(test)## Effect sizes were labelled following Cohen's (1988) recommendations.
## 
## The Two Sample t-test testing the difference between dat2$sample1 and dat2$sample2 (mean of x = 1.25, mean of y = 0.10) suggests that the effect is positive, significant and large (difference = 1.15, 95% CI [0.53, Inf], t(9) = 3.41, p < .01; Cohen's d = 2.07, 95% CI [0.52, 3.55])

如您所见,该函数为您解释了测试(以及p-值)。

注意report()功能可用于其他分析。如果你觉得这个有用,请查看 R 中的更多提示和技巧。

如果您的数据是长格式(长格式更好),只需使用~。例如,想象完全相同的数据如下所示:

dat2bis <- data.frame(
  value = c(1.78, 1.5, 0.9, 0.6, 0.8, 1.9, 0.8, -0.7, -0.1, 0.4, 0.1),
  sample = c(rep("1", 6), rep("2", 5))
)
dat2bis##    value sample
## 1   1.78      1
## 2   1.50      1
## 3   0.90      1
## 4   0.60      1
## 5   0.80      1
## 6   1.90      1
## 7   0.80      2
## 8  -0.70      2
## 9  -0.10      2
## 10  0.40      2
## 11  0.10      2

下面是如何用长数据在 R 中执行学生的 t 检验:

test <- t.test(value ~ sample,
  data = dat2bis,
  var.equal = TRUE,
  alternative = "greater"
)
test## 
##  Two Sample t-test
## 
## data:  value by sample
## t = 3.4113, df = 9, p-value = 0.003867
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
##  0.5304908       Inf
## sample estimates:
## mean in group 1 mean in group 2 
##        1.246667        0.100000test$p.value## [1] 0.003866756

结果完全一样。

场景 3:具有 2 个不相等且未知方差的独立样本

对于第三种情况,假设下面的数据。此外,假设两个样本是独立的,两个总体中的方差都是未知且不相等的,并且我们想要检验总体 1 是否小于总体 2。

dat3 <- data.frame(
  value = c(0.8, 0.7, 0.1, 0.4, 0.1, 1.78, 1.5, 0.9, 0.6, 0.8, 1.9),
  sample = c(rep("1", 5), rep("2", 6))
)
dat3##    value sample
## 1   0.80      1
## 2   0.70      1
## 3   0.10      1
## 4   0.40      1
## 5   0.10      1
## 6   1.78      2
## 7   1.50      2
## 8   0.90      2
## 9   0.60      2
## 10  0.80      2
## 11  1.90      2ggplot(dat3) +
  aes(x = sample, y = value) +
  geom_boxplot() +
  theme_minimal()

对于这个版本的测试,R 中也有一个函数,它就是带有var.equal = FALSE参数的t.test()函数。FALSEvar.equal参数的默认选项,因此您实际上不需要指定它。这个版本的检验实际上是韦尔奇检验,当总体的方差未知且不相等时使用。要测试两个方差是否相等,可以使用 Levene 的测试({car}包中的leveneTest(dat3$value, dat3$sample))。请注意,另一个假设是 H1:μ1-μ2<0,因此我们还需要添加参数alternative = "less":

test <- t.test(value ~ sample,
  data = dat3,
  var.equal = FALSE,
  alternative = "less"
)
test## 
##  Welch Two Sample t-test
## 
## data:  value by sample
## t = -3.0841, df = 8.2796, p-value = 0.007206
## alternative hypothesis: true difference in means is less than 0
## 95 percent confidence interval:
##        -Inf -0.3304098
## sample estimates:
## mean in group 1 mean in group 2 
##        0.420000        1.246667

上面的输出概括了执行测试所需的所有信息(将 R 中找到的结果与手工找到的结果进行比较)。

可以照常提取 p 值:

test$p.value## [1] 0.00720603

p-值为 0.007,因此在 5%的显著性水平上,我们拒绝了均值相等的零假设,这意味着我们可以得出人口 1 小于人口 2 的结论。这个结果证实了我们手工发现的东西。

场景 4:差异方差已知的配对样本

对于第四种情况,假设下面的数据。此外,假设两个样本是相关的(匹配的),总体差异的方差已知且等于 1,并且我们想测试总体差异是否不等于 0。

dat4 <- data.frame(
  before = c(0.9, -0.8, 0.1, -0.3, 0.2),
  after = c(0.8, -0.9, -0.1, 0.4, 0.1)
)
dat4##   before after
## 1    0.9   0.8
## 2   -0.8  -0.9
## 3    0.1  -0.1
## 4   -0.3   0.4
## 5    0.2   0.1dat4$difference <- dat4$after - dat4$beforeggplot(dat4) +
  aes(y = difference) +
  geom_boxplot() +
  theme_minimal()

由于 R 中没有函数在已知差异方差的情况下对成对样本执行 t 检验,因此这里有一个函数的参数接受两个样本之间的差异(x)、总体差异方差(V)、零假设下的差异均值(m0,默认为0)、显著性水平(alpha,默认为0.05)以及备选项(alternative"two.sided"(默认)、"less""greater"):

t.test_pairedknownvar <- function(x, V, m0 = 0, alpha = 0.05, alternative = "two.sided") {
  M <- mean(x)
  n <- length(x)
  sigma <- sqrt(V)
  S <- sqrt(V / n)
  statistic <- (M - m0) / S
  p <- if (alternative == "two.sided") {
    2 * pnorm(abs(statistic), lower.tail = FALSE)
  } else if (alternative == "less") {
    pnorm(statistic, lower.tail = TRUE)
  } else {
    pnorm(statistic, lower.tail = FALSE)
  }
  LCL <- (M - S * qnorm(1 - alpha / 2))
  UCL <- (M + S * qnorm(1 - alpha / 2))
  value <- list(mean = M, m0 = m0, sigma = sigma, statistic = statistic, p.value = p, LCL = LCL, UCL = UCL, alternative = alternative)
  # print(sprintf("P-value = %g",p))
  # print(sprintf("Lower %.2f%% Confidence Limit = %g",
  #               alpha, LCL))
  # print(sprintf("Upper %.2f%% Confidence Limit = %g",
  #               alpha, UCL))
  return(value)
}test <- t.test_pairedknownvar(dat4$after - dat4$before,
  V = 1
)
test## $mean
## [1] 0.04
## 
## $m0
## [1] 0
## 
## $sigma
## [1] 1
## 
## $statistic
## [1] 0.08944272
## 
## $p.value
## [1] 0.9287301
## 
## $LCL
## [1] -0.8365225
## 
## $UCL
## [1] 0.9165225
## 
## $alternative
## [1] "two.sided"

上面的输出概括了执行测试所需的所有信息(将 R 中找到的结果与手工找到的结果进行比较)。

可以照常提取p-值:

test$p.value## [1] 0.9287301

p-值为 0.929,因此在 5%的显著性水平上,我们不拒绝差异均值等于 0 的零假设。数据中没有足够的证据否定两个人群的差异等于 0 的假设。这个结果证实了我们手工发现的东西。

场景 5:差异方差未知的配对样本

对于第五个也是最后一个场景,假设下面的数据。此外,假设两个样本是相关的(匹配的),总体差异的方差是未知的,并且我们想测试一种治疗在增加跑步能力方面是否有效(数值越高,跑步能力越好)。

dat5 <- data.frame(
  before = c(9, 8, 1, 3, 2),
  after = c(16, 11, 15, 12, 9)
)
dat5##   before after
## 1      9    16
## 2      8    11
## 3      1    15
## 4      3    12
## 5      2     9dat5$difference <- dat5$after - dat5$beforeggplot(dat5) +
  aes(y = difference) +
  geom_boxplot() +
  theme_minimal()

对于这个版本的测试,R 中有一个函数,它就是带有paired = TRUE参数的t.test()函数。这个版本的测试实际上是学生配对样本 t 检验的标准版本。注意,另一个假设是 H1: μD > 0,所以我们也需要添加参数alternative = "greater":

test <- t.test(dat5$after, dat5$before,
  alternative = "greater",
  paired = TRUE
)
test## 
##  Paired t-test
## 
## data:  dat5$after and dat5$before
## t = 4.4721, df = 4, p-value = 0.005528
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
##  4.186437      Inf
## sample estimates:
## mean of the differences 
##                       8

注意,我们按照这个顺序写了after,然后是before。如果先写before,再写after,一定要把备选改为alternative = "less"

如果您的数据是长格式,使用~:

dat5 <- data.frame(
  value = c(9, 8, 1, 3, 2, 16, 11, 15, 12, 9),
  time = c(rep("before", 5), rep("after", 5))
)
dat5##    value   time
## 1      9 before
## 2      8 before
## 3      1 before
## 4      3 before
## 5      2 before
## 6     16  after
## 7     11  after
## 8     15  after
## 9     12  after
## 10     9  aftertest <- t.test(value ~ time,
  data = dat5,
  alternative = "greater",
  paired = TRUE
)
test## 
##  Paired t-test
## 
## data:  value by time
## t = 4.4721, df = 4, p-value = 0.005528
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
##  4.186437      Inf
## sample estimates:
## mean of the differences 
##                       8

上面的输出概括了执行测试所需的所有信息(将 R 中找到的结果与手工找到的结果进行比较)。

可以照常提取 p 值:

test$p.value## [1] 0.005528247

p-值为 0.006,因此在 5%的显著性水平上,我们拒绝了差异均值等于 0 的零假设,这意味着我们可以得出结论,该治疗在提高跑步能力方面是有效的。这个结果证实了我们手工发现的东西。

绘图和统计检验相结合

写完这篇文章后,我发现了{ggstatsplot}包,我认为这里值得一提,特别是分别用于独立样本和配对样本的ggbetweenstats()ggwithinstats()函数。

这两个函数组合了一个图(代表每个组的分布)和显示在图的副标题中的统计测试结果。

请参见以下场景 2、3 和 5 的示例。不幸的是,这个包不允许运行场景 1 和场景 4 的测试。

场景 2

ggbetweenstats()功能用于独立样本:

# load package
library(ggstatsplot)
library(ggplot2)# plot with statistical results
ggbetweenstats(
  data = dat2bis,
  x = sample,
  y = value,
  plot.type = "box", # for boxplot
  type = "parametric", # for student's t-test
  var.equal = TRUE, # equal variances
  centrality.plotting = FALSE # remove mean
) +
  labs(caption = NULL) # remove caption

p-值(显示在p =之后)是使用t.test()函数获得的值的两倍,因为当我们运行t.test()时,我们指定了alternative = "greater"(即单边测试)。在我们使用ggbetweenstats()函数的图中,这是一个默认执行的双边测试,即alternative = "two.sided"

场景 3

我们也有独立的样本,所以我们再次使用ggbetweenstats()函数,但是这一次两个总体的方差并不相等,所以我们指定参数var.equal = FALSE:

# plot with statistical results
ggbetweenstats(
  data = dat3,
  x = sample,
  y = value,
  plot.type = "box", # for boxplot
  type = "parametric", # for student's t-test
  var.equal = FALSE, # unequal variances
  centrality.plotting = FALSE # remove mean
) +
  labs(caption = NULL) # remove caption

注意,出于与上述相同的原因,图的副标题中显示的p-值也比使用t.test()功能时大两倍。

场景 5

在这种情况下,样本是成对的,因此我们使用ggwithinstats()函数:

ggwithinstats(
  data = dat5,
  x = time,
  y = value,
  type = "parametric", # for student's t-test
  centrality.plotting = FALSE # remove mean
) +
  labs(caption = NULL) # remove caption

同样,图的副标题中的p-值是使用t.test()函数获得的值的两倍,原因同上。

然而,本节的重点是说明如何轻松绘制带有统计结果的图表,这正是{ggstatsplot}包的目的。在这篇文章中可以看到更多的细节和例子。

假设

对于许多统计测试,为了能够解释结果,需要满足一些假设。当其中一个或几个不满足时,尽管技术上可以进行这些测试,但解释结果或相信结论是不正确的。

以下是学生对两个样本进行 t 检验的假设,如何检验它们,以及如果假设不成立,还有哪些其他检验:

  • 变量类型:学生的 t 检验需要混合一个定量因变量(对应于与问题相关的测量)和一个定性自变量(精确的 2 个水平将决定要比较的组)。
  • 独立性:从总人口中随机选择的有代表性的部分收集的数据,在组间和组内应该是独立的。独立性的假设通常基于实验的设计和对实验条件的良好控制来验证,而不是通过正式的测试。如果你仍然不确定基于实验设计的独立性,问问自己一个观察是否与每个组内或组间的另一个观察相关(如果一个观察对另一个有影响)。如果没有,很可能你有独立的样本。如果样本之间的观察值(形成要比较的不同组)是相关的(例如,如果两个测量值是在相同的个体上收集的,这是医学研究中测量指标(I)治疗前和(ii)治疗后时的常见情况),则应首选学生 t 检验的配对版本,称为配对样本的学生 t 检验,以便考虑要比较的两组之间的相关性。
  • 常态:
  • 对于小样本(通常 n 个样本< 30), when the two samples are independent, observations in 和一个样本 都应遵循正态分布 )。当对成对样本使用学生的 t 检验时,两个样本的观察值之差应该遵循正态分布。正态性假设可以通过直方图QQ 图进行直观测试,和/或通过正态性测试进行正式测试,如夏皮罗-维尔克或科尔莫戈罗夫-斯米尔诺夫测试。即使在变换(例如,对数变换、平方根等)之后。),您的数据仍然不符合正态分布,可以应用 Wilcoxon 检验(R 中的wilcox.test(variable1 ~ variable2, data = dat)。这种非参数检验对非正态分布稳健,它比较中位数而不是平均值,以便比较两个总体。
  • 对于大样本(n ≥ 30),不需要数据的正态性(这是一个常见的误解!).根据中心极限定理,即使数据不是正态分布,大样本的样本均值通常也是正态分布的近似值。因此,当每组/样本中的观察值数量很大时,不需要检验正态性假设。
  • ****方差相等:当两个样本独立时,两组的方差在总体中应该相等(这种假设被称为方差齐性,或者有时甚至被称为同方差,与方差在组间不同时的异方差相对)。这种假设可以通过图形进行测试(例如,通过比较箱线图点线图中的离散度),或者更正式地通过 Levene 测试({car}包中的leveneTest(variable ~ group))或 f 检验(var.test(variable ~ group))。如果等方差假设被拒绝,可以使用另一种版本的学生 t 检验:韦尔奇检验(t.test(variable ~ group, var.equal = FALSE))。请注意,韦尔奇检验不要求方差齐性,但在小样本情况下,分布仍应遵循正态分布。如果你的分布不是正态分布或者方差不相等,应该使用 Wilcoxon 检验。这种检验不需要假设正态性或方差的同方差性。

这就结束了一篇比较长的文章。谢谢你阅读它。我希望这篇文章能帮助你理解学生对两个样本的不同版本的 t-test 是如何工作的,以及如何手动和在 r 中执行它们。如果你感兴趣,这里有一个闪亮的应用程序可以轻松地手动执行这些测试(你只需要输入你的数据,并通过侧边栏菜单选择合适的测试版本)。

此外,我邀请您阅读:

  • 这篇文章如果你想知道如何计算学生的 t 检验但是这次,对于一个样本,
  • 如果您想在非正态假设下比较两组,或
  • 如果您想使用方差分析来比较 3 个或更多组,请点击此

和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。如果您发现了错误或 bug,可以通过在 GitHub 上提出问题来通知我。对于所有其他要求,你可以与我联系。

相关文章:

参考

朗特里德里克。2000.统计无泪

  1. 请注意,与描述统计学相反,推断统计学是统计学的一个分支,它被定义为从对人口的代表性样本的观察中得出关于人口的结论的科学。参见人群和样本的差异
  2. 在本文的其余部分,当我们写学生的 t 检验时,我们指的是两个样本的情况。如果您只想比较一个样本,请参见一个样本 t 检验↩︎
  3. 这至少是参数假设检验的情况。参数测试意味着它是基于理论统计分布,这取决于一些定义的参数。在学生对两个样本进行 t 检验的情况下,它基于具有单个参数的学生 t 分布,即自由度(df = n1+n2 2,其中 n1 和 N2 是两个样本大小)或正态分布。

原载于 2020 年 2 月 28 日 https://statsandr.com**

学习谷歌云助理工程师认证

原文:https://towardsdatascience.com/studying-for-the-google-cloud-associate-engineer-certification-1bb53939ee2a?source=collection_archive---------10-----------------------

照片由米切尔罗Unsplash

如何学习(并通过)谷歌的云认证考试?

介绍

随着云的使用越来越多,谷歌的云助理工程师(ACE)认证提供了一个展示你在云工程和云开发方面的才能的好方法。

这篇文章提供了一些资源和建议来帮助你准备 ACE 考试。

一.评价

你应该参加这个考试吗?

照片由韦斯·希克斯Unsplash 上拍摄

1.云工程适合你吗?

如果云计算听起来与你正在做或想要做的工作相关,那么云工程是你想要拥有的技能。

  • 如果你是谷歌云平台(GCP)的新手: 谷歌在 Coursera 上的在线课程是一个很好的学习工具,会给你在云中构建的技能。
  • 如果你已经与谷歌云平台(GCP)互动过:
    学习并参加考试是完善你的技能组合并向你介绍 GCP 提供的你可能不知道的元素的一种可靠方式。(例如。谷歌的私有 ip 网络,以减少延迟和成本。)

2.认证有益吗?

  • 验证你的技能组合
    认证是对你技能组合的一个很好的验证,无论是内在的(你会对你的技能组合更有信心)还是外在的(你可以证明你知道你在说什么)。
  • 增加就业能力 这个挺明显的。
  • 进入谷歌认证目录
    通过这次考试,你将获得谷歌认证目录的排名。你还将获得许多 GCP 产品的提前发布。
  • 截止日期作为动力 认证考试可以作为你学习目标的动力&截止日期。

3.你能承受现在准备考试的压力吗?

为考试学习是有压力的。问问你自己,你现在是否能承受那么大的压力。

提示:在你准备考试的时候,制定一个计划来管理额外的压力。(例如。如果你生病了,你的日程/工作量会有什么变化。)

4.被你的目标所激励。

保持动力很重要。保持专注于你的目标——无论是学习新技能、创造新项目、获得新工作还是证明你的能力——并在你的学习计划中加入这个目标。

二。关于考试:

考试很难。许多问题将挑战你的知识和应试技巧。

照片由蒂姆·高Unsplash 上拍摄

1。谷歌 考试指南

考试内容的布局。

2。谷歌的 样本考试

这个示例与考试结构和问题风格非常相似。我建议在开始学习之前参加这个模拟考试——这样你就知道如何获取信息。

:这是网上唯一可用的实践考试(截至 2020 年 8 月 20 日)。

三。准备考试

为例题学习为你提供了基于考试材料的知识。准备考试为你提供了通过考试所需的技能和领域知识。

Unsplash 上由 NESA 拍摄的制造商

第一步:注册参加考试

给自己一个期限。你随时可以重新安排。

报名费用: $125 美元
改期费用:考试前 72 小时免费。那么,50 美元

注意:我在截止日期前工作得很好——注册是我激励自己的方式。

步骤 2:查看考试指南

复习考试指南,这样你就知道学什么了。

步骤 3:参加模拟考试

这样你就能了解考试风格,知道该期待什么。

提示:在开始学习之前参加模拟考试。这会让你对提问方式有所准备。另外,一旦你完成了学习,你几乎肯定会忘记问题的答案…

第四步:在 Coursera 上参加谷歌的云工程课程(谷歌提供)。

这门深入的课程将带你了解考试所需的一切(以及更多)。它提供讲座和实验室实践经验。参加完这个课程后,我能够轻松地部署和扩展应用程序。

注意:这是一个庞大的课程,将花费你 2-3 周的时间,每周 10 个小时。

第五步:重考样题。

看你对内容的了解程度。你应该花更多的时间学习什么。

注意:最好是全面的,因为标准化考试中的大多数问题都是低水平的,涵盖了广泛的知识。确保你的后期学习集中在你的弱点上。

第六步:再次复习课程内容。

  • 快速浏览 Coursera 上的课程。
  • 创建学习笔记。
  • 经常复习这些学习笔记。

小贴士:考虑在吃早餐的时候复习你的学习笔记。(很棒的大脑热身。)

第七步:考试前一天停止学习。

事实证明,临时抱佛脚对结果有负面影响。在考试的前一天,帮自己一个忙,放松一下。

照片由 Shutterstock 拍摄

四。关键概念

我在参加考试时签署了保密协议,不会泄露任何考试问题。也就是说,这里有一些你需要很好了解的领域。

InternationalAssociationofMachinists 国际机械师协会

  • 规则层次结构
  • 不同类型的角色(原始/预定义/定制)
  • 特定权限之间的差异(例如云存储创建者与查看者。)

虚拟机(虚拟机)

  • 虚拟机类型(托管与非托管实例)
  • 可抢占虚拟机的用途
  • 使用定制机器类型+如何重复使用它们(图像和快照)
  • 管理虚拟机。(如何开关等等。)

VPC ( 虚拟私有云)联网

  • 如何配置防火墙规则
  • 子网的角色和功能
  • 如何设置负载平衡器
  • 如何连接 VPN(虚拟专用网络)
  • 每种不同类型的对等

云存储

  • 不同的储物选项以及每种储物选项的使用时间
  • 存储类别以及如何在它们之间转换
  • 何时使用 BigQuery

云函数

  • 云功能的用例是什么?
  • 它们的局限性是什么?

库伯内特发动机

  • Kubernetes 的用例是什么?
  • 与 Kubernetes 合作
  • 自动缩放是如何执行的?
  • 如何启用互联网连接

堆栈驱动

  • stackdriver 有哪些用例?
  • 它的局限性是什么?
  • 创建和使用警报

云 SDK

  • 如何在命令行界面执行基本命令?(不需要了解它的冷,只是松松地熟悉它。)

照片由 Keegan HouserUnsplash 上拍摄

动词 (verb 的缩写)考试技巧

以下是一些有助于你参加考试的应试技巧:

1.跳过困难的问题:

如果一个问题难倒了你,跳过它!考试软件给你选择【标记】一个问题供以后复习。不要把时间花在那些旨在迷惑你的问题上。

2.永远不要留下空白答案

阅读问题前选择一个选项。(回答错误没有处罚。)如果你跳过一个硬 Q,在继续之前随机选择一个选项。

3.识别问题中的问题:

有时候问题包含很多信息(意在迷惑你)。学会识别被询问的内容,而不是被告知的内容。

举个例子: 一个管理员不小心删除了他们的数据库。在混乱中,他们恢复了错误的数据库,现在网络崩溃了。您如何确保新数据库的安全配置?

  • 这个问题实际上是在问“如何为恢复的数据库设置安全配置。”
  • 关于意外恢复版本+网络崩溃的信息是无关紧要的。

4.识别错误答案

不管是什么问题,有些答案都是错误的(并且可以被删除)。这些错误答案有几种形式:

  • 永远错误的——这些都是旨在迷惑你的错误陈述。(例如。更改无法重新定位的服务器的位置。)
  • 有时是假的——这些是规则的例外。仅当“例外”是问题的一部分时,才选择此答案。(例如。打破永不删除此服务器的规则,以便您可以将此服务器的位置重置为高速连接。)
  • 永远正确 —这些答案是正确的陈述,但并不总能解决你的问题。如果你发现了几个“永远正确”的答案,重新评估这个问题,看看它真正想要的是什么。(例如。更改网络设置以允许此用户 ip 地址的流量。)

5。留意时钟

不要在一个问题上花太多时间。如果某件事花费的时间比你想要的多,把它标记出来,以后再继续做。

6.休息一下你的眼睛

每隔几分钟就移开视线,放松眼部肌肉。这会帮助你保持专注。

7.沉思

不时花 15-30 秒闭上眼睛,慢慢呼吸。这种努力的时间成本会让你获得平静和放松。

8.审查标记的问题(迭代)

通过复习标记的问题来重复你的考试。如果你能解决它,取消标记 q。如果不能,留下标记,继续前进。这样做一次——然后检查你的答案(# 9)——然后做第二次。

9.检查您的答案

对于每个问题,首先阅读你选择的答案,然后是问题,最后是答案。(这允许您验证您的答案,并根据问题进行确认。)如果你发现自己第二次怀疑自己,标记问题,继续前进。重复所有标记的 Q,直到完成或时间用完。

不及物动词更多资源

以下是您可能会用到的一些附加资源:

结论:

祝你考试顺利!

第 2 部分:STUMPY 基础知识

原文:https://towardsdatascience.com/stumpy-basics-21844a2d2d92?source=collection_archive---------15-----------------------

用 STUMPY 分析图案和异常

(图片由阿诺·梅瑟尔拍摄)

整体大于部分之和

(图片由作者提供)

STUMPY 是一个强大且可扩展的 Python 库,用于现代时间序列分析,在其核心,有效地计算出一种叫做矩阵轮廓的东西。这个多部分系列的目标是解释什么是 matrix profile,以及如何开始利用 STUMPY 完成所有现代时间序列数据挖掘任务!

注:这些教程最初出现在 STUMPY 文档 中。

第 1 部分:矩阵轮廓图
第 2 部分: STUMPY 基础知识
第 3 部分:时间序列链
第 4 部分:语义分割
第 5 部分:用 STUMPY 快速近似矩阵轮廓图
第 6 部分:用于流式时间序列数据的矩阵轮廓图
第 7 部分:用 STUMPY 快速模式搜索 10: 发现多维时间序列模体
第 11 部分:用户引导的模体搜索
第 12 部分:机器学习的矩阵轮廓

用残肢分析图案和异常

在这篇博客中,我们将使用 STUMPY 包来看看研究论文中的一些主要内容:矩阵概要 I & 矩阵概要 II

为了探索基本概念,我们将使用 workhorse stumpy.stump()函数来寻找有趣的主题(模式)或不一致(异常/新奇),并用两个不同的时间序列数据集来演示这些概念:

  1. Steamgen 数据集
  2. 纽约市出租车乘客数据集

stumpy.stump()是流行的 STOMP 算法的 Numba JIT 编译版本,在最初的 Matrix Profile II 论文中有详细描述。stumpy.stump()能够进行并行计算,它对特定时间序列内的模式和异常值进行有序搜索,并利用一些计算的局部性来最小化运行时间。

入门指南

让我们导入加载、分析和绘制数据所需的包。

%matplotlib inline

import pandas as pd
import stumpy
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as dates
from matplotlib.patches import Rectangle
import datetime as dt

plt.rcParams["figure.figsize"] = [20, 6]  # width, height
plt.rcParams['xtick.direction'] = 'out'

什么是主题?

时间序列基序是在一个较长的时间序列中发现的近似重复的子序列。能够说一个子序列是“近似重复的”需要你能够将子序列相互比较。在 STUMPY 的情况下,时间序列中的所有子序列可以通过计算成对的 z 归一化欧几里得距离进行比较,然后只存储其最近邻的索引。这个最近邻距离向量被称为matrix profile,时间序列内每个最近邻的索引被称为matrix profile index(参见第 1 部分:矩阵轮廓进行全面回顾)。幸运的是,stumpy.stump()函数接受任何时间序列(具有浮点值),并计算矩阵轮廓和矩阵轮廓索引,反过来,人们可以立即找到时间序列主题。让我们看一个例子:

加载 Steamgen 数据集

该数据是使用模糊模型生成的,该模型用于模拟位于伊利诺伊州香槟市的 Abbott 电厂的蒸汽发生器。我们感兴趣的数据特性是输出蒸汽流量遥测,单位为 kg/s,数据每三秒“采样”一次,共有 9600 个数据点。

steam_df = pd.read_csv("https://zenodo.org/record/4273921/files/STUMPY_Basics_steamgen.csv?download=1")
steam_df.head()drum pressure  excess oxygen  water level  steam flow
    320.08239       2.506774     0.032701    9.302970
   1321.71099       2.545908     0.284799    9.662621
   2320.91331       2.360562     0.203652   10.990955 
   3325.00252       0.027054     0.326187   12.430107
   4326.65276       0.285649     0.753776   13.681666

可视化 Steamgen 数据集

plt.suptitle('Steamgen Dataset', fontsize='30')
plt.xlabel('Time', fontsize ='20')
plt.ylabel('Steam Flow', fontsize='20')
plt.plot(steam_df['steam flow'].values)

(图片由作者提供)

花一点时间,用肉眼仔细检查上面的情节。如果你被告知有一个模式是近似重复的,你能发现它吗?即使对于计算机来说,这也是非常具有挑战性的。以下是您应该寻找的内容:

手动寻找主题

m = 640
fig, axs = plt.subplots(2)
plt.suptitle('Steamgen Dataset', fontsize='30')
axs[0].set_ylabel("Steam Flow", fontsize='20')
axs[0].plot(steam_df['steam flow'], alpha=0.5, linewidth=1)
axs[0].plot(steam_df['steam flow'].iloc[643:643+m])
axs[0].plot(steam_df['steam flow'].iloc[8724:8724+m])
rect = Rectangle((643, 0), m, 40, facecolor='lightgrey')
axs[0].add_patch(rect)
rect = Rectangle((8724, 0), m, 40, facecolor='lightgrey')
axs[0].add_patch(rect)
axs[1].set_xlabel("Time", fontsize='20')
axs[1].set_ylabel("Steam Flow", fontsize='20')
axs[1].plot(steam_df['steam flow'].values[643:643+m], color='C1')
axs[1].plot(steam_df['steam flow'].values[8724:8724+m], color='C2')

(图片由作者提供)

上面突出显示了我们正在寻找的基序(图案),但仍然很难确定橙色和绿色的子序列是否匹配(上图),也就是说,直到我们放大它们并将子序列彼此重叠(下图)。现在,我们可以清楚地看到,母题非常相似!计算矩阵轮廓的基本价值在于,它不仅能让你快速找到基序,还能识别时间序列中所有子序列的最近邻。请注意,我们实际上没有做任何特别的事情来定位主题,除了我们从原始文件中抓取位置并绘制它们。现在,让我们获取 steamgen 数据,并对其应用stumpy.stump()函数:

使用 STUMP 找到主题

m = 640
mp = stumpy.stump(steam_df['steam flow'], m)

stump需要两个参数:

  1. 时间序列
  2. 一个窗口大小,m

在这种情况下,基于一些领域的专业知识,我们选择了m = 640,这大约相当于半小时的窗口。同样,stump的输出是一个数组,它包含所有的矩阵轮廓值(即,到最近邻居的 z 归一化欧几里德距离)和矩阵轮廓索引,分别在第一和第二列(我们现在忽略第三和第四列)。为了确定基元的索引位置,我们需要找到矩阵轮廓mp[:, 0]具有最小值的索引位置:

motif_idx = np.argsort(mp[:, 0])[0]
print(f"The motif is located at index {motif_idx}")The motif is located at index 643

有了这个motif_idx信息,我们还可以通过交叉引用矩阵轮廓索引来识别其最近邻居的位置,mp[:, 1]:

nearest_neighbor_idx = mp[motif_idx, 1]
print(f"The nearest neighbor is located at index {nearest_neighbor_idx}")The nearest neighbor is located at index 8724

现在,让我们将所有这些放在一起,并在原始数据旁边绘制矩阵图:

fig, axs = plt.subplots(2, sharex=True, gridspec_kw={'hspace': 0})
plt.suptitle('Motif (Pattern) Discovery', fontsize='30')axs[0].plot(steam_df['steam flow'].values)
axs[0].set_ylabel('Steam Flow', fontsize='20')
rect = Rectangle((643, 0), m, 40, facecolor='lightgrey')
axs[0].add_patch(rect)
rect = Rectangle((8724, 0), m, 40, facecolor='lightgrey')
axs[0].add_patch(rect)
axs[1].set_xlabel('Time', fontsize ='20')
axs[1].set_ylabel('Matrix Profile', fontsize='20')
axs[1].axvline(x=643, linestyle="dashed")
axs[1].axvline(x=8724, linestyle="dashed")
axs[1].plot(mp[:, 0])

(图片由作者提供)

我们了解到的是,来自矩阵轮廓的全局最小值(垂直虚线)对应于构成基序对的两个子序列的位置!并且这两个子序列之间的精确 z 归一化欧几里德距离是:

mp[:, 0].min()5.49161982776594

因此,这个距离不是零,因为我们之前看到两个子序列不是完全相同的匹配,但是,相对于矩阵分布图的其余部分(即,与矩阵分布图的平均值或中值相比),我们可以理解这个基序是非常好的匹配。

使用 STUMP 查找异常

相反,矩阵轮廓中的最大值(根据上述stumpy.stump()计算)为:

print(f"The discord is located at index {discord_idx}")The discord is located at index 3864

与这种不和谐最近的邻居有一段相当远的距离:

nearest_neighbor_distance = mp[discord_idx, 0]
print(f"The nearest neighbor subsequence to this discord is {nearest_neighbor_distance} units away")The nearest neighbor subsequence to this discord is 23.476168367301987 units away

位于这个全局最大值的子序列也被称为不一致、新奇或“潜在异常”:

fig, axs = plt.subplots(2, sharex=True, gridspec_kw={'hspace': 0})
plt.suptitle('Discord (Anomaly/Novelty) Discovery', fontsize='30')axs[0].plot(steam_df['steam flow'].values)
axs[0].set_ylabel('Steam Flow', fontsize='20')
rect = Rectangle((3864, 0), m, 40, facecolor='lightgrey')
axs[0].add_patch(rect)
axs[1].set_xlabel('Time', fontsize ='20')
axs[1].set_ylabel('Matrix Profile', fontsize='20')
axs[1].axvline(x=3864, linestyle="dashed")
axs[1].plot(mp[:, 0])

(图片由作者提供)

为了进一步发展/加强我们不断增长的直觉,让我们继续探索另一个数据集!

加载纽约市出租车乘客数据集

首先,我们将下载代表 2014 年秋季 75 天内纽约市出租车乘客半小时平均人数的历史数据。

我们提取该数据并将其插入到一个 Pandas dataframe 中,确保时间戳存储为 datetime 对象,并且值的类型为 float64 。请注意,我们将进行比上面多一点的数据清理,以便您可以看到一个包含时间戳的示例。但是请注意,在计算矩阵概要文件时,stumpy.stump()实际上根本不使用或者不需要时间戳列。

taxi_df = pd.read_csv("https://zenodo.org/record/4276428/files/STUMPY_Basics_Taxi.csv?download=1")
taxi_df['value'] = taxi_df['value'].astype(np.float64)
taxi_df['timestamp'] = pd.to_datetime(taxi_df['timestamp'])
taxi_df.head() timestamp    value
2014-10-01 00:00:00  12751.0
2014-10-01 00:30:00   8767.0
2014-10-01 01:00:00   7005.0
2014-10-01 01:30:00   5257.0
2014-10-01 02:00:00   4189.0

可视化出租车数据集

# This code is going to be utilized to control the axis labeling of the plots
DAY_MULTIPLIER = 7  # Specify for the amount of days you want between each labeled x-axis tickx_axis_labels = taxi_df[(taxi_df.timestamp.dt.hour==0)]['timestamp'].dt.strftime('%b %d').values[::DAY_MULTIPLIER]
x_axis_labels[1::2] = " "
x_axis_labels, DAY_MULTIPLIERplt.suptitle('Taxi Passenger Raw Data', fontsize='30')
plt.xlabel('Window Start Date', fontsize ='20')
plt.ylabel('Half-Hourly Average\nNumber of Taxi Passengers', fontsize='20')
plt.plot(taxi_df['value'])plt.xticks(np.arange(0, taxi_df['value'].shape[0], (48*DAY_MULTIPLIER)/2), x_axis_labels)
plt.xticks(rotation=75)
plt.minorticks_on()
plt.margins(x=0)
plt.show()

(图片由作者提供)

似乎在一天和七天之间有一个普遍的周期性,这可能是因为更多的人在白天而不是晚上使用出租车,并且有理由说大多数周都有类似的出租车乘客模式。此外,也许在接近 10 月底的窗口右侧有一个异常值,但除此之外,仅从原始数据无法得出任何结论。

生成矩阵配置文件

同样,定义窗口大小,m,通常需要一定程度的领域知识,但是我们稍后将展示stumpy.stump()对于该参数的变化是健壮的。因为这个数据是半小时采集一次的,所以我们选择了一个值m = 48来表示正好一天的跨度:

m = 48
mp = stumpy.stump(taxi_df['value'], m=m)

可视化矩阵轮廓

plt.suptitle('1-Day STUMP', fontsize='30')
plt.xlabel('Window Start', fontsize ='20')
plt.ylabel('Matrix Profile', fontsize='20')
plt.plot(mp[:, 0])plt.plot(575, 1.7, marker="v", markersize=15, color='b')
plt.text(620, 1.6, 'Columbus Day', color="black", fontsize=20)
plt.plot(1535, 3.7, marker="v", markersize=15, color='b')
plt.text(1580, 3.6, 'Daylight Savings', color="black", fontsize=20)
plt.plot(2700, 3.1, marker="v", markersize=15, color='b')
plt.text(2745, 3.0, 'Thanksgiving', color="black", fontsize=20)
plt.plot(30, .2, marker="^", markersize=15, color='b', fillstyle='none')
plt.plot(363, .2, marker="^", markersize=15, color='b', fillstyle='none')
plt.xticks(np.arange(0, 3553, (m*DAY_MULTIPLIER)/2), x_axis_labels)
plt.xticks(rotation=75)
plt.minorticks_on()
plt.show()

(图片由作者提供)

了解矩阵配置文件

让我们明白我们在看什么。

最低值

最低值(空心三角形)被认为是基元,因为它们代表具有最小 z 归一化欧几里得距离的一对最近邻子序列。有趣的是,两个最低的数据点正好相隔 7 天,这表明,在这个数据集中,除了更明显的一天的周期性之外,可能还有七天的周期性。

最高值

那么最高的矩阵轮廓值(实心三角形)呢?具有最高(局部)值的子序列实际上强调了它们的唯一性。我们发现前三个峰值恰好分别与哥伦布日、夏令时和感恩节的时间相对应。

不同的窗口大小

如上所述,stumpy.stump()对于窗口大小参数m的选择应该是稳健的。下面,我们通过运行不同窗口大小的stumpy.stump()来演示操作窗口大小如何对你生成的矩阵轮廓产生小的影响。

days_dict ={
  "Half-Day": 24,
  "1-Day": 48,
  "2-Days": 96,
  "5-Days": 240,
  "7-Days": 336,
}

days_df = pd.DataFrame.from_dict(days_dict, orient='index', columns=['m'])
days_df.head() m
Half-Day  24
1-Day     48
2-Days    96
5-Days    240
7-Days    336

我们特意选择了与人类可以选择的相当直观的白天长度相对应的时间跨度。

fig, axs = plt.subplots(5, sharex=True, gridspec_kw={'hspace': 0})
fig.text(0.5, -0.1, 'Subsequence Start Date', ha='center', fontsize='20')
fig.text(0.08, 0.5, 'Matrix Profile', va='center', rotation='vertical', fontsize='20')
for i, varying_m in enumerate(days_df['m'].values):
    mp = stumpy.stump(taxi_df['value'], varying_m)
    axs[i].plot(mp[:, 0])
    axs[i].set_ylim(0,9.5)
    axs[i].set_xlim(0,3600)
    title = f"m = {varying_m}"
    axs[i].set_title(title, fontsize=20, y=.5)
plt.xticks(np.arange(0, taxi_df.shape[0], (48*DAY_MULTIPLIER)/2), x_axis_labels)
plt.xticks(rotation=75)
plt.suptitle('STUMP with Varying Window Sizes', fontsize='30')
plt.show()

(图片由作者提供)

我们可以看到,即使窗口大小不同,我们的峰值仍然突出。但是看起来好像所有的非峰值都在向彼此靠拢。这就是为什么在运行stumpy.stump()之前了解数据环境非常重要的原因,因为它有助于获得一个可以捕捉数据集中重复模式或异常的窗口大小。

GPU-STUMP —使用 GPU 加快 STUMP 速度

当时间序列中的数据远远超过几千个数据点时,您可能需要提高速度来帮助分析数据。幸运的是,你可以试试stumpy.gpu_stump(),一种超快速的 GPU 驱动的stumpy.stump()的替代品,它提供几百个 CPU 的速度,并提供与stumpy.stump()相同的输出:

**import** **stumpy**mp = stumpy.gpu_stump(df['value'], m=m)  *# Note that you'll need a properly configured NVIDIA GPU for this*

事实上,如果你不处理 PII/SII 的数据,那么你可以在 Google Colab 上用这个笔记本来试试stumpy.gpu_stump()

树桩—分布式树桩

或者,如果您只能访问一个 CPU 集群,并且您的数据需要留在防火墙后面,那么stumpy.stump()stumpy.gpu_stump()可能不足以满足您的需求。相反,您可以尝试stumpy.stumped()函数,它是stumpy.stump()的分布式并行实现,依赖于 Dask distributed:

**import** **stumpy**
**from** **dask.distributed** **import** Clientdask_client = Client()mp = stumpy.stumped(dask_client, df['value'], m=m)  *# Note that a dask client is needed*

摘要

就是这样!现在,您已经加载了一个数据集,使用 STUMPY 包在stumpy.stump()中运行它,并且能够提取两个不同时间序列中现有模式和异常的多个结论。您现在可以导入这个包并在您自己的项目中使用它。编码快乐!

资源

Matrix Profile I
Matrix Profile II
STUMPY Matrix Profile 文档
STUMPY Matrix Profile Github 代码库

第一部分:矩阵简介 | 第三部分:时间序列链

线条画的风格转换

原文:https://towardsdatascience.com/style-transfer-for-line-drawings-3c994492b609?source=collection_archive---------50-----------------------

用 ML 从线条画生成图像

在这里,我将以类似教程的方式介绍我最近做的一个机器学习项目。这是一种从线条画中以艺术风格生成完整图像的方法。

资料组

我在 Imagenet 数据集的 10%上进行训练。这是计算机视觉任务中常用的基准数据集。Imagenet 数据集不是公开可用的;它仅限于那些需要使用它来计算性能基准以便与其他方法进行比较的研究人员。因此,通常要求您提交一份申请表。但是如果你只是随便用的话,这里有。除了个人项目之外,我不会用这个做任何事情。请注意,数据集非常大,这就是为什么我只用了 1/10 来训练我的模型。它由 1000 个类组成,所以我用了其中的 100 个图像类进行训练。

几周前,我在一个不同的个人项目中使用了 Imagenet,所以我已经在 Google Drive 中收集了大量文件。然而,不幸的是,将这 140,000 张图片上传到 Google Drive 需要大约 20 个小时。有必要在 Google Colab 的在线 GPU 上训练模型,但这需要你将图像上传到 Google Drive,因为你没有在本地托管你的编码环境。

数据输入管道

我有一个 Colab Pro 帐户,但即使有额外的 RAM,我也肯定无法处理 140,000 个线条画,每个都是 256x256 像素大小,以及它们的 256x256 像素彩色对应物。因此,我必须使用 TensorFlow 数据输入管道随时加载数据。

在我们开始设置管道之前,让我们导入所需的库(这些是我的代码中的所有导入语句):

import matplotlib.pyplot as plt
import numpy as np
import cv2
from tqdm.notebook import tqdm
import glob
import random
import threading, queuefrom tensorflow.keras.models import *
from tensorflow.keras.layers import *
from tensorflow.keras.optimizers import *
from tensorflow.keras.regularizers import *
from tensorflow.keras.utils import to_categorical
import tensorflow as tf

现在,让我们加载指向 Imagenet 子集中每个图像的文件路径,假设您已经将它们上传到适当目录结构下的 Drive,并将 Google Colab 实例连接到 Google Drive。

filepaths = glob.glob("drive/My Drive/1-100/**/*.JPEG")# Shuffle the filepaths
random.shuffle(filepaths)

如果你不想使用glob模块,你可以使用os库中的函数,这样通常效率更高。

这里有几个我需要的助手函数:

  • 标准化数据
  • 色调分离图像数据
def normalize(x):
  return (x - x.min()) / (x.max() - x.min())

色调分离

上述色调分离过程将图像作为输入,并通过将颜色值舍入到某个最接近的值,将平滑的渐变转换为更清晰分离的颜色部分。这里有一个例子:

色调分离

正如您所看到的,生成的图像具有不太平滑的渐变,这些渐变被替换为单独的颜色部分。我实现这一点的原因是因为我可以将输出图像限制为一组颜色,允许我将学习问题格式化为图像中每个像素的分类问题。对于每一种可用的颜色,我分配一个标签。该模型通过最后一个通道num_colors输出由 softmax 函数激活的形状(height, width, num_colors)的图像。给定一个变量num_values,我允许颜色值限制在np.arange(0, 255, 255 / num_values)的所有 RGB 组合。这意味着num_colors = num_values ** 3。这里有一个例子:

色调分离

作为我如何实现这一点的例子,这里有一个演示:

def get_nearest_color(color, colors):
  """
  Args:
   - color: A vector of size 3 representing an RGB color
   - colors: NumPy array of shape (num_colors, 3)
  Returns:
   - The index of the color in the provided set of colors that is
     closest in value to the provided color
  """ return np.argmin([np.linalg.norm(color - c) for c in colors])def posterize_with_limited_colors(image, colors):
  """
  Args:
   - colors: NumPy array of shape (num_colors, 3)
  Returns:
   - Posterized image of shape (height, width, 1), where each value 
     is an integer label associated with a particular index of the
     provided colors array
  """ image = normalize(image)
  posterized = np.array([[get_nearest_color(x, colors) for x in y] for y in image])
  return posterized

边缘抽取

为了从我们的彩色图像中创建输入数据,我们需要一种从图像中提取边缘的方法,这种方法类似于描画或画线。

我们将使用 Canny 边缘检测算法。让我们编写助手函数,它输入图像的路径并输出相关的示例/(X,Y)训练对,包括彩色输入的色调分离以及黑白边缘提取:

def preprocess(path):
  color = cv2.imread(path)
  color = cv2.resize(color, input_image_size) # Assuming your pipelines generator function ignores None
  if color.shape < input_image_size:
    return None, None color = (normalize(color) * 255).astype(np.uint8) gray = cv2.cvtColor(color, cv2.COLOR_RGB2GRAY
  # Removes noise while preserving edges
  filtered = cv2.bilateralFilter(gray, 3, 60, 120) # Automatically determine threshold for edge detection algorithm
  # based upon the median color value of the image
  m = np.median(filtered)
  preservation_factor = 0.33
  low = max(0, int(m - 255 * preservation_factor))
  high = int(min(255, m + 255 * preservation_factor))
  filtered_edges = cv2.Canny(filtered, low, high)
  filtered_edges = normalize(filtered_edges)
  filtered_edges = np.expand_dims(filtered_edges, axis = -1) color = cv2.resize(color, output_image_size)
  color /= 255.
  color = posterize_with_limited_colors(color, colors) return filtered_edges, color

自动 Canny 边缘检测只是我对这篇文章中使用的小函数的修改。

管道

正如我所说的,我正在使用输入管道现场加载数据。因此,我需要定义一个生成器对象,以便在需要时加载这些数据。我的生成器函数很简单,因为我们基本上刚刚定义了它。它所添加的只是过滤掉preprocess函数的None输出(分辨率低于input_image_size的图像),并过滤掉任何包含naninf值的结果。

def generate_data(paths):
  for path in paths:
    edges, color = preprocess(path.decode())
    if not edges is None:
      if not np.any(np.isnan(edges)) or np.any(np.isnan(color)):
        if not np.any(np.isinf(edges)) or np.any(np.isinf(color))):
          # Yield the clean data
          yield edges, color

我用(128, 128)来表示input_image_sizeoutput_image_size。128x128 像素的图像并不是低分辨率的,所以对于我们的目的来说没有明显的缺点。此外,Imagenet 图像的分辨率通常要高得多,因此如果需要,我们可以使用更高的分辨率。

现在让我们建立管道。我使用多线程来提高速度。TensorFlow 的.interleave()允许我们这样做:

thread_names = np.arange(0, 8).astype(str)
dataset = tf.data.Dataset.from_tensor_slices(thread_names)dataset = dataset.interleave(lambda x:
  tf.data.Dataset.from_generator(
    generate_data,
    output_types = (tf.float32, tf.float32),
    output_shapes = ((*input_image_size, 1),
                     (*output_image_size, 1)),
    args = (train_paths,)),
    cycle_length = 8,
    block_length = 8,
    num_parallel_calls = 8)dataset = dataset.batch(batch_size).repeat()

测试管道

让我们通过管道加载一个培训示例:

一个带有输入线条画/边缘(右)和输出着色(左)的训练示例

完全如你所愿。请注意,左边描绘的图像并不完全是管道输出的图像。回想一下,管道返回的是引用每个像素颜色的索引。我只是引用了每种相关的颜色来创建可视化。这里有一个简单得多的例子。

更简单的培训示例

你会看到在左边我们有输出,色调分离的彩色图像,这部分类似于一幅画。在右侧,您可以看到输入边提取,类似于草图。

当然,并不是所有的训练样本都比其他样本具有更好的边缘提取。当颜色更难分离时,产生的轮廓可能会有点嘈杂和/或分散。然而,这是我能想到的提取边缘最准确的方法。

模型架构

让我们继续讨论模型架构。

我从input_image_size = (128, 128)开始,从而在展开最后一个轴后输入形状(128, 128, 1)。我将图层输入形状缩小 2 倍,直到它等于 1。然后,我用stride = 1再应用两个卷积层,因为我们不能再减少前两个轴的形状了。然后,我对转置的层执行相反的操作。每个卷积层有padding = 'valid',每个卷积层之间有一个批量归一化层。所有卷积层都有 ReLU 激活,除了最后一个,当然它在最后一个热编码颜色标签通道上有 softmax 激活。

_________________________________________________________________ Layer (type)                 Output Shape              Param #    ================================================================= input_35 (InputLayer)        [(None, 128, 128, 1)]     0          _________________________________________________________________ conv2d_464 (Conv2D)          (None, 64, 64, 3)         30         _________________________________________________________________ batch_normalization_388 (Bat (None, 64, 64, 3)         12         _________________________________________________________________ conv2d_465 (Conv2D)          (None, 32, 32, 9)         252        _________________________________________________________________ batch_normalization_389 (Bat (None, 32, 32, 9)         36         _________________________________________________________________ conv2d_466 (Conv2D)          (None, 16, 16, 27)        2214       _________________________________________________________________ batch_normalization_390 (Bat (None, 16, 16, 27)        108        _________________________________________________________________ conv2d_467 (Conv2D)          (None, 8, 8, 81)          19764      _________________________________________________________________ batch_normalization_391 (Bat (None, 8, 8, 81)          324        _________________________________________________________________ conv2d_468 (Conv2D)          (None, 4, 4, 243)         177390     _________________________________________________________________ batch_normalization_392 (Bat (None, 4, 4, 243)         972        _________________________________________________________________ conv2d_469 (Conv2D)          (None, 2, 2, 729)         1595052    _________________________________________________________________ batch_normalization_393 (Bat (None, 2, 2, 729)         2916       _________________________________________________________________ conv2d_470 (Conv2D)          (None, 1, 1, 2187)        14351094   _________________________________________________________________ batch_normalization_394 (Bat (None, 1, 1, 2187)        8748       _________________________________________________________________ conv2d_471 (Conv2D)          (None, 1, 1, 2187)        43048908   _________________________________________________________________ batch_normalization_395 (Bat (None, 1, 1, 2187)        8748       _________________________________________________________________ conv2d_472 (Conv2D)          (None, 1, 1, 2187)        43048908   _________________________________________________________________ batch_normalization_396 (Bat (None, 1, 1, 2187)        8748       _________________________________________________________________ conv2d_transpose_229 (Conv2D (None, 1, 1, 2187)        43048908   _________________________________________________________________ batch_normalization_397 (Bat (None, 1, 1, 2187)        8748       _________________________________________________________________ conv2d_transpose_230 (Conv2D (None, 1, 1, 2187)        43048908   _________________________________________________________________ batch_normalization_398 (Bat (None, 1, 1, 2187)        8748       _________________________________________________________________ conv2d_transpose_231 (Conv2D (None, 2, 2, 2187)        43048908   _________________________________________________________________ batch_normalization_399 (Bat (None, 2, 2, 2187)        8748       _________________________________________________________________ conv2d_transpose_232 (Conv2D (None, 4, 4, 2187)        43048908   _________________________________________________________________ batch_normalization_400 (Bat (None, 4, 4, 2187)        8748       _________________________________________________________________ conv2d_transpose_233 (Conv2D (None, 8, 8, 729)         14349636   _________________________________________________________________ batch_normalization_401 (Bat (None, 8, 8, 729)         2916       _________________________________________________________________ conv2d_transpose_234 (Conv2D (None, 16, 16, 243)       1594566    _________________________________________________________________ batch_normalization_402 (Bat (None, 16, 16, 243)       972        _________________________________________________________________ conv2d_transpose_235 (Conv2D (None, 32, 32, 81)        177228     _________________________________________________________________ batch_normalization_403 (Bat (None, 32, 32, 81)        324        _________________________________________________________________ conv2d_transpose_236 (Conv2D (None, 64, 64, 27)        19710      _________________________________________________________________ up_sampling2d_1 (UpSampling2 (None, 128, 128, 27)      0          _________________________________________________________________ batch_normalization_404 (Bat (None, 128, 128, 27)      108        ================================================================= Total params: 290,650,308 Trainable params: 290,615,346 Non-trainable params: 34,962 _________________________________________________________________

培养

让我们创建一些列表来存储整个培训过程中的指标。

train_losses, train_accs = [], []

此外,训练时期数量的变量

epochs = 100

这是我们的训练脚本

for epoch in range(epochs):
  random.shuffle(filepaths)
  history = model.fit(dataset,
                      steps_per_epoch = steps_per_epoch,
                      use_multiprocessing = True,
                      workers = 8,
                      max_queue_size = 10) train_loss = np.mean(history.history["loss"])
  train_acc = np.mean(history.history["accuracy"]) train_losses = train_losses + history.history["loss"]
  train_accs = train_accs + history.history["accuracy"] print ("Epoch: {}/{}, Train Loss: {:.6f}, Train Accuracy: {:.6f}, Val Loss: {:.6f}, Val Accuracy: {:.6f}".format(epoch + 1, epochs, train_loss, train_acc, val_loss, val_acc)) if epoch > 0:
    fig = plt.figure(figsize = (10, 5))
    plt.subplot(1, 2, 1)
    plt.plot(train_losses)
    plt.xlim(0, len(train_losses) - 1)
    plt.xlabel("Epoch")
    plt.ylabel("Loss")
    plt.title("Loss")
    plt.subplot(1, 2, 2)
    plt.plot(train_accs)
    plt.xlim(0, len(train_accs) - 1)
    plt.ylim(0, 1)
    plt.xlabel("Epoch")
    plt.ylabel("Accuracy")
    plt.title("Accuracy")
    plt.show() model.save("model_{}.h5".format(epoch))
  np.save("train_losses.npy", train_losses)
  np.save("train_accs.npy", train_accs)

设计你的熊猫数据框

原文:https://towardsdatascience.com/style-your-pandas-dataframes-814e6a078c6d?source=collection_archive---------13-----------------------

让我们创造出比简单数字更多的东西。

照片由亨电影公司在 Unsplash 上拍摄

数据可视化是从普通数据中推断出有意义结果的伟大工具。它们广泛用于探索性数据分析过程,以便更好地理解手头的数据。如果我们在熊猫数据框架中集成一些可视化结构会怎么样?我认为这比简单的数字更好看。此外,我们可以在数据帧的显示上增加一些信息能力。

我们可以通过使用熊猫数据帧的 Style 属性来实现这一点。Style 属性返回一个 styler 对象,该对象为格式化和显示数据帧提供了许多选项。在本帖中,我们将浏览几个例子,看看数据帧是如何以不同的风格显示的。

我们可以通过调整参数来使用内置的样式函数。我们也可以编写自己的样式函数,并将其传递给 styler 对象,然后该对象在呈现之前实现样式。

有两种方法可以使用 styler 对象。一种是基于元素的样式,可以用 applymap 方法完成。另一种是列或行样式,需要使用应用方法。

让我们首先用 numpy 和 pandas 创建一个样本 dataframe。

df = pd.DataFrame({'A':np.linspace(1,8,8),
                   'B':np.random.random(8),
                   'C':np.random.randn(8),
                   'D':np.random.randn(8),
                   'E':np.random.randint(-5,5,8)})df.iloc[[1,5],[1,3]] = np.nan
df

它看起来简单明了。我们可以编写一个函数,根据条件用不同的颜色显示一些值。例如,我们可以选择用红色显示负值。下面是完成这项任务的函数。

def color_negative_values(val):
  color = 'red' if val < 0 else 'black'
  return 'color: %s' % color

然后我们把它传递给 applymap 方法。

df.style.applymap(color_negative_values)

Applymap 执行基于元素的操作,而 apply 基于列或行执行操作。这是一个改变列中最大值的背景颜色的函数。

def color_max(s):
    is_max = s == s.max()
    return ['background-color: lightblue' if v else '' for v in    is_max]

我们只需要通过它来应用方法。

df.style.apply(color_max)

我们还可以通过将 axis 参数设置为 1 来将该函数应用于行。

df.style.apply(color_max, axis=1)

每行的最大值是彩色的。在这种情况下,它们恰好在“A”栏中。

我们可以通过链式操作来组合不同风格的功能。

df.style.applymap(color_negative_values).apply(color_max)

通过使用子集参数选择特定的行或列,样式功能可部分应用于数据帧。

df.style.apply(color_max, subset=['B','C'])

Color_max 函数应用于列“B”和“C”。

除了定制的功能之外,pandas 还有一些内置的功能,可以满足一些常见的任务。例如, highlight_null 函数标记缺失值。

df.style.highlight_null(null_color='yellow')

我们可以用 null_color 参数改变颜色。另一个有用的内置函数是 background_gradient ,它在 seaborn 的帮助下标记与值成比例的单元格。

import seaborn as snscm = sns.light_palette("green", as_cmap=True)df.style.background_gradient(cmap=cm)

值越大,背景颜色越深。缺失值与其余值分开。

Highlight_maxhighlight_min 函数像我们的自定义 color_max 函数一样标记一列或一行中的最大值和最小值。

df.style.highlight_min(color='lightgreen', axis=1)

df.style.highlight_max()

axis 参数的默认值为 0,执行列操作。

Set_properties 功能允许组合多种风格选择。

df.style.set_properties(**{'background-color': 'lightblue',
                           'color': 'black',
                           'border-color': 'white'})

另一个非常有用的函数是 bar ,它在单元格上绘制条形,条形的长度与单元格中的值成比例。

df.style.bar(color='lightgreen')

通过使用 align 参数,我们可以用不同的颜色显示负值和正值。

df.style.bar(align='mid', color=['red', 'lightgreen'])

传送样式

我们在这里使用的样式函数非常简单。然而,我们也可以创建更复杂的样式函数来增强数据帧的信息能力。我们可能希望在我们处理的所有数据帧上使用相同的样式。Pandas 提供了一种在数据帧之间转换样式的方法。

我们首先将样式保存到 styler 对象中。

style = df.style.applymap(color_negative_values).apply(color_max)
style

让我们创建另一个示例数据帧。

df2 = pd.DataFrame({'col1':np.random.random(8),
                   'col2':np.random.randn(8),
                   'col3':np.random.randint(-5,5,8)})
df2

然后,我们可以创建另一个 styler 对象,并使用保存在前一个 styler 对象中的相同样式。

style2 = df2.style
style2.use(style.export())
style2

我们已经覆盖了

  • 如何创建自定义样式函数并应用于数据框架
  • 如何使用内置样式函数
  • 如何将样式从一个 styler 对象转移到另一个

在 pandas 用户指南的样式部分有其他可用的样式和格式选项。

感谢您的阅读。如果您有任何反馈,请告诉我。

StyleGAN v2:训练和潜在空间探索笔记

原文:https://towardsdatascience.com/stylegan-v2-notes-on-training-and-latent-space-exploration-e51cf96584b3?source=collection_archive---------2-----------------------

内容:在这篇文章中,我将展示我在训练多个 StyleGAN 模型和探索学习的潜在空间时收集的笔记、想法和实验结果。

为什么:这是一个想法/考虑的垃圾场,范围从显而易见的到“神圣的钼”,旨在为其他有类似兴趣和意图的人提供洞察力或讨论的起点。因此,可以浏览一下,看看是否有什么感兴趣的东西。

我也在这里大量利用坎宁安定律

许多考虑因素适用于 StyleGAN v1 和 v2,但是所有生成的结果都来自 v2 模型,除非明确指定。

就代码资源而言:

这里的所有内容都是通过我定制的 Jupyter 笔记本在这些回复的基础上生成的。

值得一提的是勤勤恳恳分享代码、实验和宝贵建议的人: Gwern ( TWDNE ), pbaylies, gpt2ent, xsteenbrugge, VeqtorNorod78roadrunner01 。所有这些都非常值得关注。

培养

资料组

对于自定义数据集,需要预先创建一组图像,确保所有条目具有相同的方形和颜色空间。然后,您可以生成 tf 记录,如这里的所述
正如人们多次指出的那样,这个模型非常渴求数据。数据集大小要求因图像内容而异,但一般目标是 4 到 5 个数量级,比如有镜像时大约 50k,没有镜像时加倍。这适用于从头开始的训练,而在微调的情况下,已经在非常小的数据集上进行了许多实验,提供了有趣的结果。

我主要用两个“时尚”数据集进行实验

  • 服装(~30k 包装照片)
  • 鞋类(~ 140,000 包照片)

来自鞋类和服装数据集的真实图像样本

但是也将展示一些在人工策划的艺术数据集上的实验(每个数据集大约 1k 张图片)。

真实图像样本(弗兰克·弗兰泽塔,埃贡·席勒,阿尔丰斯·穆夏)

请注意,时尚数据集的内容一致性更高(在位置、背景等方面。).与艺术作品相比。因此,无论数据集大小如何,我们都希望前者能够达到更高的生成精度。

服装图像是应该启用镜像增强的一个例子,因为我们可以免费加倍我们的训练集,学习服装的语义不变属性用于水平镜像。

相反,鞋类是应该禁用镜像的情况,因为数据集中的所有图像都是对齐的,并且学习镜像版本对于网络来说只是不必要的负担。

关于大小,我选择 512 来首先验证结果。从之前其他网络的实验来看,我相信这是一个捕捉图案、材质和纽扣、拉链等小细节的好方法。我还计划在 256 上进行下一次迭代,并验证所学表述的质量以及与训练制度的比较。
我建议,如果你有合适的硬件资源,并且已经用较小的分辨率验证了你的数据集,那么就转到全 1024 分辨率(或更高)。

火车

人们可以从头开始训练模型,或者利用以前训练的结果,将学习到的表示微调到新的数据集。

从头开始训练就像运行以下程序一样简单

python run_training.py -num-gpus=2 -data-dir=<your_data_dir> -config=config-f -dataset=<your_dataset_name> -mirror-augment=True -result-dir=<your_results_dir>

我们已经讨论过镜像增强,GPU 的数量取决于您的设置。

服装数据集多次训练的 fid50k 曲线比较

配置用于控制模型的架构和属性,从 config-a (最初的 SyleGAN v1)开始,逐步添加/更改组件(权重解调、惰性正则化、路径长度正则化)到config-e(v2 的完整更新设置),加上 config-f ,一个更大的网络版本 config-e 和本文中使用的默认设置。
对于我的 512 大小的数据集,我选择了 config-e 。在 config-f 中增加的复杂性主要是由在训练时探索网络对更高分辨率的隐含关注时注意到的信息瓶颈引起的,因此我的基本原理是增加的复杂性只会对训练稳定性更加有害。

微调用于节省时间,依赖于先前模型已经学习的结构,并试图使这样的结构适应新的目标数据集。我也见过使用与原始数据集不完全相关的图像进行微调,所以这很大程度上取决于你的目标。微调提供了关于训练质量的更快的视觉反馈,因此更容易运行多次迭代和实验,这是最初了解更多模型行为和超参数的好方法。

要微调现有网络,需要指定要重新启动的快照。对于 v2,这是在run _ training . py中完成的,通过添加和修改以下内容

train.resume_pkl = "your_network_snapshot.pkl"  # Network pickle to resume training from, None = train from scratch.
train.resume_kimg = 0.0  # Assumed training progress at the beginning. Affects reporting and training schedule.
train.resume_time = 0.0  # Assumed wallclock time at the beginning. Affects reporting.

请注意,根据您的快照指定resume_kimg是多么重要,因为它用于控制训练计划(如学习率衰减)。

监测进展

StyleGAN v1(左)和 v2(右)的训练进度对比

在训练时,我看到的主要度量Frechet 初始距离(FID) ,默认情况下,它是在 50k 图像上每 50 个训练刻度计算一次。如 repo 自述文件中所述,可以调用其他指标。注意,Tensorflow 日志是在目标目录中生成的,可以通过运行 tensorboard 来访问

tensorboard --logdir <LOGS_TARGET_DIR>

除了 FID 之外,您还可以在这里检查分数/假和分数/真,这分别是假图像和真图像的鉴别器预测。由于标签最初可能会产生误导,因此值得再次指出,这些不是损失值,而是鉴别器的纯预测输出。

张量板图

我试图从这些图表中获得一些指导,但发现很难提取网络运行情况的精确信息。理想情况下,人们希望鉴别器不能区分真假,因此趋向于零,因为这只是随机猜测。其他次要指标也是基于损失选择。例如,默认情况下,鉴别器使用带有 R1 正则化的逻辑损失,提供梯度罚分图。

对于我的数据集,FID 很好地映射到个人感知的图像质量,但由于度量是基于从 inception v3 模型中提取的特征之间的汇总统计比较来计算的,因此它可能对其他类型的数据集没有帮助,特别是度量值越趋于零。
我仍然建议避免在短期训练期间进行视觉比较,因为我们的主观近似判断往往会因我们所观察的特定示例或甚至仅因噪声贡献而产生偏差,尽管假样本中没有可察觉的变化,但网络可能仍在改进。

约 10,000 公里后为鞋类数据集生成的图像

另一方面,通过视觉检查,人们可以很容易地发现像模式崩溃这样的问题,如以下为穆卡数据集生成的假样本所示。

穆卡数据集的部分模式折叠示例

这是部分模式崩溃的一个例子,生成器被减少到只生成几个例子,在多样性方面有所损失。造成这种情况的一个主要原因可能是数据集的规模较小,再加上常见的重复条目。

请参见下面的 Franzetta art 示例,尤其是与训练曲线相关的示例。虽然有些条目可能会给人模式崩溃的印象,但更有可能的是,对于该特定示例,训练数据集中的重复项太多了。

Franzetta 数据集的 FID50k 曲线,带有在最后一步生成的假图像样本

调整和超参数调谐

一个像样的数据集通常应该提供一个遵循帕累托分布的良好的训练曲线。官方自述文件指定了不同配置的训练时间,但是正如所说的,你将在训练的第一部分获得大部分的改进;棘手和繁琐的部分是试图达到更好的质量细节。

平台是一种常见的情况,模型很少或没有改进。另一种可能但不太常见的行为是发散或爆炸,在初始步骤改进后,模型开始恶化,并以指数形式退化为纯噪声结果。

针对这种情况采取的行动是从先前的检查点重新训练(如先前的微调部分所述),根据识别的问题合理地调整超参数。正如经常提到的,这本身就是一门艺术,强烈地基于直觉、经验和运气。
根据目标、模型状态等,有多种可能性..以下是一些最常见的建议,并附有一些经验笔记。

  • 像往常一样,如果你的数据集在大小或噪音方面有明显的缺陷,花些精力去修复它们,而不是冒险在模型调优上浪费时间
  • learning-rate (lr) ,在这里您可以降低 lr 以获得潜在的更稳定(但缓慢)的训练进度。您还可以根据架构中可能存在的两个组件之间的不平衡,单独调整鉴频器和发生器的 lr。对此, Shawn Presser 在推特上指出v2 其实有一个 bug ,针对这个 bug,生成器 lr 值被错误地用作鉴别器 lr。在试验 G/D lr 平衡之前,一定要修补这个部分。我试着增加 lr,只是为了搞笑,但总是以快速突然的发散结束。
  • 批量,增加批量也可以提供更稳定的训练或从局部最小值突破。这是基于这样的想法,即随着越来越多的预测用于计算梯度,权重更新和训练方向将越精确。我用更大的 minibatch 运行的多个实验迫使 FID50k 增加了一个很好的百分点,但其中一些很快变得不稳定并爆炸。此外,请注意您的设置的内存限制,v2 更昂贵,1024 分辨率的培训需要至少 16 GB 内存的 GPU。
    值得指出的是,StyleGAN 有两个不同的批量参数,minibatch_size_baseminibatch_gpu_base。前者是要使用的实际最大 minibatch 大小,而后者是单个 GPU 一次处理的大小。这意味着这两个参数需要根据您的设置的 GPU 数量进行调整,因为梯度会累积,直到达到基本迷你批次大小。

训练曲线:用相同的数据集测试不同的超参数

关于这些方面,我想再次建议 Gwern StyleGAN v1 post ,因为它提供了深入的细节和参考,如果你想进一步探索 GAN-training,还有三篇额外的优秀论文:稳定生成性对抗网络训练:调查(2019)GAN 的哪些训练方法实际上是趋同的?(2018)训练甘斯的改进技术(2016)

一些行为仍然困扰着我,比如在我从之前的检查点(相同的配置)重新开始训练后,是什么导致了损失分数的变化。

潜在空间探索

服装和鞋类数据集的结果

漫步在林荫道上

以上是我的服装和鞋款潜在空间探索的一些例子。其思想只是生成 N 个样本向量(从高斯分布中提取)并使用任何优选的转换函数在它们之间顺序转换。在我的例子中,这个函数只是一个固定帧数的线性插值(相当于变形)。

请注意,我们依赖于非常初始的潜在向量 z. 这意味着我们使用 StyleGAN 映射网络来首先生成潜在向量 w ,然后使用 w 来合成新图像。由于这个原因,我们可以依靠截断技巧,丢弃潜在空间中表现不佳的区域。我们想要指定所生成的中间向量 w 必须接近平均值多少(基于映射网络的随机输入来计算)。ψ (psi)值衡量了 w 与平均值的偏差,因此可以针对质量/品种的权衡进行调整。ψ=1 相当于没有截断(原始的 w ),而值越接近 0,我们越接近平均值,质量有所提高,但多样性有所减少。

截断技巧在起作用,这里线性间隔从-0.5(左上)到 1.5(右下)

编码真实图像

我们经常希望能够获得关于目标模型的真实图像的代码/潜在向量/嵌入,换句话说:我应该馈送给我的模型的输入值是什么,以生成我的图像的最佳近似。

一般来说,有两种方法:

  • 通过网络的编码器组件传递图像
  • 优化潜在(使用梯度下降)

前者提供了一个快速的解决方案,但在训练数据集之外推广时存在问题,不幸的是,对我们来说,它不是现成的标准样式。该架构根本不学习显式编码功能。

我们只剩下使用感知损失的潜在优化选项。我们为参考和生成的图像提取高级特征(例如,从像 VGG 这样的预训练模型中),计算它们之间的距离,并优化潜在表示(我们的目标代码)。该目标代码的初始化对于效率和效果来说是一个非常重要的方面。最简单的方法是简单的随机初始化,但可以做很多事情来改进这一点,例如通过学习从图像到潜像的显式编码函数。想法是随机生成一组 N 个示例,并存储生成的图像和生成它的代码。然后,我们可以在这些数据上训练一个模型(例如 ResNet ),并在实际的 StyleGAN 编码过程之前使用它来初始化我们的 latent。参见关于改进初始化的丰富讨论

用于 v1 的编码器和用于 v2 的编码器为该操作提供代码和分步指南。我还推荐以下两篇文章: Image2StyleGANImage2StyleGAN++和,它们很好地概述了 StyleGAN 的图像编码,考虑了初始化选项和潜在空间质量,并分析了图像编辑操作,如变形和样式混合。

w(1)对 w(N)

StyleGAN 使用映射网络(八个完全连接的层)将输入噪声(z)转换为中间潜在向量(w)。两者的大小都是 512,但是中间向量是为每个样式层复制的。对于在 1024 尺寸图像上训练的网络,该中间向量将是形状(512,18),对于 512 尺寸,它将是(512,16)。

编码过程通常在这个中间向量上完成,因此可以决定是优化w(1)(意味着只有一个 512 层,然后根据需要平铺到每个样式层)还是整个w(N)。官方放映员操作前者,而改编通常依赖于单独优化所有w条目,以达到视觉保真度。关于这个话题,请参见这个 Twitter 帖子

使用 Nvidia FFHQ 模型投影到 w(N)和 w(1)的比较

当投影不适合模型训练分布的参考时,更引人注目,就像在下面的示例中为 FFHQ 模型投影服装图像。

一般来说,人们总是会注意到,对于高分辨率,投影仪似乎无法匹配参考图片的精细细节,但这很可能是使用 256x256 分辨率的感知损失的结果,如本主题所示。

学习方向

StyleGAN 对潜在空间解缠的改进允许以令人愉快的正交方式探索数据集的单个属性(意味着不影响其他属性)。
鉴别模型学习区分目标属性的界限(例如,男性/女性、微笑/不微笑、猫/狗),而我们感兴趣的是跨越这些界限,垂直于它们移动。例如,如果我从一张悲伤的脸开始,我可以缓慢但稳定地移动到同一张脸的微笑版本。

这应该已经提供了如何学习新方向的提示。我们首先从我们的模型中收集多个样本(图像+潜像),并针对我们的目标属性对图像进行手动分类(例如,微笑与不微笑),试图保证适当的类别表示平衡。然后,我们训练一个模型来对我们的潜在客户和人工标签进行分类或回归。此时,我们可以使用这些支持模型的学习功能作为过渡方向。

罗伯特·卢森堡分享了【FFHQ 官方车型的学习方向。

样从玩弄微笑潜向

用于前馈图像处理的 StyleGAN2 蒸馏是一篇非常新的论文,通过在 StyleGAN 生成的不成对数据集上训练的“学生”图像到图像网络来探索方向处理。该论文旨在克服编码性能瓶颈,并学习能够有效地应用于真实世界图像的变换函数。

来自论文“用于前馈图像处理的 StyleGAN2 蒸馏”的例子

结论

我的很多实验最初都是为了评估 StyleGAN 模型学习的潜在空间有多好(表示学习),以及获得的嵌入对于下游任务(例如,通过线性模型的图像分类)有多好。一方面,我将继续致力于这种评估,试图涵盖其他生成模型类型,如自回归基于流程的模型

我也有兴趣探索这种模型的纯图像合成能力,以及有效的语义混合和编辑的日益增长的潜力,特别是与我对绘画、数字绘画和动画的热情有关的方面。自动线条画着色动画绘画帧插值已经有了一些很棒的免费工具,但是对于 辅助绘图 还有很多可以做的,特别是从更语义的角度来看。实际改进的空间也很大:泛化能力、加快推理时间、训练优化和迁移学习。

接下来,我还想超越纯粹的二维画布,更多地了解在 3D 图形领域已经取得的惊人成就。去噪是我现在经常依赖的东西,可微渲染只是让我意乱情迷,为了闭环,又回到了 GAN 进行连续的 3D 形状生成

引用科学家卡罗里·索尔奈-费希尔

“多么美好的活着的时光”

你可以在 Github 上查看我的代码,在 Twitter 上关注我的更多实验和解释,并在 Instagram 上查看我的图形结果。

免责声明 :目前我不能分享数据集和训练模型。抱歉。

StyleGAN2 投影。一种可靠的图像取证方法?

原文:https://towardsdatascience.com/stylegan2-projection-a-reliable-method-for-image-forensics-700922579236?source=collection_archive---------15-----------------------

一些需要尝试的实验。还有艺术。

幻觉妄想

W W 随着 StyleGAN2 ,一种全新品质的 GAN 驱动的图像生成方式进入了舞台。在性能和结果方面有显著的改进。康纳缩短写了一篇全面介绍这款新车型:

  • 更好的图像质量(和分辨率)
  • 最大限度地减少图像伪影(如“斑点”或“水滴”)
  • 风格混合(效果更好)
  • 将图像投影到潜在空间

这里有一个简短的视频介绍 StyleGAN2,由 NVidia 团队的开发人员(Tero Karras 等人)制作。

Colab 笔记本:最近你还可以在这款 Colab 笔记本中试用 StyleGAN2(由 Mikael Christensen 改进了一些类似投影的功能)。

真相是什么?

关于真理的问题比以往任何时候都更加重要。各个时代的哲学家、艺术家和其他人都在寻找真理和谎言的区别。

在数字时代,我们得到了严峻的消息:证据受到质疑。“一图胜千言”这种老套的观念已经不管用了。我们有#deepfakes、图像生成和其他(音频)视觉建设性的可能性。我们不能确定我们现在看到的图像是否代表真实事件,或者它是否是几秒钟前生成的。

所以我们不得不谈谈图像取证

现在已经有多种方法来鉴别真假图像:

最明显(但不是最靠谱)的方法就是训练自己去检测假货。

如何检测假图像?

与比根相比,斯泰尔根是一个压倒性的发展。尽管如此,它在人脸生成方面还是有一些缺陷:

  • 对称不是斯泰勒根的朋友。
  • 你可能会在脸上和头发上发现奇怪的人造物,比如“气泡”。
  • 耳环不一样(最普遍的因素之一)。
  • 背景很奇怪。

<= This image shows various GAN glitches.

With StyleGAN2 new standards were established. “Bubble artifacts” were mostly fixed. Is it way too hard to detect fakes?

StyleGAN2 developers added a brilliant method to detect fake: 投影

什么是 StyleGAN2 投影?

方法很聪明。StyleGAN 将一个给定的图像投射到潜在空间——生成图像的起源。

它与反向图片搜索有一些表面上的相似之处(如使用 TinEye谷歌图片搜索进行查找,如果图片是库存照片):

神秘的股票形象女孩(阿丽亚娜)

在某些情况下,它不仅会导致原始股票图像提供者,甚至会导致独特的人——就像上面的例子中的股票图像模型 Ariane (另一个故事)。

StyleGAN2 投影将相关图像与生成 GAN 图像的潜在空间进行比较,并寻找原点。

理论上。在实践中(你可以在 Colab 笔记本里尝试一下),它……很复杂。

投影实验

已经有一些杰出的艺术家和研究人员对投影进行了令人惊叹的线程和测试,如吉恩·科岗乔纳森·弗莱马里奥·克林格曼迈克尔·克里斯滕森,仅举几例。不过还是自己试试吧。经验主义法则。

现状核实

第一次(一如既往),我做了一个自我实验。只是为了确定我不是在某个潜在的空间里产生的:

因此,正如你(希望)看到的,这两张图片是不可比较的。我是真实的(又是)。

用 ArtBreeder 创建的图像。

接下来,我检查了我用 ArtBreeder 生成的这个绅士(你已经读过这个奇妙的系统)。由于 ArtBreeder 实现了用于面部生成的 StyleGAN2,您可以假设这是相同的潜在空间。但是…

这个人是真的吗?原物和投影相似但不相同。

甘+我的脸=无法察觉的假

事情是这样的:自从art breader最近增加了上传你的图像并将它们与潜在空间中生成的图片混合的可能性,你不能再指望可用的图像了。

幸运的是,ArtBreeder 提供了血统功能,在这里你可以“按谱系”追踪到根源。

对于这位先生来说,一部分是我的脸,和另一个人混在一起:https://artbreeder.com/lineage?k=45f6f4c1750ed4fe014202fb

已经不是纯粹的 StyleGAN 了。

StyleGAN2 生成的图像

让我们看看潜在空间本身。让我们用 StyleGAN2 直接创建图像。我做到了。很多都是。很好玩。

现在让我们随机挑选一张脸:

如你所见,这些面孔也很相似,但仍然不相同!

从这张夸张的插值图像中,我得到了令人惊讶的最佳结果:

我看到了第一张神秘的脸,瞧!

所以如果你偶然发现这位女士穿着异国情调的时装,你可以肯定地知道:这是假的。(如果你到那时还不好奇的话)。

结论

投射到潜在空间的想法很棒——而且是 StyleGAN2 所有品质不可避免的。假检测不再是人类的任务。我们不可靠。

尽管如此,还是有可能防止投影和反向搜索。因此,开发人员仍然必须找到如何不使我们的世界陷入完全混乱的方法。(剧透:来不及了)。

艺术呢?

说到人工智能,我总是指内在的艺术。你可以做许多你以前不能做的创新的事情(查看我的系列艾&艺术)。有一些新的艺术方法是几年前在最奇怪的梦里也想不出来的。

有了投影,我们可以做一些我们已经用谷歌深梦体验过的事情。我称之为盲目崇拜

在我的定义中:
Pareidolia
是人脑识别各处模式的能力(即使它们不在那里)。在石器时代,这是一项至关重要的技能。我们最好下次把丛林和老虎混淆起来,而不是我们认不出丛林里的老虎。
石器时代已经过去,但我们仍处于这种觉知状态,看到火星上的脸和烤面包上的耶稣。
ParAIdolia 是神经网络(如 CNN)识别其接受训练的模式动机的能力。即使是在白噪音中。这就是为什么所有那些狗在最初的深度梦实验中

StyleGAN2 正在铺开,可用的 Colab 笔记本仍然提供了有限的型号选择: 人脸教堂马、 等。但是 面孔 是一个有趣的面孔,因为我们可以尝试崇拜偶像。

side note:Jonathan Fly 对非人脸和艺术品进行了实验,StyleGAN 能找到的不仅仅是上面这些。

所以,如果想知道 StyleGAN 是否梦到过大阪的惠比寿塔摩天轮:

假马里奥看起来像一个表情符号:

东京变成了一张令人毛骨悚然的脸:

最后,甚至装饰图案也变成了一场可怕的噩梦:

在这张来自的历史照片中,大都会艺术博物馆最近的展览 StyleGAN 认识到了一些非常令人不安的事情:

一个有趣的实验是,当乔纳森让斯泰尔根看一点点,而不是直到最终结果时,他用投影飞了起来。因此,即使非人类的模式也变成了人类。这里只是一个仍然来自他的综合 项目口袋妖怪

出自: 项目口袋妖怪 作者乔纳森·弗莱(iforcedabot.com)

如你所见,技术和艺术的界限再次被湮灭。

这些是人类和机器之间惊人的本体论对话。

你会在潜在空间里发现什么?

发表你的发现吧!

设计熊猫数据框架:不仅仅是数字

原文:https://towardsdatascience.com/styling-pandas-dataframes-more-than-just-numbers-4bbb790fb919?source=collection_archive---------50-----------------------

让原始数据更有洞察力

数据帧是 Python 中操作和存储数据的最标准方法——但是您知道您可以存储的不仅仅是数字吗?Pandas 有多种方法来设计您的数据框架,既方便数据管理者,也方便查看数据的人。

首先,我们将生成一个样本数据帧。它有五列,每行十行,都是从正态分布中随机抽取的。

为了根据条件规则给数据帧着色,需要创建一个颜色映射。它以函数的形式存在,接受一个值,返回一个字符串“color: [color]”。该函数将负值涂成红色。标准颜色是可以接受的,但是十六进制代码也可以。

通过使用.style.applymap功能,颜色图被应用于数据帧。

现在,它看起来像这样:

例如,假设我们想用黄色突出显示每列中的最大值。就像给文本涂上某种颜色一样,我们需要创建一个样式函数。因为此函数突出显示系列中的最大值,而不是每个值的条件,所以此函数接受完整的列(系列)并返回该列中每个单元格的样式说明列表。

在这种情况下,不使用“color: [color]”,而是使用“background-color: [color]”(通常,颜色可以是标准颜色名称或十六进制代码)。

注意,因为这个函数应用于每一列而不是一个值,所以不要使用apply_map 而是使用apply

您可能会发现,如果您之前已经应用了某些东西,那么应用.style.apply将会产生一个错误。这是因为使用函数创建的不是数据帧,而是样式化的对象。要组合许多样式元素,请使用 Python 方法链。

另一种方法是简单地将方法堆叠起来,例如.style.highlight_null().apply().apply_map()

如果您想标记所有 NaN 值,使用.style.highlight_null。这对于使丢失的值更加明显特别有用。

要使数据帧成为热图——也就是说,值根据它们的值进行着色——使用.style.background_gradient方法。该方法接受一个cmap(颜色映射)参数,该参数指示它应该如何着色。在本例中,cmap是使用 seaborn 的light_palette创建的,它接受一个根颜色(在本例中,是蓝莓的十六进制代码)。第三行的cmap参数也可以设置为标准的调色板名称,如viridismagma

要设置固有的数据帧属性,使用.style.set_properties。它将一个字典作为参数,包含各种属性及其值。

人们甚至可以在 Pandas 数据框架中创建“条形图”,其中每个条形对应一个列的值。这对可视化非常有帮助。在这种情况下,subset指的是上面有条形的列。

如果你喜欢这个,

你可能会喜欢我的其他熊猫和 Python 数据科学库教程。

[## 您的最终 Python 可视化备忘单

这个备忘单包含了你最常需要的一个情节的要素,以一种清晰和有组织的方式,用…

medium.com](https://medium.com/swlh/your-ultimate-python-visualization-cheat-sheet-663318470db) [## 处理日期时间时你必须知道的 6 种方法

迄今为止最混乱的数据类型

medium.com](https://medium.com/analytics-vidhya/6-methods-you-must-know-when-dealing-with-datetime-fa0160fe579a) [## 您的终极数据挖掘和机器学习备忘单

特性重要性、分解、转换等

medium.com](https://medium.com/analytics-vidhya/your-ultimate-data-mining-machine-learning-cheat-sheet-9fce3fa16)

R 和 Python 在通过神经网络建模数据方面的风格差异

原文:https://towardsdatascience.com/stylistic-differences-between-r-and-python-in-modelling-data-through-neural-networks-1156627ed07e?source=collection_archive---------29-----------------------

数据科学文体学

如何使用 R 和 Python 对神经网络路径进行建模,并为一组预测器和目标变量生成预测

数据科学方法的核心步骤是对数据进行建模,以产生准确的预测。最后,有大量的方法和算法可供探索。这篇博客用 R 和 Python 介绍了一种在建模数据时不断发展的方法,此外还有以前的方法( 决策树 贝叶斯定理 ),这些方法模拟了大脑的功能。

通过作者组合来自源 1源 2源 3 的图像

1.神经网络导论

数据科学中的神经网络代表了再现非线性学习的尝试,该非线性学习发生在自然界中发现的神经元网络中。一个神经元由树突组成,收集来自其他神经元的输入,并组合输入信息,以便在达到某个阈值时产生响应,该响应被发送给其他神经元。输入(Xi)通过组合函数从上游神经元收集,然后传递到激活函数以产生具有预测能力(y)的最终输出响应。

组合函数通常是求和,将节点输入和连接权重的线性组合生成单个标量值。根据下面的等式, X 表示节点 J 的第 i 个输入, W 表示与节点 J 的每个输入相关联的权重, comb 表示组合函数的最终结果。

给定节点 j 的组合函数

一旦组合函数导致一组数值结果,激活函数就沿着这条路径前进。可能有一系列选择,但最常见的是 sigmoid 函数。原因是它结合了线性、曲线和常数行为,同时使用自然对数的基数(e= 2.718..).通用公式如下所示。

广义 sigmoid 激活函数

一旦激活函数被定义,来自组合函数的值被应用于它,以便产生来自神经网络路径的输出。这些值将代表对所考虑的目标变量的预测。

应用于组合函数结果的 Sigmoid 激活函数

神经结构由称为节点的人工神经元的分层、前馈和连接网络组成。
1。分层:最少有一个输入层、一个隐藏层和一个输出层
2。前馈:没有回路和循环的单向流动
3。连接:相邻层中的每个节点都与另一个节点相连
神经网络的分层特性是其优势和弱点,因为隐藏层中的节点越多,其处理复杂模式的能力就越强,但如果以泛化为代价,也可能导致过拟合。

维基共享通过维基百科

神经网络不是静态模型,它会不断学习。对于来自训练数据集的每个观察,产生输出值,然后与一组训练观察的目标变量的实际值进行比较,并计算误差(实际输出)。为了测量输出预测与实际目标值的吻合程度,大多数神经网络模型使用误差平方和(SSE)。

误差平方和

使用神经网络的主要好处是,由于其非线性结构,它们对于嘈杂和复杂的数据非常稳健。然而,基本的内部工作仍然难以人为解释。

2.用 Python 创建神经网络模型

Python 中开始构建神经网络的起点是上传相关的库,其中有keras.modelskeras.layerskeras.utils。这些是收集和定义神经网络模型的各种组件的必要前提。

Keras 是一个用 Python 编写的开源神经网络库。它能够运行在 TensorFlow、微软认知工具包、Theano 或 PlaidML 之上。旨在实现深度神经网络的快速实验,它专注于用户友好、模块化和可扩展。

import numpy as np
import pandas as pd
from numpy import loadtxt
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Activation
from keras.utils import to_categorical
from keras.regularizers import l1
from sklearn.utils import class_weight

其次,上传或创建相关数据帧是进行分析的基础,在神经网络的情况下,选择非线性数据集是明智的,尤其是当它们与视觉记录相关时。首先,我们可以随机生成一个数据集来模拟代码。在这个例子中,对收到多少援助的预测(Y)被探索为冲击类型和位置(X1,X2)的函数。我们可以通过组合命令inserttolist来指定要插入的变量的属性数量和类型,从而将数值变量转换为分类变量。

df = pd.DataFrame(np.random.randint(0,1000,size=(1000,1)), columns= ['AidMillion'])
category = pd.cut(df.AidMillion,bins=[0,500,1000],labels=['Below_500_Mill','Above_500_Mill'])df.insert(2,'Aid_Given',category)
df.Aid_Given = df.Aid_Given.tolist()TypeShock = (['Draught','Floods','Famine'])
df["TypeShock"] = np.random.choice(TypeShock, size=len(df))Location = (['Urban','Rural'])
df["Location"] = np.random.choice(Location, size=len(df))

对于神经网络,有必要将所有分类变量转换成数值变量。在 Python 中实现这种转换的命令应该是astype(‘category’).cat.codes.另外,我们可以使用train_test_split命令预先分割数据帧。

df['TypeShockNum'] = df['TypeShock'].astype('category').cat.codes
df['LocationNum'] = df['Location'].astype('category').cat.codes
df['Aid_GivenNum'] = df['Aid_Given'].astype('category').cat.codesdf_train, df_test=train_test_split(df,test_size=0.33,random_state=2)
df.head()

一旦相关变量被转换,下一个关键步骤是以一种可以通过神经网络算法处理的方式定义预测器和目标变量。在 Python 中,这可以通过设置变量的子集并确保每个变量都处于np.array的形式下来实现。

X_train = np.array(df_train[["TypeShockNum","LocationNum"]])
y_train = np.array(df_train[["Aid_GivenNum"]])X_test = np.array(df_test[["TypeShockNum","LocationNum"]])
y_test = np.array(df_test[["Aid_GivenNum"]])

然后,创建神经网络的最关键时刻是定义要测试的模型。在 Python 中,第一步是定义我们希望探索的是顺序还是功能应用程序接口(API)。前者允许您为大多数问题逐层创建模型,但不允许模型共享层或具有多个同时输入或输出。后者使您能够创建具有更大灵活性的模型,因为您可以轻松定义可能具有多个不同输入源、生成多个输出目标或重用层的模型。在这种情况下,使用更简单的顺序模型。

model = Sequential()

其次,我们通过使用密集类开始构建完全连接的层。这是我们希望测试的层中有多少神经元或节点的规范,输入维度表示为input_dim以及使用特定参数的激活函数。在模型中,我们可以表示各种层类型。最常见的是密集,但也可能是卷积、池化或循环。在密集层中,我们可以定义几个项目,例如:

1)表示输出空间维度的单元的数量。没有完美的公式来定义最佳单元数,起点是模型中输入和输出及其属性的平均值。在我们的例子中,数据集有 2 个输入,总共有 5 个属性和 1 个输出。这些值通知一系列迭代以创建最佳模型。

*2)*激活函数: 如果没有指定任何东西,则不应用激活(即“线性”激活: *a(x) = x* )。否则,通常将激活函数应用于节点的输出,以限制或限定其值。激活函数有助于限制值,并有助于决定节点是否应该被“触发”。它们可以是线性、sigmoid、双曲正切或校正线性单位(ReLU)函数。

可以包括其他元素。例如, [***kernel_initializer***](https://keras.io/initializers/)描述了用于初始化权重的统计分布。* [***kernel_regularizer***](https://keras.io/regularizers/)在优化期间对层参数或层活动施加惩罚,以并入网络优化的损失函数中。 ***activity_regularizer*** 作为输出的函数工作,主要用于调整隐藏单元。其他组件可以在这里找到*

除了密集层,其他元素也可以添加到模型中。例如,Dropout函数的工作原理是基于概率从后续层的先前激活中“删除”输入变量。它具有模拟具有非常不同的网络结构的大量网络的效果,并且反过来,使网络中的节点通常对输入更鲁棒。

**model.add(Dense(3, input_dim=X_train.shape[1], activation='sigmoid', activity_regularizer=l1(0.001)))model.add(Dropout(0.1))
model.add(Dense(2))
model.add(Dropout(0.1))
model.add(Dense(1))
print(model.summary())**

为了用 Python 从目前创建的模型中产生预测,编译是必要的。在这个关键步骤中,我们需要通过考虑目标变量的性质来定义损失函数。我们可以使用以下选项:

1)mean _ squared _ error是回归问题的损失函数,它计算数据集中每个示例的实际目标值和预测目标值之间的平方差,然后返回它们的平均值。
2)
mean _ absolute _ error是回归问题的损失函数,计算数据集中每个示例的实际目标值和预测目标值之间的差异,然后返回它们的平均值。
3)
mean _ absolute _ per%
4)
二元 _ 交叉熵 是针对两类/二元分类问题的损失函数。通常,交叉熵损失用于计算模型的损失,其中输出是 0 到 1 之间的概率数。
5)
分类 _ 交叉熵 是针对多类(两类以上)分类问题的损失函数。****

在模型函数中,我们还必须选择一个优化器。每当神经网络完成通过网络传递一批输入时,它必须决定如何使用预测值和实际值之间的差异来调整节点上的权重,以便网络优化其解决方案。确定该步骤的算法被称为优化算法。最常见的是:

1) 随机梯度下降 ( *SGD* )计算网络损失函数相对于网络中每个个体权重的梯度。内斯特罗夫加速梯度(NAG)也可用于加速梯度下降。
2)
自适应梯度
(
*Adagrad*)是一种更先进的机器学习技术,它以可变的学习速率进行梯度下降。通过对不频繁参数的大更新和对频繁参数的小更新,保留和加强了节点梯度的历史权重。因此,它非常适合处理稀疏数据。
3)
均方根传播 ( *RMSprop* )是对 Adagrad 的一种修正,学习率进一步除以所有平方梯度的指数衰减平均值,得到全局调整值。
4)
自适应矩估计 ( *Adam* )除了存储过去梯度平方的指数衰减平均值外,它还保留过去梯度的指数衰减平均值。**

最后,我们还可以依靠一种“平衡”模式来应用于通过神经途径使用的权重。A class_weight.compute_sample_weight实用程序可以通过下面的公式n_samples / (n_classes * np.bincount(y))变换 y 的值,自动调整与输入数据中的类频率成反比的权重

**model.compile(loss='binary_crossentropy', optimizer='RMSprop', metrics=['accuracy'])**

一旦在 Python、中定义并编译了模型,我们就可以根据一组参数来拟合模型。在fit函数中,我们将指定:1)模型中的关键变量,2)运行模型的epochs的数量,这意味着在整个数据集上的迭代次数,3)batch_sizes,这是每次梯度更新使用的训练数据样本的数量,以及引用测试数据集中等效变量的validation_data。一旦定义完毕,我们就可以通过model.evaluate命令运行模型并评估其结果。如下所示的最终输出指示训练和测试数据集的损失函数和准确度系数。我们的目标是精度尽可能接近 1,并且损失函数产生的结果接近 0。呈现的输出表明模型仍然需要修正和更多的迭代来正确地参数化它。

**history=model.fit(X_train, y_train, epochs=200, validation_data=(X_test,y_test),batch_size=50, verbose=0, sample_weight= sample_weightsloss_acc_metric_train = model.evaluate(X_train, y_train, verbose=1)
loss_acc_metric_trainloss_acc_metric_test = model.evaluate(X_test, y_test, verbose=1)
loss_acc_metric_test**

3.创建神经网络模型 R

与前面的 Python 示例类似,在 R 中,我们将使用 Keras 作为创建神经网络的关键包。我们还需要安装tensorflowreticulate来运行我们的模型。Keras 的使用允许在两种编码语言之间使用非常相似的编码风格。

**library(keras)
library(tensorflow)
library(reticulate)
library(kerasR)**

第一步仍然是创建或上传相关数据框架,作为进行分析的基础。在本例中,我们将随机生成一个数据集来模拟 R 中的代码。和前面的例子一样,收到的援助预测(Y)是冲击类型和位置(X1,X2)的函数。我们还可以通过命令ifelse指定属性,将数字目标变量转换成分类变量。

**df <- data.frame(replicate(1,sample(0:1000, 1000, rep=TRUE)))
colnames(df) <- c("AidMillion")
df$Aid_Given <- ifelse(df$AidMillion <= 500, "Above_500_Mill", "Below_500_Mill")df$TypeShock <- sample(c('Draught','Floods','Famine'), size = nrow(df), replace = TRUE)df$Location <- sample(c('Urban','Rural'), size = nrow(df), replace = TRUE)**

为了有合适的变量进行分析,我们需要将分类变量转换成数字变量。在 R 中,我们的预测变量和目标变量的转换需要通过as.factoras.numeric命令将每个分类双重转换为因子和整数。要将目标变量转换成零和一的值,我们可以依靠ifelse来表达相关的条件。随后,我们可以通过命令runif将数据帧分成测试和训练帧。

**df$LocationNum<-as.numeric(factor(df$Location))
df$TypeShockNum<-as.numeric(factor(df$TypeShock))
df$Aid_GivenNum<-ifelse(df$Aid_Given=="Above_500_Mill",1,0)set.seed(8)
n<- dim(df)[1]
train_df<-runif(n)<0.60
df_train<- as.data.frame(df[train_df, ])
df_test<- as.data.frame(df[!train_df, ])head(df)**

所有变量都是数字格式后,在 R 中创建合适的目标变量和预测变量也需要进一步操作,以确保目标变量成为数组,预测变量成为矩阵。与 Python 相比,这需要一个额外的步骤,因为变量的选择不能与arraydata.matrix命令结合使用。这需要单独完成,而 Python 中的 numpy 允许组合转换。

**X <- df_train[c("TypeShockNum","LocationNum")]
y <- df_train[c("Aid_GivenNum")]X_t <- df_test[c("TypeShockNum","LocationNum")]
y_t<- df_test[c("Aid_GivenNum")]X_train <- data.matrix(X)
Y_train <- array(y$Aid_GivenNum)
X_test <- data.matrix(X_t)
Y_test <- array(y_t$Aid_GivenNum)**

一旦变量被转换,我们将定义模型。R 中的这一步在风格上与 Python 完全相似,只是有一些小的不同。在定义了顺序模型之后,我们将使用美元符号来添加层和 dropout 函数。在第一层中,参数的唯一区别是语义上的。例如,我们将使用input_shape代替 input_dim 来表示预测器的数量。其余的仍然非常相似,包括其他参数的名称。

**mod <- Sequential()
model$add(Dense(units=3, activity_regularizer=regularizer_l1(0.001), input_shape = ncol(X_train), activation="sigmoid"))model$add(Dropout(rate = 0.1))
model$add(Dense(units = 2))
model$add(Dropout(rate = 0.1))
model$add(Dense(units = 1))
model**

一旦模型被定义,模型就准备好进行编译。在 R 中,这是通过keras_compile命令完成的,同时保持大部分参数的定义方式与之前 Python 中损失函数和优化的示例相同。一旦定义了编译标准,就可以根据与 Python 中表达的参数相同的措辞来使模型适合训练变量。除了一些措辞上的变化,比如需要在验证数据规范之前添加list,以及在函数中插入我们的模型,没有重大的差异需要报告。要显示结果,在 R 中更容易,因为我们可以只调用函数的结果来查看它们,而不需要进一步的求值命令。

就损失函数而言,这种模拟的最终结果是可以接受的,但是精度仍然太低。

**keras_compile(model,  loss = 'binary_crossentropy', optimizer = RMSprop(), metrics = c('accuracy'))history <-fit(model, X_train, Y_train, batch_size = 30, epochs = 250, verbose = 0, validation_data =  list(X_test, Y_test))history**

4.用 R 和 Python 绘制模型和预测

一旦模型生成了相关的预测,我们就可以绘制结果来查看在各个迭代(时期)中损失和准确性结果的进展。在 Python 中,这要耗费更多的时间,因为我们需要定义绘图的各种参数来绘制模型在精度和损失方面的表现。下面的结果表明,在第 50 次迭代之后,精确度有了显著的提高,损失函数有所下降。

**plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()**

另一方面,在 R. 中绘制我们的模型的损失和准确性的进展要容易得多,只需调用plot函数,我们就可以访问我们的损失和准确性函数的趋势。这再次证明了 R 是一种非常注重视觉的语言,可以非常容易地生成相关的情节。我们可以再次看到我们的模型在第 50 个纪元前后有了显著的改进(也称为数据集上的迭代)。

**plot(history)**

最后,我们可以将预测值添加到测试数据集中,以进一步验证它们的一致性。在 Python 中,predict和舍入函数的组合可以生成一系列预测值,我们可以在测试数据集中使用这些预测值进行进一步分析。

**predictions = model.predict(X_test)  
predictions = [round(x[0]) for x in predictions]
X_test['predictions'] = predictions
X_test.head(7)**

同样,在 R 中,我们可以预测应用于测试数据集的值,对它们进行舍入,并通过使用美元符号来创建一个新变量,以推进我们的比较。除了语义上的一些变化,方法仍然是命令 predict 为测试样本中的输入样本生成输出预测。

**pred <- predict(model, (X_test))
df_test$pred <-round(pred, digits = 0)
head(df_test,5)**

5.最终反射

虽然这些模型的输出可以得到显著的改进,但这篇博客的目的是为了说明在 Keras 中创建神经网络时,从风格的角度来看,R 和 Python 是多么相似。事实是,神经网络可能比迄今为止所展示的要复杂得多。它可以是多层感知器、卷积网络或递归网络。它可以具有共享的要素提取图层、多个输入或多个输出。虽然这是一个不断发展的领域,但对基础概念的基本理解足以模拟神经网络。这可以为我们提供一个基础,通过测试各种参数和优化功能,不断改进和构建我们所知道的东西。

除了这种方法之外,还有其他可以探索的数据建模方法。敬请关注即将推出的方法!

R 和 Python 在通过回归分析建模数据方面的风格差异

原文:https://towardsdatascience.com/stylistic-differences-between-r-and-python-in-modelling-data-through-regression-analysis-23fbac7e8609?source=collection_archive---------48-----------------------

科学文体学

如何使用 R 和 Python 通过不同版本的回归分析对数据进行建模,回归分析代表一项估算任务,为不同类型的目标变量生成预测

数据科学方法的核心步骤是通过分类、聚类或评估任务对数据建模。最后,有大量的方法和算法可供探索。本博客用 R 和 Python 对不同类型的回归分析进行了基本介绍,这是对之前介绍的其他方法的重要补充(决策树贝叶斯定理 )。回归分析****

由作者组合来自源 1源 2源 3 的图像

1.回归分析导论

在统计建模中,回归分析是一组统计过程,用于估计因变量(通常称为“结果变量”)和一个或多个自变量(通常称为“预测值”、“协变量”或“特征”)之间的关系。(维基百科)****

回归模型可用于因果分析交叉验证,代表两个截然不同的范围。在没有实验的情况下,回归不能导致因果关系的陈述,但它可以用于交叉验证的目的,这提高了关系的预测准确性和模型内部有效性 。因果推断需要一个包括所有相关预测因素的模型,而不是一个只有有限解释因素的观察研究。因此,一个简单的滞后变量或与结果相关的变量可以产生一个在多个样本中验证的模型,而不一定导致因果推断。

换句话说,回归分析可用于交叉验证,以确保预测的可重复性。另一方面,回归分析可以在更广泛的人群中建立因果联系,并与实验的 外部有效性 相关。因果推理需要一个反映实验设计的样本结构,以及由专业知识支撑的清晰的逻辑连接。

2.普通最小二乘(OLS)回归模型

回归可以是简单的,也可以是多重的。简单回归只考虑一个预测因子,而多重回归将分析扩展到包括一个以上的因子。线性多元回归是一个参数模型,由以下等式定义,其中 x 代表预测变量,各种βeta代表未知模型参数,其值使用可用证据进行估计。

传统参数多元回归

普通最小二乘法 ( OLS )符号定义了用于估计线性回归模型中未知参数的线性最小二乘法。OLS 通过最小二乘法原理选择一组预测值的线性函数的参数。OLS 最小化给定数据集中观察到的目标变量与线性函数预测的目标变量之间的差异的平方和。下面的公式显示了第 i 次观测 y 的残差测量数据点( xi)与超平面之间的垂直距离。该公式旨在评估实际数据和模型之间的拟合程度。下面的公式显示了第 i 次观察 y 测量的数据点(*, yi )与超平面之间的垂直距离的残差*。(维基百科)这个公式意在评估实际数据和模型之间的吻合程度。****

残差平方和

此外,OLS 的应用依赖于以下假设,这些假设对于验证该方法的使用是必要的(改编自本 来源 ): 1 .回归模型在系数和误差项中是线性的,这意味着其函数形式遵循一组参数,而不是对曲率
2 建模的能力。误差项的总体均值为零,回归模型中的常数迫使残差均值等于零
3。所有的独立变量都与误差项不相关,因此 OLS 模型不会将任何方差归因于其误差
4。误差项的观测值彼此不相关,并且信息不会预测后续观测值的误差项
5。误差项具有恒定方差(无异方差),因为它不会因每次观察或一系列观察而改变
6。没有自变量是其他解释变量的完美线性函数(不存在多重共线性)
7。误差项呈正态分布,如果残差遵循正态概率图上的线,则意味着它们呈正态分布****

以下示例基于随机生成的数据集,因此可能不满足以下假设,但仍然值得考虑,以便了解回归建模中各种计算背后的代码。然而,对特定目标变量的分布和均值的行为进行分析,将告知要利用的回归类型。

3.R 和 Python 中的普通最小二乘(OLS)

Python 中开始构建 OLS 回归的起点是上传相关的库,其中statsmodels.api代表了产生回归结果的最具定义性的库。Statsmodels 允许用户探索数据、估计统计模型和执行统计测试。描述性统计、统计测试、绘图函数和结果统计的广泛列表可用于不同类型的数据和每个估计量

**import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import statsmodels.api as sm**

其次,上传或创建相关数据框架是进行分析的基础。在回归分析的情况下,最好是根据主题相关性选择变量。在本例中,对获得多少援助(Y)的预测是作为预测因素(如冲击类型、位置和持续时间)组合的函数进行研究的。

**df = pd.DataFrame(np.random.randint(0,1000,size=(1000,1)), columns= ['IncomeLoss'])df["DurationMonths"] = np.random.randint(1, 12, df.shape[0])TypeShock = (['Draught','Floods','Famine'])
df["TypeShock"] = np.random.choice(TypeShock, size=len(df))Location = (['Urban','Rural'])
df["Location"] = np.random.choice(Location, size=len(df))df["AidMillion"] = np.random.randint(0, 1000, df.shape[0])
category = pd.cut(df.AidMillion,bins=[0,500,1000],labels=['Below_500_Mill','Above_500_Mill'])
df.insert(2,'Aid_Given',category)**

为了建立 OLS 模型,有必要通过对标签进行编码将所有分类变量转换成数值变量。在 Python 中实现这种转换的命令应该是le.fit_transform。此外,我们可以使用train_test_split命令将数据帧分割成一列并测试一列,以简化估算的验证过程。

**le = preprocessing.LabelEncoder()
y1=df['Location']
df['LocationNum']= le.fit_transform(y1.astype(str))y2=df['TypeShock']
df['TypeShockNum']= le.fit_transform(y2.astype(str))df_train, df_test=train_test_split(df, test_size=0.33, random_state=2)df.head()**

上传或生成数据帧后,我们需要定义预测变量和目标变量。在 Python 中,这可以简单地通过在两个方括号中指定预测变量和目标变量来完成。一旦明确定义了变量,我们将需要通过sm.add_constant向回归中添加一个常量值。然后,可以通过运行sm.OLS命令轻松检索回归结果。输出非常详细,并提供了一系列统计值,可以对这些值进行进一步的解释。在这种情况下,模型是从随机生成的值中创建的,因此它的解释能力非常有限。

**X=pd.DataFrame(df[['DurationMonths','IncomeLoss','LocationNum','TypeShockNum']])
y=np.asarray(pd.DataFrame(df[['AidMillion']]))
X=sm.add_constant(X)model01_test= sm.OLS(y, X).fit()
model01_test.summary()**

为了验证整个数据集的分析,我们可以在测试数据集上运行相同的回归。在 Python 中,我们将使用类似的代码,唯一的区别是从df_test中提取变量。结果似乎是相似的。没有一个变量有显著的系数,强调这个输出只是为了举例说明要使用的代码。

**X=pd.DataFrame(df_test[['DurationMonths','IncomeLoss','LocationNum', 'TypeShockNum']])
y=np.asarray(pd.DataFrame(df_test[['AidMillion']]))
X=sm.add_constant(X)model01_test= sm.OLS(y, X).fit()
model01_test.summary()**

与前面的例子不同,我们不需要上传很多包来产生 OLS 输出。因此,在 R 中的第一步是创建或上传相关数据帧,作为进行分析的基础。与前一个例子一样,对接受援助(Y)的预测将作为一系列预测因素的函数来探讨。我们还可以通过命令as指定属性,将数字目标变量转换成分类变量。

**df <- data.frame(replicate(1,sample(0:1000, 1000, rep=TRUE)))
colnames(df) <- c("IncomeLoss")df$DurationMonths <- sample(0:12, dim(df), rep=TRUE)df$Type <- sample(c('Draught','Floods','Famine'), size = nrow(df), replace = TRUE)df$Location <- sample(c('Urban','Rural'), size = nrow(df), replace = TRUE)df$AidMillion <- sample(0:1000, dim(df), rep=TRUE)
df$Aid_Given <- ifelse(df$AidMillion <= 500, "Above_500_Mill", "Below_500_Mill")**

为了将目标变量转换成零和一的值,我们可以依靠从as.numericas.factor的双重转换,以便以可行的形式表达变量来运行回归。随后,我们可以通过命令runif将数据帧分为测试帧和训练帧。

**df$AidMillion<- as.numeric(as.factor(df$AidMillion))
df$DurationMonths<- as.numeric(as.factor(df$DurationMonths))
df$LocationNum<- as.numeric(as.factor(df$Location))
df$TypeShockNum<- as.numeric(as.factor(df$Type))
df$IncomeLoss<- as.numeric(as.factor(df$IncomeLoss))set.seed(8)
n<- dim(df)[1]
train_df<-runif(n)<0.75
df_train<- df[train_df, ]
df_test<- df[!train_df, ]head(df)**

一旦数据框架准备就绪,相关变量被编码成数值因子,公式就不需要将变量的规格具体化。在 R 中,lm 命令提示直接在公式中定义所有相关变量和数据帧的选项。另一方面,输出不太详细,没有像 Python 中那样指定其他统计参数的范围。同样,该模型不会产生任何显著的系数,因为它是随机生成的。

**model01<- lm(formula = AidMillion ~ DurationMonths+ IncomeLoss+ TypeShockNum+ LocationNum, data= df)
summary(model01)**

为了验证分析,我们可以在测试数据集上运行相同的回归。类似于 Python,同样在 R 中,我们将使用类似的代码,唯一的区别是从函数内部的df_test提取变量。模型的结果似乎是相似的。没有一个变量有显著的系数,R 平方只是稍微高一点。

**model01_test<- lm(formula = AidMillion ~ DurationMonths+IncomeLoss+TypeShockNum+LocationNum, data= df_test)
summary(model01_test)**

4.R 和 Python 中的模型评估估计

可以通过查看各种维度来评估回归模型,如平均绝对误差、给定一组参数的目标变量预测以及模型比例参数的平方根。所有这些推导可以指示预测元素的位置或其行为。

为了生成目标变量的预测(估计),Python中的一个简单的predict命令可以生成一系列估计值。

**y_pred=model01.predict(X)
y_pred**

预测器生成后,在 Python 中我们可以通过sklearn.metrics中的mean_absolute_error命令计算平均绝对误差。平均绝对误差取 y 的实际值和预测值之间的距离,并求出这些距离的平均值。这是一个重要的指标,表明如果 MAE 较小,则模型在预测方面表现出色,而 MAE 较大则表明您的模型在某些方面可能有问题。MAE 近似为 0 意味着您的模型是输出预测器的完美拟合。在这种情况下,MAE 非常高,这意味着模型不够充分。

绝对平均误差

**ytrue= df[['AidMillion']]
sklearn.metrics.mean_absolute_error(y_true=ytrue, y_pred=y_pred)**

平均绝对误差

为了在 Python 中验证根据一组特定参数对目标变量的估计,np.column_stack产生一个数组,该数组一旦插入预测command中,就会根据为每个参数提供的位置产生目标值。在这种情况下,参数将表示为:常量值(1)、持续时间(从 0 到 12)、收入损失量(从 0 到 1000)、位置(0,1)和冲击类型(0,1,2)。

**est01=np.column_stack((1,1,500,1,1))
est02=np.column_stack((1,2,500,0,2))
model01.predict(est01), model01.predict(est02)**

按参数位置的预测值

最后, Python 还允许我们通过应用于回归模型的np.sqrt命令轻松计算数组的正平方根,从而计算出标准误差。估计量的均方误差衡量误差平方的平均值,即估计值和实际值之间的平均平方差。这是另一个重要的适合度指标,可用于分析回归中的误差是否准确,尤其是当误差接近零时。

均方误差

**np.sqrt(model01.scale)**

标准误差输出

R 中,目标变量的预测生成可通过predict命令激活。这与 Python 非常相似,正如在其他情况下观察到的那样,这里的风格差异是将各种参数的规范放在括号内。

**X<- data.frame(DurationMonths= df$DurationMonths, IncomeLoss= df$IncomeLoss, TypeShockNum=df$TypeShockNum, LocationNum =df$LocationNum)ypred<- predict(object=model01, newdata=X)
head(ypred)**

预测响应示例

R 中,MAE 的计算包含在应用于预测和真实目标值的同名命令MAE中。这与 Python 中的sklearn.metric非常相似。为了进行模型估计,可以在训练和测试数据集之间比较该值,以确认其有效性。代码下面的输出只代表整个数据集的输出。

**ytrue<- df$AidMillion
MAE(y_pred=ypred, y_true=ytrue)**

MAE 输出

为了计算标准误差,在 R 中的lm输出已经有了这个细节。事实上,从下面可以看出,剩余标准误差是模型本身生成的可视化输出的一部分。这是 R 中的一个特殊特性,在 Python 中无法以同样的方式找到。

此外, R 还可以选择运行逐步回归,而 Python 没有这个预编码命令这是一种拟合回归模型的方法,其中预测变量的选择由自动程序执行。在每一步中,基于一些预先指定的标准,考虑将一个变量添加到解释变量集或从解释变量集中减去。输出显示了 Akaike 信息标准 (AIC),它是样本外预测误差的估计值,因此是给定数据集的统计模型的相对质量。给定数据的模型集合,AIC 估计每个模型相对于其他每个模型的质量。因此,AIC 为模型选择提供了一种手段。

**library(MASS)
model01_step<- stepAIC(object=model01)**

5.R 和 Python 中的广义线性模型(GLM)

除了线性回归模型之外,还有另一套回归模型考虑了不同类型的目标变量。OLS 模型通常适用于连续变量,而 GLM 模型适用于预测值为二进制或数字离散响应的情况。当目标变量对于每组预测变量值都具有正态分布时,我们可以使用线性回归模型。

另一方面,如果我们试图预测一个二进制响应变量(像是或否的情况),线性预测器的二进制响应集的链接函数将是一个对数函数,如下式所示。

线性预测函数

然后,为了分离平均值,我们可以使用一个指数函数,该函数以某种方式归一化,从而产生一个总是在 0 和 1 之间的值。换句话说,回归模型的值应该被用作目标变量为 1 的概率。

隔离平均值

反向工作,我们就能够通过将目标变量等同于指数函数的完整符号的扩展来制定参数形式的模型。因此,该公式代表适用于二进制目标值的逻辑回归

逻辑回归模型

作为 Python 中逻辑回归的一个例子,我们可以指定一个二元变量,如位置(1 =城市,0=农村)和一组数值预测值。然后,sm.Logit命令激活一个输出的生成,在这种情况下,虽然从解释的角度来看,它不会导致一个强大的模型,但它仍然可以作为一个参考的例子。

**X=pd.DataFrame(df[['DurationMonths','IncomeLoss', 'TypeShockNum']])
y=np.asarray(pd.DataFrame(df[['LocationNum']]))
X=sm.add_constant(X)logistic01= sm.Logit(y, X).fit()logistic01.summary()**

R 中,与之前的公式相似,目标变量是二进制变量。在这种情况下,我们将在括号前指定glmfamily类型。这一规范似乎非常重要,因为它还提供了根据目标变量的性质调整到其他类型的回归模型的机会,而无需以显著的方式改变公式。重要的是,没有提到伪 R 调整值或对数似然性。相反,与 Python 不同,输出强调了 AIC 和偏差分布。

**df$LocationNum<-ifelse(df$Location=="Urban",1,0)logistic01<- glm(formula = LocationNum ~ DurationMonths+IncomeLoss, data= df, family=binomial)summary(logistic01)**

另一种类型的目标变量可以是事件的计数,例如,某件事情发生了多少个月或多少次。因此,该变量的分布将是最小值为零的出现次数。这类目标变量的回归模型是泊松。下面是推导回归方程的各种数学步骤。最初,我们会将线性预测值等同于对数函数,以使分布正常化。然后,在分离出平均值后,我们可以通过使用指数表达式为泊松回归导出一个完整的参数函数。

链接函数、均值和泊松回归方程

Python 中,我们可以通过将目标变量指定为以月为单位的持续时间来轻松运行泊松回归。那么回归的规范似乎与逻辑类型完全不同。我们需要导入stattools,然后将sm.GL放在括号前,最后将家族sm.families.Poisson()声明为回归参数的一部分。下面的结果显示了很强的显著性,但不应过多解释这些值,因为它是随机生成的数据集。

**import statsmodels.tools.tools as stattoolsX=pd.DataFrame(df[['AidMillion','IncomeLoss', 'TypeShockNum']])
y=np.asarray(pd.DataFrame(df[['DurationMonths']]))poisreg01=sm.GLM(y,X, family=sm.families.Poisson()).fit()poisreg01.summary()**

R,泊松回归是一个简单的变量变化和一个新的家庭类型的说明,即poisson。在逻辑回归建模中,似乎没有必要对前面的例子做进一步的改变。与 Python 在stattools中的输出不同,它会引出更多关于异常及其行为的信息。输出没有显示与任何预测值的显著关系,如前所述,这是一个随机生成的数据集,仅用于说明目的。

**poisson01 <- glm(formula =  DurationMonths~ AidMillion+ IncomeLoss+ LocationNum, data= df_test, family=poisson)summary(poisson01)**

6.最终想法

各种回归说明了根据目标变量的不同性质可以选择的不同类型的模型。要开发一个有效的模型,还需要考虑许多其他因素,例如,目标变量如何在各种预测器之间分布,以及误差在不同场景和多次迭代中的表现如何。此外,选择与主题相关的变量并由之前研究的专业技术支持也很重要。到目前为止所展示的应该只是一个基础,让我们继续尝试不同的回归模型,并从手头的数据中学习!

除了基本的回归概念,还有其他方法通过关联或其他考虑因素来对数据建模,例如维度!建模数据可以采用其他形式和形状。

R 和 Python 在通过朴素贝叶斯分类器建模数据方面的风格差异

原文:https://towardsdatascience.com/stylistic-differences-between-r-and-python-in-modelling-data-through-the-naïve-bayes-classifier-b7a30e6a1715?source=collection_archive---------41-----------------------

数据科学文体学

如何使用 R 和 Python,根据与事件相关的条件的先验知识,预测事件的概率

通过作者组合来自源 1源 2源 3 的图像

由于数据科学方法的最具决定性的方面是对数据进行建模,以产生估计和强大的预测,因此有大量的方法和算法可以探索这一目标。这篇博客提出了另一种建模数据的方法,超越了之前关于 决策树的博客中所解释的方法,即朴素贝叶斯分类方法。

这种分类方法是贝叶斯定理的衍生,贝叶斯定理描述了基于可能与事件相关的条件的先验知识的事件概率。这个定理的构想者是英国统计学家、哲学家和长老会牧师托马斯·贝叶斯(1701-1761)。这个定理成为他最著名的成就。贝叶斯定理的一个应用也是基于对概率的解释,即认知置信度的大小(信念、假设等的强度)。)而不是一个频率。这允许将概率应用于各种领域,而不仅仅是引用类附带的领域。

托马斯·贝叶斯 Wikimedia Commons via [Wikipedia](https://en.wikipedia.org/wiki/Thomas_Bayes#/media/File:Thomas_Bayes.gif)

1。贝叶斯定理

在数据科学中,通过将我们以前的知识(称为先验分布)与从观察数据中获得的新信息相结合,贝叶斯定理被应用于更新我们关于特定数据参数的知识。这导致更新的参数知识,也称为后验分布。

解释该定理的主要公式考虑了两个事件。在数据科学中,这两个事件可以是变量类型(预测值和目标值)。我们可以考虑由两个预测值(X*=X1,X2)组成的数据集,响应变量 Y 可以由多个类别(y1,y2,y3…)组成。通过贝叶斯定理,我们可以确定对于预测变量的特定组合,哪个类最有可能。

由分析前类值 y*的可能性给出的先验概率和当响应对应于特定类时数据如何表现的表示的组合产生了后验概率。等式左侧的分母描述了数据在不参考目标变量的类值的情况下如何表现,也称为数据的边际概率。在没有关于参数的先验知识的情况下,我们可以使用一个无信息先验,它表示所有类值都是同等可能的。在后一种情况下,后验概率仅基于数据。

在 Y 的 3 个不同的可能类值的情况下,对于常数 X 值,我们可以计算 Y 的三个可能值中的每一个的贝叶斯概率,如下式所示。最大后验假设告诉我们将所选预测值 X 的记录分类为具有最高后验概率的目标变量 Y 的值。

重要的是,即使我们有一个以上的预测变量,类条件独立性假设将各种事件或变量描述为独立的。因此,我们预测因子的选择应该考虑这一假设,确保 X1 和 X2 之间没有关系。

2.Python 中的朴素贝叶斯定理

Python 中应用贝叶斯定理的起点是上传相关的库,其中有一个名为MultinomialNB的多项式朴素贝叶斯分类器,它适用于具有离散特征的分类(例如文本分类的字数)。

import pandas as pd
import numpy as np
from sklearn.naive_bayes import MultinomialNB
import statsmodels.tools.tools as stattools

其次,上传或创建相关数据框架是进行分析的基础。在这种情况下,为了模拟定理,我们可以随机生成一个数据集。在数据集中,预测因子和目标变量的选择可以源于特定的分析需要。在这个例子中,对收到多少援助的预测(Y)被探索为冲击类型和位置(X1,X2)的函数。

df = pd.DataFrame(np.random.randint(0,1000,size=(1000,1)), columns= ['AidMillion'])category = pd.cut(df.AidMillion,bins=[0,500,1000],labels=['Below_500_Mill','Above_500_Mill'])
df.insert(2,'Aid_Given',category)
df.Aid_Given = df.Aid_Given.tolist()df["TypeShock"] = np.random.choice(TypeShock, p=[0.40, 0.30, 0.30], size=len(df))Location = (['Urban','Rural'])
df["Location"] = np.random.choice(Location, size=len(df))df.head()

为了在 Python 中进行分析,我们需要考虑一个测试和一个训练数据帧。可以分割主数据框架,或者选择具有相同变量的另一个信息源。在这种情况下,可以使用train_test_split命令分割主数据帧。此外,如果打算手动执行贝叶斯计算,我们可以通过pd.crosstab导出预测值的边际概率和条件概率。

df_train, df_test=train_test_split(df, test_size=0.40, random_state=8)t1=pd.crosstab(df_train['Aid_Given'], df_train['TypeShock'])
t1['Total']=t1.sum(axis=1)
t1.loc['Total']=t1.sum()
t1t2=pd.crosstab(df_train['Aid_Given'], df_train['Location'])
t2['Total']=t2.sum(axis=1)
t2.loc['Total']=t2.sum()
t2

****

为了在 Python 中应用贝叶斯算法,我们需要将每个预测器转换成哑元。这可以通过对解释目标变量所需的每个变量(冲击类型、位置)使用stattools.categorical 命令来完成,并通过命令 pd.concat将它们连接成一个数据帧。

x_loc_ind= np.array(df_train['Location'])
(x_loc_ind, x_loc_dict)= stattools.categorical(x_loc_ind, drop= True, dictnames=True)
x_loc_ind= pd.DataFrame(x_loc_ind)x_shock_ind= np.array(df_train['TypeShock'])
(x_shock_ind, x_shock_dict)= stattools.categorical(x_shock_ind, drop=True, dictnames= True)
x_shock_ind=pd.DataFrame(x_shock_ind)X=pd.concat((x_loc_ind, x_shock_ind), axis=1)X.head()

将预测变量转换成虚拟矩阵后,为了清晰起见,定义 Y 变量是有用的。在预测器和目标变量被很好地定义后,就可以将代表朴素贝叶斯算法的MultinomialNB命令应用于训练数据集。

Y= df_train['Aid_Given']
Bayes_01=MultinomialNB().fit(X,Y)

决定性的一步是在测试数据集上测试朴素贝叶斯估计器。为了做到这一点,我们需要像以前一样将测试数据中的 X 变量设置为虚拟变量。一旦为测试数据集设置了预测变量,就可以使用命令predict生成预测,该命令为测试数据集中的每条记录生成一个预测值数组。

x_loc_ind_test= np.array(df_test['Location'])
(x_loc_ind_test, x_loc_dict_test)= stattools.categorical(x_loc_ind_test, drop=True, dictnames= True)
x_loc_ind_test= pd.DataFrame(x_loc_ind_test)x_shock_ind_test= np.array(df_test['TypeShock'])
(x_shock_ind_test, x_shock_dict_test)= stattools.categorical(x_shock_ind_test, drop= True, dictnames= True)
x_shock_ind_test=pd.DataFrame(x_shock_ind_test)X_test= pd.concat((x_loc_ind_test, x_shock_ind_test), axis=1)Y_predicted= Bayes_01.predict(X_test)

在对 Bayes 对象(在本例中命名为 Bayes_01)使用了predict命令之后,我们最终可以创建一个实际和预测目标类(高于和低于 5 亿)的列联表,这可以帮助我们理解我们的模型的准确性。

ypred = pd.crosstab(df_test['Aid_Given'], Y_predicted, rownames=['Actual'], colnames=['Predicted'])ypred['Total'] = ypred.sum(axis=1); ypred.loc['Total']=ypred.sum(); ypred

为了测试 Python 的准确性水平,我们可以简单地对测试数据集中记录总数中实际条目与预测条目相对应的频率进行求和。总的来说,该模型只有 51%的准确率,这意味着只有 1/2 的预测是正确的。该模型在预测 500 Mill 以上级别时比基线模型表现更好(58.3%对 48%),而在预测 500 Mill 以下级别时比基线模型表现差(44.3%对 48%)。

PerformanceGlobal=(112+92)/400
PerformanceAbove500=(112/192)
PerformanceBelow500=(92/208)
PerformanceGlobal, PerformanceAbove500, PerformanceBelow500

3.R 中的朴素贝叶斯定理

就像我们在前面的例子中所做的一样,在 R 中应用贝叶斯定理的第一步也需要上传或生成包含预测值和目标变量的数据集。在这种情况下,建议使用相同的数据集结构,预测值仍然是冲击类型和位置,而目标变量是给定 aid 的分解。

df <- data.frame(replicate(1,sample(0:1000, 1000, rep=TRUE)))
colnames(df) <- c("AidMillion")df$Aid_Given <- ifelse(df$AidMillion <= 500, "Above_500_Mill", "Below_500_Mill")df$TypeShock <- sample(c('Draught','Floods','Famine'), size = nrow(df), replace = TRUE)df$Location <- sample(c('Urban','Rural'), size = nrow(df), replace = TRUE)df$Aid_Given <- as.factor(df$Aid_Given)
head(df)

一旦选择了数据帧,我们要么将它分成两部分,要么上传一个具有相同变量的相似数据集。为了将从训练数据集生成的预测值应用于测试数据集,有必要使用两个数据框架。如果我们决定使用相同的数据帧,那么runif命令可以帮助我们做到这一点。

set.seed(8)
n<- dim(df)[1]
train_df<-runif(n)<0.60
df_train<- df[train_df, ]
df_test<- df[!train_df, ]

一旦数据帧准备好进行分析,我们就可以创建两个表来手工计算概率(如果我们愿意的话)。列联表也有助于理解预测值的分类属性在各类目标变量中的分布。请注意与 Python 的区别,在 R 中,我们必须为每个表指定列名和行名,而没有轴的指定。

t1<- table(df_train$Aid_Given, df_train$TypeShock) 
colnames(t1)<- c("Draught","Floods","Famine")
rownames(t1)<- c("Above_500_Mill","Below_500_Mill")
addmargins(A=t1, FUN=list(Total=sum), quiet=TRUE)t2<- table(df_train$Aid_Given, df_train$Location) 
colnames(t2)<- c("Urban","Rural")
rownames(t2)<- c("Above_500_Mill","Below_500_Mill")
addmargins(A=t2, FUN=list(Total=sum), quiet=TRUE)

****

一旦我们创建了列联表,下一步就是通过库e1071应用贝叶斯算法。命令naiveBayes比 Python 中的对等命令产生了更多关于先验条件** 概率的信息。之间的另一个风格差异是在 Bayes 命令中明确指定了解释预测值和目标变量之间关系的公式。**

library(e1071)
Bayes01 <- naiveBayes(formula= Aid_Given~ TypeShock+ Location, data=df_train)Bayes01

R 中的最后一步是通过命令predict将 object Bayes01 中生成的目标变量的预测类应用于测试数据集,生成最终列联表。和前面的表格一样,我们需要定义rownamescolnames和边距来创建一个可读的表格。这是与 Python 风格的一个关键区别。

ypred <- predict(object=Bayes01, newdata=df_test)
test.preds <- table (df_test$Aid_Given, ypred)rownames(test.preds)<- c("Actual:Above_500_Mill","Actual:Below_500_Mill")
colnames(test.preds)<- c("Predicted:Above_500_Mill","Predicted:Below_500_Mill")
addmargins(A=test.preds, FUN=list(Total=sum), quiet=TRUE)

一旦生成列联表,我们就可以评估模型的性能与先验计算中规定的基线值。总体而言,该模型的准确率为 50.4%,这意味着只有 1/2 的预测是正确的,就像我们前面的例子一样。与基线模型相比,该模型在预测 500 Mill 以下级别方面表现更好(51.8%对 46.5%),而在预测 500 Mill 以上级别方面,该模型表现稍差(49.62%对 53.4%)。

PerformanceGlobal=(131+71)/401
PerformanceAbove500=131/264
PerformanceBelow500=71/137
PerformanceGlobal; PerformanceAbove500; PerformanceBelow500

由于数据集是随机生成的,这些结果的唯一目的是说明性的。遵循之前博客中强调的所有步骤,以确保相关的专业知识与精心准备的数据框架相结合,从而产生有意义的分析,这仍然是非常关键的。

在这另一种建模方法之后,下一篇博客将继续解释建模数据的其他方法。敬请关注即将推出的方法!

卡格尔·新冠肺炎公开研究数据集挑战赛(CORD-19)提交的解决方案

原文:https://towardsdatascience.com/submitted-solution-for-kaggle-covid-19-open-research-dataset-challenge-cord-19-138eced43985?source=collection_archive---------49-----------------------

这篇文章描述了为 Kaggle CORD-19 竞赛提交的解决方案。

迈向数据科学 是一份以研究数据科学和机器学习为主的媒体刊物。我们不是健康专家,这篇文章的观点不应被解释为专业建议。

CORD-19 竞赛说明

2020 年 3 月 17 日,随着全球新冠肺炎封锁的开始,Kaggle 宣布与艾伦人工智能研究所合作举办新冠肺炎开放研究数据集挑战赛(CORD-19) 比赛,并与 Chan Zuckerberg Initiative、乔治敦大学安全和新兴技术中心、微软研究院、IBM 和国家医学图书馆-国家卫生研究院合作,并与白宫科技政策办公室协调。

CORD-19 数据集

CORD-19 数据集是一个开放的资源,包含超过 167,000 篇关于新冠肺炎、新型冠状病毒和相关冠状病毒的学术文章(随着时间的推移逐渐增加),由上述六位合作者创建。这些文章代表了迄今为止可用于数据挖掘的最广泛的机器可读冠状病毒文献集合。由于冠状病毒文献的快速增加,对这些方法的需求越来越迫切,使得医学界难以跟上。数据集也可以在语义学者上找到。

竞赛的目的是为世界人工智能专家和 NLP 社区提供一个机会,开发文本和数据挖掘工具,帮助医疗界找到高优先级科学问题的答案,并将这些内容的见解联系起来,以支持全球范围内正在进行的新冠肺炎响应工作。

比赛分两轮进行,最初的关键问题列表选自 NASEM 的 SCIED(国家科学院、工程和医学委员会关于新出现的传染病和 21 世纪健康威胁的常务委员会)研究主题和世界卫生组织为新冠肺炎制定的研发蓝图

第一轮截止日期为 2020 年 4 月 16 日,包括以下主题的 9 项任务:

  1. 关于传播、潜伏期和环境稳定性,我们知道些什么?
  2. 我们对新冠肺炎风险因素了解多少?
  3. 我们对疫苗和疗法了解多少?
  4. 我们对病毒遗传学、起源和进化了解多少?
  5. 关于医疗保健已经发表了什么?
  6. 关于伦理和社会科学的考虑已经发表了什么
  7. 我们对非药物干预了解多少?
  8. 我们对诊断和监控了解多少?
  9. 关于信息共享和跨部门协作,已经发表了哪些内容?

第二轮截止日期为 2020 年 6 月 16 日,包括以下主题的 8 项任务:

  1. 创建处理与新冠肺炎相关的因素的汇总表
  2. 创建治疗、干预和临床研究的汇总表
  3. 创建汇总表,说明与新冠肺炎相关的风险因素
  4. 创建用于新冠肺炎诊断的汇总表(提交的解决方案)
  5. 创建与新冠肺炎相关的材料研究汇总表
  6. 创建汇总表,说明与新冠肺炎相关的模型和未决问题
  7. 创建处理与新冠肺炎相关的人口研究的汇总表
  8. 创建处理与新冠肺炎相关的患者描述的汇总表

已提交的诊断类别解决方案:

在第一轮中,大多数提交的文章展示了分析和分类文章类型和摘要内容的各种解决方案。第 2 轮的任务主要集中在 NLP 的“信息提取”技术上,这意味着解决方案必须回答特定的问题或检索与 COVID 相关的特定搜索查询的相关信息。参与者被要求提供 CSV 格式的文章汇总表,并保存到 Kaggle 笔记本的输出文件夹中。的。CSV 文件应包含符合表格格式的汇总表,表格格式在标题为target_table的文件夹中有描述和演示。我提交的材料涉及任务 4,新冠肺炎的诊断。

为了完成上述任务,我决定从文章的正文中提取相关信息,而不是摘要,因为这种信息可能不会在那个级别提供,而且许多文章没有摘要。

图 1:1000 篇净身文章的文字分布

然而,从正文中提取相关信息的挑战是从提供的文章正文中找到包含相关信息的正确的文本片段。图 1 显示了 1000 篇文章的单词分布,这些文章的正文被清除了停用词。超过 95%的文章平均包含 5000 个单词。因此,找到每篇文章中最相似的句子是至关重要的。

因此,我分三个阶段设计了一个解决方案(见图 2):

  • 阶段 1 加载数据并预处理两个数据集的句子:诊断任务和 Kaggle 文章。
  • 第二阶段计算任务句和文章正文句的 Word2Vec 句子相似度,选出排名靠前的句子。
  • 阶段 3 对排名靠前的句子应用 BERT 预训练问答模型,以找到汇总表查询的准确答案。

图 2:提交的解决方案概述(3 个阶段)

环境设置:

Kaggle 为参与者提供了一个 jupyter 笔记本电脑环境,容量为 10 个 CPU,1 个 GPU,最大 5 GB 磁盘和 16 GB RAM。为了参加竞赛,你需要公开你的私人笔记本。为了这次提交,我在 Kaggle notebook 中开发了我的代码,这些代码可以在我的公共 github 库中找到。

然而,由于在 Kaggle 笔记本上安装变压器的容量问题,我不得不在 azure data science Linux 虚拟机上运行部分代码。

阶段 1:数据加载和预处理:

与数据集相关联的元数据如下:

请注意,在撰写这篇博客时,上面的数字与实际的数据集并不匹配。

从 Kaggle 输入目录加载数据后,生成一个字典来提取结合元数据和 json 文件内容的汇总表所需的列,如下所示:

准备 Kaggle 数据集:

一旦所有的数据都被加载,我在第二阶段和第三阶段将数据二次抽样到“paper_id”、“abstract”和“body”中。然后,最终结果在“paper_id”上与原始数据集合并。

开发了一系列函数来实现预处理步骤:

  • 使用 NLTK 英语标记器将文章的正文分成句子,该标记器通过应用词性标记来识别句子。
  • 小写所有的单词
  • 去掉标点符号
  • 标记所有的句子

Kaggle 数据集的第一阶段的结果是句子及其干净标记的熊猫数据框架。

准备任务数据集:

如前所述,对于 CORD-19 Kaggle 提交,选择了第 2 轮的任务 4,并准备了以下数据集:

阶段 2:应用句子相似度

在这个阶段,我在 Kaggle 的句子和任务数据集之间应用了句子相似性技术,如下所示。

句子相似度语义文本相似度是衡量两段文本有多相似,或者它们表达相同意思的程度。相关任务包括释义或重复识别、搜索和匹配应用程序。用于文本相似性的常用方法从简单的词向量点积到成对分类,以及最近的深度神经网络

句子相似度通常通过以下两个步骤计算:

  1. 获得句子的嵌入
  2. 取它们之间的余弦相似度如下图所示:

图 3: 资料来源:通用语句编码器

Word2vec 是一个用于从文本中学习单词嵌入的预测模型,由 Google research 于 2013 年推出

简而言之,单词嵌入是将单词表示成向量的一种方式,即语料库中有共同上下文的单词在向量空间中会靠得很近,如男-女、国王-王后等。

图 4: 来源:可视化单词向量

有两种不同的模型架构可用于产生 word2vec 嵌入:连续词袋(CBOW)连续跳格。前者使用周围单词的窗口(“上下文”)来预测当前单词,而后者使用当前单词来预测周围的上下文单词。更多关于 word2vec 的详细信息,请参见 word2vec 上的本教程和本博客

我使用了预训练的 word2vec 单词嵌入。这些嵌入在谷歌新闻语料库上进行训练,并为 300 万个英语单词提供 300 维嵌入(向量)。参见此链接了解嵌入的原始位置。

Doc2vec 是 word2vec 的扩展,它产生文档的嵌入。这里,“文档”指的是由多个记号/单词组成的更大的块。对于这个解决方案,我还应用了 doc2vec,其中的文档是实际的句子。然而,word2vec 的结果比第 3 阶段稍好,因此,这个解决方案只关注 Word2Vec。

TF-IDF 或术语频率-逆文档频率是一种加权方案,旨在衡量一个单词在更广泛的语料库(整个文章正文)中对文档(或 Kaggle 文章的句子)的重要性。权重“与单词在文档中出现的次数成比例增加,但被单词在语料库中的频率抵消”(教程链接)。

对于语料库 cc 中句子【s】中的术语 t ,则 TF-IDF 权重为:

TF-IDF 重量(来源)

其中:

TFt,s= termt出现在句子 s
dft =包含 term t
N 的句子数量=语料库的大小。

余弦相似度是向量之间常见的相似度度量。直观地,它测量任意两个向量之间的角度余弦。对于向量 ab ,余弦相似度为:

计算余弦相似度(来源)

我计算了所有单词嵌入的 TF-IDF 加权平均值以及 Kaggle 数据集和任务数据集的每个句子之间的余弦相似度,并找到了每篇文章中排名最高的句子。代码的更多细节可以在 github 上找到,第二阶段的成果如下。

例如,为一篇文章提取的与任务 4 中的诊断句子相似的排名前十的句子是:

['In addition to the poorly understood but well observed advantageous nature of narrow sutures on the prevention of abdominal incisional hernias, studies assessing for this type of suture and comparing it with other suturing techniques also carry a number of limitations, which may limit the generalizability of their results.',
 'Participants will be randomly assigned to their treatment arms in a 1:1 ratio, according to a computer generated schedule, stratified by type of surgery (vascular or non-vascular), using permuted blocks of variable sizes.',
 'Their results showed a lower incidence of wound infections, dehiscence, and incisional hernias with their new fascial closure technique as compared to the conventional one.',
 'In addition, several studies showed that the clinical detection of ventral abdominal incisional hernias is a simple, rapid, radiation-free, and cost-effective method to rely on .',
 'Nevertheless, major studies such as the STITCH trial relied on physical examination as the primary means of detecting incisional hernias  .',
 'We will use the chi-square or Fisher exact test if the expected count of any of the outcomes is less than 5 per cell for analysis of the incidence of dichotomous outcomes (fascia dehiscence, incisional hernia, wound seroma, wound infection, and intervention for wound complications).',
 'To that effect, the modality for the detection of incisional hernias remains subjective to the experience of the physician or investigator.',
 'Investigating the prevention of incisional hernias using different suturing techniques requires adequate detection of this complication as a prerequisite.',
 'On the other hand, some studies showed that ultrasound can be a superior modality for incisional hernia detection with a sensitivity ranging between 70 and 98% and a specificity between 88 and 100%    .']

阶段 3:使用微调过的 BERT 应用问题回答

阶段 1 和阶段 2 的结果是类似于 Kaggle 任务的句子。在第 3 阶段,我使用如下微调的 BERT 应用了问答技术。

问题回答是一项经典的自然语言处理任务,包括确定回答用户“问题”的相关“答案”(从提供的段落中摘录的文本片段)。这项任务是机器理解的一个子集,或者测量机器理解一段文本的程度。[ 1

BERT (来自变形金刚的双向编码器表示)是谷歌在 2019 年推出的预训练语言模型,在各种各样的 NLP 任务中呈现最先进的结果,包括问答(SQuAD v1.1)、自然语言推理(MNLI)、文本分类、名称实体识别等。,只需对特定于任务的数据集进行几次微调。BERT 的关键技术创新是应用了 Transformer 的双向训练,这是一种流行的注意力模型,用于学习文本中单词(或子单词)之间的上下文关系。[ 1

SQuAD( 斯坦福问答数据集)是一个阅读理解数据集,由人群工作者就一组维基百科文章提出的问题组成,其中每个问题的答案都是相应阅读文章的一段文字或跨度,或者问题可能无法回答。“SQuAD 1.1 是 SQuAD 数据集的上一版本,包含 500+篇文章的 100,000+个问答对”。【2】

如何针对问答任务微调 BERT:下图显示了如何针对问答任务微调 BERT。BERT 将问题-段落对插入到班数据集中作为输入,[SEP]表示是用于分隔问题/答案的特殊分隔符。在输出层,它输出Start/End来表示段落中的答案。

图 5:为 QA 微调 BERT(来源)

这里有一个很棒的关于微调 BERT 的问答教程。为了节省这篇文章的时间和空间,我跳过描述每个步骤。更多细节可以在我的 github 上找到。

注意:安装变形金刚库需要相当大的内存。在这个阶段,我不能使用 Kaggle 笔记本,第二阶段的结果保存在一个 csv 文件中,第三阶段是在 Linux 虚拟机上开发的,使用标准 NC6、6 个 vCPUs 和 56GB RAM。

使用了以下 BERT 预训练模型:

阶段 3 的结果是与诊断任务相关的问题的答案。对于此特定任务,文章摘要表格应遵循表格格式:Group 6 - DiagnosticsPublication date Study-type Study Link Journal Study Type Detection Method Sample Obtained Sample Measure of Evidence Speed of assay FDA approval Added on DOI CORD_UID

因此,提出了以下问题:

学习类型是什么?

用什么检测方法?

样本量是多少?

获得了什么样本?

证据的衡量标准是什么?

化验的速度是多少?

是 FDA 批准的吗?

结果

图 6 显示了 20 个样本的结果。我已经删除了表格中的一些内容,以适应这一页。

图 6:最终结果(20 个样本)

这些结果表明,该解决方案可有效检测特定信息,如方法类型 : pcr、胸部 x 射线、蛋白质印迹获得的样本 : 血液、纯化病毒、vp1 基因,以及数字数据,如样本量 : 25 gl,2 周或更长时间,> 400,000 名成人分析速度:该解决方案还显示了提取背景信息的有希望的结果,如 s 研究类型 : 观察、调查和报告、行为实验fda 批准: 机构伦理研究委员会,FDA 已批准使用普瑞巴林 fibr,美国 FDA 批准。对于证据度量的情况,提取了精确公式 (ρ ( τ,x p ( τ ) ) 以及概念证据:*更快的实验室和数据分析周转、表面等离子体共振(spr)分析、图论和最小生成树(mst)。*****

结论和未来工作:

这篇文章描述了为 Kaggle 竞赛(CORD-19)第 2 轮诊断任务提交的解决方案(链接到 github )。该解决方案在两个数据集的数据预处理的 3 个阶段(图 2)中实现:诊断任务和 Kaggle,计算任务句子和文章正文句子之间的单词嵌入和 Word2Vec 句子相似性,并选择排名靠前的句子,最后对排名靠前的句子应用 BERT 预训练的 QA 模型,以找到汇总表的准确答案。

结果(图 6)表明,该解决方案可以有效地检测特定信息、数字数据以及从文章正文中提取上下文信息。

对于未来的工作,作者计划通过应用其他知识提取方法来继续这项研究,包括:微软新冠肺炎 Azure 认知搜索,它对由 Azure 健康文本分析Azure 认知搜索 支持的相同 CORD-19 数据集进行分类。

MATLAB 中的支线图

原文:https://towardsdatascience.com/subplots-in-matlab-34c339082300?source=collection_archive---------25-----------------------

作者图片

组织情节的简单方法

子绘图是 MATLAB 中一个非常强大的功能。它们允许用户非常快速地创建定制的数据可视化和显示。它们还可以用来快速创建交互式图形用户界面(GUI)。在本教程中,我描述了使用 subplot()命令的三种不同方式,并提供了每种方式的示例。提供的示例在 MATLAB 和 Octave 中都可以工作。

包含示例的源代码可以在 GitHub 库中找到。

使用基本支线剧情

MATLAB/Octave 中的 subplot()函数允许您在单个图形中的网格上插入多个图。subplot()命令的基本形式接受三个输入:nRows、nCols、linearIndex。前两个参数定义了网格中包含的行数和列数。第三个参数是选择当前活动绘图轴的线性索引。索引从 1 开始,从左到右、从上到下递增。如果这还没有意义,也没关系,在本节的所有例子中,顺序都是可视化的,在网格例子中尤其明显。

让我们从一个简单的例子开始,这个例子沿着一行包含三个子图。为了方便起见,我还使用了 text()函数来显示每个子情节中的线性索引。

a1 = subplot( 1, 3, 1 );
text( 0.5, 0.5, '1', 'fontsize', 48 );
a2 = subplot( 1, 3, 2 );
text( 0.5, 0.5, '2', 'fontsize', 48 );
a3 = subplot( 1, 3, 3 );
text( 0.5, 0.5, '3', 'fontsize', 48 );

作者图片

注意,在这个例子的代码中,我已经为每个子情节保存了轴句柄(a1,a2,a3)。这一点很重要,因为现在图形上有多个绘图轴,每当我们更改属性时,我们将需要指定我们引用的轴。例如,如果我们想改变字体大小,我们必须指定每个轴上的字体大小。下面的代码片段是一个示例,其中每个轴上的字体被设置为不同的大小。这一概念扩展到所有其他绘图轴属性,并显示了如何完全定制每个子图。

set( a1, 'fontsize', 12 )
set( a2, 'fontsize', 14 )
set( a3, 'fontsize', 16 )

作者图片

这是另一个例子,我交换了 subplot 函数中的前两个参数,现在我们将创建一个有三行的图形。

a1 = subplot( 3, 1, 1 );
text( 0.5, 0.5, '1', 'fontsize', 48 );
a2 = subplot( 3, 1, 2 );
text( 0.5, 0.5, '2', 'fontsize', 48 );
a3 = subplot( 3, 1, 3 );
text( 0.5, 0.5, '3', 'fontsize', 48 );

作者图片

最后,我们可以创建一个完整的子图网格。在这个例子中,我包含了 3 行 3 列;然而,可以使用任何组合。这个例子很好地说明了线性指数是如何增加的。

for iPlot=1 : 9
  subplot( 3, 3, iPlot );
  text( 0.5, 0.5, num2str( iPlot ), 'fontsize', 48 );
end

作者图片

使用不同大小的地块

使用 subplot()的一种稍微灵活的方法是将子图放置在网格中的多个点上。这是通过传入一个线性索引数组作为第三个参数来实现的,而不仅仅是一个值。例如,subplot( 1,3,[1,2])将创建一个包含三列的 subplot 网格和一个占据前两列的 plot。这种方法可以让你做出一些非常漂亮的图,可以很容易地容纳各种类型的数据。

让我们看另一个例子。底层网格的形状为 3 x 3。第一个子图位于网格的顶部,跨越所有三列。第二个子图位于左下角,覆盖 2 x 2 子网格。最后,最后一个子图在右下角,横跨最后两行。在所有情况下,线性指数都包括在图中,以说明它们覆盖了网格的哪些部分。

% - Create a single plot on the top row
subplot( 3, 3, 1:3 );
text( 0.35, 0.5, '1, 2, 3', 'fontsize', 48 );
% - Create a single plot in the last column
subplot( 3, 3, [6, 9] );
text( 0.30, 0.5, '6, 9', 'fontsize', 48 );
% - Create a matrix in the bottom left corner
subplot( 3, 3, [ 4:5, 7:8 ] );
text( 0.25, 0.5, '4, 5, 7, 8', 'fontsize', 48 );

作者图片

填充大型网格的另一个方便的用途是简单地留出一些空间。这很好,因为它创建了空白,并允许您在图中的不同位置对齐子图。下面是一个示例,它将子图放在顶行的中央,并将底行的子图跨越所有列。

subplot( 2, 3, 2 );
text( 0.35, 0.5, '2', 'fontsize', 48 );
subplot( 2, 3, 4:6 );
text( 0.35, 0.5, '4, 5, 6', 'fontsize', 48 );

作者图片

使用位置坐标

使用 subplot()函数的最后也是最灵活的方法是直接指定轴的位置。通过使用标准化的图形单位并指定图形内的相对偏移,最容易做到这一点。如果你对相对数字单位不熟悉,你可以看前面的教程来了解这些。

要指定一个子图位置,您可以将键盘“position”作为 subplot()中的第一个参数,后跟一个描述该位置的 1 x 4 向量。position 属性分别包含水平原点(h0)、垂直原点(v0)、宽度(w)和高度(h),组织方式如下:[ h0,v0,h,v ]。以这种方式指定子图允许您完全控制位置,如果您想以编程方式创建 GUI,这是必不可少的。

我在下面加入了一个例子,在图的左半部分插入了一个子图,在右半部分插入了三个按钮。这些按钮仅用于说明。在 MATLAB 中创建 GUI 的任务留给另一个教程。请注意,对于下面的例子,我已经指定了图形的归一化单位,但是,默认单位是像素。

set( f, 'units', 'normalized' );
a = subplot( 'position', [ 0.1, 0.1, 0.5, 0.8 ] );
title( a, 'Subplots are awesome!' );
set( a, 'fontsize', 16 );
a = uicontrol( f, 'units', 'normalized', 'position', ...
  [ 0.7, 0.7, 0.2, 0.1 ], 'style', 'pushbutton', 'string', 'Press Me' );
a = uicontrol( f, 'units', 'normalized', 'position', ...
  [ 0.7, 0.5, 0.2, 0.1 ], 'style', 'pushbutton', 'string', 'Click Here' );
a = uicontrol( f, 'units', 'normalized', 'position', ...
  [ 0.7, 0.3, 0.2, 0.1 ], 'style', 'pushbutton', 'string', 'Easy' );

作者图片

摘要

在这篇快速教程中,我回顾了在 MATLAB/Octave 中使用 subplot()的三种(实际上是两种半)不同方式。我发现这个功能对很多不同的事情都非常有用,我每天都在使用它。根据我想要完成的目标,我会使用这三种方法。摆弄一下例子,放入一些真实的数据,感受一下这些类型的子图如何对你有用。

需要记住的一些要点:

  • 每个子图都有自己的轴柄和属性(如字体大小、标签、网格),需要单独设置
  • 确保您保存了轴控制柄并正确引用它们
  • 子图索引可以指定为单个值或整数索引数组
  • 如果指定位置向量,请注意图形单位

编码快乐!

在没有提供数据的情况下,作为一名数据科学家在黑客马拉松中取得成功

原文:https://towardsdatascience.com/succeed-as-data-scientist-at-a-hackathon-without-data-being-provided-490ac46c9674?source=collection_archive---------66-----------------------

黑客马拉松应该做什么,不应该做什么

简介

上个月,我参加了我的第一次黑客马拉松,因为我收到了一封来自我的大学的随机广告邮件,这封邮件宣传了一个听起来很酷的东西。我点击它,看到他们正在寻找不同技能的团队,也包括数据科学家。牛逼我以为,我进去了!

我报名、申请并被录取了。答对了。

简单介绍一下我的背景可能会有帮助。我目前在德国攻读计算机科学硕士学位的第一年,我在兼职做机器学习工程师。所以我知道一些基础知识,但是,我想黑客马拉松也是为了让新手加入游戏,让他们与志同道合的人交往。

由于这是我的第一次黑客马拉松,我认为一个月的持续时间或多或少是正常的。我查了一下其他的黑客马拉松,是不是

艰难时期。

我最终加入了一个由来自世界各地的 9 人组成的随机团队。这些人真的很了不起,非常有野心,这也是游戏走到这一步的动力。

黑客马拉松开始

正式开始了。我们先打了几个电话,相互了解了一下,头几天除了头脑风暴什么也没做。由于这次黑客马拉松持续时间特别长,我们有时间思考,所以没关系。但是等等…我是团队的数据科学家,对吗?我注册时期望我会收到一些数据。甚至在开始之前,我就已经想好了我要分析什么东西!

  • 销售?
  • 营销?
  • 也许是一些产品研究?

三天过去了。没有收到。玩得好的黑客马拉松公司!好吧,该怎么办?我可以从网上搜集数据。由于我是做营销或者销售为主的数据科学,所以先查了一下:如何刮 Instagram。

可能会有用,但是,嘿,那是第三天,我们不知道我们想要哪个产品和策略,所以我不知道从 Instagram 上刮什么。

旁注:半决赛在头两周之后举行,在被选入前七名的团队之后,我们还有十天的时间提交最终报告。

第一周已经过去了,我们对产品有了一些粗略的计划。我基本上转换成了想法产生者的角色,因为没有其他事情可做。在此期间,我发现有很多像 Statista 这样的网站提供的产品相关的销售数据。我认为很好,但是……这要花钱(€)。

你可能觉得现在是我刮 Instagram 数据做营销分析的时候了。让我感兴趣的是,在过去的几个月/几年中,为了找到我们产品的趋势,如何使用和搜索特定的关键词或标签。哦不!我很容易抓取图片和它们的标签,但 Instagram 的关键词分析也是如此..花钱(€)。

旁注:在此期间,我有考试和工作要做,所以我不能像其他人一样,花整整一个月的时间在这个黑客马拉松上。

进入决赛——只有前七名的队伍。

事实证明我的团队非常聪明。在展示了我们的半决赛展示后,我们被选中进入决赛。我提供了许多想法和想法,但数据科学相关的见解?还没有!我现在真的很想为决赛做一些数据科学方面的工作。

我有主意了!

这是怎么回事..一个是,一个调查

事实证明,用 Google Survey 建立一个调查是相当容易的。我花了几个小时想了一些好问题,尽管我以前从未这样做过。我想我不想用一个 10 分钟就能完成的调查来烦扰人们。因此,我只选择了七个问题,并试图涵盖尽可能多的内容,例如:

  • 人口统计学
  • 收入
  • 愿意使用这种新品种和其他一些品种
  • 愿意花多少钱

在想出清晰具体的问题后,我把它发给了我所有的联系人。我所有的团队成员都把它发给了他们的联系人。但是,这还不够!

如果黑客马拉松公司不想向我提供数据,他们至少应该承担责任,将我的调查分发给他们公司的实习生。

我的调查 400 票~万岁😊

收集了两天的投票,从 Google Survey 下载了结果为 CSV 文件,超级好看。最后,是时候做一些数据分析了。不幸的是,我不能展示我的任何图,因为这是机密机密信息,但让我这样说吧,Seaborn 发布了一个新版本,其中他们制作了带有hist plotpre eetient 的二元图,很好且易于使用。

https://seaborn.pydata.org/tutorial/distributions.html

现在,我可以根据调查问题,用所谓的人物角色来支持我的团队。这是一项营销工作,用来识别和描述最有可能购买我们产品的人。

我还可以评估其他指标来支持销售团队,并评估用户行为,以便向我们的设计师提出这个问题,并以这种方式调整产品设计。

结论

总的来说,我学到了很多。我不会再参加为期一个月的黑客马拉松,但肯定会参加一个更短的。我学到的是,我现在提前询问数据是否将由提供而不是。也许这是我参加的这次黑客马拉松的一个特例,因为它不太像黑客马拉松,而更像是一次创意推介。

如果你计划参加这样的活动,请记住这一点。

强烈推荐!

等等,你不能不告诉我们你赢了就走!

我们没有。我们在 130 名参与者和 30 个团队中获得了第二名名,并赢得了丰厚的奖品。足够好我猜:)。

感谢阅读。

不平衡数据的成功:答案是 25,而不是 42

原文:https://towardsdatascience.com/success-with-unbalanced-data-the-answer-is-25-not-42-9c9ffe233620?source=collection_archive---------33-----------------------

在稀缺数据上使用 xgboost 获得与业务相关的结果

图片来自 tshirtgifter.com

在《银河系漫游指南》中,我们被告知生命、宇宙和一切的答案是 42。今天,我认为老鼠错了。当处理不平衡的数据时,答案是 25,或者至少在 25 左右。

作为数据科学家,我们经常得到严重偏向非事件的数据。取消合同、升级产品或扩大服务的人往往占少数。这使得算法识别它们具有挑战性,因为缺乏从中进行预测的样本。事实上,当您想要识别的类别少于 5%时,该模型可以通过简单地预测没有人会流失/追加销售来为您提供 95%的准确性。很好的度量结果,但对业务毫无用处。

除非你有完美的数据,否则你不太可能识别出所有积极的类别。因此,我们的重点应该是以尽可能高的准确度识别阳性类别的前 x%。这里我说的是相对低的召回率,高精度。

  • 回忆:你能确定你的积极阶层的比例是多少?
  • 精确:在你认为积极的人中,正确的比例是多少?

在下面的示例中,有 100,000 名客户,有 5000 名客户经历了客户流失、追加销售、网络故障等事件,企业需要您预测这些事件会在哪里再次发生。在这里,模型挑选出 15%有问题的顾客(召回),在那些被预测的顾客中,有 60%的精确度——不完美,但如果你随机选择,比 5%好得多。

这里的挑战是,这两个价值存在权衡。一个模型可以得到更高的精度,但是召回率会下降。这归结为一个商业决策,即截止点应该在哪里。应该注意的是,多个截止点可以为或多或少可能的客户群创建不同的行动。

好的,但是我如何到达那里?

如上所述,该算法可能会将所有事情都预测为“负面的”,其结果对企业来说是不可用的。我们可以通过调整模型中错误决策的权重来防止这种情况。这告诉模型,不正确的正值赋值代价更高,因此预测更多的是上述混淆矩阵的正方向。

问题是“我们用什么值?”算法有时会提供一个“平衡”的选项。在我们上面的例子中,我们有 5%,这相当于赋予权重 20。今天我告诉你这是错误的。你的目标应该是综合价值 25。我所说的组合是指正类比例和加权值的乘积。在上面的例子中,我们的正类比例是 5%,因此我们希望权重为 5。

通过选择组合值为 25 的权重,您添加了足够的权重以确保有足够的预测,但您也添加了召回范围低端的粒度,那里有真正高的精确度。这可以增强对客户的定位。

让我们通过一个例子来实现这一点。我在 Kaggle 数据集上进行了这个实验:家庭信用违约风险挑战 : 这里大约有 8%的客户违约。 (感谢威尔·科尔森在这里做了数据准备)

我在这个数据集上运行了一个 xgboost,使用了以下参数,但是请注意,scale_pos_weight 变量被设置为 3.1,以获得神奇的 25 数字。

然后,我以 1%的增量在概率阈值上创建预测,以针对测试和验证目标集生成召回率和精确度。我创建了测试验证集,因为我想测试输出的质量和一致性。我们稍后会看到这一点很重要。

我用 12.5 的“平衡”权重重复了这个过程,并用 plotly.express 生成了这个图。

我们的业务环境要求我们需要最高精度的,因此我们专注于最低 20%的召回率。在这个图表中显而易见的是蓝色气泡的频率,它表示模型的权重为 3.1。

气泡的大小代表测试组和验证组的精度之间的差异。这是平方和平方根,以保持可比性。下面比较了两种模型在不同截止点的情况。

这表明加权值为 3.1 时,该值的平均值较低。这意味着粒度越大,我们也能获得更高的一致性。这对企业来说是个好消息。他们可以更好地锁定最有可能的客户,并获得更可靠的结果。

不要做什么…

可以推荐的另一种处理不平衡数据的方法是重新平衡它。这可以通过过采样正类或下采样负类来实现。这里的理论是,你让你的算法有机会识别你的样本中太小的部分。这可以手动完成,就像我下面做的,或者甚至有专门的包,比如 SMOTE。

下面,我比较了两者的权重都为 3.1 的输出,但是红色组已经对训练数据进行了重新平衡,因此正面类的大小是负面类的 25%。

我们在这里看到的是,红色(重新平衡)组的气泡尺寸明显更大。这也是测试集和验证集之间的精度差异。这表示通过重新平衡数据,结果更加不一致。

这甚至适用于没有对重采样数据进行加权的情况。下面是权重为 1 的重采样数据集和权重为 3.1 的非重采样数据集之间的平均差异,我们看到权重为 3.1 时的误差较低。

离别之思

有趣的是,在生成这些模型时,它们都生成了 0.74 的 AUC 和变化。所以最初的观点会说这并不好。然而,我希望这能鼓励你比你的第一个指标看得更深一点,并帮助你为你的企业创造更多的价值。

这篇文章的所有代码都在 Github

Python 项目的成功 spark 提交。

原文:https://towardsdatascience.com/successful-spark-submits-for-python-projects-53012ca7405a?source=collection_archive---------5-----------------------

在真实的集群上平稳地运行您的项目,而不是您一直使用的那个虚拟集群。

TL;博士:学习的最好方法就是去做,而学习难的东西最好的方法就是一小步一小步的去做。这是针对在独立开发环境中处理包的 Python 实践者(可能是数据科学家)的指南,他们希望在集群上使用该包成功执行 Spark 作业。大数据技术堆栈乍一看似乎令人望而生畏:本文的目标读者是那些刚刚开始有效地使用集群的人,他们希望自己的项目能够顺利启动并运行,然后满怀信心地探索、利用这一经验并完善自己的风格。

Python 程序可能无法在恶劣的环境中生存。

介绍

已经够了!带我去指南(向下滚动)。

这个问题。

在为 Spark 编写、开发和测试我们的 Python 包时,很可能我们将在某种隔离的开发环境中工作;在桌面或专用云计算资源上。至关重要的是,我们可以自由组合的 Python 环境,即我们最喜欢的所有最佳包的次要版本,很可能不同于在我们友好的邻居集群上执行的普通 spark-submit 作业可访问的 Python 环境。一般来说,希望有一定程度的灵活性,并且能够快速地将附加的依赖项合并到原型环境中。在开发我们的代码的热情和兴奋中,准备一个与我们的包兼容的集群范围的环境,准备接收和执行我们的 Spark 作业的远见可能避开了我们。现在,这个不可预见的障碍正在阻止我们大规模地运行我们的项目,这对一个数据科学家来说是一个悲哀。

一种解决办法。

在接下来的内容中,我们将以透明和可访问的方式,通过 spark-submit 完成在 Spark 上运行 Python 包的必要步骤。本指南中涵盖的步骤有:

  1. 如何打包和准备我们的 Python 项目,以便在 Spark 集群上成功执行。
  2. 使用适合我们项目的 Python 版本准备一个最小的工作环境,并将其上传到 Hadoop,使所有工作人员在执行时都可以访问它。
  3. 打包我们的项目依赖关系。
  4. 准备 spark-submit 脚本,以一种可理解的方式将上述所有内容整合在一起。

目标受众。

与该主题相关的现有资源(参见进一步阅读)主要是为了用 Python 产生生产级的 Spark 作业。它们真的很棒,但是对于那些不太熟悉集群模式下工作 Spark 的复杂性和细微差别的人来说,可能会形成一个陡峭的学习曲线;有很多东西需要消化。如果您刚刚开始接触这些大数据技术,您将需要很好地理解基础知识。本指南关注基础知识和关键概念,强调你在开始时肯定会遇到的事情。

向导

序言。

我的职业是数据科学家。我在一个运行 Hadoop 的商用集群上工作,使用 Spark 为机器学习和数据科学项目构建大数据管道,处理包含数十亿行的超大型数据集。开发在隔离的环境中进行,使用 Anaconda 作为 Python 发行版。通常,我会设置几个不同的虚拟环境,以便将 Spark 处理步骤从项目的其他方面分离出来。

在开发中,我的项目将是这样的结构。

my_data_science_project
├───data
├───models
├───envs
│   ├───/spark_env/
│   └───/ml_env/
├───conf
├───notebooks
│   ├───model_explore.ipynb
│   └───eda.ipynb
└───src
    ├───data_pipeline
    │   ├───functions.py
    │   ├───processing.py
    │   └───__init__.py
    ├───app.py
    └───__init__.py

我将使用 Jupyter 笔记本来试验和调整转换,仔细检查结果,直到它们与我试图实现的相匹配。最终,一旦所有的代码都做了它应该做的事情,下一步就是打包它,并从我们将传递给 spark-submit 作业的脚本中调用转换步骤。spark-submit 作业将按照我们的指令设置和配置 spark,执行我们传递给它的程序,然后干净地释放正在使用的资源。传递给 spark-submit 的一个简单的 Python 程序可能如下所示:

"""
spark_submit_example.pyAn example of the kind of script we might want to run. The modules and functions of our package can be imported and accessed in the usual way. Command line arguments can be accessed in parsed in the usual way. We can even read in files in the usual way. In fact, its all very... usual..."""import yaml
import sys
import src.data_pipeline.processing
from src.app import get_spark def run(ss, appConfig):
    # Do some steps using the appConfig
    input = ss.read.parquet(appConfig['input'])
    output = src.data_pipeline.processing.process(input)
    output.write.parquet(appConfig['output'], mode = 'overwrite') if __name__ == "__main__":
    #Get some configuration settings
    args = sys.argv
    appConfig = args[1] with open(appConfig) as file_handler:
        appConfig = yaml.load(file_handler, Loader=yaml.Loader) # Suppose the Spark session builder is wrapped in this function.
    ss = get_spark() run(ss, appConfig)

在一个刚刚脱离孤立开发环境的集群上,让这一点顺利工作可能会很棘手。有许多活动部件。之所以有这个指南,是因为我自己也经历过这个过程,我认为如果有这个指南作为参考,会大大加快速度。

声明:我不会开始讨论如何正确配置和创建绑定到 Spark 会话的 Python 对象。这本身就是一个话题,而且假设你已经成功地做到了这一点。在这里,我们将这个任务的复杂性委托给假设的get_spark()

1。打包项目。

第一步是打包所有属于这个包的 python 文件、模块和脚本,即./src/目录的内容。这一步没什么特别的,你可以在这里阅读 setuptools 的用法。创建您的 setup.py 文件和python setup.py bdist_egg。在这一步之后,我们将有一些新的文件和目录,包括一个.egg,它在本指南中就像一个.zip。当我们稍后运行我们的 spark-submit 作业时,我们将让程序知道包含我们的项目源代码的 egg 文件,它将把这个文件发送给驱动程序和工人。当我们的应用程序启动时,传递给--py-files的任何工件(鸡蛋、拉链)的顶层都被添加到PYTHON_PATH,这就是我们如何从传递给 spark-submit 的程序中导入我们的包。

my_data_science_project
├++ setup.py      ]- python setup.py bdist_egg to produce the below.
├++ dist/                      
│   └++ my_data_science_project-0.1-py2.7.egg
└++ build/ 

2。准备一个最小的工作环境。

当用 Python 驱动程序运行我的 Spark 作业时,我喜欢使用最小化的工作环境。在原型开发和开发时,很容易以臃肿的虚拟环境告终,因此这是重新考虑是否可以进行任何修剪的有用点。如果我们运行的程序最终被表示为纯 Spark(而不是用 numpy、pandas 做任何事情),那么我发现只使用内置模块和一个 yaml 解析器就可以走得很远。

让我们继续使用 conda 创建一个新的环境,不包含任何默认安装的包(我们的 spark 作业可能不需要这些包)。

conda create \
--name spark_submit_env \
--no-default-packages \
--copy \
--prefix ./envs \
python=xx 

运行上面的命令将在./envs/中给我们一个额外的目录,其中包含我们的最小工作环境。当我们调整 Spark 程序时,我们可能会反复使用这个环境,所以我们会将它上传到 Hadoop 文件系统,而不是每次我们想要运行 Spark 作业时都要运送和分发它。我们将把我们的环境作为.zip上传到 Hadoop,这将保持一切整洁,并且我们可以告诉 spark-submit 我们已经创建了一个归档,我们希望我们的执行者能够使用--archives标志访问它。为此,首先遵循以下步骤:

  1. cd ./envs/spark_submit_env/
  2. zip -r ..spark_submit_env.zip .

现在向上移动一级,运行以下命令:

hadoop fs -copyFromLocal ./spark_submit_env.zip /hdfs/env/path/

记住这个 hdfs 路径,我们将在稍后的 spark-submit 脚本中引用它。上面运行的命令将在我们的项目目录中添加以下内容。

my_data_science_project
├───envs
│   ├───spark_env
│   ├───ml_env
│   ├++ spark_submit_env      ]- zip this up
│   └++ spark_submit_env.zip  ]- upload to hdfs
├───conf

3。打包依赖项。

准备好我们的spark_submit_env并上传到 hdfs 之后,我们现在开始准备我们的 Spark 作业所依赖的特定依赖项。这里有多种方法可以达到同样的效果,而且非常简单。这些步骤对于曾经打包过项目的任何人来说都是直观的,但是,我们确实想确保我们的spark_submit_env中有针对特定 Python 版本的正确版本的包。在一辆requirements.txt里草草写下我们的星火工作所需的包裹:

requirements.txt
pyyaml
another_package_you_love
~

然后,source activate spark_submit_env,让which pip放心地告诉我们/path/to/your/project/envs/bin/pip。现在,我们可以确信我们的 spark-submit 工作所需的包将与我们准备的环境很好地配合。我们现在可以pip install将需求中列出的依赖项放到一个指定的目录中,我们会将其压缩并传递给 Spark。

pip install -t ./dependencies -r requirements.txt

my_data_science_project    
├++ requirements.txt     ]- pip install this
├++ requirements/        ]- to here, then zip it up
├++ requirements.zip     ]- like this.

请注意,我们可以在开发过程中直接将依赖项打包为工作环境设置的一部分并进行分发,但是单独明确地列出并捆绑包依赖项会保持事情的美观和透明。我们也可以删除多余的包,这些包对 eda、可视化等很有用。,但不是授权给 Spark 的步骤所直接需要的。

4。spark 提交脚本。

这是我们将迄今为止所经历的所有步骤汇集在一起的地方。这是我们将运行来调用 Spark 的脚本,在这里我们将让它知道我们准备的 Python 环境、我们打包的项目及其依赖项。spark-submit 脚本如下所示:

#!/bin/bashPYTHON_ZIP="hdfs:////hdfs/env/path/spark_submit_env.zip#pythonlib"
PYSPARK_PYTHON="./pythonlib/bin/python2.7"PROJECT_EGG=./dist/my_data_science_project-0.1-py2.7.eggSPARK_CMD = "spark-submit \
--conf spark.yarn.appMasterEnv.PYSPARK_PYTHON=${PYSPARK_PYTHON} \
--archives ${PYTHON27_ZIP} \
--py-files ${PROJECT_EGG},./dependencies.zip \
--master yarn \
--deploy-mode cluster \
--files ./conf/appConf.yml#appConf.yml \
spark_submit_program.py appConf.yml arg2 ..."eval ${SPARK_CMD}

我们来分析一下。

PYTHON_ZIP="hdfs:////hdfs/env/path/spark_submit_env.zip#pythonlib"

在这里,我们声明变量PYTHON_ZIP,并为它分配我们在步骤 2 中上传 Python 环境的文件 url。#pythonlib后缀是一个小技巧,允许我们在 YARN 上运行 Spark 时指定名称别名。我们可以用它为传递给--py-files--archives的任何东西指定一个文件名别名。这个别名是 Spark 应用程序将看到的实际名称。你可以在这里阅读更多。

--conf spark.yarn.appMasterEnv.PYSPARK_PYTHON=${PYSPARK_PYTHON}

这里我们设置环境变量 PYSPARK_PYTHON 指向我们打包到 spark_submit_env 中的 PYTHON 可执行文件。搜索以上这里阅读更多。

--archives ${PYTHON_ZIP}

传递给--archives get 的任何东西都被解压缩到每个执行器的工作目录中,所以传递压缩环境的 hdfs url 就是这些执行器访问我们准备的环境的二进制文件和模块的方式。

--files ./conf/appConf.yml#appConf.yml

传递给--files的单个文件也被复制到执行器的工作目录中,同样,我们可以使用/path/to/file#alias语法来命名它们。例如,我们可以传递一个 yaml 文件由驱动程序解析,如spark_submit_example.py所示。

spark_submit_example.py appConf.yml arg2 arg3 ...

在指定了我们的[OPTIONS]之后,我们传递由驱动程序执行的实际 Python 文件:spark_submit_example.py,以及程序的任何命令行参数,它们可以用通常的方式进行解析。例如,第一个参数可能是一个 yaml 文件appConf.yml,可能会有后续的参数为程序提供更多的上下文。

跑跑跑。

我们终于可以执行上面描述的 spark-submit 脚本了:

./spark_submit_script.sh

最后提醒一句,当使用虚拟环境时,要小心对PATH的修改。我以前在尝试 spark-submit 时遇到过问题,却不记得停用某个特定的虚拟环境。

如果你已经做到了这一步,我希望这是因为你发现本指南的内容很有帮助——我很想知道是不是这样。如果有人有足够的时间提出要求,我会非常乐意详细说明任何细节。我非常乐于接受反馈。因此,如果你发现不一致或错误,请大声喊出来;我会立即删除这篇文章,并删除它曾经存在过的所有痕迹,以及我的帐户和我的 LinkedIn。我将离开不适宜居住的环境象形图,虽然那花了我很长时间。

延伸阅读

当您对本指南中介绍的步骤有信心时,您可能想看看以下资源:

如何使用良好的软件工程实践设置 Python 和 Spark 开发环境

建筑生产 PySpark 岗位

编写生产级 PySpark 作业的最佳实践

对专业仪表板的建议

原文:https://towardsdatascience.com/suggestions-for-professional-dashboards-b4c74b5b1b33?source=collection_archive---------54-----------------------

办公时间

如何为企业高管构建有效的数据可视化

卢卡斯·布拉塞克Unsplash 上拍摄

在过去的几年中,随着大量数据的广泛可访问性,从可用信息中获得洞察力已经成为任何决策过程中的重要步骤。

特别是当数据是大数据时,为了更好地理解发生了什么,你需要组织、总结和可视化信息。

但是,即使有了可视化,如果你不遵循一些简单的准则来使你的仪表板有效,你所有的努力都可能是徒劳的。

当然,当你设计一个新的仪表板时,你的分析的目的和目标是首先要考虑的事情。

这就是为什么在本文中,我想关注业务主管的专业仪表板,目的是以一种有效的方式展示业务在销售、成本、收入、客户以及对你的一线经理来说重要的任何方面的进展。

了解你的受众

在定义了目的和目标之后,你不仅需要关注管理者在公司中扮演的角色,还要关注他们的偏好和品味。

例如,你需要知道:

  • 他们的关注点是什么,最重要的是,他们现在的关注点是什么?
  • 将收到仪表板的经理们可能会喜欢数据的花哨和现代的表示(蒸汽图、旭日图、弦图等)吗?),还是配条形图比较好?
  • 他们喜欢桌子吗?
  • 他们喜欢收到 PDF 还是 web 仪表板的链接?

建立一个原型

没有什么比努力工作而哑火更糟糕的了。此外,一旦你建立了一个仪表板,你会觉得非常保护它,你将很难接受任何负面的评论。

因此,在你对一个潜在的仪表板工作数周之前,注意每一个细节,最好先建立一个原型,并与同事一起测试。

原型应再现仪表板的主要功能,在大多数情况下,它可能包含样本但现实的数据。阅读报告的人应该对报告的主题有一个大致的概念,但不应该是超级专家。

在这个阶段,倾听、评估和应用建议会更容易、更快。根据我的经验,一些最受赞赏的分析或特性可以很容易地从这些评论中得到。

保持简单

根据我的经验,高层管理人员没有足够的时间,他们的注意力通常集中在特定的项目或主题上。

因此,您需要记住,您想要传达的信息应该能够从您正在构建的仪表板中轻松理解。

试图在一个仪表板中容纳大量信息可能会导致混乱。所以,最好是去掉多余的部分。

可以在仪表板中引用对特定主题的关注,并链接到其他仪表板或其他页面。

你的经理可能没有足够的时间去理解他们以前没有见过的奇特图表,所以你可能应该坚持使用他们已经知道的经典图表(条形图、散点图、折线图等)。).但同样,这取决于经理。

移除多余部分

当你不得不去除多余的时候,有一些常见的疑点需要寻找。

  • :它们是必要的还是图表有足够的信息?通常在条形图中(条上有标签),轴是可消耗的,而在散点图中,轴是必需的。
  • 价值观:你能调整你的价值观以避免大数字吗?小数值是必要的吗?20,000,000 比 20bln 差得多,在有 4 或 5 个有效数字的数字后添加小数点通常是多余的。
  • 附加信息。很可能,你需要在你的仪表盘上添加一些信息(如何阅读图表,如何计算一个指标的细节,等等。).我的建议是在主仪表板上只保留相关的笔记,尽可能把它们放到脚注、附录或隐藏层中。无论如何,不要写太多,这不是教科书。
  • 双轴。通常,双轴用于表示同一图表中的两条信息。在我看来,人们应该只使用双轴来显示相关性的存在(或不存在)。

指标和关键绩效指标

将最重要的指标和 KPI 用大字体添加到仪表板的最上方可能会很有用。这是他们开始阅读报告的地方,因此,这也是他们寻找最重要数字的地方。

惊喜

增加一些惊喜。这可能是经理们没有预料到的与图表的互动。

如果您的可视化工具具有这种功能,您可以在单击仪表板的特定点时添加额外的分析或焦点。这也是从仪表板中移除分析并按需显示的一种方式。

保持清洁

有些事情会造成混乱:

  • 在同一个仪表板中使用多种字体大小。可能有一些例外,但它们应该是合理的(例如在仪表板顶部代表 KPI 的大数字);
  • 在同一个仪表板中使用多种字体颜色。例外也必须有正当理由;
  • 未对齐的形状;
  • 使用相同类型的图表来表示不同的事物。

也许你没有意识到,但我向你保证,所有这些事情都会让读者感到不舒服(甚至他们中的大多数人都不知道这种不舒服来自哪里)。

字体大小应该足够大,以便从他们用来访问仪表板的设备上容易看到。疯狂地排列图表和测量尺寸。

如果你有品牌识别指南(规定了你可以使用哪种颜色和哪种字体),请严格遵守。

此外,如果您的经理已经收到了来自其他部门的仪表板,尽量保持格式统一,以避免混乱。例如,如果您的经理习惯于将过滤器放在左侧,将它们移到另一侧是不利的(他们会失去寻找过滤器的时间和耐心)。

保持速度

好了,现在您已经有了一个通过了强大的“走廊测试”的控制面板,但是当您打开它时,需要几分钟来加载所有的图表。对经理来说太多了。我建议停留在 10 秒以下。

有很多方法可以减少加载时间,有些取决于你使用的可视化工具(Tableau,Power BI 等)。).但大多数都很笼统:

  1. 首先,如果您的仪表板包含来自许多来源的数据,这可能会导致刷新时间成倍增加。所以,试着理解你所有的资源是否都是必要的(再次去掉多余的)
  2. 您的仪表板的大部分将由聚集和过滤数据组成。在这种情况下,您可以在数据库中创建只包含有用数据的新表,并保留原始表(包含所有数据)用于探索性数据分析。

有时,数据源可以混合在一起,这样可以节省时间。

此外,如果您的数据是与时间相关的,那么可能需要过滤掉一些旧的日期。您真的需要过去 3 年的每日数据吗?或者您可以满足于过去 3 个月的每日数据和过去的月末数据?

总结

一个精心设计和量身定制的仪表板可以让你的受众做出正确的决定,或者被忽略掉大量的辛苦工作。

在本文中,我重点介绍了面向高管的专业仪表板,并分享了在构建新的可视化时需要记住的一些事情:

  • 一个尺寸不能适合所有人,所以最好把重点放在你的主要读者上;
  • 造一个原型,和尽可能多的人一起测试;
  • 扔掉你不需要的,让你真正需要的可见;
  • 注意细节,它们会有所不同。

遵循这个建议,你的读者会喜欢你的仪表盘!

自杀是一个会传染的想法:你能做什么

原文:https://towardsdatascience.com/suicide-is-almost-as-contagious-as-covid-19-we-can-change-that-through-social-media-c0bb573a9366?source=collection_archive---------36-----------------------

丹·梅耶斯在 Upsplash.com拍摄的照片

上周一,2020 年 8 月 3 日,思科与 SAVE 合作,发布了 https://reportingonsuicide.cisco.com/的公测版。这是一个关于我们如何利用数据科学拯救生命的故事,为什么这个发布会如此重要,以及你如何通过改变你交流精神疾病的方式来帮助防止自杀。也是我的故事,我从来没有公开讲过。

上周四,8 月 6 日,是一个非常亲密的朋友自杀五周年纪念日。Erika 和我穿越了三大洲,从一架飞机上跳下,设计了定制的配对小指戒指,甚至一起创作了一本书。我们(几乎)无话不谈,并在谷歌上列出了我们将要进行的所有冒险。我们真的有一个共度余生的计划。

然后,在她 30 岁生日的前一个月,她自杀了。这让我崩溃了。对于那些因自杀而失去亲人的幸存者来说,这是很常见的,在接下来的 4 年里,我一直为她的死而自责。

2019 年,艾瑞卡的父亲比尔·艾尔金顿(Bill Elkington)和他在艾瑞卡去世后介绍给我的心理学家彼得·科姆里帮助我理解了我们谈论精神疾病和自杀的方式往往会影响人们是否寻求他们需要的治疗。或者,如果像艾丽卡那样,他们如此有效地掩盖自己的疾病,以至于威胁到生命。

丹·赖登伯格博士的一生我是通过 https://reportingonsuicide.org/而熟悉他的工作的,受到他的启发,我给丹博士打了个电话,问他是否愿意一起努力使他的研究民主化。很明显,即使科学是可靠的,并得到包括疾病预防控制中心在内的有眼光的组织的支持,指南的采用水平还是很低——太低了。丹博士接受了我的邀请,今天我很荣幸地称他为同事。基于他和他的合作者的发现,世卫组织将报道自杀确定为预防自杀的 7 个优先领域之一,并为媒体专业人员创建了一个资源库。

2019 年末,Thomas Niederkrotenthaler 博士发表了令人震惊的研究:在名人自杀的报道不符合世卫组织准则的情况下,传染效应将全国自杀率提高了高达 13%。尽管彼得已经意识到自杀的传染效应——根据统计,艾丽卡的自杀使我死于自杀的可能性增加了 5%—50 %,彼得估计我的个人风险水平接近 75%——但我不知道传染效应如此之大。当我试图更好地理解传染效应时,丹博士告诉我,总的来说,其他人是否会因为另一个人(无论是否是名人)的自杀而死亡的风险约为 3-5%。为了更好地理解这个数字,新冠肺炎的传染效应是 5.7%

我不是媒体专业人士,很可能你也不是。但是,越来越多的人每天转向社交媒体获取新闻,这模糊了内容创作者和消费者之间的界限。这意味着指导方针不仅适用于专业人士,也适用于我们这些业余爱好者(他们在脸书、推特、LinkedIn 等网站上发帖)。)也是。好消息是它们相对较短:

  1. 不要讨论、描述或描绘某人自杀的方法和地点。这样做已经导致了无数次自杀事件的增加——以同样的方式不成比例地增加。
  2. 不要用“自杀”这个侮辱性的词汇。人们犯罪,而不是生病。相反,说“死于自杀”或“自杀”
  3. 不要分享遗书的内容。它会把认同其内容的人推向自杀,而不是寻求治疗。
  4. 不要过分简化或推测自杀的原因。我们仍然没有完全理解自杀和精神疾病,但我们知道自杀从来都不简单。
  5. 不要美化、浪漫化或煽情自杀。如果你觉得自杀很迷人、浪漫或耸人听闻,请向心理健康专家寻求帮助。
  6. 请记住,自杀的话题可能会引发任何人与你交谈或阅读你的社交媒体帖子。确保你的帖子引用了帮助热线。例如,在美国,国家自杀预防生命线的号码是 1–800–273–8255;危机短信热线可以通过给家里发短信联系到 741741(美国)、686868(加拿大)或 85258(英国)。

基于这些令人难以置信的研究,我和我的合作伙伴 Annie Ying 博士(人工智能博士)制定了以下计划:创建一个类似于语法检查器的工具,用户可以在发布前/发布前粘贴文本,突出显示任何不符合指南的单词或短语,同时提供教育和建议。

2019 年早些时候,我建立了思科的数据科学和 AI for Good 计划,作为思科人无偿回报的渠道,对 100 多名自愿为预防自杀贡献时间的人表示感谢。这份名单包括执行发起人首席数据官 Shanthi Iyer 和数据科学负责人 Sanjiv Patel,没有他们,我们的全球平台愿景所需的工具和基础设施将成为巨大的障碍。

志愿者加入后,我们的第一步是数据标记,因为不存在我们可以从中获取信息的存储库。数据科学家 Riley Hun 建立了一个基于 API 的数据管道。建筑师 Edgar Murillo 随后创建了一个易于使用的 UI,即使非技术志愿者也可以阅读媒体报道,并标记哪些文本违反了哪些准则。许多许多个夜晚和周末之后,我们已经标记了将近 2000 篇文章。我想借此机会向我们的顶级贡献者大声欢呼:丹尼斯·切斯基(294 篇文章)、罗斯·普菲尔(242 篇)、泽西·基梅尔(165 篇)、阿尔特米奥·里曼多(119 篇)、佩里·梅斯(107 篇)、乔迪·麦克米伦(95 篇)、梅根·理查森(86 篇)、斯科特·埃利奥特(79 篇)、加里·班塔德(65 篇)、安东尼·纳西亚特卡(61 篇)、克里斯·多兰(54 篇)和林恩·考夫兰(50 篇)。

我们惊恐地发现,我们标记的文章中只有 3%遵守了所有的准则。

利用标记的数据,数据科学家 Artemio Rimando 和 Shima Gerani 用 Python 构建了基于字符串匹配的数据科学模型,而产品经理 Raphael Tissot 则构建了网站和用户体验。这是一个历时数月的过程,丹博士和他的团队与我们密切合作,以确保该工具的功能符合他的标准。

现在,公开测试版已经上线,该团队正在努力提高该工具的性能(在我撰写本文时,Shima 正在编写代码),并根据我们的媒体和学术合作伙伴的意见构建产品开发路线图,以最大限度地提高指南的采用率。

至于你,亲爱的读者,请采纳这些指导方针。T2 将会帮助拯救生命。

用数据科学洞察自杀预防

原文:https://towardsdatascience.com/suicide-prevention-insights-with-data-science-f33131a3c3d0?source=collection_archive---------36-----------------------

心理健康

宗教是强有力的抗抑郁药

我相信我第一次经历强烈的情感冲击是在大约 11 岁的时候,当时我发现我认识的、钦佩的、被认为成功和幸福的人突然决定以自杀来结束自己的生命。短短几年内,我的两个童年好友的爸爸就发生了这样的事情。这两个人看起来都像慈爱的父母和模范公民,所以这个消息对我和他们各自的社区来说都是一个巨大的冲击。同样的悲剧故事在我青少年时期的三个主要英雄身上重演——柯特·科本、罗宾·威廉姆斯和安东尼·鲍代恩。这些年来,我度过了无数个不眠之夜,试图找出是什么可能将我所热爱和钦佩的人推向如此极端,这些人乍一看似乎拥有成功和幸福的生活。所有这些没有答案的问题可能会折磨任何近距离接触过亲密朋友、家人或明星偶像令人震惊的自杀事件的人,在这些问题的驱使下,我决定与我的同学布莱恩·斯雷布雷尼克合作,尝试用数据科学来研究自杀之谜。

这个项目的目标是利用 200 个国家的一些社会经济和心理健康指标建立一个机器学习监督的回归模型,并试图确定哪些因素可能与国家自杀率有统计上的显著相关性。

在对之前在这个问题上所做的工作做了一些研究后,我们收集了以下自变量的数据,我们认为这些数据将有助于建立我们的模型。我们使用了 2016 年的数据。

  1. 抑郁率
  2. 精神分裂症发病率
  3. 焦虑率
  4. 躁郁症
  5. 饮食失调
  6. 酒精使用障碍
  7. 药物使用障碍
  8. GDP
  9. 人均卫生支出
  10. 失业率
  11. 居住在拥有> 10 万人口的城市的人口比例
  12. 上网人口的百分比
  13. 信教人口百分比的分类数据

注:如果您对我们如何构建和优化模型的技术细节不感兴趣,请跳至“模型总结和最终见解及结论”部分,了解我们调查结果的详细总结。

准备数据并检查多重共线性

首先,我们从世界卫生组织 API 和其他几个网站收集了 2016 年的年度社会经济数据。在清理所有数据并将其合并到一个 pd 中之后。数据框架我们使用 SeaBorn 关联热图检查了独立变量多重共线性:

使用 sns.heatmap(final_table.corr(),center = 0)的共线性热图

热图告诉我们,双相情感障碍%与其他三种精神健康问题有很高的相关性,因此我们决定在运行模型之前删除该变量,以避免由严重的多重共线性引起的额外噪声。

检查每个独立变量和自杀率之间的线性关系

接下来,我们创建了每个自变量与因变量自杀率相关性的成对散点图:

使用 seaborn.pairplot()绘制散点图对

从上面的图表中我们可以看到,在抑郁、焦虑、精神分裂症、酗酒的比率和一个国家的宗教程度之间存在某种程度上的线性关系。所以,我们最初的期望是,我们的机器学习模型应该给这些类别分配更多的权重。

缩放我们的独立变量,并在模型中引入变量组合和多项式

由于我们的一些自变量以千为单位,而另一些以百分比为单位,因此我们决定调整所有自变量,以确保我们的模型不会为某些变量分配过大的系数。

使用 sklearn.preprocessing.scale 缩放变量

下一步是通过二次多项式函数引入交互项,以帮助我们的模型进行特征选择,提高其最终精度,并降低均方根误差。下面的关联热图有助于我们识别所有相关的新变量:

对每个回归模型应用 RFE 和交叉验证,以选择最小化 RMSE 的最佳模型

既然我们的数据已经清理、缩放和预处理,现在是最后一步的时候了——根据我们的训练数据训练我们的机器学习模型,以提高其对测试数据的预测准确性。我们使用三个模型优化子步骤来创建我们自己的定制 GridSearch 函数:

  1. 我们使用下面的函数运行线性、套索和岭回归,以确定哪一个生成的模型误差最小。对于这个特定的数据集,我们发现岭回归有最好的结果。我们对训练数据-测试数据比率采用了 80–20 的比例。
  2. 我们使用 RFE(递归特征消除)将所有独立变量逐个输入每个模型,并选择最小化 RMSE 的变量数量和组合。
  3. 我们使用了 K 倍交叉验证来优化每个模型在测试数据上准确预测的能力,这是它以前从未见过的。(代码如下)

我们的定制网格搜索算法

下图显示了我们的 RMSE 函数,以及我们如何训练我们的模型来挑选产生最低误差的独立变量的数量:

选择了 22 个变量,RMSE = 3.54

模型总结和最终见解和结论

现在大部分繁重的工作已经完成,是时候分析我们的结果了。首先,我们用训练数据与测试数据的模型统计绘制散点图,以确保没有太多的训练数据偏差或过度拟合。正如我们从下图中看到的,测试和训练样本的 RMSE、z 分数和 R 平方非常相似,这正是我们所希望的。0.66 的 R_squared 分数并不惊人,但是考虑到我们只有大约 150-200 个例子(国家),我们对模型的表现相当满意。我们相信,如果我们能够将 500 多个观察值输入到我们的训练集中,模型的预测准确性将会显著提高。

基于测试数据和训练数据的模型性能

我们还想看看实际的独立变量及其系数,并试图从它们的分布中得出一些见解和结论。以下是最终模型方程和每个独立变量的条形图及其在最终模型中的权重:

自杀率 = 10.28 + 3.58* 抑郁症 + 2.74* 酒精 _ 使用—1.87 Rel _ 高 — 2.24 精神分裂症抑郁症 + 0.65* 精神分裂症 health _ spend _ perca+1.23 精神分裂症 Rel_Low — 1.56 进食障碍 焦虑 Rel_High + 1.67 药物 _ 使用****Unem _ rate+1.58 药物 _ 使用 GDP — 2.48 抑郁 Rel_High — 1.76 抑郁 Rel_Low — 0.92* 酒精 _ 使用 + 0.71* 酒精 _ 使用 GDP【T44**

结论:

根据下面的方程系数和柱状图,我们可以假设以下假设,并可以进一步检验:

  1. 倾向于增加一个国家自杀率的变量:
  • 抑郁率
  • 酒精使用障碍率
  • 城市人口比例结合与低水平的宗教信仰
  • 城市人口百分比结合高酒精使用
  • 精神分裂症的发病率与低水平的宗教信仰相结合
  • 吸毒紊乱与高失业率结合在一起
  • 与国内生产总值水平相结合的药物使用

2。倾向于降低一个国家自杀率的变量:

  • 人口的高度宗教性
  • 抑郁率结合与高宗教信仰
  • 焦虑率结合与高度宗教性
  • 酒精使用障碍率结合与高度宗教性
  • 药物使用率结合与高度宗教性
  • 饮食失调率与酒精使用率相结合
  • 饮食失调率与药物使用率相结合

调查一个国家的宗教信仰和自杀率之间的反比关系

当谈到对自杀率的影响时,我很好奇也很惊讶地发现我们的模型很重视一个国家的宗教程度。如果我们仔细观察上面的系数图,我们可以看到,大多数似乎对高自杀率有很强直接影响的特征,如抑郁症、酗酒和精神分裂症,在宗教人口高度密集的国家往往会失去它们的负面影响。这一有趣的现象在下面的两个图表中得到了证明:

大多数高自杀率的国家都是宗教人口不到 50%的国家

宗教程度最低的国家 AVG 自杀率要高得多

最后的个人想法

尽管我们没有分析足够的数据来得出任何有力的结论,但我们的发现促使我进一步思考这个话题,并试图提出有效的解释,说明宗教如何能够否定一些似乎导致高自杀率的因素的影响,如抑郁、焦虑和吸毒。我对患有抑郁症和自杀想法的人的主要症状做了一些研究,如下所列:

  • 对未来有一种深深的绝望感,对情况会有所改善不抱太大希望
  • 孤独感和逃避朋友或社交活动的倾向
  • 一种的感觉情感空虚、缺乏爱或人际关系
  • 增加使用药物和/或酒精
  • 经历了最近的创伤或生活危机

宗教是如何对抗这些症状,成为精神上的抗抑郁药物的?

  • 宗教经常围绕着信仰和希望
  • 宗教经常试图赋予苦难以意义,并试图教导人们如何克服个人创伤(解决创伤的痛苦)
  • 宗教机构倾向于提供一个支持系统和一种社区感(解决孤独感和反社会行为)
  • 许多宗教对毒品和酒精持保守观点(解决高毒品/酒精使用障碍)
  • 许多宗教教导说上帝是爱上帝无条件地爱所有的生命(解决爱的缺乏和填补情感的空虚)

因此,有意或无意地,宗教似乎充当了一种强效抗抑郁药物,它可以填补许多患有抑郁症和有自杀想法的人似乎会经历的情感和社会空白。对我个人来说,这是我们项目中最有趣的发现,我可以有把握地说,我将带着在这次调查中学到的许多其他宝贵经验,并试图在未来用它们来帮助有需要的人。我真诚地希望这篇文章也能让世界各地的许多人受益,他们能以这样或那样的方式从我们的发现中受益!和平和爱给所有的生命❤

图形数据库技术在时空数据分析中的适用性

原文:https://towardsdatascience.com/suitability-of-graph-database-technology-for-the-analysis-of-spatio-temporal-data-6167dba64be8?source=collection_archive---------39-----------------------

图形数据库 JanusGraph 和 TigerGraph 与行业标准 PostgreSQL 相比如何?

照片由亨利·佩克斯Unsplash 上拍摄

介绍

时空数据的收集在今天已经司空见惯,主要的例子是来自移动设备或社交平台的用户生成数据、来自静态或移动传感器的传感器数据流、卫星或遥感数据。为了理解这些海量的异构数据,必须应用各种聚合和融合步骤来实现语义数据丰富,以便随后在增值服务中使用。然而,实现这些丰富步骤通常依赖于稳定且高度可扩展的数据处理和存储基础设施。然而,随着时空数据量的不断增加,关系数据库技术(即使有时空数据的特殊对象关系扩展)也达到了极限,目前通常被称为“不仅是 SQL”(NoSQL)数据库的新范例被尝试作为更具可扩展性的替代,例如 MongoDB + GeoJSON 或 GeoMesa。

然而,尽管今天许多类别的数据被解释为图结构,但传统的关系数据库仍然缺乏有效地建模和操作这种结构的体系结构和高级查询语言。图形数据库被设计成将数据表示为顶点和边上的属性。它们通常是无模式的(即,没有固定的数据结构),并且它们的属性被描述为简单的键值对。因此,图数据库的主要优势在于它们擅长复杂的连接式查询,而关系数据库对于大型表的效率是出了名的低。相比之下,当从局部子图转移到完整的图聚集查询时,图数据库往往表现不佳,而关系数据库技术在这方面发挥了它的优势。在商业 ML/AI 和自然语言处理的行列中,Gartner 将 graph analytics 确定为 2019 年 T4 十大数据分析趋势之一。

这项研究调查了哪种数据库技术最适合在真实环境下的典型数据操作任务中处理大规模时空数据。特别是,调查将涵盖开源图形数据库 JanusGraph (与 Cassandra 和 ElasticSearch)、开源对象关系数据库系统 PostgreSQL 和企业级图形分析平台 TigerGraph 的查询速度、可用查询语言的表达能力和计算需求。

我们的贡献可以总结如下:

  • 将两个特征数据集建模并导入三个最先进的数据库,
  • 使用各种分析对它们进行严格的基准测试,这些分析公平地代表了数据集通常会经历的查询和数据操作的类型,并且
  • 通过调查 JanusGraph 和 TigerGraph 的特定图形查询语言实现来比较它们的适用性。

三个数据库

PostgreSQL 被选为我们的控制数据库,因为它在与 PostGIS 结合使用时具有业内公认的时空数据适用性。我们选择了两个具有不同底层架构的图形数据库,即 Java 和 C++,并比较了它们相对于我们的控制数据库以及相对于彼此的表现。尽管在数据库中有这种选择,但还有其他值得注意的提及,如 GeoMesaTerraLib 被证明是时空数据分析的合适替代方法。

这两个数据集

为了进行公正和权威的评估,一方面,我们使用一个真实世界数据集进行基准测试。另一方面,我们使用提供更多控制的模拟数据集来测试所用数据库技术的限制。对于真实世界的数据,Yelp 是一个国际性的商业目录服务和评论论坛。“ Yelp 数据集”是 Yelp 的业务、评论和用户数据的当前子集,包括两个国家的 10 个大都市地区的时空数据,约有 200,000 家企业和 660 万条评论。它在一年一度的 Yelp 挑战赛中提供学术用途,用于各种数据分析和发现任务。

相比之下,瑞典于默奥大学的救护车响应模拟数据集提供了对场景的更多控制——给定一些医院资源,如调度中心和救护车,它模拟救护车如何响应紧急呼叫。数据集记录时空属性,例如响应生命周期内的时间间隔以及响应期间资源的来源和目的地。还记录了关于紧急事件本身的其他技术属性。总之,我们对两个数据集进行了评估,这两个数据集具有不同的时空属性表示、附加属性的复杂性以及总大小。

基准测试应用程序

为了进行基准测试,我们设计了一个名为 Providentia 的时空数据 web 应用程序。它用于对管道中的分析任务进行排队,在管道上运行每个基准,测量服务器性能,并显示累积的结果。在图 1 中说明了架构和每种技术如何通信。使用 Docker 将数据库容器化。

图 1 。普罗维登西亚的建筑

我们使用普通 Python 后端的第一个动机是让基准测试的分析设置更现实。另一个优点是可以使用 Flask 框架轻松快速地设计和部署简单的 REST API。Angular 被主观地选为前端框架,因为它允许快速的前端 web 开发。所有基准测试结果都存储在 PostgreSQL 的一个单独的数据库中。

不幸的是,JanusGraph 有一些特定于 Java 的特性,当使用 Python 中的嵌入式 Gremlin 时,这些特性增加了限制。当试图利用混合索引搜索谓词(如空间查询)时,局限性在于只能通过 Java 或其超集语言来实现。解决这个问题的方法是使用 Gremlin Translator,它将 Gremlin 查询作为一个字符串,并在服务器端对其进行解释。

你可以在 GitHub 库上查看 Providentia 的代码。

分析和设置

内核表示用于数据分析的某种用户故事,特别是以将应用于相应查询的一些时空约束为特征。这些内核中的每一个都将进行 30 次基准测试,因此在比较响应时间时可以考虑平均值和标准偏差。总共有 6 个内核,每个数据集运行 3 个内核。

所有实验都在表 1 中详述的两个设置上运行。使用这些设置可以考虑这些技术如何利用多个内核并在不同的存储限制下执行。每个数据库都是作为单点 e 运行的

表 1 。用于测试数据库性能的两台机器的规格。设置 1 使用 AMD 锐龙 5 2600,而设置 2 是一个 AWS C5 . 4x 大型实例,采用英特尔至强白金 8000 系列 CPU。

结果和讨论

医疗响应数据集

在图 2 的中,可以看到 JanusGraph 在响应时间方面远远优于其他两种数据库技术。这是关于医疗响应数据集的所有三个查询中的特征趋势。另一个趋势是 TigerGraph 和 PostgreSQL 在 TigerGraph 响应最快的地方表现接近。

图二。使用医疗响应数据集为内核设置 1 和 2 的数据库响应时间:“优先级 1 表示响应时间”。误差线显示标准偏差。

与图 2 中的性能相比,每个数据库似乎表现得更加一致(参见图 3** ),偏差更小。JanusGraph 似乎在三个容器(JanusGraph、Cassandra 和 ElasticSearch)之间有某种一致的开销,这似乎会影响响应时间。**

图 3。使用医疗响应数据集为内核设置 1 和 2 的数据库响应时间:“转移患者的第二资源”。误差线显示标准偏差。

这只是一个时态查询,从图 4 中可以看出,TigerGraph 和 PostgreSQL 的性能比前两个查询更加相似。这表明 TigerGraph 比 PostgreSQL 在查询中因约束而增加的复杂性方面表现得更好。

图 4。使用医疗响应数据集为内核设置 1 和 2 的数据库响应时间(TigerGraph 和 PostgreSQL 低于 10ms):“长响应计数”。误差线显示标准偏差。

Yelp 数据集

图 5 显示 PostgreSQL 的响应时间呈线性增长,而 JanusGraph 和 TigerGraph 对于不断增长的数据量保持水平。由于这个查询的复杂性,图形数据库优于关系数据库也就不足为奇了。TigerGraph 在查询响应时间方面优于 PostgreSQL 和 JanusGraph,并且表现出非常高的一致性,因为平均值周围几乎没有标准偏差。

图 5。内核设置 1 和设置 2 的不同百分比数据集的数据库响应时间:“Kate's Restaurant Recommendation”。误差线显示标准偏差。

图 6 显示,与其他两种数据库技术相比,JanusGraph 表现不佳,偏离平均值很高。PostgreSQL 对于这个内核是水平扩展的,这很可能是因为查询是三个内核中最简单的一个。尽管如此,TigerGraph 的表现超过了这两者。

图六。内核设置 1 和 2 的不同百分比数据集的数据库响应时间:“2018 年凤凰城趋势回顾”。误差线显示标准偏差。

图 7 显示了两种图形数据库技术都优于 PostgreSQL,因为 PostgreSQL 显示了线性增长,正如图 5 中的所示。对于在 13%的数据集上的实验,JanusGraph 显示了围绕平均值的大量偏差。这可能是由于 JanusGraph 实现的所有移动部分及其多级缓存实现在这种规模的数据集上表现不佳。

图 7。内核设置 1 和 2 的不同百分比数据集的数据库响应时间:“根据朋友的情绪对拉斯维加斯进行排名”。误差线显示标准偏差。

内存消耗

每个数据库的内存消耗(空闲时)在图 8 中进行了说明,并清楚地显示了 TigerGraph 和 JanusGraph 的图形数据库技术的高成本,分别使用大约 2 GiB 和 10 GiB。PostgreSQL 只使用大约 9 MiB,这比图形数据库要轻得多。

图 8。每个数据集的数据库内存使用情况。医疗响应数据集有 1.5 Mb 大。

用于 JanusGraph 的技术都运行在 JVM 上,并且在给定 32 GB 可用内存的情况下,允许 JVM 的垃圾收集器偶尔运行。JanusGraph 使用的大部分内存是 ElasticSearch、Cassandra 和 JanusGraph 的缓存,每个都存储一个独立的缓存。内存中的大部分波动来自 JanusGraph 容器,这从容器运行的那一刻起就发生了。这种缓存可能会受到配置的限制,但是我们的结果来自于一个无限制的缓存设置。

TigerGraph 和 PostgreSQL 的内存保持不变(因为它们的内存上限和下限在 MiB 差异范围内),因为这两个数据库的大部分是用 C 或 C++编写的,这需要手动管理内存。值得注意的是,虽然 JanusGraph 使用大量内存,但还有其他遵循 Apache TinkerPop 标准的图形数据库变体,它们声称在内存方面更有效,如 Neo4j 和 OrientDB。Neo4j 和 OrientDB 的内存消耗也是可配置的,但由于 JVM 的原因,可能仍然会使用多个 GiB 的内存。

美国宇航局在 Unsplash 拍摄的照片

结论

在本文中,我们分析和比较了三种数据库技术在处理互联时空数据方面的响应时间。比较的技术是两种开源数据库技术 PostgreSQL 和 JanusGraph,以及一种企业级技术 TigerGraph。结果清楚地显示了关系模型的线性增长,而图形数据库解决方案的水平扩展更大。这主要是因为在查询大量数据时,NoSQL 数据库的可伸缩性比传统的关系模型有所提高。通过采用一组时空查询来评估这三个系统,这些时空查询类似于在分析 Yelp 挑战数据集和救护车模拟数据集等数据集中的数据时在真实世界场景中会发现的那些时空查询。

特别地,我们的结果证明,对于时空数据,在我们实验中使用的所有内核中,图数据库技术都优于 PostgreSQL。这个结果部分是由于内核由于数据的互连性质而产生复杂的查询。与关系实现产生的多连接样式的查询相比,该数据集产生了密集的图形,图形数据库能够在其上执行有效的遍历。时空多维方面在所有数据库中都得到了很好的支持,这从具有这种性质的约束的查询的响应时间可以明显看出。

这是我与布林克·范德梅尔韦和沃尔夫·蒂洛·巴尔克合写的论文的一个更简洁的版本。在 MDPI 可以免费找到完整的参考文献列表和数据库查询。

如果你有兴趣看我的其他作品,那就看看我的个人页面。同样,有网页可以找到更多关于我的合著者布林克沃尔夫-蒂洛的信息。

如果您需要工具来清理 Yelp 数据集或开始使用 TigerGraph 或 Neo4j 的 Yelp 数据集,请查看以下存储库:

9 使用 LDA 和主题建模的冠状病毒研究趋势

原文:https://towardsdatascience.com/summarising-the-latest-research-on-coronavirus-with-nlp-and-topic-modelling-28b867ad9860?source=collection_archive---------18-----------------------

受到所有公开的新冠肺炎印刷前研究的启发,我想应用一些数据科学技能,看看是否有任何趋势正在出现。有一些惊喜。

正如目前正在蔓延的冠状病毒疫情一样可怕,观察世界各地的学术和研究团体如何迅速开始了解这种病毒及其潜在影响是令人着迷的。

冠状病毒主题造型封面图片。作者插图

正因为如此,许多有趣的预印本学术论文迅速问世。我鼓励你谨慎阅读预印本,因为所做的声明未经证实,但我想看看这些论文讨论的主题和结论中是否有任何可辨别的模式。

因此,我根据来自Elsevier Novel Coronavirus Information Center的列表手动抓取了这些预印论文的结果和见解部分,并使用流行的 Gensim 库使用潜在狄利克雷分配(LDA)做了一些主题建模。如果你想亲自尝试,我会在这篇文章的底部附上 GitHub 链接。

模型困惑和主题一致性提供了一个方便的方法来判断一个给定的主题模型有多好。鸣谢:作者截图

在对 75 个预印件的样本大小训练多个 LDA 模型之后,32 个主题看起来是最佳的(可能 20 个主题是 ok ),一致性值为 0.54。然后,我选择了最突出和最令人兴奋的主题关键词集群,推断出中心观点,并为每个关键词找到最具代表性的文章。

这篇文章绝不是科学评论,而是我想分享的一个小实验。也许我们可以使用这样的工具更快地从多个来源识别模式,并促进合作。

结果。作者插图

9 个突出的冠状病毒课题及其最具代表性的论文

1.CT 扫描似乎有希望筛查新冠肺炎

关键词:肺炎,确认,证据,致死率,北京,焦点,大,预测,努力,传播

断层扫描。作者插图

尽管该病毒已被证明具有高度传染性,并可自发引起双肺感染,但临床证据显示,武汉病毒性肺炎的病死率较低。CT 成像在武汉病毒性肺炎的筛查、诊断、隔离方案、治疗、管理或预后中起着至关重要的作用。

最具代表性论文: 武汉病毒性肺炎的临床和影像学证据:一项大规模前瞻性队列研究

带有主题的文档百分比: 8%

2.利用人工智能筛查新冠肺炎患者

关键词:临床,诊断,显著,高度,特征,症状,目的,指标,嗜酸性粒细胞,入院

机器人。作者插图

使用人工智能技术来筛选患者的属性,如白细胞,嗜酸性粒细胞计数,嗜酸性粒细胞比率,2019 新型冠状病毒 RNA (2019n-CoV)和淀粉样蛋白-A。该团队开发了一种更快的方法来实现新冠肺炎诊断,提高了临床使用的确诊率。

最具代表性论文: 人工智能在新冠肺炎诊断预测中的应用

具有主题的文档百分比: 7%

3.各国尚未为 2019 年做好准备

关键词:预防,健康,能力,有效,应急,管理,加强,支持,准备,存在

地球仪。作者插图

各国在预防、发现和控制疫情的能力方面差异很大,这是因为全球卫生系统管理突发卫生事件的能力存在差异。我们需要加强全球准备,以遏制现有的疫情,包括正在进行的 2019-nCoV 国际传播。

最具代表性的论文: 根据 2019-nCoV 爆发回顾卫生安全能力——加强 IHR (2005)实施的机会

主题为的文档百分比为 7%

4.医务人员失眠、心理问题与新冠肺炎

关键词:心理,因素,发现,疾病,社交,隔离,员工,认同,抑郁,停留

医护人员失眠。作者插图

一项研究发现,在新冠肺炎疫情爆发期间,超过三分之一的医务人员患有失眠症。相关因素包括受教育程度、隔离环境、对新冠肺炎疫情的社会心理担忧和医生职业。考虑到不同的社会心理因素,需要对医务人员的失眠进行干预。

最具代表性的论文: 参与 2019 年新型冠状病毒疾病爆发的医务人员失眠及相关社会心理因素调查

带有主题的文档百分比: 7%

5.是否应该用强有力的预防措施来控制疫情?

关键词:衡量,预防,城市,强势,严格,个体,期望,维持,揭露,停止

孤立。作者插图

鼓励采取强有力的预防措施,直到冠状病毒疫情结束。国内其他地方和海外已经确认感染者应该以中国为榜样,立即采取强有力的干预措施。早期强有力的预防措施可以有效地阻止全球其他城市独立、自我持续的疫情爆发。

最具代表性的论文: 通过 EIR 模型模拟不同政策下 2019-nCov 的感染人群和传播趋势

具有主题的文档百分比: 7%

6.新的新冠肺炎快速基因诊断测试被发现

关键词:检测、pcr、样本、rt、lamp、诊断、反向、核酸、拭子、筛查

看核苷酸。作者插图

定量逆转录 PCR (qRT-PCR)是目前新冠肺炎检测的标准;然而,逆转录环介导等温扩增(RT-LAMP)可能允许在风险点进行更快、更便宜的现场检测。这项研究的目的是开发一种可以在 30 分钟内完成的快速筛查诊断测试。

最具代表性的论文: 逆转录-环介导等温扩增快速检测新型冠状病毒(covid 19)

主题为的文档百分比:5%

7.快速区分新冠肺炎病毒和其他感染

关键词:低,病人,酸,发热,肺,混浊,地面,过程,特征,图像

伪装的冠状病毒。作者插图

很少有人知道发热门诊中新冠肺炎和核酸阴性患者的不同临床特征。在肌肉疼痛的患者中观察到 2019-nCoV 感染的核酸检出率最高,其次是呼吸困难。发热、嗜酸性粒细胞减少和双侧肺毛玻璃样阴影的成像特征的结合可能是 2019-nCoV 感染的一个有价值的指标。

最具代表性的论文:2019 年门诊患者 nCoV 感染及临床表现分析:来自中国武汉发热门诊的流行病学研究

具有主题的文档百分比: 5%

8.谁最有可能感染新冠肺炎病毒?

关键词:病人,症状,系统,政府,人民,年龄,人,显著,改善,肾

确定谁处于危险中。作者插图

调查证实,人群的传染性没有明显的年龄限制,但老年人仍然是弱势群体。糖尿病患者更有可能发展成重症患者,入住 ICU 的概率也显著增加。

最具代表性论文: 中国重庆地区 197 例感染 2019 新型冠状病毒患者的流行病学和临床特征:单中心描述性研究

具有主题的文档百分比: 4%

9.重度新冠肺炎的治疗

关键词:重症,呼吸系统,治疗,急性,方法,综合征,相似,级别,起源,发生

国际电联。作者插图

新冠肺炎感染导致严重的呼吸系统疾病,类似于严重急性呼吸综合征冠状病毒,并与 ICU 入院和高死亡率有关。我们对该病的起源、流行病学、治疗方法等方面进行了研究,根据武汉协和医院制定的治疗方案,经国家卫生部认证,希望能制定出有效的治疗方法,降低该病的死亡率。

最具代表性论文: 中国石首新冠肺炎感染者的临床特征及治疗

主题为的文档百分比为 4%

结论

我喜欢这个周末项目——这是我第一次尝试将一些 NLP 技巧应用到一个问题上。我知道有人会发现我的方法有问题(请联系我),但这个想法很有趣。我想这就像是另一种形式的总结,我玩得越多,我就越思考医学和学术研究的可能性。

文字,文字无处不在。作者插图

也许是某种葡萄酒社交,我们根据聚集的主题关键词邀请学术作者,并根据主题交叉百分比进行某种人员匹配。我最好就此打住,免得我再免费给出任何奇思妙想。欢迎反馈!

完整免责声明:我是爱思唯尔的产品经理。这篇博客文章和分析是作者自己的创作,不代表爱思唯尔的想法和观点。

GitHub 回购

使用 python 脚本的 GitHub Repo 输入数据和输出:https://GitHub . com/raudashl/coronvavirus _ preprint _ research _ NLP

想要更多吗?

上述文章的 5 月更新版

[## 使用 NLP 的冠状病毒研究主题:2020 年 5 月

当你意识到在如此短的时间内发生了如此多的学术工作时,这是令人难以置信的。在这里,我潜入一些 LDA…

towardsdatascience.com](/top-coronavirus-research-topics-using-nlp-may-2020-b4166289b728)

如果你喜欢这篇文章,一定要看看我在 2020 年 2 月初制作的关于冠状病毒的漫画。

[## 冠状病毒爆发至今,为什么它如此令人担忧[漫画]

冠状病毒爆发在过去几周占据了头条。我越来越担心…

medium.co](https://medium.com/@raudaschl_32859/the-coronavirus-outbreak-so-far-and-why-its-so-concerning-comic-cd83d445f105)

文献学

多亏了伯特,总结已经商品化了

原文:https://towardsdatascience.com/summarization-has-gotten-commoditized-thanks-to-bert-9bb73f2d6922?source=collection_archive---------8-----------------------

照片由 Aaron BurdenUnsplash

你曾经不得不把一份冗长的文件总结成要点吗?或者为文档提供执行摘要?如你所知,对我们人类来说,这个过程是冗长而缓慢的——我们需要阅读整个文档,然后关注重要的句子,最后,将句子改写成一个连贯的摘要。

这就是自动总结可以帮助我们的地方。机器学习在总结方面已经走了很长的路,但仍有很大的发展空间。通常,机器摘要分为两种类型—

提取摘要:提取原始文档中出现的重要句子。

摘录摘要的类比

抽象概括:概括文档中包含的重要观点或事实,不逐字重复。当人们被要求总结一份文件时,这就是我们通常想到的。

抽象概括的类比

我想向大家展示一下最近使用 BERT_Sum_Abs 进行抽象摘要的一些结果,这是刘洋和米雷拉·拉帕塔在使用预训练编码器进行文本摘要中描述的最先进的自然语言处理摘要模型。

抽象 BERT 摘要性能

摘要的目的是将一个文档压缩成一个较短的版本,同时保留其大部分含义。抽象摘要任务需要语言生成能力来创建包含源文档中没有的新单词和短语的摘要。摘要通常被定义为二进制分类任务,其标签指示一个文本范围(通常是一个句子)是否应该包括在摘要中。

下面是 BERT_Sum_Abs 在标准摘要数据集上的表现: CNNDaily Mail 这些都是基准中常用的。评估指标被称为 ROGUE F1 得分—

基于刘洋和米雷拉·拉帕塔的带预训练编码器的文本摘要

结果显示 BERT_Sum_Abs 优于大多数非基于变压器的模型。更好的是,该模型背后的代码是开源的,并且可以在 Github 上实现。

演示和代码

让我们看一个用 BERT_Sum_Abs 总结文章的例子。我们将选择下面的故事来总结— 美联储官员表示,各国央行行长在应对冠状病毒方面步调一致。这是全文——

The Federal Reserve Bank of New York president, John C. Williams, made clear on Thursday evening that officials viewed the emergency rate cut they approved earlier this week as part of an international push to cushion the economy as the coronavirus threatens global growth.Mr. Williams, one of the Fed’s three key leaders, spoke in New York two days after the Fed slashed borrowing costs by half a point in its first emergency move since the depths of the 2008 financial crisis. The move came shortly after a call between finance ministers and central bankers from the Group of 7, which also includes Britain, Canada, France, Germany, Italy and Japan.“Tuesday’s phone call between G7 finance ministers and central bank governors, the subsequent statement, and policy actions by central banks are clear indications of the close alignment at the international level,” Mr. Williams said in a speech to the Foreign Policy Association.Rate cuts followed in Canada, Asia and the Middle East on Wednesday. The Bank of Japan and European Central Bank — which already have interest rates set below zero — have yet to further cut borrowing costs, but they have pledged to support their economies.Mr. Williams’s statement is significant, in part because global policymakers were criticized for failing to satisfy market expectations for a coordinated rate cut among major economies. Stock prices temporarily rallied after the Fed’s announcement, but quickly sank again.Central banks face challenges in offsetting the economic shock of the coronavirus.Many were already working hard to stoke stronger economic growth, so they have limited room for further action. That makes the kind of carefully orchestrated, lock step rate cut central banks undertook in October 2008 all but impossible.Interest rate cuts can also do little to soften the near-term hit from the virus, which is forcing the closure of offices and worker quarantines and delaying shipments of goods as infections spread across the globe.“It’s up to individual countries, individual fiscal policies and individual central banks to do what they were going to do,” Fed Chair Jerome H. Powell said after the cut, noting that different nations had “different situations.”Mr. Williams reiterated Mr. Powell’s pledge that the Fed would continue monitoring risks in the “weeks and months” ahead. Economists widely expect another quarter-point rate cut at the Fed’s March 18 meeting.The New York Fed president, whose reserve bank is partly responsible for ensuring financial markets are functioning properly, also promised that the Fed stood ready to act as needed to make sure that everything is working smoothly.Since September, when an obscure but crucial corner of money markets experienced unusual volatility, the Fed has been temporarily intervening in the market to keep it calm. The goal is to keep cash flowing in the market for overnight and short-term loans between banks and other financial institutions. The central bank has also been buying short-term government debt.“We remain flexible and ready to make adjustments to our operations as needed to ensure that monetary policy is effectively implemented and transmitted to financial markets and the broader economy,” Mr. Williams said Thursday.

开始之前,我们需要获取模型代码,安装依赖项并下载数据集,如下所示,您可以在自己的 Linux 机器上轻松执行这些操作:

开始总结的 Linux 命令

按照上面的代码,我们现在执行下面显示的 python 命令来汇总 /dataset2 目录中的文档:

python run_summarization.py \
    --documents_dir bertabs/dataset2 \
    --summaries_output_dir bertabs/summaries_out \
    --batch_size 64 \
    --min_length 50 \
    --max_length 200 \
    --beam_size 5 \
    --alpha 0.95 \
    --block_trigram true \
    --compute_rouge true

这里的参数如下—

documents_dir要汇总的文档所在的文件夹
summaries _ output _ dir要写入摘要的文件夹。默认为文件夹,文件为
Batch _ sizeBatch size per GPU/CPU for training
beam _ size每个示例开始的波束数
block _ trigram是否阻止波束搜索
Compute _ ROUGE仅适用于 CNN/DailyMail 数据集
alpha波束搜索中长度罚分的 alpha 值(值越大罚分越大)
min _ length摘要的最小令牌数
max _ length摘要的最大令牌数

一旦 BERT_Sum_Abs 完成了这篇文章,我们就获得了以下摘要:

The Fed slashed borrowing costs by half a point in its first emergency move since the depths of the 2008 financial crisis. Rate cuts followed in Canada, Asia and the Middle East on Wednesday. The Bank of Japan and European Central Bank have yet to further cut borrowing costs, but they have pledged to support their economies.

总结的另一个例子研究表明,低碳水化合物饮食可以预防、逆转大脑中与年龄相关的影响得出以下总结:

The research team focused on the Presymptomatic period during which prevention may be most effective. They showed that communication between brain regions destabilizes with age, typically in the late 40's, and that destabilization associated with poorer cognition. The good news is that we may be able to prevent or reverse these effects with diet, mitigating the impact of encroaching Hypometabolism by exchanging glucose for ketones as fuel for neurons.

结论

如你所见,BERT 正在渗透到 NLP 的各个方面。这意味着我们看到 NLP 的性能每天都在接近人类的水平同时还是开源的。

NLP 的巨大商品化正在到来,每一个新的 NLP 模型不仅建立了新的基准记录,而且任何人都可以使用。就像 10 年前 OCR 技术变得商品化一样,NLP 在未来几年也将如此。随着 NLP 的商品化,许多较小的参与者正在被打乱,因为他们在 NLP 技术 R&D 的护城河在他们眼前蒸发了。

NLP 的这种商品化应该引导人工智能公司转移重点,进入特定的垂直领域,建立解决领域痛点的护城河,而不是将 NLP 技术作为核心价值主张。具体来说,在这里您可以看到技术已经商品化的摘要,因为新的研究成果很快被实现为开源代码,同时超过了以前的基准。

基于 BART 模型的 COVID 研究论文综述

原文:https://towardsdatascience.com/summarization-of-covid-research-papers-using-bart-model-5b109a6669a6?source=collection_archive---------19-----------------------

用数据做酷事!

免费股票照片

介绍

与艾伦·艾、白宫和其他几个机构合作,Kaggle 已经开源了新冠肺炎开放研究数据集(CORD-19) 。CORD-19 是超过 52,000 篇学术文章的资源,包括超过 41,000 篇关于新冠肺炎、新型冠状病毒和相关冠状病毒的全文。这个免费提供的数据集提供给全球研究界,以应用自然语言处理和其他人工智能技术的最新进展,产生新的见解,支持正在进行的抗击这种传染病的斗争。由于新型冠状病毒文献的快速增长,使得医学研究界难以跟上,因此对这些方法的需求越来越迫切。

深度学习分析,我们一直在花时间,在这个数据集上尝试不同的 NLP 技术。在这篇博客中,我们展示了如何使用基于前沿变压器的摘要模型来总结与新冠肺炎相关的研究论文。这对于快速浏览研究论文或其部分内容非常有用,可以帮助你决定是否要完整阅读。请注意,我不是健康专家,本文的观点不应被解释为专业建议。

我们非常热衷于使用数据科学和机器学习来解决问题。如果您是一家医疗服务公司,并且正在寻找数据科学帮助来应对这场危机,请通过此处的联系我们。原文全文发表在我们的网站这里。

什么是总结?

根据维基百科,摘要是通过计算缩短一组数据的过程,以创建代表原始内容中最重要或最相关信息的子集摘要。摘要可以应用于多种数据类型,如文本、图像或视频。摘要已经被用于许多实际应用——摘要文章、摘要同一主题的多个文档、摘要视频内容以生成体育比赛中的精彩场面等。

具体来说,文本摘要非常有用,因为它使用户不必阅读长篇文章、博客或其他文本。可以有不同类型的总结,如下图所示,这是从这个博客借用的。

摘要的类型(来源:https://medium . com/jatana/unsupervised-text-summary-using-sentence-embedding-ADB 15 ce 83 db 1)

有多种类型的总结——基于输入类型,基于期望的输出或目的。摘要的输入可以是单个或多个文档。多文档摘要是一个更具挑战性的任务,但最近有一些有前途的研究。

总结任务可以是抽象的,也可以是提取的。摘要通过选择现有文本的子集来创建摘要。摘要类似于高亮显示。抽象概括包括理解文本和重写文本。你也可以在我的博客这里阅读更多关于总结的内容。

使用变形金刚的新闻摘要

我们将利用 huggingface 的变形金刚库对科学文章进行总结。这个库实现了不同的算法。

在这篇博客中,我们将使用 BART 算法。 BART 是一款去噪自动编码器,用于预处理序列间模型。正如他们在论文中所描述的,BART 是通过(1)用任意噪声函数破坏文本,以及(2)学习一个模型来重建原始文本来训练的。因此,BART 在抽象对话、问题回答和总结等多项任务上表现出色。具体来说,对于总结,增益高达 6 胭脂分数。

BART 架构(来源:https://sshleifer . github . io/blog _ v2/jupyter/2020/03/12/BART . html)

让我们测试一下 Huggingface 支持的 BART transformer 模型。该模型在 CNN/Daily Mail 数据集上进行训练,该数据集是用于摘要工作的标准数据集。数据集由新闻文章和人类撰写的摘要组成。在我们在研究论文上运行这个模型之前,让我们在一篇新闻文章上运行这个模型。以下代码片段可用于生成新闻文章的摘要

from transformers import pipelinesummarizer = pipeline(“summarization”)

测试摘要的新闻文章—来自https://hugging face . co/transformers/usage . html #摘要的示例

print(summarizer(ARTICLE, max_length=130, min_length=30))

运行 summary 命令会生成如下摘要。

莉安娜·巴里恩托斯已经结了 10 次婚,有时是在两个星期之内。检察官称这些婚姻是移民骗局的一部分。周五,她在布朗克斯的州最高法院表示无罪。

在我看来,这是一篇非常好的新闻摘要。可以调整 max_length 参数以获得更长的摘要。

新冠肺炎研究论文综述

全球许多科学家和研究人员正致力于更多地了解该病毒,以开发有效的治疗方法,包括疫苗或药物,以降低攻击的严重程度。我们关于这个话题的知识不断增加。如果人工智能能够第一次通读研究并提供良好的总结,它可以帮助人类有效地优先考虑他们的时间。然而,总结往往是一项困难且主观的任务。要真正总结人工智能需要理解的内容,这是很困难的,因为研究人员的写作风格差异很大。在这篇博客中,我们评估了 BART Transformer 模型在总结新冠肺炎论文内容方面的表现。

为了获得 CORD-19 研究论文的清晰数据集,我们将在这里使用来自的 dataframe biorxiv_clean.csv。非常感谢 xhulu 在 Kaggle 上创造了这个。

让我们开始总结研究论文吧!

## Read the data frame
import pandas as pd
data = pd.read_csv('biorxiv_clean.csv')

一旦我们读取了数据帧,数据看起来就像这样:

清洁新冠肺炎开放研究数据集

我们的主要栏目有论文 id、标题、摘要、作者、正文、参考书目等。

然后,我们将遍历数据帧并生成摘要。正如我们所看到的,“文本”列在数据帧中有科学文本。

from transformers import pipelinesummarizer = pipeline(“summarization”)for i, text in enumerate(data): print(summarizer(data[‘text’].iloc[i], max_length=1000,   min_length=30))

您可以试验最小和最大长度参数。我们选择上述值,因为它提供了最佳结果。

新冠肺炎研究总结结果

这些总结的一些例子是:

正文:

https://www.mdpi.com/2076-0817/9/2/107

BART 变压器生成的汇总:

类圆线虫病是一种流行于热带和亚热带地区的蠕虫感染。然而,流动人口的患病率数据很少。这项研究评估了在西班牙六家医院就诊的人群中这种感染的患病率。流行率约为 9%,非洲和拉丁美洲高于其他地区。此外,免疫系统受损患者的患病率低于未遭受免疫抑制的患者。

正文:

https://www.biorxiv.org/content/10.1101/2020.02.22.961268v1

BART 变压器生成的汇总:

转录聚合酶链式反应(RT-PCR)是用于分析和定量各种致病 RNA 的标准和常规使用的技术。新冠肺炎疫情爆发后,报道了几种检测新型冠状病毒基因组 RNA 的方法和试剂盒。传统方法耗费大量操作人员,但诊断效率低,交叉感染风险高。基于磁性纳米粒子(MNPs)的提取方法无需离心机,已被证明易于操作且与自动化兼容。

观察:

总体而言,我认为基于 CNN/Daily Mail 数据训练的 BART 模型表现不一。它确实提供了事实上正确的连贯摘要,但如果将该摘要与论文摘要进行比较,我们会发现一些差距:

  • 它可能会遗漏一些关键方法或其他相关元数据,而研究人员可能希望将其作为摘要的一部分。
  • 摘要往往比论文的摘要更短,结论也更弱
  • BART 模型中使用的嵌入是在常规英语词汇上训练的,可能不能正确理解这里的科学术语

为了应对这些挑战,最好的方法是对从上述数据框架中提取的文本和摘要的 BART 模型进行微调。我们已经开始这样做了,但是由于训练一个好的摘要模型需要大量的计算,所以我们无法继续向前。

结论

在这篇文章中,我们看到预训练的 BART 模型可以用来从新冠肺炎研究论文中提取摘要。由于科学术语和不同研究者不同的写作风格,研究论文摘要是一项困难的任务。BART 模型在生成论文摘要方面做得相当好。然而,它的局限性在于它可能无法涵盖所有的要点。

超负荷相似性度量计算

原文:https://towardsdatascience.com/super-charged-similarity-metric-calculations-969116abd948?source=collection_archive---------17-----------------------

采用 NumPy 和 TensorFlow

乔·内里克在 Unsplash 上的照片

相似性检测是一种常用的方法,用于识别具有共同特征但不一定具有相同特征的项目。产品推荐和相关文章通常由相似性度量驱动。余弦相似性是最受欢迎的,将在这里讨论。本文将使用 NumPy 和 TensorFlow 评估 Python 中余弦相似性的性能。

NumPy 和张量流

NumPy 是一个健壮而成熟的库,用于处理大型多维矩阵。NumPy 拥有丰富的线性代数函数集合。调得很好,在 CPU 上运行速度非常快。

TensorFlow 是一个数学和机器学习库,可以利用 CPU 和 GPU。TensorFlow 已经在生产中得到很好的证明,并用于支持高级机器学习算法。它还拥有丰富的线性代数函数集合。你用 NumPy 能做的大部分事情,在 TensorFlow 里也能做。

两者都是很棒的库,都可以计算数据集之间的相似性度量。

计算余弦相似度

如果 NumPy 和 TensorFlow 尚未安装,可以通过 pip 安装。本文使用的是 NumPy 1.17.4 和 TensorFlow 2.1

pip install numpy
pip install tensorflow

以下示例代码显示了如何在 NumPy 和 TensorFlow 中计算余弦相似性。

NumPy 和张量流余弦相似性

运行上面的代码将产生类似下面的输出。还会有很多 TensorFlow 消息,重要的是你要看到顶行是粗体的,以确保 GPU 正在被使用。

**I tensorflow/core/common_runtime/gpu/gpu_device.cc:1555] Found device 0 with properties:**x: 
 [[0.16522373 0.55317429 0.61327354 0.74017118 0.54443702]
 [0.46154321 0.17925365 0.3785271  0.71921798 0.91126758]
 [0.10342192 0.96612358 0.06434406 0.85482426 0.7329657 ]
 [0.1333734  0.99817565 0.42731489 0.46437847 0.40758545]
 [0.43727089 0.91457894 0.21971166 0.24664127 0.61568784]]
y: 
 [[0.15979143 0.47441621 0.20148356 0.99541121 0.41767036]]np: 
 [[0.91509268]
 [0.83738509]
 [0.91553484]
 [0.80027872]
 [0.7071257 ]]
tf: 
 [[0.91509268]
 [0.83738509]
 [0.91553484]
 [0.80027872]
 [0.7071257 ]]

最上面的两个数组显示了 x 的 5x5 数组和 y 的 1x5 数组。它还显示了 y 相对于 x 中每一行的余弦相似性,这是用 NumPy 和 TensorFlow 计算的。

让我们试着用更多的数据来计算时间。

小型阵列的性能

对于第一个测试,我们将尝试两个小数组,计算 x 的 1000x25 数组和 y 的 50x25 数组之间的余弦相似性。

小型数据阵列的时序

运行上面的代码将产生以下输出:

np time = 0.2509448528289795
tf time = 0.7871346473693848
similarity output equal: True

在这种情况下,NumPy 比 TensorFlow 快,即使 TensorFlow 启用了 GPU。与所有软件开发一样,没有一种尺寸可以满足所有问题的答案。NumPy 仍然有一席之地,它在处理小数据时会表现得更好。

将数据从 CPU 复制到 GPU 会产生开销,构建要执行的 GPU 图形也会产生开销。随着数据的增长,开销与总体运行时间相比可以忽略不计,让我们尝试更大的数据阵列。

大型阵列的性能

我们将运行与上面几乎完全相同的代码,除了我们将增加数组的大小。

x = np.random.rand(10000, 25)
y = np.random.rand(50, 25)

对于这个测试,我们将对 x 使用 10000x25 数组,对 y 使用 50x25 数组。

np time = 3.3217058181762695
tf time = 1.129739761352539
similarity output equal: True

TensorFlow 现在比 NumPy 快 3 倍。将数据复制到 GPU 并编译 GPU 图形的开销现在值得在性能上进行权衡。

让我们尝试一个更大的数组。

x = np.random.rand(25000, 100)
y = np.random.rand(50, 100)

对于这个测试,我们将对 x 使用 25000x25 的数组,对 y 使用 50x100 的数组。

np time = 23.823707103729248
tf time = 2.93641996383667
similarity output equal: True

在这种情况下,TensorFlow 快了 8 倍。只要数据集能够适合 GPU,性能增益将继续快速增长。

选择前 N 个索引

计算余弦相似度将得到一个从 0 到 1 的浮点数组,1 表示最相似,0 表示最不相似。对于大多数用例,您需要计算相似性以及最佳关联记录。在 NumPy 和 TensorFlow 中都可以这样做,如下所示。

余弦相似度和最佳匹配选择

上面的代码获得了一个按照最高余弦相似度排序的索引列表。选择并打印最上面的记录。

结论

NumPy 和 TensorFlow 都有自己的位置。GPU 不只是在所有情况下都让一切变得更快。对较小的数据集使用 NumPy,对较大的数据集使用 TensorFlow。始终根据您自己的数据进行测试,看看在您的特定情况下什么最有效。

仅使用 PyTorch 的超收敛

原文:https://towardsdatascience.com/super-convergence-with-just-pytorch-c223c0fc1e51?source=collection_archive---------30-----------------------

使用内置 PyTorch 函数和类减少训练时间同时提高效果的指南

为什么?

当创建 Snaked,我的蛇分类模型时,我需要找到一种方法来改善结果。超级收敛只是一种更快训练模型同时获得更好结果的方法!然而,我发现没有关于如何使用内置 PyTorch 调度程序的指南。

封面图片来源于此处

学习理论

在你阅读这篇文章之前,你可能想知道什么是超级收敛,以及它是如何工作的。总的要点是在开始时尽可能提高学习速度,然后以循环的速度逐渐降低学习速度。这是因为较大的学习率训练得更快,而导致损失发散。我在这里的重点是 PyTorch,所以我自己不会做任何进一步的解释。

以下是可供深入研究的资源列表:

进口

import torch
from torchvision import datasets, models, transforms
from torch.utils.data import DataLoader

from torch import nn, optim
from torch_lr_finder import LRFinder

设置超参数

设置变换

transforms = transforms.Compose([
transforms.RandomResizedCrop(size=256, scale=(0.8, 1)),
    transforms.RandomRotation(90),
    transforms.ColorJitter(),
    transforms.RandomHorizontalFlip(),
    transforms.RandomVerticalFlip(),
    transforms.CenterCrop(size=224), 
    transforms.ToTensor(),
    transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)), 
])

加载数据、模型和基本超参数

train_loader = DataLoader(datasets.CIFAR10(root="train_data", train=True, download=True, transform=transforms))
test_loader = DataLoader(datasets.CIFAR10(root="test_data", train=False, download=True, transform=transforms))

model = models.mobilenet_v2(pretrained=True)

criterion = nn.CrossEntropyLoss()
optimizer = optim.AdamW(model.parameters())

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)

Note that doing this requires a seperate library from [here](https://github.com/davidtvs/pytorch-lr-finder).

```python
lr_finder = LRFinder(model, optimizer, criterion, device)
lr_finder.range_test(train_loader, end_lr=10, num_iter=1000)
lr_finder.plot()
plt.savefig("LRvsLoss.png")
plt.close()HBox(children=(FloatProgress(value=0.0, max=1000.0), HTML(value='')))

Stopping early, the loss has diverged
Learning rate search finished. See the graph with {finder_name}.plot()

创建计划程序

使用单周期学习率调度程序(用于超收敛)。

请注意,调度程序使用图表中的最大学习率。要选择向下寻找最大梯度(斜率)。

必须在中输入训练的周期数和每个周期的步数。通常的做法是使用批量大小作为每个时期的步骤。

scheduler = optim.lr_scheduler.OneCycleLR(optimizer, 2e-3, epochs=50, steps_per_epoch=len(train_loader))

火车模型

训练模型 50 个纪元。每个时期后打印统计数据(损失和准确性)。

不同的调度程序应该在不同的代码中调用。将调度器放在错误的位置会导致错误,所以使用单周期策略时,要确保在每个批处理之后直接调用 step 方法。

best_acc = 0
epoch_no_change = 0

for epoch in range(0, 50):
    print(f"Epoch {epoch}/49".format())

    for phase in ["train", "validation"]:
        running_loss = 0.0
        running_corrects = 0

        if phase == "train":
            model.train()
        else: model.eval()

        for (inputs, labels) in train_loader:

            inputs, labels = inputs.to(device), labels.to(device)

            optimizer.zero_grad()

            with torch.set_grad_enabled(phase == "train"):

                outputs = model(inputs)
                _, preds = torch.max(outputs, 1)
                loss = criterion(outputs, labels)

                if phase == "train":

                    loss.backward()
                    optimizer.step()

                    scheduler.step()

            running_loss += loss.item() * inputs.size(0)
            running_corrects += torch.sum(preds == labels.data)

        epoch_loss = running_loss / len(self.data_loaders[phase].sampler)
        epoch_acc = running_corrects.double() / len(self.data_loaders[phase].sampler)
        print("\nPhase: {}, Loss: {:.4f}, Acc: {:.4f}".format(phase, epoch_loss, epoch_acc))

        if phase == "validation" and epoch_acc > best_acc:
            epoch_no_change += 1

            if epoch_no_change > 5:
                break

感谢阅读!

我希望这足够简单,可以相对快速地理解。当我第一次实现超级收敛时,我花了很长时间才弄明白如何使用调度程序(我找不到任何利用它的代码)。如果你喜欢这篇博文,考虑看看其他方法来改进你的模型。如果你想看看超级收敛在实际项目中是如何使用的,只需看看我的蛇分类项目就行了。

超级简单的文本分类句子向量与姐妹(库)

原文:https://towardsdatascience.com/super-easy-text-classification-by-sentence-vector-with-sister-library-843eabf962ae?source=collection_archive---------39-----------------------

照片由阿尔方斯·莫拉莱斯Unsplash 拍摄

之前的帖子中,我介绍了一个我写的库——姐姐,它可以很容易地将一个句子转换成一个向量。我们看到了用很少的代码就能做到这一点是多么简单。

然而,获得一个向量只是创建一个 ML 增强应用程序的第一步,我们需要在它上面放一个模型来做一些很酷的事情。

在本帖中,我们将通过几个简单的步骤,利用句子向量创建文本分类。

为了向您展示这样做有多简单,我将把整个代码放在前面。

就这些了。包括空行,也就 27 行!!!

这个程序主要做四件事。

  1. 加载数据集。
  2. 将每个句子转换成一个向量。
  3. 训练一个模特。
  4. 评估。

让我一步一步地解释它们

加载数据集

主函数中的前几行,

train = datasets.Imdb("train")test = datasets.Imdb("test")train_texts, train_labels = zip(*train.all())test_texts, test_labels = zip(*test.all())

正在加载一个著名的文本分类数据集,IMDb 数据集。这个数据集由电影评论和相应的情感标签组成。它有一个正面的标签—如果评论是正面的,则为 1。这意味着数据集中的所有样本都属于两个类中的一个,因此这是一个二元分类问题。

为了加载数据集,我使用了一个轻量级的 NLP 数据加载器库 LineFlow 。要了解更多这方面的信息,我建议你参考开发者写的一篇中型文章

将句子转换成向量

现在酷的部分,通过使用姐妹,我们将获得电影评论的数字表示。

sentence_embedding = sister.MeanEmbedding("en")train_x = np.array([sentence_embedding(t) for t in train_texts])test_x = np.array([sentence_embedding(t) for t in test_texts])

在第一行中,我们创建了一个类的实例,它获取一个句子,并将其中的单词转换成单词向量,最后是句子向量。想知道它是如何从一个单词向量序列中获取一个句子向量的,请参考我之前的文章

训练模特

现在,我们已经为构建 ML 模型准备好了句子。为此,我将使用机器学习库之王, scikit-learn 。通过使用这个,我们可以只用两行代码训练一个支持向量机

clf = SVC(kernel="linear")clf.fit(train_x, train_labels)

评价

最后,我们可以用测试数据来测试模型训练得有多好。

print(clf.score(test_x, test_labels))

通过使用 scikit-learn,这也可以非常简单地完成。在我的本地机器上,它的准确率超过 80%。这不是一个很好的结果,但却是一个很好的起点。

在本文中,我们看到了如何构建一个以句子向量作为输入的 SVM 文本分类模型,并且我们用不到 30 行代码就实现了它。

我将以整个程序的 GitHub 要点 T4 来结束这篇文章。

感谢您的阅读!

超级学习者对深度神经网络

原文:https://towardsdatascience.com/super-learner-versus-deep-neural-network-aa78547aabd7?source=collection_archive---------27-----------------------

“我从来没有输过。我要么赢,要么学”——纳尔逊·曼德拉

来源:https://linkites.com/

简介

深度学习在涉及预测建模和模式识别的任务中占据了突出的位置。深度学习通过其自动特征提取和前馈方法提供了提取低级特征的信心,以便在大数据应用中识别高级身份。然而,深度神经网络有缺点,包括许多超参数一起调整,在较小的数据集中收敛缓慢,以及解释为什么做出特定决定的问题。虽然传统的机器学习算法可以解决这些缺点,但它们通常无法达到深度神经网络所记录的性能水平。为了提高性能,集成方法用于组合多个基础学习器。

在这篇文章中,我们将探索超级学习者是否可以通过使用特定于任务的调整来提供比深度神经网络更高的性能。

目标

我将使用传统算法的组合,对照 深度神经网络 的多个参数,检查 深度超级学习器 的性能。我使用了银行营销数据来比较我的模型,使用的评分机制有 混淆矩阵、精确度和召回率、F1 分数、ROC-AUC 分数。

模型比较指标

深度神经网络综述

上图描绘了深度学习如何成为机器学习的子集,以及机器学习如何成为人工智能(AI)的子集,来源维基百科

深度学习是人工智能中机器学习的一个子领域,深度神经网络是深度学习的基础。他们处理受大脑生物结构和功能启发的算法,以帮助机器拥有类似人类的智能。

一个简单的前馈神经网络,完全连接的神经元模仿大脑中的神经元。这些神经元根据收到的输入向其他神经元传递消息或信号,并形成一个复杂的网络,通过某种反馈机制进行学习。

多层网络中的每个神经元从输入中提取一个特定的特征,并学习从中唯一地识别项目,使其具有像人类一样的学习能力。

维基百科页面显示了如何在深度学习的多个抽象层上表示图像

我将使用简化构建神经网络的 Keras 库。下面的代码创建了一个顺序模型,指定我们添加的每一层的输出都是下一层的输入,依此类推。

我用“relu”作为 2 个隐藏层的激活,用“sigmoid”作为输出层的激活。每一层都有不同的输入维度/神经元集,顺序为 40–20–10–1。

什么是超级学习者?

正如我们在上面看到的,深度神经网络是一种强大的深度学习架构,它使用多层处理单元来学习前一层的输入并将其前馈,这使其能够识别更高级别的特征并简化实体/身份检测。然而,深度神经网络有缺点,包括许多超参数和无限架构,结果不透明,以及在较小的数据集上收敛相对较慢。

超级学习 通过将多个传统的机器学习算法堆叠成一个集合来解决这个问题,该集合可以找到不同学习算法的最佳组合。这是一种技术,我们将您可能调查的所有模型和配置组合起来,用于预测建模问题,并使用它们做出与您可能调查的任何单个模型一样好或更好的预测。

显示从“超级学习者”获取的超级学习者算法
的数据流的图表

如上所述,超级学习器将是堆叠或 k-fold 交叉验证的变体,其中各个模型将在 k-fold 数据分割上被训练,然后最终元模型将在其输出上被训练,也称为来自每个模型的非折叠预测。

现在让我来展示一下超级学习者的表现是如何与它所涉及的任何单一模型一样好甚至更好的。

我选择了不同的基础学习者进行预测分析

这里我们可以看到基于准确性和 ROC-AUC 曲线的单个模型的性能

我将使用 ML-Ensemble 库来训练超级学习者,它提供了一个模块化的、灵活的、高效内存的高性能集成学习者。关于超级学习者实现的深度可以在这里找到。

超级学习器的性能比使用任何一种传统的 ML 算法都更可靠。

用于比较的数据集

我在这里使用了 UCI 的银行营销数据。该数据与一家葡萄牙银行机构的直接营销活动(电话)相关。通常,需要同一个客户进行多次联系,以便了解产品(银行定期存款)是否认购(“是”/1)或不认购(“否”/0)。

数据集的快速探索性数据分析

我们得到了 7 个分类特征,5 个数字特征和 4 个布尔特征。我已经使用标签编码器通过将分类值转换成数字形式来标准化数据。

如下图所示,数据非常不平衡,因此我们需要在调整模型时实现类权重调整或数据采样技术。

6。DSL vs DNN 的正面碰撞

让我们开始吧,为了比较哪种算法在我们的银行营销数据上表现最好,我将根据诸如准确度、混淆度量、精确度、召回率、F-1 和 ROC-AUC 分数等指标来比较性能。

不准确性和 F1 分数深度超级学习者比深度神经网络略高

在不平衡数据集的情况下,准确性不能用作唯一的决策度量,因为根据这种数据训练的分类器可能会给你 98%准确性的惊人结果,但是当你进一步挖掘时,却发现 100 个样本中有 98 个样本属于正确分类的多数类,而属于少数类的 2 个样本被遗漏,使得分类器在实际情况下是多余的。因此,我将使用混淆度量和 ROC-AUC 分数来确保我们的分类器正确地对两个类别进行分类。

用于比较的混淆度量

尽管有高度不平衡的数据,两个分类器都表现得相对较好,没有偏向一个类别。然而,通过微调分类器和使用平衡数据,我们可以更好地改善上面看到的错误分类率。

精确召回曲线和 ROC 曲线的比较

与深度超级学习器相比,深度神经网络的精度-召回曲线似乎更平滑。然而,在迄今为止的分析中,深度超级学习者设法以微弱优势领先于深度神经网络。

我将使用数据集平衡做一个快速分析,看看深度神经网络是否能够弥合超级学习者所达到的差距。

随着平衡训练数据的引入,错误分类率显著下降,提高了超级学习器和神经网络的准确性。然而,在上述任务的大多数评估指标中,深度超级学习器优于深度神经网络,下面的性能统计数据清楚地证明了这一点。

7。结论

最终的结论是哪一个是最好的?

实际上,对于给定的预测问题和数据集,通常不可能事先知道学习者在哪个方面表现最好。——超级学习者 ,2007 年。

上面的例子证明了深度学习不能作为所有问题的最佳解决方案。它对小数据的无效性加上无法解释所做的决定,使得传统的机器学习算法在某些用例中略占上风。

我们目前拥有的最佳答案是使用实证实验来测试和发现最适合您的数据集的方法。

用 Python 抓取 BBC 新闻文章的超级简单方法

原文:https://towardsdatascience.com/super-simple-way-to-scrape-bbc-news-articles-in-python-5fe1e6ee82d9?source=collection_archive---------17-----------------------

用最少代码抓取网站的简短教程

嗨,我是彼得·🇮🇸

我在伦敦一家咨询公司担任数据科学家。这实际上意味着我为多家公司工作,从事不同的数据科学工作。

大多数情况下,我在云端构建机器学习解决方案。有时,通用数据解决方案、仪表盘或推荐数据科学最佳实践。不过,最近主要是 NLP 或计算机视觉。关于我已经说得够多了。

如果你对数据科学、机器学习或大数据感兴趣,那么你很有可能从一个网站上收集数据。

对于小型项目或概念验证(PoC ),手动完成就可以了。其他时候,这最好用代码来完成。这就是 Python 的闪光点,有很多开源库可以和各种网站交互。

知道如何使用任何刮库,是一个非常有用的技能。非常值得投资💰

秘密是很容易刮网站

我们将一起构建一个简单的 Python class来抓取 BBC

Ps:如果你只是为了最后的代码而打开这篇文章,请随意跳到结尾,那里都是布局好的。

照片由 Clément HUnsplash 上拍摄

漂亮的组合和设置🍲🎣

BeautifulSoup 是我最喜欢的浏览网站的方式。学起来简单,用起来方便。

此外,想象一下在网络抓取时从汤里捞出好的部分是很滑稽的。

首先,使用命令行将库安装到您的 环境 中。作为一名数据科学家,我通常使用 Anaconda

我们还需要requests 模块从 BBC 获取 HTML 代码。在您的终端中运行这些:

conda install beautifulsoup4 requests -y

如果你愿意,你也可以使用pip

pip install beautifulsoup4 requests

安装完成后,创建一个 python 文件(。py)并在代码顶部导入库。

我推荐使用 PyCharm ,但是如果你刚刚开始,Jupyter 笔记本是一个很好的尝试方式。

import requests
from bs4 import BeautifulSoup as bs

我们最关心的是两个find 函数。它们允许我们在汤里找到任何 HTML 元素,只需要指定它的名字。

**find**(element_tag, attribute) *#return first matching item***find_all**(element_tag, attribute) *#return list of matching items*

始终使用 python 环境来管理您的项目

示例文章

让我们挑选一篇 BBC 的文章。我选择了一个冰岛纪念其第一座冰川因气候变化而消失的地方。

通过 Python 访问原始文章:

url = '[https://www.bbc.co.uk/news/world-europe-49345912](https://www.bbc.co.uk/news/world-europe-49345912)'
article = requests.get(url)

然后将文章内容传递给 BeautifulSoup 并指定 HTML 解析器。

soup = bs(article.content, 'html.parser')

就这么简单,汤就做好了!让我们找出好的部分🎣

下一步是手动检查页面的 HTML 以找到我们感兴趣的元素。我用的是 Chrome,但是你可以用任何浏览器。

使用浏览器定位元素

在浏览器中打开网页,右键单击并“检查”。

作者图片

将鼠标悬停在任何文本上,浏览器会告诉您该段落在哪个 div 中。

如果不起作用,按***Ctrl+ Shift+ C****或* ***CMD + shift + C*** 再试一次。

在这种情况下,“story-body _ _ introduction”包含突出显示的段落。

具有属性" articleBody" 的 div 类" story-body__inner "包含了整篇文章,这就是我们所追求的。

作者图片

在汤里找到尸体:

*body = soup.find(property='articleBody')*

这为我们提供了原始 HTML 格式的段落(p)的内容。

访问每个段落的文本,并使用列表理解将其分配到一个新列表:

*text = [p.text for p in body.find_all('p')*

我们可以将上述内容组合在一个函数中,该函数接受 BBC 文章的 URL:

访问其他区域

如果我们想要访问标题,我们再次检查站点,找到标题所在的 div,然后把它从混乱中捞出来。

作者图片

代码看起来是这样的:

更有经验的编码人员可能已经发现了这些函数的问题…

它们在很大程度上是相同的。那不是很嘛。

一种方法是将它们重构为 3 个函数,并将get_soup放在自己的函数中。

然而,这意味着如果我们想访问标题和正文,我们必须下载 BBC 文章两次!

这感觉反而应该是一门课。

另外,类看起来更专业,而不是在函数中调用函数。当刮刀变得越来越复杂时,它们也使维护变得更容易。

作为伟大的程序员,让我们把它变成一个类!

重构为一个类🚀

从定义类开始。

每个类都应该有一个__init__ 函数,你可以传递任何变量来初始化函数。

当您调用该类时,会自动调用__init__函数。

类中的每个函数还需要有self 作为第一个参数。这是那个特定类的实际实例。

***class BBC:
    def __init__(self):
        pass***

接下来,在__init__中添加 URL 作为参数,并把它变成一个汤。更改以粗体突出显示。

*class BBC:
    def __init__(self, **url**):
        **article = requests.get(url)
        self.soup = bs(article.content, "html.parser")***

将 soup 变量写成 self.soup 使它成为该类的一个属性。可以在类中的任何地方、任何函数中访问类属性。

为了访问文章的正文,我们使用前面的 body 函数。body现在也是这个类的一个属性

*class BBC:
    def __init__(self, url):
        article = requests.get(url)
        self.soup = bs(article.content, "html.parser") **self.body = self.get_body()** **def get_body(self) -> list:
        body = self.soup.find(property="articleBody")
        return [p.text for p in body.find_all("p")]***

同题:

*class BBC:
    def __init__(self, url):
        article = requests.get(url)
        self.soup = bs(article.content, "html.parser") self.body = self.get_body()
 **self.title = self.get_title()** def get_body(self) -> list:
        body = self.soup.find(property="articleBody")
        return [p.text for p in body.find_all("p")] **def get_title(self) -> str:
        return self.soup.find(class_="story-body__h1").text***

整个代码看起来像这样:

摘要

暂时就这样了。下面是它的工作原理:

作者图片

在我的下一篇文章中,我将 NLP 应用于 BBC 文章,并构建一个 Streamlit 应用程序与之交互!

超级星期二:多愁善感

原文:https://towardsdatascience.com/super-tuesday-getting-sentimental-303a8ecc0212?source=collection_archive---------38-----------------------

缩小范围

在超级星期二之前的一周里,美国民主党总统初选的格局发生了很大变化。全世界的目光都在注视着我们走向谁将与唐纳德·特朗普总统对决的最终决定。这是一个拥挤的领域,但在过去的一周,它已经明显变得不那么拥挤了。情绪高涨;到目前为止,这是一个有争议的初选季节,许多候选人获得了热情的支持者,他们可能对党内其他人感到愤怒或失望。上周开始时,大约有 8 名候选人参加竞选(老实说,很难保持跟踪),现在在超级星期二的另一边,看起来我们可能会剩下最后两名候选人。随着党内情绪的高涨,我决定看看候选人使用的语言,以及上周通过 Twitter 与他们互动的人使用的语言。

初选候选人上周使用的词汇(注意冠状病毒在中右蔓延😷)

分析概述

用于这一分析的数据从 2 月 24 日开始从 Twitter 上传到 3 月 3 日(超级星期二)。收集了满足以下要求的推文:

  • 文本包含一名候选人的姓名
  • 推特提到了其中一名候选人
  • 其中一名候选人发送或转发了推文

这些推文存储在网络数据库(Neo4J)中,用 RegEx 和 NLTK (Python 的自然语言工具包)进行处理/清理,然后使用 Seaborn 和 Matplotlib 进行可视化。每条推文的情感都是用 VADER(效价感知词典情感推理器)计算的。总共查看了候选人的 753 条推文和大约 94,000 条关于候选人的推文。这些计数的细目如下所示。

感情

情感可以被认为是文本情感内容的一种度量:数字越积极,情感越积极,数字越消极,情感越消极。VADER 用从-1 到 1 的范围来衡量情绪。在我处理 Twitter 文本的经验中,0 的情感不仅通常表示中性的价值(潜在的积极词汇和消极词汇一样多),还表示客观的文本(没有相关情感的纯粹信息传递)。

候选人

候选人推文的情绪统计摘要,也是 HBD 众议员 Lewis🎂!!

上面的可视化图描绘了候选人在 Twitter 上的用户名分组的每条推文的情绪。箱线图计算他们总体情绪的汇总统计数据,最外面的叉表示他们的极值(最低和最高),内部突出显示的方框捕捉他们情绪的中间 50%的值。穿过突出显示的框的条标记中间值(在我们的例子中是中间值)。

值得注意的是,从这张图片中,我们可以了解候选人使用 Twitter 传播信息或获得支持的频率。根据他们发出的推文数量,作为超级星期二的竞争者留在比赛中的 4 名候选人名列榜首可能不是巧合。此外,我还注意到了两条观点最极端的推文(伯尼的推文最负面,拜登的最正面)。从这些推文中,我们看到情绪分析正在收集情绪化的词,如:破产、犯罪、债务、荣誉、朋友和快乐。

重要的是要认识到,消极和积极并不一定转化为悲伤/沮丧和快乐/激励。消极可以表示正义的愤怒,积极可以表示祝贺。当我们继续估算和聚合语言的情感内容时,这是一个需要记住的重要警告。

4 个超级星期二候选人的推特情绪。离中心越近的推文越负面,离中心越远的越正面。

从总体上看超级星期二的 4 个主要候选人的推文,我们可以感觉到他们什么时候最活跃(使用的时区是美国东部时间,每个象限代表一天中的 6 个小时)。此外,下午的中性推文群暗示了发布公告或发布更新的常见时间。

成分

由于大量的推文,只有百分之一的推文被绘制成点,只有百分之十被用于方框图

如前所述,关于候选人的推文比候选人自己的推文多得多,上面我们来看看普通用户的推文样本。相对数量保持不变,似乎与少数例外情况相符。有趣的是,进步候选人似乎比温和派在 Twitter 上获得了更多的参与,这可能说明了在看待活跃在 Twitter 上的人时存在固有的偏见(即,人口统计数据可能比一般人群更倾向于自由派或年轻人)。特别是,伯尼在推特上被提及的次数远远超过了其他任何一位候选人(注意:他的推特数量与接下来三位候选人的总和相同)。

人民已经说话了

我们现在对这些推文中包含的一些情绪有所了解,但人们实际上在说什么呢?在选举中,我们的声音在投票中被听到,我们投给一个候选人而不是其他任何人。然后,我们的投票被汇总并分散到代表我们行事的代表的行为中(一般来说,不要@我)。在将我们的声音转化为选择候选人的行动的过程中,有相当多的步骤。但今天,我们可以直接看到数字化参与竞选过程的声音合唱。这个词云可视化了这些人在所有推文中的词频。单词越大,它在所有用户的词汇中就越普遍。它是围绕主节点发生的会话的聚合快照。

上面我们来看看超级星期二 4 个主要候选人最常使用的词,以及它们的总数(中上)。我把候选人的名字留在了分析中,而不是把他们作为停用词过滤掉,以了解一条推文引用另一条的频率。我们再一次看到伯尼似乎主宰了推特上的焦点。看着出现的一些词,我不得不指出,“男人”并没有出现在任何一个男性候选人的最常用词中,但“女人”却出现在竞选中唯一的主要女性候选人的最常用词中。这并不能证明潜在的厌女症或偏见,但我希望这是反思我们和媒体在整个过程中如何对待和报道每一位候选人的原因。

后续步骤

我希望这份初步分析能让你对超级星期二之前的日子有所了解。就收集到的数据而言,我们只是触及了全国性对话的表面,或者 Twitter 上的社区如何与候选人互动。接下来的步骤可能包括:

  • 社区检测(根据用户与候选人的互动,哪些用户属于谁的阵营?既然候选人的范围已经缩小,这些用户是如何转移的?)
  • 话题建模(Twitter 上发生了哪些离散的话题?这些在候选人中是如何分布的?)
  • 异常检测(是否有用户以不真实的速率或方式进行操作?TW: 2016 俄罗斯https://fivethirtyeight . com/features/what-you-found-in-300 万-russian-troll-tweets/

欢迎建议和讨论!你可以在推特上找到我,但是我花在这个项目上的时间不会像 https://twitter.com/danjizquierdo那样频繁

资源

[## danjisquierdo/感伤

twitter 数据情感和统计分析工具集

github.com](https://github.com/danjizquierdo/Sentimental)

VADER 纸业

http://comp . social . gatech . edu/papers/icwsm 14 . Vader . hutto . pdf

形象化

https://towards data science . com/3-awesome-visualization-techniques-for-every-dataset-9737 eecacbe 8

在 2020 年的最后几个月,为您的数据科学提供充足的资源

原文:https://towardsdatascience.com/supercharge-data-science-3da3ccf103-13da3ccf103?source=collection_archive---------51-----------------------

这篇文章建立在 2020 年的超级流行资源列表的基础上,在我们进入机器学习的新一年时,给你你需要的工具

今年早些时候,我分享了一份由 16 种资源组成的列表,当我从数据分析师,通过训练营,到我的第一份数据科学工作,从事真实世界机器学习项目时,我发现这些资源很有帮助。

在公布第一份名单后的这段时间里,我发现了许多优秀的信息来源,与大家分享。这些网站、视频和播客将增加您高级分析技能的深度和广度。如果你觉得这很有帮助,请考虑注册获取更多提示

网络资源

🌏 Google 数据集搜索—查找免费提供使用的数据集。我现在很有灵感,可以开始一打兼职项目。参见: 这份通过谷歌云平台 提供的公共数据集列表。

🔨 代码为 的论文——这是对 arXiv 的实际补充,提供了一个列表……嗯,代码为的论文!代码链接现在显示在 arXiv 文章上,作者可以通过 arXiv 提交代码。

ML 回顾——借用运筹学中无可指责的事后分析的概念,这个由瑞安·劳创建的发人深省的网站请求机器学习研究人员提供他们对他们在我们领域的工作和应用中好的方面和不太好的方面的想法。

🚀Launch by fast . ai——引人入胜且深入,这门课程经常被引用为编码人员进入机器学习的原因。 听听 De-Oldify 的创作者谈一谈他与课程 的经历。

📆 数据科学会议&在线活动——鉴于目前的世界形势,免费的全虚拟会议是一种希望。如果您想了解每月的活动日程,并与专家交流,请访问 KDnuggets 的这个页面。

YouTube 频道

****🏆deep learning . ai——吴恩达的平台特色课程集锦及机器学习英雄访谈。

****♘stat quest——通俗易懂、憨态可掬、充满音乐感,这个频道将提升你对优秀数据科学背后的统计学概念的理解。如果你想支持这个展览并回顾他的课程的文本和图像版本,乔希·斯塔默博士还提供了 PDF 学习指南。

两分钟论文 — 好吧,我可能用取笑了这个频道上的一些成就,但这确实是一个展示机器学习最新论文的好地方。该频道的创建者 károly zsolnais 本身就是一名研究科学家,特别关注计算机视觉、图形和动画。

🤔 莱克斯·弗里德曼——莱克斯·弗里德曼以深思熟虑的人工智能播客著称。这些对话的视频有助于将机器学习大师人性化,至少有一点。Lex 还分享了他在数学、编码和机器学习中感兴趣的概念的短片。

这位哈佛大学教授的系列文章和我记忆中的一样迷人和吸引人,对于提高你对统计方法的应用非常有价值。

播客

⚔️ 命令行英雄saron yitbarek带着热情和个性,为计算机科学背后的概念和创始故事注入了新的生命。这个播客来自 Red Hat,强调了开源范例的力量。

🎨数据科学的艺术家们——我非常感谢 Harpreet Sahota 的这个 pod。数据科学艺术家最近更名为数据科学家唯一的自我提升播客,我完全同意。每集都是与一位数据科学家就他们职业生涯的成功和失败进行的公开对话,具有非凡的洞察力和真实性。

数据工程播客 希望让你的技能多样化进入数据运营?良好的数据工程实践确实是任何数据科学工作的基础,因此了解该领域的关键工具是非常有价值的。托拜厄斯·小萌和他的客人通过这个平台提供的深厚专业知识将塑造关于数据的新思考方式。

⛅️cloud cast在机器学习工作流程的另一端,还有 DevOps 。如今,这往往需要使用云服务。Cloudcast 的工作人员将为您提供业内并购的最新消息,以及每周一次的新云技术深度探讨。****

更多资源

您正在使用哪些资源来学习数据科学?在评论里掉一行。

如果你喜欢这篇文章,请关注我的媒体LinkedInYouTubeTwitter ,了解更多提升你的数据科学技能的想法。考虑报名获取更多提示

2020 年增强数据科学的资源

原文:https://towardsdatascience.com/supercharge-data-science-5bb7376d8572?source=collection_archive---------29-----------------------

塞巴斯蒂安·沃特曼在的照片

通过这个有用的期刊、视频和讲座的集合,推进你对机器学习的理解。

无论你的背景或专业水平如何,建立一个跨越统计学、计算机科学和机器学习的知识库是你作为一名数据科学家取得成功的关键。

网络资源

🤯 arXiv 健全性——机器学习学科的特点是 arXiv 预印本形式的新信息特别密集。幸运的是,深度学习英雄 Andrej Karpathy 开发了这个界面,使跟上该领域的最新发展变得更加容易。

🔖 基础论文——聚合智力团队的(下面讨论的 ML 讲解讲座背后的团队),这里列出了数据科学领域最有影响力的论文。

🎨 蒸馏——谷歌蒸馏的团队制作了一本独特的期刊,为开创性的想法提供了卓越的可视化工具。为了更容易进入机器学习领域,请查看谷歌的人工智能探索工具

📚paper space AI wiki——这是我目前为止找到的最好的 AI 词汇表……评论里的 hmu 如果遇到更好的!

📐**——**这个在线论坛专注于通过社区传播思想,为讨论机器学习方面有影响力的论文提供了一个平台。****

🐼 Chris Albon 的博客——你曾经想知道如何在熊猫中做的一切,加上机器学习闪存卡供购买。

🍪 Cookiecutter 数据科学 不用再寻找模板来建立您的下一个数据科学项目。

YouTube 频道

💻 速成班人工智能——在这 20 集系列中,贾布里勒展示了机器学习的一些基础知识。速成班团队还制作了一个关于计算机科学的很棒的系列节目,应该是我们所有技术领域的人(是的,可能是每个使用计算机的人)必看的。****

ML 解说——加拿大就像美国的聪明大姐,在你登场之前的几年,她就用自己的才华迷倒了你的高中老师。就在你认为加拿大似乎再完美不过的时候,她去给曼梯·里解释了。这个奇妙的频道以大约一小时的讲座为特色,有助于澄清 ML/AI 中的开创性思想。****

🖌 杰伦·阿拉玛——在我写这篇文章的时候,杰伦已经制作了一个视频,但我相信这个频道会让你继续关注更多精彩的内容。杰伊是图解变形金刚首次使用 BERT 的视觉指南以及更令人惊讶的平易近人的内容的不可思议的创造者。****

👁 3 个蓝色,1 个棕色——这个频道提供了机器学习领域底层统计概念的绝佳介绍。如果格兰特·桑德森不能让你对学习数学产生兴趣,那就不知道什么能了。****

播客

🎙 英伟达的人工智能播客——自 2010 年代中期以来,英伟达一直引领着用于深度学习的 GPU 计算的兴起。这期播客的特点是主持人个性鲜明,令人印象深刻地融合了企业领袖、创业人士和技术更新。

🔭 数据交换——本·洛里卡(Ben Lorica)每集都会处理机器学习相关的商业案例。播客的网站提供了优秀的文档,加上总是有趣的“相关内容”,条目可以追溯到洛里卡在奥莱利的时候。

⚛︎ 期刊社数据怀疑论者——这个播客就像是坐在你超级聪明的朋友的学习小组里。凯尔、兰、乔治,有时还有一个客人聚在一起讨论数据科学杂志上的最新文章和相关新闻。

🗓TWIML 人工智能播客——除了主持一个引人入胜的采访系列,twiml 还开始提供播客收听派对,提供独特的协作学习体验。

📈 线性题外话——经验丰富的数据科学教育家 Katie 向企业软件工程师兼双关语爱好者 Ben 讲解统计学中的核心思想。这是开始您的数据科学学习之旅的好地方。还可以看看凯蒂的 Udacity 课程——这是我在还在学习 Python 基础知识的时候开始学习 DS 的方式。

更多资源

如果你喜欢阅读这篇文章,请关注我的媒体LinkedInYouTubeTwitter ,了解更多提升你的数据科学技能的想法。

注册以在下一篇“ 资源增强您的数据科学 ”文章发布时获得通知。

您正在使用哪些资源来学习数据科学?在评论里掉一行。

考虑辅导,增强你的数据科学技能

原文:https://towardsdatascience.com/supercharge-your-data-science-skills-by-considering-tutorship-6c0b805eeb46?source=collection_archive---------31-----------------------

辅导/指导如何成为数据科学家必要的软技能补充

UnsplashNeONBRAND 拍摄的照片

有很多很棒的数据科学文章,但是…

随意阅读《走向数据科学》中的数据科学文章是我学习新技能的首选网站,许多作者分享了他们的数据科学之旅。许多文章提供了很好的直截了当的内容,而没有大量沉重的技术文献评论,当与 arXiv 等科学期刊文章相比时,这常常使我处于一种困惑的状态。

大多数情况下,许多旨在教导和激励读者在数据科学领域追求或进行职业转换的文章涵盖以下主题:

  • 哪个学位/高级学位能让你在这个领域走得更远
  • 数据科学领域的职业前景和典型工作描述
  • 推荐的编程语言
  • 你应该学习的典型机器学习算法
  • 推荐初学者及以上注册的在线课程
  • 如何实现算法 X 求解 Y
  • 新的数据科学框架为您的数据科学流程增添趣味

在考虑数据科学领域的工作时,这些主题是绝对必要的。然而,在这篇文章中,我想强调一种软技能,它对于在数据科学领域工作的任何人来说都是绝对必要的:沟通

在现实世界中,数据科学不仅仅是从数据库中提取所需的数据,处理大量数据,并发布机器学习算法来预测或分类给定的问题。

也是生意。

谈到业务,我们不仅需要用技术术语与我们的数据团队交流,还需要用所有专业人员都能理解的语言与内部利益相关者和客户交流。

来源: KDNuggets

事实上,根据 2019 年的 KDNuggets,沟通已被封装为核心数据科学技能之一。单从信息图表来看,我认为沟通在需求技能中占很高的比例。

典型的数据科学家工作要求

考虑以下来自罗尔斯·罗伊斯公司的数据科学家的工作描述,它类似于许多其他数据科学家角色:

来源: LinkedIn

除了出现在列表顶部的标准技术数据科学技能和经验之外,与沟通相关的突出软技能也是数据科学家的一个基本特质。

那么为什么要做家教呢?

从现在开始,当我谈到辅导时,我指的是包含 STEM(科学、技术、工程、数学)类别的技术辅导。

我个人的家教经验

我在本科期间,曾在 第一代码学院 实习,担任 kids 的编码导师。我教过很多编程语言,包括 Python,HTML/CSS/JS 用于基本的 web 编程,C#结合 Unity 用于基本的游戏开发,以及基于块的编程,如 MIT AppInventor 用于 Android 和 Scratch。

“什么?为孩子编码?对他们来说是不是太难了?”

是的,这听起来可能很难,因为我们大多数人至少是在青少年晚期或成年早期学会的。我们认为编码是一项困难的任务,智力发达的成年人可能理解。我在本科期间 20 多岁的时候开始接触编程。

在大一开始熟悉编程基础后,我决定参加这次实习,天哪,我在这么短的时间里学到了很多东西!

1.掌握 ELI5 的概念

ELI5(像我 5 岁一样解释)是 Reddit 对许多难以解释的问题的社区解决方案,基本上社区试图“简单明了”地让提问者理解。

当我教 7-10 岁左右的年轻学生时,他们没有非常发达的认知能力来吸收常见的编程实践,如变量、循环和条件。教授这些内容需要大量使用视觉辅助工具来连接这些点。

向年轻学生解释条件语句的简单但非常有效的方法(来源: CodeScope

将此转化为数据科学,我们称之为解决其业务问题的数据可视化和模型解释。

1.2.数据可视化

当我们向内部利益相关者和客户展示时,我们需要假设他们的头脑是一张空白的画布,而我们是负责在他们的头脑中描绘一幅清晰明确的画面的艺术家。当你是手头项目的唯一负责人时,尤其如此。没人知道你是怎么做到的。

简单地在表格和简单的图表中加入几个关键指标是不够的。设计交互式执行仪表板并一步一步地引导他们完成是许多数据科学家的基本特征。

我说很多是因为这可能是一项交给商业智能分析师的工作。

在任何情况下,能够展示漂亮的视觉效果并满足他们的业务需求对你的角色来说都是至关重要的,除非你是一名研究学者,否则这可能并不重要。

1.3.模型可解释性

除了达到 KPI 预测目标之外,根据您的算法选择解释您的预测模型也很重要。除了做出好的预测之外,涉众可能还想知道哪些变量对预测的敏感性负责。

来源: KDNuggets

这就是你的 ML 算法选择发挥作用的地方,取决于你的最终用户是谁。如果准确性是最重要的,那么你可以考虑复杂的方法,如神经网络或集成方法。否则,变量解释更适合使用简单的算法,如多元线性回归或逻辑回归。

然而,在 ML 框架的当前状态下,诸如 random forest(这也是我个人最喜欢的)之类的复杂模型具有特性重要性函数,该函数可以轻松地可视化与模型相关的每个特性的重要性,这使得它成为业务经理研究的重要信息源。

2.战略沟通

教某人一些新的和技术性的东西绝对是一项具有挑战性的任务,尤其是在处理数字和理性概念的时候。在我上的每一堂课中,我都注意到学生们在第一节课(每节课 90 分钟)的前三分之一时间里最专心。之后,他们变得焦躁不安,开始难以跟上课程。

这也适用于我,当我在大学期间听讲座时,我想许多工作的成年人也没有很长的注意力持续时间。

人类的大脑并不是设计来 100%利用其记忆形成神经元的。

[## 大脑可能只使用了 20%的记忆形成神经元

还记得人们只使用了 10%大脑的古老神话吗?虽然一项新的研究证实,溴化物对…

www.scientificamerican.com](https://www.scientificamerican.com/article/the-brain-may-use-only-20/)

接受辅导教会了我如何以战略性的方式创建报告和演示内容,最大限度地吸引读者或观众的注意力。

我主持了一个关于有效分析的数据清理的研讨会

不同的人会有他们自己的策略,但基本上知道当你的内容变得有点乏味时,什么时候增加它的味道是给你的工作留下好印象的关键。这意味着更少的文字和更多的视觉效果,并知道如何讲述你的视觉效果。你也可以编造一些有创意的类比,与你试图解释的结果产生共鸣。

对我来说,在与利益相关者交流结果的过程中,我利用 Tableau 的交互功能。

3.同理心和耐心

“你能再给我解释一下吗?”

“哦哈哈,我完全忘了这件事”

他们说,用那双天真的小狗眼睛。这些问题几乎每节课都会出现在我面前,起初,不得不一遍又一遍地重复解释有点令人畏惧。

但后来我意识到,我也一样,这就是为什么我一开始就不是一个完美的学者!

然后我意识到,在工作的时候,有些像我一样的人很容易忘记。当然,这并不意外。许多员工被期望在工作中同时处理多项任务,当一个人把注意力从你的工作上移开一段时间,他们肯定会忘记。

因此,不要因为不得不重复自己而感到沮丧,接触教学可能会在你内心灌输同理心和耐心,让你去:“当然,我很乐意再给你解释一遍,事情是这样的……”

最后的想法

我利用我教孩子们编程的经验,作为如何在数据科学领域建立沟通能力的例子。事实上,我认为这极大地帮助了我的面试,在面试中,我必须以招聘经理可以理解的方式来解释我过去的工作经历和项目,而不要扔进太多的技术术语,除非招聘经理有技术倾向。

但这并不意味着你应该走这条路,我相信有其他方法可以让你的数据科学沟通技能更上一层楼。

一种方法是考虑做你自己的激情项目,并与你的朋友分享你的发现。如果他们喜欢,那么我肯定你做得很好!

我希望这篇文章能够帮助读者提高他们在数据科学领域的交流能力!

如果你喜欢这篇文章,可以考虑看看我在自己的个人网站上免费写的其他文章!

[## 鲍比·马尔乔诺

数据分析师

www.bobbymuljono.com](https://www.bobbymuljono.com/)

尽情享受吧!

用感应偏置增强你的模型性能

原文:https://towardsdatascience.com/supercharge-your-model-performance-with-inductive-bias-48559dba5133?source=collection_archive---------32-----------------------

照片由 CC0 的 Martin Vorel 拍摄——公共领域许可证

实践教程

如何更聪明地工作,而不是更努力:在机器学习模型中编码现实生活中的对称性可以提高其准确性几个数量级!

对称无处不在;他们包围了我们。

雪花:GL kvs 2/CC BY-SA(https://creative commons . org/licenses/BY-SA/4.0)、Romanesco:Jacopo Werther/CC BY-SA(https://creative commons . org/licenses/BY-SA/3.0)、蜂巢:Pixabay license

从雪花美丽的规则形状、romanesco 的自相似(分形)结构到蜂巢的六边形图案。

大自然似乎在寻找对称。事实上,我们存在的规律展示了太多的对称:物理学家谈到时间和空间的平移对称。他们的意思是,像重力这样的力和几百万年前的作用方式是一样的,它们在悉尼和纽约之间没有变化。

他们的另一个最爱,旋转对称,简单地说,当你从不同的角度看一个物体时,它的属性不会改变。

对称的例子不胜枚举,其中一些比另一些更容易理解(洛伦兹对称,说明在惯性系中共同运动的观察者的光速是相同的,可能已经逃过了不太精通物理的头脑)。

尽管其中一些对称性对人类来说是显而易见的,但大多数机器学习模型却出人意料地忽视了它们的存在。我举一个我自己工作中的例子:

bin im Garten/CC BY-SA(【https://creativecommons.org/licenses/by-sa/3.0】T4)

粗略地说,我研究的目标是使用 ML 来仅从结构信息预测分子的性质。这意味着,我得到了一个原子列表,以及它们的坐标。

对于一个水分子,它看起来像这样:

原子的坐标可以方便地概括在矩阵中,矩阵中的行对应于原子,列分别对应于 x、y 和 z 位置。我想预测将分子分裂成它的组成原子需要多少能量(原子化能量)。我可以通过训练神经网络 F 来做到这一点,神经网络 F 使用原始坐标作为特征并输出能量:

假设我成功地在一个大而多样的分子数据集上训练了这个神经网络,并且我想要找到以下水分子的雾化能量:

你可能已经注意到,它只是我们原始分子的旋转版本。因此,它应该具有相同的雾化能量。我们有没有任何保证神经网络会尊重这个旋转对称?可惜没有。

更糟糕的是,如果我们简单地交换两个氢原子

网络可能再次给出完全不同的答案。相同原子的排序没有物理意义,只是源于神经网络功能形式的产物。理想情况下,我们希望神经网络输出尊重这种排列对称性(排列:“交换事物的顺序”),但如何做到呢?

在化学和物理的机器学习的早期,很快就清楚了模型需要观察这些对称性才能足够准确。因此,大量的努力致力于找出如何将对称性结合到 ML 算法中。如今,这通常是通过巧妙的特征工程和神经网络设计的结合来实现的。综合考察这些方法可以在这里找到【1】。所有这些方法的共同点是,它们以某种形式将归纳偏差引入到学习算法中。

学习算法的归纳偏差[……]是学习者用来预测尚未遇到的给定输入的输出的一组假设[2]

在旋转对称的情况下,这种归纳偏差可以表述为这样的假设:“任何在旋转下不是不变的信息都可以而且应该被忽略”

不管你是否意识到了这一点,如果你以前使用过任何机器学习模型,你都会遇到归纳偏差:

  • 线性回归基于因变量和协变量之间存在线性关系的假设。
  • k-最近邻分类器假设特征空间中的邻近性转化为输出空间中的邻近性。
  • 卷积神经网络假设输出对输入的平移基本不变(不考虑边界条件)。

虽然所有这些标准算法都有一些内在的偏差,但我想用一个例子来说明引入额外的假设如何能够大大提高您的模型的准确性。

Pixabay 许可证

示例:房地产价格模型

想象以下场景:

您的客户对买卖房地产感兴趣,并要求您创建一个机器学习模型,以准确预测建筑物的公平市场价值。幸运的是,训练数据很容易获得,但有些有限(大约 1000 个样本)。让事情变得复杂的是,除了价格之外,任何关于建筑的信息都是在单位级别上给出的,价格只适用于整个建筑。

为了简化我们的分析,让我们假设每栋建筑正好包含十个单元,并且我们有关于每个单元的以下信息:

  • 户型:零售、办公、居住空间
  • 单位面积(平方英尺)
  • 房间的数量
  • 窗墙比
  • 该单元位于哪一层(占总层数的比例)

我们的数据以表格形式出现,有 1000 行(样本数)和 51 列(5 个特征 x 10 个单位+总价)。让我们把模型输入(前 50 列)写成设计矩阵𝑋,因变量写成向量𝑦

线性回归

香草 LR

任何回归任务的良好起点总是线性回归,其目的是选择权重 w 以便模型预测

最小化均方误差

为了分析该模型对于我们的数据的表现如何,我们可以查看关于训练集大小的泛化误差(测试集上的误差)。绘制我们的结果,我们得到通常所说的学习曲线:

请注意,我们已经包括了一个基线模型,它只是预测训练集的平均价格。从这个情节中我们可以推断出几件事。我们看到,对于极小的训练集,基线模型比 LR 更准确,但是当我们处理较大的数据集时(注意对数-对数比例!)我们可以改进基线。但是 100 万美元的均方根误差(RMSE)并不是很大,对我们虚构的客户也没有用。我们希望做得更好…

置换不变 LR

让我们考虑一下对称性:在设计矩阵𝑋中以什么顺序排列重要吗?答案是:不。我们可以将第 1-5 列与第 6-10 列交换,但仍然期望建筑具有相同的净值。然而,我们的 Vanilla LR 无法准确捕捉到这一点,因为无法保证权重 15 与 610 相同。目标很明确:我们需要我们的模型在单位置换下保持不变。

让我们考虑一个稍微不同版本的设计矩阵,我们称之为𝑋̃。它的维数为 10000 x 5,是通过将每个单元(即每组五列)视为一个单独的数据点,从原始𝑋获得的。那么,线性回归就变成了

其中𝑧是每个单位的价格。不幸的是,我们无法获得𝑧(一个潜在变量),但我们可以假设𝑧和𝑦.之间存在某种关系因为我们想停留在线性模型的范围内,我们写道

简单地说,这意味着一栋建筑的价格是该建筑内每个单元价格的总和。通过引入适当的𝐿矩阵,我们可以写出𝑖所有建筑物的上述总和,从而

这让我们可以求解线性回归模型

实际上,𝐿𝑋̃意味着我们总结一栋建筑内所有单元的特征,因此,例如,我们只看每栋建筑的总面积,而不是每个单元的面积。所以对于线性回归来说,强加排列对称性真的是一个微不足道的任务。当我们转向内核方法时,使用这种更抽象的符号的优点将变得明显。

使用 LR 的排列不变版本,我们得到以下学习曲线:

虽然我们看到了较小数据集的实质性改进,但该模型似乎没有从数据中学习到太多东西,导致曲线变得平坦。这表明线性模型不足以表达训练数据中包含的所有细节。显然,线性假设太强,对于“健康”模型,我们期望学习曲线在对数标度上是线性的(表明预期的幂律行为)[3]。

高斯过程回归

普通探地雷达

让我们考虑一个更复杂的模型。我们有几个选择:神经网络当然很受欢迎,但众所周知,对于这样的小数据集,神经网络是不可靠的。有效选项包括基于树的方法和 k-means 方法。我个人最喜欢的是基于内核的方法,特别是高斯过程回归(GPR)

我们正在寻找一个函数𝑦=𝑓(𝑥),它将输入或自变量𝑥映射到因变量𝑦(价格)。在探地雷达中,我们采用贝叶斯方法来寻找这个函数,首先在所有可能的𝑓上指定一个先验,然后根据观察到的数据点(𝑋,𝑦).该先验通过具有协方差矩阵𝑘.的高斯过程来定义

高斯过程是随机变量的集合,任意有限个随机变量具有联合高斯分布[4]。

对于𝑥的任意值,输出𝑓(𝑥遵循正态分布。此外,𝑥和𝑥′这两个远点的输出是联合正态的,其协方差由𝑘(𝑥,𝑥′).定义在实践中,这意味着我们可以通过选择合适的协方差函数(也称为核)𝑘(𝑥,𝑥′).来确定拟合函数𝑓的形状

核的一个非常流行的选择是平方指数协方差(有时也称为径向基函数)

选择这个核,我们本质上在𝑓上设置了一个平滑条件,因为靠近在一起的点(意味着|𝑥−𝑥′|很小)将高度相关。

让我们回到我们的例子。一旦我们根据训练数据调整高斯过程,我们就可以对测试集进行预测。

使用我们的设计矩阵𝑋和目标值𝑦,模型预测给出如下

这看起来非常类似于线性回归,除了𝑋已经被𝑘(𝑋,𝑋).取代因为该方程在参数𝜔中是线性的,所以仍然可以直接求解:

请注意,我们包含了一个乘以单位矩阵 I 的参数𝜎。该参数用于模拟数据中存在的噪声,同时有助于避免矩阵求逆中的数值问题。

将我们的训练数据代入这些方程,我们得到以下学习曲线:

嗯,效果不太好。虽然与 LR 相比,我们赋予了该模型更多的表达能力,但其测试误差仍然与后者相当。我们的模型似乎过度拟合了数据。

置换不变探地雷达

我们再加回置换不变性。和以前一样,我们想解决辅助问题

和𝑦=𝐿𝑧.一起矩阵 L 保持与线性回归问题中相同。

在摆弄了一些术语之后,我们得到了下面的等式:

重新定义

我们恢复了 GPR 的原始形式

但是这次使用置换不变核𝑘̃。插入我们的数据,我们得到以下学习曲线:

万岁!通过使用置换不变性,我们已经能够将我们的最佳测试误差从大约 700,000 美元减少到 30,000 美元。此外,比例是线性的(对数-对数比例),这表明如果需要,我们可以通过收集更多的数据来进一步提高模型的准确性。

回到科学

我希望我已经能够说服你,在用机器学习模型拟合你的数据之前,有时停下来三思是值得的。通过简单地识别数据中的对称性,我们已经能够将模型精度提高 20 倍以上!

作为一个小小的奖励,如果你理解了这篇文章中的所有内容,你实际上离成为计算化学家更近了一步。

怎么会这样

如果你用“分子”代替“建筑”,用“原子”代替“单位”,我们实际上已经建立了一个化学和材料科学研究人员经常使用的模型[5]。该模型可以通过将分子表示为原子贡献的组合来预测分子的属性,如其能量。正如在我们的例子中,这些原子的贡献是未知的——我们只知道整个分子的能量——但我们仍然可以用潜在变量 z,来表述这个问题,从而使其排列不变。

如果你喜欢这篇文章,请在这里关注我,在 twitter 或在LinkedIn上联系。

参考

[1]贝勒尔,约尔格。"展望:原子模拟的机器学习潜力."化学物理学报 145.17 (2016): 170901。

[2]https://en.wikipedia.org/wiki/Inductive_bias

[3] C. Cortes,L. D. Jackel,S. A. Solla,V. Vapnik 和 J. S. Denker,学习曲线:渐近值和收敛速度,神经信息处理系统的进展(柯伦联合公司,1994),
第 327-334 页

[4]c . e . Rasmussen & c . k . I . Williams,机器学习的高斯过程,麻省理工学院出版社,2006 年,ISBN 026218253X。c 2006 麻省理工学院

[5] Bartók,Albert P .等人,“高斯近似势:没有电子的量子力学的精确性”物理审查函 104.13 (2010): 136403。

使用 TextBlob 增强您的 Python 字符串

原文:https://towardsdatascience.com/supercharge-your-python-string-with-textblob-2d9c08a8da05?source=collection_archive---------18-----------------------

在一行代码中获得更多关于文本的见解!

照片由托马斯·凯利Unsplash 上拍摄

动机

数据不仅包含数字,还包含文本。了解如何快速处理文本将有助于您更快地分析数据,并从数据中获得更多见解。

文本处理不需要很难。如果我们只需要在一行代码中找到文本的情感、标记文本、找到单词和名词短语的频率,或者纠正拼写,这不是很好吗?这时 TextBlob 就派上用场了。

什么是 TextBlob?

TextBlob 旨在通过一个熟悉的界面提供对常见文本处理操作的访问。您可以将 TextBlob 对象视为学习如何进行自然语言处理的 Python 字符串

NLTK 提供了一些方法来完成这些任务,但是您可能需要调用几个类来完成不同的任务。但是使用 TextBlob,您需要做的就是使用TextBlob(text)来访问 TextBlob 的不同方法!

使用安装 TextBlob

pip install -U textblob
python -m textblob.download_corpora

现在,我们需要做的就是用TextBlob对象包装文本来增强我们的字符串。

让我们看看我们可以用增压弦做什么。

单词标记化

我们将借用我的文章如何在生活不给你喘息的时候学习数据科学中的一些句子来学习如何使用 TextBlob。

单词标记化根据某些分隔符将一段文本分割成单个单词。

而不是根据不同的分隔符如“,”或“.”来分割字符串或者空格,我们只需要用blob.words来修饰我们的句子!

WordList(['When', 'I', 'was', 'about', 'to', 'give', 'up', 'I', 'told', 'myself', 'to', 'keep', 'going', 'It', 'is', 'not', 'about', 'working', 'harder', 'it', 'is', 'about', 'working', 'smarter'])

WordList可以作为 Python 列表使用。要访问第一个单词,请使用

>>> blob.words[0]
'When'

名词短语抽取

名词短语是以一个名词为中心的一组两个或多个单词(例如,“狗”、“女孩”、“男人”),包括修饰语(例如,“the”、“a”、“None of”)。例如,“女孩”不是名词短语,但“漂亮的女孩”是名词短语。

有时候,提取句子中的所有名词短语而不是提取单个名词对我们来说很重要。TextBlob 让我们可以轻松做到这一点

WordList(['learning strategies'])

正如我们所看到的,只有“学习策略”是从句子中提取的,因为它是句子中唯一的名词短语。

情感分析

我们还可以使用blob.sentiment提取句子的情感

Sentiment(polarity=0.15833333333333333, subjectivity=0.48333333333333334)

极性是一个位于(-1,1)范围内的浮点数。如果极性低于 0,句子的否定性大于肯定性。如果极性在 0 以上,则该句肯定多于否定。因为我们的极性是 0.15,所以它是正的多于负的。

主观性是指个人观点。主观性是一个位于(0,1)范围内的浮点数。如果主观性值大于 0.5,则句子的主观性大于客观性,反之亦然。由于句子的主观性是 0.48,所以客观大于主观。

词汇化

词汇化是一组单词的词典形式。例如,‘eats’,‘eat’,‘eating’都是‘eat’这个词的形式。词汇化是在应用其他 NLP 模型之前处理文本的一种流行方法。

为了使单词词条化,将单词放在Word对象中,而不是TextBlob

know
that
i
can
complete
these
things
in
a
short
amount
of
time
make
me
excite
and
be
in
the
flow

厉害!一些单词被转换成它们的字典形式。'知'转换为'知','激'转换为'激','使'转换为'使'。现在,NLP 模型不会将“知道”和“知道”视为两个不同的单词!

拼写纠正

有时,我们可能会在文章中发现一两个拼写错误。如果我们分析 Twitter 等社交媒体的文本,这个拼写错误就更常见了。拼写错误会使我们的 NLP 模型很难知道单词learnin和单词learning基本上是同一个单词!

TextBlob 还允许我们用一行代码来纠正拼写

我故意拼错了句子中的几个单词,比如neded, swicth,learnin.让我们看看 TextBlob 如何纠正这些单词

TextBlob("I just need to switch my learning strategics.")

相当酷!所有的拼写错误都以合理的方式得到了纠正。

我们也可以用Word().spellcheck()纠正个别单词

[('learning', 0.25384615384615383),
 ('warning', 0.24615384615384617),
 ('margin', 0.2153846153846154),
 ('latin', 0.13076923076923078),
 ('martin', 0.05384615384615385),
 ('lain', 0.046153846153846156),
 ('earning', 0.038461538461538464),
 ('marin', 0.007692307692307693),
 ('darwin', 0.007692307692307693)]

拼写错误的单词lanin可能是许多事物的拼写错误,因此 TextBlob 给了我们不同的结果,其中learning是正确率最高的单词。

词频

有时候,知道某个单词在句子中的出现频率是很重要的。TextBlob 允许我们轻松地找到文本中某个单词的频率。

我们将使用我的文章中的所有文字,讲述如何在生活不给你休息的时候学习数据科学。我们将使用报纸刮文章。

pip install newspaper

由于这篇文章是关于我的数据科学之旅,我预计句子中会有很多“我”这个词。让我们用blob.word_counts检查一下

81

81 是一个很高的数字,但是与我文章中的其他词相比,它有多高呢?让我们用柱状图来形象化它

正如我们所猜测的,像“我”、“to”、“the”、“my”这样的词是文章中最常见的词!

结论

恭喜你!您刚刚学习了如何用 TextBlob 处理 Python 字符串。使用上面列出的所有处理方法的唯一步骤是将字符串包装在TextBlob对象或Word对象中。多简单啊!

你可以在 TextBlob 的文档中探索更多处理和分析文本的方法。

本文的代码可以在这里找到

[## khuyentran 1401/数据科学

github.com](https://github.com/khuyentran1401/Data-science/blob/master/nlp/textblob.ipynb)

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedInTwitter 上联系我。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

[## 用 Python 模块 Newspaper 和 NLTK 查找文章中的常用词

使用 newspaper3k 和 NLTK 从报纸中提取信息和发现见解的分步指南

towardsdatascience.com](/find-common-words-in-article-with-python-module-newspaper-and-nltk-8c7d6c75733) [## 使用 Python 和情感分析探索和可视化您的 LinkedIn 网络

希望优化您的 LinkedIn 个人资料?为什么不让数据为你服务呢?

towardsdatascience.com](/sentiment-analysis-of-linkedin-messages-3bb152307f84) [## 如何用 Word2Vec 解决类比问题

美国之于加拿大,就像汉堡之于 _?

towardsdatascience.com](/how-to-solve-analogies-with-word2vec-6ebaf2354009) [## PyTorch 是什么?

想想 Numpy,但是有强大的 GPU 加速

towardsdatascience.com](/what-is-pytorch-a84e4559f0e3) [## 自然语言处理中的卷积神经网络

什么是卷积神经网络,如何利用它进行情感分析?

towardsdatascience.com](/convolutional-neural-network-in-natural-language-processing-96d67f91275c)

用蜂鸟增压你的浅 ML 模型

原文:https://towardsdatascience.com/supercharge-your-shallow-ml-models-with-hummingbird-cdad2069e489?source=collection_archive---------59-----------------------

用一行代码弥合传统和深度学习之间的差距

利瓦伊·琼斯在 Unsplash 上的照片

动机

自从 2012 年深度学习的最近一次复兴以来,大量新的 ML 库和框架已经被创建。那些经受住时间考验的公司(PyTorch、Tensorflow、ONNX 等)得到了大型公司的支持,可能不会很快消失。

然而,这也带来了一个问题,因为深度学习社区已经偏离了流行的传统 ML 软件库,如 scikit-learn、XGBoost 和 LightGBM。当公司需要将具有不同软件和硬件假设的多种模型投入生产时,事情变得…令人毛骨悚然。

  • 当一些模型是基于张量的,而另一些是基于向量的,你如何保持 ML 推理代码干燥
  • 当基于 GPU 的神经网络开始围绕传统模型运行时,如何保持传统模型的推理运行效率具有竞争力?

寻找统一的模型服务界面

我知道,我知道。在 Kubernetes 中使用微服务可以通过保持事物的解耦在一定程度上解决设计模式问题…如果这是你想要的吗?

但是,我认为这真的忽略了问题。如果您想无缝部署 XGBoost 回归器或全连接 DNN 作为服务的主要输出,该怎么办?当然,你可以热交换你的服务启动的硬件。代码怎么样?

根据模型的类型,您是否打算使用一个精心设计的 if-else 开关来使用一个软件框架而不是另一个?

XGBoost/LightGBM 还不够快吗?

嗯,对于很多用例来说,就是。然而,在需要神经网络的问题和可以用更传统的模型充分解决的问题之间仍然存在巨大的差距。对于更传统的模型,难道你不希望能够使用最新和最伟大的计算框架来支持你的模型的预测吗?这将允许您在需要通过冗余实例将模型向外扩展之前,将模型向上扩展更多。

输入蜂鸟

微软研究院引入了hummingbird来弥合面向 CPU 的模型和面向张量的模型之间的差距。该库简单地采用任何我们已经训练好的传统模型,并返回一个基于张量计算的模型版本。Hummingbird 旨在解决当前 ML 应用程序的两个核心问题:

  1. 传统和深度学习软件库对其基本计算单元(向量与张量)有不同的抽象。
  2. 这种差异的结果是,传统的 ML 库没有获得与硬件加速器(读:GPU)相同的性能增益。

有了蜂鸟,你的 ML 管道将开始看起来更干净。你会知道,不管算法如何,你最终会得到一个通过张量计算来创建预测的模型。不仅如此,这些张量计算将由您的组织可能已经效忠的同一深度学习框架来运行。

所有这些都来自一个函数调用。在我看来,这是一笔不错的交易!

让我们看看它的实际效果。

设置

让我们把这部分去掉。你知道该怎么做。

确保再现性

让我们用宇宙万物的答案来控制 Numpy 和 PyTorch 中的随机性。

召唤一些数据

让我们定义一个快速助手来快速制作一些分类数据,并用它创建一些数据集。

多亏了 Deepnote,我不必占用这个笔记本的一半来为你打印数据形状和分布。这些笔记本配备了功能丰富的变量资源管理器,它提供了大多数关于数据的基本 EDA 风格的问题。

查看本文的原始版本,了解 Deepnote 如何从他们的 Jupyter 风格的笔记本中自动创建漂亮的文章。

把鸟带进来

现在,通过 Hummingbird 将您的模型转换成张量计算的一行程序是convert(clf, 'pytorch')

就是这样。那是蜂鸟。

为了使我们的比较更加容易,让我们在此基础上创建一个快速的方法,当它可用时自动将其移动到 GPU。作为一些最终添加的糖,我们将接受一个标志,如果需要的话,强制将模型保存在 CPU 上。但是请记住,对convert()的单一调用是您需要拥有的与蜂鸟的唯一接口;它在单个函数调用的掩护下完成了它所有的魔法。一旦您得到返回给您的模型,您就像任何其他传统的 pythonic ML 模型一样对它调用predict()

拿出你们的手表,时间到了

好了,是时候进行基准测试了!不要担心一连串的导入或方法包装。让我们用%%timeit魔法命令保持简单。这个神奇的命令将自动多次运行单元中的代码,报告运行时样本的平均值和标准偏差。首先,我们将按原样计时sklearn模型。然后,我们将看到蜂鸟在 CPU 上的模型和在 GPU 上的模型如何比较。

Original:        136 ms ± 1.59 ms per loop
Hummingbird CPU: 1.81 s ± 16.1 ms per loop

来源:吉菲

呀!

嗯……这真是出乎意料。关于这一点没有两种方法:对于某些数据集,Hummingbird 可能在 CPU 上运行得更慢。这甚至可以在他们当前的一些蜂鸟 Github repo 示例笔记本中看到。此外,我确实有意提到了在某些数据集上运行时较慢,因为它确实优于其他数据集。

也就是说,这个副作用不应该让任何人跑向门口——记住图书馆的目标!将模型转换为张量计算的主要原因是利用硬件,而硬件在这方面优于

剧透提示:我说的是 GPU!这款 Deepnote 笔记本由 NVIDIA T4 张量核心 GPU 驱动。让我们看看模型如何在上运行。

Original:        136 ms ± 1.59 ms per loop
Hummingbird CPU: 1.81 s ± 16.1 ms per loop
Hummingbird GPU: 36.6 ms ± 65.8 µs per loop

我们走吧!现在,我们不仅比原来有了 73%的平均加速,而且还有一个数量级的更小的方差。运行时的原始标准差是其均值的 1.1%,GPU 运行时的标准差是 0.18%!

来源: Giphy

以速度保证质量

不过,暂时不要激动。你的模型可能拥有世界上最快的运行时间;如果它不能在转换过程中保持精度,它就完全没用了。让我们看看原始模型和两个转换后的模型之间的预测是如何比较的。为此,我们求助于我最喜欢的可视化库之一,seaborn

原始模型和蜂鸟模型之间预测差异的分布

有意思…

一点也不差。基于 CPU 的模型的增量分布在零附近相当对称,3σ(注意轴刻度)在 1e-7 附近。基于 GPU 的模型的增量分布也有类似的小偏差,但显示出非零偏差和偏斜!这当然是有趣的行为,激起了好奇的心,但它仍然是一个小细节,除了最精确敏感的模型。

陪审团已经决定:蜂鸟在加速的同时也提供了精确性👍。

看看下面微软的一些大规模比较。🚀

来源:微软研究院

顶端的樱桃

哦,顺便说一句,你还可以自动加入所有未来的计算优化,这些优化来自于成千上万受雇于这些巨型框架的人。随着对不太受欢迎的框架的支持逐渐消失(相信我,这最终会发生),你会舒服地坐着,知道你的每一个模型都运行在良好支持的基于张量的推理框架上。

毕竟,我们从事的是数据科学,而不是运行时优化。利用大人物来完成该领域的工作感觉很好,让我们可以专注于我们的核心竞争力。

结论

正如微软研究院最近的许多其他举措一样,我对蜂鸟感到兴奋。在快速分化的 ML 空间中,这是走向整合的一大步,从混乱中获得一些秩序总是一件好事。我确信,随着时间的推移,他们基于 CPU 的推理的运行时停顿将被消除,同时确保 GPU 的持续优势。当他们进行更新时,我们只需点击几下鼠标,就可以使用支持 GPU 的 Deepnote 笔记本来测试他们的声明!

潜入蜂鸟

使用蜂鸟和 Deepnote

用数据解读更多生活

原载于https://beta.deepnote.com

基于 Neo4j 数据的 LynxKite 超级数据科学

原文:https://towardsdatascience.com/supercharged-data-science-with-lynxkite-on-neo4j-data-11cd0fa10f41?source=collection_archive---------45-----------------------

如果您有一个 Neo4j 数据库,那么您已经完成了您的图表之旅中的几个重要步骤:您知道如何将您的业务(的某些方面)建模为一个图表,可能您已经在使用您的数据进行特别的图表查询、本地调查,或者甚至在您的操作中!

但是,就像你不会在面向表的数据科学中直接使用 SQL 数据库一样,如果你想在一个复杂的、迭代的图形数据科学项目中取得成功,你需要的不仅仅是一个图形数据库。

在一个传统的、面向表格的项目中,你可以使用像 Pandas 或 Python 的 Spark 这样的东西,加入像 PyTorch 这样的 ML 框架,或者使用像 RapidMiner 或 Dataiku 这样的集成数据科学工具。但是无论您选择什么工具,您都将使用数据的快照,并且最终会得到一个包含许多相互依赖的操作的复杂工作流。

然而,如果你手头有一个严肃的图形项目,你应该转向 LynxKite !现在,我们的新 Neo4j 连接器让这一切变得非常简单。

为了记录,如果你想做图形数据科学,但是你还没有一个图形数据库,那也完全没问题。您可以直接使用 LynxKite 将传统数据转换成图表。但是这篇文章不是关于这个的。

现在让我们详细考虑一个简单但典型的图表数据科学工作。以 Neo4j 的 Northwind 数据集为例。(只需在你的 Neo4j 浏览器中输入:play northwind-graph,按照提示操作即可获得。)这是一个代表客户订单历史的图表。它包含客户、订单、产品、产品类别和供应商的节点。我们想要实现的是,根据同一顾客购买产品的频率,识别出迎合相似“口味”的产品组。

获取数据

首先,让我们将数据导入 LynxKite!使用新的 Neo4j 导入框非常简单:

(截图作者)

你只需在你的 LynxKite 工作区上放下一个[Import from Neo4j](https://lynxkite.com/docs/latest/user-guide/#import-from-neo4j)框,设置好你的连接参数,按下Import,你就可以开始了。

如果保留查询的默认值,则会导入所有数据。在本例中,我们通过添加 WHERE 子句修改了节点查询:现在我们只对订单和产品感兴趣。

以下是导入图形的一个小示例:

(截图作者)

在左边,您可以看到两个订单,右边是订购的产品。

图形转换

您很少想要在一个图形上运行固定图形算法,因为它在您的生产系统中是可用的。通常你想要一些结构上的改变,你想要实际的算法在一个修改过的图上运行。

值得注意的是,这些步骤构成了数据科学项目不可或缺的一部分,我们经常希望对它们进行大量迭代。在 LynxKite 中,这些步骤是您的分析工作流中的一等公民。您可以轻松地更改细节,并可以轻松地重新运行整个下游分析。如果你直接在一个 graph DB 中这样做,那么你将不得不在每次迭代中经历痛苦的清理和图形重建。

在我们的具体例子中,我们想从一个订单-产品二分图发展到一个只包含产品的图,其中边代表购买了两种相关产品的客户的数量。我们执行以下转换步骤:

  1. 我们根据客户 id 合并订单:对于这个分析,我们不关心在同一个订单中购买了哪些产品,只关心相同的客户。
  2. 我们添加反向边,然后计算三元闭包。这样,我们在产品中得到我们想要的边,除了我们还为每个产品创建了一串循环边。所以我们删除了它们,并且只保留代表产品的节点,而不是(合并的)订单。
  3. 最后,我们将所有平行边合并成单条边,并保留原始平行边的基数作为边属性。我们也只保留代表足够频繁的共享客户的边。

我们可以通过在工作区放几个盒子来完成以上所有的工作。以下是图形转换的完整流程:

(截图作者)

这是结果图的一个示例:

(作者截图)

查找和标记聚类

现在我们已经有了想要的图,对它运行一个聚类算法是很简单的,我们只需放入一个[Find modular clustering](https://lynxkite.com/docs/latest/user-guide/#find-modular-clustering)框:

(作者截图)

好吧,我们后来做了一点调整:我们删除了非常小的集群,我们将产品的边复制到产品集群,这样我们就可以看到不同集群之间的相关性。以下是完整的流程:

(截图作者)

我们基本上完成了,但让我们再做一个整容改进!让我们为每个集群找出最重要的产品,并使用该产品的名称作为我们集群的标签。这很简单:我们只需在产品图上计算 PageRank,并为所有集群取最高 PageRank 产品的名称:

(截图作者)

现在是时候惊叹我们(不那么)努力的成果了!这是一个可视化图,显示了所有有趣的带标签的集群(右侧),以及一个集群的成员(左侧):

(截图作者)

有趣的是,几乎所有的集群都是由某种奶酪主导的…我一直都知道,奶酪就是石头!

回到 Neo4j

为了结束这个循环,让我们将分析结果返回到数据库中!我们需要两个简单的准备步骤。我们为聚合标签属性取了一个更好的名字,这是我们希望在数据库中看到的。然后,我们将它从集群移至其所有成员。最后,我们应用一个 Neo4j 导出框:

(截图作者)

事实上,集群标签如预期的那样出现在 Neo4j 中!

(截图作者)

在这种情况下,我们想要将顶点属性导出回数据库,但是也可以用边属性做同样的事情,或者你甚至可以将一个完整的图形推送到数据库。

全部用代码编写

我们的经验是,迭代的、探索性的图形数据科学可以在 UI 上更有效地完成:更容易改变事物,在任何点检查值和元数据,不需要记住参数名,等等。也就是说,有些人更喜欢编码,这也是数据科学管道自动化生产部署的唯一合理方式。

对于这些情况,我们提供了强大而简单的 Python API 。仅为了演示,无需进一步解释,请参见下面执行上述完整分析的 python 代码。

概述

我们在 Northwind 数据集上进行了简单但有趣的分析。但这里的要点不是关于这个分析的具体细节,也不是结果。我们想要展示的是,为什么即使是一个相当简单的项目也需要一些步骤和功能,而这些步骤和功能在一个实时的、事务性的图形数据库中是不可能或非常麻烦的。

但是我们带来了好消息!现在有了我们的新连接器,在 Neo4j 实例上使用免费、开源的 LynxKite 来进行高效、舒适的图形数据科学变得非常容易!

通过提升模型提升客户接触点

原文:https://towardsdatascience.com/supercharging-customer-touchpoints-with-uplift-modeling-9913ddf62c1?source=collection_archive---------29-----------------------

介绍一种预测个体治疗效果的强大方法,使用 pandas 和 XGBoost 的 Python 中的合成数据。

图片来自 Pixabay

在这篇文章中,我将介绍提升建模的概念,并举例说明为什么它是数据科学家增加业务价值的工具箱中的一个重要部分。然后,我将展示一种构建提升模型的简单方法,并使用 Python 中的合成数据演示几个提升模型评估指标。

这篇文章在 Github 上以 Jupyter 笔记本的形式发布。

介绍

在机器学习可以为企业创造价值的无数方式中,与监督分类或回归等方法相比,提升建模是鲜为人知的方式之一。但是对于许多用例来说,它可能是最有效的建模技术。在任何情况下,企业可以针对不同的客户有选择地采取代价高昂的行动,以期影响他们的行为,提升建模应该是确定战略的有力候选。这是因为提升建模旨在找到受行动影响最大的客户子集。识别这个细分市场对于在商业策略中最大化投资回报是很重要的。

例如,在提供优惠券时,企业可能会遭受收入损失:如果客户购买并使用优惠券,收入会因优惠券的价值而减少。但是,如果优惠券说服顾客购买,而他们本来不会购买,那么它可能仍然是值得的。在提升建模的术语中,这些类型的客户被称为“可说服的”,提升建模将事情分解为有“待遇”和没有“待遇”的客户行为,在本例中,待遇是接收优惠券。

经易和弗罗斯特许可使用的图片(2018)

提升建模的目标,也称为净提升或增量响应建模,是为了确定“可说服的”,而不是在“确定的事情”和“失败的原因”上浪费精力,并避免打扰“睡觉的狗”,或那些对治疗有负面反应的人,如果他们存在的话。提升建模已经在许多领域得到应用,包括营销,这里展示的经典用例,以及讨债政治活动

隆起建模的数据:实验是关键

现在我们知道了隆起建模的目标,我们如何实现它呢?构建提升模型的典型起点是来自随机对照实验的数据集:我们需要一个代表治疗组和未接受治疗的对照组中所有不同类型客户的样本。如果治疗组中购买的顾客比例明显高于对照组,我们知道促销是“起作用的”,因为它鼓励所有顾客平均购买。这就是所谓的平均治疗效果(ATE)。量化 ATE 是 A/B 测试的典型结果。

然而,可能只有治疗组中的一部分客户对我们观察到的大部分 ATE 负责。举个极端的例子,也许治疗组中一半的顾客负责整个 ATE,而促销对另一半没有影响。如果我们有办法提前确定哪些顾客更容易接受治疗,那么我们就能把资源集中在他们身上,而不是把时间浪费在那些治疗效果很小或没有效果的人身上。我们可能需要找到其他促销活动来吸引不响应者。在确定因人而异的可变治疗效果的过程中,以这些人拥有的不同特质为条件,我们在寻找个体治疗效果(ITE),也称为条件平均治疗效果(凯特)。这就是机器学习和预测建模发挥作用的地方。

模型的力学

构建提升模型的经典技术是为单个客户预测如果他们得到治疗,他们购买的可能性,以及如果他们没有得到治疗,他们购买的可能性。然后将这两个概率相减以获得提升:如果给予治疗,购买的可能性会增加多少?这可以通过两种方式实现,在这两种情况下,模型的二元响应变量是顾客在治疗后是否进行了购买:

  • 将治疗组和对照组集合成一个数据集,并训练一个单一模型,其中治疗是二元特征。在推断阶段,模型用于对每个实例进行两次预测,第一次处理= 1,第二次处理= 0。这被称为“S-Learner”方法,因为它使用单一模型。
  • 为治疗组和对照组训练单独的模型。在推理阶段,治疗和控制模型都用于获得每个实例的预测。这被称为“T-Learner”方法,因为它使用了两种模型。

下面的示意图总结了这两种方法:

这些方法在关于隆起建模和因果推断的文献中有广泛记载(Lee 等人,2013 年 Gutierrez 和 Gerardy,2016 年)。它们具有相对简单和直观的优势,可以使用许多数据科学家熟悉的二进制分类建模技术以及 SAS 等企业软件中的专用包来实现(Lee et al. 2013)。与此同时,因果推理是机器学习中一个活跃的研究领域,其他方法可能会实现更好的模型性能。不同的方法包括旨在提升的基于树的模型(Gutierrez 和 Gerardy 在 2016 年进行了审查)、目标变量转换(Yi 和 Frost 2018 年)以及其他最近的创新,如 X-Learner (Kunzel 等人,2019 年)。

在所有种类中,隆起建模面临一个基本挑战。目标是为单个客户预测治疗后的购买可能性,以及未治疗时的购买可能性,以计算提价。但在现实中,我们从来没有观察到一个人既接受治疗又没有接受治疗的结果,因为这是不可能的!有人要么接受治疗,要么不接受。在数学建模中,如果我们不能观察到我们感兴趣的所有结果,这通常是一个问题。这一挑战说明了提升建模的反事实性质,以及随机实验对了解所有类型客户的美食的重要性。

图片来自 Pixabay

Gutierrez 和 Gerardy (2016)总结了这一挑战,并指出了前进的方向:

估算客户提升既是一个因果推理,也是一个机器学习问题。这是一个因果推理问题,因为人们需要估计两个结果之间的差异,这两个结果对一个人来说是互斥的(要么人收到了一封促销电子邮件,要么没有收到)。为了克服这种反事实的性质,提升建模主要依赖于随机实验,即随机分配客户接受治疗(治疗组)或不接受治疗(对照组)。隆起建模也是一个机器学习问题,因为人们需要训练不同的模型,并根据一些性能指标选择产生最可靠隆起预测的模型。这需要明智的交叉验证策略以及潜在的功能工程。

让我们通过构建一个 S-Learner 模型并对其进行评估,使用一个示例数据集来探索这些概念。

*# load packages* import numpy **as** np
import pandas **as** pd

from statsmodels.stats.proportion import proportions_ztest

import sklearn **as** sk
from sklearn.metrics import auc
import xgboost **as** xgb

import matplotlib **as** mpl
import matplotlib.pyplot **as** plt
**%**matplotlib inline

import pickle

示例数据集

建立提升模型最直接的方法是从随机对照实验的数据开始。这样,治疗组和对照组都应该有一个具有代表性的顾客群体样本。在设计的实验之外,如果一个自然控制群体作为企业正常经营的一部分存在,准实验数据可能是可用的。治疗组和对照组也可以通过一种称为倾向评分匹配的技术来近似,该技术在 causaml 包中可用,该包还提供了一套提升建模工具(causaml)。

在这里,我们使用来自最近出版物(赵等人,2020 年)的合成数据,这些数据在这里公开提供。这些数据模拟了在治疗组和对照组之间平均分配的设计实验。我们只加载该数据集中的前 10,000 行,这是“100 次试验(用不同的随机种子重复)”中的第一次。数据集的构建使得一些特征可以预测结果,一些特征不提供信息,一些特征可以具体预测治疗效果。

我们感兴趣的列是treatment_group_key,它标识客户是否接受了治疗;conversion,如果客户进行了购买,则为 1;如果没有,则为 0;以及 36 个合成特征,它们都以x开头。在真实数据中,这些特征可能对应于客户购买历史、人口统计数据以及数据科学家可能设计的其他数量,假设它们在建模提升中有用。

让我们加载数据并简单地研究一下。

df **=** pd.read_csv('data/uplift_synthetic_data_100trials.csv', nrows**=**10000)df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10000 entries, 0 to 9999
Data columns (total 43 columns):
 #   Column                      Non-Null Count  Dtype  
---  ------                      --------------  -----  
 0   Unnamed: 0                  10000 non-null  int64  
 1   trial_id                    10000 non-null  int64  
 2   treatment_group_key         10000 non-null  object 
 3   conversion                  10000 non-null  int64  
 4   control_conversion_prob     10000 non-null  float64
 5   treatment1_conversion_prob  10000 non-null  float64
 6   treatment1_true_effect      10000 non-null  float64
 7   x1_informative              10000 non-null  float64
 8   x2_informative              10000 non-null  float64
 9   x3_informative              10000 non-null  float64
 ...
 42  x36_uplift_increase         10000 non-null  float64
dtypes: float64(39), int64(3), object(1)
memory usage: 3.3+ MBdf.head()

这一万条记录中,有多少是治疗组的,有多少是对照组的?

df['treatment_group_key'].value_counts()control       5000
treatment1    5000
Name: treatment_group_key, dtype: int64

有五五分成。让我们将治疗变量编码为二进制 0/1:

df['treatment_group_key'] **=** df['treatment_group_key'].map(
    arg**=**{'control':0, 'treatment1':1})

分析实验结果

总转化率是多少?

df['conversion'].mean()0.3191

与对照组相比,治疗组的转化率是多少?

exp_results_df **=** \
df.groupby('treatment_group_key').agg({'conversion':['mean', 'sum',
    'count']})
exp_results_df

(exp_results_df.loc[1,('conversion', 'mean')] \
    **-** exp_results_df.loc[0,('conversion', 'mean')]).round(4)0.1042

治疗组的转化率(37%)明显高于对照组(27%),表明该治疗在鼓励转化率方面是有效的:ate 为阳性,约为 10%。

在真实数据中,差异通常不是很大,通常进行显著性检验来确定 A/B 检验的结果。

proportions_ztest(count**=**exp_results_df[('conversion', 'sum')],
                  nobs**=**exp_results_df[('conversion', 'count')])(-11.177190529878043, 5.273302441543889e-29)

p 值是从比例测试中返回的第二个数量,它比 0.05 小得多,或者比用于确定显著性的任何其他阈值都小得多。所以我们知道有一个重要的 ATE。这是隆起建模的典型起点。如果我们观察到这种处理没有增加转化率,虽然理论上有可能使用提升模型找到一个有说服力的客户群,但实际上这可能不值得努力。这可能取决于手头的具体问题。

然而,在我们的案例中,在观察到显著的治疗效果后,我们继续使用隆起建模来寻找 CATE,看看我们是否能确定那些有说服力的证据。

构建提升模型

这里我将使用一个XGBClassifier来训练一个 S-Learner;即包括所有特征的单个模型,其中治疗指示也是一个特征。我将数据分成训练集和验证集(80/20 分割),以便尽早停止。我还将使用验证集来说明模型评估指标。在一个真实的项目中,应该从这个过程中保留一个测试集,测试集上的评估度量将用于模型的最终评估。

train, valid **=** sk.model_selection.train_test_split(
    df, test_size**=**0.2,random_state**=**42)**print**(train.shape, valid.shape)(8000, 43) (2000, 43)

将功能指定为列表。这包括治疗栏和所有功能,从第 8 栏开始:

features **=** ['treatment_group_key'] **+** df.columns.tolist()[7:]**print**(features)['treatment_group_key', 'x1_informative', 'x2_informative', 'x3_informative',... 'x36_uplift_increase']

组合用于训练 XGBoost 分类器的训练集和验证集:

X_train **=** train[features]
y_train **=** train['conversion']
X_valid **=** valid[features]
y_valid **=** valid['conversion']eval_set **=** [(X_train, y_train), (X_valid, y_valid)]

现在是实例化和训练模型的时候了。

model **=** xgb.XGBClassifier(learning_rate **=** 0.1,
                          max_depth **=** 6,
                          min_child_weight **=** 100,
                          objective **=** 'binary:logistic',
                          seed **=** 42,
                          gamma **=** 0.1,
                          silent **=** True,
                          n_jobs**=**2)**%%**time
model.fit(X_train, y_train, eval_set**=**eval_set,\
          eval_metric**=**"auc", verbose**=**True, early_stopping_rounds**=**30)[0]	validation_0-auc:0.693049	validation_1-auc:0.648941
Multiple eval metrics have been passed: 'validation_1-auc' will be used for early stopping.

Will train until validation_1-auc hasn't improved in 30 rounds.
[1]	validation_0-auc:0.718238	validation_1-auc:0.656877
[2]	validation_0-auc:0.72416	validation_1-auc:0.667244
[3]	validation_0-auc:0.727643	validation_1-auc:0.669992
...
[99]	validation_0-auc:0.852237	validation_1-auc:0.762969
CPU times: user 6.7 s, sys: 87.8 ms, total: 6.79 s
Wall time: 3.48 s

XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,
              colsample_bynode=1, colsample_bytree=1, gamma=0.1,
              learning_rate=0.1, max_delta_step=0, max_depth=6,
              min_child_weight=100, missing=None, n_estimators=10,
              n_jobs=2, nthread=None, objective='binary:logistic',
              random_state=0, reg_alpha=0, reg_lambda=1,
              scale_pos_weight=1, seed=42, silent=True, subsample=1,
              verbosity=1)

训练过程完成,我们可以看到该模型具有相当高的验证 AUC。训练 AUC 甚至比这更高,这意味着从技术上来说模型是过度拟合的。通常我会进行超参数搜索,但我发现这里使用的值可以提供合理的结果,以便用该数据集说明隆起建模。

作为一个实用的旁注,我发现在某些情况下,当使用 T-Learner(这里没有显示)时,在计算提升时,过度适应训练集可能会导致意想不到的结果。根据我的经验,这个问题可以通过减少max_depth或增加XGBClassifier中的min_child_weight来解决,换句话说就是减少过度拟合的数量。

在模型构建中要考虑的另一点是特征选择,我在这里省略了。在隆起建模的上下文中,可以使用下面在验证集上介绍的隆起模型评估度量作为选择特征的方式,例如通过递归特征消除。隆起模型的特征选择也是最近研究的主题,包括本文所用数据集的来源(赵等人,2020)。

模型评估

现在,我们有了提升模型。如果你已经熟悉二进制分类,那么为一个 S 型学习者建立模型是非常简单的。为了实际计算给定数据集的提升,使用这种方法,我们需要对模型进行两次评分,一次处理= 1,另一次处理= 0,然后减去这两次得到提升。在这里,我们对验证集执行此操作,然后绘制提升分数的直方图。

X_valid_0 **=** X_valid.copy(); X_valid_0['treatment_group_key'] **=** 0
X_valid_1 **=** X_valid.copy(); X_valid_1['treatment_group_key'] **=** 1
Uplift **=** model.predict_proba(X_valid_1)[:,1]\
    **-** model.predict_proba(X_valid_0)[:,1]mpl.rcParams['figure.dpi'] **=** 200
mpl.rcParams['figure.figsize'] **=** (6,4)
plt.hist(Uplift, bins**=**50)
plt.xlabel('Uplift score')
plt.ylabel('Number of observations in validation set')

隆起的分布大部分是正的,这是有意义的,因为我们从对实验的分析中知道,平均而言,治疗鼓励转化。然而,一些例子有负面的提升,意味着治疗实际上不鼓励一些人的 T2 转变。换句话说,在这些数据中似乎存在一种睡狗效应。

现在的主要问题是:我们应该相信这些结果吗?我们怎么知道这个模型有多好?提升模型评估的指标比监督学习中使用的典型指标更复杂,例如用于分类任务的 ROC AUC 或用于回归的 RMSE。一般来说,对于不同范围的预测上升分数,上升评价指标对治疗组和对照组之间的转换率进行了比较。对于那些具有高提升分数的患者,我们期望看到治疗组和对照组之间的较大差异,而那些具有较低提升分数的患者应该具有较小的差异,或者甚至在对照组中具有较大的转化率(即负差异)。

分位数度量

评估提升模型的一种流行方法是使用分位数图。这将给出模型是否“工作”的快速视觉印象,在倾斜真实隆起的意义上。为了创建分位数图表,我们从验证集的提升预测开始,并根据这些分数将实例分成分位数。分位数的数量取决于我们有多少数据,尽管实际上 10 是一个非常典型的数字(十分位数)。然后,在每个箱中,我们会发现治疗组和对照组的转换率的差异。如果模型运行良好,我们应该在最高的十分位数中看到较大的正差异,在最低的十分位数中减少到小的或负的差异(即治疗率类似于控制率,或低于控制率)。换句话说,随着预测的隆起增加,从对照组到治疗组的真实隆起也应该增加。

获取分数分位数

从验证数据创建一个新的DataFrame,以添加提升分数和分位数。

Uplift.shape(2000,)valid.shape(2000, 43)valid_w_score **=** valid.copy()
valid_w_score['Uplift score'] **=** Upliftvalid_w_score.head()

检查验证集的治疗组和对照组是否大致平衡(它们应该是平衡的,因为我们使用了随机训练/验证分割,但检查总是好的):

valid_w_score['treatment_group_key'].value_counts()0    1011
1     989
Name: treatment_group_key, dtype: int64

现在,使用整个验证集(治疗组和对照组一起),为提升分数分位数制作标签。我们将检查治疗组和对照组在分位数内是否平衡,因为我们将按分位数和治疗方法分割数据以创建图表。Pandas 有一个方便的功能,可以根据输入序列中的一个观察值属于哪个分位数来生成一系列标签。

score_quantiles, score_quantile_bins **=** \
pd.qcut(x**=**valid_w_score['Uplift score'],
        q**=**10,
        retbins**=**True,
        duplicates**=**'drop')

从这个函数中,我们得到一个列,指示每个实例属于哪个分位数,由 bin 边缘表示:

score_quantiles.head()6252    (-0.00339, 0.0186]
4684    (-0.114, -0.00339]
1731        (0.201, 0.398]
4742        (0.121, 0.148]
4521      (0.0391, 0.0548]
Name: Uplift score, dtype: category
Categories (10, interval[float64]): [(-0.114, -0.00339] < (-0.00339, 0.0186]...

我们还在score_quantile_bins中获得了所有面元边缘的列表,但是我们在这里不需要它。现在,让我们将分数分位数添加到数据帧中,以便我们可以使用它进行分析。

valid_w_score['Quantile bin'] **=** score_quantiles
valid_w_score[[
    'treatment_group_key', 'conversion', 'Uplift score',
    'Quantile bin']].head(10)

使用 groupby/count 和一些多指数魔术,检查分位数区间内的处理和对照观察值是否相似:

count_by_quantile_and_treatment **=** valid_w_score.groupby(
    ['Quantile bin', 'treatment_group_key']) \
    ['treatment_group_key'].count()
count_by_quantile_and_treatment **= \** count_by_quantile_and_treatment.unstack(**-**1)
count_by_quantile_and_treatment

count_by_quantile_and_treatment.plot.barh()
plt.xlabel('Number of observations')

不太精确地说,就治疗和控制的比例而言,分数分位数似乎并不不平衡;它们在每个箱中是相似的。这是意料之中的,因为我们正在处理来自随机实验的数据,然而再次检查这样的假设是好的。

上升分位数图表

上升分位数图。我们将首先创建一个可用于治疗组的遮罩:

validation_treatment_mask **=** \
valid_w_score['treatment_group_key'] **==** 1

然后,我们分别为治疗组和对照组获得提升分数分位数内的转换率:

treatment_by_quantile **=** valid_w_score[validation_treatment_mask]\
    .groupby('Quantile bin')['conversion'].mean()
control_by_quantile **=** valid_w_score[**~**validation_treatment_mask]\
    .groupby('Quantile bin')['conversion'].mean()

最后,我们计算它们的差异,这是每个分数分位数内的真实提升。

true_uplift_by_quantile **=** treatment_by_quantile **-** \
    control_by_quantile
true_uplift_by_quantile.head(5)Quantile bin
(-0.114, -0.00339]   -0.017486
(-0.00339, 0.0186]    0.034343
(0.0186, 0.0391]     -0.004600
(0.0391, 0.0548]      0.021554
(0.0548, 0.0726]      0.133929
Name: conversion, dtype: float64

现在我们有了绘制上升分位数图表所需的所有信息。

true_uplift_by_quantile.plot.barh()
plt.xlabel('True uplift')

上升分位数图表显示,在很大程度上,真实的上升从较低的分数仓增加到较高的分数仓,这是我们期望看到的模型是否有效。因此,看来我们的模型可以有效地细分出更容易对治疗做出反应的客户。在实际项目中,对保留的测试集重复这种分析是很重要的,以确认模型使用的数据根本没有用于模型训练,因为从技术上讲,这种验证集用于模型拟合过程中的早期停止。然而,验证集上的良好性能是一个好迹象,只要测试集与训练集和验证集具有相似的特征,我们就希望在那里看到相似的性能。

我们能从分位数图中学到什么?通过对实验的分析,我们知道 ATE 约为 10%。我们用验证集创建的分位数图告诉我们,通过瞄准提升分数的前十分位数,我们可以实现超过 35%的治疗效果,这是一个显著的增加。接下来的几个十分位数似乎也比 ATE 有更大的治疗效果。根据治疗费用的高低,利用这些信息针对有限的人群可能是有意义的。

我们还可以从对真实隆起的观察中看到睡狗效应的一些支持。分数最低的十分位数,完全由负分组成,实际上有负的真实上升。因此,通过提升分数,瞄准底层 10%的人口,实际上对业务有负面影响。

提升校准

虽然提升分位数图提供了一个定性的快照,告诉我们该模型在细分客户方面是否有效,但我们可以在这个方向上更进一步,并询问该模型在预测提升方面的准确性如何。这是校准过程,为此我们需要分数分位数内的平均预测提升:

predicted_uplift_by_quantile **=** valid_w_score\
    .groupby(['Quantile bin'])['Uplift score'].mean()
predicted_uplift_by_quantile.head(5)Quantile bin
(-0.114, -0.00339]   -0.035133
(-0.00339, 0.0186]    0.008385
(0.0186, 0.0391]      0.029582
(0.0391, 0.0548]      0.047033
(0.0548, 0.0726]      0.063634
Name: Uplift score, dtype: float32

我们将把这些数据和我们上面计算的真实上升量放在一个DataFrame中,以创建一个散点图。如果隆起预测是准确的,那么预测隆起和真实隆起的散点图应该接近一对一线。

pred_true_uplift **=** pd.DataFrame({'Predicted Uplift':predicted_uplift_by_quantile,
                                 'True Uplift':true_uplift_by_quantile})

min_on_plot **=** pred_true_uplift.min().min()
max_on_plot **=** pred_true_uplift.max().max()

ax **=** plt.axes()
ax.plot([min_on_plot, max_on_plot], [min_on_plot, max_on_plot],
        linestyle**=**'--', color**=**'tab:orange', label**=**'One-one line')
pred_true_uplift.plot.scatter(x**=**'Predicted Uplift', y**=**'True Uplift',
                              ax**=**ax, label**=**'Model performance')

ax.legend()

从定性角度来看,我们可以从校准图中看到,平均预测上升接近真实上升,按分位数计算。通过计算某种度量,也许是 MAE(平均绝对误差),作为模型拟合优度的度量,可以使这种校准更加精确。

这些基于分位数的分析还有其他一些扩展方式:

  • 用于计算升高的治疗= 1 和治疗= 0 的预测值,可以分别在治疗组和对照组中根据这些分数的十分位数分别校准转换率。这将是对这些群体的预测转化概率的校准。
  • 误差线可以包含在所有的图上。对于预测的转化概率,可以分别计算治疗组和对照组的每个箱内平均值的标准误差,而对于真实的转化率,可以使用二项式的正态近似值。然后,当减去处理和控制的平均值以获得上升时,将添加基于这些计算的方差,并且可以在每个箱内计算上升的标准误差。
  • 在商业情况下,应该知道治疗的成本和转换的预期收入。提升分位数图可以扩展为代表收入的提升,这可以与治疗成本相平衡,以评估商业策略的盈利能力。

累积指标

累积增益图

在实践中使用提升分数时,一种常见的方法是根据客户的提升分数按降序排列客户。我们可以扩展分位数图的概念,通过这种方式,计算通过瞄准特定部分的人口,我们可以获得多少额外的客户(“增量客户”)。

这个想法是累积收益图的基础。Gutierrez 和 Gerardy (2016)给出的累积增益公式为:

其中 Yᵀ 是处理组每个 bin 中的累计转化数,从最高分 bin 开始向下,而 Nᵀ 是以相同方式找到的客户的累计数量; Y^CN^C 是对照组相似的累积和。累积收益有效地衡量了转化概率的累积提升,从最高 bin 开始,乘以治疗组和对照组的总客户数,以估计如果目标客户数达到该数量,将会发生的额外转化数。

为了获得累积收益图的数据,我们需要计算治疗组和对照组中每个分数分位数 bin 中的客户数量(我们在上文中对此进行了可视化,但在此将重新计算)以及转化客户的总数。在这里,我们将使用.iloc[::-1]将结果颠倒过来,以模拟首先锁定提升分数最高的客户,然后从那里继续下去的策略。

treatment_count_by_quantile **=** valid_w_score[validation_treatment_mask]\
    .groupby('Quantile bin').agg({'conversion':['sum', 'count']}).iloc[::**-**1]

control_count_by_quantile **=** valid_w_score[**~**validation_treatment_mask]\
    .groupby('Quantile bin').agg({'conversion':['sum', 'count']}).iloc[::**-**1]

下面是治疗组的情况,例如:

treatment_count_by_quantile.head(5)

以及转换和客户总数的累计总和:

treatment_count_by_quantile.cumsum().head(5)

将所有这些放入上面所示的累积增益公式中,我们得到:

cumulative_gain **=** \
    ((treatment_count_by_quantile[('conversion','sum')].cumsum()
      **/** treatment_count_by_quantile[('conversion','count')].cumsum())
     **-**
     (control_count_by_quantile[('conversion','sum')].cumsum()
      **/** control_count_by_quantile[('conversion','count')].cumsum()))\
    ***** (treatment_count_by_quantile[('conversion','count')].cumsum()
       **+** control_count_by_quantile[('conversion','count')].cumsum())

我们现在可以检查和绘制累积增益。

cumulative_gain.round()Quantile bin
(0.201, 0.398]         74.0
(0.148, 0.201]        125.0
(0.121, 0.148]        149.0
(0.0941, 0.121]       172.0
(0.0726, 0.0941]      209.0
(0.0548, 0.0726]      237.0
(0.0391, 0.0548]      242.0
(0.0186, 0.0391]      240.0
(-0.00339, 0.0186]    249.0
(-0.114, -0.00339]    248.0
dtype: float64cumulative_gain.plot.barh()
plt.xlabel('Cumulative gain in converted customers')

累积收益提供了另一种方式来看待提升模型导向战略的潜在影响。如果我们向每位顾客提供这种治疗,我们将增加 248 名转化顾客。然而,我们可以获得 149 名客户,约为最大可能的 60%,通过提升分数,只为前 30%的客户(前 3 个十分位数)提供治疗。这是因为随着我们在列表中的下移,我们的目标客户是预测个体治疗效果较低的客户。在图表中价值较低的容器中,累积的转化数量甚至可能从一个容器下降到另一个容器,因为我们实际上因为瞄准睡觉的狗而失去了客户。

累积增益曲线

上面的各种图表都是了解提升模型性能的信息丰富且直观的方式,但是它们不会立即导致模型性能指标,通过这些指标可以比较不同的建模方法。为了实现这一飞跃,可以将累积增益的思想推广到曲线,类似于如何使用接收器操作特性(ROC)曲线来评估二元分类器。为了得到 ROC 曲线,随着阳性分类的阈值被连续提高以在数据集中包括越来越多的实例,直到全部被包括,计算真阳性率和假阳性率。相比之下,累积增益曲线测量目标人群中的累积转化率增益,如上所述,随着越来越多的人成为目标,根据提升分数递减,直到所有人都成为目标。

增益曲线定义为

其中 t 是客户的指数,从最高提升分数开始向下,其他变量的定义与前面的等式类似。

增益曲线计算是 causaml 软件包的一部分,称为提升曲线(causaml)。在熊猫身上也可以算的相当快。第一步是根据提升分数进行排序:

sorted_valid **=** valid_w_score.sort_values('Uplift score',
    ascending**=**False)\
.reset_index(drop**=**True)

sorted_valid[['treatment_group_key', 'conversion',
    'Uplift score']].head(10)

在这个DataFrame上,我们添加了几列,这将使曲线的计算更容易,遵循上面等式中的符号。

sorted_valid['Y_T'] **=** \
    (sorted_valid['conversion'] ***** \
    sorted_valid['treatment_group_key']).cumsum()
sorted_valid['Y_C'] **=** \
    (sorted_valid['conversion'] ***** \
    (sorted_valid['treatment_group_key']**==**0)).cumsum()
sorted_valid['N_T'] **=** sorted_valid['treatment_group_key'].cumsum()
sorted_valid['N_C'] **=** \
    (sorted_valid['treatment_group_key']**==**0).cumsum()sorted_valid[['treatment_group_key', 'conversion', 'Uplift score',
              'Y_T', 'Y_C', 'N_T', 'N_C']].head(10)

现在,增益曲线的计算可以如下进行:

sorted_valid['Gain curve'] **=** (
    (sorted_valid['Y_T']**/**sorted_valid['N_T'])
    **-**
    (sorted_valid['Y_C']**/**sorted_valid['N_C'])
    ) ***** (sorted_valid['N_T'] **+** sorted_valid['N_C'])

让我们来看看增益曲线。

sorted_valid['Gain curve'].plot()
plt.xlabel('Number of customers treated')
plt.ylabel('Gain in conversion')

增益曲线看起来与上面的增益图非常相似(如果它被翻转过来),只是更连续,并且基本上讲述了相同的故事。然而,该曲线的一个优点是,类似于 ROC 曲线,我们可以计算曲线下的面积,解释为更大的面积意味着更好的模型:我们希望能够通过瞄准尽可能少的客户来获得尽可能多的客户。如果我们完全知道谁会对治疗做出积极反应,我们将只治疗那些会做出积极反应的人,上面绘制的增益曲线最初的斜率为 1,然后趋于平稳,如果有睡着的狗,可能会下降。这将导致增益曲线具有陡峭的初始斜率,并尽可能长时间地保持较高,从而导致曲线下的较大区域。

在计算 AUC 之前,归一化数据可能是有益的。如图所示,增益曲线在 x 轴和 y 轴上都有客户单位。这对于用真实世界的数量来可视化事物是很有好处的。然而,如果我们想要评估验证和测试集的性能,例如,这些曲线下的区域可能不可比较,因为这些数据集可能具有不同数量的观察值。我们可以通过缩放曲线来解决这个问题,使 x 轴和 y 轴的最大值都为 1。

缩放的 x 轴代表目标人群的比例:

gain_x **=** sorted_valid.index.values **+** 1
gain_x **=** gain_x**/**gain_x.max()
**print**(gain_x[:3])
**print**(gain_x[**-**3:])[0.0005 0.001  0.0015]
[0.999  0.9995 1\.    ]

缩放后的 y 轴是治疗整个人群的收益比例:

gain_y **=** (
    sorted_valid['Gain curve']
    **/**
    sorted_valid['Gain curve'].tail(1).values
    ).values

**print**(gain_y[:3])
**print**(gain_y[**-**3:])[nan  0\.  0.]
[1.00802087 1.00534686 1\.        ]

注意归一化增益曲线中的第一个条目是NaN;在开始时至少会有一个,因为至少在第一次观察时,n^t_t或 n^c_t会是零,导致被零除的误差。因此,我们将从 x 和 y 向量中删除条目,以消除NaN,如果数据集足够大,这应该不是问题。**

nan_mask **=** np.isnan(gain_y)
gain_x **=** gain_x[**~**nan_mask]
gain_y **=** gain_y[**~**nan_mask]
**print**(gain_y[:3])
**print**(gain_y[**-**3:])[0\.         0\.         0.00805023]
[1.00802087 1.00534686 1\.        ]

现在我们可以绘制归一化增益曲线,以及计算的 AUC。对此,我们将添加一条一对一的线。类似于 ROC 曲线上的一对一直线的解释,这里这对应于我们通过随机对待顾客而在理论上预期的收益曲线:我们通过对待所有顾客而获得的收益部分根据对待的部分和 ATE 而增加。

mpl.rcParams['font.size'] **=** 8
gain_auc **=** auc(gain_x, gain_y)

ax **=** plt.axes()
ax.plot(gain_x, gain_y,
        label**=**'Normalized gain curve, AUC {}'.format(gain_auc.round(2)))
ax.plot([0, 1], [0, 1],
        '--', color**=**'tab:orange',
        label**=**'Random treatment')
ax.set_aspect('equal')
ax.legend()
ax.set_xlabel('Fraction of population treated')
ax.set_ylabel('Fraction of gain in converted customers')
ax.grid()

注意,与 ROC 曲线不同,增益曲线在 y 轴上实际上可以超过 1.0。这是因为,如果我们能避免惹麻烦,我们可能会赢得比请客更多的顾客。

此处计算的 AUC 提供了一种通用方法来比较不同模型和数据集之间的提升模型性能,如给定应用的训练、验证和测试集。归一化增益曲线可以一起绘制,并以监督分类问题中比较 ROC AUCs 的相同方式比较它们的 AUC。感兴趣的读者可能希望开发一个 T-Learner 模型,并与这里作为练习显示的 S-Learner 结果进行比较。

结论

隆起建模的目标是创建个体治疗效果的预测模型。这种模型允许数据科学家将人群分为更可能对治疗有反应的群体和不太可能对治疗有反应的群体。以此为目标,各种建模技术得到了发展;隆起建模继续受到积极的研究兴趣。提升模型的评估不像监督分类或回归模型那样简单,因为它需要单独考虑和比较治疗组和对照组。然而,开源 Python 包(CausalML、Pylift)已经被创建来促进隆起模型的开发和评估。这里使用 Python 和 pandas 演示了几种有用的提升评估技术,其中一些在那些包中可用。

感谢阅读!如果您对使用提升建模解决业务用例感兴趣,包括考虑财务影响、模型可解释性和生产中的监控,请参见我的后续帖子帮助晚期借款人在 Tala 使用提升建模还款。

感谢 Pierre Gutierrez 和 Robert Yi 提供的意见和反馈

参考

causaml:一个 Python 包,提供了一套隆起建模和因果推理方法,使用基于最近研究的机器学习算法。访问时间是 2020 年 7 月 5 日。

古铁雷斯,皮埃尔和让-伊夫·杰拉德迪,2016。因果推理和隆起模型:文献综述。JMLR:研讨会和会议记录 67:1–13。

Kunzel,Soren R .等人,2019 年。使用机器学习评估异质治疗效果的金属学习者。PNAS 2019 年 3 月 5 日 115(10)4156–4165

Lee,Taiyeong 等人,2013 年使用 SAS Enterprise Miner 进行增量响应建模。2013 年 SAS 全球论坛:数据挖掘和文本分析。

Pylift:一个提升库,主要提供(1)快速提升建模实现和(2)评估工具。访问时间是 2020 年 7 月 5 日。

易、罗伯特、威尔·弗罗斯特,2018。Pylift:用于隆起建模的快速 Python 包。访问时间是 2020 年 7 月 5 日。

赵,甄宇等,2020。隆起建模的特征选择方法。

原载于 2020 年 7 月 8 日 https://www.steveklosterman.com

使用 GPU 加速游戏开发使用 Godot 引擎、Kompute 框架和 Vulkan SDK 加速机器学习

原文:https://towardsdatascience.com/supercharging-game-development-with-gpu-accelerated-ml-using-vulkan-kompute-the-godot-game-engine-4e75a84ea9f0?source=collection_archive---------19-----------------------

实践教程

一个实践教程,教你如何使用 Godot 游戏引擎和 Kompute 框架将 GPU 优化的 ML 代码集成到你的游戏开发工作流程中

作者图片

最近,世界已经看到了游戏行业和人工智能领域的各种定义性里程碑。仅在几周内,我们已经看到了游戏行业的重大财务公告,包括Unity 13 亿美元的 IPOEpic Games 17.8 亿美元的投资。人工智能领域也一直在赶上它的宣传,在 2020 年达到 600 多亿美元的市场,并在人工智能和游戏的交叉领域带来了令人兴奋的应用,包括 AlphaGo 击败冠军 Lee Sedol ,以及深度学习驱动的游戏,如人工智能地牢(以及更多应用)。

本文从技术上深入探讨了应用人工智能和游戏开发这两个领域之间的交集。我们专门研究如何利用跨供应商/移动 GPU 框架的能力来加速机器学习和高级数据处理用例的处理。

本教程的简单游戏界面(图片由作者提供)

在本教程中,你将学习如何使用 Kompute 框架 在流行的开源 Godot 游戏引擎 内部构建 GPU 优化代码。

您将了解如何通过 Godot 游戏引擎在游戏开发中利用机器学习和高级 GPU 计算。

除了编程经验之外,不需要任何背景知识,但是如果你对参考的底层 AI / GPU 计算概念感兴趣,我们建议查看我们以前的文章,“移动中的机器学习&跨供应商 GPU 使用 Kompute & Vulkan 变得简单”。

你可以在 资源库的 示例文件夹中找到完整的代码,以及 GDNative 库 实现和 Godot 自定义模块 实现。

Godot 游戏引擎

图片来自 Godot 开源 GitHub 库

拥有超过 30k github 明星和超过 1k 贡献者的 Godot 是最受欢迎的 OSS 游戏引擎。Godot 迎合了 2D 和 3D 开发的需求,已经被广泛用于手机、桌面、主机和网络兼容游戏/应用。Godot 是用 C++构建的,这使得它又快又轻——它只有 40MB 的下载空间。

Godot 通过健壮的设计原则和对高级语言的支持,包括其领域特定语言 GdScript ,对于新手来说非常直观,具有类似 Python 的语法,使其非常容易采用。也可以使用 C#、Python、可视化脚本、C++等进行开发。

在本教程中,我们将使用编辑器构建一个游戏,使用 GdScript 触发 ML 训练/推理,使用 C++开发底层的核心处理组件。

进入 Kompute & Vulkan SDK

与 Khronos 成员一起玩“瓦尔多在哪里”(图片由 Vincent Hindriksen 通过 StreamHPC 提供)

Vulkan 是一个由 Khronos Group 领导的开源项目,Khronos Group 是一个由大量技术公司组成的财团,他们聚集在一起,致力于定义和推进移动和桌面媒体(和计算)技术的开放标准。

大量引人注目的(和新的)框架已经采用 Vulkan 作为他们的核心 GPU 处理 SDK。Godot 引擎本身正在进行一个重大的 4.0 更新,将把 Vulkan 作为它的核心渲染引擎

正如您所想象的,Vulkan SDK 提供了对 GPU 的非常低级的访问,这允许非常专业的优化。这对于数据处理和 GPU 开发人员来说是一笔巨大的财富——主要缺点是冗长,需要 500–2000 多行代码才能获得编写应用程序逻辑所需的基本样板文件。这可能导致昂贵的开发周期和错误,从而导致更大的问题。这是我们启动 Kompute 项目的主要动机之一。

Kompute 是一个构建在 Vulkan SDK 之上的框架,专门用于扩展其计算能力,作为一个简单易用、高度优化、移动友好的通用 GPU 计算框架。

Kompute 文档(图片由作者提供)

Kompute 不是为了隐藏任何核心 Vulkan 概念而构建的——核心 Vulkan API 设计得非常好。相反,它通过 BYOV(自带 Vulkan)设计增强了 Vulkan 的计算能力,通过减少所需的样板代码和自动化编写 Vulkan 应用程序中涉及的一些更常见的工作流,使开发人员能够进行开发。

对于想了解更多信息的新开发人员来说,它为开始使用 GPU 计算提供了坚实的基础。对于更高级的 Vulkan 开发人员,Kompute 允许他们将其集成到现有的 Vulkan 应用程序中,并通过在需要时访问所有 Vulkan 内部来执行非常精细的优化。该项目是完全开源的,我们欢迎错误报告、文档扩展、新的例子或建议——请随时在回购中提出问题

游戏开发中的人工智能

在本帖中,我们将基于我们在“移动设备中的机器学习&跨厂商 GPU 使用 Kompute & Vulkan 简化”文章中创建的机器学习用例。我们不会像在那篇文章中那样详细地讨论基础概念,但是我们仍然会在这一节中介绍所需的高级直觉。

首先,我们需要一个允许我们公开机器学习逻辑的接口,这主要需要两个功能:

  1. train(…) —允许机器学习模型学习从提供的输入预测输出的功能
  2. predict(...) —预测未知实例输出的函数。这可以在下图中概述的两个工作流程中看到。

数据科学流程(图片由作者提供)

特别是在游戏开发中,这也将是机器学习工作流的一种常见模式,对于预测性和解释性建模用例都是如此。这通常包括利用用户与游戏本身直接(或间接)互动时产生的数据。这些数据可以作为机器学习模型的训练特征。新模型的训练可以通过数据科学家执行的手动“离线”工作流来执行,或者通过自动触发再训练模型来执行。

Godot 中的机器学习项目

我们将首先提供一个关于我们的 Kompute 绑定将如何在我们的 Godot 游戏中使用的高级概述。我们将创建一个简单的项目,并训练我们创建的 ML 模型,它将在 GPU 中运行。在本节中,我们已经可以访问定制的 KomputeModelML Godot 类——关于如何构建它并将其导入 Godot 项目的详细信息将在后面的章节中介绍。

新项目屏幕(图片由作者提供)

为此我们使用的是 Godot 版本 3.2.3 稳定版 。创建一个新项目和一个新的 2D 场景。您应该会看到一个空白项目,带有一个顶级 2D 节点,如左图所示。

现在我们可以开始给游戏添加资源了。我们将从创建一个简单的 UI 界面/菜单开始,该界面/菜单由机器学习模型的输入组成,它反映了前面的架构图中涵盖的工作流。

我们将有两个用于数据X_iX_j的输入行编辑文本框,以及一个用于Y预期预测的输入行编辑文本框。下图显示了用于构建 UI 的节点结构。您还可以通过导入project.godot文件来访问 repo 中的 full godot 项目。节点将被引用以读取输入数据并显示输出预测(和学习的参数)。

我们现在将能够在 Godot 中添加 GdScript 代码,这将允许我们读取输入,训练模型并执行预测——该脚本是在Parent节点下创建的。

下面是我们用来执行处理的完整脚本,它使用了我们在下一节中构建的KomputeModelML 自定义 Godot 类。我们将在下面分解代码的各个不同部分。

首先,我们定义变量来简化 Godot 编辑器节点的引用。这可以通过美元符号语法$NODE/PATH来实现,如下文所示。

下面的compute_ml()函数包含机器学习训练和预测的逻辑。我们首先使用 Godot 编辑器节点引用从文本框中读取输入。

我们现在可以从 C++类绑定中创建一个实例,我们将在下一节中构建这个实例。这个类公开了我们将用于机器学习推理的训练和预测函数。

我们现在可以通过传递输入和预期的预测来训练我们的模型。下面的 ML 模型是逻辑回归模型,它将调整其内部参数以最佳拟合输入和输出,从而产生一个能够预测未知数据点的模型。

既然我们已经训练了我们的模型,我们可以对看不见的数据点进行预测。为了简单起见,我们将传递用于测试的相同输入,但是您可以传递全新的数组,并查看它会产生什么样的预测。然后,我们可以在我们定义的preds_node引用节点变量中显示结果,这将显示在显示屏上。

最后,我们还想显示学习到的参数,在这种情况下,它包括w1w2bias。我们能够在各自的标签中显示权重和偏差。

最后要设置的是将“Kompute Train & Predict”按钮连接到compute_ml功能,这可以通过编辑器设置一个指向功能本身的信号来完成。

在我们的脚本中设置 compute_ml 方法的信号(图片由作者提供)

一旦这些都设置好了,我们就可以运行游戏,并使用提供的输入来触发训练和预测。然后,我们可以看到学习参数以及预测输出。当我们修改输入yxixj时,也可以看到学习参数是如何变化的。

Kompute ML Godot 界面及结果参数(图片由作者提供)

Kompute ML 实现

既然对游戏中发生的事情有了一个直觉,我们就能够使用 Kompute 框架 编写我们的底层 C++类来创建 Godot 绑定。

Kompute 建筑设计(图片由作者提供)

我们将遵循 Kompute 的设计原则,这些原则在显示不同组件的附图中有所概述。我们将按照此工作流程在 GPU 中加载数据并执行培训。

下面列出了 Godot 类绑定实现的头文件,我们将对其进行详细分析。正如你所看到的,创建一个带有绑定的 C++类是非常直观的,你可以看到我们在上面的 Godot GdScript 中调用的相同的函数。

KomputeLogisticRegression.hpp 实现

类头文件的初始部分包括:

  • 导入包含我们将在这个项目中使用的所有 Kompute 依赖项的Kompute.hpp头文件
  • 顶级Godot.hpp导入是确保所有 Godot 组件可用所必需的。
  • Node2D 是我们将要继承的资源,但是你可以从继承树中的其他类继承,这取决于你计划如何使用你的定制 Godot 类
  • 对于跨应用传递的数据,我们将使用 Godot Array来处理 GdScript 和 Naive C++之间的传输,以及 Kompute Tensor来处理 GPU 数据管理。
  • GODOT_CLASS 宏定义通过添加额外的 GODOT 相关功能来扩展该类。正如我们将在下面看到的,当构建为 Godot 定制模块时,您将需要使用 GDCLASS。

遵循基本功能,我们必须定义核心逻辑:

  • void train(Array y, Array xI, Array xJ)—使用逻辑回归模型的 GPU 本机代码来训练机器学习模型。它接受输入数组X,以及包含预期输出的数组y
  • Array predict(Array xI, Array xJ)—执行推理请求。在这种实现中,它不使用 GPU 代码,因为通常在推理端通过并行化获得的性能收益较少。然而,如果并行处理多个输入,仍有预期的性能增益(此功能允许)。
  • Array get_params()—以[ <weight_1>, <weight_2>, <bias> ]的格式返回包含学习参数的数组。

然后,我们可以声明将在 C++和高级 GdScript Godot 引擎之间绑定的方法,这些方法通常可供编辑器和更广泛的游戏访问。下面我们将简要地看一下注册一个函数所需的代码。

对于数据管理,我们将使用 Kompute 张量和数组——在这种情况下,我们只需要“学习”和“坚持”我们的逻辑回归模型的权重和偏差。

最后,我们还定义了着色器代码,它基本上就是将在 GPU 内部作为机器码执行的代码。Kompute 允许我们传递包含代码的字符串,但是对于生产部署,可以将着色器转换为二进制文件,也可以使用可用的实用程序转换为头文件。

如果你对完整的实现感兴趣,你可以在 gdnative 实现定制模块实现文件夹中找到所有的文件。此外,如果你对这些技术的理论和潜在的基本概念感兴趣,这将在我们之前的帖子中全面介绍。

编译并集成到 Godot 中

现在我们有了 GPU 优化的机器学习模型的基础代码,我们现在可以在 Godot 游戏引擎中运行它了。Godot 允许我们通过两种主要方式将 C++代码添加到我们的项目中:

  1. GdNative 库构建指令 —在 Godot 中,您可以添加自己的“GdNative 脚本”,这些脚本基本上是绑定到 GdScript 的 C++类,这意味着这些脚本可以在项目中动态使用和引用。这种方法适用于标准的 Godot 安装,不需要像第二种方法那样重新编译完整的编辑器。
  2. 自定义模块 构建指令 —在 Godot 中只有底层核心类是“核心”组件的一部分;其他的一切——UI、编辑器、GdScript 语言、网络功能——都是定制模型。编写一个定制模块很容易,这就是我们能够公开一些核心 Kompute 功能的方式。该选项要求用定制模块重新编译完整的 Godot C++项目。

一旦您通过指令设置了这些方法中的一个,您将能够从 Godot 内部访问自定义对象。每种方法之间存在一些细微的实现差异。

我们不会在博文中涉及具体的构建细节,但是你可以在上面的 GdNative 库/自定义模块链接中找到确切的代码和构建说明。

下一步是什么?

恭喜你,你一路走到了最后!虽然这篇文章涵盖了广泛的主题,但是也有大量的概念被浏览过。其中包括底层 Vulkan 概念、GPU 计算基础、机器学习最佳实践和更高级的 Kompute 概念。幸运的是,网上有资源可以扩展你在这些方面的知识。以下是我推荐的一些进一步阅读的链接:

利用 Dask 调整增压超参数

原文:https://towardsdatascience.com/supercharging-hyperparameter-tuning-with-dask-ab2c28788bcf?source=collection_archive---------50-----------------------

Dask 将 scikit-learn 参数搜索速度提高了 16 倍以上,Spark 提高了 4 倍以上

照片由斯潘塞·戴维斯Unsplash 上拍摄

声明:我是土星云的高级数据科学家——我们用 Python 和 Dask 让企业数据科学变得快速而简单。

超参数调整是构建机器学习模型的一个关键部分,通常也是痛苦的部分。从你的模型中挤出每一点性能可能意味着数百万美元广告收入的差异,或者医疗保健模型中患者的生死。即使你的模型需要一分钟来训练,你也可能要等几个小时来完成网格搜索(想想 10x10 的网格,交叉验证,等等。).每次你等待一个搜索完成都会打破一个迭代周期,并且增加你的模型产生价值的时间。简而言之:

  • 更快的运行时间意味着更多的迭代,以在截止日期之前提高准确性
  • 更快的运行时间意味着更快的交付,因此您可以处理另一个项目
  • 这两个要点都意味着将价值提升到您组织的底线

在这篇文章中,我们将看到如何通过在 Saturn Cloud 上用 Dask 代码 替换 scikit-learn 管道中的几行代码,将超参数搜索的速度提高超过16 倍。这使得传统的通宵参数搜索变成了几秒钟的等待。我们还尝试用 Apache Spark 进行类似的网格搜索,这需要更多的代码修改,但仍然比 Dask 慢得多。****

一、Dask 是什么?

Dask 是一个灵活、健壮的并行计算框架,内置于 Python 中,并为 Python 服务。它可以处理常见的数据结构,比如数组和数据帧,但是也可以用来并行处理那些不适合的复杂操作。事实上,并行数组和数据帧实际上是熟悉的numpypandas对象的集合,并且具有匹配的 API。通过这种方式,数据科学家不需要学习全新的框架,就可以在大数据上执行他们的代码。

实验设置

我们将使用公开可用的纽约出租车数据集并训练一个线性回归模型,该模型可以使用与乘客接送相关的属性来预测出租车乘坐的费用金额

我们将首先使用单节点 Python 包(pandasscikit-learn)完成数据加载和网格搜索,然后强调使用 Dask 或 Spark 并行化网格搜索需要做哪些更改。所有三个工作负载使用相同的数据执行相同的网格搜索,我们在整篇文章中将它们称为单节点(对于单节点 Python)、 Dask (对于 Dask 集群)和 Spark (对于 Spark 集群)。

五金器具

对于所有任务,我们都使用 AWS 的 r 5.2x 大型实例(8 个内核,64GB RAM)。对于 Python,我们只使用一个节点,对于 Spark 和 Dask,我们在具有不同数量工作节点的集群上运行工作负载,以跟踪运行时(3、10 和 20)。

Spark 集群使用亚马逊 EMR 管理,而 Dask 集群使用土星云管理。

给我看看结果吧!

如果您想跳过代码并查看性能改进,请跳到结果部分。

单节点工作流

首先,加载数据!我们随机抽取数据进行基准测试。

然后,创建一些特征:

我们正在使用一个 scikit-learn 弹性网模型,它可以基于l1_ratio参数执行 L1、L2 和弹性网正则化。我们还将尝试几个alpha的值,创建一个包含 404 个商品和三重交叉验证的网格,从而得到 1212 个适合搜索的模型。

当我们训练一个线性模型时,我们需要一次性编码分类特征并缩放数字特征。注意定义GridSearchCV时的n_jobs=-1参数指示 scikit-learn 在机器中的所有内核上并行化模型训练(这还没有使用 Dask,因为单节点并行化是 scikit-learn 自带的)。

最后,我们可以运行网格搜索并检索最佳分数:

如果你在和我们一样大小的机器上运行这个,大约需要 3 个小时。

顺便来看看

Dask 在单节点上运行良好,并且可以扩展到具有数千个节点的集群。要开始使用 Dask,我们需要初始化一个客户端,在这种情况下,我们将使用 Saturn Cloud 的SaturnCluster设置我们的集群

在读取数据时,我们需要做的唯一改变是使用dask.dataframe包,而不是pandas所有特征工程代码保持完全相同,因为 Dask 数据帧实现了 pandas API。

然后创建我们的管道和网格搜索:

注意 Dask 有几个不同的预处理和GridSearchCV类,用于加速预处理和避免网格搜索过程中不必要的重新计算。pipeline 和 estimator ( ElasticNet)类直接来自 scikit-learn。

我们可以像使用单节点 scikit-learn 一样使用网格搜索:

使用 20 个节点运行这个网格搜索的运行时间为1114】分钟!只需更改大约 10 行代码,性能就提高了 16 倍。让我夸张地再说一遍。

改 10 行代码 16 倍提升!

火花

Apache Spark 是 Scala 内置的大数据处理引擎,带有一个 Python 接口,向下调用 Scala/JVM 代码。它是 Hadoop 处理生态系统中的一个主要部分,围绕 MapReduce 范式构建,具有数据帧接口以及机器学习。

为了使用 Spark 运行我们的工作负载,我们需要重构我们的 Python 代码,以使用 Spark 的 DataFrame 以及 Spark ML 管道、预处理和模型类。

特征工程看起来与熊猫略有不同:

然后,我们设置我们的预处理管道和网格搜索。Spark ML 希望所有的特性都在一个向量列中,所以我们使用VectorAssembler来收集所有处理过的列。

然后,我们运行网格搜索,得到最佳结果:

在 20 个节点的集群上,这大约需要 47 分钟。

下面是一个并列的网格搜索代码,让您感受一下 Dask 在这个例子中有多简单:

代码量:Dask(左)和 Spark(右)

结果

我们用 404 个配置和 3 倍交叉验证进行了超参数搜索,使用弹性网络模型从纽约出租车数据集预测出租车出行持续时间。我们从单节点 Python 实现开始,并使用 Dask 和 Spark 将其转移到集群。从下表中我们可以看到,Dask 搜索比单节点和 Spark 集群版本快得多,同时只需要最少的代码更改。

我们在不同规模的集群上运行了 Dask 和 Spark 工作负载,以了解更大的集群如何缩短参数搜索时间:

与 Spark 和 Dask 集群相比的单节点 scikit-learn

为什么 Dask 这么快?

Dask 跨集群中的节点和核心并行化模型拟合,因此当向群集中添加更多机器时,您可以预期近似线性的加速。并行化工作会带来一些开销,这就是为什么我们通过添加 19 台机器获得了 16 倍的性能提升。

在这个例子中,Spark 的速度要慢得多,因为 Spark 网格搜索实现并没有并行化网格,它只是并行化模型拟合。这变成了连续的网格搜索,每个 fit 中的部分在集群中并行化。有一个项目 joblibspark 正在积极开发中,该项目旨在 spark 集群上并行化 scikit-learn 管道。在撰写本文时,我们无法成功运行 joblibspark。

所有代码都可以在这里获得。

您需要更快的超参数搜索吗?

是啊!你可以用土星云在几秒钟内启动 Dask 集群。Saturn 处理所有工具基础设施、安全性和部署方面的问题,让您立即开始使用 Dask。点击在你的 AWS 账户中免费试用土星

用 Python 为 MS SQL Server 增压

原文:https://towardsdatascience.com/supercharging-ms-sql-server-with-python-e3335d11fa17?source=collection_archive---------3-----------------------

如何使用 Python 来自动化 SQL 的一切

马修·施瓦茨Unsplash 上拍摄的照片

在工作中,我大量使用 SQL。它并不是没有令人讨厌的细微差别和限制,但归根结底,它是所有数据职业的基础。因此,对于任何在数据领域工作的人来说,这是绝对必要的。精通 SQL 非常重要。

虽然 SQL 很棒,但为什么要满足于棒呢?为什么我们不给 SQL** 增压?**

SQL 的局限性源于它是一种声明性语言,这意味着我们告诉 SQL 我们想要什么,然后 SQL 将从指定的数据库中获取这些信息。对于许多数据提取或简单的数据操作任务,这是所有需要的。

但是如果我们想要更多呢?

这正是我将在本文中向您展示的。

Axel Antas-Bergkvist 在 Unsplash 上拍摄的照片

它始于一个基础

点击此处查看完整脚本

这段代码是增强 MS SQL server 的基础。一旦构建完成,我们就可以从 Python 连接到 SQL,只需:

sql = Sql('database123')

简单对吗?有几件事情正在进行,所以让我们剖析代码。

class Sql:

首先要注意的是,我们将它包含在一个类中。我发现这种方法是合理的,因为在这种格式中,我们可以为这个特定的数据库添加或删除进程。一旦看到这是如何工作的,这就更有意义了。

我们初始化我们的类:

def __init__(self, database, server="XXVIR00012,55000"):

我和我的同事几乎总是连接到同一个服务器。所以我将这个公共服务器名设置为server的默认参数。

您的服务器名称可以在“连接到服务器”对话框中找到,也可以在 MS SQL Server Management Studio 的窗口顶部找到:

接下来,我们建立与 SQL 的连接:

self.cnxn = pyodbc.connect("Driver={SQL Server Native Client 11.0};"
                           "Server="+self.server+";"
                           "Database="+self.database+";"
                           "Trusted_Connection=yes;")

多亏了 pyodbc 模块,这变得非常容易。我们简单地将一个连接字符串传递给pyodbc.connect(...)函数,更多细节可以在这里找到。

最后,我喜欢在Sql类中创建一个查询字符串,它随着传递给该类的每个查询而更新:

self.query = "-- {}\n\n-- Made in Python".format(datetime.now()
                                              .strftime("%d/%m/%Y"))

这允许我们记录我们的代码,同时也作为一个可读性更强的输出,提供给那些更愿意阅读 SQL 代码的同事。

注意,我将在下面的代码片段中排除对 *self.query* 部分代码的更新,如果需要,请查看提供的链接中的完整代码。

照片由路易莎·阿泽维多Unsplash 上拍摄

积木

有几个基本功能我觉得非常有用,几乎每天都在使用。这些都侧重于将数据传入或传出数据库。

让我们从以下目录开始:

对于我们当前的项目,我们需要:

  • 将这些文件导入 SQL server
  • 将它们合并到一个表中
  • 基于列中的类别动态创建多个表

在进一步充实我们的 SQL 类之后,这将变得像下面这样简单:

让我们从头开始。

推送数据帧

点击这里查看完整的脚本,或者这个脚本可以维护数据类型(但是偶尔会在不太干净的数据集上抛出错误)

这个函数包含在我们的 SQL 类中。它允许我们轻松地将 Pandas 数据帧推送到 SQL 数据库。

这在需要上传大量文件时特别有用。然而,允许 Python 将数据导入 SQL 的真正力量来自于 Python 的灵活性。

将十几个 Excel 工作簿中的特定选项卡导入 SQL 可能是一场噩梦。但是使用 Python 很容易。现在我们已经构建了一个函数,允许我们使用 Python 来读取这些选项卡,并为我们将它们导入 SQL。

指南

点击此处查看完整脚本

该功能实际上用于uniondrop 功能。它只是让我们尽可能简单地执行 SQL 代码。

response 参数为我们提供了将查询输出提取到数据帧的选项。允许我们从generic_jan 表中的colX 中提取所有唯一值,只需使用:

sets = list(sql.manual("SELECT colX AS 'category' FROM generic_jan GROUP BY colX", response=True)['category'])

联盟

现在我们已经构建了manual 函数,创建union 函数很容易:

点击此处查看完整脚本

这只是循环遍历我们通过table_list提供的表名列表,为所有给定的表名构建一个联合查询。然后用self.manual(query)执行。

我们能够将大量的表上传到 SQL Server。这很好,但会很快使我们的数据库人满为患。为了解决这个问题,我们将创建一个drop 函数:

点击此处查看完整脚本

同样,由于有了manual 功能,这个功能非常简单。这允许我们通过向tables 提供一个字符串来删除单个表,或者通过向tables提供一个表名列表来删除多个表。

阿德里安Unsplash 上拍摄的照片

当将这些极其简单的函数结合起来时,我们可以利用 Python 的优势来大规模扩展 SQL Server 的功能。

如果你有兴趣了解更多,请查看pysqlplusGitHub 回购。这是一个小项目,只是为了增强我自己的工作场所与 MS SQL Server 的交互而构建的。

尽管如此,我希望它可以帮助其他一些用户找到将 Python 集成到他们的 SQL 例程中的方法。我个人几乎每天都在使用它,它是如此简单却又无比强大。

感谢阅读!

如果你有兴趣学习更多关于 Python 和云中 SQL 的知识,可以看看我在 Coursera 上发表的关于 IBMs 可扩展数据科学基础课程的评论,点击这里 :

** [## 对 IBM 可伸缩数据科学基础的回顾

我的想法是,在 IBM 的高级数据中,对可伸缩数据科学基础中的关键概念进行分解…

towardsdatascience.com](/a-summary-of-the-advanced-data-science-with-ibm-specialization-1-4-5caf48c011df)**

经典数据的超密集编码

原文:https://towardsdatascience.com/superdense-encoding-of-classical-data-5a2ef02d09d8?source=collection_archive---------47-----------------------

使用具有双振幅编码的维数减少

我之前的一篇文章题为“ 130,780 点量子分类”,其中的电路使用 20 个量子位来映射所有数据,这导致了一个 Twitter 帖子,激励我思考我可以减少多少量子位计数。老实说,这条赛道并没有引起太多的注意;我专注于用一个相当大的真实数据集获得准确的分类结果。然而,公平地说,第一种有效的编码不一定是最佳编码策略。

介绍

量子计算的众多挑战之一是将经典数据映射到量子位,也就是“量子位”。在我的上一篇文章中,数据集有五个特性(也就是数据列)和四个类。最简单的方法是将每一类的每个特征映射到一个量子位,结果是 5×4 = 20 个量子位。我已经考虑过在每个量子位上映射两个特征的可能性,但是,我还是保持简单来验证算法是否真的有效。

顺便说一下,请记住,每个量子位代表数千行经典数据。每个向量代表一个类别中一列的标准化平均值。

原始电路

虽然你看不到下面的 20 个数据量子位,但你看到 5 个数据量子位(最上面的 5 个量子位)被重置,每个重复使用 3 次。这是因为当你在电路中添加量子位时,模拟器的速度会明显变慢,直到两个小时后的某个时候达到运行时错误(至少对于 IBM Q 体验来说)。然而,重置和重复使用更少的量子位,可以完成更多的计算。

与我已经发表的所有其他电路相比,这个电路的一个独特反馈是,OpenQASM 子例程的使用将电路压缩得如此之多,以至于它似乎实际上没有做太多事情,尤其是没有做任何“量子”的事情。此外,虽然“设置”盒仅仅是重置和重用量子位,但“测试”盒隐藏了非常量子交换测试。因此,即使子例程使编码变得更简单和容易,我将放弃它们,以便未来的电路公开显示它们的组件门。

对于那些没有读过我上一篇文章的人来说,所有进行交换测试的电路都必须在模拟器上运行的原因是因为 Fredkin gates 转换成了大量的门。真实量子位的有限连通性加剧了电路深度的问题,这导致 CNOTs 在已经很重要的步数上增加了更多的电路深度。当测量开始时,退相干已经使结果变得毫无价值。

降维

数据集的每一列都是数据的一个维度,所以我们从五个维度开始。然而,一个量子位不是五维的,所以我们需要某种降维策略来将这个数据集映射到少于 20 个量子位。使用旋转和量子态层析成像,我们可以将数据映射到 10 个量子位,这是一个显著的减少。然而,如果我们使用经典的预处理,我们甚至可以做得更好。

这个算法很松散地受到了主成分分析(PCA) 的启发。你可能看不到任何相似之处,但思考如何将数据集缩减为二维帮助我进一步将五维数据缩减为一维。

双振幅编码

如果你看了视频,“量子机器学习- 24 -编码经典信息,”魏特克博士描述了我的编码策略的一个变种。然而,我实际上并没有对振幅进行编码,因为我并没有测量编码的量子位。此外,振幅在布洛赫球的顶部和底部附近不太敏感,而在中部附近更敏感,这似乎会扭曲交换测试的结果。

相反,我用圆周率的分数。我希望每次旋转的量是一致的,不管我们在布洛赫球的哪个位置。

算法

我不可否认不是数学家,所以这个算法的降维部分可能有捷径。正如之前我的上一篇文章中所展示的,除了别的以外,我专注于让我的算法工作。如果它们有效,我会发布我所拥有的,然后在后续项目中进行优化。

  1. 对于每个类,使用公式((平均值-最小值)/(最大值-最小值))对每个要素(列)的平均值进行归一化,其中最大值和最小值是全局最大值和最小值
  2. 对于每个类别,将上述标准化平均值相加
  3. 使用步骤 1 中的公式归一化步骤 2 中的总和;全局最大值和全局最小值再次来自整个数据集,因此我们可能映射的所有测试值将保持在 0 到 1 的范围内
  4. 将每个归一化总和乘以 pi

该算法的最终结果是每个类由一个值表示,范围从圆周率值的 0%到 100%。

问题

对于四个类,我们可以使用 U3 门来映射每个量子位的两个类。这是本文顶部显示的电路。每个量子位围绕 y 轴有一个 0 到π的旋转,围绕 z 轴有一个 0 到π的旋转。

问题是这些数据被压缩得太多了,没有用。或者说,至少,我还没想好怎么用。在 Twitter 上,我把它比作使用 ZIP 文件,你必须用它提取内容,然后才能使用。

然而,通过量子态断层扫描提取内容并不成功,否则我会在这里展示这个电路。此外,如果没有其他原因,量子 ZIP 文件对增加的电路深度没有意义。从最少数量的有用量子位开始是有意义的。

最佳选择

对于给定数据集中的四类数据,所需数据量子位的最小数量似乎是四,或者每个数据量子位一类。我们可以用 RY 门代替 U3 门。

前一篇文章的电路的目标是量子分类,所以这里是该算法的修订版。前四个量子位代表四类数据,中间四个量子位代表我们想要分类的新数据点,底部四个量子位是用于交换测试的 ancilla 量子位。

测试数据量子位可能看起来是多余的,但这种冗余是必要的,因为我们正在运行四个不同的交换测试。在这种情况下,我们可以在一个模拟量子位上使用重置门,但我宁愿明确指出,每个类别比较都需要它自己的类别数据量子位、测试数据量子位和辅助量子位。

结果

当量子状态相同时,交换测试以 1 的概率测量|0 >,当量子状态最大程度地相反时(在 Bloch 球的相对侧),以 0.5 的概率测量|0>。例如,测量值为 0.9 表示各州之间距离相对较近。因此,测量|0 >的概率最高的类是最接近测试数据点的类。

如果您进行传统的后处理,测量|0 >的最高概率是类 0,这很好,因为这是我获取测试数据点的地方。为了完全公开,数据,甚至类,有很多重叠,所以很容易得到不正确的结果。但是,因为是数据有重叠,所以使用 scikit-learn 或其他方法,我们应该会看到同样不正确的结果。

结论

本文顶部的电路显示了仅映射到两个量子位的 130,780 个数据点。虽然我目前还没有一种算法可以处理这种程度的压缩,但这并不是不可能的。

使用稍微少一点的压缩,并将相同的数据映射到仅四个量子位,我们仍然可以运行诸如量子分类之类的算法。这与我之前实现的 20 量子位相比是一个巨大的减少。

未来的工作

我仍在考虑使用最大限度压缩数据的方法,并希望在未来的文章中分享对此的感悟。我也期待有一天在真正的硬件上运行这个算法。尽管我现在可以在 ibmq_16_melbourne 上运行它,但没有办法优化电路的量子位连接,结果将是一个退相干(如果这是一个真实的词)的混乱。

承认

感谢 IBM 一如既往的为量子位,无论是真实的还是模拟的。本文所有图片均来自 IBM Q Experience。也感谢量子直觉 ( @explore_quantum )和量子史蒂夫(@史蒂夫 _quantum )没有对将 130780 个数据点映射到 20 个量子位留下深刻印象。

使用 Google Colab 为您的 Jupyter 笔记本提供超强动力

原文:https://towardsdatascience.com/superpower-your-google-colab-720d54dd6a06?source=collection_archive---------18-----------------------

您的 Jupyter 笔记本体验即将升级

Google Colab 是一个免费的基于浏览器的笔记本环境,完全运行在云中。它有一个类似于谷歌文档的界面,它是一个游戏改变者。

首先,如果你以前没有用过 Colab,那你就错过了。以下是几个原因:

  1. 无服务器: Colab 允许你在浏览器中立即弹出一个完全无服务器的 Jupyter 笔记本。这意味着您不必担心配置硬件、您的 Python 版本和路径,或者您是在 Windows、MacOS 甚至是手机上!
  2. 分享:你可以无缝分享笔记本,就像一个谷歌文档。
  3. 免费 GPU: 一键免费 GPU。对我来说太棒了,因为我有一台 MacBookAir,所以肯定没有 GPU。

对于超级大国来说:

  • 版本控制:你的笔记本上是否堆满了大量注释掉的代码?这也扰乱了你的思维。使用 Colab,您可以随意删除任何代码,因为每次保存时,Colab 都会为您保留一个版本,您可以恢复到该版本。cmd/ctrl+G 打开您的修订历史,您可以命名您过去的修订。这样你就可以随时删除旧代码,保持笔记本整洁。
  • 键盘快捷键:键盘快捷键很多。只需在工具栏的工具选项下进行检查。更好的是,它们都是完全可配置的。我经常使用快捷键来添加新的单元格。
  • 把“ #@title 这是一个块”放在一个代码单元格的顶部:你的单元格刚有了标题就变得可压缩了。这是清理笔记本的好方法。
  • 将“###节标题”放入一个文本单元格:它将使所有内容直到下一个带有“# # #”的文本框都折叠起来,因此您可以折叠整个节。
  • 表单:您可以添加滑块、下拉框和其他表单元素,无需任何代码,只需点击悬停在代码单元格右上角的三个点,然后点击“添加表单”。这使得其他想要与您的笔记本进行交互的人无需编辑代码就可以这样做。

使用表单滑块允许用户调整模型参数。

  • seed bank:谷歌在 colabs 中托管了一个完整的深度学习和数据科学概念证明库,你只需点击一个按钮就可以打开并运行它。 GAN 合成器有人吗?
  • 使用 GPU: 进入运行时- >更改运行时类型,选择 GPU。瞧啊。你现在有一个图形处理器。对于深度学习和一些可并行化的数据科学算法是必不可少的(XGBoost 有人吗??)同时,您可以添加更多内存。单击更改运行时类型后,可以选择切换到更多 RAM。
  • Colab Pro: Colab 确实有超时和使用限制(它们相当大,比如一天十个小时)。但是,如果你发现自己遇到了这些问题,你可以每月支付 10 美元购买 Colab Pro,它可以延长运行时间,并更好地访问更强大的 GPU。这是我刚刚为我的深度学习项目买的,太棒了!
  • 评论功能:你知道如何在谷歌文档上发表评论吗?现在你也可以在 Colab 上这样做了!这很好,因为笔记本实际上一半是编码环境,一半是报告。轻松地与他人分享您的发现,他们可以直接在您的笔记本上发表评论!
  • 自动完成:难以记住所有那些 Matplotlib 或 NumPy 函数和函数参数?好吧,Colab 可以自动完成,所以你只需要开始输入;当你输入的时候,它会显示出剩下的函数名,参数和任何文档。

有几件事我希望他们会补充…

  1. 自动格式化:如果你能按下“ctrl + f”键,你的代码就会自动格式化,那不是很好吗?
  2. 类似 vscode 的 Git 指示:看看自上次提交以来您修改和添加了哪些行不是很好吗?像这样:

  1. Linter :当我在做一些 Linter 知道会出错或者只是糟糕/无用代码的事情时,我很想得到那些红色的曲线。

Colab 的缺点是什么?

  • 我最近在一个深度学习项目上工作了 40+小时;随着代码库变得越来越大(深度学习比数据科学更容易发生这种情况),用笔记本管理变得越来越困难。
  • 如果你使用太多的 RAM 或 GPU,你的会话就会崩溃,你将不得不重新运行所有的代码。它也会在休眠一段时间后超时。
  • 如果你想访问谷歌硬盘上的文件,每次安装硬盘时都必须这样做。它会变得很烦人。

考虑到这一切,如果你以前从未使用过,Colab 绝对是一个更高的水平;如果你有,这些功能会给你超能力!

每个人的监督和非监督学习

原文:https://towardsdatascience.com/supervised-and-unsupervised-learning-for-everyone-526f9b746dd5?source=collection_archive---------38-----------------------

不管你是技术天才还是街舞者,任何人都可以理解机器学习

来源:https://www.pexels.com/@freestockpro

不管你是技术天才还是街舞者,听说了机器学习并出于好奇或原始的激情决定去寻找它。以错误的方式被引入这些概念,感觉就像从直升机上被丢进了大海。我是以不太友好的方式被引入这些概念的,相信我,这一点也不好玩,这就是为什么我花时间以一种简单、初学者友好和吸引人的方式写这篇文章。

在这篇文章中,在保持事情简单的同时,我将稍微深入一点,明确解释监督和非监督机器学习的确切含义,这样即使是初学者或非技术人员也可以消化信息,而不会因其复杂性而便秘。

说完这些,让我们来看看是什么把我们带到这里的。

机器学习 大致分为 2 大类:有监督和无监督机器学习。

什么是监督学习?

插图:DAVIDE BONAZZI/@SALZMANART

有监督的机器学习包括使用明确标记的数据训练计算机系统。标记数据在这里是指输入已经用相应的期望输出标签进行了标记。机器学习算法(模型)通过迭代过程从这些标记的数据中学习,然后使其能够执行未来预测。例如,这里有一个类比可以帮助你理解这个概念。

可以把监督学习算法想象成这样的学生,他们被给予大量的实践问题(数据),并被指示通过找到这些问题中的信息和它们的相关答案(输出)之间的模式来找到解决这些问题的方法。

在上面的场景中,目标变成了能够找到最有效的数据(练习题)以提供给最有效的算法(学习风格),从而获得最佳的表现(答案)

监督学习问题被进一步分成两个子类— 分类和回归。这两个子类之间的唯一区别是算法旨在预测的输出或目标的类型,这将在下面解释。

1.分类问题

来源:https://www . wkrg . com/northwestern-Florida/new-penalty-for-animal-breakers-take-effect-Monday-in-Florida/

在分类中,目标是识别一个对象(输入)属于哪个类别。例如,我们可能有兴趣确定图像是否包含狗或猫,颜色红色或黑色,电子邮件垃圾邮件或真实邮件,患者是否携带艾滋病毒。在上面的例子中,分类目标只取 2 个类的分类问题被称为二元分类问题。另一方面,如果目标输出取 2 个以上的值,这是一个多类分类问题。比如说;分类花的类型,分类汽车的类型等

2.回归问题

截图来源:https://www . slide share . net/gabrielspmoreira/introduction-to-data-science-123459159

回归问题是当要预测的输出变量是数值时。这与上面看到的分类相反。让我们举个例子,你可能会对确定伊斯坦布尔的房价、生活在昆布的男人的体重、喀麦隆教师的薪水(T21)等感兴趣。价格权重、薪水是上图所示的数值,纵轴表示房价。

趣味问答 这只是为了刺激和巩固回归和分类的区别。如果你准备好了,那我们走吧。

以下哪项是分类问题?

1.通过一个人的笔迹来预测他/她的性别。根据面积预测房价
3。预测明年季风是否正常
4。预测下个月一张音乐专辑的销量

在这篇文章的最后,我将提供答案,所以保持冷静,让我们继续前进。

用于分类和回归的监督机器学习算法。

下面概述的处理回归和分类任务的不同算法类似于不同的学习风格,每个学生都使用不同的学习风格在上面分类下的类比中得出答案。这些算法中的哪一个在特定的分类和回归问题中表现得最好,由数据科学家来决定。

信守我让事情变得简单的承诺。以下是根据问题的具体特征来解决监督机器学习问题的最常用算法列表。

支持向量机
线性回归
逻辑回归
朴素贝叶斯
线性判别分析
决策树
随机森林
K-最近邻算法
神经网络(多层感知器)
相似性学习

有关不同算法的更多信息,请查看 scikit-learn 网站 以及本文末尾的参考链接。

分类问题的一些有趣应用是在垃圾邮件检测、图像识别、语音识别。你还可以查看一下机器学习的一些现实生活中的应用概述这里

在我们继续之前,让我们冷静一下这个令人震惊的事实..

法老拉美西斯二世是唯一一位获得护照并登上飞往法国的飞机的埃及法老。

来源:https://www . ancient-origins . net/history-named-people/mummy-passport-0010944

什么是无监督机器学习?

来源:https://www.pexels.com/@alittleimagery

与有监督的机器学习相反,在无监督的机器学习中,模型被输入没有人类预定义标签的数据。在数据中寻找隐藏的结构、模式或关系,这取决于算法。

让我与你分享这个类比。

想象一下,你对游泳一无所知,不幸的是,你的朋友带你去参加泳池派对,故意把你推进去。你需要弄清楚如何游泳,并让自己离开那个冰冷的游泳池。

以此类推,就是模型(算法)就是数据。没有游泳教练教你游泳,因此得名无人监管。

就像监督学习一样,非监督学习可以分为两种类型:聚类和关联技术。

1.聚类分析技术

来源:https://www.guru99.com/

在聚类分析中,该算法使用未标记的数据,其目的是根据某些相似性或不相似性标准将数据分成称为的组。相似的数据点被分组在同一个聚类下,如上图所示。

聚类可以分为排他聚类、重叠聚类、层次聚类、概率聚类在本文中我不会深入讨论这些,但是可以在文章末尾的链接中找到更多信息。

以下是机器学习中最常用的一些聚类算法。

***层次聚类

  • K-means 聚类
  • K-NN (k 近邻)
    *主成分分析
    奇异值分解
    独立成分分析

对于好奇的读者来说,请参考文章末尾的链接以获得关于这些技术的更多信息。

2.关联规则技术

来源:https://medium . com/@ agupta . rkl/market-basket-analysis-using-association-rule-mining-66 b 61 c 0 D5 f 26

在关联问题中,模型学习数据之间的关系,然后得出某些规则。这种无监督学习技术是关于在大型数据库中发现变量之间的 有趣关系 。例如,买新房子的人很可能会买新家具,买牙刷的人很可能会买牙膏,等等。

已经提出了许多产生关联规则的算法。一些众所周知的算法是:

*** Apriori 算法

  • Eclat 算法和
    频繁模式增长*

下面包含解释个别技术的链接。

无监督学习技术的应用。

无监督学习在 e 探索性分析 中非常有用,因为它可以自动识别数据中的结构。例如,通过基因表达测量对癌症患者分组,根据浏览和购买历史对购物者分组,通过电影观众给出的评级对电影分组。

这篇关于机器学习的 文章 提供了机器学习的一些有趣的日常现实应用。

测验的答案:预测一个人的性别,预测明年季风是否正常都是分类任务。另外两个是回归。

我知道你答对了!!

希望你喜欢读这篇文章,就像我喜欢写它一样。非常感谢您的建议和意见。

参考文献。

[## 用通俗易懂的语言解释机器学习

在最近的演讲活动中,我遇到了试图从概念上解释机器学习而不…

towardsdatascience.com](/explaining-machine-learning-in-laymans-terms-9b92284bdad4)

https://www.guru99.com/unsupervised-machine-learning.html#7

https://www.wikiwand.com/en/Unsupervised_learning

https://medium . com/@ mandysdana/machine-learning-types-of-class ification-9497 BD 4 F2 e 14
https://medium . com/datadriveninvestor/class ification-algorithms-in-machine-learning-85 c0ab 65 ff 4
https://towardsdatascience . com/unsupervised-learning-and-data-clustering-eeecb 78 b 42 a

https://medium . com/@ mandysdana/machine-learning-types-of-class ification-9497 BD 4 F2 e 14
https://medium . com/datadriveninvestor/class ification-algorithms-in-machine-learning-85 c 0 ab 65 ff 4
https://towards data science . com/unsupervised-learning-and-data-clustering-eeecb 78 b 42 a
https://www.wikiwand.com/en/Unsupervised_learning

监督和非监督学习识别客户

原文:https://towardsdatascience.com/supervised-and-unsupervised-learning-to-identify-customers-568cfa0badea?source=collection_archive---------47-----------------------

解决同一问题的两种不同方法。

雷锐Unsplash 上拍照

欢迎来到我在 Udacity 的数据科学家纳米学位的最后一个项目。我正在经历职业转变,从学术界(我有天体物理学博士学位)转向工业界,这个纳米学位是我朝着那个方向迈出的一步。

我选择这个项目是因为涉及到两种不同类型的机器学习算法应用于相同的数据。还因为这是各种行业都很常见的问题。这个项目的数据和大纲是由贝塔斯曼子公司 Arvato Financial Solutions 提供的。所有的工作都在这个环节中完成。

目标

我们希望利用无监督和有监督的机器学习技术和人口统计数据,为德国的一家邮购销售公司识别新客户。

数据

该数据包括 4 个数据集:

  • 客户:德国一家邮购销售公司的客户的人口统计数据,包括 3 列,提供关于客户的广泛信息(191 652 x 369)。
  • AZDIAS:德国一般人口的人口统计信息(891 211 x 366)。
  • MAILOUT-TRAIN:公司营销活动目标的人口统计信息-TRAIN 集,包括一个回应列,该列指明每个接收人是否成为公司的客户(42 982 x 367)。
  • MAILOUT-TEST:公司营销活动目标的人口统计信息—测试集(42 833x 366)。

人口统计列没有直观的名称,这给分析带来了困难,但是我们可以从 Arvato 提供的元数据中获得每个列的含义。

数据争论

我不得不在数据上争论不休:

  1. 删除客户数据中多余的列。

我们没有使用这些数据。

2.识别缺失的值。

数据包含许多缺失值,但其中一些是编码的。我必须非常仔细地查看元数据才能发现:

  • 所有值=-1 表示未知。
  • 对于 16 列,值=0 表示未知。
  • 对于 74 列,value=9 表示未知。
  • 对于对象列,value=X 或 XX 表示未知。

我必须将所有这些值转换成 NaNs。

3.删除缺少大量值的列。

在下图中,我显示了缺少更多值的列:

有 6 列缺少 50%以上的值。我们删除这些列。

4.删除有大量缺失值的行。

在下图中,我根据缺失数据的百分比显示了行的计数:

大多数行的缺失数据不到 10%,我们只保留那些行。

5.将对象列转换为数字列。

我们有六个非数字列:

  • 两个实际上是数字,所以我把它们转换了。
  • 一个是约会。我将该列转换为 datetime 类型,然后只保存年份。
  • 一个只有两个值。我把它们映射到 0 和 1。
  • 剩下的两列是分类的,没有序号,所以我必须通过 Panda 的 get_dummies()方法执行热编码。

6.填充 NaNs。

因为大多数数据是分类的,所以我选择用 mode by 列来填充缺失的值。为了做到这些,我实现了一个估算器()。

7.删除高度相关的列。

按照这里的步骤,我删除了 AZDIAS 和 CUSTOMERS 数据帧中相关性大于 0.95 的列。

8.删除 id 列。

对于模型来说,名为 LNR 的 id 列并不是一个有趣的特性。

步骤 2-8 是在一个名为 clean_data()的函数中实现的。

9.缩放数据。

我们需要缩放数据,以获得机器学习模型的准确性能。我使用了 StandardScaler(),它通过移除平均值并缩放到单位方差来标准化特征。

使用无监督学习识别普通人群中的客户群。

在项目的这一部分,我们执行无监督聚类来识别客户群。

  1. 主成分分析。

争论之后,我们以 425 列结束。由于这个数字非常大,我们对 AZDIAS 数据集进行了主成分分析,目的是降低维数。

我决定保留 170 个组件,它们占累计解释方差的 80%左右。

2.使聚集

我做了一个 K 均值聚类。首先,我只取了一个数据样本,用不同数量的聚类来拟合算法。我在下面的图中显示了结果:

按照肘方法,我选择保留 16 个集群(我也可以选择 7 个集群,但我决定用 16 个)。

然后,我用 AZDIAS 数据集拟合 K-means 算法,并预测每一行的聚类数。

3.客户数据

我将具有 170 个特征的拟合 PCA 和具有 16 个聚类的拟合 K-means 应用于客户数据,以获得每行的预测聚类数。

为了识别客户群,我们必须比较这些聚类:

很明显,客户子群体主要由集群 10、12 和 2 表示。这三个集群的人是公司的目标。哪些主成分(PC)与这些集群相关联?哪些是代表性最不足的(13、5、6、8)?

我们可以看看这 7 个被标识为代表过多(蓝色)和代表不足(绿色)的集群的第一主成分的值。

很难对情况进行详尽的分析,但有一个明确的结论:

对于 PC # 0,所有代表不足的聚类具有小于 1 的值,而代表过多的聚类具有更大的值。PC # 1 的情况几乎相反。

分析 PC # 0,我们看到与列最相关的是:MOBI_REGIO、PLZ8_ANTG1、KBA13_ANTG1、KBA05_ANTG1、LP_STATUS_FEIN、KBA13_BAUMAX、HH_EINKOMMEN_SCORE、KBA13_ANTG4、KBA13_ANTG3、PLZ8_ANTG3。

作为一个例子,让我们看看 MOBI _ 区域列的哪种值与 PC#0>1(客户)相关,哪些值与 PC#0 相关<1 (non-clients):

In general, we can associate positive values with clients and negative values with no clients. Since all these features are scaled to mean=0 the this means values above and under the mean. The MOBI_REGIO column is related to mobility, high values indicate low mobility. So, people with low mobility are our target.

After repeating this proceeding for the other 9 columns I found out that:

结论— 我们正在寻找高收入、高社会地位、流动性低且附近有 1-2 户人家的人。

使用监督学习预测客户响应概率

在项目的这一部分,我们训练一个分类器来预测测试数据集中的人对活动做出响应的可能性。

  1. 使用 wrangling 步骤中描述的 clean_data()函数清理训练数据。
  2. 将特征与目标分开。目标是二进制标签 0 或 1。从下一张图中可以看出,数据是不平衡的:

3.使用标准缩放器()缩放特征

4.训练不同的简单模型,看看它们的表现。

我训练了 5 个模型并计算了 roc_auc。由于数据的不平衡,我使用了这个指标(也因为它是 Kaggle 比赛中用来测试我的结果的指标)。

由于结果的度量,我选择保持梯度推进算法。

5.寻找最佳参数

我使用 GridSearchCV 扫描了以下参数空间。

param_grid = {'max_depth': [3,4,5],
             'loss':['deviance', 'exponential'],
             'n_estimators': [100, 150, 200]}

我发现最好的参数是 max_depth=4,loss=deviance(默认),n_estimators=100(默认),ROC_AUC=0.779。

6.预测测试数据的标签。

首先,我必须清理测试数据。我使用了带有不删除行选项的 clean_data 函数,还保存了 id 列,因为我在第 7 步中需要它。

我用拟合最佳模型的 predict_proba 方法预测了标签的概率(因为我们使用的是 roc_auc,所以我们对精确值不感兴趣)。

7.将结果上传到 Kaggle 比赛

我取得了 0.77698 的成绩,提交时的第 91 名。

结论

我喜欢这个项目,因为它有很多值得探索的东西。数据争论的步骤真的很长,而且列没有直观的名称这一事实使得一切变得更加困难。幸运的是,大多数特征都是数字,这简化了事情。

无监督模型很容易实现,但需要大量的工作来理解结果。得出一个详尽的结论是困难的,但我对我得出的结论感到高兴:我们正在寻找高收入、高社会地位、流动性低且附近有 1-2 个家庭的房子的人。

监督模型更难,我必须测试不同的模型,寻找最佳参数。上传我的成绩到 Kaggle 后,我得到了 0.77698 分。我对结果很满意,但我知道还有改进的空间。

我能做些什么来改进模型?
-设计一些功能:例如,我可以将年份变量转换为桶
-用平均值或其他技术填充 NaNs
-测试更多的分类器或更大的参数空间

你有其他想法吗?

监督学习算法:解释和简单代码

原文:https://towardsdatascience.com/supervised-learning-algorithms-explanaition-and-simple-code-4fbd1276f8aa?source=collection_archive---------16-----------------------

监督学习算法采用一组已知的输入数据(学习集)和对数据的已知响应(输出),并形成一个模型来生成对新输入数据的响应的合理预测。如果您有正在尝试预测的输出的现有数据,请使用监督学习。

它们可以用于分类或回归。在这篇文章中,我将展示每一个的一些例子。

分类算法

k 最近邻分类器

***1) Import the Classifier* ****from** sklearn.neighbors **import** KNeighborsClassifier***2) Create arrays for the features and the response variable* **    
y = df['target'].values      
X = df.drop('target', axis=1).values ***3) Create a k-NN classifier with 6 neighbors* **  
knn = KNeighborsClassifier(n_neighbors =   6) ***4) Fit the classifier to the data* **    
knn.fit(X,y) ***5) make predictions***
new_prediction = knn.predict(X_new)

选择正确的集群数量

***1) Setup arrays to store train and test accuracies*** neighbors = np.arange(1, 9)
train_accuracy = np.empty(len(neighbors))
test_accuracy = np.empty(len(neighbors))***2) Loop over different values of k***
for i, k in enumerate(neighbors): ***3) Setup a k-NN Classifier with k neighbors***
   knn = KNeighborsClassifier(n_neighbors=k) ***4) Fit the classifier to the training data***
   knn.fit(X_train, y_train) ***5) Compute accuracy on the training set***
   train_accuracy[i] = knn.score(X_train, y_train) ***6) Compute accuracy on the testing set***
   test_accuracy[i] = knn.score(X_test, y_test)***7) Generate plot***
plt.title('k-NN: Varying Number of Neighbors')
plt.plot(neighbors, test_accuracy, label = 'Testing Accuracy')
plt.plot(neighbors, train_accuracy, label = 'Training Accuracy')
plt.legend()
plt.xlabel('Number of Neighbors')
plt.ylabel('Accuracy')

随机森林分类器

***1) Import the Classifier* from** sklearn.ensemble **import** RandomForestClassifier***2) input data as np array*** y = df[‘target'].values
X = df.drop(‘target', axis=1).values***3) import model and fit(train) data*** rfc = RandomForestClassifier(n_estimators=100)
rfc.fit(X, y)**4) make predictions** pred_rfc = rfc.predict(X_test)

支持向量机(SVM)和判别分析

***1) Import the necessary modules* **     
**from** sklearn.linear_model **import** LogisticRegression       
**from** sklearn.metrics **import** confusion_matrix, classification_report ***2) Create training and test sets*** 
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.4, random_state=42) ***3) Create the classifier:* **   
logreg = LogisticRegression() ***4) Fit the classifier to the training data* **     logreg.fit(X_train,y_train) ***5) Predict the labels of the test set* **     
y_pred = logreg.predict(X_test)

logistic 回归的 ROC 曲线

ROC 曲线是一种图示,其说明了二元分类器系统在其辨别阈值变化时的诊断能力。ROC 曲线是通过在各种阈值设置下绘制真阳性率对假阳性率而创建的。真阳性率也称为灵敏度、召回率或检测概率。假阳性率也称为假警报概率

来自:https://flowing data . com/2014/05/09/type-I-and-ii-errors-simplified/

***1) Import the necessary modules*** from sklearn.metrics import roc_curve ***2) Compute predicted probabilities***    
y_pred_prob = logreg.predict_proba(X_test)[:,1] ***3) Generate ROC curve values*** 
fpr, tpr, thresholds = roc_curve(y_test, y_pred_prob) ***4) Plot ROC curve* **    
plt.plot([0, 1], [0, 1], 'k--')       
plt.plot(fpr, tpr)       
plt.xlabel('False Positive Rate')       
plt.ylabel('True Positive Rate')       
plt.title('ROC Curve')       
plt.show()

ROC 曲线下的面积越大,模型越好。

回归算法

线性和非线性回归

***1) Import LinearRegression* **     
**from** sklearn **import** linear_model       
**from** sklearn.linear_model **import** LinearRegression***2) Create the regressor* **    
reg = linear_model.LinearRegression()***3) Create the prediction space* **    
prediction_space =  np.linspace(min(X_fertility),max(X_fertility)).reshape(-1,1)***4) Fit the model to the data* **    
reg.fit(X_fertility,y)***5) Compute predictions*** 
y_pred = reg.predict(prediction_space)***6) Plot regression line***       
plt.plot(prediction_space, y_pred,  color='black', linewidth=3)       plt.show()

***1) Import Decision Tree Regressor***
from sklearn.tree   import DecisionTreeRegressor***2) Create a decision tree regression model* **  
decision_tree = DecisionTreeRegressor() ***3) Fit the model to the training features  and targets* **     decision_tree.fit(train_features,train_targets) ***4) Check the score on train and test* **    print(decision_tree.score(train_features,   train_targets))       print(decision_tree.score(test_features,test_targets))

最后,还有两个回归算法:

高斯过程回归模型(GPR)和支持向量机(SVM)回归

感谢阅读!!

如果你想继续阅读这样的故事,你可以在这里订阅!

如果你想看看这些算法在真实世界的数据集中表现如何,我建议你阅读下一篇文章:

[## 泰坦尼克号数据集的特征工程和算法精度

机器学习最流行的数据集之一对应于泰坦尼克号事故

towardsdatascience.com](/feature-engineering-and-algorithm-accuracy-for-the-titanic-dataset-5891cfa5a4ac)

或者阅读这个项目,我正在处理来自我的研究的数据:

[## 石油和天然气工程项目中的数据科学。

探索性数据分析

towardsdatascience.com](/datascience-in-oil-and-gas-engineering-projects-daace6e6c7f)

监督学习,但是更好:半监督学习

原文:https://towardsdatascience.com/supervised-learning-but-a-lot-better-semi-supervised-learning-a42dff534781?source=collection_archive---------14-----------------------

来源: Pixabay

为什么半监督学习是 ML 的未来

监督学习是人工智能领域探索的第一种学习类型。自从它的概念提出以来,无数的算法——从简单的逻辑回归到大规模的神经网络——已经被研究以提高准确性和预测能力。

然而,一项重大突破表明,添加无监督数据可以提高泛化能力和性能。事实上,在无数的场景中,带标签的数据并不是现成的。半监督学习可以在标准任务上取得最先进的结果,只需要一小部分标记数据——数百个训练样本。

在我们对半监督学习的探索中,我们将涵盖:

  1. 半监督学习简介。什么是半监督学习,它与其他学习方法相比如何,半监督学习算法的框架/思想过程是什么?
  2. 算法:半监督 GANs 。与传统 gan 的比较,半监督 gan 的过程和性能的解释。
  3. 机器学习的用例与未来。为什么半监督学习会有这么大的需求,在哪里可以应用。

半监督学习简介

半监督学习算法代表了监督和非监督算法之间的中间地带。虽然没有正式定义为机器学习的“第四”元素(监督、非监督、强化),但它将前两者的各个方面结合成了自己的方法。

这些算法对有一些标签的数据进行操作,但大部分是无标签的。传统上,人们要么选择监督路径,只对带有标签的数据进行操作,从而极大地减小数据集的大小;否则,人们会选择无监督的路线并丢弃标签,同时保留数据集的其余部分用于类似聚类的工作。

作者创建的图像。

在真实世界的数据中,情况往往如此。由于标注非常昂贵,尤其是在大多数数据集存在的量级上,大型数据集(尤其是用于企业目的的数据集)可能只有几个标注。例如,考虑确定用户活动是否具有欺诈性。在一百万个用户中,公司知道有一万个用户是这样,但是其他九万个用户可能是恶意的,也可能是良性的。

半监督学习允许我们对这些类型的数据集进行操作,而不必在选择监督学习或无监督学习时进行权衡。

通常,半监督学习算法在这个框架上运行:

  1. 半监督机器学习算法使用有限的一组标记样本数据来训练自己,从而产生一个“部分训练”的模型。
  2. 部分训练的模型标记未标记的数据。因为样本标记数据集有许多严重的限制(例如,现实世界数据中的选择偏差),标记的结果被认为是“伪标记”数据。
  3. 标记和伪标记数据集相结合,创建了一种独特的算法,结合了监督和非监督学习的描述和预测方面。

半监督学习使用分类过程来识别数据资产,并使用聚类过程将其分组为不同的部分。

算法:半监督 GAN

半监督 GAN(Semi-Supervised GAN,缩写为 SGAN)是生成对抗网络架构的变体,用于解决半监督学习问题。

在传统的 GAN 中,训练一个鉴别器来预测图像是真实的(来自数据集)还是伪造的(由生成器模型生成),允许它从图像中学习鉴别特征,即使没有标签。虽然大多数人通常使用 GANs 中的生成器(该生成器已被训练为生成与数据集中的图像相似的图像)来生成真实生成的图像,但也可以通过迁移学习使用鉴别器作为起点来开发同一数据集上的分类器,从而使受监督的任务受益于无监督的训练。由于已经学习了大多数图像特征,所以执行分类的训练时间和准确度将会好得多。

然而,在 SGAN 中,鉴别器同时以两种模式训练:无监督和有监督。

  • 无监督中,鉴别器需要区分真实图像和生成的图像,就像在传统的 GAN 中一样。
  • 在【T4 监督】中,鉴别器需要将图像分类到预测问题中的几个类别中,就像在标准的神经网络分类器中一样。

为了同时训练这两种模式,鉴别器必须输出 1 + n 节点的值,其中 1 表示“真或假”节点,而 n 是预测任务中的类别数。

在半监督 GAN 中,鉴别器模型被更新以预测 K+1 个类,其中 K 是预测问题中的类的数量,并且附加的类标签被添加用于新的“假的”类。它包括同时为非监督 GAN 任务和监督分类任务直接训练鉴别器模型。整个数据集可以通过 SGAN 传递-当训练示例有标签时,调整鉴别器的权重,否则,忽略分类任务,鉴别器调整其权重,以更好地区分真实图像和生成的图像。

作者创建的图像。

虽然允许 SGAN 无监督地训练允许模型从非常大的未标记数据集中学习非常有用的特征提取,但监督学习允许模型利用提取的特征并将其用于分类任务。结果是一个分类器,即使在非常非常少的标记样本(几十到几百个)上训练,它也能在像 MNIST 这样的标准问题上取得令人难以置信的结果。

SGAN 巧妙地结合了非监督学习和监督学习的各个方面,以相互加强,允许两个世界的最佳部分一起工作,以最少的标签产生令人难以置信的结果。

机器学习的使用案例和未来

在一个可用数据量不断呈指数增长的时代,无监督的数据根本不能停下来等待标签赶上。无数真实世界的数据场景都是这样出现的——例如,YouTube 视频或网站内容。从爬行引擎和内容聚合系统到图像和语音识别,半监督学习无处不在。

半监督学习结合监督学习和非监督学习(分别)的过度拟合和“欠拟合”趋势的能力创建了一个模型,该模型可以在泛化的同时出色地执行分类任务,给定最少量的标记数据和大量的未标记数据。除了分类任务之外,半监督算法还有其他广泛的用途,如增强聚类和异常检测。尽管该领域本身相对较新,但算法仍在不断被创造和完善,因为它们在当今的数字世界中有着巨大的需求。

半监督学习确实是机器学习的未来。

监督学习是不够的

原文:https://towardsdatascience.com/supervised-learning-is-not-enough-8254814dfcc5?source=collection_archive---------33-----------------------

为了在人工智能方面取得进展,我们的模型需要学会应对混乱的现实世界

谢尔盖·阿库利奇在 Unsplash 上的照片

在 2002 年的一次新闻发布会上,美国国防部长唐纳德·拉姆斯菲尔德解释了情报报告的基本局限性:

“有已知的已知;有些事情我们知道我们知道。我们也知道有已知的未知;也就是说,我们知道有些事情我们不知道。但也有未知的未知——那些我们不知道自己不知道的。如果纵观我们国家和其他自由国家的历史,后一类往往是困难的。”

这句名言蕴含着深刻的智慧,我们可以将其转化为机器学习研究。通常,我们收集一些数据,并将这些数据分成训练集和测试集。一个成功的模型将能够预测测试集中的许多实例:这些是已知的知识。对于测试集中的其他实例,即已知的未知量,就不那么确定了。

然而,在这种传统的、有监督的学习体系中,未知的未知是缺失的。根据定义,只有当 ML 模型被部署到生产中时,我们才会遇到未知的未知,在那里它会遇到真实的世界。当这种情况发生时,事情可能会出错,因为模型不知道正在发生什么,同时又对其预测过于自信。

开集识别

因此,监督学习不一定足以应对现实世界。现实世界简直太乱了,它往往会向我们扔新的东西。

这里有一个聪明的方法来测试这个想法:在 MNIST 数据上训练一个机器学习模型,但在训练期间只给它显示数字 0,1,2,3,4,5。然后,在测试过程中,向它显示整个数字范围。会有怎样的表现?

当在训练期间只看到类的子样本时,根据 MNIST 数据训练的模型的退化。[1]

结果很糟糕(见上面的蓝色曲线)。随着我们在训练过程中遗漏越来越多的类,准确度从接近 1 下降到大约 0.6。研究人员 Lalit Jain 及其合作者在 2014 年展示了这一结果。他们还提出了一种新的 ML 算法,以更好的方式推广到“未知的未知”(上面的红色曲线)——当然,警告是,这些未知的未知实际上是研究人员事先知道的。

开集识别是训练 ML 模型的挑战,这些模型不仅在已知数据上表现良好,还能识别是否有全新的东西扔给它们——并相应地调整预测的不确定性。解决这个问题是在现实世界中部署模型的重要一步。

如果模型能在不确定的时候问我们就更好了。

主动学习

主动学习的想法简单而有力。假设我们有一个大的未标记的数据池,和一个小的已标记的数据样本。然后,在已标记的数据上训练一个 ML 模型,并让该模型对未标记的数据实例进行排序,例如通过它对标签的不确定程度。选择最不确定的实例,由人类标记它们,将它们添加到标记的训练集中,并重新训练。

主动学习循环。[2]

如果未标记池是有限的,只需重复循环,直到标记了足够多的数据。然而,在现实世界中,未标记的池可能是无限的:在现代生产系统中,每秒钟都会产生新数据。

这是所有事情是如何组合在一起的:在现实世界中,我们需要擅长开集识别的模型,擅长识别一个新样本是否是以前从未经历过的,一个未知的未知。我们需要主动学习循环,以便模型可以在人类专家的帮助下快速有效地填补知识空白。这两个领域的进展对于现实世界的 ML 应用至关重要。

最后的想法

我在之前的帖子中提到了伊莱恩·赫尔茨贝格的惨死。2018 年 3 月 18 日晚上,赫尔茨贝格在亚利桑那州坦佩市的一条街道上骑车时,被一辆自动驾驶汽车撞了。尽管汽车模型已经在大量驾驶数据的基础上进行训练,但这些数据错过了足够多的行人骑自行车过马路的例子。对这个模型来说,赫尔茨贝格是一个未知的未知数。

图像数据中的长尾问题示例。[3]

不管我们用多少数据来训练我们的模型,模型总是会遗漏一些东西。这就是著名的长尾问题。然而我们人类是不同的:我们不仅仅是学习模式,我们有一种“为什么”我们看到的事物是这样的感觉。这种从第一原理进行推理的形式使我们能够推广到未知的长尾,这是监督 ML 模型中所缺少的技能。

实际上,一个模型永远不会真正“完成”学习。在现实世界的场景中,学习过程必须无限期地继续下去。监督学习是不够的。此外,模型需要善于识别未知的未知,更好的是,在最需要的时候主动要求我们澄清。

参考资料和进一步阅读

[ 1 ] Jain 等,利用包含概率的多类开集识别
[ 2 落定,主动学习文献综述
[ 3 刘等,开放世界中的大规模长尾识别

[## 智能行为的起源

为什么真正的人工智能需要的不仅仅是模式识别

towardsdatascience.com](/the-origin-of-intelligent-behavior-3d3f2f659dc2)

监督学习——什么,什么时候,为什么,好与坏(第一部分)

原文:https://towardsdatascience.com/supervised-learning-the-what-when-why-good-and-bad-part-1-f90e6fe2a606?source=collection_archive---------61-----------------------

深入回归

深度学习并不总是大数据问题的答案

通常在工作场所,业务利益相关者和经理会将机器学习和大数据与深度学习联系起来。他们通常认为所有数据问题的最佳解决方案是深度学习、人工智能或神经网络,或者这些技术的某种组合(插入你最喜欢的流行语)。作为一个有统计学背景的人,我发现这种观点非常令人沮丧,因为选择的机器学习算法类型应该基于五个关键因素:

选择机器学习算法时的 5 个关键考虑因素

  1. 数据问题的类型——即监督与非监督
  2. 数据集内的变量类型,即分类或数值
  3. 验证统计模型的基本假设
  4. 由此产生的模型精度
  5. 精确度与召回率以及灵敏度与特异性之间的平衡(用于分类

在接下来的几个部分和几篇博文中,我将介绍不同类型的监督学习模型,并将上述考虑应用于每一个模型。

监督学习

很多时候,数据问题需要监督学习的应用。这是当你确切地知道你想要预测什么— 目标或因变量,并且有一组自变量预测变量时,你想要更好地理解它们对目标变量的影响。然后,模型的选择基于将数据中的基本模式映射到依赖于数据分布和变量类型的函数。

名称“监督学习”用于描述这些类型的模型,因为模型在训练集上学习基础模式。迭代/循环的次数决定了模型有机会从过去学习的次数。在随后的每一轮中,模型都会根据在之前的运行中所学到的知识,尝试提高模型的准确性(由用户选择的准确性度量)。模型在达到最大运行次数后或不再能提高模型精度时停止运行(在某些模型中由提前停止指定)。

有两种类型的监督学习算法,如下图所示,其中结果变量的类型决定了您是选择回归还是分类。

图 1:监督学习模型的类型

我们先来钻研一下回归。

回归

人们通常认为一切都是线性回归问题,但事实并非如此。R 回归算法有一套非常严格的假设,必须满足这些假设,才能使最终结果在统计上可靠(**注:我没有写统计意义上的*)。

为什么要回归?

回归分析是一种预测算法,常用于时间序列分析和预测。这是因为它模拟了预测变量和因变量之间的潜在关系,并确定了预测变量的值的变化如何解释结果变量的变化。

有几种类型的回归算法,但我将集中在下面的几个。

图 2:回归的类型

在我进一步探索上述回归技术之前。让我们了解一下与回归技术相关的假设。

回归假设

  1. 回归线的残差呈正态分布— 为确保回归模型的结果有效,残差(观察值和预测值之间的差值)应遵循正态分布(平均值为零,标准偏差恒定)。残差也称为误差项,它们的分布可以在正态概率图上观察到(Q-Q)。如果大多数残差位于正态对角线上,那么我们可以假设它们是正态的。

图 3:用于检查正态性的密度图

2。数据集中的变量来自正态分布总体 —数据中的所有变量也应该来自正态分布总体。通常,在统计学中,如果样本量足够大,则可以根据中心极限定理假设正态性。在一些教科书中,它也低至 n = 30。

3。残差是独立的— 检查该假设以避免残差中的自相关。当数据集中存在自相关时,可能会导致低估标准误差,进而使预测值看起来具有统计学意义,即使它们并不具有统计学意义。

  • 杜宾-沃森测试可用于检查自相关性。零假设是残差不是线性自相关的。德宾-沃森的 d 可以取 2 到 4 之间的任何值,但是 1.5 到 2.5 之间的 d 的经验法则值用于指示残差中缺乏自相关。
  • 注意:德宾-沃森测试只能证明直接相邻者之间的线性自相关(一阶效应)。

图 4:残差的随机分布(同方差)

图 5:残差的扇形展开(异方差)

4。数据显示同方差— 当残差沿最佳拟合线均匀分布而不是显示一种模式时,数据中出现同方差(残差具有恒定方差)。当存在异方差时,残差的形状可能呈现扇形(锥形)甚至线性趋势。

  • 通过将残差(y 轴)与预测值(x 轴)绘制到散点图上,并寻找点的随机分散而不是任何聚类或模式,可以评估同方差性。异方差的统计检验是戈德菲尔德-匡特检验。它包括将数据集分成两组,并检查两组之间的残差方差是否相似。

图 6:所示的正线性关系

5。关系是线性的 —进行线性回归(一元或多元)时,自变量和因变量之间的关系必须是线性的。从视觉上看,这可以通过在每个自变量和因变量对之间创建一个散点图来确定,并检查是否有一条可以通过这些点绘制的直线。

图 7:异常值由实心圆表示

5.没有显著的/有影响的异常值 —异常值通常是数据集中偏离平均值+/- 3 个标准偏差或超出箱线图的点。由于异常值是极值,它们会对最佳拟合线的斜率产生显著影响。

  • 异常值可以在箱线图(位于须状物外部的点)或直方图的偏斜度中直观地识别出来。
  • 为了确定异常值是否有影响,*有两个统计指标可以使用: 1)库克距离和 2)马氏距离*
  • Cook's Distance 检查当数据集中的每个观察值被移除时,回归系数如何变化,从而检查它们的影响。数据集中的每个值都被赋予一个库克距离值。厨师的距离越大,观察的影响越大。用于确定某个值是否为异常值的一个典型试探法是检查库克的 D 值是否大于 4/n (其中 n 是数据集的大小)。
  • **Mahanalobis 距离测量每个观察值距离大多数数据点(或平均值)有多远(多少标准差),通常用于多元数据集。该距离可以使用具有 n 个自由度的卡方分布来近似计算。计算数据集中每个观察值的 p 值。检查 p 值是否小于显著性水平(即 0.01),以确定它们是否极端。

6.自变量之间没有多重共线性当自变量彼此相关时,多重共线性出现。如果是这种情况,通常您希望回归模型中只包含变量对中的一个变量。这个假设可以用三种方法来检验。*

*不适用于简单线性回归

  • 方差膨胀因子(VIF) : 如果变量的 VIF 值大于 10,则变量是多重共线的。

图 7:波士顿住房数据集的相关图

  • 【相关系数(r) :创建所有变量对之间的相关矩阵。如果相关系数大于或等于-/+ 0.7,则变量高度相关。
  • 容差 该指标衡量每个自变量如何影响所有其他自变量,由等式 T = 1 — R 平方定义。通过对剩余的独立变量进行回归,可以计算每个独立变量的 r 平方(决定系数)。通常使用 0.1 的容差系数,当 T < 0.1 时,这表明数据集中存在多重共线性。

回归假设概述

让我们通过对波士顿住房数据运行回归诊断来测试我们已经学到的一些概念。

图 8:残差的诊断图

  1. 残差与拟合值— 该图用于检查线性度。假设这条线是水平的,没有任何明显的图案,我们可以假设它是线性关系。
  2. 正常 Q-Q 。该图用于检查残差的正态性。由于大部分残差都在对角线上,所以满足这个假设。
  3. 标度位置(或分布位置)——该图用于检查残差的方差是否均匀(同质方差)。我们正在寻找一条水平线,在这条线的上下有平均分布的残差。在这种情况下,线有一些曲率,这意味着我们有一些异方差。
  4. 残差 vs 杠杆。此图用于确定有影响的观察结果或那些有杠杆作用的观察结果。图中标记的点似乎是有影响的。通过去除这些,我们也可以解决异方差问题,因为相同的观察值在前面的图中被标记。

现在让我们看看常用于评估模型性能的统计数据。

评估模型性能

有几个指标可以用来衡量回归模型的准确性。我已经描述了我在构建模型时常用的方法。

  • R 平方 :决定系数衡量自变量的变化可以解释多少结果变量的变化。更高的 R 平方值被视为反映了更高的模型精度。然而,当模型中有多个预测器时, R 平方不可信。这是因为每个预测值都会影响 R 平方值。在这些情况下,使用调整的 R 平方更可靠。在决定是否信任 R 平方值时,需要该领域的专业知识。例如,在化工厂等受控环境中, R 平方可能相当高(接近 90%);然而,当模拟人类行为时,高的 R 平方值可以代表过拟合。在这些情况下,最好使用以下任何指标来验证您的模型。
  • RMSE(均方根误差): 计算为预测值与观测值之间方差的平方根(残差)。该值越低,模型拟合得越好。 RMSE 在某些情况下是更好的度量,因为它惩罚大的误差(残差)。
  • MAE(平均绝对误差): 这个度量比 RMSE 简单,只是对残差的绝对值求和。它受异常值的影响较小。每个残差对等式中的总误差有成比例的贡献。同样,值越低越好。

我们终于可以深入了解各种类型的回归算法。

最小二乘回归

线性回归,也称为最小二乘回归,使用独立变量来逼近结果变量的最佳拟合线。它是一个试图最小化平方差之和的加权方程,由以下方程表示,其中 y 是预测的因变量,每个 β 是对应于每个自变量或 x 的系数,β₀ 是 y 截距, e 是误差项。

最小二乘回归方程的数学表示

简单线性回归中,只有一个系数和一个自变量。为多元线性回归中包含的每个自变量( x) 添加一个系数项( β)

解释线性回归方程

让我们从 y 轴截距或常数开始, β₀.是所有自变量( X) 均为零时 y 的预测值。它通常也是预测的 y. 的平均值

对于连续预测变量的系数,其解释如下。保持所有其他变量不变, X ₁每增加 1 个单位, y 将增加(如果 β为正)或减少(如果 β为负)平均增加 β个单位

对于线性回归,分类自变量编码为 0 或 1(虚拟变量)。因此,当解释它们的系数时,即 y 的预测值的差异,一个单位的差异表示从一个类别切换到另一个类别,同时保持所有其他变量不变。

多项式回归

当自变量和因变量之间的关系本质上是非线性的并且包括曲率时,多项式回归可以被认为是一种选择。

图 6:多项式回归示例

在左边的图中,我们可以看到多项式回归(到 2 的数量级)比直线拟合略好。

每个独立变量的多项式回归方程如下所示。对于变量被提升到的每一阶,在等式中为变量添加一个附加项。

继续将方程提升到更高次的多项式以获得最佳拟合可能是诱人的;然而,这会导致过度配合过度拟合发生在试图解释尽可能多的点时,包括数据集(即训练集)中的随机误差,使得难以推广到其他数据集(即测试集)。

多项式回归方程的数学表示

逐步回归

逐步回归就像它的名字一样,涉及在线性模型中添加(从模型中没有独立变量开始的正向选择)或移除(从完整模型或模型中的所有独立变量开始的反向选择)独立变量,以基于模型评估度量找到因变量的最佳预测子集。

**前向选择在模型评估度量不再有改进时停止(即 R 平方停止增加),而 b 后向选择在最无影响的(即那些对 R 平方有贡献的)独立变量被移除后停止。

R 的回归

线性回归

坚持波士顿住房数据集,我对所有预测变量对中值房价进行了线性回归(“lm”)。请注意,在运行模型之前,我没有“处理”多重共线性、正态性和异常值问题。

*> linearMod <- lm(medv ~ ., data=Boston) 
> summary(linearMod)Call:
lm(formula = medv ~ ., data = Boston)Residuals:
    Min      1Q  Median      3Q     Max 
-15.595  -2.730  -0.518   1.777  26.199Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  3.646e+01  5.103e+00   7.144 3.28e-12 ***
crim        -1.080e-01  3.286e-02  -3.287 0.001087 ** 
zn           4.642e-02  1.373e-02   3.382 0.000778 ***
indus        2.056e-02  6.150e-02   0.334 0.738288    
chas         2.687e+00  8.616e-01   3.118 0.001925 ** 
nox         -1.777e+01  3.820e+00  -4.651 4.25e-06 ***
rm           3.810e+00  4.179e-01   9.116  < 2e-16 ***
age          6.922e-04  1.321e-02   0.052 0.958229    
dis         -1.476e+00  1.995e-01  -7.398 6.01e-13 ***
rad          3.060e-01  6.635e-02   4.613 5.07e-06 ***
tax         -1.233e-02  3.760e-03  -3.280 0.001112 ** 
ptratio     -9.527e-01  1.308e-01  -7.283 1.31e-12 ***
black        9.312e-03  2.686e-03   3.467 0.000573 ***
lstat       -5.248e-01  5.072e-02 -10.347  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1Residual standard error: 4.745 on 492 degrees of freedom
Multiple R-squared:  0.7406, Adjusted R-squared:  0.7338 
F-statistic: 108.1 on 13 and 492 DF,  p-value: < 2.2e-16*

上面我们可以看到调整后的 R 平方值为 73.38%* ,也就是说房价中位数的这个变化量可以用模型中的预测变量来解释。这是一个非常好的 R 平方值,并且 p 值< 0.05 表示统计显著性。*

接下来,我将确定哪些变量对这个 R 平方统计有贡献。我可以看到,除了印度河年龄都是非显著贡献者(p 值> 0.05)。

让我们看看如果我运行逐步回归会发生什么。

逐步回归

向后

让我们首先尝试解释对模型的调用。

  • 我的因变量(medv)已经针对所有自变量进行了回归。)
  • 我使用了逆向回归
  • 该模型将被调整以尝试由 1 到 13 个变量组成的模型。
*# Set seed for reproducibility
> set.seed(123)
> # Set up repeated k-fold cross-validation (10 fold)
> train.control <- trainControl(method = "cv", number = 10)
> # Train the model
> step.model <- train(medv ~ ., data=Boston,
+                     method = "leapBackward", 
+                     tuneGrid = data.frame(nvmax = 1:13),
+                     trControl = train.control
+ )
> step.model$results
   nvmax     RMSE  Rsquared      MAE    RMSESD RsquaredSD     MAESD
1      1 6.190699 0.5542196 4.512277 0.6480792 0.03585104 0.5143497
2      2 5.537331 0.6393649 3.975099 0.6194193 0.08470812 0.4184383
3      3 5.216943 0.6757786 3.675974 0.7844579 0.09606216 0.3282287
4      4 5.144946 0.6843838 3.621869 0.6838151 0.08435306 0.3033078
5      5 4.998163 0.7010740 3.543459 0.7416779 0.08756225 0.2999431
6      6 5.048162 0.6953426 3.520865 0.7245789 0.08673190 0.2717374
7      7 5.049469 0.6952020 3.500608 0.6987592 0.08276566 0.2597508
8      8 5.008368 0.7004709 3.497253 0.6740135 0.08021108 0.2756674
9      9 5.012961 0.7018661 3.490065 0.6963818 0.08564270 0.2683468
10    10 4.947244 0.7098667 3.447318 0.6896883 0.08705085 0.2222943
**11    11 4.809318 0.7249622 3.359429 0.6861143 0.08341394 0.2409937**
12    12 4.825967 0.7231964 3.365846 0.6808653 0.08309689 0.2442360
13    13 4.829796 0.7227732 3.368084 0.6796633 0.08336179 0.2455718
> step.model$bestTune
   nvmax
11    11> summary(step.model$finalModel)
Subset selection object
13 Variables  (and intercept)
        Forced in Forced out
crim        FALSE      FALSE
zn          FALSE      FALSE
indus       FALSE      FALSE
chas        FALSE      FALSE
nox         FALSE      FALSE
rm          FALSE      FALSE
age         FALSE      FALSE
dis         FALSE      FALSE
rad         FALSE      FALSE
tax         FALSE      FALSE
ptratio     FALSE      FALSE
black       FALSE      FALSE
lstat       FALSE      FALSE
1 subsets of each size up to 11
Selection Algorithm: backward
          crim zn  indus chas nox rm  age dis rad tax ptratio black lstat
1  ( 1 )  " "  " " " "   " "  " " " " " " " " " " " " " "     " "   "*"  
2  ( 1 )  " "  " " " "   " "  " " "*" " " " " " " " " " "     " "   "*"  
3  ( 1 )  " "  " " " "   " "  " " "*" " " " " " " " " "*"     " "   "*"  
4  ( 1 )  " "  " " " "   " "  " " "*" " " "*" " " " " "*"     " "   "*"  
5  ( 1 )  " "  " " " "   " "  "*" "*" " " "*" " " " " "*"     " "   "*"  
6  ( 1 )  " "  " " " "   " "  "*" "*" " " "*" " " " " "*"     "*"   "*"  
7  ( 1 )  " "  " " " "   " "  "*" "*" " " "*" "*" " " "*"     "*"   "*"  
8  ( 1 )  "*"  " " " "   " "  "*" "*" " " "*" "*" " " "*"     "*"   "*"  
9  ( 1 )  "*"  " " " "   " "  "*" "*" " " "*" "*" "*" "*"     "*"   "*"  
10  ( 1 ) "*"  "*" " "   " "  "*" "*" " " "*" "*" "*" "*"     "*"   "*"  
11  ( 1 ) "*"  "*" " "   "*"  "*" "*" " " "*" "*" "*" "*"     "*"   "*"*

在上面的例子中,我用 10 倍交叉验证和 13 个最大变量进行了逐步回归。我没有全部使用它们,因为我们知道在之前运行全线性模型时,有两个并不重要。我们可以看到,最佳模型由 11 个变量组成(最低的 RMSE、最低的 MAE 和最高的 R 平方)。

星号()表示变量包含在相应的模型中。最好的 11 变量模型包括除了印度河流域和年龄以外的所有变量,就像完全线性模型一样。*

向前逐步回归给出了与完全线性模型和向后回归相似的结果。

*> set.seed(123)
> train.control <- trainControl(method = "cv", number = 10)
> step.model <- train(medv ~ ., data=Boston,
+                     method = "leapForward", 
+                     tuneGrid = data.frame(nvmax = 1:13),
+                     trControl = train.control
+ )
> step.model$results
   nvmax     RMSE  Rsquared      MAE    RMSESD RsquaredSD     MAESD
1      1 6.190699 0.5542196 4.512277 0.6480792 0.03585104 0.5143497
2      2 5.537331 0.6393649 3.975099 0.6194193 0.08470812 0.4184383
3      3 5.216943 0.6757786 3.675974 0.7844579 0.09606216 0.3282287
4      4 5.243481 0.6736566 3.658219 0.7510340 0.08224804 0.3304744
5      5 5.098698 0.6904107 3.568604 0.7354806 0.08392928 0.2726078
6      6 5.045755 0.6953140 3.512300 0.7223225 0.08606320 0.2787373
7      7 4.969144 0.7036333 3.448631 0.7542104 0.08842114 0.2944921
8      8 4.985899 0.7027153 3.456932 0.7099500 0.08432911 0.2895184
9      9 4.985690 0.7030156 3.466382 0.6879376 0.08295944 0.2782166
10    10 4.912877 0.7137519 3.421565 0.6865803 0.07813425 0.2716994
11    11 4.809318 0.7249622 3.359429 0.6861143 0.08341394 0.2409937
12    12 4.825967 0.7231964 3.365846 0.6808653 0.08309689 0.2442360
13    13 4.829796 0.7227732 3.368084 0.6796633 0.08336179 0.2455718
> step.model$bestTune
   nvmax
11    11*

正规化

正则化是一种常用于解决回归中可能出现的过度拟合和多重共线性问题的技术。这是通过在目标函数中增加一个惩罚项来实现的,目标函数的目的是减少标准误差。

里脊回归

在岭回归中,增加了一个惩罚项(收缩参数)λ,以减少 β 系数项中的较大变化。 L2 正则化用于骑行回归,目标是通过试图使系数更接近零来最小化系数平方的 s um。

岭回归适用于包含大量变量的小型数据集,具有小到中等的效果。

套索回归

Lasso(最小绝对收缩和选择算子)回归使用 L1 正则化,其中λ被添加到系数的绝对平方和。

Lasso 回归适用于变量较少但对因变量有中到大影响的数据集。

弹性网络回归

ElasticNet 结合了套索和岭回归技术,其中应用了 L1 和 L2 正则化。

选择正则化参数

在决定使用哪个正则化参数时,我们可以基于两种方法:1)选择λ,其中信息标准最小化(如 AIC 或 BIC),侧重于模型拟合;2)运行交叉验证模型,并选择λ值,使交叉验证残差最小化,侧重于预测精度。

回归的利与弊

优点

  • 易于理解并向利益相关者展示
  • 可用于解释——即每个预测因素对结果变量的相对影响

缺点

  • 将所有独立变量标准化(定标和居中)以避免多重共线性非常重要
  • 需要检查严格的模型假设

这就是我关于回归的全部内容。我的下一篇博文将是关于分类算法的。

监督机器学习模型:你在实践中必须做出的决定

原文:https://towardsdatascience.com/supervised-machine-learning-models-decisions-you-have-to-make-in-practice-ef23d565aa4b?source=collection_archive---------67-----------------------

聚在一起—选择哪种模式?要调整哪些超参数?如何评价?

虽然我提供了机器学习模型背后的一些直觉,但本文的重点不是解释机器学习模型背后的数学,而是它们的实际应用,即我将尝试回答使用什么、如何调优、如何评估等问题。本文讨论了数据科学家在尝试将模型与给定数据相匹配时需要考虑的任务、挑战、假设、利弊和注意事项。

通过 monkeylearn 生成的 Wordcloud

偏差-方差权衡

所有的模型都遭受这种权衡。理解这一点对于调整机器学习模型的性能来说是微不足道的。假设我们有一个数据集,我们已经拟合了一个 ML 模型。

一个好的模型应该是一致的,并且能够处理训练数据集中的任何变化,而本身没有太大的变化,也就是说,它应该已经对看不见的数据进行了推广(这是我们首先要达到的目标)。模型由于训练数据集中的变化而变化的量被解释为模型的方差。

偏差可以解释为模型倾向于较少的预测变量。具有非常高的偏差会使模型对数据的变化(较低的方差)不敏感,并导致对情况的不良近似。另一方面,较低的偏差会使模型利用所有不必要的信息,并允许较高的方差。

总之,考虑到模型和数据的需求和使用,这是一个数据科学家必须明智选择的权衡。

简单线性回归

让我们从简单开始,假设我们有一个斜率为 m、Y 轴截距为 c 的直线方程,给定这条直线,我们可以计算任意特定 X 值的 Y 值。简单 LR 旨在估计直线(称为回归线)的斜率和截距,该直线在某种程度上最适合所有数据点,即最小化残差平方和(称为最小二乘法)。

可能的情况是,我们将有一个零斜率(m)。这在某种程度上传达了 Y 对 X 值的独立性。我们使用零假设检验来检测这种行为,该检验确定 m 是否足够远离零。在实践中,我们使用 p 值,它在某种程度上告诉我们数据独立于预测变量的概率。我们从零假设假设的 t 分布中得到这个概率。最后,我们只需查看 p 值,如果它小于 0.05(一般情况下),我们可以拒绝零假设。

一旦我们拒绝零假设,我们想知道我们的模型有多好地符合数据。为此,我们使用 R 平方度量(我们也可以使用 RSE,但是 RSE 依赖于 Y 的单位,不能推广到任何数据)。R-square 接近 1 意味着我们的 LR 模型解释了 Y 的可变性,是一个很好的拟合。如果 R 平方接近于 0,那么可能有两个原因。(参考下面的可解释差异部分)

多元线性回归

如果我们有不止一个预测变量呢?我们可以将简单的 LR 从直线扩展到多维超平面来拟合数据。想象一下,假设我们有两个预测变量。现在,我们在 3D 空间中拟合一个平面,其中响应是这两个预测变量的函数,具有一些截距。这可以进一步扩展到更高维度。

我们使用 f 统计量来检验零假设。尽管我们有单个预测因子的 p 值,为什么我们要看总体的 F 统计量?当有大量预测因子(比如 100 个)时,那么只是偶然地,我们保证观察到至少一个 p 值低于 0.05 的预测因子,即使在预测因子和反应之间没有真正的联系。但是,f-statistic 不会受此影响,因为它会根据预测值的数量进行调整。

一旦我们拒绝零假设,我们可能不得不选择只有重要的预测,以减少计算需求。这是使用子集选择方法完成的。

我们使用 R-square 来评估模型的拟合度。然而,需要注意的一点是,当我们包含更多的预测因子时,R-square 会得到改善。由我们来决定计算需求和模型拟合之间的权衡。此外,以更高的 R 平方为目标可能会导致过度拟合问题。

多项式回归

它被认为是线性回归,因为它在预测系数中是线性的

观察多重 LR,我们看到两个主要假设。首先,特定预测变量的变化对响应 Y 的影响独立于任何其他预测变量。(加法假设)。第二,由于预测变量的单位变化引起的响应 Y 的变化是恒定的。(线性假设)。

然而,我们的数据可能并不总是如此。我们可能不得不考虑更高程度的预测变量来恰当地拟合数据(注意:这就是过度拟合和偏差-方差概念出现的地方。此外,了解协同效应(即预测变量之间的交互效应)也是值得的

我们必须选择什么程度的预测变量?这是我们作为数据科学家试图解决的问题,选择这个程度和交互术语(称为特征工程)取决于我们。没有直接的答案或解决方案来处理这个问题。但是,可以使用残差图采用试错法。

残差图中,残差(真实响应估计响应)相对于估计响应值绘制,这将揭示关于假设模型的一些见解。如果残差图没有显示模式,那么假设的模型与数据吻合得很好。否则,假设的模型会有一些问题,我们可能需要调整多项式的次数。

一旦我们最终确定了我们的模型,我们使用 R-square 评估拟合。我们必须注意,拥有更高程度的预测变量可能会过度拟合数据(看看偏差-方差权衡)。

KNN 回归

到目前为止,我们一定已经理解了在线性回归设置中假设一个合适的模型来很好地拟合数据是非常重要的。KNN 回归消除了这种必要性,更加灵活。因此,如果预测准确性是我们的目标,给定足够的数据,KNN 优于线性回归。但是,这里有一个陷阱。“给定足够的数据”让我们陷入维度诅咒。KNN 回归是数据饥渴的,在更高的维度,实际上,永远不会有足够的数据,因此 KNN 比 LR 回归表现更差。此外,LR 更容易解释,因为它估计了每个预测因子对反应的影响。另一方面,KNN 是不可解释的,因为它只遵循数据,不关心预测。

当每个预测值的观测值较少时,参数方法往往优于非参数方法

逻辑回归

它特别用于两个类的分类设置中(可以调整为两个以上,但效率不高,因此这里不讨论)。它不是模拟响应 Y,而是利用逻辑函数来模拟 Y 属于特定类别的概率。这种分析可以用来观察特定预测变量的变化如何影响反应的几率。

通过最大化似然函数找到逻辑回归系数的估计。z 统计量类似于 t 统计量,用于执行零假设检验。较大的 z 统计量表示反对零假设的证据。使用分类错误率对逻辑回归模型进行评估。

当类被很好地分开时,逻辑回归不能在看不见的数据点上产生有希望的结果,即,即使对于数据中的小变化,它也是高度不稳定的。此外,在数据遭受“维数灾难”的更高维度中,由于缺乏足够的数据导致非常高的不稳定性,逻辑回归不能很好地执行。

贝叶斯分类器

它是一种理想的分类器,利用贝叶斯定理找出属于每一类的数据点的概率。数据点 X 的后验概率或类别 Y 的概率与类别 Y 的先验概率和 X 属于 Y 的类别条件概率的乘积成比例

它以最小的误差拟合数据。但不幸的是,我们不知道数据的确切类别条件概率和先验概率,我们试图在 LDA 和 QDA 的一些假设下进行估计。

线性判别分析:

LDA 可用于多类(> 2)分类设置。首先,我们分别对每一类中预测因子的分布进行建模。然后,我们利用贝叶斯定理找出数据点属于特定类别的概率。

可以使用属于相应类别的数据点的比例来找到每个类别的先验概率。然而,对于类别条件概率,我们必须假设从中提取数据点的分布。

我们假设数据点 X 是从多元高斯分布中提取的,该分布具有特定类别的均值向量和公共协方差矩阵。现在,我们的问题简化为估计每个类别和公共协方差的平均向量。判别方程在 x 上是线性的。

二次判别分析:

这类似于 LDA,除了关于所有类的预测变量的公共协方差的假设。这里,每个类都有自己的协方差矩阵。这导致判别方程在 x 上是二次的。

当决策边界是线性时,LDA 和逻辑回归方法往往表现更好。对于中度非线性边界,QDA 可能表现得更好。对于更复杂的决策边界,在有足够数据的情况下,选择好平滑参数的 KNN 表现得更好。

套索和岭回归

一般来说,我们最小化 RSS(称为最小二乘法)来估计回归设置中的预测系数。然而,由于拟合的灵活性,有时这些估计值可能会有很大的差异。

为了解决这个问题,我们通过向零收缩(正则化)一些预测系数估计值(在山脊的情况下)或通过使其正好为零(在套索的情况下)来惩罚预测系数估计值。岭和套索回归模型背后的直觉是,为了方差的更大减少,在模型偏差的轻微上升上进行妥协。

收缩量取决于一个参数(λ),这个参数必须由作为数据科学家的我们来决定。对于我们选择的每个λ值,产生一组不同的预测系数估计值,即对于每个λ,我们得到一个适合数据的不同模型。

从岭回归方程或套索回归方程中,我们可以观察到预测系数依赖于预测变量的尺度。因此,在对数据应用岭回归或套索回归之前,将数据中的每个预测值归一化至标准差为 1 是非常重要的。

我们使用训练数据的 R 平方值或测试数据的均方差(MSE)来比较每个模型。交叉验证方法可以用来决定λ的值。需要注意的是,在高维设置中,由于缺乏足够的数据,训练 R-square 具有很大的可变性,因此不应用于评估模型性能。

如果响应是许多系数大小大致相似的预测值的函数,则岭回归表现更好。如果少数预测因素主导了反应,那么套索回归表现更好。

决策树

基于树的方法将预测空间分割成多个框(树中的叶子),并对落入该框中的所有数据点进行相同的预测。在回归设置中,该预测通常是该框中所有训练观察的平均值,对于分类设置,多数投票被认为是预测对新数据点的响应。

在树中进行切割时,我们以具有最低可能 RSS(回归树)或分类误差(分类树)的方式决定预测变量及其切割点。对于分类设置,也可以使用像基尼指数和交叉熵这样的度量,因为它们对叶子(或盒子)的纯度更敏感。

作为一名数据科学家,我需要回答一个问题——什么时候我应该停止拆分树,或者我应该制作多少个盒子?

成本复杂度剪枝或者最薄弱环节剪枝:直观上,我们种一棵大树,然后剪枝,选择一棵导致误差最低的树。我们不是考虑所有可能的子树,而是使用一个调整参数α将树修剪到期望的水平。

对于每个阿尔法值,我们将有一个相应的树。随着 alpha 的增加,树被修剪的越来越多,导致分裂越来越少。分割越小,模型的方差越小,但偏差会有所增加。我们可以利用交叉验证来决定 alpha 的值,从而获得数据的最佳拟合。

Bagging(bootstrapped Aggregation):我们利用 bootstrap 方法生成多个数据集,并为每个 Bootstrapped 数据集生成一个深度 Bootstrapped 树。尽管每个自举树都有很高的方差,但是对所有生长的树进行平均将会减少方差。我们利用出包测试误差来评估树的性能。

当预测准确性是我们的目标时,我们使用 Bagging。然而,打包损害了模型的可解释性。另一方面,成本复杂度修剪方法生成可解释树。

随机森林:这是一个有趣而聪明的打包方法,可以去相关生成的树。在 Bagging 中,在构建决策树时,我们允许所有预测变量参与分裂。如果几乎没有主要的预测因素,这个过程可能会产生高度相关的树。

在随机森林中,在每次分裂时,我们允许 m 个预测者的随机样本(大约 sqrt(预测者的数量))参与,从而允许所有预测者参与并进而产生去相关的树。这种方法的优势是显而易见的,因为对不相关的树进行平均会大大降低方差。

支持向量分类器

在进入支持向量分类器之前,我们必须了解最大间隔分类器。最大间隔分类器生成分离两个类的超平面,使得它垂直于每个属于不同类的最近的数据点。这些指导最大间隔分类器的数据点被称为“支持向量”。有趣的是,我们发现分类器只依赖于这些支持向量,而不依赖于所有其他数据点。

最大间隔分类器对不可分数据集的推广是支持向量分类器。由于我们无法找到完美分类数据集的硬边界,我们不得不允许一些数据点被错误分类。问题—我们应该允许多少个数据点被错误分类?

我们引入一个调整参数或成本“C ”,它允许模型对点进行错误的分类。可以使用交叉验证来选择它。c 控制支持向量分类器的偏差-方差权衡。位于其类的边缘的错误侧的数据点和位于边缘的点是该分类器中的支持向量,因为只有这些考虑了支持向量分类器的形成。

较小的 C 值说明了数据的硬拟合,并且非常不稳定,即,即使支持向量有很小的变化,分类器也会变化。这导致高方差但低偏差。另一方面,较高的 C 值允许较宽的余量,并产生具有较高偏差但较低方差的灵活分类器。

我们可以通过在预测器空间中引入更高阶特征以及交互项来拟合非线性决策边界。核和支持向量机的概念是随着这个概念的复杂初始化而出现的,但是中心思想是相同的。

可解释的方差(RSS、TSS、R 平方)

总平方和:是数据反应中固有的方差总量。

残差平方和: RSS 测量数据响应中的方差,这种方差不能用我们用来拟合的模型来解释。

R-square: 可以用我们过去拟合的模型解释的数据响应中方差的比例。R-square 接近 1 表示模型很好。无法解释的差异可能是由两个原因造成的:a .考虑的模型不能准确表示数据(直线不能符合二次型-数据)b .数据中的固有误差(由于无法建模的噪声)。

当在训练数据上测量 R-square 时,试图通过增加模型复杂性来实现更接近 1 的 R-square 会导致数据的过度拟合,因为它利用了数据中存在的固有噪声。因此,总是建议报告我们使用的数据集以及评估指标。

参考资料:加雷斯·詹姆斯,丹妮拉·威滕,特雷弗·哈斯蒂,罗伯特·蒂布拉尼。《统计学习导论:在 r .纽约的应用》: Springer,2013 年。

用于异常检测的监督机器学习技术:逻辑回归

原文:https://towardsdatascience.com/supervised-machine-learning-technique-for-anomaly-detection-logistic-regression-97fc7a9cacd4?source=collection_archive---------12-----------------------

关于异常检测的小型数据科学文章

本·威克斯在 Unsplash 上拍照

这是我写的关于异常检测算法的系列文章的第 11 篇(也是最后一篇)。以下是之前的 10 篇文章,如果您想了解的话,每篇文章都侧重于不同的异常检测算法:

仔细观察,你会发现所有这些算法要么是统计的,要么是无监督的 ML 技术。无监督的,但许多这些算法实际上是围绕监督分类理论(如 kNN,SVM 或 DBSCAN)建立的。今天,我将采用一种“纯粹的”机器学习方法来进行异常检测,这意味着数据集将具有 0 和 1 标签,分别代表异常和非异常。

那么为什么监督分类在这个领域如此晦涩难懂呢?这背后有几个原因,但一个关键原因是严重的类别不平衡,这意味着只有一小部分数据代表异常。异常是罕见的事件,找到它们就像大海捞针。对于监督算法来说,这是一个很大的障碍,因为没有足够的例子可以学习!

无论如何,下面我将使用一种流行的算法——逻辑回归,用公开可用的数据编写一个监督分类的实现。

在以前的文章中,我通常动态地创建一个小的合成数据集,并用最少的代码实现算法,以给出它们如何工作的直觉。今天会有所不同,因为这是一个监督分类问题,我必须遵循所有的基本步骤。正如您将看到的,光是数据准备就要占用相当多的空间。

步骤 1:导入库

我们需要相当多的库来进行数据辩论、准备模型输入、模型构建和验证——所有的库都来自三个大的包:pandasnunpysklearn

# data wrangling
import pandas as pd
import numpy as np# inputs data preparation
from sklearn.preprocessing import RobustScaler
from sklearn.model_selection import train_test_split# modeling
from sklearn.linear_model import LogisticRegression# model validation
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix

第二步:数据争论

我正在使用一个来自 Kaggle 的关于信用卡欺诈检测的流行数据集。欧洲持卡人在删除任何用户标识符后,在公共领域发布了该数据集。让我们导入并查看一下数据集,看看特征。

# import data
df = pd.read_csv("..\creditcard.csv")# view the column names
df.columns

# view the column names
df.columns>> Index(['Time', 'V1', 'V2', 'V3', 'V4', 'V5', 'V6', 'V7', 'V8', 'V9', 'V10', 'V11', 'V12', 'V13', 'V14', 'V15', 'V16', 'V17', 'V18', 'V19', 'V20', 'V21', 'V22', 'V23', 'V24', 'V25', 'V26', 'V27', 'V28', 'Amount', 'Class']

数据集有 31 列。第一列“时间”是交易时间戳,倒数第二列“金额”是交易金额,最后一列“类别”表示交易是否欺诈(欺诈= 1,非欺诈= 0)。其余的列,“V1”到“V28”是未知的特征,并且值被缩放。

现在看看欺诈和非欺诈案例的数量。

# number of fraud and non-fraud observations 
frauds = len(df[df.Class == 1])
nonfrauds = len(df[df.Class == 0])print("Frauds", frauds); print("Non-frauds", nonfrauds)>> Frauds 492
>> Non-frauds 284315

正如我所说,这是一个相当不平衡的数据集,在 25 万个观察中只有 492 个欺诈案例。这只占所有交易中欺诈案件的 0.17%。

步骤 3:输入数据准备

数据集非常干净,所以在下一步中,我们将缩放“Amount”和“Time”列,以确保它们与其他列的格式相似。

## scaling the "Amount" and "Time" columns 
rob_scaler = RobustScaler()df['scaled_amount'] = rob_scaler.fit_transform(df['Amount'].values.reshape(-1,1))
df['scaled_time'] = rob_scaler.fit_transform(df['Time'].values.reshape(-1,1))# now drop the original columns
df.drop(['Time','Amount'], axis=1, inplace=True)

现在让我们定义 X 和 y 输入变量。

# define X and y variables
X = df.loc[:, df.columns != 'Class']
y = df.loc[:, df.columns == 'Class']

由于这是一个不平衡的数据集,我们需要采取额外的步骤来进行子采样——称为欠采样——这样机器就不必大海捞针来学习示例。

# number of fraud cases
frauds = len(df[df.Class == 1])# selecting the indices of the non-fraud classes
fraud_indices = df[df.Class == 1].index
nonfraud_indices = df[df.Class == 0].index# from all non-fraud observations, randomly select observations equal to number of fraud observations
random_nonfraud_indices = np.random.choice(nonfraud_indices, frauds, replace = False)
random_nonfraud_indices = np.array(random_nonfraud_indices)# appending the 2 indices
under_sample_indices = np.concatenate([fraud_indices,random_nonfraud_indices])# undersample dataset
under_sample_data = df.iloc[under_sample_indices,:]# now split X, y variables from the under sample data
X_undersample = under_sample_data.loc[:, under_sample_data.columns != 'Class']
y_undersample = under_sample_data.loc[:, under_sample_data.columns == 'Class']

在将数据输入模型之前,将数据拆分为训练集和测试集。

# split dataset
X_train_undersample, X_test_undersample, y_train_undersample, y_test_undersample = train_test_split(X_undersample, y_undersample, test_size = 0.3, random_state = 0)

步骤 4:模型构建

像往常一样,实际的模型构建只需要 3 行代码,就可以对给定的数据集进行实例化、拟合和预测。由于这只是为了演示,我们将使用默认参数,不做任何调整。

# instantiate model
model = LogisticRegression()# fit 
model.fit(X_train_undersample, y_train_undersample)# predict
y_pred = model.predict(X_test_undersample)

第五步:模型评估

作为标准模型评估指标,我们正在制作分类报告和混淆指标。

classification_report = classification_report(y_test_undersample, y_pred)
confusion_matrix = confusion_matrix(y_test_undersample, y_pred)print("CLASSIFICATION REPORT")
print(classification_report)
print("CONFUSION MATRIX") 
print(confusion_matrix)

离别赠言

本文的目的是展示一种用于异常检测的纯监督机器学习方法。由于严重的阶级不平衡,在这个领域很少使用监督技术。由于一个数据集中只有少数异常观测值,算法没有足够的例子可以学习。

到目前为止,我写的 11 个算法没有一个是绝对好或更好的,这都归结于数据集的性质和它来自的领域。通常,一个简单的统计算法(如箱线图)足以过滤可能的候选者,而在其他情况下,一个复杂的算法可能是无用的。

希望你觉得这个系列有用,欢迎在下面发表评论,关注我的媒体推特LinkedIn

有监督和无监督机器学习的区别

原文:https://towardsdatascience.com/supervised-vs-unsupervised-machine-learning-ae895afc57f?source=collection_archive---------66-----------------------

数据科学概念

他们实际上是如何比较的

肖恩·奥尔登多夫在 Unsplash 上拍摄的照片

机器学习能够处理大量数据。这些数据可能以多种不同的形式出现,从图像到电子表格再到文本。这些数据可以包含许多不同类型的信息,如密码、地址,甚至颜色模式。说到机器学习,有两种不同的方法:无监督有监督学习。

这两种不同类型的学习实际上有很大的区别。这些差异导致了独特的计算机算法来迎合每一种类型的学习。例如,分类机器学习算法,如能够将图像标记为苹果或橙子的算法,保留用于监督机器学习。聚类算法,例如能够根据书写风格将书籍分组的算法,是为无监督的机器学习而保留的。

我们将探索两种类型的机器学习之间的差异,并确定哪种学习形式最适合特定的数据集。

在这里注册一个中级会员,可以无限制地访问和支持像我这样的内容!在你的支持下,我赚了一小部分会费。谢谢!

监督学习

比方说,你正在开发一个机器学习模型,它能够区分在不久的将来价格会上涨的好股票投资和在下个月会贬值的坏股票投资。

Austin DistelUnsplash 上拍摄的照片

传统上,你会向专门从事股票投资的财务顾问寻求建议。这些财务顾问由经验丰富的老顾问来指导哪家公司值得投资。他们被告知,精选的公司信息会导致股票价值上升。他们挑选股票的表现由这些经验丰富的顾问监督。

有监督的机器学习以类似的方式工作。通过向算法输入精选的公司信息,并给这些信息贴上良好投资的标签,你正在教会机器哪只股票值得投资。标记数据的行为是监督学习的表现。用于该问题的机器学习算法的具体类型是一种 分类 算法。

监督学习的一个重要指标是用于训练机器学习算法的数据集。如果该数据集完全标记或识别了您希望算法得出的答案,那么这是一个很好的机会,您正在处理一个有监督的机器学习算法。

照片由马库斯·斯皮斯克Unsplash 拍摄

在选股机器学习模型的情况下,它可能处理的数据集包含公司财务信息,以及该信息是否会导致积极或消极的价格运动。如果你想看选股机器学习算法的例子,那么请查看下面的文章:

[## 我建立了一个机器学习模型,像沃伦·巴菲特一样交易股票(第一部分)

使用机器学习来分析股票的基本面

medium.com](https://medium.com/swlh/teaching-a-machine-to-trade-stocks-like-warren-buffett-part-i-445849b208c6)

上面的文章深入研究了基于监督学习的选股机器学习算法的开发。

无监督学习

对于无监督学习,假设你想开发一个约会应用程序,将约会档案分组在一起,以改善约会过程。然而,你不知道首先如何将它们组合在一起。应该按用户喜好分组还是按自身特点分组?也许根据他们的宗教或政治观点将他们归类?但是最终你仍然不能完全确定如何建立这些约会档案组。

照片由 Yogas 设计Unsplash 上拍摄

这就是无监督机器学习的用武之地。如果你不确定在一个大的数据集中是什么将数据从另一个中区分出来,那么你可以利用无监督学习。这就是无监督学习的用途——在你不知道你在寻找的数据中找到相关性和相似性。

你可能知道,与监督学习不同,无监督机器学习利用未标记的数据。 聚类 是一种流行的无监督学习形式,它检查数据片段以找到相似性和差异,从而将它们聚类或分组在一起。关于约会应用程序的开发,无监督学习将发现约会简档之间的差异和关系,以根据这些简档进行分组或聚类。

如果您希望看到聚类的实际应用,请查看下面的文章,其中实现了无监督的机器学习来将约会档案分组在一起:

[## 我用机器学习和人工智能做了一个约会算法

利用无监督的机器学习约会应用

towardsdatascience.com](/dating-algorithms-using-machine-learning-and-ai-814b68ecd75e)

哪种学习方式最好?

有监督的学习和无监督的学习之间没有更高级的学习形式。你只需要知道何时使用其中一个。因此,使用哪种形式的学习完全取决于我们在开发机器学习模型时面临的问题,或者我们将用于该模型的数据集。

取决于数据

关于数据集,您将使用的学习形式由以下因素决定:

  • 标记数据集=监督学习
  • 无标签数据集=无监督学习

照片由杰克·卡特Unsplash 上拍摄

如果数据集包含标签或标记,例如,一组带有相应名称(苹果、橘子、香蕉等)的水果图片。)然后我们将实现监督学习。然后,受监督的机器学习算法将基于图片的内容来学习哪个图片与每个标签相关联。

如果数据集不包含任何标签或标记,如水果示例,但没有相应的名称,那么我们将实现无监督学习。然后,无监督的机器学习算法将找到水果图片之间的差异和相似之处(颜色、形状、纹理等)。)将它们聚集在一起。

取决于问题

有时候,我们面临的问题决定了我们将使用哪种学习形式。在我们之前使用的例子中(选股模型和约会应用),我们面临的问题决定了我们将使用哪种类型的学习。

对于选股模型,我们需要根据公司的财务报表来了解股票的表现,无论股价是上涨还是下跌。这个基本事实导致我们使用监督机器学习模型。

对于约会应用程序,我们不知道如何区分个人资料。交友档案的聚类是没有事实根据的。这将把我们带到无监督机器学习模型的使用。

关闭

摇滚猴子Unsplash 上的照片

无监督学习和有监督学习之间的区别非常明显。监督机器学习模型被告知它应该如何基于标签或标记工作。一个无监督的机器学习模型被告知只是要弄清楚每一段数据是如何彼此不同或相似的。

使用其中一个的需要很大程度上取决于我们的数据是否有标签或标记。这也取决于我们所面临的问题,而问题通常会影响我们所面对的数据类型。

最终,在无人监督和有人监督之间没有一种更好的学习形式。你只需要知道何时何地应用它们。

在 Twitter 上关注我:@Marco_Santos

科学史上的监督者

原文:https://towardsdatascience.com/supervisors-in-the-history-of-science-deec27d19519?source=collection_archive---------22-----------------------

分析导师与学生的关系,发现谁是历史上最重要的导师。

来源:https://imgur.com/fmVmslS

这是对科学史上导师和学生关系的数据分析。我试图利用数据科学来发现谁是历史上最重要的管理者。

在你继续之前,让我建议你写下你期望在这个分析中发现的伟大科学家的预测。我敢打赌,你们大多数人会对结果感到惊讶。

数据

数据科学中的每个项目都包含一个需要解决的数据问题。在这种情况下,我们的数据集相当简单,到目前为止,它只包含主管和学生之间的关系。例如,我们有一个 Alfred Kleiner(主管)和 Albert Einstein(学生)之间的关系。总的来说,数据集有 7,070 个不同的人,6,517 个学生,2,862 个主管和 8,070 个关系。当然,很多人同时是主管和学生。

所有的数据都是使用简单的搜集技术从维基百科收集来的。该数据集包含了科学界重要人物库中可以接触到的所有人。细节不在本文讨论范围内,可以在 github 库上找到。

我想强调的事实是,数据集没有任何关于个人的个人信息。这些无害的关系将揭示关于科学史的非常有趣的信息。敬请期待!

背景

我将简要解释我们需要继续下去的几个概念。如果你没有任何数学背景— 宝贝不要离开我— 我保证会很简单。如果你有一些图论基础的背景知识,我建议你跳过这一节。我将回顾稍后会用到的概念。

图论是研究图形的数学领域(咄!).在这种情况下,图显然是我们正在寻找的结构,因为图是关系的模型。一个图是由一组通过边连接的节点(人)组成的(导师-学生关系)。

您可能已经在想,边只能在一个方向(有向图)或两个方向(无向图)连接节点。例如,监督学生表现为从监督者到学生的单向边。然而,如果我们认为监督者-学生关系是连接仅仅互相认识的人(例如,社交网络),那么边连接监督者和学生,反之亦然。

来源:阿尔伯特-拉斯洛·巴拉巴希的《网络科学》

这到底为什么重要?嗯,两个节点之间的路径对我们的分析至关重要,这两种不同的结构允许完全不同的路径。哪一个对你分析我们的数据更有意义?

无向图

首先,我们将关系建模为无向图。这个决定对分析有重要影响,因为它认为导师和学生同等重要。

组件

图中的连通分量是一个子图,其中所有的节点都可以从至少另一个节点到达。我们的图有 84 个连通分量,但最大的分量占所有节点的 95.81%。这已经相当令人印象深刻了,因为我们从不同领域(例如化学、计算机科学)的人才库中收集了数据。这表明所有这些领域如何有一个共同的祖先,这将被证明是数学领域。

学位

无向图中节点𝑣的度是连接𝑣和其他节点的边的数量(即连接到特定人的人数)。这是前十名的学位排名:

1 Arnold Sommerfeld: 44
2 David Hilbert: 37
3 Dimitris Bertsimas: 34
4 Robert Solow: 30
5 Max Born: 29
6 Felix Klein: 28
7 Alonzo Church: 27
8 Franz Boas: 27
9 Abdus Salam: 25
10 J. J. Thomson: 24

这个列表已经很有趣了,也许你知道其中的一些。把它们记在心里,因为它们以后会出现。除了前十个,这是图中所有节点的度数分布

我们可以观察到,大多数人只与他们的主管有联系,并且有一个学位,而少数人有许多联系。这在统计学中被称为幂律分布。

中间中心性

中间中心性衡量节点𝑣的中心性,即所有节点对中通过𝑣.的最短路径所占的比例在这种情况下,我们可以使用这种中心性度量来提取关于图中人的重要性的见解。如果一个节点发现自己处于连接其他节点的最短路径中,那么它对于该连接是必不可少的。排名:

1 David Hilbert: 0.159
2 Max Born: 0.152
3 Hans Reichenbach: 0.121
4 Arnold Sommerfeld: 0.120
5 Hermann Helmholtz: 0.085
6 E. H. Moore: 0.073
7 J. J. Thomson: 0.071
8 Solomon Lefschetz: 0.070
9 John von Neumann: 0.058
10 Ludwig Boltzmann: 0.055

他们所有人,除了赫尔曼·亥姆霍兹约翰·冯·诺依曼,都生于 19 世纪,死于 20 世纪。亥姆霍兹几乎活到 20 世纪,冯·诺依曼在最开始就诞生了。他们在图表中(以及在科学史上)如此重要,因为他们是连接 18 世纪最伟大的数学家与 20 世纪和 21 世纪最伟大的科学家的一代人的一部分。

从左到右,从上到下:戴维·希尔伯特,梅克斯·玻恩,赫尔曼·亥姆霍兹,阿诺德·索末菲,赖欣巴哈,E. H .摩尔,J. J .汤姆森,所罗门·莱夫谢茨,约翰·冯·诺依曼,路德维希·玻尔兹曼

该奖项由戴维·希尔伯特获得!。希尔伯特出生于德国,是历史上最有影响力和普遍性的数学家之一。在希尔伯特的学生中,我们可以找到数学家赫尔曼·维尔哈斯克尔·库里

我们还可以看到诺贝尔奖获得者梅克斯·玻恩,德国物理学家和数学家,在量子力学的发展中起着至关重要的作用。在玻恩的学生中,我们找到了诺贝尔奖获得者:玛利亚·戈珀特-梅耶、恩利克·费密和马克斯·德尔布吕克。他的另一个学生是罗伯特·奥本海默,在曼哈顿计划期间洛斯阿拉莫斯实验室的负责人,第一颗原子弹就是在那里被研发出来的。

德国物理学家阿诺德·索末菲(Arnold Sommerfeld)是量子物理领域的先驱,是获得诺贝尔奖学生最多的前两名。我们已经看到索末菲在我们的图中拥有最多的连接数。索末菲的学生包括诺奖得主沃纳·海森堡沃尔夫冈·泡利汉斯·贝特彼得·约瑟夫·威廉·德拜莱纳斯·鲍林伊西多·艾萨克·拉比马克斯·冯·劳厄。事实上,阿尔伯特·爱因斯坦曾经告诉索末菲,他很钦佩他是如何从土壤中培养出这么多年轻人才的。索末菲可以说是科学史上最优秀的导师,以在家中或咖啡馆与学生见面而闻名。索末菲还拥有一个滑雪小屋,学生们被邀请在那里讨论物理。有趣的是,索末菲本人从未获得过诺贝尔奖,尽管他创下了 84 次提名的记录。

另一方面,我们还有英国物理学家、诺贝尔奖获得者 J. J .汤姆森,他是唯一一个在拥有诺贝尔奖的学生方面可以与索末菲相抗衡的人。由于发现了电子,汤姆森的学生中有诺贝尔奖获得者查尔斯·格洛弗·巴克拉尼尔斯·玻尔梅克斯·玻恩威廉·亨利·布拉格欧文·理查森查尔斯·托马森·里斯·威尔逊弗朗西斯·威廉·阿斯顿欧内斯特·卢瑟福。事实上,汤姆森的儿子(乔治·佩杰特·汤姆生)获得了 1937 年的诺贝尔物理学奖,只有布拉格、玻尔和西格班取得了同样的成就。

俄罗斯数学家索罗门·莱夫谢茨,在代数拓扑和几何方面做了基础性工作,指导了人工智能的创始人之一约翰·麦卡锡和统计学的重要人物约翰·图基

赫尔曼·赫尔姆霍茨是德国物理学家,在人类视觉、电动力学和热力学等几个领域做出了重大贡献。在他的学生中,我们可以找到诺贝尔奖得主阿尔伯特·迈克耳孙威廉·维恩马普加布里埃尔·李普曼

最后,在名单上我们还可以找到匈牙利数学家、物理学家和计算机科学家约翰·冯·诺依曼。冯·诺依曼可以说是地球上最聪明的人之一。他是我一直以来最喜欢的科学家之一,所以我不敢简要描述他的工作。我只能说,如果你不太了解他,那就值得一读。只是为了好玩,打开他的维基百科页面,在右边他的图片下面找到“知名”部分。

特征向量中心性

特征向量中心性是测量中心性的不同方式。在这种情况下,当一个节点与另一个重要节点相关时,它的重要性就会增加。这个概念类似于 Google 在其 PageRank 算法中使用的概念。再次排名:

1 Arnold Sommerfeld: 0.578
2 Max Born: 0.214
3 Werner Heisenberg: 0.213
4 Wolfgang Pauli: 0.162
5 Hans Reichenbach: 0.158
6 Rudolph E. Peierls: 0.154
7 David Hilbert: 0.140
8 Ferdinand von Lindemann: 0.119
9 Gregor Wentzel: 0.110
10 Linus Pauling: 0.109

如果你碰巧读过中间中心性这一节,那么你已经熟悉了列表中的大多数人。

令人着迷的是,通过这种中心性的衡量,我们可以在不了解他的学生的任何情况下,仅仅根据他的后代的性质,发现阿诺德·索末菲的重要性。名单上的大多数人实际上都与阿诺德·索末菲有直接关系。

有三位科学家是我们在之前的中心性测量中没有看到的。沃纳·海森堡监督的鲁道夫·佩尔斯;费迪南·冯·林德曼,阿诺德·索末菲和戴维·希尔伯特等人的上司;和由阿诺德·索末菲监督的格雷戈尔·温策尔。

令人惊讶的是,排名第 13 位的 J. J .汤姆森没有进入前十名,因为他指导过如此多的诺贝尔奖获得者。

桥梁

桥是删除后会断开图的边。一个节点的桥边的数量给了我们一个很好的度量,这个节点连接图的不同部分有多重要,这些部分可能与不同的字段相关。排名:

1\. Franz Boas: 25
2\. Robert Solow: 21
3\. Arnold Sommerfeld: 19
4\. Alonzo Church: 19
5\. David Hilbert: 18
6\. John Archibald Wheeler: 16
7\. Felix Klein: 15
8\. Salomon Bochner: 14
9\. Garrett Birkhoff: 13
10\. Richard Karp: 13
11\. John Tate: 13
12\. Elias Stein: 12
13\. Marvin Minsky: 12
14\. Noam Chomsky: 11

再次,有很多熟悉的面孔,这也是一个很好的迹象,表明我们正在做正确的事情。

弗朗茨·博厄斯非常有趣。他是一名德国人类学家,指导过许多学生,成为该领域的中坚力量。令人惊讶的是,人类学家出现在数据集中,然而,我们可以将弗朗茨·博厄斯追溯到亚伯拉罕·戈特瑟夫·卡斯特纳,他是卡尔·古斯塔夫·雅各布·雅各比的共同祖先。

美国经济学家、诺贝尔奖获得者罗伯特·索洛也是经济学领域的一个重要节点,有诺贝尔奖获得者乔治·阿克洛夫约瑟夫·斯蒂格利茨彼得·戴蒙德威廉·诺德豪斯等学生。

其他像阿隆佐·邱奇、理查德·卡普、马文·明斯基和 T21 都是数学和计算机科学领域之间的重要纽带,最近的两位获得了图灵奖。

我们还发现了其他一些伟大的数学家,如所罗门·博克纳菲利克斯·克莱因加勒特·伯克霍夫约翰·泰特埃利亚斯·斯坦。费利克斯·克莱因在几个不同的数学领域的贡献而广为人知。作为我们将在本文结尾看到的剧透,费利克斯·克莱因是导师-学生这条非凡道路的一部分,这条道路始于拉格朗日,止于约翰·冯·诺依曼。

美国物理学家约翰·阿奇博尔德·惠勒曾负责重振人们对广义相对论的兴趣,他是诺贝尔奖获得者理查德·费曼和基普·索恩的导师。

在名单的最后,我们遇到了诺姆·乔姆斯基,他是数学和语言学领域之间的枢纽。乔姆斯基是唯一一个和索恩一起,我们提到过的,今天还活着的人。

有向图

现在,我们把这个模型变成一个无向图,这个无向图更重视监督者而不是学生。我们为什么要这么做?嗯,随着这种变化,我们期望发现数学的创始人比其他人更相关,仅仅因为他们在谱系树的顶端。

中间中心性

我们将执行与无向图相同的分析,因此,有关该度量的定义,请参考上一节。与前面分析的主要区别在于,在这种情况下,路径只在从主管到学生的方向上有效。排名(去除异常值):

1 Joseph-Louis Lagrange: 0.002
2 Leonhard Euler: 0.002
3 Johann Bernoulli: 0.002
4 Siméon Poisson: 0.001
5 Felix Klein: 0.001
6 Peter Dirichlet: 0.001
9 Rudolf Lipschitz: 0.001
10 Ferdinand von Lindemann: 0.001
11 Carl Gauss: 0.001

多好的清单啊,令人满意。事实上,我们已经找到了一些我们今天所知道的数学的创始人。在这种情况下,我们有 18 世纪和 19 世纪出生的数学家。

从左到右,从上到下:约瑟夫·路易斯·拉格朗日、莱昂哈德·欧拉、约翰·伯努利、西蒙·泊松、费利克斯·克莱因、彼得·迪里克莱、鲁道夫·利普希茨、费迪南德·冯·林德曼、卡尔·高斯

这些是一些最伟大的数学家,如果你接受过数学教育,我肯定你知道他们的大多数名字。也有许多伟大的早期数学家失踪,值得一提:波恩哈德·黎曼,亨利·庞加莱,皮耶·德·费玛,戈特弗里德·莱布尼茨,埃瓦里斯特·伽罗瓦,卡尔·魏尔斯·特拉斯,尼尔斯·阿贝尔,卡尔·雅可比,奥古斯丁·路易·柯西,约瑟夫·傅立叶和皮埃尔·西蒙·拉普拉斯,仅举几例。

路径

在图论中,路径是连接一系列节点的一系列边。正如在“桥梁”小节中所承诺的,这张图表中有一些值得观察的路径。

从莱昂哈德·欧拉到约翰·冯·诺依曼的树

结论

这有希望是对这个数据集的第一次分析。然而,为了将来的分析,我会努力收集人们的个人信息。我们已经看到了数学家的重要性,特别是德国和法国的数学家,随着我们绘制图表,随着时间的推移,我们可能会发现美国科学家的迅速变化。

我开始这个项目是因为我自己一直在寻找监督者,我想了解更多关于监督者的历史。正如我们今天所看到的,我确信找到一个合适的主管的重要性。其实如果你和我的情况差不多,我可以推荐读‘一个博士是不够的!’

我想分享的最后一个想法是数学的重要性。一切都是数学,当它变得更具体时,就有了更具体的名称。

如果你对一个我没有提到的科学家特别感兴趣,或者你想和我评论什么,请在评论中告诉我。

参考

如果你有兴趣学习更多关于图论的知识,并以类似的方式应用它,我真的推荐阿尔伯特-拉斯洛·巴拉巴西的网络科学。它很棒,可以在网上以多种语言免费下载。

这是我为这个项目准备的 github 库,以防代码对你有用。请给它一颗星,如果你觉得这个项目有趣,我将非常感谢。

用计算机视觉补充财产数据库

原文:https://towardsdatascience.com/supplementing-property-databases-with-computer-vision-ec519e5be66e?source=collection_archive---------59-----------------------

对象检测模型为改进现有的数据收集工作开辟了新的可能性

物业和地块数据库为学术和商业市场研究提供了巨大的价值。然而,这些数据库的维护成本很高,而且往往包含大量缺失、不正确或过时的记录。计算机视觉模型,加上可访问的卫星和街道图像,可以识别不正确的数据,并在这些模型经过训练以检测财产特征时估算缺失的记录。这种方法为收集数据提供了一种低成本的替代方法,否则需要通过现场访问、物业经理或业主进行报告。

Res-Intel ,我们正在使用计算机视觉模型来识别建筑特征,这些特征可以揭示建筑的能源使用和改造潜力。配有耗电的泳池泵、热水器和照明设备的游泳池是一个可以显著增加酒店能源使用的特色。县税评税员记录哪些财产有一个游泳池,并将这些信息存储在一个公共数据库中。然而,我们发现这些记录往往不完整或与观察不符。

物体检测 vs .公共记录

在我们对圣地亚哥多户房产的分析中,我们发现税务评估员数据库没有为我们评估的近一半房产提供完整的池数据。为了填补报告空白,我们收集了所有多家庭房产的卫星图像数据,然后训练了一个对象检测模型,以在每个房产图像中找到池。我们成功地找到了丢失的记录,甚至在税务评估员的数据中发现了一些不一致的地方,否则这些数据会被忽略。

池的对象检测可以补充缺失的池记录并交叉验证现有记录。

在 10,714 个多户房产的样本中,42%的房产在税务评估员数据库中的“pool”字段中报告了缺失值。对象检测模型发现了 146 个在税务评估员记录中缺失的池,这可以在这张互动地图上查看。

税务评估员记录和模型的池检测置信度之间的不一致揭示了误报的池。(图片由作者提供)

大多数属性的预测具有接近 1 或 0 的置信度(注意纵轴上的对数标度)。零置信度意味着模型确定在资产处没有池。(图片由作者提供)

此外,一些评税员的记录似乎错误地报告了一处房产中存在一个游泳池:该模型在 114 处房产中检测到一个游泳池,评税员记录为“无游泳池”,而在 29 处房产中没有检测到一个游泳池,它记录为“游泳池”下面的卫星图像显示了一处多户房产,据估税员报告,该房产有一个游泳池。看起来好像在某个时期的房产确实有一个游泳池,但是它已经被水泥填满了,这表明评税员的记录已经过时了。

县税务评估员记录了这个地方的一个游泳池,但是很明显事情已经发生了变化。(图片由作者提供)

虽然对象检测方法经常在公共记录中发现错误,但重要的是要记住没有模型是完美的。事实上,我们对预测数据的手动检查导致我们发现了一些假阳性——模型预测存在一个水池,而实际上并没有。下图是一个例子,模型把铺在屋顶上的蓝色防水布误认为是游泳池。

该模型预测绿色边界框内的区域是具有 65%置信度的池。(图片由作者提供)

通过简单地限定如何使用预测,可以减轻甚至消除模型预测误差的影响。例如,在池检测模型与资产数据库记录相矛盾的情况下,我们可以选择仅当该模型以大于 90%的置信度预测池的存在时才相信该模型。

训练模特

我们用来查找酒店特征的对象检测模型是由 Joseph Redmon 开发的“你只看一次”( YOLO)模型,此处提供。目前有大量流行的对象检测模型,它们都是卷积神经网络(CNN)的扩展。CNN 通过提取一系列基于像素的基本特征并确定这些特征与一组对象类别之间的关系来对单个图像进行分类。水池、瓦片屋顶或汽车是可能在卫星图像中可见的对象类别的示例。经过训练的 CNN 模型可以预测像素集合代表一个池或任何其他可见对象的概率。一般来说,YOLO 模型和对象检测模型通过在更大图像内的提议区域上迭代其预测来扩展 CNN。

训练检测模型是校准分配给特征的权重的过程,这些特征用于预测图像中对象的存在。权重是通过梯度下降确定的,这是一个迭代过程,寻找使预测误差最小化的权重值(或与误差成比例的某个值)。

确定预测误差需要一个地面真实数据集,一系列手工标记物体的图像。我们的观察单位是单个物业的航拍图像,因此我们首先从高分辨率卫星图像光栅文件导出物业级别的图像。识别单个属性需要在栅格数据上叠加属性边界 shapefile。有了属性图像,我们使用 YoloLabel 来标记地面真实数据集,该数据集(正如您可以从名称中猜到的那样)以文本文件格式导出图像标签,该格式可以很容易地转换到 YOLO 模型。

手动标记图像的子集,并用于训练和验证模型。(图片由作者提供)

总共,我们标记了大约 2000 个池图像,并将它们分成验证训练组。训练图像直接用于通过梯度下降来校准模型权重,而验证图像被搁置一边,稍后用于测量模型在它尚未看到的图像中检测对象的准确度。

用于模型训练的计算资源

训练神经网络模型是一项计算密集型任务。预处理 CNN 模型以提取有用的图像特征,减少了计算量;但是将这些特征连接到特定对象的数千个参数仍然可以通过迭代梯度下降过程进行优化。这种高度多维的优化问题通常需要高性能图形处理单元(GPU)提供的内存和计算能力。幸运的是,亚马逊网络服务(AWS)提供了远程弹性计算(EC2)服务器,这些服务器拥有强大的 GPU,可以以低廉的价格按小时租用。我们使用一个 p2.xlarge EC2 服务器,它带有一个 61 GB 内存的 GPU,以及一个预安装的 CUDA 和 TensorFlow 库,这些是利用 GPU 进行神经网络建模所必需的。训练池检测模型需要大约 18 个小时。

验证模型

对一个模型最重要的测试是它在图像中检测到它还没有遇到的物体的准确性。我们的验证集包括 268 处房产,69 处有泳池,199 处没有。除了两个验证属性(AUC = 0.997)之外,集合检测模型准确预测了集合的存在和位置。这两个不正确的预测是假阴性:尽管模型确实检测到了这些属性的池,但它报告的置信度略低于 50%。总而言之,池检测模型证明是非常可靠的。

由训练的 YOLO 模型预测的池边界框。(图片由作者提供)

通过将预测的边界框与地面真实情况进行比较来评估对象预测的质量也是常见的做法,地面真实情况由两者之间的重叠统计或归一化距离来测量。然而,这些统计数据并不总是有效地传达关于模型性能的直觉。或者,我们可以目视检查图像的子集,并验证池边界框是否在正确的位置形成。上面的动画展示了随机选择的模型生成的边界框,它们精确地形成在目标位置周围。

关于 Res-Intel 工作的更多信息:

Res-Intel 使用基于神经网络的对象检测模型,作为一种低成本工具,用于识别影响建筑能耗的属性特征。我们将这些数据与来自多个物业数据库的公共事业公司提供的汇总数据和记录相结合,以创建大规模的建筑级能源概况。我们与几家大型公用事业公司合作,构建和分析建筑组合,建立能耗数据模型,并设计研究来评估能效计划和技术。

供应链优化:值得还是不值得?

原文:https://towardsdatascience.com/supply-chain-optimization-worth-it-or-not-20ae4c6e635?source=collection_archive---------36-----------------------

商业科学

数学优化的悖论不应该让你远离它的好处

约书亚·希伯特Unsplash 上拍摄的照片

优化是如今人工智能对企业的一个主要卖点。每个人都希望提高自己的效率、收入和其他关键 KPI。这些都是合理的目标,也是可以实现的目标。我们可以使用优化原则来显著提高性能。

完美的不可能

然而,无论您如何努力实现最佳性能,完全优化都是不可能的。没有一个模型能够解释所有的可能性或实现完美的预测。在可预见的未来,人工智能技术还没有先进到足以让这成为可能。

而且,定义什么是“最优” 提供了自己的挑战 。每个企业都有独特的需求,因此,优化不同的目标。对一家公司来说是最优的策略在另一种情况下不太可能表现得一样好。完美是一个移动的目标,不是简单的一刀切的答案。

engin akyurtUnsplash 上拍摄的照片

这就是为什么优化是一个悖论。它的目的使它不可能。你越想给它下定义,它就变得越难以捉摸。

为什么我们喜欢悖论

直面悖论并不是什么新鲜事。我们每天都要面对矛盾,对于像我这样的数学家来说,这通常很有趣。只需考虑一下在互联网上再次出现的自相矛盾的问题:

如果你随机选择这个问题的一个答案,你答对的概率有多大?
A)25%
B)50%
C)0%
D)25%

乍一看,这似乎很容易回答。但是你越想,越多的可能性看起来像正确的答案。这些可能性使这些答案变得不正确。最终,你意识到问题没有答案。你必须打破数学原理和逻辑。这种问题可能会让你一头雾水,但是试图讲道理是磨砺批判性思维技能的绝佳方式。

沃洛德梅尔·赫里先科Unsplash 拍摄的照片

然而,最优化的悖论可能特别令人讨厌。虽然有效的优化将提供一个提升,但它永远不会实现它所设定的目标。你永远不会给出最佳结果。

然而,我认为,正是这一点让优化和其他思维练习一样有趣。你有机会挑战关于做生意的最佳方式的假设。优化打开了新的可能性,与解决上面的问题不同,你得到了一个切实的结果的满足感。比如 Boggi Milano 可能并没有通过优化完全完善他们的供应链,但即使是一个优化算法 的几次迭代也让库存效率提高了 18% 。解决悖论的回报在优化中要大得多——你总是可以一点点接近完美。

优化背后的数学

尽管如此,即使没有尝试最优化的不可能性的矛盾,最优化也是一个挑战。最优化的数学和算法设计极其复杂。看一下我使用的优化公式中的一小部分:

作者提供的图片(抄送并注明出处)

正是因为这个原因,许多人发现优化令人生畏。如果你所有复杂的编程和困难的计算甚至都不会给你最终的答案,那何必呢?

优化就像洋葱

如果这还不够复杂,任何优化算法都不会涉及单一的优化计算。比如妖怪和洋葱(还有冻糕!),优化有层次。您很少会有一个工作模型不包含至少几层相互依赖以给出结果的计算。

Evo 的 补给工具为例。补货可用于优化供应链,实现全系统商店级补货。可以想象,优化这个需要优化大量的个体因素。补充算法包含 3 个不同的优化循环:

1.一个是根据需求确定每个商店的最佳产品组合

2.一个在整个系统范围内满足这一需求的系统,平衡现有资源和其他地方的需求

3.一个是以最具成本效益的方式在商店之间和仓库之间运送货物

必须在这些优化中的每一个内进行多次计算,优化在这些更大的优化模型内使用的因子。单一模型需要层层优化。剥开它们,你会发现优化比你想象的还要复杂。随着时间的推移,这留下了大量的空间来完善和改进结果,对于像我这样的数据科学家来说,这是一个既令人沮丧又令人兴奋的过程。

总会有误差,但总会有方法来改进我的结果:简而言之就是最优化的悖论。

如果最优结果是不可能的,那么优化值得吗?

Johannes Plenio 在 Unsplash 上拍摄的照片

所以如果你永远无法做到完美,优化值得吗?任何高管都会很明显的说是。即使是微小的改进也会对底线产生重大影响,这对任何企业都有好处。

但是这并没有降低优化的复杂性。完美是不可能的,但我们必须不断努力实现它。我们不得不接受这个悖论。在尝试不可能的过程中,我们每天都离理想更近一步。

如果你对深入研究优化所需的计算或编程感兴趣,Evo 大学 有一门 优化课程 。我鼓励你查看一下,以便更深入地了解这个主题。

还没入学?现在是时候了!前往https://evo.ltd/join免费参观。

结论:值得

数学优化的许多功能和内在挑战不应该吓得你不敢抓住它的好处。

杰克·英格尔在 Unsplash 上的照片

毕竟不可能做到优于最优!你无法打败一个拥有高质量数据的设计良好的优化器。

我总是告诉我的父亲,尽管他一生都在 IBM 工作,但坐在方向盘后面时有一种意大利式的自豪感:谷歌地图导航将击败你的驾驶知识,除非你知道一些它不知道的东西。他今天还是不信任我,也许有一天?

PS 我定期写商业科学。推荐后续阅读:

[## 94%完美:2000 亿美元库存问题的惊人解决方案

机器学习和人类经理一起修复供应链

towardsdatascience.com](/94-perfect-the-surprising-solution-to-the-200-billion-inventory-problem-b6ba0bc1417a) [## 时尚被打破了。科学正在修复它

转变 5 个核心时尚流程

towardsdatascience.com](/fashion-is-broken-science-is-fixing-it-b771b1ab5b59)

Monthly Business Science in your inbox, new software, and University-level learning:[**Free access**](https://evouser.com/register)Questions? Please reach out on [Linkedin](https://www.linkedin.com/in/fabrizio-fantini/)

供给、需求和工具变量:经济学家工具箱给数据科学家的教训

原文:https://towardsdatascience.com/supply-demand-and-the-instrumental-variable-lessons-for-data-scientists-from-the-economists-21af225187cd?source=collection_archive---------13-----------------------

和我一起假装一会儿。

假装——你好心但厌恶数据的前大学室友来向你寻求建议。看,他有了下一个颠覆可穿戴设备行业的大玩意:智能脚链(智能手表的明确继任者)。智能脚链将拥有一切——健康监测器、足部按摩器和睡眠追踪器,它会告诉你的 Keurig 什么时候该排队去喝早上的咖啡了。

只剩下一个问题。你的朋友需要一些市场分析来说服种子投资者,他可以以他们愿意支付的价格将智能脚链带给世界各地的千禧一代。这就是你进来的地方。你开始在网上搜寻可穿戴设备行业的数据(Kaggle 这次不会放弃)。最后,你偶然发现一些市场研究数据,开始埋头苦干,利用经济学原理课上残留在你大脑中的信息,开始估算需求曲线。这项工作似乎很简单——一些基本的线性回归,不需要 Keras 或 LightGBM 或 XGBoost。

所以,你开始你的探索性数据分析。你希望你的散点图显示出价格和数量之间明显的负关系,并在回归模型中出现一致的负价格系数。

你知道,就像这样。

眼熟吗?(作者创作)

相反,您最终会得到类似这样的结果:

和你想的不太一样。(作者创作)

你心里想,“这完全违背了 200 年来的价格理论”。然后,当事情没有按照你希望的方式发展时,你会求助于两个可靠的朋友——谷歌和 StackExchange。像往常一样,你会发现很多人都有同样的问题。

事实证明,这个问题非常简单。价格由需求和供给曲线的交点决定。这种关系给了我们第一次见识。为了估计需求曲线,我们需要供给曲线的变化或移动。通过观察供给曲线与需求曲线相交时的变化,我们可以描绘出需求曲线。大概是这样的:

由作者创建

太好了,问题解决了。或者,如果在保持需求不变的同时改变供给曲线是一个简单的壮举,那就有可能了。看,虽然我们需要供应曲线移动,但是我们没有办法用普通的最小二乘法(OLS)来保持我们的需求曲线不变。我们无法保持需求不变,这给了我们关于价格对需求量的影响的有偏见和不一致的系数估计。也就是说,在这种情况下,OLS 给我们的估计可能很好地反映了价格-数量关系的真实性质,即使是在大样本中。相反,我们可能观察不到任何关系,如下例所示。

左图:真实发生的事情。|右:我们能看到的。(作者创作)

谢天谢地,我们在 StackExchange 的朋友有一个来自 Phillip 和 Sewall Wright 的解决方案:工具变量回归。看,在喧嚣的 20 年代末——当时髦的女孩们挤进她们的福特汽车去爵士俱乐部时——菲利普·赖特和他的儿子休厄尔正为估算植物油和动物油的需求这个同样令人兴奋的问题而苦恼。当然,他们的散点图展示了和你的散点图一样的价格和数量之间的微弱关系。因此,他们开创了现在所谓的工具变量回归。他们在 1928 年面临的问题与你今天面临的问题没有什么不同,除了你开始分析智能脚链数据,他们被黄油和橄榄油卡住了。

什么是工具变量?

先说内生性。当一个变量的值与误差项 u. 相关时,该变量可被描述为内生变量。由于与统计偏差相关的各种原因,该变量可能是内生变量。也许研究人员遇到的最常见的内生性来源来自被忽略的变量偏差。当试图确定某个变量 X、对我们的因变量 Y、的影响,而不包括另一个与 X 和 Y 都相关的解释变量 W 时,就会出现省略变量偏差

例如,吸烟和饮酒都是可能与预期寿命负相关的习惯。然而,吸烟和饮酒本身也可能是相互关联的。因此,如果我们创建一个模型来估计吸烟对预期寿命的影响,而不包括饮酒习惯,我们可能会夸大吸烟对预期寿命的影响。忽略在我们的模型中包括酒精消费会给我们一个有偏差的吸烟回归系数。

省略变量偏差有一个相对简单的解决方案——在模型中包含省略变量。然而,有时克服统计偏差变得更加困难。考虑省略变量偏差的情况,我们只是没有省略变量的数据。另一个常见的问题是同时因果偏差的情况——在这种情况下, X 影响 YY 也会增加X。经济学家在试图确定警方资助对犯罪的影响时会遇到这个问题。更多的警察理论上应该会降低犯罪率,但是更高的犯罪率可能会吸引更多的警察资金来打击这些犯罪率。在这两种情况下,运行简单的线性回归将会得到有偏差的回归系数。我们没有理由相信我们在这些模型中观察到的系数反映了 XY. 影响的真实性质

这就是工具变量发挥作用的地方。

工具变量是一个允许我们规避内生性问题的变量(我们称之为 Z )。当我们实施工具变量回归时,我们主要关注内生变量,并将其分解为两个组成部分。第一部分是有问题的内生部分。这是变量中产生统计偏差的部分。在省略的可变偏差示例中,这是与酒精消耗相关的部分。在同步因果关系的例子中,这是高犯罪率导致警察经费增加的部分。

然而,第二部分是我们感兴趣测量的变量的不成问题的外生部分。如果我们能够捕捉到这部分变量的影响,我们就可以获得无偏回归系数,从而估计 X 对 y 的影响的真实性质

工具变量,或简称为工具,允许我们分离出内生变量中没有问题的部分。如果工具变量 Z,满足两个特定标准,那么工具变量回归将给出我们的回归系数的估计值,该估计值比简单的普通最小二乘法的估计值更接近其真值

这两个标准如下:

  1. 工具相关性:工具变量, Z,必须与我们的内生变量, X 相关。数学上表示,corr ( ZX ) ≠ 0。直觉上,如果 ZX 不相关,我们将无法根据我们的工具变量捕捉到 X 的任何变化。
  2. 工具外生性工具有效性:工具变量 Z 必须是外生性的——与误差项不相关。数学上表示,corr ( Z ,u) = 0。如果 Z 与误差项相关,那么我们将违反高斯-马尔可夫定理,并且无法确定 X 和 y 之间的无偏且一致的回归系数。

一个合适的工具满足这个描述:变量 Z 与变量 Y 仅通过其与 x的相关性相关

为了进一步理解什么是好的工具,让我们看另一个经济研究的例子。劳动经济学家通常对学校教育的回报感兴趣,即多上一年学对个人工资的影响。然而,有几个混淆和不可观察的因素会影响一个人多上一年学的决定。一个不可观察的因素是天生的能力。先天能力水平较高的人更有可能多上一年学。因为多上一年学与能力相关,而我们无法在 OLS 模型中恰当地包含能力,所以受教育年限将是一个内生变量。

因此,像 Card (1995)这样的论文利用地理数据来估计学校教育-收入关系的真实性质。地理上靠近大学使得多上一年学更有可能。这满足了仪器相关性条件。与此同时,个人的父母通常决定住在哪里。只要地理邻近性与能力不相关,这可以通过控制父母教育和收入等可观察因素来实现,那么邻近性变量应该是外生的。这满足了仪器的有效性条件。在学校教育回报的背景下,地理上的邻近性与终生收入之间的关联仅仅通过它对获得额外教育的可能性的积极影响。这是一份相关和有效的文书的要素。

IV 回归是如何工作的?

OLS 回归只是简单地将 Y 回归到 X 上,而 IV 回归包含两步过程(这就是 IV 回归的另一个名称是两步最小二乘法的原因)。第一步,我们在 z 上回归 x。这给了我们一组预测值,X̂.在第二步中,我们对预测值 X̂.回归 y 下面是 IV 回归过程的演示。

第一步)

x̂=π0+π1(z)+v

其中 v 是误差项。

步骤 2)

Y = ß0+ß1(X̂)+ ε

其中,ε是误差项。

因为我们的工具变量必须是外生的,所以由 XZ 的回归预测的 X̂值也将是外生的。因此,这第一步移除了我们解释变量中有问题的内生部分, X. 这允许我们在 上回归 Y ,而不必担心内生性。

让我们暂时回到菲利普和休厄尔·赖特身上来。父子二人组意识到,要估计黄油的需求曲线,他们需要在保持需求不变的同时,隔离供应的变化。通过在供给变动时保持需求不变,莱特兄弟知道他们能够估计出各种供给曲线与需求曲线相交的所有点。为了做到这一点,莱特兄弟使用降雨作为他们的工具。父子二人推断,降雨量少会减少放牧,从而降低黄油产量。这将影响供应,但降雨应该不会对黄油需求产生任何有意义的影响。作为一种工具,降雨量满足相关条件——降雨量与黄油价格正相关。并且降雨满足外生条件——降雨只通过供给影响黄油价格。

菲利普和休厄尔·赖特为众多经济学家和聪明的分析师提供了有价值的见解。通过实施 IV 回归,使用改变供给而不是需求的变量作为工具,我们可以获得需求曲线的一致估计。我们现在准备带着真实数据的例子艰难前行。

数据

好吧,完全公开——我没有任何关于智能脚链或智能手表或智能任何东西的数据来分析这篇文章。然而,我所拥有的是 1960 年至 1999 年间肉鸡价格的一个非常令人兴奋的数据集。很有趣,我知道。然而,用于估计需求的 IV 回归原理适用于任何产品。

这些数据来自 Epple 和 McCallum (2006 年)。该数据集由鸡肉和牛肉价格、鸡饲料价格、人口、人均收入和通货膨胀的年度面板数据组成。

下面是对数数量和对数鸡肉价格的散点图(价格在 y 轴上,这是经济学的惯例)。

正如我们所看到的,这种关系似乎与需求曲线的方向相反,因为数量在价格上增加。因此,这个问题需要一个工具变量的方法。

识别需求曲线

正如我前面所讨论的,确定需求曲线需要保持需求不变,同时检测供给曲线的变化。正如前面 1700 左右的话应该已经说得很清楚了,这样做的关键是工具变量回归。具体来说,我们需要确定一个外生变量,它只通过对供应的影响来影响价格(T2)。

对于莱特兄弟和他们基于黄油的分析,选择的工具变量是降雨量。低降雨量减少了奶牛可以吃草的土地面积,从而降低了黄油产量。然而,没有理由相信降雨对黄油的需求有任何有意义的影响。对于我们的鸡肉或智能脚链数据,我们需要确定具有类似影响的变量——导致供应变化,同时对鸡肉/智能脚链需求没有任何影响。

寻找相关变量的第一个地方是输入。在我们的鸡肉数据中,我们有关于玉米和鸡饲料的信息。这些投入的价格通过它们对生产产出的成本的影响而与产出产品的价格相关联。当鸡饲料价格下降时,鸡肉价格也会下降,因为生产鸡肉变得更便宜。更便宜的投入意味着最终产品可以更便宜地生产。利润最大化的公司有动机生产更多,增加数量,同时降低价格。投入价格的变化导致供给曲线移动,使我们能够描绘出需求曲线。

这些原则很容易转移到智能脚链上——只需用钢铁、硅、铝和原油等类似投入材料的价格取代“鸡饲料”价格。

部署工具变量方法的第一步是回归我们工具的价格。大多数统计软件包都有计算 IV 回归的功能,而不必手动计算第一步 OLS 回归。然而,计算第一步回归允许我们诊断我们使用的工具是否是解决我们问题的有效工具。

一个重要的考虑是我们的工具是否相关。回想一下,当 corr(X,Z) ≠为 0 时,仪器是相关的。如果一个工具不能解释内生 X 变量的大部分变化,那么它就被认为是“弱工具”无需深究(更多信息可在此处找到),使用弱工具的 IV 回归结果可以创建偏向 OLS 方向的参数估计。不理想。然而,一个简单的经验法则是,只要第一阶段回归的 F 统计量超过 10,就可以认为一个工具是而不是弱的。因此,我们将手动计算回归的第一阶段。

我们的 IV 回归方法的第一步是在工具上回归对数鸡肉价格:对数鸡饲料价格和对数玉米价格,这样我们的方程看起来像:

ln(鸡价)= 0+1 * ln(鸡饲料)+2 * ln(玉米价格)。

下面是使用 jtools 包产生的第一阶段回归输出。287.95 的 F 统计量大大超过了判断我们的工具是否相关的经验法则。而且,调整后的-R 值 0.94 告诉我们,这些工具非常适合鸡肉价格。

因此,我们可以满怀信心地进入第二阶段。

在 IV 回归的第二阶段,我们根据内生自变量和任何其他外生自变量的预测值来回归因变量。在这种情况下,因变量是对数数量,预测变量是对数鸡肉价格。为了确保我们的回归系数不会因遗漏变量而有偏差,我们将包括额外的预测因素,如收入、通货膨胀、人口和牛肉价格。牛肉价格包括在内,因为它们代表了鸡肉的替代品。我们的模型被指定为:

ln(Q)= 0+1 * ln(Pred。小鸡价格)+2 * ln(Y)+3(CPI)+4(牛肉价格)+4(人口)

其中 Q 代表数量,Y 代表收入,CPI 代表消费价格指数。

所以让我们估计一下我们的模型。下面是一组 OLS 回归的模型估计,其中 I 没有实现工具变量。

正如我们在“仅价格”模型中看到的,价格对数量的影响是积极的,这与我们对需求曲线关系的预期相矛盾。然而,当我们在随后的两个模型中添加控制变量时,价格系数的符号会发生变化,以符合我们的预期。

然而,在咨询了菲利普和休厄尔·赖特之后,我们太聪明了,不会被这些有偏见的回归系数所迷惑。相反,我们需要实现我们的工具变量方法。当我们这样做时,用玉米和鸡饲料价格作为我们的工具,我们将获得无偏回归系数。以下是工具变量模型估计,控制变量与上述相同。

有趣的是,在没有额外控制的第一个模型中,价格变量的符号是错误的,就像上面的传统 ols 模型一样。这表明在价量关系中存在显著的遗漏变量偏差。然而,OLS 模型和 IV 模型之间的关键区别在于“全模型”规格。

OLS 模型表明,价格上涨 1%会导致鸡肉需求量下降 0.42%。然而,IV 模型表明,价格上涨 1%会导致鸡肉需求量下降 0.54%。IV 模型的结果表明 OLS 对价格-数量关系的估计偏向于零,因此低估了价格对数量的影响。

智能脚链行业的应用

在我们的例子中,有偏差的 OLS 结果和无偏差的 IV 结果之间的差异非常显著,尤其是对于快节奏鸡肉生产行业的数据科学家而言。对于你在智能脚链行业的朋友来说,这种差异也非常重要。

对于商业应用,对潜在市场的准确评估是很重要的。你的朋友希望将智能脚链引入可穿戴设备行业,他需要彻底了解消费者在决定购买哪种可穿戴产品时如何评估价格。如果你向你的朋友提供 OLS 结果,而不是我们上面例子中的 IV 结果,他会低估消费者对价格的敏感度。因此,他可能会把他的产品以过高的价格推向市场,超出消费者的支付能力。

因此,让我们回顾一下估算准确需求曲线的关键步骤。

步骤 1)识别您的乐器

回想一下,价格是在供给曲线和需求曲线的交叉点上确定的。正如 Philip 和 Sewall Wright 认识到的,我们可以通过保持需求不变,利用供给曲线的变化,并确定交点来描绘需求曲线。从统计学上来说,我们可以通过在 IV 回归过程中使用供应转移器作为工具来实现这一点。作为工具包括的关键变量是影响生产成本的变量,如投入材料的成本。在技术部门,这种投入可能包括硅、钴和铝。在肉类产品中,这些投入可能是玉米、小麦或农民为牲畜购买的其他商品的价格。在任何情况下,我们都需要批判性地思考,在我们感兴趣分析的任何市场中,是什么影响了生产商品的成本,然后在我们的模型中使用这些变量作为工具。

第二步)检查你的仪器

回想一下我们的两个条件:工具相关性和工具外生性。这些可以总结为一句话-Z 变量应该只通过它与 X 变量的关系来影响 Y 变量。就需求曲线而言,该工具应该只通过对供给曲线的影响来影响价格。也就是说,工具的变化不应对需求产生任何影响。这最后一部分与仪器的外生性有关,通常不是一个可测试的条件。这意味着,我们需要利用我们的行业专业知识和直觉来确定我们的工具是否只是按照预期转移供应。

在菲利普·赖特的问题中,降雨可以持久地影响需求和供给。更高的降雨量可能会阻止市场上的人离开舒适的小屋去买黄油。然而,利用我们的直觉,我们可以得出结论,这种关系可能很小,很难观察到,或者不存在。然而,要记住的重要一点是,我们必须批判性地思考我们的工具是否满足这两个必要条件。

步骤 3)考虑省略的变量和模型规格

正如联立方程被证明是确定需求曲线的一个问题一样,省略变量也是一个问题。正如我之前讨论的,省略变量会在我们的模型中引起统计偏差,这就是为什么使用控制变量很重要,即使在 IV 模型中也是如此。在估计需求曲线时,收入是一个关键变量。收入是需求转移因素——随着收入的增加,消费者倾向于以同样的价格要求更多的产品。对于市场分析师来说,了解消费者的收入和他们以一定价格购买产品的意愿之间的关系是一条关键信息。正如我们在上面的例子中看到的,包括收入和替代商品的价格等变量可以显著地改变回归系数,使其接近无偏的真实系数值。因此,我们应该努力追求并包括任何我们认为可能改变需求曲线的变量,作为我们模型中的外生变量。

此外,理解模型规范也很重要。两种最常见的规格是线性需求曲线和对数需求曲线。关于实现哪个规范的决定很大程度上取决于哪个解释更适合数据。在线性需求曲线中,价格每增加一个单位,需求量就会减少-1。同时,根据对数需求曲线,价格上涨百分之一会减少百分之一的需求量。在任何情况下,我们都可以通过估计两个模型来测试哪个模型更好地拟合数据——一个模型中的数量和价格是对数转换的,另一个不是——并比较拟合优度度量,如 R。

第四步走向世界

一旦您确定了潜在的工具,审查了它们的外来性和相关性,并考虑了您的模型规范,您就可以部署工具变量回归了。无论你是一家正在制定定价策略的初创公司,还是一家试图更好地了解你的客户群的老牌公司,工具变量都可以在你的数据科学武器库中扮演 工具 角色。

posted @ 2024-10-16 08:59  绝不原创的飞龙  阅读(188)  评论(0)    收藏  举报