非政府组织如何在不破产的情况下利用人工智能
人工智能不是——也不应该——只留给最赚钱的企业。
这篇文章最初是在 TechHQ 上 发表 。增加了插图。
当你想到利用人工智能(AI)的组织类型时,非政府或非营利组织(NGO)不会跃入脑海。
人们经常看到大型科技公司和风投支持的公司在拓展人工智能的可能性。由于资源和员工时间有限,对人工智能的投资似乎超出了非政府组织的能力范围。
然而,也有非营利组织利用人工智能取得惊人成果的例子。只要看看 Wildbook 就知道了,这是一个由保护技术非营利组织 Wild Me 开发的开源平台。
Wildbook 利用人工智能通过它们独特的皮毛图案或其他标志性特征来识别单个动物——它们帮助世界各地的保护主义者识别濒危物种,如 猎豹鲸鲨 和 长颈鹿 。
识别个体鲸鲨:野生本
人工智能不是——也不应该——只留给最赚钱的企业。它可以帮助推动非政府组织内部的创新,并帮助解决我们今天面临的许多最棘手的环境和社会问题。
根据这份 Salesforce 报告,非营利组织对人工智能的使用预计将在未来两年增长 361%。
但是上面的例子更多的是一个例外而不是常态。现实情况是,大多数非政府组织没有利用人工智能,或者他们不知道从哪里开始。当拥有数百万美元预算的企业无法有效使用人工智能时,非政府组织如何用最少的资源做到这一点?
强大的用例
将人工智能应用于社会公益:图片来源:麦肯锡报告
非政府组织应该从人工智能的需求开始,问问自己想做什么。
它们需要自动化吗?人工智能可能能够使用计算机视觉来识别野生动物 识别 动物并跟踪它们的运动,但它也可以帮助非营利组织优化他们的内部流程并疏导宝贵的资源——它可以帮助他们决定在哪里建立学校或者如何优化土地使用 。
非政府组织也可以根据过去的数据,使用人工智能来预测未来的事件,如偷猎或砍伐森林。这使他们能够主动做出决策,防患于未然。
例如,Terrafuse 通过将历史数据与实时卫星图像和模拟相结合来预测森林野火。非营利组织可以使用麦肯锡发布的报告来确定他们的需求。
收集数据
众包数据集的标签:企鹅观察
数据是 AI 的先决条件。在确定了他们的用例之后,非政府组织需要找到创造性的方法来收集相关数据,以训练他们的人工智能算法。
例如,一个希望训练人工智能识别大象的组织可以使用经过策划的开源 数据集 或公开的游客照片。
一旦他们有了数据,他们需要标记它。这也可以在众包的公共帮助下完成。难民例如, 开发了一款应用 ,让那些因冲突而背井离乡的人通过智能手机“训练”人工智能算法来赚钱。
寻找资源
物种分类公共 API 微软 AI for Earth
非政府组织可以通过寻找免费的 库 来快速跟踪他们的 AI 模型开发,这些库建立在流行的 机器 学习 平台 上。或者,他们可以遵循众包路线,利用公共帮助来建立模型。
例如,Kaggle,一个由数据科学家组成的在线社区,举办比赛来支持人工智能的发展。该平台定期与非政府组织合作举办比赛,如自然学家和野生动物学会 iWildcam 等,以解决物种分类的挑战。
作为建立人工智能模型的替代方案,非政府组织可以寻找现成的 API,提供公共的、现成的解决方案,如 微软 API。
固定支架
非政府组织可以申请资金支持或免费计算资源来资助他们的工作。
像 微软 AI for Earth谷歌 AI for Social Good 和AWS Imagine Grant这样的倡议在全球范围内选择非营利组织,并提供财务、技术和实施支持。
毫无疑问,人工智能可以帮助非营利组织推进他们的使命,让世界变得更美好。然而,像任何组织一样,他们必须有一个计划来启动他们的人工智能之旅。
通过确保他们心中有一个明确的问题,为算法提供高质量的数据,以及一些财政支持,非政府组织可以充分利用人工智能所能提供的一切。
自然语言处理是如何发展成金融情绪分析的
资料来源:联合国人类住区规划署
我们还需要人类去阅读无聊的财务报表吗?
机器学习模型旨在学习其输入数据的良好表示,以执行其任务。近年来,模型学习用自然语言处理(NLP)来表示单词的方式已经发生了变化,在本文中,我们将探讨模型如何理解语言以做出财务决策的显著变化。
我们关注 NLP 在金融市场中的直接应用:自动对文本文档进行情感分类,从而做出快速准确的投资决策,避免人为偏见。
为了更有意义地比较不同的技术变革,我们使用了一个金融短语库 [1],其中包含带标签的金融短语(如下例所示):
来源:好债还是坏账:检测经济文本中的语义指向[1]
词汇袋/词典方法
金融情绪分类的创始人:蒂姆& # 183;拉夫兰和比尔& # 183;麦克唐纳。来源
如果我们想让一个 8 岁的孩子解释上面的短语,我们可以给她一个带有积极、中性和消极标签的单词列表,并让她告诉我们文本中是否包含这些单词——这基本上就是词典方法。最流行的金融词典是拉夫兰·麦克唐纳词典。如果您有兴趣尝试一下,请使用这个运行速度非常快的代码片段。
使用 LM 的整体准确性并不高— 61% [1]。因此,尽管我们可以快速地对一个文本序列进行分类,并理解我们为什么要对它们进行分类,但我们仍然非常依赖那些在字典中有一席之地的单词。即使这样,单词也只有一维。也许在更高的维度上,比如 300,我们会有更好的结果来代表每一个单词?
嵌入
嵌入将序列中的每个单词投影到多维空间中。我们可以把嵌入想象成一个宽的查找表——我们有 300 列,单词充当查找索引。
以埃隆·马斯克最近影响市场的推文为例
SOTA 嵌入很可能是 ELMO 的[2]语境嵌入,即嵌入考虑到单词及其周围的语境。嵌入有三个组成部分:两个来自双向上下文表示,一个是上下文无关的表示。
如果 Elmo 在 NLP 中每次有人用他的名字都会收到一分钱。资料来源:联合国人类住区规划署
嵌入本身仅仅是表象——仅仅是表象并不能对情感进行分类。因此,我们必须训练一个模型,使用嵌入作为输入,并学习预测情绪。我找不到任何测试短语库的论文,所以我在这里做了一个快速实验。
侧:没有我想象的那么快——张量流/keras 比我记忆中的要更不确定/痛苦。最后,我从一个名为 pymagnitude 的即插即用库中取出了这些嵌入,并使用了我可信赖的 ol’random forest。
整体准确率上升到了 **78%。**比 LM 字典高,但还是不邪乎。嵌入能够从单词创建多维表示,但是即使嵌入是上下文相关的,它也只是单层表示,不管维度有多大。是时候探索一种高维度的多层表示,即深度学习了。
深度学习
资料来源:联合国人类住区规划署
最近在架构和训练方法方面的进步极大地改善了深度学习模型学习语言和执行下游任务的方式。
transformer 架构和BERT【4】无需进一步介绍——参考这篇精彩文章了解更多信息——但简而言之,自我关注和令牌屏蔽的使用允许学习真正的双向上下文关系。
NLP 中迁移学习的使用最早是在ul mfit【5】中引入的,其中网络首先学习从庞大的文本语料库中预测最可能的单词,然后使用语言建模中预先训练的权重来执行其他任务——这导致了收敛性的改善,并减少了对庞大的带标签数据集的需求。
有一篇很好的论文,FinBERT ,将 BERT 和迁移学习应用于短语库,达到了 97% 的准确率!顺便说一句,如果你有兴趣看看如何使用 FinBERT 来交易企业申报情绪,我制作了一个视频,带你了解从解析申报到回测结果的整个过程!
下一步是什么?
资料来源:联合国人类住区规划署
我们完事了吗?当我们啜饮马提尼酒时,机器能分析金融文件并产生准确客观的情绪吗?我们是否不再需要人类分析师来仔细阅读大量财务报表,并时刻警惕彭博的头条新闻?
不完全是。
当前的 BERT 模型存在实际限制,如计算成本随输入长度的二次增加——最大输入长度通常上限为 512/1024 个令牌。改革者和龙前是最近的论文,试图通过简化自我关注机制来解决。
此外,BERT 不能做心算——它只包含文本表示。这是机器完全理解和分析通常包含大量数字的金融文档的主要瓶颈。我发现的一篇论文试图用一个做基础数学的程序来增强 BERT——但在 BERT 能够进行人类水平的推理之前,可能要等待很长时间。* *更新:open ai 发布的 GPT-3 无需事先训练就能进行零炮计算!
最重要的是,金融文本可能是不明确的,并且通常需要文本本身无法提供的上下文知识 BERT 实现的高准确性是在人类注释者之间 100%一致的短语上。甚至人类都不同意的其他短语使得机器不太可能胜过人类分析师。更有可能的是,一种量化方法将主导市场,金融分析师通过机器学习得到增强,以做出准确、快速和客观的投资决策。
你认为金融情绪分析的下一步是什么?留下评论。
[1] Pekka Malo、Ankur Sinha、Pekka Korhonen、Jyrki Wallenius 和 Pyry Takala。2014.好债还是坏账:探测经济文本中的语义指向。信息科学与技术协会杂志 65,4 (2014),782–796。https://doi.org/10.1002/asi.23062arXiv:arXiv:1307.5336 v2
[2] Loughran,t .和 Mcdonald,b.《什么时候责任不是责任?文本分析、字典和 10-k。《金融杂志》第 66 期,2011 年第 1 期,第 35 期第 65 页。
[3]马修·彼得斯、马克·诺依曼、莫希特·伊耶、马特·加德纳、克里斯托弗·克拉克、肯顿·李和卢克·塞特勒莫耶。2018a。深层语境化的词语表达。在 NAACL。
[4]雅各布·德夫林、张明蔚、肯顿·李和克里斯蒂娜·图塔诺瓦。Bert:用于语言理解的深度双向转换器的预训练。arXiv 预印本 arXiv:1810.04805,2018。
[5]霍华德和鲁德。用于文本分类的通用语言模型微调。计算语言学协会(ACL),2018。
北美最大的杂货配送服务如何利用数据科学适应新冠肺炎
随着用户需求的增加,优化算法和利用机器学习来扩展复杂数据集的需求也在增加
Adobe Stock Photos 提供
Instacart 以独特的方式将零售购物和电子商务结合在一起。在全球化的疫情时代,越来越多的消费者使用网上购物来替代传统的杂货店购物。商店提供网上下单和提货服务。送货服务达到了历史最高水平。我很好奇 Instacart 的数据科学团队如何调整他们的计划,并解决他们最初在 2019 年提出的挑战。
根据 Instacart 高级数据科学家is hant Nayer的演讲,在 DSSInsider 上观看 完整视频,并与我一起参加 DSS 零售/Ecomm 虚拟体验。
Instacart 是什么?
Instacart 是一家零售和电子商务公司,在美国和加拿大提供杂货交付和提货服务。你可以通过他们的手机应用程序或网站使用这项服务。Instacart 作为一个四方市场运作,服务于客户、零售商、第三方市场和购物者。你可以选择各种食品杂货、酒类、医疗保健和个人用品。
工作原理:
- 输入您的邮政编码,查找当地参与的零售商,如 Pulix 或 Safeway
- 选择您的商品并在一天中的任何时间下订单
- 购物者去商店为你收集商品,并把它们送到你家门口
数据挑战
该目录正在接收和创建可供客户使用的商品的所有数据。该数据目录包含来自北美 20,000 家商店的 300 多家不同零售商的 5 亿多种商品。这是一个庞大的数据集,每天都要处理并保持干净。这些物品中的每一个都有大约二十到三十种不同的属性,例如,价格、大小和位置。该目录在规模上变成了一个非常复杂的数据集,包含了所有的属性。有两类主要的属性需要组织。这些数据来自零售商、CPG 制造商和第三方整合商。
店铺特定属性:产品价格、供货情况、库存
产品特定属性:图片、位置、重量、尺寸、是否按单位或磅出售、营养信息
什么会出错?对于所有这些复杂的数据集,有时会出现产品描述与图片不匹配、没有图片或产品分类错误等问题。
解决方案
让一个人全天候坐在电脑前试图捕捉每一个错误是不可能的。算法需要每天定期捕捉这些问题。每个产品属性至少有 10-15 种算法。Instacart 还使用定义的试探法来告诉团队哪些地方不准确。该团队定义什么可能是错误的,然后开发数据的真实来源,并为产品设置检查。
为了帮助产品转换,该团队还需要确保图像是高质量的,由地区测量标准准确定义,以适当的销售单位列出,并用品牌正确命名。正在开发图像检测模型来修复图像,并帮助改善我们零售商的真实数据来源。这将能够从图像中提取文本、品牌名称、营养信息和产品描述。当能够扩展该解决方案时,它将提高我们的数据质量,并波及到业务的其他技术方面。
Instacart 如何适应 COVID 挑战
问:在 COVID 期间,Instacart 如何进行整体调整以服务客户?
Ishant: Instacart 很好地适应了 COVID 时代的消费者需求。他们加入了新的零售商,这意味着他们的目录中增加了数百万件新商品。Instacart 的主要主张来自于这样一个事实,即他们允许零售商添加具有任何类型信息的任何商品,并且他们将使用他们的目录系统来处理这些商品,以满足 Instacart 的要求。正如我在上面的话题中所讨论的,困难的部分已经在去年过去了。从现在开始,只是增加新的自动化零售商。由于 COVID 的限制,许多人开始使用 Instacart 来满足他们的杂货需求,Instacart 可以快速满足这些不断增长的用户需求。
问:在 COVID 期间,领导者如何利用数据作为工具来应对挑战?
Ishant: COVID 改变了购物、房地产购买、流媒体和更多行业的许多趋势。对于领导者来说,倾听客户的意见非常重要,而数据是做到这一点的最佳资源之一。关键绩效指标(KPI)是一组指标,领导者密切关注这些指标以了解其业务的健康状况。从我作为数据科学家的职业经历来看,每个领导者都会查看关于他们的业务指标和预测趋势的每日报告,以了解他们的位置和下一步该做什么。在 COVID 期间,定期听取您的分析团队和他们的见解是领导者保持领先地位必须做的事情之一。这将有助于他们管理资源和运营,并了解公司下一步的工作重点。对于 Instacart 来说,数据帮助他们了解需要雇用多少人才能满足不断增长的需求。
问:作为一名数据科学家,在 COVID 期间,您如何看待复杂数据集的管理变化?
Ishant:数据集的管理总是在变化并适应当前的情况。这是他们的基本法。在 COVID 期间,许多公司改变了策略以满足客户的需求。这意味着模型和数据集在不断变化,以保持最新,并持续提供客户现在所要求的内容。
结论
新冠肺炎改变了购物行为,网上订单的数量在过去几个月里显著增加。利用数据科学,Instacart 能够扩展其交付服务并适应不断增长的在线购买数量,而不会影响服务质量。Instacart 中的算法能够检测产品描述中的错误或在线目录中产品的错误分类,从而避免分析团队花费冗长的工作时间进行手动错误检测,并使他们能够专注于获得有价值的见解,以做出更好的决策,并从根本上改善整体客户体验。
如何不被数据科学淹没
让数据科学再次变得有趣
马修·费雷罗在 Unsplash 上的照片
动机
如果你想学习数据科学,有许多资源可供你学习。由于学习数据科学的需求很高,因此有成千上万的数据科学课程、书籍、图书馆来帮助初学者进入该领域。
这很好,因为你不需要自己解决所有问题。但这也带来了不利的一面,那就是你成为了不知所措的资源,不知道从哪里开始。
即使是对一些数据科学概念比较熟悉的人,很多人还是觉得自己是初学者,尽量多上一些课程,掌握所有的概念和技术。
如果你的目标是掌握数据科学中的所有概念和工具,你将永远无法实现。
更聪明地工作,而不是更努力
相反,你可能想要的是拥有相关知识,从你正在处理的数据中获得洞察力,并为你的公司交付理想的结果。这个目标是可以实现的,这篇文章将向你展示如何让自己了解对你来说重要的事情。
从一个问题开始,然后寻找资源来回答你的问题
不要学习很多数据科学的课程,而是掌握基础知识,然后开始解决项目。你可能不知道处理项目的所有步骤。没关系,事实上,这是意料之中的。
通过参与现实世界的项目,你将开始问一些现实的问题,例如
- 我的数据有许多特征,我应该保留所有这些特征还是只挑选相关的特征?
- 我的数据有很多空值,有没有一种算法可以不用处理这些空值?
- 如果我想预测一封电子邮件是否是垃圾邮件,我应该从哪里开始?我应该使用哪种算法?
一旦你形成了这些问题,你就可以开始在谷歌上搜索答案。你会惊讶地发现有这么多有用的资源,比如博客帖子、Youtube 视频、关于这个主题的书籍。
没有一个好的资源。只需选择一两个,然后将你学到的知识应用到你的问题中。
通过玩基础游戏来学习
一旦你找到了一些潜在的资源,你如何着手阅读这些文章或文档而不感到困惑呢?
在一些文档或博客中,可能会有很多针对初学者和高级用户的内容。有时它提供的比你实际需要的更多。
所以如果你刚学了一个新工具,试着找一个讲解基础知识的教程。介绍该工具的文章或文档中的入门部分都可以。
一旦您对该工具的功能和使用方法有了基本的了解,您就可以通过更深入地研究文档来建立另一层理解。
看到你的问题用你刚刚学到的新知识解决了,你会感到有收获!
把有用的文章留到以后
文章是学习不同数据科学概念和工具的好方法。但是你也很容易迷失在每天新的文章数量中。
而不是读了很多文章然后忘记它们。看几个,实际应用。尝试本文中介绍的概念或工具,它们可能对您当前的项目有益。
但是如果你读了那些可以作为未来参考的文章呢?我曾经使用 Instapaper 来组织我的文章,但是当我保存的文章数量变大时,我的文章就会丢失。我意识到我很少回头去看我保存的文章。
使用 Github 问题解决了我的问题。
Github 有一个 Issues 选项卡,允许用户请求关于现有代码的问题。我发现使用 Github issues 对我保存中型文章非常有效,因为它使我能够
- 整理我的文章,以便很容易找到我的文章以备将来参考
- 不看整篇文章,快速复习文章重点
- 总结的艺术将帮助我更好地保留和理解信息
如果你想学习如何使用 Github issues 来保存你的文章,请查看这个资源库或这篇文章。
Github 恒星应该属于不同的星系
您可能会启动有用的 Github 存储库,供将来使用。但是由于你不能用 Github stars 分类,所以当你需要的时候,从你的一堆标有星号的回购中找到一个特定的回购是极其困难的。
我曾经害怕主演更多的储存库,直到我发现了星体。 Astral 从 GitHub 下载你所有的标有星号的库,并允许你使用一个简单的&直观的标记系统来组织它们。
每当你想搜索一些为你所寻找的服务的存储库,例如 NLP,你可以通过点击标签很容易地找到 repo!
如果您想将该工具与您启动的其他类似工具区分开来,您还可以记下该工具的内容。
结论
有许多学习数据科学的资源,但这不应该让你感到不知所措。创建一个有效的系统来筛选出首先要学习的重要内容,并保存你想在未来尝试的资源,这将使你不那么不堪重负。
通过这些方法,我能够快速学习对我的数据科学项目很重要的新工具和概念,并利用新知识改进我的工作流程。
如果你每天都接受新事物和学习小东西,数据科学是一个有益的领域。
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 T2 Twitter 上与我联系。
星这个回购如果你想检查我写的所有文章的代码。在 Medium 上关注我,了解我的最新数据科学文章,例如:
我努力为数据科学贡献时间。但是发现新的策略使我能够提高我的学习速度和…
towardsdatascience.com](/how-to-learn-data-science-when-life-does-not-give-you-a-break-a26a6ea328fd) [## 如何在 VSCode 上使用定制的代码片段来提高效率
与其为同一段代码复制,为什么不把它保存起来以备将来使用呢?
towardsdatascience.com](/how-to-boost-your-efficiency-with-customized-code-snippets-on-vscode-8127781788d7) [## cy thon——Python 函数的加速工具
当调整你的算法得到小的改进时,你可能想用 Cython 获得额外的速度,一个…
towardsdatascience.com](/cython-a-speed-up-tool-for-your-python-function-9bab64364bfd) [## Yellowbrick 简介:可视化机器学习预测的 Python 库…
您将 f1 分数提高到了 98%!但这是否意味着你的模型表现更好呢?
towardsdatascience.com](/introduction-to-yellowbrick-a-python-library-to-explain-the-prediction-of-your-machine-learning-d63ecee10ecc) [## 网刮电影数据库与美丽的汤
利用你的数据库预测下一部热门电影
medium.com](https://medium.com/analytics-vidhya/detailed-tutorials-for-beginners-web-scrap-movie-database-from-multiple-pages-with-beautiful-soup-5836828d23)
如何不构建数据科学项目
项目
我一路走来所犯的错误,以及你如何在下一个项目中避免这些错误。
数据科学项目的绝对禁忌(由迪米特里·豪特曼在 Unsplash 上拍摄)
我知道我做错了。
我已经积累了一系列有趣而实用的项目。我有几门在线课程来展示我学到的东西。我甚至建立了一个作品集网站来展示我所有的项目和文章(你可以在这里访问)。
但是,我仍然觉得我的知识有一个缺口。一个巨大的,裂开的,裂缝大小的洞。我觉得等式里缺少了一些重要的东西。
就在那时,我在 YouTube 上看到了一些关于从头开始构建端到端数据科学项目的非常棒的播放列表。一些很好的例子是 Ken Jee 的这个,Daniel Bourke 的这个和 Data Professor 的这个。(向所有人大声喊出一些绝对精彩的内容!)
我意识到我需要开始一个端到端的数据科学项目,stat(一语双关)。尽管一开始会感到不舒服,但亲自动手并投入其中是学习新事物的最佳方式。
所以我就一头扎了进去。
直到我卡住了。又来了。
再一次。
再一次。
但是最后,经过几个小时的辛苦工作,几十次堆栈溢出搜索(感谢上帝的堆栈溢出)和在遇到一大堆错误后沮丧地用头撞墙(这没有多大帮助),我完成了。
你可以在这里查看我的最终项目。这是一个数据科学工资预测器(受 Ken Jee 的播放列表的启发和指导)。我也在做几个我自己的,这一次没有参考或指导,真正推动自己超越我理解的感知极限。
在构建这些项目的过程中,我学到了很多东西,不仅仅是从数据科学的角度,还包括如何首先解决构建这样一个项目的问题;一次又一次地犯很多错误并从中吸取教训。
以下是我以前犯过的一些错误,以及在你的下一个项目中如何避免这些错误:
错误 1:没有把我的项目做成端到端的。
通常,花费在数据科学实际应用上的大部分时间都是在数据清理和准备上。事实上,人们普遍认为大约 80%的时间花在清理数据并将其转换成适合进一步分析的形式上。
尽管可能很烦人,但数据清理是数据科学生命周期中必不可少的一步。并不是所有你在实际工作或实习中可能用到的数据集都像 Kaggle 数据集一样干净,可以随时使用。
它可能会很乱,你的工作可能是清理它,使它可以使用。
项目中同样重要的部分是生产和部署项目。最近我越来越多地听到这样一句话:
我们的项目不应该在 Jupyter 笔记本上结束它的生命。
构建其他人可以访问的项目和产品是数据科学的主要用途之一。
Jupyter 笔记本中的一堆代码通常没有实际用途,但是使用强大且易于使用的工具(如 Streamlit 或稍微复杂一点的工具(如 Flask )来构建一个简单的 Web 应用程序,以展示您所构建的内容,只需一点点额外的努力,就可以让人们更容易地看到您所构建的内容。
从坚实的基础开始,以切实可行的产品结束,这一点非常重要。
专业建议:获取你自己的数据(如果有必要的话,可以从网上搜集)。清理它,预处理它,做一些特征工程。别忘了用 Streamlit 或 Flask 来生产你的项目。
错误 2:没有把时间花在最重要的事情上。
帕累托原则(也称为80–20 法则)指出,对于许多事件来说,大约 80%的结果来自 20%的原因。类似地,在一个项目中,大约 80%的价值来自你做的 20%的事情。同样,这也意味着你可能做的 80%左右的事情并没有真正增加价值(只有 20%左右)。
我过去常常花很多时间思考和分析我的项目可以采用的不同选项或不同路径。
我不应该。
我应该开始做点什么。我本可以稍后处理选择错误的后果。
我浪费了很多时间的一个简单例子:云提供商。
如果到目前为止你和我在一起,使用 Streamlit 或 Flask 制作一个项目是非常重要的。但是,同样重要的是,部署该项目以便每个人都可以访问它。
有很多方法可以做到这一点。
我开始着迷地分析和研究所有不同的选项来帮助部署我的项目。查找 AWS 和 GCP 之间的所有差异,各自的优缺点,它们提供什么实例,我可能会产生什么成本,等等。
直到我意识到我犯的错误。我只是不得不部署它。在哪里并不重要。
所以,我在 Heroku 上免费部署了它。(他们允许一次免费部署,我很大方地使用了它)。
下一次,我将把它部署在我认为最容易的地方。没有二心。
亲提示:停止思考,开始行动。利用 80-20 法则。
错误 3:没有计划最终结果会是什么样子。
如果我现在已经成功地让你相信生产化和部署是你的项目生命周期中非常重要的步骤,以及 80-20 法则的力量,那么另一个同样重要但经常被忽视的步骤就是计划最终的结果。
好吧,让我们假设到目前为止你已经同意了我的逻辑,并且你已经决定要构建一个展示你的项目的 web 应用程序。
但是这个应用程序要做什么呢?
问自己一些关于用户界面的问题,例如:
- 它从用户那里得到的输入是什么?
- 在中,你将采用什么形式输入?
- 你的模型会有什么样的最终结果?
- 输出将以什么形式出现?
- 我可以添加哪些附加功能来改善用户体验吗?
- 有些事情是我应该不惜一切代价避免的吗?
在我的数据科学工资预测项目中,我犯了一个严重的错误,没有考虑最终的界面及其布局。当我最终到达那个阶段时,我发现用户的分类输入对我的模型没有意义,所以我不得不返回并将某些分类变量更改为顺序变量,在这个过程中浪费了一些宝贵的时间。
一开始就回答这些问题将会为你以后节省大量的时间,也可以避免你不必要地在不同的步骤之间来回奔波**。我在这里使用“不必要”这个词是有原因的,这让我想到了第四个错误。**
专业建议:无论以何种形式开始,对最终结果都要有一个大致的概念。如果有必要的话,在某个地方画出来。
错误 4:没有回到之前的阶段。
数据科学生命周期(鸣谢: Chanin Nantasenamat 与 Ken Jee 合作)
通常,任何项目都可以分为这 5 个主要阶段:数据收集、数据清理、探索性数据分析、模型构建和模型部署。
但是我犯的一个主要错误是认为这个过程是一系列线性的步骤,而事实上,它是一个迭代的,经常是循环的过程。
例如,在我的数据科学工资预测项目中,当我处于模型构建阶段时,我想到了一些我可以添加的更有趣的功能,作为我的模型的输入。
那我做了什么?
我一直回到数据清理和预处理步骤,不得不做一些额外的功能工程,不得不对新数据执行一些探索性的数据分析,并使用额外的功能构建另一个模型。
有时候,这些绕回来的可能是完全不必要的,比如第三个错误。
但有时,在处理数据一段时间后,你可能会有新的见解,在这种情况下,返回是正确的做法。
亲提示:在手之前尽可能多的做好计划,但是如果需要的话就圈回来。据你所知,这一点点努力可能会让你的项目变得更好。
错误#5:在项目部署后没有进行自省和评估
我完全忽略的一步,实际上可能是所有步骤中最重要的一步,是在你完成后评估你的项目。
看到哪些做对了,哪些做错了,下次如何改进。
在丹尼尔·伯克着手 Airbnb 项目后,我从他的视频中了解到这个非常重要的步骤。
花些时间,分析你项目的所有步骤,反省,从中学习,然后继续前进。
没有这一步,这篇文章就不会存在。这里列出的错误是我从我的项目中学到的,我几乎可以肯定,任何人在从事自己的项目时都会犯一些错误。从中吸取教训,确保下次不会重蹈覆辙,继续前进。
亲提示:回去看看哪里做对了,哪里做错了,从中吸取教训。
犯错误没关系,只要你能从中吸取教训—匿名
最重要的是:别忘了一路上要开心。
随时联系我 LinkedIn ,查看我的GitHub了解我做过的项目,或者我个人的 网站 了解我所有的工作。
如何(不)通过隐式转换来降低 SQL Server 的性能
了解如何避免性能杀手并帮助 SQL Server 为查询选择最佳执行计划
莎拉·瓜尔蒂里在 Unsplash 上拍摄的照片
在我最近的文章中,我研究了使用 DATETIME 和 DATETIME2 数据类型之间的*【优点】**【缺点】*。这项调查似乎让我大开眼界,因为在阅读关于这些数据类型和使用 DATETIME2 时的潜在缺点的文档时,我发现了一组我需要注意的全新内容!
什么是隐式转换?
简而言之,隐式转换发生在 SQL Server 需要自动将部分数据从一种数据类型转换为另一种数据类型的时候。
在某些情况下,当您执行 JOIN s 或使用 WHERE 子句过滤结果时,您正在比较“苹果”和“橙子”——因此,SQL Server 需要将“苹果”转换为“橙子”,反之亦然。
为什么隐式转换不好?
为了解决数据类型之间的不一致,SQL Server 必须付出额外的努力并消耗更多的资源。因此,性能会受到影响,导致索引的低效使用和 CPU 的大量使用。
但是,理论已经足够了,让我们来看看隐式转换在现实中是如何影响性能的。
真实用例
我有一个包含客户发起的聊天数据的表格。这个表大约有 860 万行。其中一列是*“SourceID”*,是来自源系统的聊天 ID。在我的表中,该列是 VARCHAR(20) 类型,尽管所有值都只包含数字。
我在 SourceID 列上有一个惟一的非聚集索引,在 DatetmStartUTC 列上有一个索引(该索引包括所有其他外键列),所以让我们运行几个查询来检查后台发生了什么。
我还打开了 IO 和时间的统计,以便能够比较结果。最后,我打开了实际的执行计划,以便更深入地了解查询执行中的每一个具体步骤。
问题 1 又名“黑仔”
当有人在该表中执行简单的数据分析,并且只看到 SourceID 列中的数字时,完全可以编写这样的查询:
DECLARE @sourceIDi INT = 8000000
SELECT sourceID
FROM factChat
WHERE sourceID >= @sourceIDi
SQL Server 返回大约 822,000 行,这大约是整个表中数据的 10%。
人们可能会认为 SQL Server 在 SourceID 上使用了索引,但是让我们检查一下情况是否如此:
正如我们所注意到的,SQL Server 使用我们的索引,但是它没有选择执行预期的索引查找操作,而是扫描索引。如果我们将鼠标悬停在索引扫描步骤上,我们将在谓词窗格中看到发生了隐式转换,因为 SQL Server 必须在查询过程中在后台应用数据转换。
该操作对性能有许多额外的影响——仅看一些逻辑读取和 CPU 成本,我们就可以得出结论,这与最佳性能相差甚远:
问题 2 又名“好人 1”
现在,让我们检查当我们向 SQL Server 提供匹配的数据类型时,它是如何反应的:
DECLARE @sourceID varchar(20) = '8000000'
SELECT sourceID
FROM factChat
WHERE sourceID >= @sourceID
现在,SQL Server 按预期执行索引搜索,所以让我们另外检查 SQL Server 在后台做了什么来获取我们的结果:
哇,逻辑读取和 CPU 时间减少了近 10 倍!也正因为 SQL Server 在查询过程中不必努力应用隐式转换。
现在,想象一下大部分数据(记住,这个查询只返回表中 10%的数据)或大表的性能差异。
问题 3 又名“好人 2”
现在,我想向您展示帮助 SQL Server 做它最擅长的事情的另一种方法——选择执行查询的最佳计划。
我们仍然可以使用 INT 数据类型,而不是在我们的变量定义中给 SQL Server 正确的数据类型,但是我们可以稍后 显式地 告诉 SQL Server 我们想要比较“苹果”和“苹果”(在我们的例子中,VARCHAR 和 VARCHAR):
DECLARE @sourceIDi INT = 8000000
SELECT sourceID
FROM factChat
WHERE sourceID >= CAST(@sourceIDi AS VARCHAR(20))
我们在这里做了什么?我们明确地通知 SQL Server 我们希望他做什么:将 VARCHAR(20)列 SourceID 与变量的 VARCHAR(20)值进行比较。
SQL Server 对此很感激,我们可以看看结果:
一开始,索引查找操作是存在的。让我们来看看统计数据:
数字与前一次运行中的相似,因此我们可以得出结论,这两次运行几乎相同。
结论
隐式转换可能是一个巨大的性能杀手,而且特别危险,因为它不是那么明显和容易发现。
因此,我推荐阅读 Jonathan Kehayias 撰写的这篇文章,其中他提供了一个非常有用的脚本,用于识别计划缓存中的隐式转换。
此外,如果您想确定何时发生隐式转换,请直接查看由微软提供的这个超级有用的表:
数据类型优先级
数据类型优先级可以在这里找到,这有助于理解 SQL Server 将如何处理数据类型转换。例如,INT 的优先级高于 VARCHAR,这意味着 SQL Server 会将 VARCHAR 转换为 INT,而不是相反。
因此,如果您将 INT 类型的列与 VARCHAR 类型的值进行比较,您的索引仍然可以使用,因为用于比较的列不需要转换。
此外,当比较来自同一“家族”的类型(例如,INT 和 BIGINT)时,SQL Server 仍然倾向于索引查找操作,因为它足够聪明,能够识别这些情况并使用适当的索引。
总之,作为一个 一般的经验法则 :不要指望 SQL Server 的“仁慈”或者用数据类型优先来挠头——数据类型应该尽可能匹配,或者比较最终应该使用显式转换来处理。
如何(不)在初创公司中错误管理人工智能
我从机器学习和早期创业公司的战壕中学到的东西
作为一名技术创始人,我在初创公司中建立并管理了 ML 的方向。
我也犯了很多错误。
许多起源于将 ML 视为软件开发。另一些来自创业公司本身的非结构化性质。
以下是我的一些心得。
不要建人工智能创业公司(如果可以的话)
不要把 AI 作为你的核心产品。而是用 AI 来补充一个现有的产品。
用软件或硬件解决一个问题,卖掉它,然后用人工智能扩充它。或者,如果你是一名人工智能专家,加入一家现有的初创公司,成为后期联合创始人。
这样,你已经坐在数据上,并有空间去实验。
对奥迪来说,开始研究自动驾驶汽车比研究一屋子人工智能博士更容易。后者需要获得专有数据,甚至在开始之前就建立行业联系。
机器学习最好专注于边际改进。也就是说,从 100%到 110%。
从自动化简单的东西开始
在 AI+领域建立能力需要时间,不管你以前有多少经验。
在 Kaggle 竞赛中对狗的品种进行分类(提前给你分类),并不一定会转移到一个真正的领域,在那里你需要自己想出类别。
一个好的策略是找到团队成员已经在做的重复性决策,并尝试自动化这些决策。具有现有 sop 的流程是理想的。
在解决改变游戏规则的问题之前,先培养自己的能力。有趣的是,如果人类很难吸收信息并做出决定,人工智能几乎不可能做到这一点。
AI 是自动化,不是魔法
不要指望把数据扔给神经网络,然后从另一边得到解决方案。这不会发生在大公司的新闻稿之外。
通常有一个巨大的软件工程组件与人工智能集成,堆叠在多个层上,即使从外面看起来很简单。
用 AI 解决小窄题,结合领域知识把这些堆在一起。
深度学习很少产生奇迹,但随着时间的推移,渐进的改进可以产生奇迹。
训练自己的模型
你的数据就是你的护城河。你辛辛苦苦收集的。
在内部训练你的模型,而不是从大型云提供商那里向人工智能服务提供数据。
他们非常乐意将从中得到的知识传授给任何其他付费的竞争对手。这不是你想要的。
对于核心产品之外的非常微小的改进,冒这个风险是值得的。但是一般来说,不要让任何人接近你的数据。
大多数时候,这并没有那么难。
人工智能不是目标,用钱为人们解决问题才是目标
我们已经过了提到“人工智能”就能在客户中获得额外加分的阶段。炒作太多了。
现在所有人都在假装用 AI。所以,把更多的精力放在解决客户的问题上,而不是展示酷的技术。
如果他们问起人工智能,很好。否则,拿他们的钱,解决他们的问题。
不管它是如何完成的,他们都会同样高兴。
总结所有的成功和失败
实验结束后,一定要写下实验的内容和结果。这包括疯狂的成功和彻底的失败。
员工会来来去去,大脑会忘记。知识很难用好的文档来传递。
所以如果你花了几天、几周或几个月在一个项目上。把它写下来,并牢牢记住这些知识。
结论
我的经验只适用于早期阶段的创业公司,在这种情况下,我们有能力依靠一毛钱,不需要说服一百个利益相关者去尝试一些东西。
我只能猜测,如果在一个更大的组织内部,有更多的经验法则要遵循。
如果你有这方面的经验,我很乐意在评论中听到。
如何(不)用 LSTMs 预测股票价格
股票和机器学习——天作之合。但是事情真的像看起来那么简单吗?
想成为一夜之间的百万富翁吗?这篇文章(不)适合你!【原始照片由卡罗琳娜·格拉博斯卡从派克斯,energepic.com从派克斯
就在不久前,我突然想到了一个绝妙且“原创”的想法——如果我能利用机器学习来预测股票价格会怎么样。毕竟,时间序列可以很容易地用 LSTM 建模。我可以想象自己一夜暴富!如果这这么容易,为什么还没有人去做呢?
我对自己的光明前景非常兴奋,我打开笔记本电脑,打开谷歌,键入“预测 LSTM python 的股票价格”结果纷至沓来——很快,我意识到我的想法并不新颖。好吧,就这么多了。无论如何,我浏览了许多这样的文章,每一篇似乎都获得了令人惊讶的好结果。但是教程到此为止——没有人用真钱来测试它。为什么这些人还没有成为百万富翁?有些可疑。
作为免责声明,注意本文内容无一是理财建议,纯属教育。很明显,我知道,但还是要说出来。恰恰相反,我在努力教育你如何不被这个愚弄,开始动动脑筋。
如今,随着股票和机器学习变得如此易于操作、易于使用和容易获得,不陷入这个陷阱变得非常困难,在这个陷阱中,对这两个领域不完整、不成熟的知识会让你陷入严重的麻烦。
让我们开始学习如何不使用 LSTM 来预测股票价格。这篇文章的流程如下:
- LSTMs 的简单介绍。
- 用 python 获取历史股票数据。
- 以适合 LSTM 模型的格式创建数据集。
- 用 TensorFlow Keras 建立和训练 LSTM 模型。
- 预测和解释结果。
LSTMs 简介
长短期记忆(LSTM)网络是一种通常用于预测时间序列数据的神经网络。简而言之,它们具有内存/缓存功能,这有助于它们了解数据中的长期依赖性和关系。因此,查看之前的 N 个数据点,他们可以通过学习模式来预测下一个(或下几个)点。
我会让这部分非常简单。如果你想更清楚地了解一个 LSTM 是如何工作的,我推荐你浏览一下,但是即使没有深入的理解,你也应该非常理解这篇文章的主旨和目的。
第一步:获取股票数据
在 python 中有多个选项可以访问历史股票价格,但是最简单的库之一是 yfinance 。非常方便和免费,它通过从雅虎财经搜集数据来完成工作。
*!pip install yfinance# Import the required libraries
import yfinance as yf
import pandas as pd
import matplotlib.pyplot as pltfrom pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()*
在本文中,我将讨论“Reliance”的股票价格,但这也适用于所有其他工具。
下面这段代码下载 Reliance 公司 15 年来的股票价格数据,分辨率为 1 天,并将其存储在 pandas dataframe 中。你可以根据你的实验改变这些参数。
打印出熊猫数据帧的头部,可以看到股票数据可用的各种参数。
熊猫数据框架顶部为 Reliance 股票数据
画出“收盘”价格以可视化数据,看看股票在过去几年中上涨得有多好。2020 年 3 月的急剧下降(由于 COVID)也是可见的。但它似乎战胜了这种衰落,再次上升到一个新的高度。
Reliance 股票数据的收盘价
**在这里问自己一个问题——你认为一个 ML 模型能够捕捉所有这些随机性吗?
步骤 2:创建数据集
现在让我们修正我们的问题陈述—LSTM 模型将看到过去 10 天(称为时间步长)的收盘价,并预测第二天的收盘价。
为了简单起见,我们只测试最后 200 天。我们可以用剩下的数据进行训练。我们有 3486 个数据点进行训练(将根据您执行代码的日期而增加)。
(注意,你可以根据自己的要求改变这一点,但我觉得这应该足以表明我的观点)。
*# Get Close data
df = data[['Close']].copy()# Split data into train and test
train, test = df.iloc[0:-200], df.iloc[-200:len(df)]print(len(train), len(test))
>>> 3486 200*
现在,我们需要标准化我们的数据。 人们在这个阶段常犯的一个错误是,他们也单独对测试数据进行归一化 。但是在实际场景中,测试数据将是实时的,所以你不会事先知道最小值、最大值或平均值!如果你给模型提供来自未来的信息,,你基本上最终提供了一个趋势或指导方针* ,预测价格需要遵循。我已经看到很多作者犯了这个错误,我不怪他们,因为我也花了一段时间才意识到这一点。*
为了解决这个问题,我们将使用最小和最大的训练数据来标准化测试数据。这应该是一个不错的近似值(当然,还有更好的方法,例如,只取最近 N 个价格的最小值和最大值)。
最后,让我们构建数据,以便我们的 LSTM 模型可以轻松地读取它们。LSTM 需要以*【样本,时间步长,特征】*的形式输入。下面的代码以这种需要的格式创建数据集。
步骤 3:创建模型并训练
对于我们的模型,我们将使用 python 中的 TensorFlow Keras 库。简单的序列模型有一个 LSTM 层,然后是一个下降层(以减少过度拟合)和一个最终的密集层(我们的输出预测)。我们将使用具有平均绝对误差损失的可靠的“Adam”优化器。训练它 50 个纪元左右。记住保持 shuffle = False(因为样本的顺序很重要——这是本文的重点:P)。
模型总结如下图所示。这个模型非常小,但是你可以试着再玩几层什么的。注意不要过度拟合数据(即使是这个小模型,数据也会过度拟合)。
我们的 LSTM 模式总结
训练后,将损失绘制为:
*plt.plot(history.history['loss'], label='train')
plt.legend();
plt.show()*
培训损失
随着时间的推移,训练损失明显减少(有些波动)。这位模特似乎训练有素。还是有?我们来评价一下。
第四步:预测!
通过模型传递测试集。重新调整结果(记住,我们之前已经对其进行了标准化),最后绘制出来,看看它在视觉上的表现如何。
看看下图中的预测!他们非常好!该模型似乎也预测到了 COVID 下降!这太棒了。我们现在可以在股票市场赚几百万了!
模型的预测
大部分教程到此结束。作者的遗言是“结果看起来很有希望,调整参数,改变模型,等等”。但是等等,在你辞职成为全职交易员之前, 让我们放大一下结果吧!
放大预测
你能看出现在发生了什么吗?预测价格落后真实价格 1 个时间步长。模型只是预测一个与它看到的前一个价格接近的值,因为这是对下一个价格的最佳预测。
我来帮你简化一下。让我们在下图中绘制一个滞后 1 天的真实价格值。看看图的形状是如何匹配的——现在可以更清楚地看到,我们的模型只是试图模仿它看到的最后价格。
该模型只是模拟了以前的价格值
**有什么问题吗?LSTM 没有做错任何事!如你所知,股票是相当动态和随机的(就所有实际目的而言)。该模型给出了一个 随机游走问题 的最佳可能猜测,结果是前一天的价格。但这意味着该模型没有预测任何对交易/投资有用的东西。这就是为什么在实践中盲目使用它是非常危险的。
总结词
我并不是说预测股价的任务是不可能的。这肯定是可能的——有几种算法和交易机器人,它们使用了一些机器学习——但这不会这么简单。
制定问题陈述、输入和模型需要更多的努力。一些好的方向是预测价值(一阶导数或二阶导数)的变化,而不是价值本身。仅预测股票价格变动(二元分类问题)可能是另一种选择。或者使用一组模型来实现组合/不同的目标。我建议你首先尝试在这些领域获得更强的领域知识,然后进行探索——不要把自己局限于这些想法或你在互联网上看到的其他想法。
我并不是说我是这些领域的专家——我只是提出了我对这个主题进行探索后得出的结论,所以请随意指出我的错误或补充我遗漏的任何内容。谢谢你的时间。
ML 模型真的能读懂可视化股价图吗?看看我下面的文章,看看结果!
股票和机器学习——天作之合。如果你的 ML 模型可以从字面上阅读价格图表…
towardsdatascience.com](/can-an-ml-model-read-stock-charts-and-predict-prices-fb73c551c7a4)
既然可以预测股市,为什么还要浪费时间和精力去预测呢……
连续 10 年跑赢指数!当您可以随机选择时,为什么还要费心预测/优化…
medium.com](https://medium.com/geekculture/a-monkey-picks-my-stock-portfolio-dc10fd665368)
或者,看看我的其他一些机器学习文章。我相信你会发现它们很有用……
使用 PyCoco、Tensorflow Keras Python…探索和操作 COCO 图像数据集进行语义图像分割
towardsdatascience.com](/master-the-coco-dataset-for-semantic-image-segmentation-part-1-of-2-732712631047) [## 创建一个合成图像数据集——“什么”、“为什么”和“如何”
缺少图像来训练你的模型?以下是如何使用合成图像将数据集的大小增加数倍…
towardsdatascience.com](/create-a-synthetic-image-dataset-the-what-the-why-and-the-how-f820e6b6f718)*
如何不进行 A/B 测试
偷看:为什么你不应该这样做!
想象一下下面的情况。您做了一些分析,发现两组之间存在巨大差异,这可能会为您的团队带来一些重大胜利。第一组平均转化率为 65%,而另一组平均转化率为 40%。那就是 37.5%的涨幅!
你决定做一个实验,只是为了确定第一组确实比第二组好,但是也要坚持实验设计一旦达到显著性就停止实验。
以下是一些可能发生的结果…
A/B 测试的目标是什么?
正如你们中的一些人可能已经猜到的,上面的图表是两枚硬币各翻转 100 次。他们中的每一个都有 50%的概率正面着地,但在一个小样本实验中,他们总有 50%的概率不会正面着地。
我们进行 A/B 测试的原因是不要等到有显著性(你很快就会看到,p 值很常见< 0.05 at some point of the experiment), but to come up with a system for rejecting or failing to reject the null hypothesis.
Often, a null-hypothesis is 控制组和治疗组之间没有差异)。
为了拒绝它,我们必须建立一个系统,在这个系统中,似乎不可能没有差别。从数据的角度来看,这可能更容易查看。
随着样本量的增加,我们的控制和处理会趋同还是趋异?
每组中的样本越多,就越容易区分两组是相同还是不同,因为两组样本之间的方差变小了。
实验 1——翻转相等的硬币
让我们试着抛两个硬币,每当 p 值低于 0.05 时做标记:
如果 p 值< 0.05
If we stopped the test as soon as we saw “significance”, or as soon as the p-value dipped below 0.05, then there are multiple periods in time that we could have ended a test early and declared a winner. “Blue really is better than orange!” But in reality, you and I both know that the coins have the same probabilities.
Why then did the p-value mislead us?
It’s called chance, or variance. Sometimes, the coins land a little more on heads than tails, or the reverse. If we are comparing two coins, they might go in different directions before converging back together. As you can see in the chart above, most of the time the p-value >为 0.05,绿线会从 0 翻转到 1,只有少数情况下会翻转到< 0.05。
这里还有两个这样的事件:
p 值示例< 0.05 at some point in time
We can see that had we waited, we would have been much less likely to have declared a winner since the two groups converge to 50%. This convergence is due to 大数定律、**、**正因如此,数据科学家喜欢大量样本,以便更清楚地了解分布的真相。
实验二——不公平硬币:硬币 1 有 0.5 的几率,硬币 2 有 0.6 的几率
在这种情况下,你对你的团队的实验不耐烦了,你想在一个月后结束。假设一个月只能让你每组参加 800 次活动…
当 coin1!= coin2
有时我们可能很早就看到了真正的不同,而其他时候我们不得不等待真正的改变实现。在某个点之后,p 值阶跃函数翻转并保持翻转状态。换句话说,一段时间后,我们变得相当确定确实存在差异,如果我们测试显著性,我们很有可能在我们越过事件视界时看到它。
实验 3——知道何时停止
在这里,如果您在仔细分析后计算出预期影响(效果大小)约为 4%,并决定使用 5%的 alpha 值和 80%的幂,您将最终需要 3856 个样本(遵循下面的样本大小计算器链接)。
当预期效果大小存在实际差异时:
万岁!你的实验成功了!
如果有一个好的实验装置,你很可能会看到它。
无差异时:
万岁!你的实验成功了!
幸运的是,你没有很早就得出结论说有区别,因为你一直等到你的实验结束。
当差异大于预期时:
仍然有效,但你浪费了时间。
当差异小于预期时:
仍然有效,但是你错过了选择一个成功的变体。我说还能用是什么意思?当你设置测试时,你说你期望 X%的大小。在这种情况下,真正的差异要小得多,您的测试表明,在给定的 X%下,我们不能说对照组和治疗组真的有那么大的效果,所以您无法拒绝零。
这些说明了了解预期效果的大小以及等待整个过程后再打电话是多么重要。如果效果大很多,你也不想浪费时间测试。如果效果尺寸更小,你可能会说没有区别。但是,如果效果大小为 0,在一个精心设计的测试中,你有 95%(或者你的 alpha 设置的倒数)可能拒绝错误的改进。
实验 4 —概率当它不显著时,我会说它显著
当它不重要时,我说它重要的概率是多少?
这在很大程度上取决于测试运行的时间和您查看的次数。但这里有一些例子:
peeks 1, samples 250
probability of saying it’s significant when it’s not: 0.042.peeks 2, samples 250
probability of saying it’s significant when it’s not: 0.079.peeks 3, samples 250
probability of saying it’s significant when it’s not: 0.085.peeks 10, samples 250
probability of saying it’s significant when it’s not: 0.114.peeks 250, samples 250
probability of saying it’s significant when it’s not: 0.174.peeks 500, samples 500
probability of saying it’s significant when it’s not: 0.219.peeks 250, samples 1000
probability of saying it's significant when it's not: 0.271\. peeks 500, samples 1000
probability of saying it's significant when it's not: 0.292.
基本上,如果你不断检查,你宣布一个错误的赢家的机会可以超过 30%。这比你原来打算的 5%要高得多。
结论
这里的要点是,你不是想什么时候偷看就什么时候偷看,而是在设定的时间后才偷看。这可以防止你根据实验开始时指定的数量做出假阳性或假阴性的声明。一旦你打破了这一点,你有假阳性或假阴性的机会上升。
即使有了硬币,也非常容易被甩开,进行虚假索赔。解决这个问题的唯一方法是利用统计数据并了解所需的样本大小。
代码:
https://gist . github . com/davidblaszka/534 f 88067379587 ff 6 c 06 da 4b 235 E1 cc
参考资料:
[## 如何不进行 A/B 测试
如果你在你的网站上运行 A/B 测试并定期检查…
www.evanmiller.org](https://www.evanmiller.org/how-not-to-run-an-ab-test.html)
样本大小计算器:
[## 样本量计算器(Evan 出色的 A/B 工具)
需要 iPhone 或 iPad 上的 A/B 样本大小吗?立即下载 A/B 好友。问:一门课程需要多少科目
www.evanmiller.org](https://www.evanmiller.org/ab-testing/sample-size.html) [## g *功率
这些页面是使用 GPower 版本 3.0.10 开发的。您可以从以下网址下载 GPower 的最新版本……
stats.idre.ucla.edu](https://stats.idre.ucla.edu/other/gpower/)
如何(不)使用机器学习进行时间序列预测:续集
时间序列预测是机器学习的一个重要领域。这一点很重要,因为有太多的预测问题涉及到时间因素。然而,虽然时间组件增加了额外的信息,但与许多其他预测任务相比,它也使时间序列问题更难处理。顾名思义,时间序列数据不同于其他类型的数据,因为时间方面很重要。从积极的方面来看,这为我们提供了在构建我们的机器学习模型时可以使用的额外信息——不仅输入特征包含有用的信息,而且输入/输出随着时间的变化也包含有用的信息。
我之前关于同一主题的文章如何(不)使用机器学习进行时间序列预测,已经收到了很多反馈。基于此,我认为时间序列预测和机器学习是人们非常感兴趣的,许多人都认识到了我在文章中讨论的潜在陷阱。由于对该主题的浓厚兴趣,我选择写一篇后续文章,讨论一些涉及到时间序列预测和机器学习的相关问题,以及如何避免一些常见的陷阱。
通过一个具体的例子,我将展示一个人如何表面上有一个好的模型,并决定将它投入生产,而实际上,这个模型可能没有任何预测能力。重要的是,我将更详细地讨论其中的一些问题,以及如何在为时已晚之前发现它们。
示例案例:时间序列数据的预测
下图说明了在这种情况下使用的示例数据。我们稍后将更详细地讨论这些数据,但现在,让我们假设这些数据代表了股票指数的年度演变、产品的销售/需求、一些传感器数据或设备状态,以及任何可能与您的情况最相关的数据。目前的基本想法是,数据实际代表的内容不会真正影响下面的分析和讨论。
如图所示,我们总共有 4 个“输入特征”或“输入变量”和一个目标变量,这就是我们试图预测的。这种情况下的基本假设是,我们模型的输入变量包含一些有用的信息,允许我们根据这些特征预测目标变量(可能是,也可能不是)。
相关性和因果性
在统计中,相关或依赖是任何统计关系,无论是否为因果。相关性是有用的,因为它们可以表明在实践中可以利用的预测关系。例如,基于电力需求和天气之间的相关性,电力公司可能在温和的日子产生较少的电力。在这个例子中,有一个因果关系,因为极端天气导致人们使用更多的电力来取暖或制冷。然而,一般来说,相关性的存在不足以推断因果关系的存在(即相关性并不意味着因果关系)。这是一个非常重要的区别,我们将在后面详细讨论。
为了检查我们的数据,我们可以考虑的一件事是计算相关矩阵,它表示我们数据集中所有变量之间的相关系数。在统计中,皮尔逊相关系数是两个变量之间线性相关性的度量。根据柯西-施瓦茨不等式,它的值介于+1 和 1 之间,其中 1 表示完全正线性相关,0 表示没有线性相关,1 表示完全负线性相关。
然而,虽然相关性是一回事,但我们通常感兴趣的是因果关系。传统观点认为“相关性并不意味着因果关系”这意味着相关性本身不能用来推断变量之间的因果关系(在任一方向上)。
儿童的年龄和身高之间的相关性相当明显,但人的情绪和健康之间的相关性就不那么明显了。心情变好会导致健康变好吗,还是健康变好会带来好心情,或者两者兼而有之?还是两者背后都有其他因素?换句话说,相关性可以作为可能的因果关系的证据,但不能表明因果关系(如果有的话)可能是什么。
相关性和因果性之间的重要区别是建立基于机器学习的预测模型时的主要挑战之一。该模型是根据我们试图预测的流程的代表性数据进行训练的。然后,我们的输入变量和目标之间的任何特征模式/相关性被模型用于建立关系,该关系可用于给出新的预测。
在我们的例子中,从相关矩阵中,我们看到我们的目标变量确实与我们的一些输入变量相关。尽管如此,根据我们的数据训练一个模型,这种明显的相关性可能只是一种统计上的侥幸,它们之间根本没有因果关系。然而,现在,让我们忽略这个事实,并尝试建立我们的预测模型。稍后我们将回头更详细地讨论这些潜在的陷阱。
时间序列预测的机器学习模型
有几种类型的模型可用于时间序列预测。在我以前的文章中,我使用了一个长短期记忆网络,或者简称为 LSTM 网络。这是一种特殊的神经网络,它根据以前时间的数据进行预测,即它在模型结构中明确内置了“记忆”的概念。
然而,根据我的经验,在许多情况下,更简单的模型实际上提供了同样准确的预测。在这个例子中,我实现了一个基于前馈神经网络(如下图所示)的预测模型,而不是基于递归神经网络。我还将预测与随机森林模型进行了比较(这是我的首选模型之一,基于其简单性和开箱即用的良好性能)。
使用开源软件库实现模型
我通常使用 Keras 来定义我的神经网络模型类型,这是一种高级神经网络 API,用 Python 编写,能够在 TensorFlow 、 CNTK 或 Theano 之上运行。对于其他类型的模型,(像这种情况下的随机森林模型),我通常使用 Scikit-Learn ,这是一个免费的软件机器学习库。它具有各种分类、回归和聚类算法,并且被设计为与 Python 数值和科学库 NumPy 和 SciPy 互操作。
本文的主题不是关于如何实现时间序列预测模型的细节,而是如何评估预测。正因如此,我就不赘述建模等细节了。,因为有大量其他博客帖子和文章涉及这些主题。(但是,如果你对这个例子中使用的代码感兴趣,请在下面的评论中告诉我,我会与你分享代码)。
训练模型
在使用 Keras 建立神经网络模型之后,我们将数据分成训练集和测试集。前 6 个月的数据用于训练,剩余的数据用作保留测试集。在模型训练期间,10%的数据用于验证,以跟踪模型的表现。然后,可以从下面的训练曲线中可视化训练过程,其中绘制了作为时期函数的训练和验证损失。从训练曲线来看,模型确实能够从数据中学到一些有用的东西。训练和验证损失都随着训练的进行而减少,然后在大约 50 个周期后开始变平(没有明显的过拟合/欠拟合的迹象)。到目前为止,一切顺利。
评估结果:
现在,让我们将模型预测与保留测试集中的地面真实数据进行可视化,以查看我们是否有很好的匹配。我们还可以在散点图中绘制真实值与预测值的对比图,并可视化误差分布,如下图右侧所示。
从上面的数字可以清楚地看出,在比较真实值和预测值时,我们的模型并没有获得很好的匹配。我们的模型看似能够学习有用的信息,但在坚持测试集中表现如此糟糕,这是怎么回事?
为了获得更好的比较,让我们也在相同的数据上实现一个随机森林模型,看看这是否会给我们带来更好的结果。正如我们可以从下图左侧的结果中看到的,随机森林模型的性能并不比神经网络好多少。然而,随机森林模型的一个有用的特征是,它还可以输出“特征重要性”作为训练过程的一部分,指示最重要的变量(根据模型)。这种特性的重要性在很多情况下可以为我们提供有用的信息,这也是我们将要详细讨论的内容。
虚假的相关性和因果关系
有趣的是,我们从上图中注意到,根据随机森林模型,变量 4 显然是最重要的输入变量。然而,从下图中的相关矩阵和图中,我们注意到与目标最强相关的变量是“变量 1”(它具有第二高的特征重要性)。实际上,如果你仔细观察下面绘制的变量,你可能会注意到变量 1 和目标遵循完全相同的趋势。这是有意义的,在我们下面对本例中使用的数据的讨论中将变得显而易见。
本例中使用的数据的来源
随着我们越来越接近完成这篇文章,是时候透露一些关于所用数据来源的额外细节了。如果你读过我之前的一篇关于时间序列预测机器学习的陷阱的文章,你可能已经意识到我是随机行走过程(以及一般的随机过程)的粉丝。在这篇文章中,我确实选择了一种类似的方法,来解决虚假的相关性和因果关系。
实际上,数据集中的所有变量(4 个输入变量和一个“目标”)都是由随机游走过程生成的。我最初生成了 4 个随机行走体,为了获得目标变量,我简单地实现了“变量 1”的 1 周时间偏移(添加了一点随机噪声,使其第一眼看起来不那么明显)。
因此,变量和目标之间当然没有因果关系。当谈到第一个变量时,由于目标与变量 1 相比在时间上向后移动了一周**,目标变量的任何变化在变量 1 的相应变化之前发生**。因此,与目标变量的唯一耦合是通过随机游走过程本身固有的自相关。****
如果我们计算变量 1 和目标之间的互相关,可以很容易地发现这种时移,如下图左侧所示。在互相关中,有一个 7 天时间偏移的清晰峰值。然而,我们从上面的相关矩阵和下面的图中注意到,即使在零天的滞后期,目标和变量 1 之间也存在显著的相关性(准确地说,相关系数为 0.75)。然而,这种相关性仅仅是因为目标变量具有缓慢衰减的自相关性(明显长于一周的时间偏移),如下图右侧所示。
格兰杰因果关系检验
如前所述,我们模型的输入变量与目标相关,并不意味着它们有因果关系。当试图在稍后阶段估计目标时,这些变量实际上可能没有任何预测能力。然而,当制作数据驱动的预测模型时,错误的相关性和因果性是一个容易陷入的陷阱。这就引出了一个重要的问题:我们能做些什么来避免这种情况吗?
****格兰杰因果检验是一种统计假设检验,用于确定一个时间序列是否对预测另一个有用,通常情况下,回归反映“仅仅”相关性,但是克莱夫·格兰杰认为因果关系可以通过测量使用另一个时间序列的先前值预测一个时间序列的未来值的能力来测试。如果通常通过对 X 的滞后值(也包括 Y 的滞后值)的一系列t-检验和F-检验可以表明,那些 X 值提供了关于未来值的统计上显著的信息,则称时间序列 X 为格兰杰原因 Y
格兰杰根据两个原则定义了因果关系:
- 原因发生在结果之前。
- 原因具有关于其结果的未来值的唯一信息。
当时间序列 X 格兰杰原因导致时间序列 Y ( 如下图 ) 时, X 中的模式在一段时间延迟后在 Y 中大致重复(两个示例用箭头表示)。因此, X 的过去值可用于预测 Y 的未来值。
格兰杰因果关系的原始定义没有考虑到潜在的混杂效应,也没有捕捉到瞬时和非线性的因果关系。因此,进行格兰杰因果关系测试并不能给你一个明确的答案,即你的输入变量和你试图预测的目标之间是否存在因果关系。尽管如此,它绝对值得研究,并且与纯粹依赖它们之间的(可能虚假的)相关性相比,它提供了额外的信息。
非平稳时间序列的“危险”
大多数统计预测方法都是基于这样一种假设,即通过使用数学变换,时间序列可以呈现为近似平稳的(即“平稳化”)。一个平稳时间序列是指其统计特性如表示、方差、自相关等。都是不变的。一个这样的基本转换是对数据进行时差。
这种变换的作用是,我们不是直接考虑数值,而是计算连续时间步长之间的差值。定义模型来预测时间步长值之间的差异而不是值本身,这是对模型预测能力的更大考验。在这种情况下,不能简单地使用数据具有很强的自相关性,并使用时间“ t 的值作为“ t+ 1”的预测。由于这一点,它提供了对模型的更好的测试,以及它是否从训练阶段学到了任何有用的东西,以及分析历史数据是否实际上可以帮助模型预测未来的变化。
摘要
我想通过这篇文章强调的要点是,在处理时间序列数据时要非常小心。正如上面的例子所示,人们很容易被愚弄(在我以前的一篇关于人工智能和大数据的隐藏风险的文章中也讨论过)。通过简单地定义一个模型,进行一些预测和计算常见的准确性度量,人们可能看起来有一个好的模型,并决定将其投入生产。然而,在现实中,该模型可能没有任何预测能力。
有了高质量和易于使用的机器学习库和工具箱,构建模型的实际编码部分变得非常简单。这一进展是个好消息。它节省了我们大量的时间和精力,并限制了实现过程中编码错误的风险。在建立模型的过程中节省下来的时间应该用来集中精力问正确的问题。在我看来,这是数据科学最重要的方面之一。你如何正确地验证你的模型预测?您的数据中是否存在任何隐藏的偏差,可能会扭曲您的预测,或者任何微妙的反馈循环,可能会导致意外的结果?
我想强调的最重要的一点是,对数据告诉你的事情保持怀疑是非常关键的。问关键的问题,永远不要得出任何草率的结论。科学方法应该应用于数据科学,就像应用于任何其他种类的科学一样。
你自己在机器学习和时间序列预测方面有什么经验?我将非常感谢任何关于这个话题的评论和新的投入。希望你觉得这个帖子有用,觉得有意思就随意分享吧!
你觉得这篇文章有趣吗?如果是这样的话,你可能也会喜欢我的其他一些关于人工智能、机器学习、物理等主题的文章。,你可以在下面的链接和我的中型作者简介中找到:
2018 年夏天我发表第一篇关于“走向数据科学”的文章时,数字背后的统计数据…
medium.com](https://medium.com/@vflovik)
而且,如果你想成为一个媒体会员,免费访问平台上的所有资料,你也可以使用下面我的推荐链接。(注意:如果您使用此链接注册,我也会收到一部分会员费)
[## 通过我的推荐链接加入 Medium—Vegard flo vik
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@vflovik/membership)
更多来自 Vegard Flovik 媒体:
- 蒙特卡洛方法简介
- 从物理学到数据科学的转变
- 什么是图论,为什么要关心?
- 用于图像分类的深度迁移学习
- 建造一个能读懂你思想的人工智能
- 人工智能和大数据隐藏的风险
- 如何使用机器学习进行异常检测和状态监控
- 如何(不)使用机器学习进行时间序列预测:避免陷阱
- 如何利用机器学习进行生产优化:利用数据提高绩效
- 如何向 AI 系统教授物理?
- 我们能否利用纳米级磁铁构建人工大脑网络?
- 供应链管理中的人工智能:利用数据推动运营绩效
研讨会演示—从宣传到实际应用**
如何不使用 ROC、精确回忆曲线和 MCC(马修斯相关系数)
我们在这些指标上犯的常见错误&如何选择最适合您的业务案例的指标
SpaceX 在 Unsplash 上拍摄的
作为一名数据科学家,我喜欢很多事情。其中之一就是对你正在为之创建解决方案的业务有一个整体的认识。让我们使用的公式具有真实世界的背景使它变得更加有趣。这就是为什么当我团队中的一位初级同事通过精确回忆曲线向我展示各种模型的比较时,我询问这是否是我们案例的最佳指标,他的反应是,“我可以通过 ROC 曲线展示这一点;也许那样会更好?”
每个有经验的数据科学家都会告诉你,没有对错之分。业务决定了最佳方法。所以,让我向你提出同样的问题,让我们看看什么是好的方法。
除非另有说明,所有图片均归作者所有。
问题陈述
我们正在为生产齿轮零件的制造工厂实施自动质量控制系统。这是一个计算机视觉问题。作为第一步,我们挑选了一个齿轮零件,并试图根据是否存在划痕、生锈、尺寸不正确等因素将其分为“好”或“坏”。发现的缺陷类型现在并不重要,只需要将其分类为好的或坏的。
此外,将不良零件运送给最终客户的惩罚是巨大的,因此我们应该非常仔细地正确分类不良零件。
让我们假设实际的和预测的(来自我们的模型)结果给出了下面的混淆矩阵,其中我们将好的部分视为正的 ,将坏的部分视为负的 :
如果你想温习与混淆矩阵相关的各种指标,如精确度、召回率、特异性,或者更喜欢预测作为列的“其他”表示,我会推荐阅读 混淆矩阵的两种变化-弄糊涂了,再也不会了 以获得更大的清晰感。
当然,上面的矩阵是基于特定的概率阈值(在这种情况下为 0.5),ROC 曲线将通过考虑各种阈值来构建,但您可以对一般的类别分布有一个大致的了解。
您应该使用哪个指标?-
- 受试者工作特征曲线
- 精确召回曲线
- 还有别的吗?
思维过程
首先,让我们消除 ROC 曲线,因为它不是最适合不平衡的类问题。这里有一个很棒的视频可以帮你打好基础。
现在进入精确回忆曲线——这是我的同事选择的。y 轴表示精度,x 轴表示召回率。如果我在不同的阈值下使用上面的混淆矩阵来绘制这条曲线,你会发现这个方法有什么问题吗?
精确回忆曲线应该会把我们的注意力吸引到 P 阳性类别。
如果我们想把注意力集中在“坏”的阶层上,那么积极和消极的阶层应该互换。这类似于一个医学用例,在这个用例中,癌症的检测相当于检测结果为“阳性”。如果只有很少的人/部分会有癌症/缺陷,那么我们将它设为阳性类别,然后使用 PR 曲线。
如果您不想交换类别标签,另一种非传统的方法是将 y 轴映射为 TN/(TN+FN) ,x 轴映射为特异性或 TN/(TN+FP) 。我可以用数学来解释这些新的轴,但是一个非常直观的记忆方式是:
案例一(传统 PR 曲线):以 TP 为‘pivot’,pivot 除以行和为 y 轴(精度),pivot 除以列和为 x 轴(回忆)。
“传统”公关曲线
案例二(非传统曲线):既然你不希望交换标签,我们就以 TN 为支点。同样,与上面完全一样,pivot 除以行总和是 y 轴,而 pivot 除以列总和是 x 轴(特异性)。
“非传统”曲线
理想的 PR 曲线在(1,1)处具有“最佳”值。
一些其他指标?
如果不提及马修斯相关系数或 MCC,这篇文章将是不完整的。
MCC 适用于这样的情况:您希望在预测所有类时评估模型的性能,而不特别关注任何特定的类。这里有一个关于这个话题的很棒的博客。
想象一下——很快,我们的问题陈述会扩大,客户会要求将所有不同的缺陷分开分类,而不仅仅是“好”或“坏”。因此,它可能是“划痕”、“尺寸错误”、“生锈”、“良好”等等。
一旦我们筛选出几个型号,最好有一个单一的指标来比较它们在不同类别中的整体表现。MCC 就是这么做的。
希望这让您对不同的场景有所了解,在这些场景中,不同的指标是有价值的。理解它们背后的数学总是一个好主意,因为只有这样,人们才能根据自己的特定需求调整它们——就像我们将 PR 曲线调整为非传统曲线一样。
对分享想法、提问或简单讨论想法感兴趣?通过我的网站、我只是个学生或者在 LinkedIn 、 YouTube 或 GitHub 上与我联系。
回头见&学习愉快!
.
www.linkedin.com](https://www.linkedin.com/in/himanshu-chandra-33512811/)
如何不写熊猫代码
大部分“如何不”用熊猫编码的想法来自于我的开始。每一次失败后,我都会向熊猫展示一个正确的“方法”。
来自 Giphy 的《国家地理坠落的熊猫》
在过去的 3 年里,我一直用熊猫作为我数据分析的主要工具。我必须承认,“如何不用熊猫编码”的大部分内容都来自于我的开端。在进行代码评审时,我仍然看到许多经验丰富的程序员的“禁忌”。
在这篇文章中,我首先展示了一个“如何不”的例子,然后展示了一个正确的“如何”用熊猫计算统计数据的方法。
改进的理由是简洁、更可读的代码和更快的执行速度。报告的时间格式为:831 ms ± 25.7 ms per loop
,表示平均 831 毫秒,标准偏差为 25.7 毫秒。每个代码样本执行多次,以计算准确的执行时间。
这里有几个你可能会感兴趣的链接:
- [How To Create Date Series in SQL](https://dataanalysis.substack.com/p/how-to-create-date-series-in-sql) [Article]- [Data Science for Business Leaders](https://imp.i115008.net/c/2402645/880006/11298) [Course]- [Intro to Machine Learning with PyTorch](https://imp.i115008.net/c/2402645/788201/11298) [Course]- [Become a Growth Product Manager](https://imp.i115008.net/c/2402645/803127/11298) [Course]- [Free skill tests for Data Scientists & Machine Learning Engineers](https://aigents.co/skills)
上面的一些链接是附属链接,如果你通过它们购买,我会赚取佣金。请记住,我链接课程是因为它们的质量,而不是因为我从你的购买中获得的佣金。
要升级您的熊猫游戏,请参见:
从提示和技巧,如何不指南到与大数据分析相关的提示,熊猫文章的精选列表。
medium.com](https://medium.com/@romanorac/pandas-data-analysis-series-b8cec5b38b22)
样本数据集
示例数据集包含各个城市的预订信息。它是随机的,它的唯一目的是显示例子。
数据集有 3 列:
- id 是唯一 id,
- 城市是预订的城市,
- booked_perc 是某个时间的预订百分比。
数据集具有 10K 条目,以使速度提高更加明显。如果以正确的方式编写代码,Pandas 可以在数百万行的数据帧上计算统计数据。
import pandas as pd
import numpy as npsize **=** 10000cities **=** ["paris", "barcelona", "berlin", "new york"]df **=** pd**.**DataFrame(
{"city": np**.**random**.**choice(cities, size**=**size), "booked_perc": np**.**random**.**rand(size)}
)
df["id"] **=** df**.**index**.**map(str) **+** "-" **+** df**.**city
df **=** df[["id", "city", "booked_perc"]]
df**.**head()
1.如何不对数据求和
来自 Reddit 的滚动熊猫
我来自 Java 世界,我把“多行中的 for 循环”带到了 Python。
让我们计算 booked_perc 列的总和—我知道对百分比求和没有意义,但我们还是要这样做:)
**%%**timeitsuma **=** 0
**for** _, row **in** df**.**iterrows():
suma **+=** row**.**booked_perc766 ms ± 20.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
对一列的值求和的更巧妙的方法是:
**%%**timeitsum(booked_perc **for** booked_perc **in** df**.**booked_perc)989 µs ± 18.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)**%%**timeitdf**.**booked_perc**.**sum()92 µs ± 2.21 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
正如所料,第一个例子是最慢的——对 10k 个条目求和几乎需要 1 秒钟。第二个例子的速度之快让我吃惊。用 pandas 对数据求和的正确方法(或对列使用任何其他操作)是第三个例子,也是最快的!
2.如何不过滤数据
来自吉菲的熊猫游戏
尽管在开始使用 pandas 之前,我对 numpy 很有经验,但我是在 for 循环中过滤数据。您可以在计算总和时观察性能损失。
**%%**timeitsuma **=** 0
**for** _, row **in** df**.**iterrows():
**if** row**.**booked_perc **<=** 0.5:
suma **+=** row**.**booked_perc831 ms ± 25.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)**%%**timeitdf[df**.**booked_perc **<=** 0.5]**.**booked_perc**.**sum()724 µs ± 18.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
正如所料,第二个例子比第一个快几个数量级。
多加几个滤镜呢?我们简单地将它们括在括号中:
**%%**timeitdf[(df**.**booked_perc **<=** 0.5) **&** (df**.**city **==** 'new york')]**.**booked_perc**.**sum()1.55 ms ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3.如何不访问以前的值
来自 Giphy 的熊猫翻滚
您可能会说:好吧,但是当我需要访问前一列的值时怎么办?那么我需要一个 for 循环。不对!
让我们计算在有和没有 for 循环的情况下从一行到另一行的百分比变化。
**%%**timeit**for** i **in** range(1, len(df)):
df**.**loc[i, "perc_change"] **=** (df**.**loc[i]**.**booked_perc **-** df**.**loc[i **-** 1]**.**booked_perc) **/** df**.**loc[i **-** 1]**.**booked_perc7.02 s ± 24.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)**%%**timeitdf["perc_change"] **=** df**.**booked_perc**.**pct_change()586 µs ± 17.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
同样,第二个例子比第一个 for 循环快得多。
Pandas 有许多函数可以基于以前的值计算统计数据(例如,shift
函数延迟一个值)。这些函数采用periods
参数,该参数定义了要包含在计算中的先前值的数量。
4.如何不应用复杂函数
来自 Giphy 的熊猫工作杆
有时,我们需要对一个数据帧应用一个复杂的函数(一个有多个变量的函数)。假设我们想将纽约的 booking_perc 乘以 2,将其他值设为 0,并将列命名为 sales_factor。
我想到的第一种方法是使用带有 iterrows 的 for 循环。
**%%**timeit**for** i, row **in** df**.**iterrows():
**if** row**.**city **==** 'new york':
df**.**loc[i, 'sales_factor'] **=** row**.**booked_perc ***** 2
**else**:
df**.**loc[i, 'sales_factor'] **=** 03.58 s ± 48.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
稍微好一点的方法是直接在数据帧上使用 apply 函数。
**%%**timeit**def** **calculate_sales_factor**(row):
**if** row**.**city **==** 'new york':
**return** row**.**booked_perc ***** 2
**return** 0df['sales_factor'] **=** df**.**apply(calculate_sales_factor, axis**=**1)165 ms ± 2.48 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
最快的方法是使用熊猫滤镜,直接计算函数值。
**%%**timeitdf**.**loc[df**.**city **==** 'new york', 'sales_factor'] **=** df[df**.**city **==** 'new york']**.**booked_perc ***** 2
df**.**sales_factor**.**fillna(0, inplace**=**True)3.03 ms ± 85.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
我们可以观察到从第一个例子到最后一个例子的加速。
当我们处理 3 个或更多变量的函数时,我们可以把它分解成多个熊猫表达式。这将比使用应用功能更快。
f(x, a, b) = (a + b) * x
df['a_plus_b'] = df['a'] + df['b']
df['f'] = df['a_plus_b'] * df['x']
5.如何不对数据进行分组
来自 Giphy 的熊猫
正如你现在看到的,当我开始使用 pandas 时,我非常依赖 for 循环。通过对数据进行分组,您可以在使用 pandas 时最大限度地减少代码行数。
假设我们想计算:
- 城市的平均销售系数
- 以及城市的第一个预订 id。
**%%**timeitavg_by_city **=** {}
count_by_city **=** {}
first_booking_by_city **=** {}**for** i, row **in** df**.**iterrows():
city **=** row**.**city
**if** city **in** avg_by_city:
avg_by_city[city] **+=** row**.**sales_factor
count_by_city[city] **+=** 1
**else**:
avg_by_city[city] **=** row**.**sales_factor
count_by_city[city] **=** 1
first_booking_by_city[city] **=** row['id']**for** city, _ **in** avg_by_city**.**items():
avg_by_city[city] **/=** count_by_city[city]878 ms ± 21.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Pandas 有一个 group by 操作,所以不需要迭代数据帧。pandas 中的 group by 与 SQL 中的 GROUP BY 语句做同样的事情。
**%%**timeitdf**.**groupby('city')**.**sales_factor**.**mean()
df**.**groupby('city')**.**sales_factor**.**count()
df**.**groupby('city')**.**id**.**first()3.05 ms ± 65.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)**%%**timeitdf**.**groupby("city")**.**agg({"sales_factor": ["mean", "count"], "id": "first"})4.5 ms ± 131 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
令人惊讶的是,第三个例子并不是最快的,但它比第二个例子更简洁。当你需要加速你的代码时,我建议你使用第二种方法。
结论
来自 Giphy 的快乐熊猫
我的建议是:
如果你对熊猫使用 for 循环,可能有一个更好的方法来写它。
存在计算开销很大的函数,即使上面的优化也无济于事。然后,我们需要使用最后的手段:Cython 和 Numba,我将在接下来的几周中介绍这两个地方。
你喜欢这个职位吗?学到了新东西?请在下面的评论中告诉我。
在你走之前
像往常一样,你可以下载这个 Jupyter 笔记本在你的机器上尝试例子。
在推特上关注我,在那里我定期发关于数据科学和机器学习的推特。
体育文章有多客观?
随机数据集挑战
分析客观性和可视化词云
探索不同类别文章的内容对于确定它们的质量、它们是否真的有用以及弄清楚它们是否是主观的非常重要;*作者自己的个人观点分量很重,*还是客观;作者提出了一个更中立的立场。
在本教程中,我们将查看 体育文章数据集 ,并从这些文章中构建美丽的词云,以及分析这 1000 篇文章中的独立特征,以计算出它们的客观性/主观性得分。本教程和实现是我的 随机数据集挑战 的一部分,在那里我构建了不同的机器学习模型来扩展我的数据科学技能。
关于数据集:
数千篇体育文章被亚马逊土耳其机器人标注为主观或客观。附加特征,例如字数、语义分数、名词、形容词、符号的频率等。,都是从这些文章中摘录的。
所以我们有两个信息来源。体育文章本身加上可量化的数字特征矩阵。
教程:
1)词云可视化-
让我们从构建一个单词云开始,实际上,有两个,所以我们可以看看最频繁出现的单词。
字云形状的排球运动员中期穗。图片作者。
首先,为了将单词组合成这种形状,我们必须将文章中的所有单词提取到一个语料库中。
我们将使用自然语言处理技术从文章中提取词干、词条和删除停用词,以及除字母数字字符之外的任何特殊字符。
然后,我们将使用单词云方法和一些其他参数来设置单词云的大小,并指定要使用的掩码。
这是你以前可能见过的另一种形状更正常的单词云。
词云。图片作者。
2)客观性分析-
在这个更“简单”的分析中,我们将使用功能 excel 表来查看哪种技术属性,属于主观文章还是更客观的文章。
像往常一样,我们将从导入所需的库、数据集、预处理数据和训练模型开始。
经过对多个分类器的反复试验,我发现支持向量分类器的性能最好,准确率为 82.66%。
3)混淆矩阵-
混淆矩阵是另一个性能指标,它一眼就能告诉我们 ,对于每个类,模型正确和错误地分类了多少个观察值。
混乱矩阵。图片作者。
可以看出,我们的模型正确预测了(预测=实际),168 篇客观文章,80 篇主观文章。对于客观文章来说,不正确的预测是 35 个,即 35 个主观文章被错误地分类为客观文章,而对于 17 个实际客观文章则相反,它们被错误地标记为主观文章。
这就是了。又是一天,又是一个机器学习模型。
这一次,我想做一些不同的事情,让同时使用 NLP 和分类算法来分析文章。
整合文本文章和可量化的特征数据集,我想到了绘制单词云,因为当我在其他几篇文章中遇到它时,我一直想知道如何做。
希望这篇文章/教程对你有帮助。如果你想看看我的其他作品,可以看看我的 GitHub 。
这个系列的其他文章可以在 这里 找到。
非常感谢您的阅读,祝您有美好的一天!
下一篇文章再见。
我们的人工智能如何使用数据科学在梦幻超级联赛中获得前 10 名
EPL 幻想博客
我们对 EPL 梦幻联盟的摇钱树方法
**注:**这是我们 2019 年以来的主要项目总结。关于 2020 年的每周更新,请查看我最近在 EPL 幻想联盟上的一些博客。
我的朋友( Andrew Sproul )和我已经玩了很多年的官方梦幻英格兰超级联赛,尽管我们坚信我们了解英格兰足球的一切,但我们倾向于年复一年地“倒霉”,不知何故似乎从来没有选出获胜的球队。因此,我们最终决定将数据科学和“金钱球”方法应用于团队/球员分析,以确定我们是否真的在每个赛季选择了最佳的球员组合。我们的研究始于从梦幻游戏 API 中提取最新的玩家数据,并使用 Python 对所有 EPL 团队和所有个人玩家进行统计分析。我们项目的最终目标是编写一个 Python 算法,它使用来自我们分析的数据进行“智能”挑选,并在我们有限的 100 毫米预算下建立最佳的梦幻联盟阵容。
注意:最理想的幻想小队将会根据每花费一美元的幻想点数返回的总点数=投资回报率来衡量。
我们的分析将以以下假设为指导,旨在回答以下关键问题:
- 要检验的主要假设:
- 大多数休闲 EPL 幻想玩家在为他们的幻想队挑选队员时使用个人偏见和偏爱。换句话说,人们通常会根据他们支持的球队以及目前哪些 EPL 球员是“最热门”的来做出决定,而不会将单个球员视为长期投资以及他们每一美元的投资回报率。
- 我们相信,如果我们在选择我们的梦幻阵容时,从决策过程中消除偏见和偏袒,并专注于单个球员的统计数据和整体团队表现,我们可以在赛季结束时比普通人做得更好。
2.我们的分析旨在回答的关键问题:
- 个别球员梦幻联赛的统计数据,他们的球队在英超联赛中的总积分,以及该球队相应的积分榜位置之间是否存在相关性?
- 我们能否识别出有很多表现不佳、价格过高的球员的球队,以及那些拥有非常稳固但被低估的阵容的球队,这样我们就可以告诉我们的算法相应地从这些球队中挑选球员?(注:“被低估”和“被高估”是根据幻想联盟成本而非现实世界中的实际玩家价值来衡量的。)
- 我们能否将官方的英超梦幻游戏视为等同于股票市场和将单个球员视为金融资产并尝试根据他们的投资回报率找出所有定价过低和过高的球员,并相应地投资我们的梦幻美元预算?
单个玩家投资回报率=玩家幻想点数/玩家幻想成本(换句话说,我们在玩家身上花费的每 1 毫米幻想美元的总点数回报。)
- 我们的理论是,这有助于将我们有限的 1 亿英镑梦幻联盟预算花在球员身上,在整个赛季中,每花 1 美元梦幻就能获得尽可能多的积分。
- 如果这被证明是真的,那么我们是否可以使用 Python 来构建一个算法,通过挑选尽可能多的高 ROI 球员并结合一些昂贵的超级明星来优化预算的使用,以最大化每总预算支出的总积分回报?
- 我们的算法和玩 EPL 幻想游戏的普通人相比怎么样?我们的团队获得了什么样的总体排名,他们是否以显著优势击败了普通玩家?
**注:**该项目于 2018 年 11 月 14 日执行,在 Gameweek 10 之后,因此文章中提供的所有数据和表格都是准确的。
我们程序的主要步骤如下:
1.查看单个团队的数据
首先,我们首先根据目前的积分榜排名排列所有巴克莱 EPL 球队,并查看所有球员的总积分,以了解这是否与球队的积分榜位置直接相关。
我们可以清楚地看到,一般来说,一支球队在英超联赛中的表现与其球员的累计梦幻积分之间存在线性相关性。上面的橙色条显示了每支球队的球员在梦幻联盟货币方面的总成本。这有助于我们识别平均每美元投资(ROI)产生可观梦幻积分回报的球队,如— 曼城、利物浦、切尔西、亚足联伯恩茅斯、沃特福德和狼队。这也暴露了一些被认为是不良投资的球队,如托特纳姆、阿森纳、曼联、富勒姆、哈德斯菲尔德、西汉姆和南安普顿。
接下来,我们绘制了每支球队的累积球员投资回报率与教练经常使用的球员数量的关系图(本赛季迄今为止至少打了 360 分钟的球员)。这将有助于我们识别那些拥有太多昂贵且表现不佳的球员的球队,由于他们的教练经常轮换阵容,这些球员很少每场比赛打满 90 分钟,从长远来看,这使他们成为一项糟糕的投资,因为他们不会每场比赛都持续不断地产生梦幻积分。此外,下面的图表将帮助我们确定教练不经常轮换球员的球队,这将导致这些球队拥有更一致的常规球员核心。这将通知我们的算法从这些球队中挑选更多的球员,因为从长远来看,他们的球员预计会产生更高的总 ROI,因为与来自经常轮换球员的球队的球员相比,他们平均会参与更多的游戏活动。
在上图中,我们在寻找有很高的蓝条(累积球员投资回报率)和较短的橙条(教练定期使用的球员总数)的球队。这一类别的领导者是伍尔弗汉普顿,的 AVG 投资回报率为 8.21,只有 11 名教练经常使用的球员(平均每名伍尔弗汉普顿球员身上花费的 1 美元产生 8.21 分的收益)。这意味着与他们的表现相比,伍尔弗汉普顿的大多数球员都被低估了,教练经常使用同样的 11 名球员,并且只在比赛快结束时或正式队员受伤时使用替补队员。即使像曼城、利物浦和切尔西这样的球队也属于这一类,拥有 13-14 名正式队员,这意味着从上述任何球队中挑选球员从长远来看都是一项不错的投资,因为正式队员比替补队员平均上场时间更长。
这一类别中最大的输家是曼联、热刺、阿森纳、埃弗顿、西汉姆和富勒姆,他们的投资回报率在 4-5 之间,许多常规球员的回报率高达 15-16。这意味着,通过从这些球队中挑选球员,你正在进行一项“糟糕的投资”,因为教练经常轮换阵容,你的球员可能无法参加每场比赛。此外,统计数据清楚地表明,与他们在梦幻联盟中的表现相比,这些球队的球员被高估了,这是由他们低于平均水平的 ROI 所表明的。
2.查看单个玩家的数据
在确定了哪些团队产生了更高的累积投资回报率之后,我们接着放大了单个玩家。在股票市场方面,我们已经确定了所有的高收益市场部门——团队——现在我们要开始分析每个部门的所有个股——玩家。计划是分离出一个具有最高 ROI 的玩家列表,并编写一个 Python 算法,该算法将使用智能逻辑来挑选最佳的玩家组合,这将为我们 1 亿毫米的有限预算带来最高的投资回报。
看着上面玩家花费与玩家总幻想点数的散点图,我们希望我们的人工智能选择出现在图上尽可能靠西北的玩家(低花费玩家产生大量幻想点数)。请注意,我们还希望包括一些来自该地块东北角的顶级玩家,因为这些将是一些产生大量积分的明星联盟玩家,尽管他们有点昂贵,但他们最终仍有不错的 ROI。下图描绘了前 20 名投资回报率玩家与后 20 名投资回报率玩家的对比。因此,我们希望我们的最终算法尽可能多地选择这些高产玩家。我们希望远离那些相对于他们的表现(高成本/低幻想点)价格过高的球员,如哈里·凯恩、阿莱克西斯·桑切斯、罗梅卢·卢卡库、克里斯蒂安·埃里克森、阿尔瓦罗·莫拉塔、保罗·博格巴、德勒·阿里等等。
投资回报率排名前 20 和后 20 的球员与 AVG 联盟投资回报率的对比图
我们决定绘制上面的统计数据,包括联盟中所有球员的 AVG 投资回报率(绿线= 5.74 ),以直观地了解“*表现出色”*和“表现不佳”的球员是什么样子。例如,联盟中收益最高的球员马科斯·阿隆索的投资回报率为 12.11 ,是 AVG 5.74 的两倍多,这使他成为我们算法中显而易见的选择。
在下面的饼状图中,我们可以看到球员价值最高的球队和球员价值最低的球队的分布情况。我们期待我们的最终算法能够从拥有许多高产球员的各种球队中挑选球员,例如——**伯恩茅斯、狼队、利物浦切尔西、曼城、沃特福德和埃弗顿。**这种聪明的方法与普通人玩幻想游戏的方法非常不同,后者主要从他/她最喜欢的球队中挑选球员,加上来自 4 或 5 个最受欢迎球队的少数球员——**阿森纳、托特纳姆、曼联、切尔西、利物浦或曼城,**然后用廉价的“填充”球员填充他们幻想球队的剩余部分,这些球员从不在真实比赛中出场,也不会产生任何幻想积分。
投资回报率前 50 名球员最多的球队
ROI 排名倒数 50 名球员最多的球队
3.编写挑选最佳幻想团队的 Python 算法
现在是最有趣的部分——编写实际的 Python 算法,并将人工智能选择的结果与普通人可能为他们的幻想团队选择的结果进行比较。
要理解我们算法的逻辑,首先必须理解下面 EPL 幻想游戏的规则和约束:
- 每个幻想玩家的预算都是 100 万英镑,必须购买 15 名足球运动员(11 名主力+ 4 名替补)才能参赛。
- 你需要至少有 2 名守门员,5 名后卫,5 名中场球员和 3 名前锋,以完善你的阵容并有资格参加比赛。
- 同一个足球队不能有 3 名以上的球员。
因此,我们用一个针对这些条件的if-else
语句开始我们的 python 算法,然后在此基础上添加我们自己的条件和逻辑,这样每次算法遍历我们的玩家列表时,它都可以使用智能逻辑根据下面的条件做出有效的选择:
- 检查一个球员是否受伤,被禁赛或不能比赛,如果是这样,即使他们有很高的投资回报率,也不要选择这个球员加入我们的梦幻队。
- 先挑联盟累计联赛积分最多的前三名明星球员。(我们将使用不同数量的明星球员来测试这种情况的结果,并选择能够产生最大投资回报的版本,同时仍然允许足够的剩余预算来填充我们的团队,让我们拥有许多投资回报率排名前 50 的球员。
- 每次我们挑选一名球员并将其加入我们的球队,我们都会从 1 亿美元的预算中减去他们的费用,并将他们的位置和球队名称添加到一个列表中,以确保我们不再为达到限制的位置和球队购买球员。
- 一旦选择了最佳数量的昂贵超级明星球员,该算法就开始浏览投资回报率最高的球员名单,并试图尽可能多地找到顶级球员,直到我们接近耗尽我们的预算并填补所有的球队职位。
- Algorithm 打印出它在最后挑选的球员名单,并给我们剩余的预算和球队的总幻想点数。
这里是我们团队挑选算法的一些压缩 Python 代码:
最佳幻想队选择器
下面你可以看到我们的算法选出的最终团队的截图:
**注:**以下团队仅准确到 2018 年 11 月 14 日。我们的算法被设计成在每个游戏周之后更新玩家数据,并根据团队/玩家 ROI 数据的波动做出新的选择。
截至 2018 年 11 月 14 日的金钱团队(总幻想点数为 944,世界排名:580 万人中的第一名)
**注:**我们为 AVG·乔团队编写了一个类似的算法,该算法更侧重于将预算花在大球队的明星球员身上,这些球员往往定价过高,可能无法在我们 1 亿英镑的有限预算中获得最高的累计投资回报。
**注意:**我们还要求一位同学选择一个他自己的随机团队,这样我们就可以比较他的选择,并验证我们针对 AVG·乔算法的随机团队选择器函数是准确的。
4.比较我们的结果
既然两种算法都已经建立并执行,让我们比较一下“金钱团队”与“AVG·乔的团队”和“随机同学团队”的结果,看看哪一个表现最好,差距有多大。最终结果显示,我们队的总得分为 944 分对仅 **812 分。**对于 AVG·乔团队(类似于我们同学的团队),这是一个显著的 **132pt 差异!**下面的柱状图展示了我们的结果:
**需要回答的有趣问题:**我们的算法是否返回了最高 ROI 团队?它是否以显著优势击败了其他公司?我们的算法是否成功地从一些我们最初认为被低估的中游球队中挑选了球员?AVG·乔算法和我们的同学从顶级球队中挑选了更多价格昂贵的球员吗?
下面我们可以看到,我们的算法从我们在项目开始时确定的大部分高 ROI 团队中挑选了一组球员:
金钱团队玩家分布
这是一个更加平衡和公正的选择方法,而不是 AVG·乔在选择他/她的球员时所用的方法。请注意,下面的饼状图显示了 AVG 乔队选择的 11 名球员的球队名单。由于 AVG·乔将他/她的大部分预算花在挑选 11 名非常昂贵的球员上,他/她不得不将剩余的预算花在最便宜的可用球员上,以填补所有的替补位置,但是这些球员中没有一个可以用于产生幻想积分,因为他们实际上从未参加过真正的 EPL 比赛,并且仅被用作球队填充员。这些是来自布赖顿和卡迪夫的一些替补队员。
AVG 乔队球员分布
结论:
消除团队/玩家的偏见和偏袒,专注于实际的玩家统计数据,让我们的算法得到最大的回报,并以总计 132 分或整整 16.25% 的优势击败了普通的 EPL 幻想玩家!最后,事实证明我和我的朋友实际上并不“不幸”,我们的梦幻联盟球队年复一年表现不佳是有原因的。这种对球员数据的深入研究让我们意识到,我们正在允许球队偏袒和购买大量高价球员的倾向,从而损害我们的整体梦幻联盟表现。
5.后续步骤
我们计划继续监控这些数据,在赛季中当球员开始受伤,争夺积分奖杯变得更加激烈时,检查球员统计数据中的任何剧烈变化和异常值。我们还想比较算法的团队在赛季结束时与世界上大多数休闲球员相比的表现。此外,我们计划每月更新一次这个博客,为那些对我们的人工智能进展感兴趣的人,所以请在每个月底重新访问这个博客,了解性能更新,并享受 EPL 行动的其余部分!!!
使用序列模型的自然语言生成
使用单层 LSTM 模型生成文本
递归神经网络(图片由作者提供)
简介
如果我告诉你,你可以让你自己的设备以你自己的方式用不到 100 行代码为你写东西,那会怎么样?
让你的设备代表你书写的想法非常鼓舞人心。这种实践被称为文本生成或自然语言生成,这是自然语言处理(NLP)的一个子领域。
文本生成的基础可以很容易地分解成一个简单的监督机器学习问题,其中,存在某些特征(称为 x)及其相应的标签(称为 y),并且使用这些特征,我们可以创建我们自己的预测函数,该预测函数然后将生成我们预测的标签(称为 ŷ或 yhat)。然后,我们将这些预测标签映射到实际标签,以确定成本并使用优化算法(如梯度下降、RMSprop 甚至 Adam 优化器)进行优化。
我们把文本生成的任务简化为一个简单的预测问题。因此,通过这一点,我们可以有一个文本语料库,其中可能有几个句子。我们提取每个句子(假设它有 n 个单词),在每个句子中,我们将开始的 n-1 个单词标记为特征(称为 x ),将第n个单词标记为标签(称为 y)。
现在,假设我们有一个句子,“深度学习已经自动化了我们的世界”,在这里,“深度学习已经自动化了我们的”这个短语可以是特征(称为 x),最后一个词“世界”可以是标签(称为 y)。所以在未来,每当设备遇到文本“深度学习已经自动化了我们的”时,它就会知道预测“世界”是下一个单词。
结果,如果我们用大量的数据训练一个网络,我们会得到一个相当复杂的模型,可以预测接下来的单词和 voilà ,我们已经教会了我们的设备写作。
使用 TensorFlow 生成文本
我们现在将学习如何应用实用方法生成新文本。为此,我们将使用 TensorFlow 2.0,这是一个开源的机器学习库。
导入必要的库
为此需要遵循的步骤是:
- 数据预处理:
我们来看两个例句:
艾是新电
AI 就是我的力量
(注意,与机器学习实践者用来训练模型的实际数据相比,这里采集的样本非常小。通常,使用作家出版物的整个语料库或整本书作为数据集,然而在这里,为了便于理解,作者只取了其中的一小部分。)
为简单起见,为了减少我们集合中的大量单词,我们可以将句子中的每个单词都转换为小写,因为这不会改变句子的意思(new、NEW 和 New 都是相同的意思)。我们可以通过使用来做到这一点。Python 3 中的 lower() 。
所以我们句子的小写形式是:
艾是新电
ai 是我的力量
我们现在有一个样本来训练我们的模型。接下来要做的是为每个单词生成一个唯一的令牌。语料库中的重复单词被分配相同的标记。这可以使用 TensorFlow 中的 Tokenizer 轻松完成。
第一句:
ai - > 1
是- > 2
->3
新增- > 4
电- > 5
第二句:
ai - > 1
是- > 2
我的- > 6
电源- > 7
现在,我们可以用一系列数字来表示我们的句子:
【1,2,3,4,5】->为第一句
【1、2、6、7】->为第二句
生成令牌
我们现在生成 n-gram 序列,其中,这样的句子的前两个单词可以是一个序列,前三个单词可以是下一个序列,以此类推。因此,我们列出了以下可能的顺序:
对于第一句[1,2,3,4,5]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
对于第二句[1,2,6,7]
[1, 2]
[1, 2, 6]
[1, 2, 6, 7]
我们现在将这些生成的序列添加到另一个列表中(形成一个 2-D 列表)。
生成 n 元语法序列
这里需要注意的一个关键点是,每个生成序列的长度是不同的,因此为了保持顺序,我们用零预先填充,每个序列的长度等于可用的最长序列。因为在当前情况下,序列的最大长度是 5,所以我们相应地进行预填充。可以使用 Keras 的 pad_sequences()方法进行填充。
填充后,每个序列将看起来像:
对于第一句[1,2,3,4,5]
[0, 0, 0, 1, 2]
[0, 0, 1, 2, 3]
[0, 1, 2, 3, 4]
[1, 2, 3, 4, 5]
对于第二句[1,2,6,7]
[0, 0, 0, 1, 2]
[0, 0, 1, 2, 6]
[0, 1, 2, 6, 7]
我们现在知道,对于这些序列中的每一个,前 4 个字是特征(称为 x),最后一个字是标签(称为 y)。然后,我们通过简单的 NumPy 数组切片来提取我们的特征及其相应的标签。
剩下要做的一件事是将我们的标签转换成一个热点编码向量,以便于优化。
说特征是x =【0,1,2,3,4】****
对应的标签是标签=【5】****
因此,标签的独热码编码向量是:[0,0,0,0,1],即在向量的第 5 个位置存在 1,在剩余位置存在 0。
因此, y = [0,0,0,0,1]
生成要素(x)和标注(y)
我们现在已经准备好了可以输入到模型中的训练数据。
- 构建模型:单层 LSTM 模型
我们定义了一个序列模型,其中每一层恰好有一个输入张量和一个输出张量。
- 第一层是嵌入层**,它将是网络中的第一层。这一层有三个参数,即输入维度(我们的语料库中唯一单词的总数);输出维度(或向量将被映射的嵌入维度);和输入长度(输入的每个序列的长度)。**
- 对于第二层,我们添加了 20 个单元的双向 LSTM** 层,这对于处理长句和依存关系中的消失梯度问题是有效的。**
- 因此,在第三层,我们添加了一个密集层和 p 单元。其中 p 是我们的语料库中唯一单词的总数,我们将 softmax 激活应用于这些单元中的每一个。
模型构建
- 编译模型:
由于下一个单词的预测是一个多类分类问题,我们选择我们的损失函数作为分类交叉熵**和优化器作为 **Adam。通过选择这一优化器,我们允许 TensorFlow 自行调整学习速率,这为我们消除了一个需要微调的超参数。然后我们训练模型,比如说 500 个时期。
编译模型
拟合训练数据后,我们的模型显示训练准确率接近 95%,剩下我们要做的就是使用该模型进行预测。
- 预测下一个单词:
现在,为了进行预测,我们必须给我们的模型一些感知,让它知道我们希望它在什么意义上生成文本。为此,我们给它一个初始短语或句子,然后模型解析它,并根据我们训练它的文本语料库进行计算预测。因此,该模型将预测下一个单词的标记,然后将该标记转换回原始单词,最后显示整个预测的字符串。
预测接下来的 t 个单词(这里 t=5)
现在通过一个例子来理解整个过程,让我们用下面的句子来训练这个模型:
深度学习的范围一直在以指数速度增长,深度学习蓬勃发展的原因隐藏在这样一个事实中,即在当今世界中存在大量我们认为理所当然的应用程序,从在我们的 iPhone 上使用嘿 Siri(触发词检测)到在我们的 Gmail/LinkedIn 上使用自动回复(情感分析);深度学习已经在我们甚至没有意识到的情况下自动化了我们的世界。这个世界需要深度学习来维持,因为它已经变得必要。”
这里,生成新文本的种子是:
输入=人工智能的范围
因此,该模型预测:
输出=人工智能学习范围已经自动化了我们的世界
现在,由于我们的模型,预测的句子可能在语法上不正确,但句子的整体主旨很容易理解。
总而言之
人们可能会认为模型做出的预测看起来有些微不足道,但必须记住,在文本生成之前,我们的设备无法形成新的句子,事实上,它甚至不知道构造单词所需的基本字母。
从让我们的设备理解文本中的情感到预测给定序列中的新词,NLP 已经走过了很长的路,我们甚至可以走得更远。
这里是作者的 Github 库的链接,可以参考完整的代码。
** [## ujjwalkumar 2607/NLP-使用 LSTM 自动生成文本
该模型被给予一个初始数据序列来学习,这是:“深度学习的范围已经…
github.com](https://github.com/ujjwalkumar2607/NLP-automatic-text-generation-with-LSTM)**
疫情如何影响大学成绩:基于真实数据集的分析
深入探究我的大学成绩并发现其中的趋势
疫情冠状病毒已经影响了世界上很多人。所有类型的企业都崩溃了,人们正在转向不同的领域,大多数行业正在转向在线模式。随着在线模式在今天如此普遍,教育领域也不例外。我住在印度和这里,这是第一次所有的教育机构都选择在线教学方法。这个系统对我们来说很新,完全适应这个环境需要时间。最近,我第四学期的成绩公布了,当我把这学期的统计数据与前几个学期进行比较时,我震惊了。想知道我发现了什么?开始挖掘数据吧!
关于数据
数据看起来怎么样?
我所在的大学最棒的一点是,它以开放的 pdf 格式发布结果,每个访问其网站的人都可以访问这些结果。但是这里有一个问题,pdf 有多层、多层次的表格,很难处理。即使您查看表格并尝试推断您的最终得分,这也是一个繁琐的过程,因为您需要参考多个 pdf 中的多个页面来获得想要的值。以下是 PDF 的截图:
由于隐私问题,一些细节已被隐藏。作者照片
如果你仍然对查看实际的 PDF 感到好奇,请点击这个链接下载你想看的任何学期成绩!
一件重要的事情
我不会解释数据提取过程,因为解析器仍在开发中,源代码尚未公开。这是一个很长的过程,因为文件可能从 100 页到 400 页不等,并且必须进行大量预处理才能获得最佳结果。我根据这些 pdf 做了一个简化的结果门户。你可以在这里查看(这是一个 Heroku 应用,可能需要一分钟左右才能启动)。这所大学在不同的文件中同时公布所有附属学院的成绩。我把所有学院的数据综合起来,每学期做一个档案,简化比较。每个文件大约有 5.9k 个条目,这里我们将比较第四学期的结果和以前的学期。
缩写:
印度的常见分支机构:
- IT:信息技术
- CSE:计算机科学与工程
- 欧洲经委会:电子和通信工程
- EEE:电气和电子工程
- 机械与自动化工程
不同的分科招收多少学生?
我们考虑的第一个问题非常简单,我将以柱状图的形式展示数据来回答这个问题。
不同学科的学生
这里有一个有趣的事实,印度每年培养出世界上 25%的工程师,但缺乏推动创新的研究人员。在这里,每个学生都想获得 CSE,只是为了加薪,不管他们是否足够熟练。从这个柱状图中可以明显看出,在一所相当小的大学中,大约有 2000 名学生选择了 CSE(如果你想知道,我选择了它😀)其次是 ECE 和 MAE 是这里最不被看好的分支。你一定在想这和疫情有什么关系?这是我做预测的地方。由于新生入学尚未开始,我没有这一届的数据,但鉴于目前的情况,我相信 CSE 和 IT 将迎来另一个高峰,因为大多数学生都在广泛使用小工具,每个人都将真正对技术感兴趣,而不是任何其他外部因素,这可能会增加研究人员。
平均 SGPA 和百分比
SGPA 代表学期绩点,这是在最初阶段筛选工作简历时最常见的标准。让我们来看看第三学期的 SGPA 和第四学期的 SGPA 的对比:
这里所有大学的平均水平都在各自的学期范围内
这里所有分支的平均值都在各自的学期范围内
惊讶,困惑?我也是。让我解释一下这是怎么回事。您正在查看的图表是 seaborn-distplot,它显示了位于分布范围内的 SGPA 大学或分校的平均值,图表显示了第三和第四学期的数据。为了更好地理解这一点,下面是第四学期的 SGPA 分支的实际数值形式:
按作者分类的数据
在第四学期,SGPA 山脉的变化是如何发生的?答案很简单。发生这种情况是因为在这个学期,冠状病毒处于高峰期(☹️仍处于高峰期),所有的课程都暂停了。在此期间,该大学试图提出不同的解决方案来评估本学期的学生,因为物理考试不可行,在线考试也有其自身的困难。然后决定在第三学期对学生进行 50%的评估,50%的内部评估通过电话和一些谷歌测验进行。奇怪的是,在大学水平上,当第三学期 SGPA 在 5.5 到 7.5 之间时,那么怎么会第四学期有 6.5 到 9 的范围?为了证明我的观点,我回去将这些学期与第二学期进行了比较,结果确实令人震惊:
第二学期 SGPA 与第三学期的比较
第二学期 SGPA 与第四学期的比较
从上面的两个图表,我们可以说第四学期的评估方法对学生太宽松了。如果一个学生得了 8 分 SGPA,那么与第二学期相比,这没什么大不了的。如果我们看百分比趋势,那么它与我们在 SGPA 发现的非常相似:
第二学期与第四学期的百分比比较
第三学期与第四学期的百分比比较
让我们假设大学在采取这种评估方式时犯了一个错误,最终给了所有学生额外的分数,但是当我从学生的角度思考时(我就是这样!),要知道小小的努力却换来了大量的成果,这绝对令人惊叹。从长远来看,这不会有帮助,这一切都归结为一个结论,为什么印度失业率高。
终极顶级
第四学期对学生来说是个灾难。这学期 SGPA 加入后,他们本来很低的平均绩点提高了。因为每一个团体都有一个领导者,toppers 与此类似,他们都是在各种情况下都表现出色的杰出人士。鉴于目前的情况,我原以为这学期我们不会有这种趋势,但当我看到过滤后的结果时,我的想法发生了转变:
分支明智的学生数得分完美 10 SGPA
本学期某一特定分支的 60 名学生中最多有 10 名获得了满分!我在第三学期尝试过,没有结果!他们中没有人得过满分 10 分,所以我调整了逻辑,让第三学期的 SGPAs 高于 9 分,结果如下:
SGPA 得分大于 9 的学生人数
即使有了这些标准,也只有 45-48 名学生的 SGPA 得分高于 9 分!
最后一个音符
这是一种令人担忧的情况,就好像我们给了学生太多的评分自由,那么他们就会认为这些课程是理所当然的,而永远不会努力通过实际表演来取得好成绩。这类似于我们在模型构建中称之为假阳性的情况,当学生应得的分数较低时,他们被错误地给予分数(如果你想要混淆矩阵的详细解释,请在下面评论)。从学生的角度来看,我们永远不会满足于我们没有达到的分数,我认为需要一种更好的评估方法来取代这个有缺陷的系统。
这就是这篇文章的全部内容,我希望我能够以最好的方式表达我的分析。在 medium 上关注我以获得关于新文章的更新,如果你是一个热情的 Python 开发者,想要升级他们当前的技能,那么请确保在 medium 上查看我的 Python 系列中的 android 应用。说完了,合十礼!
你的生日有多受欢迎?
阿迪·戈尔茨坦在 Unsplash 上的照片
房间里的两个人同一天生日的几率有多大?
在 2020 年之前的几年里,大量学生(20-30 或更多)在一起上数学课是很常见的。在许多课堂上,学生们被要求计算其中两人同一天生日的概率。
为了进行这种计算,学生们通常会做一个默认的假设,即每个人在任何给定日期出生的可能性都是相等的(均匀分布)。没有这个假设,问题就变得很难手工做。另一方面,你会经常看到类似于下图的可视化在互联网上流传。
生日的相对受欢迎程度
我将在下面更多地讨论用于生成本文中的数字和值的数据。这张图表显示了某人在某一天过生日的相对可能性。
- 值为 1(如 12 月 16 日)意味着一个随机的人在那一天出生的概率与你对均匀分布的预期相同。
- 小于 1 的值(特别是 1 月 1 日、7 月 4 日和 12 月 24-26 日)意味着随机选择的人在那一天出生的可能性比均匀随机选择的人低很多倍。
- 大于 1 的值(特别是 9 月中旬)意味着一个随机的人更有可能在那一天出生,而不是你天真的期望。
请注意,对于大约每 4 年出现一次的 2 月 29 日,均匀分布意味着一个人在 2 月 29 日出生的可能性是在 2 月 28 日出生的可能性的四分之一。这在上面的图表中有所说明(如果不进行修正,与假设均匀分布的一年中其他任何一天出生的概率相比,2 月 29 日生日的相对频率为 0.92/4 = 0.23)。
7 月 4 日是美国的一个重要节日,但它不受欢迎,这应该会提醒你,这个数据只是针对美国的。
在本文的第一部分,我们将重点讨论概率问题,即:一个房间里的两个人同一天生日的几率是多少?首先,我们将使用生日在一年中均匀分布的假设来计算生日问题的解决方案。其次,我们将使用蒙特卡罗方法来计算给定的观察分布的解决方案。
结果将是,即使考虑到经验分布,答案也是不变的(虽然很接近!).对于我们考虑的问题的每一个版本,答案都是 23 刚好可以让两个人同一天生日的概率达到 50%。
在文章的第二部分,我们将进一步探索生日的分布,并建立一个简单的模型来理解出生的变化。
制服生日问题
在学校里,这个问题可以这样提出:
假设一个房间里有 n 人。假设没有人在 2 月 29 日生日,并且他们的生日是均匀分布在一年中其他 365 天的随机变量。找出 n 的最小值,使得至少两个学生同一天生日的概率至少为 50%。
为了解决这个问题,我们改为计算没有两个学生同一天生日的概率。我们把学生编号为 1 到 n 。第一个学生不与任何以前的学生共享生日的概率是 365/365=1。对于第二个学生,有 364 天不与以前的学生重叠,所以他们不与以前的学生同一天生日的概率是 364/365。下一个学生是 363/365 等等。
结果是下面的量,我们将把它表示为 q 。目标是找到最小的 n ,使得 q ≤0.5。
没有两个学生有相同的生日
在这一点上,大多数人都伸手去拿他们的计算器。但是我们可以通过对数和泰勒展开继续手工估算:
用对数的一阶泰勒展开式逼近 ln q
在第一行中,我们取对数,把乘积变成和。我们还将每个分数重写为 1–x 的形式。当 x 较小时,一阶泰勒展开是一个很好的近似,ln(1–x)=–x。这是我们在第二行中应用的内容。第三行使用算术级数求和的公式(我们只是将分子中的 1+2+3+⋯+(n–1)相加)。ln(2)是著名的 0.69。乘法 0.69⨉365≈252(四舍五入)。 n 应该比 2⨉252 = 504 的平方根大一点,所以 n = 23 是我们基于这些近似值的猜测(在 ln q 近似值的分子中产生 253)。事实上,这是正确答案,如下图所示(精确计算/精确到数字)。代码链接在末尾。
经验生日问题
现在我们转向使用真实数据解决生日问题。这个数据是由 FiveThirtyEight 提供的,是基于社会保障局(政府)从 2000 年 1 月 1 日到 2014 年 12 月 31 日每天的出生人口统计数据。有理由假设这涵盖了那段时间内美国几乎所有的新生儿。
根据给定的数据,我们来估计两个人同一天生日的概率。我们假设我们的 n 人的生日根据我们数据的经验分布是 iid 分布的。没有可行的直接方法从数据中计算出来,所以我们求助于蒙特卡罗方法。
具体来说,对于每个 n ,我们将从分布中进行抽样,并观察是否有生日相同的。同样,代码(和测试用例)在最后链接的回购中。有点令人惊讶的是,结果基本上没有变化。结果如下图所示,其中还标有统一生日问题的值。经验结果也有 99%的置信区间,这个区间小到你看不到(每个n使用 100,000 次模拟)。
这种分布足够接近均匀,以至于结果 n=23 继续适用于经验案例!从某种意义上说,事后看来,这是一个不必要的分析。两条曲线之间的差异如下图所示,您可以看到它们在统计上是不可区分的。
要明确的是,分布是不一样的。然而,该模拟是在每个 n 值 100,000 次抽取的情况下运行的,没有足够的统计能力来揭示差异。大量的模拟将揭示统计上显著的(但实质上很小的)差异。例如,仅针对 n=23 运行 5,000,000 次抽奖,最终产生足够的统计能力来区分。经验分布有 P=50.786% 0.022%,而均匀分布有 P=50.730%。(误差幅度是 1 个标准差,而不是 95%的置信区间)。
一岁生日问题
现在,在任何一个固定的年份,出生分布偏离均匀的程度都应该高于总体水平。我们期望在任何一年看到的许多变化将会被消除。例如:
- 任何给定的日期都将在 14 年的周期中循环通过一周中的每一天,因此由于一周中的每一天(下面讨论)而与统一值的偏差将被隐藏。
- 感恩节(美国 11 月的第四个星期四)并不是每年都在同一天。回顾一下生日的相对流行度表,我们可以看到,在 11 月底有一个下降,但每年精确日期的轻微变化使它变得平滑。
回到生日问题,这可能会让我们担心。如果你问一个典型的 2020 年秋季四年级学生,大多数人会在 2010 年 9 月至 2011 年 8 月出生。我们期望比经验分布更高的可变性,因为他们中的每一个都不太可能出生在某一天,比如说,恰好是 2010 年秋天的劳动节。这可能导致不同的解决方案(也许 n=22?)的生日问题。
为了探索这一点,我们可以如下进行。
- 我们可以量化这种差异。kull back–lei bler 散度(KL–div)是两个概率分布之间差异的度量。对于整个数据集和每一年,我们可以计算出均匀分布的变化。
- 我们可以使用蒙特卡罗方法并从基于 1 年的分布中提取数据来重新解决生日问题。为了简单起见,我们将它保持为一个日历年。
对于第一个,我们在下面的图表中确认了我们的预期。年度基础上(0.021 .006)与统一基础上(0 . 002)的差异约为 10 倍。数据似乎还有一个有趣的趋势。我能想到的唯一可能的解释是日历通过一年中 7 个可能的开始日期逐渐循环。闰年打乱了周期,但粗略地说,我们预计,例如,7 月 4 日会从周一到周二再到周三等等。在 6 到 7 年的时间里。
在使用年度数据重新估计生日问题方面,我们可以这样做(使用每 n 10000 次运行的较小模拟规模)。曲线略高于均匀分布(以蓝色显示)。解决方案几乎改变,但事实上,n=23 仍然适用于一屋子同年出生的人。当 n=22 时,2009 年出生的人出现这种情况的概率高达 49.1%,而均匀分布的概率为 47.6%。
因此,事实证明,对于这个问题,统一假设已经足够好了,没有必要再烦恼了。
生日的分布
既然来了,那就看看我们还能从数据中得到什么其他见解吧。
星期几
你可能会惊讶地发现,周末并不是生孩子的好时机。下图显示了在我们的数据集中,一周中任何一天的平均出生人数。显示了 95%的置信区间,该区间很紧,表明周末和工作日之间有统计学上的显著差异,以及周一出生的人数明显较少。
你可能需要记住两个假设。让我们称之为消极和积极的假设(因为你可能对原因有什么感觉)
- 根据我之前与医生的交谈,消极的一面是,产科医生(接生的医生)在周末分娩不方便。如果你可以去你的避暑别墅,为什么整个周末都要随叫随到呢?如果是真的,这将有点令人难过,因为剖腹产对美国医疗保健系统来说是昂贵的,而且它们将意味着不必要的手术以及随之而来的对母亲的风险。
- 积极的一面是,你可以在这个数据分析中找到,医院在一周内都是满员的,所以那时安排剖腹产更安全也更容易。
你可以在那篇 538 文章中读到更多。
回归模型
总的来说,关于这些数据,你可能想问的一般问题是:如何解释任何一天出生人数的变化?以这种方式陈述,我们有一个经典的回归问题。我们想对数据建模,看看我们能学到什么。
我的目标是做一个快速简单的模型。例如,我们可以使用复杂的时间序列/预测工具,如脸书的预言家记录各种各样的假期以及假期的临近,每个假期都可以作为回归变量输入。我不想搞得这么花哨,所以对于协变量我们就用:
- 月份。
- 年份(考虑出生的长期趋势/变化)。
- 一周中的某一天。
- 通过查看图表和思考美国的主要节日,非科学地选择了一些节日。完整的清单在下面的附录中。总共有 17 个假日协变量。
同样,更复杂的分析将使用地理分类数据,并考虑各种因素,如天气、当地运动队的 performance⁴、(当地)经济,以及任何广泛影响人们并使他们和他们的伴侣(我猜是代理人)决定怀孕(或意外怀孕)的因素。
得到的模型非常好,R 为 94%。⁵这意味着 94%的出生率变化可以用这个模型来解释。以下是系数:
出生回归模型的系数
每个系数代表了在其他因素不变的情况下,出生人数的预期变化。你可以在最后链接的 GitHub repo 中找到确切的系数。橙色条显示 95%的置信区间。例如,在圣诞节,系数约为–5300 意味着在考虑月份(12 月)、星期几(变化)和年份后,在我们的数据集中,圣诞节出生的婴儿比我们预期的要少 5300 人。
对于月份表,系数表示相对于一月份的变化。因此,如果我们选择 9 月的某一天与同年 1 月的某一天进行对比,并保持其他所有因素不变(星期几、节假日),我们预计在 9 月的某一天会多出生 1140 人。同样,对于一周中的某一天,一切都与星期一相比。
截距(未示出)是一月份的一个普通星期一的出生人数,大约每天 12,000。随着时间的推移,出生率也略有下降,2000 年后,每天的出生率约减少 33 人,尽管进一步的研究(未显示)表明,这种影响不是线性的,不应过度解读。
情人节是生孩子的好时机,而阵亡将士纪念日周末似乎和其他周末一样好。剩下的假期,感恩节、圣诞节、劳动节、阵亡将士纪念日都相当冷门。我们看到,在主要节假日的其他日子里,影响很大,但较小。
就月份而言,我们看到一个明显的趋势,即出生从春季开始,到夏末初秋,在 9 月达到高峰。据推测,这代表了父母在前一个冬天选择做的事情。星期分析与我们之前看到的非常相似。
我们想问的下一个问题是,我们还错过了其他日子吗?下面显示的是模型的残差,按日期平均。你应该把这解释为之后的某一天的相对受欢迎程度,考虑到一周中的某一天、一个月中的某一天以及有限的假日选择。
具体来说,它显示了每天出生/未出生婴儿的异常平均数。这些残差都四舍五入到最接近的 10。
按日期分列的每日出生人数无法解释的变化
几件事立刻跳了出来。万圣节(10 月 31 日)是一个不受欢迎的生孩子的日子,我们忘了把它包括在内。7 月 5 日不受欢迎。在我的假日快速编码中,7 月 4 日周末之后的星期一(通常是庆祝这一天的日子)不会被包括在内,这可能解释了这一点。12 月 23 日也不受欢迎。
13 号的垂直蓝色条纹表明,在其他条件相同的情况下,人们也不喜欢在 13 号生孩子!他们也不喜欢在 9 月 11 日分娩(至少从 2001 年开始)。看看 12 月,我们发现人们更喜欢在月末生孩子:要么是圣诞节前的一周,要么是圣诞节和新年之间的一周。
结论
人们能够以某种方式控制何时生育,这非常令人着迷。很难说这是一种潜意识现象,是不同程度的压力,还是有意的医疗干预,还是其他什么。
我们已经看到,总的来说,出生的分布非常接近均匀(接近到生日问题的解决方案仍然是 n =23 *)。*另一方面,我们在更小的时间尺度上看到了重大变化:在一周的几天中,以及当以年度为基础进行检查时。但是,即使以年度为基础来看,这仍然不足以改变生日问题的解决方案。
最后,我们研究了出生率变化的模型,发现它主要是由假期、月份和一周中的天数来解释的。对于剩余的无法解释的差异,我们可以指出我们忘记建模的几天:13 号,万圣节,7 月 4 日周末,9 月 11 日,以及圣诞节前后的几天。
附录:假期列表
共有 17 个由节假日引入的协变量。对于每一个,如果包括任何相关联的周末,则所有周末的编码都是相同的。例如,劳动节有两个指示变量:一个是劳动节本身,另一个是劳动节周末。
- 新年、除夕和后天(3)
- 情人节(1)
- 闰日(1)
- 阵亡将士纪念日及其前一个周末(2)
- 7 月 4 日和相邻的周末,如果有的话(2)
- 劳动节和劳动节周末(2)
- 感恩节,前一天,和 Fri-太阳之后(3)
- 圣诞节、平安夜和后天(3)
参考
所有的数字和计算都是我自己的,尽管第一个数字在概念上并不新颖。提供的数据基于社会保障管理局的数据。复制数字和计算的代码可以在 Github 上获得。
笔记
[1]这是一个有时被遗忘的事实,闰年每四年发生一次*,除非这一年能被 100 整除但是*有一个警告,如果这一年能被 400 整除,这个例外就不适用。这意味着 1900 年和 2100 年不是闰年,但是 2000 年和通常的年份:1996 年、2004 年、2008 年等在一起。目前已知的活着的人中,没有一个人在其一生中没有经历过每四年一次的闰年(数据来自 2000 年至 2014 年),因此为了我们的分析目的,我们可以安全地将闰年视为每四年发生一次。我们肯定会忽略像闰秒这样不会对我们的分析产生实质性影响的深奥的东西。
[2]我不打算给出一个非均匀分布应该给出不同曲线的正式证明。但是,直觉上,在一年中的每一天支持的所有分布中,均匀分布最小化了两个人生日相同的概率。任何偏离这一点(由kull back–lei bler-divergence量化)必然导致两个人同一天生日的概率上升。在回购中,你可以找到一个例子,我们越来越多地扭曲数据,差异最终变得肉眼可见。
[3]从技术上讲,我们应该在分配 p 值时考虑多重比较。然而,很明显,仅从数据来看,结果将具有统计学意义。
[4]就我个人而言,在明尼苏达双子队赢得世界冠军 252 天后,我出生在明尼阿波利斯(人类的标准怀孕期是 280 天)。
[5]有关拟合优度的更多数据,请参见 Github repo。拟合的 RMSE 大约是每天 550 个新生儿,尽管分布有厚尾。
线性模型的集合能有多强大?
一组线性模型如何在 Kaggle 上进入 Mercari 价格预测挑战排行榜的前 6%。
随着近年来深度学习算法的快速增长,今天它们已经成为人工智能的最先进水平。这让我想知道传统和老式的机器学习技术,如线性回归,支持向量机等,是否仍然足够体面,可以与深度学习技术相抗衡?
为了检查这些经常被忽视的机器学习技术的能力,我将只使用传统的机器学习技术(没有神经网络)来解决一个 Kaggle 竞赛问题。
注意:我将在这个项目中使用 python 3.7。
博客的鸟瞰图-
该项目分为 6 个主要步骤-
- 业务问题和评估指标
- 关于数据
- 探索性数据分析
- 数据预处理
- 建模
- 从 Kaggle 排行榜获取分数。
B 业务问题及评估指标
很难知道一件东西到底值多少钱。小细节可能意味着价格上的巨大差异。例如,其中一件毛衣售价 335 美元,另一件售价 9.99 美元。你能猜出哪个是哪个吗?
考虑到有多少产品在网上销售,产品定价在规模上变得更加困难。服装有很强的季节性定价趋势,并受品牌名称的影响很大,而电子产品的价格根据产品规格而波动。日本最大的社区购物应用 Mercari 深谙这个问题。他们希望向卖家提供定价建议,但这很难,因为他们的卖家可以在 Mercari 的市场上出售任何东西或任何一捆东西。
在这场竞赛中,我们需要构建一个算法,自动建议正确的产品价格。我们将提供产品的文本描述,以及包括产品类别名称,品牌名称和项目条件等细节的功能。
本次比赛的评价指标为均方根对数误差。RMSLE 的计算方法如下:
其中:
是 RMSLE 值(得分)
n 是(公共/私有)数据集中的观察总数,
pi 是价格的预测,
ai 是 i 的实际销售价格。
log(x) 是 x 的自然对数
注意,由于这种数据的公共性质,这种竞争是一种“只有内核”的竞争。因此,我们需要构建一个代码,在一台拥有 16 GB RAM 和 4 个 CPU 的机器上一小时内执行。
一个 回合的数据
我们将使用的数据由 Mercari 提供,可以通过这个链接在 Kaggle 上找到。这些数据列出了 Mercari 网站上产品的详细信息。
让我们看看网站上的一款产品,以及它在数据集中是如何描述的。
数据集有 8 个特征:
- Train_id/Test_id: 数据集中的每个项目都有一个唯一的项目 id。这将在提交预测价格时使用。
- **名称:代表产品名称,为字符串格式。以上产品名称为【安·兰德源头】
- ***物品状况:*卖家提供的表示物品状况的编号。它可以取 1 到 5 之间的值。在我们的例子中,产品的状态是’好’,所以在数据集中用 4 表示。
- **类别名称:代表物品的类别。对于上面的条目,数据集中提到的类别是‘其他/书籍/文学&小说’ ,这个特征的数据类型也是 string。
- *品牌名称:*代表该商品所属品牌的名称。上述产品的品牌名称为‘企鹅兰登书屋’。
- ***价格:*表示商品的价格,在我们的例子中,这将是我们需要预测的目标值。单位是美元。以上产品,提供的价格为 ‘$9’ 。
- ***运输:*代表产品可用运输类型的编号。如果运费由卖方支付,运费将为 1,如果费用由买方支付,运费将为 0。对于上述产品,运输是免费的,因此在数据集中,此功能将为 1。
- **物品描述:**物品的完整描述。对于上述产品,说明中写道,《源泉》袖珍平装书——安·兰德——百年纪念版——经典文学——书的状况良好,封面和边角有一些磨损(见图片)。该特征已经以预处理的形式出现在所提供的数据集中。
让我们使用 pandas 导入数据,并检查前 5 个条目。
*import pandas as pd
data = pd.read_csv('train.tsv', sep='\t')
df_test = pd.read_csv('test.tsv', sep='\t')
data.head()*
E勘探数据分析(EDA)
在这一部分,我们将深入探索和分析数据。我们将逐一介绍这些数据。
价格
这是我们需要使用其他特征形式的产品信息来预测的目标特征。
让我们使用 describe()查看该特性的统计摘要
*data['price'].describe()*
- 数据集中大约有 148 万个产品。最贵的产品定价为 2009 美元,最便宜的产品定价为 3 美元,而平均价格为 26.75 美元
现在我们来看看价格直方图。在这里,我使用的箱数是 200。
*plt.hist(data['price'], bins=200)
plt.xlabel('price')
plt.ylabel('frequency')
plt.title('histogram of price')
plt.show()*
- 我们可以观察到分布遵循幂律分布,为了解决这个问题,并使其成为高斯分布,让我们将这些值转换为对数形式,即我们将用 log(price+1)替换价格值。
我们将价格转换为正态分布,因为它是统计学中最著名的分布之一,因为它符合许多自然现象,这使它成为我们可以进行分析的最容易解释的分布之一。将数据转换为正态分布的另一个原因是价格的方差减少了,并且大多数点都以平均值为中心,这使得模型的价格预测更加容易。
我已经把数据转换成了日志形式。下面是日志的直方图(价格+1)。
*plt.hist(data['price_log'], bins=20)
plt.xlabel('log(price + 1)')
plt.ylabel('frequency')
plt.title('histogram of log of price')
plt.show()*
- 我们可以观察到,分布现在更容易解释,并试图遵循正态分布。
- 此外,请注意大多数点是如何以平均值为中心的(平均值接近 3)。
项目条件标识
这是表示物品状况的分类特征。让我们使用 value_counts()查看更多信息
*data['item_condition_id'].value_counts()*
- 输出告诉我们,这个特性可以占用 1 到 5 之间的 5 个值,并且具有特定条件的项目的数量就在它的旁边。
让我们看看这个特性的条形图
*sns.barplot(x=data['item_condition_id'].value_counts().keys(),
y=data['item_condition_id'].value_counts())
plt.xlabel('item condition type')
plt.ylabel('number of products')
plt.title('bar graph of "item condition type"')
plt.show()*
- 我们可以看到,大多数项目的条件 id 为 1,只有极少数项目的条件 id 为 5。
现在让我们比较具有不同 item_condition_id 的产品的价格分布
**
- 我们可以看到,具有不同 item_condition_id 的项目的价格分布非常相似。
让我们来看看具有不同 item_condition_id 的产品的价格分布的箱线图和小提琴图。
*# plotting box-plot
sns.boxplot(x='item_condition_id', y='price_log', data=data)
plt.show()# plotting violin plot
sns.violinplot(x='item_condition_id', y='price_log', data=data)
plt.show()*
箱线图和 violin 图还告诉我们,具有不同 item_condition_id 的商品的价格分布差别不大,而且分布有点向右倾斜。item_condition_id = 5 的产品具有最高的中间价格,而 item_condition_id = 4 的产品具有最低的中间价格。大多数产品的价格在 1.5 英镑到 5.2 英镑之间
类别名称
这是一个文本类型的数据,告诉我们产品的类别。
我们来看看特征类别名称的统计汇总-
*data['category_name'].describe()*
这些是字符串类型的特征,实际上是三个子类别合并成一个。
让我们考虑上面描述中提到的最频繁出现的类别名称特征“女性/运动服装/裤子、紧身衣、打底裤”。它可以分为 3 个子类别:
-子类别 _1:“女性”
-子类别 _2:“运动服装”
-子类别 _3:“裤子、紧身衣、打底裤”
为了使该特征的可视化更容易,我将考虑该特征的子类别。让我们把数据分成小类。
*# this is to divide the category_name feature into 3 sub categories
from tqdm import tqdm_notebook
sub_category_1 = []
sub_category_2 = []
sub_category_3 = []for feature in tqdm_notebook(data['category_name'].values):
fs = feature.split('/')
a,b,c = fs[0], fs[1], ' '.join(fs[2:])
sub_category_1.append(a)
sub_category_2.append(b)
sub_category_3.append(c)data['sub_category_1'] = sub_category_1
data['sub_category_2'] = sub_category_2
data['sub_category_3'] = sub_category_3*
子类别 _1
让我们检查一下统计描述:
*data['sub_category_1'].describe()*
- 在我们的数据中,大约有 140 万个这样的函数,可以接受 11 个不同的值。其中最常见的是女性。
让我们绘制子类别 1 的条形图
*sns.barplot(x=data['sub_category_1'].value_counts().keys(), y=data['sub_category_1'].value_counts())
plt.ylabel('number of products')
locs, labels = plt.xticks()
plt.setp(labels, rotation=90)
plt.title('bar-plot of sub_category_1')
plt.show()*
- 我们可以看到,大多数项目的子类别 1 为“女性”,最少的项目为“运动和户外”。
- 请注意,没有定义 sub_category_1 的项目用“无标签”表示。
让我们检查 sub_category_1 的分布和价格日志
*sns.FacetGrid(data, hue="sub_category_1", height=5).map(sns.distplot, 'price_log').add_legend();
plt.title('comparing the log of price distribution of products with
sub_category_1\n')
plt.ylabel('PDF of log of price')
plt.show()*
- 我们可以看到,大多数分布都是右偏的,只有一点差异。
- “手工制作”子类别略有不同,因为我们可以看到该类别中的一些产品的 log(价格)低于 2
现在让我们来看看子 _ 类别 _1 的小提琴情节
- 查看小提琴图,我们可以说,子类别 1 为“男士”的商品的销售往往更贵,而子类别 1 为“手工”的商品往往更经济。
子类别 2
让我们检查 sub_category_2 的统计描述:
*data['sub_category_2'].describe()*
- sub_category_2 有 114 个不同的值,让我们分析一下 sub_category_2 的前 20 个类别。
sub_category_2 中前 20 个类别的条形图
*plt.figure(figsize=(12,8))
sns.barplot(x=data['sub_category_2'].value_counts().keys()[:20],
y=data['sub_category_2'].value_counts()[:20])
plt.ylabel('number of products')
locs, labels = plt.xticks()
plt.setp(labels, rotation=90)
plt.title('bar-plot of top 20 sub_category_2')
plt.show()*
- 我们可以看到,大多数商品都有 sub_category_2,即“正宗服装”,其次是“化妆品”,然后是“上衣和衬衫”。
子类别 3
让我们检查 sub_category_3 的统计描述:
- sub_category_3 有 865 个不同的值,让我们分析一下 sub_category_3 的前 20 个类别的直方图。
- 我们可以看到,大多数商品都有 sub_category_3,如“裤子、紧身衣、打底裤”,后面是“其他”和“面部”。
品牌名称
这是另一个文本类型特征,表示产品所属的品牌。让我们来看看特性 brand_name 的统计摘要。
- 在这里,我们可以看到共有 4089 个不同的品牌名称。
让我们看看前 20 个品牌的直方图
*plt.figure(figsize=(12,8))
sns.barplot(x=data['brand_name'].value_counts().keys()[:20],
y=data['brand_name'].value_counts()[:20])
plt.ylabel('number of products')
locs, labels = plt.xticks()
plt.setp(labels, rotation=50)
plt.title('bar-plot of top 20 brands (including products with
unknown brand)')
plt.show()*
- 请注意,这里的“未知”表示没有指定品牌的商品。
- PINK、Nike 和 Victoria’s Secret 是网站上商品最多的前三大品牌。
让我们看看 20 大品牌及其平均产品价格的柱状图。
*plt.figure(figsize=(12,8))
sns.barplot(x=df['brand_name'].values[:20],
y=df['price'].values[:20])
plt.ylabel('average price of products')
locs, labels = plt.xticks()
plt.setp(labels, rotation=50)
plt.title('bar-plot of top 20 brands with their mean product price')
plt.show()*
让我们看看产品价格最高的前 20 个品牌的柱状图
运输
这是一种数值分类数据类型,可以取 2 个值,0 或 1
让我们来看看它的统计描述。
*data['shipping'].value_counts()*
- 发货为 0 的商品比发货为 1 的多 22%。
我们来对比一下不同出货的产品价格分布日志。
- 我们可以看到,不同运输的项目的价格分布日志略有差异。
- 运费为 1 的产品往往价格较低。
项目 _ 描述(正文)
这是描述产品的文本类型特征。让我们来看看其中的一些。
*data['item_description']*
- 我们可以看到这些总共有 1482535 个。
我们将在执行一些 NLP 技术后使用这个特性,这些技术将在本博客的后面讨论。
我们可以对该功能做的另一件事是,计算它的字长,即该功能包含每个产品的字数,并对其进行分析。
我们来查看一下物品描述的 word_length 的统计汇总。
*data['item_description_word_length'].describe()*
- 我们可以看到最长的描述有 245 个字,最短的没有字。平均来说,单词在 25 个左右
我们来绘制 item_description_word_length 的直方图,
*plt.hist(data['item_description_word_length'], bins=200)
plt.xlabel('item_description_word_length')
plt.ylabel('frequency')
plt.title('histogram of item_description_word_length')
plt.show()*
- 我们可以看到,字长直方图遵循幂律分布。
- 这个直方图我用了 200 个面元。
让我们通过取单词长度的对数,试着把这个转换成正态分布。这是分布图。
*plt.hist(data['log_item_description_word_length'])
plt.xlabel('log(item_description_word_length + 1)')
plt.ylabel('frequency')
plt.title('histogram of log of item_description_word_length')
plt.show()*
- 我们可以看到,这个特征试图遵循正态分布。
- 大多数项目的单词长度在 5 到 20 之间。(从 antilog 获得的值)。
- 我们可以将此作为建模的一个特征。
现在让我们看看 log(item_word_length)如何影响商品的价格
- 我们可以看到,随着 item_word_length 从 0 到 50,价格的对数增加,但随后价格趋于下降,除了我们可以在大约 190 的字长附近观察到的峰值。
- 此外,单词长度超过 100 的价格波动更大。
产品名称
最后,让我们看看最后一个特性,即产品的名称。这也是一个文本类型特征,我们稍后将对其执行 NLP,但首先,让我们通过绘制“名称”特征中单词数量的直方图来对其进行一些分析。
*plt.hist(data['name_length'])
plt.xlabel('name_length')
plt.ylabel('frequency')
plt.title('histogram of name_length')
plt.show()*
- 这种分布明显是左倾的,最大条目的名称长度大约为 25。
让我们看看价格是如何随着产品名称的字数而变化的。
*df = data.groupby('name_length')['price_log'].mean().reset_index()
plt.figure(figsize=(12,8))
sns.relplot(x="name_length", y="price_log", kind="line", data=df)
plt.show()*
- 请注意,我使用的是价格日志,而不是实际价格。
- 我们可以看到,name_length 值在 10 到 38 之间的分布非常线性,然后有一个急剧的下降和上升。
DT11数据预处理**
*在这一步中,我们将清理数据,并为建模做好准备。
记住,我们有 6 个特征,其中有:
- 4 个文本特征:名称、描述、品牌名称和类别
- 2 个分类特征:运输和商品条件 id*
让我们从清理文本特征开始,为此,我们将定义一些函数-
*import re
def decontracted(phrase):
# specific
phrase = re.sub(r"won't", "will not", phrase)
phrase = re.sub(r"can\'t", "can not", phrase)
# general
phrase = re.sub(r"n\'t", "not", phrase)
phrase = re.sub(r"\'re", " are", phrase)
phrase = re.sub(r"\'s", " is", phrase)
phrase = re.sub(r"\'d", " would", phrase)
phrase = re.sub(r"\'ll", " will", phrase)
phrase = re.sub(r"\'t", " not", phrase)
phrase = re.sub(r"\'ve", " have", phrase)
phrase = re.sub(r"\'m", " am", phrase)
return phrase*
该功能的工作原理是将单词从“我们将”分解为“我们将”,“不能”分解为“不能”,“我们是”分解为“我们是”等。这一步是必要的,因为我们不希望我们的模型以不同的方式对待像“我们是”和“我们是”这样的短语。
*stopwords= ['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're", "you've","you'll", "you'd", 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', "she's", 'her', 'hers', 'herself', 'it', "it's", 'its', 'itself', 'they', 'them', 'their','theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', "that'll", 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after','above', 'below', 'to', 'from', 'up', 'down', 'in','out','on','off', 'over', 'under', 'again', 'further','then', 'once', 'here', 'there', 'when', 'where', 'why','how','all', 'any', 'both', 'each', 'few', 'more','most', 'other', 'some', 'such', 'only', 'own', 'same', 'so','than', 'too', 'very', 's', 't', 'can', 'will', 'just','don',"don't",'should',"should've", 'now', 'd', 'll', 'm', 'o','re','ve','y','ain','aren',"aren't",'couldn',"couldn't",'didn',"didn't", 'doesn', "doesn't", 'hadn',"hadn't", 'hasn', "hasn't", 'haven', "haven't", 'isn', "isn't",'ma', 'mightn', "mightn't", 'mustn',"mustn't", 'needn', "needn't",'shan',"shan't",'shouldn',"shouldn't", 'wasn', "wasn't", 'weren', "weren't", 'won', "won't", 'wouldn', "wouldn't", '•', '❤', '✨', '$', '❌','♡', '☆', '✔', '⭐','✅', '⚡', '‼', '—', '▪', '❗', '■', '●', '➡','⛔', '♦', '〰', '×', '⚠', '°', '♥', '★', '®', '·','☺','–','➖','✴', '❣', '⚫', '✳', '➕', '™', 'ᴇ', '》', '✖', '▫', '¤','⬆', '⃣', 'ᴀ', '❇', 'ᴏ', '《', '☞', '❄', '»', 'ô', '❎', 'ɴ', '⭕', 'ᴛ','◇', 'ɪ', '½', 'ʀ', '❥', '⚜', '⋆', '⏺', '❕', 'ꕥ', ':', '◆', '✽','…', '☑', '︎', '═', '▶', '⬇', 'ʟ', '!', '✈', '�', '☀', 'ғ']*
在上面的代码块中,我定义了一个包含停用词的列表。停用词是不会给句子增加太多语义或字面意义的词。其中大部分是单词或不太重要的单词的压缩表示,如“a”、“at”、“for”等,以及符号。
现在我们将定义一个函数,该函数获取句子,并使用解串函数和停用词列表来清理和返回处理过的文本。
*from tqdm import tqdm_notebook
def preprocess_text(text_data):
preprocessed_text = []
# tqdm is for printing the status bar
for sentence in tqdm_notebook(text_data):
sent = decontracted(sentence)
sent = sent.replace('\\r', ' ')
sent = sent.replace('\\n', ' ')
sent = sent.replace('\\"', ' ')
sent = re.sub('[^A-Za-z0-9]+', ' ', sent)
sent = ' '.join(e for e in sent.split() if e.lower() not in
stopwords)
preprocessed_text.append(sent.lower().strip())
return preprocessed_text*
使用 preprocess_text()函数清理文本数据的时间到了。
*df['name'] = df['name'].fillna('') + ' ' +
df['brand_name'].fillna('')
df['name'] = preprocess_text(df.name.values)df['text'] = (df['item_description'].fillna('')+
' ' + df['category_name'].fillna(''))
df['text'] = preprocess_text(df.text.values)df_test['name'] = df_test['name'].fillna('') + ' '
+ df_test['brand_name'].fillna('')
df_test['text'] = (df_test['item_description'].fillna('') + ' '
+ df_test['category_name'].fillna(''))*
请注意,df[‘name’]列包含连接和预处理的’ name ‘和’ brand_name ‘功能,同样,df[‘text’]功能包含连接和预处理的’ item_description ‘和’ category_name '功能。
让我们继续进一步的过程,但在此之前,我们需要将数据分成训练集和交叉验证集。此外,我们将把目标值(即价格)转换成对数形式,以便它们呈正态分布,并且 RMSLE(均方根对数误差)易于计算。
*df = df[['name', 'text', 'shipping', 'item_condition_id']]
X_test = df_test[['name', 'text', 'shipping', 'item_condition_id']]from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScalery_scaler = StandardScaler()
X_train, X_cv, y_train, y_cv = train_test_split(df, y,
test_size=0.05, random_state=42)
y_train_std =
y_scaler.fit_transform(np.log1p(y_train.values.reshape(-1, 1)))*
现在是时候将这些预处理过的文本特征转换成数字表示了。在这个过程中,我将使用 TF-IDF 矢量器。我们将从特性“名称”开始
*from sklearn.feature_extraction.text import TfidfVectorizer as Tfidftfidf = Tfidf(max_features=350000, token_pattern='\w+', ngram_range=(1,2)) # using only top 350000 tf-idf features (with bi-grams).
X_tr_name = tfidf.fit_transform(X_train['name'])
X_cv_name = tfidf.transform(X_cv['name'])
X_test_name = tfidf.transform(X_test['name'])*
接下来是“文本”功能
*tfidf = Tfidf(max_features=350000, token_pattern='\w+', ngram_range=(1,3)) # using only top 350000 tf-idf features (with tri-grams).
X_tr_text = tfidf.fit_transform(X_train['text'])
X_cv_text = tfidf.transform(X_cv['text'])
X_test_text = tfidf.transform(X_test['text'])*
让我们也处理从“shipping”开始的其余分类特征
因为这个特征只取 2 个值 0 和 1,我们不需要对它们进行某种特殊的编码,让我们保持它们不变。
*from scipy import sparse
X_tr_ship =
sparse.csr_matrix(X_train['shipping'].values.reshape(-1,1))
X_cv_ship = sparse.csr_matrix(X_cv['shipping'].values.reshape(-1,1))
X_test_ship =
sparse.csr_matrix(X_test['shipping'].values.reshape(-1,1))*
第二个分类特征是‘item _ condition _ id’,它也是一个顺序特征。请记住,这些可以接受 5 个整数值(1–5 ),因此我们也将保持原样。
*X_tr_condition =
sparse.csr_matrix(X_train['item_condition_id'].values.reshape(-1,1)
- 1.)
X_cv_condition =
sparse.csr_matrix(X_cv['item_condition_id'].values.reshape(-1,1)
- 1.)
X_test_condition =
sparse.csr_matrix(X_test['item_condition_id'].values.reshape(-1,1)
- 1.)*
请注意,我使用了-1,因为该特性包含 5 种介于(1–5)之间的值,所以-1 会将它们转换为(0–4)的范围。这将在转换为稀疏数据时给我们带来优势。
现在,作为最后一步,我们将按列堆叠这些特性。
我现在将把这些预处理过的数据转换成二进制形式,其中的值只能是 1 或 0。
*X_tr_binary = (X_tr>0).astype(np.float32)
X_cv_binary = (X_cv>0).astype(np.float32)
X_test_binary = (X_test>0).astype(np.float32)*
这一步的优点是,现在我们将有 2 个具有良好方差的数据集要处理。
M odeling
*是时候用我们的数据测试一些模型了。我们将要尝试的模型是-
-岭回归器
-线性 SVR
- SGD 回归器
-随机森林回归器
-决策树回归器 - XGBoost 回归器*
正态数据的岭回归量
线性回归
我们使用线性回归来寻找最优超平面(上面 gif 中的红线),使得损失或每个点到平面/直线的距离之和的平方最小。我们可以注意到,如果我们考虑在迭代次数=28 次时得到的线,损失将是最小的。
岭回归也称为 L2 正则化线性回归,这意味着它使用权重平方和作为惩罚。添加惩罚项是为了限制模型过度拟合(捕捉噪声)。
岭回归只有 1 个超参数 λ ,它与惩罚/正则化项相乘,并决定模型经历的欠拟合程度。λ的值越大,我们欠拟合越多。
alpha 就是正则化强度,它必须是一个正浮点数。因此,随着α的增加,欠拟合也会增加。
*import matplotlib.pyplot as plt
plt.plot(alpha_list, train_loss, label='train loss')
plt.plot(alpha_list, test_loss, label='test loss')
plt.title('alpha VS RMSLE-loss plot')
plt.xlabel('Hyperparameter: alpha')
plt.ylabel('RMSLE loss')
plt.xscale('log')
plt.legend()
plt.show()*
- 我们可以观察到,随着 alpha 的降低,模型开始过度拟合。
- α= 1 时,试验损失最小。
好的,我们的岭在 cv 数据上返回了 0.4232 的损失。
二元数据的岭回归
现在我们将对二进制数据使用岭回归
*import matplotlib.pyplot as plt
plt.plot(alpha_list, train_loss, label='train loss')
plt.plot(alpha_list, test_loss, label='test loss')
plt.title('alpha VS RMSLE-loss plot (on binary features)')
plt.xlabel('Hyperparameter: alpha')
plt.ylabel('RMSLE loss')
plt.xscale('log')
plt.legend()
plt.show()*
- 我们可以观察到,当α= 100 时,损耗最小。
我们的岭回归在 cv 数据上返回了 0.4335 的损失。
让我们在二进制数据上尝试 SGD-Regressor(作为 SVR)
https://gifer.com/en/gifs/gradient
让我们快速刷新一下 SGD 是什么,它是如何工作的。还记得我在岭回归中提到的损失吗?损失有不同的类型,让我们从几何角度来理解。如果回归问题就是寻找最适合我们数据的最优超平面,那么损失仅仅意味着我们的数据与超平面有多大差异。因此,低损失意味着这些点与我们的超平面差别不大,模型表现良好,反之亦然。
在线性回归的情况下,损失是平方损失,它是通过将数据点到超平面的平方距离的总和除以项数而获得的。
损失函数很重要,因为它们定义了超平面是什么样子。还有其他被称为梯度下降的算法,它们利用这些损失函数并更新超平面的参数,以使其完美地拟合数据。这里的目标是最小化损失。SGD 是一种优化算法,通过逐步减少损失来更新超平面的参数。这是通过计算损失函数相对于特征的梯度,然后使用这些梯度向最小值下降来实现的。在上图(左部)中,我们可以看到该算法如何通过向山下走正确的一步来达到损失函数的最小值,并且随着每一步都在正确的方向上,参数得到更新,这导致更好的拟合超平面(右部)。要了解更多关于随机梯度下降(SGD)算法的信息,你可以查看这篇精彩的博客。
以下是一些其他常见损耗,但我们将使用“Huber”、“epsilon_insensitive”和“squared_epsilon_insensitive”来调整该模型的超参数。
随机搜索交叉验证告诉我们,L2 正则化的“平方ε不敏感”损失最适合此数据。顺便说一句,“平方ε不敏感”损失是另一个众所周知的机器学习算法支持向量机使用的损失之一,支持向量机通过利用支持向量来生成更好的拟合超平面,从而使用最大限度技术。
- 在该图中,虚线称为决策边界,位于虚线上的点称为支持向量,SVR 的目标是最大化这些决策边界之间的距离。
但是,为什么利润最大化如此重要,以至于 SVM 成为顶级最大似然算法之一?让我们使用一个简单的分类问题来快速理解这一点,我们需要找到一个分离蓝点和红点的最佳超平面。
https://medium . com/coin monks/support-vector-regression-or-SVR-8e B3 ACF 6d 0 ff
- 请看图中由名称超平面和最优超平面表示的两个平面。任何人都可以看出,最优超平面在分离蓝色和红色点方面比另一个平面好得多,并且使用 SVM,这个最优超平面几乎是有保证的。
一个有趣的事实是,“平方ε不敏感”损失中的平底部分是由于这种利润最大化技巧。可以参考本和本博客了解更多关于 SVR 的内容。
SGD 回归器(作为 SVR)在 cv 数据上返回 0.4325…的损失。
让我们在二进制数据上试试 SGD 回归器(作为线性回归器)
在这里,我们将执行所有先前的步骤,但针对的是二进制数据。
随机搜索交叉验证告诉我们,L2 正则化的“平方损失”损失最适合此数据。顺便说一下,L2 正则化的平方损失的设置听起来很熟悉,对吗?这正是我们在岭回归模型中使用的。在这里,我们从优化问题的角度来处理这个问题,因为 SGDRegressor 为我们提供了更多的超参数来调整我们的模型。
SGD 回归器(作为线性回归器)在 cv 数据上返回 0.4362 的损失。
正常数据的线性支持向量回归
让我们在正常数据上尝试支持向量回归机。这里的超参数是 C,也是我们在岭回归中讨论过的α的倒数。
*import matplotlib.pyplot as plt
plt.plot(C, train_loss, label='train loss')
plt.plot(C, test_loss, label='test loss')
plt.title('alpha VS RMSLE-loss plot (on binary features)')
plt.xlabel('Hyperparameter: C (1/alpha)')
plt.ylabel('RMSLE loss')
plt.xscale('log')
plt.legend()
plt.show()*
- 我们可以看到,0.1 是超参数 C 的最佳超参数值,它使我们的测试损失最小。
线性 SVR 在正常数据的 CV 上返回 0.4326 的损失。
二进制数据的线性支持向量回归
现在,我们将对二进制数据尝试支持向量回归机。这里的超参数也是 C,也是我们在岭回归中讨论过的α的倒数。
*import matplotlib.pyplot as plt
plt.plot(C, train_loss, label='train loss')
plt.plot(C, test_loss, label='test loss')
plt.title('alpha VS RMSLE-loss plot (on binary features)')
plt.xlabel('Hyperparameter: C (1/alpha)')
plt.ylabel('RMSLE loss')
plt.xscale('log')
plt.legend()
plt.show()*
- 我们可以看到,0.01 是超参数 C 的最佳超参数值,它使我们的测试损失最小。
线性 SVR 在二进制数据的 cv 上返回 0.4325 的损失。
基于树的模型
注意:我尝试的另一个维度技术是 truncated-SVD,但是它需要大量的 RAM(超过 16 GB)来进行计算,并且因为这是一个内核挑战,所以使用完整的数据没有多大意义。
为基于树的模型选择顶级特征:
*from sklearn.feature_selection import SelectFromModelfrom sklearn.linear_model import SGDRegressor
regressor = Ridge(alpha=100)
selection = SelectFromModel(regressor)
selection.fit(X_tr_binary, y_train_std.ravel())X_train_top = selection.transform(X_tr_binary)
X_cv_top = selection.transform(X_cv_binary)
X_test_top = selection.transform(X_test_binary)*
决策树
我们的第一个基于树的模型是决策树,在我们的数据集上使用它之前,让我们先快速了解它是如何工作的。
https://www . datascience central . com/profiles/blogs/the-complete-guide-to-decision-trees
*决策树由简单的 if-else 语句组成,使用这些条件,它们决定如何预测给定名称、条件等的产品价格。从几何学上讲,它们使用几个平行于轴的超平面来拟合数据。
在训练树的同时,树通过使用和验证训练数据来学习这些 if-else 语句。当它被训练时,它使用这些学习到的 if-else 条件来预测测试数据的值。
但是它是如何决定如何拆分数据或者在拆分数据和构建完整的树时考虑什么特征的呢?
嗯,它使用一种叫做熵的东西来构建树,熵是一种确定性的度量。
决策树有几个超参数,但我们将只考虑其中两个重要的-
- max_depth: 它表示决策树的最大深度。因此,如果 max_depth 假定为 4,则在训练时,构造的树的深度不会超过 4。
-*min _ samples _ split:表示执行分割或考虑 if-else 条件时必须存在的最小数据点数。因此,如果 min_samples_split 假定为 32,则在训练时,如果所构造的树看到的数据点少于 32 个,则它不会应用 if-else 条件。
以上两个超参数都限制了决策树的不足或过度捕捞。高的 max_depth 和低的 min_samples_split 值使决策树更容易过度拟合,反之亦然。
https://sci kit-learn . org/stable/auto _ examples/tree/plot _ tree _ regression . html
- 在此图中,我们可以看到一个经过训练的决策树算法如何尝试拟合数据,请注意拟合线是如何由轴平行线组成的。
- 我们还可以注意到,max_depth 值越大的决策树也越容易捕捉到噪声点。
我不会在这个博客中深入讨论决策树的内部工作原理,因为这会使它变得太长,要了解更多关于决策树的内部工作原理,你可以查看这个很棒的博客。
让我们使用 RandomSearchCV 对我们的决策树执行一些超参数调整,并检查什么是我们的树的最佳超参数。
返回的最佳超参数值是 max_depth=64 和 min_samples_split = 64。现在让我们检查在这些超参数上训练决策树之后获得的损失。
考虑到训练需要 14 分钟,损失值并不是很大。到目前为止,我们的线性模型已经超过了决策树模型。
随机森林—(最大深度=3,n 估计值=100)
现在,让我们使用另一个非常棒的基于树的模型,或者我应该说模型来模拟我们的数据。
随机森林是由多个模型组成的集合。这个想法是使用数据的随机部分来训练多个模型,然后使用来自这些多个模型的平均预测作为最终值。这是有意义的,因为使用完整数据的随机部分训练几个模型会创建在不同方面存在一定程度偏差的模型。现在,从所有这些模型中取平均预测值,最终会得到一个更好的预测值。
随机森林这个名称来自于我们在从训练数据集中随机采样数据时使用的 Bootstrap 采样,由于我们使用多个决策树作为我们的基础模型,所以它有单词森林。**
https://towards data science . com/random-forest-and-its-implementation-71824 ced 454 f
上图显示了随机森林如何使用随机采样数据训练不同的基础学习者,分别表示为树 1、树 2…然后收集并平均这些树的预测。
随机森林有多个超参数,但对于我们的数据,我们将只使用 2:
- n_estimator: 这表示我们希望随机森林模型拥有的基础模型的数量。
- max_depth: 表示每个基础模型即决策树的最大深度。
让我们训练一个随机森林模型,并对其执行一些超参数调整。
这个模型的训练时间大约是 23 分钟。
我们可以看到,这个模型在给定的数据集上表现不好,结果一点也不好。
随机森林—(最大深度=4,n 估计值=200)
这里我使用了相同的模型,但是在架构上做了一些改变。我已经把最大深度增加到了 4,基础学习者的数量增加到了 200。
我们来看看模特表现如何。
该模型的训练时间约为 65 分钟。
结果略好于之前的随机森林模型,但仍然不接近我们的线性模型。
XGBoost — (max_depth=4,n_estimators=200)
【https://github.com/bgreenwell】
这是我们将尝试的最后一个基于树的模型,它被称为 XGBoost。XGBoost 是 GBDT 的略微增强版本,它也是一种集合建模技术。在梯度增强中,目的是减少方差或减少数据集的欠拟合行为。让我们看看它是如何工作的。
http://uc-r.github.io/gbm_regression
在 GBDT,我们首先使用训练数据训练我们的第一个基本模型,这通常是一个高偏差决策树,然后我们从该模型中获取预测值,并计算由预测值与实际值的差异定义的误差。现在我们训练我们的第二个基础学习者,但是这次我们不仅仅使用训练数据,我们还使用从我们的第一个基础学习者获得的误差,并且我们再次从这个模型中获取预测值并计算误差。这一直持续到覆盖了所有的基础学习者,当我们一个接一个地训练基础学习者时,我们注意到误差值慢慢地减小。你可以在这里阅读更多关于 GBDT 的信息。
XGBoost 是 GBDT 的一个稍微修改的版本,它使用像随机森林中的行采样和列采样这样的技术来构造基础学习器。
*让我们快速检查一下 XGBoost 的代码,我将使用 2 个超参数:
- n_estimators:它表示作为决策树模型的基础学习者的数量。
- max_depth:表示基础学习器决策树的最大深度。*
该模型花了大约 27 分钟来训练。
结果没有随机森林差,但也没有线性模型好。
XGBoost — (max_depth=6,n_estimators=500)
让我们试试 XGBoost,max_depth=6,n_estimators=500。
我们可以看到一个体面的数量从以前的模型改进,但它需要模型 78 分钟的训练。
让我们比较不同的型号及其性能:
在上表中,我们可以看到基于树的模型花费了太多的计算时间,事实上,我用于基于树的数据要小得多,我只使用了从岭回归器中选择的顶部二元特征。因此,新数据只有大约 236k 个特征,而不是其他线性模型训练的原始 700k 个特征。我们还可以观察到,我们能够获得的交叉验证数据的最小损失是 0.4232…让我们尝试使用集成建模来进一步减少这一损失。
线性模型已经胜过其他基于树的模型,所以我将使用这些来创建一个集合。
让我们把前 6 个线性模型的结果串联起来。
**
现在,让我们快速测试一个简单的集合,该集合将这些特征作为输入,并将输出计算为这些值的平均值。
我们可以观察到损失略有增加,这意味着这种方法本身不足以产生好的分数。
现在,让我们检查这些新特征之间的相关性,因为它们都来自线性模型,并且产生类似的损失。如果它们高度相关,它们不会对整体损失有太大改善。
*import seaborn as sns
import matplotlib.pyplot as plt
plt.figure(figsize=(10,8))
columns = ['y_pred_ridge_binary_tr', 'y_pred_ridge_normal_tr',
'y_pred_svr_normal_tr','y_pred_svr_binary_tr',
'y_pred_sgd_lr_binary_tr', 'y_pred_sgd_svr_binary_tr']
df = pd.DataFrame(y_pred_tr_ensemble, columns=columns)
Var_Corr = df.corr()
sns.heatmap(Var_Corr, xticklabels=Var_Corr.columns,
yticklabels=Var_Corr.columns, annot=True)
plt.title('Correlation between different features.')
plt.show()*
- 我们可以看到,来自基础模型的结果是高度相关的,因此在它们的基础上构建一个集成并不能获得多少分数。
为了解决这个问题,我增加了数据的维度,添加了从线性模型中收集的顶级特征,这些数据是我们用来训练基于树的模型的二进制数据。
现在是时候在这些新生成的特征上尝试不同的模型,看看我们是否可以改善这种损失。
让我们试试使用不同超参数的 SGD 回归器
上面的代码块代表了 RandomSearchCV 返回的最佳超参数。
CV 损失没有达到标准,因为我们已经损失了 0.4232…我们正在寻找比这更低的损失。
让我们在新功能上试试线性支持向量回归机和岭回归机
*import matplotlib.pyplot as plt
ridge_loss = np.array(ridge_loss)
linearsvr_loss = np.array(linearsvr_loss)
plt.plot(alpha, ridge_loss.T[0], label='Ridge train')
plt.plot(alpha, ridge_loss.T[1], label='Ridge test')
plt.plot(alpha, linearsvr_loss.T[0], label='linearsvr train')
plt.plot(alpha, linearsvr_loss.T[1], label='linearsvr test')
plt.xlabel('Hyperparameter: alpha or (1/C)')
plt.ylabel('loss')
plt.xscale('log')
plt.title('Linear SVR and Ridge losses')
plt.legend()
plt.show()*
- 我们可以看到,在 alpha=100000 时,岭回归和线性 SVR 返回的 cv 损失最小。让我们把模型放在那上面。
用 alpha = 100000 训练岭回归方程
用 C = 0.00001 训练线性 SVR
**
好了,通过查看上表,我们可以知道山脊和 LinearSVR 模型产生了最好的结果,所以我们将使用这些来生成一个和我们的系综的最后一层。
让我们使用这些模型快速拟合数据,并将输出连接起来,作为最终集合层的输入。
现在,我们将使用先前图层模型生成的输出来创建总体的最终图层。我们将使用一些线性模型,但在此之前,让我们测试简单的平均结果。
结果比单独的 LinearSVR 模型要好,但是到目前为止,岭仍然优于每个模型。
现在让我们为最后一层尝试一些线性模型:
新币回归器
**
让我们尝试使用岭和线性支持向量回归作为最终的图层模型
*import matplotlib.pyplot as plt
ridge_loss = np.array(ridge_loss)
linearsvr_loss = np.array(linearsvr_loss)
plt.plot(alpha, ridge_loss.T[0], label='Ridge train')
plt.plot(alpha, ridge_loss.T[1], label='Ridge test')
plt.plot(alpha, linearsvr_loss.T[0], label='linearsvr train')
plt.plot(alpha, linearsvr_loss.T[1], label='linearsvr test')
plt.xlabel('Hyperparameter: alpha or (1/C)')
plt.ylabel('loss')
plt.xscale('log')
plt.title('Linear SVR and Ridge losses')
plt.legend()
plt.show()*
- 结果接近,但岭回归优于线性回归。
**
这里是用于集合的所有模型,以表格形式进行比较。
**
F 最后,让我们预测测试数据集的价格,并检查我们的组合在 Kaggle 排行榜上的表现。
在提交预测结果后,我获得了 0.42457 的分数,相当于 Kaggle 排行榜上的前 6%。
https://www . ka ggle . com/c/mercari-price-suggestion-challenge/submissions
福 未来工作
- 这个问题可以使用深度学习算法来解决,如 GRU,MLP,伯特,因为大多数特征来自文本描述。我们可以在这些数据上尝试这些最先进的技术,并尝试提高分数。
- 代码没有针对多处理进行优化,因此它使用所有 4 个 CPU。我认为这值得一试,因为这样的话,即使是基于树的模型也可以加入到整体中。
*R**引用 ***
- https://www . ka ggle . com/c/mercari-price-suggestion-challenge/discussion/50256
- https://www.youtube.com/watch?v=QFR0IHbzA30
- https://youtu.be/_PwhiWxHK8o
- https://youtu.be/UHBmv7qCey4
- https://www.appliedaicourse.com/
福 遗书
感谢您阅读博客。我希望它对那些有志于做机器学习、整体建模、数据处理、数据可视化项目的人有用。
如果你对这个项目有任何疑问,请在这个项目的回复部分或 GitHub repo 中留下评论。
完整的项目可以在我的 Github 上找到:
https://github.com/SarthakV7/mercari_kaggle
在 LinkedIn 上找到我:www.linkedin.com/in/sarthak-vajpayee
和平!☮