如何充分利用计算机科学学位
确保你充分利用大学时光的 7 条建议
卡尔·海尔达尔在 Unsplash 上拍摄的照片
获得学位需要大量的时间、金钱、汗水和眼泪。
然而,仅仅完成一个计算机科学学位已经不够了。
你为了一个职位而面对的数百名候选人中的每一个人都将拥有和你一样的学位和大致相同的技能。
为了在毕业时找到工作,你需要充分利用找工作前的四年时间。你需要在大学期间利用这段时间来确保你在毕业时脱颖而出。
方法如下:
1.把你的计算机科学学位和其他东西联系起来。
如果你有时间管理技巧、兴趣和能力,你应该考虑把你的计算机科学学位和其他东西结合起来。
拥有编码的能力是很棒的。如果能够在一个环境中编写代码,并在一个你实际了解的行业中解决问题,那就更好了。
编程不再是 IT 和软件行业的专利。随着对软件、网站、IT 服务和数据分析的需求变得对保持竞争优势至关重要,计算机科学毕业生正被各个行业所雇用。
虽然房间里的大多数候选人都有编程经验,但只有那些在特定行业有经验并能理解该行业面临的一些问题的人才会让雇主眼前一亮。
在接受彭博快客采访时,Ivana Seric 描述了她独特的数学博士背景,加上她在大学期间是 NCAA 级篮球运动员,如何帮助她成为费城 76 人队的数据科学家。作为一名大学水平的运动员,她对篮球有着深刻的理解,再加上她拥有数学研究生学位,这使得她从竞争该职位的其他候选人中脱颖而出。
这个例子可以应用到你的计算机科学学位上。通过把它和一些让你与众不同的东西搭配起来,你让雇主很难拒绝你的申请。
2.参加活动,拓展你的人脉。
我通过和大学里认识的人保持联系,找到了毕业后的第一份工作。
一天,一位大学同事突然在 LinkedIn 上给我发消息说,他们工作的公司正在寻找一位具有我这种技能的人来完成合同工作。一次简短的面试后,我被这家公司聘为顾问。
在一个越来越多的人拥有学士学位的世界里,利用现有关系获得毕业后的第一份工作变得至关重要。裙带关系仍然存在,尽管它从来都不是一件好事情,但这是世界的方式。因此,你在大学的时间是扩大你的人际网络和建立联系的最佳时间,这些联系可能会在以后的道路上带来回报。
虽然参加社交活动对一些人来说听起来像是一种折磨,但在这些活动中应用的相同原则可以用在你的日常大学生活中,以确保你在你的网络中增加联系。在您的课堂上结交一些朋友,与您的导师互动,并在顶点项目期间与行业专业人士联系。
虽然带着一张非常昂贵的纸离开你的大学项目是最终目标,但也应该带着一份充满同学、导师和行业专业人士的联系名单,他们可能会在未来帮助你。
3.专注于开发实用的编程技能。
计算机科学学位侧重于大量的理论知识,这些知识支持并解释了为什么某些东西可以工作,而其他东西不能。换句话说,理论知识解释了你的代码为什么能工作或者为什么不能工作。
然而,一旦你进入职场,这些理论知识并不像你想象的那么有用。
2007 年的一篇著名文章描述了当一个看起来像开发人员、走路像开发人员、能像开发人员一样谈论理论的开发人员不能编码时产生的怀疑。文章继续描述了大多数计算机科学毕业生在解决臭名昭著的“嘶嘶-嗡嗡”编码问题时是如何被难住的。作者进一步描述了即使是自称的高级开发人员也很难在不到 15 分钟的时间内写出这个简单问题的解决方案。
这篇文章的要点是:不要成为无法解决“嘶嘶-嗡嗡”编码问题的计算机科学毕业生。
严肃地说,这个故事的寓意是,作为一名计算机科学学生,如果你想在毕业后找到一份开发人员的工作,你就需要会编程。这意味着你需要在大学期间专注于开发实用的编程技能。换句话说,你不能只是说说而已。你需要学会走路。
4.研究招聘信息,这样你就知道雇主在寻找什么。
技术变化很快。
比如超快的。
就像这样快,某一天技术可能是“进”的,第二天就“出”了。
不幸的是,计算机科学学位的变化没有那么快。如果说有什么不同的话,那就是计算机科学学位往往落后于时代。
因此,你必须定期研究招聘信息,这样你才能知道雇主在寻找什么样的候选人。
当你毕业后申请开发人员职位时,你不想太晚意识到你需要精通一堆在大学里从未教授过的新技术。此外,这些工作中的许多都在寻找在这些技术方面有几年经验的开发人员。为什么不在大学期间学习这些技术,并利用它们建立一些项目,这样你就可以证明你有必要的技术经验,成为对公司有用和有贡献的成员。
许多毕业生认为,需要特定语言经验的整个概念是需要严格的就业经验。然而,大多数雇主会认为个人使用和表现出的语言熟练程度足以取代受雇经验。
因此,了解雇主在你感兴趣的行业中寻找什么样的技术和技能,并投入一些个人时间来学习这些技术。这是一项保证会有回报的投资。
5.不要忽视发展你的软技能。
软技能让我在毕业后找到了第一份工作。
虽然我需要一个技术背景来了解正在发生的事情和公司试图完成的事情,但我用来完成工作和完成工作的是软技能。
在大学里,看到所有的课程都集中在你想要精通的技术上,这可能是令人兴奋的。当然,您希望成为最优秀的开发人员(或者至少是毕业班的)。
然而,当需要与数百名其他申请人竞争一个初级开发人员职位时,你的软技能将使你脱颖而出。其他每个申请人都将能够编写干净的代码,将获得计算机科学学位,并将能够顺利通过白板面试会议。但是有多少申请人实际上拥有对雇主有用的还过得去的软技能呢?
当我在大学学习软件开发时,大约 25%的课程是商务沟通和组织行为学,这给了我毕业后找到第一份工作所需的软技能。
换句话说,不要忽视软技能。参加一些课程,让你成为一名全面发展的开发人员,这对你最终工作的公司的成功至关重要。你会惊讶地发现,雇主会多么欣赏你写一份精美商业计划书的能力,或者你向众人发表演讲的能力。
6.通过实习、兼职和咨询工作来获得成功。
在我的毕业班中,大多数毕业后找到工作的人都在大学期间实习过。
没有比向雇主展示你在该领域的实习、兼职或咨询工作经验更好的进入该行业的方法了。
不仅如此,你在大学期间可以找到的这些类型的工作是你毕业后在这个行业是否快乐的重要指标。如果你意识到科技行业不适合你,换专业并不丢人。正如老话所说,如果你对自己的工作感到满意,你一生中就不会有一天是在工作。这是你应该瞄准的目标。
许多人会建议,在你攻读学位的每一年都去实习是最理想的。虽然我部分同意这一点,但我也认为你需要考虑几个因素,包括实习是否有报酬(顺便说一下,是时候取消无报酬的实习了),他们希望你工作多长时间,你是否能平衡你的课程和实习相关的工作,以及实习是否真的会给你的简历增色。
不管怎样,没有比在大学里更好的时间来迈出你的第一步了。这些最初的经历将会给你带来回报,让你在毕业后找到工作。
7.立即开始你的专业作品集。
职业投资组合正迅速成为雇主在给你打电话面试之前考虑你能力的标准。
专业作品集是向雇主展示你作为候选人的成长的最好方式之一,也是展示你能够将所学应用到现实生活中的最好方式之一。
因此,你必须尽快开始你的投资组合。
首先建立一个 LinkedIn 个人资料、一个个人网站、一个 GitHub 个人资料和知识库,甚至一个博客(最好是在媒体上——没有比向你未来的潜在雇主解释你每月如何获得报酬更好的方式了,因为人们发现你的博客帖子信息丰富、有用且质量高)。
在你大学的第一年开始这个文件夹,每当你完成一个新的项目或者当你学习一个新概念的时候,把它添加进去。通过展示学习的进展,你将向潜在的雇主展示你愿意踏上特定职业的自我教育之旅。
最后的想法。
当你充分利用计算机科学学位时,它是无价的。
事实是,虽然计算机科学专业的毕业生与其他专业相比失业率较低,但毕业后仍然很难找到工作。
因此,不要浪费你在大学的四年时间仅仅为了获得学位而学习。充分利用它,这样到你毕业的时候,雇主就不可能拒绝你了。
如何获得熊猫数据帧的行数
探讨如何更有效地获取熊猫数据帧的行数
介绍
在今天的简短指南中,我们将讨论几种计算熊猫数据帧行数的方法。此外,我们将展示如何在导出计数时忽略空值。最后,我们将观察本文中介绍的每种方法的性能,并确定计算行数的最有效方法。
首先,让我们创建一个示例数据框架,我们将在本指南中引用它来演示一些概念。
import pandas as pddf = pd.DataFrame({
'colA':[1, 2, None, 4, 5],
'colB': [None, 'b', 'c', 'd', 'e'],
'colC': [True, False, False, True, None],
})print(df)
*colA colB colC
0 1.0 None True
1 2.0 b False
2 NaN c False
3 4.0 d True
4 5.0 e None*
使用 len()
计算数据帧行数最简单明了的方法是使用len()
内置方法:
>>> **len(df)**
5
请注意,您甚至可以通过df.index
来稍微提高性能(在本文的最后一节中有更多相关内容):
>>> **len(df.index)**
5
使用形状
或者,您甚至可以使用[pandas.DataFrame.shape](https://pandas.pydata.org/pandas-docs/version/0.24.2/reference/api/pandas.DataFrame.shape.html)
,它返回一个表示数据帧维度的元组。元组的第一个元素对应于行数,而第二个元素表示列数。
>>> **df.shape[0]**
5
您也可以解包df.shape
的结果并推断行数,如下所示:
>>> **n_rows, _ = df.shape**
>>> n_rows
5
使用 count()
在计算 pandas 中的行数时,第三个选项是[pandas.DataFrame.count()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.count.html)
方法,即返回非 NA 条目的计数。
假设我们想要计算某一列下没有空值的所有行。以下内容应该对我们有用:
>>> **df[df.columns[1]].count()**
4
只有当您希望忽略空值时,才应该使用此方法。如果不是这种情况,那么您应该使用len()
或shape
。
表演
现在我们已经知道了一些计算数据帧中行数的不同方法,讨论它们对性能的影响会很有意思。为此,我们将创建一个比我们在本指南中使用的数据帧更大的数据帧。
import numpy as np
import pandas as pd df = pd.DataFrame(
np.random.randint(0, 100, size=(10000, 4)),
columns=list('ABCD')
)print(df)
*A B C D
0 61 38 2 39
1 96 65 20 47
2 35 56 97 8
3 71 31 80 25
4 20 63 99 34
.. .. .. ..
9995 96 81 6 43
9996 43 22 83 47
9997 62 92 42 26
9998 11 48 91 85
9999 55 47 77 66
[10000 rows x 4 columns]*
为了评估性能,我们将使用[timeit](https://docs.python.org/3/library/timeit.html)
,这在对少量 Python 代码计时时很有用。
>>> **%timeit len(df)**
**548 ns** ± 24.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)>>> **%timeit len(df.index)**
**358 ns** ± 10.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)>>> **%timeit df.shape[0]
904 ns** ± 48 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)>>> %timeit df[df.columns[1]].count()
**81.9 µs** ± 4.91 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
从上面的结果我们可以看出熊猫中最高效的行数计算方法是 **len()**
方法。通过提供索引( **len(df.index)**
)甚至更快。
效率最低的方法是 **count()**
,因此,只有在需要从计数中排除空条目时,才应该使用这种方法。
最后的想法
在今天的文章中,我们讨论了如何使用
len()
shape
- 和
count()
方法。注意count()
应该只在你想忽略某些列的空行时使用。最后,我们讨论了这些方法在性能方面的差异。
成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。
你可能也会喜欢
https://betterprogramming.pub/11-python-one-liners-for-everyday-programming-f346a0a73f39
如何在数据分析中“脱身”
作为一名数据分析师,我学到了一些东西
你有没有过看着数据用头撞墙的经历?我也是。当我开始每天处理数据时,当我碰壁时,我的策略是恐慌和/或压力进食。(我也不推荐。)
照片由 Elisa Ventur 在 Unsplash 上拍摄
下面我整理了一些在这些令人沮丧的情况下对我有用的策略,希望其中至少有一个对你也有用。
数据与预期不符?
1。如果你的“期望”来自别人的数据分析,那就问他们问题。
关于您要比较的数据集,一些重要的问题:
- 这个数据的来源是什么?
- 我们是否知道该数据源的任何限制(例如,数据中是否包含一些场景)?
- 数据集的时间范围和提取日期相似吗?如果不是,数据的波动性有多大?
斯蒂芬·菲利普斯-Hostreviews.co.uk 在 Unsplash 上拍摄的照片
2。仔细检查你的数据清理/格式化。
格式上的差异可能会带来很多问题:前导/尾随空格、数据类型的差异、文本字段的大小写或拼写的差异、舍入问题等。我建议在比较之前对两个数据集进行一些探索性的数据分析,以便在一开始就发现这些问题。
3.在完成所有的基础之后,挑战预期。
有时候,在你开始之前,你的利益相关者就已经有了数据分析的结果。如果你已经检查了你的过程,可能是时候推后并质疑他们期望的来源了,尤其是如果他们没有具体的数据来支持的话。(当然要把这个留到最后——你不会想推回去却发现你的公式在某处不正确。)
想不出自己的错误?
1.快速休息一下。
我数不清有多少次,在工作中或在学校里,我离开一些我搞不清楚的分析,然后回来迅速发现我的错误。有时候,不看屏幕会有助于理清思路。
2.在网上寻找有同样问题的人。
Firmbee.com在 Unsplash 上拍照
这听起来是显而易见的,但是谷歌搜索确实是一门艺术。我会将错误信息中最重要的部分,连同我正在使用的软件或编码语言的名称,复制并粘贴到 Google 中,大多数时候有人会在在线论坛上询问这个问题。利用你正在使用的软件或语言的在线文档也很重要。当你得到一个错误信息时,不要只是举手或者立即联系更了解这个程序的人。
3.变得有条理。
无论是在代码中添加注释,清理文件结构,还是将过程分成逻辑组,“有条理”有助于更容易识别错误。列出你的分析或模型的假设也可以帮助你找出弱点。
4.试着向朋友/同事解释你的过程。
当我和一个同事(和我同级)一步一步地分析 zoom 时,很多时候我会发现自己的错误。当我不这样做时,他或她通常会发现。如果你们两个都不知道,也许是时候去见见你的经理或某个主题专家了。
坐在电脑前等待处理完成?
1.尝试使用数据的子集。
你能从一个更小的数据集开始分析吗?这可能是一个很好的默认技术,因为通过少量的数据样本,您可以轻松地检查流程中不同步骤的结果。或者,你可以把你的分析分成几部分,这样如果第 5 步失败了,你就不会浪费时间去执行第 1-4 步了。
2.如果可以,优化处理能力。
关闭其他程序,确保本地机器有足够的内存和磁盘空间。如果可能的话,我喜欢使用云计算,因为通常你可以访问比笔记本电脑更好的计算资源。根据您所使用的软件/代码,可能有一些方法可以使您的过程更加高效,而不是像
最后,深呼吸。你得到了这个。
想拖延解决问题的时间吗?查看我的一些其他文章:
https://megandibble.medium.com/
如何让您的公司为数据科学做好准备
办公时间
如何在您的公司中利用数据科学
如今,许多公司都在试图成为数据驱动的,甚至是人工智能驱动的。数据科学、机器学习和人工智能(AI)是关于公司数字化转型的几个最主要的术语。有人可能认为这些技术可以解决任何商业问题。在企业内部,数据科学家通常被视为“数字奇才”,他们能够将数据顺利转化为可操作的见解和运行良好的推荐系统。当谈到数据科学项目的需求和可预期的结果时,期望和现实之间存在差距,尤其是非技术人员。是的,这些技术非常强大,是的,数据科学家可以为企业带来巨大的好处,但这两者都只有在特定的条件下才有可能。
在这篇博文中,我将调查这些条件,并展示在企业中成功运行数据科学项目所需的关键促成因素。
IT 基础设施
数据科学并不能为所有类型的业务问题提供答案,在应用数据科学之前,必须有坚实的基础。如果设置不当,企业内部的 IT 基础设施可能会成为数据科学项目的绊脚石。下图描述了数据科学基于需求的层次结构:
数据科学需求层次(图片由作者提供)
数据收集是金字塔最原始的需求,由软件工程师建立。当然,实际收集的数据取决于公司的流程和产品。例如,在面向用户的产品中,我们会收集关于用户如何与我们的产品交互的所有信息。在这种情况下,我们将通过生成用户数据的应用程序直接检索数据。数据源也可以是安装在机器、建筑物、车辆、设备上的传感器,或者是我们想从中获取数据的任何地方。
下一阶段需要解决移动&存储收集的数据。这意味着公司内部的数据工程师必须确保数据能够可靠地在系统中流动。在实践中,实现端到端的数据连续性是一个主要问题,如果从一开始就没有正确设置,就很难实现。由于大多数数据科学项目都包括某种类型的模型拟合,因此我们应该已经在这个阶段考虑了这种互连的架构,以确保训练数据集可以随着新数据的收集而不断更新。
一家公司有不同的数据存储选项:
内部数据存储
- 由组织自己拥有和管理的服务器
- 最大程度地控制网络和数据
- 需要构建和维护 IT 基础架构
- 硬件:硬盘(价格合理,性能良好),固态硬盘(最高性能,最高成本)
托管数据存储:
- 异地保存的数据存储(在数据中心或云提供商处)
- 云通常比本地托管选项更便宜
- 可扩展,能够适应业务需求
- 敏感数据的存储需要关注,数据控制是一个问题,需要具体问题具体解决
- AWS、GCP 或 Azure 等云提供商在其生态系统中提供了大量技术,可以将原始数据转化为有意义的见解、产品或服务
混合数据存储:
- 对非敏感数据使用外部提供程序
- 本地存储敏感数据
此外,公司将需要决定如何实际管理他们的数据。整合不同来源数据的传统解决方案是数据仓库。数据仓库的架构非常好,可以创建一个清晰、一致和高性能的模型,业务用户可以轻松地使用它来获得洞察力和做出决策。随着数据成为价值最高的资产,像数据科学家这样的新角色开始出现,从数据中寻求价值。这个新角色要求数据探索和转换具有敏捷和特别的性质,这推动了数据湖的创建。数据的探索&转换是数据科学家为了更好地理解数据而要做的第一步。它包括争论数据,为数据科学过程的下一步做准备。数据湖变得越来越受欢迎,因为它们可以处理来自多个来源的大量数据,利用 Spark 等新技术,实现预测分析、推荐系统、图表分析等新型数据分析。
要考虑的关键方面是,数据科学家可以一致地链接数据,而无需付出很大努力。这要求所有相关数据集都存储在一个地方,或者可以通过适当的应用编程接口(API)进行链接。如果组织中的系统之间没有定义适当的 API,这将降低数据科学项目的速度,并阻止数据科学家高效工作。这是因为数据科学家将大部分时间投入到架构讨论中,寻找实现(半)自动化数据管道的工作区,而不是应用核心数据科学技术。
上层阶段聚合&标记、学习&优化、和建模代表了数据科学的核心部分。它们包括定义指标、为机器学习模型构建特征、应用统计技术、开始用干净的输入数据训练算法、评估结果,以及(希望)部署模型或将分析结果传达给利益相关者等活动。
数据文化
拥有强大数据文化的公司始终依靠数据来做出决策。数据驱动文化的概念将数据视为洞察组织每个部门的主要资源。目的是让员工能够主动查询和使用数据。这需要访问数据、数据治理、关于如何分析数据的方法知识,以及前面提到的适当的基础设施。
数据是数据科学的原材料。如果没有数据,就无法应用数据科学技术。当我们想要利用数据科学时,我们需要主要关注两件事:数据量和数据质量。
数据量
进行实质性分析所需的数据量取决于问题、选择的技术和项目的整体设置。对于高级机器学习技术,我们通常需要大量数据来拟合模型。机器学习模型是用特征来训练的。如果要素数量增加,精确概化所需的数据量将呈指数增长。为了理解这一点,我们需要对维度及其与算法的关系有一个概念。
在下图中,每个方框代表一个数据点。假设我们在一维特征空间中训练算法,因此仅考虑特征 X 用于训练。让我们假设五个数据点对于我们的用例是足够的。现在,如果我们添加特性 Y,我们将需要 25 个盒子来保持我们需要的相同的“数据密度”,因为覆盖是进行学习所必需的。如果我们添加另一个功能,我们将需要 125 个盒子用于训练等等。这就是所谓的维度诅咒。
维度的诅咒(作者图片)
这就是为什么我断言你永远没有足够的数据,因为更多的数据产生更好的结果的可能性非常高。更多的数据简化了噪声的处理,为我们的结果提供了更高的可信度。
数据质量
结果的有效性更多地取决于数据的质量而不是数量。**垃圾输入/垃圾输出:**更多的垃圾只是返回对错误事物的更好的估计。这就是为什么数据科学家总是需要非常了解底层数据。如果他们没有(因为他们是组织中的新人或者在不同的项目之间切换),那么他们将需要与对这些数据有深刻理解的专家密切合作。
脏的、低质量数据的原因是多方面的:
- 用户输入错误
- 遗留系统
- 数据迁移
- 编码标准应用不当/程序员错误
- 不断发展的应用
我们可以从以下几个方面来衡量数据质量:
- 有效性:符合一个模式
- 精度:符合黄金标准数据
- 完整性:数据集包含所有记录
- 一致性:数据集与其他数据集(来自其他来源)一致
- 一致性:数值使用相同的测量单位
熟练员工
数据驱动型组织需要高技能员工。数据科学领域是动态的,发展非常迅速,而作为事实上的标准的技术,例如用于大规模数据处理的 Spark,十年前甚至还不存在。数据科学需要结合计算机科学、数学、统计学和领域知识。
数据科学,一个跨学科领域(图片由作者提供)
数据科学从业者通常需要以非技术的方式在演示文稿中传达他们的核心信息和发现,以便更广泛的受众能够理解它们。相应地,公司可能也想寻找具有强大沟通技能的数据科学家。
上述技能的结合是罕见的,公司很难吸引和留住这些人才。显然,第一个挑战是支付数据科学家,因为他们在各行各业都有巨大的需求。根据就业网站实际上的数据,在美国,数据科学家的平均年薪为120,334 美元。在欧洲,平均工资较低,视国家而定。据 Glassdoor 报道,德国一名数据科学家的平均工资为€每年 6 万。在英国,平均工资是 53628 英镑,在法国,€是 45198 英镑。在欧洲,瑞士的薪资最高,超过€的 88400 欧元。
然而,要想让数据科学家留在你的组织中,除了高薪还有更多的事情要做。数据科学家离职是因为现实往往与他们的预期不同。他们寻找有意义和有挑战性的项目来利用他们的技能。很多时候,数据科学家成为任何与数据相关的事情的关键人物,并不断被打断他们实际的数据科学工作。这导致员工感到沮丧,因为编写琐碎的 SQL 查询通常不是数据科学家认为的理想工作。与此同时,许多数据科学家属于 Y 一代,他们正在积极寻找自己角色的意义。他们的工作需要符合他们的个人价值观,千禧一代比以往任何一代人都需要管理者更频繁的反馈和沟通。
此外,数据科学家需要与志同道合的人不断交流,讨论新技术、特定项目、实现他们的模型的挑战等等。如果他们孤立地工作,他们将成为孤独的战士。此外,在许多非科技公司,这类职位没有合适的职业发展路径。其他配置文件确实有这些清晰的路径。例如,在项目管理领域,你可能从 PMO 开始,然后得到你自己的第一个项目,直到你成为高级项目经理。在大多数情况下,数据科学家并不存在明确的道路,这种缺乏发展可能性的情况会导致沮丧和离开的意愿。
企业战略
除非你在硅谷地区的科技公司工作,否则人工智能和数据科学很有可能不是你公司战略的组成部分。这对一些公司来说可能绝对没问题,因为并不是每个公司都有望成为科技行业的领导者。然而,如果您的公司正在进行数字化转型,目标是成为数据驱动的组织,那么这些主题及其促成因素对未来至关重要。问题是,在演示文稿上写下这些流行语并假装利用所有新技术很容易,但深入理解这对组织来说实际上意味着什么,并确定人工智能如何帮助加快流程并实施这些技术以减少耗时、重复的任务是一个更大的挑战。
93%具有两位数有机增长的高增长公司计划在未来一到三年内将人工智能实施到他们的业务中,但 94%的企业难以理解如何在其组织中实施人工智能。资料来源:Udacity
在许多公司,业务领导通常不是极客或数据科学家,因此与他们的“数字”员工没有共同语言。然而,企业战略是由企业领导定义的,并通过不同的层级进行级联。这些策略对整个组织及其员工的日常工作有着巨大的影响。但是,在不理解其基本概念的情况下,商业领袖应该如何为一家现代化、数字化、人工智能公司设定路线?简单的回答是:他们不能。但是每个人都可以提高技能,而且有很多这样做的机会。
例如, Udacity 为人工智能、云计算和数据科学领域的商业领袖提供纳米学位。在这些课程中,企业领导学习这些技术的基础、实际应用,并遍历一系列业务案例研究,以找到特定业务场景的最佳解决方案。这些程序是为没有任何编程经验的人设计的,他们需要做出战略决策并评估提议。
提升管理技能的另一种方式是反向指导。通常情况下,导师应该比他的学员更资深、更有经验。在逆向指导中,初级员工与更资深、更有经验的员工甚至经理建立“职业友谊”。反向指导认识到双方都存在技能差距,每个人都可以从对方的优势中学习。年轻员工可以将新技能和想法传授给年长员工,并从其学员成为榜样或职业教练中受益。
关键要点
转变公司以利用新技术是一项具有挑战性的任务,只有满足一些关键条件才能奏效。让我总结一下为现代数据驱动型组织奠定基础的最重要的几个方面:
- **IT 基础设施:**数据科学家需要一个专业的工作环境来利用新技术。正确的数据收集、存储和数据探索工具是实现数据科学的最基本需求。
- **数据文化:**员工和决策者关注现有数据传达的信息,而不是依靠他们的直觉。数据被视为关键资产。
- **熟练员工:**数据科学家是声誉良好的员工,公司需要支付合理的薪水,并为他们提供有意义的项目。
- **企业战略:**企业领导人需要理解这些新技术的核心概念,以便将它们纳入企业商业模式的战略定位。
https://www.forbes.com/sites/forbesagencycouncil/2019/10/01/the-age-of-analytics-and-the-importance-of-data-quality/#2e39afc5c3c4 https://www.matillion.com/resources/blog/5-key-differences-between-a-data-lake-vs-data-warehouse/ https://coopsys.com/data-storage-options-for-your-small-business/ https://www.forbes.com/sites/bernardmarr/2016/06/15/building-your-big-data-infrastructure-4-key-components-every-business-needs-to-consider/#a04611e577e7 https://www.intouchsol.com/blog/six-must-steps-optimal-machine-learning-data-science/ https://www.wsj.com/articles/companies-take-a-piecemeal-approach-to-automation-tech-11554396270 https://sloanreview.mit.edu/projects/artificial-intelligence-in-business-gets-real/
没有任何工作经验如何获得数据科学的第一份工作
创造力、勇气和毅力将成为你赖以生存的三个词
图片来自 Pixabay
无论你是刚毕业的学生,正在寻找职业改变的人,还是和上面这只猫类似的猫,数据科学领域充满了几乎符合现代工作者清单上每一个方框的工作。在数据科学领域工作让你有机会获得工作保障、有晋升空间的高薪,以及在世界任何地方工作的能力。基本上,对于感兴趣的人来说,在数据科学领域工作是一件很容易的事情。
然而,在可怕的求职过程中,我们中的许多人都会遇到类似的情况:
图片由 9GAG
是啊,看起来很眼熟。
我自己遇到过很多这样的情况,公司经常在 22 岁之前寻找有 20 年工作经验的候选人,我理解当你是一名新毕业生、一个想改变职业的人、甚至是一只没有相关工作经验的猫时,试图找工作带来的烦恼。
然而,这不是气馁的理由。虽然许多数据科学工作需要工作经验,但有很多方法可以创造自己的工作经验,让你成为这些职业的合格候选人。
你所需要的只是一点创造力、勇气和毅力。
这不是你知道什么的问题。而是你认识谁,谁认识你。
在与加拿大类似的国家,拥有某种形式的大学资格正成为常态(2016 年,54%的 25 至 64 岁加拿大人拥有学院或大学证书),现在不再是你知道什么的问题了。而是你认识谁,谁认识你。
用谷歌搜索“网络的重要性”,你会被所有主要参与者的文章淹没(福布斯,赫芬顿邮报,事实上,等等。)为什么社交是你职业生涯中最重要的事情之一。福布斯说得好:
“网络不仅是交易信息,也是建立互利的长期关系的途径。”比安卡·米勒·科尔,福布斯
虽然人际关系网是获得如何在特定职业中获得成功的内部知识的一种非凡方式,但它也可以在以后的道路上成为一种互利的关系。
我的第一份科技工作是通过与一位大学同事保持关系获得的。我们是在最后四个月的实习中认识的。毕业后,我们一直保持联系。差不多两年后,我收到一条消息,说他们工作的公司有兴趣雇用我为他们做一些工作。由于保持了这种关系,我在没有任何工作经验的情况下找到了毕业后的第一份工作,这要感谢我的同事推荐了我。
换句话说,在你读大学的时候交几个熟人,参加社交活动,和那里的人交谈,让招聘人员知道你的名字,这些都很重要。
成为一名作家,为个人博客或主要出版物投稿。
数据科学家是天生的故事讲述者,因为他们有能力将海量数据集转化为引人注目的可视化数据,从而向大众讲述故事。正因为如此,有抱负的数据科学家应该写下他们的工作,向未来的雇主展示他们的沟通技巧,这才有意义。
许多数据科学家吹捧在 Medium 这样的平台上开博客或写作的好处。尽管许多人说,写作的好处并不仅限于让你更快乐、更无压力——写作还将有助于你的数据科学事业。
正如我上面提到的,成为一个讲故事的人和一个全面可靠的沟通者,是数据科学家的基本技能,只有在实践中才能提高。例如,通过向公众解释您的数据分析结果,您开始用任何人都能理解和欣赏的简单术语来思考数据。正如理查德·费曼曾经说过的,“我不能把它降低到大学一年级的水平。这意味着我们真的不了解它。”写作不仅会让你成为更好的沟通者,还会让你对数据科学概念有更深的理解,从而让你成为更好的数据科学家。
然而,写作的好处不止于此。
作为一名未来的数据科学家,你写的文章会成为你专业作品集的一部分,让招聘人员了解你对特定概念的理解。他们不仅能够看到你已经建立了一批信任和重视你的工作的人,而且还能够看到你愿意贡献知识来促进其他数据科学家的生活和事业。此外,在一个为你的工作支付报酬的网站上发布信息会告诉招聘人员,人们非常重视你的知识,你实际上是为此而获得报酬的。
这里有一些资源可以激发你的写作灵感:
成为一名自由职业的数据科学家,建立自己的咨询业务。
海军陆战队队员说得好:随机应变,适应,克服。
与其不断打一场硬仗,不如随波逐流,创建自己的数据科学咨询业务。
我从经验中知道,当你投了一百份简历,得到的却是拒绝信和沉默,这是多么令人沮丧。所以,如果没人愿意雇佣你,那就雇佣你自己吧!
自由职业很容易成为人们为了赚钱所能做的最可怕的事情之一,而且它肯定不适合每个人。然而,这是一个公平的选择,而不是连续几天拿头撞墙,等待潜在雇主给你回复(或者不回复)。
如果你有技能和信心,为什么不接受一些自由客户呢?这是双赢的局面。你不必经历招聘过程中的痛苦和磨难,就能获得现实世界的经验(请注意,做自由职业者可能会有同样多的痛苦和磨难,这就是为什么它不适合所有人)。雇佣自己的好处在于,如果由于积累的现实经验,你最终得到了一家梦寐以求的公司的工作邀请,你可以随时离开自由职业。
但是谁知道呢?也许你最终会真正享受自由职业的生活。在我看来,如果你无法通过传统的方式找到工作,那就值得赌一把。
做你自己的项目来展示你的才华。
如果你问我“数据科学”的定义,我会总结为一个专注于解决问题和收集信息的跨学科领域。因此,雇主不想雇佣任何没有解决任何问题或者不能从数据集中得出任何结论的人是有道理的。
通过创建自己的项目,你向雇主展示了你天生的好奇心和动力,这是数据科学家在工作中取得成功所必需的。不仅如此,科技行业的许多雇主都要求看你的项目组合,这样他们才能在雇佣你之前看到你的工作质量。
现在比以往任何时候都更容易找到免费的数据集来构建项目。以为我在开玩笑?我最后一次检查时,在 Kaggle 上有 67862 个数据集可供任何人使用。这是大量的数据。
此外,快速搜索将引导您找到数百篇充满不同数据科学项目的文章,从而激发您的灵感。这里有几个让你开始。
</12-data-science-projects-for-12-days-of-christmas-aff693f5ed2b> </12-cool-data-science-projects-ideas-for-beginners-and-experts-fc75b5498e03>
实习生、志愿者或做公益工作来获得宝贵的行业经验。
有时候,获得必要工作经验的最好方法就是免费做这些工作。没有人喜欢无偿工作,但是在一个经常要求你在 22 岁之前有 20 年工作经验的世界里,无偿工作通常是你求职成功的门票。
实习、志愿服务或做公益工作是获得许多公司正在寻找的必要工作经验的三种最佳方式。这些“工作”不仅能让你利用真实世界的数据获得真实世界的经验,还能让招聘经理看到你是一名团队成员,你是在没有报酬的情况下辛苦获得工作经验的。此外,你可能会有机会创造有意义的解决方案,并在此过程中对许多个人和社区产生积极影响。如果你工作的公司愿意在你的 LinkedIn 个人资料上写一篇热情洋溢的评论或一封推荐信来补偿你,那就更好了!
最后的想法。
对于任何进入一个新领域的人来说,无论是应届毕业生、寻求职业改变的人,还是一只学会打字的猫,缺乏工作经验都是一个令人生畏的问题。
然而,只要你愿意,有无数的机会让你获得工作经验。幸运往往偏爱勇敢的人,对于那些希望在新领域获得成功的人来说,这一点更是如此。
通过练习一点创造力、勇气和毅力(也可能是一些耐心),你将会顺利地找到第一份梦寐以求的数据科学工作。
如何给你的 Python 代码带来魔力
构建一个强大的多项式引擎,方便学习和研究
图片来自维基共享资源
在本文中,我将向您展示如何用 Python 构建一个学习多项式的工具。
此外,这个工具使用起来应该很直观,感觉就像 Python 自带的内置类型。
我们将使用所谓的邓德方法一起做这件事。
目录
Intro
魔法方法
∘_ _ str _ _
∘_ _ len _ _
∘_ _ getitem _ _
∘_ _ eq _ _,add,sub,mul,floordiv
多项式作为函数
零和图【图
介绍
几年前,我发现了一种有趣的多项式。
我想研究它们的特性,但没有工具来适当地探索它们。有了技术武装,我将通过构建这样一个工具来进行战斗。
在我们构建它之前,让我们快速回顾一下 Python 的 double-under 或*“dunder”*方法。
神奇的方法
邓德方法,有时被称为魔法方法,是以两个下划线开始和结束的类的方法。
这些方法模拟了 Python 的内置功能,比如使用关键字 len 、 + 、 with 等。
为了更好地理解这一点,让我们构建一个表示多项式并支持 Python 语法的类。
描述一个多项式所需的最少信息量是多少?是系数的问题,不是吗?
让我们尝试以下方法:
我们肯定需要系数,其余的只是为了展示。系数只是作为以常数项开始的类构造函数的参数给出。我们将为多项式赋予默认名称 f ,当然我们可以在实例化对象时更改它。
str
说到“显示”,让我们确保用户在打印多项式时看到有用的东西。我们将在上面添加一个名为 str 的 dunder 方法。
来自 str 方法的输出就是你打印出你的对象时所看到的。如果你的类中没有这个方法,那么你只能打印出你的类名,这可能没什么用。
不要太担心方法的内容,一会儿你就会看到它做了什么。
现在,我们能够打印出我们期望看到的多项式。当然,您可以根据自己的需要进行更改,请注意,我们也有一个 repr dunder,它属于同一个系列,但更适合开发人员而不是用户。
作者图片
这很好,但是我们还没有真正对多项式做任何事情。为了给这个类增加一些功能,让我们编写代码来实现多项式的加、减、乘、除以及其他有趣的运算和功能。
len
我们想这样做的方法是使用 dunder 方法来获得工具的直观性。具体来说, len 方法将让我们使用内置的 len 函数来显示多项式的某种长度。在这种情况下,我选择使用术语的数量作为度量。
getitem
当你分割一个列表或者获取第 n 个元素时,你使用 list[n]语法。我们可以对多项式做同样的事情。在这种情况下,我决定我们应该得到第 n 个系数。
_ _ eq _ _ ,_ _ add _ _ ,_ _ sub _ _ ,_ _ mul _ _ _,以及 floordiv
以上方法分别对应**=**, + , - , ***** , // ,唯一需要说明的方法可能是 floordiv 方法,我决定实现这个方法是因为可能要做多项式除法。
我只返回商,而不是余数,如果它应该是非零的。我们也可以选择使用 truediv dunder 方法,但是我认为在这种情况下划分楼层更有意义。
为了更好地理解这一点,您应该亲自试验一下代码。现在,让我们将上述方法添加到我们的类中:
多项式作为函数
我们现在有很多选择。
注意,现在 Python 理解了如何通过使用符号 + 来添加多项式,例如,这给了它在编写代码时更自然的感觉。毕竟,我们现在能够像写数学一样写它。
让我们添加一些功能来实现差异化。
我们将实现一个 prime property 方法和一个更通用的 n 次微分方法,称为 diff 。我们相应地更改名称,以帮助用户跟踪不同的对象。
因为 prime 也返回一个多项式对象,我们的其他方法也处理导数,使我们能够很好地打印出来,并继续处理它。
我们还将添加一个名为 negating_shift 的方法。
我们需要这种方法的原因与我在本文开头提到的研究有关。该方法将采用多项式 f(x) 以及实数α,并返回相应的多项式 f(α - x)。
现在,如果一个多项式不能被调用,它会是什么呢?
我们需要使它成为一个函数对象,它应该能够像我们使用任何其他函数一样计算实数和复数。
让我们将所有这些也添加到模块中。
到目前为止的完整代码:
现在我们可以用一个简单的方法来区分 n 次。还要注意,现在我们可以像调用多项式所代表的函数一样调用它们了!
这要感谢 call dunder 方法。
零和图
我们肯定希望能够找到根,我们也希望能够显示多项式的图形,现在我们有了根,我们也可以找到函数的局部最小值和最大值。
能够显示根在复平面中的位置也是有用的。
因此,我们也可以为此添加方法:
请注意,我们可以更改作为参数的轴的大小。这在某些时候可能会很方便。
现在我们可以得到根或零,也可以得到漂亮的显示和图形。我们在下面看到,单位的 5 根在复平面上构成一个五角星。
显示屏上的点是多项式的复数零点。
到目前为止,我们已经有了很多不错的 Pythonic 功能。我将在未来添加更多的像判别式,因式分解等。在此期间,是时候学习我最初想学习的多项式类了。
这将是一篇单独的文章,因为这篇文章会变得太长。
您可以在这里获得完整的代码:
https://github.com/KRBM/PolynomialEngine/
如果您有任何问题、意见或顾虑,请联系 LinkedIn:
https://www.linkedin.com/in/kasper-müller-96ba95169/
如何像专业人士一样从原始数据走向生产
关于使用合成数据提高数据质量和使用 MLOps 交付模型的探索
机器学习和人工智能这两个概念在过去十年中绝对改变了我们的思维方式,在未来几年中可能会发生更大的变化。但是,我们也知道谈论机器学习时的陈词滥调— “垃圾进,垃圾出”。这是不可否认的事实,人工智能解决方案的关键因素是在正确的时间用正确的数据持续改进。
*听起来很容易,对吧?*但是,如果我告诉您,在正确的时间获取正确的数据并使之成为现实仍然存在许多挑战,那会怎么样?尤其是将数据驱动的应用程序投入生产时。
本文解释了如何通过利用 YData 的合成数据开源工具包来提高数据质量,并确保使用 UbiOps 平台快速轻松地部署,ubi ops 平台是数据科学代码的服务和交付环境。
什么是合成数据?
让我们从基础开始,数据质量可以定义为数据如何准确、完整、一致、可靠,最重要的是,数据是否是最新的。数据是基础,正如下图中的好的和旧的 DIKW 金字塔所描述的那样,在基于机器学习的项目中尤其有效-如果我们没有好的数据,那么我们就不可能有好的信息。
总之,对于数据科学项目来说,及时了解数据的质量可以“决定成败”。
数据金字塔或大多数人所知的 DIKW。来源
在 YData,数据科学团队非常重视数据质量。非常严肃地说,YData 围绕这个概念建立了一个完整的平台。它从访问数据到探索和处理,是综合数据生成的核心特征之一。
合成数据可以成为帮助组织提高数据质量的强大盟友。但是如何?
从它的名字,我们很容易理解它指的不是从现实世界收集的数据,而是由计算机生成的数据。数据合成新技术的最大好处是,生成的数据保持了真实世界的属性。可以使用各种不同的方法生成合成数据,然而,当谈到高质量的合成数据时,我们寻找的是生成的数据,它保留了真实数据的实用性、保真度和可靠性,同时保持了隐私合规性。这就是新的方法论所提供的,如变分自动编码器或生成对抗网络。
为什么要为改进的模型训练合成数据?
来自真实世界事件的数据具有广泛的应用,可帮助数据科学团队改进其现有数据集,减少相关和敏感数据的访问时间,并无缝缓解隐含的偏见问题:
- **原型开发:**收集和建模大量的真实数据是一个复杂而乏味的过程。生成合成数据使数据更快可用。除此之外,它可以帮助更快地迭代 ML 计划的数据收集开发。
- **边缘情况模拟:**通常可以看到,收集的数据并不包含对模型性能产生负面影响的所有可能场景。在这种情况下,我们可以通过人工生成来包含那些罕见的场景。
- **数据集扩充,偏差&公平性:**并非所有时候我们都有所需的数据量,或者在其他情况下,我们可能会处理某些类别中的代表性不足问题。自动化决策会使这些问题变得更糟,但合成数据是缓解这些问题的一个很好的选择。
- **数据隐私:**合成数据是确保数据隐私的绝佳方式,同时能够共享微数据,允许组织共享敏感和个人(合成)数据,而无需担心隐私法规。
什么是机器学习操作?
机器学习操作(MLOps)的核心是一套流程和最佳实践,为运行和管理与机器学习相关的一切提供可靠的基础设施。这就产生了一个可预测的、稳定的、安全的环境。如果没有 MLOps,许多机器学习算法仍然会在一些数据科学家的笔记本电脑上运行。这不是运行关键业务算法的好方法。
好吧,假设您对(本地)模型性能感到满意,并且您想继续让您的模型在您公司的基础设施(由 IT 部门维护)上运行。然而,在将模型代码和数据完全部署到生产环境中之前,它们通常会在数据科学团队和 IT 团队之间进行不同的交接。这不仅耗时,而且令人沮丧,并会导致时间和预算耗尽或安全性受损等风险。这就是为什么理想情况下,数据科学家不仅参与构建数据集和模型训练,还参与模型服务和托管。当然,它必须对流程的安全性和健壮性感到满意。这样就很容易进行迭代,可以快速传递变更,最终的应用程序可以在预期的时间内交付预期的价值。
UbiOps 为您处理许多 MLOps 任务,以便您可以专注于创建有价值的算法,同时仍然在专业环境中使用它们。并且不需要任何 IT 专业知识。
MLOps 的一些示例包括:
- **可扩展服务:**算法应该是可扩展的。对你的算法的需求通常不是恒定的。有了可伸缩性,您总是拥有适量的资源。降低成本并保持速度。
- **标准化和可移植性:**在任何专业环境中,拥有可重复和可预期的结果都是关键。在 MLOps 中,这可以归结为拥有标准格式的模型,可以在任何地方运行,最重要的是在任何地方都可以运行。
- **版本控制:**可靠性与理解和跟踪项目中的变更有很大关系。例如,这有助于在出现问题时快速恢复到旧版本。不仅仅是在源代码层面上,比如 GIT,而且在服务层面上,如果一个新版本出现了意想不到的问题,不同的版本已经准备就绪。
如果你想了解更多关于 MLOps 的信息,你可以看看 MLOps 的 10 条戒律
把所有的放在一起:从原始数据到生产
在现实世界中,遇到非常不平衡的数据集是很常见的。这种类型的行为常见于不同的行业,从金融服务到电信或公用事业,以及许多使用案例,如欺诈检测或预测性维护。通过这种类型的行为来增强数据集的大小和质量的有效方法是通过数据扩充。
想象一下,作为一名数据科学家,您开发了一种检测信用卡欺诈的算法,但由于可用的数据集不平衡,您对结果不满意。最重要的是,您的所有代码都在笔记本电脑上运行,这不适合生产。
高度不平衡的数据。数据来源:来自 Kaggle 的信用卡诈骗
使用诸如合成数据生成器这样的工具,可以让你快速地从代表性不足的班级中学习和复制模式。 YData 的开源存储库允许您探索和试验不同的合成数据生成方法。使用 ydata-synthetic 库,只需几行代码就可以轻松生成合成数据。
使用 ydata-synthetic 库时,您可以通过几行代码轻松生成合成数据:
用 WGAN-GP 生成合成数据
通过将新的合成欺诈与真实数据相结合,您可以轻松提高分类器的质量和准确性。在本例中,我们使用带有梯度惩罚的简单 WGAN 获得了良好的结果,但有许多参数需要调整,还有其他问题需要担心,例如数据维度、生产数据集的规模以及其他问题。这就是 YData 平台所提供的,一种大规模利用最新深度生成数据综合并针对不同用途进行优化的方式。
不同的参数选择会有不同的结果。来源
但是数据科学的生命周期并没有随着模型训练和测试而结束。在获得符合业务预期的结果之后,我们需要将模型交付到稳定的生产服务环境中,并开始为最终用户交付真正的价值。
如何在不掌握容器、Kubernetes、API 开发等概念的情况下做到这一点?对于我们这些数据科学家来说,令人高兴的是,随着 MLOps 工具的兴起,如 UbiOps ,数据科学家现在不仅控制着模型开发的整个过程,还控制着交付和维护。
您可以轻松地重现和测试这个欺诈用例——y data 和 UbiOps 一起创建了一个笔记本,并在 GitHub 上提供。在这本笔记本中,您将学习如何 1)创建合成数据并从中受益,以减轻与不平衡数据集相关的问题,并进行培训,以及 2)向生产服务环境提供更好的模型。
结论
ML 解决方案的生命周期非常复杂且难以确保,这不仅是因为数据科学家和工程师的短缺,还因为(通常)现有的技术债务。数据质量对模型结果的影响是众所周知的,而实现最佳和最优训练数据集的挑战已经相当大。这使得预处理步骤成为确保可靠性和标准化的最重要步骤之一。
然而,只有当模型投入生产时,数据和模型才会对业务产生预期的影响。MLOps 是确保将模型及时、健壮且可扩展地交付到生产中的关键答案。
YData 和 UbiOps 无缝集成,使数据科学团队能够轻松改进现有数据,并在安全稳定的生产环境中交付模型。
关于 ML 数据质量的更多信息,请查看 YData 的博客。加入合成数据社区获取数据合成更新,查看关于时序数据合成数据的最新帖子。
有关 MLOps 和模型服务的更多信息,请查看 UbiOps 网站以及更多技术使用案例,请参见食谱(或查看 Github )。加入我们的[社区休闲频道](http://UbiOps is a feature rich deployment and serving layer for your data science code, models and scripts. It enables you to run your code live behind a secure serving endpoint in only a few clicks. For more information on UbiOps see our website and for more technical use cases see the cookbook (or on Github). Join our community Slack channel here.)。
如何按期间对年度数据进行分组
我将向您展示如何用 Pandas 将每年的数据分成给定长度的时间段,以及如何用 Matplotlib 绘制它们
凯莉·贝丝·威廉姆斯在 Unsplash 拍摄的照片
去年春天,在我参加的一个课程中,一个客户让我将一些年度历史数据可视化为线图。由于每年可用的数据非常少,客户希望将这些年分成几个时间段。此外,如果年度范围不能与所选的期间长度平均分割,则最后一个期间应该更短。
让我向您介绍一下我的解决方案
首先,我们需要一些数据,我们可以根据年份列将这些数据分成不同的时间段。今天我选择用加拿大的气候历史数据来展示,这些数据可以从 Kaggle 获得知识共享许可。
使用的数据集中的前 10 行。该数据集包含从 1940 年初到 2019 年底加拿大八个测量点的日平均温度和降水量。
我们将使用熊猫,NumPy 和 Plotly
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
让我们从将数据读入数据帧开始。然后,让我们缩小数据范围,只包括“本地日期”和“平均温度多伦多”两列。
df = pd.read_csv('Canadian_climate_history.csv')
df = df[['LOCAL_DATE', 'MEAN_TEMPERATURE_TORONTO']]
要创建 year 列,让我们首先将“LOCAL_DATE”列更改为 datetime,它的初始类型是 object。从日期时间类型列中,我们可以提取年份信息,如下所示。
df['LOCAL_DATE'] = pd.to_datetime(df['LOCAL_DATE'])
df['YEAR'] = df['LOCAL_DATE'].dt.year
结果列的类型是 integer,就像我在春天得到的数据一样。
0 1940
1 1940
2 1940
3 1940
4 1940
...
29216 2019
29217 2019
29218 2019
29219 2019
29220 2020
Name: YEAR, Length: 29221, dtype: int64
为了得到结果,我们将调查 1940-2019 年的范围和 20 年的周期长度。对于全年范围,我们会得到一个很好的平均分割,但由于数据中只有一个 2020 年的测量值,这没有意义。
period_length = 20start_year = 1940
end_year = 2019df = df[(df['YEAR'] >= 1940) & (df['YEAR'] <= 2019)]
为了检查分割是否均匀,以及为了确定最后一个周期的长度,我们将取模。
year_range = end_year - start_yearmodulo = year_range % period_length# For 1940–2019 the modulo is 19
接下来,让我们找出最后一期的起止年份。增加一个也是为了包括去年。否则,2019 年将被遗漏,因为它将是下一个时期(如果有的话)的开始年。
if modulo == 0:
final_start = end_year - period_length
else:
final_start = end_year - modulofinal_end = end_year + 1
然后,我继续使用 NumPy 创建一个列表,列出该年范围内所有较早开始的年份。
starts = np.arange(start_year, final_start, period_length).tolist()
然后,让我们创建元组列表,其中每个元组类似于(period_start,period_end)。从这些元组中,我们最终可以创建熊猫interval index的库。
tuples = [(start, start+period_length) for start in starts]
# We'll add the last period calculated earlier
tuples.append(tuple([final_start, final_end]))bins = pd.IntervalIndex.from_tuples(tuples, closed='left')
然后,通过将它们转换为字符串,这些 bin 可以很好地转换为标签。例如,当周期长度为 20 时,“1940,1960”将是第一个标签。在这里,我们可以看到 bin 是如何显示周期在左边关闭,在右边打开的。为了清楚起见,我同意客户将它们描述为“1940-1959”。我创建了一个字典,便于在数据框中替换。
original_labels = list(bins.astype(str))new_labels = ['{} - {}'.format(b.strip('[)').split(', ')[0], int(b.strip('[)').split(', ')[1])-1) for b in original_labels]label_dict = dict(zip(original_labels, new_labels)) # The label dict when year range is 1940-2019{'[1940, 1960)': '1940 - 1959',
'[1960, 1980)': '1960 - 1979',
'[1980, 2000)': '1980 - 1999',
'[2000, 2020)': '2000 - 2019'}
然后,使用 Pandas cut() ,我们可以轻松地将 year 列的内容放入这些 bin 中,并创建一个新列“PERIOD”。最后,在 label_dict 的帮助下,bin 标签被替换。
# Assign each row to a period
df['PERIOD'] = pd.cut(df['YEAR'], bins=bins, include_lowest=True, precision=0)
df['PERIOD'] = df['PERIOD'].astype("str")
df = df.replace(label_dict)
最后,我们按照 PERIOD 列对数据进行分组。我去掉了年份一栏,只是为了让 df 更整洁。
df = df.groupby('PERIOD').mean().reset_index().drop('YEAR', axis=1)
最终数据帧
现在我们可以用 Matplotlib 可视化它
# Styling of the figure
fig = plt.figure()
fig.set_figwidth(12)
fig.set_figheight(5)
fig.patch.set_facecolor('white')plt.plot(df['PERIOD'], df['MEAN_TEMPERATURE_TORONTO'], color='#004cff')plt.title(f"20-year average of daily mean temperatures in Toronto between {start_year} and {end_year}")
plt.xlabel("Period")
plt.ylabel("Mean temperature") # Styling of the plot
plt.grid(color = 'white', linewidth = 1)
plt.locator_params(axis='y', nbins=6)# Styling of the axes
ax = plt.gca()
ax.set_facecolor('#e6ecf7')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.tick_params(axis=u'both', which=u'both',length=0)plt.show()
结论
当每年只有少量可用的数据点,或者当数据点的数量在各年之间变化很大时,为每年的数据创建周期是有益的。为了清楚起见,我鼓励用确切的年份(例如“1940-1959”)来标记周期,而不是用数学区间来表示限制是封闭的还是开放的(例如“[1940-1960)”)。
感谢您的阅读!如果你学到了新的东西或者喜欢这篇文章,在 Medium 上跟随我。我目前正在撰写关于 NLP 和数据工程的未来文章。你也可以在 LinkedIn 上找到我。
你对完成这项任务有其他想法吗?如果你能在评论中告诉我,那就太好了😊
如何在 6 个月内从非编码人员成长为数据科学家
包含所有必需资源的完整指南
卡尔·海尔达尔在 Unsplash 上拍摄的照片
许多背景各异的人通过 LinkedIn 联系我。寻求将职业生涯过渡到数据科学的技巧和建议。我曾经认为,网上有大量免费学习数据科学的资源。他们为什么问我?在和一些我清楚了解的人交谈后,
- 选择的丰富已经成为一种诅咒
- 许多人不知道如何以及从哪里开始?
- 有些人就是不够自信
- 一些人寻求灵感和动力
- 有些人只是想知道他们是否有机会
- 他们大多数人都在寻找一个清晰的计划
我还浏览了一些数据科学初级职位的职位描述。很明显,期望被定得很高。这进一步导致了很多压力和焦虑,尤其是在非技术背景的人群中。这也是为什么许多人在整个学习过程中无法保持动力水平的原因。
在这篇文章中,我将向你展示一个清晰的计划。不仅能帮助你学习数据科学,还能帮助你找到工作。
开始简单但一致
学习数据科学的人最常犯的错误是从一个复杂的主题开始。被一个有趣的话题吸引是很自然的。问题是如果你在学习过程中过早地遇到了障碍。这足以降低你的动力,让你放弃。当你开始一个复杂的话题时,遇到问题的可能性非常高。
我给初学数据科学的人的第一条建议是从小处着手。下面是一些在数据科学工作中每天都会用到的基本技能。
- Python/R
- 结构化查询语言
- 基本统计
好的,但是需要多少专业知识,从哪里学?对于这些主题中的每一个,我将向您展示您可以从中学习的参考资源。
学习使用 Python/R 编码
要成为数据科学家,你需要编写代码。从读取数据、探索数据集、创建可视化、执行特征工程和构建模型,一切都需要编码。有许多 AutoML 和无代码 ML 工具出现来自动化重复的任务,但是作为一名数据科学家,你需要学习编码。
如果你是编码新手,那么基于网络的平台是开始学习编码的最好地方。基于网络的交互式环境使你的学习变得非常容易。通过自己动手,你会对这个话题了解得更多。此外,没有设置环境和安装工具的压力。
学习基本 Python 编程的一个极好的基于网络的平台是 Codecademy 。这是一个以互动方式学习编码的极好平台。从上次离开的地方继续很容易,也有助于跟踪你的进展。因此,当你旅行或有空闲时间的时候,做一些学习是很好的。如果你决定选择 R,那么你仍然可以从 Codecademy 这里学习。
一旦你完成了 python 或 R 的在线教程,你就可以尝试在你的系统上编程了。安装所需的工具并试用。如果你开始时对下面的内容感到满意,这就足够了,
- 不同的数据类型(包括集合数据类型)及其操作
- 控制语句(If Then Else,For Loop 等)
- 函数和λ函数
学习 SQL
数据科学家的另一项必备技能是 SQL。当您进入企业环境时,所有数据通常都存储在 DBs 中。与学习环境不同,数据集不容易提供给数据科学家。数据科学团队的主要职责是理解和提取所需的数据集。要做到这一点,您需要对 SQL 有很好的了解。
同样,在 codecademy 的课程提供了一个学习基本 SQL 的互动平台。这将帮助你掌握 SQL 的基本功能和语法。有像 learnsql 这样的在线平台提供模拟现实生活挑战的实践场景。
比如,python/R 一旦你熟悉了 SQL,你就可以安装开源数据库管理系统 MySQL 了。它有一个内置的数据库。可以参考下面我的学习 SQL 播放列表。它将帮助您使用数据科学家日常工作中使用的 SQL 的常用功能。
基本统计
基本的统计学知识有助于更好地理解数据。随着您在数据科学方面的进步和技能水平的提高。基本的统计知识将有助于提出更好的解决方案。
汗学院的统计和概率课程将涵盖数据科学家所需的所有关键统计主题。如果你觉得这门课太难了,或者你渴望用足够的统计数据开始学习数据科学,那么看看下面的文章。
它涵盖了数据科学家必备的基本统计学概念。如果你更倾向于教程视频,那么检查这个播放列表。
一致性
学数据科学的时候从小做起就够了。但更重要的是保证一致性,尤其是在早期。如果你学了一两个星期,然后休息很长时间,这对学习没有帮助。你需要每周花固定的时间来学习。
提升你的技能
一旦你熟悉了上面的基本技能,是时候扩大规模了。是时候开始处理数据集并了解数据可视化、数据探索和模型构建了。
学习可视化数据
可视化是数据科学家的一项关键技能。它有助于清晰地交流见解,并揭示数据集中存在的模式。与表格或文本数据相比,人们更容易从视觉数据中选择模式。可视化在数据分析和交流中扮演着重要的角色。
要了解更多关于从零开始构建一些惊人的可视化,请查看下面的文章。
学习执行数据分析
Coursera 里有很多数据科学相关的课程。选择一个最适合你的技能组合是非常令人困惑的。下面是一些你可以根据你目前的专业水平选择的课程。
如果你是一个初学者,还没有进行过任何数据分析,那么就从 Coursera 的这个 2 小时的课程开始吧。
https://www.coursera.org/projects/exploratory-data-analysis-python-pandas
如果你对数据分析有一个基本的概念,或者你已经完成了上面的课程,那么你可以报名参加下面的课程。本课程有一些令人惊讶的反馈,许多人承认通过本课程获得了实实在在的好处。
https://www.coursera.org/learn/data-analysis-with-python
如果你渴望了解更多,那么你可以通过下面的课程向 kaggle 学习特征工程。
建立坚实的基础
现在是时候提升你的技能了。以下是 Coursera 的一些课程,可以帮助你建立一个坚实的基础。它有助于理解和了解数据科学团队在整个项目流程中执行的活动。您将了解如何理解问题,进行分析以提取推论和见解,为业务问题选择正确的模型。这些课程也有项目课程,可以提供第一手的项目经验。
这些项目大多是长期的,至少需要几周的努力。但这些都是至关重要的,它有助于你为数据科学面试和工作中的挑战做好准备。
以下是一些关于以下课程的详细信息,帮助您选择最适合您的课程。此外,不要犹豫,浏览已经涵盖的主题。
- 选项 1 —密歇根大学用 Python 开发的应用数据科学:如果你对本文迄今为止涉及的主题有信心,下面的课程更适合。它不关注基本的统计或数据分析。它将带您快速了解机器学习用例、文本挖掘和网络分析
https://www.coursera.org/specializations/data-science-python
- 选项 2——约翰·霍普金斯大学的数据科学专业*:这个课程是基于 R 的,如果你正在用 R 学习数据科学,那么这个会更适合。这是一门完整的数据科学课程,涵盖了数据探索、可视化、统计和模型构建等主题。*
*https://www.coursera.org/specializations/jhu-data-science
- 选项 3 — IBM 数据科学:这是一门完整的数据科学课程,类似于上面的约翰霍普金斯。这门课是用 Python 讲授的,这使得它更有吸引力。这门课程提供了更好的职业机会。大约 20%完成这门课程的人获得了工作机会。本课程涵盖了数据科学项目的整个流程。它还涵盖了数据科学家常用的工具、技术和库。
https://www.coursera.org/professional-certificates/ibm-data-science
设定目标并庆祝你的胜利
你的学习之旅中最重要的部分是要有目标,并虔诚地追踪你的目标。学习数据科学时,很容易分心。避免任何干扰或偏离原计划的最好方法是写下目标。本文中提到的大多数资源都有一个进度跟踪器。每周设定一些目标,并坚持下去。为了增加责任感,在博客或 LinkedIn 帖子上分享你的学习进度。
此外,分享你的成就和进步有助于创造积极的能量和动力来进一步追求。学习数据科学是一个漫长的旅程,你需要有足够高的动机来维持和完成它。
人们放弃学习数据科学的一个重要原因是缺乏信心。制定计划并跟踪进展有助于树立信心。
做好失败的准备,但要继续学习
向数据科学过渡不会一帆风顺。预计一些技术问题和其他可能的障碍会动摇你的信心。请记住一件事,即使是经验丰富的数据科学家也会遇到问题,这是职业生涯的一部分。数据科学领域是一个快速发展的领域,因此遇到问题并不罕见。但积极的一面是有一个非常好的支持系统。有很多在线社区可以帮助你。一致性起着重要的作用,每天睡觉时多一点知识将对你的职业生涯产生复合影响。
建立工作关系网
接触与你有相似背景的人,他们已经找到了进入数据科学的方法。它有助于理解工作的挑战和需要关注的技能。它会给你一个你需要努力的事情的好画面。人际关系网在求职中也起着关键作用。许多数据科学的机会都是通过推荐直接获得的,而不需要通过求职门户。除了接触有相似背景的人。参加聚会和其他公共数据科学活动有助于建立你的职业网络。
获得数据科学工作的提示
很多学数据科学的人都在苦苦寻找合适的工作。我将分享一些可以帮助你增加被雇佣机会的建议。
- **识别公司:**发挥你的优势会让你更有优势。找出与你的教育或专业背景更相符的公司。你也可以申请许多通才数据科学职位。
- **建立投资组合:**组织招聘新人的时间和资源都是有限的。作品集有助于展示你的能力。这通常会增加你进入面试入围名单的机会。如果你有兴趣免费建立一个作品集网站,请查看我下面的文章。
- **打造一份好的简历:**你的简历代表了你和你的技能。它需要准确地代表你的经验和知识。有一些技巧可以让你用有影响力的陈述写出更好的简历。如果你有兴趣的话,请点击这里查看这篇文章,学习一些技巧和工具来打造一份令人印象深刻的简历。
- **面试前:**对你申请的职位和公司做些调查。可以与现有员工接触,以更好地了解工作、文化等。
- **面试时:**要自信,同时要诚实面对自己的优点和缺点。雇主更喜欢正直、数据科学知识水平较低的候选人,而不是数据科学知识水平很高但不诚实或不透明的人。
需要更多的动力吗?
下面的故事解释了作者从神经科学到数据科学的旅程。经过 8 年的神经科学研究和工作,作者找到了进入数据科学的方法。
下面是我从销售职业进入数据科学的个人旅程。我对 R 和 Python 一无所知。我没有受过数据科学或统计学方面的正规教育。事实上,我不擅长编程,但现在我已经写了 2 本数据科学方面的书,并成功地执行了一些交钥匙数据科学项目。
保持联系
- 如果你喜欢这篇文章,并对类似的文章感兴趣,在 Medium 上关注我
- 我在我的 YouTube 频道上教授和谈论各种数据科学主题。在这里订阅我的频道。
- 在此注册我的电子邮件列表,获取更多数据科学技巧,并与我的工作保持联系*
如何使用无服务器摄取管理器和 Node.js 处理 BigQuery 中的数据加载
实践教程
文件格式、yaml 管道定义、转换和事件触发器,为您提供简单可靠的数据接收管理器
样本管道定义。作者图片💡迈克·沙克霍米罗夫
-“现在,您只需使用一个’ $ npm run test’ '命令,就可以从云存储中加载与您的管道定义匹配的所有文件,或者在那里创建文件时调用数据加载。
代码为的 Github 库
作者图片💡迈克·沙克霍米罗夫
您将了解如何:
- 将数据自动加载到您的数据仓库中,并使用无服务器 (AWS Lambda)构建一个 数据加载服务
- 添加各种文件格式支持和加载不同的文件,即 JSON,CSV,AVRO,拼花。
- 添加 DynamoDB 表来存储摄取日志,并检查文件是否已经被摄取
- 添加数据转换功能,例如,万一您想要屏蔽一些敏感数据或动态更改格式。
- 一次加载多个文件
- 使用基础设施作为代码部署您的数据加载服务,即 AWS Cloudformation
- 如何将压缩文件加载到 BigQuery
- 如何监控数据加载错误
关于这个想法
构建数据仓库:加载数据
通常,您会希望将您的数据仓库解决方案(BigQuery、Snowflake 或任何其他解决方案)放在图表的中心。
- 轻松连接任何外部数据源,即设置一个管道从某个任意 API 获取数据,即像我之前写的关于PayPal【15】并保存到云中。
- 加载数据到 BigQuery
- 转换数据,并使用 Git、CI/CD 创建文档化的数据管道。例如,用数据表单或 dbt 。
- 使用云形成或地形** ( 基础设施作为代码)简化和自动化部署**
- 用 Google Data Studio 创建 BI 报告(例如,收入对账等。)或任何其他商业智能解决方案。查看下图,了解其他选项。
作者图片💡迈克·沙克霍米罗夫
现代数据堆栈工具(当然不是完整的列表):
- 摄入:五川,缝合
- 仓储:雪花,大查询,红移
- 转换:dbt、数据表单、API。
- BI: Looker,Mode,Periscope,Chartio,Metabase,Redash
作者图片💡迈克·沙克霍米罗夫
谈到数据提取和接收您可能希望使用付费和托管工具,如 Fivetran 或 Stitch 从任意数据源(即支付商户提供商、汇率、地理编码数据库等)提取数据。)但是如果你遵循这个指南,你将完全有能力自己做这件事。
方案
假设你是一名数据工程师,你正在做一个项目,将不同的数据源连接到你的数据仓库中。您的公司是一家手机游戏开发工作室,在 IOS 和 ANDROID 两个平台上销售各种产品。
你的筹码
你的开发栈是混合的,包括AWS和GCP*。*
你的团队经常使用 Node.js。数据科学团队使用 Python,但服务器和客户端数据管道是使用 Node 创建的。
您的数据堆栈是现代的、事件驱动的和数据密集型的。
数据仓库解决方案必须具有足够的成本效益和灵活性,以便您可以添加任何所需的数据源。它必须能够轻松扩展,以满足您不断增长的数据。
任务
所有数据来自各种数据表面的文件,即数据库、kinesis 消防水带流和各种通知服务。它以不同的格式(CSV、JSON、PARQUET 等)存储到您的云数据湖中。).
作为一名数据工程师,你的任务是将数据加载过程自动化到你的 BigQuery 数据仓库中。你有许多任意的数据源和管道将文件送入你的 AWS S3 数据湖。
现在你需要
……“一个可靠的服务来管理文件格式,决定上传到哪个表并监控整个过程。”
你决定使用AWS Lambda函数和node . js来完成这个任务。
你的微服务应用逻辑:
- 您的数据连接器从一些数据源提取数据(可以是任意的,如 PayPal)
- 文件正在被保存到 S3 T21 的数据库中。
- 当新文件进入您的 S3 数据桶时,将触发数据接收。
- 该服务将处理这些文件,并为 BigQuery 做好准备,以便将其插入到表中。该服务将决定插入哪个表。
- 该服务将检查文件是否已经被摄取,以防止重复。您将使用 AWS DynamDB 来保存数据加载记录。
- 捕捉数据摄取错误,并在需要时保存文件以供进一步调查。
- 现在,您可以在数据仓库中转换数据。
- 通过通知监控您的数据加载过程。如果有任何错误,您将收到一封电子邮件。
作者图片💡迈克·沙克霍米罗夫
先决条件、库和设置
工具
- 已安装 Node.js 和节点包管理器
- 对云计算(Amazon Web Services 帐户)、AWS CLI 和 AWS SDK 有基本的了解
- Google BigQuery 和一个服务帐户来验证您的服务。
- Shell(命令行界面)命令和脚本(高级)。
技法
- 对 REST APIs 的理解。
- 良好的节点知识。JS(中级)。您将创建一个 Lambda 函数。
- 你必须了解节点。JS 基本概念,即异步函数、节点包和代码如何工作。
- 基本调试(控制台,打印报表)
- 循环:即用于
- 分支:if,if/else,开关
- Shell 命令和脚本,就像您希望从命令行使用 AWS CLI 部署 Lambda 并能够在本地测试它一样。
我们开始吧
第一步。如何使用无服务器(AWS Lambda)构建数据加载服务,并自动将数据加载到数据仓库中
为您的数据湖创建新的 S3 存储桶
用您的 bucket 名称替换your-bigquery-project-name.test.aws
,并从命令行运行,例如,如果您使用 AWS CLI:
aws s3 mb s3://bq-shakhomirov.bigquery.aws
您将看到如下内容:
$ make_bucket: bq-shakhomirov.bigquery.aws
确认存储桶已创建。阅读 AWS S3 文档
将数据集从上传到您新创建的 S3 存储桶:
$ aws s3 cp ./data/payment_transaction s3://bq-shakhomirov.bigquery.aws/payment_transaction
$ aws s3 cp ./data/paypal_transaction s3://bq-shakhomirov.bigquery.aws/paypal_transaction
创建一个空的 AWS Lambda 函数(Node.js)。
您可以使用 AWS web 控制台或 AWS CLI 来完成。这取决于您,并在本地初始化您的Node.js
应用程序。您的微服务文件夹结构必须如下所示:
其中bq-shakhomirov-service-account-credentials.json
是您的 BigQuery 服务帐户凭证。
授予您的服务从数据湖桶中读取数据的权限
您可能希望从您的 S3 数据桶中读取您的数据集文件,然后将该数据加载到您的 BigQuery 数据仓库中。因此,您需要通过向 Lambda 函数的角色添加一个策略,将 Lambda 函数的 S3 访问权限授予您的 bucket,如下所示:
你可以在 AWS 文档中找到更多关于如何创建角色的信息。后面我会举例说明如何用AWS cloud formation栈来做。
安装所需的依赖项
安装所需的node
模块和库,如./package.json
所示。您将需要:
- “AWS-SDK”:“2 . 804 . 0”用于访问带有数据的 S3 桶
- " run-local-lambda": "1.1.1 "来测试 nad 并在本地运行您的 Lamdba
- “@google-cloud/bigquery”:摄取数据的“⁵.7.0”
- “时刻”:" . 24.0 "处理日期并创建相关的
file names
/BigQuery jobIds
确保您可以在本地运行它。这个想法是通过从命令行运行npm run local
命令来模拟一个事件( S3 对象创建事件)。安装“run-local-lambda”:“1 . 1 . 1”来测试并在本地运行您的 Lamdba。
你的./package.json
一定是这样的:
在命令行中运行npm i
,它将安装依赖项。
app.js
在您的./app.js
中添加***async process event()***函数来处理事件。
您的./app.js
看起来会像:
哪里./config.json
是你的服务配置文件。
我更喜欢用YAML来代替,不过是口味问题。最终你会找到使用
*npm config*
和 yaml 的解决方案。 对你的来说似乎是正确的事情。
你的./config.json
的例子可以有现场和登台环境设置,看起来像这样:
使用配置文件定义逻辑、表名以及如何为这些表选择相关文件。
使用上面的这个配置文件,您的数据加载服务将尝试将 name
键与相关文件名 fileKey
匹配。如果它在 S3 事件中找到匹配,那么它将开始加载数据。
BigQuery 凭据文件
./bq-shakhomirov-b86071c11c27.json
是 BigQuery 凭证文件的一个例子。你将需要这个 服务帐户凭证 文件来通过谷歌认证你的微服务,这样它实际上可以做一些事情。点击阅读更多关于服务账户认证的信息。只需从你的谷歌云平台账号下载,添加到你的应用文件夹。
看起来应该是这样的:
如何检查 BigQuery 中是否存在表
您可能希望在加载数据之前执行此操作。将这个函数添加到您的./app.js
文件的processEvent()
中。如果表不存在,它将使用配置文件中的模式并创建一个。
这个函数将在名为source
的数据集中创建一个带有配置文件模式的表。它也应该来自./config.json
,但这只是一个例子。
如何将 JSON 文件流式加载到 BigQuery 中
这将是一个 逐行 的插入操作。
当一行不符合模式时,只有该特定行会被插入,而不是 BigQuery 中的 批量插入 (一行模式验证失败—所有文件上传失败)。
您可能想要添加一个新功能:
这只是一个例子,其中已经声明了 JSON 数据(不需要从本地文件或者从 云存储 )并且已经创建了表。simple_transaction
是一个简单的表,只有 3 列:transaction_id
、user_id
和dt
,在./config.json
模式中为名为simple_transaction
的表定义。试试看,它会将数据逐行插入 BigQuery 表中。
您可以稍微调整此函数,例如从本地文件中读取数据,它将处理新的行分隔文件./data/simple_transaction
并创建一个加载作业操作来代替我们之前使用的写流。
如何从 AWS S3 加载 JSON 新行分隔数据
如果你的数据是新行分隔的 JSON(big query 加载 JSON 数据的自然方式),那么你需要一个像下面这样的函数。该功能将执行以下操作:
- 从 AWS S3 创建一个读取流并读取文件
- 使用 JSONStream 模块解析 JSON 文件中的数据
- 在 BigQuery 中创建一个 批处理 加载作业。
把这个加到你的./app.js
里,试试npm run test
。将./test/data.json
修改为object.key = 'simple_transaction
:
您的“simple_transaction”文件内容应该如下所示:
那么 BigQuery 流插入 和 批量 插入操作有什么区别呢?
它仍然是一个作业(不是像我们上面做的那样big query streaminginsert ),但是在架构方面它是非常高效的内存,并且 是空闲的 。您只需要不超过每天每个表的批处理作业配额。我之前在这里写过如何在 BigQuery 中监控批量加载作业操作:**
*
很好,但可能会产生更高的费用。
我建议尽可能使用batch
insert。每个表每天有 2000 个插入的配额,但是您可以一次插入整个文件。 流媒体插入 没那么便宜,每 GB 0.05 美元,1TB 50 美元。
流式插入是导入数据的推荐方式,因为它是可伸缩的。
然而,如果数据湖中的文件相对较小(这通常发生在使用数据流时,即 Kinesis 或 Kafka ),这不会产生很大的影响。在这里阅读更多关于大查询配额和限制的信息
如何用 Node.js 和 AWS Lambda 微服务将 CSV 数据加载到 BigQuery 表中
您可能希望添加一个函数,该函数从 S3 对象读取数据,并将其作为 CSV 上传到 BigQuery 表中:
这是一个从 S3 读取一个 CSV 文件的例子,理想情况下,你会希望在 Node.js 流模式下这样做以节省你的内存,而不是将整个文件读入内存。它创建一个 可读流 然后流入 流可写 到 BigQuery。
局部解决
这是这个项目的app.js
。这是一个简化的应用程序。复制此文件并使用它来开发您的解决方案。
您必须创建自己的 BigQuery 服务帐户凭证,例如,像我一样下载./bq-shakhomirov-b86071c11c27.json
并创建自己的./config.json
来定义表模式和应用程序环境。
该应用执行以下操作:
- 当您运行
$npm run test
时,它将使用来自./test/data.json
的有效载荷来描述 S3 文件的位置(查看./package.json
中的脚本) - 然后,它将从
./config.json
获取设置,即凭证位置等。并使用 BigQuery API 进行认证 - 它将遍历
./config.json
中描述的表格,试图在有效载荷中找到一个匹配。本例中的有效载荷模拟 S3 对象创建的 事件。 - 如果找到匹配,服务将尝试从 S3 获取该文件,并将其中的数据加载到相关的 BigQuery 表中。
- 它将检查表格是否存在,如果不存在,它将使用
./config.json
的模式创建一个新的表格
添加 DynamoDB 来保存数据摄取记录
如果您需要处理加载作业的复制尝试,那么您可能会想要创建一个新表,并保留摄取文件的记录。那么您可以考虑将这个片段添加到您的应用程序中,在./app.js
:
如果你添加类似于await logSuccessfulEvent(sourceBucket, fileKey, now.format('YYYY-MM-DDTHH:mm:ss'));
的东西,它将开始记录成功摄取的文件,但是你需要首先创建一个表:进入 AWS 控制台:
- 为成功获取的文件创建一个名为
ingestManager
的表。 - 向您的 Lambda 添加访问 Dynamo 表的权限。
作者图片💡迈克·沙克霍米罗夫
- 将处理
successfull
事件的logSuccessfulEvent
函数添加到./app.js
文件:
因此,您应该会看到创建了一个新的摄取记录:
作者图片💡迈克·沙克霍米罗夫
现在,您可能想要添加一个新函数。姑且称之为checkAlreadyIngested()
。
此函数将检查您的数据加载管道是否有任何复制企图,并防止这些复制企图。
确保用try, catch
块包裹即可。
如何监控 BigQuery 数据加载服务中的错误和复制尝试
…或者任何其他数据仓库。
您可能想在每次出现错误时收到通知。
- 使用简单通知服务(SNS)创建一个 AlarmNotificationTopic ,以便在出现任何摄取错误时通过电子邮件接收通知。
- 当您创建 Lambda 并附加策略时,它一定已经创建了一个 LogGroupName :
/aws/lambda/ingestManager
或类似的东西。使用它创建 ERRORMetricFilter ,其中错误计数> 0 。例如,我的日志组如下所示:
作者图片
- 使用以下模式创建一个 ERROR metric filter:filter pattern:’ ERROR '调用它
ingestManagerStagingMetricFilter
作者图片💡迈克·沙克霍米罗夫
- 现在去
SNS
创建你的提醒主题:
作者图片💡迈克·沙克霍米罗夫
- 单击创建订阅并输入您的电子邮件:
作者图片💡迈克·沙克霍米罗夫
- 最后创建ERROR metric alarm动作,当数字误差连续 5 分钟大于 5 时触发报警。它应该发送通知到您的社交网站的主题。
作者图片💡迈克·沙克霍米罗夫
作者图片💡迈克·沙克霍米罗夫
- 选择遇到警报时发送通知的位置:
作者图片💡迈克·沙克霍米罗夫
- 在摄取管理器出错的情况下,期望的输出是一个通知:
作者图片💡迈克·沙克霍米罗夫
理想情况下,你会希望使用类似于AWS cloud formation的东西来管理你的 基础设施,代码为 。
示例堆栈文件可以在本教程的 Github 库中找到。
如何转换原始数据湖文件中的数据并为 BigQuery 做准备
自然地, BigQuery 可以使用 新行分隔的 JSON 或者其他已经正确形成的格式。因此,如果你正在加载ndJSON
,那么它应该在那之前被新行分隔:
现在假设您有另一个服务从 MySQL 数据库 中提取数据,它的输出看起来像一个 JSON 对象数组:[{...},{...},{...}]
。这些单独的 JSON 对象也可以深度嵌套。您可能希望将它转换成nldj
: '{...}'\n'{...}'\n'{...}'\n
,这样 BigQuery 就可以将它装载到表中。
或者想象你正在使用标准的消防软管输出,其中数据被写成一串JSON
对象{...}{...}{...}
。没有逗号。您可能需要为从OBJECT _ STRING到 SRC variant 格式的 BigQuery (转换为nldj
)准备数据,即{...}{...}{...}
> > > '{...}'\n'{...}'\n'{...}'\n
。
看到里面的使徒了吗?这将把它定义为类型STRING
,并且您需要创建一个只有一列的表:name: "src", type: "STRING"
。
这可能是一个具有挑战性的任务,但我写了一些方便的助手函数。你以后会找到它们的。
因此,只需在您的
*config*
中添加文件格式规范,就可以定义处理逻辑并正确地将所有文件加载到big query中。
例如,您可能希望在yaml
配置中定义您的表,如下所示:
第一个名为paypal_transaction
的pipe
有一个单独 JSON 对象的数组(深度嵌套),您可能希望将每个单独的嵌套对象作为一个 JSON 记录插入,这样您就可以稍后在您的数据仓库中用JSON_PARSE
函数解析它。
第二个管道GeoIP2-Country-Blocks-IPv4
需要从 CSV 中解析出来,并插入到 BigQuery 表中,相关的模式有六列。这里您可能希望显式声明一个 CSV 分隔符来帮助 BigQuery 加载数据。
第三个表示一些配置不佳的 Kinesis 流输出,需要作为 JSON 插入,但必须首先为 BigQuery 做好准备(转换为 NLDJ 格式)。
第四个也需要作为 NLDJ 加载,但是它被压缩了,所以你想先解压缩它。
如何将压缩文件加载到 BigQuery
如果你的文件是压缩的,那么你会想先用zlib
库解压它。您可能想要添加一个功能loadGzJsonFileFromS3()
。因此,在本例中,我们首先解压缩文件,然后将该流通过管道传输到 JSONparse ,后者将提取我们需要的 JSON,并且将通过管道 createWriteStream 传输到 BigQuery。
用这种方法你可以非常有效地加载大文件。
在上面的例子中,我还使用了定制的 BigQuery jobIds。这是在 BigQuery 中防止重复的另一种方法。
在这种情况下你不需要DynamoDB但是我仍然使用并插入额外的度量,即插入 的 行数和一个 表名 来生成统计数据。
如何使用 AWS Cloudformation 部署服务
我不想用 AWS 控制台创建所有那些资源。 AWS Cloudformation 是一种简单的方法,只需点击一下鼠标,即可自动部署和配置所有资源。
除其他优势外,您会发现创建生产和试运行环境以及整理(删除)所有资源非常简单。
这个教程实际上是免费的,那些工具不会花费你任何东西。
用代码在 Github 库中检查。
在./stack/cf-config.yaml
中,你会发现 AWS Cloudformation 模板描述了本教程可能需要的所有资源。包括例如 AWS Lambda 角色:
要在您的 AWS 帐户中部署服务,请转到./stack
并在命令行中运行这两个命令:
那个lambdas.bq-shakhomirov.aws
是你的服务工件的 S3 桶,你的 lambda 代码将保存在那里。换成你的。
如何一次将所有文件加载到 BigQuery 表中
当您需要在选定的时间范围内(即特定日期)将所有文件从数据湖中一次性load / reload
到您的数据仓库中时,这种多文件上传功能可能会很有用。
如果需要,该服务必须能够扫描您的数据湖,并挑选符合您需要的描述和时间分区的文件。
假设您的数据湖有来自不同来源的文件保存在 AWS S3 中,具有 关键字 前缀,其中包含大查询 table name
和date
分区,即:
所以在这里,您会希望您的服务扫描数据湖桶,并只选择与这三个pipes
: paypal_transaction
、simple_transaction
和some-other-transaction
相关的文件,并带有日期前缀2021/10/04
。
然后,您会希望摄取管理器生成一个最终的payload
,其中包含找到的所有文件密钥,并将它们加载到 BigQuery 中。
./test/data.json
的最终payload
应该在数据湖中找到所有文件:
在你的本地文件夹中有了这个
*payload*
你就可以在你的命令行中运行*$ npm run test*
(如果你的有效负载在*./test/data.json*
)你的微服务会把这些文件一个一个的加载到big query中。
我在我的./package.json
中添加了脚本来运行这些命令。
- 例如,如果我在命令行中运行
$ npm run test-service
,那么./loadTestIngestManager.js
中的应用程序将使用test/integration/loadTestPipelines.json
中的管道定义扫描数据湖,并生成一个包含所有找到的文件的输出。它会将其保存到test/integration/loadTestPayload.json
。 - 然后,如果我运行
$ npm run test-load
./app.js
,摄取管理器将使用文件的有效负载,并将它们发送到 BigQuery 。
使用这些脚本,您可以轻松地为加载到 BigQuery 中的文件和格式编写集成测试。
您可能注意到上面的payload.json
与original S3 Obj created
事件负载略有不同:
那只是因为在我的环境中,我有另一个由S3 Obj created
事件触发的orchestrator
服务,它将为ingest-manager
创建有效负载。该服务可以执行您需要的任何其他功能,并且它会在需要时invoke
摄取管理器。
随意调整摄取管理器的有效载荷。您可能希望在processEvent()
函数中为event
处理添加S3
键。
结论
您刚刚学习了如何为用 Node 编写的 BigQuery 创建一个简单可靠的摄取管理器。带有一些 牛逼功能 的 JS:
- 无服务器设计和 AWS Lambda 功能。
- 非常性价比。针对批量加载作业进行了优化,这意味着您无需为数据加载付费。基本上它是免费的,但检查 BigQuery 负载作业限制。
- 可以使用流式插入(BigQuery 流式加载)。
- 为 AWS 量身定制但可以轻松迁移到 GCP,Azure 。
- 用 AWS Cloudformation 构建的代码为 的基础设施。在任何其他 AWS 帐户中一键部署。
- 使用 AWS Dynamo 进行有效的负载作业监控和文件重复处理。
- 自定义 BigQuery 作业 id。如果你不想使用 Dynamo,另一个防止复制的方法是。
- 支持单元和集成测试。
许多人认为 Python 是完成这项任务的最佳选择,但是我不同意。所有的选择都是好的,只要他们能完成工作。以前我写过如何用 Python 写代码,Python 是我最喜欢的编程语言之一。我的大部分生产管道都是用 Python 或 Java 编写的。
我的观点是你不应该限制自己。
本教程不是关于编程语言或它们的具体应用。我确实认为数据只适用于 Python/Java 这种陈词滥调。当我看到不使用 SQL(或者不知道如何使用)的数据科学家时,我也很沮丧。
这个项目是关于数据工程、现代数据堆栈、跳出框框思考、自我学习、定制、语言不可知以及能够用非常规方法达到预期结果。
资源
[4]:https://cloud . Google . com/big query/docs/reference/rest/v2/Job # JobConfigurationLoad
[5]:https://Google APIs . dev/nodejs/big query/latest/table . html # create write stream
【9】:【https://aws.amazon.com/cloudformation/
【10】:http://ndjson.org/
【11】:https://cloud.google.com/bigquery/quotas
[12]:https://stack overflow . com/questions/7985599/notification-of-new-S3-objects
[15]:https://towardsdatascience . com/extract-data-from-paypal-API-c25c 76748746?gi=e76b91a696e*
原载于 https://mydataschool.comhttps://mydataschool.com/blog/how-to-load-data-into-bigquery-with-serverless-node-js/。**
如何使用内置函数在 SQL 中处理日期
日期函数是 SQL 编程中谈论最多的领域之一
埃德加·莫兰在 Unsplash 上的照片
作为一名数据分析师,我用不同的时间粒度构建仪表板和报告,如每周、每月、每季度、每年。对于时间序列分析,我需要聚合数据中的时间戳。这就是日期函数发挥作用的地方。这些内置功能使分析师的任务变得更加容易。我无法想象没有内置日期功能的生活。
今天,我将专门讨论 PostgreSQL 附带的那些。但是几乎所有的 SQL 数据库都以某种形式支持这些。
以下是我的一些主要约会功能。
1.日期 _trunc
Date_trunc 用于将日期截断为周、月、季度或年。此函数最广泛地用于创建时间序列和粒度级聚合。例如,如果您想要绘制 KPI 的趋势,如季度销售额、活跃用户、月订单等,可以使用该函数。
语法:
SELECT DATE_TRUNC('month',calendar_date) AS Month,
COUNT(DISTINCT USER) AS active_users
FROM usage
GROUP BY 1
2.当前日期
我认为这是我所有查询中最常用的函数。顾名思义,这个函数给出当前日期。几乎每次分析数据集时,我都会根据手头的问题将数据集限制在过去几年/几周/几个月,以缩短查询执行时间。这个函数通过获取当前日期来帮助我这样做,当前日期将成为我的结束日期,然后我提取相对于这个结束日期的开始日期。例如,让我们假设我想看看去年我的销售额逐月增长的情况。我可以使用 current_date 获得最近的一个月,然后从中减去 12 个月,得到完整的一年。
语法:
SELECT DATE_TRUNC('month',calendar_date) AS Month,
SUM(sales) AS monthly_sales
FROM sales
WHERE calendar_date BETWEEN DATE_TRUNC('month',CURRENT_DATE) -INTERVAL '12 Months' AND DATE_TRUNC('month',calendar_date)
GROUP BY 1
3.Datediff
此函数给出您指定的日期部分中两个日期/时间戳之间的差异。您可以将日期部分指定为秒、分、小时、天、周、月、年等。例如,下面的查询根据用户开始和结束观看会话的时间,以分钟为单位计算电影观众人数。
语法:
SELECT DISTINCT movie,
SUM(datediff ('minutes',watch_start_time,watch_end_time)) AS watch_minutes
FROM movie
GROUP BY 1
4.日期 _ 部分
date_part 函数提取日期部分的值。例如,有时我必须从我的数据集中排除/突出周末数据来处理异常值。这个功能非常好地完成了这项工作。
语法:
SELECT CASE
WHEN DATE_PART('dow',calendar_date) IN (1,6) THEN 'Weekend'
ELSE 'Weekday'
END AS time_of_week,
COUNT(DISTINCT session_id) AS sessions
FROM sessions
GROUP BY 1
5.Trunc
Trunc 函数将时间戳截断为日期值。这类似于铸造一个时间戳。
语法:
Select DISTINCT trunc(start_time) as day
FROM usage
6.到时间戳
这个函数将时间戳转换为带时区的时间戳。当我试图分析基于事件的数据时,我不得不使用它,其中一个数据源捕获 UTC 时区的数据,另一个数据源捕获本地时区的数据。默认情况下,会添加 UTC/GMT 时区。
语法:
SELECT to_timestamp('2011-12-18 04:38:15', 'YYYY-MM-DD HH24:MI:SS')
结果:
to_timestamp
----------------------
2011-12-19 04:38:15+00
7.Dateadd
Dateadd 按指定的间隔递增日期或时间戳。例如,假设我们有一个数据集,其中包含一个持续时间为 30 分钟的在线测试的数据,该测试在 30 分钟后自动结束。如果我们只有每个考生的开始时间,我们可以使用 dateadd 来计算每个考生的结束时间。
语法:
SELECT DATE_TRUNC('month',calendar_date) AS Month,
COUNT(DISTINCT USER) AS active_users
FROM usage
GROUP BY 1
8.最后一天
Last_day 返回包含给定日期的月份的最后一天的日期。例如,你可以用它来检查一年是否是闰年,一个季度的最后几天销售额如何变化,等等。
语法:
SELECT DISTINCT year,
CASE
WHEN last_day ((year|| '-02-01')::DATE) = (year|| '-02-29')::DATE THEN 'Leap Year'
ELSE 'Not a leap Year'
END AS is_leap_year
FROM years
9.间隔
Interval 实际上是一个文字,而不是一个内置函数。这种文字允许您确定特定的时间段,如 6 个月、30 天、45 天、2 周等。例如,在下面的例子中,我用它将一个纪元值转换成一个时间戳值。
语法:
SELECT epoch_time,
TIMESTAMP 'epoch' +(epoch_time*INTERVAL '1 seconds') AS date_time_value
FROM date_time_data
总结
在执行时间序列分析时,理解处理日期-时间数据类型的技术是极其重要的。我觉得 SQL 是一个在进一步分析之前尽可能清理数据集的好地方。通过学习这些函数,您将能够分析与趋势相关的数据,并在更短的时间内找到更深入的见解。
我希望你尝试这些功能,并看到使用这些功能的好处。
如果你有任何问题或建议,请在评论区告诉我。
感谢阅读!
下次见……
如何处理丢失的数据
使用 XGBoost 的最快多重插补方法
丢失数据太糟糕了。它阻止了某些模型的使用,并且经常需要工程师进行复杂的判断。然而,在 2021 年,奥克兰大学的研究人员开发了一种解决方案…
图 1:大型数据集的缺失数据。图片作者。
他们的方法利用世界闻名的 XGBoost 算法来估算缺失数据。依靠一个针对速度优化的模型,我们可以看到相对于传统插补方法 10-100 倍的性能提升。XGBoost 还几乎不需要超参数调整,这大大减少了工程师的工作量。XGBoost 还能够维护数据中观察到的复杂关系,比如交互和非线性关系。
因此,如果数据集超过 3000 行,您可以考虑使用 XGBoost 来估算缺失数据。下面是该方法的工作原理…
技术 TLDR
- **使用 XGBoost 进行多重插补。**它是在 MICE 框架中实现的——我们不使用线性/逻辑回归,而是使用 XGBoost。
- 使用预测均值匹配(PMM)来改善我们的方差估计。 PMM 是必需的,因为 XGBoost 低估了估算数据的方差,导致置信区间的覆盖范围很小。
好的,这很好,但是这个方法实际上是如何工作的呢?
我们稍微慢一点,理解一下为什么这个方法这么有效。
我们的目标
首先,从我们的目标开始。许多真实世界的数据集都有缺失数据,这会给建模和分析带来问题。为了让我们的生活更轻松,我们将尝试用现实的预测来填补那些缺失的价值。
图 2:大型数据集缺失数据插补可视化。图片作者。
填充缺失数据的一种常用方法是简单地输入平均值、中值或众数。然而,正如你所料,我们获得的信号很少,而且这些估计的方差往往太低。
方差的重要性
但是我们为什么要在乎呢?嗯,方差是所有统计显著性和置信区间计算的基础。
基于中心极限定理,我们知道许多样本的平均值将类似于正态分布。如果我们观察一个样本,它的平均值远离这个理论分布(总体)的中心,我们可以认为这是极不可能的,因此具有统计学意义。并且,我们不会称之为统计显著的范围被称为我们的置信区间。
图 3:样本方差公式。图片作者。
为了估计这一理论总体的分布,我们使用数据的标准差,即数据方差的平方根,如图 3 所示。因此,方差是所有基于信心的计算的基础。
估算数据的方差
当输入数据时,我们希望使用观察到的数据来估计未观察到的数据。如果我们有一个完美的代表性样本,我们可以完美地估算缺失数据。然而,样本从来都不是完美的,经常会丢失关于丢失数据的关键信息。
由于这个事实,大多数数据插补方法低估了缺失数据的方差。
现在,以正确的方式系统地引入方差真的很难。一种简单的方法是简单地给每个估算值添加一些随机噪声。这肯定会使我们的数据更加多样化,并可能增加方差。但是,这种均匀分布的噪声可能并不代表我们的总体。
这就是mixb的用武之地…
该方法
奥克兰大学的研究人员提出的方法使用流行的建模技术 XGBoost 和预测均值匹配(PMM)来估算数据。让我们依次看一看每一个。
1—MICE 框架中的 XGBoost
XGBoost 是一种非常流行的基于树的算法,因为它速度快,通用性强,并且具有开箱即用的准确性。评论中有一个惊人的解释,但对于这篇文章,你可以把 XGBoost 想象成一个黑盒,它接收预测值并输出我们缺失数据的估计值。
另一方面,我们将讨论 MICE 框架。MICE 代表通过链式方程的多重插补。没有听起来那么糟糕。
图 4:具有 4 个插补集的 MICE 框架。图片作者。
MICE 的工作方式是创建数据的 M 份副本。然后,它依次遍历第一个复制的数据集中的列(图 4 中的 M1 ),并使用线性模型来预测缺失的值。预测值是该行中的所有其他变量。然后 MICE 对其余的 M 数据集重复这个过程,产生 M 个完整的数据集。
从那里,我们取所有 M 数据集的每个指数值的平均值,这些平均值成为我们的最终估算数据集。
现在,如果你仔细观察,你会发现所有的数据集都是一样的。因此,为了给外观自然的变化,我们只是添加一些随机噪声到每个预测。
很直接,对吧?
现在,线性回归有其局限性——它不允许非线性关系,并且需要人工干预来处理交互。XGBoost 在非线性关系和交互方面都很棒,所以我们只是使用 XGBoost 而不是线性回归来预测我们的缺失数据。
2 —预测均值匹配处理低方差
现在,XGBoost 受限于我们给它的数据,所以它经常低估我们预测的方差。为了增加方差,我们实施了一种称为预测均值匹配(PMM)的方法。
图 5:二维预测平均匹配。图片作者。
PMM 随机选择五个最接近我们预测的观察数据点之一。因此,在上面的图 5 中,绿点是我们的预测值,它周围突出显示的圆圈是我们的预测将成为的候选值。
通过用观察到的数据点替换预测,我们确保引入的方差与我们总体中的方差具有相同的结构。
我们对所有预测值重复这一过程,直到我们用预测值附近的观察数据点替换了所有空的数据点。
摘要
现在,你知道了。快速总结一下…
- XGBoost 是一种高性能算法,可以对数据中的复杂关系进行建模。
- mixgb 包利用 XGBoost 来估算缺失数据。
- 为了确保我们可以计算准确的置信区间,我们使用预测均值匹配来增加估算数据的方差。
实施说明
- 在更小的数据集上,XGBoost 在计算速度上更胜一筹。主要的竞争来自于随机森林实现,但是 XGBoost 在大于 3000 X 20 的数据集上表现更好。
- 对 PMM 来说,有几种不同的方法,但没有一种方法局限于 5 人的捐献者人数。其他常见的值有 2、3 和 10。
- 目前,我还不知道有哪个 python 包支持这种方法。
- 在论文中,我们开始看到 mixgb 在 3915 x 20 数据集上在计算速度方面优于所有其他方法。对于所有较大的数据集,XGBoost 是明显的赢家。
感谢阅读!我会再写 39 篇文章,把学术研究带到 DS 行业。查看我的评论,链接到这篇文章的主要来源以及 R 包。
如何处理神经网络输出:野生动物无人机图像的实际应用
处理人工智能训练的输出不一定简单,需要仔细观察数据。
通过使用野生智能实验室提供的航拍图像,我们试图找到一个好的结构,并深入了解库兹库斯野生动物保护区的土豚洞和枯树。
本文是对主项目中数据科学部分的额外的、更全面的介绍。主要文章已经详细介绍了该项目的起因以及如何训练 Mask RCNN 为我们服务。它可以在这里找到:
https://wildintelligencelab.com/deadwood-and-aardvark-hole/
提供机器学习数据
我们开始查看所提供的信息及其出现的形式。从掩模 RCNN 神经网络结构中,我们得到以下输出:
- 图像分类(输入图像的预测内容标签): dead_tree 或 aardvark_hole
- 语义分割(将输入图像中的像素与来自 1 的适当类别标签相关联)
- 物体检测(通过边界框捕获的图像中物体的位置):【x 轴,y 轴,宽度,高度】 - >例如【1925,248,1962,271】
- 实例分割(结合对象检测和语义分割以获得检测和精确分割):这输出一个数组,其中每个二进制值表示一个像素是否属于分割遮罩,例如*[[假、假、假、假、假、真、Tr…】*
可视化 1–4 来自stat twiki
为了在单个图像切片上实现它,我们使用下面的代码。通过改变第 7 行中选定的图像,我们可以看到神经网络生成的结果。
虽然这为我们提供了一个覆盖了分类的图像,但我们现在希望以数字形式详细查看输出。我们可以看到,由于输出 ROI 时的 4 个不同阵列,我们在该图像中检测到了 4 个对象。
>>print(r['rois'].shape)
(4, 4)
>>print(r['rois'])
[[ 767 0 801 26] [ 868 37 891 62] [ 316 1763 341 1787] [2004 980 2026 1006]]
>>print(r['masks'].shape)
(2048, 2048, 4)
另一方面,遮罩为我们提供了一个二进制数组(图像原始切片的大小)。当绘制它时,我们可以清楚地看到神经网络发现的面具。观察标签和面具的大小,我们可以看到在这个特定的输入图像中有 4 个土豚洞。有可能为每一个单独返回它们的边界框和相应的遮罩。
绘制掩码 // plt.imshow(r[“masks”][:,:,0]+r[“masks”][:,:,1]+ r[“masks”][:,:,2] + r[“masks”][:,:,3])
数据框架
看到并掌握了掩蔽 RCNN 呈现给我们的新发现的信息,我们现在需要考虑适当地存储数据。但是我们使用的格式很大程度上取决于我们想要得到什么样的内部信息。在第一次头脑风暴中,我们集中讨论了以下一系列模糊的问题:
- 从枯树上估计木头的重量
- 分析枯树的存在
- 一簇簇枯树
- 分析土豚洞的存在
- 某些区域的成簇孔洞
- 土豚洞的大小——与邻居的关系
这是一个困难的情况,因为我们关注每一个单独的物体,但也关注它们与周围环境的关系,从而关注全局。最方便的方式似乎是将每个检测到的对象存储为单独的实例,以便能够例如单独估计大小。我们通过构造一个数据帧并给这个表中每个检测到的对象一个自己的行来做到这一点。最后,我们将有一个填充了所有土豚洞的数据帧和一个检测到所有枯树的数据帧。我们从以下几列开始: ID (唯一标识符)标签(枯树或土豚洞)原点(原始目录)x 和 y 坐标的 pic 位置(给我们原始大图中切片的位置)边界框坐标,遮罩数组及其对应的遮罩尺寸。
直接从屏蔽 RCNN 输出
这看起来已经比单独查看每张图片要干净得多了。有了这么好的表现,我们甚至可以问一些最初的问题:每个土豚洞/死树的大小是多少。通过对掩码数组中的真值求和,我们得到表示掩码填充的像素总和的掩码大小。在无人机图片的元数据中,我们得到一个像素大约为 4 厘米的信息。因此,我们已经可以向表中添加一个新列,说明以平方米为单位的大小。对于我们的其他问题,我们没有使用掩码数组,并决定放弃它。
减少信息
和掩码数组一样,我们现在看看所有其他值,并尝试评估它们给我们带来了什么信息,如果有办法的话,只将它减少到最低限度。拥有所有的像素值使得开始进一步的分析变得困难。所以既然我们已经有了平方米的尺寸,我们就不再需要完整的边界框和它所有的 x 和 y 值了。但是我们需要的是边界框的位置。
计算每个包围盒的质心
因此,我们不使用所有四个值,而是只查看每个边界框的质心。我们通过取宽度和高度的一半,并用边界框的质心的 x 和 y 值生成一个新的数组。从四个点增加到两个点似乎很简单,但是这一步已经使进一步的分析变得更加容易。通过一个点(一维)而不是一个区域(二维),我们现在可以很容易地计算多个物体之间的距离,并通过散点图非常直观地显示它们。我们现在只需要一个(2,4)数组,而不是像我们对遮罩那样绘制一个(2048,2048,4)数组。四个物体的两个坐标。详细的形状对于聚类分析和距离计算来说是可以忽略的,并且明显比便宜得多的成本更重要。
全无人机拍摄覆盖了所有土豚洞的散点图
通过使用我们所拥有的关于切片在整个图像中的确切位置的信息,我们还可以以这样的方式改变值,即质心不仅仅代表物体在切片中的位置,而是代表整个拼接在一起的无人机拍摄。我们现在有效地将原始的 11 GB 照片压缩成几 MB。当然,颜色、背景和一些细节都不见了,但是我们想要的信息仍然是完整的。我们甚至可以用散点图覆盖原始背景图像,给我们一个现实生活中物体位置的指示。虽然听起来很强大,但在 python 中,背景图像需要极大地缩小才能做到。因为我们不能保持足够的信息和细节,所以它只能成为一个视觉辅助,我们可以放大到最终的情节。
通过查看代码,我们还可以看到,为了使背景与散点图一致,我们需要在第 1 行中适当地设置 figsize,在第 2 行中适当地设置范围。这主要是一个估计,因此这就是为什么在上面的图中一些点位于背景图像之外的原因。
遮罩旁的实际图像
通过执行这些步骤,我们可以组织模型的输出,并以这样的方式减少输出,这样我们只剩下必要的信息用于进一步的分析。同时,这也给我们带来了好处,我们已经能够很好地估计我们探测到的物体的大小。不幸的是,这并没有为死树估计提供好的结果。土豚洞的大小很简单,它们的深色使得神经网络更容易绘制出准确的面具,而树木的复杂形状则不是这样。
感受数据
质心分布 //海风显示
在进入高级主题之前,建议花点时间查看数据,并重新评估它是否正确。我们关注土豚洞及其在地形中的分布和大小。重叠散点图不会根据单个孔的大小进行缩放,只有通过丰富的想象力才能发现多个孔的大量集合。
土豚洞的数量根据它们的大小 //直方图绘制
根据大小标绘所有的洞使我们能够看到所有洞的范围和分布。我们的结果表明,平均孔尺寸约为 0.13 平方米,而中位数约为 0.11 平方米。我们可以看到一个钟形曲线,这是我们对自然现象的预期。
寻找土豚洞群
土豚以它们的洞穴而闻名,但也以它们的地下隧道系统而闻名。Kuzikus 野生动物保护区提供的研究表明,两个洞之间的隧道可长达 10 米。考虑到这个距离,我们的下一个目标是找到可能相连的洞,形成一个更大的隧道系统。
这是一个非常简单和天真的方法,使用空间中的欧几里德距离来测量两个洞之间的米数。然后,从满足 10m 以下限制的数据帧中构建一个数据帧。但是通常天真的方法是最方便的,因为手头没有额外的数据,我们决定选择这个选项。
在距离矩阵的帮助下,我们可以提取每个洞的“邻居”,并以包括所有可能连接的洞的方式创建聚类。如果 36。和 39。球洞都与 38 号球洞相连,聚类列表包括一组中的所有 3 个球洞。最后,我们在数据框中添加了一个“组”列,为位于同一个集群中的组分配相同的组号。
包含 10 个土豚洞的最大集群
应用质心图中的代码并为相应的簇添加连接线,会产生标记所有连接孔的图像。对于未来的可视化,将有可能计算集群的中心点,并围绕它绘制一个半径。目前,我们只尝试了固定半径。根据每个群中的洞的数量使用可变的一个将极大地改善这种可视化。这样一个集群的相应半径,然后可以通过赋予它一个概率增强效应来用于改进人工智能模型。然后,其中的对象将被标记为土豚洞,具有更高的确定性,因为预先存在该区域是聚类的一部分的知识。
集群投影和半径概念
图象分割法
尽管我们的模型在估算土豚洞的真实尺寸时给了我们非常好的结果,但在处理枯树时却不那么成功。正如我们在上面的可视化中已经看到的,遮罩本身就是问题所在,因为它不够精确。为了获得更好的效果,我们将注意力转移到了边界框和它所包围的物体上。由此看来,对这件作品进行图像分割似乎是合理的。
K-均值聚类
用于图像分割的最著名的算法之一。有很多关于这个主题的文章,最好看一看,以便更好地理解底层的过程。我们按照这篇文章的思路构建了一个处理裁剪图像的函数。
然后,它输出原始图像旁边的分割图像,并显示图像中存在的颜色和绝对值。
k-均值分割
我们已经可以看到这里的主要问题。颜色太相似了。很难从背景中分辨出枯树的颜色。在这个特殊的例子中,采用阴影(最暗的颜色)作为尺寸的指示器似乎是有用的,但是它不是一个通用的解决方案,并且对于其他物体是无效的。不幸的是,即使是更大的 K 也不能解决这个问题,因此唯一合理的步骤是更进一步,依靠最新和最先进的聚类和图像分割形式之一。
自组织映射 ( SOM):
Derrick Mwiti 用简单明了的方式解释了它的原理:
“自组织映射是一类用于特征检测的无监督学习神经网络。它们用于产生训练样本的低维空间。因此,它们被用于降维。”
他在 SOMs 上写的文章是进入这个话题的一个很好的入口,非常适用于死树问题。与 Derrick 所做的类似,我们可以将minicom实现应用到我们自己的输入中。
绘制 img_som,聚类和对应的权重我们得到如下结果。
具有 9 种学习颜色的 SOM
很明显,即使是 SOMs 也不能解决颜色相似的问题。虽然它没有为我们解决任何问题,但我们从图像分割中得到了有价值的知识:现在这是一个死胡同。这可能看起来很烦人,但是提高估计的唯一方法是回到掩码。重新标记数据和更加小心地选择 labelme 中的对象可能看起来远不如应用最先进的技术迷人,但这往往是必要的罪恶。要有好的结果,良好的投入是必要的!
在这个项目中,我与 Nuray Agaoglu 一起研究数据科学部分,我衷心感谢她投入的时间。
如何处理增强树的曝光偏移
保险业从 GLM/GAM 模式转向 GBM 模式的三种方式。
在保险环境中,索赔频率建模的一个常见任务是处理不同的风险等级。暴露是一个宽泛的术语,保险媒体将其定义为“对损失或风险的敏感性”,但在我们的例子中,它将与时间类似。
我们预计,如果一个实体遭受某项风险达一年之久,其索赔频率会高于仅遭受该风险一周的情况。如果我们有历史索赔信息,但不是我们观察到的所有政策都持续了一年,那么在建模时必须考虑到这一点。传统上,GLM 或 GAM 模型用于预测索赔频率,这些包中的大多数都有一个所谓的偏移参数,让您自动添加暴露的影响。
本质上,我们要求模型根据可用数据进行预测,但我们对暴露部分进行微观管理。
如果您碰巧切换到梯度增强树模型,您将很快意识到在这些包中没有显式的偏移参数。在各种论坛上可以找到很多关于这个话题的讨论,有不同的解决方案,但我还没有真正找到一个值得信赖的综合来源。我决定我将得到这个结束,并彻底调查哪种方法工作,为什么。
摘要
我们将模拟一个数据集,并根据泊松分布(保险业中一个非常常见的假设)定义索赔计数。测试是在 R 中用 LightGBM 包完成的,但是应该很容易将结果转换成 Python 或其他包,如 XGBoost。
然后,我们将研究 3 种方法来处理不同程度的暴露。我们将看看预测有多准确,然后深入研究提升树算法,找出它们是如何工作的。
正如我提到的,最初的动机是一个保险问题,但我们所谈论的将完全适用于任何其他你有时间因素的原则。这不是 LightGBM 的一般教程。然而,我在文章的最后列出了一些通用的技巧。
完整代码在一个 R 脚本中,可以从 my GitHub 中获取。
重要提示:就像你在网上读到的任何东西一样,仔细阅读这些信息。这些软件包很可能会改变现状。总是自己尝试和测试事情。
我们的测试环境
r 包
我们需要以下两个 R 包:
我们用data.table
代替默认的data.frame
,这只是我个人的喜好。如果你看到类似table[,.(column_name)]
的东西,那就是data.table
语法。
模拟数据
他们有两个分类变量,var1
和var2
。在曝光为 1 的观察中,不同的组合在泊松分布中将具有以下λ:
var1 var2 lambda_base
1: A C 0.3
2: B C 0.7
3: A D 1.3
4: B D 1.9
然后,我们将产生不同的曝光水平,并调整 lambdas。
例如,var1=A,var2=C,exposure = 0.4 的观测,索赔计数将从λ为 0.3 * 0.4 = 0.12 的泊松分布中随机生成。
我们创建了数据表的两个变体,一个简单的,一个适中的。这两个版本的区别在于我们产生风险的方式。对于data_easy
,它们被明确定义为 0.1、0.2、…1.0 的集合,而对于data_mod
,曝光在 0 和 1 之间随机生成。
我们还生成调整后的索赔计数、定义的 claim_counts / expos(我们稍后会用到)。这是数据表的外观,列名缩写以适应屏幕:
var1 var2 expos lambda_base lambda ccn ccn_adj
1: A C 0.3078 0.3 0.09234 0 0.000000
2: A C 0.2577 0.3 0.07731 0 0.000000
3: A C 0.5523 0.3 0.16569 0 0.000000
4: A C 0.0564 0.3 0.01692 0 0.000000
5: A C 0.4685 0.3 0.14055 0 0.000000
---
9996: B D 0.5999 1.9 1.13981 1 1.666944
9997: B D 0.9259 1.9 1.75921 0 0.000000
9998: B D 0.6517 1.9 1.23823 2 3.068897
9999: B D 0.6904 1.9 1.31176 4 5.793743
10000: B D 0.6317 1.9 1.20023 3 4.749090
目标
在进入建模部分之前,重要的是考虑我们期望模型预测什么。
有些人可能认为我们期望预测claim_counts
。这是不正确的。claim_counts
是一个随机变量,期望模型能够预测是“不公平的”。
我们关心的是模型对λ参数的预测有多好。
解决方案 1 —初始分数
在第一个解决方案中,一个经常在论坛上建议的方案,我们将lgb.Dataset
的init_score
参数设置为曝光的对数。
密码
solution_1_predict <- function(data_curr){ data_curr_recoded <- lgb.convert_with_rules(
data = data_curr[,.(var1, var2)])$data
dtrain <- lgb.Dataset(
data = as.matrix(data_curr_recoded),
label = as.matrix(data_curr[,.(claim_count)]),
init_score = as.matrix(data_curr[,.(log(expos))]),
categorical_feature = c(1,2))
param <- list(
objective = "poisson",
num_iterations = 100,
learning_rate = 0.5)
lgb_model <- lgb.train(
params = param,
data = dtrain,
verbose = -1)
return(predict(lgb_model, as.matrix(data_curr_recoded)))
}
请注意,LightGBM 预测没有受到init_score
的影响!所以在我们的例子中,当我们做一个预测时,我们必须手动乘以暴露量。(我认为它在 XGBoost 中的工作方式不同,除非另有说明,这里包含了base_margin
。)
进行预测的正确方法是:
temp_predict <- solution_1_predict(data_easy)
data_easy[,sol_1_predict_raw := temp_predict]
data_easy[,sol_1_predict := sol_1_predict_raw * expos]
当然和data_mod
的过程相同。
结果
原始预测非常接近基本的 lambdas,初看起来模型似乎是成功的。对于data_mod
,结果:
data_mod[,.N, keyby = .(lambda_base, sol_1_predict_raw)]
返回
lambda_base sol_1_predict_raw N
1: 0.3 0.2941616 2500
2: 0.7 0.6677160 2500
3: 1.3 1.2907763 2500
4: 1.9 1.9207416 2500
索赔总数也与预测相符。
claim_count pred_claim_count theoretical_claim_count
1: 5208 5208 5241.001
观察它和理论上的期望值,也就是 lambdas 的和,是不一样的。
预测的可能性
让我们分析一下,如果预测值与理论值不完全匹配,我们是否会感到满意。我们将解决方案 1)的性能与简单预测λ的模型的性能进行比较。
首先,我们计算对数似然性:
data_mod[,sol_1_ll := dpois(x = claim_count,
lambda = sol_1_predict, log = TRUE)]
data_mod[,base_ll := dpois(x = claim_count,
lambda = lambda, log = TRUE)]
data_mod[,saturated_ll := dpois(x = claim_count,
lambda = claim_count, log = TRUE)]
data_mod[,null_ll := dpois(x = claim_count,
lambda = mean(claim_count), log = TRUE)]
data_mod[,.(sol_1_ll = sum(sol_1_ll),
base_ll = sum(base_ll),
saturated_ll = sum(saturated_ll),
null_ll = sum(null_ll))]
退货:
sol_1_ll base_ll saturated_ll null_ll
1: -8125.188 -8126.383 -3918.93 -10101.24
正如我们所看到的,我们的解决方案的对数似然比我们简单地使用 lambdas 进行预测的结果要高一点点。这意味着我们可以对我们的结果感到满意!
顺便说一下,从对数似然性,我们也可以计算出解释偏差的百分比。我不想跑题文章,代码请参考我的 GitHub 。
然而,我认为重要的是要强调,对于一个几乎完美描述了所有非随机效应的模型,解释的偏差百分比仅为 32%。
它是如何工作的?
我最初对这种方法非常怀疑,我的想法是这样的:*“设置 init_score 可以加快这个过程,但最终,模型会远离这些数字。获取日志更没有意义,对于非负目标,它将是一个负数。”*这是不正确的。
对数是必要的,因为“poisson”
物镜将使用对数链接,即使文档中没有提到这一点。这意味着计算出的原始分数的指数将是模型返回的最终预测值。
注:其实挺有意思的,无论是 XGBoost 的 还是 LightGBM 的 文档都会特别提到 Tweedie 和 Gamma 使用了 log-link,但是没有指定用 Poisson。我知道 log-link 是针对阿松的 规范链接函数 ,但看起来确实有人抄袭了他们的答案!
当我们放入init_score
时,我们实际上设置了观测值之间的固定差异。如果曝光是两次观察之间的唯一差异,预测的比率将与曝光相同。
例如,在我们的例子中,如果我们有以下两个观察结果:
var1 var2 expos
1: A C 0.5
2: A C 0.3
第一个将得到一个修正对数(0.5),第二个在其预测总和中得到一个修正对数(0.3)。一旦设置完毕,模型就只能使用var1
和var2
。由于这两个观察值相等,模型无法以任何其他方式区分它们,第一个预测值将始终等于第二个预测值的 0.5/0.3 倍。
这就是我们想要的。拟合模型,同时考虑这种假设的线性暴露影响。
解决方案 2——经调整的索赔
这是我经常看到的另一个解决方案。
- 首先,计算调整后的索赔次数=索赔次数/风险。例如,如果您只有 0.5 的风险敞口和 3 项索赔,则调整后的索赔数为 3 / 0.5 = 6。
- 您根据调整后的索赔数量运行模型。
- 你还需要用曝光率作为权重。(现在没有关于曝光的日志材料!)
让我们看看这个解决方案的表现如何!
密码
代码与解决方案 1)几乎相同,但是
- 我们的目标不同;
- 我们没有使用
log(expos)
作为init_score
,而是将expos
作为weight
放入。
solution_2_predict <- function(data_curr){
... (same as solution 1) ...
dtrain <- lgb.Dataset(
data = as.matrix(data_curr_recoded),
label = as.matrix(data_curr[,.(claim_count_adjusted)]),
weight = as.matrix(data_curr[,.(expos)]),
categorical_feature = c(1,2))
... (same as solution 1) ...
}
结果
不再赘述,结果将与解决方案 1)完全匹配。
这使得关于应该使用哪种解决方案来处理偏移的争论变得毫无意义。
它是如何工作的?
那么,为什么我们从两个看似不同的模型中得到了相同的预测呢?
我们必须考虑提升树(以及一堆其他使用梯度下降的机器学习模型)如何处理最大似然估计。在引擎盖下,他们不会使用原始形式的似然函数。相反,他们将使用对数似然函数相对于预测值的一阶和二阶导数。这些被称为梯度和黑森。
在这个方向上走得更远真的会让我们偏离主题,XGBoost 教程有一个很好的总结。(这里的 g(i) 和 h(i) 函数在文本中没有明确命名,但是它们是 gradient 和 hessian。)底线是,如果你知道目标的梯度和 hessian(比如“泊松”),你就知道目标。
让我们看看 LightGBM 源代码中的相关位。在RegressionPoissonLoss
类下,我们有这个位:
gradients[i] = static_cast<score_t>((std::exp(score[i]) - label_[i]) * weights_[i]);
hessians[i] = static_cast<score_t>(std::exp(score[i] + max_delta_step_) * weights_[i]);
注意事项:
- 在这个术语中,分数代表预测。
- 你可以通过计算导数来重现公式的基础。
- 权重参数没有任何更深的数学意义,这是它们将如何被用来衡量梯度和黑森。当然,如果不定义权重,就不使用
* weights_[i]
位。 max_delta_step_
在黑森只是一个确保收敛的值。如果我理解正确的话,XGBoost 和 LightGBM 的默认值都是 0.7。
现在,让我们看看给定的claim_count
— prediction
对会发生什么。
在解决方案 1)中,转折是log(exposure)
被自动添加到预测中,因此梯度将是:
exp(prediction + log(exposure)) - claim_count
这等于:
exp(prediction) * exposure - claim_count
而对于解决方案 2),我们使用权重,因此梯度将简单地乘以曝光度,另外请注意,我们使用调整后的索赔计数作为标签。溶液 2 的梯度):
(exp(prediction) - claim_count_adjusted) * exposure
考虑到
claim_count_adjusted = claim_count / exposure
解 2)的梯度也将等于
exp(prediction) * exposure - claim_count
同样的思考过程可以重复用于 hessian 计算。
对于*(预测、曝光、索赔 _ 计数)的任何可能值,两个解决方案具有相同的梯度*和 hessian ,它们的所有学习参数都匹配,因此它们将返回相同的预测。
我会留下一点时间来处理这个,我认为这是一个很酷的结果。
解决方案 3 —自定义目标函数
既然我们对“泊松”目标有了如此透彻的理解,我想我们还不如编写我们自己的自定义目标函数。
我不打算在这里包括一个通用教程,我认为 R 演示脚本是相当有帮助的。要点是定制目标函数需要返回两个向量:gradient
和hessian
。
密码
对于自定义目标函数,我们基本上使用了我们到目前为止讨论过的所有内容。无论我们预测什么,都会随着曝光率自动调整,下文称之为dtrain_expos
。黑森里的 0.7,简直就是我们前面说的max_delta_step_
。
my_poisson_w_exposure <- function(preds, dtrain){
labels <- getinfo(dtrain, "label")
preds <- matrix(preds, nrow = length(labels))
preds_expos_adj <- preds + log(dtrain_expos)
grad <- exp(preds_expos_adj) - labels
hess <- exp(preds_expos_adj + 0.7)
return(list(grad = grad, hess = hess))
}
然后,我们可以使用这个新的目标函数,而不是内置的“泊松”函数。
solution_3_predict <- function(data_curr){
data_curr_recoded <- lgb.convert_with_rules(
data = data_curr[,.(var1, var2)])$data
dtrain <- lgb.Dataset(
data = as.matrix(data_curr_recoded),
label = as.matrix(data_curr[,.(claim_count)]),
categorical_feature = c(1,2))
param <- list(
max_depth = 2,
objective = my_poisson_w_exposure,
metric = "mae",
num_iterations = 100,
learning_rate = 0.5)
lgb_model <- lgb.train(
params = param,
data = dtrain,
verbose = -1)
return(predict(lgb_model, as.matrix(data_curr_recoded)))
}
瞧,基本上就是这样。请注意,我随机输入了“mae”作为度量。每个内置目标都有一个默认的度量对。当我们使用自定义目标时,需要对其进行定义。如果我们想要谨慎,我们还需要定义一个定制的度量函数。但是我们现在没有使用测试集,所以它不会在任何地方使用。
这种方法有两个缺点:
- 我无法找到在自定义目标函数中包含另一个参数的方法。因此,
data_expos
只是被假设为在全球环境中可用,这对我来说并不意味着稳定的结构。也许有一种方法可以输入除preds
和dtrain
之外的参数,一定要让我知道。 - 除了将从模型中得出的原始预测与暴露量相乘之外,我们还需要计算它们的指数。在内置的“泊松”目标中,有一个额外的步骤来计算原始分数的指数。换句话说,它使用了一个日志链接。这是我在自定义目标中无法做到的。
考虑到这两个问题,使用这种方法进行预测的正确方法是:
dtrain_expos <- as.matrix(data_mod[,.(expos)])
temp_predict <- solution_3_predict(data_mod)
data_mod[,sol_3_predict_raw := temp_predict]
data_mod[,sol_3_predict := exp(sol_3_predict_raw) * expos]
结果
是的,与前两个解决方案相同。
哪个解决方案是最好的?
这是一个个人偏好的问题,从计算的角度来看,它们是相同的模型,并将计算相同的预测。
- 我认为带有
init_score
的解决方案 1)是最优雅和简单的。我怀疑那也是最快的。 - 解决方案 3),自定义目标函数是最健壮的,一旦你理解了它的工作原理,你就可以用它做任何事情。
- 我个人最不喜欢的是解决方案 2),使用调整索赔计数的解决方案,我认为它有点绕弯,没有任何附加值。
一般照明 GBM 提示
我不想在上面的每个细节上花费时间,这里有一个通用提示列表,在使用 LightGBM 或某些情况下其他梯度增强树包时可能会派上用场。
分类特征
在 LightGBM 中,使用分类变量是一个两步过程:
- 首先,你要用
convert_with_rules
把它们转换成整数——这一步是必须的; - 然后,当您创建
lgb.DataSet
时,您可能还想用categorical_feature
指定数据中的哪些列是分类的——从技术上讲,模型将在没有此步骤的情况下运行,并将分类特征作为序数特征处理。
详情请看这个演示脚本。
证明文件
在我看来,软件包文档不是无缝的,你必须测试所有的东西。许多不同的版本(命令行接口,C / Python / R API)通常只是一起记录,这并没有什么帮助。
例如,我不太清楚如何定义init_score
。根据相关的演示脚本,您必须使用以下语法:
setinfo(dtrain, "init_score", ptrain)
然而,这样做的时候用下面的定义lgb.DataSet
:
...
init_score = ptrain,
...
似乎对我来说挺好的。set_init_score
另一方面,看起来像是 Python 特有的方法。
链接功能
您应该知道您所选择的目标所使用的链接功能。例如,它使用泊松的日志链接。如果你想放入一个init_score
,这很重要,你必须根据链接函数转换值。
当您运行predict
方法时,您可以传递一个rawscore = TRUE
参数来在转换之前获取结果并检查它们。
泊松对特威迪
如果您有非整数值,使用基本的“泊松”目标可能看起来很奇怪。毕竟泊松是离散分布。我们如何用泊松来拟合调整后的索赔数?
首先,你可以将阶乘函数扩展到非整数,所以从技术上来说,你可以在非整数处计算分布函数的值。gradient 和 hessian 也不会关心标签是否为非整数。
但是你可能仍然会倾向于使用分散参数设置为 1 的 Tweedie 分布。这样做将导致完全相同的结果。
换句话说,在模型设置中替换这一行:
...
objective = "poisson",
...
有了这个:
...
objective = "tweedie",
tweedie_variance_power = 1,
...
不会改变你的结果。
如果你看一下源代码中的泊松和特威迪损失函数,你可以看到当rho
(色散参数,又名tweedie_variance_power
)等于 1 时,它们是如何匹配的。
不同的术语
在 LightGBM 和 XGBoost 中,Metric、objective 和 eval 具有不同的含义。在 LightGBM 中,您需要一个目标函数来进行优化,只有在使用验证集时,才会显示指标。
好消息来源
https://xgboost.readthedocs.io/en/latest/tutorials/model.html https://github.com/microsoft/LightGBM/tree/master/R-package/demo
如何处理预测中的不确定性
实践教程
对保形预测的深入研究。
每当我们做预测时,我们的估计都有不确定性。例如,让我们考虑一个柠檬水摊位,该摊位希望预测需求。如果预测非常准确,就可以采取行动,他们可以优化他们的柠檬购买策略。另一方面,如果预测有很大范围的可能值,那就没用了。
图 1:不同水平的预测区间覆盖的例子— src 。顶行显示分类,底行显示回归预测任务。“有条件的”覆盖是最稳健的。图片作者。
在2017 年的一篇论文中,卡耐基梅隆大学的研究人员解决了这个问题。他们证明了在最小假设的情况下,保形预测保证了正确的覆盖率。这个证据适用于小规模的数据集。不确定性很重要的主题,如自动驾驶汽车的物体检测,确实可以从这种方法中受益。然而,尽管保形预测已被证明是有效的,但它仍是一种相当不成熟的方法,还没有被 DS 工业广泛采用。
下面,我们将概述它是如何工作的,并提供一些实现说明…
技术 TLDR
保形预测保证了仅使用可交换性假设的预测的α水平覆盖,不需要 IID 数据。这是通过使用样本外校准集创建共形分数分布来实现的。请注意,这些保形分数本质上是基于条件概率的残差,见图 2。
图 2:共形分数的公式。图片作者。
从有序共形分数的分布中,我们找到什么分位数对应于我们的置信水平( α )。然后,我们使用该分位数来确定保证 1-α 覆盖的预测区间,而不考虑 IID 数据或正确的模型。
但是,保形预测实际上是如何工作的呢?
好吧,那是很多。让我们慢下来,真正明白发生了什么。
预测区间的背景
首先,我们来讨论一下预测区间及其问题。
简而言之,预测区间是预测值的置信区间,即我们预计未来预测的大部分将落在该范围内。
图 3:假数据 95%预测区间的例子— src 。图片作者。
在图 3 中,我们可以看到一些假数据的预测区间的例子。每个数据点上方和下方的水平线对应于 95%的预测区间范围— 我们未来预测的 95%将落在该范围内。
不幸的是,预测间隔通常需要几个假设。一些例子包括独立同分布(IID)数据以及正确指定的模型。如果您真的关心准确的预测区间覆盖率,这些假设可能会有问题。
那么保形预测带来了什么呢?
保形预测缺乏假设
保形预测只需要一个叫做互换性的假设。可交换性是指数据的任何排序都同样可能发生。
对于熟悉 IID 假设的人来说,这是“ID”部分——可交换数据相对于预测值是同分布的。
由于只需要一个假设,保形预测可以说是开发预测区间的最具统计稳健性的方法。
该方法是如何工作的?
让我们从一个二元分类的例子开始。从这里开始,我们将把概念扩展到多类分类以及预测连续变量。
图 4:我们的二元分类目标是确定一幅图像显示的是一头牛还是一头骆驼。图片作者。
如图 4 所示,我们希望确定一幅图像显示的是骆驼还是奶牛。如果我们认为图像显示的是一头牛,我们将预测 y=1,如果我们认为图像显示的是一头骆驼,我们将预测 y=0。
步骤 1-创建一个共形分数分布
在我们的第一步中,我们开发了训练/测试分割,并使用训练数据拟合分类模型。假设我们使用逻辑回归。拟合模型后,我们使用测试集(称为校准集)开发因变量(奶牛对骆驼)的概率预测。
在这一阶段,我们有了校准集中每个观察值的预测概率向量。
从那里,我们使用每个预测的概率计算共形分数。图 5 中定义了保形分数的公式。
图 5:包含每个变量定义的共形分数公式。图片作者。
**共形分数可以认为是非共形分数。**它们取值在-1 和 1 之间,越接近任一极端,就越偏离观察到的标签。请注意,我们经常使用绝对值,因为我们只关心不符合的程度,而不是方向。
在获得我们校准集中所有标签的共形分数后,我们将共形分数的绝对值从低到高排序。
步骤 2-创建预测间隔
有了保形分数的分布,我们可以将这个概念与预测区间联系起来。
如前所述,预测间隔要求工程师指定一个假阳性率( α ),通常为 0.05 或 0.01。为了找到我们的预测区间的上限和下限,我们找到对应于 α的分布中的分位数。
图 6:通过预测二元类的概率找到的分级共形分数的示例分布。图片作者。
在图 6 中, α- 水平分位数由标有绿色“临界阈值”的垂直线表示。x 轴对应于一组有序的共形分数。假设他们有 500 人。蓝色和红色的交叉点,即“临界阈值”,是百分位数 1-α 。因此,如果 α 为 0.1,那么统计显著性的截止值将是第 90 百分位的一致性分数,例如第 450 一致性分数。
蓝色的适形分数没有统计学意义。它们在我们的预测区间内。非常大的共形分数(红色)表示与真实标签的高度偏离。这些适形评分具有统计学意义,因此超出了我们的预测区间。
还要注意,我们推导出每个标签的分位数截止值。
步骤 3-估计每个标签的概率
从这里开始,对于每一次观察,我们确定成为牛、骆驼、两者或都不是的概率。这是怎么做到的?
嗯,对于每个观察,我们计算每个标签的共形分数,例如骆驼和母牛。从那里,我们确定每个适形分数是否超过其相应的临界阈值。如果超过阈值,我们认为它在统计上是显著的,因此是错误的。如果不是,我们认为这是真的。
图 7:分类矩阵。蓝色和红色的值分别对应于非 stat-sig 和 stat-sig 预测。作者图片
我们的二元分类问题有四种可能的结果,如图 7 所示。红色表示预测在统计上有意义,蓝色表示没有意义。这里,统计显著性意味着预测是假的,缺乏统计显著性意味着预测是真的。
让我们依次看看每个单元格…
- 左上角:两个标签都不具有统计显著性的预测。在这里,模型预言这两个阶级都是真正的阶级。
- 右下:两个标签都具有统计显著性的预测。在这里,模型预测这两个类都不是真正的类。
- 右上:所有 camel 标签(0)都不具有统计显著性的预测。在这里,模型预测 camel 才是真正的类。
- 左下:所有奶牛标签(1)都不具有统计显著性的预测。在这里,模型预测牛才是真正的类。
这一步可能有点违反直觉。一个模型怎么能预测一个以上的类甚至根本没有类呢?
让我们采取一种直观的方法。简单的二进制分类模型找出哪个类的概率最高,并将其确定为预测。但是有了保形预测,我们可以让模型说两者都不是或者都不是真正的标签。实际上,模型可以说“我不知道”
因为我们不强迫模型做出预测,所以我们在预测集中得到了更可靠的预测。
并且,我们的 1-α 预测集只有一个预测,即右上角和左下角的单元格。
扩展到更复杂的标签
既然我们已经理解了保形预测对于二元分类是如何工作的,那么这个概念就可以很容易地扩展到多级分类。在第 3 步中,我们发现被标记为 1,0,两者皆是,或都不是的概率,我们只是对三个级别而不是两个级别进行相同的操作。
从概念上讲,这是一个简单的下一步,但计算上的复杂性呈指数增长,因此对具有许多级别的标签进行保形预测并不总是一个好主意。
对于连续变量,有几种方法,但最简单的是预测分位数而不是平均值。如前所述,我们可以将共形分数视为残差:真实的 y 减去预测的 y 。然而,与分类变量不同,我们没有固定数量的标签可供尝试。
因此,对于连续标签,我们尝试预测有限数量的不同分位数,并查看它们在哪里变得具有统计显著性。对于处于统计显著性边缘的值,我们认为它们是 α- 水平预测区间。请注意,分位数损失可以添加到几乎任何建模损失函数中,这就是为什么它被称为“最简单的”
如果你想了解更多,这里有一个非常好的资源,可以在连续变量上使用保形预测。
现在你知道了!全盛时期的共形预测。
摘要和实施说明
为了深入理解这些概念,让我们总结一下。
保形预测是开发预测区间的最少假设的方法。因此,这是最普遍的防御方法。它还适用于小样本数据集,可以产生更精确的预测区间/集合。
该方法利用共形分数的分布来开发标记的任何组合为真的概率的排列。如果预测的概率足够低,即保形分数足够大,我们认为它在我们的预测区间之外。然后,这些排列用于开发连续变量的预测区间或分类变量的预测集。
这种方法仍然没有得到太多的关注,但它对预测建模有着巨大的潜力。
感谢阅读!我会再写 36 篇文章,把学术研究带到 DS 行业。查看我的评论,链接到这篇文章的主要来源和一些有用的资源。