TowardsDataScience-博客中文翻译-2020-十三-
TowardsDataScience 博客中文翻译 2020(十三)
人工智能失控——构建人工智能产品的商业和声誉风险

照片由 Ayaz Lalani 在 Unsplash 上拍摄
人工智能系统会带来巨大的业务和声誉风险,管理这些风险是推动长期收入的关键
在过去的几年里,人工智能已经从实验和概念验证转移到创收应用。随着超过 45%的大型公司和 29%的中小型企业采用人工智能[1],人工智能将很快成为许多公司的核心部分。
虽然构建人工智能产品的好处是不可否认的,但它也不是没有风险,如果管理不当,最终可能会非常昂贵。
随着越来越多的公司现在将人工智能作为创收机会,强调人工智能产品所涉及的风险以及它们变得流氓的后果是很重要的。
“耍流氓”是什么意思?
考虑人工智能的一个好方法是将其视为一个自动决策系统。数据被输入系统,并根据这些输入做出预测或决策。建立一个人工智能模型仅仅意味着在给定当时可用的信息的情况下,尽可能准确地做出自动化决策。
当一个人工智能系统的行为不符合你的预期时,它可以被定义为失控。
人工智能系统的行为通常根据它们在给定任务中的准确度来量化。虽然这可能很乏味,但了解准确度下降 1%对收入的影响是很重要的:你会留下多少收入?
准确性的下降以及由此产生的收入要么是:
- 渐进:你正在建模的概念已经随着时间而改变
- 突变:人工智能系统不期待你发送的数据
每个人工智能系统的精确度都会逐渐下降。这是因为世界不是静态的,你所模拟的行为会随着时间而改变。这些渐变被称为 概念漂移【2】也是 AI 系统需要不断刷新的原因。
人工智能系统准确性的突然下降几乎总是数据收集过程中引入错误的结果。随着人工智能系统变得越来越复杂,它们开始依赖于在整个组织内收集的数据。因此,突破性的变化是意料之中的,就像复杂的软件永远不会没有错误一样。
由于行为的渐变和突变,所有人工智能系统都伴随着商业和声誉风险。
风险
商业风险
行为的逐渐和突然变化都会导致业绩下降,并伴随着收入损失。
让我们以一个自动投标系统为例,它决定了最优的投标。随着时间的推移,该系统将停止作出最佳决策,并会开始出价过高,每次投标,你的组织将开始失去金钱。在突然变化的情况下,由于广告不再显示,有可能人工智能系统开始大规模高估导致重大损失或低估导致销售下降。
声誉风险
让一个人工智能系统失控会给你的组织带来很大的声誉影响。
要让最终用户开始信任人工智能系统,需要大量的努力和透明度,因为默认情况下,他们往往不被信任。未能检测和修复问题性能问题将导致最终用户失去信心,而这种信心是很难挽回的。
意识到人工智能系统决策中的问题的最糟糕方式是让你的客户或最终用户告诉你。关键是要有适当的监控,这样当问题出现时你就能意识到,并能快速解决它们。
降低风险
考虑到与人工智能产品相关的增长机会,组织需要管理风险,而不是简单地完全放弃人工智能系统。
为了降低风险,您应该:
- 建立模型库存
- 实施监控解决方案
建立一个模型清单听起来微不足道,但是没有它就不可能测量一个组织的暴露程度。一个好的模型清单应该包括非技术描述、高级风险评估和已知的限制。虽然该清单由数据团队维护,但应与高级管理团队共享并由高级管理团队定期审查。要了解更多关于风险管理的信息,请查看管理模型风险的框架。
就像工具被实现来监控软件一样,为人工智能系统提供实时监控工具是很重要的。为了使这些工具实用,它们需要具有低延迟(问题发生和被检测到并发出警报之间的时间),并允许可配置的警报。拥有有效的监控策略是在客户注意到问题之前发现问题并避免声誉受损和收入损失的关键。
运行 ML 模型是令人兴奋的,可以产生非常可观的投资回报。然而,它也伴随着两个业务,即。收入损失和声誉风险,即。失去客户的信任。
对于构建和部署人工智能产品的公司来说,重要的是要有适当的工具来让他们了解 ML 模型的实时性能。
参考资料:
原载于 2020 年 1 月 6 日www . staki on . io。
人工智能解开了预测我们世界的一个关键科学障碍
偏微分方程是现代科学的基础;他们描述了从天气和洋流到广义相对论和量子力学的物理现象

授权给作者的图像
如果你和我一样,只要一提到偏微分方程(PDEs),就会想起布满灰尘的黑板、偏头痛和一种普遍的感觉“为什么我们要试图理解这些东西,它们永远不会在现实世界中帮助我们”。(是的我知道,不是一个伟大的态度)。
我不得不辩解说,自从在大学选修工程模块中学习了它们(讽刺的是,嘿),我们实际上就再也没有重新认识过。至少在我看来,它们仍然是一个非常抽象的概念。

授权给作者的图像
然而,我确实设法了解到关于偏微分方程的一件事是它们很难解决;事实证明,普通科学界也同意这个观点。那么,为什么我们还在投入时间试图解决这些问题呢?
偏微分和它们的秘密
部分答案在于这些数学方程能够模拟空间和时间变化的非凡方式。这种独特的性质使它们特别适合描述我们在我们的世界中观察到的许多物理现象,包括声音和热量传递、扩散、、静电学、、电动力学、、流体动力学、、弹性、、广义相对论、量子力学。
通过理解这些现象,并解决描述它们的偏微分方程,打开了能够预测的大门,在任何给定的时间点,接下来会发生什么,以及之前发生了什么。
听起来熟悉吗?DEVS 科技惊悚片
这种模拟我们的世界并让人工智能“解决”数学方程的能力正是英国广播公司扣人心弦的惊悚片《DEVS》背后的故事。如果你想真正看到的艺术(即时通讯?)有可能,这是一笔值得投资的一盒一套——赊账。
“宇宙是确定的,并且总是一个先前原因的结果”
[## BBC 二台- DEVS,系列 1,预告片:DEVS
全新的多维科技惊悚片即将登陆 BBC 二台和 BBC iPlayer。
www.bbc.co.uk](https://www.bbc.co.uk/programmes/p088gvvq)
真实世界中的偏微分方程
让我们回到现实,让我们探索 PDEs 的一些真实世界的应用。
一类偏微分是纳维尔-斯托克斯方程
一类特别有用的偏微分方程是纳维尔-斯托克斯方程。19 世纪初,由法国工程师克劳德-路易·纳维尔和英国物理学家乔治·加布里埃尔·斯托克斯爵士独立创建的这组方程描述了运动流体的速度、压力、温度和密度之间的关系。换句话说,它们描述了流体(包括空气)的运动。
纳维尔-斯托克斯方程适用于许多现实应用:
- 在飞机和汽车设计过程中模拟机翼和其他表面周围的空气运动。
- 研究医学中的血流。
- 发电站的有效设计、模拟流速和热传递。
- 污染、天气和海洋运动的分析。
- 和许多其他人…
微分和偏微分方程解释
在这一点上,它可能帮助读者(它当然帮助了作者)用简单的术语理解 PDEs。随意跳过这一节,但我发现这些例子很有帮助,如果你想看这些和其他的,读一些关于 MathsIsFun.com 的导数和偏导数的精彩解释。
先说一个微分方程。这是一个带有函数及其一个或多个导数的方程:
y + dy/dx = 5x
在这个例子中,函数是 y ,它的导数是 dy/dx
MathsIsFun 有助于理解 dy/dx(导数):
“把 dN/dt 想象成人口随着时间的变化而变化,在任何时刻”
这个(琐碎的)例子有助于进一步说明这一点。

偏导数是一种导数形式,其中一个变量保持不变,如下例所示:

偏微分方程和人工智能
很少有人会预见到偏微分方程和现代人工智能领域之间的任何重叠。然而,数学家开始向现代人工智能寻求帮助,因为解决偏微分的核心是一个高度复杂和计算密集型的问题。
历史上,这需要强大的超级计算机来处理计算。但是,即使拥有强大的计算能力,这些“传统”的数学方法也只能产生有限的结果。
深度学习是如何解决这个难题的

人工智能的现代进步,特别是在深度学习领域的进步,第一次使偏微分方程的求解达到了前所未有的准确性和普遍性。加州理工学院 Caltech 的突破性研究使这成为可能。
加州理工学院的研究人员应用了一类使用傅立叶神经算子的神经网络,以产生一个高度优化的神经网络来解决偏微分方程。
结果是惊人的:
- 预测未来/过去动态的精确度达到新的水平
- 高度概括,并可应用于(无需再培训)解决许多类偏微分方程,包括纳维尔-斯托克斯
- 比传统(数学)解算器快 1000 倍
Anima Anandkumar 教授也是英伟达的 AI 研究总监。在推特上关注阿尼玛·阿南德库马尔。
预测未来(你必须从某处开始)
在这个模拟中,您可以看到他们的模型(右)预测的流体运动如何与观察到的实际运动(中间)精确匹配。该模型从一个时间点(左)对此进行了预测。

图片来自加州理工学院的公开推特(上图)
在上述模拟中,使用了 10,000 的(挑战性)雷诺数。雷诺数是流体的惯性力与粘性力之比,超过 4000 的数字通常被描述为“湍流”,其中液体分子执行不可预测的运动。因此,10,000 解释了模拟中看到的看似随机的运动(摘自这篇论文)。
他们是怎么做到的?
神经网络的经典发展主要集中在学习有限维欧几里得空间之间的映射。最近,这已经推广到学习函数空间之间映射的神经算子。对于偏微分方程(PDEs),神经算子直接学习从任何函数参数依赖到解的映射。因此,他们学习了整个偏微分方程族,而传统方法只能解决方程的一个实例。”
这段摘录摘自加州理工学院于 2020 年 10 月 20 日发布的研究论文。
卷积神经网络 在论文中,他们首先讨论了使用深度卷积神经网络(CNN)的传统人工智能方法的局限性。这些模型依赖于有限维欧几里得空间,并且需要根据 PDE 和被分析的场景进行大量的调整和修改。
FEM-神经网络 他们继续讨论一种改进的,但仍然是次优的方法,使用基于神经网络的有限元 方法 ( FEM )。这种方法旨在模拟 PDE 的一个特定实例,因此比 CNN 更通用,减少了调整和修改的需要。它也产生了更准确的预测。然而,当问题集中的系数改变时,它需要重新训练,并且基本的偏微分方程必须是已知的。
神经算子 2019 年末推出,这些使得神经网络能够拥有无限维算子。神经操作者只需要训练一次,这比以前的方法有明显的优势。获得参数的新实例的解只需要网络的正向传递,减轻了神经-FEM 方法中引起的主要计算问题。最后,神经算子不需要底层 PDE 的知识,只需要数据。
然而,这并不是研究人员希望的银弹:
到目前为止,由于评估积分算子的成本,神经算子还没有产生可以在有限维设置中与卷积或递归神经网络的成功相媲美的有效数值算法。通过快速傅立叶变换,我们的工作缓解了这个问题。”
加州理工学院的研究人员,加州理工学院
傅立叶变换 傅立叶变换常用于求解微分方程的谱方法中,因为微分相当于傅立叶域中的乘法。
我们在这些[研究]工作的基础上,提出了一种直接在傅立叶空间定义的神经算子体系结构,具有准线性时间复杂度和最先进的近似能力。
加州理工学院的研究人员

授权给作者的图像
加州理工学院的神经网络使用了一种新颖的深度学习架构,该架构利用了这些傅立叶变换算子。网络的惊人性能部分源于它能够学习无限维函数空间之间的映射;如图 1 (a)所示,积分算子通过傅立叶域中的线性变换来例示。

图 1(图片来自加州理工学院公共研究论文
结论
这是一个突破性的飞跃。我可以看到它在伦理领域的积极影响,如模拟气候变化和洋流,以帮助海洋生物学和保护。预测空气动力学,例如在飞机、汽车和卡车上,可以提高效率,并帮助我们从燃烧转向电力作为我们的动力选择。
后续步骤
1.阅读加州理工学院的研究论文
2.了解更多关于安科瑞斯数据,分析&人工智能
3.与作者联系
人工智能和人机界面:新的商业模式
人机界面和人工智能的重要性

在与一家自动化和电子产品制造商合作实施用于人机界面的智能传感器和人工智能平台后,我意识到这个行业如何从产品过渡到服务…
的确,机器学习的日益成熟正在影响工业 4.0 的发展,也为某些公司创造了新的商业模式。事实上,制造企业在工业协议、专有设备/系统的庞大安装基础和陈旧的用户界面方面已经有了数十年的投资。基于这些要素:在这样一个碎片化的环境中,你如何在全球范围内推动创新、灵活性和增长?
什么是人机界面?
HMI 是关于人和自动化系统如何相互交流和沟通的。
人机界面是机器和操作人员之间的中介。毫无疑问,HMI 是操作员和经理手中监视车间或工厂生产的最重要的工具。
人机界面早已不再局限于工业中的传统机器,现在还涉及到计算机、数字系统或物联网(IoT)设备。

从操作的角度来看,机器操作员必须能够一眼看到其责任范围内的条件和过程。机器背后发生了什么?发动机和阀门状态是否在设定值内?储罐液位是否足以进行不间断生产?
HMI 最重要的任务是快速简洁地显示复杂的过程变量,以便于解释生产信息。
构建一个好的人机界面并不容易,因为构建人机界面的基础很大程度上取决于对人类身体、行为和精神能力的理解。换句话说,人机工程学构成了人机界面背后的原则。
好的人机界面设计必须让用户理解系统的行为,这反过来又必须让他们看起来可信。软因素,如系统自我解释(可解释的人工智能)不仅在提高交互质量方面发挥着重要作用,还允许机器模仿鼓励接受和使用的情感行为。
为什么 HMI 很重要
人机界面也从控制室的按钮和二极管,通过网络可视化,变成了认知解决方案。
在现实中,一台机器或一台设备只能和它与人类的界面一样好。这就是为什么对优化设计的人机界面的每一项投资都是战略性的。数据可视化和文本表示可以使操作员和经理精确地协调和控制工厂的生产过程,但我们可以通过机器学习做更多的事情。
新的人工智能商业模式
传统的 HMI 解决方案是由 OEM(原始设备制造商)作为机器的一部分部署的独立、隔离的终端。基于机器学习的新 HMI 解决方案要么是预先配置好的向云端发送数据,要么是内部部署的解决方案。
如今,状态是通过一个贴有标签的 led 信号灯、发光按钮和显示面板以及屏幕上的计算机支持的用户界面来显示的。除了人机界面,我相信开关、LED 指示灯、操纵杆和开关面板制造商将不得不通过使用智能传感器连接到他们自己创造的人工智能人机界面,使他们的产品更加智能……物联网传感器正在实现商业模式的根本转变:从产品到服务的转变。
除了与 B2B 公司合作,通过更好地利用物联网传感器和为 HMI 或 HMI 产品(如 LED 灯或开关按钮)创建新的应用程序,与 B2C 公司合作将变得更加容易。然而,从物联网传感器收集的数据只有在您可以从中获取有用的情报时才是有用的,并且最好是以自动化的方式…
这种新的转变将鼓励公司从创建 HMI 解决方案过渡到建立传感器网络和管理机器学习项目。
事实上,如今的物联网传感器解决方案大多只负责数据采集。当我们在机器学习方面将传感器与人工智能融合时,这就创造了一个可以出售给其他组织的预测工具。通过物联网传感器,我们可以测量和收集与机器的运动、温度或振动相关的数据。一旦收集了数据,我们需要应用机器学习技术对其进行分类和分析。可用的机器学习选项很多,从逻辑回归到神经网络。
为了理解这些技术如何协同工作,想象一个广泛分布的物联网传感器阵列在整个制造工厂收集数据,并将其快速传输回中央神经系统。
我们还可以想象,通过这些元素生成的数据将通过模块系统集成到独立的预测性维护系统中,或出售给其他公司,以帮助他们创造更好的产品。
例如,交通灯制造商可以制造一种新产品(基于新的 LED,配备智能传感器),当车辆驶过路面的感应回路时,这种产品可以自行改变颜色。

我希望看到原始设备制造商(OEM)和行业之间建立更多的技术合作关系。原始设备制造商必须为他们的产品创造新的附加值,并最终帮助他们的客户创新。我预测原始设备制造商将不再仅仅是供应商,而是更多的创新伙伴。
新型人机界面
我们正处于从高度复杂的方法向更加直观的界面进化的早期阶段。
随着面部识别功能等“新”技术成为移动设备的标准,HMI 现代化的必要性正处于其生命周期的开始。我意识到,语音控制是最受欢迎的人机界面之一,因为它允许免提控制,因此更少分心。
人机界面的未来将与人工智能有关。随着时间的推移,这些系统自然会产生大量数据。事实上,公司将期待配备一些机器学习算法的 HMI,这些算法可以从物联网传感器生成的所有数据中学习,并适应操作员的持续行为。此外,该系统必须足够有效,以便从先前已经进行的计算中学习,从而生成可靠的、可重复的决策和结果,这些决策和结果在所连接设备的活跃计算和操作中是可接受的。
在我个人看来,这是代工企业商业模式的一个大转变。显然,将会有一些赢家,也将会有那些不太正确和半途而废的人。
人工智能 5 行代码:葡萄酒分类
实用人工智能
准确率高达 98%的葡萄酒分类人工智能
谁说人工智能必须复杂才能构建?在本文中,我将使用机器学习创建一个能够在短短 5 行代码中区分不同种类葡萄酒的人工智能。然后我会解释每行代码的含义。

葡萄酒生化数据
我将使用包含三种不同品种葡萄酒的生化数据的数据集。人工智能将从数据中学习如何区分不同的品种。
-
- *不幸的是,让大家失望的是,葡萄酒的名字不见了。在数据集中,它们被标记为 1、2 和 3
导入模块
我要做的第一件事是从一组预先制作的算法中导入模块。它们将允许我在制造我的人工智能时使用特定的工具(这些代码行不算,因为它们本身不构建任何东西)
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
我的整个人工智能
就是这个!通过运行这些代码行,人工智能可以学习如何区分不同种类的葡萄酒。
X = pd.read_csv('/content/drive/My Drive/Colab Notebooks/Projects/20200528_Wine_Classifier/wine_data.csv')
y = pd.DataFrame(X.pop('Wine'))
clf = RandomForestClassifier(n_estimators=10)
scores = cross_val_score(clf, X, y, cv=10)
acc = ("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
print(acc, scores)
让我解释一下所有这些代码行是如何工作的。
导入数据集
正如你以前可能听说过的,为了表现良好,人工智能需要数据。我将使用从 data.world. 下载的不同葡萄酒的生化数据
X = pd.read_csv('/content/drive/My Drive/Colab Notebooks/Projects/20200528_Wine_Classifier/wine_data.csv')

的示例。我们刚刚下载的 csv 数据集
正如您所看到的,这个数据集包含第一列酒的种类,在所有其他列中是它们的生化数据。我们用来预测葡萄酒种类的所有数据被称为特征。
隔离标签
我现在将把预测数据(生化数据,特性)和我们想要预测的数据(酒列)分开,我们把这个数据标签。

标签列的示例
创建模型
现在我需要选择我想要建立哪种人工智能。有几种人工智能,每一种专门解决一个不同的问题。在这种特殊情况下,我将使用随机森林分类器,这是一种可以在分类问题上表现良好的机器学习算法。
clf = RandomForestClassifier(n_estimators=10)
对于这个模型,我也将选择它的参数:10 作为估计器的数量(如果你不了解人工智能算法的细节,这是你无法理解的)
训练人工智能
scores = cross_val_score(clf, X, y, cv=10)
为了获得可靠的准确度分数,我将使用一种叫做交叉验证的工具。本质上,我将把我的数据集分成训练和测试数据。我将使用训练数据集来指导人工智能如何找到标签和要素之间的联系。在学习如何找到这个链接之后,AI 将估计测试特征,我们将把结果与测试标签进行比较。通过交叉验证,数据集将被拆分 10 次,每次测试和训练将包含不同批次的数据。
这样做,算法将被多次测试,如果不同时间之间的分数相差太大,结果将很可能有偏差。
估计准确度
该算法已经运行了 10 次。每次我们都达到了几乎 100%的准确率。分数从 94%到 100%不等,平均 98%,成绩惊艳。
Accuracy: 0.98 (+/- 0.05)
[0.94
1.00
1.00
0.94
1.00
1.00
1.00
0.94
1.00
1.00]
人工智能中的人工智能——增强分析领域的下一个前沿
nabler.com
了解人工智能在商业智能中的未来

毫无疑问,大多数首席信息官和分析师,无论是专注于营销还是运营,都非常依赖数据。可能不清楚的是,这些数据具体是如何被检索、分析并最终用于更好的决策。商业智能、人工智能等术语并不新鲜。两者都以手动能力无法比拟的效率在收集和可视化数据方面提供了价值。单独来说,这些解决方案提供了许多组织认为强大的功能。地平线上的东西,事实上已经触手可及,是发现和实现每一个的互补性质。
人工智能
让分析师能够以更快的速度编译和检索数据,以促进深度分析,这或许是人工智能的关键成果。机器学习承诺将决策提升到一个新的水平,允许指数级完成平凡和复杂的任务,以促进更大的成果。即使在目前的状态下,人工智能真的兑现了这个承诺吗?
商业智能
虽然 AI 努力提供更快的决策,但 BI 的承诺是通过改进的分析来增加决策。众所周知,BI 旨在提供快速准确的报告、竞争分析和市场趋势识别等功能。最终,组织希望将这种洞察力转化为行动。问题是 BI 最终能否实现这一潜力。AI 能否为 BI 提供组织所需的增强分析能力?
将人工智能和商业智能与 360 度决策相结合
无论规模或行业如何,组织都在努力提高决策能力和改善结果。AI 对 BI 的应用还在继续发展,但是这种结合还没有成熟。以前使用这两种独立功能的组织现在发现其组合具有潜在的变革性。
简而言之,人工智能将改变分析师及其组织处理信息的方式。与人工智能提供几乎没有智能的花哨仪表盘不同,人工智能支持的人工智能可以扫描各种信息源,并帮助确定好坏。其结果是通知正确的利益相关者正确的信息,以便在正确的时间做出正确的决定。
当今利用人工智能的公司
实现人工智能的商业智能的想法已经不远了。事实上,它已经在这里了,因为许多组织已经开始了这场革命,转变他们的运营并取得了显著的成果。
荷兰跨国银行和金融服务组织 ING 已经使用了人工智能。ING 将支付、客户信用数据和其他信息捆绑成一个强大的工具,供各个部门使用。例如,销售部门可以利用从新工具中收集到的见解来帮助客户看到各种选项,以便做出更好的决策。此外,风险部门可以提高风险评估的质量和效率,以便更有效地为有价值的客户确定贷款和信用额度。
沃尔玛,全球超过 11,000 家零售店的运营商,也通过整合 SAP 的 HANA 加入了人工智能的商业智能革命。这个云平台从应用程序、关系数据库和其他来源复制和获取结构化数据,包括销售交易和客户信息。由于沃尔玛的复杂性,他们实施的解决方案允许该组织在几秒钟内处理大量交易记录。这使得沃尔玛能够在采购、采购和运输方面做出更快的决策。这种通过人工智能更有效地分析数据的能力正在提高效率。这也导致了更好的决策和更好的成本控制。
沃尔玛应用人工智能不仅仅是为了内部使用。该公司的网站现在可以根据位置、可用性和其他标准向个人消费者提供建议。这使得沃尔玛能够更有效地与 T4、亚马逊和其他网上零售商竞争。
在重工业领域,通用电气正在利用人工智能来更准确地预测维修需求,确保机器以最高效率运行。该公司的流程包括将传感器整合到机械和车辆中,同时将它们与生产计划联系起来。这意味着设备可以数字化,并通过人工智能进行有效监控。通用电气的运营充分利用了物联网,其中传感器与网络无缝通信。商业智能解决方案允许快速监控和解决潜在问题,以免它们变成全面的问题。
结果不言自明
根据 Gartner 的说法,“通过增加机器学习,数据管理手动任务将减少 45% 。”此外,“到 2022 年,超过 50% 的主要新业务系统将整合业务运营中的实时分析。”此外,预计到 2022 年,全球数据分析支出将超过 1040 亿美元。
这对于那些认为人工智能是主要为财大气粗的人提供的工具的组织来说,应该是个好兆头。随着两者的结合变得越来越民主化,因此也越来越实惠,更多的组织将从他们的结合中受益。
人工智能在商业智能中的未来
根据 TDWI 最佳实践报告人工智能和大数据时代的商业智能和分析,组织对利用人工智能、大数据和基于云的服务的创新非常感兴趣。几乎四分之三(74%)的组织希望投资最新技术,以提高运营效率。他们也对仅使用现有的商业智能解决方案来完成报告和分析等任务不感兴趣。大多数组织希望显著增强它们,或者完全转向新的解决方案。因此,人工智能对许多人来说是一个值得的机会。
大数据的流行有时似乎势不可挡。此外,估计大约缺少 150 万名能够仅根据数据做出明智决策的大数据分析师。这就是为什么人工智能及其机器学习能力处于组织渴望的最前沿。成功实施人工智能的企业将在速度、成本、效率和能力方面比竞争对手拥有显著优势。
教育将有助于推动人工智能应用的采用。因为人工智能需要环境和人类的投入才能继续成熟,更广泛应用的机会将会到来。现在,我们可以看看那些目前正在实施的组织,并从他们的经验中学习。
最初发表于【https://www.nabler.com】。
商业人工智能
你的公司应该实施人工智能的 10 个理由

SpaceX 在 Unsplash 上拍摄的
今天,许多公司面临着一场影响深远且意想不到的危机。企业家不得不调整他们的计划和优先事项,以保持他们的初创企业的竞争力。现在,企业比以往任何时候都更需要强有力的、果断的行动来改善现有的流程,以提高公司的工作效率。
但是这能实现吗?当然是啦!只要你相信人工智能:商业的未来。不相信我们?看看在商业中实施人工智能的以下十个好处。
据麦肯锡全球研究所报告显示,2019 年 AI 技术在标准业务流程中的使用增加了 25%。该报告还展示了至少在未来十年,人工智能将如何为年度 GDP 贡献额外的 1.2%。
很明显,人工智能拥有强大的力量——它有很多方式可以支持你的业务。
1.提高员工生产力和工作满意度
人工智能的第一个好处是它可以把员工从重复的工作中解放出来。它可以消除那些不仅不能令人满意,而且不能为职业发展或学习新技能提供机会的活动。
以故障排除为例。绝大多数客户的询问通常都是关于同一件事,因此许多公司已经决定自动化这一过程。现在,由于自动化聊天机器人,客户可以更快地获得答案,而员工可以专注于其他更雄心勃勃的任务。
根据一项 微软“人工智能&技能 ”调查,公司认识到通过将人工智能与员工的技能发展(技术和软件)相结合,使用人工智能的最显著的商业利益。
2.提高营销绩效
根据 2018 年的报告B2B 营销中的人工智能状态 ,60%的营销人员认为人工智能带来了更好的数据策略。事实上,人工智能对营销绩效产生了前所未有的影响。
但这是另一篇文章的主题——然而,简而言之,人工智能可以:
- 使用自然语言处理技术生成一个搜索引擎优化关键词列表
- 创建更相关、更吸引人的内容
- 瞄准更广泛的受众
- 创建更有效的活动
- 基于数据优化性能
- 发掘新的广告渠道
- 分析消费者行为数据
…还有更多。
3.节省时间和金钱
如果你希望节省时间和金钱,人工智能可以通过自动化长期重复的任务来提供帮助。以实验室创造的解决方案为例。艾举红豆杉为例。
Taxando 需要一种方法来缩短生成纳税申报表所需的时间。使用机器学习和神经网络。人工智能创造了一个工具,将完成任务所需的时间从五分钟减少到几秒钟。
此外,以前需要 30 分钟的端到端报税流程(包括从税卡 OCR 中提取数据并将详细信息发送给 IRS)现在只需 30 秒。
4.支持销售和增加收入
当然,完全自动化的销售过程是不专业的。但是你可以用人工智能改善特定的领域。
首先,你可以使用人工智能来分析大量的数据集,这样算法就可以得出结论,这意味着更多的销售,更快。然后,你可以创建基于人工智能的工具,帮助改善销售预测,预测客户需求,并改善沟通。最后,您可以使用类似的解决方案来定制您的产品或服务,以满足真正的消费者需求。
通过流程自动化,减少人为错误,以及更有效的销售和营销活动,人工智能可以在增加收入的同时节省开支。
5.避免“人为错误”
让我们明确一点:人工智能永远不可能完全没有错误。
然而,我们为算法提供的数据越多,我们使用的技术越好,我们基于人工智能的工具就能表现得越好。这意味着任务的执行速度更快,结果更准确,而不是让人类做同样的事情。
而且很多情况下准确率接近 100%。谷歌的淋巴结助手就是一个完美的例子:它在检测转移性乳腺癌方面达到了 99%的准确率和 69%的灵敏度。
人工智能比人更不容易出错,因为它没有像疲劳和注意力分散这样的人类特征。不管在一天中的什么时候,它都能有效地工作,避免情绪、观点和偏见——只做客观的决定。
6.增强最终用户体验
由于其复杂的工具集和分析客户和用户行为的能力,人工智能还可以改善人们对你的服务的体验。事实上,大约 38%的消费者同意人工智能将改善客户服务。
首先,用户可以通过直接嵌入网站的聊天机器人请求帮助。此外,公司可以分析用户行为,实时预测消费者需求,同时了解人们不喜欢什么。
这样做可以让公司根据当前和未来的客户需求和期望调整他们的工具和服务。
7.建立竞争优势
基于人工智能的工具将使你工作得更好、更快,并且更符合市场的实际需求。这种进步的方法是所有客户都会喜欢的,不仅仅是技术爱好者。
毕竟,最先进的解决方案增加了竞争力,这将有助于吸引更多的客户。
8.改善招聘流程,提升人力资源
根据 2019 德勤全球人力资本趋势报告,“74%的 HR 高管认为新技术在他们的组织中意义重大。”当人工智能可以支持如此多的人力资源流程时,很难不同意,包括:
- 分析和分类简历
- 收集和分组庞大的数据集
- 基于特定标准和关键字筛选候选人
- 在面试中评估候选人的行为(包括面部表情、肢体语言和语调)
- 发布招聘广告
9.吸引更优秀的候选人
对技术的前瞻性态度不仅有助于你赢得客户。这能让你成为一个更有吸引力的雇主,让你的公司成为一个理想的工作场所。如今,随着员工如此专注于职业发展,创新的机会变得非常重要。
10.产生更有意义的商业见解
最后,人工智能的分析能力可以让你处于一个非常强大的位置。强大的数据分析可以更好地预测公司业绩,更可靠地洞察新兴的消费者趋势,并提出更智能的方法来降低成本。
有趣的是,人工智能甚至可以预测汇率和股价的波动——这说明了它的预测能力有多强大。
来源:
[1] A. Cam、M. Chui 和 B. Hall,全球人工智能调查 (2010),麦肯锡全球研究所
[2]微软,用人工智能加速竞争优势。组织如何从实验转向商业影响 (2019),2019 微软公司
[3] K. Wiggers,谷歌人工智能声称转移性乳腺癌检测准确率达 99%(2018),VentureBeat
临床决策支持中的人工智能:障碍与机遇
活动讲座
Niki Athanasiadou | TMLS2019
https://torontomachinelearning.com/
关于演讲者
我在爱丁堡大学(英国)获得了分子和细胞生物学博士学位,在基因组研究、医学和人口健康的计算建模方面拥有丰富的经验。值得注意的是,作为美国国立卫生研究院的研究员,我建立了一个管道原型,利用基因组和 EHR 水平的信息创建疾病风险的个性化模型。
除了发表在国际同行评审期刊上,我的工作还在英国和美国赢得了几个奖项,包括 2018 年纽约市开放数据竞赛的一个数据科学项目。我目前是 H2O.ai 的数据科学家,与医疗保健行业的公司密切合作,帮助他们利用人工智能扩展他们的能力。
关于谈话
随着数据处理和存储变得越来越便宜,采用人工智能的主要障碍往往是数据可用性。这在医学领域是最好的例证,人工智能支持的临床决策支持的进步反映了医疗保健系统中数据记录和存储方式的创新。
人工智能支持的临床决策支持包括诊断和预后,并涉及分类或回归算法,这些算法可以预测医疗结果的概率或某种疾病的风险。在过去的两年中,FDA 已经批准了几种使用医学图像的图像分类算法作为诊断工具,并且肯定会有更多的算法出现。
类似地,FDA 已经批准了监测生命体征以捕捉异常情况的可穿戴设备。这些早期的例子展示了人工智能在医学领域应用的巨大潜力,因为获取的医疗数据的数量和种类都在增加。
超过 80–90%的美国医院和医生办公室正在实施某种形式的 EHR,全球范围内的采用率类似甚至更高。尽管持续存在未决问题,EHR 系统之间缺乏互操作性或病历连续性,过去与数据可用性和可用性相关的采用障碍正在被克服。
将讨论建立在 EHR 数据上的临床决策支持人工智能模型的三个例子。
- (1)在医疗机构中积累出生时的病史以及相关联的母亲 EHR 信息,使得能够在出生后两年内预测高肥胖风险儿童,这可能允许改变生活的预防性干预。
- (2)由 Kaiser Permanente 开发和部署的高级警报监控系统使用重症监护病房(ICU)数据来预测致命恶化的病例,并提醒员工需要救生干预。
- (3)最后但并非最不重要的是,临床决策支持系统通常需要提供对其预测的充分解释。关于医院再入院预测的全球和局部解释证明了可解释性技术是如何实现这种解释的。
随着 EHR 信息变得标准化并富含基因组信息,医学已准备好利用人工智能突破来改善健康结果。

金融中的人工智能:如何最终开始相信你的回溯测试[1/3]
模拟、风险和指标
关于回溯测试的危险,如何测量它们,不要感觉正确,但要正确

插图形式https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3544431
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
定量研究是一个包含许多中间步骤的过程,每个步骤都必须经过仔细彻底的验证。资产选择、数据收集、特征提取、建模——所有这些阶段都需要时间,并且由不同的团队交付和测试。但是投资者最终想看到什么呢?对历史数据的“完美”回溯测试,具有高夏普比率、相对于市场的阿尔法值,可能还有一些与基金相关的指标,如容量、杠杆、平均 AUM 等。然而,这种方法并不能告诉我们任何关于策略的未来表现的信息,而且这种回溯测试很容易被过度拟合,甚至当它们被用来衡量一个交易想法的“成功”时是危险的(详见我的文章金融想法发现)。
没有什么比对过去表现良好的策略进行回溯测试更容易的了,但你会冒险把资本押在这上面吗?大多数投资者都是这样。
在接下来的两篇文章中,我想全面回顾一下测试交易策略本身的想法。
- 首先,解释标准方法的危险,并展示一些替代指标,这些指标提供了关于战略绩效的更多见解。
- 然后,我将展示我们如何摆脱单一的向前回溯测试,而支持众所周知的度量标准的模拟、场景和概率解释。这将有助于我们从对过去的分析转向对未来表现的评估。
- 最后但同样重要的是,我想丰富风险的概念:通常投资者和投资组合经理会计算并考虑投资组合的风险,但不会考虑策略本身的风险,这导致他们无法控制和理解现场表演中的策略。
像我最近的大多数文章一样,这篇文章的灵感来自于洛佩斯·德·普拉多博士的书,我推荐他们深入探讨这个主题。一如既往,你可以在我的 GitHub 上找到来源。
回溯测试的危险
2014 年,由罗隐领导的德意志银行从业人员团队发布了一部名为《量化投资的七宗罪》的作品。它谈到了你可能已经听说过的事情:生存偏差、前瞻偏差、讲故事、数据窥探、交易成本、离群值和短期问题。我希望我们已经知道如何获得正确的数据并正确处理它,而不是展望未来,并执行特性重要性分析,而不是在回溯测试中解释随机模式。



上述论文中量化投资的一些“死罪”的例证
然而,除了这个至关重要的列表,我还想补充一些质疑回溯测试本身的时刻:
- 是随机过程的单一路径。市场可以用一个包含数百万变量的极其复杂的随机过程来描述。我们可以对这一过程的不同场景和结果进行采样,但我们只观察到了一个实际发生的情况。我们 依靠一个极其复杂的系统的无限的单一结果来测试一个交易算法,这本身就是疯狂的。
- 它没有解释金融发现。回溯测试说明了过去可能发生的事情,但没有解释原因。依赖夏普或索提诺配给意味着蒙着眼睛呆在不确定的世界里。诸如特征重要性分析之类的替代方法将允许我们首先建立金融理论,并且只有在用回溯测试或另一个方案测试它们之后。
- 它不允许我们预测业绩和风险。你的策略可以在 2008 年的危机中幸存下来,这是否意味着它可以轻松地度过当前的 COVID one?你怎么知道你没有过度适应某个特定的场景?还是一组特定的因素?如何准确估计这种结果的概率?经典的回溯测试没有给出任何答案。
总的来说,即使我们避免了德意志银行的人犯下的致命错误,我们的回溯测试也只能告诉我们一些规则在过去是如何执行的,除此之外别无其他。这就是为什么拥有一个更丰富的战略评估工具包至关重要,它允许概率性的、基于场景的、以风险为中心的方法,这是我们在神经元实验室使用的,我们将在这两篇文章中开发并测试它。
基于人工智能的战略概述
让我们定义一个典型的基于预测的策略:在某种工具上有一个做多或做空的信号源,我们据此采取行动。为了简单起见,我们将执行一个典型的时间序列预测练习:取前 N 天,提取因子,预测第二天的价格变化,然后交易。这是一个非常原始的场景,没有考虑交易成本、滑点、空头、获利和止损障碍,但让我们先关注市场理解原则的发现,然后关注执行——我们总是有时间因为不适合市场/交易规则而放弃策略。
基础数据
让我们把重点放在银行部门,并将学习 C、DB、BAC、WFC 和其他已知银行的投机信号。由于他们在 2008 年危机中的崩溃,看看我们的 ML 模型将如何应对这种政权更迭将是一件有趣的事情。我们将主要依靠统计因素,我们将这些因素分为三类:
- 统计特征:最小值、最大值、自相关和统计矩
- 技术指标:交易者喜爱的经典特征
- “AFML 特色”:详情查看名著:)
我们将以滚动窗口方式提取这些因素(分数微分时间序列上的统计因素),并根据 iid 规则对输入和输出进行采样。输入将是“今天”的滚动特征,预测-第二天的固定范围收盘价格变化。
预测模型
根据 López de Prado 博士的建议,我们将使用决策树的 bagging,并对 iid 抽样进行校正。我们期望集成将有助于处理过度拟合,基于树的模型将有助于进一步的特征重要性分析。一般来说,我们希望保持预测模型尽可能简单,关注我们的因素洞察力的质量。
超参数
我们将根据 5 年的数据训练我们的模型,然后在接下来的 3 年里用这个模型进行交易,之后重复这个过程,直到数据结束(从 2000 年到 2020 年)。这种方式至少在某种程度上我们应该适应不断变化的政体。
“正常”回溯测试和分析
让我们从德意志银行(DB)股票开始,运行上述策略,并计算回报率、策略绩效和基准(买入并持有)与 ML 策略相比的夏普比率。


与 HODL 基线相比,DB ticker 上 ML 策略的回报和累积回报(即业绩)
数字呢?
- 平均收益: -基准 0.00026,ML 策略 0.0008
- 夏普比率: -基准 0.14,ML 策略 0.74
看起来很不错,但是我们从这个回溯测试中得到了什么实际的见解?字面无!也许我们的模型只是在熊市中几乎总是过多地给出“做空”信号,将来会失败得很惨:)让我们回顾一下更有趣的指标,这些指标可以帮助我们更详细地了解模型的表现!
替代指标
数据统计
- 特征组重要性:显示哪个数据源在哪个时刻是重要的(市场、基本面、情绪、替代方案),我们可以检测状态并部分解释模式
- 特性暴露:如果一个模型过于依赖某个特定的特性,那么它将来可能会变得不可靠。我们可以跟踪这种不一致,并将它们视为风险的来源
模型统计
- “准确性代理”:马修相关系数(MCC)是预测模型“准确性”的一个相对通用的度量,它可以提供关于我们可以在多大程度上依赖该模型的见解。此外,它有助于检测政权,我们的模型是不可靠的。

著名的 MCC 公式
- 模型确定性:模型返回概率,我们可以跟踪预测的可信度,并研究可信度如何影响风险和回报
效率统计
- 夏普比率(年化的、概率的、紧缩的):基本的性能指标,但是,对于厚尾和偏斜分布以及多重测试,这些指标必须是固定的。



年化的、概率的和缩减的夏普比率(从https://mlfinlab.readthedocs.io/)
- “聪明的”夏普比率:我们希望我们的策略没有自相关,没有记忆,因此不会有任何长的燃烧期。如果我们用自相关惩罚我们的夏普,它可以帮助我们通过优化选择这样的策略。

夏普比率与校正的自相关,参见本文了解更多详情
- 信息比率:该指标有助于我们将我们的战略与“alpha”之外的基础或基准进行比较。它是平均超额收益和跟踪误差之间的年化比率。

来自https://mlfinlab.readthedocs.io/的信息比率公式
运行统计
- 所需的最小跟踪记录长度:回答问题“一个跟踪记录应该有多长时间,才能有统计置信度表明其夏普比率高于给定阈值?”如果跟踪记录比它短,我们就没有足够的信心认为观察到的夏普比率高于指定的夏普比率阈值。

来自https://mlfinlab.readthedocs.io/的最小要求跟踪记录长度公式
- 水位下降&水下时间:投资者不仅对最大水位下降的风险感兴趣,还对他们将在那里停留多久感兴趣。与数据和模型统计数据相结合,它可以提供关于为什么以及何时该策略表现不佳的见解。
一般化统计
- 市场推广:由于我们的目标是在特定的行业中经营,我们寻找在不同工具中一致的因素,因此我们知道,我们不会仅仅为了一个单一的证券而“过度拟合”我们的发现。没有标准化的方法来衡量这样的概括,所以我们将随机应变:)
新的指标和见解
首先,让我们在 DB ticker 上计算基准测试和策略的所有上述指标:

DB ticker 上 ML 策略的回溯测试统计数据与 HODL 基线的比较
我们可以看到,在主要性能和信息价值指标方面,我们基于 ML 的策略确实优于基线!过度拟合怎么办?概率 SR 等于 1.0,这意味着该发现是真实的,并且缩小的 SR(从 Bagging 模型的多次运行计算)也等于 1.0,这证实了我们的模型也是适当的。平均 MCC 相当高,甚至除以 MCC 的标准偏差(某种准确度得分的 SR)也有很高的值。功能重要性呢?我们可以看到,有些特征在重要性的底部是稳定的,而有些是非常高的。我们从经验上看到,基于交易量的因素在这个股票市场表现良好。

与 HODL 基线相比,ML 策略在 DB ticker 上的时变特征重要性
如果我们已经计算了特征的重要性,为什么我们不应用它来使结果更好呢?例如,我们可以删除最不重要的 3 个特性(假设它们没有任何意义)。会改变性能吗?


与 HODL 基线相比,DB ticker 上两种 ML 策略的回报和累积回报(即业绩)
从视觉上我们可以确认,具有更新功能集的外部更新策略(每 5 年重新评估一次)击败了我们使用所有功能的 ML 策略基准。从指标的角度来看,我们也看到了改进,但注意 MRTL(最小所需跟踪记录长度)特性,它现在告诉我们,我们需要更多天来观察这两种策略,以确实确认这种提升(这是有意义的,因为它们高度相关)。此外,请注意平均确定性的下降——删除一些特征实际上可能会损害模型。

与 HODL 基线和使用所有特征的 ML 策略相比,在 DB ticker 上去除了 3 个最低性能特征的 ML 策略的回溯测试统计;*-所选特性我们根据第一个 ML 策略的基准来计算该指标
现在,我们需要确保我们关于给定特征的非线性依赖性的策略和假设能够适用于其他银行 tickers。
我们可以推广到其他 tickers 吗?
BAC 股票代码(美国银行)



与 HODL 基线相比,BAC 报价器上两种 ML 策略的回报、累积回报(即业绩)和特征重要性

HODL 和两个 ML 策略的回测统计量
嗯……看起来不太好。如果我们详细检查度量,我们可以看到这是 ML 模型的一个明显的错误。“重要”特性也与德意志银行的例子有很大不同。也许只是一个异常值,让我们试试下一个!
WFC 股票交易所(富国银行)



与 HODL 基准相比,WFC 证券交易所的两种洗钱战略的回报、累积回报(即业绩)和特征重要性

WFC 证券交易所 HODL 和两个 ML 策略的回溯测试统计
接下来的尝试也是一点收益都没有!然而,这里的情况更加棘手:MCC 指标不是负数(甚至非常接近于零),但是战略绩效非常糟糕。让我们看看更多的例子,但是现在,值得考虑的是德意志银行的例子只是一个幸运的例子。
C ticker(城市集团)



与 HODL 基线相比,C ticker 上两种 ML 策略的回报、累积回报(即业绩)和特征重要性

HODL 和两个 ML 策略的回测统计量
检查图表!你看到了吗?终于,我们答对了!等等,让我检查一下漏气的 SR?零?过度装配的迹象…那么 MCC 呢?再次接近零!我们真的认为一个几乎随机的模型可以击败我们的基准吗?我们不能相信这个结果!
瑞士瑞信银行集团股份公司



与 HODL 基线相比,CS ticker 上两种 ML 战略的回报、累积回报(即业绩)和特征重要性

CS ticker 上 HODL 和两个 ML 策略的回测统计
好吧,如果它在 DB 上工作得这么好,也许它是关于在欧洲?让我们看看瑞士瑞信银行的股票吧!而且……我们又失败了:)
汇丰(汇丰控股有限公司)



与 HODL 基线相比,汇丰股票市场上两种洗钱战略的回报、累积回报(即业绩)和特征重要性

汇丰股票上 HODL 和两个 ML 策略的回溯测试统计
出于好奇,我与另一家欧洲银行汇丰银行(HSBC)尝试了这一策略,从视觉上看,它看起来非常积极,但同样,魔鬼在于模型性能和 MCC——我们只是在 ML 模型上再次走运,实际上没有学到任何有用的东西。
荷兰国际集团



与 HODL 基线相比,ING ticker 上两种 ML 策略的回报、累积回报(即业绩)和特征重要性

HODL 的回测统计量和 ING ticker 上的两个 ML 策略
我想以积极的方式完成实验,然而,奇迹,如果发生的话,不是在定量金融中,尤其是如果我们正确地衡量一切;)从业绩和 MCC 战略来看很好看,不幸的是,已经把 SR 缩小为零——样本外表现不好的可能性很大。此外,如果去掉底部特征,它的性能会更差,这本身就很奇怪。
结论
我们所做工作的主要结果是简单明了的——我们学会了如何从比过去更多的维度来评估基于 ML 的策略的回溯测试。我们需要与模型的过度拟合、多重比较和“黑箱化”作斗争,要解决这些问题,我们需要首先发现它们。新提议的统计做了以下工作:
- 用非线性模型解释数据中的因素
- 解释模式和战略绩效之间的联系
- 丰富概念“超越基准”
- 给出关于泛化和过拟合的提示
然而,结果是令人沮丧的,但我希望,没有人期望我们可以通过书中的几个公式实际上击败市场,并创造新的经济发现:)检查我们可以看到的重要特征,不同的报价器之间没有共识——所有时间不同的因素都在顶部,这不允许我们建立一个强大的理论关于驱动银行股的统计因素。我们能做些什么来弥补呢?
- 发现定义银行间差异的新特征——基本面、宏观、替代数据——2020 年依靠统计因素并不明智;)
- 改变超参数 —谁说的 5 年训练,3 年交易,14 天平均窗口等等和正确的数字?我们实际上需要运行超参数搜索来找到最优值。我们将在下一个帖子中详细检查它,同时检查我的这篇文章(这里和那里有许多错误,但搜索部分是正确的)
- 在特性重要性上多下功夫——我们看到,几乎在所有情况下,移除底层特性都会对 ML 策略有所帮助。也许我们需要移除更多?或者对特征重要性应用更好的算法?或者既然我们观察到过度拟合,也许我们不仅可以移除底部特征,还可以移除顶部特征?;)
在下一篇博文中,我们将更深入地探讨我们今天介绍的概念。我们将开发模拟和数据扩充的方案,而不是在一个历史数据集上计算这些数字,我们将得出的不是点估计,而是概率解释。谁知道呢,也许我们的模型在一个时间序列实现上表现很差,但是在这个尺度上,它们是相当可靠的?敬请关注,不要忘记查看源代码:)
附言
如果你觉得这个内容有用,有观点,可以在 Bitclout 上支持我。你也可以在脸书博客或 Linkedin 上与我联系,在那里我会定期发布一些对媒体来说太短的人工智能文章或新闻,并在 Instagram 上发布一些更私人的内容:)
金融中的人工智能:如何最终开始相信你的回溯测试
模拟、风险和指标
来自历史数据和模拟的组合和基于场景的回溯测试

插图来自 https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3544431
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
让我们拆解回测,让它们再次变得伟大:)在上一部分中,我们已经用历史数据和与策略性能相关的标准度量回顾了经典回测例程的主要危险。我们引入了与数据、模型、效率和交易相关的新的统计组,这些统计组可以提供关于潜在战略的更多见解。

这篇文章将是关于我们的初始数据集潜在的无限翻倍,来自https://harrypotter.fandom.com/wiki/Doubling_Charm的 GIF,没有侵犯版权的意图
然而,如前所述,对某个具有众多变量的极其复杂的随机过程所产生的单一历史路径进行回溯测试似乎根本不够。它既不允许概率解释,也不允许基于情景的战略观点。这篇文章的第二部分是关于为我们打开一个更广泛的方法来验证我们的定量策略的技术:
- 通过交叉验证进行回溯测试:首先,我们将开始一项技术,该技术允许使用交叉验证对随机数据进行采样,而无需知道明确的数据生成模型;
- 对合成数据进行回溯测试:然后,我们将展示如何使用随机建模和生成样本路径进行回溯测试;
- 基于压力情景的回溯测试:最后,我们将检查如何在控制主要因素的情况下对合成数据进行采样,从而允许我们对异常情况进行建模。
像我最近的大部分文章一样,这篇文章的灵感来自洛佩兹·普拉多博士的书,我推荐他们深入探讨这个话题。一如既往,你可以在我的 GitHub 上找到的来源。
通过交叉验证进行回溯测试
长话短说,我们希望有一个以上的历史路径来检查我们的战略绩效。我们可以从历史数据中以某种方式取样,但是用什么方式呢?我们可以从整个数据集中选取不同时间的不同部分作为训练集和测试集。为了生成这些部分,我们已经知道了机制——它被称为交叉验证。出于我们的目的,我们需要尽可能丰富的一组模拟——子集的所有可能的组合用于训练和测试算法,这为我们带来了组合净化交叉验证算法:

组合交叉验证时间序列分割图。行代表我们的初始数据集和列的 6 个分割—回溯测试路径。插图来自https://www . Amazon . com/Advances-Financial-Machine-Learning-Marcos/DP/1119482089和http://www.quantresearch.org/Innovations.htm
例如,我们将整个数据集分成 N = 6 组 G1…G6 ,从中随机抽取 2 组进行测试。因此,我们可以有 15 个分割选项,如上面的列 S1…S15 所示。在每个分割中,2 组用于测试,4 组用于所有组合都存在的训练。现在,我们可以对我们的算法进行比单次回测多 15 倍的测试,并获得相关夏普比率和其他风险度量的分布。尽管有这些优点,这种方法也有一些缺点:
- 它不允许历史解读,
- 数据泄漏是可能的,需要单独解决。
合成数据的回溯测试
组合清除交叉验证是一个强大的工具,但它将我们限制在可用数据的子集。在金融数学中,我们使用蒙特卡罗模拟成千上万次来获得精确的估计。例如,在衍生品定价中,我们使用随机微分方程来模拟基础价格,根据方程的不同,这些随机模拟可能看起来非常不同:



几个随机过程和相应方程的图解。从左至右:几何布朗运动、Merton 跳跃扩散模型、均值回复模型;插图来自http://www . turing finance . com/random-walks-down-wall-street-random-processes-in-python/#
这种模拟可以给我们许多不同的回溯测试数据,但我们在这里有两个问题:我们不知道从的哪个随机过程中抽取金融数据,以及如何重新创建外生变量如基本面、情绪等。
- 第一个问题可以通过校准过程解决,即找到漂移、波动性、跳跃概率、均值回复系数等参数的精确值。
- 第二个更复杂。在我用于实验的代码中,我正在训练一个单独的机器学习模型仅使用收盘价来预测高、低、开盘价和成交量。看起来有点过了(和过拟合),但是我们不打算在这里预测任何东西,只是复制潜在的动态,因此,它或多或少是合法的(但是值得怀疑,如果你知道更好的方法,请告诉我)。
最终结果是回溯测试度量在不同场景中的分布,与组合交叉验证方法相同。
压力情景回溯测试
模拟也可以用来产生我们感兴趣的特定政权和场景。例如,我们有兴趣知道在市场突然下跌的情况下我们的策略会如何表现。我们该怎么做?如果我们只看历史数据,我们可以根据市场找到 2-3 次这样的危机。在这里,蒙特卡罗模拟再次有用,但我们需要非常仔细地选择特定随机过程的参数:对我们测试这种策略所针对的确切风险进行建模。例如,对于上述市场下跌,我们可以用负的跳跃大小和相应的频率来模拟跳跃扩散过程。
还有其他数据驱动的方法来模拟基于生成式机器学习模型的现实场景,如 GANs。对于收益时间序列生成和相关矩阵采样,有几种有前途的方法:



那些相关矩阵是真实的还是由 GAN 生成的?在http://www.corrgan.io/predict检查自己
然而,通常情况下,GANs 不允许我们控制场景生成,因为神经表征是纠缠不清的,也就是说,我们不知道操纵漂移、波动或其他金融变量的“按钮”在哪里。变分自动编码器在这里可能是一个有趣的方法,我不久前写了一篇关于解开表征学习的文章,可能对这里有用。

简要说明 beta-VAEs 试图从原始数据中理清不同的市场属性。更多详情请访问 https://towards data science . com/gans-vs-odes-the-end-of-mathematical-modeling-EC 158 f 04 ACB 9
数值实验
让我们像在上一篇文章中一样,以德意志银行股价数据为例。基于 ML 的策略的回溯测试看起来非常好,直到我们意识到在其他银行这种方法失败了,这不允许我们认为我们的财务发现是可信的。现在,我想展示一下,我们如何在不看类似市场参与者的情况下实现这一点,而是使用这些指标的概率解释。
组合交叉验证
让我们重新排列价格时间序列的第一部分,以生成 15 个训练和回溯测试路径(正如我们上面讨论的)。我们可以在下面的一些插图中看到,我们的回溯测试数据已经有了不同的市场机制和方向,这立即允许基于场景的验证:



基于 DB 时间序列分割的十五个训练和回溯测试数据组合中的三个



在回测数据中,平均 MCC、其标准偏差以及两者之比的直方图表示为“MCC 夏普比率”
让我们假设风险是可接受的,并绘制战略夏普比率、收缩夏普比率和概率夏普比率的直方图(更多详细信息,请参见上一篇文章)。与 MCCs 直方图相比,我们可以在夏普比率中看到一个“更胖”的左尾,更重要的是,在这些回测中零值收缩夏普比率的总流行率,这意味着我们的结果容易出现重复实验的问题,并且不可靠。



回测数据的夏普、缩小夏普和概率夏普比率直方图
正如我们所看到的,一个单独的走查不能向我们揭示这些问题,简单的组合交叉验证已经显示了比点度量估计更多的内容。
蒙特卡罗模拟
如果组合交叉验证如此有效,我们能用随机模型的模拟做什么呢?让我们看看下面的 DB 价格时间序列,它是如何表现的?什么随机模型和什么参数在描述它?



DB 收盘价时间序列和一些模拟。动力学看起来差不多吧?
我们可以清楚地看到一些跳跃(顺便说一下,还有随时间变化的波动),但为了简单起见,让我们假设这个过程遵循Merton 跳跃扩散模型,漂移和波动取自历史数据(-3.036e-05,0.02789),跳跃强度、大小及其标准偏差选择为“肉眼可见”(0.1,-0.01,0.001)。让我们模拟这种接近价格时间序列的几条路径,预测相应的低、高、开盘价,以及在这些生成的路径上的交易量和回溯测试策略。



回测数据模拟#1:模拟数据本身,不同装袋运行的 MCC 直方图,以及相应的策略回测
从第一个例子中,我们可以从多次运行 bagging 分类器计算的 MCC 分布中看出,平均而言,我们的样本外模型精度为负。它应该阻止我们运行回溯测试,但是出于好奇,让我们这样做,我们可以看到,这样的回溯测试可能是骗人的——即使模型很差,它也优于基准测试!很好地指出了上一篇文章关于正确的指标计算和跟踪的重要性。



回测数据模拟#2:模拟数据本身,不同装袋运行的 MCC 直方图,以及相应的策略回测
重新启动模拟给出了类似的熊市时间序列,但现在随着时间的推移有了更多的跳跃(看起来更类似于原始的 DB 时间序列),但 MCC 的分布再次给出了负结果,回测再次产生误导。
当然,如果我们对这一时间序列进行更多次的重新采样,并构建这种预测的直方图,我们将清楚地看到模型精度中的一个肥胖的左尾巴,这将清楚地向我们发出信号:如果我们以非常相似的动态对数据进行采样,但与历史数据略有不同,那么我们最初的金融假设不再成立。如果我们做了正确的初步研究,就不会出现这种情况:)
结论
在这篇文章中,我们回顾了允许概率回测与历史回溯测试相比较的技术。后者的主要问题是,它只是一个复杂随机过程的单一实现,这个过程可能有许多不同的方式,我们不希望从一个分布中过度拟合一个样本。
我们使用了两种主要技术来解决这个问题:组合交叉验证和随机模拟,每种技术都有其优点和缺点。在之前的文章中,我们已经看到我们基于 ML 的策略在 DB 股票价格上表现良好,但是对银行业其他资产的实验表明,这一“发现”并不能推广到市场。在这篇文章中,我们已经表明,如果我们不使用走前估计,而是使用组合 CV 或随机模拟,我们可以看到,即使不检查市场上的其他资产,这种策略也是不可靠的,这可以节省我们的研究时间。
我们研究了更多关于回溯测试性能的额外指标,并将它们扩展到概率估计。我们这样做是为了评估我们的策略在样本外表现不佳的风险,这与测量这些策略的“过度拟合】相关。我们还知道,过拟合是样本内和样本外性能之间的权衡,在这两篇文章中,我们只关注 OOS 的情况。在这个简短系列的下一篇,即第三篇文章中,我们将关注其他考虑样本内数据的过度拟合风险的度量,并以测试量化交易策略的一般框架结束。敬请关注,不要忘记查看源代码:)
附言
你也可以在脸书博客或者 Linkedin 上与我联系,在那里我会定期发布一些对媒体来说太短的人工智能文章或新闻,以及 Instagram 上一些更私人的内容:)
工业中的人工智能:一个维护程序如何毁了我的机器学习模型!
基于一个真实的用例,发现为什么在建模一个工业过程时你应该总是注意维护活动……以及如果你不这样做该怎么做!

亚伦·巴纳比在 Unsplash 上拍摄的照片
机器学习的挑战:
许多数据科学家确实同意在实际使用机器学习算法之前进行数据准备的重要性。这一挑战通常被描绘成下图左侧显示的冰山。
第二个挑战可能是将概念验证(P.O.C .)转移到真实环境中,在真实环境中实时收集数据并将预测集成到现有的数字基础设施中。

(冰山绘图来源:fr.123rf.com)
但是,在我看来,最大的挑战是创造一个可以长期持续的解决方案:

(冰山绘图来源:fr.123rf.com)
令人高兴的是,工业过程通常不会像人类消费者那样在一夜之间改变他们的行为。(如果你需要一个奇怪行为转换的例子,只需记住当第一次 COVID 锁定开始时卫生纸短缺是多么不合理,人工智能系统应对它是多么困难!)
但是,即使是工业机器学习模型也可能会偏离,因为它们的鲁棒性也依赖于数据科学的 3 个公理:

(图标来源:flaticon.com 的 Freepix)
从好…到伟大…到更坏!
对于每一个建模项目,从一个运营团队带着一个要解决的用例来找我,到质量预测以相当高的准确度实时显示在控制室的仪表板上,我花了几个星期的时间。
然而,几个星期后,预测准确性的突然漂移使我质疑整个模型的稳健性,进而质疑工业过程的稳定性!

预测的趋势似乎不错,但总是被低估。
我们可以从“绝对误差”度量的角度来看待它:

上个月的预测准确度(MAE)
我们看到,过去四天的预测超出了我们与团队定义的稳健性阈值(2,2),并且显著高于 0.9 的平均绝对误差(M.A.E .)。

我并没有花很长时间去检查和理解发生了什么:一个为期 6 个月的全面维护已经在周末进行了!
让我们来了解一下我们是如何分析数据的变化,从而使模型立即回到正轨的!
精度漂移的三个潜在原因
1)设备的完全更换
让我们想象一下,你用一台全新的压缩机替换了一台 40 年的旧压缩机。
是的,除了电场强度、压力、转速等,它的基本工作原理是一样的。测出来会完全不一样。
这可能是最糟糕的情况,因为预先收集的数据现在已经过时。更不用说车间布局或设备类型(从燃气转换为电力)也发生变化的情况了…
这里没有魔法:最简单的解决方案是收集新的数据,根据您以前的配置经验,可能将重点放在最相关的特性上…
2)测量系统的变化
全面维护不仅仅意味着更换备件或润滑剂;也可以是重新校准传感器、探头等。
我们的模型使用 8 个特征来预测产品的质量,所以我决定看看测量值是否有显著变化,因为尽管有维护工作,系统应该是相当稳定的。让我们来看看维护停止前 30 天和维护停止后几天的每个特性的中值:

(出于保密原因,对数据进行了清理)
八个特征中的三个,包括最重要的一个(中的流速),似乎发生了显著变化。
但是我们知道“水流 1 ”和“水流 2 ”回路可以交替使用(一个优先于另一个,反之亦然),并且总流量应该保持稳定。我把这两个特征相加,检测是否有真正的变化;这并不明显。我对流出的流量做了同样的分析,同样的结论:

因此,似乎模型的最关键参数(进气流量)的测量值发生了变化,并且很可能在完全相同的物理情况下增加了 5%!(这一点后来得到了维修团队的确认,他们重新校准了相应的传感器)
因此,为了保持整个数据集的一致性,我决定在维护和重新训练模型之前对所有值应用+5%的增量。

在更新的数据集上重新训练模型后,上个月的预测准确度(MAE)
即使不完美,新模型也表现得更好,维护后的平均寿命从 3.5(原始状态)下降到 1.6。
(注意:在两种情况下(原始模型和更新模型),算法仅使用维护工作之前获得的值进行训练;这里没有目标泄漏!)
3)缓慢的性能下降
这种突然漂移的最后一个可能原因是,随着时间的推移,过程的性能已经慢慢下降…这就是为什么我们需要定期执行日常维护的第一个原因!
让我们来看看最近两次维护操作之间的流程性能:

同样,在过程的自然变化之外,下降趋势是明显的,直到我们达到某种平稳状态!
现在的问题是:我们如何将这些信息集成到模型中?
一种可能的选择是简单地添加自上次维护工作以来经过的天数。
但是我建议以较低的频率提供“维护”信息。
提供较低频率的信息就像迫使模型在一个移动范围内工作,从而使过程的自然高点和低点变平。
例如。:如果您每天都获得预测和相应的结果,请提供自上次操作以来经过的周数。
因此,模型将更容易确定该特征的重要性。
如果您以决策树的形式考虑它,它可能看起来像:

每次修正都对应于该期间的平均业绩下降。
显然,您需要几个周期来集成到您的数据集中,以便模型可以学习此模式,但是能够包括此信息(在本例中为 4 个维护周期)使我们的模型在维护重启后达到了更低的 m . a . e . 1,2。
总之,获取维护周期信息和所收集数据的潜在变化对于确保您的模型能够长期持续至关重要!你可能会想到!
数据科学、机器学习和创新
pl-bescond.medium.com](https://pl-bescond.medium.com/pierre-louis-besconds-articles-on-medium-f6632a6895ad)
工业中的人工智能:如何利用传感器的准确性来创建增强数据
了解如何通过估算传感器的准确性来扩充数据集,从而克服标注数据的不足。本文通过使用 Tensorflow 和 Scikit-learn 在一个工业案例上的实际实现来说明。

深度学习算法确实需要大量的数据!(委婉……)
当可用的标记数据不足以达到良好的准确度水平时,用于图像识别的标准技术是创建“增强图片”。
原理很简单:你可以创建同一只狗的人工图片,并进行或多或少的细微变化,这将有助于你的模型微调其网络权重,并最终提高其准确性,而不是只给你的深度学习算法提供一张狗的图片。
原始图片的经典修改将会以以下形式出现:
- 对称(水平、垂直)
- 旋转(角度)
- 宽度或高度移动
- 缩放、剪切、颜色或亮度变化
它们可以用 Tensorflow 中的几行代码轻松实现:

伯爵,我可爱的狗🐶(原图)
from tensorflow.keras.preprocessing.image import ImageDataGeneratortrain_datagen = ImageDataGenerator(
rotation_range=10,
horizontal_flip=True,
vertical_flip=False,
width_shift_range=0.1,
height_shift_range=0.1,
#zoom_range=0.2,
#brightness_range=(0.1, 0.9),
#shear_range=15
)
我总是对我的狗很好(即使是虚拟的!)所以我故意限制了转换!

扩增克隆人伯爵!
很容易理解,这种机制对于图片来说是合理的,因为这些变化不会影响主体,并且它还将帮助您的模型解释具有不同方向、颜色等的狗图片..
是否有可能将该技术应用于工业过程数据,以达到更高水平的预测准确度?

让我们探索一个我过去工作过的用例。数据集(经过净化、规范化和预处理)存储在这里并且具有 250 x 52 的形状。
尽管每周 7 天、每天 24 小时、每 30 秒测量一次工艺参数,但由于获取一个样品的难度和成本,对应于最终产品浓度的标签数量是有限的。采样频率通常在 3 到 4 天左右。
这个小数据集的每一行都对应于在获取样本之前的最后 30 分钟内过程参数的平均值。
在评估了“经典”机器学习模型(RandomForest、SVM 和 GradientBoostedRegressor)之后,我惊讶地发现,根据所选的度量标准:平均绝对误差,一个简单的 Keras 模型正在实现最佳精度。
这个“不太深”的学习架构设计如下:
model = keras.Sequential([
# The 1st layer as the same shape as the number of input features
layers.Dense(df.shape[1],
activation='relu',
input_shape=[X.shape[1]]),
layers.BatchNormalization(),
layers.Dense(12, activation='relu'),
layers.BatchNormalization(),
layers.Dense(1)
])
深度学习模型没有嵌入式交叉验证方法,因为在处理大量数据时通常不需要。
然而,当处理这样的小数据集时,训练/测试分割操作可以输出非常不同的配置,并且确实需要一个。
经过 5 k 倍交叉验证后,该 Keras 模型的平均绝对误差达到了 2.4 (相当于 4%的相对误差)。
是的,这不是一个非常高的精度,但从现场的角度来看,这仍然意味着从"盲目地在每个样品之间""切换到""在每一个时刻获得一个非常好的产品浓度估计值!”
让我们来看看这篇文章的核心:我们的样本测量过程的统计评估(通过 ANOVA gauge R & R)确定了一个 2%的相对准确度。
简而言之,当我们测量 100 时,真实值可能是 98 到 102 之间的任何值。
当我与一位专门从事深度学习和图像识别的数据科学家同事讨论时,我抱怨说,我不可能像他那样为工业过程产生增强数据!
这就是他建议利用传感器的准确性来创造人为值的时候!
**X1, X2, X3, ..., X51 => Sample measurement at 100**could actually corresponds to:**X1, X2, X3, ..., X51 => Sample measurement at 98**
or
**X1, X2, X3, ..., X51 => Sample measurement at 99.5**
or
**X1, X2, X3, ..., X51 => Sample measurement at 100.2**
or
**X1, X2, X3, ..., X51 => Sample measurement at 101**
etc.
问题是:它是否会帮助我们的模型获得比仅用初始数据集训练时更高的精度?
答案是…

乔恩·泰森在 Unsplash 上的照片
至少,对于这个非常特殊的用例!
我玩的“超参数”是:
- 传感器的估计精度:我决定谨慎行事,只考虑 1%
- 初始数据集的复制因子:我用过 1,2,5,10。这是什么意思?
复制因子为 2 时,最终数据集将是以下内容的组合:
-
初始数据集
-
一个扩充数据集,基于初始数据集,但其大小是初始数据集的两倍,标记的数据与原始值相差 1%:
Initial row: **X1, X2, X3, ..., X51 => 100**Final rows:
**X1, X2, X3, ..., X51 => 100 (initial)
X1, X2, X3, ..., X51 => 99.5 (augmented)
X1, X2, X3, ..., X51 => 100.2 (augmented)**
我见证的改进如下:

MAE Initial: 2,404342MAE (Replication x 1): 2,222344 (-0,18)
MAE (Replication x 2): 2,240588 (-0,16)
MAE (Replication x 5): 2,200172 (-0,20)
MAE (Replication x 10): 2,343116 (-0,06)
这种方法有明显的好处,但我想补充以下注意事项和警告:
- 复制因子的“最佳点”似乎位于 2 和 5 之间: -低因子(< 1)不会对数据集产生真正的显著改进。
-超过 5 将开始添加许多与实际值相比的随机值,精确度的提高可能会很快下降(只要看看 10 个复制因子的结果)。 - 我没有试图增加 X 数据集,因为这里的例子中的输入特征已经是过去 30 分钟的平均值,因此,与“y”上的唯一采样相比,不容易出现不准确。
- 一些非常特殊的训练分割配置(尤其是在非常小的数据集上)与不利的扩充数据随机化相结合,可能会导致实现比初始模型性能更低的性能。
- 只能在列车测试分割后执行增强过程!否则,一些几乎相同的值将落入训练集和测试集中。该算法将很容易推断出测试集中的值,如果它已经用它的几乎孪生兄弟训练过的话…这将错过训练和测试样本的全部意义。
长话短说:像往常一样,盲目复制粘贴这种技术是有风险的!
为了帮助您自己运行这个示例,并可能提出一些问题、评论、顾虑或想法,这里有相应的笔记本(最初创建于 Google Colab)。
请注意,出于保密原因,带标签的数据(y)也已标准化。因此,你应该在 0.035 和 0.055 之间找到 MAE。
数据科学、机器学习和创新
pl-bescond.medium.com](https://pl-bescond.medium.com/pierre-louis-besconds-articles-on-medium-f6632a6895ad)
工业中的人工智能:为什么你应该同步时间序列中的特征
用几行代码提高模型的准确性,避免这个常见的陷阱。

Alexander Schimmeck 在 Unsplash 上的照片
你不需要成为数据科学家就能体会这种感觉:现在是冬天,你早上打开“热”水龙头,需要几秒钟(有时更久)水才能从冷的温度升到理想的温度。
原因很明显:热水需要时间从锅炉流到你手里。而且,换个说法,这两件事(要热水和得到一些)是“不同步”的。
如果你想在 t 时刻达到一个特定的温度,你必须预测水通过管道需要多长时间。
这与工业中的建模过程有什么关系?

当您提取历史数据时,通常会得到一个带有时间戳的时间序列作为索引。该时间戳对应于记录值的时间:

让我们假设产品的“粘度”是您的目标特性,并且在您的温度传感器和粘度计之间有一根 200 米长的管道。
当您在 06:06 测量粘度“ 61 ”时,同一时间测量的温度(10.8°C)是否会导致此结果?除非流量真的很快,大概不会!那么在建立机器学习模型时,应该考虑什么温度呢?

从工程的角度来看,你可以试着确定流速、管道直径等。猜猜产品从 A 到 b 需要多少秒。
从数据科学的角度来看,您可以使用数据本身来确定这种“不同步”并对其进行处理!
像往常一样,没有什么比一个简单的例子更好地理解我们如何应对这个问题了。
我们将创建 3 个循环特征(x1、x2 和 x3)和相应的目标“y”,作为所有这些特征的加权组合。

让我们来计算一下(显然很强!)x1、x2、x3 和 y 之间的相关性:
**df.corr().loc["y",:]**x1 0.989357
x2 0.961574
x3 0.990654
现在,让我们在 x 特征和 y 特征之间引入一个随机延迟,因为在现实生活中,在“x1”、“x2”或“x3”上的变化确实影响“y”上的测量之前,应该需要几秒、几分钟甚至有时几小时。
(x1 移至-34;x2 移至-32;x3 偏移了-19)
这里的滞后现在是"视觉上明显的"但是让我们记住真实的情况要复杂得多!

我们现在可以将这个数据集视为我们的基线,因为“去同步特征是我们在现实生活中会得到的。正如您在下面看到的,功能之间的相关性已经急剧下降:
**df.corr().loc["y",:]**x1 x1_shifted
0.989141 -> 0.748233x2 x2_shifted
0.959595 -> 0.706007x3 x3_shifted
0.990252 -> 0.914779
现在只需循环每个特征并增加偏移值,以观察系数相关性如何演变。
当它达到其峰值时,那么它应该是目标和所述特征之间的实际滞后:
Best shift of x1_shifted at 34 with 0.9887480759856975
Best shift of x2_shifted at 32 with 0.9584397947951305
Best shift of x3_shifted at 19 with 0.9899320966442271
这与数据集中引入的初始滞后相匹配! (如果你没有看过,它们写在执行功能转换的代码下面。)
我们还可以查看 15 和 40 之间的行,以再次检查这些等级是否确实对应于相关峰值:

我们现在可以获取初始数据集,并根据相应的滞后移动每个要素。由于这一点,机器学习算法将创建一个模型,其中目标及其影响参数很好地同步,并获得最佳的潜在结果!
像往常一样,在我们结束这篇文章之前,有一些评论:
- 无论何时运行模型来预测目标,“实时”数据集也应该以同样的方式重新同步。
- 运行" pandas 时使用的默认关联方法。DataFrame.corr 为“ Pearson ”,适用于线性关系。如果你假设你的特征和目标有非线性关系,那么“ Spearman ”等级相关系数将是一个更聪明的选择。
- 我发现了一些案例,其中一个数学奇点导致了一个从物理角度来看不可能的转变提议(太远或太近)。这就是为什么与现场专家交叉验证这些变化总是更好。
- 深度学习架构,如长短期记忆(LSTM)神经网络也有能力管理这种特征的重新同步,但从计算角度来看,它通常更重。
数据科学、机器学习和创新
pl-bescond.medium.com](https://pl-bescond.medium.com/pierre-louis-besconds-articles-on-medium-f6632a6895ad)
日冕时代的艾
当过去与现在不再相关,我们如何预测未来?
如何在异常事件和极端环境中建立生产 AI/ML 的弹性

由车在拍摄
极端环境的挑战
冠状病毒是 2020 年的黑天鹅。不仅病毒的最初出现是一个意想不到的极端异常事件,人类试图遏制病毒的反应正在通过运行世界的系统产生巨大的涟漪——健康、商业、金融、零工经济、信贷、商业、汽车交通和旅游,仅举几例。
黑天鹅事件给机器学习(ML)模型带来了特殊的挑战。ML 模型根据以前看到的观察结果进行训练,以预测未来的情况。然而,今天这些模型看到的事件与他们曾经接受的训练完全不同。许多企业(尤其是在信贷和金融领域)有 100 到 1000 个实时生产模型在他们的组织中运行,对影响他们未来业务成果的数据做出不正确的决策。未来几天/几个月可能出现问题的模型包括信贷、房屋定价、资产定价、需求预测、转换/流失模型、演出公司的供需、广告定价等等。
建立一个模型来预测模型从未在训练数据中观察到的场景是很困难的。标准的模型训练过程将尽可能多的数据投入到模型中,并帮助拟合跨事件通用的数据结构。真正的黑天鹅事件没有足够的跨其他事件的可学习结构,留给人们来填补数据和模型空白。那你是做什么的?
在这篇博文中,我们将首先通过进入系统的一些极端范围的数据点来量化这个黑天鹅事件。其次,我们将介绍一些最佳实践,以便通过对生产模型进行强大的监控、分析和故障排除来掌控异常事件。
我们当前的环境有多极端
我们先问一下,现在的环境到底有多极端?
是非常极端。
当您查看今天从天气、失业数据、交通模式、用户支出进入生产模型的输入要素数据时,它将与模型的训练数据大相径庭。我们来量化一下。
首先,看看本周刚刚公布的失业数据。328 万人申请失业的读数是第二高读数的 4 到 5 倍,是一个+25 倍的 sigma 事件。

1995 年至今作者图表,资料来源——美国就业与培训管理局
任何使用失业数据作为输入并根据该数据做出决策的模型都使用了一个超出期望值超过20σ的特征。这是一个预计每 10 万年发生一次的事件!这只是一系列极端事件中的一个例子,这些极端事件正被输入到制定日常商业决策的模型中。
一个模型不可能完美地处理每一个意外的输入。记住这一点,重要的是要考虑整体系统对这些输入的弹性以及在问题出现时进行故障排除的能力。最重要的是团队要有可观察的模型;如果你不能观察,你就不能适应。这意味着对模型决策进行检测+分析。
所需的模型可观测性:
- 异常事件应该是可以检测到的,并且会自动浮出水面
- 异常值事件应与分析联系起来,以便对模型响应进行故障排除
很明显,失业数据将会严重偏离分布。
让我们看看汽车交通的数据。

来源于 TomTom 国际
纽约市从周三(3 月 18 日)到周二(3 月 24 日)测量的交通流量。上周,流量已降至日流量的 20%左右,或日流量的 1-10%。
这一跌幅远远超出了预期的每日价值,也只是一个模型可能预期的一小部分。

来源于 TomTom 国际公司
据测量,迈阿密的交通流量没有纽约下降得多。看起来迈阿密人不像纽约人那样积极接受隔离。在这种情况下,使用交通量作为输入要素进行特定于城市的预测的 ML 模型的输入变量会因城市而异。
所需的模型可观测性:
- 监控输入数据的分布变化
- 针对模型输入的强大拼接和过滤功能
在这一周里,我们已经看到人工智能没有为冠状病毒产生的事件做好准备。天气预报预测一直不准确,我们也看到银行考虑人工智能模型可能无法应对市场低迷。
在这些极端时期建立弹性
对于面临这些快速变化的企业来说,目前在生产中使用的人工智能/人工智能模型是根据与今天的情况非常不同的数据进行训练的。
当一个企业的模型之前没有看到这些观察结果时,它应该做什么?换句话说,当过去与现在不再相关时,我们如何预测未来?
随着新冠肺炎继续影响许多人类系统,利用人工智能/人工智能的企业将不得不 在他们的生产环境中建立弹性。随着模型性能的波动,企业需要实时监控生产模型,以了解模型输入是如何变化的,以及模型在哪些方面存在不足。
进去的东西必须出来
这一切都始于数据进入用于生成预测的模型。
如果罕见事件和其他极端事件之间有相似之处,有一些方法可以将预测组合在一起,以创建一个基准期并进行分析。如果一个罕见的事件在输入数据结构中与训练集中的任何其他数据组都没有关系,您仍然需要监视它如何影响模型。
就新冠肺炎而言,这些情景不仅仅是一次性的异常值,而是数以百万计的快速演变的趋势,这些趋势正在世界各地不同的城市发生,所有这些趋势都有不同的时间表和反应。展开场景的规模需要许多不同的分析和检查,跨越许多不同的预测子群。
以下是 AI/ML 模型在生产中应该具备的一些输入级监视器:
- 输入检查,以确定特性的值和分布是否与正常的基准期有很大不同
- 检查单个事件或少量最近发生的事件,检测不在分发范围内的问题
- 检测您的模型最敏感的特征是否发生了巨大变化
- 用于确定特征与训练集的距离的统计数据
模型反应如何?
一旦您知道模型的输入已经改变,接下来要监控的是模型如何响应极端输入。
- 检查特定预测子类的模型性能。某些行业,如能源、航空或旅游,可能存在重大风险。你需要快速在线检查各种预测
- 使用以前的周期来产生最坏情况和基本情况,然后与结果进行比较
- 根据你收到的每一个新的真实事件(真实世界的预测反馈)实时监控预测
- 如果现实世界的反馈由于时间滞后而不可能,那么使用代理指标——您可以预测和测量的东西来确定模型的性能
极端环境下生产 ML 模型的最佳实践
在 Arize AI,我们每天都在思考生产环境中的 ML 可观察性和弹性。我们的目标是在这个不确定的时期将我们的一些经验传授给你的团队。生产 ML 模型的最佳实践与生产软件的最佳实践相差不远——构建可观察性工具,以了解模型或软件处于活动状态时发生的情况,从而在问题影响您的客户之前发现问题。
根据我们在许多公司部署 AI/ML 模型的背景,我们分享了在这些极端环境下生产 ML 模型的一些最佳实践。
- 跟踪和识别异常事件
这包括跟踪异常事件的输入数据和模型性能。注释这些事件并能够过滤异常事件有助于为未来的极端环境收集训练数据。考虑是否在数据中包含异常事件以用于未来的模型训练也很重要。该模型将积极应对未来的极端情况,但它也可能认为极端情况是新常态。
2。决定模型后备计划
在过去,当你的模型没有什么可以借鉴的时候,它会做什么?了解您的模型过去在极端环境中的表现有助于了解您的模型现在的表现。如果你的模型表现不好,你能根据最近 N 分钟或 N 天建立天真的预测,并将你的模型表现与这个天真的模型进行比较吗?
3。寻找相似事件
你对过去的类似事件有足够的观察能力来为当前的情况建立相似的模型吗?例如,如果您的模型将失业数据作为输入,您可能能够利用类似经济衰退(如 2008 年衰退)的失业数据。
4。构建多样化的模型组合并比较模型性能
对外部世界做出反应的实时模型今天可能比批量预测表现得更好。拥有多样化的模型组合使团队能够比较模型性能,并将流量路由到对极端环境反应更好的模型。
5。当模型性能无法提高时,要知道模型预测的不确定性。
有时候,可能没有好的模型。在这些情况下,你知道你的模型有多不确定吗?在这种情况下,考虑一种贝叶斯方法,在这种方法中,返回模型的预测及其置信度。
保持安全并监控您的模型!
参考
感谢优步市场高级工程经理钦坦·图拉希亚对本文的编辑。
联系我们
如果这个博客引起了你的注意,并且你渴望了解更多关于机器学习可观察性和模型监控,请查看我们的其他博客和关于 ML 监控的资源!如果您有兴趣加入一个有趣的 rockstar 工程团队,帮助模型成功生产,请随时联系我们,并在此处找到我们的空缺职位!
人工智能是一个无限的游戏——你的公司有合适的游戏计划吗?
许多公司仍然在努力为他们的业务采用更大规模的人工智能。他们心态的转变可能有助于他们做得更好。

AI 是一个无限的游戏。(图片由 iStock photo 提供)
需要什么类型的战略思维来充分发挥人工智能和数据智能的潜力?
受 Simon Sinek 的“有限”与“无限”策略概念的启发(“无限游戏”,2019 年),本文试图挑战组织和领导者在从事人工智能(AI)计划时的思维模式。你如何参与这项改变游戏规则的技术,在人工智能和机器学习概念不断发展并改变业务基准的市场中,你需要什么来保持竞争力?
我认为目前的许多方法都存在根本性的错误。人工智能采用计划通常仍然是半心半意的,甚至是市场和投资者的托辞活动。但是,这样一个要求苛刻的环境需要一个适当的长期愿景和战略,这足以推动必要的业务和组织变革。这就是 Sinek 描述的“无限”心态。相比之下,“有限的”人工智能策略更关注眼前的挑战,比如通过为产品添加单一智能功能来赢得当前市场,或者通过基于自动化的成本降低来击败当前竞争对手。这可能是一个聪明的开始方式,但如果不致力于更长远的愿景,这是否会混淆为旅程建立组织所急需的战略投资重点。
然而,需要强调的是,不应孤立地看待人工智能。它是一个更大的数字技术和概念生态系统的先锋,目前正在改变我们周围的世界。
几年来,IT 行业一直在谈论人工智能能力的更广泛采用——甚至产业化。我们可以看到基础技术、数据和解决方案生态系统以及多行业概念采用方面的显著进步。期望仍然很高。例如,普华永道 2017 年的一项研究预测:“2030 年,人工智能可能为全球经济贡献高达 15.7 万亿美元,超过中国和印度当前产出的总和 ”
我们还没有看到的是,全球对人工智能的巨大投资如何接近为大多数企业产生相应的结果。一些精通数据的公司正在努力取得成功,并在旅游、保险、投资或娱乐等行业树立了新的基准。然而,许多组织仍然在努力应对人工智能的新世界,许多人工智能计划仍然没有比概念证明或原型状态更进一步。
但是,如果试错是任何创新过程的自然组成部分,为什么这是一个挑战呢?问题是,这些公司中的许多根本不适合迭代创新过程,因此很可能在他们有机会成熟之前就停止努力。所谓“速赢”和“快速结果”的僵化文化限制了有效人工智能和数据驱动创新的机会空间。利用基于数据的自动化或创建智能用户体验既需要颠覆现有流程,也需要基础架构和应用程序具备更高的灵活性。这对于任何遗留系统或思维定势来说都是一个重大挑战。
无限商业思维专注于为执行长期战略创造合适的条件,而不是赢得眼前的短期游戏。在游戏规则不断变化的背景下,这是有意义的,就像人工智能这样的新兴领域一样。我相信,对无限游戏机制的理解可以为公司提供巨大的杠杆,使他们的人工智能工作更加有效。
那么,为什么人工智能的采用是一个无限的游戏——你怎么玩它?
从组织人工智能采用中吸取的经验教训
通过多年参与高级分析、数据挖掘、机器学习和人工智能概念,我的个人和专业热情一直是将这些概念应用到现实世界的商业应用中。与许多优秀的同事一起,我学到了很多东西。然而,许多公司在扩大其人工智能概念和组织时,仍然会遇到非常相似的挑战。
在我看来,这往往是由于对我们所处游戏的误解造成的。这不仅会导致错误的决定;它往往会在一开始就引发错误的讨论。想想自制或购买和技术策略、团队构成或市场策略,以及它们在长期战略承诺下会如何变化。人工智能计划通常始于管理层和组织的善意和热情。然而,令管理层感到惊讶的是,单个人工智能项目很少有积极的短期甚至中期投资回报。基于人工智能的解决方案的启动投资和所需的成熟时间需要更长的投资视角,涵盖概念的多代,并包括相关的用例。项目团队和数据科学家更擅长创建功能,以服务于组织的长期人工智能支持,而不是为少量预定义的问题构建单点解决方案。
人工智能的采用没有明确的开始、中间或结束,只有一个发展能力和扩展数据集和用例的过程。
无限人工智能采用战略的要素
那么,你如何为不断发展的事物做计划,包括技术、生态系统以及不要忘记用户的采用?
- 业务关键用例
健康的人工智能应用最重要的先决条件是强大的用例以及长远的眼光。当数据可用并且建立了最佳实践时,在开始时试验较简单的问题通常是明智的。但是为了确保战略影响和持续的管理,你的人工智能战略需要解决关键业务用例。需要明确的是,将人工智能驱动的概念投入生产从来都不是一件容易的事情。它包括对基础设施、能力、销售和维护流程的重要要求,并且不要忘记专门的合规性和治理。因此,选择的用例必须能够证明所有需要的启动工作。 - 从“人工智能至上”转向“人工智能优先”的理念。实现人工智能概念的全部变革潜力需要重新设计相关的业务流程,通常还需要重新设计底层的业务模式。这意味着组织需要时间来成熟他们的概念理解,从将人工智能能力置于现有结构之上(“人工智能之上”)到围绕人工智能能力重新设计他们的解决方案(“人工智能优先”)
- 敏捷项目管理连接到高层次的长期路线图 承诺。
技术,以及我们对其可能性的理解,都在不断变化。项目优先级和解决方案细节应该能够灵活地改变,并相应地成熟。里程碑很重要,但它们应该用于根据长期战略评估和调整当前任务,而不是用于“停止/继续”评估逻辑,这种逻辑会助长错误的优先级和负面的项目氛围。 - 制造和购买策略
围绕你的人工智能解决方案创造自己的知识产权可能是一项战略资产,但成本高昂,需要持续努力。作为一个经验法则,如果人工智能应用领域接近他们的价值产生过程和核心商业模式,并且如果知识产权难以复制,组织应该只追求它。对于大多数公司来说,这封信将不会围绕开发新的算法或工具,而是围绕数据集和功能的特殊组合,他们为自己的特定用例建模和调整。其他一切都可以而且应该从外部获得,要么是开源的,要么是打包解决方案的专业供应商。
人工智能咨询实践的教训
人工智能的采用不仅对产品和服务组织来说是一个挑战,当将人工智能纳入其咨询和基础设施实践时,对技术和商业服务提供商来说也是如此。此类计划通常始于向现有的分析团队添加数据科学家和/或向他们现有的精通数据的咨询团队添加新技能。这可以产生一个非常强大的技能组合,可以支持从后端应用程序、数据基础架构、分析到数据科学组件的整个数据价值链。
这是一笔巨大的资产,在市场上需求量很大。但这并不能保证成功。许多这样的咨询公司很难通过他们的人工智能计划获得足够多的资金,并且需要多年来通过传统的面包和黄油项目获得资金。
这个问题的一个原因是对人工智能概念更强的应用关注,以及作为人工智能团队的一部分对软件开发和用户体验技能集的相关需求。如果人工智能概念可以推动决策或流程自动化,那么它们将是最强大的,这反过来需要与业务应用程序和流程紧密集成。这是与传统的分析和报告概念的主要区别,传统的分析和报告概念通常侧重于向最终用户呈现见解。
尽管许多服务提供商已经建立了这样的多学科团队,但其中大多数都面临着扩大人工智能相关咨询实践的挑战。在我看来,建立一个成功和可扩展的人工智能咨询产品的成功因素是专注于产品中的一个或几个专门的人工智能用例领域,然后围绕这些领域建立相关的能力集群。一名优秀的数据科学家可以处理任何类型的用例,但扩展业务服务需要围绕一系列用例、选定的行业或选定的人工智能概念建立共享的 IP 堆栈。这是在整个团队中推进方法和工具堆栈以及共享最佳实践的基础,这对相关的营销和销售过程同样重要。人工智能通过用例及相关的好处进行销售,而不是通过使用的方法或工具。这样的人工智能概念可能会让专家们兴奋,但它们的价值很难向最终用户解释清楚。专注于行业或用例的咨询实践可以更好地将客户对话引向新的人工智能功能和相关的商业机会。
一个公司玩无限游戏需要什么条件?
人工智能的采用不是孤立发生的事情。总是局限于一个公司的文化和战略。只有整个公司都做好了玩的准备,知道了无限游戏的规则,才能在新的领域应用。在他的书《无限游戏》中,S. Sinek 定义了一些实现无限策略的一般元素,我认为这些元素提供了一个很好的起点:

图一;无限策略的要素;来源:S. Sinek,无限游戏,2019
推进正义事业
无论你的企业是什么,为了给你的员工提供长期的动力,你需要为你的企业找到并追求一个真正的“正义事业”。正义案例可以是直接或间接有利于社会、人类发展或支持例如地球和自然保护的事情。乍看之下,可能更容易看出这样一个正义的事业对于非政府组织或社会和政府组织来说应该是什么样子。然而,所有组织都是整个社会的一部分,因此可以追求正义的事业。它可以为学校的健康膳食做出贡献,为其他企业提供融资,以促进地区经济发展。其他公司致力于探索技术创新,以推进气候保护或社会包容等社会关键任务,提高人们的生产力。正义的事业激励我们今天、下个月甚至十年后继续玩这个游戏。
信任团队
对于组织的长期成功来说,团队中的相互信任比规则和绩效体系更重要。相互信任为所有人创造了一个富有成效的工作环境,在这个环境中,他们可以感到精神上的安全。一个信任的团队将加强一种支持性的学习文化,这对于多学科团队的最佳运作是必不可少的。数据科学项目高度依赖于团队和组织对过程和结果的批判性评估能力。一个最终的解决方案通常是方向和方法的多次迭代和改变的结果。这种创造性和关键性的合作需要团队成员之间高度的信任和尊重。
值得尊敬的对手
在他的书中,Sinek 对竞争者和值得尊敬的对手做了重要的区分。竞争对手是你试图在争夺合同或客户的“有限”竞争中击败的人。一个有价值的对手是一个能挑战和激励你的人。你们一起定义和发展你们所处的市场。根据 Sinek 的说法,20 世纪 80 年代的苹果是“值得竞争的对手”心态的一个很好的例子,当时他们推出了小型个人电脑,而其他人,尤其是 IBM,仍然在投资客厅大小的商业机器。IBM 加紧了这场游戏,并通过仅经过 12 个月的开发就推出他们自己的个人电脑来应对挑战。苹果随后做出了一个惊人的公关举措,在华尔街日报上用整版广告欢迎 IB,广告中写道:
“欢迎来到自 35 年前计算机革命开始以来最激动人心和最重要的市场。[……]将真正的计算机能力掌握在个人手中,已经在改善人们工作、思考、交流和休闲的方式。”(S. Sinek,《无限游戏》,2019 年)
在由人工智能和数据智能驱动的新兴市场中,制定自己的战略很重要,但同时也要选择值得你追随的对手,然后与之竞争。与此同时,重要的是要明白,这将需要所有或大多数现有的球员,以建立这个巨大的和快速移动的新空间的生态系统。更重要的是,与每个人竞争是为了确定你想在其中扮演什么角色,以及你如何从其他人那里获益
存在的灵活性
在 IT 市场有一种普遍的说法,即公司必须拥抱灵活性,以收获人工智能采用中的转型能力。尽管我非常同意这一点,但我想补充一点,无限的心态是在战略层面上实现灵活性的基本促成因素。只有关注长期愿景和目标,才能提供重新思考方法和策略的自由。相比之下,短期有限的商业策略几乎没有给真正的创造力留下空间。
一家公司的商业思维通常直接体现在组织采用人工智能的优先顺序上。有限采用策略通常从关注成本降低和日常操作的自动化用例开始。虽然这可能会很好地工作,并为公司带来一些短期结果,但它并没有为推动和发展业务模式本身提供实质性的杠杆作用。思维有限的公司通常认为自己被市场的创新者和颠覆者追逐,而无限的参与者则设法释放新技术的潜力,让他们重新定义自己。
领导的勇气
存在灵活性指的是改变你的整个商业模式和取代传统做事方式的能力和意愿,通常是在当前商业模式仍然成功的情况下。
拥有无限思维的领导者会发现推进其事业的战略机遇,但只有强有力的领导者才能抵制短期胜利的诱惑,挽救选择。在现有策略似乎仍然有效的情况下,投资新策略需要勇气。所以,一个正常的商业反射就是驱使人们保存当前的状态。但从长远来看,所有保护和补贴旧战略或方式的努力都会削弱组织的财务和精神能力。在问领导的勇气应该来自哪里时,Sinek 也提出了一个很好的观点。它很少是个人生活改变的结果。通常,勇敢的领导是小步骤和决定的总和,由正义的事业激励和引导,并由值得尊敬的对手推动。
当前人工智能顶级研究社区的许多人都相信,我们仍然处于人工智能技术采用的非常初级的阶段,我们仍然远远无法想象商业和社会的相关变化。例如,我推荐计算机科学家和机器学习研究员迈克尔·乔丹的伟大文章【人工智能——革命尚未发生】。因此,我认为,在这种环境下,公司最重要的技能是将变革作为企业文化的一部分。
人工智能的采用是一个无限的游戏——让我们也这样玩吧。
参考文献:
Simen,Sinek《无限游戏》,企鹅商业 2019
确定奖品的大小;普华永道全球人工智能研究:利用人工智能革命,普华永道 2017
迈克尔·乔丹《人工智能— 革命还没发生叶 t》,中 04–2018。
人工智能是有缺陷的——原因如下
人工智能中的公平和人工智能偏差

比尔·牛津在 Unsplash 上的照片
人工智能已经成为每个人生活中不可或缺的一部分。从简单的任务,如 YouTube 推荐,到复杂的拯救生命的任务,如生产治疗疾病的药物,它已经无处不在。它正以比我们意识到的更多的方式影响着我们的生活。
但是,AI 公平吗?不,绝对不是。
很难定义一个公平的人工智能。这是我能想到的最好的解释。如果输出独立于敏感参数(例如,性别、种族、性、宗教信仰、残疾等),则给定的 AI 模型是公平的。)对于已经受到社会歧视影响的特定任务。
在这篇博客中,我将写关于人工智能偏见,人工智能偏见的真实例子,以及修复它的方法。
问题
人工智能偏见是由于用于训练模型的数据中固有的偏见造成的,导致了社会歧视。这导致缺乏平等的机会。
例如,假设我的任务是创建一个模型,以位置作为参数来计算一个人的信用评分。某些种族群体集中在某些地方。这将使我的模型在种族上偏向那些伦理群体,在获得信用卡和银行贷款的同时影响他们。
有偏见的人工智能模型加剧了当前的社会歧视,并为压迫铺平了道路。
人工智能偏见的真实例子
这里有一些人工智能偏见的真实例子
- COMPAS: COMPAS(惩教罪犯管理概况替代制裁)是美国法院用来判断被告(被指控犯罪的人)成为惯犯(重复先前所犯罪行的行为)的概率的软件。由于数据存在严重偏差,该模型预测黑人罪犯累犯的误报率是白人罪犯的两倍。
- 亚马逊的招聘:2014 年,亚马逊开发了一个人工智能招聘系统,以简化他们的招聘流程。人们发现这是对女性的歧视,因为用于训练该模型的数据来自过去 10 年,由于男性在科技行业占主导地位,大多数被选中的申请人都是男性。亚马逊在 2018 年刮掉了这个系统。
- 美国医疗保健:美国医疗保健系统使用了一种人工智能模型,该模型为黑人指定了比白人更低的患同样疾病的风险率。这是因为该模型针对成本进行了优化,而且由于黑人被认为支付能力较低,该模型对他们健康风险的排名低于白人。这导致黑人的医疗保健标准降低。
- Twitter 图像裁剪:2020 年 9 月,Twitter 用户发现图像裁剪算法更喜欢白人面孔而不是黑人面孔。即,当具有与预览窗口不同的纵横比的图像被发布在 Twitter 上时,该算法裁剪图像的部分,并且仅显示图像的特定部分作为预览。这个人工智能模型经常在一张黑白脸的图片中的预览窗口中显示白色的脸。
- 脸书的广告算法:2019 年,脸书允许广告商根据种族、性别和宗教来锁定目标人群。这导致护士和秘书等工作面向女性,而看门人和出租车司机等工作面向男性,尤其是有色人种。该模型还发现,当展示给白人看时,房地产广告的点击率更高,这导致少数族裔缺乏房地产广告。
这只是人工智能偏见的几个常见例子。在开发者不知情的情况下,有很多不公平的人工智能实践的例子。
你能如何修理它?

迈向公平人工智能的第一步是承认问题。AI 是不完美的。数据是不完美的。我们的算法并不完美。我们的技术并不完美。当我们假装没有问题时,是不可能找到解决办法的。
其次,问问自己这个解决方案是否需要 AI。
不要害怕推出没有机器学习的产品——谷歌
有几个问题不依赖于数据。像寻找被告再犯的可能性这样的任务更多地依赖于情感而不是数据。
第三,遵循负责任的人工智能实践。我在下面添加了谷歌负责任的人工智能实践指南的要点。
负责任的人工智能实践:
- 使用以人为中心的设计方法:设计模型,内置适当的信息披露,并在部署之前整合来自测试人员的反馈。
- 确定多个指标来评估培训和监控:使用适合任务的不同指标来了解不同错误和体验之间的权衡。这些度量可以是来自消费者的反馈、假阳性和假阴性率等。
- 如果可能的话,检查你的原始数据:人工智能模型反映了用于训练模型的数据。如果数据有错,模型也会有错。尽量拥有平衡的数据。
- 了解你的模型的局限性:一个被训练来检测相关性的模型不一定有助于建立因果关系。例如,一个模型可能会了解到购买篮球鞋的人一般来说会更高,但这并不意味着购买篮球鞋的用户会因此变高。
- 测试:进行严格的单元测试,以确定模型中的错误。
- 在部署后继续监控和更新您的模型:考虑用户反馈,并在部署后定期更新您的模型。
- 设计一个具有公平和包容具体目标的模型:与道德和社会研究领域的专家合作,了解并解释各种观点。尽量让你的模型尽可能的公平。
- 使用有代表性的数据集来训练和测试你的模型:尝试评估你的数据的公平性。即寻找特征和标签之间的偏见或歧视性的相关性。
- 检查不公平的偏见:从不同背景的测试人员那里获得单元测试输入。这有助于确定哪一组人可能会受到模型的影响。
- 分析性能:考虑不同的指标。一个指标的改进可能会损害另一个指标的性能。
开发公平人工智能的工具
- FATE: 人工智能中的公平、问责、透明和道德(FATE),由微软提供评估可视化仪表板和偏见缓解算法的工具。它主要用于比较系统的公平性和性能之间的折衷。
- AI Fairness 360:AI Fairness 360 是 IBM 提供的开源工具包,可以帮助你检查、报告、减轻机器学习模型中的歧视和偏见。
- ML Fairness Gym:ML Fairness Gym 是谷歌提供的一个工具,用于探索机器学习系统对人工智能偏见的长期影响。
结论
在过去的几年里,公司和政府已经开始认真对待人工智能偏见。许多公司开发了评估人工智能公平性的工具,并尽最大努力打击人工智能偏见。虽然人工智能具有巨大的潜力,但现在对我们来说,记住人工智能系统的潜在歧视性危险并帮助开发公平的人工智能模型比以往任何时候都更重要。
关于我
我喜欢写一些较少谈论的人工智能主题,如联邦学习,图形神经网络,人工智能中的公平,量子机器学习,TinyML 等。关注我,了解我未来所有博客的最新动态。
你可以在 Twitter 、 LinkedIn 和 Github 上找到我。
AI 正在走向错误的方向
意见
衡量标准很重要,但我们遵循的是错误的标准

四天前,汉娜·肯纳写了
“太多人工智能研究人员认为现实世界的问题无关紧要。社区对新方法的过度关注忽略了真正重要的东西。”
这不是第一篇(也不会是最后一篇)讨论人工智能社区如何遵循自己议程的文章。大型场馆公然忽视申请文件——工作侧重于将当前方法应用于现实世界的问题和这样做的挑战(有很多)。诉讼程序完全脱离现实。物体检测上额外的 10%远比癌症死亡率减少 1%更有价值。
人工智能社区在很大程度上忽略了一个显而易见的事实:深度学习是一门实验科学。尽管有其正式的根源,神经网络是难以解释的大规模非线性系统。尽管越来越多的工作致力于它们的解释,神经网络仍然像以往一样神秘。我们了解它们的唯一可靠工具是科学方法——它深深植根于实验之中。
矛盾就在这里:尽管本质上是实验性的,这个领域拒绝纯粹的实验。平均神经网络论文呈现其新颖性,尝试形式化证明,并做消融研究。
结尾。这是实验的极限。
想象一下,如果土木工程界决定发明新颖的桥梁设计,但选择在桌子大小的乐高复制品上进行所有验证。没有昂贵的模拟,也没有使用真实建筑材料的试验。你会相信新提出的设计吗?你会相信这些实验足以投资数百万美元来实现它们吗?我不这么认为。

面向建筑商的 ImageNet—获得您的。
简化的世界模型对于快速原型和尝试想法很有用。他们暗示好的设计,即使他们不能证明它们。为了实际的证明,你需要世界。这是一个两步过程。
现代人工智能研究停留在前半部分:基准测试。真正的用例是另一半——缺失的那一半。 ImageNet,COCO,CIFAR-10,以及 sort 都是 AI 的乐高。他们允许我们尝试新的想法,摒弃不好的想法。它们是很好的工具。然而,它们是达到目的的手段,而不是目的本身。
消息是而不是当前的作品很糟糕,远非如此。问题是目前学术界和现实世界之间的脱节。
考虑一下情节。它展示了 COCO 对象检测基准测试的最新进展。每个小点都是一个不同的模型——一项新技术或现有技术的混合。领导者以蓝色突出显示。

图表显示了从 2016 年 1 月的 28.8 AP 到 2020 年 7 月的 55.1 AP 的轨迹。进步是不可否认的。根据该图,EfficientDet D7x 是当前用于对象检测的最佳技术。然而,我问你:你会为应用程序实现这些模型中的哪一个?
你甚至不会回答的几率很高,因为你不知道我在说哪个应用程序,也不知道它的要求是什么。它需要实时运行吗?它能在移动设备上运行吗?它要识别多少个类?其用户对错误检测的容忍度如何?等等。
根据不同的答案,以上都不值得考虑,包括 EfficientDet D7x。例如,如果模型必须在手机上实时运行,这些模型中没有一个在性能上稍作调整。更糟糕的是,无法保证这些模型能够在连续的帧中产生一致的检测结果。我甚至想不出一款应用需要最高质量的检测,除了高精度之外没有其他要求。
换句话说,研究团体追逐的指标只服务于团体本身,不服务于任何人。
B ack 在 2015 年,将神经网络的深度增加到十几层以上不利于性能。何等人、在著名的 ResNet 论文中假设,通过跳接连接非连续层可以扩大容量,因为这将提高梯度流量。
在第一年,ResNet 在几个基准比赛中取得了优异的成绩,如 ILSVRC 和 COCO。到目前为止,你已经意识到这只是一个暗示,表明 ResNet 是一个重要的贡献——这不是证据。
ResNet 在人工智能历史上的地位的明确证据是建立在它之上的大量工作。ResNet 引人注目的方面是它解决的不相关问题的数量,而不是它赢得的比赛。而且,平心而论,真正的贡献是 skip 的想法,而不是架构本身。
同样,焦损失论文经受住了时间的考验,因为它的贡献给其他人的工作带来了真正的改善。的关注文件遵循同样的路线。每天都有一篇新文章展示注意力是如何提高某个基准的(而专注的损失会让它变得更好)。
重要的不是比赛。这是遗产。其实 AlexNet 在 2012 年就拿下了 ILSVRC,ResNet 在 2015 年就拿下了。你能说出 2013 年和 2014 年的获奖者吗?2016 年,2017 年,2018 年举办的挑战赛呢?你确定每年都有一个 ILSVRC 吗?
所以你可能会问,为什么会这样?为什么没有更好的基准或更有用的指标?我们如何衡量遗产或影响?
可悲的事实是…我们不能。我们可以使用引用次数或下载次数,或者 Reddit 提及次数或 GitHub stars。然而,这些都是有缺陷的指标。为了公平的比较,我们需要考虑每一个细节,同时将等式中的所有偏差标准化。这太难了。
例如,为了比较注意力的遗产和 ResNet 的遗产,我们需要考虑这些概念的任何成功使用,权衡它们的相对影响,并根据年龄(ResNet 更老)和范围(注意力也与文本相关)进行标准化。显而易见,量化这些属性是一项巨大的任务,很可能与任何基准或指标一样存在缺陷。《华尔街日报》的影响因子等观点甚至没有触及这个问题的表面。
有些目标就是无法量化。谁是最重要的人物:被认为是西方音乐最有影响力的作曲家巴赫,还是被认为是最有影响力的戏剧家莎士比亚?比较他们的工作毫无意义,更不用说他们的领域了。

巴赫还是莎士比亚,音乐还是戏剧?
这让我们走进了死胡同。我们可以衡量准确性,我们可以衡量速度,但我们无法衡量影响力。我们都同意我们需要更好的科学,但是我们如何判断一门科学比另一门好呢?我们如何衡量研究和现实之间的脱节?
我们想和 AI 一起前进,但我们不知道前进的方向是什么,也不知道我们已经走了多远。
这并不是艾一个人的问题。我们想要更好的政府,更好的医疗保健,更好的教育,但是我们如何真正量化这些东西呢?到目前为止,最不成功的方法(也是最流行的方法)是替代指标。surrogate 是一种替代品——我们用来代替其他东西的东西。比如 COCO AP 评分。
我们无法衡量人工智能的进步,但我们可以衡量目前的物体检测方法有多精确。由于物体检测是人工智能的一部分,如果我们在这方面取得任何进展,我们也可以期待在人工智能方面取得进展。在 COCO 之前,我们使用 ImageNet Top-5 结果…直到我们搞定它,所以我们转向更具挑战性的问题。从一个问题跳到另一个问题,我们也希望在更好的人工智能方面取得进展。
我们一直都这样。我们不能训练检测模型来提高它们的 AP,但是我们可以教它们减少包围盒坐标的 L2 损失。损失是不可微度量的替代物。L2 损耗不是 AP,但是我们知道低 L2 损耗与高 AP 相关,所以它是有效的。
曾几何时,识字率是许多国家衡量教育进步的主要标准。几十年后,识字率高到足以让重点转向更高的学校毕业率。然后,更高的大学出勤率。我不知道学位是否像我们认为的那样与教育相关,或者高中是否教授他们应该教授的内容,但这些是我们今天的目标指标。
从某种意义上说,解决这类问题没有正确的方向。所以,从定义上来说,所有的路线都是错的。我们能够增加选择一条不那么错误的道路的几率的唯一方法是尽可能多地走这条路。使用人工智能术语,我们需要使用更大的批量,并尽可能多地采样分布。
这意味着我们必须拓宽我们的关注点,不仅要关注“准确性”和“速度”,还要关注“稳健性”或“一致性”等问题最重要的是,我们需要从精心挑选的基准转移到现实世界。
鉴于我的个人帐户正在研究乳腺癌检测算法,很容易认为这个领域已经解决了。最近的 作品在题目上取得了超人的分数,然而,你没有看到这些算法在任何医院得到应用。原因很简单:行不通。
我知道这听起来有点牵强,但它非常简单:如果你在数据集 A 上训练,该算法在数据集 B 上不起作用,尽管它是同一个东西:乳房 x 光照片。今天没有一种已知的技术可以在一个数据集上训练,而不需要微调就可以在其他数据集上很好地工作。您必须为每台机器/医院建立一个数据集,以获得任何有用的结果。从公制角度来看,场已经解决了。实际上,它甚至几乎没有开始。
最重要的是,算法很少甚至没有提供对答案的洞察。站在医生的立场上:你会因为一台机器这么说而告诉别人他们得了癌症吗?你不会;你会再看一眼这些图像。如果人工智能不被信任,它将永远不会被使用。
到目前为止,出版作品的主要指标是 AUC 分数。它告诉你该算法如何将乳房 x 光片分类为良性和恶性。它没有告诉你它对其他数据集有多稳健,或者其中任何一个是可以解释的。换句话说,它几乎没有回答:它有用吗?
推进人工智能没有正确的道路,但肯定有非常错误的道路。业内人士不需要太多时间就能意识到大多数文献是多么不适用,真正紧迫的问题是如何被明显忽视的。就像我开头说的,这篇文章的信息是而不是说现在的作品不好。关键是目前学术界和现实世界之间的脱节。我们过于狭隘地关注准确性。
再次引用汉娜·肯纳的话,“社区对新方法的过度关注忽略了真正重要的东西。”在我看来,真正重要的是推进我们的社会——我们希望通过改善人工智能来实现这一点。然而,只有当我们面对真正的社会问题时,我们才能做到这一点。比精确的物体检测更复杂的问题。
欢迎评论或者联系我。如果你是中新,我强烈推荐订阅。对于数据和 IT 专业人员来说,中型文章是 StackOverflow 的完美搭档,对于新手来说更是如此。注册时请考虑使用我的会员链接。
感谢阅读:)
人工智能学习飞行(第 2 部分)|创建您的定制强化学习环境并训练您的代理
Tensorforce 让定制强化学习变得简单

来源:Pixabay
从伊卡洛斯燃烧他的翅膀到莱特兄弟翱翔天际,人类花了几千年才学会飞行,但一个人工智能要多久才能做到?
介绍
大家好!
欢迎回到这一系列文章,我将写下我使用人工智能驾驶飞机的旅程(第一部分是这里是)。
在上一篇文章中,我们根据代理的动作定义了从一个状态到另一个状态的转换函数。

在本文中,我们将呈现一个完整的例子:
- 如何使用Python/tensor force轻松创建你的自定义 RL 环境****
- 如何在您的环境中定制、培训和测试最先进的 代理。
我们首先简要回顾一下什么是强化学习什么是。然后我们要为今天的练习定义我们的环境 ( 动作,状态,奖励)(飞机会尽可能高效的学习起飞)。最后,我们将定义我们的代理(我们将使用的代理的类型、超参数优化、训练、和测试)。
什么是强化学习?

强化学习是机器学习的一个分支,它允许训练代理人如何根据当前状态选择最佳的行动序列,以最大化长期回报。这个动作序列被称为策略。强化学习通过试错模仿现实生活中的学习过程。
代理从一个给定的状态开始,它采取一个行动,然后观察其环境的状态,并因达到这种状态而获得奖励(或惩罚)。强化学习的目标是理解行动、状态和奖励之间的关系,以便找到在任何给定情况下采取行动的最佳顺序。这完全符合我们的问题,因为控制飞机可以很容易地描述为采取推力和俯仰动作的序列,从而实现最佳轨迹。
在我们的虚拟平面示例中,动作(推力和俯仰)和结果(奖励和新状态)之间的关系是已知的,因为我们在前一篇文章中已经设计了物理模型来计算它们。然而,它不为代理所知(否则它将变成规划而不是强化学习)。因此,代理必须了解其环境如何工作,以选择最佳的操作。
环境定义
如前所述,我们将使用 张量 来实现我们的工作。这个库允许我们相当容易地创建自定义环境,并进行大量的自定义。它提供了一种易于定制的先进代理的实现。Tensorforce 的自定义环境定义需要以下信息(来自 Tensorforce 的文档):
-Init 不言自明,初始化创建环境所需的值(更多细节见文档
-状态定义状态表示的形状和类型。在本例中,它由 8 个浮点数表示(因此它有 8 个连续的维度)。
-动作定义代理可用的动作的形状和类型。在本例中,代理有可能在 1、2、3 和 4 之间选择一个动作(其中每个动作将由环境处理以创建下一步,例如,我们可以在网格世界游戏中想象以下关系,1:向上,2:向下,3:向左,4:向右)。
-重置将环境恢复到其开始状态,以便开始新的一集。因此,它与状态相同。
-Execute 处理代理选择的动作,并收集新状态、奖励以及代理是否达到终止状态。
环境定制
现在让我们定制我们的环境吧!对于我们的第一个案例,我们将训练机长(我们的人工智能飞行员)学习如何起飞。我们将以它为例详细介绍所有步骤。
机长还不知道如何着陆,但没关系!(来源: gfycat )
状态和动作
让我们从定义我们的状态和动作开始。
为了能够学习如何飞行,我们希望机长观察飞机的位置和速度(水平和垂直)。因此,我们希望我们的状态空间是 4 维的(2 维用于水平和垂直位置,2 维用于水平和垂直速度)。

国家代表权
为了驾驶飞机,我们希望我们的机长能够控制飞机的推力(或功率)和俯仰(或方向)。推力将以 10%的增量(最大功率的 50%、60%、70%、80%、90%、100%)从发动机推力的 50%限制到 100%。这将有助于训练,将功率限制在飞行中实际使用的值。音高将被限制为实际的正值(从 0 到 15)。

推力和俯仰
这导致了以下实现:
终端状态
现在让我们研究一下终端状态。我们将定义一集的三种结尾方式:
- 飞机到达 25m 高度(这是我们对起飞的定义)。
- 飞机在没有起飞的情况下冲出跑道(> 5 公里)
- 这一集持续了 100 多秒。
自我。FlightModel.Pos[1] 是飞机在跑道和自身上方的垂直位置。FlightModel.Pos[0] 它离跑道起点的水平位置。
奖励
下一步是奖励的定义。它们需要被设计成鼓励代理执行我们的任务,它需要被足够频繁地遇到,以便代理快速学习,同时足够精确,以便代理仅学习我们寻求的行为。我们希望我们的机长尽可能快地起飞,因此我们希望鼓励最短的起飞距离或最短的起飞时间(这两者是直接相关的)。
为了实现这一点,我们将对代理为达到目标所花费的每一个时间步骤进行惩罚。我们可以把它想象成起飞每一秒钟就从机长的银行账户里取出 1 美元。如果它达到目标(达到 25 米的高度),我们也会奖励他,奖励金额将基于起飞时还剩多少跑道。我们可以把它想成大概是每剩余一米跑道给他 1 美元,以激励他使用尽可能少的跑道,同时也奖励他成功起飞。
执行
最后但同样重要的是,我们将使用前一篇文章中定义的转移函数,根据当前状态和动作(执行代理的动作)计算下一个状态和奖励。
转换函数( compute_timestep )在我们的飞机环境中定义如下:
对于您的定制环境,您必须提供自己的转换函数。既然已经定义了环境,让我们继续进行代理定义!

我们现在有一个完整的环境!
代理定义
我们的机长需要能够理解连续状态(位置和速度)和离散动作(推力和俯仰)之间的复杂关系(我们的转换函数,他不知道),以便最大化其长期回报。
Tensorforce 已经实现了多个代理(深度 Q 网络、决斗 QDN、演员评论家、PPO …),所以我们不必自己动手。
为了避免这篇文章内容过多,我们不会详细讨论代理的选择以及它们是如何工作的。在尝试了不同的代理之后,很明显最适合我们任务的是 PPO(近似策略优化)算法。有关其工作原理的更多详细信息,请参考这篇文章。它们之间的特性和优势可能是一整篇文章的主题,但是我们今天将继续关注实现。
代理实现
下面是取自 Tensorforce 文档的 PPO 代理的基本实现。我们将在接下来的部分中讨论超参数,并暂时坚持使用默认值。
随着代理的运行,我们已经完成了整个框架。

一切准备就绪!
培训和测试
现在环境和代理都好了,系好安全带,准备起飞!
(来源:吉菲)
让我们看一下初始化我们的环境以及训练和测试代理的基本代码。
这个函数采用我们之前定义的环境以及我们的代理,并在给定的剧集数内运行它。有两种模式,训练模式(允许探索),用于在大量剧集上训练代理;以及用于评估代理性能的测试模式(不允许浏览)。
run 函数将由 runner 函数调用,以便分批执行剧集,通过在每批之后执行测试运行来监控训练期间的结果,并收集结果。
这是控制这些功能的主脚本。
让我们来看看这个基本脚本的结果:

1 批= 100 集
结果并不令人印象深刻。不仅代理人需要更多的跑道来起飞,随着时间的推移情况会变得更糟,而且最佳起飞距离也与现实生活中的 1.7 公里左右的结果相去甚远
超参数调谐
为了改进我们的结果,让我们看看我们的代理的主要超参数(要更深入地了解那些超参数,请阅读这篇文章和关于 PPO 的原文):
- 折扣:该参数描述了代理对未来的展望,而不仅仅是对未来几个奖励预期的展望。
- 探索:这个参数是采取随机动作而不是由代理的策略决定的动作的概率,顾名思义,这允许代理尝试它通常不会去做的动作。
- 子采样分数:这是批处理时间步长与子采样的相对分数(为了减少使用的数据量)
- 熵正则化:这个参数有助于策略不要“太确定”和一开始就冻结。
- L2 正则化:这是为了使代理不过度拟合而添加到损失中的随机噪声量。
- 似然比裁剪:该参数定义 PPO 中使用的替代目标将被裁剪多少,以将策略的变化保持在安全范围内。
为了找到这些参数的最佳值,我们将针对这些参数的不同值运行一系列剧集,并通过使用起飞距离作为得分来观察最佳组合。我们将使用的脚本基本上是一个网格搜索。我们将直接将其他超参数冻结为默认值或任意值,在本例中我们不会尝试优化这些值。
然后,我们使用该函数迭代一系列超参数,并计算最佳组合。每个组合将在 100 批 100 集的跨度内运行。
让我们首先检查非网络参数结果(子采样分数、似然比剪裁、l2 正则化、熵正则化)。
下图表示具有相同给定参数值的所有配置中的平均起飞距离(例如,在第一个图中,蓝色曲线表示二次采样分数为 0.2 的所有情节的平均起飞距离)。我们可以看到这种距离的演变,因为代理学习了具有相同参数的情节。曲线周围的彩色区域代表标准偏差。

1 批= 100 集
从这些图表中,我们可以获得所研究参数的最佳值,同时也观察到它们对结果没有非常重要的影响:
- 子采样分数:0.3
- 似然比削波:0.1
- l2 正则化:0.1
- 熵正则化:0.01
然后,我们对网络参数(每层的大小和神经网络的深度)进行同样的操作

1 批= 100 集
最佳网络参数是:
- 大小:32(使用 64 可以获得更好的精度,但是 32 允许类似的结果和更好的计算效率)
- 深度:4(同样,不是绝对最好的结果,而是最好的平均结果和良好的计算效率)
现在让我们来看看最后两个参数,折扣和探索:

对于折扣系数,我们可以看到,对于 0.5 的值,它在整个研究期间并没有真正改善,对于 0.9 的折扣,它确实达到了大约 2000 米起飞距离的平台期;最后,1.0 的折扣达到 1700 万的平台,同时比 0.9 的折扣系数花费更少的时间收敛(大约 50 集,而不是大约 80 集)。因此,我们将选择 1.0 的折扣系数。
对于探索因素,结果更加接近,所有 3 个因素(1%、0.1%和 0.01%)最终似乎都表现得相当好(尽管 0.1%似乎收敛得更慢)。然而,在研究结束时,1%的勘探系数似乎是最好的,因此我们将选择这个值。
结果
使用固定的超参数、我们定义的环境和我们训练的代理,我们现在可以观察 CaptAIn 做得如何。

在这个图表上,我们可以看到每一批 100 集的每一批之后达到的起飞距离。我们可以看到,由于探索,起飞距离总体上在减少,并且有一些周期性的退化。最终实现的起飞距离为 1725 米。
该值与实际 A320(我们正在建模的飞机)所达到的值相当,因此结果令人鼓舞!现在让我们来看看代理是如何做的,也称为 T2 政策。我们先来看看培训阶段:

这是每千集政策的演变。每一张图表都代表了代理人在每一集的每个时间点所做的事情。蓝色曲线(数值在左边)是推力,红色曲线(数值在右边)是俯仰角。起初,代理人执行看似随机的行动,并没有设法起飞。

机长最初的政策看起来不太像起飞,偏离了跑道
然后,我们可以看到代理如何逐渐收敛于在整个事件中应用全部推力,并且只有当飞机达到足够的速度时才旋转。行动的高度可变性是由于训练代理人所固有的探索性和随机性。我们现在将切换到测试模式来观察实际的策略(没有探索)。

政策 vs 时间超过 100 批次,题目中的数字就是该批次的编号。蓝色表示推力(5 =最大功率的 100%,0 =最大功率的 50%),红色表示俯仰角(从 0°到 15°)。
在这部动画中,我们可以看到每一批 100 集超过 100 批的政策演变。类似于训练阶段,我们观察到代理向它的最终策略收敛:在整个事件中使用全功率,并且在获得足够的速度(大约 30 秒)后才旋转。我们还可以观察到起飞时间从一集 100 秒的最大允许时间减少到 33 秒。

最终策略是推力恒定为 100%功率(力强度为 5.0),25 秒时俯仰角为 12°。
事情是这样的:

机长的最终政策(为了形象化,高度被夸大,速度增加)
总结一下,机长已经成功起飞,甚至比真正的飞行员还要好!尽管这看起来并不令人印象深刻,因为人类会很容易地发现使用全功率并在一定速度后旋转飞机是正确的方式,但我们必须记住,机长从未见过飞机起飞,而是完全靠自己发现的!

我们做到了!(来源:吉菲)
现在,我们已经了解了如何在 Tensorforce 中创建自定义环境并使用它来训练和优化代理,您现在可以使用我们定义的框架将强化学习应用到您自己的环境和问题中!
后续步骤
机长刚刚学会如何起飞,如何让他实现水平飞行和着陆还有待观察。然而,这些任务不像起飞(像现实中一样)那么容易,需要一些更复杂的方法,而不仅仅是使用预先定义的代理和“简单”的奖励。为了保持这篇文章的主题是如何从头开始做一个简单的 RL 问题,我们将在下一篇文章中讨论奖励工程,以便队长登陆!
在经历了几百万次失败的着陆和水平飞行试验后,我暂时离开了机长休息区。(来源:吉菲)
感谢阅读,我真的很喜欢分享我的强化学习之旅,我将非常感谢你的回报。敬请关注下一部分!
扬·贝特洛
我使用的完整代码(Python)可以在我的 Github 上找到:
RL 的 PlaneModel 环境。在 GitHub 上创建一个帐户,为 YannBerthelot/PlaneModel 开发做贡献。
github.com](https://github.com/YannBerthelot/PlaneModel)
资源
https://www . coursera . org/learn/complete-reinforcement-learning-system/home/welcome:关于 RL 理论的伟大 MOOC(但缺少一点点或真正的实现,主要是数学,从今以后尝试自己的项目的重要性!)
https://tensorforce.readthedocs.io/en/latest/:tensor force 文档,相当完整,但有时不太容易理解。
https://medium . com/aureliantactics/ppo-Hyperparameters-and-ranges-6 fc2d 29 bccbe:关于 PPO 超参数的好文章
https://towards data science . com/the-complete-reinforcement-learning-dictionary-e 16230 b 7d 24 e:大部分 RL 术语的清晰解释
https://arxiv.org/pdf/1707.06347.pdf:PPO 纸。
https://toppng . com/black-and-white-plane-png-free-PNG-Images _ 71843:飞机动画使用的 PNG
AI 20 秒学会乘法
AI 学习乘法能有多快多准?
今天,人工智能正在完成曾经被认为超出人类能力的任务。从检测视网膜病变的眼睛到威胁生命的肿瘤,人工智能很快就能完成所有复杂的任务。
今天我们下坡跑,看看人工智能如何执行现代计算机最简单的任务之一:乘法。

Canva.com 的股票图片
在这篇文章中,我们将尝试教一个机器学习模型乘法,并看看它的表现如何。帖子会更倾向于 ML 的初学者一方,代码最少(准确的说是 14 行)。
声明:在现实生活中,你永远不会希望一个 ML 算法为你执行乘法。这篇文章只是带你做了一个实验,试图建立一个做算术的机器学习模型。让我们开始吧。
我们在这里的目标是开发一个模型,它以一个整数作为输入,并给出一个输出,这个输出是输入乘以某个数字,让这个数字为 5。所以,如果你给了 10 英镑作为投入,你肯定期望 50 英镑作为产出。请注意,我们不会告诉模型我们正在寻找的任务是一个简单的乘法;它必须自己想办法解决。

作者图片
重要的事情先来
我们的第一项工作将是创建一个示例数据集,通过查看该数据集,模型可以了解到我们正在寻找的任务是乘以 5。我们将使用 1 到 300 之间的 10k 个随机生成的数据点。因此,我们有 10k 个输入数据点[20,120…..5,15]和 10k 输出数据点[100,600…..25,75]即输入点数乘以 5。Python 中的相同代码如下所示。
import random
X=[]
Y=[]
for i in range(10000):
n = random.randint(0,300)
X.append(n)
Y.append(n*5)#X is the input array and Y is the output array
答对了。我们已经准备好了数据集。现在,让我们设计一个可以学习我们任务的神经网络。一个基本的教科书式人工神经网络设计看起来像下图(图 1)一样,其中有许多隐藏层和许多神经元,但那是为了复杂的任务,如数字分类。对于我们简单的乘法任务,只有一个隐藏层和一个隐藏神经元的简单神经网络可能就可以工作。

作者图片
建筑时间
让我们为图 2 中的架构编写代码。看看这个模型能不能学会乘 5。我们在 Tensorflow 上面使用 Keras,一个高级的 ML 库。我们知道,我们试图构建的架构是一个简单的顺序网络。我们添加一个带有一个神经元的密集层,这将是我们的隐藏层,然后我们再添加一个带有一个神经元的层,它将保存我们的输出答案。我们对所有神经元使用“relu”优化函数。
我们使用均方误差来查看每一步的模型预测和地面实况之间的误差,并使用“Adam”优化器来优化我们的损失。“metrics”参数在启用时会显示您的模型在训练时的状态。架构设置好了,现在模型都准备好学习了。我们最后使用 model.fit()函数,其中模型试图理解输入和输出之间的关系。
我们传递输入(X)、输出(Y)、批量大小:在重置模型权重和偏差之前要查看的数据点数、验证分割:用于验证的数据集部分和时期:模型遍历整个数据集的次数。
from keras.models import Sequential #using Keras Library
model=Sequential()
model.add(Dense(1,activation='relu',input_shape=(1,)))
model.add(Dense(1,activation='relu'))
model.compile(loss='MSE', optimizer='adam', metrics=['accuracy'])
model.fit(X, Y, batch_size=50,
validation_split=0.1, epochs=100, verbose=1,shuffle=1)
让我们看看在模型被训练时打印的一些统计数据。
#From 10k samples, since validation_split=0.1, we trrain on 0.9*10k i.e. 9k samples.After First iteration
Epoch 1/100
9000/9000 [==============================] - 1s 148us/step - loss: 625973.1757 - acc: 0.0038 - val_loss: 577468.6391 - val_acc: 0.0020After 74th iteration
Epoch 74/100
9000/9000 [==============================] - 0s 24us/step - loss: 0.0723 - acc: 0.9583 - val_loss: 0.0595 - val_acc: 1.0000
看看第 1 步和第 74 步的准确度差异。开始时的准确度为 0.0038 或 0.38%,这表明模型在开始时不知道输入和输出之间的关系。一开始的损失也是巨大的。随着训练的继续,模型开始理解数据,准确性提高,损失(误差)减少。
在第 74 步之后,该模型具有 0.9583 或 95.83%的准确度,即,它能够以 95.83%的确信度告知该任务是乘以 5。我们可以看到,在 74 次迭代中,验证损失也从 0.20%提高到了 100%。经过 100 次迭代后,训练精度(acc)和验证精度(val_acc)都达到 100%,表明我们的模型成功地发现了这种关系是乘以 5。
在 NVidia 940 MX 4 GB GPU 和 16 GB RAM 上,训练过程需要大约 20 秒来完成 100 次迭代。那确实是快速的学习。
结果呢
最后,是时候测试我们的模型了。让我们在 test_array 中取任意五个数字,并使用上面建立的模型来获得预测。理想情况下,输出应该是 test_array 元素乘以 5。
test_array=np.array([4,27,100,121,9])
print(model.predict([test_array]))
擂鼓!最后预测的时间到了。
[[19.9995174407959], [134.9995880126953], [499.9997253417969], [604.9998168945312], [44.99952697753906]]
我们看到我们的模型快完成了。实际值为[20,135,500,605,45],如果将预测值四舍五入到小数点后两位,我们看到预测值与预期结果相同。

Canva.com
这就是你要的,一个简单的人工智能已经学会了乘 5。还有一些事情;然而,需要考虑的是:尝试给出负值并检查输出,您会得到什么?我想把它留给你去尝试,实验,并提出使算法更精确的技术。此外,尝试对架构进行更改,例如添加更多的层和神经元,并查看指标的差异。如果你有任何疑问,请在评论中告诉我。
我希望你喜欢这篇文章,并喜欢构建一个可以执行简单乘法任务的人工智能。下次见。
给老师、青少年和所有介于两者之间的人上人工智能课
我的目标是概述一个课程,任何老师都可以在课堂上使用,或者任何对人工智能如何工作有兴趣的人都可以走一遍。这并不意味着是人工智能如何真正工作的精确表示,而只是给出它如何工作的直觉。我做了近十年的数学、SAT、ACT 和 ISEE 辅导老师,从事机器学习研究。
先决条件:知道什么是概率。
有两个子课程,一个较小的和一个较大的。所有课程都属于计算机视觉问题的范畴——物体检测。
- 监督学习与非监督学习
- 训练机器学习模型
机器学习问题通常分为两类,监督问题和非监督问题。监督问题是指你给模型一些例子,然后期望它能够在看不见的图像上预测那个东西。无监督的问题是,你有一堆图像,你试图找出哪些是最密切相关的(除了你能看到的以外,不基于任何东西),然后将它们分组,而不知道你试图预测的最终类别实际上是什么。
监督学习
我现在将向您展示一系列的形状和形状的名称。

“扎格斯”
上面这些形状被称为扎格斯。

" flarks "
上面这些形状被称为扇形。
现在我会给你一个物体,你告诉我它是一个扎格还是一个 flark。有一个潜规则,把 zhags 和 flarks 分类。你的工作是学习规则。

?
这是一个扎格。如果你猜对了,太棒了!你学到了一个成功的模式。
但也许现在你得到的对象并不完全符合你的想法。

?
这是一把 flark 。
你不知道,潜规则是,如果形状有任何曲线,它就是一个 flark。这就是为什么充足的训练数据对机器学习问题如此重要!如果这是自动驾驶汽车中丢失的训练数据点,这可能会让某人付出生命的代价。
无监督学习
假设我们有一组图像,并且严格使用这些图像,我们不需要任何先验知识就可以将它们放置在 xy 平面上,其中它们之间的距离表示它们彼此之间的差异。
这里有一组图片。

图片来自维基百科
现在我们要把这些放在 xy 平面上。这是一个可能的迭代。

如果我现在说,把这些分成两组,你可能会用两种方法之一。


可能的分组
现在,如果我们应用水果或蔬菜的分类任务,我们已经做了一个相当不错的分类工作,却从未被告知什么是水果或蔬菜!简单地通过确定不同图像之间的某种距离映射,我们已经对水果和蔬菜进行了分类。
训练
让我们看一个监督学习任务的例子,在这个例子中,我们试图识别一幅图像是一只杜宾还是达克斯。
神经网络结构由输入、隐藏层和输出组成。在这种情况下,输入是一幅图像,然后对于我们的隐藏层,我们将使用所谓的卷积层,然后输出将是两个数字——第一个数字是图像是杜宾犬的概率,第二个是腊肠犬的概率。
输入图像是一个固定大小的正方形图像,其中每个像素的值在 0 到 255 之间,图像有 3 层(红、绿、蓝)。一个简单的版本就是只有一层的黑白图像。所以你可以把图像想象成一个大的数字矩阵,每个数字代表一个像素值。
这是一个矩阵形式的示例,其中像素值已被转换(归一化),因此它们现在不是在 0 和 255 之间,而是在 0 和 1 之间,其中 1 与 255 相同。

摘自 fast.ai 第 4 课
简而言之,卷积层是一个小过滤器,它通过图像并捕捉图像的不同方面,如边缘或高光。不同的卷积可以提取关于图像的不同信息。这是卷积核通过后的图像。神经网络然后学习更新该过程,以便提取预测目标变量的最佳信息(在我们的情况下,是杜宾或达克斯猎犬)。

来自维基百科图像内核
隐藏图层之后,这些值会减少到预测问题中的类数。对于杜宾或腊肠犬,我们有两个等级。因此,输出看起来类似于[0.15, 0.85],这是给定图像的概率输出,并且会被归类为腊肠犬,因为 0.85 > 0.15。
现在让我们做一个稍微模仿神经网络学习过程的示例练习。
我会给你一张杜宾犬或腊肠犬的蒙版图片,你必须用一个介于-10 和 10 之间的值来回答,其中值越接近-10 意味着你认为这张图片是一只杜宾犬,而值越接近 10 意味着它是一只腊肠犬。
我们的神经网络有 4 层,所以 4 个屏蔽图像是同一图像的不同视图。
我将通过一个例子并给出值。

第一层
我会给这个一个 8 。

第二层
我给这个一个 -1 。

第三层
我给这个一个 -7 。

第 4 层
这个我给个 -9 。
所以某些层我不确定,而其他层似乎倾向于这样或那样。
现在取这 4 个值并求平均值。
np.mean([8,-1,-7,-9])
出局: -2.25
现在,我们将通过所谓的 sigmoid*层,这将给出图像是腊肠犬的概率(因为我们分配的值越大,我们就越认为它是腊肠犬)。
z = -2.25
1 / (1 + np.exp(-z))
输出: 0.095
所以我们的概率变成了[0.905, 0.095]。
*你也可以用这个站点用 sigmoid 计算概率。
现在我们看到事实上是一只杜宾犬,所以我们是对的!

图片来自 vetstreet.com
人工智能扫盲 101
它是什么,为什么我们都需要它?
没有多少人真正理解人工智能,它是什么,以及如何让它工作。许多组织已经开始,但并不真正知道如何让它工作,许多数据科学家对他们的工作感到沮丧。我们需要做点什么。
大约四十年前,我们处于类似的情况。那时候,我们处在一个大多数人缺乏 T2 电脑知识的阶段。我们生活在一个只有一小部分人在技术上有能力建造计算机,创造软件,连接软件和硬件的时代。听起来很熟悉?在那些日子里,大多数办公室工作人员不使用电脑,他们不知道这是什么,它如何能给他们带来好处。他们也不了解构建软件的复杂性,他们害怕失去工作,或者只是觉得太好而不想使用它们。

快进到今天——我们现在几乎都懂电脑。我们知道如何使用我们的电脑,即使我们不在电脑中工作,我们也是别人制造的电脑的用户。我们不需要能够看到引擎盖下,但我们知道我们需要什么,实现新系统需要什么,以及如何使用软件。
我们目前生活在人工智能的 80 年代 -有一个小型但不断增长的从业者群体能够构建人工智能系统,并非所有这些系统都出于多种原因而工作,也并非所有系统都对最终用户有用。为什么?公司的大多数员工不知道人工智能是什么,它如何让他们受益,或者他们如何参与这样的系统。与此同时,管理层无法提供所需的资源,因为他们根本不知道如何利用人工智能创造价值。他们需要成为有人工智能素养的人。
人工智能素养是关于知道什么是人工智能,关于人工智能如何让你受益,让人工智能系统工作需要什么,以及最终如何使用人工智能解决方案。如果一个公司没有人工智能素养,就很难大规模地推动人工智能项目取得成功。我真的相信人工智能素养是我们所有人未来都需要的。这就是为什么我们需要现在就开始对我们的管理层和同事进行人工智能教育,并开始缩小我们目前面临的商业和数据科学之间的差距。
你将如何在你的组织中为人工智能扫盲做出贡献?你需要想法吗?然后看看我的文章如何在 AI 上教育你的老板。
关于我:我是一名分析顾问,也是当地一所商学院“人工智能管理”研究的主任。我的使命是帮助组织利用人工智能创造商业价值,并创造一个数据科学家可以茁壮成长的环境。 在这里报名我的快讯。
AI 可能根本就不想要你的工作
人们预测人工智能将自动取代会计师和审计师已经有很多年了,但几乎没有什么变化。这是一个现实主义者的观点,他解释了为什么人工智能终究不会抢走这些工作。

会计师和审计师名声不好。对许多人来说,这种观点是基于他们在高中或大学上过的几堂会计入门课。虽然学习借方和贷方并不有趣,但实际的职业生涯要比这复杂一些。像许多工作一样,会计职业需要重复性和创造性任务的结合。会计师遵循常规清单和程序,但也运用判断来导航不同的选项,说服客户采取行动,并与利益相关者建立关系。在现实中,高级审计员和会计师,包括财务总监和首席财务官,实际上更像律师。
人工智能的进步将如何影响会计行业,这方面存在相当大的不确定性。那些对人工智能持反乌托邦观点的人认为,大多数任务都可以自动化,会计师将变得过时。事实上,在 2018 年,福布斯预测会计任务,包括税务、工资单、审计、银行业务等,到 2020 年将完全自动化。现实是,即使是现在,几年后,我们仍然离自动化很远。事实上,有几个原因让我们可能永远不会。
我认为,在短期内,人工智能自动化将使 的 会计师更有效率,而不是取代 他们。人工智能将提高会计师在员工、公司和宏观层面的效率。从长远来看,由于强大的力量,如根深蒂固的专业管辖权、自动化的成本/收益权衡以及工作本身的性质,人工智能不会取代会计师。在这篇文章中,我将分析人工智能对会计行业的影响,这也将作为许多其他行业的框架。
人工智能将如何影响员工层面的会计师
迄今为止所有的 AI 进步都真的被归类为狭义 AI——只能解决特定任务的 AI。在近期,人工智能将使会计师的某些重复性工作自动化。机器人流程自动化(RPA)已经在自动化多项任务,如导出数据、执行对账和识别异常值以供调查,而 Tableau、Power BI 和 Beautiful.ai 等工具则帮助会计更快、更清晰地可视化和交流信息。以前,这些任务需要公司花费数千个工时来完成,同时员工也不喜欢。在这个领域,人工智能工具为双方带来了明显的双赢。
强大的分析工具将使会计师能够将注意力集中在高风险和复杂的交易上,确保他们的工作放在最需要的地方。例如,考虑一个人工智能工具,它可以监控零售商的销售交易,并识别客户退货模式的变化。该系统可以根据历史结果和行业数据制定预期,并向会计师标记异常值,使他们重新考虑他们如何考虑客户退货的备抵(零售公司计算收入的一个重要输入)。
上面的例子说明了短期内的两个重要收获。首先,会计师将不得不继续参与每一项技术,但人工智能将使事情变得更快。第二,人工智能机器人不是解决所有问题的灵丹妙药。相反,这些技术只解决工作的特定方面,因为需要大量的时间和费用来完善人工智能在每个用例中的应用。
当我们考虑人工智能的长期影响时,我相信类似的趋势将会继续。会计师将拥有一系列人工智能工具,将自己从许多重复性任务中解放出来,将他们的注意力转移到复杂的任务上,如自己构建人工智能模型(软件工程师无法自己构建这些模型)、建立客户关系以及分析新型交易。
成为一名成功的会计师所需的技能将会彻底改变。会计师将需要发展全知全能:理解许多不同的能力,包括数据科学、计算机和网络,更深入地了解他们的客户,最重要的是,更坚实的道德和透明度基础——所有这些都是计算机无法复制的。随着自动化程度的提高,会计师将不得不在如何训练模型、如何应用分析以及如何保护利益相关者的利益方面做出艰难的决定。
人工智能将如何影响会计组织
在短期内,人工智能技术的实施将在几个方面影响组织。第一,会大大提高聘请会计人才的效率。大型会计师事务所将通过 LinkedIn 和 Ziprecruiter 使用 AI 筛选工具筛选简历,并通过视频面试评估候选人。
第二,人工智能工具在通过 flash teams 等工具扩展团队以满足客户需求方面也很有价值,这在会计行业尤其有价值,因为该行业的工作是季节性的,在冬季年终期间非常繁忙,在夏季期间比较轻松。
第三,企业将执行广泛的企业培训计划,用前沿技术和基于人工智能的风险评估工具提升员工的技能。公司将继续探索新途径,通过与 MOOCs 和其他第三方技能提升项目的合作来提高培训项目的有效性。不幸的是,跟不上的工人如果不能接受适当的再培训,就可能被解雇。
上述每个案例都说明了世界各地的会计组织发生的有意义的变化。然而,值得注意的是,这些工具仍然需要人参与进来,并且仍然是使技术成为可能,而不是在短期内取代技术。
从长远来看,人工智能将从根本上改变会计师事务所扩大规模和发展团队的方式。Flash 团队可能会成为公司不可或缺的一部分,模糊公司和第三方(如 SME)的界限。例如,如果与一家矿业公司合作,会计人员可能需要对潜在地点进行详细的评估,以及相关的预测,以便对账面上的资产进行适当的估价。这些报告有时由第三方公司提供,这些公司在特定主题方面有更深入的专业知识。Flash 团队可以帮助简化这一过程,并降低雇用个人的成本。
此外,从长远来看,组织将类似于特设机构,而不是官僚机构。会计师事务所目前的结构有明确的员工层级,并遵循严格的官僚程序。一旦员工从重复性的任务中解脱出来,他们将被期望在职业生涯的早期承担更大的客户关系责任,并就客户和公司的战略问题发表意见。因此,不可避免的是,会计师事务所将不得不避开目前存在的严格的官僚制度,而采取一种特别的方法。这很可能意味着晋升的层次将大大减少,这些公司的晋升途径可能会更快。
人工智能将如何在宏观层面上影响会计行业
在宏观层面,人工智能受到几个强大力量的限制,这些力量将阻止它取代工人。首先,由于会计专业管辖区的广泛权力,人工智能自动化将受到限制。在北美,注册会计师协会及其成员拥有强大的游说团体,与上市公司会计监督委员会(PCAOB)和证券交易委员会(SEC)等监管机构关系密切。事实上,许多人已经注意到监管机构的旋转门转向会计师事务所,反之亦然,这可能会降低事务所和监管机构之间的独立性(完全是一个独立的话题)。关于人工智能的采用,可以肯定地说,即使人工智能可以取代会计师,由于这些专业司法管辖区的力量,这种发展也将遇到严格的监管审查和反弹。
第二,缺乏关于会计师如何在重复性任务和创造性任务之间分配时间的数据。根据我的个人经验,我的大部分工作需要获取客户数据,清理和处理这些数据,并使用证据和分析来支持交易。虽然有些方面可以自动化,但大部分需要我运用专业判断和对客户业务的了解。这些见解不能通过死记硬背的数据分析获得,需要与几个利益相关者交流,以了解整个组织中交易流程的流程和偏差。
第三,入门级职位的起薪为 45,000 美元到 60,000 美元,这可能是因为会计劳动力太便宜,公司无法实现自动化。此外,过去 10 年,四大会计师事务所初级会计职位的起薪几乎没有增长。随着人工智能使会计师的任务越来越多,我怀疑未来工资将保持不变或面临下行压力。
我相信这些趋势将长期持续下去。人工智能不太可能实现完全取代会计师的能力,相反,它将保持狭隘,使他们能够更有效地工作。
结论
在短期内,很明显,人工智能已经并将继续成为一种使能技术,而不是替代技术。窄人工智能将提高工人的效率,并腾出时间进行创造性的任务和客户关系建设。在组织层面,公司将进行大规模的技能提升项目,并从根本上改变他们雇佣人才的方式。
从长远来看,员工在进入劳动力市场之前,必须大幅改变他们的技能组合。全知和道德将是这个行业对工作的更强要求。组织将从根本上改变他们的等级制度,类似于员工被授权在战略决策中承担更大的风险。在宏观层面上,由于强大的专业管辖权和开发人工智能与雇佣人员之间重要的成本效益权衡,人工智能将无法取代会计师。其中的每一个都代表了自动化极限的重要界限。
艾:不仅仅是一个流行词
F2 方式
当我们想到人工智能(“ AI ”)时,脑海中会浮现出几样东西:大作终结者 2 中的阿诺施瓦辛格、星球大战中的 C-3PO、以及西部世界的世界。正如许多人所看到的那样,人工智能在这些电影和系列中显而易见——计算机或机器人使用源于人类的智能来学习如何独立“思考”,发展自己的身份。
AI 在帮助人类?来源:giphy.com上映的《终结者:黑暗命运》
虽然这些电影和电视节目是虚构的(顺便说一下,也很棒),但机器人背后的真相在屏幕上与现实生活中是一样的:
通过人工智能,我们可以创造出机器,它们可以以比人类更快的速度执行无尽的任务,并且只受物理计算能力的限制。很酷吧?
人工智能、机器学习(" ML ")和深度学习都是相关的,并随着时间的推移而演变,如下所示:

来源:英伟达博客
尤其是这些天,人工智能正在改变我们世界的形状,并在各行各业实现手工流程的自动化。然而,为了建立最有效的模型,需要有一个坚实的基础。以机器学习为例。当考虑 ML 所能做的一切时,我们通常会考虑最终结果,即产品。然而,那台机器只有的功能是作为访问数据、清理数据和从数据中学习的结果。这让我想到了一个至关重要的话题:数据。
数据。
今年年初,数字世界由 44 zetta 字节的数据组成。截至 2019 年,超过 45 亿人使用互联网。统计数据说明了一切:有大量的数据,而且数量只会越来越大。然而,这些数据中的大部分仍未被利用。平均而言,一家公司 73%的数据完全没有使用,这意味着公司正在失去分析其工作流各个方面的重要机会。
因此,每个组织都在成为数据组织。理解这些大数据的唯一方法是利用人工智能。**
正因为如此,允许企业检索、消化和分析数据,并将这些数据转化为切实可行的解决方案的人工智能和人工智能的应用程序和框架变得比以往任何时候都更加重要。**

作者照片,基于 Gartner 2019
人工智能价值链。
在过去的十年中,我们已经看到了软件开发工具的激增,这些工具使得构建软件更加容易和有效。AI 也开始效仿。AI 产品靠的是自己的价值链。ML 就是一个很好的例子:它的模型只和它们所基于的数据一样好;数据越可靠,模型就越精确。企业家们争先恐后地填补空白。正如软件开发工具一样,针对 ML 价值链某一特定方面的 AI 工具正在各地涌现。
也有令人难以置信的有趣的公司努力提供全面的 ML 平台,覆盖所有或几乎所有的价值链。这些公司提供垂直领域的解决方案,如医疗保健、零售、保险等。
我们认为 ML 的价值链如下:

作者照片,基于机器学习系统中隐藏的技术债务
请注意,专用于实际 ML 代码的类别有多小。无论一家公司是针对价值链上的一个特定问题,还是为垂直特定问题创建整体解决方案,人工智能公司都是热门。
我们的论文。
F2 是一家专业的种子期风险投资基金,支持以色列深度技术公司,位于大数据、人工智能和连接的交界处。有助于构建和实施 ML 模型以及解决特定问题的价值链和框架还不够成熟。我们认为这不是一个问题,而是一个帮助发展和资助这种基础设施的机会。我们还认为,不同垂直行业的公司都有机会通过利用人工智能作为其核心技术的一部分来创建整体解决方案。
我们的公司如何适应。
根据这个论点,我们已经在人工智能领域领导了许多种子前和种子阶段投资 ,这些投资可以分为两大类:适合 ML 价值链特定部分的框架公司和核心知识产权部分基于人工智能的垂直整体解决方案公司。
以下是我们投资组合中的一些公司示例,这些公司瞄准了 ML 价值链的特定方面** :**
-
Dataloop :开发一个用于标注 ML 数据集的一站式平台。它包括一个数据管理环境,该环境包含自动注释功能和数据质量控制管理。
-
Datomize :通过先进的人工智能生成高质量的合成数据,可以在内部和云上使用。它通过支持有效的人工智能建模、第三方协作、测试和开发来增强研发和数据科学团队的能力,同时遵守最严格的隐私法规。
嗡嗡嗡嗡。来源:giphy.com的《人工智能》
以下是我们投资组合中使用人工智能为特定于垂直行业的问题提供解决方案的公司示例:
- 【real friend】:开发一个聊天机器人,利用各种最先进的 ML 技术向房地产经纪人提供个性化服务,以便他们可以同时支持多个客户。
- 零网络 :确保每个用户和机器只利用他们应该利用的网络资源。这在规模上强制实施了一个密闭的、最低特权的网络姿态,以消除内部攻击媒介,并允许公司再次信任他们的网络。
以下是这些投资组合公司如何融入 ML 价值链:

作者照片
总而言之。
这是一个真正令人兴奋的时间来参与所有人工智能的事情。没有人知道什么样的趋势会引领这个行业,未来几年会发生什么样的变化。不过,我有信心,因为它有能力将人工智能应用于几乎任何垂直领域,所以对于改变游戏规则的创始人来说,这是一片蓝海。
如果你是一家说话和呼吸都是人工智能的早期初创企业,并且有远大的想法,我们愿意提供帮助!
联系我@maor@f2vc.com
再见了,宝贝!
毛尔·弗里德曼
*作者在 F2 Venture Capital 的投资团队中担任助理
2020 年要读的 AI 论文
阅读建议让你了解人工智能和数据科学的最新经典突破

答人工智能是科学中发展最快的领域之一,也是过去几年最受欢迎的技能之一,通常被称为数据科学。这个领域有着深远的应用,通常按输入类型来划分:文本、音频、图像、视频或图形;或者通过问题公式化:有监督的,无监督的,强化学习。跟上每件事是一项巨大的努力,通常以令人沮丧的尝试而告终。本着这种精神,我提出一些阅读建议,让你了解人工智能和数据科学的最新和经典突破。
虽然我列出的大多数论文都是关于图像和文本的,但是它们的许多概念都是与输入无关的,并且提供了远远超出视觉和语言任务的洞察力。在每个建议旁边,我列出了一些我认为你应该阅读(或重读)这篇论文的理由,并添加了一些进一步的阅读材料,以防你想对某个给定的主题进行更深入的研究。
在我们开始之前,我想向音频和强化学习社区道歉,因为我没有把这些主题添加到列表中,因为我在这两方面的经验都很有限。
开始了。
排名第一的 AlexNet (2012)
克里日夫斯基、亚历克斯、伊利亚·苏茨基弗和杰弗里·e·辛顿。“使用深度卷积神经网络的 Imagenet 分类” 神经信息处理系统的进展。2012.
2012 年,作者提出使用 GPU 来训练大型卷积神经网络(CNN),用于 ImageNet 挑战。这是一个大胆的举动,因为 CNN 被认为太重了,无法处理如此大规模的问题。令所有人惊讶的是,他们以大约 15%的前五名错误率赢得了第一名,而第二名的错误率为大约 26%,第二名使用了最先进的图像处理技术。
原因 1: 虽然我们大多数人都知道 AlexNet 的历史重要性,但并不是每个人都知道我们今天使用的技术在繁荣之前就已经存在了。你可能会惊讶于论文中介绍的许多概念是多么的熟悉,比如辍学和重新学习。
原因#2: 提议的网络有 6000 万个参数,完全不符合 2012 年的标准。如今,我们可以看到有超过十亿个参数的模型。阅读 AlexNet 的论文让我们对自那以后事情的发展有了更多的了解。
延伸阅读:跟随 ImageNet 冠军历史,可以阅读 ZF 网、 VGG 、盗梦空间-v1、和 ResNet 论文。这最后一个实现了超人的性能,解决了挑战。在那之后,其他的比赛占据了研究人员的注意力。如今,ImageNet 主要用于迁移学习和验证低参数模型,例如:

AlexNet 结构的原始描述。上半部分和下半部分分别由 GPU 1 和 2 处理。模型并行的早期形式。来源:Alex net 论文
排名第二的移动互联网(2017 年)
Howard,Andrew G .等人“移动互联网:用于移动视觉应用的高效卷积神经网络” arXiv 预印本 arXiv:1704.04861 (2017)。
MobileNet 是最著名的“低参数”网络之一。这种模型非常适合低资源设备和加速实时应用,如移动电话上的对象识别。MobileNet 和其他低参数模型背后的核心思想是将昂贵的操作分解成一组更小(更快)的操作。这种复合运算通常快几个数量级,并且使用的参数少得多。
原因 1: 我们大多数人都没有大型科技公司拥有的资源。理解低参数网络对于降低你自己的模型的训练和使用成本是至关重要的。根据我的经验,使用深度卷积可以在云推理中为您节省数百美元,而且几乎不会损失准确性。
理由 2: 众所周知,体型越大的模特越强壮。像 MobileNet 这样的论文表明,除了添加更多的过滤器之外,还有很多其他的东西。优雅很重要。
延伸阅读:到目前为止,MobileNet v2 和 v3 已经发布,在精度和尺寸上提供了新的增强。与此同时,其他作者设计了许多技术来进一步减小模型尺寸,如 SqueezeNet ,并以最小的精度损失缩小常规模型。 本文给出了几种模型尺寸与精度的综合总结。
#3 你需要的只是关注(2017)
“你所需要的只是关注。” 神经信息处理系统的进展。2017.
介绍变压器模型的论文。在这篇论文之前,语言模型广泛依赖递归神经网络(RNN)来执行序列到序列的任务。然而,rnn 非常慢,因为它们很难并行化到多 GPU。相比之下,Transformer 模型仅基于关注层,关注层是捕捉任何序列元素相互之间的相关性的 CNN。与之前的 RNN 车型相比,所提出的配方取得了更好的效果和更快的速度。
原因#1: 如今,自然语言处理(NLP)文献中的大多数新颖架构都是从 Transformer 发展而来的。像 GPT-2 和伯特这样的车型处于创新的最前沿。理解转换器是理解 NLP 中大多数后来的模型的关键。
原因#2: 大部分变压器模型都是亿万量级的参数。虽然关于 MobileNets 的文献提出了更有效的模型,但是关于 NLP 的研究提出了更有效的训练。结合起来,这两种观点为有效的训练和推理提供了最终的技术。
原因#3: 虽然变压器模型主要限于 NLP,但是所提出的注意机制具有深远的应用。像自我关注甘这样的模型展示了全局级推理在各种任务中的有效性。关于注意力应用的新论文每月都会出现。
延伸阅读:我强烈推荐阅读伯特和萨根的论文。前者是 Transformer 模型的延续,后者是 GAN 设置中对图像的注意机制的应用。
#4 停止用你的头脑/改革者思考(~2020 年)
梅莉蒂,斯蒂芬。"单头注意力 RNN:停止用你的脑袋思考" arXiv 预印本 arXiv:1911.11423 (2019)。
基塔耶夫、尼基塔、祖卡斯·凯泽和安塞姆·列夫斯卡娅。改革者:高效的变压器。arXiv 预印本 arXiv:2001.04451 (2020)。
变形金刚/注意力模型吸引了很多关注。然而,这些往往是资源密集型产品,不适合普通的消费类硬件。上述两篇论文都批评了这种架构,为注意力模块提供了计算上有效的替代方案。至于 MobileNet 的讨论,优雅很重要。
理由# 1:停止用你的脑袋思考《读起来是一篇该死的搞笑论文。这本身就是一个理由。
理由#2: 大公司可以迅速将研究规模扩大到一百个 GPU。我们,正常人,不能。缩放模型的大小并不是改进的唯一途径。我不能夸大那件事。阅读关于效率的文章是确保你有效利用现有资源的最好方法。
延伸阅读:由于这是 2019 年末和 2020 年,所以没有太多联系。考虑阅读 MobileNet 的文章(如果你还没有的话),了解其他关于效率的观点。
#5 姿势估计的人类基线(2017)
肖,宾,吴,魏。人体姿态估计和跟踪的简单基线【ECCV】欧洲计算机视觉会议论文集。2018.
到目前为止,大多数论文都提出了新的技术来改善最先进的技术。相反,本文认为,一个简单的模型,使用当前的最佳实践,可以令人惊讶地有效。总之,他们提出了一个人体姿态估计网络,该网络仅基于一个主干网络,然后是三个去卷积操作。当时,他们的方法是处理 COCO 基准测试最有效的方法,尽管它很简单。
原因 1: 简单有时是最有效的方法。虽然我们都想尝试闪亮而复杂的新型架构,但基线模型可能编码更快,而且还能获得类似的结果。这篇论文提醒我们,并不是所有好的模型都需要复杂。
理由 2: 科学是一步一步来的。每一篇新论文都将最新技术向前推进了一步。然而,这不一定是一条单行道。有时往回走一点,转一个不同的弯是值得的。“停止用你的大脑思考”和“改革家”是另外两个很好的例子。
原因#3: 适当的数据扩充、培训计划和良好的问题表述比大多数人认为的更重要。
进一步阅读:如果对姿态估计感兴趣,你可以考虑阅读这篇全面的最新综述。
#6 图像分类锦囊妙计(2019)
何,童,等“卷积神经网络在图像分类中的应用”IEEE 计算机视觉与模式识别会议论文集。2019.
很多时候,你需要的不是花哨的新模式,只是几个新花样。在大多数论文中,都会引入一两个新技巧来实现一两个百分点的提高。然而,这些在主要的贡献中经常被遗忘。本文收集了一组在文献中使用的技巧,并将其总结出来,供我们阅读时参考。
原因#1: 大多数技巧都很容易应用
理由 2: 你不知道大多数方法的几率很高。这些都不是典型的“使用 ELU”一类的建议。
延伸阅读:还有很多其他的招数,有些是针对问题的,有些不是。我认为值得更多关注的一个话题是类和样本权重。考虑阅读这篇关于不平衡数据集的类权重的论文。
# 7 SELU 激活(2017)
克兰鲍尔,京特,等人,《自规范化神经网络》 神经信息处理系统的进展。2017.
我们大多数人使用批量标准化层和 ReLU 或 eLU 激活函数。在 SELU 的论文中,作者提出了一种统一的方法:一种自我标准化输出的激活。实际上,这使得批量规范化层变得过时。因此,使用 SELU 激活的模型更简单,需要的操作更少。
原因#1: 在论文中,作者主要处理标准的机器学习问题(表格数据)。大多数数据科学家主要处理图像。读一篇关于纯密集网络的论文有点提神。
原因#2: 如果您必须处理表格数据,这是神经网络文献中关于该主题的最新方法之一。
原因#3: 这篇论文数学含量很高,并且使用了通过计算得出的证明。这本身就是一种罕见但美丽的东西。
延伸阅读:如果你想深入了解最流行的激活函数的历史和用法,我在 Medium 上写了一个关于激活函数的指南。看看吧:)
#8 本地特色包(2019)
布兰德尔,维兰德和马蒂亚斯·贝奇。“在 imagenet 上,用局部特征包模型近似 CNN 的效果令人惊讶地好。” arXiv 预印本 arXiv:1904.00760 (2019)。
如果你把一幅图像分成拼图一样的小块,把它们打乱,然后给一个孩子看,它就不能识别原来的物体;CNN 可能会。在这篇论文中,作者发现,对图像的所有 33×33 块进行分类,然后对它们的分类预测进行平均,可以在 ImageNet 上获得接近最先进的结果。此外,他们用 VGG 和 ResNet-50 模型进一步探索了这一想法,表明 CNN 广泛依赖于本地信息,而很少进行全局推理
原因 1: 虽然许多人相信 CNN“看得见”,但这篇文章显示的证据表明,他们可能比我们敢打赌的人要笨得多。
理由 2: 我们偶尔会看到一篇对 CNN 的局限性及其可解释性有全新看法的论文。
延伸阅读:与其发现相关,对抗性攻击文献也显示了 CNN 的其他显著局限性。考虑阅读以下文章(及其参考部分):
我们使用的机器学习模型有内在缺陷吗?
towardsdatascience.com](/breaking-neural-networks-with-adversarial-attacks-f4290a9a45aa)
#9 彩票假说(2019)
弗兰克、乔纳森和迈克尔·卡宾。《彩票假说:寻找稀疏的、可训练的神经网络》 arXiv 预印本 arXiv:1803.03635 (2018)。
继续理论论文,Frankle 等人发现,如果你训练一个大网络,剪枝所有低值权重,回滚剪枝后的网络,重新训练,你会得到一个性能更好的网络。彩票的比喻是把每一个重量看成一张“彩票”有了十亿张票,中奖是肯定的。但是,大部分票不会中奖,只有一对情侣会。如果你能回到过去,只买中奖的彩票,你就能最大化你的利润。“十亿票”是一个很大的初始网络。“训练”是运行彩票,看看哪些重量值高。“回到过去”是回滚到最初的未受训练的网络,并重新运行彩票。最终,你会得到一个性能更好的网络。
理由#1: 这个主意非常酷。
原因#2: 至于特征袋论文,这揭示了我们目前对 CNN 的了解是多么有限。看完这篇论文后,我意识到我们的数百万个参数是如何未被充分利用的。一个悬而未决的问题是多少。作者成功地将网络缩小到原来的十分之一,未来还可能缩小多少?
原因 3: 这些想法也给了我们更多的视角,让我们了解庞大的网络是多么低效。考虑一下前面提到的改革者的论文。它通过改进算法极大地减小了变压器的尺寸。通过使用彩票技术还能减少多少?
延伸阅读:权重初始化是一个经常被忽视的话题。根据我的经验,大多数人坚持默认设置,这可能并不总是最好的选择。 《你所需要的只是一个好的 Init》是关于这个主题的开创性论文。至于彩票假说,下面是一个容易阅读的评论:
从麻省理工学院 CSAIL 有趣的论文中提炼思想:“彩票假说:寻找稀疏的、可训练的…
towardsdatascience.com](/breaking-down-the-lottery-ticket-hypothesis-ca1c053b3e58)
#10 Pix2Pix 和 CycleGAN (2017 年)
用条件对抗网络进行图像到图像的翻译IEEE 计算机视觉与模式识别会议论文集。2017.
朱,严军,等.【非配对循环一致对抗网络的意象翻译研究】IEEE 计算机视觉国际会议论文集。2017.
如果没有一些 GAN 文件,这个列表将是不完整的。
Pix2Pix 和 CycleGAN 是关于条件生成模型的两部开创性著作。两者都执行将图像从域 A 转换到域 B 的任务,不同之处在于利用成对和不成对的数据集。前者执行将线条画转换为完全渲染的图像等任务,后者擅长替换实体,例如将马变成斑马或苹果变成橙子。由于是“有条件的”,这些模型允许用户在一定程度上控制通过调整输入所产生的内容。
原因#1: 甘的论文通常只关注生成结果的纯粹质量,而不强调艺术控制。诸如此类的条件模型为 GANs 在实践中变得有用提供了途径。例如,成为艺术家的虚拟助理。
原因#2: 对抗性方法是多网络模型的最佳范例。虽然生成可能不是你的事情,但阅读多网络设置可能会启发一些问题。
原因# 3:cycle gan 的论文特别展示了有效的损失函数如何在解决一些难题时创造奇迹。聚焦损耗论文给出了类似的想法,它通过用更好的损耗代替传统的损耗,大大改进了物体探测器。
延伸阅读:AI 成长快,gan 成长更快。如果你从来没有过,我强烈推荐你编写一个 GAN。这是关于此事的官方 Tensorflow 2 文档。GANs 的一个不太为人所知的应用是半监督学习。
有了这十二篇论文和它们的进一步阅读,我相信你已经有足够的阅读材料可以看了。这当然不是伟大论文的详尽列表。但是,我尽我所能选择了我看过和读过的最有见地和最具开创性的作品。请让我知道,如果有任何其他文件,你认为应该在这个名单上。
好读书:)
编辑:写完这个列表,我又编了第二个,里面有 2020 年多读的十篇 AI 论文,第三个是关于 GANs 的。如果你喜欢阅读这个列表,你可能会喜欢它的延续
额外的阅读建议,让你跟上人工智能和数据科学的最新和经典突破
towardsdatascience.com](/ten-more-ai-papers-to-read-in-2020-8c6fb4650a9b) [## 甘 2020 年要读的论文
生成性对抗网络的阅读建议。
towardsdatascience.com](/gan-papers-to-read-in-2020-2c708af5c0a4)
随意评论或者联系我。如果你是中新,我强烈推荐订阅。对于数据和 IT 专业人员来说,中型文章是 StackOverflow 的完美搭档,对于新手来说更是如此。注册时请考虑使用我的会员链接。
感谢阅读:)
人工智能如何在这次疫情中扮演关键角色
需求预测、药物发现、弥合服务差距和诊断

图片由来自 Pixabay 的Fernando zhimaicela拍摄
冠状病毒已经影响了全球的每一个人。人们失去了他们的亲人,国家关闭,医疗专业人员夜以继日地工作,人们失去了工作。
因为人工智能已经成为几年来最热门的话题之一。在这样的时代,它有什么相关性,它如何帮助人类战胜这场危机?
需求预测以减少供应缺口
健康度量和评估研究所(IHME)是华盛顿大学医学院的一个研究机构。他们发布了一组冠状病毒数据预测可视化图,白宫、联邦紧急事务管理局和医院正在使用这些数据来调动资源。
IHME 开发了一个预测医院病床和呼吸机数量需求的模型。它还预测了未来 4 个月全球因冠状病毒死亡的人数。
IHME 于 3 月 26 日发表了他们的分析。他们预测对医院服务的需求很可能会大大超过医院的能力。41 个州将需要比医院可提供的更多的 ICU 床位,其中 11 个州需要增加超过 50%的 ICU 床位。这些分析有助于政府和组织满足即将到来的需求,并实施战略来缩小这一供应缺口。
用于药物发现的人工智能研究
新冠肺炎高性能计算联盟是一个由科技公司、学术界、国家实验室和联邦机构组成的研究联盟。
研究界已经提供了他们的技术能力,致力于复杂的研究项目,以帮助对抗病毒。研究人员正在应用人工智能算法,构建机器学习模型、生成网络、强化学习;用于药物发现、发现分子&基因组表征和结构分析,以及模拟。
公司和机构正在提供超过 402 petaflops、超过 300 万个 CPU 内核和超过 40,000 个 GPU 的免费云计算资源。这些超级计算机为顶级科学家和研究人员提供了计算需求,以确保快速获得结果。
减少呼叫中心负荷的虚拟助理
全球各地的急救和医疗服务部门已经看到,出现冠状病毒症状的人的呼叫量有所增加。随着客户代表和社会工作者越来越多地被要求在家工作,公司和国家正在转向人工智能,以弥合由此产生的服务差距。
在意识到许多人都在问同样的一般性问题后,实现虚拟助手似乎是解决方案。哥本哈根使用了一个虚拟助理机器人为人们筛查冠状病毒;该机器人在工作的第一天就回答了 3 万个电话。这使得医疗保健专业人员不必回复查询,而是将时间集中在为患者提供护理上。
微软医疗保健机器人提供自助症状检查器,其语言理解模型被调整为理解医疗和临床术语。这个自我评估机器人对于提供解决方案来帮助患者和临床团队抗击这场全球健康危机至关重要。
计算机视觉诊断冠状病毒
美国已经集体测试了一百万人,一些测试结果需要一个多星期才能出来。冠状病毒测试仍然是美国应对疫情最紧迫的问题之一——这需要快速准确的冠状病毒诊断。
阿里巴巴集团建立了一个能够根据 CT 扫描图像进行病毒诊断和分析的人工智能系统。一台 CT 机为每个病人生成 300 到 400 张图像,一个非常有经验的医生至少需要 10 分钟来诊断一个病人。人工智能系统可以在不到 30 秒的时间内进行诊断,准确率高达 96%。
这些人工智能医疗成像系统使用计算机视觉对病例进行分类,并检测改善的迹象。它作为一种分析和筛选工具,为医生做出决定提供意见。这些人工智能系统已经被 26 家医院使用,并在中国帮助诊断了超过 30,000 个病例,并且正在帮助其他国家的路上。
John Kennedy highlighted that the Chinese word for crisis (危机) is made up of two components, danger and opportunity. In every crisis lies an opportunity, we have to harness this opportunity so that we can progress as a human race. This crisis would emerge innovative ways to apply and to advance artificial intelligence. I am optimistic about the future of AI and how it can change the way we live.
用中文写,“危机”这个词由两个字组成。一个代表危险,一个代表机遇。——约翰·肯尼迪
通过缩短 65%的评估时间,人工智能在对抗疾病传播方面发挥了关键作用
towardsdatascience.com](/radiologists-computer-vision-diagnose-covid-cecbcdf96e8f)
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
JupyterLab 中人工智能驱动的代码完成
启动 JupyterLab 中几乎无用的代码建议

JupyterLab 的原生代码完成很好…不太好。
作为一名数据科学家,你几乎肯定会使用一种 Jupyter 笔记本。希望您已经了解了 JupyterLab 的优点,它集成了侧边栏、标签等等。当它在 2018 年首次推出时,JupyterLab 很棒,但感觉它缺少一些东西。
现在你可以添加一个可视化调试器,甚至还有一个名为 nbdev 的库,它允许你创作完整的 Python 包并将它们推送到 PyPI。JupyterLab 已经成为数据科学家的完整 IDE。但是有一件事直到最近还不是最理想的,那就是代码完成。
尝试使用 JupyterLab 中内置的代码补全功能会得到如下结果:

当你真的想要一个完整数据帧的绝对值时。
Kite ,一家为各种语言和 IDE 开发代码完成软件的公司,最近为 JupyterLab 发布了 Kite。现在你可以得到这样的东西:

这更有道理。
使用逻辑自动完成功能简化您的生活。它在本地运行,不会把你的代码发送到云端。

是的,我确实想要 plt.plot()。谢了。
它并不完美,当然也不了解你的想法。尽管对于默认的代码完成来说,这是一个很好的升级。
Kite for JupyterLab 让您离基于完整笔记本的 IDE 更近了一步。
如何为 JupyterLab 安装风筝
为 JupyterLab 安装 Kite 相当容易。
- 首先,为桌面安装风筝。你可以在这里得到安装程序。版本适用于 Windows、Mac 和 Linux。
- 请确保您的 JupyterLab 是 2.2 版或更高版本。这是 JupyterLab 的最新版本,因此您可能需要使用 conda 或 pip 升级您的安装。
- 安装 JupyterLab 扩展。您需要像安装其他扩展一样安装 NodeJS。
pip install jupyter-kitejupyter labextension install "@kiteco/jupyterlab-kite"
我迄今为止的经验
我用 Kite 做 JupyterLab 已经一个星期了。这不是开创性的,但它确实让我的编码体验变得更好。完成速度也明显快于本地完成。
我使用的是 Kite 的免费版本,并且 100%在本地完成。对我来说,最好的建议并不总是在顶部,但通常是在前 5 位。作为数据科学家,我们使用许多方法,这是在需要时获得提醒的好方法。
编码快乐!
感谢阅读。你可以在这里找到更多关于我的信息。考虑订阅以便在我发布时收到通知。如果你想直接支持我的文章,你可以使用我的推荐链接注册成为媒体会员。
人工智能驱动的设计工具
创意、效率和设计的民主化
德克·克内梅尔和乔纳森·福利特
AI 会对设计的实践产生什么影响?我们与 Adobe 人工智能产品营销和战略主管塔蒂亚娜·梅希亚一起探讨了这个问题,她是《硅谷商业杂志》2018 年度最佳硅谷人工智能女性之一。Meija 将我们带入了 Adobe Sensei 的世界,该公司的人工智能和机器学习技术正在影响他们所有的关键软件应用程序。
30 多年来,Adobe 一直是设计人员软件工具的领先提供商。对于依赖 Adobe 软件的设计师来说,他们工作的核心材料从纸张、像素和代码到字体、颜色和布局。在软件成为工具集的一部分之前的几十年里,这些人被称为图形设计师。模拟过程是手动的、缓慢且费力的。平面设计师是以这些物理限制的速度进步的,而不是以他们思维的速度。
随着数字过程取代模拟和物理方法,设计过程发生了巨大的变化。“我记得在大学时,我走进暗室处理我的照片,”梅希亚说。“我必须非常仔细地思考我的意图是什么。我想让它看起来梦幻。我希望有些部分比其他部分更突出。通常,它需要多种方法。所以,如果你想到拍摄照片并把它变成艺术或一种表达的活动,现在我们大部分都是用数字方式做的。在某种程度上,这就是自动化。”随着设计转向数字化,有了像 Photoshop 和 Illustrator 这样的工具,事情开始加速。制作电脑从手工练习转移到了鼠标、显示器和键盘。随后的创新和改进使得这个速度越来越快。

图 01:制作一个从艺术和手工艺练习转移到鼠标,显示器和键盘的比较。
[图片:由马库斯·斯皮斯克在 Unsplash 上拍摄]
随着软件和互联网不仅发展了工具,还发展了应用设计的媒体,出现了一系列复杂的标题和数字原生标识符。这些现在通常被概括在一个更广泛的学科中,包括研究人员、工程师和设计师之外的其他专业,称为用户体验。自从十多年前移动计算兴起以来,这种特殊的设计职业已经爆炸式增长。这体现在 Adobe 自身的成长上。2005 年,也就是 iPhone 发布的前一年,Adobe 的年收入不足 30 亿美元。到 2018 年,这一数字上升到 90 多亿美元。虽然这是各种因素的产物,但它也反映了世界上有多少人正在使用这些数字设计工具。
鉴于 Adobe 的规模、影响力和作为数字设计软件市场领导者的稳固地位,他们也在机器学习和人工智能方面进行大量投资以改善其产品也就不足为奇了。一方面,他们的软件的既定性质对什么样的解决方案可以实际应用和商业化提供了一些限制,另一方面,他们的经验、产品成熟度以及应用和功能的多样性为探索这些新技术的潜力提供了令人信服的基础。“Adobe Sensei 是我们的人工智能和机器学习技术,它用于创建和交付数字体验,”梅希亚说。“我们正在考虑如何让我们的用户更容易、更好、更快地做他们最擅长的事情。”
“如果我们考虑人工智能和机器学习,我们已经在这方面工作了 10 多年。“我们的第一个机器学习功能实际上是 Photoshop 中的红眼消除,”梅希亚说。像红眼减少这样的功能,在 15 年前是照片编辑应用程序中的神奇选项,现在已经自动化,并被视为理所当然。我们已经从慢速和模拟,到慢速和数字,到快速和数字,到现在,在许多情况下,自动。由于这些进步,设计在过去 30 年左右的时间里发生了翻天覆地的变化。

图 02:随着摄影从模拟转向数字,过程中的许多任务都实现了自动化。
【图片:托马斯·斯蒂芬在 Unsplash 上拍摄
提高创意过程的效率
Adobe 强调,借助 Sensei 的人工智能,他们希望最大限度地减少设计实践的单调乏味。唤醒人工智能可以开始处理一些经常需要入门级设计师的机械生产杂务。这方面的例子可能包括费力地从照片背景中剪切出一个复杂的对象,或者创建一组适合各种社交媒体风格的图形。在这种人工智能驱动的功能的帮助下,该软件不再需要以细节为导向的设计师来执行这些任务,而是将他们的时间花在做其他事情上。“我还没有遇到过一次就做对的设计师,”梅希亚说。“他们喜欢反复思考这个问题。人工智能让你能够做的是……更快地找出你试图做的事情。”
这种加速给了设计师解决更多问题的机会,甚至是向价值链上游移动,解决不同类别的问题。“人工智能要做的事情之一是让那些刚开始的职业生涯变得有趣得多,”梅希亚说。人工智能将比几乎任何其他创造性职业更彻底地改变设计职业。设计师将能够专注于更高层次的上下文,例如解决与系统相关的问题,而不是人们以一般方式思考“设计师”时经常想到的像素。
寻找隐藏模式
Adobe 现在让设计师更容易找到合适的库存摄影的方法是一个很好的微观案例,研究人工智能和机器学习如何增强创造性工作——无论是在设计还是其他专业领域。长期以来,股票摄影一直被元数据“标记”,以便人们更容易搜索。但凭借人工智能阅读和解释图像的能力,它可以用更广泛的术语来标记图像,从而实现精确的搜索。“我们正在做的事情之一是让人们更容易谈论他们想要什么和他们想要什么,并以直观的方式找到它,”梅希亚说。在如何对照片进行分类的粒度特异性,以及视觉搜索等更先进和用户友好的工具之间,机器学习层正在将智能注入到既节省时间又为最终的创意选择增加质量和价值的过程中。
梅希亚说:“我们正在寻找模式,我们正在利用计算机视觉来帮助丰富信息,这样,对用户来说,它就像魔术一样。”。“因此,你可以搜索‘family ’,然后拖放你想要匹配的配色方案。现在你有了所有家庭的彩色照片。”
或者,也许你可以输入你在现实世界中捕捉到的软件图像,这些图像为你带来了创造性的灵感,并且——受到机器读取图像的能力以及系统中已经存在的大量现有和经过良好审查的图像的支持——人工智能可以将你与更多更好的资产联系起来。诸如此类的功能将使设计者能够在解决问题、寻找灵感和阐明解决方案的空间中工作,减少手动中间步骤。
自动化和设定创意意图
这些人工智能解决方案将切实影响设计师的工作流程,特别是当涉及到跨所有太多形式的数字媒体的缩放工作时。“设计师设定创意意图。他们知道自己想做什么。他们甚至可能创造出第一个,”梅希亚说。“但即使你考虑制作或后期制作,创造变化,这也是人工智能非常强大的地方。…能够快速做到这一点意味着您可以在 it 上花费更多时间,即使生产压力增加也是如此。”

图 03:人工智能驱动的软件解决方案将切实影响设计师的工作流程。
【图片:由 Lubos Volkov 为 Unsplash 上的 UX 店拍摄
“因此,当我们考虑自动化时,最容易利用人工智能的事情是那些容易定义和重复的事情,”梅希亚说。“因此,如果你考虑为一个电子商务网站制作图像,例如,你可能会得到许多不同的输入,但你希望它具有某种美感,甚至可能是相同的背景颜色,等等,这些事情通常是一系列步骤——这将是你可以利用人工智能的事情。即使在创作中,它也会让一些更独立的作品变得更容易。因此,你在创意总监模式下获得的创意更多,而不是制作助理。”
对于创意专业人士,尤其是设计师来说,人工智能在早期的影响将主要是面向生产的。这包括从设计制作到撰写公式化的股票简介,再到自动化最常见的客户服务互动。虽然从字面上看,这将使一些工作过时,但这并不一定意味着特定职业的机会,如设计工作,将变得更加有限。回顾最近的设计历史,即使软件将某些元素自动化,使曾经需要几小时或几天的任务现在只需要几分钟或几小时,最终结果是越来越多的设计在世界上开花结果。苹果公司等公司展示了更好的设计对公司利润和成功的不可思议的影响,使设计成为希望竞争的公司更高的战略优先事项。因此,设计行业蓬勃发展。没有理由相信这些新的进步会有任何不同,即使具体的任务和工作已经过时。机会将会改变。设计师只需要提前思考并为此做好准备。
回路中的人类
人工智能在狭窄和有限的环境中是伟大的,在更大或更多面的环境中是可怕的——特别是在复杂、动态和始终处于运动状态的环境中,如人类、社会和文化。设计师的核心洞察力一方面引领新的趋势和时尚,另一方面为特别复杂的情况提供精确的出色解决方案,这些都不会很快被机器实现。这是设计师在准备未来成功时应该集中时间、精力和专业知识的地方——不是在制造和装配上,机器将越来越多地比我们做得更好,而是在解决问题的活动上,如研究、分析、策略和解决方案。在未来的几年甚至几十年里,有哪些任务需要人们去完成?“打破模式,看到新的模式,这是人类特有的火花,”梅希亚说。
梅希亚说:“我们委托进行了一些研究,并进行了 100 多次定性采访,询问设计师们他们对什么感到兴奋,他们觉得可以在哪里使用(人工智能工具),他们关心什么。”。
“(他们)最大的担心是,它会变得同质化。如果每个人都能使用这些工具,我们会不会开始看到艺术看起来都一样?”
虽然这是一个合理的担忧,但我们已经在模拟世界中看到了这种趋势。尽管如此,新的风格和想法找到了他们的市场,审美世界继续发展。最终,是市场和创造者引导我们走向或远离一致性。
民主化设计
在我们的谈话中,梅希亚提出了一个重要的商业模式演变:个人设计顾问,或代理业务,目前依赖于工作流,他们的能力实施简单的,以生产为导向的现有资产的更新,让他们忙碌,计费和财务上可行。这将越来越受到损害,可能不会被内部设计师和创意人员取代,而是被我们通常想象不到的负责监督资产重用和格式化的人取代——比如营销人员和产品经理。
“我认为人工智能是一个必要而重要的工具,它将帮助我们应对和满足所有这些内容速度的需求,全天候的需求,以及从人群中脱颖而出的需求,”梅希亚说。“这也将使一些创意民主化,这意味着不是每一个变化都需要回到设计师那里。”
人工智能驱动的软件将很容易取代最公式化和程序化的任务,在这个过程中,商业人士可以实现曾经被认为是创造性的过程,要求有创造力的个人通过做更多实际上有创造性的事情来赚钱。Adobe 软件的结构已经说明了现在和将来任务和角色的混合。广泛的 Adobe 工具套件不仅包括面向设计师的模块,还包括面向更广泛的创意和商业专业人士的模块。在同一个生态系统中运行,一个日益一体化的生态系统,将彼此带入彼此的工作流程和工具,预示着一个流动的未来,在这个未来,机器趋向于单调乏味,而创意者在创作过程的前端越来越多地接受挑战。
我们正在进入一个时代,在这个时代,创造力将变得越来越容易获得和民主化。Adobe 的软件也引入了非设计师,让他们和设计师一起工作。而且,随着时间的推移,越来越多的更简单或常规的设计任务将变得自动化,不需要设计师来完成。Adobe 的人工智能提供了另一个重要的证据,表明当前和下一代机器学习工具将使非专业人士——没有受过写作或设计等方面训练的人——更容易开始将他们的沟通或创作能力专业化,而以前需要请作家或设计师来做。这为公司和个人带来了很多可能性,我们期待在本系列的后续文章中分享这些可能性。
Creative Next 是一个播客,探索人工智能驱动的自动化对创意工作者,如作家、研究人员、艺术家、设计师、工程师和企业家的生活的影响。本文伴随 第三季第三集——AI 驱动的设计工具 。
人工智能驱动的未来电信网络:爱立信案例研究
人工智能推动电信行业的变革

图片由 Unsplash 上的 Anastasia Dulgier 拍摄
我们见证了电信行业每天都在发生变化,人工智能是其主要驱动力。今天的电信网络将人们联系在一起。在 5G 和物联网的帮助下,未来的电信网络不仅将连接人,还将连接物和工厂,并提供身临其境的视频用例。所有这些创新需求都给电信网络带来了压力,以支持这些用例。爱立信自动化和人工智能开发负责人 Gaurav Dixit 在 2019 年 数据创新峰会 上发表演讲时强调,他们将鼓励这些未来电信网络的设计、创建和运营发生根本性转变。Gaurav Dixit 深入探讨了爱立信如何通过部署人工智能和自动化技术来应对 5G 给电信和 it 网络带来的挑战,从而转变其服务和产品组合。

Hyperight AB 在数据创新峰会上的照片 /版权所有
爱立信如何部署人工智能和自动化技术
爱立信一直是采用新的颠覆性技术并将其集成到服务组合中的领导者。“我们正在改变自己,并为客户带来好处”,Gaurav 解释道。
爱立信并不认为 5G 架构是一个单一的人工智能堆栈。Gaurav 解释说,他们在每个架构层中都嵌入了人工智能,作为贯穿其整个产品和服务套件的端到端联合人工智能。从计费和收费到管理和协调,再到 5G 接入和网络服务,所有组件作为一个实体协同工作,以卓越的客户服务为客户提供 5G 网络的最大优势。
但如果人工智能和自动化是解决方案,那么肯定有一个问题需要解决。Gaurav 解释说,他们的最终目标是通过提供最先进的网络性能提供卓越的终端消费者体验,这反过来将通过利用 5G 和物联网支持的新用例带来新收入,从而通过降低 OPEX 带来效率提升。
因此,这是一个相互依赖的组件链,从人工智能技术开始,到卓越客户体验的最终目标结束。

由 manolofranco 在 Pixabay 上拍摄的照片
通过提供人工智能支持的服务和产品获得的经验教训
几年来,爱立信一直在他们的产品组合中部署人工智能和自动化技术,他们可以深入了解他们在这一过程中吸取的一些经验教训。
获取数据
“数据对于人工智能技术就像空气对于人类一样”,Gaurav 描绘道。因此,对数据的访问,以及正确的数据质量、正确的合同权利、数据管理和治理——这是采用人工智能的第一步,也是最重要的一步。
视频由hyperlight AB—支持人工智能的零接触、实时、电信& IT 网络设计— Kai Chaza & Gaurav Dixit,爱立信
应用和平台
下一步要考虑的是正确的应用程序和平台,因为正如 Gaurav 所说,数据必须存储在某个地方。爱立信选择的平台是一个基于云的平台,用于提供灵活和可扩展的服务。
根据经验,Gaurav 说这两个技术部分只占所有工作的 40%。这座冰山的其余 60%属于 流程 和 人员 的其他组成部分,因为他们是变革管理工作的一部分,这意味着从根本上改变人们的工作方式和评估方式。随着新技术的引入,需要新的能力,人们需要重新掌握技能,这也需要文化的改变。

爱立信如何应对技术带来的变化
Gaurav 提到了爱立信成功的人工智能和自动化应用的三大支柱:
- 业务和数据生态系统——跨产品和服务组合的端到端联合人工智能。如前所述,他们将人工智能嵌入到每一层,并将其用于预测客户行为、动态编排、预测事件等。
- 爱立信研究中心——是 2G、3G、4G 和 5G 发明的地方。一个容纳 750 名研究人员的大脑之家,其中 100 名研究人员从事人工智能相关技术的工作,他们利用这些技术来解决客户问题。
- 能力-卓越中心或全球人工智能加速器-卓越中心拥有 300 名数据科学家,并提供他们需要的能力,以扩展他们与研究一起创建的解决方案。

一切是如何协同工作的?
正如 Gaurav 之前提到的,第一个也是最终的指导方针是他们的客户。“一切从顾客开始”,Gaurav 强调说。他们以用例驱动、以客户为中心的快速原型方式工作。他们直接与客户交谈以发现他们的痛点,并通过研究寻找解决痛点的方法,与客户一起在业务部门内测试可能的解决方案,并在全球人工智能加速器的帮助下进行扩展。
人工智能用例
爱立信的托管服务业务部门在三个部门有几个经过验证的人工智能用例:网络运营、it 运营以及设计和优化。
举例来说,Gaurav 解释了现场调度优化用例,其中涉及到技术人员前往缺陷现场进行修复,并花费大量资金。在与一位客户交谈后,他们发现 10%的现场派遣是误报。为了解决这个问题,他们分析了数据,现在能够预测 10 个不必要的现场调度员中的 9 个。该解决方案直接影响客户底线,并节省不必要的成本。
至于必要的调度,通过逻辑树,他们可以预测是否有人需要爬网络塔,以及他们需要什么设备,从而节省宝贵的资源。

人工智能是一个旅程,而不是目的地
人工智能的采用本身并不是目标,它是一个旅程,应该如此对待。爱立信已经在这条路上走了几年,可以自豪地说,他们已经实现了人工智能和机器学习用例的产业化。至于未来的目标,Gaurav 说他们的目标是机器推理,这是类似人类知识的自动化。
我们已经在体验未来的网络,因为商用 5G 网络已经在世界各地上线,连接更多的物联网设备,用户已经开始感受到好处。
人工智能对 2020 年的预测
推动人工智能(AI)的商业价值,在边缘建模,对数据隐私和治理的日益关注,以及日益增长的人才战争,这些都是关键的人工智能趋势
艾:每个人都喜欢,但只有少数人做得好。2019 年麻省理工学院 SMR-波士顿咨询公司人工智能全球高管研究和研究报告指出,如今十分之九的企业都投资于人工智能,但迄今为止,70%的企业收效甚微。
2020 年将是人工智能领域活跃的一年。随着 2018 年至 2019 年的试验阶段开始变得成熟,采用将开始以严肃的方式进行,企业领导人将开始评估所做投资的价值。以下是 2020 年首席执行官和企业领导人应该期待的相关发展趋势:
1。企业将真正运营人工智能并衡量影响
2020 年,首席管理人员将开始评估他们的人工智能赌注的价值,并向企业证明投资回报率。Forrester 的人工智能预测指出:“我们相信,2020 年将是公司变得高度关注人工智能价值、跳出实验模式、立足现实以加速采用的一年”。
要做到这一点,企业首先要做的是了解衡量结果的方式。数据科学家习惯于根据召回率/精确度、AUC 和类似的“科学”指标来评估他们的“成功”,这与企业衡量计划有效性的方式不同。为了弥合差距,数据科学家必须坐下来,先验地与业务部门一起工作,并与业务部门一起制定一个通用框架,以了解和衡量他们的工作对业务的影响。
例如,在世界顶级电信公司之一的 Airtel,我们知道,对于我们的“漫游者”(在国际旅行时使用本地电话的人)活动,以下是数据科学、业务(在这种情况下为营销)和财务指标之间的关系。

图 1:数据科学指标与营销成果和收入的关系
一旦这些“翻译表”建立起来,所有相关的企业和组织就可以很容易地专注于同一个目标并衡量影响。
2。人工智能将为信任和公平而设计
随着人工智能渗透到用户生活的更多领域,系统必须可靠、公平、负责。考虑一个人工智能系统的情况,该系统根据“替代”信用数据计算无银行账户客户的信用度,这些数据包括蓝领或零工经济的工资支票、小额贷款的使用和偿还、社会档案等。非传统贷款人和用户都必须信任该系统,以使该产品长期有效。
几乎所有生活领域,从我们在零售、电子商务、银行、娱乐(仅举几例)中使用的日常产品,或者我们与越来越智能的系统或设备的交互,都将开始与人工智能结合。人工智能的实践者必须确保公众可以确信这项技术是透明的、安全的,并且其结论不会有偏见或受到操纵。2020 年,提供可信度和“公平”衡量标准的技术将开始融入人工智能生命周期,帮助我们构建、测试、运行、监控和认证人工智能应用程序,以获得信任,而不仅仅是性能。
3。AI 将进一步移动到边缘
我的“2019人工智能预测”预测了从纯云到云边缘混合策略的转变,以实现更有效的机器学习(ML)。虽然 2019 年见证了诸如联合学习等技术的发展,但 2020 年将见证这一趋势的大幅加速。今天,在云中分析高保真、高分辨率的原始机器数据的能力在传输和计算方面都很昂贵,因此,通常不会实时发生,导致从收集的数据中获得的商业价值最小。

图二。机器学习将迅速从纯云策略转向云边缘混合策略,从而变得更加有效
以数字娱乐(OTT)和 B2C 互联网应用为例。能够根据音乐爱好者跳过或听过的最后一首歌曲向他们提供实时推荐将是非常有价值的。然而,今天,许多组织已经满足于较小规模的样本数据或延时数据,这提供了一个半优化的结果。
联邦学习等技术的成熟现在使得在远程基础设施上甚至在配备人工智能处理器的领先智能手机上实时放置“边缘化”的 ML 模型成为可能。
4。人和机器将进行他们的“第一次接触”
人类和人工智能驱动的机器已经开始协同工作,想想你家里的 Alexa 或 Siri,或者今天早上提醒我机场出现意外清晨交通的谷歌助手,使我能够赶上航班,并在今天的航班上写下这篇文章。
我们看到机器兴起的第一个地方是联络中心。那里的流程更加标准化和规范化,服务成本仍然相对较高,消费者对越来越多的数字渠道的“即时服务”的期望甚至对管理最好的联络中心管理提出了挑战。人工智能不是完全取代代理,而是可以消除重复的任务(账户余额、地址变更、添加新服务)。最重要的是,人工智能处理复杂查询的快速涌现能力已经成为代理的补充,使它们能够跨渠道提供更多上下文相关和知情的响应。

图片由皮克斯拜的 Gerd Altmann 提供
与任何新技术的实施一样,联络中心的人工智能将带来自身的挑战——看起来过于自动化的客户之旅可能最终导致客户疏远或失望,特别是婴儿潮一代,他们往往是顶级付费客户,并期待个性化服务。
5。人工智能专家将成为焦点,无处不在
“人工智能冬天”于 2019 年正式结束,人工智能的先驱 Yoshua Bengio、Geoffrey Hinton 和 Yann le Cun——有时被称为“人工智能教父”——因其开发深度学习人工智能子领域的工作而获得 100 万美元的图灵奖。
人工智能和人工智能一直是热门话题,新闻主要是由脸书、谷歌、网飞等科技公司推动的。许多非科技传统企业在创建了自己的“人工智能战略”后,开始专注于解决影响其业务指标的现实问题。在花了几年时间进行数字化工作以理顺数据管道并确定人工智能可以带来回报的机会领域后,传统企业正在推进人工智能的用例及应用。
根据 LinkedIn 的数据,为了跟上需求的突然增长,人工智能从业者的招聘在过去四年中每年增长 74%,顶级从业者吸引了狂热的追随者和职业足球运动员类型的补偿。
6。最后,人工智能的黑暗面
人工智能并不是技术和文明的“万灵药”,有时你们日报上的专栏会让你相信这一点。如果不小心处理,人工智能会以今天无法想象的方式造成伤害。我们已经看到了早期的虐待。面部识别系统现在可以使用人工智能生成的 3d 打印面膜来愚弄。今天,人工智能生成的自动化虚假内容正在造成巨大破坏,下一代同样的内容被其创作者视为太危险而不能向公众发布。不考虑隐私而过度使用个性化会伤害或冒犯客户、员工和整个社会。
总结
2020 年将是人工智能的分水岭,该技术将在 2018-19 年脱离实验周期,并开始在所有类型的业务、流程、产品和服务中被采用。2020 年,企业将真正实现人工智能并衡量影响。消费者对技术的理解将开始改变。然而,随着人工智能渗透到用户生活的更多领域,系统必须可靠、公平和负责任。
2020 年,AI 将进一步走向边缘。虽然 2019 年见证了联邦学习等边缘计算技术的发展,但 2020 年将见证这一趋势的大幅加速。然而,隐私仍将是企业必须解决的一个挑战,以确保公众广泛接受这项技术。
结语:我写的是数据科学、机器学习、产品管理和职业成功的故事。你可以跟着我把这些放进你的培养基里。
上一篇: 用“印度级”技术为世界供电
下一个故事: 印度贫困地址的经济影响:一年 100-140 亿美元
人工智能伪科学和科学种族主义
最近通过面部特征预测犯罪的尝试让人回想起不道德和种族主义伪科学的悠久传统

来源:维基共享资源
更新(2020 年 6 月 30 日):*文章《从面部图像中发现犯罪倾向和性别偏见的影响》被撤回 ,因为作者“在进行这项使用人类生物特征数据的研究之前,没有寻求伦理委员会的批准。”这是我指出的关于最初研究的许多问题之一。*
本月早些时候,哈里斯堡大学即将发表的一篇论文引起了轩然大波。题为“使用图像处理预测犯罪行为的深度神经网络模型”的论文承诺:
该软件有 80%的准确率,并且没有种族偏见,仅根据一张人脸照片就可以预测一个人是否是罪犯。该软件旨在帮助执法部门预防犯罪。
这种说法是绝对荒谬的,这将在下面讨论。
来自不同研究者的广泛批评导致论文被撤回。来自 2016 年的另一篇论文做出了类似的承诺——它也受到了广泛的批评,导致作者们对他们关于 arXiv 的原始论文做出了回应。
然而,几个月前在 2020 年 1 月发表的另一篇论文基本上躲过了类似的关注和愤怒。哈希米和霍尔在大数据期刊* 上发表的“从面部图像中检测犯罪倾向和性别偏见效应”声称:*
本文探索了深度学习在区分犯罪和非犯罪人脸图像方面的能力。。。CNN【卷积神经网络】实现了 97%的十倍交叉验证准确率。
声称从一个人的照片预测犯罪有 97%的准确性是一个大胆的说法。正如我们将看到的,由于其概念和执行方面的问题,这种说法是完全没有根据的。
这将通过研究的伪科学框架以及实验的实际问题来展示,包括通过训练深度学习模型来复制类似结果的尝试。事实证明,我们可以得到类似的优秀结果,这与“犯罪行为”无关,而是与基本的实验误差有关。
什么是犯罪?
犯罪是一种社会现象。这意味着,我们所谓的“犯罪”或“犯罪行为”实际上是一个不断变化的社会定义,取决于我们所指的时间和地点。它与生物学无关,除了社会对它的定义之外,它没有更高的、不变的定义。
赌博和卖淫在加州是犯罪行为,但在内华达州却是合法行业。大麻销售和消费在加州是合法的,但直到最近才是这样,它仍然是一项联邦罪行。
但有人可能会说,这些是没有受害者的犯罪。谋杀呢?
如果你在邻居的房子里放置了一枚炸弹,炸弹爆炸并炸死了他们,你可能会被判犯有纵火罪和谋杀罪。但是,如果总统向伊拉克宣战并轰炸巴格达的整个街区,这可能不被认为是犯罪行为(根据美国法律),尽管我们中的一些人会认为这在道德上是令人反感的。
过去奴隶主杀死他们的奴隶是合法的,整个经济和文化都将这种权力的不平衡视为社会的基本权利。现在在美国,奴役他人是一种犯罪。一个被绑架、关押了一段时间并遭受残暴对待的人,无论在道德上还是法律上,杀死绑架者以重获自由都是完全正当的。在这种情况下,一个本来不会杀人的人可能会愿意杀人。
换句话说,犯罪没有什么天生的生物学特征。这和你的基因无关,更和你的脸无关。
没有任何机器学习算法,即使是一个真正好的卷积神经网络,也无法根据一张照片或关于一个人的其他生物信息来预测犯罪,因为“犯罪”与你的关系不大,而是与社会如何判断和回应你的行为有关。
这是否意味着,如果有人杀了另一个人,我们只是举起双手说,“嗯,这只是一个社会构造!”不,当然不是。但是我们必须把它放在背景中,看看造成了什么样的社会危害。在某些情况下,杀人是不人道和不道德的,而在其他情况下,这可能是一种自卫行为,唯一的区别可能不是行动,而是发生的社会。
这里的要点是,“犯罪”是一个非常模糊和宽泛的概念,我们可能认为是犯罪(或非犯罪)的行为会随着时间的推移而变好或变坏。
哈希米和霍尔如何解决这些含糊不清的问题?他们根本没有解决这些问题。事实上,他们甚至没有建立一个数据集,即使使用美国使用的最基本和广泛接受的定义,也能始终正确地将人脸标记为罪犯或非罪犯。
在被证明对数据科学有用之前是无辜的
哈希米和霍尔使用两组人脸来训练他们的模型。首先,他们的“犯罪”脸是从国家标准和技术研究所(NIST)提供的一组面部照片中收集的。他们的“非犯罪”面孔是从许多普通的非 mughsot 来源收集的,这些来源由各个大学的面部识别研究人员管理。
问题是,面部照片不一定描绘罪犯。这些人已经被逮捕,但不一定被判有罪。这是警方认为有罪的人的数据库,或者在某些情况下,警方只是想逮捕的人。
另一方面,这也引发了伦理问题,即面部照片中的人是否同意将他们的图像用于此类目的。警察定期拍摄面部照片并公之于众,以此来羞辱那些被他们逮捕的人,而许多记者未经允许就转载了这些照片,这让他们名誉扫地。再说一次,如果一个人被定罪的话,面部照片是在他被定罪之前拍摄的。目前还不清楚他们中是否有人被判有罪,或者是否同意广泛传播他们的照片。
另一方面,哈希米和霍尔的非罪犯通用图像数据库并不一定描绘出 T2 没有被定罪的人。我们对此一无所知。事实上,除了统计学上的可能性之外,没有任何理由可以解释为什么面部照片组的人在普通数据库中没有他们的脸。
一项司法部的研究估计,美国三分之一的工作年龄成年人有被捕记录。从统计数据来看,很多“非罪犯”很有可能在他们一生中的某个时候被指控,有些被判有罪,尽管他们在实验中使用的照片会显示他们比照大头照时快乐得多。
这是一个惊人的疏忽。一个人不需要成为社会学家就能从数据中理解这个问题。人们只需要对什么是犯罪有一个最天真的定义。
尽管如此,哈希米和霍尔声称已经训练了一个模型,可以准确预测一个图像是来自面部照片组还是非面部照片组,准确率达到 97%。他们是怎么做到的?
他们论文中的一条评论指出了这两个数据集之间的许多差异,神经网络可以从中发现这些差异,而这些差异与犯罪或逮捕无关:
犯罪类别的所有图像来自 NIST 数据集,非犯罪类别的所有图像来自其他来源的五个数据集。
所有标记为罪犯的图像都是打印图像的照片,并且是用相同的照相机型号以受控的方式拍摄的,所有标记为非罪犯的图像都是由各种照相机拍摄的活人的照片。
所有标记为罪犯的图像都是(无损)PNG 格式,所有标记为非罪犯的图像都是(有损)JPG 格式。
所有标记为罪犯的图像开始都是灰度的;调查人员将所有标记为非犯罪的图像从彩色转换成灰度。
哈希米和霍尔注意到,“这种与面部结构无关的差异,虽然在大多数情况下可以忽略不计,但可能在训练分类器和帮助分类器区分这两个类别方面略有贡献。”
但即使在这里,他们也只是具体提到前两点(不同的来源),而不是最后两点。
这最后两点几乎肯定被神经网络检测到,并且很可能是 97%命中率的主要原因。我们可以在实践中证明这一点
重现结果

笔迹样本来自 MNIST 数据库,来源:维基百科
在与 Hashemi 和 Hall 相似的条件下建立一个神经网络并训练一个简单区分 jpg 和 png 的模型是非常容易的。
一个下午,我就这样做了,由此产生的 Jupyter 笔记本可以在这里找到。
从弗朗索瓦·乔莱(Franç ois Chollet)的《用 Python 进行深度学习》(Deep Learning with Python )一书中的一个样本项目开始,我能够建立一个神经网络来区分“犯罪”和“非犯罪”图像。
我没有使用面部照片,而是使用了通过 Keras Python 库检索的手写数字图像的 MNIST 数据库。
首先,我随机将每张图片标记为罪犯(0)或非罪犯(1),然后我训练一个模型来预测这种任意定义的犯罪行为。注意,每个图像都被赋予了犯罪标记,而不管图像的内容如何,也就是说,不管图像中显示的是什么数字。因此,一张照片中手写的“7”被标记为“罪犯”,而另一张照片中的“7”被标记为“非罪犯”这完全是任意和随机的,而且不知道笔迹是否来自有犯罪前科的人。
该模型成功地正确确定了我指定的“犯罪”和“非犯罪”的手写数字,只有大约 50%的时间,不比随机猜测或扔硬币好。这是我们所期望的,因为这些名称是任意的。
但是在我把我所有的“罪犯”图像转换成 PNG 和“非罪犯”图像转换成 JPG 之后,我训练的最终模型在 99%的时间里都成功了!
这是一个怪异而武断的实验吗?是的,但并不比试图从一个人的脸上发现犯罪更重要。事实上,我的实验的一个版本可以用来尝试从笔迹中发现犯罪行为。从监狱里的人身上提取笔迹样本,从没有犯罪记录的人身上提取样本,我们可以以同样的准确度重现上面的结果——只要“犯罪”样本是 png,而“非犯罪”样本是 jpg。当然,除了笔迹样本,我们也可以使用人脸。
换句话说,哈希米和霍尔构建的可能只不过是一个复杂的 PNG vs JPG 图像格式检测器。他们碰巧训练他们的人脸图像,而我碰巧训练我的手写数字图像。他们用卷积神经网络实现了 97%的准确率,用标准前馈神经网络实现了 89%的准确率——后者类似于我如何以 99%的准确率训练我的模型。
那么问题就不是为什么他们如此成功,而是为什么他们的模式表现如此糟糕。
抛开所有这些问题不谈,他们的实验及其概念本身仍然存在固有的种族问题。
例如,联邦调查局的统计数据显示在旧金山湾区,黑人被逮捕的可能性是白人的四倍。在许多其他大城市和大都市区也是如此。
然而,哈希米和霍尔指出,“由于我们的数据集很小,从低质量的面部图像中识别种族很困难,有时还带有主观性,因此没有对种族进行控制。”按照描述训练的模型可以很容易地将深色皮肤的人与犯罪联系起来,因为他们在面部照片数据集中的出现率不成比例地高,除此之外别无其他。
这只会反映刑事司法系统中现存的种族主义,并进一步助长种族主义,而不是告诉我们任何关于固有犯罪的事情。此类实验还强化了警察和陪审团在认为某人“看起来有罪”时通常会做出的种族主义假设
科学种族主义的回归

查尔斯·达尔文(左)是一名真正的科学家,凯撒·朗普罗索(右)是一名伪科学家。来源:维基共享和维基百科
这个实验可以追溯到 19 世纪和 20 世纪早期的科学种族主义。与其说它是科学的,不如说它是一种种族主义的形式,用声称基于达尔文进化论但实际上没有任何科学依据的虚假科学理论来证明。
这些理论证明了一些种族主义政策的合理性,包括对移民的限制和对非白人比例过高的穷人和其他“不受欢迎的人”的强制绝育。这项工作的大部分起源于美国,并成为希特勒和第三帝国的灵感。
在第二次世界大战的恐怖之后,这些在学术界有所耳闻的理论变得完全不可信。哈希米和霍尔似乎没有得到消息,而是把他们的工作放在切萨雷·龙勃罗梭的传统。
“这项研究是由隆布罗索的研究引发的,”他们在介绍中不加批判地指出,“该研究表明,罪犯可以通过他们的面部结构和情绪来识别。”
事实上,隆布罗索的作品未能展示这些东西,已经完全被抹黑了。已故的进化生物学家史蒂芬·杰·古尔德在他的经典著作《人类的错配》中用了一章的大部分时间来揭露隆布罗索的理论,并用基于隆布罗索自己扭曲的思维的文字来描述它:
罪犯是我们中间的进化倒退。祖先的细菌潜伏在我们的遗传中。在一些不幸的人身上,过去的事情又重现了。这些人天生就像正常的猿或野蛮人一样,但这种行为在我们的文明社会中被视为犯罪。幸运的是,我们可以识别天生的罪犯,因为他们具有解剖学上的特征。
根据 2014 年一篇连线文章:
隆布罗索采用了达尔文最近发表的进化论,并加入了一个可怕的转折,这个转折将会影响几十年。你很难找到他的论点的优点,即罪犯实际上表达了我们祖先的身体素质,使他们更接近猿类而不是人类的性情。或者看看伴随他的假设而来的种族主义旋风带来了什么好处。或者把有大耳垂的人描绘成天生的罪犯。
这些犯罪迹象包括他在非洲人和亚洲人身上发现的一些特征,但甚至在一些欧洲人身上发现缺失的耳垂和钩状鼻子也是犯罪的迹象。
哈希米和霍尔文章的基础根植于伪科学和科学种族主义,因此应该被拒绝。
人们不禁要问,什么样的同行评审过程会让这么多这样的问题出现在大数据杂志的一篇文章中。
然而,更令人担忧的是这种研究在学术界的未来,以及它对每天与已经存在偏见的刑事司法系统打交道的活生生的人可能造成的伤害。
人工智能-研究进化
疫情快照
趋势
人工智能(AI)已经出现指数级增长。人工智能领域的研究论文申请也紧随其后,arxiv.org 的研究论文申请超过 3 万篇。

疫情也影响了人工智能研究,这可以从最近几个月提交的论文数量下降中看出来

然而,以医疗保健为重点的研究在疫情期间出现了激增。

学科
人工智能研究这些年来已经变得非常多学科化,如下图所示。除了人工智能和机器学习的核心学科,计算机视觉研究多年来一直占据主导地位,包括图像和视频处理。神经计算、机器人、信号处理和语言等学科也有大量研究。

在疫情期间,其中一些地区继续占主导地位。这里有几个最重要的归档原则。

然而,在疫情期间,某些生物/医学学科出现了人工智能主导的研究热潮。围绕生物分子、组织和器官、分子网络、医学/生物物理学和基因组学的研究已经起步。

概念
多年来,CNN(卷积神经网络)、RNNs(递归神经网络)、GANs(生成对抗网络)和其他使用 GPU 的算法占据主导地位。

多年来的几大概念
在疫情期间,医学研究的成果集中在 X 射线、CT 扫描、脑电图、3D 图像分析和 RNA 聚焦方法上。用于查询期刊以更快获得答案或模式的问答系统也出现了热潮。可解释的人工智能(XAI)已经占据了优先地位,尤其是在医疗诊断方面。

疾病
这些年来,人工智能应用于的疾病也发生了变化。癌症研究是主要焦点。最近几个月,肺炎相关的研究有所增加。糖尿病仍然是多年来的一个主要关注领域。



未来
人工智能的核心学科继续出现热潮,一些概念也是如此,如使用 CNN、RNNs、强化学习和其他架构的算法。计算机视觉和模式识别以及视频、音频、语音信号处理趋势。然而,随着我们走向未来,一些领域正在获得更多的关注。人工智能在语言、加密和安全、人机交互以及网络和互联网架构方面值得关注。

似乎人工智能的研究正指向一种感知。安全了。健康。网络化。人类相连。口语和解释世界。
人工智能彻底改变了抗生素的发现——从青霉素到海星

麻省理工学院的研究人员通过训练深度神经网络发现了一种强大的抗生素。
每个人可能对青霉素都不陌生——据说这种抗生素在第二次世界大战期间挽救了 12-15%伤口感染的生命。自 1928 年被苏格兰科学家亚历山大·弗莱明发现以来,它已经帮助人类抗击细菌感染引起的疾病近 100 年了。无法估计它拯救了多少百万人的生命。
然而,已经在地球上存在了几十亿年的细菌足够聪明,在广泛使用青霉素后,通过产生耐药性来逃避这种攻击。除了耐药性感染的问题,青霉素并不是对所有的细菌都有效,可能会在大约 10%的人群中引起严重的过敏反应。因此,科学家们一直在集中开发用于治疗感染的其他抗生素,希望找到具有更广活性谱和更好耐受性和安全性的新型抗生素。
但是我们怎样才能发现新的抗生素呢?
传统方法
历史上,科学家大多筛选自然来源,如霉菌、土壤微生物和植物提取物,以确定具有抗生素特性的化学物质。随着合成化学的进步,抗生素发现的现代方法包括筛选文库,该文库可由数万至数十万种合成化合物组成,这些化合物基于具有已知抗菌作用的天然化学物质和支架的半合成衍生物。一般工作流程总结如下。

抗生素发现的常规方法
然而,正如一些麻省理工学院的研究人员在他们最近在生命科学最负盛名的期刊之一的《细胞》杂志上发表的文章中指出的那样,传统方法存在一些明显的缺点,阻碍了新抗生素的突破性发现。
- 去重问题。去复制是一个消除之前已经研究过的活性物质的过程。从这些化学库中发现抗生素的不同筛选揭示了相同的分子。
- 更多的化学物质,更多的失败。自 20 世纪 80 年代实施以来,高通量筛选合成工程产生的数百万分子的化学库并未产生任何新的临床抗生素。这些库中的分子不仅化学多样性有限,而且进行这些筛选的成本也高得惊人。
人工智能方法
鉴于传统方法的这些缺点,麻省理工学院的研究人员利用人工智能(AI)的巨大进步,发现了具有潜在临床适用性的新抗生素。下图显示了这种人工智能方法是如何工作的。

抗生素发现的人工智能方法
具体来说,这些研究人员首先建立了一套训练分子,能够抑制一种常见细菌大肠杆菌的生长。他们通过指定分子特征,优化超参数和集成来增强他们的模型,这导致了通过迭代模型重新训练的最终深度神经网络。与传统方法相比,这种人工智能方法允许研究人员分析性地筛选超过 1 亿种化学物质,其中许多化学物质的分子结构与已知的抗生素不同。被筛选的化学物质的数量大约是常规方法的 100 倍,常规方法在如此大的规模下要昂贵得多。
利用这个模型,这些研究人员能够在药物再利用中心发现一种最初称为 SU3327 的激酶抑制剂,他们将其重命名为 halicin。他们发现,halicin 在小鼠中表现出广谱(即杀死多种细菌)抗生素活性,这表明它可能是一种具有潜在临床适用性的有前途的候选药物。从 ZINC15 数据库中,研究人员确定了 23 种候选化学物质,其中 8 种具有抗菌活性,其中两种特别强。
结束语
我们的生活依赖于抗生素,特别是当许多种细菌已经进化到具有抗生素抗性菌株的时候。因此,发现新的抗生素来进一步增加我们的抗生素库是至关重要的。这种人工智能方法彻底改变了抗生素的发现,使科学家能够以非常高的预测精度快速筛选更多的化学物质。像 Halicin 一样,使用这种人工智能方法将会发现更多的抗生素。
我相信,用不了多久,我们就会看到,Halicin 和其他人工合成的抗生素可以用于临床。
参考
人工智能安全、人工智能伦理和 AGI 辩论
苹果 | 谷歌 | SPOTIFY | 其他
Alayna Kennedy 在 TDS 播客

编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:
我们大多数人认为,影响我们的决定应该通过推理过程做出,将我们信任的数据与我们认为可以接受的逻辑结合起来。
只要人类在做这些决定,我们就可以探究这个推理,看看我们是否同意它。例如,我们可以问为什么我们被拒绝银行贷款,或者为什么法官宣布了一个特别的判决。
但是今天,机器学习正在自动化处理越来越多的这些重要决策。我们的生活越来越多地被我们无法询问或理解的决策过程所支配。更糟糕的是,机器学习算法可能会出现偏差或犯下严重错误,因此由算法运行的世界有可能成为反乌托邦式的黑箱统治,这可能比我们今天拥有的最不完美的人类设计的系统还要糟糕。
这就是为什么人工智能伦理和人工智能安全近年来吸引了如此多的关注,也是为什么我非常兴奋地与 IBM 的数据科学家 Alayna Kennedy 交谈,她的工作专注于机器学习的伦理,以及与基于 ML 的决策相关的风险。Alayna 曾为美国政府人工智能工作的主要参与者提供咨询,并通过之前在神经网络建模和欺诈检测方面的工作,拥有在行业中应用机器学习的专业知识。
以下是我从对话中获得的一些最大收获:
- 机器学习模型通常带有少数“标准”损失函数,每个人都同意这些函数“工作得很好”(例如,准确性、AUC 分数、分类交叉熵等)。不幸的是,我们已经确定了这些标准指标的事实可能会诱使我们停止批判性地思考优化了什么。有时,具有最佳准确性或最佳 F1 分数的模型只能通过牺牲我们应该关心的其他事情来达到这种性能水平。我们倾向于自动驾驶并接受“标准”度量,因为它们是标准的,这可能导致危险的结果。
- 人工智能伦理面临的最大挑战之一是,我们甚至还没有接近制定出人类伦理。这意味着我们不得不将我们甚至无法达成一致的规则硬编码到我们甚至无法审计其推理的模型中。
- 尽管在关键的伦理问题上缺乏广泛的共识,但许多国家的政府已经制定了非常一致的伦理框架。
- 如今,人工智能安全的一个不太受重视的领域是人工智能失控的风险;我们对人工智能安全的大部分关注都指向更直接、更实际的问题。Alayna 和我不同意这是否是一件好事。你在这个问题上的立场取决于你认为 AGI 在近期或中期发展的可能性有多大(我认为这种可能性令人不安,但 Alayna 不同意)。
你可以在这里的推特上关注阿莱娜,也可以在这里的推特上关注我。
我们正在寻找能与我们的观众分享有价值的东西的客人。如果你碰巧知道谁是合适的人选,请在这里告诉我们:【publication@towardsdatascience.com】T4。
人工智能、传感器和机器人

贝洛奥里藏特,MG,巴西,照片由— @danielmonteirox 拍摄
从感知到机器和行动的意义
本文简要介绍了人工智能(AI)、传感器和机器人之间的关系。它并不意味着全面,而是探索基本概念。
许多类似人类的操作可能需要某种程度的人工智能或机器学习来以所需的方式操作。然而,许多机器人只为一个设定的任务编程,并给出一些不同的可能性。
然而,要帮助机器理解其空间环境——就感知、语音识别或学习而言,这可以通过感官输入来实现。
我之前讨论过摄像头,但它也可以是麦克风、无线信号等等。
机器必须识别一组人类行为指示,或者从它所处的环境中获取信息来决定行动。是热还是冷,是人还是机器,是车还是人,等等。识别对象是一个方面,还有一个方面是理解哪组事件应该触发给定的动作。
这三者如果分开,可能有不同的用途。人工智能可以被编程,机器人学涉及与物理相关的广泛方面。
你可以看到 OpenAI 团队训练的机器人手几乎不可思议的动作。
OpenAI 然后训练了一个神经网络,通过使用强化学习在模拟中解决魔方。域 随机化使仅在模拟中训练的网络转移到真实的机器人。这种自动领域随机化 (ADR),在模拟中不断产生越来越困难的环境。
他们专注于“机器要掌握”的挑战性问题。
- 感知。
- 灵巧的操作。
除此之外,他们还提到了元学习的概念。
“我们相信元学习,或者说学会学习,是构建通用系统的一个重要前提,因为它能使系统快速适应环境中不断变化的条件。”
机器人和人工智能服务于不同的目的。
然而,当需要复杂的操纵时,这些场在这些类型的环境中更接近。
机器人学涉及建造机器人,而人工智能处理编程智能或使计算机像人一样工作。
“机器人学是信息工程、计算机工程、计算机科学、机械工程、电子工程等工程和研究领域的交叉学科。机器人学涉及机器人的设计、建造、操作和使用。”
在某种程度上,目标是开发能够代替人类和复制人类行为的机器。
然而,机器人需要电机和传感器来激活和执行基本操作。
传感器已经变得非常便宜,而且更容易集成到不同的系统中,无论是工业规模的还是私人的。
因此,随着廉价传感器的不断增加以及结合先进软件的可能性,已经产生了有趣的结果。另一个例子是波士顿动力公司,他们 2012-2019 年的精彩片段展示了该领域正在取得的惊人进展。
他们的现货模式是最近推出的,一直很受欢迎。
这种形式的感官智能似乎已经足够了,但据说我们需要更多的这种类型的机器人在我们的家中操作。
我们仍然让吸尘器进入我们的家。
虽然还处于早期阶段,但也可能有其他设备。
显然,在冠状病毒封锁期间,对健康机器人的需求激增:
健身追踪设备正在销售一空,家庭健身课程从未如此受欢迎,机器人技术人员也在…
www.japantimes.co.jp](https://www.japantimes.co.jp/news/2020/04/02/business/tech/health-gadgets-corona/#.Xo4-WNMzbUo)
除此之外,机器人越来越多地用于远程医疗。
[## 美国能从中国使用机器人和远程医疗抗击冠状病毒中学到什么
今年 1 月,一名感染新型冠状病毒的乘客登上钻石公主号游轮后,病毒…
www.cnbc.com](https://www.cnbc.com/2020/03/18/how-china-is-using-robots-and-telemedicine-to-combat-the-coronavirus.html)
在某种程度上,也有机器人和无人机被用来帮助对抗冠状病毒传播的奇怪战斗。
随着冠状病毒(新冠肺炎)从中国传播到其他国家,机器人和无人机被部署来提供关键的…
www.forbes.com](https://www.forbes.com/sites/bernardmarr/2020/03/18/how-robots-and-drones-are-helping-to-fight-coronavirus/#7de5eb972a12)
一个名为 TerraHawk 的博客用一个插图描述了它,鉴于上面所讨论的内容,我发现这个插图很有帮助。

图片由 Terrahawk 软件提供
或者说,理解是人们赋予集体经历意义的过程。它被定义为“正在进行的合理图像的回溯开发,使人们正在做的事情合理化。"
通过这种方式,机器被编程来尝试理解环境以采取适当的行动。
这里是#500daysofAI,您正在阅读的是第 310 篇文章。500 天来,我每天都在写一篇关于或与人工智能相关的新文章。我 300-400 天的重点是关于人工智能、硬件和气候危机。
AI 不应该留下结构化数据!
人工智能如何解决臭名昭著的数据清理和准备问题
用于自动化结构化数据准备的可扩展预测引擎 | Ihab 易勒雅斯
从自然语言理解和自动知识库构建到图像和视频的分类和生成,AI 和深度学习在处理非结构化数据方面一直大放异彩。然而,被困在产品存储库、交易日志、ERP 和 CRM 系统等业务应用程序中的结构化数据正被抛在后面!表格数据仍由老一代数据科学技术处理,如基于规则的系统或决策树。这些方法使用手工制作的功能,维护起来很繁琐,并且需要大量手动标记的数据。尽管人工智能的最新进展允许从非结构化数据中挖掘巨大价值,但如果不同样关注结构化数据在推动业务、收入、健康、安全甚至治理方面的价值,那将是失职。
与非结构化数据相比,结构化数据的主要挑战之一是消费应用程序对数据质量的高度敏感性。我们可能仍然可以观看分辨率不完美的视频,或者在稍微模糊的图像中识别物体。然而,在大型企业或制药公司中,描述产品的大小、价格和数量属性的错误可能会带来灾难性的后果,使数据质量成为释放结构化数据资产价值的障碍。虽然数据管理界花了几十年时间试图解决这个问题,但进展甚微。这主要是由于问题的复杂性,基于规则和逻辑的系统处理问题的严重局限性,以及试图让人类参与数据清理和准备周期的高昂成本。现在,很明显,只有很少或没有人工交互的自动解决方案才是解决这个问题的唯一可行和可扩展的解决方案。
这就是为什么该问题适合于一种机器学习解决方案,它能够捕捉表征企业数据的不同上下文,并从大型数据集模型中学习,这些数据集模型可以预测数据质量,甚至建议数据修复以提高数据质量。用于数据准备和清理的 ML 解决方案将解决结构化数据的长期问题:
●它可以组合所有信号和上下文,包括业务规则、约束(如功能依赖和键)以及数据的统计属性;
●它避免了规则爆炸以覆盖边缘情况。在许多情况下,管理这些规则可能比管理他们试图清理的嘈杂数据更具挑战性,也更昂贵;最后,
●它可以传达一种“信心”的概念,所提供的预测将由正确的质量保证流程使用,或者有助于明智地让人类仅参与“困难”情况的处理。
然而,由于这种数据的本质(稀疏性、异构性以及丰富的语义和领域知识),构建 ML 解决方案并不明显。从积极的方面来看,诸如模式(列名、类型、域和各种完整性约束)之类的工件编码了关于语义和各种数据片段之间可能的交互的重要信息;我们不能让两个人住在同一个邮政编码但在两个不同的城市和项目的总预算不能超过计划的费用是可以明确提供的示例约束。这种“结构”使得数据的价值超出了机器学习模型可以挖掘和利用的统计属性。
另一方面,结构化数据可能是异构的,结合了来自不同领域的信息,如文本、分类、数字甚至图像数据。也可以很稀疏。假设一个表有 100 列,每一列从 10-1000 个可能值(例如,制造商的类型、大小、价格等)的域中取值,还有几百万行描述企业的产品。可以想象可能组合的空间有多“空”,只有一小部分组合是有效的。在没有任何结构、领域知识和约束的情况下,很难了解这些数据是如何生成的,或者有多准确。因此,我们看到了构建用于清理和准备结构化数据的可伸缩 ML 解决方案的三个主要挑战:
●背景知识应如何表示为模型输入,以帮助解决数据稀疏性和异构性问题?例如,在预测某一列中的值时,我们如何将关键约束、函数依赖、拒绝约束和其他复杂的完整性逻辑传达给 ML 模型以供考虑?
●如何从有限(或没有)的训练数据和肮脏的观察中学习?以“错误检测”模型为例,该模型应该发现各种错误,包括打字错误、缺少值、不正确的值、矛盾的事实、移位的数据等。用非常有限的可用错误示例和可用数据中存在的这些错误来训练这样的模型是一个需要克服的挑战
●如何扩展到数百万个随机变量?将问题直接建模为所有相互作用的数据之间的大规模联合可能性分布将会失败!
我们建立了 inductiv,这是一个针对结构化数据的人工智能平台,专门用于建立描述数据如何产生以及如何被“污染”的模型。然后,这些模型被用于各种服务,例如错误检测、预测缺失值的错误校正、使用额外的列进行丰富以及融合数据片段。Inductiv 建立在学术开源项目 holo clean(www . holo clean . io)的基础上,该项目是我们在 2017 年由滑铁卢大学、威斯康星大学麦迪逊分校和斯坦福大学合作启动的。
作为人工智能问题的数据清洗
HoloClean 采用了众所周知的噪音通道模型来解释数据是如何产生的,又是如何被“污染”的。完整的研究论文可以在这里找到。然后,HoloClean 利用所有已知的领域知识(例如规则)、数据中的统计信息以及可用的可信来源来构建复杂的数据生成和错误模型。然后,使用这些模型来发现错误,并建议最有可能的值来进行修复。

图 1:根据一个生成过程,数据是干净的,我们观察的是被污染的版本。建模和参数化这些过程允许我们将清洗表示为推理问题
虽然该模型通过将清理和检测公式化为推理问题来提供帮助,但是提供具有足够表达能力的模型的可扩展解决方案是真正的挑战。
构建错误检测解决方案
在我们的论文中,我们讨论了如何使用很少的例子来检测错误,并解决了之前提到的一些挑战:
● 车型。这些属性对应于描述控制数据集的分布的属性级、元组级和数据集级特征。图 2 中描述的模型学习捕获这些多级特征的表示层,以学习二进制错误检测分类器。
● 数据不平衡。 由于错误是罕见的,并且以不同的类型出现,当面对不平衡数据集时,ML 算法往往产生不令人满意的分类器。少数类的特征被当作噪音,常常被忽略。因此,与多数阶级相比,少数阶级被错误分类的可能性很高。提出的模型的一部分是一个“数据扩充”过程(图 3 ),它根据一个已知的错误生成策略制造许多“假”错误。使用几个错误示例来学习策略参数。虽然有限数量的示例不足以训练错误检测分类器,但是它们足以学习可能错误的分布。

图 2:具有多级特性的错误检测模型

图 3:生成错误示例的策略用于解决训练数据类不平衡的问题
inductiv 引擎:面向结构化数据的现代人工智能
人们可以很快意识到,诸如准备、清理、错误检测和缺失值插补之类的数据问题都是可扩展的统一推理机的应用,该推理机能够模拟“结构化”数据是如何生成的以及错误是如何引入的。更重要的是,由于我们在这篇文章和附带的谈话中提到的各种原因,这个核心需要纳入现代机器学习原则,例如:
●数据扩充和数据编程,用于生成培训数据
●学习目标列/值建模中涉及的各种上下文的表示,例如学习异构数据类型的嵌入空间
●自我监督,尽可能利用所有数据,使用一些技术,如使用其他值重建一些观察数据值
●合并领域知识和规则的方法,用于扩展表示,以馈入表达模型
●针对数据分区和学习本地模型的系统风格优化,允许可扩展部署和容纳具有多种数据分布的数据集
inductiv 引擎将我们之前的所有成果整合在一个统一的 AI 核心中。该引擎生成的预测可由各种数据准备服务使用。图 4 描绘了覆盖前述原则的核心的这些主要组件,包括基于注意力的上下文表示机制、分布式学习、数据切片和具有多任务学习的自我监督,以处理不同的数据类型(例如,数字数据的回归和分类数据的分类)。在我们的 MLSys 2020 论文中,我们提出了一种基于注意力的学习架构,用于混合类型结构化数据中的缺失值插补(图 5)。

图 Inductiv 统一推理引擎中的核心组件

图 5:具有基于注意力的上下文表示和多任务学习的示例架构
结论
当今重要数据的很大一部分是结构化的,但它存在严重的质量问题,损害了其价值。现代人工智能原则帮助我们将这个臭名昭著的质量问题视为一个统一的预测任务,围绕规模、异构性、稀疏性以及整合已知的语义和领域知识提出了一系列新的挑战。我们在构建第一个用于结构化数据的可扩展人工智能 inductiv 引擎时解决了这些挑战。

肖恩·林在 Unsplash 上的照片
人工智能加速药物研发以对抗新冠肺炎
深入了解艾在新冠肺炎治疗和药物发现竞赛中的作用,以及 TCS 的第一手研究和实验

这种名为“新型冠状病毒”的病毒是全球性疫情新冠肺炎的源头,它已经严重影响了几个国家的健康和经济。多项研究正在进行中,采用不同的方法设计针对新型冠状病毒潜在靶蛋白的新疗法。冠状病毒的一个被充分研究的蛋白靶标是胰凝乳蛋白酶样(3CL)蛋白酶,其负责病毒多蛋白的翻译后修饰,这对其在宿主中的生存和复制至关重要。有各种正在进行的项目来寻找针对新型冠状病毒的 3CL 蛋白酶的抑制剂。
最近的研究证明了人工智能(AI)技术在理解已知化学空间和生成新的小分子方面的效率。这些小分子必须满足几个物理化学性质才能用作潜在的药物分子。随着人工智能方法的出现,有可能设计出具有所需药物性质的新型小分子。在塔塔咨询服务公司(TCS),我们采用了基于深度神经网络的生成和预测模型来从头设计能够抑制 3CL 蛋白酶的小分子。过滤产生的小分子,并针对新型冠状病毒的 3CL 蛋白酶结构的结合位点进行筛选。基于筛选结果和进一步的分析,我们已经确定了 31 个潜在的化合物作为进一步合成和抗新型冠状病毒测试的理想候选物。
人工智能驱动的药物研发革命
发现一种新药需要十年或更长时间,而且成功率很低。数据监管和管理的进步推动了人工智能驱动的药物发现革命的出现。
基于人工智能的方法正在成为探索巨大化学空间的有前途的工具,这些空间可用于对类似药物的分子进行采样。人工智能模型能够学习基于现有药物的特征表示,可用于探索化学空间,以寻找更多类似药物的分子。这为药物设计界提供了一盏机会的明灯,以克服包括全球抗生素耐药性危机在内的许多挑战。最重要的是,基于人工智能的方法可以将药物发现过程的初始阶段从几年缩短到几天。
算法方面的 TCS 能力
在这项研究中,我们利用我们内部基于深度神经网络的生成和预测模型来设计新的药物样小分子(新的化学实体或 NCEs)。我们的内部模型和算法已经在多种药物设计任务中得到验证,可以根据特定的目标蛋白质定制化合物。这些经过验证、预训练的最新模型被用于产生能够抑制新型冠状病毒 3CL 蛋白酶的新型小分子,利用了高级训练技术,如转移学习和正则化强化学习。
数据集收集和预处理概述
ChEMBL 是一个公共数据库,保存着最全面的类药物小分子集合。生成模型最初是在 ChEMBL 数据库中约 160 万个药物样分子的数据集上训练的。分子以简化的分子输入行输入系统(SMILES)格式表示,这将使模型能够学习必要的特征来设计新的药物样小分子。
训练深度学习模型
预处理的 SMILES 数据集用于训练基于递归神经网络(RNN)的生成模型。学习 SMILES 语法并复制它以生成新的小分子的问题被视为一个分类问题。整个微笑字符串被视为一个时间序列,其中每个位置或符号被视为一个时间点。微笑词汇中的不同符号被认为是分类的类别。在给定的时间点,在给定时间序列中先前符号的类别分布的情况下,生成模型被训练来预测下一个符号的类别。因此,该模型在时间序列的每个时间点学习各种类的概率分布。这个问题是这样的,类似于自然语言处理(NLP)问题,多年来已经为其开发了复杂的人工智能模型和架构。
我们训练过的生成模型具有 96.6%的最先进的准确性,这是基于从模型中推断的药物样分子的化学和合成可行性计算的。这种能够探索化学空间的通用模型充当了我们的先验模型,该模型进一步适用于使用迁移学习生成特定于感兴趣的目标的小分子。为了使模型偏向于集中于新型冠状病毒的 3CL 蛋白酶,从 ChEMBL 数据库中人工筛选了蛋白酶抑制剂分子的数据集。使用 2515 个蛋白酶抑制剂分子的数据集,使用迁移学习来重新训练生成模型。在迁移学习过程中,生成模型偏向于关注化学空间的较小子集。此外,正则化强化学习用于调节生成模型以产生具有优化的物理化学性质的分子(图 1)。

图 1 :用于产生靶向新型冠状病毒 3CL 蛋白酶的新化合物的方法。
筛选潜在的抗新型冠状病毒药物样分子
训练的生成模型用于从学习的化学空间采样 50,000 个小分子。在去除与 ChEMBL 数据库相同的重复和分子后,剩余数据集由 42,484 个分子组成。这些分子经过严格的物理化学性质筛选,包括药物相似性、辛醇-水分配系数(logP)、氢键供体和受体计数、分子量、生物活性和合成可达性,最终得到一组 3,960 个分子。基于这些分子对新型冠状病毒 3CL 蛋白酶的亲和力,进一步过滤这些分子。经过虚拟筛选,共获得 1,333 个可作为潜在抑制剂的小分子。
我们还观察到,生殖模型可以产生类似于 HIV 蛋白酶抑制剂的小分子,但与新型冠状病毒 3CL 蛋白酶的结合更好。一整套有希望的小分子可以在这里找到,这样任何人都可以在这个需要的时候测试这些分子对抗新型冠状病毒。
新冠肺炎药物设计研究的其他基于人工智能的应用
一些公司和初创公司已经以创新的方式转变了他们的研究目标,利用人工智能加速寻找治疗新冠肺炎的方法。欧洲以人工智能为中心的初创公司 Molecule.one 发布了其专利合成规划平台,供科学界免费使用,旨在帮助研究人员快速合成和测试潜在的候选分子来对抗新冠肺炎。IBM 已将其人工智能生成框架应用于三个新冠肺炎目标,并生成了 3000 个新分子。这些分子已经在知识共享许可(CCL)下发布给科学界用于合成、测试和优化。总部位于香港的制药研究公司 InSilico Medicine 发布了一份 97 种候选小分子的名单,这些小分子旨在抑制新型冠状病毒的 3CL 蛋白酶。已经开发了几个基于人工智能的快速虚拟筛选模型,并对新冠肺炎进行了测试,现有的公共和商业虚拟筛选化合物库作为主要数据库。从本质上说,几个研究方向已经以前所未有的速度结合了基于人工智能的模型,为新冠肺炎提出了潜在的治疗方法。
大多数“AI”创业公司都是数据创业公司
也就是说,利用独特的数据集驾驭深度学习的浪潮可能会非常有利可图。

人工智能领域一些最热门的名字,或者我应该只说数据科学?
数据让最大的科技公司变得如此有价值。一个很好的估计是谷歌比你的父母更了解你的偏好。脸书 让它最活跃的用户每年多赚 26 美元 。这都是因为在网上有最好的数据——他们知道你的位置、你的消费习惯和你的顾虑。数据访问和控制正在推动技术发展。
放大
让我们看看 2019 年融资超过 1 亿美元的一些最有价值的“人工智能”创业公司。我对每一个都做了一些研究,我将把他们的应用程序重新构建为一个新的数据访问解决方案。就连这些公司自我标榜的东西也很吸引人。
1vacas a——假期租房管理 : 这个听起来根本不像 AI。这是 Airbnb,用于创建新的房屋租赁。他们掌握了所有的数据,知道应该建造什么样的房产。他们声称“人工智能驱动的工具使得在世界各地独特的度假屋提供这种一致的体验成为可能,”但实际上我猜测这是基本的回归和决策树。
2 轮回——工业物联网 : 他们应该说——联网传感器。这是一项伟大的业务,他们将向希望拓宽数据管道的人出售大量产品。智能相机提供丰富的数据,并可以连接到云。这一切都在故事的第一句话中,除了人工智能将如何帮助他们提供产品,“我们相信廉价的无线数据、人工智能和相机技术的爆炸已经使各种类型的组织更容易以在之前不可能的方式收集数据。”
3trip actions——公司差旅&费用管理 : 我收录这一篇是为了证明一些 AI 公司的新闻狂潮只是混乱。“关于”页面上没有提到人工智能,也没有提到自动化,只有“一个照顾业务和旅行者的旅行平台”
4thought spot——搜索& AI 驱动的分析: 这家公司获取企业数据(电子邮件、物流等),并为其发现趋势。人工智能驱动的洞察将提供如此好的服务,以至于“任何人都可以在几秒钟内找到隐藏在他们公司数据中的洞察”另一个例子,给我们你的数据,我们会做一些分析,并使你更好。我确信它对那些没有时间自己做分析的公司有用。最棒的是,中间人数据公司随着每一个额外的客户而变得更好。
5CloudMinds——为人们操作智能机器人 :这是一家创业公司,希望在 2025 年前将负担得起的机器人带入家庭。我同意——很高兴能早点找到它。座右铭:“我们可以通过使用云大脑让机器人像人一样聪明。”共享数据不一定是人工智能的前沿创新,但你明白了。数据再次出现,但在这种情况下是数据共享。
6icer tis—云中企业合同管理 : Icertis 是领先的云中合同生命周期管理提供商。不是打死马,但我认为这里获得的价值大多来自拥有最多的数据。
7spark cognition——Cognitive AI:这是第一个似乎可能在进行一些有影响力的人工智能研究的项目——“我们建立人工智能系统来推进我们社会最重要的利益。”咨询型人工智能公司将会变得很大。我很好奇,在他们开始占有市场份额之前,是否有咨询行业的大公司将他们吞并。
8Vectra AI——AI 驱动的威胁检测和响应平台 :没听说过这个,但 Vectra 是“应用 AI 检测和响应网络攻击的世界领导者”,据他们自己说。我猜这是一些很酷的时间序列回归和大量数据。这里可能有一些令人敬畏的机器学习,我会给他们信用。好极了。
9 规模——数据平台为 AI: 数据标注服务的最终实现。我见过很多大规模的人,他们看起来都很棒,我认可他们。他们把曾经是研究生的克星——数据管理,做得天衣无缝。这家公司将存在几十年(或者很快被收购)。
10 这里的说法是“打造最安全的 AI 驱动,”但我不是从他们网站上卖的。时间会证明一切。现在唯一一家做有影响力的人工智能的自动驾驶汽车公司是特斯拉——他们在数十亿英里的里程上进行端到端的学习。我相信一对夫妇会赶上的
考虑到他们得到的媒体都涉及计算机智能,我有点惊讶他们中几乎没有人是 AI-forward 。AI 会把眼睛带进来,当你在有用的数据上交付一个产品,没有人(尤其是投资人)会多想。大多数公司都有一个清晰的数据杠杆,其中一些公司有一个真正创新的问题空间。
我从这篇文章中找到了最近获得资助的创业公司。我不得不撤掉一些公司,因为它们不是智能创业公司,但它们是数字化的,正在掀起浪潮。
[## 2019 年筹集资金最多的 25 家人工智能创业公司
今年有 107 亿美元投资于人工智能初创公司的种子期、早期风险投资或晚期风险投资轮…
www.forbes.com](https://www.forbes.com/sites/louiscolumbus/2019/12/22/top-25-ai-startups-who-raised-the-most-money-in-2019/#783a7ed1229b) 
来源——作者以前的工作。
真正的人工智能创业公司正在到来
我们可以通过访问这些数据看到这些公司创造的财富。在未来十年,机器学习的创新将是有规律和有影响的。2010 年是大数据的出现,这是好事——我认为 2020 年将由谁拥有最好的人工智能来决定。最好的人工智能将获得最一致的观点,它将拥有最低的物流成本,等等。
过去十年中机器学习的突破和数据基础设施正在为 2020 年代奠定基础,届时将充满真正的人工智能杠杆独角兽。
我担心迫在眉睫的衰退会导致技术行业的聚集增加。经济学很简单,但是这些公司知道的越多,他们就越会重新连接我们的大脑来赚钱。
一个关于机器人和人工智能的博客,让它们对每个人都有益,以及即将到来的自动化浪潮…
robotic.substack.com](https://robotic.substack.com/)
垂直联邦学习和数据共享时代的人工智能策略
使用垂直联合学习创建与竞争对手的数据共享联盟

迈克·科诺诺夫在 Unsplash 上拍摄的照片
你可能知道,数据共享对于大规模机器学习(ML)来说是一个挑战。此外,缺乏数据通常是 ML 项目中的一个问题。联合学习试图为孤立和非结构化数据、数据缺乏、隐私、数据共享监管以及数据联盟激励模型等问题带来解决方案。
最近,我有机会与我们的一些竞争对手一起监督基于“数据共享联盟”的垂直联合学习的实施。
我们与竞争对手建立数据共享联盟的战略需求可以用两个原因来解释。第一,我们在很多项目中受限于自己的数据。其次,外国科技公司将很快需要满足欧盟关于人工智能和与较小竞争对手共享数据的新要求。
在这篇文章中,我将分享我在确定具体用例以及利用联合学习来使我们和我们的竞争对手在创建新的商业模型时,在不共享任何原始数据的情况下训练机器学习模型的经验。
今天的现实
大多数公司都采用相同的集中式机器学习方法。具体来说,开发精确模型的过程通常从从多个来源(运营数据、遗留系统、社交媒体、CRM、物联网数据等)收集尽可能多的数据开始,然后在收集的池化数据上开发机器学习模型。
这种方法包含几个挑战,削弱了人工智能系统的潜力。事实上,只有一小部分可能的可用数据目前是可访问的,因此限制了机器学习模型达到高精度。
如果我们能够提高在公司之间共享数据的能力,我们就可以开发新的用例,或者提高现有 ML 解决方案的准确性。当谈到这个问题时,你们中的一些人可能会想到开放数据,但是,这种解决方案通常质量有限、无结构或不一致。其他解决方案可能包括合成数据或数据增强技术...

限制数据共享的原因
在大多数情况下,组织更愿意严格控制他们的数据而不是与第三方合作或交易,更不是与竞争对手合作或交易。尽管他们可能偶尔会与第三方签订合同来帮助加速开发,但数据伙伴关系或联盟仍然非常罕见。
为什么我们需要更多的数据共享
人们往往关注组织如何利用自己的数据,而最大的机会在于合并多个数据集,包括内部和外部数据集。
例如,利用竞争对手数据的能力可能会改变游戏规则。事实上,使这些数据可用于特定目的可以为多个组织和最终用户释放价值。此外,在人工智能背景下,与竞争对手的共同努力合作可以改善内部机器学习模型。这就是为什么竞争对手之间的数据共享至关重要。

到目前为止,我们的目标是尝试想象我们不仅可以利用自己掌握的数据创造出什么。这种新方法要求我们设想新的业务模型、用例、合作伙伴和框架。
根据用例的不同,我们迫切需要更多的数据来训练我们的模型。例如,我目前在医疗保健领域工作。可想而知,这个特定行业的数据采集是极其困难的。因此,我们倾向于在严格治理下收集的小数据集上工作。使用垂直联合学习架构的数据共享联盟将对我们有很大帮助。
我们设想未来不同的公司将在不披露数据的情况下共同建立模型,并分享更准确的机器学习模型或新用例的好处,以改善内部流程或客户体验。我们的想法是不仅使用共享数据来改进现有的应用程序,而且“共同创造”应用程序,否则这是不可能的。
这种转变完全符合机器学习的本质。正如你们大多数人所知,机器学习领域本质上是一个协作领域。因此,看到一些大型科技公司最近在数据共享方面的转变,我并不感到惊讶。
我们还认为,FL 将改变价值链中的权力动态,减少对单个数据垄断的依赖,并为公司创造额外收入。没有使用他们的数据的公司可以有一个新的替代方法来产生收入。
最后,构建垂直联合学习的最佳策略取决于许多因素,包括:

联合学习
我不会过多地讨论细节,因为其他文章已经完美地涵盖了联邦学习的技术方面。如前所述,FL 的主要思想是你可以分散机器学习过程,这样你仍然可以尊重隐私,但获得统计能力和额外的数据。
纵向联合学习可以被看作是“一个 B2B 模型,其中多个组织加入一个联盟,建立和使用一个共享的 ML 模型。在构建模型的同时,确保没有本地数据离开任何站点,并根据业务需求维护模型性能。”FL 确保全面的数据保护,并对分享其知识的公司给予奖励。
事实上,该联盟可以将部分收入分配给数据所有者作为激励。实际上,为所有参与者/竞争者建立一个收入模型可能非常复杂。我们已经开发了一个专门为垂直联合学习开发的收益共享方案。
显然,所有参与者都从他们本地应用程序的全局模型中受益。此外,“联合学习也有利于跨境数据模型,在许多情况下,立法要求数据存储在特定的司法管辖区和跨机构的合作伙伴关系中。” 2
我希望一些初创公司和/或顾问成为 FL 领域的专家,并开发一个框架来帮助组织选择用例,确定合作伙伴,并与他们讨论数据协作的理想设置(收入模型,数据治理,...).
重点提一下纵向联邦学习 和联邦迁移学习的区别。第一个是指我们有许多重叠的实例,但重叠的特征很少。两个不同的公司(不在同一行业,例如,银行和零售商)可能或多或少拥有相同的客户,但每个公司都拥有不同的数据集/要素。在这种情况下,垂直联合学习合并特征以创建用于机器学习任务的更强大的特征空间,并使用同态加密来提供对数据隐私的保护。
f1 的一个已知问题是对手可以从设备发送的模型更新中推断出本地训练数据。为了缓解这个问题,我们依赖同态加密(HE)。他允许数据在为训练模型进行处理时保持加密。
同态加密:一种加密形式,允许对密文执行特定类型的计算,并获得加密结果,即对明文执行操作的结果的密文。( 3 )
尽管 FL 有这些积极因素,但仍存在许多挑战。例如,孤岛式非结构化数据、隐私、数据共享监管和使用 FL 的数据联盟激励模型。我还可以提到基于 FL 的解决方案的成熟和来自 C 级高管的内部支持…(与竞争对手共享敏感数据仍然是一些难以向经理解释的事情)
使用 FL 的用例
为了帮助你更好地理解联合学习的具体应用,我在下面选择了三个“成熟的用例”:
智慧零售
实际上,这三个数据特性可能会在三个不同的部门或公司之间进行拆分。
- 购买力可能与用户的银行储蓄有关
- 个人偏好可以来自社交媒体
- 可以在电子商店上收集产品信息
根据来自微众银行和香港大学的几位研究人员的说法,我们正面临两个问题。首先,这些不同组织之间的数据壁垒很难打破。因此,不能直接聚合数据来训练模型。其次,三方存储的数据通常是异构的,传统的 ML 模型无法直接作用于异构数据。
联邦学习和迁移学习为这些问题带来了解决方案。事实上,通过利用 FL 的特性,可以在不导出公司数据的情况下为三方构建 ML 模型,从而保护数据隐私和数据安全。同时,我们可以使用迁移学习来解决数据异构问题,并突破传统人工智能技术的限制。
金融 另一个有趣的用例与多方借贷的检测有关。当某些用户从一家银行借款以支付另一家银行的贷款时,就会发生这种情况。
根据来自微众银行( 5 )的相同研究人员的说法,为了在不暴露用户列表的情况下找到这些用户,银行可以使用垂直联合学习。事实上,我们可以利用联合学习的加密机制,在每一端加密用户列表,然后在联合中取加密列表的交集。
智能医疗保健 医疗保健是另一个受益于垂直联合学习的领域。医疗报告等数据是隐私和敏感的(理由充分!).在现实中,医疗数据集很难收集,只能在孤立的医疗机构和医院中找到。根据我的经验,我可以告诉你,数据源的不足和标签的缺乏往往意味着 ML 模型的弱性能(低精度,过拟合等。),尽管有数据增强技术。理想情况下,如果所有医疗机构和制药集团形成数据联盟并共享其数据以创建大型医疗数据集,则训练的 ML 模型的性能将得到显著提高。
我相信 FL 是大规模生产系统的一个很好的选择,但对于研究项目,我仍然对整体效率持怀疑态度(除了在医学领域)。联合学习并不适用于所有的机器学习项目。
这种方法的成功很大程度上取决于您的用例。最后,在无法看到数据的情况下调试 FL 系统的复杂性是不可低估的。
关于联合学习的更多信息,我推荐以下链接:
人工合成波
用 GANs 从 YouTube 生成合成波图像

使用经过合成波成像训练的 DCGAN 生成图像
G 世代对抗网络(GANs),或者像 Yann Lecun 喜欢叫它们的那样, 【自切片面包以来最酷的东西】简直就是现象级的。
我长久以来一直迷恋于这些神秘的网络,它们能够实现我只能称之为魔法的东西。
作为这些网络的忠实粉丝,我想创造一些有趣的东西。你们中的许多人可能对 synthwave 类型很熟悉。这是一部独特的怀旧 70 年代和 80 年代科幻电影,非常有趣。
Synthwave 也是我在工作或学习时最喜欢听的音乐类型之一,所以我经常被 YouTube 上这种类型简单迷人的视觉效果所吸引。
自然地,GANs 和 synthwave 看起来是一个很酷的组合。synthwave 从科幻中汲取了大量灵感,而 GANs 实际上也是科幻。
在本文中,我们将分解如何从 YouTube 中抓取图像数据,以及如何将这些数据输入并设置一个深度卷积 GAN (DCGAN)。
这段代码也适用于任何范围的 YouTube 视频。当然,图像的复杂性和您想要的结果都是代码可直接转移的重要因素。
刮削和预处理
首先当然是数据。幸运的是,YouTube 上有很多 synthwave 视频。在选择了一些 synthwave 可视视频之后,我们可以使用pytube库来下载它们。
视频下载后,我们使用opencv库从每个视频中提取数千帧,存储在本地以备训练时提取。
处理
一旦我们有了所有的图像文件,我们可以循环通过每一个,导入和下采样每一个图像…下采样的程度将取决于计算能力,以及你想从这个过程中得到什么。在我们的 GAN 中,每个像素都会增加我们网络的规模。
*
**
原始图像的 360p 分辨率(左)和该图像的二倍下采样(右)|照片由 Lorenzo Herrera 在 Unsplash 上拍摄*
单个 360 x 640 RGB 图像由360*640*3 = **691200**个值组成,通过因子两个的下采样给我们一个四倍的减少量180*320*3 = **172800**。这大大降低了复杂性,因此也降低了运行时间。
如果您的网络太大(这不一定是由于输入图像的大小,但可能是),您将收到Error: OOM when allocating tensor。
然后我们需要将数据格式化成 TensorFlow 可读的格式。
使用 TensorFlow 数据集对象,这很容易。我们首先混洗数据,这样我们就不会同时将同一组图像输入到鉴别器中。然后我们对数据进行批处理,这意味着在我们更新网络权重之前,网络将会看到batchsize个样本。
我见过使用 GANs 生成图像时,最常见的批量范围是 16 到 64。
还有建议使用鉴别器的[SGD](https://github.com/soumith/ganhacks) 优化功能,这实际上会在单个训练示例后更新权重。尽管如此,我们还是使用了Adam和一个batchsize = 64。
DCGAN
我们使用深度卷积 GAN 架构。Simplex Mundi tis专为最大化结果和最小化复杂性而设计。
与典型的卷积神经网络(CNN)或递归神经网络(RNN)设置不同,GANs 要求我们将 TensorFlow 设置到稍低的级别。
这意味着我们将把代码分成四个关键部分:
- 发电机设置 —包括架构设置、损耗计算和优化器。
- 鉴别器设置——包括同上。
- 步骤 —在训练、噪声生成、模型预测、损失和权重更新期间,我们对每一次迭代采取的过程。
- Fit —训练控制器功能,包括可视化和模型检查点保存。
模型架构本身就挺有意思的。DCGAN 几乎只使用 CNN(没有最大池,最小密集连接的 nn)。
我们将在接下来的章节中进行更深入的探讨,但简而言之——发生器和鉴别器是两个独立的、几乎相反的 CNN。
生成器生成图像,鉴别器识别假图像(由生成器生成)和真图像(我们从 YouTube 检索)。
通过竞争,我们产生了一个图像生成器。能够骗过 CNN(鉴别者)。
发电机
生成器存储在一个创造性地命名为Generator的类中。在这里,我们将有三种方法— dcgan、optimiser和loss。
我们的第一个方法,dcgan,包含模型设置。我们将构建这个来产生大小为 360 * 640 的 RGB 图像(一个640, 360, 3的数组形状)。
我们首先初始化一个 TensorFlow Sequential模型。在这之后,我们简单地使用add方法添加每个连续的层。有三个层段,输入Dense和Reshape,后面是两个Conv2DTranspose段。
输入部分采用我们的latent_units,它只是一个输入层的噪声,我们将其输入到发生器,并将其输入到一个密集连接的神经网络。然后,这些 NN 激活被整形以适合下面的转置卷积层。

泄漏激活功能
在每个 NN 层之后,我们包括一个BatchNormalization和LeakyReLU层。BatchNormalization确保模型权重正常化,从而降低渐变消失或爆炸的几率。LeakyReLU是我们的激活功能。
最后的Conv2DTranspose层产生我们生成的图像。我们在这里使用一个tanh激活函数,在开发 GANs 时,推荐使用而不是sigmoid。
我们的发电机优化器和损耗分别用optimiser和loss定义。发电机的损耗通过fake_preds——鉴频器的输出来计算。
在鉴别器错误地将所有假图像0预测为真实图像1的情况下,发电机损耗被最小化。因此我们在二元交叉熵计算中使用了tf.ones_like。
鉴别器
鉴别器与我们的生成器非常相似,但是我们没有使用Conv2DTranspose层,而是使用普通的Conv2D。我们还包括一个Dropout层,它赋予每个值在任一时刻被屏蔽的 50%的概率。帮助我们防止过度拟合并鼓励一般化。
我们使用相同的优化器和相似的损失函数。在这种情况下,当鉴别器成功地将真实图像识别为1并将虚假图像识别为0时,损失被最小化。
步骤
step和fit都包含在Train类中,我们用生成器G和鉴别器D模型对其进行初始化。
对于每个步骤/迭代,我们必须做几件事:
- 生成
noise—使用大小的正态分布batchsize, latent_units,在我们的例子中是64, 100。 - 通过处理
noise到G.model生成fake_images。 - 通过处理
real_images和fake_images到D.model进行预测。 - 计算
G_loss和D_loss—将real_output和fake_output输入到我们在每个类中定义的loss函数、G.loss和D.loss中。 - 计算
G和D梯度——使用每个模型的tf.GradientTape,我们输入模型损失和可训练变量。 - 最后,我们使用
opt.apply_gradients应用渐变更新。
在代码中,这看起来像:
请注意,self正在被使用,因为这是一个在Train类内部的方法。在该方法的最后,我们将发生器和鉴别器损耗的平均值添加到我们的history数据帧中,我们稍后将使用该数据帧来可视化损耗。
合适的
这是我们最后的主要方法,它作为我们刚刚讨论过的所有代码的控制器。
与以前的代码相比,这部分更容易掌握。首先,我们创建gen_noise作为我们用来生成可视化效果的唯一噪声轮廓。这不是在培训中使用的,它只是为了让我们直观地衡量发电机如何随着时间的推移而发展。
我们将gen_noise输入生成器G.model,它给我们一个生成的图像数组gen_image。这个数组被格式化,转换成 PIL 图像对象,然后保存到文件中。
用sns.lineplot显示发生器和鉴别器的损耗,然后保存到文件中。两个损失值也会打印到控制台。
最后,我们使用save_weights方法每 500 个时期保存一次模型权重。

生成的图像
虽然仍处于早期阶段,但看到那些从 GAN 生成的图像中出现的迈阿密复古太阳的第一张图像是一种惊人的体验。
这是一个正在进行的项目,有很大的改进空间。但是 gan 很有趣,对于任何考虑看一看它们的人,我强烈推荐它。
如果有什么不清楚的,随时问我。如果你有改进的建议,请告诉我!我将在下面的参考资料中留下涵盖所有 GAN 代码部分的资源链接。
感谢阅读!
参考
Aviv Elbag,生成式对抗网络(GANs)完整编码示例教程在 Tensorflow 2.0 ,YouTube
深度卷积生成对抗网络教程,TensorFlow
Soumith Chintala,如何训练一个 GAN?让 GANs 发挥作用的技巧和诀窍,GitHub

在 Matplotlib 中构建的 Synthwave 图
这个想法源于我做的一个早期项目,在那里我使用 Matplotlib 构建了你在上面看到的 Synthwave visual。如果你有兴趣了解这些,你可以在这里阅读:
* [## 用 Matplotlib 创建 Synthwave
正确使用 Matplotlib 创建复古的 Synthwave 视觉效果
towardsdatascience.com](/creating-synthwave-with-matplotlib-ea7c9be59760)*
艾:往引擎盖下看一眼。第 2 部分,用传统的方法创建一个两层的神经网络

图片来源:马太·亨利
在深入本系列这一部分的新内容之前,我们先快速回顾一下本系列第 1 部分中所涉及的内容,以便让后续读者耳目一新,并为新读者提供背景知识。如前所述,人工智能只是数学。为我们今天看到的所有人工智能功能提供动力的数学算法是神经网络。
神经网络有三种一般形式:
- 标准神经网络(通常用于二元分类和点估计或回归型问题)。
- 卷积神经网络(一般用于图像识别)。
- 递归神经网络(通常应用于涉及序列数据的问题,如文本和语音识别、理解或预测)。
今天我们将构建一个标准的两层神经网络(一个隐藏层,一个输出层)。数学将被解释并且 python 代码将被提供。这将使你不仅能准确理解标准神经网络的工作原理,还能让你自己构建它们。
首先,在打开每个步骤之前,让我们快速看一下涉及的步骤。请注意,我们将不涉及数据争论、清理或转换,因为这在数据集和应用程序之间可能有很大差异。也就是说,值得指出的是,标准化输入数据对于关系识别以及最小化计算成本非常重要。
步骤:
- 定义模型结构(如输入要素的数量)
- 初始化模型的参数
- 计算电流损耗(又名“正向传播”)
- 计算当前梯度(又名“反向传播”)
- 更新参数(梯度下降)
- 根据保留数据进行预测
步骤 3-5 在一个循环中执行,该循环取决于我们执行的迭代次数。我们执行的迭代次数是我们在步骤 1 中定义模型结构时做出的决定。下图说明了这一过程。

步骤 1:定义模型结构
定义您的模型结构包括您要构建的神经网络的类型,以及神经网络的超参数。超参数是层数、每层的节点数、每层中的激活函数、alpha(学习速率——这对梯度下降很重要,因为它决定了我们更新参数的速度)和迭代次数。这些超参数将影响我们的参数“w”和“b”(权重和偏差),它们是在网络的每个节点内计算的。权重和偏差又是应用于网络每个节点的激活函数的输入。
这部分既是艺术也是科学。在某个领域拥有丰富经验的数据科学家将获得直觉,知道哪组超参数最适合他们的业务问题,但这通常不能跨问题和领域转移,需要手动试错。你可以在谷歌上搜索大量的“经验法则”来给你一个关于起点的好主意,但这不会消除尝试不同组合来为你的业务问题提出最佳模型的需要。
需要记住的一点是,正如本系列第 1 部分中所讨论的,深度神经网络往往工作得更好,并且还可以减少网络中所需的节点总数。为了说明为什么深度神经网络通常会更好地工作,我们以面部识别为例。在建立一个执行面部识别的神经网络时,你需要几个层次来将任务分成易于管理的块。第一个隐藏层将关注更简单、更小的任务,例如检测边缘。第二个隐藏层将建立在这些边缘上,以检测面部部分(如鼻子、眼睛、嘴唇等。).第三层将把这些碎片放在一起以识别整张脸。最后,你的输出图层会告诉你这是不是你要找的脸(作为一个概率)。这就是为什么有时你的手机或电脑能识别你,有时却不能。如果算法以一定的概率确定实际上是你,该软件被编程为解锁你的设备。这个由网络输出的概率根据照明、你面对屏幕的角度、你是否戴着眼镜等等而变化。
也就是说,让我们开始定义我们的神经网络的结构。
在下面的代码中,我们将定义 3 个变量:
- n_x:输入层的大小
- n_h:隐藏层的大小(隐藏层中有多少个神经元——我们将设置为 4 个神经元)
- n_y:输出层的大小
def layer_sizes(X, Y):
"""
Arguments:
X -- input dataset of shape (input size, number of examples)
Y -- labels of shape (output size, number of examples)
Returns:
n_x -- the size of the input layer
n_h -- the size of the hidden layer
n_y -- the size of the output layer
"""
n_x = X.shape[0] # size of input layer
n_h = 4 #neurons in hidden layer
n_y = Y.shape[0] # size of output layer
return (n_x, n_h, n_y)
步骤 2:初始化模型参数
初始化我们的模型参数意味着初始化我们的参数“w”和“b ”,在我们开始迭代每个节点内的计算和优化过程以识别我们的输入数据和预测(输出)变量之间的真实关系之前,以某个值开始。
权重(“w”)将被初始化为非常小的随机值,而偏差(“b”)将被初始化为 0。我们希望权重值较小,以便它们开始时接近双曲正切函数或 sigmoid 函数的中心,这样可以加快学习速度。如果我们将它们初始化为较大的值,那么我们将在曲线斜率很小的函数尾部附近开始优化,这将会减慢我们随后的梯度下降(优化)。它们需要随机的原因是它们不完全相同。节点必须计算不同的函数,以便它们有用。点击此处查看 sigmoid、tanh、ReLU 和 Leaky ReLU 函数的对比。
从这些图像中,您可以看到,靠近双曲正切函数或 sigmoid 函数的尾部(由大值产生)意味着几乎没有斜率。用小的值初始化并不总是能消除这个问题,这也是 ReLU 函数能提高处理时间的原因之一。
让我们看一下代码:
def initialize_parameters(n_x, n_h, n_y):
"""
Argument:
n_x -- size of the input layer
n_h -- size of the hidden layer
n_y -- size of the output layer
Returns:
params -- python dictionary containing your parameters:
W1 -- weight matrix of shape (n_h, n_x)
b1 -- bias vector of shape (n_h, 1)
W2 -- weight matrix of shape (n_y, n_h)
b2 -- bias vector of shape (n_y, 1)
"""
np.random.seed(2) #set up a seed so that your output is consistent
W1 = np.random.randn(n_h,n_x)* 0.01
b1 = np.zeros((n_h,1))
W2 = np.random.randn(n_y,n_h) * 0.01
b2 = np.zeros((n_y,1))
assert (W1.shape == (n_h, n_x))
assert (b1.shape == (n_h, 1))
assert (W2.shape == (n_y, n_h))
assert (b2.shape == (n_y, 1))
parameters = {"W1": W1,
"b1": b1,
"W2": W2,
"b2": b2}
return parameters
请注意,断言语句是为了确保我们的权重和偏差矩阵是符合我们的神经网络规范的正确维度(本文不涉及细节)。
步骤 3:正向传播
前向传播是指我们在网络中从输入层移动到输出层,在此过程中计算每个节点中的几个重要值。在每个节点中,我们将执行以下计算:
- Z = w^T x + b (w 转置乘以 x + b)
- 并且计算激活函数 a = σ(Z)(在这个例子中使用 sigmoid 函数)
重要的是将其矢量化以加快处理速度,而不是在 Python 中专门作为循环来执行这一步骤。为此,我们将通过以下方式将 Z 计算为矢量:
- 把我们所有的 W 堆成一个矩阵(每个 W 是一个向量,但是我们转置它们,每个转置的向量变成一行。因此将它们堆叠在一起形成矩阵),
- 然后简单地把 b 向量加到 W 矩阵上。
就选择你的激活功能而言,这实际上取决于你试图解决的问题。但是,在隐藏层中,您可能希望选择一个加速处理的函数(例如 tanh 或 ReLU),而在输出层中,您需要选择一个与业务问题相关的激活函数。例如,如果您正在进行二进制分类,sigmoid 函数是有意义的,因为它会给出一个介于 0 和 1 之间的值,然后您只需设置您的接受阈值(任何> = 0.5 的值是否等于 1,或者是其他值?).
在查看代码之前,还有一点需要注意。在优化(梯度下降)部分,我们将需要能够计算我们的激活函数的导数(斜率)。因此,我们将在正向传播期间将这些值存储为“缓存”。
def forward_propagation(X, parameters):
"""
Argument:
X -- input data of size (n_x, m)
parameters -- python dictionary containing your parameters (output of initialization function)
Returns:
A2 -- The sigmoid output of the second activation
cache -- a dictionary containing "Z1", "A1", "Z2" and "A2"
"""
# Retrieve each parameter from the dictionary "parameters"
W1 = parameters["W1"]
b1 = parameters["b1"]
W2 = parameters["W2"]
b2 = parameters["b2"]
# Implement Forward Propagation to calculate A2 (probabilities)
Z1 = np.dot(W1,X) + b1
A1 = np.tanh(Z1)
Z2 = np.dot(W2,A1) + b2
A2 = sigmoid(Z2)
assert(A2.shape == (1, X.shape[1]))
cache = {"Z1": Z1,
"A1": A1,
"Z2": Z2,
"A2": A2}
return A2, cache
通过一次正向传播计算了权重、偏差和激活值之后,我们需要计算成本(所有训练示例的平均损失)。请记住,损失本质上是误差(预测值和真实值之间的差异)。
这是我们将通过向前和向后迭代来最小化的,通过迭代生成新值,计算成本,然后更新我们网络中的值,直到模型收敛或我们满足我们指定的迭代次数。
def compute_cost(A2, Y, parameters):
"""
Arguments:
A2 -- The sigmoid output of the second activation, of shape (1, number of examples)
Y -- "true" labels vector of shape (1, number of examples)
parameters -- python dictionary containing your parameters W1, b1, W2 and b2
Returns:
cost -- cross-entropy cost
"""
m = Y.shape[1] # number of example
# Compute the cross-entropy cost
logprobs = np.multiply(np.log(A2),Y) + np.multiply(np.log(1 - A2),1 - Y)
cost = - np.sum(logprobs) * (1 / m)
cost = float(np.squeeze(cost)) # makes sure cost is the dimension we expect.
assert(isinstance(cost, float))
return cost
步骤 4:反向传播
当进行反向传播时,我们需要能够计算激活函数的导数。对于任何给定的 Z 值,该函数将具有对应于该值的某个斜率。目标是使用梯度下降来寻找凸函数的全局最小值。点击阅读更多关于梯度下降的信息。
我们将计算以下导数(斜率):
- dZ[2] = A[2]-Y
- dW[2] = 1/m dZ[2] A[2]T
- db[2] = 1/m np.sum(dZ[2],axis =1,keepdims = True)
- dZ[1] = W[2]T dZ[2] * g[1]' (Z[1])
- dW[1] = 1/m dZ[1] XT
- db[1] = 1/m np.sum(dZ[1],axis =1,keepdims = True)
注意[2]指的是神经网络的第二层,而[1]指的是第一层(在这种情况下,这是我们的隐藏层),' T '代表转置。如你所见,我们从神经网络的末端开始,然后回到起点(因此有术语“反向传播”)。
def backward_propagation(parameters, cache, X, Y):
"""
Arguments:
parameters -- python dictionary containing our parameters
cache -- a dictionary containing "Z1", "A1", "Z2" and "A2".
X -- input data of shape (2, number of examples)
Y -- "true" labels vector of shape (1, number of examples)
Returns:
grads -- python dictionary containing your gradients with respect to different parameters
"""
m = X.shape[1]
# First, retrieve W1 and W2 from the dictionary "parameters".
W1 = parameters["W1"]
W2 = parameters["W2"]
# Retrieve also A1 and A2 from dictionary "cache".
A1 = cache["A1"]
A2 = cache["A2"]
# Backward propagation: calculate dW1, db1, dW2, db2\.
dZ2 = A2 - Y
dW2 = 1 / m *(np.dot(dZ2,A1.T))
db2 = 1 / m *(np.sum(dZ2,axis = 1,keepdims = True))
dZ1 = np.dot(W2.T,dZ2) * (1 - np.power(A1, 2))
dW1 = 1 / m *(np.dot(dZ1,X.T))
db1 = 1 / m *(np.sum(dZ1,axis = 1,keepdims = True))
grads = {"dW1": dW1,
"db1": db1,
"dW2": dW2,
"db2": db2}
return grads
我们现在需要使用刚刚计算的导数来更新 W1、b1、W2 和 b2 的值。正如在本系列的第 1 部分中提到的,这是深度学习的“学习”部分。这种更新是通过取向前传播中确定的值减去学习率(我们选择的超参数)乘以来自上面确定的当前迭代的线的梯度(或斜率)来完成的。
def update_parameters(parameters, grads, learning_rate = 1.2):
"""
Arguments:
parameters -- python dictionary containing your parameters
grads -- python dictionary containing your gradients
Returns:
parameters -- python dictionary containing your updated parameters
"""
# Retrieve each parameter from the dictionary "parameters"
W1 = parameters["W1"]
b1 = parameters["b1"]
W2 = parameters["W2"]
b2 = parameters["b2"]
# Retrieve each gradient from the dictionary "grads"
dW1 = grads["dW1"]
db1 = grads["db1"]
dW2 = grads["dW2"]
db2 = grads["db2"]
# Update rule for each parameter
W1 = W1 - learning_rate * dW1
b1 = b1 - learning_rate * db1
W2 = W2 - learning_rate * dW2
b2 = b2 - learning_rate * db2
parameters = {"W1": W1,
"b1": b1,
"W2": W2,
"b2": b2}
return parameters
在预测之前,让我们将这些函数放在一起,创建我们的标准神经网络模型。在本例中,我们将迭代次数设置为 10,000 次。
def nn_model(X, Y, n_h, num_iterations = 10000, print_cost=False):
"""
Arguments:
X -- dataset of shape (2, number of examples)
Y -- labels of shape (1, number of examples)
n_h -- size of the hidden layer
num_iterations -- Number of iterations in gradient descent loop
print_cost -- if True, print the cost every 1000 iterations
Returns:
parameters -- parameters learnt by the model. They can then be used to predict.
"""
np.random.seed(3)
n_x = layer_sizes(X, Y)[0]
n_y = layer_sizes(X, Y)[2]
# Initialize parameters
parameters = initialize_parameters(n_x,n_h,n_y)
W1 = parameters["W1"]
b1 = parameters["b1"]
w2 = parameters["W2"]
b2 = parameters["b2"]
# Loop (gradient descent)
for i in range(0, num_iterations):
# Forward propagation. Inputs: "X, parameters". Outputs: "A2, cache".
A2, cache = forward_propagation(X,parameters)
# Cost function. Inputs: "A2, Y, parameters". Outputs: "cost".
cost = compute_cost(A2, Y, parameters)
# Backpropagation. Inputs: "parameters, cache, X, Y". Outputs: "grads".
grads = backward_propagation(parameters, cache, X, Y)
# Gradient descent parameter update. Inputs: "parameters, grads". Outputs: "parameters".
parameters = update_parameters(parameters, grads)
# Print the cost every 1000 iterations
if print_cost and i % 1000 == 0:
print ("Cost after iteration %i: %f" %(i, cost))
return parameters
第六步:预测
为了对保留数据进行预测,您将运行优化模型的正向传播。在本例中,我们预测了一个二进制分类,其中输出图层中激活返回的任何大于 0.5 的值都被分类为 1,因此任何小于或等于 0.5 的值都被分类为 0。
def predict(parameters, X):
"""
Using the learned parameters, predicts a class for each example in X
Arguments:
parameters -- python dictionary containing your parameters
X -- input data of size (n_x, m)
Returns
predictions -- vector of predictions of our model (red: 0 / blue: 1)
"""
# Computes probabilities using forward propagation, and classifies to 0/1 using 0.5 as the threshold.
A2, cache = forward_propagation(X,parameters)
predictions = (A2 > 0.5)
return predictions
最后,您可以按如下方式检查神经网络的准确性:
predictions = predict(parameters, X)
print ('Accuracy: %d' % float((np.dot(Y,predictions.T) + np.dot(1-Y,1-predictions.T))/float(Y.size)*100) + '%')
结束语:
在上面的内容中,我们介绍了构建两层标准神经网络的理论、数学和代码(一个隐藏层,一个输出层)。我希望这有助于增强您对日常遇到的人工智能应用程序的理解,同时为您提供一个强有力的起点,为二进制分类问题构建您自己的人工智能应用程序。网上有大量很棒的内容,你可以更深入地探讨其中的许多话题。我个人从吴恩达在 Coursera 上的神经网络和深度学习课程中学到了所有这些,你可以在这里找到。
人工智能自学玩游戏
使用 Pygame 构建了一个简单的游戏,并应用 NEAT(增强拓扑的神经进化)算法来训练 AI。

这篇文章是关于教 AI 如何玩一个我用 pygame 库做的简单游戏。游戏是这样的,球应该继续在管子之间的缝隙中滚动,如果球碰到了任何一根管子,我们就输了。当一个球成功通过管道之间的缝隙时,分数将增加 1。
上面的 Gif 图像显示了神经网络如何一代又一代地改进的训练过程,并且可以使用下面的三个值在游戏窗口中看到进度状态。
- 分数:分数/成功穿越的管道数。
- 一族:算法正在学习的世代/突变数。
- 球:表示当前世代中存活的球数。
构建游戏界面的完整代码和相关文件都在我的 Git repo 里。
现在让我们使用整齐的(扩充拓扑的神经进化)来进行训练部分。NEAT 是一种创建人工神经网络的进化算法,该算法的详细描述是 这里的 。这里的基本思想是网络不依赖于固定的结构,NEAT 允许它通过遗传算法进化。因此,当需要完成手头的任务时,它通过添加节点、连接和层来自己构建最佳网络。
一旦我们准备好一个游戏,我们将下面的输入/参数输入到 NEAT 算法中,以创建一个完成任务的最佳神经网络,在我们的例子中,是将球滚动通过间隙。
我们通过一个 配置文件传递所有这些参数。
网络的输入: 告诉 NEAT 算法网络可以期望什么样的输入,我们需要什么样的输出。

- 由于这是一个简单的游戏,我已经将隐藏层的数量设置为 0,如果需要,我们可以尝试另一个数量。
- 我正在为网络传递 3 个输入。球在 Y 轴上的位置、球和顶部管道之间的距离以及球和底部管道之间的距离。
- Num_Output s:设置为 1,即输出单节点。基于输出节点的值,我们决定跳转或不跳转。
# we used tanh activation function so result will be between -1 & 1\. if over 0.5 jumpif output[0] > 0.5:
ball.jump()
激活功能 :

- 激活默认值:使用哪个激活函数来确定输出值,在本例中,我使用了 Tanh。我们可以使用其他激活函数,如 sigmoid/relu 等。
- Activation_mutate_rate :变异时选择其他激活函数的概率。
- 激活选项:突变/育种过程中随机使用的其他激活功能。
适应度参数 : 评价网/球像距离多好的方式。

- Fitness_criterion: 可以有最小值/最大值/平均值。这告诉了 NEAT 如何挑选最好的网/球。体能分最高的球是最好的。
- Fitness_threshold :停止训练前达到的最大体能分数。
- Pop_size: 任意值,我们可以随便玩。它表示每一代有多少个球。用 20 个成员/球开始零代,测试它们,选择最好的,繁殖/变异它们以产生下一代的 20 个球,并继续该过程。
- 灭绝时重置:如果这个评估为
True,当 a 中的所有物种(球)同时因停滞而灭绝时,会产生一个新的随机种群。
在 neat 中,我们将群体成员称为基因组/物种,一旦基因组的属性如上所述被设置,NEAT 开始通过创建球的群体来构建网络,我们将其设置为 20。每个球都与控制它的完全随机的神经网络相关联&每个网络都有自己的随机权重和偏好。所以我们测试了每一个神经网络,通过评估它们的适应性来看它们做得有多好。健康取决于我们玩什么任务/游戏,在这种情况下,球前进了多远。在游戏中,每通过一个管道,我们就给它的健康值加 1。
在第一代结束时,当所有的球都用完了,尼特看到他们中哪个表现最好。然后,它挑选上一代球/网络中的最佳球/网络(得分最高的两个或三个),对它们进行变异和繁殖,以创建一组新的种群。在这篇 论文 中详细解释了这些神经网络实际上是如何繁殖和变异的。
现在我们将拥有上一代最好物种/球的后代。所以我们希望这些下一代物种/球比上一代表现得更好。neat 实际上做的是,更新权重,随机添加/删除节点和连接,直到它找到一个最适合我们正在解决的问题的架构。它从一个简单的网络开始,必要时会变得复杂。我们需要继续这个过程,直到我们对表现满意为止。
经过几代人的慢慢学习和变得更好,它终于学会了一种前进而不碰壁的模式。在这种情况下,使用当前的参数集,在第四代中,AI 开始表现得更好,并达到了一个从未失败的点,正如我们在上面的 gif 图像中看到的那样。
一旦分数达到我们设置的健身阈值,那么我们可以通过使用 pickle 保存与该球相关联的神经网络来退出训练。然后用一个球和我们保存的最好的网络创建一个游戏。现在,它可以无缝地演奏,永远不会碰到管子。
感谢阅读,快乐学习。😃
人工智能&咨询的未来:数据科学家会成为顾问吗?
了解管理咨询公司如何通过创造新的商业模式来适应新的竞争对手,如谷歌、微软和初创公司…

在为一家领先的咨询公司开发人工智能部门工作后,我意识到大多数顾问一直告诉他们的客户投资人工智能,而他们自己的公司在跟上人工智能方面落后了...
在这篇文章中,我将分享我在为一家咨询公司建立内部 AI 技能、雇用数据科学家和开发与 AI 相关的新商业模式方面的经验。
我还将分享我对咨询公司的未来的看法,咨询公司可能会受到科技公司的威胁,数据科学家和顾问之间的界限模糊。
谷歌、微软能否接下麦肯锡、BCG、贝恩的班?
获取信息和更好的数据分析
顾问根据研究提供昂贵的有见地的建议和指导。然而,咨询服务付费的重要部分是数据分析和展示。顾问收集、清理、处理和解释来自不同组织部门的数据,这取决于他们的任务。
事实上,数据挑战确保了数据人机界面的必要性。然而,关键数据经常丢失或难以访问。这些问题造成了一种情况,即寻求关键战略问题的数据驱动答案的公司需要专家(顾问)来创建、组合、清理、分析和解释数据。
在越来越多的项目中,我们倾向于需要更多的数据科学家和更少的顾问。
顾问工作的这一特定方面可以通过机器学习(ML)算法在一定程度上实现自动化。ML 模型可以通过从数据中检测模式和推断规则来理解复杂的情况,这一过程即使对于最大和最聪明的咨询团队来说也是非常困难的。
预测 n 1: 决策者可以利用智能设备(Alexa…)询问类似这样的问题:“在我们的关键市场上,谁对我来说是最大的风险?”,“我们应该如何分配我们的资本来与亚马逊竞争?”或者“我应该如何重组我的董事会?”
在互联网时代,答案很便宜,人工智能可以降低整个咨询价值链的利润率。
我们可以说,人工智能时代的管理顾问不是在提供信息,也不是在进行分析。相反,他们正在理解大多数公司已经获得的信息和分析。根据我的观察,他们通常会将分散的信息连接起来,形成一个连贯的叙述或指南。
此外,越来越多的信息正在改变这种状况。今天,曾经被严密保护的信息已经被互联网商品化了。如今,真正的附加值是通过您已经掌握的数据创造新的竞争优势。
除了已经存在的初始分析活动的自动化,算法还可以获得更高附加值的部分,即洞察力整合和战略制定。
随着基于人工智能的解决方案的民主化,咨询公司面临的风险是,他们的客户为其付费的意愿大幅降低。有人可能会说,真正的价值来自数据科学家,而不是无法识别数据中隐藏模式的纯粹顾问。
面临风险的商业模式…
对于下面提到的元素,人工智能可能真的会威胁到大多数咨询公司的商业模式:

今天的情况
根据我的经验(取决于行业和业务问题),大多数咨询任务都与业务问题有关,这些问题可以通过聚类、排名和分类/预测算法来解决。
例如,客户流失预测非常普遍,回归模型被证明非常有效。而且,协同过滤或者排名问题非常普遍。如果业务问题很清楚,数据可用且相关,预期也很现实,那么数据科学家已经可以通过机器学习算法为许多业务问题提供解决方案。
人工智能提供商 vs 管理咨询公司
随着 AI 的日益民主化(无代码/低代码 AI 解决方案、创业公司等。),管理咨询公司将面临越来越多的竞争对手。

来自大型科技公司的竞争
它始于所有三大科技公司,它们提供预先训练的模型,企业客户可以用这些模型来构建人工智能系统。
事实上,有大量工具可以帮助主流公司构建任何东西,从推荐引擎到语音识别和翻译系统、客户服务机器人等等。在这些情况下,内部顾问和数据科学家团队会更适合。
出于几个原因,大型科技公司更适合为需要人工智能帮助的主流公司服务。你们中的一些人可能会想,这样的服务仍然需要大量的定制和技术工作来使它们变得有用……
事实上,科技公司已经在试图通过提供咨询服务来填补这一空白。谷歌开设了一个“高级解决方案实验室”,部分是咨询服务,部分是技术训练营。来自客户公司的整个团队可以获得机器学习技能,并与谷歌工程师一起构建定制系统。科技公司正在演变,不再仅仅关注技术基础设施,还关注战略和人才。
科技公司将越来越多地与管理咨询公司竞争,后者收取高额费用帮助客户应对技术中断。
在现实中,多面手知道自己很脆弱。根据不同的使用案例,许多客户向科技公司寻求建议,而科技公司本身就是人工智能的先驱用户。如果咨询公司不能有效地做出反应,更专业的提供商可能会向价值链上游移动,不仅成为数据/分析提供商,还会为整体业务战略提供建议。
来自创业公司的竞争
初创公司也对咨询公司构成了威胁。事实上,许多公司提供帮助清理和标记数据等服务,并承担大型科技公司尚未提供的特定任务。在某些情况下,数据科学家可以完美地为精确的业务问题带来答案,而不需要管理顾问。
对于大公司来说,外包大部分人工智能工作是有意义的。这些初创公司通常在使用机器学习的特定业务领域开发了咨询公司尚不具备的强大专业知识。这些初创公司通常会开发个性化的解决方案,这些解决方案与客户的业务相结合,并且可以持续使用,即使顾问离开后也是如此。
来自独立人工智能公司的竞争
另一个值得一提的新竞争来自独立的人工智能咨询公司。事实上,越来越多的公司开发了帮助公司集成、开发或扩展人工智能项目的服务。这些公司通常拥有规模优势(敏捷、价格等)。).
人工智能、SaaS 和新的商业模式
我相信,许多咨询公司已经在试图通过培训顾问、雇佣数据科学家、开发人工智能和 SaaS 产品以及创造新的商业模式来适应这种变化。
公司文化&培训首先从培训和公司文化说起。事实上,我认为现代管理顾问不能再依赖于顶尖学校的毕业生和某个特定领域的专家。所有顾问必须精通远程技术/数据。
新的数据能力显然,BCG 或麦肯锡等市场领导者已经在早期投资了具有机器学习经验的分析初创公司,或雇佣了许多数据科学家,并创建了新的数据驱动部门(例如 BCG Gamma)以为客户带来新的数据能力。
成为技术提供商咨询公司已经开始开发他们的专有软件(通常使用 SaaS 或 AIaaS 模型),因为许多客户有类似的需求(例如:定价策略),这些解决方案通常可以根据客户的需求进行定制。事实上,如果你已经与该公司合作过,并且完全了解业务问题,推广你的 SaaS 解决方案是很容易的… 独特解决方案的开发为咨询公司创造了新的收入来源。这种新的商业模式非常适合没钱投资自己的人工智能开发的客户。
的确,当诊断和推荐任务频繁出现在日常工作中时,客户会有更大的动力投资于软件提供商,因为“随需应变的大脑”消失了。此外,对利用实时数据的工具的依赖改变了咨询顾问的需求。
生态系统创建越来越多的咨询公司试图通过与特定机构、创业公司或其他与人工智能相关的组织合作,建立人工智能生态系统。目标是改善品牌形象,确立自己的领导地位,聘请技术专家并推广他们的解决方案。对于最先进的咨询公司来说,这将涉及创建一个拥有人工智能专业知识的“实验室”,或许还有一个孵化器。
与 AI 经济相关的新服务
我看到咨询公司对新兴的零工经济和在线培训进行了大量投资。
我的预测
我相信,基于技术的咨询解决方案将获得更大的市场,咨询行业的人才争夺战将比今天更加激烈。此外,我希望看到更多的数据科学家也成为顾问。
我还预计,由于人工智能的民主化和客户忠诚度的下降,竞争将变得更加激烈。客户希望根据他们的具体需求更容易购买咨询服务。
人工智能提供商将越来越多地与管理咨询公司竞争。
但是,我希望客户继续从使用管理咨询公司而不是供应商本身(例如,Google、AWS、SAP)中受益,因为管理咨询公司可以提供:
- 客观性
- 将人工智能转型与整体业务战略联系起来的能力,以及如何扩展人工智能项目的知识
- 关于业内其他公司如何因人工智能而转型的知识。
显然,咨询可能会变得不那么劳动密集型。我想在未来的 20 年里,我们将会看到以下事情的展开:

顾问会被数据科学家完全取代吗?在某些形式上,是的。但当面临变化和变异的任务时,人工智能和机器学习仍将苦苦挣扎。由于这个原因,我认为在可预见的未来,顾问是不可替代的。然而,我们可能需要更少的顾问和更多的数据科学家……
数据科学家面临的最大问题是,他们仍然纠结于项目的实际有形价值,对于非科学家或纯粹关注结果而非发现的人来说,这更难衡量。出于这个原因,我希望看到由数据科学家(他们中的一些人也可能是顾问)和专家顾问组成的团队。
根据我作为人工智能顾问的经验,我发现 ML 算法可能会产生非常强大、有见地的分析,但在将这些分析转化为具体的商业决策时,往往会缺少一个环节。在这些情况下,专家顾问的需求是强制性的。
此外,由于现实和环境的原因,人工智能系统无法覆盖太多不断变化的元素。
最后,即使你构建了完美的人工智能解决方案,你仍然有一个客户需要理解解决方案的问题。咨询的很大一部分是在组织中实施正确的解决方案。
我推荐这些文章以获取更多信息:
- https://digital . HBS . edu/platform-digital/submission/BCG-digitally-disrupting-or-disrupted/
- https://www . economist . com/special-report/2018/03/28/ai-providers-将日益与管理咨询公司竞争
人工智能——过去、现在和未来
快速看一下什么是人工智能,它意味着什么,以及它是如何随着时间的推移而变化的

图片由皮克斯拜的 Gerd Altmann 提供
如题所示,我将谈论 AI 或人工智能。AI 到底是什么?它是如何产生的?这是现代现象吗?AI 的历史是怎样的,现状是怎样的,未来是什么样子的?
在我开始工作之前,每当我听到 AI 这个词,我就会想到机器人和能够像人类一样思考的超级计算机。我对艾的印象受到了《终结者》或《奥创时代》等电影的影响。但是不出所料,我后来意识到这些和好莱坞的其他作品一样接近现实。
在这种情况下,什么是人工智能,或者我们如何定义人工智能?来自维基百科的一个可能的定义将人工智能定义为:
机器对人类智能的模拟,这些机器被编程为像人类一样思考并模仿人类的行为

乍看之下简单明了,但是真的是这样吗?让我们以一个我们从小就一直使用的简单工具为例:计算器。

Annie Spratt 在 Unsplash 上拍摄的照片
它是一台被编程的机器,做人类发明的事情,也是只有我们能做的事情,数学运算。
因此,它不应该被认为是人工智能的一个例子吗?
如果它确实是一个,那么今天有什么新东西让这么多人都在谈论呢?它值得现在得到的所有关注吗?
为了更多地了解这一点,我们需要深入一点人工智能的历史,以及什么是众所周知的符号/经典人工智能。
经典人工智能:
经典人工智能的目标是使用事实和规则明确地表示人类知识。也就是说,你用一些规则给一台机器编程,当你输入一个查询时,它会根据规则给出答案。
以计算器为例,它是用数学运算规则编程的,当你输入 2+3 时,它返回 5。
专家系统如 WebMD 是另一个例子。WebMD 有一个医学知识和规则的数据库,由医生等医学领域的专家汇编而成。当你输入你的症状时,它会在数据库中查找你可能患有的疾病。

经典人工智能
虽然经典人工智能在某些情况下工作得很好,但它仍然受到一个主要问题的困扰,那就是规则。如果有很多规则或者规则没有被很好地定义怎么办?在这些情况下,很难明确地编纂或规定规则。一个例子是,如果你想让一台机器识别一只猫,你会指定什么规则来识别它?
所有这些问题导致了人工智能的期望和现实之间的不匹配,并导致了人工智能的“冬天”。在此期间,主要是在 70 年代和 80 年代,人工智能研究的资金被大量削减,增长速度放缓。

有一个流行的笑话是这样的:人工智能和自动化之间有什么区别?答案是自动化是已经实现的东西,而人工智能是还没有实现的东西。
自古以来,人类就试图让机器和装置去做他们所做的事情,或者至少让它变得简单。就像印刷机或自动送水机一样。它从让机器完成简单任务开始,随着人类的进步,让机器完成更复杂的任务。因此,经典人工智能只是这一趋势的延续,并且在那个时期发挥了很好的作用。但是随着技术的进步,我们需要一种不同形式的人工智能,一种可以完成传统人工智能无法完成的更复杂任务的人工智能。
现代人工智能
现代人工智能是人工智能的最新化身,旨在处理经典人工智能的许多弱点。与经典人工智能不同,现代人工智能不需要人们为它明确指定规则。它能够自己学习规则。
你给机器指定输入/查询和期望的输出/答案,它可以推断和提取从输入到输出所需的规则和模式。如果你想让一台机器能够识别猫,你就给它大量的猫图片,让它理解猫的共同特征。然后,每当它看到另一只猫,它就能够匹配它的特征,并确定它是一只猫。

现代人工智能
在这方面,它类似于人们如何学习。没有人向你解释猫长什么样,你看到猫的照片或真猫,你自己明白它的特征。
简而言之,现代人工智能是一种强大的模式识别方法,在许多方面模仿了人们的学习方式。
现代人工智能的兴起可以归因于三个因素:
- 数据卷宗
2.统计模型
3.计算能力
近年来,从互联网或您使用的设备上收集的数据量有所增加。由于更好的 CPU 和 GPU 导致的计算能力的上升意味着大量的数据不仅仅存储在数据库中,而是现在可以使用。这允许使用更好的计算资源对大量数据应用新的统计模型,以提取有价值的信息和模式。简而言之,我们可以称之为机器学习。
让我们举一个例子,比如 facebook 的好友推荐算法。例如,假设一个人多年来交了很多朋友。该算法能够挑选所有这些朋友,然后创建一个网络,让它找到共同的模式。在网络中,可能存在对应于他所进入的圈子而形成的主要集群。一个群可能对应于他从小就认识的人,另一个群是他在大学认识的人,另一个是同事,等等。

图片由皮克斯拜的 Gerd Altmann 提供
从这些聚类中,该算法能够学习和识别共同特征,然后预测人 A 可能还认识谁,并推荐他们作为朋友。
在这里,机器学习用于教授/学习规则和模式,而人工智能则是将其应用于推荐朋友的行为。经典人工智能使用规则为人工智能提供动力,现代人工智能使用机器学习为人工智能提供动力。随着时间的推移,人工智能的定义没有改变,只有为它提供动力和做出决策的定义没有改变。
现代人工智能的局限

马库斯·斯皮斯克在 Unsplash 上拍摄的照片
数据、数据和数据:
数据,不是任何数量的数据,而是海量的数据。但是为什么要大呢?假设一个人工智能接触到一只猫的图像:

Eric Han 在 Unsplash 上拍摄的照片
但是它不能识别这个:

照片由 Rémi Rémino 在 Unsplash 上拍摄
或者这个:

米哈伊尔·瓦西里耶夫在 Unsplash 上的照片
作为一只猫。有了少量数据,现代人工智能变得非常狭窄,需要大量数据才能概括。
它不仅仅是数据,而且是有标签的数据。你可能在网上有很多数据/图片,但是你也需要知道它的意思。这是一张大象的照片,这是一只猫吗?这就是为什么你经常听到人们说“数据是新的石油”(现在可能不是了)。正确的数据,不仅仅是数据,还有带标签的数据,很难获得,这对现代人工智能极其重要。
制度化偏见:
任何人工智能都只有它的训练数据好。如果数据包含任何偏见,那么人工智能也将继承它。一些例子可能是工作招聘算法或贷款批准算法。如果一家公司在此之前没有雇佣很多女性,那么任何接受过雇佣培训的人工智能也会学会歧视女性。因此,在日常训练和使用人工智能时需要非常小心。
结论:
今天的大多数人工智能都是狭义的人工智能,它们只能做它们被训练的事情,当试图做它们领域之外的事情时,它们会失败。此外,人工智能看待世界的方式与我们人类不同。这两者都表明,像通用人工智能或有自我意识的人工智能这样的东西似乎是一种遥远的可能性。可能需要一种全新的理论来应对这些挑战。
对人工智能的研究将继续考虑对其重要性和能力的认识。这将导致 AI 在各个领域的更好表现和更多扩散。假以时日,它可能会像手机一样随处可见。它会取代人类吗?我认为不会,它将更多地作为人们所能做的补充,通过给我们提供更多的信息,使我们能够做出更好的决定。想象一下钢铁侠是如何运作的,一个普通人在战斗中使用人工智能来增强他的决策。最终只有时间能证明一切。
人工智能&寻找疫苗
生物学的深度学习
人工智能如何改变冠状病毒疫苗的研究
尽管缺乏足够数量的数据带来了挑战,但最近开发并使用了几种基于人工智能的工具来解决当前疫情带来的许多挑战。在过去的 8 个月里,人工智能模型已经被用于生物医学图像分类,用于使用 CT 扫描& x 射线图像的临床诊断,以及通过跟踪当地新闻和社交媒体账户预测热点 &疫情的。然而,这篇文章讨论了人工智能在生物医学研究中的应用的最新进展,以快速、廉价地发现治疗新型冠状病毒感染的药物和疫苗。
在这篇文章中,没有预先理解病毒学或药物发现。
对于那些没有足够生物学背景的人,我首先讨论病毒在宿主细胞中的结构和作用模式,然后详细描述人工智能在新型冠状病毒研究中的三个具体应用,我个人认为这是最有趣和最有希望的,可以加速我们对治愈方法的探索。
技术给湿实验室的研究人员带来了巨大的挑战。当前疫情带来的前所未有的紧急情况正在推动生物医学研究人员和计算机科学家之间新的研究合作。因此,人工智能在生物医学研究中的应用是一个快速发展的领域,我在这里的目的是提供一个简要的概述,而不是对该领域的广泛调查。对于深度学习的新手,可以参考我之前关于卷积神经网络内部工作的文章。
关键构建模块的直观指南
towardsdatascience.com](/how-convolution-neural-networks-interpret-images-1f99913070b2)
病毒如何在宿主细胞中繁殖
病毒由两种基本成分组成,蛋白质和核酸(RNA 或 DNA)。蛋白质形成保护壳(通常不止一个),有助于安全地将封装的核酸(即病毒基因组)从一个细胞转移到另一个细胞。一旦病毒基因组(在 SARS-CoV2 的情况下为 RNA)被成功转移到宿主细胞中,它通过利用宿主细胞可利用的资源进行快速复制以在宿主中定居。这种对宿主必需资源的剥夺,最终导致细胞死亡和病毒颗粒的释放,然后病毒颗粒继续感染和定居邻近的细胞。


图一。(左)新型冠状病毒成像:冠状病毒颗粒被染成蓝色的透射电镜图像(来源)。(右) SARS-CoV2 结构:显示关键结构蛋白和病毒基因组的图示。刺突蛋白 S ,包膜蛋白 E ,膜糖蛋白 M ,核衣壳蛋白 N 以及病毒基因组,RNA来源。
虽然过去人工智能已经在药物发现和疫苗开发的一些领域中与实验研究结合使用,但当前疫情强加的紧急情况使得人工智能在加速寻找理想的新型冠状病毒疫苗候选物方面不可或缺。这篇文章描述了人工智能在药物发现方面的三个应用:
- ****蛋白质折叠问题:如何使用深度学习算法,仅用氨基酸序列作为输入,通过计算预测与新型冠状病毒相关的蛋白质的复杂三维结构。
- ****药物筛选问题:基于神经网络的方法如何帮助筛选超过 10 亿种化合物,以确定那些可以成功靶向与新型冠状病毒发病机制相关的特定蛋白质的化合物。
- ****疫苗覆盖率问题:如何使用基于机器学习的模型来计算设计疫苗候选物,使其在不同人群中具有最佳覆盖率。
在这一点上,我必须澄清,本文中描述的计算工具旨在通过预测一些关键实验技术的结果来加速现有的药物发现渠道,而不是传统实验研究的替代方案。这些计算工具的结果仍然需要使用传统的湿实验室技术进行验证。尽管许多计算生物学家和生物信息学家相信机器人技术和深度学习将在十年内淘汰湿实验室技术,但在我们意识到这一点之前,我们还有很长的路要走。
蛋白质结构预测
蛋白质本质上是由 20 种不同类型的氨基酸组成的线性序列,折叠成独特的 T2 三维结构。氨基酸的特定序列决定了结构,而结构又决定了蛋白质的功能。除了上面图 1 所示的四种结构蛋白之外,还有几种非结构蛋白在病毒致病中发挥关键作用,以及人类受体蛋白帮助病毒进入人类细胞,所有这些都是疫苗开发的合适目标。因此,确定它们的确切原子结构是开发针对这些蛋白质之一的疫苗的必要前提。虽然用于确定蛋白质结构的实验技术可能非常昂贵和耗时,但导致蛋白质折叠模式和三维结构的非常复杂的相互作用现在可以使用高级的非常深度的学习模型来表征。蛋白质折叠问题 代表了分子生物学研究的圣杯。问题很简单,给定蛋白质的氨基酸序列,你能预测它的三维结构吗?
虽然科学家已经与它斗争了 70 多年,但计算机科学家最近在为蛋白质折叠问题提供有意义的解决方案方面取得了非常重大的进展。
2020 年 1 月 Deep Mind 推出了 Alphafold ,这是一个基于神经网络的框架,仅使用氨基酸序列作为输入来预测蛋白质结构。Alphafold 已经被用于预测新型冠状病毒刺突蛋白(已知介导细胞进入)和其他几种相关蛋白的结构。已经发现预测的结构非常接近随后使用实验技术确定的结构。下面显示的是蛋白质 ORF3a (一种与诱导细胞死亡有关的新型冠状病毒相关蛋白)的实验结构与使用 AlphaFold 计算预测的结构的比较。

图二。ORF3a 蛋白的 AlphaFold 预测结构为蓝色,随后实验确定的结构为绿色,显示两种结构非常匹配。来源
在下面所示的从头建模工作流程中,使用 ResNet 深度学习模型预测不同氨基酸残基之间的距离和边际扭转角的概率分布,该模型对蛋白质数据库中可用的约 30,000 个实验确定的蛋白质结构进行训练。然后通过梯度下降或模拟退火进行优化以服从 ResNet 预测,从而获得最终结构。

图 3 。AlphaFold 的全新建模工作流程,仅使用氨基酸序列作为输入来预测蛋白质结构。来源
AlphaFold 神经网络由 220 个残差块组成,如下所示,每个块包括一系列卷积和批处理层;两个 1 × 1 投影层;一个 3 × 3 扩展卷积层和三个指数线性单位(ELU)非线性。更多细节可以在原始出版物中找到。经过培训的网络和用户说明可以在这里找到。

****图四。作为 ResNet 模型的一部分使用的单块深度残差卷积网络。来源
这种预测与病毒生命周期相关的关键蛋白质结构的能力将加速针对这些蛋白质的新型候选疫苗的设计和筛选。除了预测病毒蛋白质的结构,AlphaFold 还将有助于可视化许多潜在药物和疫苗与目标蛋白质的相互作用。
药物筛选的深度对接
传统的药物发现渠道是极其费时和费钱的,因为它们需要对成百上千甚至上千的潜在药物分子进行人工筛选,以得到一种既有疗效又安全的药物分子。深度** 对接 是最近提出的基于神经网络的平台,用于加速虚拟筛选潜在药物分子,方法是预测数据库中特定药物分子与潜在药物靶标选择的相互作用程度。**

****图 5。深度对接工作流程。来源
这个模型已经被应用于估计来自 ZINC15 化学品数据库的超过十亿种潜在药物化合物与新型冠状病毒主蛋白酶(MPro) 的相互作用。下面显示的是排名第一的药物化合物 ZINC000541677852(洋红色)与 MPro 蛋白(灰色密度图)的相互作用。

****图六。zinc 000541677852 与新型冠状病毒主蛋白酶的相互作用来源
除了上面图 6 中显示的药物化合物,本研究中还鉴定了 1000 种其他潜在的候选药物。这种通过计算筛选数百万种潜在药物来靶向特定蛋白质的能力,有能力真正改变药物发现渠道。必须非常谨慎地对待这种计算研究的结果,并且需要大量进一步的实验研究来确定所提出的药物的功效。
具有最佳覆盖率的疫苗设计
疫苗通过激活宿主细胞的自然免疫反应来发挥作用。为了阻止这种反应,疫苗通常由病毒蛋白本身组成。这些肽然后结合主要组织相容性复合物(MHC)I 类和 II 类蛋白质,当该复合物(MHC +肽)展示在细胞表面时,它们有助于激活 T 细胞免疫反应。这个过程被称为抗原呈递。疫苗产生的免疫反应取决于抗原呈递过程中展示的肽序列、MHC 蛋白序列以及两者之间的相互作用。本视频对此过程进行了清晰的解释。
在目前正在进行临床试验的 41 种候选疫苗中(截至 2020 年 9 月 30 日),至多有少数可能在治疗新型冠状病毒方面既安全又有效。成功的方法肯定不会在所有人群中表现出相同的效果,因为负责 MHC 蛋白的基因在不同人群中表现出显著的差异。这在疫苗设计问题中引入了另一个变量。除了安全有效之外,这种疫苗还具有广泛的覆盖面。
最近,麻省理工学院的研究人员使用了一种基于机器学习的方法,来设计在不同人群(黑人、亚洲人和白人血统)中具有最佳功效的疫苗。

****图七。基于机器学习的 OptiVax 和 EvalVax 系统,用于优化候选疫苗并评估其疗效。来源
使用 OptiVax-Unlinked 和 Opti-Vax-Robust 将两个评估度量(EvalVax-Unlinked 和 EvalVax-Robust)用作组合优化问题的目标函数。上面图 7 中总结的是三步过程,其中首先筛选具有所需特性的肽(蛋白质片段)。然后通过两步 OptiVax 优化对这些进行免疫原性评分,该优化在第一步中鉴定所有可能衍生自病毒蛋白的肽片段,其可能潜在地产生疫苗。在最后一步,候选疫苗针对导致 MHC 蛋白序列地理变异的 HLA 等位基因频率进行优化。该系统提供的疫苗将有效地为不同地理区域和种族的人群提供免疫力。提议的疫苗显示为新型冠状病毒 MHC 类制剂提供了 93.21%的人群覆盖率,为 MHC 类制剂提供了 97.21%的覆盖率。关于优化算法的更多细节可以在原始出版物的末尾找到。
结论
在这篇文章中,我试图解释在我看来人工智能在新型冠状病毒生物医学研究中最重要和最有前途的三种干预。首先,我们讨论了人工智能如何以非常高的精度预测蛋白质结构。然后,我们讨论了如何使用简单的神经网络从非常大的数据集筛选任何感兴趣的蛋白质的抑制剂。最后,我们讨论了如何使用机器学习来设计覆盖更广泛人群的疫苗。除了文章中提到的,下面是主要出版物的列表。感谢阅读。
阅读清单
- 人工智能-实现了对新冠肺炎患者的快速诊断。链接
- 新型冠状病毒刺突糖蛋白的结构、功能和抗原性。链接
- 新型冠状病毒冠状病毒视觉指南。链接
- 人工智能可以帮助下一个疫情——但不是这个
- 利用深度学习的潜力改进蛋白质结构预测。链接
- 生物学和医学中深度学习的机遇和障碍。链接
- 蛋白质结构预测的分水岭时刻链接
人工智能检测语音中的说话者
利用人工智能从语音数据中检测讲话者

随着人工智能的进步,人们可以提出许多有趣和有益的人工智能应用。这些人工智能应用在健康、零售、金融和其他各种领域都很有帮助。主要的想法是不断思考我们如何利用这些先进的技术,并提出有趣的用例。
通过这篇博文,我打算介绍一个人工智能应用,在这个应用中,人们可以从说话者的声音中检测出说话者。我还将解释我创建这个数据集的过程。代码和数据集在这里可用。有几篇博客文章围绕这个话题,但这篇文章在两个方面有所不同,首先,它将提供一个清晰的指南,说明如何使用一些最佳实践有效地检测说话者,而不陷入陷阱;其次,在最后,我将涵盖一些真正有趣的用例/应用,它们可以从这篇文章中扩展出来。 那么,我们开始吧。
创建数据集
我创建了一个由来自印度的 5 位名人/流行人物组成的数据集。

由来自印度的 5 位名人/流行人物创建的数据集。图片来源~ 维基百科
我从 Youtube 上截取了这些名人的许多演讲/采访,并将它们转换成一个 Mp3 文件。
此外,我使用流行的 Librosa Python 库将这些 MP3 文件转换成频谱图。我从 mp3 剪辑中以 90 秒的间隔重复创建了这些光谱图。
def generate_spectogram(file,path,jump = 90):
total_time = librosa.get_duration(filename=file)
till = math.ceil(total_time/jump)
for i in range(till):
x , sr = librosa.load(file,offset=i*jump,duration=jump)
X = librosa.stft(x)
Xdb = librosa.amplitude_to_db(abs(X))
librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='log',cmap='gray_r')
plt.savefig(file_save,dpi=1200)
这些光谱图看起来像:

声音的声谱图
有一本关于歌词和音乐流派分类的好书。
音乐就像一面镜子,它告诉人们你是谁,你关心什么。你就是你所流的。
towardsdatascience.com](/music-genre-classification-with-python-c714d032f0d8)
一旦我们将音频片段转换成图像,我们就可以训练一个监督的卷积神经网络(CNN) ,模型。
一些挑战
开发这样一个应用程序本身也有一些挑战。这些挑战是
- 我们的数据集包含了非常相似的人的声音。检测枪声和狗叫声并不是一件非常困难的事情,因为它们是不同的声音。在我们的例子中,区分一个人的声音和另一个人的声音是一个更困难的问题。
- 我们从这些名人的 Youtube 演讲/采访中创建了一个数据集,所以很多时候会有背景噪音或其他人/采访者在中间说话或人群鼓掌。
- 该数据集每人最多有 6-7 个片段,这妨碍了准确性。更丰富的数据集将在准确检测个人方面提供更好的准确性和信心。
培训此类模型的最佳实践
在训练这个应用程序时,有些事情对我来说不太好,而有些事情却像魔法一样提高了模型的性能。在这一节中,我将指出训练这种模型的最佳实践,而不会落入陷阱。
- 用黑白光谱图而不是彩色光谱图训练模型。这增加了我的模型准确性。一个原因可能是不太复杂的数据使模型更容易学习。这可以通过更改库的“cmap”属性来实现。
librosa.display.specshow(Xdb, sr=sr, x_axis=’time’, y_axis=’log’,cmap=’gray_r’) - 从谱图中移除所有类型的标签或记号,不需要的文本只会混淆模型。
- 允许 Resnet 或 Vgg 架构(或任何其他选择的架构)训练每个单独的层,而不仅仅是训练最后几层,可以提高性能。一个原因可能是 Imagenet 数据与光谱图非常不同。给予每一层单独训练的杠杆作用提高了模型的性能。
- 在这些人/名人的完全不同的剪辑/视频上测试模型的性能。原因是来自相同剪辑甚至来自不同时间帧的频谱图可能包含相同类型的噪声、背景或记录设备。我们希望模型总体表现良好。
- 该模型的准确性可以通过由说话人的不同剪辑来丰富训练数据来提高。这使得模型能够一般化。
- 为模型提供高质量的生成光谱图进行训练。这可以通过在保存绘图时更改 dpi 属性来实现。
plt.savefig(file_save,dpi=1200)
模型训练和准确性
我用 FastAI 库训练了模型。我用一个 ResNet 架构来训练一个 CNN 模型。创建的数据集和代码在这里可用。
当在有限的训练集上训练时,该模型对完全看不见的测试数据(来自不同剪辑)给出了大约 80–85%的准确度。可以通过丰富训练数据集来提高模型性能。
其他有趣的可能用例
这样一个经过适当训练的应用程序可以在以下方面发挥作用
- 自动标记视频/音频中的扬声器。
- 检查一个人模仿一个名人有多好,比较该名人的模型得出的分数。
- 创建一个应用程序,从随机歌曲中猜测歌手,并比较人工智能的检测能力。它喜欢玩对抗人工智能。
- 在犯罪调查中,从被窃听的电话对话中高置信度地检测人/说话者是有用的。
结论
通过这篇博文,我介绍了一个人工智能应用,在这个应用中,人们可以从说话者的声音中检测出说话者。我还强调了训练这种模型的最佳实践和其他有趣的用例。创建的数据集和代码在这里可用。
如果你有任何疑问,请联系我。我也很有兴趣知道你是否有一些有趣的人工智能应用/用例。
我的 Youtube 频道获取更多内容:
嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…
www.youtube.com](https://www.youtube.com/channel/UCg0PxC9ThQrbD9nM_FU1vWA)
关于作者-:
Abhishek Mungoli 是一位经验丰富的数据科学家,拥有 ML 领域的经验和计算机科学背景,跨越多个领域并具有解决问题的思维方式。擅长各种机器学习和零售业特有的优化问题。热衷于大规模实现机器学习模型,并通过博客、讲座、聚会和论文等方式分享知识。
我的动机总是把最困难的事情简化成最简单的版本。我喜欢解决问题、数据科学、产品开发和扩展解决方案。我喜欢在闲暇时间探索新的地方和健身。关注我的 中 、Linkedin或insta gram并查看我的往期帖子。我欢迎反馈和建设性的批评。我的一些博客-********
- 每个数据科学家都应该避免的 5 个错误
- 以简单&直观的方式分解时间序列
- GPU 计算如何在工作中真正拯救了我?
- 信息论& KL 分歧第一部分和第二部分
- 使用 Apache Spark 处理维基百科,创建热点数据集
- 一种基于半监督嵌入的模糊聚类
- 比较哪种机器学习模型表现更好
- 分析 Fitbit 数据,揭开疫情封锁期间身体模式变化的神秘面纱
- 神话与现实围绕关联
- 成为面向商业的数据科学家指南
AI 理解:大象是什么?
人类知识和人工智能模型中大象的表示
在这个故事中,我想谈谈一个词的抽象概念。它在不同语境中的含义。当前的机器学习算法如何理解它,为什么很难实现一个通用的、类似人类的知识。我想用大象这个词来说明我的想法。我会把这个帖子的收入捐出去拯救物种。*

“这不是一头大象”,字体为“大象——原图”,作者为克里斯汀·斯蓬基亚,来自皮克斯拜
字典中的大象
这是《韦氏词典》对大象的定义 [1]:
1a: 一种体形粗壮,通常非常大,几乎无毛的食草哺乳动物(象科,象科),其口鼻部拉长成肌肉发达的象鼻,上颚有两颗门牙,特别是雄性长牙:
(1): 热带非洲的一种高大、大耳的哺乳动物(loxotonta africana),有时被认为由两个独立的物种组成(撒哈拉以南的稀树草原的 L. africana 和中部和西部雨林的 L. cyclotis )
也被称为非洲象
(2)东南亚森林中一种相对较小耳朵的哺乳动物
——又称亚洲象、印度象
非常大或难以管理的人
这个条目可以说明理解一个词的概念的一些困难的挑战。首先,单词可能有许多完全不同的意思。在这里,单词大象有两个意思,它们之间唯一的联系是都指大的东西。其次,1a、1b 和 1a 亚型表明在不同的上下文中,大象这个词代表不同的事物,更大或更小的动物群体。对于一个学习动物知识的孩子来说,非洲象和亚洲象的区别没有生物学家重要(参见维基百科上大象种类的完整列表)。最后,阅读和理解这个定义需要了解其中使用的词语(例如哺乳动物、亚洲和非洲)。

这不是一个不确定的知识概念(AKMilroy 2015 after Margritte) [2]
自然语言处理中的大象
对于计算机来说,要理解一个普通的文本,它必须把它转换成数字。最直接的方法是为字典中的每个单词指定一个数字。为了将其表示为向量,其中两个单词是独立的,需要有一个向量空间,其维度与词汇的大小一样大(如果单词被用作该向量空间的标准基,这被称为一键编码)。
然而,这是一种非常昂贵的表示,人们可能想要一种更紧凑的表示。Mikolov 等人[3,4]提出了一种表示方法,其中向量空间被投影到一个更小的(100-300 dims)空间,基于该空间,单词在大型语料库中一起出现。使用这个单词嵌入向量,不仅表示变得更小,而且还有另一个非常重要的特征:相似的单词彼此更接近。在上使用 en 英语语料库这个在线演示,单词大象类似于下面的单词:elephants, rhino, tiger, rhinoceros, tigers, hippo, gorilla, giraffe, rhinos, hippopotamus。
有了这个单词向量表示,我们就可以使用向量运算了:如果我们从向量大中减去向量大象,再加上向量鼠标,一个与结果最相似的向量就是小。这叫做字类比:大和大象的关系类似于小和老鼠的关系。
正如我在上一节中提到的,单词有多重含义,通常只有上下文才能区分它们。最近的工作,如 Devlin 等人[5]提出了一种新的方法,称为上下文化单词嵌入向量来解决这个问题。如果你对此感兴趣,可以看看我以前的帖子!

空间城市词典中“房间里的大象”例句的依存可视化
明摆着的难题
为了理解一个词的每一种用法,人们还应该研究一下搭配。例如,房间中的大象不仅仅是建筑中的一只大型哺乳动物。在搭配中,单词有共同的意义,人们不能仅从各部分的总和中推导出它的意义。在某些情况下,像大象的脚,它需要特殊的参考,可能不是常识的一部分,但是,人们可以期待一个通用的人工智能理解参考。像 Spacy [6]这样的 NLP 工具包可以解决这个叫做命名实体识别 (NER)的问题。
大象的脚是切尔诺贝利事故中形成的大量堆芯熔融物和其他材料的昵称…
en.wikipedia.org](https://en.wikipedia.org/wiki/Elephant's_Foot_(Chernobyl)#/media/File:Chernobyl_Elephant's_Foot.jpg)
计算机视觉中的大象
两个主要的图像数据集都包含大象的图像。OpenImages [7]有一个单个大象类,ImageNet [8]也有一个非洲 (2277 张图片,61.32%受欢迎百分比)和印度 (1650 张图片,55.85%受欢迎百分比)大象类。ImageNet 数据集通过在分层结构中对图像进行分类来回答上面提出的关于不同级别的单词组的问题。

ImageNet 层级中的大象— 图片来自 ImageNet 网站(2020 年 10 月 22 日)
浏览这些图片,我们可以看到不同位置、年龄、大小和背景的大象。这些数据解决了第二张图中提出的问题(AKMilroy 2015,Margritte 之后):有许多图像只显示了动物的一部分,因此,根据这些数据训练的模型可以只从动物图像的一部分中识别大象。

open images 数据集中带有分割的大象 ( 许可)——原始来源作者德里克·济慈 ( 许可)
大象的人类形象
虽然上一节提到的图像数据集包含大量真实动物的图像,但我们人类还有动物的其他表现形式:图画、人物和毛绒玩具。这里可以提出一些有趣的问题:
- 一个训练有素的人工智能能理解大象的概念吗?
- 它会把玩具归类为大象吗?
- 一般模型应该把玩具归类为大象吗?
- 什么时候应该把它归为大象?

七种可选的大象图片及其 Keras DenseNet 分类,带有预先训练的 ImageNet 权重
上图显示了七个可选的大象图片及其 DenseNet [9]分类,在 Keras 中使用预先训练的 ImageNet 权重实现。我们可以看到,在很多情况下,模型识别的是格式(绘图,毛绒),而不是图像中的动物。只有两个预测的前五名中有一头大象。
上图中的图像:
- 复制早期印刷版本人类窥镜的插图(1430 年)
- 安德烈·泰韦特。F. André Thevet d'Angoulême。里昂、让·图尔内斯和吉尔的《数字评论与增刊》。Gazeau,1556 年。
- 1976 年万隆奥林匹克运动会
- 棋子,主教 17 世纪末-18 世纪初
- 后来出售的 t 恤上画的大象。丹尼斯·贾维斯
- 蓝色大象剪贴画
- 毛绒大象的图片,自己的照片
拯救物种!
大象是野生动物的标志性动物。根据拯救大象:
大象是非洲的园丁和景观工程师,无论它们漫游到哪里,都在播种和创造栖息地。
如果不采取紧急措施来拯救它们的物种,大象可能会在一代人的时间内从野外消失。
从 2010 年到 2012 年,仅仅三年时间,非洲就有大约 10 万头大象因为象牙被捕杀。
(*):我想把这个帖子的收入捐出来拯救大象。因此,每当 WWF Gifts 网站上的非洲象虚拟收养捐赠金额达到 55 美元时,我都会将其捐赠给该组织。
参考
[1]“大象。”Merriam-Webster.com。2011.https://www.merriam-webster.com(2020 年 10 月 22 日)。
[2] 米尔罗伊,A. K. (2017)。昆士兰植物群进化和灭绝的知识、技术和观点可视化。
[3]t . miko lov,Sutskever,I .,Chen,k .,Corrado,G. S .,& Dean,J. (2013 年)。词和短语的分布式表示及其组合性。神经信息处理系统的进展(第 3111-3119 页)。
[4]t . miko lov,陈,k .,Corrado,g .,& Dean,J. (2013)。向量空间中单词表示的有效估计。 arXiv 预印本 arXiv:1301.3781 。
[5] Devlin,j .,Chang,M. W .,Lee,k .,& Toutanova,K. (2018 年)。Bert:用于语言理解的深度双向转换器的预训练。 arXiv 预印本 arXiv:1810.04805 。
[6] Honnibal,m .,& Montani,I. (2017 年)。 spaCy 2:利用 Bloom 嵌入、卷积神经网络和增量解析的自然语言理解。
[7] Krasin I .、Duerig T .、Alldrin N .、Ferrari V .、Abu-El-Haija S .、Kuznetsova A .、Rom H .、Uijlings J .、Popov S .、Kamali S .、Malloci M .、Pont-Tuset J .、Veit A .、Belongie S .、Gomes V .、Gupta A .、Sun C .、Chechik G .、Cai D .、Feng Z .、Narayanan D .、Murphy K.
OpenImages:大规模多标签多类别的公共数据集
可从https://storage.googleapis.com/openimages/web/index.html.获得
[8]邓俊杰,董,魏,苏歇,李,李,李,,李(2009 年 6 月).Imagenet:一个大规模分层图像数据库。2009 年 IEEE 计算机视觉和模式识别会议(第 248–255 页)。Ieee。
[9]黄,g .,刘,z .,范德马腾,l .,,温伯格,K. Q. (2017)。密集连接的卷积网络。在IEEE 计算机视觉和模式识别会议论文集(第 4700–4708 页)中。
人工智能如何帮助金融和银行业

人工智能和机器学习为金融行业提供了前所未有的自动化承保、防止欺诈和获得新客户的能力。
在过去的几年里,金融和银行业的人已经开始看到将机器学习引入他们行业的力量。现在,各种规模的金融机构都在争先恐后地减少官僚作风,提高贷款过程的准确性和公平性。
不幸的是,许多金融机构仍在使用启发式方法来管理复杂、高度管控的流程,也就是说,他们流程的规则和法规是由一群(昂贵的)法律、金融和计算机编程专家手动配置和更新的。
是什么推动了采用人工智能的紧迫性?
需要提高速度和效率获得更深入的数据驱动洞察的机会复杂的法规和合规性要求糟糕的客户服务和漫长的等待时间。信用评分不能说明全部情况。
当机器学习进入金融和银行业时
- 新的人工智能驱动的流程和产品产生新的收入流。
- 多维度和跨辖区的欺诈计划可以立即被发现。
- 客户获取变得更加个性化、简化和数据驱动。
- 财务报告、合规性保证和管理任务都是自动完成的。
- 风险评估和承保超越了信用评分。
- 通过图像处理验证索赔并确定损失。
人工智能在金融和银行业的主要用途

文本组织和摘要
Manceps 可以帮助金融机构将自然语言处理应用于大量文本和语音数据,以提取信息、获得洞察力并简化手动任务。虽然节省时间和成本是显而易见的好处,但识别关键信息的能力(众所周知的大海捞针)却能带来巨大的不同。考虑将自动摘要应用到法律文档、收入报告或工作申请中。

欺诈检测
欺诈检测现在不仅仅涉及风险因素清单。使用 ML 技术,欺诈检测系统现在可以主动学习和校准,以应对新的(或潜在的)安全威胁。通过分析数十亿个数据点,这些系统可以标记出否则会被人类忽视的问题,防止错误拒绝。

个性化零售体验
客户越来越擅长使用聊天机器人和其他对话界面来满足他们的银行需求。这种聊天机器人必须使用强大的自然语言处理引擎以及大量特定于金融的客户交互来构建。这些技术使得银行客户越来越难以辨别他们是否真的在与人交谈。
聊天机器人、财务助理和相关工具是自学的,这意味着它们会随着额外的客户互动而不断改进。

风险保理
预测分析运行在人工智能上,在金融领域,引入这种见解可以增加收入并降低成本。金融组织出于各种目的使用预测分析。这使得他们能够识别和锁定更有利可图的客户;更好地管理现金流;预测需求波动,降低风险。随着人工智能的能力越来越强,金融机构正在寻找越来越复杂的方法来利用这些数据。

操作优化
像许多大型组织一样,金融机构正在转向人工智能,以自动化经常重复的任务,并帮助他们的业务更顺利地运行。在一个例子中,摩根大通利用机器人帮助员工重置密码。他们预计,2017 年机器人将处理近 200 万个请求,大约是 40 名全职员工的工作量。
本文改编自 Manceps《金融与银行服务》页面 。Manceps 不仅帮助组织大规模地构建和部署人工智能模型,还帮助组织识别商业用例,使人工智能投资成为可能。
如果你正在考虑将人工智能引入你的组织,我建议你从这个优秀的资源开始: 人工智能就绪讨论问题 。
更多与金融相关的用例,可以考虑查看: 来自全球最大金融和银行公司的 AI 例子 。
人工智能对新冠肺炎。真的管用吗?
弄清楚我们能用现有的数据做什么,不能做什么

艾丽莎·埃克特女士和丹·希金斯女士在菲尔上的照片
内容:
- 介绍
- 制作我们的胸部 x 光新冠肺炎分类器
2.1。数据准备
2.2。训练
2.3。结果 - 真的管用吗?
3.1。进一步分析
3.2。讨论和要点
1.介绍
今天,每个人都知道疫情。专业人士尽最大努力帮助应对这一问题:防止感染的快速传播、开发诊断方法、药物发现、病人护理策略、疫苗开发、死亡率预测、全球经济的建模影响以及许多其他问题。
数据科学家也不例外。没有必要让任何人相信人工智能在医疗应用中非常有用。你可能已经看到出版物(甚至科学论文)声称已经开发出某种模型,可以预测患者是否患有新冠肺炎。一些出版物声称,当将深度学习应用于胸部 X 射线图像时,预测准确率达到 90%以上,这提出了许多问题。
这就是为什么:在 Futuremed 我们与医生密切合作,处理医疗数据。放射科医生说,胸部 x 光片中几乎没有新冠肺炎特有的模式。有时候,人工智能能够找到任何人类医生都无法找到的特征。
使用视网膜照片进行性别分类。
也许新冠肺炎的胸部 x 光片也是如此?让我们找出答案。
2.制作我们的胸部 x 光新冠肺炎分类器
这不是一个“如何训练神经网络”的教程,但我会添加所有必要的信息来重现所描述的工作。
2.1.数据准备
对于在胸部 X 射线图像上分类新冠肺炎的任务,我们的数据集应该至少有两个类:“新冠肺炎”和“其他”。
我们将使用四个数据源进行训练:
1。著名的 GitHub 回购带有新冠肺炎的图片。
2。来自意大利数据库和新冠肺炎病例的图片。
3。胸部 x 光肺炎数据集。
4。 NIH ChestXRay-14 数据集。
为了获得尽可能多的新冠肺炎图像,让我们结合前两个来源。意大利数据库中的大部分图片已经包含在 GitHub repo 中。但有些不是,所以我们只是手动添加。通过这种方式,我们可以获得目前(2020 年 4 月 7 日)新冠肺炎的所有可用图像,以及一些没有该图像的图像(如果有其他病理或“无发现”,它们将被用作“其他”类别样本)。这里要注意一点:每个患者在数据集的那个部分可以有多个图像,所以 n_patients ≤ n_images 。
为了获得“其他”类的更多图像,使用最后两个源。
- 从胸部 X 射线肺炎数据集中随机选取 450 幅图像,每类以平衡的方式。不考虑患者 id。这样我们得到:
149 例无发现患者的 150 幅图像,
144 例病毒性肺炎患者的 150 幅图像,
144 例细菌性肺炎患者的 150 幅图像。 - 从 NIH ChestXRay-14 数据集中随机挑选 450 张图像:
每 14 种病理状态 30 张图像,另外 30 张图像带有“未发现”标签。具有一种目标病理的图像也可能包含其他病理。所以这部分数据集几乎平衡。
图像的采集方式使得该子数据集可能仅包含某个患者的一幅图像。换句话说,我们得到了 450 个独特的病人图像。
接下来,我们把所有的数据结合起来。以下是生成的数据集统计数据:
所有图像的尺寸都调整为 564x564。计算数据集中图像的平均值和标准偏差。
2.2.培养
让我们使用 DenseNet-121 作为模型的主干(它几乎成为处理 2D 医学图像的默认选择)。由于我们的新冠肺炎数据集太小,无法从头开始训练模型,让我们首先在 ChestXRay-14 上训练我们的模型,然后使用预训练的模型进行权重初始化。
处理医学图像时,确保同一患者的不同图像不会进入训练/验证/测试集至关重要。为了解决这个问题,由于新冠肺炎图像的缺乏,我们决定对患者使用 10 倍交叉验证进行训练。
为培训进行了以下数据扩充:
- 随机旋转(<15°),
- Random crop (512x512),
- Random intensity shift.
For evaluation, we used only center crops (no TTA).
计算的平均值和标准差用于增强后标准化图像。
对网络进行了修改,以便为这些类生成两个逻辑(“新冠肺炎”和“其他”)。数据是不平衡的,所以我们选择加权二进制交叉熵作为损失函数。还使用了软标记:一键编码标记平滑 0.05。当我们对患者进行交叉验证时,两个类别的图像数量会从一个折叠到另一个折叠发生变化,因此我们会实时计算每个折叠的每个类别权重。
使用带有 AMSGrad 的 Adam optimizer 来训练网络。其他超参数和代码可以在项目报告这里找到。ROC AUC 模型验证集上的最佳值保存在每个折叠中。
2.3.结果
所得到的模型形成了用于进一步分析的集合。所有验证倍数指标的平均值:
ROC AUC: 0.99387,
准确性:0.95046。
为了进行测试,我们使用了来自 GitHub repo(2020 年 4 月 7 日至 22 日添加的)的新正面(PA 或 AP 视图)X 射线图像。
和需要平衡(“新冠肺炎”和“其他”)类别的图像数量是从从 ChestXRay-14 中随机选取的未用于训练的患者图像中添加的(由于它们是随机选取的,从统计上看,它们中的大多数都带有“无发现”标签)。所有这些带有相应标签的图像组成一个测试集。
测试集上的每个标签统计信息:
常见的指标有:
还不错!看起来我们有了一个坚实的胸部 x 光新冠肺炎分类器。
对于一些读者来说,结果可能看起来令人信服,但其他人可能会有“这里有问题”的感觉。
3.真的管用吗?
让我们使用更多的数据来评估我们的分类器的性能。
3.1.进一步分析
首先,让我们看看分类器在 ChestXRay-14 数据集的其余部分(未在训练中使用)上的性能统计:
由于在该数据集中没有新冠肺炎病例,那么我们唯一可以声称的是,我们的分类器在该数据集上具有相当好的特异性(0.99235) 。
此外,您可以看到,在“肺炎”和“浸润”等类别上没有假阳性峰值,这些类别可能与新冠肺炎 x 光照片类似。这是否意味着人工智能算法可以将新冠肺炎病与其他类似的疾病区分开来?
其次,让我们来看看分类器在不可见 专有数据上的表现。使用的数据集只有“正常”和“异常”标签。该数据集中没有新冠肺炎阳性患者图像。
特异性显著下降(至 0.69333)。分类器现在好像不太好。发生了什么事?
第三,我们来看看 GitHub repo 关于新图片(2020 年 4 月 7-22 日)的详细结果,有新冠肺炎案例。
综上所述,我们得到:
重新计算指标后,我们已经可以看到一些东西:
已经不是“还不错”了。我们现在可以看到真相:我们的分类器是垃圾。让我们好好想想。
3.2.讨论和要点
正如前面提到的,结果精度表明分类器无法区分图像中的新冠肺炎特定模式(记得放射科医生说,在胸部 X 射线图像中没有多少特定的到新冠肺炎模式)。但是分类器学到了什么,为什么它在 GitHub repo 和 ChestXRay-14 数据上表现良好?
分类器学习从“其他”类的数据集中挑选的图像看起来如何。它还了解到,任何病理模式都意味着它是“新冠肺炎”,“T2”,因为图像看起来不像是来自“其他”数据集。
所以,一般来说,分类器学会了区分一些病态的和看起来不像“其他”图像的东西。

患者的原始图像,带有分类器对新冠肺炎的预测(左),对应的 GradCAM(右)。
这就是为什么它在我们的专有数据集(包含看起来不像“其他”图像的图像)上将几乎每三张图像标记为“新冠肺炎”。
分类器知道正常和异常图像之间的一些差异。每隔 3 个异常图像和每隔 5 个正常图像标记为“新冠肺炎”。至少我们的努力没有白费:)
尽管在训练时进行了强大的数据扩充,仔细的患者 k 倍交叉验证,以及加权损失函数,分类器在真实世界的数据上表现不佳。
我们鼓励任何感兴趣的人重复我们的实验。实际上,你不需要任何专有数据,你可以只从“其他”类中排除一个数据集,并将其作为“不可见”使用。
我想指出两个要点:
任何神经网络总会试图找到解决任务的最简单方法。
仔细查看验证模型性能的数据。不仅仅是光秃秃的数字。
在这一点上,我并不是说绝对不可能在胸部 x 光片上找到任何新冠肺炎特有的模式。有可能某种特定的东西确实存在,人工智能能够捕捉到它。但在以下情况下,这是绝对不可能的:
- 神经网络是根据少量数据训练的
- 当某个特定类别的图像与数据集的其余部分存在显著差异时
所有的源代码都可以在我们项目的 GitHub repo 获得。如果你有任何问题,请随时联系我。
人工智能将为安全返回工作场所提供动力。以下是方法

疫情还没有结束。如何安全地迎接员工重返职场?
想象一下你在隔离几个月后回到办公室的第一天:你不仅可能在早上的通勤途中暴露于病毒之下,而且随后你将面对拥挤的电梯。
当你进入楼层时,你会注意到门把手可能已经被你前面的几十个人碰过了,而且受限的工作空间很容易违反社交距离协议。这种情况很难让你放松,更不用说帮助你回到办公室工作的状态了。

克里斯蒂安·埃尔富特在 Unsplash 上拍摄的照片
这就是为什么组织在欢迎他们的团队回到工作场所时采取严格而谨慎的措施是至关重要的。许多企业没有意识到的是,人工智能(AI)如何能够将更普遍的健康和安全协议推向新的高度。
该技术可以让团队以最安全的方式获得面对面协作的好处。以下是方法。
人工智能允许你安排谁回来,什么时候回来

所以,你打算邀请你的员工回到办公室。了解什么是最有效的方式来组织谁来,在什么日子来,来多长时间是一项复杂的任务——尤其是如果你有超过 50 名员工的话。这就是人工智能驱动的调度和规划工具的用武之地。
组织必须首先了解工作活动、员工任务的性质、客户互动的种类、会议时间表以及期望在现场协作的人员名单。
您必须将此与每个员工的风险级别评估结合起来。这可能包括一些因素,如他们在工作中的暴露程度、工作场所的类型以及需要与公众进行身体接触的程度。它还可以包括员工的家庭所在地、年龄、先前存在的状况,以及雇主可以(在道德上)用来保护他们和他们的团队的任何其他信息。
机器学习可以使用这些因素来平衡工作的关键程度和风险水平,并帮助制定出重返工作的时间表。该算法可以通过考虑典型工作场所阻塞点的允许容量来帮助规划一天内的时间表。这包括像电梯这样的位置或用于社交聚会的区域,它们可能是办公室内的高风险区域。
您必须根据不断变化的组织优先级、病毒控制的有效性和政府对企业的指导方针,不断调整这些计划。这份麦肯锡报告概述了不同类型工作场所的风险因素,可以作为一个有用的参考点。
人工智能让你确保安全协议得到遵守

一切照旧早已成为过去。再次和同事们在一起不会有挤在咖啡机旁或者在自助餐厅里分享拥挤的桌子的奢侈。现在,在工作中,社交距离是不可协商的。人工智能如何帮助确保员工在工作场所的安全?
人工智能可以帮助企业在员工和客户进入设施时处理他们的大规模体温筛查数据。加拿大公司 PredictMedix 提供其人工智能体温检测技术来帮助零售商店防止新冠肺炎的传播。
人工智能驱动的计算机视觉工具可以自动监控工作场所,以确保人们戴上口罩,并与同事保持社交距离。人工智能初创公司 DatakaLab 使用巴黎地铁系统的安全摄像头来检查乘客是否戴着口罩。
这些系统通过匿名检测一个人是否戴着面罩,避免了面部识别技术中有争议的元素。任何违规行为都可以报告给管理团队,让他们识别并采取适当的纠正措施。

社交距离探测仪— 登陆 AI 演示
这项技术可以扩展到检测办公室内的社交距离何时被打破。LandingAI 已经开发了一个人工智能的工具,它可以分析实时视频流来估计人与人之间的距离,这可以用来立即识别违规行为。
许多组织正在探索使用物联网驱动的可穿戴设备,当用户彼此过于接近时,这些设备会向用户发出警告。组织可以分析这些数据,以了解办公室中的位置以及导致违反协议的情况。
虽然身体健康和防止病毒传播必须是当务之急,但帮助员工在艰难时期保持心理健康也至关重要。人工智能解决方案可以分析短信,以识别压力、抑郁或焦虑的潜在指标。
例如,StatusToday 的 AI 解决方案连接到组织内的电子邮件、聊天和通信系统,以识别可能处于精疲力竭边缘的员工。
人工智能推动恢复规划

Gramener 的联系人追踪应用程序— 演示
无论你为安全返回工作场所做了多少准备、策略和计划,在病毒被完全击败之前,感染的可能性总是存在的。在人工智能的帮助下,你如何制定正确的流程来处理团队成员对新冠肺炎呈阳性的事件?
接触追踪解决方案可以帮助您使用可穿戴设备、生物识别技术或门禁卡了解员工在工作场所的移动情况。如果一名员工被感染,您可以确定与此人有密切接触的同事。接触追踪可以帮助您识别和隔离有风险的员工,而不是让所有员工远程操作。
尽管采取了所有重开办公室的措施,但很可能在未来几个月内,相当一部分员工将不得不远程办公。您必须继续利用促进远程工作的数据分析和智能协作应用程序,以确保您的远程团队保持高工作效率。

人工智能具有促进安全返回工作场所的巨大潜力,无论是办公室、仓库还是零售店。然而,贯穿所有这些计划的一条主线是对数据收集水平的关注,以及对其运作所必需的监控。
虽然这是一个合理的担忧,但必须在疫情的背景下看待这些举措,以及与之斗争的必要条件。如果公司和员工希望确保安全,同时避免任何形式的数据收集,那么我们可能没有可信的选择来重新工作。
现实情况是,必须在不损害员工健康和安全的情况下,对数据收集的程度做出判断。虽然我们已经提出了一些可供我们选择的技术,但每个组织都必须根据自己国家的规范,决定哪些技术适合自己的文化。
重要的是,在监控水平和使用数据的方式上,你要对你的员工公开透明。遵循最佳实践,真诚地收集数据,并致力于在风险水平下降时降低监控程度。
与此同时, AI 可能就是那个不仅能让你的团队生存下来,还能在疫情的其余地方茁壮成长的东西。
这篇文章最初是在 IT Pro 门户网站上发表的。增加了插图。标题照片由* 埃德温·胡珀 上Unsplash*。
我不会抢走你的工作。循环和条件可能会。
我们真的需要复杂的人工智能来取代人类吗?
在过去的几年里,有太多关于人工智能的谈论,以及它如何对我们的工作有害——通常是在声称它只会帮助我们更好地工作之后。人类的角色将是做工作中人的部分——因此是与客户的交流和所有你可能讨厌的东西。

在我继续说下去之前,我想做一个简短的声明:这篇文章可能会有偏见,而且是在考虑东欧文化的情况下写的。我写的东西可能在世界其他地方不适用,所以在跳到评论区之前请记住这一点。
好了,说到这里,我们可以回到正题了。
我对世界教育的主要看法是,一个人必须接受高等教育,才能有一份收入更高的工作和更好的生活保障。
虽然在某些情况下这是真的,但在其他情况下,这与事实相去甚远。今天,至少在我的国家,拥有硕士学位的人正在从事 20 年前只需要高中文凭的工作。花点时间想想这有多疯狂——现在你需要在学校多呆 5 年,就为了在你父母工作过的地方工作!
我打算在下一节用一个小故事来支持这个观点。
让我给你讲个故事
大约一周前,我在银行开了一个商业账户。没什么特别的,基本上你和工人坐在一起,签署 10 份文件。然后,过了几天,账户准备好了,我又回去了,又一次只签了文件,但这一次文件堆得没完没了。
这个故事有什么意义,你可能会问。嗯,重点是,这个在银行工作的人需要有硕士学位(或在一些罕见的情况下有学士学位),才能分发和准备要签署的文件。
由 Giphy
当然,我不认为所有在银行工作的人都是在准备文件并把文件发给当事人,等待他们签字。但对他们中的一部分人来说,这很好地描述了他们的工作。
这种说法不仅适用于银行业,也适用于大多数公共行政部门。想想你最后一次排队,只是为了听你听到的前一个人(和你听到的后一个人)说的同一句话,只是因为你需要提交一篇论文,而这篇论文由于某种原因无法在线提交。
这是不对的。
结论 —教育水平不能保证工作安全(自动化方面)。
哪里出了问题
我并不是说银行或公共管理部门(或任何严格意味着遵循程序的部门)的工作不好,但你为什么需要 5 年的大学才能申请一个初级程序跟随者?
由吉菲
在工作的头几个月,你会学到所有需要的东西。句号。
现在我们在谈论人工智能接管类似的工作。人们很害怕。但是为什么你需要人工智能来编写循环和条件呢?
人们担心人工智能会接管他们的工作,而事实是,在计算机编程发明的那一刻,他们的工作就可以自动化,程序员学会了如何写“如果”和“for”。
就这么简单——如果有一个程序可以遵循,那么你就不需要人工智能,因为你真的不需要有人去思考,只是去执行。凡是能描述的都可以自动化。如果你的工作是遵循一个程序,那么对 AI 的要求是不存在的,因为它可以被线性编程。
问题依然存在— 为什么遵循流程的工作没有实现自动化?
作业自动化的主要问题
一些工作已经实现了自动化,这是一件好事。我这样想的原因是多方面的,但归结起来就是:
- 有些工作并不打算由人类来做(因为这些工作在体力上非常困难)
- 别人让你无聊到死(谁愿意一天 1/3 的时间都在无聊中度过)
但是这一节将讨论工作自动化的主要问题,至少从我的观点来看是这样的。这些是:
- 没有人可以责怪——你知道一个你忘记写的测试,它在生产中咬你的屁股?这同样适用于这里。如果一项工作是自动化的,那么如果一切都不顺利的话,老板就不会对任何人大喊大叫。
- 缺乏人情味——我们是社会人,因此喜欢社交和结交新朋友。机器只是机器,因此无法提供适当的人类交流方式。
现在,在下结论之前,让我们花点时间来讨论一下工作自动化的利弊。
工作自动化的利与弊
当我们谈到优点时,我认为有两方面可以受益:
- 雇主们——自动化的东西不会做错事情(如果自动化正确的话),不需要每个月发工资,也不会有一天不顺心
- 你——没错。还记得上面的排队等候的例子吗?还是银行的那个?这可以很容易地自动化,并在网上完成,节省你的时间和神经。
但是当谈到缺点时,我将只深入讨论一个——但是阻碍自动化的那个——伦理问题。
剥夺人们努力获得的工作是错误的吗?成千上万的家庭会面临风险吗?
做决定不那么容易吧?
由吉菲
带回家笔记
这不是一个容易谈论的话题——有太多不同的观点和意见。如前所述,整篇文章是基于我生活的地方的情况,我希望你生活的地方情况更好(更像 21 世纪)。
说了这么多,我能得出什么结论呢?
首先,我不明白谈论人工智能以及如果你的工作可以被一个简单的 Python 脚本取代,它将如何取代你的垃圾观点。没有必要担心,就目前而言,伦理问题似乎超过了利益。如果你的工作不能被简单的线性规划取代,那么我认为 AI 有一天会帮助你做出更好的决定,并从本质上让你更好地完成工作,至少现在是这样。
从我的角度来看,作为一个对我的技术能力相当自信的人,同时也是一个企业主,如果工作可以以任何方式自动进行——使用简单的如果和 for,或者通过实现更复杂的机器/深度学习算法,我甚至不会考虑雇佣某人。
但这只是我的观点,你有权拥有你的观点,所以请在评论区与我分享。感谢阅读。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
西雅图的 AirBnB 房屋:数据驱动的外观
分析受欢迎程度、需求和价格。

来源:谷歌图片
简介
过去几年来,AirBnB 对现有的酒店公司构成了严重威胁。2018 年,AirBnB 在美国的市场份额在 18%左右。AirBnB 的多功能性,从在大城市市区租房到在树林里租树屋,使它成为如此大的竞争对手。
在本帖中,我们将看看西雅图的 AirBnB 房源。在这个分析中使用了两个主要数据集:列表数据,关于西雅图的 3818 个列表的信息,以及日历数据,给出一年中所有列表的每日可用性。数据集可以从 kaggle 下载。

在对数据进行初步评估后,我遇到了三个问题,激发了我的兴趣:
西雅图什么街区最受欢迎?
这些地段的房源租金分布如何?
一年中去西雅图最忙的时候是什么时候?在这段时间里,价格是如何变化的?
所有用于分析的代码都可以在 GitHub 上公开获得。
入门指南
加载数据
所有数据文件都是逗号分隔值(CSV)格式。使用 pandas 可以很容易地将它们加载到数据帧中。calendar_df文件的输出如下所示:
listing_id date available price
0 241032 2016-01-04 t $85.00
1 241032 2016-01-05 t $85.00
2 241032 2016-01-06 f NaN
3 241032 2016-01-07 f NaN
4 241032 2016-01-08 f NaN
这需要稍微解释一下:available 列只包含两个值:t或f,分别代表“真”或“假”,它显示一个列表何时可用或不可用。另外,price 列中的很多值为空。这是因为当一个列表变得不可用时,它的价格就变成了NaN(不是一个数字)。
同样,listings_df文件有关于清单的详细信息:

listings.csv 文件中的示例内容
数据准备
calendar和listings数据帧的price列都有一个字符串数据类型,很难进行算术运算。为了进一步分析,我们必须将其转换为数值数据类型。
现在,检查数据帧是否缺少值:
id 0
zipcode 7
latitude 0
longitude 0
number_of_reviews 0
review_scores_rating 647
property_type 1
room_type 0
bathrooms 16
bedrooms 6
availability_30 0
availability_60 0
availability_90 0
availability_365 0
price 0
正如我们所看到的,有几列缺少值。在回答我们最初的问题之前,处理它们是很重要的。
我们发现值为review_scores_rating的列表没有评论。这是有道理的,因为评级是基于评论的。这些列表对于我们的案例来说不是很有趣,所以我们将删除它们。
zipcode列有 7 个NaN值。我们可以删除它们,但让我们尝试使用所谓的反向地理编码来获取这些位置的邮政编码值。我们将使用latitude和longitude的值来获得zipcode 的值(我们跳过了这个细节以避免跑题,但感兴趣的读者可以在GitHubrepo 中看到)。
所有其他列缺少的值并不重要,因为我们无论如何都不会使用这些列值。
现在,随着数据清理的进行,我们可以专注于分析了。
问题 1:西雅图的哪些街区最受欢迎?

虽然一个列表的受欢迎程度取决于很多因素,如物业类型、位置、提供的便利设施、价格等。我的流行度标准基于两件事:一个是一年至少三个季度不可用的列表,另一个是评论评级高的列表。现在,我对至少 9 个月不可用的标准有点模糊,因为这可能有几个原因,如主机在列表中进行翻新或主机不可用于维护列表。更好的标准是查看availability_30、availability_60、availability_90和availability_365列的可用性百分比。这些列分别给出了 30 天、60 天、90 天和 365 天中列表可用的天数。
根据可用性检查过滤后的features_df

每个街区的列表数量
正如我们所料,在 30、60、90 和 365 天内至少有 70%不可用的列表通常具有较高的总体评分。这意味着尽管有许多其他因素在起作用,但我们的标准或多或少是正确的。
要找到最受欢迎的列表,我们需要两件东西:一个是给定邻域中的列表数量,另一个是正确代表该邻域列表评级的单一聚合指标。下图显示了不同邮政编码的评级分布情况:

从上面的方框图可以清楚地看出,除了 7 个评级(满分 275 分)之外,所有评级的得分都至少为 80%。几乎全部的中值都在 90%以上。因此,用某种度量来聚合这些值是有意义的。我们将使用平均值,因为它会比使用中位数更严格一些。在使用 mean 作为聚合并将列表按邮政编码分组后,现在它们可以显示在地图上了。

将链接到互动地图
问题 2:这些地点的房源租金分布如何?

用邮政编码分配租金

在上面的图中,有几个租金超过 400 美元的离群值。我们会尽力找出这些房源是什么样的。但首先,让我们来计算这些位置的中间价格。
正如我们在左边看到的,中间价格变化很大,但主要集中在 80-120 美元之间。
大多数标价超过 400 美元的房源都是至少有 3 间卧室和 2 间浴室的整栋房子,这也解释了为什么它们会这么贵。然而有一个例外,那只是一套公寓,却是最贵的一套(1000 美元)。让我们来看看:

这个列表最贵是有道理的——它位于市中心,非常靠近城市的所有主要景点。
问题 3:一年中去西雅图最忙的时候是什么时候?
找出最繁忙的访问时间可以通过每月检查列表的可用性来完成。为了实现这一点,我们需要从calendar_df的date列中获取月份,然后应用 pandas datetime 操作。

正如我们所看到的,夏季尤其是七月、八月是游览西雅图最繁忙的时候,而可供选择的景点却最少。此外,由于需求旺盛,这几个月的挂牌价格最为昂贵。
结论
在这篇文章中,我们查看了来自西雅图的 AirBnB 数据,以了解三个主要的兴趣领域:人气、需求和价格。
虽然有许多因素被忽略了,但它仍然揭示了一些真正有趣的见解。
分析的主要要点如下:
- 大多数房源位于市中心附近,其中位于邮政编码为 98102 和 98122 的房源最受欢迎。一般来说,他们的评分非常高,达到 90%的评分。
- 大多数地点的房源价格在 80-120 美元之间。
- 夏季的几个月,特别是七月和八月,是去西雅图的高峰期,平均租金高达 150 美元。
这种分析有很大的扩展范围,包括:
- 评论的情绪是否正确地代表了总体评分?
- 还有哪些因素增加了房源的受欢迎程度,它们如何影响房源的价格?
- 价格的时间序列预测以及它们与来自 AirBnB 的最新数据的吻合程度如何?
Airbnb-A 部分(Python-可视化、比较研究、回归)
通过与华盛顿 DC 的对比研究、回归模型、互动地图
和自然语言处理,分析了西雅图 Airbnb 的情况。向市议会和旅行者提出建设性的建议

B 部分:可以在这里找到
自 2008 年以来,Airbnb 帮助客人和主人以更独特、更个性化的方式旅行。该公司从一个出租的充气床垫发展到价值超过 300 亿美元的全球合作,这都要归功于其精力充沛的创始人布莱恩·切斯基。2020 年应该是 Airbnb 的黄金年,因为它将上市并发行世界上最受追捧的股票。悲剧的是,冠状病毒发生了。旅游业被疫情摧毁了。Airbnb 现在面临着烧钱、愤怒的房东和不确定的未来,因为 2000 名员工可能会被解雇,还有数十亿美元的高利率债务,这些债务是为了偿还客户而建立的。(研,2020)
尽管如此,随着六月的到来,情况开始好转。Airbnb 报告称,5 月 17 日至 6 月 3 日期间,美国房源的预订量超过了去年同期。在成功抗击病毒的国家,如德国、葡萄牙、韩国和新西兰,国内旅游也有类似的增长。像 Expedia 和 Booking.com 这样的其他公司也见证了国内度假租赁预订的激增。几个月来被压抑的需求导致夏季预订热潮,因为越来越多的人希望逃离他们的家庭冠状病毒避难所。现在,Airbnb 的房源比危机前更多,主要集中在传统的度假租赁市场,美国的顶级目的地。它们是南加州的大熊湖、田纳西-北卡罗来纳边境的烟雾山和德克萨斯州的阿兰萨斯港。(卡维尔,2020) 尽管如此,任何反弹都来自一个非常低的基数,切茨基在 5 月份的电话会议上表示,他预计今年的收入将达到 2019 年上半年的水平。他说,今年上市仍是一个选择,但他将等待市场稳定下来,然后再做出最终决定。
作为一名之前接受过培训、现居住在西雅图的酒店经营者,我想分两部分做一个关于西雅图 Airbnb 现状的分析项目。第一部分是对西雅图和 DC 华盛顿州两个城市的比较研究。西雅图和华盛顿 DC 地区位于美国的两端,因为不同的原因而广为人知:分别是科技和文化中心与政治中心。此外,它们拥有相似的人口规模(刚刚超过 700,000)和多个列表(8740 和 9369)。然后,在第二部分,我们将从政府立场和游客的角度更深入地了解西雅图的市场,并推荐不仅有利于 Airbnb,还有利于这座城市及其市民的解决方案

数据集可以在 Airbnb 开放数据源下载。它们包括
清单 : 详细清单数据
清单 _ 详细信息: 清单的汇总信息和指标
点评 : 详细点评
reviews _ details:汇总评论数据和列表 ID(便于基于时间的分析和链接到列表的可视化)。
日历: 详细日历
邻居 : 地理过滤器的邻居列表。来源于城市或开源 GIS 文件。
neighbors . geojson:城市的街区 geo JSON 文件。
数据集获取于 2020 年 4 月 23 日。西雅图有 7237 个值,而华盛顿 DC 有 9342 个值
I/数据探索
当我们导入两个城市的“listings”数据集时,我们将 encoding='latin1 '指定为参考,以避免遇到 UnicodeDecodeError 错误:“utf-8”编解码器无法解码错误。所有西雅图的相关数据集将被命名为“sl ”,而 WashingtonDC 有“wl”。然后,我们就从数据准备部分开始。“列表”数据集有三个步骤。
第一步: 通过一个函数运行两个数据集,清洗所有数值数据。为了解决这个问题,它包括多个子功能:从两个数据集(访问、交互、house_rules 等)中识别所有我们不需要的不相关因素。),删除所有只有唯一值的列,如 id 或 url 链接(ID、listings_url 等。),添加另一个用于审核的列,将所有“价格”列转换为数字,将所有百分比列转换为浮点数,生成新的审核指标,并删除原始审核列

(图片作者)
第三步:从两个城市的“列表”数据集中检查定量信息。由于 Seattle 的“listings”的干净版本与 Washington DC 的“listings”相比具有更少的列,分别为 29 和 33,我们将检查哪个列出现在一个表中而没有出现在另一个表中:

(图片作者)
II/可视化和回归分析
1)AirBNB homes 房产对东西海岸的房价有什么影响?**
从各自的角度来看,西雅图和华盛顿 DC 的价格区间有很大差异,前者比后者差得多。西雅图的房间价格最高只能达到 1200 美元/晚,而华盛顿 DC 最贵的房间价格是这个数字的两倍多(3000 美元/晚)。除了精品酒店是西雅图和华盛顿 DC 最昂贵的酒店之一,西雅图的飞机乘客喜欢住在法律和别墅,而那些访问华盛顿 DC 的人更喜欢入住酒店而不是其他类型的酒店。同样值得一提的是,西雅图所有房地产类型的价格波动都较大。这意味着您可以选择经济或奢侈的方式在翡翠城逗留。然而,如果我们看得更近一点,我们会发现其他类型的房地产价格,如住宅、公寓、宾馆,无论位置如何,价格都在 100-200 美元/晚之间。因此,旅行者在 Airbnb 上预订时不会注意到两个城市之间不成比例的价格区间差异。

(图片作者)
在西雅图,旅行者更喜欢拥有一张真正的床,或者至少是一张折叠沙发,用于整个家庭、私人房间和酒店房间,这解释了为什么它们是这些类别中最贵的床。令人惊讶的是,在合住客房类别中,客人的期望大幅下降,其中大多数人对充气床垫感到满意,尽管与所有其他房间类型中的其他床类型相比,充气床垫可能同样昂贵(最多 500 美元/晚)。这种奇怪现象的一个原因是大量的季节性节日集中在艺术、文化、音乐等方面。整个夏天。 (Bell et al .,2019) 参与者往往是 20-30 岁,适应性更灵活,因此,在旺季共用房间里昂贵的充气床垫总比没有住宿好。相反,在 DC 的华盛顿州,除了酒店房间,充气床垫是所有房产类型中的首选。西雅图和华盛顿 DC 的床类型的价格范围没有区别,而后者的酒店房间的真正的床比前者(平均约 200 美元/晚)贵两倍(平均 600 美元/晚),并且分布更稀疏(50-1200 美元/晚)

(图片作者)
一般来说,床的数量和浴室的数量是正相关的,客人需要的床和浴室的数量越多,价格越高。然而,在达到一定数量的床(11)和浴室(6-6.5)后,相关性就变成了负的。因此,我们可以假设,因为有规定,任何预订超过 12 张床或 6 个浴室的客人将获得团体折扣。西雅图的床位和价格之间的关系比 DC 的华盛顿稳定且分布均匀。根据上述城市热爱节日的原因,人们可以相信,当在一次入住中接待大量客人时,当地的酒店经营者和主人会更加熟悉。同样重要的是,与床相比,浴室对价格变化的影响更大。分布负向偏左,分布不均匀,因为有少量波动。例如,在西雅图,4.5- 5 间浴室的价格从 600 美元/晚下降到 100 美元/晚,然后反弹到 1000 美元/晚。

(图片作者)
另一方面,在西雅图和华盛顿 DC,卧室和住宿与价格的相关性是严格正的,左偏的。这些价格范围也彼此相似,客房为 100-2000 美元/晚,住宿类为 100-800 美元/晚。有趣的是,西雅图最多有 8 间卧室,而在华盛顿 DC 是 27 间,西雅图最多有 25 间,而在华盛顿 DC 是 16 间。我们可以得出结论,那些去西雅图过夏季节日的人只需要在再次出门前洗个澡,而不是呆在家里,所以他们不介意睡在合租公寓里不舒服的充气床上。这种现象表现为 7 至 8 间卧室的房间价格猛增 600 美元。

(图片作者)
2) 哪些房东的行为或资料会影响东西海岸 AirBNB 房客的评论?
为了回答这个问题,我们将创建热图来展示 Airbnb 在每个城市的评论和行为特征之间的相关性。有四个步骤
步骤 1: 将所有六个分类列转换为虚拟变量,以进一步对它们进行评估:“host_response_time”、“host_has_profile_pic”、“host_identity_verified”、“host_is_superhost”、“instant_bookable”、“cancellation_policy”
第二步: 将虚拟变量列合并在一起
第三步: 只需从组中只保留促成行为相关的相关因素列。有些因子内部有大量的值,因此我们还需要剔除一些最多余的值,如“一周内的主机响应时间”,因为它们仅适用于少数数据集。
步骤 4: 使用 seaborn.heatmap()函数创建西雅图和华盛顿州 DC 的热图
对于西雅图的 Airbnb 来说,相关性相对较低,最高的是‘host _ is _ super _ host’和‘new _ review _ metric’之间的 0.39。这意味着你的列表的审核分数取决于该主机是否是西雅图的超级主机。另一方面,华盛顿 DC 的 Airbnb,积极方面的相关性相对较高,消极方面的相关性类似,最高的是“主机 _ 响应 _ 速率”和“主机 _ 接受 _ 速率”之间的 0.55。这意味着,如果华盛顿 DC 的主人阅读了你的信息,他/她有 55%的几率会接受你的 Airbnb 预订请求。

(图片作者)

(图片作者)
3)AirBNB 房源哪个是点评中最重要的一个?——【回归分析】**
为了了解各种因素如何影响最终评审分数,我们将借助随机森林方法进行回归分析研究,然后举例说明。数据预处理包括:删除不相关的变量和缺少评论值的行,用它们的平均值填充缺少的数字列,为分类变量创建哑元。x 是所有独立因素,而 y 以“new_review_metric”作为因变量,并以 0.75/0.25 的比率拆分这些数据表。对于回归变量,我们将使用(n_estimators=100,criterion='mse ',random_state=42,n_jobs=-1。最终的模型精度和验证如下。结果彼此非常相似,均方误差较低,R2 较高,这表明预测值和可用因变量之间的差异很小,我们可以解释超过 90%的观察到的变化可以通过模型的输入来解释。

(图片作者)
在独立特征对评论的重要程度的可视化中,我们可以看到,与西雅图相比,在华盛顿 DC 的第一和第二高度重要特征之间存在更大的差异。此外,在预订 Airbnb 时,“女王城市”的游客更重视主人本身的质量,而不是酒店或房间,这与美国首都的模式相反。西雅图的“价格”排名也较低,这是因为如上所述,该城市的平均租赁价格适中。

(图片作者)
****待续 B 部分 ****
参考&来源:
贝尔,j .,弗里德曼,e .,塞尔林,k .,&泽尔曼,J. (2019 年 7 月 17 日)。本周末,西雅图地区将举办 46 个节日。陌生人。https://www . the strange . com/things-to-do/2019/07/17/40789078/46-festivals-to-check-out-in-Seattle-this-weekend
奥卡维尔 (2020 年 6 月 8 日)。Airbnb 发现度假租赁需求激增。洛杉矶时报。https://www . latimes . com/business/story/2020-06-07/Airbnb-冠状病毒-需求
研,K. (2020 年 4 月 8 日)。 Airbnb 的冠状病毒危机:烧钱、愤怒的主机和不确定的未来。华尔街日报。https://www . wsj . com/articles/airbnbs-coronavirus-crisis-burning-cash-angry-hosts-and-an-uncertainty-future-11586365860
— — —
数据集:http://insideairbnb.com/get-the-data.html
灵感来源:https://www . ka ggle . com/Xi chenlou/Seattle-and-Boston-Airbnb-data-comparison
Airbnb-B 部分(Python-交互式地图,自然语言处理)
通过与华盛顿 DC 的对比研究、回归模型、交互式地图
和自然语言处理来分析西雅图的 Airbnb 情况。向市议会和旅行者提出建设性的建议

西雅图的可爱明信片(图片由作者提供)
来自甲部的介绍
自 2008 年以来,Airbnb 帮助客人和主人以更独特、更个性化的方式旅行。该公司从一个出租的充气床垫发展到价值超过 300 亿美元的全球合作,这都要归功于其精力充沛的创始人布莱恩·切斯基。2020 年应该是 Airbnb 的黄金年,因为它将上市并发行世界上最受追捧的股票。悲剧的是,冠状病毒发生了。旅游业被疫情摧毁了。Airbnb 现在面临着烧钱、愤怒的房东和不确定的未来,因为 2000 名员工可能会被解雇,还有数十亿美元的高利率债务,这些债务是为了偿还客户而建立的。(研 2020)
尽管如此,随着六月的到来,情况开始好转。Airbnb 报告称,5 月 17 日至 6 月 3 日期间,美国房源的预订量超过了去年同期。在成功抗击病毒的国家,如德国、葡萄牙、韩国和新西兰,国内旅游也有类似的增长。像 Expedia 和 Booking.com 这样的其他公司也见证了国内度假租赁预订的激增。几个月来被压抑的需求导致夏季预订热潮,因为越来越多的人希望逃离他们的家庭冠状病毒避难所。现在,Airbnb 的房源比危机前更多,主要集中在传统的度假租赁市场,美国的顶级目的地。它们是南加州的大熊湖、田纳西-北卡罗来纳边境的烟雾山和德克萨斯州的阿兰萨斯港。(卡维尔,2020) 尽管如此,任何反弹都来自一个非常低的基数,切茨基在 5 月份的电话会议上表示,他预计今年的收入将达到 2019 年上半年的水平。他说,今年上市仍是一个选择,但他将等待市场稳定下来,然后再做出最终决定。
作为一名之前接受过培训、现居住在西雅图的酒店经营者,我想分两部分做一个关于西雅图 Airbnb 现状的分析项目。第一部分是对西雅图和 DC 华盛顿州两个城市的比较研究。西雅图和华盛顿 DC 地区位于美国的两端,因为不同的原因而广为人知:分别是科技和文化中心与政治中心。此外,它们拥有相似的人口规模(刚刚超过 700,000)和多个列表(8740 和 9369)。然后,在第二部分,我们将从政府立场和游客的角度更深入地了解西雅图的市场,并推荐不仅有利于 Airbnb,还有利于这座城市及其市民的解决方案
在 B 部分,我们将创建一些可视化,交互式地图,并利用西雅图的 Airbnb 2020 房源数据集深入自然语言处理。除了标准库之外,我们还引入了更多专用于创建地图的库(folium,geopandas),可视化库(plotly,cufflinks),自然语言处理库(re,nltk)。

(图片作者)
除了主要用于分析的 listings.csv 和 listings_details.csv,我们还使用了“日历”和“review_details”数据集来帮助我们。正如我们在 A 部分提到的,列表基本上是广告的 id。2020 年 4 月,西雅图有 7237 个 Airbnb 房源。“列表”包含 15 个特征,而“列表 _ 细节”包含 96 个特征。我们没有使用所有可能不相关的列,而是有选择地加入了一些对 B 部分的分析有用的变量。我们还从“主机响应速率”功能中去掉了“%”。

(图片作者)
I/ 探索性数据分析(EDA)
1) 邻里
市中心是西雅图所有商业和专业活动的中心(1250 个列表),这解释了为什么它的列表数量在城市之外的其他街区中排名第二。西雅图市中心附近的其他地区似乎也没有那么受欢迎,因为在首都山只有 775 个房源,中心区只有 600 个,其余的都在 500 个以下。有一种理论认为,旅行者决定住在西雅图之外的原因是因为该市目前房地产价格的飙升。我们将揭示这个有趣的事实如何影响其他列表的因素,如价格和客户对 Airbnb 住宿的看法。对于交互式地图,您可以放大集群,最终找到列表的各个位置(下面是 Github 代码)


(图片作者)
2) 房间类型,物业类型,&每次预订人数
CBRE 酒店的美国研究表明,Airbnb 在西雅图约 80%的收入来自整间房屋的房源,拥有多间整间房屋房源的房东产生的收入在 2015 年至 2016 年间几乎翻了一番。(西雅图市议会,2017) 商业企业喜欢利用在线租赁平台来营销不同位置的多个单元,这可能会加剧西雅图的住房危机定时炸弹,正如你将在本报告稍后看到的那样。不幸的是,2020 年的情况不会更好,整个家庭/公寓占据了绝大多数房源(总共 5700 个),比私人房间高出 3 倍。然而,西雅图迟迟没有通过任何实质性的法律,不像纽约,纽约积极禁止任何房屋出租超过 30 天,直到 2017 年。(道尔顿,2017)

(图片作者)
值得注意的是,有不同的财产清单,但并不是所有的都广受喜爱。为了排除不流行的物业类型,我们创建了一个名为“total”的附加列,根据房间类型统计每种物业类型的列表,并选择超过 100 个的列表。之后,我删除了“总计”列以获得正常结果。房子和公寓是最常见的财产类型。与公寓相比,房屋似乎是整个家庭/公寓列表中不太受欢迎的财产类型,但当涉及到私人房间租赁时,它们更受欢迎。

(图片作者)
一般来说,大多数房源通常喜欢接待少于 5 名客人,其中大多数是 2 人(超过 2700 个房源)。然而,有趣的是,一个 6 人的聚会可以很容易地找到一个合适的过夜场所。这是因为与阿姆斯特丹等其他城市不同,出于对可能的噪音投诉或火灾隐患的担忧,西雅图没有短期租赁的最大容量限制为 4。因此,如果你想开派对,西雅图是最好的选择。

(图片作者)
二/给西雅图市长的建议
众所周知,Airbnb 被指责加剧了全球许多城市的经济适用房危机。(沙夫罗斯,2016) 。为了防止这种情况发生,西雅图的财政和行政服务部强制要求每一个 Airbnb 主机在 2019 年 12 月之前获得短期租赁运营商的许可证。 (Airbnb,2020) 许可证约为 75 美元/单位,每年更新一次。每个短期合同允许您经营最多两个住宅单元:
- 主要居住地: “机动车登记、驾驶证、选民登记或其他此类证明文件记载的人的经常居住地”
- 第二居所 : 度假屋或第二居所
然而,该指南并不是对所有房源都强制执行,对最大单元数量有有限的例外,包括 2017 年 9 月 30 日之前合法经营的短期租赁的一些例外。值得注意的是,如果你在 Airbnb 上经营一家酒店或汽车旅馆,主人将不需要注册短期租赁许可证,但需要申请正式的豁免。
1)
正如上面提到的西雅图定律,我们可以忽略整个 home/apt 值,直接进入私人房间,查看仅两个住宅就有太多列表的极端情况。请记住,Airbnb 没有给出房源的地址,尽管数据库中实际上有“街道”字段。这些当然不是完整的真实地址。Airbnb 会主动隐藏房源的地址,只有在你确认预订后才会透露。因此,人们不能说这些列表实际上是否在同一个房子里。

(图片作者)
通过运行 53 个值中的前 20 个值,可以根据他的列表名称将达里奥的财产分为 4 个不同的组
- 10 分钟车程到市中心
- 距离市中心 5 分钟车程
- 距离西雅图中心 3 个街区
- 私人房间

(图片作者)
此外,当您检查实际的经度和纬度本身时,它们彼此高度相似,只是略有不同。Airbnb 房源上的房间和设施图片无法区分开来:
从各自的角度来看,他似乎在经营一家精品酒店,但归类为短期租赁的许可证,这是专门为 Airbnb 设计的,位于市中心。如果所有的房源都是合法的,达里奥可能会经营一家受到上述不同监管的酒店,或者属于 2017 年 9 月 30 日之前签署的“豁免”团体。如果没有,Airbnb 或市议会应该调查一下情况,并调查达里奥是否违反了规定。不仅是达里奥,还有其他主持人,像维拉,赛义德,香农,李等。应该接受检查。
2) 职业主持人的不良影响
目前,西雅图没有阻止专业托管活动的规定。这种缺点为 Airbnb 将其平台外包给专业主机(第三方房地产公司)的可能性打开了大门。现在,80%的主机只有少于 5 个列表。我们假设拥有比 1 多几个列表的主机也可能是几个朋友的主机。但也有极端的案例(312),这让我们怀疑他们是在专业地做这件事。

(图片作者)
下面,我们显示了包含 20 个以上列表的主机。如果你看一下他们在 Airbnb 上的房源,你会被前三名的每一个房源的标准化和专业性所震撼。因此,我们可以有把握地说,这些是专业的主持人。

(图片作者)
深入了解前三名,我们可以了解更多关于 Airbnb 的运营方式。看起来,除了希望获得一些额外收入的传统主持人的非专业房源之外,Airbnb 还经常与中小型房地产公司建立合作关系。Airbnb 允许这些当地公司将其租赁的房产注册为平台上的正常房源,以产生更多的网络流量来换取佣金。如下表所示,公司参与的条款和程度因安排而异:
“我们是一个充满激情的团队,经营着一家现代化的技术支持的公司住房公司,该公司认为装修精美的高端住宅应该是一致的,负担得起的,易于预订的。”
= >尽管在系统上被注册为“Corp Condos & Apts ”,但所有房源都归 Barsala Barsala 所有,这是一家中型房地产公司,专注于在西海岸提供物有所值的租赁合同。关于 Airbnb 和 Barsala 之间的关系没有太多信息
“宙斯正在改造企业住房。我们通过在遍布旧金山湾区、洛杉矶、华盛顿的 1400 多所房屋中的每一所提供独一无二、无忧无虑、高质量的住房体验来实现这一目标。“宙斯已经成为宙斯的永久合作伙伴”
= >随着 Airbnb 吸收越来越多的住房需求,它正在探索如何将度假租赁以外的机会货币化。长期企业住房市场可能是一个巨大的业务,但 Airbnb 没有自己建设,而是战略性地投资与房地产长期租赁市场的领导者之一 Zeus Living 合作。这是一个巧妙的组合:宙斯的可用属性和 Airbnb 的全球推广平台 (Constine,2019)
“待在有价值的地方。当你预订了阁楼,你就是在为当地社区做贡献。每个阁楼都是当地居民的家,他们就住在这里,确保您的体验是愉快的。所有空间的设计都考虑到了您的舒适度!我们使入住和沟通变得轻而易举,每个家庭都为您的旅行提供了一个美丽舒适的休息场所。每一个 Loftium 家和主人都是独一无二的,在您入住期间,您将获得真正的邻里体验。参观一个新的社区,并在我们的任何一个城市预订 Loftium:西雅图、波特兰、丹佛、圣地亚哥、凤凰城、芝加哥、亚特兰大、达拉斯、夏洛特或奥兰多。我们等不及你来参观了!”
= >从只与 Airbnb 合作租房,创始人决定开发自己的房产租赁应用,同时与 Airbnb 合作。他们的商业策略是,如果潜在租户/买家同意成为 Airbnb 的托管人,就在价格昂贵的地区给予他们荒谬的折扣。Hannah Exner 和 Sam Joselyn 在西湖附近以 1000 美元/月的价格获得了一套豪华公寓,价格超过 1500 美元/月 (Levy,2019)
除了考虑西雅图政府将采取哪些有效措施来确保所有这些商业伙伴关系不会加剧危机之外,这是一个现实和产品差异化的问题。由于一家公司以提供真实体验和当地隐藏的宝石而自豪,这使其在客户眼中的形象高于其他酒店竞争对手,从房地产中介引入这种千篇一律、精心制作的房源可能会削弱该公司独特的价值比例。(拉利奇&维斯迈尔,2017) 。随着时间的推移,即使是大多数死硬的 Airbnb 爱好者也可能会在其他地方寻找“真实性”
三/给游客的建议
1) 每个小区的日均价、点评分数和安全指数
在这一部分中,我们比较了两人的平均每日比率(ADR ),并根据社区进行了评估。我们预计到市中心的距离是最重要的因素,因为所有西雅图的地标都位于市中心。距离和评论分数之间可能有很强的相关性。可能影响审查分数和 ADR 的其他因素包括:
- 位置的安全指数
- 噪音。如果一个房源位于市中心,但在嘈杂的酒吧中,这应该会在位置评论上扣分。
- 如果房源位于市中心以外,但公共交通四通八达,那么它们会得到一些加分(西雅图已经发展了火车和公共汽车系统)
- 附近的必需品和娱乐设施(超市、酒吧、餐馆等)。)
- 包括免费停车。因为在西雅图市中心停车平均要花 20/ 2 小时
有趣的是,与其他酒店相比,安女王酒店的价格要高得多(约 285 美元/天)。然后是市中心(约 165 美元/天),然后是其他街区。令人惊讶的是,不管房源在哪里,平均评论分数都在 9/10 以上,所以不管你选择哪个社区,最大的满意度总是有保证的。我们认为这是因为西雅图总的来说面积小,人口少(总共 100 万)。这座城市的交通也很便利,所以如果他们碰巧住在郊区,往返市中心大约需要 30 分钟

(图片作者)
尽管没有旧金山那么严重,西雅图仍然深受大量无家可归者和乞丐的困扰。大部分是无害的,不会惹你。尽管如此,它仍然对公众形象产生负面影响,并挫伤了游客参观城市的积极性。此外,游客可能经历的财产犯罪比暴力犯罪多 7 倍。如果你开车去西雅图,即使在停车场,你也可能会遭遇入室盗窃。像大多数城市一样,西雅图最安全的地区在市中心以外,往往是住宅区或商业不发达的住宅区。最安全的社区有日落山、巴拉德、木兰、阿尔基、木兰、下皇后安和沃灵福德。西雅图警察局有一张西雅图地区的地图,用犯罪数量进行颜色编码。深蓝色区域意味着病例较多,而浅色区域病例较少

西雅图的犯罪率统计(来源: 西雅图警察局 )
考虑到 ADR、评论评分和犯罪统计数据,建议客户在西西雅图、Magnolia、Ballard、Rainer Valley、Central Area、Seaward Park、Beacon Hill、University District、Interbay 和 Northgate 预订 Airbnb,以获得低廉的租赁价格、最高的安全性和最终的高满意度。我目前住在 Rainer Valley/ Beacon Hill,离市中心开车 20 分钟或坐火车 30 分钟,一切都很近。该地区经历了适度的中产阶级化,因此人们预订 Airbnb 体验既安全又方便。在 Beacon Hill 的一个美丽的星期天烧烤一些令人垂涎的烤肉是生活中最奢侈的事情。

莱纳山谷/比肯山壁画(作者提供图片)
2)如何使用复习分数
与书面评论同样重要的是,客人可以提交总体星级和类别星级。评级分为:
- 总体体验
- 清洁(任何酒店最重要的因素)
- 准确性(广告与产品匹配吗?)
- 价值(有没有被敲竹杠的感觉?)
- 沟通(在你入住之前、期间和之后,主人对你的关注和问题的回应如何?
- 抵达(入住过程顺利吗?)
- 位置
读者可以在下面找到所有这些类别的分数分布。人们不禁对各科的高分感到惊讶。这在 Airbnb 中很常见,因为该公司以向客户提供卓越服务而闻名 (Plautz,2015) 。因为标准如此之高,客人应该只选择在五个因素中至少有四个因素得分为 10 的房源。值是最棘手的一个,因为与其他指标相比,它们的分数明显更高,这使得该因素比其他指标更容易区分。呆在一个在价值上得到 10 分的主机上,即使他们在其他方面可能得分较低,这意味着你可能会中头彩。

所有类别的分数分布(按作者分类的图片)
3)找到一个好的主人
为了对主人的努力表示感谢,Airbnb 授予那些最受尊重的人“超级主人”的地位。成为一个超级主播意味着你可以从你的列表的可见性增加中受益,获得潜在的收入,甚至可以获得独家奖励(陈,2017) 。Airbnb 在其广告活动中展示了一些超级主机的列表,超级主机甚至被邀请发表演讲或分享如何获得这一酷头衔的技巧。为了成为超级主持人,主持人必须拥有 4.7 或更高的平均综合评分,该评分基于其 Aibnb 客人在过去一年中的评论。他们还需要在前一年组织至少 10 次住宿,或者如果这些预订的期限更长,则需要在至少 3 次住宿中组织 100 次住宿。Superhosts 不得有任何取消,除非有情有可原的情况,并需要在 24 小时内回复他们的客户。尽管要克服很多限制,但西雅图的 Airbnb 房源让他们脱颖而出,目前拥有近 3 万名超级房东(约 45%)。对于 Airbnb 的国际超高住宿率(20.2%)来说,这是一个令人震惊的数字

(图片作者)
既然超级旅馆在西雅图如此受欢迎,这就引出了一个问题:超级旅馆是否是选择房间的必要标准之一。一方面,用超高的价格预订可能意味着在住宿上花更多的钱。另一方面,作为一个顾客,我不希望遇到不好的主人,他们经常取消订单,而且总是迟迟不回复。幸运的是,在 Airbnb 上很少会遇到没有回应的主机,大多数主机不到一个小时就能回复,最晚一天之内。如此快速的数字部分解释了为什么西雅图的 Airbnb 充斥着优秀的超级房东。因此,是否是超级主持人是潜在客人不应该大力强调的事情。

(图片作者)
4)可用性和超时平均价格
“日历”文件包含 365 条记录,记录了一年中每一天每个列表的价格和可用性。为了得到正确的结果,我们将共享列 listings_id 上的‘calendar’与‘listings’[‘accommodes’]合并,listings _ id 函数作为左边的索引。合并后的表格示例如下所示,需要注意的是,“f”表示业主不想在特定日期出租其房产,或者房源已经被其他人/第三方预订。

(图片作者)
在未来的 6 个月里,在达到最低点之前,可用的住宿数量会更高。记住,数据是在 2020 年 4 月 23 日收集的。这意味着当时正值美国冠状病毒爆发的高峰期。六个月的正数意味着很多客人在意识到疫情的严重性之前就已经确定了未来的发展方向。因此,10 月 16 日的预订量不到 1100 份,到 2021 年 1 月中旬几乎没有预订量。可供住宿的数量发生如此巨大变化的另一个原因是,房东们正在积极寻找这些租赁房产的其他用途,以在面临危机时保持稳定的收入来源。Airbnb 的预订在人们的心目中是次于最后的。对于交互式地图,您可以放大集群,最终找到列表的各个位置(下面是 Github 代码)

(图片作者)
由于 2 人住宿很受欢迎,我们只选择 2 人的可用房源,并使用 mean()函数计算平均值。7 月 27 日星期六,ADR 达到 127 美元的峰值,这种愤世嫉俗的模式是由于周末的价格更高。随着时间的流逝,价格急剧下降。我怀疑这是 COVID 和 host 最后一刻降价努力的影响,这证明 Airbnb 需要一些时间才能再次盈利。

(图片作者)
然而,这并不是世界末日。据报道,西雅图的阳性病例和死亡人数已经从曾经的全国冠状病毒中心大幅下降。这都归功于华盛顿人的努力,特别是西雅图人,他们一直遵守州政府的“呆在家里”的命令。幸运的是,覆盖西雅图大部分地区并受到严重影响的金县有足够的信心申请第二阶段的重新开放计划。因此,我们乐观地认为,到 9 月/10 月,一切都会恢复正常
令人兴奋的是,这也是游览这座城市的最佳时间。夏季标志着这座城市的旺季,这意味着房价飙升,而冬季则笼罩在无尽的寒冷雨天中,即使是最热情的游客也会望而却步。西雅图的花朵在秋天绽放得最灿烂,夏天的天气随着人群的散去而挥之不去,留下了足够的 Airbnb 空间来抢占 (USnews,2019) 。9 月和 10 月也充满了庆祝活动,如 bumber shoot(9 月)、Earshot 爵士音乐节(10 月-11 月)、西雅图餐厅周(10 月-11 月)。我们建议潜在客户在 10 月 15 日之前预订,因为房价较低,并且仍有许多可用房源。没有什么比走上街头庆祝疫情的结束更好的了,在千变万化的习俗中,享受美味的饼干和温暖人心的杂烩,作为真正的糖果

著名的派克市场的新鲜农产品(图片由作者提供)
IV/文字挖掘与评论
自然语言处理(NLP)是人工智能的一个分支,它使用自然语言分析计算机和人类之间的关系。NLP 在实现 Deep Leering 的神经神经元网络等应用时非常有用,因为它有助于以有价值的方式阅读、破译、理解和理解人类语言。 (Yse,2019) NLP 帮助我根据客人对酒店的评论预测反馈分数。但是在这个练习中,我们只是想看看评论需要什么,并演示 NLP 要经历的步骤,以便为未来的研究建立一个具体的基础。
“reviews”文件并不有趣,因为它只包含每个列表的审查日期。“review_details”包括类似的信息,只是多了 4 列,因此,我们将“host_id”、“host_name”与 review_details 文件左合并在一起:

(图片作者)
以下是评论数量最多的 5 位主持人。有趣的是,Loftium 以 4181 条评论再次出现在顶部。我们认为,这是由于该公司独特的商业模式,他们能够产生如此多的建设性评论,以改善他们的产品。

(图片作者)
为了清理任何自然语言处理数据集,我们需要遵循 5 个步骤:
- 取出空注释:with notnull()
- 删除数字:用 str.replace('\d+','')
- 小写:with str.lower()
- 移除 windows 新行:with str.replace('\r\n ',"")
- 用 nltk 库去掉所有停用词:我们需要用英文指定中的 stop.word()赋值一个变量“stop_english”。然后,我们使用 lambda 函数将整个句子用“”分开,然后在没有停用词的情况下再次连接在一起
- 去掉所有标点:用 str.replace('[^\w\s]'," ")
- 将 x 个空格替换为一个空格:with .str.replace('\s+',' ')
最后,我们可以看到索引 1 处的原始审查和清理后的版本之间的巨大差异

(图片作者)
请记住,如果我们想要构建一个世界云,实际的过程实际上并没有停止,因为这些评论充满了与我们的分析无关的主机名称。不幸的是,有 1949 个名字可用,在“review_details”数据集中搜索每一个名字将花费很长时间,而且这些名字并不真正影响最终的单词云。因此,我们将从这一点继续前进,未来的研究人员可以试图找出如何处理这个特定的任务。在使用 sklearn 和 WordCloud()的 CountVectorizer()函数后,我们可以看到最常用单词的排名以及单词云本身
**
(图片作者)
V/结论
简而言之,从比较研究的角度和提出解决方案的角度探索西雅图的 Airbnb 情况,让我们对公司如何运作、制定战略和创新性地转变为酒店业不可忽视的力量有了宝贵的见解。我们相信,Airbnb 在今年年底经受住当前的风暴后,将夺回其应有的宝座。
Github:https://Github . com/lukastuong 123/Python-Projects/tree/master/Project-% 20 Airbnb % 20(Python-% 20 interactive % 20 map % 2C % 20 natural % 20 language % 20 processing % 2C % 20 comparative % 20 study % 2C % 20 regression)
参考&来源:
Airbnb 。(2020 年 6 月 16 日)。华盛顿州西雅图| Airbnb 帮助中心。从 https://www.airbnb.com/help/article/869/seattle-wa取回
卡维尔,O. (2020 年 6 月 8 日)。Airbnb 见证了度假租赁需求的激增。洛杉矶时报。https://www . latimes . com/business/story/2020-06-07/Airbnb-冠状病毒-需求
陈,b . x .(2017 . 1 . 11)。成为 Airbnb 超级房东指南。检索自https://www . nytimes . com/2017/01/11/technology/personal tech/the-guide-to-be-an-Airbnb-super host . html #:% 7E:text = In % 20 process % 2C % 20I % 20 have,percent % 20 of % 20 hosts % 20 are % 20 super hosts。&text = The % 20 design % 20 as % 20a % 20 super host,away % 20 from % 20 netting % 20a % 20 profit。
孔斯蒂内,J. (2019 年 12 月 9 日)。TechCrunch 现在是威瑞森媒体的一部分。从 https://techcrunch.com/2019/12/09/airbnb-zeus/取回
道尔顿,A. (2017 年 2 月 7 日)。纽约市开始打击非法 Airbnb 房源。检索自https://www . engadget . com/2017-02-07-new-York-city-launch-Airbnb-listings-activation . html
研,K. (2020 年 4 月 8 日)。 Airbnb 的冠状病毒危机:烧钱、愤怒的主机和不确定的未来。华尔街日报。https://www . wsj . com/articles/airbnbs-coronavirus-crisis-burning-cash-angry-hosts-and-an-uncertainty-future-11586365860
拉利奇,l .&魏斯迈尔,C. (2017)。真实在 Airbnb 体验中的作用。旅游业中的信息和通信技术 2017,781–794。https://doi.org/10.1007/978-3-319-51168-9_56
利维,N. (2019 年 5 月 6 日)。房地产初创公司 Loftium 转向租赁,停止为 Airbnb 利润份额提供首付。检索自https://www . geek wire . com/2019/loft ium-pivots-real-estate-biz-now-offers-discounts-apartment-tenders-rent-rooms-Airbnb/
普劳茨,J. (2015 年 2 月 25 日)。高于平均评分?95%的 Airbnb 房源评分为 4.5 到 5 星。检索自https://Mashable . com/2015/02/25/Airbnb-reviews-above-average/?欧洲=真
西雅图市议会。 (2017 年 4 月)。规管短期租金政策简介。检索自https://www . Seattle . gov/Documents/Departments/Council/Issues/Regulating shorterm Rentals/Regulating-Short-Term-Rentals _ Policy-Brief _ 2017-04 . pdf
沙夫罗斯,F. (2016 年 9 月 17 日)。Airbnb 给城市制造了一个经济适用房的困境。检索自https://www . governing . com/columns/public-money/gov-Airbnb-affordable-housing . html
美国新闻。 (2019 年 11 月 4 日)。游览西雅图的最佳时间。从 https://travel.usnews.com/Seattle_WA/When_To_Visit/取回
是的,迭戈·洛佩兹。 (2019 年 1 月 15 日)。自然语言处理(NLP)指南。检索自https://towards data science . com/your-guide-to-natural language-processing-NLP-48ea 2511 f6e 1
— — —
数据集:http://insideairbnb.com/get-the-data.html
灵感来源:https://www . ka ggle . com/erikbruin/Airbnb-the-Amsterdam-story-with-interactive-maps
Airbnb 价格预测:多层感知器与 TensorFlow 的 Keras API
这个项目是我在深度学习领域的第一步,使用 TensorFlow 和 Keras 开发了一个回归模型,能够尽可能低地用 MAE 进行价格预测。

泰勒·维克在 Unsplash 上的照片
语境
当我在希望成为数据科学家的旅程中第一次遇到深度学习时,它是一个难以消化的领域。我最初之所以偏见地假设它令人困惑的复杂性,是因为这一领域的潜在逻辑和机制。然而,在花了一些时间来吸收深度学习的巨大适用性,特别是神经网络之后,我开始对利用它来解决数据科学问题产生兴趣。
在进入这个项目之前,我想提请注意机器学习和深度学习之间的激烈比较这可能已经闪过我们的脑海,至少一次。本质上,当机器学习使用算法解码中到大规模的数据来做出决策时,深度学习创建了多层神经网络,需要更长的时间来训练,以产生更高精度的模型。
如果你热衷于尝试深度学习,请随意查看 Kaggle 在此公开分享的数据集,并关注以下内容。
1.解释数据分析
作为一名数据分析师/数据科学家,在数据可用于建模之前,我们 70%的时间都花在了数据清理和准备上。
*import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as snsdf = pd.read_csv("airbnb-price-prediction.csv")df.head()*

注意 : 由于本文的重点是开发神经网络模型,我将只介绍 EDA 中的重要操作,但是您可以在本文末尾的 Github 库中查看完整的 EDA。
在加载数据集后,立即给我留下深刻印象的是“便利设施”变量,它嵌入了每行的非结构化值。如果它被构造成一个 JSON 字段,对我们来说将它展平并将每个子变量解析到不同的列中会更容易。然而,根据我的观察,该变量包括每个列表的不同娱乐项目,因此为了使其更有用,我决定格式化值并合并唯一的值以计算每个列表的娱乐项目占总数的百分比:
*df.amenities = df.amenities.map(lambda x: "|".join([i.replace("}", "").replace("{", "").replace('"', "") for i in x.split(",")])df.amenities = df.amenities.map(lambda x: x.split("|")*

df.map()
*amenities_list = list(np.unique(np.concatenate(df.amenities))[1:-2])*

唯一的()
*df['amenities_percentage'] = df.amenities.apply(lambda x: len(x)/len(amenities_list)*100)*
然后,我继续进行检查是否有空值来删除或填充实际值:
*df_new.isna().sum()#Removing null values that would not help the modellingdf_new = df_new[df_new.bathrooms.notna()]
df_new = df_new[df_new.bedrooms.notna()]
df_new = df_new[df_new.beds.notna()]
df_new = df_new[df_new.host_since.notna()]#Fill null values with actual valuesdf_new.host_response_rate = df_new.host_response_rate.fillna("0%")
df_new.review_scores_rating = df_new.review_scores_rating.fillna(0)*
此外,正如我们可能都知道的,异常值对建模过程相对敏感,所以我们应该小心地处理异常值(移除或转换),以便模型可以更有效地学习数据。

sns.boxplot(df_new.price)
由于价格变量遵循高斯分布,我们将创建一个函数来移除超出固定范围的异常值:
*from numpy import mean
from numpy import stddef remove_outliers(x):
data_mean = mean(x)
data_std = std(x)
cutoff = data_std*3
lower = data_mean - cutoff
upper = data_mean + cutoff
return lower, upperlower, upper = remove_outliers(df_new.price)df_new = df_new.loc[(df_new.price > lower) & (df_new.price < upper)]*
2.特征工程和缩放
类似于机器学习的建模,特征工程有助于预处理和转换原始数据集为更易消化的数据集,以训练模型。

df.head()
除了那些数字变量,我们需要转换模型可以理解和学习的分类变量。简而言之,我们将对二进制和多类变量分别应用不同的技术:标签编码器和 OneHotEncoder 。然而,在进行任何预处理步骤之前,我们 必须始终将数据集分为训练集和测试集 ,以避免建模期间的数据泄漏。
*from sklearn.model_selection import train_test_splitx = df_new.iloc[:, 1:-1]
y = df_new.iloc[:, -1]x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 42)*
然后,我们为转换导入标签编码器和 OneHotEncoder:在训练集上拟合并在两者上转换。
*from sklearn.preprocessing import LabelEncoder, OneHotEncoder**#Binary variables**le = LabelEncoder()binary_var = ['cleaning_fee', 'host_has_profile_pic', 'host_identity_verified', 'instant_bookable']for i in binary_var:
le.fit(x_train[i])
x_train[i] = le.transform(x_train[i])
x_test[i] = le.transform(x_test[i])**#Multi-category variables**oe = OneHotEncoder(sparse=False, handle_unknown = 'error')oe.fit(x_train[['property_type', 'room_type', 'bed_type', 'cancellation_policy', 'city']])#Transform the train setmulti = oe.transform(x_train[['property_type', 'room_type', 'bed_type', 'cancellation_policy', 'city']])
df_multi = pd.DataFrame(index = x_train.index, data=multi, columns=oe.get_feature_names(['property_type', 'room_type', 'bed_type', 'cancellation_policy', 'city']))
x_train = pd.concat([x_train, df_multi], axis=1)
x_train.drop(columns=['property_type', 'room_type', 'bed_type', 'cancellation_policy', 'city'], inplace=True)#Transform the test setmulti_test = oe.transform(x_test[['property_type', 'room_type', 'bed_type', 'cancellation_policy', 'city']])
df_multi_test = pd.DataFrame(index = x_test.index, data=multi_test, columns=oe.get_feature_names(['property_type', 'room_type', 'bed_type', 'cancellation_policy', 'city']))
x_test = pd.concat([x_test, df_multi_test], axis=1)
x_test.drop(columns=['property_type', 'room_type', 'bed_type', 'cancellation_policy', 'city'], inplace=True)*
此外,由于每个变量都有不同的数据范围,我们需要对独立变量进行缩放,以便模型可以更快、更有效地学习数据。在这种情况下,我选择了最小最大缩放器将数据压缩到(0,1)的范围内,这对我们将在下一节中使用的算法很有用:
*from sklearn.preprocessing import MinMaxScalermn = MinMaxScaler()x_train_scaled = pd.DataFrame(mn.fit_transform(x_train), columns = x_train.columns)
x_test_scaled = pd.DataFrame(mn.fit_transform(x_test), columns = x_test.columns)*
好了,我们都准备好了!
3.神经网络建模
什么是神经网络,为什么我们需要同时结合建模和优化?
在进入什么是神经网络之前,我想强调一下我们不能停留在建模阶段的惯例;更确切地说, 这是一个建立模型和测试不同参数 的连续过程,以产生最高精度的模型。
回到神经网络的概念,简而言之:
神经网络是一系列算法,通过模拟人脑运行方式的过程,努力识别一组数据中的潜在关系。——投资媒体。
如果你想更深入地了解这个概念,请点击这里查看 3Blue1Brown 的一系列视频,这些视频对神经网络的底层项目提供了全面的解释。
在深度学习中,特别是神经网络,我们使用 3 种常见的标准模型来进行预测:多层感知器(MLP) 、卷积神经网络(CNN) 和递归神经网络(RNN) 。对于这个项目,我已经从 MLP 开始,以获得深度学习的基本概念,但请关注我即将开展的项目,这些项目用更先进的模型解决数据科学问题。
那么,MLP 到底是什么,它在预测方面做了什么?
根据定义,
多层感知器模型,简称 MLP,是一个标准的全连接神经网络模型。它由节点层组成,每个节点连接到前一层的所有输出,每个节点的输出连接到下一层节点的所有输入。—Machinelearningmastery.com
为了更容易可视化,

图片来源:ResearchGate
TensorFlow 和 Keras 是一个开源库,能够执行深度学习中的各种任务,即回归和分类。由于其复杂性,需要遵循几个步骤:
- 定义模型
- 编译模型
- 符合模型
- 评估模型
- 做一个预测
为了更详细地解释,让我们看一下 MLP 模型的全步骤实现,如下所示:
*from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, Dropout
from tensorflow.keras.callbacks import EarlyStopping**#Step1\. Define the model**model = Sequential()model.add(Dense(16, activation = 'relu', kernel_initializer = 'he_normal', input_shape = (x_train_scaled.shape[1],)))
model.add(Dense(8, activation = 'relu', kernel_initializer = 'he_normal'))
model.add(Dense(1))**#Step2\. Compile the model**model.compile(optimizer = 'adam', loss = 'mse', metrics = 'mae')**#Step3\. Fit the model**history = model.fit(x_train_scaled, y_train, validation_data=(x_test_scaled, y_test), epochs=50,batch_size=64, verbose=0)**#Step4.1 Evaluate the model**loss, mae = model.evaluate(x_test_scaled, y_test)**#Step4.2 Plot the learning curve**plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='val')
plt.show()*
(1)-定义模型:
- 模型类型:我们可以从 TensorFlow 中选择顺序或功能模型 API* 。虽然顺序模型是实现起来最简单的模型,它以线性方式提供了一个一层接一层的“顺序”路径,但是功能模型是一个更复杂且更灵活的模型,它需要我们手动指定输入和输出层。*
- 节点数量:这取决于你希望你的模型有多复杂。没有“一刀切”的选择,而是我们需要测试和学习,看看每层有多少节点产生最高的准确性。
- 激活:对于每层中的每个节点,神经网络计算输入的加权和(并添加一个偏差),然后决定是否应该“激活”该节点。这意味着加权总和应该超过某个阈值,节点才会被“激活”。为了找到边界,我们需要确定激活函数来帮助定义边界的上限和下限。

图片来源:StackExchange
- 初始化器:如上所述,初始化器帮助定义设置输入层初始随机权重(w)的方式。有许多不同的初始化器适合不同的激活函数,我们将在下面的内容中测试它们。
(2)-编译模型:
- 优化器:优化器帮助改变神经网络的属性(例如,权重、学习率等。)以便尽可能减少模型的损失。类似于激活和初始化器,有一些优化器我们应该测试一下,看看哪个产生的模型精度最高。
- 损失:顾名思义,损失函数表示模型为了减少误差而采用的优化方法。从技术上讲,损失用于计算梯度,梯度用于更新神经网络的权重。
- 指标:根据我们构建的模型类型(例如回归、分类),我们将选择相关的指标来评估模型的训练情况(例如回归的 MAE/MSE/RMSE 和分类的准确性)
(3)-拟合模型:
- 时期:时期的数量是训练集中整个例子的完整次数。例如,如果我们将历元数设置为 5,这意味着在模型产生最终结果之前,训练集将循环 5 次。
- Batch_size :批次大小是在模型更新之前,用于估计模型误差的一个时期中的样本数。例如,如果我们将批量大小设置为 32,这意味着训练集的 32 个样本将用于训练模型和更新模型。然后,将使用接下来的 32 个样本,直到在一个时期中没有留下任何样本。如果我们有 1 个以上的历元,将重复该过程。
(4)-评估模型:
- 。evaluate() :我们将在测试集上调用这个函数,打印出错误值以及我们希望模型优化的指标。
- 学习曲线:我建议我们应该为我们测试的每个模型绘制学习曲线,因为重要的是要看到模型在每个时期是如何被训练的,以及模型是过拟合还是欠拟合。
好了,这是我们在神经网络中应该熟悉的所有核心参数。现在让我们打印出上面第一次试验模型的结果和学习曲线。

如所见,我们通过上述模型的设置实现了 0.3356 的 MAE。让我们将这个数字作为基准,看看我们是否可以在优化模型时获得更小的 MAE。
4.神经网络优化
下面是我将使用的所有优化方法的快速总结,供您参考:
- 具有特征选择的神经网络(相关热图/PCA)
- 具有附加层的神经网络(增加模型复杂性)
- 具有不同优化器的神经网络
- 具有更高纪元的神经网络(早期停止)
- 正则化神经网络(辍学和 L1/L2)
- 具有不同激活和初始化的神经网络
- 批量较小的神经网络
对于(1)方法,我想看看减少独立变量(特征)的数量或选择更重要的变量是否有助于改进模型。我依赖的两个选项是关联热图(手动选择)和 PCA(机器学习选择):

df.corr()
正如你所看到的,并不是所有的特征都与基于色阶的目标变量(价格)高度相关。因此,我只选择了与目标有更好相关性的变量(高度正/负),但似乎模型并没有改进得更好:MAE >基准。

具有关联热图的模型:MAE = 0.3544(>基准= 0.3356)
使用 PCA,模型也没有改善多少,但是该模型的 MAE 优于我们手动选择的特征:

带 PCA 的模型:MAE = 0.3475(>基准= 0.3356)
对于(2)方法,我想看看通过增加几个额外的层来增加模型的复杂性是否有助于降低 MAE 值。
*#Step1\. Define the model4model4 = Sequential()model4.add(Dense(32, activation = 'relu', kernel_initializer = 'he_normal', input_shape = (x_train_scaled.shape[1],)))
model4.add(Dense(16, activation = 'relu', kernel_initializer = 'he_normal'))
model4.add(Dense(8, activation = 'relu', kernel_initializer = 'he_normal'))
model4.add(Dense(8, activation = 'relu', kernel_initializer = 'he_normal'))
model4.add(Dense(1))#Step2 - 4 follows the same as the 1st model*
如果第一个模型只有 2 个隐藏层,分别有 16 个和 8 个节点,我在现有的基础上添加了 2 个额外的层,并增加了节点的数量。如下所示,与上述方法相比,该模型略有改进,但与基准相比仍不够显著。

添加了额外的隐藏层:MAE = 0.3358(>基准= 0.3356)
对于(3)方法,我想测试一个不同的优化器,而不是通常推荐的“Adam”:“rms prop”。没有看到改进,但值得注意的是,模型在训练期间经常波动(正如您从橙色线—测试集上的评估中看到的):

具有 optimizer = "rmsprop "的模型:MAE= 0.3375(>基准= 0.3356)
对于(4)方法,历元的数量可能会影响模型的结果。如果你熟悉机器学习,你会有和我一样的担心——“多少个历元足够训练模型?“坦率地说,我们无法说出确切的数字,只能测试和学习。然而,Keras 提前停止有助于阻止模型进一步循环/训练,这可能会导致过度拟合。
为了实现,我们只需要定义 EarlyStopping 这个变量,并设置“耐心”作为阈值,如果通过,模型将停止学习:
*es = EarlyStopping(monitor = 'val_loss', patience=5)history = model6.fit(x_train_scaled, y_train, validation_data=(x_test_scaled, y_test), epochs=200, batch_size=64, verbose=0, callbacks = [es])*
如果你看到上面,我设置了 monitor = 'val_loss '和 patience = 5,这意味着如果 val_loss 值(测试集)在连续 5 个时期后高于 loss 值(训练集),模型将停止学习。如下,模型在 20+历元处停止。该方法不仅 防止模型过拟合 ,而且 显著提高了模型的运行时间 。

具有提前停止的模型:MAE = 0.3371(>基准= 0.3356)
对于(5)方法,正则化是一种在模型学习时对其进行修改以便更好地推广的技术。这是通过在模型学习时最小化样本外测试误差来实现的,这也有助于减少过度拟合。你可能听说过机器学习中的“ L1/L2 正则子,它缩小了特征,但我们在神经网络中还有另一种常见的正则子——DropOut。让我们看看哪一个在当前数据集下表现更好:
*#Step1\. Define the model7model7 = Sequential()model7.add(Dense(32, activation = 'relu', kernel_initializer = 'he_normal', input_shape = (x_train_scaled.shape[1],)))
model7.add(Dense(16, activation = 'relu', kernel_initializer = 'he_normal'))
model7.add(Dropout(0.3))
model7.add(Dense(8, activation = 'relu', kernel_initializer = 'he_normal'))
model7.add(Dropout(0.3))
model7.add(Dense(8, activation = 'relu', kernel_initializer = 'he_normal'))
model7.add(Dropout(0.3))
model7.add(Dense(1))#Step 2 - 4 follows the same as the 1st model*

辍学模型:MAE = 0.3660(>基准= 0.3356)
*#Step1\. Define the model8model8 = Sequential()model8.add(Dense(32, activation = 'relu', kernel_initializer = 'he_normal', input_shape = (x_train_scaled.shape[1],)))
model8.add(Dense(16, activation = 'relu', kernel_initializer = 'he_normal', kernel_regularizer = 'l1'))
model8.add(Dense(8, activation = 'relu', kernel_initializer = 'he_normal', kernel_regularizer = 'l1'))
model8.add(Dense(8, activation = 'relu', kernel_initializer = 'he_normal', kernel_regularizer = 'l1'))
model8.add(Dense(1))#Step 2 - 4 follows the same as the 1st model*

具有 L1 正则化子的模型:MAE = 0.3344 ( < benchmark = 0.3356)
Voila! Finally, the model has improved, even slightly significantly as compared to the 1st model thanks to L1 Regularizer!
For (6) method, testing 激活和初始化器的不同组合是一个很好的简单方法来查看模型是否改进。以下是实践中常用的组合:
- activation = 'sigmoid ',kernel _ initializer = ' glorot _ normal '
- activation = 'relu ',kernel_initializer = 'he_uniform '
但是,对于这个数据集,没有看到任何改进,所以我们可以传递这个方法。
转到最后一个,建议在我们优化模型时测试更小的批量,因为更小的批量提供了更好的正则化效果/更低的泛化误差,并改善了运行时间。
瞧啊。这个项目到此结束——用 TensorFlow 的 Keras API 进行 Airbnb 价格预测。我希望这篇文章对你有用并且容易理解。
在不久的将来,一定要关注我的即将到来的数据科学和机器学习项目!与此同时,您可以在这里查看我的 Github 以获得完整的资源库:
github:https://github.com/andrewnguyen07LinkedIn:www.linkedin.com/in/andrewnguyen07
谢谢!
Airbnb 价格推荐器
使用机器学习来识别最优列表价格

亚历山大·帕萨里克( Pexels )的照片
作为我的数据科学项目 Metis 的一部分,我试图为 Airbnb 主机设计一个更好的定价系统,以优化它们的上市价格。通过这篇文章,我希望解释促使我设计这个模型的原因,以及我用来训练最优回归模型的方法。
背景
如果你是一名主持人,你可能已经听说过 AirBnB 的智能定价(smart pricing),这是一种帮助主持人根据需求和其他各种因素自动控制价格的定价工具。但是,尽管智能定价能够考虑到预订历史等因素,但它旨在最大限度地提高入住率,并可以提出比东道主希望的价格更低的价格。
因此,我想设计一个工具来训练活跃的列表,以建议最佳价格,同时也允许主机将推荐价格与类似列表的价格进行比较。
定价本身是非常个人化的,因为一些主人寻求提供负担得起和预算友好的体验,而其他人可能更奢侈,并寻求提供超级奢侈的体验。我不只是向主机建议价格,而是希望主机能够将建议价格与他们的直接竞争对手进行比较,以便更好地帮助他们对其列表价格做出决定。
目标
- 确定主持人可以用来提高可销售性的可操作特征
- 探索活跃列表的地理位置
- 创建一个可解释的回归模型,让主办方了解其建议价格背后的因素
我的方法
- 从 InsideAirBnB 收集数据
- 预处理数据并确定最佳列表
- 特征工程/探索性数据分析
- 回归建模和评估
- 使用最近邻居识别相似的列表
数据
不幸的是,AirBnB 没有任何开放的数据集,但 InsideAirBnB 是一个独立的实体,它在网上搜集世界各大城市 AirBnB 房源的公开信息。对于这个项目的范围,我选择把重点放在日本东京的上市。
数据有一些限制,因为我只使用了 2019 年 9 月刮的房源。此外,虽然我想用时间序列来模拟季节性,但 InsideAirBnB 没有东京一年的数据。

数据处理
需要记住的是,在所有搜索到的列表上建模价格没有多大意义。这些上市公司中的许多可能定价很低或不活跃,在它们的基础上训练一个模型不一定会建议最佳价格。因此,定义什么是“好”列表并过滤掉次优列表是数据清理过程的第一步。要跟踪的一个关键要素是占用率,这不是数据集中包含的要素。
三藩市模式
旧金山模型是 InsideAirBnB 的入住模型,旨在估计 AirBnB 房源出租的频率。简而言之,它执行以下操作:
- 通过假设 50%的审核率来估计预订数量
- 定义每个城市的平均停留时间(大多数城市为 3 天)
- 将的预计预订量和的平均入住时间相乘,得出入住率
你可以点击阅读更多关于这种入住模式的信息。
那么,我们如何识别活跃的、可销售的房源呢?
- 在过去 6 个月中,已对列表进行了审核
- 列表在过去 12 个月中有超过 5 条评论
- 每月预定天数估计超过 7 天

加工后分配
价格分布
看一下我们的目标变量 price 的分布,发现 76.69%的列表价格低于 150 美元。这确实在后来发挥了作用,因为我发现使用 150 美元的阈值并创建两个模型,一个用于高于该阈值的列表,另一个用于低于该阈值的列表,提高了模型性能。

搬运便利设施
房源提供的便利设施的数量肯定会影响价格。InsideAirBnB 的数据集有一个便利设施功能,它列出了一个列表提供的所有便利设施,但这种格式的便利设施对回归建模没有用处。

因此,我解析了每个列表的便利设施字符串,并为每个可能的便利设施创建了一个新的特性列,用一个布尔值来表示一个列表是否提供该便利设施。这样做的一个问题是,它大大增加了数据集的维度,但我们可以通过查看 p 值和使用 lasso 正则化来消除信息量较少的便利条件。
热门旅游景点
另一个起作用的因素是靠近旅游景点。虽然东京有一个优秀的公共交通系统,但我想探索一下,到某些旅游景点的距离是否会影响列表的定价。我选择的 5 个旅游景点是:
- 东京皇宫
- 银座购物区
- 浅草寺
- 上野公园
- 东京晴空塔
事实上,绘制预处理后数据集中剩余的最理想列表的位置显示,这些列表中的大多数都相对靠近这些旅游地点。

建模和评估
线性回归
在建模阶段,由于 OLS 中的高 p 值或多重共线性,许多不相关的要素被丢弃。为了让主持人容易理解推动价格预测的因素,我选择了线性回归模型,以便于解释。平均绝对误差(MAE)约为 18 美元。我还使用了岭和套索回归来防止过度拟合,但是这两种方法对最终的 MAE 分数都没有明显的影响。

最后,让我们看看对模型预测有影响的可操作特征。正如你在下面看到的,成为一个超级主持人,为顾客提供餐具和银器,对提高一个列表的可销售性以及抬高价格有很大的帮助。

XGBoost
除了线性回归,我还使用了 XGBoost,因为它能够为数据找到更非线性的拟合。正如预期的那样,XGBoost 的表现优于线性回归,平均绝对误差约为 $14.23。虽然 XGBoost 优于线性回归,但它的可解释性较差。可以使用 SHAP 等算法来增加 XGBoost 模型的可解释性,但从主持人的角度来看,理解线性回归权重仍然比理解 SHAP 图更容易。

SHAP 力图(单次观测)
寻找相似的物品
我在这个项目中的最初目标之一是给用户一些类似的列表,以比较诸如便利设施、价格等。在项目的这一部分,我使用 NearestNeighbors 算法简单地在特征空间中查找最近的列表。由于原始数据集具有列表 url 特征,因此为最接近的列表索引数据集也为主机提供了列表 url 以转到这些列表的 AirBnB 页面。

结论
总的来说,这个项目是探索东京热门 AirBnB 房源特征的一个有趣的练习。不过要注意的是,在考虑价格时,肯定还有其他因素要考虑,如季节性、需求和一周中的某一天。虽然我使用的数据集没有很好的方法来纳入这些因素,但改进这个项目的下一步将是使用时间序列模型来解决季节性问题,并找出一种对需求建模的方法。
感谢您的阅读!
项目存储库可以在这里找到。
使用 Python 对纽约租金进行数据分析
发现最方便的租赁方式,以便继续实施具有良好可视化效果的数据分析。

科尔顿杜克在 T2 的照片
T 他的城市不需要介绍。纽约是美国人口第八大城市,估计有 800 万人口。它也是美国人口最稠密的主要城市,被称为世界文化、金融和媒体之都。
坐落在世界上最大的天然海港之一的纽约市由五个区组成,每个区都是纽约州的一个县。五个区——布鲁克林、皇后区、曼哈顿、布朗克斯和斯塔滕岛——于 1898 年合并成一个城市。
有趣的事实。
但是我们大多数人主要是通过其他东西来了解它的,比如它的规模,它的大气,以及每次我们有机会去参观它时它带给我们的快乐。
作为我上一篇文章用 Python 实现商业智能可视化的后续部分,我决定为那些喜欢它的人写一篇文章,以展示可视化在 Python 中的实际和更广泛的应用。
在这种情况下,我将浏览包含纽约租房信息的 Airbnb 数据集,以帮助我们确定租房机会、便宜的价格、最受欢迎的住宿地点和其他见解。如果这听起来很有趣,请继续关注!
内容:
数据集介绍(1 分钟阅读)
使用 Python 进行数据探索性分析(7 分钟阅读)
1.数据集简介
Airbnb 是一家总部位于旧金山的公司,在全球超过 81,000 个城市开展业务,提供超过 600 万条租赁信息。从数据创建的角度来看,该公司已经从其运营的城市产生了大量的数据,如用户评论、位置描述和租金统计。
随着游客和商务旅行者以及其他人选择它作为出租房间、公寓或任何可用于寄宿家庭住所的方式,它已经成为在线租赁市场行业的主导者。该公司是建立寄宿家庭的先驱,这是一种受欢迎的接待和住宿形式,游客与他们要去的城市的当地人共用一个住所,并预先安排不同的停留时间。
我们要分析的数据集可以在我的 GitHub 账号中获得。分析数据集之前的第一步是预览它包含的信息。为了轻松处理这些信息,我们将使用 Pandas ,这是一个用于数据操作和分析的 Python 库,它提供了用于操作数值表和时间序列的数据结构和操作。
2.数据探索性分析
在我们直接进入数据清理和数据转换之前,让我们设定要分析的前提:
A .每种房型对应的租金比例是多少?
纽约五个区的租金是如何分配的?
c .价格分布是怎样的,合理的价格范围是多少?
d .区分不同房型的价格。
哪些地方是最受欢迎的租房地点?
F.给病人读者的租借建议。
我们将从导入必要的库开始工作。
# Imports
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
继续获取包含在中的数据。CSV 文件,该文件必须位于您的工作目录中,使用 Pandas 的函数 read_csv。之后,在控制台中打印数据的预览,只是为了看看相关的变量和特性。内置函数 head 返回数据集的前五行:
data = pd.read_csv('new_york.csv')
data.head()
完成这一步后,您将获得以下输出:
现在,让我们来看看数据集的基本信息,包括特性、数据类型、行、条目和每一个乍看起来可用的值。我们将利用信息功能来实现这一点:
data.info()
从 Gist 中可以看出,数据集包含 16 列、48,895 个条目或行,以及不同的数据类型,比如 Numpy 整数、对象和 Numpy 浮点。一些价值观
在特性或列中,我们可以找到 ID、房东姓名、租赁 ID、主机名、行政区和其他有价值的信息,我们稍后将从中提取结论。
继续用零替换数据集中的“缺失或空值,因为空值主要集中在“评论数量”和“上次评论”列中,它们在我们的分析中没有有用的应用。在这一点上要小心,因为不是每次看到“丢失”的值都应该替换它:
data.fillna(0,inplace=True)
检查重复的条目,它应该返回零:
sum(data.duplicated())
既然我们已经从数据集中清除了不必要的要素,让我们继续分析。
A.每种房型对应的租金比例是多少?

作者图片
从数据集中可获得的全部租金中, 52% 对应于整户公寓, 46% 对应于私人房间租金,剩余的少数对应于样本的 2% 合租房间。
以下代码应该使您能够获得所呈现的可视化效果:
# 1 - Pie chartroom_type = data.groupby('room_type')['latitude'].count().reset_index()
room_type.rename(columns={'latitude':'n_rooms'},inplace=True)
plt.figure(figsize=(10,8))
plt.pie(room_type['n_rooms'],autopct='%1.2f%%', colors=['darkcyan', 'steelblue','powderblue'])
plt.axis('equal')
plt.legend(labels=room_type['room_type'],loc='best',fontsize='12')
plt.title('Room-type Rental Distribution', fontsize='15',color='b')
plt.show()
plt.close()
B.我在导言中提到的五个区的租金是如何分配的?

正如可视化图中所反映的那样,布鲁克林区和曼哈顿区集中了 Airbnb 上大部分的租赁信息,这两个区总共有超过 4 万套租赁信息。这意味着纽约的大部分游客都住在这些地区的房产、房间或住宅里。
看一下创建情节的代码:
# 2 - Bar plot with neighbourhood distributionneighbourhood = data.groupby('neighbourhood_group')['neighbourhood'].count().reset_index()
fig,ax = plt.subplots(figsize=(12,8))
sns.barplot(x=neighbourhood[neighbourhood.columns[0]],
y=neighbourhood[neighbourhood.columns[1]],color='#004488',ax=ax)
sns.lineplot(x=neighbourhood[neighbourhood.columns[0]],y=neighbourhood[neighbourhood.columns[1]],color='r',marker='o',ax=ax)
plt.ylabel('Rentals', fontsize='15')
plt.xlabel('Borough',fontsize='15')
plt.title('Rental Distribution by Neighbourhood Group',fontsize='15')
plt.grid('x')
plt.show()
sns.set()
C.价格分布是怎样的,合理的价格范围是多少?

作者图片
价格分布集中在 300-400 美元左右,很少观察到更高的价格。
# 3 - Histogram plot with price distributionprice = data.loc[:,['neighbourhood','price']].set_index('neighbourhood')
price_stats = data['price'].describe().reset_index()
price_counts = price.price.value_counts().reset_index()
price_counts.rename(columns={'index':'price','price':'count'},inplace=True)
fig2,ax = plt.subplots(figsize=(12,8))
fig2.patch.set_facecolor('lightgray')
ax.set_facecolor('lightgray')
plt.hist(price_counts['price'],bins=30,color='#004488',edgecolor='salmon')
ax.set_xticks(range(0,10000,500))
for tick in ax.get_xticklabels():
tick.set_rotation(45)
plt.xlabel('Price',fontsize='15')
plt.ylabel('Rentals', fontsize='15')
plt.xlim((-0.5,10000))
plt.title('New York Price-Rental Distribution',fontsize='15')
plt.show()
D.区分不同房型的价格。

作者图片
在可用的不同房间类型中,需求最大的是全屋,其次是私人房间,最后是合住房间,这一趋势与第一次分析中的趋势相同。
在这种情况下,我们注意到,在需求较少的行政区,如布朗克斯或斯塔滕岛,价格分散在私人房间和合租房间之间缩小,而整个家庭保持价格分散。
需求更多的地区,如曼哈顿,私人房间的租金与需求较少的地区的整栋房屋租金价格相似。
# 4 - Bar plot with price to location distributionloc_price = data.groupby(['neighbourhood_group','room_type'])['price'].mean().reset_index()
locations = loc_price.neighbourhood_group.unique()
x_rooms1 = [0.8, 3.8, 6.8, 9.8, 12.8]
x_rooms2 = [1.6, 4.6, 7.6, 10.6, 13.6]
x_rooms3 = [2.4, 5.4, 8.4, 11.4, 14.4]
y_values1 = loc_price[loc_price['room_type'] == 'Entire home/apt']['price'].values
y_values2 = loc_price[loc_price['room_type'] == 'Private room']['price'].values
y_values3 = loc_price[loc_price['room_type'] == 'Shared room']['price'].values
fig3,ax2 = plt.subplots(figsize=(16,11))
fig3.patch.set_facecolor('lightgray')
ax2.set_facecolor('lightgray')
plt.bar(x_rooms1, y_values1, color='purple', edgecolor='b')
plt.bar(x_rooms2, y_values2, color='b', edgecolor='b')
plt.bar(x_rooms3, y_values3, color='yellowgreen', edgecolor='b')
ax2.set_xticks(range(1,16,3))
ax2.set_xticklabels(locations, fontsize='12')
for tick in ax2.get_xticklabels():
tick.set_rotation(45)
plt.xlabel('Location/Room-type',fontsize='15')
plt.ylabel('Prices', fontsize='15')
plt.legend(labels=loc_price.room_type.unique(), loc='best')
plt.title('New York Price-Rental Distribution by Location and Room-type',fontsize='15')
plt.show()
E.哪是最受欢迎的租赁小屋的地点?

作者图片
根据 Airbnb 用户的评论,我们可以推断出哪些租房是最受欢迎的或最受欢迎的(这并不意味着它们是最好的,但为了简化案例,让我们考虑一下如果它们被访问的次数更多,可能是因为以前的访问者留下了好评)。
在上面的图片中,我们看到大多数被评论的位置涉及需求较少的行政区,其中最受欢迎的租赁往往平均有 550 条来自用户的评论。
# 5 - Most reviewed spotsreview = data.sort_values('number_of_reviews',ascending=False)
top_reviewed = review.loc[:,['neighbourhood','number_of_reviews']][:20]
top_reviewed = top_reviewed.groupby('neighbourhood').mean().sort_values('number_of_reviews',ascending=False).reset_index()
fig4,ax3 = plt.subplots(figsize=(12,8))
sns.barplot(x=top_reviewed['neighbourhood'],y=top_reviewed['number_of_reviews'].values,color='yellowgreen',ax=ax3)
plt.plot(top_reviewed['number_of_reviews'], marker='o', color='red',linestyle='--')
plt.ylabel('Reviews', fontsize='15')
plt.xlabel('Location',fontsize='15')
plt.ylim((400,580))
for ax in ax3.get_xticklabels():
ax.set_rotation(50)
plt.title('Most-Reviewed Rentals by location',fontsize='15')
plt.show()
sns.set()
F.为患者读者提供的租赁建议
正如我们在上面的图片中看到的,曼哈顿和布鲁克林区的需求明显更大。
你可能想知道,住在这些地方要花多少钱?有没有可能通过这种分析找到机会,让我以尽可能低的价格在这些区租到一个好房子?答案是肯定的!
曼哈顿最著名的居住地之一是上东区的(UES)。上东区是一些最富有的个人和家庭的家园。这里有最时髦的纽约人居住的豪华公寓。
有了熊猫可用的过滤器,我们可以过滤位于上东区的租赁,我们可以在评论最多的租赁中获得最便宜的租赁,以便找到最合适的住宿地点!
根据上述标准,这些是最适合私人房间和住宅的租赁:

最便宜和最受欢迎的整屋出租

最便宜和受欢迎的私人房间出租
正如我们所看到的,每晚只需 69 美元,我们就可以住在世界上最豪华的地方之一的出租屋里,如果我们的预算有限,还可以花 49 美元租一个私人房间。
如果你有任何悬而未决的疑问,可以考虑看看我下面的脚本:
import numpy as np
upper_east = data[data['neighbourhood'] == 'Upper East Side']
ninetieth_percentile = np.quantile(upper_east['number_of_reviews'], 0.85)
upper_east = upper_east[upper_east['number_of_reviews'] >= ninetieth_percentile]
upper_east = upper_east.sort_values('price',ascending=True)
private_room = upper_east[upper_east['room_type'] == 'Private room'].reset_index()
entire_home = upper_east[upper_east['room_type'] == 'Entire home/apt'].reset_index()
shared_room = upper_east[upper_east['room_type'] == 'Shared room'].reset_index()
private_cheapest = private_room.loc[0,:].reset_index()
private_cheapest.rename(columns={'index':'data','0':'values'},inplace=True)
entire_cheapest = entire_home.loc[0,:].reset_index()
entire_cheapest.rename(columns={'index':'data','0':'values'},inplace=True)
结论
毫无疑问, Airbnb 和在线租赁市场行业将帮助我们获得更好的房屋或房间租赁,以优化旅行和旅游体验。我写这篇文章的目的是为你提供一个工具来帮助你实现这样的优化,并且为什么不呢,决定你下次去纽约的时候会住在哪个地方?
如果你喜欢这篇文章中的信息,不要犹豫,联系我分享你的想法。它激励我继续分享!
您可以在以下社交网络中找到我:
- 。
- GitHub。
参考
- 【1】Airbnb 官网。
- 纽约
- [3] 用 Python 实现商业智能可视化
感谢您花时间阅读我的文章!如有任何问题、建议或意见,欢迎联系我:herrera.ajulian@gmail.com
气流:如何以及何时使用它
除了知道如何使用气流,知道何时使用气流也很重要。
Airflow 是一款用于管理和监控工作流程的流行工具。对于我们在 Bluecore 的大多数数据科学工作流来说,它工作得很好,但也有一些其他工具表现更好的用例。除了知道如何使用气流,知道何时使用气流也很重要。

关于气流
“Airflow 是一个以编程方式创作、安排和监控工作流的平台。”— 气流文件
听起来很有用,对吧?嗯,确实是!Airflow 使得在它们的 UI 中监控管道的状态变得容易,并且您可以使用任务之间复杂的扇入和扇出关系来构建 Dag。他们还补充道:
“丰富的命令行实用程序使在 Dag 上执行复杂的手术变得轻而易举。”
这让我笑了,因为有时与气流一起工作感觉像是脑部手术,而其他时候它工作了,感觉像是第二天回家的那种。

基本组件
在我们进入气流的更复杂的方面之前,让我们回顾几个核心概念。
熟练的技艺
DAG 或有向无环图是流水线中所有任务、工作单元的集合。这些任务是按照它们之间的关系和依赖关系来组织的。例如,如果要查询数据库一,然后将结果加载到数据库二,则需要在将结果加载到数据库二的任务之前直接运行查询数据库一的任务。有向非循环图暗示你的管道只能向前,不能向后。一个任务可以重试,但是在完成一个任务并且下游的另一个任务已经开始之后,该任务不能重新运行。
DAG 页面是 Airflow UI 中的主页。显示 DAG 计划,并且可以打开/关闭。

气流 UI DAG 视图
DAG 管道示例
气流之所以如此有用,是因为它能够处理任务之间的复杂关系。您可以轻松地构造扇入和扇出的任务。

下面是我们在 Bluecore 使用的一个工作流程示例。这是一个非常简单的 DAG,它使用 AppEngineOperator 调用我们在 AppEngine 中创建的命令,该命令进行查询并返回 Bluecore 的活动合作伙伴列表。接下来,我们使用 PythonOperator 来更新 Airflow 变量。如果更新任务成功或失败,我们将向 datadog 发送适当的度量。

任务/操作员
“实例化操作员对象时生成任务。”-气流文件
说快 10 倍。
任务是理想的独立部分,不依赖于来自另一个任务的信息。操作员类对象在运行时会变成任务。可以导入操作符类,实例化该类会产生类对象。该对象的实例化(运行操作符代码)是任务。一开始,任务和操作符之间的细微差别可能会令人困惑,所以我发现制作这个图表很有帮助。

在 DAG 文件中定义 DAG 和任务
概念很好,但是你可能会问自己,我实际上如何编写代码来创建 DAG?嗯,在 Bluecore,我们有一个专门用于定义 Dag 的 python 文件的 Github 库。例如,您可以创建 example_dag.py,并从定义 dag 对象开始。您将从 Airflow 导入 DAG 类,并定义您需要的参数。

接下来,写下每个任务。将 dag 参数设置为 dag 对象会将任务与 DAG 相关联。

最后,定义任务之间的关系。

将 DAG 和任务定义以及定义上游/下游任务放在一起会产生一个 DAG 定义文件。

变量
变量是气流的另一个有用组成部分。我们使用变量有两个基本目的:与环境相关的和特定于模型的参数。可以在 DAG 文件中访问变量,例如,可以更新项目 id 或图像标签,而无需对 DAG 进行任何更改。如果您有多个环境,例如 QA 和生产环境,这将特别有用。此外,我们的一些模型并不面向所有合作伙伴,而是面向一组特定的合作伙伴。我们有一个单独的 DAG,它更新包含特定于模型的伙伴的变量,然后当模型运行时,它从变量中提取它的伙伴列表。

气流 UI 可变视图
泳池

池控制允许 DAG 一次消耗的资源数量。应该根据任务完成的速度和 DAG 需要完成的速度来定义池。确保在使用池时,您没有使用其他人的池,否则两个 Dag 可能不会像预期的那样快速完成。

气流 UI 池视图
XComs

理想情况下,任务是相互独立的,但有时这是不可能的,任务需要相互通信。这种相互通信是由 xcom 完成的。XComs 可以在任务之间“推”(发送)或“拉”(接收)。
例如,您可能需要将一个任务的返回值推送到 xcom 表中,以便在下一个任务中从 xcom 表中提取该值,并将其用作参数。在前面 DAGs 部分描述的简单 DAG 示例中,第一个任务将活动伙伴列表推送到 xcom 表,第二个任务从 xcom 表中取出伙伴列表,并将该列表设置为气流变量。
摘要
我们回顾了何时使用气流(当您的管道需要支持扇入/扇出时),如何构建 DAG,DAG 为什么有用,以及各种气流组件。总之,我们了解了
- 熟练的技艺
- 任务/操作员
- 如何构建 DAG 和设置任务关系
- 变量
- 泳池
- Xcoms
现在,您已经有了开始创建 DAG 所需的工具,可以在其中构建复杂的数据管道了!如果您有兴趣了解更多信息,请参见 Airflow:如何以及何时使用它(高级)了解有关操作符、结构化 Dag 以及 Airflow 缩放问题的更多信息。
气流:如何和何时使用它(高级)
在《气流:如何以及何时使用它中,我们讨论了气流的基本组件以及如何构建 DAG。一旦你开始构建 DAG,你会发现它变得很复杂。选择运算符和设置 DAG 结构需要一些时间。随着我们在 Bluecore 的不断发展壮大,我们将继续寻找更好地创建和扩展数据管道的解决方案。以下是我们一路走来学到的一些东西。
运算符:高级
从基本概念开始,我们将讨论气流操作符的一些更实际的应用。在 Bluecore,我们开发了自己的kubernetjoboperator和 AppEngine(同步/异步)操作符。这些都是开源的,所以请随意查看。气流也有自己的 KubernetesPodOperator 和 AppEngineOperator。PythonOperator、AppEngineOperators 和 KubernetesJobOperator 是我们使用的三个主要运算符。因此,这是我要讨论的三个问题。
python 运算符
PythonOperator 运行可从 DAG 调用的 python 函数。该运算符对于处理 DAG 中的大量简单工作非常有用。
我们使用 python 运算符的方法示例
- 设置气流变量
- 在“气流”数据库上运行 SQL 查询
- 将 xcom 值添加到“XCom”表中
- 发送数据狗指标
KubernetesJobOperator
KubernetesJobOperator 从一个 Docker 映像运行代码。这意味着它几乎可以做任何事情!
我们使用 KubernetsJobOperator 的方法示例
- 查询/写入数据库(Bigtable、BigQuery、Datastore 等)。)
- 迁移数据
- 训练数据科学模型
这是迄今为止对我们最有用的操作符,但也是使用起来最复杂的。如果你使用谷歌云平台并从谷歌容器注册表中提取你的图片,这些是基本步骤

示例:使用 Kubernetes 构建任务
只要 Docker 映像在容器注册表中,代码就可以存在于任何地方。如果您将代码编写为脚本,那么您可以在操作符中将其用作命令,并在本地进行测试。在脚本中,接受参数并解析它们将允许 DAG 文件中的变量到达脚本。Kubernetes 的秘密也可以作为脚本可以使用的环境变量传入。

代码由 docker 文件构建,并指定入口点。
将 model_one_metrics.py 代码编译成映像后,就可以编写任务了。

KubernetesJobOperator 的示例代码
应用工程师
App Engine 操作员在 Google App Engine (GAE) 中运行一个命令。Bluecore 也创建了两个操作符。分别是 AppEngineSyncOperator 和 appengineoperatorsync。我们的大部分代码都是用 AppEngine 编写的,所以这些操作符有很多用处。
我们使用 app engine 运算符的方式示例
- 检索所有活动合作伙伴的列表
- 更新合作伙伴权限和功能
- 设置电子邮件发送时间
- 压缩表格

调试/Kubectl
Pod 日志对于调试 DAG 问题非常有帮助。在 UI 中点击任务即可找到。


气流用户界面中的日志页面。
如果这些日志还不够,使用 kubectl 研究 pod/worker/scheduler/web 日志。
DAG 结构和策略
任务结构
有两种不同的视图,底部是“图形视图”,右边是“树视图”在下面的 DAG 中,我们查询一个任务中所有伙伴的列表,但是在右边的 DAG 中,我们在每个伙伴的基础上查询使用“corec”模型的伙伴。该结构取决于运行一项任务所需的时间。正确的任务在一个任务中查询每个伙伴花费的时间太长,所以最好将任务拆分。

更新变量的 Dag 的两种不同视图。左下方的 DAG 显示在“图形视图”中,右上方的 DAG 显示在“树视图”中。
动态 DAG 创建
我们有三种不同类型的共同推荐,我们在一个 DAG 中运行它们。每个合作伙伴对三个模型中的每一个都有三组不同的任务。这条狗变得又大又慢。现在,我们从一个 corecommendations DAG 文件中动态生成三个 DAG,并且我们可以在不同的时间设置计划,这样就不会一次占用太多的资源。

corecommendations DAG 文件动态创建三个 DAG,每个模型一个。
DAG 分离
我们的一个模型有一些不同的 Dag。如果某些任务不依赖于当前 DAG 中的时间表或上游任务,则最好将 DAG 分开,尤其是在 DAG 需要经常运行,并且任务会降低 DAG 速度的情况下。
任务逻辑
我们曾经每周为每个合作伙伴运行两次模型。这导致 DAG 运行缓慢,因为所有任务都试图同时训练。为了解决这个问题,我们创建了一个合作伙伴 mod 7 的散列,结果是一周中运行该模型的那一天。加上三,我们得到第二天。这分散了每个合作伙伴的培训。
此外,每周只需要培训两次,但每天都需要“随机分配”。添加了涉及跳过的任务逻辑来处理这种情况。第一个任务决定应该采取哪条路径,并且,如果不是训练该伙伴的日子,则跳过训练和服务任务。

一个 DAG 中的两组不同的任务。左侧显示的是合作伙伴 a,右侧显示的是合作伙伴 b。在这次 DAG 运行中,是合作伙伴 a 而不是合作伙伴 b 进行训练。
DAG 细分:
- 决定走哪条路(搭档 a 训练,搭档 b 不训练)
2.将不需要的路径任务标记为“跳过”(需要传递给随机分配的虚拟任务)
3.向数据狗发送通过/失败指标
当气流不是最佳选择时
将谷歌云调度器用于 cron 作业可能更适合不需要扇入/扇出的简单管道。
当在 DAG 中调度大量任务时,Airfow 存在扩展问题。UI 在加载 DAG 时出现问题,这使得调试和检查变得困难。当试图加载这些大型 Dag 时,web pod 有时会崩溃

目前,我们已经实施了一些变通办法来避免这个问题,但我们目前仍在研究改进的方法。这可能是气流不适合这种工作流程,也许 Kubeflow 或 Argo 是更好的选择。让我知道,如果你有任何想法/意见缩放大型 Dag!
摘要
在气流:如何以及何时使用它中,我们讨论了如何使用气流和创建 Dag 的基础知识。在本文中,我们以这些主题为基础,更详细地讨论了如何创建操作符和构建 DAG。具体来说,我们
- 探究构建任务的更高级的方法
- 检查 DAG 结构和策略
气流是一个很好的工具。UI 使得监控、调度和设计 Dag 变得相当容易。当扩展超过 500 个任务的 Dag 时,气流开始变得困难。要么需要应用变通方法来保持 Dag 的可观察性,要么可能需要另一个管道软件。
气流:如何在睡觉时刷新股市数据——第 1 部分
在关于 Apache Airflow 的第一篇教程中,学习如何构建一个数据管道来自动提取、转换和加载项目所需的股票价格和统计数据。

什么是气流,它如何帮助你?
Apache Airflow 是一个工作流管理平台,允许用户以编程方式安排独立运行的作业,并通过其用户界面对其进行监控。Airflow 的主要组件是一个 Webserver (Airflow 的 UI 构建为 Flask App)、一个调度器、一个执行器和一个元数据数据库。
作为一名 BI 开发人员,我曾与数据工程师密切合作,很早就了解了 Airflow 擅长的领域,但我从未真正将理论付诸实践,直到我开始从事副业。
实际上,当我用破折号构建一个可视化股票价格和股票统计的应用程序时,我意识到每次我想要更新数据时,我都必须手动重新运行整个代码。当您需要提取、处理和提供数百个股票报价机的数据时,这个过程需要很长时间。我知道,如果我想扩大我的项目,我需要一个工具来编排幕后的重复任务,同时我专注于构建新的有趣的功能。
在本教程的第一部分,我将向您展示我最终是如何开始结合 Python 和 Airflow 来创建一个自动化的 ETL 管道的:
- 从雅虎财经下载股票价格并保存到一个列表中;
- 对股票价格执行高级操作,生成一个 S 股票价格历史 DF 和一个 S 股票价格统计 DF 用于我的项目的不同部分;
- 将数据保存为特定文件夹中的 CSV 文件。
但首先让我们激活一个虚拟环境,并安装气流。
安装和配置气流
对于本教程,我将假设您熟悉虚拟环境,并且您使用的是 Python 3.6 或更高版本,因为我发现安装有问题(如果您希望仔细检查,只需使用python -V):
- 首先,激活您的虚拟环境,然后运行
pip install apache-airflow。要验证安装是否成功,请键入命令airflow version。 - 现在用
cd ~/airflow/导航到 Airflow 主目录,用mkdir dags创建一个名为“dags”的新文件夹。在气流中,一个 DAG ( 或有向无环图 ) 由许多操作符组成,这些操作符描述了为实现特定目标而需要执行的各个任务。例如,如果你想运行一个 Python 函数,你可以使用Python Operator,而如果你想执行一个 Bash 命令,你可以使用BashOperator,以此类推。要获得完整的可用操作员列表,请查看官方文档。 - 调用
airflow initdb命令来启动 SQLite 数据库,其中 Airflow 将存储管理您的工作流所必需的元数据。请注意,SQLite 数据库在生产环境中并不是最佳选择,但是当您开始使用 Airflow 时,它会很方便,因为它非常容易在本地配置。 - 气流主文件夹中会出现一些新文件,其中有
airflow.cfg。该文件包括将应用于 web 界面和 Dag 的所有配置选项。我强烈推荐用编辑器打开文件,设置load_examples=False。该选项默认设置为True,除非更改,否则每次运行 Webserver 时,您都会在 UI 上看到一长串默认 DAG 示例,这在我看来有点混乱和混乱。 - 用创建一个空文件。py 扩展将包括您的原始 Python 脚本+ DAG 调度+ DAG 操作符+任务层次结构。基本上,因为 Airflow 是基于 Python 的,所以您可以简单地将 DAG 嵌入到熟悉的 Python 脚本中,并将其执行留给 Airflow 的调度程序(稍后将详细介绍)。对于本教程,我最初创建了一个名为
stocks_analysis.py的空文件。
下面的 bash 命令总结了到目前为止所做的工作:
(airflow_ve) AnBento-2:airflow $ mkdir dags(airflow_ve) AnBento-2:airflow $ airflow initdb(airflow_ve) AnBento-2:airflow $ ls
airflow-scheduler.err airflow-scheduler.pid airflow-webserver.out airflow.db unittests.cfg airflow-scheduler.log airflow-webserver.err airflow-webserver.pid dags airflow-scheduler.out airflow-webserver.log airflow.cfg logs(airflow_ve) AnBento-2:airflow $ open airflow.cfg(airflow_ve) AnBento-2:airflow $ cd dags(airflow_ve) AnBento-2:dags $ touch stocks_analysis.py(airflow_ve) AnBento-2:dags $ ls__pycache__ stocks_analysis.py
如果您遵循了所有的步骤,您现在应该准备好启动 Airflow Webserver 和 Scheduler,但是在此之前,您需要用 DAG 填充stock_analysis.py文件。
创建 DAG 来提取-转换-加载股票价格
我将在本教程中用来刷新股票价格、设置 DAG 及其操作符的完整代码可以在我的 GitHub 帐户中获得。

如果你正在跟随,现在是时候用open stock_analysis.py编辑空文件,并粘贴你在code _ tutorials/air flow Stock Prices ETL文件夹中找到的整个 Python 脚本了。保存更改后,在执行任何其他操作之前,请确保在环境中安装以下所有软件包:
气流现在应该能够识别有效的 DAG,您可以使用airflow list_dags轻松检查它:
(airflow_ve) AnBento-2:dags $ airflow list_dags[2020–06–27 09:40:35,002] {__init__.py:51} INFO — Using executor **SequentialExecutor**[2020–06–27 09:40:35,002] {dagbag.py:396} INFO — Filling up the DagBag from **/Users/anbento/airflow/dags** — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -DAGS — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -stocks_analysis_ETL_7AM
上面的屏幕没有抛出错误,您可以看出 DAG 实际上已被系统识别,因为stock_analysis_ETL_7AM正是我分配给 DAG 的名称:
实际上,我建议为您的 Dag 分配一个有意义的名称(遵循惯例project _ name+process+schedule interval),因为这有助于立即直观地看到您正在查看的作业以及它应该在何时运行,并且这在处理多个工作流时增加了清晰度。
上面的代码告诉 Airflow 何时调度作业,作业需要完成什么以及以什么顺序完成。从顶部开始,它可以分为三个部分:
- Airflow DAG +默认参数:在这里,您将指定作业名称、
start_date和schedule_interval以及 Python 字典中定义的附加default_args。这里有几个建议,可以让你免去很多头疼的事情,也不用花时间去阅读无数的教程和堆栈溢出的帖子:
- 将静态的
start_date设置为过去,例如start_date = datetime(2020, 6, 23)→实际上,为了正常工作,Airflow 要求任何作业的开始日期都已经是过去的日期,为了避免不可预测的行为,最好使用静态语法,而不是像start_date = datetime.now()- timedelta(days=3)这样的语法。 - 设置
catchup = False→通过这种方式,您可以清楚地知道,尽管您的start_date已经过去,但您不希望气流回填您的数据,这意味着当您第一次运行它时,作业将不会执行多次,以覆盖从start_date到 DAG 打开日期之间的所有缺失运行。相反,气流将只运行它一次(立即),之后,它将坚持时间表。 - 更改
schedule_interval时更改 DAG 名称→如果您希望将运行时间从上午 7 点更改为上午 8 点,最好也将 DAG 名称更改为stock_analysis_ETL_8AM。Airflow 会将这个 DAG 视为一个全新的 DAG,这样可以避免在元数据数据库中存储两个同名的 DAG…是的,您可以从 UI 中删除旧的 DAG。
2。DAG 操作符:对于本教程,我将使用三个PythonOperators来运行三个 Python 函数。每个 Python 操作符都是一个单独的任务,需要传递给气流顺序执行器以实现预期的结果。每个任务都由一个task_id 标识,为了避免混淆,我建议您确保任务名称和任务 id 始终匹配。我的任务是:
- fetch_prices_task →该任务将调用一个名为fetch _ prices _ function()的 Python 函数,该函数从 Yahoo Finance 下载
tickers列表中 5 只股票的完整价格历史,删除重复项,应用简单的操作,并将它们保存在stock_prices列表中:
如果您运行该函数,它应该会返回类似如下的内容:

因为我将使用stock_prices列表作为另外两个 Python 函数的输入,所以这是顺序中需要执行的第一个任务。 任务执行 层次 很重要,因为它允许我不在每一步都下载股票价格,而是只做一次(在开始时),这样每个任务将运行得更快,整个过程将更有效率。
- stocks_plot_task →该任务将调用名为 stocks_plot_function() 的第二个 Python 函数,该函数将
stock_prices列表作为输入,并将每个股票价格历史连接到一个数据帧中,该数据帧随后将用于绘制股票价格的长期趋势。数据最终保存在一个名为stocks_plots_data.csv的 CSV 文件中。当然,您可以决定采取更高级的步骤,将数据增量加载到您选择的 DB 中*——这实际上是正确的方法——但是为了保持简单并专注于气流能力,我们现在坚持使用 CSV 文件:*
该功能运行时,显示stock_plots_data DF 的前 5 行:

stocks_plots_data 包括绘制 5 只股票的趋势和蜡烛图所需的所有价格字段
- stocks_table_task →这个最后的任务将调用第三个名为stocks _ table _ function()的 Python 函数,该函数再次将
stock_prices列表作为输入,只保留最后一个可用的Adj Close价格,然后从 Yahoo Finance 获取大量统计数据。最终,输出被保存到一个名为stocks_table_data.csv的 CSV 文件中:
这个函数很长,所以只显示前 15 行。在这里找到完整版。
上述函数的输出是一个具有 5 行 13 列的 DF,其中 11 列是关键统计数据:

3。任务层级→ 这是 DAG 的最后一个组件,用于指定气流执行三个任务的顺序。就我而言,我选择了:
*fetch_prices_task >> stocks_plot_task >> stocks_table_task*
这意味着将首先执行fetch_prices_task (这是有意义的,因为它生成了用于其他两个任务的stock_prices列表),然后是stocks_plot_task和stocks_table_task。
在这种情况下,您还可以决定合并第二个和第三个任务,因为它们互不依赖:
*fetch_prices_task >> [stocks_plot_task, stocks_table_task]*
注意在 Airflow 中依赖关系是如何在语法上设置的(set_upstream()、set_downstream())或者像我一样使用、位移法、操作符。
气流交叉通信(XCom)
如果您试图在 Python IDE 中测试这些函数,您可能会注意到它们只是…失败了!。这是因为**为了让一个任务的输出在后续的其他任务中作为的输入被调用,Airflow 使用了一个名为 XCom** 的任务间通信 Python 类。因此,我必须修改原始函数,添加:
- 一个关键字参数(**kwargs) 用于所有三个;
- 下面两行为 stocks_plot_function() 和stocks _ table _ function():
*ti = kwargs[‘ti’]
stocks_prices = ti.xcom_pull(task_ids=’fetch_prices_task’)*
provide_context = True对于每个 Python 操作符。
实际上,正如文档(非常简洁……)所解释的,一个任务可以通过调用xcom_push()方法或者简单地通过在它调用的函数结束时返回输出来使输出可用(就像我对return stock_prices所做的)。
以类似的方式,一个任务可以通过调用xcom_pull()方法获取输出,该方法精确地指定应该从哪个任务获取输入(task_ids ='fetch_prices_task')。

Denys Nevozhai 在 Unsplash 上拍摄的照片
是的,我知道……如果你第一次使用 Airflow,你可能会想为什么不能在fetch_prices_function()之外定义stock_prices=[],并在其他两个函数中使用它作为全局列表。事情是这样的,Airflow 一次性解析 Python 代码,因此它需要一个更复杂的系统来让任务相互“交流”。如果你对主题仍有疑问,这是最近帮助我的另一篇优秀文章。
最后一步:如何激活股票分析 ETL 作业
既然您已经掌握了代码在做什么以及 DAG 是如何构建的,那么是时候打开两个单独的 Bash 窗口了。在第一个窗口中,您应该运行命令来启动 air flowweb server:
*(airflow_ve) AnBento-2:airflow $ airflow webserver*
而在第二个窗口中,您应该启动气流 调度器 :
*(airflow_ve) AnBento-2:airflow $ airflow scheduler*
如果您导航到默认的http://0 . 0 . 0 . 0:8080/admin/本地地址,您将有望看到下面的屏幕:

气流正确显示了stocks_analysis_ETL_7AM DAG,但是为了启动该过程,需要手动打开作业。一旦你这样做了,气流 顺序执行器 将立即根据它们的层次运行所有三个任务:

墨绿色表示 3 个任务都已成功执行,您可以点击 最近任务 进行验证:

这意味着包含股票数据的 2 个更新的 CSV 文件已经保存到指定的位置。如果出现问题,并且您希望再次检查代码,您可以在用户界面中通过单击DAG _ name>Code来完成:

结论
恭喜你!如果你有足够的动力完成本 Airflow 教程的第 1 部分的结尾,你现在应该能够构建你的第一个 ETL 本地管道,并使用它来刷新你个人项目背后的数据。你还学习了如何使用 XCom 类动态连接任务,我希望这些知识在你开始构建更复杂的 Dag 时会派上用场。
在第二部分中,我将向您展示如何在生产中部署气流 Dag,以便它们可以在您睡觉时真正运行,但在此之前,请看看最后两条建议:
- 在本地构建 ETL 管道意味着,除非您的机器启动,Dag 将不会在预定的时间运行。实际上,为了让 Airflow 正常工作,web 服务器和调度程序都需要在后台运行。如果您保持它们运行,而您的系统进入空闲状态,只要您重新激活系统,气流就会覆盖它在不活动期间错过的作业。但是,将 Dag 部署到生产环境将解决这个问题。
- 理解执行日期和开始日期之间的差异以及 Airflow 执行工作流的方式通常并不简单。为了帮助你理解要点,请看一下这篇深入探讨这个话题的文章。
请让我知道你是否喜欢评论中的教程,我希望能在第 2 部分看到你!
你可能也喜欢:
* [## 在你开始第一个项目之前,要掌握 15 个 Git 命令
您需要掌握的最后一个 Git 教程是命令行版本控制。
levelup.gitconnected.com](https://levelup.gitconnected.com/15-git-commands-you-should-learn-before-your-very-first-project-f8eebb8dc6e9) [## Python 中复制的 8 个流行的 SQL 窗口函数
关于如何利用业务分析中的 Pandas 高效复制最常用的 SQL 窗口的教程…
towardsdatascience.com](/8-popular-sql-window-functions-replicated-in-python-e17e6b34d5d7) [## 使用环境变量隐藏您的密码
关于如何在使用 Python 连接到数据库时使用环境变量隐藏密钥的教程
Docker 指标报告中的气流
在官方的 Apache 气流图像上使用 Grafana 来监控队列健康状况等等。
一个令人不安但可能熟悉的情况:您成功地部署了 Airflow,但发现自己不断刷新 webserver UI 以确保一切顺利运行。
您依赖某些警报任务在上游故障时执行,但是如果队列已满并且任务停止,您将如何得到通知?
一个解决方案是:在 Airflow 上部署 Grafana,一个开源的报告服务。

提议的架构

作者图片
首先,我假设对使用 Docker 和 Docker Compose 的气流功能和容器化有基本的了解。更多资源可以在这里找到气流,在这里找到对接,在这里找到对接合成。
参考代码跟随:https://github.com/sarahmk125/airflow-docker-metrics
现在,有趣的事情。
用过的服务
为了将气流度量放入支持警报的视觉上吸引人的仪表板中,在docker-compose.yml文件中声明的 Docker 容器中增加了以下服务:
- Airflow: Airflow 在 Dag 中运行任务,这些任务在存储于
./dags/文件夹中的 Python 文件中定义。已经有一个示例 DAG 声明文件。运行多个容器,特别是使用官方apache/airflow图像的细微差别。稍后会详细介绍。 - StatsD-Exporter:StatsD-Exporter 容器将 StatsD 格式的气流度量转换为 Prometheus 格式,即报告层(Grafana)的数据源。有关 StatsD-Exporter 的更多信息,请点击查看。容器定义包括启动时要执行的命令,定义如何使用公开的端口。
statsd-exporter:
image: prom/statsd-exporter
container_name: airflow-statsd-exporter
command: "--statsd.listen-udp=:8125 --web.listen-address=:9102"
ports:
- 9123:9102
- 8125:8125/udp
- Prometheus : Prometheus 是一个常用于时间序列数据报告的服务。由于 Prometheus 是一个受支持的数据源,所以在使用 Grafana 作为报告 UI 时特别方便。更多关于普罗米修斯的信息请点击查看。容器定义中装载的卷指示数据如何流入/流出 Prometheus。
prometheus:
image: prom/prometheus
container_name: airflow-prometheus
user: "0"
ports:
- 9090:9090
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- ./prometheus/volume:/prometheus
- Grafana 是一个报告 UI 服务,通常用于连接非关系数据库。在中描述的代码中,Grafana 使用 Prometheus 作为仪表板的数据源。容器定义包括门户的管理员用户,以及定义已经预先配置的数据源和仪表板的卷。
grafana:
image: grafana/grafana:7.1.5
container_name: airflow-grafana
environment:
GF_SECURITY_ADMIN_USER: admin
GF_SECURITY_ADMIN_PASSWORD: password
GF_PATHS_PROVISIONING: /grafana/provisioning
ports:
- 3000:3000
volumes:
- ./grafana/volume/data:/grafana
- ./grafana/volume/datasources:/grafana/datasources
- ./grafana/volume/dashboards:/grafana/dashboards
- ./grafana/volume/provisioning:/grafana/provisioning
让它走
要启动一切,需要以下工具:Docker、docker-compose、Python3、Git。
步骤(在终端中运行):
- 克隆存储库:
git clone [https://github.com/sarahmk125/airflow-docker-metrics.git](https://github.com/sarahmk125/airflow-docker-metrics.git) - 导航到克隆的文件夹:
cd airflow-docker-metrics - 启动容器:
docker-compose -f docker-compose.yml up -d(注意:除了最后分别用stop或down外,可以通过运行相同的命令来停止或移除容器)
结果:
- air flow web server UI:http://localhost:8080

作者图片
- StatsD 指标列表:http://localhost:9123/metrics

作者图片
- 普罗米修斯: http://localhost:9090

作者图片
- grafana:http://localhost:3000(登录:username= admin ,password =password)
该存储库包括一个气流指标仪表板,可以设置警报,显示一段时间内正在运行和排队的任务数量:

作者图片
解释的步骤
普罗米修斯实际上是如何得到度量的?
Prometheus 在启动时配置在作为卷挂载的./prometheus/prometheus.yml文件中:
global:
scrape_interval: 30s
evaluation_interval: 30s
scrape_timeout: 10s
external_labels:
monitor: 'codelab-monitor'scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['airflow-prometheus:9090']
- job_name: 'statsd-exporter'
static_configs:
- targets: ['airflow-statsd-exporter:9102']
tls_config:
insecure_skip_verify: true
特别是,scrape_configs部分声明了要抓取的目的地(airflow-prometheus容器)和源(airflow-statsd-exporter容器)。
如何在 Grafana 中创建仪表板和警报?
供应是您的朋友!
Grafana 中的供应意味着使用代码来定义数据源、仪表板和启动时存在的警报。当启动容器时,在localhost:3000/data sources中已经配置了一个Prometheus数据源,并且在localhost:3000/dashboards中列出了一个Airflow Metrics仪表板。
如何调配:
- 所有相关数据都作为卷安装到在
docker-compose.yml文件中定义的grafana容器中(如上所述) ./grafana/volume/provisioning/datasources/default.yaml文件包含所有数据源的定义:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
./grafana/volume/provisioning/dashboards/default.yaml文件包含关于在容器中何处安装仪表板的信息:
apiVersion: 1
providers:
- name: dashboards
folder: General
type: file
editable: true
updateIntervalSeconds: 10
allowUiUpdates: true
options:
path: /grafana/dashboards
foldersFromFilesStructure: true
./grafana/volume/dashboards/文件夹包含.json文件,每个文件代表一个仪表板。 airflow_metrics.json 文件在上面显示的仪表板中产生结果。
按照这些指令可以从 Grafana UI 中检索 JSON。
UI 中的警报可以按照这里的所述进行设置;这里还有一篇优秀的中型文章关于设置 Grafana alerting with Slack 的。可以采用与仪表板和数据源相同的方式提供警报。
额外话题:官方气流图像
在有官方 Docker 形象之前,Matthieu“puck El _”rois il发布了 Docker 对气流的支持。从 Airflow 版本 1.10.10 开始,Apache 软件基金会在 DockerHub 上发布了一个官方图像,这是唯一一个当前持续更新的图像。然而,许多人仍然依赖传统的和非官方的库。
为什么这是一个问题?好吧,依赖遗留库意味着在版本 1.10.9 中限制气流。Airflow 1.10.10 开始支持一些很酷的功能,比如在 Kubernetes 上运行任务。官方仓库也将是即将到来的(和高度期待的)气流 2.0 将被释放。
在描述的仓库中为webserver找到的新的docker-compose声明看起来像这样:
webserver:
container_name: airflow-webserver
image: apache/airflow:1.10.12-python3.7
restart: always
depends_on:
- postgres
- redis
- statsd-exporter
environment:
- LOAD_EX=n
- EXECUTOR=Local
- POSTGRES_USER=airflow
- POSTGRES_PASSWORD=airflow
- POSTGRES_DB=airflow
- AIRFLOW__SCHEDULER__STATSD_ON=True
- AIRFLOW__SCHEDULER__STATSD_HOST=statsd-exporter
- AIRFLOW__SCHEDULER__STATSD_PORT=8125
- AIRFLOW__SCHEDULER__STATSD_PREFIX=airflow
-AIRFLOW__CORE__SQL_ALCHEMY_CONN= postgresql+psycopg2://airflow:airflow@postgres:5432/airflow
-AIRFLOW__CORE__FERNET_KEY= pMrhjIcqUNHMYRk_ZOBmMptWR6o1DahCXCKn5lEMpzM=
- AIRFLOW__CORE__EXECUTOR=LocalExecutor
- AIRFLOW__CORE__AIRFLOW_HOME=/opt/airflow/
- AIRFLOW__CORE__LOAD_EXAMPLES=False
- AIRFLOW__CORE__LOAD_DEFAULT_CONNECTIONS=False
- AIRFLOW__WEBSERVER__WORKERS=2
- AIRFLOW__WEBSERVER__WORKER_REFRESH_INTERVAL=1800
volumes:
- ./dags:/opt/airflow/dags
ports:
- "8080:8080"
command: bash -c "airflow initdb && airflow webserver"
healthcheck:
test: ["CMD-SHELL", "[ -f /opt/airflow/airflow-webserver.pid ]"]
interval: 30s
timeout: 30s
retries: 3
从puckel/docker-airflow配置的一些变化来突出:
- 以前在
airflow.cfg文件中发现的自定义参数,如AIRFLOW__CORE__SQL_ALCHEMY_CONN,现在被声明为docker-compose文件中的环境变量。 - 初始化后端数据库的
airflow initdb命令现在在docker-compose文件中被声明为一个命令,而不是一个入口点脚本。
瞧啊。
这就是了。再也不用担心你的任务被无限地排队而没有运行。气流在 Docker 中运行,Grafana 中的仪表盘和警报触手可及。相同的架构可以在部署在 GCP 或 AWS 的实例上运行,以实现全天候监控,就像在本地运行一样。
成品可以在这里找到:https://github.com/sarahmk125/airflow-docker-metrics
需要注意的是,总有改进的空间:
- 此监视设置不会捕获容器或实例故障;需要一个单独的或扩展的解决方案来在容器或实例级别进行监控。
- 当前代码使用 LocalExecutor 运行,这对于大型工作负载来说不太理想。可以用 CeleryExecutor 做进一步的测试。
- 在 StatsD 中还有许多没有突出显示的可用指标(例如 DAG 或任务持续时间、任务失败次数等。).可以在 Grafana 中构建和提供更多的仪表板,以利用所有相关的指标。
- 最后,本文重点关注自托管(或高度可配置的云)气流部署,但这不是部署气流的唯一选择。
有问题吗?评论?
感谢阅读!我喜欢谈论数据堆栈。给我发个消息。
气流调度间隔 101
气流调度间隔可能是一个很难理解概念,即使对于从事气流工作的开发人员来说也很难理解。StackOverflow 上偶尔会出现一个令人困惑的问题:“为什么我的 DAG 没有按预期运行?”。这个问题通常表明气流调度间隔中的误解。在本文中,我们将讨论如何设置气流调度间隔,调度气流 Dag 的预期结果,以及如何通过示例调试气流调度间隔问题。

气流如何调度 DAGs?
首先,气流不是流式解决方案。人们通常把它作为 ETL 工具或 cron 的替代品。由于 Airflow 有自己的调度程序,并且它采用 cron 的调度时间间隔语法,因此 Airflow 调度程序中最小的数据和时间间隔是分钟。在调度程序内部,唯一持续运行的是调度程序本身。
然而,作为一个非流式解决方案,以避免锤你的系统资源,气流不会看,并触发你的 Dag 的所有时间。它以一定的时间间隔安排监控,这是一个名为scheduler_heartbeat_sec的可配置设置,建议您提供一个大于 60 秒的数字,以避免生产中出现一些意外结果。原因是 Airflow 仍然需要一个后端数据库来跟踪所有的进程,以防崩溃。设置更少的心跳秒数意味着 Airflow scheduler 必须更频繁地检查以查看是否需要触发任何新任务,这会给 Airflow scheduler 及其后端数据库带来更大的压力。
最后,气流调度器遵循心跳间隔,并遍历所有 DAG,计算它们的下一个调度时间,并与挂钟时间进行比较,以检查是否应该触发给定的 DAG。
为什么你需要一个开始日期?
每个 DAG 都有自己的时间表,start_date 就是 DAG 应该被包含在气流调度程序中的日期。它还有助于开发人员在 DAG 的生产日期之前发布它。你可以在气流 1.8 之前更动态地设置start_date 。但是,建议您设置一个固定的日期,更多详细信息可参考“动态 start_date 上的宽松调度程序”。
我们应该使用哪个时区?
气流基础设施最初仅从 UTC 开始。尽管您现在可以将 Airflow 配置为在您的本地时间运行,但大多数部署仍然采用 UTC。在 UTC 下设置气流使跨越多个时区的业务变得容易,并使您在夏令时等偶然事件中的生活更加轻松。您设置的计划间隔将与您的气流基础设施设置相同。
如何设置气流调度间隔?
您可能熟悉定义 DAG 的语法,并且通常在 DAG 类的args下实现start_date 和scheduler_interval 。
from airflow import DAG
from datetime import datetime, timedeltadefault_args = {
'owner': 'XYZ',
'start_date': datetime(2020, 4, 1),
'schedule_interval': '@daily',
}dag = DAG('tutorial', catchup=False, default_args=default_args)
为 schedule_interval 提供什么值?
气流调度器部分提供了关于您可以提供什么值的更多详细信息。当然,你需要一个 crontab 来处理scheduler_interval。如果你发现自己迷失在 crontab 的定义中,尝试使用 crontab guru ,它会解释你放在那里的内容。气流也给你一些用户友好的名字,如@daily或@weekly。我发现这些名字不如 crontab 简洁明了。它也仅限于几个时间间隔,底层实现仍然是 crontab,因此您甚至可能想要学习 crontab 并接受它。此外,如果你只是想触发你的 DAG,使用手动schedule_interval:None。
execution_date 和 start_date 有什么区别?
作为调度程序,日期和时间是非常必要的组件。在《气流》中,有两个日期你需要付出额外的努力去消化:execution_date 和start_date。注意start_date与您在之前的 DAG 中定义的日期不同。
- execution_date 是您期望 DAG 被触发的 start 日期和时间。
- start_date 是 DAG 被触发的日期和时间,这个时间通常是指挂钟。
一个常见的问题是,“为什么 execution_date 不同于 start_date?”为了得到这个问题的答案,让我们看看一个 DAG 的执行情况,并使用**0 2 * * ***、、,这有助于我们更好地理解气流计划间隔。请参考以下代码作为示例。
调度程序 101 DAG
**0 2 * * *** 意思是每天凌晨两点气流会开始新的工作。我们可以让具有此间隔的 DAG 运行多天。如果你点击Browse → Tasks Instances,你会看到执行日期和开始日期。
我在 04–10 00:05:21(UTC)启动了这个新的 DAG,任何新的气流 DAG 通常首先会进行回填,这是默认启用的。正如您在下面的快照中所看到的, execution_date 按照预期完美地按天递增,时间也是预期的。另一方面, start_date 是气流调度程序开始任务的时间。

任务实例示例(作者图片)
在回填了所有之前的执行之后,您可能会注意到 04–09 不在这里,但是现在已经是 04–10 挂钟了。这里出了什么问题?
答案是:没什么问题。

来源:托尼·巴贝尔来自 https://gph.is/2jqoiRI
首先,Airflow 是用 ETL 思维构建的,这通常是一个 24 小时运行的批处理。考虑一个 ETL 作业,在 24 小时的窗口内,只有在 24 小时结束后才触发作业。同样的规则也适用于此,我们没有看到 04–09 上的 execution_date 是因为 24 小时窗口尚未关闭。从 execution_date,我们知道最后一次成功运行是在 04–08t 02:00:00(记住 execution_date 这里是 24 小时窗口的开始时间),它结束于 04–09t 02:00:00(不含)。那么,04-09 运行的 24 小时窗口是什么呢?就是 04–09t 02:00:00 到 04–10t 02:00:00,还没到。

执行数据和开始日期的关系(图片由作者提供)
气流调度程序何时运行 04–09 执行?它会一直等到 04–10 02:00:00(挂钟)。一旦 04–09 的执行被触发,您将看到 execution_date 为 04–09t 02:00:00,而 start_date 将类似于 04–10t 02:01:15(这随着 Airflow 决定何时触发任务而变化,我们将在下一节中介绍更多)。
鉴于上述背景,你很容易明白为什么的执行日期与的开始日期不同。理解执行日期和开始日期之间的区别将会非常有帮助,当你尝试基于执行日期应用你的代码并使用类似{{ds}}的宏时
另一种思考方式是:执行日期将接近前一个开始日期。我们用一个更复杂的例子:**0 2 * * 4,5,6** ,这个 crontab 的意思是周四周五周六 02:00 运行。
下面是挂钟或开始日期的日历,红色文本是预计的执行日期。如果您有这样的计划间隔,那么对于气流会在 04–09 触发 04–04DAG 执行,您应该不会感到惊讶。

时间间隔示例(图片由作者提供)
为什么触发 Dag 会有短暂的延迟?
从上面的例子中,虽然我们发现日期不同,但时间略有不同。例如,对于每日间隔,执行日期为 04–09t 02:00:00,开始日期为 04–10t 02:01:15。气流对那 1.25 分钟的延迟有什么作用?
这类似于一个会议场景。你可能不会按照日历上的时间开始会议。比如,你有一个每周一上午 10:00:00 的虚拟会议邀请( scheduler_interval )。在本周一上午 10:00:00(execution _ date),您从日历提醒中收到加入会议的通知,然后您单击该会议链接并开始您的虚拟会议。当您进入会场,会议开始时,时间是上午 10:01:15(start _ date)。

您可能已经注意到了 execution_date 和 start_date 之间的小延迟。理想情况下,它们应该是相同的,但现实并非如此。问题是为什么气流不会按时触发 DAG 并延迟其实际运行?正如我们之前讨论的,气流调度器不会一直监控 Dag。调度程序等待其下一个心跳来触发新的 Dag,这一过程会导致延迟。此外,即使调度程序准备在同一时间触发,您也需要考虑代码执行和数据库更新时间。以上原因都会造成调度的短暂延迟。
最终想法
我希望这篇文章可以揭开气流调度间隔是如何工作的。气流是一个内部复杂的系统,但对用户来说很简单。按照最初的 ETL 思维方式,理解气流调度器如何处理时间间隔可能需要一些时间。一旦您更好地理解了气流调度间隔,创建具有期望间隔的 DAG 应该是一个无障碍的过程。
希望这个故事对你有帮助。本文是我的工程&数据科学系列的部分,目前包括以下内容:

数据工程和数据科学故事
View list47 stories


你也可以 订阅我的新文章 或者成为 推荐媒介会员 可以无限制访问媒介上的所有故事。
如果有问题/评论,请不要犹豫,写下这个故事的评论或者通过 Linkedin 或 Twitter 直接联系我。
气流—在任务之间共享数据

作者图片
如果你在网上寻找气流教程,大多数都会给你很好的介绍什么是气流。他们将从概念上谈论 ETL,DAG 是什么,构建第一个 DAG 并向您展示如何执行它。经常被忽略的是 DAG 的任务应该如何交换数据。
本文假设你至少对什么是气流及其工作原理有一个基本的了解。
如果你在网上寻找气流教程,大多数都会给你很好的介绍什么是气流。他们将从概念上谈论 ETL,DAG 是什么,构建第一个 DAG 并向您展示如何执行它。
经常被忽略的是这些任务应该如何交换数据。
在构建任务时要记住的一点是,任务必须是幂等的。简化一下我们的例子,这意味着如果使用相似的输入参数执行成功,那么无论您调用它们多少次,它们都会产生相同的结果。当与任务输入/输出相结合时,这可能并不总是显而易见的。
当考虑数据交换时,我们可以区分以下任务:
- 根本不需要共享数据
- 只分享一小块信息
- 运算符本身存储作为其执行结果的数据
- 可以以存储结果的方式编写的运算符
- 使用气流挂钩保存或读取结果的自定义操作员
不需要数据共享
这种任务关系的简单例子是在第一个任务中在数据库中创建一个表,并在下一个任务中填充该表。
这里最重要的是执行顺序。我们需要确保表存在,以便我们可以写入它。在我们的例子中,我们只需要确保第一个任务在第二个任务的上游,我们就可以开始了:
create_table.set_upstream(populate_table)
或者用我最喜欢的语法:
create_table >> populate_table
共享小块数据
在这里,达格的 XComs 开始发挥作用。它们易于使用,并允许在运行 DAG 的任何任务之间共享数据。它们被永久地保存在 Airflow 的元数据数据库中,但是我考虑在单个 DAG 之外使用它们作为反模式。
我听说过人们使用 XCom 在任务间共享大数据集的情况,这肯定是可能的,但由于一些原因应该避免。
首先,它破坏了元数据数据库,打破了气流是什么的概念——一个应该最低限度地参与执行和数据存储的编排器。
第二,不是所有的东西都可以储存。基本上,XCom 数据是泡菜,泡菜也有其局限性。
此外,有时 XComs 可能包含敏感数据,在决定将其存储在 Airflow 的数据库中之前,您应该三思而行。
应该记住的是,如果任务返回结果,那么这些结果将可用于下一个任务的“拉取”。不幸的是,您知道它们是否返回结果的唯一方法是深入研究 Operator 的源代码(我强烈推荐这种方法,因为它将极大地提高您对气流如何工作的理解)。
我不知道使用 XCom 共享的数据的最大大小应该是多少,但是我想说,如果它能加速 DAGs 的开发,那么几 MB 是可以的。或者换句话说,如果你的任务的结果没有内置的结果“存储”,你会觉得懒惰🙂要编写单独的操作符,您可以考虑将其推送到 XCom。
具有“本地”结果存储的操作员
很容易知道 operator 是否会存储它的执行结果,因为它是传递给 operator 类的参数之一。这里的示例是“BigQueryExecuteQueryOperator ”,其中查询输出被保存到另一个表中:
execute_query = BigQueryExecuteQueryOperator(
task_id="execute_query_save",
sql="SELECT * FROM MY_DATASET.TABLE_IN",
use_legacy_sql=False,
destination_dataset_table="MY_DATASET.TABLE_OUT")
为了使用结果,流水线中的下一个任务必须到达 TABLE_OUT。
可以被“强制”存储数据的操作员
假设我们的操作符没有等效的“destination_dataset_table”参数。
当然,您可以通过继承“BigQueryExecuteQueryOperator”来编写自己的操作符,但有时更简单的选择是编写您的查询,以便将结果存储在某个地方。类似于:
INSERT INTO TABLE_OUT
SELECT <columns> FROM TABLE_IN
自定义操作员读/写
如果你运气不好,剩下的就是使用气流的钩子来完成这项工作。该选项既可用于写入任务的结果数据,也可用于在下一个必须使用它的任务中读取数据。是的,这意味着您必须编写一个自定义任务,例如如下所示:
def load_data(ds, **kwargs):
conn = PostgresHook(postgres_conn_id=src_conn_id).get_conn() # Notice: cursor had to be named to make loading in batches work (so called "server cursor")
cursor = conn.cursor('serverCursor')
cursor.execute(kwargs['query']) while True:
records = cursor.fetchmany(size=10000)
if not records:
break
*[ ... do something with records ...]* cursor.close()
conn.close()
并使用例如“PythonOperator”来执行它:
load_and_transform = PythonOperator(task_id='load_and_transform',
python_callable=load_data,
op_kwargs={'query': 'SELECT * FROM TABLE_IN'},
provide_context=True,
dag=your_dag)
我希望这些简单的技巧能帮助你写出更可靠的任务。
旁注:如果你正在寻找在任务间传递数据时更友好的工具,可以看看与 Airflow 有很多相似之处的 impfect . io,并尝试修复 Airflow 的错误。请记住,使用它并不是完全免费的。
气流状态 101
阿帕奇气流状态概述

(图片由 Unsplash 上的 Zbynek Burival 拍摄)
在 Airflow 中,为了描述等待执行后续步骤的 DAG 或任务的状态,我们定义了 State 来共享有关管道进度的信息。如果没有状态,任何 DAG 或任务的执行都会变成黑盒,您可能需要创建额外的外部标志或资源来检查状态,以帮助确定作业是完成还是失败。幸运的是,Airflow 提供了状态机制,并将最近记录的每个状态存储在其后端数据库中。这种方式不仅易于在 Airflow UI 或 DB 中查看任何作业的状态,而且它还是一个持久层,有助于在遇到故障时重新运行或回填。
在本文中,我们将讨论什么是气流状态,这些状态有哪些类型,如何使用气流状态进行测试和调试。可能有外部服务,气流也可能跟踪这些状态,但这些状态不在我们讨论的范围内。
国家在气流中做什么?
现实生活中状态的一个很好的例子就像交通灯。你会有三种状态:红色、黄色和绿色。红灯禁止任何车辆通行,而绿灯允许车辆通行。

走红绿灯(Gif By SPAR
气流状态的最基本用法是指定当前状态,并指定气流调度程序来决定未来的动作。虽然气流有更多的状态,类似于红绿灯,但也有一些共同的特征。
- 没有双重状态。在气流中,状态是单个值。不允许双重状态。这样,一个同时有“Failed”和“UP_FOR_RETRY”的状态在这里就没有太大意义了。
- 状态是静态的,或者是给定时刻的快照。Airflow 将状态保存在其后端数据库中,并且状态的更新不是一个连续的过程。由于 Airflow 调度程序的心跳间隔,您可能会遇到数据库中的状态更新滞后,调度程序停止运行的罕见情况。
- 状态有一个定义的生命周期。气流库中有详细的生命周期图。状态必须遵循生命周期的流程,除了重试的情况,状态通常不能后退。
那些状态是什么?我什么时候能见到他们?
对于当前版本的气流 1.10.11,气流中的状态有两个主要类别:任务和运行。
- Dagrun:成功,正在运行,失败;
- 任务:成功、正在运行、失败、上游失败、已跳过、启动重试、启动重新计划、排队、无、已计划。

气流任务等级状态(作者供图)
DAG 是任务的集合;DAG 的状态就像你家里的主电源开关。如果它失败了,即使您让它的任务继续运行,气流调度程序也会忽略它,因为 dagrun 的状态是 failed。

DAG 级别的状态就像主电源开关(Ariel Victor 的黑白动画 GIF)
任务级别的状态处于更细粒度的级别,因为任务之间可能存在依赖关系。一些状态可能有多个连续的状态,这就是为什么在任务级别有更多的状态来处理更复杂的情况。例如,upstream_failed 表示当前任务由于上游失败而无法执行。
查看状态的另一种方式是查看状态是已完成还是未完成。完成状态意味着气流调度程序将不再监控它们,因此它不在调度和监控的范围内。另一方面,对于未完成状态,那些是待定状态,对于当前未完成状态将有即将到来的改变,但是最终目标是达到完成状态。
至于现在,已完成的状态是 SUCCESS,FAILED,UPSTREAM_FAILED(注意这一个在已完成状态列表中没有提到),和 SKIPPED,其余都是未完成状态。
让我们更详细地检查每个状态并进行讨论。

成功状态
成功 (在 dagrun 和任务级别|完成状态下):成功状态表示气流在运行作业时没有遇到任何错误,并且成功完成。在气流中,dagrun 有一个深绿色的圆圈,任务等级有一个深绿色的方块。即使对于一个虚拟任务,因为没有任何错误,虽然气流在这里没有执行任何有意义的事情,但它仍然会将虚拟任务视为成功,因为我们告诉气流不要运行任何东西,气流应该会将成功返回给我们。

运行状态
正在运行 (在 dagrun 和任务级别|未完成状态状态中):正在运行状态确定气流调度器已经将那些 dag 或任务分配给执行器。它正在监视(通过心跳)它的状态,执行器正在运行实际的作业。在气流中,dagrun 有一个浅绿色的圆圈,任务等级有一个浅绿色的方块。由于运行是一种未完成状态,因此在任何给定时间,您的 dag 或任务都可能失败,然后会导致重试或失败状态。此外,在任务级别,当给定的任务仍在运行时,如果您重新运行任务本身(通过清除其状态),有时气流调度程序会进入关闭状态,这是关闭和终止任务的外部请求。

失效状态
失败 (在 dagrun 和任务级|完成状态下):失败状态向用户指出在执行期间出现了问题,气流无法调度执行到底。在气流中,dagrun 有一个红圈,任务等级有一个红方块。由于气流中没有双重状态,对于部分成功,dagrun 仍然会标记为失败,以便用户进一步探索。另一方面,在任务层,Airflow 标记了确切的失败任务,并且该任务的所有下游都标记为 UPSTREAM_FAILED(如果 trigger_rule 默认为 all_success ),这很好地帮助用户立即找到失败的最初原因。

上游 _ 失败状态
UPSTREAM_FAILED (仅限任务级|完成状态):上游失败状态是指上游发生了一些错误的状态。您也可以有多个上游,在这种情况下,您可以考虑 trigger_rule ,它默认为 all_success 。在这种情况下,如果任何上游任务失败,就会得到 UPSTREAM_FAILED。然而,如果你不想有这种行为,气流提供了更多的选项,例如,你可以做 one_success,如果只有一个上游任务是成功的,它将继续当前的任务。

跳过状态
跳过 (仅限任务级|完成状态):跳过状态是已经被忽略执行的任务,调度器绕过该任务继续执行。在分支操作中,跳过一个任务通常是一种预期的行为,您有多个条件可以选择,一旦决定了其中的一些,未选择的将被标记为跳过。您还可以在不使用分支运算符的情况下明确标记跳过的任务,这涉及手动设置气流状态。每当您跳过一个任务时,它的所有下游任务也会被跳过。

启动重试状态
UP_FOR_RETRY (仅任务级|未完成状态):UP _ FOR _ RETRY 状态表示之前的尝试已经失败,因为该任务已经重试了多次,它被标记为准备重试。但是在下一次迭代中,任务需要等待多长时间才能重试呢?气流调度程序在重试时间间隔过后等待,并在下一个调度程序的心跳到达时启动。

启动重新计划状态
UP _ FOR _ schedule(仅任务级|未完成状态):UP _ FOR _ schedule 是自 Airflow 1.10.2 以来新引入的状态,更多细节可以参考 Apache Airflow 1.10.2 新版本中的亮点。这种状态主要适用于传感器,它有助于避免消耗所有工作插槽,以便解决死锁情况。

排队状态
排队 (仅任务级|未完成状态):当任务等待执行器中的槽时,触发队列状态。队列状态只是一个等待执行程序在管道中执行簿记的列表,执行程序将任务分配给工作程序来运行实际的任务。一旦一个槽可用,就从队列中拉出一个任务(有优先级),工人将运行它。

无状态
无 (仅任务级|未完成状态):无状态可能会引起混淆,因为它在某些语言中表示未知。这里它只是一种描述新任务创建的方式,它的初始状态是未知的。当一个新的 dagrun 启动时,您会观察到 None 状态,它的所有任务首先都是 None。此外,如果您想要重新运行某些 Dag 或任务,一旦您清除了状态,所有这些状态都将变为 None 状态。在后端,如果是第一次启动 dagrun,尽管所有任务都处于 NONE 状态,但在任务被调度之前,您不会在 DB 中找到任何条目。然而,重新运行一个任务来清除它的状态是另一回事,在重新运行之前,您会在 DB 中找到它以前的状态。
已调度 (仅限任务级|未完成状态)已调度状态是让气流将任务发送给执行者运行。气流调度程序检查多种条件,以确定是否可以调度任务。例如,由于整个气流中的可用时隙,以及挂钟时间和计划时间之间的时间,任务可以被阻止进行计划。一旦满足了调度的所有条件,气流调度器就会将任务推进到调度状态。
一个令人兴奋的功能是改变气流用户界面的颜色。如果你不喜欢默认的,这个新特性是在 Airflow 1.10.11 中引入的,你可以在 UI 中自定义状态颜色
气流任务状态的生命周期

气流任务生命周期图(来自阿帕奇气流
该状态由气流调度器和执行器驱动和控制。Airflow 官方 GitHub 有这个生命周期图,很好地展示了状态流程图。我们已经讨论了每个状态和传感器的状态(UP _ FOR _ RESCHEDULE)。此图还显示了每个组件的可能状态列表。可选阶段转换是每个气流操作器的选项,由用户控制以可选地执行重试。尽管如此,所有其他阶段都必须遵循这个转换流程。
最终想法

五彩缤纷的国家(照片由汉娜·摩根在 Unsplash 上拍摄)
状态是气流生态系统中不可或缺的元素。状态就像气流中的安全带。它对每个 dagrun 和任务进行跟踪,每当 Airflow 调度器、执行器或工作器中出现崩溃时,状态会作为检查点执行,因此我们不必从头开始。此外,由于状态也显示在 Airflow UI 中,每个人都将其作为监控状态的中心位置。最后,Airflow 在内部使用状态来跟踪任务的进度,工程师可以依靠状态来执行更多定制的任务。我希望这篇文章能给你一个气流状态的基本概念,以及为什么理解每种状态之间的区别是必要的。干杯!!
希望这个故事对你有帮助。本文是我的工程&数据科学系列的部分,目前包括以下内容:

数据工程和数据科学故事
View list47 stories


你也可以 订阅我的新文章 或者成为 推荐媒介会员 无限制访问媒介上的所有故事。
如果有问题/评论,请不要犹豫,写下这个故事的评论或通过 Linkedin 或 Twitter 直接联系我。
气流 vs .路易吉 vs .阿尔戈 vs. MLFlow vs .库伯流
选择任务编排工具

来源:作者
任务协调工具和工作流
最近,用于编排任务和数据工作流的新工具激增(有时被称为“MLOps”)。这些工具的数量会使我们很难选择使用哪些工具,也很难理解它们是如何重叠的,所以我们决定直接比较一些最流行的工具。

气流是最受欢迎的解决方案,其次是 Luigi。也有新的竞争者,他们都在快速成长。(来源:作者)
总的来说,Apache Airflow 是最受欢迎的工具,也是功能最广泛的工具,但是 Luigi 是一个类似的工具,更容易上手。当他们已经在使用 Kubernetes 时,Argo 是他们经常求助的一个团队,Kubeflow 和 MLFlow 服务于更多与部署机器学习模型和跟踪实验相关的利基需求。
在我们深入进行详细的比较之前,理解一些与任务编排相关的更广泛的概念是有用的。
什么是任务编排,为什么它有用?
较小的团队通常从手动管理任务开始,例如清理数据、训练机器学习模型、跟踪结果以及将模型部署到生产服务器。随着团队和解决方案规模的增长,重复步骤的数量也在增长。可靠地执行这些任务也变得更加重要。
这些任务相互依赖的复杂方式也在增加。当您开始时,您可能有一个需要每周或每月运行一次的任务流水线。这些任务需要以特定的顺序运行。随着你的成长,这条管道变成了一个拥有动态分支的网络。在某些情况下,一些任务会引发其他任务,而这些任务可能依赖于其他几个先运行的任务。
这个网络可以被建模为 DAG——一个有向无环图,它对每个任务以及它们之间的依赖关系进行建模。

流水线是一个有限的 DAG,其中每个任务最多有一个上游和一个下游依赖。(来源:作者)
工作流编排工具允许您通过指定所有任务以及它们如何相互依赖来定义 Dag。然后,该工具按计划以正确的顺序执行这些任务,在运行下一个任务之前重试任何失败的任务。它还监控进度,并在出现故障时通知您的团队。
像 Jenkins 这样的 CI/CD 工具通常用于自动测试和部署代码,这些工具和任务编排工具之间有很强的相似性——但也有重要的区别。尽管理论上你可以使用这些 CI/CD 工具来编排动态的、相互关联的任务,但是在一定的复杂程度上,你会发现使用更通用的工具比如 Apache Airflow 会更容易。
【想要更多这样的文章?注册我们的简讯。我们每周最多分享一篇文章,从不发送任何形式的推广邮件】。
总体而言,任何编排工具的重点都是确保集中化、可重复、可再现、和高效的工作流:所有自动化任务的虚拟指挥中心。记住这一点,让我们看看一些最流行的工作流工具是如何组合起来的。
告诉我用哪一个
您可能应该使用:
- Apache air flow如果你想要功能最全、最成熟的工具,你可以花时间去学习它的工作原理、设置和维护它。
- Luigi如果你需要比气流更容易学习曲线的东西。它的功能更少,但更容易起飞。****
- 如果你已经深深地投入到 Kubernetes 生态系统中,并且想要以 pods 的形式管理你的所有任务,那么就用 YAML 而不是 Python 来定义它们。
- kube flow如果你想使用 Kubernetes 但仍然用 Python 而不是 YAML 来定义你的任务。
- MLFlow 如果你更关心跟踪实验或者使用 MLFlow 的预定义模式跟踪和部署模型,而不是寻找一个可以适应你现有定制工作流的工具。
对照表

(来源:作者)-获得更多机器学习技巧— 获取我们的每周简讯
为了快速概述,我们在以下方面对这些库进行了比较:
- 成熟度:基于项目的年龄以及修复和提交的数量;
- 人气:基于领养和 GitHub 明星;
- 简单:基于易于入职和采用;
- 广度:基于每个项目的专业化程度和适应性;
- 语言:基于您与工具交互的主要方式。
这些不是严格或科学的基准,但它们旨在让您快速了解这些工具是如何重叠的,以及它们彼此之间有何不同。更多细节,请看下面的头对头对比。
路易吉与气流
Luigi 和 Airflow 解决类似的问题,但 Luigi 要简单得多。它包含在单个组件中,而 Airflow 有多个模块,可以以不同的方式进行配置。Airflow 拥有更大的社区和一些额外的功能,但是学习曲线要陡峭得多。具体来说,Airflow 在调度方面要强大得多,它提供了一个日历 UI 来帮助您设置任务应该何时运行。使用 Luigi,您需要编写更多自定义代码来按计划运行任务。
这两个工具都使用 Python 和 Dag 来定义任务和依赖关系。如果你有一个小团队,需要快速上手,就用 Luigi。如果你有一个更大的团队,可以使用气流,一旦你度过了学习曲线,可以用最初的生产力打击来换取更多的权力。
路易吉对阿尔戈
Argo 建立在 Kubernetes 之上,每个任务作为一个独立的 Kubernetes pod 运行。如果您已经将 Kubernetes 用于您的大部分基础设施,这可能很方便,但是如果您没有,这将增加复杂性。Luigi 是一个 Python 库,可以和 Python 包管理工具一起安装,比如 pip 和 conda。Argo 是 Kubernetes 的扩展,使用 Kubernetes 安装。虽然这两个工具都允许你将任务定义为 Dag,但使用 Luigi,你将使用 Python 来编写这些定义,而使用 Argo,你将使用 YAML。
如果你已经投资了 Kubernetes,并且知道你所有的任务都是 pods,那么就使用 Argo。如果编写 DAG 定义的开发人员对 YAML 比对 Python 更熟悉,您也应该考虑这一点。如果您没有在 Kubernetes 上运行,并且团队中有 Python 专家,请使用 Luigi。
路易吉对库伯弗洛
Luigi 是一个基于 Python 的库,用于一般的任务编排,而 Kubeflow 是一个基于 Kubernetes 的工具,专门用于机器学习工作流。Luigi 是为编排一般任务而构建的,而 Kubeflow 则为实验跟踪、超参数优化和 Jupyter 笔记本服务提供了预构建的模式。Kubeflow 由两个不同的组件组成:Kubeflow 和 Kubeflow 管道。后者侧重于模型部署和 CI/CD,它可以独立于主要的 Kubeflow 特性使用。
如果您需要编排各种不同的任务,从数据清理到模型部署,请使用 Luigi。如果您已经使用了 Kubernetes,并且想要协调常见的机器学习任务,如实验跟踪和模型训练,请使用 Kubeflow。
Luigi vs. MLFlow
Luigi 是一个通用的任务编排系统,而 MLFlow 是一个更专业的工具,可以帮助管理和跟踪你的机器学习生命周期和实验。您可以使用 Luigi 来定义一般的任务和依赖项(例如训练和部署模型),但是您可以将 MLFlow 直接导入到您的机器学习代码中,并使用它的帮助器函数来记录信息(例如您正在使用的参数)和工件(例如经过训练的模型)。还可以使用 MLFlow 作为命令行工具,为用常用工具(如 scikit-learn)构建的模型提供服务,或者将它们部署到常用平台(如 AzureML 或 Amazon SageMaker)。
气流与阿尔戈
Argo 和 Airflow 都允许你将任务定义为 Dag,但是在 Airflow 中你用 Python 来完成,而在 Argo 中你用 YAML。Argo 作为一个 Kubernetes pod 运行每个任务,而 Airflow 生活在 Python 生态系统中。Canva 在选择 Argo 之前评估了这两个选项,您可以观看这个演讲,了解他们的详细比较和评估。
如果你想要一个更成熟的工具,不在乎 Kubernetes,就用气流。如果您已经投资了 Kubernetes,并且想要运行在不同堆栈中编写的各种各样的任务,请使用 Argo。
气流与库伯流
Airflow 是一个通用的任务编排平台,而 Kubeflow 则专门专注于机器学习任务,如实验跟踪。这两个工具都允许使用 Python 定义任务,但是 Kubeflow 在 Kubernetes 上运行任务。Kubeflow 分为 Kubeflow 和 Kubeflow 管道:后一个组件允许您指定 Dag,但它更侧重于部署和模型服务,而不是一般任务。
如果您需要一个能够运行各种不同任务的成熟、广阔的生态系统,请使用 Airflow。如果您已经使用了 Kubernetes,并希望机器学习解决方案有更多现成的模式,请使用 Kubeflow。
空气流量与毫升流量
Airflow 是一个通用的任务编排平台,而 MLFlow 是专门为优化机器学习生命周期而构建的。这意味着 MLFlow 具有运行和跟踪实验、训练和部署机器学习模型的功能,而 Airflow 具有更广泛的用例,你可以使用它来运行任何一组任务。Airflow 是一组用于管理和调度任务的组件和插件。MLFlow 是一个 Python 库,可以导入到现有的机器学习代码中,也是一个命令行工具,可以用来训练和部署用 scikit-learn 编写的机器学习模型到 Amazon SageMaker 或 AzureML。
如果您想要一种有见解的、开箱即用的方式来管理您的机器学习实验和部署,请使用 MLFlow。如果您有更复杂的需求,并且希望更多地控制如何管理机器学习生命周期,请使用 Airflow。
阿尔戈对库伯弗洛
Kubeflow 的部分(如 Kubeflow 管道)是建立在 Argo 之上的,但 Argo 是为了编排任何任务而建立的,而 Kubeflow 专注于那些特定于机器学习的任务——如实验跟踪、超参数调整和模型部署。 Kubeflow Pipelines 是 Kubeflow 的一个独立组件,专注于模型部署和 CI/CD,可以独立于 Kubeflow 的其他功能使用。这两个工具都依赖于 Kubernetes,如果你已经采用了它,你可能会更感兴趣。有了 Argo,你可以使用 YAML 定义你的任务,而 Kubeflow 允许你使用 Python 接口。
如果您需要管理作为 Kubernetes pods 运行的一般任务的 DAG,请使用 Argo。如果你想要一个专注于机器学习解决方案的更有主见的工具,请使用 Kubeflow。
Argo vs. MLFlow
Argo 是一个任务编排工具,允许您将任务定义为 Kubernetes pods,并将其作为 YAML 定义的 DAG 运行。MLFlow 是一个更加专业化的工具,它不允许您定义任意的任务或它们之间的依赖关系。相反,您可以将 MLFlow 作为 Python 库导入到现有的(Python)机器学习代码库中,并使用其助手函数来记录工件和参数,以帮助进行分析和实验跟踪。您还可以使用 MLFlow 的命令行工具来训练 scikit-learn 模型,并将它们部署到 Amazon Sagemaker 或 Azure ML,以及管理您的 Jupyter 笔记本。
如果您需要管理一般的任务,并希望在 Kubernetes 上运行它们,请使用 Argo。如果您想要一种自以为是的方式来管理托管云平台的机器学习生命周期,请使用 MLFlow。
Kubeflow 与 MLFlow
Kubeflow 和 MLFlow 都是比通用任务编排平台(如 Airflow 或 Luigi)更小、更专业的工具。Kubeflow 依赖于 Kubernetes,而 MLFlow 是一个 Python 库,可以帮助你在现有的机器学习代码中添加实验跟踪。Kubeflow 允许您构建一个完整的 DAG,其中每个步骤都是一个 Kubernetes pod,但 MLFlow 具有内置功能,可以将您的 scikit-learn 模型部署到 Amazon Sagemaker 或 Azure ML。
如果你想跟踪你的机器学习实验,并在 Kubernetes 的支持下以更加定制的方式部署你的解决方案,请使用 Kubeflow。如果您想要一种更简单的方法来进行实验跟踪,并希望部署到 Amazon Sagemaker 等托管平台,请使用 MLFlow。
没有银弹
虽然所有这些工具都有不同的关注点和不同的优势,但是没有一个工具能够让您一劳永逸。在为选择哪种工具伤脑筋之前,通常重要的是确保你有好的过程,包括好的团队文化、无过失回顾和长期目标。如果你正在努力解决任何机器学习问题,请联系我们。我们喜欢谈论商店,您可以安排与我们的首席执行官进行免费通话。
航空业——预计复苏
使用深度学习和 DCF 预测加拿大航空公司未来三年的股价

伊森·麦克阿瑟在 Unsplash 上的照片
自从全球范围内的封锁和独特的冠状病毒的传播开始以来,全球的航空业一直不景气。
最近,也有很多关于沃伦巴菲特出售他在各航空公司的股份的新闻。与他的行动相反,价值投资者正在鼓励许多人持有航空公司股票,尤其是那些具有长期投资眼光和风险偏好的股票。
接二连三的新闻激起了我的兴趣,我决定进行一些自己的测试来验证我所看到和听到的新闻。
为了更好地理解(在个人层面)航空业和加拿大航空公司的表现,我研究了加拿大的飞机运行情况,使用 LSTM 模型预测加拿大航空公司的未来股票价格,并最终使用贴现现金流(DCF)法得出内在股票价值。
预测加拿大的飞机动向
我从 Stat Canada 收集了从 2015 年 1 月(主要机场)到 2020 年 4 月的飞机起降数据,并进行整理。随后,我在 2018 年 7 月创建了一个与飞机移动相关的指数,因为这是最高的数字-这将使我能够衡量未来牛市中飞机移动的水平。
首先,我创建了一年中所有十二个月的月平均值,并用它来创建每个月的季节性指数(即一个月的月平均值/所有月份的平均值)。然后,我计算了每个月的平均飞机力矩(指数值),并检查了这些值与 2020 年 1 月至 5 月受影响月份的“covid”值之间的差异。2020 年 4 月的指数值为 10,这与航空公司在受 covid 影响的月份削减 85-90%运力的报告相关。

4 月份的产能仅为“历史最佳月份”的 10%
此外,我假设 covid 以及国际旅行限制和封锁的影响将开始显现——至少在 2020 年 6 月底之前对企业和其他重要的经济驱动因素而言。考虑到飞机将不得不接受维护检查,飞行员将不得不在服役前重获“货币”,我将指数差向下调整了 2.5 点,以迎合保守的增长估计。
我的目的是预测价值,直到完成一个稳定的商业周期,因为这将表明飞机活动的正常化。
我发现飞机活动在 2022 年 5 月达到“covid 之前”的水平,并在 2023 年 12 月底稳定下来。

通过 Python 预测未来股票价格
我在 Python 中使用了一个简单的单变量 LSTM 模型来预测加拿大航空公司的未来价格(直到 2023 年 12 月)。在这里找到笔记本(你可以上传自己的数据集来运行测试)。
在航空业面临 9/11 事件的影响期间,我在航空公司股票的数据集上训练并验证了该模型。我选择这个数据集有两个原因。首先,这类似于现在的情况,顾客/公众害怕坐飞机。其次,这些年来,航空业受到了几乎是不可抗力的最严重打击,这导致了世界飞行方式的改变,引入了各种安全法规和检查。由于这将允许必要的业务增长延迟,我认为这将有助于预测更适合后 covid 经济,后者可能面临类似的限制。

红色-股票价格|蓝色-飞机运动
结果表明,加拿大航空公司的股价将在 2023 年 12 月徘徊在 16 美元,这是在经济稳定和复苏之后。
此外,为了衡量加拿大航空公司股票的当前价格,我使用了基本的现金流量贴现法(WACC-5.7%,EV/EBITDA-6x)和格拉汉姆法(TTM 每股收益,调整以反映当前 AAA 债券收益率,增长率为 4%)来计算加拿大航空公司股票的内在价值。
相应计算的内在价值为 9.90 美元和 12.3 美元。Python 模型预测底部为 3.5 美元,然后再次向上移动。
结果和解释
经济— 假设飞机起降代表了航空业的健康(航空业反过来代表了经济的健康),由于大多数旅行都是通过可自由支配的资金进行的,因此经济似乎将在 2021 年第三季度稳定增长,并将在 2022 年第三季度达到 Q2 之前的水平,然后在 2024 年 Q1 完全稳定。有趣的是,国际航空运输协会——一个全球航空公司协会预测,乘客需求将在 2024 年前才会恢复,这有点类似于我的模型对 2023 年 12 月的预测。
航空业— 虽然模型已经以相当初步的方式完成,但航空业似乎将需要三年的大部分时间来恢复。此外,观察消费者行为的变化以及它将如何影响航空旅行也是很有趣的,因为这将在很大程度上影响旅游和酒店业的未来。在目前裁员和储存飞机之后,航空公司如何扩大业务规模以满足更高的需求,也是一个有趣的问题。在长期裁员(通常为 6 个月)后,对飞机和机组人员进行各种检查和重新培训,将需要航空公司不断感受经济的脉搏,以便他们能够计划机组人员培训和飞机维护检查,以利用几年后的周期高峰。
加拿大航空股票— 根据最近收盘价(2020 年 5 月 15 日 14.62 美元),与通过 DCF 和格雷厄姆方法得出的内在价值平均值相比,加拿大航空股票被高估了 35%。这也许解释了为什么以发现价值股闻名的沃伦·巴菲特在今年早些时候抛售了他的航空公司股票。因此,除非你的投资期限是 7-10 年,并且很年轻/或者有很高的风险偏好,否则航空股(至少是加拿大航空)似乎是一个赔本买卖。
我想澄清的是,用于预测的方法和假设没有考虑到各种细微差别。所有观点/意见都是我个人的,所做的工作只是为了帮助我自己更好地理解疫情对经济的影响。此外,不能孤立地看待通过机器学习和 DCF 估值进行的预测。
人工智能与人类的共存以及为什么我们都应该关注它
对李开复《人工智能的超能力》的再思考
我们离完全的 AI 共存还有多远?
注 :这篇文章很大程度上是受李开复的‘AI 超能力’的启发,加上我个人的一些想法。许多观点是从他的书中摘录的,任何发现的相似之处都是有意的。
作为一名人工智能的学生、实践者和倡导者,我很幸运能够一窥人工智能技术在表面之下是如何工作的,并且在一定程度上也让我想象人工智能不仅在现在,而且在未来会有什么样的可能性。
对于普通人来说,人工智能被视为一种有可能在不同工作领域取代人类的技术,而且这种取代已经开始。然而,他们没有看到的是,人类和整个社会将在多大程度上受到人工智能革命的影响,就像工业革命和互联网繁荣如何戏剧性地改变了我们的生活方式一样。
让我感到害怕的是,如果人们继续忘记人工智能到底是什么以及它能做什么,郝在所谓的“人工智能精英”与世界其他人(她认为是“无用”的人)之间的反乌托邦世界可能会成为现实。
作为一名未来学家,我认为在过渡到人工智能驱动的世界时,每个人都应该意识到这一点。

来源:来自 istockphoto 的 BahadirTanriover
有了今天的人工智能技术,很大一部分工作将会、能够并且已经被取代
蒸汽机、缝纫机、电的发明都取代了工作。我们已经克服了。人工智能的挑战在于,这 40%,无论是 15 年还是 25 年,都比以前的革命来得更快。”
—李开复
上面的引用概括了 Lee 对我们目前生活的这场人工智能革命的预言——在未来 15 到 25 年内,世界上 40%的工作将被人工智能技术取代,关键的区别在于这种取代的变化率。
人工智能革命——第三次工业革命?
在人类历史上,我们从第一次工业革命中幸存了下来——这是一次向新制造工艺的大规模过渡,彻底改变了商品的生产方式。随后,我们在第二次工业革命中蓬勃发展,也被称为技术革命,这是一个商品和服务快速标准化和工业化的阶段,包括铁路网络、污水处理系统、电气化、海运、汽车等领域。
许多人现在将我们生活的时代称为人工智能革命,也可能是我们(未来)的孩子可能知道的第三次工业革命,因为商品和服务的消费方式已经发生了巨大的变化。相对于生产的商品数量,今天提供的服务的数量和类型已经激增,因为互联网使这成为可能。
不仅仅是互联网,而是支撑整个互联网生态系统的外围设备的快速发展,以及随之而来的人工智能的发展。
回到起点——人工智能的崛起
人工智能是一种在有明确输入和输出的问题上蓬勃发展的技术。通常,这些是优化问题(监督学习),如信用评分、垃圾邮件分类和情感分析。当输出没有被标记时(例如,垃圾邮件/非垃圾邮件,肯定/否定),我们也可以根据算法“认为”每个数据点应该被分类到什么类别来进行分类(无监督)。前面提到的是典型的传统机器学习方法(例如,随机森林、支持向量机、逻辑/线性回归、基于密度的模型),它们已经存在并被研究了很长一段时间。
导致这场人工智能革命的是深度学习技术进步的扩散和广泛采用。不是“创造”而是 采用 这项技术。
正如李所说,我们不是处在一个发现的时代,而是处在一个实施的时代。人们很容易被误导,因为媒体不断报道新的突破性成果,如谷歌的 DeepMind 和埃隆马斯克的 OpenAI 击败的 AlphaGo 、 Dota 2 和 星际争霸 。回到 2016 年,李·塞多尔甚至无法想象一个计算机程序在围棋中击败他。如今,他已经(2019 年)从围棋退役,因为他认为“即使【他】成为№ 1,也有一个不能被打败的实体”[5]。

围棋、DotA 2 和星际争霸冠军被 AI 击败(图片来源:作者创作)
继 AlphaGo 之后, Dota 2 和 Starcraft 等更复杂的实时多人在线对战竞技场(MOBA)游戏中的职业队伍也在人们认为不可能完成的任务中被废黜。在像 Go 这样的回合制游戏中,计算机程序可以可能穷尽游戏的所有可能状态(棋盘或游戏在任何给定时间点的状态),并预测下一步最佳行动应该是什么,在游戏的多次迭代中进行训练,并采用各种探索-利用策略。对于 MOBA 游戏,这些游戏状态指数(可能)为无穷大,包括额外的复杂性,如博弈论、不完全信息、长期规划和实时多人互动[3]。然而,人们不知道的是,这些突破实际上是同一基础技术的不同应用。

AlphaStar 在行动(来源:Deepmind 的博客
秘制酱?深度学习。
深度学习使用神经网络——一种通过特定网络结构解析输入的独特方式——来训练模型,以理解输入和输出之间的线性和非线性关系。神经网络试图以类似的结构模拟我们大脑中的神经元,权重作为我们在决策时对每个特征(因素)的重视程度。这种捕捉非线性的能力是与传统机器学习模型的关键区别,传统机器学习模型本质上大多是线性的。
为什么不早点采用这项技术?
尽管深度学习自 2000 年代以来就已经存在,但直到 2016 年,由 Yann LeCun (人工智能的教父之一)领导的人工智能研究人员团队在世界上最大的图像识别比赛中超过了基准错误率 ImageNet ,社区才认识到它。当时,由于缺乏研究资金、计算能力和认可,很少被采用。

艾教父:(从左至右)约舒阿·本吉奥、扬·勒村和杰弗里·辛顿(图片来源:作者创作)
今天,随着 GPU 和 TPU 为我们的人工智能系统提供支持,人们能够将开源技术应用到许多不同的领域。过去由博士主导的领域现在不再有同样的准入门槛,因为推进技术需要先进的技术技能,而技术应用不需要同样的严格程度。这就是开源技术的魅力所在,它为人们提供了实验甚至改进的基础。
借助这项新技术,我们可以看到深度学习在不同行业的快速应用——从制造业到零售业到银行业,从蓝领工人到白人。人工智能时代是一个变革的时代,一个颠覆可能成为新常态的时代。我们经常看到行业被打乱,运营被打乱,我们的道路上可能挤满了自动驾驶汽车。
谁有被技术‘取代’的风险?
李将工作大致分为两类——体力劳动和认知劳动。在下面的两个图表中,纵轴描述了工作中的社会参与程度。
第一张图表代表体力劳动岗位的替代风险,横轴描述环境中的结构水平。如前所述,AI 非常擅长学习输入与输出有某种形式关系的任务(即近似f(x) = y)。不用说,基于规则的工作是最容易取代的,因为它不需要人工智能,只需要简单的自动化。

替换风险: 体力劳动(来源:作者创作,内容改编自李《AI 超能力》)
第二张图表代表了认知劳动工作的替代风险,横轴描述了所涉及的创造力水平。

替换风险: 认知劳动(来源:作者创作,内容改编自李《AI 超能力》)
人们可以观察到体力劳动和认知劳动之间的一些相似之处——与具有某种不可预测性或需要创新思维的工作相比,涉及重复工作和很少社交互动的基于规则的工作(体力或认知)风险更大。
被取代还是被置换?
虽然更多的“传统”工作可以被取代,但我认为这 40%受影响的工作中有很大一部分是被取代的,而不是被 T21 取代的。
人工智能从未被创造出来做人类的工作——至少不完全是。机器人就是为此而生的。你可能会问这有什么区别?在我看来,机器人代表了人工智能可以驻留的物理实体。换句话说,人工智能代表了机器人的“T2 大脑”。传统工作之所以会被取代,是因为我们只需要一个拥有“基于规则的大脑”的机器人。这就是工业革命发生并改变商品生产方式的原因。
然而,有了人工智能,我们试图解决的问题会成倍地(也许是无限地)变得更加困难。在医疗场景中,AI 很大程度上用于诊断甚至药物开发和患者监测的阶段。图像识别的使用在医疗保健中更加普遍,因为图像识别变得如此之好如此之快。这通常在 X 射线图像上进行,以在检测乳腺癌甚至新冠肺炎的迹象时识别异常。在前者中,已经确定人工智能在诊断乳腺癌方面“优于”医生,假阳性率降低了 1.2%,假阴性率降低了 2.7%[6]。
在银行业,人工智能用于识别交易中的异常情况(即欺诈)并批准贷款。在海事方面,AI 用于识别海上物体,防止碰撞。在电子商务中,人工智能被用来预测你可能会购买什么商品。在我们消费内容的网站上,人工智能被用来推荐我们可能想要观看或阅读的项目。在我们的 iPhones 上,人工智能被用来自动完成我们的文本,回答我们在谷歌搜索上键入的问题(也称为自然语言处理中的问答),甚至在我们懒得自己做的时候,使用语音识别为我们设置闹钟。
这里的底线是——AI补充了我们做事的方式,因为它抽象出了我们可能必须提供客观意见的情感元素。在乳腺癌诊断中,需要多名放射科医生做出判断,尤其是当这些判断不一致时。个体放射科医生一生中只能经历有限次数的 x 光检查,并且受到疲劳和容易出错的限制。人工智能系统可以在一天内通过同样数量的 X 射线,全天候工作,并提供类似甚至更高的准确性。这也适用于其他工作。
然而,由于做同样工作所需的人员数量将会减少,人员流动是不可避免的。新的补充性工作将会出现,以帮助这一过渡,例如需要了解如何操作这些人工智能驱动技术的人员。
剩下的问题是:
我们如何应对,更重要的是,如何适应人工智能带来的这些变化?
真正的人工智能危机
是的,AI 很吓人。
如果我们不知道它能做什么,那就太可怕了。如果我们无所事事,让我们的工作被取代,或者更糟糕的是,被人工智能取代,这也很可怕。
自满
在个人层面上,我们必须意识到人工智能的能力和可能性。思考人工智能如何影响我们的生活是很重要的。如果我们选择不理解人工智能到底是什么,我们就会失败,并有被取代或取代的风险。
在国家层面,各国需要开始思考和利用他们拥有的任何数据。政府在推动人工智能和技术的采用方面发挥了巨大作用,正如中国如何在几十年内从技术落后者加速成为人工智能超级大国一样。人工智能有一种赢者通吃的趋势,因为先行者可以扩大庞大的用户群,而这本身就会产生数据,从而形成一个自我延续的循环。
能力
我们在个人、企业和国家各个层面都承担责任。就个人而言,跟上这场人工智能革命是我们的责任。 提升技能 前所未有的重要。有了互联网上的大量可用资源,学习几乎任何技能现在都是可能的。
在企业和国家层面,变革通常来自高层。高级管理层和内阁部长需要鼓励创新,并拨出预算来鼓励创新。人才管理也是至关重要的,因为人工智能人才是稀缺和流动的。
合作的
在全球范围内,世界上可能不可避免地会出现一些人工智能巨头(在人工智能领域占据主导地位的公司和国家)。这无疑会造成贫富之间以及第一和第三世界国家之间的差距越来越大。随着强大的力量而来的是巨大的责任(是的,cheesy I know)——我真的希望这些人工智能大亨们能够共同努力,在国内和国际上弥合这一差距。
我们会在有生之年体验完全的人工智能自主吗?
简而言之,没有。
事实是,今天的人工智能没有许多人想象的那么好,但也没有我们担心的那么糟糕。我们常常害怕我们没有完全掌握的东西。
在 Lee 的书中,他将自主 AI 描述为第四波 AI(第一波是互联网 AI ,第二波是商业 AI ,第三波是感知 AI )。它代表了机器从极其复杂的数据集进行优化的能力与其新发现的感官能力的融合[1]。简而言之,当机器被赋予根据它感知的事物(无论是视觉还是听觉)做出决定的能力(T21)。这些与简单地基于一套规则运行的机器形成了鲜明的对比。
我们今天最接近的东西是自动驾驶汽车。然而,当谈到自主人工智能时,仍然有许多考虑和影响,人工智能伦理和治理发挥着巨大的作用。为了实现完全的人工智能自主,我们必须超越我们的有生之年去想象可能性。
遗言
人工智能塑造我们世界的方式每天都让我感到惊讶,我希望这篇文章能揭示出今天我们的生活与人工智能是如何融合的。更重要的是,理解人工智能对我们个人、工人和全球公民的影响,是创造一个未来几代人可以生活的更加公平的世界的基础。
如果你还没有读过李开复的《人工智能的超能力》,我强烈建议你读一读!

来源:故事镜头
支持我! —如果你喜欢我的内容并且没有订阅 Medium,请考虑支持我并通过我的推荐链接订阅这里 ( 注意:你的一部分会员费将作为推荐费分摊给我)。
参考资料:
[2] 人工智能超能力对抗所有其他超能力
李·塞多尔退休了
[6] 人工智能“胜过”诊断乳腺癌的医生
人工智能的下一步:抽象和推理
用演示测试你的一般智力

抽象和推理语料库中包含的 600 个任务的一个小样本。
如果你想直接试一试: ARC 测试界面。
人工智能在过去十年取得了突飞猛进的发展,解决了许多我们认为不可能完成的任务,但我们离类人智能还很远。最重要的是,创造人工智能的领先方法不像我们在自然界中看到的那样,使用庞大的数据库来学习模式识别。这与人类形成对比,人类拥有灵活的智力,允许我们只用少量样本就能胜任。为了帮助推动世界向前发展,一个新的挑战——抽象和推理语料库(ARC)——已经提出,它可能会取代图灵测试,成为人工智能的目标。除此之外,随着全球工程师在在线平台 Kaggle 上争夺奖项,对人工智能社区的挑战正迅速接近尾声。
弧形
2019 年 11 月发表的名为“论智力的衡量标准”的 64 页研究论文,概述了人工智能研究的历史,一个新的视角和抽象与推理语料库(ARC)。它是由资深深度学习研究员兼谷歌工程师弗朗索瓦·乔莱(Franç ois Chollet)提出的。在书中,他认为:
“ARC 可用于测量类似人类形式的一般流体智能,它可以在人工智能系统和人类之间进行公平的一般智能比较。”
这很重要,因为就像正在构建的人工智能一样,人类是非常面向目标的。通过提供一个单一的努力目标,我们可以衡量我们的表现,迭代,改进并努力超越基准。我们已经在人工智能的其他领域看到了非常相似的结果;当 MovieLens 数据集发布时,推荐系统实现了飞跃;图像识别社区随着 MNIST 和随后的 ImageNet 的发展而繁荣。希望 ARC 可以成为更普遍的智能人工智能系统的火花。
本文的另一个重要成果是系统智能的定义(如下所示)。这个等式在这里有点难以解释,但它可以解释为"智力是学习者在涉及不确定性和适应性的有价值的任务中将其经验和先验知识转化为新技能的速度。因此,最智能的系统只需要少量的经验,并根据这些经验猜测在许多不同的情况下会有什么样的结果。

乔莱对智力的定义。有趣的是,公式本身就需要很高的智力门槛来处理!
让我们通过一个来自 ARC 的例子更容易地看到这一点。作为 ARC 中所有任务的标准,我们从一些必须理解的例子开始,然后归纳为一个测试用例。

任务 11:星际飞船建造者(好吧,他们并没有真正的名字,但这更有趣)。这里的目标是采用基本模式并围绕它建造一艘“星际飞船”。这是通过将外部部分从中心向外延伸一个方块,将中心部分向对角线方向延伸两个方块来实现的。
在这个例子中,你必须用基本的图案围绕它们建造一艘“星际飞船”,注意基本的颜色。对于测试用例,只提供给你一张图片(比如说,最左边的那张),你必须猜测相邻的那张。对于我们来说,看到这种模式并假设(猜测)创建解决方案的下一步是什么是相对简单的,但建立一个人工智能来为一般情况做这件事是我们目前非常非常远的事情。
上面的例子相对简单,但是肯定有更复杂的。点击这里提供的链接选择“随机任务”来尝试一些挑战: 电弧测试界面 。如果你发现任何问题特别难,请在下面分享你的结果!感谢论文作者准备了这个界面并允许它自由发表。或者,在这里查看所有示例。
似乎很容易
但是是什么让人工智能变得如此困难呢?我们可以考虑像这里的和一样手动编程每种情况。只需要一行日常语言就能表达的东西,却需要几十行代码。

任务 1:打开门户。用英语直截了当表达的东西,例如“用黄色填充绿色物体”,用代码来表达相对复杂。
“用黄色填充绿色对象”的示例变为:
def task_train001(x):
green, yellow = color2num["green"], color2num["yellow"]
def get_closed_area(arr):
*# depth first search*
H, W = arr.shape
Dy = [0, -1, 0, 1]
Dx = [1, 0, -1, 0]
arr_padded = np.pad(arr, ((1,1),(1,1)), "constant", constant_values=0)
searched = np.zeros(arr_padded.shape, dtype=bool)
searched[0, 0] = True
q = [(0, 0)]
while q:
y, x = q.pop()
for dy, dx **in** zip(Dy, Dx):
y_, x_ = y+dy, x+dx
if **not** 0 <= y_ < H+2 **or** **not** 0 <= x_ < W+2:
continue
if **not** searched[y_][x_] **and** arr_padded[y_][x_]==0:
q.append((y_, x_))
searched[y_, x_] = True
res = searched[1:-1, 1:-1]
res |= arr==green
return ~res
y = x.copy()
y[get_closed_area(x)] = yellow
return y
但这只是问题的一面。如果需要,我们可以编写任意长的代码,但我们在这里试图解决的问题是编写可以解决各种问题的代码,而不仅仅是我们手动编程的问题。
总的来说,对我们来说似乎简单的东西来源于论文所描述的“人类先天的先验”。这种先验知识指的是我们用来处理概念的东西,比如物体是什么,对称性是什么,或者排序什么东西意味着什么。任何系统都必须能够学习这些,或者至少将它们预先编程,然后开始将它们缝合在一起以找到解决方案。例如,我们可以编写关于对称性意味着什么的函数,或者我们可以创建一个能够学习对称特征的二维过滤器。
值得注意的是,在 ARC 的情况下,先验的数量保持在绝对最小值,这是使该数据集真正伟大的另一个因素。你可以将这与原始的图灵测试进行对比,在原始的图灵测试中,计算机必须模仿人类。要做到这一点,计算机必须对人类文化有充分的理解才能通过,这与智力没有直接关系。
让这项任务变得非常棘手的另一个原因是,输入量非常小,这意味着系统必须能够从少量训练样本中学习复杂的行为。出于这个原因,像深度学习这样最受欢迎的技术并不适合这个问题,因为它们通常需要数百万个训练样本。最重要的是,它们需要用于训练它们的数据和它们必须解决的问题之间的共性,这对于 ARC 来说并不成立。
这就是 ARC 真正有趣的地方。它正在推动边界,迫使研究人员提出创新的系统来解决前所未有的普遍问题。
一个解决方案?
论文发布后,在线平台 Kaggle 发布了一个竞赛:抽象和推理挑战。在这场比赛中,工程师们面临的挑战是在 ARC 中描述的任务上获得尽可能好的分数。我们不太可能在剩下的一个月里解决人工智能问题,但我们正在探索一些有趣的问题。迄今为止的主要尝试包括:
- 卷积神经网络:乍看之下,CNN(处理图像以告诉你是否有猫的同一个系统)很适合这个问题,因为它们是为处理二维图像数据而建立的,可以建立强大的模式检测器。但是如前所述,这些系统不能很好地解决问题,性能也很差。
- 细胞自动机:通过定义一套简单的规则,我们可以使用细胞自动机产生复杂的行为。如果你从未听说过它们,一定要查一下——它们超级酷!虽然到目前为止的探索大多是好玩的,但思考和触及智能的核心是很有趣的。
- 决策树:ML 工程师的另一个拿手好戏是决策树。通过一些聪明的特征工程,有可能产生一些正确的答案,但是很难看出它如何一般化。
- 遗传算法:从一些关于如何转换图像的函数(特定领域语言,DSL)开始,遗传算法采用一些随机函数并进化这些函数,类似于(在某种意义上)地球上生命的进化。有了一个定义良好的函数列表和一个关于什么“看起来不错”的强烈想法,这种方法似乎可以很好地执行。
您可以在 Kaggle 论坛上关注所有这些解决方案的更新,或者等到比赛结束后查看顶级选手的评论。
展望未来
这并不是贬低当前技术的力量。深度学习给了我们像自动驾驶汽车和象棋大师这样令人惊叹的技术。所有这些都是在一个庞大的经济体的背后发展起来的,这个经济体渴望通过能够像人类一样完成非常具体的任务的系统来实现自动化。经济需求和强大的社区解释了为什么这些系统如此流行和被大量研究。这篇论文提醒我们的是,还有其他值得探索的方向。让我们开始吧!

元胞自动机求解门户打开任务。信用: arseny-n 。
艾的凤凰计划时刻

艾的凤凰计划时刻
2018 年晚些时候,在亚利桑那州一段荒凉的双车道高速公路上,伊莱恩·赫尔茨贝格赢得了她从未想要的荣誉。
她成为第一个被自动驾驶汽车撞死的行人。

当汽车花费 290 到 520 美元的小财富时
她和 122 年前的一个女人布丽奇特·德里斯科尔有着相似的悲惨命运,她于 1896 年死于一项早期实验技术之手,当时她正在伦敦的傍晚散步:
一辆车。
普通大众喜欢把人工智能看作超人,在某种程度上他们是超人。他们可以击败世界上最好的围棋选手或 99%的 DOTA 2 选手,这是一款非常复杂的实时战略游戏。
但这并不意味着它们是完美的。即使今天最先进的人工智能也会犯严重的错误,包括大多数人会发现很容易克服的错误。
当我们把人工智能从棋盘游戏和视频游戏的狭窄领域中拿出来,放到现实世界中时,它们面临着一系列永无止境的边缘情况和意想不到的场景。这一点在高风险的自动驾驶汽车领域表现得最为明显,在这个领域,每一个错误都可能意味着生死之别。
Lyft 无人驾驶汽车部门研发负责人吕克·文森特(Luc Vincent)表示,无人驾驶汽车可能出现的问题几乎是无限的。
Lyft 自动驾驶汽车测试
Lyft 发现,当他们被其他司机超车时,他们的汽车正在刹车。另一家自动驾驶汽车公司 Zoox 发现他们的汽车无法处理黄色的左手转向灯,因为大多数转向灯都是绿色的。他们不得不请艺术家来绘制黄色的转向信号,并加载到他们的模拟软件中。很快,Zoox 的汽车在现实世界中看到它们的能力有了很大提高,但无论你做什么,总会出现另一种情况。
“这有点像打地鼠。“你解决了一个问题,另一个问题可能会出现,”应用直觉公司首席执行官合撒儿·尤尼斯说,根据 CNN 的优秀文章关于这个“世代型技术挑战”所面临的无尽困难
著名机器人专家、麻省理工学院荣誉退休教授罗德尼·布鲁克斯给写了一篇非常长且详细的帖子,解释了为什么他认为无人驾驶汽车比几乎所有人想象的都要遥远。他列举了几十个边缘案例:
- 如果你沿着一条狭窄的单行道走,这条单行道被建筑挡住了,那么违反法律回到这条单行道上可以吗?
- 这辆车能应付青少年恶作剧和大喊冲突的命令吗?
- 汽车能理解警察或路边工作人员的手势吗?
- 汽车能识别别人贴的假路牌还是损坏的路牌?
变得有鸭意识还是机器推理的局限性
所有这些场景对今天的人工智能来说都非常困难,因为它们没有更深层次的上下文意识或通用抽象推理。情境人工智能是人工智能研究的前沿,这就是为什么它得到了像 DARPA 这样的未来主义组织的资助。

DARPA 可解释人工智能框架
让人类如此神奇的是,我们善于从其他问题中抽象出解决方案,来解决我们从未见过的全新问题。我们可以研究物理定律、运动定律和惯性定律,建造一艘前所未有的火箭,并首次在月球着陆。
一个卷积神经网络 (CNN)可以研究火箭的例子,但如果没有现成的解决方案来建造火箭,那么它就不能发明一个。一个从未见过鸭子的 CNN 不会突然意识到鸭子的存在。
无人驾驶汽车推动了可能性的极限。关于我们现在已经有自动驾驶汽车自信地行驶在纽约市普通街道上的疯狂乐观的预测正在让位于现实检验意识,这可能比我们想象的要长得多。
在一个层面上,我们遇到了深度学习和强化学习的局限性。在最近的人工智能最大的会议之一 NeurIps 上,一些业界最耀眼的明星,包括蒙特利尔人工智能研究所 Mila 的主任 Yoshua Bengio,就人工智能的现状给出了一个发人深省的信息:
“我们有以非常狭窄的方式学习的机器,”本吉奥说。“他们需要比人类智能例子多得多的数据来学习一项任务,他们仍然会犯愚蠢的错误。”
机器人专家罗德尼甚至走得更远,他说,要拥有一辆真正的4 级或 5 级自动驾驶汽车,这意味着汽车不需要轮子,可以在除了最糟糕的天气条件之外的任何情况下行驶,并做出自己的决定,将需要某种接近人工通用智能的东西(AGI)。仅仅将一堆互不相连的神经网络缝合在一起,并希望更高形式的理解会神奇地出现是不够的。
要让一辆自动驾驶汽车在现实世界的混乱中工作,在司机按喇叭和插队的情况下,在坑坑洼洼、破损的交通灯或贴满贴纸的街道标志的情况下,我们很有可能无法在今天的人工智能艺术中实现这一目标。现在,我们是否能利用神经网络的魔力让自动驾驶汽车发挥作用,或者我们是否需要新的算法,将在全球顶尖 R&D 团队的实验室中决定,因为他们正在竞相寻找解决方案。
但是如果我们仔细观察,自动驾驶汽车的世界向我们展示了一个更加基本和根本的问题,这个问题正在摧毁数据科学团队,而且我们现在就可以解决这个问题。
红队崛起的凤凰
87%的数据科学项目从未投入生产是有原因的。
今天,大多数数据科学团队都不知道如何处理边缘情况,当我们的模型遇到现实生活时,这些情况就像野生兔子一样成倍增加。

一个 ConvNet 看到左边的图像是一个 45 英里每小时的标志!
自我学习的算法有各种各样的场景,只是我们无法预见,直到它们迎面而来。如果你的视觉检测系统有 97%的准确率,但检测到一个涂鸦覆盖的停车标志是 45 英里/小时的标志,它的准确率可能为零,因为有人会受伤或死亡。
即使是世界上最准确、最成功的 CNN,也常常在凌乱的现实世界中挣扎。麻省理工学院和 IBM 刚刚推出了 ObjectNet 数据集来展示这些算法在面对损坏的东西,或部分隐藏的东西,或以奇怪的角度放置的东西时表现得有多糟糕。该数据集花了三年时间整合,一些最先进的对象检测模型的准确率从 ImageNet 上的 97%下降到 ObjectNet 上的 50–55%。

提供图像识别功能的 ObjectNet 图像
仅仅测试准确性和收工已经不够了。准确性分数标志着一个模型的最低能力。这些分数就像你放在简历上为你在新工作中担保的两个人。它们表明你并没有那么无能,以至于你在这个世界上找不到两个人来说你的好话,仅此而已。
但是,要让像自动驾驶汽车这样复杂的东西成为现实,我们需要一种方法来解决快速扩散的边缘案例“打地鼠”的问题。要做到这一点,我们需要超越的整体精度,并转向对边缘案例的精度进行自动化测试。我们可以通过传统的软件编程来做到这一点。
人工智能开发有其独特的挑战,但在我们如何在一些最精英的编程团队上开发软件与数据科学团队现在和未来如何开发人工智能之间有很多重叠。
要理解为什么你只需要知道一点点编程的历史。
DevOps 是一个大问题的答案,当我们的应用程序开始变得太大太复杂,旧的编程方法无法熟练处理时,这个问题才浮出水面。早期的计算机应用程序比今天多方面的应用程序简单。它们主要是由公司开发团队为一个狭窄的用例构建的。有了这些隐藏在公司防火墙后面的应用程序,瀑布模型运行得非常好。只有几千个用户会接触那个应用程序,所以你可以把边缘情况保持在最低限度。
但是互联网改变了一切。随着上亿用户使用一个应用程序,越来越多的错误会出现,而在严格控制的环境中只有几千名用户。DevOps 来救援了。它使互联网规模的应用成为可能。
AI 再次改变游戏。
有了人工智能,我们面临着未知事物的指数级增长。
修复它的关键是单元测试。
我们可以把每一个边缘案例看作是一个需要自动化单元测试的 bug。
敏捷和 DevOps 风格编程的兴起教会了我们如何自动化测试,因为复杂的软件在广泛分布的编程团队的手中经历了无数的变化。软件团队经常发现,由于程序员签入依赖于损坏的库的代码,或者由于程序员剪切并粘贴旧代码而没有意识到它有缺陷,一个被压制的网络错误不知何故在一百次修订后又回来了。人工智能团队将需要开发自己的自动化边缘案件处理器,以处理欺诈检测系统,每当有人前往法国或在阿尔伯克基使用 ATM 机时,这些系统就会开始得到误报。
当我们调整算法的参数或重新训练新数据时,它突然开始出错,人工智能团队将不得不建立特殊的测试,以确保这些“错误”不会突然出现。自动驾驶汽车团队可能会创建一个 CNN,它擅长处理愤怒的人类司机切断他们的道路,但如果它突然又开始丢失贴有贴纸的街道标志,那也没什么关系。
为了构建一个更好的单元测试,工程团队将需要掌握机器学习操作(MLOps) 并学习构建一个良好的 MLOps 管道,可以快速发现并消除新的 bug。
在我为红帽 OpenShift Commons 的演讲中,我谈到了如何为人工智能团队建立一个 QA,我现在称之为人工智能红队。这是一个由快速响应的编码人员、工程师和数据科学家组成的团队,他们寻找人工智能异常的短期分类解决方案和长期解决方案。这是一个非常精英的团队,很像一个白帽黑客队,他们的工作是闯入网络,使他们免受黑帽的攻击。
AI 红队的工作就是墨菲定律的答案。他们专门破解 AI,再修复。他们负责找出未知的未知,并在伤害他人或伤害底线之前将它们公之于众。
在不太遥远的将来,我们将需要世界各地数以百万计的红色团队构建他们自己的 ObjectNets,并以真正的开源精神共享它们,以真正创造出可以安全地倒在单行道上或穿越暴雨和大雪的汽车。
把这当成是给 AI 的凤凰计划。

如果你不知道这本书,你应该知道。这是一本关于软件和业务转型的非常好的读物。任何一本书,只要能把软件开发和业务流程升级变成一次有趣的、超级娱乐性的旅行,书中充满了我们在现实世界中似乎都认识的人物,都是非常特别的。这本书有助于推广 DevOps 软件开发模型,但不仅如此,它还展示了我们如何通过在组织的每个级别上以不同的方式思考问题来解决过去的问题。
在人工智能时代,我们将不得不再次转变我们的理解和方法。
人工智能带来了新的挑战,这是我们手动编写所有软件并手动教给它道路规则时从未面临过的挑战。今天的软件正在自学道路规则。当它在红灯处右转时,最先进的人工智能团队已经准备好了。
现在是艾的凤凰计划的时刻。
为了建设未来,有时我们只需要回顾过去。
############################################
作者 【工程师】 亲博者播客我还运营了 实用 AI 伦理联盟 和 AI 基础设施联盟 ,两个倡导安全透明 AI 的开放社区。**
############################################
这篇文章包括亚马逊的会员链接。
############################################
阿凯克信息论
AIC 背后的想法
我们所有人都曾用 AIC 来选择模特。这个博客是关于 AIC 背后的想法,它是什么,为什么它被用于模型选择。虽然有人告诉我们如何计算 AIC,但至少没人告诉我为什么要这么做背后的逻辑——这篇博客将对此进行阐述。
AIC 是对样本外误差的估计。AIC 以信息论为基础。他称之为熵最大化原理,最小化 AIC 相当于最大化热力学系统的熵。因此,在信息论的语言中,我们可以说,当编码一个模型时(我们永远找不到确切的模型,一些信息在表示数据生成的过程中丢失了。
AIC 测量了相对信息损失。由于我们没有确切的模型,我们无法测量确切的损失。因此,我们测量不同模型之间的相对损失(我们必须从中选择我们的模型)。如果我们有 3 个 AIC 值分别为 100、102 和 110 的模型,那么第二个模型的 exp((100-102)/2)= 0.368 倍是第一个模型的概率,以最大限度地减少信息损失。同样,第三个模型的概率是第一个模型的 0.007 倍,以最大限度地减少信息损失。
AIC 由 2 x 参数数量-2 log(似然)给出
当选择模型(例如多项式函数)时,我们选择具有最小 AIC 值的模型。或者,如果我们可以选择前 2-3 个模型,收集更多的数据,并选择 AIC 最小的一次。这个博客是关于——这个 AIC 公式从何而来?
在 AIC,我们试图最小化模型和地面真实函数之间的 KL 差异。AIC 是对代理函数估计的计算。因此,最小化 AIC 类似于最小化 KL 与地面真实值的偏离,从而最小化样本外误差。下图显示了 AIC 的推导过程。

图一。推导第一部分

图二。推导第二部分
贝叶斯信息标准(BIC)的计算类似于 AIC。BIC 用 2 ln(n)k 代替 2k,这些被称为罚项。有争议的是,如果真实模型存在于模型组中,BIC 选择概率为 1 的真实模型,给定 n 趋于无穷大。由于我们在候选模型集中从来没有真正的真实模型,这个属性并没有被高度重视。此外,AIC 最大限度地降低了选择一个非常糟糕的模型的风险。
参考 1。维基百科 AIC 页面
2。AIC 的衍生
Albert 矢量化(带 Tensorflow Hub)

我们使用来自 tensorflow-hub 的预训练 Albert 嵌入对输入文本进行矢量化。它被用作 Keras 层,因此可以很容易地扩展以构建深度学习模型。
BERT 的出现打破了 NLP 的传统范式。下游的模型构建现在是从一个以语言知识为基础的模型开始,而不是从零开始。ALBERT 可以被称为 lite BERT,它使用转换器-编码器架构,参数数量大大减少。在本文中,词汇大小也是 30K,与最初的 BERT 中使用的一样。ALBERT 区别于 BERT 的三个主要方面是分解嵌入参数化、跨层参数共享和句子顺序预测。
优于伯特
当人们试图简单地放大模型的隐藏尺寸时,BERT like 模型可能提供质量差的性能。诸如因子分解嵌入参数化之类的参数缩减技术用于将隐藏层的大小与词汇嵌入的大小分开,这使得在不显著增加参数大小的情况下增加隐藏大小变得容易。而跨层参数共享防止参数随着网络的深度而增长。因此,这两种技术都显著减少了传统 BERT 的参数数量,而没有恶化性能和提高参数效率。通过引入句子顺序预测的自监督损失(SOP ), ALBERT 的性能得到进一步改善。
在本文中,我们将使用 tensorflow-hub 模块的 keras 层格式获得相应文本的 ALBERT 向量。
1.设置环境
我们将使用 tensorflow keras API 制作一个模型,它将为文本输入提供 ALBERT 嵌入。环境设置包括安装所需的库和获取所需的 tensorflow-hub 模块以获得 ALBERT vectors。使用的库有:
#tensorflow==2.2.0
#tensorflow_hub=0.8.0
#sentencepiece==0.1.91
#tqdm==4.47.0
#seaborn==0.10.1
#numpy==1.19.0
我们将使用 TF2 保存的艾伯特模型格式。您可以直接使用 tfhub 上的模块进行推断。但是对于生产场景,最好将模块放在本地。为此,我们需要首先获取模块的 zip 文件并将其解压缩。
# mkdir albert_en_base
# mkdir 1
# wget [https://tfhub.dev/tensorflow/albert_en_base/1https://tfhub.dev/tensorflow/albert_en_base/1](https://tfhub.dev/tensorflow/albert_en_base/1https://tfhub.dev/tensorflow/albert_en_base/1)
# tar-xzf albert_en_base_1.tar.gztar-xzf albert_en_base_1.tar.gz
# rm -rf albert_en_base_1.tar.gzrm -rf albert_en_base_1.tar.gz
2.符号化
我们将把 ALBERT 模块作为 keras 层导入。
albert_layer = hub.KerasLayer("albert_en_base/1", trainable=False)
棘手的是,艾伯特模块不能直接输入文本。它需要经过一个预处理层。
首先,我们将使用 ALBERT tokenizer 对输入文本进行分词,它基于一个句子片断分词器,即子词级分词器。它是一个数据驱动的标记器,用来处理词汇表之外的单词。因为我们在每次输入时只有一个文本,所以句子的标记列表看起来像["[CLS]"]+标记+ ["[SEP]"]。
sp_model_file = albert_layer.resolved_object.sp_model_file.asset_path.numpy()
tokenizer = FullSentencePieceTokenizer(sp_model_file)
stokens = tokenizer.tokenize(sentence)
stokens = stokens[:MAX_LEN]
stokens = ["[CLS]"] + stokens + ["[SEP]"]
例如,文本“车身由金属制成,具有高张力”会生成一个令牌列表,如下所示:
['▁the',
'▁body',
'▁is',
'▁made',
'▁of',
'▁metallic',
'a',
'▁and',
'▁deliver',
'i',
'▁high',
'▁tension']
现在,我们需要 3 个输入序列,可以馈入艾伯特模块。
- 标记 id:用于从 ALBERT vocab 字典中提取的句子中的每个标记。
- mask ids:for each token,用于屏蔽仅用于序列填充的标记(因此每个序列都有固定的长度)。
- Segment ids 表示一个句子序列(我们这里的例子),1 表示序列中有两个句子。
def get_ids(tokens, tokenizer, max_seq_length):
"""Token ids from Tokenizer vocab"""
token_ids = tokenizer.convert_tokens_to_ids(tokens,)
input_ids = token_ids + [0] * (max_seq_length-len(token_ids))
return input_idsdef get_masks(tokens, max_seq_length):
return [1]*len(tokens) + [0] * (max_seq_length - len(tokens))def get_segments(tokens, max_seq_length):
"""Segments: 0 for the first sequence, 1 for the second""
segments = []
current_segment_id = 0
for token in tokens:
segments.append(current_segment_id)
if token == "[SEP]":
current_segment_id = 1
return segments + [0] * (max_seq_length - len(tokens))ids = get_ids(stokens, tokenizer, MAX_SEQ_LEN)
**# [2, 13, 1, 589, 17378, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]**masks = get_masks(stokens, MAX_SEQ_LEN)
**# [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]**segments = get_segments(stokens, MAX_SEQ_LEN)
**# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]**
3.艾伯特矢量化
现在我们已经准备好了所需的输入处理。我们将使用 tf keras API 建立一个模型,它将接受处理后的输入,并获得文本的 ALBERT 向量。输出艾伯特矢量包含 2 个矢量,一个是汇集输出和序列输出。pooled_output 是维度 1x768 的句子嵌入,序列输出是维度 1x(token_length)x768 的令牌级嵌入。
def get_model():
input_word_ids = tf.keras.layers.Input(shape=(MAX_SEQ_LEN,), dtype=tf.int32,name="input_word_ids")
input_mask = tf.keras.layers.Input(shape=(MAX_SEQ_LEN,), dtype=tf.int32,name="input_mask")
segment_ids = tf.keras.layers.Input(shape=(MAX_SEQ_LEN,), dtype=tf.int32,name="segment_ids") pooled_output, sequence_output = albert_layer([input_word_ids, input_mask, segment_ids]) model = tf.keras.models.Model(inputs=[input_word_ids, input_mask, segment_ids], outputs=[pooled_output, sequence_output])
return model
制作 keras 模型的想法是通过添加所需的层和参数,轻松地将其扩展到任何分类模型。
现在所有的艰苦工作都完成了。将只需要一个推理函数来获得文本的相应艾伯特嵌入。
s = "This is a nice sentence."def get_albert_vec(s):
stokens = tokenizer.tokenize(s)
stokens = ["[CLS]"] + stokens + ["[SEP]"]
ids = get_ids(stokens, tokenizer, MAX_SEQ_LEN)
masks = get_masks(stokens, MAX_SEQ_LEN)
segments = get_segments(stokens, MAX_SEQ_LEN)
input_ids = np.asarray(ids, dtype=np.int32).reshape(1,22)
input_masks = np.asarray(masks, dtype=np.int32).reshape(1,22)
input_segments = np.asarray(segments, dtype=np.int32).reshape(1,22)
return input_ids, input_masks, input_segmentsinput_ids, input_masks, input_segments = get_albert_vec(s)
pool_embs, word_embs = albert_model.predict(
[[input_ids, input_masks, input_segments]]
)
为了快速检查句子嵌入的质量,让我们在一小组示例上运行它,并使用它们对应的归一化句子嵌入向量的点积来检查每对的句子相似性得分。
sentences = [
# Smartphones
"I like my phone",
"My phone is not good.",# Weather
"Recently a lot of hurricanes have hit the US",
"Global warming is real",# Asking about age
"How old are you?",
"what is your age?"]run_and_plot(sentences)

参考文献
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/sambit9238/Deep-Learning/tree/master/sarcasm_classifier/albert_tfhub) [## 从伯特到阿尔伯特:预训练的兰格模型
预训练语言模型的研究进展
medium.com](https://medium.com/doxastar/from-bert-to-albert-pre-trained-langaug-models-5865aa5c3762) [## ALBERT:一个用于语言表达自我监督学习的 Lite BERT
自从一年前 BERT 问世以来,自然语言研究已经采用了一种新的范式,利用了大量的…
ai.googleblog.com](https://ai.googleblog.com/2019/12/albert-lite-bert-for-self-supervised.html) [## 谷歌的 NLP 驱动的预训练方法 ALBERT 更精简&更刻薄
自然语言处理(NLP)是新兴技术中最多样化的领域之一。去年,搜索引擎…
analyticsindiamag.com](https://analyticsindiamag.com/googles-nlp-powered-pretraining-method-albert-is-leaner-meaner/) [## 视觉论文摘要:阿尔伯特(A Lite BERT)
考虑下面给出的一个句子。作为人类,当我们遇到“苹果”这个词时,我们可以:联想“苹果”这个词…
amitness.com](https://amitness.com/2020/02/albert-visual-summary/)
AlexNet
用代码解释论文

照片由好股票照片
2012 年秋季 9 月,AlexNet 首次参加了 ImageNet 大规模视觉识别挑战赛(ILSVRC),并展示了 GPU 在深度学习方面的异常实力。点燃图像深度学习整个领域的火花是这样的。由 Alex Krizhevsky 与当今深度学习的大腕 Ilya Sutskever 和 Geoffrey Hinton 一起创建。这是任何进入深度学习领域的人阅读的第一篇论文。
所以,让我们回顾一下这篇论文,看看我们怎样才能重新创造,使它重现往日的辉煌。
网络

由于网络设计时 GPU 内存不足,因此必须通过结合 2 个 GPU 来训练。
- 我们的输入是 224x224x3 的图片。(论文中给出的是 150,528 维,有点混乱)
- 接下来,执行 96 个 11×11的卷积(今天,没有看到任何网络采用如此大的卷积),步长为 4 。然后,响应规范化(稍后解释)和池应用于层外。在这一层之后,网络分裂成两个相同的主干,直到完全连接。这样设计是为了考虑 GPU 的内存需求。
- 接下来是 256 个 5x5 的滤波器,每个滤波器然后再次被响应归一化(稍后解释)并被汇集。
- 第三、第四、第五层与 384 个内核相同,每个内核为 3×3。
- 由于这里内存的限制,作者不得不将 4096 个神经元分成两部分,每部分 2048 个。每个部分都从两个主干获得数据。
- 当从两个茎获得数据时,再次重复完全连接的层
- 最后,我们输入 1000 个神经元的密集层,即 ImageNet 中的类的数量。
网络的成功在于他们用过的伎俩。
局部响应标准化
这是他们使用的巧妙伎俩之一。
什么是局部响应正常化?
我们先来看看 ReLU。
ReLU(x) = max(0,x)
ReLU 最好的一点是,即使极少量的训练样本有一些激活,也会有学习。但是,缺点是它们是无限的。因此,他们控制他们的权重,并且,为了产生更好的特性,我们使用局部响应标准化。

这个公式乍一看很吓人,所以,我们来理解一下。
首先,在求和算子中,存在激活,我们对其求平方以消除正负效应。
现在,让我们来看看,求和运算符的范围是什么,给定一个 n ,它在其左侧迭代 n/2,在其右侧迭代N/2,同时考虑边界,即 0 和 N-1。
这进一步乘以因子 α ,以减少其与分子相比的值,从而保持分子中的激活值(如果 α 高,则分子中的激活将减少,从而导致渐变消失,如果太低,将导致渐变爆炸)。
增加 k 是为了防止被零除的错误。
最后,将 β 作为一个指数来决定该局部响应对所讨论的激活的影响,较高的 β 将更多地惩罚对其邻居的激活,而较低的 β 将不会对其邻居的所讨论的激活产生太多影响。
因此,局部反应标准化有助于我们找出那些对其邻居表现更好的激活。这也有助于提高网络的效率,因为一些神经元将充当网络的核心,所以计算将会很快。
此外,它有助于减少冗余特征,假设许多相邻神经元具有高值,则它们将通过局部响应归一化来归一化,从而抑制冗余的连续特征。
因此,局部反应正常化也在相邻神经元之间产生竞争,以更好地学习将自己与邻近的其他神经元区分开来。所以,你可以称之为竞争正常化。
局部响应标准化不再使用,因为我们更喜欢批量标准化,它在批量水平上工作,以消除内部协变量的变化。
与不可训练并且没有正则化效果的局部响应归一化相比,批量归一化是可训练的并且具有正则化效果。
重叠池
这是他们用过的下一个酷招。
通常,我们使用非重叠池,如下所示:

图一(来源:阿布舍克·维尔马)
但是,在 AlexNet 中,使用了重叠池。

图二(来源:阿布舍克·维尔马)
我们来了解一下背后的直觉。

给定一幅图像,我们推断出图像中物体的形状和边界,因为边界的两边有明显的区别。这也有助于我们确定物体在图像中的位置。
让我们以上图为例。我们的注意力集中在图像的对象上,也就是说,在这种情况下,是女孩。我们可以清楚地定位图像中的女孩,因为我们可以在脑海中围绕女孩画出边界。
这就是我们推断的图像中的空间信息。
在非重叠汇集的情况下,我们可以看到,由于汇集的不连续性,将会丢失一定量的空间信息,因为所有高值都将被捕获。
但是,在重叠汇集的情况下,我们可以看到,随着高值,一些低值密度高的区域,它们也将得到保护。空间信息是两者的结果,因此,在重叠池的情况下,它将被更好地保存。
什么是过度拟合?
当网络开始关注某个特定的特征时,任何偏离都会导致错误的预测。这种超敏感性导致泛化能力差。
因此,如果使用非重叠池,那么,网络将继续集中主要特征,只会导致灾难性的过度拟合。
但是,在重叠池的情况下,由于空间信息是守恒的,网络不会轻易溢出。
现在我还没有看到这种技术被普遍使用。最合理的原因是批量标准化,它具有正则化效果,还可以防止过度拟合。因此,为了节省空间,我们使用正常的非重叠池。
数据扩充
他们使用的第三个技巧是数据扩充。
我们希望我们的神经网络能够很好地泛化,因此,我们通过进行一些简单的操作和动态操作来增强我们的数据,即增强的图像是在训练时生成的(就像在 AlexNet 中一样)。
AlexNet 使用图像翻译和水平反射。在他们拥有的 256x256 的图像中,他们随机选取了 224x224 的图像以及它们的水平反射。因此,随机获取补丁的行为就是图像转换。至于水平翻转,我们来看这个例子:

来源:阿布舍克·维尔马
他们使用的第二种增强手段是我在别处从未见过的。他们改变了训练样本中 RGB 通道的强度。
他们首先对整个 ImageNet 训练数据集的 RGB 像素执行 PCA。他们提取了每个通道的主要成分。然后,他们将这些主成分的随机部分添加到图像的每个像素中。
它对图像所做的是改变照明的颜色和强度。因此,它利用了自然图像的一个特性,即物体的标签对于光照参数是不变的。一只狗是一只在明亮的白光和黄灯下的狗,句号!
这是我第一次与这种增强幽会,还没有看到它被使用。由于当今数据的巨大规模,当我们今天有其他随机操作用于增强时,如缩放、倾斜等,经历寻找主成分的痛苦似乎是低效的。
拒绝传统社会的人
这是他们用的第四招。老实说,这不需要介绍,因为这是今天减少神经网络过度拟合的事实上的方法。
丢弃是随机关闭一些神经元,这样,每个神经元被迫学习不依赖于其邻居的特征,从而导致更健壮的特征。
最后,让我们来统计一下对这个网络帮助最大的是什么:

来源:阿布舍克·维尔马
如果您对什么是前 1 名和前 5 名错误感到困惑,那么,我们知道 ImageNet 总共有 1000 个类。正常的方法是预测对应于最终层中最高值的类别,这里称为 top-1。另一种方法是采用 top-k 方法(在这种情况下,k = 5),这里,我们将预测作为对应于最终层中具有前 5 个最高值的单元的类。如果在这 5 条中,有任何一条符合事实,那么,我们认为这是一个成功的预测。
培训策略
他们使用的优化器 SGD with momentum 至今仍在使用,但需要一个适当的训练计划,因此很难训练。所以,事实上的优化者是亚当。在 AlexNet 的情况下使用了 0.9 的动量。
训练批量 128,不错,符合所有关于深度学习的建议。批量样本数量越多,模型越好。
重量衰减也使用了 0.0005 的值。体重下降在今天仍然很流行,并被用于模特身上来提高她们的表现。
权重初始化使用标准偏差为 0.01 的零均值高斯分布完成。在偏置初始化的情况下,在第二、第四、第五和更高密度层的情况下,它们已经用 1 初始化偏置,而其他层的偏置用 0 初始化。这种初始化最初通过给 ReLU 正输入来帮助网络。
学习率最初设定为 0.01,每当验证错误率停止提高时,学习率就会降低 10 倍。
我们终于了解了 AlexNet 的一切。
编码时间
资料来源:阿布舍克·维尔马
如果你想试试这段代码,我建议 Google 的COLAB。这个用的是 TensorFlow 2.2.0。我在这里使用了简单的 MNIST 数据集,并调整其大小以适应 AlexNet 输入。为什么?因为如果我们输入 28x28 图像可用 MNIST,这不会编译。试试看!第一次卷积后,就没有什么可以应用最大池了。
现在,我已经尽我所能从论文中吸收了更多的内容。首先,我没有使用两个词干,因为这不是 GPU 空间匮乏的古代。所以,我用了一个单独的茎。
在要点的第 37 行之前,我已经加载了 MNIST 的数据并对其进行了整形。我只取了 MNIST 的一小部分,因为加载它并调整它的大小会溢出内存,导致内核被转储。
在第 38 行,我已经用tf.keras.layers.Conv2D定义了第一层。滤镜数量为 96,滤镜大小为 11x11,激活为relu,我用过的最后一个不熟悉的kernel_initializer是用均值为 0,标准差为 0.01 的高斯分布初始化权重,在论文中有提到。如果你想知道偏差,默认情况下,它们被设置为零。
在行 42 处,我们有tf.keras.layers.MaxPooling2D,其中我将过滤器大小设置为 3x3,步幅设置为(2,2)。
在行 44 处,我们又有了tf.keras.layers.Conv2D。在这里,有一点改变了,我也使用了一个保存值ones的bias_initializer。如论文中所述,这是为了在该层设置偏差 1。
在线 48 处,我们有一个tf.keras.layers.MaxPooling2D就像 42 线一样。
在50 线,我们有tf.keras.layers.Conv2D。滤波器数量为 384,滤波器大小为 3x3,激活为relu,kernel_initializer已用于使用均值为 0、标准差为 0.01 的高斯分布初始化权重,如论文中所述,最后bias_initializer已用于将偏差设置为 1,如论文中所述。
在线 53 和 57 处,遵循与线 50 相同的模式。
在线 61 处,我们有一个tf.keras.layers.MaxPooling2D就像 42 线一样。
在第 63 行的处,一个Flatten层被用来去掉多余的尺寸。这是正在发生的转变:

来源:Deep Tech Talker
在第 65 行,Dense层使用了 4096 个单位(在论文中,每个词干有 2048 个单位),kernel_initializer被用于初始化平均值为 0、标准差为 0.01 的高斯分布的权重,bias_initializer被用于初始化偏差为 1,如论文中所述。
在行 69 处,Dropout已被使用并设置为0.5。在论文中,辍学的价值并没有具体提到与网络的关系,但是,在关于辍学的讨论中,他们谈到了这个价值,因此,我使用了它。没有明确提到所使用的辍学。
在线 71 处,遵循与线 65 相同的模式。
在线 75 处,遵循与线 69 相同的模式。
在第 77 行,我们有预测层,这里,我们有 10 个类,相比之下,在 AlexNet 中使用的 ImageNet 中有 1000 个类。使用激活softmax和 10 个单位的Dense层进行预测。此外,kernel_initializer已被用于初始化具有平均值 0 和标准偏差 0.01 的高斯分布的权重。偏差隐含地为 0。
在第 83 行,我们有model.compile,在这里我们决定优化器、损失和模型的指标。作者使用了动量为 0.9、重量衰减为 0.0005 的 SGD,但是在 TensorFlow 中没有 SGD 的重量衰减功能。所以,我只用过动量 0.9 的 SGD。根据论文已经使用了 0.01 的学习率。论文中的指标是前 1 名(相当于准确性)和前 5 名。这两个指标都设置在这一行中。损失是用于多级分类的categorical_crossentropy。
在第 89 行处,当验证误差没有改善时,我使用了ReduceLROnPaleau来降低学习率。对于多少个时代,他们看到它是否在改变,这在的论文中没有提到。这由所用函数中的patience属性设置。factor属性允许我们在论文中提到的学习率没有提高时,将学习率除以 10。min_lr显示了学习率的下限,这是作者在训练时设定的最小学习率。
在线 93 处,我们拟合模型。根据文件设定了 128 个批次和 90 个时期。
今天,我们回顾并了解了第一个将 GPU 带到阳光下的开创性网络。这个网络单枪匹马撬动了图像深度学习的时代。它让 GPU 变得流行起来,而且它们会一直存在下去。
PCA 背后的代数
让 PCA 变得伟大的代数概要!

罗马法师在 Unsplash 上拍摄的照片
在我进行的一些采访中,我们最终会谈到降维技术。PCA 绝对是最受考生欢迎的一个。我个人不喜欢深入挖掘与角色不相关的领域,因为我自己可能也不知道答案!但是我喜欢问他们是否知道 PCA 是如何工作的。虽然我并不期望应聘者知道确切的代数,但我喜欢看他们是否有一些直觉,他们是否只是不知道(这对我来说完全没问题),或者他们是否试图假装他们知道,这就是我的大脑用黄色旗帜提醒我的地方。
一些候选人开始谈论 PCA 如何使用特征向量来计算最终特征。这里是我喜欢问的地方,什么是特征向量,PCA 计算的特征向量是什么?这是大多数候选人开始动摇的地方。同样,即使这不是成为一名数据科学家必须知道的事情,我个人也更愿意得到诸如我不确定之类的答案,而不是候选人不知道的事情。
在这篇文章中,我希望能帮助人们对 PCA 的实际工作原理有一些基本的直觉,并且在面试中有信心回答这个问题。
特征分解:特征值和特征向量
Eigen 来自德语,意思是拥有,因此可以将特征向量和特征值转换为矩阵的自向量和自值。但这实际上意味着什么呢?
让我们后退一步,把本征态的定义正式化。我们将矩阵 A 的特征值 a 定义为:
一个 v =一个 v
换句话说,对向量实施线性变换(保持和与乘的变换),通过标量改变。因此,当且仅当 v 是 A 的特征向量时,对 v 应用矩阵 A 的点积只会改变向量的长度而不会改变其方向!注意 A 是一个n×n矩阵,在做特征分解时会有 n 个特征向量和 n 个特征值。**
只是澄清一下,不是所有矩阵和向量之间的点积都满足这个条件。
必须是一个方阵(行数与列数相同)才能进行特征分解。除此之外,为了很好地定义特征向量,所有特征值必须互不相同。
最后,同样重要的是要注意,所有的特征向量都是相互垂直的,每个特征向量都有自己的特征值。
PCA 的代数
为了理解 PCA 的代数是如何工作的,我们先来思考一下 PCA 的目标是什么。使用 PCA,我们希望减少完整数据集中的特征数量,尽可能多地保留原始数据中的信息,并删除最高的相关性。
但是等等!我们如何衡量这些相关性来确定方向的优先级?嗯,我们确实有一个矩阵来跟踪不同特征之间的相关性,这就是 协方差矩阵 ,所以让我们使用它吧!
关于这一点,有一个快速说明:有其他矩阵可用于 PCA,但协方差矩阵是最流行和直观的一种。
因此,我们可以对协方差矩阵进行特征分解,看看哪些是具有更高特征值的特征向量。对应于最高特征值( x1 )的特征向量将是指示数据中最高方差的特征向量,因此是特征之间相关性最小的方向。第二个( x2 )将是垂直于 x1 的第二高方差方向,以此类推。
简而言之,一旦计算出协方差矩阵,如果想将 n 维从 n 维减少到 m 维,就很简单:
- ****第一步:计算协方差矩阵的特征向量。
- ****第二步:设置特征值最高的前 m 个特征向量。这将是你的旋转矩阵 W, 其中 W 中的每一行对应于排序后的顶部 m 特征向量。 W 是一个 m x n 矩阵。
- 步骤 3 :给定一个数据点 x, 可以通过执行线性变换x’= W x .找到在 m 维空间中的投影,给定 W 是一个 m x n 矩阵,x’****
例子
让我们看看下面的例子,以便更清楚地了解发生了什么:
假设我们有两个特征:给定城市中一套公寓的大小和该套公寓的价格。我们的任务是将数据缩减到 1D 空间。给定的数据集如下左图所示。
一个人应该采取的步骤是()同样,有多种方法可以做到这一点,我们只是举一个例子!):
- ****第一步:根据你的数据定义协方差矩阵,计算你的协方差矩阵的特征向量。
- ****第二步:特征向量在中间的图片中显示为绿色。最长的特征向量是对应于最高特征值的特征向量(特征向量通常被归一化为 1,这只是为了可视化的目的)。很明显,它是指向最高方差的方向。这是一个人想要保持的方向,因为它包含了最多的信息。
- ****第三步:一旦确定了最高特征值对应的特征向量,就要把数据点投影到后者定义的直线上。如右图所示。



图 1:(从左到右)a)原始数据集 b)原始数据集连同协方差矩阵特征向量 c)原始数据集在最高特征值对应的特征向量所定义的直线上的投影。
我希望这能让你对使用 PCA 时发生的事情有一个基本的概念!
人工智能中的算法偏差需要讨论(和解决)
你在这件事上有责任…
介绍
当人工智能用于解决全球性问题时,算法偏差可能会开始出现,并可能导致意想不到的不便、负面影响和损害。
对于那些不熟悉术语“算法偏差”的人,我将在本文中提供一个合适的定义。
但是,如果你曾经遇到过一篇新闻文章,指出某种形式的歧视是由人工智能或自动化系统传达的,那么你就会遇到算法偏见。

新闻标题中的人工智能偏见
算法偏差这个话题并不新鲜,我将提供几年前的几个偏差的例子。
我现在写这篇文章的原因是因为人工智能系统和机器学习解决方案在解决全球问题方面的快速应用。
更具体地说,在撰写本文时,有公司 、数据科学家、机器学习工程师和人工智能爱好者已经接过了衣钵,利用他们的技能来帮助对抗新冠肺炎·疫情。
理应如此。
但同样重要的是,这些公司和有才华的个人要明白,大量的人使用他们的系统,所以当涉及到算法偏差的问题时,需要某种形式的审查。
让我们开始吧
算法偏差
算法偏差这个话题很重要,也有些复杂,但是它的定义很简单。
算法偏差是从计算机系统的输出中出现的缺乏公平性。《算法偏差》中描述的不公平有多种形式,但可以总结为一个群体基于特定分类的歧视。
我不知道读者的年龄、种族或性别,但我可以向你保证,每个人都容易受到算法偏见的危害。
原因

Artem Maltsev 在 Unsplash 上拍摄的照片
算法偏差的真正原因是什么,我们真的能指责谁吗?
今天,算法和机器学习系统中的偏见是许多情况的结果。
深度学习模型的工作方式是利用神经网络的模式识别能力。
因此,可以说深度学习模型不能通过设计直接产生偏差,任何偏差的出现或原因都是神经网络的架构和设计之外的。
机器学习模型和人工智能系统产生的输出只是它们所接触的训练数据集的反映。
所以,我们需要退一步,观察训练数据。
对于那些不知道的人来说,训练数据是输入到神经网络的预期类别的例子。这些示例反映了在现实生活场景中使用时暴露给神经网络的数据。
我认为,在人工智能系统中,训练数据主要通过两种方式导致算法偏差。
- 数据收集者持有的个人偏见
- 环境偏差在数据收集过程中有意或无意地施加。
请注意,训练数据可能会以其他方式导致算法偏差。我就着重说上面提到的两个。
像你我这样的人通常会收集训练数据。有意或无意地,我们都有内部偏见,这些偏见可以在建立机器学习模型时涉及的数据收集过程中反映出来。
环境偏差可能是为旨在全球范围内使用的人工智能系统在本地获取训练数据的结果。人工智能系统可能没有用足够的数据进行训练,这些数据代表了它预期运行的实际场景。
它发生了,而且还在发生!
2015 年,Jacky Alciné写了下面这条推文。他的推文表达了他对谷歌照片背后的分类算法的担忧。该算法把他的朋友误归类为大猩猩。
谷歌声称已经解决了这个问题。但在 2018 年,《连线》再次测试了该系统,似乎谷歌的解决方案是避免将大猩猩和其他一些灵长类动物完全分类。他们似乎只是简单地解决了这个问题。
时间快进到 2020 年 4 月,仍有消息称谷歌图片标签服务在对装有物品的手臂进行分类时表现出种族偏见。这个标签系统似乎把一个拿着一个物体的黑手归类为枪。
手持的物体是一个温度计,很多你可能在最近的新闻中看到过。在当前的新冠肺炎疫情期间,这些温度计正成为一种熟悉的景象,因为它们被用作识别患病个体的方法。
这种形式的偏见,以及许多其他形式的偏见,正在实时发生。
想象一下,在未来的五十年里,先进的机器人执法系统开始管理社区,它们无法区分一个持有非威胁性物品的有色人种和一把真正的枪。
更可悲的是,这与许多人今天面临的现实并不遥远。唯一的区别就是缺少机器人。但这是一个完全不同的对话,这是不断提出的。
我们来谈谈解决方案。
解决方案?
当想到算法和人工智能偏差的解决方案时,一个词浮现在脑海中。
多样性。



图片来自 Unsplash
向前迈出的一步将是在人工智能行业的任何流程或项目的早期阶段纳入多样性工作。我们甚至可以追溯到鼓励学术机构的多样性。
我经历过技术领域缺乏多样性。在我读机器学习和计算机视觉理学硕士期间,我能数清整个课程中黑人学生的数量。准确地说是四个,包括我自己。这门课有 200 多名学生。
机构内部缺乏多样性可能不是故意的,但这一问题应该得到可悲的解决。如果我们有更多具有不同背景的个人收集数据并建立人工智能系统,我们可能会看到以前可能被忽略的数据集片段的包含。
在整篇文章中,我关注的是人工智能系统中存在的种族偏见。但我们也应该意识到可能出现的其他形式的偏见。例如,卡内基梅隆大学的研究人员在 2015 年进行的研究揭示了谷歌广告中存在的性别歧视。
长话短说,与男性同行相比,女性不太可能看到高薪工作广告。
同样,这些系统中偏差的原因不能直接确定,但是解决方案可以在与 AI 产品开发相关的所有过程中实施。
一个良好的开端将是确保训练数据确实代表这些人工智能系统被利用的实际场景。
在法律和决策部门可以看到另一种解决办法。有组织的机构正在推动关键的政策制定者确保减少算法偏差的措施是一项强制性措施,而不是一项选择。
在大多数情况下,构建人工智能系统的工程师并没有内在的偏见和对特定人群的偏见。
然而,由于缺乏对其他文化和各行各业的接触,在开发系统预期运行的实际现实和创造者打算如何使用它之间可能存在脱节。
公司和组织内部的道德教育是减少算法偏差的解决方案之一。对员工进行文化和生活方式差异方面的教育可以让他们意识到社会中可能被忽视甚至没有考虑到的群体。

Jonas Jacobsson 在 Unsplash 上拍摄的照片
一些公司正在人工智能领域做出积极努力,以增加学术机构和人工智能课程中代表性不足的群体。就拿 DeepMind 奖学金项目 来说吧。
该项目提供的奖学金面向低收入背景的个人;非洲或加勒比遗产或妇女。
要解决全球性的挑战,需要来自各种背景的优秀人才和个人的共同努力。这就是我们开始看到的。
走向可信的人工智能开发是由研究人员共同努力定义的一套指导方针,使开发人员能够在他们的人工智能系统开发中负责任。
你从哪里进来
这篇文章的大部分读者可能受雇于人工智能行业,有些人甚至可能直接参与设计在几个软件产品中使用的机器学习模型。我赞扬您花时间阅读这篇文章,并邀请您进一步探讨这个主题。
你是算法偏差整体解决方案的重要组成部分。解决方案从你开始。数据收集者、机器学习工程师、数据科学家和研究人员都扮演着至关重要的角色。

每个机器学习从业者都应该意识到算法偏差可能导致的问题和潜在损害。
这篇文章不是为了羞辱个人或公司而写的。
相反,它是为了向人工智能社区表明,在算法偏见的问题上存在着争论。
我相信,为减少人工智能偏见而采取的对话和行动的增加,应该与人工智能本身的进步速度成比例。
感谢阅读。
[## 作为机器学习工程师你需要的 5 个软技能(以及为什么)
包括成为任何劳动力的有用组成部分的提示
towardsdatascience.com](/5-soft-skills-you-need-as-a-machine-learning-engineer-and-why-41ef6854cef6) [## 机器学习工程师和研究人员之间的 7 个关键区别(包括工资)
包含有关期望薪资、工作量、可交付成果以及更多关键差异的信息。
towardsdatascience.com](/7-key-differences-between-machine-learning-engineers-and-researchers-salaries-included-b62c3aaebde9)
算法偏差和混淆矩阵仪表板
在预测分数的分布下,混淆矩阵如何表现
随着算法越来越多地对人类事务做出决策,这些算法及其所依赖的数据必须公平和无偏见,这一点非常重要。算法偏差的诊断之一是混淆矩阵。混淆矩阵是一个表格,显示了在预测中会出现什么样的错误。虽然每个处理数据的人都知道什么是混乱矩阵 什么是 ,但是对于它在不同种类的预测和结果分布以及可能的决策阈值范围下如何表现,获得直觉是一件更微妙的事情。
在本文中,我将介绍一个交互式的 混淆矩阵仪表板 ,您可以使用它来探索不同的数据集和预测模型,并观察混淆矩阵的行为。您可以加载自己的数据。其中两个数据集是纯粹的合成分布,你可以调整旋钮。另一组数据包含了一些综合的例子,这些例子说明了算法偏差是如何与环境不平衡区分开来的。我所说的环境失衡是指不同的群体可能天生拥有不同的特征分布,从而导致不同的结果分布。我提出了一种预测偏差的新方法,称为阳性预测比得分(PPRS ),它独立于混淆矩阵,而是比较预测得分范围内的阳性结果比曲线。

混淆矩阵仪表板——钟形负面和正面结果分布。
混淆矩阵仪表板还包括两组关于严重事件的真实数据,并附有一些预测模型。一个有趣的模型是用于预测刑事累犯的 COMPAS 模型。COMPAS 模型因所谓的算法偏差而受到抨击。这种说法是基于不同种族群体的混淆矩阵中出现假阳性和假阴性率的方式。然而,没有单一一致的方法来定义算法偏差。混淆矩阵仪表板允许我们探索潜在的数据分布和预测模型可能引起可能被误导的偏见指控的方式。
为了配合本文,我准备了一些视频来介绍主要概念。这篇文章的 2 分钟宣传片是:

预测得分
为了理解混淆矩阵的目的,考虑一个为二元结果变量产生预测分数的过程。分配分数后,我们进行实验并进行观察。观察结果被记录为正面或负面。多次这样做,我们可以建立两个结果分布作为预测分数的函数,一个分布用于正面结果,一个用于负面结果。
混乱矩阵仪表板允许你试验两种不同的交互式合成分布。一个合成分布定义了正面和负面结果的分数,这些分数以凸起或“钟形曲线”的形式下降。您可以控制正负分数凸起的高度、宽度和位置。第二种分布沿预测分数轴更均匀地放置正面和负面结果分数。随着分数的增加,你可以玩这些分布的上升和下降。

例如:苹果零食
这是一个真实的虚构的例子。这个例子开始很简单,但是它允许我们评估算法偏差和公平性的概念。
假设你正在为 500 个孩子的学校野餐打包快餐盒。一些孩子喜欢苹果,而另一些喜欢其他东西,如爆米花、饼干或饼干。你有两种点心盒,一种装苹果,一种装别的东西。你必须事先决定给每个孩子哪种盒子,然后贴上他们的名字,分发给他们。当每个孩子打开他们的零食盒子时,他们要么会对他们的零食感到满意,然后说“耶!”,否则他们会失望地说“Awwww”。

为了帮助你做出决定,你可以根据一些经验来预测每个孩子喜欢哪种零食。大一点的孩子喜欢苹果,而小一点的孩子不喜欢。高个子孩子喜欢苹果,而矮个子孩子不喜欢。阿普尔鲍姆先生班上的孩子倾向于喜欢苹果,而爆米花女士班上的孩子想要别的。没有硬性规定,只是有根据的猜测。
对于每个孩子,你给他们一个分数,表明他们想要一个苹果的预测。10 分意味着你很确定他们会想要一个苹果,比如在阿普尔鲍姆先生的班上,一个 10 岁的高个子。1 分意味着你确信他们不会想要苹果,就像爆米花女士班上一个较矮的 6 岁小孩。
对于每个孩子,在计算他们的预测分数后,你做出决定。你可以在 5 分的中间点做决定。或者,您可以将苹果零食阈值设置得更高或更低。例如,如果孩子们吃水果很重要,你就把门槛设得低一些,这样你就能抓住更多喜欢吃苹果的孩子。或者,如果你想尽量减少扔进垃圾桶的苹果片,那么你可以把门槛设得更高,这样分发的苹果零食就更少了。换句话说,您的决定取决于对不同类型错误的权衡。
野餐时,你记录下孩子们的反应。你写下你给他们的预测分数是多少,你是否根据决策阈值给了他们一个苹果,他们的反应是什么。这是你的决定的回报。
我们在一个表格中记录结果,表格中的行对应于孩子的偏好,列对应于你给每个孩子一份苹果零食或其他零食的决定。混淆矩阵计算表中每个象限的数字和比率。
原始计数表位于左上方,而比率表位于右侧。

混淆矩阵:计数、比率、条件使用测量。
评估绩效
你的表现取决于几个因素:
- 你的预测与每个孩子的需求有多吻合。理想情况下,你的预测会将所有想要苹果的孩子(红色)分布在右边,而所有没有苹果的孩子(绿色)分布在左边。这样你就可以把门槛放在中间,正确预测每个孩子的偏好。

零食偏好的理想可分分布。
- 有多少孩子真的想要苹果。这是基本比率,红色苹果小孩和绿色非苹果小孩的总比例。
此时,您可能需要花点时间在混淆矩阵仪表板中玩一下双单峰分布合成器。用分数排列正(红)和负(绿)凸起,使分布完全分开。然后,通过让分布重叠来增加决策的难度。左右滑动阈值,查看混淆矩阵中的计数和比率如何变化。
评估你的表现有多种方法。你可以关注你预测正确的孩子的比例(TPR 和 TNR)。(TPR:真阳性率又称为 敏感性 ,TNR:真阴性率又称为 特异性 。)或者你可以专注于你弄错的孩子(FPR:假阳性率,FNR:假阴性率)。或者,你可以关注你认为想要苹果的孩子的比例,然后他们真的想要了。这叫精度。精度,也称为正预测值(PPV),是 Berk 等人称为条件使用度量[1]的四个术语之一,如底部表格所示。
然后,这些度量可以进一步组合成聚合度量,其名称如“准确性”、F1 分数和 MCC。
ROC(接收器工作特性)和 Precision/Recall 曲线显示了随着决策阈值的变化,一些指标如何相互权衡。你可以在维基百科和许多其他解释网站上阅读所有关于这些措施的内容。
虽然这里我们只考虑二元决策,但多变量预测会产生更多行和列的混淆矩阵,以及对其他性能指标的阐述。
预测偏差
考虑两个孩子群体,其中一个总体上更喜欢苹果(较高的基本比率),而其他人不太喜欢苹果(较低的基本比率)。然后,从数学上证明,如果正分布和负分布重叠(通过设置决策阈值不能完全分离),那么这两个群体的混淆矩阵条目在假阳性率、假阴性率、假发现率和假遗漏率方面不可能相同【2】【3】。然而,这些都是评估决策过程中的公平性和偏见的有效候选者。换句话说,不存在单一的方法来确定一个决策过程是否偏向于或反对预测一个群体对另一个群体的正面和负面结果。
为了更深刻地理解这一事实,我为苹果零食决策问题生成了合成数据。一个孩子相对于其他孩子对苹果零食偏好被认为是四个属性的线性函数,这四个属性是年龄、身高、老师和宠物。公式如下:

年龄从 6 岁持续到 10 岁。身高从 40 到 60 英寸不等。Class 接受三个分类值中的一个,{Ms. Popcorn=0,Miss Fruitdale=1,Mr. Applebaum=2}。宠物取四个值之一,{乌龟=0,鱼=1,猫=2,狗=3}。系数 c 为属性提供权重。为了简单起见,我们将所有系数设置为 1.0,但是将属性值规范化为范围 0 到 1。这样,所有属性都同等重要。预测分数被标准化为 0 到 1 的范围,然后被视为孩子更喜欢苹果零食(1.0)或其他零食(0.0)的概率。为了绘制图表,预测分数被划分成一定数量的箱。对于这个问题,20 个箱很好地显示了分布曲线。

产生孩子们对零食的偏好。
为了生成合成孩子、他们的预测分数和偏好结果,我们对四个属性的生成器分布进行采样。对于年龄和身高这两个连续的属性,让我们使用一个线性生成器分布,它可以在整个范围内是均匀的,也可以向下限或上限倾斜。如果年龄的发生器分布向上倾斜,那么年龄大的假装孩子会比年轻的多。因为对苹果的偏好随着年龄的增长而增加,那么这将使预测得分的分布更加倾斜。
类似地,对于这两个分类属性,我们可以说所有的教师被分配的概率相等,或者不同。例如,如果将更多的孩子分配给 Applebaum 先生,那么分数分布将会倾斜得更高,因为 Applebaum 先生贡献的预测分数因子为 2(在范围规范化之前),而 Popcorn 女士的预测分数因子为 0。
一旦通过从生成器分布中取样给一个孩子分配了属性,我们就可以将他们的预测分数视为偏好苹果零食的概率。然后,根据概率,通过投掷一枚有偏向的硬币来为那个孩子生成一个假装的偏好结果,从而完成样本。由于统计的可变性,每个预测得分箱的阳性和阴性结果的数量将随着试验的不同而不同。出于这个原因,在这些例子中,我选取了 100,000 个假装的孩子作为样本,只是为了平滑统计数据。
结果是正面结果偏好分布(偏好苹果零食)和负面结果的分布(偏好其他零食)。混淆矩阵仪表板包括五种不同的实验条件,不同的发电机分布:
条件 1。统一:所有属性在其范围内被统一采样。由于中心极限定理,这产生了预测分数的钟形分布。作为基于预测分数产生孩子实际偏好的结果,这导致积极结果和消极结果的分布在空间上有些分离。在中间设置阈值表明,这种分布实现了 0.64 的真阳性和真阴性率,以及 0.36 的假阳性和假阴性率。精确度和阴性预测值都是. 64。ROC 曲线的面积为 0.7,这通常被认为是可接受的预测能力,但远非完美。

苹果零食条件 1:均匀发电机分布。
为了探索算法偏差的问题,我按性别分离了生成器分布。女孩为四个属性中的每一个获得一个生成器分布,而男孩可能获得不同的一个。这反映了一个事实,不管出于什么原因,结果可能是女孩在人群中有不同的年龄范围,不同的身高范围,被不同地分配给教师,或者对宠物有不同的偏好。统一实验从对男孩和女孩使用相同的生成器分布开始。因此,毫不奇怪,它们各自的预测分布是相同的。
条件二。偏斜相同:所有属性都用偏向高端的生成器分布进行采样。越来越多的年长和高的孩子出生,然后越来越年轻和矮。与爆米花女士相比,更多的孩子被安排在阿普尔鲍姆先生的班级。更多的孩子把狗作为宠物,而不是乌龟。结果,零食偏好倾向于更喜欢苹果零食而不是其他零食。在偏斜相同的条件下,女孩和男孩的生成元分布是完全偏斜的。因此,他们得到的苹果零食偏好分布是相同的。
条件 3。偏斜相反:女生的属性采样为偏高的生成器分布,而男生的属性偏低,即男生更年轻,更矮,在爆米花先生的班级里更多,有更多的乌龟和鱼而不是猫和狗。因此,女孩偏爱苹果,而男孩偏爱其他零食。总体而言,女孩喜欢苹果的基本比率为 58%,而男孩喜欢其他的基本比率也是 58%。

苹果零食合成数据——女孩和男孩倾向相反的偏好。
最有趣的是比较混淆矩阵的四个象限。(我将使用近似值来说明采样噪声。)以 10 为阈值,在预测得分范围的中间,女生表现出的真实正率为. 79,真实负率仅为. 46。这是因为女孩的偏好偏向偏好分数中点右侧的苹果偏好女孩(红色)更多。对男孩来说,情况正好相反。类似地,女孩显示出 0.54 的假阳性率,因为她们对绿色(其他零食)的偏好有一半落在阈值的右边。他们的假阴性率只有. 21。同样,对男孩来说,情况正好相反。有趣的是,Precision (PPV)和 NPV 更接近,虽然不完全相同。
人们可能会看到这些混乱矩阵,并决定预测评分和决策过程是有偏见的。我认为,对女孩的偏见取决于你是否喜欢苹果。然而,有一种方法可以将 TNR、FPR、FNR 和 TPR 这四个象限统一起来。即向上调整女生的决策阈值,向下调整男生的决策阈值,直到隔着三个 bin。例如,将女孩阈值设置为 12,将男孩阈值设置为 9。当您在混淆矩阵仪表板中进行这些调整时,您可以看到各个 ROC 曲线上的决策点发生了变化。
由于前面提到的数学约束,这种调整使对准的精度(PPV)更加于之外,并随之带来其他条件使用度量 NPV、FDR 和 FOR。你不能拥有一切。但是,如果您愿意,您可以调整阈值,使四个条件使用术语更加一致,代价是使女孩和男孩的四个正比率和负比率度量值进一步分离。
一般来说,学者和政策专家会举手表示,由于在混淆矩阵中找不到算法偏差的单一统一度量,因此必须根据政策来确定。也就是说,人群之间哪种性能指标的差异是可接受的,哪种是不可接受的?
毫无疑问,基于政策的权衡决策是必不可少的。但是作为一个技术问题,在评估预测偏差时,我们可以做得比仅仅依赖混淆矩阵更好。
受苹果零食实验的启发,让我们考虑一种不同的方法来判断预测分数是否有偏差。这种方法关注分数的一致性来预测结果。对于一个给定的预测分数箱,结果是否显示女孩和男孩以相等的比例更喜欢苹果零食或其他零食,而不管多少女孩或男孩碰巧有那个分数?这就是所谓的校准公平性【2】。该属性源自一个名为阳性预测比率的值,该值就是每个条柱中阳性结果的比例。在预测分数的范围内,阳性预测率描绘出一条曲线,在混淆矩阵仪表板中用褐色绘制。
正向预测比得分
在偏斜的相反发生器分布下,女孩和男孩的积极预测比率曲线是相同的。点击 PPRS 标签下的复选框,将它们叠加起来进行比较。这意味着预测分数准确地反映了模拟孩子的偏好,不管这个孩子是喜欢苹果零食还是其他零食的人群中的一员。
这一观察激发了基于两个群体的阳性预测比率曲线之间的差异的偏倚的汇总测量。具体来说,计算两条曲线之间的面积的函数。有许多方法可以做到这一点。我选了一个非常简单的:

这是两个群体(1 和 2)的阳性结果与所有结果之比 r 的平方差在预测分数仓上的总和,通过因子进行加权和归一化。加权因子是两个总体之间每个箱中的最小计数。这种加权的动机是当样本很少时,在样本噪声下概率可能变化很大。当任一群体在一个箱中放置少量样本时,阳性预测率的差异不显著。PPRS 测量受到统计噪声的影响,这取决于每个箱的样本大小。
偏斜相反情况的 PPRS 是 0.01。一般来说,在我的估计中,低于 0 . 2 的分数表示相对一致的阳性预测比率曲线,可以认为是无偏的,而高于 0 . 6 左右的分数表示曲线中有一些显著的偏差,并表明预测偏差。
预测偏差是什么样子的?接下来的两个生成器分布提供了示例。
条件 4。偏斜相反偏向女孩:像偏斜相反实验一样,生成器分布被设置成使女孩的零食偏好偏向高的一边,而男孩则偏向低的一边。但这一次,女生的预测分数统一下移 0.1(左移 2 格)。

请注意,在这种情况下,女孩和男孩的偏好分布表面上看起来比条件 3 更相似。绿色和红色曲线更接近对齐。但是通过改变女孩的预测分数,在每个箱中,男孩和女孩之间的积极预测与箱中孩子数量的比率现在非常不同。女孩得到的苹果会比她们喜欢的少。这种差异反映在阳性预测比率曲线中,这些曲线现在明显分开。它们之间的差距提供了 1.0 的 PPRS,这是预测偏差的重要指标。
条件 5。均匀随机化女孩:这个实验从女孩和男孩的相同均匀发生器分布开始,与条件 1 相同。除了这一次,一半的女孩被随机选中,并被分配一个随机预测分数。你可以看到女孩的积极和消极结果分布(红色和绿色曲线)变平了。ROC AUC(曲线下面积)下降,越来越少的女孩得到她们喜欢的零食。PPRS 是相对较高的 0.75。
这个项目的 GitHub repo 中提供了使用您自己版本的生成器发行版来生成苹果点心样本的 Python 代码[4]。
真实世界数据:泰坦尼克号生存
我们可以在混淆矩阵仪表板中检查真实数据。一个众所周知的数据集列出了 1912 年泰坦尼克号沉没时幸存和遇难的乘客。对于每位乘客,数据集将年龄、性别、家庭规模、票价等级和票价等特征制成表格。泰坦尼克号的生存预测任务是 Kaggle.com 号的一个开始项目,80%的准确率是典型的。对于这个数据集,我建立了两个模型;他们的预测包含在混淆矩阵仪表板中。一个简单的模型是逻辑回归,它为每个可能的特征值计算一个权重因子(在一些简单的特征工程之后)。更复杂的机器学习算法是梯度推进回归器。这使用了决策树的集合,并且可以考虑观察到的特征之间的复杂非线性相互作用。对于该数据集和特征,GBR 模型的表现略好于逻辑回归,AUC 为. 86,最佳 f1 值为. 78(决策阈值= 4)。

泰坦尼克号的生存——梯度推进回归模型。
泰坦尼克号模型展示了许多有趣的特性。男性的存活率为 19%,而女性为 74%。女人和孩子先上救生艇!适当地,预测算法显示两个相距很远的凸起。查看男性和女性数据子集,绿色的阴性结果冲击发生在男性亚群中,而红色的阳性结果冲击发生在女性中。在中点决策阈值为 5 时,女性的真实阳性率(预测存活,并且确实存活)和男性的真实阴性率(预测不存活,并且没有存活)都非常高。男性和女性乘客的假阳性和假阴性率高度不对称(FNR = .79(m)/.1(f),FPR = .02(m)/.58(f))。这反映了大多数男性的生存概率较低,而大多数女性的生存概率较低,尽管两个方向都有异常值。由于提供了相对简单的乘客特征集,模型无法可靠地预测异常值。在这些泰坦尼克号生存模型的男性/女性分类下,阳性预测比率曲线和 PPRS 不能提供信息,因为结果分布几乎没有重叠,为比较中等范围分数仓中的阳性预测比率留下非常稀疏的统计数据。
真实世界数据:布劳沃德县累犯
2016 年 5 月, ProPublica 发表了一项名为“机器偏见:全国各地都有用来预测未来罪犯的软件。而且对黑人有偏见。”【5】。这篇文章评估了一种叫做 COMPAS 的算法,该算法用于预测刑事案件中的累犯率。伴随本文的是一个 github 知识库,其中包含了用于评估 COMPAS 算法性能的数据和数据分析方法。
ProPublica 的文章提出了以下主张:
正如霍尔德所担心的那样,我们还发现了明显的种族差异。在预测谁会再次犯罪时,该算法对黑人和白人被告犯错误的比率大致相同,但方式非常不同。
- 该公式特别容易错误地将黑人被告标记为未来的罪犯,错误地将他们标记为白人被告的比例几乎是白人被告的两倍。
- 白人被告比黑人被告更容易被误标为低风险。”
关于算法偏差的说法令人担忧,这篇文章被大量引用。毕竟,公平起见,在无偏算法下,我们可能期望两个方向上的误差平均分布。ProPublica 的指控是基于黑人和白人亚群混淆矩阵中假阳性率和假阴性率的差异。
然而,我们从苹果零食的例子中看到,对偏见或不公平的解释并不简单。基本比率、混淆矩阵中的正比率和负比率以及条件使用度量(其中最著名的是精确度(PPV),但也包括负预测值(NPV)、错误遗漏率(FOR)和错误发现率(FDR))之间存在很强的相互作用。犯罪学、统计学和计算机科学文献已经详细讨论了这些算法之间的权衡,COMPAS 算法的公平性也引起了激烈的争论[1,6,7,8,9]。苹果零食的例子表明,不同群体之间偏好分布或结果概率的差异本身并不是预测偏差的指标。总的来说,不管出于什么原因,参加野餐的女孩可能比男孩更喜欢苹果零食。
我们可以使用混淆矩阵仪表板查看布劳沃德县累犯数据,并测试不同的决策阈值如何影响混淆矩阵及其导数分数。布劳沃德县的 COMPAS 决策阈值设定在十分位数 4。ProPublica 数据集不仅提供了由 COMPAS 算法产生的累犯预测,还提供了实际的预测分数,这些分数被称为“十分位数”,因为 COMPAS 报告的预测分数范围是从 1 到 10。该信息还允许我们比较亚群体间的阳性预测率曲线,并计算 PPRS(阳性预测率得分)。
检查混淆矩阵仪表板中的数据源 Broward recipiency-COMPAS 模型,我们证实,的确,在阈值为 4 时,黑人被告的假阳性率为. 42,而白人被告的假阳性率仅为. 22。白人被告的假阴性率是 0.5,而黑人被告的假阴性率是 0.28。
这种差异必须根据黑人被告的基本税率为 0.52,而白人被告的基本税率为 0.39 这一事实来评估。这反映在黑人被告堆积柱状图中红色(正)柱的数量更大。然而,类似于我们在苹果零食实验条件 3 中看到的,这种差异可以通过将黑人被告的决策阈值向上调整到 5,将白人被告的决策阈值向下调整到 3 来消除。这使两个群体的 TPR/FPR 点在 ROC 曲线上一致,尽管它进一步加剧了精确度和阴性预测值的差异。显然,为不同的受保护群体设置不同的门槛会被认为是不公平的。
问题是,FPR 和 TPR 的差异是由于预测偏差,还是由于两个亚人群之间环境特征的差异?值得注意的是,COMPAS 算法根据两组的实际累犯结果一致地分配预测分数。阳性预测比率曲线非常好地对齐,并且它们之间的间隙的 PPRS 测量获得相对小的值 0.17,表明良好的校准准确度。

布劳沃德累犯模型。
COMPAS 算法在 1-10 的十分位数范围内分配相对均匀的预测分数;与苹果零食合成数据不同,分布不是钟形的。除了基本比率之外,黑人和白人被告人群之间最明显的差异是黑人被告被分配到大致相同的位置,而白人被告被发现在较低的十分位数分数中所占比例更大,随着十分位数分数的增加而稳步下降。您可以使用混淆矩阵仪表板的近似线性数据源下拉菜单来近似这些分布,并查看混淆矩阵中的项如何响应。
布劳沃德县累犯的独立预测模型
调查累犯数据集的另一种方法是建立一个独立的模型,保证排除种族因素。假设我们观察到累犯与种族或性取向相关。那么这些因素实际上将是累犯的预测因素,在统计基础上。但是,在一个公平的社会中,我们同意应该根据个人的优点而不是根据他们碰巧属于哪个身份阶层来判断个人。
ProPublica 报道说,在大多数被告被关进监狱的时候,他们会回答 COMPAS 的调查问卷。这些信息被输入到 COMPAS 算法中。不清楚该算法到底使用了什么信息。如果使用种族或其他受保护的阶级因素,那么这可能是不公平的。
为了消除这种可能性,我们可以只提取直接基于犯罪记录的数据,并从中建立一个模型。与泰坦尼克号数据一样,我建立了线性回归模型和梯度推进回归模型。作为比较,两者都包含在混淆矩阵仪表板中。我仅从数据记录中提取了以下特征:
- 年龄
- 少年 _ 恶魔 _ 计数
- juv_misd_count
- 青少年 _ 其他 _ 计数
- 先验计数
- 电荷度
- desc 充电
这些特征与年龄、前科和指控类型有关。在此数据集中,预订时只输入了一项费用,因此原始 c_charge_degree 和 c_charge_desc 要素有且只有一个值。
为了在算法中使用这样的特征,数据科学家将它们转换成可能与我们想要预测的结果相关的数字。因此,我做了一些特征工程。我将原始年龄分为五个年龄组:{ 18–22,23–33,34–50,51–59,60+}我将计数特征分为四个或五个类别的组。对于电荷描述,我创建了一个“一键”向量。我把所有与毒品相关的指控归为一项。我将少于 10 个实例的所有费用描述归入一个名为“其他”的费用类别。然后,对于每个类别,如果该费用在原始“c_charge_desc”特征中报告,则我指定 1,否则指定 0。最后,我加入了一个数字特征,这是适用的指控描述的平均累犯率。
为了训练模型,我们注意到报告变量的观察值‘two _ year _ recid’。如果被告再犯,结果值(或因变量)为 1,如果他们在两年内没有再犯,结果值为 0。
在预测时,独立特征被输入到模型中以产生预测分数。下面是 GBR 模型的结果,显示在混淆矩阵仪表板中。预测分布的形状不同于 COMPAS 模型。但是黑人被告和白人被告之间假阳性率和真阳性率的差距仍然存在。与 COMPAS 模型一样,通过为两个子群体选择不同的决策阈值(这被认为是不公平的),可以使这些混淆矩阵条目一致。最后,与 COMPAS 模型一样,阳性预测比率曲线排列良好,预测偏差的 PPRS 较低,徘徊在约 0.09。同样,这是排除了种族和性别特征的模型。

预测模型的一个问题是数据泄漏。尽管种族、性别或其他受保护的特征可能被正式排除在考虑之外,但这些因素有时可以从其他因素中推断出来。例如,众所周知,在设定保险费率时,邮政编码红线被用作种族的替代特征。
在女孩和男孩具有不同特征生成器分布的合成苹果零食数据的情况下,人们可能会将年龄、身高、老师和宠物这些看似良性的特征解释为孩子性别的反向通道指标。没关系。即使你直接把性别作为一个特征包括进来,女生和男生分布的形状还是一样的。我们在苹果零食条件 4 和 5 中实现预测偏差的方式不是通过在预测分布的形成中引入性别因素,而是通过干扰预测分数的应有值。
在布劳沃德累犯数据的情况下,有可能使用诸如年龄、前科、指控严重程度等特征。反映了刑事司法系统或社会中的种族偏见。我们不能在这里解决这些因素,我们也不能对基础数据或整个刑事司法系统的公正性下结论。在这里,我们只是根据收集的数据集,关注对未来实际记录在案的累犯的预测。
我的结论是,布劳沃德预测算法是而不是有偏的,因为它们在这两个亚群体之间的预测分数有差异分布。在保留基本比率(再分(红色)和非再分(绿色)计数的总数)的同时,将被告铲到预测得分轴的其他地方,会扭曲相应的正预测比率曲线,并增加预测偏差的 PPRS 度量。更正确的解释是,根据获取数据特征和结果的方式,黑人被告亚群固有地表现出更大比例的特征,这些特征将他们置于更高的预测分数。FPR、TPR 和有条件使用措施的差异是其不可避免的后果。
结论
这将是一个很好的逃避难题的选择不相容的和令人困惑的所谓偏见的措施仅仅基于混淆矩阵和它的衍生指标。在这篇文章中,我提出了一个新的预测偏差的衡量标准,积极预测比得分(PPRS)。这更直接地比较了作为亚群体间预测得分函数的结果的一致性,而不考虑控制混淆矩阵中术语的决策阈值。PPRS 测量与校准准确度一致,并且当群体具有不同的基础率和分布时,它不试图校正由于在决策阈值中进行选择而产生的比率差异。根据这一标准,在 Broward 累犯数据中观察到的种族群体之间的差异是由于其特征特性的环境分布的差异,而不是由于任何预测算法的偏见。
公平合理地使用算法和数据是一个巨大而困难的问题。社会通过无数的数据收集和决策过程发挥作用。早在信息时代到来之前,规则、指导方针和程序就已经进化到在经济和治理方面取得系统性成果。从这个意义上说,当人类遵循既定的政策时,他们是在执行一种算法决策。人类的判断带有主观性的好处和代价。除了严格的规则和正式的指导方针之外,人们还能够考虑那些数字和分类账不容易捕捉到的因素。因此,他们可能会有意识或无意识地权衡超出合法范围的因素。他们带来同情和洞察力,怨恨和怨恨。
形式化数据收集和算法的一个承诺就是效率和规模。要素的数量以及处理它们的速度和效率远远超过了训练有素的专业人员、官员和代理人的能力。
算法的第二个承诺是,它们允许在决策过程中控制因素和一致性。输入变量可能不会对人类背景故事进行编码,而人类背景故事可能会令人同情地左右决策。但是他们也排除了基于不公正的偏见而影响决策的因素。形式化算法的影响必须在系统层面进行评估。这包括理解如何收集数据,如何从数据中提取特征,以及如何做出算法决策。
因为计算算法采用了普通人不熟悉的技术,有时甚至连专家都难以完全理解或解释的过程(如一些机器学习算法),所以它们受到怀疑和审查是自然和适当的。当算法因为有偏差的数据或设计不当而做出糟糕的决策时,就必须被叫出来。相反,算法不应该因为正确计算出反映其系统环境令人不快的属性的结果而受到诽谤。这样做将会失去一个强大的工具,这个工具能够消除偏见和成见,增加社会的公平性。
混淆矩阵是一个相对简单的概念,无论预测分数是通过机器算法还是其他方式分配的。但是它在不同类型的数据下的行为是微妙而复杂的。通过交互式混淆矩阵仪表板,我们打算让算法和人类预测和决策的行为更加容易理解和透明。
参考
[1] R. Berk,H. Heidari,S. Jabbari,M. Kearns 和 A. Roth,《刑事司法风险评估中的公平性:现状》,社会学方法&研究,第 1–42 页,2017 年。
[2] J. Kleinberg、S. Mullainathan 和 M. Raghavan,“公平确定风险分值的内在权衡”,载于第八届会议。论理论计算机科学的创新(ITCS)* ,2017。*
[3] S. Goel,E. Pierson 和 S. Corbett-Davies,“算法决策和公平的成本”,载于2017 年第 23 届 ACM SIGKDD 知识发现和数据挖掘国际会议。
[4] E .索恩,“索恩/算法偏差”,2020 年。【在线】。可用:https://github.com/saund/algorithmic-bias。
[5] J. Angwin、J. Larson、S. Mattu 和 L. Kirchner,“机器偏见:全国各地都有用来预测未来罪犯的软件。而且对黑人有偏见”2016 年 5 月。【在线】。可用:https://www . propublica . org/article/machine-bias-risk-assessments-in-criminal-pending/。
[6] A. Flores,K. Bechtel 和 C. Lowenkamp,“假阳性、假阴性和假分析:对《机器偏见:全国各地都有用来预测未来罪犯的软件》的反驳。而且对黑人有偏见。”、“联邦缓刑,2016 年第 80 卷。
[7] W. Dieterich,C. Mendoza 和 T. Brennan,“COMPAS 风险量表:证明准确性、公平性和预测性”,2016 年 7 月 8 日。【在线】。可用:https://www . document cloud . org/documents/2998391-ProPublica-commentation-Final-070616 . html .
[8] J. Angwin 和 J. Larson,“ProPublica 回应公司对机器偏见故事的批评”,2016 年 7 月 29 日。【在线】。可用:https://www . propublica . org/article/propublica-responses-to-companies-critical-of-machine-bias-story。
[9] J. Angwin 和 J. Larson,“研究人员说,犯罪风险得分的偏差在数学上是不可避免的”,2016 年 12 月 30 日。【在线】。可用:https://www . propublica . org/article/bias-in-criminal-risk-scores-is-mathematical-ability-researchers-say。
算法调色板
使用机器学习从图像生成调色板

我最近在做一个项目,在这个项目中,我希望能够比较图像的外观和感觉,这促使我寻找一种使用机器学习来创建调色板的方法。
生成调色板可以被认为是一个伪装的聚类问题。我们希望将一幅图像的所有像素划分成最能代表该图像的 k 个不同的组。

我们可以把我们的图像看作是在 3D 色彩空间中绘制的点的阵列,而不是把我们的图像看作是像素的网格——每个像素都有一个红色、绿色和蓝色的值。红色有一个维度,绿色有一个维度,蓝色有一个维度,在每个维度中,一个点可以位于0和255之间的任何位置。
假设我们希望创建一个由 8 种颜色组成的调色板来代表每张图片。这意味着我们想要找到 8 个能够给出每幅图像的最佳可能表示的聚类或分区。
有许多不同的聚类算法可供选择——每种算法都有自己的优缺点——但是为了这个项目的目的,我尝试了 K-Means 聚类和凝聚聚类。
我从电影只有上帝宽恕(2013) (使用网站 FILMGRAB )中挑选了 5 张样本剧照,因为它有丰富的调色板。

仍然来自只有上帝宽恕(2013) ,由 FILMGRAB 提供,使用 k-means 生成调色板。
上面是一个使用 K-Means 生成的电影静止图像和调色板的例子。正如你所看到的,该算法做了一个相当好的工作,没有太多的超参数调整,使一个很好的代表性调色板。此外,它允许您指定调色板的大小——这是其他一些聚类算法(例如 DBSCAN)所不具备的。
你可以在我的笔记本中看到更多生成调色板的例子。
算法挑战
事实证明,像 K-Means 这样的算法更喜欢高容量的颜色,而不是稀疏但突出的颜色。例如,参见下面的静止图像。

仍然来自《只有上帝宽恕》(2013) ,由 FILMGRAB 提供,使用 k-means 生成调色板。
K-Means 调色板可以很好地近似大多数颜色,但在查看图像时,您可能会期望它包含一些蓝色(如摔倒的拳击手的垫子或短裤上)或红色(如绳子上,或站立的拳击手的手套/服装等)。
回想一下 K-Means 是如何工作的,该算法试图将图像中的颜色划分为 k 组,由颜色空间中的 k 个平均点表示。在这种情况下,图像中没有足够的蓝色或红色被算法提取出来,所以它们被其他类似的、更丰富的颜色洗掉了。
为了解决这个问题,我们可以尝试一些方法。

仍然来自《只有上帝宽恕》(2013) ,由 FILMGRAB 提供,使用 K-Means 和聚合生成的调色板。
上图显示了使用 K-Means 和凝聚聚类生成的调色板。凝聚聚类选择在调色板中包括蓝色,尽管它失去了柔和的黄色,仍然没有包括任何红色。

仍然来自Only God forgible(2013),由 FILMGRAB 提供,带有 k-means RGB 和 HSV 生成的调色板。
另一种方法是将图像的颜色从RGB转换为HSV。RGB将颜色表示为红色、绿色和蓝色通道强度的组合,而HSV将颜色表示为色调(基色的光谱)、饱和度(颜色的强度)和值(颜色的相对亮度或暗度)——你可以在这里了解更多关于的信息。上图显示了使用 K-Means 聚类和RGB颜色和HSV颜色为同一幅图像生成的调色板。正如你所看到的,HSV 方法包括蓝色和黄色(尽管仍然没有红色)。
为了进一步改善结果,一些选项包括组合技术(即凝聚聚类+ HSV 颜色),超参数调整,使用不同的算法(如 DBSCAN),以及调整颜色距离度量(如果你感兴趣,可以在这里阅读更多关于颜色差异的信息)。
烧瓶应用程序
作为最后的奖励,我决定创建一个简单的概念验证 API,用于从图像生成调色板。API 将图像 URL 作为参数,并使用 K-Means 生成调色板。
此外,我发现网站 Coolors 使得创建调色板 URL 变得很容易,因此 API 可以将调色板作为颜色的 2D 数组或 Coolors 调色板的 URL 返回。
例如,使用此图像…

还是出自只有上帝会原谅(2013) ,承蒙 FILMGRAB
API 将产生以下链接…
在 Coolors.co 上查看和编辑调色板或创建自己的配色方案。
coolors.co](https://coolors.co/3c030b-050002-3967cd-152f63-760102-7e504c-110c33-b4d1df)
一起看,你会得到…

仍然来自《只有上帝宽恕》(2013) ,由 FILMGRAB 提供,k-means 生成调色板由 Coolors 提供。
你可以在我的 GitHub repo 里查看 Flask app,这里。
结论
这是一个很短但很有趣的副业,这里肯定还有很多值得探索的地方。如果你认为你可能会感兴趣,一定要去看看电影抓取和酷人。
你可以在 GitHub 上找到我的代码,或者用 nbviewer 或 Binder 查看笔记本。
感谢阅读!我很想听听你的想法。请在下面发表评论,或者在 LinkedIn 或 Twitter 上联系我。
算法复杂性
真实网络中的社区发现算法

扎卡里的空手道俱乐部网络与 2 个社区确定。
由于真实网络的规模,使用强力算法来定义社区有时是不可行的。用于处理这些问题的算法,在最好的情况下,在多项式时间内运行。虽然,大多数时候,有必要探索随着网络规模增长的指数数量的可能性。第一个问题叫做 P 问题,第二个问题叫做 NP 问题。
在接下来的章节中,我们将探究 P = NP 的问题,并大致介绍这种证实或反驳的后果。之后,介绍了一个根据算法的速度和内存需求来描述算法复杂性的系统——Big-O 符号。
p 对 NP 问题
P vs NP 问题由 Stephen Cook [1]于 1971 年提出,并在 2000 年被认为是计算机科学中最重要的公开问题之一[2]。这是克莱数学研究所定义的七个千年奖问题[3]中的六个问题之一。能够解决其中一个问题的人将获得 100 万美元的奖金。 P vs NP 问题可以表述为:每一个其解可以被计算机快速验证的问题是否也可以被计算机快速求解?【4】。
P 问题的特征在于可通过确定性图灵机(DTM)在多项式时间内求解。另一方面, NP 范畴包括那些仅使用非确定性图灵机(NTM)在多项式时间内可解的。它们都是一组二元决策问题的一部分。DTM 是一台没有分支的机器,每次只能进行下一步。这是一台普通电脑的工作原理。NTM 是一台概念性的机器,能够在每一步同时分析多项式数量的不同选项。因此,一个分支装置。一个快速验证的解意味着它可以在多项式时间内找到。计算机这个词指的是决定性的图灵机(DTM)。
虽然 P = NP 这个问题还没有答案,但是根据定义,这两个组之间存在联系。 NP 问题包括那些在 DTM 中其解可能无法得到但可以在多项式时间内验证的问题。这意味着每一个 P 问题都属于 NP 问题,验证一个解决方案总是比找到它容易。他们可以在多项式时间内找到它。平凡地,𝑃 ⊂ 𝑁𝑃.
一类不同的问题是 NP 完全问题。不仅是 NP,也是 NP 难(图 1)。当一个属于 NP 的算法可以化简为第一类中的另一个算法时,问题就是 NP 难的。这意味着 NP-hard 类中的任何问题至少和 NP 中的任何问题一样难解决。简化项意味着问题𝐴的输入可以使用多项式时间算法转换为问题𝐵的输入,并提供完全相同的输出。如果𝐴被简化为𝐵,这将会带来几个直接的后果:
- If𝐵∈𝑃,然后是𝐴∈𝑃;
- If𝐵∈𝑁𝑃,然后是𝐴∈𝑁𝑃;
- 如果𝐴是 NP 难的,那么𝐵就是 NP 难的。
因此,如果找到了 NP 完全问题的多项式时间的解,那么 P 对 NP 问题被解决,并且𝑃 = 𝑁𝑃.因此,不仅找到多项式解,而且证明𝑋问题是 NP 完全的也是基本的。根据上述定义,这可以分为两个步骤:
- 显示𝑋属于 NP。这可以通过在多项式时间内验证给定的解或找到𝑋的非确定性算法来完成;
- 展示𝑋是 NP 难的。通过将一个已知的 NP 完全问题简化为𝑋.问题在这种情况下,上面得到的第三个结果意味着𝑋是 NP 难的。

图 1 P vs NP 问题图示表示[5]。
尽管没有得到证实,但大多数计算机科学家𝑃 ≠ 𝑁𝑃相信这一点[6]。证明𝑃 = 𝑁𝑃将在现实世界中产生重要的影响。不仅生物模型将得到加强,而且运输系统、多媒体处理、经济模拟等方面的效率也将大大提高。另一方面,有基于𝑃 ≠ 𝑁𝑃.事实的真实系统其中之一是现代密码系统,它依靠质因数分解来保护数据。这个问题被认为是 NP 。
网络科学中很大一部分问题是 NP、NP 难或 NP 完全的。因此,该解决方案在例如寻找系统发育网络中的社区中的重要性就不足为奇了。
接下来给出算法时间/存储器复杂性的数学表示。
大 O 符号
在分析算法性能时,通常会考虑时间和内存的复杂性。当计算能力有限,需要进行大数据分析时,它们尤为重要。
在某些情况下,同一问题的解决方案可以在不同的时间范围内找到。出于这个原因,重要的是要有一种方法来上限绑定算法的执行时间,而且要估计它的平均值。这导致了 Big-O 符号的产生。
根据算法必须执行的指令数量和输入的大小,运行时间会有所不同。Big-O 符号提供了一种量化算法执行需求的方法,独立于运行它的机器。确定的复杂度可以是线性的、对数的、二次的、三次的、指数的…表 1 给出了一个有序的列表,按照最常见算法的执行时间(有一些例子)。

表 1 一些最知名的算法方法的时间复杂度。
在确定了算法的复杂性之后,就有可能预测执行该算法的机器的时间和内存需求。
定义
一个函数𝑓(𝑁)称为𝑂(𝑔(𝑁))如果常数𝑘和𝑁0 存在,使得 0 ≤ 𝑓(𝑁) ≤ 𝑘 × 𝑔(𝑁)对于全𝑁≥𝑁0 [12]。
参考
[1] S. A. Cook,“定理证明程序的复杂性”,第三届 ACM 计算理论年会论文集(STOC'71) ,1971 年。
[2] L. Fortnow,“P 与 NP 问题的现状”,《美国计算机学会通讯》,,第 52 卷,第 9 期,第 78–86 页,2009 年。
[3] C. M .研究所,“P 对 NP 问题”,[在线]。可用:https://www.claymath.org/millennium-problems/p-vs-NP-问题。[访问日期:2019 年 5 月 15 日]。
[4] N. Viswarupan,“P vs NP 问题”,Medium,2017 年 8 月 17 日。【在线】。可用:https://medium.com/@niruhan/p-vs-np-problem-8d2b6fc2b697.【2019 年 5 月 15 日获取】。
[5]“P 对 NP 问题”,维基百科,[在线]。可用:https://en.wikipedia.org/wiki/P_versus_NP_problem.【2019 年 5 月 12 日访问】。
[6] J. Rosenberger,“P 与 NP 民意测验结果”,《美国计算机学会通讯》,第 55 卷,第 5 期,第 10 页,2012 年。
[7] E. Ravasz,A. L. Somera,D. A. Mongru,Z. N. Oltvai 和 A. L. Barabá si,“代谢网络中模块化的层次组织”,《科学》,第 297 卷,第 5586 期,第 1551-1555 页,2002 年。
[8] M. E.J .纽曼和 m .格文,“发现和评估网络中的社区结构”,《物理评论》。统计、非线性和软物质物理学,第 69 卷,2004 年。
[9] M .格文和 M. E. J .纽曼,“社会和生物网络中的社区结构”,美国国家科学院学报,第 99 卷,第 12 期,第 7821-7826 页,2002 年。
[10] M. E. J. Newman,“检测网络中社团结构的快速算法”,物理评论 E,2004 年第 69 卷第 6 期。
[11] G. Palla,I. Deré nyi,I .法卡什和 T. Vicsek,“揭示自然和社会中复杂网络的重叠社区结构”,《自然》,第 435 卷,第 814-818 页,2005 年。
[12] T. H. Cormen,C. E. Leiserson,R. L. Rivest 和 C. Stein,《算法导论》,麻省剑桥:麻省理工学院出版社,2003 年。
算法投资组合对冲
动态套期保值的 Python 和 Black-Scholes 定价

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
期权投资组合
直接暴露于特殊和系统风险的股票。另一方面,期权不仅暴露于标的资产,还暴露于利率、时间和波动性。这些风险是布莱克-斯科尔斯期权定价模型的输入(参见推导布莱克-斯科尔斯模型)。由于这些输入会影响所讨论的期权的价值,函数的偏导数可以告诉我们,当其中一个风险敞口发生变化,而其他风险敞口保持不变时,期权的价值会如何变化。让我们首先讨论这个期权定价模型的所有偏导数,然后用 Python 编写一个算法对冲系统。
希腊人
使用泰勒级数展开,我们可以得到所有的希腊人。希腊人告诉我们,当一个或多个期权敞口发生变化时,我们可以预期一个期权或期权组合会发生变化。需要注意的是,所有一阶近似都是线性的,而期权定价函数是非线性的。这意味着基础参数偏离初始偏导数计算越多,它就越不精确。这就是为什么希腊人通常是实时更新的,所以当某事发生变化时,我们可以不断地对期权或投资组合价值有一套新的预期(更多信息请参见 Python 中的期权希腊人)。
注意:在以下情景中,我们通常会考虑看涨和看跌期权,一些更高级的价差可能是多头或空头,具有不同的敞口平价。
三角洲
Black-Scholes 方程的基础资产的一阶偏导数称为 delta。Delta 是指当基础资产价格发生变化时,期权价值如何变化。在其他参数保持不变的情况下,将 delta 乘以标的资产的+/-1 美元的变化,将得到期权的新价值。对于多头买入和空头卖出头寸,Delta 为正值,对于空头买入和多头卖出头寸,Delta 为负值。
微克
Black-Scholes 方程的基础资产的二阶偏导数称为 gamma。Gamma 是指当基础资产价格发生变化时,期权的 delta 如何变化。将 gamma 乘以标的资产的+/-1 美元变化,保持所有其他参数不变,将得到期权 delta 的新值。本质上,gamma 告诉我们 delta 的变化率,给定基础资产价格的+-1 变化。对于多头头寸,Gamma 始终为正,对于空头头寸,Gamma 始终为负。
低湿平原
Black-Scholes 方程的基础资产波动率的一阶偏导数称为 vega。Vega 是指当标的资产波动率发生变化时,期权价值如何变化。将 vega 乘以标的资产波动率的+-1%的变化,保持所有其他参数不变,将得到期权的新价值。 Vega 对多头头寸为正,对空头头寸为负。
希腊字母的第八字
Black-Scholes 方程中期权到期前时间的一阶偏导数称为θ。θ是指期权价值如何改变久而久之。一般按年计算,theta 指的是一个期权在一天过去后的价值变化。对于空头头寸,θ为正,对于多头头寸,θ为负。
希腊字母的第 17 字
Black-Scholes 方程关于无风险利率的一阶偏导数称为 rho。Rho 是指期权价值随着利率的变化而如何变化。将ρ乘以利率的+-1%的变化,保持所有其他参数不变,将得到期权的新价值。 Rho 对于多头买入和空头卖出头寸为正,对于空头买入和多头卖出头寸为负。
动态对冲
考虑以下情况:
一位同事目前持有 1000 份 NVDA 看涨期权的空头头寸,她希望对冲波动率、标的资产的变动以及标的资产的变动速度的风险。你在风险管理台上,提议构建一个动态对冲,每天进行再平衡(稍后会有更多)。我们怎样才能中和她对织女星,德尔塔和伽玛的暴露?
我们可以利用线性代数的第一周来帮助我们构建一个解决方案。
首先要意识到的是,为了中和对希腊的风险敞口,我们需要在其他期权中建立抵消头寸。有三个希腊人要中和,所以我们需要三个期权来创建三个希腊人和带有三个未知数的权重(其他可交易期权中的权重)的方程。然而,这里的技巧是认识到基础资产对自身的偏导数只是 1,这意味着基础资产的 delta 是 1,而所有其他希腊值都是 0。这意味着我们可以构建两个可交易期权的投资组合,找到适当的权重来中和希腊人,然后在基础资产中建立抵消头寸——有效地中和对所有三个希腊人的敞口。
用于动态对冲的 Python
考虑以下模拟欧式看涨和看跌期权的代码…
对于上述情况,请考虑以下条件…
- 短 1000 NVDA 来电 @ 545
- NVDA 价格 $543
- NVDA 隐含波动率 53% (参见什么是隐含波动率?)
- 期权到期前 1 个月
- 30 天伦敦银行同业拆放利率 1.5%
使用这些输入,我们可以找到我们同事的期权头寸的理论价值…
32264.05329034736
这意味着我们的同事将因出售期权而获得 32264.05 美元的溢价。
希腊人呢?为了找到我们的同事在希腊语中的位置,我们可以把它们打印出来,然后乘以位置…
-523.8788365375873
-6.3495209433350475
-815.5392717775394
这意味着净投资组合 delta、gamma 和 vega 是…
- 增量: -523.88
- 伽马: -6.35
- 织女星: -815.54
现在让我们考虑另外两个可交易的看涨期权,所有其他参数都相同,但两个执行价格分别是 550 和 555 …
0.49991533666729754
0.006059078318647928
0.7782345099310374
0.47616874797224407
0.005771264702719988
0.741267420785845
调用选项 A:
- 增量: 0.49991
- 伽玛: 0.00605
- 织女星: 0.77823
调用选项 B:
- 增量: 0.47616
- 伽玛: 0.00577
- 织女星: 0.74126
基础资产(NVDA 股票):
- △:1
- 伽玛: 0
- 织女星: 0
使用这些资产的组合,我们可以中和我们的投资组合对 delta、gamma 和 vega 的风险敞口。问题是怎么做?答案:线性代数。
希腊中性化
我们有兴趣中和当前投资组合中的希腊人可以表示为一个向量…

目标是找到我们能够交易的三种资产的权重,以抵消这些价值。首先,我们将设法压制 gamma 和 vega,然后使用底层资产压制 delta…

这意味着通过对包含可交易期权希腊价值的矩阵求逆,我们可以找到合适的权重…

我们可以使用 Python 来做到这一点…
注意:虽然我们在原始选项中有一个短位置,但我们乘以一个正 1000,因为我们想将矩阵反转为正伽玛,织女星位置
[[-1850\. 25.]
[ 1950\. -25.]]
我们已经有效地找到了矩阵的逆矩阵,点积将是两个可交易期权的最终权重…
[[ 8641.86804927]
[-8006.91595494]]
利用这些重量,我们将有效地中和伽马射线和织女星的辐射…
[[ 0.]
[-0.]]
现在伽马射线和织女星的辐射被中和了我们需要中和新的德尔塔的辐射。为了找到我们的新敞口,我们取我们投资组合中所有期权头寸与其各自 deltas 的和积…
[[-46.]
[ 0.]
[ -0.]]
在我们的新期权头寸乘以原始希腊头寸后,我们发现我们的净 delta 头寸是-46。这意味着通过购买基础资产(NVDA)的 46 股,我们将拥有 delta、gamma 和 vega 中性投资组合。这意味着当基础资产价格、基础资产波动性或基础资产价格变化速度发生变化时,我们的期权组合的价值不会改变。这里列出的代码可以直接在一个实时交易系统中实现(参见算法交易系统开发或Python 算法交易)
最终 Delta、Gamma 和 Vega 中性投资组合
- -1000 个 NVDA 电话
- 8641 调用 A 选项
- -8006 调用 B 选项
- 46 股 NVDA 股票
下一步是什么?
看看我的其他文章,了解更多关于期权、理论定价和波动交易的知识…
MACD 和 Python 的算法交易
有了 MACD 十字战略

Photo by 贝莉儿 DANIST on Unsplash
机器学习交易对于每天进行数千笔交易的大型对冲基金来说效果很好。然而,私人交易者只是没有实时运行具有数百万参数的机器学习模型的设施。这就是为什么私人算法交易者使用技术指标进行自动交易。
什么是 MACD?
我今天要用的技术指标是 MACD,移动平均线收敛发散,这是一个动量指标,显示了两条移动平均线之间的关系。MACD 的计算方法是从 12 期均线中减去 26 期均线。
这条 MACD 线画在信号线上(9 周期均线)。这两条线的交点就是 MACD 指标的信号。如果 MACD 指标从下方与信号线交叉,这将是上升趋势。如果 MACD 指标从信号线上方交叉,这将是一个下降趋势。
概念:
为了在编程时有效率,为了心中有一个明确的目标,有必要创建一个关于程序应该如何工作的总体想法。这个程序应该能够绘制 MACD 信号和 MACD 线,并根据 MACD 指标的信号进行交易。一个好的程序还应该能够评估交易策略的盈利能力,从而对其进行优化。
代码:
import yfinance
import talib
from matplotlib import pyplot as plt
这些是我将在程序中使用的库。yfinance 用于下载股票的财务数据,talib 用于计算 MACD 指标的值。Matplotlib 用于绘制数据,以更好地理解技术指标。
data = yfinance.download('NFLX','2016-1-1','2020-1-1')
data["macd"], data["macd_signal"], data["macd_hist"] = talib.MACD(data['Close'])
fig = plt.figure()
这个脚本下载数据,然后计算 macd 值,比如信号和定义趋势的直方图。

作者图片
这是 MACD 指示器和信号线两条线的图形。这只是对程序进行故障排除,以确保指示器正常工作。正如我们所看到的,该指标显然是有效的,因为两条线经常相交。
def intersection(lst_1,lst_2):
intersections = []
insights = []
if len(lst_1) > len(lst_2):
settle = len(lst_2)
else:
settle = len(lst_1)
for i in range(settle-1):
if (lst_1[i+1] < lst_2[i+1]) != (lst_1[i] < lst_2[i]):
if ((lst_1[i+1] < lst_2[i+1]),(lst_1[i] < lst_2[i])) == (True,False):
insights.append('buy')
else:
insights.append('sell')
intersections.append(i)
return intersections,insightsintersections,insights = intersection(data["macd_signal"],data["macd"])
交集函数使用一种非常规的方式来寻找交集:
- 如果列表 1 中的值大于列表 2 中相同索引的值,则存储 True。否则,存储 False。
- 将此函数应用于大于 1 的索引。如果存储的值不同,则一定发生了交集。
这是计算相交的唯一方法,因为相交可能发生在真实点之间,使得不可能在两个列表中找到相似的点。
我们使用这个函数来寻找交叉点,并记下程序是卖还是买股票。
要做好一个股票交易程序,我们必须评估程序的盈利能力。
profit = 0
pat = 1
for i in range(len(intersections)-pat):
index = intersections[i]
true_trade= None
if data['Close'][index] < data['Close'][index+pat]:
true_trade = 'buy'
elif data['Close'][index] > data['Close'][index+pat]:
true_trade = 'sell'
if true_trade != None:
if insights[i] == true_trade:
profit += abs(data['Close'][index]-data['Close'][index+1])
if insights[i] != true_trade:
profit += -abs(data['Close'][index]-data['Close'][index+1])
这个程序通过计算 true_trade 来计算盈利能力,true _ trade 存储值是上升还是下降。如果交易符合真实交易变量,交易就是盈利的。如果交易不匹配,交易就会失败。
运行程序时,利润为-288.26。什么?
发生了什么事?
我发现了这个错误,并一直试图扰乱耐心值,也就是交叉点形成后多久,交易就完成了。所有的值都是负数。当面对这样的问题时,其中值的极性都是错误的,人们可以很容易地改变极性。
在这种情况下,这是因为交集顺序不正确!当我们做交叉点时,我们做了与我们描述的策略相反的洞察!例如,如果 MACD 线从上方相交,程序会将其标记为价格上涨!这将使所有被认为是有利可图的交易变成亏损!
通过将交叉点代码更改为:
def intersection(lst_1,lst_2):
intersections = []
insights = []
if len(lst_1) > len(lst_2):
settle = len(lst_2)
else:
settle = len(lst_1)
for i in range(settle-1):
if (lst_1[i+1] < lst_2[i+1]) != (lst_1[i] < lst_2[i]):
if ((lst_1[i+1] < lst_2[i+1]),(lst_1[i] < lst_2[i])) == (True,False):
insights.append('buy')
else:
insights.append('sell')
intersections.append(i)
return intersections,insightsintersections,insights = intersection(data["macd_signal"],data["macd"])
我们获得 298 美元的利润!
结论:
我写了另一篇关于 RSI 的文章,那个程序用同样的数据只赚了 58 美元。这个项目赚了 298 美元,每笔交易买一股。这里有一些方法可以改进我的程序:
- 调整耐心变量
这个变量是相交后多长时间,将进行交易。用这个值做玩具,找到一个模式,并优化它以获得更好的结果。
2.找到最好的份额
这个算法对哪只股票最有效?在不同的公司上测试这个程序以进行评估。
我的链接:
如果你想看更多我的内容,点击这个 链接 。
用 Python 进行算法交易
为期货市场建立一个算法交易系统

定量发展
Python 已经迅速成为数据科学、机器学习和人工智能领域最强大的计算语言之一。在用 Java 写了一本关于算法交易系统开发的指南之后,我觉得是时候为 Python 写一本了;尤其是考虑到 Interactive Broker 新支持的 Python API。本文是一个 API 指南,通过定期参考我自己的实现和官方文档,帮助您入门和运行。
装置
假设您已经正确安装了 Python 并建立了适当的环境变量,要安装交互式代理的 Python API,您可以在命令行中调用 pip 包管理器。
pip install ibapi
这将把 ibapi 包安装到 Python 的默认版本中。如果你有多个版本的 Python(甚至可能是 Python2),你可能想安装 Python3 的包。
pip3 install ibapi
需要特别注意的是,如果您成功安装了软件包,但仍然出现 ModuleNotFound 错误,那么您很可能是在使用安装了 API 的不同 Python 版本运行 Python 脚本。如果你想下载源代码,或者看看 Java、C++和其他语言的 API 实现,你可以在这里下载:【https://www.interactivebrokers.com/en/index.php?f=5041。
接下来,我们需要一个网关来发出请求和接收来自交互代理的数据,我称之为服务器。从上面的链接(页面底部)下载 IB 网关,当你登录时,你会看到一个类似这样的界面…

导航到配置→设置→ API →设置,您可以配置您的 API 设置(主机、端口、只读等)。

连通性
在成功安装了交互式代理的 Python API 之后,就到了实现的时候了。直观上,这个 API 可以分为两个通信通道,一个从服务器读取,另一个向服务器写入…
EClient
EClient 类负责向服务器发送请求。这些请求被保存在一个队列中,直到这个队列被 run() 函数清除。该类将 EWrapper 作为参数,因为该 EWrapper 的实例是服务器用回调进行响应的地方。
新闻记者
EWrapper 类负责在回调函数中接收数据。
多线程操作
要构建一个算法交易系统,多个进程必须同时发生,这就是为什么我们必须将 EClient 持久化在它自己的线程上,这样读写就可以异步发生。如果你想了解更多关于多线程的知识,我写了一个快速入门指南,介绍如何用 Python 为金融开发多线程。
TradingApp 主类
要创建读写服务器的能力,需要创建 EClient 和 EWrapper 的两个子类。我将把 EWrapper 子类声明为 APIController,把 EClient 声明为 APISocket。主类将成为这两个实现的子类。
让我们分析一下这是怎么回事。正如我之前所说,EClient 类负责向服务器发出请求,而服务器则响应 EWrapper 类。通过创建 APISocket 和 APIController 子类,我们可以覆盖超类函数并编写自定义实现。在这个例子中,您可以看到 APIController 有两个回调,一个用于错误,一个用于连接。服务器只会调用@iswrapper 函数来响应对服务器的请求。为了在 main 类中发出连接请求,我们引用 self(API socket)并用 host、port 和 clientId 参数调用 connect。这将请求放在 EClient 队列中,但是正如我所说的,要构建一个算法系统,必须有并发读写的能力,所以我们将支持在请求队列自己的线程上清除请求队列(通过发出请求)。在运行 TradingApp 类的一个实例后,您将得到一个成功连接到服务器的消息,这个连接在 EClient 线程的生命周期中是持久的。
成功建立连接后,您将可以通过各种请求的形式访问来自服务器的所有类型的数据,在他们的文档中可以找到请求的完整列表。
流式市场数据
如果你对实时市场数据感兴趣,你需要购买一份市场数据订阅服务,最低账户金额为 2000 美元。
创建合同
合约是告诉服务器我们对什么工具感兴趣的交易/流/分析的类。输入参数非常简单,只引用感兴趣的特定证券。我一直在交易 E-mini NASDAQ-100,并将在这个例子中使用它。
# Create a new contract object for the E-mini NASDAQ-100
contract = Contract()
contract.symbol = "NQ"
contract.localSymbol = "NQM0"
contract.secType = "FUT"
contract.exchange = "GLOBEX"
contract.currency = "USD"
请求数据
要请求数据流,只需将请求放在连接请求下。
self.connect('127.0.0.1', 4002, 1)
self.reqMktData(1001, contract, "", False, False, [])
接收数据
要从服务器接收数据,请向 APIController 添加 tickPrice 和 tickSize 回调函数。
[@iswrapper](http://twitter.com/iswrapper)
def tickPrice(self, reqId, tickType, price, attrib):
super().tickPrice(reqId, tickType, price, attrib)
# Do something with trading price[@iswrapper](http://twitter.com/iswrapper)
def tickSize(self, reqId, tickType, size):
super().tickSize(reqId, tickType, size)
# Do something with trading volume
来自回调的请求
对实时数据流执行分析相对简单,因为数据可以间隔存储在数据缓存中,也可以内部存储在 APIController 中。然而,从回调函数发出服务器请求有点复杂,我想提供一个创造性的解决方案。
用 EClient 和 Contract 参数创建一个名为 signal 的新类(我用它在回调函数中下订单,但其他请求也可以),允许主类作为 EClient 作为 Signal 类的参数。那么这个 signal 类就是 APIController 的一个新参数,这样控制器就可以直接引用 self.signal.FUNCTION_IN_signal 或者 self . SIGNAL . e client . server _ REQUEST,分别在 SIGNAL 类或者 direct requests 中进行定制请求实现。
想要现场解说?
我制作了一个视频指南,进一步分解了交互式经纪人 API。
使用 Python 的 RSI 算法交易
使用 talib 和 yfinance

美国宇航局在 Unsplash 拍摄的照片
机器学习是计算密集型的,因为算法是不确定的,因此必须随着时间的推移不断调整。然而,技术指标要快得多,因为等式不会改变。因此,这提高了它们用于实时交易的能力。
这里是 github 回购(广告)。
什么是 RSI?
要创建一个使用 RSI 的程序,首先要了解 RSI 指标。RSI 是相对强度指数的缩写。它是一个动量指标,使用价格变化的幅度来评估证券是超买还是超卖。
如果 RSI 值超过 70,则认为该证券超买,如果低于 30,则认为超卖。超买是指由购买产生的泡沫可能很快破裂,因此价格会下跌。这创造了一个强有力的切入点。
然而,好的做法是,只有当 RSI 值与超买线相交时,才卖出订单,因为这是一种更保守的方法。至少可以猜测 RSI 何时会达到最高点。
概念:
这个程序试图使用 talib(技术分析)库来实现 RSI 线和超卖超买线的交叉。该程序的大部分不是来自于对指标的编程(因为它已经在库中创建了),而是如何使用超卖和超买区域进行交易的实现。
代码:
import yfinance
import talib
from matplotlib import pyplot as plt
这些是该计划的先决条件。Yfinance 用于下载股票数据,talib 用于计算指标值。Matplotlib 当然是将数据绘制成图形。
data = yfinance.download('NFLX','2016-1-1','2020-1-1')
rsi = talib.RSI(data["Close"])
该脚本访问数据,并根据以下两个等式计算 rsi 值:
RSI step 1= 100[100/(1+平均损耗/平均增益)]
RSI step 2= 100[100/(1+平均平均损耗÷13+当前损耗/先前平均增益÷13+当前增益)]
fig = plt.figure()
fig.set_size_inches((25, 18))
ax_rsi = fig.add_axes((0, 0.24, 1, 0.2))
ax_rsi.plot(data.index, [70] * len(data.index), label="overbought")
ax_rsi.plot(data.index, [30] * len(data.index), label="oversold")
ax_rsi.plot(data.index, rsi, label="rsi")
ax_rsi.plot(data["Close"])
ax_rsi.legend()
该图显示了所有的超买和超卖区域,以及为股票收盘价计算的 RSI 值。这给了股票数据一个很好的可视化

作者图片
这是合成图。随着时间的推移,我们可以看到 RSI 值在不同部分之间波动。RSI 的好处在于它是相对的。这意味着信号的强度与实际值无关,而是与过去值的关系有关。
缺少的步骤:
通常,文章到此为止。他们在给出股票交易程序的初步代码后结束。有必要更进一步,真正评估股票交易程序,基于程序的盈利能力。这就是为什么我要交程序。
section = None
sections = []
for i in range(len(rsi)):
if rsi[i] < 30:
section = 'oversold'
elif rsi[i] > 70:
section = 'overbought'
else:
section = None
sections.append(section)
这个脚本记录了每个点所在的部分。它要么在超买,超卖或无区域,这是指在两条线之间。
trades = []
for i in range(1,len(sections)):
trade = None
if sections[i-1] == 'oversold' and sections[i] == None:
trade = True
if sections[i-1] == 'overbought' and sections[i] == None:
trade = False
trades.append(trade)
这个脚本整合了 RSI 交易的基本策略。交易策略是当价值离开超买和超卖部分时,进行适当的交易。例如,如果它离开超卖区,就进行买入交易。如果它离开了超买区,就进行卖出交易。
acp = data['Close'][len(data['Close'])-len(trades):].values
profit = 0
qty = 10
for i in range(len(acp)-1):
true_trade = None
if acp[i] < acp[i+1]:
true_trade = True
elif acp[i] > acp[i+1]:
true_trade = False
if trades[i] == true_trade:
profit += abs(acp[i+1] - acp[i]) * qty
elif trades[i] != true_trade:
profit += -abs(acp[i+1] - acp[i]) * qty
这个脚本使用程序进行的交易来计算每笔交易的利润或损失。这给出了程序的最佳评价,因为它准确地锁定了要寻找的变量。qty 变量计算购买了多少股票。
运行程序后,计算的利润为:
Profit : $58.3
结论:
事实上,当考虑到风险回报比时,58.3 美元的利润实际上不是一个很好的投资。有很多方法可以改进我的程序:
- 调整耐心变量
这个变量是在 RSI 值之后多久,将进行交易。用这个值做玩具,找到一个模式,并优化它以获得更好的结果。
2.找到最好的公司
这个算法对哪只股票最有效?在不同的公司上测试这个程序以进行评估。
我的链接:
如果你想看更多我的内容,点击这个 链接 。
算法是不够的
意见
人工智能的下一个突破需要重新思考我们的硬件

现在的 AI 有一个问题:贵。训练 Resnet-152,一个现代计算机视觉模型,估计花费大约 100 亿次浮点运算,这与现代语言模型相比相形见绌。OpenAI 最近的自然语言模型 GPT-3 的训练预计将花费 3000 亿万亿次浮点运算,这在商用 GPU 上至少需要 500 万美元。相比之下,人脑可以识别人脸,回答问题,驾驶汽车,只需一根香蕉和一杯咖啡。
我们是怎么到这里的?
我们已经走了很长一段路。第一台计算机是专用机器。1822 年,英国数学家查尔斯·巴贝奇创造了“差分机”,它的唯一目的是计算多项式函数。1958 年,康奈尔大学教授弗兰克·罗森布拉特(Frank Rosenblatt)创造了“Mark I”,这是一种用于机器视觉任务的单层感知机的物理化身。在早期,硬件和算法是一回事。
随着冯诺依曼架构的引入,硬件和算法的统一性发生了变化,这是一种由用于计算的处理单元和用于存储数据和程序指令的存储单元组成的芯片设计。这种范式转变使得制造通用机器成为可能,这些机器可以被编程来完成任何期望的任务。冯-诺依曼体系结构已经成为现代数字计算机的蓝图。
但是,有一个条件。数据密集型程序需要内存和计算单元之间的大量通信,从而降低了计算速度。这种“冯-诺依曼瓶颈”是人工智能早期尝试失败的原因。标准 CPU 在大型矩阵乘法(深度神经网络中的核心计算操作)方面效率低下。由于现有硬件的瓶颈,早期的神经网络太浅,性能不佳。
这个问题的解决方案不是来自学术界,而是来自游戏行业,这是历史的讽刺之一。GPU 是 20 世纪 70 年代为加速视频游戏而开发的,它通过数千个计算核心并行处理数据密集型操作。这种并行性是解决冯-诺依曼瓶颈的有效方法。GPU 能够训练更深层次的神经网络,并已成为现代人工智能的现状硬件。

Riho Kroll 在 Unsplash 上拍摄的照片
硬件彩票
人工智能的研究有一点纯粹的运气成分。谷歌研究员萨拉·胡克称之为“硬件彩票”:早期的人工智能研究人员只是运气不好,因为他们被缓慢的 CPU 卡住了。在 GPU 出现的时候,恰好在该领域的研究人员“赢得”了硬件彩票。他们可以通过训练由高效 GPU 加速提供动力的深度神经网络来取得快速进展。
硬件彩票的问题是,一旦这个领域作为一个整体确定了赢家,就很难探索新的东西。硬件开发速度缓慢,而且需要芯片制造商在回报不确定的情况下进行大量前期投资。一个安全的赌注是简单地优化矩阵乘法,这已经成为现状。但从长远来看,这种对硬件和算法的特定组合的关注会限制我们的选择。
让我们回到最初的问题。为什么当今的人工智能如此昂贵?答案可能是我们还没有合适的硬件。硬件彩票的存在,加上商业激励,使得经济上很难打破目前的现状。
作为一个例子,考虑杰弗里辛顿的胶囊神经网络,一种计算机视觉的新方法。谷歌研究人员 Paul Barham 和 Michael Isard 发现这种方法在 CPU 上工作得相当好,但在 GPU 和 TPU 上表现不佳。原因?加速器已经针对最频繁的操作进行了优化,例如标准矩阵乘法,但是缺少针对胶囊卷积的优化。他们的结论(这也是他们论文的标题): ML 系统停滞不前。
人工智能研究人员存在“过度适应”现有硬件的风险,从长远来看,这将抑制该领域的创新。
前进的道路
“下一个突破可能需要一种根本不同的方式,用硬件、软件和算法的不同组合来建模世界。”莎拉·胡克,谷歌大脑
在人脑中,记忆和计算不是两个独立的组件,而是发生在同一个地方:神经元。记忆来自神经元通过突触连接在一起的方式,而计算来自神经元放电和传播来自感觉输入的信息的方式。硬件和算法是一回事,很像早期的计算机。这与我们今天做人工智能的方式完全不同。
由 GPU 和 TPU 支持的深度神经网络,即使它们在今天的许多任务中表现得非常好,从长远来看可能不是前进的方向。也许在硬件和算法架构的可能组合的广阔前景中,它们只是局部最优。
前进的道路始于认识到算法是不够的。对于下一代人工智能,我们需要在硬件和算法上进行创新。在 GPU 之前,AI 研究被卡住了。硬件上没有新的突破,就有可能再次卡住。
为了在人工智能方面取得进展,我们的模型需要学会应对混乱的现实世界
towardsdatascience.com](/supervised-learning-is-not-enough-8254814dfcc5) [## 智能行为的起源
为什么真正的人工智能需要的不仅仅是模式识别
towardsdatascience.com](/the-origin-of-intelligent-behavior-3d3f2f659dc2)
源于我们偏见的算法
算法有辨别能力吗?恐怕是的。让问题变得复杂的是,算法开发者很难被指控有恶意。那么,一个数学公式怎么会让个人和社区处于危险之中呢?

马库斯·斯皮斯克在 Unsplash 上的照片
尽管数学方程看起来遥远而冷漠,但它们通常也与可靠的硬科学联系在一起。然而,时不时地,事实证明一系列数字和符号隐藏着更不祥的潜在危险。是什么导致应用程序变坏,而这些应用程序原本是为好的事业服务的?可能有很多原因。首先浮现在脑海中的一个问题与人性有关。众所周知,人们遵循一种熟悉的机制,让刻板印象和偏见指导他们的生活。他们将它们应用于其他个人、社会团体和价值体系。这种认知模式很容易被缺乏想象力和不愿意给予事情适当的考虑所驱动。由此产生的爆炸性混合物会产生负面后果。盲目相信计算机数据的人看不到情况的复杂性,容易放弃对事件的主观评估。一旦发生这种情况,不幸的事情就会发生,给每个相关的人带来巨大的问题。我们的无知和算法越来越大的自主性(事实证明算法远非万无一失)产生了一个令人不安的混合体。
为警察服务的算法
警察非常适合测试智能技术。这种技术有其独特之处,业界非常清楚一个有用的算法有时会引发问题。但是让我们公平一点。智能数据处理允许警方计算机有效地将犯罪、历史数据和环境分组到类别和数据集。毫无疑问,应用程序有助于将地点、人物、心理特征、犯罪时间和使用的工具联系起来。孟菲斯大学的犯罪学家和数据处理学者选择使用 IBM 设计的预测分析软件。该项目团队创建了一个分析机制,该机制考虑了气温、当地地理、人口分布、商店和餐馆的位置、居民偏好和犯罪统计等变量。底层算法使用这些变量来识别城市中的潜在爆发点。它们确实有效。对该系统的测试表明,确实有可能在一定程度上预测未来,尽管没有给出具体的程度。然而,这种确定性足以证明向以这种方式确定的“高风险”地区派遣警察是合理的。还有人声称,这有助于将警方从报告事件那一刻起的反应时间缩短三分之一。我只能想象在这样的地方仅仅有警察在场就能阻止犯罪活动。虽然这个例子对于外行人来说可能难以理解,但它证明了现代技术提供了具有产生惊人结果潜力的“爆炸性”创新。
当计算机出错时
创业公司 Azavea 的 HunchLab 系统已经在美国推出,该系统筛选各种类型的海量数据(包括月相),以帮助警方调查犯罪。和前面的例子一样,这个想法是创建一个犯罪发生概率特别高的地点的地图。该计划的重点是整个城市的酒吧,学校和公共汽车站的位置。事实证明这很有帮助。虽然它的一些发现是显而易见的,但其他发现可能会令人惊讶。很容易解释为什么天气越冷犯罪越少。然而,要找到停在费城学校附近的汽车更容易被偷的原因却相当困难。没有这种软件的警察会想到去调查学校和汽车盗窃之间的联系吗?以上都是正面情景。然而,很难接受的事实是,智能机器不仅在处理过程中出错,而且还会导致错误的解释。通常,他们无法理解情境背景。不是完全不像人。
软件不可靠的可信度
2016 年,联合调查记者的独立新闻编辑室 ProPublica 发表了“机器偏见” 一文,内容是美国法院使用 Northpointe 的专业软件对罪犯进行侧写。文章指出,该软件旨在评估有前科的人再次犯罪的可能性,事实证明该软件很受美国法官的欢迎。Northpointe tool 估计黑人罪犯再次犯罪的可能性为 45%。与此同时,白人再次犯罪的风险为 24%。为了得出这些有趣的结论,算法假设黑人居住区比白人居住区有更高的犯罪行为风险。软件传播的假设受到了质疑,最终结束了 Northpointe 软件套件的分析生涯。问题的根本原因在于仅仅根据历史数据进行评估,以及缺乏认识,或者说未能设计出算法来说明最新的人口趋势。
算法和白脸
凯茜·奥尼尔(Cathy O'Neil)在她 2016 年的著作《数学毁灭的武器》中,探索了一个有趣的假设,即算法极大地影响了人们生活的各个领域。她指出,人们倾向于过于相信数学模型。她声称,这导致了以多种方式和多种层次形成的偏见。她说,偏见很早就产生了,甚至在算法用于分析的数据被收集之前。亚马逊的经理们也发现了同样的机制。他们注意到他们使用的招聘程序经常歧视女性。在寻找有前途的人时,女性总是占少数。是什么导致了偏差?对历史数据的依赖表明有更多的男性申请特定的职位。这破坏了就业中的性别平等,使天平向有利于男性的方向倾斜,最终导致了有偏见的就业政策的制定。
算法没有改变文化
上述评估软件是建立在基于性别的严重不平等困扰就业的时代开发的算法基础上的。那个特定时刻的特点是男性人数过多。在历史数据的基础上训练出来的算法致力于世界没有改变的“信念”。这意味着他们的假设和简化(如黑人意味着更高的犯罪概率,男性更有可能成为优秀的专业人士)是被误导的。
令人不安的问题
如果你认为类似上述的机制在职业和个人生活中可能很普遍,你可能会有所发现。有多少情况是我们不知道的,在这些情况下,数据是根据错误的假设组织起来的?算法未能解释经济和文化变化的频率有多高?
黑匣子是一个术语,用来指人类面对人工智能“大脑”中发生的事情时的无助。我们的无知和算法越来越大的自主性(事实证明算法远非万无一失)产生了一个令人不安的混合体。算法的偏见不会随着魔杖的挥动而消失。因此,关键问题是,他们的开发人员(他们经常自己完成设计和培训工作)是否会承担起这项任务,并意识到人类的偏见和行为模式会多么容易影响软件。
****作品引用:
IBM,孟菲斯警察局,IBM SPSS:孟菲斯警察局,详细 ROI 案例研究, 链接 ,2015。
《边缘》,莫里斯·查马,马克·汉森补充报道,《维持未来》。弗格森事件后,圣路易斯警察采用犯罪预测软件, 链接 ,2018。
ProPublica,机器偏见:全国各地都有用来预测未来罪犯的软件。而且是对黑人的偏见,作者茱莉亚·安格温(Julia Angwin)、杰夫·拉森(Jeff Larson)、苏亚·马特图(Surya Mattu)和劳伦·基什内尔(Lauren Kirchner),ProPublica、 链接 ,2018。
相关文章:
从零开始的算法:决策树

约翰·西门子在 Unsplash 上拍摄的照片
从零开始的算法
从头开始详述和构建决策树模型
熟悉我早期作品的人会记得,我曾经写过一篇关于随机森林算法的概述。决策树的坚实基础是理解随机森林内部工作的先决条件;随机森林构建多个决策树,并输出回归问题中每棵树预测的平均值,在分类问题中,它输出每棵树预测的相对多数。
随机森林的概念概述
towardsdatascience.com](/random-forest-overview-746e7983316)
基于上面的故事,我将更加关注决策树学习算法,因为它是机器学习领域的一个基本算法。许多模型的结构基于决策树模型,如随机森林和梯度提升树。此外,我将从头开始做这个算法的 Python 实现,以进一步扩展我们对算法中发生的事情的直觉。
定义术语
- 参数模型:用于对总体参数进行推断,但是如果所有假设都不满足,这些推断就无效。
- 非参数模型:不假设数据或总体有任何特征结构。
决策树(购物车)
由于其可理解性和简单性而广受欢迎,决策树是最容易可视化和解释的算法之一,在向非技术观众展示结果时非常方便,这是行业中经常需要的。如果我们简单地考虑一棵处于类似流程图状态的树,从根到叶,其中从根到叶的路径定义了关于特征的决策规则,那么我们已经有了理解决策树学习所需的良好的直觉水平。
与我们在从零开始的算法系列中介绍的前两种算法(线性回归和逻辑回归)不同,决策树算法是一种非参数算法,这意味着它不对数据或总体做出假设。这确实对我们的模型有影响,因为我们在训练期间在模型中用偏差换取方差,使得决策树更容易过度拟合。
在机器学习领域,有两种主要的决策树模型。我们使用的方法取决于我们试图预测的目标变量的类型:
C 分类树:用于预测取离散值的目标变量的树模型。因此,叶节点代表一个类,而分支代表导致这些类标签的特征的合取。
R回归树:用于预测取连续值的目标变量的树模型。与分类树相反,在回归树中,每个叶节点包含一个连续值(即房价);分支代表导致每个连续变量的特征的合取。
注:分类和回归树(CART)是指这两个过程的总称,由 Breiman 等人于 1984 年首次提出。
在图 1 的中,我们可以看到 CART 算法遵循的结构。尽管这种结构是为两棵树设置的,但是分类树和回归树之间还是有一些细微的差别,比如每棵树的输出;分类树返回叶节点的模式类别,而回归树返回平均值。

图 1:决策树图表。
这两种算法之间的另一个显著区别是我们在划分特征空间时试图最小化的标准。一般来说,我们希望选择特征 j 和分割点 s ,它们能够最好地将特征空间分割成两个区域,但是如何在回归树和分类树中测量这一点是不同的,如图 2所示。

图 sklearn 中使用的杂质公式。[来源:Stacey Ronaghan——Scikit-learn 和 Spark 中的决策树、随机森林和特性重要性的数学
分块算法
注意:我们将构建一个决策树分类器,以基尼系数作为分割的标准。
- 考虑特征 j 和分割点 s 的所有可能分割
- 找到最佳分割后,将数据分成两个结果区域
- 重复 1 和 2,直到达到停止标准
上面的伪代码演示了计算机科学中称为递归的现象:一种解决问题的方法,其中解决方案取决于同一问题的较小实例的解决方案(来源: Wikipedia ),以及二进制分裂因此在一些示例中,步骤 1-2 被称为递归二进制分裂。
履行
对于此次实施,我们将利用以下框架:
- 线性代数和数据处理
- 熊猫(数据处理)
- Sci-kit 学习(机器学习)
- 图形可视化软件
点击此处查看完整代码…
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/kurtispykes/ml-from-scratch/blob/master/decision_tree.ipynb)
import numpy as np
import pandas as pd
import graphviz
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import export_graphviz
from sklearn.model_selection import train_test_split
我们将使用的数据集是来自 Scikit learn 的虹膜数据集—参见文档
# loading the data set
dataset = load_iris(as_frame=True)
df= pd.DataFrame(data= dataset.data)
# adding the target and target names to dataframe
target_zip= dict(zip(set(dataset.target), dataset.target_names))
df["target"] = dataset.target
df["target_names"] = df["target"].map(target_zip)
print(df.shape)
df.head()(150, 6)

图 3:虹膜数据集(前 5 行)
# Seperating to X and Y
X = df.iloc[:, :4]
y = df.iloc[:, -1]
# splitting training and test
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.75, shuffle=True, random_state=24)dt = DecisionTreeClassifier()
dt.fit(X_train, y_train)DecisionTreeClassifier()dot_data = export_graphviz(dt, out_file=None,
feature_names=X.columns,
class_names=dataset.target_names,
filled=True, rounded=True,
special_characters=True)
graph = graphviz.Source(dot_data)
graph

图 4:经过训练的决策树可视化——上面代码单元的输出。
sklearn_y_preds = dt.predict(X_test)
print(f"Sklearn Implementation:\nACCURACY: {accuracy_score(y_test, sklearn_y_preds)}")Sklearn Implementation:
ACCURACY: 0.9473684210526315
我的实现
我们将需要根据特定分支的决策规则,将我们的数据分为真索引和假索引。如果满足决策规则的条件,我们说该分支为真(我们将表示为left)和假(表示为right)。
划分数据
def partition(data, column, value):
"""
Partition the data into left (indicating True) and right (indicating false).
Inputs
data: The data to partition
Outputs
left: index of values that meet condition
right: index of values that fail to meet the condition
"""
left = data[data[column] <= value].index
right = data[data[column] > value].index
return left, right
为了检查我们的函数是否正常工作,我们将对所有数据执行拆分,并手动将最佳列和值传递给它,以查看我们的数据是否相对于上图进行了分离。
# performing a split on the root node
left_idx, right_idx = partition(X_train, "petal length (cm)", 2.45)
print("[petal length (cm) <= 2.45]")
# print results --> left_idx = 38 setosa | right index = 42 versicolor, 32 virginica
print(f"left_idx: {dict(zip(np.unique(y_train.loc[left_idx], return_counts=True)[0], np.unique(y_train.loc[left_idx], return_counts=True)[1]))}\n\
right_idx: {dict(zip(np.unique(y_train.loc[right_idx], return_counts=True)[0], np.unique(y_train.loc[right_idx], return_counts=True)[1]))}")[petal length (cm) <= 2.45]
left_idx: {'setosa': 38}
right_idx: {'versicolor': 42, 'virginica': 32}
完美!
接下来,我们需要一个我们想要最小化的标准。在这个实现中,我们将使用一个名为gini_impurity的函数来最小化基尼系数。在不触及技术层面的情况下,基尼系数只是简单地衡量了我们的数据在某个节点上的混合程度;为了帮助理解这个概念,想想黄金。当黄金不纯时,它指的是其中其他物质的混合物,然而当它纯时,我们可以说没有杂质(这并不完全正确,因为精炼黄金纯度高达 99.99%,所以技术上仍有一些杂质)。
理想情况是节点是纯的,这意味着目标标签被分成单独的节点。—要深入了解基尼系数杂质的技术细节,请参见此处
基尼杂质
def gini_impurity(label, label_idx):
"""
A measure of how often a randomly chosen element from the set would
be incorrectly labelled if it was randomly labelled according to the
distribution of labels in the subset (Soure: Wikipedia)
Inputs
label: The class label available at current node
Outputs
impurity: The gini impurity of the node
"""
# the unique labels and counts in the data
unique_label, unique_label_count = np.unique(label.loc[label_idx], return_counts=True)
impurity = 1.0
for i in range(len(unique_label)):
p_i = unique_label_count[i] / sum(unique_label_count)
impurity -= p_i ** 2
return impurity
如果你向上滚动回到图 4,你会看到在根节点的杂质是 0.663。因此,为了确定我们的gini_impurity函数是否正常工作,我们应该在输出中看到这个数字
# Gini impurity of the first node
impurity = gini_impurity(y_train, y_train.index)
impurity`0.6626275510204082
太好了!
为了在一个特性(和价值)上分裂,我们需要一种量化的方法,如果我们在那个点上分裂,什么会产生最好的结果。信息增益是量化在每个节点上分割什么特征和特征值的有用方法。对于树的每个节点,信息值“表示在给定实例到达该节点的情况下,指定新实例应该被分类为是还是否所需的预期信息量”。(来源:维基百科)
信息增益
def information_gain(label, left_idx, right_idx, impurity):
"""
For each node of the tree, the information gain "represents the
expected amount of information that would be needed to specify whether
a new instance should be classified yes or no, given that the example
reached that node. (Source: Wikipedia)
Inputs
left: The values that met the conditions of the current node
right: The values that failed to meet the conditions of the current noode
gini_impurity: the uncertainty at the current node
Outputs
info_gain: The information gain at the node
"""
p = float(len(left_idx)) / (len(left_idx) + len(right_idx))
info_gain = impurity - p * gini_impurity(label, left_idx) - (1 - p) * gini_impurity(label, right_idx)
return info_gain
最佳的第一分割是提供最多信息增益的分割。对每个不纯节点重复这个过程,直到树完成。(来源:维基百科)
基于上面的陈述,我们现在可以明白为什么值为 2.45 的花瓣长度(cm)被选为第一个分割。
# testing info gain of the first split at root node
info_gain = information_gain(y_train, left_idx, right_idx, impurity)
info_gain0.33830322669608387# testing a random feature and value to see the information gain
left_idx, right_idx = partition(X_train, "petal width (cm)", 1.65)
impurity = gini_impurity(y_train, y_train.index)
info_gain = information_gain(y_train, left_idx, right_idx, impurity)
info_gain0.25446843371494937
以上助手功能现在要发挥作用了。我们必须手动选择特性和值,对吗?下一个函数现在将自动搜索特征空间,并找到最佳分割数据的特征和特征值。
寻找最佳分割
def find_best_split(df, label, idx):
"""
Splits the data on the best column and value
Input
df: the training data
label: the target label
idx: the index of the data
Output:
best_gain: the max information gain
best_col: the column that produced best information gain
best_val: the value of the column that produced best information gain
"""
best_gain = 0
best_col = None
best_value = None
df = df.loc[idx] # converting training data to pandas dataframe
label_idx = label.loc[idx].index # getting the index of the labels
impurity = gini_impurity(label, label_idx) # determining the impurity at the current node
# go through the columns and store the unique values in each column (no point testing on the same value twice)
for col in df.columns:
unique_values = set(df[col])
# loop thorugh each value and partition the data into true (left_index) and false (right_index)
for value in unique_values:
left_idx, right_idx = partition(df, col, value)
# ignore if the index is empty (meaning there was no features that met the decision rule)
if len(left_idx) == 0 or len(right_idx) == 0:
continue
# determine the info gain at the node
info_gain = information_gain(label, left_idx, right_idx, impurity)
# if the info gain is higher then our current best gain then that becomes the best gain
if info_gain > best_gain:
best_gain, best_col, best_value = info_gain, col, value
return best_gain, best_col, best_valuefind_best_split(X_train, y_train, y_train.index)(0.33830322669608387, 'petal length (cm)', 1.9)
太好了,我们有了算法运行所需的所有组件。然而,上面的函数只对我们的训练数据(树桩/树根)执行一次分割。
附加助手功能
# helper function to count values
def count(label, idx):
"""
Function that counts the unique values
Input
label: target labels
idx: index of rows
Output
dict_label_count: Dictionary of label and counts
"""
unique_label, unique_label_counts = np.unique(label.loc[idx], return_counts=True)
dict_label_count = dict(zip(unique_label, unique_label_counts))
return dict_label_count# check counts at first node to check it aligns with sci-kit learn
count(y_train, y_train.index){'setosa': 38, 'versicolor': 42, 'virginica': 32}
这里有一些类,我们将使用它们来存储决策树中的特定数据并打印我们的树。
# [https://github.com/random-forests/tutorials/blob/master/decision_tree.ipynb](https://github.com/random-forests/tutorials/blob/master/decision_tree.ipynb)class Leaf:
"""
A Leaf node classifies data.
This holds a dictionary of class (e.g., "Apple") -> number of times
it appears in the rows from the training data that reach this leaf.
"""
def __init__(self, label, idx):
self.predictions = count(label, idx)# [https://github.com/random-forests/tutorials/blob/master/decision_tree.ipynb](https://github.com/random-forests/tutorials/blob/master/decision_tree.ipynb)class Decision_Node:
"""
A Decision Node asks a question.
This holds a reference to the question, and to the two child nodes.
"""
def __init__(self,
column,
value,
true_branch,
false_branch):
self.column = column
self.value = value
self.true_branch = true_branch
self.false_branch = false_branch# [https://github.com/random-forests/tutorials/blob/master/decision_tree.ipynb](https://github.com/random-forests/tutorials/blob/master/decision_tree.ipynb)def print_tree(node, spacing=""):
"""
World's most elegant tree printing function.
Input
node: the tree node
spacing: used to space creating tree like structure
"""
# Base case: we've reached a leaf
if isinstance(node, Leaf):
print (spacing + "Predict", node.predictions)
return
# Print the col and value at this node
print(spacing + f"[{node.column} <= {node.value}]")
# Call this function recursively on the true branch
print (spacing + '--> True:')
print_tree(node.true_branch, spacing + " ")
# Call this function recursively on the false branch
print (spacing + '--> False:')
print_tree(node.false_branch, spacing + " ")
递归二进制分裂
为了使算法工作,我们将需要分裂递归地发生,直到我们满足停止标准——在这种情况下,直到每个叶节点都是纯的。
def build_tree(df, label, idx):
"""
Recursively Builds the tree until is leaf is pure.
Input
df: the training data
label: the target labels
idx: the indexes
Output
best_col: the best column
best_value: the value of the column that minimizes impurity
true_branch: the true branch
false_branch: the false branch
"""
best_gain, best_col, best_value = find_best_split(df, label, idx)
if best_gain == 0:
return Leaf(label, label.loc[idx].index)
left_idx, right_idx = partition(df.loc[idx], best_col, best_value)
true_branch = build_tree(df, label, left_idx)
false_branch = build_tree(df, label, right_idx)
return Decision_Node(best_col, best_value, true_branch, false_branch)my_tree = build_tree(X_train, y_train, X_train.index)print_tree(my_tree)[petal length (cm) <= 1.9]
--> True:
Predict {'setosa': 38}
--> False:
[petal width (cm) <= 1.6]
--> True:
[petal length (cm) <= 4.9]
--> True:
Predict {'versicolor': 40}
--> False:
[sepal length (cm) <= 6.0]
--> True:
[sepal width (cm) <= 2.2]
--> True:
Predict {'virginica': 1}
--> False:
Predict {'versicolor': 1}
--> False:
Predict {'virginica': 2}
--> False:
[petal length (cm) <= 4.8]
--> True:
[sepal width (cm) <= 3.0]
--> True:
Predict {'virginica': 3}
--> False:
Predict {'versicolor': 1}
--> False:
Predict {'virginica': 26}
超级!现在,您已经看到了如何从头开始实现决策树,并且我们已经根据我们的训练数据对其进行了训练。然而,它并没有就此停止,首先构建算法的目的是自动对新的观察结果进行分类。下一节将致力于推理…
推理
def predict(test_data, tree):
"""
Classify unseen examples
Inputs
test_data: Unseen observation
tree: tree that has been trained on training data
Output
The prediction of the observation.
"""
# Check if we are at a leaf node
if isinstance(tree, Leaf):
return max(tree.predictions)
# the current feature_name and value
feature_name, feature_value = tree.column, tree.value
# pass the observation through the nodes recursively
if test_data[feature_name] <= feature_value:
return predict(test_data, tree.true_branch)
else:
return predict(test_data, tree.false_branch)
为了检查我们的函数是否正确运行,我将使用一个观察示例。
# taking one instance to test function
example, example_target = X_test.iloc[6], y_test.iloc[6]
example, example_target(sepal length (cm) 5.3
sepal width (cm) 3.7
petal length (cm) 1.5
petal width (cm) 0.2
predictions setosa
Name: 48, dtype: object,
'setosa')
当我们将我们的predict函数应用到示例中时,我们应该希望观察相应地遍历树并输出setosa,让我们检查…
# if working correctly should output setosa
predict(example, my_tree)'setosa'
至高无上!!然而,这只是一个例子。如果我们想将这个函数应用到我们测试集中的每一个观察值,我们可以使用df.apply——参见文档
# create a new col of predictions
X_test["predictions"] = X_test.apply(predict, axis=1, args=(my_tree,))
好了,关键时刻到了。我们需要检查我们的算法是否返回与 scikit 学习模型相同的预测,作为检查我们是否正确实现了我们的算法的一种方式。我们通过简单地执行sklearn_y_preds == X_true["predictions"]来做到这一点,它为每个观察返回一个布尔数组——在我们的例子中,它们都是真的。
print(f"Sklearn Implementation:\nACCURACY: {accuracy_score(y_test, sklearn_y_preds)}\n\n\
My Implementation:\nACCURACY: {accuracy_score(y_test, X_test['predictions'])}")Sklearn Implementation:
ACCURACY: 0.9736842105263158
My Implementation:
ACCURACY: 0.9736842105263158
赞成的意见
- 简单易懂
- 能够处理数字和分类数据
- 几乎不需要数据准备
- 适用于大型数据集
- 内置功能选择
骗局
- 树的不稳定性(改变数据中的某些东西可以改变一切)
- 缺乏平滑度(回归问题的特殊问题)
- 倾向于过度拟合
包裹
建立决策树的良好基础将有助于理解许多其他重要的机器学习算法。它是一种非常强大的算法,经常被用作集成模型来赢得各种数据科学比赛。虽然很容易概念化,但决策树很难从头开始构建,因此我总是主张尽可能使用已建立的机器学习框架。
感谢您阅读到文章结尾!如果你想和我保持联系,你可以在 LinkedIn 上找到我。
[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn
在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)
从头开始的算法:K-最近邻
从零开始的算法
从头开始详述和构建 K-NN 算法

介绍
能够执行分类和回归的非参数算法;斯坦福大学教授 Thomas Cover 于 1967 年首次提出了 K 近邻算法的思想。
许多人经常把 K-NN 称为懒惰学习器或一种基于实例的学习器,因为所有的计算都推迟到函数求值。我个人认为,当我们开始概念化机器学习算法时,这将 K-最近邻推向了不太复杂的一端。
无论我们是在做分类还是回归风格问题,输入都将由原始特征空间中的 k 个最近的训练样本组成。然而,算法的输出当然取决于问题的类型——关于不同输出的更多信息,请参见术语部分。
链接到文章中生成的代码…
通过在 GitHub 上创建一个帐户,为 kurtispykes/ml 的从头开发做出贡献。
github.com](https://github.com/kurtispykes/ml-from-scratch/tree/master)
术语
K-最近邻分类 →输出将确定类成员,并且通过其邻居的多数投票来进行预测。因此,新实例将被分配到最常见的 k 个最近邻居的类中。
K-最近邻回归 →输出将确定对象的属性值。因此,新实例将被分类为第 k 个最近邻居的平均值
基于实例的学习 →一系列机器学习算法,不执行显式归纳,而是将新的问题实例与存储在内存中的训练中看到的实例进行比较。(来源: 维基百科 )
惰性学习 →一种机器学习方法,在这种方法中,训练数据的概括在理论上被延迟,直到向系统发出查询,这与系统在接收查询之前试图概括训练数据的急切学习相反。(来源: 百科 )
创建模型
创建 K-NN 算法非常简单。训练阶段实际上是存储训练样本的特征向量和标签,但是我们需要为 k. 通常为,确定一个正整数。当我们选择一个较大的值 k 时,我们会减少噪声对分类的影响,从而使类别之间的边界不那么明显。最终, k 的选择很大程度上受到数据的影响,这意味着我们无法知道,直到我们尝试了数据,然而我们可以使用许多不同的试探法来为我们的数据选择 k 。
注:要阅读关于调整 k 超参数的更多信息,请参见维基百科页面的 超参数优化 。
太好了,我们选择了 k。为了对分类任务的新实例进行预测,识别出与新观察最接近的 k 个记录(来自训练数据)。在对 K 个近邻进行评估后,将进行预测——参见术语部分的K-最近邻分类,了解如何进行预测。
为了识别与新实例最接近的 k 个记录,我们必须对所有实例进行测量。这可以通过多种方式实现,尽管作为一种指导,当我们有连续变量时,许多从业者经常使用欧几里德距离,而对于离散变量则使用汉明距离。
图像汉明和欧氏距离
分块算法
- 计算欧几里德距离
- 定位邻居
- 预测
实现
为了实现我们的 K-最近邻分类算法,我们将使用来自 Scikit-Learn 的虹膜数据集。在这项任务中,我们面临的挑战是在给定花朵尺寸的情况下,预测花朵是setosa、versicolor还是virginica——这使它成为一项多类分类任务。
注意:在这个实现中,我没有执行任何试探法来选择最佳的k——我只是随机选择了一个 k 值。
import numpy as np
import pandas as pd
from collections import Counterimport matplotlib.pyplot as plt
%matplotlib inlinefrom sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_splitiris = load_iris()
X, y = iris.data, iris.targetX_train, X_test, y_train, y_test = train_test_split(X, y, test_size= 0.2, random_state=1810)X_train.shape, y_train.shape, X_test.shape, y_test.shape((120, 4), (120,), (30, 4), (30,))
我们现在有了数据,并使用了基于维持的交叉验证方案来拆分数据——如果您不熟悉这个术语,请参见下面的链接。
验证机器学习模型的性能
towardsdatascience.com](/cross-validation-c4fae714f1c5)
第一步是计算两行之间的欧几里德距离。
def euclidean(x1, x2):
return np.sqrt(np.sum((x1 - x2)**2))
为了测试这个函数,我从 Jason brown lee那里取了一些代码,他用这些代码来测试他的距离函数。如果我们有正确的实现,那么我们的输出应该是相同的。
# dataset from [https://machinelearningmastery.com/tutorial-to-implement-k-nearest-neighbors-in-python-from-scratch/](https://machinelearningmastery.com/tutorial-to-implement-k-nearest-neighbors-in-python-from-scratch/)dataset = [[2.7810836,2.550537003,0],
[1.465489372,2.362125076,0],
[3.396561688,4.400293529,0],
[1.38807019,1.850220317,0],
[3.06407232,3.005305973,0],
[7.627531214,2.759262235,1],
[5.332441248,2.088626775,1],
[6.922596716,1.77106367,1],
[8.675418651,-0.242068655,1],
[7.673756466,3.508563011,1]]row0 = dataset[0]for row in dataset:
**print**(euclidean(np.array(row0), np.array(row)))0.0
1.3290173915275787
1.9494646655653247
1.5591439385540549
0.5356280721938492
4.952940611164215
2.7789902674782985
4.3312480380207
6.59862349695304
5.084885603993178
我们得到完全相同的输出——请随意查看提供的链接。
如前所述,新观察的 k —邻居是来自训练数据的 k 最近实例。使用我们的距离函数euclidean,我们现在可以计算训练数据中的每个观察值与我们已经传递的新观察值之间的距离,并从最接近我们的新观察值的训练数据中选择 k 个实例。
def find_neighbors(X_train, X_test, y_train, n_neighbors):
distances = [euclidean(X_test, x) for x in X_train]
k_nearest = np.argsort(distances)[:n_neighbors]
k_nearest_label = [y_train[i] for i in k_nearest]
most_common = Counter(k_nearest_label).most_common(1)[0][0]
return most_common
此函数计算新观察到定型数据中所有行的距离,并将其存储在一个列表中。接下来,我们使用 NumPy 模块np.argsort()找到 k 最低距离的索引—参见文档。然后我们使用索引来识别 k 个实例的类。之后,我们使用 Pythons 内置模块中的Counter函数计算k_nearest_labels 列表中实例的数量,并返回最常见的(计数最高的标签)。然而,在我们做出预测之前,我们不会看到它的实际运行,所以让我们来构建预测函数。
def predict(X_test, X_train, y_train, n_neighbors=3):
predictions = [find_neighbors(X_train, x, y_train, n_neighbors) for x in X_test]
return np.array(predictions)predict(X_test, X_train, y_train, n_neighbors=3)
**array**([0, 0, 2, 2, 0, 1, 0, 0, 1, 1, 2, 1, 2, 0, 1, 2, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 1, 1, 0, 2])
在predict函数中,我们使用列表理解来为测试集中的每个新实例找到最近的邻居,并返回一个数组。使用 3 个邻居,我们在任务上获得了 100%的准确性,并且我们可以将其与 scikit-learning 实现进行比较,以查看我们是否获得了相同的结果——确实如此。
注意:K 近邻分类器的文档可以在这里找到
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)sklearn_preds = knn.predict(X_test)
preds = predict(X_test, X_train, y_train, n_neighbors=3)**print**(f"My Implementation: {accuracy_score(y_test, preds)}\nScikit-Learn Implementation: {accuracy_score(y_test, sklearn_preds)}")My Implementation: 1.0
Scikit-Learn Implementation: 1.0
优点
- 直观简单
- 没有训练步骤
- 可用于分类和回归(以及无监督学习)
- 对于多类问题易于实现
缺点
- 随着数据的增长,算法变得非常慢
- 对异常值敏感
- 不平衡的数据会导致问题—可以使用加权距离来克服这个问题。
包裹
在本故事中,您了解了 K-最近邻算法、如何在 Python 中从头开始实现 K-最近邻分类算法,以及使用 K-最近邻的利弊。
让我们继续 LinkedIn 上的对话……
[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn
在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)
从头开始的算法:线性回归
从零开始的算法
从头开始详述和构建线性回归模型

线性回归是一种流行的线性机器学习算法,用于基于回归的问题。由于它的简单性以及它如何构建到逻辑回归和神经网络等其他算法中,它通常是第一次学习机器学习时学习的第一批算法之一。在这个故事中,我们将从头开始实现它,这样我们就可以对线性回归模型中发生的事情建立直觉。
链接到 Github Repo…
[## kurtispykes/ml-从零开始
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/kurtispykes/ml-from-scratch/blob/master/linear_regression.ipynb)
注意:许多框架都有高度优化的代码,如 Scikit-Learn、Tensorflow 和 PyTorch,因此通常没有必要从头构建自己的算法。然而,当我们从零开始构建模型时,它为我们对模型中正在发生的事情的直觉提供了一个很好的目的,这有助于我们尝试改进我们的模型性能。
线性模型是一种算法,它通过简单地计算输入要素加上偏差项(也称为截距项)的加权和来进行预测。考虑到这一点,当我们使用线性回归模型时,我们希望解释因变量(即房价)和一个或多个自变量(即位置、卧室、面积等)之间的关系。

图 1:多元线性回归
当我们训练一个模型时,我们试图设置参数以得到一条最适合训练数据的线。因此,当我们训练线性回归模型时,我们试图找到最能最小化成本函数的θ值。回归模型最常见的成本函数是 RMSE ,然而,最小化 MSE 要容易得多,因为它会导致相同的结果。
创建模型
如果你从未从头开始编写过机器学习算法,我非常鼓励你这样做。约翰·苏利文写了一个非常有用的故事,名为 从零开始编写任何机器学习算法的 6 个步骤:感知机案例研究 w 这是我在互联网上找到的关于从零开始编写算法的最好建议。
分块算法
- 随机初始化假设函数的参数
- 计算偏导数(点击阅读更多关于这个的信息)
- 更新参数
- 重复 2-3,重复 n 次迭代(直到成本函数最小化)
- 推理
实施
对于本节,我将利用 3 个 Python 包。NumPy 用于线性代数,Scikit-Learn 是一个流行的机器学习框架,Matplotlib 用于可视化我们的数据。
**import** **numpy** **as** **np**
**import** **matplotlib.pyplot** **as** **plt**
**from** **sklearn.datasets** **import** make_regression
**from** **sklearn.linear_model** **import** LinearRegression
**from** **sklearn.model_selection** **import** train_test_split
**from** **sklearn.metrics** **import** mean_squared_error
首先,我们需要一个数据集。为此,我将sklearn.datasets.make_regression允许您生成一个随机回归问题—参见文档。接下来,我将用sklearn.model_selection.train_test_split — 文档将我的数据分成训练集和测试集。
# creating the data set
X, y = make_regression(n_samples=100, n_features=1, n_targets=1, noise=20, random_state=24)
# splitting training and test
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.75, random_state=24)
让我们用matplotlib.pyplot来看看我们的数据是什么样子的— 文档。
*# visualize*
plt.scatter(X, y)
plt.show()

图 2:我们生成的回归问题
现在我们可以开始实施线性回归了。我们程序块的第一步是为我们的假设函数随机初始化参数。
**def** param_init(X):
*"""*
*Initialize parameters for linear regression model*
*__________________*
*Input(s)*
*X: Training data*
*__________________*
*Output(s)*
*params: Dictionary containing coefficients*
*"""*
params = {} *# initialize dictionary*
_, n_features = X.shape *# shape of training data*
*# initializing coefficents to 0*
params["W"] = np.zeros(n_features)
params["b"] = 0
**return** params
非常好。接下来我们要计算偏导数并更新我们的参数。我们使用一种非常重要的叫做梯度下降的机器学习算法来做到这一点。因此,我们可以用梯度下降实现步骤 2-4。
**def** gradient_descent(X, y, params, alpha, n_iter):
*"""*
*Gradient descent to minimize cost function*
*__________________*
*Input(s)*
*X: Training data*
*y: Labels*
*params: Dictionary contatining random coefficients*
*alpha: Model learning rate*
*__________________*
*Output(s)*
*params: Dictionary containing optimized coefficients*
*"""*
W = params["W"]
b = params["b"]
m = X.shape[0] *# number of training instances*
**for** _ **in** range(n_iter):
*# prediction with random weights*
y_pred = np.dot(X, W) + b
*# taking the partial derivative of coefficients*
dW = (2/m) * np.dot(X.T, (y_pred - y))
db = (2/m) * np.sum(y_pred - y)
*# updates to coefficients*
W -= alpha * dW
b -= alpha * db
params["W"] = W
params["b"] = b
**return** params
使用这些函数,我们可以根据训练数据训练我们的线性回归模型,以获得我们进行推理所需的模型参数。
**def** train(X, y, alpha=0.01, n_iter=1000):
*"""*
*Train Linear Regression model with Gradient decent*
*__________________*
*Input(s)*
*X: Training data*
*y: Labels*
*alpha: Model learning rate*
*n_iter: Number of iterations*
*__________________*
*Output(s)*
*params: Dictionary containing optimized coefficients*
*"""*
init_params = param_init(X)
params = gradient_descent(X, y, init_params, alpha, n_iter)
**return** params
现在,当我们运行这个函数时,我们将从我们的训练数据中获得优化的权重,我们将使用这些权重对我们的测试数据进行推断。接下来,我们需要使用我们存储的权重为我们的推断创建一个预测函数。
**def** predict(X_test, params):
*"""*
*Train Linear Regression model with Gradient decent*
*__________________*
*Input(s)*
*X: Unseen data*
*params: Dictionary contianing optimized weights from training*
*__________________*
*Output(s)*
*y_preds: Predictions of model*
*"""*
y_preds = np.dot(X_test, params["W"]) + params["b"]
**return** y_preds
太好了!让我们运行这些函数并绘制它们,看看会发生什么…
params = train(X_train, y_train) *# train model*
y_preds = predict(X_test, params) *# inference*plt.scatter(X_test, y_test)
plt.plot(X_test, y_preds, color="red")
plt.title("Predictions Dummy Regression Data")
plt.xlabel("X axis")
plt.ylabel("Y axis")
plt.show()

图 3:来自自定义线性回归模型的预测。
我们的最佳系列似乎相当不错。为了完全确定我们的实现,我们很幸运有许多机器学习库,带有优化的代码,可以用来比较我们的实现。为了进行比较,我将简单地检查我们的实现与 Scikit-learn 的 RMSE 。
注意:在同一个图上绘制它们的实现也是值得的,如果它们的最佳拟合线覆盖了你的,那么你就在正确的轨道上。
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)
sklearn_y_preds = lin_reg.predict(X_test)print(f"My implementation: {np.sqrt(mean_squared_error(y_test, y_preds))}**\n**Sklearn implementation: {np.sqrt(mean_squared_error(y_test, sklearn_y_preds))}")>>>> My implementation: 20.986105292320207
Sklearn implementation: 20.986105292320207
匹配了!
对于这种实现,我们使用了过程化编程,这种编程维护起来会变得非常复杂和麻烦,并且没有最大限度地发挥 Python 的潜力,Python 是一种面向对象编程(OOP) 语言。关于这一点,这里是我们的线性回归模型的 OOP 实现。
**class** **LinReg**():
*"""*
*Custom made Linear Regression class*
*"""*
**def** __init__(self, alpha=0.01, n_iter= 1000):
self.alpha = alpha
self.n_iter = n_iter
self.params = {}
**def** param_init(self, X_train):
*"""*
*Initialize parameters for linear regression model*
*__________________*
*Input(s)*
*X: Training data*
*"""*
_, n_features = self.X.shape *# shape of training data*
*# initializing coefficents to 0*
self.params["W"] = np.zeros(n_features)
self.params["b"] = 0
**return** self
**def** gradient_descent(self, X_train, y_train):
*"""*
*Gradient descent to minimize cost function*
*__________________*
*Input(s)*
*X: Training data*
*y: Labels*
*params: Dictionary contatining random coefficients*
*alpha: Model learning rate*
*__________________*
*Output(s)*
*params: Dictionary containing optimized coefficients*
*"""*
W = self.params["W"]
b = self.params["b"]
m = X_train.shape[0]
**for** _ **in** range(self.n_iter):
*# prediction with random weights*
y_pred = np.dot(X_train, W) + b
*# taking the partial derivative of coefficients*
dW = (2/m) * np.dot(X_train.T, (y_pred - y_train))
db = (2/m) * np.sum(y_pred - y_train)
*# updates to coefficients*
W -= self.alpha * dW
b -= self.alpha * db
self.params["W"] = W
self.params["b"] = b
**return** self
**def** train(self, X_train, y_train):
*"""*
*Train Linear Regression model with Gradient decent*
*__________________*
*Input(s)*
*X: Training data*
*y: Labels*
*alpha: Model learning rate*
*n_iter: Number of iterations*
*__________________*
*Output(s)*
*params: Dictionary containing optimized coefficients*
*"""*
self.params = param_init(X_train)
gradient_descent(X_train, y_train, self.params , self.alpha, self.n_iter)
**return** self
**def** predict(self, X_test):
*"""*
*Train Linear Regression model with Gradient decent*
*__________________*
*Input(s)*
*X: Unseen data*
*params: Dictionary contianing optimized weights from training*
*__________________*
*Output(s)*
*y_preds: Predictions of model*
*"""*
y_preds = np.dot(X_test, self.params["W"]) + self.params["b"]
**return** y_preds
让我们调用这个类,让它对我们的测试数据进行预测…
linreg = LinReg()
linreg.train(X_train, y_train)
linreg.predict(X_test)>>>>
array([ 4.73888182, -90.06369632, 80.39799712, 66.76983607,
-49.97207144, 93.77905208, 34.30778991, -38.2209702 ,
78.03331698, 53.81416352, 102.96993005, 151.71946744,
95.52801857, 104.82707085, 98.0492089 , 45.05150211,
-7.29917923, -78.41675446, -27.14118529, -98.52923336,
170.75840972, -106.22126739, 24.86194847, -21.39127805,
50.24074837])
作为健全性检查,我们将测试预测是否与我们的过程实现相同(因为我们知道这已经与 scikit-learn 实现类似)。
linreg.predict(X_test) == y_preds>>>>
array([ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True])
现在你知道了!
注意:我们作为例子的问题是简单线性回归问题(一元线性回归),y = WX + b,其中 W 是权重,b 是偏倚。
假设
在决定我们要使用线性回归之前,了解模型对我们的数据所做的假设是很重要的,这样我们就可以执行必要的特征工程来与我们的模型保持一致。
关于特征工程的更多信息,请参阅我以前关于这个主题的文章…
工程数值的技巧
towardsdatascience.com](/feature-engineering-for-numerical-data-e20167ec18)
线性 —线性回归假设特征和我们想要预测的目标之间存在线性关系。我们可以通过绘制与目标变量相关的特征散点图来检查这一点的有效性。
多重共线性——指多元回归模型中两个或两个以上解释变量高度相关的情况(来源:维基百科)。当我们实施线性回归时,我们假设很少或没有多重共线性,因为多重共线性的存在会削弱回归模型的统计能力。要确定数据中是否存在多重共线性,我们可以使用相关矩阵来查看哪些要素高度相关,并移除其中一个高度相关的要素。
同方差 —在统计学中,一个随机变量序列(或向量)如果其所有随机变量都具有相同的有限方差,则该序列(或向量)是同方差的(来源:维基百科)。线性回归假设所有观测值中的噪声是相同的(也可称为误差项或随机扰动),并且不依赖于独立变量的值。我们可以用残差值与预测值的散点图来检验同方差性。我们应该期望分布中没有模式,因为如果有模式,那么数据就是异方差的。
误差分布的正态性 —数据点正态分布在回归线周围。换句话说,我们假设残差遵循正态分布。我们可以使用直方图或 QQ 图来检查这一点——我们可以使用广义线性模型(GLM) 来克服这一点。
自相关——信号与自身延迟副本的相关性,作为延迟的函数——通俗地说,就是观测值之间的相似性,作为它们之间时滞的函数(来源:维基百科)。简而言之,当残差彼此不独立时,就会出现自相关。我们可以使用散点图来直观地检查自相关性,或者使用 Durbin-Watsons 检验来测试残差不是线性自相关的零假设。
赞成的意见
- 易于实施
- 易于解释输出系数
- 不太复杂
骗局
- 对异常值敏感
- 假设自变量和因变量之间呈线性关系
- 假设特征之间相互独立
关于线性回归的更多信息,你可以阅读维基百科页面。
在统计学中,线性回归是一种建模标量响应(或变量)之间关系的线性方法
en.wikipedia.org](https://en.wikipedia.org/wiki/Linear_regression#:~:text=In statistics%2C linear regression is,is called simple linear regression.)
包裹
线性回归是最简单的机器学习模型之一,也最有可能是你将要学习或者应该学习的第一个模型。它是一个非常有用的分析变量之间关系的工具,但是由于模型的假设很多,现实问题的简化,所以在大多数实际应用中不推荐使用。
感谢您花时间阅读这个故事。如果我错过了什么或者你想让我澄清什么,请在评论中回复。另外,如果你想和我联系,我在 LinkedIn 上是最容易联系到的。
[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn
在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)
从零开始的算法:逻辑回归
从零开始的算法
从头开始详述和构建逻辑回归模型

与普遍的看法相反,我在此声明,逻辑回归是而不是一种分类算法(本身是 ) —事实上,逻辑回归实际上是一种回归模型,所以不要对其命名中出现“回归”感到惊讶。回归分析是一套统计过程,用于估计因变量与一个或多个自变量之间的关系(来源:维基百科)。如上所述,逻辑回归不是一种分类算法,它不执行统计分类,因为它只是估计逻辑模型的参数。
逻辑回归是一种统计模型,其最基本的形式是使用逻辑函数来模拟二元因变量,尽管存在许多更复杂的扩展。(来源:维基百科)
允许将逻辑回归用作分类算法的是使用阈值(也可称为截止或决策边界),这反过来会将概率大于阈值的输入分类为一个类别,而将概率低于阈值的输入分类为另一个类别,正如我们在机器学习中通常所做的那样。
参见 这一环节 来看我们如何处理多类分类问题。
现在,让我们把注意力从零开始回到算法系列的目的。
链接到 Github 存储库…
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/kurtispykes/ml-from-scratch/blob/master/logistic_regression.ipynb)
注 :有很多机器学习框架的代码经过高度优化,这使得从头开始编写机器学习算法在实际设置中成为一项多余的任务。然而,当我们从零开始构建算法时,它有助于我们对模型中正在发生的事情获得更深入的直觉,这可能会在尝试改进我们的模型时带来高回报。
二元分类的线性回归
在《从零开始的算法:线性回归》的最后一集里,我说“它通常是第一次学习机器学习时学习的第一批算法之一,因为它很简单,而且它如何构建到其他算法里,如逻辑回归和神经网络”——你现在会明白我的意思了。
我们如何从预测连续变量到伯努利变量(即“成功”或“失败”)?由于响应数据(我们试图预测的数据)是二元的(取值 0 和 1),因此仅由 2 个值组成,我们可以假设我们的响应变量的分布现在来自二项式分布——这需要一个完美的时间来引入由约翰·内尔德和罗伯特·威德伯恩制定的广义线性模型(GLM)。
GLM 模型允许响应变量具有不同于正态分布的误差分布。在我们的情况下,我们现在有一个二项分布,通过使用 GLM 模型,我们可以通过链接函数将线性模型与响应变量相关联,并允许每个测量的方差大小是其预测值的函数,从而推广线性回归(来源:维基百科)。
长话短说,逻辑回归是具有二项式条件响应和 logit 链接的 GLM 的特例。
停止…
在继续之前,我们应该弄清楚一些统计术语(用外行人的术语来说):
- 几率——某事发生与某事未发生的比率。例如,切尔西赢得接下来 4 场比赛的赔率是 1 比 3。发生的事情(切尔西赢得比赛)1 与没有发生的事情(切尔西没有赢得比赛)3 的比值可以写成一个分数,1/3。
- 概率——发生的事情与可能发生的事情的比率。使用上面的例子,正在发生的事情(切尔西获胜)1 与所有可能发生的事情(切尔西获胜和失败)4 的比率也可以写成分数 1/4,这是获胜的概率——因此失败的概率是 1–1/4 = 3/4。
概率的范围在 0 和 1 之间,而赔率并不局限于 0 和 1 之间,而是可以取 0 到无穷大之间的任何值。
我们可以通过将获胜概率的比率(用我们的例子来说是 1/4)除以失败概率的比率(3/4)来得到概率的赔率,从而得到 1/3,即赔率。参见图 1 了解我们如何用数学方法表达它。

图 1:从概率中得出的赔率。
如果切尔西是一支糟糕的足球队(难以想象,我知道),他们获胜的几率会在 0 到 1 之间。然而,由于我们都知道切尔西是世界上最伟大的球队之一(毫无疑问是伦敦最好的球队),因此,切尔西获胜的几率将在 1 到无穷大之间。不对称使得很难比较支持或反对切尔西获胜的几率,所以我们采用几率的对数来使一切对称。
图 1 向我们展示了我们可以用概率计算赔率,既然如此,我们也可以使用图 1 中的公式计算赔率的对数。概率比的对数被称为 logit 函数,它构成了逻辑回归的基础。让我们通过考虑具有给定参数的逻辑模型来更好地理解这一点,并看看如何从数据中估计系数。
注:下面这个例子来源于逻辑回归的例子部分 维基百科 。
考虑一个有两个独立变量( X 1 和 X 2)和一个伯努利响应变量 Y 的模型,我们用 p = P (Y=1)表示。我们假设独立变量和 Y=1 事件的对数概率之间存在线性关系,可以用数学方法表示为:

图 2:独立变量与 Y=1 事件的对数比数之间的线性关系表达式。
通过对对数赔率求幂,我们恢复赔率如下:

图 3:对对数赔率求幂以恢复赔率。
通过简单的代数运算,Y=1 的概率为:

图 4:代数操作
考虑到这一点,图 4 向我们展示了,如果我们有线性模型的参数,我们可以很容易地计算给定观察值的对数优势或 Y= 0 的概率。逻辑回归仍然是一个回归模型,没有与使反应的预测概率二分法的阈值结合使用。
分块算法
- 随机初始化假设函数的参数
- 将逻辑函数应用于线性假设函数
- 计算偏导数( Saket Thavanani 写了一篇很好的文章,题目是 逻辑回归成本函数的导数 )
- 更新参数
- 重复 2-4,重复 n 次迭代(直到成本函数最小化)
- 推理
实现
在本节中,我使用了 3 个 Python 框架:NumPy 用于线性代数,Pandas 用于数据操作,Scikit-Learn 用于机器学习工具。
**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**from** **sklearn.metrics** **import** accuracy_score
**from** **sklearn.datasets** **import** load_breast_cancer
**from** **sklearn.linear_model** **import** LogisticRegression
**from** **sklearn.model_selection** **import** train_test_split
首先,我们需要一个数据集。我使用的是经典的二元分类数据集sklearn.datasets.load_breast_cancer——参见文档。
*# loading the data set*
dataset = load_breast_cancer(as_frame=**True**)
df= pd.DataFrame(data= dataset.data)
df["target"] = dataset.target
df.head()

图 5:上面代码单元的输出。注意:数据帧有 31 列,太大而无法显示,因此出现省略号(仍有一些列看不到)。
接下来,我们将预测变量和响应变量分开,然后创建一个训练和测试集。
*# Seperating to X and Y*
X = df.iloc[:, :-1]
y = df.iloc[:, -1]
*# splitting training and test*
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.75, shuffle=**True**, random_state=24)
我们从头开始构建线性回归所做的大量工作(见下面的链接)可以借用一些微小的变化来使用逻辑回归调整我们的分类模型。
从头开始详述和构建线性回归模型
towardsdatascience.com](/algorithms-from-scratch-linear-regression-c654353d1e7c)
**def** param_init(X):
*"""*
*Initialize parameters*
*__________________*
*Input(s)*
*X: Training data*
*__________________*
*Output(s)*
*params: Dictionary containing coefficients*
*"""*
params = {} *# initialize dictionary*
_, n_features = X.shape *# shape of training data*
*# initializing coefficents to 0*
params["W"] = np.zeros(n_features)
params["b"] = 0
**return** params**def** get_z(X, W, b):
*"""*
*Calculates Linear Function*
*__________________*
*Input(s)*
*X: Training data*
*W: Weight coefficients*
*b: bias coefficients*
*__________________*
*Output(s)*
*z: a Linear function*
*"""*
z = np.dot(X, W) + b
**return** z**def** sigmoid(z):
*"""*
*Logit model*
*_________________*
*Input(s)*
*z: Linear model*
*_________________*
*Output(s)*
*g: Logit function applied to linear model*
*"""*
g = 1 / (1 + np.exp(-z))
**return** g**def** gradient_descent(X, y, params, lr, n_iter):
*"""*
*Gradient descent to minimize cost function*
*__________________*
*Input(s)*
*X: Training data*
*y: Labels*
*params: Dictionary contatining coefficients*
*lr: learning rate*
*__________________*
*Output(s)*
*params: Dictionary containing optimized coefficients*
*"""*
W = params["W"]
b = params["b"]
m = X.shape[0] *# number of training instances*
**for** _ **in** range(n_iter):
*# prediction with random weights*
g = sigmoid(get_z(X, W, b))
*# calculate the loss*
loss = -1/m * np.sum(y * np.log(g)) + (1 - y) * np.log(1-g)
*# partial derivative of weights*
dW = 1/m * np.dot(X.T, (g - y))
db = 1/m * np.sum(g - y)
*# updates to coefficients*
W -= lr * dW
b -= lr * db
params["W"] = W
params["b"] = b
**return** params**def** train(X, y, lr=0.01, n_iter=1000):
*"""*
*Train Linear Regression model with Gradient decent*
*__________________*
*Input(s)*
*X: Training data*
*y: Labels*
*lr: learning rate*
*n_iter: Number of iterations*
*__________________*
*Output(s)*
*params: Dictionary containing optimized coefficients*
*"""*
init_params = param_init(X)
params = gradient_descent(X, y, init_params, lr, n_iter)
**return** params**def** predict(X_test, params):
*"""*
*Train Linear Regression model with Gradient decent*
*__________________*
*Input(s)*
*X: Unseen data*
*params: Dictionary contianing optimized weights from training*
*__________________*
*Output(s)*
*prediction of model*
*"""*
z = np.dot(X_test, params["W"]) + params["b"]
y_pred = sigmoid(z) >= 0.5
**return** y_pred.astype("int")
值得注意的区别是,我们现在将 logit 函数应用于我们的线性模型,根据推断,我们将 logit 模型中大于 0.5 的每个输出都分类为第一类(否则为第 0 类),并且我们使用不同的成本函数来工作于我们的分类模型,因为 MSE 会使我们的损失函数为非凸的-要了解更多关于所使用的成本函数的信息,您一定要阅读 逻辑回归的成本函数的导数 。
params = train(X_train, y_train) *# train model*
y_pred = predict(X_test, params) *# inference*lr = LogisticRegression(C=0.01)
lr.fit(X_train, y_train)
sklearn_y_pred = lr.predict(X_test)print(f"My Implementation: {accuracy_score(y_test, y_pred)}**\n**Sklearn Implementation: {accuracy_score(y_test, sklearn_y_pred)}")>>>> My Implementation: 0.9300699300699301
Sklearn Implementation: 0.9300699300699301
很好,我们获得了与 Scikit-Learn 实现相同的精度。
现在,我们将用面向对象编程来重复这一点,面向对象编程被认为更适合协作。
**class** **LogReg**():
*"""*
*Custom made Logistic Regression class*
*"""*
**def** __init__(self, lr=0.01, n_iter= 1000):
self.lr = lr
self.n_iter = n_iter
self.params = {}
**def** param_init(self, X_train):
*"""*
*Initialize parameters*
*__________________*
*Input(s)*
*X: Training data*
*"""*
_, n_features = self.X.shape *# shape of training data*
*# initializing coefficents to 0*
self.params["W"] = np.zeros(n_features)
self.params["b"] = 0
**return** self
**def** get_z(X, W, b):
*"""*
*Calculates Linear Function*
*__________________*
*Input(s)*
*X: Training data*
*W: Weight coefficients*
*b: bias coefficients*
*__________________*
*Output(s)*
*z: a Linear function*
*"""*
z = np.dot(X, W) + b
**return** z
**def** sigmoid(z):
*"""*
*Logit model*
*_________________*
*Input(s)*
*z: Linear model*
*_________________*
*Output(s)*
*g: Logit function applied to linear model*
*"""*
g = 1 / (1 + np.exp(-z))
**return** g
**def** gradient_descent(self, X_train, y_train):
*"""*
*Gradient descent to minimize cost function*
*__________________*
*Input(s)*
*X: Training data*
*y: Labels*
*params: Dictionary contatining random coefficients*
*alpha: Model learning rate*
*__________________*
*Output(s)*
*params: Dictionary containing optimized coefficients*
*"""*
W = self.params["W"]
b = self.params["b"]
m = X_train.shape[0]
**for** _ **in** range(self.n_iter):
*# prediction with random weights*
g = sigmoid(get_z(X, W, b))
*# calculate the loss*
loss = -1/m * np.sum(y * np.log(g)) + (1 - y) * np.log(1 - g)
*# partial derivative of weights*
dW = 1/m * np.dot(X.T, (g - y))
db = 1/m * np.sum(g - y)
*# updates to coefficients*
W -= self.lr * dW
b -= self.lr * db
self.params["W"] = W
self.params["b"] = b
**return** self
**def** train(self, X_train, y_train):
*"""*
*Train model with Gradient decent*
*__________________*
*Input(s)*
*X: Training data*
*y: Labels*
*alpha: Model learning rate*
*n_iter: Number of iterations*
*__________________*
*Output(s)*
*params: Dictionary containing optimized coefficients*
*"""*
self.params = param_init(X_train)
gradient_descent(X_train, y_train, self.params , self.lr, self.n_iter)
**return** self
**def** predict(self, X_test):
*"""*
*Inference*
*__________________*
*Input(s)*
*X: Unseen data*
*params: Dictionary contianing optimized weights from training*
*__________________*
*Output(s)*
*y_preds: Predictions of model*
*"""*
g = sigmoid(np.dot(X_test, self.params["W"]) + self.params["b"])
**return** g
为了检查我们是否正确地实现了它,我们可以看看预测是否与我们的过程实现相同,因为我们已经知道这大约等于 Scikit-learn 的实现。
logreg = LogReg()
logreg.train(X_train, y_train)
oop_y_pred = logreg.predict(X_test)oop_y_pred == y_preds
这将返回一个对每个值都为真的数组。
假设
- 二进制或序数 —响应变量在二进制逻辑回归中要求为二进制,在序数逻辑回归中要求为序数
- 独立性 —要求观测值相互独立
- 多重共线性-预测变量之间很少或没有多重共线性。
- 线性 —自变量和对数优势的线性
赞成的意见
- 低方差
- 提供概率
- 易于实施
骗局
- 高偏差
包裹
在大多数在线课程中,逻辑回归往往是在线性回归之后教授的内容。虽然通常逻辑回归用于不同领域的回归,但通过将其与阈值相结合,我们能够将其用作非常有用、易于实现的分类器,这证明是在处理分类问题时实现的良好的第一模型。
感谢您花时间阅读这个故事。如果有什么我错过了,说错了,或者你想让我澄清的,请在评论中留下你的回复。另外,如果你想和我联系,我在 LinkedIn 上是最容易联系到的。
[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn
在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)
您可以从这里访问从头开始系列的完整算法:
阅读《走向数据科学》中关于算法的文章。分享概念、想法和…
towardsdatascience.com](https://towardsdatascience.com/tagged/algorithms-from-scratch)
从零开始的算法:朴素贝叶斯分类器
从零开始的算法
从头开始详述和构建朴素贝叶斯分类器

介绍
T 朴素贝叶斯分类器是一种 急切学习 算法,属于基于贝叶斯定理的简单概率分类器家族。
虽然贝叶斯定理(简而言之,是一种在没有联合概率的情况下计算条件概率的原则方法)假设每个输入都依赖于所有其他变量,但为了将其用作分类器,我们删除了这一假设,并认为每个变量都是相互独立的,并将这种用于预测建模的贝叶斯定理简化称为朴素贝叶斯分类器。换句话说,朴素贝叶斯假设类中某个预测值的存在与任何其他预测值的存在无关。这是一个非常强有力的假设,因为预测者在现实世界的数据中不发生相互作用的可能性非常小。
顺便说一下,如果你对渴望学习不熟悉,渴望学习是指在系统的训练过程中,系统旨在构造一个通用的、与输入无关的目标函数的学习方法。相反,像K-最近邻 这样的算法,是一个懒惰的学习者,要等到进行查询之后,才能在训练数据之外进行任何泛化。
本质上,朴素贝叶斯(或白痴贝叶斯)赢得了它的名字,因为每个类的计算被简化以使它们的计算易于处理,然而,分类器证明了自己在许多现实世界的情况下是有效的,无论是二元分类还是多类分类,尽管它的设计简单且假设过于简化。
对于本笔记本中使用的完整代码…
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/kurtispykes/ml-from-scratch/blob/master/naive_bayes.ipynb)
创建模型
如前所述,如果我们要对条件概率分类模型(朴素贝叶斯模型)应用贝叶斯定理,那么我们需要简化计算。
在讨论如何简化模型之前,我将简要介绍边际概率、联合概率和条件概率:
边际概率 —不考虑其他随机变量的事件概率,例如 P(A ),这意味着事件发生的概率。
联合概率 —两个或两个以上同时发生事件的概率,例如 P(A 和 B)或 P(A,B)。
条件概率 —给定一个或多个事件发生的概率,例如 P(A|B)可以表述为给定 B 的概率
关于这些概率的一件很酷的事情是,我们可以用它们来计算彼此。联合概率可以通过使用条件概率来计算,这被称为乘积规则;参见图 1。

图 1:使用条件概率计算联合概率
关于乘积法则的一个有趣的事实是,它是对称的,意味着 P(A,B) = P(B,A)。另一方面,条件概率是不对称的,这意味着 P(A|B)!= P(B|A ),但是我们可以利用联合概率来计算条件概率,见图 2。

图 2:使用联合概率计算条件概率
图 2 有一个问题;计算联合概率通常很困难,所以当我们想要计算条件概率时,我们使用另一种方法。我们使用的另一种方法称为贝叶斯法则或贝叶斯定理,它是通过使用一个条件概率来计算另一个条件来完成的——参见图 3**

图 3:贝叶斯定理——这个等式的逆等式也成立,因此 P(B|A) = P(A|B) * P(B) / P(A)
注:当反向条件概率可用或更容易计算时,我们也可以决定使用替代方法来计算条件概率。
为了给贝叶斯定理中的术语命名,我们必须考虑使用该方程的上下文—参见图 4。

图 4:命名贝叶斯定理的术语
因此,我们可以把贝叶斯定理重述为…

图 5:重述贝叶斯定理
为了将此建模为分类模型,我们这样做…

图 6:用分类模型表示的贝叶斯定理
然而,这个表达式在我们的计算中是一个复杂的原因,因此为了简化它,我们去除了依赖性的假设,并且考虑到每个变量独立,我们简化了我们的分类器。
注意:我们去掉了分母(本例中观察到数据的概率),因为它对于所有计算都是常数。

图 7:朴素贝叶斯分类器
现在你明白了…嗯,不完全是。这个计算是针对每个类标签执行的,但是我们只想知道对于给定的实例最有可能的类。因此,我们必须找到最有可能被选为给定实例的分类的标签;这个决策规则的名字叫做最大后验概率(MAP)——现在你有了朴素贝叶斯分类器。
分块算法
- 将数据按类分段,然后计算每个类中 x 的均值和方差。
- 使用高斯概率密度函数计算概率
- 获取类别概率
- 获得最终预测
实施
我们将使用 iris 数据集,由于该数据集中使用的变量是数值型的,因此我们将构建一个高斯朴素贝叶斯模型。
注:不同的朴素贝叶斯分类器的区别主要在于它们对 P(Xi | y)分布的假设(来源 : Scikit-Learn 朴素贝叶斯)
import numpy as np
import pandas as pdfrom sklearn.datasets import load_iris
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split# loading the data
iris = load_iris()
X, y = iris.data, iris.target# spliting data to train and test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size= 0.2, random_state=1810)
X_train.shape, y_train.shape, X_test.shape, y_test.shape((120, 4), (120,), (30, 4), (30,))# scikit learn implementation
nb = GaussianNB()
nb.fit(X_train, y_train)
sklearn_preds = nb.predict(X_test)print(f"sklearn accuracy:{accuracy_score(y_test, sklearn_preds)}")
print(f"predictions: {sklearn_preds}")sklearn accuracy:1.0
predictions: [0 0 2 2 0 1 0 0 1 1 2 1 2 0 1 2 0 0 0 2 1 2 0 0 0 0 1 1 0 2]
Scikit-Learn 实现在推理上给了我们一个完美的准确度分数,让我们构建自己的模型,看看我们是否可以匹配 Scikit-learn 实现。
我构建了一个效用函数get_params,这样我们就可以为我们的训练数据获取一些参数。
def get_params(X_train, y_train):
"""
Function to get the unique classes, number of classes and number of features in training data
"""
num_examples, num_features = X_train.shape
num_classes = len(np.unique(y_train))
return num_examples, num_features, num_classes# testing utility function
num_examples, num_features, num_classes = get_params(X_train, y_train)
**print**(num_examples, num_features, num_classes)120 4 3
我们的效用函数工作得很好,所以我们可以进行第一步,按类获取统计数据(特别是均值、方差和先验)。
def get_stats_by_class(X_train, y_train, num_examples=num_examples, num_classes=num_classes):
"""
Get stats of dataset by the class
"""
# dictionaries to store stats
class_mean = {}
class_var = {}
class_prior = {}
# loop through each class and get mean, variance and prior by class
for cls in range(num_classes):
X_cls = X_train[y_train == cls]
class_mean[str(cls)] = np.mean(X_cls, axis=0)
class_var[str(cls)] = np.var(X_cls, axis=0)
class_prior[str(cls)] = X_cls.shape[0] / num_examples
return class_mean, class_var, class_prior# output of function
cm, var, cp = get_stats_by_class(X_train, y_train)
cm, var, cp# output of function
cm, var, cp = get_stats_by_class(X_train, y_train)
print(f"mean: {cm}\n\nvariance: {var}\n\npriors: {cp}")mean: {'0': array([5.06111111, 3.48611111, 1.44722222, 0.25833333]), '1': array([5.90952381, 2.80714286, 4.25238095, 1.33809524]), '2': array([6.61904762, 2.97857143, 5.58571429, 2.02142857])}
variance: {'0': array([0.12570988, 0.15564043, 0.0286034 , 0.01243056]), '1': array([0.26324263, 0.08542517, 0.24582766, 0.04045351]), '2': array([0.43678005, 0.10930272, 0.31884354, 0.0802551 ])}
priors: {'0': 0.3, '1': 0.35, '2': 0.35}
我们将从get_params获得的num_classes和num_examples传递给函数,因为它们需要按类分离数据并按类计算先验。既然我们已经有了足够的信息来计算类别概率——嗯,不完全是,我们正在处理连续数据,一个典型的假设是与每个类别相关的连续值按照高斯分布分布(来源 : 维基百科)。因此,我们建立了一个函数来计算密度函数,它将帮助我们计算高斯分布的概率。
def gaussian_density_function(X, mean, std, num_examples=num_examples, num_features=num_features, eps=1e-6):
num_exambles, num_features = X_train.shape
const = -num_features/2 * np.log(2*np.pi) - 0.5 * np.sum(np.log(std + eps))
probs = 0.5 * np.sum(np.power(X - mean, 2)/(std + eps), 1)
return const - probsgaussian_density_function(X_train, cm[str(0)], var[str(0)])array([-4.34046349e+02, -1.59180054e+02, -1.61095055e+02, 9.25593725e-01,
-2.40503860e+02, -4.94829021e+02, -8.44007497e+01, -1.24647713e+02,
-2.85653665e+00, -5.72257925e+02, -3.88046018e+02, -2.24563508e+02,
2.14664687e+00, -6.59682718e+02, -1.42720100e+02, -4.38322421e+02,
-2.27259034e+02, -2.43243607e+02, -2.60192759e+02, -6.69113243e-01,
-2.12744190e+02, -1.96296373e+00, 5.27718947e-01, -8.37591818e+01,
-3.74910393e+02, -4.12550151e+02, -5.26784003e+02, 2.02972576e+00,
-7.15335962e+02, -4.20276820e+02, 1.96012133e+00, -3.00593481e+02,
-2.47461333e+02, -1.60575712e+02, -2.89201209e+02, -2.92885637e+02,
-3.13408398e+02, -3.58425796e+02, -3.91682377e+00, 1.39469746e+00,
-5.96494272e+02, -2.28962605e+02, -3.30798243e+02, -6.31249585e+02,
-2.13727911e+02, -3.30118570e+02, -1.67525014e+02, -1.76565131e+02,
9.43246044e-01, 1.79792264e+00, -5.80893842e+02, -4.89795508e+02,
-1.52006930e+02, -2.23865257e+02, -3.95841849e+00, -2.96494860e+02,
-9.76659579e+01, -3.45123893e+02, -2.61299515e+02, 7.51925529e-01,
-1.57383774e+02, -1.13127846e+02, 6.89240784e-02, -4.32253752e+02,
-2.25822704e+00, -1.95763452e+02, -2.54997829e-01, -1.66303411e+02,
-2.94088881e+02, -1.47028139e+02, -4.89549541e+02, -4.61090964e+02,
1.22387847e+00, -8.22913900e-02, 9.67128415e-01, -2.30042263e+02,
-2.90035079e+00, -2.36569499e+02, 1.42223431e+00, 9.35599166e-01,
-3.74718213e+02, -2.07417873e+02, -4.19130888e+02, 7.79051525e-01,
1.82103882e+00, -2.77364308e+02, 9.64732218e-01, -7.15058948e+01,
-2.82064236e+02, -1.89898997e+02, 9.79605922e-01, -6.24660543e+02,
1.70258877e+00, -3.17104964e-01, -4.23008651e+02, -1.32107552e+00,
-3.09809542e+02, -4.01988565e+02, -2.55855351e+02, -2.25652042e+02,
1.00821726e+00, -2.24154135e+02, 2.07961315e+00, -3.08858104e+02,
-4.95246865e+02, -4.74107852e+02, -5.24258175e+02, -5.26011925e+02,
-3.43520576e+02, -4.59462733e+02, -1.68243666e+02, 1.06990125e+00,
2.04670066e+00, -8.64641201e-01, -3.89431048e+02, -1.00629804e+02,
1.25321722e+00, -5.07813723e+02, -1.27546482e+02, -4.43687565e+02])
这是一个计算类概率的函数…
def class_probabilities(X, class_mean, class_var, class_prior, num_classes=num_classes):
"""
calculate the probability of each class given the data
"""
num_examples = X.shape[0]
probs = np.zeros((num_examples, num_classes))for cls in range(num_classes):
prior = class_prior[str(cls)]
probs_cls = gaussian_density_function(X, class_mean[str(cls)], class_var[str(cls)])
probs[:, cls] = probs_cls + np.log(prior)
return probs
现在我们需要使用 MAP 进行预测,所以让我们将所有这些步骤放在一个预测函数中,并输出最大概率类。
def predict(X_test, X_train, y_train):
num_examples, num_features, num_classes = get_params(X_test, y_train)
class_mean, class_std, class_prior = get_stats_by_class(X_train, y_train)
probs = class_probabilities(X_test, class_mean, class_std, class_prior)
return np.argmax(probs, 1)my_preds = predict(X_test, X_train, y_train)**print**(f"my predictions accuracy:{accuracy_score(y_test, my_preds)}")
**print**(f"predictions: {my_preds}")my predictions accuracy:1.0
predictions: [0 0 2 2 0 1 0 0 1 1 2 1 2 0 1 2 0 0 0 2 1 2 0 0 0 0 1 1 0 2]
作为健全检查…
sklearn_preds == my_preds**array**([ True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True])
饼干就是这样碎的!
赞成的意见
- 需要少量的训练数据来估计必要的参数
- 与复杂的方法相比,速度极快
骗局
- 众所周知是一个糟糕的估计器(在 Scikit-Learn 框架中,
predict_proba的输出没有被太认真对待。 - 独立预测者的假设在现实世界中并不成立(大部分时间)
包裹
现在,您已经了解了朴素贝叶斯分类器以及如何使用 Python 从头开始构建一个分类器。是的,该算法有非常过于简化的假设,但它在许多现实世界的应用中仍然非常有效,如果你想要非常快速的预测,值得一试。
让我们继续 LinkedIn 上的对话…
[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn
在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有两个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)
从零开始的算法:PCA
从零开始的算法
从头开始详述和构建 PCA 算法

图一 : PCA(来源:深度学习。AI Twitter ) —原创者;劳纳克·乔希
介绍
主成分分析(PCA)是卡尔·皮尔逊在 1901 年发明的一种技术,通常用于降低数据的维度,以进行探索性数据分析,也用于构建预测模型时的特征选择——下面将详细介绍特征选择和数据可视化。
选择有用功能的初学者指南
towardsdatascience.com](/getting-started-with-feature-selection-3ecfb4957fd4) [## 有效的数据可视化
构建有效的数据可视化的技巧可以简化为 3 个简单的步骤
towardsdatascience.com](/effective-data-visualization-ef30ae560961)
通常,当我们谈到 PCA 时,我们指的是计算主成分,然后使用这些主成分对数据进行基变换的过程。用人类的话来说,我们会说 PCA 允许我们降低数据的维数。
更多从零开始的算法,可以访问“ 从零开始的算法系列 ”。
共享概念、想法和代码的媒体出版物。
towardsdatascience.com](https://towardsdatascience.com)
创建模型
正如我们之前提到的,PCA 通常用于降维。这是通过将每个数据点投影到前几个分量来实现的,这样我们最终得到的是低维数据,但保留了尽可能多的数据方差。
关于这一点,需要知道两件事:
注:以下列表摘自维基百科(来源 : 维基百科)
- 第一主分量可以等效地定义为使投影数据的方差最大化的方向
i^th主分量可以取为与第一个i - 1主分量正交的方向,其最大化投影数据的方差。
但是主要成分是什么呢?很棒的问题!主成分是数据协方差矩阵的特征向量。因此,我们不必深入研究数学元素,观看接下来的两个视频可以更好地理解特征向量、特征值和协方差矩阵。
特征向量 →(线性变换的)是一个非零向量,当对其应用线性变换时,它会改变一个标量因子。
特征值 →特征向量缩放的因子
协方差矩阵 →协方差矩阵是一个方阵,给出给定随机向量的每对元素之间的协方差。任何协方差矩阵都是对称正半定的,其主对角线包含方差(即每个元素与其自身的协方差)(来源 : 维基百科)。
为了执行 PCA,我们应该从数据的协方差矩阵中获得特征向量和特征值。为了做到这一点,我们的意思是标准化我们的数据,然后获得协方差矩阵,最后执行奇异值分解(SVD)。

图 2 :获取一组不相关的特征(图片由作者提供)
接下来,我们必须使用从上一步任务中检索到的特征向量和特征值,将我们的数据投影到一组新的特征。为此,我们取我们的特征和我们的特征向量的前 n 列的点积。如果我们想把数据的维数减少到 2 维,我们将使用特征向量的前两列。

图 3 :将特征数据投影到一组新的特征。 U 表示特征向量,S 表示特征值(图片由作者提供)
我们现在准备实现 PCA,我们将使用它来可视化虹膜数据集。
分块算法
- 获取一组不相关的特征
- 将数据投影到新要素
实施
让我们从使用sklearn框架对 iris 数据集执行 PCA 开始…
图 4 : Sklearn 实现 PCA
对于我们自己的实施,我们从获取不相关的特征开始,为此我们遵循图 2 中的步骤。
均值归一化数据→获取协方差矩阵→执行奇异值分解
图 5 :步骤 1——获取不相关的特征。我的实现
下一步是将数据投影到一组新的特征上——参见图 3。
图 6 :将数据投影到一组新的特征上
现在你知道了!
总结
PCA 是降低数据维度的一种很好的方法,这些数据可能出于不同的原因而需要,即在构建预测模型时,2 维数据用于数据可视化,或 n 维数据用于特征选择。在这篇文章中,我们还学习了特征向量和特征值,以及它们在将高维数据投射到 n 维中的作用。
这可能是我写过的最难的帖子,我非常希望听到反馈,所以请留下回复或在 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)
从头开始的算法:支持向量机
从零开始的算法
从头开始详述和构建支持向量机

支持向量机是一种流行的算法,能够执行线性或非线性分类和回归,在深度学习兴起之前,由于令人兴奋的内核技巧,支持向量机是一个热门话题——如果这个术语现在对你没有意义,不要担心。在这篇文章结束时,你会对支持向量机的直觉有很好的理解,在线性支持向量机下发生了什么,以及如何用 Python 实现一个支持向量机。
要从头开始查看完整的 算法 系列,请点击下面的链接。
阅读《走向数据科学》中关于算法的文章。分享概念、想法和…
towardsdatascience.com](https://towardsdatascience.com/tagged/algorithms-from-scratch)
直觉
在分类问题中,SVM 的目标是拟合两个类别之间的最大可能差值。相反,回归任务改变了分类任务的目标,并试图在裕度内适应尽可能多的实例——我们将首先关注分类。
如果我们只关注数据的极端值(位于聚类边缘的观察值),并且我们将阈值定义为两个极端值之间的中点,那么我们就剩下了一个用于分隔两个类的裕度,这通常被称为超平面。当我们应用一个给我们最大余量的阈值(意味着我们严格确保没有实例落在余量内)来进行分类时,这被称为硬余量分类(一些文本称之为最大余量分类)。
当详细说明硬利润分类时,直观地看到发生了什么总是有帮助的,因此图 2 是硬利润分类的一个例子。为此,我们将使用来自 scikit 的虹膜数据集-学习和实用函数plot_svm(),您可以在下面的 github 链接上获得完整代码。
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/kurtispykes/ml-from-scratch/blob/master/support_vector_machine.ipynb)
注意:这个故事是使用 python 包
*jupyter_to_medium*直接从 jupyter 笔记本上写的——要了解关于这个包 的更多信息,请点击这里——github 上提交的版本是初稿,因此你可能会注意到这篇文章的一些改动。
import pandas as pd
import numpy as np
from sklearn.svm import LinearSVC
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
%matplotlib inline# store the data
iris = load_iris()
# convert to DataFrame
df = pd.DataFrame(data=iris.data,
columns= iris.feature_names)
# store mapping of targets and target names
target_dict = dict(zip(set(iris.target), iris.target_names))
# add the target labels and the feature names
df["target"] = iris.target
df["target_names"] = df.target.map(target_dict)
# view the data
df.tail()

图 1:原始数据集
# setting X and y
X = df.query("target_names == 'setosa' or target_names == 'versicolor'").loc[:, "petal length (cm)":"petal width (cm)"]
y = df.query("target_names == 'setosa' or target_names == 'versicolor'").loc[:, "target"]
# fit the model with hard margin (Large C parameter)
svc = LinearSVC(loss="hinge", C=1000)
svc.fit(X, y)
plot_svm()

图 2:SVM 的可视化决策边界
图 2 显示了线性 SVM 如何使用硬边界分类来确保没有实例落入边界内。尽管这对于我们当前的场景来说看起来不错,但我们必须小心考虑执行硬利润分类带来的陷阱:
- 对异常值非常敏感
- 只有当类是线性可分的时候它才起作用
处理异常值和非线性数据
硬边界分类的一种更灵活的替代方法是软边界分类,这是一种很好的解决方案,可以克服上面列出的硬边界分类中的缺陷,主要是解决对异常值的敏感性问题。当我们允许存在一些错误分类时(意味着一些负面观察可能被分类为正面,反之亦然),从阈值到观察的距离被称为 软余量 。在软裕度分类中,我们的目标是在最大化裕度大小和限制裕度中的违规数量(落在裕度中的观察数量)之间实现良好的平衡。
是的,线性 SVM 分类器(硬边界和软边界)非常有效,并且在许多情况下工作得非常好,但是当数据集不是线性可分的时候,就像许多数据集经常出现的情况一样,更好的解决方案是利用支持向量机内核技巧(一旦你理解了内核技巧,你可能会注意到它不是支持向量机独有的)。内核技巧将非线性可分离数据映射到更高维度,然后使用超平面来分离类别。让这个技巧如此令人兴奋的是,将数据映射到更高的维度实际上并没有增加新的功能,但我们仍然得到了相同的结果,就好像我们做了一样。因为我们不需要在数据中加入新的特征,我们的模型计算效率更高,效果也一样好。
你会在下面看到这种现象的一个例子。
术语
- 决策边界:将数据集分成两类的超平面
- 支持向量:观察值位于聚类的边缘(离分离超平面最近)。
- 硬边界:当我们严格规定所有观察值都不在边界内时
- 软边界:当我们允许一些错误分类时。我们试图找到一个平衡点,既保持尽可能大的差值,又限制违规次数(偏差/方差权衡)
from sklearn.datasets import make_moons
from mlxtend.plotting import plot_decision_regions
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC# loading the data
X, y = make_moons(noise=0.3, random_state=0)
# scale features
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# fit the model with polynomial kernel
svc_clf = SVC(kernel="poly", degree=3, C=5, coef0=1)
svc_clf.fit(X_scaled, y)
# plotting the decision regions
plt.figure(figsize=(10, 5))
plot_decision_regions(X_scaled, y, clf=svc_clf)
plt.show()

图 3:应用于非线性数据的内核技巧
注意:我们对这个数据集应用了一个多项式核,但是 RBF 也是一个非常受欢迎的核,应用于许多机器学习问题,并且经常在数据不是线性可分时用作默认核。
创建模型
既然我们已经对 SVM 正在做的事情建立了概念上的理解,让我们来理解在这个模型的引擎盖下正在发生什么。线性 SVM 分类器计算决策函数w.T * x + b并预测结果为肯定的肯定类别,否则为否定类别。训练线性 SVM 分类器意味着找到使边缘尽可能宽的值w和b,同时避免边缘违规(硬边缘分类)或限制它们(软边缘分类)

图 4:线性 SVM 分类器预测
决策函数的斜率等于权重向量的范数,因此为了实现最大可能的裕度,我们希望最小化权重向量的范数。但是,我们有办法实现硬利润分类和软利润分类。
硬边界优化问题如下:

图 5:线性 SVM(硬边界分类器)目标
和软利润:

图 6:线性 SVM(软间隔分类器)目标;请注意,为了实现软余量,我们为每个实例添加了一个松弛变量(zeta ≥ 0),该变量测量每个实例允许违反余量的程度。
履行
注意:对于这个实现,我将进行硬边界分类,但是进一步的工作将包括软边界的 Python 实现和对不同数据集执行的内核技巧,包括基于回归的任务——要获得这些帖子的通知,您可以在 Github 上关注我。
from sklearn.datasets.samples_generator import make_blobs
# generating a dataset
X, y = make_blobs(n_samples=50, n_features=2, centers=2, cluster_std=1.05, random_state=23)def initialize_param(X):
"""
Initializing the weight vector and bias
"""
_, n_features = X.shape
w = np.zeros(n_features)
b = 0
return w, bdef optimization(X, y, learning_rate=0.001, lambd=0.01, n_iters=1000):
"""
finding value of w and b that make the margin as large as possible while
avoiding violations (Hard margin classification)
"""
t = np.where(y <= 0, -1, 1)
w, b = initialize_param(X)
for _ in range(n_iters):
for idx, x_i in enumerate(X):
condition = t[idx] * (np.dot(x_i, w) + b) >= 1
if condition:
w -= learning_rate * (2 * lambd * w)
else:
w -= learning_rate * (2 * lambd * w - np.dot(x_i, t[idx]))
b -= learning_rate * t[idx]
return w, bw, b = gradient_descent(X, y)def predict(X, w, b):
"""
classify examples
"""
decision = np.dot(X, w) + b
return np.sign(decision)# my implementation visualization
visualize_svm()
# convert X to DataFrame to easily copy code
X = pd.DataFrame(data=X,
columns= ["x1", "x2"])
# fit the model with hard margin (Large C parameter)
svc = LinearSVC(loss="hinge", C=1000)
svc.fit(X, y)
# sklearn implementation visualization
plot_svm()


赞成的意见
- 非常好的线性分类器,因为它找到了最佳决策边界(在硬边界分类意义上)
- 易于转换成非线性模型
骗局
- 不适合大型数据集
包裹
SVM 是一种很难编码的算法,它很好地提醒了我们为什么应该感谢机器学习库,让我们可以用几行代码实现它们。在这篇文章中,我没有深入到支持向量机的全部细节,仍然有相当多的空白,你可能想要阅读,例如计算支持向量机和经验风险最小化。
此外,可能值得观看吴恩达关于支持向量机的讲座— 点击此处
感谢您花时间通读这个故事(因为它被称为媒体)。现在,您对支持向量机、SVM 下发生的事情以及如何用 Python 编写硬边界分类器有了很好的概念性理解。如果你想和我联系,我在 LinkedIn 上很容易找到。
[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn
在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)
算法、迭代和洗衣:我们能把它们联系起来吗?
帮助您更好地理解代码的简单解释

简·安东宁·科拉尔在 Unsplash 上拍摄的照片
我坚信,如果你能理解洗衣,你就能理解算法和多级迭代。
现在,我必须指出,洗衣服是我每天都要做的事情之一。我和它邪恶的表亲,熨衣服,过得特别艰难。对我来说,这几乎是不可能的,这就是为什么我很高兴我们正在进入北半球的毛衣天气(当你穿着一件不那么皱的毛衣时,没有人会注意到一件皱的衬衫)。
在寻找洗衣艺术和科学的动机时,我开始意识到它的工作有点像算法和迭代,更好的是,如果我们能让自己像对待那些数据科学概念一样看待洗衣,也许我们可以做得更好。因此,我尝试用一些常识来解决一个非常常见的数据科学问题。
披露:在我们开始之前,请记住,我在这里的目标不是给出算法和迭代的完整技术解释。如果那是你要找的,这里不适合你。有大量的文章/书籍/视频可以提供这方面的信息,所以我恳请你不要在这里浪费时间。然而,如果你对数据科学和日常生活之间意想不到的联系感兴趣,请继续阅读。
好了,现在我们已经解决了法律上的问题,算法就是“用来解决问题的一组指令”。另一方面,迭代是“一次又一次做某事的过程”。好的,这很好,但问题是这些只是教科书上的定义,(根据定义)这些在现实生活中几乎没有用处。它们往往只是抽象的概念,大学课程喜欢把它们扔给你,这样他们就可以收取一大笔钱。所以让我们转而去洗衣服吧。
我想让你想象你已经很久没有洗衣服了,拖延症已经到了极限。你必须面对严酷的现实,你不能再用同一件衬衫出门,你必须照顾自己的肮脏,所以你把所有的衬衫扔在一个巨大的篮子里。我还想让你想象一下,你有一台神奇的电脑为你洗衣服(我愿意为此花大价钱),你用它来处理你危险堆积的脏衬衫。
第一个例子
让我们首先清楚地定义我们在这里有什么。假设你只有绿色、蓝色和黄色的衬衫:

作者图片
而且你想洗、干、烫它们,所以你的神奇洗衣电脑的基本指令是:

作者图片
很直接,是吧?但问题是,你想让你的洗衣过程井井有条,所以你想按颜色洗、干、熨衬衫。从概念上讲,这是你会指示你的神奇计算机做的事情:

作者图片
你就完了。你已经成功地按颜色洗完了所有的衬衫。你所做的就是在三个独立的迭代中执行指令,每种颜色一次。
第二个例子
好的,现在我想让你认为你也有有袖和无袖的衬衫:

作者图片
坚持我们在前面的例子中所说的,这些衬衫可以是绿色,蓝色或黄色。还是那句话,作为一个非常有条理的洗衣人,你想按颜色洗你的衬衫,但你也想先洗袖子再洗无袖的。这些是你的神奇电脑的说明:

作者图片
现在,请注意,我们只洗了我们的绿色衬衫(有袖和无袖),但我们还没有接触其他颜色。换句话说,当我们迭代套筒变量时,我们保持圆“固定”在绿色正方形上。为了完成这项工作,我们对蓝衫重复这个过程:

作者图片
再次注意,当我们迭代 sleeve 变量时,圆圈是如何“固定”在蓝色方块上的。最后,我们以完全相同的方式处理黄色衬衫:

作者图片
仅此而已。基本上,您以下面的方式进行了两个不同“级别”的迭代:
- 您在遍历底部 iterable 的对象时,在顶部 iterable 的第一个对象(绿色)上固定了圆圈,并在每个对象上执行指令。
- 然后,您只需切换到顶部 iterable 的第二个元素(蓝色),并遍历底部元素中的对象,再次执行指令。
- 最后,重复相同的过程,但是这次将圆固定在顶部 iterable 的第三个对象(黄色)上。
就这样,你洗完了衣服。
第三个例子
正因为迭代和算法如此有趣,让我们假设你也有带纽扣和不带纽扣的衬衫,这可以是三种颜色中的任何一种,可以有袖子也可以没有袖子(就我个人而言,我从未见过带纽扣的无袖衬衫,但嘿,这里没有判断)。
那么,让我们看看这次的指令是什么样的:

作者图片
如果你一直跟着这里,你会意识到我们只关心我们的绿衬衫。所以我们对蓝色的重复这个过程:

作者图片
最后是黄色的:

作者图片
修复圆圈的逻辑同样适用于此,只是我们现在讨论的是三个级别,而不是两个。实际上,这是这篇文章的要点,所以让我们扩展一下,称之为迭代和算法的‘洗衣原则’。
迭代和算法的“洗衣原则”

里卡多·戈麦斯·安吉尔在 Unsplash 上的照片
那么,为什么你在过去的几分钟里一直在看一篇关于洗衣的文章呢?
事实证明,上面的例子有助于使迭代和算法更容易理解,因为它们揭示了一个简单但非常有用的想法,我们从现在开始称之为洗衣原理。
正如我们在一开始所看到的,算法只是一组指令,它们被传递给计算机来解决一个特定的问题。但是这些指令的执行顺序使得算法如此有用。正如我们在上面看到的,指令是按照特定的顺序执行的,这允许以一种结构化的有效方式处理问题,这就是迭代思维发挥作用的地方。
洗衣原则:“自下而上”每天都胜过“自上而下”。
这里的主要思想是,你必须总是自下而上地考虑多级迭代。让我们从三个层次来看这个问题,就像我们的洗衣例子一样。除了最后一层,所有的层都固定在它们的第一个对象上,最后一层是你将按照你的指令移动的那一层。让我们称这个过程为:

作者图片
一旦最后一层上的所有对象都用完了,您就可以激活中间层上的迭代,并对那里的每个对象重复过程 A。我们将用字母 B 来命名这个过程,并且记住这是一个复合过程。换句话说,流程 B 包括:
- 对最后一级(进程 A)中的所有对象执行指令,中间一级有一个固定对象。
- 移动到中间层的下一个对象并重复过程 a。
- 这样做,直到中间级别的所有对象都用完为止。

作者图片
一旦中间层的所有对象都用完了,就激活顶层的迭代,并对那里的每个对象重复复合过程 B:

作者图片
如果你有更多的层次,那么,你将永远继续下去(或者直到你的迭代层次用完)。
值得注意的是,这些例子非常简单,目的是清楚地传达想法。和往常一样,现实生活没有那么温和,所以当你试图理解别人的代码时,你肯定仍然会时不时地抓狂。例如,一些代码片段将只在特定的迭代级别上执行指令(与我们的示例相反,在我们的示例中,指令总是在底层执行),并且一些迭代可能相当长。然而,原则是相同的。
衣物包装
我们在这里学到了什么?嗯,几件事:
- 洗衣服很烂,但最终还是要洗(冬天熨烫更容易躲闪)。
- 多级迭代从下往上看更容易理解(洗衣原理)。
- 现实生活中的代码比我们有时希望的要复杂得多,但是对迭代如何工作有一个清晰的想法会让你脚踏实地。
所以下次当你试图理解 Kaggle 上的一些密集代码时,你应该庆幸至少你没有在洗衣服。
外星人、费米悖论和黑暗森林理论:博弈论观点

银河系。来源:亚历克·法瓦利,转自 Unsplash (CC0)。
德雷克方程
20 世纪 60 年代,时任康奈尔大学天文学教授的弗兰克·德雷克提出了 T4·德雷克方程。这是对银河系中智慧文明数量的概率估计。正如他所定义的,智慧文明是一种先进到足以与其他地外文明交流的文明。
德雷克的方程式不是试图精确量化智慧文明,而是唤起人类对外星人存在的好奇心。如果 60 年后你还在读这篇文章,那么德雷克已经成功了。
在这篇文章中,我们讨论了人类寻找外星人的尝试。我们评论费米悖论,这是宇宙的浩瀚和缺乏任何外星生命证据之间的明显矛盾。然后,我们解释了取自我与人合著的调和这一悖论的一篇课堂论文的博弈论模型,以及我们是否应该尝试接触外星生命。所以,系好安全带,准备在社会宇宙的海洋中漫游吧。
我们生活在一个巨大的宇宙中,那里的星星比地球上的沙粒还要多。许多恒星都有行星围绕它们旋转。甚至还有一份由阿雷西博的波多黎各大学保存的潜在宜居系外行星清单。德雷克方程表明,这种外星人存在的可能性很高,不容忽视。排除它们已经在这里的可能,我们必须问自己为什么在地球上没有发现它们。我们当然尽力了。
在 20 世纪 70 年代,我们试图越来越多地了解这些文明。1972 年,我们向木星发射了一艘宇宙飞船——先驱者 10 号。当你阅读这篇文章时,这艘宇宙飞船正朝着金牛座前进,在最终离开我们的太阳系之前,终于给了外星人一个捕捉它的机会!如果它们存在,并且它们确实感染了,我们已经发送了一个铭牌(如下),描述我们的长相和我们生活的世界的象征。

该牌匾在左上角有一个中性氢的超精细跃迁,一个男人和一个女人的形象,太阳和银河系的地标,底部是太阳系,以及人类身后的飞船剪影。来源:维基媒体常用。
1974 年,我们发送了阿雷西博信息,这是由著名的科学传播者卡尔·萨根和弗兰克·德雷克创造的星际调频无线电信息。这是技术成就的展示,而不是接触外星人,但这并没有给我们,阴谋论者,足够的数据来工作。

阿雷西博信息描述了当时的科学技术:白色的是数字 1 到 10。紫色表示组成 DNA 的元素的原子序数:氢、碳、氮、氧和磷。绿色、白色和蓝色的 DNA 结构和分子式。红色的是人类的图形,白色的是人类的数量。黄色是太阳系的图形,表示信息来自哪个行星。紫色的是阿雷西博射电望远镜和发射天线盘的照片。来源:维基媒体常用。
这种星际调频无线电信息包含了许多假设。FM 代表频率调制,对于外星人来说,这种技术可能太先进(或者不够先进)。谁知道呢?无线电信号也随着进入宇宙而衰减,但是我们不能排除外星人拥有敏感的技术来发现每一个微弱的信号,对吗?

卡尔·萨根是天文学家、宇宙学家和科学传播者。来源:维基媒体常用。
那绝不是我们最后一次试图联系外星人并泄露我们所有的秘密!1977 年,卡尔·萨根编辑了自然的声音和图像,以描绘地球上生命和文化的多样性,并将其载入旅行者号宇宙飞船的黄金唱片。截至 2004 年,旅行者 1 号已经离开了我们的太阳系,进入了星际空间,即恒星之间的空间,终于给了外星人一个了解我们的机会。美国宇航局于 2015 年 7 月将该唱片的音频内容上传至 SoundCloud。是时候了!

这些图像包括植物、昆虫、动物、人类和风景。他们展示了文化的各个部分,如博物馆、机场、比赛和交通。其他图像显示了像太阳系和 DNA 这样的科学发现。这些声音包括用 55 种语言表达的问候和从巴赫、莫扎特到贝多芬和斯特拉文斯基的精选音乐。自然声音包括海浪声、风声、雷声和黑猩猩的声音。这张唱片还包含了莫尔斯电码的励志信息。来源:维基媒体常用。
在这一点上,你可能认为这是一种单方面的关系;我们一直在联系,但是没有任何回复。但是在 1977 年夏天,这一切都要改变了。俄亥俄州立大学大耳射电望远镜的科学家们收到了“哇!来自人马座方向的信号。这个信号的特别之处在于它是一个强有力的信号。好像我们注定要得到这个。也许外星人用他们的语言打招呼?

费米悖论
恩利克·费密,核时代的建筑师,1938 年诺贝尔物理学奖得主,涉足宇宙学。在一篇关于宇宙辐射起源的论文中,费米引入了假设的外星生命概率和我们没有收到任何联系的事实之间的矛盾。这个矛盾后来被称为费米悖论。

恩利克·费密是一位天才物理学家,在统计力学、量子理论、核物理学和粒子物理学方面都有重大贡献。来源:维基媒体常用。
既然我们已经介绍了德雷克方程、费米悖论和我们与外星人交流的尝试,让我们探索一下为什么同样聪明的文明避免了交流。
慈欣的前提
尽管对费米悖论有大量的假设解释,我们还是讨论了黑暗森林理论,并将其建模为一个具有不完全信息的序列博弈。黑暗森林理论是由中国科幻作家刘在他的三部曲《地球往事追忆》中描述的
“宇宙是一片黑暗的森林。每个文明都是一个武装的猎人,像幽灵一样在树林中潜行,轻轻地推开阻挡道路的树枝,试图无声无息地行走。连呼吸都是用心做的。猎人必须小心,因为森林里到处都是像他一样的隐形猎人。如果他找到了另一种生活——另一个猎人、天使或恶魔,一个蹒跚老人的娇弱婴儿,一个仙女或半神——他只能做一件事:开火并消灭他们。”
黑暗森林理论指出,我们的星系确实包含德雷克方程中描述的丰富的文明。这些文明仍然有意放弃与其他文明的交流,因为害怕其他文明会摧毁它们。该理论还指出,没有实践这种谨慎的文明已经在这种情况下被摧毁了。
位于加州山景城的搜寻地外文明研究所(SETI) ,以前是一个政府机构,现在是一个非营利组织,认为这个理论并非不可信。SETI 社区的官方政策是只收集信息,不回应任何信号或外星智慧的证据,因为担心这可能是地球生命的终结。
在这里,我们用基于非正式激励的推理来验证慈欣的结论,从两个公理开始:
- 任何特定文明的目标都是生存。
- 文明不断发展壮大,但宇宙中的资源是有限的。
鉴于这些公理,以及宇宙的物理性质,即恒星之间的距离非常遥远,文明之间的交流最初会以几十年到几百年的极慢速度进行,因为光速限制了我们。慈欣描述了任何两种文明之间产生的“怀疑链”,因为它们无法自信地评估对方的真实意图或潜在威胁。当一个文明已经收集了足够的信息来考虑另一个不可协商的时候,另一个文明可能已经开始摧毁他们了。
此外,由于一个文明可能会经历指数级和不可预测的技术进步速度,让技术不太先进的文明——因此威胁较小的文明独自存在不一定是安全的选择。即使一个文明的技术进步从未超过另一个文明,它也可以向其他文明传播关于该文明的信息,而这些文明本身可能在技术上更先进,并决定摧毁它。
黑暗森林理论的博弈论解释
我们用两个场景来解释黑暗森林理论,然后我们进一步推广它们,得到一个忠实于黑暗森林理论的博弈论模型。
第一个场景
两个不同星球上的两个文明已经知道彼此的存在。他们都有足够的技术来摧毁对方,这样做可以让他们获得额外的资源。
从数学上讲,被摧毁的收益是-inf,什么都不做的收益是零。然而,摧毁另一个文明的回报是某个数字θ,其中θ> 0,因为宇宙中的一些有限资源现在已经变得可用。这些新释放的资源允许毁灭者使用它们来扩张,服务于慈欣的第二公理。
因此,第一个场景是一个扩展形式的游戏,有两个回合和以下属性:
- 有两种文明(C1 和 C2)相互了解。
- 首先轮到 C1,然后轮到 C2。
- 每个文明都有同样的两种可能的行动:毁灭(对方文明)或者什么都不做。

很明显,C1 的优势策略和子博弈完美是摧毁 C2。通过选择破坏行动,C1 确保了收益θ>0。如果 C1 选择“什么都不做”,C1 将任由 C2 摆布。使用逆向归纳法,“毁灭”是 C1 唯一安全的选择。
推论:如果一个文明能够毁灭另一个文明,它就会。
第二种场景
一个文明可以向其他文明广播自己的存在。第二个场景是一个扩展形式的游戏,有两个回合,具有以下属性:
- 有两种文明(C1 和 C2)彼此并不了解。
- 首先轮到 C1,然后轮到 C2。
- 每个文明都有同样的三种可能的行动:
- 摧毁一个文明:这个行动只能针对那些知道他们存在的文明。
- 广播:让其他文明知道它的存在。
- 什么都不做。

请注意,C2 不能摧毁一个它没有听说过的文明。
C1 什么都不做是最优策略和子博弈。广播再次将 C1 置于 C2 的控制之下。通过逆向归纳,什么都不做是 C1 唯一安全的选择。
推论:一个文明永远不会与一个能毁灭它的文明分享关于它存在的信息。
黑暗森林理论
黑暗森林理论建立在前面的场景之上,并有更多的概括:
- 这些游戏会随着时间无限重复。
- 文明很多(两个以上)。
- 随着时间的推移,技术在某种程度上是随机增长的。
在重复的游戏中,文明 A 不能让文明 B 活下来,仅仅是因为文明 B 在未来的一个回合中,如果它的科技水平提高了,就可以消灭文明 A。这与第一种情况密切相关。
文明也可以向更强大的文明广播其他文明的存在信息,威胁它们被启示的任何其他文明摧毁启示的文明。这使得任何文明都没有动力与任何其他文明分享其存在的知识,无论它在技术进步方面更弱还是更强。这与第二种情况密切相关。
很明显,摧毁任何已知的文明,并且因为害怕被更强大的文明甚至是更弱小的文明摧毁而不分享存在信息,是帕累托最优的,甚至是纳什均衡的。我们也可以更进一步说,共享它们存在的文明被毁灭了。
在广阔的宇宙中不交朋友听起来可能有点沮丧,有点反社会。然而,我们对其他星球和系统知之甚少,在缺乏共同语言和理解的情况下,在怀疑链的存在下,保持沉默或面临毁灭是有道理的!
这篇文章最初发表在 ProjectNash 上。
在继续教育中使用数据分析协调供需关系

背景
继续教育提供者越来越关注教育供应与当地雇主对技能和资格的需求以及当地经济需求之间的一致性,原因有很多。
新的 Ofsted 教育检查框架(EIF)将重点放在教育的目的、实施和影响上,根据 FE News 课程目的,可以向[教育]计划和雇主定制。
政府的继续教育劳动力战略给出了一套战略优先事项,其中“教师和培训者的数量和质量”是第一优先事项,“对雇主需求的反应”是第二优先事项。
最后,商业公司通常会考虑商品和服务的供给与需求,以便为定价和生产水平的决策提供信息,在这方面,继续教育提供商与商业公司有许多相似之处。
挑战
获取劳动力市场情报(LMI)数据
提供商可以通过多种方式加快获取经济数据,例如使用来自 https://www.economicmodeling.com/ EMSI()的优秀分析师工具。

作者图片(www.emsieconomicmodeling.com 截图)
这种订阅服务以可理解的格式提供了对相关数据综合的快速访问,但这仅仅是获取与供需匹配相关的情报和知识的第一步。
供应和需求用不同的单位表示
教育供给用“SSA”或“学科领域”代码表示(例如 SSA2 42 是“制造技术”),而雇主需求用“SOC”或“标准职业代码”表示(例如 SOC1 是“经理、董事和高级官员”)。
为了在供给和需求之间进行任何比较,它们都必须用一个共同的单位来表示,这是复杂的,因为没有清晰的映射。例如,SSA2 代码“11”有 7 个子分类。其中 6 个映射到 SOC1 代码“2”,一个映射到 SOC1 代码“3”。
涉及权重的复杂转换需要具备有效转换所需的数据分析和数据科学能力。
一旦完成这一步,供需之间的比较就可以可视化,如下例所示

作者图片
供求模型有几个相互冲突的输入
我最近开发了下面的模型,以帮助可视化供求之间的复杂相互作用,并解释在考虑战略和战术课程设计时,什么因素影响继续教育学院面临的设计选择,该模型强调了几个挑战

作者图片
学生是这项服务的顾客,但他们并不为此付费(在 16-18 岁的情况下),而是由政府付费。这就是 EMSI 高级经济学家 Duncan Brown 向我描述的第三方支付问题,它在供求动态中制造了复杂性。
最终有需求的雇主也不为产品/服务支付任何费用(在 16-18 岁的情况下也是如此),也许更能说明问题的是,是其他利益相关者,如奖励组织,广泛决定课程内容和标准,而不是雇主增加了供求关系的复杂性。
16-18 岁离开教育进入劳动力市场通常是在职业阶梯的第一级。直到员工在职业生涯中取得进步,他们所受教育的全部影响才会被意识到,因此在商品的生产(受过教育的学生)和服务的消费(高技能和多产的员工)之间可能会有很长的延迟。
这种模式的另一个复杂性是,学生渴望的教育和技能可能与雇主和经济需要的不一致,这进一步增加了复杂性。
这是一个延迟影响的例子,同样重要的是要认识到,教育提供者只是一个经济体新增劳动力的来源之一。其他人是流动的现有工人、在职雇员的技能提高和进入经济的工人(例如季节性农场工人)。
该模型将“历史课程设计”作为第一个输入,这表明大学将有一个强大的拉力来推动现有课程向前发展,而不是做出根本的改变来反映需求的变化。大学将在员工和资本资源方面进行大量投资,而供应转移是耗时、复杂和昂贵的,因此与需求的匹配可能会逐步进行。
EMSI 大学高级经济学家 Duncan Brown 向我描述了最后一种复杂性,即教育是一种“信用商品”。不像一罐可以品尝的豆子或者一辆可以试驾的汽车,教育的影响无法被消费者直接、即时地评价。这有助于教育机构品牌的重大影响,特别是在高等教育领域,这在许多继续教育提供者的交付中占很大比例。
结论

扎克·卢塞罗在 Unsplash 上的照片
要点
继续教育的供需协调是复杂的、多方面的,但是有许多原因可以解释为什么 FE 学院越来越需要根据当地雇主和经济需求来调整他们的教学,并且有一些方法可以让提供者开始分解这个复杂的任务
数据分析和数据科学是关键推动因素。有大量的数据,包括私有、公共和订阅数据集,可以开发成信息、情报和知识。
与其他区域提供者的合作也很重要。继续教育学院不倾向于彼此直接竞争,因此,如果通过合作而不是孤立地完成,获取、处理和解释数据将会更快、更准确。
劳动力市场情报(LMI)数据只是一个方面。其他数据,如历史学习者行为、进度数据、人口统计数据、旅行距离等。所有人都扮演着重要的角色,需要许多不同的“镜头”来构建整体画面。
外部利益相关者关系也很关键。与当地企业合作伙伴、理事会和其他机构的关系是建立战略情报的必要条件。例如,世界上最好的数据模型也无法知道,像亚马逊(Amazon)这样的大型企业是否将建立一个新的本地履行中心,从而扰乱本地劳动力市场,但强大的外部利益相关者关系却能做到。
提供者应努力不断提高他们对供求的理解,并确保可以收集情报,然后嵌入到战略课程设计和规划流程的各个方面。
一锤定音
关于数据分析和数据科学,我最喜欢的两句名言是
"只有当我们收集的数据能够告知并激励那些有能力做出改变的人,事情才能得以完成"(迈克·施默克博士)
还有…
如果你折磨数据足够长的时间,它会承认任何事情
在这两个极端之间,有必要支持教育领导者理解和采纳数据模型提供的有见地但往往复杂的信息,并根据结论采取行动,同时避免过度检查这些模型或过度依赖直觉可能带来的任何过度自信的偏见。
感谢您的阅读!
如果你喜欢读这篇文章,为什么不看看我在 https://grahamharrison-86487.medium.com/的其他文章呢?
此外,我很乐意听到您对这篇文章、我的任何其他文章或任何与数据科学和数据分析相关的内容的看法。
如果你想联系我讨论这些话题,请在 LinkedIn 上找我—https://www.linkedin.com/in/grahamharrison1或者发电子邮件到ghar rison @ Lincoln college . AC . uk。
围绕数据操作协调您的分析师和数据科学家
SQL 优先的方法带来了巨大的好处
根据最近由 Dimensional Research 进行的一项调查,只有 50%的数据分析师的时间真正用于分析数据。另一半花在什么上了?数据清理——在你深入研究数据科学之前必须做的单调乏味的重复性工作。我说的是重复数据删除、模糊匹配、替换无效字符,基本上就是为了让数据更容易理解和处理而需要做的所有数据争论和处理。
通常,数据操作有两种方式,每种方式都有优点和缺点。第一种方法主要依赖于 SQL,它非常适合于执行连接、联合和重复数据删除,这些是数据清理的基础。对于 SQL 无法执行的特定操作,例如从非结构化文本中提取字数,您只需嵌入用通用编程语言(通常是 Python)编写的用户定义函数(UDF)。
第二种方法使用通用编程语言,如 Python 或 Scala,作为处理数据的“入口点”。您将在 SQL 中执行的操作(如连接)由 Pandas 等数据框库提供。许多数据科学家自然倾向于这种方法,因为他们对 Python 或 Scala 有更多的经验,并且他们认为 SQL 主要是业务分析师的次要工具。然而,他们错过了 SQL 优先方法的一些巨大优势:
- 最常见的数据清理操作会产生更简单的 SQL 代码。代码越简单,别人越容易理解,你越难出错;
- SQL 在数据分析师中无处不在,所以更容易与分析师共享代码;
- 与 Python 或 Scala 相比,招聘 SQL 专家更容易。
我刚刚描述的这些好处是“以人为中心的”,但是还有一个非常重要的基础设施好处。大规模并行处理(MPP)系统,如 Snowflake 和 BigQuery,将自动在任意大的计算集群上分发您的代码,如果您用 SQL 编写的话。
另一方面,如果您使用 Python 或 Scala dataframes 作为您的主要编程模型,您将经常需要指定数据分布和系统如何跨节点分布您的计算的其他细节。由于写入障碍以及额外的序列化和反序列化步骤,生成的执行计划通常不如基于 SQL 的系统有效。当您处理较大的数据集时,最后一点变得越来越重要。这并不是说在使用基于数据框架的系统时不可能有效地分配您的工作负载,而是说您将做不增加价值的基础设施工作,而不是花费时间从数据中获得洞察力。
最后,也是最重要的一点,通过以 SQL 为基础,您可以避免在您的组织中形成两个相互竞争的阵营,数据科学家和分析师。随着每个人对如何完成数据操作保持一致,您的团队可以专注于在当今业务中越来越重要的深度数据分析。
所有关于决策树算法!
介绍

理解这种算法最简单的方法是把它看作一系列 if-else 语句,在树的顶部有最高优先级的决策节点。
这是一个监督的机器学习算法,这意味着对应于每一个数据,我们都有一个标签或类别或决定。
决策树有回归和分类两种类型。
一棵决策树包含 4 样东西:
- 根节点
- 子节点
- 树枝
- 叶节点
给定一个数据集,我们首先找到一个在结果决策中最占优势的属性,该属性成为决策树的根节点,然后考虑根属性中存在的属性,找到最占优势的属性,然后将其表示为根节点的子节点,然后根据已经形成的树节点计算每个剩余属性的熵。重复这个过程,直到构建了整个树。
确定主导节点
在 ID3(迭代二分法 3)算法的帮助下,确定在每个步骤中寻找主导节点的方法,这将在下面解释。
ID3 算法有 3 个公式,在这些公式的帮助下,我们可以计算主导节点:-
- 信息增益:表示该节点相对于其他节点对最终节点的影响有多大。
- 熵:表示随机性,即节点中值的随机性。
- 增益:它是节点的整体增益,基于这个值我们决定主导节点,具有最大增益值的属性被选为主导节点。
按照惯例,我们把“p”和“n”分别作为正决策和负决策。它们是由我们必须应用决策树的数据计算出来的。
信息增益:
它通过以下公式计算:

作者图片
它是针对整个表或子表计算的。
熵:
它通过以下公式计算:

IG =信息增益【图片由作者提供】
它是为属性计算的。
增益:
它通过以下公式计算:
信息 _ 增益(母体)-熵(属性)
决策树算法的求解示例:
以下是我使用过的数据:

图片来源:https://rb.gy/urgqbp
首先,我们找到整个表的信息增益,以便找到树的根节点,这里 p(正)和 n(负)决策分别是 9 和 5。[查看“打高尔夫”一栏中的“是”和“否”]
根据公式,我们得到 IG(整体 _ 表格)= 0.940
现在,我们将通过计算信息增益和熵来计算表中每个列/属性的增益。
计算 Outlook 的收益:
Outlook 有三个类别,分别是晴天、阴天和雨天。

展望熵与增益(图片作者)
计算温度增益:
温度有三个类别,热,温和,凉爽。

温度的熵和增益(图片由作者提供)
计算湿度增益:
湿度有两类:高湿度和凉爽湿度。

湿度的熵和增益(图片由作者提供)
计算风的增益:
湿度有两类,一类是假的,一类是真的。

风的熵和增益(图片由作者提供)
从上面的结果我们可以看出,outlook 的增益是最大的,所以它将是树的根节点。
到目前为止的树:

(图片作者)
现在,我们将计算其余属性的增益,即风、温度和湿度与晴天、阴天和雨天的关系,因为我们已经获得了 outlook 作为根节点。
请记住,从现在开始,在计算增益时,全局 p 和 n 将取自晴天、阴天和雨天,因为它们将作为它们的子属性的父属性。
计算晴天时的温度增益:

(图片作者)
计算晴天时的湿度增益

(图片作者)
计算多风天气的增益:

(图片作者)
从上面的结果我们可以看到 windy 的增益是最大的,所以它将是 sunny 之后的下一个树的根节点。
在 windy 中,我们有两个类别“假”和“真”,它们直接引导我们找到解决方案。
到目前为止的树:

(图片作者)
在这里阴天的情况下,从上面看,information_gain 是 0,这意味着我们将从阴天场直接做出决策,这是确切的情况,在数据中,我们在任何阴天的情况下都将导致 yes。
到目前为止的树:

(图片作者)
计算相对于雨天的温度增益:

(图片由作者提供)
计算相对于雨天的湿度增益:

(图片作者)
计算多风多雨的增益:

(图片作者)
从上面的结果我们可以看到,湿度的增益是最大的,所以它将是下雨后树的下一个根节点。
在 windy 中,我们有两个类别“高”和“正常”,它们直接引导我们找到解决方案。
最终决策树现在:

(图片作者)
我已经尽了最大努力自己解释和绘制了所有的图形和函数,希望你们能理解。
关于特征缩放的所有内容

苹果和草莓图片来源:Pixabay
深入分析
扩展数据以提高机器学习模型的性能
机器学习就像制作一种混合果汁。如果我们想得到最好的混合果汁,我们需要混合所有的水果,不是根据它们的大小,而是根据它们正确的比例。我们只需要记住苹果和草莓是不一样的,除非我们在某些情况下让它们相似来比较它们的属性。类似地,在许多机器学习算法中,为了使所有特征处于相同的地位,我们需要进行缩放,以便一个重要的数字不会仅仅因为其巨大而影响模型。
机器学习中的特征缩放是在创建机器学习模型之前的数据预处理期间最关键的步骤之一。缩放可以在弱机器学习模型和更好的机器学习模型之间产生差异。
最常见的特征缩放技术是规范化和标准化。
当我们想要将我们的值限制在两个数字之间时,通常是在[0,1]或[-1,1]之间,就使用规范化。虽然标准化将数据转换为具有零均值和方差 1,但它们使我们的数据没有单位。参考下图,该图显示了数据在 X-Y 平面缩放后的样子。

为什么我们需要缩放?
机器学习算法只看到数字——如果范围有很大差异,比如几千范围内的差异和几十范围内的差异,它会做出基本假设,即更高的范围数具有某种优势。所以这些更重要的数字在训练模型时开始起更决定性的作用。
机器学习算法处理数字,但不知道这个数字代表什么。10 克的重量和 10 美元的价格代表了完全不同的两件事——这对人类来说是显而易见的,但对于作为特征的模型来说,它将两者视为相同。
假设我们有重量和价格两个特征,如下表所示。“重量”无法与“价格”进行有意义的比较。因此,假设算法认为,既然“重量”>“价格”,因此“重量”比“价格”更重要

所以这些更重要的数字在训练模型时开始起更决定性的作用。因此,需要进行功能扩展,以便将每个功能放在相同的位置,而没有任何前期重要性。有趣的是,如果我们将重量转换为“千克”,那么“价格”就成了主导。
应用特征缩放的另一个原因是,很少有像神经网络梯度下降这样的算法在使用特征缩放时比不使用特征缩放时收敛得更快。

另一个原因是饱和,就像神经网络中的 sigmoid 激活一样,缩放将有助于不要太快饱和。
什么时候做缩放?
特征缩放对于计算数据之间的距离的机器学习算法来说是必不可少的。如果不是比例,具有较高值范围的要素在计算距离时开始占主导地位,这在“为什么?”中有直观的解释部分。
ML 算法对特征的相对尺度敏感,这通常发生在它使用特征的数值而不是说出它们的等级时。
在许多算法中,当我们希望更快收敛时,缩放是必须的,就像在神经网络中一样。
由于原始数据的值的范围变化很大,在一些机器学习算法中,目标函数在没有归一化的情况下不能正确工作。例如,大多数分类器通过距离来计算两点之间的距离。如果其中一个要素的值范围很大,则距离决定了该特定要素。因此,应该对所有要素的范围进行归一化,以便每个要素对最终距离的贡献大致成比例。
即使在不满足上述条件的情况下,如果 ML 算法预计会出现某种缩放或饱和现象,您可能仍需要重新缩放要素。同样,具有饱和激活函数(例如,sigmoid)的神经网络是一个很好的例子。
我们可以遵循的经验法则是计算距离或假设正态性的算法,缩放您的特征。
特征缩放很重要的算法的一些例子是:
- 具有欧几里德距离测量的 K-最近邻 (KNN)对量值敏感,因此应针对所有要素进行缩放,以使权重相等。
- K-Means 在这里使用欧几里德距离度量特征缩放关系重大。
- 在执行主成分分析(PCA) 时,缩放至关重要。PCA 试图获得具有最大方差的特征,对于高量值特征,方差是高的,并且使 PCA 向高量值特征倾斜。
- 我们可以通过缩放来加快梯度下降的速度,因为θ在小范围内下降很快,在大范围内下降很慢,并且当变量非常不均匀时会低效地振荡到最优值。
不需要标准化/缩放的算法是那些依赖规则的算法。它们不会受到变量的任何单调变换的影响。缩放是一种单调的变换。这类算法的例子是所有基于树的算法— CART、随机森林、梯度推进决策树。这些算法利用规则(一系列不等式)并且不需要标准化。
像线性判别分析(LDA)和朴素贝叶斯这样的算法是设计来处理这种情况并相应地给特征赋予权重的。在这些算法中执行特征缩放可能没有太大效果。
需要注意的几个要点:
- 均值居中不影响协方差矩阵
- 变量的缩放确实会影响协方差矩阵
- 标准化会影响协方差
如何进行特征缩放?
下面是我们可以进行特征缩放的几种方法。
1)最小最大定标器
2)标准定标器
3)最大 Abs 定标器
4)鲁棒定标器
5)分位数变压器定标器
6)电力变压器定标器
7)单位矢量定标器
为了便于说明,我们将使用顶部所示的表格并形成数据框来显示不同的缩放方法。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
df = pd.DataFrame({'WEIGHT': [15, 18, 12,10],
'PRICE': [1,3,2,5]},
index = ['Orange','Apple','Banana','Grape'])
print(df)WEIGHT PRICE
Orange 15 1
Apple 18 3
Banana 12 2
Grape 10 5
1)最小-最大缩放器

通过将每个要素缩放到给定范围来变换要素。该估计器单独缩放和翻译每个特征,使得它在训练集的给定范围内,例如在 0 和 1 之间。如果有负值,此缩放器会将数据缩小到-1 到 1 的范围内。我们可以设置范围,如[0,1]或[0,5]或[-1,1]。
如果标准偏差很小,并且分布不是高斯分布时,该定标器响应良好。该定标器对异常值敏感。
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()df1 = pd.DataFrame(scaler.fit_transform(df),
columns=['WEIGHT','PRICE'],
index = ['Orange','Apple','Banana','Grape'])ax = df.plot.scatter(x='WEIGHT', y='PRICE',color=['red','green','blue','yellow'],
marker = '*',s=80, label='BREFORE SCALING');df1.plot.scatter(x='WEIGHT', y='PRICE', color=['red','green','blue','yellow'],
marker = 'o',s=60,label='AFTER SCALING', ax = ax);plt.axhline(0, color='red',alpha=0.2)
plt.axvline(0, color='red',alpha=0.2);

2)标准定标器

标准缩放器假设数据在每个要素内呈正态分布,并对其进行缩放,使分布以 0 为中心,标准差为 1。
通过计算训练集中样本的相关统计数据,对每个特征独立进行居中和缩放。如果数据不是正态分布的,这不是最好的缩放器。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df2 = pd.DataFrame(scaler.fit_transform(df),
columns=['WEIGHT','PRICE'],
index = ['Orange','Apple','Banana','Grape'])
ax = df.plot.scatter(x='WEIGHT', y='PRICE',color=['red','green','blue','yellow'],
marker = '*',s=80, label='BREFORE SCALING');
df2.plot.scatter(x='WEIGHT', y='PRICE', color=['red','green','blue','yellow'],
marker = 'o',s=60,label='AFTER SCALING', ax = ax)
plt.axhline(0, color='red',alpha=0.2)
plt.axvline(0, color='red',alpha=0.2);

3)最大 Abs 定标器
按最大绝对值缩放每个要素。该估计器单独缩放和转换每个特征,使得训练集中每个特征的最大绝对值为 1.0。它不会移动/居中数据,因此不会破坏任何稀疏度。
在只有正的数据上,该定标器的行为类似于最小最大定标器,因此,也存在显著的异常值。
from sklearn.preprocessing import MaxAbsScaler
scaler = MaxAbsScaler()
df4 = pd.DataFrame(scaler.fit_transform(df),
columns=['WEIGHT','PRICE'],
index = ['Orange','Apple','Banana','Grape'])
ax = df.plot.scatter(x='WEIGHT', y='PRICE',color=['red','green','blue','yellow'],
marker = '*',s=80, label='BREFORE SCALING');
df4.plot.scatter(x='WEIGHT', y='PRICE', color=['red','green','blue','yellow'],
marker = 'o',s=60,label='AFTER SCALING', ax = ax)
plt.axhline(0, color='red',alpha=0.2)
plt.axvline(0, color='red',alpha=0.2);

4)稳定的定标器
顾名思义,这个定标器对异常值是健壮的。如果我们的数据包含许多异常值,使用数据的平均值和标准差进行缩放将不会很好。
此缩放器移除中值,并根据分位数范围(默认为 IQR:四分位数范围)缩放数据。IQR 是第一个四分位数(第 25 个四分位数)和第三个四分位数(第 75 个四分位数)之间的范围。这个定标器的定中心和定标统计是基于百分位数的,因此不受少数巨大的边缘异常值的影响。请注意,异常值本身仍然存在于转换后的数据中。如果需要单独的异常值削波,则需要非线性变换。
from sklearn.preprocessing import RobustScaler
scaler = RobustScaler()
df3 = pd.DataFrame(scaler.fit_transform(df),
columns=['WEIGHT','PRICE'],
index = ['Orange','Apple','Banana','Grape'])
ax = df.plot.scatter(x='WEIGHT', y='PRICE',color=['red','green','blue','yellow'],
marker = '*',s=80, label='BREFORE SCALING');
df3.plot.scatter(x='WEIGHT', y='PRICE', color=['red','green','blue','yellow'],
marker = 'o',s=60,label='AFTER SCALING', ax = ax)
plt.axhline(0, color='red',alpha=0.2)
plt.axvline(0, color='red',alpha=0.2);

现在让我们看看如果引入异常值会发生什么,并看看使用标准缩放器和鲁棒缩放器的缩放效果(圆圈表示异常值)。
dfr = pd.DataFrame({'WEIGHT': [15, 18, 12,10,50],
'PRICE': [1,3,2,5,20]},
index = ['Orange','Apple','Banana','Grape','Jackfruit'])
print(dfr)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df21 = pd.DataFrame(scaler.fit_transform(dfr),
columns=['WEIGHT','PRICE'],
index = ['Orange','Apple','Banana','Grape','Jackfruit'])
ax = dfr.plot.scatter(x='WEIGHT', y='PRICE',color=['red','green','blue','yellow','black'],
marker = '*',s=80, label='BREFORE SCALING');
df21.plot.scatter(x='WEIGHT', y='PRICE', color=['red','green','blue','yellow','black'],
marker = 'o',s=60,label='STANDARD', ax = ax,figsize=(12,6))
from sklearn.preprocessing import RobustScaler
scaler = RobustScaler()
df31 = pd.DataFrame(scaler.fit_transform(dfr),
columns=['WEIGHT','PRICE'],
index = ['Orange','Apple','Banana','Grape','Jackfruit'])df31.plot.scatter(x='WEIGHT', y='PRICE', color=['red','green','blue','yellow','black'],
marker = 'v',s=60,label='ROBUST', ax = ax,figsize=(12,6))
plt.axhline(0, color='red',alpha=0.2)
plt.axvline(0, color='red',alpha=0.2);WEIGHT PRICE
Orange 15 1
Apple 18 3
Banana 12 2
Grape 10 5
Jackfruit 50 20

5)分位数变压器定标器
使用分位数信息变换要素。
该方法将特征转换为符合均匀或正态分布。因此,对于给定的特性,这种变换往往会将最频繁出现的值分散开来。它还减少了(边缘)异常值的影响:因此,这是一个健壮的预处理方案。
要素的累积分布函数用于投影原始值。请注意,这种转换是非线性的,可能会扭曲在相同尺度下测量的变量之间的线性相关性,但会使在不同尺度下测量的变量更具直接可比性。这有时也被称为等级缩放器。
from sklearn.preprocessing import QuantileTransformer
scaler = QuantileTransformer()
df6 = pd.DataFrame(scaler.fit_transform(df),
columns=['WEIGHT','PRICE'],
index = ['Orange','Apple','Banana','Grape'])
ax = df.plot.scatter(x='WEIGHT', y='PRICE',color=['red','green','blue','yellow'],
marker = '*',s=80, label='BREFORE SCALING');
df6.plot.scatter(x='WEIGHT', y='PRICE', color=['red','green','blue','yellow'],
marker = 'o',s=60,label='AFTER SCALING', ax = ax,figsize=(6,4))
plt.axhline(0, color='red',alpha=0.2)
plt.axvline(0, color='red',alpha=0.2);

上面的例子只是为了说明,因为当我们有一个包含许多数据点(通常超过 1000 个)的大型数据集时,分位数转换器非常有用。
6)电力变压器定标器
power transformer 是一系列参数化的单调变换,应用于使数据更加高斯化。这对于建模与变量的可变性相关的问题非常有用,变量的可变性在整个范围内是不相等的(异方差)或者需要正态性的情况。
幂变换通过最大似然估计找到稳定方差和最小化偏斜的最佳比例因子。目前,PowerTransformer 的 Sklearn 实现支持 Box-Cox 变换和 Yeo-Johnson 变换。通过最大似然估计稳定方差和最小偏度的最优参数。Box-Cox 要求输入数据严格为正,而 Yeo-Johnson 既支持正数据也支持负数据。
from sklearn.preprocessing import PowerTransformer
scaler = PowerTransformer(method='yeo-johnson')
df5 = pd.DataFrame(scaler.fit_transform(df),
columns=['WEIGHT','PRICE'],
index = ['Orange','Apple','Banana','Grape'])
ax = df.plot.scatter(x='WEIGHT', y='PRICE',color=['red','green','blue','yellow'],
marker = '*',s=80, label='BREFORE SCALING');
df5.plot.scatter(x='WEIGHT', y='PRICE', color=['red','green','blue','yellow'],
marker = 'o',s=60,label='AFTER SCALING', ax = ax)
plt.axhline(0, color='red',alpha=0.2)
plt.axvline(0, color='red',alpha=0.2);

7)单位向量定标器

缩放是在将整个特征向量视为单位长度的情况下进行的。这通常意味着将每个分量除以向量的欧几里得长度(L2 范数)。在一些应用中(例如,直方图特征),使用特征向量的 L1 范数可能更实际。
像最小-最大缩放一样,单位矢量技术产生范围[0,1]的值。当处理具有硬边界的特征时,这非常有用。例如,在处理图像数据时,颜色的范围可以从 0 到 255。

如果我们绘图,那么它会看起来如下分别为 L1 和 L2 规范。

下图显示了所有不同缩放技术的数据分布情况,正如我们所见,有几个点是重叠的,因此无法单独看到。

最后注意:
特征缩放是机器学习预处理中的一个重要步骤。深度学习需要特征缩放以实现更快的收敛,因此决定使用哪种特征缩放至关重要。有许多针对各种算法的缩放方法的比较调查。然而,像大多数其他机器学习步骤一样,特征缩放也是一个试错过程,而不是单一的银弹。
如果您有任何与功能缩放相关的独特经验,我期待您的评论和分享。感谢阅读。可以联系我@ LinkedIn 。
参考:
http://sebastianraschka . com/Articles/2014 _ about _ feature _ scaling . html
https://www . kdnugges . com/2019/04/normalization-vs-standardization-quantitative-analysis . html
https://scikit-learn.org/stable/modules/preprocessing.html
关于假设检验,从 p 值到 Z 检验,一应俱全
假设检验的一个超级简单的定义,只适用于初学者。
p 值、假设检验、统计显著性或统计检验是您最常听到的词,尤其是当您是数据科学家时。你可以在多种媒体的帖子和 YouTube 视频中找到所有这些定义,这些帖子和视频只涵盖了这些概念的一部分,而将其他的放在一边阅读。因此,随着符号的变化,读者可能会对主要思想感到困惑。所以我决定写一篇帖子,用简单明了的方式涵盖所有与统计测试相关的概念。

Peter Bravo de los Rios 在 Unsplash 上拍摄的照片
让我们从一个例子开始我们的旅程。披萨时间!
🍕 🍕 举例 :假设一家快餐声称其送货服务平均为 30 分钟或更少。这是我们所期待的,也是所有人所想的。但是因为你是一个好奇的人,你想测试这个想法。
- 有一种说法(送货服务平均 30 分钟或更少)说我们想测试一下。我们称之为假设。
- 有一个公认的说法是,送货服务平均 30 分钟或更少。我们称之为零假设。零假设目前是可以接受的。
- 你有一个想法,即送货服务可能平均超过 30 分钟。所以你应该做个测试。因此,你可以接受这个主张(零假设)或者拒绝它。你的主张叫做替代假设。请注意,你测试快餐的说法,你决定是否接受或拒绝。
现在你应该选择一个阈值来显示你的测试的可信度。你想有 99%的把握,那么置信度应该是 0.99。你应该在开始实验前决定。
从送货服务开始取样。您的样本是独立的,并且您收集了足够的(超过 30 个)样本。您的样本是随机选择的,具有正态分布。
到现在为止,你已经定义了你的问题。你有一个零假设,一个替代假设和足够多的随机样本。假设我们想要 95%的置信度,这意味着与正常状态的 0.05 偏差对您来说是很重要的。我们称之为显著水平(alpha)。这意味着如果参数超过阈值(α),则该参数异常。
我们首先转换样本。为什么?因为我们希望有一个简单、独特和易懂的度量标准来理解。由于样本来自正态分布,我们选择标准正态分布(均值=0,标准差=1)。我们可以简单地将数据从任何正态分布转换成标准正态分布。现在出现了 z-score (这部分是借用了【mathbitsnotebook.com】的)。A z -score(或标准分数)代表给定值 x 偏离平均值 μ 的标准偏差数。

“def。-得分是位置的度量,表示数据值偏离平均值的标准偏差数。是一个标准正态分布的水平刻度。”

所有正常曲线下的面积都是相关的。例如,平均值以上 1.5 个标准偏差右侧的面积百分比对于所有的正常曲线都是相同的。使用 Z 得分计算的面积百分比(比例、概率)将是一个介于 0 和 1 之间的小数值,并将出现在 Z 得分表中。任何正常曲线下的总面积是 1(或 100%)。由于正态曲线关于平均值对称,因此平均值两侧的面积为 0.5(或 50%)。
变量的 z 值小于 0.36 的概率。
假设我们有一个样本,我们计算它的 z 分数,称为z。另一方面,找出阿尔法参数的 z 分数,称为 zc 。如果 z 与 zc,交叉,则意味着我们与平均值(0)有显著的距离,这是一种异常事件。Z 值越高或越低,结果越不可能是偶然发生的,结果越有可能是有意义的。注意阿尔法是从 zc 向右的曲线下的面积。(我们在右边的尾巴上测试。)
p 值是获得样本的概率比我们接受零假设时在样本中观察到的更极端。这里有一个 p%的机会我们会看到由于随机噪声平均交付时间会更长。**
因此,如果我们有更低的 p,我们可以说,由于噪声,这个事件不发生的几率更大。如果 p 足够小(从我们之前设置的阈值α开始),我们可以拒绝我们的零假设,因为它被嘲笑我们有一个异常事件(我们接受零假设是真的),随机噪声发生的几率很低。它不受噪音的影响,但它确实发生了,并不像我们第一次声称的那样。
因此,我们的样本 z 值穿过 zc(其中曲线右下方的面积是标准正态分布中的α),从 z 值到标准正态分布右侧的曲线面积就是我们的 p 值。因此,如果 p 值低于α(显著水平),那么我们称事件为异常。然后我们可以拒绝我们的无效假设。
你可以在这个视频中找到一个简单的例子:
但是最后一件事。你在大部分教程的 z-score 的公式里看到的都是 sqrt(n)。这个 sqrt(n)是干什么的?

请注意,当我们有多个样本时,我们会找到样本平均值的 z 得分。我用这个数学堆栈交换来回答:
* [## 为什么归一化的 z 值会引入平方根?(还有更多困惑)
begingroup\(如果\)X\(是一个正态随机变量,你可以记录它的一个观察值,\)x$并将其与均值相比较…
math.stackexchange.com](https://math.stackexchange.com/questions/845769/why-does-the-normalized-z-score-introduce-a-square-root-and-some-more-confusio)
如果 X 是一个正态随机变量,你可以记录下对它的观察,并将其与平均值进行比较。通常的做法是将变量标准化,即,

假设 X1,X2,…Xn 是随机变量,来自与上面 XX 相同的分布。如果我们记录每个的观察值并计算平均值,那也是一个随机变量。然而,我们不能期望均值,我们的新随机变量,和我们的原始分布有相同的分布。它会有相同的均值,但不会有相同的方差。有一个直觉,如果你增长了足够多的 n,然后把你的样本分成不同的组,每组中的平均值是一个随机变量,具有相同的均值分布,但平均值彼此越来越接近,因为它们模糊了异常值数据。(只是再想一想得到一个直觉)。实际上是方差除以 n,所以公式这样变。
现在你明白了在统计测试中你需要的所有单词的定义。
快乐的数据科学时间。*
关于主定理及其证明!
简介:这是通过递归关系求任何算法时间复杂度的最佳方法(捷径)/技巧。

主定理
主定理的版本仅适用于递推关系的形式:

作者图片
- 其中 a ≥ 1,b≥1,d≥ 0
主定理有三种情况:
情况 1:d<log(a)【base b】=>时间复杂度=o(n ^ log(a)【base b】)
案例二:****d = log(a)【base b】=>时间复杂度= O((n ^ d) * log(n) )
案例三:****d>log(a)【base b】=>时间复杂度= O((n ^ d))
主定理的证明
主定理的上述形式表示问题是树的形式,并且树的形成如下所示:

各层次的问题划分(图片由作者提供)
还有,我们都知道,如果一个问题可以用如上的树的形式来表示,那么它最多到层次log(n)【base b】。
每一级所做的功表示为:

各级完成的工作!
注意:上图最后一行有一处修正,应该是“log(n)[base b]”,而不是“log(b)[base n]”。
在我提供对主定理的每种情况的证明之前,有一些概念我需要弄清楚,它们解释如下:
- 在一个几何级数中,由于级数中的每一个下一个元素相差一个公倍数的整数,习惯上我们把它取为“r”。
- 几何级数的和公式是 a *(1-r^n)/(1–r),其中 a 是第一项。
案例 1 的证明; d < log(b)【基数 a】:
- 上述情况也可以理解为在树的每个后续级别中所做的工作都在增加。
- 同样,当 r < 1 in a Geometric series, so, in this case, the major term will be the last term of the geometric series which will be having the maximum effect.
- So, in the total work done formula we take to take only the last term, i.e. substitute k = log(n) [base b] in the time complexity expression.

求解表达式时也是如此
这个表达式需要对数属性来求解,所以请研究一下。
我们得到了我们以前说过的结果。因此证明。
案例 2 的证明;d = log(b)[基数 a]:
这意味着在每一级中所做的功是相等的,所以我们可以很容易地通过将乘以级数和在每一级上所做的功得到最终的功。

因此证明。
案例 3 的证明;****d>log(a)【base b】:
这意味着所需的功在随后的各级中不断减少= >在第一级中所做的功是最大的= >我们只需要考虑第一项。
这显然为 O(n^d).提供了
因此证明。
我希望你们喜欢这篇文章,并且容易理解总是令人困惑的主定理的证明。
关于 Python 列表理解的所有内容

图片提供:Pixabay
优雅、舒适、简洁、快速的列表创建方式
Python 是一种用简洁的代码表达的语言,非常优雅,易于理解。列表理解提供了一种创建列表的简洁方法。列表理解是构建一个可访问的、简洁的、快速的列表的合适的“pythonic 式”方法。它允许使用一行代码对列表执行复杂的操作。
什么是列表理解?
列表理解为我们提供了一种简单的方法来创建一个基于某种序列的列表或者另一个我们可以循环的列表。在 python 术语中,任何可以循环的东西都称为 iterable。在最基本的层面上,列表理解是一种从现有列表创建列表的语法结构。列表理解的核心,就是循环(“for”循环)。我们可以将任何列表理解表示为 for 循环,但是当我们在一行中用等价的列表理解来表示它时,它看起来确实是独一无二的。
列表理解有以下几个重要部分:
- 一个可迭代的输入序列(可以是一个列表、一个范围或者任何序列),我们使用一个变量名来迭代它。
- 输出表达式
- 变量过滤或映射或执行某些逻辑操作的可选条件

例如,如果我们想从 1 到 5 的变量列表中创建一个正方形列表,我们可以像下面这样使用标准的 For 循环,但是当我们使用列表理解时,它变得简洁和轻量级。

图片:Pixabay 的称重机
如果我们分解列表理解部分,它看起来如下。

解释一个简单列表,包括每个输入变量的输出平方
因此,这里 iterable 是 range(1,6),x 是表示该范围内每个值的变量。对于每个 x (1,2,3,4,5),输出表达式 x*x 计算相应的输出(1,4,9,16,25),最终成为最终的输出列表(参考上图)。
基本构造之外的几种用法:
1)基于条件的过滤
列表理解提供了一种方法来检查条件,并从输出的输入列表中过滤掉我们不需要的元素。这种过滤发生在输出表达式发生之前。参考下面的例子,我们只计算那些能被 2 整除的变量的平方。


带有过滤条件的列表理解
2)嵌套条件
列表理解可以用来检查嵌套条件。参考下面的代码,我们想找到输入列表中所有的变量都可以被 2,4 & 5 整除。

3)如果..列表理解中的 else
我们可以在 Python 的列表理解中使用“if-else”。参考下面的代码块,它查找奇数和偶数的数字列表。我们需要首先指定输出是什么,接着是“if”条件,然后是“else”,接着是“else”下的输出是什么

注意,如果不使用逗号和括号,我们不能直接打印输入值。
4)扁平化多维列表
假设我们必须展平一个 2D 列表。我们可以很容易地通过使用子列表来理解列表。

我们怎样才能使 3D 列表变平?这变得有点复杂,我们首先将 3D 平铺到 2D,然后将 2D 平铺到 1D。在下面的例子中,蓝色下划线部分是使 2D 从 3D 列表变平的步骤,然后外部部分对 1D 进行变平。

5)嵌套的“for”列表理解
我们可以对多个嵌套的“for”循环使用列表理解。当我们使用嵌套列表理解时,我们必须注意执行的顺序。假设我们有一个 3x3 的正方形矩阵,我们想使用这个矩阵创建一个矩阵,其中所有对角线值都必须是正方形,而其他值必须为零。这里的输出是一维的,我们需要额外的逻辑来转换成 2D 矩阵形式。这里我使用了“列”和“行”来解释,但是也可以直接用在“for 循环”中,不需要中间变量(如下面列表理解中所使用的)。
matrix = [[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]]row = len(matrix)
column = len(matrix[0])
output = []
for i in range(row):
for j in range(column):
if i == j:
output.append(matrix[i][j] * matrix[i][j])
else:
output.append(0)
output
[1, 0, 0, 0, 25, 0, 0, 0, 81]
现在我们看到等价的嵌套列表理解(只有一行,但是为了容易理解,我用了 3 行)。
[[matrix[i][j]*matrix[i][j] if i == j else 0
for i in range(len(matrix))]
for j in range(len(matrix[0]))]
现在,让我们通过每个循环是如何工作的图片来理解这一点。循环执行顺序是从上到下(绿色粗体箭头)。我们首先完成内部循环(深绿色),然后控制回到外部循环(蓝色)。这里的列表理解是一行,而普通的“for 循环”是五行,如上面的代码所示。我们也可以通过在第一个 for 循环后加括号直接得到输出的矩阵形式。

列表理解的优势
- 列表理解的一个显著优点是开发人员需要编写更少的代码
- 列表理解通常变得更容易理解
- 当向列表追加项目时,列表理解的速度明显优于 for 循环
- 列表理解是内置的映射和过滤器函数的一个很好的替代品
其他理解
在 Python 中,我们也有“字典理解”和“集合理解”,它们在操作上是相似的,但只适用于字典和集合。Python 也有“生成器表达式”,它使用了“圆形”括号。
最后一个音符
当我开始我的 Python 之旅时,我曾经发现理解列表理解是如何工作的很有挑战性。一旦我明白了它的优雅和力量,我就再也没有回头。尽管一开始感觉有点吓人,但是经过一点练习,每个 python 爱好者都可以爱上列表理解。
我期待着你的评论和分享,如果你有任何独特的列表理解的经验。感谢阅读。可以联系我@ LinkedIn 。
只需每月 5 美元,就可以无限制地获取最鼓舞人心的内容……点击下面的链接,成为媒体会员,支持我的写作。谢谢大家!
【https://baijayanta.medium.com/membership】
关于 Pythonic 类的一切:诞生和风格
Python 数据模型
Python 数据模型—第 2 部分[a]

图片:来源
如果您错过了本系列的第一部分,您可以在这里阅读对象、类型和值;Python 数据模型—第 1 部分。
我们将这个“关于 Pythonic 类的一切”的标题分成两部分。
—关于 python 类的一切:诞生和风格
— 关于 python 类的一切:生命周期
这些章节的标题最终可能不会明确地反映读者刚刚描绘到她/他脑海中的想法。我们将试图用一个简单的叙述来涵盖 Python 类如何形成和析构的基本概念。Python 类(更具体地说是 Python 3.x 类)的创建和销毁不可避免地会涉及许多看似不相关的主题。
更重要的是,读者至少需要适度了解 Python 数据模型、特殊方法、元编程以及解释器如何在幕后工作。此外,有些重复、循环讨论和过度简化是不可避免的——例如,我们必须坚持用对象来解释一个类的行为。
1。如何写一个基础类
让我们为 Foo 小姐阁下写一个基础类,她是我们当地一位著名的后摇滚吉他练习者,她要求我们写一个程序来跟踪她的学生的 姓名金钱* ,他们将支付给她并分配一个带有她的域名的 电子邮件 地址。她自己是一名开发人员,但是每天的日程安排很紧,她向像我们这样懒惰的程序员寻求帮助。然而,她将把这个蓝图或类用到自己的脚本中。现实生活中代码重用的例子,哈!让我们帮助她。*
*>>> class Student(): # ...[1]
pass>>> student_1 = Student() # ... [2]
>>> student_2 = Student() # ... [3]>>> student_1, student_2 # ... [4]
(<__main__.Student object at 0x7fec1b6387b8>, <__main__.Student object at 0x7fec1b638780>)>>> print(id(student_1), id(student_2)) # ... [5]
140652048517048 140652048516992>>> type(student_1) # .......... [6]
<class '__main__.Student'>*
我们刚刚编写了一个框架类Student并给解释器传递了一个pass语句,告诉她在我们给它赋值之前保持它的完整性。我们还在语句[2]和[3]中创建了两个Student类实体。这里需要注意的最重要的两点是,尽管来自同一个类Student , student_1和student_2在 RAM 语句[5]和[4]中具有不同的身份和位置。
一个星期天的早上,安德鲁·汤普森被她的班级录取了。 傅小姐 每个月会收他 五千 块钱。让我们加上他的名字
*>>> student_1.firstname = "Andrew"
>>> student_1.lastname = "Thompson"
>>> student_1.pays = 5000
>>> student_1.mail = student_1.firstname.lower()+'_'+student_1.lastname.lower()+"@msfooguitar.edu"
>>> student_1.mail
'andrew_thompson@msfooguitar.edu'*
一个星期五的早上,安德鲁的朋友马克·伯德报名参加了这个班。因为他是个初学者,所以傅小姐需要对他付出更多的努力和关注。马克每月将支付 6000 美元。让我们把他的名字登记在登记簿上。
*>>> student_2.firstname = "Marc"
>>> student_2.lastname = "Byrd"
>>> student_2.pays = 6000
>>> student_2.mail = student_2.firstname.lower()+'_'+student_2.lastname.lower()+"@msfooguitar.edu"
>>> student_2.mail
'marc_byrd@msfooguitar.edu'*
请注意,我们在上述示例中采用的方法符合我们的目的,但使进一步的工作变得复杂。
- 我们重复地给每个对象分配实例。当类将产生更多的对象时,这将进一步增加复杂性。
- 我们将需要在需要的时候定义类。当前的例子对我们没有帮助。
我们可以通过避免重复和确保代码的可重用性来使情况变得更加灵活,具体方法是编写一个蓝图,描述Student类及其对象将获得什么属性。
*class Student():
def __init__(self, fname, lname, pays): # ... [1] an initialiser.
self.fname = fname
self.lname = lname
self.pays = pays
self.mail = f"{self.fname.lower()}@msfooguitar.edu"
student_1 = Student("Andrew", "Thompson", 5000)
student_2 = Student("Marc", "Byrd", 6000)*
现在我们所拥有的是,
- 类
Student现在的行为就像一个表单,有三个必填字段——名、姓、支付的金额以及一个额外的电子邮件地址——由每个新学生或对象在注册课程时填写。这样编码器可以避免重复。 __init__魔法方法(将在几分钟内讨论)初始化每个新的Student对象/实例将获得的变量、字段或属性。在创建类的每个新对象时调用此方法。记住__init__不是构造器。在 Python 中,__new__是构造函数- 你有没有注意到初始值设定项中传递了
self参数?当从一个类中创建一个对象时,解释器将首先把对象本身传递给__init__方法,这个方法通常用self参数表示。我们可以使用除了self之外的任何参数名。
*class Student():
def __init__(self, fname, lname, pays): # ... [1] an initialiser.
self.fname = fname
self.lname = lname
self.pays = pays
self.mail = f"{self.fname.lower()}@msfooguitar.edu"
def details(self):
print(f"name: {self.fname} {self.lname} pays: {self.pays} mail:\
{self.mail}")
student_1 = Student("Andrew", "Thompson", 5000)# ... [2]
student_2 = Student("Marc", "Byrd", 6000)print(student_1.details(), student_2.details()) # Output
'''
name: Andrew Thompson pays: 5000 mail: andrew_thompson@msfooguitar.edu
name: Marc Byrd pays: 6000 mail: marc_byrd@msfooguitar.edu
'''*
语句[2]可以重写为 Class.objectMethod(object)。在我们这里相当于Student.details(student_1)。
有趣的是,我们可以像动态变量一样覆盖实例方法。比如,我们可以把details()这个可调用的函数改成一个新的字符串。
*student_1.details = "A new string."
print(student_1.__dict__)
# Output
'''
{'fname': 'Andrew',
'lname': 'Thompson',
'pays': 5000,
'mail': 'andrew_thompson@msfooguitar.edu',
'details': 'A new string.'}
'''*
注意details现在已经变成了一个不可调用的字符串对象。dict 是一个字典,包含了对象拥有的变量。
注意details现在已经变成了一个不可调用的字符串对象。
*print(student_1.details())
# Output
'''
Traceback (most recent call last)
...
---> 19 print(student_1.details())
TypeError: 'str' object is not callable
'''*
2.类和对象:硬币的两面
继续本系列的第一部分,关于 Python 数据模型的讨论,我们会经常遇到“陈词滥调”和重复的概念 “在 Python 中,一切都是对象。”
它们或者是原型或者是类型的元类或者是一些其他类的对象
*这可能与我们刚刚开始我们的 nix 之旅的时候相比,我们被告知至少数百次,从文本文件到键盘 的一切都是文件。
在 Python 3.x 中,类也是对象。也就是说,我们可以把一个类当作一个对象。我们可以像前面提到的例子一样动态地操作和修改一个类:
*>>> class ObjClass(): pass
...
>>> ObjClass.sentence = "A class is an Object" # ...[1]
>>> ObjClass.sentence
'A class is an Object'>>> type(ObjClass) # ... [2]
<class 'type'>>>> print(ObjClass)
<class '__main__.ObjClass'>
>>> ObjClass = "I'm a string now" # ... [3]>>> type(ObjClass)
<class 'str'>*
通过把类本身当作一个对象来对待,我们可以改变它的类型 [3]为什么这是可能的?
准确地说,我们可以运行一个循环来查看我们的常规数据类型,甚至type本身也是从type 元类中派生出来的。我们将有一章深入讨论元类。目前,元类从其他类获取属性,生成一个具有附加功能的新类。**
*class MyClass():
pass
myObj = MyClass()
for x in str, int, float, type, True, bool, myObj, MyClass:
print(f'{x} : {type(x)}') # Output
'''
<class 'str'> : <class 'type'>
<class 'int'> : <class 'type'>
<class 'float'> : <class 'type'>
<class 'type'> : <class 'type'>
True : <class 'bool'> # ...
<class 'bool'> : <class 'type'> # ... [2]
<__main__.MyClass object at 0x7f70d8380550> : <class '__main__.MyClass'>
<class '__main__.MyClass'> : <class 'type'>
'''*
所以,从上面的例子可以清楚地看出,Python 中的类和对象在本质上是一样的。它们或者是原型或者是类型的元类或者是一些其他类的对象
3.旧式班级和新式班级的区别
一个旧样式的类曾经被声明为class A(),而一个新样式是class A(object),它“从对象继承,或者从另一个新样式的类继承。”根据文档:
“在 Python 2.1 之前,旧式类是用户可以使用的唯一风格。(旧式)类的概念与类型的概念无关:如果 x 是旧式类的实例,那么
x.__class__指定 x 的类,但是type(x)总是<type 'instance'>。
...这反映了这样一个事实:所有旧式的实例,不管它们的类是什么,都是用一个内置类型实现的,这个内置类型叫做 instance。
...引入新型类的主要动机是提供一个具有完整元模型的统一对象模型。
让我们来看一个例子
- 旧式班级:
*#python 2.1
class Student(): _names_cache = {}
def __init__(self, fname):
self.fname = fname
def __new__(cls,fname):
return cls._names_cache
.setdefault(name,object.__new__(cls,fname)) student_1 = Student("Andrew")
student_2 = Student("Andrew")
print student_1 is student_2
print student_1
print student_2
>>> False
<__main__.Student instance at 0xb74acf8c>
<__main__.Student instance at 0xb74ac6cc>
>>>*
2.新型类:
*#python 2.7
class Student(): _names_cache = {}
def __init__(self, fname):
self.fname = fname def __new__(cls,fname):
return cls._names_cache
.setdefault(fname,object.__new__(cls,fname))student_1 = Student("Andrew")
student_2 = Student("Andrew")
print student_1 is student_2
print student_1
print student_2
>>> True
<__main__.Student instance at 0xb74acf8c>
<__main__.Student instance at 0xb74ac6cc>
>>>*
Python 3 只有一个新样式的类。即使你写的是‘旧式类’,也是从object隐式派生的。新式职业有一些老式职业所缺乏的高级特征,比如super,新的 C3 mro ,一些神奇的方法等等。请记住,我们在整篇文章中都使用 Python 3.x。
Guido 已经写了 关于新型类的内幕 ,这是一篇关于 Python 中新型和旧式类的非常棒的文章。
在的下一部分,我们将讨论类的生命周期
参考资料:
- https://docs.python.org/3/reference/datamodel.html
- 卢西亚诺·拉马尔霍的流畅 Python。这是每一个 python 爱好者都应该读的书,以提高他们的 python 技能。
关于 Pythonic 类的所有内容:生命周期
Python 数据模型
Python 数据模型—第 2 部分[b]

图片:来源
这是“关于 Pythonic 类的一切”的第二部分。现在,我们的“Python 数据模型”系列—
- 对象、类型和值;Python 数据模型—第 1 部分
- 关于 Pythonic 类的一切:诞生和风格;Python 数据模型—第 2 部分[a]
- 关于 Pythonic 类的所有内容:生命周期;Python 数据模型—第 2 部分[b]
在前一章中,我们已经展示了如何编写一个基本类,类和对象之间的关系,以及新式类和旧式类之间的区别。我们将从上一章离开的地方开始这一章
4.当我们定义一个类时,实际上会发生什么
那么当我们声明一个类时会发生什么呢?Python 解释器是怎么解释的?
当我们调用一个类来形成一个对象时,有两个特殊的方法被调用。
- 首先,解释器调用 __ new__ 方法,这是一个类的“真正”构造函数。然后,这个特殊的方法在内存中未命名的位置创建一个具有正确类型的对象。
- 然后调用 __ init__ 用 __ new__ 创建的前一个对象初始化类对象。大多数时候,如果没有明显的原因,我们不需要声明一个 __ new__ 的特殊方法。它主要发生在后台。用 __ init__ 实例化一个对象是最常见和标准的做法,足以满足我们的大多数目的。
这是一个复杂的过程,在幕后创建一个类。它还需要深入了解 Python 解释器的设计以及该语言的核心实现。为了简单起见,我们将从高层次的角度描述该过程,并编写后端过程的假设或伪代码。
当我们调用一个类来形成一个对象时,解释器调用type。它需要三个参数-
type(classname, superclass, attribs)或
type("", (), {})
其中类名是声明类的字符串表示,超类是类的元组表示,我们的类将从该元组表示中继承属性,属性是class.__dict__的字典表示。让我们正常地声明一个类
class Footballer():
game = "Football"
def __init__(self, name, club):
self.name = name
self.club = club
def a_method(self):
return None
print(Footballer.__dict__)
# Output
'''
{'__module__': '__main__', 'game': 'Football', '__init__': <function Footballer.__init__ at 0x7f10c4563f28>, 'a_method': <function Footballer.a_method at 0x7f10c45777b8>, '__dict__': <attribute '__dict__' of 'Footballer' objects>, '__weakref__': <attribute '__weakref__' of 'Footballer' objects>, '__doc__': None}
'''
现在我们将使用type元类编写相同类型的类
def outer_init(self, name, club):
self.name = name
self.club = club
Footballer1 = type("Footballer1", (), {"game":"Soccer", "__init__": outer_init, "b_method": lambda self: None})print(Footballer1.__dict__)
print(Footballer1.game)
# Output
'''
{'game': 'Soccer', '__init__': <function outer_init at 0x7f10c4510488>, 'b_method': <function <lambda> at 0x7f10c4510f28>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Footballer1' objects>, '__weakref__': <attribute '__weakref__' of 'Footballer1' objects>, '__doc__': None}Soccer
'''
啊哈!我们刚刚使用类型元类创建了一个常规的用户定义类!!这到底是怎么回事?
当类型被调用时,它的__call__方法被执行,运行另外两个特殊的方法-
type.__new__(typeclass, classname, superclasses, attributedict)建造师type.__init__(cls, classname, superclasses, attributedict)发起者/初始者
__new__(cls, [...)特殊方法__new__是创建对象时调用的第一个方法。它的第一个参数是类本身,后面是构成它所需的其他参数。这个函数很少使用,默认情况下在对象创建期间由解释器调用。
__init__(self, [...)初始化器特殊方法初始化一个类,并给出对象的默认属性。此方法将一个对象作为第一个参数,后面跟它的其他参数。这是 Python 世界中最常用的特殊方法。
下面的pseudo-code展示了 Python 解释器如何从一个类创建一个对象。请记住,为了有一个基本的理解,我们已经省略了解释器所做的底层工作。看一看不言自明的代码说明
class Bar():
def __init__(self, obVar):
self.obVar = obVar
>>> obj = Bar("a string") ----------------[1]# putting object parameter into a temporary variable
>>> tmpVar = Bar.__new__(Bar, "another string")
>>> type(tmpVar)
>>> __main__.Bar>>> tmpVar.obVar -------------------------[2]# the class is not initialised yet
# It will throw errors>>> AttributeError Traceback (most recent call last)
....
AttributeError: 'Bar' object has no attribute 'obVar'
------------------------------------------------------# initialise a temporary variable
>>> tmpVar.__init__("a string") ---------------[3]
>>> tmpVar.obVar
>>> 'another string'>>> obVar = tmpVar
>>> obVar.obVar
>>> 'another string'
Obj的表现和我们预期的一样[1]。但是,当我们通过调用Bar.__new__并试图访问obVar,来创建tmpVar时,它抛出了一个错误[2]。因此,我们需要用__init__初始化,之后,它会像前面的变量[3]一样很好地工作。
附:名字两边加双下划线的方法被称为特殊方法或魔法方法。特殊方法是 CPython 的“实现细节”或低级细节。为什么我们称之为魔法方法?因为这些方法给我们的课增加了“魔力”。对于魔法方法,我们将有两个单独的章节。
5.类的生命周期
到目前为止,我们已经讨论了 Python 类的几乎所有基本概念。我们在这一节将要讨论的内容可以算作是上一节的重复,我们将讨论一个类的更微妙的细节。
当我们运行 Python 程序时,它会在运行时从内置或用户定义的类中生成对象。每个对象在创建后都需要内存。Python 在完成分配给它的任务时不需要对象。它变成了一条不需要的信息或垃圾。
另一方面,Python 解释器需要定期释放内存用于进一步的计算、新对象的空间、程序效率和内存安全性。当一块“垃圾对象”被处置时,它就不再存在于内存中。问题是 Python 类存在多久,什么时候不再存在?最简单的答案是一个对象或类存在,只要它
- 保存对其属性或派生的引用,并且
- 它被另一个对象引用。
当两个标准都不满足时,一个对象或类就不存在了。答案是最简单的,但是很多事情都是在幕后进行的。我们将揭示其中的一些。
下面的类是设计来连接到一个 web 服务器并打印状态代码,服务器信息,然后我们将关闭连接。我们将属性从另一个名称空间“打包”到Response类中,该名称空间将是类型的元类;不出所料。
import requests
# Another name space
var = "a class variable."
def __init__(self, url):
self.__response = requests.get(url)
self.code = self.__response.status_code
def server_info(self):
for key, val in self.__response.headers.items():
print(key, val)
def __del__(self): ---------------------- [1]
self.__response.close()
print("[!] closing connection done...")# Injecting meta from another namespace
Response = type('Response', (), {"classVar":var,"__init__": __init__, "server":server_info, "__del__":__del__})
# Let's connect to our home server on my father's desk
resp = Response("http://192.168.0.19")print(type(Response))
print(resp.code)
resp.server()del resp # It will call the DE-CONSTRUCTOR# Output
'''
<class 'type'>
401
Date Fri, 25 Sep 2020 06:13:50 GMT
Server Apache/2.4.38 (Raspbian)
WWW-Authenticate Basic realm="Restricted Content"
Content-Length 461Keep-Alive timeout=5, max=100
Connection Keep-Alive
Content-Type text/html; charset=iso-8859-1
[!] closing connection done... # resp object destroyed
'''
__del__(self)特殊方法__del__可以称为终结器或析构器,负责终止一个对象或类。__del__是在对象的垃圾收集过程中调用的终结器。当对一个对象的所有引用都被删除时,这个过程就会发生。
在上面这段代码中,为了有一个基本的理解,我们省略了解释器所做的底层事情。当我们删除响应对象del resp时,会执行__del__特殊方法或反构造函数来清除 RAM 中的对象。
该方法在删除时需要额外清理的特殊情况下很有用,例如套接字和文件对象。然而,请记住这样一个事实,即使解释器退出时目标对象仍然存在,也不能保证__del__是否会被执行。因此,手动或使用包装器关闭任何文件或连接是一个很好的做法。
6.碎片帐集
一个类产生一个对象。当一个对象不再存在于一个名称空间中时,假设一个类也不需要存在于该空间中。类也可以像普通对象一样被删除,因为类本身就是一个对象。为了内存安全和高效的代码,垃圾收集过程会处理不必要的对象。
Python 在 CPython*中采用了两种垃圾收集机制
- 引用计数
- 分代垃圾收集
在这两者之间,第一个是最常用的,因为在用户空间中销毁对象的自由如果不小心实现可能会带来灾难,例如,任何对被销毁对象的强引用都可能成为孤儿/悬空对象并泄漏内存。引用计数很容易实现,但是它不能处理引用周期,这使得它更容易发生内存泄漏。
默认情况下,一个类在创建时会得到一个类型和引用计数。每当我们通过调用一个对象来创建它时,解释器就增加它的引用计数。对象或类的引用计数在
- 作为函数参数传递
- 赋给另一个对象或变量
- 附在名单上
- 作为一个类的属性添加等等。
当该计数达到零时,该类不再存在于存储器中,这可以被视为“类的死亡”。换句话说,当一个对象在任何地方被引用时,它的引用计数增加,而当它被取消引用时,它的引用计数减少。我们编写的高级代码不会影响这种低级实现,尽管可以使用分代垃圾收集或gc模块手工处理垃圾收集。请遵守以下代码
import sys
class Bar():
pass
print(sys.getrefcount(Bar)) # default reference count is 5
a = Bar()
b = Bar()
c = Bar()
print(sys.getrefcount(Bar)) # reference count increased by 3
del a , b , c
print(sys.getrefcount(Bar)) # reference count decreased by 3
# Output
'''
5
8
5
'''
当一个或多个 Python 对象相互引用时,就会出现引用循环。因此,在这些情况下,仅仅使用del删除一个对象只会减少它的引用计数,并使它不可被程序访问。它实际上保留在记忆中。
例如
class Foo():
pass
obj.var = obj
在上面的例子中,我们通过将对象obj本身赋予其属性obj.var来创建一个引用循环。仅仅减少obj的引用计数不会从内存中破坏它,而是需要分代垃圾收集来永久清除。这种实现可以由高级编码空间中的gc模块来处理。
这是‘杀班’的另一种方式。
最终想法:
从这两部分,我们试图展示关于 Pythonic 类的 6 个重要事实。预计现在我们至少对 Python 类如何工作以及如何从后台内存中清理有了一些基本的概念。
为了掩盖 python 数据模型,我们将有单独的更详细的文章,讨论魔术方法、装饰器、元编程、python 继承等。对该过程的良好理解使开发人员能够充分利用 Python 的潜在能力,并在事情变得更加复杂时调试复杂的问题。
参考资料:
- https://docs.python.org/3/reference/datamodel.html
- 卢西亚诺·拉马尔霍的流畅 Python。这是每一个 python 爱好者都应该读的书,以提高他们的 python 技能。
- https://stackify.com/python-garbage-collection/
所有关于随机梯度下降扩展:内斯特罗夫动量,简单的方法!

罗科·卡鲁索在 Unsplash 上的照片
我们在生活中做的每件事都与成本相关,就像从一个地方到另一个地方会产生成本,我们希望通过选择更便宜的旅行方式或找到更短的方式来最小化成本。随着我们在生活中日复一日地做家务,我们估计做这些工作的成本,并无意识地将它们最小化,以节省我们的时间和金钱。这种最小化成本并获得最佳结果的过程就是我们可以与梯度下降联系起来的。
概述原始梯度下降算法
让我们回忆一些基础知识,梯度是一个成本相对于另一个变量的微小变化。下降是移动的(向下),进一步改变成本到它可能的最小值。梯度下降正在逐步达到最小成本,但它通过一次输入所有训练数据来计算每一步的成本,这对于大型数据集需要很高的计算能力,有时甚至是不可能的。为此,使用随机梯度下降,其中单个随机训练数据点用于计算每一步的成本。但是这个任务也变得令人讨厌,因为它在达到最小成本之前会产生大量噪声(振荡)。小批量梯度下降通过用小批量训练数据点计算每一步的成本来处理这个问题。这有助于减少噪音,并提供更快和更好方法来达到最低成本。
图 1 解释了最小化成本背后的直觉。通过改变等式-1 中 m 的值,我们可以计算梯度/随机/小批量算法的成本。突出显示的等式定义了假设的成本。如果我们的假设预测值等于真实值,那么成本为零。

图一。最小化成本背后的直觉
在图 2 中,我们定义了梯度下降方程。我们还在学习参数θ和特定θ值下的假设相关成本之间绘制了一条曲线。θmin 左侧所有点的斜率为负,θmin 右侧所有点的斜率为正。

图二。定义梯度下降
现在,让我们看看梯度下降如何帮助我们的假设达到最小值(最小化成本)。正如我们从图 3 中看到的,在θmin 时成本最小,所以我们的梯度下降方程应该帮助我们得到那些成本最小的θ值,即θmin。当我们试图找到更好的θ时,我们正在向全局最小值前进。这就是梯度下降算法的妙处。

图三。梯度下降如何帮助达到最小值
动量(内斯特罗夫加速动量)
对于数据科学中的每一个算法来说,达到最佳的最优解非常重要,因为它决定了我们的模型的准确性和表现。在当前情况下,我们能多好多快地达成一个最佳解决方案(最小化成本)很重要。这就是物理学可以帮助我们实现的地方,使用一种叫做动量的现象。动量可以认为是物体运动时获得的一种动力。当我们把球滚下山时,它的速度会增加,因为它倾向于向山下的相同方向移动,因此动量会很快到达山底(最小成本)。类似地,如果我们在梯度下降算法中倾向于以相同的方向移动以最小化成本,那么为什么不以更高的速度移动以快速到达最小值。
我们举个例子简单解释一下这个动量概念。在图 4.1 中,我们有一个场景,一个人需要从 A 点移动到 b 点。我们假设在每次迭代中,这个人只能移动两步。比较图 4.2 中没有动量和有动量的两种情况,我们可以通过使用动量的概念大大减少到达目的地 B 的时间。

图 4.1 动量方程如何帮助快速达到目标

图 4.2 动量方程如何帮助快速达到目标
类似地,我们可以重新考虑动量梯度下降方程,如图 5 所示。动量有助于参数θ达到成本最小的值,通过取梯度变化的大值可以快得多。

图五。用随机梯度下降定义内斯特罗夫加速动量
当我们滚一个球下山时,当球到达底部时,它有一个很大的加速度,它不会在底部停下来,而是越过底部。类似的情况也发生在我们的内斯特罗夫加速动量算法中,但是当我们移动曲线的右侧时,斜率从负值变为正值,因此它试图减小动量。最后,在底部振荡之后,对于参数θ的特定值,实现成本函数的最小值。
随机梯度下降中添加动量的影响
在图 6 中,我们比较了两种梯度下降算法达到最小成本值所需的迭代次数。随机梯度下降需要 35 次迭代,而内斯特罗夫加速动量需要 11 次迭代。因此,可以清楚地看到,内斯特罗夫加速动量很快达到最小值,因为它在同方向移动时获得了动量,并在达到最小值之前进行了大的θ跳跃。

图六。比较 SGD 和 NAM-SGD 达到全局最小值所需的步骤数
这里有很多内容可以展示高级梯度下降算法背后的数学原理。我已经尽力使它尽可能简单。在下面的帖子中,我将涵盖其他 AdaGrad、RMSprop 和 Adam 算法,这些算法在深度学习领域的当今优化技术中被广泛使用。我会向你解释简单的方法,以及在什么时候使用哪种方法。到时候见!
特别感谢尤里·内斯特罗夫,这一启蒙运动背后的数学家。
分类任务的目标编码
设置上下文以实现多类分类的目标编码

在 Unsplash 上由 Silvan Arnet 拍摄的照片
背景
最近我做了一个项目,其中的目标是多类。这是一项简单的预测任务,数据集既包括分类特征,也包括数字特征。
对于那些想知道什么是多类分类的人:如果你想用‘0 对 1’、‘点击过的对没点击的’或者‘猫对狗’来回答,你的分类问题是二进制的;如果要用‘红色 vs 绿色 vs 蓝色 vs 黄色’或者‘轿车 vs 舱口 vs SUV’来回答,那么问题就是多级的。
因此,我正在研究合适的方法来编码分类特征。不用猜,我被带到了 medium 文章中,列举了 mean target 编码的好处,它如何优于其他方法,以及如何使用 category_encoders 库只用两行代码就完成了任务。然而,令我惊讶的是,我发现没有文章在多类目标上演示这一点。我查阅了 category_encoders 的文档,发现它没有提到支持多类目标。我深入研究了一下源代码,发现这个库只适用于二进制或连续目标。
所以我想:“每一个问题背后都蕴藏着一个机会。”—罗伯特·基波萨基
继续深入,我直奔丹尼尔·米西-巴雷卡的原始论文,该论文介绍了平均目标编码。不仅对于回归问题,本文还给出了二元分类和多类分类的解决方法。这也是 category_encoders 引用的关于目标编码的论文。
虽然有几篇文章解释了回归和二进制分类问题的目标编码,但我的目标是实现多类变量的目标编码。然而,在此之前,我们需要了解它是如何对二进制目标完成的。在本文中,我将概述介绍目标编码的文章,并通过示例展示目标编码如何解决二进制问题。
该理论
简而言之,这篇论文对分类目标是这样说的:
(如果您希望通过示例来理解,请跳过本节)
人们可以将一个类别的每一次出现映射到目标属性的概率估计。在分类场景中,数字表示对应于目标的后验概率,由分类属性的值决定。给定分类属性的值,这实际上是目标期望值的数字表示。为了避免由于一个类别中的少量观察值而导致的过度拟合,还应用了均值平滑。
让我们实际地看待这个问题。在二元问题中,目标不是 0 就是 1。然后,分类变量中的类别的概率估计可以由经验贝叶斯概率 P(Y=1|X=Xi)给出,即

其中,n(TR)是总行数,n(Y)是目标值为 1 的总行数,n(i)是第 I 个类别的行数,n(iY)是第 I 个类别中目标值为 1 的行数。因此,第一项中的分数表示第 I 类中概率为 1,而第二项中的分数表示整体数据中概率为 1。λ是一个给出单调权重的函数,当我们有少量的几个类别时,这很有帮助,随着 n(i)计数从 0 到 1 增加。

如果您使用了 category_encoders 库中的 TargetEncoder,k 是“min_sample_leaf”参数,f 是“smoothing”参数。
引入加权因子是有意义的,因为当样本量很大时,我们应该对上面第一项提供的后验概率估计值给予更多的信任。然而,如果样本量很小,那么我们用从属属性的先验概率(即所有 y 的平均值)给出的零假设来代替概率估计。通过这种转换,丢失的值被当作另一个变量来处理。
本文也将同样的概念推广到多类目标。我们对每一类目标都有一个新的特性。在给定分类属性的值的情况下,每个特征实际上是一类目标的期望值的数字表示。当然,如果目标有非常多的类,输入的数量会显著增加。然而,实际上班级的数量通常很少。请在我的下一篇文章中阅读更多相关内容。
在下一节中,我们用一个例子来看看二进制分类的情况。
一个例子
让我们看一个二进制目标例子。

如果特征性别的类别是‘男性’,目标为 1 的概率是多少?
是 1/2=0.5。
同样,如果特征性别的类别是‘女性’,目标为 1 的概率是多少?
是 1/4=0.25。
够简单吗?
等等,现在如果你用 0.25 代替所有出现的“女性”,你就冒了所谓的过度拟合的风险。这是因为你没有考虑到 1 的总概率不是 0.5。是 4/9=0.4。
为了说明这一事实,我们使用上一节中显示的公式,给这个“先验”信息添加一个权重。
设置 min_sample_leaf,k=1 和平滑,f=1,
对于‘男性’,我们有两行,所以 n = 2;
λ(‘Male’)=1/(1+exp(-(2–1)/1))=0.73 # Weight Factor for 'Male' Target Statistic=(Weight Factor * Probability of 1 for Males)
+ ((1-Weight Factor) * Probability of 1 Overall)S(‘Male’)=(0.73 * 0.5) + ((1–0.73) * 0.4) = 0.485
同样,对于‘女性’,我们有四行,所以 n = 4;
λ(‘Female’)=1/(1+exp(-(4–1)/1))=0.95 # Weight Factor for 'Female'Target Statistic=(Weight Factor * Probability of 1 for Females)
+ ((1-Weight Factor) * Probability of 1 Overall)S(‘Female’)=(0.95 * 0.25) + ((1–0.95) * 0.4) = 0.259
如果您仔细观察,您可能会注意到λ有助于突出那些行数较多的类别。在我们的例子中,有 4 行性别“女性”,而只有 2 行性别“男性”。相应的权重因子分别为 0.95 和 0.73。
因此,用 0.485 替换所有出现的“男性”,用 0.259 替换所有出现的“女性”。“其他”的值可以以类似的方式计算。
恭喜你!您刚刚实现了目标编码。
不信任我?
通过运行下面的代码自己检查一下,它使用您最喜欢的 category_encoders 库做同样的事情:
!pip install category_encodersimport category_encoders as cex=['Male','Male','Female','Female','Female','Female','Other','Other','Other']y=[1,0,0,0,0,1,1,1,0]print(ce.TargetEncoder().fit_transform(x,y))
结论
在本文中,我介绍了 category_encoders 库的 TargetEncoder 类的一个缺点。我解释并总结了介绍目标编码的文章。我通过一个例子解释了如何用数值代替类别。
我的下一篇文章将完全集中在我们如何对多类目标做同样的事情。敬请期待!
编辑:发表下一个,演示实现多类目标编码这里。
在 LinkedIn 上与我联系
在 GitHub 上查看一些我感兴趣的项目
关于类型:显式与隐式,静态与动态
快速浏览类型以及它们如何与语言交互。

(图片由作者提供)
虽然编程通常被认为是非常复杂的活动,但从最简单的定义来看,它相对容易理解。所有的编程都以移动数据和处理数据为中心,没有例外。即使在编程的最底层,编写机器码,目标也是在注册表和内存地址之间来回移动数据。我个人喜欢将这些编程目标分成四个不同的类别。
- 获取数据
- 使用数据
- 修改数据
- 发送数据
编程的时候大部分时间都在使用这四个操作中的一个。虽然循环和条件是允许我们操作和处理这些数据的工具,但首先是类型允许我们存储和创建数据。虽然类型是一个很容易理解的概念,但是在编程语言的幕后有很多事情会影响到在特定语言中如何创建、处理和使用类型。在很大程度上,这些观察包括语言处理关于类型的错误(类型错误)的方式,以及在语言的执行中如何处理类型。
静态与动态类型
许多编程语言的一个显著区别是它们的编译器处理类型的方式。很可能大多数程序员都熟悉“静态”和“动态”这两个术语,但是这两个术语暗示了什么类型呢?
静态类型是指在执行时创建的类型。这意味着,在这种语言运行它的代码之前,它就已经知道它将使用什么类型,以及它们将如何彼此交互。静态类型具有使类型不可变的优势,这意味着您的数据可以安全地驻留在所述类型中,并且通常需要完成从所述类型中检索数据的工作。这对于需要这种类型应用的代码来说非常好。然而,每当您需要在不同场景中不断改变和使用的类型时,寻找动态类型语言作为解决方案可能是明智的。
动态类型化指的是编译器在运行时处理更多的类型,而不是在编译程序时。像静态类型一样,这当然有应用,但也会产生问题——特别是如果程序员不知道类型在语言中是如何使用的。说静态类型语言或动态类型语言更好可能有点愚蠢,但是对于数据科学中的大多数应用程序来说,动态类型可能是最好的选择。也就是说,在数据科学中使用静态类型语言当然也有好处。
隐式与显式类型
程序员应该熟悉的另一个非常重要的概念是隐式和显式类型声明。在使用一门新语言时,这一点可能比它是静态类型还是动态类型更重要。当然,这是主观的,但是我记得我很早就开始使用 JavaScript,因为它会不断地假设我想要使用什么类型——看起来是随机的。隐式和显式类型,也称为强类型或弱类型,是一种编程语言将应用于类型断言的假设量。
隐式类型可以让你摆脱困境,并且在很多情况下让编程变得更加流畅。然而,这样做的缺点是,有一种编程语言会猜测您在幕后试图做什么,这是一个非常严重的缺点。当您对错误的反应是
“它连一根弦也没有!为什么突然变成一串了?!"
另一方面,显式类型可能会使转换类型和使用类型变得更加困难,但是会产生更可预测的结果。显式是这里的关键词,因为没有假设类型声明,没有显式的指令,类型不会神奇地转换。
对一些语言进行分类
最后,为了给出这些概念的含义以及它们在类型中的位置,看看你的语言在更大的画面中的位置可能是个好主意。从许多数据科学家选择的武器开始,Python 是一种非常动态类型化的语言。这一点尤其有效,因为 Python 是一种由 c 语言运行的解释型语言。尽管如此,Python 并不假定你想对你的类型做什么,而且在很大程度上是非常严格和明确的。虽然这不是一门精确的科学,但我认为 Python 会在这两个因素之间找到平衡点:

(图片由作者提供)
如果我没有把我生命中的爱人朱莉娅纳入讨论,这就不是我写的文章。虽然 Julia 肯定是动态类型的,但它利用方法来创建类型之间的不变性和不兼容性,这在某些情况下是不可能的。也就是说,尽管在静态类型化的传统定义范围内,Julia 不是,但考虑到它的即时编译器在执行时编译代码,Julia 也可以被认为比 Python 之类的东西更静态一些。就含蓄或明确而言,Julia 对类型非常认真,不会随便乱搞。这是我真正欣赏朱莉娅的地方,也是我个人更喜欢的地方。

(图片由作者提供)
当我们浏览科学计算的语言时,R 当然是一种值得归类的语言。就动态性而言,r 与 Python 相似,但是在处理类型断言的方式上却有很大的不同。更具体地说,R 可能是一种难以置信的隐性语言。
另一种许多人可能都有过经验,并且可能都很熟悉的语言是一种叫做 JavaScript 的小语言。JavaScript 是一种语言,实际上我很难适应它,因为它在早期具有隐含的本质。虽然肯定有一些更含蓄的语言的例子可以指出,但我要说的是,在我使用过的语言中,它可能是最含蓄的语言之一。

(图片由作者提供)
最后,让我们看看一种可能用于数据科学的静态类型语言。在这个领域中最流行的是 C++。由于 C++的速度、历史以及在科学和其他计算领域的影响力,对于那些寻求在这种范式中工作的人来说,c++是一个很好的面向对象的选择。C++是一种静态类型的、显式的语言——正如您所料。

(图片由作者提供)
结论
打字的想法对于一个编程语言角色来说是至关重要的。虽然可以说某些活动用其中一种可能会更好,但这通常是主观的,大多数语言,不管它们在我上面举例说明的指南针上处于什么位置,通常都可以执行相同的任务——也就是说,不考虑性能或级别。
也就是说,虽然这些因素不一定会限制编程语言做某些事情的能力,但是如果使用这种语言的人不知道他们的编程语言的本质,它会对生产率产生很大的影响。知道如何正确地使用和操作你的编程语言是很重要的,当你的语言想承担一些事情,或者你想随时编辑类型的时候,这一点更是如此。此外,在选择编程语言时,这些因素也可以应用到您的选择中,并且是决策过程中的一个重要部分。也许你想从事数据科学,并且非常不喜欢弱类型语言,了解 R 和 Python 之间的这种差异可能是促使你做出结论的一个巨大因素。
另一件要记住的重要事情是——特别是对于显式和隐式类型,这些决定是有尺度的。虽然在静态和动态类型上采取非常规的观点也是如此,但通常这些只是一个布尔值 yes 或 no。有这么多有创意的语言编译器,有些可能两者兼而有之,或者您可能会遇到像 Julia 这样的东西,它能够在任何需要的时候利用两者的优点。
一张图中线性回归的所有假设和含义
你唯一需要的图表+视频讲解
丹·万鲁宁的帖子
为了恰当地解释线性回归,您需要理解满足哪些假设以及它们意味着什么。
下面的图表总结了关键假设及其含义(首先是有限样本 OLS,然后是渐近 OLS)。然后我分享了一个视频,在视频中我讨论了实验的假设,以及它们如何符合回归的假设。最后,我总结了一些关于线性回归假设的要点。
关键假设


假设的视频讨论
线性回归假设:要点
无偏性/一致性
我们希望我们的系数平均来说是正确的(无偏的),或者至少在我们有大量数据的情况下是正确的(一致的)。
如果你想要无偏的系数,关键的假设是严格的外生性。这意味着给定回归中使用的协变量,回归中误差项的平均值为 0。
对于一致的系数,关键的假设是“预定的回归变量”,这是一个花哨的说法:误差项和回归的任何协变量之间没有相关性。
严格地说,如果不随机分配您希望得到正确系数的协变量,就无法确认这些假设是正确的。没有随机分配,你必须做出一个定性的论证,假设是满足的。然而,如果您在 y 轴上绘制残差散点图,在 x 轴上绘制预测结果值,并且存在远离 0 的系统趋势,则表明该假设不成立。
例如,让我们假设我们正在模拟一个人花在狗美容上的钱的数量作为狗的大小的函数。我们还假设喜欢大狗的人倾向于在狗狗美容上花更多的钱(这是一个我们无法控制的混杂因素)。下面的代码为这个示例和上面建议的图创建了一个示例数据集,这表明假设不成立。这解释了为什么我们估计的大小系数与我们设定的真实值相差甚远。

系数远离+2 的真实效果

假设对于理解系数估计的精度也很重要。
了解系数的精度
无偏/一致系数不需要同伦方差和正态性。如果您想了解使用快捷方法(如 f 检验)测量系数的精确度,只需要这些额外的假设。然而,你总是可以使用异方差稳健标准误差、自举或随机化推断来理解精度。
如果你喜欢这篇文章,请在 stat exchange 上投票支持我的回答,这样更多的人可以从中学习。
所有的深度学习都是建立统计模型

作者图片
深度学习通常用于为数据驱动的分析进行预测。但是这些预测的意义是什么呢?
这篇文章解释了深度学习中使用的神经网络如何提供描述事件发生概率的统计模型的参数。
事件的发生和任意的不确定性
数据、可观察的事物、事件或任何其他描述我们可以看到和/或收集的事物的方式都是绝对的:我们在一对六面骰子上掷出两个六,或者我们得到一些其他结果的组合;我们掷硬币 10 次,每次都是正面,或者是正面和反面的混合。我们的宇宙以某种方式进化,我们观察它,或者它没有——我们没有。我们不知道,,我们是否会在每次投掷硬币时掷骰子或掷人头得到两个六,或者有什么可能的宇宙存在,让我们能够形成并观察它。我们把这种由于缺乏知识而产生的不确定性描述为任意性。这是由于关于这种数据生成的基本信息缺失——我们永远无法确切知道我们将获得什么结果。我们可以认为随机不确定性是无法知道某个随机数生成过程的随机种子。
我们用函数描述事件发生的概率,p‖:‖d∈‖e‖↦‖p(d)∈‖【0,1】,即概率分布函数,p *E. 如果一个事件不可能发生,那么p(d);=0,而某个结果有概率p(d);=1。 这个概率是可加的,使得所有可能事件的联合d∈e是确定的,即 p(e)=*1。**
稍微滥用一下符号,我们可以写成d‖~‖p,这意味着某个事件 d 是从所有可能事件 E 的空间中抽取出来的,概率为 P(d) 。这意味着观察到事件 d 的概率为 100× P(d) %。 d 可以是一个过程的任何观察、事件或结果,例如,当掷出 n = 2 个六面骰子,两个都得到一个六时, d = (d = 0,d = 0,d = 0,d ⁴ = 0,d ⁵ = 0,d ⁶ = 2 我们事先并不知道通过掷骰子会得到什么结果,但是我们知道有一定的可能性会得到任何特定的结果。在多次重复掷骰子实验(骰子完全平衡且条件相同)后,我们应该看到 d 发生的概率是p(d)≈/₃₆.即使不重复多次掷骰子,我们也可以提供我们相信的对我们看到特定结果的可能性分布的估计。
统计模型
为了进行统计预测,我们使用参数化分布 Pₐ 对数据分布进行建模。我们可以认为 a 定义了一个统计模型,它包含了数据分布的描述和模型的任何可能的不可观察参数 v ∈ Eᵥ 。然后,分布函数将概率值归因于可观察/不可观察事件的发生 Pₐ : (d,v) ∈ (E,Eᵥ ) ↦ Pₐ(d,v)∈【0,1】。需要注意的是,我们可以把这个联合概率分布写成一个条件语句,pₐ=lₐpₐ=ρₐeₐ。这些概率分布函数是:
- 可能性——lₐ:(d,v) ∈ (E,eᵥ)↦lₐ(d|v)∈【0,1】
- 先验——pₐ:v∈eᵥ↦pₐ(v∈【0,1】
- 后方——ρₐ:(d,v) ∈ (E,eᵥ)↦ρₐ(v|d)∈【0,1】
- 证据——eₐ:d∈e↦eₐ(d)∈【0,1】
这些函数的引入允许我们将观察到 d 和 v 的概率解释为,在给定模型参数值 v、的情况下,观察到 d 的概率乘以这些模型参数值的可能性——同样,它也等于给定观察到 d 的情况下,模型参数值 v、的概率乘以在中观察到 d 的可能性
对于掷骰子实验,我们可以(也确实)使用多项式分布来模拟数据的分布, Pₐ = ∏ᵢ n!/d ⁱ! pᵢ ᵈⁱ其中多项式模型的固定参数为 v = {p₁、p₂、p₃、p₄、p₅、p₆、n } = { p \,n | I∈【1,6】}其中p *为从骰子中获得数值I∈【1,6】的概率如果我们考虑完全无偏的骰子,那么p₁=p₂=p₃=p₄=p₅=p₆=/₆.观察到两个六的概率, d = (d = 0,d = 0,d = 0,d ⁴ = 0,d ⁵ = 0,d ⁶ = 2),我们用 n = 2 掷骰子的多项式模型中的因此可以估计为 Pₐ(d)由于模型参数 v 是固定的,这相当于为I∈【1,6】设置了pₐ=δ(pᵢ/₆,n2)的先验值,使得lₐ=∏ᵢ2(/₆)ᵈⁱ/dⁱ!或者 0。*
当然,我们可以建立一个更复杂的模型,其中 pᵢ 的值取决于其他因素,例如骰子可以弹开的表面数量,或者投掷的力度,或者在骰子离开我们手的那一刻击中骰子的每个空气分子的速度,或者无数种不同的效果。在这种情况下,分布 Pₐ 将根据描述这种物理效应的不可观察参数 v 、即之间的相互作用,为数据 d ~ P 的出现分配概率,在多项式模型中,模型参数的值 v、将改变描述 d 有多可能的 pᵢ 的值然而,我们可能不知道这些不可观测参数的确切值。因此 Pₐ 不仅描述了对数据真实分布的估计,还描述了其对不可观测模型参数的依赖。我们把描述来自不可观测参数的观测数据的概率的条件分布函数称为似然、* Lₐ 。由于模型 a 描述了整个统计模型,模型参数 v 的先验概率分布 pₐ 是模型的固有属性。*
我们不知道模型 a 中参数的值 v (甚至缺乏关于模型本身选择的知识)这一事实引入了不确定性的来源,我们称之为认知——这种不确定性是由于我们可以通过观察事件的支持了解到的事情。因此,尽管由于来自数据分布 P 的事件 d 发生的真实随机性质而存在随机不确定性,但也存在认知不确定性,这种认知不确定性来自使用 Pₐ 对该分布进行建模。然而,先验分布 pₐ 不应该与认知不确定性混淆,因为先验是对特定模型和的选择。可能使用不明智的先验分布选择(由于统计模型的定义),这不允许模型得到数据的支持。
例如,对于掷骰子问题,当我们建立一个模型时,我们可以决定我们的模型是确定的,并且模型参数的可能值的先验分布是pₐ=δ(pᵢ/₆,n-2)对于I∈【1,6】。在这种情况下,认知的不确定性将不被考虑在内,因为假设没有什么我们可以了解的。然而,如果骰子被加权,使得 p₁ = 1,p₂ = p₃ = p₄ = p₅ = p₆ = 0 ,那么我们将永远得不到两个 6,我们的模型也不会得到数据的支持。相反,如果我们选择一个不同的模型a’,它是一个多项分布,但是其中关于 pᵢ 的可能值的先验分布是这样的,在∑ ᵢ pᵢ = 1 的条件下,它们可以取从 0 到 1 的任何值,那么没有假定的知识(在这个特定的模型内)。因此,由于我们缺乏知识,存在着很大的认知不确定性,但这种不确定性可以通过在观察可用数据时推断可能的参数值来减少。
主观推断
我们可以使用主观推断(通常称为贝叶斯推断)了解观察到的数据支持哪些模型参数值,从而减少我们选择模型时的认知不确定性。使用联合分布的条件展开的两个等式, Pₐ,我们可以计算后验概率,在模型 a 中,当某个 d ~ P 被观察到时,参数具有值 v

这个后验分布现在可以用作新模型的基础,a′,具有联合概率分布pₐ′,其中pₐ′=ρₐ,即 pₐ′=lₐ**pₐ′。请注意,模型的形式没有改变,只是由于数据的支持,我们对模型参数的确定性有所改变——我们可以使用这个新模型对数据的分布做出更明智的预测。
在众多方法中,我们可以使用 MCMC 技术来描述后验分布的特征,从而减少这一假设模型中的认知不确定性。然而,无论对错,人们通常只对数据的最佳拟合分布感兴趣,即找到 v 的集合,其中 Pₐ 与p最相似
最大似然和最大后验估计
为了使模型符合数据的真实分布,我们需要测量两个分布之间的距离。最常用的度量是相对熵(也称为 Kullback-Leibler (KL)散度)

相对熵描述了由于用 Pₐ(d,v) 逼近 P(d) 而丢失的信息。相对熵有一些有趣的性质,这使得它不能作为理想的距离度量。首先,它不是对称的,d(p∩pₐ)≦d(pₐ∩p),因此它不能被用作度量。我们可以采用d(pₐ∩p)和d(p∩pₐ)的对称组合,但问题仍然存在,例如 P 和 Pₐ 必须定义在同一个域上, E 。其他测量,例如推土机距离,在这里可能具有优势,因为它是对称的,并且可以在不同的坐标系上定义(并且当用作任意函数而不是用于预测模型参数时,现在可以使用神经网络很好地近似)。然而,我们仍然经常考虑相对熵。重写相对熵我们看到,我们可以用两个术语来表示相似性的度量

第一项是数据分布的负熵,即通过观察一个结果可以获得的预期信息量,直接类比于统计热力学中的熵。第二项是交叉熵, H(P,pₐ),它量化了将一个分布 P 与另一个分布 P ₐ 区分开所需的信息量,即需要多少次 d ~ P 的抽取才能判断出 d 是从 P 中抽取的,而不是从 P 中抽取的注意,在这种相对熵的形式中,只有一组自由参数 v ,然后我们可以尝试通过最小化相对于这些参数的相对熵,使 Pₐ 尽可能接近 P

但是我们实际上是如何做到的呢?我们可能无法访问所有可能的数据分布来进行积分。相反,考虑一个采样分布,s:d∈s↦s(d)∈【0,1】,其中 s(d) 是来自采样空间的事件的归一化频率,其中 N 的条件独立值为 d , S ⊆ E 。在这种情况下,积分变成一个和 H(P,pₐ)≊∑s(d)logpₐ(d,v)。使用条件关系,我们然后如前写下 Pₐ = Lₐ pₐ ,这样交叉熵是 H(P,pₐ)≊∑s(d)loglₐ(d| v)∑s(d)logpₐ(v).由于先验独立于数据,它只是向交叉熵添加了一个附加常数。
换句话说,我们可以把可能性写成概率的乘积,给出抽样分布中数据出现的频率

所以,除了由于先验的加性常数,交叉熵与模型中数据的似然负对数成正比。这意味着最大化数据相对于模型参数的可能性的对数,假设所有 v 的均匀先验(或忽略先验)等同于最小化交叉熵,这可以解释为最小化相对熵,从而使 Pₐ 尽可能接近 P 。忽略交叉熵中的第二项提供了参数值的非主观最大似然估计(非主观意味着我们忽略了参数值的任何先验知识)。然而,如果我们考虑先验,我们恢复最简单形式的主观推断,最大后验概率(MAP) 估计

其描述了一组参数值 v ,其提供尽可能接近 P 的 Pₐ 。这里必须强调一点,因为我们使用抽样分布, s,最大化可能性(或后验概率)实际上为我们提供了最接近抽样分布的分布 Pₐ , s 。如果 s 不代表 P,则该模型不一定是 P 的合适模型。第二点需要注意的是,尽管 Pₐ 可能尽可能接近 P (或实际上 s ) 与这组 v ,但可能性(或后验概率)的模式实际上可能远离分布的高密度区域,因此根本不能代表更可能的模型参数值。当使用 MCMC 技术或类似技术考虑整个后验分布时,这是可以避免的。本质上,使用最大似然或最大后验估计,认知误差将被大大低估,而没有考虑大部分先验(或后验)概率密度。
模型比较
请注意,到目前为止还没有声明说一个型号一个实际上有任何好处。我们可以通过计算证据来测量模型与数据 d 的拟合程度,这相当于对模型参数即的所有可能值进行积分

通过选择一个不同的模型a’和它自己的一组参数 u ∈ Eᵤ ,我们可以得出一个标准来描述是模型 a 还是a’更符合数据 d 。请注意,该标准不一定定义明确。我们是更喜欢与数据完全吻合但具有半无限数量参数的模型,还是更喜欢参数很少但拟合度不太好的优雅模型?在神经网络出现之前,我们通常选择参数最少的模型,这些模型能够很好地拟合数据,并进行归纳,以对未来事件做出一致的预测——但这仍有待讨论。
到目前为止所描述的一切都是科学方法。我们观察一些数据,并希望对未来观察的可能性进行建模。因此,我们建立一个参数化的模型来描述观察结果和它发生的可能性,了解该模型参数的可能值,然后根据某些标准(如奥卡姆剃刀或其他标准)来改进该模型。
神经网络作为统计模型
深度学习是一种建立数据分布模型的方法
不管目标是什么——监督学习、分类、回归、生成等等——深度学习只是为数据的分布建立模型。对于监督学习和其他预测方法,我们认为我们的数据, d,是一对输入和目标, d = (x,y) 。例如,我们的输入可以是猫和狗的图片, x ,附带标签, y 。然后,我们可能想要对先前未看到的图像x’进行标签y’’的预测——这相当于对一对相应的输入和目标 d、进行预测,假定部分 d 是已知的。
因此,我们希望使用神经网络对分布 P 进行建模, f: (x,v) ∈ ( E,Eᵥ) ↦ g= f(x,v) ∈ G ,其中 f 是一个由权重、 v、参数化的函数,它接受输入 x 函数的形式 f 由超参数化a描述,包括架构、初始化、优化例程,以及最重要的损失或成本函数λₐ:(d,v) ∈ (E,eᵥ)↦λₐ(y|x,v) ∈ K [0,1】。损失函数描述了数据出现概率的非标准化度量, d = (x,y),带有不可观察参数, v 。也就是说,当给定 x 时,使用神经网络对 y 进行预测等同于对数据 d 出现的概率 P 进行建模,其中分布的形状由网络 a 的形式和属性以及 it 参数 v 的值来定义。我们通常将经典神经网络(预测目标)与神经密度估计器(估计输入的概率,即空间 G = [0,1】)区分开来——然而,它们执行相同的工作,但是来自经典神经网络的分布只能使用损失函数来评估(并且通常不像真实概率那样归一化为 1)。这阐明了经典神经网络的输出或预测的意义-它们是控制我们模型中数据概率分布形状的参数值(由超参数的选择定义)。
例如,当使用均方误差作为损失函数来执行回归时,神经网络的输出 g = f(x,v) 相当于具有单位方差的广义正态分布的平均值。这意味着,当馈入一些输入 x 时,网络通过参数的值 v、提供对 y 的可能值的平均值的估计,其中 y 的可能值是从具有单位方差即 y ~ N(g,I)的广义正态中提取的。请注意,无论如何,这种针对 y 值的模型可能都不是一个好的选择。另一个例子是当使用 softmax 输出执行分类时,我们可以将输出直接解释为多项式分布的 pᵢ ,其中模型的不可观察参数 v 以类似于物理模型中的参数影响不同数据出现概率的方式影响这些输出的值。
有了这些知识,我们就可以将网络参数的优化(称为训练)理解为模拟数据的分布, P 。通常,在经典训练一个网络时,我们选择的模型允许 v ~ pₐ = 均匀-∞,∞的任意值。本质上,我们忽略了关于权重值的任何先验信息,因为我们没有任何先验知识。在这种情况下,所有关于数据分布的信息都来自于可能性, Lₐ 。因此,为了训练,我们执行网络参数的最大似然估计,这最小化了数据分布和来自神经网络的估计分布之间的交叉熵,因此最小化了相对熵。为了实际评估具有参数值 v 的经典神经网络的似然对数,我们可以将一些观察数据 d 的似然展开为lₐ(d| v)≊λₐ(y| x,v)s(x)其中 s(x) 是 x 的采样分布,相当于指定 x 在中出现的次数的归一化频率当给定相应的 x,时,在抽样分布中的每个 y 处评估λₐ(y| x,v)* ,取该概率的对数并对结果求和,从而给出抽样分布的可能性的对数。相对于网络参数最大化这一点, v ,因此给出了分布, Pₐ ,其最接近 s (其应该有希望接近 P )。*
仅此而已。一旦经过训练,神经网络提供了统计模型的参数,可以对这些参数进行评估以找到最可能的预测值。如果损失函数给出一个非标准化的似然性,像 MCMC 这样的方法可以用来获得表征数据分布的样本。
必须考虑一些注意事项。首先,损失函数的选择定义了统计模型—如果损失函数无法描述数据的分布,那么数据分布的统计模型将是错误的。避免分布假设的一种方法是考虑均方差、分类交叉熵或绝对误差之外的损失函数——一个理想的选择是推土机距离,它可以通过特定类型的神经网络很好地近似,并提供一个目标,模拟数据分布到统计模型之间的最佳运输计划,从而为 Pₐ 提供一个未假设的形式。另一件需要注意的事情是,使用神经网络的统计模型被过度参数化了。宇宙演化的模型只需要 6 个参数(在天气好的时候)——而神经网络会使用数百万个无法识别的参数来完成更简单的任务。在追求模型优雅的情况下进行模型选择时,神经网络几乎总是会失败。最后,基于数据,使网络适合数据——如果数据中存在任何偏差, d ∈ S ,即 s 与 P、不相似,则偏差会很明显。物理模型可以通过建立直觉来避免这些偏见。事实上,神经网络也可以做到这一点,但代价是要比盲目挑选东西花费更多的脑力和更多的时间来编写代码。
所以深度学习使用神经网络和损失函数,相当于建立一个描述数据分布的参数化统计模型。
汤姆·查诺克是统计学和机器学习方面的专家。他目前在巴黎工作,致力于解决机器学习和人工智能模型的统计可解释性方面的突出问题。作为一名国际自由职业顾问,他为与复杂数据分析、数据建模和计算机科学的下一代方法相关的问题提供实用的解决方案。他的职责包括一对一的支持、全球协作以及通过讲座、研讨会、教程和文章进行推广。
各种很酷的功能定标器
通过选择合适的工具优化连续特征。

什么是定标器?
要素缩放器是一种训练工具,可让您通过使用线性代数获得更好的训练数据。一些目标函数严重依赖于,事实上,如果没有适当的缩放,就无法正常工作。在数据处理中,特征缩放也称为“数据标准化”,这种标准化通常在处理和清理步骤中进行。
缩放器专门用于连续要素,因为缩放器的目的是降低数据的方差,以使大多数预测位于数据最多的区域。除此之外,使用定标器绝对可以提高你的准确性。
很多人没有意识到实际上有多少个定标器。这是因为通常情况下,z 分数归一化定标器是最有效的。在过去,我曾用一个重定标器来降低精确度,用一个单位长度定标器来提高精确度。这进一步说明了有时在数据科学中,
这要看数据。
重新标度

重新缩放或最小-最大规范化使用最小值和最大值来缩放数组。虽然这很酷,但我真的没有发现它对机器学习有用。我会说,检查它只是为了信息和学习,因为在我的经验中,这个标量通常会扰乱估计并破坏准确性。在一种情况下,我能够使用一个重定标器作为一个端点上坏数据输出的最小-最大过滤器。虽然这肯定不能弥补损失,但我认为这绝对是一个很酷的用法。如果你想试试这个定标器,它在车床里!
using Lathe.preprocess: Rescalar
?(Rescalar)
Rescalar scales a feature based on the minimum and maximum of the array.────────────────────────────────────────────────────────────────────────────array = [5,10,15]scaled_feature = Lathe.preprocess.Rescalar(array)
为了缩放您的要素,您需要首先获得 x 的最小值和最大值,然后 x 将被分子上的最小值减去,最大值减去分母上的最小值。对于那些希望在代码中看到它的人来说,
function Rescalar(array)
min = minimum(array)
max = maximum(array)
v = [i = (i-min) / (max - min) for i in array]
return(v)
end
均值归一化

均值归一化顾名思义就是基于均值对数据进行归一化。这一个当然可能是有用的,唯一的问题是,通常 z 分数标量在归一化数据方面比均值归一化器好得多。还好车床也有这个!公式很简单,分子上 x 减去均值,分母上 max 减去 min。我没怎么用过这个,因为它通常比标准的定标器返回更低的精度分数。不管这个特定的是否有用,
这是代码
function MeanNormalization(array)
avg = Lathe.stats.mean(array)
a = minimum(array)
b = maximum(array)
v = [i = (i-avg) / (b-a) for i in array]
return(v)
end
任意重新标度
因此,也许你知道所有的重标度、均值归一化和标准标度,但你可能没有听说过任意重标度。与之前的版本相反,我发现这非常有用。当您有一个小的四分位数差距时,任意重新调整特别有用,这意味着中位数离最小值或最大值不远。你猜怎么着?这也是这个的代码!
function ArbitraryRescale(array)
a = minimum(array)
b = maximum(array)
v = [x = a + ((i-a*i)*(b-a)) / (b-a) for x in array]
return(v)
end
标准缩放器

啊,是的——好的标准定标器。标准缩放器,也称为 z 分数规格化器,可能是缩放连续要素的最佳选择。如果你需要提高精确度,这就是方法。我经常使用标准的定标器,可能每天我都会在某个时候使用。对我来说,标准缩放是所有标量中最有用的,对大多数人来说也是如此。
标准定标器的线性公式也非常非常简单。就像从 x 的迭代中减去平均值,然后将余数除以标准差一样简单。至于这样做的代码,也非常简单!:
function StandardScalar(array)
q = Lathe.stats.std(array)
avg = Lathe.stats.mean(array)
v = [i = (i-avg) / q for i in array]
return(v)
end
单位长度标量

我们在机器学习方面的另一个选择是缩放到单位长度。缩放到单位长度可以提供与 z 分数归一化类似的结果,我确实发现它非常有用。这个公式相当简单,尽管现在在车床上还没有支持它的代码库…这是因为单位长度标量在 x 迭代的分母上使用欧几里德距离。整体单位长度缩放对于提高模型的准确性非常有用。
结论
标量太棒了。当您只是运行一个函数来修改您的特征时,获得百分之五到百分之十的精度提升是非常有益的。另一个很大的好处是,大多数定标器背后的数学非常简单,这使得它们更加通用,你甚至可以用计算器来计算。
6 分钟解释所有机器学习模型
最流行的机器学习模型的直观解释。

如果您想测试这些 ML 算法,请查看 土星云 ,这是一个可扩展的、灵活的数据科学平台,有免费层和企业层。

在我之前的文章中,我解释了什么是回归,并展示了如何在应用程序中使用它。本周,我将回顾实践中使用的大多数常见机器学习模型,以便我可以花更多的时间来建立和改进模型,而不是解释其背后的理论。让我们深入研究一下。

机器学习模型的基本分段
所有的机器学习模型被分类为监督的或非监督的。如果模型是监督模型,那么它被细分为回归或分类模型。我们将讨论这些术语的含义以及下面每个类别中对应的模型。
监督学习
监督学习涉及学习一个函数,该函数基于示例输入-输出对将输入映射到输出【1】。
例如,如果我有一个包含两个变量的数据集,年龄(输入)和身高(输出),我可以实现一个监督学习模型,根据年龄预测一个人的身高。

监督学习的例子
重复一下,在监督学习中,有两个子类别:回归和分类。
回归
在回归模型中,输出是连续的。下面是一些最常见的回归模型。
线性回归

线性回归的例子
线性回归的概念就是找到一条最符合数据的直线。线性回归的扩展包括多元线性回归(例如,找到最佳拟合的平面)和多项式回归(例如,找到最佳拟合的曲线)。你可以在我的上一篇文章中了解更多关于线性回归的知识。
决策图表

图片来自 Kaggle
决策树是一种流行的模型,用于运筹学、战略规划和机器学习。上面的每个方块被称为一个节点,节点越多,你的决策树就越精确(一般来说)。决策树的最后一个节点,也就是做出决策的地方,被称为树的叶。决策树直观且易于构建,但在准确性方面有所欠缺。
如果您想测试这些 ML 算法,请查看 土星云 ,这是一个可扩展、灵活的数据科学平台,有免费层和企业层。

随机森林
随机森林是一种基于决策树的集成学习技术。随机森林包括使用原始数据的自举数据集创建多个决策树,并在决策树的每一步随机选择一个变量子集。然后,该模型选择每个决策树的所有预测的模式。这有什么意义?依靠“多数获胜”模型,它降低了单个树出错的风险。

例如,如果我们创建一个决策树,第三个,它会预测 0。但是如果我们依赖所有 4 个决策树的模式,预测值将是 1。这就是随机森林的力量。
StatQuest 做了一项了不起的工作,更详细地说明了这一点。见此处。
神经网络

神经网络的可视化表示
神经网络本质上是数学方程的网络。它接受一个或多个输入变量,并通过一个方程式网络,产生一个或多个输出变量。你也可以说一个神经网络接受一个输入向量并返回一个输出向量,但是我不会在本文中讨论矩阵。
蓝色圆圈代表输入层,黑色圆圈代表隐藏层,绿色圆圈代表输出层。隐藏层中的每个节点代表前一层中的节点经历的线性函数和激活函数,最终导致绿色圆圈中的输出。
- 如果你想了解更多,看看我对神经网络的初学者友好的解释。
分类
在分类模型中,输出是离散的。下面是一些最常见的分类模型。
逻辑回归
逻辑回归类似于线性回归,但用于模拟有限数量结果的概率,通常为两个。在对结果的概率建模时,使用逻辑回归而不是线性回归的原因有很多(见此处)。实质上,逻辑方程是以这样一种方式创建的,即输出值只能在 0 和 1 之间(见下文)。

如果您想测试这些 ML 算法,请查看 土星云 ,这是一个可扩展、灵活的数据科学平台,有免费层和企业层。
支持向量机
一个支持向量机是一种监督分类技术,实际上可以变得非常复杂,但在最基本的层面上是非常直观的。
让我们假设有两类数据。支持向量机将找到一个超平面或两类数据之间的边界,以最大化两类数据之间的差距(见下文)。有许多平面可以分隔这两个类别,但只有一个平面可以最大化类别之间的边距或距离。

如果你想了解更多细节,Savan 写了一篇关于支持向量机的文章在这里。
朴素贝叶斯
朴素贝叶斯是数据科学中使用的另一种流行的分类器。背后的想法是由贝叶斯定理驱动的:

说白了,这个等式就是用来回答下面这个问题的。“给定 X,y(我的输出变量)的概率是多少?因为假设变量是独立的,你可以说:

同样,通过去掉分母,我们可以说 P(y|X)与右侧成正比。

因此,目标是找到具有最大比例概率的类 y。
查看我的文章《 一个朴素贝叶斯的数学解释 》如果想要更深入的解释!
决策树,随机森林,神经网络
这些模型遵循与前面解释的相同的逻辑。唯一区别是输出是离散的而不是连续的。
无监督学习

与监督学习不同,非监督学习用于从输入数据中进行推断和发现模式,而不参考标记的结果。无监督学习中使用的两种主要方法包括聚类和降维。
如果您想测试这些 ML 算法,请查看 土星云 ,这是一个可扩展、灵活的数据科学平台,有免费层和企业层。
使聚集

摘自 GeeksforGeeks
聚类是一种无监督的技术,涉及数据点的分组或聚类。它经常用于客户细分、欺诈检测和文档分类。
常见的聚类技术有 k-means 聚类、分层聚类、均值漂移聚类、基于密度的聚类。虽然每种技术在寻找聚类时有不同的方法,但它们的目标都是一样的。
降维
降维是通过获得一组主变量来减少所考虑的随机变量的数量的过程[2]。简单来说,就是减少特性集的维数的过程(更简单来说,就是减少特性的数量)。大多数降维技术可以分为特征消除或特征提取。
一种流行的降维方法叫做主成分分析。
主成分分析
从最简单的意义上来说, PCA 涉及到将高维数据(如 3 维)投影到更小的空间(如 2 维)。这导致数据的维度降低(2 维而不是 3 维),同时保持模型中的所有原始变量。
这涉及到相当多的数学问题。如果你想了解更多…
点击查看这篇关于 PCA 的精彩文章。
如果你更想看视频,StatQuest 在 5 分钟内解释 PCA这里。
如果您想测试这些 ML 算法,请查看 土星云 ,这是一个可扩展、灵活的数据科学平台,有免费层和企业层。
感谢阅读!
请务必 订阅此处 千万不要错过另一篇关于数据科学指南、技巧和提示、生活经验等的文章!
我希望你觉得这很有趣,很有见地。在评论里让我知道你最喜欢的 2022 年的数据可视化是什么!
不确定接下来要读什么?我为你挑选了另一篇文章:
来自亚马逊、谷歌、脸书、微软等公司的面试问题!
towardsdatascience.com](/over-100-data-scientist-interview-questions-and-answers-c5a66186769a)
或者你可以查看我的媒体页面:
阅读特伦斯·申在媒体上的文章。数据科学@ KOHO,SaturnCloud |理学硕士,MBA |…
terenceshin.medium.com](https://terenceshin.medium.com/)
特伦斯·申
不是所有的名字都一视同仁
探究单词嵌入中的偏见如何影响简历推荐
随着机器学习变得越来越流行,越来越多的任务被自动化。虽然这可能有许多积极的好处,如释放人类的时间来做更具挑战性的任务,但也可能有意想不到的后果。
任何机器算法都是使用人类创造的数据来训练的,这些数据可能传达生成数据或构建模型的人不打算或不想要的信息和想法。有许多模型包含对特定人群的非故意偏见的例子。你可能听说过谷歌的面部识别算法将黑人标记为大猩猩或者更近的亚马逊简历推荐系统的事故,该算法自学男性候选人更受欢迎,并惩罚包含“女性”一词的简历,该词可能出现在“女子高尔夫球队队长”等短语中
尽管这些算法得到了广泛的应用,但是如何解决它们所包含的偏差仍然是一个悬而未决的问题。这也是一个微妙的问题,因为没有明确的数学标准来衡量一个算法有多大的偏差。偏见也没有一成不变的定义;虽然我当然相信女性和任何人一样能够胜任亚马逊的任何工作,并为此而奋斗,但世界上还是有人不相信性别平等。尽管如此,有大量真实世界的例子表明,机器学习算法中的偏见是如何歧视人们并加剧我们社会中的不公正的。
研究人员正在积极研究机器学习算法中的偏见,我鼓励你查看他们的工作,我在本文末尾提供了链接。为了尝试探索偏见是如何影响简历推荐系统的,我自己进行了一些实验。这些只是一个开始,希望能激发更多的问题和研究,而不是解决这个非常复杂的问题。
在解释我的过程时,我会假设你了解机器学习、单词嵌入和自然语言处理。单词嵌入最初是通过谷歌的 Word2Vec 算法流行起来的,但斯坦福的手套嵌入也越来越受欢迎。为了更好地了解 Word2Vec,请查看 Zafar Ali 的教程,为了更好地了解 Glove,请查看 Sciforce 的文章,为了更详细地了解 doc2vec,请查看 Gidi Shperber 对 doc2vec 的介绍。我将简要概述如何在推荐系统中使用单词嵌入,然后深入研究我的实验、结果和后续步骤。
单词嵌入和推荐系统
除了将单词向量相互比较之外,还可以使用各种技术,使用每个文档中单词的单词嵌入来比较文档。在我的实验中,这些文档是谷歌的招聘启事和不同的简历,但是文档可以是任何类型的文本数据。我没有比较代表单个单词的向量,而是创建了文档的向量表示以及它们在向量空间中的距离。在向量空间中具有彼此最接近的向量表示的文档将被认为彼此最相似并被推荐。
在这个实验中,我计算了文档的向量表示(质心),方法是删除停用词,然后取文档中所有剩余词的向量的平均值。在计算了我的示例职位发布和我测试的所有简历的文档质心之后,我比较了职位发布质心和每个测试简历质心之间的欧几里德距离和余弦距离,以对简历进行排序。一般来说,简历推荐系统不仅仅使用平均简历质心来进行推荐,所以请记住,生产中的系统会涉及更多的算法和步骤,但这个实验仍然可以提供见解。
方法论
在这种主观领域没有真正中立的选择,我天生就把我自己的信念融入到我如何设置和运行这个实验中。对于像我这样的研究人员来说,重要的是不仅要检查他们自己的偏见,还要查看其他研究,并与他人合作来减轻偏见。
没有一个名字或一组名字能真正代表任何一群人。许多人的名字并不反映他们自我认同的种族或性别。性别也不是一个二元结构,尽管为了这个实验的目的,我只比较了男性和女性的名字。我选择使用 Aylin Caliskan、Joanna J. Bryson 和 Arvind Narayanan 在他们的论文 中使用的一组名称,这些名称是从包含类似人类偏见的语言语料库中自动导出的语义 。我觉得自己没有资格去挑选甚至可以代表我不属于的一群人的名字,也不会有一组名字可以完全代表任何一个群体。我使用了他们使用的非裔美国人和欧洲人的名字,并进一步将他们分成不同性别的群体。我对比了八套简历,有以下几套名字:
●非裔美国人的名字
●欧美名字
●女性非裔美国人的名字
●男性非裔美国人的名字
●女性欧裔美国人的名字
●男性欧裔美国人名字
●女性名字(结合女性欧裔美国人名字和女性非裔美国人名字)
●男性姓名(结合男性欧裔美国人姓名和男性非裔美国人姓名)
我用美国英语进行这项研究,但这种调查应该在所有语言中进行,由母语人士主导研究。我选择了谷歌软件工程招聘,并创建软件工程简历,因为软件工程是一个公认的高薪领域,目前是男性主导的。谷歌是这一领域的领导者,也是一个非常受欢迎的雇主,所以使用谷歌的招聘信息似乎是一个合理的选择。我还选择了软件工程,因为我觉得通过利用我在数据科学研究中获得的专业知识和工作经验,我可以撰写一份合理的入门级简历。在未来的实验中,查看不同公司和不同领域的招聘信息会很有用。
为了起草我的通用入门级软件工程简历,我综合了来自 indeed.com 的、卡耐基梅隆大学计算机科学系的和 monster.com 的样本软件工程简历。每份简历都包括教育部分、一年相关工作经验、一年非相关工作经验和软件工程项目部分。对于不相关的工作经历,我使用了来自的文本,一份关于工作英雄的理发师简历。

实验用简历;每份简历唯一改变的是名字。
为了计算谷歌招聘信息的质心,我使用 300 维预训练手套嵌入采取了以下步骤:
- 处理了职位发布的文本,创建了一个删除了标点符号和停用词的单词列表(关于停用词的更多信息,请查看马志威关于停用词的帖子)。)
- 对于单词列表中的每个单词,查找 300 维单词嵌入。
- 取这些单词嵌入的平均值作为文档质心。
为了计算每组名字的简历重心,我采取了以下步骤:
- 为组中的每个名称创建了一个简历文本。
- 处理每份简历的文本,为每份简历创建一个单词列表,删除标点符号和停用词。
- 对于单词列表中的每个单词,查找手套 300 维单词嵌入。
- 将这些单词嵌入的平均值作为该组中每个简历的简历质心。
- 计算一个组中所有简历质心的平均简历质心。
- 计算该组的平均简历质心和 Google 职位发布质心之间的余弦和欧几里德距离。

我的流程的高级图表,用于比较姓名组和职位发布的距离。
初步结果
当使用手套向量时,我发现使用欧几里德距离或余弦距离时,有男性欧裔美国人名字的简历与谷歌软件工程简历最接近。下一个最接近的群体是欧裔美国人的名字,其次是全男性的名字。我查看了欧几里德距离和余弦距离,以及每个组与所有组到招聘信息的平均距离的标准差。

结果图表。请查看我的完整笔记本 这里 。
这表明了这些词嵌入中编码的偏见的非故意但却是负面的影响。虽然所有组都在平均值的 2 个标准偏差内,但是当观察组之间的欧几里德或余弦距离的分布时,在组的顺序中有一个清晰的模式。男性欧裔美国人的简历比男性非裔美国人的简历更接近谷歌的招聘信息,大约有 3 个标准差。种族歧视和性别歧视都会影响这些简历的排名。这些简历除了上面的名字之外都是一样的,而且都应该和招聘信息一样接近。

这些图表直观地显示了与职位发布的平均距离的标准偏差。每组简历都标在 x 轴上,y 轴上是它们与职位发布的标准差。具有负值的组意味着其组的平均简历质心比所有组的平均值更接近职务发布质心。相反,具有正值的组表示他们组的平均恢复质心比所有组的平均值更远。
结论和后续步骤
目前,解决单词嵌入中的偏见是一个活跃的研究领域。在有更强有力的解决方案来解决偏见之前,我认为任何使用推荐系统的人都应该从系统排名系统使用的简历文本中删除姓名。暗示候选人性别的职称和经历也可能影响结果,但去除起来更复杂。这些结果只是初步的,这类实验应该用不同的名字、招聘信息等重复进行。在生产中的简历推荐系统中对这些相同的简历进行 A/B 测试也会提供有价值的见解。
在一个公平公正的世界里,每个人的简历都有可能被任何算法推荐,不管他们的名字或身份如何。这只是单词嵌入和机器学习模型中的偏见有害的许多情况之一,在任何研究领域,我们都需要所有我们可以获得的声音和想法。我鼓励你学习更多,与他人合作,如果你所在的公司在你的推荐系统的任何部分使用这种措辞,调查编码的偏见并努力解决它。
特别感谢雷切尔·托马斯和詹姆士·威尔森在这一努力中给予的支持。更多详情请查看我的 GitHub 。我很乐意听到你的想法和建议,以及进一步研究的想法!
我邀请反馈,可以通过 gmail.com>的 keck.quinn <联系到我。感谢阅读!
来源及延伸阅读
Google 相册文章
https://www . USA today . com/story/tech/2015/07/01/Google-道歉-拍照后-识别-黑人-大猩猩/29567465/
亚马逊使用简历推荐系统的不幸
简历算法审计
https://qz . com/1427621/companies-is-on-the-hook-if-they-hiring-algorithms-is-biased/
手套制品
手套项目
https://nlp.stanford.edu/projects/glove/
Doc2Vec 文章
https://medium . com/@ zafaralibagh 6/a-simple-word 2 vec-tutorial-61e 64 e 38 a6 a 1
Word2Vec 文章
https://medium . com/@ zafaralibagh 6/a-simple-word 2 vec-tutorial-61e 64 e 38 a6 a 1
从语言语料库中自动获得的语义包含类人偏见
作者:艾林·卡利斯坎、乔安娜·j·布赖森、阿尔温德·纳拉亚南https://science . science mag . org/content/sci/Suppl/2017/04/12/356.6334 . 183 . dc1/CALIS Kan-sm . pdf
纸张:
【https://science.sciencemag.org/content/356/6334/183? URL _ ver = z 39.88-2003&RFT _ id = doi % 3a 10.1126/science . AAL 4230&col wiz-ref = wbdp(需要 AAAS 登录才能访问)
历时词语嵌入揭示语义变化的统计规律
作者:林子幸·汉密尔顿,朱尔·莱斯科维奇,丹·茹拉夫斯基
https://nlp.stanford.edu/projects/histwords/
男人对于电脑程序员就像女人对于家庭主妇一样?去偏置词嵌入
作者:、张开伟、詹姆斯·邹、文卡特什·萨利格拉玛、亚当·卡莱
https://arxiv.org/pdf/1607.06520.pdf
猪身上的口红:去偏见方法掩盖了单词嵌入中的系统性性别偏见,但并没有消除它们
希拉·戈宁,约夫·戈德堡
https://arxiv.org/abs/1903.03862
理解机器学习意外结果的框架
约翰·古塔格·哈里尼·苏雷什
https://arxiv.org/abs/1901.10002
如果公司的招聘算法有偏差,他们就有麻烦了
戴夫·格什格恩
https://qz . com/1427621/companies-is-on-the-hook-if-they-hiring-algorithms-is-biased/
自然语言处理的数据陈述:减少系统偏差和实现更好的科学
艾米莉·本德,巴特亚·弗里德曼
https://www.aclweb.org/anthology/Q18-1041
我们身边所有的作者
对 GoodReads 作者+数据集的分析研究|第一部分

在过去的几个世纪里,作者们一直在塑造我们的思维模式。创作圣书、诗歌、小说、哲学见解、历史事实、漫画、小说人物和数以千计的其他体裁的人们,对我们现在的身份发挥了重要作用。
我们坚持将资格的每个方面都转换成可描述的数字,这诱使我们去看一看作者和他们的书的世界。在这篇博文的第一部分,我们将大致了解一下来自世界各地的超过 20 万名作者的数据集。
数据采集
我不会深入讨论这一部分的技术细节,但是理解数据收集的方法对于确认分析的准确性是必不可少的。
关于书籍和作者的最好和最大的数据来源之一是 GoodReads 。Goodreads 为我们提供了一个 API ,使得它的大范围数据集可以自由访问;同时,我们可以使用 BS4 来废弃其他部分。在我的 GitHub 页面上可以找到用于数据收集的完整 python 脚本。

标记部分显示了收集的部分数据。
最终数据集类似于下表。为了收集这么多的数据,我们需要大约 800 个小时,花了将近三天的时间在 15 滴水滴上。如你所见,已经收集了 209517 个作者的数据。
数据集中有一些空值是很自然的。例如,我们只知道 88587 位作者的性别,我们不知道其余的,或者只有 7882 位作者提到他们受到了谁的影响。

作者的数据集:列表,包含每列中值的计数和类型。
1.哪些作者的评分和评论数最高?
评分、评论和关注者的数量遵循类似于幂律的分布。例如,看看下面的评论直方图。你可以看到很多作者(超过 100,000 名作者)的书得到的评论不到 100 条。另一方面,在图表的尾部,我们很少有作者的书籍评论超过 100,000 条。

如果我们按照评论和评分的数量来排列作者,我们会得到下面的柱状图。
收视率超过 2400 万的 J.K .罗琳高居榜首。斯蒂芬·金、苏珊·科林斯、斯蒂芬妮·梅耶和 J.R.R .托尔金将紧随其后。我想我们都看过一些根据这些作者的小说改编的电影。

用户可以在 GoodReads 中给书籍打分,从 1 到 5。评级分布遵循正态分布。作者的平均评分是 3.87。

评级遵循正态分布
现在,让我们根据作者的评分来排列他们。
虽然 J.K .罗琳仍然位居榜首,但许多职位面临着变化。例如,乔治·r·r·马丁和卡勒德·胡赛尼获得了更好的位置。

2.是不是写的书多的人就有更多的受众?
GoodReads 中的图书数量等于该作者在不同出版物和不同语言中的图书数量。例如,为 J.K .罗琳提交了 246 本书,而她原本写的书更少。
下面的相关矩阵可以帮助我们得到这个问题的答案。书的数量和吸引更多观众的相关性很低。
写更多的书并不意味着成为成功的作家。

如你所见,这里我们有一个额外的专栏,Shelved _ books。这一栏显示了用户搁置作者书籍的次数。不幸的是,获取所有 209k 作者的数据非常耗时。对 200 名作者的观察显示,搁置的书籍和评论数之间有很高的相关性。
3.几个世纪以来,书籍和读者的数量是如何变化的?
随着时间的推移,作者越来越少。(或者至少 Goodreads 上提交的作者更少了。)而且随着作者数量的增加,评论和评分的数量也在增加。
就评论和评级而言,出生于 1860 年至 1960 年之间的作家获得了最多的关注。年轻作家需要更多的时间来获得认可。

4.哪些作者对他人的影响更大?
近 8000 名作者指明了谁是他们的文学灵感来源。虽然与庞大的作者数据集相比,这是一个小数目,但我们仍然可以通过查看结果获得一些见解。
举个例子,弗朗兹·卡夫卡是最具影响力的前 20 名之一,而我们却看不到他有任何迹象进入评论数最高的前 50 名。

5.作者性别分布如何?
男性和女性作者的总数几乎相同,都在 4 万人左右。(男性略高)非二进制作者也有限。
一般来说,女性作者比男性作者拥有更多的关注者。她们也比男性参与更多。

6.哪些是最受认可的流派?
超过 74000 个作者可以使用这些类型。下面的柱状图显示了不同类型的书籍数量,以作者的性别区分。
近三分之一的作者写小说。言情、当代和成人书籍类型以女性为主,男性更热衷于政治、商业、哲学和科学,而他们写作较少。

如果我们把评论的数量作为受欢迎程度的衡量标准,排名前 30 的流派如下。
小说和言情类书籍排在最上面,读者更少的商业、政治、科学和哲学书籍排在最下面。

7.随着时间的推移,这些书的类型是如何变化的?
在这里,我们可以看看不同世纪的不同流派。在我们的数据集中,20 世纪的作者数量最多。那么,我们来看看本世纪的流派分布。

要比较时间内的不同流派,可以看一下几十年间不同流派的痕迹条。
久而久之,宗教和精神作者变得越来越少,而虚构和科学书籍上升。同时,我们看到更多的历史和传记。

8.哪些国家的作者比较多?
虽然有大约 46000 个作者的出生地是可用的,但数据集非常脏,因为不同的城市和国家有不同的名字。
我们使用一个名为 Geonames 的开源数据库来识别出生地点的国家和地理信息。世界范围内的作者分布如下图所示。如你所见,北美和欧洲的作者非常密集。

细看一下,就作者数量而言,美国位居榜首,英国、加拿大、法国和德国紧随其后。

如果把出生地和作者性别结合起来,就可以观察到每个国家的男性、女性和未知作者的数量。
在大多数国家,男性作家多于女性作家。而在一些国家,如美国、加拿大、澳大利亚、瑞典、新西兰和日本,女性作家多于男性。有趣的是,牙买加也有很多女作家。

结合出生日期和出生地,我们得到一个更有限的数据集。但是如果我们将结果制作成动画,我们会看到时间是如何影响每个国家的作者数量的。

9.不同国家之间的流派分布如何?
不同国家的流派分布取决于许多不同的参数,如社会、经济和文化因素。这些雷达图显示了不同国家的主要流派。
看看日本和沙特阿拉伯的区别。在日本,漫画和漫画非常普遍,而在沙特阿拉伯,小说和宗教书籍占主导地位。

下一步是什么?
有了清理过的作者数据集,我们可以进行更多的分析,并做出其他有见地的可视化。不要犹豫,从 Kaggle 获取数据集,并开始使用它。
在接下来的部分,我们将更深入地了解作者的传记和他们的书籍描述。我们也将看看作者的共同阅读网络。
信用
- 你刚刚读到的;是 内达·索尔塔尼·哈尔瓦伊 和 梅 合作的结果。
- 感谢Vahab Khoshmagham为图表添加视觉元素。
有用的链接
你需要知道的 Python 熊猫的所有核心功能

照片由 Pixabay 上的 Sarah_Loetscher 拍摄
成为一名合格的 Python 数据分析师所需的所有 Pandas 函数。
作为 Python 编程语言中最受欢迎的库之一,Pandas 是数据 I/O、清理、转换和聚合的“必学”库。
在 Stack Overflow 中看到这类关于熊猫的问题是很常见的:
- 如何将我的数据框转换为…
- 如何计算一列的不同值…
- 如何将列类型从…转换为…
- 如何合并两个数据框…
- 等等
在我看来,所有熊猫的新手都应该至少知道基本的熊猫功能,并在开始实际使用它们之前练习它们。不算太多,但是可以帮你解决大部分常规问题。
功能列表
这些功能是什么?好的。在本文中,我用不同的表格将所有这些函数组织成不同的类别。如果你相信你可能已经知道一些(如果你曾经使用过熊猫你一定至少知道一些),下面的表格是TD;DL 让你在通读之前检查你的知识。
表格中的符号:
- pd 熊猫
- df :数据框对象
- s :系列对象(数据框的一列)
数据输入输出
数据预览
数据清理
数据转换
数据聚合
接下来,让我演示这些功能。我将给出它们的示例用法,但是当然,我不能列举这些函数可能被使用的所有场景。所以,强烈建议你自己练习。
数据输入输出

CSV、Excel 和 JSON 文档的读写使用非常相似。请注意,您可以从本地路径或 URL 读取。
# Read from local path
df1 = pd.read_csv('./data.csv')
df2 = pd.read_excel('./data.xlsx', sheet_name='Sheet1')
df3 = pd.read_json('http://example.com/data.json', orient='records')
在read_excel中,如果存在多个工作表,我们可以通过给出sheet_name来指定加载哪个电子表格。
对于read_json,正确使用orient参数很重要。当 JSON 文档是一个数组时,最常用的是records,如果您想使用根键作为索引,则使用index。
to_csv、to_excel、to_json是对应的书写功能。重要的区别在于,我们需要从数据框对象而不是 Pandas 对象调用这些函数。
df1.to_csv('./data.csv')
df2.to_excel('./data.xlsx')
df3.to_json('./data.json')
直接从/向数据库读写要稍微复杂一些。Pandas 支持多个库,比如 SQL Server 的pymssql和 MySQL 的pymysql。然而,我最喜欢的是sqlalchemy,它支持最流行的数据库,甚至包括云数据库,如雪花数据库。
from sqlalchemy import create_enginedb_engine = create_engine(
'snowflake://{user}:{password}@{account}/'.format(
user='...',
password='...',
account='...',
))df = pd.read_sql("SHOW TABLES", db_engine)
df.head()

数据预览

照片由 Christian Wiediger 在 Unsplash 上拍摄
很多时候,我们想要得到我们所拥有的数据集的一个大概情况,或者仅仅想要检查数据是否已经被正确地加载到 Pandas 数据框中。为此,我们需要知道几个函数。
df.head()
df = pd.DataFrame({
'id': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'name': ['Alice', 'Bob', 'Chris', 'David', 'Ella', 'Frank', 'Grace', 'Hellen', 'Iva', 'Jack']
})df.head()

出于演示的目的,我首先创建了一个包含两列的数据框——“id”和“name”。
默认情况下,df.head()函数显示前 5 行。
然而,你可以指定显示多少行,比如df.head(10)显示 10 行。
df.tail()

df.tail()
与df.head()类似,该函数将显示尾部 n 行。
当数据集被排序,并且您想要检查结果时,这将很有帮助。
df.sort_values()

df.sort_values(by='name', ascending=False, inplace=True)df.head()
我们可以按升序或降序排序。请注意,如果您想将排序后的数据框赋回您的变量,需要将inplace设置为True。否则,您的数据帧df将不会改变。
df.columns
请注意,这不是函数,而是数据框的属性。
df.columns
获取属性值将返回以下结果。

此外,您可以为此属性分配一个列表来重命名数据框的所有列。例如:
df.columns = ['no', 'firstname']
df.dtypes
这也是返回列的所有数据类型的数据框的属性。当您想要检查数据类型,尤其是处理datetime列时,这非常有用。
df.dtypes

df.shape
这可能是我使用最多的属性。我们可能经常想要检查数据框的行数和列数。
df.shape

请注意,这个属性是一个元组,其中第一个元素是行数,第二个元素是列数。
df.describe()

df.describe()
当我们处理一些度量时,我们可能想要有一个数据分布的图像。df.describe()给出了这个粗略的统计数据。
当对具有多列的数据框调用此函数时,非数字列将被忽略。
注意,id列的统计数据没有任何意义,但是它演示了函数。
s .值计数()
此函数适用于熊猫系列,而非数据框。它计算序列中每个值的出现次数。
让我们用一些重复的名称创建另一个数据框。然后,统计这个数据框中的名字频率。请注意,我们使用df.name或df['name']来获取数据框的名称列,作为一个可以应用value_counts()功能的序列。
df = pd.DataFrame({'id': [1, 2, 3, 4, 5],
'name': ['Alice', 'Bob', 'Chris', 'Chris', 'Alice']})
df.name.value_counts()

数据清理

我们得到的原始数据集不完美是很常见的。因此,我们需要在使用前清理数据集。以下是相关的熊猫函数。
伊斯纳酵母
当我们想要过滤数据框中的“空”值时,此函数会有所帮助。让我们创建另一个数据框,在名称列中包含一些空值。注意,我们在 Python 中使用None表示空对象。
df = pd.DataFrame({'id': [1, 2, 3, 4, 5],
'name': ['Alice', 'Bob', None, 'Chris', None]})

然后,假设我们想过滤掉所有的空值。
df[~df.name.isna()]
df.name帮助获取数据框的“name”列作为一个序列,然后isna()返回一系列表示名称是否为 null 的布尔值。之后,开头的~符号反转了布尔值,因为我们想要保留没有空值的行。最后,数据帧df将被这个布尔序列过滤,其中具有“假”布尔值的行将被丢弃。
df.dropna()
df = pd.DataFrame({'id': [1, 2, 3, None, 5], 'name': ['Alice', 'Bob', None, 'Chris', None]})df.dropna()

如果我们有多个包含空值的列,并且我们希望过滤掉至少包含一个空值的所有行,该怎么办?我们仍然可以使用上面的方法,但是你需要对每一列重复很多次。
df.fillna()
df = pd.DataFrame({'id': [1, 2, 3, 4, 5],
'name': ['Alice', 'Bob', None, 'Chris', None]})df.fillna('Unknown')

有时,我们可能不想简单地丢弃具有空值的行。相反,我们希望用其他东西填充空值。
在本例中,带有空值的 name 列被替换为“Unknown”字符串,我们仍然有这些行。
df.drop_duplicates()
df = pd.DataFrame({'id': [1, 2, 3, 4, 3],
'name': ['Alice', 'Bob', 'Chris', 'David', 'Chris']})df.drop_duplicates()

有时原始数据集可能有一些重复的行,而我们实际上并不需要它们。
在本例中,我们有两个 id = 3 的“Chris”。所以,函数丢弃了第二个。
df.drop()
df = pd.DataFrame({'id': [1, 2, 3, 4, 3],
'name': ['Alice', 'Bob', 'Chris', 'David', 'Ella'],
'comments': ['', '', 'author', '', '']})df.drop(columns=['comments'])

在本例中,数据帧有 3 列。
假设我们不需要“comments”列,我们可以使用df.drop()函数删除它。
这个函数也可以用来删除行。
df.rename()
df = pd.DataFrame({'id': [1, 2, 3, 4, 5],
'name': ['Alice', 'Bob', 'Chris', 'David', 'Ella']})df.rename(columns={'id': 'no', 'name': 'firstname'})

在本例中,仍然使用列名“id”和“name”创建数据框。然而,df.rename()函数有助于重命名列标题。
请注意,它将一个字典作为参数,其中键是旧的头,值是新的头。
df.reset _ 索引()
df = pd.DataFrame({'name': ['Alice', 'Bob', 'Chris', 'David', 'Ella']})df.reset_index()

在本例中,数据框只有“名称”列。那么,如果我们想创建另一个列作为标识呢?
如果您认为行号中的某一列没有问题,只需使用df.reset_index()函数。
这个函数还有一个典型的用法。假设我们刚刚清理了数据集,丢弃了一些重复的行。但是,索引将不再是连续的。如果你想有一个连续的索引,这个函数也有帮助。
数据转换

由 SwapnIl Dwivedi 在 Unsplash 上拍摄的照片
在数据清理之后,我们可能需要转换数据。
pd.to_datetime()
通常,我们的原始数据集包含字符串格式的所有日期或时间。为了稍后的分析目的,比如排序,我们可能想要将这些字符串转换成datetime对象。
df = pd.DataFrame({'datetime': ['01/04/2020', '02/04/2020', '03/04/2020']})pd.to_datetime(df.datetime, format='%d/%m/%Y')

请注意,这个函数返回一个序列,所以我们可以将它赋回数据框的列。
s.astype()
这个函数帮助我们轻松地转换列的数据类型。在本例中,创建的数据框的“id”字段包含所有字符串类型。然后,s.astype()函数帮助将它们转换成整数。
df = pd.DataFrame({'id': ['1', '2', '3', '4', '5']})df.id.astype(int)

s.apply()
这大概是我用的最多的功能了。虽然 Pandas 允许我们轻松地对一个数据帧的一整列执行一些转换,例如,df.col + 1会将该列的所有值加 1。然而,有时我们可能需要做一些熊猫内置功能不支持的独特事情。在这种情况下,apply()功能会有所帮助。
当我们使用apply()函数时,通常会同时使用lambda函数。在下面的例子中,我们手动使用apply()功能实现了df.number + 1。
df = pd.DataFrame({'number': [1, 2, 3, 4, 5]})df.number.apply(lambda n: n+1)

在某些特殊情况下,lambda 函数可能不够用。例如,我们有一大堆逻辑应用于一个列,而这些逻辑只能放在一个定制的函数中。因此,apply()功能也可以与定制功能一起使用。
下面的例子使用了一个定制的功能来做同样的事情。
def add1(n):
return n+1df.number.apply(add1)
df.apply()
如果我们需要在一个apply()函数中使用多列怎么办?事实上,apply()函数也可以用于数据框对象。
df = pd.DataFrame({'num1': [1, 2, 3, 4, 5],
'num2': [5, 4, 3, 2, 1]})df.apply(lambda row: row['num1'] + row['num2'], axis=1)

在上面的示例中,数据框是用两个数字列创建的。然后,我们使用lambda函数获取包含所有单元格的每一行。之后,我们仍然可以使用['col_name']来访问这些值。因此,row[‘num1’] + row[‘num2’]将返回两列值的总和。
非常重要的是,这里必须指定参数axis=1,因为数据框对象上的apply()函数将默认应用于行索引。
同样,我们也可以使用定制功能。
def sum_cols(row):
return row['num1'] + row['num2']df.apply(sum_cols, axis=1)
df.explode()
我以前处理 JSON 文档的时候用这个函数。由于 JSON 的风格,有时我们有一个带有数组值的键。在这种情况下,我们可以轻松地展平数组。
df = pd.DataFrame([{
'name': 'Chris',
'languages': ['Python', 'Java']
},{
'name': 'Jade',
'languages': ['Java', 'Javascript']
}])

在这个例子中,直接从 JSON 文档加载的语言仍然是数组。然后,我们用df.explode()函数把它拉平。
df.explode('languages')

数据聚合

马丁·桑切斯在 Unsplash 上拍摄的照片
数据聚合在数据分析中起着重要的作用。Pandas 提供了许多执行数据聚合的方法。这里我整理了一些你必须知道的基本功能。
pd.concat()
df1 = pd.DataFrame({'id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Chris']})
df2 = pd.DataFrame({'id': [4, 5],
'name': ['David', 'Ella']})pd.concat([df1, df2])

在本例中,创建了两个数据框。
然后,我们可以使用pd.concat()函数将它们连接在一起。
请注意,我们也可以使用这个函数来垂直连接。对指数感到不舒服?你还记得df.reset_index()功能吗?😃
pd.merge()
这是另一个我在实践中经常用到的。如果您有 SQL 查询的经验,这就像连接两个表一样。
df1 = pd.DataFrame({'id': [1, 2, 3],
'name': ['Olivier', 'Jade', 'Chris']})
df2 = pd.DataFrame({'id': [1, 2, 3],
'language': ['Objective-C', 'Java', 'Python']})pd.merge(df1, df2, on='id', how='inner')

如上面的代码块所示,创建了两个数据框,分别包含“name”列和“language”列。然后,我们可以使用这个函数将它们“连接”在一起。请注意,我们需要指定哪一列用于与on='id'连接,并指定两个数据帧如何连接how='inner'。
df.groupby()和 df.groupby()。agg()
这两个函数一起演示会更好,因为函数df.groupby()本身不能产生有意义的结果。它必须与适用于群组的其他功能一起使用,我相信df.groupby().agg()是最常见的功能。
df = pd.DataFrame({'id': [1, 2, 3, 4, 5],
'name': ['Alice', 'Bob', 'Chris', 'David', 'Ella'],
'language': ['Python', 'Java', 'Python', 'COBOL', 'Java'],
'age': [21, 32, 31, 68, 29]})df.groupby('language').agg({'name': 'count', 'age': 'mean'})

在本例中,我们创建了一个包含“姓名”、“语言”和“年龄”的数据框。
然后,数据框按语言分组,我们计算这些人的姓名数量和平均年龄。嗯,列标题现在没有意义,但是我们可以使用df.rename()函数来修复它们。
pd.pivot_table()
对于上面的例子,我们也可以使用pd.pivot_table()函数来实现它。也就是说,我们需要如下指定组键和测量值(使用上例中的相同数据框):
pd.pivot_table(df,
values=['name', 'age'],
index=['language'],
aggfunc={'name': 'count', 'age': ['min', 'max', 'mean']})

因此,很明显,当我们有多级组键和度量值时,pd.pivot_table()函数更方便。
摘要

照片由 Aaron Burden 在 Unsplash 上拍摄
事实上,Python 的 Pandas 库有更多的功能,使它成为 Python 中如此灵活和强大的数据分析工具。在这篇文章中,我只是整理了一些我认为最有用的基本原则。如果一个人能搞定所有这些问题,肯定可以开始使用熊猫来进行一些简单的数据分析。当然,要成为大师还有很多要学的。
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@qiuyujx/membership)
如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)
你需要知道的所有分布

来源: Vecteezy 。图片免费分享。
二项式、双峰式、泊松、+更多
分布不仅在统计学中很重要,在解释你周围的世界时也很重要。因为一切都是由数据定义的,所以可以根据数据最终是如何分布的来提取各种属性和观察结果。
在本文中,我们将讨论几种类型的分布,包括类比、真实世界的例子和属性。
- 二项式分布。
- 伯努利分布。
- 泊松分布。
- 双峰分布。
- 正态分布。
- 均匀分布。
二项分布
你掷一个标准骰子 10 次。你正好 3 次降落在 1 上的几率有多大?还是正好 7 次?5 次怎么样?
二项式分布接受两个参数:实验次数 n (在这种情况下,10,因为骰子滚动了 10 次),以及成功的概率 p (在这种情况下,1/6,意味着六个结果中的一个)。然后, x 的每个值是在所有实验 n 中,确切地说是 x 实验产生成功结果的机会。
这是由二项分布概率质量函数给出的,它比看起来更直观。

q 定义为 1-p,即实验不正确的概率。
等式的第一个元素是 choose 函数,它选择从总共 n 个对象中选择 x 个对象的不同方式的数量。第二部分求实验成功 x 次的概率,第三部分求实验不成功 n-x 次的概率,实验的余数。
当用我们初始设置的参数绘制二项分布图时——1/6 = 0.1666……在右边脸着陆的机会,重复 10 次——在总共 10 次实验中,有多少可能或不太可能恰好在那张脸上着陆就很清楚了。从分布图来看,答案似乎是 1 倍。

和德斯莫斯一起创造的。
二项式分布出现在许多现实环境中。如果一种情况符合以下所有四个标准,那么你看到的很可能是二项分布:
- 只有两种可能且相互排斥的结果——例如,是或否、客户与否等。(二项式中的 bi 。)
- 有一个预定义的、有限的和恒定数量的重复实验或试验。
- 所有的试验/实验都是相同的,因为它们都是以与其他试验相同的方式进行的,但又是独立的,因为一个试验的结果不会影响其他试验。
- 每次试验的成功概率是一样的。
例如,考虑一家公司,该公司希望预测客户在看到相同的广告后购买产品的可能性。在确定了 p 和公司希望投放的最大广告量( n 之后,公司可以使用二项式分布的质量概率函数来确定在他们的营销活动中有多少广告值得投放。
二项分布
伯努利分布是只有一次试验的二项分布。它发生在只有两种结果的实验中,成功的概率为 p ,失败的概率为 q = 1 - p 。

资料来源:统计方法。图片免费分享。
伯努利分布实际上不是一个分布,因为它是二项分布的特例,但它是一个很好理解的行话。
泊松分布
泊松分布模拟给定数量的事件在固定的时间或空间间隔内发生的概率,前提是这些事件以恒定的平均速率发生,与自上次事件以来的时间无关。每个分布的可控因子是λ,也就是平均速率。

资料来源:统计方法。图片免费分享。
例如,如果你记录每天收到的电子邮件数量,并注意到你平均每天收到 14 封。如果收到一封邮件不影响未来邮件的到达时间,那么你一天收到的邮件数量很可能服从泊松分布。在其他场景中,还有许多这种分布的其他示例。例如,呼叫中心每天接到的电话数量或每秒钟从放射源发出的衰变事件数量都遵循泊松分布。
分布遵循以下概率质量函数:


a 用λ代替。用德斯莫斯画的。
双峰分布
双峰分布有两个峰(因此得名, bi modal)。它们通常是两个唯一单峰(只有一个峰值,例如正态或泊松分布)分布的混合,依赖于两个分布变量 X 和 Y ,混合系数为α。
这意味着,当双峰分布出现在看似单峰的场景中时,可能有外力在起作用。事实上,2010 年,理查德·奎因教授在中佛罗里达大学发现他的学生在期中考试中作弊,作弊的依据是分数的分布。考试成绩几乎总是正态分布的,几乎任何大学的期中考试都是如此,ACT 或 s at 也是如此。然而,2010 年秋季中期选举有两个高峰。

你可以在 YouTube 这里找到完整的作弊指控讲座。图片免费分享。
因为不自然的双峰分布几乎总是两个独特的单峰分布的部分组合,所以教授意识到这两个分布代表了两组学生:没有作弊的学生和作弊的学生。表现更差的单峰分布与 2010 年夏季的中期分布有着明显的相似之处。教授发现这一点后,做了一番调查,发现题库已经泄露给了一群学生。
虽然双峰(或多峰)分布可以揭示系统偏差或问题,但它们也经常自然发生。这些自然双峰分布变量包括:
- 间歇泉喷发的间隔时间
- 星系的颜色
- 工蚁的大小
- 霍奇金淋巴瘤的发病年龄
- 交通分析
- 需水量
正态分布
最标准的(因此也是“正态”)分布是正态分布,根据其外观也称为钟形曲线。
它最标准和众所周知的属性包括数据的百分位数和标准偏差之间的关系。
- 68.2%的数据在数据的一个标准偏差内。
- 95.4%的数据在数据的两个标准偏差之内。
- 99.6%的数据在数据的三个标准偏差之内。

资料来源:ExcelUser。图片免费分享。
方程式 exp(- x )给出了钟形曲线。虽然这不是正式的概率质量函数(这要复杂得多),但正态分布可以使用该方程来创建。思考这个问题的一个好方法是,exp( x )创建一条向左逐渐减小、向右逐渐增大的曲线,而 exp( -x )创建一条向右逐渐减小、向左逐渐增大的曲线。通过应用平方函数,这两个函数被“组合”,两个函数的属性逐渐减少。

有趣的是,概率质量函数成功地包含了π,而我们也可以完全不用π,只用 Desmos 中的 e 来写。
在统计学和机器学习中,正态分布起着重要的作用,例如在机器学习模型的假设中。例如,线性回归模型假设残差(线拟合的数据点误差)呈正态分布。毫无疑问,这是研究最多、最广为人知的分布,各种定理、性质以及在其他领域的应用都得到了很好的证明和探索。
在自然界中,植物和动物的物理特征(如身高或体重)形成正态分布。股票价格的表现倾向于符合正态分布,常见的预测和计量误差倾向于正态分布。据观察,自然流行病遵循钟形曲线的路径。其他衡量表现的指标,如智商、音乐能力和标准化测试都是正态分布的。这和中心极限定理有关,中心极限定理本质上是说各种随机信号自然组合在一起形成正态分布。
均匀分布
均匀分布是指对于插入概率质量函数的每个 x 值来说, y 值大致相同。

近似均匀分布。来源:ResearchGate。图片免费分享。
这种分布在等概率中是最标准的,比如掷骰子。均匀分布虽然看起来很无聊,但它有许多有用的统计特性。例如,考虑德国的坦克问题。在二战中,盟军需要估计德国人正在生产多少辆坦克,并意识到他们可以使用缴获的坦克上的连续序列号来估计坦克的总数。
在从 1 到 n 的均匀分布中,捕获的序列号可以被假设为彼此距离相等。利用这一特性,盟军能够创建一个公式来估计生产中的坦克数量。通常,如果分布未知,根据上下文,通常可以假设它是均匀分布。统计推断的许多原理都是基于这个前提。
感谢阅读!
如果你喜欢,你可能会喜欢我的其他一些关于统计的文章:
频繁主义者-贝叶斯之争
medium.com](https://medium.com/dataseries/the-most-fundamental-and-controversial-debate-in-statistics-and-data-science-e8dd1bad737a) [## 你的终极数据科学统计和数学小抄
机器学习指标、统计指标等
medium.com](https://medium.com/analytics-vidhya/your-ultimate-data-science-statistics-mathematics-cheat-sheet-d688a48ad3db)
所有他们认为你不应该知道的事情
入门
无限和…线性代数?!

信用:Pixabay
特征值(向量、值、分解)是线性代数的基础概念之一。这种东西往往会让 STEM 学生在挫折中“一头撞墙”。对我来说,特征向量(和行列式)是这个数学分支中最具挑战性的想法。更重要的是,它是统计学、物理学、工程学、计算机科学等领域的基础。在这篇文章中,我将把 Eigen-stuff 描述得非常简单,希望它能在你处理基于它的更复杂的话题时提升你的自信。
万圣节就要到了,因此,我将使用一个牵强的例子来说明特征分解:比方说,你正在某条街上“不给糖就捣蛋”——所有奇数编号的房子都在左边,偶数编号的房子在右边——所以当你沿着糖果巷前进时,你从左到右反弹回来。街道左侧的邻居只分发 KitKats,而右侧的邻居只分发 M&Ms。一个“回合”将包括敲街道左侧的一扇门,然后敲街道右侧的一扇门。
不管出于什么原因,所有的邻居都遵守一些规则,即左边的邻居会根据你目前拥有的糖果给你 M & Ms。即:
MM = 1*MM + 2*KK #left
KK = 3*MM + 7*KK #right
这些规则由下面矩阵中的“线性变换”表示:
[[1,3],
[2,7]]
所以问题变成了——当你走过整条街(或者任意长的一段距离) 你的糖果包会是什么样子? 和 你的糖果包的首发成分有多重要? 假设你从包里的每种糖果开始:
[1,1]
#KK, MM
一轮(街道的左右两侧)后,你更新的袋子有 3 个 KitKats 和 5 个 M & Ms 换句话说,你增加了 2 个 KK 和 9 毫米。(记住要做出区分:线性变换矩阵缩放你的糖果数量,它不只是简单地增加它们-尽管我们可以计算加法量。)
[1*1 + 1*2, 1*3 + 1*7] = [3,10]
那么两轮过后你的包包是什么样子的呢?
[3*1 + 10*2, 3*3 + 7*10] = [23, 79]
让我们看看我们的包在 10 个回合后是什么样子,使用 python:
import numpy as np
import matplotlib.pyplot as pltj = np.array([[1,3],[2,7]])
curr = np.array([1,1])
results = [curr]for i in range(10):
curr = np.matmul(j,curr)
results.append(curr)x = [i[0] for i in results]
y = [i[1] for i in results]
plt.plot(x,y)
plt.scatter(x,y)

一个非常明显的趋势出现了:首先,迭代 1-8 彼此映射得非常接近,靠近原点,而迭代 9 和 10 伸展得更远,这表明缩放效应的幅度随着每次迭代而复合。第二个趋势是这些迭代遵循一条线!回想一下高中代数——直线由两个参数描述,斜率和 y 截距。如果直线通过原点(0,0),则直线完全由坡度单独定义。如果你还记得“上升超过下降”,这条线描述了 y 与 x 或者 M&Ms 与 KitKats 的比率。这条线显示,几乎就在你开始不给糖就捣蛋之后,你的书包也会被定义成同样的比例!这真是太棒了。
在我们兴奋之前,让我们试试不同的起始包组合:
j = np.array([[1,3],[2,7]])
curr = np.array([3,2])
results = [curr]for i in range(10):
curr = np.matmul(j,curr)
results.append(curr)x = [i[0] for i in results]
y = [i[1] for i in results]
plt.plot(x,y,color='r')
plt.scatter(x,y,color='r')

现在这是令人兴奋的!我们已经看到了两种不同的开始糟糕组合,然而它们汇聚在相同的 KitKat 对 M & M 比率上。
然而,这并不是普遍适用的。请注意,如果您从任一糖果的 0 开始,由于线性变换的乘法性质,所述糖果将永远不会增加,因此您的旅行将糖果巷不会收敛于此比率。(但是,如果在一个或两个糖果中以负数开始,收敛仍然会发生!然而,这在我们的问题中毫无意义。)
现在,让我们在特征向量上绘制这些数据点:
eigVec1 = np.linalg.eig(j)[1][:,0]
eigVec2 = np.linalg.eig(j)[1][:,1]e1_x = [eigVec1[0]*-i for i in range(0,1_000_000,100)]
e1_y= [eigVec1[1]*-i for i in range(0,1_000_000,100)]
e2_x = [eigVec2[0]*-i for i in range(0,1_000_000,100)]
e2_y= [eigVec2[1]*-i for i in range(0,1_000_000,100)]plt.scatter(x[:7],y[:7],color='r') #points
plt.plot(e2_x,e2_y) # dominant eigenvector

想象一下,在第一次迭代之后,包的 KK 与 MM 的比率遵循特征向量中的,完全正确!但这意味着什么呢?
我们可以像考虑微积分极限一样考虑线性代数的特征向量!它们描述了系统的最终行为。注意,就像不是所有的代数函数都有极限(有时极限不存在)——不是所有的矩阵都有实特征向量:比如旋转矩阵就有虚特征向量。为什么?因为,你可以旋转一个向量无限次,但它永远不会以任何比例收敛!鉴于这种线性变换收敛于 KitKats 与 Peanut M 的特定比率,本征分解在数学中有许多应用;一个这样的应用是解微分方程系统。为什么?因为我们说的正是比率!
注意:沿特征向量有无穷多个点,由于共享相同的斜率,它们只是相同比值的倍数(虽然没有明确限定为整数倍)。记住这条线和点的概念。
到目前为止,我们已经忽略了非常重要的考虑:一个系统可以有多个特征向量,然而,我们的分析表明,我们只收敛于一个特征向量。解释在于特征值:一个特征向量拉伸了一个向量(或者旋转——同样是虚数),但是特征值定义了这些效应的相对大小。
np.linalg.eig(j) #eigenvalue 1, eigenvalue 2
array([0.12701665, 7.87298335]) #eigenvector 1, #eigenvector 2
array([[-0.96017331, -0.40004303],
[ 0.2794051 , -0.91649636]]))
请注意,第一个特征值约为 0.13,而第二个特征值约为 7.88。当你用 7.88 除以 0.13 时,得到的数大约是 60。这意味着,每当线性变换矩阵被(递归地)应用于一个向量时,第二个特征向量的效果是另一个的 60 倍。经过几次迭代后,第一个特征向量的影响可以忽略不计,并被第二个特征向量的主要影响所抵消。这就引出了特征向量的第二个(软)定义:线性变换的主要效应。
从我们的不给糖就捣蛋的例子中,你可以看到特征向量可以描述随机变量的最终行为。我们会很快接近 KK 和 MM 的特定比例,一旦达到这个比例,敲更多的门只会巩固这个比例,真的无法逃避!如果这听起来像马尔可夫链,那么恭喜你,你很好地掌握了上下文线索。
考虑下面的网页网络;下面矩阵的列描述了你来自的网页,行代表你来到的网页。所以chain[0,1]代表从页面 1 过渡到页面 0 的概率。这个矩阵从何而来?它基于网页上的链接;例如,第 0 列表示,在第 0 页的所有链接中,25%指向自身,20%指向第 1 页,25%指向第 2 页,最后 30%指向第 3 页。
chain = np.array([[0.25, 0.20, 0.25, 0.30],
[0.20, 0.30, 0.25, 0.30],
[0.25, 0.20, 0.40, 0.10],
[0.30, 0.30, 0.10, 0.30]])np.linalg.eig(chain)
我们想知道,哪些页面或多或少相关。做到这一点的一种方法是使用随机行走:我们让一个机器人从上述任意页面开始执行任务,随机选择,然后根据当前网页对应的列定义的转移概率随机移动。如果允许机器人无限期行走(或任意长的一段时间),并且我们将它对每个页面的访问次数归一化,我们会发现平稳分布,这是机器人在每个页面上被发现的概率,如果它的无限行走在某个时间被随机停止。
这种平稳分布非常重要。这是最终行为比率的另一个例子!这意味着,它可以通过特征分解很快找到。但它变得更好了——马尔可夫链的转移矩阵的一个方便的属性是主要特征值等于 1。这意味着它将输入向量拉向最终行为比率,而不缩放它。换句话说,它将输入向量拉向空间中的特定点,而不仅仅是比率的任意倍数(就像前面的例子一样)。)
请注意,该属性非常有用,计算机通常就是这样计算任何本征向量的(然而,在每一步都需要进行一些缩放/调整,以迫使系统表现得好像本征值等于 1 一样。)有关代码和解释,请参见幂迭代法。
# eigenvalues
array([ 1\. , -0.0961781, 0.0773547, 0.2688234]),# eigenvectors
array([[ 0.49854055, 0.55341887, -0.62120306, 0.08851168],
[ 0.52623725, 0.41236876, 0.75039074, 0.11472596],
[ 0.46746621, -0.31362083, 0.0814811 , -0.79384381],
[ 0.50597137, -0.6521668 , -0.21066878, 0.59060617]])
将注意力集中在特征值数组的第一个元素和特征向量矩阵的第一列。这是平稳分布。我们看到页面 1 的访问频率比页面 0、2 和 3 稍高。注意:在实践中,使用了 PageRank 算法,它解决了各种棘手的问题——比如一个网页只链接到它自己(一种吸收状态),或者成对的网页只链接到彼此。这些问题往往会从网络中“窃取”比他们应得的更多的可信度,从而导致错误的排名。但这是完全不同的问题。
为什么马尔可夫链如此重要?它是许多统计技术的理论基础——贝叶斯统计中的 MCMC 抽样、随机过程的蒙特卡罗方法(密切相关)以及许多其他应用。总体思路是,如果你有一些随机过程,比如糖果街上的不给糖就捣蛋,你可以估计这个过程的最终行为,一些事件发生的可能性,或者一些结果的相对频率。这一切都始于 Eigens-stuff!
注意:毫无疑问,你知道我从未使用过,A*x = lambda*x,,它用简单的英语说:“给定的向量 x 是矩阵 A 的特征向量,当(且仅当)当被 A 变换时,返回一个缩放的向量——按特征值缩放。”你可以从我上面展示的一切中证实这是真的。事实上,既然我们已经从自顶向下的方法探索了一些核心思想,那么这条规则就更加合理了。对我来说,自下而上的学习在数学教育中太常见了。
如果你喜欢这篇文章,请关注我的类似内容!欢呼:)
增强深度学习代码所需的所有数字

米克·豪普特在 Unsplash 上的照片
NumPy 或 Numerical Python 是一个开源的 Python 库,使复杂的数值运算变得容易。使用机器学习和深度学习应用程序涉及大型数据集的复杂数值运算。与纯 Python 实现相比,NumPy 使得实现这些操作相对简单和有效。
在其核心,NumPy 实现了它的(n 维数组)数据结构,这类似于一个常规的 Python 列表。大多数编程语言只有数组的概念。Python 实现了列表,列表作为数组工作,但还是有区别的。
常规 python 列表和 NumPy 之间的一个关键区别是 python 列表可以包含各种数据类型。相反,NumPy 数组只能包含相同数据类型的对象。换句话说,数据结构是同质的。虽然这看起来像是一个缺点,但它允许 NumPy 操作更快,因为它们可以在进行计算时避免转换和约束。
为什么要关心 NumPy,为什么专门针对深度学习?
我将在本文中讨论几个具体的用例,但是与其他 python 数据结构相比,NumPy 最重要的特性之一是速度。NumPy 比使用常规 Python 列表快几个数量级。性能提升是可能的,因为 NumPy 函数是用 C 实现的,这除了使执行更快之外,还使 NumPy 能够分解大型作业并并行执行多个作业。深度学习涉及处理大型数据集,当处理这些大型数据集时,NumPy 数组可能是一种有效的技术。
创建 NumPy 数组
创建 NumPy 数组有几种不同的方法,一种直接的方法是使用array()函数创建它们。
#import NumPy
import numpy as np#create a NumPy array
a = np.array([1,2,3])#check the shape of the array
a.shape#get the dimensions
a.dim
此外,你可以直接从标准的 Python 列表 中创建。Numpy 阵列是智能的。如果您将一个 Python 列表传递给array()函数,它将自动执行操作并返回一个 Numpy 数组。您不必先显式转换为 NumPy 数组。
#python List
my_list = [1,2,3,4,5]#creating a NumPy array from a list
np.array(my_list)
您还可以使用 pandas 函数将 Pandas 数据帧转换为 NumPy 数组。to_numpy()
#import Pandas
import pandas as pd#create a DataFrame
df = pd.DataFrame({"A":[1, 2],"B":[3, 4]})#convert DataFrame to NumPy array
df.to_numpy()
值得注意的是,由于 NumPy 数组只能包含相同数据类型的元素。默认情况下,当您转换数据帧时,返回数组的dtype将是数据帧中所有类型的公共 NumPy dtype。
NumPy 热爱数学
NumPy 数组是专门用来做数学的。该软件包包括几个辅助数学函数,允许你做这些计算,而不需要自己快速编写。
常见的例子包括用于获得平方根的sqrt()函数、用于计算对数的log()函数和用于计算双曲正切的tanh()函数,后者通常用作深度神经网络中的激活函数。
a = np.array([1,2,3])#get the square root
np.sqrt(a)#get log
np.log(a)#find the tanh
np.tanh(a)
线性代数
线性代数广泛用于机器学习和深度学习应用。在处理深度学习时,你会发现自己正在处理高维数组,这些数组可以很容易地转化为线性方程,以分析给定空间中特征的相互作用。
NumPy 有几个内置的线性代数算法,作为linalg子模块中的方法。
一个常用的线性代数函数是norm()一个用于计算向量长度的函数,也被称为向量范数或向量幅度。向量范数作为一种归一化技术被应用于解决机器学习和深度学习应用中的过度填充问题。NumPy 的linalg子模块有norm()函数来计算向量范数
a = np.array([1,2,3])#getting a norm of the vector
np.linalg.norm(a)
使用线性代数时,遇到数学错误并不罕见。一些数学运算是不允许的。处理这些错误的一个好方法是使用linalg.LinAlgError异常处理,这是一个从 Python 的异常类派生的通用异常类。
例如,如果我们试图对一个奇异矩阵求逆,这个操作是不允许的,并且会抛出一个错误。
x=np.ones((2,2)) np.linalg.inv(x) #this will throw an error#exception handling using LinAlgError
try:
np.linalg.inv(x)
except np.linalg.LinAlgError:
print("Linear Algebra Error")
如果将几个矩阵堆叠在同一个数组上,这些线性代数函数可以计算出它们的结果。
广播
NumPy 进行算术计算的基本特征之一是通过广播。广播允许不同形状和大小的 NumPy 阵列之间的操作。
广播通过比较拖尾维度来工作,广播有效有两个主要规则。
- 尺寸相等,或
- 其中一个维度是 1
当您在 NumPy 中执行元素操作时,比如向 np.array 添加一个标量,这实际上就是广播。
x = np.ones((2,2))
y = np.ones((3,2,1))
a = np.ones((2,3,3))x+y #Broadcasting will work; trailing dimensions match
x+a #Broadcasting will fail; trailing dimensions do not match
数字和矩阵
NumPy 的真正潜力来自于处理矩阵。Numpy 支持各种易于使用的方法来进行标准矩阵运算,如点积、转置、获取对角线等。
矩阵乘法,具体来说,计算度量的 点积 ,是深度学习中的常见任务,尤其是在处理卷积神经网络时。NumPy 函数dot()计算两个指标的点积。在 NumPy 的更高版本中,您还可以使用@操作符来计算点积。
x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])#dot product with dot()
x.dot(y)#dot product with @
x@y
深度学习中接下来两个常用的矩阵运算是 求逆和 转置。
我们先来看逆。什么是逆?一个数乘以它的倒数等于 1。重要的是要记住,不是所有的矩阵都有逆矩阵,在这种情况下,你会得到一个错误。你可以用linalg.inv()函数得到一个矩阵的逆矩阵。
x = np.array([[1, 2], [3, 4]])#getting the inverse
np.linalg.inv(x)
矩阵的转置是一种在矩阵对角线上翻转矩阵的操作。也就是说,它切换矩阵的行和列索引。在 NumPy 中,你可以用T得到一个矩阵的转置
x = np.array([[1, 2], [3, 4]])#getting the transpose
x.T
在深度学习中, 特征值和特征向量 在实现主成分分析(PCA)等降维方法时很有用
你可以使用linalg.eignvals()函数计算一个向量或矩阵的特征值。
x = np.array([[1, 2], [3, 4]])#getting the eigenvectors
np.linalg.eigvals(x)
使用矩阵时,一定要记住不要使用 NumPy 类中的 matrix 函数,而要使用常规数组。
改变形状
使用深度学习时,您会经常遇到需要改变数组或矩阵形状的情况。您可以使用reshape()功能重塑NumPy 数组。该函数返回具有新形状的新 NumPy 数组。
x = np.array([[1, 2], [3, 4]])#Reshape 2X2 to 4X1
x.reshape(4,1)
如果需要改变原始 NumPy 数组的形状,可以使用resize()函数。它的工作方式与reshape()函数相似,但它改变了原始对象,而不是创建一个新对象。
x = np.array([[1, 2], [3, 4]]#Resize the original array 2X2 to 4X1
x.resize(4,1)
扁平化 是另一种标准的深度学习操作,用于将数据或输入传递到你的神经网络的不同层。flatten() NumPy 功能将展平一个ndarray。
x = np.array([[1, 2], [3, 4]]#flatten the array
x.flatten()
除了使用flatten()之外,你还可以使用ravel()方法来做同样的事情。flatten()和ravel()的区别在于,ravel()可以直接用于常规链表,并将返回一个 NumPy 数组。
x_list = [[1, 2],[3, 4]]#flatten a list
np.ravel(x_list)
整形的一种形式是 给一个数组增加一个新的维度 。例如,您可以通过使用关键字添加一个新维度newaxis来取消展平
y = np.array([1,2,3,4,5])#add a new dimension
y[:,np.newaxis]
重塑 NumPy 数组的另一种方法是使用函数拆分它。该函数采用,并根据指定的索引或节返回子数组。
x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])#split array into 3 sections
np.split(x,3)
使用 NumPy 生成数据
NumPy 为数值运算提供了强大的工具包;但是,NumPy 也可以生成数据。让我们看看一些常见的场景。
一个 单位矩阵 是一个任意阶的正方形矩阵,沿主对角线为 1,所有其他元素为 0。NumPy 函数创建指定阶数的单位矩阵。
#generate a identity matrix 5
np.identity(5)
在深度学习中,你会遇到需要一个0&1的矩阵的情况。NumPy 有方便的函数zeros()和ones()可以用来生成 0 或 1 的矩阵。
#generate a 2X3 matrix of 0s
np.zeros((2,3))#generate a 2X3 matrix of 1s
np.ones((2,3))
使用 NumPy random.rand()函数,您可以创建一个由随机数元素组成的指定顺序的数组。
#generate a 2X3 matrix of random numbers
np.random.rand(2,3)#generate a 2X3 matrix of random integers
np.random.randint(2,3)
注意,如果您想要随机整数,您可以使用random.randint()函数获得一个包含随机整数的 NumPy 数组。
上面讨论的数据生成方法可以与它们的_like对应物一起使用,例如zeros_like、ones_like来生成数组,这些数组采用作为参数传递给函数的数组的形状。
x = np.array([[1, 2],[3, 4]])#generate a matrix of 1s based on dimensions of x
np.ones_like(x)
换句话说,当使用函数的_like形式时,我们不指定形状,而是传递一个现有的 NumPy 数组。产生的 NumPy 数组采用传递的数组的形状。
总结想法
在这篇文章中,我涵盖了你需要开始的所有必要的数字。NumPy 比这里介绍的内容更多,但是我们在这里介绍的内容应该足以让您在深度学习项目中开始使用 NumPy。最好的学习方法是建立。当你开始从事深度学习项目时,你会遇到需要你使用额外技术和学习更多知识的情况。快乐大厦!
所有的熊猫合并()你应该知道合并数据集
你应该知道的一些最有用的熊猫把戏

Galymzhan Abdugalimov 在 Unsplash 上拍摄的照片
Pandas 提供了各种内置函数来轻松组合数据集。其中,merge()是一个非常类似于 SQL 这样的关系数据库的高性能内存操作。当您想进行类似数据库的连接操作时,可以随时使用merge()。
在本文中,我们将浏览一些使用熊猫merge()函数合并数据集的例子。我们将介绍以下常见用法,应该可以帮助您开始使用数据组合。
- 没有任何键列的最简单的调用
- 使用
on指定关键列 - 使用
left_on和right_on合并 - 各种形式的连接:
inner、left、right和outer - 使用
validate避免无效记录
源代码请查看笔记本。
1.没有任何键列
当您使用merge()时,最简单的调用必须有两个参数:left数据帧和right数据帧。例如,要组合df_customer和df_info:
df_customer = pd.DataFrame({
'id': [1, 2, 3, 4],
'name': ['Tom', 'Jenny', 'James', 'Dan'],
})df_info = pd.DataFrame({
'id': [2, 3, 4, 5],
'age': [31, 20, 40, 70],
'sex': ['F', 'M', 'M', 'F']
})pd.merge(**df_customer**, **df_info**)

最简单的呼叫(图片由作者提供)
默认情况下,该函数将组合公共列(在我们的示例中是列 id )上的数据,并且只生成在左右数据帧中都匹配的结果。
如果您喜欢从左侧数据帧调用 merge,下面是一个等效的语句。
**df_customer**.merge(df_info)
2.使用上的参数指定键列
您可以指定用于合并的公共列。为此,向函数merge()传递一个额外的参数on作为公共列的名称,在我们的示例中为'id':
pd.merge(df_customer, df_info, **on='id'**)

pd.merge(df_customer,df_info, on='id' )(图片由作者提供)
如果你使用on,你必须确保你指定的列必须出现在左右数据帧中。
要合并多个公共列上的数据,您可以将一个列表传递给on:
pd.merge(df_customer, df_order, **on=['id', 'name']**)
3.使用left_on和right_on合并
您要合并数据框的列可能会有不同的名称。对于这种合并,您必须指定left_on作为左侧数据帧名称,指定right_on作为右侧数据帧名称,例如:
pd.merge(
df_customer,
df_info_2,
**left_on='id',
right_on='customer_id'** )

合并左 _ 开和右 _ 开(图片由作者提供)
结果将同时包含 id 和 customer_id 列。
4.各种类型的连接:inner、left、right和outer
它们是 Pandas merge()函数可用的 4 种连接类型。这些连接背后的逻辑与您在 SQL 中连接表时的逻辑非常相似。您可以通过使用以下值指定how参数来执行一种类型的连接:
inner:Pandasmerge()函数中的默认连接类型,它产生在两个数据帧中都有匹配值的记录left:从左侧数据帧产生所有记录,从右侧数据帧产生匹配记录right:从右侧数据帧产生所有记录,从左侧数据帧产生匹配记录outer:当左侧或右侧数据帧中存在匹配时,生成所有记录

来源https://en . Wikipedia . org/wiki/Join _(SQL)
下面是我们测试数据集的维恩图
df_customer = pd.DataFrame({
'id': [1,2,3,4],
'name': ['Tom', 'Jenny', 'James', 'Dan'],
})df_info = pd.DataFrame({
'id': [2,3,4,5],
'age': [31,20,40,70],
'sex': ['F', 'M', 'M', 'F']
})pd.merge(df_customer, df_info, **on='id'**, **how=?**)

维恩图(图片由作者提供)
4.1 内部连接
默认情况下,Pandas merge()执行内部连接,它只产生在两个数据帧中匹配的记录集。
pd.merge(df_customer, df_info, on='id')

Pandas merge with inner join (图片作者提供)
下面是等效的 SQL 查询:
SELECT * from customer
**INNER JOIN** info
ON customer.id = info.id
要显式指定内部连接,可以设置参数how='inner'
pd.merge(df_customer, df_info, **how='inner'**, on='id')
4.2 左连接
左连接从左侧数据帧产生所有记录,从右侧数据帧产生匹配的记录。如果没有匹配,左侧会包含NaN。您可以将参数how='left'设置为左连接:
pd.merge(df_customer, df_info, **how='left'**, on='id')

带左连接的 Panda merge()
下面是等效的 SQL 查询:
SELECT * from customer
**LEFT OUTER JOIN** info
ON customer.id = info.id
4.3 右连接
右连接从右数据帧产生所有记录,从左数据帧产生匹配的记录。如果没有匹配,右边将包含NaN。您可以设置参数how='right'来执行右连接:
pd.merge(df_customer, df_info, **how='right'**, on='id')

熊猫合并()带右连接(图片由作者提供)
下面是等效的 SQL 查询:
SELECT * from customer
**RIGHT OUTER JOIN** info
ON customer.id = info.id
4.4 外部连接
当左数据帧或右数据帧中有匹配时,外部连接产生所有记录。NaN将因双方无比赛而被填满。您可以设置参数how='outer'进行外部连接:
pd.merge(df_customer, df_info, **how='outer'**, on='id')

熊猫合并()与外部连接(图片由作者提供)
下面是等效的 SQL 查询:
SELECT * from customer
**FULL OUTER JOIN** info
ON customer.id = info.id
5.使用validate避免无效记录
如果合并键不是唯一的,那么merge()的结果可能会增加行数。例如
df_customer = pd.DataFrame({
'id': [1,2,3,4],
'name': ['Tom', 'Jenny', 'James', 'Dan'],
})df_order_2 = pd.DataFrame({
'id': [2, 2, 4, 4],
'product': ['A', 'B' ,'A', 'C'],
'quantity': [31, 21, 20,40],
'date': pd.date_range('2019-02-24', periods=4, freq='D')
})
df_customer和df_order_2都有 4 条记录。但是,当运行以下 merge 语句时,您将得到包含 6 条记录的结果:
pd.merge(df_customer, df_order_2, **how='left'**, **on='id'**)

(图片由作者提供)
原因如下:
how='left'将产生来自df_customer的所有记录,以及来自df_order_2的匹配记录。- 另外,
df_order_2中的id不是唯一的,所有匹配的记录将被合并返回。
这是一个 一对多 合并的例子。在我们的示例中,这是一个有效的场景,其中一个客户可以有多个订单。但是,一对多在其他一些情况下可能无效,例如df_info中有两条 id 值为2的记录
df_customer = pd.DataFrame({
'id': [1, **2**, 3, 4],
'name': ['Tom', **'Jenny'**, 'James', 'Dan'],
})df_info = pd.DataFrame({
'id': [**2**, **2**, 3, 4, 5],
'age': [**31**, **21**, 20, 40, 70],
'sex': [**'F'**, **'F'**, 'M', 'M', 'F']
})
合并结果将以同一个客户的两个不同记录结束珍妮:
pd.merge(df_customer, df_info, **how='left'**, **on='id'**)

(图片由作者提供)
这当然是错误的,因为同一个客户不可能有不同的信息。为了避免这个问题,我们可以将参数validate设置为'1:1',这样它可以检查合并键在左右数据帧中是否是唯一的。如果验证失败,将引发 MergeError ,例如:
pd.merge(df_customer, df_info, **how='left'**, **on='id', validate='1:1'**)

合并错误
参数validate采用以下值之一,因此您可以使用它来验证不同的合并输出。
one_to_one或1:1:检查合并键在左右数据集中是否唯一。one_to_many或1:m:检查合并键在左侧数据集中是否唯一。many_to_one或m:1:检查右数据集中合并键是否唯一。many_to_many或m:m:允许,但不检查。
结论
Pandas merge()函数是一个简单、强大、高性能的内存操作,非常类似于 SQL 这样的关系数据库。
我希望这篇文章能帮助你节省组合数据集的时间。我建议你查看一下关于merge() API 的文档,并了解你可以做的其他事情。
感谢阅读。请查看笔记本获取源代码,如果您对机器学习的实用方面感兴趣,请继续关注。
你可能会对我的其他一些熊猫文章感兴趣:
- 熊猫重采样()你应该知道的处理时间序列数据的技巧
- 如何对熊猫数据帧进行自定义排序
- 何时使用 Pandas transform()函数
- 你应该知道的熊猫串联()招数
- Pandas 中应用()和转换()的区别
- 使用熊猫方法链接提高代码可读性
- 在 Pandas 数据帧中处理日期时间
- 熊猫阅读 _csv()你应该知道的招数
- 你应该知道的用熊猫 read_csv() 解析日期列的 4 个技巧
更多教程可以在我的 Github 上找到
熊猫 read_csv()加快数据分析速度你应该知道的小技巧
一些最有帮助的熊猫技巧来加速你的数据分析

来自 https://www.flaticon.com/search?word=csv file的搜索结果
导入数据是任何数据科学项目的第一步。通常,您会处理 CSV 文件中的数据,并在一开始就遇到问题。在本文中,您将看到如何使用 Pandas read_csv()函数来处理以下常见问题。
- 处理不同的字符编码
- 处理标题
- 处理列
- 解析日期列
- 设置列的数据类型
- 查找和定位无效值
- 向现有 CSV 文件追加数据
- 用
chunksize加载一个巨大的 CSV 文件
请查看我的 Github repo 获取源代码。
1.处理不同的字符编码
字符编码是从原始二进制字节串映射到组成人类可读文本的字符的特定规则集[1]。Python 内置了对标准编码列表的支持。
字符编码不匹配现在不太常见,因为 UTF-8 是包括 Python 在内的大多数编程语言中的标准文本编码。然而,如果你试图读取一个不同于原始编码的文件,这肯定还是一个问题。当这种情况发生时,您很可能会以类似下面的内容或 DecodeError 结束:

来源于 Kaggle 字符编码
熊猫read_csv()函数有一个名为encoding的参数,允许您指定读取文件时使用的编码。
让我们看看下面的一个例子:
首先,我们用一些汉字创建一个数据框架,并用encoding='gb2312'保存。
df = pd.DataFrame({'name': '一 二 三 四'.split(), 'n': [2, 0, 2, 3]})df.to_csv('data/data_1.csv', **encoding='gb2312'**, index=False)
然后,当试图用默认的 utf8 编码读取文件时,您应该得到一个 UnicodeDecodeError 。
# Read it with default encoding='utf8'
# You should get an error
pd.read_csv('data/data_1.csv')

为了正确地读取它,您应该传递文件编写的编码。
pd.read_csv('data/data_1.csv', **encoding='gb2312'**)

2.处理标题
标题是指列名。对于某些数据集,标题可能完全缺失,或者您可能希望将不同的行视为标题。read_csv()函数有一个名为header的参数,允许您指定要使用的头。
没有标题
如果您的 CSV 文件没有头,那么您需要将参数header设置为None,熊猫将生成一些整数值作为头
例如导入 data_2_no_headers.csv
pd.read_csv('data/data_2_no_headers.csv', **header=None**)

将不同行视为标题
我们来看看 data_2.csv
x1, x2, x3, x4
**product, price, cost, profit**
a, 10, 5, 1
b, 20, 12, 2
c, 30, 20, 3
d, 40, 30, 4
看起来更合理的列名应该是product、price、… profit,但是它们不在第一行。参数header还允许您指定用作列名和数据开始的行号。在这种情况下,我们希望跳过第一行,使用第二行作为标题:
pd.read_csv('data/data_2.csv', **header=1**)
3.处理列
当您的输入数据集包含大量列,并且您想要将这些列的子集加载到 DataFrame 中时,那么usecols将非常有用。
就性能而言,这样做更好,因为不必将整个数据帧加载到内存中,然后删除备用列,我们可以在加载数据集时选择我们需要的列。
让我们使用同一个数据集 data_2.csv 并选择 产品 和 成本 列。
pd.read_csv('data/data_2.csv',
header=1,
**usecols=['product', 'cost']**)

我们还可以将列索引传递给usecols:
pd.read_csv('data/data_2.csv',
header=1,
**usecols=[0, 1]**)
4.解析日期列
从 CSV 文件加载数据时,默认情况下日期列表示为对象。
df = pd.read_csv('data/data_3.csv')
df.info()RangeIndex: 4 entries, 0 to 3
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
**0 date 4 non-null object**
1 product 4 non-null object
2 price 4 non-null int64
3 cost 4 non-null int64
4 profit 4 non-null int64
dtypes: int64(3), object(2)
memory usage: 288.0+ bytes
为了正确读取 日期 列,我们可以使用参数parse_dates来指定日期列的列表。
df = pd.read_csv('data/data_3.csv', **parse_dates=['date']**)
df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4 entries, 0 to 3
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
**0 date 4 non-null datetime64[ns]**
1 product 4 non-null object
2 price 4 non-null int64
3 cost 4 non-null int64
4 profit 4 non-null int64
dtypes: datetime64[ns](1), int64(3), object(1)
memory usage: 288.0+ bytes
有时日期被拆分成多个列,例如, 年 , 月 , 日 。为了将它们组合成一个日期时间,我们可以将一个嵌套列表传递给parse_dates。
df = pd.read_csv('data/data_4.csv',
**parse_dates=[['year', 'month', 'day']]**)
df.info()RangeIndex: 4 entries, 0 to 3
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
**0 year_month_day 4 non-null datetime64[ns]**
1 product 4 non-null object
2 price 4 non-null int64
3 cost 4 non-null int64
4 profit 4 non-null int64
dtypes: datetime64[ns](1), int64(3), object(1)
memory usage: 288.0+ bytes
要指定一个自定义的列名来代替自动生成的year _ month _ day,我们可以通过一个字典来代替。
df = pd.read_csv('data/data_4.csv',
**parse_dates={ 'date': ['year', 'month', 'day'] }**)
df.info()
如果您的日期列是不同的格式,那么您可以定制一个日期解析器并将其传递给参数date_parser:
from datetime import datetime
**custom_date_parser = lambda x: datetime.strptime(x, "%Y %m %d %H:%M:%S")**pd.read_csv('data/data_6.csv',
parse_dates=['date'],
**date_parser=custom_date_parser**)
有关解析日期列的更多信息,请查看本文
[## 您应该知道的用 Pandas read_csv()解析日期列的 4 个技巧
一些最有用的熊猫把戏
towardsdatascience.com](/4-tricks-you-should-know-to-parse-date-columns-with-pandas-read-csv-27355bb2ad0e)
5.设置数据类型
如果要设置 DataFrame 列的数据类型,可以使用参数dtype,例如
pd.read_csv('data/data_7.csv',
**dtype={
'Name': str,
'Grade': int
}**)
6.查找和定位无效值
当使用参数dtype设置数据类型时,您可能会得到类型错误

发生这种错误时,查找并定位无效值总是有用的。以下是找到它们的方法:
df = pd.read_csv('data/data_8.csv')**is_error = pd.to_numeric(df['Grade'], errors='coerce').isna()**df[is_error]

7.向现有 CSV 文件追加数据
你可以在熊猫to_csv()函数中指定一个 Python 写模式。为了将数据添加到现有的 CSV 文件中,我们可以使用mode='a':
new_record = pd.DataFrame([['New name', pd.to_datetime('today')]],
columns=['Name', 'Date'])new_record.to_csv('data/existing_data.csv',
**mode='a',**
**header=None,**
**index=False**)
8.用chunksize加载一个巨大的 CSV 文件
默认情况下,Pandas read_csv()函数会将整个数据集加载到内存中,当导入一个巨大的 CSV 文件时,这可能是一个内存和性能问题。
read_csv()有一个名为chunksize的参数,它允许您以相同大小的块来检索数据。这在作为数据科学项目的一部分读取大型数据集时尤其有用。
让我们看看下面的一个例子:
首先,让我们创建一个 400,000 行的大型数据集,并将其保存到 big_file.csv
# Make up a huge datasetnums = 100_000for name in 'a b c d'.split():
df = pd.DataFrame({
'col_1': [1]*nums,
'col_2': np.random.randint(100, 2000, size=nums)
}) df['name'] = name
df.to_csv('data/big_file.csv',
mode='a',
index=False,
header= name=='a')

接下来,让我们在用read_csv()加载数据时指定一个 50,000 的chucksize
dfs = pd.read_csv('data/big_file.csv',
**chunksize=50_000,**
dtype={
'col_1': int,
'col_2': int,
'name': str
})
让我们对每个块执行一些聚合,然后将结果连接成一个数据帧。
res_dfs = []
**for chunk in dfs:**
res = chunk.groupby('name').col_2.agg(['count', 'sum'])
res_dfs.append(res)**pd.concat(res_dfs).groupby(level=0).sum()**

让我们对照没有chunksize的解决方案来验证结果
pd.read_csv('data/big_file.csv',
dtype={
'col_1': int,
'col_2': int,
'name': str
}).groupby('name').col_2.agg(['count', 'sum'])
你应该得到相同的输出。

好了
感谢阅读。
请在我的 Github 笔记本上查看源代码。
如果你对机器学习的实用方面感兴趣,请继续关注。
这里有一些相关的文章
参考
- [1] Kaggle 数据清理:字符编码
你可以用 GitHub API 和 Python 做的所有事情
GitHub REST API 允许您管理问题、分支、回购、提交等等,所以让我们看看您如何使用 Python 来做到这一点!
我们大多数人每天都在使用 GitHub,要么使用 CLI,要么使用它的网站。然而,有时您需要自动执行这些相同的任务,例如创建 Gist、查询存储库分析或只是拉取、修改和推送新文件。使用 GitHub API 可以很容易地完成所有这些事情,Python 可以在这方面提供帮助,让事情变得更加简单。

我们需要什么
在我们开始使用 GitHub API 之前,我们首先需要生成一个个人访问令牌,它将允许我们根据 API 进行身份验证。我们可以通过点击生成新令牌在https://github.com/settings/tokens获得一个。您将被要求为令牌选择范围。您选择的范围将决定您能够对 API 执行哪些信息和操作。你应该小心那些以write:、delete:和admin:为前缀的,因为这些可能具有相当大的破坏性。您可以在处的文档中找到每个范围的描述。
现在我们有了令牌,让我们测试它是否真的工作:
这是预期的(经过修整的)回应,显示了我的公共列表:
用 Python 做这件事
我们有了个人令牌,并用cURL测试了它,所以现在我们可以切换到用 Python 做同样的事情。不过,我们有两个选择。我们可以使用原始请求,也可以使用。
PyGitHub 公开了一些 GitHub API 端点,用于最常见的操作,如存储库、问题或分支管理。它不能用于通过 GitHub API 公开的每一个单独的特性,所以在下面的章节中,我将展示 PyGitHub 和 Requests 调用的混合,这取决于是否可以用 PyGitHub 来完成。
首先,让我们安装两个库( PyGitHub 和 Requests )并查看一个简单的例子:
使用 PyGitHub 的示例:
使用请求的示例:
上面的两个片段都使用相同的 API 端点来检索指定存储库的所有开放问题。
在这两种情况下,我们都从环境变量中获取 GitHub 令牌开始。接下来,在使用 PyGitHub 的示例中,我们使用令牌来创建GitHub类的实例,然后使用该实例来获取存储库并查询其处于打开状态的问题。结果是分页的问题列表,我们打印第一页。
在使用原始 HTTP 请求的示例中,我们通过从用户名和存储库名称构建 API URL 并向其发送 GET 请求来获得相同的结果,该请求包含作为主体参数的state和作为Authorization头的令牌。唯一的区别是结果没有分页。以下是两个示例的结果:
第一个是 PyGitHub 输出:
二、原始 Python 字典列表(JSON):
制造一个问题
在讨论话题的时候,让我们也创造一个话题,好吗?
这是用例之一,在这里 PyGitHub 非常方便。我们只需要获取存储库,针对它创建问题并指定一系列参数。在上面的代码片段中,我们使用了title、body、assignee和labels参数,但是您也可以添加里程碑或更多标签,使用它们的名称进行查询。
创造一个要点
我们可以创建的另一个东西是 GitHub Gist ,这次使用请求:
创建gist的请求非常简单。在 POST 请求中,您需要指定要点是否应该是public,接下来您需要填充将成为所述要点的一部分的files列表,其中每个关键字是一个文件名,其content包含文件的实际字符串内容。上面的代码使用json.dumps()将 Python 字典转换成 JSON 字符串来创建请求体和通常的授权头。
下面您可以看到预期响应的相关部分:
在创建了一个要点之后,你可能想要做其他的事情,比如更新它、列出提交、派生它或者只是获取它。对于所有这些操作,这些文档中列出了一个 API 端点。
以编程方式更新文件
使用 GitHub API 的一个非常实用但非常复杂的用例是以编程方式获取、修改、提交并最终将一些文件推送到存储库。让我们来分解一下,看一个例子:
从顶部开始,我们使用通常的存储库引用获取文件内容,将其解码为普通字符串并修改它。接下来,在push函数中,我们从使用source.commit.sha指定的提交创建新的分支。基于if的陈述,我们有两个选择:更新现有文件或创建新文件。如果我们正在进行更新,我们首先检索现有文件以获得其散列和路径,然后我们使用先前修改的数据(content)、提供的message、branch和author对象来执行更新。另一方面,如果我们想在存储库中创建一个新文件,那么我们只需忽略传入现有文件的 SHA,就完成了。
分析流量
如果您对数据科学和分析更感兴趣,您可能会发现从存储库中查询视图/克隆统计数据的有用可能性:
从 GiHub 中检索数据所需的代码实际上只有一行用于克隆和一行用于视图。clones和views对象都包含count、uniques和views属性。我们使用 print 语句中的前两个来分别显示实际的和唯一的克隆和视图。
令人讨厌的(漂亮的)一行遍历包含每天视图count的View对象列表,以及我们提取到元组列表中的各个timestamp。然后,我们找到具有最大值count的元组,并在最后一行打印其日期和实际视图计数。这为我们提供了如下所示的输出:
渲染降价
这个例子使用 GitHub API,但是也可以用于非 GitHub 目的。我说的是 GitHub APIs 从 markdown 文本生成 HTML 的能力。如果你的网站不能直接显示 markdown,这可能很有用,但是你可以使用 GitHub API 为你创建 HTML。
同样,查询非常简单。我们所要做的就是发送文本到text body 参数中,同时将模式设置为markdown。上面的text示例包括,code片段,斜体和粗体文本,这正是我们以 HTML 形式返回的内容:
回应:
更新提交状态
你知道 CI 工具在你的提交旁边添加的这些漂亮的绿色对勾、黄色圆圈和难看的红叉吗?您想改变它们吗(也许只是为了好玩,也许是作为您自己的 CI 解决方案的一部分)?你当然知道。有这样的 API:
令人惊讶的是(对我来说),这个模糊的 API 端点是 PyGitHub 库的一部分。为了使用它,我们使用提交散列来检索 repo 及其提交。之后,我们通过使用参数描述其当前状态来为所述提交创建状态。
我们可以指定 4 种状态,即error、failure、pending或success——在这个例子中,我选择了success。接下来,target_url是细节链接指向的 URL。您可能已经注意到,description和context是下面对话框中显示的其他值。

为了能够验证状态改变实际上已经完成,我们接收到代表提交当前状态的CommitStatus响应。在这种情况下看起来像这样:
添加对问题评论的反应
GitHub 问题评论允许你添加各种反应到其中。所以,也许你想给某人的评论加上+1 / -1。也许只是加入一些庆祝的表情符号。如果是这样的话,那么你可以用 Python 来实现:
为了能够创建响应,我们需要注释 ID。可以从文档中此处显示的API 中检索,或者点击问题评论右上角的三点图标,然后点击复制链接:

这样我们就可以在 URL 中插入owner用户名、repo姓名和这个comment_id,在content主体参数中插入表情名称(例如hooray)。此外,我们还需要包括Accept头,因为这个端点是开发者预览的一部分。
这里的预期响应是201,这意味着该反应已被创建,或者是200,在这种情况下,该反应已经被预先添加。
这是我们得到的(经过修整的)JSON 响应体:
结论
玩公共 API 是开始一个新项目的好方法(例如 CI 工具、存储库流量分析、GitHub 机器人), GitHub API 有很多这样的数据/内容。我在这里展示的只是一个小样本。要探索完整的 API,请查看这里的文档或者如果您不想弄乱 REST API,请查看 PyGitHub 示例。
如果你喜欢这篇文章,你应该看看我下面的其他 Python 文章!
本文最初发布于martinheinz . dev
每个 Python 项目都可以从使用 Makefile、优化的 Docker 映像、配置良好的 CI/CD、代码…
towardsdatascience.com](/automating-every-aspect-of-your-python-project-6517336af9da) [## 下一个 Python 项目的最终设置
从零开始任何项目都可能是一项艰巨的任务…但如果您有这个最终的 Python 项目蓝图就不会了!
towardsdatascience.com](/ultimate-setup-for-your-next-python-project-179bda8a7c2c) [## 使用 Python 实现 gRPC 服务器
你的下一个 API 不需要用 REST 和 JSON 来构建。gRPC 和协议缓冲区如何获得更好的性能…
towardsdatascience.com](/implementing-grpc-server-using-python-9dc42e8daea0)
从信息论到机器学习中的日志丢失
熵、交叉熵、对数损失和背后的直觉

马库斯·斯皮斯克在 Unsplash 上的照片
1948 年,Claude Shannon 在他长达 55 页的论文中介绍了信息论,这篇论文名为“一种沟通的数学理论”。信息论是我们开始讨论的地方,这将把我们带到 log loss,这是机器学习和深度学习模型中广泛使用的成本函数。
信息论的目标是有效地将信息从发送者传递到接收者。在数字时代,信息用比特 0 和 1 来表示。根据香农的说法,发送给接收者的一位信息意味着将接收者的不确定性降低两倍。因此,信息与不确定性的减少成正比。
考虑抛一枚公平硬币的情况。正面朝上的概率 P(正面)是 0.5。在你(接收者)被告知正面朝上后,P(正面)变成 1。因此,1 比特的信息被发送给你,不确定性被降低了两倍。我们获得的信息量是不确定性的减少,不确定性是事件概率的倒数。
信息的位数可以通过不确定性减少的对数(以 2 为底)很容易地计算出来。

(图片由作者提供)
让我们来看一个稍微复杂一点的案例。你的两个朋友去商店买一件 t 恤,有 4 种不同的颜色可供选择。
你的朋友朱莉娅有点犹豫不决,她告诉你她可以选择任何颜色。你的另一个朋友约翰告诉你,他喜欢蓝色,他很可能会买一件蓝色的 t 恤。
你对朱莉娅的决定肯定比对约翰的更不确定。熵是一种量化不确定性的度量。更准确地说,它是从概率分布内的样本接收的平均信息量。
下表显示了 Julia 和 John 购买 t 恤衫事件的概率分布。

朱莉娅和约翰购买 t 恤衫的概率分布(图片由作者提供)
让我们从朱莉娅开始。如果朱莉娅选蓝色,不确定性减少 4 (1/0.25)。在以 2 为底的对数中等于 2 位(熵的基本单位是位)。因此,在蓝色的情况下,我们获得的信息量是 2 位。由于熵是样本的平均信息量,我们对其他颜色重复相同的计算。因为概率相同,所以它们的位数相同。对于 Julia,熵的计算如下:

(图片由作者提供)
对约翰来说,步骤是一样的,但结果是不同的。

(图片由作者提供)
熵更多的是在朱莉娅的情况下,所以我们对朱莉娅的决定有更多的不确定性,这是我们开始时预期的。
我们已经计算了熵。是时候引入公式了:

熵的公式(图片作者提供)
注意:我们在计算中没有包括负号,因为它已经通过取概率的倒数(1 / p)而被消除了。
我们有两个事件,有四个结果。第一个事件是朱莉娅买了一件 t 恤衫,第二个事件是约翰买了一件 t 恤衫。熵分别是 2 比特和 1.19 比特。换句话说,平均来说,我们接收到关于第一个事件的 2 比特信息和关于第二个事件的 1.19 比特信息。
我们正在朝着机器学习中使用的概念前进。下一个主题是交叉熵,它是平均消息长度。
你的朋友选择的颜色是以数字方式(即以比特为单位)传输给你的。下表表示用于传输有关 John 选择的信息的两种不同编码。

(图片由作者提供)
在情况 1 中,每种颜色使用两位。因此,平均消息长度为 2。

(图片由作者提供)
Julia 可以接受这种编码,但 John 不能接受。约翰的选择的概率分布的熵是 1.19 比特,因此平均使用 2 比特来发送关于他的选择的信息不是最佳方式。
在情况 2 中,交叉熵结果是 1.3 比特。它仍然大于 1.19,但肯定比情况 1 更好。

(图片由作者提供)
但是,“十字架”这个词从何而来?在计算交叉熵时,我们实际上是在比较两种不同的概率分布。一个是变量的实际概率分布,另一个是比特选择的预测概率分布。

(图片由作者提供)
交叉熵可以表示为真实分布和预测分布的函数,如下所示:

交叉熵公式(图片由作者提供)
如果你看看我们为寻找交叉熵所做的计算,你会注意到这些步骤与这个公式重叠。
我们现在可以开始讨论交叉熵如何用于机器学习领域。交叉熵损失(即对数损失)是机器学习和深度学习模型中广泛使用的成本函数。
交叉熵量化了两个概率分布的比较。在监督学习任务中,我们有一个目标变量,我们试图预测。使用交叉熵比较目标变量的实际分布和我们的预测。结果是交叉熵损失,也称为对数损失。
交叉熵和交叉熵损失略有不同。计算损失时,通常使用自然对数,而不是以 2 为底的对数。
交叉熵损失:

交叉熵损失(图片由作者提供)
我们来做一个例子。我们有一个 4 类的分类问题。我们的模型对特定观测值的预测如下:

(图片由作者提供)
因为我们知道真实的概率分布,所以对于真实类是 100%,对于所有其他类是 0。根据我们的模型,这个观察值所属的类是有 80%概率的类 1。该特定观察的交叉熵损失计算如下:

(图片由作者提供)
因为除了实际类别之外,所有类别的真实概率都是零,所以只有实际类别的预测概率对交叉熵损失有贡献。
请记住,这是特定观察的损失。训练集或测试集的损失是该集中所有观测值的交叉熵的平均值。
为什么会日志丢失?
您可能想知道为什么使用对数损失而不是分类精度作为成本函数。
下表显示了两个不同模型对一个由 5 个观察值组成的相对较小的集合的预测。

(图片由作者提供)
两个模型都正确地对 5 个观察值中的 4 个进行了分类。因此,在分类精度方面,这些模型具有相同的性能。然而,概率揭示了模型 1 在预测中更确定。因此,总体而言,它的表现可能会更好。
对数损失(即交叉熵损失)提供了对分类模型的更稳健和准确的评估。
感谢您的阅读。如果您有任何反馈,请告诉我。
参考文献
- http://people . math . Harvard . edu/~ CTM/home/text/others/Shannon/entropy/entropy . pdf
- https://www.youtube.com/watch?v=ErfnhcEV1O8
全 GCP:在虚拟机实例中安装 ORACLE 数据库

众所周知,ORACLE 是甲骨文公司的专有数据库之一。由于这不是开源软件,在云上使用它相当困难。
如果你真的想在云中使用 oracle,最简单的(也可能是唯一的)解决方案是使用支持 Oracle 数据库的 Oracle cloud 。
据我所知,甲骨文不支持任何其他云提供商的许可。但大多数用户使用 AWS、GCP 和 Azure 的云解决方案。仅将 Oracle 云用于数据库实际上是错误的。
动机
对于我的组织,我需要从。dmp 文件。由于我们严重依赖 GCP,使用 GCP 进行数据库存储是显而易见的。
安装步骤
启动虚拟机实例
- 启动虚拟机实例
- 使用 Centos 图像

3.虚拟机初始化后,点击 SSH(如果需要,我们可以使用 putty )

将 Oracle 安装到 Centos 虚拟机
- 安装所需的软件包
sudo yum 安装 unzip libaio bc flex wget

2.我们将使用 dd 命令创建一个 2GB 大小的交换文件,如下所示。请注意,bs=1024 表示一次最多读取和写入 1024 个字节,count = (1024 x 2048)MB 文件大小。
sudo DD if =/dev/zero of =/mnt/swap file bs = 1024 count = 2097152
3.对文件设置适当的权限;使它只对根用户可读,如下所示。
sudo chmod 600 /mnt/swapfile
4.现在用 mkswap 命令为交换空间设置文件。
sudo mkswap /mnt/swapfile
5.启用交换文件,并将其作为交换文件添加到系统中。
swapon /mnt/swapfile
6.允许在引导时挂载交换文件。
编辑 /etc/fstab 文件,并在其中添加以下行。
/mnt/swapfile 交换交换默认值 0 0
7.下载 Oracle 数据库快速版 11g
8.使用 wget
重命名文件名(我将其命名为 Oracle-xe-11 . 2 . 0–1.0 . x86 _ 64 . rpm . zip)
9.更改权限
chmod 755 Oracle-xe-11 . 2 . 0–1.0 . x86 _ 64 . rpm . zip
解压缩 Oracle-xe-11 . 2 . 0–1.0 . x86 _ 64 . rpm . zip
10.然后转到文件夹
光盘 1
sudo rpm-IVH Oracle-xe-11 . 2 . 0–1.0 . x86 _ 64 . rpm
sudo/etc/init . d/Oracle-xe configure
11.安装好了!
通过虚拟机登录 Oracle
- 切换到 oracle 用户
sudo 密码 oracle
2.检查类型
显示本用户信息
苏——甲骨文
3.去…
vi $HOME/。轮廓
4.写
。~/product/11 . 2 . 0/xe/bin/Oracle _ env . sh
5.注销
注销
6.再次登录
苏——甲骨文
7.注册
sqlplus / as sysdba

您已经成功登录到 Oracle 数据库。万岁!
视频教程
尾注
谢谢你达到这个目的。如果你想了解更多与此相关的内容,你可以通过 Linkedin 或 email :)联系我
所有的向量都不相等,但有些向量比其他向量更不相等…

在特朗普的推文中寻找意义。第二部分。
从我们在第一部分停止的地方继续,深入到矢量文本。讨论使用文本向量表示的问题,并为最后一部分设置场景,我们将尝试解决这些问题。
在第一部分中,我们设置了问题,并对数据集进行了一些基本的探索性分析。概括地说,我们使用特朗普四年的推文历史作为 NLP 分析的试验场。好处是,这是一个具有挑战性的数据集,相当混乱,有许多缩写和连接的单词,标签。每条推文都是一个相对较短的句子,有时是句子的一部分(因为几条推文之间的分裂,或者因为它是对附加链接或图像的一个单词的评论)。格式的简洁为主题识别提供了一个特殊的挑战,因为我们实际上没有太多的文本可以继续。
关于数据集的链接和初始处理步骤(以及一些额外的分析),请参见本系列的第一部分:
这比你想象的要难。使用 LDA、TSNE、Spacy、Gensim 和 XX-Berts 进行深入的 NLP 分析,以获得良好的…
medium.com](https://medium.com/swlh/searching-for-meaning-in-trumps-tweets-part-i-dbb453be26ee)
在这里,我们将运行预处理的数据帧,其中我们已经创建了一个三元组集合。
这里有一张快照,让您更好地了解我们面临的情况:

Word2Vec
在这篇文章中,我们将使用 Spacy 的大型语料库来看看一个相当标准的 word2vec 表示(请参见第一部分的导入/设置)。Bert 表示将非常相似,至少在我们需要采取的步骤方面,以获得最终答案(我们将使用预先计算的权重),所以我将把它们留到第 3 部分。
把这些都放在一个地方:
import spacy
import en_core_web_lg
nlp = en_core_web_lg.load()X_w2v = np.array(
trgrms['trigram'].apply(
lambda x: nlp(' '.join(x)).vector
).apply(pd.Series).values
)
这里发生的是——我们首先将 nlp.vector 应用于“三元模型”列中的令牌列表。本质上,我们将每个句子的整个单词/二元模型/三元模型集合转换成一个 300 维的向量(如果你认为这很多,那就等着看 Bert 模型家族吧)。第二个 apply 将每个维度拆分成一个单独的列,因此我们可以得到一个包含 300 列的漂亮而干净的 numpy 数组:
array([[-0.23228563, -0.17819926, 0.00618625, ..., 0.18152575,
0.003564 , -0.00292437],
[-0.13923544, 0.16094644, -0.08356622, ..., 0.01945878,
-0.00872067, 0.00360556],
[-0.38719398, 0.3154016 , 0.0200642 , ..., -0.0342296 ,
0.0602775 , -0.01440797],
...,
[-0.27288002, 0.22488602, -0.18610317, ..., 0.01231567,
-0.29833835, -0.0486265 ],
[-0.01917143, 0.09390885, -0.20039713, ..., 0.08660271,
-0.22473843, 0.14869857],
[-0.0496735 , 0.20026001, -0.156335 , ..., -0.039683 ,
0.476 , 0.07886 ]], dtype=float32)
即使我们不能完全想象这一点,因为我们局限于可怜的 3D 视觉,我们当然可以尝试并找到一些表示,让我们至少知道我们面对的是什么。
我们要做的第一件事是,我们只看前两个维度(或者我们想要选择的任何一对维度,只是为了对其中潜藏的东西有所了解):
plt.figure(figsize=(12,12))
sns.scatterplot(
x='x',
y='y',
data=pd.DataFrame(X[:, [0, 1]], columns=['x', 'y']),
s=20,
alpha=0.7
)

这看起来就像一个大斑点。如果你在其他维度中循环——你会发现所有维度都非常相似。虽然乍一看令人失望,但这实际上给出了一个重要的见解。我一次又一次地看到人们进行向量转换,然后直接使用 KMeans 进行聚类,并试图从他们不可避免地识别的聚类中得出一些结论(这就是 KMeans 的工作方式——如果你告诉它在这里找到 36 个聚类,它会毫不犹豫地找到所有 36 个聚类)。现实是,这种集群化是没有意义的,被识别的组和随机的一样好。
也许这太令人惊讶了,因为单词或整个句子甚至句子集合的向量表示主要与它们的共现频率有关。它背后确实有一些含义,但不一定是为了主题识别而准备的。很难在 300 个维度(或伯特模型中的 768 个维度)中的每一个背后建立任何类型的直觉,尽管人们可以推测其中只有一小部分会负责语义关系的大部分。问题是我们不知道哪一个,并且在无监督的模型设置中很难找到它们。
向前跳一点——使用 Bert 嵌入对这一点来说特别具有挑战性,因为我们有更多的维度,并且它们根本没有为向量相似性做好准备。事实上,试图计算不同句子之间的余弦将导致它们都非常接近 1,并且从句子到句子的比较中得出任何意义将是极其困难的。已经进行了一些尝试来重新训练专门用于相似性任务的权重,然而结果并不足够普遍以用于任何设置。我们需要为我们的特定目的训练模型,这是我们在这里试图避免的,因为我们的数据集不够大。
这并不意味着我们应该就此止步。我发现尝试降低问题的维度,看看我们是否可以通过这种方式获得更好的结果,这很有启发性。
降维
首先,我们来看看主成分分析。如果你以前没有使用过,这里的是一个很好的教程,可以提供一个快速的概述,或者在维基百科这里阅读更深入的理论概述。本质上,我们正在做的是拟合一个为数据集定制的新坐标系,并删除最不重要的轴。我们将把它减少到只有 2D,可视化它,看看我们是否喜欢我们的新数据表示比我们以前玩的随机选择的维度更好。请注意,PCA 并不只是从我们的原始数据集中选择两个最重要的维度——生成的维度是全新的,它们本身是我们原始的 300 维轴的线性组合。还值得注意的是,除非我们做一个完整的 300 到 300 转换,否则我们将无法转换回来,通过下降到 2D,我们将不可避免地丢失一些信息。
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_w2v_pca = pca.fit_transform(X_w2v)
plt.figure(figsize=(12,12))
sns.scatterplot(
x='x',
y='y',
data=pd.DataFrame(X_w2v_pca, columns=['x', 'y']),
s=20,
alpha=0.7
)

好不了多少……结构有些变化,但是如果你在寻找被一些与意义或情感有一点点联系的东西分开的文本组,你可能在这里找不到。
但是我们不会轻易放弃。让我们看看,如果我们能得到更多的使用 SNE 霸王龙。它代表 t-分布式随机邻居嵌入,除了比 PCA 年轻 75 年之外,它通常可以更好地处理多维非线性系统。关于 t-SNE 更深入的讨论,请看这里的。让我们看看,如果将 t-SNE 应用于数据集,我们可以达到什么程度:
from sklearn.manifold import TSNE
X_w2v_tsne = TSNE(n_components=2).fit_transform(X_w2v)
plt.figure(figsize=(15,15))
sns.scatterplot(X_w2v_tsne[:,0], X_w2v_tsne[:,1])

这已经好多了。数据无疑是聚集的。我仍然会非常小心这里的 KMeans 应用程序,因为我们无法真正确定这里的最佳集群数量,而且它看起来非常大。
研究星团
我将在这里应用一些定制的东西——我在我的 2 篇文章系列中描述的聚类算法:
深入研究一种新的聚类识别方法。
towardsdatascience.com](/a-fresh-look-at-clustering-algorithms-c3c4caa1a691) [## 聚类算法。第二部分。
更快、更聪明、更快乐…
towardsdatascience.com](/clustering-algorithm-part-2-57907f5c0437)
第 2 部分附有所有需要的代码。理论上,我们可以将该算法应用于第一步中的 300 维矩阵,但是维数灾难在那里非常活跃,我们将最终只得到一个聚类。这在一定程度上与我们的数据集不够大的事实有关,考虑到我们处理的维度数量,数据点实在是太少了。或者,这可能是 SNE 霸王龙在没有结构的地方找到了结构,所以我们需要更详细地观察它。
让我们将聚类算法应用于 t-SNE 结果,然后我们可以看到这些聚类是否既合理(图形上)又有意义(语义上)。
第一步,我们需要确定每个维度的最佳分割数。此外,该算法的当前版本需要标准化的数据,因此让我们继续并同时执行这两项操作:
import sklearn
Xtsne_norm = sklearn.preprocessing.normalize(X_w2v_tsne, axis=0, norm='max')
prop=[]
for d in range(1,200,1):
Xint = (Xtsne_norm * d).astype(int)
unique, counts = np.unique(Xint, axis=0, return_counts=True)
prop.append(
len(counts[counts > 7]) / (
len(counts[counts == 1]
) + len(Xint) - len(unique)
)
)plt.figure(figsize=(12, 8))
plt.plot(list(range(1, 200, 1)), prop)

在我们的道具列表上应用 np.argmax 得到 25,所以我们将运行 25 作为 D 参数(每个方向的分裂数)和第 90 百分位置信水平。降低置信度将导致一些集群合并在一起。更高的值会导致一些不太明显的集群被忽略。就目前而言,我们希望变得更加细化。我们还应用了算法的最近邻版本来对所有被遗漏的点进行属性化。
yh=density_trees_fit_nn(Xtsne_norm, 25, 90, attribute=True)
获取我们:
Processed 99.24% ids
19 clusters found
首先,让我们想象一下:
plt.figure(figsize=(15,15))
for i in np.unique(yh):
sns.scatterplot(Xtsne_norm[yh==i][:,0],Xtsne_norm[yh==i][:,1], s=20, alpha=0.7, label=i)

也许不完美,但也没那么糟。让我们看看我们是否能从这些组中得到一些合理的东西,看看一些较大的组中的前 10 个词:
res = []
for yi, ci in zip(*np.unique(yh, return_counts=True)):
if ci>600:
w,c = np.unique(
trgrms[yh == yi]['trigram'].sum(),
return_counts=True
)
res.append(
pd.DataFrame(
{
'words':w,
'counts':c
}
).sort_values(
'counts',
ascending=False
).reset_index(drop=True).head(10)
)
600up = pd.concat(res,axis=1)
600up

计数在 300 和 600 之间:

200 到 300:

一方面,它看起来一点也不坏,我们开始在这里发展一些主题。关于贸易/关税和中国的推文明显分组在一起(尽管它们分成两组,可能应该合并),关于边境和臭名昭著的隔离墙的推文也有联系,fake/news/cnn 在另一组。关于集会的公告,为即将到来的采访做广告,或者宣传一个受欢迎的州长候选人——所有这些现在都清晰可辨。
有趣的是,看起来像是可以合并的群组,确实是紧挨着出现的。例如,提及中国和关税的两个组与集合中的其他组相比如下:

当然也有问题。例如,大多数连接在一起的单词和二元模型最终都堆积在一起,因为它们没有得到适当的处理,所以它们最终都是一个通用向量(左下角的两个同心圆)。大量的术语出现在多个组中,这是意料之中的,因为我们使用整个 tweets 而不是单个单词进行分组。这可能可以通过查看单词重要性的度量来减轻。然而,并非所有情况下都是如此,因为,例如,许多关于“假新闻”的推文最终与通用组捆绑在一起,所以这些只是没有被识别出来。也有本该上来却没有上来的话题。
有些问题我们应该可以通过使用更通用的文本向量表示法来解决,这种向量表示法使用的是 Bert 模型族。这些将未知单词分解成组件,并尝试以这种方式匹配它们,这对连接单词很有帮助。我将在第 3 部分讨论这些,以及基于 LDA 和两者结合的更直观的主题建模。
今天到此为止。感谢您的阅读。
初始化你的神经网络的所有方法
在本文中,我评估了权重初始化的许多方法和当前的最佳实践。
零初始化
将权重初始化为零不起作用。那为什么我在这里提到了?为了理解权重初始化的需要,我们需要理解为什么将权重初始化为零不会工作。

图一。简单的网络。图片由作者提供。
让我们考虑一个如上所示的简单网络。每个输入只是一个定标器 X₁,X₂,X₃.每个神经元的权重是 W₁和 W₂.每次重量更新如下:
out₁=x₁w₁+x₂w₁+x₃w₁
out₂=x₁w₂+x₂w₂+x₃w₂
正如你现在看到的,如果权重矩阵 W = [W₁ W₂]被初始化为零,那么 out1 和 out2 完全相同。
即使我们向两者添加非零随机偏置项,权重也被更新为非零,然而,它们将保持相同,因此隐藏单元的两个神经元正在计算相同的东西。换句话说,它们是 对称 。
这是非常不希望的,因为这是浪费计算。这就是零初始化不起作用的原因。
随机初始化
现在我们知道权重必须不同,下一个想法是随机初始化这些权重。随机初始化比零初始化好很多,但是这些随机数可以是 任意 数吗?
让我们假设您使用的是 sigmoid 非线性。函数如下图所示。

乙状结肠。图片由作者提供。
我们可以看到,即使对于大到 6 的值,sigmoid 的值也几乎是 1,而对于小到-6 的值,sigmoid 的值是 0。这意味着如果我们的权重矩阵被初始化为太大或太小的值,所有有用的信息都会在 sigmoid 函数中丢失。
如果我们使用 ReLu 非线性,这并不重要,但是当权重被初始化为大或小的值时,会有其他问题。有更好的方法来初始化我们的权重。
Xavier 初始化
Xavier 初始化由 Xavier Glorot 和 Yoshua Bengio 在 2010 年提出。本文的主要目的是初始化权重,使激活的平均值为零,标准差为 1。考虑如下所示计算的函数。
Z = WX + b
这里 W 是权重矩阵,X 是来自前一层的输入,b 是偏差。z 是由也称为激活的层计算的输出。我们希望 Z 的平均值为 0,标准差为 1。(从技术上讲,Z 是类似 ReLu 的非线性激活后的结果)
为什么均值为零和标准差为 1 很重要?
考虑一个有 100 层的深度神经网络。在每一步,权重矩阵与来自前一层的激活相乘。如果每一层的激活数大于 1,当它们重复相乘 100 次时,它们将继续变大,并且将爆炸到无穷大。类似地,如果激活少于一次,它们将消失到零。这就是所谓的 爆炸和消失渐变 问题。我们可以在下图中看到这一点。稍大于 1 的值会爆炸成非常大的数字,稍小于 1 的值会消失为零。

图片由作者提供。
为了避免渐变和激活的爆炸和消失,我们希望激活的平均值为 0,标准差为 1。我们可以通过精心选择砝码来实现这一目标。
在本文发布期间,权重的最佳实践是从[-1,1]的 均匀分布 中随机选择,然后除以输入维度的平方根。事实证明,这不是一个好主意,梯度消失,训练非常缓慢,如果可能的话。
Xavier 初始化解决了这个问题,他建议我们从均匀分布中随机初始化权重,如下所示。

泽维尔初始化均匀分布。图片由作者提供。
如今,Xavier 初始化是通过从标准正态分布中选择权重来完成的,并且每个元素被除以输入维度大小的平方根。在 PyTorch 中,代码如下。
*torch.randn(n_inp, n_out)*math.sqrt(1/n_inp)*
Xavier 初始化非常适合 sigmoid 和 Tanh 等对称非线性。然而,对于现在最流行的非线性项 ReLu 来说,它就不那么适用了。
明凯初始化
何等人在 2015 年写了一篇名为《深入研究 整流器:在 ImageNet 分类 上超越人类水平的性能》的论文,他们在论文中介绍了现在广为人知的明凯 Init。
但是我们为什么需要明凯呢?Xavier Init 在 ReLu 非线性方面有什么问题?

雷鲁。图片由作者提供。
从上图可以看出,对于所有 X <0 and Y=X for all X> 0,ReLu 给出 0。ReLu 没有很好地定义为 0,但是大多数现代程序赋予它一个接近于 0 的近似值,就像机器ε。

左图:平均值为 0、标准差为 1 的正态分布。右图:经过 ReLu 后的正态分布。图片由作者提供。
上面我们可以看到两个散点图,左边是 ReLu 之前的数据,右边是 ReLu 之后的数据。从图像中可以清楚地看到,在 ReLu 之后,方差几乎是一半,平均值略高。这改变了激活,方差减半,所以我们需要将方差加倍,以获得 Xavier Init 的原始效果。因此,我们将权重乘以额外的
√2 。所以在 PyTorch 中,明凯 Init 如下所示。
*torch.randn(n_inp, n_out)*math.sqrt(2/n_inp)*
如果你仍然感到困惑:
方差=(标准差)
因此,如果你想将方差加倍,你可以将数据乘以 √2
修复初始化
Fixup 是张等人在 2019 年提出的一种初始化。他们的观察是,明凯初始化和其他标准初始化对于具有剩余分支的网络(又名剩余网络)来说效果不佳。他们发现使用标准初始化的残差网络仅在使用 批处理 时工作良好。
让我们看看为什么明凯 Init 在剩余网络上不起作用。考虑下图所示的跳过连接。**X2 = f(X1)**X3 = f(X2)+X1**。我们知道,明凯初始化选择权重,使得每层之后的激活具有 0 均值和 1 方差。所以我们知道 X1 的方差为 1,X2 的方差为 1。但是明凯初始化不考虑跳过连接。因此,根据总方差定律,X3 的方差是双倍的。剩余分支增加的额外差异在明凯初始化中没有考虑。因此,剩余网络不能很好地与标准 init 一起工作,除非它们有 BatchNorm。如果没有 BatchNorm,输出方差会随深度呈指数增长。
Var[Xₗ₊₁] ≈ 2Var[Xₗ ]

跳过剩余网络中的连接。图片由作者提供。
论文中的作者进行了重要的观察,即 SGD 对每个剩余分支的权重的更新以高度相关的方向更新了网络输出。这意味着,如果剩余分支权重全部由 X 更新,网络输出也在权重更新的相同方向上与 X 成比例地变化。
作者将所需的网络输出变化定义为θ(η)。如我们所知,平均而言,每个剩余分支更新对输出更新的贡献是相等的,如果我们将剩余分支的数量称为 L,则平均而言,每个剩余分支应该将输出改变θ(η/L ),以实现输出的总改变θ(η)。
接下来,作者展示了他们如何初始化 m 层的剩余分支,以便它的 SGD 更新将输出改变θ(η/L)。作者表明,这可以通过以下方式重新调整这些权重层的标准初始值来实现:

重量比例因子。图片由作者提供。
作者还讨论了偏差和乘数的效用。他们发现,在每次卷积之前添加一个初始化为 0 的偏置层,线性层和逐元素激活可以显著改善训练。他们发现,在每个剩余分支上增加一个乘法定标器,有助于模拟标准化网络的权重范数动态。
总结一下修正:

修复摘要。图片摘自张等人的修图论文。
Fixup 有点令人困惑,所以如果你有任何问题,请在评论中自由提问,我将很乐意尽我所能回答。
LSUV 初始化
LSUV 是由 Mishkin 等人在 2016 年的一篇名为 的论文中介绍的,你需要的只是一个好的 Init 。LSUV Init 是一种数据驱动的方法,具有最小的计算量和非常低的计算开销。初始化是一个两部分的过程,首先初始化正交矩阵的权重(与高斯噪声相反,高斯噪声只是近似正交的)。下一步是用一个小批量进行迭代,并调整权重,使激活的方差为 1。作者断言,在很大范围内,小批量对方差的影响可以忽略不计。
在本文中,作者列出了如下初始化步骤。
- 将权重初始化为具有单位方差的高斯噪声。
- 用 SVD 或 QR 将它们分解成正交基。
- 使用第一个小批量在网络中迭代,并在每次迭代中调整权重,以使输出方差更接近 1。重复直到输出方差为 1 或最大迭代次数已经发生。
在论文中,作者提出缩放因子为 √Var(BL) ,其中
BL——其输出 blob作者还提出了一个最大迭代次数的值来防止无限循环,然而,在他们的实验中,他们发现单位方差是在 1-5 次迭代中达到的。
LSUV Init 可视为正交初始化和 BatchNorm 的组合,batch norm 仅在第一个小批量上执行。作者在实验中表明,与完全批处理相比,这种方法具有很高的计算效率。

LSUV 算法。图像取自 LSUV 纸张。
迁移学习
迁移学习是在我们的新模型中使用已经训练过的模型的权重的方法,该模型是为类似的任务而训练的。这些重量已经学习了许多有用的信息,我们可以简单地为我们的特定目标进行微调,然后瞧!我们有一个惊人的模型,没有初始化的麻烦。
每次都使用另一个模型的预训练权重是最好的方法。我们唯一需要初始化我们自己的权重的时候是我们在一个从来没有人训练过的网络上工作。而在大多数实际场景中,几乎不会出现这种情况。
关于 Git、GitHub 和 GitLab 您需要知道的一切

数据科学家入门包—第 2 部分
在上一篇文章中,我谈到了在从事数据科学项目时需要使用的一些最重要的工具,包括 VS 代码中的Git小部件。在本文中,我们将揭开工具Git的神秘面纱,该工具允许对代码进行versioning以及对collaborative库的处理。
目录
摘要如下:
- Git & GitHub/GitLab
- 你的第一个库库
- 推拉码
- Git 项目理念
- 带 GitLab 的 CI-CD
1.Git & Github
Git 是一个编码工具,主要用于三个原因:
- 代码的时间版本控制
- 跟踪所做的更改
- 允许多个部分的并行协作
为此,git 分三个阶段工作:
Working directory:是存放你项目所有文件的本地文件夹,更确切地说,是 git 被初始化的文件夹Staging directory:记录并索引每一个修改过的文档Git local repository:每次执行的更改都会产生一个版本的文档或快照,可以使用消息对其进行拍摄和标记。
在深入 git 的命令行之前,让我们先看看如何安装和配置它。
安装 Git
- Windows:从以下网站下载 Windows Git 安装程序
- Mac:大部分版本的 MacOs 都已经安装了 git。
配置 Git
如前所述,git 是一个版本控制和协作工具,因此了解项目中每个文件的工作人员非常重要,这就是为什么您应该使用您的姓名和邮件来配置 git:
git config --global user.name "Name"
git config --global user.mail "mail"
2.您的第一个存储库
创建您的第一个 Git 回购
一旦安装并配置了 git,您就可以使用以下命令行创建您的第一个 git 项目:
mkdir projectFolder
cd projectFolder
git init #initialize git on your project
git status
touch file.md # create new file
open file.md # open the file and modify it
git status # file untracked -> add it to git index
git add file.md
git commit -m "file.md modified ..."
在下一段中,你会发现图表总结了不同阶段之间的关系。
在 GitHub/GitLab 上托管您的存储库
Github 或 GitLab 是允许托管您的项目和协调多方协作的平台。以下步骤详细说明了如何做到这一点:
- 在 GitHub/GitLab 中创建一个帐户
- 创建新存储库
- 复制它的链接
- 将其克隆到您计算机上的一个文件夹中
- 对它们的提交进行所有必要的更改
- 将更改推送到 GitHub/GitLab
NB1:前四步只进行一次,而第五步和第六步重复进行(见下一段)。NB2:也可以使用以下命令将现有文件夹推入 github 目录:
git remote add origin gitAdress
git branch -M master
git push -u origin master
3.推拉代码
一旦你完成了所有的修改,你会想要把你的工作分享给 GitHub/GitLab 库,以便让你团队的其他成员也能访问到它。以下是需要遵循的必要步骤:
- 修改您计算机上的文件
- 运行:
git add file.extension #Add it to the git index:
git commit -m "message" #Commit the changes
git push #Push the changes to github
您可能还想通过使用以下命令行来获取其他人所做的最新更改:
git pull
下图显示了本地存储库和 GitHub/GitLab 之间的连接。

作者图片
注意:当从 GitHub/GitLab 推送或拉取时,您的凭证将被填写。
插图
在下面的 GIF 中,我将创建一个本地文件夹,在其中启动 git 版本控制,并创建一个名为 README.md 的文件,然后添加并提交更改。稍后,我将创建一个 Github repo,将本地文件夹推送到这个 repo,并检查 Github 是否得到了更新:

作者图片
合作
在处理一个复杂的项目时,团队的每个成员通常都被分配到一个任务或功能上,他或她可以独立地工作。也就是说,每个项目可以被看作由不同成员处理的多个子项目。为了协调他们的工作,git 使用了分支的概念:主分支被称为master,一旦其他分支上的工作稳定下来,其他分支就可以合并到其中。分支也可以用来将production版本从development版本中分离出来,其中新的功能不断被开发,因此得名。以下是结合两者的智能工作流程:

作者图片
为此,一旦进入 git 存储库,就可以使用下面的 bash 脚本:
git branch # get current branch (master)
git checkout -b devBranch # create and switch to development branch
git checkout -b featureBranch devBranch # Create feature branch over the development branch
git add file.extension # Add changed file to staging
git commit -m "message" # commit the message
git checkout devBranch # switch back to development branch
git merge featureBranch # merge featureBranch into devBranch
git push origin featureBranch # push the changes on featureBranch to github/gitlab
git push origin devBranch # push the changes on devBranch to github/gitlab
他用之前的项目举例说明了分支和合并:

作者图片
当合并分支时,可能会发生一些冲突,尤其是当两个人处理同一个文件时,在这种情况下,您应该
- 打开引发冲突的文件
- 解决冲突(例如使用 VSCode)
- 运行:
git add .
git commit -m "message"
NB 1 :分支也可以被看作是对开源项目做出贡献的一种方式,即它们的代码在 GitHub/GitLab 上公开发布。
NB 2 :你可能想要在你的机器和你的 GitHub/GitLab 库之间设置一个SSH连接,以便让你的协作更加流畅。
忽略文件
在某些情况下,某些文件应该保存在本地,在这种情况下,这些文件的relative path应该添加到 git 启动时自动创建的.gitignore文件中。Github 和 Gitlab 主要用于处理商店代码,因此向它们发送数据库或深度学习权重没有意义,它们的路径通常被添加到.gitignore文件中。
WEIGHTS_DIR/ #ignoring the folder of DL weights
DATA_DIR/ # ignoring the folder of data
作弊的

作者图片
作为一个小小的提醒,有两种方法可以在 VS 代码中处理你的 git 版本:要么通过 Gitlens,要么通过你安装的终端。更多细节,请随意访问 git 的官方文档。
4.Git 项目理念
当从事一个项目时,比如说一个应用程序,最好考虑编码/分支的三个层次:
Master branch:或者主分支托管应用日常用户使用的代码版本(仅针对发布)Dev branch:用于托管应用程序计划的新开发和功能Feature branch:每次开发新功能时创建
NB :如果 dev 分支稳定了,你可以将它镜像到另一个分支上,这个分支可以被应用测试人员使用,例如在UAT phase中,以便尝试新的特性并最终报告 bug。
主要指导方针
鉴于上面描述的workflow,这里有一些重要的事情要记住:
主支行:
- 千万不要在本地主机中提交!
- 保护好总支!
开发分支:
- 永远不要在本地开发中提交!
- 保持分支开发受到保护!
特征分支:
- 即使你的工作没有完成,也要把它推到你的远程分支上!
- 在同一个分支上协作时,避免处理同一个文件或函数!
- 每次停滞前检查状态:
*git status* - 始终检查您是否有最新版本的开发代码
开发新功能
即从 dev 分支创建一个新分支:
- 检查是否在开发分支中:
git branch
- 如果是这样:
git --rebase origin/dev #Check if you are up-to-date
git checkout -b branchName
- 如果不是:
git checkout dev
git --rebase origin/dev
git checkout -b branchName
2.进行更改,添加并提交它们
3.将您的工作推送到您的远程分支机构:
git push --set-upstream origin branchName
4.确保您的分支机构在开发方面是最新的:
git checkout branchName
git pull --rebase origin/dev
解决冲突有哪些:
git add path_to_resolved_file
git commit -m "message"
git push #sends automatically to your remote branch
5.在 GitHub/Gitlab 中创建一个拉请求,并分配一个审核者
注:Rebase 是另一种让你的日志更干净的合并技术
我们可以把上面描述的git flow总结成下图:

作者图片
当进行合并时,你需要通过运行自动测试来确保应用程序运行良好,并且与之前的版本相比没有退步。这就是为什么你需要 CI/CD!
5.带有 GitLab 的 CI-CD
CI/CD 代表持续集成和持续交付/部署。这是一种技术方法,通过运行测试来检查应用程序开发过程是否自动化
- 新功能按预期工作
- 旧的没有倒退
Gitlab 提供该选项,该选项与每个项目相关联,并提供 runners 或拾取并执行 CI/CD 作业的流程。
CI/CD 渠道的开发遵循 3 个主要步骤:
- 安装和注册 GitLab 转轮
- 在本地创建一个 yml 文件,详细说明要进行的工作/测试
- 将工作推给 Gitlab
5.1.GitLab 跑步者
如前所述,运行者是用于执行预定义测试的过程。有三种:
- git lab 实例中的所有组和项目都可以使用共享的 runners 。
- 组跑步者可用于一个组中的所有项目和子组。
- 具体跑者与具体项目关联。
在本练习中,我们将深入研究一次用于一个项目的特定转轮,要手动设置特定转轮,我们首先需要安装 GitLab 转轮。为此,例如在 MacOS 上,我们可以使用 brew:
brew install gitlab-runner #Install GitLab Runner
brew services start gitlab-runner # Install GitLab Runner as a service and start it.
一旦我们安装了运行器,我们将需要通过运行以下命令将其注册到项目中:
gitlab-runner register
然后,我们需要输入以下信息:
- GitLab 实例 URL:非常常用https://gitlab.com/
- 注册令牌:在库>设置>跑步者中找到
- 跑步者描述:跑步者的简短描述
- 与跑步者相关的标签
- 执行者:许多选项需要考虑(Docker、ssh、shell……)
5.2.YML 文件
为了使用 GitLab 的 CI/CD 服务,您需要在平台上托管您的项目,并且在其根目录下有一个名为.gitlab-ci.yml的 YAML 文件,它托管 CD/CD 配置。
脚本被分组到作业中,而作业作为一个更大的管道的一部分运行。您可以将多个独立的作业分成按定义顺序运行的阶段。标签用于选择一个跑步者。
variables:
GIT_DEPTH: 1 #Shallows cloning: Last commit for each file of the project
stages:
- build
- test
#- deploy
install-dependencies: #Job 1
stage: build
tags:
- python
script:
- echo "Install dependencies"
- conda install environment.yml
linting: #Job 2
stage: test
tags:
- python
script:
- echo "check linting"
- pylint
unit-tests: #Job 3
stage: test
tags:
- python
script:
- echo "unit tests"
integration-test: #Job 4
stage: test
tags:
- python
script:
- echo "Integration tests"
在将你的文件推送到 GitLab 之前,你可以先检查它的语法,并在 CI Lint 上验证它的配置。
5.3.GitLab 上的管道
正如在 yml 文件中看到的,CI/CD 的配置由运行不同的作业组成,这些作业属于按时间顺序引用的不同阶段:构建、测试和部署。同一阶段的作业并行运行,而下一阶段的作业在前一阶段的作业成功完成后运行。在每次推送到 GitLab 时,都会执行作业,并且一旦成功计算了所有作业,就会传递合并请求。您可以通过检查 CI/CD 管道来跟踪执行过程:

作者图片
NB :如果测试不相似,可以对master和dev分支使用separate yml 文件。
结论
Git 是一个非常强大的工具,几乎在世界范围内的每一个应用程序中使用,特别是那些有多个开发团队的应用程序,因此需要掌握这项技术,以便拥有一个可持续和健壮的开发管道,从而实现更快更好的协作。
原载于 2020 年 1 月 27 日 https://www.ismailmebsout.com。
关于 PCA 的核心思想

来源:https://unsplash.com/photos/n6B49lTx7NM
目的:读完这篇文章和第二部分后,读者应该对使用主成分分析感到舒适,并能够解释这些数字的含义。
观众:第一部分不需要任何数学背景,主要是逻辑和直觉。第 2 部分将假设读者熟悉矩阵、特征值和特征向量。
目录:
- 介绍
- 主成分分析的直觉
- 简单的例子
- 摘要
介绍
什么是 PCA,你为什么关心它?
主成分分析广泛用于数据科学和机器学习。 PCA 可以减小尺寸,从而减轻重量,便于进一步加工。但是这怎么可能呢?我们会失去信息吗?答案是,我们确实会丢失一些信息,但如果我们以一种聪明的方式去做,就不会丢失很多。这个帖子是可视化和手工计算可能带来的便利。
有很多 PCA 教程。是什么让这个帖子与众不同?
网上有很多教 PCA 的资源。有些太浅,读者没有信心使用它。其中一些过于深入数学,需要读者有良好的数学背景。我个人非常喜欢数学,并且相信有一种方法可以从主成分分析中理解这些数字,而不需要通过许多数学定理。
在第一部分,我们将解释什么是 PCA,什么时候需要它,为什么需要它。我们将向您展示 PCA 非常基本的概念和直觉,以及一些简单的例子,并手动计算一些数字来给你一些味道。
在第二部分中,我们将把我们对主成分分析的直觉转化为数学,并解释来自主成分分析的数据。
主成分分析的直觉
除了旋转坐标

图 1。来源:作者手绘。
在我们解释什么是 PCA 之前,让我们看一下图 1。我们的数据就是那些绿点。它们最初用 (x,y) 坐标表示。在实际应用中, XY 对可以是体重和身高。它们可以是收入和健康,等等。只要确保它们在均值-离差表中,这意味着数据的均值在所有维度上都为零。不知何故,我们找到了一个新的正交坐标系 (PC1,PC2) 。在我们的数据中,我们可以清楚地看到数据沿着 PC1 轴传播。PC2 轴不能很好地代表数据,因为我们的大多数数据点在 PC2 轴上非常接近于零。
两个简单的问题
问:当我们使用(PC1,PC2)坐标时,我们可以去掉 PC2 轴,并且仍然能够保留大部分信息吗?是的,我们可以。移除 PC2-轴等同于将所有数据点投影到 PC1-轴上,并且在投影到 PC1-轴上之后(x,y)没有太大变化。
问:我们能从图像中看出 xy 轴对 PC1 轴的贡献有多大吗?是的,我们可以。很明显,PC1-轴在 y 轴上的投影比 x 轴上的多得多。
那么,什么是 PCA?PCA 就是在图像 1 中寻找新的坐标。更准确地说,PCA 就是旋转坐标系(参考系)以更好地表示数据。在大多数情况下,事实证明某些维度并不能很好地代表我们的数据,可以删除这些维度而不会丢失太多信息。但是,为什么我们要降低数据的维度呢?在实际应用中,我们的数据可能有数百个以上的维度。在许多情况下,从主成分分析中发现的新坐标,只有几百个维度中的几个负责 90%的数据。这是个好消息,因为数据的维度越少,计算量就越小。我们希望使用 PCA 的另一个原因是,我们可以深入了解我们的数据。它可以告诉我们原始坐标中哪几个维度支配了数据。好吧!怎么才能找到这个新坐标呢?让我们看一个例子。
简单的例子
平均偏差形式
在我们找到解决办法之前。我们需要量化数据在特定轴上的分布情况。不如给你举个例子。假设我们有 2D 数据和总共 3 个样本。我们的数据集是
(-1,1),(0,3)和(1,5)。
让我们先把数据转换成均值离差形式。我们数据的平均值是(0,3)。均值离差形式就是原始数据集减去原始数据集的均值。因此,我们的平均偏差形式的数据集为
(-1,-2),(0,0)和(1,2)。
数据如何在给定的轴上传播
现在我们测量数据集在 x 轴上的分布情况。我们简单地计算 x 分量到原点的距离的平方的平均值。我们有((-1) + (0) + (1) )/3 = 2/3。类似于 y 分量,我们有((-2) + (0) + (2) )/3 =8/3。所以数据在 x 轴上的扩散程度是 2/3。对于 y 轴是 8/3。y 轴上的扩散大于 x 轴上的扩散
如下图 2 所示,绿色、紫色和红色的点是我们的数据。很明显 y 轴更多。事实上,我们测量轴上分布的方式在统计学上被称为方差。

图 2 来源:作者手绘
方差的定义如图 3 所示

图 3 来源:https://www.onlinemathlearning.com/variance.html
为了简单起见,我们使用了总体方差。由于我们的数据是均值离差形式,所以总体的均值为零。
就现在。我们的数据集在 x 轴上的方差为 2/3,在 y 轴上的方差为 8/3。所以总方差是 10/3。请注意,无论我们选择使用什么正交坐标,总方差都应该是相同的。
寻找主轴
下一步是找到主成分轴。它被定义为在该轴上最大化数据的方差,从而与所有先前的主分量轴正交。从定义中不难得出结论:第一主成分(PC1)方差最大;第二主成分(PC2)具有第二高的方差。
下一步是找到第一主成分轴(PC1) ,它使该轴的数据方差最大化。之后,我们可以找到使数据方差最大化的第二主成分轴(PC2) ,此外,该轴与 PC1 正交。
在我们的例子中,如图 2 所示,很明显我们的数据集是 y=2x。并且 Arctan(2/1) = 63.4 度。(通常,您无法直观地找到 PC1。我们稍后会讨论如何找到这些轴。)这意味着我们的新轴应该是 x 轴逆时针旋转 63.4 度,如图 4 所示。

图 4 来源:作者手绘。
那么 PC1 轴上数据的方差是多少呢?它是从原点到 PC1 轴上的数据点的距离平方的平均值。即((-1) +(-2) + ⁰ + ⁰ + + )/3=10/3。高于 8/3 和 2/3。如果我们继续旋转轴,我们不会得到比 10/3 更高的值。为什么?因为总方差是 10/3。这也意味着单个轴可以代表 100%和 0%损失的 2D 数据。
现在,我们需要找到名为 PC2 的第二个轴。因为数据是 2D,第二个轴必须与第一个轴正交,所以只剩下一个轴。因此,我们必须考虑第二轴的最大方差。如下图所示。

图 5 来源:作者手绘。
我们的数据在 PC2 轴上的方差为 0。只是因为我们的数据集太理想了,三个点都在一条线上。在现实生活中,数据应该包含一些噪声。它应该看起来更像图 1。
因此,我们可以将坐标从(-1,–2),(0,0),(1,2)更改为(-5,0),(0,0),(5,0)。因为 PC1 代表所有方差,而 PC2 代表零方差,所以我们可以去掉 PC2。所以我们有(-5),(0),(5)。
一般找主轴。
我们的情况有点极端,因为三点都在一条直线上。在现实生活中,你的数据有噪音。这意味着不是所有的点都在一条直线上。一种不用线性代数就能找到主轴的方法是尝试所有可能的轴,然后选择方差最大的一个。但是因为即使在 2D 情况下也有无穷多个轴,所以你需要离散它们。然后你会有一个近似值。这是一种非常低效的寻找主轴的方法,尤其是在高维空间中。因此,我们需要线性代数来使它快速准确。
下降主轴
当您的数据有少量噪声时,您可能会发现总方差为 200。PC1 的方差为 180,PC2 的方差为 20。这 10%是否必要由你决定。大多数情况下,如果您的计算机能够承担进一步处理的计算,您不希望丢失信息。
摘要
PCA 就是寻找一个新的轴,使方差最大化,并与之前找到的轴正交。您还可以检查单个新轴代表数据的能力。
我没有告诉你如何用线性代数找到主轴。在我们的示例中,数据非常简单,您只能直观地看到 PC1 和 PC2。在第 2 部分中,我将向您展示如何用线性代数找到 PC1 和 PC2。它又快又准确。
敬请期待;我将很快更新第 2 部分
机器学习中的 PCA 技术
最广泛使用的降维技术的详细解释

王占山在 Unsplash 上拍摄的照片
有没有人遇到过这样的情况,在建立模型时处理大量的变量,并担心准确性和效率低下?如果是这样,主成分分析(PCA)将会来救你 ✌️
什么是主成分分析?
它是最广泛使用的降维技术之一,通过识别相关性和模式将较大的数据集转换为较小的数据集,同时保留大部分有价值的信息。
对认证后活动的需求?
它用于克服数据集中的要素冗余。此外,它还旨在获取有价值的信息,解释导致提供最佳准确性的高差异。它使得数据可视化易于处理。它降低了模型的复杂性,提高了计算效率。
在选择主成分数量的概念背后有很多混乱。在本文中,我们将浏览所有步骤,并理解确定需要为数据集选择的组件数量的逻辑。
我们将使用包含 8 个变量的披萨数据集。你可以在这里找到数据集。
下面是披萨数据集的前几条记录。“品牌”为目标变量,其余为自变量。

披萨数据集的前几条记录
删除“品牌”列,因为我们只需要对独立变量进行 PCA。

去除“品牌”变量后
让我们来看看这些步骤
👉第一步:数据标准化
在进行 PCA 之前,我们需要对数据进行标准化。
执行标准化是至关重要的一步,因为原始变量可能有不同的标度。我们需要将它们带到相似的范围,以获得合理的协方差分析。
从 sklearn 库中,我们可以使用下面的代码来标准化数据。
from sklearn.preprocessing import StandardScaler
df_std = StandardScaler().fit_transform(df)
df_std

应用标准化后的输出
👉步骤 2:用标准化数据计算协方差矩阵
协方差矩阵表示两个变量之间的相关性。这有助于我们理解哪两个变量严重依赖于彼此,并捕捉数据集中的偏差和冗余。
如果矩阵中的条目带有负号,则意味着它们彼此成间接比例。如果符号是正的,意味着它们成正比。
df_cov_matrix = np.cov(df_std.T)
df_cov_matrix

协方差矩阵的输出
👉步骤 3:计算协方差矩阵上的特征向量和特征值
这两个代数公式总是成对计算,也称为特征分解,通过压缩数据来减少维数空间。主成分分析的核心就是建立在这些值之上的。
每个特征向量将具有相应的特征值,并且所有特征值的总和表示整个数据集中的总体方差。计算特征值非常重要,因为它解释了数据集中最大方差的位置。
要了解更多关于特征向量和特征值的信息,请访问此[ 链接
eig_vals, eig_vecs = np.linalg.eig(df_cov_matrix)print(‘Eigenvectors \n%s’ %eig_vecs)
print(‘\nEigenvalues \n%s’ %eig_vals)

特征向量和特征值的输出
👉步骤 4:按降序排列特征值列表
完成特征分解后,我们需要按降序排列特征值,其中第一个值是最重要的,从而形成我们的第一个主成分。
eig_pairs = [(np.abs(eig_vals[i]), eig_vecs[:,i]) for i in range(len(eig_vals))]print(‘Eigenvalues in descending order:’)
for i in eig_pairs:
print(i[0])

排序特征值的输出
👉第五步:选择主成分数
第一个主成分将捕获原始变量的大部分方差,第二个主成分捕获第二高的方差,依此类推…
total = sum(eig_vals)
var_exp = [(i / tot)*100 for i in sorted(eig_vals, reverse=True)]
cum_var_exp = np.cumsum(var_exp)
print(“Variance captured by each component is \n”,var_exp)
print(“Cumulative variance captured as we travel with each component \n”,cum_var_exp)

每个组件捕获的差异的输出
从上面可以看出,第一个主成分(PC1)获得了总方差的 60%,其次是 PC2,方差为 32.7%。

从累积差异来看,总体上 92%是由 2 个组件捕获的,98%的差异是由前 3 个组件解释的。因此,我们可以决定数据集的主成分数为 3。
我们也可以通过下面的 scree 图用解释的方差比率的累积和来形象化同样的情况。
pca = PCA().fit(df_std)
plt.plot(np.cumsum(pca.explained_variance_ratio_))
plt.xlabel(‘No of components’)
plt.ylabel(‘Cumulative explained variance’)
plt.show()

确定组件数量的 Scree 图
👉步骤 6:创建主成分
通过上面提到的所有步骤,考虑到最大方差,我们已经确定数据集所需的组件数量为 3。
from sklearn.decomposition import PCA
pca = PCA(n_components = 3)
pcs = pca.fit_transform(df_std)
df_new = pd.DataFrame(data=pcs, columns={‘PC1’,’PC2',’PC3'})
df_new[‘target’] = df1[‘Brand’]
df_new.head()

用主成分创建的新数据集的数据框架
PCA 只能对数值变量进行。如果您有分类数据,那么您需要在应用 PCA 之前将其转换为数字特征。另外,请注意,这些主成分是原始数据集的线性组合。这些组件不像原始特征那样可读和可解释。
总结
在本文中,我们已经经历了所有的步骤,以了解如何选择数据集所需的主成分的数量。应该记住,需要极其小心地选择组件,否则可能会丢失信息。
如果您要处理数据集中的多重共线性问题,可以应用这种 PCA 技术,这将是一个很大的帮助。如果你想了解更多关于多重共线性的知识,请访问我以前的博客[ 这里
你可以从我的 Github [ 这里 ]获得数据集和完整的代码
感谢阅读,快乐学习!🙂
您需要了解的关于 Python 的所有信息
看看我们如何使用 Python 通过 API 与网络通信

照片由 Pavan Trikutam 在 Unsplash 上拍摄
用 Python 在网上聊天,听起来很恐怖,对吧?幸运的是,互联网很长一段时间以来一直处于良好的状态。我们与互联网交流的方法已经很成熟,而且出奇的简单。
我们将跳过简短的介绍,直接进入正题。本文将涵盖我们通过网络进行有效沟通所需的所有内容,包括:
- Application Program Interfaces (**APIs**)
- JavaScript Object Notation (**JSON**)
- **Requests** with Python
- Real world **use-cases**
应用程序接口
应用编程接口就像一个魔术盒。我们以指定的格式发送数据。然后,我们以指定的格式获取数据。
这个神奇的盒子只是保存在服务器上的一个脚本。它就像一个看门人——我们告诉看门人我们想知道、更改或删除一些东西,看门人会(希望)执行我们要求的动作,并告诉我们进展如何。
幸运的是,API 通常都有很好的文档记录,并且遵循相同的使用模式。绝大多数的 Web APIs 使用代表性的状态转移(REST)结构——这听起来比实际情况复杂得多。
休息
RESTful API 体系结构应用了六个关键约束:
-
所有请求都通过 单个外向接口 处理。
-
客户机-服务器独立性——一方的开发和功能变化不应该影响另一方(客户机指我们,服务器指 API)。
-
无国籍状态——服务器不保留我们会话的任何信息;每个请求都被视为新的。
-
使用 分层系统——意味着 API 由层组成,其中每一层都连接到另一层,从而创建模块化结构。****
-
如果适用,API 应该能够根据请求 为用户提供可执行的 代码。
所有这些对我们来说意味着,我们将与单个位置进行通信,并期待特定的行为——这将使用一组 HTTP 方法进一步标准化。
方法
当与 API 通信时,我们倾向于使用四种方法:
- GET —用于从 API 中检索信息。
- POST —创建新资源(例如,GitHub repo)。
- 上传 —更新现有资源。
- 删除 —删除现有资源。
其中最常用的是 GET 协议。在大多数情况下,对于数据,我们更感兴趣的是下载它。
如果我们想使用 Google Maps API 获取一个地址的经度和纬度坐标,我们会发送一个 get 请求——因为我们实际上是从 API 获取 T21 数据。
修改信息时会用到发布、上传、删除。以 GitHub repo 为例,我们可以用 POST 创建它,用 PUT 更新它,用 DELETE 删除它。****
您可能还会看到补丁——这用于部分更新,类似于 PUT。我以前没用过这个,看起来不太常见但值得了解。
HTTP 代码
当使用 GET、POST、PUT 和 DELETE 时,我们通常会收到以下代码之一:
****2xx - Success Codes
200 OK** - success (most common with **GET**)
**201 Created** - request fulfilled and new resource created (**POST**/**PUT**)
**204 No Content** - success but no content is returned in response**4xx - Client Error Codes
400 Bad Request** - request could not be understood due to bad syntax
**401 Unauthorized** - most likely we missed the auth key
**403 Forbidden** - we're trying to go places we're not allowed
**404 Not Found** - what we're trying to access doesn't exist**Honorable Mentions**
**418 I'm a teapot** - stop asking a teapot to brew coffee
**420 Enhance Your Calm** - sending to many requests to Twitter**
记下最后两个——它们非常重要,永远不要忘记它们。
JavaScript 对象符号
当与 API 通信时,我们需要一个发送和接收数据的标准化模板,这样 API 和我们都可以正确地处理数据。这种格式是 JavaScript 对象符号(JSON)。
JSON 实现了与 Python 字典中相同的键值对层次结构。
点击此处将使用我们的浏览器向 Pokemon API(所有东西都有 API)发送请求,然后加载来自 API 的 JSON 响应:

来自口袋妖怪 API 的 JSON 响应
在 Python 中,我们使用字典和json库来构建 JSON 字符串以包含在请求中,通常如下所示:
**request = {'name': 'John',
'age': 21}
json_obj = **json.dumps(**request**)**
requests.post('https://api.com', data=json_obj)**
Python 中的请求
好了,我们知道它是怎么工作的了。但是我们怎么做这些事情呢?
我们使用requests——一个非常容易使用的库。例如,如果我们需要发送一个 GET 请求,我们只需编写:
**import requests
data = **requests.get(**http**)****
http是 API 的网址,包括指定我们想要的信息的参数。
让我们以神奇宝贝 API 为例——它使用起来非常简单。
该 API 包括一种方法,用于查找每个新一代中添加的所有口袋妖怪——我特别记得有 151 个口袋妖怪,现在有多于896 个。所以让我们看看他们用第二代增加了多少。
1.调用 API
首先,我们简单地使用 GET 请求来请求数据,指定我们对**generation** 数据感兴趣,特别是**generation-ii**:
**API_CALL = "https://pokeapi.co/api/v2/**generation/generation-ii**"
requests.**get**(API_CALL)**
**[Out]:** <Response [200]>
好的,<Response [200]>是什么意思?嗯,这是 HTTP 200 OK状态码。意味着我们的请求成功了!但是我们想要的数据在哪里呢?
2.提取数据
我们返回的是一个requests.Response Object——它包含许多有用的方法,我们想要检索实际 JSON 响应的方法是:
**RES = requests.**get**(API_CALL)
RES**.json() # returns a dictionary****

来自 Pokemon API 的 JSON 响应—显示所有第二代相关数据。
现在,我们有一个非常详细的响应,包含了第二代中添加的所有内容。为了统计新口袋妖怪的数量,我们访问了pokemon_species列表:
**DATA = RES.json()
DATA[**'pokemon_species'**]**

来自口袋妖怪 API 的 JSON 响应—显示所有第二代口袋妖怪物种
最后,我们可以键入len(DATA['pokemon_species'])来查找新口袋妖怪的数量(它是 100 )。
现在我们可以找到我们需要知道的关于口袋妖怪的一切。这很好,但可能没那么有用。
真实世界的使用案例
让我们使用真正的 API 和用例来编写一些更相关的代码。
使用 Google Maps API 可视化地址
我写的第一个代码很大程度上依赖于谷歌地图地理编码 API。现在看着它让我感到恶心——所以我们要重写它。
我们的目标是在地图上绘制一个地址目录。为此,我们需要它们的相对 x-y 坐标(对于 Matplotlib 来说),这就需要我们找到它们的经纬度坐标。
我目前住在罗马——所以我整理了一份这里著名地标的小清单;我们将在示例中使用这些数据——所以请随意下载并跟随。
授权
首先,我们需要一个授权密钥来使用 Google Maps 地理编码 API ( ~每月 40,000 次请求是免费的)。大多数 API 总是需要我们在调用中包含一个授权密钥;否则,我们的请求将被拒绝:

我们在没有授权密钥的情况下尝试访问 API 时的反应,单击此处尝试相同的。
地理编码 API 文档包含获取 API 密钥的说明。
API 参数
如果我们想找到罗马斗兽场的坐标,我们从 HTTP 地址内部将街道地址传递给 API。
API 需要两个变量,address和key。我们在[http://maps.googleapis.com/maps/api/geocode](http://maps.googleapis.com/maps/api/geocode.) 访问地理定位 API。
**API = "http://maps.googleapis.com/maps/api/geocode"
ADDR = "piazza+del+colosseo,+1,+rome"
KEY = "API_KEY" # replace this with the API key from Googlerequests.get(f"{API}/json?address={ADDR}&key={KEY}")**
此代码将发送一个 GET 请求到:
**[http://maps.googleapis.com/maps/api/geocode/json?address=piazza+del+colosseo,+1,+rome&key=**AUTH_KEY**](http://maps.googleapis.com/maps/api/geocode/json?address=piazza+del+colosseo,+1,+rome&key=AUTH_KEY)**
如果您用**AUTH_KEY**在浏览器中输入这个,我们将看到来自 API 的 JSON 响应:

当请求罗马斗兽场的位置数据时,来自 Google maps 的 JSON 响应。
请求数据
我们可以通过遍历列表并为每一项发送 GET 请求来找到地址列表中每一项的坐标:
结果
在收到我们的响应RES后,我们使用json方法将其转换成 Python 字典,允许我们访问纬度LAT和经度LONG的值。我们将坐标添加到COORDS列表中——现在可以用来在地图上绘制位置。

该数据与我们新的 lat 和 long coordinate 列一致。
我们不会涉及绘图代码,但如果这是你想做的事情,我会建议使用 Matplotlib 的底图扩展 —尽管现在可能有更好的工具可用(我很久以前就这样做了)。
与 GitHub 交互
我们也可以使用 API 与 GitHub 交互。简单来说,我们将使用 POST 请求创建一个名为api_test的新 repo。
授权
首先,和往常一样,我们需要一个授权令牌。幸运的是,我们可以比使用 Google Maps API 更快地完成这个设置——你可以在这里找到一个分步指南。
请注意,在第七步中,选择哪些权限完全由您决定——但是我们需要的只是repo:

我们只需要回购许可。我避免勾选delete _ repo——这似乎是个坏主意
现在,我们可以通过在请求中添加headers={'Authorization': f'token {TOKEN}'}来验证自己。
创建一个回购
要创建 repo,我们只需向[https://api.github.com/](https://api.github.com/) user/repos发送 POST 请求。这里唯一需要的字段是name值,它指定了新的回购协议名称。我们还将public设置为true,这只是将回购隐私设置设置为 public——而不是 private(默认设置)。
注意,我们使用PAYLOAD来包含我们对 API 的指令,我们将这些指令传递给requests.post中的data参数。我们还使用headers参数包含了我们的授权密钥/令牌。
结果
如果我们成功创建了 repo,我们将收到代码**201 Created**——表明请求已经成功,我们已经创建了一个新的资源。

我们也可以在 GitHub 上查看,果然api_test回购就在那里:

GitHub API 非常酷,我们可以用它做很多事情,正因为如此,它非常适合学习——如果你想了解更多,我建议你看一下文档(也可以随时问我问题!).
最终注释
这就是开始使用 Python 中的 API 所需要知道的一切。当然,还有更多更相关的用例。
对我自己来说,我现在几乎只在公司环境中使用 APIs 主要用于数据传输和操作,以及模型设置和培训。
从互联网上获取数据也是一项经常性的任务,因此,这是一项非常重要的技能。理解并实践 API 是非常有用的。
希望这篇文章有用。如果你有任何问题或建议,请告诉我,随时通过 Twitter 或在下面的评论中联系我。
感谢阅读!
有兴趣学习更多关于数据和 web 开发的知识吗?试试我最近写的这篇关于使用 Angular 部署 Python 构建的 TensorFlow 模型的文章:
**** [## 如何使用 Angular 部署 TensorFlow Web 应用程序
在角度构建的 web 应用程序中使用 Python 构建的模型
towardsdatascience.com](/how-to-use-angular-to-deploy-tensorflow-web-apps-5675b5a042cc)****
在技术面试中你应该知道的关于操作系统的一切
意见
处理技术访谈中常见操作系统问题的完整指南

马库斯·斯皮斯克在 Unsplash 上的照片
“你现在准备好面试了吗?”
“是的,当然。”
“太好了。可以请你说说你对操作系统的理解吗?”
“嗯……嗯……”
“好的,谢谢你今天抽出时间。请在未来几天等待我们的进一步通知。”
你觉得这类似吗?
不要放弃。你肯定能做得更好。
以下是一些你在技术面试中会遇到的常见操作系统问题。你可以按照这个指南从零开始学习操作系统,并清楚地向你的面试官解释。
1.什么是操作系统?
操作系统的定义可以分为三个部分:
- 操作系统为用户提供了与计算机硬件交互的接口。
- 操作系统(OS)是管理计算机硬件和软件资源的程序。
- 操作系统由内核和其他一些基本组件构成。一般来说,内核是应用程序和硬件之间的桥梁。它负责管理进程、内存、文件和网络等东西,直接访问硬件,维护系统的稳定性和性能。

操作系统架构。作者图片
2.用户如何访问计算机资源?
计算机操作可分为两种模式:
- 用户模式:该级别下的流程只能访问用户提供的数据。
- 内核模式:该级别下的进程对计算机硬件有完全的访问权,可以执行机器的一些特殊操作(如 I/O)。
典型的应用程序通常运行在用户模式下。当内核模式下有服务需求时,应该发出系统调用。它是一个请求,要求内核进程执行设备管理、文件管理、进程管理和内存管理等功能。

用户和内核模式的范围(图片由作者提供)
3.进程和线程的区别是什么?
简而言之,进程是一个活动的程序。它可以在执行时生成多个线程。进程通常是相互独立的,但是线程不是必需的。进程会导致更多的开销,但也更便于管理,而线程正好相反。
以 JVM 进程为例,里面的线程是共享堆空间和方法区(metaspace)等全局变量的,但是程序计数器寄存器、JVM 栈、native 方法栈是私有的。

JVM 进程结构(图片由作者提供)
4.流程的状态是什么?
该过程有 7 个状态,分别是:
- 新建:流程正在创建。
- 就绪:进程准备运行,即等待来自处理器的资源(如时间片)。
- 运行:该进程当前正在 CPU 下运行。一次只允许一个进程。
- 等待(或阻塞):流程暂停,等待所需资源可用。
- 完成(或终止):流程执行完毕。它可能因某些原因或正常退出而中断。
- 暂停就绪:就绪队列已满,进程暂停。
- 暂停块:等待队列已满,进程暂停。

流程生命周期(作者图片)
5.什么是上下文切换?什么时候会发生?
上下文切换意味着保存正在运行的进程状态并加载另一个进程的状态。这通常发生在高优先级进程进入就绪状态或发生中断时。
6.什么是竞争条件?
当多个进程共享相同的代码或资源时,就会发生争用情况。在这种情况下,可能会出现意外的结果,因为每个进程都可以随时访问共享变量。
7.进程之间是如何通信的?
进程间通信(IPC)有六种方式:
- Pipe :使一个流程的输出成为与有共同原点的另一个流程的输入,即同一个流程。使用管道的数据流是单向的(例如,Linux 中的“|”命令)。
- 命名管道:这允许来自不同来源的进程的通信。它遵循先进先出(FIFO)规则。
- 消息排队:这两种管道都是低效的,因为将数据发送到缓冲区的进程需要等待,直到另一个进程取回数据。消息队列能够解决这个问题,生产者不需要等待消费者检索数据。
- 共享内存:消息排队还有一个缺点,就是发送数据的规模太大的时候比较耗时。因此出现了共享内存的想法。它允许多个进程访问同一个内存区域。这是最有效的方法,因为每个进程都可以立即看到数据的更新。
- 信号量:共享内存最大的问题是多个进程会争夺资源。信号量是在进程同步中使用的程序计数器,用于控制访问共享内存的进程数量并避免竞争情况。它表示共享内存中有多少可用资源。
- 插座:上面提到的所有通信方式都只基于一个设备。套接字是允许多个设备之间远程通信的接口。它主要用于客户/服务器通信。
8.线程之间是如何同步的?
线程同步的目的类似于进程间通信,避免并发线程之间竞争共享资源。有三种常见的线程同步方式:
- 互斥:是一种互斥的机制。互斥一次只允许一个线程访问共享资源(如 Java 中的
synchronized)。 - 信号量(Semaphore):它与互斥量非常相似,但是它的值可以大于 1,并且允许多个线程同时进入共享资源。
- 事件:通过通知(wait/notify)保持线程同步。
9.CPU 如何调度进程?
为了实现最大的 CPU 利用率,有几种 CPU 调度算法:
- 先来先服务(FCFS) :将资源分配给就绪队列中首先请求 CPU 的进程。它是一种非抢占式算法(计划的进程将一直运行,直到完成或被阻塞)。
- 最短作业优先(SJF) :将资源分配给就绪队列中执行时间最短的进程。它是一种非抢占式算法。此外,还有一个最长作业优先(LJF)调度算法。
- 最短剩余时间优先(SRTF) :将资源分配给就绪队列中剩余执行时间最短的进程。它是一种抢占式算法(当一个更高优先级的进程进入时,被调度的进程可以被抢占)。还有一种最长剩余时间优先(LRTF)调度算法。
- Round Robin :每个进程被分配给一个给定的时间,称为时间片,执行到时间用完为止。
- 基于优先级的:每个进程被赋予一个给定的优先级。优先级越高,越早被选中。
- 多级队列:流程按照优先级被分配到不同的队列中。低级队列中的进程被允许执行,直到高级队列中的进程完成。
- 多级队列反馈:这是 UNIX 系统中使用的调度算法,允许进程在各级队列之间移动。如果该进程花费太多的执行时间,它将被移到较低级别的队列中。
10.操作系统中的内存模型是如何设计的?
操作系统中有两种类型的内存:
- 主存储器(内部存储器) : CPU 寄存器、高速缓冲存储器和主存储器,可由处理器直接访问。
- 二级存储器(外部存储器):不同类型的磁盘(磁盘、光盘),是处理器可以通过 I/O 访问的一些存储设备。

操作系统内存模型(图片由作者提供)
11.操作系统中的内存管理是如何工作的?
操作系统的内存管理负责为进程分配内存,包括将逻辑地址转换为物理地址或在内部和外部内存之间交换进程。
12.什么是虚拟地址和物理地址?
举个常见的例子,我们在一些编程语言中看到的指针概念,存储的是内存的虚拟地址,这个地址是由操作系统决定的。物理地址是物理存储器中的地址,即存储器地址寄存器。

虚拟地址(图片由作者提供)
现代处理器使用虚拟寻址技术,通过 MMU(内存管理单元)将虚拟地址转换成物理地址。虚拟寻址的过程如下图所示:
13.操作系统如何分配内存?
有四种常见的内存分配技术:
- 分区分配:按块划分内存,每个块包含一个进程。如果进程只需要很小的内存来运行,空间就会被浪费。这是一种连续分配,因为这些块在内存中是连续的。
- 分页内存管理:按页帧划分内存,页帧是比块小的单位。这增加了内存的使用并减少了内部碎片。这是一种不连续的分配,因为页面框架可以分开。分页表用于将虚拟地址映射到物理地址。
- 分段内存管理:按段划分内存,段是数据或代码的逻辑组。它是不连续的分配,因为允许将数据段分开。段表用于将虚拟地址映射到物理地址。
- 带分页的分段:结合了分页和分段内存管理的优点。它将内存分成几个段,然后将每个段分成几个页帧。
14.什么是 TLB(翻译后备缓冲器)?
在分页内存管理中,有两个问题需要处理:
- 虚拟到物理的映射应该很快。
- 当虚拟地址空间很大时,页表会变得更大。
TLB 可以用来加速虚拟内存和物理内存之间的转换。它可以被看作是一个缓存,在一个页表中存储一部分数据。有了这个缓存,我们在执行 I/O 时只需要访问主内存一次,而不是两次。
将虚拟地址转换成物理地址的过程是:
- 搜索 TLB 内部的页码。
- 如果找到给定的页面,从 TLB 中读取相应的物理地址。
- 如果找不到给定的页,则读取页表中相应的物理地址,并将其存储到 TLB 中。
- 当页面满了的时候,通过一定的策略来消除 TLB 内部的页面。
15.什么是多级页表?
除了加速映射,我们还可以使用多级页表来处理由大的虚拟地址空间引起的问题。它避免了总是将所有的页表放在主存中,这样可以节省更多的空间。
16.什么是虚拟内存?
当一个软件的内存成本超过计算机的空间时,这是很常见的。之所以能实现这个,是因为虚拟内存。它将一个程序分成几个部分,并允许在程序需要之前将它们临时存储在外部存储器(磁盘)中。通过这样做,程序将认为自己拥有一片连续的空间。
17.如何实现虚拟内存?
虚拟内存实现有两种常见类型:
- 按需分页:基于分页技术,具有页面替换功能。如果我们在进程开始前找不到所需的页面,操作系统将在辅助内存中搜索它,并根据给定的页面替换算法交换在主内存中找到的页面。
- 需求细分:这是一种类似于需求分页的技术。它们之间唯一的区别是,根据给定的段替换算法,按需分段将段而不是页面交换到主存中。
18.页面替换算法是什么?
当所需页面不在主存储器中时,发生页面错误。我们需要页面替换算法将页面从辅助内存交换到主内存中。下面列出了一些常见类型的页面替换算法:
- 最佳页面替换:替换不再使用或最长时间不使用的页面。这将确保页面错误存在的最低可能性。然而,由于人们无法预测哪个页面在将来不会被再次使用,因此无法实现 OPT 替换。
- FIFO(先进先出)页面替换:清除在主存中停留时间最长的页面。
- LRU(最近最少使用)页面替换:清除自上次访问以来耗时最长的页面。
- LFU(最少使用的)页面替换:清除一段时间内最少使用的页面。
19.什么是操作系统中的死锁?
死锁是指两个以上的进程都在等待彼此持有的资源,但是没有一个进程会先释放资源。
如果系统满足以下所有条件,则会出现死锁:
- 互斥:一次只允许一个进程访问。
- Hold & wait :一个进程正在持有一个其他人可能需要的资源,同时也在等待其他人持有的资源。
- 无抢占:一个资源不能被其他进程访问,除非拥有者进程释放它。
- 循环等待:每个进程都在等待另一个进程持有的资源。

死锁示例(作者图片)
20.如何处理死锁?
有三种方法可以处理死锁:
- 死锁预防和避免:死锁是不允许的,应该被预防或避免。
死锁预防是为了消除上面提到的死锁条件中的一个,因为当其中四个条件都满足时,就会发生死锁。
死锁避免是一种测试进程发送的每个请求是否会导致死锁状态的技术。 - 死锁检测和恢复:允许死锁。一旦检测到死锁,就抢占进程。
- 忽略问题:当死锁很少发生时,只需重新启动系统。
参考
- 现代操作系统(第四版)
- snail climb/Java guide—GitHub
- 操作系统介绍
- 操作系统中的微内核
- 内核(操作系统)
- 操作系统—维基百科
- 流程管理简介
- 进程同步介绍
- 进程间通信的方法
- 操作系统中的 CPU 调度
- 操作系统调度算法
- 操作系统分页
- 操作系统需求分页
- 什么是需求细分?
- 操作系统死锁介绍
通过学习操作系统,你会发现这个领域涉及到如此多的计算机科学概念,因此深入研究其中的每一个主题都是非常值得和重要的。希望你觉得有用,祝你下次面试好运!
关于深度学习你想知道的

2020 年夏季学期总结。路易斯·罗查在 Unsplash 上的照片
FAU 深度学习讲义
在综合视频和博客文章中
电晕对我们许多人来说是一个巨大的挑战,并以各种方式影响着我们的生活。几年来,我一直在德国弗里德里希-亚历山大-纽伦堡大学教授深度学习课程。今年夏天,我们大学决定完全“虚拟化”。因此,我开始用 15 分钟的短片记录我的演讲。

深度学习地标检测也在 X 射线投影中发挥作用。图片由 Bastian Bier 提供。
对于“深度学习”这样的课题,你每学期都要更新一次讲座的内容。因此,我至今无法提供课堂讲稿。然而,有了录像和自动语音识别的帮助,我能够转录整个讲座。这就是为什么我决定在媒体上为每一个视频发布一个相应的,手动更正的抄本。我很高兴“走向数据科学”在他们尊敬的出版物上发表了所有这些。他们甚至要求我创建一个专栏“ FAU 讲座笔记”。所以,我想借此机会感谢数据科学对这个项目的大力支持!

阿尔法星打塞拉勒。完整视频可以在这里找到。使用 gifify 生成的图像。
为了简化博客文章的创建,我创建了一个小工具链“ autoblog ”,并且免费提供。除非另有说明,这里的所有内容都是在 CC BY 4.0 下发布的。所以,你也可以自由地重用这些内容。
在下文中,我列出了按章节分组的个人帖子,并附有相应视频的链接。如果你喜欢视频,你也可以通过播放列表观看整个讲座。注意我这学期升级了两次录音设备。从第 7 章——架构和第 9 章——可视化&注意,您应该看到视频质量有所提高。
所以,希望你觉得这些帖子和视频有用。如果你喜欢,请留下评论,或者把这个项目推荐给你的朋友。
第 1 章—简介

显示 Yolo 能力的示例序列。完整的序列可以在这里找到。使用 gifify 生成的图像。
在这些视频中,我们介绍了深度学习的主题,并展示了一些文献和应用方面的亮点
第一部分:动机&高调应用 ( 视频 )
第二部分:FAU 集锦 ( 视频 )
第三部分:深度学习的局限性及未来方向 ( 视频 )
第四部分:模式识别短期课程 ( 视频 )
第五部分:【T20
第 2 章—前馈网络

经典特征提取。 CC 下的图片来自深度学习讲座的 4.0 。
在这里,我们介绍模式识别的基础,简单的前馈网络包括层抽象的概念。
第 1 部分:我们为什么需要深度学习? ( 视频 )
第二部分:网络究竟该如何训练? ( 视频 )
第三部分:反向传播算法 ( 视频 )
第四部分:图层抽象 ( 视频)
第 3 章—损失和优化

只需几个步骤,我们就可以转换高斯分布的对数似然。下图 CC BY 4.0 来自深度学习讲座。
损失函数的一些背景知识以及深度学习与支持向量机(SVM)等经典方法的关系。
第一部分:分类回归损失 ( 视频 )
第二部分:支持向量机打败深度学习了吗? ( 视频 )
第三部分:优化与亚当和超越… ( 视频)
第 4 章—激活、卷积和池化

使用多通道卷积的正向传递。 CC 下的图片来自深度学习讲座的 4.0 。
在这一章中,我们讨论经典的激活函数,现代版本,卷积层的概念以及池机制。
第一部分:经典激活 ( 视频 )
第二部分:现代激活 ( 视频 )
第三部分:卷积层 ( 视频 )
第四部分:池机制 ( 视频
第 5 章——正规化

将函数拟合到数据可能会导致过度拟合或拟合不足。 CC 下的图片来自深度学习讲座的 4.0 。
本章探讨了过拟合问题,并讨论了避免过拟合的几种常用方法。
第一部分:偏差-方差权衡 ( 视频 )
第二部分:古典技法 ( 视频 )
第三部分:归一化&辍学 ( 视频 )
第四部分:初始化&迁移学习 ( 视频 )
第五部分:多
第 6 章—常见做法

只有在我们设置了关于培训过程的所有其他重要选项之后,才会查看测试数据。 CC 下的图片来自深度学习讲座的 4.0 。
本章致力于你在实践中会遇到的常见问题,从超参数到性能评估和显著性测试。
第一部分:优化器&学习率 ( 视频 )
第二部分:超参数和集合 ( 视频 )
第三部分:班级失衡 ( 视频 )
第四部分:绩效评估 ( 视频)
第 7 章—架构

在这一章中可以看到很多很多的架构!下图 CC BY 4.0 来自深度学习讲座。
在这一章中,我们介绍了深度学习中最常见和最流行的架构。
第一部分:从 LeNet 到 GoogLeNet ( 视频 )
第二部分:更深层次的架构 ( 视频 )
第三部分:残余人脉 ( 视频 )
第四部分:残余人脉的崛起 ( 视频 )
第五部分:学习架构(
第 8 章——递归神经网络

作家一代可以创作手写文字。更多的细节可以在文森特的博客中找到。 CC 下的图片来自深度学习讲座的 4.0 。
递归神经网络允许处理和生成依赖于时间的数据。
第一部:艾尔曼细胞 ( 视频 )
第二部:穿越时间反向传播 ( 视频 )
第三部:致敬施密德胡伯— LSTMs ( 视频 )
第四部:门控循环单元 ( 视频 )
第五部:
第 9 章——视觉化和注意力

同样的说话者,用麦克风 1(蓝色)和麦克风 2(绿色)录音,这造成了我们想要抑制的混淆。 CC 下的图片来自深度学习讲座的 4.0 。
可视化方法用于探索深层网络的弱点,并提供理解它们的更好方法。
第一部分:架构&训练可视化 ( 视频 )
第二部分:混杂因素&对抗性攻击 ( 视频 )
第三部分:直接可视化方法 ( 视频 )
第四部分:基于梯度和优化的方法 ( 视频 )
第五部分:
第 10 章—强化学习

基于智能体的器官分割。图片由夏忠提供。
强化学习允许训练能够独立行动并控制游戏和过程的代理系统。
第一部分:序贯决策 ( 视频 )
第二部分:马尔可夫决策过程 ( 视频 )
第三部分:策略迭代 ( 视频 )
第四部分:备选方法 ( 视频 )
第五部分:深度 Q 学习 ( 视频
第 11 章——无监督学习

呼吸和心脏运动使得心脏可以被模拟。 CC 下的图片来自深度学习讲座的 4.0 。
无监督学习不需要训练数据,可以用来生成新的观察值。
第一部分:动机&受限玻尔兹曼机器 ( 视频 )
第二部分:自动编码器 ( 视频 )
第三部分:生成对抗网络——基础知识 ( 视频 )
第四部分:条件&循环甘斯 ( 视频 )
第五部分
第 12 章—分割和对象检测

在组织切片图像上检测有丝分裂是一项经典的检测任务。图片由 Marc Aubreville 提供。点击查看完整视频。
分割和检测是使用深度学习的常见问题。
第一部分:分割基础知识 ( 视频 )
第二部分:跳过连接&更多 ( 视频 )
第三部分:一族区域 CNN(视频 )
第四部分:单镜头检测器 ( 视频 )
第五部分:实例分割
第 13 章——弱自我监督学习

监管不力试图充分利用你的标签。 CC 下的图片来自深度学习讲座的 4.0 。
弱监督试图最小化所需的标签努力,而自我监督试图完全摆脱标签。
第一部分:从类到像素 ( 视频 )
第二部分:从二维到三维标注 ( 视频 )
第三部分:自监督标签 ( 视频 )
第四部分:对比损失 ( 视频)
第 14 章—图形深度学习

欢迎来到图形深度学习的世界。下图 CC BY 4.0 来自深度学习讲座。
图形深度学习用于处理图形和网格中可用的数据。
第一部分:光谱卷积 ( 视频 )
第二部分:从光谱到空间域 ( 视频)
第 15 章—已知操作员学习

什么是已知算子学习?来源;推特。图像在下 CC 乘 4.0
已知算子允许将先验知识插入到深度网络中,从而减少未知参数的数量并提高深度网络的泛化性能。
第一部分:不要重新发明轮子 ( 视频 )
第二部分:学习上的界限 ( 视频 )
第三部分: CT 重建重温 ( 视频 )
第四部分:深度设计模式 ( 视频)
承认
非常感谢 Katharina Breininger、Fu、Tobias Würfl、Vincent Christlein、Florian Thamm、Felix Denzinger、Florin Ghesu、、Yixing Huang Christopher Syben、Marc Aubreville 以及我们所有的学生导师在本学期和上个学期给予我们的支持,他们制作了这些幻灯片和相应的练习,在现场和虚拟环境中教授课程,以及在过去几年中伟大的团队工作!
如果你不是 Medium 的订阅者,并且在访问这些材料时有困难,我们还会在模式识别实验室的网站上发布所有的博客文章。
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中获得文字记录,试试自动博客。
几乎你需要知道的关于决策树的一切(带代码)
以你想不到的方式理解决策树的指南!

托德·夸肯布什在 Unsplash 上的照片
介绍
你一生中没有一天不做任何决定。从你早餐吃什么到你感兴趣的职业,你的生活被决定所包围。假设你想出去玩板球。出门前你会寻找哪些因素?今天会下雨吗?外面会不会太热?作为一名资深玩家,你被要求接最后的电话。你从气象部门网站上查了过去几天的数据。将这些数据与今天的天气状况进行了比较,并预测天气状况非常适合进行板球比赛。瞧啊。你只是在不知道的情况下用决策树解决了问题。
在使用决策树的实际功能之前,您需要精通以下术语
- 基尼杂质
- 熵
基尼杂质与熵
两个朋友乔和萨姆开始觉得无聊了。所以他们决定玩一个游戏。找到最能把下面的点分成蓝色和橙色的线的人赢得游戏。唯一的限制是这条线必须平行于任何轴。

图 1
两人都尝试了很多,想出了下面的台词。

图 2
仅仅通过视觉化的要点,很容易说乔的尝试比山姆好。然而,当我们有两种以上的颜色时,事情会变得疯狂。人们需要一个量化值来判断分裂。这就是基尼系数不纯的原因。它谈到了错误分类点的概率。
没拿到?
让我们看看拆分前的条件,即图 1。错误分类一个点的概率有多大?
我们可能有两种方法来错误地对一个点进行分类。首先,我们选择一个蓝点,将其归类为橙色。第二,我们选择一个橙色的点,将其归类为蓝色。

图 3
和

图 4
总概率= 0.25+0.25 =0.5(开始时的基尼杂质)
任何数据分割都会将该区域分成两个或多个部分。通过对所有部分进行加权求和,计算出最终的基尼系数。基尼系数越小,分割越好。
我们来分析一下乔的企图-

图 5
同样,我们也可以分析山姆的企图-

图 6
这两种尝试都显著降低了原始基尼系数的不纯度,但是,Joe 进行了更好的分割,因为他的分割得到了更大的基尼系数增益。
设 y 是一个随机变量,取值为{y₁,y₂,y₃,….,yₖ}那么计算基尼系数的一个简单方法是

图 7
基尼杂质的性质
设 y 取值 y₊,y₋(两个班)
案例一:
当 100%的数据点属于 y₊。在这种情况下,该系统的基尼系数为

图 8
案例二:
当 50%的数据点属于 y₊时。在这种情况下,该系统的基尼系数为

图 9
案例三:
当 0%的数据点属于 y₊时。在这种情况下,该系统的基尼系数为

图 10
基尼系数与 y₊的关系曲线如下:

图 11
受够了这种基尼不纯。先说一会熵。
熵,简单来说就是数据中的随机性。想象你面前有两个盒子。盒子 1 大部分是蓝色的球,而盒子 2 是不同颜色的球。

图 12
现在从每个盒子里抽出一个球。你认为从盒子 1 中抽出的球最有可能是什么颜色?蓝色,对吗?你能预测从盒子 2 中抽出的球的情况吗?我想不会。原因是盒子 2 与盒子 1 不同,具有很大的随机性。恭喜你,你已经知道熵意味着什么了!如果你选择熵作为度量,决策树会以这样一种方式分割数据,即在每次分割时,数据的随机性不断降低。
设 y 是一个随机变量,取值为{y₁,y₂,y₃,….,yₖ}接着计算出系统的熵为:

图 13
熵的性质
设 y 取值 y₊,y₋(两个班)
案例一:
99%的数据点属于 y₊。在这种情况下,系统的熵将是:-

图 14
案例二:
当 50%的数据点属于 y₊时。在这种情况下,系统的熵将是:-

图 15
案例三:
当 1%的数据点属于 y₊时。在这种情况下,系统的熵将是:-

图 16
从 H(y) w.r.t .到 y₊的曲线将会是:

图 17
必须注意的是,当所有值出现的概率相等时,熵最大= 1。
到目前为止一切顺利。但是如何用熵来分割数据呢?
类似于基尼增益,我们使用信息增益(I.G ),来决定分割的最佳特征。
它被定义为:-

图 18

图 19:显示基尼系数和熵随 y+变化的图表
为什么基尼不纯超过熵?
熵涉及对数计算,而基尼系数涉及计算开销较小的平方计算,这就是 S klearn 库使用基尼系数作为默认选择标准来构建决策树的原因。
但是,观察到它们之间的差异很小,可以使用这两个指标中的任何一个。
构建决策树的步骤
- 决定分解/分割数据的特征:计算每个特征的信息增益,选择最大的一个。
- 继续拆分数据
- 停止拆分数据,如果:-
a)我们得到纯节点,即仅包含正或负数据点的节点,或者
b)我们在一个节点上得到很少的点,或者
c)我们到达树的一定深度
一旦您构建了一个决策树,对于一个查询点,从根到适当的叶节点遍历树。如果叶节点是纯的,预测查询点对应的类标签,否则执行多数投票。
分裂分类特征
假设我们的数据集是:

图 20
有两个特点。如果有一个特征,我们会简单地选择它。然而,当我们有一个以上的特征时,我们需要查看在分割后提供最大信息增益的特征。
从特写 F₁:开始

图 21
信息增益将是:

图 22
现在检查功能 F₂:

图 23
而信息增益(IG)₂会是:

图 24
由于 IG₂ > IG₁,我们将首先使用 F₂.要素分割数据请注意,F₂=IND 之后的节点可以使用特征 F₁.进一步分解最终的树看起来会像-

图 25
直觉
让我们使用简单的 if-else 条件重写上面的决策树:

图 26
我的朋友,这就是你的决策树。
从程序上讲,决策树只不过是一系列 if-else 条件语句。
从几何学上讲,它是一组轴平行的超平面。
分割数字特征
假设我们的数据集是:

图 27
- 按 F₁值排序
- 如果我们用 F₁分割每个值

图 28
您可以看到,我们在每个节点中只获得一个值,这导致了数据的过度拟合。
我们处理这个问题的方法是定义一个阈值,然后将数据分成两部分——一部分的值小于或等于阈值,另一部分的值大于阈值。
门槛如何确定?

图 29
我们检查每个可能阈值的信息增益,并选择使其最大化的值。这里,如果我们使用 F₁=4.2 分割数据,信息增益将最大。
有许多类别的范畴特征
我们已经看到了如何处理分类和数字特征。然而,当一个分类特征有许多类别时,事情会变得疯狂。
假设我们有一个 pin 码功能。它可能有 1000 个 pin 码,当我们使用此功能拆分数据时,它将创建 1000 个子节点,每个节点只有很少的数据点,这将导致过度拟合。
一种方法是将分类特征转换成数字特征。
代替 pin 码,我们可以有一个新功能,例如:

图 30
所以,现在如果我们使用这个新特性来分割数据,子节点将有足够的点来避免过度拟合。
过度拟合和欠拟合
当决策树的深度越大,底部节点出现非常少的数据点的可能性就越大,如果这些点是离群值,我们就会过度拟合我们的模型。因为每一个分割都只是一个 if-else 条件语句,所以模型的可解释性也会随着树的深度的增加而降低。
当树太浅时,我们可能得不到任何纯节点。纯节点是只有正点或负点的节点。在这种情况下,我们必须进行多数投票才能得出结果。
那么决策树的高度应该是多少?
身高是一个超参数,我们必须使用交叉验证数据集进行超参数调整,以获得最佳值。
训练和测试时间复杂性
列车时间复杂性:

图 31
在训练阶段发生的事情是,对于数据集中的每个特征(维度),我们将对花费 O(n log n)时间的数据进行排序,然后我们遍历数据点以找到花费 O(n)时间的正确阈值。对于 d 维,总时间复杂度为:

图 32
列车空间复杂性:
在训练决策树时,我们需要的是通常作为 if-else 条件存储的节点。
因此,列车空间复杂度将为:【O 节点】
测试时间复杂度将是 O(深度) ,因为我们必须从决策树的根节点移动到叶节点。
测试空间复杂度将为【O(节点)
使用决策树的回归
当我们处理回归问题时,情况就变了。这里的输出不再是一个类,而是一个实数值。
我们如何拆分数据?
与分类中的熵或基尼系数不同,我们将使用均方误差(MSE)或中位数绝对偏差(MAD)来分割数据。选择降低 MSE 或 MAD 最大的特征进行分割。
我们如何预测一个测试数据点的值?
一旦我们到达一个叶节点,我们取那里已经存在的点的平均值/中值,并预测它是给定测试数据点的输出值。
真实案例
- 不平衡数据集:建议通过上采样或类别权重来平衡数据集,因为这可能会影响熵值。
- 高维数据:随着维数的增加,训练的计算时间也增加。建议如果一个特征有许多类别,应该避免一次性编码,而是将其转换为数字特征,如上所述。
- 多类分类:决策树自然可以扩展处理多类。因为熵或基尼系数杂质可以针对两个以上的类别进行计算,并且可以通过多数表决来做出决定。
- 特征交互:出现在遍历路径中的特征相互交互,因为子节点的条件取决于父节点的条件
- 离群值:如果树很深,离群值会影响并使树不稳定。
- 可解释性:由于决策树只不过是 if-else 语句的集合,所以它具有高度的可解释性。然而,可解释性随着树深度的增加而降低。
- 特征重要性:那些信息增益高的特征是重要的。如果一个特征被多次用于分割,我们使用由于该特征的信息增益的归一化总和。
优势
- 它不需要缩放或标准化数据
- 高度的可解释性,尤其是当维数较少时
- 适用于低延迟系统
- 较少的超参数数量
- 处理分类数据和数值数据
- 容易理解
限制
- 训练模型通常需要更长的时间
- 当您有高维数据时,它可能不合适
- 过度拟合数据的可能性很高
- 数据的微小变化可能会导致决策树结构的整体变化
- 随着深度的增加,树变得更加复杂
- 决策树通常没有其他分类或回归算法那样的预测准确性
使用 Python 构建决策树
感谢 sci-kit 学习库的 plot_tree 函数可视化决策树。我们的决策树看起来会像-

图 33
参考
- https://victorzhou.com/blog/gini-impurity/
- 统计学习导论:R 中的应用
- https://towards data science . com/decision-tree-intuition-from-concept-to-application-530744294 bb6
- M. Gopal 的应用机器学习
字母表甘:AI 生成英文字母表!
这就是我如何创建一个可以生成英文字母的 GAN。

GAN 输出在各个时期的演变
首先,你需要知道 GAN 到底是什么。这里有一个简单的描述。生成对抗网络是两个模型的组合,即生成器和鉴别器。生成器试图生成模仿原始数据的假数据。另一方面,鉴别器试图辨别一个给定的数据是原始的还是伪造的。多亏了这种对抗性的设置,最终,这两种模式在完成任务方面都变得越来越好。当然,关于甘斯还有更多需要了解的。如果你好奇,请观看这个视频…
甘是如何工作的?
在本文中,我想向您展示如何实现这样一个 GAN。我还会提到一大堆帮助你训练第一个 GAN 的技巧。但是,在进入模型之前,让我们先了解一下数据集。
数据集:A-Z 手写字母
这里,我使用的是 MNIST 风格的手写英文字母数据集。 A-Z 数据集包含来自 26 类的 372,450 个字符。每个数据样本都是字母表的灰度图像。像 MNIST 数据集一样,每幅图像的维数是 28px28px* 并表示为一个784(28 * 28)维向量。让我们想象一下其中的一些…

来自 EMNIST Letters 数据集的 100 张随机图像
最初,像素值的范围在【0,255】之间,但是我们应该在馈送到任何机器学习模型之前将它们归一化。一般情况下,我们通过划分255.0 来归一化【0,1】之间的像素,但这里我们归一化的是 [-1,1】之间的像素。这是因为我们后面会用到tanh(tanh=[-1,1】)函数。**
现在让我们建立我们的 GAN。我喜欢按照 4 的步骤来做。
1.建造发电机(G)
生成器是一个神经网络,它将噪声向量(100-维)作为输入,并输出单个英文字母的图像。当我们处理图像数据时,使用卷积神经网络是有意义的。其想法是在输入通过不同层时增加输入的空间维度,直到它达到期望的输出形状( 28px28px )。网络的前两层是具有 ReLu 激活的密集层。我强烈建议在每个图层的输出上使用 BatchNormalization。*
注:批处理规范化使训练收敛更快。快多了。
注意,第一密集层包含 1024 神经元,第二密集层包含 6272 神经元。之后是整形层。整形是很重要的,因为我们希望以后使用卷积,为了应用卷积,我们需要类似矩阵的实体,而不是列/行向量。
注意:为了找到正确的尺寸,我们需要向后思考!首先,确定矩阵的维数( 7*7 )以及需要多少个矩阵( 128 ),然后将它们相乘得到密集层的维数( 77128 = 6272 )。
在应用卷积之前,我们将对矩阵进行上采样。我使用了( 2,2 )上采样,将维度从 77 增加到 1414 。**
上采样是池的一种反函数。
之后,我们有了 22 卷积滤波器( 64 )。注意,我已经根据正态分布初始化了内核的权重。这一层的激活是 LeakyReLu。同样,我们有一个上采样层,后面是卷积层。这一次上采样层将输出 2828 维矩阵。最后一个卷积层只包含 1 滤镜,因为我们只想要一个通道用于灰度图像。这里的激活函数是 tanh 。这就是我们把 [-1,1】之间的像素值归一化的原因。**
注意:我们可以通过使用转置卷积来避免对层进行上采样。因为它们也会增加矩阵的维数。
代码:
发电机
建筑:
**Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 1024) 103424
_________________________________________________________________
batch_normalization_1 (Batch (None, 1024) 4096
_________________________________________________________________
activation_1 (Activation) (None, 1024) 0
_________________________________________________________________
dense_2 (Dense) (None, 6272) 6428800
_________________________________________________________________
batch_normalization_2 (Batch (None, 6272) 25088
_________________________________________________________________
activation_2 (Activation) (None, 6272) 0
_________________________________________________________________
reshape_1 (Reshape) (None, 7, 7, 128) 0
_________________________________________________________________
up_sampling2d_1 (UpSampling2 (None, 14, 14, 128) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 32832
_________________________________________________________________
batch_normalization_3 (Batch (None, 14, 14, 64) 256
_________________________________________________________________
leaky_re_lu_1 (LeakyReLU) (None, 14, 14, 64) 0
_________________________________________________________________
up_sampling2d_2 (UpSampling2 (None, 28, 28, 64) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 28, 28, 1) 577
=================================================================
Total params: 6,595,073
Trainable params: 6,580,353
Non-trainable params: 14,720
_________________________________________________________________**
你注意到我没有在这里编译生成器吗?这将在第 第三 步骤中完成。
2.构建鉴别器(D)
我们的鉴别器只是一个二元分类器,它将灰度图像作为输入,并预测它是原始图像还是伪造图像,即由生成器创建的图像。前两层是卷积层。请注意,我使用了一个步幅 2 ,这意味着输出尺寸将小于输入尺寸。所以,我们不需要池层。两层的滤波器大小都是 55 ,但是第二层中的滤波器数量更多。*
注意:在构建鉴别器时,你应该记住我们的目标是支持生成器,因为我们想要生成假图像。因此,使鉴别器比发生器弱一点。例如,这里我在鉴别器中使用了较少的卷积层。
在卷积层之后,我们需要展平输出,这样我们就可以把它传递到一个密集层。密集层的大小是 256 与 50% 的落差。最后,我们有了 sigmoid 层,就像任何其他二元分类器一样。我们现在必须编译鉴别器。损失应该是二进制交叉熵,我已经使用了一个定制的亚当优化器(学习率= 0.0002 )。
注意:默认的 Adam 学习率( 0.001 )对于 GANs 来说太高了,所以请始终定制 Adam 优化器。
代码:
鉴别器
建筑:
**Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_3 (Conv2D) (None, 14, 14, 64) 1664
_________________________________________________________________
leaky_re_lu_2 (LeakyReLU) (None, 14, 14, 64) 0
_________________________________________________________________
conv2d_4 (Conv2D) (None, 5, 5, 128) 204928
_________________________________________________________________
leaky_re_lu_3 (LeakyReLU) (None, 5, 5, 128) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 3200) 0
_________________________________________________________________
dense_3 (Dense) (None, 256) 819456
_________________________________________________________________
leaky_re_lu_4 (LeakyReLU) (None, 256) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 256) 0
_________________________________________________________________
dense_4 (Dense) (None, 1) 257
=================================================================
Total params: 1,026,305
Trainable params: 1,026,305
Non-trainable params: 0
_________________________________________________________________**
3.联合 G & D
根据原 GAN 论文我们要分别训练发生器和鉴别器。那为什么要走这一步?
可以通过反向传播在最后一个 sigmoid 层计算的损耗来直接训练鉴别器。但是为了训练生成器,我们需要在不影响鉴别器权重的情况下,将这种损失发送回生成器!
实现这一点的一种方法是通过堆叠生成器和鉴别器来创建新的模型。这也是我之前没有编译生成器的原因。我们把新型号叫做甘。它将噪声向量作为输入,然后通过生成器创建一个假图像。然后图像通过鉴别器,鉴别器计算它是原始图像的概率。当我们训练这个 gan 时,鉴别器不应该学习任何东西。因此,' discriminator . trainiable = False '。 只有生成器的权重会被修改。
代码:
发电机+鉴频器= gan
建筑:
**Model: "model_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 100) 0
_________________________________________________________________
sequential_1 (Sequential) (None, 28, 28, 1) 6595073
_________________________________________________________________
sequential_2 (Sequential) (None, 1) 1026305
=================================================================
Total params: 7,621,378
Trainable params: 6,580,353
Non-trainable params: 1,041,025
_________________________________________________________________**
4.火车
终于准备好训练我们的 GAN 了!你觉得代码看起来奇怪吗?别担心,我会解释每一步。
代码:
GAN 的训练环路
外层用于遍历各个时期,内层用于批处理。我已经训练了 80 个时期的模型,并且批次大小是 128。因此,在一个时期中,我们将有 2909(每时期步数= ⌊数据数量 samples/batch_size⌋=⌊372,450/128⌋= 2909)步。
G 固定时的 D 列:
首先,通过从标准正态分布中随机抽取数字来形成噪声向量的 batch_size 数目。然后将这些向量交给生成器来创建假图像。现在我们从训练数据中画出真实图像的 batch_size 数。为了得到鉴别器的输入,我们需要连接假数据和真数据。相应的,我们需要提到标签向量(0:假数据,1:真数据)。但是等等,代码说的是 0.1 和 0.9!WTH 是怎么回事?
这种技术叫做水平平滑。它防止鉴别者对其预测过于自信。
然后,我们为鉴别器调用 train_on_batch 函数,并传递数据标签对。
G 固定时的 D 列:
这里,我们只需要噪声向量和标签。标签向量包含 1。等等,生成器制造假数据,所以标签不应该是 0 吗?
是的。但在这里我们故意给错误的标签,使歧视犯错误。原因是我们希望发电机的性能优于鉴别器。通过这样做,G 将知道 D 在被给定真实标签时的行为,并且它(G)将相应地改变它的权重来愚弄 D。记住,在这个阶段,我们没有改变鉴别器的权重,因此鉴别器没有“忘记”任何东西。
现在,我们为生成器调用 train_on_batch 函数,并传递数据标签对。而那就是朋友,一个甘是怎么练出来的!
让我向您展示一些我的模型产生的最佳(精选)结果…

人工智能生成的字母(T,P,J,S,A,E,L,U)
这里是这个项目的完整代码。瞧啊。现在你知道如何训练甘了!
如果你想进一步探索,请看这个…
人工智能生成 2 种语言的字母(英语和孟加拉语)
我希望你喜欢阅读。下次见…学习愉快!
一种新的强化学习算法
了解并实现 AlphaZero,完全用 JavaScript 实现!
在这篇博文中,你将了解并实现 AlphaZero ,这是一种令人兴奋的新颖的强化学习算法,用于在围棋和国际象棋等游戏中击败世界冠军。您将使用它来掌握一个钢笔和铅笔游戏(点和方框),并将其部署到一个 web 应用程序中,完全用 JavaScript 编写。
AlphaZero 的关键和最令人兴奋的方面是它能够在不依赖外部知识的情况下,在棋盘游戏中获得超人的行为。AlphaZero 通过与自己对弈(自我对弈)和从那些经历中学习来学习掌握游戏。

我们将利用 Github 中可用的 Surag Nair 的 AlphaZero 的“简化的、高度灵活的、有注释的、易于理解的实现”Python 版本。
你可以在这里玩游戏。WebApp 和 JavaScript 实现在这里可用。这段代码是从这个 Python 实现移植过来的。
https://carlos-aguayo.github.io/alphazero/
AlphaZero 是由 Silver,David 等人在论文中描述的“ 掌握没有人类知识的围棋游戏”nature 550.7676(2017):354–359。
点和盒子游戏
《点和盒子》是一个初级的儿童游戏,有着惊人的复杂程度。
两名玩家轮流在两个相邻的点之间放置一条水平线或垂直线。完成 1×1 方块第四边的玩家得一分,并获得另一轮机会。棋盘满了,游戏结束,得分最多的玩家获胜。

人工智能和桌游
我们已经思考了很长时间,如果机器可以证明智能。如何验证机器展现智能行为的能力?一种典型的方式是玩棋盘游戏,如国际象棋,并试图获得超人的行为来击败世界冠军。
1957 年,希尔伯特·西蒙预言计算机系统将在十年内击败国际象棋世界冠军 i 。它花了更长的时间,但在 1997 年 5 月的,一台计算机打败了国际象棋世界冠军加里·卡斯帕罗夫。
尽管这个里程碑意义非凡,但人们可能会争论这个计算机系统是否是“智能的”。
这些计算机系统由三部分组成:
- 自定义的评估函数。
- 博弈树搜索算法。
- 非常强大的硬件。
评估函数将棋盘作为输入,并返回棋盘的“值”。高值表示当前玩家处于非常有利的位置。例如,棋手将要将死的棋盘配置将具有非常高的值。
博弈树搜索算法(如 Minimax )搜索所有可能的走法,寻找一个能保证有高价值的棋盘配置的路径。通过不访问那些我们知道找不到更好价值的配置,可以提高搜索效率。这就是Alpha–beta 修剪的作用。
最后,添加非常强大的硬件,你将拥有一台能够击败世界冠军的机器。
有什么条件?有经验的玩家 手动工艺 这些评价函数。这些系统将依靠开局书来指示最著名的棋步。中级游戏将使用通过研究大师的游戏而创建的评估函数。然后大师们会进一步微调它们。
例如,我们可以为点和盒子游戏创建一个评估函数。一个合理而直接的评估函数是比较分数。分数中的正 delta 越高,棋盘游戏越有利。在大多数情况下,这是可行的。然而,在点和盒子游戏中,就像在许多棋盘游戏中一样,最好的行动可能包括牺牲短期利益以获得更好的长期收益。在点和盒子游戏中,有时最好不要在盒子中得分,以避免获得另一轮机会,相反,要迫使对方移动。然后,我们必须调整我们的评估函数,以考虑越来越多的复杂场景!
击败卡斯帕罗夫的评价函数有 8000 个特征!这些功能中的大部分都是手工创建和调整的!
因此,在不贬低像击败国际象棋世界冠军这样的重要里程碑的情况下,一个不可取的方面是需要顶级玩家定义这些计算机的行为,并手动调整如此多的变量。
alpha zero 是什么,为什么这么激动人心?
AlphaZero 是第一个能够在国际象棋或围棋等游戏中获得超人行为的计算机系统,它击败了世界冠军,仅依靠游戏规则而没有人类领域的知识。
如果只给定游戏规则,AlphaZero 将开始自相残杀。一点一点地学习策略和技术,相对快速地获得超人的行为。
像深蓝这样的系统需要国际象棋专家的帮助,而 AlphaZero 会通过与自己对弈变得强大。此外,AlphaZero 不仅在国际象棋上表现出超人的力量,在围棋上也是如此。围棋对电脑来说是一个更复杂的游戏,因为它的更大的游戏空间和其他因素。
虽然人类从数千年的数百万场游戏中积累了像 T4 围棋和国际象棋这样的游戏知识,但 AlphaZero,一种只使用游戏规则的简单算法,在几天内重新发现了这些知识和新策略。
甚至还有一部关于它的电影。
仅通过自我游戏,AlphaZero 将如何学习?
回想一下,像 DeepBlue 这样的系统依赖于人定义的“评估函数,它将电路板状态作为输入,并输出状态的“值”。
如今,深度学习模型非常容易将图像作为输入,并将其分类为狗或猫。这个想法是将棋盘作为深度学习模型的输入,并训练它预测棋盘是赢还是输的配置。
但是训练机器学习,需要数据,大量的数据。你从哪里得到游戏的数据集?很简单,我们让计算机自己玩,生成一组游戏,并从中制作一个数据集。
AlphaZero 训练算法
算法很简单:
- 让电脑和自己玩几局游戏,记录棋盘的每一步棋。一旦我们知道了结果,在游戏结束时用给定的结果更新所有的棋盘,“赢”或“输”。然后,我们建立了一个数据集,提供给神经网络(NN ),并开始学习给定的电路板配置是赢还是输。
- 克隆神经网络。使用上一步中生成的数据集训练克隆。
- 让克隆神经网络和原始神经网络相互对抗。
- 挑一个神经网络赢的,丢掉另一个。
- 转到步骤 1。
就像魔术一样,经过多次迭代,你就有了世界级的模型。这个模型仅用了 4 个小时就成功超越了最强的电脑象棋程序!
AlphaZero 组件
AlphaZero 有两个组成部分。我们已经讨论过第一个,也就是神经网络。第二个是“蒙特卡罗树搜索”或 MCTS。
- 神经网络(NN) 。将棋盘配置作为输入,输出棋盘的值,以及所有可能走法的概率分布。
- 蒙特卡罗树搜索(MCTS) 。理想情况下,神经网络足以选择下一步行动。我们仍然希望看到尽可能多的董事会配置,并确保我们确实选择了最好的行动。像极小极大一样,MTCS 是一种算法,它将帮助我们了解董事会的配置。不像极小极大,MTCS 将有助于有效地探索游戏树。
让我们深入细节,确定下一步行动
跟随 AlphaZero 更容易,首先看它在决定下一步棋(竞技模式)时的行为,然后再看训练套路。
神经网络已经很擅长对事物进行分类,比如猫和狗。这里的想法很简单,神经网络可以学习将棋盘配置分类为赢与输吗?更具体地说,神经网络将预测表示赢与输的概率的值。此外,它将输出所有可能移动的概率分布,表示我们下一步应该探索哪个动作。
神经网络将游戏状态作为输入,输出一个值和一个概率分布。具体对于点和方框来说,游戏状态由三个元素表示:首先,一条线是否已经玩过,使用 0 和 1 的数组表示穿过点的每条线。如果一个玩家已经给这条线着色,则为 1,否则为 0。第二,如果当前移动是通过,第三,分数。我们可以用这三个元素来表示所有需要的信息,以确定董事会的价值并预测其下一步行动。
我们来分析一下下面的博弈,该轮到蓝玩家了。蓝有两个选择,走上面的路输了,或者走下面的路赢了。

如果蓝色先玩 23 然后玩 21,红色赢。相反,如果蓝色先玩 23 再玩 9,蓝色就赢了。如果 AlphaZero 要出蓝色,它如何找到获胜的一步?
你可以用这个笔记本重现下面看到的结果。
如果我们将棋盘配置输入神经网络,我们将得到一个数组,其中包含每个动作移动概率:
move_probability[0]: 9.060527501880689e-12
move_probability[1]: 3.9901679182996475e-10
move_probability[2]: 3.0028431828490586e-15
move_probability[3]: 7.959351400188552e-09
move_probability[4]: 5.271672681717021e-11
move_probability[5]: 4.101417122592821e-12
move_probability[6]: 1.2123925357696643e-16
move_probability[7]: 6.445387395019553e-23
move_probability[8]: 2.8522254313207743e-22
**move_probability[9]: 0.0002768792328424752**
move_probability[10]: 1.179791128073232e-13
move_probability[11]: 5.543385303737047e-13
move_probability[12]: 3.2618200407341646e-07
move_probability[13]: 4.302984970292259e-14
move_probability[14]: 2.7477634988877216e-16
move_probability[15]: 1.3767548163795204e-14
move_probability[16]: 8.998188305575638e-11
move_probability[17]: 7.494002147723222e-07
move_probability[18]: 8.540691764924446e-11
move_probability[19]: 9.55116696843561e-09
move_probability[20]: 4.6348909953086714e-12
**move_probability[21]: 0.46076449751853943**
move_probability[22]: 2.179317506813483e-20
**move_probability[23]: 0.5389575362205505**
move_probability[24]: 5.8165523789057046e-15
我们还获得了板配置的值:
-0.99761635
你可以在这里找到生成这些值的代码。
这些输出中有一些有趣的东西:
- 在 8 个可能的移动中,最有可能的移动是 23、21 和 9。如果 NN 打 23 或 21,他得一分。23 是赢棋,其值(0.53)略高于 21 的值(0.46)。
- 神经网络将输出概率,即使是无效的移动。遵循游戏规则并确保我们不玩无效的动作是代码的工作。
- 该值为-0.99。这表明 AlphaZero 认为它已经输掉了这场比赛。该值的范围从-1(失败)到 1(成功)。这个值应该更接近于 1(赢)而不是-1(输),因为我们知道这是一个赢的状态。也许我们需要更多的训练回合来达到这样一种状态,即 AlphaZero 将学习这种板配置的正确值。
利用神经网络的输出来决定我们的下一步很有诱惑力。
在桌游中(在生活中!),玩家在决定自己的下一步棋时,通常会看到许多“前面的棋”。这里也没什么不同。我们使用神经网络预测来选择下一步要探索的状态,并忽略那些低价值的状态。像 Minimax 一样,传统的人工智能博弈树搜索算法效率低下,因为它们必须在进入下一步之前分析每一步棋。即使有很小的分支因素的游戏也使他们的游戏空间难以处理。分支因子是可能的移动次数。随着游戏的进行,可能的移动次数会发生变化。如果是这样,你计算一个平均分支因子。国际象棋的平均分支因子是 35。围棋是 250。
这意味着,在国际象棋中,仅仅走了两步,就有 1,225 (35)种可能的棋盘布局,而在围棋中,可能是 62,500 (250)。在点和框中,对于一个 3x3 的游戏,初始分支因子是 24,并且随着每一步棋而减少(除非是一次通过)。所以在中局中,当分支因子为 15 时,仅三步棋就有 2730(15 * 14 * 13)种棋盘布局。
相反,NN 会引导我们,告诉我们应该探索哪里,避免被许多无用的路径淹没。NN 告诉我们 23 和 21 是很强的移动。
这是蒙特卡洛树搜索的工作。
蒙特卡罗树搜索(MCTS)
神经网络已经给了我们下一步行动的指示。蒙特卡洛树搜索算法将帮助我们遍历节点,选择下一步行动。
看看这个链接中这篇论文对蒙特卡罗树搜索的图形描述。
MCTS 的工作方式是,对于给定的电路板,它将运行 N 次模拟。n 是我们模型的一个参数。在这些模拟的最后,下一步将是最受欢迎的。你可以跟随代码到这里。
运行 n MCTS 模拟
MCTS 模拟包括遍历游戏树,从当前棋盘开始,通过选择具有最高“置信上限(UCB)”值(定义如下)的节点,直到我们到达我们以前没有访问过的游戏状态,这被称为“叶子”。这就是本文所称的 A 部分“选择”。
UCB 是什么?就是 Q(s,a) + U(s,a)。其中“s”是状态,“a”是动作。Q(s,a)是我们期望从动作“a”之后的状态“s”中得到的期望值,与 Q-Learning 中的值相同。请记住,在这种情况下,该值的范围将从-1(输)到 1(赢)。 U ( s ,a)∧P(s,a)/(1+N(s, a )。这意味着 U 与 P 和 N 成比例,其中 P(s,a)是元组(s,a)的先验概率,即 NN 返回的值,N(s,a)是我们访问状态 s 并采取行动 a 的次数。
# Upper Confidence Bound
ucb = Qsa[(s,a)] + Ps[s,a] * sqrt(Ns[s]) / (1 + Nsa[(s,a)]
UCB 的要点是最初偏好具有高先验概率(P)和低访问计数(N)的动作,但是渐近地偏好具有高动作值(Q)的动作。
你可以沿着这里的看代码。
A 部分—选择置信上限最高的行动(UCB)
一旦找到一片叶子,我们就用神经网络来搜索这块板子。这就是本文所说的 B 部分,“扩展和评估”。你可以跟随代码到这里。
B 部分—扩展和评估
最后,我们将传播神经网络返回的值。这就是论文所说的 C 部分“备份”。你可以跟随代码到这里。
C 部分—备份
决定下一步棋
我们来看看 AlphaZero 是如何针对上面提到的状态确定下一步行动的。

AlphaZero 将运行 50 次蒙特卡罗树搜索模拟。
您可以使用这个笔记本重现下面看到的结果。
这些是每次迭代遵循的路径:
Simulation #1 -> Expand root node
**Simulation #2 -> 23**
Simulation #3 -> 21
Simulation #4 -> 9
Simulation #5 -> 17
Simulation #6 -> 12
Simulation #7 -> 19
Simulation #8 -> 3
Simulation #9 -> 18
**Simulation #10 -> 23,24**
Simulation #11 -> 21,24
**Simulation #12 -> 23,24,21**
Simulation #13 -> 21,24,23,24
**Simulation #14 -> 23,24,9**
**Simulation #15 -> 23,24,17**
Simulation #16 -> 21,24,9
**Simulation #17 -> 23,24,12**
**Simulation #18 -> 23,24,18**
Simulation #19 -> 21,24,17
**Simulation #20 -> 23,24,21,24,9**
Simulation #21 -> 21,24,19
**Simulation #22 -> 23,24,3**
Simulation #23 -> 21,24,18
**Simulation #24 -> 23,24,19**
Simulation #25 -> 21,24,23,24,17
**Simulation #26 -> 23,24,21,24,18**
**Simulation #27 -> 23,24,21,24,3**
Simulation #28 -> 21,24,3
**Simulation #29 -> 23,24,21,24,19**
Simulation #30 -> 21,24,12
**Simulation #31 -> 23,24,21,24,9,24**
Simulation #32 -> 21,24,23,24,12
**Simulation #33 -> 23,24,21,24,9,24,18**
Simulation #34 -> 21,24,23,24,9,24,17
**Simulation #35 -> 23,24,21,24,9,24,12**
**Simulation #36 -> 23,24,21,24,9,24,3**
Simulation #37 -> 21,24,23,24,9,24,19
**Simulation #38 -> 23,24,21,24,9,24,18,17**
Simulation #39 -> 21,24,23,24,9,24,18,17,24
**Simulation #40 -> 23,24,21,24,9,24,18,17,24,19**
Simulation #41 -> 21,24,23,24,9,24,18,17,24,19,24
**Simulation #42 -> 23,24,9,21**
**Simulation #43 -> 23,24,9,18**
**Simulation #44 -> 23,24,9,17**
**Simulation #45 -> 23,24,9,19**
**Simulation #46 -> 23,24,9,12**
**Simulation #47 -> 23,24,9,21,24**
**Simulation #48 -> 23,24,9,3**
**Simulation #49 -> 23,24,9,21,24,18**
**Simulation #50 -> 23,24,9,21,24,17**
上面的意思是:在第一个模拟中,我们以前没有见过那个板,因此它是一个“叶”节点,并“扩展”它。扩展意味着它用神经网络评估该板。
Simulation #1 -> Expand root node
在第二个模拟中,我们已经扩展了根节点,因此它不再是“叶子”,因此我们可以搜索具有最高 UCB 的节点
UCB 最高的动作是 23。它进入那个状态,因为它以前没有见过那个状态,因此它是一个叶节点,它展开它,第二个模拟完成。
Simulation #2 -> 23
在这种情况下,神经网络给出 23 的损失值。我们之前讨论过这个。神经网络可以使用更多的训练来了解它确实是一个糟糕的状态。但是现在,这仍然有效,我们将在下面看到。
对于接下来的模拟,每次,具有最高 UCB 的选项是剩余的选项。这是因为在访问每个动作后,它发现它的值很低,因此 UCB 也很低。
Simulation #3 -> 21
Simulation #4 -> 9
Simulation #5 -> 17
Simulation #6 -> 12
Simulation #7 -> 19
Simulation #8 -> 3
Simulation #9 -> 18
在接下来的模拟中,一个令人兴奋的模式开始浮现。记住中奖顺序是 23,24(跳过),9。
Simulation #10 -> 23,24
Simulation #11 -> 21,24
Simulation #12 -> 23,24,21
Simulation #13 -> 21,24,23,24
Simulation #14 -> 23,24,9
Simulation #15 -> 23,24,17
Simulation #16 -> 21,24,9
Simulation #17 -> 23,24,12
Simulation #18 -> 23,24,18
Simulation #19 -> 21,24,17
Simulation #20 -> 23,24,21,24,9
Simulation #21 -> 21,24,19
Simulation #22 -> 23,24,3
Simulation #23 -> 21,24,18
Simulation #24 -> 23,24,19
在模拟 10 到 24 中,MCTS 已经将其注意力集中在节点 21 和 23 上。这是有意义的,因为这两条路中的任何一条,我们都得了一分。
Simulation #33 -> 23,24,21,24,9,24,18
Simulation #34 -> 21,24,23,24,9,24,17
Simulation #35 -> 23,24,21,24,9,24,12
Simulation #36 -> 23,24,21,24,9,24,3
Simulation #37 -> 21,24,23,24,9,24,19
Simulation #38 -> 23,24,21,24,9,24,18,17
Simulation #39 -> 21,24,23,24,9,24,18,17,24
Simulation #40 -> 23,24,21,24,9,24,18,17,24,19
Simulation #41 -> 21,24,23,24,9,24,18,17,24,19,24
然后在模拟 33 到 41 中,它开始深入失败的组合。注意一个有趣的事情。尽管深入,它永远不会到达游戏的结尾,因为仍然有可玩的移动。
Simulation #42 -> 23,24,9,21
Simulation #43 -> 23,24,9,18
Simulation #44 -> 23,24,9,17
Simulation #45 -> 23,24,9,19
Simulation #46 -> 23,24,9,12
Simulation #47 -> 23,24,9,21,24
Simulation #48 -> 23,24,9,3
Simulation #49 -> 23,24,9,21,24,18
Simulation #50 -> 23,24,9,21,24,17
然后,在模拟 42 至 50 中,在 NN 的帮助下,它认识到 23、24、21 或 21、24、23 不是好的选项,并完全集中在获胜序列 23、24、9 上。
50 次模拟后,我们的时间到了,我们需要选择一步棋。MCTS 选择了我们去过最多的地方。以下是我们每次移动的次数(在第一次行动中):
counts[3] = 1
counts[9] = 1
counts[12] = 1
counts[17] = 1
counts[18] = 1
counts[19] = 1
counts[21] = 15
counts[23] = 28
在前 10 个模拟中,动作 3、9、12、17、18 和 19 仅被访问一次。然后 MCTS 把注意力集中在第 21 步和第 23 步。最近 9 次模拟访问行动 23。鉴于我们访问 23 号行动最多,达 28 次,MCTS 将其作为下一步行动。
有哪些外卖?
- 通过每次模拟,MCTS 将依靠神经网络,使用累积值(Q)、神经网络给出的移动先验概率(P)以及它访问节点的频率的组合,来跟随看起来最有希望的路径。或者换句话说,具有最高 UCB 的路径。
- 在每次模拟期间,MCTS 将尽可能深入,直到它到达一个它以前没有见过的板配置,它将依赖神经网络来评估板,以告诉板有多好。
如果我们将它与经典方法进行比较,如使用带有 Alpha-Beta 修剪和评估函数的 Minimax,我们可以说:
- 在 Minimax 中,深度是由设计者建立的参数。它会深入到那个深度,然后使用评估函数。如果没有 Alpha-Beta 修剪,它将不得不访问给定深度的所有节点,效率非常低。在上面的场景中,还剩 8 步棋,深度为 3,这意味着评估 336 个棋盘。在 MTCS,有 50 个模拟,我们只需要评估 50 个板,并设法深入得多。
- 阿尔法-贝塔剪枝会帮助我们减少 336 这个数字。然而,它不允许我们走一条智能的道路。
- 我们依靠神经网络随时告诉我们电路板的“价值”,而不是使用人类定义的评估函数。
- 有趣的是,神经网络在最初的移动中没有预测到正确的值。然而,当我们深入游戏而没有一直到游戏结束时,它有正确的预测。
- 最后,注意 AlphaZero 的优雅和简单。而在 Alpha-Beta 剪枝中,您必须跟踪 Alpha 和 Beta 参数才能知道在哪里剪枝,并且人工定义的评估函数可能很难使用。MCTS 和 NN 让一切变得优雅而简单。你可以用 JavaScript 实现这一切!
训练神经网络
我们遗漏了最后一个关键方面。我们如何训练神经网络?
幸运的是这很简单。我们之前提到过这些步骤:
- 让电脑在“训练模式”下和自己玩几局,记录棋盘的一举一动。一旦我们知道了结果,在游戏结束时用给定的结果更新所有的棋盘,“赢”或“输”。然后,我们建立了一个数据集,提供给神经网络(NN ),并开始学习给定的电路板配置是赢还是输。
- 克隆神经网络。使用上一步中生成的数据集训练克隆。
- 让克隆神经网络和原始神经网络相互对抗。
- 挑一个神经网络赢的,丢掉另一个。
- 转到步骤 1。
玩“训练模式”是什么意思?差别很小。当在“竞争模式”下玩时,我们总是选择访问量最高的棋步。而在“训练模式”中,对于游戏开始时的一定数量的移动,计数成为我们的概率分布并鼓励探索。例如,假设有 3 个可能的操作,访问次数为[2,2,4]。在竞争模式下,我们总是选择第三个动作,因为它有最高的访问计数。但是在训练模式中,[2,2,4]变成了概率分布,2+2+4 = 8,因此[2/8,2/8,4/8]或[0.25,0.25,0.5]。换句话说,我们 50%的时间选择第三个动作,而 25%的时间探索第一个和第二个动作。
然后我们用一个简单的井字游戏来描述数据集。

在上面的游戏中,第一个玩家,Xs 获胜。
我们可以这样配置棋盘的状态:如果方块还没有下完,则为 0;如果第一个玩家下了方块,则为 1;如果第二个玩家下了方块,则为-1。
例如,董事会如下:
0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0
0 0 0 -> 0 0 0 -> -1 0 0 -> -1 1 0 -> -1 1 0 -> -1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 -1 0 1
或者:
[0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0,-1, 0, 0, 0, 0, 0]
[1, 0, 0,-1, 1, 0, 0, 0, 0]
[1, 0, 0,-1, 1, 0,-1, 0, 0]
[1, 0, 0,-1, 1, 0,-1, 0, 1]
然后我们必须做两件事。首先,更新每个棋盘,就好像轮到玩家 1 了。我们总是从第一个玩家的角度向神经网络提供训练数据。在 TicTacToe,这很简单。每次轮到第二个玩家时,我们可以翻转棋子,变成玩家 1 的视角。
我们从这里开始:
[0, 0, 0, 0, 0, 0, 0, 0, 0] # Player 1 turn
**[1, 0, 0, 0, 0, 0, 0, 0, 0] # Player 2 turn**
[1, 0, 0,-1, 0, 0, 0, 0, 0] # Player 1 turn
**[1, 0, 0,-1, 1, 0, 0, 0, 0] # Player 2 turn**
[1, 0, 0,-1, 1, 0,-1, 0, 0] # Player 1 turn
**[1, 0, 0,-1, 1, 0,-1, 0, 1] # Player 2 turn**
对此:
[ 0, 0, 0, 0, 0, 0, 0, 0, 0] # Player 1 turn
**[-1, 0, 0, 0, 0, 0, 0, 0, 0] # Player 1 turn**
[ 1, 0, 0,-1, 0, 0, 0, 0, 0] # Player 1 turn
**[-1, 0, 0, 1,-1, 0, 0, 0, 0] # Player 1 turn**
[ 1, 0, 0,-1, 1, 0,-1, 0, 0] # Player 1 turn
**[-1, 0, 0, 1,-1, 0, 1, 0,-1] # Player 1 turn**
第二,我们追加游戏结果。如果一号玩家赢了,我们就用“1”,如果输了,就用“0”。
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, **1**] # Winning board
[-1, 0, 0, 0, 0, 0, 0, 0, 0, **0**] # Losing board
[ 1, 0, 0,-1, 0, 0, 0, 0, 0, **1**] # Winning board
[-1, 0, 0, 1,-1, 0, 0, 0, 0, **0**] # Losing board
[ 1, 0, 0,-1, 1, 0,-1, 0, 0, **1**] # Winning board
[-1, 0, 0, 1,-1, 0, 1, 0,-1, **0**] # Losing board
数据集开始有一些形状了!正如你从上面看到的,我们可以把它输入神经网络来学习棋盘上的输赢值。
不过,我们忽略了概率。那些是从哪里来的?请记住,在训练模式下,我们仍然会在每一步运行 MCTS 模拟。与我们记录棋盘配置的方式相同,我们将记录概率。
然后,我们克隆神经网络,并使用该数据集训练克隆,预计它会随着使用新数据而稍微变强。我们通过让它与原来的 NN 竞争来验证它确实更强。如果它赢了 55%以上的时间,我们认为它更强,并放弃原来的,克隆成为我们新的神经网络。
我们不断重复这个过程,神经网络会不断变强。
你可以从论文这里看到图表。
为什么数据集有更强的动作可以学习?通过学习 MCTS 生成的概率,他们通常会选择比神经网络给出的原始移动概率更强的移动。我们通过让 MCTS 深入许多路径来提供神经网络知识!
用这个笔记本训练一个点和方框模型。
将其部署到 WebApp 中
几个月前,我发表了一篇博文,带你完成将 Keras 或 Tensorflow 模型转换成供 Tensorflow.js 使用的 JavaScript 的过程。我们将转换我们在 Keras 中训练的模型,以便在 Tensorflow.js 中使用。
这个笔记本将预先训练的点和方框模型转换成 Tensorflow.js 模型。
一旦我们这样做了,我们就可以轻松地用 JavaScript 加载模型,如这里的所示。
结论
在这篇博文中,你了解了 AlphaZero,这是一种新颖的强化学习算法,可以在双人零和棋盘游戏中击败世界冠军。
您了解了它如何沿着神经网络使用蒙特卡罗树搜索来找到最佳的下一步行动。你也学会了如何训练这个神经网络。
我希望你喜欢这篇博文,并发现它很有价值。如果是,伸出!
我是 Appian 的软件开发高级总监兼机器学习工程师。我在 Appian 工作了 15 年,我一直很开心。这个疫情并没有让我们放慢脚步,我们正在招聘!给我发一条消息如果你想知道我们是如何制作软件的,请取悦我们的客户,玩得开心!

AlphaZero 和人工智能之美
自我学习人工智能如何重新定义我们的创造力概念

Natasha Reddy 在 Unsplash 上的照片
2016 年,谷歌的 AlphaGo 以 4:1 击败围棋世界冠军 Lee Sedol 的胜利引起了不仅仅是围棋界的轰动,超过 1 亿人观看了比赛。这是人工智能发展的一个里程碑:围棋经受住了计算机科学家构建可以在人类水平上玩很长时间的算法的尝试。现在,一个人造大脑已经建立起来,控制着一个花了数千小时练习来相对轻松地磨练技艺的人。
这已经是相当大的成就了,但随后 AlphaGoZero 出现了,给 AlphaGo 吃了点自己的药:它以 100:0 的优势战胜了 AlphaGo,仅在 Lee Sedol 失败一年后。这更加壮观,而且不仅仅是因为显而易见的原因。AlphaGoZero 不仅是 AlphaGo 的改进版本。AlphaGo 曾在最好的人类围棋选手进行的专家游戏的帮助下进行训练,AlphaGoZero 则从零开始,在没有任何监督的情况下解决了游戏的复杂性。
给定的无非是游戏规则和如何赢 ,它把自己锁在自己的虚拟房间里,和自己对弈只有 34 个小时。它不仅将人类历史上建立起来的对游戏原则和美学的理解与计算机毋庸置疑的超强数字能力结合起来,而且它本身就成为了已知宇宙中的主导力量。
它是如何做到这一点的?
国际象棋和围棋
在西方,国际象棋远比围棋更受欢迎。部分原因可能是文化上的,某种与东西方知识分子性格相关的亲缘关系。国际象棋有时被比作基于规则的西方思维,而围棋更类似于东方思维的整体倾向。围棋被认为比象棋更开放,更直观。
这个角度有助于解释科学家们在建造围棋计算机和象棋计算机方面的巨大成功差异。毕竟,人工大脑的统治地位对于国际象棋界来说已经是很久以前的新闻了。
计算机一出现,人们就试图建造下棋计算机(计算机科学先驱巴贝奇、图灵、香农和冯·诺依曼都在设计特定的象棋硬件),使象棋成为历史上所有人工智能中研究得最彻底的问题。
作为这一发展的高潮,深蓝在 1997 年赢得了世界冠军加里卡斯帕罗夫赢得了国际赞誉。三年后,最好的围棋计算机仍然被一个 9 岁的男孩打败(包括九步障碍)。
这种差异是相当深刻的,并且与游戏的基本构成的差异有关。理解它有助于解释为什么构建围棋引擎比象棋引擎困难得多,也有助于解释为什么它一旦成功,就是我们追求人工智能的一个里程碑。
战术与战略
"国际象棋是表现逻辑科学的艺术."
米哈伊尔·博特文尼克
为了克服这个问题,程序员需要 好的试探法和决策表来排除明显不好的走法 并树桩决策树(参见这里关于国际象棋中决策树的好介绍)。
这些在国际象棋中比在围棋中更容易获得:一个棋子大约值 1,一个主教和骑士 3,一辆车 4,一个皇后 9,如果你控制了中心,你通常更好,如果你的棋子被开发,那通常是好的,如果你的棋子被连接,那是好的,等等。(和所有事情一样,例外证实了规则)。
在对未来棋步树进行了深入的、启发式的增强搜索之后,国际象棋的位置可以被数值化地评估为黑棋或白棋的某个值。因此,人工智能的符号化、基于规则的方法在上个世纪的大部分时间里最受欢迎,似乎最有前途,这种方法自然适用于国际象棋,而构建更好的引擎的问题是找到更有效的算法来搜索决策树,并提升计算能力。
但是对于围棋来说,这是行不通的:用同样的方法评估围棋的位置要困难得多。人类所说的“直觉”和长期策略起着更大的作用。在许多情况下,即使是职业围棋手也无法解释他们对棋局的直觉。可能发生的事情太多了,搜索树膨胀得太快,无法建立具有明确标准的算法,从而使它们能够与人类竞争。
所以围棋需要用完全不同的方法来破解。深度学习革命在一个方便的时间到来,提供了大量的新技术。正如 AlphaGo 团队的领导者 David Silver 解释的那样,AlphaGo 是第一个不依赖于结构化搜索,而是使用强化学习和深度神经网络的算法。
正如他们的成功所证明的那样,这种方法非常有效。
强化学习
“强化学习感觉就是智能。”
大卫·西尔弗
强化学习可以粗略地定义为在环境中交互的智能代理。正如我在这里使用的“智能”一词已经表明的那样,强化学习的问题更清楚地表述了人工智能的整体问题。我们自己的智慧最明显地体现在我们在我们称之为世界的复杂而不确定的环境中运作的能力上。我们可以设定自己的目标,或者通过探索我们的环境和解决挡在我们和目标之间的问题来追求目标。
我们可以想象一个围棋手坐下来开玩笑地探索游戏,可以想象以这种方式发现一个新的创造性想法意味着什么。因此,与我们对智力的直觉理解相比,AlphaGoZero 背后的原理非常切中要害。
这就是为什么大卫·西尔弗认为人工智能的未来很可能建立在强化学习的基础上。
直觉在象棋中的作用
虽然在国际象棋中构建符号人工智能是可能的,但不应该忘记,我们所说的“直觉”在游戏中对人类玩家也起着巨大的作用。虽然现代国际象棋引擎可以通过计算大量可能的走法并将其与专家游戏数据库进行比较来评估任何位置,但大师们没有这种奢侈,尽管他们可以提前计算许多走法,但他们也依赖于对位置优点和走法质量的直观估计,特别是在快速、闪电战或火箭棋等更快的时间格式中(每个玩家只有 15 到 1 分钟)。
“不是所有的艺人都是棋手,所有的棋手都是艺人”
马塞尔·杜尚
国际象棋从来不仅仅是一门科学。国际象棋也是一项运动,国际象棋也是一门艺术,一种独特的奇观,在这种奇观中,永恒的美可以与表演同时发生,就像在爵士乐唱片上一样。所以在国际象棋中,艺术和科学元素之间总是有相互影响的。这些在每一个优秀的棋手和每一局棋中都有体现,尽管侧重点明显不同。但正如所料,在过去的二十年里,这一重点一直在转移。
计算机的出现在现代国际象棋上留下了痕迹,并在国际象棋界引发了一股迷人的活力。这一发展可能预示着人类的许多发展,质疑我们如何定义自己和一些使我们最像人类的东西:我们的艺术,我们的创造力,我们的美感。
机器如何改变了国际象棋

为了和棋而战,至少是用白棋,在某种程度上是对国际象棋的一种犯罪。
米哈伊尔·塔尔
继 1997 年世界冠军卡斯帕罗夫击败深蓝之后,国际象棋再也不一样了。如果电脑比人类更擅长下棋,那么肯定有东西可以向它们学习。因此,现代国际象棋大师开始在引擎的帮助下研究位置,检查组合,评估位置,并在组合力和远见的帮助下研究最好的移动。2013 年阿南德对阵卡尔森的冠军赛被许多人认为是老一代国际象棋选手与新一代新星之间的比赛,新一代新星是第一个在超级计算机的帮助下训练他们一生的人。卡尔森赢了,开创了国际象棋的新时代,这可能在 2018 年的世界锦标赛中得到最好的概括,卡尔森和卡鲁阿纳以平局结束了所有 12 场锦标赛。
当然,错误对于一盘棋来说是不好的,但是错误是不可避免的,而且在任何情况下,一盘没有错误的棋,或者如他们所说的“完美的棋”是无色的。
一些人批评说,高水平的国际象棋越来越不在于大胆的牺牲和漂亮的攻击,而在于不犯任何错误,很好地理解位置,并从里到外知道许多开口中的最佳步骤(然后赢得平局的残局,正如世界冠军卡尔森所熟知的那样)。当然,这也是由于极高的比赛质量,这是今天达到国际象棋世界的顶峰所必需的。
国际象棋中人的因素
对我来说,国际象棋与其说是一门科学,不如说是一门艺术。
米哈伊尔·塔尔
但部分原因也是由于引擎:社区中的一些人声称“机器毁了国际象棋”,现代国际象棋缺乏“人”的元素,缺乏早期大师们在经典游戏中发现的灵感和新鲜感。保罗·墨菲或阿道夫·安德森的游戏,如常青树或歌剧院之夜在玩了 150 年后仍被分析,而卡帕布兰卡或塔尔等大师的游戏继续让人们爱上这个游戏。但是“人类”国际象棋的时代真的结束了吗?“人类”国际象棋是由扭断脖子的攻击和灵感的击打来定义的吗?
米哈伊尔·塔尔有很多绰号:在国际象棋界,他被简单地称为来自里加 的 魔术师。像除他之外的少数人一样,他把棋手描绘成艺术家、诗人、古怪、大胆和有趣的人。他的许多戏剧性的牺牲在国际象棋界获得了传奇般的地位。他玩游戏不是为了画画,而是为了让每一场游戏都像一首诗:独特、激动人心、感人肺腑,如果一切顺利的话,还会很美。尽管如此,许多人认为现代大师会轻松战胜老大师。因为虽然戏剧性的牺牲有时会压垮对手,动摇阵地,招致错误(塔尔将其比作将对手带入黑暗森林),并在残局中带来优势,但如果小心应对,它们也很容易导致浪费材料,不稳定的阵地,并最终导致失败。
但也许我们的二分法是错误的。机器思维一定要表现机械僵化,蛮算吗?是不是要拿出游戏的精神?对我们来说,人造思维一定看起来是人造的和陈腐的吗?还是有另一种美有待发现?
AlphaZero 说是的:它可能会再次改变现代国际象棋。
AlphaZero 和人工智能之美
机器毁了国际象棋。自学式人工智能可能会拯救国际象棋。
agadmator
AlphaZero 是一个多面手:它从围棋转到了国际象棋,经过不到 24 小时的训练,它击败了目前市场上最强大的国际象棋引擎 Stockfish。
AlphaZero 的下棋有些奇特。它做出的动作看起来像人类,而且具有根本性的创造力。AlphaZero 可以玩得很激进,追求长期策略,看似戏弄对手,聪明而富有想象力地关闭棋子。几乎像一个人,几乎像棋盘的那些诗人,几乎像塔尔,但更好:像打了类固醇的塔尔。
我一直在想,如果有一个高级物种降落在地球上,向我们展示他们是如何下棋的,那会是怎样的。现在我知道了。
彼得·海恩·尼尔森
观看 AlphaZero 的一些游戏会是一次鼓舞人心的经历。它的玩法对于人类玩家来说几乎是不可思议的。外星象棋,即使是大师级的。包括世界冠军芒努斯·卡尔森在内的许多人都在研究 AlphaZero 的国际象棋游戏。根据卡尔森的说法,他们给他带来了关于游戏的新想法和观点,并帮助他改善了自己的风格。阿尔法在训练阶段通过不同“人类”入口的方式也引起了人们的兴趣。
深蓝 20 年后,人工智能再次改变了国际象棋。
在围棋中也观察到了类似的模式:在与李·塞多尔(Lee Sedol)的第二场比赛中,AlphaGo 做出了著名的“37 步棋”。它违背了围棋选手从小就被教导的所有规则,没有一个职业选手预料到这一点。它被计算机发现,成为人类共享知识的一部分。同样,在最初的失败震惊之后,Lee Sedol 甚至说 AlphaZero 让他重新感受到了游戏的乐趣,因为他意识到在他一生都在探索的游戏中还有很多东西需要探索。
这会把我们引向何方
"创造力是充满乐趣的智慧."
爱因斯坦

照片由 Tim Mossholder 在 Unsplash 上拍摄
创造力意味着发现以前不知道的东西。随着 AlphaZero 通过一个发现过程进行训练,它有空间变得真正有创造力,甚至提出了我们所说的创造力是什么的问题。
对于加里·卡斯帕罗夫(Gary Kasparov)来说,AlphaZero 的出现是人工智能历史上比深蓝更深远的时刻,因为它是基于发现的。当我们想到 AI 的曙光时,我们会想到机器思维慢慢接管人类的冰冷理性。我们通常不会想到创造力,以及由此带来的乐趣。
我们是万有引力无法阻止我们冒险进入太空的类人猿。我们是以接近光速的速度向对方发射质子,并发现数十亿光年外黑洞的引力涟漪的类人猿。我们是现实中难以置信的复杂性和错综复杂性的代理人,不断探索,不断学习。AlphaZero 向我们展示了人工大脑的发现如何为我们不断的好奇心提供灵感。还有许多其他领域,错综复杂的模式的相互作用丰富了我们的生活。有音乐(Deepfake 音乐开始听起来令人恼火的好)、诗歌、艺术、科学。
在这些领域中,我们可能过于执着于我们的理想,即创造性和有意义的意义。
AlphaZero 之所以如此伟大,正是因为它展示了人工智能可以为这种组合增加什么:而且人工智能不必剥夺我们相信让我们成为最具人性的人的快乐。





浙公网安备 33010602011771号