AI 如何让建筑变得更好?
建筑业在创新和生产率方面落后于其他行业。这篇文章探讨了人工智能可以帮助弥合差距的应用。
Digital assistant in construction (Illustration by author)
到 2030 年,世界将需要在基础设施和住房上花费 57 万亿美元,为从农村到城市的移民腾出空间。基础设施和建筑行业雇佣了全球 7%的劳动适龄人口,将承担大部分责任。然而,建筑行业有一个棘手的生产率障碍。大型项目通常比计划多花 20%的时间来完成,并超出预算高达 80%。在过去二十年中,建筑行业的劳动生产率停滞在 1%。承包商的财务回报通常相对较低且不稳定。同样令人担忧的是工人死亡的比例(所有其他部门中最高的)。
传统上,建筑业一直在进行渐进式改进。每个项目都是独一无二的,正因为如此,不可能扩大新想法的规模。采用新技术是不切实际的。在本帖中,我们将看看人工智能可以帮助该行业实现跨越的一些应用。
建设项目管理的可预见性。
在工程采购和合同领域,有太多的变量会导致执行失控。劳动力短缺、恶劣天气、供应中断和监管许可是导致项目管理固有可变性的一些参数。每个项目都被认为是独特的。这种标准化的缺乏使得过程数字化变得缓慢。日常报告、图纸、合同继续严重依赖基于纸张的通信。一线承包商和项目规划者之间的信息流不稳定且速度缓慢。一线承包商的计划范围通常仅限于未来 7 天。大多数项目管理是被动的。中高级工作人员从事日常消防应急工作。
我们可以使用机器学习来实现一天和一周的预测。每个站点都会得到一个活动列表,这些活动预计在该日期开始。实时仪表板列出了成本和时间超支的高风险活动。施工中的运营数据来源有限。但是,大多数站点记录项目成本的库存水平。类似地,项目进度也通过计划工具进行监控。人工智能可以将这些数据流编织在一起,并将它们与天气和历史表现结合起来,以预测未来的结果。它将使承包商和现场管理人员能够采取现实的观点和优先干预。
Using machine learning to forecast delays, list out activities likely to overrun budget and schedule(Illustration by author)
一线蓝领工人的个性化培训
过去二十年来,建筑业劳动生产率增长停滞不前。如果不对人力资本进行投资,该部门就不可能加速发展。与其他行业相比,建筑业的农民工比例很高。许多建筑移民和劳动力市场严重依赖的非正式招聘渠道是公平和安全工作环境的障碍。新加入者在最初的五到七年里做学徒。在此期间,当机会出现时,他们会改变交易。学徒工在经济上很脆弱,并陷入移民债务。大多数学徒工只懂当地方言,这一障碍限制了他们提高自身技能、理解自己的基本权利,甚至寻求技能认证的能力。
Personalized training in native language for frontline workmen (Illustration by author)
对话式人工智能彻底改变了训练。个性化语言学习应用已经教会超过 1 亿人一门新语言。建筑部门。例如,个性化机器人可以教育工人操作混凝土振动器,从而获得制造这种振动器的公司的认证。我们可以根据个人的学习进度和他的母语来定制课程。培训平台也可以取代目前使用的不透明的非正式渠道,成为寻找和招募人才的一种手段。它可以使招聘对工人和雇员都透明。
对于劳动力培训来说,合作是关键:政府、教育工作者、制造商和建筑公司。人工智能可以通过引入个性化、规模化和易于部署来扮演关键推动者的角色。
通过对象检测实现安全审计自动化
20%的工人死亡发生在建筑业。当你考虑到只有 7%的工人受雇于建筑行业时,这个统计数字就更加可怕了。自满的心态导致了受伤成为工作的一部分。安全部门经常人手不足:一个检查员管理着遍布工地的 500 名员工。
坠落、触电和倒塌占建筑行业所有工作场所事故的 60%。我们可以使用计算机视觉来检测导致此类事故的潜在条件。大多数项目都有监控摄像头来阻止盗窃。我们可以处理这个 feed 来检测边界框内的单个工人。随后,我们可以根据安全帽和安全带的存在与否对边界框进行分类。我们可以每分钟重复自动化过程,并记录所有不安全事件。我们还可以训练图像分类模型来检测正在执行的活动的性质,例如。钢筋弯曲、混凝土浇筑等。我们可以调整一个面罩-RCNN 来探测水溢出、障碍物和其他类似的不安全状况。所有此类事件和相关元数据在所有提要中聚合,相关人员会实时收到报告或警报,以便采取进一步的行动。
Aggregated unsafe incidents detected from surveillance footage. (Illustration by author)
存在局限性:错误检测、错误分类、视野中的障碍和弱光。目前,我们还不能完全自动化。但是,我们可以加强审计和合规性。我们可以将检查员的工作量减少 80%。这将使他有时间专注于训练和授权前线船员。
协作汇总合同,推动卓越发展
我们可以把建筑业大致分为两个部分。参与大型基础设施和住房项目的大型跨国公司,以及规模较小、分散的专业建筑商。分散单位的生产率通常是大单位的一半。较小公司执行的项目的财务回报和时间表仍不确定。
项目执行的一个重要组成部分是合同管理。我们应该根据标准对承包商进行评估,如过去的表现、财务状况、认证和 HSSE 合规性。较小的公司缺乏供应商网络,更不用说拥有管理复杂关系和合同的内部技能。低效的合同导致公司在一笔交易中损失价值的 5%到 40%之间。
零售电子商务同比增长 20%。到 2020 年,这一数字可能会超过 4.2 万亿美元。双边平台买方-卖方平台可以改变承包格局。美国初创企业、上市公司、跨国巨头正试图进入这一领域,以利用他们的物流、网络存在和对产品的深入了解。然而,此类平台缺少的关键方面是对签约中涉及的后端流程的支持。小型组织和部门需要工具来预算、预选、评估、管理投标、向卖方发出采购订单。一些较大的公司可能已有 ERP,需要集成到电子商务平台。现有的平台都没有提供这样的功能。
建筑公司将每个项目视为一项独特的努力。平台的力量来自于它组织和构造信息的能力。缺乏共享标准造成了额外的障碍。我们不能通过制定复杂的采购订单并要求人手不足的部门来填写来解决这个问题。
Using Entity Extraction on Contract Documents and preparing a relational database (Illustration by author)
今天,自然语言理解算法是几个应用程序的关键部分,从自动完成到处理保险索赔,再到垃圾邮件过滤器。除了财务数据之外,大多数建筑合同都是非结构化信息。如果我们需要组织这些信息,我们应该能够从非结构化的文本文档中提取信息。我们已经看到一些应用增强了准法律团队对法律文件的尽职调查能力。通过提取命名实体和关系,类似的方法将帮助我们组织项目间混乱的构造合同。平台上无障碍透明的交易将提高效率,降低成本。该平台可以利用从数百万类似交易中获得的知识来帮助编写合同规范,建立评估指南,匹配买家和卖家,并剔除不完整和模糊的订单。
B2B 电子商务规模巨大,大约是 B2C 的两倍。到 2020 年将达到 6 万亿美元。建筑合同在这一领域是一个未被充分利用的机会。
用摄影测量进行测量和检查
任何建设项目的首要活动之一就是土地测量。配备经纬仪的测量员将地形记录为网格点。在大型分散的基础设施项目中,这是一项在困难条件下的劳动和时间密集型活动。计算机视觉,即摄影测量已经彻底改变了这个领域。无人驾驶飞机携带的相机捕捉一系列图像,随后使用位置元数据对这些图像进行处理,以将其拼接成 3D 坐标阵列。在 8 小时的轮班中,一架无人机(带有额外的电池)可以覆盖勘测员在 2 个月内可以捕捉到的所有地形。在预设计阶段,时间是至关重要的,计算机视觉方法要快两个数量级,产生更高分辨率的 3D 网格,并且不会受到手动错误的影响。
Using 3D cameras to create an as-built point cloud |source Matterport
摄影测量的应用不仅限于测量。安装在固定装置上的 3D 摄像机可以生成建筑物的内部视图。我们可以将测量的竣工尺寸与原始设计进行比较,并自动检测偏差。在改装结构中,我们可以直接从 3D 视图中读取尺寸。我们还使用摄影测量对风力发电场和桥梁等资产进行维护审计。我们可以比较不同时间的结构维度,并检测异常应变。
这个领域的一些令人兴奋的工作已经朝着从 RGB 全景图像生成布局的方向发展。其他人使用立体和单目照片来估计景深。在一些最先进的方法中,精度水平大约是每米 5-10 厘米。我们还不能使用这些维度检查。然而,我们可以构建应用程序来使用来自智能手机的全景图像,导出房间布局,使用布局来呈现家具选项供房主选择。
From RGB image to 3D geometry to Furnishing and production drawings (Illustration by author)
建筑业颠覆的时机已经成熟。然而,存在着巨大的挑战。跨公司的数字化转型进展缓慢。除了试点规模的实施之外,创新的采用一直较为缓慢。数据透明度有限。在 b2c 领域,解决方案提供商必须介入并创建一个完整的垂直市场。
尽管如此,建筑行业提供了无与伦比的规模。如果我们耐心地微调用户体验,并达到产品与市场的契合,应用程序可以改变数百万人的生活。人工智能将在这些产品中发挥关键作用。
你经历过这篇文章中提到的建筑行业的一些挑战吗?我很想听听您对如何确定解决方案优先级的看法。你正在努力应对这些挑战吗?听听你的故事就好了。请在我的 LinkedIn 上留言。
反应最佳实践⚛
前端
您应该在 React 项目中遵循的 React 最佳实践
Photo by Mimi Thian on Unsplash
在 Sysco 实验室实习期间,我大量接触了 React Js。对于我们的项目,我们使用 React Js,并遵循 React 最佳实践。因此,我的团队领导和我的导师 Nadun Indunil 建议我写一写 React 最佳实践。这是我在 Medium 的第 25 篇文章。
反应⚛️
React 是一个用于开发用户界面的 JavaScript 库。 React 图书馆是脸书创建的。React 允许集成许多令人兴奋的组件、库和框架。诚然,开发者可以自己制作组件。
在最佳实践之前,我建议在开发 react 应用程序时使用测试驱动开发。测试驱动开发意味着先写一个测试,然后根据测试开发你的代码。更容易识别缺陷。如果当你发现一个 bug 时,你遵循另一个软件开发过程,首先写一个测试。
最佳实践
目录
- 文件组织
- 微小功能部件
- 复用组件
- 删除冗余代码
- 索引为键
- 不必要的<部门> s
- 仅必要的注释
- 理解为处理‘这个’
- 道具—状态—构造器
- 最终命名
- 感知状态和渲染
- 避免“设置状态”内的对象
- 使用上部骆驼案例名称
- 利用道具类型
- JavaScript 中的 CSS
- 测试
- 使用 ESLint、Prettier 和 snippet 库
- 使用 React 开发者工具
1.文件组织📂
文件组织不仅是 react 应用程序的最佳实践,也是其他应用程序的最佳实践。 create-react-app 的文件结构是组织 react 文件的一种可能方式。虽然不一定有一种文件结构比另一种更好,但保持文件有条理是很重要的。在 React 中,考虑到每个组件至少有一个与之相关联的文件,您的文件结构将快速增长。保存一个包含顶级 CSS、图像和字体文件的 资产 文件夹。维护一个 helpers 文件夹来存放其他文件的任何种类的文件功能。将与组件相关的所有文件保存在一个文件夹中。通常情况下, 组件 文件夹包含不止一个组件文件,比如测试文件 CSS 和一个或多个组件文件。如果有某个特定组件只使用的小组件,最好将这些小组件保存在 组件 文件夹中。当您将大型组件放在它们自己的文件夹中,而将组件使用的小型组件放在子文件夹中时,就更容易理解文件的层次结构。开发人员主要将文件中的主要组件文件命名为 index.js。如果有几个文件都命名为 index.js,这可能会变得很麻烦。解决方法是在每个组件文件夹中添加一个 package.json 文件,并为相应的文件夹设置主入口点。例如,对于 button 组件,主要入口点是 Button.js。将 package.json 添加到每个文件夹并不是一个好的做法,但它有助于轻松处理您的文件。所以我们可以在按钮组件文件夹中添加下面的 package.json 文件。
当你在 React 项目中使用 Redux 时,你可以根据你的项目使用 Rails 风格 或 Domain 风格 或 【鸭子】 模式文件夹结构。在 Rails 风格的 模式中,单独的文件夹用于“动作”、“常量”、“缩减器”、“容器”和“组件”。在 域风格 模式中,每个特征或域使用单独的文件夹,每个文件类型可能有子文件夹。***【Ducks】***模式类似于领域风格,但是它明确地将动作和 reducers 联系在一起,通常是通过在同一个文件中定义它们。然而,文件夹结构可能是开发人员所希望的,但是应该有一种简单的方法来处理组件。React 说,它对你如何将文件放入文件夹没有意见。新队伍使用鸭式反应。当他们变得成熟时,他们开始使用 rails。Rails 具有易于理解项目的优势。
丹·阿布拉莫夫在推特上发布了一个解决方案👉
移动文件,直到感觉合适为止。
这正是你应该做的。你应该移动文件,直到他们觉得合适。
2.微小功能元件🤏
众所周知,React 可以处理大型组件。但是如果我们把它们分成小块,我们可以重复使用它们。小组件更容易阅读、测试、维护和重用。大多数 React 初学者创建类组件,即使他们没有使用组件状态或生命周期方法。功能组件对于简单组件来说效率更高。
上面的类组件可以编写如下。
使用功能组件的优势。
- 较少代码
- 更容易理解
- 无国籍的
- 更容易测试
- 没有
this
绑定。 - 更容易提取更小的成分。
当您使用功能组件时,您无法控制重新渲染过程。当某些东西改变甚至组件自身改变时,React 会重新渲染功能组件。在以前的 react 版本中有一个解决方案可以使用React.PureComponent
。PureComponent 允许浅层 props 和状态比较。当组件的道具或内容或组件本身发生变化时,组件会重新呈现。否则,PureComponent 跳过重新渲染,而是重用最后一次渲染的结果。
React v16.6.0 之后 React 引入了一个新特性,那就是备忘录。Memo 浅比道具。当组件的道具或内容或组件本身发生变化时,组件会重新呈现。根据比较结果,react 将重用上次渲染的结果或重新渲染。Memo 允许你创建一个纯粹的功能组件。Memo 抹杀了有状态组件和PureComponent
的使用。
Components, Picture credit: https://www.kirupa.com/react/images/c_app_144.png
3.可重用组件♻️
每个功能组件应该有一个功能,这意味着一个功能组件等于一个功能。当你创建一个具有一个功能的功能组件时,你可以提高组件的可重用性。
4.删除冗余代码🗑️
不仅在 React 中,而且在所有应用程序开发中,通用规则是尽可能保持代码简洁。反应最佳实践指示保持无错代码和精确代码。不要重复你自己(DRY)是软件开发的一个原则,专注于最大限度地减少软件模式的重复,用抽象来代替它,或者使用数据规范化来避免冗余。在代码设计中,你可以使用你自己的风格指南,或者使用一个流行的成熟的风格指南( Airbnb React/JSX 风格指南、脸书风格指南等等)。如果你开始追随任何一种风格的人,不要和其他人混淆。
Picture credit: https://quotefancy.com/quote/46568/Lemony-Snicket-Don-t-repeat-yourself-It-s-not-only-repetitive-it-s-redundant-and-people
5.作为关键字的索引🔑
当创建一个 JSX 元素的数组时,react 要求你给你的元素添加一个关键道具。这通常是通过使用映射函数来完成的,而映射函数又会导致人们使用索引来设置键属性。这太糟糕了!React 使用 key 属性来跟踪数组中的每个元素,并且由于数组的折叠性质。这很容易导致错误的信息出现在错误的地方。这在用状态循环遍历类组件时尤其明显。
6.不必要的🚫
当创建 React 组件时,记住您仍然在构建 HTML 文档是很重要的。人们倾向于在 React 中使用divitis
,最终导致不正确的 HTML。
在上面的例子中,div
是ul
的直接子节点,这是不正确的 HTML,而在下面的例子中,li
是ul
的直接子节点,这是正确的 HTML。
我们可以使用另一种使用<React.Fragment>
标签的方法。<React.Fragment>
是在 React v16.2 中引入的,我们可以用它们来代替无关的<div>
标签。
7.仅必要的注释📝
必要时在应用程序中添加注释。从应用程序中移除注释的能力意味着我必须编写有文化的代码,没有例外。它给出了混乱的自由代码段。一般来说,注释是糟糕设计的一个标志,尤其是冗长的注释,很明显开发者不知道他们在做什么,试图通过写注释来弥补。
Picture credit: https://www.toptal.com/sql/guide-to-data-synchronization-in-microsoft-sql-server
8.理解处理“这个”👆
因为功能组件不需要this
绑定,所以只要有可能,你就会想要使用它们。但是如果你使用的是 ES6 类,你需要手动绑定它,因为 React 不会自动绑定组件中的函数。这里有一些这样做的例子。
例 1:绑定渲染
将以下代码片段添加到名为 bind in render 的渲染中
onClick={this.logMessage.bind(this)}
这种方式清晰、简洁且可行,但可能会导致轻微的性能问题,因为每次组件重新渲染时都会调用新的函数,这可能会很频繁。
例 2:渲染中的箭头功能。
将以下代码片段添加到 render 中名为 arrow function 的渲染中。
onClick={() **=>** this.logMessage()}
这种方式清晰、简洁,就像示例 1 一样,但是像示例 1 一样,它也会在每次组件呈现时创建一个新函数。
例 3:绑定构造函数
将以下代码片段添加到名为 bind in constructor 的构造函数中。
this.logMessage = this.logMessage.bind(this);
这种方法将解决示例 1 和示例 2 的潜在性能问题。不要忘记在构造函数中调用 super。
例 4:类属性 中的箭头函数
将以下代码片段添加到类属性中名为 arrow function 的类中。
logMessage = () **=>** {
**const** { message } = this.state;
console.log(message);
}
这种方式非常简洁、易读,它将避免例 1 和例 2 中的性能问题,并避免例 3 中的重复。但是要注意,这种方法依赖于实验特性,它不是 ECMA 脚本规范的正式部分。您可以通过安装和配置 babel 包来试验语言功能,create react 应用程序创建的应用程序启用了许多功能。
Picture credit: https://codeburst.io/javascript-arrow-functions-for-beginners-926947fc0cdc
9.道具-状态-构造器🏁
我们可以把标题分成两个子标题,如。
- 初始状态的时候不要用道具。
- 不要在类构造函数内部初始化组件状态。
当你在初始状态使用 props 时,问题是当组件被创建时构造函数被调用。所以构造函数只被调用一次。如果您下次对 props 进行更改,组件状态将不会更新,它将保持与以前的值相同。您可以使用 react 生命周期方法componentDidUpdate
来解决这个问题。当属性改变时,componentDidUpdate
方法更新组件。componentDidUpdate
在初始渲染时不会被调用。但是,在初始状态下使用道具并不是最好的做法。
将状态初始化为类字段是最佳实践。用构造函数初始化组件状态并没有那么糟糕,但是它增加了代码中的冗余,并产生了一些性能问题。当你初始化类构造函数内部的状态时,它会不必要地调用 super 并记住 props,这会造成性能问题。
另一个问题是,当你要在构造函数中初始化状态时,想想你需要多少行,你需要constructor()
,super()
?
Picture credit: https://indepth.dev/in-depth-explanation-of-state-and-props-update-in-react/
10.最终命名🔚
键入脚本后命名一个函数或组件,因为它们应该易于识别。比如你因为组件代码,瞬间选择了FacebookButton
这样的组件名称。但是将来你可能会用那个组件作为TwitterButton
、YoutubeButton
。因此,最佳实践是将该组件命名为Button
。通常,当您完成函数时,您应该能够为组件和函数选择通用名称。最后命名增加了可重用性。
11.意识到状态和渲染🎭
在 React 中,我们可以根据状态对组件进行分类。有 有状态 和 无状态 。有状态组件存储组件的状态信息,并提供必要的上下文。反过来,无状态组件没有内存,也不能给用户界面部分提供上下文。无状态组件是可伸缩的、可重用的,就像纯 JavaScript 函数一样。将有状态提取逻辑与呈现无状态逻辑分开。一个更好的方法是使用有状态组件获取数据,使用另一个无状态组件显示获取的数据。
在 React v16.08 之后有一个新特性叫做“React Hooks”。React 钩子编写有状态的功能组件。React 钩子取消了类组件的使用。
如果数据没有在 render 方法中直接呈现,它就不应该处于组件状态。未直接呈现的数据可能会导致不必要的重新呈现。
Picture credit: https://www.barrymichaeldoyle.com/sub-rendering/
12.避免“setstate”🛑内的对象
根据 React 文档 React 不保证立即应用阶段更改。因此,在调用setState
之后立即读取this.state
是一个潜在的陷阱,因为this.state
实际上可能不是你所想的那样。
**const** { ischecked } = this.state;
this.setState({ischecked: !ischecked});
我们可以使用下面的函数,而不是像上面的代码片段那样更新对象的状态。
this .setState((prevState, props) => {
return {ischecked: !prevState.ischecked}
})
上面的函数将接收先前的状态作为它的第一个参数,并将应用更新时的props
作为它的第二个参数。状态更新是异步操作,所以要更新状态对象,我们需要使用带有setState
的 updater 函数。
13.使用大写骆驼名称🐪
当你在 React 中工作时,记住你使用的是 JSX (JavaScript 扩展)而不是 HTML。你创建的组件应该用上驼格命名,又名 帕斯卡格 。大写骆驼字母表示单词书写时没有空格,每个单词的第一个字母大写。例如,如果有一个名为selectbutton
的组件,那么你应该将其命名为SelectButton
而不是selectbutton
。使用大写骆驼有助于 JSX 区分默认的 JSX 元素标签和创建的元素。但是,您可以使用小写字母来命名组件,但这不是最佳做法。
Photo by Artem Sapegin on Unsplash
14.利用支柱型🧪
“prop-types”是一个用于类型检查道具的库,它可以通过确保你为你的道具使用正确的数据类型来帮助防止错误。React.PropTypes
从 React v15.5 开始,已经转移到一个不同的包中。React.PropTypes
包让我们能够对组件的属性进行类型检查,并赋予它默认值。因此,npm install 将使用一个外部库。
npm i prop-types
导入库,添加PropTypes
到组件,相应地设置数据类型,如果需要道具,添加isRequired
,如下所示。
可以使用defaultProps
将默认值分配给属性。当一个组件没有收到它的道具时,它指的是已经赋值的defaultProps
。如果你已经按要求标记了你的道具,就不需要分配defaultProps
。在下面的代码片段中,您可以看到所有已经分配给 ModalButton 的属性的默认值。对于这个例子,我使用了 React Bootstrap 框架。
始终为所有可选属性定义显式 defaultProps
需要注意的是,做类型检查时使用PropsTypes
后赋值defaultProps
*。*因此,它也对分配给属性的默认值进行类型检查。
15.JavaScript 中的 CSS💅
在我的实习工作中,我们面临一个造型问题,尤其是主题。CSS 已在开发环境中加载,但没有在生产环境中加载。我的队友哈里斯·桑卡帕写了那个问题。但是现在我根据不同的应用找到了这么多最好的方法。
当你有一个大的 CSS (SCSS)文件时,你可以使用全局前缀,后跟块-元素-修饰符约定来避免名字冲突。当您的应用程序变得更大时,这种方法是不可伸缩的。所以你必须评估你的 CSS(SCSS)文件。还有另一种通过 webpack 的迷你 CSS 提取文本插件提取 CSS 的方法(它需要 webpack 4 才能工作),但它对 webpack 产生了严重的依赖性。如果你使用这种方法,测试你的组件是困难的。最佳实践是拥有一个易于测试的应用程序,因此,遵循这种方法并不是最佳实践。
EmotionJS 、laminate和 Styled Components 是 JS 库中的一些新 CSS。您可以根据您的用例来使用它们。当你需要生成一个编译好的 CSS 时,你可以使用 EmotionJS 库。当你有一个复杂的主题问题时,你可以使用迷人的和风格化的组件库。
Picture credit: https://wordpress.org/plugins/custom-css-js/
16.测试🚀
不仅在 React 中,在其他编程语言中也应该进行测试。测试是很重要的,因为它确保代码如预期的那样运行,并且可以简单快速地测试。在最佳实践中,在组件文件夹中创建一个__Test__
文件夹。用组件名加上一个.test.js
后缀来创建测试文件。您可以将 Jest 用作测试程序,将 Enzyme 用作 React 的测试工具。我的队友卡温杜文迪卡写了关于的笑话和酶测试,如果你想你可以看看。
对组件进行崩溃测试是一种简单快速的方法,可以确保所有组件都正常工作而不会崩溃。组件崩溃测试很容易应用到你制作的每个组件中。
你应该做明显比碰撞测试更广泛的测试。如果你写更多的测试用例,它会给你的代码更多的测试覆盖率。但是,至少你应该做一些碰撞测试。在崩溃测试中,我们所做的是创建一个元素,然后它使用 ReactDom 并装载您导入到刚刚创建的 div 中的任何组件,然后它卸载 div。
一个真正的 react 开发人员会对整个 React 应用程序进行适当的测试。
17.使用 ESLint、Prettier 和 snippet 库📚
ESlint 用歪歪扭扭的字体对你大喊大叫,让你的代码保持整洁。您可以将它链接到您的 IDE。最佳实践是保留您自己的 ESLint 配置文件。
一个好的开发人员会修复所有的 ESlint 错误和警告,而不是禁用那个错误。
更漂亮是一个代码格式化工具。漂亮有一套代码格式和缩进的规则。您可以使用 Sonarlint 来检查法术、功能长度和更好方法的建议。使用 Husky 不仅对 React 是一个好的实践,对 Git 也是一个好的实践。可以在 package.json 文件中定义哈士奇。Husky 防止您的应用程序出现错误提交和错误推送。
代码片段有助于您编写最佳代码和趋势语法。它们使你的代码相对没有错误。你可以使用很多代码片段库,比如 ES7 React,JavaScript (ES6)代码片段等。
Picture credit: https://medium.com/dubizzletechblog/setting-up-prettier-and-eslint-for-js-and-react-apps-bbc779d29062
18.使用 React 开发工具🛠️
React Developer Tools 是 Chrome 和 Firefox 的扩展。如果您使用 Safari 或其他独立 shell,请使用以下命令来安装它。
npm install -g react-devtools@^4
如果您正在寻找 React 中内置的 web 应用程序,您可以在 Components 选项卡中看到组件层次结构。如果您点击一个组件,您可以查看该组件的属性和状态。如你所见,React Developer Tools extension 是一款非常有价值的工具,可用于测试和调试,并真正了解该应用程序发生了什么。
结论✌️
本文描述了 React 中的最佳实践。这些实践提高了您的应用程序性能、应用程序代码和编码技能。作为我的第 25 篇文章,我想动态更新这篇文章。这意味着我会用新的趋势来更新这篇文章。如果我更新这篇文章,我会通过推特通知。保持联系。呜哇!!!🙌
快乐编码😎
关注我的Twitter和 Medium 如果你将来对这些更深入、更翔实的文章感兴趣的话!
React Native 推出其最新版本 0.60
React Native 是最受欢迎的移动应用程序开发框架之一,它的高级特性和创建功能丰富的跨平台移动应用程序的能力一直吸引着开发者和企业。
凭借其显著的特性,这种混合应用程序开发框架比其他框架节省了创建应用程序的时间。它有助于减少大约 40%到 50%的移动应用程序开发费用。
经过几个月的努力和奉献,近日,React Native 宣布推出最新版本 0.60。如今,用户很高兴看到 React Native 新版本的每个功能。根据 Stack Overflow 调查,React native 是目前第二受欢迎的框架:
下面我们来了解一下 React 原生 0.60 的各种新特性:
React Native 的最新版本可以处理 Android 和 iOS 平台的各种重要迁移,旧版本 0.59 中的其他小问题也通过最新更新得到了解决,以提供更好的用户界面和体验。
以下是最新的 React 原生 0.60 中的一些其他变化:
可访问性的改进
最新的 0.60 版本发布了针对 Android 和 iOS 的可访问性 API 前端的多项改进。所有的改进虽然范围很广,但都包含了一些元素,例如宣布可访问性,以及角色、动作支持、标志等方面的改进。react native 的开发团队希望,随着这些进步,成为 A11Y(可访问性的数字符号)会更容易。Reach Native 0.60 在可访问性方面有更多改进,包括:
为各种元素包含过多的缺失角色,以便根据需求有效地使用它。
包括点击回叫和一个可点击的道具,有助于使用键盘导航来请求操作。
通过最新的可访问性状态 API,保证在未来的运行中增强 web 协助。
启用最大的可访问性操作,以便添加回调来处理用户特定的功能可访问性。
最新的 0.60 版本引入了大量的改进,同时引入了一些元素,如宣布可访问性、动作支持改进、标志和角色等等。
所有新屏幕
React 的最新版本带有新的应用程序屏幕,据称更加用户友好。它显示了有用的说明,例如文档链接,编辑 App.js,如何启动调试菜单,以及最后如何与即将到来的网站设计和重新设计保持一致。新的用户界面“Hello world”将以更好的方式向手机用户介绍生态系统。
支持 AndroidX
随着 React Native 与 Android 扩展库(AndroidX)的迁移,原生代码和依赖项也应该迁移。由于这种转变,所有的 React 原生应用将不得不自己使用 AndroidX。虽然,React Native 的开发团队已经针对这个问题开发了一个名为“Jetifier”的临时解决方案。它是一个 AndroidX 过渡工具,风格与 React Native 兼容。
操作系统自动链接
React Native 的库通常由本机代码和特定于平台的代码组成。这种新机制还允许您的项目发现并再次使用该代码。React Native 的 CLI 团队在自动链接中引入了类似这样的重大改进。
CocoaPods 作为 iOS 的一部分
CocoaPods 是一个应用级依赖管理器,是为 Objective-C Cocoa 项目和 Swift 设计的。现在,React Native 在 iOS 中默认自带 CocoaPods。现在要求手机 app 开发者使用“xcworkspace”文件打开 iOS 开发平台 代码。
精益旧件移除
React Native 的新变化包括将 NetInfo 和 Webview 放在单独的存储库中。它们已从 React Native 的存储库中成功删除。此外,基于社区反馈,地理定位已被移除。
升级助手
React native 的开发人员构建了一个名为“升级助手”的伟大工具,以使升级过程变得非常简单。它还可以帮助用户对棕色地带应用程序或复杂的自定义应用程序进行本地反应,以了解它们的版本之间发生了哪些变化。快速浏览最新的升级文档。
给库维护者的一个快速提示
AndroidX 的所有改动几乎都需要更新库,所以请务必尽快加入支持。如果您还不能升级您的版本,您可以考虑根据 Jetifier 检查库,以便确认用户可以在构建时修补您的库。
您还可以查看自动链接文档,以更新您的自述文件和配置。根据之前库的集成方式,您可能需要进行一些额外的更改。为此,您可以从 CLI 查看依赖关系指南,了解定义依赖关系接口的不同方法的信息。
让我们总结一下:
脸书创始人马克·扎克伯格在 2012 年评论说,“作为一家公司,我们犯的最大错误之一是在 HTML 而不是原生语言上下了太多赌注”。基于以上陈述,我们可以得出结论,React 原生框架比其他选择更好。你不必相信我们的话,因为你可以通过事实自己看出来。随着 react native 的最新更新,我们可以看到对该平台的需求不断增长,其用户群可能会随着时间的推移而增强。
除此之外,为 Android 和 iOS 构建的移动应用在这两个平台上将保持相似。对于未来,预测这种混合型 手机 app 开发平台 点播会更高。此外,随着时间的推移,其用户基础可能会有所改善。
react native 的最新进步引发了在印度雇佣最佳移动应用程序开发公司的需求,因为大多数 软件开发公司 将 react native 作为其跨平台应用程序开发的首选。如果你也在寻找 react 本地开发解决方案,你可以联系这些公司,你会得到你所需要的最好的服务。
反应扩散模型与数据可视化
在科学界,模型是一个概念的表示,可以用来模拟和帮助描述一个想法。如果模型足够接近真实世界,它也可以用来预测在一系列条件下会发生什么。常见的一种模型表示是天气图,如下所示。
National Centers for Environmental Prediction [Public domain], via Wikimedia Commons
天气图是天气模型的可视化表示。天气模型接收许多位置的输入,如温度、压力、风速和其他参数,在处理这些信息后,它可用于描述和预测天气。模型要考虑的另一个方面是它们可能是错误的。任何根据天气预报出门时不打伞的人都知道这一点。因此,记住模型通常是真实世界的不完美再现是很重要的。然而,这并不意味着它们没有用处。
例如,当一个物理系统被很好地理解时,可以开发一个模型来允许系统内的实验在虚拟环境中运行。这使得科学家能够探索系统参数的变化,这可能允许他们发现给定目标的最佳条件集。人们可能选择创建模型而不是在系统上进行物理实验的原因是,在探索最佳系统条件的任务中,收集一系列参数的足够数据常常是昂贵且耗时的。一个这样的系统是反应扩散模型。
涉及反应和扩散的化学系统具有许多变量,并且当涉及的组件是昂贵的时,在整个参数域上运行试验是不可行的。这种类型的系统的一个模型将在这篇文章中介绍。具体来说,本文中的模型将代表发生在立方体化学阱中的反应和扩散,其中活性位点吸附在阱的壁和底部。这些井与下图中的井相似,但几何形状将是立方体而不是圆柱形。井的表面充满了反应位点,井溶液中的化学物质与这些位点相互作用。
Obtained from Wikimedia Commons
Obtained from https://www.hitbullseye.com
反应空间是一个立方体,它将被分成更小的立方体,就像左边的立方体一样。大立方体的尺寸将是 10×10×10 的小立方体,以下称为单元。该模型将通过开发一个具有四个维度的数组来工作:x、y、z 和 t。这四个维度分别代表 x、y 和 z 空间维度以及时间维度。每个数组索引的值将代表该空间和时间的浓度。
毫不奇怪,反应扩散模型中的两个重要因素是反应和扩散。反应只发生在井壁,但扩散发生在整个系统。反应后,化学物质被认为是从系统中清除。扩散后,化学品从一个井移动到另一个井,但不会从系统中移除。
首先,必须用初始条件来定义系统。这些包括扩散常数、每个单元边的长度、模拟时间的长度、时间步长的长度、单元的初始浓度、初始井表面位置浓度、吸附和解吸的速率常数以及吸附的化学物质的初始浓度。
在时间 0,所有细胞都等于初始浓度。下一个时间步骤的细胞浓度是通过从每个细胞中去除由于反应而损失的化学物质,并基于感兴趣的细胞和所有相邻细胞之间的浓度差计算来自扩散的细胞浓度变化来计算的。完成此任务的 python 代码如下所示。
"""
D = Diffusivity constant in m^2/s
r = length of each dimension of cubic well in meters
n = number of partitions in each dimension of cubic well
tf = length of time of simulation
dt = numerical integration time step
initial_conc = initial concentraion of well solution
dx = r/n
nt = tf/dt
xrn is in moles per time
Aconc and Sconc are in moles per m^2
k_des is in per time
k_ad is in per M per t
dx is in m
rxnDMtot is total change in cube molarity due to reaction"""
stracker = 0
D = 1 * 10 ** -5
r = 0.0048
tf = 0.1
dt = 0.000001
n = 10
nt = int(tf / dt)
dx = r/n
initial_conc = 2.5 * 10 ** -5
import numpy as np
conc = np.zeros([n,n,n,nt+5])
for i in range(0, n):
for j in range(0, n):
for k in range(0, n):
conc[i, j, k, 0] += initial_conc
#print(conc)
Sconc = 1 * 10 ** -8 #surface site concentration
Aconc = np.zeros([nt+6]) #adsorbed concentration
Dfactor = D *dt/(dx ** 2)
k_ad = 1 * 10 ** 7
k_des = 1 * 10 ** -6
Sconc = 1
Aconc[0] = 0
time_list = []
Aconc_list = []
SminusA_conc_list = []
for t in range(0, nt + 6):
for i in range(0, n):
for j in range(0,n):
for k in range(0,n):
#start of neighbor unit diffusion calculations
if i == n - 1:
xposdiff = 0
else:
xposdiff = Dfactor * (conc[i + 1, j, k, t] - conc[i, j, k, t])if i == 0:
xnegdiff = 0
else:
xnegdiff = Dfactor * (conc[i - 1, j, k, t] - conc[i, j, k, t])
if j == n - 1:
yposdiff = 0
else:
yposdiff = Dfactor * (conc[i, j + 1, k, t] - conc[i, k, k, t])
if j == 0:
ynegdiff = 0
else:
ynegdiff = Dfactor * (conc[i, j - 1, k, t] - conc[i, j, k, t])
if k == n - 1:
zposdiff = 0
else:
zposdiff = Dfactor * (conc[i, j, k + 1, t] - conc[i, j, k, t])
if k == 0:
znegdiff = 0
else:
znegdiff = Dfactor * (conc[i, j, k - 1, t] - conc[i, j, k, t])
#end of neighbor unit diffusion calculations
#start of neighbor unit reaction calculations
if i == 0 or i == n - 1:
xrxn = dx ** 2 * (k_ad * conc[i, j, k, t] * (Sconc - Aconc[t]) - k_des * Aconc[t]) #xrn is in moles per time, Aconc and Sconc are in moles per m^2, k_des is in per time, k_ad is in per M per t, dx is in m
else:
xrxn = 0
if j == 0 or j == n - 1:
yrxn = dx ** 2 * (k_ad * conc[i, j, k, t] * (Sconc - Aconc[t]) - k_des * Aconc[t])
else:
yrxn = 0if k == 0:
zrxn = dx ** 2 * (k_ad * conc[i, j, k, t] * (Sconc - Aconc[t]) - k_des * Aconc[t])
else:
zrxn = 0
#end of neighbor unit reaction calculations#calculates total molarity change due to reactions
rxnDMtot = -(xrxn + yrxn + zrxn) * dt / (dx * 10) ** 3 #total change in cube molarity due to reaction#limits change in concentration due to reaction because time step minimization is limited by processing power
if rxnDMtot < -1 * conc[i, j, k, t]:
rxnDMtot = -1 * conc[i, j, k, t]
#keeps track of the surface site concentration
stracker = stracker - rxnDMtot * (dx * 10) ** 3#uses the current unit concentration and the reaction and diffusion changes to calculate the unit concentration at the next time step
conc[i, j, k, t + 1] = conc[i, j, k, t] + xposdiff + xnegdiff + yposdiff + ynegdiff + zposdiff + znegdiff + rxnDMtot
Aconc[t + 1] = Aconc[t] + stracker / (5 * r ** 2)
stracker = 0
time_list.append(t * dt)
Aconc_list.append(Aconc[t])
SminusA_conc_list.append(Sconc - Aconc[t])for i in range(0, n):
for j in range(0,n):
for k in range(0,n):
totalconc = totalconc + conc[i, j, k, nt] * (dx * 10) ** 3totalconc = totalconc / ((r * 10) ** 3)
totalconc = totalconc + Aconc[nt] * 5 * r ** 2 / (r * 10) ** 3
我承担这个项目的主要原因之一是因为我想发展我使用 python 呈现信息的技能。显示包含细胞浓度的四维数组将需要五维来显示三个空间维度、浓度和时间。这可以通过三维动画热图来实现。我可能会回到这个项目来完成显示所有的信息在稍后的时间。目前,我已经开发了 gif,使用了 z 维度固定的细胞浓度的等间隔时间快照。这意味着 x 和 y 轴将代表细胞在 x 和 y 方向上的位置,垂直轴将代表每个细胞的浓度,时间维度将由动画表示。显示的 z 坐标显示在每个 gif 下面。
The second from the bottom layer (z = 1)
The fourth from the base (z = 3)
你可以看到反应空间两侧细胞中的浓度立即下降到零。我们将这些细胞称为壁细胞,因为它们与反应空间的壁接触。壁细胞中的浓度比内部细胞下降更快的原因是因为壁细胞是唯一由于反应而损失浓度的细胞。扩散导致溶质从高浓度流向低浓度。由于浓度高于壁细胞,扩散导致内部细胞的浓度在反应开始后开始下降,因为溶质向壁净转移。
不幸的是,这不是一个完美的模型,因为有更复杂的方法来更准确地描述这个系统,而且时间步长不够小,不能准确地反映现实。
承认
约翰·罗勃兹,因为他开发了最初的 VBA 模型。
卢克·博尔斯对他在图形开发方面的协助表示感谢。
芳芳,凯文和卡罗琳的指导。
图形和 Gif 生成 Python 代码
import matplotlib
!pip install imageio
import mpl_toolkits
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
!pip install --upgrade matplotlibdef plot_looper(snapshot_number, z_level):
#this will only work correctly with n = 10
t = 0
file_title = 'z'
while t < tf / dt:
fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
X = [[0,1,2,3,4,5,6,7,8,9],[9,0,1,2,3,4,5,6,7,8],[8,9,0,1,2,3,4,5,6,7],[7,8,9,0,1,2,3,4,5,6],[6,7,8,9,0,1,2,3,4,5],[5,6,7,8,9,0,1,2,3,4],[4,5,6,7,8,9,0,1,2,3],[3,4,5,6,7,8,9,0,1,2],[2,3,4,5,6,7,8,9,0,1],[1,2,3,4,5,6,7,8,9,0]]
Y = [[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9]]
Z = conc[X,Y,z_level, t]
file_title += 'z'
ax.scatter(X, Y, Z, c = 'r', marker = 'o')
fig.savefig(f'model_image{file_title}'.format('PATH/x'))
print(t)
t += 1000
import os
import imageio
png_dir = 'PATH/Model_Images'
images = []
for file_name in os.listdir(png_dir):
if file_name.endswith('.png'):
file_path = os.path.join(png_dir, file_name)
images.append(imageio.imread(file_path))
imageio.mimsave('PATH/model.gif', images)
用一行 Python 代码从图像中读取文本
处理图像不是一件小事。对你来说,作为一个人,很容易看到某样东西,并立即知道你在看什么。但是电脑不是这样工作的。
Photo by Lenin Estrada on Unsplash
对你来说太难的任务,像复杂的算术和一般的数学,是计算机不费吹灰之力就能完成的。但是在这里正好相反适用于——对你来说微不足道的任务,比如识别图像中是猫还是狗,对计算机来说真的很难。在某种程度上,我们是天造地设的一对。至少现在是这样。
虽然图像分类和涉及某种程度的计算机视觉的任务可能需要一些代码和扎实的理解,但从某种程度上格式良好的图像中读取文本却是 Python 中的一行程序——可以应用于许多现实生活中的问题。
在今天的帖子中,我想证明这一点。虽然还有一些安装工作要做,但应该不会花太多时间。这些是您需要的库:
- OpenCV
- 宇宙魔方
我不想再长篇大论这个介绍部分了,所以我们现在为什么不进入正题呢?
OpenCV
现在,这个库将只用于加载图像,你实际上不需要事先对它有一个坚实的理解(虽然它可能是有帮助的,你会看到为什么)。
根据官方文件:
OpenCV(开源计算机视觉库)是一个开源的计算机视觉和机器学习软件库。OpenCV 旨在为计算机视觉应用提供一个公共基础设施,并加速机器感知在商业产品中的应用。作为一个 BSD 许可的产品,OpenCV 使得企业利用和修改代码变得很容易。[1]
简而言之,你可以使用 OpenCV 做任何种类的图像转换,这是一个相当简单的库。
如果您还没有安装它,它将只是终端中的一行:
pip install opencv-python
差不多就是这样。到目前为止,这很容易,但这种情况即将改变。
宇宙魔方
这到底是什么库? 嗯,根据维基百科:
Tesseract 是用于各种操作系统的光学字符识别引擎。它是自由软件,在 Apache 许可下发布,版本 2.0,自 2006 年以来一直由 Google 赞助开发。[2]
我确信现在有更复杂的库可用,但是我发现这个运行得很好。根据我自己的经验,这个库应该能够读取任何图像中的文本,前提是字体不是一些连你都无法读取的粗体字。
如果它不能读取你的图像,花更多的时间玩 OpenCV,应用各种过滤器使文本突出。
现在安装有点底层的痛苦。如果你使用的是 Linux,这可以归结为几个 sudo-apt get 命令:
sudo apt-get update
sudo apt-get install tesseract-ocr
sudo apt-get install libtesseract-dev
我用的是 Windows,所以这个过程有点繁琐。
首先,打开这个 URL ,下载 32 位或 64 位安装程序:
安装本身很简单,归结起来就是点击几次 下一个 。是的,你还需要做一个 pip 安装:
pip install pytesseract
就这些吗? 嗯,不是,你还是要告诉 Python 宇宙魔方安装在哪里。在 Linux 机器上,我不需要这样做,但是在 Windows 上是必须的。默认安装在 程序文件 中。
如果您做的一切都是正确的,那么执行这个单元格应该不会产生任何错误:
一切都好吗?你可以继续了。
阅读课文
先说一个简单的。我发现了几个包含某种文字的免版税图片,第一个是这样的:
这应该是最简单的,并且有可能宇宙魔方会把那些蓝色的“物体”读成括号。让我们看看会发生什么:
我的主张是真实的。不过这不是问题,你可以用 Python 的魔法轻松解决这些问题。
下一个可能更棘手:
https://live.staticflickr.com/7892/46879778504_3b11c328b0_b.jpg
我希望它不会发现硬币上“B ”:
看起来效果很好。
现在就看你把这个应用到你自己的问题上了。如果文本与背景融为一体,OpenCV 技巧在这里可能至关重要。
在你离开之前
对于计算机来说,从图像中读取文本是一项非常困难的任务。想想看,计算机不知道什么是字母,它只对数字起作用。在引擎盖后面发生的事情起初可能看起来像一个黑箱,但是如果这是你感兴趣的领域,我鼓励你进一步调查。
我不是说 PyTesseract 每次都能完美地工作,但是我发现它甚至在一些复杂的图像上也足够好了。但不是直接从盒子里拿出来的。需要一些图像处理来突出文本。
我知道这是个复杂的话题。过一天算一天。总有一天它会成为你的第二天性。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
参考
[2]https://en . Wikipedia . org/wiki/tessera CT _(软件)
读者选择的 10 篇最佳数据文章
数据科学收藏中您最喜欢的博客文章
我问社区,这个博客的哪些文章特别能引起他们的共鸣…下面是列表!
Image from the 1927 film Metropolis.
AI:用更多的精力更快地做蠢事!
头发尖尖的老板是启示录……中的四骑士之一
在数据推动的时代,我们为什么需要新一代的领导者
towardsdatascience.com](/artificial-intelligence-do-stupid-things-faster-with-more-energy-379aa6bac220)
#9 注意窗帘后面的那个男人
数学会掩盖人的因素,给人一种客观的错觉
人工智能偏见和公平的严酷事实
medium.com](https://medium.com/hackernoon/ai-bias-and-what-you-can-do-about-it-4a6ae48b338e)
#8 数据驱动?再想想
如果没有决策基础,你的决策最多会受到数据的启发,而不是由数据驱动 …
大多数人缺乏的心理习惯以及为什么你不能希望用数据有效地指导你的行动而不…
medium.com](https://medium.com/hackernoon/data-inspired-5c78db3999b2)
#7 为什么企业在机器学习上失败
当谈到机器学习时,许多组织都做错了生意 …
我想告诉你一个秘密:当人们说“机器学习”时,听起来好像这里只有一个学科…
medium.com](https://medium.com/hackernoon/why-businesses-fail-at-machine-learning-fbff41c4d5db)
#6 你读过的关于机器学习的最简单的解释
机器学习是一种新的编程范式,一种向计算机传达你的愿望的新方式
你可能听说过机器学习和人工智能,但你确定你知道它们是什么吗?如果…
medium.com](https://medium.com/hackernoon/the-simplest-explanation-of-machine-learning-youll-ever-read-bebc0700047c)
#5 分析和统计有什么区别?
分析帮助你形成假设。它提高了你的问题的质量。统计学帮助你测试假设。它提高了你答案的质量 …
理解两种完全不同职业的价值
towardsdatascience.com](/whats-the-difference-between-analytics-and-statistics-cd35d457e17)
#4 数据科学到底是什么?
请看我最精辟的尝试:“数据科学是让数据变得有用的学科”现在可以随意逃离或者逗留在它的三个分区域 …
寻求一个有用的定义
bit.ly](http://bit.ly/quaesita_datasci)
#3 对匆忙人群的统计
简而言之,测试:“我们的证据让零假设看起来可笑吗?” …
曾经希望有人能告诉你统计学的意义是什么,术语用简单的英语表达是什么意思吗?让…
towardsdatascience.com](/statistics-for-people-in-a-hurry-a9613c0ed0b)
#2 数据科学最被误解的英雄
优秀的分析师是数据工作取得成效的先决条件。让他们放弃你是很危险的,但是如果你低估了他们,他们就会这么做
为什么像对待二等公民一样对待分析会伤害你
towardsdatascience.com](/data-sciences-most-misunderstood-hero-2705da366f40)
#1 什么是决策智能?
基于纯数学理性的策略相对幼稚,往往表现不佳…
人工智能时代领导力的新学科
towardsdatascience.com](/introduction-to-decision-intelligence-5d147ddab767)
对结果感到惊讶?我也是!我个人最喜欢的五个不在名单上。【1】2】3】4【5】义愤填膺?把你认为应该更突出的文章分享给你的朋友。**
以下是该列表在社交媒体上分享的链接:
- bit.ly/quaesita_di
- bit.ly/quaesita_hero
- bit.ly/quaesita_statistics
- bit.ly/quaesita_datasci
- bit.ly/quaesita_versus
- *【bit.ly/quaesita_simplest *
- bit.ly/quaesita_fail
- bit.ly/quaesita_inspired
- bit.ly/quaesita_aibias
- bit.ly/quaesita_genie
【免费课程】和机器学习交朋友
如果你正在寻找一门为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:
Enjoy the entire course playlist here: bit.ly/machinefriend
阅读混淆矩阵
精确度,召回,f 分数,真阳性,假阴性,真阴性,假阳性…你困惑了吗?
Image from https://pixabay.com
本文将尝试解释上述术语,并演示如何阅读混淆矩阵,以便从中获取最多信息。
什么是混淆矩阵?
混淆矩阵是一种可视化分类结果的方法。您已经建立了一个分类模型,该模型预测了测试集上的一些值,并且您还有一些目标变量的实际值要与之进行比较。困惑矩阵将向你展示你的预测是否与现实相符,以及它们是如何更详细地计算的。
下面的混淆矩阵显示了预测值与实际值的对比,并给出了分类对的名称:真阳性、真阴性、假阴性和假阳性。我们将讨论每一个预测患者高血压的特殊例子的意义。
真阳性
我们现在将考虑 130 名患者的数据集,其中基于一些特征集,我们试图预测患者是否患有高血压。在数据集中,有 46 名患者有高血压,其余 84 名没有。我们已经运行了我们的分类算法,并绘制了我们的模型相对于实际值的预测值。混淆矩阵如下所示。我们可以看到我们得到了 34 个真阳性。这对应于患有高血压的患者,并且我们的模型正确地识别了他们。
真底片
我们可以看到,我们也得到了 78 个真负对。这意味着我们的算法已经正确地发现了 78 名没有高血压的患者(他们没有高血压,并且模型也预测他们没有)。真正的否定和真正的肯定是我们的模型做对的部分。我们希望找到能最大化这两者的模型。
误报
现在,我们开始关注我们的模型表现不佳的部分。假阳性代表我们的模型归类为有高血压的患者的数量,但实际上,他们没有。对病人来说可能不是一个严重的错误,但是对治疗病人没有的疾病的医院机构来说可能是昂贵的。假阳性也称为 1 型错误。
假阴性
假阴性代表患者有高血压,但我们的模型预测他们没有。它也称为第二类错误,这种错误的含义可能不同于第一类错误。在我们的情况下,后果甚至可能是严重的,因为那些患有高血压的患者将被诊断为健康的,而没有得到治疗。
精度
累积正确预测并将该数字放入所有实例的对比中的度量是准确性。它将真阳性和真阴性相加,然后除以所有实例的数量。
准确度的实际公式如下:
如你所见,我们将所有真值(真正值和真负值)相加,然后除以所有示例。在我们的例子中,这是(34+78)/130。我们得到的精度比 0.86 稍高一点。
重要的是要注意,有一些例子,准确性本身可能会产生误导。因此,在我们的例子中,有 84 名患者没有高血压,因此,一个只预测所有患者没有高血压的模型将获得 64%的准确性(84/130=0.64)。因此,我们希望使用其他指标来帮助模型评估。
精度
这是一个非常重要的概念。这是模型正确识别的高血压患者数(真阳性)除以模型预测的所有高血压患者数(真阳性和假阳性)。换句话说,它衡量的是在我们模型的正面预测中,正确识别的实例所占的比例。
回忆
召回代表正确识别的高血压患者(真阳性)除以患病患者总数(真阳性和假阴性)。换句话说,它衡量的是我们的模型能够正确识别的疾病患者的比例。
如果你仍然感到困惑,你可以把召回率理解为被模型正确分类的所有相关结果的百分比,把精确度理解为相关结果的百分比。
F 分数
精确度和召回率可以结合成一个单一的指标,称为 f-score。如果你对回忆和精确给予同等的重视,你可以用它来优化你的模型。如果你不强调回忆和精确更重要的话,这可能是一个很好的折中方案。公式如下所示,它结合了我们讨论过的两个指标。
结论
在这篇文章中,我介绍了一个混淆矩阵,并给出了可以从它导出的度量标准。在评估分类问题时,查看上面提到的所有指标是很重要的。然而,当试图优化或选择最佳模型时,增加一个指标可能会导致另一个指标下降。根据模型应用选择折衷方案并理解这些决策的含义是很重要的。
原载于 aboutdatablog.com: 阅读一个困惑矩阵,2019 年 12 月 11 日。
PS:我正在 Medium 和上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的 邮件列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入。**
下面是一些你可能会喜欢的帖子
** [## python 中的 lambda 函数是什么,为什么你现在就应该开始使用它们
初学者在 python 和 pandas 中开始使用 lambda 函数的快速指南。
towardsdatascience.com](/what-are-lambda-functions-in-python-and-why-you-should-start-using-them-right-now-75ab85655dc6) [## Jupyter 笔记本自动完成
数据科学家的最佳生产力工具,如果您还没有使用它,您应该使用它…
towardsdatascience.com](/jupyter-notebook-autocompletion-f291008c66c) [## 当你开始与图书馆合作时,7 个实用的熊猫提示
解释一些乍一看不那么明显的东西…
towardsdatascience.com](/7-practical-pandas-tips-when-you-start-working-with-the-library-e4a9205eb443)**
层间阅读(LSTM 网络)
使用 PyTorch 框架进行深度学习
Photo by Paul Skorupskas on Unsplash
构建深度神经网络的最关键部分之一是——当数据流经经历维度变化、形状改变、展平然后重新成形的层时,要有一个清晰的视图…
我们将参考之前在情感分析教程中看到的 LSTM 架构。链接到这篇文章。
使用 PyTorch 框架进行深度学习
towardsdatascience.com](/sentiment-analysis-using-lstm-step-by-step-50d074f09948)
LSTM Network Architecture for Sentiment Analysis
这些层如下所示:
0.令牌化:这不是 LSTM 网络的一个层,而是将我们的单词转换成令牌(整数)的一个强制步骤
- 嵌入层:将单词标记(整数)转换成特定大小的嵌入
- LSTM 层:由隐藏状态变暗和层数定义
- 全连接图层:将 LSTM 图层的输出映射到所需的输出大小
- Sigmoid 激活层:将所有输出值转换为 0 到 1 之间的值
- 输出:最后一个时间步的 Sigmoid 输出被认为是该网络的最终输出
**在定义模型类之前,仔细观察每一层会有很好的洞察力。**这将有助于您更清楚地了解如何为模型架构的嵌入、LSTM 和线性层准备输入
背景:
我们正在使用 IMDB 电影回顾数据集,数据处理和准备步骤已经完成。如果您需要重新查看这些步骤,请点击此处的按钮。我们从数据加载器开始(我们已经定义了batch_size=50
和sequence length=200
)。根据我关于使用 LSTM 构建情感分析模型的文章,我们正在用显微镜观察第 14 步——
- 我们先来看看来自的
**inupts**
和**targets**
dataiter = iter(train_loader)
x, y = dataiter.next()
x = x.type(torch.LongTensor)
print ('X is', x)print ('Shape of X and y are :', x.shape, y.shape)
Reviews converted into tokens (integers)
从X
的形状我们可以看出X
是一个 50 行(=批量)& 200 列(=序列长度)的张量。这确保了我们的令牌化过程运行良好。这个X
将作为嵌入层的输入
- 嵌入层:
允许你使用嵌入的模块是torch.nn.Embedding
。它需要两个参数:词汇量和嵌入的维数
from torch import nnvocab_size = len(words)
embedding_dim = 30
embeds = nn.Embedding(vocab_size, embedding_dim)
print ('Embedding layer is ', embeds)
print ('Embedding layer weights ', embeds.weight.shape)
Embedding Layer ‘Weight Matrix’ or ‘Look-up Table’
embeds_out = embeds(x)
print ('Embedding layer output shape', embeds_out.shape)
print ('Embedding layer output ', embeds_out)
Input tokens converted into embedding vectors
从嵌入层的输出我们可以看到,由于嵌入了权重,它创建了一个三维张量。现在它有 50 行,200 列和 30 个嵌入维度,也就是说,在我们的评论中,对于每个标记化的单词,我们都添加了嵌入维度。这些数据现在将被传送到 LSTM 图层
- LSTM 层:
在定义 LSTM 层时,我们保持 Batch First = True,隐藏单元数= 512。
# initializing the hidden state to 0
hidden=None
lstm = nn.LSTM(input_size=embedding_dim, hidden_size=512, num_layers=1, batch_first=True)
lstm_out, h = lstm(embeds_out, hidden)
print ('LSTM layer output shape', lstm_out.shape)
print ('LSTM layer output ', lstm_out)
Output of LSTM layer
通过观察 LSTM 层的输出,我们看到我们的张量现在有 50 行,200 列和 512 个 LSTM 节点。接下来,该数据被提取到完全连接的层中
- 全连通层:
对于完全连接的图层,输入要素的数量= LSTM 中隐藏单元的数量。输出大小= 1,因为我们只二进制输出(1/0;正/负)
请注意,在将 lstm 输出放入 fc 层之前,必须将其展平。
fc = nn.Linear(in_features=512, out_features=1)
fc_out = fc(lstm_out.contiguous().view(-1, 512))
print ('FC layer output shape', fc_out.shape)
print ('FC layer output ', fc_out)
Output from Fully Connected Layer
- 乙状结肠激活层:
只需要将全连接层的所有输出值转换为 0 和 1 之间的值
sigm = nn.Sigmoid()
sigm_out = sigm(fc_out)
print ('Sigmoid layer output shape', sigm_out.shape)
print ('Sigmoid layer output ', sigm_out)
Output from Sigmoid Activation Layer
- 最终输出:
这包括两个步骤:首先,重新调整输出,使行数=批量大小
batch_size = x.shape[0]
out = sigm_out.view(batch_size, -1)
print ('Output layer output shape', out.shape)
print ('Output layer output ', out)
Sigmoid Activation Layer output reshaped
第二,正如我们在网络架构中看到的,我们只想要最后一个序列之后的输出(最后一个时间步长之后)
print ('Final sentiment prediction, ', out[:,-1])
Final output from the model
这些输出来自未经训练的网络,因此这些值可能还不能说明任何问题。这只是为了举例说明,我们将使用这些知识来正确定义模型。
结束语:
- 我希望你读它的时候和我写这篇文章的时候一样开心
- 试着为你正在尝试实现的任何其他深度学习模型复制这个过程
- 请随意写下您的想法/建议/反馈
用卷积神经网络读取股票图表
Source: trendspider.com
介绍
"历史不会重演,但它经常会重复。"马克·吐温
在了解了卷积神经网络(CNN)在图像识别方面的强大功能后,我想知道算法是否能比人类图表分析师更好地阅读股票市场图表,人类图表分析师的工作是发现图表模式并从中获利。我们知道CNN 比人类更擅长对 ImageNet 图片进行分类,但是他们能比其他市场参与者更好地阅读和发现模式吗?
以下是我为适应 CNN 的股票价格预测所做的细微差别和调整。你可以在这里找到我凌乱的 jupyter/colab 笔记本。
1.选择正确的市场/数据集
我认为合乎逻辑的是,技术分析在量化基金交易的市场中不会起作用——任何从有趣的图表模式或【插入复杂的声音术语】中可能获得的收益都已经被任何体面的量化者榨干了,但我很想知道,在量化者由于能力有限而不去的地方,是否仍然存在简单的低效率。因此,我寻找全球顶级交易所之外但仍可进入的市场——华沙证券交易所就是这样一个例子。
2.时间序列的训练-测试分裂的危险
使用标准 ML 包分割数据集很容易,但必须小心处理时间序列,否则会发生数据泄漏,并产生乐观的样本内结果,而非样本外结果。如果你的随机训练测试分割让你的模型学会如何填补下面的空白,你实际上是在用未来预测过去!
Source: fast.ai
我遵循了 Rachel Thomas 的建议,以一种不会让模型预测过去的方式分割数据——关于选择验证集时的其他细微差别,请阅读她的帖子。
3。使用循环图成像时间序列
向 CNN 提供信息的最直接方式是使用标准的价格/交易量图表,如下所示:
然而,由于 CNN 从数据中处理和学习洞察力的方式可能与人类不同,因此以不同的形式表示时间序列可能是有用的。此外,由于图像有 3 个通道,所以可以用不同的度量来包装每个通道,以便为我们的算法提供更多信息。这个有用的库有几个函数实现了时间序列的 SOTA 图像表示。
一种这样的转换是 Gramian Angular Fields (GAFs),它将时间序列转换到一个“极坐标系统,而不是典型的笛卡尔坐标。【0】。另一种这样的表现是循环图,这种图*“显示了重要的和容易解释的关于时间尺度的信息,否则是很难得到的”。*【1】下面是一些变换后的图表,看起来蛮不一样的吧?你可以在这一页的末尾看到我实验的最终结果。
Recurrence Plot transformations
4.分数微分——平衡内存和稳定性
平稳性是 ML 算法的高性能的必要的非充分条件。问题是,在平稳性和记忆性之间有一个权衡。我们总是可以通过微分使一个序列更加平稳,但这将以擦除一些记忆为代价,这将挫败 ML 算法的预测目的。”马科斯·洛佩斯·德·普拉多【2】
Figure 1: Memory vs Time [2]
使用价格系列时的一个标准工程特征是退货系列。Lopez[2]写道,return 系列的问题是丧失记忆。图 1 本质上显示了相对于时间保存的内存。对于返回序列,即“整数 1”微分,在第一个周期后,序列的记忆会失去对过去值的记忆。但是我们可以看到,对于分数微分值,历史值的记忆仍然存在,这有助于预测。
然后,诀窍是找到一个分数,其中微分小于 1,但仍达到平稳性——一个 ADF 测试可以检查给定分数是否达到平稳性。
5.平移不变性的可选性
CNN 如此擅长对图像进行分类的一个关键原因是平移不变性,即输出对输入的微小变化不变。如果你试图对一只不总是在同一个地方的猫进行分类,它仍然可以识别这只猫。
Source: What is wrong with Convolutional neural networks
但是对于时间序列,时间上较早的尖峰与预测时间之前的尖峰具有不同的含义,因此如果平移不变性有用的话,我们可能希望抛弃它——使用 Coordconv [3]可以实现这种可选性。一个 Coordconv 层包括 2 层 I 和 j 坐标,让 CNN 知道每个像素的位置。如果算法决定坐标是有用的,权重将反映这一点,因此使用 Coordconv 只有好处!作者发现,将 Coordconv 添加到各种 CNN 任务中几乎总能提高性能。
Source: An intriguing failing of convolutional neural networks and the CoordConv solution [3]
结果和进一步的工作
我使用 CNN 通过将时间序列数据表示为图像来预测时间序列。CNN 有一个相对简单的二元分类任务——决定第二天的收盘价是否为正。
我关注的是精确度,因为我们赌假阳性会赔钱。使用 GAF 成像的分数微分序列(d=0.3),最好的评分是 64 %。我跑得最好的笔记本是这里的。
接下来,我将着眼于改进 CNN 架构,以更好地捕捉时间关系,即波网!兴奋地去理解和测试它。
特别提及:fast.ai
我从我的人工智能硕士那里学到了很多东西,但我也学到了同样多的东西,如果不是从 fast.ai 那里学到更多关于实用深度/机器学习的话。 fast.ai 库挤满了最先进的深度学习技术,这些技术可以加快训练速度,它们的默认设置会产生惊人的结果,从而使用户可以专注于实验的其他部分。论坛也非常活跃,上面的大多数想法都来自这个帖子中的人。
参考
[0] Z. Wang 和 T. Oates,“使用平铺卷积神经网络将时间序列编码为用于视觉检查和分类的图像。”AAAI 研讨会(2015 年)。
[1] J.-P Eckmann 和 S. Oliffson Kamphorst 和 D Ruelle,“动力系统的递归图”。欧洲物理学通讯(1987 年)。
[2]马科斯·洛佩兹·德·普拉多,“金融机器学习的进展”。2018
[3] 罗莎妮·刘、乔尔·雷曼、皮耶罗·莫里诺、费利佩·彼得罗夫斯基这样的、埃里克·弗兰克、亚历克斯·谢尔盖耶夫、杰森·约辛斯基、【卷积神经网络和 CoordConv 解决方案的一个耐人寻味的失败】。2018.
应用人工智能阅读书目
Photo by Nong Vang on Unsplash
如果你在 2020 年将人工智能应用到你的业务中,六本书值得一读
据行业领袖称,2020 年将是人工智能(AI)“现实检验”的一年。在未来一年,许多企业将寻求从人工智能和机器学习试点计划转向为将人工智能完全嵌入企业奠定基础。IDC 预测到 2022 年,75%的企业将在运营中嵌入智能自动化。
如果你是一名商业领袖或数据专业人士,正在考虑如何在你的组织中使用人工智能,以及部署这一新兴技术的最佳方式,这里有一份书单,可以添加到你的新年阅读清单中。这些书涵盖了在商业中应用人工智能的战略和实践层面。他们会让你明白;
- 人工智能在不久的将来对商业意味着什么。
- 如何为应用人工智能建立合适的团队?
- 部署机器学习的最佳实践。
- 如何制定坚实的战略,将人工智能和机器学习嵌入到组织中。
- 实施人工智能的伦理和道德考虑。
机器学习向往
吴恩达
被称为谷歌大脑背后的人的吴恩达在 2018 年发布了这本完全免费的书。根据他领导谷歌大脑团队的经验,他介绍了一个将机器学习嵌入组织的框架。
这本书涵盖了如何制定机器学习策略,测试机器学习模型的正确方法以及如何建立一个“超级英雄”团队。对于希望开始在企业中使用或扩展机器学习的数据科学家和企业领导者来说,这是一本必读的书。即使你已经在部署机器学习,这本书也将提供如何改进现有流程的技巧。
机器学习的规则
马丁·津克维奇
另一本免费下载的书,作者是谷歌的一位研究科学家,这本书涵盖了机器学习工程的最佳实践。这是一本非常实用的书,既适合商业领袖,也适合数据科学家。它涵盖了实现机器学习的最佳实践,从最基本的原则开始,比如只在有意义的地方使用机器学习。
这本书分为四个部分,包括:如何了解在实施机器学习(ML)之前需要准备什么,如何部署端到端的 ML 管道,如何启动模型和迭代以获得性能改善,以及当性能增益达到平台期时该做什么。
数据科学行动手册
柯克·博恩和埃兹梅拉达·哈利勒·萨格尔
这是一份来自数据科学咨询公司 Booz Allen Hamilton group 的出版物。这本书概述了成功的数据科学的“六个关键要素”,这些要素是他们通过与众多公共和私营部门企业合作而确定的。
这六个要素包括:
- 识别分析机会。
- 如何更好地管理和治理数据。
- 从这些数据中产生有用见解时需要考虑的分析技术。
- 如何建立和发展数据科学团队?
- 如何最好地将新技术和现有技术用于数据科学项目。
- 为数据科学的成功开发一种企业文化,他们称之为“Adapt-C”。
这本书主要针对商业和数据科学领导者,并就如何制定公司范围的数据科学战略给出了非常实用的建议。
预测机器
阿贾伊·阿格拉瓦尔、阿维·戈德法布和约书亚·甘斯
这本书是从市场营销、经济和管理专家的角度写的。它旨在回答“人工智能对我的业务意味着什么?”。他们相信将人工智能重新定义为“廉价预测”而不是“魔法”,并提出人工智能将为能够成功利用这项技术的企业提供经济优势。
这本书为商业领袖和战略家提供了一个关于人工智能的现实视角,并介绍了一个实用的框架来理解你需要了解的关于这项技术的知识以及它将如何影响你的业务。
人+机器:重新想象人工智能时代的工作
保罗·r·多尔蒂和 h·詹姆士·威尔森
这本书聚焦于人工智能的不远的将来,以及这将如何用这种技术导致所有业务流程的转变。作者讨论了他们如何看到公司部署人工智能解决方案来增强创新和盈利能力。这本书还提供了一个“领导者指南”,它给出了成为人工智能驱动的企业并实现公司业绩改善的五个关键原则。
这本书是商业领袖对人工智能的实用介绍,并解释了它在不久的将来对企业和“人类”意味着什么。
破坏数学的武器
凯茜·奥尼尔
人工智能目前的局限性之一是,尽管机器能够通过复杂的计算学习数据中存在的模式,但它们还无法对它们做出的预测做出任何道德判断。当企业开始将这项技术应用到他们的流程中时,考虑自动做出的决策的道德含义是很重要的。因此,我觉得在人工智能的推荐书目中至少包括一本关于伦理的书是至关重要的。
这本书强调了在将人工智能集成到企业中时一些最重要的伦理和道德考虑。作为业务领导者或数据从业者,这将为您正在部署的模型的潜在含义提供许多思考的素材。
感谢阅读!
解读市场——机器学习与金融新闻
大量的金融新闻文章出版了。但只有一小部分能真正推动市场。知道哪些可能会有帮助。机器学习能指明方向吗?
【本文涵盖今年 5 月在维也纳举行的 QuantMinds 国际会议上介绍的工作,以及 12 月在纽约举行的量化金融中的机器学习和人工智能会议上的更新。它基于我们在《走向数据科学:机器学习与新闻中发表的测量新闻情绪的工作。]
想象一下,你想要战胜股票市场。你是个勤奋的投资者。每天早上开市前,你会阅读前一天收盘后发布的所有新闻。在以某种方式预测了这些文章中的哪一篇会推动市场后,你运用你巨大的直觉和洞察力来下注。然后你去海滩。
这种梦境的问题在于数据量巨大,而且数据和结果之间的关系从未被可靠地公式化。但是,这当然是我们喜欢应用机器学习的那类问题的本质【1】。
道琼斯通讯社是主要的实时财经新闻提供商之一,每年传送几百万篇文章。这些包括从主要报纸的文章到新闻发布和经纪人的评论。即使我们把自己对世界的看法限制在与标准普尔 500 指数成份股公司明确相关的文章上,我们每天仍会看到成千上万篇文章。如果我们在开市前一个小时到达工作地点,我们几乎没有两秒钟的时间来阅读和评估每篇文章。我们也许能够以这样的速度浏览一些文章,并发现一些有趣的文章,但我们的分析不太可能非常深入,而且几乎可以肯定的是,我们无法保持这样的速度一个小时。人们也早已清楚,即使有足够的时间,投资者也不太擅长预测市场。
我想到的一个大问题是:
有没有可能建立一个算法,可以成功地找到将推动市场的文章?
继续读下去,你会发现答案最终是肯定的。但实现这一目标的能力取决于投入大量精力,培养对现有新闻文章本质的理解,以及对相关工具和算法的直觉。
理解新闻
对于这个项目,我们使用自然语言处理,特别是情感分析。参考维基百科的定义:
Wikipedia’s definition of Sentiment Analysis
在我们的语境中,这意味着分析一篇新闻文章的文本,并决定它“听起来”是积极的还是消极的。有几种常用的库可供使用:
●斯坦福 CoreNLP
● NLTK
●谷歌云平台
这些库的运行方式各不相同,但总的想法是,它会消耗一些文本并返回一个分数,其中如果一篇文章特别乐观,它可能被评为+1,如果它特别消极,它可能被评为-1,或者其他适当的介于两者之间的值。本文给出的结果是使用 NLTK VADER 获得的。这种选择主要是出于计算的原因,因为它比其他选择要快得多。
为了举例说明,让我们看几个已经传递给斯坦福的情感分析器的句子(可以在这里运行)。
Sentiment computed for a variety of sentences by Stanford’s CoreNLP
我们看到一些无关紧要的句子被评价为或多或少积极的,与我们可能希望期待的一致。当处理新数据或新库时,为了确定您可能遇到的弱点,运行这样的小测试是非常有用的。所有库的结果都很差——为了避免显得卑鄙,这里不分享这样的例子。
如何预测未来
一旦我们知道了一篇新闻文章的观点,我们希望能够预测它的发表是否会引起市场的重大变化【2】。
用机器学习的行话来说,这是一个有监督的学习问题。我们有包含特征(文章的属性)的历史新闻文章数据,并添加了一些标签(基本上是 0 或 1 ),指定文章实际上是否跟随了文章中提到的公司的股票价格的显著移动。
我们将这些数据传递给一个分类器——某种算法,在我们的例子中,该算法试图推断某一特定商品是否可能会发生重大价格变化。在实践中,我们希望能够确定我们是否从可用的历史数据中学到了任何有用的东西。为此,我们将历史数据分为训练集和测试集。在“学习”阶段,我们向算法展示来自训练数据的特征和标签。然后,在测试阶段,我们向经过训练的算法提供以前未见过的特征,指示它预测最可能的标签,然后将该预测与实际对应的标签进行比较。
鉴于这一总体框架,我们的工作必须朝着两个方向前进:
●确定可用新闻文章的最佳功能集。
●确定将最成功地学习我们的特征和标签之间的关系的分类器(及其参数化)。
机密情报
我们将很快讨论我们脑海中的特征类型,但是首先对分类器进行一些评论。对于监督学习问题,存在多种分类器。最基本的是逻辑回归。然后是决策树、随机森林等算法。在数学上复杂的一端,我们发现了神经网络。对于这个项目,我们使用神经网络找到了我们的最佳结果,所以我们在这里展示的结果是通过这种方式获得的。
我们不会尝试在这里介绍神经网络。只要说它们是一种非线性回归工具就够了,其基础设计是从人脑基本结构的简化中找到灵感的。
在过去的几年里,我们在机器学习方面经历的许多重大进步都利用了神经网络。这种基本算法已经存在了几十年,但随着处理能力和数据可用性的稳步增长,它开始发挥作用。
对于这个项目,我们用 Python 实现了我们的神经网络,使用了 Google 流行的 TensorFlow 库。我们的神经网络的特征,特别是它的复杂性,被选择来平衡精度和泛化能力。这相当于:
●准确预测样本内训练数据的标签
●准确预测样本外测试数据的标签
这并不像听起来那么容易。很明显,如果一个模型非常简单,即使在训练过程中“看到”的数据上也不太可能表现良好。随着模型变得越来越复杂,它开始在训练数据上表现得更好。如果它运行良好,它将越来越多地在以前看不到的测试数据上表现良好——即,它将学会概括。但是从某种复杂程度上来说,它将继续在训练数据上表现得更好,而在测试数据上表现得越来越差。因此,选择架构的目标是在最佳点着陆,在这个点上,模型在测试 数据上的准确性最高。
对这种现象的一种思考方式是,没有一种关系可以从数据中完美地学习到。这很大程度上是因为数据本身并不是我们试图了解的关系的完美例子——总有噪音。随着模型变得更加复杂,它获得了从训练数据中学习噪声的数值自由度。但是从这个角度来看,既然噪音基本上是随机的(因此是不可预测的),那么这些知识只能分散对未知数据的有用学习。
因此,诀窍在于找到一个足够复杂的网络,以学习数据中非线性关系的本质,但又不足够丰富,以至于能够有效地记住所呈现的数据(每个观察结果都包含特定的噪声,这些噪声不会在未来的数据中再现)。
这是很重要的,因为记忆数据证明是一个非常差的保证,知识可以推广到以前看不到的情况。从某种意义上说,对记忆的约束是洞察力的起源。但只是在一定程度上——给定一个足够有限的模型,我们既不会记住任何东西,也不会学到任何有用的东西。
最适合我们的网络架构如下:
●四个隐藏层—64、128、128 和 64 个节点
●层完全连接并使用 Relu 激活
●输出层包含具有 sigmoid 激活的单个节点
特征工程
特征工程是确定可用数据的特定属性集的工艺,这将最好地促进我们寻求推断的关系的学习。我们可以想象一些物品属性的效用:
●文章的正文
●刊登文章的出版物的名称
●文章发表的时间
●出版商的文章 ID 代码
我们可能随后会发现在我们的特性中包含文章 ID 是没有帮助的。包括它甚至可能使结果恶化。在直觉层面上,我们可以认为这个特性只是带来了额外的噪声,妨碍了算法搜索洞察力。在这种情况下,从特性中删除文章 ID 实际上消除了干扰,使学习更容易。
相反,文章的文本本身可能很难让我们的算法从中学习任何东西。因此,特征工程工艺的另一个方面是计算出可以从数据中导出哪些进一步的属性,以帮助突出关键关系,并使算法的工作更容易。(如前所述,我们将使用情感等衍生特征)
该过程
为了获得这里给出的结果,我们遵循一个相当典型的机器学习过程。实际上,我们将把数据随机分成训练集和测试集。所呈现的结果是从将已训练的模型应用到测试测试中获得的结果(即,未被用作训练模型的一部分的数据集)。
首先,一篇新闻文章只有一个特征——文章的情感。我们将把它与 0(意味着股票的绝对超额收益小于 1%)或 1(意味着绝对超额收益大于 1%)联系起来。
接下来,我们在随机选择的训练子集上训练我们的分类器,然后通过从测试数据集生成预测并将它们与股票价格的实际记录历史移动进行比较来测试训练的网络。
为了使这种比较对一组数据有用,我们需要一个度量标准。评估分类问题解决方案成功与否的一个常用指标是 F1 分数。这在我们这样的情况下特别有用,在我们的数据集中有大量的“真正的负面消息”,这意味着大多数文章之后没有重大的股价波动。
请记住,如果我们的模型预计一篇新闻文章之后会有市场变动,则预测值为 1,否则预测值为 0,F1 得分计算为以下各项的调和平均值:
●从我们的模型中得出的 1 个预测实际上为 1 的比例(所谓的精确度),以及
●我们的模型正确预测为 1 的所有实际 1 的比例(召回)。
如果我们的结果是完美的,这个值将是 100%,如果它们完全没有用,这个值将是 0%,更有可能在两者之间。
为了说明这类项目的发展,我们将以渐进的方式呈现结果——查看我们在实验不同功能集时发现的 F1 分数。要记住一个重要的事实:
虽然添加功能的过程是由我们的直觉和智慧驱动的,但现实往往不会被我们最伟大的洞察力所打动,有时甚至会成为苛刻的批评家。
无论如何,我们希望通过明智地添加功能,我们将提高我们的模型的预测能力!
第一步:那些艰难的早期结果
看到第一个结果往往是你无畏的机器学习工程师或数据科学家陷入绝望的时刻——所以我们必须做好准备,对我们最终的结局保持一定程度的乐观。
虽然我们还没有天真到想象用一个数字来表示一篇文章——它的情感——会让我们的分类器有更多的希望来推断这篇文章是否会推动市场,但从这里开始仍然是有用的。
这有几个原因。首先,它是一种检查我们的整个管道是否正常工作的方法——我们可以收集数据,构建功能,分离测试数据,训练模型,根据测试数据评估模型,等等。第二,它有助于建立一个基准水平的准确性,我们可以根据它来决定增加其他数据特征或改变我们的分类器结构的效用。
尽管如此,人们希望我们在这个阶段取得的结果会比随机的好——因为那至少会令人感到鼓舞。从本能上来说,由于我们是在预测这篇文章是否会推动市场,所以感觉是二元的。因此,人们可能会认为 50%是随机猜测的结果。因此,我们希望在测试数据上获得介于 50%和 100%之间的 F1 分数。
因此,当第一次运行完成时,F1 分数出现在屏幕上,其值为 25%,很难不感到有点沮丧。稍微思考一下,我们就可以从以下事实中得到安慰:我们的文章中,只有少于一半的文章出现了大幅的市场波动,因此,选择频率相同的 0 和 1 会导致较低的结果,所以我们的结果确实比随机结果要好。
进度检查:第一步
第二步:物品预处理
数据科学家最重要的活动之一是理解数据。有时这可能是微不足道的。但是,如果一项工作足够复杂,需要一名数据科学家,那么数据集可能会很大,而且是非结构化的。这种分析可能是一种令人沮丧且耗时的活动,但也是必不可少的。
我们找到的第一篇文章显然是我们希望从中学习到一些东西的:
贝尔沃租赁有限公司(BLV。LN)周三表示,该公司超过了 2017 年投资组合收购的目标。这家英国房产租赁公司表示,2017 年期间,特许经营商完成了 23 笔交易,增加了超过 330 万英镑的网络收入,超过了其目标。
这篇文章有几个优点:
●它明显与特定公司相关
●它拥有可以相对容易地推断出情感的语言
●它不包含大量中性或分散注意力的文本
我们开始注意到的许多其他文章就不一样了。有些形式经常重复出现,其中包括:
●经纪人的价格更新
●带有免责声明的新闻稿
● S&P 评级评论
●与多家公司相关的文章
第一种方法对我们的目的没有多大用处,因为它们只是简单地引用了特定证券的出售价格。它们本质上几乎完全是数字——尽管这并不排除它们的用处,但我们的 NLP 情感算法并不适合解释它们。此类物品最好能被检测出来,并从我们的流程中排除。
新闻稿和 S&P 评级评论可能非常有用。但是他们经常以免责声明的形式包含大段的法律术语。情感是作为文档句子的平均值来计算的。由于法律术语往往是中性的,在分析文章时包括这些标准文本的大段文字将会大大削弱文章报道的情感。因此,在评估这些标准文本之前,我们将把它们从我们的文章中去掉。这是一项繁琐的工作,但是可以通过一系列正则表达式有效地实现。
一些新闻文章总结了与不同公司相关的多条新闻。由于这些文章遵循特定的格式(取决于出版商等),通常可以自动将它们分成一系列迷你文章,每篇文章只报道一条新闻。
一旦我们建立并实现了一套预处理数据的规则,我们就可以重新运行我们的分析,看看我们得到了什么样的测试结果。
进度检查:第二步
事实上,通过对文章进行预处理,我们看到 F1 分数提高了 15%。这是第一次表明,了解您的问题领域和技术领域是有实际价值的。在这种情况下,这意味着理解:
●在浩如烟海的文章中究竟能找到什么样的文章,以及
●算法将如何在各种类型的文章上执行
第三步:添加更多功能
为了提高我们的神经网络学习某些东西的机会,我们现在将向它扔更多的数据——具体来说,我们将为每篇新闻文章提供额外的功能。
在我们这样做之前,有必要思考这样一个事实,即一篇新闻文章只有在改变我们对某件事的看法时才会对我们“有用”。在我们对世界的简化观点中,我们从新闻报道对股票的情绪中推导出对股票的情绪。因此,如果一篇新闻文章偏离了我们之前对该股的看法,它可能会被认为是有趣的。请注意,一篇文章不一定要与我们当前的观点相矛盾,它可能只是让我们对我们当前的观点更加自信。考虑到这些目标,我们为每篇文章引入了以下功能:
●近期新闻文章对该股的平均情绪
●本文观点与该股近期历史均值之间的偏差
●近期文章对该股情绪的波动
我们还可以想象,股票对新闻报道的反应可能取决于股票最近的交易情况,因此我们纳入了捕捉以下信息的指标:
●该股的交易量表现如何?
●该股相对于整体指数的表现如何?
●该股近期超额收益的波动性如何?
最后,一些公司在正常时期很少被报道,而在重大事件发生时会被更频繁地报道。因此,我们纳入了一个衡量标准,衡量股票的报告频率相对于其长期平均水平的近期表现。
将所有这些特性放在一起,重新运行我们的测试,我们看到我们的 F1 分数从 40%增加到 49%。
进度检查:第三步
第四步:一点新闻洞察力
这类工作最重要的一个方面是发展对领域的理解。许多新闻都是按照所谓的倒金字塔模型构建的。借用维基百科,我们可以将一篇典型新闻文章的结构形象化如下:
Inverted Pyramid Model of Journalism courtesy of Wikipedia
这是写文章的一个相当标准的方法。这个想法是在文章的开头传达谁,什么,等等,然后在接下来的段落中提供更多的辅助细节。开头的几个句子被称为文章的导语。
我们可能会假设,Lede 中传达的情感更多地与公司相关新闻的最重要部分相关,并且我们越深入文章,我们就越会偏离它(通过关注不太重要的细节的情感)。如果我们被这个假设所吸引,那么我们应该考虑运行网格搜索来识别文章中要处理的最佳部分。
我们通过使用 NLTK 工具包将文章文本转换成句子来做到这一点。接下来,我们从文章中选择第一个 n 句子(每篇文章都有相同的 n ),然后我们用这部分文本继续完成剩下的过程,并计算 F1 总分。此外,我们迭代不同的 n 值,直到我们找到最好的 F1 分数。我们发现的结果如下:
F1-score computed using a series of Lede lengths (in number-of-sentences)
这显示了大约十个句子的最佳情感信息内容,因此在完成步骤四时,我们将处理限制在十个句子的文章。
进度检查:第四步
停下来想一想——我们被困住了吗?
通过几次迭代,我们已经推进到这样一个点,即我们的结果有一些统计意义,但没有足够的意义来保证写一篇关于它的文章。我们已经花了很多时间来加深对新闻文章的理解,所以现在我们必须努力加深对我们正在使用的人工智能工具的理解。
尤其值得思考的是,情感分析是否很好地适应了我们试图解决的问题。要做到这一点,我们必须更深入地了解我们可用的特定情感分析工具。这是有见地的考虑语料库的性质,每一个是建立在。一般来说,流行的情感分析师没有接受过金融新闻报道方面的培训。更常见的是,它们是通过以下方式构建的:
●来自亚马逊或 IMDB 的评论
●推特
每种类型的文本都有自己的特点。推文肯定是用与完整长度新闻完全不同的语言写的,所以为推文精心校准的工具不太可能理解更正式写作的情感范围。
值得注意的是,从我们对股票的看法来看,“结果略有改善”这样的句子是积极的。然而斯坦福的 CoreNLP 把这句话归类为否定。同样,所有的库都有自己的特点和不一致性,所以这并不是对 CoreNLP 的批评。
所有这些都让人怀疑,最好的前进方式是不是建立我们自己专有的情绪分析器。如果我们环顾一下可用的工具,很容易被 Doc2vec 的流行和据称的功能所诱惑。所以我们来看看有没有帮助。
与 Doc2vec 一起前进
Doc2vec 是流行的 Word2vec 的扩展,有效地在文档级别而不是单个单词级别应用该技术。Word2vec 最初来自谷歌进行的研究。Word2vec 的想法是学习一个将单词映射到一个 n 维向量的函数。该算法通过查看一些语料库中的单词序列来做到这一点。在机械上,一个简单的神经网络用于学习预测哪个单词最有可能跟随任何给定的单词。第一个惊喜在下一步。扔掉神经网络的输出层,转而看看倒数第二层的 n 节点的激活。然后,这些激活的值可以被认为对应于输入单词的矢量表示。
这有什么用呢?对于这是如何发生的还有一点不确定性,但是如果我们绘制一系列单词的向量值,我们会开始注意到一些非常有趣的模式。从谷歌深度思维研究科学家的一篇文章中截取这张图片:
Word embeddings for related words under Word2vec
这里我们看到的是一些常见单词对应的向量值的曲线图。(实际的向量是高维的,但是它们在这里通过称为降维的数学过程被简化,以便它们可以在某种意义上近似为我们可以绘制的二维图形)
要注意的是,虽然像“慢”、“短”、“强”、“暗”这样的词都出现在图表上相当不同的位置(沿着左手边),但更慢和最慢(到慢)的相对位移,基本上与我们看到的短/更短/最短、强/更强/最强等完全相同。
这几乎表明,该算法已经推断出某种语言语义的算法。事实上,我们可以制作图表,展示语言的许多其他属性的类似有趣的结果。
我们不会在这里详述细节,只是说 Doc2vec 将该方法扩展到了文档级别——并且已经发表了几篇在情感分析中使用 Doc2vec 文档矢量化的论文。
这特别有趣,因为在任意文档语料库上训练 Doc2vec 很容易。因此,我们建立了新闻文章的向量化,然后,当沿着这个新方向前进的兴奋达到顶点时,我们看一下这个过程的下一步:训练我们的情感分析器。我们意识到了问题。
已发表的使用 Doc2vec 进行情感分析的工作主要是通过评论数据完成的,特别是来自亚马逊客户或 IMDB 电影评论者的评论数据。这些案例有标签,而我们没有,也就是说,对于每个评论,都有文本和用户指定的星级。这两者的结合大大简化了从文本中学习情感。
然而…在我们这里,我们只有文章,没有星级。因为我们知道我们的目标是拥有一个情感分析器,它是根据出现在财经新闻而不是电影评论中的语言类型来训练的,所以我们陷入了困境。
所以我们碰壁了
在努力寻找解决我们问题的方法后,一个真正的障碍出现了。就像马拉松运动员必须在最后一次努力中找到出路一样,我们也必须如此。
想想我们在努力做什么。实际上有两个步骤:
- 文本-> Doc2vec ->情绪,然后
- 情绪->市场结果预测
我们的问题是缺乏可用的情感价值。但是注意到情绪既是一个步骤的输出,又是下一个步骤的输入,我们就不能简化一下吗?
为什么不用市场结果来代表情绪呢?这将给我们留下一个步骤:
- TEXT -> doc2vec ->市场结果预测
第五步:集成 Doc2vec
事实证明,以这种方式可以发现显著的改进。实现相对简单,尽管我们使用 gensim,而不是 Google 的实现。结果如下所示。
进度检查:第五步
第六步:拿着香槟
在我们忽略的各种细节中,有一些在使用 Doc2vec 时出现的基本实际限制。主要的问题是,我们需要一套完整的文章来建立模型——不可能动态地添加新文章,然后对这些文章进行预测。这意味着,对于出现的每一篇新文章,我们都可能需要重新训练我们的文档矢量器。
问题实际上比那更糟糕。Doc2vec 中的特定向量不是算法的本质——重点是不同文章的相对嵌入。重建模型时,这些不同向量之间的形状可能会保持不变,但绝对值可能会改变。由于我们用作分类器的神经网络与实际值有关,因此也有必要对其进行重新训练。
这是很大的计算负担,并且在每天有数千篇新文章的实时环境中一点也不方便。
我们可以认为,基本约束源于 Doc2vec 需要一个完整的词汇表来构建其矢量化模型。给定一个足够大的特定领域训练数据集,在以前看不到的文章中很少会遇到新词。但在实际操作层面,总会有一个新人的名字、地名、公司名称等。这表明我们可以尝试构建没有专有名称的向量。事实上,有一些 NLP 工具可以让我们获取文本并标记每个单词的词性。然后我们可以过滤出与专有名词相对应的单词。
这在直觉上很有吸引力,因为它应该使归纳更容易(所以我们对一只股票的了解肯定适用于另一只股票,因为股票的名称被排除在外)。我们肯定会找到更好的结果…所以让我们看看。
进度检查:第六步
不幸的是,这并没有改善我们的结果——无论这个想法多么吸引人。
更仔细的观察表明,基本的词类过滤并不是特别有效——它删除了一些不是真正专有名词的单词。并且为了推断情感,需要那些被移除的单词中的一些。
然而:
由此得出的关键点是,通过采取这一步骤,我们解决了困难的实时问题,而不会显著影响结果的质量。
结论
在本文中,我们展示了处理新闻文章并确定哪些文章可能影响股票价格是可能的。这并不是说我们的模型在 70%的时间里正确地预测了市场。如果是这样,我们就不会写这篇文章了。我们的测试范围要窄得多——请记住,我们关注的是预测一篇新闻文章之后,股价的变动是否会超过指数变动的 1%。我们也在看昨晚收盘和今天开盘之间的变化。所以并不是所有变化都可以直接归因于这篇文章。我们不应该混淆相关性和因果性。
当然,一个人理解得越多,能够取得的结果就越好。这意味着有必要密切关注所有方面:
●了解数据
●了解新闻业
●理解算法
与许多机器学习应用一样,处理新闻和市场几乎是一门手艺,就像它是一门硬科学或工程学科一样。在某种程度上,处于科学、工程和工艺之间的这一位置使它成为一门迷人和令人愉快的学科。
在这个领域还有很多工作要做——未来几年还会有很多研究要做。考虑到金融市场的风险,最好的作品不太可能被出版。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
【1】为了清楚起见,这里要注意这是一种简化。今天早上不可能以昨晚的收盘价交易。我们可以在新闻文章发表时对其进行评估,但这将需要比我们现有的这个项目更多的当天价格数据。此外,值得注意的是,这里的重点是确定哪些消息将推动市场,而不是确定该移动将是哪个方向。(也就是说,给定一个,确定另一个可能相对简单——但鉴于我们历来对波动性的关注,这就是我们的兴趣所在)
【2】注意,我们不是在推断因果关系。在任何时刻,都有多种因素驱动着任何一只股票价格的变动。此外,我们关注的是超过同期标准普尔& P500 指数变动的股票价格变化,也就是说,我们关注的是超额回报,通常称为 Alpha。
扩展 Pandas API 的简单方法
写出你自己的熊猫味道
Photo by Zach Rowlandson on Unsplash
在本文中,您将通过使用pandas _ flavor,学习如何根据您的业务、研究或个人工作流程定制 pandas API。
Pandas-flavor 是一个引入 API 来扩展 Pandas 的库。这个 API 处理将定制的访问器/方法注册到 Pandas 对象上的样板代码。
但是在本文中,我将展示如何使用它来扩展功能。为简单起见,我将使用泰坦尼克号数据集:
**import pandas**df = pd.read_csv("titanic.csv")
注册方法
Pandas-flavor 将以下自定义方法直接添加到 Pandas 的 DataFrame/Series 上:
- 允许将方法附加到数据帧。
register_series_accessor()
允许将方法附加到序列。
这两个装饰器允许你我们可以调整上面的例子,将“is_old_lady
”方法直接附加到 DataFrame 上。
**from** **pandas_flavor** **import** register_dataframe_method**@register_dataframe_method**
**def** is_old_lady(df):
is_lady = df["Sex"] == "female"
is_old = df["Age"] > 70
**return** df[is_old & is_lady]df.is_old_lady()
但这可能会导致一些问题,例如,如果许多包开始用自定义方法对数据帧进行猴子式修补,可能会出现重复和混乱。
通过使用隔离(名称空间),注册一个包含自定义方法的访问器,可以很容易地解决这个问题。
注册访问者
熊猫数据框架/系列的访问者注册也是如此:
register_dataframe_accessor()
允许将访问器附加到数据帧。register_series_accessor()
允许将访问器附加到序列。
作为一个例子,这里有一个简单的“titanic”访问器,它有一个“is_old_lad
”方法:
**from** **pandas_flavor** **import** register_dataframe_accessor**@register_dataframe_accessor**("titanic")
**class** **TitanicAccessor**:
**def** __init__(self, df):
self._df = df
**def** is_old_lady(self):
df = self._df
is_lady = df["Sex"] == "female"
is_old = df["Age"] > 70
**return** df[is_old & is_lady]df.titanic.is_old_lady()
但是熊猫有自己的 API
在本文中,我选择展示 pandas-flavor,尽管 pandas 有自己的 API来扩展 DataFrame/Series 功能,您可能应该在注册访问器时使用这些功能。
但是有一些限制:
- 您使用较旧的 pandas 版本,因为它只在 0.24.x 中引入
- 您希望注册方法而不是访问器,一个用例可以是覆盖 pandas 自己的方法,如 pandas-log 。
- 您希望将访问器/方法注册到其他包,如 xarray。
出于简洁的原因,我选择为所有用例展示熊猫风味。
遗言
当您想要扩展 Pandas 的功能并使您的代码更好时,Pandas flavor 非常有用。这篇文章的灵感来自 Zach Sailer 的博客(熊猫风味作者)。
我希望你觉得有趣和有用。我乐于接受任何建设性的反馈。
真实数据科学家有冒名顶替综合症
Photo by Matthew Henry from Burst
我妻子曾是一名天文学家。她在这方面非常擅长,并开始与该领域的一些顶级人物合作。但是,大约五年前,她对工作的热情耗尽了。她决定转向商业数据科学。
像许多学者一样,她不确定如何实现这一飞跃。从一个世界到另一个她知之甚少的世界是相当令人害怕的。然而,事实上,她已经比大多数有这个头衔的人更像一个数据科学家。在过去十年的大部分时间里,她除了使用 PCA、贝叶斯推理、误差分析、Python 代码、多维宁滨、迭代模型拟合以及天知道还有什么来分析大型数据集之外,什么也没做。
虽然完全符合她想要的角色,但感觉不太适合她。但这并不令人惊讶:同样的自我怀疑模式出现在我共事过的每一位才华横溢的数据科学家身上,我已经在机器学习领域工作了超过 25 年。
我认为优秀数据科学家的标志是他们不觉得自己是一员。他们的眼睛后面总是藏着一点点恐慌,有人会发现他们不是真的,这种感觉永远不会消失。不过没关系。很好,甚至。我也有。但问题是为什么?在我看来,数据科学作为一个领域所面临的显著的冒名顶替综合征效应至少有四大原因。
1:我们被工具淹没了
你学会 TensorFlow 了吗?如果没有,可能已经太晚了。你应该把注意力放在 Keras 上。也就是说,如果你还没有开始学习 PyTorch 的话。但也许你在处理由你的客户定义的大型商业数据流,所以你的人工智能需求正由 Spark MLib 满足。除非你的公司决定你需要 Flink 额外的流稳定性,在这种情况下,你无疑已经得到了 FlinkML 的支持。
除此之外,如果您的客户端已经绑定到 AWS,您的数据馈送可能来自 Kinesis 流。因此,也许在 Sagemaker 上提高技能、理解和认知更有意义。或者,如果你的客户与 MS Azure 有关联,你可能只想使用 Azure ML。
但是等等,我听到你说,你做的大部分工作是调查,就在你的笔记本电脑上。你更熟悉蟒蛇和熊猫。在这种情况下,你肯定想确保你知道 NLTK,Spacey,SciKit-Learn,幕府将军,Theano,SciPy,Seaborn,Plotly 和 Gensim。
有人知道如何正确使用所有这些吗?如果那个人存在,我还没见过他们。然而,当你不知道一个软件包时,总会有一种潜在的感觉,如果你想称自己为专业人士,你应该已经掌握了他们的一些重要和新的东西。这是一个问题,因为每个月都会有新的包和工具到来。一旦你进入机器学习的杂草中,同样的模式就会重复出现,因为总有另一种人们正在谈论的神经网络,网络上充斥着教程,这些教程几乎没有完全解释它们是如何工作的。(实际上让发挥作用所需的数百次重复实验通常被隐藏在视线之外。)
这些工具的真相是,它们中的大多数都有很大的重叠。你不需要把它们都冷冻起来。但这不会阻止你的感觉。我们在 productOps 尝试解决这一问题的方法是,在每个新包发布时尝试对其进行研究,并在我们的数据科学团队中共享知识。我们在尝试深入之前先扩大范围,然后根据项目需要提高技能。我们让自己摆脱对未知的一切,并相信我们会到达那里。这样,理智就更容易坚持。
2:行业言论与实际行动不符
在推动人工智能的许多行业压力背后,是云服务中令人发指的巨额利润。三大供应商都急于让自己与众不同,锁定新客户。他们这样做的一种方式是分发像糖果这样的工具。
你不仅在人工智能和数据科学产品中看到这种模式,在 BI 套件领域也是如此,现在甚至在快速应用原型框架中也是如此。事实上,云提供商会提供几乎任何东西让你站在他们一边。因为真正的钱不在自动驾驶汽车上,而且暂时也不会。真正的钱是彻底检查财富 500 强公司的架构,并让他们在可预见的未来承担云费用。
这意味着,主要技术机构所鼓吹的工具不可避免地会比大多数经营企业的人实际需要的更华丽、更强大。但是当你是一个数据科学家时,很难看到闪亮的数字树的森林。你会看到人们开发出越来越聪明的机器学习产品,肯定有人从中受益。
我们的解决方案是,只在业务情况需要的时候使用闪亮的工具和,并为此感到自豪。如果线性回归为你的客户找到了正确的答案,那么使用深度学习就没有意义。
3:数据科学家的角色定义不明确
数据科学的另一个现实是,这项工作仍然非常模糊。并不是每个组织都需要聪明的新见解。有时候真的有研究要做。然而,更多的时候,问题实际上与数据工程有关。一旦你在数据中发现了有用的模式,你需要一种能够反复识别它们的方法。这意味着,数据科学往往会渗透到数据工程甚至开发运营中。尤其是现在,云提供商正试图提供如此多的现成机器学习解决方案,这些解决方案更多的是即插即用,而不是摆弄变量,直到奇迹出现。
当你将这一点与许多组织仍然不知道他们试图从自己的数据中学习什么的事实结合起来时,事情就变得更加复杂了。有时候,无论你如何努力寻找,令人敬畏的发现并不仅仅是藏在你手里的一大堆日志数据中的*。在其他情况下,你需要制作简单而漂亮的 BI 仪表板,并参与组织性的故事讲述,以证明你的工作或保持你的创业活动。通常情况下,如果你被训练成一名科学家,有些讲故事的过程会让人觉得有点手忙脚乱,即使它对商业成功至关重要。这只会加深症状。*
4:社会训练聪明人永远生活在怀疑中
最重要的是,许多数据科学家在第一天就带着包袱出现了。那些从学术界转行的人(比如我的妻子)经常敏锐地意识到,他们对这个新领域的了解是多么少,而在他们的前世,对前沿成果的深刻把握对职业生涯至关重要。对于那些从其他地方转行过来的人来说,他们通常会敏锐地意识到他们不是而不是职业科学家,并且觉得他们把所有时间都花在了追赶上,不管他们有多聪明或勤奋。
我的版本是这两种感觉的奇怪混合体,多年来游走于商业和科学之间,在这两个地方都没有家的感觉。我花了几年时间才明白“数据科学家”是我所做工作的现代术语,因为当我开始做这件事时,这个术语并不存在。我认为数据科学是一种特殊而不同的东西,不知何故与我一直从事的机器学习、模拟建模、软件工程或统计工具设计无关。回想起来,这似乎不仅仅是愚蠢,但这就是冒名顶替综合症的工作方式。这不理智。
现在我已经达到了我职业生涯中管理一支球队的地步,我试着把这些都记在心里。我努力确保我们互相照顾,相信彼此的智慧。我们给人们留下了足够的空间来说‘我不知道那是什么’或者‘我还不知道那是什么’。在我看来,这是至关重要的,因为对于优秀的数据科学家来说,冒名顶替综合症永远不会消失。这是我们都必须学会接受的事情。
德克萨斯州的房地产投资
你能用时间序列分析预测德克萨斯州的房价吗?
简介
对于这个项目,我使用 Zillow 的美国历史房价中值进行了时间序列分析。其目的是为投资者提供最好的邮政编码,以便在德克萨斯州购买和开发房屋。
我们开始吧!
数据
Figure 1: Zillow Median Housing Prices
数据集包含描述性变量,如州、城市、地区 ID 和县。它还包含一个名为 SizeRank 的变量,在数据探索后,该变量根据城市化程度对邮政编码进行排名。城市化程度越高的地区,规模排名越高。该数据还包括 1996 年 4 月至 2018 年 4 月的房价中位数。这些是我用来进行时间序列分析的值。在深入分析之前,需要满足一些先决条件才能考虑投资。
邮编选择
投资者有几种投资偏好:
- 州:投资者希望专门投资于德克萨斯州,因为该州的人口在过去五年中增长了 10 %,居住在该州的人口的中值年龄为 33.9 岁,而美国的中值年龄为 37.4 岁。
- 城市化:根据 SizeRank 变量,邮政编码应该在前 20 %
- 房价中值:邮政编码区的平均房价应该在邮政编码区 1 年房价中值上下 1.5 个十分位数之间。选择一年期参数是因为这是房地产投资者即将面临的最现实的价格。
- 风险:因为投资者采取规避风险的策略,所以根据低于 60%的变异系数来选择邮政编码。
- 回报:一旦根据投资者的偏好过滤了所有的邮政编码,我就选择投资回报率最高的邮政编码。
当所有的邮政编码被过滤和排序后,我得到了以下五个邮政编码:
Figure 2: Final zip codes
邮政编码属于德克萨斯州的以下城市:
Figure 3: Locations that suited the investor’s needs
现在已经获得了 5 个邮政编码,我继续执行时间序列分析,根据预测的 10 年回报对这些邮政编码进行排序。
时间序列分析
现在可以绘制时间序列,我们可以直观地检查数据。
Figure 4: Exploring price change over time
住房价格中位数有一个积极的趋势,价格可能不是稳定的,因为下一个时期的价格取决于前一个时期的价格。因此,我计算了月度回报,对每个邮政编码进行了模型拟合,并使用月度回报计算了预测。回报更有可能是稳定的,并且具有恒定的零均值。接下来,我开始计算并绘制这五个邮政编码的月回报率。
*# new column for monthly returns* **for** zc **in** range(len(dfs_ts)): dfs_ts[zc][‘ret’] = np.nan *len(dfs_ts) **for** i **in** range(len(dfs_ts[zc])-1): dfs_ts[zc][‘ret’][i+1] = (dfs_ts[zc].value.iloc[i+1]/dfs_ts[zc].value.iloc[i]) — 1
*
#plot the monthly returns for each zipcode* **for** i **in** range(len(dfs_ts)): dfs_ts[i].ret.plot(figsize=(11, 5), color = 'b') plt.title(f'Zipcode: **{dfs_ts[i].ZipCode[0]}**') plt.xlabel('Date') plt.ylabel('Returns %') plt.legend(loc='best') plt.show()
Figure 5: Waxachie’s Monthly Returns
从上面的图中,我注意到数据中没有明确的趋势,数据似乎是稳定的,这是构建模型的一个假设。检查平稳性的一个有用的可视化方法是滚动平均值和标准偏差,它们不应该显示数据平稳的趋势。
**for** i **in** range(len(dfs_ts)):
rolmean= dfs_ts[i].ret.rolling(window=12, center=**False**).mean()
rolstd = dfs_ts[i].ret.rolling(window=12, center=**False**).std()
fig = plt.figure(figsize=(11, 5))
orig = plt.plot(dfs_ts[i].ret,color='blue',label='Orginal')
mean = plt.plot(rolmean, color='red', label='Rolling Mean')
std = plt.plot(rolstd, color='black', label='Rolling Std')
plt.legend(loc='best')
plt.title(f'Rolling Mean & Standard Deviation for Zipcode: **{dfs_ts[i].ZipCode[0]}**')
plt.show()
Figure 6: Rolling Mean
虽然数据看起来不是静态的,但仅仅依靠可视化并着手拟合时间序列模型是不够的。因此,有必要对平稳性进行扩展的 Dickey-Fuller 检验。
Figure 7: Dickey-Fuller Results
从上面的结果来看,五个邮政编码中的两个导致了 95 %置信水平下的非平稳。因此,这四个邮政编码需要将 ARIMA 模型中的“I”参数设置为 1。
ARIMA 模式
ARIMA 代表自回归综合移动平均线。到目前为止,只有“I”参数的值是已知的。现在是时候搜索 AR §和 MA (q)参数来最适合每个邮政编码了。
使用平稳时间序列的自相关函数(ACF)和偏自相关函数(PACF)图来估计 AR 和 MA 参数。
**def** acf_pacf(df, alags=48, plags=48):
*'''Creates the ACF and PACF plots to*
*observe possible parameters for ARIMA model'''*
*#Create figure*
fig,(ax1, ax2) = plt.subplots(2,1, figsize=(13,8))
*#Create ACF plot*
plot_acf(df, lags=alags, zero=**False**, ax=ax1)
*#PACF plot*
plot_pacf(df, lags=plags, ax=ax2)
plt.show()
**def** seasonal_plot(df, N=13, lags=[12,24,36,48,60,72]):
*#differencing the rolling mean to find seasonality in acf plot*
fig,(ax1, ax2) = plt.subplots(2,1,figsize=(13,8))
rolling = df - df.rolling(N).mean()
plot_acf(rolling.dropna(), lags=lags, ax=ax1)
plot_pacf(rolling.dropna(), lags=lags, ax=ax2)
plt.show();
Figure 8: ACF & PACF plots
为每个邮政编码创建了曲线图,以找到 AR 和 MA 参数的最佳估计值。对于大多数邮编来说,这些图遵循一种衰减模式。因此,模型将可能包括这两个参数。
为了进一步帮助寻找参数,使用 Akaike 信息标准或 AIC 执行嵌套 for 循环。AIC 是由 statsmodels 提供的一个值,用于估计统计模型的相对质量,并提供模型选择的方法。与具有较少要素的模型相比,具有较多要素且能很好地拟合数据的模型将被赋予较大的 AIC 值,以实现相同的拟合优度。因此,我们感兴趣的是尽可能低的 AIC 值。
*# Define the p, d and q parameters to take any value between 0 and 3*
p = d = q = range(0,2)*# Generate all different combinations of p, d and q triplets*
pdq = list(itertools.product(p, d, q))
pdqs = [(x[0], x[1], x[2], 12) **for** x **in** list(itertools.product(p, d, q))]
ns = []
**for** comb **in** pdq:
**for** combs **in** pdqs:
**try**:
mod = sm.tsa.statespace.SARIMAX(TS_75165,
order=comb,
seasonal_order=combs,
enforce_stationarity=**False**,
enforce_invertibility=**False**)
output = mod.fit()
ans.append([comb, combs, output.aic])
*#print('ARIMA {} x {}12 : AIC Calculated ={}'.format(comb, combs, output.aic))*
**except**:
**continue** ans_df = pd.DataFrame(ans, columns=['pdq','pdqs', 'aic'])
ans_df.loc[ans_df['aic'].idxmin()]
根据这一估计,获得的 ARIMA 参数(P,I,Q)为(1,1,1),季节分量(P,D,Q,S)为(0,0,0,12)。这告诉我们,数据有 12 个周期的季节性。其他邮政编码也是如此。参数被传递到一个模型上,摘要如下:
Figure 9: Summary of Athe RIMA model
从上面的图中,我们可以看到 KDE 曲线相对接近 N(0,1)曲线,这表明残差是正态分布的。Q-Q 图还向我们展示了残差是正态分布的,因为蓝点(残差)沿着红线(正态分布)。左上角的图表没有显示任何明显的季节性,似乎是白噪声。右下角的图表证实了这一点,因为时间序列残差与其滞后版本的相关性较低。
拟合模型后的下一步是通过将预测值与真实值进行比较来验证模型的准确性。
**def** forecast(df, pred_date, start_date):
*#make these global so they can be accessed later*
**global** pred
**global** pred_conf
*#get predictions from specific date and calculate confidence intervals*
pred = output.get_prediction(start=pd.to_datetime(pred_date), dynamic=**False**)
pred_ci = pred.conf_int()
*#plot real vs predicted values*
rcParams['figure.figsize'] = 15,6
*#plot observed values*
ax = df[start_date:].plot(label='Observed')
*#plot predicted values*
pred.predicted_mean.plot(ax=ax, label='One-Step Forecast', alpha=.9)
*#plot range of confidence intervals*
ax.fill_between(pred_ci.index,
pred_ci.iloc[:,0],
pred_ci.iloc[:, 1], color = 'g', alpha=.5)
*#axes labels*
ax.set_xlabel('Date')
ax.set_ylabel('Monthly Returns')
plt.legend()
plt.show()
values_forecasted = pred.predicted_mean
values_truth = df
rmse = np.sqrt(mean_squared_error(values_truth[pred_date:], values_forecasted))
print('RMSE: '+str(rmse))
print('mean: '+str(df[pred_date:].mean()))
我决定将过去的三年作为测试集,并在此之前对模型进行所有方面的训练。创建模型后,我计算了训练数据集的 RMSE,然后对测试集执行了一步预测,以计算模型的拟合优度。
Figure 10: One-step Forecast
从上图中我们可以看到,单步预测似乎与真实值非常吻合。量化我们预测的准确性也是有用的。我们将使用 MSE 或均方差,它概括了我们预测的平均误差。
对于动态预测,我们仅使用截至某个时间点的时间序列信息,之后,使用之前预测时间点的值生成预测。
预测
一旦模型被训练好,我就用这个模型来计算未来 10 年的月回报率。有了这些信息,我计算了 1 年、3 年、5 年和 10 年的总回报。
Figure 11: 10-year forecast for Waxahachie
调查结果
在对五个邮政编码进行时间序列分析并预测了十年的总回报后,我向投资者推荐了以下邮政编码:
- 76028:德克萨斯州伯利森(10 年回报率为 448 %)
- 75104:德克萨斯州雪松山(10 年回报率为 187 %)
- 75165:德克萨斯州沃克西哈奇(10 年回报率为 127 %)
拥有更多房地产投资领域的知识将提高分析能力。这些模型可以通过考虑其他外部变量来改进。这些其他变量可能包括税率、犯罪率、学区评级和利率。将时间序列分析中的房价和月回报率进行比较可能会很有趣。两者的结果将改善决策过程。
请注意,这个项目只是时间序列建模的一个练习,不应该作为实际的房地产投资。
自动气象站的实时异常检测
数据越新,就越具有可操作性和价值。这是实时数据分析的基本逻辑。
可能会有一些用户进行可疑的活动,或滥用您的折扣。另一方面,你也可以只是观察客户的行为并采取行动。为了实现这个目标,我将介绍如何使用 AWS 工具创建一个实时数据分析应用程序。
Picture taken from AWS Docs
想象一下,你想要实时观察的最后一千个数据点就画在上面这样的 2D 图上。我们的应用程序将能够捕捉那些暗示异常值的红色点。最重要的是,我们还建立了一个警报系统,只要出现一个红色点就会触发。
管道
投入
我们的应用程序的输入实际上*可以是任何流数据。*然而,我们需要它成为可操作的数据,以便我们的异常检测应用程序有意义。后端的方法日志、来自移动应用程序的点击/触摸事件或数据库更改事件将会很好,因为它们的性质赋予了我们观察客户端动作的能力。
溪流
我们如何将现有数据接收并传输到我们的应用程序中?AWS Kinesis 是一个非常方便的工具,易于使用,易于配置和自我管理。坦率地说,Kinesis 由 3 个不同的服务组成;对于流媒体,我们将使用 Kinesis 数据流。
为了创建一个 Kinesis 数据流,你需要给它一个名字,并为它选择碎片计数。碎片是 Kinesis 流的处理单位,在我写这篇文章的时候,一个碎片可以每秒接收 1MB 和 1000 条记录,每秒发出 2MB。对于大多数基本应用程序,1 个 shard 足以处理您的输入数据。
摄取
现在我们已经创建了流,我们可以接收实时数据了。有官方库可以使用 AWS 工具,例如:
- botoforPython 2
- boto3 为 Python 3
- AWS-SDKfornode . js
我们只需要我们想要放置记录的流的名称,以及写入该流的权限。
数据分析应用
为了处理数据并从我们的实时数据中捕捉异常,我们将使用 Kinesis 的另一项名为 Kinesis 数据分析的服务。这是一个非常灵活的工具,它使我们能够在应用程序处理数据之前对数据进行预处理,然后使用丰富的 SQL 引擎处理数据,并对应用程序捕获的数据进行后处理。
- 预处理器是一个由 Kinesis 数据流触发的 AWS Lambda 函数,它可能会丰富数据或清理数据。如果我们想在应用程序中使用一些其他数据,我们可以用这些数据丰富我们的输入。此外,我们可能希望通过类型转换来清理输入,或者移除未使用的字段。
- 异常检测是我们的 Kinesis 数据分析应用程序的名称。它是用 SQL 编写的,并增加了特殊的分析功能。我将在下一部分对此进行更深入的探讨。
- 后处理器是一个 AWS Lambda 函数,由 Kinesis 数据分析为其每个结果触发。你可以对结果做任何你想做的事。您可以将它附加到一个警报系统,或者您可以调用一个端点,或者您可能希望用该数据训练一个模型。灵活性是存在的。
警报
AWS 提供了一个名为简单通知服务的工具,您可以用它来创建警报系统。在我们的例子中,我们将异常检测应用程序的结果发送到一个 SNS 主题。然后,订阅该主题的每个用户都会收到一个通知,比如说,一封电子邮件。
因此,我们的管道如下图所示。你可以断开 Lambda functions,或者 SNS,用你想要的另一个服务来代替。这种方法提供了灵活性,同时借助 AWS 工具保持了自我管理和持久性。
数据分析应用
在 Kinesis 中创建数据分析应用相当简单:
- 我们选择应用引擎,SQL 或 Apache Flink。我们将在我们的案例中使用 SQL。
- 我们选择一个数据源,Kinesis 流或 Kinesis 消防水带交付流。在我们的例子中,我们将使用 Kinesis 流。
- 可以创建一个 lambda 函数来预先预处理数据。
- 由于我们是用 SQL 构建我们的应用程序,我们的数据需要严格类型化,这意味着需要一个模式。Kinesis 数据分析具有自动推断模式的功能,然后您可以根据需要编辑模式。
An example schema enforced data analytics app input format
- 我们可以连接另一个称为参考数据的数据源,以便在应用程序中使用。我们将暂时忽略它。
- 我们可以在 Kinesis 流、Kinesis 消防水管输送流或 Lambda 函数中选择结果的目的地。在我们的例子中,选择了一个后处理器 Lambda 函数来将数据发送到 SNS 以创建警报。
- 至于应用程序的代码,人们需要阅读 AWS Kinesis 数据分析 SQL 参考文档。SQL for data analytics 应用程序增加了分析功能和技术,如流、泵和窗口。我将在接下来的章节中略微谈到它们。
整体逻辑
- 有流像带有 TTL(生存时间)数据的表。
CREATE OR REPLACE STREAM "DESTINATION_SQL_STREAM"
(
"field1" DOUBLE,
"field2" INTEGER,
"ANOMALY_SCORE" DOUBLE
);
- 还有将实时数据输入数据流的泵。
- 您可以用名称
SOURCE_SQL_STREAM_001
访问您的输入流。 - 代码的输出应该是一个流。你需要把结果注入到这条流中。
CREATE OR REPLACE PUMP "STREAM_PUMP"
AS INSERT INTO "DESTINATION_SQL_STREAM"SELECT "field1", "field2", ANOMALY_SCORE
FROM TABLE (RANDOM_CUT_FOREST(CURSOR(SELECT STREAM "field1", "field2"
FROM "SOURCE_SQL_STREAM_001"
WHERE "field1" > 0 AND "field2" > 0
ORDER BY STEP("TEMP_STREAM".ROWTIME BY INTERVAL '10' SECOND);)));
上面的代码片段实际上构建了一个完整的实时数据分析应用程序代码。我们确实从 windows 中的流中读取了 field1 和 field2 ,我将在这之后谈到,并将它们应用到后台使用机器学习的RANDOM _ CUT _ FOREST内置 SQL 函数中。该模型被增量地训练,并且在为具有足够数据来训练的模型输入一些数据点之后,可以说出一个数据点是否是异常。随机切割森林函数的结果被泵入目标流。
Windows 操作系统
窗口让我们能够对数据执行聚合功能。例如,要对实时数据进行计数,我们需要为数据设定边界。
窗口有不同的技术,但我将只通过最常用的窗口:翻滚和滑动。
- 滚动窗口分批分离数据。这些批次的界限通常以时间为基础选择,很少以数据计数为基础。我们想要使用滚动窗口的根本原因是我们不会两次使用相同的数据点。
GROUP BY field1,
STEP("SOURCE_SQL_STREAM_001".ROWTIME BY INTERVAL '60' SECOND);
- 进行时基聚合时,滑动窗口更有用。有一个固定大小的窗口,它逐渐向右移动。你可能想用它来观察一个峰值点。
WINDOW W1 AS (
PARTITION BY field1
RANGE INTERVAL '1' MINUTE PRECEDING);
您还可以构建自定义窗口或使用交错窗口,每当新数据点到达时都会创建一个窗口。
高级用法
Kinesis 数据分析 SQL 引擎让您可以灵活地创建更复杂的逻辑来处理更困难的情况。
- 如果我们只想发送异常值大于特定值的记录,该怎么办?或者,如果该分数需要与一些其他参考数据聚合在一起呢?为了解决这些问题,可以在应用程序中定义第二个流。异常检测算法的结果应该被泵送到这个新的临时流中,而不是我们的目的流中。然后,我们有另一个窗口来对我们的结果数据进行新的聚合。这种新聚合的结果现在可以被注入到我们的目标流中。
从上面的例子可以看出,可以有多个不同窗口类型的流。
结论
我已经经历了灵活的结构,强大的 SQL 引擎与实现流技术,自我管理服务的 AWS。我们已经创建了一个示例实时数据分析应用程序,用于检测数据中的异常。我们利用 AWS Lambda 在手动数据分析应用之前和之后对数据进行预处理和后处理。我们使用 AWS SNS 创建了一个警报系统,一旦出现异常情况,该系统就会实时通知我们。
感兴趣的
Zynga 技术团队展示了他们对 Kinesis 数据分析的使用,以及他们如何使用它来解决复杂的情况。
基于指数分布数据的实时异常检测
一个简单的算法可以提示你异常活动
动机
考虑以下情况:您运营一个网站,允许人们预约他们的医生。在过去的一个月中,您观察到有人每 5 分钟预约一次,但略有不同。然而,在某一天监控预约量时,您发现 10 分钟内没有任何预约。然后 15 分钟。然后 20 分钟。在什么情况下你应该关注并跟进,以确保不存在可能阻止人们预约的问题?
衍生物
这是一个常见的统计问题,它来源于对“到达间隔时间”或事件之间的时间的考虑。如果所讨论的事件是相互独立的,并且它们发生的速率在一段时间内是稳定的,那么到达间隔时间是指数分布的。形式上,我们有以下内容:
Exponential PDF, CDF and first two moments
其中 f(y)是 y 的密度函数,y 是到达间隔时间的随机变量。累积分布函数 F(y)表示观察到小于 y 的值的概率。
这是一个非常好的、简单的分布,它将允许我们实时地对观察到的数据做出一些快速的推断。再次考虑上面的例子。我们声明预约之间的平均间隔时间是 5 分钟。所以平均每分钟,我们观察到 0.2 个约会——这是到达率,或者上面指定的模型中的λ。
我们的目标是提出一个阈值,以便在没有预约的情况下经过足够长的时间后,我们将认为不活动是异常的。这个阈值有点武断——就像统计推断中的大多数显著性阈值一样。但是让我们想出一个阈值(c ),使得通过该阈值的概率小于 1%。数学上,这看起来像
这告诉我们,观察到超过 23.02 分钟的到达间隔时间的概率小于 1%。如果我们只考虑这一个事件,我们会认为观察到这个到达间隔时间是罕见的,我们会将其归类为异常值并进行随访。当我们将我们的容忍水平(也称为“生存概率”)从 1%更改为其他值时,我们可以看到阈值是如何变化的:
直觉上,观察到较高到达间隔时间的概率降低。如果我们将容忍度设置为 0.1%,那么我们将有一个 34 分钟的阈值。这个“生存函数”在保险等其他领域有很多应用(想想人寿保险和死亡率)。我们可以看到,从大约 20 分钟开始,概率变得非常小,并且渐近接近于零。这个尾部的值应该让我们停下来研究一下。
现在让我们停下来,思考一下这个结果给了我们什么。这个推导所代表的是观察到单一随机事件的概率。有了足够的数据或事件,这些离群事件就会发生最终。这就是指数分布的本质——所有正值都有可能出现。在现实世界中,由于自然限制,这可能不是真的,但它是近似的。这个阈值的推导并没有给我们一个完美识别异常的幻数。这意在引起一些人的注意,并刺激对什么是可能异常的调查。或者换句话说,它意味着标记那些不太可能是纯粹随机的结果的事件。
此外,验证之前做出的关于事件独立性和到达率稳定性的假设非常重要。如果其中任何一个不成立,模型就会崩溃。
从数学到应用科学
从数学练习到应用的、生产就绪的算法需要几个额外的步骤。整个过程中更重要的部分不是统计数据,而是与生产环境的集成。我不打算深入设置生产管道的血淋淋的细节——无论如何,这些细节中的许多都是特定于上下文的(Azure vs AWS vs Google Cloud 都是不同的)。然而,我提供了一些我发现对这种练习特别重要的细节。
在处理真实数据时,会出现一些实际障碍。如上所述,即使您确信数据是独立的,到达率也很容易随时间而变化。在预约的情况下,潜在的患者行为可以改变,或者新的提供者可以添加到您的网络中,然后更多的患者可以访问在线调度(可能会增加到达率)。此外,到达率可能因一天中的时间甚至一周中的日期而异。在这种情况下,考虑基于这些类型的变量来调节平均值是有意义的。代价是样本量的减少,这也阻止了对平均值的精确估计。
接下来,根据数据的提取方式,真正的实时检测可能是不可能的。如果数据是直接从一些实时流媒体服务中提取的,那么就有可能获得更实时的感觉。然而,如果在您的算法和初始数据源之间有一个 ETL 管道,可能会有很大的延迟。
如果有延误,也不一定是世界末日。视上下文而定,可能根本不重要。例如,如果 ETL 管道每 5 分钟运行一次,并且捕获的数据的平均到达时间为 2 分钟,则以 1%计算的异常将出现在 9:12 分钟标记附近,这意味着算法将在 10 分钟标记处拾取它,增加了 48 秒的检测过程。几乎在任何情况下,这都不应该成为交易的破坏者。你只需要决定什么最适合你的环境。
最后,如果 ETL 备份或失败,一旦 ETL 再次开始运行,这可能会触发算法将事件分类为异常值。显然,这些不是真正的离群值。
如果这些障碍可以避免(或充分处理),那么算法是简单明了的。核心代码可以用几行代码来概括。只进行一次比较,即(I)自上次事件以来经过的当前时间和(ii)上面推导出的阈值。如果经过的时间大于阈值,则标记该事件;如果不是,那么什么也不做。简单!
结论
我们已经走过了一个方法,推导出一个简单的指数分布数据异常检测技术。通过一些基本的假设,一个好的模型和公式可以应用于到达间隔时间,以标记那些预先定义的“太长”的时间。这种方法不是识别实际异常的简单方法,而是识别不太可能偶然发生的事件的方法。
虽然这个讨论的核心是一个数学练习,但实现和相关的障碍是更重要和更实质性的组成部分。这些障碍包括(1)选择包含在模型中的一致准确的到达率,(2) ETL 管道引入实时数据访问的延迟,以及(3) ETL 失败可能在结果中引入假阳性。一旦这些问题得到充分解决,实际的算法就是一个简单的过程。
考虑 1000 个事件的集合。每个都有 1%的概率被归类为异常值。而非在整个集合中看到异常值的概率是 0.99⁰⁰⁰= 0.004%,这非常小。换句话说,虽然对于任何给定的事件,可能不太可能观察到异常值,但很可能在足够大的样本中至少会出现一个异常值。
使用 Tensorflow 对象检测 API 和 iOS 集成示例进行实时汽车/行人/车道检测
Prediction with mPA > 80% using ssd_mobilenet_v1_pets.config with pretrained ssd_mobilenet_v1_coco_2018_01_28 nets
Total Loss decrease with respect of optimization steps. 100 training photos and 20 testing photos. Better results can be achieved with more data.
受到其他人在异议检测项目上的工作的启发,例如
- 如何使用 TensorFlow 的对象检测器 API 训练您自己的对象检测器,它演示了如何使用 Tensorflow 的 API 来构建和训练用于对象检测的定制 DL 网络。
- 如何构建实时物体识别 iOS app ,演示了如何将一个经过训练的 DL net 集成到 iOS app 中。
然后,我真的很想尝试如何使用类似的程序来建立自己的网络,在 iOS 的实时摄像头中检测汽车/行人/自行车(+车道)。结合我之前关于自适应巡航控制的帖子,集成的功能应该真的很有意思。
在我进一步谈论技术细节之前,为了节省你的时间,使用的软件版本必须放在最前面。我在使用 Xcode 7.3 版本的 macOS EI Capitan 时遇到了一些问题,所以在我的尝试中,我不得不将我的系统更新到 Xcode 10.2 版本的 Moyawe。主要问题是我尝试[例 2](http://How to build real-time object recognition iOS app, which demonstrates how integrate a trained DL net into iOS) 的例子时,我 iphone 8 上安装的 app 一直碾压。
Tensorflow 是使用 pip 虚拟环境 1.9.0 版安装的。在我使用 1.8 之前,问题是当我试图冻结用于 iOS 检测 app 的训练图时,它总是失败,并出现错误“non_max_suppression()”。
根据这篇帖子,tensor flow for iOS 版本为 v1.11。我也安装了最新版本,但是[例 2](http://How to build real-time object recognition iOS app, which demonstrates how integrate a trained DL net into iOS) 中的代码无法成功编译。因为我想将周围的框添加到检测到的项目中,所以我必须回到 1.11 版。
如果你想知道更多的细节,请在下面评论,我会试着分享更多我的经验。
图片报和培训网
- 正在准备输入 TFRecord 文件
首先,我从这里得到合适的数据集。只使用了 120 张图片,100 张用于训练,20 张用于测试。记录的街道快照用于训练。然后我用 labelImg 来标记物体。我的标注地图包含三个项目,如下所示
My model contains three items: car, pedestrian and bike
手动给物品贴标签既无聊又对眼睛有害。所以我建议你使用一些聪明的方法来这样做,比如使用一些自动注释工具。实际上,这种注释过程也与使用机器学习(ML)技术的对象检测/分割/分类的主题相关。如果我有时间,我会写另一个关于它的故事。
在对来自 100 张训练图片和 20 张测试图片的对象进行人工标记之后,对象在 2D 图片中的位置被保存为 xml 格式。然后,我使用以下两个步骤来获得 TFRecord 格式,它将被直接提供给 TF 训练过程。使用的代码可以从我的 github 下载。有些文件是来自 Dat Tran 的 github 库的令牌。
转换图片+xml = > TFRecord 文件
- 为每个数据集将单独的
*.xml
文件转换为统一的*.csv
文件。 - 将每个数据集的
*.csv
文件转换为*.record
文件(TFRecord 格式)。
2.设置培训配置
我目前的目的不是从头构建一个新的网络,而是演示获得定制工作网络的过程。然后我用 TF 发布的 github 的预建配置SSD _ mobilenet _ v1 _ pets . config。不是从一个完全随机的初始化模型开始,而是采用了一个预先训练好的模型,SSD _ mobilenet _ v1 _ coco _ 2018 _ 01 _ 28,以加快训练过程,就像 TF 官网上建议的那样。然后,一些相应的参数设置如下
- num_classes: 3 #设置不同标签类别的数量
- 键入:’ ssd_mobilenet_v1’ #设置为您选择的预训练模型的名称
- fine _ tune _ check point:" pre-trained-model/model . ckpt "#预训练模型提取文件路径
- TF _ record _ input _ reader {
input _ Path:" annotations/train . record “#第一步训练 TFRecord 文件的路径
}
label _ map _ Path:” annotations/label _ map . Pb txt "#标注地图文件的路径如前所示 - TF _ record _ input _ reader {
input _ Path:" annotations/test . record “#测试 TFRecord 的路径
}
label _ map _ Path:” annotations/label _ map . Pb txt "#标签映射文件的路径
3.TF 培训流程
使用以下命令进行训练过程(注意:—必须用两个减号(-)替换)
python train . py-logtostderr-train _ dir =。/training/—pipeline _ config _ path =。/training/SSD _ mobilenet _ v1 _ pets . config
Configuration of my laptop
如果遇到一些错误,首先检查输入数据路径和 tensorflow 的版本。训练过程应该持续很长时间。我的训练是在我自己的笔记本电脑上进行的,花了大约 20 个小时/8k 步。通过调查损失,我终止了它,形成了一个用于 iOS 集成的次优模型。对于更精确的模型,必须使用更多的输入图片。训练过程也可以像 Dat Tran 所做的那样从云中运行。
4.训练数据观察和可视化
Tensorboard 用于即时可视化培训,使用
tensor board—logdir[你的日志目录] — host=127.0.0.1
如果你遇到关于 LC_ALL 的问题,使用下面的命令并重新运行 tensorboard
export LC_ALL="en_US。UTF-8”
导出 LC_CTYPE="en_US。UTF-8”
根据来自终端的弹出信息执行以下操作。因为我对损失很满意,所以我终止了训练并提取了图形。
5.提取/冻结图表
输入类型=图像张量
管道配置路径=。/training/SSD _ mobilenet _ v1 _ pets . config
特训 _ CKPT _ 前缀=。/training/model.ckpt-7265
EXPORT_DIR=。/frozen_inference_graph
python ~/tensor flow/models/research/object _ detection/EXPORT _ inference _ graph . py-INPUT _ TYPE = $ { INPUT _ TYPE }-PIPELINE _ CONFIG _ PATH = $ { PIPELINE _ CONFIG _ PATH }-TRAINED _ check point _ PREFIX = $ { TRAINED _ CKPT _ PREFIX }-output _ directory = $ { EXPORT _ DIR }
如果你遇到***【non _ max _ suppression()】***的问题,尝试使用 TF v1.9.0
构建 iOS 应用程序
直到现在我有了自己定制的训练图,然后我按照这篇文章的步骤开发一个测试 iOS 应用。没有什么特别的事情发生,但是错误信息可能会再次出现。也看看这个 github 帖子,可能会有帮助。由于代码使用了 iphone 的后置摄像头,所以它不能正确地简单运行 Xcode 内的模拟器。应该特别注意一些设置,尤其是头文件和库的搜索和链接路径。其他技术细节可以从 ios 的 tensorflow 官方网站上查看。
我的 iOS 应用程序的最终实现示例,不完美,但足够好,可以更进一步。
未完待续…
- 车道检测
- 网速快一点的,试试 yolo net,不然对一个高速条件没用。
- 距离计算
支持电子竞技观看的实时仪表盘
这一定是我在学术界期间最喜欢的项目。
The League of Legends and Counter-strike: Global Offensive dashboards in action! Read on to learn more.
我的博士学位是通过多个(欧洲和更小的)项目资助的,主题包括学习分析、数字人文和失业。它们很有趣:我设计了桌面、桌面和移动设备上的数据可视化,我研究了用户的感知和体验……所有的乐趣和游戏。
但是不,不是游戏。
我一直对游戏情有独钟。我搬到国外住了两年(并让我的妻子放弃了一份很好的工作),这样我就可以实现梦想,成为一名游戏开发人员(以后再说吧)。将我的研究与游戏相结合是我长久以来的梦想。
唉,没有资金支持这项研究。但是生活总会有办法的,对吧?;)
学生来救援
同学们!当然啦!每年我们都有新的工程硕士学生从事有趣(有时很无聊)的硕士论文课题。所以我引入了一个新的:支持观众的电子竞技仪表板。不同玩家在大型战场上的高节奏行动不容易跟上。那么,我们如何帮助观众在职业玩家玩的这些狂热游戏中,更好地实时了解正在发生的事情。
在学生中取得了巨大的成功,但遗憾的是名额有限,两名学生“中了彩票”(我们对此事没有发言权。挺随机的):Hans Cauwenbergh 和 Bram Luycx。
我们很幸运。这被证明是有史以来与学生最好的合作之一。
仪表板
汉斯跳上了《英雄联盟》,而布拉姆则接下了《反恐精英:全球攻势》。我们在 Reddit 上设计并设置了几项调查,以深入了解观众的动机和对各场比赛提供的不同统计数据的感知有用性,从而为仪表板的设计提供信息。然后,他们就出发了!
Viewer preferences (167 responses for League of Legends, 596 for Counter-strike: Global Offensive)
英雄联盟
a) Gold distribution, b) Damage dealt, c) Vulnerability.
仪表板是五次迭代的结果:两个数字非交互设计,两个交互原型,以及用 React.js 和 D3.js 开发的最终全功能原型。第一次到第四次迭代是使用界面设计工具 Figma 开发的。22 名参与者参与了原型迭代的评估。
主视图分为三个模块:黄金,伤害和脆弱性。所有模块持续实时更新。金和伤害相当明显。我来解释一下漏洞。
漏洞提供了每个玩家有多脆弱的指示。一个简单的线性方程结合了玩家相对于团队其他成员和/或敌人的位置劣势,当前的生命和法力点,防御统计和召唤师法术可用性。这些值被组合并可视化在播放器图标周围,作为一个摘要指示器。这个视图让观众预测游戏的状态。
汉斯还添加了一个有趣的荣格勒可视化:
反恐精英:全球攻势
a) Round progression, b) Economy button, c) Map button, d) Scoreboard, e) Money Distribution, f) Average Damage per Round
该仪表板是三次迭代的结果:一个纸质原型,一个使用 Figma 设计的非交互式数字原型,以及一个使用 React.js 和 D3.js 开发的全功能原型。14 名参与者参与了迭代的评估。仪表板由回合进程、经济、地图、记分牌、金钱分配和每回合平均伤害组成。
结果
通过半结构化采访和眼球追踪,我们设法进一步了解参与者在使用我们的仪表盘观看这些电子竞技游戏时的感知和体验。它产生了一个有趣的观众仪表盘设计目标列表,我们在澳大利亚墨尔本举行的 2018CHI PLAY 上发布并展示了该列表。
LoL and CS:GO eye tracking results from each participant after the evaluation. The attention heatmap indicates the areas of interest where participants focused more during the whole match.
我不会把这篇容易理解的博客文章变成一篇冗长的科学文章。但是如果你对指南感兴趣,你可以在这里找到的文章(或者在我的网站上给我发消息)。或者浏览下面的幻灯片!
如果有足够的兴趣,我将在 Medium 上发布指南的摘要;)就在评论里告诉我吧!
汉斯(全职)和我(兼职自由职业者)并没有止步于此,而是在为GRID eSports Gmbh工作,在那里,大量的电子竞技数据奇迹正在发生!
接下来,我是一名 自由职业数据可视化体验设计师/顾问 。我是被雇佣的,所以如果你有任何 dataviz 需求,来 svencharleer.com打个招呼吧!
基于 Python、Keras 和 OpenCV 的实时人脸活性检测
Image by Jon Tyson from Unsplash.
你在互联网和研究论文上找到的大多数面部识别算法都遭受了照片攻击。这些方法在检测和识别来自网络摄像头的图像、视频和视频流中的人脸方面非常有效。然而,他们不能区分现实生活中的脸和照片上的脸。这种无法识别人脸的现象是由于这些算法是在 2D 框架下工作的。
现在让我们想象我们想要实现一个面部识别开门器。该系统将很好地区分已知和未知的面孔,以便只有授权的人才能访问。尽管如此,不怀好意的人很容易通过仅展示授权人的照片来进入。这就是 3D 探测器,类似于苹果的 FaceID,进入游戏的地方。但是如果我们没有 3D 探测器呢?
Example of photo attack with Obama face ❌ (Image by author)
本文的目的是实现一个基于眨眼检测的人脸活性检测算法来抵御照片攻击。该算法通过网络摄像头实时工作,只有当人们眨眼时才会显示他们的名字。通俗地说,程序运行如下:
- 检测网络摄像头生成的每一帧中的人脸。
- 对于每个检测到的面部,检测眼睛。
- 对于每个检测到的眼睛,检测眼睛是睁开还是闭上。
- 如果在某个时间点检测到眼睛是睁开的,然后闭上,再睁开,我们推断这个人已经眨眼,程序显示它的名字(在面部识别开门器的情况下,我们将授权这个人进入)。
对于人脸的检测和识别,你需要安装 face_recognition 库,它提供了非常有用的深度学习方法来查找和识别图像中的人脸。特别是, face_locations、face_encodings 和 compare_faces 函数是 3 个最有用的*。*face _ locations方法可以使用两种方法检测人脸:梯度方向的历史程序(HoG) 和 C 选择性神经网络(CNN)。由于时间限制选择了 HoG 方法。 face_encodings 函数是一个预训练的卷积神经网络,能够将图像编码成 128 个特征的向量。这个嵌入向量应该代表足够的信息来区分两个不同的人。最后, compare_faces 计算两个嵌入向量之间的距离。它将允许算法识别从网络摄像头帧中提取的人脸,并将其嵌入向量与我们数据集中所有编码的人脸进行比较。最近的向量应该对应于同一个人。
1.已知人脸数据集编码
在我的例子中,算法能够识别我和巴拉克·奥巴马。我选择了大约 10 张图片。下面是处理和编码已知人脸数据库的代码。
既然我们知道了我们想要识别的每个人的编码,我们可以尝试通过网络摄像头来识别和辨认人脸。但是,在移动到这一部分之前,我们需要区分人脸照片和活人的脸。
2.人脸活性检测
提醒一下,我们的目标是在某个时刻检测一个睁开-闭上-睁开的眼睛模式。我训练了一个卷积神经网络来分类一只眼睛是闭着的还是睁开的。所选择的模型是 LeNet-5,该模型已经在【CEW】数据集上被训练。它由大约 4800 个大小为 24x24 的眼睛图像组成。
在评估模型时,我达到了 94% 的准确率。
每当我们检测到一只眼睛时,我们使用我们的模型预测它的状态,并且我们跟踪每个人的眼睛状态。因此,由于下面的函数,检测眨眼变得非常容易,该函数试图在眼睛状态历史中找到闭-开-闭模式。
3.活人的人脸识别
我们几乎拥有了设置我们的“真实”——人脸识别算法的所有元素。我们只需要一种实时检测人脸和眼睛的方法。我使用 openCV 预训练的 Haar-cascade 分类器来执行这些任务。关于 Haar-cascade 人脸和眼睛检测的更多信息,我强烈推荐你阅读 openCV 的这篇伟大的文章。
上面的函数是用于检测和识别真实人脸的代码。它接受论点:
- 模型:我们的睁眼/闭眼分类器
- 视频捕获:一个流视频
- 人脸检测器:一个哈尔级联人脸分类器。我用了Haar cascade _ frontal face _ alt . XML
- 睁眼探测器:一个哈尔级联睁眼分类器。我用了Haar scade _ eye _ tree _ glasses . XML
- 左眼检测器:一个哈尔级联左眼分类器。我用的是Haar cascode _ lefteye _ 2 splits . XML可以检测眼睛睁开还是闭上。
- 右眼检测器:一个哈尔级联右眼分类器。我用了Haar scade _ righteye _ 2 splits . XML可以检测眼睛睁开还是闭上。
- 数据:已知编码和已知名称的字典
- eyes_detected:包含每个名字的眼睛状态历史的字典。
在第 2–4 行,我们从网络摄像头流中抓取一帧,并调整其大小以加快计算速度。在第 10 行,我们从帧中检测人脸,然后在第 21 行,我们将它们编码成一个 128 维向量。在第 23–38 行中,我们将这个向量与已知的人脸编码进行比较,通过计算匹配的数量来确定这个人的名字。具有最大匹配数量的一个被选择。从第 45 行开始,我们试着从面部框中检测眼睛。首先,我们尝试用睁眼 _ 眼睛 _ 检测器检测睁开的眼睛。如果检测器成功,则在第 54 行**,,‘1’被添加到眼睛状态历史中,这意味着眼睛是睁开的,因为 open_eye_detector 不能检测到闭着的眼睛。否则,如果第一分类器已经失败,(可能因为眼睛是闭着的或者仅仅因为它没有识别出眼睛),那么使用左眼和右眼检测器。面部被分成左侧和右侧,以供相应的检测器进行分类。从行 92 开始,提取眼睛部分,并且训练的模型预测眼睛是否闭合。如果检测到一只眼睛闭上,则预测两只眼睛都闭上,并且将“0”添加到眼睛状态历史中。否则就断定是睁眼了。最后,在行 110 处,使用 isBlinking() 函数检测眨眼,如果此人眨眼,则显示其姓名。**
注:完整代码可以在my github上找到。😃
Photo attack thwarted using eye-blink detection ✔️ (Image by author)