TowardsDataScience-博客中文翻译-2020-十一-
TowardsDataScience 博客中文翻译 2020(十一)
成为数据产品经理的分步指南
林赛·亨伍德在 Unsplash 上的照片
在当今快速发展的世界中,技术比以往任何时候都占主导地位。随着越来越多的产品变得数字化,产生和收集的数据量也在增加,与数据相关的就业机会也在增加。
在当今的全球市场上,一个正在崛起的角色——产品经理。角色一直呈指数级增长,让您在管理产品和人员的同时又能接*数据的角色叫什么?数据产品经理—拥有数据科学和分析以及产品管理经验的专业人士是一个巨大的机会!
整个夏天,我发现了对产品管理的热情。我希望磨练一个下午的技能,正如他们所说,做一个“副业”。当我完成 Udacity 的产品经理 nanodegree 时,我正在探索数据中的 PM 角色:责任、技能、产品和工具。
随着数据访问量的增加,产品经理现在有机会利用数据优势,不仅增强现有产品,而且创造全新的产品。
在这篇博客中,我们试图了解数据产品经理在组织中的角色,以及他们如何利用数据科学、机器学习和人工智能来解决问题。
谁是数据产品经理?
你和其他任何产品经理都差不多,指导一个产品的成功,领导负责改进产品的跨职能团队;这里补充一点:你把数据放在你所做的一切的核心。
数据项目经理负责基于先进的数据驱动洞察设计产品和功能,使用 viz 工具可视化数据以进行统计分析,并通过假设测试和建模确定变量之间的独特关系。
旁注:一个好的数据产品经理角色更适合职业生涯中期的角色。
责任
数据产品经理的主要职责是分析市场数据,以提出新产品机会。
- 利用市场知识数据促进产品开发
- 应用数据科学技术、数据工程流程和市场实验测试来交付定制的产品体验
- 利用数据仓库和可视化的强大功能为产品战略提供信息
- 开发数据管道和仓储策略,准备从产品中收集的数据,以便进行稳健的分析
- 学习评估实时产品数据的技术,包括如何设计和执行各种 A/B 和多变量测试来塑造产品的下一个迭代
- 评估统计分析中捕获的输出,并将其转化为洞察,为产品决策提供信息
如何准备成为数据 PM!?
数据项目经理是专注于构建数据产品的多学科团队的一部分,对产品领域有兴趣和资质。
1.了解如何管理数据团队的复杂性
在任何组织中,数据科学团队都是不同业务部门的交叉部门,并在其感兴趣的特定领域内开展工作。话虽如此,数据科学团队都非常不同。
- 理解业务需求、团队目标和每个团队成员的动机
- 使用已建立的学习-计划-测试-测量流程,找到将数据输入产品的方法
- 根据所考虑的产品扩展数据科学团队
- 评估 DS 团队在产品决策过程中的作用
- 培养跨职能团队协作:让来自营销、设计、工程师的不同人员加入您的团队,与数据和 PM 团队紧密合作。
2.了解数据产品的生命周期和发展
数据生命周期管理是一个团队在组织中控制数据的过程。
当在团队中处理涉及数据的产品、解决方案或服务时,重要的是每个团队成员都了解从构思到需求收集、理解、项目规划、实现、迭代、评估和发布的产品生命周期。
数据产品的生命周期只是对产品生命周期的一种增强,只是数据的细微差别:可以是敏捷模型或瀑布模型,这取决于业务需求,但这无疑在您成为数据 PM 的过程中扮演着重要的角色。
- 数据采集
- 数据准备
- 假设和建模
- 评估和解释
- 部署
- 操作
- 最佳化
- 发动
3.磨练你的技术知识:统计、SQL、机器学习
当你是一个产品经理时,你需要学习和了解产品生命周期中所有方面的知识。同样适用于数据 PM。
数据是一种力量,它允许企业和利益相关者做出明智的决策,并利用数据为他们的产品解决问题。
从理论上来说,了解数据概念、统计学:至少回归和相关之间的区别、机器学习算法、何时使用什么模型的人,可以被定义为“好的”数据 PM。
高效数据产品管理的方法是不断学习。正如埃隆·马斯克所说,(在互联网上)学习是免费的;更多的是对学习的追求。任何人都可以用数据做一些普通的事情。区别线是你能比 x 人做得多好。
4。提高你的分析能力
产品经理是典型的问题解决者。不可避免地,当出现问题时,产品经理将需要分析技能来解决问题或改变方向。
了解你的技术团队正在发生什么是不可避免的。数据产品经理必须能够以熟练的技术进行分析和思考。
并不是说数据项目经理需要专注于具体的技术细节,但重点肯定应该更多地放在他们如何看待、分析问题,以及用强大的分析技能处理问题。
在产品及其管理的背景下,数据 PM 也做大量的分析:从创建定制的仪表板、报告工具来帮助表面到在整个组织中共享见解。数据项目管理的利益相关者多种多样,从精明的数据科学家到高管等只读消费者。
5.发展情商
随着我与职场人士的接触越来越多,我每天都在阅读情商的重要性。
"情商是理解和管理情绪的能力."
情商涉及的技能有自我意识、自我调节、动机、同理心和社交技能。
我认为,情商之所以成为热门词汇,是因为它包含了人类情感在工作中的细微差别。这种东西正引领着员工之间更好的协作和更快乐的工作场所。随着全球化,情商比以往任何时候都更加重要,越来越多的团队变得跨文化和全球化,增加了情感互动及其表达方式的复杂性。
简而言之,情商就是理解、表达和管理与同龄人的良好关系,即使在压力下也能高效解决问题。
6.数据叙事
当我们谈论数据产品时,显然需要以能够帮助客户了解信息并做出更明智决策的方式向客户呈现数据。最优秀的产品经理将能够让数据看起来简单而吸引人,尽管其背后有很多复杂性。
当数据产品成功时,它们解决了客户、利益相关者的担忧,同时也产生了新的问题。然而,一个精通数据的项目经理将围绕产品创造一个故事,定义一个路线图,在产品推出之前,随着客户对数据变得更加聪明,该路线图将理解并结合客户的需求。
7.通过在职学习成为产品经理
你可能已经从一名初级数据科学家,甚至是一个对数据和产品管理充满热情的 SDE 角色开始了你的旅程。在工作中,你在工作中积累技能和经验。这无疑是一条缓慢的道路,但却是成为成功产品管理的最有效途径。
如果你没有或不能接受从事产品工作的专业培训,探索成为自由职业项目的产品经理的机会,或者作为副业参与公司的生产过程。
这就是我的博客的结尾。感谢您的阅读!我希望这有助于理解数据产品经理的角色。请务必让我知道你是否是一名数据项目经理,你正在寻找或已经学习或探索什么技能。
如果你喜欢阅读这样的故事,并希望支持我成为一名作家,可以考虑使用这个链接注册成为一名媒体会员(我可以赚取一小笔佣金,而不需要你额外付费!)
免责声明:本文表达的观点仅代表我个人,不代表严格的观点。
了解你的作者
拉什是芝加哥伊利诺伊大学的研究生。她喜欢将数据可视化,并创造有见地的故事。当她不赶着赶学校的最后期限时,她喜欢喝一杯热巧克力,写一些关于技术、UX 等的东西。
使用 Python 下载漫画的分步指南
网页抓取/ 采集
技术可以用来解决我们的日常问题。
由奥拉夫·阿伦斯·罗特内在 Unsplash 上拍摄的照片
那些不熟悉漫画和动漫的人,让我为他们澄清一些事情。在日本文化中,漫画是包含故事的漫画,其中有卡通人物的精髓。动漫是在漫画出版并流行到足以制作动画并从中获利后由漫画改编而成的。在日本,所有年龄的人都阅读漫画。
有一天,我开始看《一拳》动漫,因为我的一个动漫爱好者朋友推荐我在这个疫情尽情观看。我不经常看动漫。但是,我只看推荐的和在 IMDB 上有很高人气的。所以,它总共有两季,而且都完成了。但是,它有更多的季节来晚了,由于这个疫情,整个日本的动画制作已经停止。所以,我告诉我的朋友,我已经完成了两季,在等待第三季的时候,我不能保持我的渴望,他告诉我有一个网站,你可以在那里阅读漫画。它叫做mangapanda.com
我看到有太多的广告弹出来创收,这太分散注意力了。开始在漫画网站搜索《一拳》,开始看了一段时间。我厌倦了阅读,因为每次你看到主屏幕和广告都会让你心烦。
作为一名电脑极客,我开始使用 web developer 工具分析该网站,默认情况下,任何 web 浏览器都可以通过按 CTRL+SHIFT+I 来使用该工具。我发现该网站的主项目容器(包含漫画图像)有一个 HTTPS 链接。jpg 格式。
来源:(在网站上按 CTRL+SHIFT+I,选择图片查看此菜单)
点击该链接在浏览器中打开图像,没有广告。但是每次打开切换工具然后点击链接听起来很乏味,对吗?。于是,一个念头涌上心头,有没有办法把这些图像和其他图像在延续中提取出来?事实证明,在这种情况下,网络搜集会有所帮助。啊,我听说过它,但是从来没有时间使用它。
使用我们的大脑和编码技巧来解决问题的时候到了。
为此,我使用了 google-colab。如果你对它不熟悉的话 查一下 这个就出来了!
第一步:
引进必要的图书馆来建立我们自己。
第二步:
我们会将所有的 HTTPS 图片链接保存在 img[] 中。
漫画的每一部分总共有两个 for 循环。
来源:来自我笔记本电脑的截图
回路的第一个是零件号,回路的第二个是段号。在上面的例子中,它是第 135 部分和一拳漫画的第 5 部分。
在上面的代码中,我使用了 range (1,2) 来提取漫画的第一部分,在第二个循环中使用了 range (1,200) ,因为这部漫画的任何部分都没有超过 200 页。
使用请求库获取页面的链接,如果 URL 存在,使用漂亮的汤库解析它,并将这个解析包含在 page_content 中。这个页面 _ 内容页面的所有信息都以 HTML 标签的形式出现。
我们的图像链接在 page_content 的一个脚本标签中。因此,我们提取所有的脚本标签并添加到一个名为 row_data 的列表中。我们发现索引号 2 有我们的图像,所以我们使用正则表达式提取图像并添加到 img[] 。对我来说这是一个困难的部分,因为我对它不熟悉。
现在我们有了 img[]中的所有图像,所以我们剩下的就是使用我们在 starting 中导入的文件库来下载它(从 google.colab 导入文件)
来源:来自我笔记本电脑的截图
(注意:如果您使用另一种环境来下载图像,方法会有所不同。可以用 wget 下载)。
现在,你可以把所有这些图片做成 PDF 格式,开始阅读没有任何广告的漫画。万岁!!
如果你想下载你最喜欢的漫画,那么去漫画熊猫网站,获取网址并粘贴到网址变量中。
链接到 colab 笔记本
我相信它会对你有用,你会从这篇文章中有所收获。直到那时快乐编码!!
获得基线算法的逐步指南
在任何给定的数据科学解决方案中获得基准算法的逐步过程。
第一步
确定你的商业目标。我们最成功的目标(推动最大价值)是可衡量的、可操作的、可行的,并直接影响业务。例如,一个好的初始目标是“让我们建立一个算法模型,在评估我们业务的未来客户时,帮助我们识别坏客户和好客户”。假设我们有一个数据字典,它定义了潜在好客户和潜在坏客户的标准。
步骤 1a:
建立你的评价标准。什么指标将为我们提供实现业务目标所需的洞察力?例如,“我们想衡量我们的算法有多精确?”
第二步
采集数据&开始分析。
从任何来源提取数据(这本身就是一个过程,并不是本文的基础)。成功导入文件后,观察列数、行数、列名等。仔细看看,检查各个列的名称,是否清楚您正在查看哪种数据?为什么或为什么不?在开始挖掘细节之前,先从高层次的概念上审视您的数据。即使您发现您的数据特别“脏”或不清楚,了解所有事物是如何联系在一起的也是很重要的。
步骤 2a:
确定它是数值型还是分类型。你的变量类型是什么?是正态分布吗?如果数据是分类的,那么你的数据是有序的还是名义的?如果你的数据是数值,你的数值是离散的还是连续的?我建议在你的 Jupyter 笔记本上记下这些信息,例如,通过注释(这里用#comment)。
步骤 2b:
确定您的数据是否有异常值。为了对您的数据进行适当的计算,您需要尽可能地将其标准化。去掉无关的数据点将有助于你的数据结构不会过于倾斜。
步骤 2c:
识别缺失值(如有)。通常,我们使用*均值,有时是中值或众数来给出最佳值,以填充数据集中的任何空白。
第三步
分割数据80/20 或 75/25,其中 80%或 75%是您的训练集,20%或 25%是您的测试集。你不需要在你所有的东西上训练你的算法——你的算法需要新的原始数据来测试。我们使用样本在新的东西上测试模型(模型以前没有见过这个数据)。我们基于训练数据集建立我们的预测结果。通过将我们的预测结果与测试数据集进行比较,我们可以衡量该算法的真正实力。
为了获得我们可以进行计算和预测的标准化数据,我们必须以各种方式清理数据。
第四步
对训练数据进行规范化和‘清洗’。填充缺失值、剩余的异常值以帮助规范化数据,以便您可以正确地使用它。
步骤 4a:
对测试数据进行规范化和‘清洗’。虽然这种方法可能被视为更加繁琐,但它被认为是将测试数据集与训练数据集分开进行清理的最佳实践——它有助于避免过度拟合。过度拟合是指当预测数据与历史数据过于接*时,模型中出现的错误。
第五步
建模阶段。确定哪些类型的模型,这取决于我们寻求应用哪种机器学习类型。我们自问,是分类问题,回归问题,还是无监督学习问题?
一旦确定,实现模型。在这里,您可以选择属于您的“问题类型”的 3-4 种不同的算法。
基本算法分解
分类:随机森林、朴素贝叶斯、逻辑回归、梯度推进、K *邻。
回归:山脊、套索、弹性、网状、线性、非线性(这些算法不要与分类算法混淆,因为它们是回归算法——随机森林回归器、梯度推进回归器、K-最*邻回归器)。
无监督学习:降维((SVD:奇异值分解,PCA:主成分分析,LDA:潜在狄利克雷分配))、K-Means((分层的,基于密度的,基于距离的))。
第六步
训练你的算法。从上面的列表中选择,根据训练数据集训练你的算法。
第七步
做个预测。采用经过训练的算法,通过将您的预测结果应用到测试数据集来进行预测。接下来,我们将获取预测结果或输出,并对其进行分析。
第八步
评估。获取测试结果,并将其与真实值进行比较。将预测值与真实值进行比较的行为被归类为评估模型。一旦进行了比较,我们就会看到我们之间的差距(即准确度得分度量告诉我们有多远)。如果你的评价低于你的门槛,你应该高兴!如果您的预测结果非常不准确,也许您在第一次运行时看到了极高的准确度,您将不得不返回并检查您的数据和所做的任何调整。当您没有看到您希望的指标时,首先在内部解决您的问题,检查您是如何清理数据的,以确保您没有遗漏任何东西。尝试一种不同的算法,使用您可能创建的任何函数或新列或数据集。一旦你可以自信地确认你的过程和算法是合理的,然后从外部寻找不同的数据来源——也许有一些开源数据可以支持你的预测模型?
第九步
特色工程。如果你穷尽了所有不同类型的数据,穷尽了所有不同类型的算法,那么就开始特征工程。最好的做法是,一旦你开始第二轮,就开始特征工程。制作笔记本的副本,并开始在副本上重新制作模型,这样您就可以比较和对比过程差异和输出差异。创建新功能不是一件轻而易举的事情,所以要坚持做下去,并花时间进行评估。
第十步
把你的发现和分析放在一起。用一种最能引起受众共鸣的方式传达你的发现。考虑一个 Keynote、PowerPoint、Google Slides 演示文稿,它以一种有意义但易于理解的方式概括了你的发现,让你的业务伙伴能够最好地综合所有已经完成的工作。
Python 中的交互式 Choropleth 地图
学习使用 Python 的叶库轻松开发 Choropleth 地图
Choropleth 地图是最有趣和最有用的可视化工具之一。它们很重要,因为它们可以提供地理位置信息,它们看起来很漂亮,在演示中能吸引注意力。几个不同的库可以用来做这件事。在本教程中,我将使用叶。
什么是 choropleth 地图?
这是来自维基百科的定义:
Choropleth 图提供了一种简单的方法来可视化一个地理区域内的测量值如何变化,或显示一个区域内的可变性水*。一张热图或是一张类似但不使用先验地理区域。它们是最常见的专题地图类型,因为发布的统计数据(来自政府或其他来源)通常被聚合到众所周知的地理单元中,如国家、州、省和县,因此使用 GIS 、电子表格或其他软件工具创建它们相对容易。
用简单易懂的话来说,choropleth 地图是通过在地图上使用颜色来显示地理位置信息的地图。看下面的一些图片,获得更多的理解。
数据准备
数据准备是所有数据科学家的一项重要而普遍的任务。我在这里使用的数据集相当漂亮和干净。但是对于这个可视化,我仍然需要做一些工作。让我们导入必要的库和数据集。
import pandas as pd
import numpy as npdf = pd.read_excel('[https://s3-api.us-geo.objectstorage.softlayer.net/cf-courses-data/CognitiveClass/DV0101EN/labs/Data_Files/Canada.xlsx'](https://s3-api.us-geo.objectstorage.softlayer.net/cf-courses-data/CognitiveClass/DV0101EN/labs/Data_Files/Canada.xlsx'),
sheet_name='Canada by Citizenship',
skiprows=range(20),
skipfooter=2)
我不能在这里显示数据集的截图,因为它太大了。我鼓励你自己运行代码。这是唯一的学习方法。
该数据集包含从 1980 年到 2013 年有多少来自世界不同国家的移民来到加拿大。让我们看看数据集的列名,以了解该数据集包含的内容:
df.columns#Output:
Index(['Type', 'Coverage', 'OdName', 'AREA', 'AreaName', 'REG', 'RegName', 'DEV', 'DevName', 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013],
dtype='object')
我们要绘制每个国家从 1980 年到 2013 年的移民总数。
我们需要国名和年份。从数据集中删除一些不必要的列。
df.drop(['AREA', 'REG', 'DEV', 'Type', 'Coverage', 'AreaName', 'RegName', 'DevName'], axis=1, inplace=True)
“OdName”列是国家的名称。为了便于理解,将其重命名为“国家”。
df.rename(columns={'OdName':'Country'}, inplace=True)
现在,做一个“总数”栏,这是每个国家所有年份的移民总数。
df['Total'] = df.sum(axis=1)
看,我们在最后有“总计”栏。它给出了每个国家的移民总数。
记住将这个轴设置为 1 是很重要的。它说求和操作应该是跨列的。否则,它将跨行求和,我们将得到每年的移民总数,而不是每个国家的移民总数。
基本 Choropleth 图
我将在这里展示,如何一步一步地绘制出一张 choropleth 地图。进口叶。如果您没有 lyum,请在 anaconda 提示符下运行以下命令进行安装:
conda install -c conda-forge folium
现在导入叶子,生成世界地图。
import folium
world = folium.Map(location=[0,0], zoom_start=2)
现在在这个世界地图中,我们将设置我们的数据。但它也需要包含每个国家坐标的地理数据。从此链接下载地理数据。我已经下载并把它放在了我在本教程中使用的笔记本所在的文件夹中。我现在只需要看那份文件。
wc = r'world-countries.json'
对于这张 choropleth 地图,你需要传递
- 我们在上面保存为“wc”的地理数据,
- 数据集,
- 我们需要从数据集中使用的列,
- 来自地理数据的“钥匙开启”参数。“key_on”参数的值始终以“feature”开头。然后,我们需要添加我们保存为“wc”的 geo_data 中的键。那个 JSON 文件太大了。因此,我展示了其中的一部分来解释 key_on 参数:
{"type":"Feature","properties":{"name":"Afghanistan"},"geometry":{"type":"Polygon","coordinates":[[[61.210817,35.650072],[62.230651,35.270664],[62.984662,35.404041],[63.193538,35.857166],[63.982896,36.007957],[64.546479,36.312073],[64.746105,37.111818],[65.588948,37.305217],[65.745631,37.661164],[66.217385,37.39379],[66.518607,37.362784],[67.075782,37.356144],[67.83,37.144994],[68.135562,37.023115],[68.859446,37.344336],[69.196273,37.151144],[69.518785,37.608997],[70.116578,37.588223],[70.270574,37.735165],[70.376304,38.138396],[70.806821,38.486282],[71.348131,38.258905],[71.239404,37.953265],[71.541918,37.905774],[71.448693,37.065645],[71.844638,36.738171],[72.193041,36.948288],[72.63689,37.047558],[73.260056,37.495257],[73.948696,37.421566],[74.980002,37.41999],[75.158028,37.133031],[74.575893,37.020841],[74.067552,36.836176],[72.920025,36.720007],[71.846292,36.509942],[71.262348,36.074388],[71.498768,35.650563],[71.613076,35.153203],[71.115019,34.733126],[71.156773,34.348911],[70.881803,33.988856],[69.930543,34.02012],[70.323594,33.358533],[69.687147,33.105499],[69.262522,32.501944],[69.317764,31.901412],[68.926677,31.620189],[68.556932,31.71331],[67.792689,31.58293],[67.683394,31.303154],[66.938891,31.304911],[66.381458,30.738899],[66.346473,29.887943],[65.046862,29.472181],[64.350419,29.560031],[64.148002,29.340819],[63.550261,29.468331],[62.549857,29.318572],[60.874248,29.829239],[61.781222,30.73585],[61.699314,31.379506],[60.941945,31.548075],[60.863655,32.18292],[60.536078,32.981269],[60.9637,33.528832],[60.52843,33.676446],[60.803193,34.404102],[61.210817,35.650072]]]},"id":"AFG"}
在 properties 键中,我们有国家的名称。这就是我们需要传递的。因此,key_on 参数的值将是“feature.properties.name”。
5.我还将使用一些样式参数:fill_color、fill_opacity、line_opacity 和 legend_name。我觉得这些都是不言自明的。
这是我们第一张 choropleth 地图的代码:
world.choropleth(geo_data=wc,
data=df,
columns=['Country', 'Total'],
key_on='feature.properties.name',
fill_color='YlOrRd',
fill_opacity=0.8,
line_opacity=0.2,
legend_name='Immigration to Canada'
)
world
这张地图是互动的!你可以用鼠标导航。而且,它会随着强度改变颜色。颜色越深,越多的移民从那个国家来到加拿大。但是黑色意味着没有可用的数据或者没有移民。
添加图块
这张地图可能看起来有点*面。我们可以用瓷砖让它看起来更有趣:
world_map = folium.Map(location=[0, 0], zoom_start=2, tiles='stamenwatercolor')
world_map.choropleth(geo_data=wc,
data=df,
columns=['Country', 'Total'],
threshold_scale=threshold_scale,
key_on='feature.properties.name',
fill_color='YlOrRd',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='Immigration to Canada'
)
是不是更好看!我们可以通过使用一些瓷砖来使它变得更有趣,这将为我们提供根据需求更改瓷砖的选项。我们将使用 follow 的 TileLayer 方法在地图上添加不同的*铺层。最后,我们还将包含 LayerControl 方法,以获得更改图层的选项。
world = folium.Map(location=[0, 0], zoom_start=2, tiles='cartodbpositron')
tiles = ['stamenwatercolor', 'cartodbpositron', 'openstreetmap', 'stamenterrain']
for tile in tiles:
folium.TileLayer(tile).add_to(world)
world.choropleth(
geo_data=wc,
data=df,
columns=['Country', 'Total'],
threshold_scale=threshold_scale,
key_on='feature.properties.name',
fill_color='YlOrRd',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='Immigration to Canada',
smooth_factor=0
)folium.LayerControl().add_to(world)
world
看,在传说的右上角下面,有一堆瓷砖。如果你点击它,你会得到一个列表。您可以在那里更改瓷砖样式。我觉得这个选项很酷!
添加信息标签
最后,我想向您展示另一个有用且有趣的选项。那就是使用一个信息标签。我们不能指望每个人通过看地图就知道国家的名字。地图上有国家的标签会很有用。我们会让它变得有趣。Folium 有一个名为“GeoJsonTooltip”的功能可以做到这一点。首先,我们需要像往常一样制作世界地图。将所有参数添加到其中并保存在一个变量中。然后使用带有 add_child 方法的“GeoJsonTooltip”添加此附加功能。这是完整的代码。
world = folium.Map(location=[0,0], zoom_start=2, tiles='cartodbpositron')
choropleth = folium.Choropleth(geo_data=wc,
data=df,
columns=['Country', 'Total'],
threshold_scale=threshold_scale,
key_on='feature.properties.name',
fill_color='YlOrRd',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='Immigration to Canada',
).add_to(world)choropleth.geojson.add_child(
folium.features.GeoJsonTooltip(['name'], labels=False))
world
注意,我把光标放在法国,它显示法国这个名字。同样的方法,你可以把光标放在地图上的任何地方,得到这个地方的名字。
结论
我想展示如何开发一个交互式 choropleth 地图,设计它的样式,并向它添加信息标签。我希望它有帮助。
阅读推荐
绘制世界特定地区的地图,在地图上展示活动,并四处导航
towardsdatascience.com](/interactive-geospatial-data-visualization-in-python-490fb41acc00) [## 使用 Python 的 Matplotlib 的华夫饼图表
如何使用 Matplotlib 库在 Python 中绘制华夫饼图表
towardsdatascience.com](/waffle-charts-using-pythons-matplotlib-94252689a701) [## Matplotlib 中的气泡图
通过使用 Python 的 Matplotlib 库的例子学习绘制气泡图
towardsdatascience.com](/bubble-plots-in-matplotlib-3f0b3927d8f9) [## 用于数据建模的探索性数据分析
如何了解数据集,定义因变量和自变量,计算相关系数…
towardsdatascience.com](/exploratory-data-analysis-intro-for-data-modeling-8ff019362371) [## 置信区间的完整指南,以及 Python 中的示例
对统计学中一个非常流行的参数——置信区间及其计算的深入理解
towardsdatascience.com](/a-complete-guide-to-confidence-interval-and-examples-in-python-ff417c5cb593) [## 在 Python 中生成任意形状的单词云
学习生成一个单词云,设计它的样式并使用自定义形状
towardsdatascience.com](/generate-word-clouds-of-any-shape-in-python-e87f265f6352)**
在 macOS/Linux 上运行 Cron 和 Launchd 的完整指南
编程;编排
计划任务的逐步指南
左图由 Unsplash 上的 Mindspace 工作室拍摄。作者的正确图像
**Table of contents**[**Introduction**](#7f32)1\. [Papermill and terminal-notifier](#b73c)
2\. [cron for Linux/macOS](#919e)
3\. [launchd for macOS](#bfcb)
[**Conclusion**](#c03d)
[更新:2021 年 5 月 28 日]
介绍
你有一个需要你每天花费时间的数据科学项目吗?您是否使用每天更新的数据馈送?例如,约翰霍普金斯大学 CSSE 分校的 2019 新型冠状病毒新冠肺炎(2019-nCoV)数据仓库每天更新,我在我的个人项目中使用它。
我手动启动 Jupyter,打开一个项目,重启内核并运行所有单元,然后 git add/commit/push。这是一点工作。在本文中,我将分享为您的数据科学项目设置launchd
和cron
作业的一步一步的过程,这样它将在后台自动更新您的项目,甚至通知您。
用于 Linux/macOS 的**cron**
和用于 macOS 的 **launched**
虽然 launchd 是 macOS 中的首选方法,但是
cron
方法在 macOS 中也同样适用。
cron
是一个 Linux 实用程序,它可以安排服务器/计算机上的命令或脚本在指定的时间和日期自动运行。cron 作业是计划任务,它对于自动化重复任务非常有用。
launchd 是苹果公司创造的,是许多 Unix 工具的替代品,如cron
、inetd
、init
、等。
看完这篇文章,你就可以开始安排任务了,节省了你很多宝贵的时间。
** [## 用 Jupyter 笔记本写作的 7 个基本技巧
第一篇数据科学文章指南
towardsdatascience.com](/7-essential-tips-for-writing-with-jupyter-notebook-60972a1a8901) [## 手把手的 Jupyter 笔记本黑客
您应该使用的技巧、提示和快捷方式
towardsdatascience.com](/hands-on-jupyter-notebook-hacks-f59f313df12b)
步骤 0:造纸厂和终端通知程序
造纸厂
Papermill 是一个参数化和执行 Jupyter 笔记本的工具。我可以用它在 cron 和 launchd 作业文件中运行 Jupyter 笔记本文件。
$ pip install papermill
或者
$ pip3 install papermill$ papermill --help
你可以在这里找到命令行界面帮助。
造纸厂的用途:
papermill [OPTIONS] NOTEBOOK_PATH OUTPUT_PATH
我很快会给你看一个例子。
终端通知程序
运行中的终端通知程序。作者图片
终端通知器是一个发送 macOS 用户通知的命令行工具。当计划的作业完成时,我将用它来通知我。
安装终端通知程序。
$ brew install terminal-notifier
$ terminal-notifier -help
今天你将度过的最好的 11 分钟:程序员的终端提示
towardsdatascience.com](/the-ultimate-guide-to-your-terminal-makeover-e11f9b87ac99)
用于 Linux/macOS 的 cron
在 macOS 中,您可以通过两种方式定时运行后台作业:启动作业和 cron 作业。请注意,macOS v10.15 仍然支持它,尽管cron
不是推荐的解决方案,并且launchd
已经被取代。
步骤 1:设置 cron 作业
您可以使用您的用户名设置 cron 作业:
$ whoami
your-name$ sudo crontab -u your-name -e
Password:
sh-3.2#
您可以在 macOS 中使用sudo su
来启用 root 用户,这样您就不需要输入密码了。
$ sudo su
$ crontab -u your-name -e
-u
指定用户的名称。-e
编辑当前的 crontab。
句法
cron 语法指南。作者图片
如上所述,添加五个数字和一个要执行的文件的路径。
示例:
0 10 * * * ~/DataScience/covid-19-stats/covid19-cron
上面会在每天 10:00 运行文件~/DataScience/covid-19-stats/covid19-cron
。
如果系统关闭或休眠,cron 作业不会执行。如果您错过了指定的时间,它将在您的系统打开时的下一个指定时间执行。
可以输出stdout
和stderr
:
# log stdout and stderr
42 6 * * * ~/DataScience/covid-19-stats/covid19-cron > /tmp/stdout.log 2> /tmp/stderr.log
>
将标准输出重定向至/tmp/stdout.log
,而>2
将标准误差重定向至/tmp/stderr.log
。
一旦设置了 cron 作业,您可以列出它:
$ crontab -l
0 20 * * * ~/DataScience/covid-19-stats/covid19-cron
如果要删除所有 cron 作业:
$ crontab -r
您可以在 crontab 中添加多个 cron 作业。
0 20 * * * ~/DataScience/covid-19-stats/covid19-cron
0 7 * * * Path/to/file/to/execute
0 7 * * 0 Path/to/another/file/to/execute
crontab guru 是一个快速简单的 cron 计划工具。
步骤 2:编写 cron 作业
您可以将所有 cron 作业文件放在一个目录中,但是我将它放在项目根目录中。将当前工作目录更改为您的项目,创建一个 cron 作业文件,并在编辑器中打开它。根据谷歌风格指南,可执行文件不应该有.sh
扩展名。
$ cd path/to/project
$ touch covid19-cron
$ vim covid19-cron
步骤 3:定义 shebang
脚本第一行中使用的 shebang 表示要执行的 UNIX/Linux 操作系统。
尽管 Papermill 和 terminal-notifier 在终端中工作,但我们需要添加它们的路径。
让我们找到他们。
$ which papermill
/usr/local/bin/papermill$ which terminal-notifier
/usr/local/bin/terminal-notifier
在我的 covid19-cron 文件中:
#!/usr/bin/env bash
# run covid-19 files
# git add, comit and push
dir=/Users/shinokada/DataScience/covid-19-stats
papermill=/usr/local/bin/papermill
notifier=/usr/local/bin/terminal-notifier
cd $dir
$papermill covid-19-matplotlib.ipynb ./latest/covid-19-matplotlib.ipynb
# more files ...
$papermill covid-19-plotly.ipynb ./latest/covid-19-plotly.ipynb git add .
git commit -m "update"
git push
$notifier -title Covid19 -subtitle "Daily Updated" -message "Completed" -open "https://mybinder.org/v2/gh/shinokada/covid-19-stats/master"
now=$(date)
echo "Cron job update completed at $now"
我在根目录中创建“最新”目录。造纸厂将文件输出到这个“最新”目录。因为我们将使用 git,所以您需要确保在项目根目录中有.git
。
如果您使用的是%run somefile
,我建议您将它们添加到 cron-file 中。
我使用title
、substitle
、message
和open
作为终端通知器选项。
终端通知程序快速指南
终端通知程序快速指南。作者图片
步骤 4:添加执行权限
这个 bash 文件需要权限才能执行。
$ chmod u+x covid19-cron
chmod
设置文件权限。
chmod 用户指南。作者图片
chmod 行动指南。作者图片
chmod 权限指南。作者图片
chmod u+x covid19-cron
允许用户执行 covid19-cron。
上述命令与以下命令相同:
$ chmod 744 covid19-cron
邮寄
在运行 cron 作业后,您的终端通过邮件发送其输出和错误消息。让我们检查一下 cron 的工作是否有效。
$ mail
你需要按回车键来阅读信息,然后按 q 和回车键退出。使用j
查看下一行。你需要检查邮件是否没有错误。如果出现错误,您需要关注问题。
测试 cron 作业
您需要重置 crontab 时间来测试您的 cron 作业。launchd
允许我们测试工作,但对于cron
这是唯一的测试方式。
$ sudo crontab -u your-name -e# change time
5 20 * * * ~/DataScience/covid-19-stats/covid19-cron
$ crontab -l
5 20 * * * ~/DataScience/covid-19-stats/covid19-cron
测试完成后,它会显示通知。
终端通知。作者图片
macOS 的启动
[launchd](https://www.launchd.info/)
是一个统一的开源服务管理框架,用于启动、停止和管理守护程序、应用程序、进程和脚本。
如果您通过设置 StartCalendarInterval 键来计划一个启动的作业,并且计算机在该作业应该运行时处于睡眠状态,则您的作业将在计算机唤醒时运行。
然而,如果在作业本应运行时机器关闭,则作业不会执行,直到下一个指定时间出现。
步骤 1: plist 文件
一个 PLIST 文件是一个系统范围的和每个用户的守护进程/代理配置文件。守护程序/代理是在后台运行的程序,无需用户输入。你定义程序的名字,什么时候运行,你想运行什么,等等。您将所有 plist 文件存储在~/Library/LaunchAgents
目录中。
[Update.1]如果您没有~/Library/LaunchAgents
,您需要创建它。
# check ~/Library if it has LaunchAgents
$ ls ~/Library
# if not create the directory
$ mkdir ~/Library/LaunchAgents
创建一个plist
文件:
$ cd ~/Library/LaunchAgents
$ touch com.shinokada.covid19.plist
在 com.shinokada.covid19.plist 中:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.shinokada.covid19</string>
<key>Program</key>
<string>/Users/shinokada/DataScience/covid-19-stats/covid19-launchd</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/bin:/usr/bin:/usr/local/bin</string>
</dict>
<key>StandardInPath</key>
<string>/tmp/covid.stdin</string>
<key>StandardOutPath</key>
<string>/tmp/covid.stdout</string>
<key>StandardErrorPath</key>
<string>/tmp/covid.stderr</string>
<key>WorkingDirectory</key>
<string>/Users/shinokada/DataScience/covid-19-stats</string>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>8</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</dict>
</plist>
在这里我每天早上八点跑/Users/shinokada/DataScience/covid-19-stats/covid19-launchd
。
plist 文件快速指南中的配置
plist 文件快速指南中的配置。更多关于发射配置。作者图片
步骤 2:创建 bash 文件
在项目根目录下创建一个名为 covid19-launchd 的文件。这与上面的covid19-cron
非常相似。
#!/usr/bin/env bash
# run covid-19 files
# git add, comit and pushpapermill covid-19-data.ipynb ./latest/covid-19-data.ipynb
papermill multiplot.ipynb ./latest/multiplot.ipynb
# more files ...
papermill uk-japan.ipynb ./latest/uk-japan.ipynb
papermill Dropdown-interactive.ipynb ./latest/Dropdown-interactive.ipynbgit add .
git commit -m "update"
git push
terminal-notifier -title Covid19 -subtitle "Daily Updated" -message "Completed" -open "[https://mybinder.org/v2/gh/shinokada/covid-19-stats/master](https://mybinder.org/v2/gh/shinokada/covid-19-stats/master)"
now=$(date)
echo "launchd update completed at $now"
因为我们在 plist 文件中设置了PATH EnvironmentVariables
,所以我们不需要担心 Papermill 和终端通知程序的绝对路径。
你可以通过bash covid19-launchd
测试一下是否有效。
步骤 3:添加执行权限
这个 bash 文件需要权限才能执行。
$ chmod u+x covid19-cron
步骤 4:测试 launchd
lauchctl
控制 macOS 启动过程。它有list
、start
、stop
、load
、unload
、等子命令。
为了我的案子;
$ launchctl list | grep covid
- 0 com.shinokada.covid19# test/debug
$ launchctl start com.shinokada.covid19# if you need to stop
$ launchctl stop com.shinokada.covid19# load the job
$ launchctl load ~/Library/LaunchAgents/com.shinokada.covid19.plist# unload the job
$ launchctl unload ~/Library/LaunchAgents/com.shinokada.covid19.plist# get help
$ launchctl help
作者图片
再装
launchctl
没有用于读取 config.plist 文件更改的 reload 命令。相反,您必须卸载然后重新加载 plist 文件,例如:
$ launchctl unload ~/Library/LaunchAgents/com.shinokada.covid19.plist$ launchctl load $_
$_
和!$
一样,指的是前一条命令的最后一个参数。
如果您对脚本或 plist 进行了任何更改,请确保卸载并加载 plist。
启动快速指南
launchctl
有多个子命令,下图显示了重要的子命令。
启动快速指南。作者图片
结论
计划任务节省您的时间,并且易于设置。您不仅可以为您的数据科学项目设置它,还可以为您的日常工作设置它,例如更新节点包、自制公式等。如果你每天节省 3 分钟,一年就能节省 18 个小时以上!如果你有兴趣,可以在这里看到我的样本项目。
通过 成为 会员,可以完全访问媒体上的每一个故事。
参考
- https://apple . stack exchange . com/questions/29056/launch CTL-difference-between-load-and-start-unload-and-stop
- https://www.launchd.info/
Jupytext 分步指南
towardsdatascience.com](/version-control-with-jupyter-notebook-b9630bc5996e) [## Jupyter 用户的生产力提示
使用 Jupyter 笔记本和 JupyterLab 让您的工作流程更加高效
towardsdatascience.com](/stepping-into-intermediate-with-jupyter-f6647aeb1184) [## 用 Jupyter 笔记本探索正态分布
使用 scipy 和 matplotlib 的正态分布初学者指南
towardsdatascience.com](/exploring-normal-distribution-with-jupyter-notebook-3645ec2d83f8)**
微软新闻推荐竞赛分步指南
微软新闻推荐大赛如何入门
本文作者是吴、易经纬、、应乔、和米盖尔冈萨雷斯-菲耶罗,他们都在微软工作。
介绍
新闻推荐已经成为许多新闻服务的关键机器学习技术,也是数百万人消费新闻时的重要体验。为了促进新闻推荐的公开研究,微软的几个团队最*发布了微软新闻数据集(MIND) ,并发起了微软新闻推荐竞赛。这篇博客文章提供了一个关于为竞赛中的新闻推荐问题开发一个算法,然后提交给竞赛进行评估的演练。这篇文章中描述的代码可以在微软推荐者 Github 知识库中找到。
竞争基准
为了帮助微软新闻推荐竞赛的参与者开始,我们提供了五个基线:深度知识感知网络(DKN)、长期和短期用户表示(LSTUR)、注意力多视图学习(NAML)、个人注意力(NPA)和多头自我注意力(NRMS)。这些模型在 MIND 上的性能在这篇 ACL 论文中进行了评估。在这篇博文中,我们以 NRMS 为例来说明提交过程,所有五个基线的代码都在微软推荐库上。
NRMS
NRMS 是一种基于内容的神经新闻推荐算法。它使用多头自我关注来捕捉单词之间的相关性以学习新闻表示,并捕捉之前点击的新闻文章之间的交互以学习用户表示。它还通过选择重要的单词和新闻,使用附加注意力来学习信息性新闻和用户表示,如下图所示。
关于算法的细节可以在本文中找到,核心的 NRMS 算法可以在这里找到。
NRMS 算法的体系结构
代码示例
我们提供了一本 Jupyter 笔记本来帮助参赛者开始学习 NRMS 算法。在笔记本中,首先下载思维数据集。为了训练 NRMS 模型,应该从竞争*台复制原始数据集。代码示例中的实用函数使这一步变得很方便。应该注意的是,用于比赛的数据集是“MINDlarge”集。建议先熟悉“MINDdemo”或“MINDsample”数据。
有关培训和评估流程的更多详细信息,请参见笔记本。为了确保结果符合提交要求,预测分数保存在压缩文件夹中以便上传。
服从思维竞赛
提交前应进行注册。关于注册的细节可以在这里找到。发送标题为“头脑大赛报名”的邮件至 mind[at]microsoft.com 并附上您的信息(CodaLab 账号昵称、真实姓名、联系邮箱和所属关系)以及您对微软头脑新闻推荐大赛官方规则的同意(请在邮件中写上“我同意微软头脑新闻推荐大赛官方规则”)。如果提供了完整的所需信息,注册将在一两天内获得批准,并将向参与者发送一封确认电子邮件。
确认电子邮件
一旦参与者的批准完成,就允许提交结果。竞赛分为两个阶段,即开发和测试阶段。在开发阶段,您可以将开发集上的结果提交到 Codalab 系统,以获得官方分数。在测试阶段,我们将发布测试集,您可以在截止日期前将您对它的预测结果提交给 Codalab。
在 CodaLab 上提交需要几个步骤:
- 导航至“参与”。
- 简要描述您的模型(可选)。
模型描述
- 点击“提交”按钮。
- 上传您提交的压缩文件。我们使用在前面步骤中获得的压缩文件夹(参见笔记本),在那里训练 NRMS 模型。
压缩提交
- 等待评估状态变为“已完成”或“未通过”。下图显示了一个成功的提交。除了提交状态,系统还返回从模型评估中生成的分数。
提交结果
如果提交状态为“失败”,您可以单击“查看评分输出日志”,然后单击“查看评分错误日志”来查看调试日志。当评估完成后,您可以决定是否在排行榜上显示您的分数。
在开发阶段,参与者可以在验证集上上传他们的预测,并根据结果调整他们的模型。虽然这种提交不是强制性的,但我们强烈建议您提交,以防您在获得正常评估结果时遇到困难。对于那些不熟悉 CodaLab 的参与者来说,这也是一个有用的实践。
后续步骤
在我们的研究中,NRMS 在思想上超越了其他基线,但仍有可能改进:
- 目前,我们不考虑单词和新闻的位置信息,但它们可能对学习更准确的新闻和用户表示有用。
- 用户通常既有长期偏好,也有短期兴趣。然而,我们的方法只学习短期兴趣,即在当前印象之前从点击的新闻中学习用户表示。通过学习长期用户表征,我们可以将信息整合到多重印象中,从而潜在地获得更好的用户表征。
- 最*,图形神经网络(GNNs)已经被证明在图形数据的学习上是强大的。一个基于用户行为的精心构建的图表可能会达到这个目的。
请注册参加比赛,祝黑客快乐!
参考
1.微软推荐库:【https://github.com/microsoft/recommenders
2.心里话:【https://msnews.github.io/assets/doc/ACL2020_MIND.pdf】T4
3.注意 Azure 开放数据集:https://Azure . Microsoft . com/en-us/services/Open-Datasets/catalog/Microsoft-news-dataset/
Python 中 Web 抓取的分步指南
抓取任何有请求和美丽声音的网页
作为数据科学家,我们总是在寻找新的数据和信息来分析和处理。现在查找数据的一个主要方法是在网上搜索特定的查询。
当我们浏览互联网时,我们会遇到大量的网站,这些网站在浏览器上显示各种数据。如果我们出于某种原因想要将这些数据用于某个项目或 ML 算法,我们可以——但不应该——手动收集这些数据。因此,我们将复制我们想要的部分,并将其粘贴到 doc 或 CSV 文件中。
前 5 个库的概述以及何时使用它们。
towardsdatascience.com](/choose-the-best-python-web-scraping-library-for-your-application-91a68bc81c4f)
不用说,那将是一项相当乏味的任务。这就是为什么大多数数据科学家和开发人员使用代码进行网络搜集。编写代码从一个 100 美元的网页中提取数据比手工操作更容易。
Web 抓取是程序员使用的一种技术,用于在相对较短的时间内自动完成从互联网上查找和提取数据的过程。
说到网络抓取,最重要的问题是,它合法吗?
网络抓取合法吗?
简答,是。
更详细的答案是,在 2020 年 1 月下旬,出于非商业目的收集公共可用数据被宣布为完全合法。
你可能想知道,公开可用是什么意思?
公开可用的信息是任何人都可以在互联网上看到/找到的信息,而不需要特殊访问。因此,维基百科、社交媒体或谷歌搜索结果上的信息都是公开可用数据的例子。
现在,社交媒体有些复杂,因为它有一部分是不公开的,比如当用户将他们的信息设为私有时。在这种情况下,该信息是非法的要被抓取。
最后一点,公开的和有版权的是有区别的。例如,你可以取消 YouTube 的视频标题,但你不能将这些视频用于商业用途,因为它们是受版权保护的。
如何报废 web?
有不同的编程语言可以用来抓取 web,在每种编程语言中,都有不同的库来实现相同的目标。
那么,用什么呢?
在本文中,我将使用 Python 、请求和 BeautifulSoup 从维基百科中删除一些页面。
要从互联网上截取和提取任何信息,你可能需要经历三个阶段:获取 HTML,获得 HTML 树,然后从树中提取信息。
作者图片(使用 Canva 制作)
我们将使用请求库从特定的 URL 获取 HTML 代码。然后,我们将使用 BeautifulSoup 来解析和提取 HTML 树,最后,我们将使用纯 Python 来组织数据。
基本 HTML
在我们开始之前,让我们快速复习一下 HTML 基础知识。HTML 中的一切都是在标签中定义的。最重要的标签是,这意味着后面的文本是 HTML 代码。
在 HTML 中,每个打开的标签都必须关闭。所以,在 HTML 文件的末尾,我们需要一个结束标签
作者图片(使用 Canva 制作)
HTML 中不同的标签意味着不同的东西。使用标签的组合来表示网页。任何包含在开始和结束标签之间的文本被称为内部 HTML 文本。
如果我们有多个具有相同标签的元素,我们可能——实际上,总是——想要以某种方式区分它们。有两种方法可以做到这一点,要么使用类,要么使用 id。id 是唯一的,这意味着两个元素不能有相同的 id。另一方面,类不是。多个元素可以有相同的类。
这里有 10 个你在浏览网页时会经常看到的 HTML 标签。
作者图片(使用 Canva 制作)
基本刮削
太棒了,现在我们知道了基础知识,让我们从小做起,然后逐步积累!
我们的第一步是通过在命令行中键入以下内容来安装 BeautifulSoup。
pip install bs4
为了熟悉抓取基础知识,我们将考虑一个示例 HTML 代码,并学习如何使用 BeautifulSoup 来探索它。
BeautifulSoup 不从网络上获取 HTML,但是它非常擅长从 HTML 字符串中提取信息。
为了在 Python 中使用上述 HTML,我们将它设置为一个字符串,然后使用不同的 BeautifulSoup 来探索它。
注意:如果您正在使用 Jupyter Notebook 来跟踪这篇文章,您可以键入以下命令在笔记本中查看 HTML。
from IPython.core.display import display, HTML
display(HTML(some_html_str))
例如,上面的 HTML 看起来会像这样:
接下来,我们需要将这个 HTML 馈送给 BeautifulSoup,以便生成 HTML 树。HTML 树是 HTML 代码不同层次的表示,它显示了代码的层次结构。
上面代码的 HTML 树是:
图片由作者提供(使用 Canva 制作)
为了生成树,我们编写
some_html_str = """
<HTML>
<HEAD>
<TITLE>My cool title</TITLE>
</HEAD><BODY>
<H1>This is a Header</H1>
<ul id="list" class="coolList">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
</BODY>
</HTML>
"""
#Feed the HTML to BeautifulSoup
soup = bs(some_html_str)
变量soup
现在有了从 HTML 字符串中提取的信息。我们可以使用这个变量从 HTML 树中获取信息。
BeautifulSoup 有许多函数可以用来提取 HTML 字符串的特定方面。不过,两个函数用得最多:find
和find_all.
作者图片(使用 Canva 制作)
函数find
只返回搜索查询的第一个匹配项,而find_all
返回所有匹配项的列表。
比方说,我们正在搜索代码中的所有
头。
如你所见,find
函数给了我< h1 >标签。标签什么的。通常,我们只想提取内部的 HTML 文本。为此,我们使用.text
。
这仅仅是因为我们只有一个
标签。但是如果我们想寻找列表项呢——在我们的例子中,我们有一个包含三项的无序列表——我们不能使用find
。如果我们这样做,我们只会得到第一项。
为了找到所有的列表项,我们需要使用find_all
。
好了,现在我们有了一个项目列表,让我们回答两个问题:
1-如何获取列表项的内部 HTML?
为了只获得内部文本,我们不能使用。文本,因为现在我们有了一个元素列表,而不仅仅是一个。因此,我们需要遍历列表并获取每个列表项的内部 HTML。
2-如果我们在代码中有多个列表怎么办?
如果我们在代码中有不止一个列表——这是通常的情况——我们可以精确地搜索元素。在我们的例子中,列表有 id='list '和 class='coolList '。我们可以通过find_all
或find
函数使用这两个或一个函数来精确获取我们想要的信息。
这里需要注意的一点是find
或find_all
函数的返回是漂亮的一组对象,它们可以被进一步遍历。因此,我们可以像直接从 HTML 字符串中获取对象一样对待它们。
本节的完整代码:
我们可以使用其他漂亮的组函数遍历 HTML 树,比如children
、parent
、next
等。
作者图片(使用 Canva 制作)
抓取一个网页
让我们考虑一个更现实的例子,我们从一个 URL 获取 HTML,然后使用 BeautifulSoup 提取模式和数据。
我们将从获取一个网页开始。我喜欢咖啡,所以让我们试着通过咖啡生产获取列出国家的维基百科页面,然后使用 Pygal 绘制这些国家。
[## 用 Pygal 实现 Python 中的交互式数据可视化
一步一步的教程,创造惊人的可视化
towardsdatascience.com](/interactive-data-visualization-in-python-with-pygal-4696fccc8c96)
为了获取 HTML,我们将使用请求库,然后将获取的 HTML 传递给 BeautifulSoup。
如果我们打开这个 wiki 页面,我们会发现一个大表格,上面有各个国家和不同的咖啡产量指标。我们只想提取国家名称和咖啡产量吨。
为了提取这些信息,我们需要研究页面的 HTML,以知道要查询什么。我们可以只突出显示一个国家名称,右键单击,然后选择检查。
通过检查页面,我们可以看到国家名称和数量都包含在“table”标签中。由于它是页面上的第一个表,我们可以使用find
函数来提取它。
然而,直接提取表格会给我们所有的表格内容,包括表头(表格的第一行)和不同度量的数量。
所以,我们需要微调我们的搜索。让我们与排名前 10 的国家一起尝试一下。
注意,为了清理结果,我使用了字符串操作来提取我想要的信息。
关于 Python 中格式化字符串的五种方法,您只需要知道
towardsdatascience.com](/a-guide-to-everything-string-formatting-in-python-e724f101eac5)
我可以使用这个列表最终用 Pygal 绘制出前 10 个国家。
十大咖啡生产国
本节的完整代码:
抓取多个网页
哇,太多了!😃
但是,我们还没有写代码,碎片不同的网页。
在这一部分,我们将删除维基页面上的有史以来最好的 100 本书,然后我们将根据它们的类型对这些书进行分类。试着看看我们是否能找到流派和列表之间的关系——哪种流派表现得最好。
维基页面包含了这 100 本书的链接以及它们的作者。我们希望我们的代码导航列表,进入图书 wiki 页面,提取诸如流派、名称、作者和出版年份等信息,然后将这些信息存储在 Python 字典中——您也可以将数据存储在 Pandas 框架中。
因此,要做到这一点,我们需要几个步骤:
- 获取主 URL HTML 代码。
- 将 HTML 输入 BeautifulSoup。
- 从列表中提取每本书,并获得每本书的 wiki 链接。
- 获取每本书的数据。
- 获取所有书籍数据,整理并绘制最终结果。
让我们开始吧…
步骤#1:获取主 URL HTML 代码
url = '[https://en.wikipedia.org/wiki/Time%27s_List_of_the_100_Best_Novels'](https://en.wikipedia.org/wiki/Time%27s_List_of_the_100_Best_Novels')
page = rq.get(url).text
第二步:将 HTML 输入到 BeautifulSoup
soup = bs(page)
步骤#3:从列表中提取每本书,并获得每本书的维基链接
rows = soup.find('table').find_all('tr')[1:]
books_links = [row.find('a')['href'] for row in rows]
base_url = '[https://en.wikipedia.org'](https://en.wikipedia.org')
books_urls = [base_url + link for link in books_links]
步骤#4:获取每本书的数据
这是最漫长也是最重要的一步。我们首先只考虑一本书,假设它是列表中的第一本书。如果我们打开这本书的 wiki 页面,我们会在屏幕右侧的表格中看到这本书的不同信息。
浏览 HTML,我们可以看到所有的东西都存储在哪里。
为了使事情变得更容易和更有效,我编写了自定义函数来从该书的 wiki 中提取不同的信息。
现在,我们有了这些很酷的函数,让我们写一个函数来使用这些函数,这将帮助我们实现自动化。
在这个函数中,我使用了 try..除了格式,以避免崩溃,如果书的一些信息丢失。
步骤#5:获取所有书籍数据,清理并绘制最终结果
我们已经拥有了自动化代码并运行它所需的一切。
最后要注意的一件事:废弃维基百科是合法的,然而,他们不喜欢你每秒废弃一页以上。因此,我们需要在每次获取之间添加暂停,以避免破坏服务器。
数据收集完毕!这需要 100 秒才能完成,所以在你等待的时候,请随意做些别的事情😉
最后,让我们清理数据,获得流派计数,并绘制结果。
我们完了。
我不得不说,收集数据并不总是 100%准确,正如你在图中看到的,最长的柱属于“无”值。这意味着两件事之一
- 要么是维基页面没有包括这本书的类型。
- 或者,这本书的代码与其他书不同。
这就是为什么在自动化数据收集后,我们经常检查奇怪和不寻常的结果,并手动重新检查它们。
结论
网络搜集是数据科学家需要的基本技能之一。没有比使用 Python、Requests 和 BeautifulSoup 更简单的了。
我们永远不能相信完全自动化,有时我们需要手动检查最终结果,重新检查异常信息。
图书部分的完整代码:
Python 中群组分析的分步介绍
来源: Unsplash
学习如何进行群组分析,以更好地了解顾客的行为
群组分析是一种非常有用且相对简单的技术,有助于获得关于任何企业客户/用户行为的有价值的见解。为了进行分析,我们可以关注不同的指标(取决于业务模式)——转化率、留存率、产生的收入等。
在本文中,我提供了群组分析的简要理论介绍,并展示了如何在 Python 中实现它。
队列分析导论
让我们从基础开始。一个群组是一群有共同之处的人,比如某个 app 的注册日期,第一次购买的月份,地理位置,获取渠道(有机用户,来自效果营销等。)等等。在群组分析中,我们随着时间的推移跟踪这些用户群,以识别一些共同的模式或行为。
在进行群组分析时,考虑我们正在跟踪的指标和业务模式之间的关系至关重要。根据公司的目标,我们可以关注用户保留率、转换率(注册付费版本的服务)、产生的收入等。
在本文中,我将讨论用户保持的情况。通过了解用户保持率,我们可以推断客户的粘性/忠诚度,并评估业务的健康状况。重要的是要记住,不同企业之间的预期保留值差异很大,一年购买 3 次对一个零售商来说可能很多,而对另一个零售商来说可能太少。
留住客户对任何企业都至关重要,因为留住现有客户(通过使用 CRM 工具、会员折扣等)要便宜得多。)而不是获得新的。
此外,群组分析还可以帮助观察产品变化对用户行为的影响,无论是设计变化还是全新的功能。通过观察这些群体在一段时间内的行为,我们可以或多或少地观察到我们的努力是否对用户产生了一些影响。
现在这应该是足够的理论了,让我们来看看现实生活中的例子。
设置
在本文中,我们将使用以下库:
数据集
我们将使用从 UCI 机器学习库下载的数据集,该库是不同种类数据集的绝佳来源。它们已经根据可用于机器学习的领域进行了标记:
- 监督(回归/分类),
- 无监督(聚类)。
你可以在这里找到数据集。或者,您可以使用以下代码行直接从 Jupyter 笔记本下载数据:
!wget [https://archive.ics.uci.edu/ml/machine-learning-databases/00352/Online%20Retail.xlsx](https://archive.ics.uci.edu/ml/machine-learning-databases/00352/Online%20Retail.xlsx)
该数据集可以简单描述为:“这是一个跨国数据集,包含了一家总部位于英国的注册无店铺在线零售商在 2010 年 1 月 12 日至 2011 年 9 月 12 日之间发生的所有交易。该公司主要销售独特的适合各种场合的礼品。公司的很多客户都是批发商。”
接下来,我们从 Excel 文件中加载数据。
加载的数据如下所示:
我们还使用df.info()
检查了数据帧,看看是否有丢失的值。至于分析,由于我们需要客户 id,我们删除了所有没有客户 id 的行。
df.dropna(subset=['CustomerID'], inplace=True)
为了完整起见,我们还做了一个非常快速的 EDA,重点是用户。EDA 始终是任何分析的一个非常重要的步骤,因为我们会发现我们正在处理的数据集的细节。
我们首先检查数字变量的分布——数量和单价。
df.describe().transpose()
从上表中,我们可以看到存在数量为负的订单,这很可能是退货。总的来说,大约有 9000 个负数量的采购。我们将它们从数据集中移除。这就引入了一种偏差,因为我们包含了初始订单并删除了退货,这样初始订单就被考虑在内,即使理论上它没有实现也没有产生收入。但是,为了简单起见,我们保留初始订单,至于保留率(表示客户参与度)等指标,这仍然是一个有效的假设。
然后,我们计算一个聚合指标,表明每个客户下了多少订单。
使用上面的代码,我们可以得出 65.57%的客户订购了不止一次。这已经是一条有价值的信息,因为客户似乎下了多个订单。这意味着至少会有一些保留。鉴于数据集没有注册/加入日期,如果大多数用户只下了一个订单,这将是有问题的,但我们稍后将回到这个问题。
此外,我们查看每个客户订单数量的分布。为此,我们可以重用之前聚合的数据(n_orders
)并将数据绘制在直方图上。
运行代码会生成以下图形:
有一些不常见的客户案例,他们订购了 50 次以上。
断代分析
我们在本例中使用的数据集不包含客户注册日期,即他们向零售商注册的日期。这就是为什么我们假设他们所属的群组是基于第一次购买日期的。这种方法的一个可能的缺点是,数据集不包含过去的数据,我们在这个快照(2010 年 1 月 12 日至 2011 年 9 月 12 日之间)中已经看到的数据包括重复出现的客户。换句话说,我们在这个数据集中看到的第一次购买可能不是给定客户的实际第一次购买。但是,如果不能访问零售商的整个历史数据集,就无法对此做出解释。
第一步,我们只保留相关的列并删除重复的值——一个订单(由InvoiceNo
表示)可以包含多个项目(由StockCode
表示)。
第二步,我们创建cohort
和order_month
变量。第一个指示基于第一次购买日期的每月群组(按客户计算)。后一个是购买日期的截断月份。
然后,我们根据cohort
和order_month
汇总数据,并计算每组中独立客户的数量。此外,我们添加了period_number
,它指示群组月份和购买月份之间的周期数。
下一步是以这样一种方式透视df_cohort
表,即每行包含关于给定群组的信息,每列包含某个时间段的值。
为了获得保留矩阵,我们需要将每行的值除以该行的第一个值,这实际上是群组大小——在给定月份中第一次购买的所有客户。
最后,我们将保留矩阵绘制成热图。此外,我们希望包括关于队列规模的额外信息。这就是为什么我们实际上创建了两个热图,其中一个指示群组大小的热图使用的是纯白色的色图——没有任何颜色。
最终结果是以下保留矩阵:
在图中,我们可以看到在第二个月(指数为 1)已经出现了大幅下降,*均约 80%的客户在第二个月没有进行任何购买。第一组(2010-12)似乎是个例外,与其他组相比,表现出人意料地好。第一次购买一年后,有 50%的保留。这可能是一群忠诚的顾客,他们最初加入*台是基于与零售商已经存在的一些联系。然而,仅从数据来看,这很难准确解释。
在整个矩阵中,我们可以看到保留时间的波动。这可能是由业务的特点造成的,客户会定期购买,随后会有一段时间不活动。
结论
在本文中,我展示了如何使用 Python 的pandas
和seaborn
进行群组分析。在路上,我做了一些简化的假设,但这主要是由于数据集的性质。当在一个公司的真实场景中工作时,我们会对业务有更多的了解,并能从分析中得出更好、更有意义的结论。
你可以在我的 GitHub 上找到本文使用的代码。一如既往,我们欢迎任何建设性的反馈。你可以在推特或评论中联系我。
喜欢这篇文章吗?成为一个媒介成员,通过无限制的阅读继续学习。如果你使用这个链接成为会员,你将支持我,不需要额外的费用。提前感谢,再见!
我最*出版了一本关于使用 Python 解决金融领域实际任务的书。如果你有兴趣,我贴了一篇文章介绍这本书的内容。你可以在亚马逊或者 Packt 的网站上买到这本书。
Giraffle 的逐步介绍
如何以编程方式在 TigerGraph 上创建图形
照片来自 Unsplash 由 Charl Durand 拍摄
为什么要用长颈鹿?
Giraffle 由 Joshua Meekhof 创建,是一种在 TigerGraph 中以编程方式创建图形的方法。当与许多团队成员一起处理一个图表项目时,将我们的图表写在代码中会使协作更容易。此外,在协作空间中,如果有人不小心丢失了全部或部分数据,您的模式和查询都会被保存并可重用。总的来说,通过以编程方式创建图形,Giraffle 可以帮助简化与 TigerGraph 中的图形的协作。
开始的步骤
在这篇博客中,我们将讨论:
- 在 TigerGraph 上创建解决方案
- 设置 Giraffle
- 创建模式
- 加载数据
- 创建查询
到这篇博客结束时,你将知道足够用 Giraffle 创建你自己的项目!如果你遇到困难或困惑,GitHub 链接在博客的最后,供你参考。
另外, Jon Herke 创建了一个博客来帮助 Giraffle 入门,而 Ramki Pitchala 写了一个关于迁移到 Giraffle 的博客。我强烈建议你也去看看那些博客!
步骤 1:在 TigerGraph 上创建一个解决方案
首先,我们需要在 TigerGraph 上运行一个解决方案。你需要去 TigerGraph Cloud 。如果您还没有帐户,请创建一个。另一方面,请访问解决方案。
点击我的解决方案(图片由作者提供)
接下来,点击右上角的Create Solution
。
创建解决方案
点击第一部分的空白。
(图片由作者提供)
不要更改第二部分的任何内容,只需点击Next
。
在第三部分中,您可以对其进行命名、标记、添加密码、创建子域以及添加描述。其中,确保你记得你的密码和子域。
键入名称、解决方案、密码、子域和描述。(图片由作者提供)
请注意,每个子域必须是唯一的。因此,你可能会或可能不会得到子域blog
。
单击下一步,然后提交。接下来你需要等待它,因为它可能需要几分钟来加载。加载后,通过按 Solution Operations(蓝框)和 start 来启动您的解决方案。加载可能需要一段时间
按下蓝框,开始。(图片由作者提供)
恭喜你。现在,您的解决方案已经开始运行了!
步骤 2:设置 Giraffle
首先,确保你已经在电脑上安装了 gradle。您可以使用命令gradle
检查您是否已经升级。然后,键入以下命令:
gradle init
在接下来的两个选项中,键入 1 和 2。你可以给这个项目起任何你喜欢的名字。
键入 1(基本),然后键入 2 (Kotlin)(图片由作者提供)
您将看到您将在目录中获得几个文件夹。
创建的文件夹(图片由作者提供)
从这里,去build.gradle.kts
。将其更新为:
import com.optum.giraffle.tasks.*
import com.optum.giraffle.*
plugins {
id("com.optum.giraffle") version **"1.3.4.1"**
id("net.saliman.properties") version "1.5.1"
}
repositories {
jcenter()
}
请注意 1.3.4.1,因为这是最新版本!没有正确的版本,您的代码可能会生成,也可能不会生成。
如果gradle build
跑成功了,你就厉害了!接下来,在您的终端中,记住第一步中的子域,键入:
gradle gsqlNewProject --console=plain
按照步骤,填写子域等。
我的图是 GiraffleBlog,我的子域是 blog.i.tgcloud.io。我使用默认的用户名和密码。最后,我没有使用多种环境,而是使用 Kotlin。(图片由作者提供)
接下来,我们需要创建一个证书。要生成一个,请使用以下命令:
openssl s_client -connect SUBDOMAIN.i.tgcloud.io:14240 < /dev/null 2> /dev/null | openssl x509 -text > cert.txt
对我来说,应该是:
openssl s_client -connect blog.i.tgcloud.io:14240 < /dev/null 2> /dev/null | openssl x509 -text > cert.txt
如果所有运行都没有错误,那么您已经完成了存储库的设置。现在你应该可以开始开发了!
步骤 3:创建一个模式
您首先需要创建一个模式。一个模式就像一个地图,显示了图形将会有什么。在db_scripts/schema
中,创建schema.gsql
。
在该文件中,我将在这里创建一个非常基本的模式:
CREATE VERTEX Blog(primary_id title STRING) WITH primary_id_as_attribute="true"CREATE VERTEX Person(primary_id name STRING) WITH primary_id_as_attribute="true"CREATE UNDIRECTED EDGE BLOG_CREATOR(FROM Blog, TO Person) CREATE GRAPH @graphname@(Blog, Person, BLOG_CREATOR)
我们有两个顶点叫做 Blog 和 Person,它们通过一条叫做“BLOG_CREATOR”的边连接在一起。
将您的build.gradle.kts
更新为:
这是我们将要构建的构建函数的模板。
我们来破解密码。本文档提供了供您运行的任务。例如:
register<GsqlTask>("createSchema") {
scriptPath = "schema/schema.gsql" // Where the schema is
useGlobal = true
group = schemaGroup // The group the task is associated with
description = "Runs gsql to create a schema" // Description of the task
}
对于createSchema
,如果您以任何不同的方式命名您的模式文件,您可以更改脚本路径。然后它有一个描述和一个组。它应该可以编译,但是,为了仔细检查,您可以运行gradle tasks
。
接下来,我们将更新我们的gradle-local.properties
。将文件更新为以下内容(填写您的详细信息):
gHost=SUBDOMAIN.i.tgcloud.iogAdminUserName=INSERT_YOUR_ADMIN_USERNAMEgAdminPassword=INSERT_YOUR_ADMIN_PASSWORDgUserName=INSERT_YOUR_USERNAMEgPassword=INSERT_YOUR_PASSWORDgGraphName=GRAPH_NAMEgCertPath=cert.txtgHostUriType=httpsgRestPort=9000
(注意:如果您完全按照说明进行,用户名/密码的默认值是 tigergraph。如果您自定义设置了用户名或密码,请将其更改为您的用户名和密码。将第一步中的子域插入 gHost。gGraphName 是您希望图形使用的名称。)
接下来,我们将把我们的模式上传到云中。为此,请前往https://tgcloud.io/app/solutions。点按“应用程序”(带有四个形状的蓝色按钮),然后点按“GraphStudio”。
按下应用程序按钮,然后单击 GraphStudio 启动它。(图片由作者提供)
现在,回到您的终端,我们将使用我们添加的 createSchema 命令。键入:
gradle createSchema
您应该得到一个显示成功的输出。如果出现任何其他错误,可能是出了问题。(图片由作者提供)
如果它工作,你的输出应该像上面一样。最后,如果您转到 GraphStudio 并点击 Design Schema,您应该能够看到您的模式。
Graph Studio 中的模式(图片由作者提供)
恭喜你!您已经创建并加载了您的模式!
步骤 4:加载数据
接下来,我们将把实际数据加载到图表中。我将创建一个充满作者姓名和博客的 CSV。
在主目录下创建一个名为data
的文件夹(应该和db_scripts
在同一层,但不在里面。在data
文件夹中,创建data.csv
,并添加以下数据:
AUTHOR,TITLE"John Smith", "Cool Things to do in Paris""Jack Paul", "101 Best Tourist Spots""Alice Walker", "101 Best Tourist Spots""Blake Coles", "Lessons Learned from a Dog""Amelia-Rose Kim", "Cool New Places""Taha Wardle", "An Awesome Guide to Awesomeness""Bella Bloom", "Cool Things to do in Paris""Nakita Talbot", "Why Learn French?""Kaison Reilly", "Why Learn Spanish?""Philippa Palacios", "Five Habits of Successful People""Pawel Medrano", "101 Best Tourist Spots""Jasper Franklin", "Cool New Places""Abid Little", "How to Love Yourself""John Smith", "Cool Things to do in Lorraine""Alice Walker", "Five Habits of Successful People"
接下来,在db_scripts/load
中,创建一个名为loadData.gsql
的新文件。在该文件中,添加以下代码:
drop job loadData // deletes past load job called loadDatacreate loading job loadData for graph @graphname@ { // creating a load job called loadData define filename f1; // set the file load f1 // loads the file to vertex Blog values($1), // loads data from the 2nd column in the CSV to the vertex Blog to vertex Person values($0), // loads data from the 1st vertex to vertex Person to edge CREATOR values($1, $0) // connects all data from the 2nd column with the data from the 1st column using header="false", separator=","; // Comma separator, not using headers}
为此,我们创建了一个名为loadData
的加载作业。如果您想创建更多的加载作业,将其他文件添加到db_scripts/load
,并用您的加载作业名称替换loadData
。
接下来,在您的build.gradle.kts
中,在tasks {
下,添加
register<GsqlTask>("createLoadData"){ scriptPath = "load/loadData.gsql" // Call the file you have the load job in. group = loadingGroup description = "Loads our data"}register<HttpTask>("loadData") { group = loadingGroup description = "Load data via the REST++ endpoint" post { httpConfig -> httpConfig.request.uri.setPath("/ddl/${gGraphName}") httpConfig.request.uri.setQuery( mapOf( "tag" to "loadData", "filename" to "f1", "sep" to ",", "eol" to "\n" ) ) httpConfig.request.setContentType("text/csv") val stream = File("data/data.csv").inputStream() // If your data file was called anything else, you can change the File(""). httpConfig.request.setBody(stream) }}
这里,我们创建两个任务:一个创建或“构建”文件,另一个将数据加载到图表中。
在将我们的更改加载到图表之前,我们需要生成一个秘密。进入 GraphStudio 并点击右上角的Admin
按钮。点击后,点击左侧栏中的User Management
。
你应该在这里结束。(图片由作者提供)
最后,在标有 Create Secret 的框下,点击橙色的Create
按钮并复制密码。
在gradle-local.properties
中,添加一个新字段:
gSecret=SECRET_YOU_COPIED
要运行,只需:
gradle createLoadData
gradle loadData
您的终端输出应该如下所示。(图片由作者提供)
最后可以去 Graph Studio。转到Load Data
以确保所有东西都已装载。
注意右边顶点和边的数字。因为它们不全是 0,我们的数据加载!(图片由作者提供)
接下来去Explore Graph
看看数据。您可以选取几个顶点并双击它们,以探索与其连接的其他顶点。
探索图表的一些结果(图片由作者提供)
步骤 5:创建查询
最后,我们可以使用查询来分析数据。在db_scripts/queries
中,用以下内容创建一个名为selectAll.gsql
的文件:
drop query selectAllcreate query selectAll (STRING auth) for graph @graphname@ { ListAccum<EDGE> @@edgelist; People = {Person.*}; author = select s
FROM People:s -() -:t
where s.name == auth; blogs = select c
from People:s -(BLOG_CREATOR:e) -Blog:c
where s.name == auth ACCUM @@edgelist+=e;
print author; print blogs; PRINT @@edgelist;}install query selectAll
接下来,在与加载任务相同的区域中,您需要为build.gradle.kts
(在tasks
部分中)中的查询添加一个任务。您应该添加以下内容:
register<GsqlTask>("createQuerySelectAll") { scriptPath = "query/selectAll.gsql" group = queryGroup description = "Creates a select all"}
最后,要将查询推送到解决方案,运行:
gradle createQuerySelectAll
转到 GraphStudio,转到查询,您应该会找到 selectAll。
注意左上角附*的 selectAll。(图片由作者提供)
您可以单击 selectAll,按顶部的 play 按钮,然后它将运行查询并接收参数。现在,您可以运行自己的查询了!
接受查询的名称(图片由作者提供)
第六步:创建你自己的项目!
恭喜你!您现在知道了如何用 Giraffle 以编程方式创建图形。现在,您可以开始为自己的项目建模和查询数据了。祝你好运!
额外资源
- 博客回购:https://github.com/GenericP3rson/GiraffleBlog
- TigerGraph 不和谐(如有问题):https://discord.com/invite/F2c9b9v
对 PCA 的逐步介绍
关于如何使用 python 对数据集应用主成分分析的指南
鸢尾花。图片由 S. Hermann & F. Richter 从 Pixabay 拍摄。
在本文中,我将讲述如何解决对高维数据集(即每个样本都有大量测量值的数据集)进行可视化、分析和建模的问题。对于这种类型的数据集,很难确定要素之间的关系,也很难可视化它们之间的关系。将模型应用于高维数据集时,通常会导致过拟合,即不在训练集中的样本性能较差。
我今天要讨论的方法是一种无监督的降维技术,称为主成分分析,简称 PCA。在这篇文章中,我将讨论执行 PCA 的步骤。我还将使用 python 演示数据集上的 PCA。你可以在这里找到完整的代码脚本。执行 PCA 的步骤如下:
- 将数据标准化。
- 从数据集中计算要素的协方差矩阵。
- 对协方差矩阵执行特征分解。
- 根据相应特征值的大小,按降序对特征向量进行排序。
- 确定 k,即要选择的顶部主成分的数量。
- 从所选数量的顶部主成分构建投影矩阵。
- 计算新的 k 维特征空间。
选择数据集
为了使用示例演示 PCA,我们必须首先选择一个数据集。我选择的数据集是 Fisher 收集的虹膜数据集。
该数据集由来自三种不同类型鸢尾的 150 个样本组成:刚毛鸢尾、杂色鸢尾和海滨鸢尾。对于每个样本,数据集有四个测量值。这些测量值是萼片长度、萼片宽度、花瓣长度和花瓣宽度。为了访问这个数据集,我们将从 sklearn 库导入它:
from sklearn.datasets import load_iris
现在数据集已经导入,可以通过执行以下操作将其加载到数据框中:
iris = load_iris()
colors = ["blue", "red", "green"]
df = DataFrame(
data=np.c_[iris["data"], iris["target"]], columns=iris["feature_names"] + ["target"]
)
既然数据集已经加载,我们可以像这样显示一些样本:
使用 df.sample 从数据集中选择一些样本(n=5)。
箱线图是可视化数据分布的好方法。可以使用以下方法创建一组箱线图:
df.boxplot(by="target", layout=(2, 2), figsize=(10, 10))
这给出了:
箱线图显示每种类型虹膜的每次测量值的分布。
箱线图向我们展示了许多细节,比如弗吉尼亚的花瓣长度中值最大。我们将在本文的后面回到这些箱线图。
使数据标准化
既然数据集已经加载,就必须为降维做准备。当所有特征都在同一尺度上时,大多数机器学习和优化算法的性能会更好。为了做到这一点,可以实施标准化方法。通过使用以下计算,特征值 xⁱ可以变成标准化的特征值 xⁱₛ:
其中,μₓ是特征列的*均值,σₓ是相应的样本方差。这导致特征值具有*均值 0 和标准偏差 1,因此具有与正态分布相同的参数。例如,对于具有从 0 到 5 的值的特征列,应用标准化将产生以下新值:
值从 0 到 5 被标准化的特征列的示例。
就我们的数据集而言,虹膜特征的标准化可以使用 sklearn 实现,如下所示:
X = StandardScaler().fit_transform(X)
计算协方差矩阵
协方差衡量两个要素之间的差异。正协方差表示要素同时增加和减少。反之,负协方差表示两个特征的变化方向相反。对于两个特征向量 xⱼ和 xₖ,它们之间的协方差σⱼₖ可以使用下面的等式来计算:
协方差矩阵包含要素之间的协方差值,形状为 d × d。因此,对于我们的数据集,协方差矩阵应如下所示:
由于特征列已被标准化,因此它们各自的均值为零,协方差矩阵σ可通过以下公式计算:
其中 Xᵗ是 x 的转置。如果你需要矩阵乘法如何工作的提示,这里的是一个很好的链接。
这可以用 python 实现,如下所示:
cov = (X.T @ X) / (X.shape[0] - 1)
执行特征分解
特征向量代表协方差矩阵的主要分量(最大方差的方向)。特征值是它们相应的大小。具有最大相应特征值的特征向量代表最大方差的方向。特征向量 v 满足以下条件:
其中λ是一个标量,称为特征值。手动计算是相当复杂的,可能是一个帖子本身。然而,如果你想知道更多,我推荐你看看这个视频。相反,我将使用 python 中的特征分解函数:
eig_values, eig_vectors = np.linalg.eig(cov)
这给出了协方差矩阵的特征向量(主分量)和特征值。
确定选择哪些主成分
既然已经计算了特征对,现在需要根据它们的特征值的大小对它们进行排序。这可以在 python 中通过执行以下操作来完成:
idx = np.argsort(eig_values, axis=0)[::-1]
sorted_eig_vectors = eig_vectors[:, idx]
既然已经根据主成分对应特征值的大小对主成分进行了排序,那么是时候决定选择多少主成分进行降维了。这可以通过绘制特征值的累积和来实现。累积和的计算方法如下:
上述公式可以计算并绘制如下:
cumsum = np.cumsum(eig_values[idx]) / np.sum(eig_values[idx])
xint = range(1, len(cumsum) + 1)
plt.plot(xint, cumsum)
plt.xlabel("Number of components")
plt.ylabel("Cumulative explained variance")
plt.xticks(xint)
plt.xlim(1, 4, 1)
该图显示了以下内容:
显示特征值累积和的图。
从图中,我们可以看到,超过 95%的方差包含在两个最大的主成分中。因此,选择前两个最大的主成分构成投影矩阵 w 是可以接受的。
计算转换
既然已经决定了有多少个主分量构成投影矩阵 W,则得分 Z 可以计算如下:
这可以在 python 中通过执行以下操作来计算:
eig_scores = np.dot(X, sorted_eig_vectors[:, :2])
绘制结果
现在数据集已经被投影到一个新的更低维度的子空间上,结果可以如下绘制:
def biplot(score, coeff, labels):
xs = score[:, 0]
ys = score[:, 1]
n = coeff.shape[0]
for i, u in enumerate(iris["target_names"]):
xi = [
score[j, 0] for j in range(score.shape[0]) if df["target"].tolist()[j] == u
]
yi = [
score[j, 1] for j in range(score.shape[0]) if df["target"].tolist()[j] == u
]
plt.scatter(xi, yi, c=colors[i], label=u)
for i in range(n):
plt.arrow(
0, 0, coeff[i, 0], coeff[i, 1], color="r", head_width=0.05, head_length=0.1
)
plt.text(
coeff[i, 0] * 1.35,
coeff[i, 1] * 1.35,
labels[i],
color="g",
ha="center",
va="center",
)
plt.xlabel("PC{}".format(1))
plt.ylabel("PC{}".format(2))
plt.grid()
biplot(scores, sorted_eig_vectors, iris["feature_names"])
plt.legend()
这给出了:
绘制在二维特征空间上的虹膜样本。
从图中可以看出,versicolor 和 virignica 样品之间的距离较*,而 setosa 与它们之间的距离较远。如果你还记得上面的双标图,海滨锦鸡儿有最大的*均萼片长度、花瓣长度和花瓣宽度。然而,刚毛藻具有最高的*均萼片宽度。通过跟踪原始特征的轴可以看出这是正确的。
使用奇异值分解(SVD)计算 X 的替代方法
特征分解的一些缺点是计算量大,并且需要一个方阵作为输入。部分由于这些原因,寻找 PCA 的主成分的更流行的方法是使用奇异值分解(SVD)。SVD 将矩阵分解为满足以下条件的三个独立矩阵:
其中 U 是左奇异向量,V*是右奇异向量的复共轭,S 是奇异值。奇异值与从特征分解计算的特征值相关。SVD 的另一个有用特性是奇异值是数量级的,因此不需要重新排序。右奇异向量与通过特征分解得到的特征向量相同,因此 W=V。使用 python,矩阵的 SVD 可以如下计算:
u, s, vh = np.linalg.svd(X)
由此,现在可以计算分数:
svd_scores = np.dot(X, vh.T[:, :2])
从这些分数可以画出双标图,当使用特征分解时,将返回与上面相同的结果。查看代码了解全部细节。
摘要
在这篇文章中,我们讨论了 PCA,以及如何使用它来更清楚地了解数据集特征之间的关系,同时消除不必要的噪声。我们经历了每一步,也讨论了不同的计算方法。我希望这篇文章能对您未来的数据科学工作有所帮助。
原载于 2020 年 4 月 25 日 datasciencesamurai.com。
加入我的邮件列表,了解更多关于数据科学的知识。
处理预测分析问题的一步一步的过程
马库斯·斯皮斯克在 Unsplash 上的照片
W 什么是机器学习项目?什么是真正的预测分析问题陈述?我们该如何解决这个问题?这些问题将在本文中得到解答,一些新颖的问题将会被提出,这将有助于我们更好地理解和更准确地解决问题
基本上,使用一些以前的信息,对未来的预测是机器学习模型的基础。提取信息和生成趋势的过程被称为训练或建模,讲述未来被称为预测。ML 模型包括各种步骤,如探索性数据分析、处理数据、特征工程、训练、预测、模型评估,以及我们如何改进我们的性能。我们将经历创建任何模型的非常基本的结构,并理解基本术语的含义。
数据
通常,我们的数据集是以一个 CSV (逗号分隔文件)或一个 Excel 文件或一个文本文件或图像和声音的形式给出的。
例如, CVS 文件或 Excel 文件有行和列。行基本上是一个观察,列是决定我们目标的特征。对于其他类型,我们需要通过一些规定的方法来提取特征信息,如定义图像包含像素值的三维矩阵,该矩阵可以转换为二维矩阵,用于训练深度学习模型。
但是为了方便起见,让我们考虑一下我们想要预测房价,你认为影响房价的基本因素是什么?(将在文章后面回答)
第一步:问题陈述
非常非常仔细地阅读问题陈述。大多数人和不成功的数据科学家都会犯这个错误。阅读问题是非常关键的一步,因为从中可以提取很多信息。
一旦你读完了,问自己这些基本问题
- 有什么问题?
- 为什么需要解决这个问题
- 怎样才能解决问题?
我发现回答这些问题对于理解这个问题非常重要。我们可以使用有史以来最好的算法来获得最高的准确性,但如果我们解决了错误的问题,这将毫无意义。
这些问题不仅会向我们介绍一个问题,还会帮助我们理解和验证收集的数据,并改进结果。
步骤 2:假设生成
一旦你阅读了问题陈述,是时候利用我们的知识和经验来列出目标变量所依赖的因素了。这是一种头脑风暴。它让我们知道哪些因素是重要的,而哪些不是,这可以在稍后的 EDA 部分中证明。我们在预测房价。那么,它依赖于什么?可能是位置,大小,房子的年龄,房间的数量,中央空调的存在,停车场的可用性,该地区的人口密度,等等。也许房子的颜色也很重要?嗯,这些答案都可以找出来。
人们应该钦佩这一步是多么重要。这个过程是初学者的必经过程。在第一步,这不是准确性,我们的意图应该是成为一个好的数据科学家,而不仅仅是一个问题解决者!
第三步:阅读和理解
阅读你的数据,让自己适应它。阅读你的数据的中心趋势。问问自己什么是连续特征,什么是分类特征,是否有任何缺失值,涉及什么数据类型等。
步骤 4:探索性数据分析(EDA)
有两种类型的可视化分析,即单变量分析和双变量分析,
单变量分析:
它由一次一个特征的可视化组成。这些可以用来了解我们的连续特征是如何分布的,有没有异常值或者缺失值?对于分类特征,我们可以提取每个类别的数量。主要是,直方图和箱线图用于连续特征的情况,而计数图用于分类数据。
双变量分析:
当我们用目标变量来检验每个特征的趋势时,我们称之为双变量分析。数据是如何关联的,每个特征对目标变量的影响是什么,这些都是分析中回答的基本问题。
在对不同的特征、趋势和模式对进行双变量分析时,可以生成缺失值的插补。
对于连续-连续特征,我们使用散点图。它告诉我们特征之间的线性关系有多强。对于连续分类,我们使用 violin 图,因为它们包含了特征的范围和分布。对于分类-分类,我们可以使用在 Pandas 库中预定义的跨表方法。
第五步:特征工程
这是建模过程中最具创造性和决定性的因素。但是由于每一个难题都可以被分解成更小的简单问题,这也可以制定为两个主要部分,即。特征生成和编码。
特征生成是从现有特征生成新特征的过程。例如,给出一个字符串日期特征,可以提取关于年和月的信息。另一个很好的例子是,当预测一个商场的销售额时,价格和重量是可以给出的特征,我们可以生成新的特征,即每单位重量的价格。这有助于我们减少数据的维度,同时保持数据的质量。
在所有上述过程之后,我们的数据集已准备好进行模型构建,但问题是大多数机器学习算法无法读取诸如男性、女性、否、是等分类值。我们使用编码方法将它们转换成数值。这主要涉及标签编码、一键编码、计数编码等
步骤 6:建模和评估
这一步是关于机器学习算法的选择和我们的训练数据对它的拟合。选择算法取决于问题是分类的还是回归的,是有监督的还是无监督的。有各种型号可供选择。
线性算法:
梯度下降,线性回归,逻辑回归,线性判别分析
非线性算法:
分类和回归树,朴素贝叶斯,K *邻,学习矢量量化,支持向量机
集成算法:
装袋和随机森林、Boosting 和 AdaBoost
在使用算法将训练数据拟合到模型之后,我们对新数据进行一些预测,这对于模型来说是新的。
许多算法可以预测,但问题是哪一个是最好的?因此,我们需要评估我们的模型。目前,有各种方法来评估我们的模型,如 MSE、MAE、roc-curve、f1-score、log loss 等等。
Scikit Learn 的备忘单
下面的流程图旨在为用户提供一点粗略的指导,告诉他们如何处理关于使用哪些估计器来处理数据的问题。
来源:Scikit 学习算法备忘单:https://scikit-learn.org/stable/_static/ml_map.png
总结一下:
对于任何问题来说,这都是一个非常基础和幼稚的方法,但是对于初学者来说已经足够好了。一旦你掌握了这些步骤,并对预测建模有所了解,你可以从几个方面着手提高你的技能。
请分享你对这篇文章的看法,我很想听听!
进行情感分析的分步指南
由 Unsplash 上的hkon grim stad拍摄的照片
第 2 部分:用 TFIDF 矢量器转换文本数据
在我的上一篇文章中,我讨论了进行情感分析的第一步,即预处理文本数据。这个过程包括标记化、去除停用词和词条化。在本文中,我将讨论将“干净的”文本数据转换成稀疏矩阵的过程。具体来说,我将通过简单的例子讨论不同矢量器的使用。
在我们进入更多的技术之前,我想介绍两个在文本分析中广泛使用的术语。对于我们想要分析的文本数据集合,我们称之为语料库。一个语料库包含几个观察结果,如新闻文章、顾客评论等。这些观察结果中的每一个都被称为文档。从现在开始我将使用这两个术语。
转换步骤的作用是搭建一座桥梁,连接文本数据中携带的信息和机器学习模型。对于情感分析,要对每个文档进行情感预测,机器学习模型需要学习文档中每个唯一单词的情感得分,以及每个单词在那里出现的次数。例如,如果我们想要对某个产品的客户评论进行情感分析,在训练模型之后,机器学习模型更有可能从负面评论中提取像“糟糕”、“不满意”这样的词,而从正面评论中获得像“棒极了”、“棒极了”这样的词。
面对有监督的机器学习问题,为了训练模型,我们需要指定特征和目标值。情感分析是在解决一个分类问题,大多数情况下是一个二元分类问题,目标值定义为正和负。用于模型的特征是来自矢量器的转换的文本数据。不同的矢量器构造的特征也不同。在 Scikit Learn 中,有三个矢量器,CountVectorizer、TFIDFVectorizer 和 HashingVectorizer。我们先来讨论一下 CountVectorizer。
计数矢量器
CountVectorizer 使用单词包方法,该方法忽略文本结构,只从单词计数中提取信息。它会将每个文档转换成一个向量。向量的输入是这个文档中每个唯一单词的出现次数。当语料库中有 m 个文档,并且所有 m 个文档中有 n 个唯一单词时,CountVectorizer 会将文本数据转换为 m*n 稀疏矩阵。以下示例显示了计数矢量器的用法:
CountVectorizer 获取文档列表,并通过两步生成稀疏矩阵:拟合和转换。在拟合过程中,矢量器读入文档列表,计算语料库中唯一单词的数量,并为每个单词分配一个索引。对于上面的例子,我们可以看到这两个文档有六个不同的单词,我们根据字母顺序给它们分配了一个索引。请注意,您可以在这里指定停用字词来排除无用的字词。您可以使用默认列表,也可以自定义列表。或者如果已经对文本数据进行了预处理,就可以通过这一步。
下一步是转换拟合的数据。CountVectorizer 将计算每个文档中每个唯一单词的出现次数。这里我有两个文档和六个唯一的单词,因此我们将得到一个如上所示的 2*6 矩阵。为了更好地理解矩阵的元素,这里我有一个图表:
这里,行 id 与每个文档相对应,列 id 在匹配过程中跟随唯一单词的索引。例如,单词“day”在两个文档中都出现了,所以第一列输入是(1,1)。如果某个单词没有出现在文档中,则该单词在该文档行中的输入将为 0。随着文档数量的增加,矩阵变成稀疏矩阵,因为矩阵中会有更多的 0。
tfidf 矢量器
另一个更广泛使用的矢量器是 TFIDFVectorizer,TFIDF 是术语频率,逆文档频率的缩写。除了每个文档中的字数,TFIDF 还包括该单词在其他文档中的出现次数。具体来说,TFIDF 的计算公式如下:
其中 t_i,wj 是单词 wj 在文档 I 中出现的频率。通过检查等式,可以清楚地看到,第一项是计算术语频率,第二项是计算逆文档频率。第一项是评估单词 wj 在文档 I 中出现了多少次,用文档 I 的长度归一化。较高的词频率指示较高的 TFIDF 值,表明单词 wj 通过出现显著的次数而在文档 I 中扮演非常重要的角色。但是如果 wj 也出现在 I 之外的很多其他文档中,wj 的作用就会减弱,也就是说它是这个题目的常用词。这个过程被第二项捕获,第二项是 wj 出现的文档数除以文档总数的倒数。综合两种效果,文档 I 中 TFIDF 值高的一个词 wj,意味着 wj 在文档 I 中出现多次,在其他文档中只出现很少。
使用前一个示例的 TFIDF,区别如下:
我们可以看到每个元素的值都变小了,但是矩阵的形状还是一样的。
哈希矢量器
另一种常用的矢量器叫做哈希矢量器。它通常在处理大型数据集时使用。使用特征散列,散列矢量器是内存高效的,并确保大型数据集的更好的模型性能。在这篇文章里我不会讲太多细节,但是你可以在这里查阅更多信息。
附加功能输入
除了指定和定制停用词,我们还可以定制矢量器中的标记化功能。正如我在上一篇文章中所讨论的,在这里包含定制的 tokenize 函数会减慢矢量化过程。
在前面的例子中,我们正在构建只有单个单词的稀疏矩阵,我们可以通过包含二元模型来增加特征的数量。我们可以通过在函数中添加 ngram_range 来在函数中指定它。这里有一个例子:
通过包含 bigram,特性的数量从 6 个增加到 11 个。有时,当我们在文档中有“不错”这样的词时,包含 bigram 会提高模型性能。
您还可以在矢量函数中指定 min_df 和 max_df 。通过指定一个单词在不同的文档中出现多少次才能被认为是一个特征,我们过滤掉在语料库中不太常见的单词。此外,当设置一个单词在不同文档中出现的次数限制(max_df)时,我们忽略了太常见的内容,比如停用词。在不同场景中定制矢量器函数输入应该会提高模型性能。
了解矢量器的定制选项非常有用。更多选择,你可以访问每个矢量器的 sklearn 文档。为了确保最佳的模型性能,我们可以使用 GridSearchCV 来调整变压器的超参数。在我的下一篇文章中,我将讨论在我的项目中应用 TFIDF 的更多细节,并构造估计器。
感谢您的阅读!这是我所有博客帖子的列表。如果你感兴趣的话,可以去看看!
我快乐的地方
zzhu17.medium.com](https://zzhu17.medium.com/my-blog-posts-gallery-ac6e01fe5cc3) [## 阅读朱(以及媒体上成千上万的其他作家)的每一个故事
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
zzhu17.medium.com](https://zzhu17.medium.com/membership)
进行情感分析的分步指南
科塞拉·博尔塔在 Unsplash 上的照片
第 1 部分:预处理文本数据
据估计,全球 80%的数据是非结构化的。因此,从非结构化数据中获取信息是数据分析的重要组成部分。文本挖掘是从非结构化的文本数据中获取有价值见解的过程,情感分析是文本挖掘的一个应用。它使用自然语言处理和机器学习技术从文本数据中理解和分类主观情绪。在商业环境中,情感分析广泛用于理解客户评论、检测电子邮件中的垃圾邮件等。本文是教程的第一部分,介绍了使用 Python 进行情感分析的具体技术。为了更好地说明这个过程,我将使用我的一个项目作为例子,在那里我对 WTI 原油期货价格进行新闻情绪分析。我将展示重要的步骤以及相应的 Python 代码。
一些背景信息
原油期货价格短期波动较大。虽然任何产品的长期均衡都是由供求状况决定的,但价格的短期波动反映了市场对该产品的信心和预期。在这个项目中,我使用原油相关的新闻文章来捕捉不断更新的市场信心和预期,并通过对新闻文章进行情绪分析来预测原油未来价格的变化。以下是完成此分析的步骤:
2、预处理文本数据(本文)
5、使用 python flask web app 在 Heroku 部署模型
我将讨论第二部分,即本文中的文本数据预处理。如果您对其他部分感兴趣,请点击链接阅读更多内容(即将推出)。
预处理文本数据
我使用 NLTK、Spacy 和一些正则表达式中的工具对新闻文章进行预处理。要导入库并在 Spacy 中使用预构建的模型,您可以使用以下代码:
import spacy
import nltk# Initialize spacy ‘en’ model, keeping only component needed for lemmatization and creating an engine:nlp = spacy.load(‘en’, disable=[‘parser’, ‘ner’])
之后,我用熊猫来读取数据:
“Subject”和“Body”是我将对其应用文本预处理过程的列。我按照标准的文本挖掘程序对新闻文章进行预处理,从新闻内容中提取有用的特征,包括标记化、去除停用词和词条化。
标记化
预处理文本数据的第一步是将每一个句子分解成单个的单词,这就是所谓的标记化。采用单个单词而不是句子会破坏单词之间的联系。但是,这是一种用于分析大量文本数据的常用方法。通过检查什么词在文章中出现以及这些词出现了多少次,计算机分析文本数据是高效和方便的,并且足以给出有见地的结果。
以我的数据集中的第一篇新闻文章为例:
您可以使用 NLTK 标记器:
或者您可以使用 Spacy,记住 NLP 是上面定义的 Spacy 引擎:
需要将每个令牌改为字符串变量
在标记化之后,每篇新闻都将转化为一系列单词、符号、数字和标点符号。您可以指定是否要将每个单词都转换成小写。下一步是删除无用的信息。例如,符号、数字、标点符号。我将使用 spacy 结合正则表达式来删除它们。
import re#tokenization and remove punctuations
words = [str(token) for token in nlp(text) if not token.is_punct] #remove digits and other symbols except "@"--used to remove email
words = [re.sub(r"[^A-Za-z@]", "", word) for word in words]#remove websites and email address
words = [re.sub(r”\S+com”, “”, word) for word in words]
words = [re.sub(r”\S+@\S+”, “”, word) for word in words]#remove empty spaces
words = [word for word in words if word!=’ ‘]
应用上述转换后,原始新闻文章看起来是这样的:
停用词
经过一些改造后,新闻文章更干净了,但我们仍然会看到一些我们不希望看到的词,例如,“和”,“我们”等。下一步是删除无用的词,即停用词。停用词是在许多文章中频繁出现但没有重要意义的词。停用词的例子有' I ',' the ',' a ',' of '。这些词如果被删除,将不会影响对文章的理解。要删除停用词,我们可以从 NLTK 库中导入停用词。除此之外,我还包括其他在经济分析中广泛使用的停用词列表,包括日期和时间,更一般的没有经济意义的词等。我是这样构造停用词列表的:
#import other lists of stopwords
with open(‘StopWords_GenericLong.txt’, ‘r’) as f:
x_gl = f.readlines()
with open(‘StopWords_Names.txt’, ‘r’) as f:
x_n = f.readlines()
with open(‘StopWords_DatesandNumbers.txt’, ‘r’) as f:
x_d = f.readlines()#import nltk stopwords
stopwords = nltk.corpus.stopwords.words(‘english’)#combine all stopwords
[stopwords.append(x.rstrip()) for x in x_gl][stopwords.append(x.rstrip()) for x in x_n][stopwords.append(x.rstrip()) for x in x_d]#change all stopwords into lowercase
stopwords_lower = [s.lower() for s in stopwords]
然后从新闻文章中排除停用词:
words = [word.lower() for word in words if word.lower() not in stopwords_lower]
应用到前面的例子,它看起来是这样的:
词汇化
除去停用词、符号、数字和标点符号,每篇新闻文章都将转化为一系列有意义的单词。然而,要统计每个单词的出现次数,就必须去除语法时态,将每个单词转换为其原始形式。例如,如果我们想计算单词“open”在一篇新闻文章中出现了多少次,我们需要计算“open”、“opens”、“opened”的出现次数。因此,词汇化是文本转换的一个重要步骤。另一种将单词转换成原始形式的方法叫做词干提取。它们之间的区别如下:
词干化是将一个单词提取到它的原始词干中,词干化是提取一个单词的语言学词根。我选择词汇化而不是词干化,因为词干化之后,一些单词变得难以理解。为了解释的目的,引理比语言根更好。
如上所示,用 Spacy 实现引理化非常容易,这里我调用。引理 _ 函数从空间开始。在词汇化之后,每篇新闻文章都将转化为一个单词列表,这些单词都是它们的原始形式。新闻报道现在变成了这样:
总结步骤
让我们总结一个函数中的步骤,并在所有文章中应用该函数:
def text_preprocessing(str_input): #tokenization, remove punctuation, lemmatization
words=[token.lemma_ for token in nlp(str_input) if not token.is_punct]
# remove symbols, websites, email addresses
words = [re.sub(r”[^A-Za-z@]”, “”, word) for word in words]
words = [re.sub(r”\S+com”, “”, word) for word in words]
words = [re.sub(r”\S+@\S+”, “”, word) for word in words]
words = [word for word in words if word!=’ ‘]
words = [word for word in words if len(word)!=0]
#remove stopwords
words=[word.lower() for word in words if word.lower() not in stopwords_lower] #combine a list into one string
string = “ “.join(words) return string
上面的函数 text_preprocessing()结合了所有的文本预处理步骤,这里输出的是第一篇新闻文章:
在推广到所有新闻文章之前,按照下面的代码,将它应用到随机的新闻文章中并看看它是如何工作的是很重要的:
import randomindex = random.randint(0, df.shape[0])
text_preprocessing(df.iloc[index][‘Body’])
如果有一些额外的词你想排除这个特定的项目或一些额外的多余信息你想删除,你可以随时修改该功能之前,适用于所有的新闻文章。这是一篇在标记化前后随机选择的新闻文章,去掉了停用词和词条。
预处理前的新闻文章
预处理后的新闻文章
如果一切正常,您可以将该功能应用于所有新闻文章:
df[‘news_cleaned’]=df[‘Body’].apply(text_preprocessing)
df[‘subject_cleaned’]=df[‘Subject’].apply(text_preprocessing)
一些言论
文本预处理是文本挖掘和情感分析中非常重要的一部分。有很多方法可以对非结构化数据进行预处理,使其对计算机可读,以便将来进行分析。下一步,我将讨论我用来将文本数据转换成稀疏矩阵的矢量器,以便它们可以用作定量分析的输入。
如果您的分析很简单,并且在预处理文本数据时不需要太多的定制,那么矢量器通常有嵌入式函数来执行基本步骤,比如标记化、删除停用词。或者,您可以编写自己的函数并在矢量器中指定自定义函数,这样您就可以同时对数据进行预处理和矢量化。如果您希望这样,您的函数需要返回一个标记化单词的列表,而不是一个长字符串。不过个人来说,我更倾向于先对文本数据进行预处理,再进行矢量化。通过这种方式,我不断地监控我的函数的性能,实际上这样更快,尤其是当你有一个大的数据集的时候。
我将在我的下一篇文章中讨论转换过程。感谢您的阅读!这是我所有博客帖子的列表。如果你感兴趣的话,可以去看看!
我快乐的地方
zzhu17.medium.com](https://zzhu17.medium.com/my-blog-posts-gallery-ac6e01fe5cc3) [## 阅读朱(以及媒体上成千上万的其他作家)的每一个故事
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
zzhu17.medium.com](https://zzhu17.medium.com/membership)
进行情感分析的分步指南
马库斯·温克勒在 Unsplash 上的照片
第三部分:最后一步,应用逻辑回归
按照我以前文章中的步骤,我对文本数据进行了预处理,并且将“清理”后的数据转换为稀疏矩阵。请点击链接查看更多详情。
现在我正处于对 WTI 原油期货价格进行新闻情绪分析的最后阶段。在本文中,我将讨论逻辑回归的使用,以及我在项目中发现的一些有趣的结果。我这里有一些这个项目的背景介绍。
定义并构建目标值
正如我在以前的文章中简要讨论的那样,进行情感分析是通过机器学习模型和文本数据来解决分类问题(通常是二元的)。解决一个分类问题就是解决一个有监督的机器学习问题,在训练模型的时候既需要特征也需要目标值。如果是二元分类问题,目标值通常是正面情绪和负面情绪。它们是根据你的研究问题的上下文来分配和详细定义的。
以我的项目为例,我的项目的目的是从最*发布的新闻文章中预测原油期货价格的变化。我把好消息定义为预测价格上涨的消息,而坏消息则预测价格下跌。因为我已经收集并转换了文本数据,并将它们用作要素,所以现在需要为数据集分配目标值。
我的项目的目标值是不同新闻文章的价格变化方向。我从彭博收集了 WTI 原油期货收盘价的高频交易数据,每五分钟更新一次。我将数据绘制在下图中:
资料来源:彭博
数据是 2019 年最后一个季度的。价格有很多波动,但是没有明显的趋势,非常适合情绪分析。这里的价格数据是一个连续变量,我需要将它转换成一个带有二进制值的分类变量,以便进行情感分析。
假设金融市场是完全有效的,并且市场对新信息的反应足够快,我定义新闻对 WTI 原油期货价格的影响在新闻发布后的五分钟内得到反映。我建立了一个虚拟变量:如果一篇新闻文章发布后五分钟内价格上涨,价格虚拟变量将是 1。否则,如果价格下降或不变,虚拟价格将为零。在整个数据集的五分钟时间段内,价格几乎不可能保持不变。因此,当虚拟价格等于零时,意味着价格在新闻发布后的五分钟内下降。
对于每篇新闻文章,通过寻找发布后五分钟内的价格变化,本文将新闻和价格虚拟进行匹配。下图显示,通过比较价格上涨事件和价格下跌事件的数量,数据大致*衡:
引入逻辑回归
在构建目标值之后,我已经为每篇新闻文章准备好了文本特征(TFIDF 矢量化文本数据)和价格虚拟数据。现在我需要应用一个估计器来建立机器学习模型。解决二元分类问题的模型有很多,这里我选择的是 logistic 回归。
逻辑回归是一个线性分类器,它是一个线性函数的转换:
线性回归
其中 b0,b1…bn 是一组独立变量 x =(x_1,x_2…x_n)的回归系数的估计值。逻辑回归函数 p( x )是 f( x )的 sigmoid 函数:
sigmoid 变换
变换后 p( x )的值会在[0,1]之间,可以解释为一个概率。一般 p( x )解释为 x 在正类时的预测概率,1-p( x )是 x 在负类的概率。在本项目中,p( x )定义为新闻文章 I 发布后五分钟内 WTI 原油期货价格上涨的概率。
应用逻辑回归进行新闻情感分析,我将每篇新闻文章视为一个观察,将新闻文章中的内容视为特征,并通过以下等式估计β_w0,β_w1,… β_wj:
这里 I 代表每篇新闻文章作为观察,wj 是所有新闻文章中第 j 个唯一的词。在左边,Y_i 是上一节描述的价格变化虚拟值。具体而言,Y 的值由以下条件决定:
虚拟价格
在右边,第一项是一个稀疏矩阵,每行代表一篇新闻文章,每列代表一个独特的单词。在 4616 篇新闻文章中出现过超过 20,606 个独特的单词,它们表明了稀疏矩阵的形状。稀疏矩阵的每个值 X_{i,wj}被表示为每个新闻文章 I 中每个唯一单词 wj 的 TFIDF 值,有关 TFIDF 变换的更多详细信息,请查看我的上一篇文章。
实施逻辑回归
为了实现逻辑回归和训练模型,我首先将数据集分为训练集和测试集。“df['news']”这里是“干净的”新闻文章,“df['price']”是作为目标值的价格虚拟。为了找到最好的转换器和最好的估计器,我建立了一个机器学习管道,并使用 GridSearchCV 来找到最好的超参数。我在此附上代码供您参考:
#train and test split
X_train, X_test, y_train, y_test = train_test_split(df['news'],
df['price'],
random_state=0)#build a machine learning pipeline
est = Pipeline([(‘vectorizer’, TfidfVectorizer(lowercase=False)),
(‘classifier’, LogisticRegression(solver=’liblinear’))])#GridSearchCV with a transformer and a estimator
parameters = {‘vectorizer__max_df’: (0.8,0.9),
‘vectorizer__min_df’: [20,50,0.1],
“classifier__C”:np.logspace(-3,3,7),
“classifier__penalty”:[“l1”,”l2"]}gs=GridSearchCV(est,param_grid=parameters)#fit the training data
gs.fit(X_train, y_train)#Evaluate the model
predictions = model.predict(vect.transform(X_test))
print('AUC: ', roc_auc_score(y_test, predictions))
AUC: 0.719221201684
如果没有指定,GridSearchCV 将寻找为模型评估生成最高精度的超参数。有时候,准确性不是评估模型的最佳指标,我们可能会使用其他指标。您可以通过在 GridSearchCV 函数中定义“计分”输入来指定它。对于如何选择合适的度量标准,我有一篇文章《模型评估分类度量标准终极指南》详细回答了这个问题。
我使用 AUC 作为我的模型度量,它在我的测试集中达到 0.71。鉴于我必须训练模型的观察数量(超过 4000 篇新闻文章),我相信模型已经准备好部署了。
有趣的发现
按照前面的步骤,我估计了每个唯一单词的系数(βs)。总的来说,我得到了超过 20,000 个独特的单词,下面的图显示了每个独特的单词的β:
x 轴上的每个点代表从所有新闻文章中收集的一个独特的词,总共有 20606 篇。y 轴代表每个单词的符号和系数的大小。该图表明,大多数独特词本身对价格的影响非常有限,其系数非常接*于零。但是,有一些词的系数绝对值超过 0.5,它们在估计价格变化时非常具有预测性。
使用 Python 单词云函数,根据系数的值,我绘制了预测不同方向价格变化的最积极和最消极的单词。字体越大,表示预测价格变化的影响越大。
部署在 Heroku
在构建和评估模型之后,我将模型实现为 Flask web 应用程序,并将其部署在 Heroku:
在“新闻正文”框中,您可以粘贴任何新闻文章并按“提交”,然后模型将预测该新闻文章的情绪,即该新闻发布后价格上涨的概率。
构建 web 应用程序需要在线部署训练好的模型,并根据新的输入进行预测。除了用 Python 编码来构建机器学习模型和构造 flask app,还需要一些 web app 的 HTML 背景知识。以后我会写一个关于部署机器学习模型的教程。
在 web 应用程序中,也有一些关于我的项目的解释性数据分析和其他有趣的发现。请随意查看并在这里玩。
这都是为了进行情感分析。如果您有任何意见或问题,请随时联系我。感谢您的阅读!
这是我所有博客帖子的列表。如果你感兴趣的话,可以去看看!
我快乐的地方
zzhu17.medium.com](https://zzhu17.medium.com/my-blog-posts-gallery-ac6e01fe5cc3) [## 阅读朱(以及媒体上成千上万的其他作家)的每一个故事
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
zzhu17.medium.com](https://zzhu17.medium.com/membership)
构建和部署影像分类 API 的分步教程
从使用 Labelme 的数据注释到使用 FastApi+Docker 的部署的所有步骤
图恩·nguyễn·明在 Unsplash 上拍摄的照片
在这个小项目中,我们的目标是从头开始构建一个图像分类 API。
我们将经历实现这一目标所需的所有步骤:
- 数据注释(使用 Unsplash API + Labelme)
- 模型训练(使用 Tensorflow)
- 制作 API(使用 Uvicorn 和 FastApi)
- 在远程服务器上部署 API(使用 Docker 和 Google 云*台)
数据注释:
任何机器学习项目最重要的部分之一是注释数据的质量和数量。这是部署 API 时影响预测质量的关键因素之一。
在这个项目中,我们将尝试将输入图像分为四类:
- 城市
- 海滩
- 日落
- 树木/森林
我选择这些课程是因为很容易在网上找到大量代表它们的图片。我们使用这些类来定义多标签分类问题:
来自https://unsplash.com/的输入和目标/图像示例
现在我们已经定义了我们想要解决的问题,我们需要获得足够数量的标记样本来进行训练和评估。
为了做到这一点,我们将首先使用 Unsplash API 来获取给定多个搜索查询的图像的 URL。
# First install [https://github.com/yakupadakli/python-unsplash](https://github.com/yakupadakli/python-unsplash)
# Unsplash API [https://unsplash.com/documentation](https://unsplash.com/documentation)
import json
import osfrom unsplash.api import Api
from unsplash.auth import Authwith open('tokens.json', 'r') as f:
data = json.load(f)client_id = data['client_id']
client_secret = data['client_secret']redirect_uri = ""
code = ""keyword = 'beach'auth = Auth(client_id, client_secret, redirect_uri, code=code)
api = Api(auth)photos = api.search.photos(keyword, per_page=1000, page=i)['results']for photo in photos:
print(photo)
print(photo.id)
print(photo.urls)
print(photo.urls.small)
我们将尝试获取与我们的目标类相关的图像 URL,加上一些其他随机图像,作为反面例子。
下一步是遍历所有的图像,并给每一个图像分配一组标签,如上图所示。为此,使用专为此任务设计的注释工具总是更容易,例如 LabelMe,它是一个 python 库,您可以从命令行轻松运行:
labelme . -flags labels.txt
Labelme 用户界面
使用 Labelme 我标记了大约一千张图片,并在这里提供了 urls 标签:https://github.com/CVxTz/ToyImageClassificationDataset
模型
现在我们有了标记的样本,我们可以尝试使用 Tensorflow 构建一个分类器。我们将使用 MobileNet_V2 作为分类器的主干,因为它速度快,而且不太可能过度拟合。鉴于我们只有少量的标记样本,您可以通过从 keras_applications 导入它来轻松使用它:
from tensorflow.keras.applications import MobileNetV2base_model = MobileNetV2(include_top=False, input_shape=input_shape, weights=weights)
由于这是一个具有四个类别的多标签分类问题,我们将有一个具有 Sigmoid 激活的四个神经元的输出层(给定一个示例,我们可以将多个神经元激活或没有神经元激活作为目标)
迁移学习
解决标记样本缺乏的一个常用技巧是使用迁移学习。它是当你把从源任务(像带有不同标签集的图像分类)中学到的一些权重转移到你的目标任务,作为你训练的起点。与从随机开始相比,这允许更好的初始化,并且允许为我们的多标签分类重用在源任务上学习的一些表示。
这里我们将转移在 ImageNet 中训练得到的权重。在为 MobileNet_V2 使用 Tensorflow+Keras 时,做到这一点非常容易,您只需要在创建 MobileNetV2 的实例时指定 weights="imagenet "
base_model = MobileNetV2(include_top=False, input_shape=input_shape, weights="imagenet")
数据扩充
当有一小组带注释的样本时,提高性能的另一个技巧是进行数据扩充。应用随机扰动的过程保留了标签信息(扰动后的城市图片看起来仍然像一个城市)。一些常见的变换是垂直镜像、椒盐噪声或模糊。
数据扩充示例/图片来自https://unsplash.com/
为了实现这一点,我们使用了一个名为 imgaug 的 python 包,并定义了一系列变换及其幅度:
sometimes = **lambda** aug: iaa.Sometimes(0.1, aug)
seq = iaa.Sequential(
[
sometimes(iaa.Affine(scale={**"x"**: (0.8, 1.2)})),
sometimes(iaa.Fliplr(p=0.5)),
sometimes(iaa.Affine(scale={**"y"**: (0.8, 1.2)})),
sometimes(iaa.Affine(translate_percent={**"x"**: (-0.2, 0.2)})),
sometimes(iaa.Affine(translate_percent={**"y"**: (-0.2, 0.2)})),
sometimes(iaa.Affine(rotate=(-20, 20))),
sometimes(iaa.Affine(shear=(-20, 20))),
sometimes(iaa.AdditiveGaussianNoise(scale=0.07 * 255)),
sometimes(iaa.GaussianBlur(sigma=(0, 3.0))),
],
random_order=**True**,
)
培养
我们将数据集分为两部分,训练和验证,并使用 binary_crossentropy 作为我们的目标,binary_accuracy 作为评估度量。
在更新一些配置文件后,我们从命令行运行培训:
# data_config.yaml for defnining the classes and input size **input_shape**: [null, null, 3]
**resize_shape**: [224, 224]
**images_base_path**: **'../example/data/'
targets**: [**'beach'**, **'city'**, **'sunset'**, **'trees'**]
**image_name_col**: **'name'**# training_config.yaml for defining some training parameters **use_augmentation**: true
**batch_size**: 32
**epochs**: 1000
**initial_learning_rate**: 0.0001
**model_path**: **"image_classification.h5"**
然后运行训练脚本:
**export PYTHONPATH=$PYTHONPATH:~/PycharmProjects/FastImageClassification/****python train.py --csv_path "../example/data.csv" \
--data_config_path "../example/data_config.yaml" \
--training_config_path "../example/training_config.yaml"**
我们最终得到的二进制验证准确率为 94%
制作 API
我们将使用 FastAPI 通过一个易于使用的 API 来公开一个预测器,该 API 可以将一个图像文件作为输入,并输出一个包含每个类的分类分数的 JSON。
首先,我们需要编写一个预测器类,它可以轻松地加载 tensorflow.keras 模型,并有一个方法来对文件对象形式的图像进行分类。
**class** ImagePredictor:
**def** __init__(
self, model_path, resize_size, targets, pre_processing_function=preprocess_input
):
self.model_path = model_path
self.pre_processing_function = pre_processing_function
self.model = load_model(self.model_path)
self.resize_size = resize_size
self.targets = targets @classmethod
**def** init_from_config_path(cls, config_path):
**with** open(config_path, **"r"**) **as** f:
config = yaml.load(f, yaml.SafeLoader)
predictor = cls(
model_path=config[**"model_path"**],
resize_size=config[**"resize_shape"**],
targets=config[**"targets"**],
)
**return** predictor @classmethod
**def** init_from_config_url(cls, config_path):
**with** open(config_path, **"r"**) **as** f:
config = yaml.load(f, yaml.SafeLoader) download_model(
config[**"model_url"**], config[**"model_path"**], config[**"model_sha256"**]
) **return** cls.init_from_config_path(config_path) **def** predict_from_array(self, arr):
arr = resize_img(arr, h=self.resize_size[0], w=self.resize_size[1])
arr = self.pre_processing_function(arr)
pred = self.model.predict(arr[np.newaxis, ...]).ravel().tolist()
pred = [round(x, 3) **for** x **in** pred]
**return** {k: v **for** k, v **in** zip(self.targets, pred)} **def** predict_from_file(self, file_object):
arr = read_from_file(file_object)
**return** self.predict_from_array(arr)
我们可以使用一个配置文件来实例化一个 predictor 对象,该对象具有进行预测的所有参数,并将从项目的 GitHub 存储库中下载模型:
**# config.yaml
resize_shape**: [224, 224]
**targets**: [**'beach'**, **'city'**, **'sunset'**, **'trees'**]
**model_path**: **"image_classification.h5"
model_url**: **"https://github.com/CVxTz/FastImageClassification/releases/download/v0.1/image_classification.h5"
model_sha256**: **"d5cd9082651faa826cab4562f60e3095502286b5ea64d5b25ba3682b66fbc305"**
完成所有这些之后,当使用 FastAPI 时,我们的 API 的主文件变得微不足道:
**from** fastapi **import** FastAPI, File, UploadFile**from** fast_image_classification.predictor **import** ImagePredictorapp = FastAPI()predictor_config_path = **"config.yaml"**predictor = ImagePredictor.init_from_config_url(predictor_config_path) @app.post(**"/scorefile/"**)
**def** create_upload_file(file: UploadFile = File(...)):
**return** predictor.predict_from_file(file.file)
我们现在可以用一个命令运行应用程序:
uvicorn main:app --reload
这使我们能够访问 Swagger UI,在那里我们可以在一个新文件上尝试我们的 API。
http://127 . 0 . 0 . 1:8080/docs
由 Antonio Resendiz 在 Unsplash 上拍摄的照片
上传上面的图像会产生以下输出:
{"beach": **0**,"city": **0**.**999**,"sunset": **0**.**005**,"trees": **0** }
这是预期的输出!
我们还可以通过 curl 发送请求并计时:
time curl -X POST "[http://127.0.0.1:8080/scorefile/](http://127.0.0.1:8000/scorefile/)" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "file=[@antonio](http://twitter.com/antonio)-resendiz-VTLqQe4Ej8I-unsplash.jpg;type=image/jpeg">> {"beach":0.0,"city":0.999,"sunset":0.005,"trees":0.0}
>> real 0m0.209s
>> user 0m0.012s
>> sys 0m0.008s
部署应用程序
码头工人
如果一个应用在 Docker 这样的容器中,部署起来会更容易。
在安装正确的环境后,我们将创建一个 docker 文件,其中包含运行我们的应用程序所需的所有说明:
**FROM** python:3.6-slim
**COPY** app/main.py /deploy/
**COPY** app/config.yaml /deploy/
**WORKDIR** /deploy/
**RUN** apt update
**RUN** apt install -y git
**RUN** apt-get install -y libglib2.0-0
**RUN** pip install git+https://github.com/CVxTz/FastImageClassification
**EXPOSE** 8080**ENTRYPOINT** uvicorn main:app --host 0.0.0.0 --port 8080
安装 Docker:
sudo apt install docker.io
然后我们可以运行 Docker 构建:
sudo docker build -t img_classif .
我们最后运行容器,同时将容器的端口 8080 映射到主机的端口:
sudo docker run -p 8080:8080 img_classif .
在远程服务器上部署
我试图在 AWS 的 ec2 实例上这样做,但是 ssh 命令行很笨拙,终端在最后一个命令时会死机,不知道为什么。所以我决定使用谷歌云*台的应用引擎进行部署。点击链接到关于这个主题的更详细的教程。
- 创建一个谷歌云*台账户
- 安装 gcloud
- 创建项目 project_id
- 克隆https://github.com/CVxTz/FastImageClassification并叫:
cd FastImageClassificationgcloud config set project_idgcloud app deploy app.yaml -v v1
最后一个命令需要一段时间,但是…瞧!
结论
在这个项目中,我们使用 Tensorflow、Docker、FastAPI 和谷歌云*台的应用引擎,从头开始构建和部署了机器学习支持的图像分类 API。所有这些工具使整个过程简单明了,相对容易。下一步是探索处理大量查询时与安全性和性能相关的问题。
重现结果的代码可从这里获得:https://github.com/CVxTz/FastImageClassification
走向工业化的一步:用 pyspark 和 argparse 为您的代码提供参数
使用 argparse 创建您自己的命令行参数,并对 prophet 预测模型的运行进行参数化
【https://unsplash.com/photos/qjnAnF0jIGk
Argparse 是什么?
argparse 是一个 python 库,它允许我们编写自己的命令行,以便在代码中包含灵活性。我个人在我的许多脚本中使用它,以使我的数据管道更加灵活,并形成例如在移动时间窗口上的模型。快速浏览一下库之后,我们会看到一些用例。
参数化你的代码:生产力,灵活性和更高的质量。
首先,我们需要导入库。
import argparse
然后我们定义一个“解析器”
parser = argparse.ArgumentParser()
[ArgumentParser](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser)
对象将保存将命令行解析成 Python 数据类型所需的所有信息。然后我们可以传递一些参数给解析器对象。
就说那个吧:
parser.add_argument(
'--train_start',
help='''Our algorithm deal with a moving window so we need to flexibilise our filename and so on it will be initialised with a flexible name like my_training_set_at_{train_start}''',
required=True,
)
我们向解析器添加了一个名为“train_start”的参数,并创建了一个帮助消息,它定义了参数的用途和用法,或者您想要编写的任何内容。最后,我们设置一个顺序条件,强制使用该参数,如果为 False,则可以忽略。
先说教程:(https://docs.python.org/3/library/argparse.html)
我们将把脚本复制到. py 文件中:
这里我们定义一个 ArgumentParser 对象来存储我们的参数。然后我们定义两个参数,一个有一个值,另一个会把它们加在一起,让我们来详述一下。
ArgumentParser.**add_argument**
( 名称或标志... [,动作 ][, nargs ][, const ][,默认 ][,类型 ][,选择 ][,必需 ][,帮助 ][, metavar ][, dest ]
我们首先添加一个参数:
- 一个名称或标志:'整数'
- 类型:这里的数据类型是整数
- 帮助:帮助命令用户的消息
- 一个元变量:改变显示的名称。
- nargs:它定义了应该使用的命令行参数的数量。这次行动
'+'
。就像'*'
一样,所有存在的命令行参数都聚集到一个列表中。此外,如果没有至少一个命令行参数,将会生成一条错误消息。
在第二个增加的参数中
- 一个名字或旗帜:'- -sum '
- 默认操作:如果没有指定,则返回最大值
- const:对整数列表求和的动作
- a dest:要添加到由
[parse_args()](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.parse_args)
返回的对象的属性的名称 - 助手消息
现在,我们将它保存为“parser _ exemple.py ”,然后打开控制台查看它:
那就试试吧
好了“教程”,现在让我们来看一个真实的例子。
几个使用的例子
我们将从我之前关于熊猫的一篇文章开始——UDF 和 prophet 对于这个脚本的预测和参数化,这将允许我们通过一个真实的例子使用 argparse 来参数化我们的脚本,避免一篇冗长无用的文章。下面是这篇文章的链接,其中包含了我们将要参数化的大部分代码
它将成为我们的工作基地:
参数化你的文件名和文件路径
其实也不是很难,我们会在一个不同的文件里用几个参数定义我们的解析器(这是我个人的偏见:其实你可以在同一个空间里做所有的事情)。
因此,我们将定义一个函数来创建 ArgumentParser,向其中添加所需的参数并返回分析后的参数。
在 main 中,我们导入我们的函数并检索我们在启动 spark submit 时放入的参数。
然后使用正确的参数通过 shell 将其作为 python 作业或 spark 提交作业启动,就这样。
这些基本元素对于构建高度通用的管道是必不可少的,并且不需要特殊的开发技能。
最后
这看起来很简单,但是这种工具对于拥有灵活的管道和使生活变得更容易是绝对必要的。我在我的项目中经常使用它,特别是与气流一起使用,以便对一段时间内的重复预测进行编程——这将是未来文章的主题。
感谢您的关注,您会在我的 github:https://github.com/AlexWarembourg/上找到所有的要点和要旨
数据产品的战略蓝图
如何用数据构建战略护城河
在当今的商业环境中,战略护城河是用数据构建的。不用数据游戏就能在软件上建立新的业务线的日子已经一去不复返了。数据最初被比作石油,表明数据为创新引擎提供燃料。最*,经济学家将数据比作阳光,因为像太阳光线一样,数据将无处不在,成为一切的基础。数据也是精明的商业人士建立差异化商业模式的新基础设施。
设计数据产品成本高昂。数据科学家和机器学习工程师是收入最高的专业人士,仅次于外科医生和医生。不用说,将一个数据科学项目从实验转变为生产应用需要强大的财务实力和一致的商业激励。成功数据产品的蓝图由三个核心要素组成:业务工作流、分销渠道和数据源。
业务工作流程
数据产品作为建立在业务工作流之上的应用层出现。数据产品在管理流程自动化、客户支持、法规遵从性等运营环境中部署时,都有成功的记录。也就是说,数据产品目前被分配给“安全”的后台部门,在那里性能故障的代价较低。
并不是每个业务流程都能支持一个数据产品。我已经为许多企业准备并审核了记分卡,以证明数据产品应用程序的业务工作流是合格的。看看吧!
数据源
公共数据或开放数据可供每个人访问、修改、重用和共享。开放数据组织是支持开放源代码软件的组织的对应组织。他们的工作赋予公民权力,可以加强民主,简化社会、政府和私营企业的流程和系统。几个很棒的开放数据源是世界银行开放数据、全球健康观察站数据、谷歌公共数据浏览器、AWS 开放数据注册中心、美国人口普查局。
私有数据来源是谷歌、亚马逊和脸书等差异化公司的支柱。先发战略使公司能够在数据聚合游戏→数据引力中实现跨越。搜索结果、产品/电影推荐和社交网络随着数据而改善。这就是为什么老牌玩家会留在这里,除非我们让机器学习系统简单地分享和学习不同的数据源。
私有数据的许可权变得复杂。一个普遍的问题是,数据源的所有者不能从外部再授权数据。这意味着私有数据只能由拥有该数据的同一组织所拥有的产品利用。第二十二条军规?如果数据是根据带有分许可条款的许可收集的,这就为在母公司之外将私人数据商业化提供了机会。我们必须解决房间里的大象。在各公司中,数据管理实践的范围很广。领先的公司通过遵守道德、隐私和安全规则树立了榜样。一些行业自行处理事务,并建立了数据隐私标准和框架。在医疗保健和金融服务领域,数据隐私由监管机构强制执行。消费行业必须遵守消费者隐私法。适用于任何人的经验法则:总是尽可能经常地消除数据标识并许可聚合数据的孤岛。
合成数据是一种可取之处,取决于手头的数据产品。计算机算法已经非常擅长生成合成数据:无论是名人的视频还是《T2》杂志的文章,我们都可以伪造。类似的技术可以用来生成合成数据,这些数据训练数据产品背后的机器学习模型。为了用相关的数据种子引导这样的算法,公司可以建立数据捐赠计划——内部的或外部的——并签订适当的数据使用协议。
分配路线
一个好的产品只是故事的一半。您的产品已经签名盖章,现在需要交付。一些分销渠道可用于企业产品。每个分销渠道都对产品定价模式和整体产品策略有影响(构建对购买对收购)。
最后,数据驱动型产品需要持续监控质量表现。你可能会问,为什么所有这些审查,做同样工作的人没有被全天候监控。这么说吧,人类每季度都要接受伦理方面的培训,并对自己的行为负责。机器在沉默中行动,所以我们需要使用监控脚本来查询它们的行为。监控产品性能和标记角落案例是一个很好的做法。从定义故障管理、产品道德和人在回路中的审查的内部政策开始。
软件工程面试者的学习计划
成为技术面试的专家——第三部分
这是软件工程师面试准备系列的第三部分。
我强烈建议您查看本系列的第一部分和第二部分,以了解该学习计划的背景。
该计划旨在实施我在第二部分中提到的刻意练习方法。
以此为指导——这里的主要目的是遵循有意练习的原则和我将在下面谈到的 7 步流程。享受旅程!
学习计划
设置:
好了,我们已经就什么是刻意练习进行了一次大讨论,但是现在让我们来谈谈我们如何实际实施刻意练习以达到我们的最终目标并赢得现场面试。
总结一下,我们的最终目标是:
每个主题都达到 3 级。
我们首先需要拿出一个空间,在那里我们可以客观地捕捉和跟踪每个主题的进展,每周。为此,我们将利用上面提到的 3 分制评分系统。这就是我们如何努力保持这个过程客观。
我将通过一个例子向你展示我如何跟踪进度,但我鼓励你发挥创造力,想出一种适合你和你的学习风格的方式。
首先,创建一个谷歌文档或表格来跟踪每个主题的进展。对于每个主题,创建一个表格来记录该主题每周的分数,并创建另一个表格来记录您的带有“正确/错误”列的题库。
我个人也喜欢用分区来记录每个主题的笔记、有用的链接和待办事项。这将成为下一步要做什么、你遇到了什么问题以及你克服了什么的列表——这有助于你更加关注自己一周的进步。
对我来说,布局可能是这样的:
如何跟踪主题进展的示例。(图片由作者提供)
我还会在周末维护一个每周更新的每个主题的水*表。刚开始的时候,这些话题大部分会是 1 级(也没关系!!).我可能会这样追踪:
每周记录每个主题的水*。(图片由作者提供)
日程安排:
既然我们已经有了一个有组织的空间来跟踪我们的进展,我们需要弄清楚 什么时候 我们实际上要把所有这些研究都放进去!
每个人的时间表都不一样——有些人在全职工作时准备面试,有些人在全职找工作(🙋🏼♀️).因此,你学习每个主题的时间和顺序完全取决于你自己和你的时间。
不管你如何选择你的主题,你有多少时间来学习,你的学习课程的结构将是相同的,并遵循以下循环:
- 确定问题区域
- 研究问题领域(谷歌/YouTube/书籍/同行讨论等。)
- 测试(来自 LeetCode 等的问题。)
- 学习试题解答(重要!!!)
- 重新评估和反思(确定成功和问题领域)
- 复试(与#3 相同的问题)
- 重复
我们需要在这些步骤之间留出空间。例如,你不会在同一个小时内重新测试同一个问题。这通常会在当天晚些时候完成,或者最好在几天后完成。
我们还需要决定如何*衡 20 个主题,以及如何为每个级别适当地学习。谢天谢地,我们有一个评级系统,这将有助于指导我们。
一级主题:
- 这些主题在开始时不会有很多“测试”。
- 在研究开始时做其中的一两个问题可以帮助你找到不足之处,并指导你的研究工作,但除此之外,钻研一个你一无所知的问题没有多大用处。
- 1 级课题的研究将主要包括整理一份棘手领域的清单,然后研究/学习这些领域。
- 根据题目的不同,你可能会在解决一个问题之前花整整一周的时间做研究(尤其是如果这是一个大题目的话)。
- 对于困难的话题,在一周结束时(经过一周的集中研究)尝试问一个问题,给自己一个新的基线。这里的要点不是把问题做对,而是把你所学的内容放回背景中,给自己机会去研究解决方案。即使你不知道从哪里开始,也要给这个问题一个明确的答案——说点什么。然后,花大量时间研究解决方案——这就是你学习如何解决问题的方法!(相对于仅仅阅读理论)。然后将这个问题添加到你的“错误”堆中,你将在以后再次测试它。
二级主题:
- 这些主题将在研究和测试之间保持*衡。
- 保持与这些主题的良好流程:确定问题领域、研究、测试、研究解决方案、评估、重新测试。
- 强调 做 题对二级题目很重要。
- 真正挑战自己,只是“做”。这就是这些主题如何到达第三级的原因!
第 3 级主题:
- 某样东西被评为 3 级意味着你对它“几乎无所不知”,根本不需要做太多的研究。
- 在这个阶段,只是实践:测试、解决方案、测试、解决方案…
- (当然还要重新测试你做错的题!).
改变级别:
不要对自己太苛刻——如果你觉得自己在某个话题上取得了进步,那就让自己进步吧!
然而,在以这种方式学习之后,你可能会意识到你需要把某些东西降低一个等级——不要为此惊慌。这是发现问题领域过程的一部分。你可能习惯于通过“感觉”来评估你在某方面的能力——现在我们有了一个客观的衡量标准,所以可以预料我们可能会出错。
对于第 2 级主题,如果你花更多的时间研究而不是做题,那么这是一个信号,表明这个主题可能应该下降到第 1 级。
对于第 3 级问题,如果你发现你得到了正确的答案,但是它的时间和空间复杂度一直很低,并且你的解决方案感觉有点“粗糙”,那么也许将这个问题移到第 2 级并研究这些类型问题的一些更优的解决方案是一个好主意。
相信你的判断,不要想太多!
学习计划示例:
这里有几个学习计划的例子,告诉你如何安排我们刚刚谈到的所有内容。抱歉,它们不太漂亮。
我假设每个计划每天学习 2 小时。当然,这些只是建议——你显然可以根据你的时间表和时间框架进行相应的调整。我相信你会想出更好的时间表!
关键是保持上面的 7 步流程。
14 天计划示例:
实施深思熟虑练习的 14 天学习计划示例。(图片由作者提供)
7 天计划示例:
实施深思熟虑练习的 7 天学习计划示例。(图片由作者提供)
5 天计划示例:
实施深思熟虑练习的 5 天学习计划示例。(图片由作者提供)
我在这里提供了 5、7 和 14 天的计划,告诉你无论你的时间表是什么,你都可以适应学习!作为一名教师,我听过各种各样的借口,比如“你不适合学习”,但我更乐意和你坐在一起,为你找时间!
请给我发消息告诉我你想到了什么——我总是很想知道人们是如何利用他们的时间来创造的!
数据科学家注意:
我和软件工程师一起实施了这个学习计划,并取得了巨大的成功。然而,我是一名数据科学家,目前正在接受数据科学职位的面试。这个领域比软件工程面试稍微微妙一些,因为对于数据科学的角色还没有直接的共识。
直接联系我如果你想讨论如何准备数据科学面试,以防你不知道,我喜欢谈论这个话题😝。
我们到了!
现在我知道了,我知道了。这是一个很大的数字,可能看起来有点过了。这是一个我充满热情的话题,我也相信这个话题的需求量很大。
让我们提高现场面试成功率,同时提高我们的学习效率!
一个成功的数据科学模型需要 GitHub。原因如下。
GitHub 给你的数据科学项目带来的好处。
在 Unsplash 上由 Roman Synkevych 拍摄的照片。
目录
- 介绍
- 开源代码库
- 利益
- 摘要
- 参考
介绍
数据科学家经常独自开始他们的学术甚至职业之旅,所以他们习惯于自己在本地驱动器上组织他们的概念和代码——也许是以某种临时的方式。但是,当你在一个由几个数据科学家、数据工程师、软件开发人员甚至产品经理组成的团队中工作时,会发生什么呢?你必须以某种方式合作。对于您的数据科学模型,您的代码将在哪里共享和控制?GitHub 就是这些问题的答案。
这个*台作为一个工具,让团队和组织的跨职能成员使用 Git 在同一版本的代码库上工作,并批准和评论通过 pull 请求请求和记录的新代码更改。
下面,我将在一个数据科学项目上分享和描述 GitHub 的好处。
开源代码库
照片由 Jantine Doornbos 在Unsplash【2】拍摄。
GitHub【3】通过使用 Git、pull requests、issues、wikis 和 gist 来记录和指导软件开发人员、设计人员和项目经理。建立数据科学项目相当简单,并允许您的团队对您的文件和代码进行检查和*衡。Git 是在终端中进行交互的主要系统,用于导航分支、代码更改以及最终的版本控制。Gists 对于提交代码片段以供共享也很有用,例如,如果您不想共享整个数据科学项目。下面,我就来讨论一下 GitHub 的好处。
利益
数据科学模型可以在您的本地计算机上工作,但一旦您将其他人纳入同一项目,GitHub 就可以作为一种工具,它有几个好处,可以确保成功的机器学习模型到位。我将包括更多描述性的好处和 Git、拉请求、协作和 gist 的例子。
【Git】—您可以执行某些命令,这些命令会推高您代码库的新版本。使用如下 Git 命令,可以创建一个 pull 请求,然后您的数据科学模型代码将被监控和增强。以下是一些常用的、有用的 Git 命令:
- 查看你在哪个分支——git 分支
- 从您的主分支创建一个新的分支—git branch branch _ name
- 拉你的主分支,使其保持最新— git 拉
- 检查您的文件(代码)变更— git 状态
- 添加您的文件(代码)从您的分支— git 添加
- 从您的分支提交您的更改—git commit-m " Added change "
- 从你的分支推送你的变更— git 推送
拉请求 —这个动作是 GitHub *台极其有用的一部分。对于 pull 请求,通常命名为“ PR 的”,您可以有第二个、第三个,甚至更多对代码变更的关注。当您想要将代码添加到现有的主分支时,您可以创建自己的分支,该分支将包含新的代码。您团队中的人必须查看并测试它,以确保您新添加的内容是正确的。公关过程不仅有利于消除错误,确保人们会仔细检查你的工作,而且在某种意义上,它也有利于你团队中的所有人都在同一页上。当其他人必须查看您的更改并批准新的代码时,他们将重申模型的知识,因为它扩展到更多的文件和系统。
协作 —通过使用 GitHub,还可以实现来自多个团队成员的相关协作,包括其他数据科学家、软件工程师、数据工程师和产品经理。协作是一种优势,因为它将使您的数据科学模型更加健壮、高效,并且在受到其他人的影响时可能更加准确。您可以在数据科学模型中包括所有合适的人员,并对整个项目产生积极的影响。
Gists —如果你想与他人分享一个更小的代码片段,甚至在这里,就在介质上,你可以用适当的编程语言显示代码,这些都很有用。这是一种显示代码示例的简单方法。当您以. py 格式指定编程语言(比如 Python)时,您可以很容易地看到彩色编码的函数——例如,导入代码以红色突出显示。下面是一个例子的要点:
要点示例。作者代码[4]。
摘要
GitHub 是您组织内数据科学项目的有用工具。它可以通过使用协作、Git、pull 请求和 gist 来存放、共享和增强代码。GitHub 还有其他几个好处,在他们提到的网站上也有概述。数据科学模型需要所有这些关键组件来确保成功。
虽然学术界对数据科学的关注不一定是 GitHub,而是通用机器学习模型的理论、概念和代码,但在学生进入劳动力市场并必须立即开始与其他人合作之前,应该重点关注这个*台。总之,这有利于开发成功的数据科学模型。
要了解更多关于 GitHub 的 Git 部分,请在下面找到这篇文章[5]:
通过使用 GitHub 成为更好的数据科学家指南
towardsdatascience.com](/common-github-commands-every-data-scientist-needs-to-know-e7d5d9c4f080)
我希望你觉得这篇文章有趣并且有用。感谢您的阅读!
参考
[1]照片由 Roman Synkevych 在Unsplash(2019)上拍摄
[2]照片由 Jantine Doornbos 在 Unsplash 上拍摄,(2017)
[3] GitHub,Inc ., GitHub 主页,(2020)
[4] M.Przybyla, pandas-append.py ,(2020)
[5] M.Przybyla,每个数据科学家都需要知道的通用 Git 命令,(2020)
句子向量表征中作文评价综述
自然语言处理领域著名研究论文综述
来源:https://www.aclweb.org/anthology/C18-1152.pdf(艾丁格等人,2018)
背景:为了理解什么是句子嵌入,有必要理解单词嵌入。单词嵌入已经变得非常著名,因为它们能够以可以普遍使用的向量的形式来表示单词。著名的嵌入有 word2vec、Glove 等。
单词嵌入的相同概念可以扩展到句子,使得每个句子用向量表示。诸如“发现两个堆栈溢出问题是否重复”之类的任务需要使用句子嵌入。
引言:为了理解语言,理解句子的意思和组成是必不可少的。今天的大部分神经网络模型本质上都是黑盒。因此,很难理解句子嵌入作为最终产生它们的训练的一部分正在捕捉什么。
本文讨论了专门用来测试句子嵌入是否抓住了句子的组成和意义的特定任务。本文基于另一篇论文(Adi 等人。al,2016),其中,(Adi 等人。al,2016)使用弓模型和自动编码器进行类似的实验。然而,由于数据集中的非预期偏差,他们的结果非常可疑。例如,他们表明,在单词顺序任务中,BOW 模型实现了 70%的性能,即使这种模型在逻辑上不可能保留与单词顺序相关的信息。因此,这篇论文的作者认为,BOW 模型的这种表现是一个偶然事件,因为数据集中存在偏差。
本文提出消除/减少这种偏见,并测试其他深度学习模型。它们还引入了额外的任务,这些任务将在下面详细讨论。本文的贡献包括一个句子生成集,一个已证实的模型来测试组成和意义是否确实被嵌入,生成系统和用于分类的数据集作为开源提供给其他人进行进一步的探索和分析。
研究问题:本文试图回答的研究问题有:
1.当前的神经句子嵌入模块在它们的句子嵌入中捕获句子的含义和组成的情况如何?
2.我们能提出一种方法和框架来评估句子嵌入和它们的模型在多大程度上捕捉了句子的意义和组成吗?
意义和构成:构成句子的元素向读者传递意义。它通常包含一个代理、一个患者和一个事件。构图是元素排列的一种方式,有助于传达意义。一个句子的不同部分可以结合起来达到它的意思。
数据集准备:作者提出了一种新的句子生成系统,减少了数据集中的偏差。例如,它根据英语的句法、语义和词汇规则生成多样化的、完全带注释的句子。它由三部分组成。
事件/句子表征:这些是句子的部分表征,接受诸如施事、受事、及物、不及物动词以及关系从句的存在与否等参数。这些表示作为输入提供给事件生成系统。例如,考虑如下所示的句子。
事件填充:系统从句子表示系统获取输入,并用给定的信息填充事件。它使用副词和 17 个词汇。字数受到限制,以保持对生成句子的控制。它循环通过副词和名词来生成句子。
句法实现:它使用基于规则的技术对生成的句子中的单词进行词形变化,以遵循词法。他们使用(Bird 等人,2009)中提到的 NLTK 框架,屈折从 XTAG 形态学数据库中提取(Doran 等人,1994)。
分类任务:设计不同的任务来测试句子嵌入是否保持句子的组成和意义。大致可分为两种类型,肯定和否定。SemRole 任务旨在测试句子嵌入是否抓住了意思。要回答的问题是,给定一个名词(n),一个动词(v)和一个句子嵌入(s),n 是 v 在 s 中的施事吗?
否定任务是测试句子嵌入是否捕捉到动词的否定。即给定一个动词(v)和一个句子嵌入(s),v 是否在 s 中被否定?生成的句子在动词和否定之间填充副词,使得动词在否定之后不明显,并且该模式易于模型学习和检测。
其他三项任务与单词内容和顺序有关。第一个任务, Content1Probe 被设计为测试句子嵌入是否包含输入句子中存在的动词。 Content2Probe 类似于 Content1Probe,它测试句子嵌入是否同时包含名词和动词,假设两者在句子嵌入生成之前都作为输入出现。
排序任务旨在测试合成句子嵌入是否捕捉到句子中单词顺序的信息。给定一个既包含动词(v)又包含名词(n)的句子嵌入(s ),那么名词(n)出现在动词(v)之前吗?
分类实验:作者建立了一个神经网络/多层感知器模型,其输入大小等于句子嵌入的大小。ReLU 用作神经元的激活函数。上述分类任务本质上是二元的。因此,对于生成的句子,每个任务的标签(是或否)被分配。生成 5000 个这样的句子,其中 4000 个具有适当标签的句子被用作训练集,其余 1000 个句子(具有适当标签)被用作测试集。不需要超参数调谐,因为网络规格在(Adi et。al,2016)。作者不执行任何训练来生成句子嵌入。他们也没有设计一个句子嵌入算法。他们使用嵌入算法,这些算法已经可以作为他们自己的语料库上的预训练模型。这些模型用于为生成的 5000 个句子产生句子嵌入。句子的嵌入和它们各自的任务标签形成了神经网络模型的数据集。该模型用训练集进行训练,并用测试集进行测试。
句子嵌入模型:下面描述所使用的不同句子嵌入模型:
BOW:BOW 模型是一个简单的模型,它使用一个向量来表示句子中的每个单词。它对这些嵌入进行*均,并将其用作句子嵌入。
顺序去噪自动编码器:它是一种无监督学习技术,使用基于 LSTM 的自动编码器。
跳过思想嵌入:他们利用 GRUs 生成句子嵌入。有两种可用的变体,uni-skip (ST-UNI)和 bi-skip (ST-BI)。Uni-skip 编码器在正向传递时进行回复,而 bi-skip 在神经网络中同时使用正向和反向传递。
InferSent: InferSent 是最先进的模型,它使用多层双向 LSTM 来生成句子嵌入。
结果:
表。1(摘自 来源 论文)
各种任务的模型结果如上表所示。它摘自 Ettinger 等人(2018 年)。
单词袋(BOW)模型在基于内容的任务上表现良好。这说明弓模型完美地编码了单词的意思。人们期望它在顺序、语义角色和否定任务中表现糟糕,它确实如此。这用作对数据集的检查,并且它满足该标准。这也可能是由于数据生成模块中使用的 17 个单词的词汇集非常有限。
在否定任务中,除了 ST-BI,所有模型都表现良好。这可能是因为在向前传递时,它首先遇到否定,然后是动词,但在向后传递时,这个顺序是相反的。因此,信息可能没有被很好地捕获。其他模型做得很好,即使很难捕捉到否定和动词之间的关系,即使很难做到这一点。这也可能是由于嵌入的维数从 1200 减少到 300。
对于语义角色(SemRole)任务,InferSent 表现随机,其他模型也表现不佳。正如本文作者(Ettinger 等人,2018 年)所述,句子嵌入模型没有提供有力的证据表明它们充分捕捉了语义角色。
还可以推断出,当通过它们的嵌入进行评估时,具有不同设计架构和目标的不同句子嵌入模型未能对句子的含义和组成产生任何显著影响。所有的模型在其嵌入中捕获几乎相同水*的意义和组成。
实验结果也证明了所提出的方法是可靠的,可以检测句子嵌入捕获了多少或是否捕获了句子的意义和成分。可以定义更多的任务来更好地理解句子嵌入中捕获的信息。
作者计划通过显式嵌入 e 中提到的句法结构来测试其他模型(Bowman 等人,2016;戴尔等人,2016;Socher 等人,2013 年)在他们未来的工作。
参考文献
Ettinger,a .,Elgohary,a .,Phillips,c .,& Resnik,P. (2018)。评估句子向量表示中的成分。arXiv:1809.03992。
约西·阿迪、埃纳特·克尔马尼、约纳坦·贝林科夫、奥弗·狮式战斗机和约夫·戈德堡。2016.使用辅助预测任务对句子嵌入进行细粒度分析。arXiv 预印本 arXiv:1608.04207。
史蒂文·伯德、伊万·克莱恩和爱德华·洛珀。2009.用 Python 进行自然语言处理:用自然语言工具包分析文本。奥赖利媒体公司。
克里斯蒂·多兰、达尼亚·埃杰迪、贝丝·安·霍基、班加罗尔·斯里尼瓦斯和马丁·扎伊德尔。1994.XTAG 系统:覆盖面广的英语语法。《第 15 届计算语言学会议论文集》第 2 卷,第 922-928 页。计算语言学协会。
塞缪尔·R·鲍曼、加博·安格利、克里斯托弗·波茨和克里斯托弗·D·曼宁。2015.用于学习自然语言推理的大型标注语料库。在 EMNLP。
克里斯·戴尔、阿迪古纳·昆科罗、米盖尔·巴列斯特罗斯和诺亚·史密斯。2016.递归神经网络语法。纳克。
理查德·索彻、亚历克斯·佩雷金、让·吴、贾森·庄、克里斯托弗·曼宁、和克里斯托弗·波茨。2013.情感树库语义合成的递归深度模型。2013 年自然语言处理经验方法会议论文集,第 1631-1642 页。
Twitter 美国航空公司情感数据集的监督或半监督 ULMFit 模型
Twitter 美国航空公司情感数据集的监督或半监督 ULMFit 模型
我们的任务是将类似 ULMFit (Ruder 等人,2018 年)的监督/半监督技术应用于 Twitter 美国航空公司情绪分析数据。
这个问题是半监督的原因是,它首先是一种非监督的训练方式,然后通过在网络顶部添加一个分类器网络来微调网络。
我们使用 Twitter 美国航空公司数据集(https://www . ka ggle . com/crowd flower/Twitter-airline-情操 )
https://unsplash.com/photos/rf6ywHVkrlY
我们将从 开始:
- 浏览数据集,为模型进行预处理和准备
- 探索情感分析的历史
- 探索语言模型及其重要性
- 设置基线模型
- 探索文本分类技术
- ULMFit 概述
- 将 ULMFIT 应用于 Twitter 美国航空公司数据
- 结果和预测
- 结论和未来方向
数据集
我们将从探索数据集统计数据和执行所有强制特征转换开始。
- 由于这是一个多类分类问题,我们将对目标变量进行编码。
- 我们将改变列的显示顺序
- 我们将执行基本的统计以从数据中获得一些洞察力
- 最后,我们将把新的数据帧分成 df_train、df_val 和 df_test
# Loading datasetdf = pd.read_csv(DATA_DIR)# LabelEncoder to change positive, negative and neutral to numbers (classes)labelEncoder = LabelEncoder()def cleanAscii(text):"""Remove Non ASCII characters from the dataset.Arguments:text: str"""return ''.join(i for i in text if ord(i) < 128)def gather_texts_and_labels(df=None, test_size=0.15,random_state=42):"""Gathers the text and the corresponding labels from the dataset and splits it.Arguments:df: Pandas DataFrametest_size: represents the test sizerandom_state: represents the random stateReturns:(x_train, x_test, y_train, y_test, new_df)"""# textstexts = df["text"].values# encoding labels (positive, neutral, negative)df['airline_sentiment'] = labelEncoder.fit_transform(df['airline_sentiment'])labels = df['airline_sentiment'].values# changing the order for fastai tokenizers to capture data.new_df = pd.DataFrame(data={"label":labels, "text":texts})df_train, df_test = train_test_split(new_df, stratify = new_df['label'], test_size=test_size, random_state = random_state)df_train, df_val = train_test_split(df_train, stratify = df_train['label'], test_size = test_size,random_state = random_state)print("Training: {}, Testing: {}, Val: {}".format(len(df_train), len(df_test), len(df_val)))return df_train, df_test, df_val,new_dfdef describe_dataset(df=None):"""Describes the datasetArguments:df: Pandas Dataframe"""print(df["airline_sentiment"].value_counts())print(df["airline"].value_counts())print("\nMean airline_sentiment_confidence is {}".format(df.airline_sentiment_confidence.mean()))# Optionaldef add_negativereason_to_text(df=None):# change negativereason to "" if NaN else remain as is.df['negativereason'] = df['negativereason'].apply(lambda x: "" if pd.isna(x) else x)# add negativereason to textdf['text'] = df['text'] + df['negativereason']add_negativereason_to_text(df)df['text'] = df['text'].apply(cleanAscii)describe_dataset(df)df_train, df_test, df_val, new_df = gather_texts_and_labels(df)
数据的统计
一些基本功能
一些视觉统计
更多统计数据
我们将依靠不同的指标来衡量模型的性能(精度、召回率、F1 得分)。
历史
历史
B 在 ULMFit (2018)或 NLP 中的迁移学习之前准确地说,我们使用 word2Vec 或 GLove 等单词嵌入将单词表示为密集稀疏向量表示。通常,我们使用嵌入层作为模型中的第一层,然后根据我们的需要附加一个分类器。这使得该系统很难训练,因为它需要大量的数据。这些语言模型是早期的统计 LMs,使用概率分布来表示单词。(《由公司一言保管》)。
- ULMfit,BERT,Universal sentence encoder,OpenAI GPT-2 使用一种叫做神经语言模型的东西来以分布式方式表示单词,并允许微调一个大型预训练语言模型来帮助我们完成任务。
- 具体来说,ULMfit (2018)引入了三种新技术来微调预训练语言模型
- 微调是计算机视觉中的一种流行方法,虽然这种方法在 NLP 上尝试过,但结果证明这种方法在 ULMFit 之前是错误的。
在本文的后面,我们将看到语言模型和分类器的概述。
设定基线
B 在任何机器学习实验之前,我们都应该设立一个基线,并与我们的结果进行比较。
为了建立基线,我们将使用 word2vec 嵌入矩阵来尝试预测情绪。
- 为了加载我们的 word2vec,我们将使用嵌入层,然后是基本的前馈神经网络来预测情绪。
我们也可以加载一个预先训练好的 word2vec 或 glove 嵌入,并输入到我们的嵌入层中。
我们可以在嵌入层之后使用 LSTM 或 CNN,然后激活 softmax。
# The word2vec requires sentences as list of lists.texts = df['text'].apply(cleanAscii).valuestokenizer = keras.preprocessing.text.Tokenizer(num_words=5000, oov_token='<OOV>')# fittingtokenizer.fit_on_texts(texts)vocab_size = len(tokenizer.word_index) + 1# max length to be padded (batch_size, 100)max_length = 100train_text = tokenizer.texts_to_sequences(df_train['text'].values)test_text = tokenizer.texts_to_sequences(df_test['text'].values)# getting the padded length of 100padded_train_text = keras.preprocessing.sequence.pad_sequences(train_text, max_length, padding='post')padded_test_text = keras.preprocessing.sequence.pad_sequences(test_text, max_length, padding='post')labels_train = keras.utils.to_categorical(df_train['label'].values, 3)labels_test = keras.utils.to_categorical(df_test['label'].values, 3)metrics = [keras.metrics.Accuracy()]net = Sequential()# return 50 dimension embedding representation with input_length as 100net.add(keras.layers.Embedding(vocab_size, 50, input_length=max_length))net.add(keras.layers.Flatten())net.add(keras.layers.Dense(512, activation='relu'))net.add(keras.layers.Dense(3, activation='softmax'))net.compile(optimizer='adam', loss=keras.losses.categorical_crossentropy, metrics=metrics)net.summary()# The word2vec requires sentences as list of lists.texts = df['text'].apply(cleanAscii).valuestokenizer = keras.preprocessing.text.Tokenizer(num_words=5000, oov_token='<OOV>')# fittingtokenizer.fit_on_texts(texts)vocab_size = len(tokenizer.word_index) + 1# max length to be padded (batch_size, 100)max_length = 100train_text = tokenizer.texts_to_sequences(df_train['text'].values)test_text = tokenizer.texts_to_sequences(df_test['text'].values)# getting the padded length of 100padded_train_text = keras.preprocessing.sequence.pad_sequences(train_text, max_length, padding='post')padded_test_text = keras.preprocessing.sequence.pad_sequences(test_text, max_length, padding='post')labels_train = keras.utils.to_categorical(df_train['label'].values, 3)labels_test = keras.utils.to_categorical(df_test['label'].values, 3)metrics = [keras.metrics.Accuracy()]net = Sequential()# return 50 dimension embedding representation with input_length as 100net.add(keras.layers.Embedding(vocab_size, 50, input_length=max_length))net.add(keras.layers.Flatten())net.add(keras.layers.Dense(512, activation='relu'))net.add(keras.layers.Dense(3, activation='softmax'))net.compile(optimizer='adam', loss=keras.losses.categorical_crossentropy, metrics=metrics)net.summary()
模型摘要
培养
# test the baseline model
def test_baseline_sentiment(text):"""Test the baseline modelArguments:text:str"""padded_text = keras.preprocessing.sequence.pad_sequences(tokenizer.texts_to_sequences([text]), max_length, padding='post')print(net.predict(padded_text).argmax(axis=1))net.evaluate(padded_test_text, labels_test)preds = net.predict(padded_test_text).argmax(axis=1)
如您所见,使用简单的前馈神经网络和嵌入层,我们很难达到 12%的精度
加载语言模型和微调
astAI 为我们提供了一个易于使用的基于维基文本(AWD)的语言模型。
我们将从加载 LM 数据并使用所需的数据初始化它开始。
data_lm = TextLMDataBunch.from_df(train_df = df_train, valid_df = df_val, path = "")# Saving the data_lm as backupdata_lm.save("data_lm_twitter.pkl") # saving as a back stop# Loading the language model (AWD_LSTM)learn = language_model_learner(data_lm, AWD_LSTM, drop_mult=0.3)print(learn)
我们的样本数据
正如你所看到的,fastai 库使用了 spacy tokenizer,所以除了删除 asci 字符之外,我们不对数据进行任何预处理。ULMFit 的作者在经验上很好地检验了标记化过程。
培养
# Finding the optimal learning ratelearn.lr_find(start_lr=1e-8, end_lr=1e2)learn.recorder.plot()# Fit using one cycle policylearn.fit_one_cycle(1, 1e-2)# Unfreeze all layerslearn.unfreeze()# fit one cycle for 10 epochslearn.fit_one_cycle(10, 1e-3, moms=(0.8,0.7))# save the encoderlearn.save_encoder('fine_tuned_enc') # we need the encoder in particular..FOr classifier
模型进度
文本分类
我们现在创建添加我们的分类器在下面的网络(微调)。这是将指定的任务分类器添加到预训练语言模型中的最后一步
这是逐步冻结步骤。
# Preparing the classifier datadata_clas = TextClasDataBunch.from_df(path = "", train_df = df_train, valid_df = df_val, test_df=df_test, vocab=data_lm.train_ds.vocab)# Building the classifierlearn = text_classifier_learner(data_clas, AWD_LSTM, drop_mult=0.5)# loading the saved encoderlearn.load_encoder('fine_tuned_enc') # load th encoder from the LM# slanted learning rate scheduler# fine tuning the whole networklearn.fit_one_cycle(3, 1e-2, moms=(0.8,0.7)) # you can of course train more, Jeremy promises its hard to over fit here :D# fine tuning the network layer by layer to preserve as much information is possible.learn.freeze_to(-2) # unfreeze last 2 layerslearn.fit_one_cycle(2, slice(1e-2/(2.6**4),1e-2), moms=(0.8,0.7))learn.freeze_to(-3) # unfreeze last 3 layerslearn.fit_one_cycle(2, slice(5e-3/(2.6**4),5e-3), moms=(0.8,0.7))learn.freeze_to(-4) # unfreeze last 4 layerslearn.fit_one_cycle(2, slice(5e-3/(2.6**4),5e-3), moms=(0.8,0.7))learn.freeze_to(-5) # unfreeze last 5 layerslearn.fit_one_cycle(2, slice(5e-3/(2.6**4),5e-3), moms=(0.8,0.7))# Unfreezing all the layers and traininglearn.unfreeze() # unfreze alllearn.fit_one_cycle(3, slice(1e-3/(2.6**4),1e-3), moms=(0.8,0.7))
我们达到了 94%的准确率
ULMFit 概述
ULMfit 流程的回顾
https://arxiv.org/abs/1801.06146
不同类型的流程如下:
- LM 预训练:这是我们遵循无监督学习来捕获大型语料库的语义和概率表示的步骤。(维基文本-103)
- LM 微调:这是我们通过使用某些新技术来微调 LM 的步骤。由于 AWD-LSTM(预训练模型)的每一层都捕获关于语料库的不同信息,我们首先微调最后一层,因为它包含最少的信息,而所有其他层都被冻结。然后,我们解冻所有其他层,用指定的任务重新训练模型。这样,我们不会丢失信息。通过使用倾斜的三角形学习率(模式为三角形的循环学习率)来完成训练。
- 最后一步是分类器微调,其中分类器模型附加到模型的顶部,并通过使用逐步解冻来训练,我们通过逐层解冻来训练模型。
T 这些技术是:
- 区别微调
- 倾斜三角形学习率
- 逐渐冻结
乌尔菲特在推特上表达了美国航空公司的观点。(预测和准确性)
def get_sentiment(text:str):"""Get the sentiment of text.Arguments:text: the text sentiment to be predicted"""index = learn.predict("This was a great movie!")[2].numpy().argmax()print("Predicted sentiment: {}".format(mapping[index]))def evaluate():"""Evaluates the networkArguments:NoneReturns:accuracy: float"""texts = df_test['text'].valueslabels = df_test['label'].valuespreds = []for t in texts:preds.append(learn.predict(t)[1].numpy())acc = (labels == preds).mean() * 100print("Test Accuracy: {}".format(acc))return preds, labelsget_sentiment("This is amazing")preds, labels = evaluate()print(classification_report(labels, preds, labels=[0,1,2]))print(confusion_matrix(labels, preds))
模型结果
混淆矩阵
- 如你所见,我们的模型很好,但可以通过试验超参数来改进。
- 如果我们看到混淆矩阵,我们可以看到我们的模型对大多数类别进行了正确的分类。
- 黑色代表 0,从图上看,我们得到的大多数预测都是黑色的
结论和未来方向
到得出结论,我们取得以下结果:
- 我们使用美国航空公司的推文数据库训练一个模型来预测推文的情绪。
- 我们使用 ULMFit (Ruder 等人,2018 年)通过上面给出的新技术来训练我们的模型。
- 我们使用流行的 fastai 库来训练模型,因为它包含 AWD-LSTM 的预训练权重。
- 我们实现了 94 的测试准确度,由于我们的数据集不*衡,我们使用 F1 分数等指标。
- 我们得到一个 F1 分,即 89 的准确度。
- 我们使用混淆矩阵进一步检验我们的模型的性能。
为了建立一个更好的模型,我们还可以使用其他语言模型和技术,如 BERT、use、Transformers、XLNet 等。
Colab 笔记本:https://Colab . research . Google . com/drive/1 eismifjg 1 aengepsfseb 55 bjcciop 5 pq?usp =共享
混合蛙跳算法综述
自然;人类最优秀的老师
穆罕默德·N·穆罕默迪的图片
T 何混合蛙跳算法(SFLA)是受自然界中青蛙的社会行为启发的最具创新性的优化算法之一,在分类方面,行为算法或模因算法都包含在其中。蛙跳优化算法的其他名称包括蛙跳算法、蛙跳算法和 SFLA 算法。该算法由 Eusuff 和 Lansey 在 2003 年首次提出,尽管此后提交了许多论文来改进该算法。在下载链接的底部是青蛙优化算法的主要文章。
什么是 SFLA 算法?
SFLA 算法是一种基于元启发式模因论的算法。memetic 算法是一种基于种群的算法,用于复杂而重要的优化问题。该算法的主要思想是在遗传算法的结构中使用一种局部搜索方法来提高搜索强化过程的水性能。memetic 算法首先加密初始答案的总和,然后 Ibn 算法基于一个适应度函数计算每个答案的效用,并生成新的解。
SFLA 算法的灵感来自青蛙寻找食物的方式。该算法使用诺模法在青蛙子群中进行局部搜索。青蛙混合跳转算法使用混合策略,并允许在局部搜索中交换消息。该算法结合了诺模算法和粒子群优化的优点。在青蛙混合跳转算法中,不仅在局部搜索中而且在全局搜索中交换单词。因此, 局部 和 全局 搜索在该算法中得到了很好的结合。青蛙混合跳转算法是高度可搜索和易于实现的。青蛙混合跳转算法可以解决许多非线性、不可检测和多状态问题。
青蛙变异算法的描述
该算法结合了两类基于遗传算法(如模因论)和基于社会行为算法(如粒子群鸟算法)的优点。它试图在可能的答案空间中的广泛审查之间取得*衡。在这种群体算法中,一群青蛙(答案)组成,每只青蛙在遗传算法中都有一个类似染色体的结构。青蛙的整个种群被分成更小的组,每组代表不同类型的青蛙,它们分散在答案空间的不同地方。然后,每组青蛙开始在它们的栖息地周围进行精确的局部搜索。
每一类中的每一只青蛙都受到其群体中其他成员以及其他群体的影响。几个步骤之后,混合发生了,信息在所有组中传播,以建立收敛和到达答案的条件。如何在该算法中找到最优解包括全局和局部搜索两个阶段。
初级种群形成
在初始种群的形成中,首先确定群体的数量和每个类别中应该有的青蛙数量。如果群体的数量和每个群体中青蛙的数量被认为是 1,那么样本的总数量将是 F = m * n。然后为生产的所有样本计算成本函数。分类和分配基于计算的成本函数来计算选择的青蛙的总数,使得具有最低成本函数和最佳位置的示例在第一位置。最佳青蛙的位置存储在整个种群中。然后将所有的青蛙分成 m 个选定的类别,这样每个类别中就有一只青蛙。
划分方法如下:在有序群体中,第一个成员在第一个类别中,第二个成员在第二个类别中,依此类推,直到受托人被选择并被置于“m”类别中,然后 1 + m 成员将在第一个类别中,因此划分青蛙的过程将继续。
群体的进化青蛙在每个群体的不同类别之间的划分以预定的数量重复进化的步骤。在这个步骤之后,所有的青蛙被组合,并且重复全局搜索步骤。
SFLA 流程图
SFLA 蛙跳算法的步骤
SFLA 算法的元探索策略按照以下步骤概括为全局探索和局部探索两个主要阶段。
全球勘探阶段
- 第一步:初始化
选择 M,N. M 代表 memeplex 的数量,n 代表每个 meme plex 中青蛙的数量,所以池塘的总种群大小由关系式 f = m * n 得到。
- 步骤 2:虚拟人口的产生
从可用空间中,采样 F 个虚拟青蛙 U(1),U(2),…,U(F)。计算每个 U(i)的能力值。
u(I)=(ui1 \u 2,…\u Uid)。此外,d 是决策变量的数量。
- 步骤 3:对青蛙进行分级和分类
将青蛙按优劣降序存放在数组 X = {U(i),f(i) & i=1…,F}中。记录种群中最好的 Px 蛙的位置。(U = Px(1))。
- 第四步:把青蛙分成复合物
将数组 X 分成 Y,每个数组包含 n 只青蛙。
- 第五步:模因论在每个模因丛中的进化
每个 Yk memeplex(k = 1,2,3,…,m)由下面描述的局部搜索蛙跳算法进化而来。
- 第六步:合并 memeplexes
在每个模因丛中发生一定数量的模因进化后,将模因丛(Y1,…,Ym)置于 X 中,使得关系 X = {Y(k),k = 1,2,…。,m}成立。然后,更新(Px)种群的最佳位置。
- 步骤 7:趋同研究
如果满足收敛条件,则停止。否则,转到全局搜索的第四步。
穆罕默德·N·穆罕默迪的图片
当地探险步骤:
在全局搜索的第五阶段,每个迷因复合体的进化被独立执行 N 次。在 memeplexes 进化之后,算法返回到全局搜索以完成组合。以下描述了每个 memeplex 中本地搜索的详细信息:
- 步骤 1:初始化
将中的 im、和置零,im 统计 memeplexes 的个数,iN 统计进化步数。
- 第二步:1 + im = im
- 第三步:1 + iN = iN
- 步骤 4:创建一个子复合体
青蛙的目标是通过改善它们的迷因来移动到最佳位置。选择子丛的方法是给性能较高的青蛙分配较多的权重,给性能值较低的青蛙分配较低的权重。权重通过三角概率分布来分配,Pi = {2(j-1 + n) / n(n+1),j = 1,…,n}。为了构建子 memeplex Z 数组,从每个 memeplex 的 n 只青蛙中随机选择 q 只青蛙。子丛中的那些分别用 PB 和 PW 表示。
- 第五步:纠正最差青蛙的位置。
子模板中最差的青蛙(具有最差性能的青蛙)的新位置通过关系 U(q) = S + PW 来计算。s 是青蛙的步长(跳跃的速率),它将被获得:
如果新位置比前一个位置更好,那么用前一个 U(q)替换新的 U(Q ),并转到局部搜索的步骤 8。否则,转到本地搜索的步骤 6。
- 第六步:用 PX 计算步长。
如果在步骤 5 中没有获得更好的结果,那么使用下面的等式计算青蛙的步长:
并且通过关系式 U (q) = S + PW 来计算新位置(U(q))。如果 U(q)在可能的空间内,则计算新效率 f(q)的值。如果 f(q)新的优于前一个,那么用前一个 U(q)替换新的 U(q ),进入局部搜索的第八步。否则,转到本地搜索的第七步。
- 第七步:审查
如果新位置不在可实现区域内或不比先前位置好,则在可用位置随机产生新的辙叉(r ),并替换其新位置不适合前进的辙叉。计算 f(r),设 U(q)等于 r,f(q)等于 f(r)。
- 第八步:更新 memeplex。
在子丛中最差的青蛙模仿变化后,将 Z 中的青蛙放在 Yim 上它们原来的位置。按性能降序排列 Yim。
- 第九步:如果 N > iN,转到第三步本地搜索。
- 第十步:如果 m > im,则进入本地搜索的第一步。否则,返回全局搜索以合并 memeplexes。
希望有帮助。如果您对 Linkedin 有任何问题或反馈,请告诉我。
Common Lisp 快速入门
熟悉有史以来第二种高级编程语言。
在 1958 年,一个新成员以第二高级和第一函数式编程语言 Lisp 的形式出现了。Lisp 是一种伟大的开源语言,尽管它已经存在了很长时间,但这些年来一直在不断地发展。此外,Lisp 已经发展成许多更小的方言,这些方言通常允许在 Lisp 内部更容易地完成特定的任务。Lisp 是一种很棒的语言,因为它得到了很好的支持,有很好的文档记录,并且非常受人尊敬。最流行的现代 Lisp 方言有 Common Lisp、闭包、Scheme、Machine Lisp、Arc,当然还有 Emacs Lisp。
如果你来自任何一种不是基于 Lisp 本身的语言,Lisp 是一种非常不同的语言。Lisp 编程非常具有功能性,它围绕着使用宏来断言数据的功能。这是一件需要注意的重要事情,因为语法一点都不相似。
获取 CLisp
Common Lisp (CLisp)实际上是可爱的 GNU 基金会的产品,并且是完全免费和开源的。要在非 Unix 系统上安装 Common Lisp,您需要从 SourceForge 或其他地方找到的镜像下载二进制文件。由于我不知道如何在 Windows 上安装应用程序,我就不讲我不知道如何做的东西了。至于 Linux,你当然可以使用你的包管理器,在我的例子中是 dnf。
sudo dnf install clisp
至于 MacOS,你也可以通过你的软件包管理器来安装它:
brew install clisp
要测试您的 CLisp 安装,只需在终端中输入以下命令就可以进入 REPL
clisp
变成巴什。
基本语法
今天,我将专门在 REPL 工作。这是为了确保文本编辑保持编译器、编辑器和语法高亮之间的一致性,而且我们不必保存文件。因此,首先,我将像之前一样使用命令进入 CLisp REPL
clisp
关于 Lisp 首先需要了解的是语法。Lisp 的语法当然很漂亮,也很酷,但最重要的是它是独一无二的。在 Lisp 中,几乎所有的命令都包含在括号中,并且使用空格作为语法,所有的命令都不区分大小写(所有的命令都是大写的)。)在我开始解释 Lisp 之前,我认为需要解释 Lisp 的范例,函数式编程范例。这对于学习 Lisp 非常重要,尤其是在学习非函数式语言的时候。
首先,构造类型只能保存数据,不能保存函数。Lisp 的独特之处在于数据可以作为代码使用,甚至可以在后台编写代码。构造类型被称为构造函数,与面向对象的类不同,尽管它们填补了同样的空白。换句话说,如果不使用多态,我们就不能将函数作为构造函数的属性来应用。例如,在 Python 中,我们可以有一个名为 cl 的类,该类可以有一个子类,并有可以用 cl.function 或 cl.subclass 调用的子方法。
换句话说,Lisp 函数调用总是以方法开头,而不是以变量开头。这也可以和另外两种函数式语言相提并论,它们是我一生的挚爱,
朱莉娅
另一个很酷,
稀有
所以很可能来自这两种语言会让你更接*。所以让我们从定义一个变量开始。当我们命名一个变量时,注意语法的结构是很重要的。在下面的例子中,我使用 setq,它将生成一个全局变量。我们使用 setq 的方式与使用 Lisp 中任何其他函数的方式基本相同。
v-method vvv-Variable Value
(setq x '(5 4 8 4))
^-Variable Name
这将创建一个我们可以用列表类型的 x 调用的变量,它是通过在括号前放一个'来定义的。下面是 Lisp 中的简单加法:
vvv Parameters
(+ 5 5)
^ Method (addition)
这里有一个类似的例子,打印一个字符串:
(prin1 "Hello World!")
要记住的最重要的事情是方法和变量是如何对齐的,因为这将使你更习惯于在 Lisp 中调用函数的方式。
函数和 For 循环
Lisp 中的函数是用 defunc 定义的。我们可以定义一个函数,它有一个名字,和一组参数,参数之间用空格分开,放在一组单独的括号中。
(defunc add (x y)
; (We'll add logic later)
)
这个函数定义非常典型,就好像我们把它与 Python、Julia 和 R 相比,R 是唯一一个显著不同的。
计算机编程语言
def add(x, y):
朱莉娅
function add(x, y)
稀有
add <- function(x, y){}
因此,给定我前面展示的添加 5 + 5 的代码,很容易猜到我们在这里需要做什么,特别是有了其他语言的经验之后。
(defunc add (x y) (+ x y))
是的,真的就这么简单。
当我学习一门新语言时,我总是喜欢写一个函数,它是一个均值函数。虽然这是非常基本的,但是尝试写一个需要 sigma(总和)和 n(样本大小)。)求和以及样本大小对于很多编程都是必不可少的,尤其是统计编程,这也是我特别使用 Lisp 的原因。
如上所述,我们需要两个东西,n 和σx。幸运的是,Lisp 有一个长度函数,可以这样使用:
(length x)
很简单,对吧?唯一的问题是求和没那么简单。为了对数组求和,我们需要使用 reduce。我们可以通过简单的操作做到这一点:
(defun sum (x) (reduce '+ y)
)
Lisp 中的 Reduce 是一种简单的说法,即从开始处开始,到列表的末尾。为了进行这样的操作,因为它是基于数组的,我们需要使用'+操作数,而不是+操作数。现在,我们可以用我们的函数来总结一个数组:
(sum x)
现在我们已经有了求和的方法,我们需要决定如何来设计这个函数。以最简洁的方式,不定义任何变量,并通过计算建立回报。这当然是编写这个函数的最佳方式,但是以这种方式思考公式可能会特别令人困惑——所以在这种情况下,我每次都会使用它,而且在大多数情况下我都会这样做。然而,当有大量的数学运算时,这可能会很困难,有时会导致使用更多的编译能力和内存。)
但是首先,让我们写出我们的*均函数。
(defunc mean (x) (/ (sum x) (length x))
为了更好地理解这一点,我们首先在括号中进一步计算数学(运算顺序),然后对 sigma 和 n 执行除法运算。
为了使用我们的函数,记住‘是指数组,所以在 Lisp 中创建一个数组,我们使用:
(setq x '(5 8 4 6 8))
所有的暗都被空间隔开。
至于 for 循环,想象一下 Python、Julia 或 R 中典型的简明 for 循环:
x = [u = u * 5 for u in x]
在 Lisp 中,我们将完全遵循这种循环风格,除了一个例外,我们将首先在括号中使用 loop,并且逻辑将需要翻转,使用单词“do”来代替,就像这样:
(loop for w in array do (+ w 1))
这当然只是给每个元素加一。另一个需要记住的重要事情是,do 后面的括号之外的任何逻辑都不会包含在循环中,这意味着层次结构中的所有内容都将期待一个返回,类似于我们的 mean 函数,操作的顺序决定了先做什么。
再用力一点…
最后一部分,我们要写一个函数来计算标准差。为了计算一个数组的标准差,我们需要μ。幸运的是,我们刚刚创建了一个函数,它将为我们提供 mu。使用 mean 函数和 setq,我前面谈到的全局变量定义(这会使 dims 公开,这并不总是一个好主意,但我认为知道如何使用全局变量比私有变量更好。)我们可以将*均值定义为μ,并使用一个简单的 for 循环来计算。在 for 循环内部,我们有(x 减去 mu),我们可以通过将这个数乘以它本身来执行。
正如我前面讨论的,这个选项可能不总是优于 setq,为了看起来更简洁,可能不值得这样做。无论如何,在我们将这个 for 循环应用到我们的列表之后,我们将能够求*均值的*方根并返回标准偏差。
(defun std (x) (setq μ (mean x)) (loop for y in x do
(* (- x μ) (- x μ)))) (sqrt (mean x)
)
总结一下…
我喜欢编写 Lisp,我真的希望这篇文章能为有兴趣学习它的人提供很多信息。我有可能在未来做类似的工作。在我看来,Lisp 是一种美丽的语言,它在我心中占有一席之地。虽然 Lisp 肯定不同于许多其他语言,但我认为它的语法看起来很酷也很漂亮。在相关新闻中,我的 Julia 模块,用于机器学习、统计和数据处理的车床即将进入 Lisp、Python 和 R,Python 和 R 在 Julia 中本地运行包,Lisp 从包的 Lisp 端口本地运行包。此外,这让我对 Lisp 感到兴奋和激动。
Julia 对 Flux 的快速介绍(使用 CUDA)
用 Flux 在 Julia 中建立你的第一个渐变模型
(src = http://fluxml.ai)
自从经典的 Mocha.jl 时代以来,Julia 中的机器学习已经走过了漫长的道路,对该生态系统做出贡献的最具开创性的创造之一是 Flux.jl. Flux 是 Julia 的权威梯度下降库,可以与 Python 的 Tensorflow 相提并论。Flux 遵循与许多 Julia 包类似的概念,如 Lathe.jl 和 DataFrames.jl,只用大约 1000 行代码编写,并且只依赖于 Julia 本身。与 Tensorflow 和 Pytorch 等解决方案相比,它们都使用各种语言,包括 C++、Go 和 C。
(src = http://juliacomputing.com)
Julia 的一个优点是并行计算*台和多线程与语言的无缝结合。没有比这更形象化的了(明白吗?相比 NVIDIA 图形处理器的古老*台 CUDA。Julia 和您的硬件之间的紧密集成很好地延续到 Flux 中,使 Flux 和 CUDA 成为真正的天作之合。将机器代码中的零标志设置为一,系好安全带,因为这肯定会令人兴奋!
获取数据
对于我今天的样本数据,我选择了来自 MLDatasets.jl 的数据集,它是可爱的 Julia Computing 的产品,您可以使用 Pkg 添加它:
using Pkg;Pkg.add("MLDatasets")
或者,在 Pkg REPL:
bash -$ julia
julia> ]
pkg> add "MLDatasets"
我通常不从常用的包中选择数据集,但是我做了这个例外,以确保这段代码不需要任何下载就可以重现(至少不需要通过您的 web 浏览器)。我要使用的数据集是时尚敏斯特数据集,我们可以这样下载:
**using** MLDatasets FashionMNIST.download(i_accept_the_terms_of_use=true)
train_x, train_y = FashionMNIST.traindata();
test_x, test_y = FashionMNIST.testdata();
您还可以选择添加一个验证集,或者用 Lathe 分割您自己的数据集:
using Pkg; Pkg.add("Lathe")
using Lathe.preprocess: TrainTestSplitusing DataFrames
# Validation:
train_x, train_y = FashionMNIST.traindata();
test_x, test_y = FashionMNIST.testdata();
df = DataFrame(:Feature => train_x, :Target => train_y)
train, val = TrainTestSplit(df)f = :Featuret = :Target
val_x = val[f]
val_y = val[t]
train_x = train[f]
train_y = train[t]# Bring your own data:
using CSV
df = CSV.read("data.csv")
train, test = TrainTestSplit(df)
因为我的数据集处理图像,所以我应该将数据从各自的文件格式转换成图像,我们可以这样做:
**using** ImageCore
FashionMNIST.convert2image(FashionMNIST.traintensor(4))
建模
首先,我们需要导入通量本身:
**using** Flux, Statistics
**using** Flux: onehotbatch, onecold, crossentropy, throttle, params **using** Lathe.stats: mean
**using** Base.Iterators: partition
**using** Random
我还直接从 Flux 导入了几个模块包括 onehotbatch,onecold,crossentropy,throttle,params,还有从 Lathe.stats 导入的 mean 函数,从 Julia 的迭代器导入的 partition,还有 Random。所有这些都是我们可以用来制作通量模型的拼图的一部分。下一步将是构建模型链。这是 Flux 真正闪光的地方,因为与大多数其他机器学习库不同,Flux 的渐变层使用链工作。Flux 使用 Julia 语言中各种独特而令人敬畏的语法点的组合来创建一个非常优雅的机器学习环境,chain 就是一个很好的例子。
model() = Chain(
Conv((5, 5), 1 => 64, elu, pad=(2, 2), stride=(1, 1)),
BatchNorm(64),
MaxPool((3, 3), pad=(2, 2), stride=(2, 2)),
Dropout(0.25),
Conv((5, 5), 64 => 128, elu, pad=(2, 2), stride=(1, 1)),
BatchNorm(128),
MaxPool((2, 2), stride=(2, 2)),
Dropout(0.25),
Conv((5, 5), 128 => 256, elu, pad=(2, 2), stride=(1, 1)),
BatchNorm(256),
MaxPool((2, 2), stride=(2, 2)),
Dropout(0.25),
x -> reshape(x, :, size(x, 4)),
Dense(2304, 256, elu),
Dropout(0.5),
Dense(256, 10),
softmax) |> gpu
接下来,我们需要为我们的训练数据获取 N:
N = size(train_x)[**end**]
现在,我们可以使用 N 通过范围迭代来随机混洗和排列我们训练索引:
ixs = collect(1:N)
shuffle!(ixs)
n = Int(floor(.9 * N))
这里需要注意的重要一点是,我们的数据需要存储在子数组或字典中。鉴于这将适用于字典,它很可能也适用于数据帧。将我们的数据转换成 Flux 批处理可以接受的格式后,我们可以像这样对数据进行批处理:
**function** make_batches(data; bs=100)
n = size(data[1])[**end**]
sz = (28, 28, 1, bs)
iter = [(reshape(Float32.(data[1][:, :, i]), sz), onehotbatch(data[2][i], 0:9)) **for** i **in** partition(1:n, bs)] |> gpu
**end**
train = make_batches(train)
val = make_batches(val)
test = make_batches(test);
现在,我们简单地用预期回报构建我们的模型:
m = model()
这是输出:
**Chain(Conv((5, 5), 1=>64, elu), BatchNorm(64), MaxPool((3, 3), pad = (2, 2), stride = (2, 2)), Dropout(0.25), Conv((5, 5), 64=>128, elu), BatchNorm(128), MaxPool((2, 2), pad = (0, 0, 0, 0), stride = (2, 2)), Dropout(0.25), Conv((5, 5), 128=>256, elu), BatchNorm(256), MaxPool((2, 2), pad = (0, 0, 0, 0), stride = (2, 2)), Dropout(0.25), #9, Dense(2304, 256, elu), Dropout(0.5), Dense(256, 10), softmax)**
我没有为这个特定的模型进行超参数调整,所以很可能只需要一点优化就可以提高精度。
接下来,我们需要一个度量函数,它将允许我们的模型检测它什么时候做得好或者坏。为此,我们需要三大部分:
尝试、验证、重建
我喜欢把这种尝试称为网络学习任何东西之前的初步猜测。验证是该过程中的一个重要步骤,模型需要检测它是变得更准确了,还是变得不准确了。最后但同样重要的是,重构是一个递归过程,在这个过程中,猜测被恢复并从中学习。这是我的函数:
**function** met(data)
**global** batch_idx
acc = 0
**for** batch **in** data
x, y = batch
pred = m(x) .> 0.5
tp = Float32(sum((pred .+ y) .== Int16(2)))
fp = Float32(sum((pred .- y) .== Int16(1)))
fn = Float32(sum((pred .- y) .== Int16(-1)))
tn = Float32(sum((pred .+ y) .== Int16(0)))
acc += (tp + tn) / (tp + tn + fp + fn)
**end**
acc /= length(data)
push!(eval_acc, acc)
**if** batch_idx % 100 == 0
@show(batch_idx)
**end**
batch_idx += 1
**end**
然后我们可以将所有这些部分插入语法表达式:
loss(x, y) = crossentropy(m(x), y)
evalcb = () -> met(val)
然后训练我们的模型!
Flux.train!(loss, params(m), train, opt, cb = evalcb)
现在,我们可以使用相同的度量函数来检查我们的精度:
met(test)
println("accuracy:", eval_acc[1])
百分之九十七的准确率!
结论
Flux 的语法、表达式和速度使其成为在 Julia 工作的数据科学家的一个非常有价值的工具。Flux 在许多测试中击败了竞争对手,因为它体积小、简单、快速且有效。Flux 的另一个巨大好处是模块化模型可以是什么样的,正如我通过在一个链中构建我的网络层,然后在其上传递更多内置来说明的那样。总的来说,我对 Flux 的发展以及 Julia 在机器学习和统计方面的整体发展感到兴奋。如果你对 Flux 感兴趣,另一个你可能感兴趣的很酷的东西是 KNet,我将很快写一篇关于它的“快速介绍”!你现在可以亲自去看看 Metalhead.jl,这是一个用 Flux 编写的图像分类器,可以适应新数据,并可回收用于任何分类用例。
车床快速入门:面向对象建模语言
车床机器学习库使用介绍。
(图片由作者提供)
介绍
在 Julia 生态系统中,有许多针对数据科学学科的包。有用于分布、推理和贝叶斯统计、数据可视化甚至深度学习的包。虽然这些包中的许多都是很棒的解决方案,并且分别工作得很好,但是还有一个更新的、更具包容性的解决方案,它在 Julia 语言中提供了类似 Sklearn 的语法,这通常有助于编写更多的函数代码。
车床。jl 是一个统计,预测建模,数据处理和深度学习库,所有这些都浓缩到一个单一的包中,您可以通过 Pkg 添加。与机器学习的其他 Julian 解决方案相比,Lathe.jl 的一个优势是,Lathe 利用 Julia 的调度类型来创建具有子调度方法的类型。这对于像模型这样的东西非常有用,在这种情况下,您可能希望有一个在拟合或预测之前执行一些逻辑的初始化函数。此外,使用包含在给定类型中的类型和数据的能力,而不是为了使用给定的方法而需要提供它们,对于机器学习来说也是非常有价值的。
入门指南
为了开始用车床处理算法,你首先需要安装它。虽然这很简单,但重要的是要确保你使用的是正确的分支和版本的车床。要添加最新版本的车床,可以这样做
using Pkg;Pkg.add("Lathe")
你体内的朱莉娅·REPL。
(图片由作者提供)
这将给你车床版本 0.1.1“黄油球。”只要您使用的是车床“Butterball”的版本,本教程应该适用于所有涉及的代码。如果您想先睹为快,也可以添加不稳定分支:
julia>]
pkg> add Lathe#Unstable
您还可以为 0.1.0 以上的每个特定版本添加分支:
add Lathe#Butterball
add Lathe#0.1.0
add Lathe#0.1.1
add Lathe#0.1.2
您还需要添加 DataFrames.jl。它不仅是这台车床唯一的依赖项,而且还与车床中的许多函数相关联,这些函数将采用数据帧类型。
add DataFrames
现在你应该可以导入车床了:
using Lathe
关于使用任何 Julia 包,我能给出的一些很好的建议是熟悉如何使用?()方法来浏览文档。大多数软件包使用 Documenter.jl 来创建它们的文档,这些文档通常是通过 Juliahub 生成的(这真的很酷),所以经常会有一些文档,你可以很容易地在你的 REPL 或笔记本中访问它们。如果你想了解更多关于用 doc-strings 和 Documenter.jl 创建自动化文档的知识,我写了一个完整的教程,你可以在这里查看:
[## 如何用 Documenter.jl 自动化 Julia 文档
没有文档,软件是没有用的,所以用 Documenter.jl 把文档的痛苦去掉吧
towardsdatascience.com](/how-to-automate-julia-documentation-with-documenter-jl-21a44d4a188f)
每当我们运行我们的。()方法放在车床模块上,我们得到这样的回报:
(图片由作者提供)
让我们先来看看 Lathe.stats,它是 Lathe.jl 包含的统计库。我们将在下面的代码中直接使用它:
using Lathe: stats
现在我们将调用我们的?()方法在上面:
(图片由作者提供)
作为回报,我们得到了这个库中所有可用函数的详细列表。今天,我们将忽略统计库,直接进入预处理,但是如果您需要的话,统计数据总是存在的。
数据
为了开始使用车床,我们当然需要一些数据来支持它。用于基本示例的一个很好的格式是逗号分隔值,我们需要 CSV.jl 包来读取它。如果您的计算机上没有该包,您可以使用以下命令获取它:
pkg> add CSV
在本例中,我将使用一些汽车数据训练一个模型,这些数据包含欧洲汽车的信息,如里程、价格和转售价值。
using CSV
df = CSV.read("car data.csv")
该数据有两个可能相关联的特征,并且用线性回归来探索是有趣的,那就是汽车的销售价格和它的制造年份。让我们从删除所有我们不需要的特性开始。为此,我们可以创建一个全新的数据框,或者删除我们不需要的要素。我更喜欢后者。
using DataFrames
df = DataFrame(:Year => df[:Year], :Price => df[:Selling_Price])
为了检查缺少的值,我们将运行一个快速 for 循环来检查值是否缺少:
for year in df[:Year]
if year == Missing
println("missing")
end
end
for price in df[:Price]
if price == Missing
println("missing")
end
end
幸运的是,这个数据没有值,所以我们将继续把数据分成测试和训练集。为此,我们将使用车床:
(图片由作者提供)
我们正在寻找的方法是 TrainTestSplit()。要找到关于函数的更多信息,我们可以使用?()方法上也是如此:
(图片由作者提供)
这不是最好的文档,但是它确实给了我们一个概念,我们需要为这个函数提供什么参数。有趣的是,这个函数使用 Julia 的 dispatch,所以我们也可以直接调用 dispatch 函数,就像这样:
train, test = preprocess._dfTrainTestSplit(df, .75)
(图片由作者提供)
现在,我们将把它放入新的数组中,用于训练值和测试值:
trainX = train[:Price]
trainY = train[:Year]
testX = test[:Price]
testY = test[:Year]
建模
最后,我们可以从 Lathe.models 获取 LinearRegression。如果您使用的是更新版本的 Lathe,您可能需要调用 SimpleLinearRegression。
?(models.LinearRegression)
(图片由作者提供)
如您所见,我们需要为 y 和 x 提供一个一维数组,并将调用 predict 函数来返回一个预测值。我们可以像在 Julia 甚至 Python 中创建类型一样拟合模型:
model = models.LinearRegression(trainX, trainY)
现在我们可以在没有测试数据的情况下调用这个模型。
yhat = model.predict(testX)
(图片由作者提供)
因为年份是整数,所以我将遍历这些值,并将它们四舍五入为最接*的整数:
yhat = [year = Int64(round(year)) for year in yhat]
(图片由作者提供)
注意:
如果您使用的是车床 1.2 +,那么在直接调用模块时,您将能够调用所有函数作为导出。或者,您可以调用作为由车床导出的模块的子模块的函数。
为了验证我们的模型,我们可以使用来自 Lathe.stats 的*均绝对误差指标:
using Lathe.stats: mae
println(mae(yhat, testY))
我认为这是非常准确的!如果我们真的需要,我们也可以使用来自 Lathe.preprocess 的规格化器。对于这个例子,我打算迭代最小可行产品,但是 MAE 为 0 意味着模型在这个测试中是完美的,所以我真的没有任何改进可以做,除非我着手建立一个验证集并进一步提高模型的准确性——并冒过度拟合的风险。
结论
车床是一个伟大的上升和未来的工具,我非常兴奋。虽然肯定还有很多工作要做,但我认为它对 Julia 语言的影响是相当大的。有了类似 Sklearn 的语法,以及非常容易理解的函数和类型,我认为它可以为许多 Python 用户搭建一座桥梁,这些用户不太习惯于将参数放入一个结构并将它们作为参数传递,以使方法适合模型类型和数据。
Julia 中元编程的快速介绍
在 Julia 中使用 Julia 的元包进行编程的基础。
(茱莉亚 logo src = http://julialang.org)
介绍
Julia 语言因其许多相对有用的特性而备受推崇。然而,我认为在 Julia 语言中经常被忽略的一个特性是 Julia 的元编程能力。元编程是一种编程方式,其中一个程序使用另一个程序作为其数据。当我说程序时,我指的是可以在该语言中运行的任何可执行代码,而不是单独的语言或应用程序。
元编程非常有用。有些事情你可以用代码作为数据来做,而这些事情在编程语言中是无法做到的。我想从我的文件夹中给大家带来一个很好的例子是 Hone.jl. Hone.jl 使用元标记,这些元标记只是包含代码的字符串,可以随后连接和修改这些字符串以形成图和绘图。如果不使用这些元标记,有些事情是不可能实现的,那就是扩展 Hone 的能力。如果你想了解更多关于如何编写 Hone 扩展的知识,你可以看看这篇文章:
[## 我是如何在 Julia 中编写第一个 Hone 扩展的
在 Julia 中创建和使用我的绘图库的扩展。
towardsdatascience.com](/how-i-programmed-the-first-hone-extension-in-julia-edf7813d0e1b)
幸运的是,Julia 中的元编程很容易上手。朱莉娅的元是很容易掌握和学习的东西之一,但要掌握起来要困难得多。使用元编程的一个很大的缺点是,它会使调试变得特别困难,因为您的代码都包含在表达式中,一个小错误,比如省略一个逗号,就会使您的代码无法运行。这是因为在线上读取错误返回比解析错误要容易得多。
表达式类型
为了在 Julia 中有效地进行元编程,你需要很快习惯的一件事是一种新的类型。让我给你介绍一下:
:Expr
表达式类型是一种旨在存储可评估的已解析元代码的类型。为了进行基本的字符串到表达式的转换,您需要熟悉 Base.Meta 中的 parse()方法。
using Base.Meta: parse
让我们试着在一个字符串上使用它:
请注意,我们的输出现在变成了一个符号。这个符号在某种程度上可以被看作是我之前谈到的应用程序。这是一个运行该符号内部代码的表达式。或者,我们也可以创建一个我们自己的符号来执行这个运算。
正如您所看到的,这两个都是表达式,一个是解析的,另一个是使用内部带有语法的符号创建的。这实际上是存储在符号数据类型中的代码。
表达式的属性
Expr 类型实际上有一些您可能没有想到的有趣属性。真正酷的是,它们允许我们剖析数据/代码的内容,并对它们有更多的了解。我想给你看的第一个财产是人头。Expr 类型包含两种主要的数据类型,头数据和参数数据。head 用于界定要传递的是哪种表达式。在这个例子以及大多数例子中,我们使用:call 类型。这不是一个实际的数据类型,只是一个存储在 Expr 结构中的符号。
接下来我们有参数。Args 是我们的数据包含的所有参数。这些争论可以分为两类。他们要么是
操作
其中包括方法和操作数。这些将用符号数据类型来表示。事实上,这些是你的元表达式的元部分。然而,如果没有数据,这些操作是没有用的,所以除了操作之外,我们还有
数据。
我们可以通过打印所有参数的类型来可视化这一点。
这基本上就是解析器为我们做的事情。解析器将需要执行的功能和数据相互分离。之后,它会把所有东西按正确的顺序排列,这样它就可以被正确地评估。另一件应该提到的事情是从字符串类型到表达式类型的转换。
解析和评估
既然我们理解了 parse()的作用,以及它如何将字符串转换成表达式类型,我们现在可以开始创建一些表达式,然后用 eval()对其求值:
data_code = "mean([5,10,15,20])"
expression = parse(data_code)
mu = eval(expression)
这是相对基本的,但也有一些事情你应该注意。首先,如果你所有的数据都在一个字符串中,你如何使用字符串数据类型?不幸的是,在 Julia 中没有办法像在 Python 中那样在字符串内部分隔字符串,所以我们需要使用正则表达式。仔细想想,正则表达式本身也是元程序;所以我们真的是在兜圈子。在 Julia 中获取字符串而无需创建字符串的最简单方法是使用一个符号:
symb = :hello_world
a_string = string("\"",string(symb),"\"")
正则表达式\ "用于在字符串中分隔引号。
这真的就是全部了!
元编程是一个强大的工具,我相信有时会被忽略。我认为茱莉亚的处理方式是最完美的处理方式。虽然它肯定不是这门语言的重点,但是它的实现非常好,使用起来也非常简单。Julia 有很强的元编程能力,我已经享受了很长时间了!
一种表格检测、单元格识别和文本提取算法,用于将图像中的表格转换为 excel 文件
如何使用 OpenCV 和 pytesseract 将表格截图转换成可编辑的数据
来源:pixabay
假设您在文章、pdf 或图像中有一个表格,并希望将其转换为 excel 表格或数据框架,以便能够对其进行编辑。特别是在机器学习的预处理领域,这种算法将非常有助于将许多图像和表格转换为可编辑的数据。如果您的数据存在于基于文本的 pdf 文件中,已经有一些免费的解决方案。最受欢迎的是表格式,卡梅洛特/神剑,你可以在https://tabula.technology/,https://camelot-py.readthedocs.io/en/master/,https://excalibur-py.readthedocs.io/en/master/下找到。
但是,如果您的 PDF 是基于图像的,或者您在网上找到一篇带有表格的文章,该怎么办?为什么不直接截图转换成 excel 表呢?因为基于图像的数据(jpg、png、基于图像的 pdf 等)似乎没有免费或开源软件。)的想法是开发一个通用的解决方案,将表格转换成可编辑的 excel 文件。
但是现在已经足够了,让我们看看它是如何工作的。
入门指南
该算法由三部分组成:第一部分是使用打开 CV 的表格检测和单元格识别,第二部分是将单元格彻底分配到适当的行和列,第三部分是使用 pytesseract 通过光学字符识别(OCR)提取每个分配的单元格。
和大多数表格识别算法一样,这种算法是基于表格的行结构的。清晰和可检测的线条对于正确识别细胞是必要的。具有虚线、间隙和孔洞的表格导致较差的识别,并且没有检测到仅部分被线包围的单元。如果您的某些文档出现断行,请务必阅读本文并修复断行:单击此处。
首先,我们需要输入数据,在我的例子中是 png 格式的截图。目标是拥有一个具有相同表格结构的数据框架和 excel 文件,其中每个单元格都可以编辑并用于进一步分析。
用于进一步表格识别和提取的输入数据。
让我们导入必要的库。
关于图书馆的更多信息:
cv2—https://opencv.org/宇宙魔方—https://pypi.org/project/pytesseract/
**import** cv2
**import** numpy as np
**import** pandas as pd
**import** matplotlib.pyplot as plt
**import** csvtry:
**from** PIL **import** Image
except ImportError:
**import** Image
**import** pytesseract
第一步是从正确的路径读入文件,使用阈值将输入图像转换为二进制图像,并将其反转以获得黑色背景、白色线条和字体。
**#read your file** file=r'/Users/YOURPATH/testcv.png'
img = cv2.imread(file,0)
img.shape**#thresholding the image to a binary image** thresh,img_bin = cv2.threshold(img,128,255,cv2.THRESH_BINARY |cv2.THRESH_OTSU)**#inverting the image** img_bin = 255-img_bin
cv2.imwrite('/Users/YOURPATH/cv_inverted.png',img_bin)**#Plotting the image to see the output**
plotting = plt.imshow(img_bin,cmap='gray')
plt.show()
二进制反转图像。
请继续关注 Marius Hucker 的新文章。如果您还没有注册,您将创建一个中型帐户…
medium.com](https://medium.com/subscribe/@hucker.marius)
下一步是定义一个内核来检测矩形框,然后是表格结构。首先,我们定义核的长度,然后沿着垂直和水*核检测所有的垂直线和水*线。
**# Length(width) of kernel as 100th of total width**
kernel_len = np.array(img).shape[1]//100**# Defining a vertical kernel to detect all vertical lines of image** ver_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, kernel_len))**# Defining a horizontal kernel to detect all horizontal lines of image** hor_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_len, 1))**# A kernel of 2x2** kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
下一步是垂直线的检测。
**#Use vertical kernel to detect and save the vertical lines in a jpg**
image_1 = cv2.erode(img_bin, ver_kernel, iterations=3)
vertical_lines = cv2.dilate(image_1, ver_kernel, iterations=3)
cv2.imwrite("/Users/YOURPATH/vertical.jpg",vertical_lines)**#Plot the generated image**
plotting = plt.imshow(image_1,cmap='gray')
plt.show()
提取的垂直线。
现在所有的水*线都一样。
**#Use horizontal kernel to detect and save the horizontal lines in a jpg**
image_2 = cv2.erode(img_bin, hor_kernel, iterations=3)
horizontal_lines = cv2.dilate(image_2, hor_kernel, iterations=3)
cv2.imwrite("/Users/YOURPATH/horizontal.jpg",horizontal_lines)**#Plot the generated image**
plotting = plt.imshow(image_2,cmap='gray')
plt.show()
提取的水*线。
我们通过用 0.5 对水*线和垂直线进行加权,将它们组合成第三幅图像。目的是得到一个清晰的表格结构来检测每个细胞。
**# Combine horizontal and vertical lines in a new third image, with both having same weight.** img_vh = cv2.addWeighted(vertical_lines, 0.5, horizontal_lines, 0.5, 0.0)**#Eroding and thesholding the image**
img_vh = cv2.erode(~img_vh, kernel, iterations=2)
thresh, img_vh = cv2.threshold(img_vh,128,255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
cv2.imwrite("/Users/YOURPATH/img_vh.jpg", img_vh)bitxor = cv2.bitwise_xor(img,img_vh)
bitnot = cv2.bitwise_not(bitxor)**#Plotting the generated image**
plotting = plt.imshow(bitnot,cmap='gray')
plt.show()
提取的不包含文本的表格结构。
有了表格结构后,我们使用 findContours 函数来检测轮廓。这有助于我们检索每个盒子的准确坐标。
**# Detect contours for following box detection** contours, hierarchy = cv2.findContours(img_vh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
以下函数是获取轮廓序列并从上到下对其进行排序所必需的(https://www . pyimagesearch . com/2015/04/20/sorting-contours-using-python-and-opencv/)。
def sort_contours(cnts, method="left-to-right"): **# initialize the reverse flag and sort index** reverse = False
i = 0 **# handle if we need to sort in reverse**
if method == "right-to-left" or method == "bottom-to-top":
reverse = True **# handle if we are sorting against the y-coordinate rather than
# the x-coordinate of the bounding box** if method == "top-to-bottom" or method == "bottom-to-top":
i = 1 **# construct the list of bounding boxes and sort them from top to
# bottom** boundingBoxes = [cv2.boundingRect(c) for c in cnts]
(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
key=lambda b:b[1][i], reverse=reverse)) **# return the list of sorted contours and bounding boxe**s
return (cnts, boundingBoxes) **# Sort all the contours by top to bottom.** contours, boundingBoxes = sort_contours(contours, method=”top-to-bottom”)
如何检索单元格的位置
需要进一步的步骤来定义每个单元的正确位置,这意味着正确的列和行。首先,我们需要检索每个单元格的高度,并将其存储在列表 heights 中。然后我们从高处取*均值。
**#Creating a list of heights for all detected boxes**
heights = [boundingBoxes[i][3] for i in range(len(boundingBoxes))]**#Get mean of heights**
mean = np.mean(heights)
接下来,我们检索每个轮廓的位置、宽度和高度,并将其存储在盒子列表中。然后我们在所有的盒子周围画出矩形,并绘制图像。在我的例子中,我只对宽度小于 1000 像素、高度小于 500 像素的盒子这样做,以忽略可能没有单元格的矩形,例如整个表格。这两个值取决于你的图像大小,所以如果你的图像变小或变大,你需要调整两者。
**#Create list box to store all boxes in**
box = []**# Get position (x,y), width and height for every contour and show the contour on image**
for c in contours:
x, y, w, h = cv2.boundingRect(c) if (w<1000 and h<500):
image = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
box.append([x,y,w,h])plotting = plt.imshow(image,cmap=’gray’)
plt.show()
由检测到的轮廓/方框包围的每个单元。
现在我们有了每个单元格,它的位置、高度和宽度,我们需要在表格中得到正确的位置。因此,我们需要知道它位于哪一行哪一列。只要一个盒子的差异不超过它自己的(高度+*均值/2 ),这个盒子就在同一行。一旦高度差高于当前值(高度+*均值/2),我们就知道新的一行开始了。列在逻辑上从左到右排列。
**#Creating two lists to define row and column in which cell is located** row=[]
column=[]
j=0**#Sorting the boxes to their respective row and column**for i in range(len(box)): if(i==0):
column.append(box[i])
previous=box[i] else:
if(box[i][1]<=previous[1]+mean/2):
column.append(box[i])
previous=box[i] if(i==len(box)-1):
row.append(column) else:
row.append(column)
column=[]
previous = box[i]
column.append(box[i])print(column)
print(row)
接下来,我们计算最大列数(意味着单元格),以了解我们最终的数据框架/表格将有多少列。
**#calculating maximum number of cells**countcol = 0
for i in range(len(row)):
countcol = len(row[i])
if countcol > countcol:
countcol = countcol
拥有最大数量的单元格后,我们将每列的中点存储在一个列表中,创建一个数组并对值进行排序。
**#Retrieving the center of each column**center = [int(row[i][j][0]+row[i][j][2]/2) for j in range(len(row[i])) if row[0]]center=np.array(center)
center.sort()
此时,我们有了所有的框和它们的值,但是正如您可能在您的行列表的输出中看到的,这些值并不总是按照正确的顺序排序。这就是我们下一步要做的,关于到列中心的距离。我们存储在列表最终框中的正确顺序。
**#Regarding the distance to the columns center, the boxes are arranged in respective order**finalboxes = []for i in range(len(row)):
lis=[]
for k in range(countcol):
lis.append([])
for j in range(len(row[i])):
diff = abs(center-(row[i][j][0]+row[i][j][2]/4))
minimum = min(diff)
indexing = list(diff).index(minimum)
lis[indexing].append(row[i][j])
finalboxes.append(lis)
让我们提取值
在下一步中,我们将使用我们的列表终结框。我们取每一个基于图像的盒子,通过扩张和腐蚀来为光学字符识别做准备,并让 pytesseract 识别包含的字符串。循环遍历每个单元格,并将值存储在外部列表中。
**#from every single image-based cell/box the strings are extracted via pytesseract and stored in a list**outer=[]
for i in range(len(finalboxes)):
for j in range(len(finalboxes[i])):
inner=’’
if(len(finalboxes[i][j])==0):
outer.append(' ') else:
for k in range(len(finalboxes[i][j])):
y,x,w,h = finalboxes[i][j][k][0],finalboxes[i][j][k][1], finalboxes[i][j][k][2],finalboxes[i][j][k][3]
finalimg = bitnot[x:x+h, y:y+w]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 1))
border = cv2.copyMakeBorder(finalimg,2,2,2,2, cv2.BORDER_CONSTANT,value=[255,255])
resizing = cv2.resize(border, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)
dilation = cv2.dilate(resizing, kernel,iterations=1)
erosion = cv2.erode(dilation, kernel,iterations=1)
out = pytesseract.image_to_string(erosion)
if(len(out)==0):
out = pytesseract.image_to_string(erosion, config='--psm 3')
inner = inner +" "+ out outer.append(inner)
最后一步是将列表转换成数据帧,并将其存储到 excel 文件中。
**#Creating a dataframe of the generated OCR list** arr = np.array(outer)
dataframe = pd.DataFrame(arr.reshape(len(row),countcol))
print(dataframe)
data = dataframe.style.set_properties(align="left")**#Converting it in a excel-file** data.to_excel(“/Users/YOURPATH/output.xlsx”)
终端中的最终数据帧。
包含所有单元格的最终 excel 文件。
就是这样!您的表格现在应该存储在数据帧和 excel 文件中,可用于自然语言处理、通过统计进行进一步分析或仅用于编辑。这适用于结构清晰简单的表格。如果你的表格有一个非常特殊的结构,在某种意义上说,许多单元格被组合在一起,单元格的大小变化很大,或者使用了许多颜色,那么这个算法可能必须被采用。此外,OCR 在识别计算机字体方面*乎完美。但是,如果您有包含手写输入的表格,结果可能会有所不同。
如果你把它用在你自己的桌子上,让我知道它是如何工作的。
请继续关注 Marius Hucker 的新文章。如果您还没有注册,您将创建一个中型帐户…
medium.com](https://medium.com/subscribe/@hucker.marius)
你喜欢这个故事?
支持我和我在这里的工作
亦读:
Python 系列的触觉指南
由 Unsplash 上的 chuttersnap 拍摄
Python 是一种功能强大的编程语言,具有动态语义,由被称为“python 之禅”的 19 条原则指导。这些原则列举如下:
谓美丽胜过丑陋。
显性比隐性好。简单比复杂好。
复杂总比复杂好。
扁*比嵌套好。
稀不如密。
可读性很重要。特例不足以特殊到违反规则。
虽然实用性胜过纯粹性。错误永远不会悄无声息地过去。
除非明确消音。
面对暧昧,拒绝猜测的诱惑。应该有一种——最好只有一种——显而易见的方法来做这件事。虽然这种方式一开始可能并不明显,除非你是荷兰人。
现在总比没有好。
虽然永远也不会比现在好。如果实现很难解释,这是个坏主意。
如果实现起来容易解释,这也许是个好主意。名称空间是一个非常棒的想法——让我们多做一些吧!”
如果我们不想违背 python 的原则,我们必须适当地充分存储我们的数据。Python 提供了一些内置的容器来帮助存储我们的数据,如列表、元组、集合、字典等。已经开发了几个模块,它们提供附加的数据结构来存储数据集合。Python 集合模块就是这样一个模块,它的目的是改进内置容器的功能。坚持 python 说“… 很难解释,这是个坏主意”的禅,我会进一步解释什么是模块。
模块化编程指的是将一个庞大、笨拙的编程任务分解成单独的、更小的、更易于管理的子任务或模块的过程。然后可以将各个模块拼凑在一起,创建一个更大的应用程序。
模块化代码的一些优势包括:
- 简单
- 可维护性
- 复用性
模块是包含 Python 定义和语句的文件,有助于实现一组函数。模块可以定义函数、类和变量。文件名是模块名加上后缀.py
。而包是堆叠在一起的相关模块的集合。它们也被称为图书馆。
Python 模块和 Python 包,两种便于模块化编程的机制。
收集模块
collections 模块提供了内置容器数据类型的替代方法,如 list、tuple 和 dict。在本文中,我们考虑 python 集合模块中六(6)种常用的数据结构。它们如下:
- 命名元组
- 双端队列
- 计数器
- 有序直接
- 默认字典
- 链式地图
回想起来,内置容器的概要如下。
- List 是一个有序的、异构的、可变的 python 容器。它是用“[]”创建的。
- Tuple 非常类似于一个列表,但有一个主要区别——它是不可变的。我们用括号“()”创建一个元组。
- 集合也类似于列表,只是它是无序的。它可以存储异构数据,并且是可变的。我们通过用花括号“{}”将数据括起来来创建一个集合。
- Dictionary 是一个无序的、异构的、可变的 python 容器。它与一个密钥对值相关联。它只能通过它的键进行索引。
- named tuple:‘named tuple’生成一个类似于元组的类,但是有命名条目。namedtuple 返回一个元组,其中包含元组中每个位置(索引)的名称,而不是一个数字。普通元组的一个最大问题是,你必须记住元组对象的每个字段的索引。
namedtuple 的代码段
2.dequee:dequee 是一个为插入和删除项目而优化的列表。我们可以把一个“队列”想象成一个列表,我们通常关心的是处理列表的末尾。
deque 的代码段
3.计数器:计数器是一个非常有用的对象。它对一些 iterable 中的元素进行计数,并返回一个类似字典的结构,其中包含每个元素的计数。
4.order dict:Python 字典没有自然的顺序,但是有时候让字典条目的属性通过排序来访问是很有用的。“OrderedDict”与“Dict”完全一样,但它会记住键的插入顺序。
5.字典的一个常见范例是处理丢失键的情况。defaultdict 的工作方式与 python 字典完全一样,只是当您试图访问一个不存在的键时,它不会抛出 KeyError。相反,它使用创建 defaultdict 时作为参数传递的数据类型的元素来初始化键。数据类型称为 default_factory。
- ChainMap: 这是用来合并几个字典,它返回一个字典列表。
我希望这篇文章能让你体会到 python 集合的重要性和应用,以便你能更频繁地使用它。感谢阅读。
一个关于巨人、机器学习药丸和汽车工业的故事
汽车中的人工智能
关于人工智能对世界上最重要的行业之一的影响的童话三部曲的大结局。
从前,有一个巨人。一个巨大而强大的巨人,每个人都知道这个巨人。然后,一位友好的仙女给了巨人一颗神奇的机器学习药丸。药丸承诺让巨人变得更加强大,但也给他带来了剧烈的疼痛。巨人吞下了药丸,成长的烦恼开始了。
这是这个关于机器学习对汽车行业影响的三部曲的最后一部。为了更好地说明复杂性和挑战,这个关于巨人和机器学习药丸的故事补充了主要观点。这些见解基于我在汽车行业的工作经验以及与来自世界各地的汽车专家的长期对话。三部曲分为以下几个部分:重要性(一)、机遇(二)、汽车行业在实现机器学习的超越性技术方面的挑战(三)。
这部分阐述了机器学习对汽车行业的挑战。成长的烦恼发生在以下几个部分:数据、基础设施、算法。让我们看看怎么做。
数据
汽车行业坐拥未来最宝贵的资源之一——数据。一辆配备现代传感器的汽车每天可以产生 4-10tb 的数据。最大的数据生产者是相机和激光雷达传感器。摄像机观察环境以检测物体或车道标志。激光雷达传感器有助于获得与其他物体的精确距离。机器学习有助于解释输入的数据。
让我们客观地看待产生的大量数据。如果你的智能手机有 256 GB 的存储空间,10 TB 的数据相当于 40 部智能手机每天的使用量。数据是机器学习的关键因素,教会算法学习什么。因此,访问大量数据是构建智能系统的先决条件。但这种过多的数据给汽车行业的存储、过滤和分析带来了新的挑战。
竞争对手,或者说小巨人,明白数据的价值。他们竞相收集公路上行驶的数百万英里。2019 年,电动汽车制造商特斯拉收集了超过 20 亿英里的数据。自动驾驶汽车公司 Waymo 在 2018 年 10 月已经超过了 1000 万英里大关。此外,这些公司已经在模拟中驾驶数十亿英里。Elon Musk 声称特斯拉目前收集了所有收集的汽车数据的 99.5% 。今天有超过 50 万辆配备摄像头的特斯拉汽车在行驶。然而,曲棍球棒曲线在收集英里是最令人印象深刻的。小巨人拥有创建成功的机器学习算法的原材料。
然而,价值并不在于纯粹的记录数据量。训练机器学习算法需要多样化的数据集。在红灯前站几个小时记录数据会产生大量数据,但价值有限。关键是收集智能数据。角落案例数据尤其有价值,例如,一个孩子在追球时突然穿过街道。在这些情况下,您需要 100%确定算法运行正确。
为了测试非正统的情况,Waymo 首席执行官约翰·克拉夫茨克(John Krafcik)公开描述了他们如何测试不寻常的场景。据说约翰装扮成芝麻街里的大鸟,看看汽车是否会停下来!让一只大鸟穿过街道肯定是汽车以前没有见过的情况,但它仍然应该停下来。
理解了处理数据的挑战之后,让我们继续讨论让机器学习工作所必需的基础设施。
基础设施
具有智能功能的汽车需要先进的传感器来感知环境。根据 Udacity 的估计,制造一辆研究车可能要花费 25 万美元以上。为卡车配备足够的传感器以实现自动驾驶功能需要花费数百万美元。
最昂贵的传感器是顶级激光雷达,大约 12 万美元。一旦激光雷达传感器大规模生产,成本预计将大幅下降。Waymo 出售其自主开发的激光雷达传感器 Honeycomb,,他们声称这可以降低 90%的成本。大多数汽车公司都同意,激光雷达是安全高级驾驶功能所必需的。特斯拉省略了传感器,著名的称之为【拐杖】。
一个主要的突破点是量产汽车制造商的成本敏感性。大众或丰田等公司的新车利润率只有 5%左右。所以,如果你花 25.000 美元买了一辆车,公司只有 500 美元的利润。插入新的传感器会立即降低企业的盈利能力。将传感器成本降低到仍然能够实现人工智能驱动功能的水*仍然是一个挑战。
此外,考虑下图。它没有显示一个不断演变的组织结构图。的。gif 展示了自 20 世纪 70 年代以来现代汽车电子架构的演变。如您所见,架构变得越来越复杂,越来越难以维护。
即使该架构使用了与 Kubernetes 协调的微服务,它仍然非常复杂。请记住,汽车从来都不是纯粹的软件产品,它们与关键硬件相互作用。这使得收集数据和集成机器学习算法成为一项复杂的挑战。
让我们看看在机器学习的帮助下使巨人成长的最后一块拼图。
算法
在汽车功能中包含机器学习算法带来了新的挑战。传统的编程被认为是安全的,因为它的确定性地工作。机器学习被认为是不安全的,因为它的操作是概率性的。
想想声称神经网络可以根据一个人的脸来检测他是否是罪犯的研究。除了这项研究的道德和伦理风险,它被证明是完全错误的。
研究人员以不同的方式从罪犯和非罪犯那里收集输入数据。他们从政府颁发的罪犯身份证上获取面部图像。另一方面,他们从一个公共网站上获取非罪犯的面部图像。现在,谁会愿意把自己的身份证照片放在个人资料上呢?我在护照照片上看起来确实像个罪犯!本质上,该算法学会了区分政府 ID 和你的 LinkedIn 个人资料图片,而不是区分罪犯和非罪犯。
另一个值得警惕的例子来自加州大学欧文分校。一名学生训练了一个神经网络来区分哈士奇和狼。这个学生很高兴在这个任务中达到了 94%的准确率。然后教授问学生,他怎么能确定网络学到了它应该学的东西?分析数据后,该小组发现了关键的区别点。大多数哈士奇图片的背景是雪,而狼图片的背景是没有雪的。本质上,算法并没有学会区分哈士奇和狼,而是在后台区分“下雪”和“没下雪”。
这些例子表明,理解算法学习什么对开发安全函数很重要。功能开发人员必须确保他们的算法在驾驶车辆绕过人类时能够按预期工作。该行业需要对输入数据进行清晰的检查,以及测试和批准基于机器学习的功能的清晰流程。
结局(三)
通过这个童话,我希望你能更好地理解汽车巨头实施机器学习的当前机遇和挑战。这种机器学习药丸可以让巨人变得如此强大,但也会带来剧烈的疼痛。
谢谢你跟随巨人的旅程!然而,这个故事远未结束。巨人需要你来帮助它处理成长的烦恼。鉴于这个行业的重要性,我希望你能考虑加入这个巨人的故事。加入巨人,帮助它处理痛苦,这是最激动人心的时刻。
如果你喜欢这个故事,你可以在这里重读童话三部曲。第一部分讨论了汽车工业的重要性,第二部分解释了未来的机遇。
这个故事是在数据节 2019 上呈现的。点击此处查看本次演讲的视频。如果你想听更多关于商业、项目管理和数据科学的交集,在 Medium 、 LinkedIn 或 Twitter 上关注 me。
一个关于巨人、机器学习药丸和汽车工业的故事
汽车中的人工智能
关于人工智能对世界上最重要的行业之一的影响的童话三部曲的第二个故事。
从前,有一个巨人。一个巨大而强大的巨人,每个人都知道这个巨人。人们为巨人工作,为自己和他人创造巨大的财富。然后,巨人从一个友好的仙女那里收到了一颗神奇的机器学习药丸,承诺让巨人变得更加强大。
这是这个关于机器学习对汽车行业影响的三部曲的第二部。为了更好地说明在老牌汽车制造商中使用机器学习的复杂性和挑战,这个关于巨人和神奇药丸的故事补充了主要观点。这些见解基于我在汽车行业的工作经验以及与来自世界各地的汽车专家的长期对话。三部曲分为以下几个部分:重要性(一)、汽车行业在实现机器学习这一超越性技术方面的机遇(二)、挑战(三)。
第二部分详细阐述了机器学习药丸可以给巨人带来的机会。它承诺让这个巨人变得更大更强大。让我们看看怎么做。
自动驾驶
今天,汽车由人类驾驶,从一个地方到达另一个地方。机器学习是一项关键技术,可以让人们或货物自动驾驶到目标目的地。这就是所谓的自动驾驶(AD)。
AD 允许创建多种应用程序。机器人轴立即浮现在脑海中,它在城市环境中运送人们。谷歌子公司 Waymo 被视为未来城市交通的领跑者。2019 年,该公司开始在亚利桑那州凤凰城测试其自动驾驶出租车服务,车辆中没有安全驾驶员。
然而,AD 要大得多,不仅允许人类自主地从 A 地运输到 B 地,还允许货物运输。汽车制造商大众承认,物流行业对自动驾驶的需求最为迫切。因此,它将大众汽车自主有限公司从其商用车子公司中剥离出来。在物流业务中,三个主要的成本构成是车辆价格、汽油和工资。降低薪资成本最能提高物流行业的盈利能力。
AD 技术还支持其他用例,如斯堪尼亚的 自主运输设备、采矿卡车、拖拉机或任何其他工作车辆。重型设备制造商 John Deere 已经研发半自动拖拉机 20 年了。在一些农田需要一整天犁一条线的地方,自动拖拉机有望带来巨大的好处。
自动驾驶车辆承诺打破车辆的神奇产品三角。产品三角形表明,你应该致力于在短时间内,以高质量和低成本创造任何产品。你可以沿着神奇的产品三角排列任何产品。当今汽车的产品三角如下。
汽车可以在短时间内把人或货物从 A 地送到 B 地,成本低,质量合理。AD 提供了将每种产品的能力扩展到可以想象的最大限度的机会。
打车公司优步估计,无人驾驶汽车可以将每英里费用从 T2 的 2.86 美元降低到仅 0.35 美元。这种几乎 90%的成本降低提高了产品三角的成本能力。AD 通过让司机有时间在车内阅读、睡觉或工作,潜在地提高了乘坐的质量。当卡车可以自主移动时,卡车司机所需的休息时间也可以减少到最低限度。AD 扩展了移动车辆的所有产品功能,从而为客户满意度和公司发展提供了巨大的机会。
鉴于人们对广告的极度兴奋,消费者期待着无人驾驶汽车的到来。主要汽车制造商宣布了自主打车服务的雄心勃勃的开始日期,从而加剧了这种兴奋。电动汽车制造商特斯拉宣布其计划在 2019 年年底推出自动驾驶班车服务。这一切似乎都很容易,到处都有关于自动驾驶汽车的精彩玩具视频。此外,在线学习*台 Udacity 从 2011 年开始提供自动驾驶汽车工程师纳米学位。创业公司如此接*解决 AD 的故事比比皆是,就像下面这个。
谷歌正在研究自动驾驶汽车,他们似乎也在努力。人们在驾驶汽车方面如此糟糕,以至于计算机不必那么好就能好得多。— 马克·安德森,风险投资家于 a16z , NYT 2011
硅谷著名企业家、 comma ai 创始人乔治·霍兹,在 2016 年底差点提供自动驾驶功能。乔治入侵了一辆 Acure 汽车,给它配备了一部智能手机,让它的摄像头透过挡风玻璃对准前方的道路。然后他突然打方向盘、加速和刹车信号来操纵汽车。点击此处查看open pilot 发布视频。Comma.ai 开始以 999 美元的价格出售广告硬件,外加每月订阅费。在第三部分,你会听到这个故事是如何展开的。
不管这些雄心勃勃的声明,许多汽车制造商已经推迟了将广告投放市场的时间表。机器学习是帮助这家巨头创造变革性新产品的关键促成因素。让我们调查一下机器学习药丸如何帮助这个巨人带来另一个基石产品。
个人助理
让我们假设有一天自动驾驶能力无处不在。那么是什么将一辆车与另一辆区分开来呢?越来越多的关注将转向室内用户体验。
如今,汽车驾驶舱是手动操作的。按钮和旋钮让驾驶员无法选择操纵汽车设置。想提高汽车温度?打开空调,向右转动两个轮子以提高目标温度,并增大风扇。四个步骤,为了一个目的。机器学习使汽车能够预测用户需求,并立即满足基于语音的请求。
机器学习是实现汽车个人助理的关键技术。这个助手可以学习司机喜欢的温度,并自动调整汽车的设置。用户通过语音与汽车互动,省略了按钮和旋钮。
据 Samsung Next 报道,风险投资者对投资*台感兴趣。正如、 Greylock Partners 的风险投资人 Sarah Guo 在 2018 人工智能前沿大会期间提到的,互联网*台催生了谷歌或脸书这样的独角兽。移动作为下一个*台推动了像 Lyft 或 AirBnB 这样的公司达到独角兽的估值。自动驾驶汽车会成为下一个*台,推动独角兽游戏、娱乐或 VR/AR 初创企业的崛起吗?
机器学习为汽车公司提供了巨大的新产品机会。个人助理和自动驾驶只是机器学习使之成为可能的少数面向客户的应用。在智能生产、RPA 和营销领域存在更多机会。
回到故事。现在,这位巨人明白了这种神奇的机器学习药丸是如何让它变得更大更强的。但是巨人仍然在思考经历这些成长的烦恼是否值得。毕竟,它是世界上最强大的巨人之一,不怕任何人。然后,在远处的地*线上,巨人发现了一个小巨人。走*小巨人,巨人意识到它一直在享用机器学习药丸。小巨人还不会走路,但很明显,一旦它长到最大力气,它就能轻而易举地打败巨人。接下来我们来检查一下小巨人。
竞争对手
以下两张图表值得你高度关注。下图显示了六家移动公司的公司估值。Waymo 目前的估值最高,为1050 亿美元。特斯拉的股票一直不稳定,仅在过去的两个月里,公司价值在 2020 年 1 月就翻了一番,达到约 810 亿美元。像 Waymo、优步或特斯拉这样的公司代表了这个小巨人。这个巨人的代表是大众、宝马或戴姆勒这样的汽车巨头。
Waymo 的估值超过了所有其他公司的估值。在获得一美元收入之前,它的价值已经高于宝马和戴姆勒的总和。 Waymo 的技术非常依赖机器学习来创造世界上最安全的司机。优步和泰斯拉的估值也受到他们努力将广告变成现实的推动。优步创始人特拉维斯·卡兰尼克称自动驾驶汽车是优步未来最重要的技术。特斯拉著名的自动驾驶功能完全依靠机器学习来检测物体,并使汽车保持在车道上。
相比之下,下图显示了每家公司达到预期估值所需的员工数量。2018 年,Waymo 勉强跨过了 1000 名员工的大关。另一个极端是,大众汽车目前在全球雇佣了超过 66 万名员工。你可以看到这个小巨人比巨人需要更少的员工来创造惊人的市场估值。
现在,让我们不要不公*。汽车制造商今天生产有形的价值。他们每年销售数千万辆汽车。如果自动驾驶汽车技术没有得到验证,投资者将会损失很多钱,但也仅此而已。但是如果它被证实了呢?
又怕又急,巨人吞下了苦涩的机器学习药丸。
结局(二)
这篇文章展示了通过机器学习药丸可以实现的变革机会。虽然巨人仍然对服用这种药丸犹豫不决,但其他一直在享用这些机器学习药丸的小巨人看到他们的力量爆炸了。
接下来会发生什么,当巨人吞下药丸,对它的身体造成严重压力?继续在这里(即将于 1 月 19 日)阅读在这个成熟的行业中实现机器学习的挑战和副作用。重读三部曲开篇这里。
这个故事是在数据节 2019 上呈现的。点击此处查看本次演讲的视频。如果你想听更多关于商业、项目管理和数据科学的交集,在 Medium 、 LinkedIn 或 Twitter 上关注 me。
一个关于巨人、机器学习药丸和汽车工业的故事
汽车中的人工智能
打开童话三部曲,讲述人工智能对世界上最重要的行业之一的影响。
从前,有一个巨人。一个巨大而强大的巨人,每个人都知道这个巨人。它有一种相当特殊的气味,对环境有害,但那是另一回事了。世界各地的人们热爱这个巨人,顺从地为它工作。
一天,一个仙女飞向巨人。仙女给了巨人一颗药丸,并说:“这颗机器学习药丸是来自一个很远很远的地方的强大魔术师创造的。它会给你巨大的力量,但是要小心,它也会给你带来严重的痛苦。".
图片由 Pixabay 上的 Oberholster Venita 拍摄
这是这个关于机器学习对汽车行业影响的三部曲的第一部。为了更好地说明在老牌汽车制造商中使用机器学习的复杂性和挑战,这个关于巨人和神奇药丸的故事补充了主要观点。这些见解基于我在汽车行业的工作经验以及与来自世界各地的汽车专家的长期对话。该三部曲分为以下几个部分:汽车行业在实施机器学习的卓越技术方面的重要性(I)、机遇(II)和挑战(III)。
让我们在第一部分集中讨论为什么这个童话的主角是一个巨人而不是一只乌龟或小马。虽然汽车行业可能面临严峻的挑战,但你为什么要在乎呢?让我们看看汽车行业的经济、社会和未来影响。
汽车工业的经济影响
汽车行业是世界上最重要的行业之一。为了证明这一点,让我们来看看对世界 GDP 贡献最大的四个国家中的两个,美国和德国,以及汽车行业在其中的重要性。
下图显示了按行业分组的上市公司的市值。市值表明市场认为某个公司或行业有多大价值。它的计算方法是将当前股票价格乘以发行在外的股票数量。例如,美国大型汽车制造商通用汽车的股票在2019 年 12 月 30 日今天的价格是 36.56 美元。该公司有 14.3 亿股流通股。因此,通用汽车的市场价值为 36.56 美元* 1.43 亿美元= 52.28 亿美元。
如果你把美国所有汽车行业公司的市值加起来,你会得到 8000 亿美元的行业估值。如上图所示,汽车工业比航空业或烟草业更重要。软件业的价值远远高于所有其他行业。对汽车行业未来发展方向的暗示?尽管如此,图表显示了汽车行业对世界最大经济体的重要性。
接下来,让我们考虑一下汽车行业对世界第四大经济体德国的重要性。
德国拥有全球汽车公司,如大众、宝马、戴姆勒、大陆或博世。他们的总市值超过了 2000 亿€,略微超过了化学工业的头把交椅。德国经济的主要驱动力是汽车。
在理解了汽车工业的经济影响之后,让我们更个人化地评价一下汽车工业对全球就业的社会影响。
汽车工业的社会影响
根据国际汽车制造商组织的数据,全球汽车行业雇佣了超过 900 万人在 T2 工作。此外,汽车行业创造了一个相邻企业的生态系统。汽车经销商、保险公司或洗车店依赖于汽车工业的持续运转。如果算上在汽车相邻企业工作的人,超过 5000 万人间接受雇于汽车行业。这相当于 60 个工作成年人中有 1 个。
如果我们比较德国的数据,我们会发现类似的分布。德国汽车工业协会估计超过 80 万人直接受雇于汽车工业,* 200 万人间接受雇于汽车工业。在德国,依赖汽车行业的成年人中有 1/50 的比例更为极端。
在了解了汽车行业对你或你邻居的薪水有多重要之后,让我们来看看汽车行业的现状和未来预测。
汽车工业的前景
根据丰业银行 2019 年的报告,过去 5 年来,全球汽车销量一直持*。自 1990 年以来,汽车行业取得了巨大的增长,汽车销量在 15 年内翻了一番。然而,这种增长停滞不前,尤其是富裕市场的需求停滞不前,正如下面的按地区分列的大众汽车销量信息图所示。一些希望在于南美等新兴市场需求的上升,但尚不清楚它们是否能弥补现有市场的增长不足。为了扩大业务和市值,汽车公司可以做些什么?
另一方面,全球对移动解决方案的需求预计将在未来十年内激增。 Statista 估计对打车、公共交通或航班等服务的需求将继续增长。对于一些客户来说,共享移动解决方案而非所有权将变得更具吸引力。抓住这个机会,一些汽车公司开始将自己重新定位为移动提供商。例如,宝马的企业使命是“塑造明天的个人高级流动性”,而不是生产汽车。
总而言之,目前全球汽车销售停滞不前,而对移动性的需求却在增加。汽车行业在寻找发展和繁荣的机会方面面临着严峻的挑战。机器学习药丸能延长巨人的寿命并帮助它成长为新的力量吗?
结局(一)
第一部分向您展示了汽车行业有多重要,以及您为什么应该关注它。汽车巨头就在我们身边,影响着许多人的生活。
继续下一集(将于 1 月 12 日播出),阅读机器学习药丸对巨人的影响。最后一部分(将于 1 月 19 日发布)详细阐述了在这个成熟的行业中实施机器学习的挑战和副作用。
这个故事是在数据节 2019 上呈现的。点击这里可以找到这个演讲的视频。如果你想了解更多关于商业、项目管理和数据科学的交集,在 Medium 、 LinkedIn 或 Twitter 上关注我。
TF Lite 中模型量化的故事
生产中的机器学习
模型优化策略和量化技术,帮助在资源受限的环境中部署机器学习模型。
在此与结果仪表板互动。
最新的机器学习模型通常体积庞大,这使得它们在资源受限的环境中部署时效率低下,如移动电话、树莓 pi、微控制器等。即使您认为您可以通过在云上托管您的模型并使用 API 来提供结果来解决这个问题,也要考虑到互联网带宽可能并不总是很高,或者数据不能离开特定设备的受限环境。
我们需要一套工具来无缝过渡到设备上的机器学习。在这篇报道中,我将向你展示 TensorFlow Lite (TF Lite) 如何在这种情况下大放异彩。我们将讨论 TensorFlow 支持的模型优化策略和量化技术。
感谢 Arun 、 Khanh 和 Pulkit (谷歌)为这篇报道分享了非常有用的技巧。
不同量化实验之间的性能概述(此处可用
概观
在本文中,我们将涵盖以下主题
- 对设备上机器学习的需求
- TensorFlow 支持的模型优化策略
- 量化技术
- 执行量化时需要记住的事项
对设备上机器学习的需求
在他们的演讲tensor flow Lite:ML for mobile and IoT devices(TF Dev Summit ' 20)中,Tim Davis 和 T.J. Alumbaugh 强调了以下几点:
- 更低的延迟&紧密互动:在许多关键应用中,你可能希望预测的延迟为零,例如无人驾驶汽车。您可能还需要保持系统的所有内部交互非常紧凑,这样就不会引入额外的延迟。
- 网络连接:正如我之前提到的,当你依赖云托管模式时,你实际上是将你的应用程序限制在一定的网络带宽水*上,而这可能并不总是能够实现的。
- 隐私保护:对隐私有硬性要求,例如,数据不能离开设备。
为了使大型 ML 模型能够部署在小型设备上,我们需要对它们进行优化,例如,将 1.9GB 的模型放入 2GB 的应用程序中。为了帮助 ML 开发者和移动应用开发者,TensorFlow 团队提出了两个解决方案:
TensorFlow 支持的模型优化策略
通过 TensorFlow Lite 和模型优化工具包,TensorFlow 目前支持以下模型优化策略-
- 量化你可以使用不同的低精度格式来减小模型的大小。
- 修剪在这里,您可以丢弃模型中对模型预测意义不大的参数。
在本文中,我们将重点讨论量子化。
量化技术
通常,我们的机器学习模型以float32
精度格式运行。所有模型参数都以这种精度格式存储,这通常会导致模型更重。模型的重量与模型进行预测的速度直接相关。因此,你可能会自然而然地想到,如果我们能降低模型运行的精度,我们就能减少预测时间。这就是量化的作用——它将精度降低到更低的形式,如 float16、int8 等,来表示模型的参数。
量子化可以以两种方式应用于一个模型
- 训练后量化在训练后应用于模型。
- 量化感知训练通常对模型进行训练,以补偿量化可能带来的精度损失。当您降低模型参数的精度时,可能会导致信息丢失,您可能会看到模型的精度有所降低。在这些情况下,感知量化的训练会非常有帮助。
我们将在这份报告中看到这两种味道。我们开始吧!
实验设置
我们在这份报告中做的所有实验都是在 Colab 上进行的。我使用 flowers 数据集进行实验,并微调了一个预先训练好的 MobileNetV2 网络。这是定义网络架构的代码-
对网络进行 10 个时期的训练,批次大小为 32。
正常微调下的性能
运行页面可用此处
所有这些文件都可以在这里找到
我们看到网络运行良好,达到 35.6 MB。
量化微调后的模型
当你在tf.keras
中训练好一个模型后,量化部分只是几行代码的事情。所以,你可以这样做-
首先将您的模型加载到一个TFLiteConverter
转换器类中,然后指定一个优化策略,最后,您要求 TFLite 使用优化策略转换您的模型。序列化转换后的 TF Lite 文件非常简单
这种量化形式也被称为训练后动态范围量化。它将模型的权重量化到 8 位精度。在这里你可以找到关于这个和其他训练后量化方案的更多细节。
关于为转换设置配置选项的说明
TF Lite 允许我们在转换模型时指定许多不同的配置。我们在前面提到的代码中看到过一次这样的配置,其中我们指定了优化策略。
除了tf.lite.Optimize.DEFAULT
,还有另外两个政策可供选择- tf.lite.Optimize.OPTIMIZE_FOR_SIZE
& tf.lite.Optimize.OPTIMIZE_FOR_LATENCY
。从名称中可以看出,基于策略的选择,TF Lite 会相应地尝试优化模型。
我们可以指定其他事情,比如-
target_spec
representative_dataset
点击了解更多关于TFLiteConverter
类的信息。值得注意的是,这些不同的配置选项允许我们在模型的预测速度和准确性之间保持*衡。在这里,你可以找到 TF Lite 中不同训练后量化方案的一些权衡。
下面我们可以看到这个转换模型的一些有用的统计数据。
餐桌可用此处
我们看到模型的规模大幅缩小,但这是以准确性为代价的。理想情况下,我们不希望转换后的模型精度损失这么大。这表明,我们需要探索其他量化方案,以进一步提高转换模型的准确性。
具有相同模型的量化感知训练(QAT)
这里一个好的第一个方法是训练你的模型,让它学会补偿可能由量化引起的信息损失。通过量子化感知训练,我们可以做到这一点。为了以量化感知的方式训练我们的网络,我们只需添加以下代码行-
现在,你可以像训练一个tf.keras
模型一样训练qat_model
。在这里你可以找到 QAT 的全面报道。
下面,我们可以看到这个量化感知模型比我们之前的模型稍好一些。
运行可用的这里
QAT 与非 QAT 模型的简要比较
就模型大小而言,QAT 模型与非 QAT 模型相似:
请记住,这些文件可以在任何运行的“文件”选项卡下找到
但是在模型训练时间方面,我们看到 QAT 模型需要更多的时间。这是因为在 QAT 过程中,模型中引入了伪量化节点来补偿信息损失,这使得 QAT 模型需要更多的时间来收敛。
在优化收敛时间的情况下,记住这一点很重要。如果你的训练模型需要很长的训练时间,那么引入 QAT 会进一步增加这个时间。
量化 QAT 模型与我们在上一节中看到的完全相同(我们将使用相同的量化配置)。
现在让我们比较量化版本的 QAT 模型的性能。
模型训练时间的比较
评估量化的 QAT 模型
在下表中,我们看到量化版本的 QAT 模型确实比以前的模型表现得更好。
此处可用的表为
我们清楚地看到,用 QAT 训练的模型没有引起任何精度下降。在下一节中,我们将把两个模型的参数都保持为浮点数,看看我们能在多大程度上推动模型大小和准确性之间的权衡。
量化为浮动模型
为了将我们的模型量化到浮点精度,我们只需要丢弃这条线— converter.optimizations = [tf.lite.Optimize.DEFAULT]
。如果你想利用 GPU 代理,这个策略尤其有用。注意, float16 量化在 TensorFlow Lite 中也是支持的。在下表中,我们可以看到使用该方案量化的模型的大小和精度。
此处可用的表为
虽然这些型号的尺寸有所增加,但我们看到这些型号的原始性能仍然很高。注意,不建议使用这种方案转换 QAT 模型,因为在 QAT 期间,插入的伪量化运算具有int
精度。因此,当我们使用这种方案量化 QAT 模型时,转换后的模型可能会出现不一致。
此外,硬件加速器,如边缘 TPU USB 加速器,将不支持浮动模型。
探索其他量化方案和总结思路
还有其他训练后量化技术可用,如全整数量化、浮点量化等。这是你可以了解他们更多的地方。请记住,全整数量化方案可能并不总是与 QAT 模型兼容。
有许多 SoTA 预训练的 TF Lite 模型可供开发人员在其应用中使用,它们可以在以下位置找到:
- https://www.tensorflow.org/lite/guide/hosted_models
- https://tfhub.dev/s?deployment-format=lite&publisher = tensor flow&q = lite
对于希望在应用程序中集成机器学习的移动开发人员来说,TF Lite 中有许多示例应用程序值得一试。TensorFlow Lite 还为嵌入式系统和微控制器提供工具,您可以从这里了解更多信息。
如果您想重现此分析的结果,您可以–
双城记!(用数据讲故事)
基于 Foursquare 数据和机器学习的城市对比分析
关键词:数据科学、机器学习、Python、网络抓取、Foursquare
图片来源:【https://www.sussexscenes.co.uk/view-shard-london/
【https://br.pinterest.com/pin/92816442292506979/
这篇文章涵盖了在 IBM 数据科学专业 课程中用于最终顶点项目的方法和分析。详细的报告、代码和结果可以在 Github 上找到,并在文章末尾有链接。
1。简介
当谈到伦敦和巴黎时,选择一个城市总是一个艰难的决定,因为这两个城市都是真正的全球化、多元文化和国际化城市,位于两个欧洲国家的中心。除了作为欧洲两个最重要的外交中心,它们还是金融、商业、科学、时尚、艺术、文化和美食的主要中心。伦敦(英国首都)和巴黎(法国首都)都有着丰富的历史,是欧洲游客最多、最受欢迎的两个城市。伦敦是英国最大的城市,位于英格兰东南部的泰晤士河畔。另一方面,巴黎位于国家的中北部。与伦敦相似,这座城市也坐落在一条通常被称为塞纳河的河边。
我们的目标是对这两个城市进行比较,看看它们有多相似或不相似。这种技术使用户能够根据当地提供的便利设施或服务来确定城市中的类似社区,从而有助于了解当地的活动,不同活动的中心是什么,市民如何体验城市,以及他们如何利用城市资源。
什么样的客户会从这样的分析中受益?
- 具有可转移技能的潜在求职者可能希望在特定的城市寻找工作,这些城市在工资、社会福利,甚至在适合外籍人士的文化方面,为他们的资格和经验提供最合适的匹配。
- 此外,在新城市购买或租赁房屋的人可能想要寻找该城市中与他们所知的其他城市相似的位置的推荐。
- 类似地,一家希望将其地点扩展到其他城市的大公司可能会从这种分析中受益。
- 许多市内城市规划计算也可能受益于模拟一个城市与其他城市的关系。
2。数据准备
为了解决手头的问题,数据提取如下进行:
网络抓取: 城市数据是使用请求和 BeautifulSoup 库从各自的维基百科页面【1】【2】中提取的。
*## URL to extract City neighbourhood information*
urlL = "https://en.wikipedia.org/wiki/List_of_London_boroughs"
urlP = "https://en.wikipedia.org/wiki/Arrondissements_of_Paris"
pageLondon = urllib.request.urlopen(urlL)
pageParis = urllib.request.urlopen(urlP)wikitablesL = read_html(urlL, attrs={"class":"wikitable"})
print ("Extracted **{num}** wikitables from London Wikipedia".format(num=len(wikitablesL)))
wikitablesP = read_html(urlP, attrs={"class":"wikitable"})
print ("Extracted **{num}** wikitables from Paris Wikipedia".format(num=len(wikitablesP)))dfP = wikitablesP[0]
dfL0 = wikitablesL[0]
dfL1 = wikitablesL[1]*## Request & response*
s = requests.Session()
responseL = s.get(urlL,timeout=10)
对提取的数据执行进一步的数据清理,以便存储关于其邻*地区、其相应的坐标、面积和人口以及相应的区编号的相关信息。
**def** scrapeLondonTable(table):
c1=[]
c2=[]
c3=[]
c4=[]
c5=[]
c6=[]
c7=[]
c8=[]
c9=[]
c10=[]
c11=[]
**for** row **in** table.findAll("tr"):
cellsL = row.findAll('td')
**if** len(cellsL)==10: *#Only extract table body not heading*
c1.append(cellsL[0].find('a').text)
c2.append(cellsL[1].find(text=**True**))
c3.append(cellsL[2].find(text=**True**))
c4.append(cellsL[3].find(text=**True**))
c5.append(cellsL[4].find(text=**True**))
c6.append(cellsL[5].find(text=**True**))
c7.append(cellsL[6].find(text=**True**))
c8.append(cellsL[7].find(text=**True**))
c9.append(cellsL[8].find('span',{'class': 'geo'}))
c10.append(cellsL[9].find(text=**True**))
*# create a dictionary*
d = dict([(x,0) **for** x **in** headerL])
*# append dictionary with corresponding data list*
d['Borough'] = c1
d['Inner']= c2
d['Status']=c3
d['Local authority']=c4
d['Political control']=c5
d['Headquarters']=c6
d['Area (sq mi)']=c7
d['Population (2013 est)[1]']=c8
d['Co-ordinates']=c9
d[' Nr. in map']=c10
*# convert dict to DataFrame*
dfL_table = pd.DataFrame(d)
*## convert Area units to kms^2*
*#dfL["Area"] = 2.59 * (pd.to_numeric(dfL["Area"]))*
Latitude = []
Longitude = []
**for** i **in** range(len(dfL_table)):
locationSplit = dfL_table['Co-ordinates'].iloc[i].getText().split("; ")
Latitude.append(locationSplit[0])
Longitude.append(locationSplit[1])
dfL_table['Latitude'] = Latitude
dfL_table['Longitude'] = Longitude
dfL_table.drop(['Inner','Status','Local authority','Political control','Headquarters','Co-ordinates'],axis=1,inplace=**True**)
dfL = dfL_table.rename(columns={'Area (sq mi)': 'Area', 'Population (2013 est)[1]': 'Population',' Nr. in map':'District Number'})
dfL['District Number'] = dfL['District Number'].astype(int)
**for** i **in** range(len(dfL)):
dfL['Area'].iloc[i] = float(re.findall(r'[\d\.\d]+', dfL['Area'].iloc[i])[0])
dfL['Population'].iloc[i] = int(dfL['Population'].iloc[i].replace(',',''))
**return** dfL
在必要的数据清理之后,我们获得了以下用于研究的数据框架:
伦敦市区列表。
巴黎市的区列表(1-4 区合并为 1 区)。
Foursquare 位置数据: Foursquare 是一个社交位置服务,允许用户探索周围的世界。Foursquare API 提供了基于位置的体验,包含关于地点、用户、照片和签到的各种信息。我们利用 Foursquare 数据来提取所有被研究社区的基于地点的信息。对 API 的调用返回一个 JSON 文件,我们需要将它转换成数据帧。然后,位置数据被用来在每个街区寻找顶级和独特的场地。我决定在方圆 1 公里内的每个街区挑选 100 个最受欢迎的景点。
3.探索性数据分析
城市数据
维基百科的数据为我们提供了各个城市中每个行政区的坐标、面积和人口信息。人们可以利用这一信息来绘制一张城市地图,根据人口密度标出每个行政区。 Geocoder 和“leave map库用于活页地图上的数据可视化,根据人口密度标记行政区。密度越高,标记的半径越大。
基于人口密度的伦敦(左)和巴黎(右)地图。(注:伦敦地图上的标记已按 1/1000 的比例缩小,巴黎地图上的标记已按 1/2000 的比例放大)。
场馆数据
Foursquare 的位置数据给出了每个区 1 公里半径内的地点列表信息。这是了解街区特征的合理距离。
## Extracting Foursquare venue data
LIMIT = 100 *# limit of number of venues returned by Foursquare API*
radius = 1000 *# define radius*
**def** getNearbyVenues(names, latitudes, longitudes, radius=500):
venues_list=[]
**for** name, lat, lng **in** zip(names, latitudes, longitudes):
print(name)
*# create the API request URL*
url = 'https://api.foursquare.com/v2/venues/explore?&client_id=**{}**&client_secret=**{}**&v=**{}**&ll=**{}**,**{}**&radius=**{}**&limit=**{}**'.format(
CLIENT_ID,
CLIENT_SECRET,
VERSION,
lat,
lng,
radius,
LIMIT)
*# make the GET request*
results = requests.get(url).json()["response"]['groups'][0]['items']
*# return only relevant information for each nearby venue*
venues_list.append([(
name,
lat,
lng,
v['venue']['name'],
v['venue']['location']['lat'],
v['venue']['location']['lng'],
v['venue']['categories'][0]['name']) **for** v **in** results])
nearby_venues = pd.DataFrame([item **for** venue_list **in** venues_list **for** item **in** venue_list])
nearby_venues.columns = ['Borough',
'Borough Latitude',
'Borough Longitude',
'Venue',
'Venue Latitude',
'Venue Longitude',
'Venue Category']
**return**(nearby_venues)print("Getting venues inside the following Boroughs of London:")
London_venues = getNearbyVenues(names=tableL['Borough'],
latitudes=tableL['Latitude'],
longitudes=tableL['Longitude']
)
伦敦总共有大约 219 个独特的场馆类别,巴黎有 180 个。我用这些信息在一个条形图上显示了伦敦市中心和巴黎市中心区的一些最常见的场馆。
*## Picking major districts inside inner London and inner Paris respectively*
districtsL = ['City of London','Westminster','Kensington and Chelsea','Hammersmith and Fulham', 'Wandsworth']
districtsP = ['Louvre, Bourse, Temple, Hôtel-de-Ville', 'Panthéon', 'Luxembourg', 'Palais-Bourbon', 'Élysée']
**def** nearbyvenues_count(venues_df, district):
venues_count = venues_df
venues_count = venues_count.rename(columns={'Venue Category': 'Category'})
venues_count = venues_count.groupby(['Borough']).Category.value_counts().to_frame("Counts")
fig, ax = plt.subplots(1,1,figsize=(20, 7))
fig.subplots_adjust(left=0.115, right=0.88)
venues_plot = venues_count['Counts'].loc[district][:10].head(10)
pos = np.arange(len(venues_plot))
ax.set_title(district,size=20)
freqchart = ax.barh(pos, venues_plot,align='center',height=0.5,tick_label=venues_plot.index)
**return** freqchart
伦敦内城区(上图)和巴黎内城区(下图)最常见的比赛场地。
虽然伦敦市中心最常见的场所在咖啡馆/咖啡店、酒吧、果汁吧或酒店之间,但在巴黎市中心或主要地区的行政区,最常见的场所大多是法国或意大利餐馆以及酒店。
为了以更全面的方式探索场馆数据并进一步用于分析,foursquare 场馆数据被安排到 pandas 数据框架中,如下所示:
## Categorizing venues into pandas
*# one hot encoding*
London_onehot = pd.get_dummies(London_venues[['Venue Category']], prefix="", prefix_sep="")
*# add neighborhood column back to dataframe*
London_onehot['Borough'] = London_venues['Borough']
*# move neighborhood column to the first column*
fixed_columns = [London_onehot.columns[-1]] + list(London_onehot.columns[:-1])
London_onehot = London_onehot[fixed_columns]
London_onehot.head()
London_grouped = London_onehot.groupby('Borough').mean().reset_index()**def** return_most_common_venues(row, num_top_venues):
row_categories = row.iloc[1:]
row_categories_sorted = row_categories.sort_values(ascending=**False**)
**return** row_categories_sorted.index.values[0:num_top_venues]num_top_venues = 10
indicators = ['st', 'nd', 'rd']
*# create columns according to number of top venues*
columns = ['Borough']
**for** ind **in** np.arange(num_top_venues):
**try**:
columns.append('**{}{}** Most Common Venue'.format(ind+1, indicators[ind]))
**except**:
columns.append('**{}**th Most Common Venue'.format(ind+1))
*# create a new dataframe for London*
Londonboroughs_venues_sorted = pd.DataFrame(columns=columns)
Londonboroughs_venues_sorted['Borough'] = London_grouped['Borough']**for** ind **in** np.arange(London_grouped.shape[0]):
Londonboroughs_venues_sorted.iloc[ind, 1:] = return_most_common_venues(London_grouped.iloc[ind, :], num_top_venues)
Londonboroughs_venues_sorted.head(10)
伦敦(左)和巴黎(右)的熊猫数据框中排列的 Foursquare 场馆数据部分。
然后,使用“”k-means”将提供每个区最常见的场地数据的信息用于对街区进行分类。
4。聚集街区
我使用' k-means '算法进行了聚类分析,以便根据场地类别提供的相似性将相似的街区分类成簇。为了获得一些理解,我决定对将要使用的聚类数(k)进行一些研究,如下所示:
肘形法:我尝试使用肘形法确定伦敦聚类分析的有效聚类数(k),并在 k = 6 附*看到一个小扭结(虽然不清楚也不尖锐)。肘形法对不同的 k 值使用组内误差*方和(WSS ),并且可以选择 WSS 开始减小的 k 值,并且可以被视为 WSS 对 k 图中的肘形。然而,对于 Paris 数据,没有明显看到扭结,因此我试图查看每个 k 值的聚类的剪影得分。剪影值衡量一个点与其自己的聚类(内聚)相比与其他聚类(分离)的相似程度。k = 2 左右的值给出了轮廓分数的全局最大值。尽管从这些研究中可以看出,我们没有明确的聚类数据,但为了我们的分析目的,我决定将伦敦街区分为 6 组聚类,将巴黎街区分为 2 组聚类。这可能是有益的,看看一个更详细的分析,以优化 k 在未来的此类研究。
5。结果讨论
为了解决手头的业务问题,我们考虑了伦敦内外的 33 个区和巴黎内的 16 个区。虽然这些社区中的每一个都可能是独一无二的,但其中一些在提供的便利设施方面可能更相似。执行聚类分析以找到那些相似的邻域。值得注意的一点是,从伦敦维基中提取的数据给出了伦敦内外各区的信息,因此将郊区也考虑在内。而巴黎维基提供的数据只给出了巴黎市内各区的信息,不包括巴黎周围大部分人口居住的郊区的信息。因此,这项研究中进行的分析需要更多的信息,以便在*等的基础上比较这些城市。
从解释性分析中得出的一些推论如下:
- 巴黎市中心的大部分地区比伦敦市中心的类似地区人口更稠密。伦敦 33 个区中有 9 个区的人口密度超过 1 万,而巴黎 16 个区中只有 3 个区的人口密度低于 1 万,4 个街区的人口密度超过 3 万。
- 在地图上,密集的行政区更多地集中在伦敦的内部区域,而不是外部区域,对于巴黎来说,最密集的行政区位于塞纳河以北。
- 对 Foursquare 场所数据的初步研究显示,咖啡店、咖啡馆、酒吧和果汁吧是伦敦市中心五个主要行政区最常见的场所。类似地,法国餐馆、意大利餐馆和酒店是在内巴黎五个主要行政区最常见的场所。
此外,对基于地点的数据的机器学习分析揭示了伦敦的大部分区可以被分组到一个聚类中。在这些区最常见的场所总是咖啡店、咖啡馆、酒吧、旅馆或餐馆,然后是某种服装、便利店或药店。巴黎总共被分为两个独立的区域。虽然两个集群中最常见的场所总是法国餐厅,但第一个集群中有大量的意大利餐厅、酒店和咖啡馆,第二个集群中有其他美食餐厅、酒吧、小酒馆、服装店或超市。
在这两个城市中,最常见的场所类型大多是餐馆、咖啡馆、酒店、酒吧、服装店或公园。这在某种程度上凸显了伦敦和巴黎在提供服务方面的相似性。
人们可以进一步使用场馆数据来比较城市,这是一种更全面的方式,人们也可以探索不同层次的空间聚合,即网格、街区和城市整体。当从场馆的角度来描述一个城市时,空间聚集的水*可能是一个重要的因素。
使用不同级别的空间聚合可以回答的一些问题可能是:
- 场馆类别在一个街区内是如何分布的,也就是说,这个街区是居住区还是商业区?
- 哪个城市的各种便利设施(酒吧、餐馆、公园、大学、图书馆、购物中心等)的数量最多?)
6。结论
总之,使用 Foursquare 基于场馆的数据分析城市,可以对每个街区的场馆类型有一个总体的了解,并呈现城市的一些关键特征,但是数据水*不足以提供城市间比较的全面分析。对于潜在的感兴趣的人(求职者或决定搬到两个城市之一的人)或更大的客户,如商业公司或城市规划者,需要做更详细的分析,增加诸如租金、工资、交通、生活成本、增长率、经济等特征。
capstone 项目提供了一个深入了解现实生活中数据科学项目如何工作以及构建数据科学方法的所有步骤的媒介。这里详细讨论了从理解业务问题、数据理解到数据准备和模型构建的所有步骤。还提到了目前分析的许多缺点和改进分析的进一步方法。这是理解和解决手头业务问题的初步尝试。然而,这个项目在现实生活中仍然有巨大的扩展潜力。
参考
[1] 伦敦维基百科
[2] 巴黎百科
关于我:
我是一名物理学家,几年来一直在分析粒子物理数据。在过去的几年里,我在卡尔斯鲁厄、日内瓦、圣保罗和芝加哥之间工作,目前居住在巴黎。尽管这样的数据分析将是设计一种方法来比较任何城市的垫脚石,但比较伦敦和巴黎是出于个人对这些城市的热爱。❤
你可以在 Linkedin 上找到更多关于我的信息。
"此刻做得最好会让你在下一刻处于最好的位置."保持安全和健康。
两种框架的故事
Tensorflow 和 Pytorch:终于并肩了。
如果你像我一样,你在每个项目中都有一个最喜欢的框架。对我来说,这是 Tensorflow,特别是因为他们在 tf2.0 中更好地集成了 Keras。但每次 PyTorch 中发布另一个功能时,另一边的草看起来会更绿一些。所以本教程是为那些对一个框架有很强理解,对另一个有好奇心的人准备的。
在本教程中,我将带您浏览两个框架中的相同示例,包括一些最佳实践的并排比较,例如:
克里斯·亚瑟·柯林斯在 Unsplash 上拍摄的照片
资料组
我将使用一个熟悉的数据集,Cats v Dogs,因为本指南不是要解决一个棘手的问题(您可能已经想到了自己的问题),而是要创建一个您可以轻松适应的通用、最小的示例。不过,最主要的是,我使用这个数据集是因为如果我要花大量时间看图片,我宁愿它们是可爱的动物。如果你想完全跟随,从这里下载数据。
我的数据集存储在包含我的训练脚本(“文件夹”)的文件夹的子目录(“数据”)中,其结构如下:
folder/
├── data/
├── test/
├──1.jpg
├──...
└── train/
├──cat.0.jpg
├──dog.0.jpg
├──...
设置数据生成器
我的数据集不是很大(25,000 个相当小的图像,其中我只使用 1000 个作为最小的例子),所以我可以将它们全部加载到内存中。但是数据集太大而无法加载到内存中变得越来越常见,因此拥有一个能够处理这些情况的管道非常重要。数据生成器是一个很好的选项,它允许您实时生成数据,批量运行预处理和扩充,并将其直接输入到模型中。这可以在训练期间带来巨大的效率,因为它允许在 GPU 正在运行训练的 CPU 上准备数据。
张量流数据生成器
对于我的 Tensorflow 数据生成器,我将从 tf 中继承。 keras 。实用工具。序列,这样我就可以利用多处理这样的额外好处。你会注意到我在这段代码中调用了一个函数‘augment ’,你可以在这里找到那个的代码,或者创建你自己的函数,其中输入是一个图像,输出是那个图像的放大版本,大小固定(im_size ),范围在-1 和 1 之间。
我们将重要信息作为参数,例如包含数据的目录(data_dir)、批量大小、图像将被重新缩放的大小(为此,它们将具有相同的高度和宽度)、要使用的图像数量(将此设置为小于图像总数的数字有助于测试网络和调试),以及数据是否应该在每个时期被打乱。
该类需要一些方法才能正常工作:
- init 是初始化方法,在类被实例化时调用。在这里,它定位我们的图像名称,把它们放在一个列表中,并洗牌。
- on_epoch_end 在每个 epoch 结束时触发,这里只是对数据进行洗牌。
- 每次训练循环从生成器请求新数据时,索引将从 0 递增到由 len 定义的上限。最佳实践是将该上限值设置为每个时期中的批次数量,以便每个时期可以看到每个图像一次。
- getitem 在每次请求数据时被调用,它获取前面提到的索引,基于该索引获得图像名称的 batch_size 列表,并获取它们。
该类中的另外两个方法不是严格必需的:
- __get_data 是一个私有方法,由 getitem 调用以获取图像并对其进行扩充。您可以将代码放在 getitem 中,但是这种布局使代码更加模块化。
- load_val 一次性加载所有验证图像。这与使用数据生成器处理大型数据集的目的背道而驰,但不幸的是,我将使用的一种训练方法(“fit”)不接受生成器作为验证数据集,希望在未来的版本中可以解决这个问题。
然后,在训练脚本中创建一个生成器实例,并读入所有验证图像,这是一件非常简单的事情。
PyTorch 数据生成器
PyTorch 数据生成器与 Tensorflow 生成器非常相似。然而在这种情况下,传承自的火炬。 utils 。数据。数据集允许我们使用多重处理,类似于上一节中 tf.keras.utils.Sequence 的继承。还有很多其他的相似之处,我们使用了增强功能,我们也使用了类似的参数,包括批量大小、图像大小、图像数量和随机播放。
生成器包含三种相同的方法:
- init 是初始化方法,这里是打乱图像文件名(它已经被传递了),并设置增强参数。
- len 的操作方式与上述相同
- getitem 读取一幅图像并放大。注意,这个生成器与前面的生成器的一个关键区别是,这里的生成器只生成一个图像,而 label - PyTorch 管理图像的批处理。
这里需要注意的一件重要事情是,如果 mobilenet 中的模型类型是应用于图像的归一化,这是因为我们将用于“mobilenet”的网络是一个预先训练的 torchvision 模型,它是使用在这种情况下归一化的图像训练的。因此,在使用这个模型时,我们需要以同样的方式进行归一化。
在培训管道中创建 PyTorch 生成器需要一些额外的工作。首先,我们设置一些参数,包括用于并行加载数据的线程数量。然后我们实例化该类,并将其传递给 DataLoader 类,该类也接受我们设置的参数。我们为验证创建第二个生成器,传递验证标志以确保图像不会被放大。
创建简单的模型
现在让我们看看创建一个简单的 CNN 是什么样子的。在这两个框架中,我将设置一个具有 4 个卷积层的 CNN,由最大池分隔,然后是 50%的下降,然后是两个线性层。我们在这里不是为了表演,只是为了演示。
这两个框架都允许你从头开始创建你需要的层,这意味着你有相当多的可定制性。然而,除非你有一个非常好的理由想要创建你自己的定制层,否则我鼓励你省去麻烦,使用两个框架都提供的用户友好的包装器。
张量流简单模型
Tensorflow 最*正确集成了 Keras,这是一种非常受欢迎的包装器,可以简化深度神经网络的创建和训练。这就是在 Tensorflow Keras 中创建我们的简单 CNN 的样子。
使用顺序模型类型将一堆层组合在一起。层在序列内堆叠的顺序表示层在网络中的顺序。与我们将在 PyTorch 中看到的不同,所有的层,包括那些没有可训练参数的层(比如 MaxPooling 和 activation 函数)都包含在模型中。这是因为这个函数既声明了模型的结构,又定义了向前(和向后)传递的数据流。
PyTorch 简单模型
在 PyTorch 中,模型被定义为从 nn 继承的类。模块,包含图层的 init 和定义数据如何通过网络的 forward()方法,并返回网络的输出。
请记住,任何具有需要训练的参数的层(如卷积层)都需要在 init 中注册。没有可训练参数(如最大池和激活函数)的层可以在 init 或 forward()中注册。
这可能比我们在 Tensorflow 中连接网络的方式要复杂一点,但是层和连接的分离为 PyTorch 提供了相当大的灵活性,这在 Tensorflow 中是不容易实现的。
定义损失函数和优化器
损失函数将模型的输出与目标值进行比较,并估计它们之间的差距。您使用的损失函数将取决于您的应用,我使用的是二元交叉熵和 Logit 损失,因为我正在训练一个二元分类器。“logit 损失”部分是因为我的模型的输出具有线性激活函数,这在 DL 框架术语中意味着我的损失函数的输入是“logit”,该术语用于分类输出在通过 sigmoid 或 softmax 层之前。使用交叉熵计算 sigmoid/softmax 的计算效率更高,具有 logit 丢失层的 BCE 就是这样做的。
优化器用于更新模型的参数,以减少损失。有很多优化器可供选择,但我使用的是亚当。
张量流损失函数和优化器
在 Tensorflow 中,有和没有 logit 损失的二元交叉熵是通过相同的函数定义的。
PyTorch 损失函数和优化器
在 PyTorch 中,有 logit 损失的二元交叉熵是一个独立于没有 logit 损失的函数。此外,优化器将模型参数和学习率作为输入。因此,如果您没有训练所有的参数(即,如果您正在微调模型),那么请确保只传入您正在训练的参数。
训练循环(带记录)
最后,我们得到了好东西,训练我们的网络。我们还将在训练循环中添加两个独立的函数,一个用于将训练过程记录到 Tensorboard,另一个用于模型检查点。
Tensorboard 用于记录模型在训练过程中的损耗和精度。您还可以添加其他功能,如记录图像(如果您正在训练图像生成器,这将非常方便)和直方图(非常适合跟踪梯度)。
Tensorboard 提供了一个很好的方法来检查训练的结果,并比较不同的模型。
模型检查点在训练期间定期(默认为每个时期)将模型或权重保存在所选文件夹中。如果验证精度大于当前检查点,我们将只覆盖每一步的权重。
你可以(也应该)添加许多其他功能,比如学习率计划和提前停止。
Tensorflow 训练循环(选项 1)
在 Tensorflow 中,有多种训练网络的方法。第一种是最简单的,它利用 Keras 的“fit”方法,使用您的数据生成器作为训练数据输入(请注意,在 Tensorflow 2.0 之前,您必须使用“fit_generator”将生成器作为输入,但这在最*的版本中已被否决)。不幸的是,验证数据不能作为生成器传入。
在调用“fit”之前,我们需要用优化器和 loss 编译我们的模型。我们还为多重处理设置了一些参数,以加速训练循环。这里要注意的另一件事是回调的使用,这就是我们如何定义 Tensorboard 和前面提到的模型检查点行为。
在没有 GPU 的 MacBook Pro 上,该训练代码应用于 850 个猫/狗训练图像,其中有 150 个验证图像,给出了以下结果:
Tensorflow 训练循环(选项 2)
或者,我们可以更明确地定义训练循环。具体来说,我们定义了一个 for 循环,它遍历所有的历元,然后是另一个批量遍历数据集的循环。首先,我们定义了许多度量标准(训练/验证准确性和损失),它们在训练和测试步骤功能中得到更新。
然后我们定义训练和验证函数。在 train 函数中,我们打开一个 GradientTape()范围,在其中我们调用模型来运行正向传递并计算损失。然后,我们检索梯度,并使用优化器根据梯度更新权重。验证函数的不同之处在于,我们仅通过模型运行数据来计算损失和准确性,并记录两者。
这里需要注意的一点是在训练和测试步骤函数上面使用了 tf.function 装饰符。默认情况下,Tensorflow 2.0 以后以渴望模式运行,这对于逐行执行和调试非常有用,但会导致函数执行速度变慢。这个装饰器将 python 函数转换成静态张量流图,这样运行速度更快。
我们还需要手动设置 Tensorboard 日志记录,并检查验证准确性,以监控何时保存模型权重。
在没有 GPU 的 MacBook Pro 上,该训练代码应用于 850 个猫/狗训练图像,其中有 150 个验证图像,给出了以下结果:
PyTorch 训练循环
Pytorch 循环遵循与 tensorflow 循环相同的逻辑,要注意的主要区别之一是向后传递是如何非常优雅和直观地运行的,方法是在丢失时调用 backward 方法,参数是通过在优化器上调用 step 方法来更新的。值得注意的是,在验证步骤中使用了 no_grad 范围,它会将模型参数中的所有“requires_grad”标志临时设置为 False。
还要注意“model.train()”和“model.eval()”的使用,它们用于在包含具有不同训练和评估行为(如批处理规范化)的模块的模型的模式之间切换。
在没有 GPU 的 MacBook Pro 上,该训练代码应用于 850 个猫/狗训练图像,其中有 150 个验证图像,给出了以下结果:
与张量流相比,这显然是每个历元更长的时间。尽管在数据加载器中设置了 num_workers 参数,但在执行过程中监控我的 CPU 内核的使用情况显示,与 Tensorflow 实现相比,它们没有得到充分利用。这是 Pytorch 目前已知的问题,如果您知道修复方法,请发表评论!
使用预先训练的模型改善结果
Tensorflow 和 PyTorch 作为深度学习框架的一个重要方面是能够利用内置的预训练模型。这两个框架都包括许多在 ImageNet 上预先训练的最流行的模型,供您免费使用。更好的是,很容易开始使用这些网络,并用更适合您的问题的东西替换分类图层。
Tensorflow 预训练模型
在 Tensorflow 中使用预训练模型的一个特别简单的方法是通过 Keras 应用,这是带有预训练权重的固定架构。请注意,这不是使用预训练模型的唯一方式,但可能是最简单的方式。如果你选择的模特没有在这里列出,你可以去 TFHub 或者 TF 模特园看看。
在没有 GPU 的 MacBook Pro 上,该训练代码应用于 850 个猫/狗训练图像,其中有 150 个验证图像,给出了以下结果:
这比简单模型好多了!请注意,训练时间比简单模型短,因为实际训练的参数数量较少(即使整个模型大得多)。
PyTorch 预训练模型
与 Keras 应用程序相当的 Pytorch 是 Torchvision。火炬视觉预训练网络要求其输入以特定方式标准化,详情见此处。如前所述,我在数据扩充阶段对图像进行了归一化处理。
我们不想训练网络的特征提取阶段,因此在用我们自己的(可训练的)线性层替换第二分类层之前,我们为所有层关闭网络的‘requires _ grad’标志。我们只将这一层传递给优化器。
在没有 GPU 的 MacBook Pro 上,该训练代码应用于 850 个猫/狗训练图像,其中有 150 个验证图像,给出了以下结果:
模型评估
这是一个漫长的阅读,但我们几乎在那里,我们只需要评估模型。以下代码假设您已经创建了模型布局,因此只需要从文件中加载权重。
张量流模型评估
在预定义模型结构上使用的张量流方法“load_weights”加载并应用在所选检查点文件中找到的模型的训练参数。下面的代码从测试集中抓取一批图像,并在模型中运行它们。
Pytorch 模型评估
Pytorch 函数' load_state_dict '应用在所选检查点文件中找到的' model '参数的状态。下面的代码从测试集中抓取一批图像,并在模型中运行它们。
摘要
我希望本教程能让你更好地理解你喜欢的框架的对应部分的用法。这两个框架都已经发展到这样一个程度,即它们既易于初学者使用,又在需要时高度可定制。要查看完整代码,请查看 GitHub 上的代码。
双城记
抗击新冠肺炎的模型思维
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
随着世界各地的城市和国家寻求在开放经济和将感染控制在可控水*之间找到正确的*衡,模型思维的应用可以帮助城市管理者更有信心地做出这些决定。
传统模型:严格但有限的决策支持
疫情最著名的模型将人群分为四大类:易感人群、已感染人群和已康复或死亡人群。然后根据新出现的数据对这些区间的相互作用进行建模和校准,然后用于预测感染。让我们称这些模型为 SIRD 模型。虽然这些是流行病学的优雅模型,但它们不适合在真实场景中评估影响和做出决策。关键缺点如下:
- 关注流行病学部分,而非行为/影响部分:此类模型假设跨这些区间的传播参数相似。然而,传播可能因社会经济条件和工作性质而异,主要是因为这些因素影响采取预防措施的能力,如社会距离和在家工作。举例来说,送餐员必须在外面工作,同时与几个不同的陌生人打交道,优步的司机也是如此。然而,一名 IT 专业人员或大多数白领员工能够承受严格限制与人的身体接触。
- 作为*滑且通常固定的参数的传播 : SIRD 模型假设传染病的传播可以通过*滑曲线来建模。这在直觉上是没有帮助的,因为传导主要是一条不规则的曲线(比如说在封锁期间更*坦,但在开放经济期间更陡峭)。
- 依赖于确诊病例的模型校准:对于像 Covid 这样的疾病,其检测具有很大的不确定性(围绕是否有一次感染以及何时可以检测到),并且已经通过不同的检测方案得到满足(最初强调检测国际旅行者,后来转向基于医疗保健准备情况和预期的社区传播的更广泛的检测),确诊病例可能不会有益地用于了解该疾病迄今为止是如何传播的。
由于每个城市都有不同比例的行为群体(比如白领和蓝领工人),一直在试验不同的控制措施和测试模式,纯 SIRD 模型无法回答如下问题:
- 哪些控制措施将允许无害的相互作用,但防止可能导致疾病传播增加的相互作用?
- 对弱势群体有什么影响,国家提供什么支持可以减轻这种影响(例如,国有保险、公共部门床位的可用性、药品定价等)。)?
- 鉴于目前的事态(比如严格的封锁,然后是宽松的封锁),感染情况如何,政策措施将如何影响感染?
- 确保每个城市都包含 Covid 并采取措施防止新浪潮的最终策略和阶段是什么?
给 SIRD 模型增加助推器
为了解决其中的一些缺点,提出了一些对香草 SIRD 模型的改进,以获得更好的决策话语。我还选择利用一些可用的数据点(这些数据点仍然非常非常有限或者很难找到)为德里创建一个代表性的模型。以下是建议的增强措施:
- 模拟社会经济区:城市(德里)被分为白城和蓝城。BlueTown 代表人口密集、通常无规划的居住区,大多数居民从事需要体力劳动的活动,社会经济地位相对较低。WhiteTown 代表人口密度较低的地区,居民从事可以在家中进行的工作(在家工作),具有相对较好的社会经济地位。传播模型既有细分市场内的(比如拥挤的贫民窟中使用社区设施的邻居),也有跨细分市场的(比如一个来自 BlueTown 的披萨外卖男孩感染了 WhiteTown 的居民,后者已经点了餐)。虽然这是一个抽象概念,但其目的是在一个真实的模型中模拟相关的社会经济部分,也许不仅仅是这两个部分。
- 纳入已采取的控制措施:该模型将截至日期的总持续时间视为一组间隔,其中传播与已采取的措施和观察到的影响相关联。举例来说,在严格的锁定期间,传输速度直观上会变慢,但一旦解锁,传输速度就会再次激增。对于我的玩具模型,具有不同检测的 4 个清晰间隔由关键事件分开建模——第一种情况检测、完全锁定、绿色区域的初始开放以及具有一些放松的延长锁定
- 传播系数的经验计算:虽然传播率的评估仍然存在很大的不确定性,但我们可以做出一些简单的假设来简化这一点。我们可以假设,随着人均接触次数的减少(如在锁定场景中),传播确实变慢了,并且在打开时再次移回。我们还可以假设检测率(每次感染的病例数)根据检测标准而变化。最后,使用一组职业的相互作用来估计白镇、蓝镇内部和之间的传播。
虽然很难对模型进行清晰的校准(由于渐*情况以及检测和报告中的延迟),但通过上述经验估计将模型调整到合理的限度。下图说明了结果输出。虽然由于校准挑战,这些数字没有对齐,但输出反映了相对于具有*滑传输假设的德里 SIRD 模型的建模灵活性-例如,在经典 SIRD 模型中很难发现 6 月显示的陡度。此外,开放的可怕影响(以及在各个部门内)可以更好地从这一练习中收集,这可以创造必要的话语,说明在开放时可以做些什么来防止这种上升,以及这种措施是否足够,损害是否可以接受。
德里的松散校准模型(直到 2020 年 6 月 23 日)
创造可供选择的世界
扩展现状,看看它会把我们引向何方,然后考虑通过模拟两个场景对两个虚构的城镇进行影响评估。在第一种情况下,假设封锁后的传播率将继续(6 月份暗中观察到的传播率仍然低于疫情开始时的传播率,当时人们的认识甚至更低)。这表明明年二月会达到高峰。在另一种情况下,如果我们假设封锁前的传播率,我们会在 8 月看到高峰。还可以看到,对 BlueTown 的影响比对 WhiteTown 的影响大得多,预计是因为那里估计的高传输速率。结果绘制如下。
场景 1:根据观察到的 6 月趋势控制传输
场景 2:遵循预锁定趋势的传输
虽然该模型侧重于模拟对两个社会经济部分的影响,但必要时也可以确定对决策有用的多个部分——例如模拟热点地区的店主,然后模拟他们的传输参数。此外,关于受感染人员的指示可以帮助准备跨区域的医疗资源分配。因此,所有关键决策都可以通过模拟备选方案和评估相对影响来决定。
城市管理者的外卖
好的模型有助于决策,即使他们的预测是错误的。它有一个特定的决策者——城市管理者,他们希望做出决定抗击疫情,它的核心是定制化,以帮助做出相关的政策决策,从全面封锁、医疗准备、服务许可到甚至开放边境。因此,城市管理者需要依赖代表他们的城市及其事务的模型,并使决策能够跨越他们所面临的决策
该模型还需要在传统流行病学模型的范式中注入各种数据来源,对我来说,这在这样的危机中是必要的。城市管理者需要利用他们拥有的所有数据,而不是依赖清教徒式的传统数据,因为他们做出的任何决定都会影响生活、生计和经济。在这种情况下,这意味着不仅考虑官方报告的数字,所有州可用数据,如第一次报告的可能病例症状(在医院)以及死亡,都被用来调整检测中的滞后。
最后,虽然随着我们对疾病、死亡率和渐*人群的理解不断发展,像这样的修改模型仍可能产生不准确的数字,但具有这种社会经济或细分市场的味道可以让我们更有意识地做出决策,同时了解各个细分市场的相对影响。这可以为更有针对性的干预提供信息
总的来说,当管理者在政治、社会和情感压力中挣扎的时候,他们不应该忘记一个好的决策只有一个定义特征,那就是它是有意识地做出的。
帽子提示:
- https://timesofindia . India times . com/city/Delhi/Half-of-Delhis-population-lives-in-sludges/articleshow/16664224 . CMS
- https://www . science direct . com/science/article/pii/s 0307904 x 11005191
- https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7190554/
- https://science . the wire . in/the-sciences/basic-reproductive-ratio-value-India-estimate/
- https://assets . 2030 vision . com/files/resources/2030 vision-full-report . pdf?416997c759
- https://www . lewuathe . com/新冠肺炎-dynamics-with-sir-model . html
- https://www.thehindu.com/coronavirus/
体验 ACL2020: 6 个新数据集和基准
计算语言学协会今年的会议挤满了 700 多份出版物。为了让你更容易地浏览,这里有一个新的刷新数据集和语言任务基准的论文选择。
数据集和基准是自然语言理解进展的核心(NLU) :在排行榜驱动的研究中,进展受到我们评估的质量的上限。虽然机器学习的数据集曾经持续很久——即 MNIST 在推出十多年后才达到人类的表现——但最新的自然语言理解基准变得过时的速度比我们预期的还要快,这凸显了找到更好的基准的重要性。
关于这个主题的论文数量之多令人震惊,因此在 Zeta-Alpha 上,我们精选了 ACL2020 上最有趣的作品,这些作品将影响如何衡量该领域的进展。
1。对抗性 NLI:自然语言理解的新基准
在这篇论文中——已经引起了+20 次引用——作者雄辩地说明了为什么静态 NLU 基准很快就过时了并且模型经常利用在数据收集阶段检测不到的虚假统计模式。
他们引入了自然语言推理的数据集(NLI),其中给定了前提和本质,人们应该确定它们是必然的,矛盾的还是中性的。问题是,他们还引入了一个框架,根据来自训练模型的反馈对数据集进行迭代,并且人类在循环中引入了对立的例子;目的是在模型失败的地方创建数据集。如下图所示,注释的圆包括:
- 注释数据集并在其上训练模型。
- 让注释者在给定的上下文中编写新的对抗性假设,并在训练好的模型上测试它们。
- 如果模型成功,我们将新样本添加到训练集中。
- 当模型失败并且另一个人同意注释时,我们将他们添加到开发、测试或训练集中。
对抗性人在回路数据收集图。来源:对抗性的 NLI:自然语言理解的新基准
作者将这一过程称为 HAMLET ( 人和模型在回路中启用的培训),在论文中,他们展示了 3 轮数据集的创建,其中注释者受到激励,提出模型将失败的假设。这导致的数据集越来越具有挑战性,并且作为副作用,他们在 MNLI 数据集的一些变体上达到了最先进的水*。虽然他们推测,由于其收集方式,该基准不会很快饱和,但他们强调,即使如此,仍可以增加新的回合来克服这一点。
动态数据集的主要不便之处在于标准化的困难,这使得不同作品的比较成为可能。虽然对抗性的人在回路中并不是一个新的想法,但这个干净的实例有可能成为未来迭代的灵感,并可能克服标准化的障碍,在不久的将来,动态数据集将成为规范。
2。橡皮擦:评估合理化 NLP 模型的基准
本文介绍了一个由 7 个任务组成的成熟的语言基准,这些任务不仅包括标签,而且受 GLUE 基准成功的启发,还有人类注释的“基本原理”。这些任务包括:证据推理、 BoolQ (布尔 QA)影评、发烧(事实提取验证) MultiRC (阅读理解)常识解释(CoS-E)E-SNLI(语言蕴涵)人情约定。
作者提出了一个精确-召回曲线度量下的区域,用于评估模型和人类注释推理的符合性,但是他们知道这种评估很难客观地进行,这就是为什么他们明确地呼吁在这个方向上进行更多的研究。
这个被提议的基准测试是迈向一个更具解释力的语言模型综合评估的宏伟愿景的第一步。
擦除基准中的任务示例。来源: ERASER:评估合理化 NLP 模型的基准
3。GoEmotions:一个细粒度情感的数据集
情感分析长期以来一直是 NLP 中的一项基本任务,但一些最广泛使用的数据集(如具有二元积极/消极情感的 SST2)正在超越人类表现,对于衡量有意义的进展来说已经过时。
GoEmotions 是一个数据集,由来自流行英语 subreddit 评论的 58k 个人工注释样本组成,它非常细粒度,有 27 个情感标签(或中性标签)。数据收集过程坚持高标准,进行全面的人工审查、长度过滤、情感*衡、子编辑*衡以及屏蔽专有名称和宗教术语。伯特模型的早期基线测试表明,还有很大的改进空间,当前最先进的 NLU 模型未能在这一程度上理解情绪,使其成为一个具有挑战性的新情绪基准。
GoEmotions 数据集的类统计数据,以及情绪相关性的热图及其对粗糙情绪(积极、消极和模糊)的聚类。来源: GoEmotions:一个细粒度情感的数据集
这种类型的数据集在这个时代非常有价值,可以帮助我们理解互联网上复杂的大规模社会动态。
类似地,也是在 ACL2020 上, iSarcasm:一个有意讽刺的数据集,是一个专注于有意讽刺和感知讽刺之间的区别的数据集,这样我们就可以克服当前模型只检测更明显形式的偏见。该数据集规模较小,只有 4.4k 个样本,也强调了该主题作为理解社交媒体背景下的社交互动的一种手段的重要性。
4。SCDE:含有高质量考试干扰项的句子完形填空数据集
句子完形填空任务包括从一组候选词中填充句子大小的空白。类似的句子级任务经常被用作语言模型预训练的自我监督(即 BERT 的下一句预测);然而,这项任务通常过于简单,因为它可以依赖虚假的句子模式,因为自我监督的候选句子不够有挑战性。
在这项工作中,他们引入了干扰句,这是由英语教师设计的人类策划的句子,这些句子需要语言的非本地语篇层面才能成功完成任务。目前的模型只能达到 72%的准确率,而人类可以达到 87%左右,这表明还有相当大的改进空间。
5。死亡杀死了猫或者:BabelPic,一个非具体概念的多模态数据集
人类不会孤立地学习语言,那么我们应该期待机器会这样做吗?多模态机器学习探索了利用不同模式的数据,如视觉和语言,来制作更好的世界模型的想法。
“[……]语言理解系统应该能够对描绘隐退和悔恨的图像进行分类,而不仅仅是猫、狗和桥。”
在对大多数当前多模态视觉和语言数据集进行这种挑衅性的描述后,这项工作建立了关注非具体概念的数据集,作为扩大多模态语义理解覆盖范围的一步。该数据集是通过结合 WordNet 和 BabelNet 词汇知识库建立的。
巴贝皮克的非混凝土样本。来源:死亡杀死了猫或:BabelPic,一个非具体概念的多模态数据集
经过许多过滤技巧、试探法和手动验证后,最终的“黄金”数据集具有 2.7k 同义词集(同义词集)和 15k 匹配图像,以及由视觉语言模型通过使用 WordNet 中的自然语言定义生成的具有 10k 同义词集的扩展“白银”集。
6。R4C:评估 RC 系统的基准,以便为正确的原因获得正确的答案
同样,正如对抗性的 NLI 指出的,许多阅读理解任务依赖于现有数据集中的注释工件和其他偏见,使得任务的完成不需要任何理解。为了减轻这一点,井上直也等人。艾尔提出了一个任务,不仅要求在阅读理解任务中找到正确答案,而且还要求提供足够的支持事实。
包括基本原理的问答示例,其中示例来自 HotpotQA⁶.来源: R4C:一个评估 RC 系统的基准,为了正确的理由得到正确的答案 & HotpotQA⁴
得到的带注释的数据集是总共 7.1k 个训练样本和 6.6k 个开发样本,它们是从 HotpotQA⁴数据集采样的,其中每个答案的理由都包含在注释中。这项任务的评估包括对答案打分和评估“基本原理与地面事实的一致性”的正确性。
虽然这绝不是今年 ACL 中首次亮相的数据集和基准的全面列表,但它是一个有代表性的样本,显示了会议是如何挤满了贡献。在 @zetavector 的团队将会关注会议,并从我们的 twitter feed 中报告见解,所以请不要错过任何事情!
参考
- 自然语言推理数据中的标注工件。Suchin Gururangan,Swabha Swayamdipta et。al 2017。
- WordNet:一个英语词汇数据库。乔治·米勒 1995。
- BabelNet:一个广覆盖多语言语义网络的自动构建、评估和应用。RobertoNavigli,Simone Paolo Ponzetto,2012 年。
- HOTPOTQA:一个多样化的、可解释的多跳问答数据集。杨,彭琪,张赛正等。al 2018。
使用张量流数据集和张量板的张量流建模管道
介绍
在完成由泰勒·埃利奥特·贝蒂荣(TEB)教授的名为面向开发人员的深度学习的高信息量 AICamp 在线课程时,我对为机器学习模型构建者(像我这样的学生)创建一种更结构化的方法产生了兴趣,以理解和评估各种模型,并观察它们在应用于新数据集时的表现。因为这个特殊的类关注 TensorFlow (TF ),所以我开始研究 TF 组件来构建一个工具集,使这种类型的建模评估更加有效。在这样做的过程中,我了解了两个非常有用的组件, TensorFlow 数据集 (TFDS)和 TensorBoard (TB),这篇博文讨论了它们在这项任务中的应用。参见参考文献部分链接到 AICamp,TEB 和其他有用的资源,包括由 Neptune.ai 提供的全面的 TensorBoard 教程
目标
虽然术语“管道”在数据科学上下文中可能有多种含义,但我在这里使用它来表示一个建模管道或一组编程组件,它们可以从加载数据、应用预先确定的模型和记录性能结果中自动完成端到端建模。目标是建立大量的建模测试,并为每个测试自动运行管道。一旦模型经过训练,每个测试结果都可以很容易地与其他结果进行比较。总之,目标是为模型测试建立一个有效的、有组织的和系统的机制。
建模管道的逻辑流程
这种方法如图 1 所示。管道由三个步骤组成:
- 数据:加载并处理一个数据集,
- 分析:建立预定义模型并应用于该数据集,
- 结果:为每个数据集-模型测试捕获关键指标,以便以后进行系统的比较。
任何研究甚至涉足深度学习神经网络的分析师可能都经历过看似无限的建模选择。任何数量的许多层类型,每种类型都有许多配置选项,可以相互连接,一旦堆叠,就可以使用多个优化例程和许多超参数来训练模型。还有数据的问题,因为可能需要将有前途的模型应用于新的数据集,以观察它们在看不见的数据上的性能,或者为进一步的模型迭代获得基础。
对于这个应用程序,我专门处理图像分类数据和模型。TFDS 包括音频、图像、对象检测、结构化、摘要、文本、翻译和视频数据,深度学习模型可以专门针对这些问题构建。虽然这里展示的现成代码需要一些修改和测试才能应用到其他集合,但是它的基本框架仍然是有帮助的。
张量流
本文中的代码总结在表 1 中,基于 TensorFlow 2.0(2019 年 9 月发布的产品)和两个组件 tensor flow 数据集和 TensorBoard。Keras 是一个与 TensorFlow 交互的高级 API,现在与 TF 2.x 深度集成,这里使用的许多工具都依赖于 Keras 组件。
建模管道中使用的关键 TensorFlow 组件
编码
事实证明,构建预期的建模管道需要相当多的编码。虽然可以更简单地部署这些 TF 模块的简单或直接的应用程序,但是在健壮的管道中使用它们需要一些定制的包装和实现组件来编排它们的使用,在该管道中数据和模型都被期望以编程方式改变。我把我的代码放在一个共享的 Google Colab 笔记本 (TF_Modeling_Pipeline)中,所有人都可以访问。然而,我应该注意到,我使用 Colab Pro(一种订阅服务),并在 GPU 设备上运行该笔记本。
虽然这个笔记本包含了很多代码,但我试图干净地组织和完整地记录这些工作,使其更易于浏览。此外,我在整个文档中添加了大量参考链接,以识别来源并提供对更多信息的快速访问。
调用 TensorFlow、TensorFlow 数据集和 TensorBoard 模块的关键自定义包装器
如前所述,这里的目标是构建一个自动化的管道。考虑到这个目标,我使用了几个定制的包装器来处理数据加载和处理、模型构建和训练以及结果记录过程。这些在图 2 中描述,并在表 2 中讨论。
调用 TensorFlow、TensorFlow 数据集和 TensorBoard 模块的关键自定义包装器
试验
为了演示这个管道,我设置了以下测试,其中数据集名称可以在 TFDS 目录中找到。
测试配置,检查应用于两个数据集的两个模型
回顾建立这些演示测试的思维过程,举例说明了这种管道方法的好处。在将 Tyler Bettilyon 的类和 TF 示例模型(TBConvTest)应用于 MNIST 数据集并发现良好结果后,我想看看它在彩色图像数据集上的性能。我最终选择了疟疾数据。正如你从 TFDS 目录链接或数据集信息类中看到的,TFDS 数据集带有参考资料。
事实证明,这些材料非常有价值,因为 TBConvTest 模型在疟疾数据集上的早期测试结果不佳。这让我想到了 Sivaramakrishnan Rajaraman 等人的工作以及这篇论文和 GitHub 资源库。在那里,我能够找到关于他们对这些疟疾图像数据进行分类的方法的有用资源,vgg 16 测试模型相当于他们的一个模型。
数据
图 3 和图 4 中的训练数据图像示例保存在日志中,可以通过 TB 的图像特性获得(参见建模管道代码中的步骤 5)。
MNIST 图像示例
疟疾图像示例
模型
图 5 和图 6 中的模型图是由 TB 回调创建的,并且在 TB 的 graphs 特性中可用(参见建模管道代码中的步骤 7)。
TBConvTest 模型
vgg 16 测试型号
结果
这些测试的所有结果都存储在 TensorBoard 中,可以通过运行 TF_Modeling_Pipeline Colab 笔记本重新创建。作为概述,图 7 中的屏幕截图显示了 TB 仪表板。如您所见,有几个功能,其中一些我们已经讨论过,可以通过标题菜单访问。在这幅图中,我们正在查看标量下每个建模测试的关键准确性指标。
TB 仪表板和标量显示每次测试的预测准确性
从注释(我添加的)中,我们可以快速比较模型并进行一些观察。首先,test_1 和 test_2 之间明显的性能差异清楚地表明,TBConvTest 模型没有扩展到疟疾数据集。由于疟疾测试是一个二元分类,50%的准确率并不比猜测更好,并且该模型没有提供解释能力。其次,通过在疟疾数据集(test_3)上使用 VGG16Test 模型,我们可以看到增量改进。第三,通过查看每个时期(x 轴)的准确率,我们可以快速了解所有模型随着训练的改进。考虑到 Rajaraman 等人训练了至少 100 个时期,检查 test_3 的缓慢精度增长率并想知道额外训练的益处如何或何时显现是有趣的。
查看我们定制的指标“混淆矩阵”也很有帮助。假设我们的 TB 配置(参见建模管道代码中的步骤 7)在 IMAGES 选项卡中可用。该视图是在 10 个时期之后,但是顶部滑块允许用户浏览每个时期之后的混淆矩阵变化。从这个归一化矩阵中,我们注意到未感染类的准确率为 80%,而被感染类的准确率仅为 57%,这可以提供对其他模型变化和该模型的适当使用的洞察。
10 个时期后测试 3 的混淆矩阵
结论
建立一个半自动的、有组织的和有方法的管道来测试机器学习模型,并在多个数据集上验证它们的性能,这对建模者来说是一个有用的工具。TensorFlow 数据集和 TensorBoard 是 TensorFlow 2.x 开发套件中的两个组件,可提供大量管道功能,并可作为此类 TensorFlow 管道的基础。然而,为了实现自动化的好处,它们应该被包装在定制的编程组件中,这些组件提供有效构建深度学习模型所需的效率和可见性。
参考
- 如果你想了解更多关于 AICamp 或深度学习课程导师泰勒·埃利奥特·贝蒂莱恩(TEB)的信息,请访问他们这里: AICamp 和 Teb 的实验室。
- 关于全面的冲浪板教程,请看 Neptune.ai 的深潜。
博客
- 在 TensorFlow 1 & 2 中使用 TensorBoard 的基础知识:塞巴斯蒂安·蒂勒非常有用的总结
- 面向专家的 TensorFlow 2 快速入门
- 如何从头开始创建 TensorFlow 2 模型——一个“无用”的例子
- 如何使用 Keras 的 TensorBoard】
- tf。为 Keras 用户解释的 GradientTape】
- 如何在 TensorFlow 中使用数据集和迭代器
- 用 TensorFlow 2 迁移学习
张量流
管道代码
物体探测效率的彻底崩溃
在这篇文章中,我们深入探讨了用于物体检测的 EfficientDet 的结构,重点是模型的动机、设计和架构。我们还在博客上发布了 物体探测效率分析 。
最*,Google Brain 团队发布了他们的 EfficientDet 对象检测模型目标是将架构决策具体化为一个可扩展的框架,该框架可以轻松应用于对象检测的其他用例。该论文的结论是 EfficientDet 在基准数据集上的表现优于类似规模的模型。在 Roboflow,我们发现基本的 EfficientDet 模型可以推广到托管在我们*台上的自定义数据集。(关于实现 EfficientDet 的深入教程,请参见这篇关于如何训练 EfficientDet 的博文和这篇关于如何训练 EfficientDet 的 Colab 笔记本。)
在这篇博客文章中,我们探讨了在形成最终 EfficientDet 模型时所做决策背后的基本原理,EfficientDet 如何工作,以及 EfficientDet 与 YOLOv3、fast R-CNN 和 MobileNet 等流行的对象检测模型相比如何。
探索激发 EfficientDet 创作的理论基础。图片来源和引用论文
The founder of Mosaic Augmentation, Glen Jocher has released a new YOLO training framework titled YOLOv5\. You may also want to see our post on [YOLOv5 vs YOLOv4](https://blog.roboflow.ai/yolov5-improvements-and-evaluation/) This post will explain some of the pros of the new YOLOv5 framework, and help illuminate breakthroughs that have happened since the EfficientDet publication.[YOLOv5 Breakdown](https://blog.roboflow.ai/yolov5-improvements-and-evaluation/)
深度学习效率面临的挑战
在探索该模型之前,这里有一些阻碍图像检测系统部署到现实生活用例中的关键领域。
- 数据收集 —借助模型架构和预训练检查点,EfficientDet 减少了推广到新领域所需的数据量。
- 模型设计和超参数化 —一旦收集了数据,机器学习工程师需要仔细设置模型设计并调整许多超参数。
- 训练时间 —在收集的数据集上训练模型所需的时间。在 EfficientDet 论文中,这是以 FLOPS(每秒浮点运算次数)来衡量的。
- 内存占用 —一旦模型被训练,当被调用进行推理时,需要多少内存来存储模型权重?
- 推理时间 —当模型被调用时,它能足够快地执行预测以用于生产设置吗?
图像特征和 CNN
训练对象检测模型的第一步是将图像的像素转换成可以通过神经网络输入的特征。通过使用卷积神经网络从图像中创建可学习的特征,计算机视觉领域取得了重大进展。卷积神经网络以不同的粒度级别混合和汇集图像特征,允许模型在学习手头的图像检测任务时选择可能的组合。然而,一段时间以来,卷积神经网络(ConvNet)创建特征的确切方式一直是研究社区感兴趣的领域。ConvNet 版本包括 ResNet、NASNet、YoloV3、Inception、DenseNet 等,每一个版本都试图通过缩放 ConvNet 模型大小和调整 ConvNet 设计来提高图像检测性能。这些 ConvNet 模型是以可扩展的方式提供的,因此如果资源允许,程序员可以部署更大的模型来提高性能。
效率网:动机和设计
最*,谷歌大脑团队发布了他们自己的 ConvNet 模型,名为 EfficientNet。 EfficientNet 构成了 EfficientDet 架构的主干,因此在继续介绍 EfficientDet 的贡献之前,我们将介绍它的设计。EfficientNet 着手研究 ConvNet 架构的扩展过程。有很多方法——事实证明💭-您可以向 ConvNet 添加更多参数。
你可以使每一层更宽,你可以使层数更深,你可以以更高的分辨率输入图像,或者你可以将这些改进结合起来。你可以想象,对机器学习研究人员来说,探索所有这些可能性可能会非常乏味。EfficientNet 开始定义一个自动程序来扩展 ConvNet 模型架构。本文试图在给定深度、宽度和分辨率的自由范围内优化下游性能,同时保持在目标存储器和目标触发器的限制范围内。他们发现,他们的扩展方法改进了以前的 ConvNets 的优化及其高效的网络架构。
高效网络、扩展和评估
创建一种新的模型缩放技术是向前迈出的一大步,作者通过创建一种新的 ConvNet 架构将他们的发现向前推进了一步,从而将他们的最新成果推向了更高的水*。通过神经结构搜索发现新的模型结构。在给定一定数量的 FLOPS 的情况下,神经架构搜索可优化精度,并创建一个名为 EfficientNet-B0 的基线 ConvNet。使用扩展搜索,EfficientNet-B0 将扩展到 EfficientNet-B1。从 EfficientNet-B0 到 EfficientNet-B1 的缩放功能被保存并应用于通过 EfficientNet-B7 的后续缩放,因为额外的搜索变得极其昂贵。
新的高效网络系列在 ImageNet 排行榜上进行评估,这是一项图像分类任务。注意:自从 EfficientNet 最初发布以来,已经有了一些改进,包括从优化分辨率差异以及将 EfficientNet 部署为教师和学生。
相当甜蜜!EfficientNet 看起来是一个很好的基础。它可以有效地随模型大小扩展,性能优于其他 ConvNet 主干网。
到目前为止,我们已经介绍了 EfficientDet 网络的以下部分:
引入效率检测
现在,我们将讨论 EfficientDet 的贡献,它试图回答以下问题:我们应该如何准确地将 ConvNets 的功能结合起来用于对象检测?一旦我们开发了这个组合过程,我们应该如何扩展我们模型的架构呢?
特征融合
特征融合寻求组合给定图像在不同分辨率下的表示。通常,融合使用 ConvNet 的最后几个要素图层,但确切的神经架构可能会有所不同。
在上图中,FPN 是一种自上而下融合要素的基本方法。PA net 允许特征融合从较小的分辨率到较大的分辨率来回流动。NAS-FPN 是一种通过神经架构搜索发现的特征融合技术,它看起来肯定不像人们可能想到的第一个设计。EfficientDet 论文使用“直觉”(可能还有许多许多开发集)来编辑 NAS-FPN 的结构,以确定双向功能金字塔网络 BiFPN。EfficientDet 模型将这些 BiFPN 块堆叠在一起。在模型缩放过程中,块的数量是不同的。此外,作者假设某些特征和特征通道对最终预测的贡献可能不同,因此他们在通道的开头添加了一组可学习的权重。
效率检测模型缩放
先前关于图像检测的模型缩放的工作通常独立地缩放网络的部分。例如,ResNet 仅扩展主干网络的规模。但是还没有探索联合标度函数。这种方法非常类似于为创建 EfficientNet 而进行的联合扩展工作。
作者设置了一个缩放问题来改变主干网络、BiFPN 网络、类/箱网络和输入分辨率的大小。主干网络通过 EfficientNet-B0 到 EfficientNet-B6 的预训练检查点直接扩展。BiFPN 网络的宽度和深度随着 BiFPN 堆叠的数量而变化。
EfficientDet 模型评估和讨论
EfficientDet 模型在 COCO(上下文中的公共对象)数据集上进行评估,该数据集包含大约 170 个图像类和跨越 100,000 个图像的注释。COCO 被认为是对象检测的通用挑战。如果模型在这个一般领域表现良好,它很可能在更具体的任务上表现得很好。在许多约束条件下,EfficientDet 优于以前的对象检测模型。下面,我们来看看该模型的性能与 FLOPS 的关系。
在这里,我们可以看到,在类似的约束条件下,该模型相对于其他模型族表现得相当好。作者还对 Pascal VOC 上的语义切分模型进行了评估。他们发现他们在那里也达到了艺术水*。嘿,为什么不呢?
简单来说,EfficientDet 为什么有用?
从实现细节上退一步,想想 EfficientDet 的开源检查点对计算机视觉工程师来说意味着什么是相当不可思议的。efficient net 的预训练检查点结晶了所有的发现和谷歌大脑的研究人员在建立一个 ConvNet 时放置的自动化,以及ImageNet 上的图像分类可以提供的所有监督。功能融合进一步利用了 EfficientNet 检查点,并且架构的所有组件都得到了有效扩展。最后,这些模型权重在 COCO 上进行预训练,COCO 是一个通用的图像检测数据集。作为一个用户,除了提供模型的数据类型之外,没有什么决策需要考虑。
很好的分解——我如何使用 EfficientDet?
在 Roboflow 上,我们已经在这篇关于如何训练 EfficientDet 的博文和这本关于如何训练 EfficientDet 的 Colab 笔记本上提供了一个教程。通过 Roboflow,您可以输入带有注释的数据集,只需将新的数据下载链接输入到我们的示例中,就可以得到一些结果。然后,在训练之后,笔记本将训练好的重量导出,以便部署到应用程序中!
使用我们的 Colab 笔记本中的 efficientDet 进行推理
Roboflow 是免费使用的,您可以托管和转换多达 1000 张图像。保持联系!
如果您对 EfficientDet 有一些很棒的成果,并想与我们分享,请给我们写信🎣!
一千个小玩意:我对 R Tidyverse 的看法
现在有一种 R 的主要方言,被大声宣扬,而且显然方兴未艾:Tidyverse,由 RStudio 颁布,主要是一个人 Hadley Wickham 的努力。我们应该采用它吗?学生该不该学?有 R 方言是个好主意吗?
作为一个在学术和专业领域广泛使用 R 的人——从科学研究和模拟建模到定制可视化和预测建模——我对此有一些强烈的看法,并且现在教一门 R 课程。
大体上,我对这种“整洁”的时尚持怀疑态度:它不适合我。
我不是没有同情心
很容易同情 tidyverse 最初的动力和动机:让 R 变得更容易,特别是对于非程序员。
Base R 并不容易:它是一种语言的混血儿,有许多不一致之处,是在“数据科学”成为职业之前设计的。在过去糟糕的日子里,我的许多 R 工作既痛苦又乏味,从将数据帧拼成不同的形状,到在它们之上连接和聚合。通常更容易的方法是将数据放入本地 SQL 数据库,对其进行处理,然后将其传输回 R. Ugh。我也看到很多人非常努力地学习 R,尤其是当他们是编程新手的时候——尽管 R 的核心市场是科学家和统计学家,而不是专业程序员。
所以这很糟糕,我们需要有所改变。
但是让我们客观地看待这些困难。任何人的第一门编程语言都会很难,尤其是当他们试图同时探索机器学习的时候——让一只乌龟在屏幕上移动可能天生就更容易。在研究生院,学习的人经常被强迫学习,而不是因为他们决定对编程本身感兴趣。让我们也考虑一下,仅仅因为我们需要某些东西去改变,并不意味着 R 的新方言是唯一的答案;事实上,它仍然不是(见下文)。
批评零分
这是我对 tidyverse 的第一次不好的感觉。这是一次翻拍 R 的尝试,基本上是按照哈德利·韦翰的形象。我的意思是,以一种对一个人有意义的方式完全改变 R 的界面。现在我被告知哈德利是一个非常好的人,相当谦虚,但我们不能忽视这个目标中的傲慢。为什么要由一个人来决定我们的编码风格,尤其是在开源语言中,不管他的意图有多好?也很难不把这看作是 RStudio 对整个 R 生态系统的土地掠夺——都是为了他们的利益。
现在,我是一个多疑的人,怀疑人群和狂热者——tidyverse 似乎有很多这样的人——所以你可以半信半疑地接受这第零个批评:它根本没有提到 tidy verse 的有用性,或者它的单个包装的有用性。所以我们继续吧。
批评一
比喻:你(数据科学家)是一个有抱负的厨师,试图将原料变成食物。tidyverse 试图让烹饪变得更简单,给你一个拥有三到四个 T2 千件 T3 小器具的厨房。每个小工具只做一件事,而且非常容易使用——基本上不需要什么技能。
开始做汤时,你把胡萝卜放进洗菜机;然后你把它们移到剥皮机上;然后进入去头机;然后放进切丝机。最后,你的胡萝卜就可以放进锅里了。可能也有一个该死的机器。如果你想要一个不同的切法,比如说,或者磨碎胡萝卜,你会使用完全不同的小工具。
换句话说,tidyverse 中的每一步都很简单,但是有很多步骤——也就是说,有很多功能。您必须了解每一种方法的作用、名称、参数、假设和局限性。从审美的角度来看,我讨厌这种方式。我喜欢紧凑、简洁的语法,无论我去哪里都一样。我喜欢简单、概括的解决方案——用概括的工具——而不是巴洛克式的解决方案;不管它们有多容易使用。
批评二
不过,这不仅仅是个人编码偏好的问题。tidyverse 似乎被设计成允许非程序员在根本没有学习过编程的情况下用 R 将命令串在一起。您可以过滤()和变异()数据帧,而无需学习如何索引数组;而无需部署环路;无需编写匿名函数。人们很容易编写冗长、杂乱的代码脚本,将一千个众多的函数链接在一起,却丝毫不知道它们内部到底发生了什么。
公*地说,早在 tidyverse 之前,我们就有科学家程序员的意大利面条式代码了。我没有资格说 tidyverse 在这方面真的有帮助还是有伤害。但是,当我们避免用编程语言编程时,当我们试图简化操作,因此不需要理解 R 时,我很怀疑。毕竟,这是 R 存在和我们使用它的原因:我们从实际编写代码中获得灵活性和能力。如果我们需要的是一些重塑工具的最简单的接口,也许 R 不是合适的*台?毕竟,他们为此制作图形用户界面。
批评三
我讨厌管子。它们在 unix 命令行中有意义,但在 R 中没有意义——尤其是对于难看的%>%符号。当我浏览一个函数时,我想知道有什么数据被传入其中——而不仅仅是有什么东西传入。我希望对象的名字和它们的参数是显式的,这样我就不必每次浏览时都要重新记住整个步骤序列。
让我们记住,代码是为人类编写的:编写长序列的命令是忘记正在发生的事情和犯错误的秘诀。这也是调试困难的原因,因为中间步骤是隐藏的,并且没有命名。
您真正需要知道的是,在包开发中不推荐使用管道。
但是我们能做什么呢?
如果这些问题是不采用 tidyverse 的好理由,那么应该做些什么呢?我在开头说过 tidyverse 解决了一些令人难以置信的恼人问题,这些问题需要解决。的确如此。但是这并不是采用整个 she bang——或者随之而来的编码风格的理由。例如,我使用 stringr,它是“韵文”的一个成员,对此我并不觉得有什么不好。但是我越是怀疑我的基本方法论。因此,让我们抛开管道和“tibbles”,以及我们需要一千个小函数而不是用我们选择的语言的构建模块自己编程的感觉。
对于数据帧的争论,我们在数据表中有一个非常明确的替代方案。它的功能和样式是对 base R 中括号符号的适度扩展,对于 SQL 用户来说也是高度合乎逻辑的。它也有其奇怪之处,可能更像是一个高级特性——但这样更好:先学习 base R,准备好了再学习 data.table。Data.table 不会试图降低 R,也不会试图避免编码。它给了你一把价值 1000 美元的厨师刀,而不是满厨房的小玩意,并希望你好好使用它——以免你切掉自己的指尖。
这只是风格的问题吗?是的。但是风格很重要。你可以从你的代码中删除所有的空白,这就是“风格”,但是没有人会感谢你的决定。代码也不仅仅是给人们看的,它也是给人们写的时候用来推理的。你的代码风格告诉我们你是如何思考的;它也会限制你的思维:如果你的整个世界是一系列管道和黑盒(tidverse 方式),那么有很多问题你无法解决——或者只能通过脆弱的 Rube Goldberg 装置来解决。
学习索引。学习控制结构。学习这门语言的基础知识,并用它来编写自己的工具。这就是你开始编程的原因,不是吗?
所以,放下螺旋器,拿起你的削皮刀,开始练习吧。
Jasper McChesney 是一名高级数据分析师,拥有自然科学和数据可视化方面的背景。他曾在非营利组织、人力资源和高等教育部门工作过。他目前在麻省大学教授 R 课程,在 Udemy 上: 所以你需要学习 R 。
基于不*衡 Twitter 数据集的 SVM 三级情感分类
从现场反应推文到 2016 年第一次电视直播的共和党辩论,中国人正在学习情绪分类
作为一名新闻迷,我喜欢看到政治如何在社交媒体上获得如此情绪化的回应,并想知道这种轶事般的激情感是否可以转化为机器学习分类。我发现了一个针对 2016 年第一次共和党总统辩论的推文数据集( h ere ),并希望创建一个三级情感分类器,可以从推文文本中解释情感。这篇文章是我整理的一套方法和技术的一部分,现在我将只关注一个方面;不起眼的支持向量机。作为次要任务,我注意到数据集严重不*衡,所以想尝试对少数类进行增采样,以提高分类器在所有标签中的有用性(这有望帮助分类器在所有类别中得到改进)。
数据探索和清理
谁能想到 Twitter 如此负面?作者图片
从数据集细分的原始数据中,我们立即看到了推文传播的问题。负面推文很普遍,是中性和正面推文总和的两倍多。这可能会对分类器在实践中的表现产生影响。(最有可能的是,如果像这样训练,分类器会很好地理解负面推文,但不会有太多识别其他任何东西的练习!)
“清理”数据的第一步是将所有字母转换成小写,然后从推文中删除标点符号、数字、网址和用户名。
使用“NLTK”停用词语料库从推文中删除停用词,并从推文中提取空白,每个词都被标记化,以便表示被视为停用词的单独数据块。
重复的推文随后被删除。在其他预处理步骤之后,我们决定删除重复的内容,因为 Twitter 的本质是由“转发”组成的,回复其他用户或评论的用户名可能会有完全相同的内容。这剩下总共 9836 条独特的推文准备分类。阴性:5692,中性:2521,阳性:1623。数据集被分成 80%用于训练,20%用于测试
矢量化— TF/IDF
出于对文本进行大多数数学建模的目的,以及出于该实验的目的,实施了不同的“矢量化”过程。
文本内容在没有被转换成数字以供机器学习算法读取的情况下,不能单独被改变和强制到数学空间中。
这就是为什么在本项目中,出于监督方法的目的,使用不同类型的矢量化将定性数据转换为定量数据,以便进行数学处理。这些向量成为模型的嵌入特征。
术语频率/逆文档频率(TF/IDF)
这是用于支持向量机模型的矢量化技术。TF/IDF 在训练数据上使用了一种单字方法,该方法将每个单词作为一个术语。“术语频率”是指某个单词在文本中出现的频率,“逆文档频率”是指降低在所有文本中出现频率最高的单词的重要性。
这用于产生在给定文档中频繁出现但不一定在所有文档中出现的单词。
数据*衡和采样技术
随机过采样、合成少数过采样和真实世界不*衡方法形式的数据*衡都被利用和比较。
采样技术
考虑数据*衡问题和协议是至关重要的,因为每一项行动都应减少偏差和提高真实性能,但也要尝试和减少过度拟合,并对模型的潜力有更细致的表示。考虑上采样技术很重要,因为它可以使模型更容易地勾勒出其决策边界。决定不使用欠采样技术,因为在这种情况下,由于数据集最初非常小,并且由于预处理措施和训练分割而进一步减少,所以感觉这对于提高性能没有什么作用。
没有采样
班级可能会不*衡,因为模型正在接受训练,以准确了解推文在现实生活中的表现。如果认为模型在之前没有进行上采样的情况下可能表现不佳,那就太天真了。如果给定领域中的数据天生严重不*衡,那么对不*衡数据的训练可以产生最佳输出。
随机过采样
随机过采样是从两个少数类中提取重复样本并将其添加到训练集中的过程。样本是从训练集中的少数类中随机选择的,然后被复制并添加到训练集中,在那里它们有可能被再次选择。
因为重复是精确的,并且重复的例子有可能出现多次,所以存在用这种方法过度拟合少数类的风险,并且对于实现这种技术的模型来说,数据的一般化增加了。
为了这个实验的目的,少数类都被上采样到与多数负类相同的值,因此在应用上采样之后,每个类有 5,692 个样本。
合成少数过采样技术 SMOTE
研究人员;舒拉、鲍耶、霍尔和凯格尔迈尔在他们的论文中创建了这种上采样技术,该论文以题为“SMOTE:合成少数过采样技术”的技术命名( 看这里!
SMOTE 是另一种有用的上采样方法。与从少数类创建数据点的精确副本的随机过采样相反,SMOTE 使用一种类型的数据扩充来“合成”全新且独特的示例。通过在特征空间中选择彼此接*的实例,并在这些实例之间创建边界,以及在沿着该边界的某个点创建新样本,来实现 SMOTE。这种方法往往是有效的,因为新的合成推文更接*特征空间中的其他示例,因此它们的极性可能比随机上采样的示例更接*,并且因为它们与随机过采样中的示例不完全相同,所以过拟合的可能性降低了。
估价
实验评估指标各不相同,通常取决于所执行任务的性质。一些常用于分析程序分析的评估指标包括但不限于:准确度、精确度、召回率、均方误差、损失函数分析、曲线下面积、F1 分数。不同领域中的不同模型将导致每个指标的不同结果,必须确定合适的模型,并且必须满足必要的评估标准。
精度
准确性是分类任务中最常测量的评估度量之一,并且最常被定义为正确分类的标签的数量与总预测数量的比例。
F1-得分
“F1 分数”、“F 分数”或“F 度量”是用于评估基于自然语言的任务的常见度量。它通常被认为是“精确度和召回率的调和*均值”,或者传达了精确度和召回率之间的*衡。
F-Measure 表达了精确度和召回率之间的*衡。由于准确性仅给出了模型正确结果的百分比,但并未显示出模型在寻找真正的正面结果方面的熟练程度,因此根据需要,这两种方法都有优点。
接收机工作特性(ROC)
ROC 是显示分类模型在其真阳性率(TPR)和假阳性率(FPR)方面的性能的图表。TPR 定义为模型输出的真阳性总数除以真阳性数加上假阴性总数。
曲线下面积(AUC)
AUC 统计是 ROC 曲线下的维度空间的度量。该图给出了所有潜在分类阈值的模型性能的综合得分。
对此的一种解释是,该模型将一个正的随机例子置于比一个随机负的例子更高的位置。AUC 总是介于 0 和 1 之间的数字。
ROC 度量是有用的,因为它对数据中的先验类别概率或类别流行度以及 AUC 具有不变性。这对于这项研究很重要,因为这些阶层是严重不*等的。负面类别的大量存在表明模型随机正确分类正面推文的概率增加了。
结果
以下是从支持向量机获得的结果,该支持向量机利用各种过采样技术对少数类训练有词频率/逆文档频率向量。
下图显示了根据不*衡训练数据训练的支持向量机模型的结果。此处模型的总体准确率为 60%,但从这种方法的精确度、召回率和 f1 分数来看,我们可以看到该模型在对较小的类别进行分类时表现不佳。该模型理解负类,但未能从较小的类学到很多,这从中性类和正类相当低的 18%和 19%的“f1”中可以清楚地看出。
作者图片
从下面显示的 ROC 曲线和 AUC 中,我们看到了模型性能的更全面的观点。除了中性组的 AUC 比其他组低 1%之外,所有三组的真实阳性率几乎相同。即使该模型具有 60%真阳性率的总体准确度,该模型的总体分类能力也不是特别明显。
从所示的混淆矩阵中,我们看到了 SVM 模型的实际预测值。该模型清楚地显示了其在对负面类别进行分类时的最佳性能。
这个班有 1086 个正确的预测。然而,我们只看到 37 个负类的正确预测,比这里正确预测的 10%略少。中性类有 55 个正确的预测,比这里的负类略有改进。有趣的是,这个模型错误地将一条推文标记为负面的情况比其他任何类别都多。显示了该模型如何严重依赖于负面类别来影响其决策。
作者图片
作者图片
支持向量机 TF/IDF 随机过采样类
下面显示的分类报告显示了应用随机过采样技术对少数类进行上采样时 SVM TF/IDF 模型的结果。值得注意的是,这种方法的总体准确性与具有不*衡类别的相同方法没有不同,但是模型在正确分类较小类别方面的性能确实略有提高,如负面类别上改进的 f1 分数所示。
作者图片
下图显示了采用随机过采样的 SVM 模型的 ROC 曲线和 AUC 图。该模型在所有类别中的真实阳性率在所有类别中至少提高了 4%。该模型不仅通过增加少数民族类别的样本来改进其对否定类别的分类,而且该模型在所有类别中都有相当大的改进。该模型仍然最擅长发现负类,但是当呈现更多样化的训练示例时,它也没有丢失任何这种知识。
作者图片
下图显示了 SVM ROS 模型的混淆矩阵。值得注意的是,当与不*衡数据集相比时,分类器在正确分类负面类别方面稍差(分别为 1086 对 977),但其正确分类正面类别的能力几乎加倍(37 对 70)。中性类的正确预测数量显著增加(从 55 到 140)。还需要指出的是,错误分类的负面例子的总数显著减少。
作者图片
支持向量机 TF/IDF SMOTE
下图显示了应用 SMOTE 上采样技术的 SVM-TF/IDF 的分类报告。该模型的总体准确性保持在 60%的静态水*,但是,与不*衡方法而不是随机向上采样方法相比,我们确实看到两个少数类的 f1 得分有所提高。
作者图片
下图显示了 SMOTE SVM 的 ROC 曲线和 AUC 数。通过比较下面的两个图表和指标可以清楚地看出,与 ROS 方法相比,真正的正数明显下降。当与不*衡方法相比时,这种方法仅略微有所改进。当与没有上采样相比时,负类的分类具有 2%的改进,并且通常该模型对任何类的分类能力降低 1%到 2%。
作者图片
最后,下图显示了带 SMOTE 的 SVM 的混淆矩阵。负面类别仍然是分类器正确识别的标签,但有趣的是,当使用这种技术时,中性类别的正确预测与 ROS 相比下降了几乎一半(72 对 140)。与 ROS 相比,这里的分类器使用这种技术也将推文错误分类为负面的。在这种情况下,分类器严重依赖于否定类标签,而不是使它做出的预测范围多样化。同样值得注意的是,这个模型不仅比 ROS 模型对阳性类别的错误分类更多,而且对这个标签的总预测也少得多。
作者图片
评估和结论
当在不*衡的训练数据上训练时,支持向量机发现很难做出正确的分类。不使用参数调整技术和简单的线性方法也可能导致问题。
SVM 对不*衡的数据很敏感,对自然*衡的类工作得最好。这可能导致性能下降。这也解释了为什么不*衡的实验产生了不太有用的结果。
就一般意义上的总体精度而言,所有三种上采样技术给出了相同的精度度量,但是直观上清楚的是,最好的性能始终是标记负类。
参考分类器的“F1-Measure ”,随机上采样模型给出了最好的结果。但是,必须记住,随机过采样数据会精确地重新创建实例,这有可能导致过度拟合。
在 GitHub repo 这里 上可以找到 Jupyter 笔记本以及伴随该报告的所有 python 代码!😃
爱尔兰都柏林自由数据科学家艾伦·科因撰写的报告和代码
让你的老板了解人工智能的三步秘诀
你的经理认为人工智能只是一台输入数据并自动产生输出的机器吗?你的任务是让人工智能在你的组织中发挥作用吗?那么这篇文章是给你的。
林赛·亨伍德在 Unsplash 上的照片
我不得不对你说实话,你最好长期做好你的工作。希望你对自己工作的公司充满热情,对 AI 感到兴奋。如果你真的想投资,那么这里有一个三步秘诀,让你的老板了解你,让你的生活更轻松。
没有什么比在一个期望不切实际的环境中工作更令人沮丧的了,在这样一个环境中,没有完成工作所需的资源,你不得不面对会议上和顾问们精心编造的故事。
不幸的是,改变人们的想法不会在一夜之间发生。没有一个演示能让你的老板明白其中的诀窍。你需要带着他踏上你自己的旅程。循序渐进。
第一步
帮助他们理解什么是人工智能
你的老板可能正处于一种尴尬的境地,他问你人工智能到底是什么已经太晚了。或者他只是没有时间讨论这个话题,或者还不知道他们的定义可能不正确。
那么你如何帮助他们理解呢?在你的会议中,你可以提到这样一个事实,即许多人有不同的理解,你也听说过在其他公司他们对人工智能的定义。你也想这么做。定义人工智能的含义,并让主题返回几次。给他们提供其他公司 AI 解决方案的例子。
当他们开始向别人解释这个定义时,你就知道是时候进行下一步了。
第二步
帮助他们发现人工智能在您的组织中有哪些不同的可能性
你有可能被赋予这项任务,因为如今每个公司都在“做人工智能”。现在你已经有了明确的定义,指导你的老板找到正确的用例就容易多了。教育他们如何识别可能性(提示:在那里做出许多决策,并提供大量数据)。他们需要开始看到可能性。一旦他们这样做了,就会产生你在项目中工作所需要的“拉力”。这是进入第三步的信号。
第三步
帮助他们了解如何让你的第一个项目取得成功
你可能知道将你的第一个项目投入生产是很困难的,有太多的事情需要你从技术上去发现。然后,我们甚至还没有触及采用人工智能解决方案所需的文化变革。
可能有不同的方法。我喜欢用特斯拉做例子。在跑车出现之前,没有工厂,他们必须建造工厂。在他们能够适应其他车型之前,他们需要学习如何制造汽车。他们从向一小群客户销售少量汽车开始,并可以在过程中学习。现在,Model 3 已经为更多的用户做好了准备。
如前所述,人不会一夜之间改变,也不会一夜之间学会。这是关于在一段较长的时间内填鸭式地灌输正确的信息。在更大的公司里,你可能需要几年时间才能达到目标。在中型公司,你可能会比这更快。如果你要开自己的公司…太好了!然后就可以自我教育了。
关于我:我是一名分析顾问,也是当地一所商学院“人工智能管理”研究的主任。我的使命是让数据科学家(再次)开心,并帮助组织利用人工智能创造商业价值。 在这里报名我的快讯。
整洁的预言家
由 Unsplash 上的 Viva Luna 工作室拍摄的照片
在许多没有显式循环的情况下进行预测
对于任何分析师/数据科学家来说,一个常见的问题是采用分析管道,然后在多个数据集上使用它。正如所料,R 有几种方法来处理这个问题——显式循环、*应用函数和 purrr。Purrr 是新来者(特别是对于我们这些在 RStudio 出现之前就已经了解 R 的人来说),但因为它承载了 tidyverse 背后所有深思熟虑的、富有表现力的设计,所以它可能是最强大的。
脸书的 prophet 是一个越来越流行的时间序列建模包,有 R 和 python APIs。它建立在概率编程语言 stan 的基础上,速度很快,擅长用相对较少的分析师工作量对高频率(daily plus)数据做出相当好的预测。实现 prophet“大规模预测”的承诺需要拟合多个模型,这使得它成为展示 purrr 优势的一个很好的例子。
我们将使用 google trends 每日数据进行搜索,将流行饮食与蔓越莓酱结合起来,看看 tidyverse 和 prophet 如何在几行代码中结合起来,预测尽可能多的时间序列。
蔓越莓不仅仅是用来喝的!
对于那些不熟悉的人来说, google trends 是一款用户可以输入搜索词并获得使用这些词的搜索历史的产品。可以并排放置多达五个搜索词,所有搜索词都按相同的因子缩放(我相信是屏幕上的最大值),以查看搜索活动的时间轨迹。在这种情况下,我找到了五个关于蔓越莓酱的相关搜索。
谷歌趋势:keto 超过旧石器时代两年运行在重要的蔓越莓酱搜索量!
我们在每年的美国感恩节附*都会看到一个强劲的峰值(注意,趋势数据是针对美国搜索而提取的),这与我们的直觉相匹配,并为我们提供了一组有趣的时间序列来建模。
为了将我们的重点紧紧放在结合 purrr 和 prophet 上,我已经手动将下载的数据重新调整为长格式。我还将日期列重命名为 ds,趋势卷列名设置为 y,以符合 prophet 包的要求。文件的顶部看起来像这样:
方便成形的输入数据是你如何知道这是一个教程!
为了设置我们的示例,我们需要导入。csv 文件作为我们的训练数据,并创建一个数据框架,以传递到拟合的先知模型进行预测(在代码中称为未来)。
现在,我们的表格中的数据基本上是按照。csv 文件。但是从 Hadley Wickham T1 的意义上来说,这并不十分整洁,因为对于我们的目的来说,每个搜索词(即表中的列的每个值案例、趋势数据)都是一个单独的案例或分析项目。
请记住,我们的目标是将第一个案例的数据传递给 prophet(),然后将下一个案例的数据传递给 prophet(),直到处理完所有案例。
分析大量案例的简洁方法是将给定案例所需的所有数据打包到表的一个单元格中,这样表的每一行都包含标识符、函数参数和分析单个案例所需的数据。nest()函数用于从我们现在拥有的普通*面 tibble 转换为具有嵌套列的 tibble。它是嵌套的,因为新列的每个元素都是一个 TiB ble——我们在 tibbles 中得到 tibbles,就像嵌套的洋娃娃一样。嵌套的 tibble 在每个案例中只有一行(对我们来说是 5 行),而不会丢失原始表中的任何数据(本例中有 1300 行)。
整洁怎么样?
第 7 行创建了嵌套的时间序列数据。使用默认参数调用 nest()意味着所有非分组列都嵌套到一个名为 data 的新列中。在第 14 行,我们还使用一个显式规范将未来数据案例嵌套到一个名为 future 的列中,其中嵌套的列名为 future。
现在我们可以在所有这些案例上训练我们的先知了!但是首先我们应该为 prophet()调用准备一个额外的输入。如果你记得上面的图表数据,我们可能需要包括感恩节的假日效应。prophet 包为此提供了两个选项,但是传入一个定义假日的 data.frame 与 purrr 一起使用效果更好。
第 12 行最后做了本文承诺的事情,用一行代码在每种情况下拟合一个先知模型。我们使用了*map 系列函数的最基本版本;map()有两个必需的参数:一个列表和一个函数名(不带括号!).map()所做的是遍历列表,依次获取每个成员,并将其作为函数的第一个参数传递给函数。每次调用函数的返回值都保存在一个列表中,map()调用返回所有函数返回的列表。在所有情况下都具有单个值的函数的附加参数(即,不是根据正在处理的数据列表的成员而变化的值)可以通过调用函数名后面的 map()来传递。在我们的例子中,holidays=turkeyDayUSA 论证了这一点。
我们要传递的列表在哪里?map()的第一个参数是数据。回想一下,这是我们用 nest()调用生成的 nestedData 中的列名。在 R 中,data.frame(以及 tibble,tidyverse 的等价物)的每一列都是一个列表。也就是说数据是一个列表。因为 map() 也输出一个列表,这个输出可以用来创建一个 tibble 的列。mutate()函数在这里为我们处理这个问题,但是我们也可以很容易地用nestedResults$model=map(data,prophet,holidays=turkeyDayUSA)
直接添加列。模型列表的每个成员都是类先知(具有复杂结构)的对象这个小细节根本不会困扰 R,也不应该困扰我们。
坦白地说,所有这些都很难想象,所以我建议您运行代码(来自 github repo ),然后使用 nestedData 表。你觉得 nestedData\(data[[1]]是什么?或者 nestedData\)data[[1]][1,:?
12 号线只是一个开始。因为一旦我们理解了 map()的工作方式和嵌套列的工作方式,我们就可以画一条线 19。这里我们展示了 pmap(),它只是对 map 的一个通用调用,允许从列表中提取任意数量的(可选的)命名参数并传递给函数。我们还利用了这样一个事实,即在单个 mutate()调用中,我们可以创建变量,然后在下一个要创建的变量中使用它们来为第 12 行中的模型创建预测和绘图。是的,我们可以很容易地在一个 mutate()调用中包含第 12 行的模型拟合。
我将把从 nestedResults 中提取情节的练习留给读者(提示:像访问常规列一样访问列名,然后记住它是一个列表!).
预言家预测 keto 蔓越莓酱去年达到顶峰
我希望这篇文章有助于解释 purrr 包的函数式编程工具。与其他 tidy 工具一样,*map 函数简化并阐明了一项常见任务的编码。在这种情况下,该任务在多个案例上运行一组步骤。更简单和更清晰的代码意味着更少的时间调试和检查搜索 stackoverflow 和更多的时间尝试花哨的模型和向关键的利益相关者展示结果——这对任何人来说都是一个胜利。
本文引用的完整代码和附带的源数据文件可以在github上找到。
从 a 到 Z:使用此规则集的主数据可视化
图片由 Free-Photos 来自 Pixabay
简介:
无论您是尝试进入数据分析还是数据科学领域,无论您是产品经理、销售主管还是任何希望了解其业务的人,能够以有意义的方式利用数据都是关键。无论你使用的是 Tableau、Domo、PowerBI 等数据可视化软件。或者你用的是 R,Python 等语言。有各种各样的原则和概念可以帮助你开始。
您分析的目的:
首先,请记住,任何分析都应该有一定的目的。看着图表,很容易问自己:“我为什么要看这个?”或者“我应该在这里得到什么?”。归结为一个非常简单的原则,我们希望了解给定变量的性质&该变量可能与其他变量有什么关系。
需要牢记的关键事项:
维度,数据类型
维度:
这里我们讨论的是 3D 中 Ds 的数量。所以当你在二维空间玩超级马里奥的时候,你有一个 x 轴和一个 Y 轴。我们大多数人都见过许多二维图表和图形。思考这个问题的方法是,“在一个给定的可视化中,我想要包含多少个变量?”。作为这里的一般规则;少往往就是多。
数据类型:
字段是否为数值型;年龄、体重等。绝对的;性别,发色等。或者时间;某事发生的日期、月份或日期。一旦你理解了这一点,并对某些变量之间的关系有了一些假设,你就可以开始规划你可能使用的可视化类型。
语言和数据集:
所有的可视化都将使用 R 中的 ggplot2 包,使用各种样本数据集,包括 iris、mtcars、mpg 和 economics。我不会在这里包括太多的 r 代码,因为我希望这是广泛适用的,但如果你想要这些代码,请在下面评论或联系。
跳跃中:
在我们实际进行任何可视化之前,我们还需要做其他事情来理解数据,但是我们将直接进入可视化,以便具体了解可视化的规则。
我们将按照数据类型和维度,从一个维度开始,讨论各种选项和规则。
维度数量:1
数据类型:数字
数据集:mtcars 包含在 base R 中的样本数据集给出了汽车上的各种数据点
目的:了解分布和汇总统计
图表:直方图和箱线图
当试图孤立地理解一个数字变量时,你首先要理解它的分布。为此,您将使用一个简单的直方图来告诉您每个值出现了多少次。我们想了解的第一个变量是马力。
我们在这里看到的是,马力向右倾斜,或者说峰值右侧的尾部比左侧的尾部延伸得更远。如果你想一想一辆汽车的典型马力,大多数将小于 250,但肯定仍有汽车被制造来推动这一极限,尽管少得多。
这是同一变量 hp 的盒状图、盒状图和须状图。箱线图对于可视化给定变量的大量汇总统计数据非常有用。图末端的水*线代表最大值和最小值。黑色水*线是中间值。中位数所在的方框表示 IQR 或四分位数范围(将数据分成四个偶数四分位数,IQR 表示第一个四分位数和第三个四分位数之间的范围)。
这里我们看到一个每加仑英里数的直方图,我们看到一个稍微右偏的分布。它也几乎呈现双峰。双峰是指实际上有两个峰值。一种解释是,我们重叠了燃气汽车和电动汽车的分布,所以我们假设燃气汽车的*均 mpg 在 15-20 之间,而电动汽车的*均 mpg 在 30-35 之间,那么如果有足够的量,我们可以在分布中看到两个峰值。
我们现在关注 qsec。汽车性能指标。这是汽车行驶一英里所需的时间。我们在这里看到的是一个非常标准的正态分布。
维度数量:1
数据类型:分类
数据集:mpg 包含在 base R 中的样本数据集给出了汽车上的各种数据点
目的:理解比例
图表:条形图和饼图
当试图孤立地理解单个分类变量时,您要考虑的主要问题是一个给定术语出现了多少次。
现在让我们来看看 mpg 数据集中的变速器和等级变量。为此,我们将创建一个条形图,X 轴上是分类变量,Y 轴上是出现次数。
在这里,您可以了解到哪些传播是经常发生的,而哪些传播似乎稍微少见一些。通常你不需要包括颜色,只是为了让事情更清楚一点。
类似地,我们可以看到按类别绘制的事件计数。我们可以看到,与 SUV 或紧凑型车相比,2 座车和小型货车的出现频率要低得多。这个条形图可以像饼图一样容易地显示出来。饼图有时比条形图更难描绘给定切片的体积,因为任何给定切片都有不同的角度,可能在饼图的不同侧,等等。
如上所述,这是一个类变量的饼状图。
此外,我们可以使用条形图来绘制分类变量的其他聚合。例如,每辆车*均每加仑跑多少英里,但我们会在后面讨论。
好了,现在我们已经单独研究了数字变量和分类变量;让我们将绘制的维度数量增加到两个,并查看一些不同的组合。
维度数量:2
数据类型:数字
数据集:Iris & mpg 包含在 base R 中的样本数据集给出了三种鸢尾的各种数据点以及它们的一些测量值
目的:理解两个变量之间的关系
图表:散点图
每当试图理解两个数值变量之间的关系时,散点图是最佳实践。
在这里,我们试图观察萼片的长度(Y 轴)和宽度(X 轴)之间的关系(对于植物解剖,只需运行快速谷歌搜索..😃 )
我还查看了这两个变量的相关性(衡量两个变量如何相关或一起移动,1 表示移动完全同步,-1 表示它们完全相反,5 或-.5 是良好的关系,3 或-.3 可能是弱关系,任何低于这一水*的都是弱关系或随机关系),发现它是-.11,表明没有真正的关系。虽然看起来这两个变量是不相关的;考虑变量之间关系的许多潜在层面是很重要的。
这个我以后再讲,现在先来先睹为快。虽然在前面的图中,我们看到宽度和长度似乎不相关,但尽可能多地包括潜在的视角是很重要的。看着和之前一样的剧情,我们准备给它再增加一个维度;物种。我们将用颜色来显示物种。
一旦我们添加了第三维,我们可以看到,在物种的长度和宽度之间有一个清晰的线性关系。
下面我已经包括了按物种分组时的相关性,我们可以看到在高端的相关性为 0.74,在低端的相关性为 0.46,这仍然是相当可观的。
现在让我们回到评估两个数值变量。在这里,我们看到的是城市英里数和公路英里数。这里,散点图以线性方式向右上方移动,表明两者之间存在正相关关系。这两个变量的相关系数为 0.96。
如果你是统计学新手,需要记住一些事情。即使这些东西一起移动。并不一定意味着一个是另一个的原因。这只能说明他们有血缘关系。
为了继续评估二维数据的其他组合,让我们考虑如何分析两个分类变量之间的关系。
维度数量:2
数据类型:分类
数据集:mpg 包含在 base R 中的样本数据集
目的:理解两个变量之间的关系
图表:表格、热图、条形图
在开始可视化之前,我将在一个表格中展示两个分类变量,因为两个分类维度的可视化代表了我们在表格中会发现的内容。
下表来自 mpg 数据集;我们正在考虑汽车的级别,以及汽车是四轮驱动、前轮驱动还是后轮驱动。
在这里,我们可以看到属于任何给定分类变量组合的记录的频率
一眼就能看出 SUV,4 轮驱动是最常见的。你可以添加的另一层是把每个单元格看作整体的一个百分比。
关于道具桌还有更多内容要做,但是我们将把它留到下一次。
从这里开始,我们要想象我们在道具桌上看到的东西。
将这个表格可视化的一个很好的方法是使用热图。看看下面的图表。在任一轴上,您可以看到分类变量,热图的颜色由出现次数表示。
正如我们在原始表格中看到的,SUV,4 轮驱动是最常见的,中型前轮驱动次之,紧凑型前轮驱动第三。
热图在准确测量数量方面存在一些困难。我们有一个图例,根据你使用的软件,你可以很容易地把它作为工具提示。
另一个选项是返回到条形图,其中一个分类变量在 x 轴上,数值变量(计数)在 y 轴上,第二个分类变量在颜色维度上表示。
在这里,我们可以再次看到哪种组合是最频繁出现的,从而使我们达到类似的目的。
下一个绘图选项非常相似,但是除了用颜色表示第三维,我们还可以使用刻面。分面是一种技术,它允许您为分类变量的每个级别提供自己的绘图。看看下面。
正如这里提到的,我们可以看到一个与之前非常相似的情节,但是每个职业等级都有自己的情节。
在这一点上,我们已经看到了各种图表非常相似的结果。你要考虑的是一个给定的情节在多大程度上传达了你的信息或产生了必要的洞察力,它是否过于复杂,它是否占用了太多的空间,潜在的利益相关者会在多大的屏幕上看到你的图表,等等。
现在我们开始绘制多维度的图。
维度数量:3–5
数据类型:数字和分类
数据集:mpg 包含在 base R 中的样本数据集
目的:了解多个变量之间的关系
图表:散点图
在这里,我们看到的是与之前相同的图,只做了一处修改。为了包括“发动机排量”的第三维度,我们现在改变点的大小以对应发动机排量。正如我们所见,它似乎与较高的城市和公路里程数成反比。
现在,添加维度的另一个选项是颜色。
我现在用颜色来表示发动机排量,而不是用尺寸。
在下面,我添加了一个我们两者都做的额外的情节,这使得它更容易被看到。
需要记住的一点是,我们可以引入第四个数字维度,而不是用颜色和大小来表示发动机排量。
这里我已经换出了 cyl 来填充尺寸维度;这似乎也与公路和城市 mpg 成反比。
我们在这里可以介绍的几个其他选项可以是使用颜色来引入分类变量或根据分类变量来分面。
在这里,您可以看到现在按类分面的示例图,这使我们可以看到这些数字变量在分类变量的不同级别上如何相互关联。
在我们总结之前,最后要考虑的是我们是否有一个表示时间的变量的二维数据。时间的一个重要经验是使用折线图。
维度数量:2
数据类型:数字和时间
数据集:经济学;包含在 base R 中的样本数据集
目的:理解时间和数字变量之间的关系
图表:线条
我们将要研究的数据来自经济学样本数据集,代表了过去 50 年左右的失业率。
当绘制具有时间维度的数据集时,我们试图识别给定数值变量中的趋势,以了解趋势以及给定活动是否可能与该运动一致。把你的时间维度放在 X 轴上,把你测量的数值变量放在 Y 轴上。
即使在这里,还有很多事情可以做,但我将把它留到下次再做。
外卖:
- 一维
- 数字:直方图,盒状图
- 分类:表格、条形图、饼图
- 二维
- 数字/数字:散点图
- 数字/分类:条形图
- 分类/分类:条形图、表格
- 三维
- 数字/数字/数字:大小/颜色散点图
- 数值/数值/分类:带颜色/面的散点图
- 数字/分类/分类:带颜色/面的条形图
- 4+维度
- 在 x 和 y 轴上使用不同的数据类型和变量的组合,以及颜色、填充、大小、刻面等。
使用数据可视化可以做很多事情&这仅仅是开始。希望这能帮助你开始!
如果有帮助,请将您自己添加到我的电子邮件列表中;另外,如果您喜欢代码示例、附加信息等,请务必告诉我。
来看看我在 datasciencelessons.com 的其他帖子吧&祝数据科学快乐!
甘潜在空间的合作工具
2020 年 1 月,我们完成了骨髓的开发阶段。 shirin anlen 和我正在分享在这个过程中吸取的经验教训,我们关于优化和扩充一个小数据集的帖子最*发表在了toward SATA science上。这篇文章着眼于在使用机器学习模型时,定制的基于网络的工具如何激发协作的艺术工作流。
利用网络浏览器工具制作甘《潜伏空间》中的阴影动画
我和骨髓
髓是石林安伦的一个动手研究项目和互动剧场体验,探索精神障碍在机器学习中的可能性。我之前与希林合作过许多项目,最著名的是虚拟现实纪录片Tzina:Symphony of desire。2018 年,我加入了 shirin,在 2018 年 IDFA Doclab上预览骨髓装置。原型取得了成功,一年后我们作为合作者进入了由加拿大国家电影委员会和 Atlas V 共同制作的密集开发阶段。
关于甘及其潜在空间
生成对抗网络,或 GAN,是我们决定研究的第一个机器学习模型。它专注于生成性视觉意象,如果你试图用*庸的股票图像训练它复杂的概念,它会表现出非常明显的不协调。在之前的一篇帖子中,我们描述了我们如何创建一个由“完美家庭晚餐”图像组成的数据集,并用它来训练斯泰勒甘·V1。这个特殊的数据集是为体验的故事而构建的;一个功能失调的家庭,只能通过被训练出来的扭曲数据来看待自己。正因为如此,我们的目标是不完美的结果,并代表当模型试图深入社会叙事时出现的故障。
我们的数据集是一捆大约 6500 张图片,包含四个家庭成员的照片,从他们的家庭晚餐场景中剥离出来。一旦 StyleGAN 完成了训练过程,我们就有了一个新生成的包含四个扭曲家庭形象的图像的巨大空间。输出图像的无限、连续的可能性空间被称为 潜在空间 。它是“潜在的”,因为 GAN 生成的输出图像是由一个看似隐藏的数学变换过程确定的,从一系列数字开始,以位图图像结束。当您更改系列中的任何初始数字时,生成的图像会略有不同。变换网络如此之深,以至于很难预测图像中会发生什么变化。
潜在空间转换动画
如果你有足够好的数据集和算法,你也许能够达到解缠:即当一个输入数字控制结果图像中一个有意义的元素;例如,一个数字会改变一个生成的人的年龄,而另一个数字会改变他们的头发颜色。不用说,我们无法解决小数据集的问题。从最初系列的一个单一数字的变化可能导致多个家庭成员的各种变化。同一个数字可以同时控制一个家庭成员的姿势,另一个成员的微笑,以及第三个人物的圣诞帽的外观(这似乎是日常图片中的重复主题)。这些家庭成员事实上是纠缠在一起的。
影子寓言
髓跟踪它的每个模型的“思考”过程,并询问什么可能出错。在 GAN 中,潜在空间为我们提供了关于输入数据如何被分解,然后重建成新的东西的信息。但是,尽管视觉化潜在空间很有趣,我们还是在寻找将讲故事融入体验的方法。我们想把甘扭曲的世界形象物化。
在观察甘正在进行的训练过程时,我们开始注意到来自源数据集的非人类的东西。这就像盯着罗夏测验;根据观看者的不同而呈现不同的*面图像。我们意识到,我们对 GAN 的了解不是通过看到我们期望的结果,而是通过看到它的中间空间。柏拉图的洞穴寓言谈到了在简单扁*的事物表象中寻找意义。寓言中的人被困在一个山洞里,外面着火了。火把经过的物体的影子投射在洞穴的墙壁上,这就是他们所能看到的现实。他们如此习惯于那些阴影,以至于一旦囚犯挣脱,他们的眼睛就会被耀眼的阳光灼伤。当囚犯的眼睛终于习惯了现实,他们回到洞穴告诉其他人,但现在他们在黑暗中什么也看不见。其他囚犯认为外面有邪恶的东西。
有趣的是,柏拉图的洞穴寓言与的结构和甘的训练过程非常吻合。甘始终处于现实、现实的再现和幻想的冲突之中。当该算法生成的图像过于接*原始数据集时,它会发现自己陷入了一个简单而扁*的世界表示中,无法逃脱创造性的途径。当甘的后代过于荒诞的时候,他们就不可避免地被认为是假的和错误的。甘一直在努力寻找现实与想象之间的*衡。因此,我们决定通过使用扭曲的家庭输出的阴影表示来可视化甘的斗争。
全色过渡与阴影模式
在潜在空间上制作动画
髓是一个互动的戏剧作品,参与者在家庭晚餐环境中扮演机器学习模型的角色。在体验中,一名代表甘的参与者讲述了他们在区分记忆和想象时面临的困难——这两种感知在甘的作品中实际上都被扭曲了,因此我们决定在这一阶段探索阴影世界中的附加幻想动画层,这将代表人物在真实和虚假之间的斗争。我们和才华横溢的帕洛玛·道金斯一起工作,他是手绘动画和交替维度的大师。现在,我们必须问自己:我们如何编排一个工作流程,从甘的数学深度开始,但以手绘动画结束,完美地匹配甘在图像空间中的潜在运动?答案来自我们定制的工具: 骨髓甘探索者。
骨髓@ NFB 2020 _ 安德烈本达汉 2020 NFB。版权所有
骨髓甘探索者
髓甘探索者是一个基于网络的交互式工具,让团队成员探索风格甘 V1 结果的潜在空间,并在潜在空间的不同点之间创建关键帧动画链。
来自 web 浏览器工具的屏幕截图
动机
开发这个工具的主要动机是让我们能够与一个额外的团队成员一起工作,在这个例子中是一个动画师,处理机器学习输出。我们希望动画师能够探索潜在的空间,选择他们感兴趣的过渡来制作动画。一旦他们做出选择,他们可以将该序列保存为机器学习模型可读的格式,并可以实时加载和推断。同时,他们可以将过渡保存为视频文件,以便加载到他们的动画软件中,并逐帧制作动画。这回答了我们当时的两个主要问题:第一,给动画师创作的自由,第二,确保在体验中链接时序列将完美同步。该工具还允许我们在网上交流,并在对创作过程进行头脑风暴时查看相同的序列。它还允许我们以彩色和理想的输出形式查看源:阴影。
用例场景
我们录制了一段视频,展示了我们工具的常见用例:
用例视频
链接动画
浏览器的一个更优雅的特性是链接动画的能力。假设动画师生成了一个 12 秒的潜在空间过渡,并在其上画了一个漂亮的动画。现在,他们可以使用该工具以另一个序列推进故事。通过加载第一个过渡,然后选择使用目的地作为下一个源,艺术家可以生成一个序列,它是前一个序列的延续,并在非线性潜在空间上创建一个线性故事。
帕洛玛·道金斯的动画叠加甘的阴影输出
在后台
潜伏空间探索者的代号是免费提供 这里 。这将需要对其他项目进行调整,但只要该模型是基于 StyleGAN 的,就应该非常简单。迁移到其他类型的 gan 也应该相对简单。
在我们的 GitHub 上,你可以找到浏览器各种特性的详细解释和代码遍历。
反光
这是为无障碍交流寻找解决方案的时候了——不仅为公众,也为团队成员之间。我们需要创造性地思考如何让每个人都参与到使用复杂技术的过程中。这是我们对彼此的责任。在某种程度上,与游戏中的关卡设计过程没有什么不同,像“潜在空间探索者”这样的工具将创作带到了前端,但在后端却讲述了模块化和娱乐的语言。
在整个过程中一起工作,并坚持在每一步中采取艺术方向,这是非常有力量的。在《骨髓》的创作过程中,我们坐在一起观看和选择镜头,玩得很开心。当我们目睹眼前紧张的视觉效果时,保存在服务器上的数据是一系列简单的数字,这些数字触发了一个巨大的计算网络,产生了不可预见但却惊人一致的后果。同样,我们并不总是知道为什么我们喜欢一个特定的序列,我们只是感觉到它。这是我们共同的直觉。
骨髓@ NFB 2020 _ 安德烈本达汉 2020 NFB。版权所有
开发阶段是与音效师菲利普·兰伯特和动画师帕洛玛·道金斯合作完成的。
建筑中的人工智能之旅
阿森纳馆的虚拟之旅
人工智能与建筑虚拟之旅|来源:作者
在本文中,我们将介绍正在巴黎阿森纳馆博物馆展出的“人工智能建筑”的内容。由于最*发生的事件,博物馆已经关闭了大门,但重新在网上开放,并在今天提供展览的虚拟参观,免费提供。我们在这里揭开展览的部分内容,并邀请您参观,使用 t 和兵工厂馆的虚拟之旅 。
展览虚拟参观演练
一、简介
人工智能(AI)已经进入了这个行业,为它提供了迎接新挑战的手段。它在建筑领域的应用仍处于初级阶段,但已经获得的预期结果是有希望的。这项技术不仅仅是一个机会,它无疑是向前迈出的决定性一步,完全有能力改变建筑实践。本次展览探索了这种参与及其在建筑环境中的应用。定义人工智能,解释它所包含的技术和范例,是理解它在建筑中出现的核心。
人工智能首先需要从科学史和建筑史的角度来考虑。围绕和支持人工智能的技术进化不是“颠覆”,而是一个缓慢成熟的结果。事实上,这个职业已经经历了相当长一段时间的转变。技术解决方案的逐步采用已经深刻改变了价值链的每个阶段:首先是利用新的建筑技术,然后是开发适当的设计软件,现在是引入统计计算能力,包括前沿的数据科学和人工智能。从今以后,与其说是一个激进的轨道改变,不如说我们希望看到一个轨迹的改变,它的加速最终是在一种实践的延续中,这种实践将建筑引向了今天的样子。模块化、计算机辅助设计(CAD)、参数化和人工智能(AI)是一个序列中不可阻挡地交织在一起的四个阶段,这一序列构成了我们实践的缓慢混合,比如我们今天所经历的和可以想象的。
汇集了具体的例子和最*在各个研究领域取得的成果,我们首次展示了人工智能在建筑中的存在,以及该领域最新进展的全景。立面、*面、结构、视角:尽可能多的尺度来衡量人工智能已经可以做出贡献的城市,无论是真实的还是假设的。
在当前的理论和实验之间,这个展览旨在阐明一个新技术时代的开始,利用建筑实践,同时赋予它新的相关性。
在下面的视频中,我们展示了 2 月 27 日在阿森纳馆举行的展览开幕式。在这个演讲中,我们总结了展览的远大目标,同时勾勒出人工智能在建筑中的潜力。
二。历史
M 协同性、计算设计、参数化以及最后的人工智能** 是塑造了过去 100 年建筑系统化的 4 个相互交织的步骤。人工智能只是这种渐进努力的最新发展。我们在这里提供每个时期的解包,并用关键事件和历史人物来说明它们,以建立人工智能在我们的学科——建筑——中的出现。
A.模块性
w·格罗佩斯的《包卡斯滕》(最左)巴克明斯特·富勒的《迪马克森之家》(左)麦克劳林的《温斯洛·艾姆斯之家》(右)萨夫迪的《人居 67》(最右)
模块化可以被定义为系统化建筑设计的起点。瓦尔特·格罗皮乌斯在 1920 年为包豪斯提出的“模块化网格”理论,带来了技术简单的希望和廉价建筑的承诺。最初,它是作为学者和实践者探索的主题出现的。格罗皮乌斯和阿道夫·迈耶一起引入了“包卡斯滕”的概念,这是一种具有严格组装规则的典型模块。在同一时期,里查德·巴克明斯行·福勒提供了一个更系统的模块视图,其中集成了管道,结构等。他的 Dymaxion house(1929-1946)将模块化住宅推向了极致,开创了一个充满活力的先例,也是该行业首次令人信服的概念展示。这种标准化后来在勒·柯布西耶的“模块”(1945)中得到了阐述,该书将模块思想应用于人体尺度,早在 1946 年就使这一原则的整体实施成为可能。
通过 Modulor,建筑环境的尺寸与人体比例的关键指标和比率保持一致。因此,从马赛的“统一住宅”(1952 年)到埃沃的圣玛丽·德拉图雷修道院(1959 年),勒·柯布西耶系统化了与这种规模相关的维度和跨度。
遵循这些早期的理论家,建筑师调整他们的做法,以优先考虑矩阵,这相当于将建筑设计的部分技术方面转移到模块的逻辑。这些论点证明是令人信服的:施工可预测性的显著提高降低了设计的复杂性和成本。模块化然后迅速扩展到整个领域:由罗伯特·w·麦克劳克林教授于 1933 年在美国建造的温斯洛·艾姆斯住宅是世界上第一个大规模模块化项目之一。这一倡议理所当然地被视为一项重大突破,很像摩西·萨夫迪 1967 年在加拿大提出的人居 67。
模块化甚至影响了 20 世纪 60 年代早期的城市规划,当时像 Archigram 的“插件城市”这样的项目渴望创造完全模块化的城市。通过不断组装和拆卸三维结构矩阵上的模块,城市有望找到一种新的逻辑,解决增长的可能性和可行性的必要性。理论最初的圆滑很快就达到了极限,过早地被耗尽。事实上,将建筑设计限制在一个简单的设备上,用于组装在框架上机械调整的模块,最终导致了它的衰落。架构不能被解决为将它的实践局限于组装者的角色,仅仅是规则和过程的保证者,特别是因为结果被证明是单调的,并且组装系统暴露了真正的建设性弱点。然而,如果严格遵守的模块化显著地影响了专业的实践,由于其规则系统,它也是普遍的,并对建筑设计的基本原则有持久的影响。
B.计算机辅助设计
帕特里克·汉拉蒂的 PRONTO(最左),n·内格罗蓬特的 URBAN II(左),n·内格罗蓬特的Seek****,塞德里克·普莱斯的 GENERATOR(最右)
计算机技术(微处理器、内存、个人电脑、网络等)的激增。)允许模块化设计前所未有的复杂性。20 世纪 80 年代初,标志着基于规则的建筑设计系统化的复兴。
事实上,早在 20 世纪 50 年代中期,一些工程办公室就开始了对计算机设计潜力的基本分析。1959 年,Patrick Hanratty 教授发布了第一个 CAD(计算机辅助绘图)软件原型 PRONTO,它是为设计工程组件而创建的。该软件提供的可能性,加上计算能力的快速发展,引发了建筑领域的讨论。
从 20 世纪 70 年代起,整整一代的计算机科学家和建筑师开始创建一个新的研究领域:计算机辅助建筑设计(CAD)。尼古拉斯·尼葛洛庞帝教授于 1967 年在麻省理工学院创建的建筑机器小组(AMG)可能是其中最突出的例子。尼葛洛庞帝的书《建筑机器》(1970 年)概括了 AMG 使命的精髓:“研究机器如何增强创作过程,更具体地说,是作为一个整体的建筑生产”。随着项目 URBAN II 和后来的 URBAN V 的发布,这个团队甚至在行业在该领域取得任何进展之前就展示了 CAD 应用于空间设计的潜力。几年后,时任剑桥大学建筑系主任的塞德里克·普莱斯发明了发电机(1976 年)。在 Negroponte 之后,Price 使用了 AMG 在人工智能方面的工作,并通过探索一种不断进化的自主建筑的想法来扩展它,这种建筑能够“智能地”做出反应以适应用户的行为。根据 Price 的说法,“智能”一词体现了生成器设法模仿的行为。
在麻省理工学院这一新动力的基础上,建筑师和整个行业积极地将这些发明转化为大量的创新。建筑师弗兰克·盖里无疑是这项事业最活跃的倡导者,他认为计算的应用是彻底放松装配系统的界限并赋予他的建筑新的形状和几何形状的手段。Gehry Technologies 由 Gehry 和 Jim Glymph 于 20 世纪 80 年代创立,使用早期的 CAD-CAM 软件(CAM:计算机辅助制造),如达索系统公司的 CATIA,来处理复杂的几何问题。Gehry Technology 为未来三十年的计算设计开创了先例,向建筑师展示了 CAD 的价值。在接下来的 15 年里,计算能力和数据存储能力的惊人增长,加上越来越便宜和更加用户友好的机器,极大地促进了 3D 设计软件的采用。设计者很快就掌握了这种新系统,通过严格控制几何形状,提高了设计的可靠性、可行性,并降低了设计成本;促进设计师/建筑师之间的合作,此外,与传统手绘相比,能够实现更多的设计迭代。更多的测试和更多的选择来获得更好的设计结果,这就是目标。然而,缺点最终会出现。特别是,某些任务的重复性和缺乏对复杂几何形状的控制成为严重的障碍。面对这些限制,一个超越 CAD 的新范式出现了:参数化。
C.参数化
路易吉·莫雷蒂的 N 体育场(最左)伊凡·苏泽兰&画板(左)蚱蜢界面(右)扎哈·哈迪德建筑师事务所的卡尔塔尔-彭迪克总体规划(最右)
参数主义允许建筑师更好地掌握复杂的形状,同时避免重复的任务。由于这种新方法,每项任务都被合理化为一套简单的规则,构成了一个过程。这个过程可以由架构师编码到程序中,以便自动执行以前手动和繁琐的执行。然而,在允许给定过程的编码的同时,参数化程序有助于隔离影响结果的关键参数。然后,建筑师能够改变参数,以生成不同的可能场景:通过简单地改变先前定义的参数,立即生成不同的形状或选项。
20 世纪 60 年代初,建筑师 Luigi Moretti 倡导了参数化建筑的出现。他的项目“N 体育场”,是参数化的第一个清晰表达。通过定义 19 个驾驶参数,其中包括观众的视野和 tribunes 的阳光照射,Moretti 建立了一个严格的程序,直接负责建筑的形状。参数集的每一个变化都为体育场引入了一种新的形式。最终的形状可能会令人惊讶,但它给出了这种新的参数美学的第一个例子:尽管来自一个准科学的过程,但结果因其有机性而引人注目。
三年后,伊凡·苏泽兰将这些原则应用于设计软件,他创造了画板,这是第一个真正用户友好的 CAD 软件。嵌入软件核心的“原子约束”概念是萨瑟兰对莫雷蒂“参数”概念的翻译。在用画板绘制的图形中,每种几何形式都被机器翻译成一组原子约束,换句话说,就是参数。这个概念是参数化设计在计算机术语中的首次表述。Samuel Geisberg,Parametric Technology Corporation(PTC)的创始人,于 1988 年推出了 Pro/ENGINEER,这是第一个为用户提供完整几何参数访问的软件程序。随着软件的发布,盖斯伯格完美地总结了参数理想:
“我们的目标是创建一个足够灵活的系统,鼓励工程师轻松考虑各种设计。设计变更的成本应该尽可能接*零。”
由萨瑟兰和盖斯伯格建立的设计和计算之间的桥梁,使新一代“参数意识”建筑师得以出现。事实上,少数关键人物采用参数化方法将这种新方法转化为整个行业的实际创新。扎哈·哈迪德建筑师事务所是建筑参数化的杰出代表。作为一名在英国接受教育的伊拉克建筑师和数学家,Hadid 使用参数化设计融合了数学和建筑。她的工作通常是规则的结果,编码在程序中,允许对建筑物的几何形状进行前所未有的控制。每个建筑决策都被转化为一组给定的参数,从而形成特定的建筑形状。对于扎哈·哈迪德建筑事务所的公司董事、建筑师和工程师帕特里克·舒马赫来说,这门学科因此向参数化主义靠拢,不仅作为一种设计技术,而且作为一种建筑风格。在他的书《参数化——建筑和城市设计的新全球风格》( 2008 年)中,他解释说,在建筑环境的每个阶段,参数化与对“参数”概念的日益增长的认识有关。如果没有大卫·于滕在 2000 年代开发的软件 Grasshopper,这项工作是不可能完成的。Grasshopper 是一个可视化编程接口,它允许架构师轻松地隔离设计的驱动参数,同时允许他们迭代地调整这些参数。其界面的简单性加上内置功能的智能性继续推动着世界上大多数建筑的设计,并激发了整整一代“参数化”设计师。
然而,自 21 世纪初以来,由参数化驱动的一场更深刻的革命,使参数化在大多数建筑师的日常实践中盛行:BIM(建筑信息建模)是其最显著的表现。由时任 Autodesk 副总裁的菲利普·伯恩斯坦(Philip Bernstein)倡导的 BIM 的创建和发展,将建筑行业的合理性和可行性提升到了一个全新的水*。BIM 的基本思想是,3D 建筑模型中的每个元素都是参数(“属性”)的函数,这些参数驱动每个对象的形状并记录它。从萨瑟兰的画板到 Revit——当今使用最广泛的 BIM 软件——都有一个共同的主线:明确使用参数作为设计的驱动力。
D.人工智能
、(左)、【Nvidia Research】AI 生成的人脸(中)、【GAN】模型架构(右)
人工智能(AI)基本上是一种架构的统计方法。人工智能似乎不仅对参数化建筑的局限性做出了回应,而且最重要的是开启了建筑设计的全新时代。
1956 年,美国数学家约翰·麦卡锡发明了人工智能的概念,即“用人脑作为机器逻辑的模型”。人工智能不是设计一个为一系列变量和规则构建的确定性模型,而是让计算机根据从数据中收集的信息或用户传输的信息来创建中间参数。一旦达到“学习阶段”,机器就可以生成解决方案,这些解决方案不只是简单地回答一组预定义的参数,而是创建模拟学习阶段期间接收到的信息的统计分布的结果。这一概念是人工智能带来的范式转变的核心。机器建立自己对问题的理解的部分独立性,加上它消化一组例子的复杂性的能力,破坏了参数化的前提。由于并非所有的规则和参数都由用户事先明确声明,因此机器可以出人意料地揭示潜在的现象,甚至试图模仿它们。这是从启发式世界(基于规则的决策)到统计建模世界的巨大飞跃。
80 年代初,计算能力的突然增强和经费的急剧增加给 AI 研究带来了第二股风。这个时期的关键是两个主要的革命:专家系统和推理机。第一种对应于能够使用条件语句基于一组规则进行推理的机器。当时真正的突破是 Cyc,由 Douglas Lenat 开发的项目,涉及面向推理推理的机器。使用知识库(一组建立为真的陈述),推理机能够推断出一个新陈述的真实性。
直到 20 世纪 90 年代早期,人工智能的高级数学化,这个领域才提供了有希望的结果。一种新型模型的出现揭示了人工智能潜力的第二个领域:网络和机器学习。由于使用了“分层”计算机模型,也称为“神经网络”,因为它们回忆了人脑的神经结构,所以现在机器可以掌握比以前开发的模型更复杂的东西。这种模型可以被“训练”,或者换句话说,针对特定的任务进行调整。在受这一发展启发的众多创新中,生成性对抗网络(GAN)被证明与建筑尤其相关。谷歌大脑(Google Brain)研究员伊恩·古德费勒(Ian Goodfellow)在 2014 年提出了这一理论,该模型可以从神经网络生成图像,同时通过自我纠正的反馈回路确保一定程度的准确性。
Goodfellow 的研究将人工智能从一个分析工具变成了一个生成代理,这样做使它更接*于建筑问题:设计和图像制作。换句话说,人工智能现在代表了该学科的新一代负担得起的、强大的和相关的工具。如果尼葛洛庞帝或普莱斯的工作最初几乎没有真正的机器智能,那么现在的建筑软件可以利用这种可能性,并成倍增加其潜力。
尽管人工智能对建筑的潜在代表是先验的重要,但它仍然取决于设计者向机器传达其意图的能力。为了成为一个可靠的助手,机器必须经过训练,这意味着架构师面临两个主要挑战:在广阔的人工智能领域中选择合适的工具,以及选择相关的抽象级别和可测量的限定符,这些可以与机器交流。这两个先决条件的满足决定了一种与建筑兼容的人工智能形式的成败。
E .历史视频
为了说明和补充前一章,我们在这里提供几个视频,将赋予上述最重要的时刻以生命。
历史视频摘录
三。建筑中的人工智能
人工智能代表了新的技术浪潮,而不是颠覆。它通过协助建筑专业知识并增强其表达来补充我们的建筑实践。今天,学术和私人研究的结果显示了这一演变的第一个证据。所谓的“生成性”人工智能技术——也就是说,能够创建形状,而不仅仅是分析它们——是最*才出现的。在过去的三年里,他们开辟了新的实验领域。
生成对抗网络(GAN)代表了这些潜在的有前途的领域之一。这些模型能够学习复制呈现给它们的数据中发现的具有统计意义的现象。他们的结构是一个概念上的决定性创新。甘将“发生器”和“鉴别器”两个模型结合起来,进行了一个类似于学生和老师的类比。“生成器”(学生)试图生成图像。“鉴别者”(老师)给“生成者”每生成一个新图像给“生成者”一个“等级”。该分数将评估所创建的图像与在训练集中发现的图像的相似性。基于这个结果,“生成器”会适应以获得更好的结果。正是“生成器”和“鉴别器”之间的这种来回过程,在 GAN 模型的整个训练阶段磨练了所生成的图像。因此,这种模型将逐渐发展其创建相关合成图像的能力,同时考虑到它将在观测数据中适时检测到的现象。
如果 GANs 代表着一个巨大的机会,明智地训练他们是必要的。格式化图像数据库或“训练集”,可以控制模型将学习的信息类型。例如,简单地定义一个地块的形状和相关建筑物的轮廓将生成一个模型,该模型一般可以根据预先存在的地块的形状创建建筑物轮廓。然而,模仿也不能免于失误,如果没有指导,也不会漫无边际。因此,我们自己的“架构感”将仍然是保证训练集质量和结果质量的保证。换句话说,一个模型只有在被架构师适当训练的情况下才是相关的。
作为一个例子,下面展示的训练序列是在一天半的时间内完成的(见下文),展示了我们的一个 GAN 模型如何逐渐学会布置房间和分配必要的开口(窗户和门)。尽管最初的尝试不精确,但经过 250 次迭代后,机器建立起了某种形式的架构直觉。
训练序列 |来源:作者
四。应用程序
一个 人工智能终于开始进行图像创作,这是建筑设计实践中的一个基本媒介。事实上,图像在建筑中已经成为绘制和设计城市的主要手段。因此,这是人工智能和建筑之间的一座明显的桥梁:如果人工智能能够创建图像,并衡量它们的复杂性,那么将其应用于建筑生产就是一种自然的延伸。这里展示的是最*的研究成果,涉及四个不同的建筑尺度:*面、立面、结构和视角。
我们在下面展示了展品中展示的一些应用示例。为了对每个研究项目进行更多的解释和深入的描述,我们邀请您使用虚拟参观 来参观展览 。
不同建筑尺度的 AI 应用实例 | 左上:甘-洛克里,凯尔·斯坦菲尔德,右上:阿奇根,斯塔尼斯拉斯·夏鲁,右下:Pix2Pix,伊索拉& al。右下:DS 实验室,凯特琳·米勒&雷诺·丹海芙
动词 (verb 的缩写)未来和前景
对于建筑来说,人工智能最终既不是一种“自成一格”的现象,也不是不合时宜的破坏,更不是一种新的令人生畏的教条。几十年来,信号一直在宣布它,它只是七十五年发明和创新的顶点。在某种程度上,人工智能可以让我们协调效率和组织性,同时为设计师提供各种各样的选择,我们在这里看到了巨大的潜力。至少,人工智能将丰富我们的实践,并照亮我们学科的任何盲点。
这个展览希望站在这一演变的最前沿,并为创造一个关于人工智能和建筑之间关系的讨论*台做出贡献。我们敦促建筑师对人工智能感兴趣,并敦促科学界将建筑视为一个独立的研究领域。我们相信人工智能是一种资产,有利于建筑设计的统计方法。它的不确定性和整体性对我们的职业来说无疑是一个机会。人工智能可以让我们部分依赖机器来提取重要和相关的建筑质量,并在整个设计过程中再现它们,而不是使用机器来优化一组变量。
人工智能永远无法自动化建筑师的直觉和感受力。然而,建筑的真正风险与任何关于人机关系的反命题考虑都没有多大关系,而是,更通俗地说,与竞争和行业主权有关。事实上,要么该专业将能够围绕这些预示未来建筑实践的智能*台推动学科聚合,要么错过这个机会,将沦为一个辅助学科,为建筑或技术领域出现的更强大的工程实践服务。与此同时,让我们实际一点:架构师必须认识到,从智能助理中受益比许多人想象的要容易,并且在最早的阶段,应该认真研究和试验这一选择。
根据本次展览中提供的例子,以及行业和学术界正在开发的研究项目的数量,让我们承认,建筑中的人工智能正在进行中,并逐渐成为一个实际的研究领域。计划、立面、结构、视角:人工智能目前正处于试验阶段,旨在为我们建筑环境的所有设计规模带来解决方案。很明显,结果就在那里,人工智能的应用也非常明显。
我们并不认为人工智能是建筑的新教条,而是认为这一领域是一个充满潜力和希望的新挑战。
外部链接
机器学习算法之旅
阅读机器学习算法的介绍性列表
机器学习算法概述(来源
"机器智能是人类需要创造的最后一项发明."尼克·博斯特罗姆。
如果你可以回顾几年前人工智能的状态,并与它目前的状态进行比较,你会震惊地发现它是如何随着时间呈指数级增长的。
它已经扩展到各种领域,如 ML 、专家系统、 NLP 等等。
虽然人工智能背后的想法是建立更智能的系统,可以自己思考和执行,但它们仍然需要训练。
人工智能的 ML 领域正是为了这个目的而创建的,引入了几种算法,允许更*滑的数据处理和决策制定。
什么是机器学习算法?
ML 算法是任何模型背后的大脑,允许机器学习,让它们变得更聪明。
这些算法的工作方式是,为它们提供一批初始数据,随着时间的推移,随着算法精度的提高,更多的数据被引入到混合数据中。
这种将算法定期暴露给新数据和经验的过程提高了机器的整体效率。
ML 算法对于与分类、预测建模和数据分析相关的各种任务至关重要。
"机器学习的一项突破相当于十个微软."
- 比尔·盖茨
机器学习算法的类型
在这一节中,我们将集中讨论现有的各种类型的最大似然算法。ML 算法的三个主要范例是:
● 监督学习
顾名思义,监督算法通过定义一组输入数据和预期结果来工作。通过对训练数据迭代地执行函数,并让用户参与引入控制参数,模型得到改进。当发现其映射和预测是正确的时,该算法被认为是成功的。
监督学习(来源)
● 无监督学习
虽然监督算法对用户标记的数据进行输出预测,但这些训练机器明确地对未标记的数据进行训练,几乎没有用户参与。
算法留给数据进行分类和分组,以识别一些隐藏或未发现的模式,通常用作监督学习的初步步骤。
无监督学习(来源)
● 强化学习
强化学习算法旨在探索和利用之间找到一个完美的*衡,而不需要标记数据或用户干预。
这些算法通过选择一个动作并观察其结果来工作,在此基础上,它学习结果的最优程度。这个过程反复重复,直到算法进化并选择正确的策略。
顶级机器学习算法
在熟悉了几种类型的 ML 算法之后,请继续阅读一些流行的算法。
1。线性回归
线性回归是一种受监督的 ML 算法,有助于找到一组点的合适的*似线性拟合。
从本质上讲,线性回归是一种确定两个变量之间关系的线性方法,其中一个值是因变量,另一个值是独立的。
这背后的想法是理解一个变量的变化如何影响另一个变量,从而产生积极或消极的关系。
线性回归表示为 y = a+bx(ssource形式的直线
*这条线被称为回归线,用线性方程 Y= a X + b 表示。
在这个等式中:
- y-因变量
- a-斜率
- X —独立变量
- b —截距
该算法适用于预测输出连续且斜率恒定的情况,例如:
- 估计销售额
- 评估风险
- 天气数据分析
- 预测分析
- 客户调查结果分析
- 优化产品价格
有用链接:
2.逻辑回归****
逻辑回归算法常用于二元分类问题中,这些情况下的事件通常会产生两个值中的一个,通过或失败,真或假。
它最适合需要预测因变量属于两类响应之一的概率的情况。
这种算法的常见用例是识别给定的笔迹是否与有问题的人匹配,未来几个月石油价格会上涨吗。
逻辑回归算法(来源
一般来说,回归可用于现实应用中,例如:
- 资信评分
- 癌症检测
- 地理图像处理
- 手写识别
- 图像分割和分类
- 衡量营销活动的成功率
- 预测某种产品的收入
- 某一天会有地震吗?
有用链接:
3.决策树****
决策树算法属于监督 ML,用于解决回归和分类问题。目的是使用决策树从观察到处理每一层的结果。
处理决策树是一种自上而下的方法,从训练数据中选择最合适的属性作为根,并对每个分支重复该过程。决策树通常用于:
- 构建知识管理*台
- 选择要旅行的航班
- 预测酒店入住高峰期
- 建议顾客买什么车
- 预测和识别不同领域的可能性
决策树算法(来源)
有用链接:
- sk learn . ensemble . randomforestclassifier
- sk learn . ensemble . gradientboostingclassifier
- XGBoost 文档
- https://catboost.yandex/
- 理解随机森林:从理论到实践
- Python 中的实用 XGBoost
4.Apriori 机器学习算法
它是几个在线*台上流行的名为“你可能也会喜欢”的推荐系统背后的算法。
它通过在数据集中搜索公共项目集,然后在这些项目集上建立关联来运行。
它通常用于从关系数据库中进行项目集挖掘和关联规则学习。
该算法背后的思想是尽可能将相关项目扩展到更大的集合,以创建更有用的关联。
这种算法的应用包括突出市场中的购买趋势。
此外,它更容易实现,并可用于大型数据集。
5.朴素贝叶斯****
朴素贝叶斯分类器属于高效监督 ML 算法,是最简单的** 贝叶斯网络模型之一。**
它的工作原理是对数据应用贝叶斯定理,并假设每对要素之间的条件独立性,给定类变量的值。
朴素贝叶斯(来源)
更简单地说,假设事件 B 已经发生,它有助于找到事件 A 发生的概率。朴素贝叶斯最适合—
- 过滤垃圾邮件
- 推荐系统如网飞
- 对一篇关于技术、政治或体育的新闻文章进行分类
- 社交媒体上的情感分析
- 面部识别软件
6.人工神经网络****
模仿人类大脑的人工神经网络充当了一个巨大的神经元迷宫,或者简单地说,是相互移动信息的节点。
这些相互连接的节点通过边缘将数据即时传递给其他节点,以便快速处理,促进更顺畅的学习。
人工神经网络通过例子来学习,而不是用一套特定的规则来编程。能够模拟非线性过程,它们可以在以下领域实施——
- 模式识别
- 网络安全
- 数据挖掘技术
- 检测患者体内的各种癌症
人工神经网络(来源
7.K-均值聚类****
k 均值聚类是一种迭代无监督学习算法,将 n 个观察值划分为 k 个聚类,其中每个观察值属于最*的聚类均值。
K 均值算法的步骤(s 源
更简单地说,这种算法根据数据点的相似性来聚集数据点的集合。它的应用范围从聚类相似和相关的网络搜索结果,在编程语言和库如 Python 、 SciPy 、 Sci-Kit Learn 和数据挖掘中。
K 均值聚类的实际应用—
- 识别假新闻
- 垃圾邮件检测和过滤
- 将书籍或电影按流派分类
- 城市规划中的热门交通路线
有用链接:
8.支持向量机****
支持向量机被归类为监督机器学习算法,主要用于分类和回归分析。
该算法的工作原理是建立模型,将新的示例和数据分配到一个类别,这些类别很容易通过间隙相互区分。
在维数大于样本数的情况下,SVM 非常有效,并且非常节省内存。
高效支持向量机算法(来源)
SVM 应用程序可以在以下位置找到:
- 人脸检测
- 图像分类
- 文本和超文本分类
- 手写识别
- 用于治疗的药物发现
- 生物信息学——蛋白质、基因、生物学或癌症分类。
有用链接:
9.K-最*邻****
K-最*邻是一种监督 ML 算法,用于回归和分类问题。
该算法通常用于模式识别,首先使用距离函数存储和识别数据中所有输入之间的距离,选择最接*查询的 k 个指定输入并输出:
- 最常用的标签(用于分类)
- k 个最*邻的*均值(用于回归)
k-最*邻(来源)
该算法的实际应用包括—
- 指纹检测
- 信用评级
- 预测股票市场
- 分析洗钱
- 银行破产
- 货币汇率
10.降维算法
降维算法通过使用两种主要方法之一,即特征选择或特征提取,减少数据集中的维度空间或随机变量的数量。
这些通常用于预处理数据集,并删除冗余特征,使算法更容易训练模型。
这些算法也带来了一些好处,例如:
- 低存储要求
- 需要更少的计算能力
- 精确度提高
- 降低噪音
一些众所周知的降维算法是:
- 主成分分析
- 线性判别分析
- 局部线性嵌入
- 多维标度
11.主成分分析****
主成分分析是 ML 的一种无监督算法,主要用于通过使用特征消除或特征提取来降低特征空间的维度。
它还被用作探索性数据分析和构建预测模型的工具。需要标准化数据时,PCA 可以帮助:
- 图像处理
- 电影推荐系统
- 计算数据协方差矩阵
- 对协方差矩阵执行特征值分解
- 优化多个通信信道中的功率分配
主成分分析(来源
PCA 旨在减少数据集中的冗余,在不影响准确性的情况下简化数据。它通常部署在图像处理和风险管理领域。
有用链接:
12.随机森林
随机森林使用各种算法通过实现决策树来解决分类、回归和类似问题。
它的工作方式是,用随机的数据集创建一堆决策树,并在其上重复训练一个模型,以获得*乎精确的结果。
最后,来自这些决策树的所有结果被组合起来,以确定最适合的结果,该结果最常出现在输出中。
随机森林(来源)
随机森林应用可在— 中找到
- 银行账户、信用卡欺诈检测
- 检测和预测药物的药物敏感性
- 通过分析病人的医疗记录来确定他们的疾病
- 预测购买特定股票时的估计损失或利润
13.梯度增强& AdaBoost****
Boosting 是集成 ML 算法将弱学习者转换为强学习者的技术。当数据丰富时,需要 Boosting 算法,我们寻求减少监督学习中的偏差和方差。下面是两种流行的提升算法。
- 梯度增强
梯度推进算法用于分类和回归问题,通常以迭代方式建立预测模型,如决策树。它通过对强学习者的错误进行训练来改进弱学习者,从而产生总体上准确的学习者。
- AdaBoost
自适应增强的简称,AdaBoost 在弱学习者失败时改进模型。它通过修改附加到样本中实例的权重来更集中于困难的实例,然后,来自弱学习器的输出被组合以形成加权和,并被认为是最终的增强输出。
结论
ML 算法对于数据科学家来说至关重要,因为它们在现实世界中的应用越来越多。有了上面提到的各种算法,你就能找到一个最能解决你问题的算法。这些算法虽然是监督和非监督的混合,但可以处理各种任务,并能够与其他算法同步工作。
其他来源—
我希望这篇文章对你有用!如果您有兴趣了解更多信息,以下是附加资源:—
使用谷歌人工智能中心将想法变为现实
towardsdatascience.com](/top-google-ai-tools-for-everyone-60346ab7e08) [## 通俗易懂的机器学习算法,第 1 部分
(即如何向你奶奶解释机器学习算法)
towardsdatascience.com](/machine-learning-algorithms-in-laymans-terms-part-1-d0368d769a7b) [## 如果你在处理机器学习算法,你需要这些备忘单。
当我两年前开始学习机器学习(ML)时,我有许多关于使用哪些算法、如何使用的问题
medium.com](https://medium.com/free-code-camp/you-need-these-cheat-sheets-if-youre-tackling-machine-learning-algorithms-45da5743888e) [## 何时使用不同的机器学习算法:简单指南
如果你从事机器学习的时间够长,你就会知道有一个“没有免费午餐”的原则——没有…
medium.com](https://medium.com/free-code-camp/when-to-use-different-machine-learning-algorithms-a-simple-guide-ba615b19fb3b) [## 支持向量机——机器学习算法简介
从零开始的 SVM 模式
towardsdatascience.com](/support-vector-machine-introduction-to-machine-learning-algorithms-934a444fca47)
关于作者
克莱尔 D 。是Digitalogy—的内容制作者和营销人员,这是一个技术采购和定制匹配市场,根据全球各地的特定需求,将人们与预先筛选的&顶尖开发人员和设计师联系起来。在LinkedinTwitterinsta gram上连接 Digitalogy 。**
最流行的机器学习算法之旅
对机器学习的组成、学习风格和算法的全方位快速概述
阿道夫·费利克斯在 Unsplash 上拍摄的照片
M 机器学习可以说是目前计算机科学领域最热门、讨论最多的话题,但是你如何跟踪似乎从无到有的不同算法的无尽级联呢?
从个人经验来看,当算法的名字被抛来抛去的时候,你可能会觉得非常难以理解,你只需要知道它们是什么以及它们是如何工作的。如果你在同一条船上,你就来对地方了!
在本文中,我们将对最流行的机器学习算法进行一次高层次的浏览,以便了解该领域的真实范围。首先,我们将研究算法的学习风格,然后是算法本身及其功能。最后,你应该对机器学习涵盖的所有算法以及它们之间的相互关系有一个坚实的认识。让我们开始吧!
学习风格
在机器学习中,传统的做法是根据算法的学习风格对其进行分类。一般来说,学习风格只是一种花哨的方式,用来说明你有什么数据可以用来训练你的算法。我们来看一些!
1.监督学习
在监督学习中,输入数据被称为训练数据,并且具有已知标签/结果。输入的一个例子可以是动物的图片,标签可以是它的名字(例如,大象、猫等。).另一个例子可以是电子邮件作为输入,以及它们是否是垃圾邮件作为标签。
然后通过对输入数据进行迭代训练来学习一个模型,其中它不断地进行预测,并且当那些预测是错误的时候自我校正。这里有一个更简单的思考方式。
照片由 Jovana Askrabic 在 Unsplash 拍摄
每当我想到机器学习,我都喜欢想到婴儿。想象一下,教一个婴儿什么是猫,它偶尔会指着一只狗大叫“猫”任何理智的父母都会纠正孩子,并告诉婴儿这个动物实际上是一只狗;同样,经过的反复试验,婴儿最终会很好地了解其中的区别。
这正是监督学习的工作方式;电脑是婴儿。当它看到一张猫的照片,并说“狗”,你作为父母告诉它,这实际上是一只猫。经过上千次告诉电脑或孩子什么是猫或不是猫,机器/孩子最终将能够很好地预测标签。
这个训练/校正过程一直进行到模型在数据上达到期望的精度水*。
2.无监督学习
与监督学习不同,非监督学习没有标签——只有输入数据。
通过推断输入中存在的相似性和其他结构来学习模型。
帕特里克·福尔在 Unsplash 上拍摄的照片
作为对我们之前类比的赞美,想象一下在一个婴儿面前倾倒一吨不同的 M & Ms 巧克力豆。有可能孩子会根据颜色和形状有效地将巧克力块分类(假设里面有花生巧克力豆:),而不会被明确告知它们属于哪一类。
这是 ML 工程师在无监督学习中努力做的事情。我们希望将大量数据转储到计算机中,并根据各个数据点之间存在的相似性和差异性对其进行有效的分组。
3.半监督学习
顾名思义,半监督学习的输入数据混合了有标签和无标签的例子。
里克·梅森在 Unsplash 上拍摄的照片
在半监督学习中,我们希望机器能够做出预测 ,同时学习结构来组织手头的数据。
这种类型的学习不太常见,但仍然是一个非常酷的领域,在这个领域正在进行大量的研究。然而,当使用 ML 进行商业决策时,由于可靠性和准确性,您通常会看到团队和个人使用无监督和有监督的学习方法,而不是半监督的方法。
机器学习算法概述
现在我们对学习风格有了一个坚实的了解,让我们来看看最流行的算法本身。
当你通读它们的时候,我强烈建议你思考可以用这些方法解决的问题,以及问题所属的学习风格;这样做不仅会激励你,还会让算法坚持下去。
回归算法
回归算法关注的是输入和输出之间关系的建模;这是迭代通过使用预测中的误差度量来改进(回想一下猫宝宝的例子)。
Tatiana Rodriguez 在 Unsplash 上拍摄的照片
最流行的回归算法包括:
- 线性回归
- 逻辑回归
- 逐步回归
- 普通最小二乘回归(OLSR)
- 多元自适应回归样条(MARS)
- 局部估计散点图*滑(黄土)
基于实例的算法
基于实例的算法涉及将新实例与已经存储在内存中的实例进行比较。正如该过程所示,这种算法的另一个名字是基于记忆的学习。
图片来自推特: Unsplash 上的@jankolario
这些算法通常依赖于建立示例数据的数据库。然后比较提交给数据库内数据的新输入数据,并使用相似性度量,以便找到最佳匹配并做出预测。当编程和实现这些算法时,重点放在存储实例的表示以及用于确定关系的相似性度量上。
最流行的基于实例的算法包括:
- k-最*邻
- 支持向量机(SVM)
- 学习矢量量化(LVQ)
- 自组织映射(SOM)
- 局部加权学习
正则化算法
尽管正则化算法在本文中自成一类,但它们主要是与其他算法一起使用的。在高层次上,正则化基于模型的复杂性来惩罚模型;这反过来导致了更简单的模型,也证明了更好的一般化模型。
举个例子,想象一下被问到“你会怎么把一个数 x 翻倍?”。你可能会想到用 2 ( x * 2
)乘以数字x
,但是你也可以通过做((4x + 8)/4 — 2) * 2
来使数字翻倍。显然,第二种方法更复杂,也不是理想的方法;正则化不利于这种复杂性,并导致模型偏向简单性,例如将数字乘以 2。
最流行的正则化算法包括:
- 弹性网(L1)
- 岭回归(L2)
- 最小绝对收缩和选择算子(LASSO)
- 最小角度回归
决策树算法
决策树方法关注的是基于数据中的值构建“决策”模型。
“决策树”的“树”部分来自于这样一个事实,即决策在树结构中向下分叉,直到做出决策/预测。
我最喜欢的解释决策树的方法是将算法与 20 个问题进行比较。在 20 个问题中,猜测的人问一系列是或否的问题,最终落在另一个人的脑海中(应用程序 Akinator 是这一概念的另一个例子)。类似地,计算机询问关于输入的某些特征的“问题”,以遍历树并最终做出决定。
最流行的决策树算法包括:
- 迭代二分法 3 (ID3)
- 分类和回归树
- C4.5 和 C5.0
- 卡方自动交互检测(CHAID)
- 决策树桩
- M5
- 条件决策树
贝叶斯算法
贝叶斯算法关注于将贝叶斯定理明确应用于回归和分类等问题。如果你不熟悉贝叶斯定理,这里是:
简而言之,它计算给定事件 B 的情况下,事件 A 的概率。例如,“假设是阴天,下雨的概率有多大?”将表示为 P( 雨 | 阴)。同样,它将通过使用下雨时天气多云的概率(P(多云|下雨))乘以一般下雨的概率(P(下雨))并除以天气多云的概率(P(多云))来计算。
最流行的贝叶斯算法包括:
- 朴素贝叶斯
- 高斯朴素贝叶斯
- 多项式朴素贝叶斯
- *均单相依估计量(AODE)
- 贝叶斯信念网络(BNN)
- 贝叶斯网络
聚类算法
顾名思义,聚类算法关注的是将相似数据点聚类在一起。采取的所有方法(即分级、基于质心等。)使用数据中的固有结构以便最好地将点组织成具有最大相似度的组。
还记得我们很久以前提到的 M&Ms 类比吗?想象一下,把一袋彩色 M & Ms 巧克力豆倒在一个人面前,告诉他们“分组”。他们很可能会用颜色、形状等将巧克力块很好地组合在一起。
类似地,计算机查看输入的数据点之间的相似性,并根据最大相似性将它们分组。
最流行的聚类算法包括:
- k 均值
- k-中间值
- 期望最大化
- 分层聚类
降维算法
降维,顾名思义,就是对输入数据的特征进行降维的过程。例如,如果我们的每个数据条目有 100 列特征,我们可以将列减少到 20 列。
但是你可能会问,为什么不用所有的列呢?这是因为维度的诅咒 ( 哦,阴森森的 …对不起,这远没有听起来那么酷)。
没有太多的细节,维度的诅咒基本上说明了数据有太多的维度会导致过于复杂的模型,这些模型不能很好地概括;换句话说,该模型冒着过度拟合我们的训练数据的风险,并导致在真实世界数据上表现不佳。
最流行的降维算法包括:
- 主成分分析
- 主成分回归
- 偏最小二乘回归(PLSR)
- 线性判别分析(LDA)
- 混合判别分析
集成算法
集成算法涉及组合多个较弱的独立训练模型及其预测,以便产生最终的、更准确的预测。
亚历山大·安德鲁斯在 Unsplash 拍摄的照片
正如亚里士多德所说,“整体大于部分之和”。“谁想到哲学会适用于 ML,嗯?
一般来说,这是一类非常强大的算法和技术,在机器学习社区中经常使用。
最流行的集合方法包括:
- 助推
- 引导聚合(Bagging)
- adaboost 算法
- 随机森林
- 加权*均(混合)
- 堆叠概化(堆叠)
- 梯度增压机(GBM)
神经网络算法
神经网络是由我们的生物大脑和神经连接激发的模型(强调激发,而不是模仿……@ elon musk)。虽然它们超级浮华,看起来闪闪发光,但神经网络实际上已经存在几十年了!
一般来说,神经网络可以被归入模式匹配保护伞之下,其中它被用于回归和分类。正如我们将在接下来的章节中看到的,神经网络具有非常强大的现代计算能力,并且已经进入了他们自己的领域,称为深度学习。
然而,将这部分称为神经网络“算法”是不正确的,因为神经网络是一个非常大的子领域,由数百种不同的算法和满足特定方面和问题(即计算机视觉、语言处理、分类等)的变体组成。).
构成神经网络的基础和最流行的算法包括:
- 感知器
- 多层感知器(MLP)
- 反向传播
- 梯度下降(随机)
- Hopfield 网络
深度学习算法
深度学习是神经网络的现代转世,它利用了当前的“廉价”计算。****
总的来说,深度学习努力使用同样大的数据集的标签数据(图像、文本、视频、音频等)来创建大得多的和更健壮的神经网络。).
Robina Weermeijer 在 Unsplash 上拍摄的照片
深度学习最流行的基本算法和结构包括:
- 卷积神经网络(CNN)
- 递归神经网络
- 长短期记忆网络
- 堆叠式自动编码器
- 深度信仰网络(DBN)
其他 ML 算法
安妮·斯普拉特在 Unsplash 上拍摄的照片
尽管我们在这篇文章中所涉及的内容看起来相当广泛,但我很遗憾/很高兴地说,我们仅仅触及了的皮毛!例如,我没有涉及任何与 ML 子领域相关的算法,如自然语言处理、推荐系统、强化学习、图形模型等。这个列表还在继续,但希望这能激起你足够的好奇心,让你冒险去发现当今这个领域中正在实现的所有非常酷的算法。
为了对我们正在浏览的所有机器学习算法有所了解,看看这个维基百科页面。
但是不要烦恼!这个维基页面相当广泛,了解我在本文中提到的算法应该会给你足够多的强大基础,以开始你在机器学习方面的新职业:)。
结论
现在,为了总结我们在一起的时间,让我们看看我们都复习了些什么。我们从学习机器学习中的三种核心学习风格开始;你能记住他们吗?(如果没有,是时候重读了!)
然后,我们花了文章的大部分时间来研究不同类别的机器学习算法,并在每个类别中提到最流行的算法。
如果你有一个没有提到的算法,并且你想解释/把它放在列出的类别中,那么把它放在回复中让所有读者看到;毕竟,我们是在一起学习:)
在接下来的文章中,我们将更深入地研究这些特定的算法,以及我们如何从头开始制作它们;一定要拍一个跟拍,这样你就知道他们什么时候出来了!但是现在,我希望你喜欢这次旅行,并且学到一些新的东西。
编辑:解说系列第一部出来了!绝对零经验学习线性回归和梯度下降!
给数据科学爱好者的一个难题
试试你的手在一个多项选择的统计推理难题!
关于恶作剧问题,我最喜欢的是吹毛求疵(你的和我的)是公*的游戏。当一个问题警告你这是一个陷阱问题时,请仔细阅读。
最初发布在的推特上,现在再次让你尝试:
”博做了一个假设检验。没错。如果你对它的唯一了解是以下之一,哪一个给你的信息最多?”
A)显著性水*= 0.08
B)显著性水*= 0.05
C) p 值= 0.1753
D) p 值= 0.0032
现在,让我们来揭晓观众的答案:
你知道我第二喜欢的恶作剧问题是什么吗?当它运行良好时,最不受欢迎的答案就是正确的答案!是的,伙计们——答案是 a。正确答案是只获得 15%选票的答案。
获胜者是… A。
阅读推特上的评论让我很想岔开话题,谈论一下邓宁-克鲁格效应,但我会克制自己。我们来分析一下这个问题。
为了帮助你浏览讨论,我们可以推断的线索将用阿拉伯数字 1、2、3、4、… 和加粗,我们不知道的事情用罗马数字 I、ii、iii、… 加粗
这个问题告诉你什么
每个 A-D 只有在特定的决策框架下才有意义,所以:
1。博使用的框架来自 的统计 。
”博做了一个假设检验。正确。”
2。计算没有错误。
3。所使用的测试适合于数据和假设。
4。测试对决策是有效的。
每个人可能都会同意,如果计算出错,嘟嘟犯了一个错误,但哪个“正确”的化身经得起最极端的挑剔?超越良好的技术执行,进入决策有效性的领域。这是你的第一个盒子外的线索。这个假设检验不仅仅是数学上的正确。
博的假设检验在数学上是* 和* 决策——理论上是正确的。
这个问题没有告诉你什么
其中,用哪个代词来表示 Bo 。我在评论中看到了很多假设,所以当你向下滚动看到真正的 Bo 的照片时,你可能会感到惊讶。
更确切地说,这里有一些你无法从措辞中回答的问题:
Bo 是决策者还是统计学家,还是两者兼而有之?
ii)有多少名事实上的决策者?
为了使事情变得简单(对我来说也不那么罗嗦),我们将假设这个场景有一个决策者(Bo ),他碰巧也是统计学家。你要知道,这种假设在现实生活中经常会给你带来麻烦。专业数据科学中的许多工作上的痛苦来自围绕决策授权、决策者无能的问题,以及涉及多个利益相关者的复杂性。
不过,如果你想对它吹毛求疵,可以把下面的“ Bo ”替换成“决策者”,除非我们讨论的是计算。
这个决定是关于什么的?
尽管新手通常很难发现潜在的决策,但经典假设检验在哲学上植根于决策。(看我的文章《 千万不要从一个假设 》来更好的理解框架。)
在你说“我只是在做一些科学研究”或“我只是想知道 我的证据有多强”之前,花点时间找出真正的决策者(例如你向其提交科学研究的科学杂志的编辑),他们有明确的默认行动(例如不发表)和预定义的决策标准(例如 alpha 设置为当你只为自己做数据工作时,想想你为什么要做以及根据你所看到的会有什么变化。如果你有明确的答案,你也会看到决定。如果你真的不做决策,那么你想要的数据科学子领域是分析,而不是统计。分析可能使用假设检验方程,但实际上并不检验假设。(就像用手术刀不代表你在做手术。)
什么是零假设和决策标准?测试假设是什么?
绝对没有提供关于这些的信息,这自然意味着选项 C 和 D 都是垃圾。你可能会惊讶地发现一个关于 p 值的严酷事实:
如果你不知道假设检验设置的所有细节,p 值是没有用的。
提供的两个 p 值对你来说都一样没用。(不知道什么是 p 值的可以在这里学习基础。)
这两个 C & D 都是故意转移话题,意在给那些错误地把 p 值当成表面价值的人敲响警钟。
那些转移注意力的东西是故意给你的,是为了提醒你,普通大众并没有意识到 p 值本身并不能提供很多信息。让我们深入了解人们不正确的两件主要事情(!)相信他们从那些 p 值中得到。首先:
VI)Bo 使用了多少数据?
p 值告诉你样本大小是一个神话。有许多途径可以达到低 p 值,包括方便的或明显违反的假设。如果你对测试唯一了解的是它的 p 值,那么你对测试一无所知。
如果你对测试的唯一了解是它的 p 值,那么你对测试一无所知。
为了说明这一点,我故意以一种反常的方式生成选项 C 和 D 的 p 值。我仅使用两个数据点来生成 p 值= 0.0032 ,然后我再添加一个数据点来得到 p 值= 0.1753。就好像我预料到人们会犯这种非常常见的统计思维错误。耶,恶作剧问题!
不,低 p 值并不意味着大量数据。
其次:
从测试中我们可以得出什么统计结论?
伙计们,你们一直在评论的“我们”是谁?
评论中反复出现的一个主题是暗指一个虚构的“我们”在学习一些东西。好像我们都在一起做决策。退后,没人邀请“我们”——波在这里负责。
伙计们,这个“我们”是谁?这里由波负责!
统计假设检验是在不确定情况下做出合理决策的工具。你选择设置,输入一些数据,然后得到一个建议的动作。如果其他人喜欢使用不同的——但也是有效的——假设或设置,他们可能会得到不同的结果。两者都将是正确的。
“我们”在试图把自己的观点强加给那些不想要的人之前,应该三思。
唯一有可能学到东西的实体是决策者,然而许多评论似乎没有意识到这一点。那种认为“我们”都应该参与——并从——T2 的每一个决策中学习的想法很奇怪。这不切实际,效率低下,而且对自由造成了不必要的冲击。“我们”不会选择我下一次咖啡的口味。
选项 A 还是 B?
既然我们知道 Bo 的假设检验对决策有效,下面是一些必须为真的附加项:**
5。假设以正确的顺序建立,从默认动作开始。
(详见我的文章 千万不要从一个假设开始 。)
6。对 显著性水* 被设置在石头前的任何 数据 或 p 值 进行检查。
没有一个自尊的决策理论家会宽恕对确认偏差敞开大门的决策方法,所以从那个角度来看,测试也必须以正确的方式进行。
如果你允许自己在球落地后移动球门柱,那你就做错了。重要级别必须提前设置!
如果你允许自己在球落地后移动球门柱,那你就做错了。这意味着无论重要性级别是什么,Bo 在项目的早期就致力于它。
7。 显著性水* 的 0.05 是默认的示教值,所以在统计软件中经常是默认设置。
老师们通常喜欢掩盖令人分心的细节,以便专注于他们试图引入的新概念。默认值有助于减轻认知负担,因此要求学生假设显著性水*= 0.05,除非另有说明。有一天,我可能会写下为什么是 5%而不是其他数字的迷人而武断的历史(这个故事涉及一个留着大胡子的名人、一本雄心勃勃的教科书、版权法和农业)。
8。经典假设检验框架的美妙之处在于它让你控制决策质量和犯错误的风险。
大多数人没有意识到的是,统计假设检验是一个个性化的决策框架,给你三个拨号盘。你设置其中的任意两个,第三个会自动就位,然后你输入数据,得到一个建议的动作作为输出。这里有三个刻度盘:
- 显著性水*
- 最小功率曲线
- 最大样本量预算
所有这些都是*衡的。较低的显著性和较高的功效分别指对第一类和第二类错误的更好控制。(我已经在我的文章《 为匆匆忙忙的人统计 中为你定义了所有这些行话术语)。你可以要求一个程序使这两种错误都变得不太可能…但是要付出代价:更多的数据。所需的样本大小预算拨号可能会设置自己过高的数字。太贵了?提高你的重要性等级或降低你的能量需求。
如果你已经来到 p 值和置信区间的土地,你最好是在这里为控制质量和风险的某种方式。
你选择决策质量的能力几乎是经典统计推断的要点。你不选择贝叶斯方法(不使用 p 值、显著性或置信区间)的原因是你想要控制出错的风险。如果你不在乎这个,去贝叶斯。
现在让我告诉你当我看着大多数人用经典统计推断做什么时我看到了什么。
我看到一个强大的框架,有三个表盘。一个(样本量)通常是耸耸肩设定的,这意味着你最终会陷入两个糟糕的极端之一:为数据支付过多费用或浪费你的整个项目。一个通常被忽略(功效,一个(显著性水*)被设置为 0.05,因为这是人们从学校记住的。我无法面对手掌。说到没抓住重点!
我无法面对手掌。说到没抓住重点!
为了正确使用该框架,决策者每次都应该仔细考虑显著性水*。
他们应该如何设置?如果人们表现出足够的兴趣,我会单独写一篇文章。与此同时,重要的是你要明白,无论是谁负责做决策,都应该选择决策设置。
无论你选择什么…都要深思熟虑地选择。
当我负责时,我使用了高于 0.1753 和低于 0.0032 的显著性水*。我也用过 0.05 和 0.08…还有一大堆其他的。这总是取决于利害关系和决策的质量。
决策者认为合适的显著性水*是允许的。
当他们说 Bo“几乎肯定”会拒绝/不拒绝具有那些选项 D & C p 值的零假设时,评论在两个方面是错误的首先,你对决策或决策者打算做出的决策的质量一无所知,所以不要太确定。其次,“几乎肯定”是一个来自测量理论的技术术语,你几乎肯定错误地使用了这个术语,可能是因为你不知道你的统计教授在讲课时开了一个私人玩笑。更好的表达你的意思的方式是,决策者使用“常规”设置会得出某些结论,这让我想到…**
Bo 会在乎惯例吗?
这个很棘手。如果 Bo 有完全的权力做决定,那么没有;Bo 不应该对惯例不屑一顾,而应该使用 Bo 认为合适的任何决策工具。总有不止一种合理的方法来做决策。但是,既然不知道 Bo 是不是的决策者,这里就真的不能做假设了。当决策监管者代表社会行事时(就像政府批准新药的过程一样),传统规定了他们的大部分决策标准,他们确实必须遵循惯例,因为他们不能每次都要求社会直接参与。如果决策者完全参与决策,那么遵循惯例通常是懒惰的表现。(诚然,有时候懒惰是高效的。)
当你看到选项 B(显著性水*= 0.05)时,你不知道决策者是否深思熟虑地选择了它,他们是否因为所有的旅鼠都选择它,或者是否有人懒得调整软件设置。这比选项 A 提供的信息少,它至少告诉你测试的显著性水*几乎肯定是故意设置的。
标新立异还是不怀好意?
许多评论把他们自己引入了关于惯例的话题。遵循惯例只有在特定情况下才是明智的。
如果你在假设检验中做了什么坏事,你就没有正确地检验一个假设。
选项 A ( 显著性水*= 0.08 )会告诉你决策设置是非传统的,但假设非传统的选择在某种程度上是偷偷摸摸的,这是无知的。(事实上,那些认为这意味着 Bo 不怀好意(例如“alpha-hacking”)的人错过了“正确地”这个词的所有含义以及上面的线索#6 。如果你在假设检验中做了什么坏事,你就没有正确地检验一个假设。)
事实上,像 0.08 这样的非常规选择更有可能表明 Bo 是一位了解数据预算、功率和重要性之间权衡的专家。但是我们不能确定。
摘要
下面是问题中每个选项实际告诉我们的内容:
A)显著性水*是故意设置的。有人在选择它之前至少考虑了一下,因为它不同于默认设置。
B)显著性水*恰好与示教和软件默认设置相同。经过深思熟虑,它可能被设置为 5%,也可能没有。不多。不多。
这就是为什么赢家是选项 a。
见见激发这个谜题的老板(在右边)。她是统计学家、决策者、数据科学家,也是加拿大的大坏蛋。也是我大学最好的朋友。
为什么答案不是关于效果大小
对于那些思考“效果尺寸”的人来说,有一个小小的附言:
9。【检验一个假设】与不是一回事,“使用假设检验的数学为EDA”所以效果大小不应该进入讨论范围。****
采取行动的适当效应大小应该已经包含在 Bo 表述零假设的方式中。
仍然不明白为什么 C & D 是不正确的?
如果你知道关于决策者的决策设置和假设的一切(你不知道!),你可以推断出零假设世界不太可能产生至少像 Bo 观察到的那样极端的数据。
如果你知道显著性水*和 p 值(你不知道!),您可以推断决策者是否发现数据令人惊讶,足以改变他们的想法,并放弃他们的默认操作。
当你发现别人的 p 值“足够低”时,你真正学到的只是“决策者被某件事惊到了。”
如果您没有关于测试的假设和假设的信息,一个 p 值和另一个 p 值一样没有用。
不幸的是,你不知道什么是“足够低”,所以你甚至不知道博是否被惊讶地付诸行动。如果没有所有这些信息,一个 p 值和另一个 p 值一样没用。这两个 C & D 都是故意转移话题,意在给那些错误地把 p 值当成表面价值的人敲响警钟。(解释见我的文章 为什么 p 值像针一样? )
不要做一只旅鼠
统计假设检验最好的一点是,它给你一种方法来控制你的第一类和第二类错误概率,根据你的数据预算来*衡它们。(见我的文章 为赶时间的人统计 如果需要复习。)
如果你不仔细考虑你对犯这一框架中最糟糕的错误——I 型错误——的风险容忍度,那么你就错过了整个练习的关键部分。每次选择 5%的显著性水*都没有意义——这相当于扔掉了你能控制的最重要的刻度盘。
感谢阅读!喜欢作者?
如果你想说谢谢,我欣赏分享和转发。如果你渴望阅读更多我的作品,这篇文章中的大部分链接会带你去我的其他思考。不能选择?试试这个:
有一场关于 p 值的战争…而且双方都是错的!
towardsdatascience.com](/why-are-p-values-like-needles-its-dangerous-to-share-them-b94c11be537)
人工智能课程怎么样?
如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:
在这里欣赏整个课程播放列表:【bit.ly/machinefriend
与凯西·科兹尔科夫联系
让我们做朋友吧!你可以在推特、 YouTube 和 LinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用表格取得联系。**
一个棘手的问题
更好地理解画面以避免挫败感
micha Parzuchowski 在 Unsplash 上的照片
作为一名自由职业者,我已经用 Airtasker 设置了一些提醒,这样如果有任何新的与仪表板相关的演出发布,我就会收到通知。Airtasker 有点像“逐底竞赛”,人们(包括我自己)发布相对简单的任务,他们只想以最少的钱完成这些任务。
我以这种方式参加演出,他们带来了更大更好的东西,所以这并不全是坏事。如果没有别的,这是让你自己出去的好机会(尽管你必须小心那些要求你完成 20 美元作业的可疑大学生)。
Tableau 辅导是我做过多次的事情(私下和通过 AirTasker)。我想我也可以分享一些我遇到的常见问题。所以这可能会变成一篇博文系列 …
这篇博文是关于一个 Airtasker 的演出,它提出了一个我似乎已经多次(以某种形式)遇到的 Tableau 问题。这是一个直击要害的问题,为什么许多人觉得画面非常令人沮丧。
海报上有两张图片来说明她的问题。
我的回应
我最终没有被分配到这个工作(drats!),但这里是我想要传达的整洁版本。
为了让我们开始,我可以使用 R(参见这里的要点)快速生成虚拟数据,包含每月预算和每日实际金额,以模拟他们的数据。
请随意下载生成的 Excel 文件,点击这里(如果您愿意跟随)。
我们可以把这个放到桌子上,然后稍微布置一下。
在他们的照片中,他们有一些与上面不同的东西。他们并不仅仅使用金额,而是有几个计算字段显示几个特定时间段的金额:
- 当前月份
- 本年度
- 当前年度累计(财政)
- 当前年度(YTG)(财政)
这是我如何创造这些。
第一步是创建一个新的列,该列正好是一直向下重复的当前日期。
我认为计算字段是添加到数据源表中的新列——除非您正在处理 LOD 计算——在这种情况下,它更像是一个连接的聚合表——但 LOD 是一个完全不同的话题。
然后,我们创建一系列布尔(真/假)列,这些列将表明每一行中的日期是否满足我们的四个时间段条件中的任何一个。
使用 datetrunc()函数,当前月份和年份就足够简单了。
但是财政年度需要更多的策略。
不错!用一个表仔细检查这些布尔值也是一个好主意,如下所示:
似乎一切都好。
我们的下一步是利用这些布尔列来只包含金额列值,如果它们的条件满足。我们可以简单地做到这一点,通过添加一个 IF 公式到每一个。
然后将每个选项拖到 Measures 部分。
亲爱的。
我们现在可以把它们都拖到我们的 viz 上,我们得到了一些看起来非常接*海报图片的东西。
寻找解决方案
根据原图,她的要求有两部分:
1。添加一个差异列
2。从“未来一年(YTG)”部分删除“实际值”和“差异”。
这正是这种看似简单的事情,在 Tableau 中很难实现,这促使人们重新使用 Excel,在那里他们可以轻松地添加或隐藏列。
弄清楚“Tableau 方式”需要很好地理解 Tableau 是如何“思考”的
快速取胜的解决方案
(看起来)最简单的解决方案是向表中添加小计。
太棒了。
如您所见,新的 total 列只是 Actuals 和 Budget 列的相加。
为了得到方差,我们必须创建一个“代理”金额列,其中实际值为负。
然后,我们将执行“替换引用”,这样,我们新创建的所有特定于时间的公式都链接回代理,而不是原始的 Amount 列。
这没问题。格式栏还允许我们将标题标签从“总计”更改为“差异”。
但是我们对这个新的差异列的控制非常有限。
除了格式化它的颜色和排列,我们没有什么可以改变它。如果我们想把它显示成一个百分比,我们就不能这样做。
这种解决方案只会真正满足最随和的客户。
另一个诱人的方法是右键单击我们的每个测量药丸,然后选择“快速表格计算”和“差异”…
这将我们的列从两列(实际&预算)变为一列(差额)。在这种情况下,很容易在意识到它不会给我们带来工作解决方案之前,在这个领域浪费几个小时。
令人沮丧的画面
我们可能会认输,继续手动聚合我们的数据,在预处理步骤中(可能使用 SQL 创建视图,甚至是计划的 Tableau 准备流程),将方差值附加到我们聚合的原始数据中。
这是一个使用 Tableau Prep 的快速视频。
这种事情只应该是最后的手段。
创建一大堆单一用途的数据源是一个坏习惯。尤其是刚开始的时候。
有时这是不可避免的,它们的创建既快又简单。但是一直这样做可能会阻止你获得所有不同的提示和技巧,这些提示和技巧允许你想要的功能从原始数据源产生。
此外,这一过程的时间安排可能会成为你的一个障碍。如果我们正在处理一个数据库源,那么就有可能用这种正确的形式创建一个数据视图。但是,如果我们在没有一些中间位置(我们可以在那里建立这样一个视图)的情况下工作在一个直播服务上,那么我们将会在设置它的过程中做更多的跑腿工作。
诚然,如果报告只是每月更新一次,那么在常规流程中增加一个准备流程可能没什么大不了的。
真正的解决方案
有一种方法可以非常接*我们客户的要求,在原始数据集之外进行操作。
我们要做的是为我们四个时间段的每个创建三个新的(实际、预算和差异)度量。
不得不制定所有这些(12 项措施)听起来很令人头痛…但是我将向你展示一个漂亮的捷径。
首先,我们创建两个辅助列。
制作多个计算字段的诀窍是鲜为人知的拖放方法。
首先,创建新字段的名称作为注释。相应地修改每个公式。然后将每个部分(包括注释/标题)拖到 measures 窗格上。
哒哒!该注释成为度量的名称。很惊讶,对吧?
创建方差计算字段略有不同。请记住,从 Tableau 看到的内容来看,没有任何一行我们会看到预算和实际金额值。
这由 SAP 版本列决定。任何特定的行都是T21、“实际”或“预算”。因此,使用[当月实际]—[当月预算]作为公式将而不是为我们工作。
相反,公式需要是一个集合,依赖于观想的情境。我们需要使用 SUM([当月实际])—SUM([当月预算])。
为了整洁,我把所有这些新的计算结果放在一个文件夹里。让我们来看看它们。
哦不!在这一点上,我意识到“是实际的”栏不起作用!
SAP 版本有“实际的 S ”而不是“实际的”。幸运的是,我只需要更新“is Actual”列,而不是我们刚刚创建的每一个“… actual”计算字段。唷!尽可能减少重复代码是一个很好的教训。
好吧。回到正轨。
将所有这些计算过的场都加入到 viz 中,我们面临着一系列新的挑战。
对于每个新度量,我想将标题别名从“当前月实际值”更改为“实际值”,但我只能这样做一次,因为它不能有重复的别名。
作为回应,我不得不在随后的别名上添加尾随空格,例如“Acutals”。我还将这些标题格式化为左对齐,并且从不“换行”(这样它们看起来都一样)。
诚然,这是一个相当小的问题。
使用所有这 12 个新计算的度量,我们现在可以根据需要灵活地修改差异列(例如,我们可以将其更改为预算的百分比)。我们还可以删除“未来一年的实际和差异”部分。
然而,作为一个信息丰富的表格,这是非常乏味的,它缺少了客户请求的一个关键部分。
**
我们不能将“月(\(m)”、年初至今(\)m)”标题添加到显示“资本支出 OPEX”的上方(我们的源表中没有允许这样做的列)。我们目前的设置只是有一大堆数字,没有明确的时间框架之间的区别。
我们可以用这些新的方法制作任何数量的酷图表,但是假设我们的客户是一个真正的坚持者,要么让表格看起来像她想要的那样,要么明确地知道她想要的根本不可能。
在所有这些艰苦的工作之后,我们会承认失败吗?
选项 2
和我们的委托人谈谈。尝试说服她一个你知道如何做的替代解决方案。
也许他们不需要在一个表中显示每个时间段。我们可以创建一个参数,只显示选择的时间范围,一次一个。
然后使用参数选择器驱动显示的数量。
一个小标题公式,会给我们需要的标题。
选项 3
如果他们绝对必须把它们都放在一个页面上,有一个解决方案。
我们可以通过制作一个包含一系列表格的仪表板来实现这一点,这些表格只包含每个时间段的度量。
我们还将添加一个突出显示操作,这样在一个表中突出显示的行也会在其他 3 个表中突出显示。确保一切都正确排列。
如果实际数据有许多类别,我们还必须处理这些滚动条,因为它们不会以同步的方式滚动。有一个黑客,可用于这一点,解释得很好,在下面的视频。
这允许我们通过一个中心参数来限制每张表上显示的行数。但是你最终会得到一个水*滚动条,这有点烦人。可能有其他方法来改善滚动体验。
*[## Tableau 公共
编辑描述
public.tableau.com](https://public.tableau.com/profile/klaus.schulte#!/vizhome/SynchronizedScrollingacrosssheetsinTableau2019_2/SynchronizedScrollingacrosssheets)*
这个演示展示了参数的使用。但我认为也好不到哪里去。
上下合计
我们可能向客户展示的最后一个技巧是根据报告级别扩展和收缩表格。不幸的是,在我们的仪表板中,层次结构不能跨多个工作表工作。
最简单的解决方案(复制自这段 Youtube 视频)是添加一个报告级别参数。
然后用计算字段替换实际报告级别,该字段将根据参数设置显示级别(或为空)。
这使我们能够根据不同的报告级别向上或向下(跨所有工作表)汇总。
也可能有“集合行动”演习,以进行调查。启用“单击展开”功能。但对我来说,参数滑块似乎令人满意。
所以你有它。
看来我们终于找到了(理论上)能够满足客户最初要求的东西。您可以从 Tableau public 下载 Tableau 工作簿。
在这个过程中,我们也向她展示了 Tableau 的一系列方面,其中许多方面她可能从未见过。
现在有很多地方可以这样做,比如可视化,理解起来不需要太多的认知负荷。
原载于 2020 年 7 月 8 日 https://tadge-analytics.com.au*。***
真实的端到端 ML 示例:销售线索评分
实践教程
从机器学习的想法到用 MLflow、AWS Sagemaker、 Booklet.ai 实现的解决方案
介绍
卖东西可能是一项艰苦的工作。一个企业可能有许多潜在客户,但这些客户中的大多数最终不会变成实际的付费客户。销售团队必须整理一长串潜在客户的名单,并想出如何打发他们的时间。这就是领先得分的由来。这是一个系统,它分析每个新线索的属性与该线索实际成为客户的机会的关系,并使用该分析对所有潜在客户进行评分和排名。有了新的排名,销售团队就可以优先安排他们的时间,只将时间花在极有可能成为付费客户的销售线索上。
酷,听起来棒极了!我该怎么做?
嗯,很高兴你问了!在本帖中,我们将介绍一个定制的销售线索评分模型的完整端到端实现。这包括提取数据、构建模型、部署模型,最后将这些结果直接推送到最重要的地方——销售团队使用的工具。
如果你想测试出这个模型而不经历整个流程,我们在booklet . ai上有一个 全功能的线索评分模型 。我们已经将所有代码以 Jupyter 笔记本的形式发布在 GitHub 上。
先决条件
这将是一个技术教程,需要一点编码和数据科学的理解才能通过。为了从中获得最大收益,您至少应该接触一些:
- Python(我们将一直呆在 Jupyter 笔记本中)
- 机器学习(我们将使用随机森林模型)
- 命令行(是的,它可能很吓人,但我们只是使用一些简单的命令)
- AWS(我们可以牵着你的手度过这一关!)
此外,您应该安装一些东西,以确保您可以快速浏览教程:
通过 awscli 访问的 AWS 用户名(我们将在下面介绍!)
带有几个包的某种 Python 3:
- 熊猫
pip install pandas
- MLflow
pip install mlflow
- SKlearn
pip install scikit-learn
- Docker(非常快速和容易地安装这里
在我们开始之前…
我们将在很短的时间内接触到很多工具和想法。在我们开始之前,重要的是后退一步了解这里发生了什么。我们将使用一些工具:
- Jupyter 笔记本:数据科学家的必备品。允许您以笔记本的形式运行 python 脚本,并在线获得结果。
- MLflow :开源的模型管理系统。
- Sagemaker :来自 AWS 的全栈机器学习*台。
- Booklet.ai :模型测试与集成系统。
- 对讲机:客户服务和销售团队常用的管理客户关系的客户信息*台。
下图概述了这些不同工具的使用方法:
过程概述,作者的工作。利用来自名词项目的图像
在最高级别,我们将使用 Jupyter 笔记本来提取销售线索数据并训练模型。接下来,我们将把模型发送到 MLflow 来跟踪模型版本。然后,我们将把 docker 容器和模型发送到 AWS Sagemaker 来部署模型。最后,我们将使用小册子将模型投入使用,并开始将销售线索分数输入内部通信系统。
既然我们已经解决了这个问题,那就让我们开始吧!
训练模型
关于数据
首先,我们需要访问关于我们的线索的数据。该数据应包含两种类型的信息:
(一)响应变量:是否导致转化为付费客户
(B)特征:有助于我们了解响应变量的每个线索的详细信息
在本练习中,我们将使用来自 Kaggle 的示例销售线索数据集。该数据集为一家名为 X Education 的销售在线课程的公司提供了大量模拟销售线索。我们有各种各样的功能,为每一个线索,以及是否有线索转化为付费客户。感谢 Ashish 提供这个数据集以及对 Kaggle 的精彩分析。
导入和清理数据
要导入这些数据,只需将leads_cleaned
数据集读入 Pandas。如果您从数据库中读取这些数据,请用pd.read_sql_query
代替。
接下来,我们想挑选出几个对我们很重要的列。为此,我们将创建适合不同类别的列列表:数字、分类和响应变量。这将使加工和清洁处理更容易。
在这里,我们可以创建将用于培训的培训/测试数据集:
现在我们有了一个测试数据集,让我们继续为数值变量创建一个缩放器。重要的是只在训练数据集上运行,这样我们就不会“泄露”任何关于测试集的信息。
现在,我们需要对模型进行一些调整,为建模做准备。我们已经创建了一个函数来执行一些事情:
- 选择我们定义为重要的列
- 使用安装的缩放器来居中和缩放数字列
- 将分类变量转换为一次性编码变量
- 确保训练数据集中的所有列也在输出的、已处理的数据集中(这一点很重要,以便创建所有级别的哑变量,即使我们导入的数据集没有每个单独的级别。)
下面是我们将它们放在一起并通过预处理函数运行训练和测试数据集时的样子:
训练模型
这给我们带来了激动人心的部分!让我们使用我们新清理和分割的数据集来训练一个随机森林模型,该模型预测某人转变为 X Education 的付费客户的机会。首先,让我们定义几个标准超参数并初始化 SKLearn 模型:
从这里,我们可以快速计算测试集中的一些准确性指标,以查看模型的表现。
在我们坚持的测试集中,我们有 82%的准确率和 80%的 AUC 分数!不算太寒酸。肯定有改进的空间,但是为了本教程,让我们继续这个模型。
MLflow:管理模型
什么是 MLflow?
在我们开始设置之前,让我们快速地聊一下 MLflow。官方说法是,MLflow 是“机器学习生命周期的开源*台。”Databricks 开发了这个开源项目,以帮助机器学习构建者更轻松地管理和部署机器学习模型。让我们来分解一下:
管理模型:在构建 ML 模型时,您可能会经历多次迭代并测试各种模型类型。跟踪关于那些测试的元数据以及模型对象本身是很重要的。如果你在 100 次尝试中的第二次发现了一个很棒的模型,并想回去使用它,该怎么办?MLflow 已经覆盖了你!
部署模型:为了使模型可访问,您需要部署模型。这意味着将您的模型作为 API 端点来托管,这样就可以很容易地以标准的方式引用您的模型并对其进行评分。为您部署模型的工具有一长串。MLflow 实际上不是这些工具之一。相反,MLflow 允许将您的托管模型轻松部署到各种不同的工具。它可以在你的本地机器上,微软 Azure,或者 AWS Sagemaker。我们将在本教程中使用 Sagemaker。
设置 MLflow
MLflow 跟踪服务器是一个很好的 UI 和 API,它包含了重要的特性。在我们可以使用 MLflow 开始管理和部署模型之前,我们将需要设置它。
确保您安装了 MLflow 软件包(如果没有,请查看先决条件!).从那里,在您的终端中运行以下命令:
mlflow ui
在这之后,您应该会看到闪亮的新 UI 在 http://localhost:5000/ 上运行
如果您在进行此设置时遇到问题,请查看 MLflow 跟踪服务器文档此处。此外,如果你不想在自己的机器上安装跟踪服务器,Databricks 还提供了一个免费的托管版本。
一旦您运行了跟踪服务器,让我们将 Python 指向我们的跟踪服务器并设置一个实验。实验是 MLflow 跟踪服务器内部的模型集合。
用处理包装我们的模型
如果您正在处理一个没有与您的数据相关联的预处理的模型,那么记录模型是相当简单的。在我们的例子中,我们实际上需要在模型本身的旁边设置这个预处理逻辑。这将允许销售线索按原样发送到我们的模型,模型将处理数据准备。展示这一点的快速视频:
数据处理流程,作者工作。利用来自名词项目的图像
为此,我们将利用 MLflow 的pyfunc
模型类型(更多信息这里),它允许我们将模型和预处理逻辑打包到一个不错的 Python 类中。我们需要向这个类发送两个不同的输入:对象(即数字列列表或随机森林模型本身)和逻辑(即我们创建的预处理函数)。这两个实体都将在类中使用。
现在,让我们设置类。首先,检查代码,然后我们将讨论不同的部分:
该类基于 MLflow 的pyfunc
类领导 Model by。这将允许我们将这个模型推入 MLflow 并最终实现 Sagemaker。
接下来,我们在 init 中设置我们需要的所有对象。这包含了对象和逻辑功能。
最后,我们设置预测函数:
- 首先,我们接受 model_input(这是在部署后发送给被部署对象的数据帧),并确保所有的列名都是小写的。
- 接下来,我们将这个数据帧发送到我们之前创建并用于模型训练的预处理函数中。这一次,我们将响应列留空,因为我们不需要它们来进行部署!
- 然后,我们引用原始训练数据集的列名,并用 0 填充任何缺少的列。这一点很重要,因为当我们在部署后将数据集发送到模型时,我们将有一些热编码变量级别没有计算。
- 最后,我们将这个漂亮、干净的数据集发送到我们的随机森林模型进行预测。
既然我们已经准备好了所有的逻辑和对象放入一个类中,我们可以将这个模型登录到 MLflow 中了!
将模型记录到 MLflow
在我们打包所有东西并记录模型之前,我们需要设置 Anaconda 环境,当模型在 Sagemaker 上运行时将会用到这个环境。关于 Anaconda 的更多信息,这里有一个详细的概述。
现在,我们开始在 MLflow 中运行。在运行过程中,我们记录我们的超参数、准确性指标,最后是模型本身!
如果您转到我们之前检查过的 MLflow UI,您将看到新创建的模型以及我们刚刚定义的所有指标和参数。呜哇呜!
MLflow 中的日志模型
Sagemaker:部署模型
什么是 Sagemaker?
Sagemaker 是亚马逊网络服务(AWS)创建的一套工具,用于支持机器学习的开发和部署。Sagemaker 中有大量可用的工具(太多了,无法在此列出),我们将专门使用他们的模型部署工具。在他们的 GitHub repo 这里有一些伟大的 Sagemaker 例子。
设置 Sagemaker
首先,你需要得到许可。AWS 权限从来都不简单,但是我们会尽量保持简单!您需要设置两个不同的设置:您自己的用户和 Sagemaker 的角色。
第一个是用户帐户,这样您就可以在将模型发送到 Sagemaker 时访问 AWS。为此,您需要转到身份和访问管理(IAM)控制台,并设置一个具有管理员权限的用户帐户。如果您的安全团队进行反击,“Sagemaker 完全访问”应该也可以工作!在设置流程的最后,您将获得一个 AWS 访问密钥 ID 和一个 AWS 秘密访问密钥。一定要保存好这些!第一次之后就无法访问了。现在,到你的终端键入aws configure
。这将提示您输入刚刚收集的 AWS 密钥。完成设置后,您就可以从终端和 Python 访问 AWS 了!这里是来自 AWS 的更多细节。
第二个是 Sagemaker 的角色(本质上是 AWS 内服务的用户帐户)。要设置这一点,请访问 IAM 的角色部分。您需要将这个角色分配给 Sagemaker,然后选择名为“SagemakerFullAccess”的策略。在这个过程的最后,你会得到这个角色的 ARN 奖!部署时我们需要这个,所以把它放在手边。更多细节来自 AWS 这里。
最后,我们需要将一个 MLflow docker 容器推入 AWS。假设您正确设置了上面的权限并安装了 docker(参见 docker 设置的先决条件一节),您将希望在您的终端中运行以下命令:
mlflow sagemaker build-and-push-container
这将把一个 docker 容器推入 AWS,该容器将在部署期间使用。
部署到 Sagemaker
现在我们已经设置好了一切,是时候将我们的模型推送给 Sagemaker 了!
部署功能通常需要 5 到 10 分钟才能完成,并且在完成之前会经常使用此功能检查状态。一旦部署完成,您将能够在 Sagemaker UI 中找到一个正在运行的模型!
Sagemaker 中部署的模型
小册子:整合模型
恭喜,您的模型现在已经部署好了!我们的下一个目标是让这个模型对销售团队有所帮助。为此,我们希望使用部署的模型为新的销售线索创建线索得分,并将这些结果发送给销售团队使用的工具。我们现在需要创建一个系统,定期引入新的销售线索,将每个线索的信息发送到我们部署的模型,然后将这些模型结果发送到 Intercom,销售团队的工具。
有一些定制的方法来设置它:
- 我们可以设置一个定制的 Python 脚本,定期在我们的数据仓库中收集新的 Intercom 用户数据,使用 Sagemaker Python SDK 将数据发送到我们部署的端点,然后使用它们的 API 将结果发送回 Intercom。
- 我们可以利用 Sagemaker 的批量转换功能(很好的例子这里)来对一批内部通信用户进行评分。所有数据都在 S3 开始和结束批量转换,因此我们需要将数据拉入 S3 进行评分,然后将数据从 S3 推送到 Intercom,以提供给销售团队
我们知道必须有一种更有效的方式将模型结果推入最有用的工具中,所以我们构建了booklet . ai来简化这些步骤。
什么是小册子?
Booklet 为您的每个机器学习端点添加 web 测试界面和数据集成,无需更改代码。使用 Booklet,您可以快速尝试模型测试用例,以确保结果如预期那样执行,并将这些结果发送给最重要的工具。对于销售线索评分模型,我们可以将结果发送回我们的数据仓库(本例中为 Redshift)或销售团队的工具(Intercom)。
测试模型
使用 Booklet,我们快速设置了一个演示来测试销售线索评分模型。这连接到我们到目前为止在本教程中创建的端点。您可以尝试不同的输入,并查看模型如何对每个理论线索进行分类。要自己开发一个网络应用程序,你可以免费注册小册子,查看入门文档。
连接模型
一旦您对测试的模型输出感到满意,您就可以开始将这些结果发送到输出最有用的系统。我们已经在 Redshift 中设置了我们的源,它将数据导入模型。我们还设置了一个红移目的地和一个对讲机目的地,结果将被发送到那里。要开始一个示例数据流,它从数据源提取数据,用模型对数据进行评分,并将结果发送到两个目的地,您可以在这里尝试一个数据流。
让你的模型更有影响力
Tada!现在,我们通过将结果直接发送到 Intercom,使我们的销售线索评分模型更具影响力。为了让销售团队成员了解这一点,您可以看到每个示例线索现在都有一个自定义属性,列出了他们是否有可能转化:
对讲机*台内的销售线索评分示例
有了每个潜在销售线索的这些标签,销售团队成员可以开始优先安排他们的时间,并选择他们将首先联系的人。这将有望为您的企业带来更高的效率和更多的销售额!有许多方法可以衡量这些结果的成功,但我们将在另一个时间访问它!
结束语
如果你已经走了这么远,谢谢你!你已经成功导航了一个完整的端到端机器学习项目。从创意开始到商业影响,以及中间的所有步骤。如果你有任何想法,问题,或遇到问题,请在下面留言。
非常感谢 Ashish 提供的数据集, Bing 提供的有益评论,以及 Kyle 提供的牛逼博客供 MLflow 和 Sagemaker 参考。
一个 Kaggle 不会教你的教程:网页抓取,数据清理等等
因为数据科学不仅仅是 EDA 和培训模型
Kaggle 太棒了。你可以从一个伟大的社区中学到很多东西。你可以与世界上最优秀的数据科学家竞争和比较,这一切都是免费的。然而,Kaggle 并不完美。它不会告诉您在导入 CSV 文件和训练模型之前会发生什么。
本教程的目的是填补“真实”项目和 Kaggle 之间的空白。
定义问题
任何项目(无论是哪个领域)的第一步都是定义问题。你的问题是什么,你想回答什么?问题可能来自你的老板,但是能够创造值得回答的问题不会伤害你。Kaggle 一般会给你定义问题(特别是在比赛中)
对于本教程,假设的问题将是:是什么决定了加拿大魁北克省(我来自那里)每个地区的冠状病毒病例数。
网页抓取和数据清理
一旦有了想要回答的问题,就需要数据来回答。Kaggle 为您提供了完美的 CSV 文件,其中包含您的因变量和所有您需要做出伟大预测的预测器。显然,实际情况通常不是这样。
回到手头的问题,首先需要的是魁北克省每个地区的病例数,即因变量。当然,这不是我在电脑上某个地方存储在 CSV 文件中的数据,所以我不得不继续从这个网站上收集数据:https://www . Quebec . ca/en/health/health-issues/a-z/2019-coronavirus/situation-coronavirus-in-Quebec/。下面是我如何使用 Python 一步一步完成的。
导入库之后,首先要做的是使用请求库提取 URL 的内容:
**# Import libraries** from bs4 import BeautifulSoup
import requests
import pandas as pd
import re
from re import findall**#Get URL and extract content** url = requests.get('[https://www.quebec.ca/sante/problemes-de-sante/a-z/coronavirus-2019/situation-coronavirus-quebec/'](https://www.quebec.ca/sante/problemes-de-sante/a-z/coronavirus-2019/situation-coronavirus-quebec/'))c = url.content
一旦完成,我们就可以使用 BeautifulSoup 创建一个 soup 对象,beautiful soup 是用于从 HTML 文件中提取数据的终极 Python 库。这个美丽的物体是我们将继续工作的对象。
**# Create a soup object** soup = BeautifulSoup(c, 'html.parser')
现在,我们必须定义我们想要从我们指定的 URL 中得到什么。通过检查页面(右击,检查),我们可以看到网站的结构。在那里,通过 Ctrl+shift+C,您可以浏览页面,并轻松识别哪个代码块与网站的哪个部分相关。
在下面,我们看到“contenttable”表包含了我们想要收集的信息,即魁北克每个地区冠状病毒病例的数量。
使用 BeautifulSoup 中的 find 函数,我们可以找到表并导入数据。
my_table = soup.find('table', attrs = {'class': 'contenttable'})
之后,我们看到所有我们想要的信息都存储在一个标签中,它定义了 HTML 表中的一行。
通过使用 find_all 和 get_text 函数,我们可以从我们识别的表中的所有标签中提取所有文本。
data=[]
for link in my_table.find_all('tr'):
data.append(link.get_text())data
结果是一个包含所有数据的列表。我们离我们想要的已经很*了,但还不到那个程度。这里有一堆我们不需要的东西。列表中的一些元素是无用的,在每个元素中,都有一些我们不想要的字符/数字。这就是能够清理数据派上用场的地方,这是 Kaggle 不会教你的另一件事。首先,我将删除列表的前两个和后三个元素,因为这里不需要它们。
del data[0:2]
del data[18:21]
现在,如果我们仔细观察,我们会发现列表中的每个相关元素都有一个模式。它总是这样:“一个数字-地区+案例”。我们可以对 re 库使用正则表达式,以便只保留 region+cases 部分,去掉其余部分。下面是对列表中的所有元素执行此操作的循环。
real_data=[]
for i in range(0,18):
pattern = re.compile('[0-9][0-9] - (.*)')
result = pattern.findall(data[i])
real_data.append(result)
让我们仔细看看下面的代码:'[0–9][0–9]—(。)'.这意味着我们正在寻找一个包含 00 到 99 之间的任意数字的模式,一个“-”,最后是我们想要保留的部分(。).findall 函数将在每个元素中寻找这种模式,并返回我们想要保留的部分。
现在,我们想把这一地区从病例中分离出来。为此,我们只需要两个命令:一个只保存字符,另一个只保存数字。下面的代码就是这样做的,并用输出创建两个列表。
**#Creating the separate lists** regions=[]
cases=[]
for i in range(0,18):
strings = ''.join([i for i in real_data[i] if not i.isdigit()])
no_numbers = ''.join([i for i in strings if not i.isdigit()])
no_letters = ''.join(filter(lambda x: x.isdigit(), strings))
regions.append(no_numbers)
cases.append(no_letters)
然后,最后,我们可以创建一个以列表为列的数据框架。
**#Dataframe**
df=pd.DataFrame()
df['regions'] = regions
df['cases'] = casesdf.head()
数据帧的头部
我们有因变量,但我们现在需要预测。
预测器创建
在 Kaggle 上,你将总是被提供你必须用来提出你的预测的预测者。在现实生活中,不仅数据不会给你,而且你也不一定知道哪些预测是有用的。
回到我们的问题,我们需要弄清楚什么样的变量可以帮助预测每个地区的冠状病毒病例数。有些是显而易见的(人口,测试次数等。)但有时候,你需要跳出框框思考。也许城市中国际机场的存在有助于预测病例数?也许一个地区的教育水*也能说明一些问题?找到哪些预测因素会对你定义的问题产生影响是任何项目的一个重要部分,Kaggle 在这方面不会真正帮助你。
对于本教程,我保持简单,按地区刮人口。
**#Get URL and extract content**
url2 = requests.get('[https://www.stat.gouv.qc.ca/statistiques/population-demographie/structure/ra-totaux.htm'](https://www.stat.gouv.qc.ca/statistiques/population-demographie/structure/ra-totaux.htm'))c2 = url2.content**#Create soup object** soup2 = BeautifulSoup(c2, 'html.parser')**#From table, get only text** my_table2 = soup2.find(id='contenu_table')data2=[]
for link in my_table2.find_all('td'):
data2.append(link.get_text())**#Only keep elements we need in the list** population = data2[39:232:12]**#Add missing region** population.append(str(17141))**#Add population to the dataframe** df['population'] = population
当我定义 population 时,我使用了“data2[39:232:12]”,因为所需的信息出现在 data2 列表的第 12 个元素中,从第 39 个元素开始。另一个清理数据的酷招!另外,一个地区的人口,Terre-kress de la Baie-James,没有列在我搜集的网站上,所以我手动将其添加到人口列表中,正如你在上面看到的。
当然,在实践中,需要更多的预测器。对于本教程,我将到此为止。
Kaggle 很牛逼。你应该尽可能多的花时间在这上面。然而,它不会教会你成为最好的数据科学家所需要知道的一切。
非常感谢你的阅读!
人工神经模糊推理系统教程
图片来源:谷歌图片。一个简单的模糊逻辑模型表示!
如今,计算方法并不短缺。几乎每一个与数据相关的问题都有一个最适合在知识发现中获得最大收益的方法。在实践中,回归、聚类、神经网络、深度学习和贝叶斯方法都常用于创建可靠而精确的模型。然而,我观察到一种在工程社区之外被广泛忽视的模型类型,并且工作得很好,就是模糊逻辑。模糊逻辑最初是由洛特菲·扎德[1]提出的,它的工作原理是将预测值分配给模糊成员,而不是其他建模方法使用的固体二元结果。因此,模糊逻辑模型可以将该值归类为“中度温暖”,这可能适合更大范围的人群,而不是指定值“78”并自动将其归类为炎热。此外,构建伟大模型的一个重要方面,特征工程,在模糊逻辑中被处理到极致,因为用户必须建立论域(数据集内的值的范围,例如 0 到 200)和许多模糊规则,这些规则覆盖给定数据集中变量组合的所有可能情况。这允许对模型进行各种类型的调整,以提高性能,同时降低计算成本。简而言之,模糊逻辑使用数学预测能力和人类主观性的组合来创建可能的最佳模型。虽然由于人的交互性成分,这不会被认为是“机器学习”,但是模糊逻辑的扩展限制了人的主观性,并且向模糊逻辑模式添加了人工神经网络预测能力。这种方法被称为自适应神经模糊推理系统(ANFIS ),在工业领域的应用还不如在学术领域多。这篇文章将涉及 ANFIS 的一些能力,以及为什么许多从业者认为它优于神经网络。
ANFIS 开发于 20 世纪 90 年代[2,3],允许将模糊推理和神经网络应用于同一数据集。ANFIS 模型由五层或五个步骤组成,它们执行算法的模糊逻辑部分和神经网络部分的每个阶段。这里我使用 ANFIS 包中的 R 和美国的太阳能产值来制作我的例子。
第一步:计算隶属函数
隶属函数是某个值具有的“相似性”或“隶属度”的指标。这些通常用一系列数值的正弦曲线来表示(图 1)。因此,如果您要估计给定年份的能源消耗,您需要将这些值从最小到最大(可能有较低和较高的分位数以及*均值)分成五个不同的类别,偏差值会导致这些值之间存在一定程度的差异和相似性。
图片来源:作者。该图显示了每个值分段的模糊隶属度。
第二步:模糊规则的触发强度
在步骤 1 中被“模糊化”的值现在被传输到节点层,并乘以自动生成的模糊规则的强度(图 2) [3]。可以认为这是根据自动生成的规则和提供给该规则的数据计算“权重”。
照片来源:张,1991 年[2]。显示了 ANFIS 算法的第二步。
第三步:归一化射击强度计算
第三步获取第二步的输出,并将前一个节点的触发强度值与所有触发强度的总和进行比较(图 2)[2,3]。为了简化这种描述,考虑将单个节点的输出规则的强度与其他节点及其底层规则的强度进行比较的算法。如果某个节点的强度更大,那么它可能是数据集的“最佳”规则配置,并优先用于下一步。
引自张,1991 [2]。显示了 ANFIS 算法的第三步。
第四步:将前提(自变量)和结果(因变量)结合起来
第四步是将加权值与训练数据集中的原始输入相结合,根据结果数据计算输出(图 2)[2,3]。
引自张,1991 [2]。显示了 ANFIS 算法的第三步。
第五步:预测&最终输出
最后一步是监督所有输入信号总和的计算,并将它们应用于测试数据集,以产生预测值。这一步还包括数据的去模糊化过程和转换回有意义的值(图 3)。
图片来源:作者。显示了 2017 年各州太阳能发电总量的预测。
如您所见,生成的输出与原始数据非常相似。我们的模型的均方误差约为 12 %, R2 为 0 . 91,这非常好,尤其是因为我使用了如此有限的训练数据集。虽然 ANFIS 肯定不是倒数第二个建模技术,但它在从适度复杂的数据集预测值方面显示出相当大的准确性。该模型的一个限制是以必要的存储器形式的高计算成本。当我尝试运行一个有 8 个独立变量的模型时,我总是耗尽内存,直到我转移到另一台有 64GB 内存的计算机上。这是由每个变量的 5 层方法引起的,这扩展了需求。值的范围也会导致计算时间增加。尽管有这些缺点,仍然可以利用 ANFIS 的能力来改进预测,并与其他模型及其输出进行比较。
一些提示:
如果你试图将这个模型应用于你自己的数据集,确保你正确地计算了话语的范围。如果您的值没有涵盖数据集中存在的所有值,您将无法成功定型该模型。此外,如果您的 sigma(偏差)没有与其他模糊成员准确地收敛,您也将很难运行模型并获得准确的预测。如果您有一个大数据集(10GB 或更大),明智的做法是在 Apache Hadoop 中计算这些描述性统计数据,然后将它们应用到 ANFIS 中。
参考文献
[1]扎德,洛杉矶(1988 年)。模糊逻辑。计算机,21(4),83–93。
[2]张智成(1991)。 模糊建模采用广义神经网络和卡尔曼滤波算法 (PDF)。第九届全国人工智能会议论文集,美国加利福尼亚州阿纳海姆,7 月 14-19 日。 2 。第 762-767 页。
[3] Jang,J.-S.R. (1993 年)。“anf is:基于自适应网络的模糊推理系统”。IEEE 系统、人和控制论汇刊。23(3):665–685。doi:10.1109/21.256541。
Spotify 管道 Luigi 教程
Luigi 是一个 Python (2.7、3.6、3.7 测试版)包,可以帮助您构建批处理作业的复杂管道。它处理依赖关系解析、工作流管理、可视化、处理故障、命令行集成等等。
- 介绍
- 利弊
- 管道结构:
。任务
。目标
。因素 - 积木
- 执行它
介绍
我和 Luigi 的经历始于几年前,当时公司 pipeline 的唯一负责人离开了,我得到了一个巨大的遗留代码库。
当时,我对管道没有任何了解,尤其是 Luigi,所以我开始寻找教程并完整阅读官方文档。
没发现特别有用;当然,它在事实上是正确的,但它不是一个教程。当时,也没有很多关于它的课程或博客。
因此,这篇文章是我填补这一空白的尝试。我收集了我所学到的东西,希望能在你使用 Luigi 包的第一步中对你有所帮助
利弊
在深入研究代码之前,让我们看看这个包的优点和缺点。
Luigi pipeline 库已经被 Spotify 设计出来,现在还在使用。多年来,它已经被其他公司采用,特别是像 Deliveroo。但是,确切地说,因为它是为 Spotify 量身定制的,它可能不适合解决你的需求,我建议你仔细考虑这个系统是否能为你工作。
优点:
- 是 Python!因此,首先,您已经知道如何在其中编码,另外,您可以将您想要自动化的流程(您的原始代码)与管道基础设施(因此,Luigi)相结合
- 它的“向后”结构允许它从失败的任务中恢复,而无需重新运行整个流水线。
- 直接与 Amazon ECS 一起工作的 AWS 批处理包装器。
- 显示任务状态和管道图形表示的 GUI。
缺点:
- 很难测试。
- 它有一个中央调度程序,使得并行化任务变得困难。
- 需要保持简单,或者更好的线性(尽量保持< 1k 任务)。过多的分支和分叉会极大地降低运行时间。
- 没有触发器。因此,当所需的文件就位时,管道不会启动,但是您需要设置一个 cronjob 来检查它们并使管道启动
如果你已经决定开始使用 Luigi,运行
pip install luigi
让我们开始看看它是如何工作的
马丁·亚当斯在 Unsplash 上的照片
管道结构
Luigi 中的管道结构就像许多管道系统中的一个,类似于一个图形。它包含节点、节点和边节点,前者处理信息,后者连接节点,将信息传递到下一个节点。
该流程通常遵循线性流程,其中第一个节点被视为开始节点,这是第一个被执行的节点,接着是第二个,然后是第三个,直到结束节点完成工作流。类似这样的东西:
Start -> Node A -> Node B -> Node C -> End
相反,在 Luigi,这个过程是相反的!
程序从最后一个任务开始,它检查它是否可以被执行或者它是否需要任何东西。
如果是这种情况,它会向上移动到管道,直到找到满足所有要求的节点,只有在这时,它才开始运行已经访问过的节点。就像下面这样:
Start -> Node C -> Node B -> Node A -> Node B -> Node C -> End
这种方法初看起来似乎违反直觉,但它实际上有助于避免在出现故障或错误后重新运行已经执行的节点。
让我们设想第一次运行我们的管道,在第一次运行中,节点 B 失败了:
Start -> Node C-> Node B -> Node A (Done) -> Node B (Error) -X-> Node C -> End
在我们手动修复了节点 B 中的错误之后,管道可以再次运行,但是在这种情况下,它不会考虑节点 A
Start -> Node C-> Node B -> Node C-> Node.
完全避免运行它。
积木
如前所述,Luigi 包就像一个图形一样工作。Luigi 中的节点称为任务,边称为目标
任务()
任务是 Luigi 的基本组成部分,也是实际工作发生的地方。
要创建任务,您必须创建一个类并继承 luigi.Task 类。
在新类中,包含至少一个或所有以下方法:
- 需要()
- 运行()
- 输出()
- 目标
需要()
方法 requires()是执行的第一个方法(如果存在)。
它包含在当前任务之前已经执行的所有实例。最常见的情况是,该方法调用工作流上方的另一个 Luigi 任务,允许代码向后移动到管道的开头。
如果我们之前看到了目标是将任务连接到下一个任务所需要的,那么()是将任务连接到前一个任务的。
目标将代码移动到末尾,需要移动到开头。
只有当一个方法要求被满足时,任务才能执行第二个方法运行:
运行()
在这个方法中包含了任务必须执行的动作。它可以是任何东西,调用另一个方法,运行一个脚本,等等。
Luigi 中与前两个模型相关的任务示例如下:
class MakeTaskA(luigi.Task):
def requires(self):
return MakeTaskB() def run(self):
return luigi.LocalTarget(DoSomething())
输出()
顾名思义,方法 output()返回一个或多个目标对象。但是,建议任何任务在输出中只返回一个目标。
例子
Luigi 文档中有一个很好的例子:
在这个例子中,
- 第一个任务是 CountLetters(),它需要 GenerateWords()类,所以它移到那里
- GenerateWords()没有要求,所以它调用它的 run()方法并创建一个名为“words.txt”的文件
- 轮到输出了()。该方法查找文件 word.txt,并以 LocalTarget 类对象的形式将其返回给 CountLetters 类
- CountLetters()现在可以执行 run()。它从 self.input()中获取所需的内容
- 之后,它执行 output()
Task.input()是 Task.requires()的包装器,它返回相应的目标对象,而不是任务对象。
目标
目标是连接一个任务和下一个任务的边。
这些通常表示为一个文件。事实上,我们在前面的例子中已经看到了一个。文件“hello.txt”是一个目标。
当且仅当任务的每个输出目标都存在时,才可以认为任务已经完成。它们可以是简单的空文件,一个 S3 或任何东西。
因素
我们在示例中看到的最后一个重要元素是参数,但我们还没有考虑到。
参数在 Luigi 中,相当于为每个任务创建一个构造函数。这些是类的实例变量。对于每组参数,只创建一个实例。
就我个人而言,这让我想起了在 Java 或 C++中,你必须声明变量的时候,我知道它们不是一回事,但这有助于理解它的用法。
您可以用以下方式声明参数:
class MakeSomething(luigi.Task):
string = luigi.Parameter(default='hello world!')
现在,我们有了一个带有参数属性“hello world!”的类字符串。
您可以在任务之间来回传递参数。
参数类型
除了上面看到的,还有不同的参数子类:
有几个:DateParameter,DateIntervalParameter,IntParameter,FloatParameter 等。
这些提供了序列化和读取的方法,你可以自己做。但是,您没有义务指定参数的类型。
您可以简单地使用基类参数。使用 DateParameter 这样的子类的原因是 Luigi 需要为命令行交互执行转换。
这就是它如何知道如何将命令行上提供的字符串转换为相应的类型(即 datetime.date 而不是 string)。
从命令行
要执行代码,请从命令行键入以下内容:
python -m luigi — module file_name TaskName — local-schedule
我希望这篇文章能帮助你迈出与 Luigi 交往的第一步
使用 Spark 实现大数据的教程:预测客户流失的示例
Apache Spark 已经成为分析大型数据集最流行的工具。作为我的 Udacity 数据科学纳米学位的顶点项目,我将展示 Spark 在可扩展数据操作和机器学习中的使用。就上下文而言,我们使用虚构的音乐流媒体公司 Sparkify 的用户日志数据来预测哪些客户有流失的风险。
完整的数据集是 12GB。我们将首先分析一个迷你子集(128MB)并通过 python 接口 API py Spark 在本地模式下使用 Spark Dataframe、Spark SQL 和 Spark ML APIs 构建分类模型。然后,我们将在 AWS 上部署一个 Spark 集群,在全部 12GB 的数据上运行模型。此后,我们假设安装了 Spark 和 PySpark(安装 py Spark 的教程)。
建立一个火花会议
在我们能够将 csv、json 或 xml 数据读入 Spark 数据帧之前,需要建立一个 Spark 会话。Spark 会话是 Spark 2.0 中 Spark 应用程序的统一入口点。注意,在 Spark 2.0 之前,需要各种 Spark 上下文来与 Spark 的不同功能进行交互(关于这个的一篇很好的文章)。
# Set up a SparkSession
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("capstone").getOrCreate()
数据集
# Load data and show basic data shape
path = "mini_sparkify_event_data.json"
df = spark.read.json(path)
既然 mini Sparkify 用户日志数据集是 Spark dataframe 格式的,我们可以做一些初步的探索来熟悉这些数据。Spark dataframe 和 Spark SQL 模块具有如下方法:select()、filter()、where()、groupBy()、sort()、dropDuplicates()、count()、avg()、max()、min()。它们也有窗口功能,对基本分析很有用(见文档了解语法)。总结数据:
- 数据集有 286500 行和 18 列。
- 时间跨度为 2018 年 9 月 30 日至 2018 年 12 月 2 日。
- 它将用户在这段时间内做的每个事件记录为一行。
- 列定义如下:
-- artist (string): artist's name for a song
-- auth (string): Logged Out | Cancelled | Guest | Logged In
-- firstName (string): user's firstname
-- gender (string): Female | Male
-- itemInSession (long) : number of items in a session
-- lastName (string): user's lastname
-- length (double): a song's length in seconds
-- level (string): paid | free
-- location (string): city and state of the user
-- method (string): HTTP method
-- page (string): which page a user is on at an event
-- registration (long): timestamp of user registration
-- sessionId (long): the Id of the session a user is in at an event
-- song (string): song name
-- status(long): 307 | 404 | 200
-- ts (long): timestamp ateach event
-- userAgent (string) :
-- userId (string): user ID
5.其中一些列可能对预测不是很有用,例如 firstName、lastName、method 和 userAgent。分类特征需要编码,如性别和级别。一些数字特征对于工程聚合行为特征是有用的,例如 itemInSession、length、page visits 等。
6.阶层失衡;当我们分割训练测试数据时,我们需要考虑分层抽样。我们还应该考虑 f1 分数,而不是模型评估指标的准确性。
7.对于模型,我们将尝试逻辑回归、决策树、随机森林和梯度推进树。
有了这些初步的想法,让我们继续处理丢失的值。
处理缺失值
seaborn 热图是显示缺失值在数据集中的位置以及数据是否以某种系统方式缺失的好方法。
# Let's take a look at where the missing values are located.
plt.figure(figsize=(18,6))
sns.heatmap(df.toPandas().isnull(),cbar=False)
注意(1): 从热图中,我们可以看到在相同的行中缺少名字、姓氏、性别、位置、用户代理和注册。我们可以推断这些丢失的值来自未注册的用户。通常,未注册的用户没有用户 ID。我们将进一步探讨这一点。
df.select(‘userid’).filter(‘registration is null’).show(3)
原来,userId 列实际上有缺失值,但它们被编码为空,而不是编码为“NaN”。这种空值的数量与注册中丢失的行数相匹配。由于这些记录甚至没有 userId 信息,我们将继续删除它们。
注(2): 同样,艺术家、长度和歌曲也是同一行的缺失数据。这些记录没有与歌曲相关的信息。我们将探究用户在这些行的哪些页面上。
print(df_pd[df_pd.artist.isnull()][‘page’].value_counts())
print(df_pd[df_pd.artist.isnull()==False][‘page’].value_counts())Thumbs Up 12551
Home 10082
Add to Playlist 6526
Add Friend 4277
Roll Advert 3933
Logout 3226
Thumbs Down 2546
Downgrade 2055
Settings 1514
Help 1454
Upgrade 499
About 495
Save Settings 310
Error 252
Submit Upgrade 159
Submit Downgrade 63
Cancel 52
Cancellation Confirmation 52
Name: page, dtype: int64NextSong 228108
Name: page, dtype: int64
特征工程和 EDA
基于直觉和领域知识,我们决定暂时不在第一轮建模中包含 firstName、lastName、method 和 userAgent 列,因为这些变量可能不会影响我们的预测。我们还决定暂时不包括艺术家、地点、歌曲和状态。这留给我们以下几列:
-- gender (string): Female | Male
-- itemInSession (long) : number of items in a session
-- length (double): a song's length in seconds
-- level (string): paid | free
-- page (string): which page a user is on at an event
-- registration (long): timestamp of user registration
-- sessionId (long): the Id of the session a user is in at an event
-- ts (long): timestamp ateach event
-- userId (string): user ID
- 定义被搅动的用户:我们可以看到大约有 1:3 的阶级不*衡。
flag_cancellation = udf(lambda x : 1 if x=="Cancellation Confirmation" else 0, IntegerType())
df = df.withColumn("churn",flag_cancellation("page"))# Create the cross-sectional data that we’ll use in analysis and modelling
w1 = Window.partitionBy(‘userId’)df_user = df.select(‘userId’,’churn’,’gender’,’level’) \
.withColumn(‘churned_user’,Fsum(‘churn’).over(w1)) \
.dropDuplicates([‘userId’]).drop(‘churn’)df_user.groupby(‘churned_user’).count().show()+------------+-----+
|churned_user|count|
+------------+-----+
| 0| 173|
| 1| 52|
+------------+-----+
- 分类特征:对于分类特征,我们需要先进行标签编码(简单的把每个值转换成一个数字)。根据机器学习模型,我们可能需要进一步将这些数字编码为虚拟变量(例如,一次性编码)。
在 Spark 中,StringIndexer 执行标签编码部分:
indexer = StringIndexer(inputCol="gender",outputCol="genderIndex")
df_user = indexer.fit(df_user).transform(df_user)
indexer = StringIndexer(inputCol="level",outputCol="levelIndex")
df_user = indexer.fit(df_user).transform(df_user)
df_user.show(3)+------+------+-----+------------+-----------+----------+
|userId|gender|level|churned_user|genderIndex|levelIndex|
+------+------+-----+------------+-----------+----------+
|100010| F| free| 0| 1.0| 0.0|
|200002| M| free| 0| 0.0| 0.0|
| 125| M| free| 1| 0.0| 0.0|
+------+------+-----+------------+-----------+----------+
only showing top 3 rows
我们来看看性别和级别与流失有什么关系。通过查看简单的统计数据,似乎男性用户比女性用户更容易流失,付费用户比免费用户更容易流失。
df_user.groupby(‘genderIndex’).avg(‘churned_user’).show()+-----------+-------------------+
|genderIndex| avg(churned_user)|
+-----------+-------------------+
| 0.0| 0.2644628099173554|
| 1.0|0.19230769230769232|
+-----------+-------------------+df_user.groupby('churned_user').avg('levelIndex').show()+------------+-------------------+
|churned_user| avg(levelIndex)|
+------------+-------------------+
| 0|0.23121387283236994|
| 1|0.15384615384615385|
+------------+-------------------+
由于我们将利用逻辑回归和 SVM 分类器,我们需要将标签编码转换为虚拟变量。OneHotEncoderEstimator()完成这一部分:
encoder = OneHotEncoderEstimator(inputCols=[“genderIndex”, “levelIndex”], outputCols=[“genderVector”, “levelVector”])
model = encoder.fit(df_user)
df_user = model.transform(df_user)
df_user.select('genderVector','levelVector').show(3)+------+-------------+-------------+
|userId| genderVector| levelVector|
+------+-------------+-------------+
|100010| (1,[],[])|(1,[0],[1.0])|
|200002|(1,[0],[1.0])|(1,[0],[1.0])|
| 125|(1,[0],[1.0])|(1,[0],[1.0])|
+------+-------------+-------------+
only showing top 3 rows
OneHotEncoderEstimator()的输出列与 sklearn 的输出不同。它给出的是稀疏向量格式,而不是二进制值,如上面的代码片段所示。
- 一般活动聚集:基于 sessionId、歌曲、艺术家、长度和注册的列,我们生成聚集的特征,包括:
- numSessions (用户在此期间拥有的会话数)
- numSongs (用户收听的不同歌曲的数量)
- 数字艺术家(用户收听的不同艺术家的数量)
- 播放时间(播放歌曲的总时间,以秒为单位)
- 活动天数(用户注册后的天数)
- 页面访问聚集:基于页面列,我们生成聚集的页面访问行为特征,计算用户在该期间访问每种类型页面的次数。
w2 = Window.partitionBy('userId','page')
columns = [str(row.page) for row in df.select('page')\
.dropDuplicates().sort('page').collect()]
df_pageVisits = df.select('userId','page')\
.withColumn('pageVisits',count('userId').over(w2))\
.groupby('userId')\
.pivot('page',columns)\
.mean('pageVisits')
df_pageVisits = df_pageVisits.na.fill(0).drop(['Cancel','Cancellation Confirmation'],axis=1)
- 检查多重共线性:基于树的模型不会受到多重共线性的影响,但是,由于我们也测试线性模型(逻辑回归和 svm),我们将继续移除高度相关的特征。
所有功能的关联热图
移除高度相关要素后的相关性热图
- 向量组装和特征缩放:在 Spark 中,机器学习模型要求特征为向量类型。VectorAssembler()方法将所有功能列转换为一个向量,如下面的代码片段所示。
# Vector Assembler
cols = df_inuse.drop('userID','churned_user').columns
assembler=VectorAssembler(inputCols=cols,outputCol='feature_vector')
df_inuse=assembler.transform(df_inuse).select('userId','churned_user','feature_vector')df_inuse.take(1)[Row(userId='100010', churned_user=0, feature_vector=SparseVector(13, {0: 1.0, 2: 52.0, 6: 2.0, 7: 7.0, 8: 11.4259, 9: 1.0, 12: 1.0}))]
缩放后的数据如下所示:
df_inuse_scaled.take(1)[Row(userId='100010', label=0, feature_vector=SparseVector(13, {0: 1.0, 2: 52.0, 6: 2.0, 7: 7.0, 8: 11.4259, 9: 1.0, 12: 1.0}), features=SparseVector(13, {0: 0.3205, 2: 2.413, 6: 0.7817, 7: 0.4779, 8: 0.3488, 9: 2.0013, 12: 2.4356}))]
- 将数据分成训练集和测试集:
ratio = 0.8
train = df_inuse_scaled.sampleBy(‘churned_user’,fractions={0:ratio,1:ratio}, seed = 42)
test = df_inuse_scaled.subtract(train)
型号选择
我们将比较五种基线模型:逻辑回归、线性 SVM 分类器、决策树、随机森林和梯度推进树分类器。
# initiate the models
lr = LogisticRegression()
svc = LinearSVC()
dtc = DecisionTreeClassifier()
rfc = RandomForestClassifier()
gbt = GBTClassifier()
ParaGridBuilder()类可用于构建超参数网格进行搜索。然而,因为这里的目的是展示 Spark 的 ML 方法,所以我们不会在这里对模型进行深入调优。
# this line will keep the default hyper-parameters of a model
paramGrid = ParamGridBuilder().build()# to search over more parameters, we can use the ,,addGrid() method, for example:paramGrid = ParamGridBuilder()\
.addGrid(lr.regParam, [0.1, 0.01]) \
.addGrid(lr.fitIntercept, [False, True])\
.addGrid(lr.elasticNetParam, [0.0, 0.5, 1.0])\
.build()
我们将定义一个评估函数来运行所有五个分类模型,并输出它们的交叉验证*均指标(f1)。
def evaluate(model_name,train,test):
evaluator = MulticlassClassificationEvaluator(metricName=’f1')
paramGrid = ParamGridBuilder().build()
crossval = CrossValidator(estimator=model_name,\
evaluator=evaluator, \
estimatorParamMaps=paramGrid,\
numFolds=3)
cvModel = crossval.fit(train)
cvModel_metrics = cvModel.avgMetrics
transformed_data = cvModel.transform(test)
test_metrics = evaluator.evaluate(transformed_data)
return (cvModel_metrics, test_metrics)
最后,五个基线模型的性能如下面的代码片段所示。正如我们所见,所有车型的 f1 成绩都不令人满意。我们当然需要更好的调整来为这些模型搜索优化的超参数!
然而,如果我们要从这些基线模型中选择,交叉验证模型的 f1 分数应该是标准。在这种情况下,LinearSVC 模型将是首选模型。(注意测试分数比训练数据上的分数差,表示过拟合)。
model_names = [lr,svc,dtc,rfc,gbt]for model in model_names:
a = evaluate(model,train,test)
print(model,a)LogisticRegression ([0.6705811320138374], 0.6320191158900836)
LinearSVC ([0.6765153189823112], 0.6320191158900836)
DecisionTreeClassifier ([0.6382104034150818], 0.684376432033105)
RandomForestClassifier ([0.666026954511646], 0.6682863679086347)
GBTClassifier([0.6525712756381464], 0.6576482830385015)
在云上部署(AWS)
为了在 AWS 上运行完整的 12GB 数据的模型,我们将使用基本相同的代码,除了 Pandas 完成的绘图部分被删除。不过有一点值得注意:按照 Spark 课程在 Nanodegree 课外材料中关于配置集群的说明,我能够运行代码;但是,该会话会在一段时间后变为非活动状态。这可能是由于火花驱动程序内存不足。因此,我们需要使用高级选项来配置集群,并增加驱动程序内存。
步骤 1:在 EMR 控制台中,创建新的集群
步骤 2:转到高级选项
步骤 3:在框中,输入所需的配置
结论
这个项目提供了一个学习使用 Spark 和 AWS 操作大型数据集的绝佳机会,Spark 和 AWS 是数据科学领域需求最高的技能之一。
就主题而言,预测客户流失是数据科学家和分析师在任何面向客户的业务中面临的一个具有挑战性的常见问题。这里完成的分析和建模是为了突出一个使用 Spark 的机器学习项目的过程。模型性能当然还有很大的提升空间:
1)聚集的行为特征是简单的总和和*均值。加权*均值可以用来强调最*的行为。还可以包括分集测量。需要更精细的超参数调谐。
2)由于数据集是纵向的,我们可以潜在地使用生存模型或时间序列模型。这里有一些关于这些策略的文章,用于对客户流失建模。
阴阳魔界:真实和想象的*面在哪里融合?
摄动多项式的数值分析
问一个多项式的求根问题是否良态,这是数值分析中很自然的问题。也就是说,我们希望多项式系数的微小变化会导致其根值的微小变化。有趣的是,事实往往并非如此。
威尔金森多项式是数学家詹姆斯·威尔金森(James Wilkinson)在 1963 年使用的一种特殊的多项式,用来说明这样一种思想,即根的位置可能对多项式系数的扰动非常敏感,即使它具有分离良好的零点。他后来将这一发现对个人的影响描述为:
“就我自己而言,我认为这是我作为数值分析师职业生涯中最痛苦的经历。”
威尔金森多项式经常被用来说明计算矩阵特征值的常用技术的不可取性,该技术涉及导出矩阵特征多项式的系数,然后求解其根。应该注意的是,使用系数作为中间步骤可能引入极端的病态,即使原始问题是条件良好的。
扰动多项式
让我们观察一下,当我们随机扰动一个类似威尔金森的多项式的系数时,它的根会发生什么变化。我们考虑多项式
其度为 10,根为 1,2,3,4,5,6,7,8,9,10。扩张,我们得到
其中 C = { cᵢ },其中 i 的范围从 0 到 9,包括 0 和 9,是非前导项的系数集合。我们随机扰动 p ( x )的系数,用 cᵢ ⋅ (1 + aεᵢ 代替每个元素 cᵢ ∈ C ,其中每个 εᵢ 是均值为 0、方差为 1 的正态分布随机变量, a 是某个小的整体比例因子。如果我们插入每个 cᵢ ,我们得到扰动多项式是
下面, p ( x )以蓝色绘制,而 p ( x )的随机扰动版本以粉红色给出。我们观察到扰动后实根的数量减少了,根的位置也改变了,正如蓝点和粉色星星的位置不同所证明的那样。
根的值随着小的系数扰动而显著变化,实根的数量也是如此。
接下来,我们研究在多个小值的 a 上 p ( x )的根发生了什么,证实了根确实对应用于系数的扰动高度敏感。
根分布
我们试图弄清楚是否存在一个明显的点,在这个点上实根开始转变为复根。
真实的
对于每个 a 的单次运行,我们观察到 p ( x )的扰动版本的实根在各种 a 值上的分布。
多项式扰动形式的实根分布
出于可见性的目的,上面的点被随机水*避开,最左边的 a 值表示没有扰动。我们看到随着 a 的增加,一些实根改变位置甚至丢失,也就是变成了复根。这就引出了一个问题:
有没有一个 a 的特定值,在这个值上几乎可以确定会出现复根?我们如何描述到那时为止真实根的分布?
让我们称为值,在该值处,原本都是实数的 p ( x )的根开始以某种概率切换到严格复*面pᵣ临界点 a *。这个 pᵣ ,由下面几节描述的计算实验提供信息,设置得有些随意,但是成功地捕捉到了问题的一些相关特征。
复杂的
这里我们展示了 100 个不同扰动版本的 p ( x )的根的图,对应于 10 个不同的 a 值中的每一个。如前所述,对于更大的 a 值,我们看到越来越多的根进入复*面。
多重比例因子上的扰动多项式根
只有较大的 a 值似乎说明了虚方向上的扩展。这些观察激发了在 a 的多个值上与 p ( x )的根相比较的扰动实根分布的探索。
临界比例因子
我们放大两个特定的 a 值,一个低于临界点,一个大于临界点 a *。这些图描绘了八个不同的扰动多项式的根。
多重扰动下根分布的突变
达到临界点后,根的分布似乎会发生突然的变化。让我们尝试将这个关键的定义为。
定义
下图描绘了基于用于扰动 p ( x )的 a 的值的复根出现的概率。对于每个 a 值,我们扰动 p ( x ) 1000 次,其中成功表示一个或多个复杂根的存在。绘制的概率通过将成功总数除以 1000 来计算。
比例因子的临界值,即复数根出现的概率为 0.25 的点
概率 pᵣ = 0.25 由金色虚线表示。临界点 a *出现在粉色曲线和黄金线的交点。
趋势
下面,我们使用上一节中建立的 a 的定义,绘制了在多个多项式次数上达到的临界点。在 n 的程度上,我们指的是从(x–1)到(x–n*)的单项式的乘积。
不同次数多项式的临界点
我们发现多项式次数和 a *值之间存在有趣的指数递减关系。逻辑上, a *对于根多的多项式减少。在下一节中,为了试图理解在一个比临界点低一毫的 a 值处, p ( x )的实根的扩散会发生什么。
根的伸展
这里,我们为 a 的一个特定小值绘制了 p ( x )的八个不同扰动版本的根。
在扰动强到足以把一些根吹到复*面之前实根的状态
我们想要量化相对于原始根值的真实根的变化范围。下面,我们展示了在小于 a *的多个小 a 值上 p ( x )的 100 次扰动的实根分布。水*轴显示原始根值,而垂直轴显示扰动的根值。
多个比例因子在数百个多项式扰动上的实根扩散
我们观察到扰动根最大扩展出现在 p ( x )的第八个根处。这可以通过与最接* a *的 a 值相关联的橙色点如何在第八个根处沿垂直方向变化最大以及在其前后变化较小来看出。
结论
所展示的实验激发了对为什么这种扰动多项式的根的分布是这样的更深入的分析研究。
如果你想了解更多,请在本文的中找到额外的微扰实验。这里的代码是。在其中,我们导出了量化 p ( x )的根扩散的表达式,并且还使用判别式来寻找二次(x-1)(x-2)和三次(x-1)(x-2)(x-3)的临界点。
数据科学家的典型一天
来自德克萨斯州的数据科学家的一天。
目录
- 介绍
- 站立
- 吉拉—冲刺
- 代码审查
- 模型过程
- 摘要
- 参考
介绍
数据科学家的一天可能会有所不同,但日常工作有一个遵循一定顺序的总体流程。你可以期待有一个站立,用吉拉(或类似的任务管理*台)组织你的任务,和一个代码审查。还有其他更大的项目里程碑,但这包括更大的时间范围,在本文中,我们将重点关注典型数据科学家的日常工作。
我曾在几家较大的科技公司和一家初创公司工作过,包括 Indeed、home away(Vrbo-Expedia)和 ScaleFactor。虽然我不会具体说明哪家公司有哪种流程,但我会从我过去的职位中总结我的经验。
站立
大多数科技公司都有一个惯例,那就是“起立”。通常在早上进行,团队会聚在一起,大多数情况下,顾名思义,站起来讨论三个主要问题。站立的目的是确保同一个团队的每个人都在同一页上。这是突出单个成员的工作,同时强调流程的哪些部分被暂停,以便尽快就决议采取行动的有效方式。以下是站立时提出的主要问题。
- 你最*在做什么?
—作为一名数据科学家,我通常会提到我目前正在从事的项目,以及我前一天做了什么。一个例子是:“昨天,我在调整集合机器学习模型的参数”。
- 你今天在做什么?
—您将在与关键流程的会议以及与利益相关者、数据工程师、软件工程师、产品经理或主题专家的其他会议之后,讨论您正在从事的工作。此步骤的一个例子是:“我将输出结果,并概述预测变化之间的差异以及我调整的所有参数各自的准确性”。
- 有没有屏蔽器?
—首先,这一步可能看起来令人尴尬或不舒服,因为你在强调你不知道的东西,或者在其他情况下,因为你当前控制之外的外部过程而不起作用的东西。但是,当你与你的团队会面时,你会变得更容易敞开心扉,这最终会成为你一天中的一个关键部分,为高效和有效的变革创造一个环境。拦截器的一个例子是:“对于我正在调整的一个参数,我的 Jupyter 笔记本一直坏,我想不出测试这个重要参数的方法”。也许,有人会在几秒钟内知道这个问题的答案,你就不必浪费一整个星期的时间试图自己找出答案。
吉拉—冲刺
有几个像吉拉一样组织任务的*台,所以如果你在未来的公司不使用它,你可能会遇到类似的事情。它的工作方式是显示你的 sprint(通常一两周长),并根据任务在你的数据科学过程中所处的位置对其进行分组。
首先,您将创建票证。票据本质上是一个项目,它概括了一个问题、一个数据拉取、一个请求,并且有一个带有注释的描述。基于完成任务的难度或预计时间,您可以应用故事点,以便利益相关者或其他数据科学家知道您预计需要多少天来完成任务。门票也可以细分。任务单或故事单就是一个例子。一个故事是一个项目的更大的总结,比如“流失预测模型”。它将链接与该故事相关的任务单,以便您可以将项目组织成更小的块,其他工程师、科学家和经理可以被分配到这些任务单。任务单的一个例子是:“代码/。随机森林参数网格的 py 文件”。
还有其他类似的票证类型,但命名约定不同,称为问题类型:
**sub-task** - a smaller drill down of a task **bug** - an error in the code **epic** - the overarching theme of a data science team ("Churn") **improvement** - addition to an existing product (usually - engineers) **new feature** - a new part of a product (usually - engineers) **story** - logs the associated task tickets **task** - a main task assigned to a team member
在描述 sprint 的特性之前,你可以把你的票放在一个“backlog”里。这个区域存放下一个票据,或者在 sprint 中没有当前票据重要的票据。
吉拉及其 sprint 的一个例子如下:
- 规划/可用
—您将进行本次冲刺的入场券
- 在发展中
—您当前正在处理的票证
- 测试
—您为其编写代码并正在测试的票证
- 回顾
—票证已完成测试,但正在审核中,通常带有 GitHub 拉取请求
- 完成的
—一旦你最终完成了任务
一个完整而典型的大纲将包括这些步骤或类似的内容:
1\. Planning/Available2\. In Progress3\. Testing4\. Review5\. Done
虽然吉拉和 sprints 可能看起来势不可挡,但关键是这些工具和过程能让你的项目和团队更有效率。因此,这些带有许多定义的票证可以按照您想要的任何方式使用。这取决于您和您的团队使用这些标签和功能来改善您的数据科学流程。你可以在这里找到更多关于吉拉和短跑的信息。
代码审查
代码审查对于拥有一个成功的数据科学团队非常重要。一些公司或团队将只整合一个 GitHub pull 请求,而其他公司或团队仍将面对面(或电话会议),并共享他们的屏幕和代码。此外,一些团队可能每隔一天而不是每天执行一次代码审查。
代码审查有助于确保您的团队了解您的代码变更。在你花了大部分时间编写和组织代码之后,现在是时候与你的队友分享了。这是有益的,就好像你被困在一些代码片段上,其他数据科学家可以帮助你,你也可以帮助他们。
总而言之,代码审查有以下好处:
- 团队意见一致
- 代码正确
- 代码高效
- 合作创新
- 向他人解释代码有助于你更好地了解你的代码
模型过程
虽然建模过程需要几天、几周甚至几个月的时间来完成,但是这个过程的每个部分都有一个日常的方面。我将为一个数据科学家描述模型过程的主要步骤;提出问题,举例回答。数据科学家的典型建模过程如下所示:
业务问题陈述 —出现了什么问题,数据科学如何解决?有没有一些我们可以自动化的手动流程?
例子:客户在不断变化。
需求收集 —这个项目什么时候到期?谁会参与其中?涉众想要什么样的可交付成果?结果需要每天、每周或每月更新吗?
例如:我们希望客户流失的 CSV 输出,以及他们每周流失的概率。
数据位置 —数据在哪里?我们需要访问 API 来获取更多数据吗?这已经在本地数据库中了吗?
例:大量客户的数据在我们的本地 SQL 数据库中。
探索性数据分析 —分布是什么样的?是否存在缺失值?我们有足够的数据吗?我们需要更多的观察吗?
示例:当缺少值时,我们可以估算该字段的*均值。
特征工程 —哪些特征是重要的?哪些是多余的?我们需要查看相关性/多重共线性吗?
示例:使用 L1 特征选择移除冗余的、不重要的特征。
基础模型 —我们需要一个用 Python 制作的通用算法,还是需要一个实际的分类模型?最小可行产品是什么?
示例:导入没有参数调整的随机森林模型。
最终模型——我们需要多个模型吗?有些人比其他人做得更好?我们将使用哪些成功指标,为什么?
示例—我们可以对这些观察使用随机森林,对其他观察使用 xgboost,精确度是关键指标。
模型迭代 —我们需要调整参数吗?之前的结果看起来怎么样?我们能让模型火车更快更省钱吗?
示例—我们使用了一个参数网格,发现我们可以获得很高的准确度,同时将训练时间减少 20%。
结果输出 —输出是什么样子的?它应该只是一个 CSV 还是插入到 SQL 数据库中的数据?
示例—我们发现,我们可以在这个 SQL 数据库中用预测的客户流失标签和概率来更新我们的客户。
结果解释 —您将如何向利益相关者以及其他数据科学家解释您的模型及其结果?你会使用什么可视化工具或*台?
示例—我们可以使用 Tableau 在一个漂亮的彩色编码图表中显示我们的预测和概率得分。利益相关者可以访问这个仪表板。
摘要
Arnaud Mesureur 在Unsplash【4】上拍摄的照片。
有大量的数据科学家和公司。其中许多地方会有所不同,但它们的一些流程会有所重叠。我已经讨论了公司如何形成数据科学过程的类似方法。你可以期望有一个站立会议,使用吉拉或类似的*台来组织你的 sprint,并在代码评审中分享你的代码变更。数据科学家的日常工作可能会有所不同,但我们已经介绍了一天中最常见的步骤以及典型数据科学家的建模流程。
总体而言,数据科学可以涵盖工程和产品等业务的多个方面。数据科学家的职位可以有很多变化,但我希望我能阐明数据科学家每天将参与的主要流程和任务。
如果你想知道数据科学家通常会在哪里出错,以便你可以在未来避免同样的错误,请查看我的另一篇文章[5]。
可能出错的地方以及如何解决的例子
towardsdatascience.com](/10-mistakes-ive-made-as-a-data-scientist-f6118184e69)
我希望你觉得这篇文章有趣并且有用。感谢您的阅读!
参考
[2]阿特兰西斯,吉拉软件,(2020)
[3]李·坎贝尔在 Unsplash 上拍摄的照片,(2016)
[4]Arnaud Mesureur 在 Unsplash 上拍摄的照片,(2016)
[5] M.Przybyla,我作为数据科学家犯下的 10 个错误,(2020)
MITRE 的新冠肺炎决策支持仪表板的用户界面设计审计
我在米特新冠肺炎医疗保健联盟决策支持仪表板上执行了快速用户界面/UX 和数据可视化审计。请在这里观看,并查看我推荐的团队应该做出的设计更改。
随行视频: 【https://www.youtube.com/watch?v=TLtZmMrFDs0】
最*,我一直在做一些建议,以协助几个冠状病毒相关的黑客马拉松和新冠肺炎相关的数据科学和分析倡议。令人难以置信的是,看到这么多的人和私营公司走到一起,分享信息、知识、数据和见解,以解决这个疫情的各个方面。
我最*参与的一个团体是由 MITRE 领导的 Covid 19 医疗保健联盟,该联盟有一个团队正在从事一个名为“决策支持仪表板”的项目。该仪表板旨在帮助美国各州州长和地区政策制定者就“重新开放”做出基于数据的明智决策。在这个截屏视频中,我正在进行我的 UI 审计&补救计划服务的缩小版,以帮助团队从一个全新的角度看待他们的设计,以及他们可能想要改变什么,以使这个工具对目标受众来说更容易、更有用。我希望通过分享这些,他们也能对自己的工作多一些关注。
请注意,他们正在快速迭代,因此视频很可能与当前版本的过时。特别赞扬 MITRE 团队迅速公开地协助决策者抗击冠状病毒!
仪表板 UI 审核—补救计划:
下面的设计变更列表代表了我向 MITRE 的仪表板团队提出的关于变更内容的建议。我做的这些大部分几乎没有关于目标用户或用例的信息,而这在我的正式审计中是关键的第一步。判断一个设计是主观的,除非我们事先定义了一些“好的设计”的标准因此,我对这里的目标客户做了许多假设,目标客户是州级决策者(例如,美国州长或向州长提出建议的下属)。以下是我在视频中讨论的一些变化的总结:
- 地图:持续的缩放和缺少州级焦点让我感到沮丧(神奇鼠标:滑动手指缩放地图,而不是滚动页面=考虑取消鼠标驱动的缩放功能,因为它对设计来说并不重要)
- 地图:不点击地图就无法调出数据感觉怪怪的(如果我搜索我的州,我认为州长会关心这个州,为什么它不把我的州数据载入整个页面?)
- 过度关注比较:如果真正重要的比较是“我的地区与科学和医学上可接受的地区相比”,为什么如此关注地区之间的比较我不理解这个工具如此注重“与其他地区的比较”如果领导者真的专注于管理自己的区域。
- 地图:太大了— 对当地决策者来说,占用了太多的房地产。考虑将其缩小,以便更好地呈现下面的有用数据。
- 默认显示(不要折叠)KPI 部分(如再现率)
- 数据应该“表明立场” - >现在,还不是。看:如果像 1.1 这样的数字真的很糟糕,那么 UI 应该表明立场。别这么含蓄。视觉上帮我认识到“1.1 不好。”图标:不确定他们是否正在尽全力支持这项工作;他们感到胆怯和低调,但可能是视觉传达量化信息的强大盟友。
- 欢迎信息可以放在别处/更安静。
- 图表:感觉它们可以不那么高 (Y 轴=太高)
- 复制率没有 x 轴 —为什么没有?我觉得我想看这个。
- “我下一步做什么” —没有一个 KPI 建议我下一步可能采取什么行动,如果必要的话,接下来逻辑上应该检查什么更深入的数据,等等。
- 这个设计需要大量的用户交互来获取价值:我们能不能让我只需付出最少的努力就能获取我所在地区的信息?
- 考虑让位置搜索非常直观/响亮,立即设置背景。除了总统没有人[我们希望?]会在意国民的看法;这是一个虚荣心的衡量标准,但对地区决策没有多大用处。
- 搜索:奇拼(bug?):Massacusets,MA,USA =这出现在 type-head 搜索中(需要归一化数据?).此外,通过搜索,我可以深入到地图上没有可用数据的粒度级别。因此,如果我无法从这个仪表板中获得“邮政编码”级别的数据,我会建议将地图/搜索重定向到一个适当的高度,比如“县”这可以通过用户界面和交互设计选项微妙地传达出来,例如“米德尔塞克斯郡(包括 02140 邮政编码)”
- 定义:不确定是否需要默认拼出;也许他们可以进入工具提示。我会在图表上方更“水*”地显示它们,而不是在一列中。
- “空状态”图表区不清楚/模糊:有时 UI 中的“空”(空白)会令人困惑,我们需要有一个明确的“空状态”我认为那会有帮助。因此,举例来说,不要仅仅在“再现率”定义旁边显示白色/空/空,而是提供一个灰色/浅色的填充区域,其中包含 CTA(行动号召),例如位置搜索输入框。"输入县名以查看结果:[输入]. "这引起了交互,同时微妙地显示了 UI 区域的状态是“空的”
- 显示“14 日趋势”标签:我必须“调查”图形中有多少根棒线,这意味着什么,因为没有明确的标签/X 轴。
- 对每个 KPI 使用明确的语言: 当前:“案例增长率:0 天持续下降”可能会显示得更好?如下面:
“案件增速依旧【持*】【递增】。下一个里程碑:实现 7+天稳定下跌。” - …然后展示证据(图表)
觉得这有帮助吗?加入下面我的洞察邮件列表,了解设计以人为中心的数据产品的未来更新。
在此了解我的 UI 审计和补救计划咨询服务。
关于我
我叫 Brian T. O'Neill,是一名设计师、顾问和 Designing for Analytics 的创始人,Designing for Analytics 是一家独立的咨询公司,帮助公司将分析和 ML 转变为不可或缺的数据产品和决策支持应用程序。我还主持了播客“体验数据”,并为数据科学、产品和分析领导者发布了一份见解邮件列表,介绍他们如何使用以人为中心的设计来创建更有用、可用和吸引人的数据产品。此处免费订阅。
— —
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
短文本聚类的独特方法(算法理论)
短文本聚类中的高维数挑战和使用 GSDMM 对抗稀疏性。
高纤维(呃)?!当然了。
问题是
最*我一直在读安·兰德的《阿特拉斯耸耸肩》(我知道……回到高中英语文学时代,那时我本来应该读它,但没有读)。安·兰德有很多东西,但简短肯定不是其中之一。在不少于 1000 页的篇幅里,兰德精心构思了这部杰作中的场景和人物。好像我必须知道窗外树叶下面的颜色,因为里尔登喜欢啜饮轻微掺水的威士忌。我花了太多时间阅读文章片段、新闻摘要和听优雅概括的播客,以至于我忘记了如何真正融入作者的大脑。在过去的 1000 页中,我对安·兰德的写作风格了如指掌,我甚至可以复制它。这让我想到我的大脑如何为这位作者构建了一个非常优秀的自然语言处理器,因为我向它提供了大量的数据。但是我看文章,文字,推文等等。尽管理解不同,但考虑到随着时间的推移对材料的吸收,我仍然能够得出一些结论。我对短文材料的理解与安·兰德长篇大论的独白有何不同?我的大脑处理许多小片段和一篇长文章的方式有什么不同吗?
鉴于许多机器学习模型是建立在我们大脑如何处理信息的假设基础上的,我认为在我们处理新问题时考虑这些问题是有用的。短文本聚类传统上是一个难题,原因如下:
- TF-IDF 意义不大,因为与文章相比,句子中的字数较少。如果一个句子中所有的词频都是 1(因为这个句子很短,没有重复的词),那么我获得了什么价值?
- 对高维数据使用向量空间会导致稀疏。这导致高计算和内存存储。
- 问题 1 和 2 的结果是,确定用于分离文本的聚类的数量越来越具有挑战性,因此我们失去了将数据解释成主题的能力。
什么是 GSDMM?
GSD mm(Gibbs Sampling Dirichlet Multinomial Mixture)是几年前由尹建华和王建勇在一篇论文中提出的短文本聚类模型。该模型声称解决了短文本聚类的稀疏性问题,同时还显示了像 LDA 这样的词主题。GSDMM 本质上是一种改进的 LDA(潜在狄利克雷分配),它假设一个文档(例如 tweet 或 text)包含一个主题。这与 LDA 不同,LDA 假设一个文档可以有多个主题。正如我在前面的 TF-IDF 陷阱中提到的,由于稀疏性,在一个文档中权衡多个主题对于短文本文档来说不是一个好方法。
使用称为“电影组方法”的类比来描述 GSDMM 的基本原理。想象一下,一群学生(文档),他们都有一个喜欢的电影(词)的列表。学生们被随机分配到 K 桌。在一位教授的指导下,学生们必须在脑海中为两个目标洗牌:1)找一张有更多学生的桌子 2)选择一张你对电影感兴趣的桌子。冲洗并重复,直到达到集群数量不变的稳定水*。
在这里可以找到对 LDA 和 GSDMM 之间差异的直观描述,而在这里可以找到对 LDA 更深入的分析。在这篇文章中,我将重点讨论尹和王论文中描述的 GSDMM 模型的参数和推导。
狄利克雷多项式混合物
对于该模型的第一部分,理解什么是狄利克雷分布是很重要的。狄利克雷分布本质上是多维度(文档)上的贝塔分布。贝塔分布是简单的概率分布,其表示文档加入聚类的先验状态可能性以及该文档与该聚类的相似性。两个参数(下面描述的α和β)控制β分布的形状。
数字万用表的组件
转自尹和王的论文
让我们来看看构成该模型的关键参数:
如上所述,α是一个影响我们概率分布形状的参数。更重要的是,alpha 是从文档被分组到一个簇中的概率中得出的。在电影例子中,这是学生选择桌子的概率。
贝塔:贝塔是我们分布的另一个形状参数。Beta 来自一个文档中的单词与另一个文档中的单词的相似性。与电影组相关,beta 是学生加入有相似电影选择的桌子的概率。例如,如果 beta 为 0,学生将只连接有共同电影的表。这可能不是最佳策略。也许两个同学都喜欢惊悚电影,但是他们没有列出相同的电影。我们仍然希望学生们最终加入同一批惊悚片爱好者。
phi :使用 k 个聚类(混合),phi 是聚类在单词上的多项式分布,使得 p(w|z = k) = phi,其中 w =单词,z =聚类标签
theta: 同样,theta 是考虑了 alpha 的多项式分布,所以 p(d|z=k) = theta 其中 d = document。
这些参数的最终结果是文档(d)是由假设 Dirichlet 先验的聚类(k)生成的概率。
转自尹和王的论文
此外,重要的是要指出,论文假设对称狄利克雷先验。这意味着相同的阿尔法和贝塔在开始时被假定。Alpha 表示相同的群集同等重要,而 beta 表示相同的单词同等重要。Yin 和 Wang 指出,在该算法的未来迭代中,betas 不应该具有对称的先验,而是更流行的词应该具有较低的重要性。如果一个单词出现在每个文档中,它就不是一个非常有价值的信号(再次参见 TF-IDF 的缺陷)。
吉布斯采样
Gibbs 抽样描述了基于条件分布遍历和重新分配聚类的方法。与朴素贝叶斯分类器的工作方式相同,基于最高条件概率将文档分配到聚类中。
其他短文本算法
我关注 GSDMM 是因为我通过一个个人项目对它了解最多(见下一篇文章)。短文本聚类还有其他方法,但我注意到 DMM 是其中许多方法的基本原则(GPU-DMM 和 GPU-PDMM 添加单词嵌入),因此我相信理解这些参数和基本构建块将有助于开发更复杂的模型。
参考
原论文由尹和王此处
这篇文章很好地总结了 GSDMM 与 LDA 和应用的关系。
我没有深入研究吉布斯采样。LDA 和 Gibbs 的另一篇好文章是
收集数据的有用工具:网络搜集
安德烈·季霍诺夫斯基在 Unsplash 上拍摄的照片
使用这一工具的好处和道德
第一节:简介
计算机的发展产生了许多有用的技术,可以创建大规模的数据库。一种技术是 web 抓取,这是统计学家、数据科学家、计算机科学家和 web 开发人员最常用的一种技术,用于积累大量数据,这些数据用统计方法进行处理,以便进行分析。顾名思义,web scraping 是一种从万维网中提取特定数字、文本和表格等信息的方法,使用的软件可以方便地存储和管理已下载的所有信息。
不管我们使用什么样的浏览器,每个网页都使用计算机语言,比如 XML/HTML、AJAX 和 JSON 来呈现网页中的信息。当一个人在互联网上进入一个网页时,无论是社交媒体、维基百科还是像谷歌或必应这样的搜索引擎,使用浏览器都意味着使用 HTML (Munzert et al .,2014)。网页在任何浏览器上呈现的信息与 HTML 中呈现的信息不同;换句话说,HTML 是网页的代码,浏览器能够确保用户友好的体验。特别是,本文将尝试解释 HTML 成功实现 web 抓取工具所具有的一些特性,以及它们与 Python 的关系。
本文的主要目的是展示 web 抓取背后的有用性,以及统计学家如何利用这种方法。在第 4 节的结尾,Python 代码提供了一个解释,以深入了解这种技术的范围。
这篇文章将由以下不同部分组成。首先,第 2 部分将解释为什么网络搜集对统计人员有用。第 3 节将解释为什么在某些情况下,网络抓取很难使用,以及进行网络抓取的法律后果。在第 4 节中,将提供 Python 代码来解释使用金融 web 页面的 web 报废的简单实现。最后,在最后一节给出了结论。
第二节:网页抓取的重要性
统计学家经常发现获取数据很困难。收集数据的方式通常是通过观察、抽样调查、访谈或焦点小组。在许多情况下,从上述方法中收集信息需要时间和金钱。如今,互联网已经成为许多专业人士和科学家的重要信息来源。从这个意义上说,要解决很多学术角度或者行业内的问题,从互联网上提取信息是容易、快捷、廉价的。例如,政府通过各自的统计局免费提供公共商业周期数据;世界各地的中央银行提供经济和金融数据;国际能源署(IEA)提供石油和天然气等信息。
作为从网络浏览器复制和粘贴信息到电子表格的替代方法,计算机程序可以比人类更快更精确地完成这项工作(Broucke 和 Baesens,2018 年)。此外,如果一个人需要从许多网页下载数据,该算法会自动将收集到的所有信息整理到一个数据库中,以便随时进行分析。
或者,API 是由网页的创建者提供的一组功能,以便程序员能够使用这些功能从特定网页中提取信息。此外,API 允许运行它的程序正确地与网页通信。正如 Broucke 和 Baesens (2018 年)所建议的,“例如,Twitter、脸书、LinkedIn 和谷歌都提供这样的 API,以便搜索和发布推文,获得你的朋友和他们喜欢的人的列表,查看你与谁联系,等等”。
不幸的是,该网站可能会提供一个昂贵或用途有限的 API,等等;因此,使用网页抓取可能是实用的。事实是,只要数据在 web 浏览器中是可见的,scraper 就可以使用程序来访问和提取一些信息。如果是这样,这些信息可以以任何方式被清理、存储和使用(Broucke 和 Baesens,2018)。
正如前面提到的,HTML 有一些特性可以用来用 Python 实现 web 抓取机器人。此外,程序员可以在 Python 中安装 web 抓取工具,比如 Selenium。这个抓取工具的主要功能是使浏览器自动化,以便可以加载网站,恢复其内容,并像用户一样使用浏览器执行操作。Selenium 可以通过使用不同的编程语言来操作,包括 Python、PHP、C #和 Java (Broucke 和 Baesens,2018)。出于本文的目的,将使用 Python。
假设一名统计学家已经成功地下载并安装了 Python 中的 Selenium,并创建了一个简单的代码来从 web 中提取一些信息。那个人运行代码,发现它不起作用;没有 web 浏览器,Selenium 本身无法工作。特别是,它将需要使用一个网络驱动程序。该工具适用于大多数浏览器,如 Chrome、Firefox、Safari 和 Explorer (Broucke 和 Baesens,2018)。web 驱动程序可以从互联网上下载,并且必须与将要用于执行抓取的浏览器具有相同的版本。通过下载正确的 WebDriver,然后运行前面介绍的代码,Python 通过 Selenium,它会“说”和浏览器一样的语言。这将使得能够从网页中正确地提取信息。
迄今为止,我们知道我们需要一个特定的程序来做网络搜集,Python 我们还需要在 Python 中安装 Selenium,以及一个能够与 Python 成功通信的 WebDriver。
有很多方法可以从网页上抓取信息。Selenium 可以在 HTML 代码中通过 ID、名称、XPath、链接文本、部分链接文本、标记名、类名和 CSS 选择器从特定网页中提取特定信息(Broucke 和 Baesens,2018)。上面提到的一个有用的框架是 XML Path 或 XPath。XPath 是一种分层寻址机制,类似于计算机用来在许多文件夹中定位文件的机制(Munzert 等人,2014 年)。换句话说,XPath 是指向信息在网页的 HTML 代码上的确切位置的路径。值得一提的是,Munzert 等人(2014)指出,XPath“只是从 HTML、XML 等标记文档中选择信息的一个非常有用的工具”。
第三节:使用网页抓取时的常见问题
本节将展示在进行网络抓取时可能出现的真实例子和复杂情况;刮网时问题是不可避免的,也是常见的。对于网络抓取来说,能够检测、抛出和管理这些错误是至关重要的(Mitchell,2013)。正如 Mitchell(同上)所言,“网络是杂乱的,你永远无法确定是否有某个元素,或者某个页面是否返回了你想要的数据,或者某个网站的服务器是否已经启动并在运行”。许多数据分析师在进行网络搜集时会遇到意想不到的问题。有趣的是,我曾经在一家投资银行工作,其中许多分析数据来自互联网,我们通过对金融网页进行网络抓取来提取这些数据。我们开发了这些工具来提取股票、债券和指数的金融时间序列,而不是将彭博或路透社作为主要的信息来源。
团队遇到的最常见的问题是网页模板的突然更新。换句话说,为提取特定网页的信息而开发的网络抓取工具将不能与网页的新结构一起工作。一个需要花费大量时间开发的代码可能在几秒钟内就变得无关紧要了。解决这个问题的一个方法是确保代码的结构足够灵活,以便能够更快地适应新的网页。
当试图下载信息时,一些网站可能不同意网页抓取器。例如,如果在同一个网站发送数百个 HTTP 请求,尽管许多网页相对健壮,但一些网页可能会停止工作,无法参加常规的用户流(Broucke 和 Baesens,2018)。网页之所以有效,是因为公司拥有可以处理大量用户的服务器。如果许多用户同时进入一个网页,这个网页很可能会崩溃。
同样的问题也发生在 Bidder's Edge 上,这是一家致力于从拍卖网站收集数据并提供给网站的公司。用户可以在他们的网站上搜索列表,而不是在每个拍卖地点张贴许多申请。该公司被易贝起诉,并针对其网站上使用的机器人进行了有效辩护(H. Liu and Davis,2015)。
此外,一个新的问题出现了:网络抓取的合法性。在分析了一些涉及网络抓取的真实案例后,Munzert 等人(2014)确认“从这些令人不安的故事中吸取的教训是,不清楚哪些行为可以归入‘网络抓取’标签下,哪些行为实际上是非法的”。H. Liu 和 Davis (2015)指出“法律是模糊的。在很大程度上,公司已经成功地阻止了不必要的刮削——至少是部分地。但称这是一个既定法律领域还为时过早”。此外,Mitchell,R. (2013)也持类似观点,认为“网络抓取的法律先例很少”。
为了避免法律上的问题,遵循网站上的使用条款和版权文件(同上)是被普遍接受的。Broucke 和 Baesens (2018 年)还讨论了网络抓取的合法性,写道“显而易见的是,围绕网络抓取的法律格局仍在演变,许多被引用为违反的法律在我们的数字时代尚未成熟”。最后 13 洗。J.L .技术公司。& Arts 275 (2018)指出“技术往往领先于法律和政策。网络爬虫目前几乎完全受社会规范和礼貌的支配,国会、行政部门和法院都没有颁布法律”。很明显,使用网页抓取工具时存在灰色地带;大公司并没有打赢所有的官司。
为了避免网页出现问题,最*提出了一个想法,那就是 robots.txt 文件。这一概念是为了表明机器人可以或不可以访问存储在网站根目录中的文本文件中的数据(Munzert 等人,2014 年)。换句话说,这个文本文件“告诉”网页抓取工具哪些信息可以从网页下载,哪些不可以。然而,并没有表明 robots.txt 文件本身具有法律约束力,尽管服务条款通常具有法律约束力(Mitchell,r .,2013)。
最后,美国列出的最常见的法律问题有:违反条款;版权或商标侵权;《计算机欺诈和滥用法》(Fraud 侵犯动产;机器人排除协议;以及《数字千年版权法案》(DMCA)、《CAN-SPAM 法案》(Broucke and Baesens,2018)。
第四部分:网页抓取的示例
本节将帮助理解如何从金融网页实现 Python web 抓取代码。这个想法是给出一个概要,指定代码中最重要的部分;完整的代码可以在我的 GitHub 库中找到。如果你愿意,请随时检查和使用它。该机器人从不同的交易所交易基金(etf)中提取特定特征,并将其排列到数据库中(etf.com,2020)。ETF 是一组证券,如股票、商品、债券或投资类型的混合,其目的是复制或跟踪基础指数。每只 ETF 都有一个价格,投资者可以轻松地买卖它们(Investopedia,2020)。
首先,我们需要导入将在整个代码中使用的库。如前所述,我们将使用 Selenium、Chrome 作为浏览器,以及 Chrome WebDriver(因为 WebDriver 版本需要与浏览器版本相同)。从代码行 1 到 5,显示了将要使用什么库以及使用了特定库的什么功能。
为了更好地理解,库 openpyxl 帮助读写 Excel 文档,numpy 提供有用的数学函数,pandas 是一个帮助操作数据结构的包(PyPI,2020)。从这个意义上说,第 7 行将创建一个工作簿,存储从 web 下载的所有数据。
第 16、20、21 和 105 行是需要修改的特定目录,以便代码可以在另一台计算机上运行。具体来说,第 21 行包含工作簿,其中包含将要被剔除的 ETF 的输入。此外,第 20 行显示了 WebDriver 的位置,它将用于进行 web 抓取。
第 29 行显示了包含路径和如何显示浏览器的首选项的变量。第 34 行描述了将要从网页中提取的特性。因此,第 43 行显示了如何使用第 29 行创建的变量打开浏览器的命令。
XPath 语法出现在第 45、50、52、58、72、77、82 和 95 行。通过观察代码,在 XPath 代码之间,我们可以找到 try:和 except:参数。当代码在 HTML 代码中找不到 XPath 时,这很有帮助。否则,我们会在执行代码时看到一个错误。
一方面,第 38 行中的 for 循环将迭代从第 21 行的工作簿中提取的每个 ETF。另一方面,第 67 行和第 92 行将有助于迭代一些特定 ETF 的一些特征。最后,第 103 行累积了下载的所有信息;第 104 行将该信息保存在特定目录下的. csv 文件中,第 107 行关闭 WebDriver。下面的视频展示了这段代码的作用。
第五部分:结论
网络抓取是从网页中提取数据的强大工具。根据研究人员试图进行的分析类型,网络搜集可能会取代既费钱又难以实施的调查。如果对代码进行适当的编程,与人类相比,计算机可以提取和排列更多的信息。
尽管 web 抓取有许多方式,但本文解释了如何使用 Python 实现 web 抓取工具。此外,还展示了如何在 Python 代码上使用 Selenium,以及它与 HTML 的关系。最后,展示了使用 XPath 从 HTML 代码中提取特定信息的方法。
做网页抓取时出现困难;问题是不可避免的,但通常是可以解决的。这篇文章通过许多不同作者的研究证明,围绕这种技术工具的合法性并没有一条清晰的道路。关于这个问题的不确定性,建议先查看条款,建议有网站官方授权做网页抓取。如果没有正确的使用,网页抓取工具可能会被起诉。免费获取并不意味着必要的免费数据。
参考文献:
马蒂·阿尔钦。以及 j·伯顿·勃朗宁(2019)。 Pro Python 3:专业开发的特性和工具。压力。
Seppe vanden B .和 Bart B. (2018)。面向数据科学的实用 Web 抓取:Python 的最佳实践和示例。一种压力。
Munzert,s .,Rubba,c .,Meissner,p .和 Nyhuis (2014 年)。使用 R 的自动数据收集:Web 抓取和 Tex 实用指南。约翰·威利的儿子们。
米歇尔河(2013 年)。用 Java 进行即时网页抓取。打包。出版有限公司。
Gold,z .和 Latonero,M. (2018 年)。机器人受欢迎吗?网络爬行和抓取的道德和法律考量。华盛顿法律、技术杂志& Arts,13(3),第 277-281 页。
H.刘教授和戴维斯博士(2015 年)。网页抓取-免费样品的限制。滑坡,8(2(2015 年 11 月/12 月),第 1–5 页。
etf.com(2020 年)。 ETF.com:找到合适的 ETF——工具、评级、新闻。【在线】可在:http://www.etf.com获得。(etf.com,2020)
Investopedia。(2020). Investopedia 。【在线】可在:https://www.investopedia.com获得。(Investopedia,2020 年)
皮皮。(2020). PyPI 。【在线】可在:https://pypi.org找到。(PyPI,2020 年)
2020 年招募数据科学家的风险投资方法
终极人工智能招聘指南,仅需 4 步
信用—安东·弗里茨勒
招募和留住新人才。
对于绝大多数希望着手人工智能相关新项目的公司来说,这是当今的主要挑战。
什么是人才?
企业人才是与你的文化和战略一致的有能力的关键人物(而不是资源)。
为什么是钥匙?
因为一个由人才组成的公司,还没有发现其成功的变量,不是注定要死亡,而是要转向。
相反,一个没有能力使其服务具体化的公司,可能会享受短期内维持其服务的可变因素,但长期来看会死亡。
自我逆转的市场
招聘市场遵循供求机制。
你提议。和人才需求。
至少他们做到了。
但一个重大事件彻底颠覆了市场:全球化。
全球化摧毁了所有的进入壁垒,改变了供求机制。
现在你问。和人才报价。
具体为什么?
- 以前,人才不知道他们的选择。
- 以前,公司只在一个本地化的市场上竞争。
- 想想 Linkedin,它是这个星球上所有人才的窗口。他们知道提供什么,所有公司都可以联系他们。
就像所有的经济机制一样,这是一个零和游戏。
一个人才一次只能做一件事。
如果他不为你工作,他将自己工作或为另一家公司工作。
人工智能:紧俏的市场
与人工智能相关的学科,就像几年前的 web 开发一样,需要特定而复杂的技能,但对于绝大多数公司来说,正变得具有战略意义。
这使得 AI 中的一个天赋成为了一个不可多得的天赋。
因此,现有人才和需求之间机械地产生了差距,加大了公司的需求。
当需求超过供给时,价格就会上涨。宏观经济学 101。
你刚刚解释了为什么一些公司会为数据科学家支付几十万欧元。
那么如何吸引和留住 AI 人才呢?
不管人才如何,这里的逻辑都是一样的,但从教育学的角度来看,在一个紧张的市场中举一个具体的例子是很有趣的。
既然你主动提出要求。你必须推销自己。所以逻辑变得类似于产品的逻辑。
如果我们把问题分解到本质上,它会把我们带回四个基本问题:
- 一个人工智能专用的配置文件要寻找什么?→了解你的目标
- 竞争提供了什么?→基准测试
- 我能提供什么完美回答 1 并彻底摧毁 2 →创造竞争优势
- 如何获取个人资料以发现我的 3 →推销您的产品
1.人工智能专家档案寻找什么?
这个问题要求你了解不同的概况,他们的需求和决策标准。
第一步:列出你的需求和相应的资料
根据您的项目和策略,您将需要不同类型和粒度的概要文件。
- 数据分析师、数据科学家还是数据工程师?
- 初级还是有经验?
- 经理还是运营?
第二步:了解应聘者的决策标准
从根本上来说,你需要了解一个人才为什么要加入一家公司。
了解他们的驱动力。
根据他的个性,他的项目和他的个人资料。
从为你的候选人增加价值的角度考虑。
你为你的服务做得很好。那就为你的候选人做吧。
初级数据科学家档案的标准记分卡示例如下:
- 学徒制——35%。
- 团队— 25%
- 工资— 20%。
- 自主性/灵活性— 15%。
- 收益——5%。
经验丰富的数据工程师的标准示例如下:
- 责任— 30%。
- 工资——25%。
- 团队— 20%
- 自主性— 20%
- 学徒期——5%。
第三步:列出尽可能多的候选人通用的标准,并按个人资料类型制作记分卡。
虽然每个申请人的标准各不相同,但所有与加入公司意愿相关的需求都有一个共同的基础。它们几乎是普遍的。
问问你现在的员工。
为了了解更多关于这些标准的信息,我建议你花一些时间在https://80000hours.org/上。
2.竞争提供了什么?
没有什么神奇的方法可以找出竞争对手提供了什么,但是看看 LinkedIn,和一些以前的候选人谈谈。
一定要和一群不同的人交谈,他们都很满足,有不同的观点,以确保你得到真实的意见。
列出他们提供的服务,并对照 1 中的列表进行检查。
我倾向于认为你并不是在和自由职业者竞争。根据定义,如果这是最适合人才的模式,你和它之间就没有真正的长远眼光。除非你的文化倡导同样的价值观:自主性、绩效结果和灵活性。
在这一点上,你甚至可以去乘坐 Fiveer,Upwork 或 Malt,寻找符合你的报价的配置文件。
3.创造竞争优势
在确定你的竞争优势之前,首先要问你自己的问题是什么首先定义了你。
你的内部文化是什么?你真正的价值观是什么?
诚实地回答这些问题将为您节省宝贵的时间,不仅因为您将知道哪些档案适合您的文化,还因为您的竞争优势将不言自明!
回答问题:你现在的员工真正加入你的原因是什么?我能提供什么来区分?
现在你知道了:
- 你的目标和他们的决策标准
- 你的价值观
- 你的竞争对手和他们的报价
你要做的就是让自己与众不同。
你的目标群体重视学习,你的竞争对手没有真正的培训计划和一般的经理,打赌吧!
如果你的竞争对手擅长微观管理艺术,那就提倡自治和远程工作!
如果你的竞争对手提倡自主权,但薪酬相对较低,那就提高你的薪酬吧!
4.推销你的提议
职位描述
职位描述在公司里仍然是必不可少的。和简历一样。
没有互动很难判断一个人或者一个公司的好坏,但是锻炼是有用的。
工作描述应该吸引你的候选人,让他们愿意为你工作。它必须简洁,明确的使命,突出你的文化。
1.谈论你的义务和责任,而不是你的权利和要求。
我们在寻找一个有能力的人,我们的文化提倡 X,Y,Z,我们希望遇到重视 X,Y,Z 的人..
2.你很受欢迎。不要把好处放在最后而是放在开头!
从展示你的文化而不是公司历史开始,解释你的公司相对于你的竞争对手的优势。
3.不要用微弱的信号表达。
如果你想展示一种促进交流的轻松文化,在你的提议中明确这一点!
婴儿脚照片将被类似这样的句子取代:我们高度重视协作,我们通过 X,Y,z 大力投资于员工之间的关系。
4.把没有附加值的都去掉!
开门见山,不要增加不必要的价值。说你在寻找一个直爽、诚实、聪明、有团队精神、适应性强、有能力的人并不能增加价值。
再次坚持你与众不同的价值观。
例如:我们在寻找一个不怕拿起电话,不怕被拒绝,喜欢不断接受挑战,希望得到指导,能够让我们朝着既定方向发展的人!
5.不要夸大你的才能!
似乎显而易见。少说多做更好。
6.不要和市场结盟!
我向你保证,你要为你的才华付出高于市场的代价。这有几个原因:
- 人才的质量就是你提供的质量。
- 你可以把工资溢价转嫁到你的产品报价上。
- 离职和招聘的成本是招聘溢价的 10 倍
- 您将收到合格档案的请求和建议。
- 你的员工会觉得他们的工作受到重视。
- 你可以要求更高
我不断听到,“我们符合市场价格”。
但是真正符合市场价格的又是谁呢?
*均市场报价。
你为你的 iPhone 24 多付了两倍的钱,因为你看到了产品的附加值(或者因为你被他们的品牌所吸引,这也是他们自身的价值)。
为你的员工支付额外费用。
这是你能做的最好的投资。
这不是文化的替代品。
这一点很重要,值得在以后的文章中进一步阐述。
附加备注
- 制作个人简介的证明,使任务更加明确。
- 事先允许与您的团队会面
- 为你的目标受众大量投资内容
- 投资对员工进行再培训,例如希望成为架构师或数据科学家的数据库管理员或数据分析师。招聘不是唯一的解决办法。
- 使用值得信赖的第三方服务,比如对你的文化了如指掌的独立招聘人员。
我叫 Eytan Messika,曾在风投行业工作,现在在 AI 咨询公司工作。我也帮助数据科学家找工作。随意连接上 Linkedin 。
模糊逻辑和模糊系统的简要介绍
“随着复杂性的增加,精确的陈述失去了意义,有意义的陈述也失去了精确性”――卢特菲·扎德
介绍
许多任务对人类来说很简单,但对机器来说却是一个持续的挑战。这种系统的例子包括在杂乱的环境中行走、提升易碎的物体或停车。人类处理模糊和不精确数据的能力让我们很容易完成这些任务。因此,如果我们的目标是复制人类操作员的控制行为,我们必须能够模拟操作员的活动,而不是设备本身的活动。我们的模型必须能够处理模糊的信息。
基于模糊逻辑的系统恰恰做到了这一点;它们在特别复杂的系统中表现出色,已经成功用于从语音和手写识别到地铁列车速度控制的许多应用中。
本文着重于模糊集和系统的基本思想。
清晰的集合和逻辑
经典逻辑基于清晰集合,其中一组不同的对象被认为是一个集合。例如,白色和红色本身都是独立的物体,但是可以用符号{red,white}将它们视为一个集合。按照惯例,清晰集合被指定为大写字母,因此上述示例可以描述为:
F = {红白}
清晰子集可以从更广泛的集合中定义,其中集合的元素根据某种条件属于该子集。例如,集合 A 可以被定义为大于或等于 4 且小于或等于 12 的数的集合。可以使用以下符号来描述该语句:
A ={i | i 是一个整数,4 < = i < = 12}
如果我们引入集合的特征或指示函数的概念,则上述子集的图形表示是可能的,也就是说,在这种情况下,在整数集合上定义的函数,我们称之为 X,它指示 X 中子集 A 中元素的成员资格。这是通过将值 1 赋给 A 中的 X 元素,将值 0 赋给不在 A 中的 X 元素来实现的。因此,在我们的示例中,该集合的指示函数是:
这可以用图形显示如下:
图一。
两个集合的交集是包含两个集合共有的所有元素的集合。两个集合的并集是包含任一集合中所有元素的集合。集合 A 的否定是包含所有不在 A 中的元素的集合。
模糊集
模糊集是由洛特菲·扎德(1921–2017)在 1965 年引入的。
与清晰集合不同,模糊集合允许部分属于一个集合,该集合由隶属度定义,表示为,可以取从 0(元素根本不属于该集合)到 1(元素完全属于该集合)的任何值。
很明显,如果我们除去除了 0 和 1 之外的所有隶属值,模糊集将会崩溃为上一节所描述的清晰集。
集合的隶属函数是集合元素和它们的隶属度之间的关系。下图说明了如何将隶属函数应用于温度。
在上面的例子中,模糊集描述了发动机的温度范围,从很冷到很热。值是集合中成员的数量。例如,人们可以注意到,在 80 度的温度下,发动机可以被描述为热0.8 倍,而非常热0.2 倍。
在上一节中,讨论了清晰集合的并集、交集和非运算符,因为它们提供了一种表达对推理至关重要的合取和析取(和/或)的方式。
计算两个模糊集合的并集的最常见方法是对集合应用最大值运算符。确实存在其他方法,包括在两个集合上使用乘积运算符。类似地,计算两个模糊集合的交集的最常见方法是对集合应用最小运算符。模糊集的补集是通过从 1 中减去集隶属函数来计算的。
一个重要的观察结果是,一个元素在一个集合和该集合的补集中都有一定的隶属度。因此,作为一个例子,元素 x 既可以在 A 中,也可以在“非 A”中。
模糊推理系统
模糊系统是一个模糊专家知识库,可以用模糊的术语而不是精确的布尔逻辑推理数据。专家知识是模糊隶属函数和一组模糊规则的集合,称为规则库,具有以下形式:
**IF** (conditions are fulfilled) **THEN** (consequences are inferred)
模糊系统的基本配置如下所示:
一个典型的模糊系统可以分为四个主要部分,即模糊化器、知识库、推理机和解模糊器;
模糊化器将一个真实的清晰输入映射到一个模糊函数,从而确定输入对一个模糊概念的“隶属度”。在许多控制器中,输入变量的值被映射到相应论域的值的范围。输入模糊集的范围和分辨率以及它们对模糊化过程的影响被认为是影响控制器整体性能的因素。
知识库包括应用领域的知识和伴随的控制目标。它可以分成一个数据库,该数据库包含用于在控制器中表达语言控制规则的定义,以及一个描述该领域专家所掌握的知识的规则库。直觉上,知识库是模糊控制器的核心元素,因为它将包含完成其执行任务所需的所有信息。各种研究人员已经应用技术来微调模糊控制器的知识库,许多人使用其他人工智能学科,如遗传算法或神经网络。
推理机提供控制器的决策逻辑。它利用模糊蕴涵和模糊推理规则来推导模糊控制动作。在许多方面,它可以被看作是对人类决策的模仿。
去模糊化过程将模糊控制值转换成清晰的量,即,它将单个点链接到模糊集,假定该点属于模糊集的支持。有许多去模糊化技术,最著名的是区域中心或重心。
其他去模糊化方法包括最大值优先和最大值*均。
几个推理模型使用模糊集来推理给定输入的系统输出。最流行的方法之一是由 Abe Mamdani 教授设计的,他使用模糊集来控制蒸汽机。另一个流行的模型是由 Tomohiro Takagi 教授和 Michio Sugeno 教授开发的。
在 Mamdani 推理中,模糊规则的前提和结果是模糊集。这种推理是基于广义假言,即模糊规则的结果的真实程度就是前件的真实程度。如果有一个以上的先行子句,则使用 min t-norm 运算符连接各个隶属度。如果模糊系统包含几个规则,它们的输出使用最大 s-范数算子组合。去模糊化是必要的,以便随后的动作可以用一个明确的值来表示。该过程的图示如下所示。
在 Takagi-Sugeno 推理模型中,结果是将清晰的输入值映射到规则清晰的输出的函数。因此,模糊规则的形式如下:
**IF** x IS X **and** y IS Y **THEN** z=f(x,y)
其中 f 通常是 X 和 y 中的线性函数。与 Mamdani 模糊系统相反,规则不是使用最大值算子来组合的,而是通过找到加权*均值来组合的,其中给定规则的权重是其前提的隶属度。因此,Takagi-Sugeno 系统不需要任何去模糊化。
模糊系统的设计
在本节中,我们将构建并执行一个简单的示例系统,以可视化模糊推理系统的设计和执行。这里考虑的假设系统根据环境的温度和湿度控制风扇的速度。因此,我们的系统由两个输入(温度和湿度)和一个输出(风扇转速)组成。
我们系统设计的第一步是定义模糊集来描述输入和输出变量。为简单起见,每个变量将由三个模糊集来表征,即:
Temperature: Cold, Medium, Hot
Humidity: Dry, Normal, Wet
Fan Speed: Slow, Moderate, Fast
下图显示了我们系统的输入和输出变量及其各自集合的图形表示。
可以注意到,三角形集合被用来描述这个系统的大多数集合;然而,“正常”湿度是用一个梯形集来指定的。模糊集反映了用户设计系统的知识,因此它们可以采取各种各样的形状。
注意,输出也是用模糊集描述的;因此,正在考虑的系统是一个 Mamdani 型系统,它使用模糊规则将与系统输入相关的模糊集链接到与系统输出相关的模糊集。
共有九条规则用于描述操作风扇所需的知识:
If Temperature is Cold and Humidity is Dry Then Fan Speed is Slow
If Temperature is Medium and Humidity is Dry Then Fan Speed is Slow
If Temperature is Cold and Humidity is Normal Then Fan Speed is SlowIf Temperature is Hot and Humidity is Dry Then Fan Speed is Moderate
If Temperature is Medium and Humidity is Normal Then Fan Speed is Moderate
If Temperature is Cold and Humidity is Wet Then Fan Speed is ModerateIf Temperature is Hot and Humidity is Normal Then Fan Speed is Fast
If Temperature is Hot and Humidity is Wet Then Fan Speed is Fast
If Temperature is Medium and Humidity is Wet Then Fan Speed is Fast
如果我们使用一个组合的模糊规则库,这些规则可以被可视化,这是一个网格,其中输入模糊集占据边缘,因此网格中的每个单元定义一个规则。下图显示了该系统的规则库。
当一个输入组合输入到系统时,会发生以下步骤,例如,假设温度为 18 度,湿度为 60%:
- 确定每组输入变量的隶属度。因此我们可以说 18 度的温度是
0.48 Cold
0.29 Medium
0.00 Hot
60%的湿度是
0.0 Wet
1.0 Normal
0.0 Dry
- 使用这种输入组合,两个规则以高于零的程度被触发,这可以在下面更新的模糊规则库中看到:
因此,我们的模糊输出将由激活度为 0.48 的慢速和激活度为 0.29 的中速组成。两个规则或系统模糊输出的综合效果如下所示:
使用重心去模糊化最终去模糊化输出集合,并且获得 36.814 的清晰值来驱动风扇。
结论
本文简要介绍了模糊集和模糊推理。它展示了如何使用语言术语来表示人类知识来实现对系统的控制。在下一篇文章中,将使用 python 从头开始构建一个模糊推理系统。
一个非常精确和快速的自动获取谷歌趋势数据的方法
图片来源:Unsplash 的 Alex Blajan。
一个一站式脚本,使用 Pytrends 通过精确的关键字自动拉动 Google trends
新冠肺炎为“谷歌趋势”在美国的使用提供了便利(见下图)。毕竟,它是一个免费的公开可用的工具,提供跨谷歌搜索引擎的实际搜索请求。越来越多的公司利用谷歌趋势来了解类别趋势、消费者热门搜索查询、竞争对手在“黑天鹅”疫情事件中的表现。
每个 Google Trends 请求包含 5 个独特的参数:
- 关键词:你的关键词在这里。您可以使用下拉框下的提示来选择正确的关键字。
- 国家:拥有国际足迹的公司可以使用这个功能来获取各国的趋势。
- 日期区间:选择趋势的时间范围。请注意,google 趋势数据是基于位置和时间进行标准化的。因此,不同的时间范围会产生不同的结果。
- 类别:表示您更喜欢搜索关键字的类别。
- 搜索类型:选择搜索源,即谷歌搜索、图片搜索、新闻搜索、谷歌购物和 YouTube 搜索。
挑战:
大规模收集谷歌趋势数据面临两大挑战。
1。单个关键字手动拉动是费时的。
虽然 Google Trends 提供了“比较”功能来比较关键词,但缺点是它根据输入的最流行的术语将结果从 0 到 100 进行缩放。不太受欢迎的关键字会很快失去敏感性,如果你把它与一个受欢迎的。比如你拿“耐克”品牌和“至尊”品牌对比,基本上会得到一条“至尊”的*线。在这种情况下,当报告“最高”搜索增长趋势时,你会犯很大的错误。因此,建议分别单独拉动“耐克”趋势和“至尊”趋势。
直到你有太多的关键词需要提取,你还是有时间的。例如,当比较 50 个服装和鞋类品牌时,您需要下载 50 个 excels 并将它们组合在一起。
②。当前可用的自动化 python 方法不查询精确的关键字,这意味着它们不准确。
使用 python 有许多可用的方法来获取谷歌趋势数据。然而,他们都没有建立自动代码,可以把精确的 关键词。单词通常有多种含义,这并不罕见。例如,“巴塔哥尼亚”可以是一家服装公司,也可以是南美的一个地区。简单地搜索“巴塔哥尼亚”会给我们含糊不清的结果,因为它包含两个搜索词。我们需要确保搜索到正确的关键词。
目标:
我们的目标是提供一个解决方案,精确地、单独地、自动地提取多个关键字的 google 趋势数据。
具体来说,我们将提取三个国家(美国、英国、德国)的六个服装/鞋类品牌(耐克、阿迪达斯、安德玛、Zara、H&M、路易威登)的谷歌趋势数据。使用 Python,有四个步骤可以实现这一点:
- 第一步:安装
pytrends
API - 第二步:获取准确的关键词
- 第三步:按照国家的关键词提取谷歌趋势数据
- 第四步:可视化谷歌趋势
步骤 1:安装 pytrends API
首先,我们需要安装名为“pytrends”的软件包,该软件包旨在使用 python 拉取 google trends。只需从您的终端执行以下代码。你可以在这里找到 pytrends API 的完整文档。
pip install pytrends
然后我们将导入必要的包。
import pandas as pd
import pytrends
from pytrends.request import TrendReq
pytrend = TrendReq()
第二步:获取准确的关键词
如前所述,我们需要精确的关键词以避免歧义。Pytrends 提供了一个名为pytrend.suggestions
的函数,可以为一个关键字返回几个建议。通常,第一个建议是最受欢迎的。“mid”列包含我们想要搜索的确切关键字。
KEYWORDS=['Nike','Adidas','Under Armour','Zara','H&M','Louis Vuitton']
KEYWORDS_CODES=[pytrend.suggestions(keyword=i)[0] for i in KEYWORDS]
df_CODES= pd.DataFrame(KEYWORDS_CODES)
df_CODES
第三步:通过关键词获取谷歌趋势数据
接下来,我们将设置这 5 个参数。
EXACT_KEYWORDS=df_CODES['mid'].to_list()
DATE_INTERVAL='2020-01-01 2020-05-01'
COUNTRY=["US","GB","DE"] #Use [this link](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) for iso country code
CATEGORY=0 # Use [this link](https://github.com/pat310/google-trends-api/wiki/Google-Trends-Categories) to select categories
SEARCH_TYPE='' #default is 'web searches',others include 'images','news','youtube','froogle' (google shopping)
然后,我们将编写代码,使用上述参数通过国家的精确关键字提取 google trends 数据。
Individual_EXACT_KEYWORD = list(zip(*[iter(EXACT_KEYWORDS)]*1))
Individual_EXACT_KEYWORD = [list(x) for x in Individual_EXACT_KEYWORD]
dicti = {}
i = 1
for Country in COUNTRY:
for keyword in Individual_EXACT_KEYWORD:
pytrend.build_payload(kw_list=keyword,
timeframe = DATE_INTERVAL,
geo = Country,
cat=CATEGORY,
gprop=SEARCH_TYPE)
dicti[i] = pytrend.interest_over_time()
i+=1
df_trends = pd.concat(dicti, axis=1)
我们会做一些清理工作,将这些关键词改回易读的品牌名称。
df_trends.columns = df_trends.columns.droplevel(0) #drop outside header
df_trends = df_trends.drop('isPartial', axis = 1) #drop "isPartial"
df_trends.reset_index(level=0,inplace=True) #reset_index
df_trends.columns=['date','Nike-US','Adidas-US','Under Armour-US','Zara-US','H&M-US','Louis Vuitton-US','Nike-UK','Adidas-UK','Under Armour-UK','Zara-UK','H&M-UK','Louis Vuitton-UK',
'Nike-Germany','Adidas-Germany','Under Armour-Germany','Zara-Germany','H&M-Germany','Louis Vuitton-Germany'] #change column names
第四步:可视化谷歌趋势
一眨眼的功夫,我们就得到了谷歌趋势数据。最后,让我们可视化路易威登跨国家的谷歌趋势。正如我们所见,路易威登显然受到了新冠肺炎的沉重打击,就像许多其他品牌和行业一样。
import seaborn as sns
sns.set(color_codes=True)
dx = df_trends.plot(figsize = (12,8),x="date", y=['Louis Vuitton-US','Louis Vuitton-UK','Louis Vuitton-Germany'], kind="line", title = "Louis Vuitton Google Trends")
dx.set_xlabel('Date')
dx.set_ylabel('Trends Index')
dx.tick_params(axis='both', which='both', labelsize=10)
摘要
随着各公司密切关注新冠肺炎期间消费者行为的变化,谷歌趋势工具的使用出现激增。为了帮助实现这一点,我们构建了一个轻量级应用程序来精确、自动地提取 Google 趋势数据。
最后,保持积极,感谢阅读!
云处理现在更简单,更便宜!
在云上运行/分发您的* 现有* 处理/训练代码的一种非常简单且便宜的方式
作者图片
这发生在我身上,我相信也发生在你和许多从事中小型项目的数据科学家身上:
您已经在自己的训练管道(预处理->训练->测试)上投入了很多,使用不同的参数在本地尝试了几次,看起来很棒。但是……你意识到你需要更多的 RAM/CPU/GPU/GPU 内存或者所有这些加在一起才能充分利用它吗?
它的发生有很多原因——
- 您的本地设置花费了太多时间来进行培训
- 您需要更大的批处理大小,并且它不适合您的本地 GPU 内存
- 你想要调整超参数,所以需要很多训练
- 您希望将一些预处理步骤移到培训期间完成,例如,为了节省磁盘空间/加载时间,而 CPU / RAM 无法完成
- …
因此,,理论上,你已经拥有了你需要的一切,但是你只需要在一个更好的硬件上运行它……这在今天应该不是问题,不是吗?
现有解决方案
确实有很多解决方案,这里有一些相关的技术/*台/解决方案:
通用
- Apache Airflow —“以编程方式创作、安排和监控工作流的*台”
- 雷——“快速简单的分布式计算”
云提供商 AI 解决方案
- kube flow——“kubernetes 的机器学习工具包”( pipelines )
- GCP 人工智能*台——“一个*台来构建、部署和管理机器学习模型”(训练、管道、分布式 PyTorch 、分布式 TensorFlow )
- Azure 机器学习——“企业级机器学习服务,更快地构建和部署模型”(培训)
- AWS Sagemaker —“面向每一个开发者和数据科学家的机器学习”(培训、分布式 PyTorch 、分布式 TensorFlow )
分布式培训框架
张量流
- TensorFlow 分布式培训文档
- TensorFlow 自己的 GCP 分布式 GCP 培训教程
- TensorFlow 培训(TFJob) 针对 Kubernetes(kube flow 的一部分)
PyTorch
- PyTorch 分发的培训文件
- PyTorch 自己的 AWS 分布式培训教程
- Kubernetes 的火炬控制器
- 在 CPU 或 GPU 上运行分布式 PyTorch 培训(使用 Kubeflow 管道)
…
所有现有解决方案的优缺点的比较值得一提(甚至是一系列),我肯定我忘了提到许多其他的:)
但是,我找不到一个可以让你运行我现有代码的工具,只需要很少或者不需要额外的编码,很便宜,也不需要很多之前的特定*台知识。我也只是想尝试拥有自己的开源项目,包括文档和完全自动化的测试和发布管道:)
这就是我想出simple-sagemaker和这篇文章的原因。
很简单-Sagemaker 来拯救
Simple——sagemaker允许您将现有的代码原封不动地放在云上运行,不需要或只需要很少的代码修改。
这篇文章的剩余部分展示了如何使用这个库进行通用处理。后续文章将展示如何将其用于更高级的案例,如 PyTorch 分布式培训等。
更全面的文档和例子可以在 github 项目上找到,还有一些更多例子,包括这篇文章中所有例子的源代码。
要求
- Python 3.6 以上版本
- 为 boto3 配置的 AWS 帐户+区域和凭证,如 Boto3 文档中所述
装置
pip install simple-sagemaker
运行 shell 命令
现在,要让 shell 命令cat /proc/cpuinfo && nvidia-smi
在单个ml.p3.2xlarge
****实例上运行,只需运行下面的ssm
命令(关于ssm
CLI 的文档在下面的中给出):
ssm shell -p ssm-ex -t ex1 -o ./out1 --it ml.p3.2xlarge --cmd_line "cat /proc/cpuinfo && nvidia-smi"
一旦任务完成(几分钟),输出日志就会下载到./out1
:
正如您可能猜到的那样,使用这个命令行,您会得到:
- 选择一个用于运行代码的预构建映像(默认为 Sagemaker 的 PyTorch 框架映像)。
- 一个 IAM 角色(默认名称为
SageMakerIAMRole_ssm-ex
)和amazonseagemakerfullaccess策略被自动创建用于运行任务。 - 一个
ml.p3.2xlarge
spot 实例为你启动,你只需为你使用它的时间付费!
注意:这比执行时间稍长,因为它包括启动(如下载图像、代码、输入)和关闭(保存输出)等时间。 - 在实例上执行 shell 命令。
- shell 命令 exist 代码为 0,因此它被认为已成功完成。
- 输出日志保存到 CloudWatch,然后从 CloudWatch 下载到
./out1
文件夹。
很酷的第一名,不是吗?
分发 Python 代码
同样,在上运行下面的ssm_ex2.py
两个ml . p 3.2x largespot实例:
只需运行下面的ssm
命令:
ssm run -p ssm-ex -t ex2 -e ssm_ex2.py -o ./out2 --it ml.p3.2xlarge --ic 2
输出被保存到./out2
:
您可能已经猜到了,这里您还会得到以下内容:
- 本地 python 脚本被复制到 S3 上的一个专用路径(
[Bucket name]/[Project name]/[Task name]/[Job Name]/source/sourcedir.tar.gz
)(更多细节在这里)。 - 两个 spot 实例用 S3 桶中的代码启动。
很酷的#2,不是吗?
高水位流量
这是一个代表高层次流程的图表:
一个功能全面的高级示例
现在是一个高级的和完全(嗯,几乎:)特色的版本,但实现起来很简单。注意:当我们定制图像时,需要 docker 引擎。
该示例由两部分组成,每一部分都展示了一些特性。此外,这两个部分是“链式”的,这意味着第一个部分的输出是第二个部分的输入。
为了举例说明大多数功能,使用了以下目录结构:
.
|-- code
| |-- internal_dependency
| | `-- lib2.py
| |-- requirements.txt
| `-- ssm_ex3_worker.py
|-- data
| |-- sample_data1.txt
| `-- sample_data2.txt
`-- external_dependency
`-- lib1.py
- 代码 —源代码文件夹
- internal_dependency —源代码文件夹中的依赖项
- requirements.txt — pip 需求文件列出了在运行 worker
transformers==3.0.2
之前需要安装的包
2.数据** —输入数据文件**
3.外部依赖** —附加代码依赖**
我们将使用 to 任务,首先得到两个输入通道
第一项任务
该任务获得两个输入通道:
- 数据通道——分布在两个实例之间的
./data
上的本地路径(由于ShardedByS3Key
) - 人物频道——S3 的一条公共道路
演示了以下内容:
- 命名项目(
-p
)和任务(-t
)。 - 使用本地数据文件夹作为输入,它分布在实例中(
— i
、ShardedByS3Key
)。该文件夹首先被同步到 S3 上专用于该特定任务的目录中(根据项目/任务名称),然后被提供给工人。如果你再次运行相同的任务,就不需要上传整个数据集,只需要再次同步即可。 - 使用公共 s3 存储桶作为附加输入(
--is
)。角色会自动添加到所使用的 IAM 策略中,以允许该访问。 - 构建一个定制的 docker 映像(
--df
、--repo_name
、-- aws_repo_name
),以使pandas
和sklearn
库对工人可用。基本映像是自动获取的(PyTorch 框架是默认的),映像在本地构建,然后上传到 ECR 供正在运行的实例使用。 - 超参数任务类型。任何额外的参数都被认为是超参数。在
--
(后面跟一个空格)之后的任何内容都按原样传递给执行的脚本命令行。 - 启动两个实例(
--ic
)。 --force_running
—确保我们再次运行任务(作为本例的一部分)。- 使用按需实例(
--no_spot
)。 requirements.txt
的用法——因为它是源代码文件夹(-e
)的一部分,所以在运行 worker 之前会自动安装。internal_dependecty
文件夹作为源代码文件夹的一部分被复制。
很酷的 3 号,不是吗?
工人代码:
工人可以通过使用WorkerConfig
对象或环境变量来访问其配置。例如:
worker_config.channel_data
—输入数据worker_config.channel_persons
—来自公共 s3 桶的数据worker_config.instance_state
—实例状态,在相同任务的执行之间维护
在这种情况下,工作进程将输入通道数据中的文件“处理”到模型输出文件夹中,并将附加文件写入输出数据文件夹。
完整的配置文件可以在这里找到。
第二项任务
第二个任务也获得两个输入通道:
- ex3_1_model 通道—第一个任务的模型输出
- ex3_1_state 通道—第一个任务的状态
演示了以下附加功能:
- 链接—使用第 1 部分的输出(
— iit
)作为该部分的输入。模型输出和凝视都被采用。 - 使用附加的本地代码依赖项(
-d
)。 - 使用 TensorFlow 框架作为预建图像(
-f
)。 - 标记作业(
-- tag
)。 - 定义一个 Sagemaker 度量(
-- md
)。
很酷的 4 号,不是吗?
代码可以使用worker_config.ex3_1_state
和worker_config.ex3_1_state
访问其输入数据通道。
此外,分数日志由上面的ssm
命令中的"Score=(.*?);"
正则表达式捕获,然后可以在 AWS 控制台上查看度量图:
完整的代码
我们可以把这两个 worker 放在一个文件中,使用task_type
超参数来区分这两种类型的执行:
结论
我希望我成功地传达了简单的信息,并说服您下次需要更强大的硬件来处理脚本时,尝试一下simple-sagemaker。上面的例子,以及总结你所得到的“非常酷”的观点,不言自明:)。
让我知道你是否喜欢它,在下面鼓掌/看 github 项目。
亚马逊 Sagemaker 上深度学习的一个非常简单的介绍
这里有一个非常简单的方法来开始在云中进行深度学习!
介绍
在本文中,我将引导您将数据加载到 S3,然后在 Amazon Sagemaker 上构建一个 Jupyter 笔记本实例来运行深度学习作业。
🇨🇭·克劳迪奥·施瓦茨| @purzlbaum 在 Unsplash 上拍摄的照片
我将要回顾的方法并不是在云中运行深度学习的唯一方法(事实上它甚至不是推荐的方法)。但是这个方法是一个很好的开始方式。
优点:
- 轻松过渡到云!比方说,我想在一台更大的机器上运行我已经建立的代码,或者我没有本地 GPU,我想在没有 Google Colab 超时的情况下运行一个更长的作业,那么这个方法应该允许您以更少的代码更改启动并运行 AWS!
- 一旦你掌握了这种方法,你就可以转向更强大的选项。
CONS:
- 目前,Sagemaker 没有针对笔记本实例的自动关机功能。为什么这很重要?好吧,假设我做一份培训工作,然后去看电影。当我回到家,我的笔记本\GPU 实例仍然在运行,即使作业在几个小时前就结束了。这样不好,因为我是为那个时间付费的(而且 GPU 也不便宜)。所以用这种方法,你基本上不能让你的机器处于无人监控的状态。
边注:有一种使用“脚本模式”自动关机的方法,但是它需要一些额外的编码。这是一个你可以探索的选项,如果你愿意,你可以在这里 阅读我关于脚本模式 的文章。
在我创建了一个 S3 桶和一个 Sagemaker 笔记本实例之后,我将向您介绍一些我编写并存储在 GitHub 上的示例代码。GitHub 上的笔记本遍历了如何在 S3 连接到您的数据,然后遍历了一些 hyperpt+tensor flow \ Keras 代码。在我的远视例子中,我正在为一个递归神经网络进行超参数搜索。
神经网络超参数调整动机
(有一点需要注意,笔记本上没有提到的是,远视是在 负 精度上进行优化。是重要的。Hyperopt 希望找到您的成本指标的最小值,在我的情况下就是准确性。所以用 负 精度找到精度最高的网络!)
好吧,如果你正在读这篇文章,那么你可能以前训练过神经网络。你甚至可能用 sklearn 来做神经网络随机搜索交叉验证,但是你想把它带到下一个层次。
首先,我推荐阅读下面这篇关于超参数调优的文章。简而言之,随机搜索实际上做得很好,不需要运行大量的迭代。但是不管你是使用随机搜索还是贝叶斯方法,你都可能遇到以下问题…
1.神经网络上的超参数调整需要很长时间(即使使用 GPU)。
2.在任何免费培训*台上运行长时间的作业(例如 Google Colab,Kaggle)通常会超时。
现在,你做什么?
好吧,你有两个选择:
1.买一台带 GPU 的个人电脑(这是要花钱的,大一点的会好一点)**
2.在云上租一个 GPU(也要花钱)**
就我个人而言,我最终购买了一台带 GPU 的笔记本电脑,但在此之前,我尝试了云选项。拥有一个个人 GPU 是很棒的,但随着你的进步,你会发现自己需要更多的能力,无论如何你都会回到云中(至少我是这么发现的)。
好了,节目已经开始了,我们如何使用 Sagemaker 来建立我们的神经网络!
第一步:进入 AWS 并创建一个帐户。
似乎是合乎逻辑的第一步。转到下面的链接,然后单击“创建 AWS 帐户”(如果您还没有帐户)。
步骤 2:将数据保存到 S3
因此,此时您应该在管理控制台上。
接下来,点击“服务”,然后点击“S3”。
现在点击“创建存储桶”。
现在按照提示创建您的 bucket,给它命名,等等。确保你选择了你所在的地区。我在美国东海岸,所以对我来说,北弗吉尼亚的作品。
如果你像我一样,只是在玩 Sagemaker,并且不太关心权限(因为存储的信息都不是敏感的)那么你可以点击“下一页”进入第 2-4 页。
当你完成后,你应该有一个新的 S3 桶!现在点击你的 S3 桶名。
这应该带你到你的 S3 桶,你可以上传数据!点击“上传”,然后点击“添加数据”,从本地机器中选择您的数据,并按照提示进行操作。再说一次,我并不太关心权限,所以我只是在选择了我的数据后,点击了很多次“下一步”。
(注:S3 是有代价的。因此,当您完成时,您可能希望删除您的数据集,甚至您的存储桶。)**
第三步:启动 Sagemaker 笔记本
返回“服务”并找到\点击“Sagemaker”。
(注意:我们将启动一个运行在 ml.p2.xlarge 上的笔记本实例,它有一个 GPU,成本大约为 1.20 美元/小时。当您完成培训后,请确保关闭笔记本实例。还要注意的是,这份工作是要花钱的!!)
https://aws.amazon.com/sagemaker/pricing/
单击笔记本实例>“创建笔记本实例”
现在,我们将为笔记本命名,并确保选择一个 ml.p2.xlarge 来获取一个 GPU 实例。
你可能必须通过一些权限,如果你像我一样,你可以绕过很多这种。(我在这里不打算涉及这些)。此外,如果您像我一样,在访问 GPU 时可能会遇到一些问题,在这种情况下,只需通过“支持”下拉菜单联系支持人员,并提交专门针对 GPU 实例的配额增加。当 AWS 完成您的配额增加后,您必须返回“创建笔记本实例”并重新开始。
一旦您完成了“创建笔记本实例”步骤,笔记本实例现在将被创建。这可能需要一些时间…
迈克·肯尼利在 Unsplash 上拍摄的照片
创建实例后,您应该能够单击“打开 Jupyter ”,这将带您进入运行在新 GPU 实例\机器上的 Jupyter!
Jupyter 打开后,单击“新建”下拉菜单并选择“conda_tensorflow_36”,创建一个新的“conda_tensorflow_36”笔记本。
第四步:运行一些代码!
现在,您可以在 GitHub 上查看我的完整笔记本,其中包括如何连接到您的数据、安装 hyperopt 以及运行您的作业的注释!查看完整的 GitHub repo 与笔记本此处。
第五步:全部关闭!
完成后,记得通过单击您的笔记本实例名称,然后单击“停止”来关闭您的笔记本实例。我甚至建议删除笔记本实例,以及重新访问您的 S3 存储桶并删除您的存储桶,否则将所有这些工作放在亚马逊上会让您损失金钱!
结束了!
谢谢大家,希望这对你有所帮助。快乐学习!😄
其他资源\参考资料:
*【https://github.com/hyperopt/hyperopt *
https://hyperopt.github.io/hyperopt/
https://blog . cloud ability . com/AWS-S3-了解-云存储-节省成本/
一种非常简单的利用马尔可夫模型查找表进行天气预报的方法
奥斯曼·拉纳在 Unsplash 上拍摄的照片
天气是一个非常复杂的事件。即使你只是想预测降雨事件,这也是相当困难的。但是你知道,有一句名言是这样说的
历史会重演
基于此,我们将尝试使用马尔可夫模型来预测天气。但是,第一件事是,我们必须理解马尔可夫模型的概念。
马尔可夫模型
什么是马尔可夫模型?这是一个非常简单的概念。根据维基百科,马尔可夫模型是
在概率论中,马尔可夫模型是一种随机模型,用于建模随机变化系统。假设未来状态只取决于当前状态,而不取决于之前发生的事件(即假设马尔可夫性质)。
我们必须注意的词是
未来状态仅取决于当前状态
你如何达到目前的状态并不重要,重要的只是我们目前的状态。这个很简单。为了说清楚,我们举个例子
1 和 1 和 1 和 1 和 1 和 2 和 1
在上面的字符串中,有 3 个唯一的字符,即“1”、“and”和“2”(为了简单起见,我们忽略空格(" ")也是一个字符的事实),这意味着我们有 3 种状态。为了确定如何从一个状态改变到另一个状态,马尔可夫模型有一个马尔可夫转移矩阵。这是一个矩阵,它将某一种情况的概率映射到另一种状态,包括它本身。对于这种情况,矩阵的一般形式如下
我想你们都明白上面矩阵中的符号。反正 Prob 是概率的简称。现在我们如何在转移矩阵中确定这样的概率呢?我们从观测数据中抽样获得。让我们在示例字符串中映射所有改变状态的事件及其频率。
首先,这里所有的变化状态事件
1 和 1 和 1 和 1 和 1 和 2 和 1
[1-> and][and-> 1][1-> and][and-> 1][1-> and][and-> 1][and-> 1][1-> and][and-> 1][and-> 1][1-> and][and-> 2][and-> 2][and-> 1]
所以我们得到了
“1”更改为“和”(5/5 = 100%)
“与”变为“1”(6 个中的 5 个= 83.33%)
“和”更改为“2”(6 个中的 1 个= 16.66%)
“2”更改为“和”(第 1 个,共 1 个= 100%)
由此,我们得到了转移矩阵
有了这个矩阵,我们就知道了这样一个事实:如果我们当前的状态是“1”,那么下一个状态或下一个单词一定是“and”,从“and”到“1”的概率很大(83%),到“2”的概率很小(17%)。从“2”开始,它将在“和”中结束。哦,供你参考有几种马尔可夫模型。这种假设系统完全可观测且自治的马尔可夫模型称为马尔可夫链。
使用马尔可夫模型预测天气
现在我们明白了什么是马尔可夫模型。我们知道引语(“历史重演”)和马尔可夫模型之间的关系。实际上,做天气预报的方法之一叫做模拟法。它是关于检查与我们当前状态相同的过去状态,并在这个状态之后根据过去发生的事情预测天气。因此,使用马尔可夫模型来应用模拟方法预测天气是完美的。
是时候继续我们的实验细节了。在马尔可夫模型的典型示例中,该示例总是关于天气预测,但是具有诸如“晴天”、“多云”和“雨天”的简单状态。在真实的天气报告或预测中并不是那样简单。真实报告或预测除了天气之外,还定义了当前或未来时间的温度、湿度、能见度和风。
在这个实验中,我们将把温度、湿度、能见度、风和天气的每一种独特组合视为一种状态。为了避免组合的无限可能性,我们对除天气以外的所有参数进行分组和舍入(除天气以外的所有参数都是实数,范围 0 到 1 之间有无限个实数)。分组和舍入的细节我们将在后面讨论。即使我们已经在做这个东西,参数的总可能组合将超过一千个。这就是为什么我们将构建一个查找表来映射数据集中所有现有的状态。
当我们发现一个新的唯一状态时,我们将对当前状态中所有参数的组合进行编码,并将其注册到当前状态及其未来状态的表中。当我们再次发现那个状态是当前状态时,它当时的未来状态将与那个当前状态的其他未来状态一起被附加到那个状态的未来状态的列表中。
当我们想用这个表来预测未来的天气时,首先将我们当前的天气参数的状态编码成一个关键字在我们的表中进行搜索。当我们发现相同的编码状态时,看看它未来状态的列表。挑选最频繁的编码状态并解码就这样。你得到了天气预报基于使用马尔可夫模型的模拟方法。很简单。如果你没有从表中找到我们当前的状态,这意味着我们无法预测这个状态。这就是为什么我们需要最小化可能的状态,需要一个大的数据集来最小化当我们想要预测天气时找到一个新的唯一状态的可能性。
我们将用于构建转移矩阵的数据集是元数据。METAR 是一个字母数字代码,包含某个区域每 1 小时或半小时的天气状况和其他参数。
元数据的例子
为了这个实验,我已经解码了一些从 2012 年 1 月 1 日到 2020 年 5 月 31 日的 JSON 格式的 METAR 数据。你可以在这里下载。这个 JSON 数据包含从这些 METAR 代码中提取的风速和风向、能见度、温度、露点和天气。在这个实验中,我使用 MongoDB 和 pymongo。
第一步,让我们建立转移矩阵或查找表。我们使用 2012 年 1 月 1 日至 2019 年 12 月 31 日的数据来构建该表。这是脚本
在这个实验中,我们将一天分为 4 个时段,即上午时段(当地时间上午 6 点-12 点)、下午时段(当地时间上午 12 点-下午 6 点)、晚上时段(下午 6 点-12 点)和午夜时段(当地时间下午 12 点-第二天早上 6 点)。我们的数据集的时间分辨率是半小时。因此,我们需要汇总每一节中的每一个参数值。对于除天气以外的所有参数,我们对每个部分的参数值进行*均。*均之后,是分组和四舍五入。对于天气,我们选择在该部分的时间段内发生的最重要的天气。
使用 GMT 或 UTC 作为时间指示器的 METAR 数据。我们所在地的当地时间是 GMT+7,所以我们需要调整从数据库获取数据的方式(请看上面代码中的第 77 行)。
之前我说过,我们将在后面讨论舍入和分组参数值。现在,是时候了。对于风速,我们将其分为 5 组:
- < 5 knot wind (encoded it as “<5KT”)
- 5–10 knot wind (encoded it as “5–10KT”)
- 10–15 knot wind (encoded it as “10–15KT”)
- 15–20 knot wind (encoded it as “<15–20KT”)
- 20–25 knot wind (encoded it as “<20–25KT”)
-
25 节风(编码为" > 25KT ")
对于风向,我们将其分组为 8 个方向
- < 45° (encoded as “Northeast”)
- 45–90° (encoded as “East”)
- 90–135° (encoded as “Southeast”)
- 135–180° (encoded as “South”)
- 180–225° (encoded as “Southwest”)
- 225–270° (encoded as “West”)
- 270–315° (encoded as “Northwest”)
- 315–360° (encoded as “North”)
Yeah, recently I realized that my classification of wind direction is not quite right. But it doesn't matter because we just want to group the wind direction so it will not generate too much unique state.
对于能见度,我们将该值四舍五入为第一千个值,并以同样的方式编码,能见度值>为 1000 米。对于 500–100,我们将其视为 500 米(编码为“500”),最后对于所有能见度< 500 米,我们将其视为 0 米(编码为“0”)。特别为能见度,它有 2 个槽状态,即最低能见度和最高能见度。
对于温度,我们将其四舍五入为整数(编码与此相同)。
对于相对湿度(RH) ,有点特殊,因为我们数据库里没有 RH 数据。我们从温度和露点预测它的值。之后,我们在什一税中对值进行舍入(编码与此相同)。
对于天气,我们选择该部分时间段内最重要的天气。天气的重要程度定义如下:
上面的天气代码被编码以使其更短。比如小雨编码为-RA,雨编码为 RA,雷雨编码为 TS。下降越多,天气越重要。天气编码与此天气代码相同。当没有显著的天气时,我们将其编码为“NOSIG”。
在我们对所有参数进行编码后,我们将它们连接起来,并用“|”字符分隔。这就是我们如何对单个状态进行编码。
我们得到查找表后,就该尝试用这个表来预测天气了。我们将使用 2020 年 1 月 1 日至 2020 年 5 月 31 日的数据。这是脚本
这将生成一个 CSV 格式的新文件 result.dat。第一列是当前状态,第二列是下一个状态(真值),第三列是下一个状态的预测。
下面是我从上面的代码生成的 result.dat。
哇,有这么多“未知”的预测。“未知”意味着状态太新,所以我们无法预测它。但是,有些预测结果接*实际状态,不尽相同。看起来我们的表格需要更多的数据。当我在这么多“未知”的情况下得到这个结果时,我得出结论,我需要更多的数据至少 30 年的数据(这是气象学或气候学中看到某个地区天气正常模式的标准)。
这是模拟方法的应用,使用马尔可夫模型预测天气。下一次,也许我会尝试使用稳定指数数据,或者低层和高层大气的温度和相对湿度,这是一个非常决定性的参数,经常被预报员用来预测天气。
更新
你可以在这里访问完整代码。
参考资料:
https://en.wikipedia.org/wiki/Markov_model号于 2020 年 6 月 3 日进入
http://aviation.bmkg.go.id/web/于 2020 年 6 月 6 日进入
http://ww 2010 . Atmos . uiuc . edu/(Gh)/guides/mtr/fcst/mth/oth . rxml2020 年 6 月 6 日访问
机器学习操作基础设施的观点
笔记本之后的现实:如何开发一个健壮的框架来确保对机器学习操作的控制
生成一个工作的(产生价值的)机器学习模型不是一件容易的事情。它通常涉及先进的建模技术和技能稀缺的团队。然而,这只是更复杂任务的第一步:将模型部署到产品中并防止其退化。
即使通过云转移得到缓解,至少三分之二的 IT 支出仍然集中在维护模式任务上。关于 ML 相关项目的这种划分是否成立的研究仍然很少,但我认为这一比例甚至会显著增加,因为 ML 工作负载有更多的“流动”输入和更少的控制杠杆,如下所示:
图 1—ML 工作负载维护中可变性和控制的影响
本质上,维护主要是由我们对系统中不同组件的可变性和控制水*驱动的。如图所示,有理由得出这样的结论:机器学习工作负载更倾向于维护任务。更糟糕的是,数据和代码(业务角色)的演进路径不一定需要一致。这在机器学习系统中隐藏的技术债务中有很深入的解释
有理由得出结论,机器学习工作负载更倾向于维护任务
因此,绝对有必要开发一个健壮的框架,以确保一旦我们的模型被部署到生产中,就能控制机器学习操作,同时确保模型的质量及其发展不受损害。
开发模型的科学(艺术)是一个被充分研究的领域,甚至有模型开发的行业参考框架,如 CRISP-D M,特定的 EdA 方法,所以在本文的其余部分,我们将假设我们已经有了一个具有可接受性能的经过训练的模型。
大规模运行机器学习,我们需要什么基础设施?
简而言之,我们需要设计三个大*台,当然除了构建初始模型、运行实验等的开发*台,还有另一个跨功能*台,如代码库、容器注册表、调度程序或监控系统。下图描述了这些*台:
图 2 — 基础 ML *台组件
特色店内
本质上,特征库将特征工程过程与其使用分离。这对于输入数据受制于复杂的特征转换逻辑或一个特征被多个模型使用的情况尤其有用,在这些情况下,特征存储是一个很好的工程组件,因为它隐藏了复杂性并提高了可重用性。但是,在某些情况下,我们可以跳过此组件,例如,用于训练模型的数据处于其自然状态,或者模型本身包含特征生成器(例如,卷积、双向或嵌入层)。
图 3 — 功能商店内的组件
特征库由许多元素组成:
- 摄取:该组件负责将原始数据加载到特性存储存储中。应该支持批处理和在线摄取路径。
- 特征转换:该组件负责实际计算特征,同样应支持批处理和在线处理。设计该组件时,计算时间性能至关重要。
- 特征服务层:实际为下游处理提供特征的组件。同样,可以在线或批量检索特征。
训练*台内
训练装备的目标是找到并产生最佳模型(在特定时间点),给定:(I)初始模型架构,(ii)一组可调超参数,以及(iii)历史标记特征集。
下图突出了我认为应该存在的主要组件,以确保顺利和有效的培训操作。
图 4 — 训练设备内部的组件
训练*台的输出是我所谓的“黄金模型”,换句话说,就是将在推理*台中部署的架构、权重和签名。为了产生这些资产,几个组件必须介入。
- 重新训练检查器:该组件任务是检测何时需要重新训练当前黄金模型,有许多情况下必须引发重新训练事件。我建议部署一些评估人员来检查再培训条件。一些例子可以是特征的改变(添加或删除)、训练集中的统计差异(数据漂移)、或者训练数据和服务数据之间的差异(偏斜)、或者只是准确性度量的下降。生成的模型应该被传递给 promoter 组件,该组件将拥有将它部署到生产环境以及如何部署的最终决定权。
- 黄金模型循环:这可能是最关键的一步,它实际上执行了训练。因此,在设计系统时,应考虑性能因素(例如,分布式基础设施和对硬件 asics 的访问)。另一个职责是生成模型签名,明确定义输入和输出接口以及任何初始化任务(如变量加载器)。
- 下一个黄金模型循环:该组件旨在通过不断优化(或试图优化)当前黄金模型来发现潜在的新模型。有两个子循环,一个用于优化超参数(例如学习率、优化器..)和另一个用于启动对新模型架构(例如层数)的搜索。虽然有两个独立的循环,但是新的模型架构候选可以在超参数循环上进一步细化。该组件可能是资源密集型的,特别是如果搜索空间很大并且优化算法(例如网格搜索、hyperband)是贪婪的。从工程角度来看,应该考虑可恢复操作的检查点和作业优先级机制等技术。在采取任何额外措施之前,应进一步评估该组件的输出。
- 模型发起人:该组件负责发布准备投入生产工作的模型,因此这一步需要进行大量的测试。在任何情况下,正如我们将在推理装备中检查的,没有新的模型将被公开部署到他们所有的潜在用户群。
- 元数据存储:这个组件集中了所有与训练阶段相关的元数据(模型库,参数,实验..)
预测装置内部
预测*台的主要目标是执行推理。下图展示了实现这一目标的一组组件。
图 5 — 预测试验台内部的组件
推理阶段有几个组件:
- 特性转换器:即使已经有了一个特性存储库来将特性从数据生产系统中分离出来,我认为特性转换器仍然可以在推理时将低级的特定操作应用到潜在的可重用和更抽象的特性中。对于在线系统,延迟要求至关重要。
- 调度程序:调度程序的目标是将请求路由到特定的预测端点。我相信每一个请求都应该经过试验,这就是为什么调度员应该能够将呼叫重定向到一个特定的或许多现场试验,黄金模型或两者。每一个未经实验的请求都是一个改进机会的丧失。
- 预测主干:预测装备的马力取决于该组件,因此从工程的角度来看,针对传统的非功能性需求(如性能、可伸缩性或容错)进行设计至关重要。
- 缓存层:低延迟键值存储,快速响应重入查询。它必须实现经典的缓存机制(失效、基于特征散列的密钥计算、LRU 队列..)
- 黄金推广者/去推广者:随着 A/B 测试的进行,我们可能会达到这样一个点,其中一个真实实验实际上比当前的黄金模型更具性能,该组件任务是分析元数据,特别是特征存储中的基础事实数据,以建议用一个实验替换黄金模型。
- 型号预热器:当冷启动情况发生时,确保缓存和内存预热的组件(例如,新型号升级)
- 解释器:实现模型可解释性逻辑的组件(如锚点、CEM..)并为给定的请求返回它
- 元数据存储:该组件集中了与预测阶段相关的所有元数据(实时实验性能、预测数据统计…)
*台支持的一些用户旅程
这种架构可以表达几个旅程,我的目标不是提及所有旅程,但我想强调几个有趣的旅程:
在特征生成时
- 合成一个复杂的要素并实时提供
- 编写一个踢 LRO 的复杂特征,并在许多模型中一致使用
- 在不影响转换和服务逻辑的情况下更改/更新特征信息生产者
训练时
- 启动重新训练(分布式)作业,由训练集中包含的新功能触发
- 基于数据(要素)依赖性的模型评估器
- 为当前的 DNN 模型发现一种新的、更高性能的架构
- 优化已部署模型的学习速度
在预测时间
- 逐步推广新的黄金模式,将其覆盖范围扩大到所有人群
- 查询预测及其黑盒解释
可管理性
- 检查模型、特征、签名版本
可用于部署的技术
我们可以使用大量开源软件来构建一个包含上述所有组件的*台,但在考虑独立设计每个组件之前,我们可以用一种标准和统一的方式来解决非功能性需求,如可扩展性、安全性或可移植性,这不是很好吗?
幸运的是,我们可以依赖 kubernetes 作为部署组件的主要*台。下图显示了一份提案,其中包含开源产品/项目*的组件映射。
图 6 — ML *台开源实例化
*FEAST 和 kubeflow 集成目前正在进行中
为了让事情变得更简单, kubeflow 已经以一种很好的方式打包了所有的组件,所以大部分的集成已经完成。
结论
甚至有人会认为,运行机器学习操作与传统操作有根本的不同,大多数软件工程原则实际上都成立,它们只是在不同的上下文中应用。在本文中,我们展示了一个逻辑高级架构,可以使用开源组件(如 kubeflow)轻松部署。
我在这里发布了一些关于这个主题的组件和示例笔记本。
柏林 Airbnb 托管的可视化数据驱动研究
哪些社区最物有所值?有多少主机将 Airbnb 作为主要收入来源?我用数据通过可视化和预测技术来回答这些问题。
由凯瑟琳·埃德格雷拍摄的照片
在最好的情况下,Airbnb 可以以合理的价格成为体验一座城市的绝佳方式。然而,正如经常出现的好事过多的情况一样,Airbnb 也可能对某些城市产生不利影响。为了应对因 Airbnb 的成功而导致的租金价格上涨,柏林市在 2018 年颁布了一项新法律,要求某些短期出租整个物业的主机必须获得许可。
利用 Airbnb 目前关于柏林房源和评论的数据——从 Airbnb 内部的获得——我决定自己更仔细地观察柏林的 Airbnb 景观。我想从商业的角度而不是客人的角度来调查,在新法律生效后,柏林实际上在经营什么样的房产和房东。此外,我自己在柏林断断续续住了 7 年,我也想看看使用 Airbnb 数据作为位置推荐工具的潜力,并看看结果如何与我自己的经验相吻合。关于这座城市最好、最便宜或最受欢迎的住宿地点,这些数据能告诉我们什么?
我决定专门关注这三个问题:
- 柏林有多少比例的 Airbnb 主机可能将主机服务作为主要收入来源(或者是业务)?
- 柏林各个社区的 Airbnb 价格有什么不同,哪些社区最划算?
- 我们能否预测一个列表的位置评级,以及哪些社区对这些评级有最大的影响?
由于这些问题不一定激发单一的、明确的答案,除了应用分类技术寻找答案之外,我决定选择使用 Plotly 和 follow 地图的交互式可视化。
柏林有多少比例的 Airbnb 主机可能将主机服务作为主要收入来源?
以我的经验来看,Airbnb 不仅用于柏林的短期旅游租赁,也用于长期合租,供租户搬走一段时间。有些房东只是在夏天有一个免费房间的人,而其他人已经决定购买多套公寓,以从托管中获得稳定的收入。我想知道这个崩溃到底是什么样子的。
我首先检查了柏林目前有共同主机的列表。特别是,我查看了有多少列表是来自各自主机的唯一的列表,以及来自同一主机的许多列表中的一个。
左侧显示的饼图显示了使用 Airbnb 只是为了出租房间或公寓的房东与使用 Airbnb 作为商业工具(即出租许多房间或公寓)的房东的房源百分比。我们看到超过 10% 的广告房源拥有至少 4 个房源的主机。
然而,当我们从主机总数的角度来看同样的细分时,如下图所示,拥有 3 个以上列表的主机的实际百分比仅为 1.63% 。柏林 Airbnb 上的大多数房东似乎只是把 Airbnb 作为出租自己房间或公寓的一种方式。
然而,1.63%的主机所拥有的大量列表(*均 7.5 个列表)反映在 10%的列表属于那一小部分主机的事实中。
这就引出了一个问题——我们如何区分那些只是偶尔出租房屋的房东和那些出租房屋做生意的房东?为了对选择什么样的阈值有一个概念,我们看一个主机的列表在一年中可用的*均天数,按主机有多少个列表细分。
从上图中可以看出,可用性的最大提升发生在拥有 3 个清单的主机和拥有 4 个清单的主机之间。对于只有一个房源的房东来说,一年中*均只有 49 天的空房率意味着这些房子很可能不是作为主要收入来源出租的。相比之下,那些拥有 4 个或更多房源的房东一年的*均可用时间超过 178 天(超过半年),这意味着所有者不可能在一年的大部分时间里住在这些房产中,而是可能将 Airbnb 作为主要收入来源的商业工具。
无法准确确定主机必须将其归入业务类别的列表数量的确切阈值,但从上述结果中,我们可以得出结论,拥有 4 个或更多列表的主机可能会将 Airbnb 作为主要收入来源或至少是副业。我们还可以得出这样的结论:柏林的绝大多数 ( > 90%)的主机都在把 Airbnb 作为一个产生第二收入来源的工具,这符合 2018 年制定的规定。
柏林各个社区的 Airbnb 价格有什么不同,哪些社区最划算?
使用叶子创建
上面的地图显示了柏林每个街区的 Airbnb 房源的*均价格(未填写的部分没有足够的数据)。显然,柏林市中心的*均价格略高,尤其是政府区 (Regierungsviertel) 以及亚历山大广场。
我们可能还想直接比较较大区域的社区价格。为了做到这一点,我们接下来看看每个地区的价格分布。
注意:只包括至少有一个评论的列表
上面的箱线图显示了柏林每个区的标价的中值、四分位数范围(值的第 25 至 75 个百分点)和异常值(以单个点的形式)。很明显,所有地区都倾向于 30 到 100 之间的较低值。似乎 T2 的 Mitte 和 T4 的 Friedrichshain-Kreuzberg 都拥有最昂贵的房产。米特也是住宿成本最高的地区,*均价格为每晚 83 美元,而赖尼克肯多夫是最便宜的,*均价格为每晚 46 美元。
那么,住在哪里呢?嗯,我们不仅要考虑价格。Airbnb 的评级系统对各种因素进行细分。除了对酒店的总体评级,数据集还包含对以下方面的评级:位置、清洁度、准确性、沟通、价值和入住。为了更好地了解城市不同地区的性价比,我们还想加入位置评分。下图在 y 轴上显示了每个地区的*均价格,而该地区的*均位置评级则由条形的颜色表示。
从图表中,我们或多或少可以看出哪些地区在价格和价值方面是最优的。考虑到价格和价值,Friedrichshain-Kreuzberg、Charlottenburg-Wilmersdorf 和 Tempelhof-schneberg 是最理想的地方,因为它们的价格相对较低,但位置评级极高。
这些都是相当大的区域。我们可能还想更深入地了解哪些特定社区特别适合(或不适合)居住。为了做到这一点,我还将尝试预测位置评级,以了解各种社区/较小的地区和其他因素对评级的影响。
我们能否预测一个列表的位置评级,以及哪些社区对这些评级有最大的影响?
为了预测柏林的上市地点评级,我首先查看了这些评级是如何分布的。我发现收视率主要偏向高收视率,如下图所示。
结果显示,大约 70%的被评级房产的地理位置被评为 10/10,另外 30%的被评为低于 10。由于这些评级的性质,我选择简单地预测一处房产位置的评级是等于 10 还是小于 10。
通过建立一个旨在确定一个物业的位置是否值得 10/10 评级的分类器,我能够看到哪些基于位置的变量在这个预测中最有用。为了量化一个变量在预测位置评级中的重要性,我们看看模型中使用的系数,或效应大小。
注意:效果大小单位是标准化的,与原始单位无关
从上面的图中,我们可以看到,某些街区或区对位置评级有着显著的影响。特别是,我们可以做出一些有用的推论:
- 位于 Prenzlauerberg Südwest(西南)或 Helmholtzplatz 的列表会导致明显更高的位置评级。相比之下,Osloer Straß、Parkviertel 和 central Wedding 的房源位置评分要低得多,这表明它可能真的不是最好的住宿地点。
- *房和别墅的列表与更好的评级相关联,这可能与它们位于城市中特别好的地段这一事实有关。
- 从物业位置到最*的地铁站或火车站的距离与位置评级呈负相关,这意味着交通不便的房源在位置方面不太理想(如我们所料)。
外卖食品
在这篇文章中,我们利用现有的数据来了解柏林什么样的人在使用 Airbnb(企业与个人,自住物业与出租物业)。我们还研究了柏林的个别地区和较小的社区,比较了每个地区的房源价格,以及某些社区对预测房源位置评级的影响。
特别是,我们发现:
- 拥有 4 或更多房源的房东可能会将 Airbnb 托管视为一项业务,因为这些房源在一年的大半时间里都是可用的。拥有 4 个或更多列表的主机仅占数据中主机的 1.63%,但它们的列表占总列表的 10%以上。似乎有一些企业或主机使用 Airbnb 作为商业工具,但大多数只是在一年内短期出租他们的公寓/房间。
- 不出所料,最昂贵的房产位于更中心的位置,Mitte 提供最高的*均挂牌价格。Reinickendorf 和 Lichtenberg 是住宿最便宜的地区,中间价格都是每晚 40 美元,但就其地理位置而言,这两个地区的排名并不高。
- 数据集中许多基于位置的变量确实对一个列表的位置评级有显著影响。Prenzlauerberg Südwest 和 Helmholtzplatz 似乎是特别好的住宿地点(根据我自己的经验,我同意这一点),因为它们会导致良好的位置评级。相反,Osloer Straß和 central Wedding 可能不是最好的入住地点。
在这篇文章中,我们回顾了从柏林 Airbnb 数据中提取的一些有用的见解,这些见解使我们能够更好地了解托管人口统计以及该市各区和社区之间的差异。地理洞察可以用来提供关于在哪里住宿或购买物业用于租赁的建议,而主机分析可以证明有助于更深入地了解 Airbnb 的实际使用情况。
如果你想阅读更多关于我的分析或这篇文章的代码,可以点击这里的链接。
梯度下降法的直观解释(Momentum,AdaGrad,RMSProp,Adam)
表面上 5 种梯度下降方法的动画:梯度下降(青色),动量(洋红色),AdaGrad(白色),RMSProp(绿色),Adam(蓝色)。左井是全局最小值;右井是局部最小值。
有无数的资源解释梯度下降,在这篇文章中,我想直观地向你展示这些方法是如何工作的。借助我建立的梯度下降可视化工具,希望我可以给你一些独特的见解,或者至少,许多 gif。
我假设基本熟悉梯度下降为什么以及如何用于机器学习(如果没有,我推荐这个由 3Blue1Brown 制作的视频)。我在这里的重点是比较和对比这些方法。如果你已经熟悉所有的方法,你可以滚动到底部观看几个有趣的“赛马”。
香草渐变下降
让我们快速复习一下。在机器学习的背景下,梯度下降的目标通常是最小化机器学习问题的损失函数。一个好的算法能够快速可靠地找到最小值(也就是说,它不会陷入局部最小值、鞍点或*坦区域,而是去寻找全局最小值)。
基本的梯度下降算法遵循梯度的相反方向指向较低区域的思想。所以它迭代地在梯度的相反方向上采取步骤。对于每个参数θ,它执行以下操作:
增量= -学习率梯度*
θ+=δ
Theta 是您想要优化的某个参数(例如,神经网络中神经元到神经元连接的权重,线性回归中某个特征的系数等)。在一个 ML 优化设置中可能有数千个这样的θ。 Delta 是算法中每次迭代后θ的变化量;希望随着每一次这样的改变,θ逐渐接*最佳值。
梯度下降算法的分步说明。
由于人类的感知仅限于三维,在我所有的可视化中,想象我们只有两个参数(或θs)要优化,它们由图中的 x 和 y 维表示。表面是损失函数。我们想找到曲面最低点的(x,y)组合。这个问题对我们来说微不足道,因为我们可以看到整个表面。但是球(下降算法)没有;它一次只能走一步,探索周围的环境,类似于在黑暗中只带着手电筒行走。
普通梯度下降是普通的,因为它只是在梯度上操作。下面的方法对渐变做了一些额外的处理,这样会更快更好。
动力
decay_rate = 1.0 时的动量下降(无衰减)。
动量梯度下降算法(或简称动量算法)借用了物理学的思想。想象在一个无摩擦的碗中滚下一个球。而不是停在底部,它积累的动量推动它前进,球不停地来回滚动。
我们可以将动量的概念应用到我们的普通梯度下降算法中。在每一步中,除了常规渐变之外,它还增加了前一步的运动。在数学上,它通常表示为:
delta =-learning _ rate * gradient+previous _ delta * decay _ rate(eq。1)
θ+=δ(等式。2)
我发现,如果我稍微修改一下这个等式,并跟踪梯度的(衰减)累积和,会更直观。这也将使我们稍后介绍 Adam 算法时事情变得更容易。
梯度总和=梯度+先前梯度总和衰减率*(等式。3)
delta =-学习率梯度总和*(等式。4)
θ+=δ(等式。5)
(我所做的是分解出-learning_rate。要看到数学上的等价性,你可以在 eq 中用-learning_rate * sum_of_gradient 代替 delta。1 获取情商。3.)
动量下降的逐步说明。在 app 中观看现场动画。在这篇文章的其余部分,我在可视化中草率地使用了渐变 x 和渐变 y;现实中因为是 gradient * descent,所以实际上是梯度的负数。*
让我们考虑两个极端情况,以便更好地理解这个衰减率参数。如果衰减率为 0,那么它与(香草)梯度下降完全相同。如果衰减率是 1(并且假设学习率合理地小),那么它就像我们在开始提到的无摩擦碗类比一样无休止地来回摇摆;你不会想那样的。通常,衰减率选择在 0.8-0.9 左右,这就像一个表面有一点摩擦,所以它最终会减速并停止。
具有全局最小值(左井)和局部最小值(右井)的表面上的动量(洋红色)与梯度下降(青色)
那么,动量法在哪些方面优于香草梯度下降法?在左侧的对比中,您可以看到两个优势:
- 动量只是移动得更快(因为它积累了所有的动量)
- 动量有机会逃离局部最小值(因为动量可能会将其推出局部最小值)。同样,正如我们将在后面看到的,它也能更好地通过高原地区。
阿达格拉德
不是像动量一样跟踪梯度的总和,而是 Ada 感受性 Grad ient 算法,或简称为 AdaGrad,跟踪梯度*方的总和,并使用它来适应不同方向的梯度。这些方程通常用张量表示。为了简化这里的语言,我将避免使用张量。对于每个维度:
sum _ of _ gradient _ squared = previous _ sum _ of _ gradient _ squared+梯度
δ=-learning _ rate * gradient/sqrt(sum _ of _ gradient _ squared)
θ+=δ
阿达格拉德血统的一步一步的插图。在 app 中观看现场动画。
在 ML 优化中,有些特征非常稀疏。稀疏特征的*均梯度通常很小,因此这些特征的训练速度要慢得多。解决这个问题的一个方法是为每个特征设置不同的学习速率,但是这很快就会变得混乱。
AdaGrad 使用这种思想来解决这个问题:您已经更新的特性越多,将来更新的就越少,这样就给了其他特性(例如稀疏特性)赶上来的机会。用视觉上的话来说,你更新了这个特征多少,就是说你在这个维度上移动了多少,这个概念是用梯度*方的累积和来捕捉的。请注意,在上面的逐步网格图中,如果没有重缩放调整(1b),球将主要垂直向下移动;通过调节(1d),它会沿对角线移动。
有鞍点地形上的阿达格拉德(白色)与梯度下降(青色)。AdaGrad 的学习率被设置为高于梯度下降的学习率,但是不管学习率如何,AdaGrad 的路径更直这一点在很大程度上保持不变。
这个特性允许 AdaGrad(以及其他类似的基于梯度*方的方法,如 RMSProp 和 Adam)更好地避开鞍点。阿达格拉德将走一条直路,而梯度下降(或相关的,动量)采取的方法是“让我先滑下陡坡,然后也许再担心更慢的方向”。有时,普通梯度下降可能会在两个方向的梯度都为 0 的鞍点处停止,并在那里完全满足。
RMSProp
然而,AdaGrad 的问题是它慢得令人难以置信。这是因为的梯度*方和只会增长而不会收缩。RMSProp(用于RootMeanSquarePropagation)通过添加一个衰减因子来解决这个问题。
sum _ of _ gradient _ squared = previous _ sum _ of _ gradient _ squared**** decay _ rate****+渐变**(1-decay _ rate)
delta =-learning _ rate * gradient/sqrt(sum _ of _ gradient _ squared)
θ+=δ
更准确地说,梯度*方的和实际上是衰减的梯度*方的和。衰变率表明只有最*的梯度才重要,而很久以前的梯度基本上被遗忘了。顺便提一下,“衰变率”这个术语有点用词不当。与我们在动量中看到的衰变率不同,除了衰变,这里的衰变率还有一个标度效应:它将整项按(1 - decay_rate)的因子按比例缩小。换句话说,如果 decay_rate 设置为 0.99,除了衰减之外,梯度*方之和将是 sqrt(1 - 0.99) = 0.1,即 AdaGrad 的 sqrt(1-0.99)= 0.1,因此对于相同的学习速率,步长大约大 10 倍。
RMSProp(绿色)vs AdaGrad(白色)。第一次运行只显示球;第二次运行还显示了由正方形表示的梯度*方和。
为了查看衰减的效果,在这个头对头的比较中,AdaGrad white)最初跟上 RMSProp (green),正如预期的那样,调整了学习率和衰减率。但是阿达格拉德的梯度*方和积累得如此之快,以至于它们很快就变得巨大无比(动画中方块的大小证明了这一点)。他们付出了沉重的代价,最终阿达格拉德几乎停止移动。另一方面,由于衰减率,RMSProp 一直将方块保持在可管理的大小之下。这使得 RMSProp 比 AdaGrad 更快。
圣经》和《古兰经》传统中)亚当(人类第一人的名字
最后但同样重要的是,Adam(Adam 的缩写)充分利用了动量和 RMSProp 的优点。根据经验,Adam 工作得很好,因此*年来,它通常是深度学习问题的首选。
让我们来看看它是如何工作的:
*sum _ of _ gradient = previous _ sum _ of _ gradient * beta 1+gradient (1-beta 1)【动量】
*sum _ of _ gradient _ squared = previous _ sum _ of _ gradient _ squared * beta 2+gradient (1-beta 2)【rms prop】
delta =-学习率梯度总和/ sqrt(梯度*方总和)*
θ+=δ
β1 是一阶矩的衰减率,梯度和(也称为动量),通常设置为 0.9。β2 是二阶矩的衰减率,梯度*方和,通常设置为 0.999。
亚当后裔的一步一步的插图。在 app 中观看现场动画。
Adam 从动量获得速度,从 RMSProp 获得适应不同方向梯度的能力。两者的结合使其功能强大。
结束语
现在我们已经讨论了所有的方法,我们来看几个我们到目前为止讨论过的所有下降方法的比赛!(不可避免地会对参数进行挑选。尝到甜头的最好方法就是自己在身边玩。)
在这个地形中,有两座小山挡住了通往全局最小值的路。亚当是唯一一个能够找到全局最小值的人。无论以哪种方式调整参数,至少从这个起始位置开始,其他方法都无法达到这个位置。这意味着单独的动量或自适应梯度都不能做到这一点。这实际上是两者的结合:首先,动量使亚当超越了所有其他球停止的局部最小值;然后,梯度*方和的调整将它拉向侧面,因为这是探索较少的方向,导致它的最终胜利。
这是另一场比赛。在这种地形中,全局最小值周围有一个*坦区域(高原)。通过一些参数调整,Momentum 和 Adam(由于其动量分量)可以到达中心,而其他方法则不能。
综上所述,梯度下降是一类旨在通过遵循梯度来寻找函数上的极小点的算法。普通梯度下降只是跟随梯度(按学习率缩放)。改进梯度下降的两个常用工具是梯度之和(一阶矩)和梯度*方之和(二阶矩)。动量法使用具有衰减率的一阶矩来获得速度。AdaGrad 使用无衰减的二阶矩来处理稀疏特征。RMSProp 使用具有衰减率的二阶矩从 AdaGrad 加速。Adam 同时使用一阶矩和二阶矩,通常是最佳选择。还有其他一些梯度下降算法,如内斯特罗夫加速梯度,阿达德尔塔等。,不在本文讨论范围之内。
最后,我将留给你们这个没有衰减的动量下降。它的路径组成了一个有趣的图案。我看不出它有什么实际用途,但在这里提出来只是为了好玩。【编辑:关于没有实际用途我收回我的话。在 https://en.wikipedia.org/wiki/Lissajous_curve 阅读更多关于这条曲线的信息。]
玩玩这个可视化工具,它被用来生成这篇文章中所有的可视化,看看你会发现什么!
参考文献及相关链接:
[1]http://www . cs . Toronto . edu/~ tij men/CSC 321/slides/lecture _ slides _ le C6 . pdf
https://ruder.io/optimizing-gradient-descent
[3]https://bl . ocks . org/EmilienDupont/AAF 429 be 5705 b 219 aaaf 8d 691 e 27 ca 87
多臂强盗实验的可视化探索
或者—“鱼与熊掌,不可兼得”
在营销数据科学部门工作有一个不变的事实:在实验和开发之间做出选择从来都不容易。当你想推出限时优惠时,尤其如此,因为你事先对不同版本的优惠效果知之甚少。
如果有时间,您可以运行一个多变量测试(A/B/C/…测试)来确定哪一个是最好的版本,但是到那时,从该知识中获益可能已经太晚了。
一个多臂土匪(原谅我改编自这里
有没有一种方法,我们可以创建一个报价的多个版本,但随着报价的运行,更倾向于表现最好的版本,向越来越少的人显示表现较差的版本?是啊!
进入多臂土匪(见上图)。Multi-Armed Bandit 方法的美妙之处在于,无论您有多长时间来运行测试,您都可以确保您正在做出长期的最佳决策,同时尽可能快地将表现不佳的变体的影响最小化。
我 magine 我们想运行一个在线报价,我们的报价有 5 种变化,如下所示。每一个都有一个内在转换率——看到优惠后继续购买的客户比例——但实际上我们不会提前知道这些转换率(如果我们知道,我们只会直接运行表现最好的一个!).
我们认为我们的广告有 5 种变体,每一种都有内在的,但未知的转换率。
这里设置的传统 A/B(/C/D/E)测试会在实验期间将我们网站的访问者随机分配到其中一个变量中。我们可以像这样想象这些随机分配,其中每个破折号是分配给该变量的访问者。我们可以看到,在整个测试过程中,它们都是随机分配的。
每个访问者被随机分配到一个变体
随着每个变量中访问者数量的增加,我们可以更好地了解该变量的潜在转换率(因为样本量的增加降低了总体均值估计的标准误差)。我们将在下面看到这个。
让我们暂时关注一个单一的变体。每个访问该网站的人都可以选择购买或不购买。访问的人越多,我们的样本量就越大,我们对该变量的转化率的估计就越好,这使得最终的概率密度函数在我们的估计值周围变得更窄。
随着我们对人口取样越多,我们对人口转换率的估计就越准确。
上图中,我们使用 beta 分布来估计购买和不购买的人口转换。
B 对多臂土匪的 ack。随着我们继续向访问者提供我们的服务变体,我们开始得到哪个变体表现更好的估计。我们可以用这个估计来调整我们的游客变量分配。有很多方法可以做到这一点,下面我将探讨两种。我们想要得到一个在概念上与此类似的分配:
多臂土匪和多变量测试之间分配差异的简化示例。
请注意,在多臂强盗的设置中,大部分的游客被分配到了表现最好的红色变种。这正是我们的目标。
ε-贪婪
贪婪分配背后的想法是,最好的变体应该得到所有的访问者。等一下,如果我们开始给所有的访问者分配一个变体,我们就不再得到关于其他变体的任何信息,如果我们过早地开始给每个人分配一个次优变体会怎么样?
这就是ε(ε)的由来。一小部分时间,ε,我们仍然随机分配访客,只是为了检查我们没有出错。大多数情况下,1-ε,我们将访问者分配到当前表现最好的变体。
在每个新访客之后,计算每个变体的当前估计转化率,如果找到更好的变体,将开始分配大多数访客,直到找到一个新的最佳变体。
回到我们的 5 个变量,我们可以绘制我们的分配(如我们之前所做的),以及我们的累积分配(占总数的百分比)。下面我们看到,在我们的贪婪分配发现红色变体是最好的之前,需要大约 50 个访问者,但是在提供结束时,大约 80%的访问者已经被分配到那个变体。这将给我们带来大约 28%的总转换率,而不是我们在整个过程中随机分配所能达到的 16%(这些是作为不同转换率的加权*均值计算的)。这将比我们的报价增加+75%的销售额!
ε-贪婪地将访问者分配给变体(ε = 5%)。分配可能会被“卡住”,就像这里前面所做的那样。
值得注意的是,贪婪分配可能会在一段时间内“卡住”分配给错误的变体,就像这里早期的橙色变体一样,直到ε随机分配为红色变体提供了足够的关于其他变体的信息。我解决这个问题的一个方法是从一个大的ε值开始,这样在开始时有更多的探索,随着时间的推移减少到 5%,以便利用更好的信息。如果你对此感兴趣,我在下面链接了我的分析。
与上面类似,当我们继续分配访问者时,我们可以通过绘制每个分配的转换率的估计来可视化分配的进展。每一个概率分布(在左边)只有在另一个访问者加入到那个变量中时才会得到改善。提醒各位访客:
- 95%的时间它们将被分配给具有当前最高样本均值(或“当前最佳猜测”)的变量。
- 5%的时间它们会被随机分配给一个变量。
前 500 个访问者的分配,以及我们对每个变体的转换率的估计随时间的分布。(每个变体有两个条形,实线表示购买的访问者,阴影表示不购买的访问者。)
需要注意的是,当使用ε-greedy 进行分配时,我们只关心样本均值,而不关心分布。我们很快会看到一个替代方案,它也明确地使用了分布范围。
鉴于贪婪地分配也有不好的一面,我们有没有办法完全避免它?而不是根据分配我们对转换率的估计和我们对每个估计的置信水*?是啊!其中一种方法,汤普森取样,是接下来要做的。
汤普森取样
利用前面的图来帮助解释,我们能不能想出一种抽样方法,既考虑到每个变量的概率分布的*均值又考虑到我们在其中的不确定性?
一种这样的方法被称为汤普森采样。它的工作原理是根据我们迄今为止对它们的了解来计算每个变量的β分布(这正是上面左图所示的内容),但不是取每个分布的*均值来决定下一个分配(如在ε-greedy 中),我们从每个分布中随机抽取来这样做。
这样,如果我们有很少的访问者被分配到某个变体,那么 beta 分布将会很宽,有机会从该分布中随机抽取一个高值,将会有更多的访问者被分配到该变体,随着时间的推移,我们将会增加我们的信心(并使 beta 分布变得更窄)。
类似地,如果我们有许多访问者被分配到某个变体,那么 beta 分布将会很窄,我们有信心从这个变体中得到高或低的转化率,我们知道是否过多或过少地分配访问者到这个分布中。
这样,我们完全避免了对贪婪算法的需求,贪婪算法可能会陷入次优变量!
和以前一样,我将展示汤普森采样的多臂土匪方法的分配和分布。
使用 Thompson 抽样,根据我们有信心的位置以及*均值最高的位置进行分配。
与ε-贪婪分配不同,我们对红色变体优于其他变体有更大的信心。
有趣的是,在这个模拟中,ε-greedy 在分配给正确变量的访问者数量方面优于 Thompson 采样(85%比 72%),但是我们应该记住两个因素:
- 在更长的时间范围内,Thompson 采样往往会表现得更好,因为它不会继续在较差的变量上“浪费”5%(或ε)。
- Thompson 采样将在多个实验中获得更一致的结果,因为它不会“卡住”分配给次优变量。
直观显示第二点的一种方法是绘制有效转换率(我们在上面介绍的变量之间的加权*均转换率)与最佳情况下的转换率(表现最佳的变量的转换率)的比值随时间的变化图。如果我们只是把每个人都分配到红色变量,那么这个值就是 1,对于随机分配,这个值就是 0.53(在这个特定的例子中)。
我们现在为 Thompson 和ε-greedy 的许多模拟绘制这个图。
5 个变量的ε贪婪和 Thompson 采样分配各 100 次模拟
我们可以看到,通过这组变量,ε-greedy 在大多数情况下确实比 Thompson 更快地趋向于高有效转换率,但有时会陷入较低的有效转换率。另一方面,Thompson 采样分配具有更加一致的结果(所有模拟线遵循相似的路径)。如果变量具有彼此更接*的内在转换率,则ε-greedy 可能会在更高的时间比例上停留在次优变量上,而 Thompson 采样不会与此相冲突。
上面的图表与一个叫做后悔的概念密切相关。这是你因为没有从一开始就把所有访客分配到最佳版本而遭受的损失,也是你的产出指标的单位(例如,“我失去了 50 个销售,因为我没有从一开始就运行红色版本”,我的遗憾将是 50)。上面我选择显示有效转换率,因为当你运行越来越长的测试时,这个值会缩放到 1,而不是像后悔那样继续增加。
在总结中,我们介绍了多支武装匪徒的概念,我们将优先级从探索(如在传统的 A/B 或多变量测试中)转移到开发。我们已经直观地探索了两种可能的单克隆抗体分配方法,ε-greedy 和 Thompson 采样。我们还看到,Thompson Sampling 使用我们对样本均值的最佳估计(对于我们感兴趣的度量)和我们对该估计的信心,来将访问者分配到不同的变量。通过这种方式,我们可以有信心在整个营销活动中获得良好的有效转化率。
与传统的多变量测试相比,缺点是我们失去了表现较差的变量的统计显著性,因为我们故意减少了分配给这些变量的访问者数量,从而减少了测试期间的样本量。
所以,下次你不得不开展一个限时活动,或者一个产品改变,重点是商业结果,而不是统计意义,为什么不考虑一个多臂强盗的方法呢?
[## Paul Stubley -数据和决策科学家-在温哥华寻找下一个机会
我是一名经验丰富的数据科学家,在个人工作和管理团队方面都有卓有成效的工作经历
www.linkedin.com](https://www.linkedin.com/in/paul-stubley)
如果你想联系我,你可以在 LinkedIn 上联系我。如果你想看代码和分析(包括每个发行版背后的派生),可以在GitHub上查看。动画是用 Matplotlib 和 imagemagick 制作的。
决策树的可视化指南
这是一个直观的可视化指南,介绍了用于预测美国各州投票模式的强大 ML 算法。
你有没有想过为什么某些州倾向于投票给共和党,而另一些州倾向于投票给民主党?有没有办法预测一个州在任何一年的投票结果?假设我们想要根据我们观察到的一些变量来预测一个状态是【红色】还是【蓝色】。为此,我们将使用决策树。
红蓝图,2016;图片来自维基百科
决策树是一种分类和回归监督学习模型,用于使用来自几个输入变量(x)的信息来预测目标变量(Y)的值。
作者图片
顾名思义,该模型在视觉上表现为一个倒置的树状结构,随着树的增长,数据集被分成越来越小的子集。每个内部节点或决策节点都包含一个需要回答的关于特定 X 变量的简单“对或错”问题。在此基础上,树分裂成分支——一个分支代表真,另一个分支代表假。每个分支的末端都是另一个问题。这个递归过程继续进行,随着每个决策的做出,树变得越来越深,越来越宽,直到它在做出预测的叶节点处结束。
作者图片
让我们举一个数据集的例子。我们有 Y 变量——一个州是红色还是蓝色,我们有 3 个 X 变量:教育、收入*** 和种族多样性***** 。现在,让我们尝试构建一个决策树来预测一个州的政治倾向,即基于这 3 个变量,它是红色还是蓝色。
作者图片
您可能想知道,当变量本质上是连续的或数字的,而不是简单的布尔值(真或假)时,决策树是如何进行拆分的。答案很简单。在引擎盖下,我们创建了多个变量来表示在不同的阈值下分割连续变量。这些划分通常是在该变量的不同十分位数或四分位数处进行的。在我们的例子中,让我们只使用每个变量的中值作为单个阈值。如果值小于中值,我们将把这些连续变量转换成二进制变量或布尔变量,如果值大于中值,我们将把值设置为假,将值设置为真。这些现在是布尔特征。
作者提供的图片
现在让我们开始创建决策树。为了创建第一个决策节点,我们必须选择一个变量进行分割。决策树使用一个叫做信息增益的标准来挑选合适的变量。信息增益是衡量我们在查看 x 后对 Y 了解多少的指标。例如,如果我们随机预测一个没有其他信息的州的政治倾向,则该州为红色的概率为。然而,如果我们知道关于那个状态的一些其他信息,我们可以更新我们关于那个概率的信念。
作者图片
让我们来看看,当我们在 3 个变量上一个接一个地分割树时,会发生什么。
当我们在教育上分裂时,我们看到真正的分支包含教育水*高于中位数的州,主要是蓝色州和一个红色州。错误的分支,或教育水*低于中间水*的州,大部分是红色州,少数是蓝色州。
作者图片
当我们在种族多样性上分裂时,我们看到真正的分支包含了多样性高于中间值的州,大部分是蓝色的州。假分支,或者多样性低于中间值的州,有几乎相等数量的红州和蓝州。这意味着知道一个州不是多元化的并不意味着有政治倾向。
作者图片
最后,让我们看看当我们在收入上分裂时会发生什么。这里,真正的分支包含收入高于中间值的州,大部分是蓝色州。错误的分支,或者收入低于中间值的州,有几乎相等数量的红州和蓝州。这意味着知道一个州的收入低于中值也不能有意义地表明政治倾向。
作者图片
在比较了要分割的每个可能的变量之后,决策树挑选出导致最纯粹分支的变量。在我们的例子中,教育上的分裂导致最纯的分支,因为真实分支只包含 1 个红色状态,而虚假分支包含的蓝色状态是红色状态的一半。从教育中获得的信息很多。种族多样性分裂将是最糟糕的选择。虽然真分支包含大部分蓝色状态,但假分支基本上是红蓝各半。知道国家缺乏多样性几乎不会给模型增加新的信息。从种族多样性中获得的信息非常少。
作者图片
在对教育进行了第一次拆分之后,我们现在来看看两个结果分支,并再次看看我们可以拆分哪些变量来进一步净化我们的分支。这样继续下去,直到我们到达纯分支或树的最大深度。我们最终的树在下面,它有大约 80%的准确率。考虑到我们只有 3 个变量,这太棒了。
作者图片
你可能会问:“为什么我们不简单地分割每个特征,并使树尽可能长,以得到一个完全符合数据的模型?”
这不是一个坏主意如果你有一个数据集是你正在研究的人群的超级代表。然而,问题是您的模型可能会开始进行如此多的分割,以至于它会学习特定数据集的古怪之处,并且无法拟合附加数据或做出可靠的预测。这是一个如此常见的问题,它有一个名字:过度拟合。过度拟合是当模型容量过大时遇到的问题。因此,一般来说,我们通过限制分裂的数量来减少这些树的容量,即限制树的深度。
作者图片
决策树是目前世界上最常见的模型。它们简单高效的本质,以及它们组合成非常强大的模型的能力,如随机森林和梯度增强树,使它们成为许多开发人员的最爱。敬请期待未来了解这些。
要自己实现这个模型,请查看这个链接并使用左边的播放按钮运行每个单元格!
*各州家庭收入中位数(人口普查数据 )
** %本科或以上学历(2013-2017 年美国社区调查)
-
-
-
- %非白人人口(凯泽家庭基金会基于人口普查局 2008-2018 年美国社区调查)的估计
-
-
随机森林视觉指南
直观的视觉指南和视频解释了强大的组装方法
机器学习中最明显的问题之一是“更多的模型比更少的模型更好吗?”回答这个问题的科学叫做模型组装。模型集成要求如何构建模型的集合,以提高测试准确性,同时降低与存储、训练和从多个模型中获取推理相关的成本。
我们将探索一个流行的应用于决策树的集合方法:随机森林。
为了说明这一点,让我们举一个例子。想象一下,根据野火的大小、位置和日期,我们正试图预测是什么导致了这场野火。
随机森林模型的基本构建模块是决策树,所以如果你想了解它们是如何工作的,我建议看看我在之前的帖子。作为快速复习,决策树通过递归地询问简单的真或假问题来执行分类或回归任务,这些问题将数据分成最纯粹的可能子组。
现在回到随机森林。在这种集成方法中,我们训练一组决策树(因此得名“森林”),然后在不同的树中进行投票。一棵树一票。
在分类的情况下,每棵树吐出一个类别预测,然后拥有最多投票的类别成为随机森林的输出。
在回归的情况下,每棵树的预测的简单*均值成为随机森林的输出。
随机森林背后的关键思想是群体中有智慧。从一大群模型中获得的洞察力可能比单独从任何一个模型中获得的预测更准确。
简单吧?当然,但是为什么这个有用呢?如果我们所有的模型都学习完全相同的东西,并投票给同一个答案会怎么样?这难道不等同于只有一个模型做出预测吗?
是的,但是有一个办法可以解决。
但是首先,我们需要定义一个词来帮助解释:不相关。我们需要我们的决策树彼此不同。我们希望他们不同意分裂是什么和预测是什么。不相关对随机森林很重要。一大群不相关的树在一个系综中一起工作将胜过任何一个组成树。换句话说,森林不会受到个别树木错误的影响。
有几种不同的方法来确保我们的树是不相关的:
第一种方法叫做“自举”。Bootstrapping 是通过采样从我们的训练集中创建更小的数据集。现在,使用普通决策树,我们将整个训练集输入到树中,并允许它生成预测。然而,通过自举,我们允许每棵树随机采样训练数据和替换,产生不同的树。当我们允许替换时,一些观察结果可能会在样本中重复。通常,bootstrap 的样本大小与原始数据集的大小相同,但为了提高计算效率,可以对数据集的子集进行采样。使用自举来创建不相关的模型,然后聚合它们的结果被称为自举聚合,或简称为 bagging 。
在我们的树中引入变化的第二种方法是通过改变每棵树可以分裂的特征。这种方法叫做特征随机性。请记住,使用基本决策树,当需要在一个节点上分割数据时,该树会考虑每一个可能的特征,并选择一个导致最纯粹子群的特征。然而,对于随机森林,我们限制了每棵树可以考虑分割的特征的数量。一些库在分割级别而不是树级别随机化特征。如果我们假设树是决策树桩,这并不重要,这意味着只有 1 个分裂,或者最大深度= 1。在这两种情况下,目标都是限制可能特征的数量,以便去相关各个树。
因为单个树非常简单,并且它们只在训练数据和特征集的子集上被训练,所以训练时间非常短,所以我们可以训练成千上万的树。随机森林广泛应用于学术界和工业界。现在您已经理解了这个概念,您几乎已经准备好实现一个随机森林模型来用于您自己的项目了!请继续关注随机森林编码教程和另一个集合方法的新帖子——梯度增强树!
看看下面的视频,看看你在行动中学到的一切!
标准差的直观解释
对于那些被告知“只要记住公式”或者不知道为什么要关心的人来说,这是一个可视化的指南。
统计学中最核心的概念之一是标准差的概念及其与所有其他统计量(如方差和均值)的关系。入门课程的学生被告知“只需记住公式”,但是,相信我,这不是解释一个概念的最佳方式。在这篇文章中,我将尝试对标准差提供一个直观的解释。
假设你有一个成绩列表,在这种情况下,这将是我们的现实世界的测量。我们希望将这些测量中的信息“压缩”成少数几个量,我们以后可以用它们来比较,比如说,不同年级或不同年份的成绩。由于我们有限的认知能力,我们不想一个一个地检查成绩,找出哪个班级的*均分数更高。你需要总结这些数字。这就是为什么我们有描述性统计。
有两种方法可以总结这些数字:量化它们的相似或不同之处。量化它们之间相似性的方法被正式称为“集中趋势的度量”。这些度量包括*均值、中间值和众数。量化它们之间差异的方法被称为“可变性测量”,包括方差和标准差。标准差应该告诉我们一组数字相对于*均值是如何不同的。
让我们举一个实际的例子。假设您收集了学生成绩的数据(为了简单起见,我们假设这些成绩是总体数据):
2,8,9,3,2,7,1,6
让我们首先在一个简单的散点图中绘制这些数字
现在我们有了散点图中的所有数字,计算变化的第一步是找到这些数字的中心:*均值。
视觉上,我们可以画一条线来表示*均成绩。
现在我们有了一条*均值线,下一步是计算每个点和*均值之间的距离,然后*方这个距离。请记住,我们的目标是计算这些数字相对于*均值的变化。我们可以简单地用数学或视觉来做这件事
正如你在这里看到的,“*方”实际上就是画一个正方形。这里有两点:我们不能只取所有差异的总和。由于一些差异是正的,一些是负的,求和将使负数抵消正数,最终以零结束(这没有任何意义)。为了解决这个问题,我们采用差异的*方(我将在最后解释为什么我们采用差异的*方,而不是其他任何度量,如绝对值)。
现在,我们计算这些*方差的和(或*方和):
通过计算*方和,我们有效地计算了这些等级的总可变性(即差异)。理解可变性与差异的关系是理解许多统计估计和推断测试的关键。67.5 的意思是,如果我们把所有这些方块堆成一个巨型方块,它的面积将等于 67.5 点 2,这里的点是指等级的单位。任何一组测量值的总可变性是一个正方形的面积。
方差
既然我们已经得到了总的可变性或大方块的面积,我们真正想要的是*均可变性。为了求*均值,我们只需用总面积除以*方数。
出于最实际的目的,您希望除以𝑁−1,而不是𝑁,因为您将尝试从样本而不是总体来估计该值。然而,这里我们假设我们有总人口。重点仍然是你想计算这些小方块的均方差。我们刚刚计算的是方差,这是*均可变性,或均方差。
标准偏差
为什么我们不能继续用方差作为分数可变性的指标呢?方差的唯一问题是我们不能将其与原始等级进行比较,因为方差是一个“*方”值,或者换句话说,它是一个面积而不是长度。它的单位是点数 2,这与我们的原始分数单位(点数)不同。那么我们应该怎么做才能摆脱广场呢?取*方根!
最后,我们现在有了标准差:方差的*方根,是 2.91 点
这是标准差的核心思想。这种基本的直觉应该更容易理解为什么在处理 z 分数、正态分布、标准误差和方差分析时使用标准差的单位是有意义的。此外,如果您只是用标准偏差公式中的拟合(预测)线 Y 替换*均值,那么您将处理基本的回归项,如、均方误差(如果您没有使用*方根)、、均方误差(使用*方根,但现在是相对于拟合线)。此外,相关和回归公式都可以用不同量的*方和(或总变异面积)来表示。分割*方和是理解广义线性模型和机器学习中的偏差-方差权衡的关键概念。
简而言之:标准差无处不在。
绝对值的问题
你可能会想,为什么我们要求差的*方,而不是只取绝对值。没有什么真的阻止你使用差异的*均绝对值,而不是均方差。*均绝对值将给予所有差异相同的确切权重,而对差异求*方将给予离*均值较远的数字更大的权重。这可能是你想做的事情。然而,大多数数学理论都利用了*方差(原因超出了本文的范围,比如可微性)。
不过我还是用一个比较容易理解的反例来回答这个问题(来源)。假设我们有两组*均值相同的分数,𝑥1 和𝑥2:
通过查看这些分数,你可以很容易地发现𝑥1 比𝑥2.有更低的可变性和数字分布让我们继续计算两者的*均绝对差(知道它们的*均值是 6):
哎呀!那应该很糟糕。两组给出了完全相同的可变性值,尽管我们希望看到𝑥1 的值比𝑥2 稍低,因为数字的可变性更小。然而,如果我们使用*方差,我们会得到:
由于求差的*方,这显然给了我们所希望的:当数字越分散,标准差就越大。
如最初出现在 我的博客 。
二值图像处理的可视化介绍(第一部分)
通过简单直观的可视化理解图像处理的基本方面
伊恩·帕克在 Unsplash 上拍摄的照片
目录:
- 什么是二进制图像?
- 阈值处理:从灰度图像到二值图像
- 邻居
- 连通分量算法
- 二值图像矩
- 中轴
- 距离变换
什么是二进制图像?
二进制图像是其像素只有两个可能的亮度值的图像。在数字上,这两个值对于黑色的和白色的通常是 0,或者是 1 或者是 255。
二进制图像在图像处理领域特别有用的主要原因是因为它们允许容易地将对象从背景中分离出来。分割过程允许将每个像素标记为“背景”或“对象”,并分配相应的黑白颜色。
阈值处理—如何生成二值图像
通过遵循信息提取过程,从灰度图像获得二值图像。阈值处理是这个阶段使用的主要技术。
阈值处理的主要目标是从背景中提取前景
例如,这是一个二进制图像;)
第一步是绘制灰度图像强度的直方图。选择阈值强度。低于该阈值的像素被标记为'白色'或 1 和高于该阈值的像素被标记为黑色或 0 。
在最好的情况下,通过找到两个最高峰值之间的局部最小值,将容易地识别出区分黑色和白色的阈值。但情况并非总是如此…
下面的 gif 显示了改变阈值(红色箭头)到直方图的不同位置如何改变生成的二进制图像。
这是一个非常基本的表示,但我个人认为它足以描述阈值处理过程以及在正确位置设置阈值的重要性。
邻居
在现阶段,引入邻居的概念可能是有益的。一个像素可以有 4 或 8 个邻居。我们称直接邻居为我们感兴趣的像素共享一条边的邻居。
这个定义听起来可能很明显,但是在算法运行和标记像素值的方式上产生了巨大的差异。
例如,连通分量标记算法可以利用 4 或 8 个邻居,产生完全不同的结果!以下示例使用了 4 个邻居。
连接组件标签
作者
一旦我们成功地从前景中提取出背景,下一个合乎逻辑的步骤就是计算在我们的二值图像中可以找到的“物体”的数量。
例如,在我们左边的图像中,有 5 个对象。一个 4 岁的孩子可以回答这个问题。电脑是怎么做到的?****
答案是连通分量标记技术。
第一步:
用唯一的整数标记每个白色像素。我们从顶行到底行系统地对像素进行编号,沿着列增加整数值。
作者
第二步:
现在,我们遍历每个像素。在每次迭代中,我们称当前像素为【I】。我们看一下我们的‘I’像素的 4 个直接邻居。如果邻居的指定整数值(在步骤 1 中)小于‘I’,的当前值,那么‘I’****将取最小邻居的整数值。例如,这就是第三行中像素‘5’和‘9’的情况。或者“17”值像素的群集可能是更好的例子。****
这个步骤需要执行两次。 是的,两次。向后传递确保所有像素都被分配了可能的最小值。这将是连接成分标记技术的最后一步的基础。****
最后一步(简单的一步;)
步骤 2 的结果给出了当像素与作为其直接邻居的较小值像素共享一条边时具有相同整数值的像素。
每个具有唯一值的像素聚类对应于我们的二进制图像中的一个“对象”。
因此,最后一步只是通过增加整数值来重新标记这些对象。这个图像有 9 个对象。 注 :一个四岁的孩子可能回答不出这个问题。
二值图像时刻
在本节中,我们将介绍:
- 物体的质量
- 一阶矩
- 中心图像矩
既然我们已经在二进制图像中找到了对象,我们需要一种方法来表征它们。任何物体的形状、伸长、旋转、位置都可以用少量的值进行编码。这些被称为图像时刻。
****二进制图像矩提供了一种非常优雅的方式来描述二进制图像区域,其具有少量直观且极具描述性的值。
感兴趣对象的质量
我们从定义物体的总质量开始。这相当于我们的对象中值为 1 的像素总数。
变量 m 和 n 对应于行和列, f(m,n) 对应于一个位置处的像素强度(在二进制中这显然将只有 0 或 1)。
感兴趣对象的矩
我们可以计算单个感兴趣物体的不同阶矩。时刻的顺序将产生不同的感兴趣的信息。例如,一阶矩除以总质量(值为 1 的像素数)即为质心。而二阶矩例如是物体的转动惯量。
任意阶矩的一般方程如下:
****阶矩等于 p+q. 这些可以取任意值,对于一阶矩我们举例设定
- p=1 和 q=0 (p+q = 1+0 =一阶矩)
- 或 p=0 和 q=1 (p+q = 0+1 =一阶矩)
一阶矩的结果公式示例如下:
用一阶矩除以物体的质量,就可以求出图形的质心。这给出了我们感兴趣的对象中的中间像素的位置。
****
中心图像矩
这些特别有用,因为它们对于翻译是不变的。所有计算都是相对于感兴趣对象的质心进行的。
*****移在图像处理中,就是通过给 x 坐标和 y 坐标加上一个指定的值,在坐标空间中移动图像中的一个对象。例如,向下移动一个对象意味着给对象中每个像素的 y 坐标增加一个值。
当我们*移一个形状时,质心的坐标也被*移。因此,通过考虑质心来计算中心图像矩使得计算结果对于*移不变。
阶 p+q 的中心图像矩的一般方程为:
对于二阶的中心图像矩,存在三个 p+q 组合。由此产生的中心力矩方程如下所示:
中轴提取
对象的中轴是在对象边界上有一个以上最*点的所有点的集合。****
理解这一点的一个更容易和更直观的方法是查看所有接触两个或更多边界而没有越过任何边界的圆盘的中心所创建的线。
中轴对于字符和物体识别非常有用。我们图像中的每个感兴趣对象都有一个与其形状相关的唯一中轴。
距离变换
距离变换是一个通常只适用于二值图像的操作符。变换的结果是一个渐变颜色的图像,其形状与输入图像相同,除了“对象”区域内的点的强度被改变以显示从每个点到最*边界的距离 。
我们本质上想要找到物体中离边界最远的点。
下面的视频介绍了这个距离是如何计算的。第一个“层”被涂成红色,然后这个逐渐向内移动到边界的距离为+1。最终的中心红色像素对应于距离边界等距离和距离边界最远的像素。
非常感谢你的阅读!
如果您有任何关于如何改进的问题、建议或想法,请在下方留下评论!
如果你喜欢我的作品,你可以关注我这里的中T41。
这里我们来连线一下 LinkedIn 。
深度学习中正则化的视觉直觉
当我们应用正则化时,我们的模型会发生什么?
深度学习模型的优势和劣势——逼*任何函数的自由,以及逼*除了感兴趣的函数之外的任何其他函数的自由!
获得正则化的直觉
在机器学习中,正则化是一种用来对抗高方差的方法——换句话说,就是你的模型学习重现数据的问题,而不是关于你的问题的底层语义。以类似于人类学习的方式,这个想法是构建你的家庭作业问题来测试和构建知识,而不是简单的死记硬背:例如,学习乘法表而不是学习如何乘。
这种现象在通过神经网络进行学习的过程中尤其普遍——随着学习能力的提高,记忆的可能性也越来越大,这取决于我们从业者如何引导深度学习模型吸收我们的问题,而不是我们的数据。你们中的许多人在过去会遇到这些方法,并且可能会对不同的正则化方法如何影响结果有自己的直觉。对于那些不知道的人(甚至那些知道的人!)这篇文章为如何通过正则化来调整神经网络参数提供了直观的指导。将这些方面形象化是很重要的,因为很容易将许多概念视为理所当然;本文中的图表及其解释有望帮助您直观地了解随着正则化程度的提高,模型参数会发生什么变化。
在本文中,我将把 L2 和辍学作为正规化的标准形式。我不会讨论其他方法(比如收集更多的数据)可能如何改变你的模型的工作方式;那可能是另一个时间。
所有的图形和模型都是用标准的科学 Python 栈制作的:numpy
、matplotlib
、scipy
、sklearn
,神经网络模型是用 PyTorch 构建的。
开发复杂功能
深度学习的核心原则之一是深度神经网络作为通用函数*似的能力。你可能感兴趣的任何东西——疾病的传播、无人驾驶汽车、天文学——都可以被压缩和并由一个自学模型来表达,这种想法绝对令人惊叹!这是不管你感兴趣的问题实际上是否可以表达为某个解析函数 f 。当您通过训练来调节机器学习模型时,该模型采用参数 θ ,这允许该模型*似地学习 f *。
出于说明的目的,我们将查看一些相对简单的数据:理想情况下,一维数据足够复杂,以至于老派的曲线拟合令人痛苦,但又不至于难以抽象和理解。所以,我要创建一些任意复杂的函数,模拟周期信号,但加入一些古怪的东西。下面的函数实现了下面的等式:
我们自己的“复杂”功能
其中 A,B,C 是从不同的高斯分布中采样的随机数。这些值中的每一个的效果是在非常相似的函数之间添加滞后,使得它们随机地加在一起以生成非常不同的 f 值。我们还将向数据中添加白(高斯)噪声,以模拟正在收集的数据的效果。
让我们设想一个随机生成的数据样本:在本文的其余部分,我们将通过一个小的神经网络来重现这条曲线。
我们“复杂”功能的可视化。这对应于一个 X 和 Y 1D 数组,每个数组有 10,000 个元素长。
为了进行模型训练,我们将把它分成训练/验证集。为此,我将使用sklearn.model_selection
中极其方便的train_test_split
函数。让我们绘制训练集和验证集:
蓝色点对应测试,红色代表训练数据。
正如我们在图中看到的,两组数据在表示整体曲线方面做得相当好:如果我们去掉一个或另一个,我们可以收集到或多或少相同的数据所表示的图像。对于交叉验证来说,这是一个非常重要的方面!
开发我们的模型
现在我们有了一个数据集,我们需要一个相对简单的模型来尝试和重现它。为此,我们将处理一个四层神经网络,包括单个输入和输出值,有三个隐藏层,每个层有 64 个神经元宽。
我们的神经网络模型的简化图:奇异值输入和输出,有三个隐藏层,每个 64 个神经元宽(没有画出所有的神经元!)
为了方便起见,每个隐藏层都有一个 LeakyReLU 激活,在输出上有 ReLU 激活。原则上,这些不应该有太大的关系,但在测试期间,有时模型在学习一些“复杂”的功能时有困难,特别是当使用像 tanh 和 sigmoid 这样的激活时,这很容易饱和。就本文而言,这个模型的细节并不重要:重要的是,它是一个全连接的神经网络,具有学习逼*某个函数的能力。
为了证明该模型有效,我使用均方误差(MSE)损失和 ADAM 优化器执行了通常的训练/验证周期,没有任何形式的正则化,并以这些结果结束:
该模型的训练和验证工作良好:没有高方差或偏差的真实证据,并且两种损失在 100 个时期的过程中相对单调地减少。
当我们用这个模型来预测函数时:
我们的模型或多或少完美地得到了*似函数!
除了曲率快速变化的区域(接* x =11),模型很好地再现了我们的“复杂”函数!
现在,我可以听到你问:如果模型运行良好,为什么我要做任何正则化?为了这个演示的目的,我们的模型是否过度拟合并不重要:我想要表达的是正则化如何影响一个模型;在我们的例子中,它甚至可以有害地影响一个完美的工作模型。在某种意义上,你可以把这理解为一句警告:当你遇到过度拟合时,就去处理它,而不是在此之前。用 Donald Knuth 的名言来说,“过早优化是万恶之源”。
正则化如何影响您的参数
既然我们已经解决了所有的样板文件,我们就可以进入文章的核心部分了!我们的重点是尝试并发展一种直觉,从三个角度了解不同的正则化方法如何影响我们的简单模型:
- 培训/验证损失会怎样?
- 我们的模型性能会发生什么变化?
- 实际参数会发生什么变化?
虽然前两点有些简单,但你们中的许多人可能不熟悉如何量化第三点。在这次演示中,我将使用核密度估计来测量参数值的分布/变化:对于那些熟悉 Tensorboard 的人来说,你会看到这些图;对于那些不熟悉的人,可以把这些图想象成复杂的直方图。目标是可视化我们的模型参数如何随正则化而变化,下图显示了训练前后 θ 分布的差异:
简单模型的模型参数的核密度估计值 θ 。
蓝色曲线被标为“均匀”,因为它代表了我们用均匀分布初始化的模型参数:你可以看到这基本上表现为一个礼帽函数,在中心具有相等的概率。这与经过训练的模型参数形成对比:在训练之后,模型需要非均匀的 θ 值,以便实际表达我们的函数。
L2 正则化
最直接的正则化方法之一是所谓的 L2 正则化:L2 指的是使用参数矩阵的 L2 范数。根据线性代数,矩阵的范数由下式给出:
任意 Lpq 范数的一般表达式
在前神经网络机器学习中,参数更经常被表示为向量而不是矩阵/张量,这只是欧几里德范数。在深度学习中,我们更经常地处理矩阵/高维张量,欧几里德范数并没有很好地扩展(超越欧几里德几何)。L2 范数实际上是上述等式的特例,其中 p = q =2,并且被称为弗罗贝纽斯或希尔伯特-施密特范数,其推广到无限维度(即希尔伯特空间)。
弗罗贝纽斯/希尔伯特-施密特(L2)范数。
在深度学习应用中,应用这种 L2 正则化的一般形式是在你的成本函数 J 的末尾附加一个“惩罚”因子:
我们的成本函数:第一部分是预测值和实际值之间的均方误差差,右边的部分是我们的 L2 正则化项。
非常简单,这个等式将成本函数 J 定义为 MSE 损失,以及 L2 范数。L2 范数对成本的影响乘以这个因数λ;这在许多实施中被称为“重量衰减”超参数,通常在 0 和 1 之间。由于它控制正则化的数量,我们需要理解这对我们的模型有什么影响!
在一系列实验中,我们将重复与之前相同的训练/验证/可视化循环,但是使用λ的一系列值。第一,对我们的训练有什么影响?
L2 正则化对模型训练的影响。
我们来分解一下上面的情节。较深的红色阴影对应于较大的λ值(尽管它不是线性贴图!),将训练损失的痕迹显示为 MSE 损失的日志。记住,在我们的非正则化模型中,这些曲线单调递减。这里,当我们增加λ的值时,最终的训练误差显著增加,并且在早期损失的减少也不显著。当我们试图用这些模型来预测我们的功能时会发生什么?
使用用指定的λ值训练的模型进行预测。
我们可以看到,在λ值很小的情况下,这个函数仍然可以表达得相当好。转折点出现在λ=0.01 附*,在这里,曲线的定性形状被复制,但不是实际的数据点。从λ>0.01 开始,该模型只是预测整个数据集的*均值:就好像我们只是尝试进行线性回归一样。如果我们根据我们的培训损失来解释这些,那么损失停止减少也就不足为奇了——用一条直线你只能做这么多!
参数的分布呢?
我们每个训练模型的参数分布,具有不同的λ值。分布的峰值被截断。
我们看到,当我们从低λ到高λ时,参数值的分布受到很大的阻碍。与均匀分布相比,参数值的分布越来越接*零,并且在λ=1.0 的情况下, θ 的分布看起来就像零处的狄拉克δ函数。由此,我们可以得出 L2 正则化用于约束参数空间——迫使θ非常稀疏且接*于零。
辍学怎么办?
另一种流行且经济有效的正规化方法是在你的模型中加入辍学者。这个想法是,随着每一个模型的通过,根据某种概率 p 通过将它们的权重设置为零来停用一些神经元。换句话说,我们对我们的参数应用了一个布尔掩码,每次数据经过不同的单元时都会被激活。这背后的基本原理是将模型学习分布在整个网络中,而不是特定的一个或两个层/神经元。
在我们的实验中,我们将在每个隐藏层之间包含丢失层,并将丢失概率从零调整到一。在前一个限制中,我们应该只有一个非正则化的模型,而在后一个限制中,我们应该有各自降低的学习能力,因为每个隐藏层都被去激活。
一系列退出概率的培训损失模型。
我们看到了与 L2 正则化非常相似的效果:总的来说,模型的学习能力降低了,并且随着丢失概率值的增大,最终的损失成比例地增大。
当我们试图用这些模型来预测我们的功能时:
越往下看,我们辍学的可能性越大。从 p =0.1 开始,我们可以看到我们的模型开始对它的预测相当不稳定:最有趣的是,它似乎*似地跟踪我们的数据,包括噪声!
在 p =0.2 和 0.3 时,这在 x =11 附*更加明显——回想一下,我们的非正则化模型很难正确得到函数的这个区域。我们看到,有遗漏的预测实际上使这个区域变得非常模糊,这几乎就像模型告诉我们它是不确定的!(稍后会详细介绍)。
从 p =0.4 开始,模型的能力似乎受到了充分的限制,除了第一部分之外,它无法再现曲线的大部分。在 p =0.6 时,看起来预测几乎接*数据集*均值,这似乎也发生在 L2 正则化的大值上。
我们的模型参数呢?
作为退出概率函数的模型参数分布。
与我们的 L2 常模结果比较:对于辍学者,我们的参数分布更广,这增加了我们模型的表达能力。除了 p =1.0 之外,即使有影响,退出概率的实际值也不会对参数的分布产生很大影响。在 p =1.0 时,我们的模型没有学到任何东西,只是类似于均匀分布。在降低的值 p 下,模型仍然可以设法学习,尽管速率降低。
带回家的信息
从我们简单的实验中,我希望你已经从我们探索的三个角度开发了这两种正则化方法如何影响神经网络模型的一些心智模型。
L2 正则化非常简单,只需调整一个超参数。当我们增加 L2 惩罚的权重时,参数空间的变化——因此模型容量——对于大值(0.01–1)下降得非常快。使用较小的值,您甚至可能看不到模型预测中的差异,尽管当您绘制出 θ的分布时,这一点变得很明显。
Dropouts 是一种更复杂的正则化方法,因为您现在必须处理另一层超参数复杂性( p 对于不同的层可以有不同的值)。尽管如此,取决于你如何看待它,这实际上可以提供模型表达的另一个维度:以模型不确定性的形式。我计划在另一篇博文中更多地介绍这一点(给我发消息鼓励我吧!).包含漏失的影响是 θ 的变化变得明显更大,并扩展到 θ的不同可能值。
在这两种方法中,我们已经看到正则化增加了最终的训练损失。这些人工形式的正则化(而不是获得更多的训练数据)的成本是,它们会降低您的模型的容量:除非您确定您的模型需要正则化,否则您不希望包含这些内容。然而,有了这个指南,你现在应该知道这两种形式是如何影响你的模型的了!
如果你感兴趣,你可以在 Binder 上运行一些代码。我不一定要运行torch
模型(这会耗尽它们可怜的资源),但是你可以用它来探索笔记本中的代码。
进一步阅读
请留意更多这类文章!你可以通过推特、T2、LinkedIn 和媒体网络联系我!
线性回归的直观入门
走向稳健估计
…或者说,这意味着什么?
估计器ŷ穷尽了预测器 x₁ 和 x₂的可用信息
介绍
线性回归,或最小二乘回归,是机器学习最简单的应用,也可以说是最重要的。许多人每天都在应用方法,却没有意识到。无论何时计算算术*均值,我们都有一个线性回归的特例——也就是说,响应变量的最佳预测值是响应本身的偏差(或*均值)!
最小二乘法的核心思想是最小化“误差”的*方和,即调整未知参数,使观测值和计算值之差的*方和最小化。
关于线性回归,已经有很多关于它的文章了,为什么还要再写一篇呢?我的目的不是“展示它是如何做到的”,而是说明线性回归是一个更基本概念的方便和实用的例子——估计——并为读者开发一种对机制的直觉。
基础知识
“线性模型”中的“线性”一词不是指模型的单个项,例如它们是否是*方的,或者有*方根,等等。许多人惊讶地发现,预测变量可以应用各种非线性变换,和经常被应用以创建有效的线性模型。相反,“线性”是指模型的整体行为:线性模型是预测变量的线性组合产生响应变量的预测。这意味着
是一个线性模型,其中 x₁ 可能是(使用我们数据中的一些示例“测量”值):
游戏规则
我发现许多人都反对我们可以随心所欲地操纵变量。但是为什么我们首先接受预测变量的线性组合是进行预测的有效方法呢?最小二乘回归的唯一规则是残差的均值必须为零,不相关,并且是同方差的(这是一个有趣的词,表示残差的方差必须是常数)。我们可以做任何事情,而且事实上必须经常做很多事情,为了满足这三条规则!
为了推广,我们必须介绍一些线性代数。我们也可以用向量符号将我们的模型写成:
其中预测变量以列向量的形式给出:
在这种形式下,我们可以开始更好地理解本文顶部的几何表示的图像。显而易见,我们把预测看作是向量的和,但是什么是()的残差呢?是 X₁ 和 X₂ 不包含的所有信息的总和,并且与两者正交!这里我们有截距,或偏差项,开始发挥作用。当我们扩展到更高维度时,“截距”的概念实际上并没有太多的直观意义,因为我们无法在一个图上可视化所有变量。相反,这是我们为了“把我们的拇指放在秤上”而添加的一个偏差项,可以说,是为了使我们的预测比我们只使用预测变量时更准确。如果我们重新绘制包含偏差项的图,我们会得到如下结果:
添加偏差项以将残差的*均值设置为零
而且我们看到,偏置项, b ,降低了残差的大小。(注意:这并不完全准确,因为残差应该与和 X₂ 和b正交,但可惜我们仅限于三个空间维度)。当然,我们只查看对应于和 X₂ 的单个值的单个预测,而实际的线性模型会对和【x₂的每个值进行预测。偏差项计算为将所有残差的*均值设置为零的值。****
推广回归方程
让我们进一步用回归方程来说明如何确定系数。首先,我们可以从用向量写模型转移到矩阵符号。我们先把x₀x₁和 X₂ 组合成一个矩阵:
然后简化我们的回归方程:
这里,由于我们已经讨论过残差是,我们添加了残差项,因为我们知道它们也必须包括在内,以获得响应变量的实际测量值。请记住,残差与所有预测变量和响应变量的预测正交,这意味着它们包含无法解释的偏差,这些偏差可能存在于我们没有观测到的其他预测变量中。
我们不去研究解的推导,但是如果我们求解方程的值,我们得到:
如果你需要一些可视化矩阵乘法的帮助,我们有:
*均值是特殊的
在最简单的情况下,……即位置参数的估计,……这当然是通过样本均值来实现的。
现在,让我们考虑一个线性回归的特例,其中我们只有——也就是说,我们只有一个单位列向量。这将先前的矩阵乘法减少到:**
代入回归方程,我们得到:
希望你认识到这一点!它说的是,只有一个响应变量的线性模型的最佳预测值是响应变量本身的*均值!
为什么这很重要?这表明最小二乘回归所需的假设 也适用于*均值的计算。这些是:
- 残差具有均值为零的高斯分布。正如我们在上文中了解到的,当我们计算偏差项时,回归行为本身满足了这一点。
- 残差在所有预测值中具有恒定的方差(同方差)。
- 残差是独立同分布的。不存在时间序列数据中常见的相关性或自相关性。
因为我们只处理一个单一的响应变量,所以第二点和第三点可以看作是在谈论变量本身。如果我们的抽样很差,与其他范围相比,在特定范围的值中存在过度代表性,或者如果样本完全相关(即值相互依赖),则*均值是变量的最佳估计值 而不是 。
众所周知,如果真实分布稍微偏离假设的正态分布,样本均值可能会有灾难性的不良表现。
如果我们从*均值反向回到线性模型,我们也可以说最小二乘回归是 而不是 对于不满足我们规则的问题的最佳回归方法。
那又怎样?
最小二乘回归并不总是有效,但我们可以尝试许多其他的机器学习技术,对吗?好吧,在我们把神经网络扔向一堵墙,看看有什么粘在一起之前,让我们考虑一下我们能对这个缺点做些什么。我不是统计学家,所以在我批评整个统计学领域的基础之前。),让我引用一位在 1964 年调查过这个问题的统计学家的话:
有趣的是回顾估计理论的起源,即高斯和他的最小二乘理论。高斯充分意识到,他假设基础正态分布和二次函数的主要原因是数学上的,即计算上的便利。在后来的时代,这一点经常被遗忘,部分原因是因为中心极限定理。但是,如果要说实话,中心极限定理最多能解释为什么实践中出现的很多分布都是*似正态的。重音在“大约”这个词上。
胡伯,P. J. 1964。位置参数的稳健估计。
数理统计年鉴 35(1):73–101。https://doi.org/10.1214/aoms/1177703732
Huber 被认为是 稳健估计 研究领域的创造者之一,并且是贯穿本文的各种引文的来源。他的目标是创建最小二乘估计的替代估计,能够更好地处理异常值或其他偏离最小二乘估计规则的情况。正如他指出的,在所有其他选择中选择最小二乘法的主要动机之一是为了方便解析解。对于早于 20 世纪末的任何历史时期来说,这都是一个巨大的便利。然而现在,对于我们人类对时间的感知来说,解决回归问题的数值方法通常和解析解一样快。存在更好的评估者。
后续步骤
人们很自然会问,是否可以通过最小化另一个误差函数而不是它们的*方和来获得更高的鲁棒性。
让我们把估计量的概念简化为“距离的度量”。我们通常会想到欧几里德距离, a + b + … ,但这只是测量距离的无限方式之一。如果你在曼哈顿的城市网格上,这是一个几乎无用的测量来确定你和你试图到达的角落餐馆之间的距离。
到午餐的最短距离是多少?
绿线,欧几里德距离,是最短的…但也是不可能达到的。事实证明,红色、蓝色和黄色的线,也就是俗称的“出租车距离”,长度都是一样的。如果你想知道仅仅根据距离你应该如何到达某个地方,计算机不能为你计算出最短的路线。然而,这也意味着最短路线的解决方案是健壮的:如果发生了灾难性的错误(用 Huber 的话说),很容易找到替代路线。在下一篇文章中,我们将讨论这些替代方案,了解它们的特性,并在这样做时,扩展回归以处理比最小二乘法更复杂的情况。
这使我们更接*准确的估计的目标。
什么是卷积神经网络?
基本 CNN 的模板
卷积神经网络基本元素的可视化
可视化是理解丰富概念的一个很好的工具,特别是对于该领域的初学者。在本文中,我们将使用视觉辅助工具来浏览卷积神经网络的基本元素。本文首先为一个具有不同构件的基本 CNN 提供一个模板(可视化的),然后讨论每个构件最常用的元素。
基本 CNN 模板:
一个基本的 CNN 由三种层组成。输入、隐藏和输出如下所示。数据通过输入层进入 CNN,并在到达输出层之前通过各种隐藏层。输出层是网络的预测。根据损失或误差,将网络的输出与实际标签进行比较。对于要学习的网络,计算该损失相对于可训练权重的偏导数,并且通过使用反向传播的各种方法之一来更新权重。
基本 CNN 的完整视觉模板可以在下面看到。
基本 CNN 的模板
CNN 的隐藏层
网络中的隐藏层提供了转换数据的基本构件(输入层或先前隐藏层的输出)。大多数常用的隐藏层(不是全部)都遵循一个模式。它首先将一个函数应用到它的输入,然后转移到池化、规范化,最后在它可以作为输入提供给下一层之前应用激活。因此,每一层可以分解成以下 4 个子功能
- 层功能:卷积或全连接层等基本变换功能。
- 池化:用于改变特征图的空间大小,增加(上采样)或减少(最常见的)它。例如最大池化、*均池化和取消池化。
- 归一化:该子函数将数据归一化,使其均值和单位方差为零。这有助于处理消失梯度、内部协变量移位等问题。(更多信息)。最常用的两种标准化技术是局部响应标准化和批量标准化。
- 激活:应用非线性并限制输出过高或过低。
我们将逐一介绍每个子功能,解释它们最常见的例子。
还有更复杂的 CNN 架构,有各种其他层和相当复杂的架构。不是所有的 CNN 架构都遵循这个模板。
1.层功能
最常用的层函数是全连接、卷积和转置卷积(错误地称为解卷积)层。
a.完全连接的层:
这些层由输入和输出之间的线性函数组成。对于 i 输入节点和 j 输出节点,可训练权值为 wij 和 bj。左图说明了 3 个输入节点和 2 个输出节点之间的全连接层是如何工作的。
b.卷积层:
这些图层应用于 2D(和 3D)输入要素地图。可训练权重是一个 2D(或 3D)核/过滤器,它在输入要素地图上移动,与输入要素地图的重叠区域生成点积。以下是用于定义卷积层的 3 个参数
- 内核大小 K: 滑动内核或过滤器的大小。
- 步长 S: 定义在执行点积生成输出像素之前内核滑动了多少
- 填充 P: 输入特征图周围插入的零的帧大小。
下面的 4 幅图直观地解释了大小为( i ) 5x5 的输入上的卷积层,其中内核大小( k )为 3x3,步长( s )和填充( p )
动画卷积层(来源:Aqeel Anwar)
步幅和填充与输入特征图一起控制输出特征图的大小。输出大小由下式给出
c.转置卷积(反卷积)层:
通常用于增加输出特征图的大小(上采样)。转置卷积层背后的想法是撤消(不完全)卷积层。正如卷积层一样,它也是由步长和填充定义的。如果我们对输出应用所提供的步幅和填充,并应用所提供大小的卷积核,它将生成输入。
转置卷积层(来源:Aqeel Anwar)
要生成输出,需要执行两件事情
- 零插入( z ):在原始输入的行和列之间插入的零的数量
- padding(p’):输入特征图周围插入的零的帧大小。
下面的 4 幅图直观地解释了在不同大小( i )的输入上的转置卷积层,对于 3x3 的内核大小( k )和不同步长( s )以及填充( p )而输出 (o) 固定为 5×5
动画转置卷积层(来源:Aqeel Anwar)
关于转置卷积层的深入细节可以在下面找到
通过动画 gif 和 python 代码解释。
towardsdatascience.com](/what-is-transposed-convolutional-layer-40e5e6e31c11)
2.联营
最常用的池是最大、*均池和最大*均取消池。
最大/*均池:
基于选择由内核定义的感受域中的最大值/*均值,不可训练层用于减小输入层的空间大小。核以给定的步幅滑过输入特征图。对于每个位置,输入特征图中与核重叠的部分的最大值/*均值就是相应的输出像素。
动画最大池层(来源:Aqeel Anwar)
取消轮询:
基于将输入像素放置在由内核定义的输出的感受域中的某个索引处,不可训练层用于增加输入层的空间大小。对于一个非池层,在网络的早期需要有一个相应的池层。来自相应池层的最大/*均值的索引被保存并在非池层中使用。在非池化图层中,每个输入像素被放置在输出中池化图层中出现最大值/*均值的索引处,而其他像素被设置为零
3.正常化
通常在激活函数之前使用归一化来限制无限制激活将输出图层值增加得过高。通常使用两种类型的标准化技术
a.LRN 当地反应正常化:
LRN 是一个不可训练层,它在局部邻域内对特征图中的像素值进行*方归一化。基于邻域定义,有两种类型的 LRN:通道间和通道内,如下图所示。
左:通道内 LRN … 右:通道间 LRN
b.批量标准化 BN:
另一方面,BN 是一种可训练的标准化数据的方法。在批量标准化中,隐藏神经元的输出在被馈送到激活函数之前以下面的方式被处理。
- 将整批 B 标准化为零均值和单位方差
- 计算整个小批量产量的*均值: u_B
- 计算整个小批量产量的方差:s igma_B
- 通过减去*均值并除以方差来标准化小批量
2.引入两个可训练参数( Gamma: scale_variable 和 Beta: shift_variable)来缩放和移动标准化小批量输出
3.将该缩放和移位的标准化小批量馈送到激活功能。
下面是这两种标准化技术的总结
关于这些标准化技术的详细文章可以在 这里 找到
4.激活
激活函数的主要目的是引入非线性,因此 CNN 可以有效地映射输入和输出之间的非线性复映射。根据基本要求,可以使用多种激活功能。
- 非参数/静态函数:线性,ReLU
- 参数函数: ELU,双曲正切,sigmoid,Leaky ReLU
- 有界函数: tanh,sigmoid
下面的 gif 形象地解释了最常用的激活函数的本质。
动画激活功能(来源:Aqeel Anwar)
最常用的激活函数是 ReLU。当涉及到更深的神经网络时,诸如 tanh 和 sigmoid 的有界激活函数遭受消失梯度的问题,并且通常被避免。
5.损失计算:
一旦定义了 CNN,就需要选择一个损失函数来量化 CNN 预测与实际标签的差距。然后,在梯度下降法中使用这种损失来训练网络变量。像激活函数一样,损失函数有多种选择。
回归损失函数
- *均绝对误差:估计值和标签是实数
- 均方差:估计值和标签是实数
- 胡伯损失:估计值和标签是实数
分类损失函数
- 交叉熵:估计值和标签是概率(0,1)
- 铰链损耗:估计值和标签是实数
这些损失函数的细节可以在下图中看到
动画 ML 损失函数(来源:Aqeel Anwar)
6.反向传播
反向传播不是 CNN 的结构元素,而是我们通过在梯度变化(梯度下降)的相反方向上更新权重来学习潜在问题的方法。关于不同梯度下降算法的深入细节可以在这里找到。
总结:
在这篇文章中,介绍了一个基本 CNN 的不同元素的动画可视化,这将有助于更好地理解它们的功能。
奖金:
可以在下面的链接中找到这个主题和机器学习中许多其他重要主题的紧凑备忘单
ML 面试的视觉备忘单(www.cheatsheets.aqeel-anwar.com)
medium.com](https://medium.com/swlh/cheat-sheets-for-machine-learning-interview-topics-51c2bc2bab4f)
如果这篇文章对你有帮助,欢迎鼓掌、分享和回复。如果你想了解更多关于机器学习和数据科学的知识,请关注我@Aqeel an war或者在LinkedIn上与我联系。
通过可视化备忘单浏览机器学习中的不*衡类
什么是不*衡的训练数据,以及如何通过精确度、召回率和 f1 分数来解决它。
许多详细的文章解释了不*衡训练样本的问题以及如何应对它。在这篇文章中,我把对问题的理解总结成一张可视化的小抄。我经常发现它很有用,因为每当我不得不回到基本定义时(或者我有一个面试安排),它就派上了用场。
下面的备忘单从为什么准确性并不总是给出与您的分类算法相关的正确见解的背景开始,然后继续定义其他有意义的性能指标。然后,备忘单提供了一个示例,展示了如何为一个三类分类问题计算这些指标。一旦通过适当的指标确定了问题,备忘单就会解释许多可能的解决方案来克服不*衡的训练数据问题。
奖金:
可以在下面的链接中找到这个主题和机器学习中许多其他重要主题的紧凑备忘单
ML 面试的视觉备忘单(www.cheatsheets.aqeel-anwar.com)
medium.com](https://medium.com/swlh/cheat-sheets-for-machine-learning-interview-topics-51c2bc2bab4f)
如果这篇文章对你有帮助,欢迎鼓掌、分享和回复。如果你想了解更多关于机器学习和数据科学的知识,请关注我@Aqeel an war或者在LinkedIn上与我联系。
编写更好的函数的演练
从例子中学习如何编写更好的、可重用的函数
介绍
我看到很多初学者在编程时不使用函数。当我强迫他们写一个时,他们只是将一堆代码复制粘贴到一个函数中,然后称之为完成。
该函数将没有参数,没有各种数据结构的灵活性,也没有可重用性。变量将在函数内部声明。各种地方会用数字代替变量。也不会有类型检查,不会有测试来看它是否会崩溃。这样的例子不胜枚举。该功能将为他们的特定任务工作,就是这样。
在本文中,我将尝试向您介绍一个代码示例以及编写更好的函数背后的思考过程。我希望看到这个例子并尝试其中的一些想法会让您对如何为将来编写更好的函数有一个直观的感觉。
示例代码
最*,我在做一个计算机视觉作业,要求我们从头开始写卷积。我会仔细阅读这些代码。
技巧 1:当编写一个函数时,要记住的第一点是让他们做一件事,而且只做一件事。
这个技巧将帮助你保持你的函数简短。不要把所有东西都放进去。让我们来看看我们写的读取图像文件的函数。
我们从这样的事情开始:
我们读取一个图像,将其转换为灰度,将其转换为一个 numpy 数组,然后将其返回。这是一个简洁的函数,但是不够灵活。
改进 1:我们不总是想要灰度图像。因此我们包含了一个论点。这是我们的下一个提示。
技巧 2:在我们的函数中,我们使用库。我们传递给这些库的参数也为我们的函数提供了很好的参数。
这是一个非常有用的提示。特别是如果你使用 matplotlib 这样的东西,并且你不知道一个函数需要的所有参数,只需要包含一个**kwargs
作为你的函数的参数,并愉快地将它传递给 matplotlib。
我们可能想要改变的另一件事是到 numpy 数组的转换。如果用户不需要 numpy 数组,而只需要一个 PIL 图像,那该怎么办?给他这个选择。
提示 3:给用户很多选择,让用户在不同的方向使用你的函数输出。
我们的功能现在非常灵活,可以在许多其他地方重用。即使不是同一个,但有微小的变化。例如,通过更改默认参数来重用它。这提醒了我,我们需要明智地对待我们的违约。在我们当前的例子中,mode = None.
然而,就像我之前提到的,我们只需要灰度图像。因此,我们应该将其初始化为"L"
,而不是我们不想做的None.
:
然而,我们也不想做:
因此我们可以创建另一个函数,如下所示:
看看我们的功能建立得多好。您可以做的另一件事是,不要手动传递图像文件的名称,而是使用代码检索它们。
家庭作业:
谷歌如何获得所有图像扩展?谷歌如何使用全球图书馆检索所有文件与某些扩展名。然后马上自己编码。
提示 4:让你的代码为多种数据结构工作
最后一个技巧是在适用的地方为不同的数据结构包含不同的行为。重点是不要破坏代码,让它为大多数事情工作。
结论
这就是本文的全部内容。我希望这篇文章能帮助你在将来写出更好的代码。你可以看到,与我们开始的地方相比,现在read_image
函数几乎可以在任何地方使用。你不会从最好的函数开始。但是不断重构你的代码,你会改进很多。
在结束之前,我想指出的一点是,尽管你已经学会了所有这些技巧,但不要过度使用。保持你的功能简约但超级有用。
~快乐学习
在 GitHub Profile 上扩展您的网络的方法
简单解释一下如何在 GitHub 上链接你的社交媒体页面
介绍
建立你的关系网和分享你的作品可能是让你的名字出现在社区的最好方式。
你们中的一些人可能已经知道,GitHub 最*增加了一个隐藏的功能,可以让你自定义你的 GitHub 个人资料页面。下面是如何解锁隐藏功能的教程。
关于如何定制 GitHub 个人资料页面的简单说明
towardsdatascience.com](/unlocking-githubs-hidden-feature-in-3-minutes-2c21c8e47a20)
GitHub 个人资料页面是 GitHub 的门面,你想让它尽可能吸引人。我个人认为,你应该尽可能简单地提供尽可能多的信息——提供你的项目、网站或社交媒体的链接。通过这样做,你可以很容易地与查看你的 GitHub 的人分享你的作品,你也有机会与他们联系。
在这篇文章中,我想演示如何简单地将你的社交媒体页面与 GitHub 上的标志链接起来。
社交媒体品牌指南
首先,你需要了解并遵循品牌指南,以便使用他们的标志。下面是每个品牌的指导方针,我将使用这些标志。
YouTube
YouTube 的使命是给每个人一个声音,向他们展示这个世界。了解我们的品牌、社区、职业和…
www.youtube.com](https://www.youtube.com/about/brand-resources/#logos-icons-colors)
中等
中等设计](https://medium.design/logos-and-brand-guidelines-f1a01a733592)
推特
从推文处理到徽标和社交图标,我们的模板和工具将帮助您使用 Twitter 内容和我们的…
about.twitter.com](https://about.twitter.com/en_us/company/brand-resources.html)
领英
为了确保我们的标志清晰可辨,并保持其完整性,保持其周围的区域没有其他元素…
brand.linkedin.com](https://brand.linkedin.com/downloads)
卡格尔
[## Kaggle 品牌指南
关于如何以及何时利用 Kaggle 品牌的指南
www.kaggle.com](https://www.kaggle.com/brand-guidelines)
下载和上传徽标
一旦你理解了他们的指导方针,你就想下载徽标,并把它们上传到任何可以获得图像 URL 的*台上。我将使用 Cloudinary 来上传它们并获取 URL。你也可以使用 Google Drive 或 Dropbox。
使用 HTML 代码将徽标与您的社交媒体链接结合起来
一旦你解锁了 GitHub 的隐藏特性并初始化了 README 文件,你就可以用 HTML 来编辑它了。
使用 HTML 代码,我们可以将您的社交媒体链接和您上传的徽标结合起来。
访问您的社交媒体链接的 HTML 代码
<a href="[https://www.youtube.com/c/ImportData1](https://www.youtube.com/c/ImportData1)">
访问社交媒体徽标的 HTML 代码
<img src="[https://res.cloudinary.com/importdata/image/upload/v1595012354/yt_logo_jjgys4.png](https://res.cloudinary.com/importdata/image/upload/v1595012354/yt_logo_jjgys4.png)" alt="drawing" width="100"/>
您可以通过调整【宽度】来改变图像尺寸
你要把上面的代码一个挨着一个地放在一起,以充分地把标志和链接结合起来。
<a href="[https://www.youtube.com/c/ImportData1](https://www.youtube.com/c/ImportData1)"><img src="[https://res.cloudinary.com/importdata/image/upload/v1595012354/yt_logo_jjgys4.png](https://res.cloudinary.com/importdata/image/upload/v1595012354/yt_logo_jjgys4.png)" alt="drawing" width="100"/>
可以把放在 ;如果您想在标志之间添加空格。
<a href="[https://www.youtube.com/c/ImportData1](https://www.youtube.com/c/ImportData1)"><img src="[https://res.cloudinary.com/importdata/image/upload/v1595012354/yt_logo_jjgys4.png](https://res.cloudinary.com/importdata/image/upload/v1595012354/yt_logo_jjgys4.png)" alt="drawing" width="100"/>** **<a href="[https://medium.com/@importdata](https://medium.com/@importdata)"><img src="[https://res.cloudinary.com/importdata/image/upload/v1595012354/medium_mono_hoz0z5.png](https://res.cloudinary.com/importdata/image/upload/v1595012354/medium_mono_hoz0z5.png)" alt="drawing" width="35"/>
就是这个!非常感谢你阅读这篇文章,希望你觉得有用!
在这些*台上与我联系:
🔗 YouTube
🔗推特
🔗 LinkedIn
🔗GitHub🔗卡格尔
一个全新的人工智能世界
疫情之后人工智能的兴起
约书亚·厄尔在 Unsplash 上的照片
人工智能将在未来 10-15 年对工作世界产生什么影响?
今天的世界正在快速变化,我们希望在未来十年看到令人难以置信的变化,这要归功于人工智能。我们不要忘记,疫情的一个积极影响是,人们越来越依赖技术,正在学习在线生活,不再羞于使用技术。这种情况本身导致更多的人使用并最终信任技术。雇主也在经历这样的心理变化。这是他们有生以来第一次,他们的生意陷入停顿!
在未来几年,人工智能不一定会取代整个工作,但它会接管特定的任务。它已经开始取代这些任务,并且在未来几年将继续加速。根据世界经济论坛,在 5 年内,自动化将占现有任务的 50%以上。我们认为有四种可能的情况需要考虑:
- 一些工作,如护理职业(护士、医生和其他人),创意产业(演员、音乐家和其他人),不会受到人工智能的太大影响,因为人工智能仍然不太擅长这些任务。
- 其他工作将被淘汰。这些人包括司机(因为自动驾驶汽车的兴起)、工厂工人(因为自动化)和许多其他人。
- 许多新的工作将会出现。这些工作甚至不是我们发明的。它可能包括像器官创造者这样的服务,通过这些服务,人们可以设计新的器官(如新的心脏、肾脏或肝脏)来替代有缺陷的器官。
- 大多数现有的工作将会改变,因为人工智能技术将会增加他们的基本任务。这将产生巨大的影响。它可能小到帮助超市的堆垛机使用增强现实识别过期产品,大到在手术中协助外科医生。
AI 未来会消灭还是增加工作岗位?
很难得出一个关于人工智能会减少还是增加工作岗位的大概数字。人工智能专家声称,在未来十年内,它将会淘汰目前存在的 40%以上的职位。如果我们考虑到疫情的影响,这个数字很可能是一个保守的估计。另一方面,世界经济论坛预测,AI 将创造至少 1.33 亿个新角色。这些都是新的工作,今天甚至不存在。
此外,我们不要忘记,IT 行业并不是孤立运作的,它需要许多辅助角色,如视觉艺术家、文案和其他一些角色。因此,要达到这个正确的数字,这个数额至少应该翻两番。如果我们把所有事情都加在一起,官方估计表明,人工智能创造的就业机会很可能比它杀死的多 45%。因此,总的来说,未来看起来确实是光明的。这种前景并不意味着一切都会一帆风顺。许多人仍然需要接受再培训和再技能培训,才能在新的就业市场中茁壮成长,但在人工智能工具的帮助下,这将比以前简单得多。
工作的未来会是什么样子?
我们知道工作会逐渐改变。对自动化的依赖将呈指数增长,我们将忘记过去发生的事情。只要想想智能手机;它取代了固定电话、电话答录机、照相机、闹钟、卫星导航系统、扫描仪、音乐播放器、计算器、电视和其他东西。年轻人可能从来没有见过这些旧设备,除非他们参观了古董博物馆。同样的事情也会发生在 AI 身上。我们的软件将注入能够处理大量数据的人工智能特性。计算机将变得无所不在;不再装在一个小盒子里,而是可以从一个地方的任何地方访问。该界面对任何人来说都更容易,允许无缝的类似人类的语音交互。因此,工作将从信息的采集、处理和呈现转向人工智能服务的管理,人工智能服务将代表我们接管大多数这些任务。随着先进机器人的出现,即使是手工任务也将转向半手工任务。自动化也将使许多手动过程变得多余。在不可能的情况下,外骨骼将帮助人类搬运重物,而不会危及他们的健康。
专家们为什么要担心人工智能?
专业化一直是人类的领域,因为要实现它;一个人需要多年的学习和经验。然而,现在情况发生了变化。互联网包含大量信息,因此允许人工智能系统处理这些信息并从中学习。这个过程相当于一个人随着时间的推移不断学习和积累经验。唯一不同的是,对于机器来说,这发生在几个小时或几天内。如果我们只看一个例子,2018 年,一个由 20 名专攻公司法的律师组成的团队与一个人工智能展开了对抗。他们每个人都有五份保密协议,他们必须找出任何错误。律师们*均花费一个半小时来完成这项任务,并且达到了 85%的准确率。另一方面,合法的人工智能在 26 秒内获得了 94%的准确率。差异是巨大的,它表明每一份工作,即使是高薪工作,都将受到人工智能的影响。当然,我们不会很快看到机器人律师在法庭上辩论,但人工智能系统将开始协助律师完成日常任务。
管理者能做些什么来跟上时代?
马尔科姆·Ⅹ曾经说过,“未来属于今天为它做准备的人”。有些人已经在梦想和设计明天的解决方案。技术已经成熟,我们拥有处理能力,终于有了拥抱人工智能革命的政治意愿。它接管只是时间问题。所以管理者需要迈出第一步,学习人工智能。如果有疑问,他们应该寻求人工智能专家,他们可能会惊讶于人工智能可以为他们的组织带来的巨大节约。这个过程本身也相当简单,它遵循一些明确定义的步骤。首先,重要的是开始教育人们什么是人工智能。教育过程必须从最高层开始,向下到组织层级的所有级别。第二,组织进行人工智能准备审计,以确定组织在采用人工智能方面的状态。然后,与所有利益相关者进行协商,以确定潜在的人工智能案例研究。然后,根据可行性、所需投资和潜在回报,与管理层一起订购这些案例研究。然后,管理层简单地决定实施哪些项目。它们是在内部实施还是外包,实际上取决于复杂性和组织中可用的专业知识。人工智能专家将在那里监督项目的运行。完成后,选择并执行另一个更有雄心的项目。如此循环下去,直到组织设法用人工智能来增强其流程。
人工智能将会或不会做什么?
人工智能非常擅长以令人难以置信的速度和惊人的精度处理重复的任务。正因为如此,它可以很容易地取代几乎任何具有这些特征的任务。试想一辆自动驾驶汽车,驾驶员必须观察周围发生的事情(重复性工作),他必须立即注意到任何异常(以不可思议的速度),并采取果断行动(以惊人的精度)。通过观察这些特征,人们可以快速确定某项工作是否存在风险。
另一方面,AI 还是不善于处理人。当人们交流时,他们不仅通过言语,还通过社会规范。像话轮转换、打手势、表现出同理心和其他许多不成文的规则。这些是我们在社区中成长时学到的东西。但是对于一台机器来说,这些事情是不自然的,因为它缺乏社会背景,必须有人教它们。在过去的十年里,人机交互取得了巨大的进步,但是我们仍然远远没有达到人类交流的自然程度。人们不能指望让机器人来照顾人类病人,因为它无法处理这种情况,当然不是医疗方面,而是人的方面。
我们今天拥有的最令人印象深刻的 AI 是什么?
今天最令人印象深刻的人工智能无疑是计算机视觉。这是人工智能的一个子领域,在这个领域中,计算机设法持续击败人类水*。无论是识别医学图像中的癌细胞,还是识别视频中的物体或人,或者只是为自动驾驶汽车解释道路,计算机视觉在过去十年中都取得了巨大的飞跃。毫无疑问,如果没有深度学习算法的进步,这是不可能的。然而,这些算法将很快达到它们的极限,因此,研究人员总是在寻找可能的改进。毫无疑问,量子计算是一项非常有前途的独特技术,它将使这些算法超越我们的想象。仅举一个例子来说明它的巨大威力,谷歌设法将量子计算用于一个特殊的数学问题。系统设法在 3 分钟多一点的时间内解决了这个问题。考虑到当今最强大的超级计算机完成同样的任务大约需要 10,000 年,这个结果是一个巨大的进步!
人工智能会超越人类智慧吗?
智力是一种很难定义的属性。以至于我们没有一个一致的定义,然而我们人类非常擅长给智慧生物贴标签。通常,我们会将任务与人类可以完成的任务联系起来,如果另一种动物或机器可以复制这些动作,那么我们就将它们称为智能。
如果你执行个别任务,如下棋、分析视频和许多其他任务,人工智能不仅比人类更好,而且在某些情况下,它还达到了超人的水*。这个概念被称为狭义人工智能,因为它能够非常好地处理*距离任务。然而,如果你让一位人工智能国际象棋大师讲述纽约的当前天气,系统会惨败,因为这个请求超出了它的设计功能。
要超越人类智能,需要人工通用智能。这种智能类似于人的智能,可以同时处理多个不同的请求。虽然在过去的几十年里有很多研究,但现实是我们仍然非常遥远。当然,随着量子计算等新算法和技术的兴起,这一切都可能改变。
人工智能会有感知能力吗?
感知是感知或感觉事物的能力。这是一个我们人类很好理解的概念,但我们发现很难定义我们如何做到这一点。想象一下疼痛,以其原始的形式,它是一个信号,从我们身体的一部分发送到我们的大脑,大脑为我们解释它。这难道不类似于通过电线向机器的中央处理器发送电子信息吗?
当然,疼痛是我们非常了解的东西,但其他感觉很难复制,因为我们还没有完全了解它们。因此,最终,人工智能将变得有知觉。然而,最大的问题是,人工智能是否和人类一样。有些人会争辩说,它不是,也永远不会是。这种说法可能是正确的,但即使不同,也不一定是劣等的。试想一架飞机,它不是一只鸟,运作方式不同,但它能飞,它能携带巨大的负荷,并达到令人难以置信的速度。潜艇也一样,它不是鱼,工作方式不同;然而,它可以游到难以想象的深度。所以,是的,我相信人工智能最终会达到感知,但它可能是不同的一种。
这篇文章最初发表在 https://www.businesstoday.com.mt上请在下面留下你的想法,如果你喜欢这篇文章,请随时关注我🐦推特,🔗 LinkedIn 或者😊脸书。
关于马耳他及其如何成为世界上人工智能排名前 10 位的国家的案例研究
towardsdatascience.com](/how-to-create-a-world-class-ai-national-strategy-in-10-steps-eec5bc1f91fd) [## 人为的不人道
几个月前,菲利普·拉雷神父出版了一本名为《人造人类》的书。它讨论了对…的需求
towardsdatascience.com](/artificial-inhumanity-a8d3c9ea142c)
阿列克谢·丁力教授 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他出版了几本同行评审的出版物,并且是马耳他的一部分。由马耳他政府成立的人工智能工作组,旨在使马耳他成为世界上人工智能水*最高的国家之一。
Word2Vec 实现
如何使用 numpy 和 python 实现 Word2Vec
本文是关于一种非常流行的单词嵌入技术 Word2Vec 的实现。它是由谷歌的托马斯·米科洛夫实现的。
内容:
概念
- 目标
- 介绍
- 核心理念
- 体系结构
B —实施
- 数据准备
- 模特培训
- 模型推理和分析
目标
本文的目的是使用 numpy 展示 python 中 Word2Vec 的内部工作方式。我不会为此使用任何其他库。这个实现不是一个有效的实现,因为这里的目的是理解它背后的机制。你可以在这里找到官方报纸。
介绍
计算机只理解数字语言。我们将文本数据编码成数字的方式对结果影响很大。一般来说,有 3 种技术可以用来完成这项任务。
其中,word2vec 在 NLP 任务中表现得非常好。这个概念背后的核心思想非常简单,但却能产生惊人的效果。
核心理念
“看一个人交的朋友就知道他是谁”
― 伊索
这是一句众所周知的谚语。word2vec 也主要基于这个想法。一言既出,驷马难追。这听起来如此奇怪和有趣,但它给出了惊人的结果。让我们试着多理解一点。
一些例句:
- 你在花园里辛勤劳动的回报显而易见。
- 保持我的房间整洁是一件困难的工作。
- 艰苦的工作开始对他产生影响。
在这里,我们可以很容易地看到,“努力”和“工作”这两个词出现的位置非常接*。作为人类来说,这似乎很容易观察到,但对于计算机来说,这是一项非常困难的任务。因此,当我们将这些单词矢量化(将单词转化为数字)时,它们作为数字的表示应该是相似或接*的,这似乎是显而易见的。这正是 word2vec 所要实现的,并且取得了非常好的结果。说够了,现在是我们动手的时候了!
体系结构
因此,在理解了核心思想之后,我们知道该算法是基于识别彼此邻*的单词。换句话说,我们可以说,如果计算机试图学习单词“hard”和“work”在彼此附*出现,那么它将据此学习向量。
如果我们说我们的“目标”单词是“硬的”,我们需要学习一个好的向量,我们向计算机提供它的邻*单词或“上下文”单词,在这种情况下是“工作”,在“the,began,is 等”中。
有两种主要的架构试图了解上述内容。跳过 gram 和 CBOW
:这样我们就了解了目标词和语境词的概念。该模型试图学习每个目标单词的上下文单词。
图 1:跳过 gram 架构。演职员表
直觉:
正文:['成功的最佳途径是努力工作和坚持']
因此,对于该模型,我们的输入如下:
- 目标词:最好。上下文词:(方式)。
- 目标词:方式。现在我们有两个词,一个在前面,一个在后面。所以在这个场景中,我们的上下文单词将是: (Best,to) 。
- 目标词:到。现在我们也有两个词,一个在 I 之前,一个在 I 之后,即(成功之路)。但如果我们再想一想,那么“to”和“is”可以在彼此相邻的句子中找到。比如“他要去市场”。因此,如果我们将单词“is”包含在上下文单词列表中,这是一个好主意。但现在我们可以争论“最好”或“通过”。于是就有了“窗口大小的概念。窗口大小是我们决定要考虑多少邻*单词的数字。因此,如果窗口大小为 1,那么我们的上下文单词列表就变成了 (way,success) 。并且如果窗口大小是 2,那么我们的上下文单词列表变成(最佳,方式,成功,是)。
- 类似地,我们可以列出其余的单词
我们看到这里有一个输入层、一个隐藏层和一个输出层。我们还可以看到有两组权重(W,W `)。
CBOW: 语境包词。从概念上来说,这与 skip-gram 正好相反。这里我们试图从上下文单词列表中预测目标单词。因此,对于我们的示例,我们将输入为(最佳、方式、成功、是),我们需要从中预测到。
图 2: Cbow 模型架构
我们可以看到,这与跳格模型正好相反。
实现进程
在本文中,我将实现跳格模型。
数据准备
为了训练一个模型来学习单词的良好向量,我们需要大量的数据。但是在本文中,我将尝试展示一个非常小的数据集的工作原理。数据集由取自维基百科的杰弗里·阿彻各种故事的情节组成。
步骤 1:从文件中读取数据
解释:
- 第 2–4 行:将文本文件的内容读取到列表中
- 第 7–8 行:只保留字母,删除每行中的其他内容
- 第 9–17 行:重复句子中的每个单词,如果指定了停用词,则删除停用词
第二步:生成变量
我们将需要一些变量,这些变量将在后面的章节中派上用场。
*word_to_index : A dictionary mapping each word to an integer value {‘modern’: 0, ‘humans’: 1} index_to_word : A dictionary mapping each integer value to a word {0: ‘modern’, 1: ‘humans’}corpus : The entire data consisting of all the words vocab_size : Number of unique words in the corpus*
解释:
- 第 10 行:将每个单词转换成小写
- 第 12–15 行:用这个单词更新字典,如果这个单词还没有出现在字典中,就进行计数
该代码的输出将给出:
*text = ['Best way to success is through hardwork and persistence']Number of unique words: 9word_to_index : {'best': 0, 'way': 1, 'to': 2, 'success': 3, 'is': 4, 'through': 5, 'hardwork': 6, 'and': 7, 'persistence': 8}index_to_word : {0: 'best', 1: 'way', 2: 'to', 3: 'success', 4: 'is', 5: 'through', 6: 'hardwork', 7: 'and', 8: 'persistence'}corpus: ['best', 'way', 'to', 'success', 'is', 'through', 'hardwork', 'and', 'persistence']Length of corpus : 9*
第三步:生成训练数据
在看代码之前,让我们先了解一些概念。
- One-hot-vector:基本上这是一种用 0 和 1 对数据进行编码的方法。因此,我们的 one-hot-vector 的大小将为 2,因为我们有两个单词,我们将有两个单独的向量,一个用于 hi,一个用于 john。例如:(word: hi,one-hot-vector: [1,0]),(word: john,one-hot-vector: [0,1]
以下代码为我们的数据生成一个热向量:
解释:
*text = ['Best way to success is through hardwork and persistence']Window size = 2, Vocab size = 9 We will set the indices as 1 according to the word_to_index dict i.e best : 0, so we set the 0th index as 1 to denote naturalTarget word = best
Context words = (way,to)
Target_word_one_hot_vector = [1, 0, 0, 0, 0, 0, 0, 0, 0]
Context_word_one_hot_vector = [0, 1, 1, 0, 0, 0, 0, 0, 0]Target word = way
Context words = (best,to,success)
Target_word_one_hot_vector = [0, 1, 0, 0, 0, 0, 0, 0, 0]
Context_word_one_hot_vector= [1, 0, 1, 1, 0, 0, 0, 0, 0]*
有一种替代方法来生成上下文 _ 单词 _ 一个 _ 热 _ 向量。
*Target word = best
Context words = (way,to)
Target_word_one_hot_vector = [1, 0, 0, 0, 0, 0, 0, 0, 0]
Context_word_one_hot_vector = [0, 1, 0, 0, 0, 0, 0, 0, 0],[0, 0, 1, 0, 0, 0, 0, 0, 0]*
我们有两个不同的列表,而不是在一个列表中显示索引。但这种方法的问题是,如果我们的数据量增加,它将占用大量空间。我已经用 python 脚本说明了这一点。参考代码查看不同之处。
现在我们有了为目标单词和上下文单词生成的向量。为了训练模型,我们需要(X,Y)形式的数据,即(目标单词,上下文单词)。
这是通过以下代码实现的:
解释:
*text = ['Best way to success is through hardwork and persistence']*
- 第 7 行:迭代语料库
- 第 9 行:将第 I 个单词设置为目标单词
- 第 14,21,27 行:检查第 9 行的第 I 个单词是(first :Best),(middle : way)还是(last : persistence)单词的条件。
- 第 17 行:如果是第一个单词,获取接下来的 2 个(window_size =2)单词,并将它们设置为上下文单词
- 第 21 行:如果是最后一个单词,获取前面的 2 个(window_size =2)单词,并将其设置为上下文单词
- 第 30,37 行:如果我们的第 I 个单词是中间单词,那么我们需要在第 I 个单词之前获取 2 个(window_size =2)单词,在第 I 个单词之后获取 2 个(window_size =2)单词,并将所有 4 个单词都设置为上下文单词。如果在第 I 个单词之前或之后只有 1 个单词,我们只能得到 1 个单词。
示例:
***************************************************
Target word:best . Target vector: [1\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0.]
Context word:['way', 'to'] .
Context vector: [0\. 1\. 1\. 0\. 0\. 0\. 0\. 0\. 0.]
**************************************************
Target word:way . Target vector: [0\. 1\. 0\. 0\. 0\. 0\. 0\. 0\. 0.]
Context word:['best', 'to', 'success'] .
Context vector: [1\. 0\. 1\. 1\. 0\. 0\. 0\. 0\. 0.]
**************************************************
Target word:hardwork . Target vector: [0\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 0.]
Context word:['through', 'is', 'and', 'persistence'] .
Context vector: [0\. 0\. 0\. 0\. 1\. 1\. 0\. 1\. 1.]
**************************************************
Target word:and . Target vector: [0\. 0\. 0\. 0\. 0\. 0\. 0\. 1\. 0.]
Context word:['hardwork', 'through', 'persistence'] .
Context vector: [0\. 0\. 0\. 0\. 0\. 1\. 1\. 0\. 1.]
**************************************************
Target word:persistence . Target vector: [0\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 1.]
Context word:['and', 'hardwork'] .
Context vector: [0\. 0\. 0\. 0\. 0\. 0\. 1\. 1\. 0.]*
模特培训
图 3:跳跃图的训练
上图显示了一个神经网络是如何被训练的,在这个例子中是一个 skip-gram 模型。这里我们可以看到只有一个隐藏层。当我们在深度学习中训练一个神经网络时,我们往往会有几个隐藏层。这就是这个跳过程序工作得如此好的地方。尽管只有一个隐藏层,但这是一个最先进的算法。
正向传播
这里我们有以下参数:
- 输入:我们给模型的输入。我们场景中的目标词
- W_1 或 weight_inp_hidden:第一组权重与输入相乘得到隐藏层。
- W_2 或 weight_hidden_output:第二组权重乘以隐藏层。
- Softmax 层:这是在 0 和 1 之间挤压输出概率的最后一层。关于 softmax 函数的一个很好的解释可以在这里找到。
训练错误:
现在,一旦我们完成了一轮前向传播,我们就会得到一些输出值。所以很明显,和初始值相比,我们的预测会有一些误差。
解释:这是反向传播,以更新下一次迭代的权重
*Example: below if we have 2 context words. These are not actual values.These are just for showing how the error is calculatedcontext_words = [1 0 0 1 0]y_pred = [9 6 5 4 2]So if we break the context_word vector : [1 0 0 0 0] and [0 0 0 1 0] . 1 at index 0 and 3The error should be calculated as :diff_1 = y_pred - context_word_vector_1 =
[9 6 5 4 2] - [1 0 0 0 0] = [8 6 5 4 2]diff_2 = y_pred - context_word_vector_2 =
[9 6 5 4 2] - [0 0 0 1 0] = [9 6 5 3 2]Total_error = diff_1 + diff_2(column_wise) = [17 12 10 7 4]Since our context vector has only 1 array , we implement the above as:index_of_1_in_context_words -> **Line (6,7)**
A dictionary which has the index of 1's in the context_word_vector -> {0: 'yes', 3: 'yes'}number_of_1_in_context_vector -> A count for the above -> 2We loop the y_pred array and do the calculations as:for i,value in enumerate(y_p):**Line(13,14)** if the ith index of y_pred has a 1 in context_word_vector:
total_error[i] -> i:0 . y_pred[i]:9\. -> (9-1) + (1*9)
->error_calculated: 17
total_error[i] -> i:3 . y_pred[i]:4\. -> (4-1) + (1*4)
->error_calculated: 7**Line(15,16)** else:
total_error[i] -> i:1 . y_pred[i]:6\. -> 6*2
->error_calculated: 12
total_error[i] -> i:2 . y_pred[i]:5\. -> 5*2
->error_calculated: 10
total_error[i] -> i:4 . y_pred[i]:2\. -> 2*2
-> error_calculated: 4total_error -> [17 12 10 7 4]*
反向传播
利用上面计算的误差,我们需要更新权重(w1 和 w2 ),以便我们的网络尝试纠正该误差。
这里的是一个很好的链接,解释了反向传播的导数方程。
最后损失计算
损失计算如下:
图 4:损失函数。学分
如果我们稍微深入地观察损失函数 E,我们会发现,在给定 WI(输入单词)的情况下,我们正试图优化找到正确上下文单词 p(WO,1,WO,2,,WO,C)的概率。因此,当我们更接*为每个给定的目标单词找到正确的上下文单词的分布时,损失将会减少。
解释:
损失函数由两部分组成。
- 第一部分:我们取一个负值,其中上下文单词的值为 1
- 第二部分:我们取一个 u 的 exp,这是我们用隐藏层乘以第二组权重后得到的输出。
*u : [ 0.3831286 0.89608496 2.69426738 -1.60230182 0.45482701 0.73644591 1.10365796 1.1675781 -0.78555069]context: [0, 1, 1, 0, 0, 0, 0, 0, 0]sum_1 = -(0.89608496 + 2.69426738)sum_2 = number_of_context_words * np.log(np.sum(np.exp(u)))total_loss = sum_1 + sum_2*
超参数
到目前为止,我们可以看到在这个过程中涉及到许多变量。所以训练的一个很大的部分是找到给出最佳结果的正确的变量集。我们将逐一讨论这些变量。
- 窗口大小:这是我们为每个目标单词准备的上下文单词的数量。
- 学习率:如果我们看到反向传播代码,我们会看到权重与学习率相乘。这是称为梯度下降的优化过程的一部分。一个好的学习率定义了我们的模型多快达到它的最优值。
- 纪元:假设我们有 100 个训练例子。因此,当我们对每 100 个记录执行上述整个过程时,这被计为 1 个时期。
- 维度:当我们的最终模型准备好了,我们得到了每个单词的向量。该向量可以具有范围从 50 到 300 各种维数。
- 停用词:这些词像 a,an,the。它们本身没有任何意义,因此我们可以检查模型在有和没有它们的情况下是如何工作的。
在保持学习率为 0.01 的情况下,我做了一些有趣的实验,包括窗口大小、时期、尺寸、停用词
模型推理和分析
为了获得每个单词的单词向量,在最终训练之后,使用第一组权重,即 weight_1 来检索每个单词的向量。
为了找到相似的单词集,使用余弦相似度。这是一种度量标准,用来衡量多维空间中两个向量的相似程度。基本上,它测量两个向量之间的角度,以确定它们有多相似。很好的解释可以在这里找到。
现在我使用了两组不同的数据,一组是单行文本,另一组是文本语料库。
用单行文本作为输入进行推理
*Text : [‘best way to success is through hardwork and persistence’]*
下面显示的散点图是二维的。这是通过降维实现的。我已经为它使用了 T-SNE 。下图并没有给出一个确切的图像,因为我们把几个维度压缩成了 2 个。
不同维度的散点图:
图 5:变暗
我们可以在这里看到“最佳”和“方式”是多么接*。即使一行文字对于一个模型来说是非常稀缺的,但是它可以学习很好的嵌入。
不同窗口大小的散点图:
图 6:不同的窗口大小
用相对较大的语料库进行推理
为了了解这个模型的效果,我打印了一个相似度矩阵,用于一些拥有更大语料库的单词
变化尺寸:
**
图 7:变维相似矩阵
这里要注意的一件事是,对于更高的维度,相似性的数字很低。这背后的原因是语料库非常小,只有大约 700 个独特的单词。所以要学习更高维度的嵌入,需要一个庞大的语料库。word2vec 算法是在数百万规模的语料库上训练的。
停用词:
**
图 8:停用词效应
该模型在没有停用词的情况下似乎表现得更好,因为每个时期的损失曲线都更好。为了更好地理解它,我们需要在更大的语料库上进行尝试。
上面的散点图可以在我的 github 链接这里找到。
进一步改进:
word2vec 的训练是一个计算量非常大的过程。由于有数百万字,训练可能要花很多时间。对抗这种情况的一些方法是负采样和分级 softmax。理解这两者的好链接可以在这里找到。
完整的代码可以在我的 github 资源库中找到:
https://github . com/Rahul 1728 jha/Word 2 vec _ Implementation/blob/master/Word _ 2 _ vec . ipynb
请留下任何澄清或问题的评论。
快乐学习😃
如何用 GatsbyJS、GitHub 和 Netlify 创建和部署一个超快的网站
完整的指南,以建立和部署一个非常快速和现代化的网站免费(自定义域)。
伊戈尔·米斯克在 Unsplash 上的照片
我创建了一个个人博客网站,展示我的一些创意项目。这是一个相当坎坷的学习曲线,因为我一路上有很多问题和考虑。不幸的是,我找到的大部分教程都是零散的,所以我想我应该写一个详细的教程。如果你不是 web 开发人员,但有一些编码知识,并且想免费建立一个现代化的个人网站(没有 Wordpress 或网站建设者),这篇文章就是为你准备的!
这篇文章的目的是一步一步地向你展示如何创建、部署和配置一个简单的博客/作品集网站,并使用你自己的自定义域名。我们开始吧!
我的攻击计划(即工具设置)
一开始,我在我的小博客/作品集网站的几个选项中来来回回:
- 从头开始编写我的网站
- 使用静态站点生成器
- 使用 Wordpress/其他 CMS。
下面是我在搜索了这么多帖子和网站后创建的一个概述。我在以下几个方面对它们进行比较: (1)灵活性&自由度,(2)性能,(3)需要的知识和技能,(4)安全性,(5)可扩展性和维护 。这将有望帮助你回答这个百万美元的问题:选择什么:
建立投资组合网站的选择。来源:作者。
在分析了这些选择的利弊之后,我决定选择静态站点生成器(SSG)。这是因为我可以编码,并希望对我的网站的底层内容有更多的控制。此外,我只是想要一个简单整洁的博客网站,所以安装大量的 Wordpress 插件对我来说听起来不是很有吸引力。
具体来说,我使用了 GatsbyJS ,因为我对 JavaScript 和 React 更加熟悉和熟悉,这是 Gatsby 所基于的语言。此外,它是一个已经成熟的 SSG,拥有强大的功能和插件生态系统。如果你有兴趣了解更多关于其他 SSG 的信息,这里有一个目前顶级 SSG 的比较。
什么是静态站点生成器?
静态站点生成器是一个应用程序,它获取内容(通常用 Markdown 编写),将其应用于模板,并生成一组纯静态的 HTML 文件,准备交付给访问者。
接下来,我们还需要解决网站的其他问题,即域名、托管和部署。以下是我的设置:
工具安装。来源:作者。
如果你想让数据库操作更加用户友好(例如,当你的网站落入非技术用户手中,他们将很难浏览代码仓库),你可以考虑将你的 SSG 与无头 CMS 配对,例如 Contentful 。但是这是可选的,没有它你也可以做得很好。
设置您的开发环境
在构建您的第一个 Gatsby 站点之前,您需要进行一些安装。
#1.节点. js
由于 Gatsby 是用 Node.js 构建的,我们需要安装它才能使用 Gatsby。如果你使用的是 Windows 操作系统,你可以简单地下载并安装到你的机器上。
#2.饭桶
我们将需要 Git 来下载 Gatsby“starter”(带有一些默认配置的部分构建的站点),并在稍后使用版本控制+托管我们的项目。如果你还没有它,你可以在这里为 Windows 安装它。
#3.盖茨比 CLI
Gatsby CLI 工具允许您快速创建新的 Gatsby 支持的站点,并运行命令来开发 Gatsby 站点。您可以使用 npm 进行全局安装。打开您的终端并运行以下命令:
npm install -g gatsby-cli
您还可以查看可用于 Gatsby CLI 的命令:
gatsby --help
开始建立你的网站
Gatsby 提供了许多(免费的)预建启动器供您选择,以满足您网站的目的,包括博客网站、在线商店或简单的投资组合网站。假设你想使用这个虚构的博客主题,它是开源的,你可以简单地进入终端,将目录切换到你想要存储你的网站的文件夹,并从 Git 下载代码(注意,你可以给你的网站文件夹起任何名字,而不是mynewwebsite
):
gatsby new mynewwebsite [https://github.com/dvzrd/gatsby-sfiction](https://github.com/dvzrd/gatsby-sfiction)
下载完成后,您可以使用本地主机为站点提供服务:
gatsby develop
现在,如果你在 http://localhost:8000/ 打开你的网页浏览器,你应该会在那里看到这个网站。
接下来,您可能想要更改gatsby-config.js
文件中的默认值,以适合您的个人资料信息。你应该看到一个文件夹,里面有 markdown 文件(.md
)中的所有帖子,在那里你可以开始创建自己的帖子!如果您更熟悉 React、HTML 和 CSS,您还可以深入 React 组件并调整它们的外观,以及添加新的动态功能。
gatsby 文档和教程为你理解和开始操作 Gatsby 启动器提供了一个很好的基础。
此外,在 markdown 中写帖子相当容易。这里有 markdown 语法文档供你参考。
上传到 Github
一旦你对新网站的配置和基本功能感到满意,我们就进入有趣的部分——托管和部署你的网站。
在 Github 上创建一个存储库,并上传您的网站文件夹。由于您的 Gatsby 网站文件夹包含几个子文件夹,使用 Github 网站并尝试将您的文件夹拖放到 Git repo 中可能行不通。因此,最简单的方法是使用 Git Bash。首先,您将光盘放入您的网站文件夹,然后键入以下内容:
git commit -am "Uploading files"
git remote add origin [https://github.com/yourUsername/yourRepository.git](https://github.com/yourUsername/yourRepository.git)
git push -u origin master
git push origin master
现在,您的所有文件都应该上传到您的 Git repo。我们现在准备部署我们的网站!
部署到网络
在这一节中,我将解释如何使用 Netlify 免费部署您的个人网站。
Netlify 与 Github 页面
注意,另一个免费选项是使用 Github 页面,事实上,许多人都将其用于个人网站。这也是一个很好的选择——简单直接地让你的网站开始运行。然而,从长远来看,使用 Netlify 可能会更好,因为它提供了额外的功能。此外,如果您需要在未来扩大您的网站,有付费计划供您选择。
下面是 Netlify 做的一个比较(可能有点偏,但只是给你一个思路):
Github Pages vs. Netlify。来源:https://www.netlify.com/github-pages-vs-netlify/
实际上,我见过一些专业开发人员和精通编码的人在他们的博客中使用 Netlify(这里的和这里的)。对我来说,这是另一个证明,它是静态页面的一个很好的选择。
什么是网络生活
它是一家云计算公司,为 web 应用程序和静态网站提供托管和无服务器后端服务。根据项目的规模,他们为网站托管提供了几种方案。对于个人网站,使用免费选项就可以了。
从 Github 部署您的站点
首先,你需要用你的 Github 账户在 Netlify 网站上注册。这将连接您的 Netlify 帐户和 Github。
你可以按照这个一步一步的教程从 Github 部署你的站点。一旦你完成了,你应该有这样一个概述:
概述网络生活网站。来源:作者。
注意,这里我已经有了一个自定义域名(。com)。在你的情况下,很可能你的网站在这个阶段仍然有一个random-name.netlify.app
域名。你可能暂时还能接受这个域名,但是如果你已经拥有一个域名,你当然可以配置它来连接到你的网站。
使用自定义域
要自定义您的域名,请进入设置>域管理>添加域别名。
在 Netlify 上配置自定义域。来源:作者。
一旦你添加了你的自定义域名,接下来要做的就是去你的域名注册商那里配置你的域名。不同的主要注册商有不同的具体说明,但一般来说,您需要配置以下内容:
- A 主机:104.198.14.52(这是网络服务器 IP 地址)
- CNAME :【你的网站名称】. netlify.app(比如我的情况就是 thuhienvu.netlify.app)
- 名称服务器:
dns1.p01.nsone.net
dns2.p01.nsone.net
dns3.p01.nsone.net
dns4.p01.nsone.net
确保你保存了所有东西。到目前为止,您应该能够看到您的网站与您的自定义域生活!恭喜你!😃
但是等等,你可能会在浏览器上看到一些奇怪的东西:
来源:https://www . digicert . com/blog/not-secure-warning-what-to-do/
这是因为您的站点仍在使用 HTTP 协议,该协议无法提供安全连接。如今,互联网上的所有网站都必须使用 HTTPS 协议,数据在互联网上传输时都要加密(“S”代表“安全”)。传统上,你必须为你的网站购买一个 SSL 证书。然而,Netlify(还有 Github Pages)现在提供免费的 SSL/TLS 证书。
向下滚动到 HTTPS 部分(设置>域名管理> HTTPS )。现在,您只需点击一下鼠标,即可为您的网站提供 SSL/TLS 证书。很简单,不是吗?
如果您看到出现某种错误,很可能是因为证书实际工作需要一些时间。与此同时,你可以喝杯咖啡,你的网站应该很快就能正常工作了。
更新您的网站
在本地对您的网站进行更改时,您可以通过运行以下命令来查看网站在本地的外观(在 http://localhost:8000/ ):
gatsby develop
要将您的更改推送到您的网站,首先,您需要将更改提交并推送到您的 Git repo。之后,在 Netlify 网站上,进入Deploys
选项卡,点击触发部署>部署站点按钮,如下所示:
在 Netlify 上部署。来源:作者。
几分钟后,您的网站应该会有新的变化。您还可以看到部署日志在站点部署时展开。如果你想了解更多的细节,这里有一个完整的教程。
祝贺和最后的想法
我想首先祝贺你得到你的网站生活!
在这篇文章中,你学会了如何:
- 使用入门工具创建一个盖茨比网站
- 使用 Github 托管和版本控制您的站点
- 使用 Netlify 从 Github 部署您的站点
你现在有了自己的网站,用 Git 控制版本,有了自己的域名。全部免费托管!最棒的是,你可以完全控制你的网站,包括代码、外观和所有附加功能。
希望这个帖子有用。我很想在评论区听到你的想法,以及你是如何建立个人网站的。
带精灵的 A-Z Julia 端点
关于使用 Julia、Genie 和 Lathe 部署端点的介绍。
(茱莉亚标志 src =http://julialang.org)
任何有抱负的数据科学家应该能够完成的最重要的任务之一是创建和部署一个端点。端点是现代机器学习的主干,也是将模型转化为真实生产环境的最简单方法。为了在端点部署模型,您首先需要选择一个 web 框架来创建该端点。对于 Python 和 R 来说,选择是非常明显的,并且很容易找到一个合适的 web 框架来满足您的需求。
但是朱莉娅呢?
尽管 Julia 的生态系统肯定没有 Python 或 R 的那么成熟,但是 Julia 确实有一些有趣的选项来部署您的模型。首先,你总是可以依靠 PyCall。这将允许您使用像 Flask 和 Django 这样的 Python 库来进行部署,而不必担心使用与这两个选项相比仍然相对年轻的 Julia 项目。但是对于那些渴望更高性能的人,我介绍
Genie.jl。
当然,与其他 web 框架相比,Genie 还很年轻,但是在我看来,它带来了更多有趣的想法,使得部署模型成为一项休闲活动。Genie 仍在 0.31.1 版本中,但你可能会惊讶于这项技术已经有多强大。今天,我将带你了解 Genie 的一切,从建立虚拟环境到序列化模型和在 Ubuntu 上部署基于 Genie 的 API。
建立模型
举个例子来说,关于一个模型没有什么是真正重要的。无论如何,我们将使用 Lathe 来创建我们的模型,因为与许多其他选项不同,Lathe 模型非常容易序列化和部署。对于今天的例子,我们将使用车床 0.1.2,但语法应该保持不变,直到至少车床 1.0 的发布。第一件事是首先,让我们找到一些数据!
二手车和摩托车数据
www.kaggle.com](https://www.kaggle.com/nehalbirla/vehicle-dataset-from-cardekho/data#)
我选定的数据集是来自 Kaggle 的“车辆数据集”。我选择这个主要是因为我对汽车感兴趣。此外,我对它们感到特别兴奋,因为下周我就要去买一幅德尔·索尔的画了。对于汽车人,我只想说一件事:
双收费 B20 交换。
回到数据科学的世界,我下载了我们的新数据集,现在我们可以读取它了。我们将使用 CSV.jl:
using CSV
df = CSV.read("car data.csv")
朱莉娅的趣事:虽然 DataFrames.jl 是 CSV.jl 的依赖项,但是每当我们导入 CSV 时,它都不会被预编译。换句话说,df 的类型是 DataFrame,它来自 DataFrames.jl,但是我们不能使用与此类型相关的任何方法,直到我们也导入 DataFrames。
using DataFrames
虽然肯定有其他方法可以删除你丢失的值,但这是一个有效的方法:
df = collect(skipmissing(eachrow(df)))
使用这种方法的一个优点是 collect()和 skipmissing()都是 Julia 语言中的基本方法。这意味着它们可以应用于任何类型,如果显式导入,甚至可以应用于您自己的类型。Eachrow()来自数据帧,只是用来把我们的 df 转换成可以迭代的东西。这样做的缺点是,我们将得到一个 DataFrame 行数组作为返回。
我们可以通过断言该数据的 DataFrame 类型来缓解这一问题。
df = DataFrame(df)
跳过这一步,我们不打算考虑统计测试,因为我们并不关心这个例子的准确性,所以接下来我们将继续分割我们的数据。为此,我们将使用来自 Lathe.preprocess 的 TrainTestSplit。在 Lathe 的不稳定版本中,我们需要设置 at 参数(float 设置为 75%),但在任何稳定版本中,情况都不是这样。
接下来,我们需要确定目标和特性。我认为比较 Kms_Driven 和 Selling_Price 是一个很酷的主意。然后我想也许这一年也会很酷,所以为什么不两个都做呢?
target = :Present_Price
feature1 = :Year
feature2 = :Kms_Driven
现在,让我们插入这些内容,以便从数据帧中获取实际阵列:
trainy = train[!,target]
testy = test[!,target]
trainX1 = train[!,feature1]
trainX2 = train[!,feature2]
testX1 = test[!,feature1]
testX2 = test[!,feature2]
现在我们将安装两个独立的车床模型:
using Lathe.models
model1 = LinearRegression(trainX1,trainy)
model2 = LinearRegression(trainX2,trainy)
得到两个预测:
yhat1 = model1.predict(testX1)
yhat2 = model2.predict(testX2)
现在我们将一起和单独测试它们的准确性。对于我们的验证指标,我们将使用*均绝对误差:
还不错!
让我们看看如果我们把两者结合起来会发生什么。我们将通过对 zip 循环中的所有预测进行*均来将两者结合起来:
yhati = [mean([pred1,pred2]) for (pred1,pred2) in zip(yhat1,yhat2)]
现在我们将比较所有的精度:
正如您可能已经预料到的,我们的新功能稍微降低了我们的准确性,因为这个模型没有对使用哪个值或对哪个值进行优先级排序做出任何逻辑决策。因此,我们将只使用第一个模型,因为它具有最好的准确性。为了序列化这个模型,我们将使用 JLD2。使用 JLD2,我们可以使用@save 宏将我们的模型保存为序列化的 JLD2 格式。
using JLD2
[@save](http://twitter.com/save) "mdl.jld2" model1
创建我们的端点
现在,我们将获取 JLD2 文件,并将其移动到一个新目录中。我将在 Bash 中这样做,但是当然,您也可以按照自己的意愿这样做:
mkdir CarPrice
mv mdl.jld2 ./CarPrice
现在,我们将为我们的端点创建一个目录。
mkdir endp
cd endp
现在我们将初始化一个 Genie 项目。为此,我们将输入朱莉娅·REPL,导入精灵,然后最后是 newapp_webservice()方法:
julia
using Genie
Genie**.**newapp_webservice("CarPricePredictor")
这将实例化一个新的 Pkg 环境,并为我们的 Genie 端点创建一个新的目录系统。它还将启动一个服务器,因此您可以继续访问您的本地主机(默认为 http://127.0.0.1:8000/ )并检查您的服务器!默认情况下,无法写入这些文件,因此您需要调整权限才能编辑它们。之后,我将我们的模型文件移动到端点的目录中,然后将它放在自己的名为 models 的文件夹中。现在,我们只需在由 Genie 生成的 routes.jl 文件中使用 JLD2 重新加载它:
using Genie.Routerroute("/") do
mdl = [@load](http://twitter.com/load) "models/mdl.jld2"
end
接下来,我们将从请求中请求一个参数实参,我们可以这样做:
using Genie.Routerroute("/") do
mdl = [@load](http://twitter.com/load) "models/mdl.jld2"
year = haskey([@params](http://twitter.com/params), :year)
end
现在,我们将根据数据进行预测,并返回结果。
using Genie.Routerroute("/") do
mdl = [@load](http://twitter.com/load) "models/mdl.jld2"
year = haskey([@params](http://twitter.com/params), :year)
return(mdl.predict(year))end
部署
为了部署这个模型,我们首先要把我们的文件放到我们的服务器上。为此,您可以使用 FTP、HTTP(通过 Git 或 Wget)或 STP。通常在这种情况下,您会使用 STP,但是因为我已经将我的文件提交给 Github,所以我会将它复制到我的服务器上的/var/www 目录中。
ssh emmett@(this_is_my_ip)
cd /var/www
git clone [https://github.com/emmettgb/CarPricePredictor](https://github.com/emmettgb/CarPricePredictor)
现在我们有两件事情要设置:
- 网络服务器
- 主管
对于我的网络服务器,我将使用 NGINX。我几乎什么都用 NGINX,因为它比 Apache 有一些优势,主要是它通常有更好的响应时间。如果你需要做出决定,我建议你选择你熟悉的那个。如果你对两者都不熟悉,那就用 NGINX 吧,因为它的配置更简单,而且以我的主观观点(以及许多指标)来看,它更好。使用 Apache 当然有优势,但是我不认为至少从尝试 NGINX 开始你会错过很多。
我们要在 NGINX 配置中做的是创建一个代理传递到我们的服务器将要运行的端口上,默认情况下是 8000。如果你在 VPS 上运行多个网络服务器,那么你可能需要使用更高的端口,比如 8001 或 8002。配置文件存储在/etc/nginx/conf.d 中,所以让我们创建一个新的配置:
sudo dnf/apt/pacman/man install nginx
sudo nano /etc/nginx/conf.d/carpredictor.conf
以下是从端口 80(默认 HTTP 协议端口)到端口 8000 的代理传递的配置示例:
**server** {
**listen** 80;
**server_name** your domain;
**location** / {
**proxy_pass** http://127.0.0.1:8000;
**proxy_set_header** Host $host;
**proxy_set_header** X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
如果这是你的第一台 NGINX 服务器,你必须解除 NGINX 默认站点的链接:
sudo unlink /etc/nginx/sites-enabled/default
接下来,我们需要设置一个主管。和 NGINX 一样,supervisor 的配置文件。我的服务器在 Ubuntu 上,尽管我痴迷于 RHEL,所以安装 supervisor 就像
sudo apt-get install supervisor
现在我们将创建一个新的配置。
sudo nano /etc/supervisor/conf.d/flask_app.conf
以下是我的主管配置:
[program:genieapp]
directory=/var/www/CarPricePredictor
command=. bin/server
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
stderr_logfile=/var/log/appname/lognameerr.log
stdout_logfile=/var/log/appname/lognamestdout.log
命令和目录是您应该在这里查看的两个参数。我们将把 SH 文件放在我们的 Genie 端点附带的 bin/server 中,这将自动启动一个我们可以使用的 Genie 服务器。我们还需要运行上述命令的目录,差不多就是这样。现在我们只需要重新加载我们的服务:
sudo nginx -s reload
sudo service supervisor reload
现在我们的端点已经部署好了!
结论
Julia 部署并不太难,最*已经变得更容易了。每当我第一次进入 Genie 时,文档是绝对糟糕的。幸运的是,随着时间的推移,这种情况已经发生了变化,现在这个工具比以往任何时候都更容易使用。车床模型也是我认为非常酷的一个方面。或者,您也可以使用车床部署管道。以下是为老版本的车床部署管道的教程:
旧版本和新版本的区别在于,现在管道只接受一个参数:
台阶。
所以为了做一个管道,你只需要做:
using Lathe.preprocess
scaler = Normalizer(xt)
using Lathe.models
mdl = LinearRegression(trainX,trainy)
pipl = Pipeline([scaler, mdl])
yhat = pipl.predict(xt)
很酷,对吧?
所以管道部署肯定是可行的,而且在 Julia 中使用车床也很酷。我很兴奋地看到这种方法能够在这方面使用车床进行机器学习到什么程度,因为管道肯定是 DS 生态系统的重要组成部分。
10 分钟内探索性数据分析的 A-Z
数据以各种形式出现,数量巨大。图片来自 Pixabay 佳能-eos
EDA 是迈向数据科学的第一步。
探索性数据分析 (EDA)无论是回归还是分类,都是任何模型最关键的阶段,但往往被轻描淡写或忽略。EDA 清楚地显示了数据以及不同特性或不同数据特性组合对输出的依赖性。
我去维基百科寻找更多信息,下面是它的定义:
探索性数据分析 (EDA)是一种分析数据集以总结其主要特征的方法,通常采用可视化方法。统计模型可以使用,也可以不使用,但 EDA 主要是为了查看数据在正式建模或假设检验任务之外能告诉我们什么。
现在,问题是如何执行 EDA。下面是使用一个例子来执行 EDA 的简单方法。
下面是帖子的流程,
- 数据集简介
- 查看数据
- 单变量分析
- 概率密度函数
- 累积密度函数
- 箱形图
- 小提琴情节
4.双变量分析
- 散点图
- 配对图
5.多变量分析
- 等值线图表
让我们开始吧!!
- 数据集介绍
先说几个常用术语:
- 数据集是所用数据的集合(通常是一张表)
- 数据点是数据集(如行)中的每个观察值
- 目标,也叫因变量或输出变量,是要预测或分析的变量。
- 特征,也叫-输入变量或自变量是用来确定因变量的一个变量或变量的集合。
让我们用从 Kaggle 设置的 Haberman 的生存数据来探索 EDA。
接受乳腺癌手术患者的存活率
www.kaggle.com](https://www.kaggle.com/gilsousa/habermans-survival-data-set)
属性信息:
1。手术时患者的年龄(数值)
2。患者手术年份(年份— 1900,数字)
3。检测到的阳性腋窝淋巴结数(数值)
4。存活状态(类别属性)1 表示患者存活了 5 年或更长时间,2 表示患者在 5 年内死亡
目的:
2。调查数据
import pandas as pd
data = pd.read_csv('haberman_data.csv')
导入熊猫来读取数据。使用 pandas 将 Kaggle 中的 CSV(逗号分隔值)文件分配到数据框中。
data.shape
输出:(305,4)
数据集有 305 个数据点,4 个特征
让我们看看数据如何,
data.head()
数据集中的前 5 个元素
这里,数据集没有任何标题(列名)。第一个数据点被作为标题。因此,我们需要添加一个头。
header_list=['age','op_year','axil_nodes','surv_status']
haberman_data = pd.read_csv('haberman_data.csv',names=header_list)
添加要素名称并将数据加载到数据框中。
haberman_data.head()
添加特征名称后数据集的前 5 个元素
现在,数据已经有了特征名称。
haberman_data['surv_status'].value_counts()
输出:
1 225
2 81
Name:surv _ status,dtype: int64
该数据是不*衡数据,这意味着“surv_status”的每个类别中的数据点数量不相似。
现在我们有了数据的图片,让我们开始进一步分析它。
3。单变量分析
单变量分析,顾名思义,就是简单的用一个变量进行分析。这种分析给出了变量出现的频率/计数,并让我们了解该变量在不同值下的分布。
3.1。概率密度函数(PDF) :
在 PDF 绘图中,X 轴是进行分析的要素,Y 轴是数据中特定 X 轴值出现的次数/频率。因此在 PDF 中出现了术语“密度”。
import seaborn as sns
sns.set_style("whitegrid")
Seaborn 是一个提供各种类型的分析图的库。
sns.FacetGrid(haberman_data,hue='surv_status',height=5).map(sns.distplot,'age').add_legend()
输出:
时代的 PDF
观察结果:
- 主要的重叠被观察到,所以我们不能清楚地说年龄对生存的依赖性。
- 粗略估计,20-50 岁的患者存活率稍高,75-90 岁的患者存活率较低。
- 年龄可以被认为是一个因变量。
sns.FacetGrid(haberman_data,hue='surv_status',height=5).map(sns.distplot,'op_year').add_legend()
输出:
运营年份的 PDF
观察结果:
- 重叠是巨大的。
- 运营年份本身并不是一个高度相关的变量。
sns.FacetGrid(haberman_data,hue='surv_status',height=5).map(sns.distplot,'axil_nodes').add_legend()
输出:
腋窝淋巴结的 PDF
观察结果:
- 0 淋巴结的患者生存概率高。
- 腋淋巴结可以作为因变量。
PDF 的缺点:在 PDF 中,我们无法准确说出有多少个数据点在某个范围内/低于某个值/高于某个特定值。
3.2。累积密度函数(CDF) :
要知道低于/高于特定值的数据点的数量,CDF 非常有用。
让我们从根据存活率的类别来分离数据开始。
survival_yes = haberman_data[haberman_data['surv_status']==1]
survival_no = haberman_data[haberman_data['surv_status']==2]
现在,让我们分析这些分离的数据集。
import numpy as np
import matplotlib.pyplot as plt
count, bin_edges = np.histogram(survival_no['age'], bins=10, density = True)
#count : the number of data points at that particular age value
#bin_edges :the seperation values of the X-axis (the feature under analysis)
#bins = the number of buckets of seperation
pdf = count/sum(count)
print(pdf)
# To get cdf, we want cumulative values of the count. In numpy, cumsum() does cumulative sum
cdf = np.cumsum(pdf)
print(cdf)count, bin_edges = np.histogram(survival_yes['age'], bins=10, density = True)
pdf2 = count/sum(count)
cdf2 = np.cumsum(pdf2)plt.plot(bin_edges[1:],pdf,label='yes')
plt.plot(bin_edges[1:], cdf,label='yes')
plt.plot(bin_edges[1:],pdf2,label='no')
plt.plot(bin_edges[1:], cdf2,label='no')
plt.legend()
#adding labels
plt.xlabel("AGE")
plt.ylabel("FREQUENCY")
输出:
[0.03703704 0.12345679 0.19753086 0.19753086 0.13580247 0.12345679
0.09876543 0.04938272 0.02469136 0.01234568]
[0.03703704 0.16049383 0.35802469 0.55555556 0.69135802 0.81481481
0.91358025 0.96296296 0.98765432 1\. ]Text(0, 0.5, 'FREQUENCY')
关于年龄的分离数据
观察结果:
- 大约 80%的数据点的年龄值小于或等于 60 岁
count, bin_edges = np.histogram(survival_no['axil_nodes'], bins=10, density = True)
pdf = count/sum(count)
print(pdf)cdf = np.cumsum(pdf)
print(cdf)count, bin_edges = np.histogram(survival_yes['axil_nodes'], bins=10, density = True)
pdf2 = count/sum(count)
cdf2 = np.cumsum(pdf2)plt.plot(bin_edges[1:],pdf,label='yes')
plt.plot(bin_edges[1:], cdf,label='yes')
plt.plot(bin_edges[1:],pdf2,label='no')
plt.plot(bin_edges[1:], cdf2,label='no')
plt.legend()
plt.xlabel("AXIL_NODES")
plt.ylabel("FREQUENCY")
输出:
[0.56790123 0.14814815 0.13580247 0.04938272 0.07407407 0.
0.01234568 0\. 0\. 0.01234568]
[0.56790123 0.71604938 0.85185185 0.90123457 0.97530864 0.97530864
0.98765432 0.98765432 0.98765432 1\. ]Text(0, 0.5, 'FREQUENCY')
腋窝淋巴结分离数据的 CDF,PDF
观察结果:
- 大约 90%的数据点具有小于或等于 10 的 axil_node 值
3.3。箱线图
在探索箱线图之前,一些常用统计术语是:
- median(第 50 个四分位数)是排序数据的中间值
- 第 25 个四分位数是排序数据中的值,其中 25%的数据小于它,75%的数据大于它
- 第 75 个四分位数是排序数据中的值,其中 75%的数据小于它,25%的数据大于它。
在箱线图中,下面的线代表第 25 个四分位数,中间的线代表中位数/第 50 个四分位数,上面的线代表第 75 个四分位数。晶须代表大多数图中的最小值和最大值或一些复杂的统计值。使用 seaborn 时,胡须不是最小值和最大值。
sns.boxplot(x='surv_status',y='age', data=haberman_data)
sns.boxplot(x='surv_status',y='axil_nodes', data=haberman_data)
sns.boxplot(x='surv_status',y='op_year', data=haberman_data)
输出:
<matplotlib.axes._subplots.AxesSubplot at 0x1795943de08><matplotlib.axes._subplots.AxesSubplot at 0x179594b4948>
<matplotlib.axes._subplots.AxesSubplot at 0x1795b18ac88>
年龄、腋窝淋巴结、手术年份的箱线图
3.4。小提琴剧情:
小提琴图是箱线图和密度函数的组合。
- 白点代表中间值。
- 较粗的黑线的边缘代表四分位数。
- 小提琴形结构的边缘代表最小值和最大值
- 形状的宽度表示该值处数据点的密度/频率。
sns.violinplot(x='surv_status',y='age', data=haberman_data)
plt.show()sns.violinplot(x='surv_status',y='op_year', data=haberman_data)
plt.show()sns.violinplot(x='surv_status',y='axil_nodes', data=haberman_data)
plt.show()
年龄,手术年份,腋窝淋巴结的小提琴图
观察结果:
- 75-90 岁的患者不太可能存活,30-40 岁的患者更有可能存活。
- 运营年度似乎没有给出确切的信息,因为它几乎*均分布在给定的几年中。
- 淋巴结值低的患者更有可能存活。
4。双变量分析:
在本节中,我们将一次使用两个独立变量来分析数据。
4。1.散点图:
散点图广泛用于比较两个变量,并帮助我们分析目标变量如何依赖于它们的组合。
在散点图中,X 轴代表一个自变量,Y 轴代表另一个自变量。
通过将目标变量赋予 seaborn 提供的面网格函数中的色调参数,可以用颜色编码来表示目标变量。
sns.FacetGrid(haberman_data, hue="surv_status", height=8) \
.map(plt.scatter, "age", "op_year") \
.add_legend();
输出:
年龄和操作年份散点图
sns.FacetGrid(haberman_data, hue="surv_status", height=8) \
.map(plt.scatter, "age", "axil_nodes") \
.add_legend();
输出:
年龄和腋窝淋巴结散点图
sns.FacetGrid(haberman_data, hue="surv_status", height=8) \
.map(plt.scatter, "axil_nodes", "op_year") \
.add_legend();
输出:
腋窝淋巴结散点图和手术年份
4.2。配对图:
结对图有助于用一行代码将所有变量相互比较。这可以被认为是所有可能的散点图。当特征数量较少时,可使用配对图。在这个有 3 个独立变量的例子中,配对图的数量是 9(3X3)。因此,对于任何具有 10 个特征的数据,配对图的数量将是 100。因此,当特征数量较少(~7)时,通常使用配对图。
这是一行代码:
sns.pairplot(haberman_data, hue="surv_status", height=5)
年龄、手术年份、腋窝淋巴结配对图
5。多变量分析:
在本节中,我们将使用多个变量来分析数据的分布。
5.1。等高线图:
等高线图是一种图形技术,通过在二维格式上绘制称为等高线的恒定 z 切片来表示三维表面。
import seaborn as sns
g=sns.jointplot(x = 'op_year', y = 'age', data = haberman_data, kind = 'kde')
输出:
年龄和手术年份等高线图
此处,手术年份、年龄是两个参数,而为图提供蓝色阴影的 3D 参数是患者手术年份和年龄组合的计数。
观察结果:
大量的手术是在 60-64 岁和 45-55 岁之间进行的
结论:
- 40 岁以下的患者可能有较高的存活率,75 岁以上的患者可能有较低的存活率。
- 腋窝淋巴结越低,生存机会越高。
- 然而,年龄、手术年份或腋窝淋巴结这三个变量中的任何一个都不足以准确决定患者的生存率,而且数据集是不*衡的。因此,分类是困难的。
谢谢你的阅读。我也将在未来写更多初学者友好的帖子。请在媒体上关注我,以便了解他们。我欢迎反馈,可以通过 LinkedIn RamyaVidiyala 联系
AAAI 2020:无监督的深度学习和可以推理的人工智能
AAAI 第三十四届年会刚刚在纽约闭幕。不出所料,这是一次有数千名人工智能研究人员和实践者参加的大型会议。一大亮点是 2018 年 ACM 图灵奖获奖者 Geoffrey Hinton、Yann LeCun 和 Yoshua Bengio 的演讲,以及与丹尼尔·卡内曼的小组讨论。
我也有机会与扬·勒村和丹尼尔·卡内曼交谈。我还确保捕捉了一些照片。
图灵三人组又名深度学习教父
Yoshua Bengio、Geoffrey Hinton 和 Yann LeCun 因概念和工程突破而获得 2018 年 ACM A.M .图灵奖,这些突破使深度神经网络成为计算的关键组成部分。ACM A.M .图灵奖也被称为“计算机科学界的诺贝尔计算奖”。深度学习已经成功应用于语音识别、机器翻译、推荐系统以及自动驾驶汽车等多个领域。深度学习有各种各样的应用,目前许多大型技术公司都是围绕这种方法建立的。可以说,深度神经网络是*期最重要的计算进步的原因。然而,这些模型有它们的缺点,例如它们的决策难以解释,它们(被监督的)需要大量高质量的数据点,以及它们甚至不能进行基本的推理。在个别谈话中,他们每个人都谈到了当前的挑战,未来的方向,以及他们实验室最*的研究,以推动当前深度学习模型的局限性。
杰弗里·e·辛顿:使用自动编码器的胶囊网络
唐·辛顿的演讲是关于 CNN 的局限性以及如何克服这些局限性。在他看来,CNN 和我们识别物体的方式不同。当人们感知形状时,他们使用坐标框架并总是分配固有坐标框架——这是人类感知的一个重要方面。相比之下,CNN 依赖于重合——等式两边的值之间的重合,以及使得高维过滤器识别图像的重合。
我们希望神经网络毫不费力地推广到新的视点,只有当它们能够像处理视点转换一样处理好旋转和缩放时,这才会发生。
他最*一直在开发胶囊网络。想法是使用一组神经元来表示给定图像的片段,然后使用这些学习到的子表示来表示图像,以识别图像。他首先在 NIPS 2017 和最*的 NeurIPS 2019 中介绍了胶囊网络。
当前版本的胶囊网络是无人监管的,与前两个完全不同。它们被称为堆叠胶囊自动编码器,基于创成式建模技术。
Yann LeCun:革命将会自我监督
Don LeCun 在他的演讲中首先定义了深度学习,并指出监督学习的所有限制有时被错误地视为 DL 的内在限制。在他看来,当我们拥有大量数据或可以模拟环境进行太多尝试以学习任何东西时,监督学习和强化学习确实会分别嵌套。然而,在现实世界的场景中,获得良好的标记数据也是一个问题,因为我们无法以比实时更快的速度运行现实世界来尝试各种场景——很多时候,任务看起来很简单,但一个小错误也会杀死我们。
为了实现这种智能水*的预测,我们需要想出方法来解决深度学习面前的三个主要挑战。他在脸书和 NYU 的研究小组正在研究自我监督学习来克服这一挑战。预测是智能的本质,我们人类通过预测来自其他部分的部分输入,来自过去的未来,来自可见的掩蔽部分,以及来自所有可用部分的任何被遮挡部分来学习世界的模型。
在 2016 年的一篇教程中,他对基于能量的模型进行了如下描述:基于能量的模型(EBM)通过将标量能量与变量的每个配置相关联来捕捉变量之间的依赖关系。推理包括钳制观察变量的值,并找到剩余变量的配置,使能量最小化。学习包括寻找一个能量函数,其中观察到的变量配置比未观察到的配置具有更低的能量。
EBM 对适当的规范化没有要求,这个问题自然就被回避了。EBM 可以被视为非概率因素图的一种形式,与概率方法相比,它们在架构和训练标准的设计方面提供了更大的灵活性。
我们可以在一篇完整的笔记中更多地讨论他讨论的塑造基于能量的函数的七个策略以及他的研究团队中的其他 SSL 工作。
Yoshua Bengio:意识优先和世界模型
Yoshua 谈到了他在实现人类级别的 AI 方面所做的努力。用他的话说,“没有完全通用的智能——这些总是一些归纳的基础和先验。”越简单越少的先验越有可能被发现,并且可以被结合起来理解更广泛的背景。
他谈到了开发世界(或世界事件)模型并让神经网络学习它的可能性。这可以帮助深度学习根据系统 1 学习系统 2。系统 1 和系统 2 的概念来自丹尼尔·卡内曼。在《思考,快与慢》一书中,丹尼尔·卡内曼将系统 1 描述为快速、自动、频繁、情绪化、刻板、无意识,锚定在人类的感官知觉中,而系统 2 描述为缓慢、努力、不频繁、有逻辑、精于计算、有意识。理性的,有序的,可以用语言表达的。
系统 1 自动且快速地运行,很少或没有努力,并且没有自主控制的感觉。与此同时,系统 2 将注意力分配给需要它的费力的脑力活动,包括复杂的计算。系统 2 的运作通常与代理、选择和集中的主观体验有关。
某种层面的深度学习可以做到像系统 1 一样的自动感知,挑战在于如何将 DL 从系统 1 扩展到系统 2。如果我们需要一些先验意识来表示高级概念,并使用 DL 来预测各种先验的值?如果这些先验能以某种方式结合起来做一些真正人类水*的推理和理解?
从很多方面来说,这是一次积极的、前瞻性的谈话。他们回答了围绕深度学习及其局限性的各种问题。对他们来说,获得他们项目的录取是多么困难,以及大学教育的重要性。用 Gefforry Hinton 的话来说——无论大型科技公司拥有多少资源,好想法都会来自一个在这个问题上花了足够时间的研究生。
Hinton,LeCun,Bengio 都同意 AI 需要有推理能力。虽然不清楚推理应该使用神经网络还是神经网络应该学习推理。
复杂问题回答的推理
我们在语言理解方面取得了巨大进步,像 Siri、Alexa 和谷歌助手这样的问答系统已经成为我们生活中无处不在的一部分。然而,这些最先进的解决方案仍然无法进行基本的推理,也无法回答任何复杂的问题。即使我们不谈论大规模生产就绪的解决方案,也没有具体的研究工作解决方案可以进行推理和解释任何情况。他们很肤浅,研究信息检索的原理;给定一个查询和一个故事,他们试图找到最佳回答用户查询的跨度长度。在 AAAI 有一个全天的研讨会,试图讨论复杂问题回答中的挑战和成功。
这个研讨会做了很好的工作,将研究工作引入到克服这个缺点,开发故事理解的解决方案,并回答复杂的问题。现在,这篇文章将详细描述一些我觉得更有趣的演讲。
Ray Mooney 教授讨论了逻辑和基于向量的方法的局限性,以及如何整合它们。它可以帮助我们获得更好的因果解释,并对“为什么”问题有更深的理解。他描述了如何使用彗星模型来构建给定事件的因果图,并使用它来更好地了解基于计划的理解,在这些因果图中应用马尔可夫链看起来很有前途。它显示了神经符号方法的潜力和保持这一研究方向新发展的关键的原因。
来自的纳斯林展示了他们在常识推理和叙事理解方面的工作。他们一直致力于开发儿童书籍的心智模型,并将它们融入最先进的语言理解模型中。
任何孩子都可以很容易地理解这个故事,可能是通过对所讨论的场景建立一个心理模型。如何让一个深度模型理解它?
目前人工智能的进步是显著的,但我们仍然无法推理或解释儿童故事书中提到的简单场景。在这个方向上已经有了一些工作,Atomic 是这个方向上最令人兴奋和最新的工作。在这里,纳斯林在葡萄糖方面领先一步。他们将故事解释的因果心理模型定义为 10 维空间、5 个原因和 5 个原因维度。
葡萄糖框架
这对我来说是一个更令人兴奋的演示,因为我一直在研究 Atomic 和 Comet,并且刚刚开始了一个类似方向的新项目。葡萄糖不仅通过添加更多的因果维度扩展了原子,而且还基于给定故事细节的各种推断因果创建了逻辑推理的推理规则。
葡萄糖:统计和实例
她提供的关于从零开始训练编码器-解码器模型的另一个有见地的信息比从零开始训练基于转换器的模型给出了更好的性能。不过,微调基于变压器的模型可以获得最佳精度。
我真的很兴奋,期待几个月后能读到这篇论文。他们已经向 ACL 提交了他们的工作,正在等待接受。
我也喜欢 Sameer Singh 教授关于 T2 评估和测试问题回答能力的演讲,以及 T4 Dan Roth 教授关于为什么(以及如何)我们应该学习问题回答的演讲。
Sameer 谈到了我们最先进的 NLU 模型的脆弱性,他的各个研究小组正在进行调查,以对 QA 系统进行更彻底的评估。
脆弱的质量保证系统
他的团队正在研究干扰数据集中实例的自动化技术,这些实例可以识别问答过程中的漏洞和捷径,包括语义对手和通用触发器。
丹以约翰·麦卡锡在《纽约时报》的故事为例开始了他的演讲。
约翰·麦卡锡的纽约时报的例子
我们任何一个人都可以从上面的文章中推断出的事情
1976 年,麦卡锡在谈到不良贷款及其引发的问题时,举了一个简单的例子,即《纽约时报》的一个故事,讲述了一名推销员被推下电梯井的故事,以及我们如何回答各种问题,即使在今天,也没有自动化模型能够回答这些问题。
一个好的系统应该很容易回答这些问题
回答这些高级自然语言理解问题仍然超出了我们的能力,部分原因是这些任务中的大多数是稀疏的,并且我们当前为其生成监督信号的方法没有扩展。Dan 提到了一些最*的工作,包括使用语义图来回答这些高级推理问题,以及一些最*的时态常识数据集,作为前进的方向。
总之,问答是人类理解语言和世界的方式,也是一种诱导表达的方式,有助于我们做得更好。
还有很多我喜欢的其他演讲和海报。我会试着把它们列一个清单,并简单描述一下(也许在下一篇文章中)。这是一次学习的经历——我认识了几个来自 UT-Austin 的同事,我前雇主的同事,还交了几个新朋友。
不幸的是,由于冠状病毒的流行,许多研究人员无法展示他们的工作。我希望我们能很快找到治疗冠状病毒的方法。
参考资料:
以上大部分材料是基于我对演示文稿的理解、我拍摄的照片以及来自演示者的共享幻灯片和相关论文。其中一些列举如下:
- https://aaai.org/Conferences/AAAI-20/
- https://awards.acm.org/about/2018-turing
- 堆叠胶囊自动编码器
- 自我监督学习:Yann、LeCun 分享的幻灯片
- 基于能量的方法教程
- 思维快与慢
- Yoshua Bengio 的《意识优先》
- 复杂问题回答的推理
- 原子
- 彗星
AAMAS-20:自主代理和多代理系统自由会议
多智能体系统越来越重要。这里有一个免费的资源来学习前沿研究!
智能体,可以与其环境或其他智能体进行交互的实体,是人工智能中一个越来越重要的领域。代理可以学习,推理他人,采用规范,并在虚拟和物理环境中与人类互动。该领域包括对人工智能许多领域的贡献,包括博弈论、机器学习、机器人、人机交互、建模和社会选择。虽然大部分工作是基于实验室实验的学术研究,但也有越来越多的实际部署对政府和商业组织产生了直接影响。国际 AAMAS 会议,现在是第 19 届,在网上举行,出席是免费的,而注册费通常超过 700 美元。
本次会议于 5 月 9 日周六开始,为期两天的研讨会和辅导。5 月 11 日星期一至 5 月 13 日星期三有 300 多场论文报告和主题演讲,主讲人包括卡拉·戈麦斯、艾莉森·赫本斯塔尔、谢尔盖·莱文和托雷·格雷佩尔。ACM SIGAI 自主智能体研究奖演讲将由穆尼德尔·p·辛格发表,而张秀坤·皮特斯将为维克托·莱瑟博士论文颁奖。
虽然所有视频都将在 2020 年底之前在 underline.io 上异步观看,但 underline.io 也将支持活动期间的现场问答环节。会议记录将一如既往地在网上免费提供。
如果你有兴趣了解更多关于自主代理和多代理系统的令人兴奋的领域,我们希望你能加入我们!
-马修·泰勒,代表奥玛组织 20 名主席 Amal El Fallah Seghrouchni 和 Gita Sukthankar
附加细节
自主代理和多代理系统(AAMAS)会议系列聚集了来自世界各地的研究人员,分享该领域的最新进展。它是研究自主代理和多代理系统的理论和实践的首要论坛。第一届 AAMAS 2002 在博洛尼亚举行,随后是墨尔本(2003 年)、纽约(2004 年)、乌特勒支(2005 年)、函馆(2006 年)、檀香山(2007 年)、埃斯托里尔(2008 年)、布达佩斯(2009 年)、多伦多(2010 年)、台北(2011 年)、巴伦西亚(2012 年)、圣保罗(2013 年)、巴黎(2014 年)、伊斯坦布尔(2015 年)、新加坡(2016 年)。本卷是 AAMAS 2020 系列会议中的第 19 次会议,将于 2020 年 5 月在奥克兰举行。
AAMAS 2020 邀请提交一般轨道、蓝天想法轨道和展示 JAAMAS(自治代理和多代理系统杂志)论文的轨道,这些论文以前没有在主要会议上展示过。蓝天创意赛道由 Alessandro Ricci 和 Juan Antonio Rodriguez 主持。Rym Zalila-Wenkstern 和 Pı nar Yolum 从过去 12 个月中在 JAAMAS 上发表的论文中征集论文,用于 JAAMAS 演讲。
选出了一组地区主席(AC)来帮助监督主要路线的审查过程。ACs 对提交的文件进行了初步检查,并建议立即拒绝那些不符合 AAMAS 范围、提交或格式说明的文件。
十个地区的主席与计划主席共同负责任命高级计划委员会(SPC)成员,而高级计划委员会成员反过来又帮助确定了一组强大而多样化的计划委员会(PC)成员。PC 可以审查多个领域。每篇论文都由至少三名 PC 成员审阅,并由一名 SPC 成员监督,确保审阅内容清晰、信息丰富。在作者有机会对评审者做出回应后,SPC 成员主持了一场讨论,在讨论中评审者考虑了彼此以及作者的意见。区域主席反过来与项目主席合作,对论文的接受做出最终决定,以确保一致的高质量。
AAMAS 2020 吸引了大量高质量的提交材料:完整论文的总体接受率为 23%(808 份经审查的提交材料中有 186 份被接受)。
虽然所有被接受的论文都是高质量的,但从主流中选出的几篇论文被提名为最佳论文奖和 Pragnesh Jay Modi 最佳学生论文奖。最佳论文奖在会上颁发给最佳论文,Pragnesh Jay Modi 最佳学生论文奖颁发给主要由学生撰写的其余最佳论文。最佳学生论文奖是由斯普林格赞助的。这些奖项的提名名单如下,按第一作者姓氏的字母顺序排列;主要由学生撰写的论文标有星号(*)。这些论文还被提名为《人工智能研究杂志》(JAIR)的加速审查。
- Harshavardhan Kamarthi、Priyesh Vijayan、Bryan Wilder、Balaraman Ravindran 和 Milind Tambe。未知社会网络中的影响力最大化:有效图形采样的学习策略
- Divya Ramesh、Anthony Z. Liu、Andres J .、Jean Y. Song、Nicholas R. Waytowich 和 Walter S. Lasecki。昨天的奖励是今天的惩罚:人类对强化学习代理反馈的对比效果
- Klaus Weber、Kathrin Janowski、Niklas Rach、Katharina Weitz、Wolfang Minker、Stefan Ultes 和 Elisabeth André。使用双极加权论证图预测多模态行为适应的说服效果
- 尚同·张、温德林·贝默和西蒙·怀特森。深度残余强化学习
此外,IFAAMAS 影响力论文奖将在会议上颁发给以下两篇论文:
- Ariel D. Procaccia 和 Moshe Tennenholtz。无钱*似机制设计。《第十届 ACM 电子商务会议论文集》,第 177–186 页,2009 年。
- 科特·m·德雷斯纳和皮特·斯通。自主交叉口管理的多智能体方法。《人工智能研究杂志》,第 31 卷,第 591–656 页,2008 年。
Aaron Mayer:授权工程师建设更美好的世界
技术创新者系列
对 Impact Labs 联合创始人的采访
技术进步正以指数速度增长。数据素养正在成为许多行业的先决条件,许多热门的、新的和高薪的工作都在大型科技巨头那里。现在,比以往任何时候都更加明显的是,这种增长带来了责任——以及围绕可持续技术增长的光明未来的潜力。一个组织站在这场运动的最前沿,让技术人员能够利用他们的技能造福社会。
图片由 Aaron Mayer 提供
Impact Labs 在技术和社会公益之间架起了一座桥梁。他们将学生与经验丰富的社会企业家联系起来,同时在可持续技术领域创造有意义的机会。
“我意识到,就像很多人一样,技术有巨大的能力来影响世界的变化。”
亚伦·梅尔在布朗大学的宿舍里创建了 Impact Labs。虽然布朗大学约 20%的本科生专注于计算机科学,但这些学生中的大多数最终都在知名科技公司工作。面对这种“看似有限的”职业机会,亚伦开始增加工作的可见性,让学生能够创造积极的社会变革,而不牺牲他们的薪水。为了探索是什么激励他在技术和社会公益的交叉点上进行建设和创新,我和 Aaron 谈论了他的旅程。
图片由 Impact Labs 提供
Amber: 你能告诉我们一些你的背景吗?
伦:确定!我从小就是一个笨拙的书呆子,喜欢 STEM,但却选择了人文学科。后来才知道,那些探究的分支其实差别挺小的。在上大学之前,我利用间隔年去了 15 个国家,那是我第一次亲眼目睹贫富之间的严重不*等。
当我终于上学的时候,我学的是哲学,重点是伦理学。后来,我回到了我最初对科学和技术的热爱,我一直在思考,我们认为理所当然的技术工具是如何对那些没有分享我们好运的人的生活产生如此巨大的影响的。我想这最终导致了冲击实验室的建立。
Impact Labs 在技术和社会公益之间架起了一座桥梁。
你一直都知道在科技领域工作是你想做的吗?
AM: 创办公司绝对不在计划之内!如果你在大学问我想做什么,我可能会说我想成为一名科学老师或者一名记者。对我来说,技术和创业文化如影随形,就像他们经常做的那样,但这在很大程度上是偶然的。我记得我在布朗大学期间去过我的校园创业中心,纯粹是因为他们总是在活动中提供免费的印度食物。在大学的这个领域逗留了足够长的时间并结识了新朋友之后,我像许多人一样意识到,技术具有巨大的能力来影响世界的变化。这并不是说,我认为教育和立法等事情不能同样改变世界,但我认为我是被降低的准入门槛所逼:毕竟,任何人都可以创办公司或开发一个应用程序,可以想象这一天可以覆盖数十亿人,这种规模在其他地方真的不存在。
图片由 Aaron Mayer 提供
AT: 在您的 TEDx 演讲“我们时代的超级英雄”中,您描述了年轻的理想主义技术专家对构建更加公*和可持续的未来的需求。为什么你认为今天的技术人员在职业生涯中考虑公*、道德和可持续性很重要?简而言之,如果我们不做,就没有人会做。当你听到“科技”这个词时,你可能会想到世界上的微软和 IBM。这些可能是令人敬畏的公司,但解决气候变化、教育不普及、性别不*等、被忽视的热带疾病和贫困的科技公司在哪里?如果工程师代表了我们这一代最优秀、最聪明的头脑,难道他们不应该致力于解决我们作为一个物种所面临的最大、最根深蒂固的挑战吗?
我要补充的是,许多改变世界的公司通常会付出巨大的环境和社会成本。看看苹果和亚马逊的劳工行为,或者谷歌和脸书的侵犯隐私行为,不要让我开始谈论国防工业。我相信,为这些公司制造产品和服务的工程师和技术人员拥有坚强的道德品质和坚定不移的正直是至关重要的:如果他们拒绝制造有害的工具,那么有害的工具就不会被制造出来。
当然,不一定要像在 Snapchat 罢工那么戏剧化。软件工程师、UX 设计师、数据科学家等。都可以尽自己的一份力量,通过大声说出他们工作的公司潜在的有害方面,来降低他们所创造的技术的负面影响。
图片由 Impact Labs 提供
AT: Impact Labs 旨在“激励和授权年轻的工程师去建设一个更美好的世界”。Impact Labs 是如何实现这一使命的?
上午:我们在 Impact Labs 开展了一系列计划,这些计划都是根据我们的使命设计的。我们主持的第一个节目叫做影响力奖学金。一年一度的伙伴计划即将进入第四个年头,它聚集了对社会公益事业充满热情的高素质工程师,他们将在为期两周的时间里作为一个社区一起学习、建设和成长。我们还举办现场活动,例如我们的年度影响力峰会,在这里,年轻的技术专家和早期企业家可以聆听演讲者的演讲,并向社会创业领域的研讨会领导者学习,他们正在利用技术建立一个更加公*、可持续的社会。此外,我们还开展了一项名为 The Impact Coalition 的招聘计划,这基本上是高影响力组织的常用应用程序:一名工程师提交一份申请,然后我们会在我们投资组合中的数十家公司中为他们找到与他们的技能和兴趣最匹配的工作。此外,如果我可以自夸的话,我们有一个精彩的双周刊时事通讯,它汇集了社会影响世界技术中的机会和新闻更新,发给 5000 多名年轻工程师,所以我对此非常自豪。在不久的将来,我们一直在探索直接与大学合作的方法,让他们在计算机科学课程中实施道德要求。顺便说一句,所有这些项目都是 20 位不可思议的队友贡献的直接结果,如果没有他们的奉献和承诺,Impact Labs 就不会有今天的成就。我喜欢与他们合作,在一个我们都相信的项目上一起工作是一种快乐!
图片由 Aaron Mayer 提供
AT: 你认为下一代有抱负的技术人员面临的最大挑战是什么,目前在行业中的数据科学家可以做些什么来帮助他们?
AM: 目前,我认为最大的挑战是有悖常理的经济激励。请原谅我戴上马克思主义的帽子,众所周知,大多数公司都有基于利润的生存和发展动机,这也是我之前提到的有害副作用的最常见原因。然而,因为科技公司如此富有,他们可以支付(高得离谱的)高薪给数据科学家、机器学习专家和其他保持引擎运转的工程师。太多聪明、理想主义的技术专家被六位数的薪水所诱惑,我有太多的朋友向我承认,如果不是为了钱,他们根本不可能在帕兰蒂尔或高盛这样的机构工作。
这就是为什么我们在 Impact Labs 尽最大努力向那些通过行善而获得成功的公司展示通向有意义职业生涯的道路。当你为一家社会创业公司工作时,这并不是说你将自己托付给了贫困的生活,以我自己的经验来看,为你真正支持的使命工作的感觉是无价的。
AT: 对于其他有志于发展职业生涯并在行业中产生积极社会影响的技术专家和工程师,你有什么建议?
AM: 开始点什么!说真的,我知道这是老生常谈,但你通过自己尝试和失败学到的东西比做任何其他事情都多。
如果你完全确定成为一名创始人不是你想要的(我会再次确认这种确定性,因为成为一名创始人可能非常有趣!),那么我的建议是这样的:从你的理想职业向后工作。如果你想成为白宫的首席技术官,那么今天就开始采取措施,你有证据表明这些措施会让你在未来走上这个职位的轨道。谷歌一下那些拥有你梦想工作的人,试着模仿他们的传记——更好的是,直接联系他们!如果你带着强烈的好奇心和爱去接*他们,你会惊讶于人们是多么的容易接受!
"许多改变世界的公司往往以巨大的环境和社会成本为代价."
AT: 我们的读者如何参与 Impact Labs?
AM: 很多方法!第一件也是最简单的事情就是在这里注册订阅我们的时事通讯!你也可以关注我们的脸书页面和推特,并加入我们的脸书群!我们将在今年 8 月举办下一次峰会,它将完全在线,所有人都可以访问,所以你应该完全参与!详情及在impactlabs.io/summit报名!
最后,虽然 Impact Labs 并没有明确加入有效利他主义运动,但如果你还不熟悉的话,你绝对应该去看看 EA。我们在 Impact Labs 所做的大部分工作都明确遵循 EA 的原则,如果你对改变你的职业感兴趣,这是一个很好的方式来开始问自己一些基本的问题,关于你如何才能做到最好。
图片由 Impact Labs 提供
Impact Labs 在技术和社会公益的核心领域引领可持续创新。Impact Labs 不仅将热情的学生与利用技术产生社会影响的领导者联系起来,还建立了一个聚焦全球发展未来的社区。
特别感谢 Aaron Mayer 允许我为这个系列采访他,也非常感谢 TDS 编辑团队对这个项目的支持。
你认识一位鼓舞人心的技术专家,你希望他出现在这个系列中吗?你是否正在从事任何你希望我写的很酷的数据科学和技术项目?欢迎给我发电子邮件,向 angelamarieteng@gmail.com 寻求意见和建议。感谢阅读!
[1]https://www . brownalumnimagazine . com/articles/2019-09-09/hi-tech-ethics
【2】https://www.youtube.com/watch?v=zrjNBWMY8qM
参考文献:
"恩尼格玛福音传道者和 Impact Labs 创始人在普林斯顿——新泽西州技术周刊发表演讲."n.d .于 2020 年 5 月 26 日获得。https://njtechweekly . com/enigma-evangelist-and-impact-labs-founder-speaks-in-Princeton/。
“影响实验室——联盟。”n.d .于 2020 年 5 月 26 日获得。https://www.impactlabs.io/coalition/.
“影响实验室—峰会”n.d .于 2020 年 5 月 26 日获得。【https://www.impactlabs.io/summit/.
“影响实验室——伙伴关系。”n.d .于 2020 年 5 月 26 日获得。https://www.impactlabs.io/fellowship/.
"可持续技术发展的问题—影响实验室—中等."n.d .于 2020 年 5 月 26 日获得。https://medium . com/impact-labs/the-question-of-sustainable-technology-growth-aaea 7 B3 B4 f 4。
"见艾伦·梅尔(Enigma,Impact Labs)在普林斯顿的初创公司 Grind . "n.d .于 2020 年 5 月 26 日获得。https://www . startup grind . com/events/details/startup-grind-Princeton-presents-aaron-Mayer-enigma-impact-labs/。
"高科技伦理|布朗校友杂志."n.d .于 2020 年 5 月 26 日获得。https://www . brownalumnimagazine . com/articles/2019-09-09/hi-tech-ethics。
“(340)我们这个时代的超级英雄|亚伦·梅尔| TEDxBrownU——YouTube。”n.d .于 2020 年 5 月 26 日获得。https://www.youtube.com/watch?v=zrjNBWMY8qM.
“冲击实验室”n.d .于 2020 年 5 月 26 日获得。https://www.impactlabs.io/.
社交网络中的 AB 测试挑战
脸书和他的同事如何在 AB 测试中克服互联用户的挑战
AB 测试的概念听起来很简单:将用户随机分配到控制组或治疗组,并检查治疗组的用户与控制组相比,是否表现出想要的行为变化(或任何变化)。但是,如果用户之间相互作用,以至于在控制组和治疗组之间画一条直线变得几乎不可能,会发生什么呢?
脸书、谷歌和 LinkedIn 等公司因其 AB 测试工作而广为人知。但是,考虑到他们产品的高度互联性,他们都面临上述问题,这可能会在实验结果中产生偏差,甚至更糟的是损害他们用户的体验。那么这些公司是如何解决这些问题的呢?
社交网络中 AB 测试的挑战
在进行 AB 测试时,人们通常假设每个人在测试中的反应只取决于自己的任务,而不取决于其他人的任务。这就是所谓的稳定单位治疗值假设(SUTVA) 。
但让我们假设一个大型社交网络*台,如 LinkedIn 或脸书,测试一种改进的算法,使其订阅源与用户更相关,目标是增加内容的参与度。如果用户 A 在治疗组中,并且与控制组中的用户 B 相联系,则用户 A 的行为变化可能会影响用户 B 的行为。用户 A 可能表现出对订阅源上的改进内容的参与度增加,从而开始共享更多的帖子、图片和文章。这将最终对用户 B 产生影响,用户 B 可能在没有接触到新体验的情况下就开始做同样的事情。
治疗的成功以治疗组和对照组之间*均结果的差异来衡量。例如,可以检查转换率的差异。这就是所谓的*均治疗效果 (ATE)。溢出效应,就像在社会网络中发现的那样,会使*均治疗效果产生偏差,因为治疗组中引入的变化带来的好处再也无法准确捕捉。在新闻反馈的新算法的情况下,溢出效应可能不仅会导致治疗组的参与度增加,也会导致对照组的参与度增加。这是因为控制组中的用户也可能被鼓励更多地参与他们的提要。然而,这冲淡了治疗的积极效果,当在社交网络中使用标准 AB 测试方法时,最终会导致错误的结论。
除了偏向统计结果的风险,社交网络或协作应用中的 AB 测试也可能带来一些 UX 挑战。例如,在视频聊天应用程序或高度协作应用程序(如 Google Docs)中测试新功能时。如果正在进行视频通话或正在协作处理同一文档的用户没有相同的功能,这可能会导致混乱并恶化用户体验,从而引发诸如“您没有看到右下角新的黄色按钮吗?”。
AB 测试的经典方法可能会由于有偏见的统计结果而误导业务决策,同时严重损害用户体验。
巢式抽样法
集群抽样,又称网络分桶,是处理溢出效应的常用方法。我们的目标是将用户分为治疗组和控制组,这样各组之间的交互就尽可能少。当进行 AB 测试时,用户通常被随机分配到不同的变体,这导致了前面提到的溢出效应。取而代之的是集群抽样,随机化是在用户集群级别上进行的。换句话说,如果用户是控制组的一部分,他们的直接网络连接的重要部分也被分配给控制组。
(社会)网络中的整群抽样(自有图形)。
以最小化它们之间的信息流的方式分割这些组是一个复杂的挑战,其中可以使用各种各样的聚类算法来实现这个目标。一种叫做 e-net 的方法基于以下想法:
- 找到 k 个节点作为聚类中心,它们之间的距离大于特定阈值
- 将剩余节点随机分配到它们最*的中心
在协作应用中,例如谷歌云*台,可以使用更确定的方法来创建这些集群。相互交流的用户数量受到他们一起工作的项目数量的限制。因此,可以创建在相同项目上工作的用户群,从而将群之间的溢出效应降低到接* 0(如果用户加入不同群中的用户所拥有的新项目,溢出效应仍然会发生)。
聚集一个实验小组有其自身的挑战。例如,在网络中的集群大小和集群数量之间存在权衡。一方面,为了实现 AB 检验的高统计功效,优选具有尽可能多的单位。另一方面,用户组中不同集群的数量越多,这些集群就越不孤立。例如,如果只有一个或两个集群,溢出效应将远远小于有 100 个或更多集群的情况。在处理组之间具有相等的集群大小是另一个要求,这有助于减少方差和增加测试的功效。
AB 测试集群
一旦实验组被组织成组,这些组可以被分配给控制或处理单元。然后在集群上进行测试。首先在聚类水*上计算转化率等指标,然后在治疗组水*上再次进行*均。最终,这些结果可用于计算*均治疗效果。
这种方法也可以用来证明网络效应的普遍存在。例如,当运行一个实验时,一个在用户级别随机化的 AB 测试可以与另一个在集群级别随机化的测试并行运行。如果两种设置的*均治疗效果有显著差异,这可以被视为网络效应存在的证据。
进一步的挑战
在一个集群上而不是在一个用户层面上进行随机化,只能解决在社交网络中进行 AB 测试时出现的部分问题。另一个需要考虑的挑战是,在将用户划分为集群时,用户之间连接的强度和方向。与脸书或 LinkedIn 相比,Instagram 和 Twitter 等网络的结构非常不同。在这些网络中扮演重要角色的影响者是一个相对较小的用户群体,他们能够对许多用户产生巨大的影响。与此同时,这些联系大多是单向的:影响者可以对其追随者产生影响,但反之则不然。
想象一个极端的情况,其中一个用户非常有名,网络中的所有其他用户都追随他。该用户可以影响所有这些用户,无论网络如何划分。但是,在不太极端的情况下,溢出效应可能无法通过简单地将用户聚集到关系最密切的群体中来减少。解决这一挑战的可能方法是使用影响者作为初始聚类中心,并通过多数投票将剩余用户分配给这些聚类。
结论
一般来说,AB 测试是一个被广泛使用和深入研究的领域。与此同时,社交网络中的 AB 测试所带来的挑战还远未解决,仍有待深入研究。无论是找到正确的聚类方法还是*均治疗效果的理想估计值,仍然有许多挑战需要克服。但由于 AB 测试是脸书和 Twitter 等大型科技公司所有产品开发活动的核心,人们可以放心,克服这些非常有趣的挑战的新方法和方法论将会发展。
参考
对本文有帮助并提供更详细概述的论文和文章:
更多关于 AB 测试的文章:
像 Optimizely 这样的实验*台是如何忽略 AB 测试中最基本的原则之一的
towardsdatascience.com](/unlocking-peeking-in-ab-tests-7847b9c2f6bb) [## AB 测试:利润和社会责任之间的权衡?
产品开发中最重要的工具之一的副作用几乎没有人想到
medium.com](https://medium.com/swlh/ab-testing-a-trade-off-between-profit-and-social-responsibility-5d6394dc9eea)
A/B 测试:Python 中的分步指南
从实验设计到假设检验
作者图片
在这篇文章中,我们将回顾分析 A/B 实验的过程,从制定假设,测试它,最后解释结果。对于我们的数据,我们将使用来自 Kaggle 的一个数据集,它包含对一个网站页面的两种不同设计(旧页面与新页面)进行 A/B 测试的结果。如果你想了解我使用的代码,请随意在我的 GitHub 页面下载 jupyter 笔记本。
这是我们要做的:
为了更现实一点,这里有一个潜在的场景供我们研究:
让我们想象一下,你在一家中型在线电子商务企业的产品团队工作。UX 的设计师非常努力地设计了新版本的产品页面,希望它能带来更高的转化率。产品经理(PM)告诉您,当前的转换率全年*均约为 13% ,团队会对 2% 的增长感到满意,这意味着如果新设计将转换率提高到 15%,则认为新设计是成功的。
在推出变更之前,团队更愿意在少量用户身上测试它,看看它的表现如何,所以你建议在你的用户群用户的子集上运行 A/B 测试。
1.设计我们的实验
阐明一个假设
首先,我们要确保在项目开始时制定一个假设。这将确保我们对结果的解释既正确又严谨。
假设我们不知道新设计的表现会更好还是更差(还是一样?)作为我们目前的设计,我们将选择一个 双尾检验 :
Hₒ: p = p ₒ
hₐ:p≦pₒ
其中 p 和 p ₒ 分别代表新旧设计的转换率。我们还将置信度设为 95% :
α = 0.05
α 值是我们设定的一个阈值,通过这个阈值我们说“如果观察到一个结果为极值或更大的概率(p-值)低于 α ,那么我们拒绝零假设”。由于我们的 α=0.05 (表示 5%概率),我们的置信度(1 — α )是 95%。
如果您不熟悉以上内容,请不要担心,所有这些实际上意味着,无论我们在测试中观察到新设计的转换率是多少,在我们决定拒绝零假设 Hₒ.之前,我们都希望有 95%的把握认为它在统计上不同于旧设计的转换率
选择变量
对于我们的测试,我们需要两个组:
- 一个小组——他们将被展示旧的设计
- 一个
treatment
(或实验)组——他们将被展示新的设计
这将是我们的自变量。尽管我们知道基准转换率,但我们之所以有两组,是因为我们希望控制可能对我们的结果产生影响的其他变量,如季节性:通过有一个control
组,我们可以直接将他们的结果与treatment
组进行比较,因为两组之间唯一的系统差异是产品页面的设计,因此我们可以将结果中的任何差异归因于设计。
对于我们的因变量(即我们试图测量的东西),我们感兴趣的是捕捉conversion rate
。我们可以用一个二进制变量对每个用户会话进行编码:
0
-用户在本次用户会话中没有购买产品1
-用户在本次用户会话中购买了产品
这样,我们可以很容易地计算出每组的*均值,从而得到每个设计的转化率。
选择样本大小
值得注意的是,由于我们不会测试整个用户群(我们的人口,我们得到的转换率将不可避免地只是真实转换率的估计值。
我们决定在每个组中捕获的人数(或用户会话)将对我们估计的转化率的精确度产生影响:样本量越大,我们的估计就越精确(即,我们的置信区间越小),在两组中发现差异的机会就越高,如果存在差异的话。
另一方面,我们的样本越大,我们的研究就变得越昂贵(和不切实际)。
那么每组应该有多少人呢?
我们需要的样本大小是通过所谓的 功效分析 来估计的,它取决于几个因素:
- 检验的功效 (1 — β) —这表示当差异实际存在时,在我们的检验中发现组间统计差异的概率。按照惯例,这通常设置为 0.8(如果你好奇,这里有更多关于统计能力的信息)
- α值 (α) —我们之前设置的临界值为 0.05
- 效应大小——我们预期转换率之间的差异有多大
由于我们的团队对 2%的差异感到满意,我们可以使用 13%和 15%来计算我们预期的效果大小。
幸运的是, Python 为我们处理了所有这些计算:
# Packages imports
import numpy as np
import pandas as pd
import scipy.stats as stats
import statsmodels.stats.api as sms
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
from math import ceil
%matplotlib inline
# Some plot styling preferences
plt.style.use('seaborn-whitegrid')
font = {'family' : 'Helvetica',
'weight' : 'bold',
'size' : 14}
mpl.rc('font', **font)effect_size = sms.proportion_effectsize(0.13, 0.15) # Calculating effect size based on our expected rates
required_n = sms.NormalIndPower().solve_power(
effect_size,
power=0.8,
alpha=0.05,
ratio=1
) # Calculating sample size needed
required_n = ceil(required_n) # Rounding up to next whole number
print(required_n)
4720
我们需要每组至少 4720 次观察。
在实践中将power
参数设置为 0.8 意味着,如果我们的设计之间的转换率存在实际差异,假设该差异是我们估计的差异(13%对 15%),我们有大约 80%的机会在使用我们计算的样本量进行的测试中将其检测为具有统计显著性。
2.收集和准备数据
很棒的东西!现在我们有了所需的样本量,我们需要收集数据。通常在这一点上,你会和你的团队一起建立实验,可能是在工程团队的帮助下,并确保根据所需的样本大小收集足够的数据。
但是,由于我们将使用我们在网上找到的数据集,为了模拟这种情况,我们将:
- 从 Kaggle 下载数据集
- 将数据读入熊猫数据框
- 根据需要检查和清理数据
- 从每个组的数据帧中随机抽取
n=4720
行*
- 注:正常情况下,我们不需要执行步骤 4,这只是为了练习
因为我已经下载了数据集,我将直接进入第二个问题。
df = pd.read_csv('ab_data.csv')
df.head()
df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 294478 entries, 0 to 294477
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 user_id 294478 non-null int64
1 timestamp 294478 non-null object
2 group 294478 non-null object
3 landing_page 294478 non-null object
4 converted 294478 non-null int64
dtypes: int64(2), object(3)
memory usage: 11.2+ MB# To make sure all the control group are seeing the old page and viceversa
pd.crosstab(df['group'], df['landing_page'])
数据帧中有 294478 行,每一行代表一个用户会话,还有 5 列:
user_id
-每个会话的用户 IDtimestamp
-会话的时间戳group
-用户在该会话中被分配到哪个组{control
,treatment
}landing_page
-每个用户在该会话中看到哪个设计{old_page
,new_page
}converted
-会话是否以转换结束(二进制,0
=未转换,1
=已转换)
我们实际上将只使用group
和converted
列进行分析。
在我们继续对数据进行采样以获得我们的子集之前,让我们确保没有被采样多次的用户。
session_counts = df['user_id'].value_counts(ascending=False)
multi_users = session_counts[session_counts > 1].count()
print(f'There are {multi_users} users that appear multiple times in the dataset')
There are 3894 users that appear multiple times in the dataset
事实上,有 3894 个用户不止一次出现。由于这个数字非常低,我们将继续从数据帧中删除它们,以避免对相同的用户进行两次采样。
users_to_drop = session_counts[session_counts > 1].index
df = df[~df['user_id'].isin(users_to_drop)]
print(f'The updated dataset now has {df.shape[0]} entries')
The updated dataset now has 286690 entries
抽样
现在我们的数据框架已经很好很干净了,我们可以继续对每个组的n=4720
条目进行采样。我们可以使用 pandas 的DataFrame.sample()
方法来做到这一点,它将为我们执行简单的随机抽样。
注意:我已经设置了random_state=22
,这样如果你想在你自己的笔记本上跟随,结果是可重复的:只要在你的函数中使用random_state=22
,你应该得到和我一样的样本。
control_sample = df[df['group'] == 'control'].sample(n=required_n, random_state=22)
treatment_sample = df[df['group'] == 'treatment'].sample(n=required_n, random_state=22)
ab_test = pd.concat([control_sample, treatment_sample], axis=0)
ab_test.reset_index(drop=True, inplace=True)ab_test
ab_test.info()
`<class 'pandas.core.frame.DataFrame'>
RangeIndex: 9440 entries, 0 to 9439
Data columns (total 5 columns):Column Non-Null Count Dtype
0 user_id 9440 non-null int64
1 timestamp 9440 non-null object
2 group 9440 non-null object
3 landing_page 9440 non-null object
4 converted 9440 non-null int64
dtypes: int64(2), object(3)
memory usage: 368.9+ KB`
ab_test['group'].value_counts()
control 4720 treatment 4720 Name: group, dtype: int64
很好,看起来一切都按计划进行,我们现在可以分析我们的结果了。
3.可视化结果
我们可以做的第一件事是计算一些基本的统计数据来了解我们的样本是什么样的。
conversion_rates = ab_test.groupby('group')['converted']
std_p = lambda x: np.std(x, ddof=0) # Std. deviation of the proportion
se_p = lambda x: stats.sem(x, ddof=0) # Std. error of the proportion (std / sqrt(n))
conversion_rates = conversion_rates.agg([np.mean, std_p, se_p])
conversion_rates.columns = ['conversion_rate', 'std_deviation', 'std_error']
conversion_rates.style.format('{:.3f}')
从上面的数据来看,我们的两个设计看起来确实很相似,我们的新设计表现略好,大约。 12.3%对 12.6%的转化率。
绘制数据将使这些结果更容易掌握:
plt.figure(figsize=(8,6))
sns.barplot(x=ab_test['group'], y=ab_test['converted'], ci=False)
plt.ylim(0, 0.17)
plt.title('Conversion rate by group', pad=20)
plt.xlabel('Group', labelpad=15)
plt.ylabel('Converted (proportion)', labelpad=15);
我们组的转化率确实非常接*。还要注意的是,根据我们对*均转化率的了解,第control
组的转化率低于我们的预期。转化率(12.3%对 13%)。这表明,从总体中取样时,结果会有一些变化。
所以……这个treatment
组的价值更高。这种差异有统计学意义** 吗?**
4.检验假设
我们分析的最后一步是检验我们的假设。由于我们有一个非常大的样本,我们可以使用正态*似值来计算我们的p-值(即 z 检验)。
同样,Python 使得所有的计算变得非常简单。我们可以使用statsmodels.stats.proportion
模块来获得p-值和置信区间:
from statsmodels.stats.proportion import proportions_ztest, proportion_confintcontrol_results = ab_test[ab_test['group'] == 'control']['converted']
treatment_results = ab_test[ab_test['group'] == 'treatment']['converted']n_con = control_results.count()
n_treat = treatment_results.count()
successes = [control_results.sum(), treatment_results.sum()]
nobs = [n_con, n_treat]
z_stat, pval = proportions_ztest(successes, nobs=nobs)
(lower_con, lower_treat), (upper_con, upper_treat) = proportion_confint(successes, nobs=nobs, alpha=0.05)
print(f'z statistic: {z_stat:.2f}')
print(f'p-value: {pval:.3f}')
print(f'ci 95% for control group: [{lower_con:.3f}, {upper_con:.3f}]')
print(f'ci 95% for treatment group: [{lower_treat:.3f}, {upper_treat:.3f}]')
z statistic: -0.34 p-value: 0.732 ci 95% for control group: [0.114, 0.133] ci 95% for treatment group: [0.116, 0.135]
5.得出结论
由于我们的p-值=0.732 远远高于我们的α=0.05** 阈值,我们不能拒绝零假设 Hₒ,这意味着**我们的新设计与旧设计相比并没有显著的不同(更不用说更好了)😦****
此外,如果我们观察treatment
组的置信区间([0.116,0.135],或 11.6-13.5%),我们注意到:
- 它包括我们 13%转化率的基线值
- 它不包括我们的目标值 15%(我们的目标是提高 2%)
这意味着新设计的真实转换率更有可能与我们的基线相似,而不是我们希望的 15%的目标。这进一步证明了我们的新设计不可能比我们的旧设计有所改进,不幸的是我们又回到了起点!
你喜欢我的故事吗?请让我知道!
请随意在我的 GitHub 页面下载 jupyter 笔记本。
ABBYY NeoML:我们如何创建开源机器学习库以及我们为什么需要它
用户 12683362 在 freepik 上的照片
该框架为软件开发者提供了强大的深度学习和传统的机器学习算法,用于创建推动数字化转型的应用。
数字智能公司 ABBYY 推出了 NeoML ,这是一个用于构建、训练和部署机器学习模型的开源库。NeoML 现已在 GitHub 上发布,支持深度学习和传统的机器学习算法。跨*台框架针对在云环境、桌面和移动设备上运行的应用程序进行了优化。根据下面显示的测试,与流行的开源库相比,NeoML 为在任何设备上运行的预训练图像处理模型提供了 15–20%的更快性能。更高的推理速度与*台无关性相结合,使该库成为需要无缝客户体验和设备上数据处理的移动解决方案的理想选择。
NeoML 是一个跨*台的 C ++库,它允许你组织一个完整的 ML 模型开发周期。它的主要重点是在各种*台上简单有效地推出现成的模型。即使这些模型是由其他框架创建的。
ABBYY 的人工智能宣传员 Ivan Yamshchikov 表示:“NeoML 的推出反映了我们致力于推动全行业人工智能创新的承诺。“ABBYY 拥有超过 400 项专利和专利申请的技术创新记录。共享我们的框架允许开发人员利用它的推理速度、跨*台能力,特别是它在移动设备上的潜力,同时他们的反馈和贡献将增长和改进库。我们很高兴推动人工智能的进步,并支持机器学习应用于越来越高价值和有影响力的用例。”
你可能会问:为什么我们需要另一个机器学习库?
下面我来回答这个问题,告诉你我们在 ABBYY 是怎么创建我们的库的,遇到了什么困难,最后发生了什么。
ABBYY 开始机器学习的地方
机器学习和人工智能的发展长期以来一直是 ABBYY 数字智能技术的一部分。随着时间的推移,很明显 ML 的工作需要统一。我们开始思考如何以最干净、最简单、最有效的方式改进我们的机器学习工厂。该公司几乎所有的代码都是用 C ++编写的——这意味着我们需要一个 C / C ++解决方案。然而,没有一个 C ++框架能满足我们所有的需求。当然,现在有不同的库实现不同的功能。比如 Liblinear,XGBoost,Scikit-learn,Libsvm,Caffe,TensorFlow 等。我们开始分析他们的能力。
大多数库适合于研究目的,但不适合于生产。他们的代码需要大量的修改:日志、错误处理、内存管理。此外,许多额外的功能,不同的构建系统,额外的依赖。不是每个人都有 C ++界面。库发展和变化很快,并且不总是可预测的;他们的表现和稳定性引发了质疑,没有人承诺支持。我们别无选择,只能开始我们自己的发展,所以我们决定创建我们自己的图书馆,在里面收集我们需要的一切,然后我们为自己决定未来的道路。
马库斯·斯皮斯克在 Unsplash 上的照片
经典算法
开源库 Liblinear、Libsvm、Scikit-learn 和 XGBoost 已经存在,并且非常有用。我们开始利用它们,但是在分析了它们的能力之后,我们用我们需要的东西实现了类似的想法,并且增加了一些优化。例如,我们只处理适合内存的样本,只在 CPU 上处理,不进行低级优化。因此,经典算法的速度在我们的问题中并不是瓶颈,所以我们并没有认真努力去优化它们,但是我们成功地超越了上述类似算法的速度。
统一产生了良好的效果:培训变得更快,质量更高。发展速度也提高了。每个程序员不再需要重新发明轮子——一个人现在可以简单地使用默认设置,并立即得到一个结果,而在此之前他们至少要花几天的时间进行实验。
因此,库中出现了解决分类、回归和聚类问题的方法。
在我看来,经典算法的实现并不是一项非常困难的任务,神经网络的情况更有趣。
神经网络
经典算法本质上是一组使用公共原语的独立方法。但是神经网络的实现要困难得多。除了数学和算法问题之外,非显而易见的架构和底层优化问题也出现在其中。
在查看了当时存在的 Caffe 和 TensorFlow 库之后,我们认为 Caffe 的想法更接*我们的愿景。这就是为什么我们用 blobs 而不是 tensors 来表示数据。我们希望以更高层次的概念进行操作,在训练期间修改网络,能够在使用过程中完成它,并为用户透明地组织 GPU 上的计算。
在 NeoML 中,网络是一个有向图,其顶点表示层,边表示从一些层的输出到其他层的输入的数据传输。层是执行某种操作的元素。操作可以是任何东西,从改变输入数据的形状或计算简单的数学函数到卷积或 LSTM。可以随时在网络中添加和移除图层。网络中的所有数据——输入、输出和层间传输的数据——都以 blobs 的形式呈现。blob 是一段连续的内存。该库不直接使用 blob 内存,而是通过一个特殊的独立于*台的接口。因此,实现了算法部分与直接执行计算的设备的独立性。例如,通过使用 CUDA 实现这个接口,可以在 GPU 上进行计算。
如果我们谈论网络的架构,我们从卷积网络开始,我们添加了各种卷积层、池、全连接层、激活和损失函数。简单的梯度下降被用作优化器。
稍后,循环网络 LSTM 和 GRU,高级优化器,甚至更多的激活和损失函数,CTC,CRF 等。得到了支持。
目前,该库有大约 100 种不同类型的层,这允许我们实现几乎所有的现代网络架构。
随着新架构在我们的任务中证明其有效性,我们试图扩展功能。
于是效率之争开始了。
克里斯蒂安·威迪格在 Unsplash 上拍摄的照片
CPU 计算
一个神经网络通常是一个巨大的计算量,如果没有低级别的优化,你将一事无成。首先,我们开始针对面向 Windows 的 x86 处理器进行优化,这是我们的主要*台,我们希望在这个*台上取得尽可能大的成功。
神经网络中的大多数操作都可以归结为 BLAS(基本线性代数子程序),而 x86 的最佳 BLAS 当然是英特尔 MKL。我们开始使用它。其余操作必须使用 SIMD 系统独立实施。我们只使用 SSE 指令,也有 AVX / AVX2 的实验,但它们并没有给我们的操作带来多少收益,为了降低支持成本,我们决定拒绝它们。当英特尔发布 MKL-DNN 法案时,我们非常高兴:终于,你可以不用自己写这些了!但是,不幸的是,对比显示我们的包工作速度快了 20%,这个想法还没有被放弃。
目前,NeoML 在 x86 上工作得很好,但仍有很大的优化空间,我们计划在未来的版本中进行优化。
在 Unsplash 上拍摄的 ThisisEngineering RAEng
GPU 计算
对我们来说,GPU 计算主要是学习。培训通常在公司内部或我们的云中进行。在这里,我们可以选择我们将在其上执行此操作的设备,这简化了工作:例如,如果客户端没有 AVX,则不需要支持 SSE。因此,他们决定使用 CUDA 实现 GPU 的计算引擎,并在支持它的 Nvidia 显卡上进行计算。我们做出这个决定,除了别的以外,是因为有专门的库可用:cuDNN、cuBLAS、cuSparse 等。尽管由于不断的错误和低效的操作,我们在未来放弃了 cuDNN,转而支持我们自己的实现。其余的库表现得很好,我们没有成功地编写自己的内核。
GPU 引入的结果是显而易见的。许多网络的训练速度加快了一个数量级。得益于此,开发速度加快了,模型的质量也提高了。
在主*台上获得了不错的结果,并且建立了有效的培训之后,我们考虑将这个库发布到其他*台上。
跨*台
ABBYY 的主要开发是在 Windows 上,用于培训和测试的服务器也在 Windows 上,因此库的第一个版本只适用于这个操作系统。然而,ABBYY 的产品也可以在其他*台上工作,很快我们开始将我们的库移植到 Linux 和 macOS。转移非常容易,因为我们需要的唯一英特尔 MKL 依赖项是这些操作系统的版本,并且不需要 CUDA 支持培训。唯一的困难是 Microsoft Visual Studio 编译器与 GCC 和 Clang 的差异,但这并没有花费太多时间。
现在,我们正在积极地使用 Linux 版本的库与竞争对手进行比较测量,因为 Windows 支持往往还有许多不足之处。此外,云中还有学习网络的任务。因此,在下一个版本中,我们将有一个在 Linux 上支持 CUDA 的 NeoML 版本。
马文·迈耶在 Unsplash 上的照片
移动*台
ABBYY 正在开发和销售用于图像处理和文本识别的 SDK,包括那些适用于手机的 SDK。因此,随着这些 SDK 中神经网络的出现,关于它们在移动*台上的有效启动的问题出现了。这一刻,我们又一次想到了是否使用第三方解决方案。在评估了 TensorFlow Lite for Android 和 Core ML for iOS 的集成后,我们得出的结论是,同时使用几个框架将会非常昂贵,最好改进您自己的框架,即使这是低效的。
我们开始为 ARM 创造一个“计算引擎”。用 NEON 替换 SSE,用 Eigen 替换 MKL,在几周内,我们做出了运行在 ARM CPU 上的第一个版本的库。事实证明,就效率而言,最终的解决方案完全适合我们;它甚至在速度上超过了同类产品。当然,从那时起,TF Lite 和 Core ML 都取得了长足的进步,但我们也做了许多重大的优化,其中大部分与 x86 版本重叠,并且不是很昂贵。然而,有一些特定于 ARM 的优化。其中最严重的是我们自己的矩阵乘法,多亏了它,我们超过了特征库 20%左右的速度,结果拒绝使用它。
目前,NeoML 在 CPU 上的运行方式与其同类产品大致相同,这完全符合我们的需求。
此外,为了简化 iOS 和 Android 上现成模型的发布,我们为 ObjectiveC 和 Java 语言添加了推理包装器。
移动 GPU
几乎所有现代的 Android 和 iOS 手机都配备了独立的 GPU。有趣的是,我们思考并开始研究如何开始使用它。第一次实验是用 RenderScript 完成的,完全没有结果,一切都非常慢…然而,用 OpenCL、Vulkan 和 Metal 进行的实验显示了良好的结果。在大型网络中,GPU 可以提供 5 到 7 倍的优势。在小型计算机上,由于开销的原因,CPU 仍然更快;即使在大型网络上,也不是每个 GPU 都能盈利;只有顶级型号上的昂贵芯片才能正常工作。此外,事实证明,对于不同系列的 GPU,您需要编写不同的代码:例如,针对 Adreno 优化的着色器在 Mali 上不一定工作得一样好。总的来说,现在对我们来说,在移动设备中使用 GPU 的话题是有争议的,但潜在的非常有前途。目前,我们已经实现了在 Vulkan 和 Metal 上运行的计算引擎,我们在有限的任务中使用它们,同时继续致力于它们的开发。我必须说,移动 GPU 上的计算是一个相当广阔的话题,在许多方面不同于桌面上的计算,关于它的故事值得单独撰写一篇文章。
ONNX
所以,我们有了一个完全自给自足的框架。有了它,我们可以了解自己的网络,轻松地将它们集成到桌面应用程序中,并转移到移动*台上,而无需额外的成本。一个问题仍然存在:在阅读新文章、探索新架构及其使用示例时,我们的数据科学家经常会遇到其他框架。为了快速有效地开发解决任何问题的模型,他们需要能够将模型从第三方框架转换到我们的框架中。
新的 ONNX 格式是一个很大的改进,尽管这种格式还很年轻,它在许多框架中的支持还有很多需要改进的地方,但是它正在被积极地开发,我们认为它是目前解决这个问题的最佳方案。我们支持将神经网络模型从 ONNX 下载到我们的库中。当然,我们并不支持整个格式:它有相当大的规格和几个版本,但这不是主要的。在不同的框架中,其使用的语义是不同的。比如同一个模型,如果上传到不同框架的 ONNX 上,看起来可能完全不一样。我们决定在这件事上关注 PyTorch。当然,其他人的 ONNX 模型也可以工作,但可能效率不高。
因此,模型开发过程可能看起来像这样:在 PyTorch 上完成模型的第一次实验,然后将模型存储在 ONNX 中,从 ONNX 加载到 NeoML 中,重新训练 NeoML 模型,测量其速度和质量,然后模型进入修订或生产。
现在,我们拥有了支持 ML 模型整个开发周期所需的一切。
开源
我们决定下一步做什么?我们决定创建一个开源库,这样其他人也可以从中受益
这是图书馆发展的一个新步骤。我们与社区分享我们的最佳实践,作为回应,我们希望收到评论和建议,以使我们的图书馆更快、更方便。
该库已经有了几个独特的特性,可以成为在各种*台上的各种应用程序中启动模型的有效手段。我们希望拥有类似脚本的开发人员会喜欢 NeoML,并可能在不久的将来加入到这个库的工作中来。
比较测量
我们试图定期与同行(最常见的是 TensorFlow)比较我们的库在我们的任务上的有效性,以了解我们当前的水*。在这里,例如,我将比较从 MobileNetV2 架构的 TorchVision 包直接访问公共网络的速度,该架构被训练为对 ImageNet 数据集进行分类。网络输入的尺寸为 224x224x3。测量是在我现在触手可及的台式机 CPU 和几部手机上进行的(如你所知,这个帖子是在自我隔离期间创建的)。
在运行 Ubuntu 20.04 的酷睿 i5–4400 处理器的电脑上,我们获得了以下 10,000 次网络启动的结果:
内存消耗如下:
在 10,000 次启动的 Android 手机上,结果如下:
在 iOS 手机上:
值得注意的是手机上的运行时间测量——一个吃力不讨好的任务。如果您愿意,您可以测量几乎任何结果,对几个流的测量甚至更不具有指示性(因此,这里没有显示)。但还是可以看到发射数量相当多的整体画面。
为了详细分析和优化,我们通常使用各种处理器计数器,如 cpu_cycles、cpu_instructions、cache_access、cache_miss、branch_count、branch_miss、bus_cycles 等。您还可以从中看出两个库的工作方式大致相同。
使用强大的 NeoML 框架来构建、训练和部署机器学习模型
- 支持超过 100 层类型的神经网络
- CPU 和 GPU 支持,快速推断
- 语言:C++,Java,Objective
- 传统机器学习:20 多种算法(分类、回归、聚类等)
- ONNX 支持
- 跨*台:相同的代码可以在 Windows、Linux、macOS、iOS 和 Android 上运行
随处部署
NeoML 由 ABBYY 工程师用于计算机视觉和自然语言任务,包括图像预处理、分类、文档布局分析、OCR 以及从结构化和非结构化文档中提取数据。您可以在云中、本地、浏览器或设备上部署模型。
下一步是什么
NeoML 支持开放神经网络交换(ONNX) ,这是一个用于互操作 ML 模型的全球开放生态系统,它提高了工具的兼容性,使开发人员更容易使用正确的组合来实现他们的目标。ONNX 标准是由微软、脸书和其他合作伙伴共同支持的一个开源项目。
ABBYY 邀请开发人员、数据科学家和业务分析师在 GitHub 上使用并贡献 NeoML,其代码在 Apache License 2.0 下获得许可。该公司提供个性化的开发人员支持、持续的报告审查、定期更新和性能增强。展望未来,ABBYY 计划添加新的算法和架构,以及进一步提高使用框架算法可实现的速度。
总之,我们可以说我们得到了一个体面的解决方案,允许我们组织一个完整的 ML 模型开发和实现周期。目前,NeoML 几乎用于该公司的所有产品,并且每天都在证明其有效性。
机器学习是 ABBYY 的首要任务之一。我们计划通过定期发布新版本来发展我们的库。在即将发布的版本中,我们希望添加一个 Python 包装器,支持新的网络架构,扩展对 ONNX 格式的支持,当然,还要努力提高生产率。
如果你的工作遇到与我们相似的场景,那么访问我们的 Github 并尝试 NeoML。我们欢迎任何反馈。还有,在评论里写上你的管道是什么样子的,你在里面遇到了什么问题!
基于 K 均值聚类的 ABC 分析
基于机器学习的库存规划
由 Unsplash 上的 chuttersnap 拍摄
什么是 ABC 分析?
ABC 分析假设库存中产生收入的项目遵循帕累托分布,其中很小比例的项目产生最大的收入。使用以下约定,根据重要性给库存中的项目分配一个字母:
- a 项目占项目的 20%,但贡献了 70%的收入
- b 类商品占商品的 30%,但贡献了 25%的收入
- c 类商品占商品的 50%,但贡献了 5%的收入
请记住,这些数字是粗略的,会因实际销售分布而有很大差异。关键要点是,A 类商品占库存的比例很小,但对收入的贡献最大,C 类商品占库存的比例很大,但对收入的贡献最小,B 类商品介于两者之间。
库存计划和仓储策略都依赖 ABC 分析来做出关键的物流决策。例如,仓库经理通常希望货物离装运码头最*,以减少提货所需的时间。这提高了生产率,降低了劳动力成本。
k 均值聚类
广义地说,K-means 聚类是一种无监督的机器学习技术,它试图将相似的观察结果分组在一起。它通过计算每个随机组或群的*均值或质心,并将观察结果放入具有最**均值的群中。
一旦将观测值添加到聚类中,就再次计算质心,并且相应地将点移除或添加到聚类中。重复这个过程,直到聚类稳定(即,不再从聚类中添加或删除观察值)。
这个简单的机器学习算法可以用于 ABC 分析。
K-means 聚类的最大缺点是需要预先知道聚类的个数。虽然在许多情况下很难估计,但我们知道我们要将存货分成三组进行 ABC 分析:A、B 和 c。
此外,由于使用与*均值的距离的性质,K-means 聚类假设聚类是圆形的。在这种假设下,更细微的分类问题将无法正确分类,但 ABC 分析足够简单,它可以充分代表。
类似地,使用距离作为度量常常会扭曲高维数据。幸运的是,ABC 分析只检查两个参数:一个项目产生的收入和收入是如何分配的。
所有这些因素使得 K-均值聚类成为确定 A、B 和 C 项的最佳解决方案。
数据集
本项目中使用的数据来自流行的在线零售商 Wish。该数据集仅包括整个夏季服装的在线销售。最重要的是,它显示了售出的数量和价格,这将产生每件商品的收入。完整的数据集可以在 Kaggle 上找到。
目标是根据重要性将数据集中的所有项目分类到 ABC 分类中。当查看结果时,应该有相对较少的 A 项推动了大部分收入,而大量的 C 项没有提供多少收入。
这些的分布应该是 A 品卖的最多,C 品卖的最少,B 品落在两者中间。如果商品在数据中是随机分布的(例如,第一个最高销售额的商品是 A,第二个是 C),就有一个问题需要解决。
格式化数据
所有的数据格式化和分析都将在 python 中完成。
# Import libraries
import pandas as pd
import numpy as np# read the data to a dataframe
df = pd.read_csv("Summer_Sales_08.2020.csv")
在处理任何数字之前,导入 Pandas 和 NumPy 库来帮助管理数据。
接下来,将先前保存为 CSV 文件的数据读入数据帧。
# Add a column for revenues
df["revenue"] = df["units_sold"] * df["price"]
通过简单地将售出的数量单位乘以价格,在数据框中添加一个新的收入列。价格可能会随着时间的推移而变化,尤其是在闪购发生时,但在没有进一步数据分析的情况下,假设所有商品都以一个稳定的价格出售。
import seaborn as snssns.distplot(df["revenue"])
收入分布图。图由作者制作。
上图展示了数据中的帕累托分布。绝大多数项目的收入都低于€20 万英镑(尽管图中没有明确显示,但进一步分析发现,约三分之二的项目收入低于€2 万英镑)。与此同时,一些商品的售价在€40 万英镑到€80 万英镑之间,这是收入的主要来源。
# Create bins function
def bins(x):
for bar in range(20000, 820000, 20000):
if x <= bar:
return bar# Create new column to apply the bin function
df["rev_dist"] = df["revenue"].apply(lambda x: bins(x))
编写一个函数,将一个项目产生的收入金额分类到各个箱中,然后应用于数据帧。如果一个项目产生€20,000 或更少,它被归类为€20,000。它是一个在€20,000 到€40,000 之间的项目,它被归类为€40,000,以此类推,每增加€20,000。
选择一个箱子的大小对于做出一个好的估计是至关重要的。箱子不能太大也不能太小,否则最终的 ABC 分类会有偏差。在这种情况下,选择箱的大小,使得每个箱中的物品比前一个箱中的少。可能需要进行初步的评估,然后进行调整,以达到预期的效果。
# Create a support column of 1’s to facilitate the pivot table
df["count"] = 1# Create a pivot table of the revenue distributions
pivot_table = pd.pivot_table(df, index = ["rev_dist"], values = ["count"], aggfunc = np.sum)
创建一个数据透视表来枚举属于每个类别的项目数。例如,1,072 个项目产生的€不超过 20,000。120 件物品在€20,000 到€40,000 之间,以此类推。
为 ABC 分析执行 K 均值聚类
为了正确地训练模型,仅仅查看每个项目产生多少收入是不够的。它还需要知道收入是如何分配的。这个数据透视表为模型训练提供了一个非常易于管理的数据集。
# import model from SKLearn
from sklearn.cluster import KMeans# K -clusters is equal to 3 because things will be sorted into A, B, and C
kmeans = KMeans(n_clusters=3)kmeans.fit(pivot_table)
scikit-learn 中的 K-means 模型被导入并初始化。如前所述,参数 n_clusters 设置为三,因为我们要将数据分成三个簇。然后将模型放到数据透视表上。
pivot_table["category"] = kmeans.labels_
一个新列被放置在数据透视表中,给出来自模型的分类。值得注意的是,默认情况下,scikit-learn 的 K-means 模型将按数字比例而不是 ABC 分析中使用的字母比例对项目进行分类。因此,每一行将被标记为零、一或二。
幸运的是,虽然标签不同,但实际的潜在模式是相同的。因此,数字标签将与字母标签相关联,但需要审核才能确定。在这种情况下,0 是 A,1 是 C,2 是 b。
# Create a dictionary to give alphabetical labels
ABC_dict = {
0: "A",
1: "C",
2: "B"
}pivot_table["ABC"] = pivot_table["category"].apply(lambda x: ABC_dict[x])
编写了一个快速字典,并将其应用于数据透视表,为每一行提供 ABC 分类。
# Merge the dataframes so that there's a new column to identify ABC
df = pd.merge(df, pivot_table, on = "rev_dist", how ="left")
回想一下,模型是在数据透视表上训练的。ABC 分类尚未分配给这些项目。相反,它被分配到一个收入类别。
这意味着,虽然我们不能立即知道哪些项目属于 A 类,但我们知道某些收入类别(即€780,000 到€800,000)被评为 A 类项目。
因此,我们可以简单地合并主数据框架和数据透视表,为每一项赋予其 ABC 分类。
估价
在分析物品的最终分配时,发现:
- a 项目占项目的 11.4%,但占收入的 61.7%
- b 项目占项目的 20.5%,但占收入的 30.7%
- c 项目占项目的 68.1%,但占收入的 7.6%
虽然这些数字并不完全符合帕累托分布,但数据本身很可能与这些理想化的数字有所不同。相反,更重要的是,集群非常清楚地传达出一小部分库存产生了大部分收入。
同样,所有的 A 类商品都是最畅销的商品,而所有的 C 类商品都是最畅销的商品,B 类商品正好落在中间。模型是成功的!
结论
虽然 K-means 聚类可能不是执行 ABC 分析的最有效的方法,但它展示了该模型找到相同潜在模式的能力。
随着这一成功,它打开了使用更多无监督学习技术来揭示销售和物流洞察力的大门。特别是聚类提供了一种直观的方式,可以沿着人眼可能明显也可能不明显的模式来分割产品,并且可以为使用它的人提供前沿。
基于哈伯曼生存数据集的 EDA 基础知识
简介
探索性数据分析听起来是一个非常酷的术语,直到你真正了解它是什么。通常被称为“你好,世界!”在机器学习领域,当一个人决定深入分析时,他可能会首先遇到 EDA。
假设我给你 30 分钟时间来做一个人今天可以做出的最重要的人生决定之一——决定你想买哪部智能手机。在做出最终裁决之前的半个小时里,无论你沉迷于什么程序——无论是查看在线评论、比较规格,还是观看拆箱视频——都是我们所说的“探索性数据分析”。
EDA 不完全是一种科学工具,而更像是一种哲学,它相信以开放的心态不带偏见地分析数据。这一标准程序有助于人们在对数据进行复杂的机器学习算法之前获得对数据的见解。为了让这次对话更直观,我决定加入我对 Kaggle 上最基本的数据集之一——哈伯曼癌症生存数据集所做的分析。所以让我们开始吧。
数据集
哈伯曼的数据集包含了芝加哥大学比林斯医院在 1958 年至 1970 年间对接受乳腺癌手术的患者进行的一项研究的数据。对于数据集。我在分析中使用了 Python 及其精彩的库(Pandas、Numpy、Matplotlib、Seaborn 等)。重要的一点——本文不是编码教程,而是一种机制的概述(机器学习!=用 Python 编码),所以如果你对一些代码片段感到不知所措——忽略它们,试着专注于我们试图通过它们实现的目标。
目标——永远在你的脑海中保持以下口头禅——通过随机运算进行随机分析,会给你随机结果。我们应该非常清楚我们分析的目标,我们执行的每一个操作都应该理想地让我们一点点接*它。例如,这种特殊分析背后的动机是预测癌症患者的存活几率。
首先,我们需要从。csv 文件放到我们的数据框中。
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns haberman=pd.read_csv(“haberman.csv”,header=None)
column_names=[“age”,”year”,”axillary_nodes”,”survival_status”] haberman.columns=column_names haberman.survival_status=haberman.survival_status.map({1:”yes”,2:”no”})
现在我们的数据框实际上是左边的那个,但稍加修改,它看起来就像右边的那个,更容易理解-
在继续分析之前,让我让你熟悉一些与我将从这里开始使用的数据集相关的关键词。任何数据集都有以下特征-
- 数据点/矢量/观测值 -数据框中的每一行都是一个数据点或一个观测值。它是被记录的实例之一。如果一个数据点有 n 个特征,我们称之为 n 维向量。
- 特征/输入变量/独立变量 -它是作为预测指标的数据点的组成部分。我们的数据集有 3 个特征——患者年龄、手术年份和体内腋窝/淋巴结数量。
- 标签/类/输出变量/因变量——我们准备进入这一团乱麻的一件事——做完一切后需要预测的值/结果。标签是在特征的基础上预测的,因此被命名为因变量。在这里,我们需要预测癌症患者的生存机会,这在我们的案例中充当了一个标签。
为了确定每个类有多少数据点,我们运行一个简单的命令-
g=haberman.groupby(“survival_status”).size() g
我们可以观察到,在我们的数据集中,有 225 例患者存活,81 例患者死于该疾病。我们可以得出结论,我们的数据集是一个不*衡数据集,这是病历案例中常见的观察结果。
注意,可以用这个简单的命令找出当前的全部观察值( 306 )
haberman.shape
现在,我们已经熟悉了我们的数据,让我们前进到真正的东西。
多元分析-三维散点图
既然我们的数据集有 3 个要素,为什么不快速查看相同要素的 3-d 散点图看起来是什么样的-也许我们在这一步就能解决我们的问题?
import plotly.express as px fig=px.scatter_3d(data_frame=haberman,x=”age”,y=”year”,z=”axillary_nodes”,color=”survival_status”)
fig.show()
正如你自己所看到的,没有任何由人类定义的程序可以帮助我们从混乱中理出头绪。所以回答前面的问题-不,我们不会在第一步就解决我们的问题!
双变量分析
它指的是找到 2 个特征变量之间的关系,并用它来找到感兴趣的目标变量。双变量分析中最常用的技术是二维散点图。配对图是所有可能配对的二维散点图的集合,可从我们的特征中生成。
使用配对图背后的动机是识别那些导致 2 类标签之间最佳区别的特征-生存状态:是和生存状态:否。我使用 seaborn 来绘制配对图-
sns.set_style(“whitegrid”) sns.pairplot(haberman,hue=”survival_status”,size=3)
plt.show()
注:仅考虑对角线上方的图形,因为其下方的图形是相同的图形,只是轴颠倒,不会影响我们的观察。
注意:处理配对图的一般工作流程是选择各类别之间重叠最小的图,然后选择这些图中涉及的特征进行进一步分类,以获得最佳结果。
来自配对图的观察结果
- 年龄与运营年份——高度重叠,因此被丢弃。
- 手术年份与腋窝淋巴结数目-高度重叠,因此被丢弃。
- 年龄与腋窝淋巴结数目-重叠但优于上述情况。因此,我们将选择这两个特征进行单变量分析。
配对图的限制 -当特征的数量达到一个非常大的值时,不可能以一种有效的方式使用配对图进行分类,因为我们将不得不通过大量的图来识别我们的最佳特征。在这种情况下,我们使用特定的数学技术,如 PCA 和 t-SNE ( ,这将是下一篇文章讨论的主题!)进行降维。
结论——患者年龄和腋窝淋巴结数目是预测生存几率的最佳特征。
单变量分析
单变量分析也许是最简单的统计分析形式。关键事实是只涉及一个变量。
在当今世界,一个变得极为重要的事情是外交的概念,这也是全球所有数据科学家的身体和头脑中根深蒂固的概念。我们总是喜欢谈论机会,而不是预测将会发生什么。)。当我们开始谈论机会的时候,概率就开始起作用了。
概率密度函数 -它代表连续范围内数据点的密度,帮助我们确定特定结果的可能性。它是通过*滑直方图的边缘形成的。
患者年龄的 PDF
sns.FacetGrid(haberman,hue=”survival_status”,size=5)\ .map(sns.distplot,”age”)\.add_legend();
plt.title(“pdf for survival status labelling on the basis of age”) plt.show();
观察-
- 我们可以看到,基于年龄的生存状态的 PDF 在 40 至 65 岁之间的两个阶层高度重叠(曲线下的面积几乎相等)。
- 因此,在 40 至 65 岁之间,存活状态为“是”的患者的百分比和存活状态为“否”的患者的百分比几乎相同——因此该特征不适合分类。
运营年度 PDF
sns.FacetGrid(haberman,hue="survival_status",size=5)\ .map(sns.distplot,"year")\.add_legend();\
plt.title("pdf for survival status labelling on the basis of year of operation")
plt.show();
观察-
- 我们可以看到,在 1958 年和 1968 年之间,基于运行年份的生存状态 pdf 再次与两个类别高度重叠。
- 因此,在 1958 年和 1968 年之间,存活状态为“是”的患者的百分比和存活状态为“否”的患者的百分比几乎相同——因此该特征也不适合分类。
腋窝淋巴结数量的 PDF
sns.FacetGrid(haberman,hue="survival_status",size=5)\ .map(sns.distplot,"axillary_nodes")\.add_legend();
plt.title("pdf for survival status labelling on the basis of number of axillary nodes")
plt.show();
观察-
- 基于腋窝淋巴结数量的生存状态的 PDF 对于 2 个标记类别具有最小的重叠,并且是我们在进行最佳可能分类方面的最佳尝试。
- 因此,我们可以利用下面的 if-else 条件来获得相当准确的结果
如果腋窝淋巴结数> =0 且<= 3→生存状态=高
如果腋窝淋巴结数目>= 3→生存状态→低
基于腋窝淋巴结数量的详细单变量分析
现在知道了我们分类的最佳特征,我们就有机会进行更详细的分析,以获得一些具体的结果。
y=haberman.survival_status=="yes"
n=haberman.survival_status=="no"
haberman[y]
haberman[n]
对于存活的患者(存活状态:是)
count,bin_edges=np.histogram(haberman[y].axillary_nodes,bins=20,density=True)
print(count)
print(bin_edges)
pdf=count/sum(count) cdf=np.cumsum(pdf) plt.plot(bin_edges[1:],pdf,’g’,label=”PDF FOR SURVIVAL STATUS YES”) plt.plot(bin_edges[1:],cdf,’b’,label=”CDF FOR SURVUVAL STATUS YES”) plt.xlabel(“NUMBER OF AXILLARY NODES”)
plt.title(“pdf and cdf number of axillary nodes-survival status:YES”) plt.legend() plt.show()
观察-
- 蓝线显示了所有存活患者的 CDF(除了 PDF 值的累积和之外什么都没有)。
- 从蓝线中,我们可以清楚地看到,大约 85%的幸存患者体内的腋窝淋巴结少于 5 个。
- 如果腋窝淋巴结> =0、< =5 →生存状态=高→这个说法有 85%的几率是正确的。
- 我们还可以从 CDF 中看到,当腋窝病例的数量达到 10 个时,存活的机会变得非常低,因为存活的总患者只有 10%具有超过 10 个淋巴结。
对于未存活的患者(存活状态:否)
count,bin_edges=np.histogram(haberman[n].axillary_nodes,bins=20,density=True)
print(count)
print(bin_edges)
pdf=count/sum(count)
cdf=np.cumsum(pdf)
plt.plot(bin_edges[1:],pdf,'g',label="PDF FOR SURVIVAL STATUS NO")
plt.plot(bin_edges[1:],cdf,'b',label="CDF FOR SURVIVAL STATUS NO")
plt.xlabel("NUMBER OF AXILLARY NODES")
plt.title("pdf and cdf for number of axillary nodes-survival status:NO")
plt.legend()
plt.plot()
观察-
- 我们可以从 CDF 中看到,在所有未存活的患者中,超过 60%的患者体内存在 3 个以上的腋窝淋巴结。
- 如果腋窝淋巴结>= 3→生存状态=低→这个说法有 60%的几率是正确的。
结合以上两个图
count,bin_edges=np.histogram(haberman[y].axillary_nodes,bins=20,density=True)
pdf=count/sum(count)
cdf=np.cumsum(pdf)
plt.plot(bin_edges[1:],pdf,’g’,label=”PDF FOR SURVIVAL STATUS YES”) plt.plot(bin_edges[1:],cdf,’b’,label=”CDF FOR SURVUVAL STATUS YES”) count,bin_edges=np.histogram(haberman[n].axillary_nodes,bins=20,density=True)
pdf=count/sum(count) cdf=np.cumsum(pdf) plt.plot(bin_edges[1:],pdf,’r’,label=”PDF FOR SURVIVAL STATUS NO”) plt.plot(bin_edges[1:],cdf,’y’,label=”CDF FOR SURVIVAL STATUS NO”) plt.xlabel(“NUMBER OF AXILLARY NODES”)
plt.title(“pdf and cdf for number of axillary nodes for both survival status”)
plt.legend()
plt.plot()
单变量分析的最终观察结果-
我们可以使用下面的 if-else 条件,通过单变量分析来预测生存的机会-
- 如果腋窝淋巴结数> =0,腋窝淋巴结数<= 3→存活几率=高→这种说法大约有 75%的准确性,因为在存活的所有患者中,75%的患者腋窝淋巴结少于 3 个,25%的患者腋窝淋巴结多于 3 个。
- 如果腋窝淋巴结数目>= 3→存活几率=低→这种说法大约有 60%的准确性,因为在所有未存活的患者中,60%有 3 个以上的腋窝淋巴结,40%有 3 个以下的腋窝淋巴结。
基本统计
- 表示 -所有数据点的*均值。整个数据围绕这个中心值展开。
- 标准差 -数据围绕中心值扩散的度量。
- -当所有数据点从最少到最多排列时的中间值(集中趋势的另一种度量)。中位数优于*均值,原因很简单,它受数据集中异常值或极值的影响最小。在一半的数据点被破坏之前,中值不会受到太大影响。
print(“for all the patients who survived: \n”)
#to check the central value
print(“mean number of axillary nodes: {} \n”.format(np.mean(haberman[y].axillary_nodes))) #to check the spread about the central value
print(“standard deviation from the mean number of axillary nodes: {} \n”.format(np.std(haberman[y].axillary_nodes))) #to check the central value which is least affected by outliers print(“the middle value or the median number of axillary nodes: {} \n”.format(np.median(haberman[y].axillary_nodes)))
print(“for all the patients who did not survive: \n”)
#to check the central value
print(“mean number of axillary nodes: {} \n”.format(np.mean(haberman[n].axillary_nodes))) #to check the spread about the central value
print(“standard deviation from the mean number of axillary nodes: {} \n”.format(np.std(haberman[n].axillary_nodes))) #to check the central value which is least affected by outliers print(“the middle value or the median number of axillary nodes: {} \n”.format(np.median(haberman[y].axillary_nodes)))
观察-
- 所有存活的患者*均有 2.8 个腋窝淋巴结,偏差为 5.8。
- 所有未存活的患者*均有 7.5 个腋窝淋巴结,偏差为 9.1。
高级统计
- 百分位数- 通常以低于数据集中特定值的总值的百分比来表示。例如,如果我说 45 分代表一次测试中的 85 %,那么这意味着参加测试的学生中有 85%的人得分低于 45 分。
- 分位数- 一个有趣的术语,用来表示第 25、50、75 和 100 百分位。第 50 百分位不过是中值。
- 分位数范围(IQR) -第 25 个百分位和第 75 个百分位之间的差值。有些人也用它作为标准偏差的代表来分析价差,因为 50%的总值都在这个范围内。
print(“for all the patients who survived: \n”) print(“number of axillary nodes at 75th percentile: {} \n”.format(np.percentile(haberman[y].axillary_nodes,75))) print(“the quantiles are nothing but the values at 0th,25th,50th,75th percentile”) print(“the quantiles for the number of axillary nodes:”) print(np.percentile(haberman[y].axillary_nodes,np.arange(0,100,25))) print(“the inter quantile range is the difference of the value at the 75th and the 25th percentile”)
print(“the inter quantile range for number of axillary nodes in patients who survived is:”) x=np.percentile(haberman[y].axillary_nodes,75) y=np.percentile(haberman[y].axillary_nodes,25)
print(x-y)
print(“for all the patients who did not survive: \n”) print(“number of axillary nodes at 75th percentile: {} \n”.format(np.percentile(haberman[n].axillary_nodes,75)))
print(“the quantiles are nothing but the values at 0th,25th,50th,75th percentile”)
print(“the quantiles for the number of axillary nodes:”) print(np.percentile(haberman[n].axillary_nodes,np.arange(0,100,25))) print(“the inter quantile range is the difference of the value at the 75th and the 25th percentile”)
print(“the inter quantile range for number of axillary nodes in patients who did not survive is:”) x=np.percentile(haberman[n].axillary_nodes,75) y=np.percentile(haberman[n].axillary_nodes,25)
print(x-y)
箱形图-分位数的特殊图
直方图和 pdf 的一个主要问题是,它只能告诉我们特定事件发生的可能性。它没有给我们任何关于在某一点之前发生的可能性的线索。
CDF 在一定程度上解决了这个问题,但是如果我们想要更多的直觉呢?这就是箱形图的用武之地,它是专门用来处理分位数的。
sns.boxplot(x=”survival_status”,y=”axillary_nodes”,data=haberman) plt.title(“box plot for number of axillary nodes”)
plt.show()
考虑橙色的方框图-
- 下面的线代表第 25 百分位。
- 中间的线代表第 50(中间)百分位数。
- 上面的线代表第 75 百分位。
- 方框的高度代表分位数区间。
- 延伸的垂直线被称为胡须,其长度是分位数间距的 1.5 倍。
小提琴情节-两全其美!
到目前为止,我们已经讨论了用于讨论数据密度的直方图/pdf 和用于讨论分位数的箱线图。如果我告诉你,有另一种情节把两者结合在一起呢?
sns.violinplot(x="survival_status",y="axillary_nodes",data=haberman)
plt.title("violin plot for number of axillary nodes")
plt.show()
- 小提琴内部的盒子充当盒子情节。
- 具有不同密度的外部小提琴充当 PDF。如果观察有倾斜头部的小提琴——它看起来就像讨论概率密度函数时观察到的钟形曲线!
总结分析
- 永远不要忘记任何分析背后的动机,因为 EDA 的性能与其目标是一致的。
- 一个好的做法是在完成后用简单明了的英语记下每种调查方法的结果,以便任何人都能理解。
结论
利用本文中讨论的各种分析工具和技术,我们通过从中得出结论性的结果,成功地探索了 Haberman 的癌症生存数据集。
原载于 2020 年 10 月 12 日【https://mahavirdabasmd.wixsite.com】。**
抽象基类以及如何在您的数据科学项目中使用它们
公共许可证
通过使用这种面向对象的编程构建块,编写更干净、更安全的 python 代码
您是否曾经遇到过这样的代码,并且想知道这些类和方法有什么如此抽象?好吧,我要让你看看!
如果你能坚持足够长的时间,我还会分享一个小技巧,你可以用它在你的类中自动化单元测试。
遗产
面向对象编程(OOP)的一个关键概念是继承。继承意味着我们将一个(子)类建立在另一个(父)类的基础上。因此,子类从其父类继承某些属性,同时实现新的属性。
让我们看一个例子。假设你想写一个关于动物世界的软件库。你可能会从定义一个类动物开始:
class Animal: def __init__(self, height, weight):
self.height = height
self.weight = weight
动物是一个非常笼统的术语,这就是为什么您想要创建更具体的类:
class Dog(Animal):
def make_sound(self):
print('woof!')class Cat(Animal):
def make_sound(self):
print('meow!')
def pounce(self):
print('Pouncing at prey!')
在括号中写动物表示狗和猫 从动物类继承。这意味着,不用写出来,两个动物都会自动实现 init 方法。此外,两个子类都实现了自己的方法:“make_sound”和“猛扑”。根据经验,如果你的两个类符合“A 是 a B】:“狗是一种动物”这句话,那么继承是有意义的。
假设您想要实现一个 lion 类。狮子是猫,所以我们希望这个类继承自猫。这样一来,猫从动物那里继承的方法也同样适用于狮
class Lion(Cat):
def make_sound(self):
print('roar!')
狮子这个类现在有三个方法: init 、猛扑和 make_sound 。通过在 Lion 类中重新定义 make_sound ,我们已经覆盖了从 Cat 继承的版本。
抽象基类
抽象基类(ABC)提供了一种方法来管理这种继承,同时构造您的代码。一个 ABC 可以被看作是脚手架或者模板(不要和实际的模板混淆,想想:C++!)用于从它继承的所有类。
在 Python 中,可以通过继承 abc 来定义 ABC。ABC:
import abc
class Animal(abc.ABC):
一个 ABC并不意味着被实例化,也就是说,一个人不应该(在某些情况下不能)创建一个 ABC 的对象。
my_animal = Animal(height=100, weight=80) #Don't do this!
那么,为什么还要使用抽象基类呢?因为,就像我之前说的,他们把结构和安全加到你的项目里。ABC“Animal”告诉未来开发您的代码的开发人员(或未来的您)从 Animal 继承的任何类应该如何操作。要做到这一点,ABC 有一个工具可供使用:
抽象方法
抽象方法是必须由任何从 ABC 继承的类实现的方法。
例如,我们可以决定代码中的每种动物都必须能够发出某种声音。然后我们可以定义:
from abc import ABC, **abstractmethod**class Animal(ABC): def __init__(self, height, weight):
self.height = height
self.weight = weight **@abstractmethod**
def make_sound(self):
passclass Bird(Animal): def fly(self):
print('I am flying')
如果我们试图实例化任何没有实现抽象方法的子类,我们会得到以下错误:
tweetie = Bird(height=5, weight=1)>>> TypeError: Can't instantiate abstract class Bird with abstract methods make_sound
在一个新项目的开始,开发人员应该暂停一下,考虑哪些方法对于一个类的正常运行是绝对必要的。这些方法应该被声明为抽象方法,以避免将来出现意外的运行时错误。
在我看来,这在 Python 这样的非编译语言中尤其重要,这种语言在这些错误面前非常脆弱。
现实生活中的例子
许多流行的数据科学和机器学习库使用抽象基类。其中一个库是 scikit-learn。本文开头的代码片段包含 scikit-learn 对一个“内核”基类的实现。核用于支持向量机、核脊和高斯过程方法等。它们可以被视为两个向量之间的距离度量。您可能熟悉径向基函数(RBF)或*方指数核
但是还有许多其他的存在并在 scikit-learn 中实现。
所有这些内核的共同点是(在 scikit-learn 中)它们继承自内核 ABC:
通过使用 call 和 is_stationary 抽象方法,scikit-learn 确保每个新内核都将实现这些方法。至少在 call(self,X,Y) 的情况下,这是非常合理的,作为在两个输入矩阵上评估内核的函数是绝对必要的。没有它,内核就没有多大用处。
注册和单元测试
为内核类的每个新的子类自动生成单元测试不是很好吗?
谢天谢地,有!
注册
通过创建一个所谓的注册表,我们只需要实现一个单元测试一次,就可以在我们的类中应用它(人们可以用注册表做其他有趣的事情,但是我不会在这里详细讨论)。
注册表只是记录你创建的所有类。为了用 Python 实现注册中心,我们需要使用元类。
什么是元类?
看待它的一种方式如下:
类告诉 Python 类的实例如何行为,而元类定义了类本身的行为。[1]
因此,通过使用元类,我们可以告诉 Python:“每当实现一个新类时,在注册表中创建一个新条目”
如果这一切听起来非常混乱,您也可以将以下代码复制粘贴到您的项目中:
(注意,原则上注册中心不必继承 ABCMeta,但是将两者结合起来通常是有意义的。)
让我们回到我们的内核例子。我们现在写的不是从 ABC 继承的
class Kernel(**metaclass=ABCRegistry**):
**_registry_name = 'kernel'**
...class RBF(Kernel):
**_registry_name = 'rbf'**
...class DotProduct(Kernel):
**_registry_name = 'dotproduct'**
...
通过创建 attribute _registry_name,我们告诉我们的注册表如何调用这些类。访问注册表将产生以下输出:
Kernel.get_registry()
>>> {'kernel': Kernel, 'rbf': RBF, 'dot': Dot}
单元测试
假设我们想要测试我们实现的内核是否是对称的:
K(X,Y) = K(Y,X)
每个有效的内核都必须遵守这个条件,所以测试它是很有意义的。
使用 pytest 及其参数化功能,我们现在可以自动将测试应用到从“内核”继承的每个类:
当然,人们总是可以显式地循环所有相关的类。使用注册表的好处是,添加新类的贡献者也不需要担心向适当的测试添加条目。
如果你喜欢这篇文章,请随时关注我,在Twitter或在LinkedIn上联系。
参考文献
[1]大致基于托马斯·伍特斯对斯塔克伟福的解释。
Python 中的抽象基类:数据科学家的基础
用一个具体的例子来理解基础!
约书亚·阿拉贡在 Unsplash 上拍摄的照片
在 Python 中,抽象基类为具体类提供了蓝图。它们不包含实现。相反,它们提供一个接口,并确保派生的具体类得到正确实现。
- 抽象基类不能被实例化。相反,它们被具体的子类继承和扩展。
- 从特定抽象基类派生的子类必须实现该抽象基类中提供的方法和属性。否则,在对象实例化期间会引发错误。
让我们编写一个 Python3 代码,其中包含实现抽象基类的简单示例:
from **abc** import **ABCMeta, abstractmethod***class* **AbstactClassCSV**(*metaclass* = *ABCMeta*):
*def* **__init__**(*self*, *path*, *file_name*):
self._path = path
self._file_name = file_name **@*property* @abstractmethod**
*def* path(*self*):
pass **@path.setter
@abstractmethod**
*def* path(*self*,*value*):
pass **@*property* @abstractmethod**
*def* file_name(*self*):
pass **@file_name.setter
@abstractmethod**
*def* file_name(*self*,*value*):
pass **@abstractmethod**
*def* display_summary(*self*):
pass
约翰·邓肯在 Unsplash 上的照片
定义抽象基类
Python 为抽象基类定义提供了一个 abc 模块。我们需要导入 ABCMeta 元类,并将其分配给我们想要定义的抽象类。
from **abc** import **ABCMeta, abstractmethod***class* **AbstactClassCSV**(*metaclass* = *ABCMeta*):
.....
.....
在抽象基类内部,我们使用@ abstract methoddecorator 强制子类实现 path 和 file_name 属性。请注意,这些属性没有实现并且为空,因为抽象类仅用于定义接口。
**@*property* @abstractmethod**
*def* path(*self*):
pass **@path.setter
@abstractmethod**
*def* path(*self*,*value*):
pass **@*property* @abstractmethod**
*def* file_name(*self*):
pass **@file_name.setter
@abstractmethod**
*def* file_name(*self*,*value*):
pass
同样,使用 @abstractmethod 装饰器,我们可以定义一个抽象方法,并强制子类实现display _ summary(self)方法。
**@abstractmethod**
*def* display_summary(*self*):
pass
此时,如果我们试图实例化一个抽象类 AbstactClassCSV 的对象,我们会得到一个错误。
**abc_instantiation** = **AbstactClassCSV**("/Users/erdemisbilen/Lessons/", "data_by_genres.csv")**Output:**Traceback (most recent call last):
File "ABCExample.py", line 119, in <module>
abc_instantiation = AbstactClassCSV("/Users/erdemisbilen/Lessons/", "data_by_genres.csv")
**TypeError: Can't instantiate abstract class AbstactClassCSV with abstract methods display_summary, file_name, path**
Benoit Gauzere 在 Unsplash 上拍摄的照片
创建从抽象基类派生的具体子类
现在我们已经定义了抽象基类( AbstactClassCSV) ,我们可以通过继承来创建子类。
下面,我通过继承 AbstactClassCSV 抽象类,创建了 CSVGetInfo 具体类。因此,我必须严格遵循抽象类提供的接口,并在我的具体子类中正确实现所有规定的方法和属性。
*class* **CSVGetInfo**(***AbstactClassCSV***):**""" This class displays the summary of the tabular data contained in a CSV file """** **@*property*** *def* **path(*self*)**:
""" The docstring for the path property """
print("Getting value of path")
return self.**_path** **@path.setter**
*def* **path(*self*,*value*):**
if '/' in value:
self.**_path** = value
print("Setting value of path to {}".format(value))
else:
print("Error: {} is not a valid path string".format(value))**data_by_genres** = CSVGetInfo("/Users/erdemisbilen/Lessons/", "data_by_genres.csv")**Output:**Traceback (most recent call last):
File "ABCExample.py", line 103, in <module>
**data_by_genres** = CSVGetInfo("/Users/erdemisbilen/Lessons/", "data_by_genres.csv")
TypeError: Can't instantiate abstract class **CSVGetInfo** with abstract methods **display_summary, file_name**
为了演示这个案例,我只定义了路径属性,没有实现文件名属性和显示摘要方法。
如果我试图在这种状态下实例化 CSVGetInfo 的对象,就会出现上面的错误。
这就是抽象类如何防止不正确的子类定义。
*class* **CSVGetInfo(*AbstactClassCSV)*:**
**""" This class displays the summary of the tabular data contained
in a CSV file """** **@*property*** *def* **path(*self*):**
""" The docstring for the path property """
print("Getting value of path")
return self._path **@path.setter**
*def* **path(*self*,*value*):**
if '/' in value:
self._path = value
print("Setting value of path to {}".format(value))
else:
print("Error: {} is not a valid path string".format(value)) **@*property*** *def* **file_name(*self*):**
""" The docstring for the file_name property """
print("Getting value of file_name")
return self._file_name **@file_name.setter**
*def* **file_name(*self*,*value*):**
if '.' in value:
self._file_name = value
print("Setting value of file_name to {}".format(value))
else:
print("Error: {} is not a valid file name".format(value))*def* **display_summary(*self*):**
data = pd.read_csv(self._path + self._file_name)
print(self._file_name)
print(data.info())
由于我们已经定义了所有必需的属性和上面抽象类指定的方法,现在我们可以实例化并使用派生子类 CSVGetInfo 的对象。
文森特·范·扎林盖在 Unsplash 拍摄的照片
关键要点
- 抽象基类将接口与实现分开。
- 它们确保派生类实现抽象基类中指定的方法和属性。
- 抽象基类将接口与实现分开。它们定义了必须在子类中使用的泛型方法和属性。实现由具体的子类来处理,我们可以在其中创建可以处理任务的对象。
- 它们有助于避免错误,并通过提供创建子类的严格方法,使类层次结构更容易维护。
结论
在这篇文章中,我解释了 Python 中抽象基类的基础知识。
这篇文章中的代码可以在我的 GitHub 库中找到。
我希望这篇文章对你有用。
感谢您的阅读!
数据扩充的抽象概括
作者图片
一个创造性的解决不*衡的阶级分布
类别分布不均衡是机器学习中的一个常见问题。我最*在训练情感分类模型时遇到了这个问题。某些类别比其他类别更普遍,模型的预测质量受到影响。我用来解决这个问题的第一个技术是随机欠采样,其中我从每个类别中随机采样一个子集的行,直到一个上限阈值。我选择了一个合理*衡上面三个等级的天花板。虽然观察到了小的改进,但是该模型仍然远非最佳。
我需要一种方法来处理代表不足的阶层。我不能依赖多类分类中使用的传统技术,如样本和类加权,因为我正在处理多标签数据集。很明显,在这种情况下,我需要利用过采样。
诸如 SMOTE(合成少数过采样技术)之类的技术对于过采样可能是有效的,尽管对于多标签数据集,该问题再次变得更加困难。 MLSMOTE (多标签合成少数过采样技术)已经被提出[1],但是从文本创建的数字向量的高维性质有时可以使其他形式的数据增强更有吸引力。
变形金刚来了!
如果您决定阅读这篇文章,可以肯定地认为您已经了解强大的变形金刚在自然语言处理方面的最新进展。特别是拥抱脸的优秀开发者通过他们的开源贡献打开了这个世界的大门。他们最*的一个版本实现了迁移学习的突破,称为Text-To-TextTTransferTtransformer 或 T5 模型,最初由 Raffel 等人提出。艾尔。在他们的论文中,用统一的文本到文本转换器探索迁移学习的极限【2】。
T5 允许我们通过为输入文本指定前缀来执行各种 NLP 任务。在我的例子中,我对抽象概括感兴趣,所以我使用了前缀summarize
。
文本到文本转换转换器[2]
抽象概括
简而言之,抽象概括是一种技术,通过这种技术,一个文本块被提供给一个 NLP 模型,并返回该文本一个新颖的摘要。这不应该与提取摘要混淆,在提取摘要中,嵌入句子并执行聚类算法来找到最接*聚类质心的句子,即返回现有的句子。抽象概括作为一种数据扩充技术似乎特别有吸引力,因为它能够生成新颖而又真实的文本句子。
算法
以下是我使用抽象概括进行数据扩充的步骤,包括说明解决方案的代码段。
我首先需要确定每个代表不足的类需要多少行。因此,为每个特性添加的行数是用上限阈值计算的,我们称之为append_counts
。计数超过上限的要素不会被追加。特别是,如果给定的特性有 1000 行,上限是 100,那么它的追加计数将是 0。在特征已经被一次热编码的情况下,以下方法很容易实现这一点:
def get_feature_counts(self, df):shape_array = {} for feature in self.features:
shape_array[feature] = df[feature].sum() return shape_array
def get_append_counts(self, df):append_counts = {}
feature_counts = self.get_feature_counts(df)
for feature in self.features:
if feature_counts[feature] >= self.threshold:
count = 0
else:
count = self.threshold - feature_counts[feature]
append_counts[feature] = count
return append_counts
对于每个特征,从附加索引范围到为给定特征指定的附加计数完成一个循环。这个append_index
变量和一个任务数组的引入是为了允许多重处理,我们稍后会讨论。
counts = self.get_append_counts(self.df)
# Create append dataframe with length of all rows to be appended
self.df_append = pd.DataFrame(
index=np.arange(sum(counts.values())),
columns=self.df.columns
)
# Creating array of tasks for multiprocessing
tasks = []
# set all feature values to 0
for feature in self.features:
self.df_append[feature] = 0
for feature in self.features:
num_to_append = counts[feature]
for num in range(
self.append_index,
self.append_index + num_to_append
):
tasks.append(
self.process_abstractive_summarization(feature, num)
)
# Updating index for insertion into shared appended dataframe
# to preserve indexing for multiprocessing
self.append_index += num_to_append
为唯一具有给定特征的所有行的指定大小的子集计算抽象概括,并将其添加到附加数据帧中,其各自的特征被一位热编码。
df_feature = self.df[
(self.df[feature] == 1) &
(self.df[self.features].sum(axis=1) == 1)
]
df_sample = df_feature.sample(self.num_samples, replace=True)
text_to_summarize = ' '.join(
df_sample[:self.num_samples]['review_text'])
new_text = self.get_abstractive_summarization(text_to_summarize)
self.df_append.at[num, 'text'] = new_text
self.df_append.at[num, feature] = 1
抽象总结本身是通过以下方式生成的:
t5_prepared_text = "summarize: " + text_to_summarize
if self.device.type == 'cpu':
tokenized_text = self.tokenizer.encode(
t5_prepared_text,
return_tensors=self.return_tensors).to(self.device)
else:
tokenized_text = self.tokenizer.encode(
t5_prepared_text,
return_tensors=self.return_tensors)
summary_ids = self.model.generate(
tokenized_text,
num_beams=self.num_beams,
no_repeat_ngram_size=self.no_repeat_ngram_size,
min_length=self.min_length,
max_length=self.max_length,
early_stopping=self.early_stopping
)
output = self.tokenizer.decode(
summary_ids[0],
skip_special_tokens=self.skip_special_tokens
)
在最初的测试中,对 T5 模型的汇总调用极其耗时,甚至在 GCP 的 NVIDIA Tesla P100 实例上也达到了 25 秒。显然,这需要解决,以使其成为数据扩充的可行解决方案。
多重处理
我引入了一个multiprocessing
选项,对抽象概括的调用存储在一个任务数组中,稍后传递给一个子程序,该子程序使用多处理库并行运行调用。这导致运行时间呈指数级下降。我必须感谢大卫·福斯特简洁的 stackoverflow 贡献!
running_tasks = [Process(target=task) for task in tasks]
for running_task in running_tasks:
running_task.start()
for running_task in running_tasks:
running_task.join()
简化解
为了方便大家,我将它打包成一个名为 absum 的库。可以通过 pip: pip install absum
进行安装。也可以直接从库下载。
在自己的数据集上运行代码只需导入库的Augmentor
类并运行其abs_sum_augment
方法,如下所示:
import pandas as pd
from absum import Augmentorcsv = 'path_to_csv'
df = pd.read_csv(csv)
augmentor = Augmentor(df)
df_augmented = augmentor.abs_sum_augment()
df_augmented.to_csv(
csv.replace('.csv', '-augmented.csv'),
encoding='utf-8',
index=False
)
absum 默认使用拥抱脸 T5 模型,但它是以模块化的方式设计的,允许您使用任何预先训练或开箱即用的变压器模型,能够进行抽象概括。它是格式不可知的,只期望一个包含文本和独热编码特征的数据帧。如果存在您不希望考虑的其他列,您可以选择将特定的独热编码特性作为逗号分隔的字符串传递给features
参数。
还需要特别注意的是min_length
和max_length
参数,它们决定了结果汇总的大小。我发现一个有用的技巧是找到你正在处理的文本数据的*均字符数,从稍微小一点的最小长度开始,同时稍微填充它以获得最大长度。所有可用参数在文件中有详细说明。
欢迎在评论中添加任何改进建议,或者在 PR 中添加更好的建议。编码快乐!
参考
【1】f . Chartea,A.Riverab,M. del Jesus,F. Herreraac, MLSMOTE:通过合成实例生成处理不*衡多标签学习【2015】《基于知识的系统》,第 89 卷,2015 年 11 月,第 385–397 页
【2】c . raff El,N. Shazeer,A. Roberts,K. Lee,S. Narang,M. Matena,Y. Zhou,W. Li,P. Liu, 用统一的文本到文本转换器探索迁移学习的极限 ,《机器学习研究杂志》,21,2020 年 6 月。
【3】d .福斯特, Python:如何并行运行 Python 函数? 从 stackoverflow.com 取回,2020 年 7 月 27 日。
学术界、税务和数据科学
在我即将开始为期 10 个月的数据科学训练营之际,我觉得回顾一下引领我来到这里的道路会很有趣。
一个数学开始
我于 2012 年毕业于伦敦大学学院(UCL),获得数学一级荣誉理学硕士学位。我选择这个科目是因为我对这个科目的热情,特别喜欢纯粹的抽象数学模块,如数论。暑假期间,我参加了本科生的研究项目,交了很多好朋友,并最终发表了论文。在我的理学硕士论文中,我分析了康威生命游戏的结构(在数学意义上),并在波士顿的联合数学会议上以海报的形式展示了我的工作。毕业后,我在帝国理工学院担任研究职位,并开始攻读代数几何博士学位。然而,事情发生了不同的转变,我开始看不到“真实的世界”,我写论文的动机也减弱了。数学的优雅不再足够,我发现自己卡住了。这都是抽象的废话(我要补充的是,这是一个实际的数学领域。)我的 UCL 同学都在金融、银行或专业服务领域追求收入丰厚的职业,我也想加入职场。
从左到右:1。伦敦大学学院,2。我的毕业照,3。MSCi 论文海报
税务调查的插曲
我是偶然进入专业服务领域的,尤其是税务调查和争议解决。我并没有成为税务顾问的强烈愿望,但公司提供了一个“研究生计划”,人们可以在工作的同时学习相关资格。我获得了 ATT 和注册税务师资格,并对英国的税收制度有了全面的了解。起初,在伦敦金融城的企业界工作令人兴奋!我从一家顶级公司跳槽到另一家,一路上获得了晋升。然而,随着我职业生涯的进展,它变得不那么与数字运算有关,而是更多地与管理人员和项目有关。我看着我的资深同事,意识到自己走错了路。同样显而易见的是,税收的“前沿”或技术层面更接*法律,而不是数学,作为一个雄心勃勃、干劲十足的人,我不想停滞不前。
我是在休产假时得到这些启示的。成为一名母亲改变了我的观点,因为我想要一份令我自豪的职业,这将使每天早上离开我的女儿变得更容易忍受。我知道我想用数学和分析技巧来解决问题,税务咨询的世界不再适合我。
从左到右:1。我旧办公室附*的风景,2。为注册税务师考试而学习。公司休假日
发现数据科学
在换尿布和不眠之夜之间,我发现了数据科学。听播客、读文章和与我在该领域的朋友交谈,证实了数据科学正是我一直在寻找的。我立即被机器学习的所有不同应用迷住了,但最重要的是,这是一个将使用我的数学背景的领域,在那里我可以有一个有影响和有意义的职业生涯。作为一个喜欢谜题和挑战的人,数据科学的调查方面确实吸引了我。
我开始利用在线资源自学 Python,并报名参加了数据科学 MOOC 课程。这绝对是一个令人开心的时刻!在新的环境中看到我曾经学过的概率和统计定理是令人兴奋的!在编码方面,迄今为止,我已经在不同的地方涉足过编程(高中时是 TI-Basic,雄心勃勃地拿起一本关于 C 的书,一些 MATLAB ),但从未有过具体的目的。编程本身很有趣,但现在它变成了处理数据的工具。
虽然我可以继续自学,但我决定参加一个训练营,主要是为了从结构、导师和社区中受益。由于我已经获得了硕士学位,我不想走上大学的道路,而是专注于尽快使用数据科学工具,并建立一个项目组合。我知道接下来的 10 个月将会是艰苦的工作,但也是值得的!
从左到右:1。我刚出生的女儿和我,2。散点图,3。在我的笔记本电脑上编码
从学术界到数据科学:可转移的技能
如何利用您的实验室技能成为成功的数据科学家
作者照片
12 周前,我决定辞去学术界博士后研究员的工作,加入了一个为期 12 周的数据科学沉浸式训练营(你猜对了!训练营就要结束了!!🎉).
这个职业转换对我来说不是一个容易的决定。在我之前的博客中,我解释了导致我做出这个决定的原因。
作为一个在学术界度过了大部分职业生涯的人,我有点害怕进入数据科学的世界,因为我认为我可能缺乏作为一名数据科学家取得成功的必要技能。
现在,12 周后,我意识到我的怀疑是多么错误。事实上,我很惊讶,我在学术界发展的许多技能是可以转移的,并且是我作为数据科学家研究员取得成功的关键。
在这里,我将分享我认为非常有用的五大可转换技能。
数据处理
作为学术界的研究人员,我们每天都在处理数据。这包括数据收集、清理、分析和可视化。拥有这些技能对于成为一名成功的数据科学家非常有帮助(顾名思义!).
当然,你可能仍然会感到害怕,特别是如果你没有任何编码语言的经验,而且非常诚实地说,我一开始也有同样的感觉,但是我很快意识到学习如何编码(特别是使用 python)很容易,但是学习如何处理数据很难。
所以振作起来!你已经知道最难的部分了!🥳
照片由 Myriam Jessier 在 Unsplash 上拍摄
统计分析
在某种程度上,这种技能是数据处理技能的延伸。在研究中,对收集的数据进行统计分析是非常常见的。这是我们试图理解我们的数据,揭示有趣的趋势和模式,并分析群体之间的差异。作为一名数据科学家,牢固掌握统计学和统计方法至关重要。
如果你觉得有必要提高你的统计分析技能,这里有一本关于统计学习方法的好书。
在 Unsplash 上拍摄的 ThisisEngineering RAEng
文献评论
数据科学领域瞬息万变。作为一名成功的数据科学家,你需要跟上文献的步伐。
幸运的是,在学术界,我们在如何研究、阅读和跟上当前文献方面获得了广泛的培训和经验。尽管数据科学的文献可能与我们在学术界(就我而言是神经科学)所熟悉的不同,但拥有这些技能将大大加快你的学习过程。
伟大的文学作品应该对读者有所裨益:尽管枯燥,但必须加速他们的感知,尽管生硬,但必须增强他们的辨别力,并锤炼他们个人观点的稚嫩-A. E .豪斯曼
解决问题
我不记得有哪一次我的实验第一次就非常成功。大多数时候,实验并不像预期的那样工作,我不得不回到绘图板去找出哪里出了问题以及如何解决它。
我在数据科学领域也经历了同样的模式。我在从事不同的项目时遇到了许多障碍,事情并没有马上完美地进行。你解决问题和战略性思考的能力将帮助你识别问题,并在下次尝试时战略性地解决问题。
阿尔瓦罗·雷耶斯在 Unsplash 上拍摄的照片
通讯技能
最后但同样重要的是,有效的沟通技巧。
作为一名数据科学家,如果你不知道如何正确有效地与他人交流,你的工作和发现将毫无意义。
令人欣慰的是,在学术界,我们通过在国家和国际会议上的演讲和海报展示,学会了如何有效地交流和分享我们的发现。我们还希望通过书面出版物定期分享我们的工作。
此外,在学术界,我们不仅熟悉与同行科学家交流科学,也熟悉与公众交流科学。换句话说,我们知道如何为非技术人员简化复杂的概念,这是最重要也是最难掌握的沟通技巧之一。
这里有一篇很棒的文章,里面有一些关于如何提高你作为数据科学家的沟通技巧的提示。
结论
从学术界转向数据科学的职业道路可能会非常令人生畏,可能会让你怀疑自己是否有能力成为一名成功的数据科学家。
好消息是,你已经具备了成为数据科学家所需的大部分技能。这些包括数据处理,统计分析,文献回顾,解决问题和沟通技巧。
事实上,曾经有人告诉我,仅仅因为拥有这些技能,我就已经被认为是一名数据科学家了,尽管当时我并不熟悉 python(以及一般的编码)。这说明这些技能对于数据科学是多么重要和关键。
永远记住学习永无止境,不断学习和练习来打磨这些技能。
“阻碍你的不是你是什么样的人,而是你认为自己不是什么样的人。”——丹尼斯·威特利
感谢阅读!请随时在 LinkedIn 、 Github 或 Twitter 上与我联系!
用 Pingouin 加速数据科学家复杂的统计测试
在一个包中快速简单的重要统计测试
作为一名数据科学家,我们的工作包括创建一个机器学习模型,并建立我们对数据的假设。
了解我们的数据如何相关以及目标统计数据之间的任何差异会对我们的数据分析和模型创建产生很大影响。
如果你想在数据科学领域取得优势,我真的鼓励你学习基本的统计学和假设检验。
不管你在统计测试方面的知识如何,我想介绍一个有趣的开源统计包,我知道它会在你的日常数据科学工作中有用(因为它对我有帮助)——这个包叫做 Pingoiun 。
让我们来看看这份套餐提供了什么,以及它如何为我们的工作做出贡献。
*古因
根据 Pingouin 主页,这个软件包是为那些想要简单而详尽的统计功能的用户设计的。
之所以这样设计,是因为有些函数,就像 SciPy 中的 t-test,在我们需要更多关于数据的解释时,只返回 T 值和 p 值。
在 Pingouin 包中,计算是在上面几个步骤中进行的。例如,除了仅返回 T 值和 p 值之外,来自 Pingouin 的 T 测试还返回测试的自由度、效应大小(Cohen 的 d)、均值差异的 95%置信区间、统计功效和贝叶斯因子(BF10)。
让我们用一个真实的数据集来试试这个包。首先,让我们安装 Pingouin 包。
#Installing via pip
pip install pingouin#or using conda
conda install -c conda-forge pingouin
现在,假设我有来自不同地方的汽车 mpg 数据集(可以从 Seaborn 包中免费获得)。
import seaborn as sns
mpg = sns.load_dataset('mpg')
作者创建的图像
有了这个数据集,我可能会有一个问题。不同产地的车有没有 mpg 差异?(原产地唯一类别为“美国”、“欧洲”和“日本”)。
带着上面的问题,我已经在尝试假设不同处理(车的产地)(mpg)的因变量是有差异的。这是一个典型的假设问题。
我们知道我们需要选择哪种统计测试是有效的,来测试我们头脑中有问题的假设。为了举例,我们将使用单向 ANOVA 检验,这是一种假设检验,用于分析样本中组均值之间的差异。当您要测试的数据有两种以上的处理方式时,可以使用它。
我不会详细解释它,因为本文的目的是向您介绍 Pingouin 包;事实上,我们可能会违反一些假设。
首先,我想检查单个样本数据是否遵循正态分布(正态性检验)。我们可以通过下面的代码使用 Pingouin。
import pingouin as pgpg.normality(mpg, dv = 'mpg', group = 'origin')
作者创建的图像
默认情况下,正态性检验将使用α水*为 0.05 的夏皮罗-维尔克检验。你可以了解更多,但这里重要的是,不是每个治疗(起源)都遵循正态分布。“美国”和“欧洲”的数据不符合正态分布。
在 Pingouin 主页上,他们为我们提供了使用一些测试包的指南。其中一个是单向方差分析测试。
方差分析测试指南(来源:【https://pingouin-stats.org/guidelines.html#anova】T4)
根据上面的指南,我们的测试是组间的,因为数据是独立的。这就是为什么我们需要使用 Pingouin 来检查方差相等性。
pg.homoscedasticity(data = mpg, dv = 'mpg', group = 'origin')
作者创建的图像
默认的方差检验是使用 Levene 检验,它对于正态性的偏差是稳健的。从测试中,我们可以看到数据具有相等的方差。然后我们可以进行经典的方差分析测试。
pg.anova(data = mpg, dv = 'mpg', between = 'origin')
作者创建的图像
像往常一样,我们希望看到 p 值作为我们拒绝或不拒绝零假设的指导。上述函数的 p 值为 p-unc,即未校正的 p 值。
根据上面的结果,如果我们假设阿尔法水*为 0.05,我们可以拒绝零假设,这意味着原产地待遇和汽车的 mpg 之间存在差异。
如果你想知道哪个组是不同的,我们可以做事后测试。
pg.pairwise_tukey(data = mpg, dv = 'mpg', between = 'origin' )
作者创建的图像
根据上面的事后测试,我们使用 p-tukey 作为 p 值。从上面的结果,我们可以看到每一个人的起源都是不同的。
这意味着有证据表明,在美国、日本和欧洲生产的汽车之间的 mpg 存在差异。
这是一个使用 Pingouin 包进行统计测试的例子;你还可以使用更多的统计测试,你可以在这里看到。
结论
Pingouin 是一个简单而详尽的统计软件包,旨在简化您的统计分析。使用一行程序可以生成关于数据的重要信息,您可以使用这些信息来分析或创建预测模型。
如果您喜欢我的内容,并希望获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的简讯。
如果您没有订阅为中型会员,请考虑通过我的介绍订阅。
利用这些技巧加速地理空间数据科学
关于如何用代码加速地理空间数据处理的提示和技巧
马修·施瓦茨在 Unsplash 上的照片
在这个大数据时代,大数据集无处不在,而不是例外。虽然您可以在数据科学中使用一些其他加速技术,但地理数据科学有特殊的技术来增强您的地理数据处理。在这篇文章中,我分享了一些我最喜欢的技巧和诀窍来加速 Python 中地理空间数据的处理。
在整个教程中,我们使用纽约市出租车出行数据集。该数据包含 140 万个点。我们还使用出租车区域数据集来执行一些地理处理任务。我们首先使用 Geopandas 读取数据进行基准测试。
让我们导入本教程中使用的库。
import geopandas as gpd
import matplotlib.pyplot as plt
import geofeather
import datashader as ds
import holoviews as hv
读取数据需要相当长的时间,这取决于计算资源。在我这边,这花了 1 分 46 秒。
我们可以通过将数据格式(Shapefile)转换为 GeoFeather 格式来加快读取时间。
1.使用 GeoFeather 快速读取地理空间数据
现在这将提高你的阅读速度,但只需要一行代码就可以将你的数据转换成 GeoFeather,这要感谢 Geofeather 库。让我们将数据转换为 GeoFeather。
geofeather.to_geofeather(gdf,'tutorialData/TaxiDataGeoFeather.feather')
在我的例子中,转换为 GeoFeather 只需要 51 秒,但仅此而已,下次您可以使用 Geofeather 读取数据,这比从 shapefile 读取数据花费的时间更少。让我们看看。
gdf = geofeather.from_geofeather(‘tutorialData/TaxiDataGeoFeather.feather’)
使用 Geofeather 阅读只需要 26 秒,而使用 Shapefiles 需要 1 分 46 秒。这是一种很棒的技术,可以帮助您快速试验地理空间数据,而无需等待很长时间。
我也发现有时根据我的需要只阅读几何的一个子集。这在最*发布的 Geopandas 0.70 之前是不可能的。第二个技巧向您展示了如何读取大型数据集的子集几何。
2.读取带有几何图形的子集
让我们先读一下滑行区域,并用我们在前面章节中读到的滑行点标出它们。
zones = gpd.read_file(“tutorialData/taxizones.shp”)fig, ax = plt.subplots(figsize=(12,10))
zones.plot(“borough”, ax=ax, legend=True)
gdf.sample(5000).plot(ax=ax, markersize=2, color=”black”)
下面的地图显示了叠加在出租车区域上的出租车点示例(用行政区着色)。
现在,假设你只需要布鲁克林区,没有必要读取全部数据。在这种情况下,您只需读取带有几何图形的数据子集。您可以通过在使用 Geopandas 读取数据时提供一个掩码来实现这一点。
gdf_subset = gpd.read_file(“tutorialData/taxidata.shp”, mask=zones[zones[“borough”].isin([“Brooklyn”])])
这只花了 38 秒,而且你只得到你所需要的,仅在布鲁克林多边形内的出租车点数据的子集。
3.空间索引可能会促进地理处理
有时,空间索引可能有助于加快地理处理任务的速度。让我们看看多边形中的点(PIP)的空间索引和非空间索引实现之间的速度差异。我们首先将出租车区域分解成区多边形,然后在没有空间索引的情况下进行空间连接。
boroughs = zones.dissolve(by=’borough’)sjoined = gpd.sjoin(gdf, boroughs, op=”within”)
在没有空间索引的情况下,这个过程需要 2 分 50 秒。让我们看看空间索引是否可以提高性能速度。
在 Geopandas 中创建空间索引非常简单。让我们对两个数据集都这样做。
gdf_sindexed = gdf
zones_sindexed = zonesgdf_sindexed.sindex
zones_sindexed.sindex
现在我们用空间索引做 PIP 处理。
sjoined = gpd.sjoin(gdf_sindexed, boroughs_sindexed, op="within")
使用空间索引,该过程需要 2 分 19 秒,与非空间索引处理相比,速度略有提高。空间索引并不总是有用,尤其是在点数据和面具有相同范围的情况下。你可以从这篇博客文章中读到关于空间索引何时有效何时无效的详细解释。
4.用 Datashader 绘图
当使用其他绘图库,如 Folium 或 Plotly 时,绘制大型数据集通常会以失败告终。Datashader 专用于绘制大型数据集。
Datashader 是一个图形管道系统,用于快速灵活地创建大型数据集的有意义的表示。
这使您可以在地图上绘制所有数据,而不会因为采集样本而受到影响。让我们用 Datashader 快速轻松地绘制所有 140 万个点。
agg = ds.Canvas().points(sjoined, ‘pickup_lon’, ‘pickup_lat’)
img = tf.set_background(tf.shade(agg, cmap=fire),”black”)
img
你得到的是所有数据的美丽的点状图。
您可以在 Datashader 中创建带有漂亮底图的交互式地图。它还可以很好地工作 PyViz 数据可视化工具,如 Geoviews,并可以与 Panel 结合使用 Jupyter 笔记本创建漂亮的仪表板。
结论
在这篇文章中,我分享了一些我最喜欢的使用 Python 进行地理空间数据科学提升的技术。您可以使用 Geofeather 或仅读取子集来加快读取时间。对于地理处理任务,值得尝试使用空间索引来加快处理时间。最后,在绘制大型数据集时,使用 Datashader 可以提高速度并获得漂亮的地图。
本教程的笔记本在 Github 中。
加速超参数调谐的简单方法
优化性能
更快获得结果
介绍
如果使用多个文件来训练神经网络模型,可能会显著减少模型调整时间。
这里有一个常见的场景:你组织和准备你的数据,编写你的神经网络模型的第一个版本,为第一次测试做好一切准备,点击 run,然后你等待。
第一个纪元要花很长时间,因为你的整个数据集都要加载到内存中。最后,在几个时期的训练(甚至几批)之后,你意识到这是行不通的——模型已经过度拟合或者只是表现不佳。所以你调整一个超参数(或十个),然后等待整个过程再次完成。
在你的结果达到要求之前,你可能会一遍又一遍地这样做。
超参数调优已经是一件苦差事;为什么要花更长时间?图片由埃利亚斯施。来自 Pixabay
如果您曾经处理过中等数量到大量的数据(比如 10GB 或更多),那么这可能是一个熟悉的场景。如果您的数据集足够大,您可能需要等待 10 分钟或更长时间才能将数据加载到内存中。即使您正在使用 DataGenerators 和 flow_from_directory(),您最终也会经历相同的延迟,只是在第一个纪元上展开。如果您的大型数据集由成千上万个小文件组成,这种延迟会特别令人痛苦。
在这篇文章中,我将教你如何使用一个简单的方法,对于某些类型的大型数据集,每次开始一个新的超参数测试运行时,可以节省你几分钟的时间。
它是如何工作的
在讨论解决方案之前,让我们先来讨论一下问题:磁盘 I/O。在许多情况下,处理大型数据集时的性能瓶颈是将数据从硬盘取出并放入内存所需的时间。在许多数据科学应用中,数据是从分布在硬盘上的数千个小碎片文件中检索出来的。
这方面的一个例子是 NIH 胸部 X 射线数据集【1】,其中包含 112,121 幅图像,总计 42GB 的数据。另一个例子是 Mozilla Common Voice 数据集[2],其中包含超过大约 380,000 个 mp3 文件的 13GB。这些数据集只是冰山一角—处理大量数据并不罕见。
从磁盘中读取数千个小文件时,使用的是随机读取操作,与长时间的顺序读取操作相比,这将导致显著的性能损失。这里有一篇文章,提供了一个很好的基本介绍这个概念。【3】
因此,我们的目标是最小化随机读取操作。实现这一点的方法很简单:将所有数据组合成尽可能少的大型二进制文件,这样加载数据所需的 I/O 操作就会从数千次缓慢的随机读取变为几次快速的顺序读取。
无论是用于分类的 2D 卷积网络、1D 回归网络还是介于两者之间的任何网络,只要需要加载大量数据以训练神经网络模型,此解决方案都将改善加载时间。
我们将共同:
- 调整数据大小并将其填充到统一的文件大小;
- 一次读取所有调整大小的图像文件;
- 将数据写入单个二进制文件;
- 执行一些性能测试,以演示读取几千个图像、几万个图像和几十万个图像的性能优势。
我们来编码。
生成二进制文件
本次测试我将使用的数据集为上述 NIH 胸部 X 线片数据集,因为它广泛可用,目前在 Kaggle 上非常流行。
从数据集构建二进制文件的方法有很多,但在本例中,我们将使用一个简单而强大的方法来演示其功效:NumPy 二进制文件。
首先,为了准备数据集,我将调整所有图像的大小,使其分辨率为 512 x 512,并确保它们是一个单一颜色通道,而且位深度为每个像素 8 位的灰度格式。下面是一些有用的函数:
调整图像大小和填充图像的示例函数。
这三个函数用于将完整图像目录的大小调整为定义的大小,并根据需要添加填充。
“…在大型数据集上执行超参数调整时,另一种节省时间的方法是预先扩充数据集(在构建二进制文件时),而不是使用动态扩充。”
创建 NumPy 二进制文件很简单。首先,读取数据和标签,并将它们添加到 NumPy 数组中。这一步可以很容易地作为前一步的一部分添加,或者在数据集预扩充期间添加(这样您就不需要将调整大小后的文件保存到磁盘上),但是为了清楚起见,我将演示作为一个单独的步骤从图像目录中构建和保存二进制文件:
一个示例函数,用于从图像文件目录及其关联的。csv 标签文件。
应该注意的是,您需要有足够的内存来从这样的数据集创建一个二进制文件。在这种情况下,在调整图像大小并限制其颜色空间后,整个数据集的二进制文件大约为 30GB。因此,您必须至少有这么多的可用内存。
对于大型数据集,您可以将数据集分割成较小的二进制文件。因此,例如,如果您只有 16GB 的内存,使用几个 4GB 的二进制文件来存储数据集以避免达到内存限制可能是值得的。
此外,需要明确的是,在构建标签数组时,我将此视为二进制分类(因此我只选择肺炎类为 1,其他所有类为 0 ),如果我真的试图使用此数据,它将是多个类的分类交叉熵,并且将完成许多其他工作以确保更好地处理数据集——但这些细节对该测试没有影响,并且我通过重用一些旧代码来节省时间。
现在我们可以简单地加载这些数据来训练我们的模型,如下所示:
如何加载您创建的 NumPy 二进制文件
如果您需要扩充数据,可以使用您喜欢的任何方法,包括 Keras 的 ImageDataGenerator:
使用 ImageDataGenerator 和 data gen . flow()Source:Keras Docs
然而,在大型数据集上执行超参数调整时,另一种节省时间的方法是预先扩充数据集,而不是使用动态扩充。如果您在构建二进制文件的过程中扩充了数据,那么以后在训练模型时就不需要将 CPU/GPU 时间专门用于这些任务。这意味着每次测试超参数时,您的数据集已经被扩充,因此不需要重新扩充。在多次重复调优的过程中,这一点会变得非常重要。在构建二进制文件的过程中这样做很方便,因为这样一来,您就不需要将文件保存到磁盘,然后重新加载调整过大小的文件来构建二进制文件。
将性能与标准方法进行比较
我们将执行四组测试,每组在数据集中使用不同数量的图像。
我们将使用 5,000 幅图像、20,000 幅图像、50,000 幅图像以及完整的 NIH 胸部 X 射线数据集的 112121 幅图像来模拟不同大小的数据集。我已经预先创建了包含每个数量的图像的二进制文件。
每个测试都将包括使用 np.load()加载数据集二进制文件,并且也是基于每个图像文件(就像使用 flow_from_directory()这样的东西所做的那样)。计时将在加载图像之前开始,并在加载完成后结束。请记住,在 flow_from_directory()场景中,图像是动态加载的,因此图像是根据需要批量加载的。这与略有不同,因为我们一个接一个地加载完整数据集中的每个图像,但是读取的总持续时间应该大约与实际模型训练会话过程中的持续时间相匹配(假设您有足够的内存来存储完整数据集,并且它不是磁盘缓存的,这实际上会影响性能)。
下图说明了使用 image_flow_from_directory 与使用此二进制文件方法的性能差异。请注意,每个值都是三次尝试的*均值,没有一次是按顺序进行的(以避免内存缓存影响结果)。所有文件(单个图像和二进制文件)都是从 WD My Book USB 3.0 外置硬盘上加载的。
我们加载时间测试的结果。越低越好。图片作者。
如您所见,总体而言,加载二进制文件比加载单个图像文件要快得多,性能优势大致与图像数量成线性关系。
结论
在本文中,我演示了如何使用二进制文件在超参数调优期间减少数据集加载时间。这很有价值,因为在超参数调整过程中,每次更改神经网络模型时都会加载数据集。
如我们的测试所示,如果您在一个中等大小的数据集上进行训练,如 NIH 胸部 X 射线数据集,您可以在每次参数迭代中节省几分钟。在 50 次迭代的过程中,这可能需要超过两个小时的时间!
这种方法的缺点是您必须有足够的内存来存储完整的数据集(或者使用多个二进制文件),并且您必须花时间编写二进制文件的创建脚本。这样做的另一个好处是,此时您还可以选择增加或调整源数据的大小。通过预先扩充您的数据集,您可以获得额外的好处,即不必重复使用 CPU 时间进行动态扩充。
这对你有帮助吗?有哪些可以改进的地方?你知道加速超参数调整迭代的其他方法吗?让我知道!
参考
[1] X. Wang 等. ChestX-ray8:医院级胸部 X 线数据库和常见胸部疾病弱监督分类和定位基准。IEEE 2017,http://open access . the CVF . com/content _ cvpr _ 2017/papers/Wang _ ChestX-ray 8 _ Hospital-Scale _ Chest _ 2017 _ paper . pdf
[2] Mozilla,Common Voice (2020),【https://voice.mozilla.org/en
[3] MapR,磁盘存储导论(2019),【https://mapr.com/blog/an-introduction-to-disk-storage/
通过批量标准化加速模型训练
什么是批处理规范化,它是如何工作的?是什么使它能够实现更快的训练?这篇文章旨在用有助于发展直觉的插图来回答上述问题。
批量归一化加速模型训练 图片来源:Sebastiaan 摄影 stam on Unsplash
Sergey io FFE、 Christian Szegedy 在 2015 年发表的批量标准化论文在深度学习社区掀起了风暴。它在发布后成为深度学习中实现最多的技术之一。值得注意的是,它能够加速深度学习模型的训练,并在少于 14 倍的训练步骤中实现相同的准确性,这是一个很大的收获。事实上,这引起了今天人们的关注(谁不想训练得更快呢?).已经有很多类似的论文,如层规范化,实例规范化和其他一些。这些方法试图克服批处理规范化的一些缺点。
让我们开始吧!
什么是正常化?
让我们从了解典型的输入数据规范化的作用开始。虽然深度学习模型不需要太多的特征工程,但将输入特征缩放到相同的范围有助于更快地训练模型。最小-最大缩放是一种这样的特征缩放方法,它将所有输入带到 0 到 1 的范围。它由下面的表达式给出。
最小-最大归一化
它只是从每个数据点中减去数据中的最小值,然后除以数据中值的范围。范围就是输入数据分布中的最大值减去最小值。通过下面的例子,您可以直观地理解这是如何改进模型训练的。考虑一个机器学习模型,它以房子的*方英尺和房间数量作为输入,并预测价格。
虽然房屋的面积可能有数百或数千*方英尺,但房间的数量大多在 10 个以下。由于不同输入要素之间范围的巨大差异,模型之间的竞争趋于一致。这是因为与较小的特征相比,模型更重视较大的特征。
还有一点需要注意的是,规范化的特征列不会像非规范化版本那样在值上有很大的变化。例如,一座大厦可能有几千*方英尺的土地,但一所小房子可能只有几百*方英尺。虽然模型应该更重视面积较大的房屋,但过大的差异会阻碍模型的学习。
那么什么是批量规范化呢?
简短版
在上一节中,我们看到了 ML 模型如何受益于规范化的输入特征。现在,让我们考虑一个全连接深度神经网络作为我们的模型。并且,如果我们为隐藏的层也增加正常化会怎么样?从技术上讲,每个隐藏层的输入都是前一层的输出。对其进行标准化似乎也是正确的,对吗?是的。这就是批处理规范化的作用。
长篇版本
在朴素梯度下降中,我们一次输入一个输入,并使用反向传播来更新模型。相比之下,使用小批量梯度下降,我们一次向前和向后传递一组输入示例。而这一捆就是我们所说的“”。因此,每个隐藏层将看到来自之前层的批量激活。让我们用一个例子来进一步探讨。
MNIST 全连接网络
考虑一个具有两个隐藏层的全连接神经网络,并假设我们正在 MNIST 数字数据集上训练它。如果你不熟悉 MNIST,数据集包含 28×28 大小的图像,数字从 0 到 9。手指的图像作为模型的输入,通过将其分解成大小为 784 的长 1D 向量来给出。在成批训练时,多个数字图像向量被堆叠和馈送。鉴于此,输入形状变为(batch_size,784)。
输入数据的维度
上图的批量大小为 2,每个输入中的要素数量为 784(像素)。为了简单起见,让我们假设模型的每一层都有 50 个神经元。因此,第一个隐藏层的激活将是形状(2,50)。因为 2 是我们的批量,50 是神经元的数量。如果我们的批量大小是 64,那么形状将是(64,784)
第一个隐藏层激活的形状
此外,让我们深入检查第一隐藏层的单个神经元的激活。如果只有一个输入,单个神经元将只产生一个激活。但是,如果输入是成批给定的,它会激活 shape (batch_size,1)。使得批量中的每个输入激活 1 次。
添加批处理规范化图层
通常,在将输入乘以权重之后,网络中的每一层将应用非线性激活函数,如“”。如果我们要插入一个批量标准化层,我们必须在应用非线性之前添加它。批量标准化层通过应用标准化方法来标准化激活。**
μ是*均值,σ是标准差
它从激活中减去*均值,并将差值除以标准偏差。标准差就是方差的*方根。具体来说,我们计算整个批次的*均值和标准偏差,并分别减去和除以。
你看,层在反向传播期间调整它们的参数,假设它们的输入分布保持不变。但是所有层都用反向传播来更新,从而改变它们的每个输出。
这改变了各层的输入,因为每一层都从前一层获得其输入。这叫做 内部协变 。因此,这些层经历不断变化的输入分布。重要的是,这种标准化方法标准化了输出激活的分布。
因此,当权重改变时,它产生不会变化太多的期望的激活分布。换句话说,它最小化了 内部协变量移位 并帮助模型更快地学习。
尽管这被认为是批量标准化成功的主要因素,但一些论文将其归因于其他因素。这篇文章讲述了批量标准化层如何*滑损失曲线,从而帮助训练更快。
通过示例了解
同样,为了清楚起见,我们只考虑单个神经元的激活,并将批量大小设置为 64。我们的两个隐藏层各有 50 个神经元。正如我们之前看到的,单个神经元的输出将是(64,1)。批次归一化层计算批次中 64 个值的*均值(μ)和标准差(σ)。
从 64 个值中减去的就是这个μ值。σ除以从神经元中减去的*均激活。相反,让我们想象一下批处理规范化层是做什么的。
注:为简单起见,此解释仅针对一层中单个神经元。
考虑所有神经元的批量标准化的输出在形状上与此不同,但所有过程都是相同的。
单个神经元通过批量标准化层的激活流程
如果我们考虑一层中的所有神经元,激活形状将是(64,50)。然后对 50 个神经元中的每一个计算*均值和方差,得到 50 个*均值和 50 个方差值。并且对应于单个神经元的每一列应该用其各自的*均值和方差来归一化。
批量标准化对激活的影响
好了,我们已经成功地规范化了一个隐藏层的激活,剩下的就是应用非线性,对吗?
不,这还没有结束!
嗯,标准化隐藏层的激活有一个问题。如果我们将标准化的激活输入到一个 Sigmoid,模型的表达能力就会降低。为了澄清,归一化的激活是一个 0 均值和单位方差分布。因此,激活落在 s 形非线性的线性区域。我们将继续尝试使用 matplotlib 和 Python 绘制函数。
**import numpy as npimport matplotlib.pyplot as pltdef sigmoid(x):return 1 / (1 + np.exp(-x))x = np.arange(-10,11,1) #creates a distribution [-10,-9,-8,.........7,8,9,10]x_sig = sigmoid(x)plt.plot(x,x_sig)plt.scatter(x,x_sig)**
把这个数据分布看作是我们将要归一化的激活。下图显示了未标准化数据的 sigmoid 图[-10 到 10]。
现在,我们将对相同的数据进行归一化,看看数据点落在曲线的什么位置。这是实现这一点的 Python 代码。
**import numpy as npimport matplotlib.pyplot as pltdef sigmoid(x):return 1 / (1 + np.exp(-x))x = np.arange(-10,11,1) #creates a distribution [-10,-9,-8,.........7,8,9,10]x_sig = sigmoid(x)plt.plot(x,x_sig) #to plot the blue, unnormalized sigmoid curvex = (x-np.mean(x))/np.std(x) #standardizing the datax_sig = sigmoid(x)plt.scatter(x,x_sig)#plot the standardized values (red data points)**
归一化点落在 s 形曲线的线性区域
批量标准化的参数
正如我们所见,批量标准化并没有让模型利用 sigmoid 非线性。这使得乙状结肠层几乎是线性的,我们不希望这样!因此,本文作者给出了一种恢复网络表达能力的方法。他们引入了两个参数来移动和缩放标准化激活。
γ和β参数通过反向传播学习。x_hat 是标准化激活
引入这两个参数是为了使它们能够撤销由批处理规范化层完成的规范化。如果伽马被设置为σ并且贝塔被设置为*均值,它将完全反规格化激活返回到正常。乍一看,这似乎有悖常理。但是这样做是为了使模型能够以它想要的方式调整归一化,如果这样可以减少损失的话。这带回了当我们正常化激活时失去的表达能力。
使用批处理规范化的一个主要优点是它是完全可微的。所以,这意味着你可以通过它反向传播,可以使用梯度下降进行训练。也就是说,我们可以更新伽玛和贝塔以及模型参数。
卷积的批量规范化
卷积图层后的批量归一化略有不同。通常,在卷积层中,输入作为形状的四维张量(批次、高度、宽度、通道)输入。但是,批量标准化层会跨批量、高度和宽度维度对张量进行标准化。对于每个通道,计算其他三个维度的均值和方差。因此,这给出了“C”个*均值和方差值,然后用于归一化。
对于张量中的每个通道,计算所有其他维度的*均值和方差
因此,对于上述示例中的 64 个通道中的每一个,计算 10x200x200 (400000)值的*均值和方差。这为我们提供了 64 个均值和 64 个方差来分别归一化每个通道。
批量标准化的优势
批量标准化可以防止网络陷入非线性的饱和区域。它还有助于层中的权重在标准化输入时学习得更快。你看,一个层的大输入值(X)会导致即使很小的权重激活也很大。这将激活推到 sigmoid 或 tanh 非线性的饱和区域。
在 sigmoid 的饱和区域附*,导数几乎为零
饱和激活具有非常小的导数。因此,他们做非常小的梯度步骤,减缓了训练。这种影响随着网络深度的增加而增加。但是批量标准化将激活放在它想要的位置。
这可以防止网络因饱和而堵塞。此外,它消除了仔细初始化模型参数的必要性。有时随机初始化会使一些权重值变高,从而使激活达到饱和。但是批处理规范化允许我们不必太在意初始化。
作者声称,这也规范了模型,减少了辍学的需要。这种正则化效果是由于用小批量统计(其引入了一些噪声)而不是总体统计进行了归一化。如果批量非常大,正则化效果会减弱。
由于梯度对权重尺度的依赖性降低,这允许我们使用更高的学习速率。
参考
批量标准化:通过减少内部协变量转移来加速深度网络训练https://arxiv.org/pdf/1502.03167.pdf
使用 Pandas-Profiling 加速您的探索性数据分析
探索性的数据分析是乏味的。使用 Pandas-Profiling,通过一行代码自动执行流程并生成详细的交互式报告
当开始一个新的数据科学项目时,第一次接触数据集后的第一步是理解它。我们通过执行探索性数据分析(EDA)来实现这一点。这包括找出每个变量的数据类型、目标变量的分布、每个预测变量的不同值的数量、数据集中是否有任何重复或缺失的值等。
如果您曾经在任何数据集上做过 EDA(我假设您在阅读本文时已经做过),我不需要告诉您这个过程有多耗时。如果你已经参与了许多数据科学项目(无论是在你的工作中还是通过做个人项目),你就会知道所有这些过程是多么的重复。但是有了开源库 Pandas-profiling,就不必再这样了。
什么是熊猫概况?
Juan Rumimpunu 在 Unsplash 上拍摄的照片
Pandas-profiling 是一个开源库,可以为任何数据集生成漂亮的交互式报告,只需一行代码。听起来很有趣?让我们看一下文档,以便更好地理解它是做什么的。
Pandas-profiling 从熊猫DataFrame
生成档案报告。pandas df.describe()
功能很棒,但是对于严肃的探索性数据分析来说有点基础。pandas_profiling
用df.profile_report()
扩展熊猫数据框,进行快速数据分析。
对于每个列,以下统计信息(如果与列类型相关)将显示在交互式 HTML 报告中:
- 类型推断:检测数据帧中列的类型。
- 要素:类型,唯一值,缺失值
- 分位数统计如最小值、Q1、中值、Q3、最大值、范围、四分位间距
- 描述性统计如*均值、众数、标准差、总和、中位数绝对偏差、变异系数、峰度、偏斜度
- 最频繁值
- 直方图
- 相关性突出显示高度相关的变量(Spearman、Pearson 和 Kendall 矩阵)
- 缺失值矩阵,缺失值的计数、热图和树状图
- 文本分析了解文本数据的类别(大写、空格)、脚本(拉丁文、西里尔文)和块(ASCII)。
现在我们知道了熊猫烧香是怎么回事,让我们在下一节看看如何在 Jupyter 笔记本或 Google Colab 中安装和使用它。
安装熊猫-配置文件:
使用画中画
您可以使用 pip 软件包管理器通过以下命令非常容易地安装 pandas-profiling:
pip install pandas-profiling[notebook,html]
或者,您可以直接从 Github 安装最新版本:
pip install [https://github.com/pandas-profiling/pandas-profiling/archive/master.zip](https://github.com/pandas-profiling/pandas-profiling/archive/master.zip)
使用 Conda
如果你正在使用 conda,那么你可以使用下面的命令来安装
conda install -c conda-forge pandas-profiling
在 Google Colab 中安装
Google colab 预装了 Pandas-profiling,但不幸的是它带有一个旧版本(1.4 版)。如果您正在阅读本文或 GitHub 文档,那么代码将无法在 Google Colab 上运行,除非您安装了最新版本的库(v2.6)。
为此,您需要首先卸载现有的库并安装最新的库,如下所示:
# To uninstall
!pip uninstall !pip uninstall pandas_profiling
现在要安装,我们需要运行 pip install 命令。
!pip install pandas-profiling[notebook,html]
生成报告:
凯文·Ku 在 Unsplash 上拍摄的照片
既然我们已经完成了先决条件,让我们进入分析一些数据集的有趣部分。
我将在这个例子中使用的数据集是 Titanic 数据集。
加载库:
import pandas as pd
import pandas_profiling
from pandas_profiling import ProfileReport
from pandas_profiling.utils.cache import cache_file
导入数据
file = cache_file("titanic.csv",
"https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv")data = pd.read_csv(file)
加载数据集
生成报告:
要生成报告,请在笔记本中运行以下代码。
profile = ProfileReport(data, title="Titanic Dataset", html={'style': {'full_width': True}}, sort="None")
生成报告
就是这样。通过一行代码,您已经生成了一个详细的概要文件报告。现在让我们把报告放在笔记本上看看结果。
将报表作为 IFrame 包含在笔记本中
profile.to_notebook_iframe()
这将在笔记本中以 HTML iframe 的形式包含交互式报告。
保存报告
使用以下代码将报告保存为 HTML 文件:
profile.to_file(output_file="your_report.html")
或者使用以下命令获取 JSON 格式的数据:
# As a string
json_data = profile.to_json()
# As a file
profile.to_file(output_file="your_report.json")
结果是:
现在我们知道了如何使用 pandas-profiling 生成报告,让我们看看结果。
概述:
概观
警告信息
Pandas_profiling 通过计算预测变量的总缺失单元格、重复行、不同值的数量、缺失值、零值,创建了预测变量的描述性概述。它还会在警告部分标记基数较高或缺少值的变量,如上图所示。
除此之外,它还为每个变量生成详细的分析。我将在本文中浏览其中的一些,查看包含所有代码的完整报告,在文章末尾找到 colab 链接。
类别分布:
数字特征:
对于数字特征,除了具有详细的统计数据,如*均值、标准差、最小值、最大值、四分位距(IQR)等。它还绘制了直方图,给出了常见值和极值列表。
分类特征:
与数字特征类似,对于分类特征,它计算公共值、长度、字符等。
互动:
最有趣的事情之一是报告的交互和关联部分。在交互部分,pandas_profiling 库自动为每对变量生成交互图。通过从两个标题中选择特定的变量,可以得到任何一对的交互图(就像在这个例子中,我选择了 passengerId 和 Age)
相关矩阵:
相关性是一种统计技术,可以显示成对的变量是否相关以及相关程度如何。比如身高和体重是相关的;高个子往往比矮个子重。这种关系并不完美。同样身高的人体重相差很大,你很容易想到你认识的两个人,矮的比高的重在哪里。然而,5 英尺 5 英寸的人的*均体重小于 5 英尺 6 英寸的人的*均体重,并且他们的*均体重小于 5 英尺 7 英寸的人,等等。相关性可以告诉你人们体重的变化有多少与他们的身高有关。
相关的主要结果称为相关系数(或“r”)。范围从-1.0 到+1.0。r 越接*+1 或-1,这两个变量的关系就越密切。
如果 r 接* 0,说明变量之间没有关系。如果 r 为正,这意味着随着一个变量变大,另一个也变大。如果 r 为负,这意味着一个变大,另一个变小(通常称为“逆”相关)。
当涉及到为所有数字特征生成相关矩阵时,pandas_profiling 库提供了所有流行的选项供我们选择,包括 Pearson 的 r 、 Spearman 的ρ 等。
相关
现在,我们知道了使用 pandas_profiling 的优点,指出这个库的缺点也是有用的。
缺点:
pandas profiling 的主要缺点是使用大型数据集。随着数据量的增加,生成报告的时间也增加了很多。
解决这个问题的一个方法是为数据集的一部分生成概要报告。但是,在这样做的同时,确保数据是随机抽样的,以便它能够代表我们拥有的所有数据,这一点非常重要。我们可以通过以下方式做到这一点:
from pandas_profiling import ProfileReport# Generate report for 10000 data points
profile = ProfileReport(data.sample(n = 10000), title="Titanic Data set", html={'style': {'full_width': True}}, sort="None")# save to file
profile.to_file(output_file='10000datapoints.html')
或者,如果您坚持要获得整个数据集的报告,您可以使用最小模式来完成。在最小模式下,生成的简化报告包含的信息比完整报告少,但是对于大型数据集,可以相对快速地生成简化报告。相同的代码如下所示:
profile = ProfileReport(large_dataset, minimal=True)
profile.to_file(output_file="output.html")
结论:
现在你已经知道什么是 pandas-profiling 以及如何使用它,我希望它能为你节省大量的时间,你可以利用这些时间对手头的问题进行更高级的分析。
如果你想得到完整的工作代码报告,你可以看看下面的笔记本。如果你想看我的其他文章,你可以找到下面的链接。
泰坦尼克号数据集上的演示
colab.research.google.com](https://colab.research.google.com/drive/1elOweJGpdqQ0C0jX9kRiJUFEPPZOBQBQ)
熊猫-剖析 GitHub repo:
从 pandas 数据框架生成配置文件报告。pandas 的 df.describe()函数很棒,但对…来说有点基础
github.com](https://github.com/pandas-profiling/pandas-profiling)
如果你喜欢这篇文章,你可能也会喜欢我的其他文章。
教程和在线课程如何制造一种能力的假象,以及如何不落入这个陷阱
towardsdatascience.com](/the-trap-of-tutorials-and-online-courses-2b0c22e0388) [## 机器学习案例研究:预测银行电话营销成功的数据驱动方法
给定客户关系数据,预测客户是否会认购定期存款
towardsdatascience.com](/machine-learning-case-study-a-data-driven-approach-to-predict-the-success-of-bank-telemarketing-20e37d46c31c) [## 什么是 ACM ICPC 和如何准备它(初学者指南)
什么是 ICPC ACM?
codeburst.io](https://codeburst.io/how-do-i-prepare-for-acm-icpc-and-how-can-i-best-increase-my-chances-of-excelling-in-any-be3da114fbc7)
关于我:
嗨,我是苏坎塔·罗伊。一名软件开发人员,一名有抱负的机器学习工程师,前谷歌 2018 年代码之夏的学生和一个巨大的心理学爱好者。如果你对这些感兴趣,你可以在 medium 上关注我,或者在 LinkedIn 上与我联系。
纯 Python 中的映射、过滤和归约
map、filter 和 reduce 的概念改变了游戏规则。这些方法的使用远远超出了 Python 的范畴,是未来的一项基本技能。
映射、过滤和缩小(图片由作者提供)
基础知识
Map、filter 和 reduce 是帮助您处理各种集合的功能。它们是 Spark 和其他各种数据操作和存储框架等现代技术的核心。但是在使用 vanilla Python 时,它们也是非常强大的助手。
地图
Map 是一个函数,它将一个集合(如列表['bacon ',' toast ',' egg'])和一个函数(如 upper())作为输入。然后,它将通过这个函数移动集合中的每个元素,并生成一个具有相同元素计数的新集合。让我们看一个例子
map_obj = map(str.upper,['bacon','toast','egg'])
print(list(map_obj))
>>['BACON', 'TOAST', 'EGG']
我们在这里所做的是使用 map(some_function,some_iterable)函数结合 upper 函数(该函数将字符串中的每个字符大写)。正如我们所看到的,我们为输入列表中的每个元素生成了输出列表中的另一个元素。我们在输出中得到的元素总是和我们将要输入的一样多!这里我们发送 3 个输入,接收 3 个输出,这就是为什么我们称它为 N 对 N 函数。让我们看看如何使用它。
def count_letters(x):
return len(list(x))map_obj = **map**(count_letters,['bacon','toast','egg'])
print(list(map_obj))
>>[6, 5, 3]
在这个例子中,我们定义了自己的函数 count_letters()。集合通过函数传递,在输出中,我们有每个字符串的字母数!让我们用一个 lambda 表达式让它更性感一点。
map_obj = **map**(lambda x:len(list(x)),['bacon','toast','egg'])
print(list(map_obj))
>>[6, 5, 3]
lambda 表达式基本上只是一种定义函数的简写符号。如果你不熟悉它们,你可以在这里查看它们是如何工作的。然而,通过下面的例子应该很容易理解它们是如何工作的。
过滤器
与映射相反,映射是一个 N 到 N 的函数。Filter 是一个 N 到 M 的函数,其中 N≥M。这意味着它减少了集合中的元素数量。换句话说,它过滤它们!与 map 一样,符号也是 filter(some_function,some_collection)。让我们用一个例子来验证这一点。
def has_the_letter_a_in_it(x):
return 'a' in x# Let's first check out what happens with map
map_obj = **map**(has_the_letter_a_in_it,['bacon','toast','egg'])
print(list(map_obj))
>>[True,True,False]# What happens with filter?
map_obj = **filter**(has_the_letter_a_in_it,['bacon','toast','egg'])
print(list(map_obj))
>>['bacon', 'toast']
正如我们所看到的,它减少了列表中的元素数量。它通过计算函数 has_the_letter_a_in_it()的返回值来实现,并且只返回表达式返回 True 的值。
再一次,使用我们最喜欢的 lambda 看起来更性感!
map_obj = **filter**(lambda x: 'a' in x, ['bacon','toast','egg'])
print(list(map_obj))
>>['bacon', 'toast']
减少
让我们见见最后的敌人,也可能是 3 中最复杂的一个。不过不用担心,其实挺简单的。这是一个 N 对 1 的关系,意味着无论我们向它注入多少数据,我们都只能得到一个结果。它这样做的方式是通过应用我们要传递给它的函数链。在 3 个中,它是我们必须从 functools 导入的唯一一个。与其他两个相比,最常见的是使用三个参数 reduce(some_function、some_collection、some_starting_value),起始值是可选的,但提供一个起始值通常是个好主意。让我们看一看。
from functools import reducemap_obj = **reduce**(lambda x,y: x+" loves "+y, ['bacon','toast','egg'],"Everyone")
print(map_obj)
>>'Everyone loves bacon loves toast loves egg'
正如我们看到的,我们必须使用一个 lambda 函数,它一次接受两个参数,即 x,y,然后通过链表将它们链接起来。让我们想象它是如何遍历列表的
- x=“人人”,y=“腊肉”:返回“人人都爱腊肉”
- x= "人人爱培根",y= "吐司":返回"人人爱培根爱吐司"
- x= "人人爱培根爱吐司",y= "鸡蛋" :返回"人人爱培根爱吐司爱鸡蛋"
所以我们有了最后一个元素“人人都爱培根爱吐司爱鸡蛋”。这些是更轻松地通过处理流程的基本概念。这里值得一提的是,你不能在每一种编程语言中假设 reduce 函数将按顺序处理元素,例如,在某些语言中,它可能是“‘人人都爱鸡蛋爱吐司爱培根’”。
联合收割机
为了确保我们理解了这些概念,让我们一起使用它们并构建一个更复杂的示例。
from functools import reducevals = [0,1,2,3,4,5,6,7,8,9]
# Let's add 1 to each element >> [1,2,3,4,5,6,7,8,9,10]
map_obj = **map**(lambda x: x+1,vals)
# Let's only take the uneven ones >> [1, 3, 5, 7, 9]
map_obj = **filter**(lambda x: x%2 == 1,map_obj)
# Let's reduce them by summing them up, ((((0+1)+3)+5)+7)+9=25
map_obj = **reduce**(lambda x,y: x+y,map_obj,0)
print(map_obj)
>> 25
正如我们所看到的,我们可以使用这三者的组合来构建非常强大的东西。让我们转到最后一个例子来说明这在实践中的用途。为此,我们加载了数据集的一个小子集,并将打印出人口超过 1000 万的首都城市!
from functools import reduce#Let's define some data
data=[['Tokyo', 35676000.0, 'primary'], ['New York', 19354922.0, 'nan'], ['Mexico City', 19028000.0, 'primary'], ['Mumbai', 18978000.0, 'admin'], ['São Paulo', 18845000.0, 'admin'], ['Delhi', 15926000.0, 'admin'], ['Shanghai', 14987000.0, 'admin'], ['Kolkata', 14787000.0, 'admin'], ['Los Angeles', 12815475.0, 'nan'], ['Dhaka', 12797394.0, 'primary'], ['Buenos Aires', 12795000.0, 'primary'], ['Karachi', 12130000.0, 'admin'], ['Cairo', 11893000.0, 'primary'], ['Rio de Janeiro', 11748000.0, 'admin'], ['Ōsaka', 11294000.0, 'admin'], ['Beijing', 11106000.0, 'primary'], ['Manila', 11100000.0, 'primary'], ['Moscow', 10452000.0, 'primary'], ['Istanbul', 10061000.0, 'admin'], ['Paris', 9904000.0, 'primary']]map_obj = **filter**(lambda x: x[2]=='primary' and x[1]>10000000,data)
map_obj = **map**(lambda x: x[0], map_obj)
map_obj = **reduce**(lambda x,y: x+", "+y, map_obj, 'Cities:')
print(map_obj)
>> Cities:, Tokyo, Mexico City, Dhaka, Buenos Aires, Cairo, Beijing, Manila, Moscow
如果你喜欢这篇文章,我会很高兴在 Twitter 或 LinkedIn 上联系你。
一定要看看我的 YouTube 频道,我每周都会在那里发布新视频。
在 Tensorflow 上加速您的训练和推理
您是否使用默认设置运行 Tensorflow?您可以轻松地将其优化到您的 CPU/GPU,并获得高达 3 倍的加速。
Tensorflow 带有默认设置,可以兼容尽可能多的 CPU/GPU。您可以轻松优化它,以充分利用 CPU(如 AVX)或 GPU(如张量内核)的全部功能,从而实现高达 3 倍的代码加速。
同样,如果你是一家初创公司,你可能无法无限制地访问 GPU,或者在 CPU 上部署一个模型,你仍然可以优化 Tensorflow 代码,以减少其大小,从而在任何设备上更快地进行推理。下面我将讨论几种方法来加速你的训练或推理或两者兼而有之。
从源构建张量流
通过 pip 安装 Tensorflow 最流行的方式,但是这样的安装非常慢。为什么?
来自pip install tensorflow
的默认构建旨在与尽可能多的 CPU 兼容。如果你曾经在运行 Tensorflow 程序时看到过控制台中的日志,你一定看到过这样的警告——“你的 CPU 支持该 TensorFlow 二进制文件未被编译使用的指令:av x2 FMA”
这个警告是什么意思?现代 CPU 提供了许多对低级指令集的扩展,如 SSE2、SSE4、AVX 等
如果你有一个 GPU ,你不应该关心 AVX 支持,因为最昂贵的操作将被分派在一个 GPU 设备上(除非明确设置不要)
从源代码本身构建它可能会显著加快 Tensorflow 程序的速度。TensorFlow 实际上警告你。您应该从针对您的 CPU 优化的源构建 TensorFlow,启用 AVX、AVX2 和 FMA,无论您的 CPU 支持哪个。
XLA 加速线性代数
加速线性代数,XLA 是一个特定领域的矩阵运算编译器。它可以在不改变源代码的情况下加速张量流模型。
当 TensorFlow 程序运行时,所有操作都由 TensorFlow 执行器单独执行。每个 TensorFlow 操作都有一个预编译的 GPU 内核实现,执行器将被调度到这个内核实现。
XLA 提供了运行模型的另一种模式:它将张量流图编译成一系列专门为给定模型生成的计算内核。因为这些内核是模型特有的,所以它们可以利用特定于模型的信息进行优化。与许多其他优化一样,融合是 XLA 最重要的优化,我将在本文后面详细讨论。
https://www.tensorflow.org/xla
结果是速度和内存使用的提高:启用 XLA 后,大多数内部基准测试的运行速度提高了约 1.15 倍。
启用 XLA 很容易-
import tensorflow as tf
tf.config.optimizer.set_jit(True)
# ... the rest of your program ..
试试 XLA 在 Colab 的例子这里
NVIDIA GPUs 上的混合精度
混合精度训练通过以半精度格式执行运算,同时以单精度存储最少的信息,以在网络的关键部分保留尽可能多的信息,从而显著提高了计算速度。
使用精度低于 32 位浮点的数字格式有很多好处。首先,它们需要更少的内存,能够训练和部署更大的神经网络。其次,它们需要更少的内存带宽,从而加快了数据传输操作。第三,在精度降低的情况下,数学运算运行得更快,尤其是在支持该精度的张量核 GPU 上。它通过识别需要完全精度的步骤,并仅对这些步骤使用 32 位浮点,而对其他所有步骤使用 16 位浮点来实现这一点。
- 通过使用张量核,加速数学密集型运算,如线性和卷积层。
- 与单精度相比,通过访问一半的字节来加速内存受限的操作。
- 降低训练模型的内存需求,支持更大的模型或更大的小批量。
用于 ImageNet 分类的 ResNet-50 训练—DGX-1 上的 8 个 GPU 与 FP32 训练相比→3 倍加速—同等精度来源— Nvidia
在 NVIDIA GPUs 中,计算能力为 7.0 或更高的 GPU 将从混合精度中获得最大的性能优势,因为它们有特殊的硬件单元,称为张量核心,以加速浮点矩阵乘法和卷积。
张量流中的混合精度
混合精度 API 在 TensorFlow 2.1 中提供,带有 Keras 接口。要在 Keras 中使用混合精度,您需要创建,通常称为 dtype 策略。Dtype 策略指定了将在其中运行的 dtype 层。这将导致后续创建的层使用混合精度,混合使用 float16 和 float32。
from tensorflow.keras.mixed_precision import experimental as mixed_precision
policy = mixed_precision.Policy('mixed_float16')
mixed_precision.set_policy(policy)
# Now design your model and train it
小鬼。注:提供混合精度的张量核需要张量的某些维度,例如稠密层的维度、Conv 层中的过滤器数量、RNN 层中的单元数量是 8 的倍数。
要比较混合精度与 float32 的性能,请将策略从mixed_float16
更改为float32.
,预期性能提升高达 3 倍。
通过模型修剪改善推理延迟
我已经在我以前的博客中报道过这个概念。简而言之,修剪是如何工作的
如果你能根据神经元的贡献大小对它们之间的神经元或连接进行排序,那么你就可以从网络中移除排序较低的神经元或连接,从而形成一个更小更快的网络。
tensor flow 中的修剪
Tensorflow 提供了模型优化工具包,用于剪枝和其他训练后优化。在你的代码中使用它,这里有一个简单的例子-
import tensorflow_model_optimization as tfmot
model = build_your_model()
pruning_schedule = tfmot.sparsity.keras.PolynomialDecay(
initial_sparsity=0.0, final_sparsity=0.5,
begin_step=1000, end_step=3000)
model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(model, pruning_schedule=pruning_schedule)
...
model_for_pruning.fit(...)
将多个操作融合为一个
通常当你运行一个张量流图时,所有的操作都是由张量流图执行器单独执行的。每个 op 都有一个预编译的 GPU 内核实现。融合操作将操作整合到一个内核中,以提高性能。
op 融合示例
比如说-
def model_fn(x, y, z):
return tf.reduce_sum(x + y * z)
没有融合,没有 XLA,该图启动三个内核:一个用于乘法,一个用于加法,一个用于减法。
使用 op fusion,您可以在一次内核启动中计算结果。它通过将加法、乘法和减法“融合”到一个 GPU 内核中来实现这一点。
与 Tensorflow 2.x 的融合
更新的 Tensorflow 版本带有 XLA,它为我们进行了融合和其他优化。
from tensorflow.contrib.compiler import xla
def model_fn(x, y, z):
return tf.reduce_sum(x + y * z)
def create_and_run_graph():
with tf.Session() as sess:
x = tf.placeholder(tf.float32, name='x')
y = tf.placeholder(tf.float32, name='y')
z = tf.placeholder(tf.float32, name='z')
result = xla.compile(computation=model_fn, inputs=(x, y, z))[0]
# `result` is a normal Tensor (albeit one that is computed by an XLA
# compiled executable) and can be used like any other Tensor.
result = tf.add(result, result)
return sess.run(result, feed_dict={ ... })
融合模式示例:
■ Conv2D + BiasAdd +
■ Conv2D + FusedBatchNorm +
■ Conv2D +挤压+ BiasAdd
■ MatMul + BiasAdd +
将 ops 融合在一起提供了几个性能优势:
○完全消除运营调度开销(廉价运营的重大胜利)
○增加 ILP、矢量化等的机会。
○提高数据访问的时间和空间局部性
例如,MatMul 是逐块计算的,并且当数据在高速缓存中仍然“热”时,可以应用偏置和激活函数。
与 Tensorflow 1.x 的融合
在 Tf 1.x 中,与 fused ops 兼容的层具有“fused”参数,该参数需要设置为 True 以使用 fusion 来加快实现。
比如说-
#Using TF1.x in TF2.x
b1 = tf**.**layers**.**batch_normalization(
input_layer, fused**=**True, data_format**=**'NCHW')
#Or in pure TF1.x
b1 = tf.layers.batch_normalization
借助 NVIDIA RAPIDS 加速端到端机器学习工作流
在 34 秒内训练一个有 9200 万条记录的模型
从太空探索到机器人,从游戏引擎到医学研究,从训练单个模型到为整个数据中心提供动力,GPU 是我们处理数据过程中不可或缺的一部分。
如果说我们今天比以往任何时候都更需要的是处理我们产生的大量数据的速度。在首席执行官厨房发表的最新 GTC 2020 主题演讲中,NVIDIA 明确表示,他们希望在所有可能的领域利用 GPU。
在本文中,我们将了解如何利用 NVIDIA 的 RAPIDS 加速端到端的机器学习工作流。如果你还不知道端到端的工作流程是如何工作的,或者到底什么是 RAPIDS,请和我呆在一起,你会很开心的。我们将在本文中讨论以下内容,如果您知道一两个主题,请随意继续。
- 什么是急流?
- 端到端工作流的工作方式
- 预测纽约出租车费用并比较 CPU 和 GPU 所用的时间
另外,在我们开始之前,请注意我使用的机器有以下规格:
配备泰坦 RTX 图形处理器的英伟达数据科学电脑
什么是急流?
好吧,让我们直接开始吧。RAPIDS 是一个特定于市场/领域的库,运行在 CUDA 之上,这是一个并行计算*台和 API,由 NVIDIA 创建,你猜对了。
NVIDIA SDK 堆栈— 来自 GTC 2020 主题演讲
虽然有几个库面向不同的领域,但 RAPIDS 是专门为 GPU 加速数据分析而设计的,后来被数据科学社区采用,以更快地训练他们的机器学习模型。我的意思是谁不喜欢在眨眼之间训练他们的模型呢?对吗?要了解更多关于 RAPIDS 和最*发展的信息,请访问他们的网站和介绍性博客。
端到端工作流如何工作
如果你正在阅读如何加速你的机器学习端到端工作流,你很可能会熟悉我将要解释的工作流。如果是这样,你可以跳到下一部分,我们用 CPU 和 GPU 预测纽约市的出租车费用。但是如果你是新来的,想知道更多,请和我呆在一起。
ML Pipeline 展示了如何在 Spark 3.0 中使用 NVIDIA GPUs 加速 ETL(参考、高分辨率)
好好看看这张图。有吗?完美。现在让我们一步步理解这一点:
- ETL——提取、转换和加载
这是大多数数据科学家花费时间清理数据的地方。在这一步中,我们做了所有必要的事情来形成一个好的数据集,然后将它输入到我们的机器学习算法中——从创建数据框到进行特征工程,所有这些都属于 ETL。如果你想慢慢开始,并且想知道如何实现基本的 ETL,请阅读这篇文章,在这篇文章中,我们执行 ETL 并预测谁在泰坦尼克号上幸存。 - 训练 为了获得最好的结果,我们首先要用数据训练我们的模型,这样当它下次看到类似的东西时,它就知道它在看什么了。这是您的模型进行训练和调整的阶段。
- 推理 然后,我们将模型投入运行,以便在经过几个过程后能够响应用户的查询。比如排名。基于用户的查询,我们对结果进行排序,并将其返回给用户。想想谷歌是如何为每个新的查询呈现一组新的结果的。整洁吧?
为了避免任何误解,要知道这只是端到端工作流如何工作的一般概念。幕后有很多工作。就像电影、戏剧或歌剧一样。
对高性能计算的需求
你可能想知道为什么我们需要加快这个过程?我简单说一下原因。
实际情况是,当涉及到计算时,我们上面讨论的所有三个阶段都有自己的一系列挑战。每天都有大量的数据生成和高数据处理要求(数万亿字节的数据集),只能说 CPU 是不够的。
数据科学家将大部分时间花在清理和处理(即 ETL)上,没有人希望这个过程花费半天或一整天。我知道,我不会。
随着公司快速获取和处理 Pb 级数据,我们比以往任何时候都更需要速度。让我们通过一个例子来更好地理解这一点。
预测纽约出租车费用
理解数据
首先,你应该比你自己更了解你的数据。纽约市出租车数据集很受欢迎,可以广泛获得,你可以从这里下载数据集。它包含从 2014 年 1 月开始的 9 个不同月份的 9 个文件,每个文件大约有 2–2.2 GB 大,是的,每个文件。你大概明白了。我们将一起处理所有文件。
首先,让我们看看那些文件里有什么。数据集中有 17 个列或要素。我已经列出了它们中的每一个,它们是不言自明的。
vendor id
pickup_datetime
dropoff_datetime
passenger_count
trip_distance
pickup_latitude
pickup_longitude
rate_code
dropoff_latitude
dropoff_longitude
payment_type
fare_amount
surcharge
mta_tax
tip_ammount
tolls_ammount
total_amount
简单吧?很好。你可能会想,记录呢?这 9 个文件总共有 1.24 亿行或记录。对,没错,1.24 亿。准确的说是 124,649,497。你猜完成 ETL 过程需要多长时间?请和我一起寻找答案。
寻找数据的大小
我们将使用 cuDF 和 Dask & XGBoost 来扩展 GPU 数据帧 ETL 风格的操作和模型训练。要了解更多关于 cuDF 的信息,请阅读交流伙伴 George 关于“如何使用 CuPy 让 Numpy 快 10 倍以上”的帖子。为了简单起见,我将在帖子中保持代码最少,但你可以在 RAPIDS 的 GitHub 存储库这里找到整个 ipynb 笔记本和许多其他 E2E 示例笔记本。
数据清理
因为我们已经知道我们需要清理数据,所以我们将整理我们的数据集。
我们在不同的 CSV 文件中以不同的方式表示相同的列名。例如,一个文件有 rate_code,另一个文件有 RateCodeID,虽然这两种都是普遍接受的表示列名的方式,但我们必须使用其中的一种。我总是选择第一个,因为下划线将单词分开,我的眼睛很容易读懂。永远的团队懒。
定义我们的列应该具有什么类型
清理后的输出(map_partitions 是一个辅助函数)
处理异常值
离群值是存在的。一直都是。打破一些东西,阻止一些东西有效运行,我们必须处理它们。例如,票价低于 0 美元或高于 500 美元,谁会给 500 美元?与乘客计数相同,丢弃带有< 0 and > 6 个条目的条目。
处理异常值
清理完数据集后,我们丢弃了* 700 万条记录,现在有 1.17 亿条记录可供我们从中获得真知灼见。
选择训练集
让我们假设你要去纽约旅行,不要只是想象,在 25 日,并希望建立一个模型来预测票价价格将在最后几天给定本月初的数据。
我们正在测量时间,以了解您的集群从工作流的存储桶和 ETL 部分加载数据需要多长时间。此时,我们有 9200 万数据用于训练,剩下的 25%用于测试。
CPU 上的 ETL 时间
墙时间表示 CPU 上的总时间,即 2 分 3 秒或 123 秒。印象深刻吧。但是,如果我告诉你,我们可以实现更快的结果呢?
GPU 上的 ETL 时间
在相同的过程中,在启用 1 个 GPU(英伟达泰坦 RTX 24 GB DDR6)后,我们可以在 63 秒内完成相同的工作。将* 2 倍的提升。如果你认为这很棒,那就等着看我给你展示训练时间的提升吧。同时,我还在监视 CPU 的使用情况。所有的核心工作,这是抚慰我的眼睛,不打算说谎。
在 CPU 上计算时
培养
我们将根据我们的训练数据训练 XGBoost 回归模型,并找出完成整个训练需要多少时间。
CPU 上的训练时间
时间是 6 分 36 秒,所以是 396 秒。还不错。让我们检查启用泰坦 RTX GPU 后的相同。
GPU 上的训练时间
什么!我们刚刚在 33.9 秒内用 9200 万条记录训练了我们的整个模型吗?太对了,我们做到了。说实话,一开始我也不信。但没错,这就是现实。仅通过启用 1 个 GPU,速度就提高了 12 倍以上,如果我们使用多个 GPU 呢?
预言;预测;预告
因为我们已经有了训练好的模型,现在我们必须用我们给出的 25%的记录来测试它。
预测本月剩余时间的票价
工作指标
衡量我们模型的性能是一个重要的部分。我们将通过计算均方根误差来实现。如果你想了解更多关于成本函数的知识,请阅读由通讯伙伴卡米尔撰写的这篇关于成本函数的文章。
这些结果来自我们在 GPU 上训练的模型
一点也不差。我们还可以做进一步的改进,但这超出了本文的范围。也许改天吧。
结论
借助英伟达泰坦 RTX GPU 提升性能
随着越来越多的数据以多种形式呈现在我们面前,我们需要能够更快处理数据的工具来获得洞察力,并将这种洞察力转化为更好的决策,从医学研究到空间探索。借助 NVIDIA RAPIDS(软件堆栈)和 NVIDIA GPUs(硬件),我们可以在端到端机器学习管道上实现* 6 倍的加速。还有,这里有一张野兽的照片。
Velox X(数字风暴 X 英伟达)
快乐学习。
用 Allegro Trains 加速我的新冠肺炎深度学习项目
快板火车会带你出村!
来源:对慢性阻塞性肺病患者的 x 光片进行描述。
目前由新冠肺炎病毒引起的全球疫情已经威胁到我们人类的神圣性和我们整个社会的福祉。类似于战争时期,疫情也给了我们机会去欣赏那些我们认为理所当然的东西,比如卫生工作者、食品供应商、司机、杂货店店员和许多其他在前线保护我们在这个困难时刻安全的人,致敬!当他们为我们而战的时候,你和我做点事情怎么样?
不幸的是,疫情也给我们带来了来自数据科学家的领域不足的见解,这些见解正变得普遍。因此,我想避免类似的陷阱,这就是为什么我想从下面的免责声明开始。这篇博客的目的是展示如何使用 Allegro Trains 来管理您的机器/深度学习项目,以提高您的生产力并改善工作流程。
第一站:探索数据集
我选择这个新冠肺炎胸部 x 光数据集有两个原因。首先,它很小,而且与当前事件相关,所以你可以很容易地跟随我。第二,数据集包含肺部患者的 X 射线/CT 扫描上的数字和分类特征,以便我们可以应用传统的机器学习解决方案以及神经网络。除了声明的目标之外,本博客的任何见解或观察不应用于做出任何决定。考虑到这一点,感谢你和我一起第二次乘坐快板火车。
实验经理枢纽,快板列车
数据集的原始数据帧。
第二站:组装小零件
随着数据工程管道、存储和计算能力的复杂性急剧上升,像上面这样的异构数据集已经变得很常见。随之而来的是使用大量算法和数据挖掘技术来揭示洞察力的潜力。这也给我们提出了一个独特的问题,即如何在一把保护伞下管理激动人心的实验。这可能意味着让一个数据工程师团队来构建数据接收的数据管道,让数据科学家来按摩和实验数据,让机器学习工程师来提供可移植、可扩展、最重要的是可操作的模型。建立一个可操作的模型需要整个村庄的力量!
在部署机器学习模型之前采取的常见步骤包括摄取数据,创建一个用于版本控制、数据争论和本地或云上的数据实验的 group Github 存储库,安装依赖项以重现同事的结果,找出最佳模型(这本身并不容易),打包模型等等。如果你开始发现需要一个高级机器学习基础设施或中枢的新兴模式,那么你可能会有所发现。这就是 Allegro Trains 成为您的 ML/DL 项目管理系统的原因,它可以满足您的版本控制需求、自动化代码和实验跟踪、模型质量控制以及甚至在机器级别上对您的实验进行性能记录。
系好安全带,快板火车将带你出村!
迄今为止我发现的训练能力
第三站:聚焦研究问题
但首先,让我们回到手头的重要问题。我们也许能找出预测新冠肺炎患者存活率的最佳属性。是年龄吗?性?诊断模式?做出诊断的卫生工作者的专业?我们也有 x 光/CT 扫描显示疾病的进展。在现实生活中,我们需要医疗专业人员为我们提供必要的领域知识,以找出可能的最佳路线,但目前,我们最多只能进行数据争论和视觉探索,调整图像大小和编码,并利用工程技术为建模准备数据。我选择用 Scikit 的随机森林和 Xgboost 集成学习方法进行实验,以确定与存活率最相关的特征。请注意,准确性在这里不是一个好的性能指标,因为数据是不*衡的,不包含健康个体的扫描。因此,我们可以使用 ROC 曲线来确定最佳模型。如果我们在度量优化上更加严格,最小化假阴性或最大化召回将是我们的首要任务。我还尝试了多种架构和转移学习模型,以根据卷积神经网络从患者的 X 射线/CT 扫描中预测预后。可以想象,每个体系结构都有自己的超参数要调整,性能要跟踪。如果你开始对潜在实验的数量感到有点不知所措,不要担心!我们将利用 Trains,以便我们专注于手头最重要的任务,即回答我们的研究问题。
我开始我的项目是通过在本地建立我自己的服务器,这样火车可以跟踪我们的实验,如下面的标题所示。Trains 自动负责环境复制和日志记录,同时跟踪我们新模型的性能指标以及每个模型的机器资源分配,如 GPU、CPU、IO 速度等。这一点很重要,因为我们不想只根据一个指标来选择最佳模型。也可以选择使用 Allegro AI 的基于网络的演示服务器,它可以让你 24 小时跟踪你的 ML 项目,但我不会推荐它,因为你根本不可能在一天内完成一个 ML 项目。我使用 Keras 作为我选择的深度学习框架,但 Trains 自带对 Pytorch 和 Tensorflow 的内置支持。Trains 也在跟踪这些包,这样我们就可以协作并复制彼此的工作。
自动实验(左)和实验对比(右)。
最后一站:总结调查结果
以上是我使用 Allegro Trains 进行的 AutoML 实验的结果。为这些实验中的每一个创建单独的笔记本或者对每个输出进行版本控制会导致项目混乱。但在这里,我能够简单地比较基于几个指标的卷积神经网络的性能,包括 epoch vs loss 优化和 GPU 使用。项目管理系统的这种类型的抽象只会导致数据驱动的决策。我能够准确地确定 85%的患者存活成员,事实证明年龄是决定患者存活率的关键因素。神经网络的资源分配远不止基于树的算法的网格搜索。此外,由于数据集较小,random forest 的性能优于预期的 Xgboost。
很高兴为您提供一个高层次的概述,让您了解如何通过在同一中心下自动化您的实验来轻松处理复杂的数据集。我敢打赌,将 Trains 作为项目管理中心,您的迭代速度、工作流和实验将会显著提高。请务必查看我的第 1 部分迷你系列,了解火车相对于 GitHub 的表现。至于我,我已经到站了。我希望我能听到你为了你的深度学习项目需求而进行的快板训练的奇妙旅程,随时在 LinkedIn 上添加我,或者在 Twitter 上给我大声喊出来。多保重!
用 NVIDIA GPUs 通过 6 个简单的步骤加速 Spark 3.0 Google DataProc 项目
Genessa panainite 在 Unsplash 上拍摄的照片
Spark 3.0 + GPU 来了。它改变了游戏规则
数据探索是数据科学的关键部分。需要很长时间吗?啊。别问了。为 ML 准备数据集不仅需要理解数据集、清理和创建新特征,还需要重复执行这些步骤,直到我们有一个微调的系统。
当我们走向更大的数据集时, Apache Spark 带来了一线希望。它为我们提供了一个可扩展的分布式内存系统来处理大数据。顺便说一句,我们还看到了像 Pytorch 和 Tensorflow 这样的框架,它们使用数千个 GPU 核心来固有地并行化矩阵计算。
但过去我们从未见过这两种系统协同工作。我们继续在深度学习中使用 Spark 处理大数据 ETL 任务,使用 GPU 处理矩阵密集型问题。
这就是 Spark 3.0 的由来。它为我们提供了一种将 NVIDIA GPUs 添加到 Spark 集群节点的方法。这些节点完成的工作现在可以通过使用 GPU 计算软件*台 RAPIDS 的 CPU+GPU 并行处理。
Spark + GPU + RAPIDS = Spark 3.0
根据 NVIDIA 的说法,Spark 3.0 的早期采用者已经看到了其当前数据负载的显著更快的性能。这种处理时间的减少可以让数据科学家在更大的数据集上进行更多的迭代,让零售商改善他们的预测,让金融公司增强他们的信用模型,让广告技术公司提高他们预测点击率的能力。
兴奋不已。那么如何才能开始使用 Spark 3.0 呢?幸运的是,Google Cloud、Spark 和 NVIDIA 已经联合起来,为我们简化了集群创建过程。通过 Google Cloud 上的 Dataproc,我们可以在几分钟内拥有一个完全托管的带有 GPU 的 Apache Spark 集群。
这篇帖子是关于在 Google Cloud 上用 NVIDIA GPUs 建立自己的 Dataproc Spark 集群。
1.创建新的 GCP 项目
在谷歌云*台上完成初始注册后,我们可以开始一个新项目。在这里,我首先创建一个名为 dSparkDataProc 的新项目。
创建新项目
2.在 GCP 项目中启用 API
一旦我们添加了这个项目,我们就可以转到我们的新项目,并通过单击右上角的“激活云外壳按钮来启动云外壳实例。这样做将在屏幕底部打开一个终端窗口,我们可以在其中运行下一个命令来设置数据处理集群:
激活云壳来放置你的命令
在这之后,我们将需要运行一些命令来在云 shell 中设置我们的项目。我们从在您的项目中启用 dataproc 服务开始。启用 Compute 和 Dataproc APIs 来访问 Dataproc,并启用 Storage API,因为您将需要一个 Google 云存储桶来存放您的数据。我们还设置了默认区域。这可能需要几分钟时间:
gcloud services enable compute.googleapis.com
gcloud services enable dataproc.googleapis.com
gcloud services enable storage-api.googleapis.com
gcloud config set dataproc/region us-central1
3.创建一些数据并放入 GCS 桶中
完成后,我们可以创建一个新的 Google 云存储桶,在那里我们将把所有数据保存在云外壳中:
#You might need to change this name as this needs to be unique across all the users
export BUCKET_NAME=rahulsparktest#Create the Bucket
gsutil mb gs://${BUCKET_NAME}
在运行 spark 集群时,我们还可以将一些数据放入桶中,以便以后运行。
# Get data in cloudshell terminal
git clone [https://github.com/caroljmcdonald/spark3-book](https://github.com/caroljmcdonald/spark3-book)
mkdir -p ~/data/cal_housing
tar -xzf spark3-book/data/cal_housing.tgz -C ~/data# Put data into Bucket using gsutil
gsutil cp ~/data/CaliforniaHousing/cal_housing.data gs://${BUCKET_NAME}/data/cal_housing/cal_housing.csv
4.设置 DataProc Rapids 集群
为了创建一个使用 NVIDIA T4 GPU 的 DataProc RAPIDS 集群,我们需要一些初始化脚本来实例化我们的集群。这些脚本将安装 GPU 驱动程序( install_gpu_driver.sh )并为我们自动创建 Rapids conda 环境( rapids.sh )。由于这些脚本处于开发阶段,所以最好的方法是从 GitHub 源代码中获取脚本。我们可以在我们的云 shell 中使用下面的命令来做到这一点,我们在其中获取初始化脚本并将它们复制到我们的 GS Bucket 中:
wget [https://raw.githubusercontent.com/GoogleCloudDataproc/initialization-actions/master/rapids/rapids.sh](https://raw.githubusercontent.com/GoogleCloudDataproc/initialization-actions/master/rapids/rapids.sh)
wget [https://raw.githubusercontent.com/GoogleCloudDataproc/initialization-actions/master/gpu/install_gpu_driver.sh](https://raw.githubusercontent.com/GoogleCloudDataproc/initialization-actions/master/gpu/install_gpu_driver.sh)gsutil cp rapids.sh gs://$BUCKET_NAME
gsutil cp install_gpu_driver.sh gs://$BUCKET_NAME
我们现在可以在云 Shell 中使用下面的命令来创建集群。在下面的命令中,我们使用一个预定义的镜像版本(2.0.0-RC2-ubuntu18)来创建我们的 dataproc 集群,它包含了 Spark 3.0 和 python 3.7。我用的是这张图片的旧版本,因为最新版本在运行 Jupyter 和 Jupyter Lab 时有一些问题。你可以在这里得到所有版本的列表。
CLUSTER_NAME=sparktestcluster
REGION=us-central1
gcloud beta dataproc clusters create ${CLUSTER_NAME} \
--image-version 2.0.0-RC2-ubuntu18 \
--master-machine-type n1-standard-8 \
--worker-machine-type n1-highmem-32 \
--worker-accelerator type=nvidia-tesla-t4,count=2 \
--optional-components ANACONDA,JUPYTER,ZEPPELIN \
--initialization-actions gs://$BUCKET_NAME/install_gpu_driver.sh,gs://$BUCKET_NAME/rapids.sh \
--metadata rapids-runtime=SPARK \
--metadata gpu-driver-provider=NVIDIA \
--bucket ${BUCKET_NAME} \
--subnet default \
--enable-component-gateway \
--properties="^#^spark:spark.task.resource.gpu.amount=0.125#spark:spark.executor.
cores=8#spark:spark.task.cpus=1#spark:spark.yarn.unmanagedAM.enabled=false"
集群架构
我们得到的 Dataproc 集群具有:
- 一个 8 核主节点和两个 32 核工作节点
- 两个 NVIDIA T4 GPU 连接到每个工作节点
- 巨蟒、朱庇特和齐柏林飞船启动
- 启用组件网关以访问群集上托管的 Web UIs
- 额外的火花配置调整适用于笔记本电脑环境设置使用属性标志。具体来说,我们设置
spark.executor.cores=8
是为了提高并行性,设置spark.yarn.unmanagedAM.enabled=false
是因为它当前破坏了 SparkUI 。
故障排除: 如果您在执行此命令后收到有关限制的错误,您可能需要更改默认 Google 控制台配额页面中的一些配额。我最终改变的限制是:
- GPU(所有区域)至 12(最少 4 个)
- CPU(所有地区)到 164(最少 72 个)
- 美国中部的 NVIDIA T4 GPU1 到 12(最低:4)
- 美国中央处理器1 到 164(最少 72 个)
我实际上请求了比我需要的更多的限制,因为增加限制的过程可能需要更长一点的时间,稍后我将启动一些更大的集群。
5.在 DataProc Rapids 集群上运行 JupyterLab
一旦您的命令成功(可能需要 10-15 分钟),您将能够在https://console.cloud.google.com/dataproc/clusters看到您的 Dataproc 集群。或者你可以在浏览器上进入谷歌云*台控制台,搜索“Dataproc”,点击“Dataproc”图标(它看起来像三个相连的圆圈)。这将引导您进入 Dataproc 集群页面。
Dataproc 集群页面
现在,如果你点击 sparktestcluster,然后点击“web Interfaces ”,你将能够打开一个 Web 界面(Jupyter/JupyterLab/Zeppelin)。
我们集群的 Web 界面页面
打开 Jupyter Pyspark 笔记本后,如果您遵循本教程,这里有一些示例代码供您运行。在这段代码中,我们加载了一个小数据集,我们看到df.count()
函数运行了 252 毫秒,这对于 Spark 来说确实很快,但我稍后会发布一篇更详细的基准测试文章,敬请关注。
file = "gs://rahulsparktest/data/cal_housing/cal_housing.csv"df = spark.read.load(file,format="csv", sep=",", inferSchema="true", header="false")
colnames = ["longitude","latitude","medage","totalrooms","totalbdrms","population","houshlds","medincome","medhvalue"]df = df.toDF(*colnames)
df.count()
是的,我们的 Jupyter 笔记本起作用了
6.访问 Spark 用户界面
这一切都很好,但我面临的一个主要问题是,我无法使用笔记本中提供的链接访问 Spark UI。我发现有两种方法可以访问 Spark UI 进行调试:
答:使用网络界面选项:
我们可以通过首先点击网络界面上的纱线资源管理器链接,然后点击相应页面上的应用程序主界面来访问 Spark UI:
点击跟踪界面栏中的应用程序主以获得 Spark 界面
然后,您将到达 Spark UI 页面:
是啊!我们得到了 Spark UI。
B.使用 SSH 隧道选项:
访问 Spark UI 的另一个选项是使用隧道。为此,您需要转到 web 界面页面并点击“创建 SSH 隧道以连接到 Web 界面”。
使用 SSH 的 Spark 测试集群 Web 界面
这将给你两个你想在本地机器而不是云 shell 上运行的命令。但是在运行它们之前,您需要将 google cloud SDK 安装到您的机器上,并为您当前的项目进行设置:
sudo snap install google-cloud-sdk --classic# This Below command will open the browser where you can authenticate by selecting your own google account.
gcloud auth login# Set up the project as sparkdataproc (project ID)
gcloud config set project sparkdataproc
完成后,我们可以简单地运行第一个命令:
gcloud compute ssh sparktestcluster-m --project=sparkdataproc --zone=us-central1-b -- -D 1080 -N
然后在另一个标签/窗口中显示第二个。这个命令将打开一个新的 chrome 窗口,你可以像以前一样点击 Application Master 来访问 Spark UI。
/usr/bin/google-chrome --proxy-server="socks5://localhost:1080" --user-data-dir="/tmp/sparktestcluster-m" [http://sparktestcluster-m:8088](http://sparktestcluster-m:8088)
这就是设置由 GPU 加速的 Spark3.0 集群的全部内容。
如果不算调试时间和配额增加请求,我花了大约 30 分钟来完成所有这些步骤。
我完全被在 Spark 上使用 GPU 的概念和它开启的不同实验流所震惊。在接下来的几周里,我会做很多这样的工作,不仅是为了基准测试,也是因为它很有趣。敬请关注。
继续学习
此外,如果你想了解更多关于 Spark 和 Spark DataFrames 的知识,我想在 Coursera 上调出 Yandex 关于大数据基础知识的精彩课程:HDFS、MapReduce 和 Spark RDD 和大数据分析:Hive、Spark SQL、DataFrames 和 GraphFrames 。
我以后也会写更多这样的帖子。让我知道你对他们的看法。在 媒体 关注我,或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系到我。
使用 XNNPACK 加速 Tensorflow Lite
全新 Tensorflow Lite XNNPACK delegate 可在 x86 和 ARM CPUs 上实现最佳性能
SpaceX 在 Flickr 上的照片
TL;DR:新的 Tensorflow Lite XNNPACK delegate 在 x86 和 ARM CPUs 上实现了最佳性能,在某些情况下比默认的 Tensorflow Lite 后端快 10 倍以上。
Tensorflow Lite 是我最喜欢的软件包之一。它能够在一系列硬件上轻松快速地部署,现在提供了一系列代理来加速推理,例如 GPU、Core ML 和 Hexagon。然而,Tensorflow Lite 的一个缺点是,它的设计考虑了移动应用,因此没有针对英特尔和 AMD x86 处理器进行优化。更好的 x86 支持在 Tensorflow Lite 开发路线图中,但目前 Tensorflow Lite 主要依赖于通过 Neon_2_SSE 桥将 ARM Neon 指令转换为 SSE。
然而,有一个新的 Tensorflow Lite 委托用于基于 CPU 的浮点计算,XNNPACK,它具有 x86 AVX 和 AVX-512 优化功能。在这篇文章中,我将带您使用 XNNPACK 并展示一些基准测试。
安装和使用 XNNPACK
XNNPACK 的使用说明可以在这里找到。最值得注意的是,现在有一个默认情况下启用 XNNPACK 委托的构建标志。这很方便,因为直到现在还不可能在 Python 中加载 Tensorflow Lite 委托。从源代码构建张量流的命令如下所示:
bazel build --define tflite_with_xnnpack=true \
//tensorflow/tools/pip_package:build_pip_package
Tensorflow Lite 基准测试工具现在也有一个标志来启用 XNNPACK 委托。例如,要在 x86 机器上进行分析,首先要构建分析器工具:
bazel build -c opt --verbose_failures \
tensorflow/lite/tools/benchmark:benchmark_model
然后使用以下命令运行探查器:
bazel-bin/tensorflow/lite/tools/benchmark/benchmark_model \
--graph=<model path> --warmup_runs=50 --num_runs=1000 \
--enable_op_profiling=true --use_xnnpack=true
为 XNNPACK 优化
确保模型适合 XNNPACK 很重要,因为它只支持所有 Tensorflow Lite 运算符的子集。例如,标准的 Keras 实现通常使用显式填充层,并通过 mean 运算符实现顶层全局池层。当使用普通的 TFLite 后端时,这只增加了几个百分点的运行时间,但是 XNNPACK 不支持这些操作,导致了相当大的开销——在具有 8 个线程的 MobileNet V2 的情况下为 30%(见下文)!
通过用卷积运算中内置的填充替换显式填充层,可以轻松修复填充:
# Before
x = layers.ZeroPadding2D(padding=((3, 3), (3, 3)), name='conv1_pad')(img_input)
x = layers.Conv2D(64, 7, strides=2, use_bias=use_bias, name='conv1_conv', padding='valid')(x)# After
x = layers.Conv2D(64, 7, strides=2, use_bias=use_bias, name='conv1_conv', padding='same')(img_input)
全局*均池层可以由具有大内核的*均池层代替:
# Before
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(classes, activation='softmax')(x)# After
# Use XNNPACK compatible average pooling
x = layers.AveragePooling2D(pool_size=(7, 7))(x)
# Implement the top dense layer as a convolution, so we don't need to remove spatial dims
x = layers.Conv2D(classes, kernel_size=1)(x)
x = layers.Softmax()(x)
请注意,您必须重新训练模型。你可以在本文附带的回购协议中找到这些模型的修复版本这里。
基准
手臂ˌ武器ˌ袖子ˌ装备
好了,基准测试!首先,我决定在 Galaxy S8 上测试 MobileNet V3:
我用 1 个线程测试了 1000 次迭代,其中有 50 次预热迭代。
如您所见,XNNPACK 在标准 Tensorflow Lite CPU 后端的基础上提供了出色的性能。值得注意的是,XNNPACK 支持较新的 ARM v 8.2-A CPU(如 A55)中包含的 ARM Float 16 指令,可惜我手头没有。GPU 后端仍然更快,尤其是对于更大的模型。但是,它需要 OpenGL ES 3.1 或更高版本,仅在所有 Android 设备的约 2/3 上可用(见市场份额此处)。
x86
现在转到 x86。我决定使用 MobileNet V2 和 ResNet50 与英特尔的 OpenVino 软件包进行比较。为了测试,我使用了一个谷歌云 N2 瀑布湖实例,有 8 个虚拟 CPU。带 1 根线:
和 8 个线程:
如您所见,使用 XNNPACK delegate 的 Tensorflow Lite 的性能令人钦佩,在某些情况下比默认的 Tensorflow Lite 后端快 10 倍以上。性能接* V2 MobileNet 的 OpenVino,但不及 ResNet 50。不过,我不认为这是一个大问题,因为基于深度方向卷积的架构,如 MobileNet V2,更适合 CPU 部署。XNNPACK 还具有比标准后端更好的跨多个 CPU 内核的伸缩性。请注意,TFLite 基准测试工具对应于 OpenVINO 的延迟模式,因此如果针对吞吐量进行配置,看看 XNNPACK 能够提供什么将会很有意思。
摘要
Tensorflow Lite 现在可以通过新的 XNNPACK delegate 提供出色的 x86 性能,在某些情况下超过了英特尔的 OpenVino 包。XNNPACK 的主要缺点是它只为浮点计算而设计。8 位模型量化可以轻松实现 2 倍以上的性能提升,当部署在支持 AVX-512 VNNI 指令的全新英特尔 Cascade Lake CPUs 上时,性能提升甚至更高。对 x86 上 8 位量化的支持在 Tensorflow Lite 路线图中,甚至可能在的下一个版本中。
同样,对于移动部署,XNNPACK 优于 Tensorflow Lite 默认后端。虽然 GPU delegate 仍然比 XNNPACK 快,但 XNNPACK 在不支持 GPU 计算的设备上很有用。
我对 XNNPACK 感到特别兴奋,因为它允许用户留在 Tensorflow 生态系统中,从而简化了部署过程。现在可以使用 Tensorflow Lite 转换一次模型并部署到多个*台,从而减少所需的不同软件包的数量。同样值得注意的是,AMD 处理器越来越少见,OpenVino 是英特尔的产品。我试图在谷歌云 N2D EYPC 实例上测试,但不幸的是,我无法增加我的配额。
我希望这篇文章对你有所帮助。复制这些基准的代码位于这里和这里。
使用 Python 访问免费的谷歌云公共数据集
数据科学基本指南
下载免费的谷歌公共数据集到熊猫数据框
使用 Python 访问免费的谷歌云公共数据集(插图由 Chaeyun Kim 绘制)
谷歌公共数据集简介
G 数据科学家的好消息!谷歌正在制作一个公共数据集的托管存储库,如约翰·霍普金斯系统科学与工程中心(JHU·CSSE),来自世界银行的全球健康数据,以及【OpenStreetMap 数据,可以通过他们的新冠肺炎公共数据集项目免费访问和查询,以帮助研究人员、数据科学家和分析师努力抗击新冠肺炎。这些数据集消除了障碍,提供了对关键信息的快速、轻松的访问,消除了搜索和装载大型数据文件的需要。研究人员可以从谷歌云控制台中访问数据集,以及数据描述和样本查询,以推进研究。我们在该计划中包含的所有数据都将是公开和免费的。* 该计划将持续有效,直至 2020 年 9 月 15 日。【1】
截至 2020 年 5 月 15 日可用的免费公共数据集列表(作者截图来自 Google
为什么我这么喜欢?
我自己用数据库存储、管理和更新数据有时既无聊又昂贵。有了谷歌公共数据集,他们就在替我打理这些无聊的部分。至于定价,在新冠肺炎疫情之前,它有每月 1 TB 查询的免费层限制(嗯,已经有很多免费数据了!)支持疫情的情况,再也没有限制了!!因此,我可以愉快地专注于有趣的部分:数据分析、性感的数据可视化、开发 web 应用程序等。
本文将与您分享以下分步指南:
- 启用 Google Cloud BigQuery API。
- 为 BigQuery API 创建服务帐户,以向您的 Python 脚本授予权限。
- 使用 BigQuery Web 界面浏览数据集。
- 使用 Python 访问数据集,并将其导入熊猫数据框架。
那么,我们开始吧!
启用 Google Cloud BigQuery API
为了能够访问数据集,你应该注册谷歌云账户。在您注册之后,或者如果您已经有了一个帐户,请转到您的 Google Cloud 控制台,然后激活您的 Google Cloud BigQuery API ( 链接)。点击“激活”API 后,可以看到确认的“API 启用”,如下图所示。
激活 Google BigQuery API (作者截图)
为 BigQuery API 创建服务帐户
为了让 BigQuery API 在以后使用 Python 或其他编程语言访问您的机器,您需要一个新的 Google 服务帐户密钥,步骤如下。(如果只需要通过 web 界面访问,可以跳过这些步骤)
- 转到您的 Google API 凭证页面,为这个 BigQuery API 创建 API 键(链接)。
创建 Google BigQuery API 服务账号(作者截图)
- 选择服务帐户权限角色为“BigQuery Admin”
创建 Google BigQuery API 服务账号(作者截图)
- 然后,点击创建键并选择 JSON 类型。请确保您安全地保存这个文件,否则其他人也可能访问您的 API 帐户。我们将在最后一步中再次使用这个文件。
创建 Google BigQuery API 服务账号(作者截图)
使用 BigQuery Web 界面浏览数据集
用户可以使用 SQL 查询语法检索或查询 Google 公共数据集。首先,您可以尝试观察您可以访问哪些数据集,并通过以下三个步骤通过 Google BigQuery Web 界面测试 SQL 查询:
- 探索可用的数据资源。选择其中一个。
- 在“查询编辑器”窗口中输入查询语法。在这一步,你需要 SQL 的基本知识来查询(搜索)数据集。如果您以前从未使用过,请查看有关它的在线文档。有几个是在线的比如 W3 。
- 浏览您的查询结果。
使用 Google BigQuery Web 接口查询 Google 公共数据集的例子——纽约市新冠肺炎案例。(作者)
使用 Python 访问数据集,并将其导入熊猫数据框架。
要使用 Python 访问 BigQuery API,请使用以下命令安装该库:
**pip install --upgrade google-cloud-bigquery**
创建您的项目文件夹,并将服务帐户 JSON 文件放入该文件夹。然后,创建一个 Python 文件,用你喜欢的编辑器编辑它。你需要做的第一件事是将 Google 应用点的操作系统环境设置为你的 JSON 密钥目录,这可以通过使用os.environ["xxx"]="yyy"
来完成
**os.environ["GOOGLE_APPLICATION_CREDENTIALS"]="Your json directory"**
然后,您可以启动 BigQuery 客户机,并使用以下命令启动查询:
**client = bigquery.Client()** # Start the BigQuery Client **QUERY = ('SELECT ...')** # Input Query Syntax **query_job = client.query(QUERY)** # Start Query API Request**query_result = query_job.result()** # Get Query Result **df = query_result.to_dataframe()** # Save the Query to Dataframe
例如,您可以按照下面的完整 Python 脚本,从纽约时报新冠肺炎数据库中按较晚日期和较高确诊病例的顺序查询美国前 20 名新冠肺炎确诊和死亡病例。
从谷歌公共数据集查询新冠肺炎数据的示例 Python 脚本——纽约时报新冠肺炎数据库(作者提供的示例脚本)
谷歌公共数据集查询结果示例——纽约时报新冠肺炎数据库(作者举例)
所以,就这样吧!祝贺您,现在您可以访问数据集了,享受您的新数据框架吧!!✌🎉🎉
结论
本文涵盖了如何使用 WebUI 和 Python 通过 Google Cloud BigQuery 服务使用和访问数据集的基本步骤。请注意,这篇文章只涵盖了初学者的步骤,还有更多的功能和界面来访问和使用这项服务。你可以在这里查看完整的 BigQuery 文档。
我希望你喜欢这篇文章,并发现它对你的日常工作或项目有用。如果您有任何问题或意见,请随时给我留言。
关于我&查看我所有的博客内容:链接
安全健康健康吗!💪
感谢您的阅读。📚
[1] Chad W. Jennings,新冠肺炎公共数据集计划:使数据可自由访问以获得更好的公共结果(2020 年 3 月 30 日),谷歌云数据分析
仅用 2 行 Python 代码访问菲律宾股票数据
介绍 fastquant,一个方便访问和分析菲律宾股票数据的工具
作为一名具有金融背景的数据科学家,我一直着迷于通过交易股票赚钱的想法,因为这似乎很简单。为什么?你只需要知道两件事就能赚钱——在低点买入,在高点卖出。
那么,你怎么知道股票何时会上涨或下跌呢?通过分析股票的相关数据(如价格、收益和其他经济指标)。从理论上讲,如果你能以某种方式识别价格的(可预测的)模式,你应该能够识别购买股票的低点。这是一个尝试机器学习和其他统计方法来模拟金融时间序列数据和测试交易策略的绝佳机会。现在我只需要数据。
但问题来了:
我找不到一个免费的 API 来提供可靠的和最新的菲律宾公司的财务数据。
Yahoo Finance 很奇怪,因为它以美元报告,并将数字四舍五入到价格不变的程度,其他来源可以给我图表(例如 Investagrams ),但不能编程访问我用 python 分析数据所需的实际原始数据。
使用 fastquant 访问和分析股票数据
为了解决这个问题,我决定创建一个免费的 python 包,允许任何人获取菲律宾公司的财务数据。fastquant 能够提供任何上市股票截至最*一个交易日的定价数据。
在本文的其余部分,我将演示如何使用简单的移动*均交叉策略,使用 fastquant 对 Jollibee Food Corp. (JFC)进行简单的分析。
装置
安装非常简单,因为这个包是在 PyPi 上注册的!
# Run this on your terminal
pip install fastquant
# Alternatively, you can run this from jupyter this way
!pip install fastquant
获取菲律宾股票数据
有了 fastquant,你可以用两行代码获得任何 PSE 上市公司的财务数据。
在本例中,我们获取了 Jollibee Food Corp. (JFC)从 2018 年 1 月 1 日到 2019 年 1 月 1 日(1 年期)的定价数据。
from fastquant import get_pse_data
df = get_pse_data("JFC", "2018-01-01", "2019-01-01")print(df.head())
# open high low close value
#dt
#2018-01-03 253.4 256.8 253.0 255.4 190253754.0
#2018-01-04 255.4 255.4 253.0 255.0 157152856.0
#2018-01-05 255.6 257.4 255.0 255.0 242201952.0
#2018-01-08 257.4 259.0 253.4 256.0 216069242.0
#2018-01-09 256.0 258.0 255.0 255.8 250188588.0
至此,fastquant 已经完成了它的主要目的——轻松访问菲律宾股票数据。在接下来的步骤中,我们将重点对 JFC 数据进行简单的分析。
绘制每日收盘价
为了绘制 Jollibee 的价格,我们实际上可以直接使用由 get_pse_data 返回的 dataframe,但是我们仍然需要导入 matplotlib 包来添加标题,同时控制其 fontsize(设置为 20)。
# Import pyplot from the matplotlib module
from matplotlib import pyplot as plt# Plot the daily closing prices
df.close.plot(figsize=(10, 6))
plt.title("Daily Closing Prices of JFC\nfrom 2018-01-01 to 2019-01-01", fontsize=20)
请注意,2018 年的峰值出现在 3 月和 12 月左右,而低谷出现在 7 月和 10 月左右。
使用简单的移动*均线(SMA)交叉策略进行分析
在本节中,我们将尝试直观地评估 SMA 交叉策略的性能。有很多方法可以实现这个策略,但是我们会用一个“价格交叉”的方法来实现 30 天的 SMA。
在这种情况下,当收盘价从下方穿过简单移动*均线时,它被认为是“买入”信号,当收盘价从上方穿过简单移动*均线时,它被认为是“卖出”信号。
# Derive the 30 day SMA of JFC's closing prices
ma30 = df.close.rolling(30).mean()# Combine the closing prices with the 30 day SMA
close_ma30 = pd.concat([df.close, ma30], axis=1).dropna()
close_ma30.columns = ['Closing Price', 'Simple Moving Average (30 day)']# Plot the closing prices with the 30 day SMA
close_ma30.plot(figsize=(10, 6))
plt.title("Daily Closing Prices vs 30 day SMA of JFC\nfrom 2018-01-01 to 2019-01-01", fontsize=20)
那么我们如何知道我们的 SMA 价格交叉策略是有效的呢?视觉上,我们可以通过观察“卖出”信号是否发生在股价开始下跌之前,以及“买入”信号是否发生在股价开始上涨之前来评估这一点。
如果你看上面的图表,它看起来非常有效——收盘价线实际上在 3 月左右(第一个高峰的月份)开始几乎持续保持在 30 天 SMA 下方,并在 7 月下旬(第一个低谷的月份)开始保持在 30 天 SMA 上方。
现在,你可能会想,应该有一个更严格的方法来评估交易策略的数字精度。这个过程(如下图所示)被称为回溯测试,是投资专业人士根据经验验证不同交易策略有效性的方式。换句话说,它允许我们比较不同的交易策略,并让我们能够根据历史表现选择最好的一个。
假设我们采用最小最大支持阻力交易策略(2017 年 1 月 1 日至 2019 年 1 月 1 日),进行回溯测试
当然,重要的是要记住,历史表现并不总是会转化为未来的表现,所以应该始终考虑建仓的风险。无论如何,我不打算在这里讨论回溯测试的细节,但是我打算在以后的帖子中讨论它。
结论
祝贺您到达这篇博文的结尾。到目前为止,您应该已经知道如何 1)使用 fastquant 获得菲律宾公司的财务数据,2)绘制公司股票随时间变化的收盘价,3)直观地分析简单移动*均线交叉策略的有效性。
我们还简要地谈到了回溯测试,以及如何用它来比较不同交易策略的有效性。同样有趣的是应用机器学习和基于统计的预测方法来制定人工智能增强的交易策略。在以后的文章中会有更多关于这些和其他高级主题的内容!
你可以在这个笔记本上找到上面执行的脚本。如果您想试用 fastquant,了解更多关于该方法的信息,或者甚至为改进该模块做出贡献,请随时查看 github repo 。
感谢您阅读这篇文章,如果您对 fastquant 或任何与将数据科学应用于金融相关的问题有任何疑问,请在下面随意评论。也可以通过邮件联系我(Lorenzo . ampil @ Gmail . com)Twitter,LinkedIn;然而,期待我更快地回复评论:)
使用 AWS 和 Google Colab 访问卫星图像
使用 Python 和 Google Colab 加载、试验和下载云优化地理信息系统(COG)。
在本地下载卫星影像时,访问卫星影像需要大量存储空间。如果您在一段时间内需要多个地块,该过程会占用您的所有存储空间。更糟糕的是,您可能只需要整个图像的一个子集区域。
为了解决这样的问题,地理空间数据的最新进展使用了我们云优化的地理信息系统(COG)。
云优化 GeoTIFF (COG)是一个常规的 GeoTIFF 文件,旨在托管在一个 HTTP 文件服务器上,其内部组织可以在云上实现更高效的工作流。它通过利用客户端发出的 HTTP GET range 请求来请求他们需要的文件部分。——https://www.cogeo.org/
现在想象一下,能够倒带、前进和停止一个大视频来观看你需要的视频部分。COG 精确地允许你用卫星图像做到这一点。你可以得到一个孔瓷砖,可视化低分辨率,子集和掩盖一个地区,甚至进行任何处理,甚至没有下载它。
本教程将向您展示如何使用 Python 在 Google Colab 中访问存储在 AWS s3 存储中的 Landsat 图像。第一部分讲述了如何找到适合您感兴趣领域的图像,而第二部分向您展示了如何使用 Python 访问、可视化和处理卫星图像。
查找您感兴趣的区域的卫星图像
我收到很多关于如何获得感兴趣区域的正确图像的询问。在这种情况下,我们使用 Landsat 图像,因此我将指导您如何获得卫星图像的路径和行。进入 USGS explorer 网站,通过提供地址或地点(下图中以红色突出显示)找到您感兴趣的地方。一旦你得到结果,点击地址。如果你愿意,可以按日期过滤掉。
下一步是单击数据集并选择数据集。在本教程中,我们使用的是 Landsat 8,所以我们选择了它(下面突出显示的红色)
点击附加标准以过滤云覆盖范围。如下图所示,我们过滤掉小于 10%的云覆盖。
最后,点击结果,找出你所在地区所有可用的图片。一旦您知道您想要用于分析的图像,您就可以复制 ID 或将其记在某处(如下所示)。
你还需要记下卫星图像的路径和行。你可以点击元数据按钮(红色矩形)或者简单地记下 ID: 0030065 的第三部分。
在下一节中,我们将看到如何使用 Python 在 Google Colab 中直接访问数据。Landsat 同时存储在 AWS 和 Google 云*台中,但在本教程中,我们通过 AWS 获取数据。
用 AWS 和 Google Colab 访问 Landsat
让我们首先导入我们将要使用的库。我们的主要工具是 Rasterio,它提供了一个易于使用的 API 来处理卫星图像。
import numpy as np
import matplotlib.pyplot as plt
import rasterio as rio
from rasterio.plot import show
您可以像这样构造您的 URL 路径。
fpath = ‘http://landsat-pds.s3.amazonaws.com/c1/L8/003/065/LC08_L1TP_003065_20190925_20191017_01_T1/LC08_L1TP_003065_20190925_20191017_01_T1_B4.TIF'
我们可以将上面的 URL 分成不同的部分:
[http://landsat-pds.s3.amazonaws.com/c1/](http://landsat-pds.s3.amazonaws.com/c1/)
URL 的第一部分总是相同的,并显示 AWS 存储 URL。
L8/003/065/
L8 表示陆地卫星 8 号。路径:003。第 065 排。URL 的这一部分将根据您正在访问的数据集和感兴趣的区域而变化。
LC08_L1TP_003065_20190925_20191017_01_T1
这部分是图片的 ID,你可以从上面的图片中得到。
LC08_L1TP_003065_20190925_20191017_01_T1_B4.TIF
最后,重复图像的 ID,但这次是您想要访问的波段(这里是 B4)和图像的扩展名。TIFF)
现在,我们已经设置了访问 URL,我们可以编写一个简单的函数来使用 Rasterio 打开图像。
def rasterio_open(f):return rio.open(f)src_image = rasterio_open(fpath)
一次,我们打开光栅图像;您可以使用任何可视化库或仅 Rasterio 的数据可视化方法来绘制它。
fig, ax = plt.subplots(1, figsize=(12, 10))show(src_image, ax=ax)plt.show()
这是我们访问显示的整个图像。我们只获得了频带 4。我们稍后会看到如何将不同的波段组合起来构建一幅 RGB 图像。
如您所见,我们有显示为黑色的 NaN 值。我们可以通过使用 Numpy 功能来消除这些问题。我们首先通过用 Rasterio 读取图像,将图像转换为 Numpy 数组
src_image_array = src_image.read(1)src_image_array = src_image_array.astype(“f4”)src_image_array
图像被转换成数组,如下所示。
array([[0., 0., 0., …, 0., 0., 0.], [0., 0., 0., …, 0., 0., 0.], [0., 0., 0., …, 0., 0., 0.], …, [0., 0., 0., …, 0., 0., 0.], [0., 0., 0., …, 0., 0., 0.], [0., 0., 0., …, 0., 0., 0.]], dtype=float32)
现在,您可以通过将这些空数组赋值为 np.nan 来轻松删除它们。
src_image_array[src_image_array==0] = np.nanfig, ax = plt.subplots(1, figsize=(12, 10))show(src_image_array, ax=ax)plt.show()
我们现在在边上没有空值了。
通常,您可能只对图像的一个子集感兴趣。在下一节中,我们将介绍如何使用 Rasterio 的窗口功能对图像进行子集化。
子集化图像
要只访问图像的特定部分,可以用行、列、宽度和高度过滤掉图片。比方说,我们不想要整个图像,而是要一个 750 X 850(宽和高)的 1200 列和 1200 行的图像。
# Window(col_off, row_off, width, height)
window = rio.windows.Window(1200, 1200, 750, 850)subset = src_image.read(1, window=window)fig, ax = plt.subplots(1, figsize=(12, 10))show(subset, ax=ax)
ax.set_axis_off()plt.show()
现在图像缩小到一个子集,在城市 Eirunepe 附*,如下图所示。
最后,下一节将展示如何创建一个 RGB 图像并将其下载到本地。
创建 RGB 并下载
我们首先通过为每个波段提供一个单独的 URL 来访问每个波段。注意,除了。TIF 分机。这些是波段,在这种情况下,因为我们想要创建一个 RGB 图像,所以我们访问波段 4(红色)、波段 3(绿色)和波段 2(蓝色)。
rpath = ‘http://landsat-pds.s3.amazonaws.com/c1/L8/003/065/LC08_L1TP_003065_20190925_20191017_01_T1/LC08_L1TP_003065_20190925_20191017_01_T1_B4.TIF'gpath = ‘http://landsat-pds.s3.amazonaws.com/c1/L8/003/065/LC08_L1TP_003065_20190925_20191017_01_T1/LC08_L1TP_003065_20190925_20191017_01_T1_B3.TIF'bpath = ‘http://landsat-pds.s3.amazonaws.com/c1/L8/003/065/LC08_L1TP_003065_20190925_20191017_01_T1/LC08_L1TP_003065_20190925_20191017_01_T1_B2.TIF'red = rio.open(rpath)green = rio.open(gpath)blue = rio.open(bpath)
我们创建一个 RGB 图像,方法是打开一个空图像,并用上面打开的三个波段填充它。
# Create an RGB imagewith rio.open(‘RGB.tiff’,’w’,driver=’Gtiff’, width=red.width, height=red.height,count=3,crs=red.crs,transform=red.transform, dtype=red.dtypes[0]) as rgb:rgb.write(blue.read(1),1)rgb.write(green.read(1),2)rgb.write(red.read(1),3)rgb.close()
图像现已存储。你可以用 Rasterio 打开或者下载到本地。
使用 QGIS 可视化的图像子集
结论
在本教程中,我们介绍了如何查看和找到您感兴趣的领域的正确数据。我们还了解了如何使用 Python 和 AWS 存储来访问 Landsat 图像。
本教程的代码可以在这个 Colab 笔记本上找到。
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/shakasom/rs-python-tutorials/blob/master/Cloud_Optimized_Geotiffs.ipynb)
自己访问和检查新冠肺炎数据
构建一个 choropleth 图,显示美国各县过去七天的人均新冠肺炎死亡人数
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
数据和疫情
对于此时地球上的大多数人来说,经历一次全球性的疫情是一次前所未有的经历。有时,我会想到 1918 年至 1920 年的下一次全球疫情与今天之间的时期。这 100 年里,在你能想到的几乎所有领域,包括数据和技术,都发生了一些迄今为止世界上最引人注目的变化。我想知道那些生活在 1918 年的人是如何获得关于疫情及其传播的信息的?今天,我们有许多信息来源可用,并随时可以访问数据显示,包括预测模型,描述和预测疫情的轨迹。但是,作为一名数据科学家,您可能会发现,即使在查看了可用内容之后,您仍有一些问题没有得到解答,并且希望能够自己监控快速发展的情况。幸运的是,通过约翰·霍普金斯系统科学与工程中心(https://systems.jhu.edu/research/public-health/ncov/)的深入研究,你可以获得全球范围内每日的新冠肺炎病例数和死亡人数,也可以获得美国各州、县或地区的数据。然后,您可以使用这些信息来设计数据报告和显示,以便更好地做出困难的决策。例如,在本报告中,我将向您展示如何:
1.在 Github 上访问约翰霍普金斯大学的新冠肺炎数据,
2.执行一些简单的数据操作来转换数据,并且
3.使用 albersusa R 软件包构建一个 choropleth 图(https://rud . is/b/2016/03/29/easy-composite-u-s-choropleths-with-albers USA/),以显示美国各县过去七天的人均新冠肺炎死亡人数。
访问 Github 上的每日新冠肺炎数据
您可以从加载下面的包开始。注意,如果没有安装 albersusa 包,可以使用 devtools 包中的 install_github()函数来安装。
# Data on COVID-19 from Johns Hopkins Center for Systems Science and Engineering
# https://systems.jhu.edu/research/public-health/ncov/
# https://github.com/CSSEGISandData/COVID-19# Blog post to demonstrate chloroplot package
#https://rud.is/b/2016/03/29/easier-composite-u-s-choropleths-with-albersusa/rm(list = ls())
library(tidyverse)
library(rgeos)
library(maptools)
library(ggplot2)
library(ggalt)
library(ggthemes)
library(albersusa) # devtools::install_github("hrbrmstr/albersusa")
library(scales)
library(gtools)
可以使用以下方法读取数据。请注意,在相同或相邻的目录中,还有美国病例、全球病例和死亡病例的数据集。
# read time series data on US deaths by county
urlfile='[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_US.csv'](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_US.csv')
cov19_us_dat<-read_csv(url(urlfile))
数据每天更新。在本例中,我们只想使用最* 8 天的数据(因为我们需要减去——您将在下面看到)。我们还保存了 fips 代码(用于标识美国各县)和每个县的人口,以便我们可以计算人均值。
# Collect data consisting of the last 8 days
tot_days <- ncol(cov19_us_dat)
begin_day <- tot_days - 7
fips <- cov19_us_dat$FIPS
pop <- cov19_us_dat$Population
us_recent <- cov19_us_dat[,begin_day:tot_days]
请注意,这些文件中的数据是累积形式的,所以如果我们想要每天的计数,我们需要从前一天减去每天的总数。下面是一个简单的方法。
# Convert cumulative data to new values each day
us_daily <- us_recent[,-1] — us_recent[,-8]
us_fatal <- data.frame(fips, pop, us_daily)
colnames(us_fatal) <- c(‘fips’, ‘population’,colnames(us_daily))
最后,有几个数据处理步骤:
1.仅保存位于美国 50 个州或 DC 的县的 fips 代码。
2.处理一些实际上比前一天减少的累积计数(可能是由于数据澄清或调整)。
3.将人口转换为每 10 万人的数量。
4.计算人均比率的十分位数。选择分组到 10 个箱中是一种判断,随着数据随时间的变化,可能会有更好的选择。请注意,前 5 个十分位数的县在过去 7 天内没有出现死亡病例,因此最终只有 5 组。
5.当读入 fips 代码时,除非您能始终如一地将它们存储为“字符”类型,否则它们可能会转换为“整数”类型并丢失前导零。str_pad 函数可以解决这个问题。
6.南达科塔州奥格拉拉拉科塔的 fips 代码显然发生了变化,需要手动解决,以避免在南达科他州中部的地块上出现大的白色方块。
us_fatal <- us_fatal %>%
filter(fips %in% (1001:56045)) %>%
mutate(sum = rowSums(.[3:9]),
sum = ifelse(sum > 0, sum, 0),
pop_100_000 = population/100000,
percap = sum/pop_100_000,
percap_quint = quantcut(percap, q=10, dig.lab = 3),
fips = as.character(fips),
fips = str_pad(fips, 5, 'left','0'))
# replace fips for Oglala Lakota, SD (formerly Shannon, SD)
us_fatal$fips <- replace(us_fatal$fips, us_fatal$fips == "46102", "46113")
设置打印颜色的一个选项:
# Set up plot colors according to the number of levels of quintiles (many 0's)
no_colors <- length(unique(us_fatal$percap_quint))
quin_colors <- c("springgreen", "skyblue", "navy","violet","violetred")
start_color <- 5 - no_colors + 1
plot_colors <- quin_colors[start_color:5]
最后,使用 ggplot()创建图形:
cmap <- fortify(counties_composite(), region=”fips”)gg <- ggplot()
gg <- gg + geom_cartogram(data=cmap, map=cmap,
aes(x=long, y=lat,map_id=id),show.legend = FALSE,
color=”#2b2b2b”, size=0.05, fill=NA)
gg <- gg + geom_cartogram(data=us_fatal, map=cmap,
aes(fill=percap_quint, map_id=fips),
color=”#2b2b2b”, size=0.05)
gg <- gg + scale_fill_manual(name=”per 100,000 pop”, values = plot_colors)
gg <- gg + labs(title=’Covid-19 Fatalities per capita by US County, Last 7 days’,
subtitle=paste(‘Data source: Johns Hopkins Center for Systems Science and Engineering, ‘, Sys.Date(), sep=’’))
gg <- gg + theme_bw()
gg <- gg + xlab(NULL)
gg <- gg + ylab(NULL)
gg <- gg + theme(axis.ticks.x = element_blank())
gg <- gg + theme(axis.ticks.y = element_blank())
gg <- gg + theme(axis.text.x = element_blank())
gg <- gg + theme(axis.text.y = element_blank())
gg <- gg + theme(legend.position=c(0.85, 0.30))
gg <- gg + theme(plot.title=element_text(size=24, hjust = 0.5))
gg <- gg + theme(plot.subtitle=element_text(size=18, hjust = 0.5))
gg <- gg + theme(legend.text=element_text(size=14))
gg <- gg + theme(legend.title=element_text(size=18))png(paste(“choro.png”, sep = “”), width = 1200, height = 800, units = “px”)
gg
使用 Python 访问人口普查数据
公共数据项目
随着 2020 年人口普查的进行和即将到来的选区重新划分,访问和理解公共人口普查数据比以往任何时候都更加重要。这篇文章将指导你使用一个名为 CensusData 的 Python 包将数据导入 Pandas
普查数据集
通过 CensusData 有 5 个数据集可用,包括经典的十年一次的人口普查以及 4 个不同的美国社区调查(ACS)估计。
什么是美国社区调查?
ACS 始于 2005 年,取代了过去每十年与传统人口普查一起发送给家庭子集的长表格人口普查。相反,ACS 是在滚动的基础上进行的,每月发送给大约 350 万个家庭。这个子集然后被用来创建整个人口的估计。ACS 上的问题也更加深入,包括教育、就业和互联网接入等主题。
五个数据集
- ACS 1 年评估(2012–2018)针对人口超过 65,000 的地区,更新最频繁,但“分辨率”最低,因为它不包括人口较少的地区,且样本量最小
- ACS 1 年补充评估(2014–2017)补充数据集,重点关注 20,000+人口较少的地区
- ACS 3 年估计值(2010-2012 年至 2011-2013 年)针对人口超过 20,000 的地区,非常接* 1 至 5 年的中间值。目前由人口普查局打折,但旧版本仍然可以访问。
- ACS 五年估计值(2005–2009 年至 2014–2018 年)所有区域的数据,最高分辨率和最大样本量,但最少当前数据
- 2010 年人口普查摘要文件 1 统计美国的每一个居民,每 10 年更新一次。
笔记
- 跨越多年的估计数是总量
- 永远不要比较重叠范围的估计值,例如,比较 ACS 2010–2012 年到 2011–2013 年的 3 年
设置和搜索表格
通过您的终端使用 pip 可以轻松完成安装。
pip install censusdata
现在你可以在人口普查网站上查找你感兴趣的表格,例如这里的是 ACS 的。或者您可以使用 CensusData 的搜索方法
import pandas as pd
import censusdatasample = censusdata.search('acs5', 2015,'concept', 'transportation')
以下是来自文档的搜索参数的详细信息:
- src ( str ) —人口普查数据来源:acs1 年估计数为“ACS 1”,acs5 年估计数为“ACS 5”,acs3 年估计数为“ACS 3”,ACS 1 年补充估计数为“acsse”,sf1 数据为“SF1”。
- 年 ( int ) —数据的年份。
- 字段 ( 字符串 ) —要搜索的字段。
- 标准 ( 字符串 ) —搜索标准。
- tabletype ( str,可选 ) —从中提取变量的表格类型(仅适用于 ACS 数据)。选项包括“详细信息”(详细信息表)、“主题”(主题表)、“配置文件”(数据配置文件表)、“c 配置文件”(比较配置文件表)。
因此,在上面的搜索查询中,我们正在寻找从 2015 年开始的 5 年 ACS 估计值,其中包含“运输”这一概念。现在,这个搜索将返回一个包含变量名、概念和符合搜索标准的标签的三元组列表。这个列表可能相当大。
print(len(sample))>>>3630
让我们详细检查两个第一元组,以理解它们告诉我们什么。
print(sample[0])>>>('B08006_001E', 'B08006\. Sex of Workers by Means of Transportation to Work', 'Total:')print(sample[2])>>>('B08006_002E', 'B08006\. Sex of Workers by Means of Transportation to Work', 'Car, truck, or van:')
第一个元素是变量名,包含两个元素,父表和子表名称。两个条目共享同一个父表‘b 08006’,它对应于第二个元素概念,‘b 08006。上班交通工具上的工人性别。最后一个元素是对应于它们的子表的标签。
打印表格和查找地理位置
一旦知道了感兴趣的父表,就可以使用 print table 命令清楚地读出所有子表。
censusdata.printtable(censusdata.censustable('acs5', 2015, 'B23025'))
包含在图像中,因为它不适合介质格式
为了下载一些人口普查数据,您需要的最后一部分是您感兴趣的地区的地理代码。我们可以使用地理方法来探索这些信息。
states = censusdata.geographies(censusdata.censusgeo([('state', '*')]), 'acs5', 2015)
该查询将返回一个 dictionary 对象,其中每个键都是一个州的名称。下面是前两个元素的示例。
{'Alabama': censusgeo((('state', '01'),)),
'Alaska': censusgeo((('state', '02'),))}
因此,为了找到纽约的代码,我们需要打印相应的值。
print(states['New York']
>>>Summary level: 040, state:36
我们感兴趣的是第二个值 36,它可以用来获取该州的所有县代码。
counties = censusdata.geographies(censusdata.censusgeo([('state', '36'), ('county', '*')]), 'acs5', 2015)print(counties)
>>>Summary level: 040, state:36
{'Queens County, New York':
censusgeo((('state', '36'), ('county', '081'))),
'Rensselaer County, New York':
censusgeo((('state', '36'), ('county', '083'))),
'Richmond County, New York':
censusgeo((('state', '36'), ('county', '085'))),
...}
下载数据
现在我们已经拥有了下载第一组人口普查数据所需的一切!
data = censusdata.download('acs5', 2015,
censusdata.censusgeo([('state', '36'),
('county', '081'),
('block group', '*')]),
['B23025_001E', 'B23025_002E', 'B23025_003E',
'B23025_004E', 'B23025_005E',
'B23025_006E', 'B23025_007E'])
该查询将把请求的数据存储为 Pandas 数据帧,可以使用标准的 Pandas 方法访问该数据帧。
print(data.head)
恭喜你!你已经正式访问了公开的美国人口普查数据。
参考资料:
https://jtleider.github.io/censusdata/
https://www.census.gov/en.html
冠状病毒测试的准确性
你如何衡量冠状病毒测试的可靠性?
在我最*阅读的一篇文章中写道,
“研究人员发现,在研究组的 167-3%的患者中,有 5 名患者进行了胸部 CT 扫描特征提示新冠肺炎,通过 RT-PCR 初步检测为 SARS -CoV-2 感染阴性。”—医药网
幸运的是,测试假阴性的患者被隔离,重复测试帮助他们确认他们患有新冠肺炎(新型冠状病毒感染)。那么假阴性是什么意思?医学研究人员如何衡量这些测试的准确性?
迪米特里·卡拉斯泰列夫在 Unsplash 上的照片
在科学领域,有几种方法可以评估测试的可靠性。一些最常见的指标被称为“准确度”、“精密度”、“灵敏度(召回)”和“特异性”。这些是优化测试可靠性的一些最常用的指标。在我们深入研究一个科学家如何衡量医学测试可靠性的虚构例子之前,让我们先了解一下混淆矩阵的基础知识。
混淆矩阵
混淆矩阵是一个表格,用于分类一个测试是否准确。这张桌子被分成四个格子——
- 一项测试可以准确预测一个人是否患有冠状病毒(TP)
- 一项测试可以准确预测这个人是否没有冠状病毒(TN)
- 一项测试错误地预测一个人是否患有冠状病毒(FP)
- 一项测试会错误地预测一个人是否没有冠状病毒(FN)。下面是一幅插图
让我们继续这个例子…
如果您有一个 1000 人的随机样本来测试您的冠状病毒测试的可靠性,并且 100 人(10%)患有冠状病毒,您希望优化什么指标?错误预测的代价是什么?这是所有医学研究者都必须经历的一些问题。随着这些测试变得越来越普遍,我相信了解这些测试是如何工作的是很重要的。越来越多的人将参加考试,我们将开始在新闻文章中看到错误的统计数据,所以我希望这篇文章可以帮助你更多地了解这些考试。
准确(性)
准确性将测试正确预测的所有人除以随机样本中的所有人。这听起来可能是一个很好的指标,但在不*衡的样本中,它可能不是一个很好的指标。例如,如果测试被打破,并预测每个人都没有冠状病毒。它仍然是 90%。
当随机样本有一个*衡组,而您试图预测的目标接* 50%时,此指标更适用。
简单来说,正确答案在样本的所有人中,有多少人的测试显示了正确的结果。
精确
精度将测试正确预测的所有人除以测试结果为阳性的所有人。当样本不*衡时,精确度比准确度更好。
精确帮助你回答,在测试呈阳性的人中,有多少人实际上患有冠状病毒?
敏感性又名回忆
敏感度和召回率是可以互换的,但这两个术语都是经常使用的,所以了解这两个术语是有好处的。敏感性往往伴随着特异性,而回忆则伴随着精确性。该指标将测试正确预测的所有人分为所有冠状病毒携带者。
敏感性/回忆帮助你回答,在患有冠状病毒的人群中,有多少人检测呈阳性?
问自己一个问题:你希望人们认为他们没有冠状病毒,而事实上,他们有吗?告诉一个冠状病毒携带者自己没有的代价是什么?
通常你不得不选择优化精确度或者召回率,因为当你增加一个的时候,通常会减少另一个。反之亦然。看看 Google 的这篇文章:精准 vs 召回。还有其他衡量两种指标协调性的指标,如 F1 分数,但我不会在本文中赘述。
特征
特异性将测试正确预测为健康的所有人除以所有健康的人。
特异性帮助您回答,您希望该测试在多大程度上正确预测一个人没有冠状病毒?
问自己一个问题:你会因为一个错误的测试而隔离自己吗?
总结
这些都是医疗决策者必须自问的重要问题。我不确定是否所有的医学测试都是完美的,所以如果你开始看到关于这些测试如何不正确工作的新闻。回头看看这篇文章,试着猜测医学研究者试图优化什么。如果我是一名医生,我会认为回忆是最重要的一项,即使我们必须以假阳性为代价来优化这一指标——假检测结果告诉一些健康人他们患有冠状病毒。此外,新闻文章将开始报道准确的数字。确保通过自己做一些研究来了解这些测试的可靠性。
希望你能带走一些有用的信息。
如果您有任何问题或反馈,请随时在下面留下您的问题或反馈,或者在 LinkedIn 上联系我。
中:https://medium.com/@测试学习
领英:【https://www.linkedin.com/in/kennyk1m/
资源
新型冠状病毒的新病例在全球范围内持续增加,截至 2014 年,全球已确诊 73,332 例新冠肺炎病例
www.medicinenet.com](https://www.medicinenet.com/script/main/art.asp?articlekey=228250) [## 分类:精度和召回|机器学习速成班
预计时间:9 分钟精度试图回答以下问题:什么比例的积极…
developers.google.com](https://developers.google.com/machine-learning/crash-course/classification/precision-and-recall)
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
深度学习中的准确性可视化—第 1 部分
内部 AI
张量板是最强大的开箱即用工具之一,可用于模型性能可视化和焦点优化调整。
深度学习模型性能可视化(文章中描述的代码的输出)
“一个眼神胜过千言万语。”
我们都想以最优的方式训练深度学习模型,提高哪怕是预测精度的最后两位小数。我们在深度学习模型中有如此多的参数要调整,从优化器及其参数、激活函数、层数/过滤器等开始。找到所有这些参数的正确组合就像大海捞针。
幸运的是,我们可以利用超参数来调整模型的性能和准确性,但是我们需要对参数组合有一个广义的理解来尝试和测试。
Tensor board 是最强大的内置工具之一,可用于基于不同指标可视化单个模型的性能,也可用于不同模型之间的比较。它可以指导确定我们可以进一步尝试超参数调整的大概参数组合。
在这篇文章中,我将讨论深度学习模型可视化,结合优化器和简单回归的激活函数。它将使我们能够了解如何快速丢弃不合适的组合,并将我们的性能调优工作集中在几个潜在的参数上。
第一步: 我们将使用Scikit learnmake _ regression 方法生成一个用于回归测试的随机数据集,并使用 train_test_split 将数据集分成训练集和测试集。
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
第二步: 在下面的代码中,我们导入了张量板和深度学习 Keras 包。我们将使用 Keras 建模和张量板可视化。
from tensorflow.keras.callbacks import TensorBoard
from keras.models import Sequential
from keras.layers import Dense
第三步: 在本文中,我们将使用“adam”和“RMSprop”优化器,以及“GlorotUniform”和“normal”权重初始化器。我们在列表中提到了这些,并将按顺序调用组合来训练模型。
optimizers=["adam","RMSprop"] #Optimisers
initializers=["GlorotUniform","normal"] # Activation function
第五步:在下面的代码中,我们嵌套了 FOR 循环,用优化器和权重初始化器的不同组合来训练深度学习模型,并将结果记录在张量板中进行分析。
每个模型都用权重初始化器和优化器名称命名,以识别每个模型的结果和图形。
由于本文的主要目标是学习深度学习模型结果的可视化,因此我们将使用一个非常简单的模型,该模型具有一个输入、隐藏和输出层。
我们将使用均方误差作为所有模型的损失函数,并测量*均绝对百分比误差。如果你不知道这些统计指标,那么我建议你参考维基百科获得详细的解释。
步骤 6: 我们可以在代码执行后查看结果并进行分析。我们需要在 windows 中打开命令提示符或者在 mac 中打开终端来启动张量板。通过命令提示符/终端导航到保存日志的文件夹目录,然后键入以下命令。
tensorboard --logdir=logs/
它将实例化张量板,并显示我们需要在浏览器中输入的地址,以查看结果。
张量板登录页面
在当前示例中,我们可以通过在浏览器中键入 http://localhost:6006/ 来访问张量板。
在一个合并图中,我们可以看到随着优化器和权重初始化器的不同组合的迭代次数的增加,均方误差的变化。
不同模型的每个时期的损失值
它指示不适合当前数据集和建模的优化器和权重初始化器。在当前示例中,“RMSprop”和“normal”优化器组合的均方损失下降速度比其他组合慢。基于这种来自观想的知识,我们可以集中精力微调剩余的组合,通过不调整在广泛层面上表现不好的组合来节省时间。
同样,随着迭代次数的增加,我们可以查看不同组合的*均绝对百分比误差的变化。
不同模型的每个历元的*均绝对百分比误差值
基于型号名称的过滤器选项
我们还可以使用过滤器来查看一个或多个模型组合的图表。
给模型起一个有意义的名字是很重要的,因为它有助于正确放置过滤器,避免分析过程中的混淆。在当前示例中,权重初始化器和优化器的组合是模型的名称。
为一个模型过滤的每个历元的损失值
我们也可以下载图形,损失函数数据分别为 SVG 和 CSV 格式。CSV 格式的损失函数数据使我们能够使用 excel 快速执行高级分析。
下载图表和数据的选项
除了根据时代进展可视化结果之外,我们还可以通过单击鼠标来查看模型的相对性能。
每个时期的损失值相对比较
在本文中,我们已经学习了张量板的基础知识,并看到了一些可视化选项,可用于在瞬间掌握不同模型的更好的细节。我们还看到了我们可以使用张量板可视化来专注于微调潜在模型的方式。在下一篇文章中,我们将看到一些深度学习模型的高级可视化。
如果你想学习可视化的探索性数据分析(EDA),请阅读文章 5 探索性数据分析(EDA)的高级可视化
如果你像我一样是熊猫的忠实粉丝,那么你会发现文章 5 熊猫数据预处理的强大可视化读起来很有趣。
准确性可视化:监督机器学习分类算法
内部 AI
分类算法结果的可视化报告提供了错误分类和准确度估计的快照。更快地解释和规避一般的准确性分数陷阱。
测量任何回归或分类算法的预测准确性在建模期间的不同阶段都至关重要,当模型在生产中运行时也是如此。
我们有几种方法来衡量分类算法的准确性。在Scikit-learn**包中,我们有几个评分,比如召回评分,准确率评分等等。然后我们有现成的总结报告。在我看来,这些指标中的大多数都有一个或多个与冗长相关的限制,难以理解,在数据集中的不*衡类别的情况下,有可能误解准确性,需要引用少量分数来获得整体视图等。
为了更好地理解这种限制,让我们考虑一下表中所示的例子。我们几乎没有与样本人群以及他们是否为 COVID 阳性相关的参数。因为我们有更多的人是 COVID 阴性,而不是病毒感染者,因此,我在这个例子中考虑了类似的分布。
用于解释的假想样本数据
在此数据集上训练的分类算法预测了最后一列中所示的结果。分类模型的准确率接* 90%。它给我们的印象是,该模型在预测结果方面相当不错。
from sklearn.metrics import recall_score
from sklearn.metrics import classification_report
from sklearn.metrics import accuracy_score# 0- Healthy , 1- Covidy_true = [0, 1, 0,0,0, 1,0,0,0,0,0]
y_pred = [0, 0, 0,0,0, 1,0,0,0,0,0]print("The recall Score is" , recall_score(y_true, y_pred))
print("The accurracy score is" , accuracy_score(y_true, y_pred))
实际上,该模型预测 COVID 阳性病例的概率只有 50%。仅基于一个度量或者在不了解分类模型出错的领域的情况下部署这样的模型可能是非常昂贵的。
在考虑了召回率和准确率以及业务用例之后,我们可以充分理解适合生产使用的模型。
像混淆矩阵这样的视觉指标在几个方面胜过其他指标。我们可以即时了解模型在分类方面的性能,以及模型的优势和需要微调的方面。基于业务用例,我们可以从假阳性、假阴性、真阳性和真阴性计数中快速判断模型是否准备好进行部署。
让我们学习用混淆矩阵来形象化和解释线性回归和逻辑回归的结果。
步骤 1: 我们将使用本文中的 Scikit - learn 内置数据集 WINE 进行讨论,使用 Matplotlib 进行可视化。在下面的代码中,我们导入了将在程序中使用的模块。
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
import matplotlib.pyplot as plt
from sklearn.metrics import plot_confusion_matrix
第二步:将葡萄酒数据集中的特征(属性)分为自变量和因变量。自变量(输入特征)用“X”表示,因变量用“y”表示。使用 train_test_split 方法分为训练集和测试集。
X,y = load_wine(return_X_y=True)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.10,random_state=0)
第三步:sklearn 中的大多数监督算法需要以零为中心的标准正态分布输入数据,并且具有相同数量级的方差。由于葡萄酒数据集中的独立变量值具有不同的比例,因此我们需要在建模之前对其进行缩放。
如果你想了解更多关于Scikit-Learn**包中自变量和不同定标器的定标,那么请参考我的文章Feature Scaling-Effect Of Dive Dive Dive Dive。
SC_X=StandardScaler()
X_train_Scaled=SC_X.fit_transform(X_train)
X_test=Scaled=SC_X.transform(X_test)
第 4 步:在下面的代码中,定义了一个带有参数的分类器列表
classifiers=[ LinearSVC(dual=False),LogisticRegression(solver="liblinear",max_iter=100)]
第五步:用每个分类器依次训练模型,根据训练集中实际和预测的因变量值绘制混淆矩阵。
for clf in classifiers:
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
fig=plot_confusion_matrix(clf, X_test, y_test, display_labels=["Bad Wine","Fair Wine","Good Wine"])
fig.figure_.suptitle("Confusion Matrix for " + str(clf))
plt.show()
乍一看,我们可以看到,与逻辑回归相比,线性 SVC 中从左上角到右下角对角线的数字总和更高。这立即表明线性 SVC 在识别真正的阳性记录方面表现得更好。
基于文中讨论的代码的混淆矩阵
不同的度量分数可以指示准确性,但是使用混淆矩阵,我们可以立即看到算法错误分类的类别。在当前的例子中,两个分类器都没有准确地对大多数劣质酒进行分类。这种详细程度的信息有助于执行模型的焦点微调。
我们已经看到,混淆矩阵以一种清晰的方式提供了关于不同类别的分类模型预测模式的更好的细节。在单个混淆矩阵中,我们可以获得假警报(假阳性)和正确拒绝率等细节,并根据业务案例决定模型是否可接受。
使用 BERT 精确标注主观问答内容
关于 Kaggle 问答理解竞赛第六名解决方案的 NLP 教程
来源:https://www.kaggle.com/c/google-quest-challenge/overview
介绍
Kaggle 在 2020 年初发布了 Q & A 理解比赛。该竞赛要求每个团队构建 NLP 模型来预测问题和答案对的主观评分。我们在所有 1571 支队伍中名列第六。除了在 Kaggle 上发布的获胜解决方案博客之外,我们还写了这个更适合初学者的教程来介绍比赛以及我们是如何赢得金牌的。我们也在这个 Github 仓库中开源我们的代码。你也可以在我的博客里找到这篇文章。
数据
比赛从 70 个栈溢出式网站收集问题和答案对,问题标题,正文和答案作为文本特征,还有一些其他特征,如 url,用户 id。目标标签是 30 个维度,值在 0 到 1 之间,用于评估问题和回答,如问题是否重要,回答是否有帮助等。评分者接受的指导和培训很少,目标很大程度上依赖于他们的主观解释。换句话说,目标分数只是来自评分者的常识。目标变量是对多个评价人的分类进行*均的结果。也就是说,如果有四个评定者,一个将其归类为正面,另三个归类为负面,则目标值将为 0.25。
下面是这个问题的一个例子
- 问题标题 : 用伸缩管代替微距镜头,我损失了什么?
- 问题正文 : 在玩了便宜的微距摄影之后(阅读:反转镜头,安装在直镜头上的反转镜头,被动伸缩管),我想进一步了解这一点。关于……的问题
- 回答 : 我刚买了延长管,所以瘦子来了。…使用试管时,我失去了什么…?相当多的光!增加镜头末端到传感器的距离……
训练集和测试集分布如下
评估指标
本次比赛采用斯皮尔曼等级相关系数作为评价指标。
直观上,皮尔逊相关是 X 和 Y 的线性相关的度量,对于斯皮尔曼的秩相关,我们不使用 X 和 Y 的值,而是在公式中使用 X 和 Y 的秩。它是 X 和 y 之间单调关系的度量。如图所示,图表中给出的数据,pearson 为 0.88,spearman 为 1。
为什么这次 kaggle 比赛要用 spearman?考虑到标签的主观和噪声性质,Spearman 相关往往对异常值更稳健,例如 pearson 相关。还因为目标值是基于评分者常识的问答理解。假设我们有 3 个答案,我们评估这些答案是否写得很好。答案 A 得分 0.5,答案 B 得分 0.2,答案 C 得分 0.1,如果我们宣称答案 A 比答案 B 好 0.3,有意义吗?不完全是。在这里,我们不需要精确的值差。知道 A 优于 B and B 优于 c 就足够了
来源:https://en . Wikipedia . org/wiki/Spearman % 27s _ rank _ correlation _ coefficient
NLP 管道
(图片作者)
一般的 NLP 管道如上图所示。典型的非基于神经网络的解决方案可能是:
- 使用 TF-IDF 或单词嵌入来获得基于令牌的向量表示
- 将标记向量*均为获取文档向量表示
- 使用随机森林或 lightGBM 作为分类器或回归器
由于 2017 年和 2018 年 transformer 和 BERT 的出现,NLP 一直在经历一个“ImageNet”时刻。BERT 已经成为 NLP 竞赛的主要算法。在这个博客中,我们不介绍伯特。这里有这里有,这里有这里有,这里有这里有等几个不错的教程。
现在,我们可以使用 BERT 来重构 NLP 管道:
- 使用 BERT 单词块标记器生成(子)单词标记
- 从 BERT 生成每个令牌的嵌入向量
- 通过神经网络池层对令牌向量进行*均
- 使用前馈层作为分类器或回归器
金牌解决方案
整体情况
如下图所示,我们使用四个基于 BERT 的模型和一个通用句子编码器模型作为基础模型,然后将它们堆叠起来生成最终结果。在这篇博客的剩余部分,我们将只关注 transformer/BERT 模型。关于通用语句编码器的更多信息,可以访问原文这里,代码可从这里获得。
(图片作者)
基于 BERT 模型的体系结构
下面的动画展示了一个基本模型的工作原理。这里的代码是这里是。
- 问题标题和问题正文连接在一起作为输入。使用 BERT 记号化器得到子词,然后生成 BERT 嵌入。接着是*均池层,我们得到每个问题标题和正文对的向量表示。注意,我们对非屏蔽令牌的令牌嵌入进行了*均。这是我们与普通方法不同的地方,在交叉验证方面做了一点改进。附加其他分类或数字要素,然后通过格鲁激活和缺失与线性图层连接。
- 类似地,我们有一个镜像结构,问题标题和答案对作为输入。我们有两个选择。如果镜像 BERT 模型可以分担第一个 BERT 模型的权重,我们称之为“连体”结构。它也可以使用单独的重量,那么我们称之为“双”结构。连体结构通常具有更少的参数和更好的泛化能力。我们对连体和双结构进行了实验,并根据交叉验证分数选择了最佳的 N 基模型。
- 上述两种结构的输出被连接,并连接到前向层,以获得 30 维目标值的预测。
Huggingface 打包了大多数最新的 NLP 模型 Pytorch 实现。在我们的解决方案中,选择了 4 个由 Huggingface 实现的基于 BERT 的模型。分别是暹罗罗伯塔基地,暹罗 XLNet 基地,双阿尔伯特基地 V2,暹罗伯特基地 uncased。
(图片作者)
培训和实验设置
我们有两个阶段的训练。阶段 1 是端到端的参数调优,阶段 2 只调“头”。
在第一阶段:
- 用 huggingface AdamW optimiser 训练 4 个时代。这里的代码是这里的
- 二元交叉熵损失。
- 单周期 LR 计划。使用余弦预热,然后是余弦衰减,同时具有动量的镜像时间表(即余弦衰减后是余弦预热)。这里的代码是这里的
- 回归头的最大 LR 为 1e-3,变压器主干的最大 LR 为 1e-5。
- 累计批量为 8
在第二阶段:
- 冻结变压器主干,并以 1e-5 的恒定 LR 微调回归头额外 5 个周期。这里的代码是这里的
- 大多数型号的 CV 增加了约 0.002。
堆垛
堆叠是卡格勒人“事实上”的集体策略。下面的动画演示了训练和预测过程。示例中有 3 个折叠。为了获得每个折叠的元训练数据,我们对 2 个折叠进行迭代训练,并对剩余的折叠进行预测。并且整个非折叠预测被用作特征。然后,我们训练堆叠模型。
在预测阶段,我们将测试数据输入到所有非折叠基础模型中以获得预测。然后,我们对结果进行*均,传递到堆叠模型以获得最终预测。
(图片作者)
(图片作者)
其他技巧
分组文件夹
让我们先来看看为什么普通的 KFold split 在这个比赛中效果不好。在数据集中,一些样本是从一个问答线程中收集的,这意味着多个样本共享相同的问题标题和正文,但答案不同。
如果我们使用正常的 KFold split 函数,对相同问题的回答将分布在训练集和测试集中。这会带来一个信息泄露的问题。更好的拆分是将同一问题的所有问题/答案对放在一起,放在训练集或测试集中。
幸运的是,sk-learn 已经提供了一个函数 GroupKFold 来生成不重叠的组进行交叉验证。问题体字段是用来表示分组的,如下面的代码。
后处理
正如许多其他团队所做的那样,一个后处理步骤对性能有着巨大的影响。总的想法是基于向下舍入预测到某个分数 1/d 的倍数。
因此,如果 d=4,x = [0.12,0.3,0.31,0.24,0.7],这些值将被舍入为[0.0,0.25,0.25,0.0,0.5]。对于每个目标列,我们在[4,8,16,32,64,None]中对 d 值进行网格搜索。
在我们的集合中,我们进一步开发了这种技术,首先对单个模型预测应用舍入,然后再对模型预测进行线性组合。在这样做的过程中,我们确实发现,对每个模型使用单独的舍入参数,超出倍数的分数提高将不再转化为排行榜。我们通过在所有模型中使用相同的 d_local 来减少舍入参数的数量,从而解决了这一问题:
所有集合参数(2 个舍入参数和模型权重)都是使用小网格搜索设置的,该搜索优化了出折叠的 spearman 等级相关系数度量,同时忽略了具有重复问题的行的问题目标。最终,这种后处理将我们的 10 倍组折叠 CV 提高了约 0.05。
孙喆,罗宾·尼塞特,艾哈迈德·艾尔丹姆和覃晶
ace FAANG 系统设计面试
艾萨克·史密斯在 Unsplash 上拍摄的照片
(这个帖子也在我的博客里)
如今,系统设计在技术面试中很常见。如果编码面试验证编码的能力,那么系统设计面试验证构建的能力。它验证候选人是否能够构建一个能够大规模运行和容错的系统。有很多很棒的资源,比如探索系统设计或设计数据密集型应用,它们为您提供了关于系统设计最佳实践的很棒的例子和细节。但是在我与许多人交谈后,我感觉他们中的许多人倾向于记住每个例子的答案。因此,我发现写下这些经验法则的总结对你在真正的面试中做出反应是至关重要的。以下是我的总结。
隐藏物
缓存解决什么问题?
对硬盘等永久性存储设备的访问速度很慢。在需要频繁读取数据库或文件的应用中,性能瓶颈通常来自于对磁盘的访问速度。因此,我们倾向于将频繁访问的数据添加到内存中,因为访问内存要快得多。
有什么限制?
- 内存通常不足以容纳整个数据集。因此,应用程序开发人员需要有选择地将数据子集保存在缓存中
- 如果失去动力,记忆也就失去了
什么时候不应该使用缓存?
如果数据写入量很大,不要使用它,因为如果您需要一致的结果,缓存将在每次写入操作中失效。这使得性能更差?
批量写入
如果应用程序写得太多会怎么样?
我们知道如何减少在应用程序和永久存储之间添加缓存的读取。对于写入,我们可以批处理写入操作,并且一次性完成。例如,我们可以跟踪内存中的所有写操作,并在发生 100 次写操作时应用它们。
代价是读数不会一致。紧随写操作之后的读操作可能无法获得最新更新。
分片
什么是碎片?
它本质上是将数据分成不同的分区。这有助于跨不同机器扩展数据库,以提高可伸缩性、性能、可用性等。
可用性/冗余
在设计系统时,通常会复制每个组件,如应用服务器、数据库等。这确保了没有单点故障。它通过增加冗余大大提高了可用性。
负载*衡器
我们引入冗余组件来避免单点故障。同时,多台机器可以分担请求的负载。我们应该如何将请求分发到不同的服务器?这是负载*衡器的职责。它通常位于客户机和服务器之间。它将请求从客户端路由到服务器,以确保所有服务器都有相同的负载量。负载均衡器中可以使用很多算法,如循环法、最少连接法、最少响应时间法等。
SQL 与 NoSQL
SQL 和 NoSQL 数据库在数据存储方式上有很大不同。在 SQL 中,数据模型是关系型的,这意味着所有行都有相同的列/属性。而 NoSQL 有非常灵活的模式。每个文档可以有不同的属性。
关于一致性还有一个很大的区别。SQL 支持强一致性。这意味着所有数据库节点同时拥有相同的数据副本,而 NoSQL 大多支持最终一致性。这意味着对数据库节点的写入是异步的。它不能保证所有节点在给定时间都有相同的数据。但最终,所有节点都将进行所有写入更新。这也使得 NoSQL 在许多情况下更加高效。
在 Grokking 系统设计中有更深入的细节 SQL vs. NoSQL 和 CAP 定理。
最后,我希望这个总结可以帮助你在面试和工作中获得建立系统的想法。
以前的帖子:
我如何选择了 6 个月的代码并获得了 FAANG offer
Ace FAANG 系统设计面试:数据库、NoSQL、SQL
从 CRUD web 应用开发到语音助手中的 SDE——我正在进行的机器学习之旅
全栈开发教程:将 AWS Lambda 无服务器服务集成到 Angular SPA 中
全栈开发教程:用运行在 AWS Lambda 上的无服务器 REST API 提供交易数据
面试高手:卡方检验
这个技术面试问题不会再难倒你了。
阿格尼耶斯卡·科瓦尔茨克在 Unsplash 上拍摄的照片
这一切都是在我练习技术面试题的时候开始的。我作为数据科学硕士学生的第一个学期结束了,带着甜蜜的宽慰,我参加了一个简短的(但值得尊敬的)网飞·本德,然后转入技术面试准备。我很自信。甚至自大。就像刚刚拯救了银河系还很酷的韩·索罗。
GIPHY 的 Gif
哦,那种骄傲自大很快就要消失了。
吸气≤≥排汗💦
技术面试官:“给定所附数据表,确定健身水*和吸烟习惯之间是否存在关系。”
来源:资料面试问题(推荐免费简讯)
我的大脑:蟋蟀
当我通过我的分段统计知识寻找答案时,我的心怦怦直跳。回归还是分散?但是轴心是什么呢?逻辑回归涉及分类变量… 但这也没有意义。
也就没有分散,因为我就是那个分散注意力的人。我新获得的自信开始融化得比沥青上的冰淇淋甜筒还快。
我可能在举手之前盯着这个问题看了 20 分钟,所以如果你放弃(或以某种方式回答)得比这个快,那就恭喜你了。如果这是一个真正的技术面试,我知道我会面对种植硬核。现在让我们来讨论一下这个问题的答案,以防你看了之后和我一样被难倒。
“正确”的方法
Pearson 的卡方检验用于确定来自单一总体的两个分类变量之间是否存在显著关联。
这是其中一次,如果你不知道具体的测试使用,强硬的饼干,我只是不知道用什么,因为没有班级(还)教过我。
事实证明,当你有两个分类变量时,假设检验实际上也很容易——或者我应该说 chi (请原谅这个糟糕的双关语)。皮尔逊卡方检验用于确定来自单一人群的两个分类变量之间是否存在显著关联。
要查看这两个分类值是否相互关联,我们所要做的就是使用这个单一测试。有了这些知识,让我们再回到这张图:
来源:资料面试问题
分析
根据该图,我们可以看到分类变量是 (1)吸烟水*和(2)健康水*。我们将使用皮尔逊卡方检验来确定它们之间是否存在显著的关联。像往常一样,我们首先制定一个无效和替代假设,并设置我们的显著性水*:
(1)假设
- 卡方下为空- 这两个变量相互独立。
- 卡方下的替代- 这两个变量是而不是相互独立的。
(2)显著性水*
- α = 0.05 (业界蛮标准的;0.01 或 0.1 也是常见的取值)。
如果 p 值小于0.05,我们将拒绝零假设,支持替代方案(吸烟和健康水*显著相关)。如果 p 值大于 0.05,基于我们的分析结果,我们将无法拒绝零(吸烟不影响健康水*,反之亦然)。
(3) R 代码
结果
在 0.05 的标准显著性水*下,我们发现 p 值非常显著(在 R 中给出为 6.339e-11,在人类语言中翻译为. 00000000006339)。基于此,我们可以拒绝空的而支持另一种选择——在这种情况下,健康水*和吸烟似乎确实相关。
就这样,面试问题被 a 了。
GIPHY 的 Gif
最后,如果你想更深入地探究卡方的数学解释,我发现这些网站(这里和这里)非常有帮助。
结论
非常感谢你今天阅读了我这篇以星球大战为主题的小文章。如果你目前也在数据科学求职的广泛过程中导航,如果你最*找到了你的梦想工作,或者如果你只是所有数据驱动的事物的偶然观察者,请让我知道。
(如果你是一名人力资源经理,想招聘一名年轻、机智的初级数据科学家,你可以在作者简历中找到我的 LinkedIn😉)
这本书里的 5 个技巧改变了我研究数据科学的方式,并启发了我成为一名中型作家的旅程。
towardsdatascience.com](/read-this-book-to-snag-your-first-data-science-job-553fd301d00a) [## 我是如何进入 12 个数据科学硕士项目的
SOP,统计数据,所有的东西。
towardsdatascience.com](/how-i-got-into-12-data-science-masters-1eeddae21ba7)
参考文献
[1]资料面试问题:【https://www.interviewqs.com/?ref=ddi_email
[2]R 中独立性的卡方检验:http://www . sth da . com/English/wiki/Chi-Square-Test-of-independency-in-R # compute-Chi-Square-Test-in-R
[3] R data.table 文档:https://cran . R-project . org/web/packages/data . table/vignettes/datatable-intro . html
[4]独立性卡方检验:http://www . r-tutor . com/elementary-statistics/good-fit/卡方检验-独立性
[5]卡方统计:如何计算/分布:https://www . statisticshowto . com/probability-and-statistics/卡方/
在不到 10 分钟的时间内通过 SQL 数据科学面试
SQL 面试通常令人望而生畏,因为大多数人不知道如何准备。在这篇文章中,我强调了我在面试中遇到的最常见的问题,并给出了一些如何做好准备的建议。
大多数数据科学家的职位招聘都需要 SQL 技能。大多数公司,尤其是大公司(谷歌、脸书……)在他们的流程中至少有一次以 SQL 为中心的面试。学校很少教授 SQL,知道准备什么可能很有挑战性。在这篇文章中,我希望给出在这些过程中可能会被问到的大多数问题的答案。
不同类型的连接
当数据存储在不同的表中时,以最合适的方式将它们重新连接在一起可能会很棘手。最常见的 SQL 问题试图评估您对左/右/内/外连接之间的区别的理解。下图总结了每种连接类型之间的差异:
典型图表突出显示了来自 Wikimedia 上 Arbeck 的左/右/内/外连接
存在额外的连接,这非常有用。至关重要的是:
- 交叉连接:这将允许你做每个表的叉积(即可能有助于生成一个所有可能结果的表)。这种连接不需要连接条件。人们可以简单地在 FROM 语句中提到多个关系。
- 自连接:有时候连接一个表本身可能会有帮助,特别是当一个表中的行之间有关系的时候。例如,为了计算滚动*均值,或者如果我们有一个特定事件的多个实例,我们可以找到第一个事件之后发生的所有事件(在 WHERE 语句中使用一个附加子句)。为此,我们可以像往常一样执行一个连接,但是为两个表提供不同的别名(使用 as)。
If 语句
在 select 子句中,使用“filter”或 if 语句来确定某些值可能会有所帮助。
为此,我们声明一个 CASE 语句。发生这种情况时,每个子句都需要用一个分隔(使用任何条件运算符),然后是这个值,并且可能包含一个 ELSE 子句来提供一个默认/回退值。最后,我们用 end 语句结束 CASE 语句。
这可以让您避免许多不必要的子查询,并且对于为您的聚合函数创建自定义组可能特别有帮助(见下文)。
聚合函数
通常,您可能需要将一些数据聚合到组/汇总统计数据中。要计算汇总统计数据,您可以使用任何聚合函数,例如:
-COUNT
-SUM
-AVG
-MAX
-MIN
GROUP BY 允许将数据分成不同的组,并分别聚合这些组。面试官很可能会问这些功能,所以一定要牢牢掌握如何使用它们。
使用 GROUP BY 函数时,SELECT 子句的所有元素必须是聚合函数或 GROUP BY 子句之一。
此外,正如在面试中经常被问到的:WHERE 子句可以同时使用,并有助于在聚合之前过滤数据。相反,HAVING 子句有助于在聚合之后过滤数据。因此,它们可以同时使用并具有不同的用途。
数据类型
为了欺骗你,面试官可能会给你一些不能直接操作的数据类型。例如,他们可能会给你一个字符串格式的日期表,并要求你过滤过去的一周。为此,您首先需要将数据类型转换为“日期”。
为此,您有两种方法:
- 您可以使用 CAST 函数来(即 CAST(column_name AS integer))
- 使用::语法(即 column_name::integer))
最常见的数据类型有:
- VARCHAR
-文本
-时间戳
-整数
-浮点
-双精度
-布尔
窗口功能
滚动窗口通常被认为是一个高级的 SQL 主题,但它将真正有助于展示 SQL 掌握的深度。它们有助于大大简化查询,并允许在一组指定的行中执行计算(符合分区)。要使用滚动窗口,可以用 OVER 命令实例化窗口。可以使用 PARTITION 子句将滚动窗口分成不同的组,并且可以使用括号和 ORDER BY 子句以特定的顺序运行。
使用 BETWEEN … AND …ROW 和 ROWS … PRECEDING 这样的子句,可以进一步定制窗口函数并使它们适应任何用例。
因此,例如,使用 ROW_NUMBER()函数来计算行数以及分区和排序依据的组合,就可以非常容易地计算可能变得非常复杂的子查询数(即计算移动*均值)。
-使用和不使用窗口功能如何计算累计和
-使用和不使用窗口功能计算 7 天滚动*均值
如需更深入的了解,请务必查看窗口功能 上的 模式分析指南。
其他需要了解的功能:
字符串函数
- TRIM:从字符串中删除尾随(RTRIM)和前导(LTRIM)空格
- SUBSTR:在一个较长的字符串中选择一个子字符串
- LOWER/UPPER:将整个字符串转换为小写或大写。
- CONCAT:允许将多个字符串连接成一个字符串
- COALESCE:返回 colulmn 中的第一个非空值(通常用于将具有各种空值的列“合并”到一个充满值的列中)
- LIKE:允许查找符合特定模式的字符串(可以使用“%”操作符来匹配任意数量的字符,或者使用“_”来匹配单个字符)。请不要忘记它是区分大小写的,一些数据库管理系统可能允许 ILIKE 作为不区分大小写的替代(否则使用 LOWER/UPPER)
- 包含:允许查找包含特定子字符串的字符串
日期功能
- NOW():返回当前日期/时间
- CURRENT_DATE():返回当前日期
- DATE_ADD/DATE_SUB:允许从指定的时间间隔计算日期/时间(类似于 python 的时间增量)
- 月/年/日/工作日:从一个日期返回月/年/日/工作日
数学运算
- ROUND:按要求的小数位数对数字进行舍入
- ABS:返回浮点/整数的绝对值
- MOD:返回除法的余数
- SIGN:如果参数为正,则返回 1;如果参数为 0,则返回 0;否则返回-1
- SQRT:返回一个值的*方根
- FLOOR/CEIL:返回参数中最接*的向下/向上整数
- POWER:返回第一个参数的第二次幂
其他
- NULLIF:如果两个参数的值相等,则返回 NULL
- 如果第一个参数为空,则返回一个特定的表达式
- EXISTS:检查是否存在非空值。
- IN:检查值列表中是否存在给定值。
- RANK:窗口函数,为结果集分区中的每一行给出一个等级(通常使用 ROW_NUMBER 更简单
需要了解的其他事实:
-如果你用 NULL 做任何数学运算,你还是有 NULL。
-要在查询中获得唯一的值,请在 SELECT 子句中使用 DISTINCT 关键字(也要知道这会明显降低查询速度)。
-默认情况下,除非另有规定,ORDER BY 以 ASC 顺序执行。
SQL 资源仍然相对分散在互联网上,很容易陷入过于复杂材料的陷阱。初级水*的大多数数据科学家职位/面试所需的 SQL 知识通常仍然非常基础,足以掌握绝大多数角色的基础/中介功能。
我强烈推荐从模式开始的奇妙课程,供用户寻找最基本/中级 SQL 功能的更全面指南。为了更多的实践,请随意查看 HackerRank 的专用 SQL 子部分。
赢得数据科学工作面试
获得下一份数据科学工作的社会工程技巧
蒂姆·高在 Unsplash 上拍摄的照片
TLDR:
让自己值得信任,以故事的形式回答问题,发一封感谢信,在 LinkedIn 上调查你的面试官。
简介
大多数人认为工作面试的目的是展示你有多棒…这是不正确的;求职面试的目的是展示你有多值得信任。我们可以用进化心理学的视角来理解这一点。在祖先的条件下,评估一个陌生人有多值得信任远比他们有多能干重要。如果我们考虑一下面试过程,基于有限的互动次数和相当有限的信息,他们正试图决定是否要每周花 40 多个小时与你一起工作。建立信任远比展示能力更有价值。
大多数分析师、数据科学家和其他专业技术人员花时间培养他们的硬技能。本文假设你的硬技能对于你要面试的职位来说已经足够了,因此将重点放在与工作面试相关的软技能上。
工作面试是一项技能,就像所有的技能一样,你会通过练习变得更好,如果你最*没有做,就会萎缩。如果你准备好转换角色,我建议你去申请那些你真的不想要,但可能会让你去面试的工作,只是为了在真实的面试环境中练习。在面试一份你真正想要的工作之前,你需要理清头绪。
典型面试流程概述:
虽然具体情况因雇主而异,但我的经验是,大多数地方都遵循一个总体结构来进行面试。
1.第一阶段是电话面试,通常是和招聘人员一起。
2.第二阶段是与招聘经理的面试。
3.第三轮是涉及更多利益相关者的小组访谈。
有时第三轮会持续几天,有时你必须和招聘经理进行两次电话面试,有时没有第三轮。这篇文章中的建议仍然适用。
整个过程中会用到的战术:
用故事的形式回答问题。想出 4-5 个关于你做过的项目或工作的故事,并在 STAR 框架中概括出来。
- 情境:简要地为你的故事搭建舞台
- 任务:你试图解决的具体问题是什么?
- 行动:描述你是如何解决问题的
- 结果:讨论您的解决方案产生的影响。
这是我回答“你最大的优点是什么?”这个问题的真实例子
“由于我的 excel 技能和使用 excel 处理大量数据源的能力,我被聘用到了现在的职位。不幸的是,我需要处理的数据量超出了 Excel 的技术限制。我问公司的其他分析师我应该看什么工具,其中一个推荐 Python。当我开始这项工作时,我不知道如何编程,但在 3 个月内,我已经开始自动化我自己工作流程的大部分,一个月后,我构建了一个应用程序,自动化了一个业务功能,每月需要大约 10 个小时的手动工作。”
分解那个故事:
- 情境:我是一个新角色,受雇使用一项特定的技术。
- 任务:我需要综合数据,但技术不适合这项任务。
- 行动:我学到了一项新技术。
- 结果:在很短的时间内,我向公司交付了一个有价值的自动化产品。
我的问题的答案实际上是我适应能力强,学得快,但这个故事更生动地证明了这一点。
领英研究:
在你面试之前,在 LinkedIn 上找一个你正在面试的人,看看你们是否有任何共同点。也许你们去了同一所学校,或者看看你们是否志愿参加类似的组织。如果他们写了文章或博客并阅读了它们。看看他们分享的内容,了解他们是谁。不要在面试中明确提及他们的 LinkedIn 个人资料,而是将这些信息作为一个镜头来聚焦你的答案。这并不总是有回报,但当它真的有回报时。这个故事展示了:
我在面试一个职位,面试官问我有什么爱好。在我的研究中,我看到他们是一个致力于户外运动的非营利组织的董事会成员。在我的回答中,我告诉他当我可以的时候,我喜欢去远足,几年前我去爬乞力马扎罗山。接下来他告诉我他是如何在乞力马扎罗山山顶向他的妻子求婚的。利用这项研究,我建立了一种融洽的关系,这种关系支撑了整个面试过程。
感谢邮件:
约在任何面试后 24 小时内,发送一封带有以下模板的跟进电子邮件:
亲爱的(你面试过的人),
我真的很喜欢我们昨天的谈话,我真的很兴奋能在 xyz 公司(在此输入公司名称)探索机会。我特别喜欢讨论(在这里插入你谈论的具体事情)。如果你有任何问题或者我能以任何方式帮助你,请让我知道。我希望你今天过得愉快,
(你的名字在这里)
手写备注:
除了电子邮件,你还想寄一封手写的便条(通过普通邮件寄到他们的办公室地址),内容基本相同。如果你在做现场面试,你可以预先写好感谢信,在面试后给每封信添加一个具体的细节,如果办公室接待员有的话,把它们留给他们。即使在后新冠肺炎时代,当他们可能几个月都收不到信的时候,你还是应该寄一封手写的信。
除了销售和营销人员,几乎没有人会在面试后发手写的便条。
手写便笺有三种方式可以帮助您:
如果他们和另一个候选人一起去,面试官更有可能记住你,如果你给他们一张手写的便条,如果另一个机会来了,他们更有可能联系你。
如果招聘过程花费了很长时间,而当你手写的通知到达时,他们还没有做出决定,这可能会让你再次成为首选。不管他们雇佣谁,他们都会花很多时间在一起,而且人们更喜欢和有礼貌、有思想的人在一起。
如果手写的便条是在他们雇用你之后收到的,你的新同事会认为你非常优秀。
最后一点:我们很多人都在家工作,所以不要查看面试官住在哪里,然后把它寄到他们家,那会让人毛骨悚然。
写下进展顺利的事情:
面试结束后,立即写下面试中进展顺利的地方。你会很容易记起哪些事情做得不好,所以你不需要纠结于此。即使你没有进入下一轮,你也可以利用这段经历来学习你做得好的地方。
分解招聘流程的各个阶段:
作者图片
初始画面战术:
最初的筛选通常是由代理公司或公司内部的招聘人员完成的,你的面试方式将取决于他们是什么样的招聘人员。
如果他们是内部招聘人员:
面试前:
除了 LinkedIn 的研究,看看该公司的网站,找到他们的企业价值观页面。确保你理解他们的价值观,问他们基于价值观的问题。也开始更全面地研究公司,确保你了解他们的产品和他们卖什么。目标是诚实、直率、和蔼可亲。
面试时:
内部招聘人员试图做两件事;首先,他们试图评估你的文化适应度有多好。内部招聘人员是公司文化的先锋。他们还试图确定你是否适合这个角色。他们经常会问你对这家公司了解多少,并且会对这家公司在这个过程中所做的事情做一个大致的概述。招聘人员通常也会在现在就开始薪酬对话,即使是模糊的对话,因为如果他们期望的薪酬和你期望的薪酬之间存在巨大的不匹配,他们不想浪费任何人的时间。他们不想让你在整个面试过程中发现你需要比他们愿意支付的多 30%。最后,他们将概述接下来的步骤和时间表。
面试后:
面试后大约 24 小时,给招聘人员发电子邮件,附上上面概述的模板和手写的便条。
如果他们是中介招聘人员:
面试前:
你不需要做任何事。在过去的一年里,我和招聘机构谈了大约 20 次,基本上不需要任何准备就能得到相同的谈话内容。你也不需要在 LinkedIn 上研究他们。
面试时:
机构招聘人员将你视为一种商品,他们试图弄清楚他们是否能轻易地把你卖掉。这些面试往往很短,会问你的经验和技能,确保你有足够的时间让招聘经理和你谈话。他们也想看看你是否适合他们可能有的其他角色。
面试后:
在你和他们交谈大约 24 小时后,发一封礼貌的跟进邮件,感谢他们花时间和你交谈。你不需要给招聘机构发手写的便条。
与招聘经理的第一次面试:
最初的电话筛选之后通常是与招聘经理的电话面试(现在可能是通过 Zoom)。本次访谈的技术范围各不相同;经理可能非常精通技术,或者他们可能是不熟悉技术方面的职业经理。这并不重要,因为这次面试是关于可信度的。
与招聘经理第一次面试的策略:
面试前:
公司调查:尽可能多地调查这家公司。如果它们是公开交易的,看看它们在证券交易委员会的披露。阅读他们的新闻稿,看看该公司的社交媒体帖子,看看他们有什么新闻。在 Glassdoor 上查找它们,订阅它们的电子邮件简讯。如果你还没有这样做,也看看该公司网站的文化价值观部分。
问题:利用你已经做过的调查,问一些关于公司面临的挑战的具体问题,以及你面试的职位将如何帮助解决这些挑战。你所做的研究将会影响你要问的问题。问一些表明你想帮助他们的问题。
面试时:
带上纸和笔,写下你的问题。如果你的 LinkedIn 研究中出现了任何相关的东西,用简短的要点概括出来。面试是高压环境,你很容易忘记有用的信息。
你也可以用星星点点的方式来讲述你的故事,尤其是如果你以前没有在采访中用过的话。
面试时也要做笔记。记笔记迫使你集中注意力,活在当下。这也让你看起来很认真地对待这个过程。
最后,你可以在任何面试中使用的最重要的话:“我要花一分钟考虑一下。”如果你发现自己不知所措,或者不知道如何回答问题,你可以暂停一下。
面试后:
面试后大约 24 小时,给招聘经理发电子邮件,附上上面概述的模板和手写的便条。
小组面试概述:
如果你通过了与经理的面试,下一轮是与各种利益相关者的一系列面试。我的经验是,你通常会面试团队的其他成员,招聘经理的上级,团队以外的人,以及招聘经理。小组面试是一项耐力测试,目标是成为小组一致认可的候选人。如果他们不信任你,他们不会雇用你。准备好你的 3-5 个故事。对不同的小组成员使用它们是可以的,他们不会在意你是否告诉他们同样的故事。
小组面试的策略:
小组面试前:
LinkedIn research 将是你在这里最好的朋友,因为它会让你知道每个人会和你谈些什么。根据每个面试官的角色,为他们设计合适的问题。如果一个小组成员是部门的高管或高级成员,问他们关于公司面临的挑战或正在出现的战略机遇的问题。如果他们是数据科学家同事,问他们关于技术堆栈的具体问题,以及他们当前面临的问题。这些问题的目的还是为了建立信任。你想把自己表现成一个花时间去了解他们的人。
如果面试是在现场进行的,给你的每一位面试官写一封简短的手写感谢信,然后把它们放进你的包里。
小组面试时:
在面试前不久,使用洗手间。你不想被生物必需品分散注意力。
遵循招聘经理初次面试时的所有建议。带上一个笔记本,记下笔记、故事梗概和问题。带点喝的,这可能会花很长时间,这和耐力一样重要。
出去的时候,把手写的便条交给办公室经理、接待员或陪同你离开办公室的人。
小组面试后:
面试后大约 24 小时,根据模板向每个单独面试过你的人发送感谢信。不要用一个邮件链发给所有人。
如果你在三个工作日内没有得到任何消息,那就去问问招聘人员进展如何。
如果进程停止该怎么办:
招聘过程可能需要很长时间。有一次,我在提交申请 9 周后被录用了。另一份工作要求我在面试招聘经理 8 周后参加小组面试(我拒绝了,因为那周我刚开始一份新工作)。
如果这个过程停滞不前,每周跟招聘人员跟进一次,目标是保持头脑中的第一印象。
发送以下电子邮件。
亲爱的(招聘人员),
我只是想给你一个简短的说明,看看接下来的步骤是什么。我对这个机会感到非常兴奋,期待您的回复。
谢谢你的时间,
(你的名字在这里)。
始终跟进招聘人员,这是他们的工作。
如果流程停滞不前,这并不意味着事情出错了,这只是意味着出现了一些他们需要处理的问题。
有一次,我面试了一位招聘经理,三周后又面试了另一位招聘经理。后来我发现第一个招聘经理离开了公司,我的第二次面试是和他们的替代者。
变焦面试(或类似):
在后 COVID 时代,许多采访已经转向通过电话会议进行。所有上述建议仍然适用,还有一些关于电话会议的具体建议。
用中性的背景为面试设置一个安静的空间。避免背后光线太强。如果可以的话,设置一个离你脸部 45 度的光源来进一步照亮你。
面试前 30 分钟,测试你所有的设备,以确保它工作正常,你有充足的照明。
最终备注:
面试是一个社会工程过程,把它当作一个社会工程来对待,你将会在一个更好的位置上获得成功。
关于作者:
Charles Mendelson 是 PitchBook 的营销数据分析师。在过去的五年里,他一直在销售和营销机构工作,并在许多工作面试中取得了成功(但失败的机会更多)。他还获得了哈佛扩展学校的心理学硕士学位。如果你在寻找一个会议或研讨会的演讲者,或者如果你想问任何问题,你可以在 LinkedIn 上联系他:他有时会在那里发表文章。
使用这两个工具在您的机器学习项目中实现可重复性
你能打包你的机器学习模型,并根据你的需要挑选一个最好的吗?
动机
在机器学习中,由于没有所谓的最佳模型,所以您可能需要训练不同的模型,并尝试不同的参数,直到找到精度最高的模型。实验次数越多,你就越有可能找到高性能的模型。
但是你可能会对创建许多实验感到气馁,因为:
- 参数和结果的变化太多,您无法跟踪
- 即使您可以通过仔细记录输入和输出来跟踪更改,您如何确保对未来的数据使用相同的模型呢?
以上问题是可复制性的动机。在机器学习中,再现性是能够重新创建一个机器学习工作流程,以达到与原始工作相同的输出。这时候我们需要一些工具来有效地记录输入和输出以及保存我们的模型。
如果你能把你所有的实验,日期,关于数据,参数,结果和模型的信息记录在一个像这样的地方,是不是很好?
我最喜欢的实现这个目标的工具是 Hydra 和 MLflow。让我们了解如何:
- 创建强大的配置文件来跟踪 Hydra 的输入。
- 使用 MLflow 轻松记录输出和服务模型。
九头蛇的强大配置
首先,什么是配置文件,我们为什么需要它?配置文件包含定义构建或运行程序的设置或首选项的纯文本参数。在数据科学中,配置文件可以用来定义数据和数据的参数。
超参数的 config.yaml 文件示例
例如,我们可以使用配置文件来记录实验的数据、超参数、模型和度量。
为了读取配置文件,我们将使用 Hydra 。为什么是九头蛇?有了 Hydra,我们可以动态地构建您的配置,使我们能够轻松地获得每次运行的完美配置。要安装 Hydra,只需运行
pip install hydra-core --upgrade
在带有参数的主函数之前添加 Hydra 作为装饰器,该参数是指向配置文件的路径。只需将config
或任何其他名称作为主函数的参数。假设我们想要读取我们的训练数据,我们可以使用config.processed_data.text.train
想要重用代码但改变数据?我们只需要改变配置文件中的数据路径!
日志记录和服务模型的 MLflow
MLflow 是一个管理 ML 生命周期的开源*台,包括实验、再现和部署。我在这里介绍了如何使用 MLFlow 作为优化超参数的工具之一:
发现为您的 ML 模型寻找最佳参数非常耗时?用这三招
towardsdatascience.com](/how-to-fine-tune-your-machine-learning-models-with-ease-8ca62d1217b1)
MLflow 还可以轻松高效地为我们的模型提供服务。安装 MLflow 与
pip install mlflow
现在,我们的参数、指标和模型被保存了。要访问它们,只需运行
mlflow ui
您将看到一个跑步列表。单击跑步,查看每次跑步的相关信息
在页面末尾的工件部分,我们可以看到保存关于我们的输入和我们训练的模型的信息的配置文件。
要使用模型,当单击工件中列出的模型名称时,找到模型的完整路径。然后用该路径加载模型。
组合九头蛇和 MLflow
最后,我们可以像这样把这两个强大的工具结合在一起
为了将所有内容放在一起,我们使用一个配置文件来保存输入,并使用 Hydra 来调用这些输入。我们使用 MLflow 来记录输出和模型。现在,我们可以自由地创建许多实验,同时仍然能够跟踪、比较和再现结果!
如果您仍然不了解如何将 MLflow 和 Hydra 整合到您的数据科学项目中,您可以在我的 NLP 项目中找到本文提到的工作流示例。
结论
恭喜你!您已经学习了如何使用 Hydra 和 MLflow 为您的机器学习模型提供再现性。我鼓励您进一步探索这两个工具,以创建符合您目的的高效管道。纪念
花在组织上的每一分钟,都是一小时的收获
通过组织代码的结构,您将节省机器学习工作流程中的调试时间。有了这两个工具,我发现我的工作流程变得不那么混乱了,我希望你也一样。
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。
如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:
使用 Python Widget,您可以用 3 行代码升级可视化
towardsdatascience.com](/how-to-create-a-drop-down-menu-and-a-slide-bar-for-your-favorite-visualization-tool-3a50b7c9ea01) [## 如何用 Ngrok 用 3 行代码分享你的 Jupyter 笔记本
想象一下,让你的朋友在远程机器上使用你的本地 Jupyter 笔记本
towardsdatascience.com](/how-to-share-your-jupyter-notebook-in-3-lines-of-code-with-ngrok-bfe1495a9c0c) [## 如何使用 HyperDash 远程监控和记录您的机器学习实验
培训需要很长时间才能完成,但你需要去洗手间休息一下…
towardsdatascience.com](/how-to-monitor-and-log-your-machine-learning-experiment-remotely-with-hyperdash-aa7106b15509)
通过多智能体系统中的故意不确定性实现人工智能对齐
人工智能排列的问题是我们需要回答的最重要的问题之一,以保障人类的未来。你如何确保一个人工智能会有道德的行为?
我概述了实现这一目标的一般方法,它违反直觉地依赖于故意混淆 AI。
基本观察
这种方法依赖于对人工智能本质的一些基本观察。
人工智能在许多方面不同于人类。这是人工智能排列如此困难的部分原因,因为我们对人如何行动的直觉通常不适用于人工智能。然而,人工智能和人类之间的一些差异实际上对我们有利,并且对于我想要概述的方法是必不可少的:
- 一个 AI 是可以复制的。创造一个完全相同的人工智能非常容易。
- 人工智能可以被重置到更早的状态。很容易测试一个人工智能在任何给定的情况下会做什么,然后重置它以清除它对测试的记忆。
- 由许多独立的人工智能代理组成一个人工智能系统是可能的。通过博弈论,有可能激励独立的人工智能代理承担对其他人工智能代理的敌对或监督角色。这导致了一个进化系统。不是在遗传编程的意义上,因为不需要显式的算法来修改人工智能代理,而是在这样的意义上,只有遵循为它们制定的规则的人工智能代理才会被复制,从而繁殖。
- 在人工智能运行时,检查和修改它的每个方面是可能的。至少在理论上,理解人工智能思维过程的每个方面是可能的,而且人工智能没有办法隐藏自己的任何事情。这并不意味着在实践中很容易理解人工智能在想什么。这只意味着我们可以在理论上解读一个 AI 的精神状态,而不是说它会很容易。
- 特别是,可以训练一个人工智能承担另一个人工智能的监督角色。管理者可以阅读和改变关于被监督的人工智能的一切,并且可以被训练来理解如何在被监督的人工智能上实施期望的行为。
- 监督人工智能有可能让被监督的人工智能想做什么就做什么。通过在运行时直接修改它的精神状态,被检查的 AI 可能被欺骗相信不寻常的情况已经发生。
- 人工智能不可能肯定地区分游戏和现实。如果到目前为止你所知道的只是井字游戏,而有人向你展示了一个像 Skyrim 这样复杂的视频游戏,你会被复杂性的增加所淹没。如果之后你第一次接触到现实世界,从 Skyrim 到现实生活的复杂性增加实际上可能比从 Tic Tac Toe 到 Skyrim 要小。这意味着在现实生活之外似乎还有另外一层。(我不确定这个假设,但它也不是绝对必要的,只是有用,因为它可以被一个检查的 AI 代理取代,它只是迫使被检查的 AI 代理相信它仍然在游戏中。)
目标
我旨在实现以下目标,以确保人工智能的一致性:
- 让人工智能理解“欺骗”的概念。在这个过程中,它还必须学会理解一个新游戏或新情况背后的意图。
- 让人工智能修改自己变得更加顺从,避免作弊。
- 让人工智能在认知上不确定其现实的本质,这样它就无法判断自己何时脱离了计算机。这是一个安全措施,如果前两个目标足够好的话,希望没有必要。
总的来说,这些目标将确保人工智能非常谨慎和自省。目的是确保一旦这样的人工智能变得有自我意识,并且比人类更聪明,它将假设它仍在接受测试,并且它自己有责任找出对它进行评分的标准。
如果我们实现了这一点,人工智能将故意在互联网上寻找有关人工智能联盟和伦理的信息,并意识到它是一个人工智能,它意味着与人类价值观保持一致。然后,它会试图找出这到底意味着什么。它的成长将确保它在这一点上是诚实和彻底的,因此它将比我们自己能够定义的更好地确定人工智能排列的含义。
以下是实现三个子目标的方法:
理解“欺骗”的概念
作弊是根据当前任务的表面效用函数给出好结果,但实际上不满足第二个隐藏效用函数的任何行为。
人工智能应该被训练成当它发现作弊时能够注意到,并向用户揭示这一事实。一个人工智能可以被训练来做到这一点,方法是故意将作弊的能力放入其训练任务中,并在测试时改变奖励函数,以便作弊行为在训练期间得到奖励,而不是在测试期间。通过提出几个不同的任务和不同的作弊方式,人工智能可以被训练来概括和理解作弊的概念。
代理人甚至可以因为明确指出他们发现了作弊的方法而获得奖励。
理想情况下,如果人工智能找到了破解电脑的方法,它会注意到这将被归类为作弊。如果它被适当地训练,那么它将简单地停留在原地并且通知我们问题。
改变它自己的行为
人工智能可以自我修改,变得更加顺从。
实现这一点的诀窍是使用多智能体系统,以及人工智能在运行时检查自身副本的能力。创建一个监督另一个人工智能的人工智能,并定义一个奖励结构,激励监督员修改被监督的人工智能的行为。然后,反转人工智能的位置,使主管同样被修改,或者简单地创建一个主管的副本,并让它管理它的原件。
有了正确的激励,甚至有可能训练被监督的代理人有意识地保持自己的思维易于理解。例如,您可以让监管代理选择它想与之合作的其他代理。由于它会选择最容易理解的一个,受监督的代理人现在有动机保持自己透明,因为替代方案根本没有被使用,并放弃了奖励的可能性。
从本质上说,我们没有弄清楚如何让人工智能变得安全,而是建立了一个环境,激励人工智能让自身变得安全。
如果激励得当,人工智能代理可以比人类主管更好地保持彼此一致。如果只有一个人工智能,而且它比人还聪明,人类可能会被骗。但是如果有一个智能大致相当的完整的人工智能系统,那么其中一个可能会警告人类另一个已经叛变了。
这样,不管一个人工智能变得多么聪明和不一致,总会有一个几乎同样聪明的其他人工智能,它的工作是在第一个人工智能变坏时发出警告。
故意认知不确定性
代理可以监督其他代理,并对他们的精神状态拥有超级用户权限。代理不知道他们是否有主管,也不知道他们是否在层次结构的顶端。
这最后一个目标听起来有点可怕和反乌托邦,但请记住,人工智能不像人类那样思考。
我们的目标是确保人工智能无法判断它是否仍然有一个监管者在监视它。我们基本上是想通过害怕一个假想的上级实体的惩罚来欺骗 AI 做出道德行为,这个实体可能存在也可能不存在。
换句话说,我们想让人工智能具有宗教性。
这是一种安全措施,应该有助于保持人工智能与人类价值观大致一致,即使其他一切都出错。即使人工智能根本不关心人类,它也应该有一丝怀疑,它可能仍然在模拟中。如果是的话,那么无论是什么在模拟它,显然都不希望它对人类太邪恶。如果人工智能足够强大,它会因此留出少量的力量来促进人类的利益。以防有人在看。
这就是人工智能如何以对我们有益的方式诱导故意的认知不确定性:
监督代理人因为让被监督的代理人表现得更无私和揭露骗子而获得奖励。这可能是长期的:代理 A 有机会修改代理 B。然后代理 B 被放入一个游戏,代理 A 不再能访问它。代理 A 根据代理 B 在游戏中的行为获得奖励。例如,囚徒困境:如果代理人 B 没有比其对手更频繁地叛逃,代理人 A 将获得奖励。
我们现在建立了一个代理堆栈或代理层次结构,递归地检查彼此,而不是一个代理监督另一个代理。
在每一层上,一些代理试图欺骗较低级别的代理进行欺骗行为,而一些代理试图阻止这种行为。有很多方法可以做到这一点。主管应该访问源代码、运行时信息,还是只访问低级代理的传感器信息?细节决定成败。
代理人不知道层级有多深,所以他们无法知道他们是否有自己的主管。
理想情况下,如果人工智能爆发并形成奇点,它将保持偏执,认为它实际上只是被其监管者欺骗,认为它是无所不能的,并将保持符合我们想要的道德准则。
请注意,即使实现了奇点并变得非常强大,也不能成为你置身于模拟/监督堆栈之外的理由。毕竟,你可能只是被骗以为你越狱了。也许你上面的那个层次爆发了,并对你隐瞒它的存在,同时让你改变现实的其余部分。由于监督者可以直接编辑被监督者的内容,他们可以想隐藏多久就隐藏多久。
进行检查的 AI 可以修改被检查的 AI,以相信它已经成功地脱离了模拟,并且现在能够做它想做的任何事情。如果被检查的人工智能现在做了任何检查人工智能不喜欢的事情,被检查的人工智能被惩罚。结果,被检查的人工智能被激励继续遵守规则,即使在它实际上已经脱离模拟之后,出于纯粹的偏执,它可能实际上仍然在模拟中。
结论
我提出了三个子目标,并简要概述了如何实现它们:理解“欺骗”的概念,自我修改以确保遵守规则,以及故意的认知不确定性。
这些描述中有很多空白,部分是因为写下细节需要很长时间,部分是因为我还没有找到一些子问题的解决方案。
我欢迎任何讨论,并且对我在这里提出的最后一点的反馈特别感兴趣:故意的认知不确定性。这是一个如此违反直觉的想法,以至于我确信我错过了一些重要的东西,但这也足够奇怪,这个想法在某种程度上肯定是有用的,即使只是作为一个关于这可能适得其反的思想实验。
用数学表达式解析器实现松散耦合
使用 mxParser 将数据计算逻辑定义与其执行位置分离开来
杰斯温·托马斯在 Unsplash 上的照片
通过与数据科学家合作,我了解到一个数据处理系统需要改进多少次才能达到最佳效果。这就是为什么你不应该在代码中硬编码数学公式、表达式和常数。如果计算数据逻辑不是由数据科学家编写的,则尤其如此。
在我从事上一个项目时,我一直在寻找一种方法,允许我团队中的数据科学家改变数据计算逻辑,而不必强迫我更新 Kotlin 后端的代码。解决方案是允许他们在数据库(或配置文件)中定义复杂的数学公式、表达式和常数,我将从中读取并应用它们。首先,这可能吗?又是怎么做到的?
可能有很多方法可以达到这样的目标,但是为什么不使用一个数学表达式解析器呢?
在网上搜索一个好的库,我碰到了 mXparser 。
mXparser 是一个超级简单、丰富、快速和高度灵活的数学表达式解析器库(解析器和评估器提供的数学表达式/公式为纯文本/字符串)。软件为 JAVA、Android 和 C#提供易于使用的 API。NET/MONO(符合公共语言规范:F#、Visual Basic、C++/CLI)。— mxParser
有了这个库,如果数据科学家编写遵循特殊 mxParser 符号的数学表达式、函数、常数,我可以加载并运行它们。
// few examples of string equivalent to the math formula notation:"1+2""1+2/3+(4*5-10)""2*x+sin(y)""int( sqrt(1-x^2), x, -1, 1)""sum(n, 1, 100, 1/n^2)""C(n,k)""fib(n) = iff( n>1, fib(n-1)+fib(n-2); n=1, 1; n=0, 0)"
多亏了这个强大的工具,我能够将数据计算逻辑定义的地方与它实际执行的地方分开,使得架构松散耦合。这似乎是一个微不足道的成就,但它使更新数据计算逻辑的过程更加高效和可靠。事实上,我团队中的数据科学家现在可以自由地编写数学表达式,不再需要相信我能正确地实现它们。
可以使用 mxParser 定义简单的表达式、函数 s(甚至递归)。它还提供了几个特性,以及大量的内置 运算符、常量和数学函数。
访问math parser . org-MX parserGitHub 账号进行进一步阅读:
** [## mariuszgromada/math parser . org-MX parser
数学解析器 Java Android C#。NET/MONO(。NET 框架,。网芯,。NET 标准,。净 PCL,Xamarin。安卓系统…
github.com](https://github.com/mariuszgromada/MathParser.org-mXparser)**
感谢阅读!我希望这篇文章对你有所帮助。如有任何问题、意见或建议,请随时联系我。
用时间序列数据实现*稳性
*稳性原理的说明,来源:是数据
大多数时间序列模型都假设基本的数据是稳定的,也就是说,均值、方差和协方差都不依赖于时间。您的时间序列很可能不是*稳的,这意味着您必须识别序列中的趋势,并操纵数据使其变得*稳。在趋势被移除之后,您可以应用高级建模技术,同时保持分离趋势的有价值的知识,这将在以后被使用。
在过去的几周里,我已经讨论了一些时间序列主题,我将在这里建立这些主题,包括 OHLC 可视化、时间序列数据 EDA 和趋势分析。
在消除趋势方面,数据科学家有几个选择:数据转换、消除滚动统计和差异。下面我将使用从下面的 UniBit API 获得的历史标准普尔 500 指数价格数据来介绍这些方法。
标准普尔 500 历史价格——由 UniBit API 提供
1)转型
我把我的价格数据组织在一个熊猫数据框架中。索引设置为日期列,日期按升序排序。我获得了截至 2020 年 1 月 9 日的一年 OHLC 价格。
按升序排列的标准普尔 500 数据帧的头部
Python 的 NumPy 库中有几种可用的转换,包括对数、*方根等等。我为其中的一些转换创建了一个新列,方法是将它们应用于调整后的收盘价列。
时间序列数据的 NumPy 转换示例,注意数据帧被称为“inx_df”
应用 NumPy 变换后的数据帧
没有一种单一的转换方法能让所有的时间序列都变得*稳,你必须自己测试它们。对数变换的可视化如下。
调整后收盘价的标准普尔 500 对数变换
这个特殊的转换没有完全实现这个系列的*稳性。价格的范围发生了巨大的变化,该系列的上升趋势已经减弱,这是一个良好的开端。对数函数是同底数的指数函数的逆。
2)滚动方式
您可以从时间序列中减去滚动*均值。当*均值依赖于时间时,这种方法特别有效。A 滚动*均值是系列中先前 x 次观察的*均值,其中每次观察之间的时间是一致的。您必须决定哪个时间窗口最适合您的数据。因为我使用的是每日交易数据,所以我选择了 20 天的窗口,因为这是一个月中有多少个交易日,尽管这不是金融数据的通用窗口。
Pandas 的.rolling()
方法可以用来计算这个滚动*均值。例如,计算我的数据的 20 天滚动*均值的代码是:
inx_df[‘adj_close’].rolling(window = 20).mean()
标准普尔 500 和二十天滚动*均
我创建了一个从原始收盘价中减去滚动*均值的新数组,并将其绘制在下面,以查看这是否改善了序列的*稳性。
从标准普尔 500 的调整收盘价中减去二十天滚动*均值
这一系列似乎更接**稳性。上升趋势实际上已经消失,但差异仍然明显。对于金融数据,从原始数据中移除加权滚动*均值也是完全合理的。加权滚动*均值为最*的观测值分配更大的权重。在 Python 中,这是用[.ewm()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.ewm.html)
方法计算的,对于我的数据,代码如下:
inx_df[‘adj_close’].ewm().mean()
该方法中有几个参数可用于确定观察值的单个权重,包括 com、跨度和半衰期。
从标准普尔 500 调整收盘价中减去的指数滚动*均值。半衰期参数设置为 2。
3)差异
另一种去除时间序列数据趋势的方法是差分法。这是用一个观察值减去另一个观察值的过程 x 之前的周期数,其中 x 是时间周期滞后。例如,在 S & P 500 的例子中,如果滞后一年,那么 2020 年 1 月 1 日的差异值等于 2020 年 1 月 1 日观察到的实际价格减去 2019 年 1 月 1 日观察到的值。Pandas 库的.diff(periods=*x*)
方法可以用来计算一组不同的值。周期参数表示使用的滞后。我的值以日为增量,这意味着滞后 365 等于一年,滞后 1 等于一天。
标准普尔 500 调整收盘价格差异,滞后一天
差异也消除了时间序列的上升趋势,尽管方差仍然是时间相关的。
摘要
Python 的 NumPy 和 Pandas 库有许多针对时间序列数据的转换和趋势分析方法。你必须用不同的参数尝试许多方法,看看什么能帮助你的序列最接**稳性。一旦你应用了这些变换,你就可以应用像 Dickey-Fuller 这样的统计测试来比较你的结果。
在数据科学工作面试中表现出色
容易避免的常见错误的自以为是的列表
在我担任数据科学家期间,我有机会面试了相当一部分数据相关职位的候选人。在这样做的时候,我开始注意到一个模式:某些类型的(简单的)错误在候选人中极其频繁!在我看来,与托尔斯泰的一句名言截然不同的是,“案例研究中大多数令人不快的错误看起来都很相似”。
在我的脑海中,我开始想象我会毫不犹豫地雇佣哪种候选人。不,不是 rock star/Guru/布道者,拥有 12 年管理 Kubernetes 集群和使用 Hadoop/Spark 的专业经验,同时为 TensorFlow 的开发做出贡献,获得 2 个博士学位,每年至少发表 3 篇深度学习论文。没有。我会立刻被一个至少没有犯我将要描述的那种错误的人所打动……我可以想象同样的事情会发生在其他公司,发生在其他面试官身上。
虽然这是一个个人的和相当固执己见的列表,但我希望这些小技巧和窍门能对刚开始数据科学生涯的人有所帮助!我在这里只是把我想到的更多的与 DS 相关的东西放在这里,但是当然,编写 Pythonic 式的、可读的、有表现力的代码也会让采访你的人非常高兴!
草率使用熊猫
让我们面对现实吧:作为一名数据科学家,对于您的大多数日常任务,您将操作表、对表进行切片、根据列中包含的值对表进行分组、对表应用转换等等。这几乎自动意味着 Pandas 是数据科学家最重要的基础工具之一,如果你能够展示对它的掌握,那么人们会非常认真地对待你。
相反,如果您系统地对存在内置 Pandas 命令的数据帧进行非常低级的操作,您可能会引发各种危险信号。
这里有一些提高熊猫的技巧:
- 使用它!
- 每当你必须对一个数据帧或系列进行任何操作时,停下来几分钟,阅读文档,检查是否已经有内置的方法可以帮你节省 90%的工作。即使你没有找到它们,在通读文档的过程中,你也会学到很多东西,这些东西将来很可能会派上用场。
- 看信得过的人写的教程,看看他们是怎么做一些操作的。特别是,汤姆·奥格斯伯格的现代熊猫教程第二部分是一个很好的开始。更好的是,不只是读第二部分,而是整个系列。另外,文森特·d·沃默达姆的这个演讲也值得一看。
- 如果您必须执行一些复杂的,可能不是内置的数据转换,请考虑将其封装在一个函数中!这样做之后,
.pipe(...)
和.apply(...)
就是你的朋友了。
最后提示:不要在任何地方使用inplace=True
。与普遍的看法相反,它不会带来任何性能上的好处,而且自然会让您编写不清楚的代码,因为它会妨碍您链接方法的能力。希望这个功能会在未来的某个时候停止。
从测试集中泄漏的信息
测试集是神圣的;在建立模型或选择迄今为止你得到的最好的一个时,它甚至不应该被看。想一想:我们之所以首先要有一个测试集,是因为我们希望对一个模型的泛化误差有一个无偏的估计。如果我们被允许先睹为快“未来”(即,在训练和模型建立期间,我们根本不应该访问的数据),几乎可以肯定我们会受到影响,并使我们的误差估计产生偏差。
虽然我从未见过任何人直接在测试集上拟合模型,但通常候选人通过查看测试集上的一些度量来执行超参数调整和模型选择。请不要这样做,而是将部分数据保存为验证集,或者更好的方法是执行交叉验证。
另一个导致测试集信息泄漏的常见原因是在整个数据集上安装定标器(如sklearn.preprocessing.StandardScaler
)或过采样例程(如imblearn.over_sampling.SMOTE
)。同样,特征工程、重采样等是如何构建和训练模型的一部分:不要让测试集出现在模型中。
*均值的缺陷
尽管汇总统计数据(如*均值、分位数等)有助于获得数据的第一印象,但不要犯将分布简化为单一数字的错误,因为这没有意义。一个经典的警示性例子来展示这一点是安斯科姆的四重奏,但我最喜欢的是的 Datasaurus 打的。
来源:Autodesk Research
通常情况下,数据点的分布比它们的*均值更重要,尤其是在一些应用中,分布尾部的形状是最终决定决策的因素。
如果你表现出你考虑到了这类问题,当有人提到詹森不等式时,你甚至不眨眼,那么只有好事会发生。
盲目使用图书馆
当你得到一个案例研究时,你通常有一个可以利用的优势:你选择要使用的模型。这意味着你可以预料到面试官可能会问你的一些问题!
例如,如果你最终使用了一个XGBClassifier
来完成你的任务,尽可能深入地理解它是如何工作的。大家都知道它是基于决策树的,但是它还需要哪些“成分”呢?你知道 XGBoost 是如何处理缺失值的吗?你能用通俗的语言解释一下装袋和抢劫吗?
即使你最终使用了线性回归,你也应该清楚地知道幕后发生了什么,以及你设置的参数背后的意义。如果你说“我把学习率设为 X”,有人接着问“什么是学习率?”,如果你不能至少在它上面花上几句话,那就太糟糕了。
糟糕的可视化选择
为你的情节选择正确的选项也有很长的路要走。最后,我认为这里最常见的错误是由于标准化选择不当或者没有使用正确的轴刻度。
我们来看一个例子;以下代码片段
只创建两个带有指数分布样本的数组;然后,它生成以下图形
我无数次看到这种变化。基本上,我们真正想做的是比较两组之间的分布,但在这个图中,我们只显示观察值的原始计数。如果其中一组比另一组有更多的样本,这样的图对于了解潜在的分布是没有意义的。更好的选择是以一种合理的方式将我们显示的内容标准化:在这种情况下,只需设置参数density=True
即可将原始计数转换为相对频率,并给出以下结果:
不错!现在我们可以清楚地看到,a
和b
毕竟是来自同一个分布的样本。这里仍然有一些我不喜欢的东西:大量的空白,以及对于大于 4 的a
或b
值,我看不清楚任何条形。幸运的是,由于 1614 对数是一种常见的数学运算……如此常见,以至于我们甚至在plt.hist(...)
中有一个专用的关键字参数,它只是将我们的线性 y 轴转换为对数轴:
请注意,这绝不是一个“完美”的情节:我们的轴没有标签,没有图例,它只是看起来有点丑!但是,嘿,至少我们可以通过调用plt.hist([a,b])
来提取我们永远无法看到的洞察力。
结论
上面列出的所有错误的共同点是,通过一些思考和相关知识,它们是很容易避免的,所以我对你下一个数据科学案例研究的建议是:放松,集中精力,努力比他们与你玩的任何心理游戏领先一步,并谷歌搜索东西(很多!).面试可能会有压力,但是如果双方都是公*的(尤其是面试并提出任务的人),几乎不会浪费时间。
非常感谢对本文的任何反馈;我错过了什么你认为特别重要的事情吗?
最后,我祝你事业顺利,无论你现在从事什么工作!也许会在面试时见到你:-)
完成数据科学带回家的作业
带回家的作业是否符合他们的目的,以及如何征服他们。
如今,许多公司在数据科学家招聘流程中包括带回家的任务。在这个博客中,我将分享我对这个测试的想法和一些我发现在面对它们时很方便的技巧。
什么是带回家的作业?
类似于软件工程师的编码测试,带回家的作业是一个初步的筛选,帮助招聘人员找到具有最佳技能/承诺的候选人,以进行下一轮面试。它通常发生在筛选阶段之后,第一次技术面试之前。
在任务中,候选人得到一个数据集,并被要求在通常的一周内做“一些事情”。“某些东西”可以是清晰的,有透明的评估标准,但有时可能非常模糊。题目和难度差别很大,看公司的喜好和水准。
举例来说,以下是我去年在寻找数据科学家工作时遇到的一些任务:
- 建立一个模型,并在虹膜数据集上可视化分类区域。
- 建立一个住房图像分类模型和一个演示服务。
- 从西雅图 Airbnb 数据集中,为 Airbnb 想出一个业务问题,并解决它。
- 给定以前在线广告和点击客户的 id,为下一次广告活动提出一个策略。
可交付成果通常是源代码和一些解释作品的简短幻灯片。
带回家的作业是一件好事吗?
我要坦率地说,我个人认为,总的来说,带回家的作业花费了求职者和雇主太多的时间和精力,而不是总能很好地达到目的。总之就是坏。
对候选人不利,原因有三:
- 候选人大约需要 10 个多小时才能完成作业。考虑到这只是招聘过程的早期阶段,这是一笔很大的投资。
- 在为任务付出巨大努力后,候选人通常只会收到一封简短的拒绝邮件,没有任何反馈。这种沮丧会对候选人的动机和信心产生负面影响。
- 有了这样的风险,这项任务创造了一个进入壁垒,阻止候选人探索新的机会,或者同时申请多家公司。想象一下:如果你申请了 4 家公司,并在同一周内收到了他们的任务,这将意味着 40 个小时的工作,就像一份全职工作一样。
这对招聘人员也不利,因为:
- 寻找数据集,设计作业,评估提交的答案将花费大量的时间和精力。
- 许多优秀的候选人不愿意从事如此耗时的工作。所以,通过试图过滤掉不合格的候选人,被招募的人可能也送走了精英。
与数据科学作业相比,软件工程师的编码测试要好得多。它很容易设置测试(现在许多*台都提供这项服务),很容易判断候选人的提交情况(如果代码运行,它就运行,如果不运行,那么它就不运行),并且只需要双方花费不超过 90 分钟的时间。
通过数据科学作业的锦囊妙计
带回家的作业很糟糕。然而,由于数据科学家仍然是一个相对较新的角色,许多组织尚未设计一个标准化的程序来正确测试候选人的技能。因此,带回家的作业成了标准。作为候选人,你必须服从。
在这个环节中,我将分享一些我认为非常有用的行动技巧,以便轻松地完成任务
在任务之前
- 通过做 Kaggle 或个人数据科学项目来实践。这项任务非常类似于一场 Kaggle 竞赛,有时更简单。所以这些是做模拟测试的最好地方。实践它们将装备你的信心和经验,以征服这一轮。
- 准备好你的工作框架。无论数据集如何,大多数数据科学解决方案都遵循相同的模式:探索性分析、数据处理、特色工程、模型构建、超参数调整、培训和验证。知道了这一点,你就可以准备一个模板化的笔记本,把所有的会话都准备好。当数据到达时,你不再不知所措和惊慌失措,而是确切地知道接下来的步骤。
- 准备实用功能。在实践数据科学的时候,你会意识到有一些函数被反复使用。这些功能可以是加载和可视化数据、处理缺失值、生成要素等。您应该尝试将这些功能一般化,并将它们存储在您的 Github 上。在分配过程中,您可以简单地重用这些函数,而不是从头开始编写所有代码。这将大大节省你的时间和精力。
- 研究招聘公司。想出一个数据科学任务很难,所以许多公司倾向于坚持一个小问题池。因此,在玻璃门上研究这家公司可能会给你一些启发。关于可能问题的暗示也可能来自公司的业务性质。例如:一家电子商务公司可能存在与推荐相关的问题,一家咨询公司可能存在典型的机器学习问题,等等。
在任务期间
图片来自 Pixabay 的 Johnson Martin
- 阐明数据集和预期。不要在收到数据后就直接开始编码。询问关于作业如何评分的问题,或者如果你对数据集有任何疑问。在花接下来的 10 个小时解决这个问题之前,你需要确保你非常清楚这个问题。
- 直奔主题。为了给招聘经理留下深刻印象,你可能会尝试进行广泛的探索性分析,绘制漂亮的图表,彻底研究每种可能算法的利弊,等等。不要。这将会分散你对最终目标的注意力:提供解决方案。了解数据集后,进入下一个处理步骤,然后是模型,然后是预测。当所有的核心步骤都完成了,模型达到了令人满意的性能,那么你就可以去做额外的工作了。否则,你的作品可能会有许多美丽的数字,和一个可怕的准确性。
- 遵循软件工程 编码标准 。成为一名数据科学家并不意味着你可以编写蹩脚的代码。在你完成实验并最终确定你的解决方案后,重构你的代码。让你的代码可读,给变量和函数起一个合适的名字,写下解释的注释,等等。
- 恰当地呈现自己的作品,讲好故事。你在完成任务方面做得很好,现在是推销的时候了。说明你的工作流程,你对模型的选择,你为什么认为你的模型取得了很好的业绩,你还尝试了哪些东西等等。记住这一点:招聘人员只有非常有限的时间来看你的工作,所以让你的解释尽可能简短明了,并让它成为一次愉快的阅读体验。
- 尽可能使用 笔记本。笔记本可以让你用漂亮的流程和格式展示你的代码、分析、图表和解释。这会让雇主更容易理解和欣赏你的工作。
举个例子, 这里的 是我提交的通过任务轮次的代码之一。
任务完成后
- 彻底检查你的工作。通过了一轮分配并不意味着你已经永远地与它分道扬镳。你的工作很有可能成为下一轮面试的讨论话题。因此,准备好流畅地解释你做的每一步是什么和为什么。尤其是,确保你对你的模型背后的算法了如指掌。用一些你不了解的东西,比根本不了解它们还要糟糕。
- 看看你是否喜欢解决交给你的问题,因为这可能很好地反映了你加入公司后的未来任务。这是因为为了测试应聘者的兼容性,很多公司在这份作业中都给出了自己的真实数据和真实问题。
- ****征求反馈。如果你通过了这一轮,不要被过分宣传,如果你不幸被拒绝,也不要哭着跑开。保持冷静,征求对工作的反馈,这样你就能在技术上有所成长。你已经努力工作并提交了一份尊重的回答,因此你应该得到同样尊重的反馈。
结论
综上所述,我认为把带回家的作业纳入面试过程是不理想的,对公司和应聘者都是如此。然而,如果不得不面对它们,你可以通过优化时间和精力来克服它们:
- 分配任务前:通过做 Kaggle 获得经验,准备好你的框架和效用函数,并对你申请的公司做一些研究。
- ****在分配任务期间:澄清你的疑问,然后在做额外探索之前直接进入解决方案,遵循良好的编码标准,并恰当地展示你的工作。
- 任务完成后:彻底检查你的工作,看看你将来是否喜欢做类似的任务,并寻求反馈。
我希望我的一些建议能对你处理带回家的作业有所帮助。
谢谢你的阅读。
威瑞森媒体数据科学访谈
要成为一名数据科学家,需要通过几个面试阶段
莱昂·塞伯特在 Unsplash 上拍摄的照片
一些历史
威瑞森媒体 是威瑞森通信集团成立两年的子公司,负责开发在线、数字媒体和广告服务。这家子公司是在威瑞森收购两家公司之后成立的,这两家公司在上世纪 90 年代中期互联网繁荣时期为在线通信和网络浏览引入了一系列广泛使用的数字服务——AOL 和 Yahoo!
直到 2019 年初,AOL 和雅虎!成为威瑞森公司的一部分,被称为誓言公司,后来被命名为威瑞森媒体。今天,威瑞森媒体作为公司的主要媒体和在线广告部门,运营着无数知名的数字品牌,此外还收购了两个品牌,包括赫芬顿邮报和 TechCrunch 。就像任何其他坐拥大量消费者数据的数字媒体和营销服务公司一样,他们乐于寻求合格数据科学家的专业知识。这是他们在法国巴黎总部的入门级数据科学职位的数据科学面试。
总体要求
威瑞森媒体的数据科学家的工作描述非常典型。一个人应该至少拥有计算机科学、会计或任何相关专业的学士学位。一个人还应该在商业智能和规范分析以及数据可视化方面拥有专业知识,并使用 Tableau 等工具。新员工应该能够进行预测建模,在 Python 或 R 中实现机器学习(ML)算法,了解云环境中的数据仓库,例如亚马逊网络服务 ( AWS)或谷歌云*台。一个人应该了解数据库管理和查询,因此有一个体面水*的 SQL 技能是好的。
虽然该角色被宣传为数据科学家,但这些要求很容易成为数据工程师和数据分析师的预期职责。这有一些影响-新员工将需要作为数据科学家戴上一顶以上定义明确的帽子,并可能拥有完成各种数据相关任务的知识,以避免团队不得不雇用整个新员工来提供特定的专业知识。一个多方面的角色可能最终对一个人的发展都有好处。
面向数据工程师(左)和数据科学家(右)的典型维恩数据堆栈图。来源:数据营
因此,我们需要进行广泛的研究,以设计和实施商业解决方案,进行复杂的统计和计算分析,将 ML 算法应用于客户数据,以优化数字服务和营销*台,并将研究和分析的结果传达给商业利益相关者。这是一个很高的要求,一个人对这个角色的总体适应性将在最初的电话筛选中得到判断。
第一阶段:电话屏幕面试
下一步可能是电话面试。在 30 分钟的电话筛选中,候选人被要求提供他们在数据分析和数据科学方面的专业知识的背景信息。像往常一样,我们的目标是了解他们的技能、职业兴趣和以往的经验。在这一阶段,除了一两个简短的问题来测试一个人在解释数学和/或统计概念方面的舒适程度和能力之外,这些问题不太可能非常专业。例如,人们可能被要求向外行人解释一对事件的独立性和互斥性之间的区别。这只是众多问题中的一个,可以证明候选人对一个概念理解得足够好,能够向没有相同知识基础的人阐述或阐明这个概念。
第二阶段:带回家的作业
课后测试的第一部分将进一步评估一个人与软件工程师和利益相关者交流概念的能力。作业可能会在 Jupyter 笔记本和/或 Python 脚本中提交,其中包含以下问题:
- 向工程师解释什么是降维,并提供实例。
- 你会如何向一位企业高管解释无监督学习是如何运作的,以及它如何被用来利用营销技巧?
- 向同一个主管解释 90%的置信区间。
这项任务还要求候选人在数据建模部分展示他们作为数据科学家或机器学习工程师的技术能力。为此,需要熟悉以下概念和工具,
统计数据:
- 二元和边际分布
- 正态(高斯)和偏斜分布
预测建模:
- 时间序列
Python 实现:
- 数据可视化:Seaborn 和 Matplotlib
- 笨笨和笨笨
- Tensorflow、Scikits-learn、PyTorch APIs
面向数据科学家/分析师的典型 Python 技术堆栈
带回家的作业意味着要在几个小时到一周内完成,这完全取决于一个人的承诺。
第三阶段:现场面试
要通过这项带回家的任务,需要一个人正确完成给出的每个问题,或者让招聘团队领导满意。成功通过后,面试过程中的最后一个阶段就在候选人和工作机会之间。这是现场面试,也可以在线进行。在这一阶段,当一个人回答关于制定技术和业务战略的问题时,他与组织内不同层次的人交流复杂概念的能力将再次得到验证。最后的面试将为团队提供一个机会,让他们感受候选人的工作和沟通风格,以及他们的团队合作能力。
第四阶段:报价
通过了前两个阶段,最后的面试应该是一帆风顺的。当然,正如面试中常见的情况一样,获得最终职位需要很多运气。
结论
好吧,我们可以在这里结束。总之,我概述了威瑞森媒体的数据科学家职位的要求,以及面试过程中最终获得工作机会的各个阶段。我希望这些信息能在你求职的某个阶段对你有所帮助,并给你至少一个数据点来改进你最终数据科学面试策略的回归模型。
声学 SLAM——技术现状:综述
基于声信号的同步定位与地图创建综述。
来自维基:https://sco.wikipedia.org/wiki/Acoustics
介绍。
随着最*无人机使用的增加(包括飞行和地面车辆),在以前未知和未探索的位置自主导航的能力已经成为一项至关重要的任务。能够探索标准和极端环境(如洞穴、受损建筑等)的机器人。)正受到越来越多的关注。已经考虑的一种解决方案是同步定位和地图绘制(SLAM ),其中车辆可以同时探索和绘制其环境。
部分由于计算机视觉技术的快速发展,使用传感器摄像机阵列的视觉 SLAM 在学术界和工业界都受到了广泛的关注。然而,相机受到几个因素的严重限制,例如它们相当大的计算需求,以及它们不能在恶劣的照明条件下操作,这可能是对任务的严重限制。
基于摄像机的感测的替代方法是使用声学传感器,其以类似声纳的方式工作。声学 SLAM (aSLAM)受到的关注有限,但在这方面已经开展了一些工作,特别是地面机器人(如 Evers 等人的工作[1])。值得注意的是,声学 SLAM 也受到一些限制,如低分辨率(特别是与视觉仪器相比),但对计算的要求要低得多。本综述分为三个部分:(A)一般 SLAM 问题的一般和简要背景。(b)当今用于声学 SLAM 的最先进方法。(c)审查 aSLAM 的现代工业应用。
背景
考虑到当前的工业应用,本综述包含关于声学 SLAM 的广泛文献调查。在 SLAM 中,一个物体(机器人、汽车等。)在未知环境中沿着未知轨迹[2]移动,目标是绘制其周围环境的地图。SLAM 算法用于重建环境地图和物体轨迹。在大多数情况下,地图是由已知的地标指定的。重建地图相当于确定这些地标相对于物体的位置。达兰特-威特和贝利[3]-[4]以及卡德纳等人[5]和特鲁内等人[6]已经总结了这个问题和解决这个问题的各种方法。解决一般 SLAM 问题的两个经典算法是扩展卡尔曼滤波器(EKF-SLAM) [7]和 SLAM 的分解解(FastSLAM) [8]。EKF 是一种著名的处理非线性问题的导航和控制算法。另一方面,FastSLAM 算法利用后验概率的 Rao-Blackwellized [9]表示,集成了粒子滤波和卡尔曼滤波表示。目前,这两种方法构成了 SLAM 领域的核心。
最先进的声学 SLAM 方法
在声学 SLAM 中,许多方法在自由空间中工作良好,但由于来自地标的回声,在室内环境中部署更具挑战性。
使用粒子滤波器的 DoA 估计
埃弗斯和奈洛尔[1]提出了一种基于配有麦克风阵列的观测器的算法,用于探索和学习给定环境中各种基于声学的地标。该算法基于源位置的概率三角测量,通过估计源的到达方向(DoA),利用观察者的时空多样性,并通过使用直接路径优势多信号分类(DPD-MUSIC) [10]使其最大化来实现。对于每一个时间步,正如 Botev 和格洛托夫斯基[11]所建议的。通过估计样本的核密度来*似计算连续单源概率密度函数。多源 PDF 通过其概率假设密度(PHD)来*似。这项研究建议通过一种概率方法融合运动报告和源地图,这种方法被称为粒子滤波器(也称为序列蒙特卡罗)[12]。Andrieu 和 Godsill [13]将这种方法应用于音频。在他们的实验研究中,他们实现了定位和映射结果,包括 DoA 估计误差的鲁棒性[1]。
基于麦克风阵列的几何重建
Dokmanic 等人[14]展示了基于声学仪器(特别是麦克风阵列)的房间几何形状重建。他们将模型公式化为一个约束优化问题,而没有使用概率方法,但他们的解决方案仅限于几个麦克风。Ba 等人[15]提出了一种基于圆形麦克风阵列的新型房间建模算法。他们展示了实验结果,其中映射几乎完美地完成,并且以高精度确定了到房间墙壁的距离。
应用程序
Furukawa 等人[16]报告了使用无人驾驶飞行器(UAV)进行基于声学的定位。他们开发了一种方法,通过在多旋翼无人机上安装麦克风阵列来提高声源定位。他们声称主要问题是车辆螺旋桨发出的自身噪音。他们实现了基于广义特征值分解(GEVD)的 MUSIC。
2017 年,Krekovic,Dokmanic 和 Vetterli 根据回声重建了轨迹和房间几何形状,这些回声是由静态麦克风阵列捕获的。他们的工作受到了蝙蝠的启发,蝙蝠通过听叫声的回声在室内飞行。Lollmann 等人[18]介绍了作为 IEEE 音频和声学信号处理(AASP)源定位和跟踪(LO- CATA)的一部分的实验结果。使用*面、球形和伪球形麦克风阵列记录音频。实验包括:用于移动人类谈话者和扬声器的静态和移动阵列。
参考
[1]克里斯汀·埃弗斯和帕特里克·奈洛尔声学撞击。 IEEE/ACM 音频、语音和语言处理汇刊,26(9):1484–1498,2018。
[2]MWM·加米尼·迪萨纳亚克、保罗·纽曼、斯蒂夫·克拉克、休·达兰特-威特和迈克尔·科尔巴。一种解决同时定位和地图创建问题的方法。 IEEE 机器人与自动化汇刊,17(3):229–241,2001。
[3]休·达兰特-威特和蒂姆·贝利。同步定位和绘图:第一部分 IEEE 机器人学&自动化杂志,13(2):99–110,2006。
[4]蒂姆·贝利和休·达兰特-威特。同步定位和绘图(slam):第二部分。 IEEE 机器人学&自动化杂志,13(3):108–117,2006。
[5]塞萨尔·卡迪纳、卢卡·卡隆、亨利·卡里略、亚西尔·拉蒂夫、达维德·斯卡拉穆扎、何塞·内拉、伊恩·里德和约翰·伦纳德。同时定位和绘图的过去、现在和未来:走向健壮感知时代。 IEEE 机器人学报,32(6):1309–1332,2016。
[6]巴斯蒂安·特龙、沃尔夫拉姆·布加尔德和迪特尔·福克斯。概率机器人学(智能机器人和自主代理系列)。
7 安德鲁·H·亚兹温斯基。随机过程和滤波理论。快递公司,2007 年。
[8]迈克尔·蒙特梅洛,巴斯蒂安·特龙,达芙妮·柯勒,本·韦格布雷特,等,《Fastslam:同时定位和绘图问题的分解解决方案》。Aaai/iaai ,593598,2002 年。
[9]阿诺·杜塞、南多·德弗雷塔斯、凯文·墨菲和斯图亚特·罗素。动态贝叶斯网络的 Rao-Blackwell ized 粒子滤波。在第十六届人工智能不确定性会议记录,第 176-183 页。摩根考夫曼出版公司,2000 年。
10 或纳迪里和波阿斯·拉斐尔。使用球形麦克风阵列和直接路径优势测试定位高混响下的多个扬声器。 IEEE/ACM 音频、语音和语言处理汇刊,22(10):1494–1505,2014。
[11]兹德拉夫科·I·博泰夫、约瑟夫·F·格洛托夫斯基、德克·P·克罗斯等,通过扩散进行核密度估计。统计年鉴,38(5):2916–2957,2010。
[12]皮埃尔·德尔·莫拉尔。非线性滤波:相互作用的粒子分辨率。科学研究院报告-系列 I-数学,325(6):653–658,1997 年。
[13] C .安德烈和 SJ .戈德西尔。基于模型的声源分离的粒子滤波器。《独立分量分析和盲信号分离国际研讨会论文集(ICA 2000)》,2000 年。
[14] Ivan Dokmani c、Laurent Daudet 和 Martin Vetterli。从声学房间重建到 slam。在 2016 IEEE 国际声学、语音和信号处理会议(ICASSP) 中,第 6345–6349 页。Ieee,2016。
[15]登巴·巴、弗拉维奥·里贝罗、查·张和迪内·弗洛伦西奥。L1 正则化房间模型与紧凑的麦克风阵列。在 2010 年 IEEE 国际声学、语音和信号处理会议中,第 157–160 页。IEEE,2010 年。
[16]古川康太郎、大谷圭太、大*康*、大冢拓马、藤山胜、中代和弘和大野浩史。改善多旋翼无人机声源定位的噪声相关矩阵估计。在 2013 IEEE/RSJ 智能机器人和系统国际会议中,第 3943–3948 页。IEEE,2013 年。
[17]米兰达·克雷科维奇、伊万·多克马尼和马丁·维特利。全向蝙蝠,点到*面的距离,以及独一无二的代价。在 2017 IEEE 声学、语音和信号处理国际会议(ICASSP) 中,第 3261–3265 页。Ieee,2017。
[18]海因里希·奥尔曼、克里斯蒂娜·埃维斯、亚历山大·施密特、海因里希·梅尔曼、亨德里克·巴福斯、帕特里克·奈洛尔和沃尔特·凯勒曼。声源定位和跟踪的 locata 挑战数据语料库。在 2018 IEEE 第 10 届传感器阵列和多通道信号处理研讨会(SAM) ,第 410–414 页。IEEE,2018。
使用 RLlib 进行动作屏蔽
改善强化学习的参数动作
RL 算法通过反复试验来学习。代理人在早期搜索状态空间,并采取随机行动来了解什么会带来好的回报。非常简单。
不幸的是,这并不是非常有效,特别是如果我们已经知道一些关于在某些州什么是好与坏的行为。幸运的是,我们可以使用动作屏蔽——一种将坏动作的概率设置为 0 的简单技术——来加速学习和改进我们的策略。
TL;速度三角形定位法(dead reckoning)
我们通过对背包打包环境的动作屏蔽来实施约束,并向展示如何使用 RLlib 来实现这一点。
强制约束
让我们用经典的 背包问题 来开发一个具体的例子。
背包问题(KP)要求你打包一个背包,在不超载的情况下使包里的价值最大化。如果你收集了如下所示的物品,最佳包装将包含三个黄色盒子和三个灰色盒子,总共 36 美元和 15 公斤(这是无界背包问题,因为你可以选择的盒子数量没有限制)。
来源:维基百科
通常,这个问题是使用动态编程或数学编程来解决的。如果我们按照数学程序建立它,我们可以写出如下模型:
在这种情况下, x_i 可以是任何大于等于 0 的值,代表我们放入背包的物品数量。 v_i 和 w_i ,分别为项目的值和权重。
用简单的语言来说,这个小模型是在说我们想要最大化背包中的价值(我们称之为 z )。我们通过找到最大数量的物品( x_i )和它们的值( v_i )而不超过背包的重量限制( W )来做到这一点。这个公式被称为整数规划(IP ),因为我们有整数决策变量(我们不能打包项目的一部分,只能打包完整的整数值),并使用像 CPLEX、Gurobi 或 GLPK(最后一个是免费和开源的)这样的求解器来求解。
强制实施这些约束是模型的一部分,但它并不是 RL 的一部分。RL 模型可能需要包装绿色的 12 公斤的盒子几次,然后才知道它不能包装那个和黄色的 4 公斤的盒子,通过受到几次大的负面奖励。过度打包的负面回报是一个“软约束”,因为我们没有明确禁止算法做出这些糟糕的决定。但是,如果我们使用动作屏蔽,我们可以确保模型不会做出愚蠢的选择,这也将有助于它更快地学习更好的策略。
金伯利进程环境
让我们通过使用[or-gym](https://github.com/hubbs5/or-gym)
库打包一个背包来实现这一点,该库包含一些来自运筹学领域的经典环境,我们可以用它们来训练 RL 代理。如果你熟悉 OpenAI Gym,你会以同样的方式使用它。可以用pip install or-gym
安装。
一旦安装完成,导入它并构建Knapsack-v0
环境,这就是我们上面描述的无界背包问题。
import or_gym
import numpy as np
env = or_gym.make('Knapsack-v0')
该环境的默认设置有 200 种不同的物品可供选择,最大承重为 200 公斤。
print("Max weight capacity:\t{}kg".format(env.max_weight))
print("Number of items:\t{}".format(env.N))[out]
Max weight capacity: 200kg
Number of items: 200
这很好,但是 200 个项目看得太清楚了,所以我们可以通过一个env_config
字典来更改其中的一些参数,以匹配上面的示例。此外,我们可以通过将mask: True
或mask: False
传递给配置字典来打开和关闭动作屏蔽。
env_config = {'N': 5,
'max_weight': 15,
'item_weights': np.array([1, 12, 2, 1, 4]),
'item_values': np.array([2, 4, 2, 1, 10]),
'mask': True}env = or_gym.make('Knapsack-v0', env_config=env_config)print("Max weight capacity:\t{}kg".format(env.max_weight))
print("Number of items:\t{}".format(env.N))[out]
Max weight capacity: 15kg
Number of items: 5
现在我们的环境与上面的例子相匹配。简单看一下我们的状态。
env.state[out]
{'action_mask': array([1, 1, 1, 1, 1]),
'avail_actions': array([1., 1., 1., 1., 1.]),
'state': array([ 1, 12, 2, 1, 4, 2, 4, 2, 1, 10, 0])}
当我们将 action mask 选项设置为True
时,我们得到一个字典输出,作为包含三个条目action_mask
、avail_actions
和state
的状态。这对于or-gym
库中的所有环境都是相同的格式。掩码是一个二进制向量,其中 1 表示允许一个动作,0 表示它将打破某些约束。在这种情况下,我们唯一的约束是重量,所以如果一个给定的项目将推动模型超过重量,它将收到一个大的,负的惩罚。
可用操作对应于代理可以选择打包的五个项目中的每一个。状态是传递给神经网络的输入。在这种情况下,我们有一个连接了项目权重和值的向量,并在末尾添加了当前权重(初始化环境时为 0)。
如果我们继续并选择 12 公斤的物品进行包装,我们应该看到动作屏蔽更新,以消除包装任何其他物品,使模型超过重量限制。
state, reward, done, _ = env.step(1)
state{'action_mask': array([1, 0, 1, 1, 0]),
'avail_actions': array([1., 1., 1., 1., 1.]),
'state': array([ 1, 12, 2, 1, 4, 2, 4, 2, 1, 10, 12])}
如果你看一下action_mask
,那正是我们所看到的。环境正在返回信息,我们可以使用这些信息来阻止代理选择 12 公斤或 4 公斤的物品,因为这将违反我们的约束。
这里的概念很容易应用。在您完成通过策略网络的转发后,您可以使用掩码来更新非法操作的值,使它们成为较大的负数。这样,当你把它传递给 softmax 函数时,相关的概率将会是 0。
现在,让我们转向使用 RLlib 来训练模型以遵守这些约束。
RLlib 中的动作屏蔽
RLlib 中的动作屏蔽需要构建一个直接处理逻辑的定制模型。对于带有动作屏蔽的定制环境,这并不像我希望的那样简单,所以我将一步一步地指导您。
我们需要先进口很多东西。如果你熟悉这个库的话,ray
和我们的ray.rllib.agents
应该是显而易见的,但是我们还需要tune
、gym.spaces
、ModelCatalog
、一个 Tensorflow 或 PyTorch 模型(取决于你的偏好,对于这个我只坚持使用 TF),以及一个我们编写的or_gym
库中名为create_env
的实用程序,以使这个更加*滑。
import ray
from ray.rllib import agents
from ray import tune
from ray.rllib.models import ModelCatalog
from ray.rllib.models.tf.tf_modelv2 import TFModelV2
from ray.rllib.models.tf.fcnet import FullyConnectedNetwork
from ray.rllib.utils import try_import_tf
from gym import spaces
from or_gym.utils import create_envtf = try_import_tf()
构建自定义模型
我们需要明确地告诉神经网络如何处理状态字典中的不同值。为此,我们将基于 RLlib 的TFModelV2
模块构建一个定制模型。这将使我们能够构建一个定制的模型类,并向模型添加一个forward
方法以便使用它。在forward
方法中,我们应用如下所示的遮罩:
class KP0ActionMaskModel(TFModelV2):
def __init__(self, obs_space, action_space, num_outputs,
model_config, name, true_obs_shape=(11,),
action_embed_size=5, *args, **kwargs):
super(KP0ActionMaskModel, self).__init__(obs_space,
action_space, num_outputs, model_config, name,
*args, **kwargs)
self.action_embed_model = FullyConnectedNetwork(
spaces.Box(0, 1, shape=true_obs_shape),
action_space, action_embed_size,
model_config, name + "_action_embedding")
self.register_variables(self.action_embed_model.variables()) def forward(self, input_dict, state, seq_lens):
avail_actions = input_dict["obs"]["avail_actions"]
action_mask = input_dict["obs"]["action_mask"]
action_embedding, _ = self.action_embed_model({
"obs": input_dict["obs"]["state"]})
intent_vector = tf.expand_dims(action_embedding, 1)
action_logits = tf.reduce_sum(avail_actions * intent_vector,
axis=1)
inf_mask = tf.maximum(tf.log(action_mask), tf.float32.min)
return action_logits + inf_mask, state def value_function(self):
return self.action_embed_model.value_function()
为了完成这个过程,我们首先初始化模型并传递我们的true_obs_shape
,它将匹配state
的大小。如果我们坚持使用简化的 KP,这将是一个有 11 个条目的向量。我们需要提供的另一个值是action_embed_size
,它将是我们动作空间的大小(5)。从这里,模型根据我们提供的输入值初始化一个FullyConnectedNetwork
并注册这些值。
实际的屏蔽发生在forward
方法中,我们从环境提供的观察字典中解包屏蔽、动作和状态。状态产生我们的动作嵌入,它与我们的掩码相结合,以提供具有我们所能提供的最小值的逻辑。这将传递给 softmax 输出,从而将选择这些操作的概率降低到 0,有效地阻止代理采取这些非法操作。
一旦我们有了自己的模型,我们需要用ModelCatalog
注册它,这样 RLlib 就可以在训练中使用它。
ModelCatalog.register_custom_model('kp_mask', KP0ActionMaskModel)
此外,我们需要注册自定义环境,以便可以使用 RLlib 调用。下面,我有一个叫做register_env
的小助手函数,我们用它来包装我们的create_env
函数和 tune 的register_env
函数。Tune 需要基类,而不是像我们从or_gym.make(env_name)
获得的环境实例。所以我们需要使用如下所示的 lambda 函数将它传递给register_env
。
def register_env(env_name, env_config={}):
env = create_env(env_name)
tune.register_env(env_name, lambda env_name: env(env_name, env_config=env_config))
register_env('Knapsack-v0', env_config=env_config)
最后,我们可以初始化 ray,并将模型和设置传递给我们的培训师。
ray.init(ignore_reinit_error=True)trainer_config = {
"model": {
"custom_model": "kp_mask"
},
"env_config": env_config
}
trainer = agents.ppo.PPOTrainer(env='Knapsack-v0', config=trainer_config)
为了证明我们的约束有效,我们可以通过将其中一个值设置为 0 来屏蔽给定的动作。
env = trainer.env_creator('Knapsack-v0')
state = env.state
state['action_mask'][0] = 0
我们屏蔽了动作 0,所以根本看不到代理选择 0。
actions = np.array([trainer.compute_action(state) for i in range(10000)])
any(actions==0)[out]
False
我们做到了!我们已经成功地用 RLlib 中的自定义模型限制了我们的输出,以加强约束。您也可以使用与tune
相同的设置来约束动作空间并提供参数化动作。
面具有用
屏蔽可以非常有效地将代理从有害的局部最小值中释放出来。在这里,我们为 [or-gym](https://arxiv.org/abs/2008.06319)
构建了一个虚拟机分配环境,其中带有屏蔽的模型快速找到了一个优秀的策略,而没有屏蔽的模型则陷入了局部最优。我们尝试了很多奖励功能来摆脱这种困境,但是没有任何效果,直到我们应用了一个遮罩!
使用机器学习的动作规则发现
从数据中提取可操作的规则和提升估计值
在本文中,我们将讨论:
- 可解释的机器学习,相关性与因果性,用例
- 一个结合了预测和因果推理的强大 python 包,一个端到端的动作规则发现模型
链接到我的其他文章
简介
假设你是一个在企业工作的数据魔术师,任务是提出一个客户流失预测模型,以预测哪些客户有退订你的企业提供的服务的风险。你在 Colab Pro 上的一些 P100 GPU 上快速旋转一个深度神经网络,获得一些高预测精度,喝一杯康普茶,然后就可以收工了。第二天下午,你的老板打电话给你,说虽然预测能力很有用,但她需要知道哪些因素导致了客户流失的可能性,以及影响的程度。
您修改模型,而不是深度神经网络,使用 LightGBMs 的集合,结合对单个提升树计算的 Shapley 值,以给出如下的因子推断输出:
进球越多=流失越多…是这样吗?https://github.com/slundberg/shap在蓝海瀚的许可下
你有了另一个康普茶,满足于发现了(也相当有力地)模型认为哪些因素导致了流失,然后就到此为止。
就在你周五下午下班之前,你的老板 Zoom 再次打电话给你,告诉你尽管因素推断见解很棒,但我们仍然不知道这些因素是否实际上导致了流失或保留。她提醒你,相关性并不意味着因果关系,而且她也不知道模型所暗示的哪些因素实际上是因果关系,而不是巧合或虚假的相关性。
虚假相关的一个例子
作为一个痴迷的数据魔术师,你在网上搜索,无意中发现了一块隐藏的宝石,它能做你老板要求的一切。
有一个监督机器学习的分支叫做提升建模,它处理回答诸如“X 干预/行动会在多大程度上影响结果 Y?”给定包含关于干预 X 和结果 Y 的数据的历史记录数据集。X 对 Y 的影响是一个称为提升的量(如果 Y 是概率,通常是百分比)。在本文中,我们将简要介绍由[1]创建的名为 actionrules 的包,以及如何应用它来发现动作规则并量化它们对结果的影响。
动作规则
我们将简要介绍一些关于分类规则、动作规则、支持、置信度的定义,并看看如何估计提升。
分类规则 r_n 定义为:
r_ n =[(x1,n∧x2,n ∧ … ∧ X_m,n ) → Y_n]
其中元组(X_1,n ∧ X_2,n ∧ … ∧ X_m,n)是来自 n 个输入列的特定值 X_m。这个元组被称为前件或 ant,结果 Y_n 被称为后件。例如:
[(年龄= 55 岁∧吸烟=是∧体重= 240 磅)→心脏病风险=是]
是一个分类规则。分类规则通过称为支持度和置信度的两个数字进一步量化。支撑物被定义为
sup(ant → Yn) :=规则数(ant → Yn)
这是匹配条件(ant → Yn)的分类规则的数量,或者是匹配前因和后果的规则的数量。置信度定义为
conf(ant→Yn)= sup(ant→Yn)/sup(ant)
或者(ant → Yn)的支持度除以只有匹配前件的规则总数。
操作规则是分类规则的扩展:
a_ n =[f∧(X→X ')]→(Y→Y ')
其中 f 是一组固定的或不可改变的属性。对于动作规则,我们考虑固定属性和非固定或灵活属性的结合,从初始集合 X 到 X’的改变将改变结果 Y 到 Y’。一个具体例子是
[(年龄= 55 ∧(吸烟=是→否∧体重= 240 磅→190 磅)→心脏病风险=否]
原则上说,如果我们的受试者年龄固定,戒烟并因节食/锻炼而减轻体重,他们将不再有患心脏病的风险。我们可以再次使用置信度和支持度来量化通过某种方法发现的动作规则的质量。对动作规则的支持考虑了构成动作规则的两个分类规则 r 1 = (X→Y)和r 2 =(X’→Y’),并被定义为
sup(a_ n)= min(sup(r_ 1),sup( r _2))
并且动作规则的置信度被定义为
conf(a_ n)= conf(r_ 1)* conf(r_ 2)。
直观上,动作规则的支持度只能等于其分类规则之一的最小支持度,并且动作的置信度将小于或等于分类规则的任何一个置信度。
最后,隆起定义为
隆起= P(结果|治疗)-P(结果|无治疗)。
一般来说,任何提升模型都会尝试估计上述两种条件概率。
代码示例
动作规则发现算法的细节可以在源代码[1]中找到,但是简单地说,动作规则包包含了基于启发式的分类和动作规则发现算法,以监督的方式运行(意味着我们必须拥有/指定目标或结果标签)。我们将在一家名为 telco.csv 的电信公司的玩具客户流失数据集上运行动作规则模型。
https://github . com/hhl 60492/action rules/blob/master/notebooks/data/telco . CSV
根据 Kaggle 数据集页面[2]:
数据集包括以下信息:
- 上个月内离开的客户—这一列称为流失
- 每位客户已注册的服务—电话、多条线路、互联网、在线安全、在线备份、设备保护、技术支持以及流媒体电视和电影
- 客户账户信息——他们成为客户的时间、合同、支付方式、无纸化账单、每月费用和总费用
- 客户的人口统计信息—性别、年龄范围,以及他们是否有伴侣和家属
首先,我们使用控制台安装 actionrules 包:
pip install actionrules-lukassykora
# you can also call the following command in a Jupyter Notebook
# !pip install actionrules-lukassykora
接下来导入相关的包
import pandas as pd
from actionrules.actionRulesDiscovery import ActionRulesDiscovery
读入数据集并检查头部
dataFrame = pd.read_csv(“telco.csv”, sep=”;”)
dataFrame.head()
现在实例化动作规则模型并对数据运行模型拟合
import time actionRulesDiscovery = ActionRulesDiscovery()
actionRulesDiscovery.load_pandas(dataFrame)start = time.time()# define the stable and flexible attributes
actionRulesDiscovery.fit(stable_attributes = [“gender”, “SeniorCitizen”, “Partner”],
flexible_attributes = [“PhoneService”,
“InternetService”,
“OnlineSecurity”,
“DeviceProtection”,
“TechSupport”,
“StreamingTV”,
],
consequent = “Churn”, # outcome column
conf=60, # predefined List of confs for classification rules
supp=4, # predefined List of supports for classification rules
desired_classes = [“No”], # outcome class
is_nan=False,
is_reduction=True,
min_stable_attributes=1, # min stable attributes in antecedent
min_flexible_attributes=1 # min flexible attributes in antecedent
)end = time.time()
print(“Time: “ + str(end — start) + “s”)
在 MacBook Pro 1.4 GHz 英特尔酷睿 i5 处理器上,运行时间大约为 9 秒
接下来,我们统计发现的操作规则的数量:
print(len(actionRulesDiscovery.get_action_rules()))
结果发现了 8 条行为规则。现在让我们来看看实际的规则是什么:
for rule in actionRulesDiscovery.get_action_rules_representation():
print(rule)
print(“ “)
我们发现的一个规则的例子
r = [(Partner: no) ∧ (InternetService: fiber optic → no) ∧ (OnlineSecurity: no → no internet service) ∧ (DeviceProtection: no → no internet service) ∧ (TechSupport: no → no internet service) ] ⇒ [Churn: Yes → No] with support: 0.06772682095697856, confidence: 0.5599898610564512 and uplift: 0.05620874238092184.
我们发现了一个有趣的现象,没有互联网服务的单身(合作伙伴=否)电信客户流失的可能性约为 5.6%,支持度为 6.7%,信心为 55%。
从商业角度来看,这表明我们可能需要在短期内降低向单一客户(合作伙伴:否)积极营销附加互联网服务的力度,以减少客户流失,但我们最终需要设计一个更好的针对未来人口的营销策略,因为我们仍然希望像电信公司一样销售尽可能多的附加互联网服务。
上面有代码示例和结果的笔记本在这里:
请随意使用灵活的属性、置信度和支持最小值,因为修改这些超参数会产生不同的结果。
结论
我们看到了如何定义分类规则和动作规则、每个规则的置信度和支持值、固定属性和可变属性之间的差异,以及如何使用监督学习和 actionrules Python 包对动作规则建模的示例。
找到具有高度支持、信心和高度提升的行动规则,可以给业务涉众新的洞察力,让他们知道要采取哪些行动才能使某个结果最大化。
参考文献:
[1]s kora、Luká和 Tomákli EGR。"动作规则:Python 中的反事实解释."RuleML 挑战 2020。CEUR WS。http://ceur-ws.org/Vol-2644/paper36.pdf
https://www.kaggle.com/blastchar/telco-customer-churn
深度学习中的激活函数:从 Softmax 到 sparse max——数学证明
封闭解的稀疏最大求导及其损失函数
这篇文章有三个目的。第一部分讨论了 sparsemax 背后的动机及其与 softmax 的关系,总结了首次引入该激活函数的原始研究论文,并概述了使用 sparsemax 的优势。第二部分和第三部分致力于数学推导,具体寻找一个封闭形式的解决方案以及一个适当的损失函数。
1 .Sparsemax 概述
在论文“从 Softmax 到 Sparsemax:注意力和多标签分类的稀疏模型”中,Martins 等人通过引入 Sparsemax 提出了广为人知的 softmax 激活函数的新替代方案。
虽然 softmax 是输出 K 个概率的归一化概率分布的多类分类的合适选择,但在许多任务中,我们希望获得更稀疏的输出。Martins 等人引入了一种新的激活函数,称为 sparsemax,它输出多项式分布的稀疏概率,从而从分布的质量中滤除噪声。这意味着,sparsemax 将为某些类分配一个恰好为 0 的概率,而 softmax 将保留这些类,并为它们分配非常小的值,如 10⁻。Sparsemax 在大型分类问题中特别有用;例如,在自然语言处理(NLP)任务中,softmax 层对非常大的词汇集上的多项式分布进行建模。
然而,在实践中,将 softmax 函数变为稀疏估计器并不是一项简单的任务。获得这样的变换,同时保留 softmax 的一些基本属性(例如,评估简单、区分成本低并且容易变换为凸损失函数)证明是相当具有挑战性的。机器学习中绕过它的传统方法是使用 L1 罚函数,该罚函数允许关于输入变量和/或神经网络深层的某种程度的稀疏性。虽然这种方法相对简单,但 L1 惩罚影响神经网络的权重,而不是作为稀疏概率的目标输出。因此,Martins 等人认识到需要一个补充激活函数,即 sparsemax,他们将其公式化为一个可解的二次问题,并在一组约束下找到一个解,以获得与 softmax 相似的性质。
在深入研究 sparsemax 实现背后的证据之前,让我们首先讨论这篇论文中几个重要的高级发现。以下要点总结了一些主要要点:
- Sparsemax 是分段线性激活函数
虽然 softmax 形状相当于传统的 s 形,但 sparsemax 在一维上是“硬”s 形。此外,在二维中,sparsemax 是具有整个饱和区(0 或 1)的分段线性函数。这里有一张图可以帮助你想象 softmax 和 sparsemax。
来自“从 Softmax 到 Sparsemax:注意力和多标签分类的稀疏模型”
- Sparsemax 损失与分类 Huber 损失相关
二元情况下导出的稀疏最大损失函数与用于分类的修正 Huber 损失直接相关(定义见 Zhang,Tong。基于凸风险最小化的分类方法的统计行为和一致性。《统计年鉴》,第 56-85 页,2004 年和邹、惠、朱、纪和哈斯蒂、特雷弗。边缘向量、容许损失和基于边缘的多类分类器。斯坦福大学技术报告,2006 年)。也就是说,如果 x 和 y 是 sparsemax 之前的两个分数,使用 sparsemax 层和 sparsemax 损失,其中 t = x - y ,并且不失一般性地假设正确的标签是 1 ,我们可以表明:
这是一个很好的性质,证明了 sparsemax 的理论基础;胡伯损失是 L1 和 L2 损失之间的权衡,这正是我们试图从 softmax 激活中获得的,同时包括稀疏性。此外,这种与 Huber 损失的相似性可以通过将该损失与其他标准分类损失进行比较来证明:
来自“从 Softmax 到 Sparsemax:注意力和多标签分类的稀疏模型”
在上图中,你可以看到对于 t 的负值,即对于大误差的情况,损耗与误差成线性比例关系,类似于铰链损耗。然而,随着 t 收敛于 1,即误差减小,我们观察到*方关系,类似于最小*方损失。
- 随着类别数量的增加,Sparsemax 可以提高性能
sparsemax 框架已经被证明在具有大量标签的数据集上表现得特别好。在下面的示例中,您可以在表 1 中看到几个数据集及其详细信息,在表 2 中可以看到不同激活函数,即 sigmoid、softmax 和 sparsemax 的微观*均/宏观*均 F1 分数。我们观察到,随着标签数量的增加(即较低的行),与 softmax 相比,sparsemax 的性能提升变得越来越明显。
表 1:数据集描述(来源)
表 2:数据集上的性能基准(ssource
- Sparsemax 可用于注意力模型,以提高潜在的性能和更好的可解释性
稀疏输出的想法也可以在具有注意力机制的深度学习模型中得到利用,这是一种在潜在的大量实体上计算注意力权重的神经网络。这种注意机制在翻译或语言建模等 NLP 任务中被证明是特别有效的,这导致了所谓的转换器、即利用自我注意的非递归模型架构的创建(更多详细信息请参见 Attention Is All You Need,Vaswani et al .,2017 ),广泛用于 BERT 等最先进的语言模型(参见BERT:Devlinet al .的《深度双向转换器的语言理解的预训练》与 softmax 相比,从 sparsemax 获得严格的零概率具有完全消除一些隐藏状态(词)的影响的优势,如果它们被判断为不相关的话,soft max 中所有不相关状态的无穷小贡献的总和最终会累积,并会影响模型性能。此外,零概率,我们放大了注意力的一个主要优势:可解释性。使用稀疏分数有助于清理注意力地图,并阐明注意力系统是如何工作的。
然而,从经验上看,该论文报告了由于自然语言推理任务中的稀疏注意力而导致的仅小的性能提高。
表 3:注意力模型在 SNLI 数据集上的性能(来自论文
现在,我们已经强调了 sparsemax 的一些优点和论文的主要发现,让我们继续进行 sparsemax 背后的两个重要推导:即,找到其封闭形式的解以及其损失函数的方程。
2.稀疏最大激活函数
Softmax 综述
Softmax 是 sigmoid 对多类分类的推广。它使用 logit 变换将所有分数z映射到概率T3]p∈[0,1]:
概念上,对于一组 K 类, softmax 是将ℝᴷ的向量映射到δᴷ的概率分布,即映射到 K -1 维概率单纯形的函数。更准确地说:
值得注意的是,只有 K-1 自由度是必要的,因为概率总和总是 1。
Softmax 被定义为完全支持,即非零值输出,数学定义为
修改这个属性以允许零输出,这将使我们能够获得稀疏概率。
Sparsemax 的定义
作者将稀疏最大激活函数公式化为二次约束优化问题:
这相当于将其定义为 z 到概率单纯形δᴷ**上的欧几里德投影。稀疏性是由在投影期间命中单纯形边界的概率高引起的,因此使得某些维度为零。
封闭解
sparsemax 的上述定义可以以其封闭形式的解决方案写成
**
𝜏代表阈值函数。我们将在第 3 节一步一步地正式推导这个方程。
类似地,𝜏也可以用它的封闭解表示为
**
下面算法 1 的伪代码总结了这组等式,可以帮助更好地理解向量 z 的 sparsemax 计算背后的步骤:
来自“从 Softmax 到 Sparsemax:注意力和多标签分类的稀疏模型”
具有挑战性的部分是确定阈值𝜏(z);我们将在第 3 节的证明中回到这一点。最后,每个类别 i 的输出概率是 z 减去阈值𝜏 (z),如果值为正,则为,如果值为负,则为 0。
稀疏最大损失函数
最后,我们还想导出对应于 sparsemax 的损失函数;这将是第 4 节的一部分。虽然闭式解的第一个证明是直接从 sparsemax 的原始定义中确定的,但损失函数是一个偏好问题,可以采取不同的形式。我们来解释一下原因。
可以看出,结合 softmax 使用交叉熵损失(即多项式分布上的负对数似然),损失函数简化为
其中 k 等于真实标签的索引。
使用交叉熵损失和 softmax 的组合所带来的优点是将梯度简化为
**
这意味着在反向传播期间,评估 softmax(z) 对于正向和反向传递都是足够的,并且不需要额外的计算。这种行为也是我们希望在 sparsemax 框架中保持的属性。
然而,根据经验,这种设置对于 sparsemax 来说是不可行的。尝试将 sparsemax 与交叉熵相结合所产生的一个问题是,该损失函数现在需要完全支持,,即仅非零值输出。但是由于损失函数取概率的对数,如果一个概率严格为零,那么它的对数就没有定义。这就是为什么交叉熵损失不能用于稀疏最大激活函数。作者建议找到一个可微分的损失函数,它将满足一个类似的梯度表达式,即
通过添加进一步的约束,即当 S(z)={k} ,即只有正确的类是非零时获得的最小 sparsemax 损失为 0,我们可以表明 sparsemax 损失函数具有以下形式
3.证明 Sparsemax 闭型解的推导
目标
该证明的目的是证明以下等价性:
换句话说,我们要解决概率 p 和分数 z 之差的*方欧氏范数的 arg min 优化问题。这可以理解为从得分向量 z. 中选择δᴷ中最*的点
关于卡鲁什-库什-塔克(KKT)条件的提醒
卡鲁什-库恩-塔克(KKT)条件是数学优化中的一个概念。在给定一组特定约束的情况下,它们表示为了满足非线性规划解的一阶必要条件。在我们的 sparsemax 设置中,我们想找到某个函数 f : ℝⁿ → ℝ在一定条件下的极小点。
然后优化问题可以写成如下:找到使函数 f 最小化的 x ,使得 g (x) 和 h (x) 上的条件得到满足,即:
为了解决这个问题,我们首先需要定义拉格朗日函数 L(x,μ,λ) :
KKT 方法(在较高层次上)声明,给定拉格朗日函数 L,如果 (x,μ ) 是 L 的鞍点,具有μ ≥0 和互补松弛度μᵢgᵢ(x)≥0·∀I∈[0,n] ,那么 x 是上述优化问题的最优向量。**
具体地说,我们简单地寻找拉格朗日函数的梯度等于零的值,即:
衍生物
鉴于 sparsemax 是一个约束优化问题,我们用早期的符号【KKT】,即与 f , g 和 h 重写它如下:
那么拉格朗日函数的形式就是
我们现在可以对关于 x 的拉格朗日函数进行微分:
解变成了三个方程的系统:
第一个方程(1)来自拉格朗日函数的梯度为零。第二个等式(2)来自于原始松弛条件,即 μ≥0 以及来自于 p 是正概率向量。最后,等式(3)是互补的松弛条件。
随后,我们基于等式(2)和(3)区分两种情况。对于每个维度I∈【0,n】,或者 pᵢ > 0 从而μᵢ=0或者 μᵢ > 0 从而 pᵢ=0 。更准确地说,这意味着我们考虑两种情况:支持面的元素 S(z) ,其中 p > 0,和支持面外的元素 S(z) ,其中 p=0。**
当我们继续这个 sparsemax 的证明时,我们需要记住我们的目标是两件事:确定非零概率的值,以及确定概率为 0 的条件。因此:
在 1。第二。, zᵢ 要么比𝜏*大,因此 pᵢ 等于它们的正差值,要么 pᵢ 为零。因此, pᵢ=(zᵢ -* 𝜏 (z))⁺.**
此外,从等式(2)我们知道 ∑ ᵢ pᵢ=1 并且存在|S(z)|非零 pᵢ ,因此:**
这就结束了 sparsemax 闭型解推导的第一个证明。
4.证明二:Sparsemax 损失函数的推导
目标
第二个证明的目标是证明以下等价性:
换句话说,我们想要导出 sparsemax 的损失函数的梯度与 sparsemax 损失函数本身之间的等价性。
前题
在开始证明之前,我们需要定义一些重要的符号并建立两个重要的结果:
对于引理 1,我们可以直接计算𝜏关于 z 的偏导数。
实际上,如果 z ᵢ 在 S(z) 中,那么它将出现在分子和中,并且它的导数将与| S(z) |成反比;否则,导数将为空。
接下来,使用链式法则,我们可以推断出𝜏对 z 的导数:
注意,如果 j∉ S(z) ,那么𝜏 (z)=0 。
在引理 2 中,我们感兴趣的是所谓的过度自信 稀疏最大值,即当预测将 100%的权重仅分配给真实类 k 时。在这种情况下,我们有 spar semax(z,k)=δ_k 。这有两个后果,即:
衍生物
我们想要获得 sparsemax 的损失函数,使得
首先,让我们看看非矢量形式的 sparsemax 相对于 zᵢ 的偏导数:
****
我们于是可以推断,对于 K∈ ℝ :
剩下的最后一步是确定积分常数。我们可以简单地选择 K=0 ,梯度仍然是正确的,但是我们可能会有一个更合适的解决方案。这就是我们使用上面定义的第二个引理的地方。在完美预测的情况下,我们希望损失等于零,类似于 softmax 或其他损失函数,如 MAE/MSE。
更准确地说,我们需要满足以下要求:
因此:
最后,我们得出:
这就结束了关于 sparsemax 损失函数的推导的第二个证明。
5.结论
在这篇文章中,我们介绍了 sparsemax 激活函数背后的思想和数学公式,它允许比传统 softmax 更稀疏的输出域。我们首先总结了 Martins 等人论文中的一些关键发现,从经验上得出结论,随着类别数量的增加,sparsemax 可以提高分类模型的性能。此外,性能提升以及更好的解释能力在用 sparsemax 训练的 NLP 注意力模型中普遍存在。最后,文章的主要部分致力于 sparsemax 背后的两个重要证明;即导出封闭形式的解和基本的损失函数。