TowardsDataScience-博客中文翻译-2020-五十一-
TowardsDataScience 博客中文翻译 2020(五十一)
预测误差测量:通过实验了解它们
入门
测量是导致控制和最终改进的第一步。
H.詹姆斯·哈林顿
在许多商业应用中,提前计划的能力是最重要的,在大多数这样的情况下,我们使用预测来帮助我们提前计划。例如,如果我经营一家零售店,我今天应该订购多少盒那种洗发水?看预报。我能在年底实现我的财务目标吗?让我们预测一下,并在必要时做出调整。如果我经营一家自行车租赁公司,明天下午 4 点我需要在地铁站放多少辆自行车?
如果对于所有这些情况,我们都根据预测采取行动,我们也应该知道这些预测有多好。在经典统计或机器学习中,我们有一些通用的损失函数,如平方误差或绝对误差。但是由于时间序列预测的发展,有更多的方法来评估你的表现。
在这篇博文中,让我们通过实验来探索不同的预测误差度量,并了解它们各自的缺点和优点。
时间序列预测中的度量
有几个关键点使得时间序列预测中的指标从机器学习中的常规指标中脱颖而出。
1.时间相关性
顾名思义,时间序列预测具有内置的时间方面,并且有累积预测误差或预测偏差等指标也采用这种时间方面。
2.聚合指标
在大多数业务用例中,我们不会预测单个时间序列,而是一组相关或不相关的时间序列。高层管理人员不希望单独查看这些时间序列中的每一个,而是希望看到一个总体的度量,直接告诉他们我们的预测工作做得有多好。即使对于从业者来说,这种综合的方法也能帮助他们对建模过程中的进展有一个总体的感觉。
3.超出或低于预测
预测的另一个关键方面是过度预测和预测不足的概念。我们不希望预测模型有结构性偏差,总是超过或低于预测。为了解决这些问题,我们需要既不高估也不低估的指标。
4.可解释性
最后一个方面是可解释性。因为非分析业务功能也使用这些指标,所以它需要是可解释的。
由于这些不同的使用情形,这一领域使用了许多指标,在这里,我们尝试将其统一在某种结构下,并对它们进行严格的检查。
预测指标的分类
我们可以对不同的预测指标进行分类。广义地说。分成两个桶— 内在的和外在的。内在度量是仅采用生成的预测和基础事实来计算指标的度量。外部指标是指除了生成的预测和基本事实之外,还使用外部参考预测来计算指标的指标。
现在让我们坚持内在的度量(外在的度量需要完全不同的度量)。我们有四种主要的方法来计算误差——绝对误差、平方误差、百分比误差和对称误差。所有这些指标都是这些基本误差的不同集合。因此,不失一般性,我们可以讨论这些宽泛的部分,它们也适用于这些标题下的所有指标。
绝对误差
这组误差测量以误差的绝对值为基础。
平方误差
我们不是取绝对值,而是将误差平方,使其为正,这是这些指标的基础。
百分误差
在这组误差测量中,我们用地面实况来衡量绝对误差,将其转换成百分比项。
对称误差
对称误差被提出来作为百分比误差的替代,在百分比误差中,我们将预测值和实际值的平均值作为衡量绝对误差的基础。
实验
不要只是说这些是这样那样的度量标准的缺点和优点,让我们设计几个实验,自己看看那些优点和缺点是什么。
比例依赖性
在这个实验中,我们试图找出时间序列的规模对聚合度量的影响。在这个实验中,我们
- 生成 10000 个不同尺度的合成时间序列,但误差相同。
- 将这些系列分割成 10 个柱状图箱
- 样本量= 5000;迭代每个容器
- 从当前箱中取样 50%,从其他箱中平均分配 res。
- 计算这组时间序列的聚合度量
- 靠着垃圾箱下边缘记录
- 根据条块边缘绘制总测量值。
对称性
误差测量应与输入对称,即预测和地面实况。如果我们交换预测值和实际值,理想情况下,误差指标应该返回相同的值。
为了测试这一点,让我们为实际值和预测值制作一个从 0 到 10 的网格,并计算该网格上的误差指标。
互补对
在这个实验中,我们采用互补的基础事实和预测对,它们加起来是一个常量,并测量每个点的性能。具体来说,我们使用与对称性实验相同的设置,并计算沿交叉对角线的点,其中地面真实值+预测值总和总是为 10。
损耗曲线
我们的指标依赖于两个实体——预测和实际情况。我们可以用一个对称的误差范围(例如-10 到 10)来修正一个,改变另一个,然后我们期望该度量在该范围的两边表现相同。在我们的实验中,我们选择固定基础事实,因为在现实中,这是固定的数量,我们根据基础事实来衡量预测。
过欠预测实验
在这个实验中,我们生成了 4 个随机时间序列——基本事实、基线预测、低预测和高预测。这些只是在一个范围内产生的随机数。地面实况和基线预测是在 2 和 4 之间产生的随机数。预测下限是在 0 到 3 之间生成的随机数,预测上限是在 3 到 6 之间生成的随机数。在这种情况下,基准预测应该作为我们的基准,低预测是我们持续低估的预测,高预测是我们持续高估的预测。现在让我们计算这三个预测的 MAPE,并重复这个实验 1000 次。
异常影响
为了检查对异常值的影响,我们设置了下面的实验。
我们想要检查异常值对两个轴的相对影响——异常值的数量,异常值的规模。因此,我们定义了一个网格—离群值的数量[0%-40%]和离群值的范围[0 到 2]。然后,我们随机选取一个合成时间序列,并根据我们之前定义的网格参数迭代地引入异常值,并记录误差度量。
结果和讨论
绝对误差
对称性
这是一个很好的对称热图。我们看到对角线上的误差为零,较高的误差以一种很好的对称模式远离对角线。
损耗曲线
再次对称。如果我们走曲线的两边,MAE 变化相等。
互补对
又是好消息。如果我们改变预测,保持实际值不变,反之亦然,指标的变化也是对称的。
预测过高和过低
正如预期的那样,预测过高或过低对 MAE 没有太大影响。两者都受到同等的处罚。
比例依赖性
这是梅的致命弱点。在这里,当我们增加时间序列的基础水平时,我们可以看到 MAE 线性增加。这意味着当我们跨时间序列比较性能时,这不是您想要使用的衡量标准。例如,当比较两个时间序列时,一个级别为 5,另一个级别为 100,使用 MAE 总是将较高的误差分配给级别为 100 的时间序列。另一个例子是当你想比较你的时间序列的不同子部分,看看哪里的误差更大(例如,不同的产品类别,等等。),那么使用 MAE 总是会告诉你,平均销售额较高的子部门也会有较高的 MAE,但这并不意味着该子部门做得不好。
平方误差
对称性
平方误差也显示了我们正在寻找的对称性。但我们在这里可以看到的另一点是,误差倾向于更高的误差。对角线上的颜色分布不像我们在《绝对误差》中看到的那样均匀。这是因为平方误差(因为平方项)将较高的影响分配给较低误差的较高误差。这也是平方误差通常更容易因异常值而失真的原因。
边注:由于平方误差和绝对误差也被用作许多机器学习算法中的损失函数,这也对这种算法的训练有影响。如果我们选择平方误差损失,我们对较小的误差不太敏感,对较大的误差更敏感。如果我们选择绝对误差,我们会平等地惩罚较高和较低的误差,因此单个异常值不会对总损失产生太大影响。
损耗曲线
我们在这里也可以看到同样的模式。它围绕原点对称,但由于二次型,较高的误差比较低的误差不成比例地多。
互补对
预测过高和过低
与 MAE 类似,由于对称性,过度预测和预测不足会产生几乎相同的影响。
比例依赖性
与 MAE 类似,RMSE 也有规模依赖问题,这意味着我们讨论的 MAE 的所有缺点在这里也适用,但更糟。我们可以看到,当我们增加比例时,RMSE 的比例是平方的。
百分误差
百分比误差是业内使用的最普遍的误差度量。它大受欢迎的几个原因是:
- 规模独立—正如我们在前面的规模依赖关系图中看到的,随着时间序列规模的增加,MAPE 线是平坦的。
- 可解释性——由于误差被表示为一个百分比项,这是非常流行和可解释的,误差度量也立即变得可解释。如果我们说 RMSE 是 32,这并不意味着孤立的。但另一方面,如果我们说 MAPE 是 20%,我们马上就知道预测的好坏。
对称性
这看起来不太对,是吗?百分比误差是其中最常见的,它看起来一点也不对称。事实上,我们可以看到,当实际值接近零时,误差达到峰值,当实际值为零时,误差趋于无穷大(底部的无色带是因为除以零而导致误差无穷大的地方)。
我们可以看到百分比误差的两个缺点:
- 当基础真值为零时,它是未定义的(因为被零除)
- 当地面真实值较低时(右上角),它会指定较高的误差
让我们看看损耗曲线和互补对图,以了解更多信息。
损耗曲线
突然间,我们看到的不对称不复存在了。如果我们保持基本真理不变,百分误差在原点周围是对称的。
互补对
但是当我们看互补对时,我们看到了之前在热图中看到的不对称。当实际值较低时,同样的误差比预测值较低时的误差百分比高得多。
所有这一切都是因为我们用来衡量它的基数。即使我们有相同大小的误差,如果地面真值低,误差百分比就会高,反之亦然。例如,让我们回顾两个案例:
- F = 8,A=2 ->绝对百分比误差=(8–2)/2 = 3
- F=2,A=8 ->绝对百分比误差=(8–2)/8 = 0.75
有无数的论文和博客声称百分比误差的不对称性是一个交易破坏者。流行的说法是,绝对百分比误差对过度预测的惩罚大于对不足预测的惩罚,或者换句话说,它鼓励了不足预测。
反对这一点的一个论点是,这种不对称只是因为我们改变了地面真相。期望值为 2 的时间序列的误差为 6 比期望值为 6 的时间序列的误差为 2 要严重得多。所以根据直觉,百分误差是做它应该做的,不是吗?
预测过高和过低
不完全是。在某种程度上,对百分误差的批评是有道理的。这里我们看到,我们低估的预测比我们高估的预测具有更低的 MAPE。低 MAPE 的传播也大大低于其他。但是,就商业而言,这是否意味着总是预测较低的预测是更好的预测呢?绝对不行。在供应链中,这会导致缺货,如果你想在市场中保持竞争力,这不是你想要的。
对称误差
对称误差被认为是比百分比误差更好的选择。百分比误差有两个主要缺点——当地面真值为零时不确定和不对称。和预测的平均值作为计算百分比误差的基础来解决这两个问题。
对称性
马上,我们可以看到这是围绕对角线对称的,几乎类似于对称情况下的绝对误差。底部的栏是空的,现在有了颜色(这意味着它们不是未定义的)。但是仔细观察会发现更多的东西。它不是围绕第二条对角线对称的。我们看到,当实际值和预测值都较低时,误差会更大。
损耗曲线
这在损耗曲线中更为明显。随着原点两侧误差的增加,我们可以看到不对称性。与名字相反,对称误差对预测不足的惩罚大于对预测过度的惩罚。
互补对
但是当我们看互补对时,我们可以看到它是完全对称的。这可能是因为基数,我们保持不变。
预测过高和过低
我们在这里也可以看到同样的情况。与预测不足系列相比,预测过度系列的误差始终较低。因此,在努力使对百分比误差预测不足的偏差正常化的过程中,对称误差反其道而行之,偏向于预测过度。
异常影响
除了上述实验之外,我们还运行了一个实验来检查异常值(完全偏离的单个预测)对聚合指标的影响。
当遇到异常值时,所有四种误差度量具有相似的行为。离群值的数量比离群值的规模有更大的影响。
在这四个国家中,RMSE 受离群值的影响最大。我们可以看到等高线间隔很远,这表明当我们引入异常值时,变化率很高。另一方面,sMAPE 受离群值的影响最小。从平坦而密集的等高线可以明显看出。梅和 MAPE 的表现几乎相似,可能 MAPE 稍微好一点。
摘要
最后,没有一个度量标准可以满足误差测量的所有需求。根据不同的用例,我们需要挑选。在四个内在衡量指标中(及其所有聚合指标,如 MAPE、梅伊等)。),如果不关心可解释性和尺度依赖性,就应该选择绝对误差度量。当我们寻找与规模无关的度量标准时,百分误差是我们最好的选择(尽管它有很多缺点)。在这种情况下,像标度误差这样的外部误差度量提供了一个更好的选择(也许在另一篇博文中,我也会谈到这些)。)
代码重现实验
在 GitHub 上创建一个帐户,为 manujosephv/forecast_metrics 的发展做出贡献。
github.com](https://github.com/manujosephv/forecast_metrics/tree/master)
查看该系列的其余文章
- 预测误差度量:通过实验了解它们
- 预测误差度量:比例误差、相对误差和其他误差
- 预测误差度量:间歇需求
延伸阅读
- Shcherbakov 等人,2013 年,预测误差测量调查
- Goodwin & Lawton,1999,关于对称 MAPE 的不对称性
编辑(29–09–2020):修正了等高线图 中的一个标注错误问题
原载于 2020 年 9 月 26 日【http://deep-and-shallow.com】。
将外部信息作为预测因素的预测
照片由维达尔·诺德里-马西森在 Unsplash 拍摄
R 中预测方法如何利用外部信息的简单案例研究
预测在某些情况下是必需的:预测一个行业的供给和需求,预测产品需求和生产中需要的劳动力,预测像降雨这样的天气,或者更多的情况可以使用预测来解决。最常用的预测方法是仅使用其历史数据,如趋势和季节性,而忽略了剩余因素(从外部来源获得的信息)。然而,如果我们处理一些与一些外部信息高度相关的数据,这并没有错,但是不够明智。例如,旅游业假期的影响、金融和银行业的通货膨胀率、竞争对手的行动以及许多其他条件都需要考虑外部信息。
虽然数据科学工具已经显著发展,但它有助于预测者简化他们的工作。我们将以使用 R 创建预测为例,包括外部信息,作为其预测器的一部分。
我们的数据集包含印度尼西亚万隆的月降雨量、雨天数、平均温度等信息;
- 降雨量:以平方毫米为单位,指给定时间内给定区域的降雨量
- 下雨天数:下雨的天数
- 平均温度
图一。万隆数据集的头
万隆数据集包含 2014 年至 2019 年范围内的时间序列信息。由于这应该在进行任何分析工作之前完成,我们需要有一个我们想要解决的明确目标,在这种情况下,我们将我们的目标设定为预测 2020 年期间的降雨天数。使用降雨量或温度中的一个或两个,我们将尝试创建一个简单的预测方法来达到我们的目标。
探索我们的数据
图二。分解图
时间序列的分解是探索数据内部任何信息的最有力的技术之一。利用这一点,我们可以计算趋势和季节性强度,并找出其趋势和季节性的剩余模式。如果我们排除外部信息,我们将只利用季节性和趋势模式进行分析,并将剩余部分视为误差。当我们使用外部信息作为我们的预测器时,区别在于我们可以使用我们的外部信息来解释剩余分量的变化,或者简单地说,由我们的外部信息组成的剩余分量。
那么,如何确定我们应该使用哪些信息作为我们的外部预测器呢?最有用但最直接的方法是检查它与我们的目标变量的相关性:
图三。相关表
降雨量与降雨量有适度的相关性。我们将利用这个变量作为我们的外部预测。但是,让我们先来看看这些变量之间的曲线:
图 4。降雨量和降雨量时间序列图
在这个简单的图表上,我们可以看到雨滴(底部)和降雨量(顶部)虽然不完全相同,但由于它们在周期内的相关性,仍然有相似的运动。
时间序列预测
R 中的自动 Arima 函数使得预测比它看起来更容易。但是要在我们的模型中包含外部信息,我们必须用我们的预测器(外部信息)指定 xreg 参数。最后, auto.arima() 将进行剩余的计算,并为我们找到最佳模型。
#Creating Model
fit <- auto.arima(Bandung[,2], xreg=Bandung[,1], stepwise = FALSE,
approximation = FALSE, biasadj= TRUE)**#Summary of Our Model****Series: Bandung[, 2]
Regression with ARIMA(5,1,0) errors
Coefficients:
ar1 ar2 ar3 ar4 ar5 xreg
-0.8445 -0.7907 -0.8163 -0.7130 -0.7036 0.0269
s.e. 0.0911 0.1081 0.1003 0.1038 0.0847 0.0049
sigma^2 estimated as 25.51: log likelihood=-214.8
AIC=443.59 AICc=445.37 BIC=459.43**#Check Residuals
checkresiduals(fit)**Ljung-Box test
data: Residuals from Regression with ARIMA(5,1,0) errors
Q* = 7.0153, df = 8, p-value = 0.535
Model df: 6\. Total lags used: 14**
图五。拟合模型的残差检验
auto.arima() 选择具有 5 阶自回归和一阶差分的非季节性 arima 模型,其中包含误差作为我们的 xreg (外部预测器)。如果我们看到我们的模型的细节,xreg 组件与 AR 的 5 阶相比,对计算没有那么大的影响。但我们将继续下去,因为这是唯一一个使用简单数据集的简单教程。对于另一个数据集,外部预测可能对模型计算更有影响。
已经完成的残差检验显示残差彼此之间不相关,这意味着我们的模型可以很好地使用。
为了使用具有外部信息的模型进行预测,我们需要获得外部信息的未来值。这一步对不同的数据集有不同的处理。如果我们可以根据专业知识直接预测它的未来价值,我们就可以直接使用它。但是,如果我们不能立即预测其未来价值,我们可以建立一个单独的模型,并在与我们的主要预测目标相同的时间范围内预测其未来价值。对于我们的例子,我们将使用 auto.arima()构建另一个模型并预测其未来值:
图六。未来 12 个月的预测值
利用已知的外部预测值,我们最终可以对 2020 年的降雨进行预测,并可视化其结果。
图七。未来 12 个月的降雨预报
图八。2020 年万隆降雨预报
我们的预测显示,2020 年将有两个月(6 月和 12 月)的月降雨日数最少,最高降雨日数出现在 3 月和 9 月。
这就是我们如何进行预测,将外部信息作为模型中的一个回归变量。更详细地说,我们还可以将仅使用趋势和季节性的预测与使用外部信息的预测进行比较,并找出哪个模型更好。然而,无论你选择哪种方法,都没有错,因为不同的数据需要不同的处理。
对于免责声明,本文仅讨论如何在我们的时间序列模型中包括外部回归变量,因此在预测雨天的真实情况下,我建议咨询气候专家,并找到另一个与雨天如何发生相关的变量。
你可以在这个链接上找到数据集。
使用 LSTM 预测酒店的平均每日房价趋势
以下是如何使用 LSTM 模型来预测酒店的 ADR(平均每日房价),这是业内的一个重要指标。
平均每日房价(ADR)被认为是酒店最重要的指标之一。
资料来源:pixabay.com
其计算方法如下:
ADR = Revenue ÷ sold rooms
实质上,ADR 是衡量一个酒店房间在特定时期的平均价格。
背景
正在研究的数据集由一家葡萄牙酒店的取消预订组成,其中包括每个单独预订的 ADR 作为包含变量之一。
使用时间序列分析,我们假设酒店希望 1)计算给定一周内所有预订的平均 ADR 值,2)使用该数据预测未来每周 ADR 趋势——每周 ADR 是指任何一周内所有预订的平均 ADR——以下称为“每周 ADR”。
人们会注意到,数据集中有许多 ADR 值为正的取消事件,在这种情况下,假设即使客户取消了预订,他们最终仍会被收取预订费用(例如,在取消截止日期后取消,等等)。
一个长短期记忆网络(LSTM)被用来做这件事。LSTMs 是顺序神经网络,它假设特定序列中的观察值之间存在相关性。因此,它们越来越多地被用于时间序列预测的目的。
作为参考,每个客户的 ADR 也包括在内——考虑到一些客户既是公司也是个人,这导致在许多情况下每次预订不止一个房间。
数据操作
使用 pandas,完整的日期(年份和周数)与每个预订的相应 ADR 值相结合。
然后将这些数据点组合在一起,以获得所有预订的每周平均每日房价,如下所示:
df4 = df3.groupby('FullDate').agg("mean")
df4
df4.sort_values(['FullDate'], ascending=True)
以下是新数据帧的外观:
顺便提一下,完整的笔记本和数据集可以在下面提供的 GitHub 资源库的链接中找到,其中更详细地说明了数据操作过程。
生成时间序列图:
import matplotlib.pyplot as plt
plt.plot(tseries)
plt.tick_params(
axis='x', # changes apply to the x-axis
which='both', # both major and minor ticks are affected
bottom=False, # ticks along the bottom edge are off
top=False, # ticks along the top edge are off
labelbottom=False) # labels along the bottom edge are off
plt.ylabel('ADR')
plt.title("Weekly ADR")
plt.show()
LSTM 模型配置
让我们开始分析 H1 数据集。创建的时间序列的前 100 个观察值称为。然后,创建数据集矩阵,并对数据进行缩放。
df = df[:100]# Form dataset matrix
def create_dataset(df, previous=1):
dataX, dataY = [], []
for i in range(len(df)-previous-1):
a = df[i:(i+previous), 0]
dataX.append(a)
dataY.append(df[i + previous, 0])
return np.array(dataX), np.array(dataY)
然后,使用 MinMaxScaler 对数据进行归一化,以便神经网络正确解释数据:
# normalize dataset with MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))
df = scaler.fit_transform(df)
df
以下是输出示例:
array([[0.35915778],
[0.42256282],
[0.53159902],
...
[0.27125524],
[0.26293747],
[0.25547682]])
数据被分成训练集和测试集,其中先前的参数被设置为 5:
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import LSTM# Training and Validation data partition
train_size = int(len(df) * 0.8)
val_size = len(df) - train_size
train, val = df[0:train_size,:], df[train_size:len(df),:]# Number of previous
previous = 5
X_train, Y_train = create_dataset(train, previous)
X_val, Y_val = create_dataset(val, previous)
当先前参数设置为该值时,这实质上意味着时间 t (训练数据的 Y_train)的值是使用值 t-1 、 t-2 、 t-3 、 t-4 和 t-5 (均在 X_train 下)预测的。
这里是一个 Y_train 数组的例子:
array([0.70858066, 0.75574219, 0.7348692 , 0.63555916, 0.34629856,
0.32723163, 0.18514608, 0.21056117, 0.13243974, 0.1321469 ,
0.06636683, 0.09516089, 0.02223529, 0.02497857, 0.06036494,
...
0.12222412, 0.07324677, 0.05206859, 0.05937164, 0.04205497,
0.0867528 , 0.10976084, 0.0236608 , 0.11987636])
这里是一个 X_train 数组的例子:
array([[0.35915778, 0.42256282, 0.53159902, 0.6084246 , 0.63902841],
[0.42256282, 0.53159902, 0.6084246 , 0.63902841, 0.70858066],
[0.53159902, 0.6084246 , 0.63902841, 0.70858066, 0.75574219],
...
[0.07324677, 0.05206859, 0.05937164, 0.04205497, 0.0867528 ],
[0.05206859, 0.05937164, 0.04205497, 0.0867528 , 0.10976084],
[0.05937164, 0.04205497, 0.0867528 , 0.10976084, 0.0236608 ]])
运行 100 个时期:
# reshape input to be [samples, time steps, features]
X_train = np.reshape(X_train, (X_train.shape[0], 1, X_train.shape[1]))
X_val = np.reshape(X_val, (X_val.shape[0], 1, X_val.shape[1]))# Generate LSTM network
model = tf.keras.Sequential()
model.add(LSTM(4, input_shape=(1, previous)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
history=model.fit(X_train, Y_train, validation_split=0.2, epochs=100, batch_size=1, verbose=2)
以下是一些示例结果:
Train on 59 samples, validate on 15 samples
Epoch 1/100
59/59 - 1s - loss: 0.0689 - val_loss: 0.0027
Epoch 2/100
59/59 - 0s - loss: 0.0431 - val_loss: 0.0118
...
Epoch 99/100
59/59 - 0s - loss: 0.0070 - val_loss: 0.0031
Epoch 100/100
59/59 - 0s - loss: 0.0071 - val_loss: 0.0034
dict_keys(['loss', 'val_loss'])
这是培训和验证损失的直观表示:
训练和验证预测
现在,让我们进行一些预测。
# Generate predictions
trainpred = model.predict(X_train)
valpred = model.predict(X_val)
以下是训练和测试预测的示例:
训练预测
>>> trainpred
array([[0.6923234 ],
[0.73979336],
[0.75128263],
...
[0.09547461],
[0.11602292],
[0.050261 ]], dtype=float32)
测试预测
>>> valpredarray([[0.06604623],
[0.0982968 ],
[0.10709635],
...
[0.3344252 ],
[0.2922875 ]], dtype=float32)
使用scaler.inverse_transform
将预测值转换回正常值,并计算训练和验证分数。
import math
from sklearn.metrics import mean_squared_error# calculate RMSE
trainScore = math.sqrt(mean_squared_error(Y_train[0], trainpred[:,0]))
print('Train Score: %.2f RMSE' % (trainScore))
valScore = math.sqrt(mean_squared_error(Y_val[0], valpred[:,0]))
print('Validation Score: %.2f RMSE' % (valScore))
培训和验证分数
Train Score: 12.71 RMSE
Validation Score: 8.83 RMSE
以下是预测的图表:
测试和预测阵列被相应地重新整形,并且平均方向精度的函数被定义为:
import numpy as npdef mda(actual: np.ndarray, predicted: np.ndarray):
""" Mean Directional Accuracy """
return np.mean((np.sign(actual[1:] - actual[:-1]) == np.sign(predicted[1:] - predicted[:-1])).astype(int))
模型结果
现在计算平均方向精度:
>>> mda(Y_val, predictions)
0.8571428571428571
获得了 86% 的 MDA,这意味着该模型在 86%的时间内正确预测了实际每周 ADR 趋势的方向。
如上所示,还获得了 8.83 RMSE 的验证分数。RMSE 是衡量每周 ADR 与实际值之间的偏差,并采用相同的数字格式。验证数据的平均每周 ADR 为 69.99 。
验证数据的平均预测误差为 -1.419 :
>>> forecast_error = (predictions-Y_val)
>>> forecast_error
>>> mean_forecast_error = np.mean(forecast_error)
>>> mean_forecast_error
-1.419167548625413
测试看不见的(测试)数据
既然模型已经定型,下一步就是在看不见的(或测试数据)上测试模型的预测。
如前所述,LSTM 使用值 t-1 、 t-2 、 t-3 、 t-4 和 t-5 预测时间 t 的值。
在这种情况下,预测系列中最后 15 周的 ADR 值。
actual = tseries.iloc[100:115]
actual = np.array(actual)
actual
先前建立的模型现在用于使用时间序列中的前五个值来预测每个值:
# Test (unseen) predictions
# (t) and (t-5)
>>> XNewarray([[ 82.1267268 , 90.48381679, 85.81940503, 84.46819121,
83.25621451],
[ 90.48381679, 85.81940503, 84.46819121, 83.25621451,
84.12304147],
...
[189.16831978, 198.22268542, 208.71251185, 211.52835052,
211.16204036],
[198.22268542, 208.71251185, 211.52835052, 211.16204036,
210.28488251]])
变量被适当缩放,并调用model.predict
:
Xnew = scaler.transform(Xnew)
Xnew
Xnewformat = np.reshape(Xnew, (Xnew.shape[0], 1, Xnew.shape[1]))
ynew=model.predict(Xnewformat)
以下是生成的预测数组:
array([0.02153895, 0.0157201 , 0.12966183, 0.22085814, 0.26296526,
0.33762595, 0.35830092, 0.54184073, 0.73585206, 0.8718423 ,
0.92918825, 0.9334069 , 0.8861607 , 0.81483454, 0.76510745],
dtype=float32)
数组被转换回原始值格式:
>>> ynew = ynew * np.abs(maxt-mint) + np.min(tseries)
>>> ynewpd=pd.Series(ynew)
>>> ynewpd0 45.410988
1 44.423096
2 63.767456
3 79.250229
4 86.398926
5 99.074379
6 102.584457
7 133.744766
8 166.682877
9 189.770493
10 199.506348
11 200.222565
12 192.201385
13 180.092041
14 171.649673
dtype: float32
这里是计算出的 MDA 、 RMSE 、 MFE(平均预测误差)。
丙二醛= 0.86
>>> mda(actualpd, ynewpd)0.8666666666666667
RMSE = 33.77
>>> mse = mean_squared_error(actualpd, ynewpd)
>>> rmse = sqrt(mse)
>>> print('RMSE: %f' % rmse)RMSE: 33.775573
MFE = -30.17
>>> forecast_error = (ynewpd-actualpd)
>>> mean_forecast_error = np.mean(forecast_error)
>>> mean_forecast_error-30.173496939933216
随着测试集的平均每周 ADR 达到 160.49 ,RMSE 和 MFE 表现看起来相当强劲(误差越低越好)。
H2 结果
在 H2 数据集(葡萄牙一家独立酒店的 ADR 数据)上执行了相同的过程。以下是将预测与测试集进行比较的结果:
丙二醛= 0.86
>>> mda(actualpd, ynewpd)0.8666666666666667
RMSE = 38.15
>>> mse = mean_squared_error(actualpd, ynewpd)
>>> rmse = sqrt(mse)
>>> print('RMSE: %f' % rmse)RMSE: 38.155347
MFE = -34.43
>>> forecast_error = (ynewpd-actualpd)
>>> mean_forecast_error = np.mean(forecast_error)
>>> mean_forecast_error-34.437111023457376
对于 H2 数据集,测试集的平均每周 ADR 为 131.42 ,相比之下,RMSE 和 MFE 误差较低。
结论
在本例中,您已经看到了如何使用 LSTM 模型预测 ADR。具体而言,上述示例说明了:
- 如何构建 LSTM 模型
- 测量 LSTM 模式预测的误差和精确度的方法
本例的数据集和笔记本可从 MGCodesandStats GitHub 库获得,以及对该主题的进一步研究。
你也可以在 michael-grogan.com找到更多我的数据科学内容。
免责声明:本文是在“原样”的基础上编写的,没有任何担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。
预测印度的新冠肺炎病例
到 2020 年 4 月 7 日,印度将发现多少病例?
自 2019 年 12 月在中国武汉首次报道后,新冠肺炎在世界各地掀起了风暴。自那时以来,全球此类案件的数量呈指数级增长。截至 2020 年 3 月 28 日,报告的病例总数达到 668,352 例,其中 31,027 例已经死亡。下图显示了病毒在不同国家的爆发情况
演职员表:拉斐尔·杜楠特,链接:https://en . Wikipedia . org/wiki/2019% E2 % 80% 9320 _ 冠状病毒 _ 疫情#/media/File:新冠肺炎 _ 疫情 _ 世界 _ 地图 _ 人均. svg
可以很好地观察到,大多数国家都报告了新型冠状病毒病例。截至目前,已影响 192 个国家和 1 艘国际运输工具(停靠日本横滨港的钻石公主号邮轮)。
就印度而言,这些病例于 1 月底出现在喀拉拉邦,当时有三名学生从中国武汉返回。然而,事情在 3 月份升级,此前全国各地都报告了几起病例,其中大多数人都有去其他国家的旅行史。下图显示了 1 月 30 日至 3 月 28 日期间发现的病例数量。
截至 3 月 28 日确诊病例总数(印度)
在 1 月下旬首次出现后,该数字一直保持稳定,直到 3 月初,此后,它呈指数级增长。截至 3 月 28 日,总病例数已达 987 例,24 例死亡。鉴于目前的增长速度,如果不采取具体的预防措施,这些病例预计在未来 10 天内会到达哪里?
我们可以进行时间序列分析来创建一个有助于预测的模型。数据集可以在 Kaggle 上获得。我们使用 R 编程进行分析。
我们加载必要的包并附加数据集
#COVID India — Analyzing/Forecasting Total Cases#Packages
library(dplyr)
library(ggplot2)
library(hrbrthemes)
library(tseries)
library(forecast)attach(Data)> head(Data)
# A tibble: 6 x 4
Date `Total Confirmed Cases` Cured Deaths
<dttm> <dbl> <dbl> <dbl>
1 2020-01-30 00:00:00 1 0 0
2 2020-01-31 00:00:00 1 0 0
3 2020-02-01 00:00:00 2 0 0
4 2020-02-02 00:00:00 3 0 0
5 2020-02-03 00:00:00 3 0 0
6 2020-02-04 00:00:00 3 0 0
让我们来看看前 6 个观察结果。这些列包括:
日期:记录观察结果的日期。
确诊病例总数:截至给定日期的确诊病例数。
治愈:患者在指定日期康复
死亡:患者在给定日期死亡
由于我们只分析全部确诊病例,因此我们创建了一个仅包含这些病例的新数据框。
#Creating a new data frame with Confirmed Cases
df <- Data[2]
下一步是将数据框转换为时间序列对象。
#Converting it to Time Series Object
tsdata <- ts(df$`Total Confirmed Cases`)
ts.plot(tsdata)
时间序列图
我们得到了每天记录的每个观察值的时间序列图。下一步是检查时间序列是否是平稳的。简而言之,平稳时间序列的统计特性(如均值、方差、自相关)是恒定的。时间序列观测值保持平稳是很重要的,因为这样就很容易得到准确的预测。我们使用扩展的 Dickey Fuller 测试来测试时间序列观测值的平稳性。检验的零假设(Ho)是数据不稳定,而另一个假设是数据稳定。显著性水平(LOS) 取 0.05。
> adf.test(tsdata)Augmented Dickey-Fuller Testdata: tsdata
Dickey-Fuller = 2.2994, Lag order = 3, p-value = 0.99
alternative hypothesis: stationaryWarning message:
In adf.test(tsdata) : p-value greater than printed p-value
p 值结果是 0.99。因此,我们不能拒绝我们的 Ho,并得出数据不是稳定的结论。我们现在必须研究数据的平稳性。根据时间序列的行为,有各种方法可以使我们的时间序列平稳。最流行的是差分法。 差分通过消除时间序列的水平变化,从而消除(或减少)趋势和季节性,帮助稳定时间序列的平均值。从数学上讲,它是这样给出的:
在上面的表达式中, B 是后移运算符, d 表示差分顺序。R 中使用的代码如下
> tsdata1 <- diff(tsdata, differences = 2)
> adf.test(tsdata1)Augmented Dickey-Fuller Testdata: tsdata1
Dickey-Fuller = -4.3764, Lag order = 3, p-value = 0.01
alternative hypothesis: stationaryWarning message:
In adf.test(tsdata1) : p-value smaller than printed p-value
经过两轮差分后,我们再次执行增强迪基富勒测试 (ADF 测试)。 p 值小于 0.01。因此,我们可以拒绝我们的零假设,并得出结论,数据是平稳的。由于差分的顺序是 2, d 是 2。
下一步是绘制 ACF 和 PACF 图。
完整的自相关函数 (ACF)给出了任何序列与其滞后值的自相关。换句话说,ACF 是时间序列与其滞后值之间相关系数的图表。
部分自相关函数 (PACF)给出了两个变量之间的相关量,这不是用它们的相互相关性来解释的,而是用残差来解释的。因此,我们观察残差是否能帮助我们产生更多的信息。关于这个主题的更全面的指南可以在这里找到。
#Plotting the ACF plot and PACF
acf(data1)
pacf(data1)
ACF 图
上面的 ACF 图显示了滞后 3(q)时的显著相关性,而下面的 PACF 图显示了直到滞后 1(p)时的显著相关性。
PACF 图
使用 ARIMA (1,2,3)
基于 ACF 和 PACF,我们选择了 ARIMA (1,2,3)模型。我们将 d 作为 2,因为需要两个差分来使我们的时间序列平稳。我们现在将根据上面选择的参数来拟合模型
#Fitting ARIMA (1,2,3) model
fit1 <- arima(df$`Total Confirmed Cases`, c(1,2,3))
fit1#Forecasting
forecast1 <- forecast(fit1, h = 10)
forecast1
plot(forecast1)
我们得到以下结果
ARIMA (1,2,3)
未来 10 天的点预测(h = 10)
我们预测了未来 10 天的确诊病例,即直到 2020 年 4 月 7 日。该点预测在第 69 天达到 2278 例,也就是到 2020 年 4 月 7 日,总确诊病例很可能达到 2278 例。 还有,需要注意的是,病例几乎每 10 天翻一倍。图中显示了预测的病例。蓝线代表预测,其周围的银色阴影代表置信区间。
未来 10 天的预测
使用 auto.arima()
r 还具有 at auto.arima() 功能,可自动选择 arima 模型的最佳 (p,d,q) 值。让我们利用这一点。
#Fitting auto.arima ()
fit2 <- auto.arima(df$`Total Confirmed Cases`, seasonal = FALSE)
fit2#Forecasting
forecast2 <- forecast(fit2, h = 9)
forecast2
plot(forecast2)
我们得到以下结果
auto.arima(1,2,0)
未来 10 天的点预测(h = 10)
使用 auto.arima(1,2,0) 的模型与我们之前的模型非常相似,但是 q 值为 0。我们得到 486.42 的赤池信息标准(AIC),其小于先前模型的 AIC(491.62)。从点估算中,我们可以看到 总病例数在 第 10 天 达到 2264 例,也就是说,到 2020 年 4 月 7 日,略低于之前模型预测的 2278 例。病例每 10 天多一倍或少一倍。标绘这些预测,我们得到:**
未来 10 天的预测
为了估计模型的充分性,我们进行残差分析。对于一个合适的模型,残差应该是独立的和同分布的,并且应该是不相关的。为了测试相关性,我们使用 ACF 图并寻找显著的相关性。
残差的 ACF 图。
除了 0,在任何滞后都没有观察到显著的相关性。我们可以推断残差是不相关的。为了检验残差是否正态分布,我们使用夏皮罗-维尔克正态性检验。结果表明,残差服从正态分布。
结论
最后,我们对印度的病例总数进行时间序列建模。这个数字每天都在增加,然而,在接下来的几天里,增长的速度将会放缓。如果公众认真对待这些措施,3 月 24 日在印度实施的封锁将防止病毒的社区传播。现在,这是困扰世界每个角落每个人的一个主要问题。作为一个社区,我们有潜力阻止它,我们可以通过防止病毒传播来阻止它。
感谢您的阅读。我真诚地希望它对你有所帮助,并且一如既往地欢迎建设性的反馈。
给我发邮件:icy.algorithms@gmail.com
你可以在 LinkedIn 上找到我。
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
利用 Prophet 和 SARIMA 模型预测新冠肺炎推文量
如何在 ARIMA 建模中确定 twitter 数据的最佳季节性
本文是关于时间序列预测的季节性自回归区间移动平均法。这包括两个部分:首先是使用脸书先知图书馆,这是一个预测时间序列数据的工具,在第二部分,我们将从头开始建立一个最佳 ARIMA 模型,并将其扩展到季节性 ARIMA(萨里玛)。
数据集和笔记本已经上传到T5 这个 资源库中。
数学:
ARIMA 模型的特征在于 3 项:p,d,q:
p = AR 项的阶(自回归)
q = MA 项的阶(移动平均)
d =使时间序列平稳所需的差异数
如果一个时间序列,有季节性模式,我们必须使用季节性 ARIMA 或萨里玛,因为增加了季节性。在 AR 模型中,Yt 取决于模型的滞后。因此,它是“Yt 滞后”的函数。
在 MA 模型中,Yt 取决于滞后预测误差:
误差 Et 和 E(t-1)是来自以下等式的误差:
因此,如果您将 AR 和 MA 模型结合起来,则等式变为:
ARIMA 模型中的文字:
预测 Yt =常数+Y 的线性组合滞后(最多 p 个滞后)+滞后预测误差的线性组合(最多 q 个滞后)
你可以在这里找到更多关于 ARIMA 背后的数学知识。
资料组
我们使用了 Vakavic 记录的 Twitter 数据集,vaka vic 是中东的一个 NLP 服务。该数据集包含从 2020 年 2 月 15 日到 2020 年 4 月 18 日(64 天)发布的 1,259,478 条带有冠状病毒实体的法语推文。让我们快速浏览一下数据:
import pandas as pd
df = pd.read_json('fr-crona-tweets.json')
df.head()
正如您在 datetime 列中看到的,数据是在每秒钟内收集的,因此我们必须按分钟、小时甚至更长时间对它们进行分组。
准备数据
首先,我们只是复制我们需要的列,然后我们将其四舍五入为 1 分钟的季节性,并计算每分钟的 tweets 值。
df = df[['datetime']].copy()timeseason = '1min'
dftime = df['datetime'].dt.round(timeseason)
newdf = dftime.value_counts()
df = pd.DataFrame(newdf)
df.head()
prophet 模型期望数据集具有特定的结构,其中包含时间的列应该命名为“ds”,频率列应该命名为“y”。我们将首先重命名 dataframe 列。然后我们把它写成“1 分钟。CSV”。现在我们可以通过改变“时间季节”变量来创造任何季节性。
df.index.name = 'ds'
df = df.rename(columns = {'datetime':'y'})
nameoffile = str(timeseason+'.csv')
df.to_csv(nameoffile)
df.head()
导入库
import numpy as np
import pandas as pd
from fbprophet import Prophet
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error, mean_absolute_error
plt.style.use('fivethirtyeight')
FB 先知:
Prophet 是一种基于加法模型预测时间序列数据的程序,其中非线性趋势与每年、每周和每天的季节性以及假日影响相适应。它最适用于具有强烈季节效应的时间序列和几个季节的历史数据。
data = pd.read_csv('1min.csv',index_col=[0], parse_dates=[0])data.plot(style='.', figsize=(15,5), color=["#1DA1F2"], title='TimeLine')plt.show()
#Splinting Datasplit_date = '06-apr-2020'data_train = data.loc[data.index <= split_date].copy()data_test = data.loc[data.index > split_date].copy()#Plot train and test so you can see where we have split the datadata_test.rename(columns={'y': 'TEST SET'}).join(data_train.rename(columns={'y': 'TRAINING SET'}),how='outer').plot(figsize=(15,5), title='French tweets about Coronavirus', style='.')plt.show()
通过实例化一个新的 prophet 对象来适应这个模型。预测过程的任何设置都被传递到构造函数中。
model.fit(data_train.reset_index())# Predict on the training set with modeldata_test_fcst = model.predict(df=data_test.reset_index())
data_test_fcst.head()
# Plot the forecastf, ax = plt.subplots(1)
f.set_figheight(5)
f.set_figwidth(15)
fig = model.plot(data_test_fcst,ax=ax)plt.show()
# Plot the components of the modelfig = model.plot_components(data_test_fcst)
定义误差指标
def mean_absolute_percentage_error(y_true, y_pred):
y_true, y_pred = np.array(y_true), np.array(y_pred)
return np.mean(np.abs((y_true - y_pred) / y_true)) * 100MSE = mean_squared_error(y_true=data_test['y'],
y_pred=data_test_fcst['yhat'])MAE = mean_absolute_error(y_true=data_test['y'],
y_pred=data_test_fcst['yhat'])MAPE = mean_absolute_percentage_error(y_true=data_test['y'],
y_pred=data_test_fcst['yhat'])print ('MSE :',MSE)
print ('MAE :',MAE)
print ('MAEP', MAPE, '%')
平均误差:169.3955
平均误差:9.9056
MAEP: 167.5118%
ax = data_test_fcst.set_index('ds')['yhat'].plot(figsize=(15, 5), lw=0, style='.')
data_test['y'].plot(ax=ax, style='x', lw=3, alpha=0.1)plt.legend(['Forecast','Actual'])
plt.title('Forecast vs Actuals')plt.show()
正如你所看到的,167%的 MAPE 是完全不能接受的,我们必须尝试其他季节。请记住,要将数据更改为新的季节,您必须更改“time eason”变量(即:timeseason = ' 1min ')。其他 5 个的结果如下所示。
我们得到了 1440 分钟时间(1 天)的更好的结果,是 121%,我们知道这仍然是不可接受的。因此,让我们为此清理数据。
季节性 1 天的清洁数据
清除突出显示的坏数据(在图中用红点表示)
ax = data_train.plot(style='.', figsize=(15,5), color=['#6387c2'],
title='French tweets dataset with bad data highlighted',
xlim=('03-9-2020','04-6-2020')
)data_train.query('y > 40000').plot(style='.', figsize=(15,5), color=['#eb6b26'], ax=ax)ax.legend().set_visible(False)
plt.show()
我们想要创建新的训练数据,所以我们暂时更改数据索引名称:
data_train = data_train.rename(columns = {'y':'freq'})data_train.index.name = 'Datetime'data_train.head()
# Clean Data on freqimport numpy as npdata_train['data_clean'] = data_train['freq']data_train.loc[data_train['freq'] > 30000, 'data_clean'] = np.nan# Train model on clean datamodel = Prophet()model.fit(data_train.reset_index() \.rename(columns={'Datetime':'ds','data_clean':'y'}))# Predict on training set with clean modeldata_test_fcst_clean = model.predict(df=data_test.reset_index() \.rename(columns={'Datetime':'ds'}))
定义已清理数据的错误指标
mse_clean = mean_squared_error(y_true=data_test['y'],
y_pred=data_test_fcst_clean['yhat']
)mae_clean = mean_absolute_error(y_true=data_test['y'],
y_pred=data_test_fcst_clean['yhat']
)mape_clean = mean_absolute_percentage_error(y_true=data_test['y'],
y_pred=data_test_fcst_clean['yhat'])print(f'Cleaned data model has MSE {mse_clean:0.4f} - MAE {mae_clean:0.4f} - MAPE {mape_clean:0.4f}')
MSE:156554655.1105
MAE:10975.0188
MAEP:63.7044%
我们通过清理“1 天”时间序列实现了 63%。结果比未清洗的好 58%,但仍不可接受。清理数据对所有季节的影响并不相同。正如您在下图中看到的,清洁后的某些季节性结果甚至比清洁前的结果更差。
萨里玛造型:
导入库:
import warnings
import itertools
import numpy as np
from sklearn.metrics import mean_squared_error, mean_absolute_error
import matplotlib.pyplot as plt
warnings.filterwarnings("ignore")
plt.style.use('fivethirtyeight')
import pandas as pd
import statsmodels.api as smimport matplotlib
matplotlib.rcParams['axes.labelsize'] = 14
matplotlib.rcParams['xtick.labelsize'] = 12
matplotlib.rcParams['ytick.labelsize'] = 12
matplotlib.rcParams['text.color'] = 'G'
正如我们在上一节中得到的结果,1 天的季节性是最佳的。因此,我们将数据框定义为“1440 分钟”。CSV”。
df = pd.read_excel("1440min.xlsx")y.plot(figsize=(20,5))
plt.show()
使用 AIC(赤池信息标准):
AIC 比较了一组统计模型的质量,AIC 值较低的模型给出了更好的结果。正如我们所说,SARIMA 有三个参数,分别代表季节性、趋势和数据中的噪声。
因此,我们将检查可能的季节性订单,并获得最低的 AIC 值。
p = d = q = range(0, 2)pdq = list(itertools.product(p, d, q))seasonal_pdq = [(x[0], x[1], x[2], 12) for x in list(itertools.product(p, d, q))]for param in pdq:for param_seasonal in seasonal_pdq:model = sm.tsa.statespace.SARIMAX(y,order=param,seasonal_order=param_seasonal,enforce_stationarity=False,enforce_invertibility=False)results = model.fit()
…
ARIMA(1,1,1)x(0,1,1,12)12—AIC:717.3527391232792
ARIMA(1,1,1)x(1,0,0,12)12—AIC:961.0509395792214
ARIMA(1,1,1)x(1,0,1,12)12—AIC:939.8989814
根据结果,718.9785 是 ARIMA 模型的最优 AIC 值,那么我们将我们的季节顺序设置为(1,1,1)x(1,1,1,12):
model = sm.tsa.statespace.SARIMAX(y,order=(0, 1, 1),seasonal_order=(1, 1, 1, 12),enforce_stationarity=False,enforce_invertibility=False)results = mod.fit()print(results.summary().tables[1])
现在通过回归诊断图,您可以看到回归模型拟合数据的花费:
results.plot_diagnostics(figsize=(18, 8))plt.show()
在测试集上将实际数据(y)与预测进行比较:
pred = results.get_prediction(start=pd.to_datetime('2020-3-31'), dynamic=True)pred_ci = pred.conf_int()ax = y['2020':].plot(label='observed')pred.predicted_mean.plot(ax=ax, label='Forecast', alpha=.7, figsize=(14, 4))ax.fill_between(pred_ci.index,pred_ci.iloc[:, 0],pred_ci.iloc[:, 1], color='K', alpha=.2)ax.set_xlabel('Date')ax.set_ylabel('Tweets volume per 1 day')plt.legend()plt.show()
定义误差指标
def mean_absolute_percentage_error(y_true, y_pred):y_true, y_pred = np.array(y_true), np.array(y_pred)return np.mean(np.abs((y_true - y_pred) / y_true)) * 100 MSE = mean_squared_error(y_true=y['2020-3-31':],y_pred=pred.predicted_mean)MAE = mean_absolute_error(y_true=y['2020-3-31':],y_pred=pred.predicted_mean)MAPE = mean_absolute_percentage_error(y_true=y['2020-3-31':],y_pred=pred.predicted_mean)print ('MSE :',MSE)print ('MAE :',MAE)print ('MAEP', MAPE, '%')y_pred = pred.predicted_mean ;y_true = y['2020-3-31':]
MSE:28827140.1939
MAE:4145.2211
MAEP:19.6832%
恭喜,我们得到了 19.68 %的平均绝对误差百分比,这是可以接受的,这是约 44%低于先知的最好结果,由清洗数据。
它对我们的基本面分析有帮助吗?
答案是否定的,如果你看看时间线,你会发现在 3 月 16 日,频率已经跃升。原因是法国政府已经宣布全面隔离,但我们简单的 SARIMA 模型无法预测这种类型的时间序列数据变化。可以帮助我们的是使用 NLP N-gram 模型(未来的工作)。
预测未来两周:
pred_uc = results.get_forecast(steps=14)pred_ci = pred_uc.conf_int()ax = y.plot(label='observed', figsize=(14, 4))pred_uc.predicted_mean.plot(ax=ax, label='Forecast')ax.fill_between(pred_ci.index,pred_ci.iloc[:, 0],pred_ci.iloc[:, 1], color='k', alpha=.25)ax.set_xlabel('Date')ax.set_ylabel('Sales')plt.legend()plt.show()
结论:
我们想回答“twitter 数据上时间序列预测的最佳季节性是什么?”首先,在使用 FB-prophet 时,假设更多的数据给我们更好的结果,我们选择 1 分钟的季节性,然后发现最佳的时间序列是 1 天。我们通过删除坏的亮点来清理数据,并在 1 天序列中获得更好的结果,并且理解这不会对其他季节产生相同的影响。然后,我们尝试通过使用 AIC 选择最佳订单来创建一个 SARIMA 模型,并获得 19%的 MAPE,这是一个可接受的结果。
未来作品:
尝试其他清洁方法
使用 XG-boost 最小化 MAPE
使用 N-gram 模型预测文本内容基本时间序列
参考文献:
[1] C.McClellan,M.Ali,R.Mutter,L.Kroutil,J.Landwehr,使用社交媒体监控心理健康讨论——来自 Twitter 的证据 (2017),美国医学信息学协会杂志
[2] S.Prabhakaran ,machinelearningplus.com ARIMA 模型 Python 中时间序列预测完全指南
[3] R.Larrosa,如何使用萨里玛模型使用 Python 预测销售额【towardsdatascience.com (2019)
[4] R.Mulla,利用脸书的预言家进行逐时时间序列预测 (2020),kaggle.com
用神经网络预测能源需求
变革的数据
我们如何通过使用 XGBoost 的广泛文献综述、特征工程和特征选择,赢得了一个简单神经网络的数据
作者: 蔡美儿【李】林敏【Htoo】奎月咏家 ,所有NTU新加坡留学生。****
本文总结了我们用来赢得由新加坡南洋理工大学& ai4impact 联合举办的深度学习数据大会的方法。如有任何疑问,请通过 LinkedIn 联系我们。
这是我们文章的大纲:
- 介绍
- 目标和成功的衡量标准
- 探索性数据分析
- 数据清理
- 研究方法
- 将一维时间转换为二维时间
- 开窗术
- XGBoost SHAP 要素重要性值
- 结果和讨论:特点
- 结果和讨论:模型
- 我们模型的优点和缺点
- 关于可解释机器学习的一个注记
- 结论
介绍
将电能消耗与正确的供应水平相匹配是至关重要的,因为过量供应的电力无法储存,除非转换为其他形式,这会导致额外的成本和资源。与此同时,低估能源消耗可能是致命的,过度需求会使供应线超载,甚至导致停电。显然,密切监控建筑物的能源消耗会带来实实在在的好处——无论是办公室、商业还是家庭。
随着机器学习的出现,准确预测未来的能源消耗变得越来越可能。准确的预测提供了双重好处:首先,管理人员获得了对影响其建筑能源需求的因素的关键见解,提供了解决这些问题和提高能源效率的机会。其次,预测提供了一个基准,以挑出异常高/低的能耗,并提醒管理人员建筑物内的故障。
然而,困难在于实时能量使用的非线性和波动性,其极易受外部因素变化的影响。例如,众所周知,环境温度会通过供暖和空调显著影响建筑物的能源需求[1]。此外,由于设备故障、电源故障或难以解释的简单随机波动,可能会出现能源消耗的意外激增和下降。
目标和成功的衡量标准
我们的任务是根据从 2014 年 7 月到 2016 年 5 月每隔 15 分钟提供的 2 年历史能源需求数据,提前 1 天预测建筑物的能源消耗。此外,我们还获得了距离建筑物不同(未披露)距离的 4 个位置的温度数据,顺序为 wx1(最近)、wx2、wx3 和 wx4(最远)。我们使用了一个简单的人工神经网络(ANN,又名多层感知器),因为它能够捕捉不同数字数据之间复杂的非线性关系,与长短期记忆网络(LSTMs)等更复杂的架构相比,它的构建和训练速度相对较快。
我们使用两个指标来评估我们的模型:均方误差(MSE)和滞后。均方误差衡量误差平方的平均值:
因此,我们使用 MSE 损失来优化我们的人工神经网络。MSE 的优势在于,由于它的平方性质,它惩罚了较大的误差,降低了我们的模型做出极端预测的可能性,这种预测将是昂贵的,甚至是危险的。最低限度,我们的模型必须实现比持久性更低的 MSE,持久性是一个微不足道的基准预测,其中“提前 1 天预测的未来值=观察到的现值”。由于能量消耗的高度周期性,持久性是一个很好的起点[2]。
至于滞后,我们的目标是我们的预测和实际能耗值之间的峰值滞后为 0,平均而言,我们的模型在预测中不会延迟,并且可以及时捕捉能耗的变化。
我们解决这个问题的工作流程包括:
- 广泛的文献综述、数据可视化和分析
- Python 中的预处理、数据清理和要素工程
- 将数据导出到 AutoCaffe 以训练和评估神经网络。
我们方法的视频摘要可在:https://www.youtube.com/watch?v=dTUU9urBUoE获得
探索性数据分析
由于给定的数据集是用最小上下文匿名的,我们首先仔细检查它以获得有效特征工程的全面直觉。可以说,这是任何机器学习项目中最重要的一步,作为“垃圾进,垃圾出”的坚定信徒,我们在这上面花了将近整整一周的时间。我们发现能量和温度数据都包含大量的缺失值,因此需要一种有效的方法来填充这些值。进一步说,wx4 的数据非常稀疏(只包含 2016 年的数据),所以我们不太可能利用它。
首先,我们绘制了 2015 年的能源数据,这是数据最完整的一年,不同于 2014 年和 2016 年。月平均值被叠加,以提供跨月趋势的更清晰概览。
图 1:2015 年能源消耗(红色)和温度(蓝色)的时间序列。使用 Wx3 是因为它与能耗数据的相关性最高。
如图所示,建筑物周围的温度范围从零下到 30 摄氏度;鉴于 12 月至 2 月为寒冷月份,6 月至 8 月为温暖月份,该建筑应来自纬度> 30°的北半球。有趣的是,能源消耗存在两个局部最大值,出现在温度的两个尾端:一次在最冷的月份,另一次在最热的月份(7 月),这表明空调和供暖是能源需求的重要驱动因素。在这一年中,我们发现了 3 种不同的能源温度体系:
****冬季,12 月至 2 月:能量波动频繁且较大,平均消耗相对较大。气温一般在 10℃以下。
****夏季:6 月至 8 月:与冬季相比,频繁但较小的能量变化,随着温度稳步增加。温度一般在 20℃以上。
****过渡期:3 月至 5 月&9 月至 11 月:相对恒定稳定的能源消耗。温度范围从 10 到 20 摄氏度。
该分析启发了两个虚拟变量(值 1 代表真或 0 代表假):1)is _ season _ winter & 2)is _ season _ transition,以促进神经网络的更好学习。请注意,每当 is_winter 和 is_summer 列都为 0 (False)时,is_summer 列的值将为 1(True);因此,我们删除了 is_summer 列,以避免虚拟变量陷阱[3],其中一个变量可以从一个或多个其他变量直接推断出来,从而导致多重共线性问题。
接下来,我们绘制了整个时间段的能源消耗时间序列。
图 2:能源消耗的年度趋势。从 2014 年 7 月到 2014 年 10 月异常低的能耗值引人注目
我们意识到 2014 年 7 月至 10 月的能耗异常低。可能有各种各样的原因:建筑物可能是新建的,正在缓慢加速运行(因此不是满负荷)或正在进行维护。虽然通常不鼓励丢弃数据,但我们决定在这里这样做,因为异常数据显然会对我们依赖历史数据进行预测的模型造成更大的伤害。因此,我们的能源数据从 2014 年 10 月 29 日开始。通过 70/30 的训练/测试分割,我们的测试数据从 2015 年 12 月 7 日开始,训练集涵盖了全年的数据,这足以将我们的模型暴露给全年的所有季节。
然后我们将一周中不同日子的能量消耗可视化。我们计算了全年一周中每一天的平均、最高和最低消费,首先不包括公共假日。
图 3:2015 年每周每天的平均、最大和最小能耗值。请注意周末的能耗是如何降低的。
我们观察到,周末的能耗明显较低,这意味着该建筑可能是一座办公楼——工作日繁忙,周末空置,而不是购物中心或图书馆。为了利用这种模式,我们创建了一个虚拟变量,名为 is_weekend,用于判断预测的日期是否是周末。
接下来,我们绘制了每个月的能源消耗分布图,分为工作日、周末和公共假日。
图 4:不同月份基于一天类型的能源消耗分布。这为我们提供了特征工程和填充缺失数据的定制方法的思路。
首先,工作日的能源消耗明显高于周末和一般公共假日。第二,虽然周末有大量异常高的能源需求,但周末和公共假日的能源消耗的总体分布非常相似。这意味着我们应该将前一个周末/公共假日(以较接近者为准)的能源消耗插入一个工作日公共假日。
接下来,我们仔细研究了日常消费模式。
图 5:7 月份的日常能源消耗。
一般来说,在工作日,能源消耗在早上 7 点急剧上升,在下午 6 点之后急剧下降,这很可能是该建筑的标准工作时间。请注意,由于缺少值,一些图看起来形状奇怪,这进一步说明了填补这些空白的必要性。放大到特定的一天,我们发现,平均来说,在下午 12 点左右,能源消耗有明显的下降,我们将这归因于办公室午餐时间。
图 6:对每日趋势的进一步分析表明,通常在中午 12 点出现局部能量消耗最小值,我们将其归因于午餐时间。
因此,我们决定引入虚拟变量:is _ 午餐时间(当非公共假日工作日的时间= 12 时)和 is _ 工作时间(非公共假日工作日的上午 7 点到下午 6 点)。
接下来,我们绘制了能源消耗的自相关图,以识别由统计分析支持的循环模式,而不是“瞎猜”。
图 7:672 个时间步长(1 周)的能耗自相关图。请注意,峰值出现的时间间隔为 96 (24 小时)。
图 8 2880 个时间步长(1 个月)的能耗自相关图。请注意,672 时间步长比 96 时间步长具有更强的自相关系数。
由于数据是以 15 分钟为间隔给出的,因此相隔 24 小时对应于 96 个时间步长,12 小时对应于 48 个时间步长,依此类推。每天某个特定时间的能量消耗与前一天的同一时间最密切相关。这种关系随着天数的增加而减弱,但在 672 个时间步长或相隔 1 周时再次达到峰值,这实际上比相隔 1 天具有更强的相关性。另一方面,自相关在相隔 12 小时时最弱。这向我们暗示了强预测特征可以包括 T:-576(从当前时间起 6 天前,但是从被预测的时间起 1 周前),T:0(从被预测的时间起 1 天前)和 T:-96(从被预测的时间起 2 天前)。
接下来,我们深入研究了能源需求和温度之间的关系,并受 Valor 等人 2001 年[1]的启发,尝试拟合多项式趋势。
图 9:从散点图可以看出,能耗和温度之间的关系是非线性的。
虽然最佳拟合线显然不是理想的,但散点图仍然揭示了有用的见解。在温度的末端(太热或太冷),能源消耗往往会上升,很可能是由于空调或供暖分别增加。此外,这种关系不太可能是纯线性的,显示出在大约 19°c 的温度下“最舒适”的二次曲线。为了进一步探索这一点,我们使用 Python Seaborn 库制作了一个关联热图,将数据分为冬季、夏季和过渡月份。
图 10:温度和温度平方与能耗的相关热图
首先,我们观察到 wx3 在所有时期(0.29 比 0.24)、冬季(0.051 比 0.0079 & 0.016)和过渡月份(0.17 比 0.11)具有明显更高的绝对相关值。夏季略低于 wx1 和 wx2(0.43 vs 0.46)。这也通过对 XGBoost 中特征重要性值的初步研究得到了证实,该研究始终将 wx3 排在 T+96,高于 wx1 或 wx2。因此,我们着重于为 wx3 以外的温度创建窗口特征。
接下来,在夏季(对于所有 3 种温度)和冬季(对于 wx3),二次关系似乎略微优于具有更高绝对相关值的线性关系。因此,除了原始能量值之外,T+96(预测时间)时 wx3 的平方值可能是一个值得考虑的有用特性。
最后,在冬季,原始温度和平方温度与能量的相关性都很差。一个原因可能是,在冬天,建筑物的供暖系统可能会无限期地保持在一个固定的水平,而不管温度的大幅波动。
数据清理
我们用 Python 而不是 AutoCaffe 进行数据预处理,因为我们的团队比 Smojo 更精通 Python 库,并且我们想要更多的控制来创建特定的功能,如虚拟变量。预处理管道的大致轮廓包括将温度数据与 15 分钟间隔对齐、插值和归一化。
从 2014 年 10 月 29 日 00:00:00 到 2016 年 5 月 26 日 20:15:00,大约 17%的能源数据集丢失。我们首先尝试线性插值,但我们意识到这会导致数据泄漏,因为计算平均值涉及未来的数据(在丢失时间戳之后)。我们还注意到,缺失值通常出现在长达两天的整个时间段内,在这种情况下,由于温度和工作时间等因素,线性插值无法捕捉能源需求的内在季节性。然后我们尝试简单的向前填充,用正好 24 小时前的数据替换丢失的数据。然而,这并没有很好地反映每周的趋势,因为工作日和周末/公共假日之间存在差异。
因此,我们实现了一种定制的填充方法,考虑了一天的类型(公共假日/周末/工作日)。如果缺失值日不是公共假日,缺失值将被恰好一周前的值替换(假设这也没有缺失!幸运的是在这个数据集中没有发生)。否则,如果缺少的值日是公共假日,它将被最接近的前一个周末值替换。
****
图 11:上图:比较线性插值和我们自己定制的数据填充方法。下图:填充能量数据的放大示例。
这种方法更准确地反映了季节性,与更复杂的方法相比,相对容易实施。我们确实考虑了两个改进:
- 不是精确地复制,而是通过将那天的所有能量值乘以一个小的随机因子,比如 0.8 到 1.2 之间的因子,将一个随机的“抖动”添加到被提出的值中。只要为随机因子选择了合适的范围,这种方法就减少了我们的模型过度拟合历史数据的机会。这种随机抖动只会应用于训练数据集,而不会应用于测试集。然而,由于我们没有面临大规模的过度拟合问题,我们没有实施这一想法。
- 拟合神经网络或时间序列预测算法,该算法也考虑温度数据来估算缺失值,因为它可能会给出更真实的结果。然而,考虑到比赛的时间限制,我们认为这使任务过于复杂。
至于温度,我们从天气预报中得到了未来 24 小时的数据。我们选择线性插值,因为数据间隙持续不到一小时,所以它仍然可以很好地捕捉趋势(图 12)。其次,由于我们得到了未来的数据,数据泄露不是问题。没有对 wx4 进行插值,因为它太稀疏。
****
图 12:上图:线性插值前的温度数据。下图:线性插值后。对于温度,由于数据间隙稀疏,我们可以使用线性插值来产生合理的结果
我们使用“最小最大比例”将所有能量和温度数据归一化到范围[0,1]。所有特征输入的这种标准化对于神经网络来说是至关重要的,以确保特征重要性的任何差异仅仅是由于特征本身而不是其数值大小。我们还注意从训练数据中提取最小/最大值,以防止测试集中的数据泄露。
将一维时间转换为二维时间
在我们的文献综述中,我们发现了一种创造性的时间数据操作方法:Moon 等人 2019 [2]将日历时间转换为 2d 连续格式。虽然像月和日这样的日历数据具有周期性属性,但是用顺序数据表示它们会失去一些周期性。例如,0000 小时紧跟在 2359 小时之后,但从数字上看,它们相距甚远。因此,Moon 等人[2]利用了以下等式(EoM =月末,即该月的天数):
****
图 13:上图:将 1d 时间转换为 2d 时间的方程式。左图:时间的一维顺序表示。请注意,尽管 12 月(第 12 个月)在 1 月(第 1 个月)之后,但数值差距 11 并不反映这种周期性。右图:时间的二维变换。注意它是如何恢复月份的周期性的,十二月正好是一月的邻居。
当我们使用 2d 时间时,我们的测试损耗性能至少提高了 2.5%到 4%。
我们想要探索的另一个有趣的特征是 Valor 等人 2001 年提出的“公共假日/周末惯性”。他们发现,由于非工作日经济活动减少造成的惯性,在周末(即周一)或公共假期后的工作日,办公楼的能源消耗系统地较低。利用这一点的特征可以是“自上次公共假期以来的天数”和“自上周末以来的天数”。然而,仔细分析我们的数据表明,这种“惯性”效应并不存在,我们没有进一步研究。
研究方法
我们生成最佳可能模型的方法包括在 AutoCaffe 中训练模型,并根据测试分数和达到的延迟逐一添加特性。然而,虽然 AutoCaffe 允许快速训练,但有一个限制是我们不能“自动”排列特征,必须手动进行。为了最大限度地减少重复排列特征所花费的时间,我们依靠数据分析、领域知识、广泛的特征工程和 XGboost SHAP 特征重要性值来减少要检查的特征组合。
一个很大的假设是,功能是相互独立的,只有最小的功能交互。考虑到这种假设不太可能总是成立,我们还根据我们的直觉和从阅读科学文献中获得的领域知识,运行了某些功能组合。我们还小心翼翼地进行了充分的重复,以减少由于随机重量初始化导致的最终测试损失的差异。
开窗术
为了进行初步调查,我们准备了一个 Pandas dataframe,其中包含能量、温度(wx1 到 wx3)、日期时间特征(如月、日)和窗口特征(如最小值、最大值、平均值、范围、一阶差、一阶差的平均值、二阶差等)的原始值。
良好的窗口对于帮助我们的人工神经网络更好地对数据进行聚类至关重要。我们选择窗户是基于我们对能源消耗循环模式的理解:
- 1 小时的小窗口(例如 T:0:-4 平均值)捕捉最近的能量波动
- 稍大的 5 小时窗口,用于捕捉全天的较大变化
- 更大的 12 小时窗口,用于捕捉昼夜循环模式
- 1 天到 1 周的最大窗口,用于捕捉季节转换
我们没有使用大于 1 周的窗口,因为根据自相关图,我们认为过去太远的值可能只是噪声,更不用说给我们的输入增加额外的维度。
利用能量和 wx3 温度的窗口特征、虚拟变量和 2d 时间特征,我们在 AutoCaffe 上进行初步实验,以消除无用的特征,我们发现这些特征是“范围”、“偏斜”和“峰度”。我们希望“偏斜”和“峰度”可以向我们的模型发出信号,表明最近出现了极端值(例如,在正常温度背景下,短时间内突然出现高于正常温度的热浪),这可能会增加模型预测意外事件的稳健性。不幸的是,尽管反复实验,这些特性并没有改善我们的测试损失和滞后。关于 wx4,我们尽了最大努力来利用它,例如通过计算所有 4 个传感器的“上个月的平均温度”,但不幸的是,这些功能并没有改善我们的结果。
经过大约 150 次实验,我们生成了一个大约 130 个特征的精炼列表。
要素选择:使用 XGBoost SHAP 要素重要性值
在这个阶段,为了给我们的特征选择过程提供严格的理由,我们使用了 Python XGBoost 库,这是一个快速且用户友好的梯度增强决策树算法实现。我们选择决策树是因为它们比神经网络更擅长处理高维数据集(> 100 列特征),而神经网络由于维数灾难和不重要的输入更容易绘制出糟糕的决策边界。
我们将约 130 个特征输入到 XGBoost 回归模型中,以预测 T:0 和 T+96 能量值之间的差异(模拟 AutoCaffe 中的“差异”神经网络)。有趣的是,这个具有以下相当标准的超参数的模型实现了 0.010853 的测试 MSE(在因子 0.5 之后),这已经击败了 0.019377 的持久性 44%,尽管我们没有可视化其滞后相关性或散点图。
使用 Python SHAP 库[4,5],我们可以很容易地可视化各种特性对 XGBoost 模型输出的贡献。选择 SHAP 是因为其跨模型的一致性和准确性,这是许多重要机制所缺乏的[6],包括 XGBoost/scikit-learn 的内置版本。我们根据 SHAP 值(越高=越重要)对大约 130 个顶级功能进行了排名,并在 AutoCaffe 上进行的另一轮实验中重点关注了这些顶级功能的置换。这些顶级特征很可能有助于更好地对数据进行聚类,这些数据应该可以转移到神经网络。当然,我们知道梯度增强树和神经网络的算法存在固有的差异;SHAP 要素重要性值并不是全部,我们偶尔也会包括其他要素。
图 14:对于输入到标准 XGBoost 回归器中的大约 130 个特性,按 SHAP 值排序的顶级特性(顶级特性=最重要)。请注意,对于 wx3,T:0 实际上是指预测的时间(从 T:0 开始 24 小时后的能量),因为我们可以访问温度预测数据。请继续阅读我们的语法的简要解释。
为了阐明我们的语法,Emean _ diff 96–96:-195 是以下各项的平均值(为了减少噪声):1) E:-96 减去 E:-192 2) E:-97 减去 E:-193 … 4) E:-99 减去 E:-195。同样,Emean _ diff 48–0:-51 是以下各项的平均值:1) E:0 减去 E:-48 2) E:-1 减去 E:-49 … 4) E:-3 减去 E:-51。
对于 1week_meandiffdiff:我们首先计算七个一阶微分 Emean _ diff 96–0:-99,Emean _ diff 96–96:-195,…Emean _ diff 96–576:-675。然后,我们计算这些值之间的连续差(以获得六个二阶微分),并取其平均值以获得单个值 1week_meandiffdiff。我们可以平等地使用六个二阶微分,而不取平均值,但是我们希望最小化特征的数量,并且不希望引入太多“不重要的输入”。
结果和讨论:特点
我们最好的神经网络实现了 0.00907207 的测试损失(50 次重复)和 0 的测试滞后,以 53%的优势击败了我们的持久性 0.01937720。我们还计算了一个更现实的持久性基准,其中对下一个星期一/星期六的预测来自上一个星期一/星期六,而不是 24 小时前,因为周末和工作日的能源需求有很大不同。尽管如此,我们的测试损失以 44%的优势击败了这种“聪明”的持久性 0.0163。
我们用于差分网络的 36 个特征是(其中许多来自图 14)
- 时间特征
- 二维时间:小时,小时,日,日,月,月
- 一周中的某一天(0 =星期一,6 =星期日,按最小最大值缩放至[0,1])
3.虚拟变量:(受我们数据分析的启发)****
- 是 _ 公共场所,是 _ 工作日,是 _ 工作时间,是 _ 季节转换,是 _ 季节 _ 冬季,是 _ 午餐时间
- 请注意,我们删除了 is_weekend & is_season_summer,以避免多重共线性问题,即在同一行中,数据中一列的值可以从其他列的值中推断出来
4.能源特性:****
- T:-1 处的能量,T:0 和 T:-1 之间的一阶差,T:0 的最小值和平均值:-4,与 T:0 的一阶差的平均值:-4 (1 小时窗口)
- T:0 和 T:-20 之间的一阶差 (5 小时窗口)
- T:0 的最小值:-48,T:0 和 T 之间的一阶差:-48 (12 小时窗口)
- T 的平均值:0:-96 (1 天窗口)
- T:-96 和 T:-192 之间的一阶差 (1 天窗口)
- T 时的能量:-576,T 的最大值:0:-576 (从 T+96 开始的一周时间)
5.温度特性:****
- T+96 时的 Wx3,T+96 的 Max & Min:+92,T:+96 & T+95 之间的一阶差 (1 小时窗口)
- T+96:0 的最小值、最大值和平均值 (1 天窗口)
- T+96 的平均值和最大值:-576 (1 周窗口)
6.非线性特征****
- T+96 时 wx3 的平方
- T:0 时的能量与 T+96 时的 wx3 的乘积
在看到使用 T+96 处 wx3 的平方的改进之后,我们试验了各种其他非线性特征,T+96 处 wx3 的立方、ln(Kelvins 中 T+96 处 wx3)、T+96 处 wx3 的平方根等。T:0 时的能量与 T+96 时的 wx3 之积的概念是对二次多项式(a+b) = a + b + 2ab 的自然延伸
结果和讨论:模型
我们的最佳模式:
- 一个简单的差分网络,预测 T+96 和 T:0 之间的能耗差异,将模型预测添加到 T:0 的能耗中
- 第一层中有 32 个感知器的 4 层,逐层收缩比为 2/3(即 32、21、14、9 个感知器)
- 丢弃概率为 0,tanh 激活,10,000 次迭代,提前停止& Adam 优化器
对于大多数实验,层数保持在 3 或 4,筛选第一层感知器计数为 32、64、128,偶尔为 256,ReLU 激活用于快速训练。我们很快发现,感知器计数为 32 到 64 给出了最好的结果,并且 tanh 激活实现了较好的测试损失,尽管代价是较慢的训练。为什么 tanh 似乎比 ReLU 给出更好的结果背后的直觉可能是其额外的非线性,这对于映射能量/温度数据中的复杂关系可能是至关重要的。tanh 还避免了 ReLU 面临的一些问题,如“死亡 ReLU ”,即负激活的神经元不太可能再次变为正激活。
2 层对于最佳学习是不够的,而 5 或 6 层很快就会过度适应。SGD 优化器的控制实验给出了令人沮丧的结果。使用方形感知器、自动编码器/缩放和力/动量损失的试验并没有改善我们的结果。尽管如此,我们认为仍有机会在更多列的窗口能量/wx3 值上利用自动编码器来降低维数,同时从历史数据中提取最有用的信息。
****
图 15:训练和测试预测、散点图和滞后相关值的图表
我们模型的优点和缺点
优势:
- T=0 时的主要滞后峰值和 T=+96 时的次要滞后峰值之间的舒适间隙。零延迟意味着我们的预测没有时间延迟,这为建筑管理人员提供了一个可靠、准时的“基准”来比较他们建筑的实际能耗,其中任何不和谐的差异都可能表明,例如,建筑的供暖/制冷系统中未被注意到的故障。
- 在初冬和春季的几个月里相当不错的预测。我们的模型能够很好地预测每周的趋势,预测工作日/白天的上升和周末/晚上的下降。
- 总的来说,在整个测试期间,最少不和谐的异常预测。
弱点:
- 在冬末至初春的过渡期,我们的模型很难预测极端的能耗值,如测试预测图上的绿色方框所示,测试散点图中的两个绿色椭圆也反映了这一点。也就是说,测试数据集中大约有 16000 个点,大多数点似乎接近预测和实际之间合理的 1:1 关系。异常似乎只占总点数的相对较小的百分比。
- 不幸的是,尽管我们尽了最大努力,我们还是无法进一步降低测试损失并解决这个问题。这一时期的特点是温度和能量消耗的大幅波动,这可能是造成我们模型困难的原因。
下面是预测与实际的放大图,再次强调了我们的模型在预测初冬和春季月份的季节模式方面的优势(绿框),以及在预测 2016 年 2 月至 3 月期间的一些极值方面的不足(红框)。我们注意到,特别是在 12 月-1 月和 4 月-5 月,绿色方框显示了实际和预测图之间的良好拟合。
图 16a:绿框:良好的预测,橙框:我们的模型准确地预测了公共假日
图 16b:绿框:良好的预测,橙框:我们的模型准确地预测了公共假日
图 16c:红框:我们的模型没有正确预测峰值和谷值
仔细研究这些图表后,我们认为,也许我们的模型并不总是错的。对于我们的模型未能准确预测的峰值/谷值,它们完全有可能是异常值/意外的能量消耗行为。如果我们仔细重新检查图 16c 中的红框,这确实有一定的意义:第一个红框显示了一个周末持续的高能耗,这是不寻常的。此外,紧接着第二个盒子之后的第二个峰值落在星期六,又是一个周末。也许某些周末加班操作/工作是在冬末的几个月进行的,这不包括在我们的培训数据中。
也就是说,我们认识到,对于第二个红框,即从周三到周五的工作日,我们的模型确实未能匹配实际的峰值&预测不足。这需要进一步分析;也许在 wx3 温度和实际能量之间的相关性存在偏差。根据我们的研究,除温度之外的天气因素,如风速和湿度,会影响人类的“感觉”温度,从而影响加热/冷却的使用。因此,拥有更多数据可能有助于我们判断实际趋势是“可预测的”还是实际上是异常值。
关于可解释机器学习的一个注记
SHAP 特征值是关于数据集中存在的多种关系的极其丰富的信息源。相比之下,深入研究神经网络的“黑箱”以理解权重和偏差如何讲述不同特征的故事会更加困难。毕竟,如果我们也能够深入了解某些特征如何塑造模型的输出,而不是盲目地寻找最低的测试损失,那么对能源预测社区来说,这将更加有益,因为最终的模型可能无法转移到不同的环境中。因此,我们特意在“差异”XGBoost 回归方程上再次显示 SHAP 特征重要性图表,该回归方程正好适合我们的最佳 36 个特征。
图 15:根据输入标准 XGBoost 回归器的最佳 36 个特性的 SHAP 值排列的顶级特性。请注意,特别是对于 wx3,T:0 是预测时间(从 T:0 开始 24 小时后的能量)的温度,因为我们可以访问温度预测数据。
对于工作时间来说,存在明显的分离是不足为奇的,在预测的时间内,高值(即=1)会增加能耗,而低值(即=0)会减少能耗。尽管如此,一系列预测的出现暗示了工作时间正在与其他特征相互作用。类似地,对于 dayofweek(周一= 0 到周日= 6 minmax 缩放到[0,1]),高值(周六和周日)往往会降低模型的输出,而低值则会增加输出。
更有趣的是,该图表明,1 天 15 分钟前(ET:-1)的高能量消耗值更有可能导致现在的能量消耗降低,反之亦然(尽管反之的幅度要低得多)。此外,对于 ET:-1 的高值,我们从-0.25 到~ 0.25 的模型输出方差中看到特征相互作用的暗示。此外,过去一周从 T+96(Emax _ 0 到 576)的高最大能耗往往会略微增加模型的输出,而低值的影响很小。至于温度,图表暗示移动周平均温度的低值(wx3 mean _-0 到-672)可以增加和减少模型的输出,而高值似乎没有影响。这些现象的原因尚不清楚,可以进行后续研究来进一步研究。话虽如此,我们必须注意,虽然 SHAP 值可以表明特征&模型输出之间的高度相关性,但它们并不意味着因果关系。
结论
总之,我们已经建立了一个相对准确的神经网络模型来预测建筑物 1 天的能耗,该模型基于大约一年的历史能源数据以及直到前一天的温度预测进行训练。
人工神经网络的优势包括它比传统的机器学习方法有明显的性能提升。然而,这种性能提升的代价是需要大量的数据(维数灾难),因此计算成本在时间和金钱方面都会变得很高。人工神经网络如何学习的内部工作仍然是一个“黑盒”,我们必须使用额外的包,如 SHAP 值,以间接探索相对特征重要性值。
必须注意的是,这个项目的结果是一个“验证”损失,因为我们已经使用了测试损失值来改变我们的特征组合和改进我们的模型。鉴于我们拥有的数据有限,我们没有验证集的特权,只能依赖测试损失作为代理。考虑到我们已经进行了数百次实验,这可能导致了验证集的细微过度拟合。因此,理想的做法是在同一栋建筑的未知能源数据集上再次评估我们的模型,以便对其预测能力进行更公正的估计。
虽然我们希望我们的发现适用于其他情况,但建筑的类型及其气候应该始终被考虑在内。同样的趋势可能不适用于住宅建筑或购物中心,或位于像新加坡这样缺乏明显季节的赤道气候中的办公楼。我们还应该注意气候变化,这可能导致历史上罕见的温度(和温度变化模式),并可能给严重依赖历史数据的模型带来问题。
总的来说,我们从这种端到端的体验中学到了很多东西,从在构建预处理、特征工程和窗口管道中锻炼我们的面向对象 Python 编程技能,通过广泛的可视化和文献综述强化我们的数据和统计直觉,到理解不同机器学习方法背后的警告,并根据算法的结果做出谨慎的决定。我们在比赛中集思广益,想出了很多主意(包括为冬季、过渡季节和夏季设计不同的模型),但我们只有这么多时间(和数据)来尝试所有的想法。
最后,我们要感谢 ai4impact 和曹组织了这次有趣而宝贵的机会!
在 LinkedIn 上与我们联系!
参考资料:
1.Valor,e .,Meneu,v .,& Caselles,v .西班牙每日气温和电力负荷(2001 年)。应用气象学报, 40 (8),1413–1421。https://doi . org/10.1175/1520-0450 2.0.CO;2 。
2.Moon,j .,Park,s .,Rho,s .,& Hwang,e .建筑能耗预测人工神经网络架构的比较分析(2019 年)。国际分布式传感器网络杂志, 15 (9),1550147719877616。https://doi.org/10.1177/1550147719877616
3.Saurav,a .虚拟变量陷阱(2019 年)。https://medium . com/datadriveninvestor/dummy-variable-trap-c6d4a 387 F10 a
4.Lundberg,S. M .、Erion,g .、Chen,h .、DeGrave,a .、Prutkin,J. M .、Nair,b . …& Lee,S. I .,《用可解释的人工智能从局部解释到全球理解树木》(2020 年)。自然机器智能, 2 (1),2522–5839。https://doi.org/10.1038/s42256-019-0138-9
**5.Lundberg,S. M .,Nair,b .,Vavilala,M. S .,Horibe,m .,Eisses,M. J .,Adams,t .,… & Lee,S. I .关于预防手术期间低氧血症的可解释的机器学习预测(2018)。自然生物医学工程, 2 (10),749–760。【https://doi.org/10.1038/s41551-018-0304-0 **
6.a . am jad . XG boost(2019)中“特性重要性”的多面性。https://towards data science . com/to wards data science . com/to wards data science/
预测食物需求
神经网络在餐包行业中的应用
所以这将是过度拟合。
时间序列问题通常与过度拟合作斗争。这整个练习变得更具挑战性,看我如何能防止时间序列预测中的过度拟合。
我添加了重量衰减和脱落。这将有助于防止过度拟合。网络有分类变量的嵌入层(我改变了大小),接着是丢弃和批量标准化(对于连续变量)。
根据这篇文章的说法理想情况下,你想要更低的脱落量和更大的体重衰减量。
资料组
数据由一家餐包公司给出。由于食物容易腐烂,计划和需求预测极其重要。
弄错了这一点可能会给一家餐盒公司带来灾难。补充通常每周进行一次。我们需要预测未来 10 周的需求。
预处理
多亏了 Fastai,标准化、填充缺失值和编码分类变量现在是一个相对简单的过程。
接下来,我们将为每个分类变量创建嵌入。问题是,每个分类嵌入应该有多大?Fastai 有一个很好的经验法则,其中分类嵌入由以下公式给出:
cardinality = len(df[cat_vars[0]].value_counts().index)
emb_size = min(50, cardinality//2)
这意味着嵌入的大小将是分类变量中唯一值的数量除以 2 并向下舍入。也可能是 50。哪个最小。
我们最终的嵌入大小字典如下所示
emb_szs = {cat_vars[i]:min(len(df[cat_vars[i]].value_counts().index)//2, min_size) for i in range(1, len(cat_vars))}
{‘Day’: 15,
‘Dayofweek’: 0,
‘Dayofyear’: 50,
‘Is_month_end’: 1,
‘Is_month_start’: 1,
‘Is_quarter_end’: 1,
‘Is_quarter_start’: 1,
‘Is_year_end’: 1,
‘Is_year_start’: 1,
‘Month’: 6,
‘Week’: 26,
‘Year’: 1,
‘category’: 7,
‘center_id’: 38,
‘center_type’: 1,
‘city_code’: 25,
‘cuisine’: 2,
‘email_plus_homepage’: 1,
‘emailer_for_promotion’: 1,
‘homepage_featured’: 1,
‘meal_id’: 25,
‘op_area’: 15,
‘region_code’: 4}
我们需要调整我们的模型架构。这总是最难的部分。几篇文章强调了获得正确的模型架构的重要性。在许多方面,这可以被视为“新”特征工程。
由 Leslie Smith 撰写的这篇论文提出了一种有趣的方法,以一种更加规范的方式来选择超参数。我将从这个 kaggle 内核建模实现。
我们需要找到最优的学习速率、权重衰减和嵌入丢失。根据 Leslie Smith 的说法,为了选择最佳的超参数,我们需要针对一些不同的权重衰减和下降值运行学习率查找器。然后,我们选择具有最低损失、最高学习速率(在快速增加之前)和最高重量衰减的最大组合。
那要考虑很多。此外,还有几个我们没有考虑的超参数。为此,我将借用具有相对较大的层的模型架构。这款车型曾在罗斯曼·卡格尔比赛中获得第三名。
最后,我需要考虑批量大小。根据 Leslie 的说法,这应该设置得尽可能高,以适应所有可用的内存。我非常乐意做那件事。这大大减少了我的训练时间。
我使用 Fastai 中的学习率查找器来可视化我们改变模型架构时的损失。从那里,我创建了一个基本的网格搜索。我不想实现疯狂的深度网格搜索——那将是计算开销很大的。我认为最好的方法是手动操作。
一旦我们描绘出模型架构的所有不同组合,事情就会变得更加清晰。
作者图片
如果我们选择重量衰减为零的模型架构,损耗峰值会更早出现。从选项中,“0.6”的权重衰减允许我们以最低的损失训练合理的高学习率。
虽然与最低损失水平相对应的学习率在 1e-1 区域,但我不会使用该学习率。相反,我将为学习率选择 1e-2 值。这是爆炸的安全值。这已经显示有助于训练。
这是我们的最终模型:
learn = get_learner(emb_szs=emb_szs, layers = [1000,500], ps = [0.2,0.4], emb_drop = 0.04)
TabularModel(
(embeds): ModuleList(
(0): Embedding(146, 26)
(1): Embedding(78, 38)
(2): Embedding(52, 25)
(3): Embedding(3, 1)
(4): Embedding(3, 1)
(5): Embedding(15, 7)
(6): Embedding(5, 2)
(7): Embedding(52, 25)
(8): Embedding(9, 4)
(9): Embedding(4, 1)
(10): Embedding(31, 15)
(11): Embedding(4, 1)
(12): Embedding(13, 6)
(13): Embedding(53, 26)
(14): Embedding(32, 15)
(15): Embedding(2, 0)
(16): Embedding(146, 50)
(17): Embedding(3, 1)
(18): Embedding(3, 1)
(19): Embedding(3, 1)
(20): Embedding(3, 1)
(21): Embedding(3, 1)
(22): Embedding(3, 1)
(23): Embedding(4, 1)
)
(emb_drop): Dropout(p=0.04, inplace=False)
(bn_cont): BatchNorm1d(6, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(layers): Sequential(
(0): Linear(in_features=256, out_features=1000, bias=True)
(1): ReLU(inplace=True)
(2): BatchNorm1d(1000, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(3): Dropout(p=0.2, inplace=False)
(4): Linear(in_features=1000, out_features=500, bias=True)
(5): ReLU(inplace=True)
(6): BatchNorm1d(500, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(7): Dropout(p=0.4, inplace=False)
(8): Linear(in_features=500, out_features=1, bias=True)
)
)
我将在这里使用学习率退火。这是显示工作良好。
作者图片
作者图片
我将继续拟合更多的周期,直到验证开始增加。我将在拟合几个纪元后保存模型。这样我就可以在以后的推理中使用最好的模型。
作者图片
作者图片
我能得到的最好结果是大约 0.29 的确认损失(四舍五入)。
与马丁·阿拉克伦的文章类似。我想将神经网络的性能与更传统的方法进行比较。
其他方法
XGBoost、随机森林回归器和 LightGBM。相对于神经网络,它们的表现如何?
我将使用或多或少与神经网络相同的数据。Fastai 已经内置了优秀的预处理方法。
然而,Fastai 的分类编码有点奇怪。Fastai 从分类值到它们的编码值创建一个字典。在推断时间,分类值被编码值交换。
这很聪明,也很有用。但这使得在 Fastai 生态系统之外的模型中使用 Fastai 预处理数据有点困难。
为了解决这个问题,我创建了一个简单的脚本,将 Fastai 表格数据束转换成可以提供给另一个模型的数据。
# inspired by [https://www.martinalarcon.org/2018-12-31-b-water-pumps/](https://www.martinalarcon.org/2018-12-31-b-water-pumps/)
class convert_tabular_learner_to_df():def __init__(self, cat_names, tabular_data_bunch):
self.cat_names = cat_names
self.tabular_data_bunch = tabular_data_bunchdef driver(self):# convert tabular data to dataframe
X_train, y_train = self.list_to_df(self.tabular_data_bunch.train_ds)
X_valid, y_valid = self.list_to_df(self.tabular_data_bunch.valid_ds)# label encode data
encoder = BinaryEncoder(cols = self.cat_names)
X_train = encoder.fit_transform(X_train)
X_valid = encoder.transform(X_valid)return X_train, X_valid, y_train, y_validdef list_to_df(self, tabular_learner):# create X df
x_vals = np.concatenate([tabular_learner.x.codes, tabular_learner.x.conts], axis=1)
cols = tabular_learner.x.cat_names + tabular_learner.x.cont_names
x_df = pd.DataFrame(data=x_vals, columns=cols)# reorder cols
x_df = x_df[[c for c in tabular_learner.inner_df.columns if c in cols]]# create y labels
cols = [i.obj for i in tabular_learner.y]
y_vals = np.array(cols, dtype=”float64")return x_df, y_vals
现在,我们将对数据进行一系列回归分析。每个都使用默认值。我想知道神经网络相对于回归的标准方法表现如何。好点了吗?更糟?
现在看结果。
作者图片
在这种情况下,似乎其他模型优于神经网络。尽管如此,具有类别嵌入的深度学习模型在 Kaggle 上非常受欢迎。我可能需要改变我使用的下降量和体重衰减量。但目前,就 RMSPE 而言,RandomForestRegressor 是最好的模型。
丰富
1.模型架构。我想改变更多的超参数,同时避免昂贵的网格搜索。这可能是进一步改进模型的唯一最有用的事情。
Fastai 明确警告您不要减少参数,以免过度拟合。相反,使用辍学和体重衰减宽松。
我已经尝试过了。但最终还是稍微超配了一下。改变超参数可能有助于进一步减少过度拟合。
具体来说,我可能会受益于不同的辍学。我想改变嵌入层的漏失,更重要的是漏失的概率。
本文讲述了大型深度神经网络中的辍学效应。也许加深网络和更自由地应用 dropout 可以提高性能?
网格搜索可以随机实现。这叫做随机搜索。我可以潜在地使用 skorch 来做这件事。
2.我也想试试脸书的先知。这是一个用于时间序列预测的开源工具。我想看看它相对于这个神经网络的表现。
3.混合。在 kaggle 上的第一名解决方案使用了混合了 lightGBM 模型的神经网络。这可能是未来研究的希望。
我的 Github 上有完整的代码
原帖来自 spiyer99.github.io
用 GgPlot2 预测足球比分
使用泊松帮助可视化足球正确的分数在 R
胡闹
在我之前的一篇帖子中,我提到一场足球比赛的比分可以用泊松分布来近似计算,但我没有过多地谈论这个话题。好吧,你今天很幸运…我们将看看这个主题,在这篇文章的最后,我们将有 Ggplot2 可视化说明一场足球比赛的可能比分,这真的很棒。
首先,讲一点泊松分布的根。这种概率分布的发现归功于十九世纪的法国数学家西蒙·丹尼斯·泊松。像他同时代的许多人一样,他主要研究它的理论。直到俄罗斯统计学家 Ladislaus Bortkiewicz 于 1898 年出版了他的书《大数定律》,泊松分布才在实践中得到广泛应用。
众所周知,Bortkiewicz 获得了普鲁士军队 20 年来的一组数据,记录了被马踢死的士兵人数。冷酷无情。
总之,他证明了这些死亡可以用泊松分布来近似,剩下的,正如他们所说的,都是历史了。
现在…一个人如何从普鲁士骑兵到足球比分?
愚弄你和我
让我们先来看看满足泊松过程的基本假设:
- 事件在给定时间间隔内发生的概率不随时间变化
- 事件随机发生
- 事件独立发生
现在把进球想象成足球比赛中的一个事件。如果我们有一个指标可以表达一支球队在 90 分钟内的得分率/强度,我们可以说第一个假设得到了满足。这很难定义,但谢天谢地,体育迷们(我应该补充一句,他们比我聪明一百倍)已经为此提出了预期目标 (xG)。今天谢谢你!
下一个问题-足球比赛中进球是随机出现的吗?也就是说,在一场比赛中是否有一个特定的时间点更容易进球?这个家伙说不,许多其他的文章和研究也表明进球确实在足球比赛中随机发生。在实践中,目标可能不像人们想象的那样随机,但是…我们有足够的证据证明它们是随机的,所以让我们打勾,现在继续。
现在是最后一个假设——目标是相互独立的。如果一支球队落后,球员们肯定会更加努力地回到比赛中去,以扳平比分。或者,如果一个队已经领先 5 个球,球员可能会因为自满而放松油门,让一个人进入。无论哪种方式,你都必须说目标不是彼此独立发生的,使用基本泊松过程来模拟足球比分在这里开始失效。
有一些技术可以调整比赛中的目标依赖性,但我们都有白天的工作——所以让我们把它留到另一天……现在同意三分之二并不坏(而且,我正在努力在 it 中生成有用的内容,所以我们在这里)。为了进一步阅读,我建议看看这篇精彩的博客文章,它基本上为足球做了一个 Bortkiewicz,表明你可以用泊松分布近似一个赛季的进球数。
蹄
在我之前关于 xG 的帖子中,我创建了一个简单的泊松模型来帮助预测 r 中一场足球比赛的结果(主场胜利、平局、客场胜利)。我们将在这里使用类似的东西,但更侧重于获得正确得分的概率作为输出。
r 已经从它的基础热图库中走了很长一段路,这些热图库还不太成熟。Ggplot2 是一个神奇的软件包,它允许构建各种图形和图表。为了使用它们,我们必须首先在 RStudio 中安装一些依赖项:
*install.packages('tidyr')
install.packages('dplyr')
install.packages('scales')
install.packages('ggplot2')library('tidyr')
library('dplyr')
library('scales')
library('ggplot2')*
酷,现在让我们回到我们最初的假设之一——在一场足球比赛中,球队在 90 分钟内有恒定的得分率。我们将使用取自 FiveThirtyEight 的模型的基于镜头的 xG,用于巴塞罗那和拜仁慕尼黑之间的冠军联赛四分之一决赛(哦,天哪……)。让我们构造并获取一个ScoreGrid
:
我们创建了一个 11 列 11 行的数据框,每个条目代表一个正确的分数。因此[ 行 i ,列 j 中的条目将是得分 i,j ,其中 i 为主场得分, j 为客场得分。因此,entry [ 1,2 ]将会是客场队以 2-1 获胜。给定homeXg
和awayXg
,dpois
有助于为每个分数 i 生成随机泊松概率。最后,我们将个人得分限制在 9 分,一旦我们达到 10 分,我们将把概率加在一起,并将它们分组为一个条目。这只会让事情变得更简单。
让我们快速旋转一下。在 RStudio 控制台中,键入
*ScoreGrid(1.7,1.1)*
你应该知道这个:
足球正确得分网格。作者图片
网格不错,但不太好看。
罗伯特·莱万戈尔斯基
让我们现在建立正确的分数视觉。我们将在 Ggplot2 中使用geom_tile()
,它会在最后生成一个漂亮的热图。代码如下:
Ggplot2 要求输入数据为tidy
数据帧,因此从基数 R data.frame
的转换发生在第 10 行的pivot_longer
处。接下来,我们需要将所有的vars
转换为factors
,并按照正确的顺序对等级进行排序(记住 10+ 是一个因子,使用as.numeric
只会使它变成一个NA
)。我们希望它是列表中的最后一级)。这在第 14 行用~forcats::fct_relevel
完成。除此之外的所有内容都只包含 Ggplot2 图的常见构件。
好了,我们开始吧。启动 R 控制台,输入团队名称和 xG 输入,无论您来自哪里:
*ScoreHeatMap("Barcelona", "Bayern_Munich", 1.2, 5.6, "FiveThirtyEight")*
巴塞罗那 vs 拜仁慕尼黑正确的比分可视化。作者图片
在这场比赛中,男人对男孩,只要看看可视化/热图,你就可以看到根据 xG,拜仁慕尼黑最有可能的比分是 5-1。事实上,拜仁实际上以 8 比 2 获胜。罗伯特·莱万戈尔斯基的确。
再举一个例子来说明一场势均力敌的比赛,昨晚巴黎圣日耳曼和拜仁慕尼黑之间的冠军联赛决赛:
*ScoreHeatMap("Paris_SG", "Bayern_Munich", 1.4,1.6,"FiveThirtyEight")*
巴黎圣日耳曼 vs 拜仁慕尼黑正确比分可视化。图片作者。
一场激烈得多的比赛,1-1 是最有可能的比分,拜仁慕尼黑实际上以 1-0 获胜。
稳定的模型
和往常一样,有几个警告,其中一个我们已经讨论过了——即目标不是相互独立的,所以这个模型值得重新审视。此外,如果这些 xG 机会中的任何一个有不同的结果(即射门击中门柱或偏出而不是进入),我们可能今天就不会在这里谈论这个问题 …让我们不要忘记 xG 本身是一个有缺陷的指标,它没有捕捉到一场足球比赛中的许多细微差别。
尽管如此,这些视觉效果很好地展示了一场比赛的结果——如果有什么不同的话,这是一次很好的使用一些令人印象深刻的 R 库进行图形和可视化的练习。
和往常一样,如果我想不通的话,你可以在我的 Github 仓库里找到所有这些。为今天干杯…
其他文章
使用 Python、R 和预期目标的英超联赛 2019/20 回顾
towardsdatascience.com](/did-liverpool-deserve-to-win-the-premier-league-eda7a4e1b9ca)
足球正确比分可视化 R 码
博客文章的存储库。在 GitHub 上创建一个帐户,为我们的 andy/blog-repo 开发做出贡献。
github.com](https://github.com/ourandy/blog-repo)*
公共政策中的地理空间机器学习
实践教程
预测费城的中产阶级化,为经济适用房政策提供信息
简介
在过去的八年里,费城的房地产市场已经从衰退中复苏,并准备加速复苏。与此同时,数以千计的贫困租户努力寻找和维护价格合理的住房。负担得起的住房倡议并非没有对新住房项目的布局提出批评,特别是在新开发项目集中在低收入地区的情况下。虽然有人可能会说,在这些地区建设经济适用房项目会让租户靠近他们现有的社区,但这也会让他们远离可能的经济增长和社会流动性。
中产阶级化是街区变化的主要来源,也是理解房价随时间变化的关键。为了吸引高收入居民,公共部门努力提供更高标准的生活设施和休闲。对中产阶级化地区的关注将资金从其他低收入地区抽走。然后,这些社区会经历投资减少或社区衰落的时期。随着城市中心的扩张和周围土地价值的增加,投资不足的地区开始为未来的中产阶级化周期做准备。这一过程在费城很明显,仅从 2008 年到 2016 年就损失了 13,000 个低成本单元,而增加了 6,000 个高端单元。
很明显,随着中产阶级化正反馈循环的继续,越来越多的人因为租房合同价格过高而被迫搬迁。这种效应通过收入阶层逐级传播,从而需要更多的经济适用房。
经济适用房项目是保持经济领域公平感的一个重要因素,这些项目的位置对这一空间的形成至关重要。在目前主要由低收入或无投资地区占据的地区进行开发,可以确保那些有需要的人能够获得租金控制的住房,这种住房对开发商来说相对便宜。此外,如果该地区要中产阶级化,租金价格保持不变,而与中产阶级化相关的便利设施和机会给该地区带来了经济机会。因此,中产阶级化的预测措施将很好地指导经济适用房的安置。
数据
费城有一个强大的开放数据平台,opendatahilly,有超过 350 个来自政府组织的公共数据集可供梳理。我选择的数据集主要是基于列举整个城市的便利设施,包括公园、学校、医院、高等教育和公共交通站。此外,我收集了犯罪点的位置数据,以代表潜在房主考虑的一个常见的不利因素。还收集了 2014 年至 2020 年每个地块(建筑)的市场估值。
和往常一样,这些数据并不完美。例如,如果有过去几年公交站点扩展的可访问日志,则该模型可以将公共交通使用的增加解释为远离中心城市的地区价格发生某些变化的原因。另一个例子是,学校质量和集水区数据不包括特许学校,特许学校是费城学校景观中不断增长的一部分,将导致更准确的学校质量数据表示。尽管如此,通过一些清理,合并这些数据集创建了丰富的空间和时间数据集以进行特征化。
收集和清理数据并非易事。以下是一些在特殊化之前进入项目的数据工程工作的例子:
- 我使用了东南宾夕法尼亚交通管理局(SEPTA) API 来提取整个城市的交通可达性。然而,API 只返回离给定的经纬度坐标最近的 50 个公交站点。为了创建一个横跨整个城市的点级公交站点数据集,我以网格方式迭代查询了整个城市的坐标,每个坐标之间的距离为 0.1 英里。这给了许多副本,但彻底涵盖了费城的所有过境站。我删除了重复的点,并将结果位置修剪到城市的边界。
- 属性评估数据集详细描述了目标时间段内的宗地值和内部特征,其中有几十行的值不一致。例如,在许多情况下,房间数是 0,而卧室数是 2。在此基础上,我删除了 num_rooms 和类似的不一致列。
- 我用从属性的描述性数据中提取的值替换了一些不一致的列。数据集中的每个住宅宗地都有一个描述,包括车库的存在和建筑物在描述性文本字段中的层数。使用正则表达式,我在数据集上提取了这些信息,添加了两列,分别表示车库的存在和房间的真实数量。
- 在地产评估数据集中,宗地值的分布呈明显的右尾分布:
费城包裹市场价值直方图【作者图片】
为了缩小预测范围,我剔除了估价高于 150 万美元的地块。估价为 1 美元或 0 美元的包裹也被移除。98.5%的宗地保留在数据集中以供考虑。
快速查看每个街区的平均市场估值,可以让我们很好地了解整个城市的分布情况:
每个街区的平均价格【图片由作者提供】
从图像上看,这里有一个高密度、高价格的城市核心区和低价格的郊区。费城西北部和东北部的郊区往往也有较高的值。费城南部和西南部的机场周围地区和工业区的值较低,而东侧的中心城市滨水区的平均值较高。
2014-2020 年每个街区的百分比变化【作者图片】
这种视觉化更深入地挖掘了城市核心周围明显的中产阶级化过程。就在高物价中心城市的北部和南部,是一些平均价值快速增长的街区。这个项目的目标是预测这个过程扩展的具体位置。
特色工程
特征分为静态或动态,以及外源性或内源性。
- 静态特征假定在给定的时间段内不会改变(例如:公园、医院和公交车站的位置)
- 动态特征每年都会发生变化(例如:犯罪事件、学校质量)
- 内生特征是每个地块的内部特征(例如:总宜居面积、卧室数量、浴室数量)
- 外源特征是地块的外部特征,由周围环境引起(例如:到不同设施的距离、平均社区价格)
考虑到这些分类,我构建了以下特征:
完整功能列表【图片由作者提供】
请注意,一些特征后的数字表示平均 k-最近邻中的 k 。我在这里更深入地讨论这个版本的 k-最近邻算法。简而言之,对于每个宗地,我计算了给定要素的 k 个最近位置,并对这些最近点的特征值进行平均。
我尝试用不同的 k 值来衡量平均值。例如,对于最近的犯罪,如果某个犯罪仅在一年内发生在房屋附近,则该要素在该时间步长内将会非常倾斜。每个特征都有不同的 k 值,并且在模型构建过程中为每个特征选择了最具信息性的 k 。
请注意,平均邻域价格要素是在预定义的费城邻域上生成的。当给定的边界没有正确地在住房类型和价格的集群之间划分时,这可能会导致问题。这就是所谓的可变面积单位问题。在其他房价分析中,不同形式的聚类被用于根据具体特征对地理区域进行分组,而不是使用邻居边界。在本文中,我进一步研究了地理聚类,但是总的来说,创建定制聚类的尝试并没有比预定义的邻域更加同质。而是使用原始邻域。
建模
手头有几十个特征,我比较了线性、非线性和基于树的方法来预测整个城市的房价。
普通最小二乘法,或 OLS,经常被用于房价的享乐模型,但空间自相关的存在破坏了这一测试的统计假设。空间自相关是指房价数据在空间上并不独立,因为它们受到许多相同空间因素的影响。这个项目的目标不是优化统计推断,而是做出准确的预测。因此,准确性和普遍性更为重要。在整个特性工程过程中,OLS 预测是确定新特性质量的重要基准。
我还使用了被称为弹性网的惩罚回归作为基线估计。LASSO 的目的是将系数小的变量推向零,从而提供一种伪特征选择的方法,由于回归方程中有大量可用的特征,这一点尤其重要。岭回归还可以最小化系数,尤其有助于存在多个相关预测值,因为空间模型中存在自相关。具有混合因子的组合版本适合当前模型,因为它可以与相关变量和特征选择一起工作。
主成分回归,或 PCR,能够降低数据集的维度,也与其他模型进行了比较。PCR 首先使用主成分分析提取解释最大差异的主成分或特征向量。这个新空间的主成分将比特征少,从而降低了输入的维数。然后,可以将系数拟合到包含主成分的新特征空间中,该主成分在使用较少特征的同时解决了原始数据中的差异。这种降维在预测房价时可能很重要,因为有许多潜在的相关特征需要解释。
除了回归,我还使用了随机森林和梯度推进机器。随机森林是基于原始数据的不同自举样本的许多决策树的集合。由于在随机森林中使用了许多随机决策树,这个模型容易受到离群值的影响。随着训练的完成,它还会自动选择更多相关的功能。
最后,我测试了梯度推进机器。该算法包括连续计算决策树,以适应前一个模型的残差,按学习率缩放。随着连续树数量的增加,由于考虑了残差,模型变得更加适合训练数据。这样,GBM 能够很好地拟合已知数据,尽管它们对异常值很敏感。代表性的训练样本是这种技术有效工作的关键。
为了评估和比较这些模型,我使用平均绝对百分比误差(MAPE)和平均绝对误差(MAE)进行 10 倍交叉验证和空间交叉验证。10 倍交叉验证简单地将训练数据随机分成 10 倍。对于 10 次迭代,其中一个折叠作为测试集,其余的用于训练模型。空间交叉验证以类似的方式工作,但是折叠是在费城随机选择的邻域。以这种方式调查误差将暴露模型中未考虑的邻域级别的空间自相关。
模型结果【图片由作者提供】
预测
在所用的模型中,随机森林迄今为止表现最好。这可能是由于从许多随机树中抽取平均结果时所表现出的固有变量选择过程。随着更具预测性的预测者出现,不重要的预测者最终被排除在连续的树之外。请注意,对于所有模型,与随机交叉验证相比,计算空间交叉验证时会增加误差。这表明残差中仍存在某种程度的空间自相关,这种自相关在邻域级别上表现出来。
确定了最准确的房价模型后,我使用随机森林模型来预测未来几年的市场价值。这些预测是通过使用特定年份的训练数据来预测未来年份的目标市场价值。由于数据集最多可以使用描述 2014 年城市状态的数据进行训练,并预测 2020 年的已知值,因此最大的未来预测也是未来六年的预测。一旦经过训练,这些模型可以外推至 2020 年以后。
邻域变化预测的热图【图片由作者提供】
上图显示了 2025 年的模型预测。左图显示的是未来五年内宗地密度较高且价格预计会下降的区域,右图显示的是价格预计会上升的区域。此外,两个地图都显示了当前经济适用房项目的位置,其大小基于可用单元的数量。总体而言,该市的平均单户家庭房价预计将从 2020 年的 136,860.90 美元升至 2025 年的 138,848.80 美元,这解释了房价上涨更频繁、更密集的地区。事实上,在预测的 275,347 宗地块中,121,342 宗预计升值超过 10%,而 36,231 宗预计下降相同的幅度。
推荐
在经济适用房方面,热图为未来的安置提供了一个指标。费城北部和南部围绕中心城市的区域有着高密度的快速升值的地块,这为这些区域的经济适用房需求做好了准备。这些结果与直觉一致,即经济快速增长的地区位于城市中心的外围,这可能导致这些地区的流离失所和住房需求增加。
费城市已经认识到了这种需求,制定了“住房换权益”计划(T1),计划在未来十年内新建 25,000 个家庭。为了评估过去住房单元的位置,我计算了每个开发项目四分之一英里半径内地块的当前和预测未来平均值。宗地价值的增长率被定义为时间跨度开始和结束时的平均宗地价值之间的比率。
经济适用房开发和社区增长率【作者图片】
如上图所示,周边社区增长最快的经济适用房项目位于市中心,尤其是在西北、东北和南部。那些离中心城市较远的地方,附近的房价涨幅较小。
高增长地区的经济适用房【作者图片】
放大高增长区域的集群,发现项目所在的社区在每个时间段的平均值都翻了一番以上。根据该模型,在接下来的五年中,预计社区增长将向北扩展。形成鲜明对比的是,在显示的两个时间段中,只有一个当前项目所在的区域的价值有望翻倍。尽管南费城的价值有了显著的增长,但预计未来几年不会有同样的增长。
在预计未来平均社区价值至少翻一番的 20 个项目中,只有 4 个项目是在 2010 年代建造的。在快速发展的地区缺乏近期的经济适用房使得这些地区经济适用房的前景不稳定。资助这些开发项目的低收入住房税收抵免(LIHTC)允许开发商在 15 至 30 年后将经济适用房开发项目转化为市场价格单位。由盈利性公司开发和拥有的经济适用房项目更有可能在期限结束时将其项目改造为市场价格单位,特别是在如上所示的高增长地区。
在 2015 年至 2020 年高增长地区的 27 个项目中,有 10 个由营利性开发商所有。在 2020 年至 2025 年预计高增长地区的 20 个项目中,一半由营利性开发商所有。根据提供租金补贴住房的 15 年合同,即使需求增加,这些关键地区的负担得起的住房存量预计也会大幅下降。
因此,特别是在中产阶级化地区,随着私人拥有的负担得起的住房单元转变为市场价格单元,可用的租金控制单元预计将会减少。这种住房短缺可能导致长期租房者流离失所。正如议员 Green 早些时候提出的,预测这些变化的一种方法是提前两年宣布低收入租金状况的变化,以便给城市规划者和居民时间准备搬迁。
鉴于对宗地价值的预测,对费城未来经济适用房的建议应考虑到预计增长最快的地区。这些领域目前的项目如下
预测高增长地区的经济适用房项目【作者图片】
如果不延长经济适用房期限,这些高增长地区的营利性开发商很可能会在他们的 15 年合同到期时驱逐低收入租户,从明年的 Nellie Reynolds Gardens 开始。考虑到对高增长地区的预测,建议采用三种方法来帮助抑制迁移的影响:
- 要求从补贴租金到市场租金的变化提前两年公布
- 延长警察局公寓、Raymond Rosen 公寓或 Nellie Reynolds Gardens 的租金控制住房的期限
- 将住房券的重点放在这些地区的租户身上,这些租户在未来一年可能会面临租金上涨
像这样的意识和基于地区的策略在规划费城经济适用房投资的未来时非常重要。
备件业务中的预测
有句话说,未来就在我们眼前一寸。永远在附近,但永远在前方。
丹尼尔·塞勒在 Unsplash 上拍摄的照片
在这个例子中,一个 R 预测管道用几种统计方法创建,每天为每个零件运行,以支持自动补货系统。像加法霍尔特-温特斯、指数平滑、克罗斯顿和脸书预言家这样的方法被组合起来,以输出每个零件和下一个需求周期的需求预测。作为未来的工作,其他方法,如 LSTM,可以实施和分析,以改善预测,如果适用。
业务背景和现状
备件业务有其自身的挑战:
- 客户非常迫切,要求立即供货(他们的客户大多是车主,还记得你上次去汽车修理厂吗?这通常不是一件愉快的事。)
- 大多数零件在单位时间内销量很小(甚至没有销量)——间歇性需求
- 该企业拥有庞大的产品组合(在多品牌零件批发商中甚至更多),每个品牌拥有超过 200,000 种不同的零件
这三个问题增加了库存积压和低库存周转率的问题,并且与批发商规模成反比:小型零件企业更容易受到这些问题的影响。
除了这些挑战之外,其他挑战也确实存在,但对其他企业来说更为普遍:
- 需求可变性:更好或更便宜或两者兼而有之的替代产品,客户偏好的变化(如配件市场备件份额的增加)或季节性(保险杠和其他车身部件在冬季的销量增加,而不是在夏季之前的过滤器和其他维护)
- 上游供应链的变化和中断 : PSA 整合了批发商的数量,并收购/合资了其他品牌,如欧宝和菲亚特集团,采购集团整合,非欧盟基金收购大型欧洲公司,黑天鹅事件,如 COVID global issue
- 电子商务和市场:永久的“沉睡的巨人”一直潜伏在一个迄今为止仍然是传统的市场中,对于一个迫切需要整合的市场来说,参与者的数量仍然太多
预测简介
我先讲一个关于未来的故事:它不会完全是你预测的那样!你越想在粒度的基础上预测,你能得到的误差就越大。
在商业方面,这并不意味着你应该忽略它。平均而言,你只需要比竞争对手做得好一点,从长远来看,你将拥有的竞争优势。
对于这个业务问题,我使用了 4 种方法:
- 指数平滑法
- 加法霍尔特-温特斯
- 克罗斯顿
- 脸书先知
其他城市(ARIMA、LSTM)也可以加入进来,但为了简洁明了,我们选择从这些城市开始。
预测方法
指数平滑法
指数平滑法是由 Charles C. Holt 在 20 世纪 50 年代末引入的。基本概念是在移动平均窗口的序列中构建时间序列,然后将最近的窗口置于旧窗口之上。加权方法是指数产生良好的预测。
指数平滑是一种使用指数窗口函数平滑时间序列数据的经验法则。在简单移动平均中,过去的观察值被同等地加权,而指数函数被用于分配随时间按指数递减的权重。
加法霍尔特-温特斯
这种方法是对霍尔特之前工作的改进。它是由 Peter R. Winters 加上季节性开发的,也被称为三重指数平滑法。
克罗斯顿
该书于 1972 年出版,书名为“间歇需求的预测和库存控制”,它解决了指数平滑积压的问题,方法是仅在发生的时间段内对发生的情况进行平均,然后乘以发生的概率。
需要注意的是,它不能处理负销售额(如果总额为负,则向客户进行发票贷记)。在预测特定备件时,您必须意识到这一点。
脸书先知
Prophet 是一种基于加法模型预测时间序列数据的过程,在该模型中,非线性趋势与每年、每周和每天的季节性以及假日影响相适应。它最适用于具有强烈季节效应的时间序列和几个季节的历史数据。Prophet 对缺失数据和趋势变化非常稳健,通常能够很好地处理异常值。
这种方法发表于 2017 年(比我们使用的前三种方法更近),我们研究它的原因是,除了完全自动化的之外,它还考虑了日历效应(像假期)。
不利的一面是,数据接收与前三种不同,迫使开发另一种数据提取过程。此外,对于我们的业务案例,它比其他的要慢得多,迫使我们重建/升级一些服务器软件组件。它在生产中的实现有更大的障碍。****
预测的准备工作
替代
备件业务有很多替代品。一个零件从 sku A 开始,变化到 B,到 C(或回到 A)…对任何想要一个干净方法的人来说都是一团糟。
替代用于:
- 用一部分代替另一部分
- 由于工程变更,需要用新版本替换的过时零件
因此,我们需要一个函数,它可以为一个零件获取它的替代链。由于使用了递归公共表表达式,它可以获得链中的所有部分:
从替代的表格视图中,我们可以得到一个列表:
提前期和预测期
这也许是一个更难解决的问题。对于由多个供应商供应(具有不同的交付周期)的每个零件,有必要评估主要供应商(如果存在多个供应商)并相应地进行预测。
例如,假设供应商 A 的补货提前期为 1 周(从订单到进货后的库存可用性),我们可以预测 n 个周期,每个周期 1 周。另一方面,如果供应商 B 的零件需要一个月才能交货,那么它的预测期也应该是一个月。
为了本文的简洁,所做的分析将假设 1 个月的时间(生产方法在每个供应商/品牌的基础上有可变的交付周期)。
将表格销售数据转换为时间序列
几乎每个销售数据源都以表格的形式出现。你会得到这样的结果:
出于预测目的,有必要将此结构更改为时间序列(例如,使用月度时段的单个 sku 注意 2018 年 9 月出现的负值):
****
要从表格转换为序列,只需在数据库中“分组”时间段:
用于预测的最低可行产品
现在,使用数据,我们需要设置它的预测方面。为此我们使用了 R(感谢非凡的库 forecast ),但是你也可以使用 Python 或者其他解决方案。
添加所需的库并连接到数据库:
从数据库中获取数据:
根据数据创建时间序列:
尝试第一次预测(仅在没有负面事件发生时适用于克罗斯顿):
即使如此,如果您选择使用 Croston,您可以将负面事件归零(请在比较预测方法时考虑,因为您正在更改其中一种方法的数据):
****
看着图表,我们倾向于选择前面的霍尔特-温特斯(其他的似乎“太平”)。但是,对于这个用例,只有对“下一个时期”的预测是重要的,因为我们将重复地做它。
所有方法都导致类似的结果,2020 年 1 月平均售出 4 或 5 台,并且“Hi 95”区间达到 18 或 13。
先知呢?
正如我提到的,Prophet 数据摄入有点不同。首先,它需要每日数据,头必须是' ds 和' y 【T3 ':
因此,我们需要改变我们的数据源 SQL。类似这样的事情会发生:
(如果你注意到了,我们正在将负面事件归零。模型中还有一个我们可以使用的特性,叫做“饱和最小值”。)
获得下一期的预测只是跟踪预测:
解决生产预测问题
现在我们有了一个工作的 MVP,是时候把它投入生产了。对于那些仍在内部使用 IT 基础设施的人来说,计算相对便宜。服务器已经在那里了,大部分时间都在闲置,乞求做一些有用的事情。
对于我们的数据集(+50.000 sku),对每个 sku 进行 4 次预测很容易就需要一整天以上的时间。我给你一个提示:先知应该为此负责😊
但是有一些策略可以用来减少花费的时间:
1.并行计算
这是减少时间的最佳选择。按照仓库、品牌或任何其他标准来划分工人。请注意,组的基数相等通常意味着它运行得更快(结束得更快),因为它避免了一个延迟的组拥有比其他组更多的 SKU。
你可以使用的另一种方法是将 Prophet 与其他人分开。这样,由于数据采集是不同的,其他的将会很快结束。请注意,一些 Prophet 预测是长期运行的,数据库连接/事务可能会在数据库端关闭。
另一方面,并行计算有两个问题需要解决:
- 如果您的方法是让工作器在没有任何顺序的情况下获取数据块,那么有必要强制执行一些数据库锁。
- 当最后一名选手结束时,你需要给这个项目的合奏部分发信号(下一章会有更多的介绍)。
2.仅对前一天销售或购买的零件进行每日计算
该选项是另一种快捷方式😊。如果您的补货订单每天都有,前一天未售出/未购买的零件“可能”会减少他们的库存预测(请对此持保留态度,因为当季节性等其他问题生效时,这在数学上是不正确的)。
这种解决方案的优点是还减少了与每天售出的不同零件(平均)数量相关的因素所做的计算。如果你有 50,000 个 SKU,而你平均每天只卖出/买入 5,000 个,那么你就减少了 90%的计算量。
如果你选择使用这种策略,我建议每周/每月进行一次全面跑步。
对于给定日期的给定备件,使用哪种预测方法
现在,我们有一个渠道在每个零件上运行 4 个不同的预测,我们应该选择哪一个?
有几个概念可以帮助你选择(我不能在这里说得太详细):
- 库存不足比库存过多更贵吗?也就是说,利益相关者更重视缺失的部分还是过多库存的成本?这个问题的答案有助于你选择更保守的方法。在这一点上,克罗斯顿往往做得很好。
- 选择返回较低 MAPE(平均绝对百分比误差)或 MSE(均方误差)的方法。平均而言,ETS 表现最差。
- 通过使用 MAPE 对库存不足进行+20%的惩罚(如果实际值减去预测值为负)来综合前两种方法。
这也许是这个项目更商业的一面。这实际上取决于你试图预测的潜在原因是什么:是数学准确性还是商业优势。👍
总结
从所做的工作来看,克罗斯顿和霍尔特-温特斯都做得很好。ETS 是表现最差的模型,而 Prophet 的计算强度更大,没有为 7 天、15 天或 30 天的预报提供足够的优势。
在自动订单管道上完成工作后,预测方将估计的销售额反馈给它,并允许一个完整的自动化库存管理。
就是这样!全部完成!新的挑战在别处等待着我们!!!👏
电力商业智能预测
数据科学/电力 BI 可视化
使用 Power BI 进行预测的直观分步指南。
在本帖中,我们将介绍在 Power BI 中创建预测的过程。
获取数据
你可以在这里下载我用的数据集。它包含了 1959 年加利福尼亚每天的女性出生人数。关于其他时间序列数据集的列表,请查看 Jason Brownlee 的文章。
机器学习可以应用于时间序列数据集。在这些问题中,数值或分类值必须…
machinelearningmastery.com](https://machinelearningmastery.com/time-series-datasets-for-machine-learning/)
让我们将数据加载到 Power BI 中。打开 Power BI 并点击欢迎屏幕上的“获取数据”,如下所示。
作者截图
接下来,您将看到另一个面板,询问我们想要获取什么类型的数据。选择如下所示的“文本/CSV”并点击“连接”
当“文件打开”窗口出现时,导航到我们保存数据集的位置,然后单击右下角的“打开”按钮。
当预览出现时,只需点击“加载”
我们现在将看到 Power BI 的主要工作区域。前往“可视化”面板,寻找“折线图”
。作者截图
这是折线图图标的外观:
接下来,将出现一个可视占位符。拖动占位符右下角的热角标记,并将其对角向下拖动到主工作区的右上角。
截图由作者
接下来,打开“字段”面板。
在折线图占位符仍处于选中状态的情况下,找到“日期”字段,然后单击方形框以选中它。
我们现在将看到轴下的“日期”字段。点击“日期”右侧的向下箭头,如下所示。
截图由作者
选择“日期”而不是默认的“日期层次结构”
截图由作者
然后,让我们在“出生”字段打上勾号。
我们现在将看到一个类似下图的线形图。在可视化面板和图标列表下,找到如下所示的分析图标。
作者截图
向下滚动面板,找到“预测”部分。如有必要,单击向下箭头将其展开。
接下来,单击“+Add”在当前可视化中添加预测。
我们现在将看到一个实心的灰色填充区域和一个位于可视化右侧的线图,如下图所示。
让我们把预测长度改为 31 点。在这种情况下,一个数据点相当于一天,所以 31 大致相当于一个月的预测值。单击预测组右下角的“应用”以应用更改。
让我们将度量单位改为“月”,而不是点,如下所示。
单击“应用”后,我们将看到可视化效果的变化。下图包含 3 个月的预测。
截图由作者
如果我们想比较预测与实际数据的对比情况会怎样?我们可以通过“忽略最后一个”设置来做到这一点。
对于这个例子,让我们忽略过去 3 个月的数据。Power Bi 将使用数据集预测 3 个月的数据,但忽略过去 3 个月的数据。这样,我们可以将电力 BI 的预测结果与数据集最近 3 个月的实际数据进行比较。
如下所示,完成设置更改后,我们单击“应用”。
下面,我们可以看到功率 BI 预测与实际数据的对比。黑色实线代表预测,而蓝色线代表实际数据。
预测上的实心灰色填充表示置信区间。其值越高,面积就越大。让我们将置信区间降低到 75%,如下所示,看看它对图表的影响。
截图由作者
实心灰色填充变小,如下所示。
截图由作者
接下来,让我们考虑季节性。下面,我们把它设定为 90 分相当于 3 个月左右。输入这个值将告诉 Power BI 在 3 个月的周期内寻找季节性。用根据数据有意义的东西来玩这个值。
结果如下所示。
作者截图
让我们将置信区间返回到默认值 95%,并向下滚动该组以查看格式选项。
让我们将预测线更改为橙色,并通过将格式更改为“无”来使灰色填充消失
就是这样!只需点击几下鼠标,我们就能从数据集中得到一个预测。
感谢您的阅读。如果你想了解更多关于我从懒鬼到数据科学家的旅程,请查看下面的文章:
我的无学位数据科学之旅。
towardsdatascience.com](/from-slacker-to-data-scientist-b4f34aa10ea1)
如果你正在考虑改变方向,进入数据科学领域,现在就开始考虑重塑品牌:
给我们其他人的固执己见的建议。热爱数学,选修。
towardsdatascience.com](/the-slackers-guide-to-rebranding-yourself-as-a-data-scientist-b34424d45540)
敬请期待!
你可以通过推特或 LinkedIn 联系我。
[1]机器学习掌握。(2020 年 6 月 21 日)。机器学习的 7 个时间序列数据集。https://machine learning mastery . com/time-series-datasets-for-machine-learning/
利用 Streamlit 和 sktime 预测可再生能源发电量
开发 Streamlit web 应用程序,提供欧盟国家可再生能源发电预测
尼古拉斯·多尔蒂在 Unsplash 上拍摄的照片
气候变化无疑是人类面临的最大挑战之一。过去十年是有记录以来最热的,2019 年结束时,全球平均气温比工业化前水平高 1.1 摄氏度。全球气温上升对人类福祉的各个方面都有重大影响,如健康和粮食安全。近年来,许多人死于热浪,而其他人则因气候多变和极端天气事件而遭受饥饿。
科学家们不断做出与全球变暖有关的惊人发现。例如,最近有报道称,自 1994 年以来,地球已经失去了 28 万亿吨冰,这表明到本世纪末,全球平均海平面可能会显著上升。根据政府间气候变化专门委员会(IPCC)的说法,世界必须在 2050 年实现碳平衡才有希望将全球变暖限制在 1.5 摄氏度以内,并避免气候变化的最恶劣影响。联合国秘书长安东尼奥·古特雷斯表示,我们目前离实现这一目标还很远。
可再生能源
科学界一致认为,人为气候变化是由人类活动排放的二氧化碳和其他温室气体(GHG)造成的。因此,降低大气中的 GHG 浓度来缓解这一问题至关重要。化石燃料发电站要对很大一部分温室气体(GHG)排放负责,这使得向低碳替代能源的过渡比以往任何时候都更加重要。在过去几年中,可再生能源发电的成本大幅下降,使其成为一种可行且具有成本效益的选择,即使我们忽略了环境保护方面。不幸的是,最近的一项研究表明,只有 10%的电力公司优先考虑可再生能源,这表明这种转变非常缓慢。另一方面,这也表明可再生能源行业具有巨大的增长潜力。
图表由我们的数据世界
预测可再生能源发电
有许多可再生能源可用于发电,如太阳能、风能、水电、生物质能和地热。大多数国家都把重点放在太阳能和风能上,因为替代能源有很大的局限性。例如,水力发电站和地热发电站只能建在特定的地区。太阳能和风能更灵活,但它们的输出取决于天气条件和其他因素,所以它们被称为可变可再生能源(VRE)。由于 VRE 电站的输出功率波动较大,将它们并入电网是一项挑战。准确的预测可以帮助我们克服这一障碍,并改善电力调度和长期系统规划。
sktime Python 库
时间序列预测通常是用统计模型来完成的,比如 ARIMA。然而最近几年,机器学习算法也被使用。利用滑动窗口方法,时间序列预测可以很容易地转化为一个监督学习问题。在这个方法中,每个值被认为是一个标签 y ,前面的 n (窗口长度)值是 x 特征。产生的数据集可用于训练我们偏好的回归模型。您可以在下表中看到这样的示例(窗口长度为 n = 10)。
[ 0 1 2 3 4 5 6 7 8 9] [10]
[ 1 2 3 4 5 6 7 8 9 10] [11]
[ 2 3 4 5 6 7 8 9 10 11] [12]
[ 3 4 5 6 7 8 9 10 11 12] [13]
[ 4 5 6 7 8 9 10 11 12 13] [14]
[ 5 6 7 8 9 10 11 12 13 14] [15]
[ 6 7 8 9 10 11 12 13 14 15] [16]
[ 7 8 9 10 11 12 13 14 15 16] [17]
[ 8 9 10 11 12 13 14 15 16 17] [18]
[ 9 10 11 12 13 14 15 16 17 18] [19]
Sktime 是一个 Python 库,基于机器学习算法,为时间序列预测提供了有用的工具。它自动对时间序列应用滑动窗口方法,同时也与 scikit-learn API 兼容。这意味着它可以很容易地与每个 scikit-learn 回归器或其他兼容的库(如流行的 XGBoost 算法)一起使用。要深入了解 sktime,您可以查看这篇文章,或者阅读由其开发人员撰写的研究论文。
简化框架
Streamlit 是一个 Python 框架,可以让您非常快速地为数据科学项目构建 web 应用。您可以用几行代码轻松创建一个包含各种小部件的用户界面。此外,Streamlit 是一个很好的工具,可以将机器学习模型部署到 web 上,并增加数据的可视化效果。Streamlit 还有一个强大的缓存机制,可以优化应用程序的性能。关于 Streamlit 的详细介绍可在这里获得。
开发 Renewcast 网络应用程序
Renewcast 是一款网络应用,提供欧盟国家可再生能源发电预测。我决定开发这个应用程序有几个原因。首先,我非常关注气候变化,我想探索机器学习可以帮助缓解气候变化的各种方式。第二,我总是试图提高我的技能,开发这个应用程序是熟悉 Streamlit 和 sktime 的一个很好的方式。我现在将描述源代码的功能,从app.py
文件开始。
这是主要的 Streamlit 应用程序。首先我导入了 Streamlit 库,还有一些我自己创建的函数。之后,我使用相关的 Streamlit 函数为应用程序添加了一个标题和描述。然后,我继续创建一个基本的用户界面,在标准的 Streamlit 侧边栏上添加小部件。用户可以选择一个国家和回归算法,以及修改预测范围和窗口长度。最后,我使用了area_chart()
和line_chart()
函数来绘制总发电量,以及可再生能源发电量(太阳能和风能)的预测。让我们继续讨论entsoe_client.py
文件。
get_energy_data()
功能与 ENTSOE-E API 接口,下载每个欧盟国家的必要能源生成数据。在定义函数之前,我插入了@st.cache
装饰器来使用 Streamlit 的缓存机制。我这样做是为了让 ENTSOE-E API 不会在我们每次需要使用这些数据的时候被调用,而是只在需要更新的时候被调用。这将优化我们的应用程序的性能,并显著减少运行它所需的时间。现在让我们继续,检查最后一个主要源代码文件forecast.py
的功能。
select_regressor()
函数只是将用户界面的回归算法选项映射到相关的 scikit-learn 类。我已经包含了一些典型的 scikit-learn 回归算法,比如线性回归、随机森林和梯度推进,但是任何与 scikit-learn API 兼容的回归器都应该可以工作。generate_forecast()
函数负责应用程序的主要功能,即预测能源生产时间序列的未来值。我用ReducedRegressionForecaster
类实现了这一点,它将滑动窗口方法应用于时间序列,然后用该数据训练一个回归模型,这是前面讨论过的一种技术。最后,我还创建了calculate_smape()
函数,它返回对称平均绝对百分比误差(SMAPE ),这是一个有用的指标,可以帮助我们评估预测的准确性。
结论
我希望读完这篇文章后,你会被鼓励开发自己的 Streamlit 应用程序,甚至 fork renew cast(Github 存储库在这里可用)。也许你会受到启发,获得更多关于气候变化的知识,以及用机器学习减轻气候变化的许多方法。欢迎在评论中分享你的想法,或者在 LinkedIn上关注我,我会定期在那里发布关于数据科学、气候变化和其他主题的内容。你也可以访问我的个人网站或者查看我最新的一本书,书名是用 PyCaret 简化机器学习。
参考
[1] M. Joos,I. Staffell,可变可再生能源的短期整合成本:英国和德国的风电削减和平衡 (2018),可再生和可持续能源评论
[2] D. Rolnick,P. L. Donti,L. H. Kaack,K. Kochanski,A. Lacoste,K. Sankaran,等.用机器学习应对气候变化 (2019),arXiv:1906.05433
[3]m . lning,F. Király,用 sktime 进行预测:设计 sktime 的新预测 API 并应用它来复制和扩展 M4 研究 (2020),arXiv:2005.08067
预测生存指南:避免 PoC 诅咒的 4 个专业建议
我从野外预测项目中学到的经验将帮助您从一开始就获得更好的结果,并将您的模型投入生产。
埃里克·麦克林在 Unsplash 上的照片
很多机器学习模型都没有投入生产。有些人甚至称之为 PoC 魔咒:概念证明显示出有希望的结果,但从来没有人使用它们。
然后,数据科学家经常抱怨数据质量、破损的数据管道或 MLops 有多难。然而,我认为很多模型在被训练之前就注定要失败。
正如任何其他项目一样,范围和目标可以决定预测项目的成败。当开始一个新项目时,有时我们在这些重要步骤上花费的时间太少。尤其是与未来用户有一定距离的团队(如数字创新团队、数据实验室等跨职能部门),必须意识到这种危险。
让我分享一些如何在项目早期避免 PoC 诅咒的技巧。
思考来自于决定
预测项目的目标在项目开始时似乎非常明确。在一些项目中,你被要求预测客户流失,在下一个项目中,你应该预测零售销售,在另一个项目中,他们被要求预测实验室中某个过程的能耗。
然而,在大多数情况下,你的项目发起人不会因为做预测而得到报酬。她因取得商业成果而获得薪水。你将要做的预测模型应该会帮助她获得更好的结果。问她将根据预测模型的结果采取什么措施:
- 可以采取什么行动?
- 谁将决定要采取的行动?
- 你如何根据预测做出这些决定?
- 你还需要什么来做决定?
- 这些决定通常在什么时候做出,多久做出一次?
为什么这很重要?您可能会遇到这样的情况,人们在谈论公司使用预测模型可能获得的优势,但没有人真正做出决策来实现这一点。这些优势很可能只是虚幻的,不会实现。
史蒂夫(项目成员):“如果我们知道哪个客户将要离开,我们就可以给他们打折。那就太好了!”
你:“谁来决定一个顾客是否得到折扣以及折扣的金额?”
史蒂夫:“哦,那是客户经理。让我们看看莎拉是否能加入我们的讨论。”
你:“嗨,Sara,我们考虑了一个可以支持你的新应用程序。它将能够预测即将离开的客户,你可以为他们提供折扣!”
萨拉(客户经理):“嗯。我们的客户通常会因为功能缺失而离开。一旦上船,他们很少要求打折。我们没有那么多顾客。我已经知道那些不快乐的人和原因。”
这并不一定会使你的客户流失预测模型变得无用(Sara 可能并不像她认为的那样了解她的客户),但你需要获得更多关于你的模型将支持的决策的见解。
在评估模型的准确性和精确度时,了解要采取的决策可能是有益的。它甚至可以彻底改变必要的机器学习模型。
利益相关者可能会告诉你,他们需要一个回归模型来预测 6 个月内的原材料消耗。然而,他们真正需要的决策(购买更多或更少的原材料)可能是一个分类模型,该模型指示下个月的消费量是否大致相同,比上个月的消费量低 20%还是高 20%。
这就是为什么你应该总是从决定中思考。
让所有相关人员都参与进来并做出承诺
一旦你知道了相关的决策,你应该让相关的决策者参与进来,并致力于这个项目。从决策者那里获得项目承诺的最好方法之一是在设定项目目标时让他们参与进来。
其他相关人员包括拥有可以为您的模型提供数据的系统的人员、通常处理分析和 BI 项目的团队、制定 IT 标准的架构师或负责模型运营的团队。
有些人可能在开始时不能做出很多贡献,但是一旦你需要他们的支持,如果他们已经了解你和你的项目会更好。早期的反馈也有助于避免以后出现各种不愉快的问题,比如这个:
彼得(数据所有者):“这是我们的数据。你不能用它。”
你:“但这是公司的数据。我们的模式依赖于此。”
彼得:“人们从未想到这些数据会被用于自动预测。我还需要三个职位来保证数据的质量。我会在人员成本规划中考虑这一点。我们可以明年再谈。”
尽早澄清所有相关干系人的要求。另一个例子:立即开始使用 Python 比以后发现运营团队甚至不会考虑部署 Julia 应用程序要容易得多。
根据项目的不同,您还应该与负责数据保护和安全的人员交谈,例如数据保护官员。
预测项目的潜在利益相关者
先问你如何能改善人们的生活,模型其次
避免过早进入白板建模和特征工程。相反,问问你的解决方案如何改善你的股东、他们的客户和你未来的用户的日常生活。
如果你的模型对他们没有好处,为什么有人要用呢?如果只是他们的老板告诉他们使用它,你可以肯定他们会在你的模型中发现最小的怪癖和不一致。
人们不会在意更好的 R 或者牛逼的 F1 成绩。他们确实关心他们的工作&时间,也许还有地位。对他们中的一些人来说,这将是使用一个花哨的人工智能应用程序的足够动力,但对其他人来说,你必须提供更多实质性的改进。它远没有你想象的那么深奥。询问您的利益相关者和未来用户:
你和你的同事如何注意到我们的项目是成功的?
这会如何让你的工作生活变得更轻松?
每个人都在谈论客户亲密度,为什么不也想想他们呢:
您的客户将如何注意到我们的项目是成功的?
这将如何让他们的生活更轻松?
问这些问题并得到答案可能需要几个小时,但这比两周的超参数调优要有益得多。
口头说明风险和要求
一旦你得到了所有利益相关者的承诺,你知道要支持的决策以及如何改善每个人的生活,预测项目仍然有一点复杂:预测未来真的很难。
虽然我们正在取得进展,但许多机器学习项目仍然更像是一个研究项目,而不是一些商业应用程序的开发项目。
从一开始就乐观地开始这个项目,但是老实说,很多进展会是这样的:“太好了,现在我们知道消费者信心指数对于预测销售是而不是有用的。”
此外,不要从太少的数据开始。许多公司刚刚开始考虑成为一家数据驱动型公司,没有包含几十年数据的数据湖,许多初创公司甚至还没有存在足够长的时间。
如果你想预测原材料的消耗,并且你的生产过程遵循一个年度模式,用一年半的数据是不会成功的。
如果你想预测零售额,而你的典型产品生命周期是七年,三年的数据是不够的。
说出风险和需求将有助于管理涉众的期望,并使您的生活更轻松。
我希望这些见解对你有用。感谢您的阅读,我期待您的评论和预测体验!
用自回归预测特斯拉的股价
了解如何使用 Python 将基本的时间序列建模技术应用于 Tesla 的股票价格。
资料来源:Bram Van Oost via Unsplash。
过去几个月里,特斯拉一直在金融市场兴风作浪。此前被评为美国最被卖空的股票[1],特斯拉的股价此后飙升至 2780 亿美元的市值[2]。其最新的季度业绩表明,它现在可以加入标准普尔 500 了,尽管它是美国第 12 大公司,但它目前还不是其成员[3]。
在市场波动、各种交易策略和“FOMO”(害怕错过)感的背景下,预测特斯拉股票的回报是一项艰巨的任务。但是,我们将使用 Python,使用自回归来预测特斯拉的股价回报。
探索数据
首先,我们需要导入数据。我们可以使用从雅虎财经下载的历史股票价格数据。我们将使用“接近”价格进行分析。
import pandas as pddf = pd.read_csv("TSLA.csv", index_col=0, parse_dates=[0])
df.head()
来源:雅虎财经。
来源:雅虎财经。
为了确定 ARMA 模型的阶数,我们可以首先绘制一个偏自相关函数。这给出了因变量和其自身滞后之间的相关量的图形解释,未通过所有低阶滞后的相关来解释。
从下面的 PACF 中,我们可以看到滞后的显著性在滞后 1 之后消失,这表明我们应该使用自回归(AR)模型[4]。
# Plot PACF
from statsmodels.tsa.stattools import acf, pacf
plt.bar(x=np.arange(0,41), height=pacf(df.Close))
plt.title("PACF")
有限&滞后 1 后截止,所以 AR。
当绘制自相关函数时,我们会得到一个稍微不同的结果。该系列是无限的,并慢慢衰减,这表明 AR 或 ARMA 模型[4]。考虑到 PACF 和 ACF,我们将使用 AR 模型。
#Plot ACF
plt.bar(x=np.arange(0,41), height=acf(df.Close))
plt.title("ACF")
无限和阻尼所以 AR/ARMA。
数据预处理
在运行模型之前,我们必须确保我们使用的是静态数据。平稳性是指数据移动的方式不会随时间而改变的特征。查看本文前面看到的原始股票价格,很明显该序列不是平稳的。我们可以看到,随着时间的推移,股票价格以看似指数的方式上涨。
因此,为了使数列平稳,我们差分数列,这实质上意味着从明天的值中减去今天的值。这会导致序列围绕一个常数均值(0)旋转,从而给出股票收益而不是股票价格。
我们还将使差分序列滞后 1,这将昨天的值向前推至今天。这样我们就可以得到我们的 AR 期限(Yt-1)。
将这些值放入同一个数据帧后,我们将数据分成训练集和测试集。在代码中,数据被大致分成 80:20。
# Make the data stationary by differencing
tsla = df.Close.diff().fillna(0)# Create lag
tsla_lag_1 = tsla.shift(1).fillna(0)# Put all into one DataFrame
df_regression = pd.DataFrame(tsla)
df_regression["Lag1"] = tsla_lag_1# Split into train and test data
df_regression_train = df_regression.iloc[0:200]
df_regression_test = df_regression.iloc[200:]tsla.plot()
差分序列。来源:雅虎财经。
形成 AR 模型
现在,我们应该用多少个值来预测下一个观察值呢?使用所有过去的 200 个值可能不会给出很好的估计,因为直观上,200 天前的股票价格活动不太可能对今天的价值产生重大影响,因为自那时以来许多因素可能已经发生了变化。这可能包括收入、竞争、季节等等。因此,要找到用于回归的最佳观察窗口,我们可以使用的一种方法是使用扩展窗口运行回归。下面的代码详细介绍了这种方法,它使用一个过去的观察值进行回归,记录 r 平方值(拟合优度),然后重复这一过程,每次将过去的观察值扩展 1。从经济角度来看,我将窗口期限制在 30 天。
# Run expanding window regression to find optimal windown = 0
rsquared = []while n<=30:
y = df_regression_train["Close"].iloc[-n:]
x = df_regression_train["Lag1"].iloc[-n:]
x = sm.add_constant(x)model = sm.OLS(y,x)
results = model.fit()rsquared.append(results.rsquared)n +=1
查看每次迭代的 r 平方图,我们可以看到它在 1–5 次迭代附近较高,并且在 13 个过去值处也有一个峰值。在 1 和 5 之间选择一个值似乎很诱人,但是,非常小的样本量可能意味着我们的回归在统计上有偏差,所以不会给我们最好的结果。因此,让我们选择 13 次观察的第二个峰,因为这是一个更充分的样本量,它给出了大约 0.437 的 r 平方(即模型解释了数据中 43%的变化)。
r 平方图。
对训练数据运行 AR 模型
下一步是使用我们过去 13 次观察的窗口来拟合 AR(1)模型。我们可以使用 statsmodels 中的 OLS 函数来实现这一点。以下代码:
# AR(1) model with static coefficientsimport statsmodels.api as sm
y = df_regression_train["Close"].iloc[-13:]
x = df_regression_train["Lag1"].iloc[-13:]
x = sm.add_constant(x)model = sm.OLS(y,x)
results = model.fit()
results.summary()
AR(1)模型的回归输出(训练数据)。
正如我们在统计摘要中看到的,常数和第一个滞后的 p 值在 10%的显著性水平上是显著的。查看系数的符号,常数上的正号表明,在其他条件相同的情况下,股票价格回报应该为正。此外,第一个滞后上的负号表明,在其他条件相同的情况下,股票回报的过去值低于今天值,这也维持了股票回报随着时间推移而增加的说法。
很好,现在让我们使用这些系数来找到特斯拉股票回报的拟合值,这样我们就可以根据原始数据绘制模型。我们的模型现在可以指定为:
我们的 AR(1)方程。
绘制残差图(实际-拟合)
残差(训练数据)
残差表明模型在 2019 年表现更好,但在 2020 年随着波动性增加,模型表现相当差(残差更大)。这很直观,因为 2020 年 3 月抛售经历的波动对美国股市产生了巨大影响,而科技股尤其感受到了快速而可观的反弹。这一点,加上 Robinhood 等平台上的散户投资者加大了对特斯拉股票的押注,加剧了价格波动,从而加大了预测难度。
考虑到这些因素,以及我们之前 43%左右的 r 平方,我们不会期望我们的 AR(1)模型能够预测准确的股票回报。相反,我们可以通过计算其“命中率”来测试模型的准确性,即当我们的模型预测为正值而实际值也为正值时,反之亦然。总结真阳性和真阴性的实例,我们的模型的准确性达到 55%左右,对于这个简单的模型来说,这是相当好的。
根据测试数据拟合模型
现在,让我们将同样的方法应用于测试数据,看看我们的模型如何执行样本外的。
实际值与拟合值(测试数据)。
# Calculate hit rate
true_neg_test = np.sum((df_2_test["Fitted Value"] <0) & (df_2_test["Actual"] <0))
true_pos_test = np.sum((df_2_test["Fitted Value"] >0) & (df_2_test["Actual"] >0))accuracy = (true_neg_test + true_pos_test)/len(df_2_test)
print(accuracy)# Output: 0.6415
在将模型应用于测试数据时,我们的命中率提高到了 64%,这是一个很有希望的改进!提高其准确性的下一步可能包括运行滚动回归,其中系数随着每次迭代而变化,或者可能将移动平均(MA)元素并入模型。
感谢阅读! 如果你有什么见解,欢迎随时留下评论。包含我用来做这个项目的源代码的完整 Jupyter 笔记本可以在我的 Github 资源库 中找到。
参考
[1]卡门·赖尼克(2020)。特斯拉再次成为美国(TSLA)被卖空最多的股票。市场内幕。可在:https://markets . business insider . com/news/stocks/Tesla-stock-most-shorted-us-beats-apple-higher-short-interest-2020-1-1028823046
[2]雅虎财经,截至 2020 年 8 月 6 日。
[3]史蒂文斯,皮帕(2020)。“特斯拉可能很快就会加入标准普尔 500 指数,但这并不是自动的,即使全年都有盈利”。见:https://www . CNBC . com/2020/07/21/Tesla-not-a-guarantee-for-s-p-500-even-with-year-of-profits . html
[4]约翰逊法官,迪纳多法官(1997 年)。《计量经济学方法》,第四版。
免责声明:本文表达的所有观点均为本人观点,与任何金融实体无关。我不是一个交易者,也没有用本文中的方法赚钱。这不是财务建议。
用 Prophet 预测铜生产者价格指数
利用 Prophet 预测商品价格
来源:图片由 Pixabay 的 papazachariasa 提供
免责声明:本文是在“原样”的基础上编写的,没有担保。它旨在提供数据科学概念的概述,不应被解释为投资建议或任何其他类型的专业建议。
即使在最好的情况下,预测资产价格也可能是一件棘手的事情。首先,资产价格受高度随机性(或随机影响)的影响,这使得预测未来变得困难。
也就是说,脸书的先知时间序列模型的一个有用的特性是能够识别变点,或者时间序列中重大结构变化的时期。准确识别这些点反过来可以改进时间序列预测。让我们看看 Prophet 如何预测铜的生产者价格指数。数据来源于弗雷德经济数据使用 Quandl。
背景
铜生产者价格指数从 1985 年 9 月到 2020 年 7 月进行分析。由于这是一个金融时间序列,因此该序列被转换为对数格式,以平滑数据并确保模型考虑了百分比基础上的回报。
这是一张数据图表:
资料来源:弗雷德经济数据
从 1985 年 9 月到 2017 年 1 月的数据作为训练数据。截止到 2020 年 7 月的剩余月份用作测试数据——这些数据用于与模型预测进行比较,以评估准确性。
以下是对该系列的分解:
来源:Jupyter 笔记本输出
我们可以看到,在这种情况下,该系列有一个强大的上升趋势。然而,没有证据表明该系列具有季节性。
也就是说,数据中确实出现了几个结构性突变。从这个角度来看,Prophet 模型在预测测试数据的价格时可能会产生很好的预测能力。
模型结构
数据集定义如下:
train_dataset= pd.DataFrame()
train_dataset['ds'] = train_df['Date']
train_dataset['y']= train_df['Value']
train_dataset.head(10)
标准 Prophet 模型与数据集的拟合如下:
prophet_basic = Prophet()
prophet_basic.fit(train_dataset)
以下是使用该模型生成的预测:
forecast=prophet_basic.predict(future)
fig1 =prophet_basic.plot(forecast)
来源:先知
如上所述,特别令人感兴趣的是变化点,或者时间序列中的重大结构突变。
from fbprophet.plot import add_changepoints_to_plot
fig = prophet_basic.plot(forecast)
a = add_changepoints_to_plot(fig.gca(), prophet_basic, forecast)
来源:先知
从上图可以明显看出,模型已经识别出 12 个变化点。现在在此基础上进行预测。
pro_change= Prophet(n_changepoints=12)
forecast = pro_change.fit(train_dataset).predict(future)
fig= pro_change.plot(forecast);
a = add_changepoints_to_plot(fig.gca(), pro_change, forecast)future_data = pro_change.make_future_dataframe(periods=43, freq = 'm')
#forecast the data for future data
forecast_data = pro_change.predict(future_data)
pro_change.plot(forecast_data);
Prophet 生成了详细的预测:
来源:先知
准确(性)
现在让我们根据以下内容评估模型的准确性:
- 平均定向精度: 95%
- 均方根误差: 0.1948
- 平均预测误差: 0.1839
下面是测试集的预测价格与实际价格的对比图:
来源:Jupyter 笔记本输出
整个测试集的平均值为 5.93(以对数表示),相比之下,RMSE 和 MAE 相当低(大约为平均值的 3%),表明该模型在预测方面表现良好。由于我们使用的是月度数据,因此不清楚当使用较短的时间范围(例如每小时或每天)时,该模型的表现如何。从这个角度来看,模型预测在预测短期波动方面可能是有限的,但在捕捉总体趋势方面似乎做得相当好。
此外,由于 MDA 为 95%,这表明该模型能够在 95%的时间内预测特定月份的价格方向,这相当不错。
请注意,变点配置对预测准确性有直接影响。例如,当预测中的变点数降低到 4 时,RMSE 达到 0.2840 。虽然这与平均值相比仍然很低,但仍然是用 12 个变点计算的 RMSE 的近两倍。
限制
一般来说,预测资产价格(或任何种类的经济数据)都很棘手。
这是因为资产价格天生受制于反馈回路。例如,假设一个预言家模型在预测铜价方面带来近乎完美的准确性。在这种情况下,更广泛的市场最终将开始使用该模型——假设市场在长期内保持有效——此时,就预测能力而言,竞争优势不再能够获得。
例如,不像天气这样的时间序列——它不能通过人为干预来改变——基于预测的后续交易具有改变价格本身的效果——这意味着以前准确的预测不再准确。
此外,金融时间序列可能会受到干预,这些干预在以前的数据中可能没有被捕捉到。例如,2008 年之前的时间序列数据不会捕捉到美联储将美国利率降至零的情况,因此时间序列本身无法解释如此重大的结构性变化。
当涉及到具体的干预建模时,更有效的方法可能是通过使用因果影响包。这里有一个的例子,说明如何使用这样的工具来模拟利率变化对货币波动的影响。
结论
在这个例子中,我们已经看到,在预测资产价格的长期趋势时,Prophet 可以非常有效,并且在识别重大结构变化点以通知此类预测时特别有效。
非常感谢您的阅读,非常感谢您的任何问题或反馈。
更新:如果你感兴趣,这里有一篇关于这个主题的更新文章,我在其中讨论了如何使用 CNN(卷积神经网络)预测铜价!
预测时间序列数据-股票价格分析
时间数列预测法
重点介绍了使用不同的平滑方法和 Python 中的 ARIMA 对时间序列数据进行预测。
在本文中,我们将浏览某家公司的股票价格。然而,本文并不鼓励任何人仅仅基于这种预测进行交易。股票价格取决于各种因素,如供求关系、公司业绩、投资者情绪等。
什么是时间序列?
时间序列由定期捕获的观察值组成。时间序列数据集具有很强的时间依赖性。它可以用来根据以前的观测结果预测未来的观测结果。
分解时间序列:
时间序列可分为以下几个部分:
趋势: 数据值的增减。这可以进一步分为全球趋势和局部趋势。
实际观察值=全球趋势+当地趋势(来源:UpGrad)
季节性: 系列中可见的是重复模式。数据值的这种上升或下降是固定频率的。例如,圣诞树的销量在 12 月份总是较大,而在其他时间则较少。
周期性: 它是数据的值的上升和下降,不是固定的频率。它可以被看作是经济条件或其他外部因素的结果
噪声: 它只是我们从时间序列中提取趋势和季节成分后得到的一些随机数据。
时间序列的组成部分可以是加法或乘法版本。当季节性模式的幅度随着数据值的增加或减少而增加或减少时,乘法模型是优选的。当季节模式的幅度与数据值不相关时,最好使用加法模型。
加法和乘法季节性——资料来源: kourentzes
在加法版本中,季节性模式的幅度仍然与上升趋势无关,而在乘法版本中,它随着时间序列趋势的增加而增加。
如何获取股价数据?
我们可以通过使用请求包创建一个 API 请求来获取股票价格。我们也可以使用 quandl 包,它被设计用来提供金融和经济数据。
我们将通过创建一个 API 调用从 alphavantage 网站提取美国股票的价格。使用下面的代码片段,我们提取了 IBM 的每日股票价格。您可以参考此链接来更改您的请求需求。
为了使用 quandl 包将数据导入 python,您可能需要安装 quandl 包。输入命令!pip 将 quandl 安装到您的 Jupyter 笔记本中,您就可以开始了。我们已经导入了 Infosys (BOM500209)的价格,并将使用这些价格进行进一步的分析。关于 quandl 以及如何充分利用它的更多文档可以在这里找到。
对于这两种方法,您都需要创建一个 API 键,用于获取数据。你可以通过点击这些链接轻松获得你的 API:alpha vantage和 quandl 。
现在我们已经得到了数据,我们需要绘制它来获得趋势的概貌。
趋势会像股票一样经历一些起伏。这不是季节性的,因为季节性因素并不能提供更清晰的情况。除了一些观察结果,残差的方差似乎保持不变。
检查平稳性
对于 ARIMA,必须使时间序列静止以便进一步分析。对于一个平稳的时间序列,它的统计特性(均值、方差等)在整个序列中都是相同的,与你观察它们的时间无关。平稳的时间序列没有长期可预测的模式,如趋势或季节性。时间图将显示序列大致具有恒定方差的水平趋势。
滚动统计
我们可以绘制滚动平均值和标准偏差,以检查统计数据是呈上升趋势还是下降趋势。如果这些统计数据随时间变化,那么时间序列很可能是非平稳的。
ADF 和 KPSS 试验
为了检验时间序列的平稳性,我们还将使用 ADF (增广的 Dickey-Fuller) 检验和 KPSS (科维亚特科夫斯基-菲利普斯-施密特-辛特斯)检验。ADF 检验的零假设是时间序列不是平稳的,而 KPSS 的零假设是平稳的。
时间序列的平稳性检验
我们可以看到,随着股票价格的上涨和下跌,滚动平均线会随着时间的推移而上升和下降。ADF 检验的 p 值大于 0.05,这意味着我们不能排除零假设。KPSS 检验的 p 值低于 0.05,这意味着我们拒绝零假设。所有这些检验的结论是,时间序列不是平稳的。
时间序列如何去趋势化?
求差:通过对当前时间与其前一时间的实际观测值求差,计算当前时间的值,构造新的序列。
值(t) =实际观察值(t) -实际观察值(t-1)
转换:使用乘方、平方根、对数等转换数值有助于数据线性化。例如,记录这些值有助于获得具有指数趋势的序列的线性趋势。 log(exp(x))=x
季节差异:时间序列的值是通过一个观测值与其前第 n 个观测值之间的差异来计算的。这有助于消除这种趋势
值(t) =实际观察值(t) -实际观察值(t-N)
拟合模型:我们可以用线性回归模型来拟合时间序列。它将符合时间序列的线性趋势。通过用模型预测的值减去实际观测值,可以计算出去趋势时间序列的值。
值(t) =实际值 _ 观察值(t) -预测值(t)
时间序列去趋势化后,ADF 和 KPSS 检验表明时间序列是平稳的。部分自相关函数(PACF)图表明,相关性存在于某些滞后。
分割数据集
列车测试分离
模型结构
为了预测价格,我们可以使用平滑法和 ARIMA 法。平滑方法可用于非平稳数据,而 ARIMA 要求时间序列是平稳的。我们还可以利用 auto_arima ,它使序列平稳,并确定 arima 模型的最佳阶数。
对于每一种方法,我们将对超参数的优化进行多次拟合,并将最优值用于最终模型。
简单指数平滑
当数据不包含任何趋势或季节性时,使用简单指数平滑或 SES。level (α)的平滑因子为观测值的影响提供了权重。α值越大,意味着越重视最近的过去观测,而值越小,表明预测时考虑的过去观测越多。
简单指数平滑
简单指数平滑片段
简单指数平滑预测
霍尔特指数平滑法
霍尔特的指数平滑法在预测时间序列时将趋势考虑在内。当数据中有趋势而没有季节性时使用。它计算平滑值(第一个等式),该值与 SES 中用于预测的值相同。趋势系数(β)为后续平滑值和之前的趋势估计值之间的差异提供权重。预测是平滑值和趋势估计的组合。
霍尔特指数平滑法
霍尔特的指数平滑片段
霍尔特指数平滑预测
霍尔特-温特斯指数平滑法
霍尔特-温特斯指数平滑法在预测时间序列时考虑了趋势和季节性。它使用用于计算时间序列中的水平分量、趋势分量和季节分量的公式来预测这些值。根据数据的季节变化,要么使用加法,要么使用乘法。
加法(来源: otexts
乘法(来源: otexts
自回归综合移动平均(ARIMA)
ARIMA 模型是自回归模型和移动平均模型的结合,并结合了差分法。自回归模型确定了一个观测值和一定数量的滞后观测值之间的关系。积分部分是实际观测值的差值,以使时间序列平稳。移动平均确定观测值和残差之间的关系,残差是通过对滞后观测值使用移动平均模型获得的。
自回归(p) - >模型中滞后观测值的个数。也称为滞后订单。
积分(d) - >实际观测值的平稳性差值的次数。也称为差异程度。
移动平均线(q)——>移动平均线窗口的大小。也称为移动平均的顺序。
ARIMA 片段
ARIMA 天气预报
摘要
为了评估模型的性能,我们将使用均方根误差(RMSE)并比较哪个模型的性能优于其他模型。
RMSE 摘要
在这三个模型中,表现较好的模型是霍尔特的指数平滑法,它获得的 RMSE 最小。
在本文中,我们了解了时间序列及其组件,使用 API 调用和包获取数据,检查时间序列的平稳性,对时间序列进行去趋势化,用不同的类型对时间序列建模,以及最后对其进行评估。
你可以在这里找到笔记本供你参考。
用自回归预测模型预测印度新冠肺炎确诊病例总数
使用自回归预测 COVID 的全部确诊病例
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
作者图片
作为我之前关于新冠肺炎数据端点及其可视化的文章的续篇,这里有一个快速的方法可以让你建立一个简单的时间序列预测模型
对于那些不熟悉什么是时间序列预测的人来说:时间序列是按时间顺序索引(或列出或绘制)的一系列数据点。最常见的是,时间序列是在连续的等间隔时间点取得的序列。在预测设置中,我们发现自己在时间 t,我们对估计 Y(t+h)感兴趣,只使用时间 t 可用的信息。
我个人用过自回归预测模型。自回归是一种时间序列模型,它使用以前时间步长的观测值作为回归方程的输入,来预测下一个时间步长的值。这是一个非常简单的想法,可以导致对一系列时间序列问题的准确预测。
- 和往常一样,我们从导入所需的模块开始
import requests
import pandas as pd
from statsmodels.tsa.ar_model import AR
然后,我们从相应的端点获取所需的数据,并用它来训练自回归模型。
x = requests.get('https://api.covid19api.com/total/country/india/status/confirmed').json()
df = pd.DataFrame.from_dict(x)
model = AR(df['Cases'][:-1])
model_fit = model.fit()
在这里,为了进行培训,我只使用了截至 2020 年 4 月 17 日的数据,以便我可以用它来预测 2020 年 4 月 18 日的确诊病例总数,并将其与实际值进行比较。
现在,为了预测 18–04–2020 的值(即数据列表中的第 87 个值,因此预测值旁边的数字是 87),我已经将开始和结束索引参数作为输入数据的总长度传递给预测函数,这将给出所需预测的索引(即,如果我有 87 个值,则最后一个输入值的索引将是 86,作为开始和结束参数传递的值将是 87,告诉它预测第 87 个值)。
prediction_for_18_04_2020 = model_fit.predict(start=len(df['Cases'][:-1]), end=len(df['Cases'][:-1]))
prediction_for_18_04_2020
这给了我一个大概的预测。15879,非常接近实际值 15722
作者图片
供你参考:
传递自回归模型索引的数据时,将数据作为“['Cases'][:-1]”传递,以便仅传递数据帧的已确认病例列,并且“:-1”用于跳过最后一个值,即日期 18–04–2020 的值。
当你训练一个模型来拟合它时,拟合一个模型意味着在数据中找到一个模式。这就是我在培训过程中使用 model.fit()的原因。
开始和结束参数:这些参数用于定义要预测多少个值。在我的例子中,我为它们传递了相同的数字,因为我只想预测一个值。但是,如果您想让我们预测未来 4 天的确诊病例总数,那么在“开始”中,您将传递从预测开始的时间点的索引,在“结束”中,您将传递到需要预测值的时间点,即,由于您的列表在 86 索引处结束,您可以静态地传递“开始”作为 87,传递“结束”作为 90,或者如果您想要传递它 动态地在“开始”发送数据的长度,然后在“结束”传递总长度+ 3,这将会给你相同的结果
关于 statsmodels AR()库需要注意的一点是,它很难以“在线”方式使用(例如,训练一个模型,然后在新数据点出现时添加它们)。您需要根据添加的新数据点重新训练您的模型,或者只保存模型中的系数并根据需要预测您自己的值。
你可以在这里找到我的代码:
[## nischalmadiraju/新冠肺炎-用印度数据进行自回归预测
通过创建一个帐户,为 nischalmadiraju/新冠肺炎-用印度数据进行自回归预测的发展做出贡献…
github.com](https://github.com/nischalmadiraju/COVID-19-Autoregression-forecasting-with-indian-Data)
请随意浏览,如果您想让我介绍其他内容,也请在评论中告诉我
预测战争:经典预测方法与机器学习
我们将使用来自 kaggle 竞赛的数据 M5 预测-准确性。
任务是尽可能精确地预测沃尔玛在美国销售的各种产品的单位销售(需求)。
更准确地说,我们必须预测未来 28 天的日销售额。该数据涵盖了美国三个州(加利福尼亚州、德克萨斯州和威斯康星州)的商店,包括商品级别、部门、产品类别和商店详细信息。
数据是巨大的,对于这个演示,我将使用其中的一个子集,一个来自销售数据集中的产品。
我们的目标是将经典的时间序列分析技术与机器学习算法进行比较。
所有代码都可以在 GitHub 上获得。
谁会更好地预测未来?
竞争对手:
- 简单指数平滑
- 双指数平滑
- 三重指数平滑
- ARIMA
- 萨里玛
- 萨里马克斯
- 光梯度增强
- 随机森林
- 线性回归
下注吧!
加载要使用的包。
读取数据。
数据集的前 5 行。
要预测的目标变量是需求(该产品在该日期将售出多少件)。
日期从 2011 年 1 月 29 日到 2016 年 5 月 22 日,总共 1941 天。后 28 天是竞赛 _ 测试集,按照竞赛的指示,所以我们不知道需求(等于 0)。
为了训练和验证模型,我将数据分成两部分:训练和测试。测试装置不应与竞赛测试装置混淆。
测试集将具有与测试 competition_test 相同的长度,以模拟相同的条件。因此,它将由 2016 年 3 月 27 日和 2016 年 4 月 24 日(28 天)之间的日期组成。训练集将是所有其他先前的值。
从初始数据中分离出训练测试。
时间序列(训练-测试)线图。
我们有很多训练数据,过去 28 天是测试集。我们的目标是使用以前的值来预测它们。
接下来,我将创建一个预测数据帧来存储所有模型的预测。每个模型将是该数据框架中的一列。另外,一个 stats dataframe 存储每个模型的性能和执行时间。
训练和评估模型
我们将从简单的传统预测模型开始。不要低估他们。
简单指数平滑
这是简单移动平均的一种变体,称为指数加权移动平均(EWMA)或简单霍尔特-温特斯法。用于将其加载到 Python 的包称为 SimpleExpSmoothing。我们必须定义一个名为 span 的参数,它将等于数据集的季节周期。
自相关。
每个值与多达 60 个以前的滞后进行比较。
从自相关图中,我们可以清楚地看到,每 7 个滞后就有一个相关性峰值。这意味着当天的值和之前 7 天的值具有很高的相关性。我将设置 span 等于 7。经过训练,使用。预测(x) ,x=28 天,模型预测未来 28 天。将使用均方根误差进行评估。
简单的指数平滑。
简单指数平滑的性能。
那些投票支持简单指数平滑的人确实会失望。然而,让我们以 RMSE 为基准。
双指数平滑
简单指数平滑仅使用一个平滑因子α (alpha ),而双指数平滑添加了第二个平滑因子β (beta ),用于处理数据趋势。我们必须定义季节周期。
双重指数平滑。
双指数平滑的性能。
比 SES 好,但还是直线。我们能做得更好吗?
三重指数平滑
与霍尔特-温特斯最密切相关的三重指数平滑法增加了对数据中趋势和季节性的支持。
三重指数平滑。
三重指数平滑的性能。
现在我们正在做一些事情!TES 很好地捕捉到了数据的季节性,并且几乎总是接近测试数据。缺点是我们必须输入季节周期的数量。如果这个数字不是 7,性能会变差。
ARIMA
一个 ARIMA 模型由三部分组成:p,d,q
- p 是 AR 项的阶数。它是指用作预测值的 Y 的滞后数。
- q 是 MA 项的阶数。它是指应该进入 ARIMA 模型的滞后预测误差的数量。
- d 是使时间序列平稳所需的差分次数
自动选择 ARIMA 参数
我们将使用优秀的 auto_arima 包,它会自动发现 arima 模型的最佳订单。
让我们忽略季节性。如果我们加上季节性,这个模型将是 SARIMA,这将在后面讨论。
arima 的 auto_arima 结果。
ARIMA。
ARIMA 的表演。
这里使用的简单 ARIMA 模型没有考虑季节性。这是一个(5,1,3)模型。这意味着它使用 5 个滞后来预测当前值。涉及滞后预测误差数量的移动窗口的大小等于 1。使时间序列平稳所需的差值为 3。
该模型的性能比三重指数平滑法差。
萨里玛
它是 ARIMA 的扩展,接受一组额外的参数,专门描述模型的季节组成部分。
与 ARIMA 相比,我们将使用 2 个额外的参数:季节性=真实值和 m=7 。我们现在考虑季节性,并对模型说它等于 7。Auto_arima 运行的时间要长得多。
SARIMA 的 auto_arima 结果。
萨里玛。
萨里玛的表演。
这比简单的 ARIMA 好得多,事实上也比三重指数平滑法好得多!
萨里马克斯
使用以前的方法,我们唯一可以使用的数据是以前的历史数据。带有外生回归的季节性自回归综合移动平均引入了外部特征可以影响时间序列的思想。
我们将添加数据集的另一个特征,即 sell_price ,以帮助模型,并有望做出更好的预测。
萨里麦克斯。
SARIMAX 的 auto_arima 结果。
SARIMAX 的性能。
SARIMAX 运行时间更长。额外的功能减少了误差!
机器学习
机器学习模型,不能仅仅通过它本身以前的值来预测目标。他们需要特色。这就是我们将要做的,构造一些特征。
目标先前值的所有信息都将丢失。我们将创建要素来维护这些信息。
史上最大的 github gist。
数据集的前 5 行。
我将创建的功能相对较少且简单。
- 滞后 7:提前 7 天的需求值
- 滚动平均值 7_7:在滞后 7 上,计算前 7 天的滚动平均值。这意味着我们现在回到了 14 天前。
当滞后 7 捕获一天时,滚动平均 7 在单个特征中捕获关于 7 天的信息。
有人可能会想,哦,那么我们为什么不为每个滞后创建一个特征呢?滞后 1,2,3,..1885,..?我们可以创建一些,如滞后 6 和 8(我们看到它们在自相关图中很强),或滞后 14,30。然而,增加数据集的维度将是一个严重的问题。RAM 过载、巨大的执行时间、过拟合、相关性。
创建的其他功能包括:
- 每月需求平均值,最大值,最大值到最小值差值。这捕获了信息:该产品在 12 月、4 月等的平均销售额是多少。
- 每天每周平均值、中值、最大值
创建特征的函数。
为 ML 准备数据。
适合模型
适合三个 ML 模型。
使用滑动窗口通过模型进行预测
这部分需要更多的关注。我会解释的。
测试集由 28 天组成。假设是第 1,2,3…,28 天。还记得我们为训练集创建的特性 lag_7 吗?显然,我们将为测试集创建相同的特性。当我们为测试集的第一天创建这个特性时,它被创建得非常好。它提前 7 天(在训练集中)并复制该值。如果我们在第 10 天创建这个特性,它会提前 7 天。这是测试的第三天。我们不知道它的价值!
所以我们做了一个滑动窗口,一次向前移动一天。在每次迭代中,我们预测今天的价值。所以我们用我们的预测来填充测试集。当我们到达测试集中的第 10 天时,我们将具有先前的值,并且可以计算 lag7。
等等,你为什么使用长度为 15 的滑动窗口(max_lags=15)?功能 lag 7 需要至少提前 7 天的样本。特征滚动平均 7_7 需要提前 14 天。因此,为了成功创建要素,最小窗口大小应为 14。如果我们增加窗口的大小,它不会影响这些功能。他们不使用早期的值。但如果我们增加它,那么它将影响其他功能(每月平均需求等)。我尝试过增加它,但 rmse 减少了一点,执行时间增加了一点。
预测未知未来的滑动窗口技术。
光梯度增强
我调整了算法的参数以获得更好的性能。
光梯度增强。
光梯度增强的性能。
啊,LightGB...它从不让人失望。(但是,不要盲目的用在每个问题上。)
随机森林
我调整了树的最大深度以获得更好的性能。
随机森林。
随机森林的性能。
随机森林的表现也很好。
线性回归
线性回归。
线性回归的性能。
好老线性回归在这里是极好的!
所有竞争者的执行时间和 RMSE。
传统的预测方法要慢得多。
每个模型的均方根误差。越低越好。
在我们分析的最后,我可以说这只是一个基线实验。当然,可以创建更多的特征,然后通过特征选择技术来选择最佳数量,可以进行更多的超参数调整,这样的例子不胜枚举。
那么 ML 方法是否优于经典的时间序列预测方法呢?
也许是
这当然取决于问题。机器学习方法需要特征。如果我们只有时间序列的值,那么我们能够创建的唯一特征就是基于它们。这些将是滞后,移动平均线等,所以我们可以包括尽可能多的信息,而不需要做太多的栏目。只有 6 个特征的线性回归优于所有经典方法。通过特征工程使 ML 方法变得更好是数据科学家的职责。突出算法的不一定是模型,而是提供给算法的数据。
所以带 LightGB 的 ML 机型赢了战斗,但没打赢战争。
用 Python 和 Google Analytics 预测网络流量
实践教程
向业务经理展示未来:一步一步地创建 web 流量的时间序列预测,绘制成 GIF 图。
最终的结果是:一个美丽的图表描绘了我的 12 月份的交通会有多糟糕。
SolarPanelCompany 决定雇佣他们的第一个数据科学家:我。我对从零开始构建一切的挑战感到非常兴奋。我的目标是获得第一场速战速决的胜利,向车队展示我的价值。
第一周,一位营销经理惊慌失措地来到你的办公桌前:“你看!”他指着笔记本电脑的屏幕说,“在谷歌分析上,我看到我们的流量在上个月下降了!你的预测数据学习材料能做些什么来拯救企业吗?”。
“好吧,”我想“这不是真正的问题。”所以我换了一种说法:“你是在要求我证明我们是有下降趋势,还是只是季节性效应?”。他茫然地凝视着。“你是在问我,我们什么时候能希望它回升?—是的!正是如此!我明天和市场总监有个会议。我让你在那上面工作!”
如果这种情况发生在你身上,或者如果你想创建自己的网站流量的可视化预测,你就在正确的页面上!下面是的一步一步的指导,根据你的谷歌分析数据预测你网站的访客数量,作为奖励,让它成为商业人士喜欢的 GIF。简而言之,我们将使用 Prophet 包创建一个时间序列模型。
本指南包括 3 个步骤:
- 用 Python 调用您的 Google Analytics API 数据
- 使用 Prophet 构建您的模型
- 制作你的预测的 GIF 图(因为它很有趣)
1.连接到您的 Google Analytics API
这一步需要:谷歌分析帐户的管理员权限。如果你没有,你可以用一个 演示谷歌分析账号 然后简单的导入 csv 格式的数据。
这不是一个容易的步骤,但是 Google 创建了很多文档来帮助你完成。我将在这里提出一步一步的指南来获取流量。如果你对其他指标感兴趣(比如目标、浏览量等。)你需要看一看内容广泛的官方 Google 的管理 API 文档。
让我们导入我们的包:
第一个包裹是我们永远的朋友熊猫。最后两个包来自 Google,允许您调用 Google Analytics API。
如果你还没有访问 Google API 的权限,你需要在你这边激活它。下面的视频解释了这样做的所有步骤。
所以让我们开始开心吧。我们的第一段代码是调用键和右视图。请注意,您可以在谷歌分析账户的“设置>查看”中找到查看次数
在上面的部分中,第一行没有改变,但是第二行和第三行必须用你自己的访问键来改变。
现在我们将使用 Google API 文档中的代码。如果你不完全理解,没关系:如果你适当地修改了上面的段落,复制粘贴就可以了。
我们可以看到上面提到的“度量标准”。在我这边,因为我想做一个时间序列,所以我只关心流量维度,但也导入页面视图供以后分析。
这些代码块是谷歌为愿意获取他们数据的人提供的标准代码。
好了,现在你的数据在数据框中了。恭喜你!你成功调用了 Google API,第一步就实现了。
2.预测你的网络流量
所以我们有数据。这已经花了一些时间,但现在是有趣的部分:预测 SolarPanelCompany 的网络流量。
迈克尔·威尔森在 Unsplash 上的照片
为了开始预测谷歌分析流量,我们需要开始导入我们的包。我们将在这里使用脸书的先知。这个伟大的工具非常容易使用,因为它使用了与软件包 scikit 相同的语法。脸书自己使用他们所有的时间序列预测,无论是网络流量或其他。
让我们先探索一下,并检查我们的数据是如何做的。一个简单的情节就完成了任务。
我们已经可以在数据中看到很强的季节性。的确,这是关于太阳能电池板的数据。因此,季节性是可以预料的:随着阳光越来越强烈,它从 2 月到 7 月平稳生长。然后,到了八月,人们知道享受阳光已经太晚了,队伍就下降了。
回到我们的代码,让我们看看先知说了什么。脸书的先知要求你改变你的两个专栏的名字:
- 值列需要称为‘y’
- 时间戳需要是‘ds’并且是一个日期时间变量。
2.1 缺失数据
尽管脸书声称 Prophet 对缺失数据和异常值有很好的抵抗力,但去掉它们也未尝不可。尤其是在我们这种情况下:假设网站的跟踪崩溃了一两天,你不希望这个影响。
如果你有一些丢失的数据,就像我一样,你将把它们输入到一个新的数据框架中。您还需要给它赋值。我个人用的是 7 天均线。
然后我们把框架连接在一起,放上一个盖子和一个地板。楼层是“0 ”,因为你知道你不会有负流量。另一方面,cap 纯粹是“人在回路中”的工作,所以基于你的良好判断。这个顶部和底部将有助于创建模型的边界。
2.2 EDA
那会很快,因为我们没有那么多的功能;只有观察本身的价值。
我们看到,丢失的数据中不再有离群值,我们可以继续保留。
2.3 预测我们的网络流量:培训
用 Prophet 训练模型真的很简单。该团队复制了 scikit 软件包所使用的机制:。fit()和。预测()
创建模型
所以首先我们创建模型。有许多变化可以添加。下面我会解释我的选择。
- Changepoint_prior_scale:应对欠拟合。增加使趋势更加灵活(因此在视觉上扩大了终端漏斗)
- Changepoint_range:默认情况下,Prophet 只改变前 80%数据的趋势斜率。我在这里将它设置为 0.9,以包含 90%的数据。
- 季节性模式= '乘法'作为参数,因为季节性的影响越来越大。我们清楚地看到,我们的业务正在呈倍增趋势增长,而不是呈线性增长。
- 每年.季节性= 20。它是 10,但我想要更多。这个数字代表傅立叶级数。
如果你想在不同的标准下改编你的模型,我推荐看看脸书的先知 Github。
2.3.2 构建预测时间戳集合。
到目前为止,我们已经根据以前的数据训练了我们的模型。为了预测未来的 web 流量,我们首先需要创建未来的时间戳。在这里我将创造 60 天,也就是未来的两个月。
2.3.3 预测未来
开始了。在接下来的两行中,我们将通过 Google Analytics 预测我们的网站流量。
瞧!11 月和 12 月可以看到我的交通跳崖之美。
分析组件
现在 Prophet 有了另一个伟大的功能:它可以在一个图形中显示不同的组件。
已经有了一些有趣的结论:
- 总趋势是下降。要知道,我的增长是成倍增长的,因此 2020 年秋季将趋势大幅向下推。
- 每周趋势:周四到周六是最糟糕的时刻。如果我想做广告,周日是个好时机。
- 年度:非常有见地。我们可以在八月一日看到顶峰。另外,我们可以看到圣诞节搜索并没有带来多少收入。所以硕果累累的时期是 4 月到 10 月底。
这已经是一些很好的见解,我可以反馈给营销经理。我不仅可以建议他们应该花更多的广告预算,而且我还可以确认,是的,看到我们的流量下降是正常的。而且要到二月份才会恢复。
同样有趣的是将总体趋势与数据进行比较。我们可以在这里看到趋势的变化。
红线横线是趋势。红色虚线是趋势改变的点。
2.4 测试模型
太好了,现在我们已经完成了预测谷歌分析流量的大部分工作。但作为严谨的数据科学家,我们也想测试模型。
时间序列的测试与传统模型略有不同。我们需要使用滚动窗口:滚动窗口意味着使用 60 天的数据,并评估它对未来 30 天数据的预测能力。
例如,在上面的图表中,红色部分用于预测绿色部分。在交叉验证后,红色部分将向前移动,以适应下一个 60 天,并再次预测下一个 30 天。这就是滚动窗户的概念。关于滚动窗口的文章已经够多了,所以我就不再赘述了。
就编码而言,它是这样写:
RMSE 在地平线上密谋
我们在这里。我们现在有了白天地平线上的 RMSE。我们可以看到,视野越远,误差越大。
现在为了你自己的工作,你可以玩模型的超参数来试着把这个推下去。因为我们使用这个图表是为了营销目的,而不是为了工程目的,这样的 RMSE 已经足够好了。
3.形象化
所以在第一部分,我获取了我的数据,在第二部分,我创建了模型。现在,是时候让它变得更好,让营销经理和 CMO 对此感到兴奋了。人类真理:有令人愉快的东西看会使它更有价值,所以是时候让我的工作有价值了。
纯粹为了吸引注意力,我创造了一个 GIF 图片。这种动画真的可以吸引人们的注意力,从而引起利益相关者对我的项目的兴趣。
3.1 数据绘图
让我们从导入包开始:
我们希望它朗朗上口,所以我们将直接从一个时尚的元素开始:深色背景。
黑色背景上的网络流量数据
非常好的效果。现在让我们画出我们的预测。
3.2 将预测绘制成 GIF
我们首先需要创建一个包含数据和预测的数据框架。
好了,这是容易的部分,现在我们将有大块来创建我们的 GIF。要在这里继续,一定要安装 PillowWriter 或 Imagemagick,它们可以将你的图像转换成 GIF 格式。
经典的 fig,ax matplotlib 操作的不同之处在于,我们需要创建函数来为图表制作动画。
ax.clear()操作超级重要。如果你像我一样没有把它放进去,动画会在之前的图形上创建一个新的图形。不可怕,除非..每个新图都有一种新的颜色。最终的动画将是一个快速闪烁的图形,每四分之一秒改变一次颜色。足以杀死癫痫患者。
一个艺术上的失败:我丢失了 90%的数据,创建了一个“派对”图,让人看了恶心。
请注意,如果您在笔记本中工作,您将不会在图表中看到动画。你必须下载创建的“animation_video.gif”才能真正看到动画。
你在这里,为你的长时间工作感到自豪,并准备好用你令人惊叹的动画震撼舞台。你现在可以知道你的企业的未来是什么样子了!
结论
从 Google Analytics API 获取数据后,我可以在 GIF 中绘制未来网络流量的时间序列。
这个视觉上吸引人的结果帮助营销经理和 CMO 明白,是的,如果流量在冬天下降是正常的。是的,它会在春天重新生长,那时太阳会回来,人们会考虑太阳能投资。
猜猜哪家公司开始加大对其数据团队的投资。
更进一步
你的业务经理不明白预测是如何工作的,也不明白你是如何工作的?你可能对如何向经理们解释预测建模感兴趣
附录
Jupyter 笔记本:https://github . com/Arthur mro/Prediction _ marketing/blob/master/Prophet _ GA _ cs _ info . ipynb
从多个数值天气预报预测风力
数据科学技术在可再生能源领域的应用。
随着美国和整个欧洲对风能生产重新产生兴趣,现在是重新审视可再生能源的可变性和可预测性等重要因素的时候了。
在本文中,我将讨论以下内容:
- 风能的可变性和可预测性
- 使用多种天气预测的挑战
- 处理混乱天气数据的技巧
- 特征工程
- 风电功率预测的非时间序列方法
风能的可变性和可预测性
可靠的能源需要具有低可变性和高可预测性。虽然适度的变化是可以容忍的,但不良的可预测性是不可接受的,并可能导致巨大的收入损失。
风能的可变性是由于对天气的强烈依赖,而天气在一天中会随季节而变化。因此,准确的天气预报对于实现有用的风力预测是必要的。
众所周知,天气预报的准确性随着预报范围的缩短而提高。此外,结合使用不同数值技术的模型预测可能是有益的。因此,风电场依赖于在一天或一周的不同时间生成的模型中的多种天气预测来源。
虽然天气无法控制,但风能行业可以利用人工智能技术的进步来提高能源的可预测性。
使用多种天气预测的挑战
我们来讨论一下在风力发电预测中使用多种天气预测时遇到的一些挑战。
- 不同高度可预测变量 :
风速随高度变化。不同的模型可能提供不同高度的速度数据,这使得在没有额外的风电场特定参数或公式的情况下,很难推断出跨模型的缺失值。 - 推断时间大量缺失数据 :
天气数据可能由不同时间生成的不同模型的预测组成。每一列可能有几个缺失的数据,因为在风力发电预测时并非所有的天气预测都是可用的。这种缺失数据不能通过简单的已知策略来估算,例如所有观察值的列平均值或行删除。
样本训练和测试数据中缺失的值在下面以黄色显示。
作者图片
作者图片
处理杂乱天气数据的技巧
下面概述了一些处理来自多个模型和不同时间的天气数据的技巧。
- 用来自同一模型的最近可用预测的平均值填充缺失值(按列,比如最近三个小时内)。
- 从最近可用的预测开始,用模型间的平均值填充其他缺失值。
- 如果仍然有更多的缺失值,使用风电场特定的参数和标准公式将风速从一个已知高度映射到另一个缺失速度的高度。
- 在一天的不同时间获得的天气预测可以由模型聚合,以减少特征空间和缺失值的数量。
- 为了生产中机器学习模型的健壮性,在数据管道中实现至少两个上述技巧是很重要的。
- 最后,如果剩余任何缺失值,则可以应用标准的行移除过程。
特征工程应该为每个模型计算这个变量。
添加不同高度的速度大小的标准偏差等特征可以提高预测精度。此外,根据来自多个风电场的一次性编码数据训练模型可能会比根据来自每个风电场的较少数据集单独训练产生更好的结果。
与风电场运行相关的重要特征,如在用涡轮机的比例,可以提高预测性能。该特性不适用于本文中的预测示例。因此,即使在风力发电场似乎要关闭时,也能获得一些电力预测。
Sweetviz 库用于探索变量分布和变量之间的关系。分布可以在这里找到,变量之间的关联如下所示:
图片由作者使用 sweetviz 库提供
速度幅度显示了与目标变量(产生的功率)的最强关联,如基于流体动力学领域的科学知识所预期的。这强调了在将数据驱动的解决方案应用于工程问题时,物理学的重要性。
预测风力发电的非时间序列方法
虽然从涡轮机或风电场产生的风力发电是具有一些季节性的时间序列,但是可以在不使用来自目标变量的滞后特征的情况下进行预测。此外,这种方法是稳健的,比时间序列方法更容易实施。
对应于测试集的功率生产不可用。因此,根据训练数据创建验证集来评估模型性能。新的训练集是原始训练数据的 80 %,数据中的每个观察值代表一个由名为 ID 的特征索引的每小时报告。
XGBoost 算法用于预测六个风电场的每小时风力发电量。累积绝对百分比误差(CAPE)用于评估模型性能。
def cape_func(y_true, y_pred):
return 100*np.sum(np.abs(y_pred-y_true))/np.sum(y_true)
六个不同风电场的风力(MW)与 ID(每小时产生的风力指数)的曲线图如下所示。
作者图片
作者图片
作者图片
作者图片
作者图片
作者图片
模型的性能在不同的风力发电场之间有明显的差异,这表明有一些特定于风力发电场的变量可能会改善预测。此类变量的示例包括预测时正在使用的风力涡轮机的比例和总装机容量。
风电场 6 获得了最佳性能,其 CAPE 值为 21.7%。这个预报例子的 Jupyter 实验室代码包括混乱的天气数据清理可以在这里找到。
接下来的步骤
将使用此处描述的非时间序列方法实施人工神经网络算法,并与 XGBoost 结果进行比较。此外,将研究使用长短期记忆(LSTM)算法的时间序列方法。此外,时间序列和非时间序列方法的所有模型都将使用 CAPE 指标进行评估。
结论
讨论了风能的可变性和可预测性以及在风力发电预测中使用多种数值天气预测的基础。
需要小心处理大量缺失数据和预测变量高度的不匹配,并提供了一些应对挑战的技巧。
此外,在将数据驱动的解决方案应用于工程问题时,相关物理学知识也至关重要。
最后,在不使用基于目标的滞后特征的情况下,使用数值天气预测和风电场特定变量来预测风力。
什么更有趣?你可以通过我下面的推荐链接订阅 Medium 来获得更多我和其他作者的启发性文章,这也支持我的写作。
阅读 Abiodun Olaoye(以及媒体上成千上万的其他作家)的每一个故事。您的会员费直接支持…
aolaoye.medium.com](https://aolaoye.medium.com/membership)
资源
- Bertrand,f ., 强大的 EDA(探索性数据分析)只用两行代码使用 Sweetviz
- 数据来源:https://challengedata.ens.fr/participants/challenges/34/
用随机模型预测
使用 ARIMA 模型预测沃尔玛的销售数据
我们都想知道未来。想象一下,如果我们知道未来会发生什么,我们会拥有多大的力量,我们可以改变它以获得更合适的结果,为财务收益打赌,甚至更好地制定预算。虽然我们不能完全确定未来会发生什么,但我们可以对未来可能发生的事情建立某种直觉。
我们经常从自我提升的倡导者那里听到,通过反思我们过去的行为,我们可以区分我们是如何到达我们现在的人生阶段的。因此,在某种程度上,我们可以预测我们的生活轨迹,如果我们继续在特定的道路上。这是时间序列分析的精髓。如 Adhikari,R .和 Agrawal,R. (2013)所述。关于时间序列建模和预测的介绍性研究,“时间序列建模的主要目的是仔细收集和严格研究一个时间序列的过去观测值,以开发一个描述该序列内在结构的合适模型。然后,该模型用于生成序列的未来值,即进行预测。因此,时间序列预测可以被称为通过了解过去来预测未来的行为
“现在是过去决定的积累”——未知
一个流行的和经常使用的随机时间序列模型是 ARIMA 模型。它假设时间序列是线性的,遵循特定的已知统计分布,如正态分布,并具有其他模型的子类,如自回归(ar)模型、移动平均(MA)模型和 ARIMA 模型所基于的自回归移动平均(ARMA)模型。在有效地将 ARIMA 模型应用于一个问题之前,我们应该了解一些关于我们的数据的事情,你会在这篇文章结束时明白的。
需要知道的事情——时间序列的 4 个主要组成部分:
趋势 →一个时间序列在很长一段时间内增加、减少或停滞的倾向。
季节性 →一年内有规律且可预测的波动。
周期性 →周期性重复的系列中期变化。
不规则性 →不可预测的不规则影响,不会以特定模式重复。
数据
要下载数据,点击此链接并按照说明进行操作。
我将在本文中使用的数据来自 Kaggle 上的 M5 预测准确性竞赛,该竞赛目前仍在进行中(在撰写本文时)。这场比赛向竞争对手提出了挑战,他们已经获得了来自 3 个不同州(加利福尼亚州、德克萨斯州和威斯康星州)的分层销售数据,以预测未来 28 天的销售情况。要访问本文中生成的代码,可以在我创建的 Kaggle 笔记本上找到,可以在这里或下面的链接中找到。
使用 Kaggle 笔记本探索和运行机器学习代码|使用来自 M5 预测的数据-准确性
www.kaggle.com](https://www.kaggle.com/kurtispykes/a-look-at-arima-model-for-forecasting)
下面是我们必须导入的框架,以执行手头的任务。
import numpy as np
import pandas as pdimport matplotlib.pyplot as plt
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacffrom statsmodels.tsa.arima_model import ARIMA
from statsmodels.tsa.stattools import adfuller
我对数据做了一些预处理,以利用它的层次结构。
# store of the sales data columns
d_cols = full_df.columns[full_df.columns.str.contains("d_")]# group columns by store_id
df= full_df.groupby(full_df["store_id"]).sum()[d_cols].T
df.head()
图 2:按 store_id 分组的数据
本次竞赛基于 RMSE(均方根比例误差)进行评估,RMSE 源自 MASE ( 平均绝对比例误差),MASE 设计为不变且对称,您可以在此处了解更多关于预测准确度指标(本次竞赛的不同之处在于,MASE 中的 A(绝对)替换为均方差的 S(平方),我们取 RMSE 的根)。
平稳性概念
理解平稳性的概念是很重要的,因为它对我们可以用数据来预测未来值的模型类型有很大的影响。当一个时间序列的性质不依赖于该序列被观察的时间时,我们称之为平稳的。平稳性的一些标准如下:
- 时间序列中的常数均值
- 时间序列中的恒定方差
- 没有季节性
简而言之,从长期来看,一个稳定的时间序列没有可预测的模式。对于数学家来说,当联合分布在一段时间内保持不变时,就知道随机过程是平稳的。让我们看看数据中的一些随机项目,看看它们是否是平稳的。
ARMA 模型是自回归模型和移动平均模型的组合。这种传统方法要求数据是静态的,然而,在现实世界中,事情并不总是像我们预期的那样发展。事实上,在现实世界中,数据更有可能是非平稳的,因此诞生了 ARIMA,它使用一种称为差分的巧妙技术来使非平稳数据平稳。
区别
差异计算原始序列中连续观测值之间的变化,这有助于稳定平均值,因为它消除了序列水平的变化,这具有消除(或减少)季节性和趋势的效果。这种技术广泛用于非平稳数据,如金融和经济数据。ARIMA 模型采用差分技术将非平稳时间序列转换为平稳时间序列。我们可以用数学方法表示差分数列,如图 2 所示。
图 2:第一个区别
当差分数据看起来不稳定时,我们可以进行第二次差分——在实践中几乎不需要超过第二阶——这可以用数学方法表示在图 3 中。
图 3:二阶一阶差分公式。
我们还可以得到同一季节的一个观测值和另一个观测值的差异。这种现象被称为季节差异。
图 4:一级季节性差异公式
有时,我们可能需要取普通的差值(这是我们在图 2 中讨论的差分技术。被称为第一差异,意思是滞后 1)和季节差异,使我们的数据平稳。
图 5:第一差异和季节差异的公式
在 python 中,我们可以使用可视化和/或单位根测试来确定我们的数据是否需要差分——没有其他方法来确定平稳性。有许多不同的单位根检验有不同的假设,但我们将使用迪基-富勒。下面我将想象一个商店,并在你看 dickey-fuller 测试的结果之前,尝试确定你是否认为它是稳定的。
图 6:每个商店的总销售额——注意,我已经照亮了商店“CA_1”。在笔记本中,你可以点击任何一家你想照亮的商店,或者同时想象它们。
# Dickey-fuller statistical test
def ad_fuller(timeseries: pd.DataFrame, significance_level= 0.05):
non_stationary_cols= []
stationary_cols= []
for col in timeseries.columns:
dftest= adfuller(df[col], autolag="AIC")
if dftest[1] < significance_level:
non_stationary_cols.append(
{col:{"Test Statistic": dftest[0],
"p-value": dftest[1],
"# Lags": dftest[2],
"# Observations": dftest[3],
"Critical Values": dftest[4],
"Stationary": False}})
else:
stationary_cols.append(
{col:{"Test Statistic": dftest[0],
"p-value": dftest[1],
"# Lags": dftest[2],
"# Observations": dftest[3],
"Critical Values": dftest[4],
"Stationary": True}})
return non_stationary_cols, stationary_colsnon_stationary_cols, stationary_cols= ad_fuller(df[stores])
len(non_stationary_cols), len(stationary_cols)
>>>> (10, 0) non_stationary_cols[0]
图 7:商店 CA_1 的扩充 DIckey-Fuller 结果。
p 值大于我们设定的显著性水平(0.05),因此我们不拒绝数据中存在单位根的零假设。换句话说,我们的数据是不稳定的——它不符合我们上面描述的平稳性标准,因此我们必须做一些差分来使我们的数据变得稳定。熊猫有一个很酷的功能DataFrame.diff()
为我们做到这一点——你可以在这里的文档中读到更多。
# making the data stationary
df["lag-1_CA_1"]= df["CA_1"].diff().fillna(df["CA_1"])
ACF 和 PACF 图
ARIMA 模型具有必须定义的超参数 p、d 和 q。自相关函数(ACF)和偏自相关函数(PACF)图使确定模型的 p 和 q 阶变得更加容易。
ACF 图显示了时间序列的自相关性,这意味着我们可以测量 y_t 和 y_{t-k}之间的关系。最简单的方法是把它作为一个时间序列和它本身的滞后之间的相关系数。
注:“y_t”表示下标。
PACF 图显示了消除滞后效应后 y_t 和 y_{t-k}之间的关系。如果我们想到相关性,就是变量的相互依赖。“部分”相关性指的是它们之间的相关性,这种相关性不能用它们与一组特定的其他变量的相互相关性来解释。当我们对自相关进行调整时,我们说的是时间序列和滞后本身之间的相关性,这种相关性不能用较低阶滞后的相关性来解释。
这是了解 ACF 和 PACF 地块的绝佳资源。
让我们看看我们的一些可视化…
_, ax= plt.subplots(1, 2, figsize= (10,8))
plot_acf(df["lag-1_CA_1"], lags=10, ax=ax[0]), plot_pacf(df["lag-1_CA_1"], lags=10, ax=ax[1])
plt.show()
图 8:lag-1 _ CA _ 1 的自相关函数和偏自相关函数;正如在确定 ARIMA 模型中 AR 和 MA 项的阶次中所述,仅通过检查 PACF,您就可以确定需要使用多少 AR 项来解释时间序列中的自相关模式:如果偏自相关在滞后 k 处显著,而在任何更高阶滞后处不显著——即,如果 PACF 在滞后 k 处“截止”——那么这表明您应该尝试拟合 k 阶的自回归模型;
这表明我们应该尝试用 AR(8)模型来拟合我们的数据,我已经在下一节中这样做了。
滞后/后移符号
滞后/后移记数法是一种非常有用的记数方法。不同的来源使用不同的符号来表示滞后 L 或后移 b。
图 9:后移运算符符号
自回归 AR(p)模型通过使用变量的过去变量的线性组合来生成预测。我们可以认为自回归是变量对自身的回归。
图 10:自回归模型(没有滞后/后移符号)
另一方面,移动平均 MA(q)模型在类似回归的模型中使用过去的预测误差而不是过去的值。因此,我们可以把每个预测值看作是过去几个预测误差的加权移动平均。
图 11:移动平均模型(没有后移符号)
ARIMA 模式
条条大路通这一点。如果我们结合差分,我们的自回归模型和移动平均模型,我们得到 ARIMA(p,d,q)。
图 12: Arima 公式。资料来源:Hyndman,R.J .,& Athanasopoulos,G. (2018) 预测:原则与实践,第二版,OTexts:澳洲墨尔本。OTexts.com/fpp2.2020 年 9 月 6 日访问
注意,用滞后符号来表示 ARIMA 模型通常要容易得多。你可以在这里了解更多关于如何做这件事的。
p =模型的自回归部分的阶
d =我们的模型中的一阶差分的程度
q =模型的移动平均部分的顺序
图 13:ARIMA 的特殊情况。资料来源:Hyndman,R.J .,& Athanasopoulos,G. (2018) 预测:原则与实践,第二版,OTexts:澳大利亚墨尔本。OTexts.com/fpp2。于 2020 年 9 月 6 日访问
# fitting the model
model= ARIMA(df["lag-1_CA_1"], order=(8,1,0))
results= model.fit(disp=-1)# visualizing the fitted values
fig= go.Figure(data=
[go.Scatter(x= df["date"],
y= df["lag-1_CA_1"],
name= "original",
showlegend=True,
marker=dict(color="blue"))])
fig.add_trace(
go.Scatter(x= df["date"],
y=results.fittedvalues,
name= "fitted values",
showlegend= True,
marker=dict(color="red")))
fig.update_layout(
title="Fitted values",
xaxis_title="Dates",
yaxis_title="Units Sold",
font=dict(
family="Arial, monospace",
size=14,
color="#7f7f7f"
)
)
fig.show()
图 14:ARIMA 模型的拟合值。
我们可以仔细看看…
# a closer look
_, ax= plt.subplots(figsize=(12,8))
results.plot_predict(1799, 1940, dynamic=False, ax=ax)
plt.show()
图 15:实际值与预测值的对比
为了了解我们如何与实际预测进行对比,我们必须首先回到数据的原始规模进行比较。我们可以在 pandas 中使用一个有用的cumsum()
函数— 文档。
compare_df= pd.DataFrame({"actual": df["CA_1"],
"predictions": pd.Series(results.fittedvalues.cumsum(), copy=True),
"d": df["d"]}).set_index("d")
compare_df.loc["d_1", "predictions"]= 0
然后我们绘制这个…
图 16:模型的实际与预测。
我参加这个比赛有点晚,但仍然有足够的时间来改善这个结果(我将与大家分享)。
有用资源:工作流程指南
Rob Hyndman 在《预测:原则与实践》一书中提供了一个非常有用的流程图。在线书籍的链接将在下面的其他资源部分。
图 16:ARIMA 流程图。资料来源——hynd man,R.J .,& Athanasopoulos,G. (2018) 预测:原理与实践,第二版,OTexts:澳大利亚墨尔本。OTexts.com/fpp2.2020 年 09 月 06 日访问
一锤定音
感谢您花时间阅读这篇文章。我是一名自学成才的数据科学家,来自英国伦敦。可以通过 LinkedIn 和 https://www.linkedin.com/in/kurtispykes/的联系到我。请不要犹豫联系我,认识新朋友是很棒的。
其他资源:
利用 web 流量数据进行预测
不使用时间序列的预测
介绍
通常,当您访问时间序列数据时,在这种情况下,我们将查看一个例子,其中我们有一周的 web 流量数据,本能地应用时间序列模型。然而,情况并不总是如此,我将在这篇博文中进一步说明原因。
在这篇文章中,你将学会如何:
- 设置您的分析数据集以预测未来的事件,即网络用户是否会在第二天成为销售线索
- 创建辅助预测的附加要素
- 识别并绘制特征重要性
- 利用强大的分类技术进行时间序列预测
数据概述
数据问题:预测某网站用户第二天是否会成为 lead?
数据集:提供了一个为期一周的网站流量样本数据集,包括三个变量:用户 id、事件(“查看”、“搜索”或“引导”)和时间戳(日期和时间)
建议方法:为了预测用户第二天是否提交线索的可能性,我们需要了解用户前一天或前几天的活动以及网站上的聚合活动。为此,我们需要创建功能。
R 中的建模
加载库和导入数据集
library(data.table)
library(dplyr)
library(padr)
library(xgboost)
library(Matrix)
library(RcppRoll)
library(zoo)
library(readr)
library(sqldf)data_interactions<-read_csv("C:\\Users\\srivastavas\\Downloads\\data-interactions\\data-interactions.csv")
数据询问
一旦数据集被加载,查看数据集以确保它被正确读入总是有帮助的。如下所示,我们可以看到数据集由四列组成:事件类型(“查看”、“搜索”或“潜在客户”)、用户 id(唯一标识符)、时间戳(用户访问网站的时间和日期)以及日期。
# A tibble: 6 x 4
event userid utc_timestamp date
<fct> <chr> <dttm> <date>
1 view 4c02df98-fee3-43dd-8582-4192180a52c8 2019-01-17 03:49:36 2019-01-17
2 search bcc02079-d9d6-461a-bb7a-6ad679dc3ddb 2019-01-19 22:33:14 2019-01-19
3 search 4443b108-11aa-44e8-9934-a9c75e7a5b2e 2019-01-20 06:54:42 2019-01-20
4 search a8513b28-c94b-49b4-9260-07f9ce8a24aa 2019-01-17 23:33:44 2019-01-17
5 search 261eb70e-af13-4d0c-a2d8-7c2095586b2d 2019-01-20 01:28:01 2019-01-20
6 search 7d670d0a-f815-4ce1-955a-f026f478ebb5 2019-01-17 22:42:44 2019-01-17
时间变量和唯一标识符是我喜欢称之为“垃圾”的变量。它们对模型的预测没有帮助。然而,在我们的案例中,时间是一个重要的特征,因为我们想知道用户是否会在第二天成为销售线索。个人用户 id 也很重要。那么,我们如何还能利用这些信息。
这让我想到了建模的下一个部分——特征工程。
特征工程
由于用户每天可能会查看或搜索一个网站一次或多次,因此有必要汇总这些信息,以减少每个用户的记录数量,同时能够创建每日数据集,即每个用户每天一条记录。这可以用 R 的 dplyr 包或者 sqldf(用 R 写 SQL 代码)来完成。
在下面的代码片段中,我按照日期和用户 id 对数据集进行了分组,以计算每个用户每天的查看次数、搜索次数和线索数。
sql_str<-"select userid, date
, SUM(CASE WHEN event = 'leads' THEN 1 ELSE 0 END) AS num_leads
, SUM(CASE WHEN event = 'view' THEN 1 ELSE 0 END) AS num_views
, SUM(CASE WHEN event = 'search' THEN 1 ELSE 0 END) AS num_searches
FROM unique_data_interactions
GROUP BY userid, date"df1<-sqldf(sql_str,stringsAsFactors = FALSE)
接下来,为了有意义地使用日期变量,我们可以创建与时间相关的变量,如访问网站的日期、访问时间、访问月份和访问周。因为我们只有一周的时间,所以只有访问日(即星期日与星期一)可能有用。下面的代码可以用来创建与时间相关的变量。
df1$day<-as.numeric(as.factor(weekdays(as.Date(df1$date))))
现在,因为我们希望预测某个用户第二天是否会成为潜在客户,所以我们希望了解该用户以前的活动。例如,用户是在前一天还是前一天、三天前浏览网站的?他们以前也搜索过网站吗?
为了使用以前的活动来预测未来的活动,我们需要创建滞后变量。因为我们想要预测某个用户第二天是否会成为销售线索,所以我们使用前一天的活动来预测第二天的活动。
首先,你需要按日期排列数据。然后,您希望按 userid 对数据进行分组,因为您希望预测给定用户是否会在第二天成为销售线索。
为了预测用户第二天是否成为潜在客户,我们需要知道客户前一天是否是潜在客户(滞后 num _ leads 1),他们前一天是否查看和搜索了网站(滞后 num_views 和 num _ searches 1),以及到目前为止的查看和搜索总数(cum_sum_views 和 cum_views_searches)。
df1<-df1[order(df1$date),]#Create lag variablesdf2<-df1 %>%
group_by(userid) %>%
mutate(lag_leads_1 = lag(num_leads,1) #lag target variable by 1
, cum_sum_views = cumsum(num_views)
, cum_sum_searches = cumsum(num_searches)
, lag_views_1 = lag(num_views,1) #lag num_views by 1 day
, lag_searches_1 = lag(num_searches,1)#lag num_searches by 1 day
)
在时态数据中,通常会创建一些变量,如滚动平均值、滚动中值平均值和各种滞后变量,但由于我们只能访问一周的数据,这些变量似乎并不合理。
现在,如果我们有用户前一天的信息,我们只能预测用户第二天是否会成为潜在客户。例如,如果用户仅在周末(第 7 天)出现在数据集中,则很难测试该用户的模型准确性,因为我们没有关于该用户是否成为销售线索的信息。因此,此类记录已从数据集中删除。
#remove users who don't have previous day records as can't predict next day lead for them
df3<-df2[!is.na(df2$lag_leads_1),]
第二件要做的事情是决定一个模型。由于问题是确定用户 a 是否在第二天成为销售线索,这是一个二元问题,也是一个分类问题,即用户成为销售线索= Success = "1 ",用户没有成为销售线索= Failure = "0 "。为了对这个问题建模,我们需要如下对这个目标变量进行特征工程。
df3$lead_flag<-ifelse(df3$num_leads>=1, 1, 0)
准备分析数据集
我们已经删除了重复的记录,创建了每个用户每天一条记录的每日数据集,并创建了时间相关变量和我们的目标变量(我们希望预测的变量)。
下一步是现在决定我们如何训练和测试我们的模型。在大多数情况下,随机拆分数据是有意义的,即随机的行子集成为训练集,其余的成为测试集。通过这种方式,您的模型在数据集上接受训练,然后在从未见过的数据上测试准确性。
但是,当您拥有时态数据时,您预测的是未来的某个时间,因此数据集应根据时间进行拆分,即数据集的前 75%用于训练(即周一至周四),其余部分用于测试(周五至周日)。由于我们的数据集只有一周,这种划分似乎不合理。
在我们的示例中,我们希望预测某个特定用户是否会成为潜在客户。因此,按用户 id 分割数据集是有意义的,其中模型针对一组特定的用户进行训练,然后针对从未遇到过的用户进行准确性测试。为了以这种方式分割数据,编写了以下代码。
#Subset data into training and test sets - split on different users
user_ids<-as.data.frame(unique(df3$userid))
names(user_ids)<-"user_ids"
train_user_ids<-sample_frac(user_ids,0.75)
names(train_user_ids)<-"user_ids"
train <-df3[df3$userid %in% train_user_ids$user_ids,]
test <- anti_join(df3, train, by = c("userid" = "userid"))
一旦你有了训练集和测试,你就可以开始建模了!😃
运行模型
对于二进制分类,您需要一个分类模型。基于树的方法通常用于二元分类。一种流行的基于树的方法是 xgboost,它从每一棵新树(迭代)中学习,试图减少错误的百分比。与最终结果是一组树或平均加权树的随机森林不同,最终的 xgboost 决策树是所有回合中错误率最低的一个。
众所周知,randomforest 和 xgboost 在试图改进之前的迭代时会过度拟合数据;然而,由建模者决定提供给模型的变量是否独立(不相关),是否能提供信息,是否以任何方式影响结果。
R 中的 xgboost 模型需要一个矩阵和定义的参数,如下面的代码片段所示。
xgboost 模型需要以下步骤:
- 定义目标变量—“标签”
- 删除 NAs
- 创建一个包含要包含在模型中的变量的矩阵(当数据集中有标称/分类变量时,使用 contrasts.arg)
- 为您的模型设置参数—使用二元逻辑函数,因为这是一个分类问题,不需要非常深的树(导致过度拟合,所以只指定了四个级别;当你有一小组变量时,2 和 3 通常是好的)
set up model
label <- train$lead_flag
#returns object unchanged if there are NA values
previous_na_action<-options('na.action')
options(na.action='na.pass')#build matrix input for the modeltrainMatrix<- sparse.model.matrix(~num_views+num_searches+day+lag_leads_1+cum_sum_views+cum_sum_searches
+lag_views_1+lag_searches_1
, data = train,
, contrasts.arg = c('day')
, sparse = FALSE, sci = FALSE)
options(na.action=previous_na_action$na.action)#create input for xgboosttrainDMatrix <- xgb.DMatrix(data=trainMatrix, label = label) #set parameters of model# Define the parameters for binomial classificationparams <- list(booster = "gbtree",
objective = "binary:logistic",
eta=0.3,
gamma=0,
max_depth=4,
min_child_weight=1,
subsample=1,
colsample_bytree=1)
当您的模型正在训练时,您可以使用一种叫做 交叉验证的方法来测试它的准确性。 在交叉验证中,你运行多个不同的训练测试拆分,然后平均结果,而不是完全依赖单个特定的训练集。最常见的交叉验证类型是 K 重交叉验证,最常见的是将 K 设置为 5 或 10。例如,为了进行五重交叉验证,将原始数据集划分为大小相等或接近相等的五个部分。这些部分中的每一个都被称为“褶皱”。然后训练一系列五个模型,每个折叠一个。第一个模型:模型一,使用折叠 2 至 5 作为训练集进行训练,并使用折叠 1 作为测试集进行评估。第二个模型:模型 2,使用折叠 1、3、4 和 5 作为训练集进行训练,使用折叠 2 作为测试集进行评估,以此类推。当这个过程完成时,我们有五个精度值,每个折叠一个。通常取准确度分数的平均值。
您可以为交叉折叠验证设置您的模型,如下所示。在这里,我们指定了五轮交叉验证,告诉模型运行 1000 次迭代,但如果它不再显示任何准确性的提高,就提前停止(在第 20 轮)。
最后一行告诉我们,在哪个迭代中,模型生成的树具有最低的误差。在我们的例子中,输出是第 40 次迭代。
xgbcv <- xgb.cv( params = params, data = trainDMatrix, nrounds = 1000,
nfold = 5, showsd = T, stratified = T,
print_every_n = 10, early_stopping_rounds = 20, maximize = F)
num_iterations = xgbcv$best_iteration
现在,我们可以使用这些信息在训练集上运行我们的模型,并让它在第 40 次迭代时停止。我们还告诉我们的模型使用内置的错误度量来评估树以及 logloss 度量。
model <-xgb.train(data=trainDMatrix
, params=params
, nrounds = num_iterations
, maximize = FALSE
, eval.metric = "error", eval.metric = "logloss")
模型评估
功能重要性图告诉我们,模型中的变量是如何用来预测用户是否会在第二天成为潜在客户的。
在这里,我们可以看到当天的浏览量和搜索量是预测客户当天是否会成为销售线索的最重要的预测因素。我们还可以看到,尽管创建了滞后和累积变量,但它们并不十分有用。然而,这是意料之中的,因为数据集覆盖了一周的很短的时间范围。
importance<-xgb.importance(feature_names=colnames(trainDMatrix), model=model)
xgb.ggplot.importance(importance_matrix=importance)
下一步是测试模型的准确性。这需要将测试数据集设置为矩阵,并使用训练好的模型对测试集运行命令“预测”。
为了测试模型的准确性,我们在这里比较有多少 lead_indicator 值被模型正确分类为“0”或“1”。“预测”数据集在模型输出概率时被重新编码。任何大于 0.5 的概率都转换为“1”(是销售线索),任何小于 0.5 的值都转换为“0”(不是销售线索)。我们对测试集(testMatrix$label)中预测值(“预测”)等于原始值的所有实例求和,然后除以测试集的大小。
这里,我们得到 97.53%的准确率,或者 0.03 的错误率,这意味着测试集中所有用户的 97.53%被正确分类为他们是否会在第二天成为销售线索。
testMatrix<- sparse.model.matrix(~num_views+num_searches+day+lag_leads_1+cum_sum_views+cum_sum_searches
+lag_views_1+lag_searches_1
, data = test,
, contrasts.arg = c('day')
, sparse = FALSE, sci = FALSE)
options(na.action=previous_na_action$na.action)pred<-predict(model,testMatrix)
prediction <- as.numeric(pred > 0.5)
print(head(prediction))
err <- mean(as.numeric(pred > 0.5) != testMatrix$label)
print(paste("test-error=", err)) #average error is 0.03 very low so model is good result = sum(prediction==test$lead_flag)/length(test$lead_flag)
print(paste("Final Accuracy =",sprintf("%1.2f%%", 100*result))) #97.53%
如果你和我一样无法相信自己的眼睛,那么将测试集和预测结合起来,并排查看如下信息会很有帮助。在下图中,您可以看到,对于 2019 年 1 月 15 日,并非所有用户都在这一天成为销售线索,这些用户的预测值为“0”(非销售线索)。
如果我们的模型显示精度降低,我们可以使用 xgboost 参数,比如树深度、轮数、用于树分支分裂的最小行数。然而,在这种情况下,以如此好的精度,这是不需要的。
希望您现在已经很好地理解了如何对分类性质的时间序列数据建模!如有疑问,请在下方评论。
完整的代码文件可以在这里找到:
https://gist . github . com/shedoedasdatascience/fbdd 1b 52 c 5089 d3b 80 ba 512 f 969 e 704 c
日冕时代的预测
现在,我们比以往任何时候都更需要谨慎地创建和使用预测
在此次危机期间,我作为一名数据科学家在旅游业工作,经常被问到如何利用数据来预测旅游业何时会恢复某种健康。我的回答都归结为:“伙计,现在我几乎不能给你一个今天下午会发生什么的准确预测”。但这让我想到:目前我们应该如何进行预测?到底什么是预测?
Tardis:终极预测机器(照片由查理·西曼在 Unsplash 上拍摄)
什么是预测?
预测的根本问题是我们实际上无法预测未来。当我们说我们要“预测”某事时,我们实际上是在说我们要做三件事情中的一件(或多件):
时间序列投影
在这里,我们将重点放在我们试图预测的指标的历史上,并假设历史上的模式将持续到未来。因此,如果我们预测冰淇淋销售,我们将只查看以前的冰淇淋销售数据,并假设夏季和周末的高峰将持续下去。
一旦我们做出了这个假设,我们需要做的就是建立准确描述历史(或“时间序列”)的模型,然后用这些模型预测未来。ARIMA 等车型就属于这一类。
系统模型化
在这里,我们使用对其影响最大的各种因素的数据或与之相关的数据,建立一个感兴趣的度量模型。在这种情况下,我们的冰淇淋预测将涉及了解冰淇淋销售与温度、降雨量、工作日、学校假期等之间的关系。这里的一个关键点是,您需要确信已经捕获了影响预测指标的所有关键因素,并对这些因素本身有一个良好的预测。因此,如果你有一个坏天气预报,这将损害你的能力,建立一个良好的冰淇淋销售预测。
天气预报和对体育赛事和选举的预测就是这种预测的好例子。
情况分析
在这里,我们不试图从数据中推测趋势或关系,而是想象会发生什么,然后看看在我们感兴趣的各种系统/过程中会发生什么。你可能在想“等等,这只是猜测?”是的,确实如此。但这也是吸引力所在:你不会用看似精确的数字来哄骗人们产生一种虚假的安全感,在猜测千载难逢的场景可能会如何发展方面,人类的想象力比任何机器都做得更好。
这是一个简单的方法,但比你想象的更常见。养老金、投资和抵押贷款提供商做了很多这样的事情,银行的压力测试本质上是一种悲观的情景分析。很明显,在一切都失控之前,这些往往更有用,但在危机当中,当人们不确定事情将如何发展时,这些可能会有用。
为什么预测这么难?
要进行预测,你需要对两件事有信心:
- 你很好地掌握了影响结果的主要因素,即统计术语中的低随机不确定性。
- 没有任何重大的不可预测的事件会突然发生并把事情弄糟,即低认知不确定性
你们中目光更敏锐的人可能已经发现了第二点的一个问题:如果上述重大事件是不可预测的,我们怎么知道它们不足以左右结果?让我们通过一个例子更深入地探讨这一点。
想象一下,一个为英国政府工作的预测者,被旅游部长委派预测明年每月将有多少国际游客到达英国。看着数据,他们心里想:“嗯,这看起来非常规律和稳定,这应该不会太难”,然后使用季节性 ARIMA 模型建立一个预测,如下图所示。它们包括一些很好的、清晰的 95%预测区间,这样旅游部长就能感觉到这个预测有多少不确定性。
对英国游客数量的糟糕预测
他们表现如何?虽然我没有英国游客数量的最新数据,但根据波士顿咨询集团在此有益总结的行业数据,在撰写本文时,机票数量几乎为零,因此我们可以假设所有游客都在做类似的事情。总的来说,不太好。
发生了什么事?嗯,有人可能会说没有什么真正出错:有一个 95%的下限预测区间,我们超过了它,但我们应该预计 20 分之一的时间,所以,有什么大惊小怪的?这个推理的问题是,我们不仅仅是超出了下限一点点。我们撞穿了它,直到撞到地面才停下来。使用预测区间的正态分布假设,这种事件的概率为 0.000002%,即我们应该每 500 万年才观察到一次这样的事件!
相反,问题在于预测区间只是一个关于随机不确定性的陈述,基于算法在它被训练的数据中观察到的东西。换句话说,预测区间本身只是不确定性的预测,因此只显示了现实世界不确定性的最小界限。
公平地说,认知的不确定性是不可量化的(如果它是可量化的,它将是任意的),并且很难在图表上显示出来。预测者本可以做的一件事是,在预测的同时,考虑 2001 年和 2008 年的危机是如何影响旅游人数的。这清楚地表明,他们只是提供了一个“正常年份”的预测,而在现实世界中,任何事情都可能发生。马后炮是一件奇妙的事情。
预测通常是错误的,相应地计划
正如我们所看到的,无论你正在看什么样的预测,大多数时候都会有一点点错误,有时还会有很多错误。正因为如此,始终知道你可以接受多少误差,以及当误差超过这些界限时你会怎么做是至关重要的。
因此,任何预测者工作的最重要的部分是理解一个人预测的客户或系统对什么样的错误最敏感。如果你要预测库存,是库存过多还是缺货成本更高?如果你预测要设定一个目标,如果目标经常被超过或经常被错过会更好吗?预测者可能犯的一个常见错误是花费数小时研究不同的预测技术和模型,但只花几分钟去理解不可避免的误差将如何影响他们为之建立预测的系统或客户。
一个好的预测者不仅仅是最小化错误,他们还会选择正确的错误来最小化
幸运的是,当决定被恰当地框定时,这种想法会自然而然地来到我们身边。我敢打赌,上次你办派对时,买的食物和饮料比你最终需要的还多。这远非不理性,而是因为过度预测的成本很低(多余的可以廉价储存),而预测不足的成本很高(还有什么比没有酒喝的派对更让人难过的吗?).
适应,不要预测
正如你可能已经收集到的,基于数据的预测在未来几个月不会有太大帮助,因为我们有大量的随机和认知的不确定性。我们不知道人们在接下来的几个月里会如何或是否想去旅行。即使我们开始理解这一点,任何基于这一理解的预测都有被不可预测事件粉碎的高风险,如第二波浪潮、政治决策、经济影响(如果没有航空公司就不能飞行),或者更乐观地说,新的治疗方法或疫苗。
你得等等,老朋友(图片由帖木儿 M 在 Unsplash 上拍摄)
那么如果我们不能预测,我们能做什么呢?最有效的方法将是以下方法的组合:
使用情景分析概述几种可能的结果,并描绘它们如何影响你感兴趣的内容。请注意,这并不一定是花哨的,在许多行业和领域中,有许多已经开发出来的现成产品可以使用。在这样做的时候,基于你所拥有的信息,选择一个“最有可能”的场景,然后围绕这个场景设计计划是很有诱惑力的。但这又落入了预测陷阱:你现在拥有的信息明天可能就无关紧要了。
清楚地评估客户、系统或您正在做出的决策对风险的**敏感度,并将这些敏感度与可能的情景进行比较。请注意,无论哪种情况发生,你都应该努力做出最大化你实现目标的能力的决策,即使在每个特定的情况下都不是最优的*。你的风险承受能力在这里也发挥了作用;你可能准备好接受一个在某些情况下冒着破产风险的决定,如果在其他情况下会有很大的回报。*****
最后,给定的环境可能会继续快速演变,探索如何提高自己的能力以变得灵活和响应将使你更有效地应对这种变化,并减少对场景分析中固有的猜测的依赖。
那么什么时候才是回归预测的合适时机呢?嗯,如果可能的话,你可能不想。预测是一件不确定的事情,你的决策依据越少,你的决策就越稳健。这并不意味着你不应该再次启动 ARIMA 模型或查看天气预报,许多决定需要对未来将要发生的事情有一些看法,但这确实意味着你应该永远记住:如果这真的是错的,我该怎么办?如果有,我该如何快速适应?
你觉得幸运吗?(照片由马库斯·斯皮斯克在 Unsplash 上拍摄)
从一个重要的意义上来说,预测现在比以往任何时候都更像是在股市上挑选赢家:有很大程度的随机性,很少有人能做好,而且很难区分有才华的人和仅仅是幸运的人。但是,我们可以使用优秀基金经理管理投资组合的相同工具和方法:了解他们的风险承受能力,选择能够承受一系列结果的多样化等策略,并确保他们能够灵活地转移资金以利用机会。当然,永远不要忘记古老的投资格言:过去的表现并不能保证未来的结果。
基于 FgSegNet 的前景图像分割
具有类似自动编码器结构的多尺度 CNN
FgSegNet 的架构图;它使用三个 CNN 模型和一个 TCNN。[1]
介绍
一个有待解决的棘手问题是前景图像分割(从不同的角度来看),即(或)。这个任务听起来可能很琐碎:创建一个二进制蒙版,其中只有移动/重要对象的像素被标记。然而,当现实世界的可变性被引入到图片中时,这可能变得特别困难(没有双关语)。例如, 一个真正鲁棒的图像分割模型必须考虑以下所有 😗*
- (背景)景色的微妙变化
- 忽略移动的树木、树叶、雪、雨、阴影等。
- 处理光线不好的情况
- 处理相机抖动和/或运动
- 摄像机视野内模糊区域的伪装物体
- 这个清单还在继续……
完成这项任务的最初几个方法之一(在当时)是相当健壮的,本质上是统计学。具体来说,它涉及使用多个高斯模型来映射输入的每个像素的每个颜色值(即 RGB)的分布。如果像素的颜色值在特定帧中与其高斯分布不匹配,则可以确定该像素持有前景对象。然而,这种方法仍然很容易受到上述挑战的影响,但在当时(1999 年)[2]仍然是鲁棒图像分割的一个突破。****
快进到最近的时代,现在我们有足够的计算能力和数据让卷积神经网络(CNN)和其他复杂的模型相当精确地运行,更不用说简单的前馈网络了。不出所料, 现在比以往 有更多基于深度学习的背景减法。
我们来看看 前景分割网络 ,或者 FgSegNet ,这是一种最近提出的、性能最好的神经网络架构,它使用多个 CNN 和一个转置 CNN (TCNN)来实现背景减法。[1]
理论
CNN 和 TCNNs
FgSegNet 在其架构内使用 3 个卷积神经网络(CNN)和一个转置 CNN (TCNN)。具体来说,该架构为其每个 CNN 使用一个预训练的 VGG-16 模型。****
综上所述,CNN 广泛用于图像特征提取,因此在图像分类中工作良好。卷积层如何在 CNN 内工作的前提是通过内核(具有初始化的但可改变的值/权重的小 2D 矩阵),其跟踪图像输入并聚集内核值和相应输入像素值之间的乘积。换句话说,内核 在运行时会对输入 进行卷积,这就是 CNN 中的 C。卷积层在实际应用中更容易理解,所以这里有一张内核操作的 GIF 图片。
CNN 内核的例子。蓝绿色是完整的输出,蓝色是图像输入,阴影/轮廓是内核。内核将其相对于输入的每个值相乘,然后相加,产生一个像素作为输出。[3]
那么什么是转置 CNN 呢?把它想成是 CNN 应该做的完全相反的事情。CNN 自然产生的输出通常小于其输入;这与 TCNNs 相反,,因为它的内核执行与 CNN相反的操作。****
根据上面的架构图, FgSegNet 首先将输入馈入三个 CNN,连接三个输出,并将其作为输入馈入 TCNN。最终输出是二进制掩码。
为什么是“类自动编码器”?
论文称 FgSegNet 为“编解码型网络模型”,这是名副其实的。首先,架构类似于自动编码器的架构:输入首先被漏斗化/瓶颈化成一个更小的特征图(编码),然后在模型的后半部分结束时被扩展回其原始形状(解码)。CNN 本质上也是编码器,因为它们通过内核操作提取特征。也就是说,tcnn(与 CNN 相反)将是解码器也是事实。
我推测,在前景提取等任务中使用编码器的目的是精确定位图像帧中容易发生变化的“重要”特征,用通俗的话来说,就是使用压缩信息输出带有 TCNN 的遮罩。让 3 个不同形状的 CNN 并行工作也支持这一概念,并且允许该模型更加通用于不同大小的前景对象。
表演
数据集
前景提取器模型的一个突出数据集是 CDnet2014 数据集。 CDnet2014 包括模型的 11 种不同挑战场景(即恶劣天气、相机抖动、夜间视频等。),每个场景包含 4 到 6 个视频序列。数据集包括地面真实图像/遮罩,标记每一帧的所有前景对象和阴影。 FgSegNet 在多个图像数据集上进行测试,其中一个是 CDnet2014。
模型实现
FgSegNet 是使用 Keras 和 Tensorflow 框架构建的。它的所有层(除了最后一层)都使用 ReLU 激活层,而 VGG-16 CNN 的多个池层被替换为 dropout 层。除了辍学,该模型利用 L2 权重正则化。RMSProp 被用作具有学习率降低器的优化器,当验证损失停止改善 6 个时期时,学习率降低器被激活。 最后,该模型允许选择用 50 或 200 帧图像进行训练。
要了解更多关于模型实现的信息,请点击这里阅读其论文。
估价
FgSegNet 是 CDnet2014 数据集评估期间表现最好的模型之一。当用 200 帧训练时,达到的平均 F 分数是 0.9734(分数范围从 0[差]到 1[最好]),用 50 帧训练时是 0.9545。下面是一个场景分类的例子,以及由模型生成的基本事实和掩码。
(a)是原始图像。(b)是基本事实。(c)由 FgsegNet 生成。[1]
图像行从上到下依次显示原始图像、地面实况和模型生成的遮罩。[1]
正如你所看到的,模型生成的遮罩非常令人印象深刻,尤其是对于跟随基线的三个类。
在左侧,您可以找到模型意外执行的一些实例。然而,即使对人类来说,分割这些样本看起来也很麻烦。
总的来说,FgSegNet 给人印象非常深刻,是一个很好的前景提取任务。
如果你想看看,这里是 github 对 FgSegNet 源代码的回购:
这个库包含以下论文的源代码和训练集:“前景分割使用…
github.com](https://github.com/lim-anggun/FgSegNet)
参考
[1] L. Ang Lim 和 H. Yalim Keles,使用三重卷积神经网络进行多尺度特征编码的前景分割 (2018),arXiv-1801。
[2] C. Stauffer 和 W. E. L. Grimson,用于实时跟踪的自适应背景混合模型 (1999),IEEE 计算机学会会议。
[3] V. Dumoulin 和 F. Visin,深度学习卷积算法指南 (2016),arXiv-1603。**
犯罪和事故现场的法医分析
随机森林分类器的性能
机器学习解决多类分类问题
作者图片
机器学习算法通常假设对象数量大致相似的类别。然而,在现实生活中,数据分布大多是倾斜的,一些类出现的频率比其他类高得多。因此,当面对这种不平衡时,我们必须设计一个智能系统,能够克服这种偏见。
这里,我们将处理一个多类问题,数据取自 UCI ML 库,如下所示。
url = ("https://archive.ics.uci.edu/ml/machine-learning-"
"databases/glass/glass.data")
df = pd.read_csv(url, header=None)
df.columns = ['Id', 'RI', 'Na', 'Mg', 'Al', 'Si','K', 'Ca', 'Ba', 'Fe', 'type']
df.set_index('Id', inplace=True)
print('Data loading:')
df.head()
在这里,我们把具有不同化学成分特征和不同类型的玻璃归为多类。该问题提出了各种玻璃的化学成分,其目的是确定玻璃的用途。
探索性分析
类可视化
figure, ax = plt.subplots(1,1, figsize=(10,5))
sns.countplot(x = 'type', data=df)
ax.set_xticklabels( ('building_windows_float_processed', 'building_windows_non_float_processed','vehicle_windows_float_processed','containers', 'tableware', 'headlamps'), rotation = 90 ) plt.show()# summarize the class distribution
target = df.values[:,-1]
counter = Counter(df['type'])
for k,v in counter.items():
per = v / len(df) * 100
print('Class=%d, Count=%d, Percentage=%.3f%%' % (k, v, per))
我们可以观察到数据有些不平衡。每个等级从人口最多的 76 到人口最少的 9。平均统计数据可能主要由人口最多的类的值决定,没有理由期望其他类的成员具有相似的属性值。激进行为对于区分不同的类来说是一件好事,但它也意味着进行预测的方法必须能够追踪不同类之间相当复杂的边界。
箱形图
让我们来看看标准化数据的箱线图。我们使用平均值和标准差对数据进行了标准化。偏差。
X = df[['RI', 'Na', 'Mg', 'Al', 'Si','K', 'Ca', 'Ba', 'Fe']]
X_norm = (X - X.mean())/X.std()
boxplot = X_norm.boxplot(column= ['RI', 'Na', 'Mg', 'Al', 'Si',
'K', 'Ca', 'Ba', 'Fe'])
plt.xlabel("Attribute Index")
plt.ylabel(("Quartile Ranges"))
plt.show()
这里可以观察到大量的异常值。我们有一个多层次的分类问题。更有甚者,数据有些不平衡。
平行坐标图
我们将使用标准化数据绘制平行坐标图,以保持比例一致。而且,因为并行坐标图计算的动态特性在显示中起着很大的作用。
X_norm = pd.concat([X_norm, df['type']], axis=1)
pd.plotting.parallel_coordinates(X_norm, 'type')
plt.show()
绿色和蓝色的线条很好地组合在一起,并在许多属性上与其他类很好地分开。此外,绿线位于几个属性的数据边缘,换句话说,就是这些属性的异常值。中间的蓝色线条也聚集在一起,但其值处于中间范围。
预测能力评分(PPS)
PPS 在数据中发现更多模式,并检测线性或非线性关系。分数范围从-1 到 1,表示是否存在强线性关系。PPS 使用交叉验证的决策树,并计算合适的评估指标。要了解更多,请访问这里。
非线性关系由“0”值标识。目标不包括在相关图中,因为问题的目标具有几个离散值中的一个。
从探索性分析中,我们很好地理解了这个问题的权衡,导致了对什么算法将给出最佳性能的一些猜测。这里,数据量很小,考虑到不平衡数据集涉及多个类,问题有点复杂。
我们可能需要一个基于非线性树的算法来针对这个用例。我们将尝试决策树(DT ),它通过在某个值重复分割特征,将特征空间分割成许多更小的区域。为此,DT 使用一个贪婪算法和一些启发式算法来寻找一个分裂,使子节点的组合杂质最小化。在 DT 下的许多算法中,我们将在这里尝试随机森林。
具有 OOB 误差的随机森林
随机森林使用树,根据事例是高于还是低于所选特征变量的所选阈值,将数据分成组(重复)。输入异常值没有额外的影响。输出异常值将影响它们所在叶节点的估计值,但不会影响任何其他叶节点的值。输出异常值对随机森林有“隔离”效果。埃文·埃尔格
由于不平衡的类,我们选择分层抽样在列车测试分裂。
X = df.drop(columns = ['type'], axis=1)
y = df['type']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20, stratify=y, random_state=123)miss_class_error = []
nTreeList = range(50, 2000, 50)
for iTrees in nTreeList:
depth = None
max_feat = 4
rfc = RandomForestClassifier(n_estimators=iTrees, max_depth =depth, max_features=max_feat, oob_score=True,n_jobs = -1, random_state=123)
print('RandomForest model fit:')
rfc.fit(X_train, y_train)
我们想要评估我们的训练集中的观察值的数量对某些度量(准确性、F1 等)的影响。).
学习曲线
它实际上是可视化我们的模型在训练和交叉验证过程中的性能(例如,准确性、召回率),因为训练集中的观察次数增加了。我们在 100 个不同的训练集大小(从 1%的观察值到 100%的观察值)下绘制了拟合分类器的准确度。交叉验证模型的准确度分数越来越高,这告诉我们,我们可能会从额外的观察中受益。这是一个缓慢的过程。
准确(性)
混淆矩阵
cm = confusion_matrix(y_test, prediction)
pd.DataFrame(cm)
plt.figure(figsize=(10,6))
print('')
print("Confusion Matrix plot")
sns.heatmap(cm.T, square=True, annot=True, fmt='d', cbar=False)
plt.xlabel('true label')
plt.ylabel('predicted label');
分类报告
接收机工作特性(ROC)
以下代码摘自 sklearn 指南:
我们将使用一对所有的方法,这种方法在标签方面具有独特的优势。
特征重要性
feature_importance = rfc.feature_importances_
# normalize by max importance
feature_importance = feature_importance / feature_importance.max()#plot variable importance
idxSorted = numpy.argsort(feature_importance)
barPos = numpy.arange(idxSorted.shape[0]) + .5
plt.barh(barPos, feature_importance[idxSorted], align='center')
plt.yticks(barPos, variable_names[idxSorted])
plt.xlabel('Variable Importance')
plt.show()
总的来说,我们可以看到我们的模型在给定数据集的情况下为眼镜的分类提供了很好的洞察力。
超参数值的影响
这表明,训练大规模森林的计算成本可能没有太大价值。因此,我们可以用更少的树重新训练出模型来评估性能。
结论
用相同的数据集与其他模型进行比较总是明智的。然而,多标签分类在最近几年已经成为一个非常重要的范例。随着 ML 算法的进步,在 RandomForest 的最新版本中,不需要交叉验证或单独的测试集来获得测试集误差的无偏估计。它是在运行期间内部估计的。每个树都是使用来自原始数据的不同引导样本构建的。大约三分之一的情况被排除在引导样本之外,并且不用于第 k 棵树的构造。此外,使用随机平均梯度(SAG)求解器来训练逻辑回归模型进行比较也是一个好主意。
参考:
- https://www . stat . Berkeley . edu/~ brei man/random forests/cc _ home . htm
- 鲍尔斯博士(2015 年)。Python 中的机器学习:预测分析的基本技术。约翰·威利的儿子们。
注意:这里描述的程序是实验性的,在用于任何商业目的时都应谨慎使用。所有此类使用风险自负。**
异常检测的 ML 和精确召回曲线的重要性
使用机器学习的欺诈检测
处理不平衡数据集以检测欺诈概率
作者图片
https://sarit-maitra.medium.com/membership
F 在电子商务、医疗保健、支付和银行系统等许多不同领域都可以看到欺诈行为。财务欺诈对投资者、监管者、审计师和公众都有重要影响。数据挖掘在检测在线交易中的金融欺诈中起着重要的作用。然而,数据挖掘变得具有挑战性,因为正常和欺诈行为的特征不断变化,并且欺诈数据集高度扭曲。
在这里,我们有银行支付的数据集如下。显示交易欺诈性(1)还是有效(0)的目标变量。
该数据集包含了有关数字金融欺诈风险上升的信息,强调了获取此类数据的难度。它对预测欺诈构成的技术挑战是 600 万行数据中正负类之间的高度不平衡分布。为了更好地理解金融交易数据集,让我们按特性统计不同值的数量。
正如我们在下图和 outlier_fraction 中看到的,数据是不平衡的。
ax = (df['fraud'].value_counts()*100.0 /len(df)).plot(kind='bar', stacked = True, rot = 0)
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.set_ylabel('Frequency Percentage')
ax.set_xlabel('Class')
ax.set_title('Frequency Percentage by Class')
totals = [] for i in ax.patches:
totals.append(i.get_width())total = sum(totals) for i in ax.patches:
ax.text(i.get_x()+.15, i.get_height()-3.5, \
str(round((i.get_height()/total), 1))+'%', color='black', weight = 'bold')
数据预处理:
只有一个唯一的邮政编码值,因此我们将删除它们。
print("Unique zipCodeOri values: ",df.zipcodeOri.nunique())
print("Unique zipMerchant values: ",df.zipMerchant.nunique())
# dropping zipcodeori and zipMerchant
reducedDF = df.drop(['zipcodeOri','zipMerchant'],axis=1)# changing object dtype to categorical for easing the transformation process
categorical = reducedDF.select_dtypes(include= ['object']).columns
for col in categorical:
reducedDF[col] = reducedDF[col].astype('category')# categorical values to numeric values
reducedDF[categorical] = reducedDF[categorical].apply(lambda x: x.cat.codes)
reducedDF.head()
可以注意到,为了计算容易,这里避免了一位热编码;但是,通常最好将这些类别值转换为虚拟值,因为它们在大小上没有关系(即客户 1 不大于客户 2)。
创建特征矩阵 X 和标签数组 y
让我们重新调整特征矩阵,使均值为零,标准差为一。
featuresToScale = X.columns
sX = pp.StandardScaler(copy=True)
X.loc[:,featuresToScale] = sX.fit_transform(X[featuresToScale])
特征的相关性:
模型准备:
现在数据准备好了,就来准备模型吧。我们需要将数据分为训练集和测试集,选择一个成本函数。
选择成本函数:
在训练之前,我们需要将误差率的成本函数应用于算法。该算法将通过从训练示例中学习来尝试最小化该成本函数。我们将使用二元分类对数损失,这将计算真实标签和基于模型的预测之间的交叉熵。
这里, n 是观察次数; m 是类标签的个数; log 是自然对数;如果观察值 i 在类 j 中则 1 否则01;并且是观测值 i 在类 j 中的预测概率。
该模型将为每笔交易生成欺诈概率。欺诈概率越接近真实标签,对数损失函数的值越低。ML 的目标是尽量减少测井损失。
featuresToScale = X.columns
sX = pp.StandardScaler(copy=True)
X.loc[:,featuresToScale] = sX.fit_transform(X[featuresToScale])# Define resampling method and split into train and test
method = SMOTE(kind='borderline1')
trainX, testX, trainY, testY = train_test_split(X,y, test_size = 0.2, random_state = 42, stratify=y)# Apply resampling to the training data only
X_resampled, y_resampled = method.fit_sample(trainX, np.ravel(trainY))
安装灯 GBM:
model = LGBMClassifier().fit(X_resampled, y_resampled)# Get model performance metrics
predicted = model.predict(testX)
print(classification_report(np.ravel(testY), predicted))probabilities = model.fit(trainX,
np.ravel(trainY)).predict_proba(testX)
print('AUPRC = {}'.format(average_precision_score(testY, \
probabilities[:, 1])))# Probabilities for the positive outcome only
lgb_probs = probabilities[:, 1]# Precision-recall AUC
precision, recall, _ = precision_recall_curve(np.ravel(testY), lgb_probs)
auc_score = auc(recall, precision)
print('LightGBM PR AUC: %.3f' % auc_score)average_precision = average_precision_score(testY, lgb_probs)plt.figure(figsize=(10,6))
# calculate the no skill line as the proportion of the positive class
no_skill = len(y[y==1]) / len(y)# plot the no skill precision-recall curve
plt.plot([0, 1], [no_skill, no_skill], linestyle='--', label='No Skill')# plot the model precision-recall curve
plt.plot(recall, precision, marker='.', label='LightGBM')
plt.fill_between(recall, precision, step='post', alpha=0.3, color='k')# axis labels
plt.xlabel('Recall')
plt.ylabel('Precision')plt.legend()
plt.title('Precision-Recall curve: Average Precision = {0:0.2f}'.format(average_precision))
灵敏度、特异性、精确度、F1 和 MCC:
敏感性和特异性通常被认为是混淆矩阵的特征。
- 敏感度或召回率是指检测到的欺诈行为将产生阳性测试结果的可能性(真阳性率)。
我们在这里看到,公式不包含 FP 和 TN;因此,敏感性可能导致有偏差的结果,特别是对于我们的不平衡类用例。
因此,当分类器在 10 个交易中有 8 个报告肯定有可能欺诈时,灵敏度为 0.8 (80%)。它代表了我们的分类器检测欺诈的能力;低敏感度分类器不能识别许多欺诈交易,而高敏感度分类器在结果为否定时有助于排除交易。因此,我们看到,灵敏度是假阴性率的补充(即假阴性率加上灵敏度= 100%)。
- 特异性是指欺诈性交易在非欺诈性交易中测试结果为阴性的可能性(真-负比率)。
因此,当分类器在 10 个无欺诈交易中的 8 个中报告否定时,特异性为 0.8 (80%)。特异性代表我们的分类器正确识别欺诈交易的程度,因为特异性高的分类器的假阳性率低。具有低特异性的分类器将许多真实的交易信号化为欺诈性的。它是假阳性率的补充。然而,这里我们也看到,公式不包含 FN 和 TP;对于不平衡的类,特异性也可能给我们有偏见的结果。
- 精确度也称为阳性预测值。
这里,公式也不包含 FN 和 TN,同样,精度可能会对我们的不平衡类给出有偏差的结果。它给出了所有预测欺诈中正确预测欺诈的百分比。
- F1 分数结合了召回率和精确度,与上述 3 个指标相比,呈现了一个更平衡的视图,但在该场景中可能会给出有偏差的结果,因为它不包括 TN。
- 马修斯相关系数(MCC)在其公式中考虑了混淆矩阵的所有单元。然而,我们没有在这项工作中试验 MCC,尽管一些报告表明 MCC 易于解释,并且对预测目标的变化也是稳健的。
在我们的案例研究中,欺诈占总案例的 1.2%。欺诈检测可能无法通过获得高准确率来实现。因此,我们将考虑其他性能指标,特别是灵敏度、精确召回曲线下面积(AURPC)和 F1 分数。
准确率代表两个类别中正确分类的观察值的百分比:
百分比精度= (T P +T N / T N +F N +T P +F P) * 100
灵敏度,即真阳性率(TPR)和回忆,代表了被正确分类为阳性的阳性的比例。这些参数至关重要,我们认为这些参数与精确度一起是一种性能指标。
灵敏度= T P / T P +F N
然而,单独的灵敏度也有误导性,因为它允许忽略大量的假阳性。我们的目标是在这两个参数之间找到平衡。我们需要获得高欺诈检测率(灵敏度),以及尽可能高的准确性。为了解决这个问题,我们考虑了像 AUPRC 和 F1 分数这样的权衡措施。
精确度-召回曲线:
对于我们不平衡的数据集,更好的评估结果的方法是使用精度和召回率。精度-召回曲线显示了精度(结果相关性的度量)和召回(返回多少相关结果的度量)之间的权衡。我们已经讨论了精确度、召回率和 F1 分数。
- 高精度意味着,在我们所有的积极预测中,许多是真正的积极预测。
- 高召回率意味着模型已经捕获了大部分的实际阳性(换句话说,它具有低的假阴性率)
最优解需要高精度和高召回率。因此,我们在这里看到的是精度和召回之间的权衡。这通常由算法设置的阈值来确定,以将阳性病例与阴性病例分开。为了评估精度-召回曲线,我们需要计算平均精度,即在每个阈值达到的精度的加权平均值。平均精度越高,解决方案越好。
print("Classification Report for LightGBM: \n", classification_report(testY, predicted))print("Confusion Matrix of LightGBM: \n", confusion_matrix(testY, predicted))
鉴于我们的金融交易数据集高度不平衡,使用混淆矩阵将没有意义。考虑到这种不平衡的阶级问题,混淆矩阵在捕捉这种次优结果方面表现不佳。
拟合逻辑回归模型:
# fit Logistic Regression model
logreg.fit(trainX, trainY)
log_pred = logreg.predict_proba(testX)
log_probs = y_pred[:, 1]# calculate the precision-recall auc
precision, recall, _ = precision_recall_curve(testY, log_probs)
auc_score = auc(recall, precision)
print('LogReg PRAUC: %.3f' % auc_score)log_probabilities = logreg.fit(trainX, trainY).predict_proba(testX)
avg_prec = average_precision_score(testY, log_probabilities[:, 1])plt.figure(figsize=(10,6))
# calculate the no skill line as the proportion of the positive class
no_skill = len(y[y==1]) / len(y)
# plot the no skill precision-recall curve
plt.plot([0, 1], [no_skill, no_skill], linestyle='--', label='No Skill')
# plot the model precision-recall curve
plt.plot(recall, precision, marker='.', label='LogisticRegression')
plt.fill_between(recall, precision, step='post', alpha=0.3, color='k')plt.xlabel('Recall')
plt.ylabel('Precision')
plt.legend()
plt.title('Precision-Recall curve: Average Precision = {0:0.2f}'.format(avg_prec))
LightGBM 和 Logistic 回归的集成
堆叠概括提供了一种利用异质分类方法集合的集体辨别能力的机制。这包括使用顶级分类模型,该模型能够从基础级模型的预测(和分类偏差)中学习,以实现更大的分类能力。考虑到 XGBoost 和 LightGBM 来自同一个家族,我们将选择 LightGBM 和 Logistic 回归模型用于集成方法。
kfold = model_selection.KFold(n_splits=10, shuffle=True, random_state=42)# create the sub models
estimators = []
model1 = LogisticRegression()
estimators.append(('logistic', model1))model2 = LGBMClassifier()
estimators.append(('lgb', model2))# create the ensemble model
ensemble = VotingClassifier(estimators)
= model_selection.cross_val_score(ensemble, trainX, trainY, cv=kfold)print(results.mean())
这种性能比逻辑回归好不了多少,但远不如前两种模型。因此,我们将拒绝这一点。
使用无监督的 LightGBM 模型,我们实现了 0.90 的平均精度。我们将尝试安装自动编码器,以检查无监督模型是否带来更好的准确性。
自动编码器:
这里,我们将通过对欺诈案例的数量进行过采样来调整我们的训练集。我们希望将更多欺诈案例添加到我们的数据集中,以便我们训练的自动编码器能够更容易地将有效交易与欺诈交易分开。
oversample_multiplier = 100
trainX_original = trainX.copy()
trainY_original = trainY.copy()
testX_original = testX.copy()
testY_original = testY.copy()trainX_oversampled = trainX.copy()
trainY_oversampled = trainY.copy()trainX_oversampled = trainX_oversampled.append( \[trainX_oversampled[trainY==1]]*oversample_multiplier, ignore_index=False)
trainY_oversampled = trainY_oversampled.append( \[trainY_oversampled[trainY==1]]*oversample_multiplier, ignore_index=False)trainX = trainX_oversampled.copy()
trainY = trainY_oversampled.copy()model = Sequential()
model.add(Dense(units=20, activation='linear',
activity_regularizer=regularizers.l1(10e-5), input_dim=7,name='hidden_layer'))model.add(Dropout(0.02))
model.add(Dense(units=1, activation='linear'))
model.compile(optimizer='adam',loss='mean_squared_error',metrics=['accuracy'])num_epochs = 5
batch_size = 32history = model.fit(x=trainX, y=trainY,epochs=num_epochs,
batch_size=batch_size,shuffle=True,validation_split=0.20,verbose=1)
predictions = model.predict(testX, verbose=1)
anomalyScoresAE = anomalyScores(testX, predictions)
preds, average_precision = plotResults(testY, anomalyScoresAE, True)
基于精度-召回曲线的测试的平均精度是 0.40,这是数据的最差表示。我们可以尝试将监督和非监督结合起来,创建一个半监督模型来检查性能。然而,由于我们现有的数据是有标记的,无监督算法可能会带来更好的结果。
精确召回曲线的阈值:
fscore = (2 * precision * recall) / (precision + recall)
ix = argmax(fscore)
print('Best Threshold=%f, F-Score=%.3f' % (thresholds[ix], fscore[ix]))no_skill = len(testY[testY==1]) / len(testY)
plt.plot([0,1], [no_skill,no_skill], linestyle='--', label='No Skill')
plt.plot(recall, precision, marker='.', label='LightGBM')
plt.scatter(recall[ix], precision[ix], s=(10*2)**2, marker='s', color='black', label='Best')plt.xlabel('Recall')
plt.ylabel('Precision')
plt.legend()
plt.show()
可以进一步调整该图以获得最佳性能;然而,在这里,最佳 F1 分数被标注为阈值 0.74。
生产管道:
一旦我们确定了用于生产的模型,让我们设计一个简单的管道,对新的传入数据执行三个简单的步骤:加载数据,缩放特征,并使用我们已经训练并选择用于生产的 LightGBM 模型生成预测:
*# Pipeline for New Data*# first, import new data into a data frame called ‘newData’
# Scale all the variables to a range of 0 to 1
newData.loc[:, featuresToScale] = sX.transform(newData[featuresToScale])# third, predict using LightGBM
lgb.predict(newData, num_iteration=lgb.best_iteration)
关键要点
一个欺诈检测系统应该具有下面提到的一些属性,以使现实世界的商业意义。
- 该系统应该能够处理偏斜分布,因为所有交易中只有一小部分是欺诈性的。为了克服这一点,需要将训练集分成分布不那么偏斜的部分。
- 系统应该能够处理噪声,即数据中的错误。无论训练有多广泛,数据中的噪声都会限制归纳的准确性。
- 如果使用重采样技术,应该小心使用;它们不应该作为独立的解决方案使用,而必须与问题的返工相结合,以达到特定的目标
- 系统应该能够适应新类型数据。欺诈者总是不断改变他们的行为,因此,过一段时间后,成功的欺诈技术会降低效率。
- 良好的度量对于检查分类器性能至关重要。偏斜分布的总体高分并不意味着系统能够捕捉所有欺诈交易。
- 该系统还应考虑到检测欺诈交易的成本和阻止欺诈交易的相关成本。欺诈检测系统之上的决策层可能有助于降低成本。分类器和决策规则必须相对于最小化成本来设置。
结论:
随着时间的推移,解决方案将需要重新培训,因为欺诈的模式总是在变化。此外,我们可以试验其他 ML 算法,它们的性能与梯度提升一样好,并且可以将它们包括在集成中,以提高整体欺诈检测性能。通过足够的迭代,通常有可能找到一个适当的机器学习模型,在偏差与方差以及精度与召回之间取得正确的平衡。此外,可解释性对于机器学习的现实应用非常重要。我们将为下一次讨论保留可解释性。
如果不进行全面调查,永远无法确认财务欺诈,欺诈检测方法的进步可能会发出危险信号,警告利益相关方欺诈的可能性。
我可以到达 这里 。
忘记学习事实,专注于学习如何做人
人工智能如何改变我们使用信息的方式。
在工业革命的早期,对于大多数人来说,能够制作和执行体力劳动是赚钱的关键。在工厂工作 8 小时,在建筑工地工作,或者——如果你够幸运并且负担得起的话——为一份需要更多脑力而不是体力的工作而学习。随着机器的兴起,越来越多的艰苦体力劳动由早期的机器人完成。组装汽车或搬运重物被机器取代,我们慢慢进入了一个更加以知识为基础的经济。人工智能的兴起现在正在重复这一过程,但现在这项技术正在智力基础上更多地帮助我们。
从苦力到脑力
我是一个 80 后(更准确地说是 80 后),对我来说,我被告知记住信息是成功的关键。90 年代我在学校的时候,在接下来的几年里,我们没有谷歌、必应或任何其他形式的数字搜索引擎。我们被教导要记住尽可能多的信息,因为如果没有这些常识,你对工作社区的价值就会降低。我们正在过渡到一个知识时代,而不是启动工业革命的艰苦体力劳动时代。你可以看到这种转变,因为人们毕业的年龄越来越大,继续上大学的雄心也在迅速增长。我们现在有工具来部分自动化艰苦的体力工作,所以现在每个人都想通过使用他们的大脑来赚钱。公司为聪明人付了很多钱。
“我们是以信息为导向的,你的学位将是伟大事业的保证。”
所以我接受教育的目标是尽可能多的学习,尽可能的得到最高分,在任何类型的测试中达到最高分。当然,我们慢慢有了像早期的谷歌和类似的搜索引擎这样的工具,但这仅仅是为了查找你必须记住的信息。软技能是一个没有人听说过的词,更不用说将其作为你未来工作的一项资产了。我们是信息驱动的,你的学位将是伟大事业的保证。没有人想学习成为一名木匠、瓦工或擦窗工。我们被告知“努力学习,你会有所成就的”。软技能工作是为那些想成为心理学家或社会工作者的人保留的。
你的知识不在你的脑袋里,而是在你的指尖
人工智能如何改变我们从事体力工作的方式,同时满足我们对信息的持久需求?首先,人工智能擅长帮助我们做体力活。一个现实生活中的例子是连接到虚拟现实设备和手持控制器的机器人手臂,以执行精确的工作。通过深度学习,它能够学习不同的任务,如装沙拉或叠毛巾,只需对信息进行微小的调整。没有“仅仅会叠毛巾”——作为一个单一的任务——它可以学习新的技术并扩展它的一系列动作。在某种程度上类似于我们人类,能够像我们一样学习新的物理技术。
现在,我们正在进入一个机器覆盖物理部分的时代,这意味着人类可以更加专注于知识。但是,身处 2020 年的我们,还需要我们大脑中所有的精确知识、事实和细节吗?我个人很怀疑。我们觉得有必要存储所有这些信息,并根据你拥有多少事实知识来确定你有多“聪明”,这可能仍然是一种自我或声望的事情,但这仍然值得吗?如今,你可以在 Google Home 或 Siri 上问任何维基百科上有价值的问题,并在 2 秒内得到答案,这比我解锁手机主屏幕和打开谷歌还快。当然,手头有知识会派上用场,但在大多数情况下已经不再需要了。事实上,我们大多数人不是一直带着 4G 手机甚至 Siri 吗?事实上,所有的答案不都在我们的指尖或牛仔裤的口袋里吗?我们真的应该用我们(不断发展的)手机、平板电脑、智能扬声器等现成的琐碎信息来加重我们大脑的负担吗?
忘记琐碎的事实,专注于做人
我们现在正在应对如此多的现代挑战,这些挑战不需要太多的“顶级知识”,而是需要更多的理解和执行让我们与众不同的东西。我们人类是世界上最有创造力的生物(或者至少有足够的创造力让我们认为自己是)。我们也有强大的道德指南针,这是人工智能所缺乏的东西你可以在我以前的一篇文章中读到。我们不应该再想去回忆西尔斯大厦有多高,或者哪位将军在 1729 年的一场战斗中骑着白马。这是我们在几秒钟内从我们的人工大脑(谷歌、Siri、Alexa 等)接收到的信息类型。)如果你愿意的话。
图片 1 :来自品牌人性化论文 (2018)的人类与机器人
我们确实需要投资于人工智能(还)无法从我们手中接管的事物。理解人类情感、处理道德问题、发挥创造力、管理工具和人员。我们在 2018 年发表的品牌人性化论文 Jonathan Flores 和我自己做了一个“机器人 vs 人类”的概述(图 1)。它显示了两者的优势和弱点,并显示了机器人和人类在不同领域的优势。机器人可以防止错误,运行重复性任务,全天候工作,并存储难以置信的大量信息和数据。那么,为什么我们还想用我们有限的大脑来储存信息呢?我们将做人工智能能做的事情,只是数量少得多,而且有丢失数据的风险。更确切地说,我们会关注机器人缺少我们所拥有的东西的领域。如果我们专注于更软的技能,我们实际上可以拥有 AI/Robots/ML 或任何你更喜欢的工具来做它最擅长的事情:成为一台机器,使用数据和体力来支持我们的日常生活。让我们——人类——专注于我们最擅长的事情,那就是创造性和人性。
你怎么想呢?
我们需要继续专注于在大脑中存储知识和事实,还是应该利用人工智能来为我们记住非关键信息?
忘了 Python 吧。学习 COBOL,成为危机英雄
意见
为什么编程恐龙是现在最受欢迎的语言
仍然有一些恐龙存在——而且需求量很大。乌曼诺德在 Unsplash 上拍摄的照片
目前仍在市场上销售的最古老的编程语言是什么?Python 三十多岁了。c 快五十岁了。Fortran 已经 60 年代了。而且还在用!
还有另一种计算机语言恐龙被广泛使用。一个你可能从未听说过的故事。遇见六十多岁的 COBOL。
80%的个人交易和 95%的 T4 提款机都使用 COBOL,它是货币的编程语言。超过 2000 亿行 COBOL 今天仍在使用,所有这些都需要维护。
现在比以往任何时候都多。随着失业索赔的激增,古老的——基于 COBOL 语言的——社会保障系统超负荷运转。所以管理者愿意做任何事情来得到 COBOL 程序员。
因此,如果你想获得一些大的薪水,并做一些事情来帮助那些受这场危机影响的人,COBOL 是一条出路。
为什么没人知道 COBOL 了…
首先,因为 COBOL——通用面向业务的语言——是面向业务人员的语言,而不是面向程序员的语言。它的设计是为了让一个没有代码知识的商人明白发生了什么。这意味着代码背后的程序员的福祉不是优先考虑的。
COBOL 有许多语法上的奇怪之处,这使得它适合商业,但不适合铁杆书呆子。比如它没有任何函数或子程序,而是有分部、章节、段落和语句。非常令 20 世纪 70 年代的系统编程先驱们厌恶。
“使用 COBOL 语言会使大脑瘫痪;因此,其教学应被视为刑事犯罪。”埃德格·w·迪杰斯特拉
但那时已经太晚了。银行和官僚机构的核心代码已经建立。
许多银行和联邦机构仍然使用 COBOL。马库斯·伦克在 Unsplash 上的照片
…为什么它仍然无处不在
考虑到 COBOL 奇怪的结构,你可能会认为它是由不知道计算机代码是什么的人编写的。远非如此。围绕着传奇人物格蕾丝·赫柏的一个了不起的团队使它的发展成为可能。
与五十年代的编程语言相比,COBOL 是一场革命。它易于使用和理解,可移植,独立于机器,并且能够改变。所有这些只需要很小一部分成本。这是一种直接来自未来的语言。
所以它被到处采用:银行,保险,联邦政府机构,你能想到的。到 1970 年,几乎没有一个系统不是用 COBOL 编写的。
矛盾的是,事实上是新语言的出现——如 Fortran & co——巩固了 COBOL 的遗产。商业计算机语言在 80 年代被宣布死亡,这一趋势发展如此之快,以至于新程序员甚至懒得学习它。因此,虽然有足够多的老程序员来维护现有的代码,但却没有足够多的合格人员来将代码转换成更新的语言。
快进到 2020 年:虽然代码维护人员几十年来在保持联邦系统坚如磐石方面做了令人难以置信的工作,但没有人预料到需求会如此激增。突然间,我们需要更多的实践平台来应对这场危机。
[## 重温你的 COBOL:为什么一门 60 年前的语言突然大受欢迎?-堆栈溢出博客
突然变得紧张的失业系统通常运行在一种有 60 年历史的编程语言 COBOL 上。所以,你怎么能…
stackoverflow.blog](https://stackoverflow.blog/2020/04/20/brush-up-your-cobol-why-is-a-60-year-old-language-suddenly-in-demand/?utm_source=Iterable&utm_medium=email&utm_campaign=the_overflow_newsletter)
需求极高
“我们全国各地的许多劳工部仍在使用 COBOL 系统。你知道非常非常古老的技术。[……]我们的劳工部已经认识到这是一个问题,并启动了现代化,不幸的是,这需要时间。这种(病毒)干扰,他们不得不停止过渡到一个更强大的系统。所以他们在用非常旧的东西做手术。”——劳拉·凯利,堪萨斯州州长
随着失业率一飞冲天,几个州的州长正在争相寻求帮助。突然间,他们需要升级系统,而在正常情况下,这些系统需要数年时间才能实现现代化。突然间,一切都失控了。
新泽西州州长甚至在电视上露面来传播这个消息。IBM 一直试图通过发布 COBOL 程序员的呼叫来提供帮助,但是搜索仍然很困难。
现在非常需要知道如何编码的人。具体来说就是懂 COBOL 的人。
不性感,但值得
这不是你的酷屁股热新编程语言。这甚至不是 Python——阅读我文章的人都知道我对后者又爱又恨。这不是一些性感的数据科学,或怪异的人工智能,或两者兼而有之。
如果你选择使用 COBOL,你很可能是在做维护工作。你在吸收几十年前的商业逻辑,而不是开发前沿算法。你在计算机科学的石器时代工作,使用的技术看起来仍然像是为那些过时的打孔机卡设计的。
但是现在你不能做任何更重要的事情。数百万人已经失业。尽管许多州已经重新开放,但经济反弹不太可能。
这意味着我们将会看到另外几百万人失业。很多很多人将需要这些国家福利来维持生活。而目前的情况——有些人已经给他们的办公室打了上百次电话——不仅仅是绝望。
所以如果你能帮忙的话,你应该去做。COBOL 并不性感——但是,让我们面对现实吧,帮助人类是性感的。从这个意义上说:快乐编码!
这门 Udemy 课程并不是完全免费的,但至少从 175 美元降到了 10 美元左右。如果您想建立自己的 Corona 编程技能,不妨一试。
www.udemy.com](https://www.udemy.com/course/mainframe-the-complete-cobol-course-from-beginner-to-expert/)
厌倦了被告知新冠肺炎方向每两天改变?
忘记每日统计,遵循正确的 KPI!
索菲·戴尔在 Unsplash 上的照片
我们[和媒体!]过于看重日常数字。
对于大多数国家来说,病例统计遵循一个周模式,在周末达到最低点。
用过去 7 天的滚动平均值代替每日数据及其解释会带来一些决定性的优势:
- 清晰的趋势而不是摇摆不定、令人困惑的模式。
- 减少 60%的误解(即草率的结论)。
让我们放大意大利数据来更好地理解这种效果:
[疫情爆发以来新增确诊新冠肺炎病例(>每百万人口 5 例)。每日统计(蓝线)与连续 7 天平均值(绿线)。
图表显示:
- 每日确诊病例 ( 蓝线)。
- 确诊病例的滚动 7 天平均值(绿线)。这是按照当天和过去 6 天的平均值计算的。
- 周末(灰色阴影区域)。
在每个图表中,两个指标中的一个用粗线突出显示。现在让我们添加箭头来表示观察到的方向变化:
[疫情爆发以来新增确诊新冠肺炎病例(>每百万人口 5 例)。每日统计数据(蓝线)与 7 天滚动平均值(绿线)。箭头表示指标的方向性变化。
在左侧,每次我们观察到一个微逆趋势时,我们都会看到一个红色箭头,即每日数据的方向变化与主趋势相反。9 次我们得到了一个“错误信号”(或者说“曲解”)。
在右边,我们没有一个错误的信号!单一方向变化对应于宏观趋势在三月底的正确突破——由绿色箭头指示。****
现在我们很容易意识到,意大利已经连续 4 周呈持续下降趋势。
我们所认定的“错误信号”就是我们一开始所说的“误解”或“草率结论”。我们在计算中使用的确切定义是:
如果在不到 5 天的时间内恢复方向,则方向变化被视为“对数字的误解”。
回到整体数据集。
我们使用了来自 JHU 的数据,并分析了 117 个国家从 2020 年 4 月 20 日到 2020 年 4 月 20 日的病毒单独爆发(>每百万人口 5 例)的数据。这些国家的误解平均减少了 60% 。对许多国家来说,降幅甚至更高。这些国家的例子包括:
美国:73%;意大利:95%,德国:91%,西班牙:83%
让我们快速看一下这些国家:
自疫情爆发以来新增确诊新冠肺炎病例(>每百万人口 5 例)。每日统计(蓝线)与连续 7 天平均值(绿线)。
O 很明显,7 天的滚动平均值(绿线)再次比每日数据平滑。但更重要的是——滚动平均值改变方向的次数要少得多!
死亡人数
针对确诊病例显示的效果也适用于死亡病例。在该指标上应用滚动平均,我们会获得相同的优势。
是什么导致了周线模式?
这种模式(主要是每周一次)可能有不同的原因:
- 周六和/或周日测试较少。
- 周末进行测试的记录延迟。
即使“季节性”的原因是另一个,通过取 7 天平均值来平滑数据会使结果更加稳定。
预言
数据中季节性模式的存在也应纳入预测模型。季节性效应的调整使得预测更加准确并且其可信度(或置信度)区间更窄。
已经有很多非常好的预测模型,例如
2020 年 3 月 30 日,帝国理工学院,评估 11 个欧洲国家的新冠肺炎感染人数和非药物干预的影响。
这项研究考察了各国采取的不同干预措施:禁止活动、关闭学校、封锁等。,其影响通过减少再现数 R0 (或 Rt)来衡量。非常有趣的阅读!
最终注释
普通人每隔几天就会看到新冠肺炎数字改变方向,这并没有什么好处。相反,它制造了更多不必要的恐慌和不确定性。
毕竟,这些方向的快速转变与成功实施的干预(如“呆在家里”)无关,而往往是周末的产物。因此,同样:
使用滚动 7 天平均线!
想看看自己国家的数据吗?
几周前,我开发了一个微型网络应用程序来可视化冠状病毒病例统计。现在我添加了 7 天滚动平均值,所以如果你想查看你所在国家或美国各州的数据,请点击以下链接:
Web App截图,可在https://go.aws/2xsdb7q访问。该应用程序显示了 历史每日病例数据加上来自 JHU 数据集的所有国家 , 加上美国各州和中国各省 。
而如果你想自己(用 R 或者 Python)创建这样一个 app 的话,查看我更多的技术 101 篇: R 版 , Python 版 。
忘记锚盒与 FCOS 的争论:完全卷积的一阶段目标检测
信用: FCOS
本文详细解释了一种新的目标检测技术,该技术在 ICCV 19 年发表的论文 FCOS :全卷积一阶段目标检测中提出。我决定总结这篇论文,因为它提出了一种非常直观和简单的技术来解决对象检测问题。留下来了解它是如何工作的。
内容
- 基于锚的检测器
- FCOS 提出的想法
- 多级检测
- FCOS 的中心
- 基于锚的检测器的实验和比较
- 结论
基于锚的检测器
我们现在使用的每一种著名的物体检测方法(Fast-RCNN,YOLOv3,SSD,RetinaNet 等。)使用锚点。这些主播基本都是预定义的训练样本。它们有不同的比例,以方便不同种类的对象及其比例。然而,正如你从它们的定义中清楚理解的那样,使用锚涉及到许多超参数。例如,图像的每个部分的锚的数量、框的尺寸的比例、图像应该被分成的部分的数量。最重要的是,这些超参数影响最终结果,即使是最微小的变化。此外,哪个边界框被认为是负样本还是正样本由另一个称为并集上的交集(IoU)的超参数决定。IoU 值极大地改变了哪些盒子将被考虑。下面是一个简单的图像,描述了在 Yolov3 中锚定框的使用:
我们一直在使用这种方法,原因只有一个,那就是延续以前方法使用的理念。第一个物体检测器从经典计算机视觉的早期检测模型中借用了滑动窗口的概念。但是,既然我们拥有多个 GPU 的计算能力,就没有必要使用滑动窗口了。
FCOS:提议的想法
这就引出了一个问题,为什么还要使用锚点,为什么不像分割那样执行对象检测,即像素方式。这正是本文所要提出的。到目前为止,通过使用滑动窗口方法,在图像的逐像素值和检测的对象之间没有直接的联系。现在让我们正式看看这种方法是如何工作的。
设 Fᵢ 为总跨度 s 的骨干 CNNI层的 Fᵢ⁰ 特征图。此外,我们将图像的地面实况包围盒定义为 Bᵢ = ( x⁰ᵢ,y⁰ᵢ,x ᵢ,y ᵢ,cᵢ ) ∈ R₄ × {1,2 … C} 。这里是 C 是班级人数。这里 (x⁰ᵢ,y⁰ᵢ)****(xᵢ,y ᵢ) 分别表示左上角右下角。对于特征图上的每个位置 (x,y) ,我们可以将其指向原始图像中的一个像素。这与我们在语义分割中所做的事情类似(尽管不完全相同)。我们将特征图上的 (x,y) 映射到感受野中心附近的点 (floor(s/2) + xs,floor(s/2) + ys) 。我鼓励用户使用大小为(8,8)的示例图像和大小为(4,4)的特征图来真正理解这种映射。在这种映射的帮助下,我们能够将图像中的每个像素作为训练样本进行关联。这意味着,每个位置 (x,y) 可以是正样本或负样本之一,这取决于以下条件:它落在地面真实(GT from now)边界框中,并且为该位置计算的类标签是该 GT 边界框的类标签。
现在我们知道了 GT 边界框中的一个点,我们需要评估这个框的尺寸。这是通过对四个值 (l、t、r、b)的回归来完成的。它们被定义为:
l * =x-x⁰ᵢ;t * =y-y⁰ᵢ;r * = x⁰ᵢ-x;b = y⁰ᵢ-y*
最后,正如您将看到的,这些值的基于回归的计算是整个检测算法的损失函数的一部分。
现在,因为没有锚点,所以不需要计算锚点和 GT 边界框之间的 IoU 来获得可以训练回归器的正样本。相反,给出正样本的每个位置(通过在 GT 框内并具有正确的类)可以是边界框尺寸回归的一部分。这是 FCOS 比基于锚的检测器工作得更好的可能原因之一,即使在使用更少数量的参数之后。
对于特征图中的每个位置,我们计算分类分数,对于每个正样本位置,我们进行回归。因此,总损失函数变为:
信用: FCOS
对于本文, λ 的值取为 1。
RHS 的第一部分是位置分类 (x,y) 。RetinaNet 中使用的标准焦点 loos 也在这里使用。RHS 的第二部分是回归包围盒。对于不是正样本的位置,它等于零。
信用: FCOS
用 FCOS 进行多层预测
多级预测基本上意味着使用不同级别的特征图进行对象检测。这类似于 RetinaNet 中使用的 FPNs(特征金字塔网络)的概念。探测器头应用于几个级别的特征图,P3,P4,P5,P6,P7 如上图所示。这有助于我们检测图像中不同大小的对象。这有助于解决重叠 GT 边界框的问题。如果两个不同大小的边界框相互重叠会怎样。这是用多级预测来处理的。与基于锚的检测器不同,基于锚的检测器将不同大小的锚框分配给不同的特征级别,从而在不同的级别分离不同大小的重叠 GT 边界框,像 FCOS 这样的无锚检测器通过在不同的特征地图级别限制回归来实现这一点。它们为所有要素级别(P3 至 P7)定义了一个值 mᵢ,该值设置为 0、64、128、256、512 和无穷大,P2 为 0,因此没有要素级别。基本上是特征级别 I 需要回归的最大距离。例如,特征级别 P7 需要回归其中 max(l,r,t,b) < infinity 但是大于下一个 m 的值,即 512 的盒子。同样,它也适用于其他功能级别。此外,如果一个位置即使在多级检测后仍被分配给一个以上的 GT 箱,它将被自动分配给两个 GT 箱中较小的一个。
FCOS 的中心
信用: FCOS
除了两个传统的探测头,分类和回归,FCOS 建议使用第三个头,称为中心头。顾名思义,它是对为其回归的边界框内的正样本位置的中心性的度量。这是为了提高无锚检测器的性能,并使它们与基于锚的检测器不相上下。从经验上来说,我们发现,就特征在盒内的位置而言,具有偏斜特征位置的低级回归盒会妨碍整体结果。因此,上面的项是使用 BCE 损失对每个回归的盒子进行计算的,因为它的范围是从 0 到 1。这个损失被加到上面讨论的最终损失函数中。测试时,在对推断出的边界框进行排名之前,将该值乘以分类分数以获得最终分数。
实验和与基于锚的最新技术的比较
信用: FCOS
上表显示了与 RetinaNet 的比较,retina net 是一个最先进的基于锚点的模型。具有多级预测和中心分支的原始实现在其他参数方面优于 RetinaNet,例如。两种型号的 nms 阈值设置相同。上表中提到的“改进”是在最初提交后增加的。它们包括以下内容:将中心性分支移动到回归分支而不是分类分支,控制采样,这基本上是添加基于超参数的去除坏样本以及中心性分支。其他补充请点击这个链接。
信用: FCOS
上表很有趣,因为它强调了中心性分支带来的改进。基于锚的模型采用 IoU 阈值,同时对正负锚盒进行分类。中心性分支有助于消除这些超短波。
需要注意的非常重要的一点是,重要的超参数如学习率、NMS 抑制阈值等。直接取自 RetinaNet。通过专门针对无锚模型进行更好的超参数调整,有可能获得更好的结果。
结论
FCOS 是一个伟大的想法,使对象检测问题更简单,更快。这是对远离基于锚的滑动窗口的目标检测思想的鼓励。这可以在解决这个棘手的计算机视觉问题上带来巨大的成果。
这就是所有的乡亲😃
你可以在我的Github上看更多深度学习相关的东西,关注我的Linkedin。
我之前的一些文章:
[## 关于 Auto-Deeplab 你需要知道的一切:谷歌关于细分的最新消息
搜索图像分割模型
towardsdatascience.com](/everything-you-need-to-know-about-auto-deeplab-googles-latest-on-segmentation-181425d17cd5) [## 关于 MobileNetV3 及其与以前版本的比较,您需要了解的一切
论文综述:寻找 MobilenetV3,ICCV 19
towardsdatascience.com](/everything-you-need-to-know-about-mobilenetv3-and-its-comparison-with-previous-versions-a5d5e5a6eeaa) [## 使用辅助旋转损耗的自监督 GANs
弥合有监督和无监督图像生成之间的差距
towardsdatascience.com](/self-supervised-gans-using-auxiliary-rotation-loss-60d8a929b556) [## 使用专门为其制作的损失来处理类不平衡数据
通过添加大约 10 行代码,在严重的类不平衡数据上获得超过 4%的准确性提升。
towardsdatascience.com](/handling-class-imbalanced-data-using-a-loss-specifically-made-for-it-6e58fd65ffab)
从计算机视觉到深度学习:工业应用中的人工智能创新之路
机器视觉如何演变成深度学习来提供一双额外的眼睛
图片由 Flickr 提供
在让制造工厂在面对间歇性人类劳动力的情况下提高产量的竞赛中,制造商正在考虑如何为他们的摄像机配备人工智能,以使人类检查员能够立即发现有缺陷的产品并纠正问题。
虽然机器视觉已经存在了 60 多年,但最近深度学习的流行已经使这种有时被误解的技术引起了全球主要制造商的注意。作为一家深度学习软件公司的首席执行官,我已经看到深度学习是机器视觉的自然下一步,并有可能推动制造商的创新。
深度学习与机器视觉有何不同,制造商如何利用相机技术的这种自然演变来应对现实世界的需求?
机器视觉:当简单太简单的时候
在 20 世纪 60 年代,几组科学家,其中许多在波士顿地区,着手解决“机器视觉问题”该方法简单而强大:科学家提出了一个框架,其中机器视觉系统由两个步骤来表征。
首先,科学家决定哪些简单的特征——图像中的边缘、曲线、色块、角落和其他突出的关键点——对图像来说是重要的。第二,他们设计了一个分类器,通常手动调整几个“阈值”(例如,多少“红色”和“曲率”将一个对象分类为“红苹果”),自动衡量这些特征并决定它们属于哪个对象。虽然这种方法远非人类视觉能力的完整表征,但它简单有效,足以在 50 年内保持不变。
在这种原始形式下,它支持大量现实世界的应用,并成为制造应用的重要组成部分,从那以后一直为质量控制部署提供动力。
在视觉检查示例中,可以部署机器视觉系统来搜索产品图像中的缺陷。第一步通常是通过计算对比度、边缘、颜色和其他特征对产品图像进行采样,因为它们可能指示了物体中的缺陷。第二步,质量检查员将手动调整分类器,以确定产品是否有足够的“可疑特征”来最终确定损坏。
这种方法在某些情况下简单而强大,但在许多其他情况下却非常无效,因为它在好的产品属性和缺陷之间的差异是高度定性的、微妙的和可变的情况下失败了。然而,这就是我们生活的世界的本质。
机器视觉的答案是:创建更多的功能和阈值,稳步攀升到更高的复杂性,使这些系统变得极其复杂,即使是最有经验的工程师和操作员也难以调整。
深度学习之路:将智能从人类转移到软件
神经网络——以及它们的子类,深度学习,就在这里。图片由 Piqsel 提供
在 80 年代,当机器视觉风靡一时时,一小群对弥合生物系统和机器之间的差距感兴趣的科学家开始尝试模仿大脑视觉系统中的神经元及其架构。目标是更好地理解我们如何感知,并在此过程中,设计出“看”得更好的机器。
在那些年里,今天的深度学习模型的前身被开发出来。关键是:自组织。重要的是,这些模型和后来的深度学习表兄弟不依赖于传统机器视觉的两个手动调整的步骤。相反,他们将寻找(学习)这些特征和阈值的负担从科学家转移到深度学习模型。科学家们仍然需要开动脑筋,设计出能够直接从数据中进行广义学习的方程,但现在只需要做一次。
这确实是深度学习的关键 : 我们不需要为每种情况手工制作一个机器视觉模型,而是设计一个可以直接从数据中学习几乎任何东西的学习机器,无论是对水果、飞机还是机器中的产品进行分类。
深度检测:将人工智能的能力和灵活性带到每一台制造相机上
在机器视觉主导的质量控制领域,深度学习代表着一种至关重要的创新,特别是在需要用更少的人完成越来越多的工作的时候。
随着机器能够以每分钟轻松超过 60 件的速度生产极其多变、不断变化的产品,深度学习正在改变机器视觉的格局,特别是结合了边缘学习(或直接在相机/机器中学习的能力)的产品。
今天,在机器的边缘节点上运行的深度学习使数十台摄像机能够在不断引入新项目的可变生产环境中学习新的项目类型和缺陷,并且新的、以前未见过的缺陷出现在生产线上。机器视觉无法完成这项任务——有太多专门的、手动调整的功能和阈值,每个产品都有自己非常复杂的要求。深度学习降低了优化质量检测的成本和时间,使其在技术和经济上对所有类型的制造商都可行。
深度学习是一种范式转换技术,它通过将智能从工程师和质量检查员转移到一个在计算边缘持续运行的软件,在需要的速度、延迟和成本方面为工业 4.0 革命开辟了一条清晰的道路,从而使高效实现 100%检查成为可能。
虽然机器视觉已经达到了目的,但深度学习相机将为这个从未如此需要突破的领域带来创新。
Python 中的格式函数
Python 的 string 类别的 str.format() 技术允许您尝试进行变量替换和数据格式化。这使您能够通过点数据格式以所需的间隔连接字符串的各个部分。
本文可以引导您了解 Python 中格式化程序的一些常见用法,这可能有助于您的代码和程序对用户友好。
1)单一格式化程序:
格式化程序的工作方式是将一个或多个替换字段或占位符(由一对方括号 "{}" )固定成一个字符串,并调用 str.format()技术。您将把希望与字符串连接的值传递给 format()方法。运行程序后,该值将打印在占位符{}所在的位置。单格式器可以定义为只有一个占位符的格式器。在下面的例子中,你可以看到 print 语句中 format 的实现。
print("{} is a good option for beginners in python".format("Research Papers"))**OUTPUT:** Research Papers is a good option for beginners in python
除了在 print 语句中直接使用它之外,我们还可以对变量使用 format()
my_string = "{} is a good option for beginners in python"print(my_string.format("Research Papers"))**OUTPUT:** Research Papers is a good option for beginners in python
2)多重格式化程序:
比方说,如果一个句子中需要另一个变量替换,可以通过在需要替换的地方添加第二个花括号并将第二个值传递给 format()来实现。然后 Python 会用输入中传递的值替换占位符。
my_string = "{} is a good option for beginners in {}"
print(my_string.format("Research Papers","Machine Learning"))**OUTPUT:** Research Papers is a good option for beginners in Machine Learning
我们可以在给定变量中添加任意数量的占位符或花括号,并为格式()添加相同数量的输入。
my_string = "{} is an {} option for {} in {}"
print(my_string.format("Research Papers","excellent","experienced","Machine Learning"))**OUTPUT:** Research Papers is an excellent option for experienced in Machine Learning
3)使用位置和关键字参数的格式化程序:
当占位符为空{}时,Python 解释器将通过 str.format()按顺序替换这些值。
str.format()方法中存在的值主要是 tuple(“tuple 是一系列不可变的 Python 对象”)数据类型,tuple 中包含的每个单独的项通常由其索引号引用,索引号从零开始。然后,这些索引号被传递到原始字符串中的花括号中。
您可以使用花括号中的位置参数或索引号,以便将特定值从格式()中获取到变量中:
my_string = "{0} is a good option for beginners in {1}"
print(my_string.format("Research Papers","Machine Learning"))**OUTPUT:**
Research Papers is a good option for beginners in Machine Learningmy_string = "{1} is a good option for beginners in {0}"
print(my_string.format("Research Papers","Machine Learning"))**OUTPUT:**
Machine Learning is a good option for beginners in Research Papers
关键字参数通过调用花括号内的变量名来帮助调用 format()中的变量:
my_string = "{0} is a good option for beginners in {domain}"
print(my_string.format("Research Papers",domain = "Machine Learning"))**OUTPUT:** Research Papers is a good option for beginners in Machine Learning
我们可以同时使用关键字和位置参数:
my_string = "{domain} is a good option for beginners in {0}"
print(my_string.format("Research Papers",domain = "Artificial Intelligence"))**OUTPUT:**Artificial Intelligence is a good option for beginners in Research Papers
4)型号规格:
通过使用格式代码语法,可以在语法的花括号中包含更多的参数。在此语法中,无论 field_name 在哪里,它都会指定参数或关键字对 str.format()技术的指示符,而 conversion 是指数据类型的转换代码。一些转换类型包括:
s-字符串
d —十进制整数(以 10 为基数)
f——浮动
c-字符
b —二进制
o-八进制
x—16 进制,9 后面有小写字母
e —指数符号
my_string = "The Temperature in {0} today is {1:d} degrees outside!"
print(my_string.format("Research Papers",22))**OUTPUT:** The Temperature in Vizag today is 22 degrees outside!
确保使用正确的转换。如果您使用不同的转换代码,将会出现以下错误:
my_string = "The Temperature in {0} today is {1:d} degrees outside!"
print(my_string.format("Vizag",22.025))--------------------------------------------------------------------ValueError Traceback (most recent call last) in () ** 1** my_string = "The Temperature in {0} today is {1:d} degrees outside!" ----> 2 print(my_string.format("Vizag",22.025)) ValueError: Unknown format code 'd' for object of type 'float'
您甚至可以限制浮点整数中的小数位数:
my_string = "The Temperature in {0} today is {1:f} degrees outside!"
print(my_string.format("Vizag",22.025))**OUTPUT:**
The Temperature in Vizag today is 22.025000 degrees outside!my_string = "The Temperature in {0:20} today is {1:.2f} degrees outside!"
print(my_string.format("Vizag",22))**OUTPUT:** The Temperature in Vizag today is 22.02 degrees outside!
5)使用格式化程序的间距和对齐:
我们可以使用 format()将空格或对齐方式应用到占位符的右侧、左侧或两侧。对齐代码是:
< : left-align text
^ : center text
:右对齐
my_string = "The Temperature in {0:20} today is {1:d} degrees outside!"
print(my_string.format("Vizag",22))**OUTPUT:** The Temperature in Vizag today is 22 degrees outside!my_string = "The Temperature in {0} today is {1:20} degrees outside!"
print(my_string.format("Vizag",22))**OUTPUT:** The Temperature in Vizag today is 22 degrees outside!
我们可以看到字符串是左对齐的,数字是右对齐的。通过使用 format(),我们可以对它们进行如下修改:
my_string = "The Temperature in {0:>20} today is {1:d} degrees outside!"
print(my_string.format("Vizag",22))**OUTPUT:** The Temperature in Vizag today is 22 degrees outside!my_string = "The Temperature in {0:<20} today is {1:d} degrees outside!"
print(my_string.format("Vizag",22))**OUTPUT:** The Temperature in Vizag today is 22 degrees outside!my_string = "The Temperature in {0:^20} today is {1:d} degrees outside!"
print(my_string.format("Vizag",22))**OUTPUT:** The Temperature in Vizag today is 22 degrees outside!
6)整理资料:
我们倾向于在 Excel 表中组织数据,我们可以用各种方法调整列的大小,但是我们如何在程序中应用同样的东西,一列中的值以指数方式递增,一列中的项目进入另一列,或者最终用户可能会发现很难理解哪个值属于哪个列。
for i in range(4,15):
print(i,i*i,i*i*i)**OUTPUT:** 4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
11 121 1331
12 144 1728
13 169 2197
14 196 2744
在这里,我们可以使用 format()来定义每一列之间的间距,以便最终用户可以轻松地区分不同列的值。
for i in range(4,15):
print("{:6d} {:6d} {:6d}".format(i,i*i,i*i*i))**OUTPUT:** 4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
11 121 1331
12 144 1728
13 169 2197
14 196 2744
总结:
从上面的使用中,我们可以说,用于变量替换的格式化程序是连接字符串、转换值、组织值和数据的有效方法。格式化程序代表了一种简单但非描述性的方式,用于将变量替换传递到字符串中,并有助于创建某些可理解且用户友好的输出。
谢谢
用 Python 格式化字符串
如何在 Python 中使用 format()方法和 f 字符串
凯文·Ku 在 Unsplash 上的照片
介绍
python 中有多种格式化字符串的方法。我们将讨论 format()方法和 f 字符串,以创建以下内容:
我们将使用 first_name、last_name 和 age 变量来创建一个字符串,该字符串包含某人的名字、姓氏和年龄,格式如下:
'名字姓氏年龄岁'
一个例句是:“约翰·多伊今年 43 岁”。
使用 format()方法
实现这一点的一种方法是使用 format 方法。format()方法是一个字符串方法。一旦你从一个字符串中调用它,它会用括号中传递的变量值替换字符串中所有的花括号,按照它们被传递的顺序。因此,花括号充当变量的占位符。
例如,要使用上述示例的 format 方法,我们将使用以下代码:
first_name = 'John'
last_name = 'Doe'
age = 43sentence = '{} {} is {} years old'.format(first_name, last_name, age)print(sentence)
# 'John Doe is 43 years old'
注意:format 方法将按照变量在括号中出现的顺序用变量的值替换花括号。
如果我们不想担心以正确的顺序传递变量,我们可以在每个花括号中使用键,然后为该特定键分配变量:
first_name = 'John'
last_name = 'Doe'
age = 43sentence = '{first} {last} is {age_yrs} years old'.format(last=last_name, age_yrs=age, first=first_name)print(sentence)
# 'John Doe is 43 years old'
注意,如果我们为每个占位符使用特定的键,变量就不必以正确的顺序传递。
虽然 format()方法完成了这项工作,但是还有一种更好的格式化字符串的方法,那就是使用 f 字符串。
如何在 python 中使用 enumerate()函数
towardsdatascience.com](/looping-in-python-5289a99a116e)
f 弦
f 字符串是 Python 3.6 及更高版本中格式化字符串的一种新方法。对于大多数人来说,它们是格式化字符串的首选方式,因为它们易于阅读,因此更加直观。
f'{var_1} {var_2}是{var_3}岁'
要指定我们想要使用 f 字符串,或者格式化字符串,我们只需在字符串前面放一个 f。然后,我们可以直接将变量添加到我们的花括号中,在我们希望它们出现的位置。因此,我们不需要像使用 format 方法那样在字符串末尾使用任何方法或传递任何变量。这是一种更直观的格式化字符串的方式,因为我们不必确保所有的变量都与占位符的顺序相同,也不必确保它们被添加到正确的位置。
因此,为了用 f 字符串完成上述任务,我们将使用以下代码:
first_name = 'John'
last_name = 'Doe'
age = 43sentence = f'{first_name} {last_name} is {age} years old'print(sentence)
# 'John Doe is 43 years old'
与 format 方法类似,我们也可以在 f 字符串中运行方法或函数。例如,如果我们希望名字大写,姓氏小写,我们可以在 f 字符串中使用相应的字符串方法:
first_name = 'John'
last_name = 'Doe'
age = 43sentence = f'{first_name.upper()} {last_name.lower()} is {age} years old'print(sentence)
# 'JOHN doe is 43 years old'
如果你喜欢阅读这样的故事,并想支持我成为一名作家,考虑注册成为一名媒体会员。每月 5 美元,你可以无限制地阅读媒体上的故事。如果你用我的 链接 注册,我会赚一小笔佣金。
阅读卢艾·马塔尔卡的每一个故事(以及媒体上成千上万的其他作家)。您的会员费直接支持…
lmatalka90.medium.com](https://lmatalka90.medium.com/membership)
结论
在本教程中,我们快速了解了在 python 中格式化字符串的方法。我们首先看了 format()方法,然后看了更优雅和直观的 f 字符串。然后我们看到了如何在 f 字符串中使用方法或函数。
一级方程式大奖赛分析
一级方程式数据集的数据分析(1950-2017 年)
从我还是个孩子的时候起,ormula 1 就一直是我最喜欢的运动。极高的精确度、高准确度和优秀的团队是一个团队参与并赢得大奖赛的关键要素。当任何人决定独自行动时,团队要么失去位置,要么直接退出竞争。所有主要车队,如法拉利、迈凯轮、红牛、雷诺和许多其他车队都在争夺世界冠军。作为数据科学爱好者和 Formula1 的超级粉丝,我和 Vineet Viswakumar 决定分析我们从 Kaggle 获取的 Formula1 数据集,该数据集为我们提供了开放数据集,为我们提供了许多数据属性,如 Formula1 车手、比赛、圈速、赛季数据、进站状态和其他相关属性。
资料来源: GIPHY
TL;我们决定用各种可视化工具分析这个数据集,比如 Tableau、plotly、matplotlib、seaborn 和其他各种工具。事实证明,仪表板看起来非常有前途,并打开了分析这个巨大平台的潜力,这个平台对数据科学世界开放,可以分析历史和结果,并应用现代技术和方法,如机器学习、强化学习、ARIMA 建模和许多其他技术。
这是初步分析,以 Tableau 交互式仪表盘的形式呈现这个庞大的数据集:
甘特图:
线条图
甘特图描述了这一时期(1950 年至 2017 年)大奖赛的历史。这张图表很好地描述了 1950 年至 2017 年期间大奖赛的发生情况。
离散折线图:
折线图
线形图描述了一年中从一月到十二月所有大奖赛的分布情况。
符号映射:
符号地图
符号地图描绘了分布在世界各地的赛道。这显示了这一魅力事件在世界范围内的传播,其中突出显示的颜色表示赛道的位置。
圆形视图:
圆形图表
圆形图用各种颜色描述 F1 车手的国籍。除了是竞争最激烈的运动,这项运动也同样受到不同人群的喜爱。这些是参加大奖赛的车手的不同国籍。
气泡图:
泡泡图
气泡图描述了 F1 参赛车手的回合数,其中气泡的大小与各自车手在相应大奖赛中的回合数成正比。
堆积条形图:
堆积条形图
描述 F1 大奖赛参赛车手比赛状态的堆积条形图。这包括参加了世界各地组织的各种大奖赛的各个车手的各种状态。
查看分析 GitHub 的完整代码:
点击此处查看 Tableau 交互式仪表盘上的完整分析…
github.com](https://github.com/gandalf1819/Formula1)
点击此处查看互动画面仪表盘:
[## Tableau 公共
编辑描述
public.tableau.com](https://public.tableau.com/profile/chinmaynw#!/vizhome/Formula1Analysis/Sheet1)
我们将添加进一步的分析和更直观的图表来显示这一时期的趋势,以丰富结果并利用数据科学界的各种工具和方法获得有意义的见解!欢迎对改进分析提出任何建议或改进,我们希望听到您对这一主题的想法。虽然这仍然是一项由热爱运动动力和能量的选定爱好者追随的运动,但我们建议每个人都尝试一下!
正如 Formula1 的标语所说:“工程精神错乱!—从技术角度来看,现在是我们遵循相同思维模式的时候了!
一级方程式仪表盘:
一级方程式大奖赛仪表板
来源:吉菲
参考资料:
[1]https://www.kaggle.com/cjgdev/formula-1-race-data-19502017
一级方程式赛车预测
预测下一届 F1 大奖赛冠军的机器学习方法
由 Unsplash 提供
当我还是个孩子的时候,我大部分时间都和我的祖父母在一起。我的祖父是一个超级 F1 迷,所以每当大奖赛开始时,我们都会一起坐在沙发上,对着电视欢呼尖叫,直到比赛结束。
多年后,我仍然对这项令人难以置信的运动充满热情,所以我认为预测某个车手赢得大奖赛的可能性并将其与博彩公司的赔率进行比较会很有趣。该项目将分为三个部分:
- 数据收集
- 数据分析
- ML 建模
1。数据收集
在第一部分中,我将解释我是如何收集所有的数据以及数据背后的决策过程。
数据帧 _1:比赛
对于我的数据挖掘,我找到了两个很好的来源:Ergast F1 数据库和官方的一级方程式网站;它们基本上有相同的数据,但我使用了两者以获得更高的准确性和完整性。
我的第一个 dataframe 包含了从 1950 年到 2019 年所有锦标赛和比赛的信息,包括它们的位置和维基百科页面的链接。
数据帧 _2:结果
对于我的第二个数据帧,我遍历了每一年和每一轮的比赛文件,以查询 Ergast API 并获得关于所有车手成绩的信息。我包括了一些特征,如每位车手的发车位置和完赛位置,他们的车队,以及其他不太相关的变量,如出生日期、国籍和完赛状态,我将在后面探讨这些特征,以检查车手的年龄和他们的表现之间是否存在相关性,在他们的祖国比赛是否会有任何心理影响,或者一些车手是否比其他人更容易发生车祸。
数据帧 _3:驾驶员排名
在锦标赛中,积分是根据车手和车队完成比赛的位置来决定的。只有前 10 名车手获得积分,获胜者将获得 25 分。 Ergast API 提供冠军赛中每个车手和车队的积分、获胜次数和名次。因为积分是在比赛后授予的,所以我必须创建一个查找函数来转移同一锦标赛中以前比赛的积分。
DataFrame_4:构造函数排名
车队总冠军是在 1958 年首次颁发的,所以没有那一年之前的数据。数据挖掘过程与车手积分榜相同,最终在比赛前应用相同的查找功能来获取数据。
DataFrame_5:合格
获得合格时间数据是最棘手的部分,主要是因为 Ergast 数据存储库中的数据有一些漏洞,也因为合格规则在这些年里变化很大。自 2006 年以来,排位赛在周六下午举行,采用三阶段“淘汰赛”制度,赛车试图创造自己的最快圈速。过去,资格认证只包括一次或两次会议,导致我的数据框中缺少数据。我决定只考虑每位车手的最佳排位赛时间,不管那一年举行了多少场排位赛。最佳排位赛时间反映在发车位置上,所以我稍后会计算第一辆符合条件的赛车和其他赛车之间的累计时间差异,希望这可以让我知道一辆赛车比其他赛车快多少。
由于 Ergast API 有一些缺失的数据,我不得不使用 BeautifulSoup 抓取官方 F1 网站并为每条赛道添加在发车区页面中找到的表格。
DataFrame_6:天气
f1 中的天气对轮胎的选择、车手的表现以及车队的整体策略都有着重要的影响。我决定遍历 races_df 中附加的每个比赛的维基百科链接,并抓取天气预报。由于 wikipedia 页面没有一致的 html 结构,我需要查看一些不同的表,即使在这一点上,我仍然有许多丢失的值。但是,我注意到我可以在不同语言的相应页面中找到剩余的信息。然后,我使用 selenium 点击每个链接的意大利语页面,并添加缺失的天气数据。最终,我创建了一本字典来对天气预报进行分类,并绘制出我的结果。
2.数据分析
第一届世界车手锦标赛于 1950 年在英国银石赛道举行,只有 7 场比赛。几年来,每个赛季的大奖赛次数各不相同,最近几个赛季平均有 19 场比赛。比赛的地点也随着时间的推移而变化,这取决于赛道的适用性和其他财务原因。目前,只有意大利和英国大奖赛是自 1950 年以来唯一没有错过一个赛季的赛事。
历年来最受欢迎的电路
渐渐地,越来越多的非欧洲赛道被添加到 F1 锦标赛的合适主办城市名单中。这张地图显示了自赛季开始以来举行的所有大奖赛的地点。
自 1950 年以来的大奖赛地点
杆位有多重要?
在资格赛阶段,车手们试图在赛道上创造自己的最快时间,发车位置由车手的最佳单圈成绩决定,最快的是杆位。在杆位起步在超车更加困难的赛道上是至关重要的,除此之外,还有一个优势是可以在前方几米的正常赛道上起步,这条赛道通常更干净,抓地力更强。下图显示了在一些最受欢迎的赛道上以杆位起跑和赢得比赛之间的关系。
P1-Q1 相关
赛车在你的祖国有什么影响?
在你的祖国比赛的优势可以归因于支持者对车手的心理影响,以及在熟悉的情况下在家附近驾驶。条形图显示了这些年来登上领奖台的一些车手的国籍,以及他们在所有赛道比赛中获胜的百分比。尽管没有显示出明显的差异,但我们可以注意到,甚至心理因素也在赢得比赛的可能性中发挥了作用。
按国籍划分的获奖者
最危险的电路
近年来,一些电路布局已经过重新设计,以满足更严格的安全要求。目前,大多数赛道都是专门为比赛建造的,以避免长而快的直道或危险的弯道。然而,一些比赛仍然在街道赛道上举行,如摩纳哥大奖赛,尽管不符合最新的严格措施,但仍主要因其名气和历史而被使用。下面的树形图按照事故或碰撞的数量显示了一些最受欢迎的赛道。
事故最多的危险线路
哪些车队出现了更多的汽车故障?
条形图显示了在过去几个赛季中参加比赛的车队在这些年中经历了最多的汽车问题,包括发动机故障、刹车、悬挂或传动系统问题。
团队见证的汽车问题比率
谁更容易撞车?
一级方程式赛车的最高时速可达 375 公里(233 英里/小时),因此撞车事故最终会终止车手的比赛。下面的图表显示了过去两个赛季中参加比赛的一些车手的撞车率。
2018 年至 2019 年驾驶员的车祸率
从快 40 岁的人到青少年明星
在世界锦标赛的最初几年,大多数领先的车手都在 40 多岁:尼诺·法里纳在 43 岁时赢得了第一个世界冠军,而 Luigi Fagioli 在 1952 年创造了 F1 历史上年龄最大的冠军纪录,当时他 53 岁,在未来几年里不太可能被超越。然而,他们被新一代取代只是时间问题。从 20 世纪 60 年代到 1993 年,平均年龄约为 32 岁,而在最近几个赛季,只有少数车手年龄超过 30 岁。
下面的散点图显示了第一个赛季获胜车手的年龄,显示了一条向下倾斜的趋势线。
获胜车手的年龄
3.机器学习建模
这最后一节将讨论以下主题:我用来评估最佳模型的指标,合并数据的过程,以及最终使用神经网络的机器学习建模。
成功指标
- 精准评分—2019 赛季正确预测赢家的百分比
- 赔率对比 —我的模型能战胜赔率吗?
数据准备
收集完所有数据后,我最终得到了六个不同的数据帧,我必须使用公共键将它们合并在一起。我的最终数据框架包括从 1983 年到 2019 年的比赛、结果、天气、车手和车队排名以及排位赛时间的信息。
我还计算了车手的年龄和排位赛时间的累计差异,这样我就可以知道每场比赛中第一辆赛车比其他赛车快多少。最后,我将赛道、国籍和车队变量虚拟化,去掉那些不太重要的变量。
回归还是分类问题?
由于我想预测 2019 年每场比赛的第一名,所以我可以将目标变量视为回归或分类。
当评估一个回归的精度分数时,我将我的预测结果按升序排序,并将最低值映射为比赛的获胜者。最终,我计算实际值和预测值(映射 1 和 0)之间的精度分数,并在 2019 年的每场比赛中重复,直到我获得该赛季正确预测的比赛的百分比。
这是 2019 年任何一场比赛的评分函数中的 prediction_df 的样子。实际领奖台映射为 0 和 1(获胜者),排序后的预测结果也是如此。在这种情况下,模型错误地预测 Bottas 是比赛的获胜者,因此模型的得分等于 0。
在分类问题中,目标在建模之前被映射为 0 和 1(赢家),因此,当我查看预测值时,根据预测的概率,我可能有多个赢家或根本没有赢家。因为我的算法不够智能,无法理解每场比赛我只需要一个获胜者,所以我创建了一个不同的分类得分函数,对每位车手赢得比赛的概率进行排名。我将概率从最高到最低排序,并将概率最高的车手作为比赛的获胜者。
在这种情况下,即使马克斯·维斯塔潘只有 0.35 的获胜概率,因为这是那场比赛中获胜的最高概率,该函数也会正确地将他映射为获胜者。
ML 建模
由于我的自定义评分功能需要在评估之前对模型进行拟合,所以我必须对不同的模型进行手动网格搜索,最终将分数和参数添加到字典中。
我尝试使用逻辑和线性回归、随机森林、支持向量机和神经网络来解决回归和分类问题。
训练-测试分割:训练集包含从 1983 年到 2018 年(含)的所有比赛。测试集由 2019 赛季的所有 21 场比赛组成。
回归
分类
调查的结果
在花了几天时间运行所有的网格搜索后,神经网络和 SVM 的分类似乎返回了最高分,正确预测了 2019 年 62%的比赛的获胜者,这对应于 13/21 的比赛。
ML 模型比较
我还使用 2018 年和 2017 年两季作为测试集,以检查模型是否仍然表现良好。神经网络在这两年都比 SVM 分类器返回了更高的分数,所以我决定选择具有以下参数的神经网络分类器。
- hidden _ layer _ size =(75,25,50,10)
- 激活=身份
- 求解器= lbfgs
- 阿尔法= 0.01623776739188721
考虑到特征重要性根据线性回归,在预测获胜者时,网格位置似乎起着最重要的作用,还有其他特征,如比赛前的车队或积分。
根据线性回归的特征重要性
查看过去几年的结果,我注意到算法总是错误地预测一些赛道的获胜者,可能是因为发生了更多的事故或超载。最难预测的赛道是阿尔伯特公园、巴库、斯帕、蒙扎和霍根海姆环。
算法能战胜几率吗?
在将所有我预测的获胜者聚集在一起后,我决定查看由 SkySport 发布的 2019 赛季比赛的赔率,并发现如果我在这些比赛上下注,我会赢得的奖励。
下表显示了根据 SkySport 在“赔率最大”下最有可能赢得比赛的车手,而“车手预测”是由神经网络预测的获胜者。红色的驱动程序名称表示错误的预测,因此与“实际”驱动程序列不同。以绿色突出显示的行表明算法预测的驱动因素结果是正确的,与赔率预测相反;然而,红色的突出显示表明,我可能应该在赔率最大的赔率上下赌注。最后两列显示了赔率奖励和利润,如果我一直在每场比赛中投资 100€,最终利润为 4,255.00€。
赔率比较
结束想法
我希望你喜欢我的帖子!欢迎在下面评论我可能错过的任何东西。所有代码都可以在我的 GitHub 中找到:
在 GitHub 上创建一个帐户,为 veronicanigro/Formula_1 开发做出贡献。
github.com](https://github.com/veronicanigro/Formula_1)
领英:【https://www.linkedin.com/in/veronica-nigro/
公式一:提取和分析历史结果
《美汤熊猫》F1 赛季的网页抓取与数据分析
资料来源:Unsplash.com
数据无处不在
作为一名数据科学家,有时你手头没有你需要的数据,或者没有现成的渠道向你提供你需要的数据。在其他时候,您可能只是对探索一个没有全新数据集的领域感兴趣。幸运的是,互联网上有一个星系间的数据海洋(如果你还不知道的话),几乎可以分析任何主题,Python 拥有为你选择的项目收集和格式化数据所需的所有工具。
对我来说,我将在这里探索的主题,以及在未来的一些帖子中,是一级方程式赛车的历史成绩。对于外行人来说,F1 是世界上的精英赛车运动,在这里,像埃尔顿·赛纳和迈克尔·舒马赫这样的传奇人物在车轮战中与他们时速 200 英里的骏马搏斗!
对我来说幸运的是,F1 官方网站包含了从 1950 年至今 F1 锦标赛的存档数据。比赛结果,排位赛时间,冠军位置和许多其他结果都在档案中(见下文),很容易浏览网站找到你感兴趣的任何信息。
来源:formula1.com 网页截图
在我让你对所有这些 F1 的东西兴奋起来之前,让我们用 Python 从档案中提取一些信息,并用熊猫来显示它。
美味的汤
B eautiful Soup 是一个很棒的包,用于将组成网页的 HTML 数据解析成更可读和可用的格式。我使用 Beautiful Soup、urllib 和 Pandas 从 F1 档案中抓取数据,并以数据帧的形式呈现出来。如果我们追溯到 1950 年左右,一些历史数据会有点稀疏,所以现在我打算从 1990 年开始,也就是说,从现代 F1 和综合数据开始。
从一些简单的事情开始,我决定从 1990 年开始收集所有的冠军排名并绘制结果。首先我用 urllib.request.urlopen() 打开了包含 1990 年车手总冠军成绩的网页(可以导航到相关网页复制链接)。然后我使用带有' table '参数的 find_all() 方法来搜索网页中包含的表格(这里只有一个)。最后,我使用 Pandas 方法 read_html() 将数据转换成 DataFrame。这是一个非常有用的方法,任何人都可以从网页上抓取数据进行后续分析,因为它使立即开始使用 Pandas 功能变得简单。
来源:为本帖制作的情节(恰兰·库尼)
好了,我成功地从一个网站上提取了一些数据,虽然我们可以看到埃尔顿·赛纳击败阿兰·普罗斯特获得了 1990 年 F1 世界冠军,但这里没有什么特别有趣的东西!
我认为从每场比赛中提取结果并建立自己的冠军表来显示所有结果,然后绘制车手在一年中的进步,这可能会更有趣,而不是像上面那样获取最终的冠军排名。在此之前,我想看看每场比赛的数据是如何存储在网页上的,所以我导航到 20 世纪 90 年代比赛结果页面这里。
来源:formula1.com 网页截图
您可以从上面的截图中看到,1990 年的第一场比赛是在美国,我用这场比赛来查看比赛结果格式,使用了与上一个例子类似的代码。
得到的数据帧包含一些有用的列、一些不太有用的列以及一些不可读的列。为了构建我自己的冠军表,我现在只需要“Driver”、“Car”、“No”和“PTS”列。与其手动点击网页来提取数据或找到所有比赛结果的链接,不如使用网络爬虫来自动完成这一过程。
搜索链接
为了做到这一点,我必须搜索 1990 年比赛结果网页(上面截图中的页面)中的所有链接,并根据特定条件仅提取我想要保留的链接。我想对比赛 URL 列表应用一些条件,因为我不想要网页中经常包含的无关信息或重复链接。为了找出使用哪些条件,我查看了网页的源文件(ctrl + u ),发现每个比赛结果链接都包含年份和字符串“race-result”——红色箭头指向下面的这些内容。这将允许我反复搜索链接,只保留那些符合这些条件的链接。
来源:formula1.com 网页截图
为了提取所有比赛结果,我创建了一个函数,它将相关年份作为参数,并返回一个 URL 列表。当 URL 满足条件(“1990”和“race-result”)并且还没有包含在列表中时,它们被添加到列表中。注意:“a”标签——如 soup.find_all('a') —是链接,告诉浏览器呈现另一个网页的链接。
它返回一个 URL 列表,每个 URL 对应一组比赛结果。然后,我可以使用这个列表将每场比赛的结果反复加载到一个数据帧中,并将本赛季的所有结果合并到一个包含所有分类车手和所有积分的数据帧中。
在第一次迭代中,在将比赛结果加载到数据帧中之后,我创建了一个新的数据帧来存储整个赛季的结果,其中包含第一场比赛中分类的车手和车号( season_results_df = pd)。DataFrame(df[['驾驶员','汽车']],columns=['驾驶员','汽车'],index=df.index) 。对于随后的每一次迭代,如果以前没有分类,我会在数据帧中添加新的驱动因素(下面的第 25-26 行)。然后从每场比赛中提取每位车手的积分,并添加到 season_results_df 数据帧中(见下文第 28-30 行)。最后,我对数据帧进行了格式化,按驱动程序编号(“否”)排序,用零填充任何 NAN 值,并通过应用 lambda 和 map 函数将汽车制造商的名称重新格式化为三个字母的版本。
如您所见,它返回了一个数据帧,其中包含了每位车手在每场比赛中的得分。请注意,数据帧目前是根据车手编号排序的(普罗斯特作为卫冕世界冠军排名第一)。我本可以增加一个“总计”栏,把每个车手在整个赛季的积分加起来,但那会给我提供和开始时差不多的信息。
我n 取而代之,我决定创建一个数据框架,使用熊猫中可用的 cumsum() 方法跟踪每个车手在赛季中的累积积分。我还重新排列了数据框,显示了从塞纳开始的最终冠军位置。我用累积成绩绘制自己的冠军表的原因之一是为了更容易看到竞争是否在整个赛季中波动。为了整理图形图例,我将驾驶员姓名转换为他们姓氏的前三个字母。
现在,我可以看到整个赛季积分的积累,以及今年澳大利亚站最后一场比赛的结果,显示出最终的积分榜。然而,从数据图表中很难得到赛季进展的总体感觉,所以我也绘制了数据。
来源:为本帖制作的情节(恰兰·库尼)
现在,你不用太费力就可以看出,在 1990 年,只有两位车手争夺冠军(塞纳和普罗斯特),而普罗斯特确实在赛季中期领先塞纳,之后领先优势再次扩大。从这一点上也可以清楚地看到,总得分由相对较少的车手决定,在 36 名车手中,只有 9 名车手得分超过 10 分。从累积图中我还注意到了让·阿莱西(金牌)的形态。他在赛季开始时状态很好,在前 4 场比赛中获得了 13 分,但在赛季余下的比赛中表现平平。
你可能已经注意到,与我在上面绘制的最终冠军排名相比,一些车手的最终分数有所不同。这是我没有预料到的事情,所以我不得不做一些调查,看看到底发生了什么。原来,1990 年 F1 采用了“最佳 1 1 名”的规则,即根据车手在 16 场比赛中的最佳 11 名成绩的累积来确定冠军排名。由于这个原因,我决定使用这个公式来查看数据,并创建了下面的函数来计算基于最好的 11 个的累积分数。
best_11_cumsum() 函数只是计算前 11 场比赛的累积分数。从第 12 场比赛开始,它会检查该场比赛的得分是否大于前 11 场最佳得分的最小值。如果评估结果为真,则删除之前的最小值,添加新的分数,并计算修订后的累积分数。
你现在可以看到,积分分数与上面的最终冠军排名相匹配,从下面的图中可以看出,“最佳 11”评分系统的整体效果是最小的。唯一真正的影响之一是,它使小尼尔森·皮奎特的最终分数减少了一分,这使他从第三名直接与加赫特·贝加并列。
形式是短暂的,但它仍然可以被分析。我想看看整个赛季的表现波动,特别是塞纳和普罗斯特争夺冠军的表现。绘制滚动平均值是跟踪数据点的基本方法,我决定使用 3 场比赛的滚动平均值来观察车手的表现如何不同。
来源:为本帖制作的情节(恰兰·库尼)
这个情节乍一看有点嘈杂,但它确实表明了两个冠军争夺者之间的势头有一些相当大的转变。你可以看到普罗斯特的状态达到顶峰,塞纳的状态达到最低点,反之亦然。普罗斯特的状态达到顶峰,随后他取得了冠军的领先地位,这似乎表明他势不可挡。当然,这并没有持续多久,普罗斯特的死亡恰好与塞纳的状态明显复苏相吻合,最终锁定了冠军。
你可能已经从数据图表中注意到,1990 年大奖赛冠军获得了 9 个积分。当我在 90 年代后期开始观看 F1 比赛时,车手赢得了 10 分,现在是 25 分(尽管积分结构有所改变——我猜这是我的专业知识)。我经常想知道这些分数差异是否真的改变了谁在冠军争夺战中胜出。我在 1990 年用一个简单的 if 语句做了一个快速测试: if pts ==9: pts = 10 。无论如何,这不是一个问题,因为那一年塞纳会得到 6 分,普罗斯特 5 分,一切都会保持不变。
接下来去哪里?
W 我在这里展示的是一个相当基本的网络抓取介绍和一个 F1 赛季的一些探索性数据分析,但还有更多的事情可以做。我可以看看车手和车队的形式是如何随着赛季甚至几十年的变化而变化的。我可以试着从排位赛时间中获取一些信息,来判断不同时代谁是最快的车手。我可以将不同的积分系统映射到不同的赛季,看看它们实际上是如何影响最终结果的,我也许可以看看更长期的影响,比如在不同的时代系列赛的竞争有多激烈。我甚至可以考虑建立一个预测性的机器学习模型,也许可以使用排位赛时间和以前的比赛结果来预测比赛结果。
你甚至可能想自己尝试一下这些东西。
我在这篇文章中使用的所有代码都可以在 Jupyter 笔记本中找到。
数据科学基金会
入门
获取关于数据的一切的简单解释
数据科学是一个迅速发展的领域,最初是基于统计学。在过去的几十年里,由于数据和计算资源的数量呈指数级增长,以及对更深入理解它的需求,它变得更加广泛。人工智能和机器学习在许多方面都非常接近 DS,但最重要的是,它们的目标是让机器理解和操作数据,基本上使人类目前使用计算机所做的事情更加自动化。
我认为将数据科学描述为几乎所有研究和实践领域的共同基础是公平的,这些领域起源于数字计算机的发展,以及大多数依赖事实数据及其分析来取得进展的经验领域。然而,由于 DS 已经发展到不仅仅是统计,而没有完善基础理论,交流思想和在重要项目上合作变得更加困难。在这篇文章中,我想通过以简单的方式定义核心概念来填补空白,并使用它们来描述最常见的数据类型。
什么是数据?
—任何信息的任何给定表示。文本、数字、图形、声音或任何其他形式。它来自于测量、成像、挖掘、描述以及许多其他方式。重要的是要了解它是如何收集的,以及该方法的局限性,记住它不是对现实的完整描述。然而,数据是我们可以讨论和分析的一切。
在一个非常基本的层面上,根据我们目前对物理学的理解,所有的数据都可以被分割成某种独立的对象。在许多情况下,连续表示法作为近似值仍然很有用,但是它们也可能被视为抽象或数学对象。有些数据,比如艺术,根本无法用正式语言来描述。
虽然任何数据都可以表示为某种对象,但有时它可以更好地描述为对象之间的关系。这种类型的数据通常包含有关相关对象标识符的信息,通常还附带有连接描述或在它们之间发送信息的编码器/解码器功能。
有时数据来源是随机的,就像掷硬币的结果一样。它通常由一组可能的状态来表示,例如(头像;tails) ,再加上代表我们对系统在观察过程中有多大可能最终处于其中一种状态的信念的数值,比如(0.5;0.5) 为公平币。在大多数情况下,由于缺乏知识,概率变量实际上代表了我们的近似值。例如,如果你有足够的数据、施加的力、空气条件和其他细节,你实际上可以准确地预测硬币会落在哪一边。然而,对于本质上看似随机的量子粒子来说,情况似乎并非如此,但我们稍后将回到这一点。
爱德华多·苏亚雷斯在 Unsplash 上拍摄的照片
理解概率对于理解存储在数据中的信息通常是如何量化的很重要。想象一下扔一次硬币,不看。为了让您知道结果,其他人必须向您发送的最少数据量是多少?正面/反面、1/0 或其他表示形式。这是熵背后的基本思想,表示为,通常用位来度量。你至少需要获得 1 比特的信息才能知道结果。例如,在英语中,你需要更多的信息来描述一个单词,因为有数百万个可能的单词和它们的形式,而不仅仅是两种可能的结果。有趣的是,随着句子中每个后续单词的出现,随着概念变得越来越清晰,大多数单词出现的概率越来越接近于零,而剩下的单词越来越少,并且每个后续单词实际上传达的信息越来越少。
另一个基于熵的重要概念是互信息,记为 I 。简而言之,它是衡量两个数据之间有多少共同信息,或者一个数据告诉我们多少关于另一个数据的信息。在上面的英语句子的例子中,每个单词都和它的邻居有交互信息,平均来说,每个新单词增加的信息都比之前的单词少。此外,这也解释了为什么尽管语言能够构建任意长的序列,但句子很少超过 10-50 个单词。
怎么处理它
通常原始数据太重而没有意义,我们需要对其执行操作来提取有趣的信息。在实践中,我们使用许多不同的转换:排序、过滤、清理、计数、查询、合并、推断、重构、建模、可视化、搜索、映射、近似、压缩、修剪、粗粒度化等等。
所有这些操作的共同点是,如果我们考虑所有输入数据,包括过程中使用的函数,输出将包含相同或更少量的信息。此外,如果我们放弃产生与所提供的输入无关的输出的操作,如数学常数函数,我们将剩下可能实际上帮助我们有意义地将数据转换成其他表示并找到相关信息的操作。由于我们的目标通常是将大量数据简化为可解释的表示,我建议将这种类型的操作称为简化,并表示为 ~ > 。从数学角度来说:
对于某个数据 A 那一个操作被定义为,A ~>B是有效的 还原ifB = f(A)其中运算符 f B) > 0 。
许多这样的操作都有自己的名字,就像上面的例子一样,但并不是每一个都有,即使是有名字的操作,不同类型或不同数据实例之间的实际计算也可能不同。此外,这种符号迫使我们考虑所有用于产生输出的数据,如函数或模型的参数、数据库的内部工作方式、关于这些数字来源的领域的隐式或显式知识,以及许多其他潜在的方面。
约简的例子:( 2 + 2) ~ > 4 、⠀ sin(π) ~ > 0 、⠀“我走了”~ >“我走了”、⠀数据库(查询)~ >结果、⠀模型(输入)~ >输出、⠀(有缺失值的表∪函数来填充它们)~ >(完整的表)、⠀(量子态ψ= ax**
转向实际的数据表示
现在,我们可以回顾一些我们可能会用到的实际案例,从更直观的案例开始,逐渐转向复杂的现实问题。
汉娜·赖特在 Unsplash 上的照片
让我们从你现在正在读的东西开始——书面的自然语言。我在上面的例子中提到了一点,但是这种类型的数据非常丰富,由相对较小的字母组成。一些语言实际上有成百上千的基本符号,如埃及象形文字或一些东方书写系统,它们通常在图形上与这些字符的含义相似。除了打字语言之外,还有可能与书面语几乎一对一对应或差异很大的口语变体、手语(通常包含与口语相同的信息,但表达方式非常不同)、盲文和许多其他例子。一种常见的简化方法是摘要,其中一些数据加上语言知识可以简化为一种更短的形式。
有一种语言特别突出,并在全世界范围内被广泛使用,那就是数学。对于我们自己或在计算机的帮助下进行的计算的定义,它是特别正式、简洁和方便的。
由 Alexander Sinn 在 Unsplash 上拍摄
数字计算机中的基本数据表示——位和字节 (=8 位)通常用 1 和 0 来表示。布尔值真/假值仅为 1/0,整数直接转换为二进制数字系统,并增加一位表示符号,浮点数是指数和分数的组合,二者相乘产生存储值。字符串可能用 ASCII 或 Unicode 等不同编码表示,但都只是整数和指定字符之间的映射。数组、向量、张量等通常只是同类型值的集合。根据编程语言和库的不同,这些表示也可能有内置的函数/缩减,或者组合成更复杂的结构。
马库斯·斯皮斯克在 Unsplash 上的照片
编程语言中的代码本身就是一个被翻译成机器代码的字符串,是处理器中整数和指定操作之间的映射。这些映射通常被称为指令集架构或只是计算机架构,其中最受欢迎的是大多用于台式机和服务器的 x86,以及大多打包在移动设备中的 ARM。有趣的是,最近 ARM 也进入了笔记本电脑和服务器市场。
将高级代码转换成低级指令的程序,通常被称为编译器或解释器,它们本身曾经是直接用这些指令编写的,但现代版本是用旧版本编译的。重要的是要注意,在这个过程中,许多信息,如变量的名称和注释,通常会丢失,而源代码与编译器相结合,被简化为一系列特定的机器指令。
除了上面描述的代码和基本类型,计算机通常还存储其他数据,如文本、表格、图像、声音、视频和许多其他以不同方式编码的形式。所有的数据都按照某种文件系统分割成文件,这样人们就可以浏览并理解它们。这对于数量相对较少、整体结构不太完整的数据非常有效。
来自 Pixabay
然而,将数千、数百万甚至数十亿的条目作为文件来处理几乎是不可能的。这就是我们需要数据库的地方。一般来说,数据库是存储数据的表、数据编码器/解码器、可以添加新条目或对现有条目执行不同缩减的查询引擎,以及用于访问控制、迁移、复制和其他目的的大量辅助工具的集合。
数据库之间的区别在于它们对单个对象和它们之间的关系的重视程度。在一个极端,我们有 SQL 数据库,它们实现了结构化查询语言,非常适合具有大量关系的数据,在另一个极端,我们有 NoSQL 数据库,比如键值和文档存储,它们擅长处理大量独立的条目。在中间的某个地方,我们有图形数据库,它将数据表示为对象的节点和关系的边。虽然图形数据库还不是很受欢迎,但我相信它们的灵活性、直观性和更好地表示混乱的真实世界数据的能力最终会使它们至少像 SQL 和 NoSQL 的竞争对手一样受欢迎。
一台计算机可以存储高达数十万亿字节,每秒钟可以执行高达数十万亿次最简单的操作。这听起来可能很多,但这样的性能要归功于成千上万的内核,实际上它需要工作负载的并行化。例如,如果你想得到 sin(x ) ,在你完成平方 x 之前,你不能开始计算 sin() 。但是,如果您需要类似于 (ab) + (cd)* 的东西,您可以在不同的内核上同时执行乘法,然后在其中一个内核上对结果求和。*
来自 Pixabay
但是如果你不想建造一台超级计算机来扩大规模,或者你想远程连接计算机,你需要网络。除了硬件之外,您还需要像 TCP 和 HTTP 这样的协议来对传输的数据进行公共表示。有了它,你就可以用数字电脑把各种东西连上互联网,甚至是你的衣服和家具,这种现象通常被称为物联网。
然而,仅仅来回发送原始数据可能会对您的安全造成危险。几十年前,只有政府、银行和少数其他实体需要保护他们的数据,但如今,随着你周围的所有环境都在收集数字数据并受其控制,我们需要加密来确保我们能够控制对这些信息的读取和编辑。粗略地说,加密的工作原理是将数据转换成无法识别的表示形式,同时使用数字密钥保存完整的信息。这些密钥是编码和解码算法工作所需的输入,通过控制谁拥有这些密钥,就可以控制谁拥有访问权。
一个特别有趣的数据结构,基于数据库、互联网和加密的混合物,是 T4 区块链 T5。它背后的基本思想是创建一个数据库,任何人都可以按照一致同意的程序添加新的数据块,并通过加密防止编辑或删除等操作。最受欢迎的应用是加密货币,如比特币和以太坊,但还有更多。然而,它的名字有点误导,因为在实践中很难将所有数据存储在单个链上,并且扩展需要一些分支来处理成千上万的用户。由于现实世界的解决方案已经更接近于类似于“块树”的东西,我相信将核心思想概括为类似于“块图”的东西是有益的,使其更具可扩展性,并适用于更广泛的问题集。
描述某个对象行为的更一般的表示概念被称为模型。它可以像单个变量的线性函数一样简单,就像在固定速度参数 v 和给定时间 t : d=vt ,下行驶的总距离 d 一样,也可以像具有数十亿个参数的人工神经网络一样复杂,用于处理任意长系列的输入。有些数据模型定义了它们在数据库中应该如何表示,有些模型描述了事物应该如何分类、估值、生成、决策,还有许多其他类型的模型。*
来自 Pixabay
机器学习模型,如回归、决策树或神经网络,特别有用,因为它们不需要人类对我们想要建模的东西做出精确的说明,而是可以从提供的例子中“学习”它的表示。通过调整参数,以提高它们模拟给定数据的能力,模型可以自动完成任何数据处理任务,有时它们在重要问题上胜过人类。然而,它们的有效性直接取决于这些例子包含多少关于感兴趣的对象的信息,以及它们的架构与对象的内部工作有多相似。
另一类重要的模型是物理模型。它们是对我们所拥有的真实世界最准确和详细的描述。其中,你可以找到像水、电和计算机如何工作、引力和行星如何围绕恒星形成这样的常见事物的模型,一直到暗物质、暗能量和其他几乎不为人知的事物。
来自 Pixabay
其中最基本和被广泛接受的是量子物理模型。它们大多描述了我们观察到的最小粒子的行为,但这些数据也与我们对黑洞的理解以及宇宙如何发展成我们所看到的样子有着深刻的联系。还有一些模型寻求更小的基本对象,如弦理论,以及许多更高层次的抽象概念,如电路或内燃机。
量子粒子有很多令人费解的性质,但其中最违反直觉的是叠加和纠缠。第一个意思是一个粒子可以处于不同状态的混合状态,根据某种概率分布,在测量后会在其中一种状态下被看到。第二个意思是,你可以把多个粒子联系起来,把它们的状态联系起来,这种联系不会因为距离而中断,并且有即时的效果。这种怪异的行为是有问题的,因为在经典的数字计算机上很难建模和理解,但它导致了利用它们的量子计算机的发明。
量子计算机中数据的基本单位——量子比特,代表一个量子比特。目前,我们知道这种计算机可以比经典计算机更快地执行某些操作,但我们没有一个理论来描述所有这些操作,这些计算机仍然非常罕见和昂贵。另一个重要区别的例子是:对于经典数据,您总是可以在副本上应用缩减,并在保持原始数据完整的情况下获得结果,但它并不总是适用于量子数据。
来自 Pixabay
所有可观测的物质都是由量子粒子构成的,包括生命体。虽然从物理和化学的角度来看,它的大部分相对简单,但有些部分非常复杂,即使经过几十年的研究也很难理解。DNA 可能是最有趣的生化结构,因为几乎所有关于单个细胞如何行为和构建像我们这样的大型生物的数据都存储在其中。人们通常认为 DNA 只是一长串编码一些蛋白质的静态数据,但它也对环境的变化做出动态反应,这些机制背后的所有复杂性和可能性仍然知之甚少。此外,它被许多其他生化机械以许多方式与之相互作用,在这种规模下,甚至一些量子效应也是完全可以想象的。
由 Robina Weermeijer 在 Unsplash 上拍摄的照片
在我们周围和体内,有数不清的细菌种类和细胞类型。但是有一种特别的类型因其数据处理能力而特别有趣——神经元。它们可以相互之间以及与数米之外的其他细胞形成数千个连接,以电和化学形式接收、携带和发送信号。身体中神经元最集中的部分——大脑,有着极其复杂和相互关联的结构,我们仍然几乎不了解。大脑的一个大问题是,我们不知道信号中有多少是不必要的噪音,有多少是有意随机的。我并不认为这种规模的量子效应,但强化学习的探索-开发困境以及机器学习模型训练中噪声的有效性表明,一些随机性可能是一种进化的特征,而不是一个问题。
来自 Pixabay
神经元和一堆其他细胞一起可以构成一个人类,而一堆人类可以构成一个社会。在这些尺度下,量子效应不再是问题,但收集数据和对人类进行操作会有很多伦理和其他方面的问题。此外,由于互联网和数字设备,与几千公里外的人联系变得容易多了。然而,这些设备也可以用来收集我们可能不想分享的关于我们生活的各种信息,尤其是当我们不知道谁会看到这些信息时。总的来说,理解社会和政治从来没有像今天这样重要,因为我们可以跨越国界和全球团结起来,而且还因为我们有足够的核武器来摧毁所有文明,杀死几乎所有人,使整个地球无法居住。**
总之,不可能对数据的所有类型、表示和操作进行计数。物理学家每天都在发现关于宇宙的新事实,生物学家——新的生命物种,工程师——新的工具,心理学家——我们头脑中的新维度,其他人以各种形式收集新知识。然而,在计算机的帮助下,我们可以在这些成堆的数据中找到新的见解,这些数据反过来可以用来给我们生活的许多方面带来积极的变化。
基础统计术语解码
统计学初学者!请继续阅读,了解一些重要的基本术语及其含义。
用 VS 风格解释,先左后右!
相信我!你可以!
任何决定开始精通统计学习方法(SLM)的漫长而艰难的旅程的人都面临着对一些非常基本的术语的公开的技术解释。这篇文章旨在通过用简单的英语解释一些基础术语来揭穿统计学很难的流行神话。
举例来说,如果我们想根据不同的参数,如阅读等级(D)、每句话字数(D)、阅读时间(D)等,来确定一个中型故事(I)的成功与否。(一中文末参考)
- 因变量(响应变量)与独立变量(预测变量)
故事成功的概率是因变量或反应,用于预测的变量(标记为 D)是自变量或预测因子。
2。预测 VS 推理方法
如果我想使用一种只关注最佳输出预测的方法,而不考虑因变量和自变量之间的关系,我们将选择一种预测方法(一般来说,像决策树一样复杂且不易解释)。但是,如果目标也是理解反应和预测之间关系的本质,那么我们将使用一种推断方法(像线性回归一样容易理解)。
3。参数与非参数方法
参数方法是一种两步方法。首先,我们假设自变量的性质和形状,假设它本质上是线性的。
成功概率= a+ b(阅读成绩水平)+ c(每句话字数)+……..+n(读取时间)
第二步是使用 OLS(普通最小二乘法)等技术预测系数(a 到 n)。这种基于简化模型的方法本质上是参数化的。
然而,在非参数方法中,我们不对自变量的函数形式做任何明确的假设。这种方法比参数方法有更大的优势,因为通过避免任何假设,它们有可能精确地拟合更大范围的独立变量的可能形状。
4。监督与非监督学习方法
我们正在讨论的问题是,一个媒体故事的成功与上述预测因素之间的关系,这有助于我们确定这个故事是否成功。为了开发这个模型,我们必须访问适当的训练数据,其中我们有一堆已经发布的故事的成功结果来训练模型,然后该模型将预测未来故事的成功。这是一种监督学习方法。
然而,如果我们遇到一个问题,比如说,确定特朗普是否会喜欢他遇到的下一个国家元首(他从未见过)。现在,我们没有任何可用的过去的数据,所以我们不能训练一个模型。在这里,我们将部署一个能够自我学习的模型,并在每次新的会议中变得智能。随着时间的推移,这类模型需要定期反馈才能成为可靠的预测器。这是一种无监督的学习方法。
最后但绝对不是最不重要的,
5。回归与分类
变量可以定性或定量(也称为分类)。定量变量采用数值,如每句话字数、阅读文章的时间等。然而,分类变量在 K 个不同的类或类别中取值,如对像标题中的句子格这样的变量取 Yes 和 No。
简单地说,我们把有定量反应的问题称为回归问题,而那些涉及分类反应的问题通常称为分类问题。
我参考了下面的媒介故事来了解媒介故事成功的预测因素。这是一本好书。
[## 是什么让一篇文章在媒介上流行?我们分析了 10,000 多个数据点来寻找答案
在过去的几年里,Medium 已经迅速成为我最喜欢的出版和阅读的地方。这是一个民主的天堂…
感谢您的阅读:)观看这个空间,了解更多关于统计、数据分析和机器学习的信息!
气候变化统计分析的基础——概率分布
数据分布的描述统计
威廉·博森在 Unsplash 上的照片
为了更好地理解本文的数据集和其他基本统计数据,可以考虑在这里阅读该系列的第一部分: 气候变化统计分析的基础 。
我在之前的一篇文章中简要地提到了核密度估计(kde)的主题。在这里,我将扩展 KDEs 并介绍概率密度函数、概率质量函数和累积分布函数。我将再次使用 Python 编程语言进行演示。
让我们再快速看一下我们的数据。日期列中的值对应于年和月,而 Monthly_Anom 列中的值是每月的温度异常。在这里阅读更多关于为什么全球气温显示为异常的信息。
连续分布
下面是我们数据的分布图。异常范围从低于全球平均值约 1.5 度到高于全球平均值 1 度,平均值为-0.093。
持续分发— PDF
我们的数据分布是一个连续分布,因为温度是一个连续变量(身高、体重和距离也是)。我们可以观测到 0.1 度,0.008 度,0.98600093828209 度等等,但是连续变量的精确值只能估计到给定的精度。
概率密度函数或 PDF ,是一种估计数据集中特定范围内随机值出现概率的参数方法。因为数值不可能精确,你要问自己变量 X 落在 0.3 到 0.4 之间的概率是多少?通过问这个问题,你在寻找一个值出现的相对可能性,而不是绝对可能性,对于连续变量,绝对可能性是 0,因为它们是无限的。要计算特定范围内给定值的概率,您需要计算曲线下的面积,即 AUC。AUC 将在下一篇文章中讨论。
为了可视化连续变量的分布,您可以使用 Seaborn 库的 distplot() 来显示直方图(条形)和内核密度估计(红线),并可以选择绘制概率密度函数(黑线)。
kde 是一种估计随机变量中某个值的概率的非参数方法。KDEs 在分布中的每个单独点绘制一条曲线,然后作为平滑密度估计添加到分布图中,从而得到平滑线。当分布是正态或接近正态时,使用的核将是高斯核,尽管如果分布不是正态的,也将使用其他核。
直方图将数据分成多个条块,并对每个条块内的每个数据点进行计数。Seaborn 的 distplot()直观地显示了数据中的条柱数量,尽管您可以指定您希望直方图中的条柱有多粗糙。您可以通过归一化计数来确定落入每个条柱中的点的百分比。请记住,y 轴反映的是频率,KDE 下的总概率等于 1。根据已指定的箱数,可视化可能会发生变化,解释可能会有所不同。
在上面的图中,PDF 显示为黑线。首先,我们假设我们的数据在可视化直方图后是正常的,尽管分布可能是双峰的、指数的等等,所以你的 PDF 可能不是正常的。正态分布的概率密度函数是通过取变量的两个参数,平均值和标准差来计算的。一旦拟合到图,您就可以评估 PDF 估计随机变量的概率有多好。对于我们的数据,PDF 做得相当好,尽管在 0.6 标记附近有一个轻微的概率凸起和一个轻微的负偏度,这在 PDF 中没有考虑。
离散分布
当变量是分类的,并且值可以假设为一个有限的、可数的数时,就有了一个离散分布。任何一个结果的概率都等于 1。例如,在标准骰子(未加权)上掷出任意数字的概率为 1/6,总概率等于 1。
离散分布— PMF
一个概率质量函数,或 PMF ,显示一个离散随机变量的概率。每个值的概率之和为 1。分类变量可以用 PMF 来描述,因为分布中有有限数量的无序值。
这张图表来自 2015 年的排放数据集,展示了每个行业中工厂对这份特定温室气体报告的贡献百分比。y 轴显示每个行业中工厂的频率,以样本的分数表示。
累积分布函数
正如我们之前在连续变量和 PDF 中看到的,给定月份的温度异常为精确值的概率为 0,y 轴展示了值的密度,但没有展示实际的概率。
一个累积分布函数,或 CDF ,计算变量 X 小于或等于值 X 的概率,给定月份全球气温异常为 0 度或以下的概率是多少?
从名称推断,CDF 给出了 PDF 下概率的累积和。对于我们的例子,小于或等于 0 度的概率的累积和看起来大约是 0.75。我们可以有把握地假设,任何给定月份的温度异常在大约 75%的时间里都是 0 度或更低。
了解数据的分布和描述性统计数据至关重要,尤其是在研究全球气候变化时。了解变量中某个值的可能性有多大的基础知识,将有助于您识别某些趋势何时是预期的或远离基础,更容易捕捉错误或意识到意外何时发生。
赶上下面的第一卷,并留意未来关于更多描述性统计、预测、机器学习等的文章!
量化全球变暖的环境和经济影响的基础
towardsdatascience.com](/climate-change-analysis-series-volume-1-48708a938fcc)
概率基础
Python 中的适马代数、测度论和幂集
安德里亚·皮亚卡迪奥在像素上拍摄的照片
西格玛代数被认为是概率论公理基础的一部分。卡塞拉和伯杰的统计推断简要介绍了这个话题。对西格玛代数的需求源于与定义概率相关的技术困难。那么 sigma 代数到底是什么?
什么是适马代数?
简单来说, X 上的 sigma 是包括空集和 X 本身在内的 X 子集的集合。换句话说,sigma 是 X 的幂集。西格玛代数也称为 Borel 场。其正式定义如下:
第一个性质表明空集总是在 sigma 代数中。此外,由于空集的补集也在样本空间 S 中,第一和第二个陈述暗示样本空间总是在 Borel 域中(或 sigma 代数的一部分)。最后两个语句是可数交集和并集的条件。
与测度论有什么联系?
Borel 空间是测度论的一个基本对象。它由一个集合及其对应的 sigma 代数组成。具体来说:
让我们看一个小例子。考虑以下集合:
给定 X ,Borel 场是 2 = 8 个集合的集合,也称为幂集:
幂集与描述二项式幂的代数展开的二项式定理密切相关,如下所示:
我们可以使用二项式公式对此进行扩展:
其中二项式系数为:
X 的幂集中子集的个数由二项式系数 C(n,k)的个数给出
任何集合的幂集是包含空集和该集合中元素的组合的集合,从 1 到原始集合的大小:
python 中幂集的实现
现在我们将讨论如何使用 python 中的实现来生成幂集。首先,让我们从 itertools 导入组合和链:
from itertools import combinations, chain
接下来,让我们初始化一个包含空元组的元组:
powerset = ((),)
现在,让我们定义一个函数,它接受一个参数输入集,并使用链和组合方法来生成幂集:
def powerset(input_set):size = len(input_set)
combs = (combinations(input_set, k) for k in range(1, size+1))
return chain(empty_powerset, *combs)
如果我们用之前指定的集合调用函数:
print(tuple(powerset({10, 20, 30})))
事实证明,与我们上面的例子不同,对于不可数集合,sigma 代数是必要的。西格玛代数是必要的,以便我们能够考虑实际事件的实数子集。换句话说,在可数并集和可数交集的条件下,集合需要被很好地定义,才能被赋予概率。
给定我们对 Borel 空间的基本理解,让我们继续定义概率函数。
概率公理(Kolmogorov 公理)
给定样本空间 S 和相关联的西格玛代数 B,,概率函数是满足以下条件的具有域 B 的函数 P :
满足以上陈述的任何函数 P 都是候选概率函数。因为可以定义许多满足概率公理的概率函数,所以概率论关心的是理解哪些函数反映了在特定实验中可能观察到的情况。
需要考虑的最后一件有趣的事情是:
巴拿赫-塔尔斯基悖论说明了在缺少西格玛代数的情况下出现的矛盾。它声明如下:
给定两个实心 3D 球,一个小,一个大,任何一个球都可以重新组合成另一个。这也被称为豌豆和太阳悖论,即一颗豌豆可以重新组合成太阳,反之亦然。这意味着,如果你在三维空间中处理实数(例如,体积比),你将很难定义事件的概率,因为你可以重新排列空间来改变体积。如果你的概率取决于体积,通过改变集合的体积,你也将改变概率。这意味着没有一个事件可以被赋予单一的概率。这需要 sigma 代数,它允许我们定义可测量的集合和概率。
在人工智能竞赛中领先的四大人工智能公司。
人工通用智能
下面让我们来看看走在 AGI 前列的四家公司。
尼斯·姆舒蒂在 Unsplash 上的照片
一种人工智能已经接管了世界,但不是以末日杀手终结者机器人、反乌托邦未来那种方式。在 21 世纪,人工智能被用于增强商业、教育、建筑、医疗保健、交通等行业。它被用来拯救生命,创造下一代技术,主要是为了让我们的生活更美好。人工智能的应用似乎是无穷无尽的。尽管看起来人工智能是一种领先于我们时代的未来科幻技术,但它不会停留在个性化你的社交媒体体验或自动化单调的任务上。如果你认为这是人工智能革命的顶峰,请再想想,因为你今天看到的人工智能只是冰山一角。
窄 AI vs 强 AI
在我们开始之前,这里有一个关于人工智能的速成班,简单地定义为机器思考和学习的能力。今天使用的人工智能被称为狭义人工智能,狭义的意思是,它只能按照编程完成特定的任务,除此之外什么也做不了。AI 的下一个“级别”是强 AI 或者本文标题中使用的术语——人工通用智能。强人工智能是一个假设的机器大脑,它具有执行任务和理解语音的智能能力,其认知水平与人脑相同。换句话说,一个机器人可以像我们一样感受事物,恋爱,并基本上做我们人类每天可以做的事情,这对一个狭隘的人工智能系统来说几乎是不可能的。
在 AGI 的投资
这个假想的 AGI 是不朽的,可能会改变历史的进程。这就是为什么投资者向公司投入数百万美元,专家们努力工作,希望将这种虚构的技术变成现实。根据 Mind Commerce 的一份报告,预计到 2023 年,AGI 的投资将达到 500 亿美元。
说到投资,有很多科技公司都有一群专家在研究这项技术。IBM 和百度等大型科技公司可能正在人工智能领域实现飞跃。然而,有四家著名的公司领先于人工智能的终点线。奖品不是金杯,而是人工智能的圣杯——超级智能。
以下是对它们的简要介绍。
4 家人工智能公司
1.开放 AI
始于 : 2015
驻于:加州三藩市
使命:确保人工通用智能造福全人类
目标:率先创造 AGI,不是为了利润的支配,而是为了社会的安全,为了平等地分配给世界。
创始人:埃隆·马斯克、山姆·奥特曼等人。
投资方:微软——10 亿美元
近期成就:创造了 Open AI Five ,一个由 5 个 AI 机器人组成的团队击败了世界 Dota 2 冠军和一个能够解魔方的机器人手。
AGI方法论:更大的神经网络模型
OpenAI 是一家人工智能研究公司,发现并制定安全人工智能的道路。
openai.com](https://openai.com/)
2.深度思维
始于 : 2010
基于:伦敦
任务:研究并构建安全的人工智能系统,学习如何解决问题并推进所有人的科学发现。
目标:通过融合机器学习和系统神经科学的新技术来构建强大的通用学习算法,从而实现“解决智能”。
【创始人】:戴密斯·哈萨比斯
投资人 : Founders Fund 和 Horizons Ventures
近期成就 : AlphaGo ,2016 年在围棋比赛中击败人类最优秀棋手的 AI 系统。
方法论 AGI :神经科学——更深入地观察人类大脑,并从中汲取灵感,创造复杂的算法。
[## deep mind——如果解决一个问题可以解开成千上万个问题的答案,会怎么样?
人工智能可能是人类最有用的发明之一。我们研究和建立安全的人工智能系统…
deepmind.com](https://deepmind.com/)
3.谷歌大脑
开始于 : 2011
总部位于:加州山景
任务:让机器变得智能,改善人们的生活
目标:创造一个拥有人类小孩智力的 A.I。
创始人:吴恩达和杰夫·迪恩
投资人:隶属母公司谷歌
近期成果:发明变形金刚(一种用于自然语言处理的神经网络) TensorFlow
方法论到 AGI :监督学习,以及其他神经网络结构。
关于团队研究,自由谷歌大脑团队成员制定自己的研究议程,团队作为一个整体…
谷歌研究](https://research.google/teams/brain/)
4.脸书人工智能研究所
始于 : 2013
基于 : —
任务:推进人工智能
目标:创造类人人工智能
创始人 : Yann LeCun 、深度学习先锋
投资方:母公司
方法论到 AGI :无监督和自我监督学习。
我们将人们与他们关心的事物联系起来,为新的、有意义的体验提供动力,并推进…
ai.facebook.com](https://ai.facebook.com/)
展望未来
吉列尔莫·费拉在 Unsplash 上拍摄的照片
人工智能肯定会给我们的社会带来混乱。它对我们世界的影响将跨越每一个行业,我们必须为这一天的到来做好准备。尽管 AGI 似乎被描绘成危险和暴力的,但真正的危险来自我们。
我们,人类,是不完美的,我们往往不知道我们行为的后果。只要看看我们是如何应对气候变化的生存风险的,世界上许多地方已经遭受了它,但我们仍然无动于衷。对于 AGI 这种有能力终结人类的技术,我们是在扮演上帝的角色,我们必须非常小心我们的行动。T2 的风险是巨大的,我们的比赛岌岌可危。
为了确保这项技术将被用于好的方面,而不是以任何方式被滥用,必须制定适当的规则来确保 AGI 系统 100%安全,并且有意识的 AGI 自己将具有人文主义价值观,如诚信和道德,以防止他们伤害人类。
只要参与推进 AGI 进程的人是负责任的,并且意识到 AGI 的危险,安全高效的 AGI 体系就能建立起来。
行动计划
既然你已经意识到了 AGI 将会带来的影响,试着去了解人工智能,并想办法把它应用到你的生活中。拥有将人工智能应用到现实世界的技能和能力将至关重要,无论你只是一名大学生还是一家大型零售公司的首席执行官。
如果你是人工智能的爱好者,你可以从学习人工智能流行的编程语言开始。我建议从 Python 开始,因为你可以继续学习 PyTorch 这是一个流行的机器学习框架,或者你可以学习 TensorFlow 的 JavaScript,也是一个机器学习库。
如果你是一名业务经理,你希望看到人工智能改变你的公司,那么开始投资人工智能,聘请机器学习工程师或数据科学家。在您的业务中使用人工智能,您可以增加销售额,增强客户体验,自动化流程,进行预测分析,检测欺诈,等等。
如果你是一个梦想改变世界的年轻人,目标是成为一名企业家,我敦促你从人工智能开始。找到你的激情或者一个你想解决的问题,尝试把 AI 的元素加入其中。比如你梦想设计一个新的服装品牌,为什么不让 AI 替你设计呢?或者,如果你想帮助找到大脑疾病或癌症的治疗方法,请使用人工智能来找到新的治疗方法。
总而言之,人工智能不是也不应该局限于富人,而是所有人都可以体验并参与这场让世界变得更美好的革命。不要害怕实验和使用人工智能来实现不可能的事情。
感谢您的阅读,我希望您已经了解了什么是人工智能,以及哪些公司正在引领它成为现实。
以下是美国人工智能研究人员兼作家埃利泽·尤德考斯基(Eliezer Yudkowsky)的一段话:
“任何可以产生比人类更聪明的智能的东西——以人工智能、脑机接口或基于神经科学的人类智能增强的形式——都毫无疑问地成为最能改变世界的东西。其他的甚至都不在一个联盟里。”—
查看这些文章,了解更多关于人工智能和机器学习的信息!
[## 互联网上 20 大免费数据科学、ML 和 AI MOOCs
以下是关于数据科学、机器学习、深度学习和人工智能的最佳在线课程列表
towardsdatascience.com](/top-20-free-data-science-ml-and-ai-moocs-on-the-internet-4036bd0aac12) [## 机器学习和数据科学的 20 大网站
这里是我列出的最好的 ML 和数据科学网站,可以提供有价值的资源和新闻。
medium.com](https://medium.com/swlh/top-20-websites-for-machine-learning-and-data-science-d0b113130068) [## 机器学习的未来
与杰夫·迪恩一起展望曼梯·里的未来
towardsdatascience.com](/the-future-of-machine-learning-ce0a9dc18cb8)
如果您对学习数据科学感兴趣,请查看“超学习”数据科学系列!
这是一个简短的指南,基于《超学习》一书,应用于数据科学
medium.com](https://medium.com/better-programming/how-to-ultralearn-data-science-part-1-92e143b7257b)
联系人
如果你想了解我的最新文章,请通过媒体关注我。
其他联系方式:
注意安全!
四种常见类型的神经网络层
(以及何时使用它们)
神经网络 (NN)是当今许多机器学习(ML)模型的支柱,松散地模仿人脑的神经元,从输入数据中识别模式。因此,多年来已经设计了许多类型的神经网络拓扑,使用不同类型的神经网络层来构建。
有了今天大量的 ML 框架和工具,任何有一点 ML 知识的人都可以很容易地用不同类型的神经网络拓扑建立一个模型。在大多数情况下,这都是关于了解每种类型的神经网络擅长解决什么问题,并优化它们的超参数配置。
四种最常见的神经网络层是全连接、卷积、反卷积和递归、,下面你会发现它们是什么以及如何使用它们。
全连接层
图像由感知实验室
全连接层将一层中的每个神经元连接到下一层中的每个神经元。全连接层存在于从标准神经网络到卷积神经网络 (CNN)的所有不同类型的神经网络中。
随着输入的增长,完全连接的层在计算上可能变得昂贵,导致要执行的矢量运算的组合爆炸,以及潜在的较差的可扩展性。因此,它们通常用于神经网络中的特定目的,例如对图像数据进行分类。
用例
- 使用全连接神经网络的实验或学习 ML。
- 为计算机视觉对图像进行分类。
通常与全连接层相关的超参数
- 激活功能
- 神经元数量
- 拒绝传统社会的人
卷积层
图像由感知实验室
卷积层是 CNN 中一种重要的层类型。它最常见的用途是检测图像中的特征,其中它使用一个过滤器来扫描图像,一次扫描几个像素,并输出一个特征图,对发现的每个特征进行分类。
过滤器(有时称为内核)是一组与输入相乘的 n 维权重,其中过滤器的维度与输入的维度相匹配(例如,当处理 2D 图像时是两个维度)。过滤器描述了给定的像素模式表示特征的概率。因此,滤波器权重的数量(即,滤波器的大小)小于输入,并且由层的卷积过程执行的乘法是在匹配滤波器大小的图像“小块”上执行的。
在整个图像上从左到右和从上到下系统地重复乘法以检测特征。滤波器在下一次迭代中移动的像素数称为步幅。可以在输入图像周围添加填充,以确保滤波器总是适合给定步幅的图像的总边界。
用例
- 用于图像识别和分类的图像分析。
通常与卷积层相关的超参数
- 维度
- 补丁大小
- 进展
- 要生成的要素地图的数量
- 填充策略
- 激活功能
- 拒绝传统社会的人
- 联营
去卷积层
图像由感知实验室
反卷积图层是一种转置卷积过程,可有效地将数据向上采样至更高的分辨率。这可以包括从卷积层生成的图像数据和/或特征图,或者其他类型的数据。对于图像数据,通过去卷积输出的上采样分辨率可以与原始输入图像相同,也可以不同。
常见用例
- 向上采样图像
通常与反褶积层相关的超参数
- 维度
- 进展
- 要生成的要素地图的数量
- 填充策略
- 激活功能
- 拒绝传统社会的人
循环层
图像由感知实验室
一个循环层包括一个“循环”能力,使得它的输入既包括要分析的数据,也包括由该层执行的先前计算的输出。递归层形成了递归神经网络(RNNs)的基础,有效地为它们提供了内存(即,在迭代过程中保持状态),而它们的递归性质使 RNNs 适用于涉及自然语言和时间序列等顺序数据的情况。它们对于将输入映射到不同类型和维度的输出也很有用。
常见用例
- 将情绪分为积极情绪和消极情绪。
- 生成图像内容的文本描述。
- 将文本段落翻译成另一种语言。
通常与重现层相关的超参数
结论
当谈到机器学习时,神经网络是当前最先进的,有许多拓扑和层类型可供选择。每种类型的神经网络都擅长解决特定领域的问题,每种神经网络都通过优化这些解决方案的超参数进行调整。此外,ML 从业者现在可以访问许多 ML 框架和工具,这使得实现围绕神经网络拓扑结构构建的 ML 模型比以往任何时候都更容易。
要了解更多信息,请查看我的机器学习手册,它提供了关于神经网络和 ML 其他方面的更多细节。
四种有趣的方式帮助您在研发中保持高效
这四个想法将帮助你,如果你被困在等待长脚本完成
许多 R 程序员会证明他们坐在电脑前盯着 R 控制台,等待长脚本运行的情况。有时是因为他们担心某件事会失败,有时是因为他们在祈祷脚本会毫无错误地运行。
但是,如果您的脚本需要很长时间,您可能会变得非常低效。在您等待的同时,您可能正在编写其他 R 代码。在你的电脑上做一些其他的事情,或者甚至做一些完全不同的事情,比如去健身房,看书,或者学习一些新的东西。
这里有四个想法可以帮助你。
1.在你等待的时候写更多的 R 代码
许多 R 程序员——尤其是初学者——不知道如何在活动会话之外运行他们的代码,所以他们最终会在活动会话中运行他们的脚本,并等待它完成,然后才能进行更多的编码。
从 RStudio 1.2 开始,您可以利用作业功能。作业允许您在 rstu 迪奥内部的独立 R 会话中运行脚本。这将释放您的控制台,以便您可以继续处理其他代码,但也允许您在脚本运行时查看其进度。
要将脚本作为本地作业运行,请查找一个小下拉菜单,您可以在其中看到源按钮,然后选择“源为本地作业”。脚本运行时,您可以使用“作业”窗口中显示的绿色条来监视其进度,如果您用代码节(至少有三个尾随破折号的注释)对脚本进行注释,则“作业”窗口会在脚本中显示注释,以便您可以准确地看到脚本的位置。
RStudio 迪奥 1.2+中的“作业”窗口
2.在你等待的时候,学习一些新的事实
wikifacts
包是一个简单的包,显示从维基百科主页随机选择的事实。您可以使用install.packages("wikifacts")
从 CRAN 直接安装。
如果您偶尔将wikifacts
中的命令插入到您的脚本中,您可以在等待脚本执行时阅读一些有趣的琐事。
对于随机事实,您只需要使用wiki_randomfact()
,对于特定类型的事实,您可以使用wiki_didyouknow()
、wiki_onthisday()
和wiki_inthenews()
。
事实将从今天的维基百科主页中提取出来,或者如果你愿意,你可以在上面的函数中指定前一个主页的日期作为参数。
wikifacts
如果你真的想提升你的输出,你也可以很容易地进入其他有趣的显示工具,比如cowsay
。
通过管道将 wikifacts 连接到 cowsay
3.多任务处理时获得通知
如果在脚本执行时你在 R 之外工作,你可以使用beepr
包,当你的脚本完成或者某些部分完成时,你就可以播放噪声。在您安装并加载软件包之后,您可以使用beep()
功能来播放一组简短的提示。例如,如果你像我一样是一个最终幻想迷,你会喜欢beep("fanfare")
。
此外,beep_on_error()
功能允许你指定一个表达式来测试,如果测试失败,你选择的声音将被播放。如果你在脚本中加入测试,这非常方便。
4.当您离开电脑时获得通知
当你设置了一个很长的脚本来运行,然后离开你的计算机去做别的事情,然后当你在几个小时后回来时,你发现它在五分钟后因为一些愚蠢的错误而失败了,这是多么令人沮丧。听起来熟悉吗?
有许多电子邮件包可以在你的脚本中发生事情时给你发送电子邮件,但我真的很喜欢textme
包,它给你发送一条你选择的消息。
textme
目前在 CRAN 上不可用,但是您可以使用devtools::install_github("richpauloo/textme")
从 Github 安装它。您可以在这里找到完整的说明,但基本上主要步骤如下:
- 在这里建立一个
twilio
账户,验证自己并建立一个项目——一个试用账户就可以了。 - 获取您的试用电话号码、SID 和令牌。
- 使用
tm_configure()
功能输入您的凭证和您想要发送短信的目的地电话号码,即您的号码。 - 使用
textme()
功能发送所需信息(如textme("Awesome, your script just completed successfully!")
)。
下面是一个我如何使用textme
来提醒我出错的例子:
左边的短信是由右边的代码发送的
编码时,你还用什么有趣的事情来帮助你避免浪费时间?
最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在 LinkedIn 或Twitter上找我。也可以看看我在drkeithmcnulty.com的博客。
图片由simpleprogrammer.com提供
整合了数据科学和人种学的四个创新项目
图片来自 DarkoStojanovic
在之前的文章中,我已经讨论了整合数据科学和人种学的价值。在 LinkedIn 上,人们评论说他们对此很感兴趣,希望听到更多关于潜在方法的细节。我回答说,“我发现解释如何进行将两者实际结合起来的研究,通过例子比抽象地演示更容易,因为如何做的细节会根据每个项目的具体需求而变化。”
在本文中,我打算这样做:分析四个在某种程度上整合了数据科学和人种学的创新项目。我希望这些能激发你的创造力,帮助你思考如何在你正在做的项目中创造性地组合它们。
简介:
1.没有展示模型:使用人种学设计机器学习软件(https://ethno-data.com/show-rate-predictor/)
2.网络敏感性研究:使用机器学习将民族志调查的范围扩大到更大的人群(https://ethno-data.com/masters-practicum-summary/)
3.脸书新闻反馈民间理论:使用人种学来了解用户如何理解他们遇到的机器学习系统并对其做出反应,以及这如何反过来塑造有问题的机器学习算法的发展(https://dl.acm.org/doi/10.1145/2858036.2858494)
4.事物民族志:使用机器学习将物体的交互纳入民族志研究(https://dl.acm.org/doi/10.1145/2901790.2901905和https://www . semantic scholar . org/paper/Things-Making-Things % 3A-An-Ethnography-of-of-the-Giaccardi-Speed/2 db 5 feac 9cc 743767 FD 23 aeded 3 aa 555 EC 8683 a 4?p2df
项目 1:没有展示模型
纽约市一家医院系统的医疗诊所要求我使用机器学习来建立一个节目速率预测器,以便为改进其调度实践提供信息。在最初的构建阶段,我使用人种学来更深入地理解诊所面临的调度问题,并确定适当的界面设计。
图片来自 NASA
通过人种学调查,我发现了日程安排者在安排约会时问的最重要的问题。这个问题是,“在某一天被安排去看医生的人中,有多少人会真的出现?”然后我建立了一个机器学习模型来回答这个问题。我的人种学调查为我提供了数据科学项目的设计要求。
此外,我用我的人种学调查来设计界面。我观察了调度程序如何与他们当前的调度软件交互,这让我知道什么样的可视化对我的应用程序有用或没用。
该项目举例说明了人种学在确定机器学习算法需求的机器学习项目的开发阶段以及在向用户传达算法并评估其成功性的前端是如何有所帮助的。
作为一名民族志学者和数据科学家,我能够将我的民族志见解无缝地转化为机器学习建模和 API 规范,并且还进行了后续的民族志调查,以确保我构建的内容能够满足他们的需求。
图片来自 Kon Karampelas
项目 2:网络敏感性研究
我和 Indicia Consulting 一起进行了这个项目。它的目标是探索个人能量消耗和他们与新技术的关系之间的潜在联系。这是一个使用人种学来探索和确定少数人的潜在社会和文化模式,然后使用数据科学来分析大量人口中的这些模式的例子。
我们通过观察和采访大约 30 名参与者开始了这个项目,但随着研究的进展,我们需要开发一种可扩展的方法来分析整个社区、县甚至州的模式。
人种学是深入探索一种现象和发展初始模式的伟大工具,但它是资源密集型的,因此很难在一大群人身上进行。分析成千上万的人是不实际的。另一方面,数据科学可以很容易地测试在较小的人种学研究中发现的整个群体模式的有效性,但因为它通常缺乏人种学的粒度,所以经常会错过复杂的模式。
人种学在确定已实现的机器学习模型及其产生的见解是否有实际意义方面也非常有用。这形成了一种迭代反馈循环,其中数据科学扩大了人种学的见解,而人种学将数据科学模型置于上下文中。
因此,人种学和数据科学很好地覆盖了彼此的弱点,形成了一个伟大的方法论组合,用于以深入理解客户、用户、同事或其他用户为中心的项目。
图片来自 Pixabay
项目 3:脸书新闻和民间理论
在他们的研究中,Motahhare Eslami 和她的研究团队进行了一项民族志调查,研究不同的脸书用户如何看待脸书新闻订阅如何选择哪些帖子/故事出现在他们的订阅顶部。他们分析了几种不同的“民间理论”或日常生活中人们的工作理论,作为机器学习系统选择头条新闻的标准。
用户对整个系统工作的看法会影响他们对新闻反馈的反应。例如,相信算法会优先考虑他们过去喜欢的朋友的帖子的用户通常会有意喜欢他们最亲密的朋友和家人的帖子,以便他们可以看到更多他们的帖子。
用户对 Newsfeed 算法如何工作的观点会影响他们对它的反应,这反过来会影响算法学习的数据,从而影响算法的发展。这创建了一个循环反馈回路,随着时间的推移,它会影响机器学习算法系统的开发。
他们的研究例证了理解人们如何思考、响应以及更广泛地与基于机器学习的软件系统相关的重要性。对人们与这种系统的互动进行民族志研究是发展这种理解的重要途径。
在某种程度上,许多机器学习算法在本质上是非常社会化的:它们——或者至少是它们所在的整体软件系统——往往基于人类如何与它们交互而成功或失败。在这种情况下,无论机器学习算法在技术上多么强大,如果潜在用户不能积极有效地与之相关,那么它就会失败。
对机器学习软件系统的“社会生活”(我的意思是它们如何成为个人生活的一部分,或者在某些情况下未能成为个人生活的一部分)的民族志有助于理解算法是如何开发或学习的,并确定它们是否成功实现了我们希望它们做的事情。这种人种学不仅需要人种学方法方面的深入专业知识,还需要深入了解机器学习算法如何工作,进而了解社会行为可能如何影响他们的内部发展。
项目 4:事物民族志
Elise Giaccardi 和她的研究团队一直在开拓利用数据科学和机器学习来理解事物并将其观点纳入民族志。随着物联网(IOT)的发展,她认为来自物体传感器的数据可以通过帮助描述这些物体如何相互关联,为人类如何与环境相关的民族志提供新的见解。她称这种的东西为民族志。
这种实验方法举例说明了在民族志中使用机器学习算法作为社会过程/互动的一种方式。这可能是在人种学研究中分析这些 IOT 物品在日常生活中的社会角色的一种创新方法。如果说 Eslami 的工作举例说明了一种将民族志分析移植到机器学习算法的设计周期中的方法,那么 Giaccardi 的研究则说明了一种将数据科学和机器学习分析融入民族志的方法。
结论
这里有四个创新项目的例子,涉及整合数据科学和人种学,以满足各自的目标。我不打算这些是如何整合这些方法的完整或详尽的说明,而是作为思考的食粮,以激发进一步的创造性思考如何连接它们。
对于那些当他们听到整合数据科学和人种学的想法时,会问合理的问题,“有趣,但实际上会是什么样子?”这里有四个例子来展示它的样子。希望它们有助于发展你自己的想法,如何将它们结合到你正在做的任何项目中,即使它的细节完全不同。
您可以在这里找到原文:https://ethno-data . com/projects-integrating-data-science-and-ethnography/。有关该网站和其他文章的更多信息,请访问https://ethno-data.com/。
也感谢《数据科学》杂志发表这篇文章。关于他们工作的更多细节,见 本 。
数据收集的四项原则
数据收集
通过减少对数据的处理来简化分析
资料来源:农业营销服务本地食品目录
我花了一生的时间收集原始数据,无论是在我的工作中还是作为更广泛的研究团队的一部分。在这样做的过程中,我对数据在科学中的作用、数据的收集和组织变得相当固执。在这篇文章中,我详细介绍了数据收集和组织的四个原则,这些原则对任何需要收集数据的分析师都很有用,不管是用手还是用机器。通常,学生、初级学者、商业分析师和公共管理者会参与数据收集。然而,它在大多数课程中很少受到关注。尽管数据科学的兴起,以及其用于抓取、解析和自动化清理、组织和学习过程的工具,我们许多人仍然需要收集我们的数据。
我定量研究精英文本和政策文件。我的项目涉及官僚主义、政策实施和监管政策。我的书使用了近 25 万份监管提案的数据,我目前正在从事一个国家科学基金会(NSF)资助的项目,该项目逐段检查 10 万份公众对监管的意见。
我还在一所大型公立大学教授本科生和研究生级别的统计学。我经常被一些学生所震惊,他们理解统计学的概念逻辑和如何建立回归模型,但对如何收集和组织数据却缺乏直觉。尽管数据科学和统计学开始在日常管理中发挥更大的影响,但我发现这种直觉在私营部门更加缺乏。以下一套基本原则可作为数据收集的指南。对它们的忠诚将提高数据的质量及其对决策的影响——无论是研究还是公共和私营部门的管理。
忠实于数据生成过程
我们经常讨论或描述科学,或学习,作为一个围绕理论和假设检验的过程。这种描述只是部分准确。在萌芽阶段,科学是结构化的观察。没有对观察结果的精确记录和保存,发展和检验理论是不可能的。而且,科学是不可复制的。
数据是社会、生物或物理过程的结果。这个世界没有给我们半个人,百分比,或对数美元;它给我们人,计数,和美元。对数据生成过程的保真度允许我们在迭代决策过程中以及归纳和演绎推理循环之间的转换中改进计算和测量。
原则 1:记录数据;不要计算,不要变换。
过去,可用的电子表格或数据库(例如 MS Excel 或 MS Access)的数据限制限制了一个单元格中可以存储的字符数或给定数据集可以包含的行数。这些限制意味着保留数据原始形式的记录极具挑战性,并且需要大量文件和空间。幸运的是,大多数电子表格应用程序不再是这种情况。(SQL 或 SQLite 数据库可以快速处理剩余的限制。)鉴于这些进步,在收集期间按原样存储数据。
1A:如果可能的话,以文本或文本兼容格式存储数据。
在获取忠实于数据生成过程的数据方面,数据收集并不是唯一的危险。程序,尤其是“工具化”的电子表格,经常给数据添加隐藏的结构或内容。例如,开头或结尾的空白尤其令人讨厌,因为问题并不明显。其他问题包括将文本存储为数字,反之亦然,以及将所有字符串作为因子变量读取。因此,建议将您收集的数据存储为文本或文本兼容文件(例如。txt 或者。csv“分隔”文件)。
1B:备份数据。
这里不需要大量的文字。将您的数据存储在多个位置。如果必要的话,其中一个应该是物理硬盘——所有的云都会不时出现故障。如果遵循这些原则,您应该只需要存储原始的、基于文本的文件。
原则 2:管理数据组织
一旦收集了数据,首先要做的是围绕它的结构思考。我在这里使用“策划”这个词,因为它意味着对数据的仔细(重新)组织——一些经过思考的事情。数据很容易在“宽”或“长”格式之间转换,只要其结构和组织是一致的。(宽格式和长格式数据之间的差异可能是一个单独的帖子。)
2A:观察值出现在行中;变量出现在列中;变量的观察值出现在它们之间的单元格矩阵中。
数据组织的基本关注点是观察值和变量或指标之间的区别。观察、主题或案例总是成排出现;变量出现在列中。(第一列包含行[即观察]标签。)
2B:嵌套结构应该出现在列中,而不是行中。
观察可能包含分组。例子包括时间、地理位置、重复测试、宗教等。在商业中,常见的分类是部门、类别或商店。这些类型的分组不应该在行中显示(通过缩进或任何其他方式),而应该在列中作为单独的变量出现。例如,在一项全国性调查中,受访者的居住状态可能会被记录下来。“State”应该出现在一个单独的列中行标签右侧的某个列中,列标签为“state”
商业计算提供了一个很好的例子。在我涉足商业咨询的过程中,我经常看到按时间顺序排列的时间段。当您从这些列计算奇异值时,这是有意义的,但是如果没有大量的重组,对数据做任何其他事情几乎是不可能的,特别是如果行包含嵌套的话。句点是分组变量,应该出现在它们的列中。
小心复杂的行、列或数值标签。
带有区分大小写字符、特殊字符或空白的行、列或值标签会在电子表格之外的分析软件中引起问题(它们也可能是电子表格中的问题)。使用小写字母完全表示观察值、变量或标签,除非数据按原样使用。避免空格。使用下划线而不是句点来表示空白。避免使用特殊字符——“百分比”或“百分比”比“%”更好
最后,要认识到组织和标签是有意义的,因为其他人会使用你的数据。我们通常不为单一用例生成数据。组织简单的干净数据促进了数据的使用以及对程序和分析的共同理解。
原则 3:计算和分类在数据收集之外。
记住,度量是观察的模型。度量并不完全忠实地表示数据。通过忠实地以原始形式记录观察,从观察到测量的地图是可见的,允许评估、复制、更新和调整。
我发现初学分析的人(尤其是学生)经常误解什么是数据,把它们误认为是从数据中计算出来的统计数据(例如,均值不是数据,而是数据的简约表示)。这种误解通常是由于我们这些年长的分析师没有花太多时间来教授什么是数据或传达什么是数据收集的关键。
3A:所有计算都应该在数据存储库之外进行。
在商业中,电子表格是分析的引擎。原则 3 只需将原始的、未掺假的数据副本保存在单独的表格或文件中即可。对于社会科学家来说,所有的计算和其他统计程序都应该发生在统计程序中,而不是在原始数据中。在这两个领域中,从数据收集和保存中解析计算和分析方法都有逻辑上的好处。更新一个分析仅仅意味着更新由过程调用的数据集(也是以原生形式),如果脚本和函数被很好地记录的话。自动化报告和分析在公共部门和私营部门都是一件大事。在数据结构中进行计算、汇总和分析会妨碍有效的更新。
3B:在收集过程中不要汇总数据。
除非需求紧迫,否则不要在收集期间汇总数据。摘要必然意味着信息的丢失。禁止汇总包括数据结构中的总计和平均值等计算。再次,记住忠实于数据生成过程。所有的总结都可以通过记录良好的分析程序轻松重复。
在文本作为数据的情况下,如果需要摘要,你应该尽力把全文和摘要放在一起。同样,这种总结应该在收集之后进行。
原则 4:如果错了,就一直错下去。
这个原则乍听起来可能很奇怪,它需要理解分类或归类的可靠性和有效性之间的区别。出于这里的目的,有效性仅仅是一个观察是否被放在“正确的”类别中或者被“正确地”分类。可靠性指的是相似的观察结果、案例、主题或项目是否以相同的方式被归类或分类。这两种品质对于数据收集和测量都是必不可少的。
4A:在对数据进行分类或归类的最初尝试中,可靠性优先于有效性。
我使用或开发了无数的分类和归类方案。这些经历告诉我,在分类或归类上一贯错误比平均正确要好,但差异很大。使分类或归类正确(充满有效性)是一个迭代过程,高度的可靠性有助于这一过程。在三种情况下,您会发现自己在调整分配的类别或分类:
- 分类不正确,但可靠性高。
- 分类平均正确,但可靠性低。
- 分类不正确,可靠性低。
如果你发现自己处于第一种情况,调整是很容易的,因为所有不正确的分类可以一起被分配一个新的分类。然而,请注意,第二点意味着所有数据必须逐个观察地重新编码。换句话说,由于缺乏可靠性,你必须重复整个过程。最后,第三点意味着你可能还没有很好地理解这个概念来对观察结果进行分类。
分类或归类应该是互斥的。
模糊和双重分类是可靠性的敌人。在一个列中,每个观察应该接收一个且只有一个代码。综合来看,4A 和 4B 是比较的敌人。重要的是要记住,所有的研究和分析(无论是公共部门、私人部门还是学术部门)都是在时间或空间上比较事物并做出选择的努力。如果你觉得有必要对案例或观察结果进行两次分类,那么就在单独的一栏中这样做。尽管记住,如果代码是可靠的,双重编码的安全网就没有必要了。
总而言之
无论是在商业、公共部门还是在学术领域,回答问题和做出决策首先取决于在观察中收集的信息——记录和保存数据。使用这些原则并不复杂,它们使分析师的生活变得更加容易。最后,使用现有的数据集总是很诱人的。当数据适用于许多问题时,这很好。小心使用。所有数据的存在都是为了一个可能与你无关的目的。这些原则不能回答你的目标和现有数据之间的匹配的概念问题。
原载于 2020 年 5 月 13 日 https://www.samuelworkman.org**的 。
为什么除了计算机科学家,其他人都写马虎代码的四个原因
五次黑客攻击让你的更干净。
有些代码看起来很干净,但实际上很乱。尼基塔·万托林在 Unsplash 上的照片
为什么每个开发人员都认为他们正在编写完全可以理解的代码?为什么同一个开发人员不能破译别人的代码,更不用说维护它了?
因为他们写的都是可以工作的草率代码。也就是说,代码现在可以工作,但是由于它的混乱,不太具有可扩展性或通用性。除了计算机科学家——他们写的漂亮代码行不通。
理由 1:对计算机科学家来说,编码是一门艺术。对其他人来说,它是一种工具
计算机科学家编码是因为他们想编码。其他人编码是因为他们想完成一些事情。
一个普通的开发人员会根据他们脑海中出现的第一个想法来构建一个程序。然后他们会在这个想法的基础上发展,直到他们有了一个 MVP。通常,他们甚至不会考虑替代方法。
因为大多数时候,我们都弄错了
medium.com](https://medium.com/better-programming/what-does-a-real-mvp-look-like-ac35b4953e28)
相比之下,计算机科学家会考虑实现的每一个选项,并权衡每一个选项的利弊。几周后,他们会有一段漂亮的代码,但仍然没有完全发挥作用,因为计算机科学家还没有决定输出的格式。
由于开发人员从一个简单的工具开始,并有机地发展代码,所以产生了许多草率的代码。相比之下,计算机科学家通常先建立一个结构,然后在其中工作。
有机的方法是避免程序员的阻塞和按时交付的最好方法。然而,如果你想写持久的代码,你可能想把结构放在第一位。
当你害怕你的游戏机时
towardsdatascience.com](/how-to-overcome-coders-block-51ece9dafe00)
原因 2:开发者并不总是把读者放在心上
即使在协作项目中,开发人员在编写代码时也倾向于只考虑它的功能。在这样做的时候,他们忘记了代码也需要维护的事实。
问题是这种心态适得其反。当开发人员想在三个月后添加一个特性时,他们可能无法理解自己的代码。这种情况比你想象的要经常发生!
当不同的开发人员被要求实现一个新特性时,事情变得更加复杂。根据项目的大小,理解别人的代码可能需要几天到几周的时间。
理由三:风格是一个东西
每个人的编码都不一样。有些人讨厌在线评论,有些人喜欢。有些人在它的第一行上面评论它们的功能,有些人在下面。有些人喜欢开关盒,有些人讨厌它们。
这就是为什么一段代码对一个人来说可能很可怕,但对另一个人来说却很好。
当你独自工作时,这不成问题。但是现在,很多软件都是合作开发的。所以在项目的早期阶段确定一个风格指南是很重要的。
当然,您需要确保所有开发人员都遵守它。否则,您最终会得到混乱的代码,因为它是不同约定的混杂。
快速修复是值得的,但从长远来看可能会导致大混乱。Muhannad Ajjan 在 Unsplash 上拍摄的照片
原因 4:即时奖励的谬论
当你被一个问题困扰了好几天,直到你最终找到解决问题的办法时,你有没有感到兴奋?这是一个非常激动人心的时刻。
问题是,当开发人员追求快速修复时,他们往往会忽略长期问题。例如,他们可能修复了一个 bug 或者添加了一个特性,但是没有意识到代码的结构已经过时了。
这意味着每增加一项新功能,他们都必须投入更多的工作。相比之下,从长远来看,对程序进行一次重组会更容易添加更多的特性。
如果你喜欢快速解决问题,而不是解决根本问题,你并不孤单。人类的奖励系统更容易受到短期修复而不是长期变化的影响。但这样一来,你就积累了技术债务。从长远来看,这会让你付出很大代价。
你赢不了。你只能控制你输得有多快。
medium.com](https://medium.com/@erichiggins/technical-debt-is-like-tetris-168f64d8b700)
干净与脏乱的危险
声称自己总是写出干净代码的开发人员要么是在撒谎,要么是高估了自己。也就是说,有几个原因让你不想写太干净的代码:
- 如果你的目标是从头开始编写干净的代码,你就增加了遇到编码障碍的机会。为了防止主要的阻塞发生,最好在一开始就有机地发展你的代码。这尤其适用于你是初学者的情况。
- 一些开发人员花了一整天的时间清理他们的代码,没有别的原因,只是为了美观。当然,如果有许多其他合作者,或者代码将以任何方式呈现,这可能是有用的。但通常情况下,润色代码就像普通医疗的整形手术一样有效——它可能看起来不错,但并不能解决任何更深层次的问题。
糟糕的代码是有代价的,写好的代码并没有那么复杂
medium.com](https://medium.com/better-programming/the-art-of-refactoring-5-tips-to-write-better-code-3bc1f6f7689)
另一方面,你也不想让你的代码太乱。太多的混乱会使你的代码不可维护。缺乏维护会导致代码腐烂,从长远来看,项目会被丢弃,因为它们弊大于利。
因此,我们需要的是快速结果和可维护代码之间的健康平衡。大多数开发人员都倾向于凌乱的一面,所以提高整洁度是一条可行之路。好消息是,一些好习惯可以对开发人员的整洁和生产力产生巨大的影响。
黑客 1:尽早并经常测试
一些开发人员对他们的技术非常有信心,以至于他们在没有运行测试的情况下构建了整个项目。但是,除非手头的任务完全无关紧要,否则就会适得其反。
一旦他们试图编译或执行程序,屏幕就会充满错误信息。或者,更糟糕的是,错误直到几个月后才被发现,这时用户才意识到程序没有按预期运行。
这些都是不好的做法。如果说在科技行业工作教会了你什么,那应该是这个:
如果你没有测试过所有的场景,千万不要认为某样东西能按预期工作。
尽快尝试构建一些可执行的东西。哪怕非常非常简单。一有机会就测试一下。这样,您就可以在错误一产生就修复它们。
诀窍 2:结构良好,格式草率
只要代码的底层结构良好,追求快速修复是没问题的。现实情况是,开发人员试图在结构混乱或过时的代码中实现快速修复。
在这种情况下,最好花时间重新构建代码。如果修复没有得到正确的注释,或者有一些模糊的变量名,那也不是世界末日。但是试图在错误的代码中构建一个干净的特性是浪费时间和资源——无论如何,你都可能不得不重写很多。
因此,在整洁和速度之间的一个好的折衷是保持底层结构的整洁和更新,并且在细节上尽可能的整洁。
把魔鬼藏在细节里。阿尔瓦罗·雷耶斯在 Unsplash 上拍摄的照片
黑客 3:为重构分配时间
每当你变得混乱,你就在制造技术债务。就像货币债务一样,你拖得越久,它就变得越昂贵。
另一方面,花几天甚至几周的时间清理代码对普通开发人员来说听起来并不怎么鼓舞人心。这就是为什么建立一个每天偿还一点债务的惯例是有用的。
一个好的开始方法是每天用 15%的时间进行重构。我称之为时间法则。您会惊讶于您可以改进多少代码!
列出了八种代码气味,所以您可以避免它们
medium.com](https://medium.com/better-programming/what-is-it-that-makes-your-code-smell-f9c96ac93ba2)
黑客 4:留下比你发现的更干净的代码
我称之为厕所规则。如果每个人离开公共浴室时至少保持他们发现的清洁,他们将处于一种无可挑剔的状态。
从大多数公共厕所的状况来看,现实并非如此。遵守这样的规则需要每个开发人员的纪律,这反过来又需要一个优秀的经理。
但这种纪律是值得的,因为随着时间的推移,回报会是巨大的。你不能通过做不可能的事情来实现不可能——你只能通过做一些好的决定,每天朝着这些决定迈出一小步来实现。
黑客 5:请求评论!
有时,代码很混乱,因为开发人员不知道如何做得更好。例如,一个代码可能会使用 switch 语句,这样映射就容易多了。在这种情况下,高级开发人员的建议是关键。
建立一个常规的代码审查可以帮助创建一个反馈循环。这将改善年轻开发人员的学习曲线,并培养健康讨论的文化。
就像如厕规则和时间规则一样,常规是关键。要求评审应该是初级开发人员的习惯,而给出建议应该是高级开发人员工作中不可或缺的一部分。
理想情况下,评审时间应该是开发团队核心流程的一部分,关键建议的总结应该是每次会议的一部分。
平衡结构和混乱
过多的清洁会浪费时间和资源。写草率的代码要比遇到编码器阻塞而不交付好得多。
另一方面,草率的代码缺乏灵活性,难以维护。这五条规则将有助于在不浪费时间的情况下,使您的代码更加清晰。正如生活的每一部分一样,美好的事物都是在结构和混乱的健康平衡中产生的。
关于 Python 类和库,数据科学家需要知道的四件事
我从来没有机会在教室里学习 Python。而是通过自学,学会了编程语言。没有系统地学习编程语言的一个缺点是,有时我不能完全理解其他人的 Python 代码,我可能无法充分利用 Python 编程的特性。在这里,我将总结一下关于 Python 类和库的四件事,这四件事曾经让我很困惑。希望这对你学习 Python 有帮助!
1.调用内部变量和函数的类
在 Python 类中,_ _ init _ _ 方法需要显式传递 self 参数。此外,如果一个函数需要使用在同一个类中定义的内部变量或函数,self 参数也需要显式传递给那个函数。
2.定义具有多个输入参数的类
Python 允许通过使用 arg,args 和**kwargs 来定义具有多个输入参数的类。args 接受无关键字的可变长度参数列表,而**kwargs 接受有关键字的可变长度参数列表。下面我们来看一个例子。
Multiple_constructor(1, 2, 3, 4, a='a',b='b')
输出:
arg1: 1,arg2: 2
args: (3,4)
args: {'a': 'a ',' b': 'b'}
Multiple_constructor(1, 2, a='a',b='b')
输出:
arg1: 1,arg2: 2
没有*args 传入
args: {'a': 'a ',' b': 'b'}
Multiple_constructor(1, 2)
输出:
arg1: 1,arg2: 2
无*args 传入
无**kwargs 传入
Multiple_constructor(1)
输出:
init()缺少 1 个必需的位置参数:“arg2”
3.重用模块
通常,我们希望在其他程序中重用类或函数。其实 Python 库是一种代码复用的方式。在下面的例子中,我将展示如何在 main.py 文件中重用 moduleA 和 moduleB。
重用 moduleA 很简单。由于 moduleA.py 与 main.py 在同一个文件夹中,所以 moduleA 可以直接导入到 main.py 中。
由于 moduleB 位于子文件夹中,我们需要先将 moduleB.py 的相对路径添加到系统中。然后我们可以在 main.py 中导入 moduleB。
moduleA.py 和 moduleB.py 在 main.py 中重用
输出:
你好爱丽丝!你好鲍勃!
4.if name == 'main '
name 是一个特殊的 Python 变量。如果直接运行当前文件,name = 'main '。但是,如果导入了当前文件,name = fileName。
if name=='main ' '是控制是否在此 if 测试中运行代码的一种方式。当直接运行当前文件时,将运行 if 测试中的代码。但是,当当前文件被其他文件导入时,if 测试中的代码将不会运行。通过这种方式,Python 允许根据文件是直接运行还是导入来灵活地控制是否运行代码。
输出:
文件 1 在 if name=='main '测试之前是 _ _ main _ _
文件 1
文件 1 在 if _ _ name _ _ = ' _ _ main _ _ '测试之后直接运行
文件 1
输出:
文件 1 是文件 1
文件 1 之前 if _ _ name _ _ = ' _ _ main _ _ '测试
文件 1 导入
文件 1 之后 if _ _ name _ _ = ' _ _ main _ _ '测试
文件 2 是 main
文件 2 之前 if _ _ name _ _ = ' _ _ main _ _ '测试
文件 2 直接运行
文件 2 之后 if _ _ name _ _ = ' _ _ main _ _ '测试
结论
在这篇短文中,我讨论了 Python 类和库的四个重要方面。作为一种面向对象的编程语言,Python 允许灵活使用类和库。通过包含一些代码示例,希望您对这四个 Python 概念有更清晰的理解!
在 Python 中探索数据的四个有用函数
在 Python 中探索和可视化数据
瓦伦丁·安托努奇在的照片
在探索数据的过程中,我经常发现自己重复定义类似的 python 逻辑,以便执行简单的分析任务。例如,我经常计算数据中特定类别的数字列的平均值和标准偏差。我还经常分析数据中分类值的频率。为了节省时间,我编写了一些函数,允许我在不重写太多代码的情况下进行这种类型的分析。
在这篇文章中,我将分享我在模型构建的探索性数据分析步骤中经常使用的四个有用的函数。然后我将展示我们如何使用这些函数来探索葡萄酒评论数据集。数据集可以在这里找到。该文件夹包含三个。csv 文件。我将使用名为“winemag-data_first150k.csv”的文件。
我们开始吧!
- 计数器
我将讨论的第一个函数允许我们查看分类值在数据集中出现的频率。它接受数据帧、列名和限制作为输入。当被调用时,它打印分类值的字典以及它们出现的频率:
def return_counter(data_frame, column_name, limit):
from collections import Counter print(dict(Counter(data_frame[column_name].values).most_common(limit)))
让我们打印数据集的前五行:
import pandas as pd
df = pd.read_csv('winemag-data_first150k.csv')
print(df.head())
我们可以看到有几个分类列。让我们将函数应用于“国家”列,并将结果限制在五个最常见的国家:
return_counter(df, 'country', 5)
我们可以看到大部分的葡萄酒记录都对应于美国生产的葡萄酒。
让我们将函数应用于“品种”列:
return_counter(df, 'variety', 5)
大多数葡萄酒是夏敦埃酒和黑皮诺酒。这是一个有用的快速测试,可以查看数据中是否有任何明显的不平衡,这通常是建模时要处理的一个关键问题。
2.汇总统计
下一个函数是汇总统计函数(有点类似于 df.describe())。该函数采用一个数据帧、一个分类列和一个数字列。每个类别的数字列的平均值和标准偏差存储在数据框中,并且数据框根据平均值以降序排序。如果您想要快速查看特定类别对于特定数字列是否具有更高或更低的平均值和/或标准偏差值,这将非常有用。
def return_statistics(data_frame, categorical_column, numerical_column):
mean = []
std = []
field = []
for i in set(list(data_frame[categorical_column].values)):
new_data = data_frame[data_frame[categorical_column] == i]
field.append(i)
mean.append(new_data[numerical_column].mean())
std.append(new_data[numerical_column].std())
df = pd.DataFrame({'{}'.format(categorical_column): field, 'mean {}'.format(numerical_column): mean, 'std in {}'.format(numerical_column): std})
df.sort_values('mean {}'.format(numerical_column), inplace = True, ascending = False)
df.dropna(inplace = True)
return df
我们可以查看“品种”和“价格”的汇总统计数据:
stats = return_statistics(df, ‘varieties’, ‘prices’)
print(stats.head())
麝香葡萄品种的平均价格最高。
我们可以为国家做同样的事情:
stats = return_statistics(df, ‘countries’, ‘prices’)
print(stats.head())
英国的平均价格最高。
3.箱线图
下一个函数是 boxplot 函数。我们使用箱线图来显示基于最小值、最大值、中值、第一个四分位数和第三个四分位数的数值分布。如果你对它们不熟悉,可以看看文章了解盒子情节。
与汇总统计函数类似,此函数采用数据框、分类列和数值列,并根据限制显示最常见类别的箱线图:
def get_boxplot_of_categories(data_frame, categorical_column, numerical_column, limit):
import seaborn as sns
import matplotlib.pyplot as plt
keys = []
for i in dict(Counter(df[categorical_column].values).most_common(limit)):
keys.append(i)
print(keys)
df_new = df[df[categorical_column].isin(keys)]
sns.boxplot(x = df_new[categorical_column], y = df_new[numerical_column])
让我们为 5 个最常见的国家的葡萄酒价格绘制箱线图:
get_boxplot_of_categories(df, 'country', 'price', 5)
正如我们所见,在所有五个国家类别中,葡萄酒价格都有明显的异常值。我们可以对“多样性”做同样的事情。为了更好地可视化,我将类别值限制为三个国家:
get_boxplot_of_categories(df, 'variety', 'price', 3)
4.散点图
最后一个函数是散点图函数。此函数将一个数据框、分类列、分类值和两个数字列作为输入,并显示一个散点图:
def get_scatter_plot_category(data_frame, categorical_column, categorical_value, numerical_column_one, numerical_column_two):
import matplotlib.pyplot as plt
import seaborn as snsdf_new = data_frame[data_frame[categorical_column] == categorical_value]
sns.set()
plt.scatter(x= df_new[numerical_column_one], y = df_new[numerical_column_two])
plt.xlabel(numerical_column_one)
plt.ylabel(numerical_column_two)
让我们制作一个美国葡萄酒点数与价格的散点图:
get_scatter_plot_category(df, 'country', 'US', 'points', 'price')
价格和奖励积分之间似乎存在轻微的正相关关系。我就讲到这里,但是请随意处理数据并自己编码。
概括地说,在这篇文章中,我回顾了我在探索性数据分析过程中经常使用的四个有用的函数。我回顾了分析数据的方法,包括用箱线图和散点图可视化数据。我还定义了生成汇总统计数据的函数,比如平均值、标准差和分类值的计数。我希望这篇文章是有帮助的。
这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!
团队在 Kaggle 上获胜的四种方式
框架、多重处理、云以及更大的团队
Kaggle 是最好和最差的机器学习的家园。这是成千上万个团队的战场,他们争相建立最佳模型,在最后期限内解决现实世界的问题,赌注是几十万美元。在大型数据集上训练这些世界级的模型通常需要数百个计算小时。在本帖中,我们将探索获胜团队使用的一些技巧以及如何加快速度。
[图片来源】
#1 —使用顶层框架
有时 Kaggle 上的竞争会导致模型无法复制或者彻头彻尾的欺诈。但其中一些竞争为整个行业设立了新的标准。Kaggle 是机器学习成为焦点并取得巨大进展的地方。世界上最好的模型构建框架受到 Kaggle 竞赛的启发并围绕其构建。
获胜——团队从他们的工具中榨出每一分每一毫的绩效。当工具不够好或不够快时——更好的工具就会被制造出来。这方面的例子有流行的梯度增强库:
- 2014—XGBoost—【github】【论文】—2015 年 Kaggle 比赛期间,29 个获奖方案中有 17 个方案使用了 XGBoost 。
- 2017—light GBM(LGBM)—【github】【paper】—由微软开发,比 XGBoost 快 20 倍,但并不总是那么准确。这个库是 2019 年 Kaggle 上流行内核的默认选择。
- 2017—CatBoost—【github】【论文】 —没有 LightGBM 常用,但在利用分类列的中可以有优势。
竞赛获胜者经常结合多个模型构建库来稍微提高性能。关于这些梯度增强框架的深入比较,请参见本文。许多竞赛获胜者也使用 Keras 库,尽管它最初的设计并没有考虑到 Kaggles。
上面的图片来自 Keras 图书馆的作者 Franç ois Chollet 的一条推文。在这条线索中,他指出:
赢家是那些经历了“进步循环”的“更多迭代”的人——从一个想法,到它的实施,再到可操作的结果。所以获胜的团队就是那些能够跑得更快的团队。
#2 —利用多重处理
为了获胜,Kaggle 团队需要在有限的时间内测试尽可能多的想法。对于千兆字节的数据,每次迭代都以小时为单位。有许多参数可以调整,使训练过程更短。但是,为了优化排行榜分数,训练必须“进行到 11”。考虑到需要许多小时的计算,自然的优化是并行化。
在 Python 中,由于全局解释器锁(GIL),使用线程来并行化工作通常是没有意义的。Kaggle 上流行的框架都在内部进行了多线程优化,以利用多个内核将训练时间减少 10 倍。他们还可以利用 GPU 将训练速度提高10 倍。但是,测试许多超参数和特征组合意味着进一步增加工作量。仅仅是加载数据就可能非常耗时,以至于一些团队使用多重处理来应对这种情况,如下所示:
files = ['../input/test_identity.csv',
'../input/test_transaction.csv',
'../input/train_identity.csv',
'../input/train_transaction.csv',
'../input/sample_submission.csv']def load_data(file):
return pd.read_csv(file)with multiprocessing.Pool() as pool:
test_id, test_tr, train_id, train_tr, sub = pool.map(load_data, files)
多重处理本身可以在强大的机器上本地工作。不幸的是,我的 MacBook 有点温顺。最重要的是,繁重的任务完全消耗了我的机器资源。后台任务繁重,即使阅读电子邮件也变得缓慢而痛苦。
#3 —云上的多重多处理
启动一台机器来运行一个可能需要一个多小时才能返回的函数可能是值得的。让机器运转几个小时来实现多种功能尤其有用。有很多方法可以获得一台机器来完成工作,比如使用 AWS Fargate、Google Cloud Run 和其他提供商。在 XGBoost 分布式培训教程中有一些这样的例子。
使用云时要考虑的权衡是速度、成本和设置一切的复杂程度。下面的代码片段使用了dismap,它提供了对multiprocessing.Pool()
的替换,所以它非常简单。map 中的每次迭代可能会发现自己在不同的机器上,而我们的主机只会等待结果。
def pow3(x):
print (x**3)
return (x**3)
with discomp.Pool() as po:
results = po.map(pow3, range(10))
print(results)
# prints [0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
虽然这个例子很简单,但是您可以推断出可以做什么。对于更完整的场景,您可以看到我如何使用 XGBoost 在信用卡欺诈数据集中比较不同超参数配置的性能。使用传统的map
呼叫测试 30 组参数需要 82 分钟,使用multiprocessing.Pool().map
需要 35 分钟,使用discomp.Pool().map
需要 9 分钟。使用云机器,我可以以 9 倍的速度运行测试。使用云确实要花钱,所以它并不是适合所有人的解决方案。有点像这艘船。
[图片来源
#4 —更大的团队
通常较大的团队在 Kaggle 上有优势,因为每个团队成员都用不同的参数和库探索不同的特性和不同的模型。团队中的每个人也将贡献自己的计算资源。最后,所有的模型将被组合成一个集合平均值,它往往比每个单独的模型表现得更好。要更深入地分析团队规模趋势,请查看本笔记本。
优化时间
在 Kaggle 中,给你的是带标签的数据,所以机器学习中的一个大问题已经解决了。所有竞争者剩下要做的就是预处理,选择正确的模型,使用最好的软件包,设计最好的特性和确定最好的参数。这仍然是一项很少有人擅长的艰巨任务。一个团队可以测试的组合数量直接受限于他们周期的持续时间以及他们可以在多少台机器上运行它们。幸运的是,现在有许多选择可以节省时间并获得计算资源。请告诉我你是否觉得这些技巧有用,或者只是在 twitter 上打个招呼。
根据数据值集合过滤 Spark 数据集的四种方法
Ref: Pixabay
实践教程,SPARK 执行指南
根据数据值集合过滤 Spark 数据集是许多数据分析流程中经常遇到的问题。这个特别的故事将解释四种不同的方法来达到同样的目的。
假设有一个非常大的数据集“A ”,其模式如下:
root:
| — empId: Integer
| — sal: Integer
| — name: String
| — address: String
| — dept: Integer
数据集“A”需要根据一组员工 id(empid)、“B”(可以广播给执行者)进行过滤,以获得过滤后的数据集“A”。过滤操作可以表示为:
A` = A.filter(A.empId contains in 'B')
为了实现这种最常见的过滤场景,您可以在 Spark 中使用四种类型的转换,每一种都有其优缺点。这里描述了使用所有这四种转换来执行这个特定的过滤场景,并详细说明了每种转换的可靠性和效率。
Filter:Filter transformation(在布尔条件表达式或布尔返回过滤函数上过滤数据集记录),在数据集上,可以用以下方式:
1\. Dataset<T> A` = A.filter(Column condition)
2\. Dataset<T> A` = A.filter(FilterFunction<T> func)
3\. Dataset<T> A` = A.filter(String conditionExpr)
对于筛选场景,如前所述,可以对“A”使用“Filter”转换,将“FilterFunction”作为输入。对相应数据集的分区中包含的每个记录调用“FilterFunction ”,并返回“true”或“false”。在我们的过滤场景中,将对数据集“A”的每个记录调用 FilterFunction,并检查记录的“empId”是否存在于广播的 empId 集“B”中(“B”由相应的哈希表支持)。
不管数据集“A”的大小如何,如上所述的过滤器变换的使用都是非常简单、健壮和有效的。这是因为,转换是逐记录调用的。此外,由于所广播的 empIds 组由执行器上的哈希表支持,所以在过滤函数中对每个记录的过滤查找保持有效。
映射:映射转换(对数据集的每条记录应用一个函数,以返回空的、相同的或不同的记录类型),在数据集上以下列方式用于:
Dataset<U> A` = A.map(MapFunction<T,U> func, Encoder<U> encoder)
对于过滤场景,如前所述,可以对“A”使用“Map”转换,将“MapFunction”作为输入。在我们的过滤场景中,将对数据集“A”的每个记录调用“MapFunction ”,并检查记录的“empId”是否存在于广播的 empId 集“B”中(由相应的哈希表支持)。如果记录存在,MapFunction 将返回相同的结果。如果记录不存在,将返回 NULL 。此外,MapFunction 的编码器输入将与数据集“A”的相同。
尽管‘Map function’的语义类似于‘Filter function ’,但是对于过滤场景,如上所述的‘Map’转换的使用与直接‘Filter’转换方法相比并不简单和优雅。必须在转换中明确提供额外的编码器输入。此外,在调用“Map”转换后,需要过滤输出中的空值,因此,“Map”方法不如“Filter”方法有效。然而,该方法的可靠性类似于“过滤”方法,因为无论“A”的大小如何,它都不会出现问题。这是因为,“映射”转换也是逐记录调用的。
map partitions:map partitions转换(在数据集的每个分区上应用一个函数,返回 null 或迭代器到相同或不同记录类型的新集合),在数据集上,以下面的方式使用:
Dataset<U> A` = A.map(MapPartitionsFunction<T,U> func, Encoder<U> encoder)
对于筛选方案,如前所述,还可以对“A”使用“MapPartitions”转换,该转换将“MapPartitionsFunction”作为输入。在我们的过滤场景中,将在数据集“A”的每个分区上调用“MapPartitionsFunction ”,迭代该分区的所有记录,并检查每个记录,如果记录的“empId”存在于广播的 empId 集“B”中(由相应的哈希表支持)。在记录存在的情况下,相同的记录将被添加到在“MapPartitionsFunction”中初始化的可返回集合中。最后,从“MapPartitionsFunction”返回可返回集合的迭代器。
与“映射”和“过滤”方法相比,“映射分区”方法通常更有效,因为它是分区方式操作,而不是记录方式操作。然而,与“映射”类似,必须在转换中明确提供编码器输入。此外,在数据集‘A’的某些分区的大小超过为执行每个分区计算任务而提供的存储器的情况下,‘map partitions’方法可能变得非常不可靠。这是因为更大的分区可能导致潜在的更大的可返回集合,从而导致内存溢出。
内连接:内连接转换应用于两个输入数据集,A & B,采用的方式:
Dataset<Row> A` = A.join(Dataset<?> B, Column joinExprs)
对于筛选场景,如前所述,还可以对“A”使用“内部连接”转换,该转换根据连接条件连接“B”的数据集表示(A.empId 等于 B.empId ),并从每个连接的记录中只选择“A”的字段。
“内部连接”方法返回一般“行”对象的数据集,因此需要使用编码器将其转换回 A 的记录类型的数据集,以匹配精确的过滤器语义。然而,类似于“过滤”方法,“内部连接”方法是有效和可靠的。效率来自于这样一个事实,因为“B”是可广播的,Spark 将选择最有效的“广播散列连接”方法来执行连接。此外,可靠性来自于“内部连接”方法适用于“A”的大型数据集,就像“过滤”方法一样。
考虑到所有的方法,从可靠性和效率的角度来看,我会选择“过滤”方法作为最安全的选择。此外,要注意的是,“过滤器”方法还允许我以类似的效率和健壮性执行反搜索,这是“内部连接”所不允许的。
如果对这个故事有反馈或疑问,请写在评论区。我希望,你会发现它有用。这里是我在 Apache Spark 上的其他综合报道的链接。 还有,拿一份我最近出版的关于 Spark Partitioning 的书:《Spark Partitioning 指南: 深入讲解 Spark Partitioning》
傅立叶变换和图像的床单视图。
约翰·汤纳在 Unsplash 上拍摄的照片
开发傅立叶变换工作原理背后的直觉。
傅立叶变换是做什么的?傅立叶模式代表什么?为什么傅立叶变换在数据压缩方面是出了名的受欢迎?这些是本文旨在用一个有趣的类比来表示图像的问题。
图像是数字绘画。它们由不同的特征组成。有些功能需要非常精确地控制笔刷,比如在狗身上画胡须。其他的可以用粗画笔快速填充,像清澈的蓝天。所有图像都是不同程度的精细和暗淡特征的组合,即高频和低频特征。
让我们花点时间来理解频率是如何进入我们的分析的。想象正弦波经过半个周期。它慢慢上升,达到最大值,然后慢慢减小。正弦的频率越高,波就越窄。
想象一个被诅咒的画家,他只能用笔尖是半波正弦的画笔画画。如果他要画一个精致的特征,比如狗的胡须,他会选择一个正弦频率高的笔刷,即一个窄尖的笔刷。类似地,如果他要画一个没有任何细节的晴朗的天空,他会选择低频率的笔刷,也就是说,一个厚一点的笔刷。
频率越高,峰值越窄。
令人惊讶的是,所有现存的图像就像被诅咒的画家的作品一样。值得注意的是,傅立叶表明每一幅图像(信号)都可以分解成一系列复杂的项,其中每一项都有一个数值。幅度被称为傅立叶系数。将图像分解成各种正弦项及其幅度的整个过程称为傅立叶分解。傅立叶级数是一种更普遍的情况,其中要分解的信号是周期性的。傅立叶变换是信号具有无限时间周期,即非周期性的特殊情况。
完成上述分解的一种优雅而快速的算法是快速傅立叶变换,它可以说是 21 世纪将要开发的最重要的算法。它在蜂窝通信、卫星、电影、电视等领域有着深远的应用。
为了形象化图像的弯曲性质,绘制图像的大小,就像绘制表面图一样,并观察轮廓的俯视图,这将是很有趣的。这个想法是由华盛顿大学的史蒂文·布伦顿博士提出的。
图像的曲折性质清晰可见。高频特征作为窄峰清晰可见。这些包括眼睛、面部结构的轮廓和人手的轮廓。低频特征通常是均匀颜色的巨大延伸,在背景中观察到。这些包括大面积的黑色皮毛和背景。
下面是复制先前结果的简单代码。
制作表面情节动画的源代码包含在我的 Github 中,在这里!
这被称为图像的床单视图。这个名字背后的想法是,如果四个人拿着一张床单的每一边,并开始以相应的幅度在一个傅立叶频率下振荡,并且对于无限傅立叶模式中的每一个都存在四个人的类似设置,那么所有床单的叠加将导致物理上的折痕,看起来像上面的图像。因此得名,床单观!
好了,现在有了一个好的直觉来理解傅立叶变换能做什么,这是一个很好的练习来正式回顾这些想法。离散信号的傅里叶分解方程如下:
这里,xn 是时间 N 处的信号值,Xk 是每个频率 k 的傅立叶系数,N 是信号样本的总数(即记录信号的离散时间步长的数量)。FFT 算法返回每个频率的 Xk 值。使用欧拉公式可以将复指数分解为正弦和余弦。这为迄今为止开发的直觉提供了一个健全的检查。
例如,让我们用多个频率构建一个正弦信号。比方说,频率为 50、100 和 200 赫兹的正弦信号以不同的比例组合而成。周期性质仍然可见,但通过在时域中可视化信号来理解原始频率成分确实很难。
傅立叶变换有助于直观地显示频域中的信号。因此,对上述信号进行傅立叶分解,我们可以得到下面的图。
混合物在 50、100 和 200 Hz 下的真实频率在频域中显示出预期的峰值。值得注意的是,FFT 算法也可以给出每个频率分量的权重,而不需要信号的任何先验知识。
啊,是的!臭名昭著的单线 FFT 命令。在 MATLAB 中,就更简单了,不需要任何导入,只需要 fft()。
现在回到图像的单页视图,每张图片都是可以应用傅立叶分解的二维信号。如果获取图像的一部分,它将类似于我们示例中的时域信号,但具有自己的频率成分。床单的看法是强大的开发直觉背后的一个图像可以是一个简单的信号,在时域,与多维度。
一般来说,信息密集区由高频项组成,而均匀的平坦区域由低频项组成。傅立叶的天才在于推导加权模式(或频率-幅度对)。这为理解构成图像的最重要的模式提供了一个思路。事实证明,帕累托法则在这里是成立的,只有极少数的模式包含了图像的大部分信息。这个原则对数据压缩至关重要。通过忽略大多数模式,我们可以减小图像的大小。然而,图像质量只是略有下降。
如果你有兴趣更深入地了解傅立叶变换如何用于数据压缩,或者理解为什么数据是可压缩的,首先,查看我的前一篇文章。像往常一样,联系我继续对话,或者向我提供一些关于内容的反馈。
FP 增长——用 Python 实现数据挖掘中的频繁模式生成
在大项目集中挖掘关联规则的强大算法!
介绍
在前一篇文章中,我们已经介绍了 Apriori 算法,并指出了它的主要缺点。在本文中,我们将展示一种叫做 FP 增长算法的高级方法。我们将介绍 FP 增长算法的整个过程,并解释为什么它比 Apriori 算法更好。
[## Apriori:关联规则挖掘的深层解释及 Python 实现
关联规则挖掘是一种识别不同项目之间潜在关系的技术。方法有很多…
towardsdatascience.com](/apriori-association-rule-mining-explanation-and-python-implementation-290b42afdfc6)
为什么好?
让我们回忆一下上一篇文章,Apriori 算法的两个主要缺点是
- 候选项目集的大小可能非常大
- 计数支持的高成本,因为我们必须一遍又一遍地扫描项目集数据库
为了克服这些挑战,Fp 增长的最大突破是
不需要候选人生成!
Apriori 的所有问题都可以通过利用 FP 树来解决。更具体地说,项集大小将不再是一个问题,因为所有的数据将以一种更紧凑的方式存储。此外,没有必要一遍又一遍地扫描数据库。相反,遍历 FP 树可以更有效地完成同样的工作。
FP 树
FP 树是整个 FP 增长算法的核心概念。简单来说,FP 树就是项目集数据库的压缩表示。树结构不仅在数据库中保留项目集,而且跟踪项目集之间的关联
该树是通过获取每个项目集并一次一个地将其映射到树中的路径来构建的。这个建筑背后的整个想法是
更频繁出现的项目将有更好的机会共享项目
然后我们递归地挖掘树来得到频繁模式。模式增长,算法的名字,是通过连接从条件 FP 树生成的频繁模式来实现的。
忽略树上的箭头。图片作者。
FP 增长算法
请随意查看评论良好的源代码。这真的有助于理解整个算法。
pip 安装 fpgrowth_py,然后像使用 git clone git clone 一样使用它来获得此回购的副本…
github.com](https://github.com/chonyy/fpgrowth_py)
FP 增长如此高效的原因是这是一种分而治之的方法。我们知道,有效的算法必须利用某种数据结构和高级编程技术。它实现了树、链表和深度优先搜索的概念。这个过程可以分为两个主要阶段,每个阶段又可以进一步分为两步。
阶段 1: FP 树构建
第一步:清洁和分类
对于每个事务,我们首先删除低于最低支持的项目。然后,我们按照频率支持降序对项目进行排序。
图片作者。
第二步:构建 FP 树,标题表包含已清理的项目集
遍历清理后的项集,一次映射一个到树中。如果分支中已经存在任何项目,则它们共享同一个节点,并且计数递增。否则,该项将位于创建的新分支上。
标题表也是在这个过程中构建的。交易中每个独特的项目都有一个链表。使用链表,我们可以在短时间内找到项目在树上的出现,而无需遍历树。
来源:https://www . researchgate . net/figure/An-FP-tree-and-its-header-table-15 _ fig 1 _ 280940829
阶段 2:挖掘主树和条件 FP 树
步骤 1:将主 FP 树分成条件 FP 树
从每个频繁 1-模式开始,我们用 FP 树中的前缀集创建条件模式基。然后,我们使用这些模式库,以与阶段 1 完全相同的方法来构造条件 FP 树。
步骤 2:递归挖掘每个条件树
频繁模式从条件 FP 树中生成。为一个频繁模式创建一个条件 FP 树。我们用来挖掘条件树的递归函数接近深度优先搜索。它确保在继续之前,没有更多的树可以用剩余的项目来构建。
让我们仔细看看下面的过程
图片作者。
同级别同颜色。算法工作流程如下所示
- 检查第一个 1-频繁模式“a”
- 获取粉红色的“a”的条件 FP 树
- 挖掘粉红色的树,深入到第二层
- 检查粉色树上的“f ”,发现没有更多的树可以构建
- 在粉红色的树上勾选 c
- 开采黄树,深入到第 3 层
Python 实现
FP 增长函数
乍一看这个 FP growth 主函数,你可能会对它的两个部分产生疑问。
为什么要为项目集和频率使用单独的列表,而不是创建一个字典?
原因是 Python 字典中的键必须是不可变的,所以我们不能把 set()作为键。然而,不可变版本的 set, frozenset 是可以接受的。不幸的是,由于这些项目的顺序在 FP 增长算法中至关重要,我们无法在转换到 frozenset 后保留顺序。对此的唯一解决方案是将其存储在单独的列表中。
为什么在 mineTree 函数中不把 FP 树作为输入变量?
这就是表头的威力。因为我们已经在标题表中存储了所有的事件,所以没有必要将根节点传递给函数。利用表上的链表,我们可以快速找到树上的项目。
树形结构
对于 itemset 列表,我们首先创建一个半空的标题表,其中只包含项目及其频率。我们遍历每个项目集,按照频率降序对项目进行清理和排序。然后,我们通过从清理的项目集中逐个传递项目来更新树。
如果项目已经存在于树中,我们只需增加计数。否则,我们用该项创建一个新的分支,并将其附加到父节点。这里要做的一个重要步骤是更新标题表,因为出现了新的条目。将新出现的链接到标题表中的链接列表。
树木开采
矿井树
从 1-频繁模式出发,我们找到所有的前缀路径,并用它构造条件模式库。对于条件模式基,使用与上面完全相同的 constructTree 函数来构建树。如果这棵树能被成功构建,我们会更深入,开始研究这棵树。这是递归发生的地方。
还记得我提到过为每个频繁模式构建一个条件树吗?你可以在线 8 上看到图案生长。
查找前缀路径
获取该项在树上的第一个匹配项,它是表头链表的头节点。然后,遍历树直到根,以获得前缀路径。之后,我们转到链表中的下一个节点,重复遍历。
上升 FP 树
用自递归来提升树。继续追加项目并调用自身,直到它到达根。
比较
FP 增长与先验
图片作者。
我已经组织了两种算法的主要特征,并把它制作成上表。通过观察表格,我们可以知道,在大多数情况下,FP 增长通常比先验增长好。这就是为什么 Apriori 只是一个基本方法,FP Growth 是对它的改进。
具有不同最小支持的运行时
图片作者。
我们从 源代码回购 中取数据集,尝试一些实验。我们做的第一件事是检查最小支持如何推断运行时间。
从图中我们可以看出,FP 的增长总是比 Apriori 快。原因已经在上面解释过了。一个有趣的观察是,在两个数据集上,apriori 的运行时间在一个特定的最小值后开始快速增加。另一方面,FP 增长的运行时间仅仅受到值的干扰。
运行时有不同数量的交易
图片作者。
两种算法的运行时间都随着项目集数量的增加而增加。然而,我们可以清楚地看到,先验增加的斜率要高得多。这意味着与 Fp 增长相比,Apriori 算法对项集大小更敏感。
升序与降序
您可能想知道为什么在使用它构建树之前,我们必须按照频率降序对项目进行排序。如果用升序试试会怎么样?从图中可以看出,降序排序总是更快。而且支撑越低速度的差别越明显。
图片作者。
但是为什么呢?我想给出一些我自己的假设。让我们回忆一下 FP 增长的核心概念
更频繁出现的项目将有更好的机会共享项目
从支持度较高的物品开始,共享分支的可能性会较高。共享的分支越多,树的大小就越小。树越小,运行整个算法的成本就越低。因此,按降序对项目进行排序会使该方法运行得更快。
结论
我想分享一个有趣的故事。当我下班后写这篇文章时,一个全职工程师走过,他看到我正在写一些关于先验和 Fp 增长的东西。他说,“有趣,但不现实”他进一步解释说,这种算法不考虑称重。例如,有多个相同项目的交易怎么办?还有更微妙的条件没有包含在这个算法中。这就是为什么公司不会在他们的业务中实现这一点。
源代码
pip 安装 fpgrowth_py,然后像使用 git clone git clone 一样使用它来获得此回购的副本…
github.com](https://github.com/chonyy/fpgrowth_py)
以前的帖子
[## Apriori:关联规则挖掘的深层解释及 Python 实现
关联规则挖掘是一种识别不同项目之间潜在关系的技术。方法有很多…
towardsdatascience.com](/apriori-association-rule-mining-explanation-and-python-implementation-290b42afdfc6)
PyPi 包
pip 安装 fpgrowth_py,然后像使用 git clone git clone 一样使用它来获得此回购的副本…
pypi.org](https://pypi.org/project/fpgrowth-py/)
医疗保健中的欺诈检测
使用表格即识别可疑的医疗服务提供者
engin akyurt 在 Unsplash 上拍摄的照片
你知道吗,在美国,数十亿美元花费在欺诈、浪费和滥用处方药上。
此外,您是否知道只有 20%的医疗保健提供商承担了 80%的成本!?
你会问,我是怎么知道的?
TLDR :如何识别可疑的和可能有欺诈行为的医疗服务提供者?看看我的场景,即和我制作的解释这些场景的视频。
我曾经和美国一家主要的健康保险公司合作过。在广泛研究了绝密的患者索赔数据后(它受到严格的法律保护!)在多个项目中,我意识到的一件事是阿片类药物危机是真实存在的。即使我们把阿片类药物放在一边,欺诈性索赔的数量也是巨大的。然而,应该提到的是,我们通常所说的欺诈,实际上是欺诈、浪费和滥用(FWA)。而欺诈是故意和恶意进行的(咄!),浪费和滥用并不要求对不法行为有意图和知情。浪费是对资源的过度利用,而滥用是指提供者的做法与合理的财政、商业或医疗做法不一致。
无论如何,当目标是确定这样的医疗保健提供者时,我们面临一个问题:他们实在是太多了!
这就像大海捞针。更准确地说,这就像在一堆针中找到一根有缺陷的针。进入图形分析来拯救。使用 Tableau 仪表板,我将展示如何过滤提供者并识别可疑的提供者。通过这种方式,我们减少了搜索池的大小,从而使查找故障针变得容易。;)
但是数据在哪里呢?实际的患者索赔数据受到保护(称为 PHI,即受保护的健康信息),公众无法获得。但是我们可以凑合使用公共可用的医疗保健数据,这些数据是在提供者级别上汇总的,因此它不会识别患者。医疗保险和医疗补助服务中心在开处方者汇总表中提供此类数据。该数据包含每个提供者提供的处方的汇总详细信息,如阿片类药物、抗生素、品牌药物、仿制药,以及提供者的人口统计信息。
我确定了一些我认为在判断开处方者的欺诈行为时很重要的特征。
我应用了 k-means 聚类,并使用 KElbowVisualizer 来确定最佳聚类数,如下所示。
from yellowbrick.cluster import KElbowVisualizervisualizer = KElbowVisualizer(KMeans(init='k-means++'), k=(3,11))
visualizer.fit(X) # Fit the data to the visualizer
visualizer.show()
完整的代码可以在这个 colab 笔记本中看到。使用肘方法,我决定 5 是集群的最佳数量
我在数据帧中为每个处方者标记了他们的簇号。
看看我做的这个画面。它有三个视图来讲述一个故事,并帮助确定一些特定的可疑处方。
以下是三视图显示的内容:
美国整体医疗保健提供者/开处方者情景概述;这些图表还充当其他图表的过滤器,因此我们可以使用上面的两个图表在右下角的条形图中看到加利福尼亚去看牙医的患者的疾病水平。
第二个屏幕直观地解释了集群之间的差异;查看器可以选择使用下拉功能列表来更改指标,该列表给出了每个集群的前 3 个特性。可以明显看出,集群 4 确实是可疑的,因为它在所有类别中具有最高的成本。
最后,我们更深入地研究集群 4,以识别异常提供商。我们还可以选择任何其他集群来精确定位混淆的提供者。右侧的散点图提供了悬停在圆圈上的提供商的详细信息。最右边的提供者/处方者是产生高费用的人。当他们的患者风险评分低时,我认为他们是可疑的。
总之,仪表板的视图 1 旨在教育美国数据和整体医疗保健情况的分析师或查看者。在熟悉数据之后,在第二个视图中,我希望直观地传达所形成的集群和所使用的特征之间的差异。因此,观点 2 可以被认为是解释性的。在视图 3 中实现了识别一个或多个混杂或异常处方者的最终目标。正如在第三视图的最后一个图表中可以看到的,我们有一个简单的方法来确定潜在欺诈的开处方者。
所呈现的可视化的优势在于成功地实现了识别可疑处方者的主要任务。在这个过程中,分析师或观众还可以了解医疗保健领域数据的复杂性,如成本和患者风险评分。然而,这种方法的鲁棒性不能保证。
仍然需要领域专家来判断使用 viz 识别为可疑的开处方者是否是假阳性。
例如,通过可视化识别的开处方者可能是仅迎合高费用患者/病例的开处方者。这样的开处方者将通过建议的可视化被错误地识别。与此同时,可以认为,考虑到其他特征,精通医疗保健领域的分析师或观察者将能够判断开处方者实际上是否是混淆者。
在 LinkedIn 上与我联系
在 GitHub 上查看一些我感兴趣的项目
欺诈检测:问题、解决方案和工具
机器学习如何改变欺诈检测格局
瑞安·波恩在 Unsplash 拍摄的照片
1.1 问题的性质
什么是欺诈?有许多正式的定义,但本质上欺诈是一种“艺术”,是在金融交易中欺骗和诈骗人们的犯罪。欺诈在整个人类历史中一直存在,但在这个数字技术时代,金融欺诈的策略、范围和规模变得越来越广泛,从信用卡交易到健康福利再到保险索赔。欺诈者也变得越来越有创造力。谁从来没有收到过一个尼日利亚皇室寡妇的电子邮件,说她正在寻找一个值得信任的人来移交她的大笔遗产?
难怪欺诈是一件大事。由于欺诈性交易,商业组织的估计损失飙升至其收入的 4-5%。5%的欺诈听起来可能不算多,但从货币角度来看,这不是小事,远远超过不采取任何行动的成本。普华永道的一项调查发现,他们调查的 7200 家公司中有 50%是某种欺诈的受害者。FICO 最近的一项研究发现,接受调查的五分之四的银行经历了欺诈活动的增加,预计这种情况在未来还会增加。
尽管许多组织采取措施打击欺诈,但欺诈永远无法根除。我们的目标是将它的影响降到最低。这种筛选的好处必须与成本进行权衡,例如,欺诈检测技术的投资和由于“假阳性”警报而可能失去的客户。
因此,本文的目的是强调欺诈检测领域的一些工具、技术和最佳实践。最后,我将使用公开可用的数据集提供一个 python 实现。
1.2 个使用案例
欺诈无处不在——无论交易涉及到哪里——但信用卡欺诈可能是最广为人知的案例。它可以是简单的偷窃或使用偷来的卡,也可以是侵略性的形式,如账户接管、伪造和更多。信用卡欺诈一直存在,但由于每天通过信用卡进行的在线交易越来越多,其规模只是在最近有所增长。根据尼尔森报告2010 年,全球欺诈金额为 76 亿美元,预计 2020 年将突破 310 亿美元。仅在英国,2018 年欺诈交易损失估计超过10 亿美元。
保险行业还在发生其他类型的大欺诈案件。一些估计表明,美国多达 10%的健康保险索赔可归因于欺诈,这是一个不小的数字,每年高达 1100 亿美元。
2.1 数据科学解决方案
在过去(即机器学习成为趋势之前),标准做法是使用所谓的“基于规则的方法”。由于每个规则都有例外,这种技术只能部分缓解问题。随着越来越多的在线交易和大量客户数据的产生,机器学习越来越被视为检测和反欺诈的有效工具。然而,没有一个特定的工具,银弹,适用于每个行业的各种欺诈检测问题。在每个案例和每个行业中,问题的性质是不同的。因此,每个解决方案都是在每个行业的领域内精心定制的。
在机器学习中,用语欺诈检测通常被视为一个监督分类问题,其中根据观察结果中的特征将观察结果分类为“欺诈”或“非欺诈”。由于不平衡的数据,这也是 ML 研究中一个有趣的问题,即在极其大量的交易中很少有欺诈案例。如何处理不平衡的阶级本身是另一个讨论的主题。
欺诈也可以通过几种异常检测技术来隔离。离群点检测工具有自己解决问题的方式,如时间序列分析,聚类分析,实时事务监控等。
2.2 技术
统计技术:平均值、分位数、概率分布、关联规则
监督 ML 算法:逻辑回归、神经网络、时间序列分析
无监督的 ML 算法:聚类分析、贝叶斯网络、对等组分析、断点分析、本福特定律(异常数定律)
3.一个简单的 Python 实现
3.1 数据准备
对于这个简单的演示,我使用了一个流行的 Kaggle 数据集。
# import libraries
import pandas as pd
import numpy as np# import data
df = pd.read_csv("..\creditcard.csv")# view the column names
df.columns
数据集有 31 列。第一列“时间”是交易时间戳,倒数第二列“金额”是交易金额,最后一列“类别”指定交易是欺诈还是非欺诈(欺诈= 1,非欺诈= 0)。其余的列,“V1”到“V28”是未知变量,在公开数据之前进行了转换。
# number of fraud and non-fraud observations in the dataset
frauds = len(df[df.Class == 1])
nonfrauds = len(df[df.Class == 0])print("Frauds", frauds); print("Non-frauds", nonfrauds)## scaling the "Amount" and "Time" columns similar to the others variablesfrom sklearn.preprocessing import RobustScaler
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)# define X and y variables
X = df.loc[:, df.columns != 'Class']
y = df.loc[:, df.columns == 'Class']
3.2 制作子样本
这是一个极度不平衡的数据集,所以我们需要通过所谓的欠采样进行子采样。
# 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])# Under sample 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']
3.3 建模
## split data into training and testing set
from sklearn.model_selection import train_test_split# # The complete dataset
# X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.3, random_state = 0)# Split dataset
X_train_undersample, X_test_undersample, y_train_undersample, y_test_undersample = train_test_split(X_undersample,y_undersample ,random_state = 0)## modeling with logistic regression#import model
from sklearn.linear_model import LogisticRegression
# instantiate model
model = LogisticRegression()
# fit
model.fit(X_train_undersample, y_train_undersample)
# predict
y_pred = model.predict(X_test_undersample)
3.4.模型验证
注意:不要使用准确性分数作为衡量标准。在一个具有 99.9%非欺诈观察的数据集中,您可能会在 99%的时间内做出正确的预测。混淆矩阵和精确度/召回分数是更好的度量。
# import classification report and confusion matrix
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrixclassification_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)
结束注意:
感谢您通读这篇文章。一个 Jupyter 笔记本连同 python 演示可以在GitHub repo中找到。可以通过Twitter或LinkedIn联系到我。
欺诈检测—无监督的异常检测
发现信用卡交易欺诈的 100%无人监管的方法
瑞安·波恩在 Unsplash 拍摄的照片
许多企业主最关心的问题之一是如何保护他们的公司免受欺诈活动。这种担忧促使大公司保存与他们过去的欺诈行为相关的数据,然而,无论是谁实施欺诈,目的都是不被发现,那么这种数据通常是未标记的或部分标记的。
在本文中,我们将讨论如何在信用卡交易数据集上发现欺诈,与大多数欺诈数据集不同,该数据集是完全标记的,但是,我们不会使用标签来发现欺诈。信用卡欺诈是指有人使用他人的信用卡或账户信息进行未经授权的购买或通过预付现金获取资金。信用卡诈骗不仅仅发生在网上;这也发生在实体店中。作为企业主,您可以通过识别支付环境中潜在的信用卡欺诈来避免严重的问题和不必要的宣传。
发现欺诈交易最常见的方法之一是随机选择一些交易,并要求审计员对其进行审计。这种方法非常不准确,因为欺诈交易的数量与正常交易的数量之间的关系接近 0.1%。
然后,我们的目标是利用机器学习来检测和防止欺诈,并使反欺诈者更加高效和有效。通常,有监督和非监督方法:
此外,还可以部署这些模型来自动识别未来已知欺诈模式/类型的新实例/案例。理想情况下,这种类型的机器学习算法的验证有时需要时间验证,因为欺诈模式会随着时间的推移而变化,但是为了简化本文,验证将被简化。
数据集
该项目使用了来自 Kaggle 的约 284000 笔信用卡交易的数据集。
标记为欺诈或真实的匿名信用卡交易
www.kaggle.com](https://www.kaggle.com/mlg-ulb/creditcardfraud)
数据集高度不平衡,正类(欺诈)占所有交易的 0.172%。它只包含作为 PCA 变换结果的数字输入变量。不幸的是,由于保密问题,原始特征和关于数据的更多背景信息没有被提供。特征 V1、V2、…、V28 是用 PCA 得到的主要成分,唯一没有用 PCA 变换的特征是“时间”和“数量”,并且没有空值(数据集页面)。
因为只有“时间”和“金额”特征很容易解释,所以我们可以使用一些可视化方法来查看这些特征对目标变量(欺诈)的影响。首先,欺诈更多发生在小额交易还是大额交易上?
检测欺诈的方法
本文提出了一种无监督的方法来检测欺诈,唯一使用标签的地方是评估算法。这个问题的最大挑战之一是目标高度不平衡,因为只有 0.17%的案件是欺诈性交易。但是表征学习方法的优点是它仍然能够处理这种不平衡性质的问题。使用 TSNE,我们可以尝试了解交易是如何相似的:
这种方法的主要思想是压缩数据,形成“潜在表示”,然后重构数据。如果样本与数据集的其余部分相似,则重构的数据将与原始数据相似甚至相等。然而,如果样本与其余样本不相似,则重构样本将不会与原始样本相似。
简而言之,我们压缩数据并重建它。如果重建的数据与原始数据不相似,我们就有欺诈行为。
主成分分析
使用主成分分析(PCA),我们设法将数据从 30 个特征压缩到 10 个特征,并计算重建分数。该分数的直方图如下:
我们可以看到,大多数样本具有较低的重构分数,然后,可能大多数欺诈具有超过 50 的重构分数。使用 TSNE,我们可以将原始数据处理与 PCA 压缩数据分布进行比较。
原始分布与 PCA 分布
现在,我们需要为重建分数设置一个阈值。通常使用领域专业知识来帮助设置这个阈值,因为它直接影响精确度和召回率的权衡。
使用重建分数的平均值和标准偏差,我们可以设置合理的阈值。然后,我选择将阈值设置为 mean + 2std。*这样,我们审计了 0.74%的交易,发现了 87%的欺诈行为。
自动编码器
自动编码器是一种人工神经网络,用于以无监督的方式学习有效的数据编码。它由负责压缩数据的编码部分和重建数据的解码器组成。
自动编码器的目的是学习一组数据的表示(编码),通常是为了降维。与 PCA 方法类似,重建得分直方图如下所示:
我们可以看到,大多数样本的重构分数较低,而大多数欺诈的重构分数可能超过 60。使用 TSNE,我们可以将原始数据处理与自动编码器压缩数据分布进行比较。
原始发行版与自动编码器发行版
自动编码器表示似乎很好地将欺诈从正常数据中分离出来。现在,我们需要为重建分数设置一个阈值。通常使用领域专业知识来帮助设置这个阈值,因为它直接影响精确度和召回率的权衡。
使用重建分数的平均值和标准偏差,我们可以设置合理的阈值。然后,我选择将阈值设置为 mean + 2std。*通过这种方式,我们审计了 0.85%的交易,发现了 65%的欺诈行为。
结论
该方法的目标已经实现,使得用 100%无监督的方法检测欺诈成为可能。然而,有几种方法可以使这种方法更好地工作,例如:
- 调整使用的模型(PCA 和自动编码器);
- 调整重建分数的阈值;
- 探索 PCA 和 Autoencoder 是否检测到相同的欺诈。如果他们以不同的方式工作,也许值得一试;
- 用一些特征工程增加数据。
在 GitHub 上可以找到用于执行这种方法的代码以及更多的分析:
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/lmeazzini/Small-projects/blob/master/Credit_fraud.ipynb)
欺诈防范不仅仅是不平衡的数据集
大型电子商务网站的欺诈防范看起来与 Kaggle 竞争非常不同。
数据科学家在欺诈检测上花费了大量时间。数据科学博客充满了关于如何处理不平衡数据集、平衡精确度和召回率以及解释 F1 分数的文章。这些主题对于欺诈检测系统至关重要,但它们经过了充分的研究,可以说是人满为患。说真的,关于如何处理不平衡数据集的文章已经够多了。正在寻找新挑战的数据科学家应该考虑大规模欺诈防范系统面临的一些较少探索但同样重要的问题。本文将重点讨论这些系统面临的三大挑战,以及数据科学家如何提供帮助。
挑战 1:敏捷
欺诈是一个移动的目标。一旦部署了模型,欺诈者就会找到漏洞。虽然您可能认为这可以通过一个更好的模型来解决,但请记住,数据科学家面对的是复杂的组织,这一点很重要。例如,这个由 18 名成员组成的诈骗组织利用一个复杂的电子商务账户网络窃取了 2 亿美元。这些诈骗组织有时间和资源找到漏洞。这不是是否的问题,而是何时的问题。
欺诈是一个移动的目标。一旦部署了模型,欺诈者就会找到漏洞。
数据科学家不应该专注于构建完美的模型,而应该专注于尽快发现漏洞。他们应该尽快专注于建立新的模型。这是许多大型电子商务公司仍在使用陈旧的基于规则的系统,而不是更复杂的机器学习模型的原因之一 ( 查看使用 Accertify 的公司列表 ,这是一个主要基于规则的欺诈管理平台)。基于规则的模型在处理增量变化方面非常出色,而随机森林、逻辑回归或深度神经网络中的一个微小变化可能会产生与原始模型完全不同的结果。
挑战 2:更快的反馈循环
数据科学家以退款的形式了解遗漏的欺诈或漏报。也就是说,欺诈的受害者向他们的信用卡公司提交报告,声称他们的账户上有未经授权的购买。然后,信用卡公司将这种欺诈行为通知给该商家。
当数据科学家收到对他们模型的反馈时,几个月已经过去了,欺诈交易已经损失了数百万美元。
然而,像 visa 这样的支付处理商允许他们的客户有 120 天的时间来提交退款。当数据科学家收到对他们模型的反馈时,几个月已经过去了,欺诈交易已经损失了数百万美元。因此,数据科学家需要找到更具创造性的方法来更快地识别遗漏的欺诈行为。
挑战 3:更便宜的假阳性
当电子商务公司将信用卡交易归类为欺诈交易时,他们会取消该交易。如果交易是误报,那么公司就错过了合法收入,并给他们的客户带来了不便。像 Airbnb 这样的电子商务网站正在寻找方法来降低他们欺诈模型的误报成本。
误报的代价是收入损失和给客户带来不便
降低误报成本的一种方法是防止上游欺诈行为。也就是说,开发分类模型,在欺诈用户有机会完成交易之前识别他们。提前预测欺诈行为通常会降低精确度。但是,您不是取消交易,而是要求客户验证他们的帐户或重置他们的密码。因此,误报的代价不是取消交易,而是给客户带来不便。
欺诈数据科学家的下一个前沿
为了让数据科学家保护公司免受财务欺诈,他们需要做的不仅仅是建立一个模型。他们需要接受他们的模式会被打破,一旦被打破,他们需要迅速采取行动。为了让复杂的机器学习技术在防欺诈领域得到广泛应用,数据科学家需要学习如何优雅地进行渐进式改变。
[1] E Vuittpm,签证退款时限 (2016),Chargeback.com
使用 Geopandas 和 Contextily 为静态地图提供免费底图
了解如何在 Python 中添加免费底图
来源:https://github.com/darribas/contextily
context ily是 Python 中对上下文瓦片的一个包。在这个快速教程中,我将向您展示如何在 Jupyter Notebook 中使用上下文和 Geopandas 来制作一些漂亮的地图。首先,我们需要确保安装了这些包,在 anaconda 提示符下键入:
conda install -c conda-forge geopandas
conda install -c conda-forge contextily
我假设你已经安装了 matplotlib 包,如果没有,确保你先安装它。
conda install -c conda-forge matplotlib
现在,我们需要将包导入笔记本:
import geopandas as gpd
import contextily as ctx
import matplotlib.pyplot as plt
在本教程中,我将使用北达尔富尔州/苏丹的冲突点数据及其边界形状文件,该数据和本教程的完整代码可在Github找到。
# Read in the conflict points and the boundary shape files using geopandas
conf_data = gpd.read_file("NorthDarfurConf.shp")
ND_Boundary = gpd.read_file("NorthDarfurBoundary.shp")
为了快速浏览数据,您可以简单地打印地理数据帧的标题,以查看它们有哪些列。
conf_data.columns
ND_Boundary.columns
我们只需要冲突地理数据帧中的 event_type 列,它包含所记录事件的类型。显示这些数据只有一行代码:
# we specify the column that is going to be used for the symbology
conf_data.plot(column = 'event_type');
为了使它更好,需要设置一些参数,我们还将使用边界地理数据框架来显示州的边界。但是首先,我们需要定制情节的颜色(如果你已经意识到它是随机生成的)。简单地说,我们将为 even_type 列中的唯一值创建一个字典,并为每个值分配一个唯一的自定义颜色代码。
# get the uniques values in event_type column
categories = conf_data.event_type.unique()# create a list for our custom colors
c = ['m', 'k', 'g', 'r', 'y', 'c']# create a dictionary to combine both lists, categories are keys and # color codes are values
colorDict = dict(zip(categories,c))
print(colorDict)
要使用自定义颜色绘制我们的点,我们需要按照 event_type 列对 conf_data geo-dataframe 进行分组,以便每个唯一的事件类型都能从颜色字典中获得其指定的颜色。
# plot the state's boundary with black edge color only and line width of 2
ax = ND_Boundary.geometry.boundary.plot(figsize = (10,15), color = None, edgecolor = 'K', linewidth=2)# Loop through each event type group for eventType, data in conf_data.groupby('event_type'):
color = colorDict[eventType]
data.plot(ax = ax, color = color, label = eventType)
上下文地
现在我们准备探索上下文,看看我们如何使用它在我们的地图中包含一个底图。Contextily 有一个完整的供应商列表。它们都存储为字典,因此您可以在 python 中轻松地浏览和切换它们:
print(ctx.providers.keys())
要查看每个提供者包含哪个切片,您可以使用提供者名称来打印其切片。例如,让我们看看开放街道地图提供商有哪些切片:
print(ctx.providers.OpenStreetMap.keys())
要将基础地图添加到前面的地图中,我们只需将一行代码添加到前面的代码中,其中我们指定:
- 轴:以确保我们一起策划一切。
- 坐标参考系统(crs):对于 crs,将使用 conf_data 或 ND_Boundary 的相同 crs(两者具有相同的 crs ),否则它将不起作用。
- 提供者:例如带有 Mapnik 磁贴的开放街道地图。
# add open street map basemap
ctx.add_basemap(ax, crs = ND_Boundary.crs, url = ctx.providers.OpenStreetMap.Mapnik)
最后,将为我们的地图添加一个图例和标题:
ax.legend(bbox_to_anchor = (0.31,1), prop={'size':10}) # set legend's position and sizeax.set(title="Conflict in North Darfur/Sudan (1997-2020)") # add a title to the mapax.set_axis_off() # remove the axis ticks
plt.tight_layout() # adjust the padding between figure edges
plt.savefig('norhtDarfur_conf_OSM_Map.png')# Save the map as an image
plt.show()
以下是一些其他提供商:
从左至右:Esri 世界影像、Esri 地形和开放地形底图。
参考文献
[## GeoPandas 0.7.0 - GeoPandas 0.7.0 文档
GeoPandas 的目标是简化 python 中地理空间数据的处理。它结合了熊猫的能力…
geopandas.org](https://geopandas.org/) [## 达里巴斯/语境地
contextily 是一个小的 Python 3 (3.6 及以上版本)包,用于从互联网上检索切片地图。它可以添加那些瓷砖…
github.com](https://github.com/darribas/contextily) [## 苏丹-冲突数据
ACLED 项目代码报告的信息类型,代理人,确切位置,日期和其他特点…
data.humdata.org](https://data.humdata.org/dataset/acled-data-for-sudan)
自然语言处理入门的免费实践教程
开始使用 NLP 并不困难
自然语言处理(NLP)是人工智能的一个子领域,近年来发展迅速。由于研究、学术和工业领域的许多人的共同努力,取得了巨大的进展。其中一些机构非常友好地公开了他们的资料,这样全世界的人都可以从中受益。这篇文章是五个这样的优秀资源的汇编,这些资源可以被证明对刚开始学习 NLP 的人或者有经验的人非常有益。这些课程由各自领域的专家创建,提供互动练习、简明理论和真实案例研究的组合。
1.dair.ai 的《自然语言处理基础》(第一章)
dair.ai 是一个致力于使人工智能研究、教育和技术民主化的社区。他们所有的项目都在 GitHub 上免费托管,他们通过聚会、时事通讯、博客和学习材料传播知识。其中一个正在进行的项目是关于自然语言处理基础的****,,这将是一个从零开始的自然语言处理原则系列。目前,只有第一章是可用的,如果你是一个绝对的初学者,这应该是一个很好的起点。这一章有 colab 版本和网络版本。本章以清晰易懂的术语介绍了以下 NLP 基础知识:
作者图片
阅读完教程后,你会对一些重要的 NLP 概念背后的动机有足够的理解。这将为先进的东西奠定基础。
2.sci kit-学习文本数据
[来源:scikit-learn 开发者](http://r The scikit-learn developers)
Scikit-learn ,一个流行的用于机器学习的 Python 库,有几个关于 处理文本数据 的动手教程。实践教程使用 20 个新闻组数据集向您介绍文本分析的一些基本方面:大约 20,000 个新闻组文档的集合,平均分布在 20 个不同的新闻组中。在本教程结束时,您将对 NLP 的以下方面有一个大致的了解:
作者图片
本教程后面还有一些练习来进一步练习和巩固概念。
3.Elena (Lena) Voita 的 NLP 课程
来源:https://lena-voita.github.io/nlp_course.html
莉娜是爱丁堡大学的博士生。她最近发布了一个名为 NLP 课程|给你 的 NLP 课程。这是她从 2018 年秋季开始在 Yandex 数据分析学院(YSDA) 教授的(ML for) 自然语言处理课程的延伸。这门课程在很多方面都很独特:
- 首先,它是免费和公开的。
- 其次,本课程设计方便、清晰,并且对学习者友好。这使得它不同于我过去遇到的许多其他 NLP 课程。事实上,埃琳娜如此关注课程的个性化是非常值得称赞的。用她的话说:
我想制作这些材料,这样你(是的,你!)可以自己学习,学自己喜欢的东西,按自己的速度学习。我的主要目的是帮助你进入你自己的非常个人化的冒险。送给你。****
本课程目前涵盖以下模块:
- 单词嵌入
- 文本分类
- 语言建模
- Seq2seq 和注意
每个模块都是精心策划的内容的组合,包括交互部分、练习、相关研究论文的链接,甚至一些 NLP 游戏。该课程正在积极开发一个关于迁移学习的模块,预计将于 11 月添加。甚至还有关于卷积网络的补充部分。
4.带空间的高级 NLP
来源:https://course.spacy.io/en/
spaCy 是一个用于工业级自然语言处理的现代 Python 库。 高级 NLP with spaCy 是由 spaCy 的核心开发者之一 Ines Montani 打造的免费互动课程。在这个免费的互动在线课程中;您将学习如何使用 spaCy 构建高级自然语言理解系统,同时使用基于规则和机器学习的方法。本课程包括四个章节,这些章节又进一步细分为几个小的互动模块:
本课程结束时,您将有足够的经验使用 spacy 在 NLP 中构建自己的小项目。
5.Fastai 的自然语言处理的代码优先介绍
自然语言处理 代码优先入门是 Rachel Thomas 教授的课程,遵循 fast.ai 自上而下的教学方法。以下是该课程官方博客文章的节选:
该课程教授传统的自然语言处理主题(包括正则表达式、奇异值分解、朴素贝叶斯、记号化)和最新的神经网络方法(包括 RNNs、seq2seq、注意力和变压器架构),以及解决紧迫的伦理问题,如偏见和虚假信息。
本课程配备了 Jupyter 笔记本和相关视频,涉及 NLP 的一些重要方面,如:
结论
在这篇文章中,我们看了五种不同的 NLP 资源,它们对初学者或有语言处理经验的人都有好处。这不是一个详尽的列表,还有其他一些我可能遗漏了的众所周知的资料。然而,我亲自浏览了所有上述资源,因此可以毫无疑问地推荐它们。你可以选择所有的课程,也可以选择其中的一些。无论你走哪条路,确保你练习你的技能,因为仅仅有理论知识不会让你在这个行业走得更远。
自动驾驶汽车人工智能应用的免费激光雷达数据集
Scale AI 发布了一个新的开源数据集,用于学术和商业用途,并加速了自动驾驶研究的发展。
数据标注,也称为数据标注/标注/分类,是用标签标注(即标注)数据集的过程。这个过程的质量对于受监督的机器学习算法来说是至关重要的,这些算法在试图通过识别未标记数据集中的相同模式来预测标签之前,从标记的数据中学习模式。
半自动图像标记的数据标记引导流程示例。图片来源: segments.ai
对于自动驾驶汽车应用程序,我们通常会避免明确地对机器学习算法进行编程,以如何做出决策,而是向深度学习(DL)模型提供带标签的数据进行学习。事实上,DL 模型可以随着更多的数据变得更好,似乎没有限制。然而,要得到一个功能良好的模型,仅仅有大量的数据是不够的,还需要高质量的数据标注。
有鉴于此, Scale AI 旨在为自动驾驶汽车、地图绘制、AR/VR 和机器人等人工智能应用提供训练数据。Scale 首席执行官兼联合创始人亚历山大·巴甫洛夫·王在最近的一次采访中告诉 TechCrunch :“机器学习绝对是一种垃圾进,垃圾出的框架——你真的需要高质量的数据来支持这些算法。这就是我们建立规模的原因,也是我们今天使用该数据集以开源视角帮助推动行业发展的原因。”
车道和边界检测应用的注释点云示例。图片来源:比例人工智能
本周,该公司与激光雷达制造商何塞合作,发布了一个名为 PandaSet 的新数据集,可用于训练机器学习模型,例如应用于自动驾驶挑战。该数据集是免费的,并授权用于学术和商业用途,包括使用何塞的前向(固态)PandarGT 激光雷达和名为 Pandar64 的机械旋转激光雷达收集的数据。
该车安装有广角相机、长焦距相机、1 台机械旋转激光雷达(Pandar64)和 1 台固态激光雷达(PandarGT)。图像演职员表: 比例人工智能
这些数据是在旧金山和硅谷的市区行驶时收集的,之后官员们在该地区发布了呆在家里的新冠肺炎命令(据该公司称)。
数据集功能:
- 48,000 张相机图像
- 16000 次激光雷达扫描
- +100 个 8 的场景
- 28 个注释类
- 37 个语义分割标签
- 完整的传感器套件:1 台机械激光雷达、1 台固态激光雷达、6 台摄像机、机载 GPS/IMU
它可以在这个链接免费下载。
PandaSet 包括 28 个对象类的 3D 边界框和一组丰富的与活动、可见性、位置、姿势相关的类属性。该数据集还包括具有 37 个语义标签的点云分割,包括烟雾、汽车尾气、植被和充满汽车、自行车、交通灯和行人的复杂城市环境中的可驾驶表面。
开源数据集的一些形态。图像演职员表: 比例 AI
虽然存在其他优秀开源自动驾驶汽车数据集,但这是一种不受任何限制地许可数据集的新尝试。
我收集了以下四个高质量的其他数据集,它们肯定会对您的机器学习/自动驾驶汽车项目或推动点云数据的形成和研究有用:
编队学习先进的点云处理和三维自动化。开发新的 python 地理数据技能和开源…
learngeodata.eu](https://learngeodata.eu/point-cloud-processor-formation/) [## 三维点云的未来:一个新的视角
被称为点云的离散空间数据集通常为决策应用奠定基础。但是他们能不能…
towardsdatascience.com](/the-future-of-3d-point-clouds-a-new-perspective-125b35b558b9)
开源自动驾驶汽车数据集
与 LiveData 和 MVVM 一起提供免费的冠状病毒案例 API
我们将通过 LiveData & MVVM 实现实时冠状病毒病例应用编程接口
Dương Trần Quốc 在 Unsplash 上拍照
我们将建造什么?
我们将构建一个 Android 应用程序,它将在 RecyclerView 中显示冠状病毒的真实病例。我们将遵循 MVVM 架构模式,用 Kotlin 实现 LiveData。
我们最终的应用程序将是这样的。
我们会学到什么?
- MVVM 建筑模式
- LiveData
- 使用改进的 API
为什么是 MVVM?
MVVM 是一种架构设计模式,它帮助我们实现以下目标。
- MVVM 让代码更容易理解
- 对于其他开发人员来说,代码变得更容易维护
- 这也使得项目松散耦合,意味着减少了组件(如类、活动和片段)之间的依赖性。
- 代码测试变得容易多了。
MVVM 建筑模式
MVVM 建筑
上图解释了 MVVM 架构模式。在这个图中,在体系结构的顶部存在我们的视图,用户通过这些视图与数据进行交互。
为了显示数据,我们使用 ViewModel ,因此我们的视图依赖于 ViewModel 来获取数据。使用 ViewModel 的好处是,如果活动被破坏,它不会更新数据。这意味着它减少了应用崩溃的机会。
接下来,在视图模型下面存在存储库,它进一步依赖于各种数据源。存储库可以从任何来源获取数据,它可以是远程存储库或本地存储库,这完全取决于您的逻辑。
LiveData
当谈到可观察或观察者时,这意味着我们在谈论两种不同的东西,一种你可以认为是电视,另一种你可以认为是正在观看电视的人。所以电视是可观察的,因为它被观察,而观看它的人是一个观察者。如果我们把这个概念应用到我们的数据和视图上,数据被我们的视图观察,所以数据是可观察的,而视图是观察者。现在我希望你能理解这个概念。
现在是时候来点技术了,不是吗?
[LiveData](https://developer.android.com/reference/androidx/lifecycle/LiveData)
是一个可观察的数据持有者类,这意味着扩展了LiveData
类的类负责通知处于活动状态的视图。一旦数据发生任何变化,我们的视图就会看到,即我们的视图会得到通知。
让我们考虑一个场景来更好地理解这个概念。
例如:-
让我们假设,你在任何应用程序的主屏幕上,它向你显示项目列表,但只要你单击任何项目,就会发生一些处理,这意味着后台服务正在获取数据,同时,你关闭应用程序。该应用程序对您不可见,但后台服务很快停止(因为您关闭了该应用程序),并且它仍在尝试设置视图上的数据,现在由于数据未被提取,因此您的应用程序将因NullPointerException
而在后台崩溃。那就是没有使用LiveData
的问题。
现在,我们可以从这个例子中了解到,我们获取数据的过程并不知道我们的活动、片段和服务的生命周期,这就是我们的应用程序崩溃的原因。
市场上唯一可用的解决方案是解决此类问题的LiveData
。那我们还在等什么?让我们直接进入编码部分。
项目结构
在您的项目中创建以下包
网络包:
这个包包含另外两个包,即 data 和 repos,data 包有两个类来接收从 RemoteRepository 类获取的数据。
用户界面包:
这个包还有另外两个包,它们是适配器和接口,适配器包有一个ModelListAdapter
类,这个类创建了一个冠状病毒的详细列表。
接口包包含一个返回改造对象的接口。在这个接口中,我定义了 BASEURL 和它的端点。
接下来的两类 ui 包是MainActivity
和MyViewModel
。我们的MainActivity
类包含了RecyclerView
和ProgressBar
。MyViewModel 类为我们的活动提供数据。
说够了,让我们现在开始编码…
这个项目我准备用免费的冠状病毒 api。
API 网址:【https://api.covid19api.com/summary
我将只使用国家数组。
主活动. kt
我在这个应用程序中有一个单独的屏幕,这个屏幕使用 RecyclerView 描绘了冠状病毒详细信息的列表。
ViewModelProviders
是一个类,这个类的of()
方法返回活动范围的 MyViewModel 类的对象。这是提供视图模型核心逻辑的主类。一旦我们创建了我们的 MyViewModel 类的对象,现在我们可以开始使用 observer() 方法观察数据。这个观察者接受两个参数,即当前活动的上下文和观察者匿名类。匿名类是没有任何名称的唯一类,这些类减少了类的数量。java 文件,这些类用于一些特定的情况,当只有一次使用是必要的。在 Observer 匿名类中,我们设置 recyclerview 适配器来显示我们的项目列表。所以这是我们在活动中需要的唯一代码。当 observer() 发现数据中有任何更新时,它会通知适配器或任何视图。
MainActivity 的布局文件仅包含 recyclerview 和一个 progressBar,用于显示从远程存储库获取数据时的处理情况。
ModelListAdapter.kt
这是在 recyclerview 中设置项目列表的适配器类。这个类是从MainActivity
中调用的。ModelListAdapter 类使用*list_item*
布局文件,该文件有四个 textviews 来显示数据。
我们的适配器类的布局文件。
MyViewModel.kt
这是我们的 ViewModel 类, MainActivity.kt 类依赖于这个类。每当视图需要数据时,这个类就提供它。ViewModel 类只负责管理数据。这个类永远不能访问视图。这个类的callAPI()
方法访问Repository
类的对象并调用它的callAPI()
方法。然后Repository
类返回可变数据对象的对象。这个对象进一步传递给 our MainActivity
来设置数据。
翻新设备服务
是一个有fetchData()
方法的接口,这个函数返回Country
类的对象。注意,fetchData()方法是用 @GET 请求注释的,这意味着我们要发出的是一个 GET 请求。Get request 仅在仅从服务器获取数据时使用,这意味着在服务器上既不发送数据也不更新数据,除此之外,该接口还创建了 reform 类的 singleton 对象。 invoke() 函数在伴随对象内部,这意味着无论何时我们需要调用这个invoke()
方法,我们都不必创建对象。伴随对象与 Java 的静态方法相同。在 baseurl()方法中,我传递了我的 web 服务的 url。
Repository.kt
Repository 类处理网络调用。当从MyModelView
类调用这个类的 callAPI() 方法时,它很快开始执行它的异步方法enqueue()
。该方法有两个回调函数, onFailure() 和 onResponse() ,如果调用成功,则调用onResponse()
,否则调用onFailure()
。
数据类别:
Country 是我的主类,它在构造函数中接受一个 GlobalData 类的列表。这个类由我们的 API 返回。
**class** Country(**val Countries**: List<GlobalData>) {
}
这是我们从 API 得到的数据。
**data class** GlobalData(
**var Country**: String,
**var NewConfirmed**: Int,
**var TotalConfirmed**: Int,
**var NewDeaths**: Int,
**var TotalDeaths**: Int,
**var NewRecovered**: Int,
**var TotalRecovered**: Int
)
使用 LiveData 的优势
- 确保用户界面与数据状态相匹配
- 没有内存泄漏:观察器被绑定到
[Lifecycle](https://developer.android.com/reference/androidx/lifecycle/Lifecycle)
对象,当它们相关的生命周期被破坏时,它们会自行清理。 - 没有因停止的活动而崩溃:如果观察者的生命周期处于非活动状态,例如在后台堆栈中的活动,那么它不会接收任何 LiveData 事件。
- 不再手动处理生命周期: UI 组件只是观察相关数据,并不停止或恢复观察。LiveData 自动管理所有这一切,因为它在观察时知道相关的生命周期状态变化。
- 总是最新数据:如果生命周期变为非活动状态,它会在再次变为活动状态时接收最新数据。例如,一个在后台的活动在返回前台后会立即收到最新的数据。
- 适当的配置更改:如果由于配置更改(如设备轮换)而重新创建活动或片段,它会立即接收最新的可用数据。
如果你在代码的某个地方卡住了,不要担心,你可以从 这里 下载我的 Github 项目。
我希望你喜欢读这篇文章,你也可以访问我的 网站 ,在那里我会定期发布文章。
订阅 我的邮件列表,以便在您的收件箱中直接获得我的文章,并且不要忘记关注我自己在 Medium 上发表的文章The Code Monster来完善您的技术知识。
结论
我们已经看到了如何将 LiveData 用于 MVVM 和改进 API。为了详细说明 LiveData 的用例,我使用了 Live Api,这样可以帮助您轻松理解 LiveData 的概念。
新冠肺炎危机期间的免费在线数据科学课程
提供免费课程的在线平台
J. Kelly Brito 在 Unsplash 上的照片
许多教育公司希望让数据科学对每个人来说更实惠、更容易获得。由于现在对许多人来说,时间是艰难和不确定的,许多付费平台现在要么提供免费订阅,要么提供课程。
如果你现在希望提高你的数据科学技能,查看这篇文章中的资源。
在你开始学习之旅之前,请务必阅读我在如何学习和做更好的笔记上的帖子。
[## 如何记笔记:来自人工智能、神经科学、社会学家和免费应用程序的见解
帮助您更好地记笔记和思考的见解和工具
medium.com](https://medium.com/@ausius/how-to-take-notes-insights-from-ai-neuroscience-a-sociologist-and-a-free-app-34b4be63080a) [## 使用这个免费的笔记应用程序做更好的笔记,它将成为你的第二大脑
黑曜石使连接想法变得容易,帮助你更好地思考和写作
medium.com](https://medium.com/swlh/take-better-notes-with-this-free-note-taking-app-that-wants-to-be-your-second-brain-1a97909a677b) [## 2 元学习原则帮助你更有效地学习
高效获取知识和技能
medium.com](https://medium.com/@ausius/2-meta-learning-principles-to-help-you-learn-more-efficiently-44061c9951e1)
JetBrains 学院
制作 PyCharm 等 ide 的软件公司 JetBrains 通过 JetBrains Academy 提供免费课程。您将通过构建工作应用程序来学习 coe。此优惠活动免费,有效期至 2021 年 1 月 1 日。
乌达城
图片来自 Udacity 的博客
Udacity 提供为期一个月的免费高级纳米学位课程,但只针对美国或欧洲的学生,而且每位学生仅限一个纳米学位课程。他们还计划在未来几周和几个月内宣布更多的举措,所以请注意!
乌德米
Udemy 免费资源中心页面截图
Udemy 免费提供数百门课程。许多是数据科学课程,但你也可以找到关于生产力、个人发展和音乐的免费课程。
谷歌云培训
谷歌云网站截图
谷歌通过谷歌云培训在有限时间内提供独家优惠。你可以在qwikilabs、Pluralsight 或 Coursera 上学习课程(只是这三个网站中的一个,尽管 Pluralsight 和 Coursera 也在提供优惠——见下文)。
我们在 Qwiklabs、Pluralsight 和 Coursera 上提供的 Google Cloud 培训有特别折扣。要申领这些特别优惠,只需填写下表,并在 2020 年 5 月 31 日(星期日,太平洋时间晚上 11:59)之前在您首选的平台上注册培训。
Coursera
图片来自 Coursera 的博客
危机期间,Coursera 提供了许多新的免费课程(带证书)。许多甚至与危机直接相关:精神健康和福祉、公共健康和流行病学。
从今天开始,我们将为任何人、任何地方提供完全免费的课程选择,这样更容易坚持学习。虽然 Coursera 上的许多课程已经可以免费获得,无需证书,但这次促销活动使您不仅可以参加讲座和测验,还可以获得提供这些课程的免费证书。我们计划在 2020 年 5 月 31 日前提供此项优惠,更多详情请访问以下链接。
国际商用机器公司
IBM 的培训和技能博客截图
IBM 正在提供数百门免费课程,比如 IBM Cloud、Watson、Systems、Professional Skills、Finance & Operations。
包装
Packt 的免费车间访问页面截图
Packt 是一家出版公司,出版编程书籍和工作坊。他们目前正在为 web 开发、数据科学和编程提供免费的研讨会。你必须向他们注册,购买他们的工作室(想买多少就买多少),并在结账时输入促销代码(PACKTFREE)。
代码集
代码学院页面截图
Codecademy 正在提供专业版订阅。然而,只有 10,000 个奖学金可用,你需要一个有效的学校电子邮件地址。
Dataquest
图片来自 Dataquest 的助学金奖学金页面
Dataquest 为那些真正有经济需求并渴望提高数据科学技能的人提供经济援助奖学金。
谁可以申请?任何人都可以申请,但我们要求两件事:你有真正的需求,并且在 5 月 27 日之前至少完成一次 Dataquest 任务。
多元视觉
Pluralsight 页面截图
Pluralsight 提供四月份的免费订阅。他们提供各种主题的课程,从软件开发到网络安全和机器学习。
Linux 基金会培训奖学金
Linux 基础培训页面截图
Linux 基金会提供了高达 500 英镑的奖学金来发展开源社区。你将接受培训课程和认证考试。
奖金
许多教育公司都提供免费订阅(看看这个庞大的汇编,尤其是如果你在为你的孩子寻找资源的话!)由于学校关闭
国家应急图书馆(互联网档案馆)已经提供了超过 140 万册图书。
当你享受这些难以置信的学习资源时,记得保持安全和健康!
更多帖子, 订阅我的邮件列表 。
免费阅读资源|机器学习
有助于理解机器学习概念的资源
在这篇文章中,我们将通过免费阅读资源来更好地理解机器学习。这将是一个简短的帖子。我将通过提供一些基本信息向您介绍每种资源。我试图通过在线访问找到资源,这样任何地方的任何人都可以免费访问它们。这也是我喜欢编程的原因之一,有无限多的开源和免费资源。这个列表中的七本书都与机器学习有关,但每本书都会给你不同的视角。希望这些资源对您也有所帮助。
阅读一本编程书籍可能有点挑战性,但我通常不会阅读整本书,而是检查他们的索引,阅读我觉得有趣或需要在那一刻学习的部分。当然,如果你有时间,你可以读完整本书。我们开始吧!
1-Python 数据科学手册
这是对 Python 世界中最重要的数据科学工具的全面介绍。这是杰克·范德普拉斯写的一本书。Jake VanderPlas 以前是 eScience Institute 的开放软件主任和物理科学研究主任;他现在在谷歌工作。在本书中,您还可以找到关于 Numpy、Pandas 和 Matplotlib 库的有用内容。
https://jakevdp.github.io/PythonDataScienceHandbook/
https://jakevdp.github.io/PythonDataScienceHandbook/
2-Python 101
另一个有用的书籍资源,由 Michael Driscoll 撰写。Michael 从 2006 年开始用 Python 编程。他是广受欢迎的 Python 博客“鼠标大战 Python”的作者。他也是 Real Python 的贡献者。
如果您刚刚开始使用 Python,这是一个很好的资源。这也是更新您 Python 知识的好读物。这本书将帮助你从头到尾学习如何用 Python 3 编程。Python 101 从 Python 的基础开始,然后转到 Python 的标准库。
https://leanpub.com/python_101
3 —机器学习和大数据
这个资源比其他资源更具学术性。可以找到机器学习和大数据的实现。这些项目大多是使用 Python、C++、Java 和 Scala 解决的。如果您有兴趣了解有关大数据的更多信息,这将是一本不错的读物。
http://www.kareemalkaseer.com/books/ml/
【http://www.kareemalkaseer.com
4 —用于机器学习的数学
这本书更侧重于机器学习背后的数学。如果你有兴趣提高你的机器学习知识,你应该知道它是如何工作的。当你知道事情是如何运作的,你就有更多的力量去改变和尝试新事物。这本书分为两部分:
- 数学基础
- 使用数学基础的示例机器学习算法
https://MML-book . github . io
https://MML-book . github . io
5 —机器学习向往
人工智能正在改变众多行业。来自吴恩达的免费电子书《机器学习向往》教你如何构建机器学习项目。
这本书的重点不是教你 ML 算法,而是如何让 ML 算法工作。读完《机器学习向往》,你将能够:
- 优先考虑人工智能项目最有前途的方向
- 诊断机器学习系统中的错误
- 在复杂的设置中构建 ML,例如不匹配的训练/测试集
- 建立一个 ML 项目来比较和/或超越人类水平的表现
- 了解何时以及如何应用端到端学习、迁移学习和多任务学习。
https://www.deeplearning.ai/machine-learning-yearning/
https://www.deeplearning.ai/machine-learning-yearning/
6 —理解机器学习:从理论到算法
作者:Shai Shalev-Shwartz 和 Shai Ben-David。
这本教科书的目的是以一种有原则的方式介绍机器学习,以及它所提供的算法范例。这本书提供了机器学习的基础理论和数学推导,将这些原则转化为实际的算法。
https://www . CSE . huji . AC . il/~ shais/understanding machine learning/copy . html
https://www . CSE . huji . AC . il
7 —百页机器学习书
这本书涵盖了机器学习的大部分新趋势。安德烈写的。他是两个孩子的父亲,也是加拿大魁北克市的机器学习专家。9 年前,他获得了人工智能博士学位,在过去的 7 年里,他一直在 Gartner 领导一个机器学习开发人员团队。
这本书就像一杯奶昔,里面有你最喜欢的水果。健康简洁🙂
在一个段落中,本书涵盖的主题可以列为:监督和非监督学习,支持向量机,神经网络,集成方法,梯度下降,聚类分析和降维,自动编码器和转移学习,特征工程和超参数调整!数学,直觉,插图,都在短短一百页里!
我是贝希克·居文,我喜欢分享关于创造力、编程、动力和生活的故事。
谢谢你,
使用 Yahoo Finance API 为 Python 免费提供股票数据
在这篇文章中,我将探索通过 Python 代码与 Yahoo Finance API 集成的用途。
什么是雅虎财经 API?
雅虎财经是一个媒体平台,提供金融新闻、股票报价数据、新闻发布和财务报告。而且雅虎财经提供的所有数据都是免费的。Yahoo Finance API 是 Yahoo 提供的获取财务信息的 API。
雅虎在 2017 年弃用了他们的财务 API。所以你可以看到很多网站在谈论雅虎财经 API 的替代品。然而,python 库 yfinance 通过从 Yahoo!财务并以 DataFrame 格式返回数据。所以你仍然可以使用雅虎财经获得免费的股市数据。
雅虎财经提供了超过五年的每日 OHLC 价格数据。此外,您可以获得最近几天的分钟 OHLC 数据。
开始吧
Yahoo Finance API 提供对以下信息的访问:
- 财务摘要,如收益,资产负债表。
- 股票历史价格。
- 股票行为(包括拆分和分红)。
所有这些信息都来自雅虎财经官网。
# To install yfinance before you use it.
> pip install yfinance
速度限制
调用 Yahoo Finance API 有一些限制:
- 使用公共 API(没有身份验证),每个 IP 每小时最多只能有 2,000 个请求(或者一天最多 48,000 个请求)。
我不确定这是为了财务数据。但是请使用 time.sleep(1)来避免您的 IP 被阻止。
历史价格和图表
您必须调用Ticker
模块来访问 ticker 数据。这里有一个简单的例子来检索五天的MSFT
股票 OHLC 数据:
现在你可以得到如下结果:
您可以为 history()方法设置更多参数:
绘制历史价格
如果还没有安装,可以运行命令安装 matplotlib 和 seaborn。
pip install matplotlib
pip install seaborn
将数据导出为 CSV 格式
此外,您可以将数据导出为 CSV 格式进行分析。
该功能将设置 auto_adjust 默认值为真。如果你不想要它,你可以改变它的值。
金融基础
您可以快速查看一些财务数据,如股息和拆分。您需要更改历史记录的代码长度来获取金融基本面数据。
更新于 2020/03/21 :目前没有收益和资产负债表信息。可能需要另一个 API 来找出数据。
最后
在本文中,我们了解了从雅虎财经获得股票市场数据有多简单。你可以开始写数据背后的分析。如果你有任何问题,请在下面提问。
2020 年你应该去看看的免费虚拟数据科学会议
数据科学会议发生了怎样的变化,为什么您仍然应该参加
由于疫情会议的召开,像数据科学会议这样的大型聚会不再明智。许多组织者没有完全取消会议,而是将会议虚拟化——有些人甚至免费举办会议!对于那些已经有旅行或预算限制的人来说,这是一个很好的机会(会议可能很贵!).你仍然可以舒舒服服地坐在沙发上享受数据科学会议的诸多好处。
数据科学会议可以提供很多东西:对该领域的发展轨迹有重大想法的演讲者,深入前沿话题的会议,在该领域有应用经验的专家,网络等。这些好处中的大部分仍然可以在虚拟会议上实现。
我参加了在旧金山举行的 2019 年地层数据会议
在我分享要查看的会议列表之前,我先简要总结一下数据科学会议体验的变化。
- 缩放(或其他平台)格式。会议是指在预定的时间主持会议,并有一个现场发言人。观众可以通过聊天或语音实时提问。
- 录制并免费提供的会话。错过了你想要的疗程?不用担心,录音通常在演示结束后不久就可以免费获得!过去,会议为与会者提供了这种服务,但现在许多录音可供所有人使用。
- Slack 等消息 app 已经取代了面对面的联网。像 Slack 这样的应用程序提供了与更多观众互动的好处,并可以继续关于不同会话的对话。虽然这显然不同于面对面的交流,但它近似于曾经面对面的讨论。
免责声明——我不隶属于本文所列的任何会议,也不受其赞助。所有列出的会议之所以被选中,是因为它们对我来说很有趣,也很有用。
即将召开的会议
该列表突出显示了当前虚拟的会议。我可能会在将来更新这个列表。按日期顺序排列的清单。
Spark + AI 峰会
2020 年 6 月 22 日至 26 日
Spark + AI 峰会涵盖了与 Apache Spark 和 AI 相关的主题,为开发人员、数据科学家和高管提供了不同的赛道,他们将应用最好的数据工具并使用 AI 来构建创新产品。在虚拟会议上,您将了解到:
- Apache Spark、Delta Lake、MLflow 和考拉的下一步是什么
- 管理机器学习生命周期的最佳实践
- 大规模构建可靠数据管道的技巧
- 流行的深度学习和机器学习框架的最新发展
- 人工智能的实际、真实的用例
会议是虚拟的,对所有人开放。会议是免费的,但半天和全天的培训课程和认证课程需要付费。峰会在 5 天内举行了 200 多场会议。
“数据和 AI 需要统一。但是最好的人工智能应用程序需要大量不断更新的训练数据来建立最先进的模型。Apache Spark 是唯一一个将大规模数据处理与最先进的机器学习和人工智能算法相结合的统一分析引擎。”
[## Spark + AI 峰会|人工智能& Apache Spark 大会
对于数据团队来说,这是前所未有的重要时刻。齐心协力,我们可以解决世界上最棘手的问题,而且…
databricks.com](https://databricks.com/sparkaisummit/north-america-2020)
数据和分析:实时
2020 年 7 月 14 日至 16 日(美国),2020 年 7 月 21 日至 23 日(欧洲)
Data & Analytics: Live 是一个端到端的数字会议,它通过 keynote theatres、互动展览、虚拟会见发言者分组会议和网络区域复制了面对面的会议。该会议旨在为与会者提供从数据中提取商业价值和可行见解所需的最佳实践和见解。会议的目标是高管和精通技术的数据从业者。会议将包括直播和点播。
免费通行证仅适用于所有行业的数据/分析从业者,他们不提供任何解决方案、招聘服务、咨询或在数据社区内提供任何软件/硬件解决方案作为其核心业务。
参加这一面向数据和分析领导者的免费实时虚拟活动。在手机、台式机或平板电脑上。我们带来了最好的…
data-analytics-live.coriniumintelligence.com](https://data-analytics-live.coriniumintelligence.com/) [## 数据和分析实况-欧洲| Corinium
数据与分析:Live,Europe 是一个 100%虚拟的会议,将连接欧洲最先进的数据分析…
data-analytics-live-eu.coriniumintelligence.com](https://data-analytics-live-eu.coriniumintelligence.com/)
人工智能的未来
2020 年 7 月 28 日
人工智能的未来活动展示了“人工智能的最新创新、技术和商业模式”,并将“领先的公司、创业公司、投资者、开发者和科技巨头聚集在一起,共同探索、学习和交流。”该会议旨在通过网络机会将会员和商业及技术领导者联系起来,以支持他们的增长和商业战略,并提供与人工智能相关的最新内容。
参加会议是免费的,但空间有限。
下载活动计划书,联系人工智能、数据、商业和技术虚拟活动的初创公司、企业和投资者…
www.futureofai.com](https://www.futureofai.com/)
AI4
8 月 18 日至 20 日
AI4 是一个为期三天的会议,主要关注人工智能和机器学习在企业中的采用和应用。会议采用了“面向内容的用例方法”,并提供了“一个通用框架,用于思考人工智能对每个行业意味着什么,并提供在组织的人工智能旅程的任何阶段促进理解的内容”。商业领袖和数据从业者都会发现这个会议很有价值。
要想免费参加,你必须申请一张会议通行证。Ai4 2020 是免费参加合格的申请人谁是…
- 在拥有 250 多名员工的组织中工作
- 担任高级职位和/或技术职务
- 对会议听众没有销售兴趣(或为有销售兴趣的公司工作)
[## 人工智能大会——8 月 18 日至 20 日——数字化举行
Ai4 2020 是业界最具影响力的人工智能活动。通过聚集来自各行业、政府和企业的领导者…
ai4.io](https://ai4.io/)
具有(免费)录制会话的过去会议
英伟达的 GPU 技术大会(GTC)
英伟达 GPU 技术大会的所有内容,包括人工智能、高性能计算、加速数据科学、医疗保健、图形等广泛主题的最新突破,都可以在 GTC 点播平台上免费获得。NVIDIA 已经在计划下一届 GTC 数字盛会了!
[## 观看英伟达首席执行官黄仁勋的 GTC 2020 主题演讲
加入我们新的实时网络研讨会,与专家会议联系,并录制讨论最新人工智能的演讲…
www.nvidia.com](https://www.nvidia.com/en-us/gtc/)
全球人工智能体验
DataRobot 在本次会议上的会议承诺向与会者传授人工智能如何有意义地影响组织,以及如何解决组织的关键问题。有来自各行各业先驱的用例会议,以及关于如何在人工智能方面取得成功的实际见解。所有录制的会议都是免费的。
两天充满了无限的机会来加速你的人工智能。查看数据机器人人工智能体验的完整议程…
aiworldwide.datarobot.com](https://aiworldwide.datarobot.com/agenda)
MongoDB.live
MongoDB.live 推出了 100 多个教育讲座和一个激动人心的主题会议,并发布了大量公告。现在可以免费点播课程。这是与 MongoDB 数据库软件相关的内容的一个很好的来源。
[## MongoDB World 现在是 MongoDB.live | June 年 6 月 9 日-10 日
加入我们的 MongoDB .无论你在哪里都可以现场直播!了解前沿内容、流式主题演讲、分组会议等
www.mongodb.com](https://www.mongodb.com/world)
PyCon US 2020 Online
PyCon 2020 是“使用和开发开源 Python 编程语言的社区的最大年度聚会。”会议记录的会议涵盖了各种与 python 相关的主题,如语言特性、机器学习和数据工程。
[## PyCon US
PyCon 2020 Online 已进入最后一周。回想过去 5 周左右的时间,有一个想法贯穿其中:…
us.pycon.org](https://us.pycon.org/2020/online/)
奥赖利地层数据和人工智能超级流
约会 TBD——“更像是来了”
奥莱利已经取消了 2020 年的所有会议;但是,将继续举办实时在线活动,并提供交互式教程。此外,O'Reilly 在线学习平台包含大量与数据科学、数据工程、机器学习、编程和可视化各种主题相关的有组织的内容(包括以前活动的会议记录)。在线学习平台不是免费的,但是 O'Reilly 目前提供 10 天的免费试用。
将我们的现场活动转变为在线活动
www.oreilly.com](https://www.oreilly.com/conferences/)
借助加权产品模型,让您不再犹豫不决
公司和疯狂的数据科学家如何使用决策分析来选择事物
来源:像素 (CC0)
作为一名友好的数据科学家,同事们总是带着有趣的问题来找我寻求帮助。人们要求我创建一个模型,一个公式,一个图表,一些东西…来解决一个定量的问题。
在过去的六个月里,一个反复出现的问题出现在不同的人面前:如果你必须评估许多标准,如何在众多选择中决定最好的项目/活动/项目/公寓?
人们可能会认为我毫不犹豫地选择了一些令人惊叹的人工智能算法、深度学习分类器,甚至是带有 Bootstrap 采样的爬山集成选择。然而,正如罗伯特·勃朗宁所说,“嗯,少即是多,卢克雷西亚”。
一个加权产品模型 (WPM)是解决多准则决策分析 (MCDA)问题的一个简单而流行的技术。它基本上包括将所有属性值相乘以得到一个分数。越高越好。
例如,请看下表:
表一:项目和特点。来源:作者
第一行的 WPM 分数为:
项目 1 = 30 x 17 x 5 x 20 = 51,000
更正式的定义是:
公式一:WPM 得分。来源:作者
其中:
- i :索引
- n :特征数量
- vi :第 I 个特征的值
- wi :第 I 个特征的重量
因此,使用 WPM 提供的分数,偏好被排序如下
表二:按 WPM 评分排序的项目。来源:作者
如果每个特征的权重相同( wi = 1 )。
现实生活中的问题
称重产品模型是一项非常简单的技术。你可以使用任何编程语言,甚至是电子表格(从 Github 获取代码)。
为了展示如何用 Python 来做这件事,我们再举一个例子:
表三:待售公寓清单。来源:作者
上表对应于伊利诺伊州芝加哥市的待售公寓,数据基于一个流行的 real state 网站,并针对教育目的进行了调整。这些特征是卧室数量(张床)、浴室数量(个浴室)、总面积、业主协会费用( hoa )、停车位数量、建筑年份、公寓楼层、日照、是否有电梯、价格。************
尽管它很简单,但还是有一些陷阱。首先我会告诉你如何正确地做这件事,然后我会告诉你什么是你不应该做的。
让我们导入一些库:
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
然后,我创建了一个熊猫数据框架:
raw = pd.read_csv('apartments.csv')
WPM 只使用数字特征。所以,我把曝光和升降转换成数字:
# keep original data safe
df = raw.copy()
# now exposure to West and to East are, respectively, 0 and 1
df['exposure'] = df.apply(lambda r: 1 if r['exposure'] == 'E' else 0, axis=1)
# if an building has an elevator, it will receive 1; 0 otherwise
df['elevator'] = df.apply(lambda r: 1 if r['elevator'] == 'Yes' else 0, axis=1)
现在,表格看起来像这样:
表四:曝光量和电梯转换成数字。来源:作者
接下来,我将所有特征缩放到相同的范围:
# create a scaler with range [10, 100]
mms = MinMaxScaler(feature_range=(10, 100))
# apply scaler
df = pd.DataFrame(mms.fit_transform(df), columns=df.columns)
现在,每个值都在 10 到 100 之间。
表 V:缩放到范围[10,100]的特征。来源:作者
是时候定义权重了:
weights = {'beds' : 1.,
'baths' : 1.,
'area' : 1.,
'hoa' : -1.,
'parking' : 1.,
'year' : 1.,
'floor' : -1.,
'price' : -1.,
'exposure' : 1.,
'elevator' : 1.}
这里的想法是让消极的特征不是好处。举个例子,如果价格上涨,WPM 值就会下降。
让我们定义 WPM 函数:
def wpm(option, weights):
value = 1
for column in option.keys():
if column in weights.keys():
value *= option[column] ** weights[column]
return value
然后,我们对行应用函数:
df['wpm'] = df.apply(lambda r: wpm(r, weights), axis=1)
# merge the wpm score with the original table to a better interpretation of the results
pd.merge(raw, df['wpm'], left_index=True, right_index=True).sort_values(by='wpm', ascending=False)
表六:按 WPM 评分排序的公寓。来源:作者
WPM 评分以所有功能同等重要的方式对公寓进行了排名。然而,如果一个负担得起的 HOA 比浴室的数量更重要呢?不同的特征重要性可以通过改变它们的权重来实现:
weights = {'beds' : 1.,
'baths' : 1.,
'area' : 3.,
'hoa' : -5.,
'parking' : 5.,
'year' : 1.,
'floor' : -5.,
'price' : -3.,
'exposure' : 1.,
'elevator' : 5.}
这些权重值完全是任意的,它们通常取决于决策者的判断。此外,还可以定义不同的比例。这里我用了一个李克特量表,因为它非常简单。
车位、电梯、便宜的 HOA、低矮的楼层,现在都是必不可少的;面积和价格都很可观,其余的都不太重要。
表七:按新 WPM 评分排序的公寓。来源:作者
WPM 得分现在有了一个完全不同的尺度,但这并不重要,因为只有排名是相关的。
不要
正如我之前所说,你需要采取一些预防措施来正确使用 WPM。
首先,你必须对数据进行缩放。所有功能。永远不会。人们可能会说你不需要这样做,因为数据已经准备好了,或者 WPM 本身不需要它。不要相信他们:否则,你会弄乱权重。作为一个例子,让我们只取两个特征:床和区域,并假设权重分别等于 2 和 1:
表八:带有未缩放数据的 WPM 示例。来源:作者
如你所见,卧室的数量比总面积更重要,但后者的比例更高,破坏了重量。如果您对[10,100]范围的特征进行缩放,情况就不同了:
表九:带有缩放数据的 WPM 示例。来源:作者
第二:不要将值缩放到[0,1]范围。更喜欢比这大的值。为什么?因为以下电源属性:
公式 II:功率特性的一些例子。来源:作者
0 几乎总是 0,1 总是 1,如果应用大于 1 的幂,分数会变小。所以,选择另一个范围。
与权重相关,可以使用任何值。但是,还是要保持简单:使用整数,只有当一个特性是一种负担时才使用负数,并且小心使用零。
第三个警告有点复杂:特性应该是合理独立的。如果其中两个或两个以上有因果关系,你应该只保留一个。例如,假设您有一个名为 房产税 的特性,其计算强烈依赖于公寓的价格:
表十:公寓及其财产税。来源:作者
如果计算这两个特征之间的皮尔逊相关系数:
df[['price', 'tax']].corr()
你会发现一个完美的相关性:
XI:价格和税收之间的完美关联。来源:作者
如果添加这两个特性,就像添加两次列价格。它的权重将增加一倍,使其相关性增加两倍。换句话说,会把权重搞乱。
然而,皮尔逊相关性的高值可能是一个线索,但不能保证这两个特征是相关的。作为一个例子,让我们测试另外两个特性,电梯和停车:
df[['elevator', 'parking']].corr()
表十二:电梯与停车的完美关联。来源:作者
这两个特征是高度相关的,但是大楼里有电梯并不意味着公寓会有停车位!
因此,您需要分析这些特征来决定应该丢弃哪些特征。
WPM 很酷,但是…
决策分析有很多技巧,解决了很多问题。如果你有兴趣了解更多,请随意点击我放在这篇文章末尾的链接。
参考
[1] C. Tofallis,加法还是乘法?关于多标准排名和选择的指南 (2013),告知教育事务
[2] E. Triantaphyllou,B. Shu,S. Sánchez 和 T. Ray,多准则决策:一种运筹学方法 (1998),电子电气工程百科全书
2021 年,自由职业可能是从事数据科学的最佳方式
为什么我决定做自由职业者
在 Unsplash 上由 Austin Distel 拍摄的照片
虽然由于新冠肺炎的冲击,经济形势一直在转型,但英国的失业率已经上升到 4.5%,这是三年来的最高水平,它也在缓慢但肯定地蚕食数据科学市场— Edouard Harris 几个月前写了一篇非常有趣的文章,题为“过去一个月数据科学市场发生了什么”。
随着公司预算紧缩,找到最具成本效益和时间效率的方法来满足需求是非常重要的,因此我认为自由职业者正在增加,我相信你可能更适合做自由职业者(至少目前是这样),特别是作为一个试图进入这个领域而不是申请数百份工作却没有成功的人。
让我们来谈谈我相信这一点的一些原因:
真实世界的体验
图 1 :西装男形象由猎人赛于 Unsplash 上; robtowne0 在 Pixaby 上竖起大拇指毕业照;(图片由作者整理)
注意:你需要一定程度的教育才能得到一份数据科学的工作。
考虑到我们有两个有抱负的候选人,他们有相似的教育背景,但是其中一个决定从事项目并使它们开源,而另一个继续寻找教育资源来学习。谁的努力会首先引起你的注意?
希望你说的是参与项目的人。如果是这样,太好了!为什么是自由职业者?你今天问了所有正确的问题…作为一个有抱负的人,你获得了在现实世界中从事项目工作的经验,再加上客户的好评,这使你成为许多正在招聘全职数据科学家的公司非常有竞争力的雇员,如果你决定在机会出现时过渡到全职角色。
一般来说(对于有抱负和经验丰富的数据科学家来说),作为一名数据科学家,自由职业不仅会在你从事客户工作的同时增长你的数据科学技能。你还在培养一些人可能称之为“T0”的创业技能——我个人认为这是成为数据科学家的一个关键方面。
这是因为自由职业不仅让你对客户的工作负责,因为你还必须负责自己的个人营销、个人财务管理和客户服务。实际上,你已经变成了一个企业——我们已经在以前的帖子中讨论了数据科学的各种“创业”方面。
每个数据科学家都必须做的项目
towardsdatascience.com](/the-most-important-data-science-project-458d016ef8a6) [## 品牌在数据科学中的重要性
最近,一个特别的话题在我和朋友的讨论中反复出现。品牌的重要性!我…
towardsdatascience.com](/the-importance-of-branding-in-data-science-467b2d2b1e7f)
我认为这非常有价值,原因有二:
- 你对经营企业有一种感觉,如果你觉得它适合你,你可能会决定继续经营自己的企业。
- 当你管理自己的事务时,你发展了对企业价值的第三感
赚取你的价值
学习新的技能和增加你的知识是在这个领域长期存在的必要条件。然而,一次又一次,公司因支付给数据科学家的报酬过低而闻名,因为他们做的事情超出了他们的预期。
除此之外,在一家公司工作时,如果没有某种形式的妥协,你就不太可能因为学习新技能或提高原有技能而获得加薪。例如,为了弥补你将会赚到的几个额外先令,你可能会被安排一些无关紧要的任务,或者你可能不得不增加工作时间,这样你就没那么多时间来花这些额外的钱了。
“学得越多,赚得越多”
另一方面,作为一名自由职业者,你有能力与客户协商你的收入。如果你已经学会了如何将机器学习模型部署到云上,这反过来应该会产生 5%的报酬,你有权与你的客户谈判。本质上,随着你发展和提高你的技能,你的收入潜力就在你手中,你可以决定自己的价值。
灵活性
我觉得,对于在家工作是否会持续下去,世界上的意见分歧很大,但就目前情况来看,我们大多数人都在家里工作。
虽然在办公室工作 8 小时是可行的,但我个人认为许多人可能会同意我的观点,即在家工作是无益的,因为随着越来越多的干扰进入我们的环境,我们的生产力会下降。
当自由职业者时,这不是一个大问题,因为一个主要原因…你可以决定工作多长时间,这意味着你可以花一些时间专注于深度工作,以完成你为一天留出的任务。
包裹
现在,有一些显而易见的原因可以解释为什么自由职业可能不像一个公司的永久工作那样合适:
- 提交新作品的提案本身几乎就是一项工作
- 工作和现金流不一致
- 没有带薪休假
在疫情之前,我最初从未想过做自由职业者,但随着全球经济持续紧张,我开始认为,对于那些认为自己可以独立工作的人来说,这可能不是一个坏选择。
因此,如果你认为自己有能力被一家公司聘用,但由于一些你无法控制的原因,你无法获得一份工作,那么在缓冲期间从事自由职业是个不错的主意。同样,如果你想在毕业后(或学习期间)获得实践经验,那么自由职业是一个不错的选择。
对于已经接受自由职业的弊端并接受经济现状的数据科学家来说,自由职业数据科学是一个非常赚钱的职业,这可能是 2021 年的发展方向,尤其是在经济面临更大压力的情况下。
另一个你可能会感兴趣的帖子是“你不需要工作来获得数据科学经验”
把硬币翻转过来
towardsdatascience.com](/you-dont-need-a-job-to-get-data-science-experience-26af4fd4c200)
你觉得这个帖子怎么样?留下回复或者让我们在 LinkedIn 上进行对话…
[## Kurtis Pykes -数据科学家-自由职业者,自由职业者| LinkedIn
在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有 3 个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)
对博客感兴趣?订阅我的 youtube 频道获取最新内容(本周日第一篇帖子)!
欣赏您喜爱的视频和音乐,上传原创内容,并在上与朋友、家人和全世界分享这些内容…
www.youtube.com](https://www.youtube.com/channel/UCu6zdBQhvEY5_j-ifHWljYw?view_as=subscriber)
FreeLB:一种通用的文本对抗训练方法
一种改进文本和自然语言处理对抗训练的新的通用技术。
图片由来自 Pixabay 的 Gerd Altmann 提供
2013 年,Szegedy 等人发表了“神经网络的有趣性质”。这篇论文的一大要点是,模型可能会被的反面例子所愚弄。这些例子包含了某种人类肉眼无法察觉的扰动,但却可以完全欺骗模型。本文还发现,对立的例子可以在不同数据上训练的模型中推广,也就是说,所有这些模型都被一个具有同样难以察觉的扰动的例子所愚弄。
计算机视觉领域中的一个对立的例子(来自 Goodfellow 的《解释和利用对立的例子》,参见下面的参考资料)
Goodfellow 等人在 2014 年发表了“解释和利用对抗性例子”作为这项工作的后续,以进一步分析为什么对抗性例子如此普遍以及如何生成它们。这产生了对抗性训练的概念,其中除了训练数据集之外,还使用生成的对抗性样本来训练模型,以使模型更加健壮和可推广。这里有一个警告:健壮性和可推广性在某些领域(计算机视觉)是不一致的,而在其他领域(NLP)则是互补的。因此,对抗性训练有助于模型变得更加健壮,并可能更具普遍性。
自从 Goodfellow 的论文以来,对抗性训练技术继续变得更加优雅和有效,从而使模型对恶意示例更加健壮。这项来自微软 Dynamics 365 AI Research 的新工作提出了一种新的针对 NLP 域的对抗训练算法 FreeLB (Free Large Batch ),该算法通过向单词嵌入添加对抗扰动并最小化输入样本周围不同区域内的结果对抗风险,来促进嵌入空间中更高的鲁棒性和不变性。这不同于先前的工作,先前的工作通过添加随机的单词/句子,通过拼错单词,或者通过将文本输入解释成完全不同的句子结构,向文本输入即添加对抗性扰动。通过在嵌入级别添加扰动,这种方法可以引入一些示例,如果我们只是简单地修改输入文本,这些示例是不可能生成的。
FreeLB 利用“免费”培训策略(Shafahi 等人,2019;张等(2019)用多样化的对立样本来扩大每个训练批次的大小,而不需要比当前最先进的算法投影梯度下降(PGD)额外的成本。具体来说,PGD 试图找到一组参数来最小化标准球内任何 r 的最大风险,如下所示:
其中 D 为数据分布, y 为标签, L 为某损失函数。与 PGD 在最后一步只使用 X+r 输出的梯度相比,FreeLB 每次迭代都取 r 输出的梯度的平均值,相当于把输入看成是 K 倍大的虚拟批次,【 X+r1,X+r2,…,X+rk】。具体公式是:
该团队在几个下游任务中使用这种 FreeLB 技术微调了 BERT 和 RoBERTa 语言模型。在 GLUE 基准测试中,BERT 测试分数从 78.3 增加到 79.4,而 RoBERTA-large 模型的分数增加了 0.3,达到 88.8。经过微调的 RoBERTa-large 还能够在 ARC-Easy (85.44%)和 ARC-Challenge (67.75%)基准测试中实现一流的性能。最后,在 CommonsenseQA 基准测试上的实验表明,FreeLB 可以被推广,并提高 RoBERTa-large 模型在其他任务上的性能。
如果你想了解更多关于 FreeLB 如何工作的细节,这里有一个链接链接到 FreeLB 的文章,点击这里查看更多的出版物和团队的其他工作。
参考文献
- 克里斯蒂安·塞格迪,沃伊切赫·扎伦巴,伊利亚·苏茨科夫,琼·布鲁纳,杜米特鲁尔汉,伊恩·古德菲勒,罗布·弗格斯,神经网络的耐人寻味的性质 (2013),arXiv 预印本,arXiv:1312.61999
- 伊恩·j·古德菲勒、黄邦贤·史伦斯、克里斯蒂安·塞格迪、解释和利用反面例子 (2014),国际学习表征会议,ICLR,2015
- 亚历山大·马德里,亚历山大·马克洛夫,路德维希·施密特,迪米特里斯·齐普拉斯,阿德里安·弗拉多,走向抗对抗性攻击的深度学习模型 (2017),arXiv 预印本 arXiv:1706.06083
- A.Shafahi,M. Najibi,A. Ghiasi,Z. Xu,J. Dickerson,C. Studer,L. Davis,G. Taylor,T. Goldstein,对抗性训练免费!,神经信息处理系统,NeurIPS 2019
- 张定淮,张天元,陆,朱占兴,董斌,你只传播一次:最大原理无痛对抗训练,神经信息处理系统,NeurIPS 2019
- 、于成、哲干、孙思齐、汤姆·戈尔茨坦、刘晶晶、 FreeLB:语言理解的强化对抗训练(2019) ,学习表征国际会议,ICLR 2020
谁做的薯条客观上是最好的?
薯条:数据科学的最后前沿
二月份,我们的数据科学团队就我们去哪家餐厅做的炸薯条最好的问题展开了争论。
我们决定在整个二月/三月举办一场比赛,看看谁才是真正的薯条之王。挪过去三月狂,你好淀粉狂
淀粉疯狂:比三月疯狂少得多的运动比赛(但更美味)——由艾美奖·史密斯在 Unsplash 拍摄
我把我们的发现打成了第一篇关于薯条的学术论文,并提交给了 arXiv。
它立即遭到拒绝。😦
然而,这里有一个关于客观上最好的薯条的故事,或者如我所称:
对圣莫尼卡市区薯条主观质量的客观分析
警告:这篇文章很可能会让你对薯条产生饥饿感
摘要
这一切 都是从一次团队午餐开始的。我们总是点薯条。几次午餐后,我们开始问这个问题:我们圣莫尼卡办公室附近最好吃的薯条是什么?你怎么确定“最好”呢?作为一家数据科学公司,我们知道这不能简单地通过在各种餐馆吃薯条来确定,我们必须围绕科学的严谨性和特定的限制来构建我们的分析,这样我们才能对我们的发现充满信心…如果结果不能通过同行评审来重现,那还有什么意义呢?因此,淀粉疯狂诞生了; 一场比赛,一群数据书呆子客观地评选出圣塔莫尼卡哪家餐馆的炸薯条是主观上最好的。
介绍
1802 年,托马斯·杰斐逊在白宫的一次晚宴上提供了“法式土豆”。从那里,薯条诞生了。土豆被切成片并油炸成了美国菜肴中的一种主食。
尽管与汉堡和快餐联系最紧密,但大多数餐馆都供应炸薯条。由于它们无处不在,人们肯定会问这样一个问题:“谁的薯条最好吃?”食物配方的简单性使得这个问题特别有趣,因为厨师只有几个变量可以用来制作他们理想的炸薯条。
作为一个加州人,In-n-Out 薯条在我心中占有特殊的位置。
此外,一些机构每天生产大量的薯条——这种大量生产会降低薯条的质量吗?他们必须将很大一部分业务集中在生产美味的薯条上,这一事实是否比以高端菜肴闻名的餐厅质量更好?
我们想借此机会谈谈房间里的研究大象——如果这项研究首先是重要的话。事实上,我们建议:
是的。
无论规模大小,对知识的追求都是令人钦佩的,而且还没有对圣莫尼卡市中心地区的炸薯条质量进行过任何研究。我们可能还没有几百万美元的炸薯条基金供我们支配,但是我们有毅力和动力(和调色板)来完成这个项目。我们很高兴能给人类资料库增加一点新知识。
1。方法
1.1 位置
我们必须首先选择将要参加比赛的薯条。最简单的抽样方法是选择离我们办公室不到 10 分钟步行路程的地方可以买到的薯条。幸运的是,我们的办公室位于圣莫尼卡市中心,那里不缺油炸食品;事实上有太多了。为了缩小搜索范围,我们只需在 Yelp 上输入“最好的炸薯条”,然后选择前 12 个结果。由于 fry 风格(见第 1.2 节),有几个位置最终被替换,但这种方法产生了一批强有力的竞争者。
为了避免评委根据薯条的产地产生偏见,每个地点都被随机分配了一个基于流行电视节目的虚假身份。图 1 是将真实的餐馆映射到其虚假身份的关键。从今以后,所有的餐馆都将使用虚假的名字。
图 1:为了消除位置偏见,给每个参赛者的虚假身份表
1.2 样式&采购
薯条有很多种,不幸的是,比较不同风格的薯条就像比较苹果和橘子一样,因此我们必须标准化我们的薯条类型。我们选定了最常见的样式——咸马铃薯薯条。这排除了像华夫饼干薯条和甘薯薯条等流行的变体,但仍然允许参与者之间的创造性和多样性。
我们通过只评判经典的马铃薯薯条,将风格偏好/偏见保持在最低限度——照片由艾美奖·史密斯在 Unsplash 上拍摄
一次判断一批薯条不是一个可行的选择,因为这将需要四倍于当前实验分配的时间,并使锦标赛(1.3.2)不可能进行。时间的增加将不可避免地导致法官的疲劳。相反,我们试图在不降低每批薯条完整性的情况下,一次收集每轮所需数量的薯条。
尽管我们尽最大努力尽可能接近同时获得鱼苗批次,但我们的检索并非没有缺陷,有些人可能会认为一批鱼苗经过的距离与该批次的分数成反比。我们在 3.2 节的讨论中详尽地回顾了这个猜想。
负责拿薯条的人被指示点薯条时说:“我可以点一份薯条吗?”餐馆根据这份订单制作的任何风格都被认为是他们典型的油炸风格。
1.3 实验设计
类似于 FIFA 世界杯的比赛设计,Starch Madness 由两部分组成:小组赛(1.3.1)和锦标赛(1.3.2)。在小组赛阶段的出色表现使你有资格参加锦标赛。
图 2:小组赛分组。“经典”电影的区分是主观的(但却是正确的)
1.3.1 小组赛阶段
12 份参赛炸薯条中的每一份都被随机分成 4 组,每组 3 名参赛者,称为分组,在小组赛阶段进行评分。使用的评分是 1.4 中定义的 F.A.T 系统。裁判被指示使用 F.A.T .系统(1.4)而不是比较来自一个部门的薯条来得分。
这是一个重要的区别,因为对每个鱼苗产生一个客观的分数比一个比较分数更能显示鱼苗的强度。此外,如果一个特定的部门有三个优秀的(或糟糕的)批次,他们应该被允许参加锦标赛发挥他们的实力,而不是他们的部门的整体实力。图 2 概述了这些划分。
1.3.2 锦标赛玩法
图 2:小组赛分组。“经典”电影的区分是主观的(但却是正确的)
虽然这不是比较炸薯条最科学严谨的方法,但它确实很有趣。在此阶段,前 8 个最高等级的炸薯条批次被播种并放置在单个剔除支架中。每场一对一的比赛都是由裁判盲目投票决定谁更喜欢弗莱。通过锦标赛,获胜者将被加冕。
【The F . A.T 系统
O 评判薯条的首要障碍之一是如何标准化评分。要做到这一点,人们必须回答一个深刻的哲学问题,“什么是好的薯条?”我们的薯条专家团队将薯条的质量分为三类:
风味。
外观。
质地。
这个由三部分组成的评分标准被出色地命名为“F.A.T 系统”这些都代表了一份好薯条的核心属性。通过根据这些指标对批次进行评级,我们可以满怀信心地决定哪种油炸食品是最好的。这些指标都采用 5 分制评分,1 分为最低,5 分为最高。这三个数字的平均值产生了 fry 的整体质量,并帮助裁判在锦标赛中做出重要的投票决定。
1.5 评委
薯条由能干的 RETINA.ai 团队评判,他们对薯条的热爱仅次于他们对数据收集和分析的热爱。这些法官的优点在 3.5.2 中得到很好的辩护
2.结果
A 小组赛阶段结束后,每位选手都在 F.A.T .系统中进行了评分,我们制作了以下数据表:
以绿色突出显示的人获得了足够高的 F.A.T 分数,有资格参加比赛。那些没有突出显示的低于麦当劳线,因为麦当劳不仅是合格的分数最低的薯条,而且平均分数为 2.43/5,可以被认为是一个普通的薯条。
还应该指出的是,小 Ruby 的得分绝对令人难以置信,比任何其他竞争者高出近 0.5 分,接近满分 4.44/5。另外一个有趣的结果是,小鲁比和汉堡休息室的得分高于大美式薯条,这是一种专门供应薯条的食品卡车。
麦当劳线以上的所有参赛者都进入了种子锦标赛,导致锦标赛结构如图 3 所示。使用虚假身份是因为这是评委在比赛中看到的相同支架。
图 3:锦标赛比赛等级的合格薯条
第一轮过后,洛斯·波洛斯·赫曼诺斯 & 莫斯·艾斯利如预期获胜,洛斯·波洛斯·赫曼诺斯横扫 JJ 餐厅7-0。然而,在垫底的两场比赛中,两场比赛都令人失望。Krusty Krab 以 6-1 赢得决定性胜利,而开心汉堡店在一场激烈的辩论中以 4-3 险胜。 Krusty Krab 击倒破釜酒吧,而且这样做很有效,这是非常令人惊讶的,因为如前一节所述,破釜酒吧(伟大的美国薯条)只有卖薯条——然而他们在季后赛中一场比赛都没赢。
最后的四场比赛如预期的那样进行,第一名洛斯波洛赫曼诺斯以 7 比 0 击败第四名莫斯艾斯利酒吧和第六名克鲁斯蒂克拉布击败第七名鲍勃汉堡。冠军赛是 ESPN 的经典之作。种子 6 号 Krusty Krab ,在整个锦标赛中只有 1 票反对,迎战种子 1 号 Los Pollos Hermanos ,他的小组赛分数明显高于其他任何人,比他们的冠军对手高出 1.44 分。但最终,经过激烈的辩论和评判,处于劣势的一方以 4 比 3 赢得了冠军。
嗨,Ho Burger ( Krusty Krab )被冠以淀粉疯狂的胜利者!
在一个令人惊讶的失败者的故事中,Krusty Krab (HiHo Burger)尽管是第 6 号种子,却赢得了淀粉疯狂!
3.讨论
现在我们有了每种薯条的客观分数,我们有机会从 F.A.T 分数平均值中看到某些属性对薯条质量的影响
3.1 价格是否意味着质量?
图 4:价格和鱼苗质量的关系
当看着炸薯条的价格和质量时,有一件事非常明显:比赛中最贵的炸薯条,Misfit,也被评为最差。事实上,不匹配是一个异常值,以至于将其作为数据点实际上改变了鱼苗价格和质量之间的关系,从正变到负。
在没有不匹配的情况下,价格和质量之间的相关性是适度正的(0.40 皮尔逊相关系数),而与不匹配的相关性是零到负的(-0.08 皮尔逊)。简单总结一下:
- 价格确实意味着质量,但最多只有 10 美元
- 不合时宜的(也许任何/所有高于 10 美元的薯条)是一种敲竹杠。你最好去麦当劳
说到麦当劳——最便宜的选择实际上是你能得到的最好的价格。虽然绝对质量确实会随着价格的上涨而提高,但它不会提高到每花一美元就能提高质量的程度。事实上,在麦当劳花一美元生产的油炸食品质量比旁边的餐馆高 38%。如果你在寻找最好的“性价比”,麦当劳是最好的选择。
3.2 距离是否暗示质量?
评委打分时的一个主要讨论是,离我们办公室的距离是否意味着薯条更好还是更差。这背后的原因很简单,因为薯条在新鲜和热的时候是最好的,如果我们不得不步行几分钟回到办公室,它们可能会比离我们办公室更近的一批薯条失去更多的热量。
双方都有强有力的论据。为了支持这个理论,Umami burger 是最远和最低评级的薯条之一,Little Ruby,Plan Check 和 HiHo 都进入了季后赛,并且离我们的办公室非常近。然而,最近的餐厅 Misfit 得分最低,Great American Fries 虽然很远,但质量仍然非常高。很明显,解决这个问题的唯一方法是
统计数据!
位置邻近性及其与鱼苗质量的关系。从左上顺时针移动命名的象限
我们在地图上标出了每家餐馆的位置,找到了从每家餐馆到我们办公室的欧几里得距离,并在地图上做了标记。首先,即使从数据中去除不匹配,也只有 10%的方差可以通过线性或指数关系(0.1 R2 值)来解释,因此距离降低质量的假设被拒绝。距离质量图为这些餐馆提供了一个有趣的策略。通过将数据除以麦当劳线和平均距离,我们可以创建 4 个象限/段。
象限 I 可以被标记为“容易下注”,每家餐馆都很近,而且质量很高。
象限 II 可以贴上“值得一游”的标签,因为它们距离更远,但质量仍然很高。
象限 III 可以被贴上“不值得旅行”的标签,因为它的质量低于麦当劳,距离高于平均水平。
最后象限 IV 可以被贴上“看似糟糕”的标签,因为虽然它们离办公室很近,但它们甚至不是短途旅行。象限 IV 的名称也源于这样一个事实,即我们经常去不适合的地方,因为它离我们很近,我们已经开始相信他们的薯条非常好。我们的研究表明这是不正确的,我们频繁的访问只是让我们产生了偏见
3.3 外部因素是否影响了我们的投票?
3.3.1 喜剧性的虚假身份
虚假身份被添加到餐馆中,以便人们在投票时不会基于他们之前在该餐馆的经历而产生偏见。然而,在我们试图掩盖他们的身份时,我们可能通过与虚构的餐馆来自的电影宇宙的联系引入了新的偏见。具体来说,如果一家餐厅被赋予了喜剧的身份,并且因为我们与该电影/节目的积极关联,我们给它的评分更高,会怎么样?或者反过来说,如果一家餐厅被赋予了非常严肃的电影/节目身份,并且正因为如此,评委们更加仔细地审查油炸食品,会怎么样?人们对待《沉默的羔羊》的态度会比《阿呆和阿呆》更消极吗?
答案是没有。用喜剧拆分薯条,我们得到的 t 检验 p 值为 0.52。虚假身份的喜剧价值并没有影响我们的投票。
3.3.2 天气
我们在二月和三月进行了这些实验——洛杉矶的冬天。在我们的一些回合中,气温达到了令人不寒而栗的 58 度——这影响了我们的投票吗?寒冷的天气会让热薯条味道更好,从而导致更高的 F.A.T .分数吗?还是阴天让我们变得忧郁,因此对我们吃的薯条更挑剔?
答案是否。如果天气温度在 60 度以上,我们可以通过 t 检验得出 p 值为 0.74。外面的天气没有影响我们的投票
3.3.3 星期几
在 Fryday 上评判 fries 会影响我们的投票吗?否,p 值 0.55 否定了这个假设。
3.4 Yelp 评分可以表示 F.A.T 得分吗?
elp 是一项以众包餐馆评级为荣的服务。许多人在决定是否应该去某个地方吃饭之前,通常会先查看 Yelp。在选择一个地方吃最好的炸薯条时,我们能使用同样的策略吗?人们希望随着 Yelp 总评分的增加,薯条的质量也会提高。
图 Yelp 分数和鱼苗质量的关系
不幸的是,事实并非如此。如图 8 所示,评价高的 Yelp 食用者不能生产出和他们的餐馆一样高的平均评价的薯条。即使我们剔除了不合时宜的异常值,好的 Yelp 餐厅也低于 Yelp-FAT 线,这只是简单地显示了 Yelp 分数和 F.A.T .分数之间的 1:1 关系——高于 Yelp-FAT 线(如 3.0 Yelp 分数)的餐厅生产的薯条的厚度高于 Yelp 分数所显示的厚度。我们对 4.0+餐厅未能生产 4.0+薯条的解释是,Yelp 评分不仅包括其他食物,还包括餐厅的氛围。Yelp 分数高的餐馆往往比分数低的餐馆有更好的就餐体验,尽管他们的薯条质量相同或更差。
3.5 解决潜在的混淆变量
3.5.1 季后赛排名
每个人都喜欢失败者的故事,因此,尽管在小组赛和锦标赛中弄瞎了每家餐厅,知道排名可能会迫使投票者在比赛结束时选择失败者。锦标赛的鱼苗质量比小组赛高,所以这是完全可能的。未来如何控制这一点是为了避免告诉排名,但也要在比赛中多次改变虚假身份,从而消除评委在之前的品尝中产生的任何偏见。
3.5.2 判断敏锐度
为了解决这样的担忧,即法官本身有偏见,不能代表那些没有参与研究的人的分数,这也是可能的。然而,每个法官都通过了薯条法官认证程序(图 9 ),因此他们的专业知识对于薯条质量来说是足够准确的。
图 9:所有评委收到的认证计划标志
4。结论
安京薯条是一个与所有读者相关的主题,我们希望在圣莫尼卡地区之外继续我们的研究。虽然我们的资源将我们限制在圣莫尼卡和单一淘汰,下一步可能是扩大区域和审判。我们都很感兴趣,如果这些结果适用于所有餐厅,或者如果有餐厅声称拥有最好的薯条,并希望参加挑战。
对于那些不相信圣莫尼卡炸薯条的油炸质量的研究主题值得发表的人,我们强烈主张应该永远鼓励对知识的追求,无论影响有多小或应用有多专业。
我们希望所有阅读过本书的人能够以同行评议的形式进行自己的薯条质量评估,并公布任何有趣的结果。炸薯条质量的研究领域还很年轻,已经成熟,可以发表更多的文章了。
对终极薯条的探索仍在进行中,数据科学家在未来的道路上扮演着重要的角色。
人类对完美炸薯条的追求的可视化——照片由 Matthew Kalapuch 在 Unsplash 上拍摄
希望你喜欢,
亚当·弗莱·布朗内尔
机器学习中的频繁主义者与贝叶斯方法
线性回归和贝叶斯线性回归的比较
作者照片
贝叶斯统计推断和频率主义统计推断之间一直存在争论。20 世纪,频繁主义者主导了统计实践。许多常见的机器学习算法,如线性回归和逻辑回归,都使用频率主义方法来执行统计推断。虽然贝叶斯主义者在 20 世纪之前主导了统计实践,但近年来,贝叶斯学派的许多算法,如期望最大化、贝叶斯神经网络和马尔可夫链蒙特卡罗,在机器学习中得到了普及。
在本文中,我们将在机器学习的背景下讨论它们的区别和联系。我们还将使用两种算法进行说明:线性回归和贝叶斯线性回归。
假设
为简单起见,本文中我们将使用θ来表示模型参数。
Frequentist 方法假设观测数据是从某个分布中抽样得到的。我们将这种数据分布称为似然性:P(Data|θ),其中θ被视为常数,目标是找到使似然性最大化的θ。例如,在逻辑回归中,假设数据是从伯努利分布中抽样的,而在线性回归中,假设数据是从高斯分布中抽样的。
贝叶斯方法假设数据和假设的概率(指定数据分布的参数)。在贝叶斯理论中,θ是一个变量,假设包括假设 P(θ)的先验分布和数据 P(Data|θ)的可能性。对贝叶斯推理的主要批评是先验的主观性,因为不同的先验可能得出不同的后验和结论。
参数学习
频率学家使用最大似然估计来获得参数θ的点估计。对数似然表示为:
通过最大化对数似然或最小化负对数似然(损失函数)来估计参数θ:
Bayesians 不是点估计,而是使用 Bayes 公式估计参数的完全后验分布:
您可能已经注意到,分母的计算可能是 NP 难的,因为它在θ的所有可能值上都有一个积分(或分类情况下的求和)。你可能也想知道我们是否能得到θ的点估计,就像 MLE 所做的那样。这就是最大后验概率 ( 图)估算发挥作用的地方。MAP 绕过了后验分布的繁琐计算,而是试图找到使后验分布最大化的θ的点估计。
由于对数函数是单调的,我们可以在对数空间重写上述等式,并将其分解为两部分:最大化似然性和最大化先验分布:
这个看起来不像 MLE 吗?
事实上,这两者之间的联系是 MAP 可以被视为对正则化损失函数执行 MLE,其中先验对应于正则化项。例如,如果我们假设先验分布为高斯分布,则 MAP 等于 L2 正则化的 MLE 如果我们假设先验分布是拉普拉斯分布,那么在 L1 正则化的情况下,MAP 等于 MLE。
还有一种方法可以得到后验分布的点估计:期望后验(EAP) 估计。MAP 和 EAP 的区别在于 MAP 得到的是后验分布的众数(最大值),而 EAP 得到的是后验分布的期望值。
不确定
频率主义者和贝叶斯方法之间的主要区别是他们在参数估计中测量不确定性的方式。
正如我们前面提到的,常客使用 MLE 来获得未知参数的点估计,他们不会给可能的参数值分配概率。因此,为了衡量不确定性,频率主义者依赖于零假设和置信区间。然而,需要指出的是,置信区间并不直接转化为假设的概率。例如,95%的置信区间,只意味着你生成的 95%的置信区间将覆盖真实的估计,但是说它以 95%的概率覆盖真实的估计是不正确的。
另一方面,贝叶斯在可能的参数值上有一个完整的后验分布,这允许他们通过整合完整的后验分布来获得估计的不确定性。
计算
由于在许多参数上的整合,Bayesians 通常比 frequent ists计算更密集。有一些方法通过使用共轭先验或使用采样方法或变分推理来近似后验分布来降低计算强度。
例子
在本节中,我们将了解如何使用两种算法进行训练和预测:线性回归和贝叶斯线性回归。
线性回归(频率主义者)
我们假设线性回归模型的以下形式,其中截距包含在参数θ中:
假设数据按照高斯分布分布:
使用 MLE 最大化对数似然,我们可以得到θ的点估计,如下所示:
一旦我们从训练数据中学习了参数θ,我们就可以直接使用它来对新数据进行预测:
贝叶斯线性回归(贝叶斯)
如前所述,贝叶斯方法是对先验和可能性都进行假设:
使用这些假设和贝叶斯公式,我们可以得到后验分布:
在预测时,我们使用后验分布和可能性来计算后验预测分布:
请注意,参数和预测的估计值都是全分布。当然,如果我们只需要一个点估计,我们总是可以使用 MAP 或 EAP。
结论
机器学习的主要目标是使用从训练数据中学习到的参数进行预测。我们应该使用频率主义者还是贝叶斯方法来实现目标取决于:
- 我们想要的预测类型:点估计或潜在值的概率。
- 我们是否有可以整合到建模过程中的先验知识。
顺便说一下,我们之前讨论过判别模型和生成模型。一个常见的误解是将判别模型称为频率主义模型,将生成模型称为贝叶斯模型。事实上,频率主义和贝叶斯方法都可以用于判别或生成模型。你可以参考这个帖子获得更多的澄清。
我希望你喜欢阅读这篇文章。😃
学习率常见问题
学习率问题和答案
这篇文章旨在解决我的学生经常问的关于学习速度的常见问题,也称为步长。所以,我发现以问答的形式收集它们很有用!你应该能够找到所有你想知道的关于学习率的信息。
eberhard grossgasteiger 在 Unsplash 上的照片
什么是学习率,它的目的是什么?
神经网络计算其输入的加权和,并将其传递给激活函数以获得输出。为了获得准确的预测,称为梯度下降(GD)的学习算法在从输出向输入反向移动的同时更新权重。当对训练集的每个样本进行更新时,我们称之为随机梯度下降(SGD)。
梯度下降优化器通过最小化损失函数(L)在多次迭代中估计模型权重的好值。这就是学习率的来源。它控制模型学习的速度,或者说,控制权重更新以达到 l 的最小值的速度。新(更新后)和旧(更新前)权重值之间的关系表示如下:
学习率取负值吗?
梯度∂L/∂w 是损失函数增加方向的向量。因此,-∂L/∂w 是 l 递减方向上的向量。由于η大于 0,因此是一个正值,-η∂L/∂w 在 l 递减方向上朝着它的最小值前进。如果η是一个负值,那么你正在远离最小值。它正在逆转梯度下降所做的事情,甚至使神经网络不学习。如果你考虑一个负的学习率值,你必须在上面的等式中做一个小的,但是必要的改变,这样你就可以保持最小化损失函数:
学习率的典型值有哪些?
学习率的典型值范围从 10 E-6 到 1。这里,你必须知道已经为 GD、具有动量的 GD 和 SGD 建立了,对于任何优化问题,如果学习率小于 1/L,梯度下降收敛到局部极小值,其中 L 是损失函数关于参数的 Lipschitz 光滑性。
坡度上选择不当的学习率会有什么问题?
达到最小梯度所需的步长直接影响模型的性能:
- 小的学习率消耗大量的时间来收敛,或者由于梯度消失,即梯度变为零而不能收敛。
- 较大的学习率使模型面临超过最小值的风险,因此它将无法收敛:这就是所谓的爆炸梯度。
消失(左)和爆炸(右)渐变(图像来源
因此,您的目标是调整学习率,使梯度下降优化器以最少的步骤数达到 L 的最小值。通常,您应该选择一个理想的学习速率,该速率既要足够低,以便网络收敛到有用的值而不会导致梯度消失,又要足够高,以便可以在合理的时间内对模型进行训练而不会导致梯度爆炸。
除了你对学习速率的选择,损失函数的形状,以及你对优化器的选择,决定了你能多快收敛到目标最小值。
错误选择的重量学习率有什么问题?
当我们的输入是图像时,学习率设置不当会导致噪声特征,如下图所示。恰恰相反,平滑、干净和多样的特征是良好调节的学习速率的结果。正确和不正确地设置学习率决定了你的模型的预测质量:一个良好的训练或者一个未收敛的网络。
由神经网络的第一层产生的标绘特征:不正确地(左)和正确地(右)设置学习率的情况(图像信用
能否先验地计算出最佳学习率?
对于简单的模型来说是可能的。对于复杂的问题,从理论推导中计算出能产生最准确预测的最佳学习率是不可行的。为了发现给定数据集上给定模型的最优学习率值,必须进行观察和经验。下一个问题的目的是了解你可以用来设定学习率的不同选择。
我们如何设定学习率?
通过参考我在文献中读到的内容,我区分了 4 种主要方法,你可以选择它们来调整你的模型的学习率。下面是配置η值所需了解的一切。
- 固定学习率的使用:
您为学习率设定了一个值,您将在整个学习过程中使用该值。在这里,两种方式是可能的。第一种是琐碎而简单的,不需要任何努力。它包括使用实践中常用的通常值,即 0.1 或 0.01。第二种方法更相关,因为你必须寻找适合你的特定问题和神经网络结构的正确的学习速率。如前所述,学习率的典型值范围从 10 E-6 到 1。因此,你在这个范围内粗略地搜索 10 的各种顺序,以找到你的学习速率的最佳子范围。然后,在粗搜索找到的子范围内,用小的增量来细化搜索。你在实践中可能会看到的一个启发是在训练时观察损失,以找到最佳的学习率。
- 学习率计划的使用:
与固定的学习速率不同,这种替代方案要求η值根据时间表在训练期内变化。这里,你从一个大的学习率开始,在模型的训练过程中逐渐降低学习率。这是合乎逻辑的!在学习过程的开始,权重被随机初始化,并且远未被优化,因此大的变化步长是足够的。随着学习过程接近尾声,需要更精确的权重更新。通常每隔几个历元就减少一个学习步骤。学习率也可以在固定数量的训练时期衰减,然后在剩余的时期保持恒定在一个小值。
我从阅读材料中得出的两个流行的时间表方案是在平稳状态下降低学习率和学习率衰减。在第一种方案中,对于固定数量的训练时期,每次丢失稳定期,即停滞时,学习率降低。关于第二种方案,学习率被降低,直到它达到接近 0 的小值。在这里,我区分了学习率的三种衰减方式,即阶跃衰减、指数衰减和 1/t 衰减。
- 给新币加动量:
它包括在经典 SGD 方程中增加一项:
由于 Vt-1,这个增加的项考虑了权重更新的历史,这是过去梯度的指数移动平均的累积。这平滑了 SGD 的进程,减少了它的振荡,从而加速了收敛。然而,这需要设置新的超参数γ。除了具有挑战性的学习速率η的调整之外,还必须考虑动量γ的选择。γ设置为大于 0 小于 1 的值。其常用值为 0.5、0.9、0.99。我将不详细讨论动量。这将在另一篇文章中处理。
- 自适应学习率的使用:
与上述方法不同,不需要手动调整学习速率。η由优化器调整,以根据权重的重要性执行更大或更小的更新。此外,确保了模型中每个权重的学习率。自适应梯度(Adagrad)、Adadelta、均方根传播(RMSProp)和自适应矩估计(Adam)是自适应梯度下降变体的例子。在这里,你要知道,没有单一的算法对所有问题都是最好的。
这里概述了学习率配置的主要方法。它提供了一个简明扼要的图形表示,方便您的理解!
学习率有哪些实用的经验法则?
- 学习率是你的模型所依赖的最重要的超参数。所以,如果你被迫设置一个且只有一个超参数,你必须优先考虑学习率。你可以参考我以前的一篇文章来了解另一个重要的神经网络超参数:激活函数。
激活函数:神经网络最重要的超参数之一,必须仔细选择…
- 模型学习率的调整是耗时的。因此,没有必要执行网格搜索来找到最佳学习速率。为了达到成功的模型,找到一个足够大的学习率,使得梯度下降有效地收敛,但是不要大到它永远不收敛。
- 如果你选择一种非自适应学习率设置方法,你应该意识到这个模型会有成百上千的权重,每一个都有自己的损失曲线。所以,你必须设定一个适合所有人的学习速度。此外,损失函数实际上并不具有清晰的 U 形。它们往往具有更复杂的形状,有几个局部最小值。
- 自适应方法极大地简化了适当学习率配置的挑战性任务,这使得它们更常用。此外,它通常收敛得更快,并且优于其学习速率被非自适应方法不适当地调整的模型。
- SGD with momentum、RMSProp 和 Adam 是最常用的算法,因为它们对几种神经网络体系结构和问题类型具有鲁棒性。
我希望它对新的深度学习实践者足够有用和清晰。如果这篇文章中没有提到的新问题突然出现在你的脑海中,请随时提问!也许把上面的问答做得更详尽一些会有用。
一篇关于动量的文章正在进行中。敬请期待!
简单解释了假设检验以及 I 型和 II 型错误
如何为实验选择正确的测试,并根据统计证据做出决定?
合著者:艾米特·库马尔
"事实是顽固的东西,但统计数字是易驾驭的."
― 马克·吐温
我最近在阅读 A/B 测试时偶然发现了假设测试的概念。
维基百科将假设检验定义为:
统计假设,有时也称为验证性数据分析,是一种在观察通过一组随机变量建模的过程的基础上可检验的假设。统计假设检验是一种统计推断方法。通常,比较两个统计数据集,或者将通过采样获得的数据集与来自理想化模型的合成数据集进行比较。为两个数据集之间的统计关系提出了另一个假设,并与这两个数据集之间没有关系的理想零假设进行了比较。如果根据阈值概率(显著性水平),数据集之间的关系不太可能实现零假设,则认为这种比较具有统计显著性。当确定某项研究的什么结果会导致拒绝预先指定的显著性水平的无效假设时,使用假设检验。
读这本书的人可能会认为有人这样写,所以很少有人能理解它。真正的挑战是大多数教程依赖于统计学家喜欢使用的大量术语和语言。
在这篇文章中,我将尝试用简单的方式解释假设检验以及第一类和第二类错误,而不使用太多的数学知识。
我建议提前阅读这篇文章,因为置信区间和误差幅度的概念将有助于理解假设检验。
真实世界的例子
路易斯·基冈-Skillscouter.com 在 Unsplash 上的照片
假设一家在线教育公司希望借助一项新功能来提高学生的参与度。参与度定义为观看课程的分钟数除以可用内容的总分钟数。让我们假设参与度的值在 1 到 10 之间。由于该公司不确定新功能是否会提高参与度,他们想在学生样本中进行测试。
现在,如果我们从总体中随机抽取 n 名学生的样本(具有均值 μ_p 和标准差σ_ p),中心极限定理告诉我们以下内容:
- 如果我们从替换总体中随机抽取足够多的样本,那么样本均值的分布将是近似正态的。
- 抽样分布的平均值( μ_s )可用于估计真实总体平均值, μ_p
- 抽样分布的样本标准差( σ_x) 由 σ_p/√n 给出(即总体的标准差除以样本中的观察数)。
我们现在有了总体中所有样本大小为 n=20 的样本均值分布。现在,让我们向随机抽取的 20 名学生介绍这项新功能,然后计算新的参与度。假设这 20 名学生的新平均参与度是。
我们想知道新的**、、、**在抽样分布中落在哪里?换句话说,我们想找到 z 值?
z 得分基本上是标准偏差( σ_x) 的数量,通过该数量,值 Xₑ 高于或低于平均值 μ_s 。
现在让我们问一个问题“随机选择一个大小为 20 的样本,得到一个至少为 8.94 的平均值的概率是多少?”概率将等于1-蓝色阴影区域的面积* 。我们可以使用 z 表来获取数值。我们发现 10.06 的 z 值非常大,超出了图表范围!这仅仅意味着概率很小,几乎不可能偶然得到 8.94 的平均值,或者换句话说,新功能似乎对学生的参与度有影响。*
这里我们需要定义一个阈值,如果概率低于这个阈值,我们可以安全地假设所获得的结果不太可能是偶然获得的,并且该结果是由于一些干预(在我们的例子中引入了一个新的特性)。统计学家确定了三个常规水平,称为 α 水平,也称为显著性水平。
- α = 0.05(5%)
- α = 0.01(1%)
- α= 0.001(0.1%)
如果得到特定样本均值的概率小于 α ,则不太可能发生。
这里,我们假设在引入新功能后,平均参与度会增加。在现实生活中,我们不能做出这样的假设,因为相反的情况也是可能的。为了解决这种不确定性,我们使用双尾测试,将 α 对称地分成两部分。分割 α 会导致两个不对称的 z 临界值。
注意:对于双尾检验,z-临界值与用于计算置信区间的值相同。参考本文了解更多关于置信区间的信息。
在特定的 α 水平上,我们在任一情况下都有两种可能的结果(单尾或双尾)。样本均值( 、Xₑ )要么位于临界区域之外,要么位于临界区域之内。我们将这两种结果称为零假设( 、Hₒ )或替代假设( 、Hₐ )。
零假设( 、Hₒ )假设经过某种干预后,当前人口和新人口之间没有显著差异。
当我们确定变化的方向时,我们选择单尾检验。双尾检验是一个保守的选择,因为我们可能会弄错方向。
给定一个样本均值,我们可以拒绝一个零假设(【hₒ】)或者拒绝失败。拒绝零假设( Hₒ )可以用以下方式解释:
- 我们的样本均值落在临界区域内。
- 平均值的 z 得分的绝对值大于 z 临界值的绝对值。
- 获得样本均值的概率小于 α 水平。
第一类和第二类错误
这种类型的统计分析容易出错。在上面的例子中,可能的情况是,所选的 20 名学生已经非常投入,而我们错误地认为高平均投入比是因为新功能。下图显示了可能发生的四种不同情况。
熟悉机器学习的人可能会观察到,类型 I 错误基本上是假阳性,类型 II 错误是假阴性。
https://www . Reddit . com/r/Mcat/comments/ao 6 Ovi/type _ I _ and _ type _ ii _ errors/
I 型错误(假阳性)
- 解读:你预测的是正的,是假的。
- 你预言一个男人怀孕了,但他没有。
第二类错误(假阴性)
- 解读:你预测的是负数,这是假的。
- 你预言一个女人没有怀孕,但她确实怀孕了。
我希望假设检验这个术语将不再是一个陌生的概念。虽然这篇介绍遗漏了一些技术部分,但是有很多非常好的资源,可以提供更多的细节。我总是乐于接受问题和建议。在 LinkedIn 上联系我,别忘了点击👏🏻如果你喜欢邮报。
Friendshipify:一个用于朋友的播放列表生成器
用 Spotify API 和 Flask 构建的多用户歌曲推荐器 webapp
你有没有在和朋友的长途旅行中被困在听自己不喜欢的音乐?
你的朋友问你想听什么,你说“你喜欢什么音乐就放什么。”所以他们开始演奏他们的音乐,你意识到他们喜欢的音乐是你不能忍受听的。现在你后悔没有在把音乐控制权交给他们之前说出来,公路旅行才刚刚开始。
我也遇到过几次这种情况。我和我的搭档对音乐的品味截然不同。他大多喜欢说唱,也时不时听听 ska 和朋克。我什么都喜欢一点,但是我听什么主要取决于我的心情。我们的品味在另类/独立音乐的一个非常特定的子集上重叠。在四个小时的车程中,我们轮流将歌曲添加到 Spotify 队列中,但我们仍然受困于对方的歌曲。
像这样的情况让我希望有一种方法,我们只能播放我们都喜欢的歌曲。我建立了 Friendshipify 来拯救我们,使我们不再陷入这种境地。
Friendshipify 根据两个用户的喜好交集生成一个播放列表。每个用户提供三首歌曲,应用程序将把它们作为他们的“音乐品味”,并策划一个两个用户都会喜欢的歌曲播放列表。试试这里的!
方法概述
使用 Python 编写的数据收集管道收集了大约 40,000 首歌曲。这些管道利用 Spotify API(通过 Spotify,一种 Python 包装器)来收集歌曲、元数据(如艺术家信息和流派)以及 Spotify 特有的音频功能(如可跳舞性、速度和乐器性)。使用 LibROSA 从原始音频文件中提取附加音频特征(例如,过零率、Mel 倒谱系数)。使用 Pandas 和 Numpy 构建特征向量,并存储在 PostgreSQL 数据库中。Friendshipify web 应用程序是使用 Flask 开发的,并通过 Google 云平台部署。伴随的可视化是用 Plotly 编写的。
数据收集和争论渠道;图片由 Deandra Alvear 提供
我是如何创建 Friendshipify 的
数据收集和争论渠道
Friendshipify 数据库存储了跨越 11 个流派的数千首歌曲的特征向量。当用户输入一首歌曲时,Friendshipify 会检查歌曲的特征向量是否已经存储在数据库中。如果不是,轨迹通过数据收集和特征提取管道来生成特征向量。
数据收集管道利用 Spotify API 收集歌曲及其元数据,如曲目名称、艺术家姓名和流派。使用音频特征端点检索音频特征,例如节奏、可跳舞性和能量。以下是我选择包含的 9 个 Spotify 特性的样本分发,这些特性的定义可以在 Spotify API 文档中找到。
9 个 Spotify 功能的样本分布;图片由 Deandra Alvear 提供
我本可以在这里停下来,基于 Spotify 提供的功能构建一个简单的推荐器,但我有两个顾虑:我选择的 9 个 Spotify 功能是否足以提供高质量的推荐,以及我如何能够验证我的结果。在做一些研究时,我偶然发现了几篇关于音乐信息检索的博客文章(流派分类、重要音频特征),作者使用了 LibROSA,一个用于音频分析的 Python 库,从原始音频文件中提取音频特征。
Spotify API 在歌曲对象元数据中提供了歌曲 30 秒预览的链接。我想我可以使用 LibROSA 从歌曲预览中提取潜在特征,从而扩展我的数据集中的特征。我构建了一个特征提取管道来做这件事。下面是我根据自己的研究选择提取的一些特征的样本分布。有关频谱特性(质心、带宽、滚降)的更多信息,请参见本笔记本,有关过零率的更多信息,请参见本笔记本。
4 个 LibROSA 特征的样本分布;图片由 Deandra Alvear 提供
一旦收集并处理了所有数据,我就将它们存储在 PostgreSQL 数据库中。Spotify 和 LibROSA 的组合功能将用于推荐。
创建匹配算法
决定如何配对可能是这个过程中最困难的部分。我不仅需要决定如何评估歌曲之间的相似性,还必须想出如何推荐能迎合两个用户的歌曲。虽然协同过滤方法被广泛用于构建推荐系统,但它并不是我想要解决的问题的正确方法。协同过滤试图根据评级历史找到个相似用户。在我的例子中,我想找到两个用户的歌曲之间的相似之处。
在评估歌曲之间的相似性时,我采取的第一步是尝试聚类。我认为将歌曲分类会给我不同的群体,我最终可以从中得出建议。我把所有收集到的曲目的特征向量输入到 K 均值聚类算法中。这导致了一些有趣的集群,但并没有给我一个清晰的想法,如何或为什么歌曲被集群的方式。当我听每个集群中的歌曲时,我可以听到相似之处,但我没有办法量化这些相似之处来验证结果。
最后,我决定按流派对歌曲进行分组,这是数据收集过程中包含的一个功能。使用流派作为分组标准意味着,如果用户提交一首摇滚歌曲,应用程序只会推荐其他摇滚歌曲。
Friendshipify 如何工作
一旦两个用户提交的曲目通过了数据收集和特征提取管道,该应用程序就具备了开始提出建议所需的所有标准。下图显示了这一过程。表“用户 A 的选择”和“用户 B 的选择”代表两个用户和他们提交给 Friendshipify 的歌曲。使用左侧的图例以不同的颜色表示类型。
按流派做推荐;图片由 Deandra Alvear 提供
首先,计算歌曲和数据库中属于同一流派的所有其他歌曲之间的余弦相似度。例如,用户 A 的第一首歌曲是小红莓乐队的“僵尸”。这是一首摇滚歌曲,因此 Friendshipify 计算“僵尸”的特征向量与属于摇滚流派的所有其他歌曲特征向量之间的余弦相似度。前两首最相似的歌曲(具有最高余弦相似值)成为该歌曲的推荐。在图形中,每首歌曲都有一个指向其最相似歌曲的箭头;《有些东西变了》和《美国梦》是 Friendshipify 数据库中与《僵尸》最相似的前两首歌。
用户 A 和用户 B 的余弦相似性矩阵;图片由 Deandra Alvear 提供
一旦 Friendshipify 为每个用户推荐了 6 首歌曲,它们就被用来构建一个 6×6 的余弦相似矩阵,其中用户推荐的歌曲是行索引或列索引。矩阵的单元包含每个用户之间所有可能的歌曲配对的成对余弦相似性值。例如,用户 A 的推荐“男朋友”和用户 B 的推荐“很高兴见到你”的相似度得分是 0.9798。
具有最高余弦相似值的歌曲对被用作最终推荐。上表中,《Star76》和《改变的东西》相似度最高,所以这两首歌会被纳入结果。然而,“起义”和“失乐园”具有最低的相似性得分,因此这些歌曲可能不会被包括在最终结果中,除非它们与不同的歌曲具有高的相似性得分。
测试案例
虽然 Friendshipify 总是会推荐与两个用户最相似的歌曲,但也会有一些情况很好,而另一些情况不太好。
流行与摇滚
两个朋友,唐娜和杰姬,都喜欢不同的音乐。成龙喜欢 2000 年代的流行音乐和玛丽亚·凯莉的早期音乐。唐娜更喜欢 90 年代到 21 世纪初的摇滚。成龙挑选了以下流行歌曲:
- 糟糕的爱情,嘎嘎小姐
- 幻想,玛丽亚·凯莉
- 为我哭成一条河,贾斯汀·汀布莱克
唐娜挑选了以下摇滚歌曲:
- 闻起来像青少年精神,涅槃
- 阳光下的岛屿,威泽
- 永远不会让你走,心灵蒙蔽合唱团
Friendshipify 为 Jackie 和 Donna 的播放列表推荐了这些歌曲:
- 商会,蓝尼·克罗维兹,流行
- 贝弗利山,威泽,洛克
- 半迷人的生活,心灵蒙蔽合唱团,摇滚
- 我的浪潮,声音花园乐队,摇滚
- MMMBop,汉森,流行
- 还有我,丹尼尔·梅里威瑟,爸爸
- 再见,麦迪逊啤酒,流行音乐
为了验证这些推荐的歌曲是否符合两个朋友的口味,我决定检查四个音频特征的分布,可跳舞性、能量、速度和效价。
成龙和唐娜提交歌曲的小提琴情节及其推荐;图片由 Deandra Alvear 提供
以下是来自 Spotify API 文档的这些功能的定义:
可跳舞性:根据速度、节奏稳定性、拍子力度和整体规律性的组合,一首曲目是否适合跳舞。值 0.0 最不适合跳舞,1.0 最适合跳舞。
能量:从 0.0 到 1.0 的度量,代表强度和活动的感知度量。通常,高能轨道感觉起来很快,很响,很嘈杂。例如,死亡金属具有高能量,而巴赫前奏曲在音阶上得分较低。
速度:以每分钟节拍数(BPM)为单位的轨道整体估计速度。在音乐术语中,速度是给定作品的速度或节奏,直接来源于平均节拍持续时间。
效价:从 0.0 到 1.0 的一个量度,描述一首曲目所传达的音乐积极性。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。
从小提琴的情节中,我们可以看到成龙的流行歌曲节奏较低,适度可舞,能量多样,适度积极(价)。唐娜的所有摇滚歌曲似乎都有相同的低节奏,不如杰基的流行歌曲适合跳舞,有高能量,适度积极。“推荐歌曲”的值分布在视觉上与 Jackie 和 Donna 的歌曲的分布相匹配。推荐的歌曲同样是低节奏,变价。
推荐的能量与在两个朋友的歌曲中看到的值的范围重叠。然而,小提琴的形状表明,Friendshipify 推荐像唐娜的高能歌曲的可能性更高。推荐的可跳舞性值是有趣的,因为包括了两个极值 0.88 和 0.51,尽管其余的歌曲落在 Jackie 和 Donna 的平均可跳舞性值内。Friendshipify 可以包括这些极值,以解决 Jackie 的下一首歌曲具有 0.88 的可跳舞性值的 50%概率,或者 Donna 的一首歌曲具有 0.51 的可跳舞性值的事实。
尽管在可跳舞性上存在差异,但基于绘制的特征,结果似乎是好的。我觉得这些歌曲在听觉上符合并迎合了两个朋友的口味。蓝尼·克罗维兹的《密室》听起来很流行/摇滚,所以我觉得这首歌对杰姬和唐娜都会有吸引力。“MMMBop”符合成龙和唐娜选择的时代,听起来类似于心灵蒙蔽合唱团的“永远不会让你走”和“半迷人的生活”,后者是从唐娜的歌曲中推荐的。“Good In Good Good In Good”是杰基精选推荐的歌曲,听起来与贾斯汀·汀布莱克的“泪流成河”非常相似。
摇滚对嘻哈
唐娜和杰基的朋友海德喜欢和唐娜一样的摇滚乐。他挑选了以下歌曲:
- 中间,Jimmy Eat World 组合
- 布莱特赛德先生,杀手们
- 红辣椒乐队加州
他们问他们的朋友菲斯喜欢什么样的音乐。他喜欢嘻哈,他最喜欢的两个组合是 OutKast 和 TLC。他最喜欢的德雷克歌曲是《在我的感觉里》。菲斯挑选了以下歌曲:
- 嘿,你好,奥特卡斯特
- 在我看来,德雷克
- 瀑布,TLC
以下是 Friendshipify 提出的建议:
- 一支舞,德雷克,嘻哈
- 抱紧我,动感城市原声带,摇滚
- 皇家翼,银阳皮卡,摇滚
- 家的色调,盲瓜,摇滚
- 三是个神奇的数字,瞎瓜,石头
- 后院,朋友哥打,嘻哈
- 傻逼乐队,跑酷乐队,嘻哈
海德和非斯提交歌曲的小提琴情节及其推荐;图片由 Deandra Alvear 提供
海德的摇滚歌曲中度到不适合跳舞,能量很高。这是有道理的,因为“中间”和“亮边先生”听起来又快又有活力。尽管能量很高,海德的舞蹈性和节奏分布都被加州化扭曲了,这是一首比他的另外两首歌更柔和的歌。菲斯的歌和海德的歌相比表现出截然相反的特点。菲斯的可舞性小提琴以接近 0.8 为中心,这意味着他的歌曲具有很高的可舞性。尽管可以跳舞,菲斯的歌曲的能量和节奏是可变的。奥特卡斯特的《嘿呀》很有活力,《在我的感觉里》就没那么有活力了,《瀑布》是非斯挑的最慢的。海德和菲斯的歌曲都有不同的效价,考虑到他们的选择,这是有道理的。
“推荐歌曲”的特征分布似乎偏向海德或菲斯的歌曲。推荐的可跳舞性可能被一首或两首值约为 0.9 的歌曲所扭曲。能量和速度分布都包含异常值。包含这些异常值的歌曲可以被推荐,因为海德在高能量摇滚歌曲中有一首低节奏、低能量的歌曲,而非斯在更柔和的嘻哈歌曲中包括一首高能量、高节奏的歌曲。化合价似乎是推荐抓住两个朋友口味的一个特征;推荐的歌曲表现出相同的变价可变性。
推荐给海德和菲斯的歌,似乎并不能同时迎合两人的口味。Run-D.M.C 的“Sucker m . c . s”是最接近的,因为这首歌的打击乐性质,尽管它是一首嘻哈歌曲。向菲斯推荐另一首醇厚的德雷克歌曲是有道理的,因为他包括了一首德雷克歌曲。这两首盲瓜的歌曲也很圆润,Friendshipify 可能会试图在“在我的感觉中”和“一支舞”的特点上与它们相匹配。
如果 Friendshipify 的目的是提供单独的推荐,那么这些结果会是好的,然而,摇滚和嘻哈音乐似乎差别太大,无法推荐符合两种用户口味的歌曲。然而,流派并不是 100%的一个流派或另一个。如果菲斯和海德选择了不同的歌曲,结果可能会更有凝聚力,特别是如果两个朋友选择的歌曲不是那么多变。
最后的想法
Spotify 包含 4000 多种不同的风格,有些甚至是杜撰出来的。起初,我对按流派逐步限制最初的推荐持怀疑态度。即使使用像流行和摇滚这样宽泛的流派,感觉还是会给出不连贯的最终结果。音乐的美在于它不是非黑即白的。艺术家可以将不同的声音和风格融入歌曲中。例如,一首嘻哈或说唱歌曲可能有放克、古典或 R & B 的背景旋律(见泰勒,创作者),但仍然被认为是嘻哈/说唱。通过提取每首歌曲的潜在特征,该应用程序可以识别这些微妙的模式,并推荐类似的声音歌曲。有几次,我对给出的结果感到惊喜。因此,如果一个结果“似乎是错误的”,我鼓励你听一听。
如果我有更多的时间在这个应用上工作,我会通过改变风格的处理方式来改善推荐。我不会将 Spotify 的独特子类别映射到更一般的类别(例如,afrofuturism 变成了 R&B),而是会保留独特的类别,并扩展数据集,以包含大量属于每个独特类别的歌曲。改变匹配算法的这一部分将提高推荐的质量,并且很可能减少应用程序的运行时间。我还将实现一个 Spotify 授权流,这样用户就可以直接将播放列表添加到他们的 Spotify 库中。
参考
[1] 获取音轨的音频功能 (2020) Spotify API 文档
[2] Parul Pandey ,用 Python 进行音乐流派分类 (2018),走向数据科学
[3] Joel Jogy,我是如何理解的:在训练音频文件时需要考虑哪些特性? (2019),走向数据科学
[4] Steve Tjoa,谱特征 (2017),音乐信息检索笔记
[5]史蒂夫 Tjoa,过零率 (2018),音乐信息检索笔记
[6]莫拉·约翰斯顿,Spotify 如何发现未来的流派 (2018),Spotify for Artists,News
[7] Paul Sorres,数据分析能告诉我们关于花童的什么 (2019),走向数据科学
从一个完全的新手到通过 TensorFlow 开发者证书考试
我从学习 Python 到通过 TensorFlow 开发者考试不到 5 个月的旅程。
阿迪·戈尔茨坦在 Unsplash 上的照片
我刚从土木工程学士学位毕业,准备今年秋天开始攻读交通工程硕士学位。不幸的是,因为新冠肺炎,我的计划被推迟到了冬季学期。所以到今年一月为止,我没有上学,也没有工作。
在查看我未来的研究生院正在进行的一些研究时,我遇到了机器学习和深度学习正在许多运输工程相关的研究项目中实施。当时,我对 ML、DL,甚至是整个数据科学是什么一无所知!所以,我开始研究这个课题。我和我的几个计算机和软件工程师朋友聊过,我从他们那里了解到,机器学习植根于统计学、微积分和线性代数,所有这些都是我最喜欢的数学主题。我记得我对自己说,我不能错过这个机会,我有世界上所有的时间和无限的资源(感谢互联网!).除此之外,我将进入一个被数据科学迅速改变的领域,我需要尝试一下。
我一直在与编程语言作斗争,我曾经开始学习 Java,但在开始后的 5 个小时内就放弃了。这很尴尬,因为我对开发 android 应用程序抱有很高的期望。现在想起来,我只是懒惰和不耐烦。但这次不同,我不得不学习比 Java 更容易掌握的 Python,我发现自己真的被这个新领域迷住了。
所以,让我们直接开始吧!在这篇文章中,我将带你经历我如何在不到 5 个月的时间里从一个完全的新手变成一个 Google 认证的 TensorFlow 开发者的旅程。
1.学习 Python
有很多学习 Python 的资源,既有免费教程,也有给你结业证书的付费课程。我个人选择了证书课程,因为它为我提供了一种切实的信誉形式,并让我负责任。来自非编码背景,这对我很重要。这里是一些可用的资源;
证书课程
- 这是我学 Python 上的课。我向任何没有编码背景的人推荐这本书,因为这本书涵盖了所有的基础知识,并且不断更新。最棒的是,你可以终身使用所有的材料,并获得证书证明你已经完成了全部课程。
- 这是密执安大学在 coursera.com提供的另一个精彩专业。它由 4 门不同的课程组成,涵盖广泛的主题,从写你的第一首“Hello World!”使用数据库的代码。你可以买下来领证,也可以免费审核。
链接: Python 为大家
更多课程列表此处
免费教程
- freeCodeCamp.org 的优秀员工定期在 YouTube 上发布高质量的编码教程。
- 另一个很棒的 Python 教程视频
好了,现在你已经学会了 Python 的基础,干得好,祝贺你!!
但是,不要指望自己成为专家,仅仅因为你有一个证书或者你坐了 5 个小时的视频教程。这项工作远未完成!这将是一个渐进的过程,有一些很棒的工具可以帮助你练习和提高你的编码技能。
我用了两个网站,
- Codewars.com 真是太棒了!他们已经想出了一种方法来将练习编码的过程游戏化。一定要去看看
链接:代码大战:融会贯通
- Leetcode.com 是另一个伟大的网站。他们有编码面试风格的问题,以增加难度,这是另一个练习和提高你的编码技能的好地方。
我建议定期练习和提高你的 Python 技能。记住:间隔重复有效!
2.学习机器学习理论
正如我之前提到的,机器学习植根于统计学、微积分和线性代数,因此你不需要为了理解和学习机器学习概念而能够编码。在我看来,吴恩达在 coursera.com 讲授的机器学习课程绝对是一门瑰宝。这门课很老了,使用 Matlab 而不是 Python,但是介绍和解释概念的方式非常相关,会让你做好准备。对于像我这样一个完全的新手来说,有时会非常沮丧,但我现在很感激我完成了课程,尽管当时我并没有完全理解其中的一些主题。我发现自己一直在参考课程中的材料,甚至在准备 TensorFlow 开发者考试时也是如此。
注意:这个课程甚至可以在学习 Python 之前上,但我会建议先学习 Python,这样你可以在学习机器学习概念的同时练习。
3.学习数据科学库
Python 中有一些特定的库,使得数据科学相关的任务变得更加简单和高效。其中一些库是 Pandas(数据操作和分析),Numpy(支持多维数组和矩阵),Matplotlib(绘图)和 Scikitlearn(创建 ML 模型)。网上有数不清的资源,这里是我用过的一些-
- 熊猫——我看了很多视频、教程,甚至旁听了一门证书课程。codebasics 的这个 YouTube 播放列表无疑是互联网上最好的资源之一。
- numpy——一如既往freeCodeCamp.org为胜利而战!!
- matplotlib——YouTube 上的这个播放列表很容易理解,并且很好地解释了棘手的话题。
- scikitlearn——我参加了在udemy.com开设的一门课程,这门课程几乎涵盖了所有的 ML 模型,并使用真实世界的数据集解释了它的实现。YouTube 上还有一个 3 小时的免费教程,你可以在这里找到。
4.深度学习理论
在这一点上,可以肯定地说,除了深度学习,你已经知道了成为一名成功的数据科学家所需要知道的大部分事情。DL 足够复杂,需要单独的课程甚至单独的库来实现。吴恩达在 Coursera 上开设的机器学习课程提到了神经网络和深度学习,但这比那门特定课程涵盖的内容要多得多,因此吴恩达开设了另一门课程,深入研究神经网络和深度学习。Deeplearning.ai 创建了一个由 5 门课程组成的专业,涵盖了不同的主题,如卷积神经网络、超参数调整、序列模型等。本课程着重于不同神经网络模型的理论和工作原理。我认为,完成本课程是必不可少的,尽管为了成功构建和部署深度学习模型,您并不一定需要完成本课程。然而,当您必须在 TensorFlow 中调优模型或从头创建模型时,它会让您的生活变得简单得多。
链接:深度学习专精
注意:本课程可以免费旁听。
我写了一篇文章,通过实际实现解释了深度神经网络的内部工作原理,可以在这里找到
5.张量流
TensorFlow 是一个免费的开源软件库,用于神经网络等机器学习应用。其他类似的库有 PyTorch 和 Theano,但我决定继续使用 TensorFlow,因为它应该对生产模型和可伸缩性更好,特别是因为 Keras 现在已经完全集成到 TensorFlow 中。 Deeplearning.ai 的人在 Coursera 上发布了另一个专业化,这是上面提到的深度学习课程的延续。它使用 DL 课程中教授的概念,并使用 TensorFlow 实现它们。我选择参加 TensorFlow 实践专业化认证的另一个原因是,它涵盖了 Google tensor flow 开发人员认证考试所需的所有先决条件。
链接:练张量流
我需要参加 TensorFlow 开发者考试吗?
这种特殊的证书考试是相当新的,在这个时间点上大约 5 个月,因此现在还不确定它在行业中对改善就业前景有多大价值。来自一个非编码的背景,这个考试作为一种方式来验证我在深度学习方面的技能。
这种考试需要一定程度的准备和编码能力,甚至能够尝试成功。最重要的是,它给了我一个固定的目标,并成为我完成所有课程的动力。
这里是一篇详细谈论考试的大文章。
作者图片
这些是我遵循的步骤,我打算继续学习。还有很多东西需要学习,尤其是因为数据科学是一个快速发展的领域。
从愿景到生产:第 3 部分
你建立了一个 ML 模型——这个 之后,你做什么呢?你如何把它变成可以在网上展示的东西?你如何把它变成其他人可以使用的东西,与之互动,并使之有用?
你部署一下!
大多数时候,人们在构建统计模型的阶段结束他们的项目,这可能是数据科学家的典型角色,他们通常不会最终将他们的模型作为开源软件部署到互联网上进行真实世界的测试,因为人们通常认为 前端和后端开发 会发挥作用(这也是我在这个项目开始时的想法:P)
图片来源:Pexels
显然有一些更简单的方法可以做到这一点,我将在我的博客中解释。我们使用 Heroku 和 Github 在 web 上部署我们的模型。
这篇文章我们要看什么?
1。使用你编码并从头构建的模型来制作应用。
2。如何整合谷歌模式做 app?
3。在本地机器上部署这两种方法。
5。将模型推送到 Github 并部署在 Heroku 上
为什么是烧瓶?
当我到达这个阶段时,我想先在 GitHub 页面上部署这个模型。GitHub Pages 是一个免费的静态站点托管服务,旨在托管来自 GitHub 库的项目。
当使用 web 应用程序时,我不能使用 GitHub 页面来托管它们。GitHub Pages 只适用于静态网站,而不适用于需要服务器和数据库的动态应用程序。你必须使用云服务,比如亚马逊网络服务来链接 Gitpages。所以 flask 是下一个选择,因为它使用 Python 作为服务器端语言,并且确实与模型完美集成。我了解到我可以使用名为 Flask 的框架来使用 Python 作为服务器端语言
使用您的编码 CNN:
使用 Flask 在 Herkou 上部署您的模型以供开源使用。
了解你的应用部署基础知识(如果你想看的话,可以在这里找到官方安装指南!)
建立一个虚拟环境来管理项目的依赖关系是一个好主意。为此,您可以为您的项目设置一个文件夹,然后在您的终端上运行:
mkdir myproject
cd myproject
python3 -m venv venv
我将在这里用 Python 3 做 Windows 上的作品。如果您在 Mac 上工作或运行 Python 2,您可能想看看官方文档,看看您可能需要调整什么来启动和运行。
接下来,激活您的环境并安装 flask
py -3 -m venv venv
pip install Flask
要创建一个非常小的 Flask 应用程序,首先要创建一个文件。创建文件并在文本编辑器中打开它。然后打字
**from** flask **import** Flask
app = Flask**(**__name__**)**@app.route**(**'/'**)**
**def** hello_world**():**
**return** 'Hello, there!'
上面的代码是做什么的?
首先,我们导入了 Flask 类。接下来,我们创建了该类的一个实例。第一个参数是应用程序模块的名称。如果你使用单个模块,你将使用(__name__)
以便 Flask 知道在哪里寻找东西。“route”部分告诉 Flask 哪个 URL 应该触发我们的函数。我们给这个函数一个名字,这个名字也用来为这个函数生成 URL,并返回我们希望在用户浏览器中显示的消息。
你可以把这个存成 hello.py 或者 whatever.py 或者任何让你开心的东西。只是不要存成 flask.py 因为那会和 flask 冲突。我喜欢用 app.py 作为 flask 的主文件,因为这将是 Flask 以后想要找到的文件。
如果您想运行它,请在您的终端上键入:
set FLASK_ENV=development
set FLASK_APP=app.py
我在运行flask run
之前运行这个命令。这将使您处于开发模式。这意味着,当您更改代码时,您的服务器会自动重新加载,而不是每次更改代码时都必须手动重启。当出现问题时,它还会为您提供一个非常有用的调试器!
然后运行:
flask run
如果一切正常,您会看到类似这样的内容
Running on [http://127.0.0.1:5000/](http://127.0.0.1:5000/)
现在,您可以将它复制并粘贴到浏览器中。看看有没有用!要关闭它,你可以在终端窗口输入 Control C
您可以通过更改您的 app.py 文件来轻松传递值。我的 app.py 文件是这样的:
from flask import Flask, request, render_template
app = Flask(__name__)from commons import get_model
from inference import read_image
from inference import time
from inference import test_single_image
#import os
#from werkzeug.utils import secure_filename[@app](http://twitter.com/app).route('/', methods=['GET', 'POST'])
def hello_world():
if request.method == 'GET':
return render_template('index.html', value='hi')
if request.method == 'POST':
print(request.files)
if 'file' not in request.files:
print('file not uploaded')
return
file = request.files['file']
# Save the file to ./uploads in case you want to save uploads
#basepath = os.path.dirname(__file__)
#img_path = os.path.join(basepath, 'uploads', secure_filename(file.filename))
#print(img_path)
#file.save(img_path)
bulbimage = file.read()
print(bulbimage)
bulbpreds,final = test_single_image(path=bulbimage)
test_single_image(path=bulbimage)
return render_template('index.html', bulb=bulbpreds,finalpred=final)if __name__ == '__main__':
app.run(debug=True)
假设我们有了模型。文件,将该检查点放在您的项目文件夹中。
现在我们需要写信获取图像,并将信息发送到模板。首先,您需要一个函数来获取模型并创建您的预测。创建一个 commons.py 文件,并编写一个函数来获取模型以及允许您将上传的文件转换为张量的内容。试试这个!
公共文件:
import io
import torch
from PIL import Image
from keras import layers
from keras import models
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator
from keras.preprocessing.image import img_to_array, load_img
from keras.models import load_model
import tensorflow as tfdef get_model():
global model
model = load_model('checkpoint_final.h5')
print("Loaded Model from disk")
model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
return model
确保从其他文件中导入您使用的函数,比如从 commons import get_model 导入。 该函数读入图像,转换成 NumPy 格式,并调整图像大小以传入模型。然后它调用 model.predict,后者从 commons.py 文件中获取模型。整理灯泡类并返回预测。
接下来,创建一个推论. py 文件。我们需要能够整理出灯泡的名称、类别和标签,所以您可以编写如下内容:
rom keras import layers
from keras import models
import numpy as np
from keras import optimizers
from commons import get_model
from keras.preprocessing import image
from keras.preprocessing.image import ImageDataGenerator
from keras.preprocessing.image import img_to_array, load_img
from PIL import Image
import io
#import torchvision.transforms as transforms
import cv2def read_image(file_path):
print("[INFO] loading and preprocessing image...")
#print(file_path)
bulbimage = np.array(Image.open(io.BytesIO(file_path)))
bulbimage = cv2.resize(bulbimage, dsize=(400, 400))
#print(bulbimage)
#my_transforms = transforms.Compose([transforms.Resize(400)])
#bulbimage=my_transforms(bulbimage)
#print(bulbimage)
#bulbimage= load_img(file_path, target_size=(400, 400))
#bulbimage = img_to_array(bulbimage)
bulbimage = bulbimage.astype('float')
#bulbimage= np.array(bulbimage).copy()
bulbimage = np.expand_dims(bulbimage, axis=0)
bulbimage /= 255.
print(bulbimage)
return bulbimagemodel=get_model()
import time
def test_single_image(path):
bulbs = ['A19', 'BR2040', 'MR16', 'PAR203038', 'R20', 'T5T8']
images = read_image(path)
time.sleep(.5)
preds = model.predict(images)
predictions = {
"A19":round(preds[0][0],2),
"BR2040":round(preds[0][1],2),
"MR16":round(preds[0][2],2),
"PAR203038":round(preds[0][3],2),
"R20":round(preds[0][4],2),
"T5T8":round(preds[0][5],2),}
print('Final Decision:')
time.sleep(.5)
for x in range(3):
print('.'*(x+1))
time.sleep(.2)
class_predicted = model.predict_classes(images)
#class_predicted.shape()
class_dictionary= {'A19': 0, 'BR2040': 1, 'MR16': 2, 'PAR203038': 3, 'R20': 4, 'T5T8': 5}
inv_map = {v: k for k, v in class_dictionary.items()}
result= inv_map[class_predicted[0]]
#print("ID: {}, Label: {}".format(class_predicted[0], inv_map[class_predicted[0]]))
return predictions,result
我的 index.html 看起来像:
<!DOCTYPE html>
<html>
<head>
<title>Bulb App</title>
<meta name="viewport" content="width=device-width, initial-scale=1"><style>
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
.hero-image {
background-image: linear-gradient(rgba(0, 0, 0, 0.3),rgba(0, 0, 0, 0.3)), url("/static/image.jpg");
background-color: #cccccc;
height: 800px;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
position: relative;
}
.hero-text {
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
}
input[type=file] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: block;
width: 200px;
color: white;
justify-content: center;
align-items: center;
text-align: center;
box-sizing: border-box;
border-style: solid white;
border-width: 2px;
border-radius: 2px;
}
input[type=submit] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: block;
width: 200px;
font-size: 1.5em;
color: white;
justify-content: center;
align-items: center;
text-align: center;
box-sizing: border-box;
background-color: #DC143C;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="hero-image">
<div class="hero-text">
<h1 style="font-size:50px">Bulb Classifier</h1>
<h3>Upload a picture of a bulb to see what type it is! </h3><form method ='file' enctype=multipart/form-data>
<input type="file" name="file">
<input type="submit" value="upload"><ul class="actions">
<h4>Predictions: {{ bulb }}</p>
<h5>Final Prediction:{{ finalpred }}</p>
</div>
</div>
</body>
</html> def get_model():
global model
model = load_model('checkpoint_final.h5')
print("Loaded Model from disk")
model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
return model
这是您应该拥有的文件结构。不要担心
静态文件夹包含你在背景中使用的图像。templates 文件夹包含 index.html 文件,您将需要在 Heroku 中进行部署的文件需求,可以通过
该函数读入图像,转换成 NumPy 格式,并调整图像的大小以传递到模型中。然后它调用 model.predict,后者从 commons.py 文件中获取模型。整理灯泡类并返回预测。
看起来很简单,你应该能够上传一张图片并得到一个结果!
现在,如果你想让公众可以使用它,让它对所有人开放。如果您想使用此应用程序部署到 Heroku,请跳到下一节。
使用 Auto ML 模型集成到您的 web 应用程序中
使用 AutoML 的TensorFlow.js
模型格式的过程需要两个步骤:导出模型,然后加载它进行推理。
以下分步说明将帮助您加载任何基于 TF.js 的模型,并在您本地计算机的浏览器中部署您的应用程序,我们将为代码添加一些火花,以将其用作一个应用程序,人们可以上传图像并轻松获得他们的预测。这是一个良好的开端:
[## Edge TensorFlow.js 教程|云自动视觉文档
术语:参见 AutoML Vision Edge 术语页面,了解本教程中使用的术语列表。在本教程中…
cloud.google.com](https://cloud.google.com/vision/automl/docs/tensorflow-js-tutorial)
*loadImageClassification*
函数在运行时使用**model.json.*
加载模型*
*model.json*
文件包含了所有*.bin*
模型文件的信息。
加载该文件会自动加载 TensorFlow.js 中的模型
*classify*
功能可应用于图像*DOM*
元素。也就是说你只需要替换这里的 image DOM 元素:*const image = document.getElementById('daisy');*
就可以得到图像预测。**
基于训练,classify
函数返回一个 JSON 文件,其中包含了这些类的置信度得分。
根据你训练的模型类型,输出模型。JSON 和 bin 文件应该如下所示:
templates 文件夹包含第二个文件夹中的文件,但是 model.json 文件也可以放在主文件夹中
如果您没有 git 帐户,您可以在 git 上创建一个帐户,初始化一个存储库并上传存储库中的所有文件夹。
通过键入以下内容将要求归档,您将看到下载的文本文件:
**pip freeze > requirements.txt**
我能够上传模型,将其集成到 Heroku 中,并将其部署在 Heroku 上,而无需使用任何命令行界面。但是,如果您使用的是您编码的模型,则. h5 文件很大,需要通过 CLI 推送到 Github,您需要使用 Git LFS 来推一个大于 25mb 的文件。
您可以在此浏览文档:
下载并安装 Git 命令行扩展。下载并安装后,为您的用户设置 Git LFS…
git-lfs.github.com](https://git-lfs.github.com/)
如果你想用命令行上传到 Heroku 你可以看这里:
Heroku 使用流行的版本控制系统 Git 管理应用部署。你绝对不需要成为一个饭桶…
devcenter.heroku.com](https://devcenter.heroku.com/articles/git)
您的 proc 文件应该包含代码
python -m http.server $PORT
你可以在 Heroku 上自动观看:
按如下方式配置变量:
您已经准备好部署应用程序,只需单击“部署”按钮,您就会看到一个如下所示的链接,其中包含了我们的模型:
https://bulbdetection.herokuapp.com/templates/
您的 web 应用程序已启动并运行!
图片来源:Giphy.com
整个项目可以在我的 Github repo 找到:
数据准备和模型:https://github.com/aditi310896/Bulbdetection
部署:https://github.com/aditi310896/wavelengthmodel**
从愿景到生产:第 1 部分
图片来源: NASA 开源
本系列旨在将您从计算机视觉图像分类问题的第一步带到部署阶段,并让您思考在此过程中您可能想要实现的替代方案和方法!
数据科学项目的生命周期通常从用例或想法开始,从所有可用的来源收集数据,分析数据并执行功能工程,建立一个统计模型,对未来数据进行良好的概括,然后部署到生产中。部署之后,您需要继续监视以执行度量,并使用新的可用数据重新训练模型。
在我们开始这个项目之前,这里有一些灵感和我的成果的链接,这里有一些给你们的动力:
【https://bulbdetection.herokuapp.com/templates/
作者图片
这篇文章的目的是什么?
1.从谷歌上抓取图片
2.消除重复的问题
3.建议其他更简单快捷的方法来获取图像数据集。
没有我们想要识别的图像的数据,首先求助于谷歌!
训练图像分类器或在任何计算机视觉项目上工作的最乏味的部分之一是收集你将用来训练你的模型的图像。在本文中,我将通过一个简单的过程来指导您快速收集和过滤您的训练图像。
硒
Selenium 可用于自动化 web 浏览器与 Python(以及其他语言)的交互。通俗地说,selenium 假装是一个真实的用户,它打开浏览器,“移动”光标,如果你告诉它这样做,它就会点击按钮。Selenium 背后的最初想法是自动化测试。然而,在自动化基于 web 的重复性任务方面,Selenium 同样强大。
让我们看一个例子来说明硒的用法。事先需要做一点准备。我将用 Google Chrome 概述 Selenium 的安装和使用。
步骤:
- 安装谷歌浏览器(如果已经安装,跳过)
- 识别你的 Chrome 版本。通常通过点击“关于谷歌浏览器”找到。我目前有版本 77.0.3865.90 (我的主版本因此是 77 ,第一个点之前的数字)。
- 从这里为你的主版本下载相应的 from 驱动,并把可执行文件放到一个可访问的位置(我用桌面/抓取)
- 通过 pip install selenium 安装 Python Selenium 包
启动网络驱动
运行下面的代码片段(为了便于演示,请在 Jupyter 笔记本上运行)并查看幽灵浏览器是如何打开的。
下面是我写的从谷歌上抓取图片的代码:
作者图片
此功能有助于获取要下载的每张图片的 URL,提取、保存 URL,并使网络驱动程序自动点击 google images 中的“加载更多”按钮,从而可以平滑地抓取图片。
我们需要构建的第二个功能是访问每个 URL 并下载 URL 中的图像。
图片由作者提供
这两个函数用于将所有图像抓取到一个文件夹中,该文件夹包含您正在寻找的所有图像。下面是一个屏幕记录,显示了这些功能是如何工作的,以及每张图片是如何从网上抓取的。一定要看一看!
[## MR16 —谷歌搜索—谷歌 Chrome 2020–08–18 13–59–02 _ Trim _ Trim . MP4
编辑描述
drive.google.com](https://drive.google.com/file/d/1a6c6VXAB_cqx_KwM8KwJS6LuCnp-pWug/view?usp=sharing)
PROTIP:如果你将照片数量增加到 500 张,那么从网络驱动程序抓取和抛出错误的次数是有限制的。我发现最简单快捷的方法是使用 chrome 扩展下载图片。
你所需要做的就是获得扩展,打开你的浏览器,输入你的谷歌搜索,点击右上角的扩展图标下载图片。将下载一个压缩文件夹。
https://chrome . Google . com/web store/detail/download-all-images/ifipmflagepipjokmbdecpmjbibjnakm
图片由作者提供
重复数据删除
“如何删除相同大小、相同图像但不同名称的?在数千张图片的数据清理过程中。”
如果您曾经尝试过手动构建影像数据集,您应该知道数据集中很可能会有重复的影像。
在你的数据集中有重复的图像会产生问题,原因有两个:
它 将偏差 引入到你的数据集中,给你的深度神经网络额外的机会来学习模式特定的到重复的图像,这损害了你的模型将 推广 到它所训练的图像之外的新图像的能力。
通常,通过
从多个来源(例如,Google、Bing 等)抓取图像,您的数据集中会出现重复的图像。)或合并现有数据集(例如将 ImageNet 与 Sun397 和室内场景相结合)
当这种情况发生时,您需要一种方法:
检测您的数据集中有重复的图像,并删除重复的图像。
下面是删除重复图片的代码,删除文件夹中所有重复的图片。
由作者提供
该函数初始化一个名为 duplicates 的空列表和一个空字典 hash_keys。然后,它打开并读取每个文件,为文件夹中的每个文件创建一个哈希值。
“md5”算法用于生成哈希值(32 位字符)。“hexdigest()”函数用于创建每个文件的哈希值。如果 file_hash 不在我们的 hash_keys 中,则给出 file_hash 的索引,否则将重复值附加到名为 duplicates 的列表中。
图片由作者提供
现在我们已经准备好了图片,我们需要把它们组织成一个可用的格式,然后开始制作模型!
抓取和重复数据删除的完整代码可以在我位于 https://github.com/aditi310896/Bulbdetectio T21 的 GitHub 仓库中找到
从设想到生产:第二部分
这篇文章是多类模型第 1 部分的延续
图片来源:Pexels
本文讨论了为多级灯泡分类而建立的模型。
这篇文章我们要看什么?
1。在 Google Collab/Jupyter Notebook 上从头构建一个多类分类器
或者,你可以使用 Google 的 Auto ML 软件构建一个模型作为验证指标,或者直接使用 Google 模型
2。使用 Google Auto ML 模型验证模型。
**此步骤要求您拥有一个 Google cloud 帐户,以便在云上训练您的模型,或者您可以使用我们从头开始训练的模型进行部署。
作者图片
我们的目标是做多类图像分类,其中的目标是分类的灯泡类型的图像属于 6。
由于这是一个新问题,还没有尝试过,我被告知从单一标签分类开始,我们从确定图像是否是 MR16 灯泡开始。下图表示预测值和实际值,其中 0 为 MR16,1 为其他。
作者图片
我使用 Google collaboratory 是因为它利用了 GPU 的使用,这将帮助您训练模型的速度比本地机器快 10 倍。你可能想把你的谷歌 collab 升级到专业版,以增加它的内存,并帮助它在你的屏幕关闭时不会断开连接。
训练验证和测试分割
训练:6003 张图像
验证:266 张图像
测试:383 张图像
由于我们有一个大型数据集,我们有足够的图像来验证和测试它,因此大多数图像都放在训练集中。
作者图片
这是训练集和验证集的结构,两者都应该具有类似的结构,每个标签都有一个文件夹,其中包含如上所述的相同图像。
正如您在上面的图片中所看到的,test 文件夹还应该包含一个单独的文件夹,所有的测试图像都在这个文件夹中(可以把它想象成“未标记的”类,这是因为 flow_from_directory() 期望在给定的目录路径下至少有一个目录)。
这些类的文件夹名很重要,用各自的标签名来命名(或重命名)它们,以便于以后使用。
一旦你把图片设置成上面的结构,你就可以开始编码了!
可视化数据:
作者图片
这是我最初试图分类的 6 类球茎。我首先检查了每个标签有多少张图片,以确保我的数据集是平衡的。
作者图片
检查每个标签有多少张图片,以确保数据集是平衡的。
作者图片
类别 mode = categorical 执行一键编码并存储标签。
- 必须将目录设置为您的“n”类文件夹所在的路径。
- target_size 是你输入图像的大小,每张图像都会被调整到这个大小。
- batch_size: 每批从生成器生成的图像数量。
- class_mode: 如果只有两个类需要预测,则设置为“binary”,如果没有设置为“categorical”,则在开发自动编码器系统时,输入和输出可能是同一个图像,在这种情况下设置为“input”。
- shuffle: 如果您想要打乱正在生成的图像的顺序,则设置 True,否则设置 False。
- 种子:随机种子,用于应用随机图像增强和打乱图像的顺序。
让我们看看 class _ mode = categorical 从生成器中出来时做了什么?
我花了一段时间来了解生成器的输出以及它是如何存储图像和标签的,没有相关的文档,如下所示:
作者图片
要知道数据的组织方式是每批有 32 张图片。图像存储时图像中显示的标签为[a][b][c]其中:
[a]=图像的批次号[b]= b 取值 0 和 1 其中[a][1][c]存储图像的标签,[a][0][c]存储图像本身。[c]=该批次中的图像编号。
刚接触计算机视觉的人问过我好几次,CNN 的每一层都学到了什么? 下图显示了 CNN 每一层从图像中挑选和学习的内容。
来源:https://arxiv.org/pdf/1311.2901.pdf
现在我们创建我们的模型。第一步是用 Sequential()初始化模型。之后,我们展平我们的数据,并添加额外的 3 个(或更多)隐藏层。这一步是完全可定制的你想要的。我们制作了几个不同的模型,有不同的漏失、隐藏层和激活。
对于多类分类,最后一个密集层必须有几个与类数量相等的节点,然后是softmax
激活,即你的模型的最后两层应该是:
model.add(Dense(num_classes))
model.add(Activation('softmax'))
损失最好也是分类交叉熵。我尝试了各种迁移学习模型,包括 ResNet、VGGnet 和 Inception,因为这些模型因其性能和特定的架构创新而广泛用于迁移学习。我试着转动这些模型的最后几层,但它们似乎没有给出更好的结果,因此,我认为它们不适合区分我使用的图像类型(即不同类型的灯泡)
作者图片
然后,在我创建并编译了我们的模型之后,我们将我们的训练和验证数据与我们之前提到的规范相匹配。最后,我们创建一个评估步骤,来检查我们的模型训练集相对于验证集的准确性。
这是我们的模型,现在训练数据,然后验证它。一个时期是模型在我们整个数据集上训练的次数。一批可以解释为少量摄入,训练,多摄入一些。在进入下一个时段之前,每个时段必须完成所有批次。用太少的历元训练会导致数据拟合不足,而用太多的历元训练会导致数据拟合过度。你也希望损失尽可能低。下面的图片将显示我们的数据集的准确性和损失。
下图显示了我们刚刚制造的机器对未知数据的预测能力。注意,它说它在 test_data 上进行测试。准确性是第二个数字。然而,这不是检查我们的机器性能的唯一方法。有两种很好的方法可以检验你的机器预测或分类的能力。其中一个是分类度量,另一个是混淆矩阵。
我们的分类指标显示,我们的模型对所有图像类别都具有相对较高的精确度,让我们知道这是一个有效的模型
作者图片
为了使用分类度量,我们必须将测试数据转换成不同的 NumPy 格式,NumPy 数组,以便阅读。这就是第一行代码所做的一切。第二个单元块接收转换后的代码,并通过内置的分类指标运行它,从而给我们一个整洁的结果。请注意,由于我们的生成器函数,我们不需要在这里手动标记我们的类,因为我们在接受输入时设置了 class = categorical。这里重要的因素是精确度和 f1 分数。分数越高,你的模型越好。
作者图片
正如我们在标准化数据中看到的,我们的机器非常擅长对灯泡进行分类。MR16 被误归类为 PAR203038,很可能是因为它们的结构相似。此外,PAR203038 可能因为同样的原因被误划为 MR16。
最后一个阶段是对图像进行测试。下面的单元块将实现这一点:
作者图片
第一个 def 函数是让我们的机器知道它必须加载图像,改变大小,并将其转换成一个可以在 GitHub 访问的数组。第二个定义函数使用预测模型和迭代函数来帮助正确预测图像。路径是我们定义图像位置的地方,最后, test_single_image 单元块将打印出最终结果,这取决于第二个单元块的预测。
这是我们的模型给出的最终结果:
作者图片
PRO HACK :你可以直接使用 Google Auto ML 模型来训练数据,然后尝试将模型权重和 model.json 融入到我们尝试构建的应用中。
在进行这个项目时,我遇到了谷歌的 Auto ML 软件,由于我能够获得 78%的准确性,即使在尝试了不同的转移模型和调整超参数后,我决定通过用 Auto ML 模型训练我的数据来验证我的模型。
AutoML 是一套机器学习产品,使机器学习专业知识有限的开发人员能够针对他们的业务需求训练高质量的模型。这是一个可以设计神经网络的神经网络。
我将分享我如何使用Google Cloud AutoML Vision Edge从零开始训练一个定制的机器学习模型。
您可以在以下位置了解更多关于 google edge 计算机视觉自动 ml 模型的信息:
我不想让教程变得冗长,并记录上面做得很好的训练您的视觉 edge 模型的步骤!
一旦我们准备好一个干净的数据集,我们就可以开始设置我们的谷歌云项目。
1.我们可以按照这个指南来创建一个谷歌云项目:
* [## 设置项目| Dataproc 文档| Google 云
登录您的 Google 帐户。如果您还没有帐户,请注册一个新帐户。在云控制台中,在…
cloud.google.com](https://cloud.google.com/dataproc/docs/guides/setup-project)
2.下一步是在 AutoML 页面上创建我们的数据集。这里,正如您在快照中看到的,我们将使用单标签分类。当图像属于一个类别时,使用单标签分类。在我们的灯泡识别问题中,每个图像将被标记为六个标签中的一个,即单类标签。在多标签分类中,一幅图像可以同时属于多个类别。
这个视频很好地解释了你如何在 Auto ml 中上传和训练你的数据,并带你一步一步地通过它。
3。导入所有图像
在这个初始项目设置之后,我们将使用“导入”按钮,导入狗和猫的文件夹以及它们各自的图像。
注意:最佳实践是将所有输出图像上传到 Google 云存储桶,然后从 AutoML 仪表板导入该桶。
上传后,我们可以在“图片”标签下看到所有的图片。这是你的数据上传后的样子,我建议你上传不同类别的 zip 文件夹到你的 bucket 中,这有助于这个过程更加高效和方便。
作者图片
4。开始模型训练
一旦你看到你的图像反映在 AutoML 仪表板,你训练你的模型。
使用 AutoML 训练该模型非常容易——转到Train
选项卡并单击Train New Model
。培训完成后,我们会收到电子邮件通知。
在训练之前,您应该决定您的模型将如何被使用—作为 API(在线预测)还是在边缘设备上(离线预测)。在线预测是测试结果的最佳方式,或者如果您希望通过 AutoML API 直接使用模型,也是最佳方式。它们更准确。离线模式节省了大量成本,可以在设备上运行。它们通常体积较小,可以在没有互联网连接的情况下运行。我们使用边缘设备,因为我对制作一个可以在任何机器上运行的应用程序感兴趣。
作者图片
对于模型的评估,我们知道精度指的是相关结果的百分比。另一方面,召回指的是被你的算法正确分类的总相关结果的百分比。
查看我们的灯泡分类器的召回率和精确度值。
作者图片
经过训练后,模型可以以 AutoML 提供的各种格式消费,如TF Lite
、Core ML
、Tensorflow.js
等集装箱出口格式。
TensorFlow.js 是一个帮助在浏览器中直接使用 ML 的库。AutoML 创建模型只需很少的时间,TensorFlow.js 是直接在浏览器中运行模型的最简单、最有效的方法。
这是一个有趣的问题,众说纷纭,比如浏览器广泛存在于所有设备中,无论是台式机、平板电脑还是手机。因此,浏览器中的 ML 可以产生很大的影响。从用户的角度来看,ML 模型可以很容易地在浏览器中建立,不需要任何驱动程序、库等。所有数据都保存在用户的设备上,不需要将数据发送到服务器。
使用 AutoML 的TensorFlow.js
模型格式的过程需要两步:导出模型,然后加载进行推理。
作者图片
下面的分步说明将帮助您将任何基于 TF.js 的模型加载到浏览器中。
单击 Tensorflow.js 框后,它会下载如下所示的 bin 文件,这是您准备好部署后的目录外观。
作者图片
模型导出后,您会看到一个model.json
文件,它包含张量信息以及权重文件名和包含模型权重的文件。将 bucket 中的所有文件下载到您的本地系统。
我们将介绍创建一个部署在 Heroku 中的 web 应用程序的过程,该应用程序可以由网络上的任何人使用,但是这里的说明是一个很好的尝试起点。
[## Edge TensorFlow.js 教程|云自动视觉文档
术语:参见 AutoML Vision Edge 术语页面,了解本教程中使用的术语列表。在本教程中…
cloud.google.com](https://cloud.google.com/vision/automl/docs/tensorflow-js-tutorial)
Github 链接可以在:
https://Github . com/aditi 310896/bulb detection/blob/master/multiclassmodeltrial 1 . ipynb*
用 PyTorch 从 LSTM 细胞到多层 LSTM 网络
用 PyTorch 的实际例子理解 LSTM 单元的基础的指南
如何只用 LSTMCells 构建多层长短期记忆神经网络?
这篇博客的目的是展示 PyTorch 中 LSTMCell 类的实际应用。众所周知,PyTorch 提供了一个 LSTM 类来建立基于 LSTMCells 的多层长短期记忆神经网络。在这篇博客中,我们将通过一个实际的例子来解释如何使用 LSTMCells 手工构建这样一个神经网络。
博客组织如下:
- 简介
- LSTM 牢房
- 来自 PyTorch 的 LSTMCell 类
- 多层 LSTM
介绍
LSTM 网络是一种递归神经网络。众所周知,这些类型的神经网络能够正确处理可以表示为序列的数据,例如文本、音乐、频率、时间序列等。LSTM 架构的一个主要特征是它包含门,门的功能是保存有意义的信息以及忘记无用的数据。然而,重要的是要提到 LSTMs 在训练时往往慢,本质上是因为要更新的参数数量。
如果你想深入研究 LSTM 核心,请看看这个惊人的资源:了解 LSTM 网络。
如果你想避开 LSTM 细胞结构的机制和它内部的工作方式,你可以直接跳到 PyTorch 的 LSTMCell 类或者进入多层 LSTM。****
LSTM 细胞
首先,让我们了解一下 LSTM 细胞的机制。LSTM 单元主要由遗忘、输入和输出门以及单元状态3 个门组成。那么,让我们来发现“忘记”“输入”“输出”是什么意思。图 1 显示了 LSTM 单元的架构。
图一。LSTM 细胞
遗忘门决定哪些信息是不相关的,不应该考虑。遗忘门由之前的隐藏状态 h(t-1) 和当前时间步长 x(t) 组成,其值由 sigmoid 函数过滤,这意味着接近 0 的值将被视为要丢弃的信息,而接近 1 的值被视为值得保留的有用信息。然后,根据遗忘门用要保持的信息更新单元状态。图 2 突出显示了构建遗忘门所遵循的操作。等式 1 显示了遗忘门的数学表示。
图二。忘记大门
等式 1。忘记大门
输入门决定什么信息应该是单元状态的一部分(LSTM 的存储器)。它由先前的隐藏状态 h(t-1) 和当前的时间步 x(t) 组成。输入门考虑两个函数,第一个函数通过 sigmoid 函数过滤先前的隐藏状态和当前的时间步长。第二个通过 tanh 函数过滤先前的隐藏状态和当前的时间步长。因此,在更新单元状态之前,两个输出(一个来自 sigmoid 功能,一个来自 tanh 功能)一起操作,其想法是 sigmoid 输出将确定来自 tanh 输出的哪些信息对于保持单元状态是重要的。图 3 突出显示了构建输入门所遵循的操作。等式 2 显示了输入门的数学表示。
图 3。输入门
等式 2。输入门
到目前为止,我们已经讨论了忘记门以及输入门。现在是时候介绍单元状态了。
单元状态被称为 LSTM 的存储器,它由遗忘门和输入门更新。本质上来说,遗忘门定义了不应保存在存储器中的内容,而输入门定义了应保存在该存储器中的内容。图 4 突出显示了更新单元状态的过程。等式 3 显示了单元状态的数学表示。
图 4。细胞状态
等式 3。细胞状态
最后,我们有输出门,其结果产生新的隐藏状态。****输出门利用先前的隐藏状态以及当前的时间步长,其值由 sigmoid 函数过滤。并行提取当前单元状态,由 tanh 函数过滤,两个输出一起操作,以生成新的隐藏状态。图 5 突出显示了构建输出门的过程。等式 4 和等式 5 分别给出了输出门和隐藏状态的数学表达式。
图 5。输出门和隐藏状态
等式 4。输出门
等式 5。隐藏状态
PyTorch 的 LSTMCell 类
到目前为止,我们已经看到了 LSTM 细胞的工作原理及其组成部分。现在是时候看看如何将 PyTorch 的实际输入调整到 LSTMClass 中了。
先来了解一下初始化 LSTMClass 时的输入输出参数是怎样的,以及使用初始化对象时的输入输出参数是怎样的。
为了被初始化,LSTMCell 类需要两个重要的参数
- input_size: 指每个时间步的特征数量
- hidden_size: 指的是在 LSTM 单元内的每个函数中要学习的参数的数量(即,它是每个 W 向量的大小,该向量复合了每个门以及单元和隐藏状态)
初始化后,LSTMClass 创建的对象接收三个输入:
- 输入:包含待学习特征的张量。这个张量有一个形状( batch , input_size ),其中 batch 指的是批量大小, input_size 指的是每个时间步包含的特征个数。
- h_0 :张量,将存储学习到的隐藏状态。这个张量有一个形状(批量,隐藏 _ 大小
- c_0: 张量,它将存储单元状态(LSTM 的存储器)。这个张量有一个形状(批量,隐藏 _ 大小)。
图 6 突出显示了输入【t】隐藏状态(t-1)和 h(t) 以及单元格状态(t-1)和 C(t) 的矢量形状。
图 6。突出显示矢量形状。
正如我们已经知道的,LSTMs 处理顺序数据。所以让我们用一个简单的例子来理解如何顺序地给 LSTMCell 馈电(即如何展开 LSTM 网络)。
假设我们有一个句子“天空是蓝色的”,我们想把它引入 LSTM。因此,我们需要将这些单词转换成神经网络可读的格式。我不得不说,为了将单词转换成一种 LSTM 可读的格式 t,有很多选择,因为这些选择超出了本博客的范围,我将限制自己选择一个最常见的选择,那就是单词标记化。
因此,为了将单词编码成 LSTM 可读的格式,我们首先需要将句子分割成一组单词(单词标记),然后我们需要将每个单词标记转换成索引标记形式。之后,我们需要使用一个嵌入器层,以便将每个索引令牌转换成一个嵌入向量。至此,我们已经拥有了为 LSTM 提供数据所需的一切,我们只需要将序列组织成一组时间步长,其中每个时间步长都将被分配一个批处理大小。
假设我们想要创建一组 2 个时间步长,其中每个时间步长包含 2 个批量大小,我们将有 2 个输入张量,每个张量都有一个形状( batch_size = 2 , input_size = 2 ),其中 batch_size 指的是每个时间步长的样本数, input_size 指的是嵌入维数。图 7 直观地解释了上述过程。
图 7。从原始句子到张量格式的可视化表示。
因此,为了向 LSTM 网络提供顺序数据,我们需要创建一个循环,其中每次迭代都将向当前 LSTM 单元提供一个具有 shape ( batch_size , input_size )的时间步长。因此,就前面的例子而言,每个时间步长将包含批量大小 2 和输入大小 2。在图 8 中,上面的图像通过使用基于单词标记的表示来表示展开的版本,中间的图像通过使用基于索引标记的表示来表示展开的版本,按钮图像通过使用基于嵌入的表示来表示展开的版本。(三个图像是等效的,顶部和中间的图像仅用于说明)。
图 8。展开的版本
是时候看看代码了。在 PyTorch 中,建议在构造函数中定义设置和层。因此,就上面提到的玩具示例而言,代码片段 1 显示了初始化应该如何进行。
代码片段 1。构造器
值得一提的是两个重要方面,第一个是嵌入层作为输入参数接收的 input_size ,注意它指的是词汇量,在这个玩具示例中我们只有 4 个单词,这意味着词汇量是 4。第二个重要的方面是 LSTMCell 接收的输入大小参数,注意它的大小是 embedding_dim ,在本例中是 2(与上面的例子完全一样)。
一旦我们准备好了构造函数,我们需要在转发函数中工作。首先,我们需要创建并初始化单元格状态以及隐藏状态,例如:
代码片段 2。单元格和隐藏状态初始化
在第 3 行和第 4 行中,隐藏的和单元格状态分别被初始化,两者都有一个形状( batch_size , hidden_dim )。紧接着在第 7 行和第 8 行,两种状态都被初始化(在这种情况下,我使用 X 而不是普通的初始化,不过你可以选择你认为合适的那个)。
一旦我们初始化了隐藏的和单元格状态,我们就可以将每个索引令牌转换成基于嵌入的表示,例如:
代码片段 3。从索引标记到嵌入张量
这里,嵌入层接收包含索引标记的张量作为输入,因此 out 变量被赋予具有形状的嵌入值的张量( batch_size,embedding_dim)。
现在,一切都准备好了,以饲料 LSTM,然而在这样做之前,我们需要适应的形状出张量。我们只需要将第一维定义为时间步长的数量,因此我们继续执行以下操作:
代码片段 4。重塑张量
所以现在我们的 out 张量有了一个形状( sequence_len,batch_size,embedding_dim)。好了,是时候展开 LSTM 网络了:
代码片段 5。展现 LSTM
正如我们所观察到的,在循环中,我们用当前时间步长(即 out[i】)来填充 LSTM 单元。同样,通过该循环,隐藏状态和单元状态被更新“I”次,其中“I”表示时间步长为时间“I”。
那么现在让我们来看看完整的前进函数:
代码片段 6。正向功能
多层 LSTM
现在,如果你想堆叠 LSTM 细胞,以建立一个多层 LSTM?图 9 显示了一个 2 层 LSTM 网络的简单架构。
图 9。多层 LSTM
我们首先需要做的是在构造函数中初始化第二个单元(如果你想构建一个“n”堆叠的 LSTM 网络,你需要初始化“n”个 LSTMCell)。
代码片段 7。细胞初始化
因此,我们需要为每个 LSTM 层初始化隐藏和单元状态。
代码片段 8。权重初始化
现在是时候养活 LSTM 网络了。第一层将接收包含每个单词的每个标记的嵌入版本的输入张量。第二层将在时间步长“t”接收 LSTMCell 的隐藏状态作为输入。
代码片段 9。展开 LSTM 网络
所以基本上就是这样!
紧接着,如果你想使用 LSTM 网络的最后一个隐藏状态,你应该使用最后更新版本的隐藏状态层 2。
因此, forward 函数应该是这样的:
代码片段 10。正向功能多层 LSTM
结论
这篇博客解释了 LSTM 网络背后的数学原理,特别是 LSTM 细胞是如何工作的。同样,还解释了如何实现 LSTMCell 类以及如何准备数据,以便仅使用 LSTM 单元构建 LSTM 神经网络和多层 LSTM 网络。
了解幕后的机制总是很重要的,这次我们分解了 LSTM 的组件,以及这些组件是如何用当今最流行和强大的深度学习框架之一 PyTorch 实现的。
从高级分析到有效分析
了解并协调数据驱动型企业中的 Lukes 和 Yodas 的途径
在过去的十年里,企业的决策方式发生了根本性的转变。获胜的组织已经从一个个人经验和直觉为王的环境,转变为一个数据驱动的世界,在这个世界中,决策得到可量化的历史证据的支持。我们现在正处于下一次变革的边缘,即从简单分析到高级分析的转变。这种变化,像其他任何变化一样,需要在宏观和微观层面上提出发人深省的问题。转型领导者应该问的一个关键问题是,“从简单到高级分析的转变有意义吗,或者我们应该考虑另一条路线?”
随着在线课程的激增,高度宣传的成功和媒体的大肆宣传,高级分析(以各种形式营销)作为商业的下一步发展已经占据了中心舞台。这种宣传有积极的一面,因为以前认为数据价值不大的企业开始信任数据,并从中获益。然而,硬币的另一面并不那么闪亮。大肆宣传也造成了预期,让企业感到沮丧,许多员工失去了动力。
为了增加销售额和信任度,企业已经跳上了“站在人工智能和分析的最前沿”的潮流。这种策略是否能成功促进销售尚不清楚,但它确实为新的、有分析天赋的资源加入业务创造了期望。为了简单起见,我将这些资源称为“Lukes”。许多卢克加入了人工智能驱动的企业,希望“伸展四肢”,建立最新和最伟大的预测模型(这是可以理解的,因为这些模型在技术上很有趣,并增加了你的街头信誉)。不幸的是,卢克没有意识到需要进行的培训,也没有意识到他们在商业中的核心技能似乎是不切实际的。这导致了卢克内部的沮丧和消极情绪。随着业务资历的增加,技术理解能力的下降加剧了挫折感。
不管企业如何推销他们的分析能力,其中有一个共同的事实。企业希望从他们的数据中获得可操作且可信的见解。很少重视所使用的方法或技术。相反,当从数据中提取的洞察力允许卓越的解决方案时(特别是在竞争激烈的市场中),真正的价值来自于分析能力。当考虑在成功的数据驱动环境中运营的企业时,您会发现一些企业领导者特别擅长以最小的复杂性提取这些见解。从现在开始,我将称这些领导人为“Yodas”。
为了抑制挫折感,卢克斯获得了解决问题的极大自由,而商业领袖期望从他们的解决方案中获得有限的价值。这种方法确实在短期内减少了挫折感,但是,会导致很大一部分分析工作不再“有效”,无法被 Yodas 或企业使用。
有效分析
为了平衡分析工作对 Yodas 的有用性和 Lukes 的挫折感之间的权衡,提出了“有效分析”的概念框架。
为了介绍有效分析的概念,想象对于每个问题都有无限多种可能的分析解决方案。此外,这种简单的解决方案从简单到高级/复杂不等。
图一。所有解析解都存在的平原。
每个问题的解决方案都会落在这个平原上的某个地方,确切的点取决于尤达和卢克之间的关系。尤达自然喜欢更简单、更容易理解的解决方案,而卢克喜欢更复杂、更先进的解决方案。解决方案落地的准确位置将取决于每一方展现的“武力强度”。各方的“力量强度”将取决于他们各自的可信度,以及问题的商业重要性。
图二。最终的解析解将取决于卢克和尤达所施加的力。
不幸的是,没有一个框架将卢克斯和约达斯纳入同一个参照系。相反,尤达或卢克做出了妥协,导致至少一方遭受损失。
有效的分析框架试图将 Lukes 和 Yodas 纳入同一个参考框架。这是通过向解决方案平面添加另一个维度来实现的。新的轴负责衡量解决方案从简单到高级的有效性。
图 3。效力的轴心
使用这种方法,并从其他研究领域窃取一些理论,可以为每个问题创建有效的前沿解曲线。
图 4。有效性边界和有效分析领域
所得曲线上的每个解决方案都有一定的分析有效性。此外,在构建详细的解决方案之前,Yodas 和 Lukes 可以很容易地确定并商定一组有效的分析解决方案。这种透明度将使陆客对业务需求有所了解,减少他们的挫折感。对于 Yodas 来说,这种方法将允许他们最终获得可用且值得信赖的解决方案,并且随着时间的推移,获得非常强大的 Lukes。
企业如何创造有效分析的文化?
这是一个很难回答的问题,主要是因为每个企业都是独特的,没有单一的解决方案。
在进入细节之前,需要进行一个重要的区分。有效分析的文化是让数据引领方向的下一步,这不是第一步。如果你正在阅读这篇文章,它假定你的企业已经有了数据驱动的思维模式,并且数据的价值已经实现。向数据驱动的思维模式迈出第一步是另一回事,这里就不讨论了。
让有效分析的环境扎根的关键是与雷伊·达里奥的彻底开放和透明的概念相一致。
在大多数企业中,即使是那些扁平化的企业,Yodas 和 Lukes 之间也有明显的界限。在这些独立的领域中运作导致了卢克斯和约达斯的主观现实之间的错位。通过尤达斯培养真正的商业透明度,卢克夫妇能够更好地理解大多数商业环境与他们接受培训的学术环境明显不一致。这需要卢克调整他们的重点和价值定位,关键的调整是区分什么是华而不实,什么是为企业增加真正价值的技能。
此外,培养这种透明度会鼓励高层领导(包括尤达斯和共和国的其他人)在高级分析领域发展自己。对高级分析的概念性理解使 Yodas 能够更好地可视化“有效解决方案边界”,了解提议的解决方案在边界上的位置,并在整个空间提供更有效的指导。
认为这一领域应该与其个人技能相分离的 Yoda 冒着以下风险:a)落后于拥抱数据驱动世界下一步的 Yoda,b)无法吸引或留住 Lukes,因为他们的特定技能没有通过增长机会得到回报。
理解原力之道
进入细节,下面是 Lukes 和 Yodas 需要理解/学习的一些具体要点,以实现一致并实现有效分析的文化。
卢克夫妇必须了解:
- 最酷/最准确的模型/技术并不总是问题的最佳解决方案。这在一开始对他们来说没有意义,甚至可能会有很大的阻力,但是给他们时间,他们会发现有时电子表格是这项工作的最佳工具。
- 您正在解决的问题应该作为相关技能/技术的指南。不要每个问题都拿着深度学习的锤子。
- 你的时间耗费金钱。用这个来计算你正在构建的解决方案的成本,然后问自己这样一个问题,“我会在我正在做的事情上花那么多钱吗?”如果不是,那么你需要重新考虑你的方法。
从尤达的角度来看,重要的是要知道:
- 整个分析景观。是的,这看起来很专业也很吓人,但是如果你真的相信这是你的业务发展的方向,那就投入进去吧。如果不是,那就值得重新考虑你雇用陆客的理由。
- 数据驱动进化的每一步都比上一步更大。这表明,有效的分析不是企业可以掉以轻心或对冲赌注的运动。在这个领域的承诺问题可能会导致很少的价值收益和失败的自我实现。为了增加价值,信任和信念需要放在这个方向上。
- 不要屈服于人工智能热潮。如果你雇佣卢克通过“爱”东西来解决你的问题,你很可能在浪费你和他们的时间。
- 确保你有一个 Lukes 可以工作的环境。不要雇佣卢克,指望他们创造奇迹。你会很失望,甚至可能以一个维达(一个真正优秀的卢克变成了负面)而告终。
- 卢克不知道原力之道(即商业如何运作),所以给他们指导。如果你不这样做,你可能会得到非常酷的解决方案,但是没有办法实现或使用它们。
结论
干得好!你已经完成了这个想法(显然人们通常不会坚持这么久)。我留给你这条忠告。如果你是一个正在寻找尤达的卢克,我相信你会考虑到以上几点。如果你是一个已经有卢克的尤达,请认真对待这一点,并在你的业务中寻求结盟。如果你是一个带着维达的尤达…好吧…愿你永远幸运…
从业余到数据科学家——3 个月,够不够?
数据科学培训师视角的故事
“短短 3 个月成为数据科学家!我们将保证"
这段话是你经常从数据科学训练营广告中看到的吗?虽然这些话可能和你在那里看到的一样,但是你明白了。许多训练营会试图在尽可能短的时间内向推销成为数据科学家的前景。
虽然真的有可能吗?从对数据科学一无所知到成为一名有天赋的数据科学家?这是我从训练营的一位前数据科学培训师那里得到的观点。
数据科学训练营
为什么 Bootcamp 有足够的勇气做出这样的声明?我们首先需要知道就业市场想要从数据科学家那里得到什么。下面我举一个我在 LinkedIn 上找到的数据科学家职位需求的例子。
数据科学职位发布要求(来源:LinkedIn)
上面是一个典型的数据科学家招聘广告,你可以在任何地方找到。除了工作经验,这里列出的任何其他技能特别是我圈出的是技术技能。
这是大多数数据科学训练营经常致力于实现的目标;让训练营的学生具备技术技能,以确保他们能够参加工作面试。
如果我们看一下数据科学在线课程和训练营,学习大纲将遵循类似的方面:
- 学习 Python/R(编程语言)
- 学习可视化包
- 学习 SQL
- 学习机器学习
- 学习基本概率/统计
这是数据科学训练营经常提供的内容,也是我在担任数据科学培训师期间教给学生的内容。
那么 3 个月的时间学会以上所有技能,保证数据科学家这份梦寐以求的工作,够吗?简短的回答是没有,但是总有一个异常的空间。我来解释一下原因。
培训师的观点
数据科学训练营
数据科学培训师将在您的数据科学训练营的学习过程中为您授课。不管是好是坏,当教一个学生时,并不是所有的教练都有相同的经验和技能;也不是训练营机构本身——有些是为了销售。
在我担任数据科学培训师期间,我的工作场所显然没有准备好合适的学习材料和合格的教师。
当然,有一个来自 web 和开发编程背景的培训师,我承认他们的技能是神一样的,但教授数据科学?这是一个很大的不。
培训师大多是年轻人,他们因为编程技能和一些 Udemy 幻灯片课程而被迫教授数据科学。此外,在我加入公司时,我是唯一一个真正有数据工作经验的人,所以这对我来说是一个很大的惊喜。
有了这样的经历,我总是对数据科学训练营持保留态度。这是我作为前数据科学家培训师的第一个观点:
"申请数据科学工作需要技术专长,但并非所有数据科学训练营的质量都一样。有些只是伪造的,会阻碍你成为数据科学家的机会。
考虑到这一点,选择一名合格的数据科学家训练营是你在三个月内成为数据科学家的第一步——或者像广告宣传的那样。
老师和学生
当你有一个合适的教学机构和合格的老师,现在我能成为一名数据科学家吗?你的机会会更高,但有一件事我需要提醒你;不是每个人都会放弃在数据领域的工作。这就是这个世界的残酷现实,每个人都有天赋,但每个人都有自己的天赋。数据科学工作值得吗?你可以在这里阅读我的观点。
长话短说——的确如此(至少对我来说)
towardsdatascience.com。](/data-scientist-job-is-it-worth-the-sacrifices-made-efdf34139aa6)
当我在做培训师的时候,我见过各种各样的学生——从有经验的天才到完全的业余爱好者。我可以看到一个学生跟上学习材料和理解新概念的能力,从真的很快到需要更多的时间来学习。
我很难确保每个学生都理解这些材料,因为我们的时间有限——训练营的广告是三个月,记得吗?。在短短的时间内,我需要教授所有可用的学习材料。
当然,对于拥有快速学习技能的学生来说,这是轻而易举的事情,但对于没有掌握数据科学技能的学生来说,这将是一次痛苦的经历。
从我作为一名培训师的角度来看,在三个月内成为一名数据科学家的广告对一些学生来说当然是可能的,但对另一些学生来说几乎是不可能的,因为他们的能力不同。
所以,我的第二点是:
并不是所有的人都适合从事数据领域的工作,尤其是需要较长的时间来掌握必要的数据技能。如果你更加努力的话,也许可以,但是肯定比广告上说的三个月时间要长。
我的建议是,如果你对自己的技能不确定,尝试学习哪种数据科学家技能,甚至在参加数据科学训练营之前就做好准备。这会对你有很大帮助。
训练营后
在承诺的时间和从训练营毕业后,我现在是一名数据科学家吗?我不这么认为,现在是最难的部分——获得工作面试。
我见过许多有才华的学生连面试都很难,更不用说获得工作机会了。有些训练营提供与各种公司面试的机会,但有些没有。尽管有些学生在面试时仍然很难接受。
为什么那个学生过得很艰难?这是因为大多数学生只教授数据科学技术技能;忘记了许多其他方面,即业务和沟通。
我知道很多容易找到工作的学生并不是最聪明或最有才华的,但他们有很好的沟通技巧并了解公司业务。学习这项技能对我来说是从其他候选人中脱颖而出的最重要的技能。你可能想在我的其他文章中了解更多关于数据科学家的商业技能。
每个数据科学家的核心。(抱歉,不是编码的问题)
towardsdatascience.com](/learn-the-business-to-become-a-great-data-scientist-635fa6029fb6) [## 数据科学家必须了解商业 x 统计
为什么业务和统计之间集成对于数据科学家来说至关重要
towardsdatascience.com](/data-scientist-must-know-business-x-statistics-7bb8575a9525)
无论如何,成为数据科学家重要的不仅仅是技术技能,还有业务和沟通技能。事实上,如果你和一些培训师关系很好,他们甚至会给你推荐一份数据科学的工作(这是我自己的经验)。
所以,我的第三点是:
"当你申请成为数据科学家时,训练营的技术技能并不是公司寻求的唯一东西。你可能需要另一种技能,比如商务和沟通。
尽管如此,即使你缺乏商业技能,仍然有可能获得一份数据科学家的工作。毕竟这个世界是一个奇怪的地方,有许多变量会影响你的就业机会。
结论
总之,我想说,成为一名数据科学家很难,尤其是在三个月内。这是因为:
- 一些训练营不够资格教你必要的数据科学技能。
- 不是每个学生都有足够的天赋在短时间内跟上学习材料。
- 完成训练营后需要很多必要的技能。
如果您喜欢我的内容,并希望获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的简讯。
如果您没有订阅为中等会员,请考虑通过我的推荐订阅。
从分析到仪表板——连接笔记本和表格
现实世界中的数据科学。
这个故事讲述了在尝试和失败了许多方法后,我是如何从笔记本上创建梦想仪表盘的。在这里,我分享我是如何将我的数据帧连接到 Tableau 的。希望这篇博客能帮助那些在笔记本和仪表盘之间挣扎的人。
卢克·切瑟在 Unsplash 上的照片
数据分析的大背景不仅仅是数据和获得见解,还包括让每个人都能理解这些信息。当时,作为数据科学的初学者,我接触了 Jupyter 笔记本电脑。笔记本就像其他演示媒体一样。它由单元格组成,您可以在其中放置代码,然后在单元格下运行和输出,它还带有一个 markdown 功能,您可以用基本的 HTML 记录您的代码。这些笔记本用于探索性数据分析,便于与队友分享您的工作成果。尽管它有 Plotly、matplotlib 等库,但对于非技术用户来说,它仍然不是现成的。
例如,以新冠肺炎为例。世界各地的每个人都关心了解他们国家的日常状况。他们会选择一个记录了更多单元格、代码的笔记本,还是一个以交互形式分享你的分析可视化的仪表板?这就是为什么每个数据分析师都需要具备讲故事的技能。仪表板就像讲故事一样,你从你所获得的信息中构建一个故事,这个故事应该以一种不会让他们转移视线的方式呈现。
所以问题是,我如何将我的 jupyter 笔记本连接到 Tableau,而不需要在 Tableau 中安装 python?
答案很简单。Tableau 只需要数据。jupyterlab 的数据帧可以保存为 CSV、Xls、JSON 等格式,但在实时分析中,当数据每天都在更新时,每天从 jupyter 笔记本下载数据并上传到 Tableau 是低效的。
但是有一个解决方案,尽管笔记本电脑不支持数据库,因为它们的唯一目的是分析数据集。
如何这些分析的数据集,准备可视化是发送到谷歌使用谷歌 API 表。因此,即使数据在每次刷新我们的笔记本时不断更新,我们从在线门户网站读取的数据也会在分析后自动保存到 google sheets,tableau 可以连接到这些数据表。
因此,创建实时仪表板的任务非常简单。你要做的就是
- 创建笔记本
- 从在线门户数据 API 读取数据到熊猫数据框架
- 分析并创建一个干净而精确的数据报。
- 将数据发送到 google sheets。
- 让我们将以下库导入笔记本
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from df2gspread import df2gspread as d2g
- 现在,在做任何事情之前,请按照以下说明获得对您的工作表的凭据访问权限:
- 前往谷歌开发者控制台创建一个新项目(或者选择一个你已经有的项目)。
2.在“APIs & Services > Library”下,搜索“Drive API”并启用它。
3.在“APIs & Services > Library”下,搜索“Sheets API”并启用它。
4.启用项目的 API 访问如果你还没有这么做的话。
5.转到“APIs &服务>凭据”并选择“创建凭据>服务帐户密钥”。
6.填写表格
7.点击“创建密钥”
8.选择“JSON”并点击“创建”
您将自动下载一个带有凭证的 JSON 文件。它可能看起来像这样:
{
"type": "service_account",
"project_id": "api-project-XXX",
"private_key_id": "5ty … bg4",
"private_key": "-----BEGIN PRIVATE KEY-----**\n**NrDyLw … jINQh/9**\n**-----END PRIVATE KEY-----**\n**",
"client_email": "443000000000-msmhj@developer.gserviceaccount.com",
"client_id": "445 … hd.apps.googleusercontent.com",
...
}
记住下载的凭证文件的路径。同样,在下一步中,您将需要该文件中 client_email 的值。转到您的电子表格,并与上面步骤中的 client_email 共享。
- 创建一个新的 google 工作表,将键复制到一个名为 spreadsheet_key 的变量中。粗体字将是我的工作表的关键。可在打开工作表的链接中找到)
[https://docs.google.com/spreadsheets/d/**1vd6hDT6k8lcWNMDYz13kqW7zXnIX5TVED9–4Kq7EAQnvI**/edit#gid=0](https://docs.google.com/spreadsheets/d/1vdDT6k8lcWNMDYz13kqW7zXnIX5TVED9-4Kq7EAQnvI/edit#gid=0)
- 将以下代码添加到您的 python 脚本或笔记本中。另外,友情提示,在复制下面的代码之前,您刚刚下载的 JSON 文件和 python 脚本应该在同一个文件夹中。
scope = [‘[https://spreadsheets.google.com/feeds'](https://spreadsheets.google.com/feeds'),
‘[https://www.googleapis.com/auth/drive'](https://www.googleapis.com/auth/drive')]
credentials = ServiceAccountCredentials.from_json_keyfile_name(
‘myfile.json’, scopes=scope)
gc = gspread.authorize(credentials)spreadsheet_key=’[**1vd6hDT6k8lcWNMDYz13kqW7zXnIX5TVED9–4Kq7EAQnvI**](https://docs.google.com/spreadsheets/d/1vdDT6k8lcWNMDYz13kqW7zXnIX5TVED9-4Kq7EAQnvI/edit#gid=0)’
- 现在清理您的数据集,并将准备可视化的数据保存到数据框中。
- 复制并粘贴以下代码,将您的数据帧发送到 google sheets。
wks_name= “nameofyoursheet”
d2g.upload(df, spreadsheet_key, wks_name, credentials=credentials, row_names=True)
print(“Data upload success”)
wks_name 将是您的工作表的名称,df 将是您的 dataframe 变量。现在,每次刷新笔记本时,数据都会自动更新到工作表中,您可以通过数据 API 将数据读取到笔记本中,这样就可以轻松地使用 jupyter notebook 进行实时分析。
- 完成以上步骤后,打开 Tableau,连接你的 google sheets。要下载 Tableau,请点击这里
- 若要连接,请前往服务器> google sheets
将 google sheet 添加到 Tableau 数据连接后(数据来源: OGD 平台印度
- 使用工作表中的数据框在 Tableau 中创建可视化效果。每个可视化都可以在表格中完成,这就是他们所说的 Tableau。这些表可以拖放到仪表板中。将您的仪表板发布到 Tableau Public,就大功告成了。
现在,由于数据每天都在变化,我们所要做的就是刷新笔记本和 Tableau 数据连接。你所有的可视化会自动更新。
Tableau 相对于其他可视化库(如 Plotly 和 matplotlib)的一个优势是,你可以零编码地获得可视化效果,这是非常专业的。
点击此处查看我使用 jupyter notebook(用于分析)和 Tableau(用于可视化)制作的一个仪表板。
神经网络优化轨迹的可视化
从动画到直觉
飞越纽约风暴王艺术中心,2018 年夏天。我在 DJI 马维克航空公司拍摄的照片
更新:我已经把代码移植到一个 Python 包 这里 。请随意试验并制作类似本文中的情节!
在前后中,我展示了一些线性回归和逻辑回归的训练过程的动画情节。对他们如何“学习”有一个良好的“感觉”是有帮助的,因为在应用更复杂的模型之前,他们可以被用作基线。虽然大多数深度神经网络也使用基于梯度的学习,但类似的直觉要难得多。一个原因是参数是非常高维的,涉及到许多非线性,很难在我们的脑海中描绘出优化过程中发生了什么。与计算机不同,我们只能感知小于或等于 3D 的空间。
在这篇文章中,我将展示更多的动画情节,让你一窥这些高维空间。我使用的模型是带有 ReLU 激活的全连接多层感知器。然后,我们可以直观地看到宽度和深度如何影响损失情况和优化轨迹。
让我们考虑这个由 3 个类组成的 2D 数据集。我们人类一眼就能看出这种模式是由某种螺旋函数产生的。我们只需不到一秒钟就能识别它,同时,我们会自动为看不见的数据产生一种外推方法。这是因为我们从出生起就接受了这种视觉任务的训练(也不要忘了我们只能在非常低维的空间中做这件事)。在这里,我将训练几个人工神经网络来对这个形状进行分类,并在参数空间中检查训练过程。
在继续之前,我想提出一个重要的问题:我们如何在高维参数空间中可视化优化轨迹?
最直接的方法是找到两个方向来穿过高维空间,并可视化该平面上的损失值。但是用哪两个方向呢?有无限多的潜在方向可供选择。在论文 中用神经网络可视化损失景观,李等。艾尔。 ,作者讨论了几种方案,并采用了一种使用 PCA 进行降维的方案。下面是动机的简要总结:
- 2 高维空间中的随机向量很可能是正交的,并且它们很难捕捉到优化路径的任何变化。路径在两个向量所跨越的平面上的投影看起来就像随机漫步。
- 如果我们选择一个方向作为从初始参数指向最终训练参数的向量,而随机选择另一个方向,可视化将看起来像一条直线,因为第二个方向与第一个方向相比没有捕获太多的变化。
- 如果我们在优化路径上使用主成分分析(PCA ),并获得前 2 个成分,我们可以用最大方差可视化 2 个正交方向上的损失。
因此,我使用 PCA 方法来获得更好的优化路径。请记住,这不是路径可视化的“最佳”方法,因为它可能不适用于其他目的。例如,如果您的目标是比较不同优化器采用的路径,例如 SGD 与 Adam,这种 PCA 方法将不起作用,因为主要成分来自路径本身。事实上,不同的优化器具有不同的路径和不同的 PC 方向,即损失情况的不同部分,使得不可能进行比较。为此,我们应该使用两个固定的方向。
这里的架构是通过改变和组合下面的两个属性产生的
- 隐藏层数:1,5,10
- 每个隐藏层中的神经元数量:5,20,100
总共 9 种配置。
让我们看看不同模型产生的决策区域/边界旁边的优化路径。通过显示决策区域,而不是依赖于生成数据集分割的验证/测试准确性,我们可以更好地直观了解不良拟合,因为我们已经有了先验知识,即头脑中的“螺旋”预期。
首先,让我给你展示一下逻辑回归在这种情况下的作用,
逻辑回归
显然,它的 3 条直线做得不好,但它的损失景观是完全凸的。
从第一个配置开始:1 个隐藏层和 5 个神经元。每个带有 ReLU 的神经元本质上是一条直线,有一边被激活。
1 个包含 5 个神经元的隐藏层
从逻辑回归来看,这是一个明确的进步,但 5 个神经元无法捕捉螺旋的弯曲形状,并努力达到高精度和低损耗值。损失情况似乎大多是凸的。
我们看到增加了更多的神经元
1 个包含 20 个神经元的隐藏层
1 个包含 100 个神经元的隐藏层
请注意,每个主成分捕获的方差都标在轴上。顶部组件几乎总是获得 95%+这部分是由这些数据的性质和网络的架构决定的。在论文中,作者还观察到类似的行为,即对于 CIFAR-10 数据集和各种架构,优化路径位于非常低维的空间中。
接下来,5 个隐藏层,
5 个隐藏层,每个层有 5 个神经元
5 个隐藏层,每层 20 个神经元
5 个隐藏层,每层 100 个神经元
通过 5 个隐藏层,PC-2 子空间中的损失景观变得明显不那么凸。对于窄的 5 个隐藏层乘以 5 个神经元的设置,我们可以猜测高维景观是高度非凸的,并且优化器很快陷入局部谷并产生不良拟合。
有了 20-100 个神经元和 5 层,优化器可以非常快地达到接近零的损耗。进一步的训练只是让它波动,出现意想不到的“小故障”。正在发生的是,神经网络试图用数据所在的 2D 空间之外的奇怪的高维形状来拟合这些数据。它过拟合得很快,但并没有像我们直觉上所做的那样真正捕捉到底层的数据生成机制。
事情变得有点疯狂的 10 个隐藏层。
10 个隐藏层,每个层有 5 个神经元
10 个隐藏层,每层 20 个神经元
10 个隐藏层,每个层有 100 个神经元
它们都有相同的特征,比如很快达到接近零的损失,但却产生奇怪的拟合,不能很好地概括。在其他条件相同的情况下,窄而深的神经网络比宽而浅的神经网络更难训练。
看看这个薄而深的 20 层网络,每个隐藏层有 5 个神经元,损失景观是如此不凸,它只是卡住了,变得不可捉摸。
的论文更详细地讨论了神经网络属性的几个方面。作者研究了网络深度、宽度、初始化、跳跃连接的影响,以及损失景观几何的含义。一个关键要点是,跳过连接对于使深度网络更容易训练至关重要。如果你对为什么我们可以训练深度神经网络这个问题感兴趣,我强烈推荐这篇论文。
一图抵千言 。这里的每个动画情节都是 50 张图片,我们在这篇文章里有 21 张。比较不同配置之间的历元数、损失值和准确度,可以对基本神经网络的学习过程有一个“感觉”。同样的方法可以用来可视化更大更复杂的架构。
尽管今天对深度学习进行了大肆宣传,但人工神经网络仍处于早期阶段。许多技术是经验性的,还没有理论支持。获得经验的最好方法是通过反复试验。一旦深度学习的学生在基础上发展出一些直觉,我推荐 fast.ai 提倡的自上而下的学习方法。许多科技上的突破都是实验过程中的偶然事件,而不是理论推导的自然结果。人们通常理解为什么某样东西在应用了几年后会起作用。所以不要害怕未知,把手弄脏就好,多培养模特!
参考
从艺术到分析
一个艺术专业的学生如何学会用数字画画
就在新加坡经济因新冠肺炎而关闭的三天前,尽管新加坡颁布了禁止人们旅行的禁令,我还是决定踏上一段旅程,让这位文科专业的学生(我)穿越未知的科学宇宙。
最初,我在考虑加入一个数据分析训练营,但我的研究没有提供任何可信和有价值的来源。当我联系那些完成了新兵训练营的人时,他们中的一个引导我去寻找在线学位课程。几个小时后,我发现自己全身心地投入到了佐治亚理工学院的分析学硕士课程中。
我很确定这是一时冲动,到周末我会意识到我有多疯狂。
差不多两个月过去了,我已经清醒过来,我断定自己是疯了。但不是因为我认为这是一个错误的决定,而是因为我仍然认为这是正确的。
当我 20 多岁的时候,回到大学,我觉得我们都陷入了自己专业的刻板印象中。漂亮的书呆子从事商业管理,运动员和戏剧极客从事国际研究,数学不好的人从事通信。同学们在我们的数学课上会耸耸肩说,“哦,我们不应该擅长数学。我们在通讯!”这是一个方便的借口,到我们在一起的四年结束时,这是我们内在的真理。
除了简单的算术,我想我会尽可能远离数学,因为我相信我会与画板打交道,而不是梦想商业活动。然而,今天,在任何工作场所,熟悉数字和指标、查找数据、能够分析和可视化数据正成为一个额外的优势。尽管如此,我想我记得数学至少得过 B。但是另一周,当我翻出成绩单准备申请研究生时,我发现我的数学成绩是大大的 c。
我吓坏了!但是,我现在如何进入分析领域呢?
检查一下先决条件,招生网站是这样说的:
至少一门大学水平的课程或概率/统计、Python 计算机编程、微积分和基本线性代数方面的同等知识。
我差点死掉。
我觉得自己爆炸成无数个小碎片,然后有人按下了倒带键,我回到了自己的身体里,凝视着客厅地板的天花板。
有趣的是,我惊讶地坐起来,然后打开一个新的浏览器标签,开始输入:“在线大学水平的数学和编程课程。”
当我感到震惊时,我发现自己注册了一门 cs 1301 Python 编程入门课程和一门六门课程的数学课程,这门课程将带我从线性代数到微积分再到概率和统计。
我想,“哦哦”,然后令人惊讶的是,“哦有趣!”
问题是,有趣可能不是描述它的最好的词。即使我每天早上照镜子,告诉镜子里的自己我非常需要的肯定,我的数学还是没有更好。
“你很擅长数学!你是个天才!你能做到的!”
在过去的几周里,我看到自己在解决编码问题,我(自己)想出了如何将 215 这样的整数转换成 11010111 这样的 8 位二进制数。我从来没有想过,我可以创建一个程序来做这件事。我的意思是,我从来没有想过我能告诉你什么是 8 位二进制数。
我认为这也有助于我参加的编程课程非常令人鼓舞,有时甚至是彻头彻尾的哲学。在翻阅材料时,我看到了这段关于调试的文字:
“一个好的程序员不是从不出错的人;一个好的程序员知道如何诊断和修复出现的错误。”
作为一个带着跨越我大半辈子的有限信念和刻板印象来到这里的人,我知道犯错误是旅程的一部分。现在,每当我写代码或解决数学问题时,我不再试图第一次就做对。它帮助我将问题分解成更小的块,测试它,并找出错误在哪里。这是一件很酷的事情。这可能也是让我走上这条路的原因。
不过说真的,我想象着我现在随时会举起双手说我已经受够了。但是每天我都兴奋地坐下来,看着问题,然后试图解决它们。
我知道我仍然需要记住我的二次方程。当看到分数、平方根或任何我没有遇到过的数学符号时,我仍然在研究我的第一反应——我只能说这是很多,因为我不想去数它们。
现在想想,以前还有哪些事情是我因为先入为主的观念而讨厌的?今天,我还拥有哪些不再为我服务的身份?有多少次我退缩了,因为我甚至在开始之前就把自己从等式中剔除了?还有,那是数学双关语吗?😏 )
我知道路很长,我必须完成所有的先决条件,甚至在我申请硕士课程之前就有良好的声誉。我不能保证我会被录取,尽管我知道我会尽最大努力。如果有什么不同的话,我确信至少这个通信专业的学生可以从中得到一个好的故事。
从业务需求到运行应用的大数据
揭开大数据应用的面纱
大数据工具和技术—数据存储框架
如果你仍然不确定你是否正在处理大数据应用,我鼓励你阅读文章 处理大数据应用 。
在本文中,我将深入介绍主要的大数据工具和技术,它们可以满足您构建运行良好的大数据应用程序的所有目的。
当你看一看大数据生态系统时,你会对你可能注意到的工具的数量感到惊讶和困惑,并且会产生许多问题:我们需要知道所有这些工具吗?可供选择的最佳工具有哪些?有没有一些工具比其他的更好?如果我们只是在寻找某些功能,如处理大量数据的存储或实时分析,我们需要使用什么?
这些问题和更多的问题可能会造成这种混乱,这将使大多数具有相当好的专业水平的人迷失在这个领域。这些问题将在接下来的章节中回答。
我们需要知道现在市场上所有的工具吗?
我宁愿说不!你不需要知道所有可用的工具,只需要知道你需要什么。
为了消除混淆,市场上的工具根据其功能分为不同的类别,如下所示:
- 数据存储框架:这些框架是为了处理基于分布式存储机制的海量数据而构建的。这些分布式存储机制通常支持复制和分区数据,以便处理节点(主机)中的任何故障转移,并使它们始终可供用户或其他应用程序使用。
- 数据处理框架:这些框架有一个特定的角色,通过对数据应用各种处理来概括,包括过滤、清理、转换等等。这些工具通常以分布式方式实时执行它们的任务,考虑将记录分成多个节点,并并行应用不同种类的处理任务。
- 数据采集框架:这些框架的作用就像一个排队机制,它们确保每个记录都不会被遗漏。从而确保推送到这些框架的每个记录的交付保证。它们通常还支持复制数据,以避免任何节点发生故障时的任何数据丢失。
- 数据可视化框架:这些框架是理解大数据应用程序生成的结果的关键。这些结果是决策的基础。负责决策的经理将使用图表和不同种类的可视化小部件来进行所需的推理。
在本文中,我将详细讨论数据存储框架,我完全知道一篇文章对于如此庞大的工具和框架集是不够的,因此,我将更多地考虑大数据的核心及其所有不同的架构,并尝试列出当今市场上被认为非常重要的多种其他工具。
Hadoop —大数据的核心
简而言之,我想提一下 Hadoop 是基于 2003 年发表的 Google 文件系统(GFS)论文创建的。这篇论文是引领大数据时代的核心工作。在揭示了 GFS 的秘密之后,Hadoop 的开发开始付诸实践,成为一个名为 Apache Nutch 的项目,该项目于 2016 年转移到新的 Hadoop 项目,其中发布了第一个版本。Hadoop 是第一个开源、可靠、可扩展的计算框架,能够处理数 Pb 的数据。它的核心是基于 Java 编程,带有一些 C 和 shell 脚本中的原生代码。
你需要知道的是,Hadoop 主要由两个重要的层组成,一个是数据层,称为 Hadoop 分布式文件系统(HDFS),另一个是处理层,最初称为 Map 和 Reduce 框架(MapReduce)。我们将更多地关注 HDFS 端,因为它非常重要,目前没有其他文件系统可以取代它。然而,市场上的处理端被其他一些工具所取代,如 Spark、Flink 等。HDFS 仍然是任何大数据应用程序的主要焦点,尤其是在我们希望保留不同的数据实体(原始数据、处理后的数据等)时。).
Hadoop 一直在高速发展。即使你熟悉 Hadoop 1,也不意味着你熟悉 Hadoop 2 或 Hadoop 3。事情正在彻底改变,一些组件被替换,其他组件被删除,新功能正在添加。由于其重要性,我将确保报道这一演变。如果你还没有升级你的 Hadoop,你可能会重新考虑。
正如我在所有 Hadoop 版本中提到的,唯一保持健壮并得到良好维护而没有更换的组件是 HDFS,这是我们真正关心的。
Hadoop 1 和 Hadoop 2 的区别
任何对知识好奇的人,都想知道有什么不同?为什么那时我需要迁移到 Hadoop 2?
这个问题的答案非常简单:我们可以有多个主控作为主要的突出区别。好像答案太雾了。我将开始详细解释发生了什么。
Hadoop 1 与 Hadoop 2 的高级架构
Hadoop 2 在 Hadoop 的架构中增加了一个名为 YARN 的新层,也被称为另一个资源协商者,负责管理应用程序使用的资源,监控这些应用程序,并在 HDFS 之上调度作业[1]。该层导致详细架构中的新层次,如下所示:
- 第一层(在名称节点层):由两个主要组件组成,它们是资源管理器(YARN)和 HDFS。
- 第二层(在主节点级别):由三个组件组成,它们是节点管理器(负责管理和监控容器,容器是指 HDFS 中的一部分内存)、应用程序主(允许资源管理器与节点管理器交互)和数据节点。
- 第三层(数据节点层):由节点管理器和数据节点两部分组成。
[source = "https://www . journal dev . com/8800/Hadoop-architecture-yarn-HDFS-MapReduce"]
Hadoop 2 中引入的这种架构是实现不同目的的关键,例如:
- 支持多个名称节点,而不是一个名称节点(单点故障),在 HDFS 联合的情况下,每个名称节点都可以分配到一个特定的名称空间,而不是由一个名称节点管理 Hadoop 1 中的所有名称空间[2]。
- 支持多种编程模型,包括 MapReduce、Streaming、Graph、Spark、Storm 等。而不是单一的编程模型 MapReduce。
- 获得比 Hadoop1 更高的可扩展性。
- 在 Hadoop 1 中使用可变大小的容器而不是固定大小的槽。
Hadoop 2 和 Hadoop 3 的区别
除了 Hadoop 2 中的变化之外,我们还将讨论 Hadoop 3 中的新变化。我将区分两个版本之间的重要区别如下:
- Hadoop 3 要求最低 Java 版本为 8,而不是 Hadoop 2 的 7。
- Hadoop 3 引入了一种基于擦除编码的新机制来最小化存储(存储开销仅为 50%)并实现容错,而 Hadoop 2 使用复制来实现容错并带来更多存储(HDFS 在存储空间中有 200%的开销[3])。
- Hadoop 3 使用 YARN timeline service v2,然而,Hadoop 2 使用 YARN timeline service v1。
- Hadoop 3 使用机会容器,而 Hadoop 2 使用保证容器。
- Hadoop 3 使用数据内节点平衡,而不是 Hadoop 2 中的 HDFS 磁盘平衡器 CLI。
- Hadoop 3 使用 Linux 临时端口范围之外的更方便的默认端口,而不是像 Hadoop 2 中那样使用默认端口。
- Hadoop 3 可以实现更好的可扩展性,能够扩展到每个集群超过 10,000 个节点,而在 Hadoop 2 中只能扩展到 10,000 个节点。
在 Hadoop 上查询存储工具
在 Hadoop 生态系统中,我们注意到各种各样的工具和框架,这里我将向您介绍三种主要的数据存储和查询工具,它们都是建立在 Hadoop 之上的。这些工具将列出如下:
- Hive【4】是开源的 Hadoop 平台中用于数据汇总分析和大型数据系统查询的数据仓库系统。它将类似 SQL 的查询转换为 MapReduce 作业,以便于执行和处理大量数据。
- h base【5】是一个分布式、可扩展的 NoSQL 大数据存储,运行在 Hadoop 集群上。HBase 可以托管非常大的表—数十亿行、数百万列—并且可以提供对 Hadoop 数据的实时、随机读/写访问。
- Impala是一个 MPP(海量并行处理)SQL 查询引擎,用于处理存储在 Hadoop 集群中的海量数据。与 Hadoop 的其他 SQL 引擎相比,它提供了高性能和低延迟。根据[6], Impala 是性能最高的 SQL 引擎(提供类似 RDBMS 的体验),它提供了访问存储在 Hadoop 分布式文件系统中的数据的最快方式。****
与 Hadoop 共存的其他存储工具
尽管 Hadoop 是理解大数据存储的中心,但人们注意到 Hadoop 在安装、管理和监控方面有些复杂。除此之外,并不是所有的大数据应用程序都需要使用 Hadoop 的复杂性,因为他们可能会关心某种更轻的数据存储和更类似于数据库的东西。一些类似数据库的存储工具被称为 NoSQL 存储工具,NoSQL 不仅代表结构化查询语言。这些 NoSQL 工具将有助于实现上述关于数据复制和分区、数据可用性以及数据查询的特性。下面列出了一些最著名的 NoSQL 存储工具:
- MongoDB【7】是一个面向文档的 NoSQL 数据库,用于大容量数据存储。MongoDB 不像传统的关系数据库那样使用表和行,而是使用集合和文档。文档由键值对组成,键值对是 MongoDB 中的基本数据单元。集合包含一组文档和函数,相当于关系数据库表。它还具有查询和索引功能的高可伸缩性和灵活性。
- InfluxDB 是一个用 Go 编写的时间序列 NoSQL 数据库,针对运营监控、应用度量、物联网传感器数据和实时分析等领域的时间序列数据的快速、大规模可伸缩性、高可用性存储和检索进行了优化[8]。
- Neo4j【9】是一个 NoSQL 图形数据库。它是一个完全事务性的数据库(ACID ),以图形的形式存储数据。图由通过关系连接的节点组成。受人类思维结构的启发,它允许对复杂数据的高查询性能,同时对开发人员来说保持直观和简单。****
- Redis是一个开源的(BSD 许可的)、内存中的数据结构存储,用作数据库、缓存和消息代理。它具有内置的复制、Lua 脚本、LRU 驱逐、事务和不同级别的磁盘持久性,并通过 Redis Sentinel 和 Redis Cluster 的自动分区提供高可用性。****
摘要
每当我们构建大数据应用程序时,我们都应该记住,我们可能需要理解和应对许多工具。这些工具不仅数量多,而且版本和功能也多。我们应该小心选择正确的技术来解决匹配良好的问题。在了解 Hadoop 这个大数据时代的核心之后,我们可以清楚地注意到,发展仍在继续,每天都有新功能添加进来,因此我们必须投入时间来检查新添加的功能是否会简化我们应用程序的开发流程。此外,我还介绍了一些其他重要的工具,它们可能有助于构建所需的应用程序。
参考
[1]https://www . journal dev . com/8800/Hadoop-architecture-yarn-HDFS-MapReduce
[2]https://big data path . WordPress . com/2018/12/19/comparison-between-Hadoop-2-x-vs-Hadoop-3-x/
[3]https://data-flair . training/blogs/Hadoop-2-x-vs-Hadoop-3-x-comparison/
https://intellipaat.com/blog/what-is-apache-hive/
https://mapr.com/products/apache-hbase/
https://www.tutorialspoint.com/impala/impala_overview.htm
https://www.guru99.com/what-is-mongodb.html
从制图学到数字制图:你知道真相吗?
公平和偏见
一个在线展览反思了说服制图学的历史是如何教会我们发现视觉数据中的偏见的
《布里斯托尔信封》作者埃德·费尔伯恩(乔布森)
在疫情之前,我们已经看到了数字化的趋势。特别是像美术馆、博物馆、图书馆和档案馆这样的文化机构面临着通过数字媒体来获取其物品的批评。这些机构可以将当前的疫情危机转化为变革的机会。适应将允许以可持续的方式为任何地方的每个人保存、展示和消费遗产,迎合“期望稳定性和灵活性”的当代观众[1]。
引诱欧洲人在新英格兰定居(弯线)
当代观众还期待什么?展览提供遗产消费的方式,也应该提供研究历史的方法,作为一个重要的工具。用来思考当前的挑战,这个工具会非常方便。数字对象可以占据的“空间”是没有限制的,所以为什么不利用这种自由呢?[2]
“弯曲的线条”——一个关于“弯曲”现实的展览
波士顿公共图书馆的 Leventhal 地图中心目前正在策划一个为期一年的在线展览,名为“ 弯曲的线条:从扭曲到欺骗的地图和数据”[3]。它通过为学生提供互动材料来挑战传统的在线展示。这个想法源于“说服制图学”——地图和视觉数据如何为主观议程操纵现实的历史[3]。如果你认为你从未听说过这个,相信我,你已经看过了。新闻中的国家宣传和政治活动地图、广告或统计图表如何?
利文塔尔中心的地图策展人 Garret Dash Nelson 解释说,这个展览指导观众如何成为一个负责任的地图读者[4]:
"每张地图都注入了制作者的决策,最终呈现出一种模式、一个故事或一个论点."
1943 年《新闻地图》中的《落日之地》(弯线)
他不仅提到了中世纪的普鲁士地图或二战时期的日本帝国地图,还强调了“在一个数据和数字工具丰富的时代”,地图学的历史是多么有说服力。我们可能认为“现代”工具带来了客观性和准确性,但数据与真相的关系仍然模糊不清——无论是书面还是数字。
"你怎么知道什么是真实的,什么是扭曲的?"加勒特问道。
参观数字展览
展览的互动形式带你经历三个部分:为什么要说服?、线条如何弯曲、让信念产生的力量。有照片,描述,解释,身临其境的内容,迷你旅游等等。这迫使我们问是谁制作了这些地图,它们的动机和信念有什么意义,它们是如何“扭曲”现实的?
“参观数字展览”菜单(弯曲线条)
第一部分将审查引向某人创建地图背后的意图,例如民族主义和帝国主义地图的爱国主义。例如,“永远具有威胁性的章鱼”是一幅被广泛认可的 17 世纪俄土战争地图,使用章鱼的视觉主题来代表和夸大威胁。
永远有威胁的章鱼
第二部分深入研究了分类和量化数据的许多技术,包括交流和符号化信息的代表性选择。作为其中的一部分,Garret 解释说他们委托了一个名为 相同的数据,不同的故事 的项目来展示同一组数据如何产生不同的视觉效果。
一个例子来自马萨诸塞州跨环境、基础设施和人口统计类别的地理数据。由此,制图者被要求制作一对结论相反的地图。分析师 Maggie Owens 创建了一个显示全州有毒物质危害的地图对。一幅可视地图显示城市受污染影响最大,而另一幅显示农村地区受污染影响最大。
(左/右)马萨诸塞州的有毒污染表明城市受影响最大/ 马萨诸塞州的有毒污染表明农村地区受 Margaret Owens ( 弯线)影响最大
“我们愿意认为数字本身就能说明问题,但是每当我们使用数据时,解释者都有一个至关重要的角色,人们绘制这些地图的方式真的会影响他们带入任务中的假设,”Garret 说[4]。
最后一节讲的是真理与权力的关系;以及它在视觉上是如何表现的,触及到包括种族、语言和领土在内的主题。以特殊的教育活动结束,这让年轻的学生要求更多。
《白人至上的气候学》(弯曲线条)
为什么要关心 Covid 世界中的地图?
在一个信息无止境的时代,或者说“信息时代”,了解哪些数据的可视化表示是可信的是至关重要的[5]。在新闻中,当你看到关于新冠肺炎的选举地图或统计数据时,它们会受到偏见的影响。鉴于疫情的背景,弯曲线有一个更大的目标,如 Garret 所解释的[4]:
“我们也想将此视为促进数据素养的一种方式,这是对媒体和数据可视化的一种批判态度,以汇集地图如何产生我们的真实感的悠久历史。”
威廉·普莱费尔——图表和图形的视觉简史
加勒特是对的。而“网络上充斥着无数复杂的可视化项目”[6];看到错误信息像蜂巢爆炸一样传播,我们需要学习如何成为负责任的数据读者。视觉数据和地图的主要缺点之一是不成比例的简化论。数字、线条、点、形状和颜色声称代表了物体和它们之间的关系,“不管这些是人、它们的社会关系、股票价格、国家收入、失业统计还是其他任何东西”[6]。
在网络和新闻中,新冠肺炎地图倾向于强调一些因素,而隐藏其他因素。例如,它们通常只显示确诊病例,而不是所有的病例。这意味着,虽然声称显示一个国家的疫情状态,但他们实际上代表了该国对该疾病的测试规模和水平[8]。
冠状病毒图表如何误导我们
如果不将视觉数据与地理、社会人口统计、文化和政治决策联系起来,错误信息就会继续传播。
超越地图的天真
为什么误传会通过可视化地图持续传播?他们拥有某种力量,使人们信任他们,并倾向于“天真地”接受他们是真的[5]。视觉语言在很大程度上与科学客观性的范式有关。作为一个观众,我们往往会忘记,我们看到的数据从来没有脱离上下文、解释或说明[9]。
“数据经常以被精心制作来讲述一个特定故事的视觉化形式来传达,而在简化数据的过程中,上下文经常会丢失;类似地,数据经常被吹捧为客观的、固有的事实信息,不受人为干扰”[9]。
数据来自人民(弯线)
视觉数据受制于它所处的位置,就像所有的交流行为一样。因此,我们每天看到的新冠肺炎地图和图表并不是他们所声称的“客观”表现。我们将它们与“逻辑论证和科学启蒙”[7]联系在一起,却忘记了它们的社会、文化和政治背景。
弯线是一个强大的展览,无论是形式还是内容。它试图以新的方式利用数字自由来互动地展示历史,同时允许观众从批判的角度参与和反思历史。在一个“真理”比以往任何时候都更加遥远的时代,我们学会了辨别什么是可信的数据,什么是不可信的数据。
参考书目
[1] 创新&文化遗产研究:2018 年 3 月 20 日,布鲁塞尔皇家艺术与历史博物馆:会议报告。出版处,2018。DOI.org【CSL JSON】,https://data.europa.eu/doi/10.2777/303242。
[2]卡恩,丽贝卡。“封锁而不是封锁——评估博物馆对新冠肺炎的数字反应”。社会科学的影响,2020 年 5 月 8 日,https://blogs . LSE . AC . uk/Impact of Social Sciences/2020/05/08/locked-down-not-lock-out-assessing-the-digital-response-of-museums-to-新冠肺炎/ 。
【3】弯曲的线条:从扭曲到欺骗的地图和数据。www.leventhalmap.org,https://www . leventhalmap . org/digital-exhibitions/bending-lines/。于 2020 年 9 月 21 日访问。
[4]布利斯,劳拉。关于地图的偏见,历史教会了我们什么。城市实验室,Bloomberg.Com,2020 年 5 月 28 日。www.bloomberg.com,https://www . Bloomberg . com/news/articles/2020-05-28/how-to-解构-解读-地图。
[5]穆尼、彼得和莱文特·胡哈斯。新冠肺炎地图:基于网络的地图如何对信息时代做出贡献。人文地理对话,第 10 卷第 2 期,SAGE 出版,2020 年 7 月,第 265–70 页。贤者期刊,doi:10.1177/2043820620934926。
[6]马诺维奇,列夫。什么是观想?视觉研究,第 26 卷第 1 期,Routledge 出版社,2011 年 3 月,第 36–49 页。泰勒和弗朗西斯+奈吉姆,doi:10.1080/1472586 x . 2011.548488。
[7]多恩,萨拉。歪曲新冠肺炎:在数据设计的第二个黄金时代用图表撒谎。商业和技术交流杂志,SAGE 出版公司,2020 年 9 月,第 1050651920958392 页。贤者期刊,doi:10.1177/1050651920958392。
[8] 冠状病毒图表如何误导我们。2020. Vox ,【https://www.youtube.com/watch?v=O-3Mlj3MQ_Q】T4。
[9]雷切尔·阿泽顿。“缺失/未指明”:新冠肺炎疫情期间的人口数据可视化。商业和技术交流杂志,SAGE 出版公司,2020 年 9 月,第 1050651920957982 页。贤者期刊,doi:10.1177/1050651920957982。
编辑自MoM中的原始出版物,作为 MA 新媒体&数字文化@阿姆斯特丹大学作业的一部分,2020 年 9 月 27 日
从圆形到 ML 通过蝙蝠侠:第一部分
美丽的方程式不仅仅是艺术!
“M”、“L”和蝙蝠侠符号都是单个不等式的结果。查看图表
蝙蝠侠不等式一:查看图
简介:
这个圆圈本身很漂亮,不是吗?但是,带着一些好奇心,你可以超越一个圈子。它不需要任何微积分或任何先进的概念,只是用我们最喜欢的 10 级数学和一些美丽的想法,我们可以超越圆,甚至创建蝙蝠侠不等式。这篇文章是关于为我们想要的任何形状创建不等式。在第二部分,我们将看到如何改进和推广这个框架,并派生出机器学习中常用的函数。
这是一个从左边的曲线到右边的曲线的旅程
这里创建的所有可视化都是在公开可用的软件中生成的,如 Desmos 和 Geogebra。我建议读者继续使用这些工具玩这些方程,自己探索其中的美妙之处。
一圈之势!
谦逊的圆描述了与给定中心点等距的多个点。让我们以各种形式来看看我们熟悉的朋友。当所有的点都位于给定的距离时,让我们考虑 1 个单位,我们得到一个圆。距离小于 1 的点位于圆内,距离大于 1 的点位于圆外。在三维空间中,方程为 z = x+y–1 的抛物面与 XY 平面相交时形成我们的圆。
圆的不同视图
我们都知道圆通常采用 x +y =1 的形式。如果我们超越 2 的幂,你认为会发生什么?这就是神奇之处。让我们取 2 到 10 的值,观察会发生什么。
从 3 到 10 的幂
对于偶次幂,我们看到圆开始看起来像一个正方形,在无穷次幂时它确实变成了一个正方形。但是为什么它会这样做,尤其是在偶数倍的情况下?我们将首先试图理解曲线上的点(xn+yn=1)是如何表现的,然后研究曲线内的点的本质和属性(xn+yn<=1).
先来了解一下奇幂。如果幂是奇数,假设 x 是负的,那么 x^n 项的结果也是负的,因此 y^n 项取一个大于 1 的值,所以和仍然是 1。对于大功率,随着功率的增加,2 个数的差异变得无关紧要。让我们举个例子,如果 x⁵是-100,000,那么 y⁵的值应该是 100,001,以满足等式。但是,我们绘制的是 x 和 y,所以证明该等式正确的 x 和 y 的值是(-10,10.0000199..).这非常接近 y=-x 线。这也适用于负 y 和正 x 的情况。另请注意,功率越高,与 y=-x 的偏差越小。这在负 y 和负 x 的情况下是不可能的,这就是为什么我们在该象限中看不到函数的一部分。当 x 和 y 都是正数时,我们看到类似正方形的一部分。这是因为如果 x 明显小于 1,比如 0.7,那么 x⁵会很快变得非常小(这里是 0.168)。因此,y⁵必须是 1-x⁵,也就是 0.832,这意味着 y 将非常接近 1,但这里稍小(0.9638)。同样的逻辑反过来也适用。因此,对于远离 1 的 x 值,y 取接近 1 的值(像水平边),对于接近 1 的 x 值,y 快速下降到 0(像垂直边)。这使得曲线看起来像正方形的一部分。这可以从下面看出:
用 n=9 演示自然。
一旦理解了奇幂,理解偶幂就变得容易多了。负值的情况现在不存在了,所以整个函数在所有象限看起来都像一个正方形。这点可以从下面看出来。这是我们从现在开始要关注的。
n=10 的图表
最后,圆和方并不矛盾,他们的力量相当。希望你能接受这些观点,不要被怀疑所困扰,我们不走捷径地回到数学。
等等!!!数学宝库中还有很多东西。我们也知道如何移动坐标。左减右加。所以我们不仅可以生成一个正方形,还可以把它放在任何我们想放的地方。不仅如此,我们还可以重新缩放,从而拉伸正方形,使之成为矩形。让我们来试试:
改为矩形:(2(x-3)) ⁰+(3(y-2)) ⁰ <=1; 查看图形
到现在为止,你们中熟悉更深层次数学的人应该能够明白这与闵可夫斯基距离和F-范数中的概念有什么联系,但是我们将把它们留到将来。
超越圈子
除了圆形和矩形,我们还必须从稍微不同的角度来看待这些图表。这次我们从不等式的角度来看曲线上和小于 1 的点。如果两个正数之和小于 1,那么这两个数字都必须小于 1。类似地,如果有很多这样的项,那么所有的项都必须尽可能小,以使总和不超过 1。即使其中一项大于 1,不等式也不成立。这不是很像交集的思想吗?所选点应位于所有集合中(即所有不等式应给出接近 0 的值),如果它们甚至不在其中一个集合中,则它们不被选择(即使其中一项大于 1,不等式也不成立)。因此,上面制作的正方形可以被视为两个术语的交集区域,x^(2n) <1 and y^(2n)<1 (referred to as trenches for their shape) as shown below. Higher values of n allow the terms to be as small as possible.
The squares(z = x¹⁰+y¹⁰) as the intersection of 2 trenches made by z=x¹⁰ and z=y¹⁰
And now we have taken a humongous step. We can make very complex figures which emerge from such intersections and take our designing skills to the next level.
A diamond as the intersection of diagonal trenches: z = (y-2x)¹⁰+(y+2x)¹⁰
We can get back our graph by just making z=1:
The same figure in 2D: (y-2x)¹⁰+(y+2x)¹⁰<=1. Higher the power, better is the approximation of intersection. 视图图
让我们在一些简单的事情上试试这个策略:
这是一个简单的形状,有三条边和一个圆弧,所以很容易制作。表情:((y+x-1)/2)⁵⁰+((y-x-1)/2)⁵⁰+(y-0.5)⁵⁰+(x+y)⁵⁰<=1; 查看图表
请记住,我们制作的沟槽在以下位置有壁:y — f(x)=1 和 y — f(x)= -1。这是因为所有小于 1 的绝对值趋于零,因此是沟槽的一部分,而所有大于 1 的绝对值增加得非常快,因此形成了壁。所以我们可以使用下图所示的沟渠。
我们现在已经完全准备好制作蝙蝠侠标志,并且已经走了一半以上的路程。策略不仅仅是相交,还包括从曲线中消除区域以雕刻出形状。这是通过一个接一个地提取曲线,并对它们和它们的位置进行精炼以匹配形状来完成的。在某些地方,曲线必须反转,即大于 1 的区域必须小于 1,反之亦然。这是通过改变曲线功率的符号来实现的。请注意,这种策略可以应用于许多形状。所有这些曲线都具有一边大于 1(远离符号)而另一边小于 1(朝向符号)的性质。因此,每个部分都有自己的曲线,然后使用前面描述的大偶次幂的和来组合这些曲线。
使用以下表达式(根据曲线形状选择):
- f1(x,y):(0.5(x-1.16)(2.8))(2)+(y+1.6):右翼下边缘
- f2(x,y):(0.5(x+1.16)(2.8))(2)+(y+1.6):左翼下边缘
- f3(x,y):(0.5(y+1.6))^(8)+(x+3):左翼的左边缘
- f4(x,y):(0.5(y+1.6))^(8)+(-x+3):右翼的右边缘
- f5(x,y):y+0.6:上水平线
- f6(x,y):(3(x+0.45))^(14)-y+1:头部和翅膀之间的左曲
- 头部和翅膀之间的 f7(x,y):(3(x-0.45))^(14)-y+1:右曲线
- f8(x,y):e((3(y-0.1)-258.18((1.9x+0.1)(1.9x-0.1))(1.6))):形成了头和耳朵
当所有这些曲线组合在一起时,得到下图:
请注意,边上有额外的位,但原始功能是完整的。
为了去除多余的位,通过添加另一项来清理函数,该项在我们想要的形状附近给出接近 0 的值,而在我们不想要的位置给出大于 1 的值。这使得最终数字为:
上图经过清洗,有如下等式(第一项多余);查看图形;第一学期做什么?它不会杀死我们的曲线,所以它只是使它更强(通过消除不需要的部分)。
我们可以分别识别曲线的所有部分,如下所示:
用不等式表示的 f(x,y)=1 形式的所有曲线
结论和下一步
我们刚刚获得了对圆和类似的高偶次幂不等式的深刻理解。我们理解了为什么他们的行为像不等式的交集,并通过创造我们自己的蝙蝠侠不等式掌握了这一点。除非有人去做,否则一切都是不可能的。嗯,蝙蝠侠方程式是十年前创立的,所以我们尝试了蝙蝠侠不等式。但是,我们仍然不得不与大国打交道,不得不削减我们的规模,这个过程似乎仍然很复杂。本博客的第二部分将消除所有这些挑战,并简化一切。它还将以 Softmax(我们的分类朋友)、Softplus(众所周知的激活函数)、log-sum-exp(常用函数和 Softmax 之父)和其他相关方向的形式解释这些思想如何与机器学习相关。
数学在申请前是最重要的。而且我向你保证,申请来了!
参考
[1] J.S. Grover,代数表达式的可微集合运算(2019);Arxiv 符号计算。
[2] K.M .肯丁,单方程可以画图 (1991)。大学数学杂志 22.2:134–139。
从圆形到 ML 通过蝙蝠侠:第二部分
更多的艺术!在 ML 中衍生美。
“M”、“L”和蝙蝠侠符号都是单个不等式的结果。查看图表
背景
等等!上面的等式和我们上次发现的不一样吗?是的,非常不同,但看起来还是一样的,或者更好一点。万一你想知道我在说什么,请参考本系列的第一部分。这里陈述的许多观点都来自那篇文章,并且解释得非常清楚。主要的问题是:为什么圆变得像正方形,我们如何把它看作是沟渠的交叉点,以及我们如何通过交叉这些沟渠来构建我们自己的图形和方程。
挑战
我们之前用来制作图表的沟渠(左边)在我们的蝙蝠侠(右边)中造成了额外的区域
在战壕里工作并不是一件快乐的事情,不是吗?老实说。他们有两面墙,而我们通常只用一面。另一个只是徘徊,有时会产生不必要的区域。记住,我们也因为同样的原因不得不修剪我们的蝙蝠侠。接下来,我们只能执行战壕的交集和否定(翻转力量的符号),但它们的联合仍然有点挑战性,但非常有用。强大的能力带来了巨大的计算困难。将我们的输入提升到非常高的幂是不常见的,并且在计算上也不是非常有效。因此,我们先前所获得的范围受到了我们设计技巧的限制。
数学的宇宙集合是无限的,我们永远无法将它表达为我们有限思想的结合。所以,让我们开始寻找应对挑战的解决方案吧!
从战壕到边界
请记住,每当权力变得太大,无法控制,对数和指数来拯救。有壕沟的根本原因是当使用大的偶次幂时,会形成两堵墙。一个在 y-f(x)=1(我们一般用这个),另一个在 y-f(x)=-1(我们一般弃用这个)。因此,我们必须做一些改变,使每个沟槽只有一面墙(这使它只是一面墙)。我们可以很容易地做到这一点。只是用 e^(nx).代替 x^(2n)一切正常的主要原因是,对于大于 1 的绝对输入值,我们的函数会快速增加到 1 以上,而对于小于 1 的输入值,我们的值接近于零。在 e^(nx 的情况下)对于正 x,我们的输出值很快超过 1,而对于负 x,它们接近于零。第一个挑战解决了!指数是常用的,并且有快速的实现。这是一个很好的财产,不是吗?
一堵墙总是比一条沟好,尤其是当没有人需要为此付钱的时候(至少在我们的例子中不是计算上)。
补集、交集和并集
一旦我们有了这个合适的工具,我们就能明白我们能用它做什么伟大的事情。我们刚刚定义的边界对于负 x 有接近于零的值,对于正 x 趋向于无穷大,那么让我们来理解什么是集合。这里的集合本质上是一个类似 y≤x 或 x +y -1≤0 的不等式。这些集合的边界就是我们想要表现的。因此,我们可以乘以大的 n,并对两边取幂来得到我们的边界。因此,y-x≤0 将看起来像 e^(50(y-x))≤1,类似于(y-x)⁵⁰≤1(我们以前的一个战壕边界)。我们前面看到的逻辑同样适用于这两种情况。
让我们看看集合的补集,我们可以像上次一样,通过简单地改变幂的符号来得到它。
接下来,让我们看看我们最喜欢的十字路口。这和我们之前推导的一样,因为小数字之和小于 1 的逻辑没有什么不同。这可以从以下几个方面来看:
最后是我们的新人,尤宁。我们来推导一下。根据德-摩根定律,我们知道 AUB = (A'∩B ')'。因此,这意味着集合的逆和的逆。啊啊!这就像你如何评估并联电阻的电阻(1/Rt=1/R1+1/R2)。或者,对于熟悉的人来说,是调和平均数而不是总和。让我们看看:
还有一个很重要的观察。集合内点的值趋于零,集合外点的值趋于无穷大的性质也适用于上述集合运算的结果。因此,这些集合运算也是可重复的,无需再次求幂。这意味着我们可以通过逐一应用上述集合运算来计算更复杂的运算,如 AU(B∩(CUD))。
代数和集合论中各种想法的结合引导我们通过数学和创造性艺术的狭窄交叉。总结我们所有的高能量想法,我可以说与我们目标的差异将很快趋于零。还有最后一项活动,我想对其进行指数运算,我们将为机器学习的应用做好准备。
让我们做点什么吧!
让我们制作下面的拼图:
上面的等式可以通过首先创建一个正方形,然后与两个圆(突出的那些)合并,接着与另外两个圆(移除的那些)的补集相交来获得。设正方形的 4 条边分别表示为 A、B、C、d,每条边是一条直线。进行并的圆被表示为 E 和 F,而被去除的圆被表示为 G 和 H,因此上图为:((A ∩ B ∩ C ∩ D) U E U F) ∩ G' ∩ H '。
让我们来代表这些集合:
- 答:e^(50(x-1)
- B: e^(-50(x+1))减号来改变集合的方向(使其面向图内)
- 丙:e^(50(y-1))
- D: e^(-50(y+1))减号来改变集合的方向
- E: e^(50((x+1) +y -0.25))
- F: e^(50((x) +(y-1) -0.25))
- G: e^(50((x-1) +(y) -0.25))
- H: e^(50((x) +(y+1) -0.25))
表演(A ∩ B ∩ C ∩ D)给出:(e(50(x-1))+e(-50(x+1))+e(50(y-1))+e(-50(y+1)))
接下来是与圆结合,从而给出:
((e(50(x-1))+e(-50(x+1))+e(50(y-1))+e(-50(y+1)))-1+e(-50((x+1)+y -0.25))+e(-50((x)+(y-1)-0.25)))-1
最后,与另外两个圆的补集相交,得到上图所示的理想方程。
所有上述操作也与我们之前所学的相一致,因此正方形可以恢复其真实的形状:x⁵⁰+y⁵⁰=1.给出了如下所示的相同图形的替代等式。注意第一项。
((x⁵⁰+y⁵⁰)-1+e(-50((x+1)+y -0.25))+e(-50((x)+(y-1)-0.25)))-1+e(-50((x-1)+(y)-0.25))+e(-50((x)+(y+1)-0.25))≤1
真实应用
请记住,如果我们可以创建好看的图形和它们的方程,那么我们也可以创建一些在各个领域中常用的非常有趣的函数,甚至为我们自己创建一些函数。我的背景是机器学习,因此我熟悉在我的领域中使用的一些功能。
导出 Log-sum-exp 和 Softmax
我们都已经学习了很多关于 max 函数的知识,它接受多个数字,然后吐出最大的一个。在机器学习的许多应用中,我们希望最大值运算不仅尽可能接近实际的最大数,而且与非最大数有某种关系。这些数字越接近最大值,它们对结果的贡献就越大。这是很重要的,因为它允许梯度在反向传播或其他训练算法期间也通过非最大值项传播。不深入 ML,我们可以说我们需要一个最大运算的近似值,它考虑了所有的项。这种固定(硬)决策函数的近似,如 max、if-else、排序等。叫做软化。
max 本质上是什么?它是单个函数的联合,最大的一个在输出端显示。请注意,union 运算中最大的函数下面会自动包含较小的函数。对于一维示例,max(y=1,y=2,y=3)是 y=3。我们也可以把这个写成并集的边界(y≤1,y≤2,y≤3)。联合是 y≤3,所以边界是 y=3。让我们想象一些更真实的函数:
深蓝色曲线代表 4 条输入线的最大值。因为这等同于对给定输入 x 的每个输出执行 max,所以它被称为逐点 max。
设输入函数为 f(x),g(x)和 h(x)。我们可以把它们表示为 y-f(x)≤0,y-g(x)≤0,y-h(x)≤0。让我们执行这些边界的并集,以生成最大值函数的近似值:
(e(-n(y-f(x))+e(-n(y-g(x))+e(-n(y-h(x)))-1≤1
取边界上的点,我们得到:(e(-n(y-f(x))+e(-n(y-g(x))+e(-n(y-h(x)))-1=1
重新排列结果,使其成为 x 的函数,得到:
y = ln(e(nf(x))+e(ng(x))+e^(nh(x)))/n
这实质上是对数和指数的形式。1/n 通常指温度,记为 T,通常取为 1。对于多个术语,我们得到:y=ln(sum(e^xᵢ,所有 I)。由此导出其名称 log-sum-exp (LSE)。
之前说的软化和 ML 是怎么回事?请注意,log-sum-exp 始终大于实际最大值。这种差异解释了第二大项、第三大项等等。如上式所示,输出是所有项的混合,但较大项的贡献要比较小项大得多,因为我们已经逼近了最大值运算。记住!!n 的值越大,圆越接近正方形。类似地,较大的 n 意味着较大的项比较小的项贡献更大,从而使近似更精确。注意弯曲的可微角,这是我们近似的另一个好处,在 ML 中非常有用。顺便问一下,对数和指数的导数是什么?是我们共同的朋友 Softmax (对,分类层一)。我希望现在你能明白这个著名的函数是如何得到它的名字的。是的,我知道这不是维基百科的文章,所以我会继续。
不同 n 值的图表。随着 n 值的增加,近似性提高;查看图表
对数和指数方程的应用并不少见。它的许多属性都在它的维基百科页面上讨论过。也有论文直接用它作为架构,就像用它作为泛凸逼近器和泛函数逼近器一样。这个函数有更多的应用,因此它在从 Numpy 到 Pytorch 和 Tensorflow 的几乎所有 ML 库中都内置了有效的实现。即将到来的应用程序就像这一个的特例。
导出软加激活函数
软加激活是神经网络中使用的一种非线性类型。一种常见的非线性是 ReLU,其形式为 max(0,x ),非常常用。在这篇论文中描述的许多条件下,我们需要近似 ReLU 函数。不要深究激活函数和 ML 细节,我们可以通过用我们刚刚学到的方法近似 ReLU 函数来处理这个挑战。
因此,我们必须近似 max(0,x)。为什么不直接引用我们的对数和指数的推导。需要的两个分量是 y≤0 和 y-x≤0。这将因此给联盟作为(e(-ny)+e(-n(y-x)))^-1≤1.这将因此给我们以下等式:y = ln(1+e^(nx))/n.当 n 是 1 时,这被称为软加激活函数。除了最初的论文,这个函数还被用于其他激活函数,如 swish 、 mish 和 soft++ 。
随着 n 的增加,近似性提高;查看图表
我们甚至可以超越并创造出我们自己的 softplus 变种,称之为 leaky-softplus。本质上是使用相同程序的 leaky-ReLU ( max(0.05x,x))的近似值。该函数采用以下形式:y = ln(e(0.05nx)+e(nx))/n.,根据通常的惯例,我们设 n=1。结果如下所示。测试和实验留给读者。;-)
不同 n 下的漏软加;查看图表
推导对数损耗
在许多回归任务中,使用被称为绝对损失的损失函数,其本质上是误差的平均绝对值。这种损失在零处是不可微的,并且对于使用高阶导数的训练算法也没有二阶导数。Log-cosh 通过对其进行近似处理很好地处理了这些问题,因此看起来像接近零的均方误差和远离它的绝对损失。更多信息可在这篇文章中了解。因此,我们必须近似|x|,它本质上是 max(x,-x)。我们可以用同样的老把戏得到:y=ln(enx+e-nx)/n.我们还没有达到我们的目标。我们现在可以加减 ln(2)/n,给我们:ln((enx+e-nx)/2)/n+ln(2)/n.下一步是使 n=1,忽略常数,因为它不影响训练过程。这给了我们:ln((ex+e-x)/2)也就是 ln(cosh(x))。这是我们的对数损失函数。
注意与 0 附近的抛物线相似。这就是我们进行 ln(2)调整的原因。查看图表
结论
纯粹出于好奇的简单想法可以有非常广泛的应用。好奇心和它能给我们的东西没有上限。希望这些文章为您提供了新的工具和视角,您可以将其应用于科学、工程和艺术等不同的领域。对于好奇的人,我想留下一个很好的资源来提高您对这一思想的理解:代数表达式的可微集合运算。
挑战
用一个不等式得出这个数字:
用一个不使用模函数的不等式制作这个图形:
这个图形向四面八方无限延伸。解决方案。
从 CityGML 三维城市模型到三维网络应用
实践教程
在 Web 应用程序上可视化 CityGML 的分步指南——荷兰海牙市的一个示例区域。
本教程的预期输出截图——在海牙地区使用 3D 语义建筑模型的 3D 网络应用(作者)
基于虚拟地球的 3D 可视化最新技术是一个独特的机会,可以促进各种应用领域的高级分析和可视化任务,如城市规划、室内/室外步行导航、环境模拟、文化遗产或设施管理。让这个概念成为现实的一个核心数据是由开放地理空间联盟(https://www.ogc.org/ OGC—)开发的 CityGML 模型。CityGML 是用于描述 3D 地理空间化城市模型的全球数据模型模式。公开提供开源 CityGML 模型的城市越来越多。
本文将指导您如何基于这些 CityGML 3D 城市模型数据集使用 CesiumJS 创建交互式 3D web 地图。本指南材料最初是(由作者)特别为 2020 年荷兰大地测量和地理信息中心(NCG) 研讨会的研讨会制作的。
架构和工作流程
基于这些 CityGML 3D 城市模型使用 CesiumJS 创建交互式 3D 网络地图的工作流程(作者)
3D 网络 app 的整体系统架构如上图所示。它包括四个主要组件:CityGML 数据集、3D Tiles 数据集、Web 服务器和用户。
- 组件 1) CityGML 3D 城市模型
- 组件 2) 3D 瓦片城市模型
- 组件 3)网络服务器
- 组件 4)用户
因此,让我们开始一起创建每个组件💻
组件 1) CityGML 3D 城市模型
我们可以下载 CityGML 格式的 3D 城市模型。在这篇文章中,我选择了海牙地区的 3D 城市模型,因为它是一个紧凑的模型。
- 从下载部分的https://den haag . data platform . nl/#/data/36049 d1a-4a 0f-4c 5d-8 ADB-21 dbfb 7252 F9下载 CityGML 数据集。
当然,您也可以自由探索其他 CityGML 数据集。越来越多的城市公开提供数据集,如下文所列:
开源 3D 城市模型的完整列表(2020 年 10 月更新)
towardsdatascience.com](/open-source-3d-semantical-building-models-in-2020-f47c91f6cd97)
组件 2) 3D 瓦片城市模型
为了优化 3D web 可视化,必须将 CityGML 转换为 3D 切片格式。有几种工具可以执行这种转换。在这篇文章中,我们将使用 FME,它有一个开放免费许可证至少可以免费使用一年,供家庭、研究人员等使用。
用 FME 将 CityGML 模型转换成 3D 瓦片
- 从打开 FME 工作台开始,将所有 CityGML 模型拖放到 FME 窗口。
- 选择输入格式“CityGML”和工作流选项“单一合并要素类型”。
- 点击“添加一个新的作家”按钮,并选择格式“铯三维瓷砖”
- 工作流应该如下图所示。单击运行,然后等待转换完成。然后,最终的 3D 平铺城市模型将位于您输入的目标文件夹中。
组件 3) Web 服务器
使用 CesiumJS 库准备 3D Web 应用程序
在这一步中,我们将使用 CesiumJS 库创建一个包含 3D Web Globe 的 HTML web 文档。你可以使用任何你喜欢的代码空闲或编辑器。我的选择是 VS 代码。然后,创建一个名为“denHaagApp.html”的文件。您可以使用自己喜欢的名称创建文档,并遵循下面的示例 HTML 代码。
- CesiumJS 查看器(第 13 行)是构建具有灵活设置的 3D globe 的主要组件(如本例中的第 14 到 21 行)。您可以查看 CesiumJS API 文档了解更多可用设置。
- 3D Tiles 数据可以作为 tileset 加载到 CesiumJS 查看器中(第 23 到 25 行)。不要忘记在第 24 行指定目标 Tileset.json 的 URL。您可以查看文档 CesiumJS API 文档了解更多关于 3D Tiles 数据集的设置。
在 Web 服务器上托管 3D Web 应用程序
这一步,我们将在 Web 服务器上托管第 2 步中的 Web 应用程序和第 1 步中的 3D Tiles 城市模型。你可以自由使用任何你喜欢的网络服务器。在这个例子中,我们使用 XAMPP 开源 web 服务器。(可以从https://www.apachefriends.org/index.html那里得到)
- 安装 XAMPP。打开 XAMPP 控制面板并启动 APACHE web 服务器。或者,您可以通过C:\ xampp \ Apache \ bin \ httpd . exe 手动启动 Apache。
用 XAMPP 控制面板启动 Apache web 服务器。(作者)
- 在 macOS 和 Linux 中,您可以使用终端输入以下命令来触发 Apache HTTP 服务。
**$ sudo apachectl -k start** // start Apache **$ sudo apachectl -k stop** // stop Apache **$ sudo apachectl -k restart** // restart Apacheor **$ sudo /usr/sbin/apachectl -k start** // start Apache **$ sudo /usr/sbin/apachectl -k stop** // stop Apache **$ sudo /usr/sbin/apachectl -k restart** // restart Apache
- 将最后一节中的 web 文档(【denHaagApp.html】)和组件 2)中的 output 3D Tiles city models 文件夹放在 C:\xampp\htdocs 目录中。
复制并粘贴 3D 瓷砖模型和 web 文档。(作者)
- 在 HTML web 文档中,将 URL 值更新到 htdocs 文件夹中 3D Tiles 模型的 tileset.json 文件。例如,如果您的 3D Tiles 目录位于 C:\ xampp \ htdocs \ 3D tile \ tileset . JSON .您应该将 URL 值设置为"。/3dtile/tileset.json "或"http://localhost/3d tile/tileset . JSON"因为 APACHE 将为相对于" http://localhost "的 htdocs 目录中的所有内容提供服务。
组件 4)用户
前三个组件完成后,我们可以通过 Web 服务器测试 3D Web 应用程序。您可以在您的 web 浏览器上访问您的 3D web 应用程序可视化 3D 城市模型,网址为http://localhost/denhaagapp . html
用本地主机测试 3D Web App。(作者)
结论
本文提供了从 CityGML 语义 3D 城市模型创建 3D 基于 web 的应用程序的分步教程。该指南首先介绍了 CityGML 数据模型。然后,引入 FME 作为从 CityGML 到 3D 瓦片格式的转换工具。最终的 3D web 应用程序由 CesiumJS 库创建,托管在 Apache HTTP web 服务器上。
作者
Thunyathep Santhanavanich(JOE)博士候选人
地理信息、计算机科学和数学系,
应用科学大学,斯图加特,Schellingstr。24、D-70174 斯图加特
thunyathep . santhanavanich @ hft-Stuttgart . de
⭐需要我协助你的项目吗?在这里找到我⭐
引用
[1]吴,何,何,龚等(2010).公众参与城市规划过程的基于虚拟地球的三维可视化和交互式框架。计算机,环境和城市系统,34(4),291–298。https://doi.org/10.1016/j.compenvurbsys.2009.12.001
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Joe t . Santhanavanich
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@joets/membership)
从云到设备
人工智能和机器学习的未来在边缘
在设备上训练 ML 模型的最新技术的简要概述。要进行更全面的调查,请阅读我们关于本主题 的 全文。
我们被智能设备包围着:从手机、手表到眼镜、珠宝,甚至衣服。但是,虽然这些设备小巧而强大,但它们仅仅是计算冰山的一角,这个冰山始于你的指尖,终于遍布世界各地的巨大数据和计算中心。数据从设备传输到云,在云上用于训练模型,然后再传输回来部署到设备上。除非用于学习简单的概念,如唤醒词或识别你的脸来解锁你的手机,否则机器学习在计算上是昂贵的,数据在转化为有用的信息之前别无选择,只能传播数千英里。
这种从设备到数据中心再回到设备的旅程有其缺点。用户数据的隐私和安全性可能是最明显的,因为这些数据需要传输到云中并存储在那里,通常是无限期的。用户数据的传输容易受到干扰和捕获,存储的数据也有可能遭到未经授权的访问。但是还有其他明显的缺点。基于云的 AI 和 ML 模型具有更高的延迟,实施成本更高,缺乏自主性,并且根据模型更新的频率,通常更不个性化。
随着设备变得越来越强大,通过将部分或全部模型开发转移到设备本身来解决云模型的缺点成为可能。将模型开发转移到设备上通常被称为边缘学习或设备上学习。进行边缘学习的最大障碍是模型训练,这是模型开发过程中计算量最大的部分,尤其是在深度学习时代。通过向设备添加更多资源或者更有效地使用这些资源或者两者的某种组合,可以加速训练。
将模型开发转移到设备上通常被称为边缘学习或设备上学习。
图 1:边缘/设备上学习的各种方法的分层视图。灰色方框是本文和相应论文中涉及的主题。作者图片
图 1 给出了改进设备上的模型训练的方法的分层视图。左边是与实际芯片组一起工作的硬件方法。该领域的基础研究旨在改进现有的芯片设计(通过开发具有更多计算和内存、更低功耗和更小尺寸的芯片)或开发具有新型架构的新设计,以加快模型训练。虽然硬件研究是改善设备上学习的有效途径,但它是一个昂贵的过程,需要大量的资本支出来建立实验室和制造设施,并且通常涉及长时间的开发。
软件方法包含了该领域当前工作的很大一部分。每种机器学习算法都依赖于一小组计算库来高效执行一些关键操作(如神经网络中的乘法-加法)。支持这些操作的库是硬件和算法之间的接口,并允许不基于任何特定硬件架构的算法开发。然而,这些库被大量调整到执行操作的硬件的独特方面。这种依赖性限制了新库所能获得的改进。当涉及到在边缘上改进 ML 时,软件方法的算法部分得到了最多的关注,因为它涉及到机器学习算法本身的开发和改进。
最后,理论方法有助于指导最大似然算法的新研究。这些方法提高了我们对现有技术的理解,以及它们对新问题、环境和硬件的可推广性。
这篇文章集中在算法和理论方法的发展。虽然硬件和计算库同等重要,但考虑到新硬件的长交付周期以及硬件和库之间的相互依赖性,算法和理论空间的最新发展变化更快。
算法
设备上 ML 的大部分工作都是部署模型。部署侧重于使用模型量化和模型压缩等技术来提高模型大小和推理速度。对于设备上的训练模型,需要在模型优化和超参数优化(HPO)等领域取得进展。但是,这些领域的进步提高了准确性和收敛速度,通常是以计算和内存使用为代价的。为了改进设备上的模型训练,重要的是具有知道这些技术将在其中运行的资源约束的训练技术。
为了改进设备上的模型训练,重要的是具有知道这些技术将在其中运行的资源约束的训练技术。
进行这种资源感知模型训练的主流方法是设计满足代理软件中心资源约束而不是标准损失函数的 ML 算法。这种替代测量被设计成通过渐近分析、资源剖析或资源建模来近似硬件约束。对于给定的以软件为中心的资源约束,最先进的算法设计采用以下方法之一:
轻量级 ML 算法 —现有算法,如线性/逻辑回归或支持向量机,具有较低的资源占用,并且不需要对资源受限的模型构建进行额外的修改。这种低占用空间使得这些技术成为构建资源受限学习模型的简单而明显的起点。但是,如果可用设备的资源小于所选轻量级算法的资源占用,这种方法将会失败。此外,在许多情况下,轻量级 ML 算法导致模型复杂度低,可能无法完全捕捉底层过程,从而导致拟合不足和性能不佳。
降低模型复杂性 —控制学习算法的大小(内存占用)和计算复杂性的更好方法是通过约束模型架构(例如,通过选择更小的假设类)。这种方法具有额外的优势,即这些模型可以使用传统的优化例程来训练。除了模型构建,这是为模型推理部署资源高效模型的主要方法之一。最重要的是,这种方法甚至可以扩展到深度神经网络(DNNs ),如图 2 所示,这是朝着更小、更快、更精简架构的缓慢但稳定的进展。这一进展得益于神经结构搜索(NAS)技术的使用增加,该技术显示出对更小、更有效的网络的偏好。与轻量级 ML 算法方法相比,模型复杂性降低技术可以适应更广泛的 ML 算法类别,并且可以更有效地捕获底层过程。
图二。模型复杂性按时间顺序演变的球形图。最高精度是在 ImageNet 数据集上测量的。模型复杂性由 FLOPS 表示,并由球的大小反映。精确度和误差来自模型的原始出版物。模型的时间是相关联的出版物首次在线可用的时间。郭俊耀图片。
修改优化例程 —算法上最重要的进步是专门针对资源高效模型构建的优化例程的设计,其中在模型构建(训练)阶段纳入了资源约束。这些方法不是预先限制模型架构,而是可以调整优化例程以适应任何给定模型架构(假设类)的资源约束。
资源受限的以模型为中心的优化例程关注于通过随机舍入、权重初始化或通过将量化误差引入梯度更新来提高将在训练后量化的模型的性能。分层训练和用计算换取内存的技术也很流行,这两种技术都试图减少与训练 dnn 相关的计算需求。在某些情况下,这种方法还可以动态地修改架构以适应资源约束。尽管这种方法提供了更广泛的模型类别选择,但设计过程仍然依赖于特定的问题类型(分类、回归等)。)并取决于所选择的方法/损失函数(线性回归,回归问题的岭回归)。
资源受限的通用优化例程,如 Buckwild!SWALP 致力于通过使用低精度算法进行梯度计算来减少模型训练的资源占用。另一条工作路线涉及实现定点二次规划(QP ),例如用于求解线性模型预测控制(MPC)的 QSGD 或 QSVRG。这些算法中的大多数涉及修改凸优化的快速梯度方法,以在资源受限的设置下在有限次迭代中获得次优解。
数据压缩 —数据压缩不是限制模型的大小/复杂性,而是在压缩数据的基础上构建模型。目标是通过固定的每样本计算成本来减少数据存储和计算,从而限制内存使用。一种更通用的方法包括采用高级学习设置,以适应样本复杂度更小的算法。然而,这是一个更广泛的研究课题,不仅仅局限于设备上的学习。
数据观察的新协议 —最后,完全改变传统数据观察协议的全新方法是可能的(如在批处理或在线设置中 i.i.d .数据的可用性)。这些方法由潜在的资源约束学习理论指导,该理论根据泛化能力捕捉资源约束和模型的良好性之间的相互作用。与上述方法相比,该框架提供了一种通用机制来设计资源受限算法,用于更广泛的学习问题,适用于针对该问题类型的任何方法/损失函数。
挑战如果没有恰当地抽象出硬件依赖性,相同的模型和算法在不同的硬件上可能会有非常不同的性能特征。虽然新的损失函数可以考虑这种依赖性,但它仍然是一个相对较新的研究领域。在许多情况下,假设可用于培训的资源预算不会改变,但通常情况下不会。我们的日常设备通常是多任务的——查看电子邮件、社交媒体、给人发消息、播放视频……不胜枚举。这些应用和服务在任何给定时刻都在不断争夺资源。将这种不断变化的资源状况考虑在内,对于有效的边缘模型训练来说是一个重要的挑战。
最后,需要改进的模型分析方法来更准确地计算算法的资源消耗。这种测量的当前方法是抽象的,并且集中于应用软件工程原理,例如渐近分析或像 FLOPS 或 MACs(乘加计算)这样的低级测量。这些方法都没有给出资源需求的整体概念,并且在许多情况下代表学习期间系统所需的总资源的微不足道的一部分。
理论
每一种学习算法都是基于一种保证其性能某些方面的基本理论。该领域的研究主要集中在可学性——开发框架来分析算法的统计方面(即错误保证)。虽然传统的机器学习理论是大多数当前方法的基础,但开发包含资源约束的新的可学习性概念将有助于我们更好地理解和预测算法在资源受限的环境下将如何表现。大多数现有的资源受限算法可以分为两大类理论
传统学习理论 —大多数现有的资源受限算法是根据传统的机器学习理论(如 PAC 学习理论、错误界限、统计查询)设计的。这种方法的局限性在于,这些理论主要是为分析用于模型估计的算法的误差保证而建立的。资源约束对算法泛化能力的影响没有通过这样的理论直接解决。例如,使用降低模型复杂性的方法开发的算法通常采用两步方法。首先,假设类的大小被预先限制为那些使用较少资源的假设类。接下来,设计一种算法来保证该假设类中的最佳模型。这种框架所缺少的是错误保证和资源约束之间的直接相互作用。
资源受限的学习理论 —更新的学习理论试图克服传统理论的缺点,特别是因为新的研究表明,在资源受限的设置下,学习假设类可能是不可能的。早期的大多数算法假设新的数据观察协议都属于资源受限理论的范畴。通常,这种方法修改了以批处理或流式方式呈现的 i.i.d .数据的传统假设,并引入了限制该方法所使用的存储器/空间占用的数据可观察性的特定协议。这些理论提供了一个平台,在内存受限的设置下,利用现有的计算高效的算法来建立具有强错误保证的机器学习模型。著名的资源受限学习理论包括有限注意力焦点(RFA)、基于新的统计查询(SQ)的学习范式,以及将假设类建模为假设图的基于图的方法。分支程序在资源约束(记忆)下以矩阵的形式(与图相反)翻译学习算法,其中在矩阵范数的稳定性(以其最大奇异值的上界的形式)和具有有限记忆的假设类的可学习性之间存在联系。虽然这种理论驱动的设计提供了一个通用框架,通过该框架可以为广泛的学习问题设计算法,但是迄今为止,基于这些理论开发的算法非常少。
挑战
结论
当我们把第一代 iPhones 放进口袋时,充满智能设备的未来还是科幻小说中的东西。13 年后,设备变得更加强大,现在承诺人工智能和人工智能的力量就在我们的指尖。然而,这些新发现的能力是由大规模计算资源(数据中心、计算集群、4G/5G 网络等)支撑的门面,这些资源将人工智能和人工智能带入了生活。但是,只有当设备能够切断它们和云之间的生命线时,它们才能真正强大。这需要在这些设备上而不是在云中训练机器学习模型的能力。
迄今为止,在设备上训练 ML 模型仍然是一种学术追求,但随着智能设备数量的增加和硬件的改进,人们对在设备本身上执行学习产生了兴趣。在行业中,这种兴趣主要是由硬件制造商推动的,这些硬件制造商推广针对特定数学运算进行优化的人工智能专用芯片组,以及主要在计算机视觉和物联网领域为特定利基领域提供特别解决方案的初创公司。从 AI/ML 的角度来看,大部分活动位于两个领域——开发可以在资源约束下训练模型的算法,以及开发为这种算法的性能提供保证的理论框架。
在算法层面,很明显,当前的努力主要针对利用已经轻量级的机器学习算法,或者以减少资源利用的方式修改现有算法。在我们能够在边缘上一致地训练模型之前,存在许多挑战,包括需要将算法与硬件解耦,以及设计捕捉资源约束的有效损失函数和度量。同样重要的是,扩展对具有低样本复杂度的传统以及高级 ML 算法的关注,并且处理资源预算是动态的而不是静态的情况。最后,提供一种简单可靠的方法来分析资源约束下的算法行为将会加快整个开发过程。
资源受限算法的学习理论关注的是算法在资源受限情况下的不可学性质。自然的下一步是找出能够保证算法可学性和相关估计误差的技术。现有的理论技术也主要关注这些算法的空间(存储)复杂性,而不是它们的计算要求。即使在可以确定满足资源限制的理想假设类别的情况下,也需要进一步的工作来从该类别中选择最佳模型。
尽管有这些困难,边缘机器学习的未来是令人兴奋的。即使是深度神经网络,模型规模也一直在下降。苹果的 Core/CreateML 等主要平台都支持设备上模型的再训练。虽然模型的复杂性和训练制度继续增长,但出于隐私和安全、成本、延迟、自主性和更好的个性化的原因,我们可能会继续看到将计算从云卸载到设备的趋势。
本文由 Sauptik Dhar、Junyao Guo、Samarth Tripathi、Jason Liu、Vera Serdiukova 和 Mohak Shah 供稿。
如果你有兴趣对边缘学习进行更全面的调查,请阅读我们关于这个话题的 全文 。
从相关到因果
如何避免常见的陷阱,并从相关性到因果关系?
在现实生活和商业中,我们经常想知道具体行为的偶然联系。我们想知道新的政府政策是否在减少贫困,上私立大学是否会增加我们未来的收入,或者我们在应用程序中推出的新功能是否会增加销售额。
基本术语
相关性是指一对变量线性相关的程度。
因果关系暗示了两个变量之间的因果关系,意味着一个变量的变化会引起另一个变量的变化。
相关性并不意味着因果关系
相关性并不意味着因果关系一定是你听说过的。那到底是什么意思?如果 A 与 B 相关,这可能意味着 A 导致 B(因果关系)。但它也可能意味着所有这些其他事情——B 导致 A(反向因果关系),两者可以互为因果(双向因果关系),C 导致 A 和 B(共同的因果变量)或只是 A 和 B 之间的巧合关系(虚假相关)。下面是一个来自有趣的网站的虚假关联的例子,它收集了一些荒谬的关联。
虚假相关的一个例子
在美国,一所精英私立四年制大学比公立大学要贵得多。在本州上公立大学的人通常每年要少付 20,000 美元。那可是一大笔钱啊!但是私立大学可能更好,因为它有更杰出的教师、更好的设施和更聪明的同龄人,这导致了一个合理的假设,即它可以给你未来的收入带来显著的增长。如果你比较两个群体之间的收入,那些上私立大学的和那些上公立大学的,它确实揭示了一个有利于私立大学的巨大差距。
其他条件不变的意思是“所有其他事情都一样”,这是因果推理的核心思想。这里的比较是其他条件不变吗?私立大学通常更具选择性,要求更高的 SAT 分数,让更聪明的学生去那里。此外,事实上他们花费更多,使得去那里的普通学生更富有。通常来说,经济背景较好的聪明人比其他人挣得多,不管他们上的是什么大学。这里的因果关系问题是,如果一个学生在“其他条件相同”的情况下去了公立大学和私立大学,那么收入会有什么不同?当然,我们不能在同一个学生身上观察到两者。
观察行为的平均差异=平均因果效应+选择偏差
为了从观察到的差异中获得偶然效应,你需要消除选择偏差。这方面的黄金标准是随机对照试验(RCT)。随机分配一些人,给他们应用程序中的新功能,称他们为治疗组。将他们与另一组随机分配的没有新特征的人进行比较,称他们为控制组。当你比较两组之间的销售差异时,你会发现你的新功能对销售的因果影响。随机分配确保了选择偏差在平均水平上相互抵消,并且假设你的群体代表了你的真实群体,它留给你因果效应。
媒体经常忽略这一点,用吸引人的标题暗示因果关系。看看《赫芬顿邮报》这篇题为狗能帮你活得更久的文章。这是基于一项研究得出的结论,养狗可以降低 24%的全因死亡率。然而,它也提到“一个可能的限制是分析没有针对混杂因素进行调整”。这意味着这是一项没有考虑选择偏差的观察性研究。养狗的人比不养狗的人更富有、更快乐、锻炼更多,这可能是他们活得更久的真正原因。
有时影响更可怕——研究表明,接受激素替代疗法(HRT)的女性患冠心病(CHD)的几率更低。这导致医生建议用激素替代疗法来治疗冠心病。后来的随机对照试验表明,HRT 的使用导致冠心病风险的小幅增加。原来,最初进行 HRT 分析的妇女更有可能来自更高的社会经济背景,可能有更好的饮食和更多的锻炼,这是 CHD 发病率较低的原因。下次你看到一篇声称“吃这种新时尚饮食的人更长寿”或“服用特定的维生素补充剂会让你更聪明”的文章时,花点时间想想这是否真的是其他因素不变。
缺乏随机分配的因果关系
随机分配并不总是可能的。你不能让一群学生随机加入特定的大学。我肯定学生和大学都会反对。如果你仔细控制选择偏差,我们仍然可以在实践中获得真实实验的偶然力量。
我们可以通过对 SAT 分数和性别(通常是容易获得的数据)进行控制,首次发现这种因果关系。在 SAT 分数相近、性别相同的人群中,我们还能看到收入上的差异吗?我们仍然看到了积极的影响。这是否意味着你应该选择私立大学?收入的影响远不止这些——家庭背景、学生志向和人脉都可能影响收入。可能性是无穷无尽的,有些很难量化。我们如何解释这些可能导致选择偏差的省略变量?
Stacy Berg Dale 和 Alan Krueger 的一项聪明的研究使用了一种捷径来捕捉这些效应。关键的假设是,申请类似的选择性大学并被类似的选择性大学录取的学生应该是相似的(基于 Barron 的方案,该方案将大学分为 6 类,从最具竞争力到无竞争力)。通过对此进行控制的回归分析,他们发现上私立大学似乎与未来收入无关。
当然,可能有一些隐藏的变量,我们没有数据,因此无法控制。例如,这里我们没有家庭规模的数据。但是我们知道较小的家庭平均收入较高。此外,私立学校的学生一般来自较小的家庭。因此,我们可以对这个被忽略的变量的可能影响进行有根据的猜测——也就是说,控制这个变量可能会对私立学校收入优势的假设产生更大的影响。这让我们对原来的结论更有信心。这种对省略变量的仔细推理通常是因果分析的重要部分。在添加了几个关键控件之后,添加更多的控件应该不会对我们的结果产生太大的影响。在这里,在添加了对申请和录取选择性的控制后,添加更多的控制,如 SAT 分数,不会对结果产生太大影响。这也让我们对结果更有信心。
让我们以另一个假设的商业例子来结束。假设你去年在社交网络应用中推出了一项新功能,即加入当地社区的能力。你想知道它是否让用户对应用程序有了更多的参与。如果你比较加入社区的人和没有加入社区的人,并比较他们的参与度,你会发现加入社区的人参与度更高。但是那些已经对你的应用有更多参与的人很可能是加入你的社区的人。如果你看看在过去一年中有类似参与并加入社区的人,也许你会意识到社区减少了他们之间的参与。这可能是因为这些社区中有很多仇恨或垃圾邮件,这使得用户不太喜欢这个应用程序。
揭示隐藏的变量和有一个强有力的潜在原因表明因果关系,直到它可以被证明不是这样。
最后的想法
好的比较总是能解释选择偏差。对于许多业务应用程序,这在实践中通常就足够了。对于更重要的政策,在使用更复杂的方法之前,这可以是一个很好的基准,如使用工具变量或 T2 回归不连续设计。尽可能使用随机分配。
参考
- 黛比·A·劳洛尔,乔治·戴维·史密斯,沙·易卜拉欣,评论:激素替代-冠心病难题:这是观察流行病学的死亡吗?https://doi.org/10.1093/ije/dyh124,国际流行病学杂志,第 33 卷,第 3 期,2004 年 6 月,第 464–467 页
- Joshua d . ang rist & jrn-Steffen Pischke,2014 年。“掌握‘度量’:从原因到结果的路径”,经济学书籍,普林斯顿大学出版社,第 1 版
- 史黛西·伯格·戴尔和克鲁格(2002)。估算上一所更好的大学的回报:选择在可观察和不可观察上的应用。《经济学季刊》, 第 117 期 (4),1491–1527 页。于 2020 年 5 月 10 日从www.jstor.org/stable/4132484检索
机器学习中从相关性到因果性:为什么和如何
为什么我们的人工智能需要理解因果关系
相关性怎么了?
2016 年 5 月,COMPAS 算法被标记为种族偏见[1]。这种算法被美国用来通过预测再次犯罪的可能性来指导刑事判决。据估计,在其他背景因素相同的情况下,黑人比白人更有可能再次犯罪。
问题是,该算法将相关性(过去的犯罪模式)与因果关系(黑人更有可能犯罪)混淆了。
这在医学上也是一个问题。请考虑以下情况:
100 名患者因肺炎入院,其中 15 名还患有哮喘。医生知道哮喘使他们更容易生病,所以给他们更积极的治疗。正因为如此,哮喘患者实际上恢复得更快。
如果我们使用这些数据来训练一个模型,并且不小心的话,这个模型可能会得出哮喘实际上可以改善恢复的结论。因此,它可能会建议减少治疗的力度。当然,我们可以看到这是错误的——但对于一个人工智能模型来说,这并不那么明显。
从统计学到机器学习
这个没有因果关系的相关问题是机器学习中的一个重要问题。
正如 ryx,r 博客指出的那样,统计学和机器学习的一个关键区别是我们关注的焦点。在统计中,重点是模型中的参数。例如,对于预测房价的模型,我们希望了解每个参数以及它如何影响预测。
另一方面,在机器学习中,重点是更少关于参数,更多关于预测。参数本身的重要性仅在于它们预测感兴趣的结果的能力。
机器学习非常擅长在大量数据中识别复杂、微妙的关系,以高精度预测结果。问题是:这些关系是相关性,而不是因果关系。
相关性和因果性有什么区别?
简而言之:
关联是一个关联。当一个事物上升时,另一个事物下降。或者向上。其实无所谓,只要他们一起改变就好。
但是我们不知道第一次变化是否引起了第二次变化。或者即使第二个导致了第一个。还可能有第三个因素,它实际上独立地改变了这两点。
假设我们注意到晒伤和冰淇淋销售之间的相关性。人们被晒伤后会买更多的冰淇淋吗?还是人们买了冰淇淋,然后在太阳下晒了太久?
也许吧,但这与相关性的真正原因相比微不足道。两者都有一个共同的原因。晴朗的天气。在这里,太阳是一个“混杂因素”——同时影响两个感兴趣的变量(导致相关性)。
由dinosoftlab制作的图标。经许可使用。受安东尼·菲格罗亚的启发相关性不是因果关系
因此,总而言之,从相关性到因果关系,我们需要排除所有可能的混淆因素。如果我们控制所有的混杂因素(并考虑随机机会),我们仍然观察到一种联系,我们可以说有因果关系。
那么,我们如何去除混杂因素呢?
金标准是随机对照试验(RCT) 。
这里,我们完全随机地将样本人口分成两部分。一半接受一种治疗,另一半接受另一种治疗。因为这种分裂(至少在理论上)是完全随机的,结果之间的任何差异都是由于不同的治疗方法造成的。
来源:人工智能在医疗保健中的作用是什么?目前的证据表明了什么。原纸。
但有时我们不能跳 RCT。也许我们已经收集了数据。或者,也许我们正在调查一个我们无法改变的变量(比如遗传或天气的影响)。我们能做什么?
这里有一个简洁的数学方法,叫做‘分层混杂’。我不会在这里深入讨论细节,但是本质上它通过对它们的值的每一个可能的组合求和来去除混杂因素。(如果感兴趣,朱迪亚·珀尔是这一领域的先驱,并在这里概述了方法论。费伦茨·胡萨尔分享了一个更简短的描述。
因果关系:机器学习的未来?
将因果关系引入机器学习可以使模型输出更加稳健,并防止前面描述的错误类型。
但是这看起来像什么呢?我们如何将因果关系编码到模型中?
确切的方法取决于我们试图回答的问题和我们可用的数据类型。
最近的一个例子是巴比伦健康的这篇论文。他们使用因果机器学习模型,根据患者的症状、风险因素和人口统计数据对可能的疾病进行排序。
他们训练模型问“如果我治疗这种疾病,哪些症状会消失?”以及“如果我不治疗这种疾病,会留下哪些症状?”。他们将这些问题编码成两个数学公式。使用这些问题带来了因果关系:如果治疗疾病导致症状消失,那么这就是因果关系。
他们将他们的因果模型与只关注相关性的模型进行了比较,发现它表现更好——特别是对于更罕见的疾病和更复杂的病例。
展望未来
尽管机器学习潜力巨大,令人兴奋,但我们不能忘记我们的核心统计原则。
我们必须超越相关性(关联)来看待因果关系,并将其构建到我们的模型中。
我们可以通过去除混杂因素来做到这一点;通过随机对照试验或智能数学操作。
这对于确保我们作为一个社会能够受益于机器学习而不屈服于其缺陷至关重要。
原载于 2020 年 10 月 31 日chrislovejoy . me。
参考文献
(2) 统计学中的因果推断:初级读本,第 3 章:干预的效果
(3) ML 超越曲线拟合-推理博客
(5) 用因果机器学习提高医疗诊断的准确性【研究论文】巴比伦健康
其他关于相关性和因果关系的文章:
- 数据科学中的相关性与因果关系
- 如果相关性不意味着因果关系,那么什么意味着因果关系?
附录:因果推理层级(朱迪亚·珀尔的因果阶梯)
朱迪亚·珀尔描述了因果推理的阶梯。
当超越联想推理时,他考虑了两种主要类型:介入因果推理和反事实因果推理。
介入式因果推理 问“如果我把 A 设为值 X,B 会怎么样?”如果将 A 的值设置得更高导致 B 的值更高(没有混杂因素),我们说这种关系是因果关系。
反事实因果推断 有点小技巧。我们问“假设 A 是值 X,这导致 B 等于 Y,如果 A 实际上是一个更高的值,会发生什么?”(即。它在事件已经发生之后询问这个。如果不同的 A 会导致不同的 B 值,我们说这种关系是因果关系。
如果有兴趣了解这些区别,请查看以下资源:
- 统计中的因果推理:朱迪亚·珀尔的初级读本:对该主题的一个伟大的数学介绍
- 朱迪亚·珀尔的《为什么》一书:一个伟大的门外汉对这个主题的介绍,有历史和更广泛的背景
- 因果关系推理博客系列
从尖端研究到 Giotto 的工业应用
为拓扑机器学习创建自己的转换器指南。
如果你是一名企业数据科学家,你最好能接触到最前沿的研究,因为这个领域发展如此之快。其中一个挑战是,与 PyData 堆栈和 scikit-learn 等机器学习框架的集成很难做到简单。
从前沿研究到工业应用需要什么?
目前,机器学习的大多数研究都是以文章的形式发表的,在某些情况下,还会以伴随代码的形式发表。通过设计,这些代码库针对特定的研究应用进行了优化,将这些工具与更广泛的生态系统集成并不总是那么简单。
在 L2F ,我们启动了 Giotto 开源项目,其愿景是让更广泛的数据科学社区可以使用先进的机器学习技术。我们目前开发了两个库:
- giotto-time ,用于时间序列预测、
- giotto-tda ,用于拓扑机器学习。
在这篇文章中,我们的目的是展示如何使用最先进的技术进行图形分类,并将其与 giotto-tda 集成。具体来说,我们将把最近 GUDHI/Inria 的 Royer 等人的研究和开源代码整合到 giotto-tda 管道中。
GitHub repo 用于图形拓扑特征的自动提取(以下分子毒理学分类示例)
在 Github 、 Twitter 和 Slack 上关注 Giotto 的最新动态
Royer 等人引入的算法被称为 ATOL,用于自动面向拓扑的学习。它解决了拓扑数据分析(TDA)中的一个关键问题,即从所谓的持久性图中自动提取特征。持久性图是一个数据集的全局拓扑的表示,以其同时在所有尺度上的连通性表示,它是通过逐渐连接相邻点并记录结构“同源性”的演变而获得的。这是一种理解、可视化和从数据中提取特征的新方法。
对于拓扑机器学习、持续同源/持续图以及如何在 ML 管道中使用 giotto-tda 的一般介绍,您可以参考这篇博客文章。
在 giotto-tda 中推出您自己的评估工具
与 scikit-learn 的紧密集成是 giotto-tda 背后的关键设计原则之一。这使得为您自己的项目实现与 scikit-learn 管道、元估算器和网格搜索等模型选择工具交互的定制组件变得简单。
让我们通过考虑 scikit-learn 提供的 transformer 模板来热身。从模板中,我们可以看到,要创建一个定制的转换器,我们需要实现三个基本组件:构造函数“init”、“fit”和“transform”。
scikit-learn 中的 transformer 方法模板
变压器是特殊类型的估算器。估计器是基于一些训练数据来拟合模型的对象。所有估计器都实施“拟合”方法,该方法将估计模型存储在公共或私有属性中:
拟合方法的模板
创建对象时,您会希望定义一个实例化方法,该方法定义了对象的默认参数。__init__
方法应该只定义独立于训练数据的模型的超参数。
init 方法的模板
变压器与一般估算器的不同之处在于,它们还应该实现一种用于过滤或修改数据的“转换”方法。传递给“transform”的数据可能与用于拟合模型的数据不同,在“fit”中学习到的信息可以用于“transform”中—通常情况下,这是监督或非监督统计学习的情况!
转换方法的模板
从纸张到代码
在 ATOL 的例子中,原始代码的作者已经定义了一个 transformer 类、Atol 、T2(检索于 2020 年 1 月 21 日)。如您所见,它实现了“fit”和“transform”方法。“fit”的主要作用是将 KMeans 算法的运行所计算的聚类中心存储在一组持久性图中,而“transform”可以应用于一个单个不可见的持久性图,以产生一个向量表示。
这个 Atol 类接近于在机器学习框架中直接使用,但是它有一个关键的缺点:如果你的数据问题产生了持久性图的集合,你可能会希望“transform”方法也能够作用于持久性图的集合。这是 scikit-learn transformers 的典型特征,也是模型验证等工作的关键。
这一点,加上其他旨在使 Atol 转换器更符合 scikit-learn 的贡献指南的小变化,就是为什么我们在这里放在一起这个类的一个稍微修改的版本。下面是新的转换方法。它通过在集合的每个元素上调用“transform_single_diag”方法来作用于图的集合 X 。
专家将注意到另一个技术差异,这与 giotto-tda 向用户单独展示不同“同源维度”的独特能力相关(因此将 Atol 独立应用于每个)。
拓扑特征自动生成
将持久性图与机器学习集成的一个常见挑战是需要将图矢量化为特征向量。多年来,提出了各种各样的建议。几个特别的矢量化方法被社区广泛使用,其中许多都在 giotto-tda 中实现!然而,找到自动学习特定于任务的向量表示的鲁棒方法仍然是一个具有挑战性的研究问题。
为了解决这个问题, Royer 等人最近提出了一种新的
算法来自动矢量化持久性图。ATOL 基于以下步骤:
ATOL 算法的不同宏步骤
- 为目标向量空间选择一个嵌入维数 d。
- 将一组持久性图连接成一系列点。
- 在这些点上运行聚类算法以获得 d 个聚类中心
c₁,…,d. - 对于每个聚类中心 cᵢ,计算所谓的拉普拉斯对比度
函数(将其视为从 2D 平面到真实直线的特殊映射)。 - 连接拉普拉斯函数以形成一个向量(v₁,…,v_d ),该向量
从持久性图中捕获基本的拓扑信息。
用 Giotto-learn 对分子进行毒理学分类
图分类是一项核心的机器学习任务,可用于确定分子的毒性,或将社交网络的成员分为一个或多个类别。观察结果是完整的图表,目标是预测它们属于哪一类。
化学和图形,它们有点像手和手套:天生一对。有趣的事实是,图形这个术语本身首次出现在 1878 年的《自然》杂志论文,将代数的应用庸俗化为……化学。
GitHub repo 用于 TDA 毒理学分类
图上的机器学习
为了发挥它们的魔力,机器学习算法要求输入是数字形式的。为了学习图形,我们需要一种方法来用数字编码它们的结构。
图编码了实体之间关系的一个非常基本的概念,这使它们成为非常灵活的对象。然而,只有在它们的数值表示中,我们才能对它们进行机器学习。
两张看起来非常相似的图实际上可能有很多不同之处。图与图之间的距离表示我们认为图与图之间的差异很小的程度,并且是根据它们的数值表示来计算的。
图可以通过其路径网络的鲁棒性来表征。
路径网络移除一条或两条边的弹性是根据不连通区域的创建来衡量的。移除图 0 和图 1 中的一条或两条随机边会限制您从一个节点到另一个节点自由移动的能力,因为一些点会与其余的点不相交,而在图 4 或图 6 中不会发生这种情况。
用 TDA 实现图形矢量化:HKS +阿托尔
在你能想到的所有数据结构中,图是最有可能有一些拓扑概念的。
HKS 算法(热核签名)研究当您在图中添加或删除边时,图的组件如何合并。在固定了参数 t 之后,它为每个 H₀和 H₁.输出两个持久性图我们对 t=0.1 和 t=10 运行 HKS,并有 8 个图表来描述该图。
ATOL 算法然后基于 N 个持续图的集合产生特征向量。在固定了多个聚类 b 之后,Atol 输出大小为 Nb 的特征向量。我们对 b=2 运行 HKS,这产生了 82=16 个坐标。
基于标记为安全或有毒的 1478 个分子的集合(分类比率为 93:7 ),我们使用 ATOL 从持久性图中构建描述性特征。
结果
数据集上的现有基准在 AUC 中通过称为 TextCNN 的单一深度学习模型达到 0.995。利用分子的特征和我们管道中产生的特征,我们达到了非常可观的 0.976。
更具体地说,我们最终的 XgBoost 模型具有以下特性:
- 分子中存在的化学物质(17 个特征)
- 关于键取向的化学特征(3 个特征)
- 环礁特征(16 个特征)
有趣的是,仅环礁特征(没有化学信息)在 AuRoc 上的得分为 0.72。
更多带代码的文章:
图形嵌入
时间序列
可视化
- Mapper 入门,可视化高维数据以找到其粗略结构
- 美国大选结果的社会经济研究(笔记本):使用制图仪。
坚持
乔托
- Github 上的 Giotto-tda 库
- 更多学习资料请访问网站
- 推特
- 松弛用于支撑
参考
- 马丁·罗耶、弗雷德里克·夏萨尔、池宇一、梅田裕平。自动面向拓扑的学习。2019. ⟨hal-02296513⟩
- ATOL:python 3 package for ATOL:Automatic topological-Oriented Learning,开源代码作者 Martin Royer,版权:Inria。
从数据分析师到数据故事讲述者只需 3 步
使用 Matplotlib 中的这个简单过程改进您的数据可视化
为什么你需要学习这个
众所周知,各种形式的数据准备构成了数据科学家工作的 80%以上。鉴于进入该领域的新人似乎认为这一切都是关于昂贵的计算机和复杂的深度学习模型,这是一条有价值的信息。你也许可以用这些东西给数据团队的同事留下深刻印象,但是你的经理和客户通常不太关心技术细节。然而,让这些人注意到并正确理解你的工作是至关重要的。这就是为什么你需要学习数据可视化!
对某些人来说,数据可视化只是困扰着烦人的利益相关者。这是一种非生产性的思维方式,也是错误的!请这样想:
如果你不能可视化你的结果,你就不知道你的结果。
每个人和他们的祖母都可以创建一些单行散点图,并称之为数据可视化。然而,要将基本的可视化转化为一个故事,让您的经理和客户不仅能够理解,还会感到兴奋和受到鼓舞,这需要一个充满激情和技能的数据科学家。在这篇文章中,我将帮助你把你的技能提升到一个新的水平!你所需要做的就是遵循一个简单的三步程序,这个程序可以应用到你的每一个视觉化形象中。你的经理、客户和未来的雇主会感谢你努力阅读这个故事!
糟糕的视觉效果是什么样的?
试着想象一些你的第一个 matplotlib 可视化。很可能,它们看起来像图 1。我在这里尝试做的是将不同年龄组的各种音乐类型的流行程度形象化。
图 1 —我们的基本图
该线图由以下代码生成:
fig, ax = plt.subplots(figsize =(10,6))# Loop through the genres
for i, g in enumerate(genres):
# Define x and y
x = np.arange(7)
y = music_pref_2019[g]
# Plot lines
ax.plot(x, y, label = g)
# X axis
ax.set_xticks(x)
ax.set_xticklabels([“14–19”, “20–29”, “30–39”, “40–49”, “50–59”, “60–69”, “70+”])
ax.legend()plt.show()
这个情节有很多问题。我们将通过以下三个步骤来改进它:
- 添加信息
- 减少信息
- 强调信息
信噪比描述了与不必要的信息量相比有价值的信息量。在任何创造性的产品(文章、视觉化图像、音乐作品)中,我们应该以最大化这个比率为目标。
我们可以通过添加有用信息来提高信噪比,也可以通过删除无用信息来提高信噪比。在理想的可视化中,所有重要的信息都被呈现和强调,而没有任何实际价值的东西都被删除。
步骤 1—添加信息
让我们集思广益,看看图 1 中缺少了什么。以下是我的观察。我们需要补充:
- 一个标题
- 轴标签
- y 轴的刻度和刻度标签
- 直接从行中读取不同年龄组的单个值的方法
我们可以通过在完整的可视化代码中包含以下代码行来实现这一点:
# 1
ax.set_title("Popularity of Different Genres by Age Groups")
# 2
ax.set_xlabel("Age")
ax.set_ylabel("Amount of people with preference (%)")
# 3
ax.set_ylim(0,1)
ax.set_yticklabels(int(i*100) for i in ax.get_yticks()) # Turns the # decimals into percent values
# 4
ax.scatter(x, y) # adds points at every tick of x
最重要的是,我为我们的系列选择了不同的颜色。matplotlib 标准颜色对于色盲的人(比如我)来说很难处理。因此,我在下图中只使用了 tableau 色盲调色板中的颜色。
图 2 —增强图
我们可以清楚地看到,从图 1 到图 2,在给出的信息量方面有所改进!通过添加相关信息,我们提高了信噪比。我们需要不惜一切代价保护相关信息!因为我们需要的一切都以某种形式包含在可视化中,所以很容易就把它留在那里。然而,这就是奇迹发生的地方。第 2 步和第 3 步将保留所有相关信息,但使用某些技术使整个图表更加清晰易读。
第二步——减少信息
减少信息并不总是意味着删除标签、图例或记号等信息。有时,它只是意味着减少信息对读者的阻碍程度。这里有一些关于如何处理这个情节的想法:
我们可以:
- 移除蜱
- 移除脊椎
- 去掉大图例,直接把标签写在每一行上
- 仅在 y 轴上留下 4 个刻度
- 去掉 x 和 y 标签,直接在最后一个刻度上标出
# 1
ax.tick_params(bottom = False, top = False,
left = False, right = False)
# 2
for key, spine in ax.spines.items():
spine.set_visible(False)
# 3
ax.text(0,.875, "Rock/Pop", rotation = -1.5)
ax.text(0,.144, "Classical", rotation = 16)
ax.text(0,.395, "Hardrock/Metal", rotation = 4.5)
ax.text(0,.679, "Hip Hop/Rap", rotation = -31)
ax.text(0,.592, "Techno/House", rotation = -15)
# 4
ax.set_yticks([0,0.25,0.5,0.75,1])
# 5
ax.set_xticklabels(["14-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70+ years"])
ax.set_yticklabels([0, 25, 50, 75, "100%"])
图 3 —简化图
第三步——强调信息
现在我们已经添加了所有相关信息,并删除了所有不相关的信息,我们仍然可以优化我们的可视化。也许我们可以做些什么来强调某些方面。这里有一些关于这个特定情节的想法:
- 更改标题的字体、字号和粗细
- 强调数据的连续质量
要改变标题字体,我们可以创建一个 font_dict,在 ax.set_title()函数中调用。
title_font= {"family" : "Cambria",
"size" : 16,
"color" : "black",
"weight" : "roman"}
# LATER IN THE CODE
ax.set_title("Popularity of Different Genres by Age Groups", fontdict = title_font)
为了强调数据的连续质量,我们需要去掉类别标签,改用平均年龄。对于分类变量,我们不知道任何年龄组参与者的平均年龄是多少。然而,我们可以使用类别中可能年龄的四舍五入平均值。任何 c 类的平均年龄 m 为:
m = int(c_start + c_end)
现在,我们可以用这些平均年龄作为 y 轴标签:
ax.set_xticklabels(["17", "25", "35", "45", "55", "65", "70+ years"])
为了进一步强调数据的连续性,我们可以减小点的大小和透明度,同时增加线的大小:
ax.scatter(x, y, c = cb_colors[i], label = mapping_dict[g], marker = ".", linewidth = 3, alpha = 0.8)ax.plot(x,y, c = cb_colors[i], linestyle = "-", linewidth = 2.5, alpha = 0.8) # lowering alpha is also good here, as it gives more attention to the annotations and labels
我还将注释大小增加到了 12pt。
这将给出我们的最终输出(图 4)。
图 4 —最终图
在这里,我们可以清楚地看到,线开始有意义。虽然这不完全是数据告诉我们的(毕竟这是绝对的),但我们的平均年龄允许我们讲述一个真实的故事。通过这种可视化,我们可以预测偏好如何随年龄变化,而不仅仅是比较它们在不同年龄之间的差异。这些点仍然允许我们针对特定的年龄,并看到它的准确值,同时也揭示了点之间的联系是线性预测,而不是实际数据。
我们也可以走另一条路,强调数据的分类特征。图 5 是这种方法的一个例子。
图 4 —备选最终图
在这里,我强调了点,并在背景中添加了一个网格。我还保留了原来的类别标签。
结论
在本文中,我向您展示了如何使用三步公式来改进 matplotlib 可视化。这篇文章要带回家的一个关键点是,魔力不在于你添加的信息,而在于你删除或转换的信息。请看图 1,并将其与我们的最终结果进行比较。然后检查你自己最近的想象,看看你是否能利用三步公式使它们变得更好!
感谢阅读!
从数据湖到数据水库
使用 Apache Spark 和 Delta Lake 创建干净、美观、受保护的数据资源
混乱中有美。图片来源:Unspalsh @powwpic
数据以各种形状和大小出现
有趣的是,当我们谈论数据时,最好的类比通常植根于水。为了理解数据的概念,这是有意义的——数据以各种形状和大小出现——人们倾向于接受抽象。可以说,单个数据记录可以被比作一滴水,许多相同种类(记录类型)的水滴聚集并结合成孤立的数据池(表/目录),而正是这些池驻留在更大的构造中,该构造是数据湖的主体。
数据湖是一个生态系统,它支持多种类型的记录在无数用例中共存,但从足够高的角度看,它似乎是一个简单的容器,用于存储几乎无限量的数据。
拥抱抽象
作为工程师,我们所做的大部分事情都遵循这样的路线:将一个大的概念或者可能是一个更松散的组合“想法”分解成更小的组成部分,以便理解构建一个系统或框架的方法,该系统或框架的“行为就像】那个东西。
同样的策略可以应用于您的数据建模方法中,更一般地说,可以应用于您如何定义表示事件、指标和实体的结构化数据,甚至更具体地说,可以应用于您希望从您的数据存储中涌现出来的行为和趋势。这些数据是你对过去发生了什么,现在正在发生什么的时间点镜头,可以作为一个参考框架来预测未来“可能”发生什么。
然而,存储在不完美系统中的完美数据可能会导致大规模甚至灾难性的失败。我喜欢把这看作是污染了数据湖。没有人希望这样,过去几年发布了许多新的框架,试图解决与大规模(甚至小规模)运营数据生态系统密切相关的许多陷阱和未知的未知问题。
所以我们来了。我们知道以下为真
- 数据可以是复杂的和狂野的。
- 存储的数据“可以”用于 解决未来的问题 并提供对过去发生的事情的洞察。
- 数据随时间变化 。这可能导致历史数据损坏。不要往井里投毒!
- 基于水的数据类比几乎和糟糕的双关语一样有趣!
鉴于上述各点。除了第四点,我真的想深入 进入这篇文章的核心,它围绕着将你所知道的数据湖转换成我所认为的数据库的概念,我还将介绍一些目前正在使用的框架,它们可以帮助你的数据湖增加结构和吸引力,例如 Apache Parquet、Apache Spark、 DeltaLake
数据湖的意义是什么?
数据湖。它看起来很有条理,但却建立在一个破碎的想法之上。图片来源:法比奥哈Unsplash
数据湖有一个主要目标。这个目标是充当一个廉价的、水平可伸缩的(或无限可伸缩的)集中式筒仓,存储基于文件系统布局“最佳实践”松散组织的原始、半结构化或结构化数据。例如,一些众所周知的最佳实践集中在 a)限制基于单个目录的文件总数,以便快速列出操作,以及 b)遵循可用于将数据分组到可理解的实体中的目录方案。
例如 HDFS://insights/hive/tableName/year = 2020/month = 7/day = 30。这两种最佳实践相结合,允许使用文件系统快速跳过不相关的数据,而不使用索引,并轻松列出目录中文件的总数。
廉价存储
云计算是变革性的,因为它使各种规模的公司能够将服务器和网络的管理工作交给几家真正擅长运行服务器的云提供商。这些相同的云供应商(亚马逊、微软等)随后开始提供基于他们云产品的其他服务,如亚马逊的 S3 和微软的 Blob 存储。这花了一段时间,但最终达成了普遍共识,云足够安全,可以存储宝贵的数据,而不会因为糟糕的备份、糟糕的硬件、糟糕的机架/交换机等而丢失数据,这一新颖的想法开始兴起。公司意识到,他们可以存储所有数据,而成本只是目前内部解决方案的一小部分。
“如果我们可以存储我们所有*的数据,而成本与我们目前只在所有数据的一小部分上花费的成本相同,那会怎么样”
更简单的开发人员操作
这一想法导致了从更昂贵的 Hadoop 集群和为大型企业扩展 Hadoop 的开发-运营团队到商用存储和几乎无限的可扩展性的概念的转变。
数据湖采用这种集中式数据存储层的形式,可用作*公司或组织内所有数据的统一暂存平台,通过提取转换加载(ETL) 管道/流程将数据送入更严格、更标准化的数据仓库;传统上运行 SQL 的一些变体(Oracle、MySQL、Postgres、SQL Server ),由于这些 OLAP(在线分析处理)引擎的分析性质,这些变体产生了好几个数量级的响应时间。
本质上,你可以在准备好了的时候 解冻你的旧数据 ,重新读取它并重塑它来解决许多问题,但这并不是典型的情况。
数据湖解决了数据孤岛问题。ETL 为王:图片来源:微软
白日梦
真正的白日梦是数据湖还可以用来解决未来尚未确定的问题。这到底是什么意思?在缺乏可靠想法的情况下,许多公司会存储数据,希望最终能够使用这些数据。然而,大约 73%的公司存储的数据从未被访问用于分析,我愿意打赌,对于许多公司来说,超过 50%的存储数据从未被访问过一次。
公司存储的 73%的数据从未被用于分析…
许多公司围绕如何将数据输入这些数据湖制定了自己的政策,目的是通过提前设计时间并考虑 1 / 3 / 5 年后如何访问数据来保留其数据的未来处理能力。虽然这可能感觉像是不可思议的想法,但也有许多公司决定即兴将半结构化数据或非结构化数据(也称为 JSON 或 CSV)写入许多单独的文件或大的换行(\n)分隔的文件,以便在批量操作期间读取。但是如果没有模式、读/写策略,治理最终会陷入混乱…
对许多公司来说,这是蛮荒的西部
就像许多事情一样,那些从最美好的意图开始的事情往往会在没有规则和标准的情况下转变并呈现出新的形态。数据湖很容易变成廉价的、水平可伸缩的、集中式的数据混乱,它的运行没有任何规则或秩序,就像“狂野西部”一样。虽然我们都可以支持牛仔,有时可能会梦想没有规则和条例的生活,但在我们的内心深处,我们最有可能得出类似的结论
“没有规则,就没有秩序感或平衡感”。
那么,我们如何解决潜在的混乱呢?
结构化数据湖:政策、框架和治理
结构化数据湖的出现正在引领一场新的数据革命!图片来源: sortino 经 Unsplash
标准的出现
好主意一旦形成,就会像野火一样迅速传播。最近,数据社区已经标准化了至少一种足够好的核心数据格式。这就是文件存储格式 Parquet,我们将进一步了解为什么它是静态数据的绝佳选择。静态数据只意味着它当前不在活动内存中。
感谢谷歌赠送的拼花地板。
拼花拼花是什么做的?信用: Apache Parquet docs
虽然看起来像某种巫术,但实际上它只是一个执行得非常好的柱状数据存储原语。
当你分解文件格式时,你会看到有行、列和类型。
这允许通过通用格式(模式)封装的大量记录被有效地压缩或压缩到更小的空间中。
例如,如果我有 4000 万条记录存储为 JSON,每条记录的开销在 1-2kb 之间,那么我大概有 40gb 的文件。
现在,如果您使用 JSON 并将其转换为 parquet,您可以预期在文件开销方面节省大约 50–80%。但是除了节省成本之外,还可以轻松地对数据进行分区,并使用 snappy、gzip、lz4 或任何二进制可拆分压缩格式进一步压缩。
根据经验,我可以说每天大约有 4000-8000 万条中等复杂程度的记录(例如,超过 20 个字段)可以被分解到 128 个分区中,并且存储在 12-24gb 之间!这包括作为快速压缩分区的拼花页眉和页脚,并支持数据集的分布式读取,这非常适合我们的许多用例,这些用例都以 Spark 为中心的数据平台为中心。
Cloudera 基准测试(parquet/avro/csv)。图片来源: Cloudera :拼花赢了
然而,减小磁盘大小并不是唯一的重大胜利。一旦您的数据被存储为 parquet,您就能够在数据中进行行或列级别的高效跳转—因此,在 4000 万条记录中检索 1-2 条记录可能只需要大约 5 秒钟。在读取实际内容之前,Parquet 能够只读取页脚来检查某些内容是否存在于 parquet 块中。它使用列统计来帮助加速这一直观的行/列级提取和过滤过程。如果你想看看它与 Avro 相比如何,你可以从 Cloudera 看到这个基准。
最后,parquet 已经成为当今许多最广泛使用的数据工程和数据分析框架和平台的事实上的标准,如 Apache Spark (SparkSQL 与 Parquet 进行开箱即用的本地互操作) Presto 、 DeltaLake 和 Apache 胡迪等等。
Apache Spark 是数据催化剂
Apache Spark 的出现应该感谢它在组织和统一整个数据从业者社区方面接过了接力棒并引领了前进的步伐。 Databricks ,Spark 社区背后的公司已经付出了很多努力来保持社区的参与,并继续生产在 Spark 生态系统中运行的令人惊叹的新技术。核心 SparkSQL 引擎的一个较新的补充是一个名为 DeltaLake 的框架,它将原子操作、更新(插入或更新)、合并、删除和附加的条件 SQL 逻辑直接添加到 Spark DSL 中。为与现有数据湖体系结构一起工作而编写的这一微妙的增强带来了最佳实践,包括文件系统布局、操作可观察性以及对增量表中现有记录所做操作的良好审计跟踪支持。
三角洲湖泊生态系统:图片来源:数据块/三角洲
还记得之前我提出的问题吗:毒害了数据湖,以及事物如何需要某种秩序和治理才能进化成更伟大的东西。我称之为数据库,我相信 DeltaLake 已经准确地标准化了一个数据湖应该如何工作,并在适当的位置设置正确的安全防护,以确保数据湖随着时间的推移保持干净和美丽。让我们深入探讨这是如何可能的。
增量模式和文件布局
从第一次写入增量表开始,Spark 就使用与它正在写入数据湖的数据帧相关联的底层 StructType 来确保模式将被保留,并且新的写入符合那个严格模式或者在写操作时执行一个 "mergeSchema=true" 。下面是一个将数据帧写入 Delta 的示例。
以批处理模式将数据帧写入增量。
此操作将与原子提交日志一起存储。
上面操作中的 _delta_log 示例。
DeltaLake 表的其余部分。按年、月、日划分。
这个模式和文件位置元数据存储在所谓的 _delta_log 中,它存在于你的 Delta 表的根中。这个小目录存在于封装您的“表”的文件系统层次结构的根目录旁边。
增量提交日志的示例。信用:自我
现在,对增量表进行的任何附加操作都将具有关于变异的文件、当前表的版本、与该表相关联的模式的信息。这为您提供了观察应用于存储在这个数据湖(DeltaLake)中的数据的操作的机会。
在三角洲湖读书轻而易举
借助 Delta,读取和转换用于分析的数据变得非常简单。信用:自我
从上面的代码片段可以看出。从 delta 读取很简单。有趣的是,在上面的查询中,我们没有引用数据的 load 命令中的特定路径,我们可以使用所谓的分区下推来跳过目录,只扫描六月 (col("month ")的内容。在上面的 where 子句中,equalTo(6) 。这利用了文件系统的优势,因此您不必将所有的表实体加载到位。节省时间和金钱。
支持批量写入和完全连续流写入
Delta 处理批量读/写和流读/写。太好了。信用:自我
上面是一个从我们之前用批处理创建的增量表创建 readStream 的例子。Delta 带来的新奇事物是批量读/写、流读/写流的混合用例支持。想想 Airflow 解决了一些困难的用例——air flow 基本上只是在父作业完成时触发子作业,然而 DeltaLake 允许您生成 spark 作业的复杂流 DAGS (有向无环图),如果您喜欢 Spark,这会让您有点流口水。Spark to the rescue 解决您所有与 Spark 相关的需求。
Zeppelin 视图:展示了如何使用批处理查询从流表中读取数据(参见上面的查询以查看窗口写流)
你可能有一些上游作业需要完成,以便下游作业能够继续工作,就像传统的数据传送带一样。现在,您可以利用完整的端到端流系统来编排这种体验——把它视为您的数据传承管道——您的数据工程工作变得越来越简单。
鉴于当今数据生态系统中的数据湖需要能够进行近乎实时的插入/上插/合并、准确的历史分析、高效的 ETL 到机器学习作业和更快的在线特征存储中,并且还需要成为可靠可信数据的支柱,那么单独使用 DeltaLake 就可以解决所有这些用例。我认为这是数据工程和分析的瑞士军刀,是 ETL 到更快的内存数据存储(如 Redis 或 ElasticSearch,取决于您的数据检索 SLA)的坚实基础。
结论
传统的数据湖通常是非结构化或半结构化的,数据的质量与向数据湖发布数据的团队一样好。随着时间的推移,这个过程很容易被污染和破坏,导致可怕的数据湖中毒。
您可以通过依赖您可能已经在使用的系统(S3、Apache Spark,也许 parquet 已经出现或者您已经在使用 Parquet)来解决您未来的未知问题,DeltaLake 只是让您更容易以标准和结构化的方式快速移动。在整个组织中处理数据时,将快乐带回桌面。
干杯。
从数据框架到 N 元语法
数据科学/ Python NLP 片段
使用 nltk 为自然语言处理创建和可视化 n 元语法排序的快速入门指南。
坦纳·马迪斯在 Unsplash拍摄的照片
当我第一次开始学习 NLP 的时候,我记得我被信息过载弄得沮丧或害怕,所以我决定写一篇涵盖最基本内容的帖子。你知道他们说什么,“先走后跑!”
这是一个非常温和的介绍,所以我们不会在这里使用任何花哨的代码。
简而言之,自然语言处理或 NLP 简单地指使用计算机阅读和理解书面或口头语言的过程。举个最简单的例子,我们可以用电脑来阅读一本书,并计算每个单词被使用了多少次,而不是我们手动去做。
NLP 是一个很大的话题,已经有很多关于这个主题的文章,所以我们在这里不做介绍。相反,我们将关注如何快速实现 NLP 中最简单但有用的技术之一:N 元语法排序。
n 元语法排序
简单地说,一个 n-gram 是一个由 n 个字组成的序列,其中 n 是一个范围从 1 到无穷大的离散数字!例如,单词“cheese”是 1-gram (unigram)。单词“奶酪味”的组合是一个 2 克(双字母)。同样,“奶酪风味小吃”是一个 3 克(三元组)。而“终极芝士味零食”是 4 克(qualgram)。如此等等。
在 n-gram 排名中,我们只是根据 n-gram 在文本主体中出现的次数对其进行排名,无论是一本书、一组推文还是贵公司客户留下的评论。
我们开始吧!
获取数据
首先,让我们获取数据并将其加载到 dataframe 中。你可以在这里下载样本数据集或者从特朗普推特档案创建你自己的数据集。
import pandas as pddf = pd.read_csv('tweets.csv')
使用df.head()
我们可以快速熟悉数据集。
特朗普总统的推文样本。
导入包
接下来,我们将导入包,以便正确设置我们的 Jupyter 笔记本:
# natural language processing: n-gram ranking
import re
import unicodedata
import nltk
from nltk.corpus import stopwords# add appropriate words that will be ignored in the analysis
ADDITIONAL_STOPWORDS = ['covfefe'] import matplotlib.pyplot as plt
在上面的代码块中,我们导入了熊猫,这样我们就可以用各种不同的奇妙方式来塑造和操作我们的数据!接下来,我们为 regex 导入了re
,为 Unicode 数据导入了unicodedata
,并导入了nltk
来帮助解析文本并稍微清理一下。然后,我们指定了我们想要忽略的额外的停用词。这有助于降低噪音。最后,我们导入了matplotlib
matplotlib,这样我们可以在以后可视化我们的 n 元排序的结果。
接下来,让我们创建一个执行基本数据清理的函数。
基本清洁
def basic_clean(text):
"""
A simple function to clean up the data. All the words that
are not designated as a stop word is then lemmatized after
encoding and basic regex parsing are performed.
"""
wnl = nltk.stem.WordNetLemmatizer()
stopwords = nltk.corpus.stopwords.words('english') + ADDITIONAL_STOPWORDS
text = (unicodedata.normalize('NFKD', text)
.encode('ascii', 'ignore')
.decode('utf-8', 'ignore')
.lower())
words = re.sub(r'[^\w\s]', '', text).split()
return [wnl.lemmatize(word) for word in words if word not in stopwords]
上面的函数接受一列单词或文本作为输入,并返回一组更清晰的单词。该函数执行规范化、编码/解码、小写和词汇化。
让我们使用它!
words = basic_clean(''.join(str(df['text'].tolist())))
上面,我们只是简单地调用函数basic_lean()
来处理我们的数据帧df
的'text'
列,并使它成为一个带有tolist()
的简单列表。然后我们将结果分配给words
。
已经清理、规范化和词条化的单词列表。
N-grams
有趣的部分来了!在一行代码中,我们可以找出哪些二元模型在这个特定的 tweets 样本中出现得最多。
(pd.Series(nltk.ngrams(words, 2)).value_counts())[:10]
我们可以很容易地将数字 2 替换为 3,这样我们就可以得到前 10 个三元模型。
(pd.Series(nltk.ngrams(words, 3)).value_counts())[:10]
瞧啊。我们给自己开了个好头。但是为什么现在停止呢?让我们尝试一下,做一个小眼睛糖果。
奖励回合:可视化
为了让事情变得简单一点,让我们将 n 元语法的结果赋给具有有意义名称的变量:
bigrams_series = (pd.Series(nltk.ngrams(words, 2)).value_counts())[:12]trigrams_series = (pd.Series(nltk.ngrams(words, 3)).value_counts())[:12]
我用[:12]
替换了[:10]
,因为我希望结果中有更多的 n-grams。这是一个任意值,因此您可以根据自己的情况选择对您最有意义的值。
让我们创建一个水平条形图:
bigrams_series.sort_values().plot.barh(color='blue', width=.9, figsize=(12, 8))
让我们通过添加标题和轴标签来美化一下:
bigrams_series.sort_values().plot.barh(color='blue', width=.9, figsize=(12, 8))
plt.title('20 Most Frequently Occuring Bigrams')
plt.ylabel('Bigram')
plt.xlabel('# of Occurances')
就是这样!通过几行简单的代码,我们很快从一个熊猫数据帧中制作了一个 n-grams 的排序,甚至制作了一个水平条形图。
我希望你喜欢这个。自然语言处理是一个很大的话题,但是我希望这个温和的介绍将鼓励你探索更多并扩展你的技能。
在下一篇文章中,我们将 可视化一个 n-gram 在 Power BI 中的排名,只需简单地点击几下鼠标和一小段 Python!
敬请期待!
你可以通过推特或 T2【LinkedIn】联系我。
从数据帧到命名实体
数据科学/ Python NLP 片段
使用 spaCy 从 Pandas 数据帧中提取命名实体的快速入门指南。
很久以前,在一个遥远的星系,我在分析客户留下的评论时,注意到他们似乎更多地提到了特定的公司。这给了我一个想法。也许有一种方法可以从评论中提取公司的名称,我可以量化它们并进行进一步的分析。
有!输入:命名实体识别。
命名实体识别
根据维基百科,命名实体识别或 NER“是信息提取的子任务,旨在定位非结构化文本中提到的命名实体并将其分类为预定义的类别,如人名、组织、位置、医疗代码、时间表达式、数量、货币值、百分比等。”换句话说,NER 试图提取归类为专有名词甚至数字实体的单词。
在这篇文章中,我将分享让我们使用 spaCy 从 Pandas 数据帧中提取命名实体的代码,spaCy 是一个开源库,提供 Python 中工业级的自然语言处理,是为生产使用而设计的。
首先,让我们使用以下 pip 命令安装 spaCy:
pip install -U spacy
之后,让我们下载英语的预训练模型:
python -m spacy download en
解决了这个问题,让我们打开 Jupyter 笔记本,开始吧!
进口
将下面的代码块运行到一个单元格中,以将所有必需的导入内容导入到我们的 Python 环境中。
# for manipulating dataframes
import pandas as pd# for natural language processing: named entity recognition
import spacy
from collections import Counter
import en_core_web_sm
nlp = en_core_web_sm.load()# for visualizations
%matplotlib inline
这个块中重要的一行是nlp = en_core_web_sm.load()
,因为这是我们稍后将用来从文本中提取实体的。
获取数据
首先,让我们获取数据并将其加载到 dataframe 中。如果你想跟进,请在这里下载样本数据集或从 Trump Twitter 档案创建你自己的数据集。
df = pd.read_csv('ever_trump.csv')
在单元中运行df.head()
将使我们快速熟悉数据集。
获取代币
其次,让我们创建将作为 spaCy 输入的令牌。在下面一行中,我们创建了一个变量tokens
,它包含了df
数据帧的'text'
列中的所有单词。
tokens = nlp(''.join(str(df.text.tolist())))
第三,我们要提取实体。我们现在只能提取最常见的实体:
items = [x.text for x in tokens.ents]
Counter(items).most_common(20)
作者截图
提取命名实体
接下来,我们将根据类别提取实体。我们有几个选择,从人到事件甚至组织。要获得 spaCy 提供的所有内容的完整列表,请查看他们关于命名实体的文档。
作者截图
首先,我们将使用PERSON
类型提取人(真实的和虚构的)。
person_list = []for ent in tokens.ents:
if ent.label_ == 'PERSON':
person_list.append(ent.text)
person_counts = Counter(person_list).most_common(20)df_person = pd.DataFrame(person_counts, columns =['text', 'count'])
在上面的代码中,我们用person_list = []
创建了一个空列表。
然后,我们利用一个 for 循环来遍历在带有tokens.ents
的令牌中找到的实体。之后,我们创建了一个条件,如果实体标签等于PERSON
类型,它将追加到先前创建的列表中。
我们想知道某个PERSON
类型的实体在令牌中出现了多少次,所以我们对person_counts = Counter(person_list).most_common(20)
进行了处理。这一行将给出这种类型的前 20 个最常见的实体。
最后,我们创建了df_person
数据帧来存储结果,这是我们得到的结果:
作者截图
我们将为识别国籍、宗教和政治团体的NORP
类型重复相同的模式。
norp_list = []for ent in tokens.ents:
if ent.label_ == 'NORP':
norp_list.append(ent.text)
norp_counts = Counter(norp_list).most_common(20)df_norp = pd.DataFrame(norp_counts, columns =['text', 'count'])
这是我们得到的结果:
作者截图
奖励回合:可视化
让我们创建一个df_norp
数据帧的水平条形图。
df_norp.plot.barh(x='text', y='count', title="Nationalities, Religious, and Political Groups", figsize=(10,8)).invert_yaxis()
作者截图
瞧,就是这样!
我希望你喜欢这个。自然语言处理是一个巨大的话题,但是我希望这个温和的介绍将鼓励你探索更多,扩展你的技能。
敬请期待!
你可以在 Twitter 或 LinkedIn 上找到我。
[1]:维基百科。(2020 年 5 月 22 日)。命名实体识别https://en.wikipedia.org/wiki/Named-entity_recognition
[2]: spaCy。(2020 年 5 月 22 日)。【https://spacy.io/】工业级自然语言处理中的 PythonT23
从数据框架到网络图
数据科学/ Python 代码片段
使用 networkx 和 matplotlib 可视化熊猫数据帧的快速入门指南。
照片由 Alina Grubnyak 在 Unsplash 上拍摄
我非常偶然地发现了如何从 JIRA 导出数据,于是我开始想办法将信息可视化,并从数据集中收集一些见解。我偶然发现了网络图的概念,这个想法很快抓住了我的想象力。我意识到我不仅可以用它来讲述人与人之间的关系,还可以用它来讲述单词之间的关系。但是 NLP 是个大话题,我们先走后跑怎么样?!
这只是一个非常温和的介绍,所以我们不会在这里使用任何花哨的代码。
网络图“显示了一组实体之间的互连”,其中实体是nodes
,它们之间的连接通过链接或edges
来表示。在下图中,点是节点,线称为边。
马丁·格兰让/CC BY-SA(https://creativecommons.org/licenses/by-sa/3.0)
在这篇文章中,我将分享一些代码,这些代码将让我们使用一个流行的网络图包来快速可视化熊猫数据帧: networkx 。
首先,让我们获取数据并将其加载到 dataframe 中。你可以在这里下载样本数据集。
import pandas as pddf = pd.read_csv('jira_sample.csv')
其次,让我们裁剪数据帧,只包含我们想要检查的列。在这种情况下,我们只需要“受托人”和“报告人”列。
df1 = df[['Assignee', 'Reporter']]
第三,是时候创建图形将要存在的世界了。如果你还没有安装,通过快速的pip install networkx
来安装 networkx 包。
import networkx as nxG = nx.Graph()
然后,让我们用来自df1
数据帧的'Assignee'
和'Reporter'
列填充图表。
G = nx.from_pandas_edgelist(df1, 'Assignee', 'Reporter')
接下来,我们将在 matplotlib 的帮助下具体化我们创建的图表以进行格式化。
from matplotlib.pyplot import figurefigure(figsize=(10, 8))
nx.draw_shell(G, with_labels=True)
上面这个块中最重要的一行是nx.draw_shell(G, with_labels=True)
。它告诉计算机使用打开实体标签的 shell 布局来绘制图形G
。
瞧啊。我们得到了一个网络图:
马上,我们可以告诉有一个来自三个主要玩家的台词高度集中,“芭比娃娃”,“苏珊·李”和“乔·苹果籽”。当然,为了保险起见,用一些硬数字来证实我们的“目测”总是一个好主意。
奖励回合
让我们看看“芭比娃娃”。
G['barbie.doll']
要查看“芭比娃娃”有多少联系,让我们使用len()
:
len(G['barbie.doll'])
接下来,让我们创建另一个显示节点及其连接数的数据框架。
leaderboard = {}for x in G.nodes:
leaderboard[x] = len(G[x])s = pd.Series(leaderboard, name='connections')df2 = s.to_frame().sort_values('connections', ascending=False)
在上面的代码块中,我们首先初始化了一个名为“leaderboard”的空字典,然后使用一个简单的 for 循环将名称和连接数填充到字典中。然后,我们从字典中创建了一个系列。最后,我们从使用to_frame()
创建的系列中创建了另一个数据帧。
要显示数据框,我们只需使用df2.head()
,我们就有了自己的排行榜!
就是这样!通过几行简单的代码,我们很快就从熊猫的数据帧中制作了一个网络图,甚至显示了一个带有名称和连接数的表格。
我希望你喜欢这个。网络图分析是一个大话题,但我希望这个温和的介绍将鼓励你探索更多和扩大你的曲目。
在下一篇文章中,我将通过 Power BI 的自定义可视化工具“网络导航器”到 创建一个网络图 ,只需简单地点击几下鼠标。
敬请期待!
你可以在 Twitter 或 LinkedIn 上找到我。
[1]:数据到即(2020 年 5 月 15 日)。【https://www.data-to-viz.com/graph/network.html】网络图网络图网络图
从决策树和随机森林到梯度推进
在垃圾邮件数据集上回顾机器学习中的关键概念
图 1:图片引用:Brett Jordan 在 Unsplash 上的照片。
假设我们希望对分类问题执行监督学习,以确定传入的电子邮件是垃圾邮件还是非垃圾邮件。 垃圾邮件数据集 由 4601 封电子邮件组成,每封都被标记为真实(或非垃圾邮件)(0)或垃圾邮件(1)。该数据还包含大量预测值(57),每个预测值或者是字符数,或者是某个单词或符号的出现频率。在这篇短文中,我们将简要介绍基于树的分类的主要概念,并比较和对比最流行的方法。
在统计学习的要素,第二版中详细介绍了这个数据集和几个工作示例。
图 2:统计学习的要素第二版。图片引用:https://web.stanford.edu/~hastie/ElemStatLearn/
数据:
垃圾邮件数据集由 4601 个观察值组成,响应为 Y ,不是垃圾邮件(0)也不是垃圾邮件(1)。该数据还包括 57 个预测值 x 。每个预测值反映了电子邮件中某个单词或字母或某个符号的频率。例如大写字母的总数,符号“$”的频率等。看一看原始数据的样本。
图 3:垃圾邮件数据集的前 15 个观察值和前几列。图片来自作者。
请注意,预测值非常小,似乎有许多零数据点。在拟合模型来帮助处理这个问题之前,我们对预测值进行对数变换。我们将ε0.1 添加到我们的日志中,以确保我们不会试图取 0 的日志。
我们还将数据集随机分为训练集和测试集。稍后我们将使用测试集来评估我们的模型性能。
决策树:
用于分类的决策树是最古老和最简单的机器学习算法之一。由于直观的解释,它们很受欢迎。然而,在实践中,他们倾向于过度拟合训练数据,这导致在试图进行预测时表现不佳(也称为高方差问题)。r 允许我们很容易地用 rpart 函数来拟合决策树。有几种方法来决定什么是“好”或“最好”的树,但通常我们使用 基尼杂质 。理想情况下,一个终端节点应该只包含一个类。混合得越多,就越不“纯粹”,树在新数据上的表现就越差。
该函数构建了几棵树,在每个点上,我们根据预测值向左或向右移动。我们可以看到,在我们的训练数据中,“$”似乎是确定电子邮件是否为垃圾邮件的最重要特征。根据' $ '的不同,我们要么向左,在这一点上检查' remove ',要么向右,在这一点上查看' hp '。不管我们的路径如何,我们最终会到达一个终端节点,在那里我们的电子邮件被分类为垃圾邮件(1)或非垃圾邮件(0)。在我们的根节点,我们有 100%的训练样本。根据 log 的值($+0.1),我们要么向左(76%的情况下发生),要么向右(24%的情况下发生)。中间的数字代表那个节点的‘杂质’。我们的根节点有大约 40%的杂质,因为我们的训练数据包含大约 40%的垃圾邮件。
图 4:适合垃圾邮件数据的简单决策树。符合对数(预测值+0.1)。在每次分割时,我们查看预测器来确定我们下一步要去哪一侧。作者使用 r。
一旦我们将模型拟合到我们的训练数据,我们就可以看到它在我们的测试数据上的表现。这是通过把我们的新例子放入树中并遵循指示的路径来完成的。为了评估性能,我们检查混淆矩阵。我们获得了相当高的 91%的测试准确度。
图 5:我们混淆矩阵的总结。我们使用一个简单的决策树获得了低于 91%的准确率。图片来自作者。
随机森林和装袋:
在决策树中,我们的算法构建了几棵树,并选择了一棵我们认为是“最好”的树。然后,我们用这一棵树对新邮件进行预测。 Brieman 通过引入两个关键概念,对这些简单模型进行了大幅改进。首先是装袋或引导聚集,最后是随机森林。这些组合了许多(数百或数千)树,我们从我们的观察和预测中随机抽取样本来形成新的树。
随机森林通过对多棵树进行平均,极大地减少了过度拟合的可能性(即减少了方差),这有时被称为群体智慧。
Hastie 在一次演讲中描述了以下内容(参考资料链接):
- Bagging (Breiman,1996):“将许多大树拟合到训练数据的自助重采样版本,并通过多数投票进行分类。”
- (布雷曼 1999) :“更好的装袋版本”
本质上,随机森林利用套袋形成数百棵树。由于 bagging 的定义排除了一些模型中的某些观察值,我们可以使用不包含某个观察值的树来获得“超出 bagging 误差”的估计值。我们还可以通过观察哪些预测因子在许多树中始终是重要的,来获得对最重要特征的估计。注意,自举聚合通常会导致预测值的去相关。因此,如果我们有一些基本相同的预测器,随机森林应该能够梳理出这些预测器,并且只保留一个副本。
图 6:使用 randomForest 函数的测试数据的混淆矩阵。图片来自作者。
我们使用 R 中的 randomForest 包来拟合一个模型。我们还可以保留我们的树中包含最多的变量,这允许我们可视化“变量重要性”。我们将准确率从不到 91%提高到了 94.6%。
图 7:可变的重要性。统计学习的要素,第二版。https://web.stanford.edu/~hastie/ElemStatLearn/
随机森林的一个伟大之处在于,它们还允许我们保留预测者的“相对重要性”。图 7 总结了在确定垃圾邮件时哪些符号/单词是重要的,哪些是不重要的。
梯度提升:
- Boosting (Freund & Shapire,1996): “使许多大树或小树适合训练数据的重新加权版本。按加权多数票分类。”——哈斯蒂。
梯度推进是对随机森林的一种改进(如果你调整好超参数的话)。现在,我们不再仅仅拟合引导聚合树,而是考虑中间树的表现。使用这些中间树,我们调整未来树的权重(我们对某些树的权重大于其他树)。这可以认为是重复拟合我们模型的残差。我们从一个基本模型开始,看看它如何预测新的观察结果。残差是我们在预测方面做得不好的地方,所以我们将我们的下一棵树拟合到这些残差,以此类推,以说明我们做得不好的地方(我们也不使用 bagging,而是用替换进行采样)。梯度推进也倾向于创建许多“浅”树。也就是说,它们包含一个根节点和少量的后续分割。通常,他们只包含一个单一的分裂,这些被称为“树桩”或“弱学习者”。
- **“梯度提升继承了树的所有好的特征(变量选择、缺失数据、混合预测器),对弱的特征进行了改进,比如预测性能。”——特雷弗哈斯蒂
图 8:说明装袋的图像。图片引用:知识共享。
图 8 示出了上面讨论的装袋。装袋可以被视为一种并行工作的算法。也就是说,装袋是通过选择多个同时替换的器械包来完成的。
图 9:展示了一般的增强方法。图片引用:知识共享。
装袋和助推是不一样的。如图 8 所示,Bagging 是并行完成的,用于形成几组观察值来构建模型。Boosting 实际上使用中间树来调整计算最终预测时使用的权重。如图 9 所示,boosting 不是并行完成的,它会随着进程更新权重。
我们使用 R 包“gbm”对数据集进行梯度增强。使用梯度增强进行拟合需要
超参数 n.trees、interaction.depth 和 shrinkage 可以使用网格搜索和交叉验证来调整。我们将相互作用深度设置为 6,这允许六阶相互作用。
图 9:我们使用梯度增强获得了最佳精度,精度超过 95%。图片来自作者。
我们已经将测试数据的准确率提高到了 95%以上!
总结:
基于树的分类仍然是当今使用的最流行的算法之一,主要是因为它易于解释并且能够处理大量的预测值。决策树是基于树的方法中最基本的,并且可以容易地解释,但是非常容易在训练数据上过度拟合。幸运的是,这些年来已经有了一些改进来解决简单决策树所面临的弱点。随机森林利用 Bagging (Bootstrap Aggregation)来获得许多树,并使用群体的智慧来获得较低的方差预测。提升树通过考虑中间树的表现进一步改进了以前的算法,并调整树以在它们以前表现不佳的地方表现得更好(并对强大的树加权更多)。所有这些技术和方法都很容易在 R、Python 和其他编码语言中使用。尤其是梯度推进仍然是机器学习竞赛中最受欢迎的算法之一,例如 Kaggle 上举办的那些竞赛。**
我希望这篇文章提供了这些基本 ML 技术的广泛概述和简单示例。感谢阅读!
代码:
来源:
[1]特雷弗·哈斯蒂的演讲,助推,https://www.cc.gatech.edu/~hic/CS7616/pdf/lecture5.pdf
[2]利奥·布雷曼(1996 年)。打包预测值。机器学习**
[3]利奥·布雷曼(2001 年)。随机森林。机器学习**
[4] 哈斯蒂,提比拉尼,弗里德曼(2009)。统计学习的要素 2。
[5]j . h .弗里德曼(2002 年)。随机梯度增强。计算统计&数据分析, 38 (4),367–378。
[6] Liaw,a .,& Wiener,M. (2002 年)。randomForest 分类和回归。 R 新闻, 2 (3),18–22。
[7]杰努尔、波吉、J. M .和图洛-马洛特(2010 年)。使用随机森林的变量选择。模式识别字母, 31 (14),2225–2236。
泰国曼谷从工程到数据科学的转变
办公时间
将你的职业生涯转移到数据科学领域的初学者指南
D ata 科学仍然是当今泰国最具吸引力的趋势。与两年前相比,现在有许多数据科学家、数据工程师和数据相关职位的空缺。我也是跳进这个领域的人之一。我想和大家分享一下我转行到这个领域的历程。
决定
2017 年,我是一名机械工程师,在泰国罗勇省的石化工厂工作。通常,我会向管理团队做一个关于机器故障原因或如何防止机器故障的演示。当时,我有机会利用数据来确保和回答大多数技术问题。
有一天,我意识到罗勇不是一个适合我定居的地方。我想回曼谷,所以我需要找到一种方法来重新安置自己。我正在找工作,很难找到一份好的工作,因为我的背景是机械工程,在曼谷并没有很多好的工程工作。因此,我决定从工程领域转到数据领域。
入门指南
首先,我收集了有关这一领域的信息,这在当时的泰国是相当新的。我也开始参加在线课程,看看这个主题是否是我继续前进的正确选择。幸运的是,我选修了斯坦福大学最著名的机器学习课程“机器学习”。该课程由吴恩达(Coursera 平台创始人)教授。由于吴恩达精彩的解释,每一件复杂的事情都变得简单易懂,同时也变得有趣。我决定在那之后修几门课,因为我觉得在这个新领域很愉快。
其次,我进入了名为“Kaggle”的平台。对我来说,这是迈向数据科学领域的真正起点。我参加了许多比赛,学会了如何通过内核编写数据分析代码。对于新手来说,内核是一个很好的资源,可以让你想学多少就学多少。几种内核可以加速您的数据技能,如探索性数据分析(EDA)、建模、集成、堆叠和其他特殊的数据处理技巧和诀窍。
还有,我在转行阶段拿了应用统计学硕士。我希望扎实的学术背景能帮助我抓住新的机会。然而,这并没有我预期的数据科学工作那么重要。我建议任何对这个领域感兴趣的人去寻找 Kaggle 用例,或者自己开发。坚实的用例在说服你的面试官时非常重要。
需要多长时间?
在申请数据科学家职位之前,我花了大约 8 到 9 个月的时间研究和探索 Kaggle 平台。那是 2018 年年中左右。在泰国,没有多少公开的数据科学家职位。大部分分析工作仍然在商业智能和分析师领域。我认为 Linkedin 是你进入这个领域的一个有益的工具。在泰国,许多信息技术或数据职位已经放在 Linkedin 上,招聘人员非常积极地寻找该职位的候选人。我真的建议你们专业点。
提交了很多申请后,我面试了几家公司,从初创公司到有限公司。有幸有机会去泰国最大的银行面试,和数据科学家这个职位钉在了一起。Kaggle 竞赛对我获得第一份数据科学家工作帮助很大,因为有一个名为“数据挑战”的面试测试,你有有限的时间来完成分析/建模任务,并在一天结束时向面试官展示。我从 Kaggle 竞赛中获得的模式和最佳实践让我如此自信和舒适。
到目前为止我所做的
从那以后,我已经做了大约 3 年的数据科学家/分析师。我涉足的领域很多,例如,贷款、投资、保险、酒店和商业建筑等。做数据科学家的好处是有很多机会接触很多业务运营领域。另一方面,缺点是数据永远不会被清理。我们不得不花大部分时间净化、探索、理解,以提取有意义的洞察力。有时候这让我很难过,但是花在分析上的时间是值得的。当你在 A/B 测试阶段看到指标上升时,这是如此令人震惊。
差别
与我学习在线课程和参加 Kaggle 竞赛时相比。我想指出我得到这份工作前后的区别。
建模部分是所有数据科学任务中最令人兴奋和愉快的部分,但是与其他任务相比,我花在这上面的时间最多只有 20-30%。
就像大家在数据科学博客中指出的,最耗时的任务是数据清理,我想把范围扩大到数据理解和修正。我在 Kaggle 竞赛中看到的所有漂亮的数据框架都不是现实生活中存在的。我需要与多方合作,以获得我们必须分析的数据的真相。在我们根据这些数据做出决定之前,有许多事情需要核实。这不像 Kaggle 竞赛,我们提供了完整的元数据来阅读。有时,没有人知道操作过程的有效和准确的数字,因为根本没有看过数据。
第二项耗时的任务是数据分析团队和业务运营部门之间的来回流程。大量的会议和交流在这里起着至关重要的作用。您知道需求可以根据您向其提交分析的人而动态地改变。如果他们有足够高的职位,他们可以根据自己的喜好请求添加任何内容。你必须明智地说服并推荐他们,这样我们才能顺利地通过实施阶段。
了解这种差异可以帮助你们重新调整从事数据科学工作的期望值。我听到许多人抱怨工作范围没有他们期望的那么有趣,或者他们要等多久才能做建模。我希望这能让你对数据科学的日常生活有一个更清晰的认识。
下一步是什么
现在,泰国的数据领域与 2 年前相比增长了很多。许多人已经将他们的分析用例交付给内部企业。管理团队开始意识到在他们自己的组织中拥有数据团队的好处。即使有些人对数据能做什么有误解,这对那些不在技术领域的家伙来说也是正常的。我们需要不断告诉他们利用数据的正确方法及其对业务的重要性。
对我自己来说,我仍然喜欢日常的数据操作,也期待着向数据工程学科扩展我的专业知识。当你知道模型能做什么时,就好像你有神奇的工具来影响销售/推荐产品。然而,它需要将正确的数据输入到模型中,以获得有希望的预测结果。数据工程是控制数据管道质量和完整性的答案。我希望这是一个正确的选择,让我在这个领域有一个光明的未来。
我希望这能鼓励那些有兴趣将工作/责任转向这个领域的人。我认为这个行业仍然需要许多人和社区在整个混乱中实现可持续发展。让我们加入进来,一起产生影响。
从金融到电信:在西班牙建立数据科学职业生涯
虽然数据科学角色在旧金山和纽约已经变得无处不在,但该领域在世界各地仍处于早期阶段。在欧洲,传统公司开始采用预测分析的思维模式,为决策提供信息。
进入这个领域的最好方法是利用你以前的分析或技术经验,再加上硕士学位或训练营。我与 Euskaltel 的首席数据科学家 Ignacio Vilaplana 坐在一起,他是从风险管理职业转型过来的。
你能分享你的故事吗?
我最初来自西班牙南部。你听说过赫雷斯吗?它是雪利酒的发源地,至今仍在那里酿造。在农村。这不是一个你会想到会有很多数据科学家的地方。
从小到大,我一直热爱科技。我想从事工程方面的职业。我去了马德里,学的是电信工程。在我完成学业后,我去埃森哲工作,成为一名程序员。
我和其他程序员一起帮助管理项目,并向我们的客户交付项目。我在那里呆了几年。然后,我转向了银行业。
我受雇于西班牙两大银行之一的 BBVA 银行,担任风险分析师。因为我的技术背景,我开始和 quants 并肩工作,把他们的项目交付给银行的风险领域。
我开始学习更多的金融定量模型。构建金融产品有许多复杂的方式。当你为客户创造产品时,理解这一点会给你带来优势。我还学会了如何管理和评估这些产品带来的风险。
几年后,我搬到了桑坦德银行。我在那里呆了将近四年。我继续从事技术方面的工作。我与量化团队密切合作。与此同时,我开始攻读定量金融学的硕士学位。
我在工作的时候完成了这个。它专注于传统的数学金融,但也引入了现代数据科学的概念。我发现数据科学中的技术可以产生类似于使用复杂的数学公式甚至长时间模拟的结果,这需要大量的计算能力来计算数十万种产品的价格。
有时候,你可以从机器学习模型中获得相同的值。在那里,我了解了什么是机器学习模型,以及一般的数据科学。
我对可能发生的事情感到惊讶。我开始学习越来越多。我开办了一个数据科学训练营,是在工作的时候完成的。我想说,这甚至比我过去的两个金融硕士还要密集。我没想到会如此激烈,但我喜欢完成所有的项目,也喜欢学到许多新概念。
与此同时,我搬到了英国,因为我的妻子找到了一份更好的工作。当我结束训练营时,我不得不开始在一个新的县找工作。幸运的是,对数据科学家的需求很大。当我被 Atom bank 雇佣时,我还在训练营做我的最后一个项目,Atom bank 是一家数字银行。
我不确定有多少人意识到这有多重要。如果你正在向数据科学转型,你将在你工作过的行业中最成功地分析数据。
是的。我从初级数据科学家做起,因为我有金融行业经验和足够的数据科学经验来帮助他们建立模型。
几年后,我再次回到马德里,这次是作为 DataRobot 的数据科学家。这是一个巨大的机会,因为我帮助了很多客户解决他们的问题。
我大致了解了西班牙大量公司的人工智能成熟程度。他们真正的问题是什么,他们倾向于拥有什么样的数据基础架构,甚至是他们组织内部的人员。
这是对西班牙数据科学行业的宝贵概述。如你所知,由于病毒,很多公司都进行了裁员,DataRobot 就是其中之一。在西班牙工作的 9 人中,有 7 人被解雇。我是其中之一。
我以为运气好的话要两三个月才能再找到工作。仅仅两周,我就收到了两份工作邀请。我决定接受西班牙北部一家电信公司的邀请。我是首席数据科学家。我在公司负责 ML/AI 项目。这是更多的责任。我们有许多项目正在进行中。我很期待这个新角色。
我一直在 LinkedIn 上关注你。我看到了你关于被解雇的帖子,然后两周后又被新的职位录用了。我以为我看错了什么。
在英国和西班牙,数据科学工作的面试是怎样的?
说实话,我在英国参加的面试不多。由于我有金融方面的经验,我在最初的求职中瞄准了银行和相关公司。我的经验帮助我很快找到了一份工作。
我找新工作的时候,面试了 DataRobot 和其他几家公司。我是 DataRobot 的超级粉丝,所以我确保我为面试过程做好了准备,并能够获得录用。然而,当我在没有任何通知的情况下被 DataRobot 解雇时,我发现自己没有工作。
我对此没有准备。我开始申请很多地方。这是我第一次参加很多面试。我在西班牙公司的经历不同于英国(Atom bank)和美国(DataRobot)公司。
在西班牙,有两种面试。一种与你在英国或美国会发现的相似。面试有很多步骤,对于某些步骤,你可能需要解决一个问题。您可能需要演示如何使用实时编码,或者您可能需要演示您的编程、SQL 或如何创建基于数据的模型的知识。我参加的 30-40%的面试都是这样安排的。这些面试是由有技能的人进行的,他们花时间创建一个强大的流程,并想看看你如何解决问题。你需要在这些面试中投入大量时间。我的建议是确保你想要这些角色,否则你会浪费很多时间来完成面试挑战。有些挑战甚至需要几天的努力。在我收到的两个提议之一中,我花了一周时间为他们准备一个模型,然后我接受了数据组织所有成员的面试。花了很多时间才拿到最终报价。
其他 60–70%的采访是由不知道数据科学是什么的人完成的。他们不知道该问什么。你可能是他们要雇佣的第一个数据科学家。他们不确定你是否是 IT 人员,他们不确定如何评估你的知识水平。就像被一个不知道你在做什么的 HR 成员面试一样。我感觉那些公司暴露了。他们不知道如何评估你的经历,也不知道是否可以信任你。即使组织中负责评估你的个性或你喜欢如何在团队中工作等等的人面试你,你也需要向他们证明你不仅精通数据科学,而且你可以解决问题。
如果你是唯一一个要处理模型或数据的人,那么你需要证明你能独立解决问题,你是独立的,有决心的,积极主动的。
我注意到你得到了提升,而且升得很快。
离开金融领域的高级职位开始新的职业生涯是什么感觉?
当我开始职业转型时,这是一个巨大的风险。我在桑坦德银行有个好职位。在我之前的工作中,我在 BBVA 领导团队。当我开始担任这家英国银行的初级成员时,这是一个艰难的决定。银行里和我职位相同的其他人都比我年轻 10 岁。我已经在大得多的银行工作并向高层汇报。但说实话,我并不在乎。
我知道如何管理项目,以及如何或多或少地在一个大的组织内部活动。一旦你知道如何做到这一点,你可以在另一个领域复制它。然而,我不知道数据科学的技术方面。我不得不从头学起。在银行的时间对此很重要。
当我转到 DataRobot 时,我处于一个更好的位置,不仅可以为 DataRobot,也可以为他们的客户提供更多价值。现在,我觉得我在管理项目,就像在大银行一样,但对于电信公司来说,我是从我热爱的技术角度来管理项目的,这就是数据科学。
我把我的旅程视为爬山。在我之前的职业生涯中,我一直在上升,在金融领域已经很高了。然后有一个下降,然后我又迅速上升。主要是因为数据科学急需新的人才。如果你在正确的时间在那里,你有正确的经验,他们会给你责任。
你未来的职业发展方向是什么?是继续做个人贡献者,还是晋升到管理层?
我不想和技术面脱节。这是我喜欢做的事情。我喜欢写模型,看数据来发现一些可能被人忽略的东西。这是对数据的技术好奇心,类似于人们喜欢在 Kaggle 上竞争的原因,但在一家公司内部解决真正的问题。
另一方面,我喜欢解决公司的大问题,并在公司内跨职能部门工作,交付项目并解决这些问题。要解决那些问题,你需要有更高的视角。
在未来,我认为自己是一个混合角色,既要负责技术方面的工作,又要对他们在公司创造的价值负责。
这个领域有哪些让你感到兴奋的趋势?
我感到兴奋的一个趋势是人工智能的民主化。这是我们每年看到的越来越多的事情。云提供商正在创造工具和平台,使交付价值变得更加容易。我们正朝着这样一个方向前进,在这个方向上,部署预测模型将需要更少的编程和技术知识。
现在有一些工具可以让你上传数据。数据清理、准备、特征提取和分类是自动化的。你只需要确定你得到的解决方案和答案是你想要的。你仍然需要知道你在做什么,但是你需要更少的数学和编程知识。
在西班牙,没有足够的数据科学家。我们需要有足够数据科学经验的人来维护他们的模型。数据科学家不仅在你为项目创建算法时需要,在你将项目投入生产时也需要。
你需要有人持续关注这个模型,以确保它给出的答案是正确的,它接收的数据是正确的,并且一切都有意义。你需要知道什么时候重新训练模型,什么时候不需要重新训练。你需要一个了解整个项目的人。自动化工具使这一过程变得更加容易。
我发现的另一个令人着迷的趋势是人工智能中的伦理概念。这越来越重要,也是我所关心的事情。不是把数据科学比作医生,而是医生必须考虑他们所有行为的道德性。
数据科学家的模型和预测会影响许多人的生活,这种情况比人们通常理解的要多。它会影响一些人是否能买房子,或者一些人是否能贷款买车。将来,它可能会决定一个人是否能够接受医疗手术。模型做出的决定对人们的生活有很大的影响,这些模型做出这些决定的原因需要明确。
同样重要的是,输入到模型中的数据是公开和透明的。客户需要知道你为什么要这些数据,为什么要保存这些数据。关于处理人们的数据的道德方面也很重要。这是目前普遍理解的事情。我们有关于如何处理数据的法规和指南,比如欧洲的 GDPR。
我们仍然没有一个关于如何在人工智能中操作道德的同质框架,但社区正在继续发展并产生更多影响。你报道一个模型如何工作以及为什么工作的方式可能会有所不同。你需要透明地报告这个模型正在做什么,为什么它正在做它正在做的事情,以及它对人和企业的影响。这是我们在项目期间的责任。
工作之外,你有什么副业或爱好?
我喜欢的一项活动是瑜伽。在我知道这是什么之前,我认为这是一件奇怪的事情。当我遇到我的妻子时,她做瑜伽,虽然我觉得她做瑜伽有点疯狂,但渐渐地,她让我相信这一点也不奇怪。我现在可以说,我比她更热爱瑜伽。我几乎每天都练习,甚至比她还多。这是一项我能够在 COVID 前后保持相同水平的活动
我也试图帮助其他人更接近技术。我一直在帮助孩子们学习如何编码。我在英国的时候就开始这样做了。我也在马德里成立了一个小组,所以我已经做了将近三年了。这种事情已经停止了,因为这是一种面对面的活动。然而,我现在已经开始与非政府组织合作。他们通常不能雇人来管理他们的数据。我在马德里和一群人一起工作。我正在帮助非政府组织了解如何获得更好的融资,以及如何对社会产生更大的影响。
你会给那些对这个领域感兴趣的人什么职业建议?
这里是再次提及非政府组织的好地方。人们去很多地方学习如何做数据科学。他们通常去上在线课程,这些课程有时是免费的,有时是付费的。他们开始在 Kaggle 上完成数据科学挑战。之后,他们希望被一家公司雇佣。然而,这通常不会发生,因为他们没有数据科学方面的经验。
我所做的是鼓励那些想转向数据科学的人开始帮助非政府组织。非政府组织不在乎你没有经验,因为即使你没有经验,你也有他们需要的知识水平,而这是他们找不到的。如果你免费帮助一个 NGO,你可以处理现实生活中的场景和现实生活中的数据技术。帮助非政府组织意味着你将对社会产生影响。你将能够在面试中利用这段经历。这是很多人没有想到的一件大事。我已经和一些想转向数据科学的人一起工作了。这对他们来说太棒了。他们获得的经验是,在为社会做有益的事情时,他们需要被雇用。
好主意。在美国,我们有 DataKind 和 Statistics without Borders,人们可以在那里做志愿者。
谢谢你接受采访。
没问题。谢谢你。
为什么你应该在你的离线 A/B 测试中使用贝叶斯方法
从频率主义到贝叶斯主义
在假设检验方面,贝叶斯方法可以取代经典的统计方法。这里将使用非常具体的 web 分析案例来说明我们的演示。
由 Carlos Muza 在 Unsplash 上拍摄的照片
第一次介绍贝叶斯方法在经典统计学中的重要性可以在这里找到,还有一个更高级的应用那里!
假设检验是统计学中的一个中心话题,它的应用范围很广,超出了数学的界限,扩展到了大多数科学领域。
我们将强调常规统计频率方法的局限性,并提出一个相关的贝叶斯框架来解决在零售或营销领域工作的数据科学家可能遇到的最常见的情况之一: A/B 测试。
问题陈述
A/B 测试(也称为桶测试或分批次测试)是一个随机实验,有两个变量,A 和 B。这是一种比较单个变量两个版本的方法,通常是通过测试受试者对变量 A 和变量 B 的反应,并确定两个变量中哪个更有效。[维基百科]
也许我们想测试我们网站的新设计、新功能,甚至是针对我们客户的新策略(邮件、RTB 等)。),以衡量哪一个会带来最高的投资回报率。为了清楚起见,我们将考虑一个广告商试图使用两个创意 A 和 B 中的一个来提高转换率的情况:广告与用户的每次互动都可以被视为一个伯努利试验,正好有两种可能的结果,“转换”和“不转换”,这取决于用户是否在看到广告后购买了我们的产品。
可以考虑两种设计来进行该实验:
- 离线:实验运行,结束后才进行分析和决策。(这个故事中我们只考虑这个设计)
- 在线:分析和决策是在实验过程中做出的。
对于这个故事,只有离线的情况将被处理,因为在线的 A/B 测试问题需要完全不同的解决方案。
频率主义方法:p 值和 ROC 曲线
我们考虑为弱者运行测试的情况,向每个用户展示概率为 0.5 的创造性 A 或 B,并直接转换为未知概率 p_A=0.04 或 p_B=0.05。
第一个困难很快就出现了:为了确定一个创意是否明显优于另一个创意,我们应该使用什么测试?下表总结了常见的测试,由我们选择最适合我们问题的测试。
来源:维基百科
在我们的案例中, Fisher 精确检验和 Barnard 检验似乎是最相关的,因为我们关注的是从二项式分布中获得的转换率,尽管考虑到我们将在实验中获得的观察值数量,卡方检验也可以使用。
我们将使用 Fisher 检验,它具有属于精确检验类的特征,之所以这样叫是因为它的 p 值可以精确计算,用
- H0:创意表现相当(p_A = p_B)
- H1:一个创意比另一个表现得更好
良好实践希望我们确定测试的统计功效。它可以通过模拟来计算,给出我们的环境是如何具体设计的。我们的目标是 0.8,为了达到这个阈值,我们将校准我们将使用的观测值。为方便起见,我们将只考虑一个替代假设”(H1)“替代假设 p_A=0.04 或 p_B=0.05 ”,这将使我们很容易计算出我们的检验的功效。
测试 13500 和 10000 次观察的 ROC 曲线
通常α= 0.05 是 p 值拒绝区域可接受的极限,换句话说,就是假阳性率。对于这个阈值,将需要至少 13500 次观察的平均值。
解释测试的结果
我们面临着和我们在这里做的相似的情况,问我们自己相似的问题。从我们的测试结果和 p 值中我们可以得出什么结论?
- 我们有办法估计创意 A 优于创意 B 的概率吗?
- 如果是这样,我们能估计它们之间的改进吗?
我不会再让你担心了。这两个问题的答案都是否定的。我们已经知道 p 值仅仅是在假设(H0)下观察结果的一种概率,至少是极端的。但这也凸显了 p 值最重要的局限性:
p 值不是效应大小的量度!它没有给我们任何关于创造性的 A 比 B 表现好多少的信息,即使是在正面结果的情况下!
为了提取关于效应大小的知识,常客可以使用另一个更强大的工具:置信区间。
置信区间。
置信区间表示未知参数的似是而非的值的范围,与真实参数在建议范围内的置信水平相关。
正因为如此,竞争情报给了我们更容易理解和丰富的洞察力,为我们提供了关于我们估计的概率和不确定性的知识。然而它们也有自己的缺点:
- 我们需要选择不同的方法来定义这些区间,这取决于许多假设:二项分布的置信区间。
- p_A 和 p_B 值的置信区间不能直接转化为 p _ A 和 p_B 之间差值的置信区间!幸运的是,存在直接计算差值置信区间的方法,然而,我们需要从几十种方法中选择一种。
例如,我们可以使用“最简单的”,即没有连续性校正的 Wald 方法:
无连续性修正的沃尔德方法
用𝑝̂对 p_A et p_B 的经验估计,z 对应于正态分布的α/2 百分位。因此,对于 95%的置信区间(即α=0.05),相应的 z 值为 1.96。
数值应用将给出区间[0.0009;0.0171]以 0.009 为中心,没有像我们希望的那样与 0 重叠!
贝叶斯方法:简单之美
对于这一部分,我们将使用 python 的 PyMC3 库,这使我们可以轻松地构建贝叶斯非参数模型。
重要的是要记住,作为统计学家或数据科学家,我们的目标显然是构思准确和相关的结果,但同样重要的是,要生成可以被任何其他利益相关方(甚至是非科学家的利益相关方)共享和理解的 KPI,并且包含尽可能多的信息。贝叶斯方法给了我们这样做的工具,它允许我们精确地计算我们正在寻找的东西:P _ A 和 p_B 的后验分布,即 P(p_A|X)和 P(p_B|X)以及 P(p_A — p_B > 0| X),即。创意 A 比创意 b 产生更多转化的概率。
这里,贝叶斯建模再次变得非常简单,因为我们已经用数学方法设计了环境,我们只需要用贝叶斯语言复制它。
先验选择的问题不可避免地出现了。我们将为 p_A 和 p_B 选择无信息的制服先验。
我们还可以计算贝叶斯网络的图形表示:
贝叶斯网络
就这么简单,我们的工作结束了!我们剩下的工作就是通过网络运行 MCMC 算法来计算后验分布。这些将给予我们比以前的方法更多的洞察力,因为现在我们可以通过从后验样本直接得到任何α水平的置信区间。
MCMC 抽样估计的 p_A,p_B 和 delta = p_A — p_B 的后验分布
(重要的是要注意,δ不能从 p_A 和 p_B 的后半部分计算,因为 p_A 和 p_B 可能是相关的)
结果
然后,我们可以简单地计算δ小于 0 的后验概率:
np.mean(delta_samples<0)
这里我们得到 0.956,这相当于创意 A 比创意 B 有 96%的可能性产生更多的转化!
但是我们可以更进一步。设想从设计 B 转移到设计 A 是昂贵,且已经确定只有至少 5%的性能改进才是有利可图的。我们有办法计算这个!只需在我们的网络中插入一个新的确定性变量 Tau = p_A / p_B 并对后验分布进行采样。
tau = pm.Deterministic(“tau”, p_estimates[0] / p_estimates[1])
从 MCMC 抽样估计的τ的后验分布
np.mean(tau_samples>1.05)
这次我们得到 0.91……不像我们通常希望的 95%那样具有决定性。如果我们需要更多的信心,我们只需要运行 A/B 测试更长时间。
结论
- 贝叶斯框架为 A/B 测试的经典方法提供了一个易于执行的和易于阅读的替代方案,并允许我们通过简单地计算后验分布来测试任何假设。
- 贝叶斯方法使我们能够在 A/B 测试的情况下实现更有效的离线决策,以及更有效的在线决策,这将在另一个故事中展示。
评论
对于 frequentist 方法,我们必须选择一个特定的测试和一个特定的方法来计算我们的置信区间,其他测试和区间计算会给出不同的值;就像不同的先验会给我们不同的后验一样。
更进一步
贝叶斯网络的应用很多,A/B 测试只是冰山一角。当它被证明是一个非常强大的工具时,它可以用于建模和机器学习,正如你可以在文章中读到的:
[## 贝叶斯分层建模(或者“autoML 还不能取代数据科学家的更多原因”)
贝叶斯网络允许我们对协变量之间的实际关系进行建模,弥补所提供信息的不足…
towardsdatascience.com](/bayesian-hierarchical-modeling-or-more-reasons-why-automl-cannot-replace-data-scientists-yet-d01e7d571d3d)
参考
- 卡梅隆.戴维森-皮隆。(2015)黑客的贝叶斯方法:概率编程和贝叶斯推理
假设检验,贝叶斯框架优越性的简单说明
从频率主义到贝叶斯主义
当谈到假设检验时,贝叶斯方法可以取代经典的统计方法,我们将通过一个简单的例子来说明:不公平硬币。
通常假设检验并不是我们谈论贝叶斯主义时首先想到的话题。目前的趋势确实是更多地将这种方法纳入机器学习模型,而不是审查老式的统计数据。
然而,越来越多的研究揭示了许多研究论文的失败程度,这些失败可以归因于对“初级”统计方法的误解/误用。鉴于这种现象的程度,很明显,这并不是科学家个人在这方面缺乏认真的结果,而是一种已经持续了相当长时间的全球系统性异常现象。鉴于此,似乎应该考虑更直观、更易于解释的方法。
对什么是 p 值的误解是这种情况的根源,或者至少最能体现这一现实。如今,当谈到机器学习时,大多数数据科学家都受过良好的教育,甚至连最基本的统计概念都受到了损害;假设检验就是其中之一。
我们现在将探索一个统计学家可能必须运行的最简单的测试之一,并从那里了解如何建立一个贝叶斯方法,它允许一个简单而直接的结论。
问题陈述
我们将考虑一个最简单的实验,为了不忽略我们想要用不必要的卷积来证明的观点:抛硬币。问题是这样定义的:
- 一枚硬币可以被翻转有限的次数。
- 我们的目标是找出这枚硬币是否公平。换句话说,我们想知道我们的假设(H0)“硬币是公平的”有多大可能是假的。
很简单,对吧?
实验设计:p 值和 ROC 曲线
实验的设计应该考虑到将用来回答我们问题的统计方法。学生 t 检验似乎是我们假设检验的一个明显的选择。我们将样本的平均值与数值 0.5 进行比较。
良好实践希望我们在设计研究时计算统计功效,以便估计适当的样本量,或者至少告诉我们样本量已经固定时研究的局限性(通常要求功效至少为 0.8)
换句话说,测试的能力是当硬币实际上不公平时,在指定阈值下获得 p 值的概率。
为了方便起见,我们将只考虑另一个假设(H1)“硬币遵循参数 p = 0.4 的伯努利定律”,这将允许我们轻松地计算我们的测试的功效。
100°和 192°翻转的 ROC 曲线
看一下这个测试的 ROC 曲线将有助于我们理解发生了什么。对于给定的显著性水平α,我们可以通过分析或模拟得出真阳性率和假阳性率;或者换句话说,测试的统计功效和显著性水平本身。
通常α= 0.05 是可接受的极限,对于这个阈值,最少需要翻转 192 次才能达到我们的目标(因为当一个人想到娱乐活动时,翻转硬币不是第一个想到的事情,我们将限制自己翻转硬币 192 次!).
解释测试的结果
我们的问题来了。假设我们发现硬币是不公平的,p 值= 0.01,我们现在可以得出什么结论?
- 零假设为真的可能性有 1%吗?
- 我们 99%确定我们的硬币不公平吗?
这些都不是你可能已经得出的结论。事实上,在这一点上,没有办法给出我们的硬币不公平的概率…相当烦人,特别是考虑到我们最初的问题:我们的硬币有多大可能不公平?我们能得出的唯一结论是,如果硬币是公平的,我们只有 0.01 的概率观察到如此极端的结果。
事实上贝叶斯定理给了我们计算这个值的方法,但是我们需要更多的信息:先验。H0 =“硬币不公平”,H1=“硬币公平”,S =“测试成功,p 值< 0.05”,我们有:
P(H0 | S)= P(H0)* P(H0)/(P(H0)* P(H0)+P(H1)* P(H1))
最初假设我们的硬币更可能是公平的,我们设置 P(H1) = 0.9 和 P(H0) = 0.1。于是我们有了
p(H0 | S)= 0.8 * 0.1/(0.8 * 0.1+0.05 * 0.9)
P(H0 | S) = 0.64
所以即使我们的测试呈阳性,我们的硬币也只有 64%的机会不公平。与我们希望的 95%相差甚远…然而这个概率比简单的 p 值包含了更多的见解,幸运的是我们可以走得更远。这仅仅是进入贝叶斯世界的第一步,正如我们现在将要看到的,还有更多需要展开来改进我们的测试!
贝叶斯方法
对于这一部分,我们将使用 python 的 PyMC3 库,这允许我们轻松地构建贝叶斯非参数模型。
我们对一个不公平硬币(p = 0.4)的抽样建模,并计算得到的后验分布。虽然使用了非平凡的马尔可夫链蒙特卡罗 ( MCMC ) 算法,但其背后的思想仅仅是贝叶斯定理的应用。
既然我们已经理解了如何用贝叶斯术语来转置我们的常规假设检验,我们可以调整先验分布来反映我们对系统初始状态的真实信念:以 0.5 为中心的 beta 分布将强调这样一个事实,即我们认为如果硬币有偏差,它一定不会像 0 或 1 那样极端。
import pymc3 as pm
N = 192 #Sampling sizewith pm.Model() as model:
p = pm.Uniform("p", 0, 1)
observations = pm.Binomial("observations", N, 0.4)
obs = pm.Binomial("obs", N, p, observed=observations)
step = pm.Metropolis()
start = pm.find_MAP()
trace = pm.sample(100000, step=step, start=start)
burned_trace=trace[1000:]
p_samples = burned_trace["p"]
- 我们也可以像许多贝叶斯主义者建议的那样,提供非信息性的前科。例如,我们可以假设 p 在[0;1].
p = pm.distributions.continuous.Beta("p", 2, 2)
在每种情况下,我们可以直接计算 p < 0.5 from the posterior distributions.
Posteriors densities after 192 flips
print(np.mean(p_samples<0.5))
We get respectively 0.98 and 0.97 with the uniform prior and the beta(2,2) prior, informing us of the degree of confidence we have that the coin we observe is actually fair or not.
Going further
In his paper 贝叶斯估计取代 t 检验(最佳)的概率, John Kruschke 建议查看他所谓的最高密度区间,它由包含 95%后验密度的最小区间组成,以便定义我们的检验标准。
192 次翻转后的最高密度区间
例如,在我们的例子中,我们想知道这些区间是否与我们针对 0.5 测试的值重叠,并且如果 0.5 不包括在这些区间中,则得出结论(H0)被拒绝。
用密度进行推理使我们能够利用我们所能接触到的所有信息。更好的是,它允许我们从数据中捕捉所有的细微差别,并得出明确的结论。
鉴于我们必须选择一个先验,有人可能会认为我们的分析是有偏见的。我不会在这里讨论频繁主义和贝叶斯主义之间的范式差异,而是简单地回忆一下,不选择先验往往等同于隐含地选择一个。
结论
- 贝叶斯框架提供了一个易于执行的和易于阅读的来替代经典的统计测试。
- 后验密度为我们提供了更便于理解和使用的数学概念,而 p 值等概念已经被无数次地证明具有误导性。
- 最终,贝叶斯网络的概念允许我们设想更复杂的实验,并通过简单地考虑后验分布来测试任何假设,就像我们观察 A/B 测试 的情况一样。
参考
- T.V. Pereira 和 J.P.A. Ioannidis。"统计上有意义的临床试验荟萃分析可信度不高,效果夸大."临床流行病学杂志 64,第 10 期(2011):1060-1069。DOI:10.1016/j . jclinepi . 2010 . 12 . 012。
- 约翰·克鲁施克。(2012)贝叶斯估计取代了 t 检验。实验心理学杂志综述。
从 GLM 到 GBM
诺贝尔经济学奖如何给保险和贷款带来革命
作者:迈克尔·普罗克什博士;帕特里克·霍尔
简介
保险和信贷借贷是高度监管的行业,几十年来一直严重依赖数学建模。为了给他们的模型提供可解释的结果,这两个行业的数据科学家和统计学家都非常依赖广义线性模型(GLMs) 。然而,这篇文章认为现在是时候过渡到更现代的方法了。具体来说,我们致力于使用一种新型的机器学习(ML)模型,梯度推进机器(GBM)的过渡。GBM 不仅是更复杂的风险评估工具,而且由于被称为 Shapley values 、的诺贝尔奖得主突破,它们现在看起来和传统 glm 一样可以解释。对保单和信贷发行人来说,更细致的风险评估意味着更少的支出和冲销,但也意味着更广泛的客户群体可以参与主流保险和信贷市场。Shapley values 提供的高级可解释性使您能够向客户、业务合作伙伴、模型验证团队和监管机构解释模型预测。简而言之,所有这些意味着更少的损失、更多的客户和管理法规要求!你感兴趣吗?向下滚动以了解更多信息。
GLMs:满足监管要求和业务需求
在美国,许多联邦和州法规管理预测模型在保险和金融服务中的使用。例如,去年纽约金融服务部向人寿保险公司发出了一封指导函以解决“非常规来源或类型的外部数据……包括算法和预测模型中的数据”的使用问题,声明保单定价必须排除“种族、肤色、信仰、国籍、家庭暴力受害者身份、过去的合法旅行或任何形式的性取向,或任何其他受保护的类别” 以避免歧视。当然,人工智能监管不仅仅是美国现象,而是一个国际现象。至少加拿大、德国、荷兰、新加坡、英国和美国的政府已经提出或颁布了针对人工智能的法规。一般来说,这些现有的和提议的法规旨在确保预测建模过程准确、受监控、无歧视、稳定、安全和透明。
众所周知,glm 是高度稳定和透明的模型。在大型保险和金融机构的“回归艺术家”手中,它们也可以非常准确。各机构花费了数年时间来优化 GLM 方法,并围绕 GLMs 建立文档、区分测试、监控和验证流程。因此,由于数学和面向过程的综合原因,GLMs 至今仍被广泛使用。然而,新的方法可以提供更准确、更灵活、更透明的方式来创建更高级的预测模型。
Shapley values 和 GBM 相对于 GLM 的优势
GLMs 已被证明对保险业和银行业具有的巨大价值。然而,新算法在准确性甚至可解释性方面胜过线性模型。特别是,GBM 可以解决预测器和因变量之间的非线性以及预测器变量之间的交互,而无需大量手动调整。这就是为什么 GBM 通常比 glm 在样本外预测中显示出更高的准确性,从而导致重大的业务影响。(这将在这篇博文的第二部分演示。)
GBM 的解释可以基于几种技术,如累积局部效应(ALE)图、个体条件期望(ICE)图、部分相关图、替代模型、变量重要性以及最近的 Shapley 值。沙普利价值观以二战中的数学家、经济学家、密码破译者 劳埃德·沙普利【1923–2016】命名。沙普利在 1953 年介绍了他的方法,并在 2012 年因其发明获得了诺贝尔经济学奖。
从 20 世纪 60 年代开始,Lloyd Shapley 使用合作博弈理论来研究不同的匹配方法。在一个合作博弈中,其中收益必须归于做出不平等贡献的玩家,而沙普利值决定了收益的最公平分配。例如,Shapley 值可用于确定当每个人分享他们的食物时,一个组中的每个成员在餐馆应该支付的费用。Shapley 值的理论基于四个公理原则,效率、对称性、对称性和可加性,这使得这种方法与其他解释技术相比是独一无二的——甚至是我们心爱的回归系数!此外,研究表明,与其他解释相比,与人类解释有更强的重叠。
GBM 与 GLM 的区别:情景分析
信任一项新技术的第一步是,对比你习惯做的事情,看看它是如何工作的。博客这一部分的其余部分将针对 GBMs 和 Shapley 值与 GLMs 进行比较。沙普利值和 GLM 增量值计算之间最重要的区别之一是它们有不同的基线:
● GBM 和 Shapley 值基线:当所有输入变量的贡献等于 0 时,模型预测的平均值。
● GLM 基线:当所有输入变量的值等于 0 时,数据中已知结果的平均值。
因此,当预测变量的值等于 0 时,线性模型的基线(或截距)是平均预期结果,当 Shapley 值仅评估一个变量的影响时,它们总是包括所有的观察值和变量!这看起来不是更现实吗?现实世界中的什么事件是以完全独立的方式发生的?
让我们看一个更详细的例子来看看一些更基本的区别。在汽车保险方面,当投保人不在夜间开车时,只有 20%的司机不开车,他们发生事故的可能性较低。在一个简单的示例建模场景中,Shapley 值显示了与普通驾驶员相比,该客户节省的成本。相比之下,GLMs 使用非驱动因素作为基线,并将额外的风险支付值添加到该基线。知道了差异,就可以对两种情况下的增量值进行精确的比较和计算。为了显示 GBMs 和 GLMs 在准确性和解释能力方面的更多差异,我们想在汽车保险示例的上下文中引入三个场景:线性场景、非线性场景、案例和交互场景(参见图 1)。
图 1: 展示 GBM 和 GLM 区别的三个场景。
假设数据集包含每个场景的 50 个观察值。在所有三个场景中,没有这个特征的支付,比如说在晚上开车,是 50 个硬币(见图 2)。在线性关系场景中, 10 个成员都是夜间司机,他们每个人都有额外损失 50 个硬币的风险。结果显示,两个模型都是 100%准确的,总共属性 500 个硬币(所有 10 个成员)。在线性情况下,两个模型都是准确的,并且将正确的硬币数量归因于特征。第二种情况包括预测值和因变量之间的非线性关系。我们现在也观察一个人晚上开车的频率。如果你一周只开一次车,你就造成了额外 50 个硬币(8 个顾客)的损失风险。如果每周开车两次或两次以上,就是 70 个币(2 个客户)。最终归属的硬币应该加起来是 540。然而,只有 GBM 显示 540 作为结果,误差为 2%,而 GLM 显示 4%的预测误差和 503 归因硬币作为结果。最后一种情况包括变量夜间驾驶和大于 1 小时的通勤时间的相互作用。每个变量都增加了 50 个硬币作为可能的损失,但加起来就是 200 个。结果应该是 3000 个硬币,但只有 GBM 显示正确的归属,预测误差为 0%。
图 2: 三个示例场景的 GBM 与 GLM 结果。
虽然我们只显示了不同预测变量的结果归因的总和,但通过 Shapley 值得出的每个客户的归因也可能比 GBM 与 GLM 的结果更准确。每个客户的属性将在第二部分进一步讨论。
总结
在这篇博文中,我们展示了 GLM 模型和 GBMs 模型都具有很高的准确性,能够在不太现实、线性和独立的情况下提供有效的解释和归因。一旦我们更深入地研究更复杂的情况,GBM 在预测非线性和相互作用关系方面更加准确,并且它们还为每个变量的增量影响提供准确的结果。这篇博文的第二部分将更深入地比较一个更现实的信用卡违约例子的不同模型和结果。与此同时,如果你想自己比较 GLMs、GBMs 和 Shapley 值,你可以免费检查并开源 H2O-3 (或 XGBoost ,或 shap ,或尝试 H2O 无人驾驶 AI 。
从 GLM 到 GBM(下)
更好模型的商业价值
作者:帕特里克·霍尔和迈克尔·普罗克施博士
TL;速度三角形定位法(dead reckoning)
- 这篇文章从技术上概述了从可信的广义线性模型(glm)向新型梯度推进机(GBM)的过渡,同时实际考虑了已知的风险、合规性要求和业务影响。
- 它带有代码。
- 查看迈克尔·普罗克什的第一部分帖子和 H2O.ai 帖子。
介绍
本博客的第 2 部分使用了一个更现实、更详细的信用卡违约场景来展示单调性约束、Shapley 值和其他事后解释,以及判别测试如何使从业者能够在 GLM 和 GBM 模型之间进行直接比较。这种比较可以使从业者以循序渐进的方式建立从 GLM 到更复杂的 GBM 模型,同时保持模型的透明度和检验歧视的能力。在我们的信用用例中,我们表明 GBM 可以带来更好的准确性、更多的收入,并且 GBM 也可能满足模型文档、不利行动通知和区分测试要求。
一些银行家最近对贷款中的人工智能(AI)表示怀疑——这是正确的。(参见:https://www . American banker . com/opinion/ai-models-could-fight-to-hand-the-market-down或https://www . American banker . com/opinion/don-let-ai-trigger-a-fair-lending-violation。)要明确的是,我们不是提倡脑残人工智能炒作。我们希望在这篇文章的第二部分提出一个明智的、可测试的、循序渐进的方法,从 GLM 过渡到 GBM。或许很明显,我们认为 GBMs 比 GLMs 更能模拟真实世界和信用风险。我们还认为 ML 可以在保持极高透明度的同时,防止算法歧视。
本文的第 1 部分已经表明,GBM 可能不仅是更准确的预测因子,而且当与 Shapley 值结合时,它们还可以更准确地解释和归因于预测因子的因果影响。在第 1 部分的基础上,我们现在想展示贷款从 GLM 到 GBM 的过渡所带来的潜在透明度和商业利益。为了完全透明(并有望再现),我们使用了 UCI 信用卡数据,它可以从 UCI 机器学习数据集库中免费获得,以及开源 h2o-3 代码。信用卡数据集包含 30,000 名信用卡客户的人口统计特征信息以及支付和账单信息。要预测的因变量是付款拖欠。我们的用例将从技术和业务角度比较一个 GLM 和几个不同的 GBM。
机器学习可以推动商业影响
为了显示 GBM 相对于 GLM 的商业价值,我们训练了几种不同的算法(GLM、单调 GBM (MGBM)、GBM 和混合 GBM)。以下是这些模型的简短总结:
- GLM: 弹力网罚物流 GLM。
- 最大 46 棵树。深度 3,所有变量单调约束。
- GBM: 最多 44 棵树。深度 5,无单调约束。
- 杂交:最多 50 棵树。深度 14,学习了一些变量的单调约束。
正如您将在下面看到的,在我们的测试中,这些型号的预计收入有很大差异。为什么?这些模型对风险的判断不同。如果不进行人工调整,GLM 无法反映变量之间的非线性关系和相互作用。GBM 固有地模拟变量之间的非线性关系和相互作用。过去,GLMs 被认为是高度透明的,因此更适合用于商业目的。GBM 在过去被认为是黑箱。但是使用单调性约束可以赋予 GBM 与 glm 相同的内在可解释性,并且不会牺牲准确性。表 1 提供了不同测试模型及其功能的概述。
表 1:模型及其功能概述。“+”表示功能的存在。“-”表示没有能力。能力是相对于 GLM 来衡量的。
通过网格搜索选择所有模型,并使用验证 AUC 进行评估。结果见表 2。GLM 模型的 AUC 得分最低,为 0.73,而最好的 GBM 模型的 AUC 达到 0.79。太好了…但是这对企业来说意味着什么呢?
表 2:模型模拟结果。箭头表示每次测量的改进方向。货币是新台币。
为了评估每个模型的业务影响,我们做了一些基本假设,如表 3 所示。信用卡客户,我们准确地归类为拖欠客户,是中性的成本。一个准确分类的没有拖欠的客户将带来新台币 20,000 元的终身价值,一个错误分类为拖欠的客户将导致新台币 20,000 元的终身价值,而错误地向拖欠客户提供信贷将导致新台币 100,000 元的注销。
表 3:用于估计表 2 中业务影响的假设。货币是新台币。
基于这些假设,GLM 模式的结果显示最低收入为新台币 790 万元。影响最大的模式是混合 GBM,其业务价值为新台币 1922 万元,几乎是 GLM 模式的 2.5 倍!
这怎么可能呢?混合 GBM 模型在避免那些代价高昂的假阴性预测方面要好得多。这个简单的例子表明,从 GLM 到 GBM 模型的过渡可以显著增加业务价值和降低风险。现在,让我们从技术角度看一下如何比较 GLMs 和 GBMs,这样您就可以决定如何以及何时从 GLMs 过渡到 GBMs。
更好的模型,同样的透明度
事实上,GLMs 具有出色的可解释性。他们是如此可解释,因为他们的加法单调形式和他们的低程度的相互作用的变量。信不信由你,GBMs 也可以有极高的可解释性。通过单调性和交互约束的明智应用,GBM 用户现在可以将领域知识用于建模任务,增加可解释性,避免过度适应开发数据,并对何时使用何种模型做出明智的决定。(例如:https://xgboost . readthe docs . io/en/latest/tutorials/monotonic . html,https://xgboost . readthe docs . io/en/latest/tutorials/feature _ interaction _ constraint . html。)
单调性约束
用户通常可以在 GBM 中指定与 GLMs 中相同的单调性变量。在图 1(右)、中,特征 PAY_0 的 GLM 模型化行为,或客户的最近还款状态,是单调增加的。随着 PAY_0 值变大,违约概率也变大。在图 1(右)中,MGBM 使用正单调约束来模拟相同的行为——就像 GLM 一样!随着 GBM 下的 PAY_0 增加,违约概率也增加。
不同的是 GLM 的函数形式和广义相对论的函数形式。在这种情况下,GLM 被限制为逻辑曲线,而 GBM 可以采取任意复杂的阶梯形式,也遵守用户提供的单调性约束。此外,图 1 显示了 GBM 和混合模型在没有单调性约束的情况下对 PAY_0 的表现。你觉得哪个看起来更真实?图 1(左)中 PAY_0 的直方图和均值行为可以帮助您确定哪个模型最符合数据。目标是匹配直方图加权的红色平均目标线。好消息是,无论您喜欢哪种功能形式,您现在都可以用一种反映业务领域知识的可解释的方式来使用它。
图 1:PAY_0 的直方图,用红色表示目标的平均值,DEFAULT_NEXT_MONTH,用 PAY _ 0 表示(左)。每个模型的部分相关性和 ICE 估计行为(右)。通过左图中数据的频率衡量平均行为有助于衡量右边模型的拟合度。该图还允许对简单模型和更复杂的模型进行有意义的比较。
事后解释
我们如何能够看到 GBM 建模 PAY_0 的方式?通过所谓的部分依赖和个体条件期望(ICE)图[1],[2]。在图 1(右)中,部分相关(红色)显示了模型的估计平均行为。图中的其他 ICE 曲线显示了某些个体在模型下的行为。通过结合这两种方法,我们得到了一个图表,显示了我们模型的整体和个体行为。部分依赖和 ICE 只是事后解释技术的一个例子,或者说,在对模型进行训练以更好地理解其工作原理之后,我们可以在模型上运行的过程。
沙普利值,一个诺贝尔奖获得者的博弈论技术,为 GBM 模型提供了额外的和关键的见解[3]。当应用于 GBM 等基于树的模型时,Shapley 值是一个高度精确的测量变量对模型预测的影响,无论是对整体还是对任何单个客户。这对于可解释性非常有帮助,因为它支持:
- 模型预测的整体业务驱动因素分析(图 2)。
- 对单个客户的预测描述,以及潜在的不利行动通知的生成(图 3)。
- 比较 GLM 系数和对 GBM Shapley 值的贡献(图 2 和图 3)。
图 2:与 DEFAULT_NEXT_MONTH 的绝对 Pearson 相关性和每个模型的平均特征贡献。GLM 和 GBM 的贡献可以在对数优势空间中解释。该图允许对简单模型和更复杂的模型进行有意义的整体比较。
正如图 1 显示了如何从 GLM 到不同的 GBM 处理 PAY_0 的变化,现在可以直接比较 GLM 和 GBM 的总体(图 2)和每个客户(图 3)的可变贡献。在图 2 中,我们可以看到每个模型如何从整体角度处理变量,并将简单模型(如皮尔逊相关、GLM)与更复杂的模型进行比较。在图 3 中,我们可以看到每个模型是如何对三个客户做出预测的。所有这些都可以直接比较 GLM 和 GBM 对变量的处理,因此您既可以充分记录 GBM,又可以满怀信心地做出向 GBM 过渡的决策!此外,图 3 中显示的每个客户的信息还可以提供不利行动通知所需的原始数据,这是信贷中一个重要的监管考虑因素。
图 3:在 GLM 模型预测的选定百分位数,个体对预测的可变贡献。这种类型的分析允许对简单和复杂模型如何对待单个客户进行有意义的比较,并可能生成不利行动通知。
模型诊断的另一个重要方面是辨别测试,在美国的一些联邦和地方法规下必须进行该测试。当然,如果发现某些类型的歧视,那么也必须予以纠正。在这种情况下,GLMs 的透明度通常是有帮助的。然而,上面概述的约束和事后解释步骤使得在 GBM 模型中发现和修复歧视比以前容易得多。此外,ML 中良好模型多样性的概念——其中单个数据集可以生成许多精确的候选模型——提供了许多解决歧视的选项,这些选项通常对于 GLMs 是不可用的。(参见:https://www.youtube.com/watch?v=rToFuhI6Nlw。)
辨别测试
表 4。测试模型的女性(受保护)对男性(对照)的区分措施。该表允许比较简单和更复杂的模型。
在我们的信用卡示例中,使用具有长期法律和监管先例的措施来测试 GBM 的歧视性:负面影响比率(AIR)、边际效应(ME)和标准化平均差异(SMD)。这些结果见表 4。幸运的是,在男性和女性之间,我们的模特几乎没有歧视的迹象。然而,如果发现歧视,GBMs 实际上可能比 GLMs 提供更多的补救选择。
基本上,GBM 只是比 glm 有更多的旋钮可以转动,留下更多的回旋空间来找到一个准确和非歧视的模型。除了变量和超参数选择,研究人员还提出了潜在的兼容对抗方法来训练非歧视性 ML 模型[4],GBM 现在为用户提供单调性和交互约束,可以帮助修复歧视性模型结果。同样,上面描述的事后解释技术也可以用来理解算法歧视的驱动因素,并验证它们从 GBM 模型中的移除。
机器学习和合规
许多政府机构已经暗示了未来可能的洗钱管制,或者在美国以外,已经开始实施这样的管制。值得注意的是,美国政府监管机构并没有说禁止洗钱。一般来说,他们说要确保你的 ML 是有记录的,可解释的,可管理的,可监控的,并且歧视性最小。可以说,第 2 部分中概述的步骤为使用 GBM 进行可解释性和区分性测试提供了蓝图,这反过来应该有助于模型文档的各个方面。此外,大多数大型金融机构已经为其传统预测模型建立了模型治理和监控流程。这些可能适用于 ML 模型。
当然,非监管者真的没有资格评论什么符合监管,什么不符合监管。所以,你可以自己看看一些美国政府机构在想什么:
机器学习的动力
在政府之外,一些金融服务组织已经声称在受监管的交易中使用机器学习,研究人员正在发布关于信用贷款应用的 GBM 和 Shapley 值。例如,2018 年,Equifax 宣布了他们的神经决策系统,“一项正在申请专利的机器学习技术,用于合规的高级神经网络信用评分建模。”自 2018 年以来,富国银行还推出了几种用于模型验证的机器学习技术,包括 LIME-SUP [5]、可解释的神经网络[6]以及许多附加的模型调试方法。
2019 年,英格兰银行的 Bracke 等人发表了一个可解释的人工智能信用风险用例,其中包括 GBM 和 Shapley 值[7]。同年晚些时候,巴斯曼等人发表了一篇类似的文章,在《信用风险管理》杂志上介绍了一个 GBM 和 Shapley value 的例子。2020 年 3 月,Gill 等人发表了一份基于单调约束 GBM、可解释神经网络和 Shapley 值的抵押贷款工作流,该工作流仔细考虑了美国不利行动通知和反歧视要求[9]。
结论
现在看来,从可信的 glm 到更复杂的 GBM,可以采取谨慎的步骤。使用约束、事后解释和区分测试,可以将 GBM 与 glm 进行比较。这些技术也可以很好地符合不利行动通知、歧视和文件要求。幸运的话,GBMs 可以为消费者、保险公司和贷款人带来更好的财务结果。随着监管金融服务中机器学习的势头和宣传的增加,我们希望这篇文章的第 1 部分和第 2 部分将有助于那些寻求负责任地从 GLM 过渡到 GBM 的人。
参考
- Friedman、t . Hastie 和 r . TiB shirani(2001 年)。统计学习的要素(第 1 卷,№10)。纽约:统计学中的斯普林格系列。网址:【https://web.stanford.edu/~hastie/ElemStatLearn/ 。
- Goldstein,a .,Kapelner,a .,Bleich,j .,& Pitkin,E. (2015 年)。窥视黑箱内部:用个体条件期望图可视化统计学习。计算与图形统计杂志, 24 (1),44–65。网址:https://arxiv.org/pdf/1309.6392.pdf。
- Lundberg,S. M .,& Lee,S. I. (2017 年)。解释模型预测的统一方法。在神经信息处理系统的进展(第 4765–4774 页)。网址:http://papers . nips . cc/paper/7062-a-unified-approach-to-interpretation-model-predictions . pdf。
- 张,B. H .,b .,& Mitchell,M. (2018 年 12 月)。用对抗性学习减轻不必要的偏见。在 2018 年 AAAI/ACM 关于人工智能、伦理和社会的会议录中(第 335-340 页)。网址:https://arxiv.org/pdf/1801.07593.pdf。
- 胡,l,陈,j,奈尔,V. N .,& Sudjianto,A. (2018)。基于监督分割(LIME-SUP)的局部可解释模型和效果。 arXiv 预印本 arXiv:1806.00663 。网址:https://arxiv.org/pdf/1806.00663.pdf。
- Vaughan,j .,Sudjianto,a .,Brahimi,e .,Chen,j .,& Nair,V. N. (2018 年)。基于加性指数模型的可解释神经网络。arXiv 预印本 arXiv:1806.01933 。网址:https://arxiv.org/pdf/1806.01933.pdf。
- 布莱卡,p .,达塔,a .,荣格,c .,和森,S. (2019)。金融中的机器学习可解释性:违约风险分析的应用。网址:https://www . bankofengland . co . uk/-/media/BOE/files/working-paper/2019/machine-learning-explability-in-finance-an-application-to-default-risk-analysis . pdf .
- 北卡罗来纳州巴斯曼、乔治迪奇、马里内利和帕彭布洛克(2019 年)。信用风险管理中的可解释人工智能。信用风险管理(2019 年 12 月 18 日)。网址:【https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3506274 。
- 北卡罗来纳州吉尔、北卡罗来纳州霍尔、堪萨斯州蒙哥马利和北卡罗来纳州施密特(2020 年)。一个负责任的机器学习工作流程,侧重于可解释的模型、事后解释和辨别测试。信息, 11 (3),137。网址:https://www.mdpi.com/2078-2489/11/3/137。
从优秀到卓越—为您梦想中的数据科学角色打分
图片来自 Pexels
首先是闯入数据科学领域,然后是获得一个梦寐以求的数据科学职位。从某种意义上来说,每个人都应该追求自己热爱的东西&在那个领域获得经验。解决大问题的角色,或者给你经验的角色,这些经验是你无法获得的,或者是你特别感兴趣的领域的角色。一个领域越热门,竞争就越激烈。那么如何在竞争激烈的领域脱颖而出呢?
一般来说,你需要展示这些特质:
- 激情(你需要热爱你的工作,并展示出来)
- 承诺(克服所有的拒绝)
- 主动性(学会如何为自己开门)
- 和蔼可亲(你需要软技能来建立联系)
- 结果(展示你所做的工作,以及如何应用这些工作)
本质上,你需要改变你个人故事背后的等式:
“我是一名数据科学家,对想要的领域(比如篮球)感兴趣”(许多人)
到
….“我是一名对(所需领域)感兴趣的数据科学家,曾帮助 x、y、z…..而且做了 a,b,c”(很少)。
你应该把用尽所有可能的方法来达到后者作为你的目标。你需要从众多人中的一员跃升为少数人中的一员。
这里有一些积极的步骤,可以帮助你一路前行。
做你的研究
首先研究你选择的特定领域,以及数据驱动决策在该领域的应用有多成熟。找出正在做什么,由谁做。如果这个领域竞争特别激烈,寻找邻近的机会,就像直接在那个领域工作一样——开始建立你的关系网和投资组合。
基于你已经做的研究,开始关注在那个领域特别有洞察力的人,如果可能的话,接触他们。
多年来,联系导师的渠道已经发生了变化,可能因人而异,然而,两种相对可靠的方式是通过 LinkedIn 或工作邮件。
说明你正在做什么,哪里可能有合作的机会,在你们是同事,而不是竞争对手或下属的基础上开始对话。讨论想法而不是个性(即不要花太多时间介绍自己,让你的工作、想法和抱负成为这些关系中的通用语)
创建投资组合
一旦你确定了该领域的关键影响者,开始宣传类似质量的工作,希望从不同的角度宣传他们正在做的事情。开始管理您的在线状态。通常这需要超越更新你的 LinkedIn 个人资料和将代码推送到 Github。整理你的想法,并把它们记录在博客里,这是一个很好的开始。fast . ai 的联合创始人 Rachel Thomas 在这里详细介绍了这样做的原因。
此外,开始维持一个投资组合。不是一个代码组合,虽然可能会涉及一些代码,但这是一个讲述你所做的所有项目的故事,付费或其他方式,以及结果的组合。想想一个设计师的项目组合。你也在做项目,所以开始跟踪和展示它们。一份精心设计的作品集将表明你既有条理又高效,还能让你展示自己的才华(如果你愿意的话)。
仅仅拥有一个作品集或者博客就能帮助你在“多数”和“少数”之间走得更远——不管你想进入哪个领域。
充分利用你得到的机会
学会如何索取,如何让自己变得有用,如何支持自己,即使在没有机会的地方。要求别人给你的东西是一项关键技能。超出预期也是如此。
如果突然冒出来某个数据管理的角色,和你想从事的领域有关,就把它当成一个数据主管的角色,做副业,展示你的价值,让人需要/想要你。理想情况下,你想找一个既有报酬,又有成长报酬的角色。寻找能让你接触到更大问题和更好关系的角色。
找到你的 MVP 角色,将想法付诸实践
学习如何将想法付诸实践。不管你梦想中的 MVP 角色是什么样的,为了你所处的地理位置,为了你所拥有的手段,试着把它作为第一步。
以体育为例,假设你想为一支 NBA 球队进行数据分析。明智的第一步是联系你当地的大学团队,成为他们运营分析的负责人。
还是那句话,关键是找到小机会,这些小机会可以变成大机会。定期进行自我评估,以确保你与你的总体目的和目标保持一致。如果出现偏差,一定要认识到这是因为你犯了一个特殊的错误(不太可能,但如果是这样,要从中吸取教训),还是仅仅因为 21 世纪职业的现实非线性。
从优秀走向卓越
一旦你在你想要的领域有了一个角色,就开始疯狂地建立关系网,扩大你的影响圈。你已经迈出了第一步,所以你能做的最糟糕的事情就是满足。记住,好是伟大的敌人。利用你已经为自己建立的机会,开始扩大你的人际网络和联系。到目前为止,你已经证明了你可以增加价值,现在你可以通过联系人们和想法来让自己变得更有价值。
最后,学会如何向后推,尤其是当你想兑现你通过做上述所有事情积累的经验时。当是时候去扮演那些你迄今为止所有工作的顶点的角色时,确保你独特的故事能够被理解。
记住你已经走过了从许多到少数的道路,所以不要让人们把你归类和区分开来。例如,让(招聘人员)将你归为宽泛的类别,会让你在确保自己的价值主张真正与众不同方面所做的大量出色工作前功尽弃。
本文原载此处
从谷歌日历到 Python 音频
照片由伊恩·杜利(左)和托马斯·勒(右)在 Unsplash 上拍摄
使用 python 构建日常任务阅读器
音频生产力
我们听音乐,我们听播客,YouTube 视频,甚至鸟儿啁啾。倾听是我们生活中很重要的一部分,然而,利用这种感觉来提高我们工作效率的工具似乎很少。
今天我想向你展示如何使用 python 来构建一个简单的任务阅读器,它可以大声背诵你的日常任务,并给你带来情绪上的提升。
从简单的文本到音频
有这么多令人惊叹的 python 库,这么多令人难以置信的框架,让我们的编程体验更加愉快。
就是其中的一个包。它使得将文本转换成音频成为一个简单的过程 。这是一个脱机工作的文本到语音转换库。
这个工具打开了简单文本的可能性之门,因为它为我们的书面内容提供了另一个媒体层。简单的工具,如任务清单,个人咒语,甚至更复杂的。pdf 阅读器可以快速制作。
作为一个例子,我们将使用这个库构建一个简单的任务阅读器 使用谷歌日历 API,额外的好处是阅读个人原则,让你在难以集中注意力的日子里保持正轨。
从谷歌日历到任务阅读器
基本管道将是:
- 使用日历 API 从 google calendar 获取任务。
- 选择当天的任务。
- 循环完成任务,并大声朗读出来。
- 在听完任务之后,用户将会听到一组预先定义好的咒语。
现在,让我们详细介绍一下这些步骤。
启用 Google 日历 API
- 登录您的谷歌账户,点击这里的,启用谷歌日历 API。
- 安装谷歌客户端库
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib.
- 从 google calendar API 页面中的 quickstart.py 复制示例代码,并将其放在一个文件夹中。
设置扬声器
- 安装
pyttsx3
库:pip install pyttsx3.
- 用 python 或 ipython 打开终端:
ipython
。 - 从
pyttsx3
开始测试扬声器。
import pyttsx3
text = "Hello World of Audio!"
speaker = pyttsx3.init()
speaker.say(text)
spaker.runAndWait()
你应该听清楚这个句子。
把所有的放在一起
现在我们已经有了所有的依赖项,让我们组装部件。
我们将修改来自 google API 页面的示例,以返回今天的任务列表。
现在,我们已经有了从 google 日历中获取任务的代码,我们将编写一个函数来获取任务列表并大声朗读出来:
厉害!我们就要完成了,我们要做的就是增加一个额外的选项来听一列您希望被提醒的关键原则:
我们首先编写一个名为principles.txt
的文件,并将其添加到同一个文件夹中。然后,我们可以编写一个函数来从该文件中获取句子列表:
现在,我们要做的就是编写另一个简单的函数来播放原则列表:
就是这样!完整的代码可以在我的 github 上找到。
音频作为生产力工具的潜力
我们应该总是寻求多种输入方式,而不是局限于那些更明显的方式,如视频或文本。我们可以用 python 或任何其他编程语言编写这些简单的音频工具,这表明了这种媒体作为一种方式来增强我们甚至不知道可能实现的日常工作的潜力。
如果您喜欢 Python 和 API 集成,请查看 Udemy 课程:
这是一个附属链接,如果你使用该课程,我会得到一小笔佣金,干杯!😃
如果你喜欢这篇文章,别忘了给👏,在 Twitter 或 LinkedIn 上与我联系。谢谢,下次再见!🤓
从谷歌表单到你的 Jupyter 笔记本
如何将 google sheet 连接到笔记本
Jupyter Notebook 是数据科学家的强大工具。您可以用几行代码执行许多复杂的算法,并对大量数据进行分析。Jupyter 笔记本本身能够连接到一个数据库系统,其中的数据睡眠。尽管如此,如果我们谈论数据库,作为一名数据科学家,首先想到的往往是 SQL。
当然,如果我们谈论数据库,SQL 目前仍然是主要的东西,但是许多没有编程背景的人不会那么熟悉 SQL。特别是有经验的专业人士,他们希望进入编程数据科学领域,他们经常使用 google sheet 来放置他们的数据。
因此,我想向您展示如何将我们的 Jupyter 笔记本连接到我们的 Google Sheets。
资格证书
将 Jupyter Notebook 连接到 Google Sheets 并不麻烦;你可以稍微准备一下。幸运的是我们只需要做一次。
我们需要做的第一件事是从 Google 开发者控制台获得一个合适的凭证。凭证要求我们访问谷歌表单。
在控制台中,点击创建项目。在那里,您会发现类似下图所示的屏幕。
你给项目起什么名字并不重要,重要的是你创建了一个新的项目。为了连接到 Google Sheets,我们只需要这一个项目,所以至少要选择一个你能记住的名字。
回到我们的控制台,看看项目是否已经创建。选择新创建的项目,点击左上角的汉堡菜单(Google APIs 符号旁边的那个)。在那里选择API&服务,然后选择仪表板。
在仪表板上,选择启用 API 和服务按钮。
从那里我们将被带到 API 库。应该是下图这样的。
在搜索栏上,键入“Google Sheets”来查找 Google Sheets API。
从那里点击 Google Sheets API 并启用该 API。
在这一步中,我们还启用了 Google Drive API,因此也可以搜索“Google Drive API”。
现在我们将被带到 Google Sheets API 仪表板。要使用这个 API,首先,我们需要创建凭证。
这里,另一个屏幕会提示我们创建凭据。选择 Google Sheets API 用于哪个 API,选择其他 UI 用于从哪里调用 API,选择用户数据用于访问什么数据。现在,单击“我需要什么凭据?”?按钮。步骤如下图所示。
如果是第一次创建凭证,系统会提示您创建 OAuth 同意屏幕。单击设置同意屏幕创建一个。
在这里,只需在应用程序名称中输入您喜欢的任何名称,然后单击 save。
回到仪表板,现在点击创建凭证按钮并选择 OAuth 客户端 ID 。
在这里,只需选择其他类型,然后键入您喜欢的任何名称。然后单击创建。
您将返回到仪表板。现在下载您新创建的 OAuth 客户端 ID,并将其放在您将使用 Jupyter 笔记本的文件夹中。
上面的这一步对于连接来说并不是必须的,但是我们这样做只是为了以防我们以后需要它。
我们还需要一样东西。现在回到创建凭证并点击服务帐户按钮。
键入您喜欢的任何名称,然后点按“创建”按钮。在下一个屏幕中,选择角色作为服务帐户用户。
然后点击创建密钥按钮。
选择 JSON 密钥类型,然后单击创建。将文件保存在与您想要的笔记本相同的文件夹中。
现在我们得到了所有我们需要的证书。这是一个漫长的步骤,但我们只需要做一次。
将 Google Sheets 连接到 Jupyter 笔记本
在开始之前,我们需要安装 3 个不同的 Python 模块。
pip install gspread oauth2client df2gspread
现在我们到了可以将纸张连接到 Jupyter 笔记本的部分。我将在下面的步骤中展示它。
- 导入所有重要的模块
#Importing the module
import gspread
from df2gspread import df2gspread as d2g
from oauth2client.service_account import ServiceAccountCredentials
2.在 Google Sheet 中创建一个新的工作表。然后点击右上角的 share 按钮,在 google API 仪表板中输入来自服务帐户的电子邮件。这是为了确保工作表连接到我们的 Jupyter 笔记本。
3.初始化所有重要的变量
#The scope is always look like this so we did not need to change anything
scope = [
'[https://spreadsheets.google.com/feeds'](https://spreadsheets.google.com/feeds'),
'[https://www.googleapis.com/auth/drive'](https://www.googleapis.com/auth/drive')]#Name of our Service Account Key
google_key_file = 'service_key.json'credentials = ServiceAccountCredentials.from_json_keyfile_name(google_key_file, scope)gc = gspread.authorize(credentials)
现在我们已经有了我们需要的所有重要连接。
将数据上传到 Google Sheet
首先,让我们尝试将 Jupyter Notebook 中的数据上传到 Google Sheet。
import seaborn as sns#I would use tips dataset as an example
tips = sns.load_dataset('tips')
这是我们的数据。
现在,当我们想要将数据上传到 google sheet 时,有一些事情需要注意。我们需要工作表 ID 和工作表名称。如何获取如下图所示。
现在让我们将数据上传到这个空的 Google 工作表中。
#This is the Worksheet ID
spreadsheet_key = '1ZJzLxLyfExKC-vziq21JFNzVcCISJVQxa0Dx-55Qc8k'#This is the sheet name
wks_name = 'test_data'#We upload the tips data to our Google Sheet. Setting the row_names to False if you did not want the index to be included
d2g.upload(tips, spreadsheet_key, wks_name, credentials=credentials, row_names=False)
好了,现在我们在谷歌表单中有了我们的数据。
从谷歌工作表中提取数据
如果我们想提取数据,就像把数据上传到 google sheet 一样简单。我将在下面的代码中展示它。
#Opening the worksheet by using Worksheet ID
workbook = gc.open_by_key(spreadsheet_key)#Selecting which sheet to pulling the data
sheet = workbook.worksheet('test_data')#Pulling the data and transform it to the data frame
values = sheet.get_all_values()
pull_tips = pd.DataFrame(values[1:], columns = values[0])pull_tips
就是这样。我们已经从我们的 Jupyter 笔记本上连接了我们的 Google Sheet。
结论
我已经向您展示了将我们的 Jupyter 笔记本连接到 Google Sheets 所需的步骤。我还展示了如何在 Google Sheets 中上传和提取数据。
希望有帮助!
如果您喜欢我的内容,并希望获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的简讯。
如果您没有订阅为中等会员,请考虑通过我的介绍订阅。
从图形数据库到图形嵌入
图片由 TheAndrasBarta ,授权。
7 个简单的步骤
所有的创新技术最终都会越过一个“膨胀预期的顶峰”,当所述技术得到大量营销资金的支持时,这种现象尤其如此,这些资金主要用于助长炒作和加剧公众预期。
机器学习的前景正在慢慢成熟,超越了它的“我是一把锤子,一切都是钉子”的框架,诞生于过去十年左右市场营销热情的爆发。
对于图形数据库也是如此;曾经被誉为每个企业圣诞节必备的热门新技术,它们已经达到了成为系统工程师剧本的一部分的快乐境界。
当它们与一起使用时,它们比传统的 RDBMS 提供了显著的优势,RDBMS 在过去的 40 多年里一直统治着数据库领域。简单地说,它们只是做 SQL 数据库做不到的某些事情(反过来也是如此)。
考虑到这一点,我们来找点乐子吧。
下面,我为安装图形数据库、获取数据集、创建图形的矢量嵌入表示以及可视化输出做了一个简单的入门指南。
在本教程中,我们将使用 Linux 基金会支持的图形数据库 JanusGraph 。JanusGraph 被设计用来处理数十亿个顶点和边,但是为了本教程,我们将保持它的简洁。不过,我会给你一些建议,告诉你如何扩展你的解决方案。
在开始之前,让我们先解决一些潜在的问题。
- 为什么不直接用 NetworkX?尽管 NetworkX 功能丰富,但它的可扩展性并不好。虽然下面的步骤显然不符合给定表格中的,但它们代表了可能的基础。(例如,将 JanusGraph 部署到集群,并使用 Spark 运行以下所有操作)
- 为什么是 JanusGraph 而不是另一个 db?有许多伟大的图形数据库可供选择。我在下面使用它是因为 JanusGraph 维护得很好,在 Apache 2.0 下获得许可,可伸缩,并且使用最接近通用图查询语言的东西:Gremlin。您还可以使用 gremlin-python 实现轻松地将 gremlin 嵌入到我们的 python 代码中。(虽然 Cypher 在 StackOverflow 上通过 Q &更受欢迎,但 Gremlin 得到了更多图形数据库的支持)。
- node 2 vec 的特性比定制的、手工构建的特性更有用吗?嗯,那要看情况。Node2Vec 允许我们轻松地将图形的拓扑表示编码成一系列实数,而不必繁琐地尝试手动创建它们。这节省了时间和精力,并且最终包含了比手工创建的图表更多的信息。
我们将用来加载的数据将是 Kelvin Lawrence 的机场数据集。在这里可以找到他的数据,在这里可以找到他关于 Gremlin(一种流行的图形查询语言)的(优秀)书籍。
步骤 1 —下载骏利图表
导航到 JanusGraph 发布页面并下载最新版本(在撰写本文时是 0.52-文件名Janus graph-full-0 . 5 . 2 . zip)
步骤 2-启动骏利图像服务器
下载后,将文件解压缩,并将光盘放入可执行文件和 shell 脚本所在的bin/
目录。
要启动服务器(基本后端是 Cassandra、ElasticSearch 和 gremlin-server),使用命令./janusgraph.sh start
。您应该会看到以下输出:
步骤 3-将数据集加载到数据库中
有多种方法来序列化您的图形数据。下面,我将摄取一个graphml
文件,但你也可以轻松地使用graphson
或csv
。
将以下内容保存到扩展名为.groovy
的文件中。
所有对 JanusGraph 的远程访问都是通过 Gremlin 服务器进行的;我们可以通过首先进入 gremlin 控制台来访问/加载我们的数据。通过使用命令——仍然在 bin 目录中— ./gremlin.sh
来完成。您应该会看到以下输出:
进入 gremlin 控制台后,使用以下命令加载机场数据。根据数据集的大小,所需的时间会有所不同。
:load path/to/file/load_airports.groovy
您可以通过运行计数g.V().count()
来验证它是否正常工作。尽管这对于大量数据来说会很慢——在这种情况下,设置一个顶点索引并从那里开始计数。
扩展选项:部署 JanusGraph 到集群,玩玩后端组件,批量加载,增加线程,增加工人等。关于这个主题的精彩文章,请点击这里。
步骤 4-创建随机漫步
word 2 vec——node 2 vec 的下游等价物——需要一组序列作为输入。我们可以使用随机漫步从我们的图中构造序列。简而言之,我们将使用节点,而不是单词,我们使用随机漫步,而不是句子。在这个过程中,我们将节点映射到实数。
让我们创建这些随机漫步。对于每个顶点,我们将创建 50 个深度为 6 的随机行走(根据需要进行调整,这只是一个演示)。下面的代码使用了[gremlinpython](https://pypi.org/project/gremlinpython/)
实现,它可以无缝集成到我们的 Python 脚本中。
从 3619 个顶点中,我们提取了 181k 个随机游走。
注意,下面的查询实际上是随机漫步的一个不完美的表示,它将被提供给 Node2Vec。Node2Vec 指定了两个额外的超参数来控制顶点之间的转移概率,因此您可以控制您的行走是局部的(广度优先搜索)还是全局的(深度优先搜索)。
扩展选项:通过使用多处理库,您可以轻松地垂直扩展该解决方案。通过使用 PySpark 这样的 Spark 实现来查询 JanusGraph,您可以横向扩展这个解决方案。要提取顶点 id,最好是直接查询弹性索引,而不是尝试 g.V()查询,或者在加载数据时梳理出来。
步骤 5— Word2Vec/Node2Vec 嵌入
神奇的事情就发生在这里。让我们在随机行走的集合上训练一个 Word2Vec 模型,得到一个实数的输出。
输出X
是矢量集,形状为 181,000 x 50。如果你要训练一个 ML 模型,这是你可能会用到的数据。
缩放选项:使用 Word2Vec 的 Spark 实现。
步骤 6 —降维
想象 50 维几乎是不可能的。我们可以使用降维技术来提取数据集中包含的大量差异,并将其压缩到更少的维度。这个过程是有损耗的,但如果我们能够保留足够的信息,同时能够在低维(~2D)空间中查看数据的全局结构,这是很值得的。
虽然这里可以使用 PCA 或 TSNE,但我选择了 UMAP,因为它很好地保留了全局结构,而且速度很快。以下参数将需要调整。
这是一篇关于 UMAP 的好文章。
缩放选项:虽然我找不到 UMAP 的 Spark 实现,但你可以尝试使用 MLlib PCA 实现。
第七步——想象
让我们把 50 维数据简化成两个部分,并把它们可视化。对于悬停数据和颜色数据,屏幕外有一些多余的添加。如果有足够的兴趣,我会张贴整个笔记本供参考。
这是输出——试着将鼠标悬停在上面,摆弄数据。
Plotly 图可以直接嵌入介质?非常酷。
感谢您的阅读,祝您编码愉快!
从混乱到信息
为机器学习准备数据
2016 年,CloudFlower 发布了他们的年度数据科学报告:试图阐明作为一名数据科学家意味着什么,这是一个最近才出现在普通词汇中的术语。从该报告中得出的一个关键见解是,数据科学家平均花费大约 80%的时间来收集、清理、争论或准备用于分析的数据。
2016 数据科学报告,CloudFlower
接下来是一长串标题,大意是这是工作中最平凡的部分,基本上是浪费时间和生产力。
80/20 法则相当准确,但认为这会降低生产率或带走本可以更好地用于培训模型的精力和资源的观点是错误的
引起人们注意 80/20 法则的文章。
预处理包括许多步骤。其中一些可能看起来更琐碎,比如解决不一致,一些需要更深入的统计理论知识,比如缺失数据的插补,但它们都有一个共同点:它们都是决策点,答案在任何教科书或手册中都找不到,因为它们非常依赖于您试图解决的问题和您正在处理的特定数据集。
出于这个原因,预处理不是过程中的一个微不足道的步骤,它为项目增加了很多价值:当您通过不一致、异常值和缺失数据进行工作时,您会更好地理解手头的问题和可用于解决它的数据,这反过来会使最终构建模型更加容易。
本文描述了预处理过程中解决的一些问题,以及在每个步骤中做出的决策。
机器学习模型的好坏取决于它们接受训练的数据。这可以用垃圾输入,垃圾输出的概念来概括:如果你的训练集有噪音,有错误,或包含偏见,不管你的数学有多好,也不管你花多少时间优化你的参数,你的模型结果将不可避免地不准确。
什么是数据质量?
数据质量比算法的复杂性更能区分好模型和坏模型。但是质量数据是如何定义的呢?严格的定义并不存在,但我喜欢来自维基百科页面关于数据质量的一个定义:
使数据适合特定用途的完整性、符合性、一致性、及时性、复制性、完整性和准确性的状态。
用更一般的术语来说,质量数据是“适合使用”的数据,并且正确地代表了它所涉及的现实。
让我们看一个例子,看看我们在准备数据进行分析时可能会遇到什么样的问题,以及我们可以采取什么步骤来解决这些问题。
科技调查中的心理健康
由 OSMI (开源精神疾病)每年进行的科技领域心理健康调查,衡量了科技工作场所对心理健康的态度,并调查了科技工作者心理健康障碍的频率。
在 2014 年的版本中,1259 名受访者回答了 25 个问题。这些问题中有几个允许自由输入,因此在将数据用于任何分析或将其输入模型之前,需要解决数据中存在的大量不一致和错误。
以下是一些不一致、异常值和缺失数据的例子。在我的 Github 上有一个笔记本,上面有这个数据集的完整分析。
发现不一致
第一步是检查数据的不一致性。这是从无关数据到语法错误的任何东西。下面是一些例子的非详尽列表。
- 不相关的数据,例如不应该包含的行和列。
- 重复数据。
- 类型转换错误,例如,数字列被解释为字符串。
- 语法错误,例如类别名称的拼写错误。
- 非标准缺失值,例如【不适用】【空】不适用。
运行一些简单的描述性统计通常有助于发现这些和其他不一致之处。这个步骤有时被称为剖析。
在科技心理健康调查中,我们注意到的第一个奇怪现象是年龄分布。
df['Age'].describe()# count 1259.000
# mean 79428148.311
# std 2818299442.982
# min -1726.000
# 25% 27.000
# 50% 31.000
# 75% 36.000
# max 99999999999.000
# Name: Age, dtype: float64
年龄分布的初始直方图
我们稍后将处理异常值,现在,我们将实施一个简单的业务规则——年龄应该在 14 到 100 之间——并且我们将认为该区间之外的所有值都是缺失的。
年龄直方图现在更有意义了。
添加了受访者年龄必须在 14 到 100 岁之间的规则后的年龄分布直方图。
性别是问卷中另一个开放式的答案,所以这个专栏包括了很多很多拼写男性、女性和非二进制的方法。幸运的是,大多数都可以使用正则表达式和一些模糊匹配来纠正。
调查结果中性别(计数)的初步分布。
清理后的性别分布(计数)。
接下来,国家的分布似乎没有同样的问题(没有拼写错误),但有一大群国家出现的频率非常低。这里不需要采取特别的行动,但是一个可能的选择是将分析限制在国家的一个子集——哪些国家将取决于我们正在寻找的答案的类型。这里的一个选择是将分析限于美国的数据。
极端值
离群值也没有严格的定义。异常值是与其他观察值显著不同的数据点。这可能是由测量中的实际变化或误差引起的。
因为离群值没有单一的定义,每个项目定义离群值的方式决定了检测离群值的方法。一种常见的方法是 Tuckey ' s fence,也称为箱线图规则。该方法基于四分位数范围(IQR),即第一个四分位数 Q1 和第三个四分位数 Q3 之间的差异:范围*【Q1-k *(IQR),Q3+k (IQR)】之外的任何观察值都被标记为异常值。传统上, k=1.5 用于常规异常值,而 k=3 用于大异常值。
年龄箱线图。方框表示第一和第三四分位数之间的年龄分布,分别由方框的下侧和上侧表示。Q1 和 Q3 之间的实线代表中值,虚线代表平均值。红色和深蓝色点分别代表常规(k=1.5)和大(k=3)异常值。
由于一些模型(例如线性回归)对异常值的稳健性不如其他模型,因此在选择模型之前了解它们的存在是有好处的——虽然我们现在不需要采取行动,但我们会标记它们并进入下一步。
请注意,这种方法最适用于有点正态分布的数据,但不适合,例如,两边都有很大偏斜的数据。
缺失数据
缺失数据是类型已知但值未知的数据点,例如调查中未回答的问题。大多数机器学习模型不处理丢失的数据,这意味着丢失的值必须被删除或替换。有 3 种主要机制会导致数据丢失,能够区分这三种机制非常重要,因为丢失数据背后的机制将决定如何处理它。
- 完全随机缺失(MCAR):导致特定值缺失的因素与可观察(或不可观察)变量无关。例如,有些人不填写心理健康调查暗示 MCAR——没有具体的原因会发生这种情况。
- 随机缺失(MAR):缺失数据背后有一种非随机的可观察机制。例如,男性不太可能填写心理健康调查,因为他们是男性暗示着 MAR:只要我们能观察到变量性别,我们就能解释缺失数据的非随机性,并建立无偏估计量。
- 不是随机失踪:失踪是由于一些不可见的因素。例如,男性不太可能填写心理健康调查,因为他们的心理健康暗示 MNAR。
那么如何看待缺失数据呢?在某些情况下,例如当一列有大量缺失值时,删除是一种有效的方法。然而,在大多数情况下,缺少的值会被替换为一些替代值。这个过程叫做插补。有许多可能的估算方法,有些比另一些更复杂。
- 数值插补:用单个值代替所有缺失的观察值,通常是平均值。
- 从分布中随机选择。
- 热卡插补:缺失值从数据集中的相似记录进行插补。
- KNN 插补:确定最近的邻居,并使用他们值的集合来插补缺失的那个。
没有单一的规则来决定使用哪种方法,选择取决于多种因素的组合,如缺失数据的记录数量、我们正在处理的数据类型、特定的用例以及缺失的底层机制。要记住的一条重要规则是,插补不应改变数据的分布,因此比较插补前后的分布是一种好的做法,以确保我们没有注入任何偏差。
让我们看几个科技心理健康调查的例子。
自主创业的变量有一些缺失。对于其中的每一个,我们将从所有可能值的集合中随机选择一个值(是/否),其概率与数据集中是/否的分布成比例。这确保了插补后的分布是相同的。
在(p_original)插补之前和(p_imputed)插补之后自营职业的概率。
在这个过程的第一阶段,我们发现年龄有一些超出范围的值,我们决定假设它们丢失,所以现在是时候估算它们了。对于这个变量,我们将使用一个更有趣的方法:KNN 插补。对于每个年龄缺失的受访者,我们会找到最相似的邻居,并用这些邻居的平均年龄来估算缺失值。
插补前后的年龄分布。
流程和最佳实践
预处理不是一个线性过程。您可以在流程的任何给定点返回、编辑和重复所有步骤。
通常有 4 个主要步骤。
- 检查:检测意外的、不正确的和不一致的数据(数据剖析和可视化)。
- 清除:删除、纠正或估算不正确的数据。
- 验证:现在数据正确吗?重新检查和测试以验证没有违反假设。
- 报告:记录发现的不一致和错误,以及它们是如何解决的。
这些步骤在概念上是连续的,但过程远不是线性的!在任何给定的步骤中,您可能必须返回、编辑并重复所有步骤,这甚至可能发生在您将数据输入到模型中之后,因此重要的是,它们中的每一个都被很好地记录下来并可重复,并且没有任何东西是手动编辑的,无论多么简单,将来您会非常感激。
摘要
这不是一个完整的预处理指南,但它应该给出一个更清晰的过程是什么样子的前景。有许多决策要做,而解决方案并不总是直截了当的,这就产生了许多可能的故障点。花时间分析和准备数据将使您更好地理解手头的问题,同时确保输入预测模型的数据真正代表正在解决的问题。这一点尤为重要,因为越来越多的决策过程依赖于机器学习模型来做出公平的决策,因此这些模型必须根据可靠、一致和无偏见的数据进行训练。
从创意到生产
如何将一个数据科学项目从想法变为现实
由凯特·玛丽·路易斯 — 16 分钟阅读
我面试过很多数据科学候选人,他们都是各种各样的角色。从初级数据科学家到雇佣我所在的数据科学团队的负责人。在我参加过的无数次面试中,有几个问题是我非常喜欢反复问的。
熊猫变漂亮了
丽贝卡·维克里——5 分钟阅读
流行的 Python 数据分析库 Pandas 中的绘图功能一直是我制作超级快速图表的常用方法之一。然而,可用的观想总是相当基础的,并不特别漂亮。
重新思考数据科学的持续集成
爱德华多·布兰卡斯 — 29 分钟阅读
随着数据科学和机器学习得到更广泛的行业采用,从业者意识到部署数据产品会带来高昂的(往往是意想不到的)维护成本。
搭配:火烧考拉(第一部、第二部)
由 Svitlana Midianko 和 Magali de Bruyn — 15 分钟读取
匹配是一种计算工具,用于提高因果推理的稳健性或可信度。为此,它将来自治疗组的数据点与来自对照组的数据点配对——基于它们在所选特征上的相似性。
美国宇航局的数据科学
杰瑞米·哈里斯和大卫·梅萨
机器学习不是火箭科学,除非你在 NASA 做。如果你碰巧在美国国家航空航天局做数据科学,你和我今天播客的嘉宾大卫·梅萨有共同之处。
从不平衡数据集到助推算法
艰难的教训,真正的秘诀
不平衡数据集完整工具包
在 Unsplash 上 engin akyurt 拍摄的照片
不平衡数据集出现问题有两种不同的情况。
第一类是当错误分类的成本对少数阶级来说比多数阶级高得多的时候。换句话说,我们模型的主要目标是最小化假阳性预测。一些例子是:检测信用卡欺诈,客户流失,检测一种罕见的致命疾病。为了更好地理解不同类型的错误预测如何转化为实际的业务成本,请查看我的帖子: 为什么我们必须谈论第一类错误和第二类错误?
第二种是我们没有为少数群体收集足够的数据。我们的样品不够有代表性。换句话说,不平衡的数据集应该是平衡的。
在 python 中,我们的工具箱中有几个工具可以修复不平衡的数据集。然而,每个工具都是为解决不同类型的问题而构建的。
文章大纲:
- 介绍所有工具:下采样,上采样,平滑,改变类权重
- 用我上周完成的项目展示他们用树算法的表现。
- 讨论我们应该何时使用每种工具
- 解释与升压算法的联系和比较
工具概述
下采样:从多数类中随机选择一些点并删除。
上采样:从少数类中随机选择一个点,复制粘贴做一个新点。重复这个过程,直到你有和大多数班级一样多的样本。
SMOTE: 在少数类中创建更多的样本。然而,不是通过复制现有的数据点,而是通过在可能的范围内创建新的点。换句话说,它在现有数据的周围创建新的数据点。请参见下图进行说明。(关于这个的一个很棒的视频: SMOTE(合成少数过采样技术))
调整等级权重:有两种方法可以实现。一种是将决策树和随机森林中的参数 class_weights 改为class _ weight =‘balanced’。该算法将使用分层抽样来构建树,而不是默认设置:随机抽样。
第二种方法只适用于随机森林。您可以手动将权重分配给不同的类别。下面我就分享一下代码。通过给一个阶层分配较重的权重,我们将使用加权基尼系数。加权基尼系数将使我们用来制作树的所有变量对少数民族阶层更加敏感。例如,当我们计算我们的基尼系数时,能够更好地识别少数群体的变量将具有较低的杂质分数,因此,更有可能被选择来构建一个树。
性能概述
背景:数据集来自一家电信公司。它有 3333 个样本(原始数据集通过 Kaggle)。在这些样本中,85.5%来自“流失= 0”组,14.5%来自“流失= 1”组。目标是预测客户流失。我将展示 4 种树算法的性能——决策树、随机森林、梯度推进和 XG 推进。
原始数据集的性能:
下采样后的性能:
缩减采样代码
上采样后的性能:
用于上采样的代码:
击打后的表现:
RF 和决策树使用平衡类权重的性能:
手动调整权重后射频的性能
见解:
当谈到每种方法的优缺点时,许多文章都是这样说的:
随机下采样:遗漏一些有价值的信息。众所周知,样本越多越好,因为这让我们更接近现实。但是下采样减少了样本。
随机上采样:倾向于过度拟合少数群体的现有数据点,因为我们一直在复制现有数据点。
这个弊端其实从上面的分析就反映出来了。比较假阳性的数量,上采样的假阳性没有其他方法减少的多。
SMOTE 和加权类:通常被描述为“高级”方法,用来克服下采样和上采样的缺点。确实,SMOTE 找到了一种合理的方式来提供新数据,这是一种革命性的想法。加权类方法保留了所有的信息,这也是事实。
但是如果你是商业决策者,看着结果,你会选择哪种方法?
要回答这个问题:我们可以用数字来表示事物。我们就挑随机森林的表现来举例吧。假设在我们预见到客户会流失之后,我们能够挽救所有的客户。
- 缩减采样成本=失去 2 个客户+在 38 个客户身上浪费营销努力和金钱,因为我们认为我们会失去他们
- 上采样成本=失去 22 个客户+浪费 15 个客户。
- SMOTE 成本=失去 17 个客户+浪费 27 个客户。
- 平衡级成本=失去 20 个客户,浪费 16 个客户。
- 加权成本=失去 12 个客户,浪费 24 个客户。
尽管成本会因行业而异,但我愿意说我会选择下采样。一是因为我失去的客户最少,这是我的首要目标。另一个原因是,既然这 38 位客户打算和我们住在一起,我想我们应该不会花太多精力或成本去“拯救”他们。
当然,这取决于我们的“储蓄”方法和样本量的大小。如果我们有一万个客户,考虑的可能就不一样了。
不管怎样,这里的关键观点是——没有更好或更坏的方法,我们需要始终牢记上下文。
Gif via GIPHY
有一般的经验法则吗?
是的。我提到过不平衡的数据集成为问题的两个原因。第一类是假阳性数字对我们来说比整体准确性更重要。类型 2 在数据收集过程中有偏差。流失率问题是第一类问题。换句话说,这里的主要问题不是我的数据集有偏差,而是他们是天生的少数。在这种情况下,下采样和加权类最好地解决了我们的问题,因为它们扩大了少数类的声音。
如果我们面对的是 2 型问题,那么 SMOTE 应该比其他方法更好,因为它在少数类中引入了新的样本。它试图填补少数阶级的空白,缓解有偏见的人。
上采样和平衡类方法的工作方式相同,因此结果非常相似。它们并不特别适合任何一种类型。原因是在你不停地从少数数据集复制数据之后,不可能没有过拟合的问题。
萨汉德·巴巴里在 Unsplash 上的照片
有趣的技术见解:(随意跳过)
注意最大深度和假阳性的数量。在下采样中,如果我限制深度,我实际上会有更多的假阳性和更低的准确性。但是在手动调整类权重时,我减少的深度越多,我得到的假正数就越少。缺点是我会因为一个 0 的假阳性数字而牺牲整体的准确性。
这个细节真正展示了这两种方法之间的区别。当使用缩减采样时,我们仍然通过寻找最佳变量进行分割来构建树。它就像一个普通的随机森林。随机森林非常适合处理过度拟合。当我限制深度时,我可能真的会不适应。而且不可能有 0 假阳性,除非我们以后做一些正则化。
然而,在调整类权重的情况下,它像正则化一样工作。也就是说,我们需要小心选择重量。
增压连接
通过调整类权重,我们刚刚从 bagging 算法转移到伪 boosting 算法。
再看看数据。您是否注意到加权类的性能与 boosting 算法的性能非常相似?还有,你注意到别的了吗?梯度增强和 XG 增强这两种增强方法没有其他两种树方法波动大。他们的两类错误一开始也更平衡。这是为什么呢?
GIF via GIPHY
bagging 和 boosting 算法的核心区别之一是,在 bagging 算法中,它遵循 1 树 1 票的规则。不管在什么情况下,没有一棵树高于另一棵树。对于助推来说,不等于。在最终决定上,有些人会比其他人更有发言权。不同的提升算法有不同的方式来决定一棵树在最终决策中有多少发言权。但原则是,声音是不平等的。因此,我说加权随机森林是伪提升算法。
为什么这只是伪 boosting 算法而不是 boosting 算法?
不同之处在于 boosting 算法改变样本的权重,而加权随机森林改变类的权重。如果以人为类比。一个加权随机森林说:每个投 A 的人都会被多算。一个增强算法说:谁更有资格,谁就能投更多的票。
棘手的部分是:我们如何证明谁比谁更有资格,权力大多少?这就是助推算法试图解决的问题。
那么为什么 boosting 算法波动更小呢?助推算法一瞥。
在助推算法的背景下,谁是“合格的人”?他们是产生更多正确结果的树,并且持续地产生正确结果。
如果树 X 总是比树 Y 产生更多正确的结果,那么树 X 比树 Y 更善于识别少数类(当存在不平衡的数据集时,所有的树都善于识别多数类)。增强算法放大这些声音。这就是为什么 boosting 算法一开始就比其他算法做得更好。
Boosting 算法通过反复测试不同树的准确性来确保性能的一致性。该算法在每次测试后调整树的功率,直到调整仅具有微小的波动。这是 boosting 和 bagging 算法之间的第二个主要区别(第一个是分配不同的权重)。在 bagging 算法中,树有许多期末考试,期末成绩是通过和失败的简单相加。在推进算法中,你有测验和期中考试。每次测验都会影响你的期末成绩。
因此,有了一个平衡的数据集,无论数据集的结构如何,产生更正确结果的树总是占主导地位。这就是为什么在我们实现 SMOTE 和上采样后,梯度增强的性能丝毫没有改变。
因此,第二个关键的见解是:当你不确定不平衡的主要原因是什么时,使用一个增强算法。你会少错一些。
好了,这是升压算法的一瞥。我正在写一篇文章来更详细地解释 boosting 算法。
GIF via GIPHY
更多信息:
- 成本敏感学习与阶层失衡问题,x .凌,s .盛
- 树木的不同重采样方法我在 Kaggle 上的原始重采样分析
- 使用树模型的客户流失我在 Kaggle 上的全面流失分析
从隐形女人到派对生活
硅谷的一份数据科学工作改变了人们对我价值的看法
我在阿德莱德的朋友有各种不同的职业,但在旧金山,我遇到的几乎所有人都是科技行业的。我制作了这张图片来说明不同之处。
当我第一次搬到硅谷时,是为了在一个世界领先的研究中心进行脑瘤研究。很有趣,对吧?似乎不在旧金山。
在澳大利亚,我的朋友们有着不同的背景和职业。我喜欢我们都有不同的观点。当你能听到别人的观点和经历与你不同时,谈话会变得有趣得多。我的朋友中有律师、教师、会计师、护士、美容师和许多不同的职业。
认识拥有这些不同专业知识的人不仅有帮助,还能让生活不会变得无聊。我不知道你怎么想,但是当我下班的时候,我不想在我和朋友在一起的时候谈论我的工作。那将是极其单调的。相反,我喜欢和朋友交谈,给我新的想法来处理事情。
我的工作只是我的一部分。
我需要我的友谊来培养我的整个自我,而不仅仅是我的职业部分。所以我喜欢和与我有共同价值观和兴趣,但又与我不同的人在一起。
当我完成博士学位时,我有一种变得狭隘的倾向。我的研究将永远在我脑海深处滴答作响。所以花时间和科学之外的人在一起让我的大脑得到喘息是很重要的。这让我不会太专注于自己的工作。
我坚信人们的工作可能很有趣,但它们很少是一个人最有趣的事情。我喜欢倾听人们的激情。例如,我在阿德莱德有一些朋友,他们喜欢骑越野自行车下坡、钩针编织、研究古埃及、芭蕾、肚皮舞、摇摆舞和在唱诗班表演。
搬到世界的另一边是很难的,我离开了我的朋友和家人去追求我的研究事业。我积极努力去认识新的人,结交新的朋友。然而,我发现我在高科技聚会上受到的接待并不热情。
社交聚会往往不是为了社交,而是为了获得优势。湾区是非常短暂的。人们倾向于去科技圣地做科技。每个人都想结交朋友,这使得结交真正的朋友变得更加困难。你知道那种你可以真正交谈的人。只是闲逛和喝杯茶,而不是计划令人兴奋的郊游。
当人们发现我不在科技行业工作时,他们似乎完全没有兴趣了解我。你有没有遇到过有人在你谈话时鬼鬼祟祟的?看到他们眼中的变化,从评估你的潜力到忽略你,再到扫视房间寻找另一个潜在客户,这给人留下了深刻的印象。
当我在旧金山的一家初创公司找到第一份数据科学工作后,一切都变了。我突然变成了一个很酷的孩子,人们想知道我的一切。令人不安的是,我的感知价值与我的职业联系如此紧密。
你想知道为什么科技有包容性问题吗?技术不重视不从事技术的人。
我的癌症研究
我的研究旨在帮助脑瘤患者,或者从一开始就阻止他们生长。旧金山以外的大多数人都觉得这很有趣。
让我给你高水平的音高。
近年来,癌症治疗越来越好。随着早期检测和这些新的治疗方法,越来越多的人从他们的原发性癌症中存活下来。今天,许多癌症死亡是由于癌症扩散到身体的其他部位。这些继发性癌症很难治疗。
乳腺癌经常扩散到大脑。血脑屏障应该阻止癌细胞从血液循环进入大脑,但出于某种原因,它没有。科学家们不知道为什么癌细胞可以通过。我的博士研究调查了癌细胞如何穿过血脑屏障进入大脑。有点意思,对吧?
在我的博士后论文中,我研究了大脑中正常细胞如何变成癌细胞。大脑中的大多数细胞都是高度特化的,因此不再分裂。一般来说,正是分裂最频繁的细胞获得了导致癌症的基因突变。干细胞是大脑中少数仍在分裂的细胞类型之一。我所在的实验室研究了神经干细胞是否是脑癌的起源细胞。
如果我们是正确的,这将意味着我们可能能够开发出一种早期干预或药物来预防脑瘤的形成。对于癌症来说,唯一比治疗更好的是预防。
在我搬到旧金山之前,我遇到的人都有兴趣更多地了解大脑是如何工作的,以及为什么癌症无法治愈。然而,当我住在硅谷时,这一切都变了。
成为隐形女人
我和我的男朋友搬到了旧金山,他在一家科技创业公司工作。我们参加了很多科技聚会和创业发布会。我参加这些聚会和联谊会的目的是认识新的人和交朋友。我不想在一个新的地方生活感到孤独。所以当我发现人们对认识我不感兴趣时,我很沮丧。
做一个科技行业的女性很难,做一个非科技行业的女性会让你隐形。
科技派对让人觉得排外,我不是其中一员,至少现在不是。在技术领域,你会在工作中交到朋友。他们只对为自己的创业公司建立关系网、筹集资金和招聘人才感兴趣。
当我的男朋友在这些活动中向人们介绍我时,他们最初会问我做了什么。当我告诉他们我的研究时,我得到了与我在澳大利亚得到的截然不同的反应。旧金山人似乎比澳大利亚人更痴迷于人们的工作。
他们的目光会变得呆滞,从我身边滑过,落到下一个人身上。或者他们会开始从我的肩膀上看还有谁在那里。有一次,一个家伙甚至滑稽地向后转,朝另一个方向走去,就像在一个训练队里一样。
在我看来,他们的行为相当粗鲁。他们甚至不能假装有礼貌。人们希望从他们遇到的人身上得到一些东西,如果我不能帮助他们,那么他们需要尽快离开。
有几个例外,但我基本上被忽略了。创业界的人似乎对我或我做的事情一点也不感兴趣。
似乎一旦他们意识到我没有直接的价值可以传授给他们萌芽中的创业企业,他们就想尽快离开。这些人是铁杆网络爱好者,他们很快就意识到认识我对他们没有任何好处。因此,他们不想浪费时间进行礼貌的闲聊。
这确实让我想知道旧金山是不是适合我的地方。这些人我根本不认识。所以如果他们不想跟我说话,我也能克服?但后来还是不断发生。
过了几个非常无聊的晚上后,我开始想,如果我没有一份技术工作,我是否会在硅谷交到朋友。我会尴尬地站在一群人中间听着,对谈话没什么贡献。
在大多数这些聚会上,我都感到很不自在。他们主要是 20 多岁或 30 多岁的白人男性。我是那里为数不多的女性之一,也是为数不多的不从事技术工作的人之一。
我还想知道,我收到的部分不热情的回应是否可能是因为那些经常被技术职业所吸引的人。我遇到的一些人可能在与非技术人员交谈时缺乏自信。也许他们不重视闲聊,并为与技术无关的交流而挣扎。
初创公司的数据科学家
住在旧金山时,我决定放弃癌症研究,转而从事数据科学。科技场景的诱惑对我来说太大了。如果你想更多地了解我是如何实现这一职业转变的,你可以在我之前的一些故事中找到细节,比如‘我是如何在 6 个月内从零编码技能变成数据科学家的’。
更高的工资、更好的条件和更直接的影响的诱惑让我在硅谷的一家医疗保健初创公司找到了一份数据科学的工作。我开始着手分析大量医疗索赔数据,以帮助美国人做出更好的医疗决策。
因此,我进入了神圣的创业领域,不仅草更绿,而且有一个园丁为你照顾它。在科技行业工作完全改变了人们对我的看法。
我的新人气
我突然就红了。我在科技活动中遇到的人想向我推销他们的想法。有时希望我能把他们介绍给我认识的人。其他时候,他们希望我加入他们的团队。
他们问了我所在团队的情况,工作流程如何,我喜欢什么,不喜欢什么,以及许多后续问题。
从一个社会弃儿变成一个受欢迎的孩子是一种奇怪的感觉。即使人们真的在听我的每一句话,就像我要揭示生活的秘密一样,这感觉很空洞。我总能感觉到要求的到来,他们不可避免地想要一些东西,一些他们认为我可以带给他们努力的东西。
以这样一种方式行事,你对待人类,无论是对你自己还是对他人,总是同时作为一个目的,而不仅仅是一种手段。
-伊曼纽尔·康德
我当然有这样的印象,我更多的是“达到目的的手段”,而不是目的本身。我猜之前被忽视的经历让我变得愤世嫉俗,多疑。我觉得这些品质并不吸引我。所以我努力改变自己的态度,用新的眼光看待每一次新的互动。
我想,人们尽最大努力让自己的创业公司起步,并尽可能地建立联系,这并没有那么糟糕。如果他们在这个过程中没有让我觉得被评判,那就好了。我还认为,如果他们对别人和他们要说的话更感兴趣,他们会更成功地找到他们想要的东西。但这只是我的拙见。
我如何在旧金山交到真正的朋友
科技行业的某些部分可能非常排外,甚至当你身处其中时也是如此。我最初在旧金山结交的许多朋友都不是来自科技界。
我通过我的博士后和我的同事交了朋友。我发现的另一个认识人的有用途径是通过我的爱好。当我住在海湾地区的时候,我参加了很多马戏班。我尝试了空中飞人、空中丝绸、天琴座和杂技,所有这些都吸引了奇怪但精彩的人群。
最终,当我成为旧金山一家医疗保健初创公司的数据科学家后,我和许多同事成为了好朋友。有趣的是,这些技术人员有着广泛的外部兴趣。两个是作者,一个创建了技术杂志,一个曾经是僧侣,一个在瓶子摇滚乐队演奏,一个是合格的跳伞教练,一个是令人敬畏的吉他手,一个创造了惊人的光艺术装置。我可以继续说下去,但你应该明白。
所以最终我在科技行业找到了我的部落。我觉得这些朋友把我当成了一个完整的人,而不仅仅是技能和关系的集合。有一群我可以完全做我自己的人在一起是如此的不同。
在技术领域找到我的人也帮助我享受旧金山提供的所有冒险。我和我的同事们有机会去海湾航行,在电影放映前看阿拉米达的达人秀,参加瓶摇滚音乐节,我的朋友在那里,在奥克兰的 Yoshis 看我从未见过的古典吉他手,去 Taho 滑雪,参加 Hardly Strictly Bluegrass 等等。如果没有我在那里遇到的人,我永远也不会发现所有这些事情。
所以一旦我周围有了这些支持我的人,海湾地区就更像是我的第二个家了。
除了数据,我的另一个爱好是绘画。你可以在 www.katemarielewis.com 找到我的野生动物艺术
了解我是如何成为数据科学家的:
我用来自学数据科学的 4 个工具没有花一美元
towardsdatascience.com](/how-i-went-from-zero-coding-skills-to-data-scientist-in-6-months-c2207b65f2f3) [## 让我获得第一份数据科学工作的面试策略
我是如何展示自己得到这份工作的
towardsdatascience.com](/interview-strategy-that-landed-me-my-first-data-science-job-bdd5e77bfb49)
从朱庇特笔记本到剧本
不要玩玩具模型;准备好生产你的作品吧!
8 月 16 日:从脚本到预测 API
2 月 23 日:从 cURL 到自动化工作流程
2022 年 1 月:面向高级初学者的 Python
作为高级初学者,我们知道很多:EDA、ML 概念、模型架构等……我们可以写一个大的 Jupyter 笔记本,点击“重启并运行全部”,生成最先进的结果。好吧,接下来呢?别人如何使用/复制/扩展你的成果?
在本文中,我将向您展示我如何将 Jupyter 笔记本从葡萄酒数据集上的 Kaggle 转换为脚本,分享一些我们可以轻松适应并立即带来好处的工程实践。
对于它们中的每一个,都有更多的内容需要挖掘,但我们将只介绍基本的内容,展示其优势,并解释思考过程!目标是尽量减少工程师在和你说话时翻白眼的可能性。
Jupyter 笔记本
Jupyter 笔记本是很好的探索和原型,但我们不能永远停留在那里。没有工程师(或没有人)愿意阅读你的代码并重写它。即使你足够幸运地拥有工程资源,它也只会减慢整个过程🙁
不知何故,我们需要调整工程实践,使其可重复、可自动化和可部署!第一步是将笔记本转换成脚本,这是本文的主题!
回购中这部伟大笔记本的所有功劳归原创者所有!
脚本:ipynb-->。巴拉圭
为什么要写剧本?为什么我们不能在交互式笔记本工作正常的时候使用它呢?让我提出一些场景来证明为什么在探索之外使用脚本是一个好主意!
- 如果要并行运行 20 个大机型,会开 20 台笔记本吗?
- 假设你愿意打开 20 台笔记本,你会如何配置超参数?去每个笔记本找相关单元格?
- 假设你手动配置 20 台笔记本,你会如何分析结果?转到每个笔记本?
- 假设您可以在前 3 步处理 20 台笔记本电脑,如果您有一个伟大的想法,但您需要用 200 组超参数进行实验,您愿意重复步骤 1-3 吗?
- 假设您在原始笔记本中发现了一个错误,需要重新运行所有内容,您愿意重复步骤 1–3 吗?
如果你的回答都是肯定的,那么这篇文章不适合你,再见,祝你有美好的一天😊
我构建管道的方式是将它分解成 etl.py 、 train.py 和 predict.py 。每个脚本都有自己的职责,并尽量做到原子化,这样,只要职责明确,每个团队成员都可以开发它们。
etl.py :转换原始数据,做一些转换,在数据文件夹【train_test_split】下创建 train.csv 和 test.csv
train.py :使用 train.csv 中的数据,将模型导出到模型文件夹【model.fit(X,y)】
predict.py :使用 test.csv 中的数据和训练好的模型,导出预测,并对[model.predict(X,y)]求值
脚本关系,各自处理自己的部分
# File structure
.
├── README.md
├── __init__.py
├── autoformat.sh
├── data
│ ├── predict.csv
│ ├── test.csv
│ ├── train.csv
│ └── winequality.csv
├── log
│ ├── etl.log
│ ├── predict.log
│ └── train.log
├── model
│ └── model.pkl
├── notebook
│ └── prediction-of-quality-of-wine.ipynb
├── requirement.txt
└── scripts
├── config.yml
├── **etl.py**
├── **predict.py**
├── test_train.py
├── test_utility.py
├── **train.py**
└── utility.py
如果我搞砸了什么,我不会试图找出原因[想象 Jupyter 中的状态突变,因为你随机运行细胞],我只会再次运行脚本,看看。
# Run in command line, as simple as this :)$ python3 ./scripts/etl.py
$ python3 ./scripts/train.py
$ python3 ./scripts/predict.py
太好了,我们可以在命令行中加载和运行脚本了!但是正如我们在上面的场景中提到的那样[№2],我们如何配置超参数呢?_?
配置文件作为输入:单击
原则是尽量不要接触代码,我已经创建了另一个 config.yml 来包含所有的配置,并通过点击来加载它们。这样,每一个新的模型都是另一个配置,这保证了可复制性,避免了手动修改代码和引入错误🙁 ].
# config.yml example, I only use this to configure the scripts
etl:
raw_data_file: "data/winequality.csv"
processed_path: "data"
test_size: 0.2
random_state: 42train:
processed_train: "data/train.csv"
ensemble_model: "RandomForestClassifier"
model_config: {n_estimators: 300}
model_path: "model/model.pkl"predict:
model_path: "model/model.pkl"
processed_test: "data/test.csv"
predicted_file: "data/predict.csv"
export_result: True
在脚本中,我创建了一个实用函数来解析配置文件
def parse_config(config_file):
with open(config_file, "rb") as f:
config = yaml.safe_load(f)
return config
然后,我们可以以可扩展的方式将配置加载到脚本中!
[@click](http://twitter.com/click).command()
[@click](http://twitter.com/click).argument("config_file", type=str, default=**"scripts/config.yml"**)
def etl(config_file):
config = **parse_config**(config_file)
raw_data_file = config["etl"]["raw_data_file"]
processed_path = Path(config["etl"]["processed_path"]).......DO SOMETHING.......
如果我们有 20 个具有相似体系结构的模型,我们只需准备 20 种配置,仅此而已
不打印:记录
我们现在可以在命令行环境中组合脚本和配置了!我如何获得输出?在 Jupyter 世界中,我可以打印和查看,但这意味着我需要浏览一个很长很长的笔记本,如果我有很多模型怎么办?有什么具体的方法可以将输出收集到一个文件中吗?
放开打印,学习日志!Python 中的日志模块顾名思义就是用 Python 做日志。我们可以定义和记录我们感兴趣的事情,例如,脚本的哪个阶段[用于调试],指标的总结[用于评估],我从模型预测和评估中提取了一段作为示例
这段代码将生成如下所示的日志
从本文中了解更多关于日志记录的信息!https://www . machinelingplus . com/python/python-logging-guide/
旁白:
日志记录很好,但是如果我们有 100 个实验,我们将得到 100 个日志文件🙁即使是具体的,我们也不一定想一个一个看,有没有更好的方法来评价?以下是一些可能的解决方案:
- 还有一个脚本,利用 grep 或 regex,解析并提取关键信息[但是如果有人改变了格式或拼写怎么办!?]
- 又一个工具,checkout MLFlow 或者 ModelDB ![日志记录只是这两款产品的功能之一]
再现性问题:康达环境
哟,现在情况似乎不错!我可以推送至 GitHub,我的朋友/同事可以克隆并运行他们在的电脑😊
哦,等等……..他们的电脑……..如果我们使用不同的版本呢?之所以常见,是因为每个包都有很多版本,比如: sklearn 。APIs 接口可能会随着时间而改变[并破坏代码🙁],我们如何确保使用相同的软件包?
简答:康达 env,查看马特的文章
我在下面列出了一些有用的命令,刚好满足我们的需求
# In terminal# Create the environment
$ conda create — name YOU_CHANGE_THIS python=3.7 -y# Activate it
$ conda activate YOU_CHANGE_THIS# Install the needed package
$ pip install –r requirements.txt# # ## # ## # ## # ## # ## # ##
# # # Do your development # # #
# # ## # ## # ## # ## # ## # ### Deactivate and back to normal environment
$ conda deactivate# This will remove the environment, do it when you finish the project?
$ conda remove –name YOU_CHANGE_THIS –all
*在 requirements.txt 中,您应该始终指定版本!如果你不指定它,它会尝试下载最新的版本,但是你的最新版本可能不是我的最新版本,这样就失去了使用 Conda env 的意义
# this is what I have inside requirements.txt
pytest==5.3.5
pandas==1.0.1
Click==7.0
scikit-learn==0.22.1
black==19.10b0
isort==4.3.21
PyYAML==5.2
不要破坏你以前的代码:pytest
在软件/ ML 的世界里,变化是永恒的,无论何时我们工作,我们都会改变一些东西。但是我们如何确保新的变化不会破坏现有的变化(尤其是你几个月前写的变化)?
单元测试是有帮助的😊我们可以为每个功能编写测试用例,以确保它们具有预期的行为。单元测试不能证明程序的正确性,但是它们可以保护你列出的场景!
例如,下面的代码断言类型和输出维度是预期的。这看起来很傻也很简单,但是如果你的 load_data 函数变得更复杂,你会感激一些东西一直保护着你[特别是如果你想改变一些东西,不要问我是怎么知道的]!
要运行单元测试,只需在终端中运行 pytest ,您应该会看到如下输出
酷,我们可以在推 GitHub 之前运行 pytest,并尝试维护一个可行的程序!但是人类是不可靠的,如果我们在 push 之前忘记运行 pytest 并破解代码怎么办!?在这种情况下,我们该如何保护自己?
如果可能,不要依赖人类:持续集成
如果程序本身可以在我们推送/创建拉取请求时自动运行单元测试,那会怎么样?如果不能通过测试,它就可以停止合并!如果您听说过持续集成,这是特性的一部分!市场上流行的产品是 CircleCI / TravisCI / jenkins,但是我很懒,如果不需要,我不想做任何额外的配置工作,所以我们将使用相对较新的 GitHub 动作😊
在过去,我认为工程师是如此聪明,他们怎么能记住语法并自己想出这样的脚本(这已经很简单了)?不要这样想,大多数人只是像我一样复制和修改模板 GitHub Actions 中 CI workflows 下有一个名为 Publish Python package 的模板]
现在你看到了!脚本、包版本和 pytest 一起工作来确保包版本是正确的,程序是可行的!当我们增量开发时,他们会保护我们,如果代码破坏了单元测试,他们会说不。如果我们发现了一个 bug,我们可以把它作为另一个测试用例,以确保我们不会犯两次同样的错误!
你能以同样的信心在 Jupyter 笔记本上做同样的事情吗?
代码风格问题:黑色,isort
你听说过 pep8 吗?这是写 Python 的风格惯例,有许多(好)点,但老实说,请不要在这方面测试我,我的大脑不能记住它们!
我记得在我的一堂课上,我的教授要求我们使用 pycodestyle 这是一种检查代码风格的工具,然后我得到了这些消息并逐一修复它们。例如:
$ pycodestyle --first optparse.py
optparse.py:69:11: E401 multiple imports on one line
optparse.py:77:1: E302 expected 2 blank lines, found 1
optparse.py:88:5: E301 expected 1 blank line, found 0
我认为这是一个很好的工具,但有点不完整,如果你能找到我的问题,为什么不帮我纠正一下,节省我的时间呢?
Simply run this and the script will do the rest!# If you get permission error, you can try
# chmod +rx autoformat.sh
$ ./autoformat.sh
结论
事情现在对本地有利!我可以把它们推送到 GitHub,我的朋友可以克隆并在他们的电脑上运行它
但是!我们知道重要的(不好的)信息通常以但是开头,例如:工作申请被拒🙁
但是如果我们想要生产这个模型呢?_?
问:首先,生产化意味着什么?
答:狭义的意思是模型消费,我给你输入,你给我返回输出[可能以 JSON 的形式],例如:web 端点/ API。我们需要一台服务器[另一台计算机]来托管模型和端点,我不想用我的计算机 T11 来托管它,否则整个产品将依赖于我可怜的 Macbook🙁
我在上面突出了两个字,它们正是挑战
1.如何找到另一台计算机来托管模型?
简短的回答:要么买一台电脑,要么从云提供商那里租一台[例如:AWS,Azure,GCP],然后我们就可以宣称我们了解云计算😊
2.如果另一台计算机不是 MacOS,我如何确保我的代码在那里工作?
简答:Docker
总结一下,我们:
a. start from a Jupyter Notebook
b. Code conversion [ipynb to .py]
c. Make the scripts configurable [Click]
d. Include logging [logging]
e. Make sure the local environment is the same [Conda env]
f. Include unit test and basic CI [pytest, GitHub Action]
g. Autoformat the script style [black, isort]
我希望带有注释的文件树结构可以向您展示代码的演变,不要被许多文件夹吓到,因为它们是一步一步开发的,如果您理解思维过程,它是非常简单的!
.
├── README.md
├── __init__.py
├── .github/workflows [f]
├── autoformat.sh [g]
├── data
│ ├── predict.csv [b]
│ ├── test.csv [b]
│ ├── train.csv [b]
│ └── winequality.csv
├── log
│ ├── etl.log [d]
│ ├── predict.log [d]
│ └── train.log [d]
├── model
│ └── model.pkl [b]
├── notebook
│ └── prediction-of-quality-of-wine.ipynb [a]
├── requirement.txt [e]
└── scripts
├── config.yml [c]
├── etl.py [b, c]
├── predict.py [b, c]
├── test_train.py [f]
├── test_utility.py [f]
├── train.py [b, c]
└── utility.py
我们提到但没有详细说明的东西:
-> Databricks 的 MLFlow / VertaAI 的 ModelDB
我们可以多讨论的事情:
- 云中的模型部署[AWS]
- 集装箱化[码头工人]
现在我们已经建立了一个坚实的基础,这些脚本的形式,我们可以进一步重用它!想象一下,你如何用 Jupyter 笔记本做到这一点?
我理解当有人说你应该尝试 ABC / XYZ 时的感受,但他们没有解释为什么或如何从零开始发展,我希望这篇文章能有所贡献:)
如果这篇文章有用,可以留下一些评论
或者你可以开始我的回购!
或者我的 LinkedIn 【欢迎但请留下几句话表明你不是僵尸】!
这些东西大部分都是我在实习@ 流形 AI 中学到的
从 LeNet 到 efficient net:CNN 的演变
一个易于跟随的旅程,通过主流 CNN 的变化和新奇
卷积神经网络:构建模块
卷积神经网络,或简称 CNN,是一种常用的移位不变方法,用于提取‘可学习特征’。CNN 在深度学习和神经网络的发展和普及中发挥了主要作用。我有一个单独的博客,讨论各种类型的卷积核及其优势。
对迷人的 CNN 层的不同变化的直观介绍
towardsdatascience.com](/types-of-convolution-kernels-simplified-f040cb307c37)
然而,这里我将关注完整的 CNN 架构,而不是关注单个内核。我们可能无法单独访问 CNN 历史上的每一个主要发展,但我将尝试带您了解一般 CNN 架构是如何随着时间的推移而演变的。你需要对 CNN 有一些基本的了解。
卷积神经网络:概述[ 来源
莱内特:一切开始的地方
LeNet 是第一个将反向传播用于实际应用的 CNN 架构,突然间深度学习不再只是一个理论。LeNet 用于手写数字识别,能够轻松胜过所有其他现有方法。LeNet 架构非常简单,只有由 55 卷积和 22 最大池组成的 5 层,但为更好、更复杂的模型铺平了道路。
LeNet 架构[1]
AlexNet:越深越好
AlexNet 是第一批在 GPU 上实现的 CNN 模型之一,真正将当时日益增长的计算能力与深度学习联系起来。他们创建了一个更深入、更复杂的 CNN 模型,该模型具有各种大小的内核(如 1111、55 和 33),频道数量明显多于 LeNet。他们还开始使用 ReLU 激活代替 sigmoid 或 tanh,这有助于训练更好的模型。AlexNet 不仅赢得了 2012 年的 Imagenet 分类挑战赛,还以突然让非神经模型几乎过时的优势击败了亚军。*
AlexNet 架构[2]
概念网:多尺度特征提取
在 CNN 的历史上,InceptionNet 是一个巨大的进步,它从多个方面解决了问题。首先,InceptionNet 比现有的模型更深入,参数更广泛。为了处理训练更深模型的问题,他们采用了在模型之间存在多个辅助分类器的想法,以防止梯度消失。然而,他们的主要主张之一是并行使用不同大小的内核,从而增加模型的宽度而不是深度。他们提出,这样的架构可以帮助他们同时提取更大和更小的特征。
InceptionNet v1 架构[5]
VGG:3x 3 卷积的力量
虽然 CNN 模型之前的所有迭代都相信更大感受野的想法(例如,AlexNet 有 1111 个卷积核),但 VGG 提出了将所有这些分解为 33 个卷积的想法。根据 VGG 体系结构,堆叠在一起的多个 3×3 卷积能够复制更大的感受野,并且在它们之间存在更多的非线性(就激活函数而言),它甚至可以比具有更大感受野的对应物表现得更好。他们甚至引入了 1*1 卷积,以进一步增加模型中的非线性。从那以后,VGG 模型变得非常有名,甚至在今天还被用于各种教程中向 CNN 的新成员介绍。
VGG-16 建筑[3]
ResNet:处理消失渐变
简单堆叠多个 CNN 层来创建更深模型的总体趋势很快就停止了,原因是深度学习中一个非常常见的问题,称为消失梯度。更简单地说,在训练 CNN 时,梯度从最后一层开始,在到达初始层之前,需要穿过中间的每一层。这可能会导致渐变在某处完全消失,从而难以训练模型的初始层。ResNet 模型引入了剩余或快捷连接,为渐变创建了替代路径,以跳过中间层并直接到达初始层。这使得作者可以训练早期表现不佳的非常深入的模型。现在,在现代 CNN 架构中使用剩余连接已经成为一种常见的做法。
ResNet 架构[4]
MobileNet & MobileNetV2:向边缘友好型发展
CNN 在这个阶段的总趋势是创建越来越大的模型以获得更好的性能。虽然 GPU 提供的计算能力的进步允许他们这样做,但一系列新的产品也在 ML 世界中引起了注意,称为边缘设备。边缘设备具有极大的内存和计算限制,但却为 GPU 无法应用的许多应用打开了大门。
为了创建更轻的 CNN 模型,使其能够与现有的最先进技术相媲美,MobileNet 应运而生。MobileNet 引入了可分卷积的概念(我在之前的博客中详细讨论过)。更简单地说,它将 2D 卷积核分解为两个独立的卷积,深度卷积负责收集每个通道的空间信息,点卷积负责各个通道之间的交互。后来,MobileNetV2 也引入了剩余连接和架构中的其他调整,以进一步减小模型大小。
深度方向可分的 2D 卷积[ 来源
效率网:挤压和激励层
有了各种关注性能或计算效率的独特模型,EfficientNet 模型提出了这两个问题可以通过类似的架构来解决的想法。他们提出了一个通用的 CNN 框架结构和三个参数,即宽度、深度和分辨率。模型的宽度是指各层中存在的通道的数量,深度是指模型中的层数,分辨率是指模型的输入图像大小。他们声称,通过保持所有这些参数较小,可以创建一个有竞争力但计算效率高的 CNN 模型。另一方面,仅仅通过增加这些参数的值,就可以创建更注重精度的模型。
虽然挤压层和激发层早就提出来了,但他们是第一个将这个想法引入主流 CNN 的人。S&E 图层创建跨通道的交互,这些交互对于空间信息是不变的。这可以用来降低不太重要的渠道的影响。他们还引入了新提出的 Swish 激活,而不是 ReLU,这是性能提高的一个重要因素。EfficientNets 是目前在各种计算资源可用性类别下表现最好的分类模型。
挤压和激励网络[ 来源
下一步是什么?
如今,CNN 模型在其图像分类性能以及跨各种其他问题陈述(如对象检测和分割)的迁移学习能力方面受到测试。这些问题中的一些被认为已经解决了。焦点正转向 CNN 模型,如沙漏架构,其中输出图像分辨率与输入相同。然而,即使在今天,我在这篇博客中介绍的主干直接用于各种深度学习任务,因此即使图像分类问题几乎得到解决,该领域的发展在未来仍将具有很大的重要性。
参考
[1] LeCun,Yann 等,“基于梯度的学习在文档识别中的应用”IEEE 86.11 会议录(1998):2278–2324。
[2]克里热夫斯基、亚历克斯、伊利亚·苏茨基弗和杰弗里·e·辛顿。"使用深度卷积神经网络的图像网络分类."神经信息处理系统进展。2012.
[3]西蒙扬、卡伦和安德鲁·齐塞曼。“用于大规模图像识别的非常深的卷积网络。”arXiv 预印本 arXiv:1409.1556 (2014)。
[4]何,,等.“用于图像识别的深度残差学习”IEEE 计算机视觉和模式识别会议录。2016.
【5】塞格迪,克里斯蒂安,等着《用回旋深化》IEEE 计算机视觉和模式识别会议录。2015.
【6】Howard,Andrew G .等,《移动网络:用于移动视觉应用的高效卷积神经网络》arXiv 预印本 arXiv:1704.04861 (2017)。
[7]谭、明星、郭诉乐。"效率网:重新思考卷积神经网络的模型缩放."arXiv 预印本 arXiv:1905.11946 (2019)。
从线性回归到岭回归,套索和弹性网
图 1:普通回归与套索回归、山脊回归和弹性网回归相比的图像。图片引用:邹,h .,&哈斯蒂,T. (2005)。通过弹性网的正则化和变量选择。
以及为什么您应该学习替代回归技术
简介:
普通最小二乘法(()OLS()是最古老、最简单的回归算法之一。然而,现在有几个变种被发明出来,以解决使用常规最小二乘回归时遇到的一些弱点。
尽管是最古老的算法之一,线性模型仍然非常有用。事实上,它们往往能胜过花哨复杂的模型。当没有大量的观察值时,或者当输入可靠地预测响应时(低信噪比),它们特别有用。
在本文中,我们将首先回顾使用线性回归的基本公式,讨论如何使用梯度下降法求解参数(权重),然后介绍岭回归。然后我们将讨论套索,最后是弹性网。这篇文章也将属于我的从零开始构建机器学习算法系列(大部分)。到目前为止,我已经从头开始讨论了逻辑回归,从奇异值分解和遗传算法中导出主成分。
我们将使用来自 1989 年研究的真实世界癌症数据集来了解其他类型的回归、收缩以及为什么有时线性回归是不够的。
癌症数据:
这个数据集由 1989 年完成的一项真正的科学研究的 97 个观察数据组成。数据包括 8 个预测因子,感兴趣的结果是 lpsa(对数前列腺特异性抗原)。
这个数据集在 统计学习的要素 中有所详细讨论。
首先,我们加载将要使用的库,然后读入数据集。
下面是最初的一些观察结果:
图 2:前列腺癌数据集的最初几个观察结果。预测因子包括 log cavol、log weight、age、lbph、sci、lcp、gleason、pgg45。我们还有一个指示器,告诉我们观察值是属于训练集还是测试集。图片来自作者。
在 97 个观察值中,67 个被指示为属于训练,而剩余的 30 个被保存用于在算法训练结束时进行测试。请注意,我们不需要“Id”列或“train”列,因此我们将其删除。在回归之前,我们还经常建议缩放和居中我们的列。
我们首先将 97 个观察结果分成初始训练集和测试集。初始训练集的大小为 67,剩余的 30 个观察值在测试集中。(x_train,y_train)和(x_test,y_test)。在本文的后面,我们将进一步把我们的训练集分解成一个训练/验证集。请注意,我们的模型将根据测试数据进行评估,因此我们在拟合模型时不使用任何测试数据。
回归设置:
首先,考虑一个简单的回归问题,有 N 个观察值(行)和 p 个预测值(列),包括:
- N x 1 个结果向量, Y.
图 3:我们 N 次观察的结果向量。图来自作者。
- 观察值的 N x (p+1)矩阵, X
图 4:N 个观察值中的每一个都表示在一行中。考虑到截距或“偏差”项,我们还在每个观察值上加 1。图来自作者。
- (p+1) x 1 个权重向量, W 。
图 5:我们的权重向量,w。图来自作者。
为了获得我们的预测,我们将我们的权重 W 乘以我们的观测值 x。因此,残差或真实结果与我们的预测之间的差异可以用 N x 1 矩阵表示:
图 6:我们的预测减去我们的估计。请注意,估计值是通过将权重乘以我们的观察值获得的。我们的预测越接近真实值,该行就越接近零。图来自作者。
“完美”的情况是图 6 中的矩阵充满了零,因为这将代表对训练数据的完美拟合。但这种情况几乎从来没有发生过,这也可能是“过度拟合”模型的一种情况。
成本函数:
为了确定一个模型有多好,我们需要一些“好”的定义。在线性回归中,这几乎总是均方误差(MSE)。这只是我们的估计和真实观察之间的误差平方和。
图 7:红点代表实际观察,表面代表我们在任一点(X1,X2)的预测。这些线条表示我们的预测与实际观测数据之间的距离。这些距离的平方和定义了我们的最小二乘成本。图片引用:该图片经许可使用,如图 3.1 所示,出现在《统计学习要素》第二版中。
通常,这在一个例子中被定义为损失函数。对于整个训练数据,我们使用成本函数,即每个训练示例的平均损失。
为了找到成本曲面的最小值,我们使用梯度下降,这涉及到对每个参数进行求导。
当只有两个参数时,成本表面实际上可以被可视化为等高线图。在更高维度中,我们不能直接看到表面,但是寻找最小值的过程是一样的。梯度下降依赖于学习率α,它控制我们采取的步长。
图 8:梯度下降就是采取步骤寻找损失面最小值的过程。图片引用:https://www . research gate . net/figure/Non-convex-optimization-We-utilize-random-gradient-descent-to-find-a-local-optimum _ fig 1 _ 325142728
对于每个时期或迭代,我们计算每个参数相对于成本函数的导数,并在方向(最陡)方向上迈出一步。这确保我们(最终)达到最小值。实际上,这并不简单,因为学习率可能太大或太小,导致陷入局部最优。
图 9:梯度下降。训练我们的重量(参数)的步骤。这包括通过减去成本函数相对于权重的导数,再乘以α(学习率)来更新每个权重。图来自作者。
现在是定义我们稍后将使用的一些助手函数的好时机:
线性回归:
线性回归是最简单的回归算法,于 1875 年首次被描述。“回归”这个名字来源于弗朗西斯·高尔顿注意到的向平均值回归的现象。这指的是这样一个事实,当非常高的父母或非常矮的父母的孩子通常仍然更高或更矮时,他们倾向于接近平均身高。这被称为“回归均值”。
图 10:高尔顿在遗传地位上回归平庸。图片引用:https://RSS . online library . Wiley . com/doi/full/10.1111/j . 1740-9713.2011 . 00509 . x
最小二乘回归的工作原理是简单地拟合一条线(或二维以上的超曲面)并计算从估计值到实际观察点的距离。最小二乘模型是最小化模型和观测数据之间的平方距离的模型。
图 11:线性回归的成本函数。成本是单个损失函数的归一化总和。这和均方误差乘以一个标量是一样的(最后的结果是等价的)。图来自作者。
图 12:线性回归的成本函数的导数。图来自作者。
您可能会注意到,这可能会使我们的算法容易受到离群值的影响,其中一个孤立的观察值可能会极大地影响我们的估计。这是真的。换句话说,线性回归对异常值并不稳健。
另一个问题是,我们可能对训练数据拟合得太好了。假设我们有许多训练数据和许多预测器,有些具有共线性。我们可能会获得非常适合训练数据的线,但它可能不会在测试数据上表现得那么好。这就是替代线性回归方法的优势所在。因为我们在最小二乘法中考虑了所有的预测值,这使得它容易过度拟合,因为添加额外的预测值没有损失。
因为线性回归不需要我们调整任何超参数,所以我们可以使用训练数据集来拟合我们的模型。然后,我们在测试数据集上评估线性模型,并获得我们的均方误差。
从零开始渐变下降:
下面的代码从头开始实现梯度下降,我们提供了添加正则化参数的选项。默认情况下,“reg”设置为零,因此这将等同于与简单最小二乘法相关联的成本函数的梯度下降。当 reg 大于零时,算法将产生岭回归的结果。
由于我们现在使用自定义函数,我们需要向矩阵 x_train_scaled 添加一列 1,这将考虑截距项(将乘以权重 W0 的项)。我们还将对象转换成 numpy 数组,以便进行更简单的矩阵计算。
让我们来看看梯度下降是如何进行的:
图 14:随着我们不断制造越来越好的砝码,成本下降得相当快。图来自作者。图来自作者。
现在让我们使用通过梯度下降获得的权重来对我们的测试数据进行预测。我们内置的 MSE 函数将使用wllinear来计算预测,并将返回测试 MSE。
使用梯度下降来获得我们的权重,我们在我们的测试数据上获得 0.547 的 MSE。
岭回归:
与最小二乘成本函数相比,岭回归使用增强的成本函数。岭回归引入了一个附加的“正则化”参数,而不是简单的平方和,该参数会对权重的大小产生不利影响。
图 15:岭回归的成本函数。成本是单个损失函数的归一化总和。该成本函数通过正参数λ来惩罚权重。图来自作者。
幸运的是,这个成本函数的导数仍然很容易计算,因此我们仍然可以使用梯度下降。
图 16:岭回归的成本函数的导数。图来自作者。
快速事实:
- 岭回归是吉洪诺夫正则化的特例
- 存在封闭形式的解,因为在矩阵上添加对角元素确保了它是可逆的。
- 允许可容忍的额外偏置量,以换取效率的大幅提高。
- 在神经网络中使用,这里称为权重衰减。
- 当您有太多预测值,或预测值之间有高度多重共线性时使用。
- 等效于 lambda 为 0 时的普通最小二乘。
- 又名 L2 正规化。
- 在应用岭之前,必须缩放预测值。
图 17:二维情况下 OLS 估计和岭回归估计的比较。请注意,在成本函数中正则化项的原点处,岭估计被限制在一个圆内。岭估计可视为线性回归系数等高线与 B1+B2≤λ定义的圆相交的点。图像引用:统计学习的要素,第 2 版。
因为我们在岭回归中有一个超参数 lambda,所以我们形成了一个额外的维持集,称为验证集。这与测试集是分开的,允许我们调整理想的超参数。
选择λ:
为了找到理想的λ,我们使用一系列可能的λ值来计算验证集的 MSE。函数 getRidgeLambda 在维持训练集上尝试一系列 Lambda 值,并在验证集上检查 MSE。它返回理想的参数 lambda,然后我们将使用它来拟合整个训练数据。
理想的λ是 8.8,因为它导致验证数据的最低 MSE。
使用交叉验证,我们获得了λ= 8.8 的理想“reg”参数,因此我们使用该参数通过梯度下降来获得我们的岭估计。
使用岭回归,我们在 0.511 的测试数据上得到甚至更好的 MSE。请注意,与最小二乘法估计的系数相比,我们的系数被“缩小”了。
套索回归:
套索回归或(最小绝对收缩和选择算子’)也适用于替代成本函数;
图 Lasso 回归的成本函数。我们仍然正则化,但使用 L1 正则化,而不是在山脊 L2。这个成本函数的导数没有封闭形式。图来自作者。
然而,成本函数的导数没有封闭形式(由于 L1 在权重上的损失),这意味着我们不能简单地应用梯度下降。Lasso 允许系数实际上被强制为零的可能性(见图 19),本质上使 Lasso 成为一种模型选择方法以及一种回归技术。
快速事实:
- 被称为“诱导稀疏”的方法。
- 有时被称为基础追踪。
图 19:OLS 估计和 Lasso 回归估计的比较。请注意,Lasso 估计值被限制在成本函数中正则化项的原点处的一个框中。椭圆与边界框相交的点给出了套索估计。注意,在上面的例子中,我们在一个拐角处相交,这导致上面例子中的系数(B1)被设置为零。统计学习的要素,第二版。
由于我们不能应用梯度下降,我们使用 scikit-learn 的内置函数来计算理想的权重。然而,这仍然需要我们选择理想的收缩参数(就像我们对山脊所做的那样)。我们采用与岭回归中相同的方法来搜索验证数据上的理想正则化参数。
Lasso 在测试数据上提供了 0.482 的 MSE,甚至小于岭和线性回归!而且,Lasso 还将一些系数设置为零,完全排除在考虑范围之外。
弹性网:
最后,我们来到弹性网。
图 20:弹性网的成本函数。它包含了 L1 和 L2 的损失。图来自作者。
弹性网有两个参数,因此,我们需要搜索组合网格,而不是搜索单个理想参数。因此训练可能会有点慢。不是直接搜索λ1 和λ2,通常最好是搜索这两个参数之间的理想比率,以及λ1 和λ2 之和的α参数。
快速事实:
- 线形、脊形和套索都可以看作是弹性网的特例。
- 2014 年证明了弹性网可以化简为线性支持向量机。
- 损失函数是强凸的,因此存在唯一的最小值。
这个弹性网是套索的延伸,它结合了 L1 和 L2 的正规化。所以 L1 需要一辆 lambda1,L2 需要一辆 lambda2。类似于套索,导数没有封闭的形式,所以我们需要使用 python 的内置功能。我们还需要找到我们的两个参数之间的理想比率,以及作为λ1 和λ2 之和的附加α参数。
图 21:弹性网(红色)是脊回归(绿色)和套索(蓝色)的组合。图片引用:https://www . research gate . net/figure/Visualization-of-the-elastic-net-regularity-red-combining-the-L2-norm-green-of _ fig 6 _ 330380054
我们不会从头开始编码弹性网,scikit-learn 提供了它。
然而,我们执行交叉验证来选择两个参数,alpha 和 l1_ratio。一旦我们有了理想的参数,我们就使用选择的参数在完全训练上训练我们的算法。
哇!弹性网提供了比所有其他模型更小的 MSE (0.450)。
综合起来看:
最后,我们计算了最小二乘法、脊线法、套索法和弹性网格法的结果。我们已经获得了每种方法的权重,还获得了原始测试数据集的 MSE。我们可以在表格中总结这些方法的表现。
图 22:我们每个模型的最终比较。此表总结了测试集的最终估计系数和均方误差。图来自作者。
与所有其他模型相比,简单最小二乘法在我们的测试数据中表现最差。岭回归提供了与最小二乘法相似的结果,但它在测试数据上做得更好,并缩减了大多数参数。最终,Elastic Net 在测试数据集上提供了最好的 MSE,而且差距很大。弹性网去掉了 lcp,格里森,年龄,缩水了其他参数。拉索也去除了年龄、lcp 和格里森的考虑,但表现略差于弹性网。
总结:
了解基本的最小二乘回归仍然非常有用,但也应该考虑其他改进的方法。常规最小二乘法的一个问题是它没有考虑过拟合的可能性。岭回归通过缩小某些参数来解决这个问题。Lasso 更进一步,允许将某些系数直接强制为零,从模型中消除它们。最后,弹性网结合了套索和脊的优点。
在某些情况下,我们可以推导出最小二乘的精确解,只要λ> 0,我们总是可以推导出岭的解。选择 lambda 是困难的部分(你应该在训练数据集上使用交叉验证来选择理想的 lambda)。在本指南中,我们没有显示封闭形式的解决方案,因为最好从头开始了解解决方案是如何解决的,并且因为封闭形式的解决方案通常不存在于高维空间中。
感谢您的阅读,如果您有任何问题或意见,请发送给我!
想了解更多?
如果您喜欢这些主题,并想学习更高级的回归技术,请查看以下主题:
来源:
来自统计学习的元素的图像被允许使用。“作者(Hastie)保留所有这些数字的版权。它们可以用在学术报告中。”
GitHub 上的代码:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Robby955/CancerData/blob/master/pythonRegression.py)
[1]邹,h .,,哈斯蒂,T. (2005).通过弹性网的正则化和变量选择。皇家统计学会杂志:B 辑(统计方法学)。
[2]阿米尼,亚力山大&索莱马尼,艾娃&卡拉曼,塞尔塔克&鲁斯,达尼埃拉。(2018).用于端到端控制的空间不确定性采样 。神经信息处理系统。
[3]斯塔梅、T. A .、卡巴林、J. N .、麦克尼尔、J. E .、约翰斯通、I. M .、弗赖哈、f .、雷德温、E. A .、杨(1989)。前列腺特异性抗原在前列腺癌诊断和治疗中的应用。二。根治性前列腺切除术治疗的患者。《泌尿外科杂志》, 141 (5),1076–1083。https://doi . org/10.1016/s 0022-5347(17)41175-x
【4】哈斯蒂,t .【哈斯蒂,t .】蒂布希拉尼,r .&弗里德曼,J. H. (2001)。统计学习的 要素 :数据挖掘、推断、预测。纽约:斯普林格。
[5]霍尔,A. E .,&肯纳德,R. W. (1970 年)。岭回归:非正交问题的有偏估计。技术指标。
6 TiB shirani,R. (1996 年)。通过套索的回归收缩和选择。英国皇家统计学会杂志:B 辑(方法论), 58 (1),267–288。
从机器学习到深度学习,这里有 15 个你一定会遇到的术语
说明
人工智能领域内值得学习的关键词…
埃迪·科普在 Unsplash 上的照片
介绍
人工智能作为一个领域包括各种子领域和实践,如计算机视觉、自然语言处理、语音识别、机器学习等。在这些提到的领域中有一些概念和术语,用于描述所设计的算法和技术的目的。
本文将介绍一些你在人工智能相关研究或媒体资源中最有可能遇到的常见概念、术语和关键词。本文提供的信息只是一个高层次的概述;每个术语都有为那些寻求获得更深入知识的人提供的资源。
尺度不变特征变换
这是一种用于生成图像关键点描述符(特征向量)的计算机视觉技术。生成的描述符包含关于诸如边、角和斑点的特征的信息。该描述符可用于检测不同比例和失真的图像中的对象。SIFT 被用在诸如对象识别、手势识别和跟踪的应用中。这里有一个介绍这项技术的原始研究论文的链接。SIFT 的关键在于它的检测特征对于任何仿射变换都是不变的,例如缩放、平移和旋转。
方向梯度直方图(HOG)
这是一种用于从图像中提取特征的技术。所提取的特征是从通过图像内的边缘和拐角提供的信息中导出的,更具体地说,是从图像内的对象中导出的。对这些技术的简单描述是,它识别图像内的边缘(梯度)、角和线的位置,并且还获得关于边缘方向的信息。HOG 描述符生成直方图,该直方图包含从图像中检测到的边缘分布信息和方向信息。这种技术可以在计算机视觉应用和图像处理中找到。这里有一个包含更多信息的链接。
主成分分析
主成分分析(PCA): 对特征丰富的数据集进行降维的算法。降维是通过将数据点从较高维度投影到较低平面来实现的,但仍然保持信息并使信息损失最小化。
神经类型转移
神经风格转移(NST): 利用深度卷积神经网络和算法从一幅图像中提取内容信息,从另一幅参考图像中提取风格信息的技术。在提取样式和内容之后,生成组合图像,其中所得图像的内容和样式源自不同的图像。
递归神经网络(RNN)和 LSTM
递归神经网络(RNN)和 LSTM :人工神经网络架构的一种变体,能够接受任意大小的输入,并产生任意大小的输出数据。RNN 神经网络结构学习时间关系。rnn 用于语音识别、图像字幕和自然语言处理等应用中。
Richmond Alake 的递归神经网络解码器阶段
下面是 Luis Serrano 解释 RNNs 基础知识的精彩视频:
人脸检测
人脸检测:实现能够自动识别和定位图像和视频中人脸的系统的术语。面部检测存在于与面部识别、摄影和动作捕捉相关联的应用中。
面部检测和面部特征跟踪
姿态估计
姿势估计:从提供的数字资产,如图像、视频或图像序列,推断身体主要关节位置的过程。姿态估计的形式存在于诸如动作识别、人类交互、虚拟现实和 3D 图形游戏的资产创建、机器人等应用中。
物体识别
物体识别:识别与 a 类目标物体相关的过程。对象识别和检测是具有相似结果和实现方法的技术,尽管在各种系统和算法中识别过程先于检测步骤。
跟踪
跟踪:一种在一段时间内在一系列图像中识别、检测和跟踪感兴趣的物体的方法。在许多监控摄像机和交通监控设备中可以找到系统内跟踪的应用。
目标检测
目标检测:目标检测与计算机视觉相关联,描述了一种能够识别图像中期望的目标或身体的存在和位置的系统。请注意,要检测的对象可能出现一次或多次。
最优化算法
优化算法:执行预定次数的算法,用于寻找问题的最优解;在数学术语中,这些“问题”被称为函数。
梯度下降
梯度下降:该优化算法用于寻找降低成本函数的值。这是通过梯度值的计算来完成的,该梯度值用于在找到成本函数的局部最小值的每一步选择值。梯度的负值用于寻找局部最小值。
价值函数
成本函数:这是一种量化机器学习模型执行“有多好”的方法。量化是基于一组输入的输出(成本),这些输入被称为参数值。参数值用于估计预测,而“成本”是预测值和实际值之间的差异。
全局极小值
全局最小值:这是位于成本函数整个域内的最小参数值。您可能会遇到局部最小值,它是指位于成本函数的设定范围内的最低参数值。
趋同;聚集
收敛:这描述了在机器学习环境中使用时,向最佳参数值或全局最小值移动的概念
我希望这篇文章对你有用。
要联系我或找到更多类似本文的内容,请执行以下操作:
- 订阅我的 YouTube 频道 视频内容即将上线 这里
- 跟着我上 中
- 通过 LinkedIn 联系我
[## 为什么机器学习工程师(或数据科学家)不是这场秀的主角
但是我们仍然是成功的员工队伍中不可或缺的一部分
towardsdatascience.com](/why-machine-learning-engineers-or-data-scientists-are-not-the-stars-of-the-show-d91ec9c5256b) [## 理解卷积神经网络中的局部感受野
想过为什么卷积神经网络中的所有神经元都没有连接起来吗?
towardsdatascience.com](/understand-local-receptive-fields-in-convolutional-neural-networks-f26d700be16c)
从模型拟合到生产只需几秒钟
我能写的关于有效部署 ML & AI 模型的最短的教程
将 ML 模型投入生产是一个挑战;超过 60%的型号从未真正投入生产。事实并非如此:只需几行代码就能有效地将模型投入生产。
模型拟合
由于拟合不是本教程的目的,我将只在标准的 scikit-learn 乳腺癌数据上拟合一个 XGBoost 模型:
# Get the data:
from sklearn.datasets import load_breast_cancercancer = load_breast_cancer()X = cancer.data
y = cancer.target# And fit the model:
import xgboost as xgbxgb_model = xgb.XGBClassifier(objective="binary:logistic", random_state=42)
xgb_model.fit(X, y)
(我忽略了模型检查和验证;让我们来关注部署)
部署模型
现在我们有了合适的模型;让我们使用[sclblpy](https://pypi.org/project/sclblpy/)
包来部署它:
# Model deployment using the sclblpy package:
import sclblpy as sp# Example feature vector and docs (optional):
fv = X[0, :]
docs = {}
docs['name'] = "XGBoost breast cancer model"# The actual deployment: just one line...
sp.upload(xgb_model, fv, docs)
完成了。
使用部署的模型
运行上面的代码几秒钟后,我收到了以下电子邮件:
模型部署完成。
点击蓝色的大按钮,进入一个页面,我可以直接运行推论:
在网络上产生推论
虽然这很好,但是您可能希望创建一个更好的应用程序来使用部署的模型。只需复制粘贴项目所需的代码:
将已部署的模型简单地复制粘贴到软件项目中。
你走吧!
包裹
关于模型部署(以及如何高效地部署:上面的过程实际上将您的模型传输到 WebAssembly 以使其高效和可移植)还有很多要说的,我不会说。
这是我能想到的最短的教程。
放弃
值得注意的是我自己的参与:我是 Jheronimus 数据科学院 的数据科学教授,也是Scailable的联合创始人之一。因此,毫无疑问,我对 Scailable 有既得利益;我有兴趣让它成长,这样我们就可以最终将人工智能投入生产并兑现它的承诺。这里表达的观点是我自己的。
将工作减半的 Python 妙招:自动化执行
使用 VBA、Powershell 和任务调度程序自动执行脚本并通过电子邮件发送结果
作者图片,来自维基共享和 Flickr 的徽标
摘要: 这篇文章讲述了如何调度你的常规 python 脚本。假设你
- 将每天/每周/每月更新的 excel 报告放入共享网络或电子邮件
- 启动并运行 python 脚本来处理您的报告,并以图像、工作表或其他数据形式提供见解。
- 希望以固定的时间间隔长时间运行流程,但又非常担心必须手动运行。
数据工程也有有趣的部分——比如编程和分析数据。然后是无聊的部分,比如定期使用已经写好的程序来获得最新的结果。显然,没有人想做后者。这里有一个快速解决方法,我用它来避免运行那些需要每天/每周/每月执行的脚本,以便更好地利用这些时间。
三个词—宏、批处理和调度。
- 我使用一个宏将我收到的 excel 报告保存到一个位置。(我从一个执行分析并手动向我发送报告的地方获得它。不,这个没办法)。
- 我设置了一个 outlook 规则,只在想要的文件夹上运行宏,并附带一些其他条件(发件人、主题等)。
- 我写一个批处理文件(。bat),单击它将在命令提示符下执行脚本。
- 我使用 Windows 任务调度器调度 bat 文件,以与新 excel 报告到达的频率相同的频率执行脚本
- 我写了一个 PowerShell 脚本,将最新的结果通过电子邮件发送给所有必要的接收者,然后我安排它在 bat 文件执行后马上运行。
步骤 1: Outlook 宏
- 通过在 outlook 的选项窗格中激活 VBA 脚本,可以在 Outlook 中激活它。
- 然后,您会看到一个开发人员工具按钮出现在 outlook 主页窗口的顶部。
3.转到“开发工具”选项卡,启动 Visual Basic 脚本。
4.在这里创建一个新模块,并编写代码脚本来保存传入的附件。
很简单。
在下面的示例中,报告名称始终是我收到的自动电子邮件的主题。所以我用这个标准来决定我的文件的文件名,并把它保存到一个文件夹中。
(我还确保保存它的日期,这样我就知道在执行我的脚本之前,目标文件夹总是有最新的文件。)
在收到的电子邮件中保存附件的 VBA 脚本:
Public Sub SaveRegularReports(MItem As Outlook.MailItem)
Dim oAttachment As Outlook.Attachment
Dim sSaveFolder As String
sSaveFolder = "/You/want/to/save/here/"
If MItem.Subject = "Quarterly_rep" Then
savename = "QRep"
ElseIf MItem.Subject = "JustSomeRegRep" Then
savename = "RegRep"
ElseIf MItem.Subject = "WeeklyReport" Then
savename = "WeeklyUpdate"
End If
For Each oAttachment In MItem.Attachments
oAttachment.SaveAsFile sSaveFolder & savename & Format(MItem.ReceivedTime, "mmddyyyy") & ".xlsx"
Next
End Sub
原谅我的德语,但我相信你也能认出这些英语设置!
现在,我要做的就是决定这些规则适用于谁。因此,我转到规则,并设置我想要应用脚本的条件。
在我的例子中,我的条件是电子邮件总是来自一个特定的地址,其主题包含报告的名称。(为了安全起见,我将所有此类常规报告都移到了收件箱中的一个单独文件夹中)
在下一步中,作为一个动作,每当这个文件夹得到一个新手时,我就执行上面的脚本 SaveRegularReports。
瞧吧!不费吹灰之力就自动保存了我需要的一切!!
第二步。编写 bat 文件以在保存的 excel 表上执行 python 脚本
这也是小菜一碟。bat(或批处理)文件是一组命令,当您单击它时,命令提示符会执行这些命令。如果您曾经编写过 bash 命令或者使用过 windows 命令提示符 shell 脚本来“pip install”之类的,那么您应该知道我在说什么。
- 打开一个文本文件,编写与下面类似的命令来执行 python 脚本,就像在命令提示符下一样。(我使用的是 anaconda,所以在执行 python 脚本之前,我首先激活了 Anaconda 提示符)。
- 将该文件另存为 filename.bat
[@echo](http://twitter.com/echo) offcall C:\Users\myUSer\AppData\Local\anaconda\Scripts\activate.batC:\This\is\Where\Your\Script\Lives\Scriptchen.pypause
当我点击上面的 bat 文件(scriptchens_bat.bat)时,我的 python 脚本被执行。它使用步骤 1 中保存的 excel 报告。
第三步。任务-计划您的脚本执行
注意:我知道我每周都会收到报告,比如说周五上午 10 点。我将这个脚本设置为每周五 10:30 运行。
- 从 Windows 中的搜索栏打开任务计划程序。转到创建基本任务。
- 在出现的窗口中命名和描述后,转到触发器窗格并设置您的时间表。在这个例子中是星期五的 10:30。
现在是肉的部分。转到操作窗格。这里是您设置 bat 文件以便执行的地方。从“操作”中选择“启动程序”,在程序窗格中,给出您的。您在步骤 2 中编写的 bat 文件。
单击确定并确认。
瞧啊。现在,您每周都可以轻松地输出 Python 脚本了!
第四步。通过电子邮件发送结果
如果你对最新的结果感到满意,你可以就此打住。但是,如果您想更进一步,也想自动分发您的处理结果,请喝杯咖啡,通读最后一步。
我决定使用 powershell 将我的 outlook 结果通过电子邮件发送给其他同事。以下是方法:
- 从 windows 搜索打开 PowerShell ISE。
- 下面的脚本是我的案例的一个例子,它将结果分别用正文和主题行发送给所有收件人。你可以修改你的脚本来满足你的需要。
$OL = New-Object -ComObject outlook.applicationStart-Sleep 5$recipients = @(“recipient_one@company.de”,”recipient_two@company.de”,”recipient_three@company.de”)foreach ($recipient in $recipients){$mItem = $OL.CreateItem(“olMailItem”)$mItem.To = $recipient$mItem.Subject = “Automatic Email: Weekly Report”$mItem.Body = “This is an automated email sent using powershell. In case of any questions please contact Me. Dieses Dokument enthält… “$mItem.Attachments.Add(“\This\is\where\my\python\output\lives\file_to_email.xlsx”)$mItem.Send()}
自动发送电子邮件的 Powershell 脚本
第五步。设置任务计划程序,将您的结果通过电子邮件发送给收件人
与步骤 3 类似,现在您将安排 powershell 脚本在 python 脚本执行后每周执行一次。
- 转到任务计划程序中的新任务
- 命名并描述您的任务
- 转到 trigger 并设置您的计划
- 开始行动。在程序/脚本栏中,输入 PowerShell 应用程序的地址。它通常在这里:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
在参数栏中,输入之前编写的. ps1 脚本的路径。
瞧啊。你不费吹灰之力就发了邮件!
总而言之,您自动化了整个事件链,从接收 excel 文件开始,将其保存到某个位置,用 python 处理它,然后用电子邮件发送结果。这是一个非常巧妙的方法,节省了我大量的工作时间。希望它也能帮助你!
从哲学专业到 DevOps 工程师
办公时间
我是如何从一个非 STEM 专业的学生成为一家财富 100 强公司的开发工程师的
听到我有哲学学士学位,我的许多工程同事都很惊讶。我团队中拥有 STEM 学位的人经常告诉我,拥有非 STEM 学位是一种优势。但是成为一名 DevOps 工程师的道路并不短,在这一过程中我也犯过错误。许多人想知道我是如何走过从哲学学位到 DevOps 工程师的奇异道路的。这篇文章将阐明我是如何做到的。简而言之,这是一点点运气,重要的家庭支持,以及大量的努力和耐心。但首先,一个故事。
一个故事
当我的经理问我是否可以在我的母校 UCSD 做一些招聘工作时,我正在甲骨文公司担任云工程师。当我到达时,进入加州大学圣迭戈分校技术招聘会的队伍很长。我遇到了各种各样的学生。有些人递给我一份计算机科学 GPA 为 4.0 的简历,但无法表达连贯的思想,还有一些人不会用任何编程语言输出“hello world”。
但是我特别记得一个学生。她是非 STEM 专业,有一些有趣的技术项目。当她把简历递给我时,我能看出她很害羞,担心我会如何看待她的技能或缺乏技能。我还没来得及提问,她就开始为自己的简历辩护了。我说,“嘿,我懂你的意思”。当我告诉她我从加州大学圣迭戈分校哲学专业毕业时,她的眼睛亮了起来。我们后来在 LinkedIn 上联系上了。我给了她一些建议,鼓励她继续下去。
开始
照片由 Jukan Tateisi 在 Unsplash 上拍摄
我毕业于加州大学圣迭戈分校,获得了哲学本科学位。老实说,我不知道我在做什么。我主修哲学作为一个双学位,这样我就可以继续我在这个选民登记组织的工作,这个组织是我帮助建立的,叫做 SOVAC。经过反思,增加一个哲学专业来继续在 SOVAC 工作是一个在大学多呆一年的荒谬理由。我对学生组织的奉献妨碍了我的未来。当我毕业的时候,我意识到我没有市场需要的技能。幸运的是,就在我毕业前,我获得了国家科学基金会(NSF)的资助,从事一个激情项目。
国家科学基金会的拨款给我的钱只够我生存,但我知道这不会持续很久。这笔拨款滚雪球般地变成了我和一个大学朋友创办的公司。我们建立了一个在线投票服务,并签下了一个付费客户,圣地亚哥联盟-论坛报。有了一个想法,把想法变成产品,然后卖给一个付费的顾客,就打开了开关。我就知道这里有东西。我发现了技术故障。
转变
帕特里克·亨德利在 Unsplash 上的照片
我最终得到了一份全职工作,在一家优秀的政府非营利机构担任顾问,但我的心思却被国家科学基金会的工作和我最终创办的公司牢牢占据。我的大学朋友帮助开发了这个产品,他最终被脸书公司提供了一份软件工程的工作。和我一样,他也不是 STEM 专业的学生,但在毕业前,他决定攻读计算机科学,成为一名软件工程师。在大学里,我再也没有机会改变主意了。我已经在现实世界中作为一名非盈利顾问工作。我能回头吗?
我记得当时接到经理的电话,问我是否想成为全职员工,成为员工中的一员。再说一次,我没有真正的计划,拒绝了。事后看来,我或许应该找一份全职工作,让自己有更多选择。也许我本来可以白天工作,上夜校,但我没想那么远。我只知道我想进入科技行业。
当时,训练营开始获得很大的吸引力。但是我决定在一所社区大学尝试一下 Java 入门课程。我已经全职工作了,所以这门课是我时间的一个很大的承诺。我很快意识到我热爱编程。最让我兴奋的是能够用我学到的一点点知识来构建应用程序。就是在这个时候,我决定回到学校学习计算机科学。
要学位还是不要学位?
我决定注册成为一名计算机科学研究生,因为我想了解基础知识,并有一份证明我所发展的技能的文件。我花了太多时间准备 GRE 考试。最后,我报名参加了一个甚至不要求 GRE 成绩的项目。我才意识到,本科无论去哪里都差不多。关于课程,我在哪里上并不重要。
获得学位相当于工作保障。许多人告诉我,获得学位是浪费时间,我可以学到找工作所需的任何东西。这在一定程度上是真实的。现在回想起来,很难说哪条路会更好。我认为更快的途径是参加一个训练营,或者简单地参加一些数据结构和基础编程的在线课程。但我认为获得学位更安全,虽然慢得多。事实是,计算机科学学位并不能保证什么。
在攻读硕士学位大约一年半后,我开始坐立不安。我想要一份工作。此时,我已经完成了计算机科学学位所需的几乎所有本科课程。我看了一些硕士水平的课程,觉得高级课程没什么价值。我只是想要一份工作和经验。我不想借更多的贷款,也不想花更多的时间去完成一个学位。我开始申请世界上所有的东西。我搞砸了一些采访。我显然生疏了。最终,我获得了甲骨文公司云工程师的面试机会。老实说,我不知道什么是云,也不知道甲骨文甚至有云服务。我甚至不知道云工程师是做什么的。
开始
Ashwini Chaudhary 在 Unsplash 上拍摄的照片
我做了准备,并认为我没有通过面试,但我惊讶地得到了一份工作。我很兴奋我的脚进入了门。现在回想起来,我觉得我在甲骨文工作的时间比完成硕士学位更好。与此同时,我没有一个学位,我之前说过,它会给我一些工作保障,并记录我的技能。但现在我有了技术工程师的工作经验,有些人可能会认为这比学位更好。虽然从长远来看,有学位可能更有利。无论如何,我的长期目标是最终完成我的学位,也许能拿到 MBA。
我最近接受了一份工作邀请,在 OCI (Oracle 云基础设施)担任 DevOps 工程师,这让我进行了反思,并促使我写下了这篇文章。如果像我这样的人可以到这里,任何人都可以。我很感激我取得的进步,但是我还有很长的路要走。坦率地说,决定从事计算机科学、工程和技术领域的工作是对学习的终生承诺。科技生态系统是巨大的。技术总是在变化。就在我们说话的时候,一些新的范例正在形成。任何选择这种生活的人,一定是愿意并且有兴趣跟上的。
给以前的自己的建议
许多人问我,我会采取什么不同的做法,我的建议因人而异。但是我会尽我最大的努力告诉顽强的 20 多岁的我,我决定要改变道路。
我会参加基础编程(用 C++,而不是 Python)、数据结构和算法的课程,无论是在线还是面对面(在社区大学或其他地方提问)。然后我会读《破解编码面试》,做一堆 Leetcode 题(用 Python),做一些小项目,申请软件工程实习。最大的问题是需要多长时间才能得到工作机会?
我有一些朋友毕业于计算机科学专业,但他们仍然花了 1 年时间才找到一份技术工作。拥有计算机科学学位并不一定能说服雇主给你一份工作。你必须证明自己。参与项目会有所帮助。这意味着向 Github 发布显示一致提交的代码。你越能表现出对该领域的兴趣,招聘人员或招聘经理就越有信心在你身上投资。因为最终招聘过程相当于降低风险。你表现得越多,他们决定雇佣你的风险就越小。
参加研究生项目甚至训练营的好处是,你周围都是和你有相同目标的人。你可以了解他们如何追求这些目标,交换意见,并建立一个网络。我仍然和以前的同龄人保持联系。我后悔的一件事是没有利用已经在科技行业工作的朋友。我应该多接触一下,也许可以要求一次面试。不要骄傲。接受别人提供的帮助。当你取得一些成功时,把它传递下去。最终,它需要一个村庄。很少有人靠自己成功。你不太可能是例外。
最后的想法
技术很难。冒名顶替综合症猖獗。每个人都或多或少地感觉到称自己为工程师的负担。只要记住你不是一个人。通往成功的道路充满了失败和失望。有时我让失败的恐惧麻痹了我。我内心深处担心,如果面试失败,我可能会放弃。也许我会因为工程师的反馈而气馁,从而停止尝试。但是每次面试失败后,我对自己了解了很多。我感到很振奋,因为我觉得离得到一份工作更近了。每次面试后,我开始意识到什么是重要的,并集中精力。
不要放弃。
从物理到金融:我在工业界的第一年
这是我大约 4 年前发表的文章的修订版。我很幸运地经历了一次激动人心的旅程,所以你们中许多人可能有的一个问题的答案是否定的!我从未后悔离开学术界的决定。
许多研究生和博士后在工业界从事非研究性职业。这是其中一个人的故事。
2016 年 4 月 25 日下午 5 点,我离开了我在杜克大学的办公室,开始了新的不同的旅程,下周一上午 9 点。
在获得理论物理的两个硕士学位和一个博士学位,并在计算生物化学领域做了两年博士后,与各自领域备受尊敬的科学家合作,发表了 12 多篇同行评议论文并获得国际奖项后,寻求一个永久的学术职位似乎是合乎逻辑的下一步。
然而,在学习期间,我有幸参加了由美国光学学会和 SPIE 国际光学和光子学会等科学组织组织的专业发展活动,在那里我接触了行业领导者,了解了他们所面临的挑战。我探索得越多,就越发现自己对学术界之外的现实世界的问题和机遇着迷。
问题是,多年来,我在学术界一步一步地创造了成功的职业生涯,但我对外面的世界和适合理论物理学家的角色几乎一无所知;尽管如此,我相信没有多少职位可以利用我的量子力学或电动力学知识!
不幸的是,了解二阶光学非线性(在医学领域和电信领域有许多应用)或光裂酶修复光损伤的 DNA(使地球上的生命成为可能)并没有让许多招聘经理感到兴奋。事实上,我在这个过程中学到的第一课是
专注于我获得的技能,而不是我完成的项目。
技能,如解决问题,数值分析,编程,发表文章和演示。
几个月的阅读、学习、参加研讨会、打电话和咖啡聚会来探索不同的行业职位,将我引向了数据科学。我寻找新的职业道路是在这样一个时代,有史以来第一次,我们能够利用我们产生和储存的大量数据。这反过来又导致了对数学、统计和编程方面的熟练人才的大量需求,以便将原始数据转化为真知灼见。与此同时,任何行业都欣赏批判性思维、获得新技能的能力、有效的沟通和对新工作场所的快速适应,其中许多我以前都经历过。
对数据分析的需求正成为公司不可或缺的一部分,以至于数据科学候选人可以想象在任何领域的职业生涯,从医疗保健或航空领域的大型企业到金融或体育领域的初创公司。
就我而言,行业的选择并不是一个大问题。在我的学术生涯中,我意识到与合适的人一起工作比从事最令人兴奋的项目更有成就感。合适的人激励和挑战你,比起到达目的地,你更喜欢和他们一起旅行。正如保罗·格拉厄姆所说
重要的不是想法,而是拥有想法的人。好人可以修正坏想法,但好想法救不了坏人。
[更新:]将我过去的一些经验添加到这篇文章中,我再怎么强调和我们一起工作的人的重要性也不为过。简而言之,你最终将为你的经理和/或团队缺乏经验或远见付出代价。
我在当地的一次分析聚会上遇到了 Spreedly 的首席技术官。被他的热情和鼓励所打动,我递交了申请。后来,我会见了该公司的首席技术官和首席执行官,提交了工作样本,参加了现场面试,几周后,我疯狂地加入了他们,填补了他们的第一个数据科学职位。
在招聘过程中,我喜欢公司高管对我的角色的清晰看法,这在我做出决定时发挥了重要作用。我曾被其他公司面试过,这些公司不知道他们为什么需要一名数据科学家。
Spreedly 是一家成立 6 年的金融科技初创公司,通过存储和标记支付方法来促进在线支付,为商户简化 PCI-DSS(如果你接触金融数据,你必须遵守的规则)合规性,最重要的是,通过允许商户通过一个 API 与多个支付网关合作。因此,在 Spreedly,我可以访问交易、支付方式和支付网关的数据库。
作为创业公司的第一个数据科学雇员,与其他团队互动和学习的机会是无限的。我定期与工程师、业务开发、营销、客户成功和设计团队交流:这是一个了解其他领域、不同部门如何运作以及整体金融技术的独特机会。
以下是我一路走来学到的一些经验:
- 不要害怕问:这可能是我疯狂加入后得到的最好的建议。问得越多,学得越快!
- 机构知识:领域知识是数据科学家维恩图的一部分。然而,我想强调的是机构知识:如果不了解公司如何运作,存储什么类型的数据,每个功能到底代表什么,以及商业模式如何随着时间的推移而演变,你的数据分析可能会有缺陷。
- 耐心:这在数据基础设施可能还没有准备好的启动环境中变得更加重要。一个解决办法是考虑做几个项目,在一个项目上取得进展,同时等待合适的时机开始其他项目。
- 商务人士是你最好的朋友!它们可以帮助您确定要用数据瞄准的重要问题。利用他们的商业智能更有效地工作,并获得关于数据解释的宝贵见解。在发布结果或向客户展示之前,一定要和他们讨论你的发现。
- 重要与有趣:关注看似有趣的问题很容易,但它们与公司的使命或利益不一致,也不会让客户受益。因此,投资于真正重要的问题,而不是那些仅仅看起来有趣的问题,总是一个好主意。
- 与数据驱动的人一起工作:数据科学仍然是一个新领域。因此,无论你的工作多么出色,无论你的发现多么令人兴奋,如果你不和那些欣赏数据的力量并愿意用它来做决策的人一起工作,你的努力就会白费。
- 我提到过和一群很有幽默感的人一起工作真的很有趣吗?
各种组织已经研究了从学术界到工业界的路径。根据 T4 的简历,只有 18%完成这一转变的年轻研究人员会回到学术界。我相信我是那 82%中的一员。
更新(2020 年 12 月):在我发表这篇帖子大约 4 年后,我仍然收到许多研究生和博士后的邮件和消息,他们正在谨慎地评估自己从学术界到工业界的退出路线。以下是我给这些人和其他考虑改变或职业转变的人的信息:只要你真诚对待你所做的事情,评估每一步,从过去吸取教训并用于未来,并且不害怕道路上的起起落落,你就会没事!去做吧,你会发现一种巨大的快乐。一定要让我知道你的故事…
从 PyTorch 到 py torch Lightning——一个温和的介绍
这篇文章回答了如果你使用 PyTorch 为什么需要 Lightning 这个最常见的问题。
PyTorch 非常容易用来建立复杂的人工智能模型。但是一旦研究变得复杂,并且像多 GPU 训练、16 位精度和 TPU 训练这样的事情混合在一起,用户很可能会引入错误。
PyTorch 闪电正好解决了这个问题。Lightning 构建了 PyTorch 代码,因此它可以抽象训练的细节。这使得人工智能研究具有可扩展性,迭代速度快。
PyTorch 闪电是为了谁?
PyTorch Lightning 是在 NYU 和费尔做博士研究时创造的
PyTorch Lightning 是为从事人工智能研究的专业研究人员和博士生创造的。
闪电诞生于我在 NYU CILVR 和脸书 AI Research 的博士 AI 研究。因此,该框架被设计成具有极强的可扩展性,同时使得最先进的人工智能研究技术(如 TPU 训练)变得微不足道。
现在核心贡献者都在使用闪电推进人工智能的艺术状态,并继续添加新的酷功能。
然而,简单的界面让专业制作团队和新人能够接触到 Pytorch 和 PyTorch Lightning 社区开发的最新技术。
Lightning counts 拥有超过 320 名贡献者,由 11 名研究科学家,博士生和专业深度学习工程师组成的核心团队。
它是经过严格测试的
并且彻底记录了
概述
本教程将带你构建一个简单的 MNIST 分类器,并排显示 PyTorch 和 PyTorch Lightning 代码。虽然 Lightning 可以构建任何任意复杂的系统,但我们使用 MNIST 来说明如何将 PyTorch 代码重构为 PyTorch Lightning。
典型的人工智能研究项目
在一个研究项目中,我们通常希望确定以下关键组成部分:
- 模型
- 数据
- 损失
- 优化程序
模型
让我们设计一个 3 层全连接神经网络,它将 28x28 的图像作为输入,输出 10 个可能标签的概率分布。
首先,让我们在 PyTorch 中定义模型
该模型定义了计算图形,将 MNIST 图像作为输入,并将其转换为数字 0-9 的 10 个类别的概率分布。
三层网络(插图作者:威廉·法尔孔)
为了将这个模型转换成 PyTorch Lightning,我们简单地替换掉 nn。带 pl 的模块。照明模块
新的 PyTorch Lightning 类与 PyTorch 完全相同,除了 LightningModule 为研究代码提供了一个结构。
闪电为 PyTorch 代码提供了结构
看到了吗?两者的代码完全一样!
这意味着你可以像使用 PyTorch 模块一样使用 LightningModule 模块,比如预测模块
或者将其用作预训练模型
数据
对于本教程,我们使用 MNIST。
来源:维基百科
让我们生成 MNIST 的三个部分,培训、验证和测试部分。
同样,PyTorch 和 Lightning 中的代码是一样的。
数据集被添加到 Dataloader 中,data loader 处理数据集的加载、混排和批处理。
简而言之,数据准备有 4 个步骤:
- 下载图像
- 图像转换(这些非常主观)。
- 生成训练、验证和测试数据集拆分。
- 包装数据加载器中拆分的每个数据集
同样,除了我们将 PyTorch 代码组织成 4 个函数之外,代码完全相同:
准备 _ 数据
这个函数处理下载和任何数据处理。这个函数确保当您使用多个 GPU 时,您不会下载多个数据集或对数据应用双重操作。
这是因为每个 GPU 将执行相同的 PyTorch,从而导致重复。Lightning 中的所有代码确保关键部分仅从一个 GPU 中调用。
train_dataloader,val_dataloader,test_dataloader
其中每一个都负责返回适当的数据分割。Lightning 以这种方式构建它,以便非常清楚数据是如何被操纵的。如果你读过用 PyTorch 写的随机 github 代码,你几乎不可能看到他们是如何处理数据的。
Lightning 甚至允许多个数据加载器进行测试或验证。
这段代码被组织在我们称之为数据模块的地方。尽管这是 100%可选的,并且 lightning 可以直接使用数据加载器,但是一个数据模块使您的数据可以重用并且易于共享。
优化器
现在我们选择如何进行优化。我们将使用 Adam 代替 SGD,因为在大多数 DL 研究中,它是一个很好的缺省值。
同样,这是完全相同的,除了它被组织到配置优化器功能中。
Lightning 是极其可扩展的。例如,如果你想使用多个优化器(比如:GAN),你可以在这里同时返回两个。
您还会注意到,在 Lightning 中,我们传入了self . parameters()而不是模型,因为 LightningModule 是模型。
损失
对于 n 路分类,我们想要计算交叉熵损失。交叉熵与负对数似然度(log_softmax)相同,我们将使用负对数似然度。
再次…代码完全相同!
训练和验证循环
我们收集了训练所需的所有关键材料:
- 模型(三层神经网络)
- 数据集(MNIST)
- 优化器
- 损失
现在,我们实施一套完整的训练程序,包括以下内容:
- 迭代多个历元(一个历元是对数据集 D 的一次完整遍历)
在数学方面
用代码
- 每个历元以称为批次 b 的小块迭代数据集
在数学方面
用代码
- 我们向前传球
在数学方面
代码
- 计算损失
在数学方面
用代码
- 执行反向传递以计算每个权重的所有梯度
在数学方面
用代码
- 将渐变应用于每个权重
在数学方面
用代码
PyTorch 和 Lightning 中的伪代码都是这样的
这就是闪电与众不同的地方。在 PyTorch 中,你自己编写 for 循环,这意味着你必须记住以正确的顺序调用正确的东西——这给 bug 留下了很大的空间。
即使你的模型很简单,但一旦你开始做更高级的事情,如使用多个 GPU、渐变裁剪、提前停止、检查点、TPU 训练、16 位精度等,它就不再简单了。你的代码复杂性将迅速爆炸。
即使你的模型很简单,一旦你开始做更高级的事情,它就不再简单了
下面是 PyTorch 和 Lightning 的验证和训练循环
这就是闪电的妙处。它抽象了样板文件(不在盒子里的东西),但是没有改变其他任何东西。这意味着你仍然在编写 PyTorch,除非你的代码已经被很好地结构化了。****
这增加了可读性,有助于再现性!
闪电教练
培训师就是我们如何抽象样板代码。
同样,这也是可能的,因为您所要做的就是将 PyTorch 代码组织成一个 lightning 模块
PyTorch 的完整训练循环
用 PyTorch 编写的完整 MNIST 示例如下:
闪电中的完整训练循环
lightning 版本完全相同,除了:
- 核心成分已经由照明模块组织起来
- 培训师已经提取了培训/验证循环代码
这个版本不使用数据模块,而是保持自由定义的数据加载器。
这是相同的代码,但是数据被分组到数据模块下,变得更加可重用。
突出
让我们指出几个要点
- 如果没有 Lightning,PyTorch 代码可以位于任意部分。有了闪电,这是结构化的。
- 这两者的代码完全相同,只是它是用 Lightning 构建的。(值得说两遍 lol)。
- 随着项目变得越来越复杂,你的代码不会,因为 Lightning 抽象出了大部分内容。
- 您保留了 PyTorch 的灵活性,因为您可以完全控制培训中的关键点。例如,您可以有一个任意复杂的 training_step,比如 seq2seq
5.在《闪电》中,你得到了一堆赠品,比如一个恶心的进度条
你还得到了一份漂亮的重量总结
tensorboard 日志(没错!你什么都不用做就能得到这个)
免费检查点和提前停止。
全部免费!
附加功能
但闪电最出名的是开箱即用的好东西,如 TPU 培训等…
在 Lightning 中,您可以在 CPU、GPU、多个 GPU 或 TPU 上训练您的模型,而无需更改 PyTorch 代码的任何一行。
也可以做 16 位精度训练
使用 5 个其他替代物对张量板进行测井
与海王星一起伐木。AI(鸣谢:Neptune.ai)
用 Comet.ml 记录日志
我们甚至有一个内置的分析器,可以告诉你训练中的瓶颈在哪里。
将此标志设置为 on 会产生以下输出
或者更高级的输出
我们还可以同时在多个 GPU上训练,而不需要你做任何工作(你仍然需要提交一个 SLURM 作业)
你可以在文档中读到它支持的大约 40 个其他特性。
带挂钩的可扩展性
你可能想知道 Lightning 是如何为你做这些事情的,而且还能让你完全控制一切?
与 keras 或其他高级框架不同,lightning 不隐藏任何必要的细节。但是如果你确实发现需要自己修改训练的每一个方面,那么你有两个主要的选择。
首先是通过覆盖钩子的可扩展性。下面是一个不完整的列表:
- …
- 您需要配置的任何东西
这些覆盖发生在照明模块中
回调的可扩展性
回调是您希望在培训的各个部分执行的一段代码。在 Lightning 中,回调是为非必要的代码保留的,比如日志或者与研究代码无关的东西。这使得研究代码非常干净和有条理。
假设您想在培训的各个阶段打印或保存一些东西。这是回调的样子
PyTorch 闪电回拨
现在你把它传递给训练者,这个代码会在任意时间被调用
这种范式将您的研究代码组织成三个不同的类别
- 研究代码(LightningModule)(这就是科学)。
- 工程代码(培训师)
- 与研究无关的代码(回调)
如何开始
希望这份指南能准确地告诉你如何开始。最简单的开始方式是用运行 colab 笔记本,这里是 MNIST 的例子。
或者安装闪电
或者查看 Github 页面。
从报告到洞察:提高分析成熟度
freepik 创作的背景照片—www.freepik.com
今天的公司面临着巨大的挑战:如何从信息中提取价值,并在快速的 数据驱动的 环境中运营。长期以来,良好的洞察力在商业中一直扮演着关键角色,高管们对此心知肚明。但是,这从来没有成为全公司沮丧的根源。简单来说,想成为 数据驱动 和搞定是有区别的。原因是数据和分析之间存在巨大的基础设施和技能差距。
一个组织的业务不是写报告,而是基于洞察力采取行动
当今的分析解决方案通常在简单和假设的场景中进行测试和呈现,无法反映日常交易和真实组织的细微差别。它错误地促使企业领导相信将数据集插入工具很容易,而且会产生立竿见影的业务影响。事实并非如此,在任何可见的结果之前,数据都需要大量的提炼。
成功实施数据驱动的文化有三个关键要素:
- 领导者需要向数据和分析的新观点飞跃。摆脱将孤立的数据、业务应用程序和分析应用程序基于数据仓库和业务智能系统的旧思维,主要用于企业报告;
- 团队需要开始将数据作为决策和计划的原材料;
- 公司需要接受新的方法和工具,这将引导他们走向分析的成熟。
走向有洞察力的决策
其中一个工具是连续分析。由 Gartner 推出,它代表了组织积极处理数据的不同阶段。这是一个非常有用的工具,有助于组织了解他们当前的情况,并为未来的发展做好规划。
基于我们在各种行业帮助众多公司的经验,我们在 Math Marketing 展示了如下分析连续体:
连续分析(通过数学营销)
描述性分析:允许公司确定以前期间发生的事情。它有助于管理人员衡量绩效和关键指标,并经常转化为报告和仪表板。它关注过去的绩效,并在检测到偏差时触发反应。
不幸的是,现在有一种趋势,要么报告法规和合规性要求的最低限度(如季度财务报告和税务报告),要么生成大量报告,这些报告需要大量工作,很少及时相关,并且容易不作为。尽管如此,一个好的描述性分析是一个宝贵的基础。
解释性分析:通过关注为什么,解释性分析旨在理解描述性分析报告的结果背后的原因。它经常需要研究变量之间的相关性和回归。然而,它仍然只能提供一个向后的视野。它是关于理解关系以及为什么某些事情会发生而其他事情不会发生。好的解释模型可能会变成好的预测模型,但是开始的目标是不同的。
连续体的每个阶段都意味着技能和难度的显著增加。但是,从描述性分析到解释性分析的转变最为引人注目。法规、下架率和商业头脑可以产生可接受的报告,即使是无关紧要的报告。但是解释需要最低限度的统计知识。公司的墓地充满了仓促的结论和轶事般的关联。
探索性分析:使组织能够探索事件背后的原因和检测到的解释。它意味着拓宽对模式、趋势、异常值、意外结果的观察,并利用定量和可视化方法的混合来了解故事数据想要讲述的内容。 因果关系 比相关性更进了一步。它说一个变量的值的任何变化都会引起另一个变量的值的变化。了解原因是预测的敲门砖。
预测分析:是预测可能发生的事情,估计影响和预测未来。它允许组织创建和探索不同的场景并提前计划。它需要对环境有深入的了解,并对数据有很强的控制能力。虽然工具集在这里发挥了作用,但主要部分是关于高级统计学/计量经济学和商业知识。
规定性分析:给定已经收集的深层知识,它为组织提供了一条通向特定目标的道路。它基本上回答了“应该做些什么来实现结果 X”这个问题。在这个阶段,人类的干预可能是最少的,并且有可能将决策委托给机器来实现业务目标。(例如:对冲基金交易算法)
在一家金融服务公司的营销部门的上下文中,描述性分析提供了关于上个月特定活动参与情况的信息。解释性分析研究了参与度和营销支出之间的关系。探索性分析探索受众群以发现可能的趋势。预测分析总结未来的营销活动参与情况,并告知管理层实现预期参与目标的最佳营销活动。
你的数据有多深
分析深度(数学营销)
经常被忽视的一个方面是不同数据源所扮演的角色。即使没有提高分析的成熟度,也可以从扩展的数据源中产生价值。在某些情况下,具有大量数据源的描述性分析与基于内部信息的预测性分析一样有用。我们称之为分析深度,并认为属于以下类别之一:
内部结构化数据:公司在正常交易过程中收集的信息,如销售额和金额、客户联系信息或产品日志。它们是有意收集信息过程的结果。对于公司来说,这是最简单的,有时也是唯一的信息来源。
外部结构化数据:来自外部数据库的信息,可以公开获得,也可以来自数据提供商。它包括政府统计数据、客户报告或市场调查等。信息通常以表格形式或任何其他结构化形式提供,由组织来寻找与内部数据的相关性。它增加了公司可用的数据量。
内部非结构化数据:并非所有内部信息都可供消费。商业知识通常通过电子邮件、聊天室、论坛或维基等非正式工具传播。有些甚至可能在合同或产品手册等任何数字形式上都找不到。合并非结构化数据源是一项复杂工作。增加公司可用数据的种类
外部非结构化数据:包括来自社交媒体、社区博客和公司与客户或利益相关者互动的其他在线论坛的信息。考虑到如今创建的数据的共享量和速度,将其纳入决策流程是一项挑战。
分析深度有助于组织理解的是,通往分析成熟度的道路更多地依赖于流程评估、提出正确的问题以及使数据源多样化,而不是投资于新工具。
洞察力需要新的技能
组织在分析上花费如此多的时间和精力的核心原因不应该只是为了获得最新的报告。虽然知道刚刚发生了什么是重要和有用的,但它只能提供事情执行得如何的细节,并在粘贴中给出财务表现的概述。然而,它常常不能提供任何关于明天应该做什么的洞察力。
许多公司在描述性分析和工具上花费了太多的时间和金钱。不幸的是,让管理层感到沮丧的是,在充分发挥其潜力之前,这些工具需要的比他们预期的更多。技能仍然是企业面临的最大挑战。这些额外的能力通常需要具备额外的定量、内容和分析技能的新角色,可能是统计分析师或数据科学家。
大多数组织未能进行文化或业务模式调整来真正利用信息。提出如何使用信息或分析的想法是很棒的。但是,如果组织没有准备好实际行动,那么它可能真的会变成一个时间之水。许多见解,但实际上并没有将它们与业务联系起来
最终想法
组织每天在不同的层面做出数百个甚至数千个决策,这些决策具有不同程度的影响、复杂性、频率和用途。唯一不变的是变化,而分析代表了适应变化的一种方式。识别模式、预测结果并积极应对将是未来竞争的基础。
数学营销已经帮助各行各业的公司实施数据驱动流程。通过将统计能力、商业知识和高级工具相结合,我们帮助客户回答问题。一些最大的品牌与我们分享了他们的数据挑战,并相信我们的数据能够为日常运营和战略决策提供真知灼见。
如果您想了解我们的项目和方法,请通过电子邮件联系我们,或者直接通过 Linkedin 联系我们的任何团队经理。我们随时准备与您分享我们的见解,倾听您的经验。
从研究到生产:扩展最先进的机器学习系统
理解大数据
我们如何实施生产就绪的问答应用程序,并将响应时间减少了两个数量级以上。
(图片由作者提供)
想象一下,你已经创建了一个机器学习系统,它在某些任务上超越了最先进的性能。您已经针对一系列目标进行了优化,如分类准确性、F1 分数或 AUC。现在您想从它创建一个 web 服务。其他目标,如向用户交付结果的时间或成本,变得更加重要。
这两组目标通常是冲突的。更精确的模型通常很大,评估起来计算量很大。为了在生产中使用这种模型,通常会引入各种优化,如降低模型的精度和复杂性。虽然有利于降低成本和能耗,但不幸的是,这会损害精度。
显然,如果准确性不重要,推断时间可以大大降低。同样,可以以高成本产生非常准确的响应。最终选择哪种解决方案介于这两个极端之间。选择最佳解决方案的一个有用的技巧是从准确性和成本方面列举它们。不受他人支配的解决方案集被称为帕累托边界,它确定了准确性和成本之间的最佳权衡。
在之前的一篇博文中,我们介绍了一个服务系统,它重现了开放领域问答中最先进的准确性。我们基于脸书的密集段落检索(DPR) ,这是一个基于 Python 的研究系统。我们使用 Vespa.ai 构建了服务系统,这是一个开源的大数据服务引擎,由于其对快速相似性搜索和搜索和排名中的机器学习模型的原生支持,它非常适合这样的任务。结果是 web 服务接受一个问题并返回一个精确的答案。
虽然该系统重现了 DPR 的结果,因此具有出色的准确性指标,但从端到端延迟来看,响应时间最初很差。这篇文章将描述我们为使生产系统的性能达到可接受的水平所做的各种优化。
Vespa.ai 是为生产而构建的,因此有相当多的服务时间优化选项。我们将特别使用 Vespa.ai 的能力,通过每个查询使用多个工作线程来检索和排列文档,以达到显著的效果。然而,该应用程序的主要成本是评估两个 BERT 模型。我们想要回答的一个问题是,具有完全精度的较小模型是否优于具有量化参数的较大模型。我们将开发帕累托边界来评估各种优化的优点。
我们将从服务系统的概述开始,并确定系统的哪些部分最初推动了成本。关于实现的更多细节,我们可以参考本系列中之前的博文。
问题回答
该系统的任务是对以自然语言给出的问题产生文本回答。主要包括三个阶段:
- 编码器生成问题的表示向量。
- 检索器在 2100 万个索引段落中执行最近邻搜索。
- 读者找到最相关的段落,并摘录最后的答案。
下图说明了这一过程:
问答的编码器、检索器和阅读器(图片由作者提供)
编码器首先从问题中创建一个标记化的表示。这个令牌 id 向量作为输入被发送到编码器 BERT 模型。这最初是一个标准的基于 BERT 的模型,有 12 层,隐藏层大小为 768。最终的隐藏层状态被用作问题的表示向量。如上图所示,这主要发生在 Vespa 的无状态容器层。令牌和向量表示被向下传递(“分散”)到所有内容节点以执行查询。
在内容节点上,段落已经用它们自己的表示向量进行了索引。这些向量被构造成使得问题向量和段落向量之间的欧几里德距离指示相似性。这在 HNSW 算法中用于执行近似最近邻搜索。具有最小欧几里德距离的 10 个通道被发送到下一阶段。
同样在每个内容节点上执行的第二阶段排序阶段评估读者 BERT 模型。像编码器模型一样,这最初是具有 12 层和隐藏长度 768 的基于 BERT 的模型。来自查询和每个段落的表征被组合以形成模型输入。读者模型产生三个概率分数:相关性分数和答案在文章标记序列中的开始和结束索引。具有最佳相关性分数的段落被选为获胜者,并且其令牌表示被返回给无状态层。在这里,自定义代码使用起始和结束索引提取最佳跨度,对其进行去标记化,并返回结果文本答案。
现在,那是很多工作。以下是对问题“谁赢得了 2015 年环法自行车赛”的回答示例,其中检索了最相关的段落,并提取了正确答案“克里斯·弗鲁姆”:
来自 Vespa.ai 的回应(图片由作者提供)
为了测量性能,我们在一台机器上部署了该系统,该机器配有英特尔至强金色 6240 处理器,200 GB RAM 和固态硬盘。我们评估了超过 3610 个问题的系统,并记录了平均延迟和精确匹配分数。最初,系统获得 40.64 的精确匹配分数。在考虑优化性能之前,上述三个阶段花费的时间为:
- 编码模式:300 毫秒
- 近似最近邻搜索:13 毫秒
- 前 10 名读者排名:9085 毫秒
显然,9.4 秒的总端到端延迟对于服务来说是不可接受的。接下来,我们将把它降低到 100 毫秒以下
多线程检索排序
最初,最昂贵的步骤是阅读器阶段。默认情况下,Vespa 在一个线程上为一个查询进行所有排序。当计算成本较低时,这是最大化吞吐量的合理缺省值。在这种情况下,这意味着读者模型是针对前 10 篇文章中的每一篇依次进行评估的。这导致了很高的查询延迟。
然而,Vespa 可以选择每次搜索使用多线程。设置此值会将平均端到端延迟降低到 2.04 秒,提高了 4 倍以上,而不会影响精确的匹配分数。
值得澄清的是,阅读器模型并不是批量评估的。这是由于 Vespa 的排名框架,其中排名表达式对单个段落和查询对进行评分。然而,对于 BERT 模型,这并不重要,因为评估时间与批量成线性关系。一个原因是具有 3 维或更多维张量的张量乘法,因为这些乘法无论如何都要在几个硬件优化的矩阵-矩阵乘法上迭代。
一般来说,Vespa 有许多选项来调整性能,例如轻松地将工作负载分布在附加的内容节点上。虽然我们不在这里探讨,但请参阅 Vespa 服务扩展指南了解更多信息。
令牌序列长度
BERT 模型的定义和最显著的特征之一是完全注意层。虽然这是语言理解方面的一个重大突破,但它对评估时间有一个不幸的 O(n)影响。
因此,输入到 BERT 模型的标记序列的长度显著影响推理时间。最初,编码器 BERT 模型的输入长度为 128。通过将其减少到 30,我们将推断时间从 300 毫秒减少到 125 毫秒,而不损失准确性。
同样,阅读器模型最初的输入长度为 380。通过将此值减少到 128,我们将平均延迟从 1.9 秒减少到 741 毫秒,这是一个显著的减少。然而,我们的准确率确实下降了,因为一些问题和段落的组合会导致令牌序列超过 128。这将精确的匹配分数降低到 39.61。
编码器和阅读器型号都支持动态长度输入,但 Vespa 目前仅支持固定长度输入。不过,这个问题将在不久的将来得到解决。总之,缩短编码器和阅读器模型的令牌输入长度会导致 3 倍的加速。
模型量化
神经网络模型通常使用单精度浮点数来训练。然而,对于生产中的推理,已经表明这种精度水平并不总是必要的。可以将参数转换成更小的整数表示,而不会显著降低精度。将参数从 32 位浮点转换为 8 位整数会将模型大小减少 75%。更重要的是,整数运算执行起来要快得多。支持 AVX512 矢量神经网络指令(VNNI)的现代 CPU 旨在加速 INT8 推理性能。此外,评估这种量化模型需要更少的功率。
量化阅读器模型使其大小从 435Mb 减少到 109Mb。系统的延迟平均下降到 374 毫秒。这对准确性有一点不幸的影响,精确匹配下降到 37.98。类似地,量化编码器模型导致类似的大小减少,并且系统评估时间下降到 284 毫秒,精确匹配分数下降到 37.87。
总之,阅读器和编码器模型的模型量化导致另一个 3 倍的加速。
微缩模型
到目前为止,编码器和读取器模型都是基于预训练的 BERT-base 模型,包含 12 层,隐藏维度大小为 768,因此大约有 1.1 亿个参数。这些都是相当大的模型,尤其是在时间有限的环境中使用时。然而,在论文“博览群书的学生学得更好:论预训练紧凑模型的重要性”中,作者表明较小的模型确实可以工作得很好。本文引用的“微缩”模型可以在变形金刚模型库中找到。
我们训练了新的读者模型,如 DPR 知识库中所述,基于以下预训练的 BERT 微型模型:
- 中号(8 层,512 隐藏尺寸)
- 小(4 层,512 隐藏尺寸)
- 迷你(4 层,256 隐藏尺寸)
- 微小(2 层,128 隐藏尺寸)
我们也对每个模型进行量化。下表给出了具有精确匹配分数和平均延迟的所有 20 个模型(5 个阅读器模型,有和没有量化,有和没有量化编码器模型)的完整概述:
各种模型类型的精确匹配分数与延迟
绘制这些结果:
精确匹配与延迟(图片由作者提供)
在上图中,红线代表帕累托前沿。沿着这条战线的点在上表中也用粗体标出。回想一下,这些点代表了精确匹配和延迟之间的最佳权衡,这意味着对于这条战线上的每个点,没有其他点在精确匹配和延迟方面更胜一筹。
这里可以看到的一个有趣的结果是,一般来说,量化模型以更高的精度支配其他模型。例如,中等量化模型比具有更高精度的小模型具有更好的精确匹配和延迟数。因此,在这种情况下,尽管量化会降低精度,但选择已量化的大模型比选择未量化的小模型更有利。
帕累托前沿将客观上的最佳解决方案可视化,而我们的主观偏好将引导我们找到最佳解决方案。以上测试是在一台英特尔至强金牌 6240 机器上运行的。更强大的处理器会降低整体延迟数字,但不会改变整体形状。选择的确切解决方案基于我们的延迟和硬件预算。例如,拥有大量资源并能够充分扩展的组织可以证明在这方面向右移动是正确的。规模经济可以降低硬件投资和能源消耗的成本,使服务变得可行。这样的解决方案对其他人来说可能遥不可及。
把这些放在一起
请参考配套示例应用程序,了解更多关于如何自己运行该应用程序的详细信息和说明。
结论
总的来说,我们将一个性能不佳的研究应用提升到了适合生产的水平。从完整模型的 9.4 秒到微型模型的 70 毫秒,这代表了 130 倍的加速。不幸的是,为了达到这些水平,我们也注意到精确匹配的显著下降。最佳选择介于这两个极端之间。如果我们要将该应用程序投入生产,我们可以使用更强大的硬件来将延迟降低到 100 毫秒以下,并具有可接受的精确匹配指标。
有相当多的优化我们没有尝试,超出了本文的范围。例如, FastFormers:用于自然语言理解的高效转换器模型包括一些额外的优化,用于更高效的推理,如模型修剪。此外,新一代的 BERT 模型试图缓解与完全注意机制相关的性能问题。例如,大鸟架构看起来很有前途。
我们省略了训练微型编码器模型。从延迟的角度来看,在问题编码中使用微型 BERT 模型具有额外的好处,因为问题和段落的向量表示更短。因此,近似最近邻搜索将变得更加有效。然而,这可能会导致准确性的显著下降,并且花费在人工神经网络上的时间无论如何都不是延迟的重要驱动因素。
添加额外的内容节点将允许分配工作负载。这可能不会减少延迟,但会增加我们可以用阅读器模型评估的通道数。我们将在下一篇博客文章中回到这个话题。
利用深度半监督学习从研究到生产
理解大数据
分享经验,将研究带入现实世界。
我从 2019 年 6 月开始的一叠半监督学习论文,上面是我在该领域阅读的第一篇论文:mix match——我不建议为了很好地回忆你所阅读的内容而在所有东西下面划线。(图片作者)
T 今天大多数深度学习算法的成功很大程度上是几十年研究的结果,GPU 和数据的可用性越来越大。但并不是任何类型的数据——那种丰富、干净、标记为 的。
ImageNet、CIFAR10、SVHN 等数据集让研究人员和从业者在计算机视觉任务上取得了显著进展,对我们自己的实验非常有用。然而,对于许多寻求从这一进步中受益的应用程序(如医学)来说,最大的困难恰恰是数据必须是丰富的、干净的和有标签的。
半监督学习(SSL),结合了监督和非监督学习的子领域,在过去几年中,在深度学习研究社区中变得越来越受欢迎。很有可能,至少在短期内,SSL 方法可以成为标签繁重的监督学习和数据高效建模的未来之间的桥梁。
在本帖中,我们将讨论何时应该考虑在您的生产环境中使用 SSL 方法,以及我们在 Uizard 使用它们来改进我们的对象检测模型时学到的经验。当然,我们会尽最大努力分享大图,但对我们自己保留一些魔法的细节。
我们希望通过展示 SSL 如何以及何时对我们起作用以及不起作用,并通过分享我们从研究到生产的旅程中所学到的技巧,我们可以激励您在工作中抓住 SSL 的机会,并释放您未标记数据的潜力。
简而言之,这里有一些我们强调的教训:
- 简单才是王道。SSL 中从研究转化为生产的最成功的方法是那些最容易复制的方法。具体来说,我们将阐述“与吵闹的学生一起自我训练”(谢等人,2019 )是如何为我们工作的。
- 使用启发式算法的伪标签精化可能非常有效。伪标签是 SSL 方法的一个受欢迎的组成部分,我们发现使用简单的试探法来改进未标签数据中的伪标签可以提高不同大小的未标签数据集的性能。
- 半监督图像分类的进展很难转化为目标检测。我们跟踪的 SSL 的大部分进展是测量图像分类的性能,并承诺在对象检测方面有类似的改进,但我们发现在实践中很难适当地调整它们。因此,在半监督目标检测领域需要更多的工作和研究。
什么是半监督学习(SSL)?
半监督学习与监督学习的区别的简单说明。(图片作者)
顾名思义,半监督学习(SSL)是指介于监督和非监督学习之间的一类算法,旨在使用标记和未标记数据来建模分布。
SSL 的目标通常是比单独使用带标签的数据做得更好,能够模拟目标分布,就好像我们也可以访问所有未标记数据的标签一样。
这种算法并不是一个新的想法,尽管在过去的 18 个月中,深度半监督学习已经有了相当多的兴趣、进展和应用,我们将在下面讨论。
我什么时候适合在生产中使用 SSL?
如果您正在考虑使用 SSL 来解决某个问题,那一定是因为您的数据集很大,并且有许多未标记的数据点。你的数据集的一部分可能会被标记,当然标记的数据越多越好——但是希望至少有和标记的数据一样多的未标记的数据,或者更多的数量级。
如果您可用的大部分数据都是带标签的,或者未带标签的数据集来自与带标签的数据集显著不同的分布,那么 SSL 现在可能不太适合您的应用程序。对于后一种情况,请查看域自适应。
考虑到这一点,有两个主要的设置证明了在现实应用程序中研究 SSL 方法的合理性:
- 您正在处理一个高价值问题,对于该问题,仅标记的数据不足以产生足够的性能,但是多几倍(10–100 倍以上)未标记的数据是可用的和/或容易获得的。
在这种情况下,我们强调值得生产的性能的可能性较低——但是在给定一个数量级或更多的未标记数据以及足够的激励、时间和资源的情况下,为几乎没有标记数据的任务尝试 SSL 可能是有意义的。
- 你正在解决一个问题,对于这个问题,有标记的数据本身就足以产生足够的性能,但是你有一个未标记的样本集合,你想用 T2 进一步提高性能。
在这种情况下,您可能已经有了一个运行良好或几乎达到要求的模型,但是您希望继续提高性能,而不需要花费太多精力来标记新数据。因此,SSL 可以被视为改进建模的许多其他工具之一,如获得更清晰的标记数据集、训练更大的模型等。对于差错率相对降低 5–10%以上的性能关键型应用程序,以及可获得未标记数据的应用程序,SSL 尤其适用。
值得注意的是,特别是因为 Uizard 是一家拥有快速增长的 beta 用户群的初创公司, 在持续/主动学习环境中使用的 SSL 也有可能创造出您在下面看到的循环。 未标记的数据用于在我们的平台中训练和部署改进的模型,这反过来驱动额外的用户,从而产生额外的未标记数据来从头开始该过程。
半监督学习(SSL)模型在生产环境中的生命周期,其中不断增长的用户群可以创建一个正反馈循环。(图片由作者提供)
研究的方法
以下是我们在图像分类和对象检测方面尝试的一些方法,但 SSL 同样可以应用于其他领域,如 NLP ( Liang 等人,2005 )和音频/语音处理( Tur 等人,2005 )。
图像分类
- MixMatch(贝特洛等人,2019)[ pdf ][ 代码
- 无监督数据增强(UDA)(谢等,2019)[pdf][code]
- FixMatch (Sohn 等人,2020-A)[ pdf ][ 代码 ]
物体检测
任务无关
虽然我们不会详细讨论上面的每一种方法,但是下面关于半监督学习的博客非常棒,涵盖了上面列出的许多技术。
- 计算机视觉中的半监督学习,作者 Amit Chaudhary
- 深度半监督学习,作者亚辛·奥阿利
- Sebastian Ruder 的半监督学习的代理标签方法概述
第一课:简单是王道。
在 2019 年 6 月我们对半监督学习方法的最初文献综述中,读到 MixMatch 和 UDA 在 SSL 方面取得了显著进展,特别是在标签数据极其有限的情况下,这令人着迷。我们能够相对轻松地在 CIFAR10 和 SVHN 上重现他们的结果,这让我们对他们将这些性能提升转化到我们的数据集的能力充满信心。
然而,我们这样做的体验并不理想,主要是因为——惊喜!—超参数调谐。论文中使用的数据集的许多开箱即用的超参数对我们数据集的性能变化更敏感。我们还注意到,我们的标记数据集在分布上与未标记数据集略有不同,这个问题通常会降低 SSL 技术的性能,并在 Oliver et al .,2018 中提出,作为 SSL 需要克服的挑战,以用于“现实”设置(请参见本博客末尾的附录 A,了解我们对此的研究工作)。截至 2019 年 9 月,现有的最先进的 SSL 技术似乎不够简单或灵活,不足以让我们继续前进。
快进到 2020 年 6 月,已经发布了两个关于 SSL 的新作品,主要关注简单的实现——fix match 和嘈杂学生的自我训练。
FixMatch 中如何使用未标记图像的示意图。(图片来自 Sohn 等人,2020 )
FixMatch 是其前身 MixMatch 的一个更简单但更有效的版本,我们成功地在论文中提出的数据集上复制了他们的结果。这一次,我们能够在我们自己的图像分类数据集上看到良好的结果,性能对超参数的选择不太敏感,并且可调整的超参数更少。
有吵闹学生的自我训练图。(图片来自谢等人 2019 )
嘈杂的学生训练由一个迭代过程组成,在这个过程中,我们训练一个教师模型(可以访问标记数据的模型),使用这个模型来推断未标记数据的输出,然后根据标记数据和伪标记数据重新训练一个新模型,称为学生。然后,我们可以重复这个循环,称为自训练,通过使用这个学生模型在未标记集合上推断新的伪标签。在 Xie et al .,2019 中,他们展示了上述框架如何在使用 300M 未标记图像时提高 ImageNet 分类精度,并强调了各种类型噪声的添加(增强、丢失等。)作为几项消融研究成功的关键。
值得注意的是,嘈杂的学生方法是一个任务无关的框架,可以广泛应用于:图像分类,对象检测,情感分析等。 对我们来说,在我们尝试的所有技术中,嘈杂的学生方法是最成功的对象检测方法。 我们在第 3 课中讨论了为什么 FixMatch 的对象检测对应物(STAC)和其他方法可能对我们不起作用,但是我们坚信吵闹学生的简单性和灵活性与其他方法相比是我们看到生产模型改进的原因。
为什么很简单?现有训练超参数和设置几乎没有变化。以下是完整管道所需的内容:
- 把我们现有的生产模式当成教师模式。
- 与老师一起编写几个脚本来推断和提炼无标签数据上的伪标签(有关伪标签提炼的更多信息,请参见第 2 课)。
- 用添加的噪声(增强等)训练“学生”模型。).
- 按照嘈杂的学生图中所示的框架重复该过程。
其他注意事项和想法:
- 当可用的未标记数据少于标记数据时,我们惊讶地看到用嘈杂学生方法实现的一些模型有所改进。第二课将详细介绍这一点。不过一般来说,如谢等,2019 所述,未标记的数据越多越好。
- 我们看到,使用普通的自我训练,我们的学生模型的性能有所改善,而没有实现谢等人,2019 的一些部分,如辍学、随机深度或软伪标签。这些部分一旦被添加,可能会像在 ImageNet 上那样进一步提升我们的性能。
- 使用更大的学生模型的结果是混合的——对我们来说,这意味着在我们的检测模型中从 ResNet-50 到 ResNet-101 主干。
总的来说,当涉及到图像分类或物体检测时,简单是王道。与 MixMatch 相比,FixMatch 明显更容易适应我们的自定义图像分类数据集,而 Noisy Student 只需要对我们现有的对象检测管道进行很小的更改,就可以看到性能的提高。
第二课:启发式伪标签提炼非常有效。
伪标记,也称为自我训练,是 SSL 中的一种范式,早在 20 世纪 60 年代和 70 年代就出现了,并且由于其简单性而一直存在( Scudder,1965;麦克拉克伦,1975 。深度 SSL 伪标记的引入( Lee,2013 )展示了用标记数据训练模型,使用该模型推断未标记数据上的标签(现在称为伪标签),然后用标记和伪标记数据进行重新训练的想法是多么简单而强大。今天,许多 SSL 技术使用某种形式的伪标记,包括 FixMatch 和嘈杂学生的自我训练。
然而,这些伪标签经常会有噪声,并且需要某种形式的改进才能被使用。在 FixMatch 和 Noisy Student 中,这意味着将阈值(比如 0.7 或 0.9)应用于推断的伪标签,并且仅采用 softmax 置信度得分高于该阈值的那些预测。我们发现这是获得高质量伪标签的一种有用的启发式方法,但是还发现对伪标签应用其他领域特定的启发式方法在嘈杂的学生设置中有很大帮助。
我们在谈论什么样的启发法?例如,假设您正在为一家房地产公司构建一个对象检测分类器,该公司需要为家中的不同对象添加边框注释。您注意到(教师)模型的预测通常是好的,但是,分类器倾向于在未标记的集合上产生几个不正确的、高置信度的预测,即一些梳妆台实际上是厨房岛。
我们可以在嘈杂的学生训练中使用特定领域的启发式算法来改进伪标签,以提高半监督性能。(图片由作者提供)
这里有一些启发性的例子,我们可以从中选择来完善这个标签:
- 如果在同一个图像中预测了岛和床,请将岛标签转换为梳妆台。
- 如果梳妆台和岛预测在同一图像中,请将岛标签转换为梳妆台。
- 如果在同一个图像中预测了岛、床和梳妆台,请将岛标签转换为梳妆台。
以上哪种启发最有意义?这将取决于您的数据集和最常见的错误类型。如果模型在检测床方面做得很好,也许像第一个或第三个例子这样的启发式方法可能会有用,因为我们不希望床和厨房岛出现在同一张图像中。
特别是在对象检测中,当对象的位置和大小遵循您的应用领域中的特定规则时,您可以定义类似这样的试探法来优化嘈杂的伪标签,并帮助您的学生模型学习教师模型无法学习的更好的表示。
我们能够在我们自己的有噪声的学生模型中实现更好的性能,使用启发式伪标签细化,在某些情况下,使用,无标签数据比有标签数据少一个数量级。我们还发现有趣的是,这一课听起来与罗森伯格等人 2005 年发表的题为对象检测模型的半监督自我训练的论文中的观察结果惊人地相似:
…独立于检测器定义的训练数据选择度量大大优于基于检测器生成的检测置信度的选择度量。
这是您所有数据和建模问题的解决方案吗?当然不是——但它说明了启发式仍然是深度(半监督)学习管道中有用的一部分。同样,这里应用的试探法是特定领域的,只有仔细研究您的数据和模型的偏差,才能揭示有用的伪标签细化。
第三课:半监督图像分类的进展很难转化为目标检测。
我们跟踪的 SSL 研究的大部分进展都是测量图像分类的性能,希望能够轻松地将技术应用于其他任务的类似改进,如对象检测。然而,在我们自己尝试将图像分类方法用于对象检测时,我们遇到了几个挑战,这导致我们坚持使用第 1 课中提到的最简单的半监督对象检测方法。以下是其中的一些挑战:
- 在线与离线伪标签生成
在许多用于图像分类的 SSL 技术(FixMatch、UDA 等)中。),未标记数据的伪标记目标在训练期间或在线被更新/计算。在离线中,学习培训分为多个阶段。首先用标记样本训练模型,然后用标记样本生成伪标签。然后可以用标记的和伪标记的样本训练新的模型。
FixMatch 和 UDA 是 SSL 技术的示例,它们使用在线学习来通过阈值取得良好效果,仅允许预测高于某个阈值的未标记样本对训练信号有所贡献——在嘈杂的学生和 STAC(fix match 的对象检测变体)中,然而,伪标签是离线生成的。
虽然在线学习似乎是有利的——允许在稍后的训练步骤中纠正早期训练中的不良伪标签— ,但它使得训练在计算上更加昂贵,对于训练对象检测模型来说更是如此。为什么?两件事:数据扩充和批量大小。关于数据扩充,让我们重温一下在第 1 课 FixMatch 中首次出现的图表。
FixMatch 中如何使用未标记图像的示意图。(图片来自 Sohn 等人,2020 )
我们看到,每个未标记的示例在训练期间都是“弱增强”和“强增强”的,并且需要将两个增强图像通过网络向前传递以计算损失。这种数据扩充是许多 SSL 方法的基础,并且尽管对于图像分类是可行的,但是对于大图像(512x512+)上的对象检测任务的处理训练时间扩充会显著减慢训练。
在批量大小方面,许多作品(MixMatch、UDA、FixMatch、Noisy Student)和我们自己的实验也强调,未标记的批量大小是标记的批量大小的几倍对于 SSL 方法的成功至关重要。对对象检测任务的这种要求与存储器中的大图像以及对无标签批次中的所有样本的必要扩充相结合,产生了极大的计算负担。数据扩充和无标签批量大小这两个挑战是我们无法将像 FixMatch 这样的工作一对一转换为对象检测的最终原因。
在与 STAC 的作者的讨论中,他们也注意到了半监督对象检测空间中在线学习带来的沉重资源开销。我们希望未来的工作将更深入地研究这个问题,并且在未来几年中取得的计算成果将使研究人员更容易进行这样的工作。
- 用阶级平衡管理长尾
SSL 研究中的许多基准数据集,如 CIFAR10、CIFAR100 和 STL-10,都使用类平衡标记的训练集。我们的数据集,像许多真实世界的数据集一样,是极其长尾的。类别平衡被认为是许多 SSL 方法的关键组成部分(谢等人,2019 ,宋等人,2020 ),在图像分类中,上采样和下采样技术是常见的做法。然而,在对象检测设置中,有效的类平衡技术并不简单。
如果类平衡对于 SSL 在实践中的成功至关重要,那么我们如何在半监督对象检测中实现类平衡呢?解决这个问题的未来研究肯定会受到欢迎。
其他提示
迁移学习和自我培训是相加的
正如在 Zoph 等人关于 COCO 训练的 2020 中所发现的,执行从 COCO 到我们数据集的迁移学习,然后在嘈杂的学生环境中执行自我训练,所产生的结果比单独执行这两个步骤中的任何一个都要好。很可能任何应用于生产模型的迁移学习也可以应用于 SSL 模型,并带来同等或更多的好处。
适当的数据扩充很重要
由于数据扩充是现代 SSL 方法的主要组成部分,所以要确保这些扩充对您的领域有意义。例如,如果可用的增强集包括水平翻转,那么应该被训练来区分左箭头和右箭头的边界框的分类器显然会受到影响。
此外,在( Sohn 等人,2020-B )和吵闹的学生(谢等人,2019 )中,他们观察到,在自我训练中,对教师模型使用数据增强会导致下游学生模型较差。
(表 6 来自谢等,2019 )。在这项消融研究中,他们说明了具有增强功能的教师模型比没有增强功能的教师模型表现稍差(在 130 万张未标记图像上,84.4%对 85.1%)。
然而,我们发现嘈杂的学生和 STAC 在我们的数据集上的表现与增强的教师模型相等或略好于非增强的教师模型。虽然我们的结果对于我们自己的数据集来说可能是一个特例,但我们相信这表明了广泛实验的 重要性,以及对你在论文中读到的观点的所谓成功和失败感到好奇。 论文中显示的经验结果是一个很好的开端,但成功肯定是无法保证的,而且从理论角度来看,SSL 中仍有许多东西没有得到很好的理解。
离别赠言
半监督学习(SSL)在过去的一年中一直是我们工作的一个令人兴奋的领域,它在我们的生产模型中的最终结果向我们(希望你们所有人)表明,在某些情况下可以并且应该考虑 SSL。
特别是,对吵闹的学生进行自我训练对改进我们的目标检测模型是有效的。以下是我们在研究和生产深层 SSL 技术时学到的 3 个主要经验:
- 简约为王。
- 启发式伪标签精化非常有效。
- 半监督图像分类的进展很难转化为目标检测。
今天,许多深度学习工程仍然在为潜在的应用进行反复试验,我们希望你带着更多的先验知识离开,以推进半监督学习的工作。
作者 Varun Nair,杜克大学四年级本科生,前深度学习研究实习生。
致谢:
非常感谢 Javier Fuentes Alonso 和 Tony Beltramelli 阅读了这篇文章的几份初稿,并在我在 Uizard 工作期间成为了令人惊叹的同事和导师。我还要感谢 Uizard 的整个团队,感谢他们支持我,为我创造了一个绝佳的工作环境,无论是面对面的还是远程的。如果你有兴趣了解更多关于 Uizard 的工作和职位空缺,请查看我们的网站。
也感谢北卡罗来纳大学/谷歌的Colin raff El博士对这篇文章的早期草稿提供了很好的见解和反馈,感谢谷歌的Kihyuk Sohn博士对我关于他的作品的问题的积极和开放的回答。
附录
A —对非分布样本的稳健性
在我们过去的工作 RealMix ( Nair et al .,2019 )中,我们通过模仿 Oliver et al .,2018 中首次建立的一个实验,研究了 SSL 网络中对分布外未标记样本的鲁棒性。
(图片由作者提供)原载于奈尔等人,2019 。
我们最近在 75%的标签错配设置下对 FixMatch 进行了相同的鲁棒性实验,并在下面展示了这些结果。FixMatch 是一个更好的 SSL 应用程序,在标记和未标记的分布之间的不匹配率为 0%和 75%,但是,在这种情况下,它的性能与 MixMatch 一样差。有可能通过将 RealMix 中的元素与 FixMatch 结合起来,这种结合的技术可以克服这个问题。
在六类 CIFAR10 上进行 0%和 75%分布不匹配实验的错误率。(图片由作者提供)
从资源管理到数据科学:构建实时爬虫
对构建和实现大规模网络爬虫感兴趣?从我们的错误、经验和建议中学习,这将有助于您创建一个强大的 web 数据采集工具。
马库斯·斯皮斯克在 Unsplash 上的照片
在 Oxylabs 我们几乎是偶然地创建了一个大规模的网络爬虫。正如人们偶然发现的任何开发项目一样,我们在这个过程中犯了很多错误,也吸取了很多教训。我们希望我们的故事能对任何对创建数据采集工具感兴趣的人有用。
我们一开始是代理提供商,为所有想要执行大规模数据收集项目的人提供服务。正如那些深入研究这个行业的人所熟知的那样,当代理被用来抓取搜索引擎结果和复杂的电子商务网站时,它们很容易被禁止。
我们注意到,一些用户比其他人有更好的成功率和代理寿命,即使是在抓取相同的目标时。随着时间的推移,获得了很多关于网络抓取的知识。反过来,我们试图通过分享任何相关信息来提供价值。就像我们现在希望的那样。
卑微的出身
不幸的是,即使是最好的指导方针也无法抵御防刮擦措施不断变化的性质以及对持续数据流的需求。代理最终还是被封锁了。更换它们会推高交易双方的成本。
代理受阻对双方来说都是痛苦的经历。由于被封锁的 IP 地址,公司需要减慢他们的数据采集操作,而我们需要不断地采购更多的代理。幸运的是,一个解决我们困境的方法以最意想不到的方式出现了:我们的一位数据分析师学习了 Python 的基础知识。
不是这种类型的 Python。
构建原型
一位用户与电子商务网站进行了长期的斗争。不管他们是运气不好还是在爬虫的开发过程中出了什么差错,我们提供的代理似乎总是被屏蔽。在内部,开发我们自己的铲运机的想法已经流传了很长时间,但没有人坐下来真正开发它。直到我们的一位数据分析师决定亲自动手。
与任何对工具包有非常基本的理解但又充满热情的项目一样,它是一个烂摊子,由 Flask API、请求库和对古代蛇神的祈祷组成。当然,这是一个烂摊子,但它的工作。事实上,我们的原型做得相当好,尽管它确实有一些小问题,只是后来才变得明显。因此,在 2017 年的一个深夜,我们最新的解决方案诞生了,我们继续称之为实时爬虫。
规划和开发实践中的经验教训
不幸的是,虽然我们的解决方案有效,但最初为其开发实时爬虫的客户并没有接受我们的提议。但是我们确实有一个工作原型,它展示了很多希望。我们的想法是,我们可以进一步优化这个工具,以比以前更有效地从大型电子商务网站和搜索引擎获取数据。通过坚持我们随时间发展的最佳实践,我们可以充分利用每个 IP 地址并避免潜在的阻塞。如果我们不提供资源来购买产品,而是提供产品本身,会怎么样?希望没有人会再为棘手而复杂的数据采集过程而挣扎。
虽然我们的原型运行良好,但它仍然不适合广泛使用:一个单独的服务器托管整个过程,一次只能处理几个请求,最糟糕的是,获取的数据以 html 文件的形式存储在服务器文件系统上。当我们的工具最初被开发出来时,我们并不关注长期的大规模实施,因为它是出于我们能够解决一个特定挑战的希望。
我们意识到,如果我们承受任何压力,它都会在几秒钟内折断。但是希望就在那里,这就足够了。我们的高管和高级开发团队与我们的数据分析师坐下来,开始为未来制定计划。我们会用一个更好的计划重新开始。
亲爱的朋友们,再一次冲向缺口,再一次
于是,我们的实时爬虫开始了认真的开发。需要实现几个特性:
- 更好的请求和交付处理
- 排队系统
- 更好的服务器基础设施
幸运的是,最后两点并没有带来什么挑战。我们开发了队列系统,并通过使用 API 和 MySQL 将实时爬虫部署到许多不同的服务器上。当然,这些变化不是一夜之间发生的。虽然最初的实现相当快,但近 3 年的大部分时间都致力于消除细节和添加附加功能。
一个更好的请求和数据传递系统并不容易实现。然而,我们必须快速开发一个,因为用户在实现我们最初的构建时遇到了问题。
查询和交付:一场我们自己打的硬仗
我们开始时只有一种查询和检索数据的方法——回调。用户将发送一个有效载荷,详细说明他们对我们的服务器的请求,并能够在作业完成后检索所请求的数据。出于检索目的,将为每个有效负载分配一个唯一的作业 ID。此外,我们实现了回调 URL,我们将 ping(如果提供的话)它,以便平滑这个过程。
来源:Oxylabs 的设计团队
然而,回调有一个我们无法预测的问题:它很难实现用于测试目的。不足为奇的是,如果你的目标受众无法轻易测试你的工具,那么让别人相信你的工具对双方都有利是很难的。但我们希望以最高效的方式交付所需的数据。更重要的是,这个行业的大多数企业已经有了内部的网络爬行解决方案。为这些公司提供价值比我们预期的要困难得多。
我们的销售和营销团队不得不加倍努力工作。如果我们稍微多关注一下我们周围的开发文化****——哪些语言、API、框架等被广泛使用,就可以节省很多精力和时间。
可靠性与电子商务
我们知道我们将面临一个无止境的挑战——布局和反瓶颈变化。搜索最具挑战性和最受欢迎的搜索引擎和电子商务网站并不容易。这两家公司都不会永远使用相同的布局,也不愿意轻易放弃他们的数据。所有这一切意味着我们的大部分资源过去和现在都致力于了解反刮擦措施是如何实施的,以及我们可以为此做些什么。
仅仅通过提供我们通常的商业服务,我们就在数据采集行业获得了大量的经验和专业知识。强大的技术基础使我们能够预见某些挑战,并在它们出现之前实施解决方案。然而,有两个问题我们的经验无法解决:数据存储和易于实施。
处理数据存储问题
数据存储成为一个比预期更大的问题。我们犯的一个错误是只从一个方法开始——回调。回调似乎是一开始处理数据的好方法,因为理论上非常简单。不幸的是,被查询的数据必须放到某个地方,直到有人检索它。通常情况下,检索会被延迟。因此,这些数据必须存储天,直到有人来取走。
我们实施了一个 24 小时(通常,用户有更多的时间)的政策,因为它似乎是合理的。不可避免的是,24 小时以上存储大量数据会给任何存储基础架构带来很大压力。为此,我们决定通过创建缓存、优化数据库和简单地装备更好的硬件来消除冗余的数据查询。但这些解决方案只能到此为止。此外,电子商务数据具有时效性,24 小时前的数据可能已经过期。我们需要找到更好的方式让用户发送查询和接收数据。
将我们的重点转向提供更好的交付方法和更简单的方法来实现我们的工具给我们带来了巨大的成功。我们确信实时爬虫对双方都有利,但是我们需要一种方法来减少进入的障碍。
试用、易于实施和新的交付方法
试验问题从相同的初始开发过程中分支出来。如前所述,实现实时爬虫相当困难,这使得试验和测试非常痛苦。我们的解决方案之一是为我们的工具开发额外的方法。正如我们工具的包装上所说,实时是第二个被创造出来的方法。它的实现稍微容易一些,但是它依赖于一个开放的连接来不断地传递查询的数据。
来源:Oxylabs 的设计团队
实时给我们带来了两个好处——测试稍微容易一些,减少了对数据存储设备的压力。实时带来了一场革命,因为其他人无需重建整个基础设施就可以看到它的运行。但它仍然不够好,因为长期的实现仍然需要用户修改他们当前的爬行解决方案。需要另一种解决方案。
SuperAPI 是实时爬虫的最终形式。它允许用户实现我们的网络抓取解决方案,而不需要修改任何东西。他们会将我们的工具设置为他们自己的网络爬行工具中的代理服务器。其他一切都将正常工作,就好像它是通过其他方法实现的一样。最后,用户可以实现我们的解决方案,而不需要通过复杂的过程来改变已经为他们工作的东西。
现在有三种交付方式:
- 回收
- 实时
- SuperAPI
他们每个人都有自己的优点和缺点。大多数用户仍然使用老式的回拨,因为它可靠且使用简单,尽管入门有点困难。我们后来开发了更多的交付方法,因为我们更加关注提供更好的测试机会。现在,提高稳定性将是我们的最新目标。
维持稳定
我们最后的挑战是保持稳定。每一种工具都会偶尔发生故障,而大多数其他流程都准备好处理它。在数据采集中,尤其是与电子商务相关的数据采集,过程中的故障可能是灾难性的。
数据获取的稳定性是网站和开发者之间不断的拉锯战。出于用户体验的原因,网站可能会更新其布局,这也是一种反对数据抓取的做法。每次布局变化都会中断数据采集过程,并且需要一些时间进行重新开发。
防刮算法改进更差。就像布局变化一样,它们会破坏任何工具,但是重新开发过程会困难得多。逆向工程将是必需的,这意味着没有一个令人敬畏的开发团队和一点点运气,回到正常工作秩序可能需要大量的时间和资源。不幸的是,没有允许任何人无限期保持稳定的长期解决方案,只有最佳实践。
随着时间的推移,我们已经学会了关于保持稳定的两件事。首先,必须有一个专门的危机应对团队,每个人都准备好昼夜不停地工作,直到问题得到解决。每一个小时都很宝贵。第二,危机解决后,寻找数据采集过程中断的模式。根据你的预测打补丁也许你会避免以后出现类似的问题。
最终确定概念
虽然我们一直在构建和改进我们的网络爬行解决方案,但随着时间的推移,主要概念保持不变。以下是我们的实时爬虫如何工作的基本概要:
- 有效负载已发送到 API。
- 记录作业并设置 ID。
- 设置成队列系统。
- 每个队列可以被许多不同的 RTC 实例/服务器使用。
- 该作业由特定实例获取。
- 设置并检查指纹(根据最初要求)。
- 在作业启动之前,我们的[主]代理轮转程序会处理和分配合适的 IP。
- 作业已启动,HTML 已下载。
- 用过的 IP 会被送去冷却。
- 如果作业失败,实时爬网程序将使用不同的设置重试,直到成功。
- 数据被解析并为检索做好准备。
成功的步骤:数据收集的教训
我们的工具已经运行了一段时间了。从最初的粗陋到现在的天网般的机器霸主——实时爬虫,我们学到了很多东西:
- 创造工具,一只眼睛盯着未来,另一只眼睛看着市场。分析哪些语言、API、框架最受欢迎。它将为您节省大量的时间和成本。
- 构建行业领先的软件需要时间。这些年来,我们面临(现在依然如此)数百个挑战,有时我们认为实时爬虫可能没有我们最初想象的那么好。
- 想办法提供一个简单的测试环境。通常你必须说服商人,而不是开发商。
- 编写简单易懂的教程,并提供大量成功的例子。
- 确保您的工具是可扩展的,并且其功能不会在其他领域(如数据存储)引起问题。
- 数据存储将不可避免地成为一个问题。创建节省空间的流程—构建缓存、收购更多存储中心。
- 有一个专门的危机应对团队,因为故障是不可避免的。
- 分析每个分解。每一次危机至少都会为未来可能的崩溃提供线索。根据线索打补丁。
结局?
随着互联网格局的不断变化,大规模数据收集是一个永无止境的过程。我们仍在通过添加更多的目标,增加稳定性和适用性来改进我们的实时爬虫。我们最新的 fork,通用实时爬虫,仍然是一个萌芽项目,我们希望扩展到和它的前辈一样的高度。
我们花了很多年的时间和无数的错误来建立一个成功的大规模爬行工具。我们邀请所有人向我们学习。通过遵循我们在这一过程中学到的经验,您将使任何数据采集项目成本更低,耗时更少。
从零开始到搜索:处理数据(Elasticsearch 摄取管道)
一条管道来统治他们,一条管道来吸收他们,一条管道来转变他们,并在弹性搜索中绑定他们。
朱利安·维勒拉在 Unsplash 上拍摄的照片
介绍
在这篇文章中,我想快速浏览一下 Elasticsearch 提供的一个有趣的特性,我也倾向于在作为摄取管道的生产设置中使用它。此功能允许 在实际文档索引发生之前预处理文档 。听起来很有趣,为什么…
***Note: for an introductory hands-on overview of the Elasticsearch technology check out*** [***my previous article***](/from-scratch-to-search-setup-elasticsearch-under-4-minutes-load-a-csv-with-python-and-read-e31405d244f1)***.***
这在很多方面都很有用,但我认为有两个主要原因。首先,当你更多地处于(大)数据分析/处理方面时,你的优先事项(和任务)可能不会涉及源系统的主动变更。因此,您必须在原始数据到来时对其进行处理,并对其进行预处理以满足您的数据需求。第二,即使你打算改变生产者,你 A)可能不能直接控制所有的生产者(例如,由于一些组织方面的原因,例如,他们的遗留性质)和/或 B)仍然需要做好准备,改变可能需要相当长的时间(例如,想想你想要在你的共享日志库的新版本上升级数十/数百个微服务,等等)。).
对于这些情况,您可以调用来维护接收管道。
它是如何工作的
摄取管道是数据解析和转换领域的新玩家,长期以来一直被 Logstash 所占据。摄取管道实际上不是 Logstash 的完全替代。但是使用 Logstash 的考虑是,它不可避免地给你的架构带来了另一个 sw 组件,从而使它的操作更加复杂。摄取管道则不是这样,因为它们是由集群中的任何(或所有)常规 Elasticsearch 节点直接执行的。该节点只需要是摄取节点的类型(这是默认的),这样当您想要开始使用它们时,甚至不需要修改配置。
在索引操作期间,在协调器节点接收到请求之后,在摄取节点上执行流水线。图片来源:elastic.co。
管道定义
一般来说,管道是通过一个简单的 JSON 文档定义的,该文档包含一个处理器阵列,它代表一组有序的步骤,这些步骤应用于所有传入的文档并在其上执行。实际的处理器有各种各样的风格,所以我强烈推荐您浏览一下文档中的列表来熟悉一下。
处理器有一些共同之处。这些是:
- 能够使用花括号模板
{{service-name}}
在定义中访问/引用已处理文档的数据 - 能够定义处理器的条件执行,如果子句仅允许在检查条件后执行该步骤
- 能够使用 on_failure 子句处理处理器的故障
- 可以通过标记子句进行标记,这对于错误跟踪等非常有用
稍后将详细介绍这些内容。
测试环境加速旋转
理论已经讲得够多了,让我们在本地机器上的 Docker 中构建一个简单的(单节点)集群,并尝试第一个管道定义。注意:如果你需要更多关于 docker 部分的信息,可以在 我之前的文章 中找到。让我们也做一个 Kibana 的实例,以便有一个简单的 GUI 来查看。
#!/bin/bashdocker network create elastic-networkdocker run --rm --detach --name elastic4pipelines -p 9200:9200 -v esdata01:/usr/share/elasticsearch/data --network elastic-network -e "node.name=elastic4pipelines" -e "discovery.type=single-node" -e "bootstrap.memory_lock=true" --ulimit memlock=-1:-1 -e ES_JAVA_OPTS="-Xms2g -Xmx2g" docker.elastic.co/elasticsearch/elasticsearch:7.5.1docker run --rm --detach --link elastic4pipelines:elasticsearch --name kibana4pipelines --network elastic-network -p 5601:5601 docker.elastic.co/kibana/kibana:7.5.1
当您运行上面的脚本并等待几分钟时,您的临时弹性堆栈应该开始运行并为我们的管道测试做好准备(Kibana 在 http://localhost:5601/ 上运行)。
用管道处理文档
为了进行测试,我们将从小处着手,创建一个管道,它将:
- 用分割处理器按特定分隔符分割一个字段的值
- 在下一步中,使用 Foreach 处理器遍历新数组的所有值,并使用大写处理器转换为大写字符
curl -XPUT localhost:9200/_ingest/pipeline/my_simple_pipeline \
-H "Content-Type: application/json" \
-d '{
"processors": [
{
"split": {
"field": "meta.tags",
"separator": " ",
"target_field": "meta.tags_parsed",
"ignore_missing": true
}
},
{
"foreach": {
"field": "meta.tags_parsed",
"processor": {
"uppercase": {
"field": "_ingest._value"
}
}
}
}
]
}'
现在,让我们创建一个索引,将该管道用作默认的接收管道。
curl -XPUT localhost:9200/my_index \
-H "Content-Type: application/json" \
-d '{
"settings": {
"index.default_pipeline": "my_simple_pipeline"
}
}'
最后,让我们索引一个将由这个管道处理的虚拟文档。
curl -XPOST localhost:9200/my_index/_doc \
-H "Content-Type: application/json" \
-d '{
"comment": "I liked this article on pipelines!",
"meta": {
"tags": "good enjoyed recommended"
}
}'
现在我们可以看看基巴纳的文件。注意:不要忘记创建一个索引模式。我们可以看到适当的转换。
基于值的脚本和条件执行
不,让我们尝试两件事,为了更有效,让我们在一个处理器中同时使用这两件事:)
- 使用
if
子句的条件执行(对所有处理器都是可能的) - 使用脚本处理器进行更复杂的处理(当预制处理器不够用时)
这两者都使用了一种简单的脚本语言(基于 Groovy)。阅读无痛指南了解更多信息。然而重要的是:
- 可以通过
ctx
变量(所谓的摄取处理器上下文)在脚本中访问您处理过的文档 - ctx 包含提取的 JSON 的映射结构(用方括号
ctx['my_field']
引用各个字段) - 您可以修改 ctx 变量的值来添加、修改或删除文档的字段
简单的例子:如果 rest 对我们的目的没有用,我们可以用它只索引原始文本的一部分(子串)。所以只要更换管道…
curl -XPUT localhost:9200/_ingest/pipeline/my_simple_pipeline \
-H "Content-Type: application/json" \
-d '{
"processors": [
{
"script": {
"source": "ctx.comment = ctx.comment.substring(0,20) + '\'' (…)'\''",
"if": "ctx.containsKey('\''comment'\'') && ctx['\''comment'\''].length() > 20"
}
}
]
}'
…并为新文档编制索引。
curl -XPOST localhost:9200/my_index/_doc \
-H "Content-Type: application/json" \
-d '{
"comment": "Hello, this is a message which deserves a hair cut."
}'
提取结构化字段(解析默认 NGINX 日志行格式)
如果您正在处理以某种定义明确的格式构建的数据(但不是在单个字段中提取的),您可以尝试使用剖析处理器。只需用带百分号%{my_field}
的花括号描述提取的单个字段的模式。
我们可以使用这个处理器解析默认 NGINX 日志行格式(combined/main)之外的结构化字段,该格式具有以下结构。
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
有关 NGINX 日志的更多信息,请参见日志模块 ngx_http_log_module 的文档。我们还可以使用日期处理器提取@timestamp,因为原始值默认为非标准格式。
让我们把它放在新管道里。
curl -X PUT [localhost:9200/_ingest/pipeline/nginx_pipeline](http://localhost:9200/_ingest/pipeline/my_simple_pipeline) \
-H 'Content-Type: application/json' \
-d '{
"processors": [
{
"dissect": {
"field": "message",
"pattern" : "%{remote_addr} - %{remote_user} [%{time_local}] \"%{request}\" %{status} %{body_bytes_sent} \"%{http_referer}\" \"%{http_user_agent}\" \"%{http_x_forwarded_for}\""
}
},
{
"date": {
"field": "time_local",
"formats": [
"dd/MMM/yyyy:HH:mm:ss Z"
],
"timezone": "Europe/Prague"
}
}
]
}'
现在,您可以在消息字段中发布一个日志行并提取它。注意,您可以用查询字符串中的新管道覆盖索引中的默认管道。
curl -X POST localhost:9200/my_index/_doc?pipeline=nginx_pipeline \
-H 'Content-Type: application/json' \
-d '{
"message": "172.17.0.1 - - [24/Dec/2019:10:09:42 +0000] \"GET / HTTP/1.1\" 200 95 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36\" \"-\""
}'
刷新您的索引模式,并在 Kibana 中查看一下。
如果你想尝试一下,只需启动 nginx docker 容器并在/var/log/nginx 中找到你的日志。
您可以对不同格式的内容使用类似的处理器,例如 CSV 处理器(从 CSV 中提取字段)、 KV 处理器(解析 key=value 对)或基于 regex 的 Grok 处理器。
用另一个索引的值充实
我们要使用的最后一个东西是 Enrich 处理器,它可以用来自另一个索引的数据来丰富您的文档。酷吧!
在管道中使用它之前,有三个先决条件:
- 您需要有我们将从中获取浓缩数据的源索引
- 您需要定义一个丰富策略来定义源索引、匹配字段和附加字段
- 您需要
_execute
enrich 策略来为该策略创建一个 enrich 索引
让我们扩展前面的例子,使用已知 IP 地址的源索引(让我们忘记我们现在运行在 localhost 上的事实:),我们将检查添加一些数据,看看 IP 是否不在潜在的黑名单上。
首先创建源索引和一个文档(注意:使用refresh
查询参数来确保索引可以立即用于搜索):
curl -X POST localhost:9200/ip_source_index/_doc?refresh=wait_for \
-H 'Content-Type: application/json' \
-d '{
"ip": "172.17.0.1",
"black_listed": false,
"user_category": "test"
}'
下一步将创建充实政策。很简单——只需链接我们的源索引(我们在上面创建的),匹配 ip 字段并列出相关字段。
curl -X PUT localhost:9200/_enrich/policy/ip-policy \
-H 'Content-Type: application/json' \
-d '{
"match": {
"indices": "ip_source_index",
"match_field": "ip",
"enrich_fields": ["black_listed", "user_category"]
}
}'
我们需要执行它来创建 enrich 索引。
curl -X POST [localhost:9200/_enrich/policy/ip-policy/_execute](http://localhost:9200/_enrich/policy/ip-policy/_execute)
现在我们终于可以将 Enrich 处理器添加到我们之前的 nginx 管道中了。我们需要引用 enrich 策略、我们将匹配的字段(我们在上一步中提取的 remote_addr)、enrich 数据的目标字段和 max_matches(要包含的最大匹配文档数)。将以下内容添加到处理器中…
{
"enrich" : {
"policy_name": "ip-policy",
"field" : "remote_addr",
"target_field": "meta.ip",
"max_matches": "1"
}
}
现在只需(重新)发布之前的文档(使用相同的 nginx 日志行)并提取日志内容,然后从我们的“ip info”索引中丰富日志内容。
不错!
“生产”建议
最后,我想向您介绍摄取管道的其他概念和功能,当您想在实际场景中开始使用管道时,这些概念和功能与它们结合使用是非常有用的。
与索引模板一起使用
如果您旋转索引(在处理时间序列数据时,您可能应该这样做,大小在几十 GB 以上,等等。)如果您通过索引生命周期管理(我倾向于这样做)实现了这些自动化,那么更值得推荐的是利用索引模板。这些有助于将从索引模板创建的所有索引的配置(设置和映射)形式化。
从管道角度来看,您可以在设置中指定:
- index.default_pipeline 如果请求中没有直接指定其他管道,则默认应用该管道(如果有,则默认被覆盖)。
- index.final_pipeline 默认管道或请求管道之后每次运行的管道。
在包含它们之前,请确保您的管道存在,否则您的请求将会失败。
管道模拟
通过 _simulate API 来测试这些无疑是有用的(当你已经准备好管道并且需要执行一些改变的时候)。您可以在请求体中指定新的管道定义以及几个测试文档,并像处理这些文档一样获得结果。
POST /_ingest/pipeline/_simulate
{
"pipeline": {
"processors": [
...
]
},
"docs": [
{
"_index": "index",
"_id": "id",
"_source": {
// your doc here
}
}
]
}
故障处理
确保您处理流水线执行过程中发生的最终故障。通过在特定处理器级别或作为一个整体的流水线级别定义on_failure
块(由一些其他处理器组成)来实现。
将有问题的文档传递到不同的索引。
{
"processors": [ … ],
"on_failure": [
{
"set": {
"field": "_index",
"value": "failed-{{ _index }}"
}
}
]
}
空值的处理
对于需要条件执行的情况(即只有在字段存在的情况下),确保在引用的字段丢失或具有无效值时处理这些情况。你可以通过一些处理器提供的ignore_missing
属性(转换、重命名、删除……)或者在if
块中实现。
"if": "ctx.containsKey('foo') && ctx['foo'].containsKey('bar')"
重新索引
通常,当您发现接收管道时,您的现有索引中已经有大量数据。要让新的 shiny 管道处理这些数据,只需创建一个新的索引,并使用 reindex API 来复制数据。若要处理数据,请在索引设置或 reindex 请求正文中指定管道。
POST /_reindex
{
"source": {
"index": "source-index-*"
},
"dest": {
"index": "destination-index",
"pipeline": "my_pipeline"
}
}
注意:用 ILM 重新索引时要更加小心。
好了
我们研究了接收管道的各种特性,并进行了测试。希望你喜欢这个介绍,你可以在你的场景中看到一些潜力。
从脚本到预测 API
submission.csv?不用了,谢谢!
这是我上一篇文章的延续:
上次我们讨论了如何将 Jupyter Notebook 转换成脚本,以及各种基本的工程实践,如 CI、单元测试、包环境、配置、日志记录等
即使是脚本形式,它仍然需要我们更改配置并运行脚本,这对于 Kaggle 比赛来说是可以的,因为你所需要的只是 submission.csv ,但是你可能不想全天候坐在计算机后面,每当用户向你发送预测请求时就点击运行🙁
在本文中,我们将讨论如何利用我们上次构建的模型,并使用 FastAPI 创建预测 API 来提供模型服务!
背景:FastAPI
Python 生态系统中有很多针对 API 的框架,我最初的想法是用 Flask。但是我对 FastAPI 的简单和直观印象深刻,并且喜欢在这个迷你项目中尝试它!
“冰冻三尺,非一日之寒”,FastAPI 从 Django、Flask、APIStar 等之前的框架中学到了很多,我无法比创作者本人更好的解释这篇文章太棒了!
无聊但必要的设置
东西都在 one repo 这大概不是一个好的做法,应该是真实用例中不同的 GitHub repo,可能我以后会重构【专业的说法“清理我以前的 sxxt”】!
CS 的人总是说单一责任原则*,而不是说“不要把不同功能的代码放在一起”,下次也许你可以说“我们应该遵循单一责任原则!”
首先,让我们用新的包更新 requirements.txt,正如我们上次提到的,我们应该指定确切的版本,这样其他人就可以复制这个作品了!
# for last article
pytest==6.0.1
pandas==1.0.1
Click==7.0
scikit-learn==0.22.1
black==19.10b0
isort==4.3.21
PyYAML==5.2# for FastAPI
fastapi==0.61.0
uvicorn==0.11.8
chardet==3.0.4
在这之后,我们需要在 conda env 中再次安装 requirements.txt 因为我们有了新的包]
*# You can skip the line below if you have created conda env*
conda create - name YOU_CHANGE_THIS python=3.7 -yconda activate YOU_CHANGE_THISpip install –r requirements.txt
游戏计划
让我们想想发生了什么,我们希望有 API 端点来做预测,具体来说,如果用户给 us 输入,我们需要使用模型来预测并返回预测。
我们没有让us【human】处理传入的请求,而是创建一个 API 服务器来等待请求、解析输入、进行预测并返回结果。API 只是与我们的计算机对话并请求服务的结构化方式[在这种情况下是预测]
高层正在发生什么
下面是伪代码:
*# Load trained model*
trained_model = load_model(model_path)*# Let's create a API that can receive user request*
api = CreateAPI()*# If user send us the request to `predict` endpoint*
when user sends request to `api`.`predict`:
input = api[`predict`].get(input) # get input
prediction = trained_model(input) # apply model
return prediction # return prediction
这对快乐流有好处!但是我们应该永远不要相信用户,问问你自己,你会在日常生活中阅读用户手册吗?
例如,我们期望从用户那里得到{'a': 1,' b': 2,' c': 3},但是我们可能得到:
- 顺序错误{'b': 2,' a': 1,' c': 3},或
- 错误的键{'a': 1,' b': 2,' d': 3},或者
- 缺少密钥{'a': 1,' b': 2},或者
- 负值{'a': -1,' b': 2,' c': 3},或
- 错误的类型{ ' a ':' HELLO WORLD ',' b': 2,' c': 3},或者
- 等等等等
这对我们的 API 是致命的,因为我们的模型不知道如何对此做出响应。我们需要引入一些输入结构来保护我们!因此,我们应该更新我们的伪代码!
**# Define input schema
input_schema = {......}***# Load trained model*
trained_model = load_model(model_path)*# Let's create a API that can receive user request*
api = CreateAPI()*# If user send us the request to `predict` endpoint*
when user sends request to `api`.`predict`:
input = api[`predict`].get(input) # get input **transformed_input = apply(input_schema, input)
if not transformed_input.valid(): return Error** prediction = trained_model(**transformed_input**) # apply model
return prediction # return prediction
代码
我现在觉得不错!让我们用 FastAPI 一部分一部分地翻译它们吧!
输入模式
看起来有很多行,但事情是一样的,正如你所猜测的,我们定义了一个名为“Sample”的类,它将每个预测器定义为 float 和大于[gt] zero!
负载模型
然后我们加载训练好的模型,嗯嗯什么是‘预测器’?它只是一个用不同方法包装模型的定制类,因此我们可以调用一个方法,而不是在 API 服务器中实现逻辑
创建一个 API 服务器
然后我们使用 FastAPI 创建 API 伪代码几乎已经是代码了
预测终点
这看起来很复杂,但是非常简单
不是说“当用户向‘API’发送请求时。‘predict’”
我们说:"嘿,app,如果有人发送"GET请求"为了预测',请运行函数 predict_item,我们期望输入遵循我们在
示例`中定义的模式"
predict_item 所做的只是转换输入形状,馈送给训练好的模型并返回预测,简单的 Python 函数
如果你想了解更多关于 HTTP 请求方法
但是你可能会问:哎!少了一行!!!输入验证在哪里?如果用户提供了错误的数据类型/键或者遗漏了一个字段,该怎么办?
嗯……还记得我们已经为输入模式定义了“Sample”类吗?快速 API 自动根据模式为我们验证它,我们不需要关心这个!!!这为构建一个健壮的、经过良好测试的 API 节省了大量的脑力和代码!
尝试使用
# At project root, we can run this
# --reload is for development, API server autorefresh
# when you change the codeuvicorn prediction_api.main:app --reload
你应该能看到这些,API 服务器现在运行在“http://127.0.0.1:8000”上!
根据您的环境,有不同的方法来试验 API,您可以在 Python 中使用请求,在命令行中使用或 cURL。 BTW 有一个好用的工具叫做邮差,试试吧,这是一个非常直观和人性化的 API 工具!
我们将在下面的例子中使用 Python 请求,你可以在这本笔记本中看到它们【有时 Jupyter 是有帮助的😎]
下面的例子使用了一个有效的输入:耶!😍我们成功了!端点返回预测!!!
payload = {
"fixed_acidity": 10.5,
"volatile_acidity": 0.51,
"citric_acid": 0.64,
"residual_sugar": 2.4,
"chlorides": 0.107,
"free_sulfur_dioxide": 6.0,
"total_sulfur_dioxide": 15.0,
"density": 0.9973,
"pH": 3.09,
"sulphates": 0.66,
"alcohol": 11.8,
}result = requests.get("[http://127.0.0.1:8000/predict](http://127.0.0.1:8000/predict)", data = json.dumps(payload))print(result.json())**Output**
{'prediction': 1, 'utc_ts': 1597537570, 'model': 'RandomForestClassifier'}
下面的例子遗漏了一个字段,FastAPI 帮助我们根据我们定义的模式来处理它,除了模式类,我什么也没写
payload = {
"volatile_acidity": 0.51,
"citric_acid": 0.64,
"residual_sugar": 2.4,
"chlorides": 0.107,
"free_sulfur_dioxide": 6.0,
"total_sulfur_dioxide": 15.0,
"density": 0.9973,
"pH": 3.09,
"sulphates": 0.66,
"alcohol": 11.8,
}result = requests.get("[http://127.0.0.1:8000/predict](http://127.0.0.1:8000/predict)", data = json.dumps(payload))print(result.json())**Output**
{'detail': [{'loc': ['body', 'fixed_acidity'], 'msg': 'field required', 'type': 'value_error.missing'}]}
只是为了好玩,我还实现了一个 update_model PUT API 来交换模型,例如,最初我们使用随机森林,我将其更新为渐变 Boosting☺️
result = requests.put("[http://127.0.0.1:8000/update_model](http://127.0.0.1:8000/update_model)")print(result.json())**Output**
{'old_model': 'RandomForestClassifier', 'new_model': 'GradientBoostingClassifier', 'utc_ts': 1597537156}
自动生成的文档
其中一个很酷的 FastAPI 特性是 auto-document,只需进入http://127 . 0 . 0 . 1:8000/docs #/即可获得开箱即用的交互式强大 API 文档!如此直观,我不需要细说
重访 pytest
我再怎么强调单元测试的重要性也不为过,它验证了函数正在做我们期望它们做的事情,这样你就不会不小心弄坏东西了!
但是,如果我试图涵盖每一个测试,这将是太无聊和冗长。我打算在这里分享一些我会无脑测试的领域&一些[可能有用的]文章。然后我会讲一个叫参数化单元测试的 pytest 特性,以及 pytest 中的一些测试选项。激励自己学习单元测试最简单的方法就是尝试重构你之前的代码,越大越好!
单元测试
每当你发现编写/理解单元测试有困难时,你可能需要首先回顾你的代码结构。以下是我会不假思索考虑的 4 个方面:
- 输入数据:dimension [eg: df.shape],type [eg: str],值域[eg: -/0/+]
- 输出数据:dimension [eg: df.shape],type [eg: str],取值范围[eg: -/0/+]
- 比较:输出和预期结果
- 我调试后,防止它再次发生
例如,我非常关注下面的输出维度、类型和值范围。这似乎很简单,但如果你修改任何输出格式,它会提醒你什么是预期的格式!
FYR 的一些文章:
如何单元测试机器学习代码【深度学习】
参数化单元测试
假设您有 100 个模拟数据[用 D_i,i: 1 标注..100]并且你想为它们中的每一个运行相同的单元测试,你会怎么做呢?
蛮力大法
def test_d1():
assert some_operation(D_1)def test_d2():
assert some_operation(D_2)def test_d3():
assert some_operation(D_3)......def test_d100():
assert some_operation(D_100)
但是如果你需要修改“some_operation ”,你需要修改 100 次 LOL……虽然你可以把它作为一个实用函数,但这使得测试很难阅读,而且非常冗长
更好的方法也许是 for-loop?
def test_d():
for D in [D_1, D_2, D_3, ..., D_100]:
assert some_operation(D)
但是你不能确切地知道哪些测试失败了,因为这 100 个测试都在一个测试中
pytest 为我们提供了一个名为 参数化 的特性
[@pytest](http://twitter.com/pytest).mark.parametrize("test_object", [D_1, D_2, ..., D_100])
def test_d(test_object):
assert some_operation(test_object)
常见 pytest 选项
pytest 文件夹
上次我们提到我们可以在命令行中运行`pytest', pytest 会在文件夹下找到所有的测试。但是有时我们可能不想在开发过程中运行所有的单元测试[也许一些测试花费了很长时间,但是与您当前的任务无关]
在这种情况下,你可以简单地运行 pytest 文件夹,例如:` pytest。/scripts '或' pytest。演示中的/prediction_api '
并行 pytest
有时你的测试用例太重,并行运行可能是个好主意!您可以安装 pytest-xdist 并在您的命令中用 py.test 替换 pytest,例如:py.test -n 4
pytest -v
这是个人喜好,我更喜欢冗长的输出,看到绿色通过✅开始我的一天
pytest
pytest -v
您可以从以下材料中了解更多信息:
最后,我希望你能和我一样喜欢这个 1 分钟的 Youtube 视频😆
结论
Yooo✋:我们已经创建了一个使用我们模型的预测 API,用户现在可以发送请求并获得预测,而无需人工参与,这过度简化了现实[吞吐量、延迟、模型管理、身份验证、AB 测试等],但这就是我们的想法!
至少如果你的原型达到了这个水平,工程师们会更乐意接手,从而加快整个过程,你可以向他们展示你知道一些东西😈
最后,我们:
a. Update conda env [requirements.txt]
b. Brainstorm pseudocode and convert to code [FastAPI, uvicorn]
c. Utilize API [cURL, requests, Postman]
d. Talk about Auto-generated documents by FastAPI
e. Some pytest techniques [parallel, parameterized, -v]
下面的文件树显示了开发步骤
.
├── notebook
│ ├── prediction-of-quality-of-wine.ipynb
│ └── prediction_API_test.ipynb [c] <-consume API
├── prediction_api
│ ├── __init__.py
│ ├── api_utility.py [b] <-wrap up methods
│ ├── main.py [b] <-modify demo
│ ├── mock_data.py [e] <-Unit test
│ ├── test_api_utility.py [e] <-Unit test
│ └── test_main.py [e] <-Unit test
├── requirements.txt [a] <-FastAPI doc
.
.
.
但是(还是那句话,坏消息通常以 BUT 开头)它们还在我的本地电脑上。
尽管我们不需要坐在后面点击 Run,但是用户请求不能到达 API 端点。即使他们这样做了,这也意味着我不能关闭我的 Macbook,这意味着如果有许多传入的预测请求,我就不能扩展😱!!!
正如我们在上一篇文章中提到的,逃离这个地狱的方法是,要么购买另一台计算机,要么从 AWS 等云提供商那里租用服务器
但是首先,我们还需要确保代码在那里工作正常!怎么会?
简答:Docker
旁白:
虽然我没有尝试过,但有一家名为 Cortex 的初创公司专注于开源机器学习 API 框架,他们也在幕后使用 FastAPI !
到现在,你应该能理解他们的教程了,简而言之,他们在幕后解决了滚动更新、DL 模型推理、与 AWS 集成、自动缩放等许多生产层面的问题……这些都是 DevOps 关心的问题?或者用一个更好的术语: MLOps
但是从用户的角度来看,他们使用声明性的 yml 部署 APIs 类似于我们在上一篇文章中配置模型的方式],有一个预测器类[类似于我们的预测器类],trainer . py[类似于上一篇文章中的 train.py
编写代码相对容易,但是为代码写一篇文章却很难,如果你觉得这篇文章有用,你可以留下一些评论
或者你可以开始我的回购!
或者我的 LinkedIn 【欢迎但请留话表示你不是僵尸】!
从 sklearn 导入*
以及其他暴露你是假数据科学家的证据
像大多数报道“黑客”的新闻媒体一样,虚假数据科学家乐于使用他们在网上找到的任何随机代码(图片来源: Picography
最近,似乎每个人和他们的狗都在推销自己是数据科学家——你很难责怪他们,因为“数据科学家”被评为本世纪最性感的工作,并且拿着高薪。尽管如此,我们还是会责怪他们,因为许多装腔作势的人在公司间招摇撞骗,尽管他们几乎没有实践经验,甚至更没有理论基础。在我采访和与当前和未来的数据科学家合作的经历中,我发现了一些区分装腔作势的文章和真实文章的线索。我无意贬低自学成才和有抱负的数据科学家——事实上,我认为这个领域特别适合热情的自学者——但我肯定想贬低那种参加一门在线课程,然后自称专家的人,尽管对该领域的基本理论一无所知(或不感兴趣)。我整理了这份清单,这样,如果你是一名招聘经理,不知道你在数据科学家身上寻找什么,你可以过滤掉渣渣,如果你是一名有抱负的数据科学家,并且其中任何一条引起了你的共鸣,你可以在自己变成装腔作势者之前解决它们。以下是数据科学的三大领域失言和具体的例子,它们会让你的简历被扔进垃圾箱。
1.你不用费心去探索数据
数据探索是任何机器学习项目的第一步。如果你不花时间去熟悉你的数据,并充分了解它的特性和怪癖,你将会浪费大量的时间,在得到一个可用的产品之前,错误地选择决策树——如果你真的成功了的话。
a)您没有可视化您的数据
探索性数据可视化是启动任何数据相关项目的最佳方式。如果你正在应用机器学习,很可能你正在处理大量的高维数据;仔细阅读 Excel 中的. csv 文件或运行df.describe()
并不是适当的数据可视化的合适替代方法。Francis Anscombe 在他著名的四重奏中阐述了数据可视化的重要性:
安斯科姆的四重奏(来源:维基共享资源)
每个面板中的数据集都具有基本相同的汇总统计数据:x和 y 均值、 x 和 y 样本方差、相关系数、R 平方值和最佳拟合线都(几乎)相同。如果您不可视化您的数据并依赖汇总统计数据,您可能会认为这四个数据集具有相同的分布,但粗略一看就会发现显然不是这样。
数据可视化允许您识别数据中的趋势、工件、异常值和分布;如果你跳过这一步,你也可以蒙着眼睛完成项目的其余部分。
b)您没有清理您的数据
数据是杂乱的:数值输入错误;转换出错;传感器瘫痪了。在你浪费时间在一个没有前途的项目上之前解决这些问题是很重要的,在将你的模型推向生产之前解决这些问题是非常关键的。记住:垃圾入垃圾出。
有很多好的方法来识别数据中的问题,但没有好的方法来识别所有问题。数据可视化是很好的第一步(我提到过这个吗?),虽然这可能是一个繁琐的手动过程,但它的回报是很多倍的。其他方法包括自动异常检测和条件汇总统计。
例如,考虑人类身高的直方图:
成人身高直方图
用这些数据训练一个模型无疑会导致糟糕的结果。但是,通过检查数据,我们发现这 100 个“异常值”实际上是以米而不是厘米为单位输入身高的。这可以通过将这些值乘以 100 来校正。适当地清理数据不仅可以防止模型被错误的数据训练,而且,在这种情况下,让我们挽救 100 个数据点,否则它们可能会被丢弃。如果您没有适当地清理您的数据,最好的情况是将钱留在桌子上,最坏的情况是构建一个有缺陷的模型。
c)您不必为功能选择和工程设计费心
神经网络的一个很酷的事情是,你可以经常把你所有的原始数据扔给它,它会学习你的目标函数的一些近似值。不好意思,错别字,我指的是其中的 最坏的 事情。当然,这很方便,但是效率低而且脆弱。最糟糕的是,这使得初学数据的科学家依赖深度学习,而通常情况下,更传统的机器学习方法可能更合适,这让他们慢慢陷入困境。进行功能选择和工程设计没有“正确”的方法,但有几个关键的结果值得努力:
- 降维:数据越多并不总是越好。通常,您希望在拟合模型之前减少特征的数量。这通常涉及删除不相关和冗余的数据,或将多个相关字段合并成一个字段。
- 数据格式化:电脑是哑巴。你需要把你的数据转换成你的模型容易理解的格式:神经网络喜欢-1 到 1 之间的数字;分类数据应该是一次性编码的;有序数据(可能)不应该表示为单个浮点字段;对指数分布数据进行对数变换可能是有益的。简单地说,在数据格式化中有许多依赖于模型的细微差别。
- 创建特定领域的特性:从数据中创建自己的特性通常很有成效。如果您有计数数据,您可能希望将其转换为相关的二进制阈值字段,如"≥100" vs " < 100 ",或" is 0" vs "is not 0 "。如果您有连续的数据 x 和 z ,您可能希望在您的特征集中包含字段 x 、 xz 和 z 以及 x 和 z 。这是一个高度依赖于问题的实践,但是如果做得好,可以极大地提高某些类型模型的性能。
大多数外行人认为机器学习就是从原始数据中神奇地产生结果的黑盒;请不要助长这种误解。
2:您没有选择合适的型号
机器学习是一个有着丰富历史的广阔领域,在那段历史的大部分时间里,它被称为“统计学习”。随着 Scikit-Learn 和 TensorFlow 等易于使用的开源机器学习工具的出现,结合我们现在收集的海量数据和无处不在的快速计算机,使用不同的 ML 模型类型进行实验从未如此简单。然而,这并不是一个巧合,取消 ML 从业者实际上理解不同模型类型如何工作的要求导致许多 ML 从业者不理解不同模型类型如何工作。
a)你什么都试了
有抱负的数据科学家的 github repos 上散落着 Kaggle 项目和在线课程作业,看起来像这样:
from sklearn import *
for m in [SGDClassifier, LogisticRegression, KNeighborsClassifier,
KMeans, KNeighborsClassifier, RandomForestClassifier]:
m.overfit(X_train, y_train)
这是一个明显的信号,表明你不明白自己在做什么,而且这么多在线课程推荐这种做法,这是一个该死的耻辱。这是浪费时间,并且容易导致选择不合适的模型类型,因为它们碰巧在验证数据上工作良好(您记得持有验证集,对吗?对吗?)。应该根据底层数据和应用程序的需求来选择所使用的模型类型,并且应该对数据进行设计以匹配所选择的模型。选择模型类型是数据科学过程中的一个重要部分,在几个合适的模型之间进行直接比较可能是有保证的,但盲目地应用每一种工具来寻找“最佳数字”是一个主要的危险信号。特别是,这掩盖了一个潜在的问题,即…
b)你实际上并不了解不同的模型类型是如何工作的
如果您的输入是“车龄”和“行驶公里数”,为什么 KNN 分类器可能不太好用?应用线性回归预测全球人口增长有什么问题?为什么我的随机森林分类器不能在我的数据集上使用 1000 类一热编码变量?如果你回答不了那些问题,没关系!有很多很好的资源可以学习这些技术是如何工作的;在你申请这个领域的工作之前,一定要阅读并理解它们。
这里更大的问题不是人们不知道不同的 ML 模型是如何工作的,而是他们不关心并且对底层的数学不感兴趣。如果你喜欢机器学习但不喜欢数学,那你不是真的喜欢机器学习;你看上什么你就看上什么 觉得 那就是。如果你不关心学习模型是如何工作的,或者是否适合数据,那么当它们不可避免地出错时,你就没有希望解决它们。当…时,问题只会加剧
c)你不知道你想要的是准确性还是可解释性,也不知道为什么你必须做出选择
所有模型类型都有其优点和缺点。机器学习中的一个重要权衡是准确性和可解释性之间的权衡。你可以有一个预测能力很差但很容易理解并能有效解释过程的模型,你可以有一个非常准确但其内部运作是个谜的黑匣子,或者你可以在中间的某个地方着陆。
您选择哪种类型的模型应该根据这两个特征中哪一个对您的应用更重要来决定。如果目的是对数据建模并获得可操作的见解,那么一个可解释的模型,如决策树或线性回归,是显而易见的选择。如果应用程序是生产级别的预测,如图像注释,那么可解释性就不如准确性,随机森林或神经网络可能更合适。
以我的经验来看,不理解这种权衡的数据科学家,以及不考虑为什么可解释性很重要而一味追求准确性的人,都不是你想要的那种训练模型。
3:你没有使用有效的度量和控制
尽管构成了 50%的单词和 64%的字母,但数据科学的“科学”部分经常被忽略。对于 poser 数据科学家来说,盲目地在真空中应用单一指标作为他们的模型评估并不罕见。不知情的利益相关者很容易被像“90%的准确率”这样的大胆断言所震惊,这些断言在技术上是正确的,但是对于手头的任务来说却是非常不合适的。
a)您没有建立基线模型
我有一个胰腺癌测试,准确率超过 99%。不可思议吧。嗯,这是真的,你可以点击这个链接自己试试。
如果你看到一个红色圆圈,中间有一条线穿过,你的测试结果是阴性。如果你看到一个绿色的对勾,你在撒谎。关键是,99%的人没有胰腺癌(实际上,更多,但为了这个例子,让我们假设是 99%),所以我的愚蠢的小“测试”在 99%的时候是准确的。因此,如果准确性是我们所关心的,任何用于诊断胰腺癌的机器学习模型都应该至少像这个无信息的基线模型一样执行。如果你刚从大学聘用的能人声称他开发了一个准确率高达 95%的工具,将这些结果与基线模型进行比较,确保他的模型比随机模型表现得更好。
b)您使用了错误的度量标准
继续上面的诊断示例,确保使用正确的度量标准很重要。对于癌症诊断,准确性实际上是一个糟糕的指标;如果降低准确度意味着灵敏度的提高,那么降低准确度通常是更好的选择。假阳性的代价是什么?病人的压力,以及浪费的时间和资源。假阴性的代价是什么?死亡。理解你的模型在现实世界中的含义,并理解这些含义如何支配指标选择,可以清楚地将真正的数据科学家与他们的脚本小子相似者区分开来。
你搞砸了训练/测试
这是一个大问题,而且太普遍了。正确测试模型对于数据科学过程来说是绝对必要的。这可能会在很多方面出错:不理解验证和测试数据之间的差异,在拆分之前执行数据扩充,不堵塞数据泄漏,完全忽略数据拆分……除了如果您不知道或不关心如何创建一个合适的维持集,您的所有工作都是浪费时间。
…将张量流作为 tf 导入
这些只是少数放弃游戏的告诉。有了足够的经验,他们很容易被发现,但如果你刚刚开始在这个领域工作,你可能很难区分世界上的 Siraj Ravals 和 Andrew Ngs。现在,我并不是说要把这个领域留给有抱负的数据科学家;如果你觉得被以上任何一个例子攻击,我很高兴听到它,因为这意味着你关心把事情做好。继续学习,继续攀登,这样你也可以被人山人海的装腔作势者无休止地折磨。
从懒鬼到数据科学家
数据科学/职业
我的无学位数据科学之旅。
Clem Onojeghuo 在 Unsplash 拍摄的照片
我肚子里的蝴蝶;我的胃打结了。我知道分享我的故事是在冒险,但我想接触到其他渴望成为数据科学家的人。我写这些是希望我的故事能鼓励和激励你。至少,希望你的旅程不会像我一样漫长。
所以,全速前进。
我没有博士学位。见鬼,我连什么学位都没有可言。尽管如此,我还是非常幸运地在一家好得离谱的公司担任数据科学家。
我是怎么做到的?提示:我得到了很多帮助。
永远不要让学校教育干扰你的教育——格兰特·艾伦
形成性格时期
那是 1995 年,我刚刚拥有了我的第一台电脑。这是 1982 年的苹果谎言。它没有附带任何软件,但有一本手册。我就是这样学会了我的第一门计算机语言:Apple BASIC。
我对编程的热爱由此而生。
在代数课上,我记得学过二次方程。那时我有一个便宜的图形计算器,卡西欧,价格大约是 TI-82 的一半。它还附带了一个手册,所以我决定写一个程序,可以毫不费力地为我解二次方程。
我对解决问题的热爱由此而生。
在我高三的时候,我的父母对经济资助一无所知,但我决心要上大学,所以我决定加入海军,这样我就可以用 MGIB 支付我的大学费用。毕竟,四年的服务似乎没那么长。
我对冒险的热爱由此而生。
后来在我的海军生涯中,我被提升为船上的财务经理。我负责管理多项预算。这段经历教会了我记账。
我对数字的热爱由此而生。
从海军退役后,我结束了在一家非营利机构的志愿服务。他们最终招募了我,让我从零开始启动一个家庭暴力危机项目。我没有社会工作经验,但我还是同意了。
我喜欢说“为什么不呢?”诞生了。
谷底
在成功的几年后,我的老板退休了,新老板解雇了我。我崩溃了。我陷入了临床抑郁症的深度状态,觉得自己一文不值。
我记得在厨房的桌子上哭得很大声。离开非营利工作已经一年多了,我还没有找到下一份工作的前景。我在一个非常黑暗的空间里。
谢天谢地,哭泣是一次宣泄的经历。它给了我一个震动,让我做一些反省,停止抱怨,并提出一个计划。
“选择一份你热爱的工作,你这辈子就一天都不用工作了。”—匿名
坠入爱河,从头再来
为了支付账单,我一直在做自由网页设计师/开发者,但我并不快乐。坦白地说,做网页设计的工作让我很无聊。与那些思维和行为都像设计专家的客户一起工作令人沮丧。
所以我开始想,“下一步是什么?”。
在网上搜索时,我偶然发现了人工智能的最新消息。它引导我走向机器学习,这反过来又引导我走向数据科学的主题。
我被迷住了。
我在 Coursera 上注册了吴恩达的机器学习课程。我听了 TwitML,线性题外话,还有其他几个播客。我重温了 Python,在 Github 上重新认识了 git。
我恋爱了。
就在这个时候,我有意识地决定成为一名数据科学家。
信念的飞跃
学习新事物对我来说很有趣。但是,我脑海中仍然有一个声音告诉我,无论我学习多少,我永远也找不到工作,因为我没有学位。
所以,我认真地看了看镜子,承认我需要帮助。现在的问题是从哪里开始寻找。
然后突然有一天,女朋友问我什么是数据科学。我跳了起来,马上开始解释。一旦我停止解释喘口气,我设法问她为什么问。就在那时,她告诉我她在广告牌上看到了一个标志。我们开车出去兜风,亲眼看到了那个标志。这是一个奇怪的广告牌,上面有两个大字“数据科学”,还有一个较小的写着“Codeup”。我上了他们的网站,研究了他们的就业结果。
我被卖了。
准备
上课前,我们拿到了一份要复习的材料清单。
- 数据科学数学技能— Coursera
- 机器学习的数学:线性代数——Coursera
- 基础统计— Coursera
- 面向数据科学的 Python—Coursera
- Excel 基础— Udemy
- 学习命令行—代码学院
鉴于我只有大约两个月的准备时间,我并不指望能完成这些课程。我基本上被告知只是浏览一下内容。不管怎样,我还是做了。我日以继夜地复习课程和材料。做了测试,拿到了证书!
训练营
新兵训练营一片模糊。我们在海军有一句关于新兵训练营经历的谚语:“日子过得很慢,但几周过得很快。”对于 Codeup 新兵训练营来说也是如此。
Codeup 被描述为“完全沉浸式的、基于项目的 18 周数据科学职业加速器,为学生提供 600 多个小时的应用数据科学专家指导。学生在整个数据科学管道(规划、获取、准备、探索、建模、交付)中发展专业知识,并适应处理真实、杂乱的数据,以便向不同的利益相关方提供可操作的见解。”
我们用 Python 编码,查询 SQL 数据库,用 Tableau 制作仪表盘。我们做了一个又一个项目。我们学习了不同的方法,如回归、分类、聚类、时间序列、异常检测、自然语言处理和分布式机器学习。
更重要的是,这次经历教会了我们以下几点:
- 真实数据杂乱无章;处理好它。
- 如果你不能和你的利益相关者沟通,你就没用。
- 记录您的代码。
- 阅读文档。
- 永远学习。
求职
我们的求职过程从新兵训练营的第一天就开始了。我们更新了我们的 LinkedIn 个人资料,并确保我们几乎每天都在推送 Github。我甚至美化了我的个人网站,把我们在课堂上做过的项目包括进来。当然,我们确保了简历的良好状态。
Codeup 帮助我解决了所有这些问题。
此外,Codeup 还帮助我们为技术和行为面试做准备。我们按照 S.T.A.R .格式(情境、任务、行动、结果)练习答题。我们优化了我们的答案,以突出我们作为高潜力候选人的优势。
毕业后
我的教育甚至在毕业后还在继续。在填写应用程序的间隙,我会每天编写代码,尝试不同的 Python 库。我定期阅读新闻,了解机器学习的最新进展。做家务的时候,我会听播客、ted 演讲或 LinkedIn 学习视频。无聊的时候,我就听书或者看书。
有很多好的技术书籍可供阅读。但是对于非技术性的,我推荐如下:
- 用数据思考
- 数学毁灭的武器:大数据如何增加不平等并威胁民主
- 《看不见的女人:为男人设计的世界中的数据偏差》
- 菜鸟智慧:为什么在工作的新游戏中学习胜过了解
- 《勇气:激情和毅力的力量》,安吉拉·杜克沃斯著
- 第一个 90 天:迈克尔·沃特金斯证明的更快更聪明地达到目标的策略
处理拒绝
我被拒绝了很多次。第一个是最难的,但之后,它变得越来越容易。我脸皮厚了,继续生活。
被拒绝了。尽量不要往心里去。没有人喜欢失败,但它会发生。当它出现时,失败。
结论
我从新兵训练营毕业后花了 3 个月才找到工作。付出了很多牺牲。当我最终得到这份工作时,我感到非常感激、宽慰和兴奋。
没有 Codeup 和家人的支持,我不可能做到这一点。
感谢阅读!我希望你从这篇文章中有所收获。
所有有抱负的数据科学家,不要放弃。尽量不要听信外面所有的仇恨者。如果必须的话,听听他们要说什么,评估一下你的弱点,并渴望比昨天学得更好。但是永远不要让他们打击你。请记住,数据科学技能取决于光谱。如果你有热情和毅力,我很确定有一家公司或组织非常适合你。
如果你正在考虑开始数据科学家的职业生涯,请查看下面的文章:
给我们其他人的固执己见的建议。热爱数学,选修。
towardsdatascience.com](/the-slackers-guide-to-rebranding-yourself-as-a-data-scientist-b34424d45540)
敬请期待!
[1] Codeup 校友门户。(2020 年 5 月 31 日)。简历——埃德纳林·c·德迪奥斯。https://alumni.codeup.com/uploads/699-1562875657.pdf
从流数据到新冠肺炎 Twitter 分析:使用 AWS Lambda、Kinesis Firehose 和 Elasticsearch
释放 AWS 和 Elasticsearch 的力量
分析实时推文的仪表板。
介绍
在我之前的博文 从流数据到新冠肺炎 Twitter 分析:使用 Spark 和 AWS Kinesis 中,我涵盖了用 Spark 和 AWS Kinesis 构建的数据管道。在这篇文章中,我将采用另一种方式来达到同样的目的。
在之前的工作经历中接触过 AWS Lambda 和 Elasticsearch。Lambda 的无服务器、事件触发特性以及与其他 AWS 工具的丰富连接给我留下了深刻的印象。Elasticsearch 向我展示了系统生成的杂乱日志是如何被整齐地处理的,并且在 Kibana 上是可见的。受到这篇文章的启发: 用 AWS 构建一个接近实时的发现平台,我复制了数据管道并将其应用于 Twitter 上的新冠肺炎分析。为了尊重原创作品的版权,我不会将这个帖子货币化。
与 参考文章 相比,我新增内容如下:
- 进行代码更改以与依赖项的最新版本保持一致。
- 提供更多关于人们容易遇到的问题的细节,而这些问题在参考文章中没有涉及。
- 遇到 Lambda 和 Elasticsearch 相关错误时如何调试?
数据管道遵循接近实时流的时尚,从消化实时 Twitter 数据到可视化。组装拼图的大部分碎片来自 AWS 家族: AWS Kinesis Firehose 、 AWS S3 水桶、 AWS Lambda 、亚马逊弹性搜索服务。架构是这样的:
数据管道的体系结构。
本文作为参考文章的补充指南,将讨论分为以下步骤:
- IAM 设置
- 创建亚马逊弹性搜索服务集群
- 配置 AWS Kinesis 消防软管和 S3
- 创建 AWS Lambda 函数
- 代码打包和更改
- Kibana 可视化和 Twitter 分析
Lambda 函数和 Twitter 捕获程序的代码已经上传到我的公共回购中。
IAM 设置
在构建数据管道之前,您需要有一个 AWS 帐户和 Twitter API 密钥以及访问令牌,这在参考文章的的先决条件中也有提及。除此之外,IAM 角色非常重要,必须正确设置。需要两个角色:
- Kinesis Firehose 需要一个 IAM 角色,并被授予传送流数据的权限,这将在 Kinesis 和 S3 桶一节中讨论。
- AWS Lambda 需要权限来访问 S3 事件触发器、添加 CloudWatch 日志以及与 Amazon Elasticserch 服务进行交互。
lambda 函数的 IAM 角色 lambda-s3-es-role。
如上图所示,我给 Lambda 执行角色 lambda-s3-es-role 附加了三个策略。如果您不确定如何配置策略,我将这些策略附在 repo 中以供参考。
创建亚马逊弹性搜索服务集群
我假设读者已经按照参考文章中的步骤在 Amazon ES 主页创建了一个 Amazon ES 域。对于自由层用户,他们可以选择 t2.micro 或 t2.small 等实例类型,并免费获得 750 小时的 Amazon ES 使用时间。创建 ES 域时需要注意几点:
- 无需设置“专用主节点”。
- 作为演示项目,我在“网络配置”中选择公共接入。
事情是这样的。在配置"访问策略"时,选择"客户访问策略",需要添加以下策略:
- 选择“ARN”,允许 lambda 执行角色 lambda-s3-es-role 访问 es 服务。
我在这里留下一个疑问:设置是否正确?我们稍后会测试它。
配置 AWS Kinesis 消防软管和 S3
与参考文章不同,我选择在 Kinesis 消防水龙带流控制台创建一个 Kinesis 消防水龙带。步骤很简单:
- 填写消防水带流的名称
- 来源:直接投资或其他来源
- 目的地:一个 S3 桶,用于存储数据文件(实际上是推文)。在这里,您可以选择一个您已经创建的 S3 桶或创建一个新的飞行。
- 权限。
正如在 IAM 部分中提到的,一个 Firehose 流需要 IAM 角色来包含所有必要的权限。单击“新建或选择”,并选择“创建新的 IAM 角色”,或使用现有的角色。默认策略将被附加,并应满足需要。
Kinesis Data Firehose Stream (KDF)和 Kinesis Data Stream (KDS)有时可能会让人混淆。KDF 在传输流数据时有额外的功能。在传递到目的地的过程中,源数据可以通过 Lambda 函数进行转换。我的另一个帖子涵盖了 KDF 的用法。
创建 AWS Lambda 函数
AWS Lambda 在这个管道中起着核心作用。我们将创建一个 Lambda 函数来完成以下工作:
- 一旦在目标 S3 桶中创建了新的数据文件,Lambda 函数就会被触发。
- 数据将使用指定的结构进行解析,这与文档的映射一致。
- 数据将被加载到 ES 集群中。
一下子实现这样一个 Lambda 函数很难。将繁琐的过程分成更小的步骤,我首先需要正确设置 Lambda 环境。
在 AWS Lambda 主页创建功能:
- 选择 Python 3.7 运行时。
- 选择 lambda-s3-es-role 作为执行角色。
- 将内存保持在 128 MB,并将超时设置为 2 分钟。
- 为 S3 添加一个触发器。如果任何新文件进入 S3 桶,Lambda 函数将接收事件并被调用。
为 Lambda 函数创建一个 S3 触发器,注意前缀“debug”用于调试,可以根据需要替换。
现在,我们可以测试 Lambda 函数是否能对 S3 事件做出反应。使用示例代码和配置好的处理程序,我们将一个文件放入 S3 桶 twitter-stream-sink。
创建一个 Lambda 函数,并将一个测试文件放入 S3 桶中。请注意,处理程序名称应该与函数代码中的入口函数相匹配。
在 Lambda function 面板的“Monitoring”选项卡上,有一个点出现在指标图上。单击“查看 CloudWatch 中的日志”,我们得到了这次调用的 CloudWatch 日志,该日志打印了我们刚刚放入的源 S3 桶和文件名。
左侧窗口显示了度量图中的一个点,表示对 Lambda 函数的调用。右侧窗口显示了 CloudWatch 日志的详细信息。
代码打包和更改
参考文章是几年前发表的,所以项目代码需要更新。
项目代码可以从 repo 下载。代码目录包含 4 个 python 文件: config.py , myhandle.py , tweet_utils.py , twitter_to_es.py 。要将必要的库添加到项目文件夹中,只需键入命令:
pip install library_name -t .
导入到项目目录所需的库如下:
requests
requests_aws4auth
elasticsearch
textblob=0.15
Lambda 函数接受 zip 格式的代码包。将代码目录与库打包需要以下命令:
zip -r ../your_package_name.zip * -x "*.git*"
关于 Lambda 部署包的教程可以在 AWS Lambda 文档中找到。
现在让我们看一下每个 python 文件:
myhandle.py
- 充当 Lambda 函数的入口点。
- 解析事件信息,获取 JSON 格式的 S3 文件内容。
twitter_to_es.py
- 向 es 集群添加索引和映射。
- 采用 bulk 方式将解析后的数据加载到 ES 集群中。
- 授权发送到 ES 集群的请求。
tweet_utils.py
- 充当助手模块。
- 将推文解析到结构化字典中。
- 使用 TextBlob 分析推特上的情绪。
配置. py
- 充当共享配置。
与参考文章中的原代码相比,我做了一些代码改动:
- 将额外的库添加到包 requests_aws4auth,requests 中。
2.将源代码从 Python 2 移植到 Python 3。
3.修复错误,因为 Elasticsearch 及其 Python 客户端库与以前的版本不兼容。
为了将源代码从 Python 2 移植到 3,我们可以使用库2to3
。
使用 2to3 命令将 Python 2 代码移植到 Python 3 的例子。
不兼容问题已修复:
- 自 Elasticsearch 7.0.0 发布以来,映射类型被移除。
- Elasticsearch 的 Python 客户端也经历了以前版本的变化,特别是 bulk 方法的使用。
为了熟悉 Elasticsearch 的 Python 客户端,你可以打开一个 Jupiter 笔记本来测试与 ES 集群的连接。
研究完代码后,我们需要打包代码。为了测试 Lambda 函数,我们将一个捕获的 twitter 文件放入 S3 桶,并查看 tweets 是否被正确解析并加载到 e S 集群中。
左边的窗口显示了 Lambda 函数的面板,右边的窗口显示了将带有 tweets 的样本数据文件放入 S3。
如果数据成功加载到 ES 集群中,我们可以使用 Kibana 的“Discover”功能来检查它。
左侧窗口显示调用 Lambda 函数期间的跟踪日志,右侧窗口显示加载到 es 中的 tweets。
除了 Lambda 函数上的代码变化,我使用一个运行在 AWS EC2 实例上的 Python 程序来捕获 tweets,可以在这里找到。参考文章包含一个 node.js 程序来捕捉推文,它们都做同样的工作。
运行 Python tweet 捕获程序
这里要注意一点。当我实现管道并尝试将数据加载到 ES 集群时,我在 Lambda 调用和 Kibana 上遇到了身份验证错误:
当我将一个数据文件放入 S3 桶时,Lambda 函数报告了这样一个错误。
当我在设置了 ES 集群后试图访问 Kibana 时。
为了找出原因,我们需要去指定 Amazon ES 的身份和访问管理的页面。
基于 IP 的策略的主要吸引力在于,它们允许对 Amazon ES 域的未签名请求,这允许您使用像 curl 和 Kibana 这样的客户端,或者通过代理服务器访问域。
所有对 Amazon ES 配置 API 的请求都必须签名。在上面的错误中,即使添加了 Lambda 执行角色,请求还是未签名并被拒绝,尤其是 HTTP 请求。为了解决这个问题,我们可以添加基于 IP 的策略,或者使用 AWS SDK 或请求添加标志。因此,我们需要将基于 IP 的策略添加到 ES 访问策略中:
Kibana 可视化和 Twitter 分析
一旦我们开始运行 twitter 捕获程序,大量的推文将被传入 S3,Lambda 函数将处理数据文件。反映数据的最佳方式是通过 Elasticsearch 中提供的可视化工具 Kibana 。
加载到 Elasticsearch 中的所有数据都需要分配索引,因此 Kibana 可以使用索引模式来检索数据。在 twitter_to_es.py 中,推文用“twitter”做索引。现在我们可以创建一个索引模式“twitter*”,并开始在 Kibana 中发现数据。
创建索引模式“twitter*”,以匹配所有以“twitter”开头的索引。
当我们在 tweet_utils.py 中添加映射时,会指定“timestamp_ms”字段。
创建索引模式后,我们可以通过选择左侧栏上的“Discover”按钮来浏览数据,数据可以按时间序列显示。
在这篇文章中,我选择了标签“ #StayHome ”和“# social distance”来挖掘 Twitter。像参考文章一样,我创建了一个仪表板来可视化推文。仪表板中有三种可视化效果:
- 一张坐标地图,展示推文的地理分布,仅当推文包含位置信息时有效。
- 一个饼图,展示用户发送推文时的情绪受欢迎程度,包括积极、中性和消极三种情绪。
- 一个数据表,统计每个情绪中包含的表情符号,只列出前 5 个表情符号。
在基巴纳创建的仪表板。
结论
AWS Lambda 和 Elasticsearch 是非常强大的技术,这篇文章可能只是展示了应用场景中的一个案例。除了实时数据处理,Lambda 还可以与 ETL(提取、转换、加载)和应用后端集成。Elasticsearch 在日志记录/日志分析和全文搜索方面已经建立了声誉。
我希望你在阅读和摆弄大数据技术时能够找到乐趣。这就是大数据让我着迷的地方。
编者注: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
从细流到赫罗库
如何主持你的项目的简单指南?
注意这个指南是针对 Heroku 上的主机的,如果你想在 AWS 实例上主机,请查看我的朋友 Marco 的 Streamlit to AWS 指南这里!
大家好,本周我将一步一步地介绍如何将您的 streamlit 项目从笔记本电脑转移到在线服务器上。对于这个例子,我将使用我的 Yelp 评论应用程序来指导您。
我们开始吧,好吗?假设我们已经在本地安装并运行了我们的 streamlit 应用程序,但是我们希望在我们的家庭环境之外安装它。在你的 Jupyter 笔记本上应该是这样的:
现在,如你所知,为了让你的 Streamlit 应用程序启动并运行,你必须把它放到一个. py 文件中,以便 Streamlit 在本地运行它,Heroku 也是如此。因此,我们将点击“文件”和“下载为..”一个 python 文件。
为 Heroku 做准备
Heroku 为开发者提供了一个在云上运行和操作平台的平台。它不仅提供托管服务,还为你的应用程序提供了一个易于构建的虚拟环境。因此,我们需要给 Heroku 准备一堆指令来启动和运行它。
对我来说,开始时最好的事情是把我的前端和项目的其他部分分开,因为我们要做一些翻找和创建文件的工作,我不想让这些文件混淆。首先,Heroku 需要一些文件来给它必要的指令,以使虚拟环境运行起来。下面是我的文件树的样子,列出了必要的文件:
Procfile
现在,app.py 就是您在。py 格式。下一个文件, Procfile 是一个声明启动时要运行什么命令的文件。它没有特殊的扩展名,只是简单地命名为 Procfile。要创建它,只需打开 Jupyter 笔记本上的应用程序,点击右上角的“新建”按钮,然后选择“文本文件”
这将创建一个没有特殊附件的空白文档。打开它,输入以下代码:
web: sh setup.sh && streamlit run app.py
您会注意到代码的后半部分包含运行我们的应用程序的 streamlit 命令。
requirements.txt
现在,我们将对 requirements.txt 做同样的事情。Requirements.txt 向 Heroku 提供了关于库的说明,这是我们运行应用程序所需要的。这实质上是定义您在设置虚拟环境时需要的东西。在我的 requirements.txt,我正在输入以下内容:
streamlit==0.49.0
numpy==1.17.3
通过这种方式,我让 Heroku 知道这个应用程序需要这个版本的 Streamlit 和那个版本的 Numpy。这并不是说 Heroku 手头没有它,但这允许我修正我想要的版本,而不必担心一些新的更新会破坏我的代码。
setup.sh
编辑:来自 的反馈 Samudrala Sai kiran mayee表示 setup.sh 全部小写以避免问题很重要。
转到 setup.sh ,我们将按照创建上两个文件的相同方式创建文件,在 Jupyter Notebook 中创建一个新的 txt 文件。顺便说一下,不要忘记用适当的扩展名来重命名您的文件。与 requirements.txt 一样,s etup.sh 有助于为我们的 streamlit 应用程序的运行创建必要的环境。我们将在 s etup.sh 中输入以下命令:
mkdir -p ~/.streamlit/echo “\
[general]\n\
email = \”[your-email@domain.com](mailto:your-email@domain.com)\”\n\
“ > ~/.streamlit/credentials.tomlecho “\
[server]\n\
headless = true\n\
enableCORS=false\n\
port = $PORT\n\
“ > ~/.streamlit/config.toml
如果你愿意,可以把电子邮件改成你自己的。如果没有,不要担心,它仍然会运行良好。
与 Heroku 互动
现在我们已经安排好了所有的事情,是时候准备和 Heroku 接触了。有一个 git 方法,但是我更喜欢使用 Heroku 的 CLI(命令行界面),因为它可以减少混乱。你可以在这里安装 Heroku 的 CLI 。注意,你还需要在你的电脑上安装某种形式的 Github。Heroku 与 Github 携手合作,我还没有看到一个部署选项在某种程度上不需要 Git。我个人用 Github 桌面。
登录 Heroku
Heroku 的 CLI 允许您从家庭终端直接与 Heroku 交互。打开终端,用 CD 找到你的应用程序的根目录。在那里,输入以下命令:
$ heroku login
这将触发一个新的网络浏览器,您可以在其中输入 Heroku 的登录信息。输入您的登录信息并点击登录,当网站通知您已登录时,您就可以关闭浏览器了。
创建一个 Heroku 实例
接下来,我们通过键入以下命令指示 Heroku 创建一个 Heroku 实例:
$ heroku create
Heroku 会自动运行并给你的应用分配一个随机的名字,我们稍后会更改它的名字。
将你的文件载入 Heroku
接下来,我们将把所有文件传送到 heroku 实例中。因为 heroku 使用 Git,所以这个过程应该很熟悉:
$ git push heroku master
现在请记住,我们仍然应该在你的应用程序的前端根目录,所以它会把所有的东西都转移到 Heroku。记住这一点很重要,因为稍后我们将讨论在您做出更改时更新 Heroku 上的应用程序。
运行您的应用
最后,我们将启动并运行我们的应用程序。输入以下内容:
$ heroku ps:scale web=1
$ heroku open
第一个命令告诉 Heroku 启动一个 dyno (Heroku 对虚拟机实例的术语)。PS 是 Heroku 影响 dynos 的许多命令的前缀。 Scale web=1 告诉 Heroku 加速 1 dyno,根据你的服务器流量,你可以告诉它加速更多。这整个命令基本上启动了你的应用程序。
最后一个命令将弹出你选择的浏览器,并把你带到应用程序。您会注意到网址是自动生成的实例名加上 heroku。
更改应用程序的名称
要改变这一点,我们必须去我们的 heroku 仪表板。在你的浏览器中,进入 Heroku.com。前往您的仪表盘,点击您的应用程序。
你现在应该在你的应用程序的“概述”页面。点击设置。
“设置”是一个非常明显的工作页面,您应该可以在这里看到更改应用程序名称的选项:
更新您的 Git 远程路径
请记住,更改名称将要求您在进行任何更新之前更新 git remotes。这里的给出了这样做的指示。
最后,在我们结束之前,如果您已经在本地更新了您的应用程序,并且想要更新您的应用程序,您需要做的就是单击“部署”
向下滚动 deploy 页面,您会看到一些有用的 git 命令,帮助您根据需要克隆或更新 heroku 实例。
这就对了。您的应用程序应该已经启动并运行,希望用户已经准备好了!我希望这个指南对你有所帮助。还有许多其他有用的 streamlit 到 Heroku 指南,但更多的例子总是更好。祝你好运,并享受构建应用的乐趣!
从桥梁到任务规划:用 Python、R 和 Tableau 构建 Gannt 图表
史诗图表
使用基本的 DataViz 工具创建项目进度可视化
前一段时间我有一个想法,有很多关于条形图,直方图,散点图,折线图和其他有效但非常简单和普通的数据可视化工具的信息。我甚至可以假设,对于每个数据科学家或 DataViz 专家来说,如何构建这些通用图表的知识必须被视为基本和必须的。但是有各种各样的情节和想象。它们不太常见,更具体,但肯定应该在你的清单中。更重要的是,你还必须熟悉一些现代工具来制作这样的图表。这就是我如何想出“史诗图表”系列的想法,你现在看到的是它的第一期。
桥梁施工(1912)甘特图示例,Schürch,1916。参考自《亨利·甘特工作回顾》(2012)
我的“史诗图表”系列的第一期是献给甘特图。这是进度可视化的一个例子。它的经典实现显示了项目中任务的周期:水平线包含任务(或阶段),垂直线包含日期或时间范围,甚至简单的周期计数。因此,每个任务都显示为一个固定长度的条形图,占据了一些时间线(或几个时间线)。现代版本还可以包括关于紧急程度、阶段之间的关系以及阶段之间的转换的附加数据。
1.很少的历史评论
这张图表最早由凯罗尔·阿达米耶茨基于 1896 年创建,亨利·甘特在他的作品《工作工资和利润》中对其进行了详细描述,其中也包含了他早期的出版物。甘特图及其可视化的首次应用出现在 1912 年 Hermann Schürch 的出版物中。实际上,这是封面上的一张图表。Gannt 开发了几种进度图的变体(例如,见下面的一个),但是 Schürch 给出了我们一直使用到今天的形式。
“奖金图表”信息来自甘特的“工作工资和利润”(1916)。参考自《亨利·甘特工作回顾》(2012)
你可以在当时的资料中找到更多信息——“甘特图,一种管理的工作工具” (1922),以及在现代研究中——“亨利·l·甘特,1861–1919。回顾他的作品《T8》(2012)。史实到此为止,我们去实施吧。
2.Python 中的甘特图
我们将使用我创建的测试示例。它是简单的项目模拟,包括几个阶段、一些同时进行的任务和一些可重复的任务。
我们将从众所周知的matplotlib
库开始。因为这是每个数据科学家都知道的基本知识,所以不需要介绍。所以,一点日期操作和情节是准备好的:
在另一个例子中,我们将使用Plotly
库——另一个著名的包。它有一个强大的交互式可视化引擎和许多内置的图表类型。包括甘特一号!
3.R 中的甘特图
R community 开发了许多绘图库,包括一些交互式图表。当然,它们在可视化风格、交互性和绘图参数的语法方面有所不同,但是图表原理是相同的。因为没有选择哪个库的问题,我将创建两个例子。
首先,我将用最著名的图书馆纯ggplot2
制作一个甘特图。我们将使用相同的数据,做一些准备,这就是:
第二个例子使用[plotrix](https://cran.r-project.org/web/packages/plotrix/plotrix.pdf)
包——独立绘图库之一。因为它集合了很多功能,所以代码更短,结果“更漂亮”。
当然,你可以自由选择其他的图书馆。
4.表格中的甘特图
我已经用 Python 比较了 Tableau 和自定义绘图。我发现 Tableau 是一个非常好的工具,可以让你看到美丽的画面。它的库存很大,可以生成几乎任何类型的图表。包括甘特图!
算法非常简单:
- 加载数据;
- 使用图表的默认线条类型;
- 使用公式创建计算字段持续时间:
DATEDIFF(‘day’,[Start.Date],[End.Date])
- 拖放开始。日字段添加到列中;
- 将名称字段拖放到行中;
- 更改任务名称的排序选项:按“字段”排序,升序,使用
[Start.Date]
变量,按最小值聚合; - 将以前创建的持续时间字段拖到“大小”选项中;
- 拖放是。颜色选项的关键字段;
- 做一些美化。
瞧,图表准备好了:
今天到此为止。敬请关注下一期的“史诗排行榜”。而且,和我的文章一样,您可能会在我的 GitHub 上找到工作示例:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Midvel/medium_jupyter_notes/tree/master/epic_gantt_chart)
另外,请不要错过我的关于用 Python 再现 Tableau 可视化的文章:
[## Python dataviz 库可以重复 Tableau 工作表吗?
我对 Tableau 用法及其与 Python 代码的比较的第一印象
towardsdatascience.com](/can-python-dataviz-libraries-repeat-the-tableau-worksheet-e38ef2876f04)
从生物学家的角度来看
生物学家如何在数据革命中导航
这是我的第一篇媒体文章。首先,我想简单介绍一下我自己。我目前在加拿大阿尔伯塔大学学习分子、细胞和发育生物学,重点是生物信息学。我以前对计算机科学毫无背景。事实上,我现在正在大学二年级上我的第一堂计算机科学课。
像大多数生物学家一样,我也缺乏计算机科学技能,也不擅长数学。我第一年上过微积分课,绩点 1.3。是的……但是这并不能准确的描述我的数学能力。那是大学第一年。我讨厌教授把大部分话题搞得过于复杂(我在高中接触微积分的前一年就自学了这些概念,并被它的优雅所折服),嗯,我只是太鲁莽了。退一步说,这只是你大学第一学期的常规课程,你要尝试很多新的经验,微积分真的不是你的首要任务。我想这是合理的,因为你大学的第一学期是为有点鲁莽而准备的,因为你以后不能再这样了,或者至少我是这么认为的。
无论如何,我第一次探索编程是在疫情飓风来袭,我无处可去的时候。近一年来,我一直在窥视编程和生物信息学的整个领域,但从未真正有足够的动力去认真对待它。每次我尝试的时候,即使是设置 Python 和 IDE 的过程对我来说也是极其可怕的,不可避免地,我会立刻放弃。现在疫情将我关在里面,周围没有朋友或家人(那是大学的第一个暑假,我是一名国际学生,因为 Covid,我所有的朋友都回了家),没有其他事情可做,我有足够的时间来玩这个我想了很久的新东西。所以我就一头扎进去了。
我打开 YouTube,搜索“python 教程”。Python 只是我想到的第一种语言。我很幸运找到了完美的教程。这个教程真正让我印象深刻的是,老师是如何让概念变得真正相关和简化,而不是过于简单。
并不是我只跟着这个教程就精通 Python 了。事实上,直到今天,我只看了视频的前 60%左右。但这足以让我在 Python 的上下文中了解编程语言的基本思想。过了一段时间,我还看了一些基本的 Java 教程,其中一个特别适合我,这进一步使我理解了计算机语言,尤其是面向对象编程语言是如何根据它们的语法和结构创建的。
除了阅读本教程,我还寻找了有效学习编程语言的方法。作为一名程序员和一名独立学习者,其中一些技巧对我的发展非常重要。为了熟悉一个概念,我会看无数的其他视频。
每次我遇到一个新的概念,我都会在 YouTube 上看一些关于它的视频,这在开始时很有效。我会从各种不同的 YouTubers 上观看相同概念的视频,只是为了从不同的角度理解它们。这给了我很大的帮助,因为如果一个老师不能足够清楚地解释这个主题,或者以一种适合我的方式解释,我会准备另一个。这都是关于尝试和错误,看看谁最适合我的学习风格。
后来,当我学到更复杂的概念时,我不得不用笔记本记下我理解的内容。并不是说我以后会看这些笔记。在学习新东西后,从我的脑海中提取概念,用我自己的话写下来的行为足以将它们嵌入我的记忆中,至少在几周内。当然,随着时间的推移,这变得越来越容易。
我进行的另一个重要实践是在整个学习过程中混合使用自上而下和自下而上的方法。事实上,直到今天我还在学习。自下而上的方法是首先学习基础知识,然后学习稍微复杂一点的概念,最后应用这些概念。自顶向下是当你选择一个特定的应用或用例,然后尝试学习理解这个特定的概念或用例所需要的一切。我决定长期采用自下而上的方法,短期采用自上而下的方法。我来详细说明一下。我从相对简单的概念开始,如循环、数据类型、变量等。,然后慢慢上升到更复杂的概念。这个挺标准的。但是我所做的与众不同的是,我使用了特定的用例来试图理解它所需要的一切。
随着时间的推移,我对用例的选择变得越来越复杂,因为我遵循了长期的自底向上的策略。例如,我最初在生物学的背景下测试并应用了我从第一个教程中学到的东西,这个教程是在罗莎琳德网站上找到的。这是我最初感兴趣的地方;使用现代计算工具回答生物学问题。由于这些问题对我有限的知识来说太复杂了,我继续前进,决定创建一个以新冠肺炎为主题的太空入侵者游戏。我使用 Pygame 遵循了一个普通的太空入侵者教程,但是加入了我自己的修改,把它变成了一个新冠肺炎主题游戏。这很有趣,有共鸣,最重要的是,鉴于我当时的技能水平,我对这一点相当满意,可以应用我最初学到的基础知识,但当我完成它时,也有足够的机会教我新概念。在选择用例或项目时,取得这种平衡可能是独立学习最重要的部分。
作者创建的图像。目的是在病毒到达底部的关键工人之前,使用注射液滴(挤压空间)杀死病毒。 GitHub
快进到今天,我现在精通许多 Python 数据科学库,自学机器学习,使用来自 Kaggle 的数据集,如新冠肺炎研究数据集或 FIFA 19 数据集,类似地结合了自下而上和自上而下的方法。我绝不是数据科学甚至编程方面的专家。我和你一样,是一名数据科学爱好者,试图利用互联网上的大量开源信息自学这个迷人的领域,坦率地说,这些信息有时会让人不知所措。但是到目前为止,我觉得我做得挺好的,如果我能做到,你也能。把我当成你的学习伙伴,而不是专家。我喜欢写和谈论我感兴趣的事情,这次媒介之旅对我来说只是一个创造性的出口,在那里我结合了我对生物学、数据科学和编程的热情。请关注我的更多文章,学习如何自学这些知识。
数据革命将在不久的将来改变许多基本的生活方式,我对它了解得越多,就越喜欢它。如果你想让我谈论它的任何特定方面,请在评论中告诉我。我喜欢开门见山,这可能是我所有文章的一贯特点。快乐学习!
附言:要获得更多关于数据科学、编程以及生物学家如何在数据革命中导航的简明扼要的文章,可以考虑关注我的博客。
由于每分钟都有成千上万的视频被上传,所以过滤掉它们是很重要的,这样你就可以只使用高质量的数据。我亲自挑选的,我会把你感兴趣的主题的教育视频发邮件给你。报名这里。
感谢您的阅读!
从理论物理学家到数据科学家
我如何成为一名拥有理论物理博士学位的数据科学家
有很多人解释他们如何成为数据科学家的故事,但我发现当我进行转换时,很难找到一个符合我个人资料的故事。这就是为什么我想分享我的旅程,以防它可以激励其他人经历同样的事情。一年多前(2018 年秋季),我决定从事数据科学职业,现在我是加拿大 Décathlon 的一名数据科学家,所以我实现了我的目标。我将描述我的旅程作为一个例子,但这并不意味着作为建议。我不是找工作的专家。
我的背景
我没有从事数据科学的人的典型背景,我指的是计算机科学或某种工程学位。我在蒙特利尔大学完成了数学和物理的本科学习,然后去了麦吉尔大学完成了理论物理的硕士和博士学位。在这些学位期间,我主要学习了高等数学以及如何利用它们解决问题。我主要做理论工作,但也做一点科学编程。我还积极参与组织每周的讲座和阅读课程,去小学和孩子们一起做科学活动,并志愿参加会议和活动。
在我博士学位快结束的时候,我开始考虑用我的学位能找到什么样的工作。我得告诉你,直接涉及理论物理的工作非常难找。他们中的大多数都在大学,他们需要至少一名博士后,所以我把他们排除了。我想过找一份教书的工作(在塞 GEP,给知道那是什么的人),但我想找一份更有挑战性的工作。引起我注意的一个话题是人工智能。
学习人工智能
当然,人工智能现在是一个大趋势,作为一个住在蒙特利尔的学生,我听到了更多关于它的事情。我花了很多时间在网上试图了解在数据科学领域找到工作的要求,发现每个人都建议在 Coursera 上学习吴恩达的机器学习课程。我听从了这个建议,发现这个课程非常棒,我从中学到了很多东西。然而,在完成它之后,我觉得我对人工智能的理论方面有了很好的理解,特别是从我的角度来看,它是基于简单的数学,但我不知道如何实现它。这就是为什么我在 Udemy 上参加了数据科学和机器学习训练营的 Python。我学习了 python、numpy、pandas 和 scikit-learn,以便实际进行机器学习。
我经常在网上读到的下一个建议是,专注于通过个人项目学习,并在 Github 和你的简历中展示它们。这是我在参加网络课程后的几个月里所做的事情。你可以在这里看到我的第一个项目。在做这些事情的时候,我总是在网上看招聘信息,看看有什么工作机会,他们需要什么技能,我认为最重要的是深度学习。这让我参加了 Coursera 上的深度学习专业,我发现这非常有趣,并给了我新的个人项目的多个想法。
第一轮求职申请
当然,我要说明的是,这些都是我还在读博的时候兼职做的。上面提到的步骤花了我大约 6 个月的时间来完成我作为博士生的常规任务。我实际上有一点点额外的空闲时间,因为研究人员的任务之一是保持最新的新研究成果,为未来的项目做准备,但我快要毕业了,所以我不必这样做。我还有额外一年的奖学金,所以我不用急着找工作,所以我慢慢来。
大约在我完成深度学习专业化的时候,我开始申请提到我所拥有的技能的工作和实习。没有多少,但我仍然设法得到了实习和几份工作的面试机会。这些职位是为像我这样有良好科学背景和一些人工智能经验的人准备的。即使我很兴奋,我认为这有点为时过早,我是对的,因为我没有得到位置。
打磨我的技能
然后,我决定在开始认真申请工作之前,把重点放在增加技能和经验上。2019 年夏天,我的情况很好,我仍然有资金,但我的论文几乎完成了。然后我就可以集中精力找工作,并在工作完成后提交论文。我也考虑过在获得博士学位后留在麦吉尔大学进行 Mitacs 实习的选择,这是一个由一位教授和一家公司共同完成的研究项目。
我没有提到的一个细节是,我和人们交谈。我发现我周围和 linkedIn 上的人已经做了我想做的事情,我向他们征求建议。我通过电子邮件与他们中的一些人交谈,并与一些人一起喝咖啡,我收到了非常好的建议。
因为我有更多的时间学习新的东西,所以我看书(尤其是这本)和看很多 Youtube 视频(sentdex 的频道非常鼓舞人心)。我开发了像这个语言标识符这样更复杂的项目,并写了关于我的项目的博文(见我的简介)。我终于花了一些时间学习数据科学工作所需的更实际的技能,如 SQL、git、linux 和 flask。
毕竟,我对只申请我感兴趣的工作很有信心。我仍然对研究和商业工作感兴趣,所以我两个都找了。我每天都在寻找新的职位,并附上个性化的求职信。一些人回来找我,我设法得到了加拿大 Décathlon 的面试机会,我现在在那里从事计算机视觉和数据驱动项目的混合工作。我在开始工作前完成了论文,在开始论文答辩几个月后,我请了一周的假。
对感兴趣的人来说,这是我用来获得目前工作的简历:
从变形金刚到表演者:近似注意力
作者图片
加速变压器的数学技巧
几周前,来自谷歌、剑桥大学、DeepMind 和艾伦图灵研究所的研究人员发布了论文反思表演者的注意力,该论文旨在寻找解决变形金刚中 softmax 瓶颈问题的解决方案[1]。他们的方法利用了一个聪明的数学技巧,我将在本文中解释。
先决条件:
- 变压器的一些知识
- 核函数
涵盖话题:
- 为什么是变形金刚?
- 变压器的问题是
- 绕过 softmax 瓶颈
为什么是变形金刚?
从本质上讲,Transformer 是一个设计用来高效处理顺序数据的模型,实际上它在自然语言处理(NLP)任务中被大量使用,这些任务需要处理单词/字母序列。与其他顺序模型不同,transformer 利用注意力机制来并行处理顺序数据(即:不需要一次处理一个单词/输入)[2]。
作者图片
如果你不熟悉变形金刚,我推荐你阅读注意力是你所需要的全部——2017 年介绍它们的论文,非常容易理解——或者图解变形金刚以获得对初学者更友好的介绍。[3][4]
变压器的问题是
变形金刚基于注意力,计算如下:
其中 Q,K,V (维度 L x d )是查询、键和值矩阵, L 是序列的长度, d 是查询、键和值向量的(任意)维度。
注意:如果你不知道这是从哪里来的,我强烈推荐阅读前面提到的文章(注意力是你所需要的全部),尽管对于本文的目的来说,并不严格需要知道什么是查询、键和值,以及为什么注意力是这样计算的(或者它是什么)。
transformer 的问题来自 softmax 函数,让我们看看为什么。
注意的时间复杂性
提醒一下,两个维数为 n x m 和 m x p 的矩阵相乘的时间复杂度为 O( nmp )。
如果我们看一下注意力的等式,我们会看到我们在乘以三个矩阵: Q (维度为 L x d )、k^t(dxl,以及v(lxd)。我们会得到不同的复杂度,取决于我们相乘的顺序。
暂且忽略 softmax 和分母 sqrt(d)(它只是一个标量),我们可以看到,通过乘以 Q K ^T 我们首先获得复杂度 O( L d ),而如果我们乘以 K ^T V 我们首先获得复杂度
O( d L )。
作者图片
我们更喜欢 O( d L ),因为 d 是我们可以选择的参数,通常我们可以有 d < L 。然而,我们实际上不能按照这个顺序执行乘法,因为 Q K ^T 被“卡”在了 softmax 里面,没有简单的方法把它取出来。这意味着我们不得不处理 O( L d )的时间复杂度,这是序列长度的二次方(因此处理更长的序列在计算上变得越来越昂贵)。
所以,softmax 是变形金刚的瓶颈,我们想找到一种方法来解决这个问题。
作者图片
绕过 softmax 瓶颈
从高层次来看,本文提出的方法非常简单。我们能否找到一种方法来近似 softmax,以允许我们选择矩阵的计算顺序?
本质上,我们能找到一些矩阵Q’和K’使得
目标很容易理解,但是如何实现的细节有点复杂。
首先,让我们回忆一下,softmax 是一个函数,它给定一个长度为 n 的向量 z ,将所有元素归一化为:
鉴于此,请注意,我们可以将注意力等式中的 softmax 改写为:
其中 A 中的指数是按元素应用的, 1 _L 是长度为 L 的全 1 向量, D 是具有元素 A1 _L 的对角矩阵。 D 给出了 softmax 的分母(实际上, A1 _L 只是通过对的列求和而获得的长度为 L 的向量)
A ,它的元素指数,是这里真正的问题,所以我们的目标是以某种方式分解它。我们可以忽略标量分母 sqrt(d ),因为这只是用于规范化,但我们可以等效地规范化查询和键。这意味着我们的目标是找到一些Q’和K’使得:
通过高斯核寻找 Softmax 核
这就是内核发挥作用的地方。我们知道核是等价于某个特征映射φ的点积的函数:
通常,给定某个高维特征图φ,我们感兴趣的是找到一个等价函数 K,它将允许我们避免在φ的高维空间中进行计算。然而,在我们的例子中,我们实际上要走相反的路:如果我们假设 A 是一个包含元素 A ( i,j)=k(q_ I,k_ j)= exp(q _ I k_j^t)(其中 q_i 和k
现在,大多数核可以用以下形式的特征图来近似
其中 h 和 f₁,…,f_l 是一些确定性函数, w₁,…,w_m 是从分布 D 中抽取的随机值(所以φ( x 是一个具有 l x m 元素的向量)。【5】
一篇以前的论文已经证明我们可以通过使用配置获得高斯核:
也就是说,如果我们从均值为 0 且单位方差的正态分布中画出 w ,我们可以通过使用特征图获得高斯核:
注意,具有单位方差的高斯核由下式给出:
现在请记住,我们希望找到一个 softmax 内核:
我们可以看到 Softmax 核的结构与高斯核相差不远。事实证明,我们可以利用这种相似性找到 softmax 内核。事实上,请注意
这意味着我们实际上可以将 softmax 内核重写为
并且我们可以通过将 h 函数从 h ( x ) = 1 改为:
这是一个不错的近似值,但它有一些问题。softmax 函数总是输出正值,所以 A 的所有元素都应该是正的。然而,使用这个内核来近似 softmax 可能会给出一些负值。事实上,由于我们是从均值为 0 的正态分布中抽取 w ,这些值中的一些将是负的,这反过来意味着 A 的一些值将是负的。这会导致问题和异常行为。
寻找更稳定的 Softmax 内核
研究人员发现,softmax 内核也可以重写为:
(这实际上是 softmax 内核的证明可以在论文的附录中找到。)
因此,我们可以简单地从前面的功能图形式,并设置
通过这样做,我们可以看到所有的值都是正的,因为我们使用了 exp,因此解决了我们之前的问题。
作者还建议了另一个导致相同内核的特性图,如果你感兴趣,我推荐你阅读这篇论文。
使用 softmax 内核查找 Q '和 V '
让我们回顾一下。我们从注意力等式开始
发现我们可以把它改写成
然后我们找到了 softmax 内核的特性图,我们可以用它来近似矩阵 A :
所以我们现在可以使用特征映射替换 A 中的元素:
注意,我们是从长度为 L 的向量 q_k 移动到长度为 m 的向量φ( q _i)和φ( k _j)。
我们现在可以分解 Q' 和 K' 中的 A ,其中 Q' 和 K' 的元素为φ( q _i)和φ( k _j)。最后,我们可以自由地改变矩阵乘法的顺序,并将时间复杂度从 O( L d )降低到 O( Lmd ),从而获得序列长度的线性复杂度,而不是二次复杂度。
作者图片
我们完了。
结论和一些结束语
本质上,在本文中,作者设法找到了一种使用特征图的点积来近似 softmax 函数的方法。由于这一点,在变压器中计算注意力的时间复杂度可以从序列长度的平方减少到线性。在处理长序列时,这将显著提高转换器的速度。
需要注意一些有趣的事情:
- 虽然这种方法是在考虑变形器的情况下开发的,但它实际上可以应用于任何需要 softmax 的模型。看看这在哪里会变得有用将会很有趣。
- 作者指出,这种方法不仅速度更快,而且内存效率更高。这可以通过查看需要存储的矩阵的维数来看出。
参考
[1] Choromanski 等人《与表演者重新思考注意力》,2020 年 9 月 30 日
【2】Jay alam mar。《可视化一个神经机器翻译模型(带注意力的 Seq2seq 模型的力学)》,2018 年 5 月 9 日
【3】瓦斯瓦尼等人《注意力就是你所需要的一切》,2017 年 12 月 6 日
【4】杰伊·阿拉姆马。《图解变压器》,2018 年 6 月 27 日
【5】刘等,“核逼近的随机特征:算法、理论及超越的综述”,2020 年 7 月 4 日
觉得这个故事有帮助?考虑 订阅 到媒体扶持写手!
从。txt 文件到 d3.js 可视化
使用数据科学技术读取、清理非结构化数据,并将其转换为引人入胜的 web 可视化
几年前,IBM 指出,作为一名数据科学家,你可能必须经常遵守“80/20 法则”——你 80%的时间将用于简单地查找、清理和组织数据,只留下 20%的时间用于实际执行分析。
作为一名数据科学研究生,我的第一门课程只关注最初的 80%。有一项任务特别需要清理下面的文本文件,其中包含虚构国际象棋选手的“elo 评级”以及虚构国际象棋锦标赛的分数和点数:
模拟国际象棋“elo”评分和点数
太残忍了!我把这个文件的底部剪了下来,因为它很长,但是总共有 64 个玩家。
现在,你可能在想,我们能用这个做什么?这里有什么有趣的信息吗?我们将使用以下工作流程进行调查:
工作流程
从文本文件到 d3.js 可视化
将文本文件读入 R
我们要做的第一件事是。txt 文件并将其拉入 R。为此,我们可以使用基本的 R 函数paste()
和readLines()
:
library(stringr)
library(knitr)chess_data <- paste(readLines("https://raw.githubusercontent.com/zachalexander/data607_cunysps/master/Project1/chess_ratings.txt"), collapse = '\n')
正如您将从链接中看到的,我将文本文件保存在一个新的 GitHub 存储库中,并访问“Raw”选项,以便提取正确的文件。此外,我已经加载了用于处理文本的stringr()
和knitr()
包。
使用正则表达式处理文本文件
尽管我已经将文本文件放入 R 中,但是如果我检查我的变量“chess_data”并将其打印到控制台,您将会看到数据根本没有格式化:
将原始文本文件放入 R 中之后——处理之前。
幸运的是,如果您仔细观察,在这个文件中有一些微妙的模式,我们可以用它们通过正则表达式解析出关键信息。如果你需要温习正则表达式,我推荐这个资源。
首先,如果能得到玩家的名字就太好了。为此,我们可以结合使用str_extract_all()
函数和定制的正则表达式来隔离这些数据。我们可以看到球员的名字全部用大写字母列出,因此,我们可以通过运行以下语法提取他们:
player_names <- unlist(str_extract_all(chess_data, '([:upper:]+\\s[:upper:]+(\\s[:upper:]+)?(\\s[:upper:]+)?)'))# change to 'proper' case
player_names <- str_to_title(player_names)
head(player_names)
在上面语法的第二部分,我简单地将所有大写字母的名字转换成“正确的”形式。你可以看到印在上面控制台上的最终产品。我们现在有 64 个玩家名字的向量!就这么简单!
查看原始文本文件,我认为将玩家的原籍州、每个玩家的赛前 elo 评级以及每个玩家的赛后 elo 评级分离出来会很有趣。下面的正则表达式解决了这个问题:
# found that each player's state could be extracted through this regular expression combination
location <- unlist(str_extract_all(chess_data, '(\n)\\s\\s\\s[:upper:]+'))
location <- unlist(str_replace_all(location, '^\\s+|\\s+$', ""))# found that each player's pre-rating could be extracted through this regular expression combination
pre_rating <- unlist(str_extract_all(chess_data, '(R:)\\s{1,}\\d+'))
pre_rating <- unlist(str_replace_all(pre_rating, '(R:)\\s', ""))# found that each player's post-rating could be extracted through this regular expression combination (used later in data visualization)
post_rating <- unlist(str_extract_all(chess_data, '(->)(\\s{1,})?\\d+'))
post_rating <- unlist(str_replace_all(post_rating, '(->)(\\s)?', ""))
类似于隔离玩家名字,由于原始文本文件中的某些模式,上面的每一项都可以被隔离。
玩家结果-其他 R 函数
这些信息安全地存储在有组织的向量中。让我们评估一下我们现在所处的位置,以及我们希望收集哪些额外的信息来进行分析。下面用黄色突出显示的所有数据都已提取,用绿色突出显示的所有数据都是从该文本文件中获取的有用值——我们将在下一步中关注这些值。
我们目前在工作流程中的位置。
最初,我们可以看到每个玩家在锦标赛中的总点数包含带小数位的数字。为了分离这些值,我们可以根据这个字符序列提取所有值(见下文)。
然后,由于用绿色突出显示的其余数据在每一轮之间用“|”字符格式化,我们可以做一些操作来获取这些分数,继续利用我们的正则表达式。
# found that each player's total points could be extracted through this regular expression combination
total_points <- unlist(str_extract_all(chess_data, '(\\d\\.\\d)'))results <- unlist(str_extract_all(chess_data, '(\\d\\.\\d\\s{2}(\\|[:upper:]\\s{2}(\\s)?(\\s)?(\\d+)?){1,})'))
results <- unlist(str_replace(results, '\\d\\.\\d\\s{2}\\|', ''))
最后,我能够将每个玩家的这些值转换成一个临时数据帧,方法是使用 for 循环去掉多余的符号,并确保它们与我的初始向量中的玩家匹配。您可以看到下面的 for 循环过程:
*# used a for loop here to iterate over V1, using strsplit and the comma to separate out the opponent numbers into the appropriate columns. This also stored N/As in columns where a player didn't play an opponent.*
**for**(i **in** 1:7){
tempdf[, paste0('game', i)] <- sapply(strsplit(as.character(tempdf$V1),','), "[", i)
}
将这些数据与我的球员数据结合后,我们得到以下数据帧:
现在我们有所进展了!
如您所见,在 game1、game2…gameN 列中找到的数据对应于索引行号。既然我们已经有了这些信息,我想用与每个球员指数相对应的赛前评分来替换这些列中的指数会很有趣。如果我这样做是正确的,我就可以确定每个玩家的“时间表强度”!为此,我再次使用了 for 循环:
*# while iterating over the game columns, iterate over the player opponent number and match it with the opponent's pre-tournament elo rating. Then replace the opponent number with their elo rating.*
**for**(i **in** 6:12) {
**for**(j **in** 1:64) {
value <- chess_ratings_df[,i][j]
chess_ratings_df[,i][j] <- chess_ratings_df$player_pre_rating[value]
}
}
我们走吧!这是我们最后的数据帧,已经清理干净,可以进行分析了:
包含棋手信息的最终数据帧,从锦标赛中获得的总点数,以及他们面对的每个对手的预 elo 评级。
初步分析
给定这个数据框架,我感兴趣的是仅基于对手的赛前评级来确定哪个(哪些)玩家的锦标赛赛程最艰难。此外,从赛前到赛后,谁的 elo 评分上升幅度最大?
为了弄清楚这一点,我首先使用了rowMeans()
函数来计算七场锦标赛的对手赛前 elo 评分的平均值。然后我创建了一个名为average_opp_rating
的新列来存储每个玩家的计算结果。
chess_ratings_df$average_opp_rating <- round(rowMeans(chess_ratings_df[,6:12], na.rm = TRUE), digits = 0)
我还决定再创建几个专栏,以确定玩家赛前评级和赛后评级的差异(最终看谁的 elo 评级收益/损失最高)。此外,我还创建了一个专栏,讨论前后的评分差异是正还是负。
最后,我开发了一个相当全面的数据框架,可以回答我的许多问题。许多人会觉得这是令人满意的,大多数情况下确实如此。然而,如果我们把它可视化不是更有吸引力吗?
将数据导出到. csv 文件
准备好数据帧后,我可以用 R 中的以下语法将其导出为. csv 文件:
filename <- './../.../filepath'
write.csv(final_df, file = filename)
对于那些熟悉 d3.js 的人来说,有一个内置函数能够读取. csv 文件并遍历其中的行。然而,我更喜欢直接与。json 文件(只是我个人的喜好)。你可以快速使用免费的在线服务,如 csvjson.com 的来转换格式。
一旦准备好了,我就有一个可行的。json 文件:
我的 R 数据帧先转换成. csv 文件,然后转换成. json 文件的例子
使 d3.js 可视化
由于时间的原因,我将简单介绍一下制作 d3.js 可视化的大部分内容。然而,如果你对学习感兴趣,我会推荐这本书——交互式数据可视化——这真的是开始接触 d3 和 Javascript 的好指南!
用我的。json 文件准备好了,我可以接着做下面的事情:
- 使用 angular-cli 创建一个角度 2+项目。
- 创建一个 firebase 项目,并使用 firebase 部署我的 Angular 2+项目。这是一个很好的指南。
- 我创建一个组件,安装必要的模块,并开始构建我的可视化!
最后,我生成了一个条形图,显示每个玩家的赛前 elo 评级,然后您可以单击一个按钮来查看他们的 elo 评级根据赛后评级的变化。您也可以将鼠标指针置于初始栏上,查看赛前评级:
最终 d3.js 可视化——要查看最终产品,请前往https://zach-alexander.com/chess-elo
要看到完整的、互动的可视化,你可以去 https://www.zach-alexander.com/chess-elo 的。希望你会发现它很吸引人。您还会注意到,我创建了一个与该数据相关的模拟报纸故事——只是为了好玩!
说到底,尽管大多数人抱怨“80/20 法则”,但我们可以看到它对这样的任务是多么重要。到处都有有用的数据,但前提是你愿意花时间去处理它们!
从用户到价值创造
上的数据值
数据的使用及其如何创造价值
T 何第一个“首席数据官”是在近二十年前的 2002 年被任命的(当时她还是一名女性)。从那时起,大数据革命开始了,今天首席数据官的头衔在某种程度上是公司内数据专业人员的最高荣誉。
这个新职位在公司最高管理层的出现至少意味着对数据创造价值潜力的某种认可。这种价值创造是围绕数据生产和使用的若干战略和政策以及为数据管理和治理实施的手段的结果。
在这一系列文章中,我将尝试解释这几个策略和政策的原因,以及如何将它们结合起来,以便从数据中创造商业价值。
第一部分是关于数据的价值是什么,谁使用它,用于什么目的。第二部分将关注方法,以及如何通过数据管理和分析最大限度地创造价值。第三部分也是最后一部分将讨论谁做什么,以及 IT 业务团队在数据时代的角色变化&。
照片由 Riccardo Annandale 在 Unsplash 上拍摄
从数据中创造商业价值
当你让一个人描述数据的价值是什么时,对他们来说,你会自然而然地得到的第一个答案是数据有内在的市场价值,这意味着你实际上可以以给定的价格出售它。当数据是一家公司卖给其客户的产品时,情况确实如此。
但对于我们绝大多数人来说,对于核心业务不是卖数据的公司来说,数据的这种内在市场价值,只占从中要创造的潜在商业价值的一小部分。
对于这些公司来说,数据以某种方式“间接”创造了超出其市场价值的价值,这种价值创造可以以不同的方式转化,可以分为三类:
- 提高客户忠诚度,通过使用数据来提高服务质量,以更好地了解客户,识别模式,预测客户流失,从而避免失去客户,实施新的高附加值数据或报告服务(此处数据或多或少会直接货币化)
- 增加市场份额,通过增加与现有客户和新客户的活动,利用数据更好地了解市场及其演变,预测、预测甚至影响市场,从而改变市场
- 降低成本,通过使用数据来优化运营、提高生产率、更好地理解和构建产品、提高效率、自动化某些活动
如果您想从业务的角度定义公司数据计划的目标,处理业务案例,评估项目投资回报,设置优先级并指导路线图,那么充分理解这一点是至关重要的。
在本文中,我将只讨论公司、产品和服务以及市场价值(直接或间接)。数据也代表了科学的巨大价值,让我们更好地了解我们生活的世界,让医学更好地了解我们自己以及如何治愈我们。但是,即使目的不同(赚钱与理解宇宙和帮助人类),与数据的生产、使用和管理相关的实践和过程是相同的。
应用程序和用户是从数据中创造价值的基础
显然,我们没有等到计算机被发明出来才开始生产数据,并利用数据创造价值。然而今天,绝大多数数据都是通过计算机应用程序生成的。
事实上,计算机应用程序本质上是生成和处理数据的系统,其中数据被输入或摄取、存储、处理、可视化、分析等。
和/或分析,从而直接或间接参与从数据中创造价值。
从应用用户到价值创造
应用程序用户除了使用软件的功能外,还对其数据进行特定的使用。这种用法要么是操作性的(do),要么是分析性的(decide),有时两者都有(实际上越来越多)。
数据的运营使用与制造产品或提供服务有关,因此会对服务质量和卓越运营、效率和生产力产生影响。让我们看一个电子商务应用程序的例子:
- “客户-用户”的数据操作用途是访问公司提供的不同产品或服务的数据、它们的特征、它们的价格等。
- “操作员-用户”的数据操作用途是访问客户数据以处理订单。
数据的分析用途的主要目的是报告和/或分析以理解和预测,在从业务战略到员工日常决策的决策过程中起着至关重要的作用。可以是简单的报告或商业智能,以分析销售、客户(著名的 V360),了解导致特定情况的模式,如客户流失等。
在两者之间的边界,分析也可以直接集成到运营中,在现场和实时进行。警报功能就是一个很好的例子,它监控过程并在出现问题时警告操作人员,以便他能够做出决定并采取行动。
服务质量、卓越运营和决策:价值创造的三个关键驱动因素
正确理解用户对数据的操作和/或分析使用对于正确理解相关的价值创造至关重要,因为数据的使用方式将影响这种价值创造的三个关键驱动因素:
- 服务质量,满足客户并满足其需求的能力 : 在这里,数据及其使用方式会对客户满意度产生积极或消极的影响。例如,如果电子商务应用程序中的库存没有正确更新,客户下了订单,认为产品有库存,但他/她的订单因为实际上缺货而无法处理,他/她将不会满意。相反,对于电子商务网站来说,提供实时的库存可见性是客户满意度的一个重要标准。
- 卓越运营,做好工作的能力:在这里,数据的使用方式可以通过效率和生产率来衡量。比如,当某些发货信息缺失或错误时,产品无法发货,不得不重新安排发货时间(从公司的角度来看这是效率的缺失)。
- 决策,在正确的时间做出正确决定的能力:这里我们主要谈论的是对数据的“分析性”使用,即利用数据中的信息,做出符合事实的东西,通过分析相关性和因果关系来更好地了解情况,预测将会发生什么,从而决定要采取的行动。
卓越运营问题不一定会影响服务质量(效率损失会增加成本,但如果满足了要求,客户会很高兴),反之亦然。然而,糟糕的服务质量将意味着某个地方更经常地存在潜在的运营卓越问题。
总之,如上图所示,运营商、分析师、客户等使用数据的方式。影响服务质量、卓越运营和决策,这是从数据中创造商业价值的三个关键驱动因素。因此,充分理解数据的用途和为什么至关重要,这样才能最大化从中创造的相关商业价值。
感谢您的阅读,请让我知道您的想法,并毫不犹豫地分享。
从冯·诺依曼到记忆增强神经网络
直观的高层次概述
2014 年,两项并行的研究工作推出了记忆增强神经网络(MANNs):神经图灵机和记忆网络从那时起,他们扩展到了一个更广泛的主题,跨越了这些最初的实现。然而,我将坚持高层次的直观概述。这篇文章旨在将过去 7 年的研究浓缩成一篇 7 分钟的文章,去掉那些没有通过时间考验的特定于论文的术语和实现细节。
记忆增强神经网络(MANNs) 是冯诺依曼架构的可微分版本。n 通用存储器与模型参数的其余部分分开,并且与 RAM 类似,存储长期信息。
大象有惊人的记忆力。在一个例子中,23 年后,两只在一起表演的马戏团大象相遇时欢欣鼓舞。大象也认出了曾与它们相处数十年的人类。Tobias Adam 在 Unsplash 上拍摄的照片
传统的冯诺依曼架构区分了 CPU(中央处理器)和三级内存:寄存器 —非常快,但存储能力仅限于几个值;主存储器(例如 RAM)——速度更快,有足够的存储空间来容纳运行程序的指令和数据,以及外部存储器(例如硬盘)——速度较慢,但有空间存储计算机使用的几乎所有数据。
记忆增强神经网络(MANNs) 是冯诺依曼架构的可微分版本(下一节将详细介绍)。神经网络的主体可以被认为是 CPU。某些架构,如 RNNs(递归神经网络),具有类似于寄存器的内置存储器,存储短期信息。神经存储器与模型参数的其余部分分离,并且与 RAM 类似,存储长期信息。它由内存插槽阵列(即矩阵)组成,最常见的是存储信息的连续表示(文本、图像等)。)
神经记忆与外部世界的相互作用由控制器调节。图 1 中的 Graves 等人【1】
通过读写操作直接与神经存储器交互的组件称为控制器。在早期的工作中,控制器与模型的其余部分(即记忆之外的所有参数)相吻合,因此它充当了记忆与“外部世界”之间的接口。它通常被实现为一个递归神经网络。最近,随着基于变压器的大规模架构的出现,控制器只是该模型的一个小子集,并协调存储器与网络其余部分之间的通信。
什么是可区分的架构?
曼恩是可微分的,冯诺依曼架构不是——但这到底意味着什么?您可能还记得以下定义:
实变量的可微函数是其导数存在于其定义域内每一点的函数——维基百科。
实变量的函数的导数衡量函数值(输出值)对其自变量(输入值)变化的敏感度— 维基百科。
函数在特定点的导数。图片来自维基百科。
冯·诺依曼体系结构执行不可微运算。例如,考虑一个读操作:当 CPU 从 RAM 中取出下一条指令时,它指定一个地址(输入)并接收回一条指令(输出)。因此,输入域是无符号整数,所以运算不是在实数变量上定义的。根据上面的定义,微分是不可能的。
使操作可区分:软读取和写入
RAM 读取不可区分的核心原因是它们在离散的地址空间上操作。神经记忆提出了一种调整:
不是从单个条目中读取,而是从所有条目中执行加权读取。
对于每个存储槽 i ,控制器指定一个实值权重 wᵢ ,使得所有权重总和为 1。这将读取操作的输入从单个整数值(地址)改变为一个实数值的向量(每个插槽的权重),这是区分性的第一个要求。请注意,这个修改后的操作更加通用:当一个权重设置为 1.0,所有其他权重设置为 0.0 时,我们实际上是从一个条目中读取。同样的推理也适用于写操作:我们用一个加权值 wᵢ * x. 来更新每个条目 i ,而不是将值 x 写入单个内存槽
由于权重 wᵢ.的连续性质,这些操作被称为 软读和写这与硬读写 RAM 形成对比,在硬读写 RAM 时,控制器会对要操作的内存插槽做出硬决定。
计算软权重:基于内容与基于位置的寻址
RAM 的访问基于位置—读操作指定要读取的确切地址。神经存储器通常是基于内容来访问的——查询指定要读取什么,而不是从哪里读取。
控制器如何计算每个插槽的重量 wᵢ ?
首先,关于术语的说明:计算权重的机制 wᵢ 通常被称为内存寻址,因为它决定了哪些内存插槽被寻址,以及对每个插槽的关注程度。可以基于内容或位置对神经存储器进行寻址。
作者插图。
利用基于内容的寻址,权重 wᵢ 反映了槽 i 的内容在解析传入查询时的相关程度。例如,对于问答任务,内存查询可以是实际问题的嵌入。然后,控制器必须向上移动作为候选答案的内存插槽。最常见的是, wᵢ 是槽 i 中的内容嵌入和查询之间的点积或余弦相似性。最后,通过 softmax 对所有权重进行归一化,使其总和为 1。
利用**基于位置的寻址、、**,权重、反映了应该对位置 i 给予多少关注,而不管其内容如何。这种技术不太常见;它是由谷歌 DeepMind 的神经图灵机[1]在 2014 年推出的,然后在他们的 2016 年迭代 MANNs [3]中放弃了。最初的理由是,对于某些需要算术运算的任务,如添加两个变量 x 和 y ,重要的是控制器能够从内存中检索操作数 x 和 y 而不管它们的确切值。
降低计算成本:稀疏读写
使读取和写入可区分会带来计算成本。现在,每个查询都在线性时间 O(N) 内解决,其中 N 是内存槽的数量(相比之下,硬读取和写入需要常数 O(1) 时间)。当网络的输入是长度为 L 的序列(例如文本文档)时,通常对序列中的每个元素进行一次查询——这使得成本高达 O(NL)。训练时,软读写也是内存低效的;计算整个内存的梯度需要复制一份。*
后续研究集中在将 O(N) 成本降低到 O(log N) (Rae 等人【2】)或 O(sqrt N) (Lample 等人【4】)。虽然这两种方法非常不同,但它们的共同点是对内存的子集进行操作,而不是对所有条目进行操作。换句话说,他们将非零权重 wᵢ 的数量限制为一个小常数 k(介于 2 和 8 之间),并且仅在非零权重的槽上应用梯度下降。
当前事态
记忆增强的神经网络已经在人工任务(例如,它们学习将序列复制给定次数)、一些自然语言任务(问答、机器翻译)和一些计算机视觉任务(字符识别)中显示出有希望的结果。然而,它们尚未成为主流。在多个方向都有有趣的研究机会:降低它们的计算成本,加快训练速度,了解它们在什么情况下最有用,以及将它们与最先进的变压器集成。
参考
- 格雷夫斯等人,神经图灵机 (2014)
- Rae 等人,利用稀疏读写扩展记忆增强神经网络 (2016)
- 桑托罗等人,使用记忆增强神经网络的一次性学习 (2016)
- Lample 等人,带有产品密钥的大型存储层 (2019)
37 天内从零到全栈 web 开发
以及如何更快地完成它
乔恩·泰森在 Unsplash 上的照片
我是
西蒙。整整一年前,我完成了我的第一个 LinkedIn 学习 Python 课程。我这么做是因为它有市场,而不是因为我喜欢它。我不打算成为一名全栈式的 web 开发人员,或者任何类型的程序员。如果你问我,我宁愿做一个口袋妖怪训练师。
这是
我是如何在 37 天内学会所有技能,构建一个 web 应用程序并将其部署到现场的。我不能回答生活中所有的重大问题,也不能告诉你复活节彩蛋在哪里。然而,如果你是第一次、第一次或第二次尝试,这是一个可以帮助你做得更好的指南。
在线教程告诉你的太少了:他们给你代码,却没有告诉你任何东西的意思,或者警告你有错误。当出现问题时,StackOverflow 会告诉你太多:你必须仔细阅读那些告诉你所有事情的帖子,从如何与你的操作系统进行对话到 Linux 早餐吃了什么。
这就是我来这里的原因。我不会给你所有的代码或者解释如何把你的 Mac 变成汽车人。相反,我会带你了解你的项目应该如何进展,给你指出相关的资源,解释绝对的基础知识,并强调要避免的重要错误。以此作为时间表和补充资源,你应该比我用更少的时间就能拥有制作一个像我这样的 web 应用程序所需要的一切。
注意:我所做的最适合于动态网站(例如,与用户交互,执行功能,产生不同的输出)。如果你想制作静态网站(即拥有不变的内容,如文本和图像),这将是不值得的麻烦——选择 Wordpress 或 Squarespace 这样的网站建设者,以获得最佳投资回报。
Crackshort 的主页——作者图片
我建造了
Crackshort.co,一个使用技术指标回溯测试可定制交易策略的应用。外行:你选择一些股票,一些根据价格变动产生买卖信号的指标,一些管理交易的规则,然后用历史数据测试这个策略。
你可能不是为了营销信息而来的,所以我就不多说了,但是绝对欢迎你来看看这个 37 天项目的成果,也许还可以进行一两次回溯测试。现在,让我们进入你来的目的。
5 月 19 日,我完成了我的第一门 Django 课程——图片来自作者
接下来的一周,我创建了我的本地 Django 项目文件夹——作者图片
我在 6 月 23 日注册了数字海洋,并在两天后(第 37 天)发布了我的网络应用——图片由作者提供
内容
如果链接没有按预期工作,请在新标签中打开它们
- 堆栈
- 视力
- 流程
- 本地构建:让它在你的计算机上工作
- 骨架站点:用 Django 创建基本结构
- App-ify:把静态网站变成一个带 I/O 的 App
- 美化:做设计和前端工作
- 部署:将其连接到互联网
- 更新:维护一个可靠的更新过程
1.堆
在这 37 天的开始,我对 Python 的基础很熟悉,也就是说,我可以编写函数,使用字典,进行文件输入/输出,使用导入的库,等等。我对 Mac 终端也有一点的接触,即我可以使用 cd 、 ls 、 pip 命令。这在以后变得非常重要。
在那之前,我一直专注于在 Jupyter 中做数据分析,所以对 pandas 和 numpy 很熟悉。后一点并不是 web 开发的先决条件,但对于我的项目来说是非常必要的。
我也曾在大约 4 年前的一个在线课程中尝试过 HTML/CSS。这几乎没用,但我相信它确实给了我一点点提升前端学习曲线的动力。不然我就有了零前端经验。
我用的堆栈。徽标属于各自的创作者。
我学会使用的栈如下,从后端到前端(左上右下):
- 后端 IaaS: 数字海洋
- 后端操作系统: Ubuntu Linux
- 后端数据库: PostgreSQL
- 后端语言: Python + Django
- 后端服务器: NGINX + Gunicorn
- 前端:Bootstrap+HTML/CSS/JavaScript
- 其他资源/工具:终端(用于部署期间的编码和 Git)name cheap(用于域名)LinkedIn Learning+stack overflow(用于字面上的一切) Git + Github (SCM,或源代码管理)
提醒一下——这是一个非常实用的演练,所以我不会详细解释每个工具的概念和基本原理。实际上我对他们中的大部分一无所知,仅仅足以让一个网站工作。
2.视力
该应用的愿景是:创建一个模块化回溯测试引擎,允许用户:1)选择一个回溯测试领域(股票和日期范围),2)选择最多 2 个技术指标,3)定义这些指标和止损规则之间的关系,4)选择如何确定每笔交易的规模,5)运行回溯测试,并生成策略结果和一些指标。
应用程序工作流程-按作者分类的图片
该网站的愿景是:制作一个网站,接受用户输入,通过执行计算的 Python 应用和输出一些输出,然后在相同的网页上传递这些输出。
这一愿景告诉我们,我们需要一个独立的 Python 应用程序,它使用单个命令运行并返回单个结果,还需要一个交互式动态网站,它允许用户通过表单输入值。
3.过程
下面是我的过程概述。我犯的主要错误,其中一些花费了我很多时间,用斜体表示。
- 在本地用 Python 构建应用程序
- 用 Django 创建静态网站
- 实现应用程序的输入和输出系统
- 开始使用 Git 进行版本控制
- 美化前端
- 通过 AWS 部署(失败)
- 迁移到 PostgreSQL
- 通过数字海洋部署
- 创建应用程序更新流程并运行多次更新
如果我再做一次,我会遵循以下工作流程:
- 本地构建:从一开始就使用 Git/Github 在本地用 Python 构建应用程序
- 骨架站点:用 Django 创建静态网站,迁移到 PostgreSQL
- App-ify :实现 App 的输入输出系统
- 美化:学习 HTML/CSS/JS,美化前端
- 部署/更新:使用数字海洋,仅在必要时更新
现在,我将更详细地解释理想的工作流程以及如何避免我所犯的错误。
4.本地构建:让它在您的计算机上工作
你需要:
Python,Git/Github,终端(基本)
请参考:
结果:
可以在文本编辑器中运行的应用程序
时间线:
第 0 天
这是您运用基本 Python 技能的地方。在开始创建网站之前,我已经花了很多周的时间来规划、构建和构建本地应用程序,因为就我的技能水平而言,这是一个大项目。
回溯测试平台的功能类似于交易实践的射击场——当用户走进来时,他们可以定义他们的目标(股票),定制他们武器的部分(策略)并选择载入什么(指标)。因此,该应用程序需要有一个预定义的策略,指标和规模方法目录,用户可以从中选择。Backtrader 库提供了应用程序的主要基础设施,交互式经纪人 API (IBPy)最初提供了数据。后来,我改用了 IEX 云 API,因为 IBPy 在本地连接到我的 IB Trader 工作站软件,不能在线工作。
成功运行的应用程序的后期版本——图片由作者提供
我在 Jupyter 笔记本中开发了整个项目,这有点不方便,因为所有的脚本后来都必须转换成。py 文件,然后才能作为 web 应用程序的一部分运行。话虽如此,我还是推荐。对于那些没有尝试过 Jupyter 的人来说,它允许您运行和调试组织到单元中的单独代码,而不是一次运行整个脚本。这对于像我这样经常出错的低技能编码人员以及必须处理大量数据的脚本来说非常有帮助。
饭桶
我很晚才知道,但是使用 GIT/GITHUB。如果你像我一样自学成才,很有可能没人把 Git 塞到你脸上,所以我来做这个荣誉。作为初学者,以下是您需要知道的所有内容:
- SCM 是版本控制软件,Git 是 SCM。
- 简单地说,Git 存储库是一种存储设备,在做了一些更改后,您可以偶尔发送(“推送”)代码文件。
- SCM 跟踪每一次上传(“提交”),所以如果你想的话,你可以回到以前的版本。
- 如果你和其他人一起工作,你也可以从 repo 下载(“克隆”)整个项目,或者从 repo 获得(“拉”)一个更新的版本来覆盖你的本地文件。
- 如果你正在构建一个大的新特性,在一个“分支”上进行编码,这样就不会影响到项目其余部分所在的“主”上,然后在特性准备好的时候将两者“合并”。
Github 是一个在线 Git 回购平台。使用 Git 或 Github 很重要,因为它让你和你的项目有条理——当我开始使用它时,我已经进入了 web 开发阶段,但它让我安心地知道我的更改正在被跟踪,并帮助我从里程碑的角度思考我的进展。此外,一旦你的应用上线,更新它是至关重要的——稍后将详细介绍。如果你还没有,开始使用 Git/Github ( 阅读这里的教程文档,或者阅读罗杰·杜德勒的这份入门指南)。
- 如果你有一个现有的项目,你想推送到一个新的 Github repo:不要添加许可证和自述文件到它上面;在您第一次推进项目后添加它们。它们一开始并不在你的本地项目中,所以如果你试图把你的文件推上来,你会遇到一个错误(见 StackOverflow )。
最终,我把这个项目分成几个部分。py 文件,创建了一堆自定义类,并使应用程序工作。该应用程序的最终结构如下:
粗略的项目结构—作者提供的图片
此时,我可以将输入定义为 FiringRange.py 中的变量,并调用 fire()来运行整个回溯测试,这将在 print()中返回结果。
5.骨架网站:用 Django 创建基本结构
你需要:
Django (basic),PostgreSQL (basic)
请参考:
Django 文档、、LinkedIn 上的“学习 Django”、、LinkedIn 上的“建立个人投资组合”
结果:
一个“网站”,你可以从你的本地主机运行,有一个 PostgreSQL 数据库
时间线:
第 1 天—第 4 天
Django 是一个用 Python 编写的全栈库,它使得创建一个网站结构变得非常快速和容易,如果你完全按照这个过程来做的话。我强烈推荐它,并强烈推荐这个 LinkedIn 学习路径,它包含了整个构建过程中我需要的所有基础知识和工具。Django 的课程无处不在,大多数都能达到目的,但是无论你选择哪一个,都要密切关注,因为有一些小的、容易被忽略的细节会使整个项目停顿下来。
同样,我不会教你 Django,因为这些课程做得更好,但当你参加这些课程时,请确保你特别注意URLs . py、views.py 和模板如何相互关联、如何配置 settings.py、和如何使用 manage.py 访问数据库、运行本地主机和组织静态文件。
因为 Django 的组件是如此错综复杂地联系在一起并且相互依赖,所以您需要有这个基本的图片来避免可能破坏整个链的小错误(例如,视图名称中的输入错误)(例如,URL 找不到要调用的视图)。Settings.py 在部署期间变得特别重要。这里有一个使用我的网站的两个页面的快速概述,动态回溯测试页面(链接到应用程序)和静态关于页面。
我的 Django 项目的基本流程。在这个阶段,你还不需要担心应用程序(firing range . py)——图片由作者提供
有了这个基础,开始你的项目。
- 在您的项目中创建应用程序
- 创建基本的网址:如主页,回测页面,关于页面。
- 创建调用相应模板的基本视图
- 创建仅包含一些占位符 html 文本的模板
- 运行服务器并在浏览器中转到 localhost
准系统代码
您将获得什么—按作者分类的图像
数据库
现在考虑数据库是很重要的,因为它以后会节省你的时间和脑细胞。这很重要,我为这部分做了个标题。
Django 默认使用 SQLite。然而,在生产中(当你的网站上线时),你最终会使用 MySQL 或 PostgreSQL。我使用 PostgreSQL 的原因是:
- 它被用在 LinkedIn 学习课程中
- 它成功了(实际上并不容易——继续读下去)
为了更好地解释数字海洋的数据库选择,请点击这里。更重要的是,当我尝试用 AWS 部署时,我遇到了很多数据库问题,首先是 SQLite,然后是 PostgreSQL ,这最终让我彻底放弃了 AWS。PostgreSQL 和 DigitalOcean 一起工作,所以我坚持使用它。
知道了这一点,我会在这个阶段将我的 Django 项目迁移到 PostgreSQL,而不是在我已经创建了实例和模型之后,我需要额外的步骤来移动。
- SQLite-AWS 问题:AWS Elastic Beanstalk 虚拟机无法找到 Django 所需的 SQLite 版本,我对此无能为力(参见 StackOverflow )
- PostgreSQL-AWS 问题:AWS Elastic Beanstalk 虚拟机首先无法安装 psycopg2,因为它找不到 pg_config ( 参见 StackOverflow ),然后当我安装它时,它找不到 psycopg2
- 对于 Mac 用户:PostgreSQL 需要 psycopg2。psycopg2 需要 pg_config。如果您试图用 pip 安装 psycopg2,pg_config 会阻止您。这个 StackOverflow 页面有所有的答案,但是对我来说最快的解决方法是自制(在答案列表中向下滚动一点)
- 如果你已经有了 SQLite 数据库,现在想转移到 PostgreSQL(像我一样):这个 Github 要点是你需要的神奇修复。
相信我的话,如果你认为 PostgreSQL 是对的,现在就迁移你的项目。为此,遵循 DjangoGirls 教程或 LinkedIn 学习 Django 路径中的建立个人投资组合课程。LinkedIn 课程更详细地介绍了 PostgreSQL。
6.App-ify:把静态网站变成有 I/O 的 App
你需要:
Django(中级;模型、表单、POST/GET 请求)
请参考:
Django 模型文档, Django 表单文档, Django 模板文档,LinkedIn 上的“Django:表单”
结果:
本地“网站”的形式,传递输入到一个应用程序,并显示输出
时间线:
第 5 天—第 14 天
静态网站结构完成后,我们将插入 Python 应用程序并为网站提供 I/O。这将使您深入 Django 领域,所以请准备好花大量时间学习 Django 文档和课程。
在我们现有的 Django 生态系统中,我们需要实现模型和表单:
- 我们输入变量的模型(策略、指标、尺寸)
- 一个输入模型,它定义了每个回溯测试的所有输入——它将有与上述模型链接的策略、指标和大小字段
- 我们的用户将填写的模型表单,其中表单字段对应于输入模型
- 保存回溯测试结果的输出模型
模型是保存在数据库中的数据表;模型中的每一列都是一个数据字段,每一行都是模型的一个实例。然后,这些模型可以与外键相链接。同样,在线课程将很好地解释基础知识,但这里是我的模型如何相互关联。
关系数据库—作者图片
上面,输入模型将策略、指标和 Sizer 模型实例作为其字段的输入。回溯测试 ID 是分配给每组输入的任意数字。在应用程序返回一组输出后,输出以相同的 ID 保存在数据库中,这样每组输出都可以追溯到用户的输入。
下面是这些模型如何与表单和我们现有的 Django 工作流的其余部分相关联。
来回传递表单—作者的图像
视图-模板关系看起来很复杂,但这仅仅是因为我特别想在表单本身所在的页面上显示回溯测试的结果。更详细地说:
- 回溯测试视图调用网页模板首先为用户呈现一个空表单
- 当用户点击“提交”时,网页通过 POST 请求将输入发送到 Backtest 视图(一种处理数据的 HTTP 方法,更多信息请点击
- Backtest 视图检查它是否是有效的 POST 请求,将其保存到输入模型,然后将其发送到 FiringRange.py 应用程序
- 回溯测试视图接收输出,将其保存到输出模型,并将其发送回同一个网页模板
- 如果收到结果,网页模板被告知不要重置表单,并在指定的空间显示输出
如果您希望输出显示在不同的页面上,POST 请求将被发送到不同的视图,这将呈现不同的“结果”模板,但过程是相同的。这是我做的:
用户第一次进入时的新表单—按作者排序的图像
用户提交表单后出现输出—作者提供的图像
当然,这是已经 CSSed 的版本。我在这个阶段混合了很多前端工作,因为我没有耐心,但是我会建议不要这样做,因为必须同时学习 HTML/CSS 和 Django 会大大降低我的速度。
你的网站应该是这样的。资料来源:熊伟·弗雷塔斯
此外,我还实现了一个结果页面和一个编辑特性。如果用户点击“详细结果”按钮,他们将被定向到一个单独的页面,其中包含使用散景为他们刚刚运行的回溯测试生成的图表。在这个结果页面的底部有一个“编辑回溯测试”按钮,如果用户想要返回并对这个特定的运行进行更改。
特定回溯测试运行的结果页面-作者图片
如果用户点击“编辑”,回溯测试视图再次被调用,并给出用户想要编辑的回溯测试的 ID。回溯测试视图在输入数据库中找到该特定 ID 的输入,并再次呈现回溯测试模板,但是这一次,将这些输入输入到表单中,而不是显示一个新的表单。**
编辑功能-按作者分类的图像
这是我的回溯测试视图最终的样子:
****7。美化:做设计和前端工作
你需要:
Django,引导程序,HTML/CSS/JS
请参考:
LinkedIn 上的引导文档(示例)、“建立个人投资组合”
结果:
一个好看的,带互动 JavaScript 的本地品牌网站
时间线:
第 15 天—第 24 天
取决于你喜欢什么,这可能是最痛苦或最不痛苦的阶段。我不会在这里阐述太多,因为不会有太多问题,当涉及到美学时,我们都有不同的优先考虑。
我建议看一下引导演示(上面的链接),选择一两个,打开页面源代码,将整个 HTML 文档复制到你的模板中。这是让你的网站看起来像样并给它一些结构的最快方法,这个过程在“建立个人作品集”课程中有很好的解释。
我用 Bootstrap 的封面作为我的主页,Navbar 为我的其余页面进行了修复。使用 Django 的“extends”标签,我制作了一个包含 Navbar、通用 CSS 属性和一个空“block”的“base”模板,然后简单地将它应用到我的每个模板中。这是我非常简单的关于页面。
****Bootstrap 的卡片(见上例)和网格也很有帮助。卡片使得对内容进行分组和格式化变得非常容易,网格系统使得整个页面布局变得非常快速。
我花了大部分时间在回溯测试输入表单的前端工作。我使用 Django 脆皮形式来快速使它看起来更好——见熊伟·弗雷塔斯的教程。然后,我开始使用 Javascript 和 JQuery 使表单具有响应性。
输入示例 1:使用止损,只有一个指标—作者图片
首先,我需要表单根据用户的策略选择来显示/隐藏止损和指标字段。其次,我需要指标的参数字段来显示/隐藏和更改它们的标题,以告诉用户他们选择的指标需要什么参数。参考上面和下面的例子来看看这些变化。
输入示例 2:无止损,使用两个指标—作者图片
对于这些特性,我基本上必须学习基本的 Javascript 和 JQuery 语法,我并不期望深入其中,但我会指出来,以便您做好心理准备。让策略和使用止损字段分别显示/隐藏指标和止损字段相对容易。
上面的代码将事件处理程序附加到文档中的“usestops”和“strategy”元素,这些事件处理程序检查它们的输入是否已被更改为某些值,并相应地显示/隐藏其他元素。使用这个 on()处理程序(在这里了解更多信息)证明比另一个常用的 JQuery 方法document ready())好得多。见下文。
****Ready()仅在文档对象模型(DOM)准备好用于 JavaScript 时运行一次,而 on()随时跟踪事件。Ready()对大多数页面都适用,但对我的页面不适用,因为我的表单可以被访问:
- 当用户第一次加载回测页面时
- 用户点击“提交”后,结果出现在旁边
- 在用户点击“编辑”并返回回测页面后
在第二种情况下,文档不会重新加载并再次准备好。
参数字段的更改实现起来要繁琐得多,我就不赘述了,因为您可能不需要这样做,但要点是:
- ****在我的指标模型中增加了字段,为每个指标指定:多少个参数,调用哪些参数,参数的默认值
- 在我的回溯测试视图中增加了一个功能,即获取指标模型中的所有对象,使用 json.dumps()和 DjangoJSONEncoder 将其打包到 JSON** 中,然后**将其发送到回溯测试模板****
- 将 JS/JQuery 添加到我的回溯测试模板中,解析 JSON** 以获取指标信息,并使用 more on()方法,检查用户对指标的选择,以相应地显示、隐藏和覆盖表单的参数字段**
品牌宣传
****最后,烙印。在项目的这一点上,这可能不是你的首要任务,因为你的网站还没有上线,但我还是建议你这么做,因为最终确定网站名称和标志意味着你不必在以后对 CSS 做大的改动,你锁定一个域名。
我对域名搜索所花费的时间以及它对我品牌选择的限制程度感到惊讶,但由于我有一些品牌设计和开发的经验,这并没有造成太大的问题。如果你不知道,这里有一个 2 分钟的品牌速成班:
****头脑风暴网站名称。Crackshort 以“射击场”开始,因为我用这个比喻来弄清楚如何使这个回溯测试引擎完全模块化,所以我想用这个想法。我列出了 40 多个名字(当然大部分都是垃圾)。
品牌名称的其他想法:你自己的名字(哈利剃刀,著名的阿莫斯饼干,JP 摩根),主要功能(Suitsupply,脸书),一个形容词(Gamefreak),一个地方(每家报纸,大学和熟食店),真实单词(Twitter,Medium,Crunchyroll),杜撰单词(Zapier,Trello),双关语(Crackshort)
****检查域。由于域名的可用性,我的列表缩小到了‘marks mind’,‘Boolsai’(因为 bulls.ai 可能很酷,但已经有人用了),‘Tryfire’,‘Stracer’,‘Tincker’,‘triffy’和‘crack short’。你知道我选了什么。如果你是游戏,现在购买域名给你额外的踢完成这个项目。
超级配色方案—作者图片
****做一个配色。这有助于标识,你可以马上将它们插入到你的基本 CSS 中。良好的做法是有一个良好的明暗范围,并侧重于两个主要的对比色-我的是橙色(中心)和海军蓝(右)。在某处记下这些颜色的 RGB/hex 代码,以便参考。
比较金融/交易/教育领域的品牌(Crackshort 在中间)。各自创作者的徽标
****为徽标进行头脑风暴/情绪板。徽标可以大致分为文字型和图片型。组合也可以。文字徽标更快(只需选择一种字体并键入名称),但表达性和记忆性较差。如果你选择文字,至少要做一个“完整”版本和一个“缩略图”版本(就像上面 Quantopian 的 Q)。
我选择制作一个带有矢量插图风格的图形标志,以便在金融/交易/教育领域脱颖而出,我觉得在这个领域,品牌一直是文本化的和“安全的”,经常出现图表或烛台之类的图像(Quantopian 除外)。虽然我的网站的事物是整个射击场的隐喻,但我不想将这个品牌与突击步枪和子弹联系起来,所以我选择了左轮手枪枪膛的图像,而噱头将是一个切除的部分,使它看起来像一个 c。
Photoshopping 作者图片
最终—作者提供的图像
活动中的收藏夹图标—作者提供的图片
****最后,加上你的配色方案,把它放到你的网站上,你就可以开始了。如果你做了一个 favicon,这是一个出现在浏览器标签中的小东西,你会得到加分。最简单的方法是将你的标志图像放入一个 favicon 生成器以获得一个 ICO 文件,然后将一个<链接>标签放入你的 HTML <头>中。如果您复制了一个 Bootstrap 模板,那么应该已经有一个 favicon 部分,您可以在其中替换代码,如下所示。不要忘记运行 collectstatic 来获取您的。静态文件夹中的 ico 文件。
Bootstrap 的默认中的 Favicon 代码—用 wherever your。ico 文件是—作者提供的图像
8.部署:将其连接到互联网
你需要:
数字海洋,终端(基本)
请参考:
结果:
一个实时网站(在一个定制的 IP 地址上,或者更好,在你的域名上)
时间线:
第 25 天—第 33 天
部署阶段很可能是最痛苦的一步,因为可能会出现无数的问题。如果你有一个非常简单的单页应用程序,如果你仔细遵循每一步,你应该没问题。如果你的应用程序很复杂,有很多依赖,祈祷星星排成一行。
从我对选项的一点点了解来看,如果你想要最少的步骤,就选 Heroku ( 姜戈女孩教程)。如果你想要最便宜的,就用 AWS 弹性豆茎** ( AWS EB 教程)。如果你想要最实际的,就用数字海洋 ( 数字海洋教程)。为了更深入的比较,阅读这个顺时针方向的软件帖子。请注意,这里的动手并不意味着乏味,它意味着当出现问题时,很可能是你的错,因此可以由你来解决。**
我第一次尝试使用 AWS EB first,由于数据库遇到了障碍。如果您之前错过了数据库部分,以下是主要部分:
- SQLite-AWS 问题:AWS Elastic Beanstalk 虚拟机无法找到 Django 所需的 SQLite 版本,我对此无能为力(参见 StackOverflow )
- PostgreSQL-AWS 问题:AWS Elastic Beanstalk 虚拟机首先无法安装 psycopg2,因为它找不到 pg_config ( 参见 StackOverflow ),然后当我安装它时,它找不到 psycopg2
- 对于 Mac 用户:PostgreSQL 需要 psycopg2。psycopg2 需要 pg_config。如果您试图用 pip 安装 psycopg2,pg_config 会阻止您。这个 StackOverflow 页面有所有的答案,但是对我来说最快的解决方法是自制(在答案列表中向下滚动一点)
- 如果你已经有了 SQLite 数据库,现在想转移到 PostgreSQL(像我一样):这个 Github 要点是你需要的神奇修复。
另外,即使我在 EB 设置中选择了 Python 3.7,它也一直回到 3.6。AWS 有一套强大的服务,但在初始化、破坏和终止无数环境和应用后,我决定减少损失。然而,脱离生态系统比进入生态系统要困难得多——如果你想在尝试过 AWS 之后断开它,请确保你查看了你的帐户的账单部分,并手动终止你在每个 AWS 服务中运行的每个对象/实例/进程。****
去数字海洋。我按照 LinkedIn 的教程(在‘参考’中),几乎没有问题。在 DigitalOcean 上,你在他们的服务器上创建你自己的 Linux 虚拟机,就像一台远程控制的计算机——你上传你的项目文件,然后使用终端命令,配置和部署。如果你是一个像我一样的 Mac 用户,你会感觉像是在做你已经在这个项目中做过的事情,但是是通过终端。对我来说,这比学习亚马逊的 EB 语法和阅读数百行日志来找出代码出错的地方要直观得多。
当然没有完美的过程。在 DigitalOcean 中也出现了 psycopg2 问题,但这次因为我拥有了对虚拟机的完全控制,一个简单的 sudo 安装 ( 参考这篇 StackOverflow 帖子中的顶部答案)让我获得了继续 Postgres 所需的软件包。另请注意 DigitalOcean 根据未知标准要求一些新用户进行身份验证。我不得不上传 ID 和一张自己的照片,这是一个烦恼,但批准在分钟内给予。
DigitalOcean 需要你自己配置 Gunicorn 和 NGINX,但是步骤很简单,在上面链接的 DigitalOcean Django 教程中有解释。除了知道 Gunicorn 是一个 WSGI 服务器,NGINX 是一个 web 服务器之外,你不需要知道任何关于它们的信息(阅读这个可以快速了解一下),但是如果你感兴趣的话,你可以阅读他们的文档。
****关于自定义域名:在这一点上,我还没有购买域名,因为我很便宜,但如果你这样做了,你就不用在应用程序上线后更新新的域名了。我在廉价网上买的,因为 Crackshort.co 和。我查过的其他网站(Google domains,GoDaddy,Name.com)都比这里便宜。
此外,如果你想保护你的品牌,或确保用户不会拼错你的网址,并最终在其他地方,购买多个域名,并重定向到另一个。我买了 Crackshort.co 和 Crackshort.com,因为我喜欢的声音。co 但是。com 仍然是最受欢迎的。
廉价主机记录设置(我的 IP 编辑)——来自 Namecheap.com 的截图
一旦你购买了你的域名,你必须进入 DNS 设置,如上所述,并创建主机记录,将“@”和“www”主机(即 https://crackshort.co 的和 https://www.crackshort.co)指向你的网站(如果是 DigitalOcean,是 Droplet 的)IP 地址。
最后,一定要设置 SSL 认证(外行:把你的‘http’改成‘https’),因为这在当今互联网基本是必须的。对于 DigitalOcean/Ubuntu/NGINX 堆栈,您拥有 shell 访问和超级用户(sudo)权限,因此使用 Certbot 获得 SSL 非常简单。否则,大多数主机提供商提供 SSL 证书(对于 Namecheap 来说,这是额外的费用)。
看到左上角那个胜利的 https 了吗?—作者图片
9.更新:维护一个可靠的更新过程
你需要:
数字海洋,Django,Git,谷歌
请参考:
结果:
一个实时网站,您可以随时更新
时间线:
第 34 天—第 37 天
Crackshort.co 正在直播。现在你会认为一切都结束了,但事实并非如此。有几件事你需要考虑。
首先也是最重要的,版权/copyleft 。如果你在你的应用程序中使用了开源代码(如果你照着做的话,你肯定会这么做),在那些库上搜索许可证。在 Github repos 中,这在 About 部分和许可证文件中非常明显。大多数开源代码都在 GPL 许可下,但我不会在这里提供法律建议,所以看看你所使用的是否需要你提供信用或公开你的源代码。这里有一个 GNU 的快速解释。
更新过程
****二、如何更新你的 app。我在网上找到的关于这方面的资源很少,但是这个过程的重要性不可低估。这是 DigitalOcean 用户感到困惑的地方,但对 AWS EB 来说并非如此。后者,后端工作打理;在对项目做了一些更改并提交给 Git 之后,您所要做的就是从终端运行一个“eb deploy”命令。
如果你在 DigitalOcean 上,后端工作是你的问题,这是你有纪律地推进 Github 得到回报的地方。参考“参考”中链接的 StackOverflow 帖子。基本流程是:
- 为本地调试配置 settings.py
- 对您的项目进行更改
- 进行迁移:运行python manage . py make migrations
- 为实时部署重新配置您的设置
- 将项目提交给本地 Git,并将推送到远程 Github repo
- 使用 ssh 命令登录您的数字海洋虚拟机
- 激活您的项目所使用的虚拟环境
- cd 到您的项目目录中,并从 Github repo 中拉出**
- 迁移:运行 python manage.py 迁移
- 静态:运行python manage . py collect static
- 重启 Gunicorn 服务器:运行 sudo 服务 gunicorn 重启
补遗:
-
你可以用 Fabric 或 Ansible 来自动化这整个过程,但这不是我的专长,如果你不经常更新,你也不需要这样做
-
如果你在设置中设置一个自定义变量,你的生活会变得更轻松。像这样在本地和实时配置之间切换:
-
建议在本地进行迁移,但是在服务器上迁移,因为迁移是源代码的一部分,不应该在服务器上被篡改;确保本地数据库和服务器数据库相同
-
即使在这次更新中没有创建新的静态文件,也只需运行 collectstatic,因为您可能会忘记
-
一旦完成更新,您不需要重启 NGINX,因为没有对 web 服务器做任何更改,只是对应用程序做了更改(由 WSGI 服务器负责)
因为有这么多的移动部件,而我对每件事都知道得很少,所以我保留了一个. txt,在那里我为自己列出了这些说明。
货币铸造
你没有白白地花 37 天,但是如果你想要除了你妈妈之外的任何流量,你需要让你的网站在谷歌上被索引。在谷歌搜索框中输入“site:yoursite.com ”,看看它是否被索引了。在谷歌搜索控制台上创建一个账户,并按照设置说明进行操作。在这里,您将获得关于您的网站是否被索引和在搜索中排名的基本信息。
要“请求”索引,你应该给谷歌你的网站地图。Django 让创建一个网站地图变得非常简单——阅读网站地图文档或跟随本教程。请注意,您需要在 Django 项目中设置站点地图和站点应用程序— 如果没有站点,您生成的站点地图将不会链接到您的域(您将得到一个包含“example.com”的 XML 文件,其中应该包含您的域)。
你的站点地图 XML 应该是什么样子——作者图片
完成后,将您的 sitemap.xml URL 上传到 Sitemaps 下的搜索控制台,然后等待。之后,谷歌至少需要几天时间来发现和索引你的网站,所以你需要耐心。一旦你被编入索引,有很多方法可以让你的网站在搜索中排名更高,但我还是不会深入讨论,因为相关的资源非常丰富。
在等待的时候,建立一个谷歌分析账户。你需要将谷歌的标签代码添加到你的页面中,但这是值得的,因为你将获得访问者的详细信息,以及他们是如何访问你的网站的。
除了在谷歌搜索中上市,不要忘记其他营销平台,如社交媒体广告和产品搜索。如果你在社交媒体上做广告,一定要小心,不要让你的网站在我的手机浏览器上发疯。
谁会在手机上回测交易策略呢?—作者图片
有几种方法可以开始用你的网站赚钱。最直接的是 Google AdSense ,Google 读取你网站上的内容并自动附上相关广告。然而,这最适合博客;如果你的网站是我这样的 app,上面不会有太多内容,Google AdSense 会拒绝你。
您可以研究的其他方法有:
- 创建付费墙
- 让它免费增值
- 销售其他产品(电子书或附属产品)
- 直接在市场上销售广告空间(但大多数时候你需要经过验证的流量来赚钱)
- 靠快乐用户的捐赠过活
- 或者写一篇 6000 字的博客,希望你能从纽约的早餐车上赚到足够买一小杯咖啡的钱
关于页面的准确性—作者提供的图像
结论
如果你在这里成功了,你现在要么是一个全新网站的所有者,要么是我的女朋友。感谢你参加我的 37 天快速跑,我希望你能学到一些东西,让你从零筹码到满筹码的旅程比我的旅程更轻松、更愉快。
也就是说,很少有什么事情比看到你的应用被人们使用更令人满足的了。找个时间到 Crackshort.co 来喝杯咖啡吧(你请客)。
主要参考文献
- 课程/教程:成为 Django 开发者(LinkedIn Learning)在数字海洋上部署 Django
- Docs: Git , Django , Bootstrap
- stack overflow:SQLite-AWS 版本控制, PostgreSQL-AWS psycopg2 ,用 pip 安装 psycopg 2,移动 Django 数据库,更新应用