用 t-SNE 检验降维
今天我探索了在两个高维数据集上应用 t-SNE:经典的 MNIST 和新时尚主义者。
你可以在这里阅读所有关于 fashionMNIST 的内容,它被设定为复杂程度更高的 MNIST。
MNIST 包含从 0 到 9 的手写数字,而 fashionMNIST 包含从 t 恤到裙子到裤子的 10 种不同的服装。
我在 MNIST 的整个原始训练集上运行了 t-SNE,这是相当好的分离,并与 fashionMNIST 进行了比较。
MNIST in 2D
并在 fashionMNIST 中观察到一些重叠。
fashionMNIST in 3D
我们可以在 plotly 中进一步旋转它,并删除明显分开的类,以识别重叠的类:t 恤,衬衫和外套。
这是我关于数据科学和视觉故事的# 100 日项目的第 53 天。我的 github 上的全部代码。感谢阅读。欢迎新主题的建议和反馈。
Check Mate 深度学习
人机交互如何打败深度学习。
Human vs Robot, by Frank Steiner, CC-BY-SA-4.0
深度学习正在主导这些天的人工智能新闻。人们看不到的——深度学习是可以被打败的。不要误解我。深度学习很奇妙。它开辟了机器学习的新领域。它惊人的图像结果给数据科学家和感兴趣的公众留下了深刻的印象。除了图像分析,您还可以在文本和时间序列分析领域发现有趣的新结果。所有这些都很棒;但被高估了。Kaggle 最近的一篇文章显示,线性回归方法击败了神经网络。那么诀窍是什么呢?如何能轻松检查 mate 深度学习?
深度学习不那么秘密的酱料
现代神经网络体系结构具有一些重要的特征,这些特征使它们在许多用例中获得成功。它们能够解决非线性问题,善于接收复杂的输入,并且能够在内部进行特征选择。
最常被引用的秘密是内部特征生成。深度学习架构在其节点中为自己构建了新的参数。你可以把它归结为一句简单的话:
在深度学习中,架构工程是新的特征工程 Stephen Merity ,Salesforce 的高级研究科学家
虽然这是一个优点,但它引入了更多的自由度。这最终会产生一个问题,即您需要输入足够的信息来设置这些自由度。值得注意的是,信息必须来自更多的线,而不是更多的特征。事实上,更多的功能使问题变得更加困难。这被称为维数灾难。
真实生活的例子
在实践中,您经常会遇到记录的例子数量有限的用例。我最近有一个用例,在那里我处理书面的维护记录。工程师正在记录维修原因。那是在大型机器上,那里没有数百万台机器。这导致了几百行错误。用例是为了确定与其他部门的相关性。
将这些记录输入深度学习算法并没有产生任何好的结果。维护记录中的语言富含用例相关的术语。有限的行数阻止了深度学习结构学习底层因素。
通过特征工程传递知识
我们确实知道零件 v 120–3 和 v 120–4 属于同一类型。所以我们可以用一个令牌 V120 来代替两者。我们所做的是通过生成新的特征将世界的知识转移到模型中。
虽然这听起来微不足道,但它有两个迷人的方面。首先,这种特征工程可以降低问题的复杂性和非线性。我们手动“设置”模型的自由度。斯科特·凯勒的线性回归有很多工程特征。我认为这种线性回归就是用一种非常类似于 SVM 中手工制作的内核的方法来解决非线性问题。
另一个更重要的部分是,我们输入关于世界的信息。原始数据中不包含此信息!我们将关于同义词或关系的信息转移到模型中。这是特征工程所独有的。我们确实有像 word2vec 或 GloVe 这样的自动方法来尝试获取单词的意思。但是都需要数据。如果你没有相应的数据,你就无法提取这些模式。另一方面,人类知道这些关系,并能把它输入进去。检查队友?
大数据拯救世界;不是!
解决数据有限问题的一个常见答案是大数据。但(可悲的是)这通常没有任何帮助。让我们在机器上安装大量的传感器。这些传感器连接到云环境。我们现在可以分析万亿字节的数据;这很酷,但很可能没有帮助。
我们正在重新研究这几百个例子,工程师写下了发生的事情。当然,我们可以用更多关于机器状态的信息充实每一行。但是我们没有生成更多相关的行。大数据往往并不意味着大样本量,而是每行包含大量信息。
迁移学习——答案?
深度学习挨打了吗?说实话,也不尽然。在深度学习的前沿,许多科学家正在尝试为深度学习结构进行迁移学习。一个关键的想法是将单词之间的关系或潜在的图像模式转移到其他用例中。这个想法是,识别图片中的一条线的网络也可能在其他应用中有用。
这个深度学习领域正在后院兴起。但迟早会冲击商业应用。如果你对如何在深度学习中进行迁移学习感兴趣,请看看 Sebastian Ruder 的精彩博文。
“Cherchez la Tech”或如何增加你发现今天的谷歌的机会
为早期投资者制定投资方案的系统方法
摘要
“软件正在吞噬世界”,安德森·霍洛维茨公司的马克·安德森有句名言。我完全同意。然而,世界很大,有很多软件。如果你是一个有抱负的技术投资者,对行业有一些不可知的看法,你从哪里开始呢?你能在 1999 年发现谷歌,2005 年发现脸书,2010 年发现优步,或者 2011 年发现 DeepMind 吗?
考虑一个我半开玩笑地称之为“Cherchez la Tech”的框架,它有三个关键部分:
- 一项成熟的技术,
- “随时准备颠覆”的部门,以及
- “最佳交付”商业模式
颠覆始于某项面向大众应用的技术的成熟,这项技术必须既有效又足够便宜。一旦确定了技术,寻找特定技术有潜力创造新产品和服务或使现有产品和服务更快、更好或更便宜的部门和更重要的部分。最后,选择一个最适合在你所选择的领域提供技术的商业模式。
“Cherchez la Tech” framework, Cornel Chiriac
请继续阅读,了解更多详情。
技术:圣杯
技术为选择行业细分和商业模式焦点提供了强有力的指导,两者都遵循。作为这个过程的第一步,我问自己“现在什么技术正在成熟?”时机是相关的,因为已经成熟的技术很可能实现了先进的商业应用。空间将会或开始变得拥挤,新来者将处于不利地位。
回到 90 年代末。个人电脑在美国的渗透率超过了 50% ( Pegasus Research ),互联网的使用处于大规模采用的边缘,很快接近 50%的采用率大关(互联网实时统计)。成熟的互联网接入技术为网上超市(如亚马逊)和世界信息的组织者(如谷歌)铺平了道路。它还允许“车库销售”走向全球(如易趣),通过可信的方法(如贝宝)完成交易。那个时代的远见者抓住了技术成熟的机会。一旦他们开始,很少有人加入他们在同一空间的金字塔顶端的行列。未来的大部分现金流已经分配出去了。
快进到 2000 年中期,社交网络革命正在进行。这是社会行为因素综合作用的结果,如个人在日益增长的技术、全球化和个人对拓展和社会友谊的渴望中的孤立。科技使之成为可能。同样的技术进步在 90 年代末引发了在线商务的发展,让人们能够相互联系和分享经验。如果有人在那个阶段发现了这一趋势,并在 MySpace、Friendster、脸书和其他几个人之间平均分配 10 万美元,那么今天的结果将是数百万美元(约 5000 万美元),尽管脸书是唯一一个站在人群中的人。当然,有很多方法可以增加投资成功初创企业的机会,但这是有据可查的,这篇文章的重点是“空间”而不是“空间内的目标”
那么,如何知道哪种技术正在成熟呢?下面的列表(Tech 2.0)是对主导初创企业生态系统或即将进入市场的技术的广泛当前指示。外面还有更多。订阅技术博客,了解最新动态。跟踪顶尖大学的研究成果(例如麻省理工学院、加州理工学院和我自己的母校芝加哥大学)。阅读思想领袖的作品,比如彼得·迪亚曼迪斯的指数技术。例如,跟随该领域的专家,如 Yann LeCun、吴恩达、Geoffrey Hinton 和其他机器学习专家。
“Technology commercialisation”, Cornel Chiriac
举一个例子——机器学习——我们正在见证这个领域前所未有的进步。随着机器学习算法在图像识别和语言处理等专业任务上变得比人更好,我们可以看到这些进步为许多高价值行业带来了颠覆。这让我想到了下一步——关注一个对商业采用成熟技术阻力最小的大行业。
扇形:阻力最小的路径
“我想投资一家使用机器学习的初创公司。现在怎么办?”这种追求本身愚蠢地进入了无数急于吹捧“我们是扰乱 X 部门的人工智能初创企业”的创始人圈子。机器学习本身不是目的,而是达到目的的手段。虽然机器学习只是一种用于构建智能企业的工具,但它可以作为筛选下一个可能经历革命的行业的起点。那么,应该怎么做呢?
在选择行业重点时,问问自己:
- 在哪个部门和分部门,一项特定的成熟技术会将现状提高一个数量级?
- 行业(机会的大小)是否足够大?
- 它为技术采用做好准备了吗?
一种观点将这一领域分为数字化和欠数字化两部分。麦肯锡 2015 年的一项研究指出,美国 65%的部门(按 GDP 份额计算)数字化不足。数字领导者平均为其底线增加了 6%至 11%,而落后者则保持不变或利润下降(衡量 1993 年至 2013 年)。这两个群体在美国国内生产总值中占有相似的份额——分别为 30%和 35%。“机会的大小”是可比的,因此数字化水平的差异是由于“采用的准备程度”。尽管领导者很早就接受了技术创新,落后者却没有。然而,潮流正在改变,我们看到越来越多的资本流入“无聊”的行业,颠覆了它们(正如 CB Insights 经常指出的)。彻底改变传统的、数字化不足的业务的机会是巨大的,这个空间作为一个整体资产配置类别是有意义的。从低基数开始,数量级的飞跃更容易。我们很可能会看到新的技术巨头在突破性技术的推动下出现在这些领域。
资料来源:麦肯锡全球研究院,2015 年 12 月( 链接 )
话虽如此,这个游戏通常是在子行业层面上进行的。在高度数字化的行业中也有“绿色领域”的机会,尽管它们可能更难找到。成功的初创企业可能会为自己赢得一席之地,但很快就会被现有的科技巨头之一吞并(这是一个不错的结果)。然而,这种战略不太可能让一家初创企业成为科技巨头。现任者已经获得了相当大的权力来控制最大的份额,而新来者如果不被收购,很可能最终会失败。
为了举例说明技术进步如何改变一个行业,让我们看看医疗保健。医疗保健是前面提到的麦肯锡研究中提到的数字落后者之一。计算机视觉和图像处理的技术发展对成像和诊断的医疗保健领域产生了革命性的影响( CB Insights )。计算机视觉技术成熟的早期迹象可以追溯到 2009 年,当时 ImageNet 在一个免费提供给计算机视觉研究的数据库中收集了 1500 万张图像。在 2012 年,谷歌大脑发现了一只猫,没有任何标签数据的帮助。2014 年,谷歌收购了机器学习初创公司 Deep Mind,该公司在该领域取得了令人印象深刻的成果。2016 年,谷歌 DeepMind 与 NHS 合作,利用机器学习对抗失明。人工智能很可能将计算机辅助青光眼诊断带入现实,并预防 98%的最严重视力丧失病例(眼科时报)。
资料来源:CB Insights《医疗保健中的 AI》,2016 年 9 月( 链接 )
发现 2009 年至 2010 年计算机视觉技术的进步,并将这些进步与成像和诊断应用联系起来,会直接帮助投资者押注于一个即将被颠覆的领域。
商业模式:最佳递送代理
这个相对简单。一旦缩小了技术和部门的关注范围,接下来的任务就是确定哪些模型最有可能服务于业务。
在过去二十年里,商业模式从简单的电子商务结构发展到旨在实现网络效应的市场,最后发展到 SaaS(尽管它主导了电信业几十年,但仍是初创企业的宠儿)。由于技术的进步,它们像部门一样进化。如果没有编程语言的优雅、基础设施(高性能计算、计算堆栈本身、存储)和连接速度的进步,SaaS 在当前的采用规模下是不可能实现的。看起来,SaaS 以其各种各样的方式主导着当前的风险投资环境。暂时如此。
“Business model evolution in the start-up ecosystem”, Cornel Chiriac
Greylock Partners 的陈佳瑞在“新护城河”中介绍了“智能系统”的概念,作为下一个可防御的商业模式。陈认为,强大的技术,如机器学习(ML),将与数据、业务流程和企业工作流相结合,以创建一个智能系统的环境。例如,陈将谷歌定位为将 ML 应用于流程和工作流的早期先驱:谷歌收集了更多关于每个用户的数据,并应用机器学习在网络搜索的工作流中提供更及时的广告。
出处:“ 【新护城河】 ”,灰锁伙伴的陈佳瑞
Gil Dibner 进一步发展了智能系统的概念,并将其作为一个新兴的风险投资元论题。网络效应作为有意义的进入壁垒的时代正在结束。技术可能正在经历价值倒置。吉尔的最后声明称,“在评估‘智能系统’公司的价值时,我们必须关注该公司正在创建的特定系统所造成的进入壁垒。价值不会仅仅来自于“智力”。价值在系统本身。”
确定最适合建立有意义的进入壁垒和建设智能企业的商业模式,可以为投资者指明钟形曲线前方的空间。在关于如何构建企业的无数选择中,只有一个最佳选择。确定最佳选择是一个过程,涉及对技术、其行业应用和行业本身的深刻理解。
结束语
软件将继续蚕食世界。在早期技术投资的大量机会中,专注、时机和深入的尽职调查是最重要的。在投资者将资本分配给机会并对特定目标进行尽职调查之前,最好设定“在哪里玩”的界限。我相信,技术将继续充当探路者,并在以最佳方式应用于成熟行业时,引领公司和投资者获得更高的经济回报。Cherchez la Tech,你可能会发现在选择行业和商业模式的重点清晰。
我很想听听你的想法,
山茱萸
__
特别感谢韦弗利·多伊奇、费尔南德·伦多耶、维多利亚·鲁斯纳克和弗拉德·卡拉教授在撰写本文时提供的宝贵反馈。
__
以上帖子并非投资建议。所有观点,如果没有出处,都是主观的。这篇文章表达了对行业层面资产配置的看法,不涉及任何与目标尽职调查相关的话题。请在投资前进行彻底的尽职调查,并在适用的情况下寻求专业的投资、法律和会计建议。
樱桃树和全球变暖:开花还是不开花?
T 他的回答似乎是“要开花”,请让我再加上“越来越早”。在京都,一个美丽的日本城市,也因春天盛开的樱花而闻名,几乎是一个真实的事实,春天每年都开始得越来越早。
由于 Aono,Kazui 和 Saito 的精心工作,京都樱花开花的历史系列物候数据可以通过上面的链接提供给每个人。据我所知,这个物候数据集在世界上是无与伦比的,因为它跨越了 1000 多年的时间!
“我从历史时期京都的皇帝、贵族、统治者和僧侣写的许多日记和编年史中搜索和收集了樱桃树(樱花)完全开花日期的物候数据。举行樱花观赏会或观察到樱花盛开的日期是从旧文献中收集来的。在这一页,你可以看到自 9 世纪以来京都樱花盛开的一长串物候数据。”青野康之。
数据科学的激情与对自然的热爱混合在一起,加上几行 Python 代码,产生了下面的情节。x 轴代表公元年,从公元 812 年开始。y 轴计算自每年 1 月 1 日以来经过的天数。对于有物候数据的每一年,开花日期用一个蓝点表示。正如你所看到的,波动性很大,但是取一个滚动的平均值来说明开花日期的趋势:这是红色曲线。浅蓝色区域代表平均值周围的+/- 1.96 标准偏差范围。红色曲线越低,樱桃树开花越早,反之亦然。
Plot of the whole Historical Series of Phenological data for Cherry Tree Flowering at Kyoto City
从公元 1825 年前后开始,滚动平均值显示出明显的下降趋势:平均而言,樱花每年开花越来越早。这是因为全球变暖还是仅仅因为当地天气或气候的影响?
在公元 1250 年至 1750 年之间缩放,显示出平均开花相对较晚的三个时期:它们或多或少以公元 1350 年、公元 1540 年和公元 1680 年为中心。它们与分别开始于公元 1315 年、公元 1550 年和公元 1650 年的欧洲小冰期有密切关系吗?也许是的…
Zooming between 1250 AD and 1750 AD. Are peaks related to the Little Ice Ages?
参考
Aono 和 Kazui,2008;Aono 和 Saito,2010 年
Aono 和 Kazui,2008;Aono 和 Saito,2010 年
2012 Aono(2012;全球环境,17,21–29)
ChiPy 数据科学导师,pt。一
这篇文章是关于我作为数据科学项目 ChiPy 导师项目的学员经历的三部分系列文章的第一部分。ChiPy 是芝加哥 Python 用户组的简称,是一个由才华横溢、热情洋溢的个人组成的社区,他们因对编程语言 Python 的欣赏而聚集在一起。这个小组的热情和兴奋是更大的 Python 社区的缩影,也是我发现 Python 如此吸引人的部分原因。
我是在参加大会的数据科学沉浸式项目时接触到 ChiPy 的,在这个项目中,我们使用 Python 编写大部分代码。在我的第一次 ChiPy meetup 上,我了解了导师计划,并急切地申请了学习更多 Python 知识和融入社区的机会。鉴于我相对来说还是一个编程新手,我很感激有机会在社区环境中继续学习。
我的导师
当我得知 GrubHub 的高级数据科学家 Kevin Goetsch 被指定为我的导师时,我激动万分。我已经有机会与 Kevin 会面,因为他和我的 GA 导师以前是 Braintree 的同事,并且看过他的 PyData 关于使用 Scikit Learn 进行流水线操作的演讲。谈到编程,我真的很欣赏 Kevin 的精神:他是工具不可知论者,相信一个好的、工作的模型比一个永远不会被使用的完美模型更好,并且专注于产品如何被清洁地生产。实际上,蒂姆·古恩“让它工作”的编程方法。
项目
我的项目的指导问题是:我们能否在一款啤酒投入生产之前预测它在 Untappd(一个致力于啤酒的有影响力的社交媒体平台)上的评级?第二个问题是——这切中了数据科学的核心——我们为什么要在乎?
我们必须先回答后一个问题,以便为前者制定一个进攻计划。如果原因的答案是“因为我想知道哪些 IPA 最受欢迎”,那么我们可以进行一些数据分析,并将我们的数据科学工具箱放在棚子里。如果答案是,“因为我希望我生产的啤酒在 10 次评级后被评为 4 星或更高”,那么在我们的模型中包括 100,000 次评级的啤酒可能没有意义。
为了这个项目,我们将假设原因如下:
我们希望能够为不同的啤酒厂提供关于他们即将推出的啤酒的建议,并就他们如何在 Untappd 上获得更高的评级提出建议。
Sample Untappd beer entry; target variable in red
为了做到这一点,我们需要建立一个模型,可以准确预测啤酒的评级。这个问题可以分成四个不同的部分:
- 从未开发的目标变量(啤酒等级)和潜在特征中获取数据
- 数据清理和探索性数据分析
- 迭代模型测试和持续特征工程
- 将训练好的模型嵌入到 webapp 中,以按需提供预测
目标
在本次导师计划结束时,我希望完成以下工作:
Trying to avoid this
- 打造我的 Python 流畅性!更加熟悉不同的结构,写更多的文章
- 通过带有请求和漂亮汤的网络抓取来获取数据
- 用我以前没用过的库可视化我的结果
- 成功实施尖端的机器学习技术,如神经网络和极端梯度推进,并将其功效与行业标准进行比较
- 通过将我的模型构建到一个 Scikit-Learn 管道对象中并对其进行酸洗,从而将它生产化
- 通过构建一个 Flask 应用程序来提供预测,我尝试了一下 web 开发
关于我
我最近从 DC 的华盛顿州搬到了芝加哥。在此之前,我在北卡罗来纳州的戴维森学院获得了比较文学学位。我对数据科学感兴趣,因为它是一种发现的手段和一种讲故事的方式(我肯定这里面有一个很好的中间笑话)。我生在丹佛,长在丹佛,现在仍然对人们认为它有多酷感到惊讶。不出所料,我喜欢啤酒。
请继续关注第 2 部分!
当…时,选择很容易
每个人都做了他们应该做的事。不幸的是,我们每天面对的大多数决定都是针对那些不完全按照计划进行的情况。
让我们假设它的季后赛时间,篮球馆挤满了人。第 22 区的 250 名球迷都购买了半场附近的指定座位。然而,一名青少年在开球前两个小时决定和他的朋友坐在第三排,而不是自己的座位。之后,粉丝们鱼贯而入,试图坐在自己的座位上,但如果他们的座位已经被占了,他们会在这个区域随机选择一个座位。你工作到很晚,不幸地在比赛开始后到达,发现只剩下一个座位——号码被人群遮住了。选择坐在最后一个座位上,实际上是选择了一个你没有购买的座位,这有什么风险?
管理不是告诉人们做什么,而是帮助他人做出最好的选择。与缺乏数据相比,人们的决策往往会受到对风险、不确定性和模糊性的认知的阻碍。在日常生活中,风险与避免“糟糕”的选择——我们对形势的客观看法——联系在一起。风险方面的传统权威弗兰克·h·奈特(Frank H. Knight)谈到了事件和备选方案的分类既客观又可知的情况。风险可以被定性为“客观的”这一事实假定决策者理解他或她所面临的问题的性质。
如果风险的概念假设决策者感知清晰的选择,那么不确定性对应于选择不清晰和/或其后果难以衡量的情况。两个人对于一个给定的事件可能有不同的概率信念,如果一个人不能使另一个人相信他的方法是错误的,不确定性来自于“状态的穷尽分类的不可能性”。类似地,任何利用当前事件来预测未来的尝试,很大程度上都是基于判断和直觉——因此从定义上来说是主观的。决策者面对的是主观概率,因为未来是未知的——我们不仅不知道某些事件的概率,也无法合理预测潜在事件的范围。
模棱两可是由于缺乏明确的上下文而产生的。模糊决策是指决策者没有足够的信息来确定他或她的直觉是正确的。模糊性是指决策者对他或她所感知的事物的信念以及他或她对风险的态度。情况从来都不是模棱两可的,但是我们对情况的看法可能是模棱两可的。因此,歧义可以有多种解释:它是人们偏好和行为的一种属性,而不是语境本身。如果我们改进决策的过程,我们就会减少模糊的感觉。
管理就是做出更好的决定,不管是你自己的还是你周围的人的。改善决策需要处理判断失误的根源:风险、不确定性和模糊性。在处理风险时,我们需要确定一个问题或机会的预计成本和收益的可验证数据。在处理复杂问题分析中的不确定性时,我们需要了解概率的基本原理,以便做出更好的选择。为了减少模糊性,我们需要了解手头数据的质量,我们面临的问题的性质,以及哪种方法将产生最好的结果。如今的管理挑战与其说与我们可支配的数据和软件数量有关,不如说与我们改善决策背后的心理过程的能力有关。
你应该过度担心篮球比赛迟到和找不到指定座位的风险吗?这个问题类似于 Brett Berry 在最近的一篇文章中提出的飞机概率问题。在分析你所掌握的数据和问题的性质时,无论你是在比赛前一个小时到达还是晚到了几分钟,你的座位都有 50%的机会被占用。如果座位是由球迷随机选择的,你将有 1/250 的机会获得自己的座位。然而,这里的情况并非如此,因为粉丝们只是在自己的座位已经有人的情况下才随机选择座位。这意味着很可能有一半的情况会自行解决(一个没有找到自己座位的球迷会选择青少年的场边座位),而另一半会在其他人的位置上结束。不管你什么时候到达竞技场,你都有百分之五十的可能性找到你的座位。
改善管理决策是商业分析研究所的核心和灵魂。在巴约纳的暑期学校,以及在欧洲的大师班,我们让分析为您和您的组织服务。该研究所专注于数据科学在管理人员中的五个应用:在数字时代工作、数据驱动的决策、机器学习、社区管理和视觉通信。培养你做出更好决定的能力会对你未来的工作和职业生涯产生影响。
【我】贝里,b .(2017)。飞机概率问题,medium.com,https://medium . com/I-math/solving-an-advanced-Probability-Problem-with-virtually-no-math-5750707885 f1
Lee Schlenker 是 Pau 商学院的教授,同时也是商业分析学院http://baieurope.com的负责人。他的 LinkedIn 个人资料可以在wq 查看。你可以在推特上关注我们,网址是【https://twitter.com/DSign4Analytics】
选择正确的编码方法——标签与 OneHot 编码器
您选择的编码如何在您的预测模型中发挥重要作用
Gateway Of India- Mumbai, India Pic by Rahil Hussain Shaikh
在最大似然模型中,我们经常需要将分类的,即文本特征转换成数字表示。两种最常见的方法是使用标签编码器或 OneHot 编码器。然而,大多数 ML 新手并不熟悉编码的选择对他们的模型的影响,通过在正确的场景中使用正确的编码,模型的准确性可能会有很大的变化。
在这篇文章中,我们将一步一步来
- 了解标签和 OneHot 编码。
- Python 中使用标注和一次热编码对预测准确性影响的实际示例。
了解标签和 OneHot 编码。
让我们了解 Label 和一个 hot 编码器的工作原理,并进一步了解如何在 python 中使用这些编码器,以及它们对预测的影响
标签编码器:
使用 Sklearn 库可以实现 Python 中的标签编码。Sklearn 提供了一个非常有效的工具,用于将分类特征的级别编码成数值。用 0 和 n_classes-1 之间的值对标签进行编码,其中 n 是不同标签的数量。如果某个标签重复,它会将之前分配的相同值分配给。
考虑下面的例子:
如果我们必须将这些数据传递给模型,我们需要使用 Label Encoder 将 Country 列编码成它的数字表示。应用标签编码器后,我们将得到如下结果
The categorical values have been converted into numeric values.
这就是标签编码的全部内容。但是取决于数据,标签编码引入了新的问题。例如,我们将一组国家名称编码成数字数据。这实际上是分类数据,行与行之间没有任何关系。
这里的问题是,由于同一列中有不同的数字,模型会将数据误解为某种顺序,即 0 < 1 <2。
该模型可能会得出一种相关性,如随着国家数量的增加,人口也会增加,但这显然可能不是其他一些数据或预测集中的情况。为了克服这个问题,我们使用一个热编码器。
一个热编码器:
现在,正如我们已经讨论过的,根据我们拥有的数据,我们可能会遇到这样的情况,在标签编码后,我们可能会混淆我们的模型,认为某一列具有某种顺序或层次结构的数据,而我们显然没有它。为了避免这种情况,我们对该专栏进行了“一个酒店编码”。
一种热编码的做法是,获取一个包含分类数据的列,该列已经过标签编码,然后将该列拆分为多个列。数字由 1 和 0 代替,这取决于哪一列有什么值。在我们的示例中,我们将得到四个新列,每个国家一列—日本、美国、印度和中国。
对于第一列值为日本的行,“日本”列将为“1 ”,其他三列为“0”。同样,对于第一列值为美国的行,“美国”列为“1 ”,其他三列为“0 ”,依此类推。
OneHot encoded country values.
关于使用标注和一个热编码对预测的影响的 Python 实例。
我们将使用医疗成本个人数据集来预测基于各种特征的汽车医疗费用,您可以从这里下载数据集。本博客使用的数据只是一个样本数据,但通过均方根误差评估预测结果,可以清楚地看到预测结果的差异,rmse 越接近 0,模型预测越好。
我们将运行 xgboost 回归算法模型(您可以使用您选择的任何回归算法),并使用标签编码器预测价格,然后使用一个热编码器并比较结果。
我从 insurance.csv 文件中取出了最后 37 条记录,并创建了一个新的文件 insuranceTest.csv,以预测对看不见的数据的收费。
代码片段:
import pandas as pd
import numpy as np
import xgboost
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from math import sqrt
from sklearn.metrics import mean_squared_errordata = pd.read_csv('D://Blogs//insurance.csv')testdata = pd.read_csv('D://Blogs//insuranceTest.csv')mergedata = data.append(testdata)
testcount = len(testdata)
count = len(mergedata)-testcount
X_cat = mergedata.copy()
X_cat = mergedata.select_dtypes(include=['object'])
X_enc = X_cat.copy()#ONEHOT ENCODING BLOCK#X_enc = pd.get_dummies(X_enc, columns=['sex','region','smoker'])
#mergedata = mergedata.drop(['sex','region','smoker'],axis=1)#END ENCODING BLOCK# =============================================================================
# #LABEL ENCODING BLOCK
#
X_enc = X_enc.apply(LabelEncoder().fit_transform) #
mergedata = mergedata.drop(X_cat.columns, axis=1)
# #END LABEL ENCODING BLOCK
#
# =============================================================================FinalData = pd.concat([mergedata,X_enc], axis=1)
train = FinalData[:count]
test = FinalData[count:]
trainy = train['charges'].astype('int')
trainx = train.drop(['charges'], axis=1)test = test.drop(['charges'], axis=1)
X_train,X_test, y_train,y_test = train_test_split(trainx, trainy, test_size=0.3)clf = xgboost.XGBRegressor()
clf.fit(X_train,y_train)
y_testpred= clf.predict(X_test)
y_pred = clf.predict(test)dftestpred = pd.DataFrame(y_testpred)
dfpred = pd.DataFrame(y_pred)rms = sqrt(mean_squared_error(y_test, y_testpred))print("RMSE:", rms)
RMSE 的产量:RMSE:18960 . 688888886867
现在,让我们取消注释代码片段中的一个热编码器块,注释标签编码器块见 RMSE
import pandas as pd
import numpy as np
import xgboost
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.preprocessing import LabelEncoder
from math import sqrt
from sklearn.metrics import mean_squared_errordata = pd.read_csv('D://Blogs//insurance.csv')testdata = pd.read_csv('D://Blogs//insuranceTest.csv')mergedata = data.append(testdata)
testcount = len(testdata)
count = len(mergedata)-testcount
X_cat = mergedata.copy()
X_cat = mergedata.select_dtypes(include=['object'])
X_enc = X_cat.copy()#ONEHOT ENCODING BLOCKX_enc = pd.get_dummies(X_enc, columns=['sex','region','smoker'])mergedata = mergedata.drop(['sex','region','smoker'],axis=1)#END ENCODING BLOCK# =============================================================================
# #LABEL ENCODING BLOCK
#
#X_enc = X_enc.apply(LabelEncoder().fit_transform) #
#mergedata = mergedata.drop(X_cat.columns, axis=1)
# #END LABEL ENCODING BLOCK
#
# =============================================================================FinalData = pd.concat([mergedata,X_enc], axis=1)
train = FinalData[:count]
test = FinalData[count:]
trainy = train['charges'].astype('int')
trainx = train.drop(['charges'], axis=1)test = test.drop(['charges'], axis=1)
X_train,X_test, y_train,y_test = train_test_split(trainx, trainy, test_size=0.3)clf = xgboost.XGBRegressor()
clf.fit(X_train,y_train)
y_testpred= clf.predict(X_test)
y_pred = clf.predict(test)dftestpred = pd.DataFrame(y_testpred)
dfpred = pd.DataFrame(y_pred)rms = sqrt(mean_squared_error(y_test, y_testpred))print("RMSE:", rms)
RMSE 的产量:RMSE:18360 . 688888868617
一个热编码器的 RMSE 小于标签编码器,这意味着使用一个热编码器可以提供更好的精度,因为我们知道 RMSE 越接近 0,精度越好,同样不要担心这么大的 RMSE,因为我说过这只是一个样本数据,帮助我们了解标签和一个热编码器对我们模型的影响。
如果你觉得这篇文章有用,给它一个掌声和与你的朋友分享。
谢谢
使用 Keras 为简单 LSTM 选择正确的超参数
Photo by Mika Baumeister on Unsplash
构建机器学习模型从未如此简单,许多文章对什么是数据科学以及它可以做的惊人事情进行了高度概述,或者深入讨论了一个非常小的实现细节。这使得像我不久前一样有抱负的数据科学家经常看着笔记本电脑,心想:“它看起来很棒,很有效,但为什么作者选择了这种类型的架构/神经元数量或这种激活功能,而不是另一种呢?在这篇文章中,我想就如何做出一些决定给出一些直觉,比如在建立模型时找到正确的参数,在一个非常基本的 LSTM 上演示根据给定的名字预测性别。由于有许多关于递归神经网络(RNN)背后的数学和一般概念的伟大课程,例如吴恩达的深度学习专业化或这里的媒体,我不会深入挖掘它们,并认为这些知识是已知的。相反,我们将只关注使用 Keras 的高级实现。我们的目标是对构建这样的神经网络所做的决策有更实际的理解,尤其是如何选择一些超参数。
带有代码和输出的完整文章可以作为笔记本在 Github 上找到。
在 Keras 上:自 2017 年支持 TensorFlow 以来的最新产品, Keras 作为更复杂的机器学习库的易于使用和直观的界面,引起了巨大的轰动。因此,构建实际的神经网络以及训练模型将是我们脚本中最短的部分。
第一步是确定我们要使用的网络类型,因为这个决定会影响我们的数据准备过程。任何名字(或单词)中的字符顺序都很重要,这意味着,如果我们想用神经网络分析一个名字,RNN 是合乎逻辑的选择。长短期记忆网络(LSTM)是 RNNs 的一种特殊形式,当输入组块链变长时,它在寻找正确特征方面特别有效。在我们的例子中,输入始终是一个字符串(姓名),输出是一个 1x2 向量,表示该姓名属于男性还是女性。
做出这个决定后,我们将开始加载我们将需要的所有包以及数据集——一个包含超过 150 万德国用户及其姓名和性别的文件,女性编码为 f ,男性编码为 m 。
预处理数据
任何自然语言处理的下一步都是将输入转换成机器可读的矢量格式。理论上,Keras 中的神经网络能够处理形状可变的输入。在 praxis 中,使用 Keras 中的固定输入长度可以显著提高性能,尤其是在训练期间。这种行为的原因是,这种固定的输入长度允许创建固定形状的张量,因此更稳定的权重。
首先,我们将把每个名字转换成一个向量。我们将使用的方法是所谓的一键编码。这里,每个单词由 n 个二进制子向量的向量表示,其中 n 是字母表中不同字符的数量(使用英语字母表是 26)。为什么我们不能简单地将每个字符转换到它在字母表中的位置,例如 a-1、b-2 等。)这将导致网络假设字符是有序的,而不是分类的——字母 Z not 比字母 A 更“有价值”。
例:
S 变为:
【0,0,0,0,1,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,1,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,0 0,0,0,0,0,0],
【0,0,0,0,0,0,1,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,0,0,0,0,0,0,0,0
既然我们已经确定了输入应该是什么样子,我们有两个决定要做:char 向量应该有多长(我们允许多少个不同的字符)和 name 向量应该有多长(我们想要查看多少个字符)。我们将只允许使用德语字母表(标准拉丁语)中最常见的字符和连字符,连字符是许多旧名称的一部分。
为了简单起见,我们将名称向量的长度设置为数据集中最长名称的长度,但以 25 为上限,以确保我们的输入向量不会因为一个人在名称输入过程中出错而变得过大。
Scikit-learn 已经在其预处理库中整合了一个热门编码算法。然而,在这种情况下,由于我们的特殊情况,即我们不是将标签转换成向量,而是将每个字符串拆分成其字符,因此创建自定义算法似乎比其他情况下所需的预处理更快。
现在我们已经准备好输入,我们可以开始建立我们的神经网络。我们已经决定了模型(LSTM)。在 Keras 中,我们可以简单地将多层堆叠起来,为此我们需要将模型初始化为Sequential()
。
选择正确数量的节点和层
对于应该选择多少个节点(或隐藏神经元)或多少层,没有最终的、明确的经验法则,并且对于您的个别问题,试错法通常会给出最佳结果。最常见的框架很可能是 k 倍交叉验证。然而,即使对于一个测试过程,我们也需要选择一些( k )数量的节点。
下面的公式或许可以给你一个起点:
Nᵢ 是输入神经元的数量, Nₒ 是输出神经元的数量, Nₛ 是训练数据中的样本数量, α 代表一个比例因子,通常在 2 到 10 之间。我们可以计算 8 个不同的数字,输入到我们的验证过程中,并根据得到的验证损失找到最佳模型。
如果问题很简单,时间也是一个问题,那么有各种其他的经验法则来确定节点的数量,这些法则大多简单地基于输入和输出神经元。我们必须记住,虽然易于使用,但它们很少会产生最佳结果。这里只是一个例子,我们将在这个基本模型中使用:
如上所述,对于要使用的隐藏层的数量,也存在相同的数量不确定性。同样,任何给定用例的理想数字都是不同的,最好通过运行不同的模型来决定。一般来说,两层已经足够检测更复杂的特征。层数越多越好,但也越难训练。一般来说,一个隐藏层处理简单的问题,就像这样,两个隐藏层足以找到相当复杂的特征。
在我们的例子中,添加第二层仅在 10 个时期后将精度提高约 0.2% (0.9807 对 0.9819)。
选择附加超参数
每个 LSTM 层都应该有一个下降层。该层将通过在训练期间忽略随机选择的神经元来帮助防止过度拟合,并因此降低对单个神经元的特定权重的敏感性。20%通常用作保持模型准确性和防止过度拟合之间的良好折衷。
在我们的 LSTM 层做了所有的工作来转换输入,以使预测朝着期望的输出可能,我们必须减少(或,在罕见的情况下,延长)形状,以匹配我们期望的输出。在我们的例子中,我们有两个输出标签,因此我们需要两个输出单元。
要添加的最后一层是激活层。从技术上来说,这可以包含在密度层中,但有理由将其分开。虽然与此不相关,但分割密度层和激活层可以检索模型密度层的缩减输出。使用哪种激活功能同样取决于应用。对于我们手头的问题,我们有多个类(男性和女性),但一次只能出现一个类。对于这些类型的问题,一般来说, softmax 激活函数效果最好,因为它允许我们(和你的模型)将输出解释为概率。
损失函数和激活函数经常一起选择。使用 softmax 激活函数向我们指出交叉熵是我们优选的损失函数,或者更准确地说是二进制交叉熵,因为我们面对的是二进制分类问题。这两个函数彼此配合得很好,因为交叉熵函数抵消了 soft-max 函数两端的平稳状态,因此加快了学习过程。
在选择优化器时,自适应矩估计(short Adam)已被证明在大多数实际应用中工作良好,并且仅在超参数变化很小的情况下工作良好。最后但并非最不重要的是,我们必须决定,在哪个指标之后,我们要判断我们的模型。Keras 提供了多种精度功能。在许多情况下,从整体准确性的角度来判断模型的性能是最容易解释的选择,也足以产生模型性能。
构建、训练和评估模型
在对如何选择最重要的参数有了一些直觉之后,让我们把它们放在一起,训练我们的模型:
Training output
98.2%的准确率令人印象深刻,这很可能是因为验证集中的大多数名字已经出现在我们的测试集中。使用我们的验证集,我们可以快速查看我们的模型在哪里得出错误的预测:
Model validation output
查看结果,至少一些错误的预测似乎发生在那些在名字字段中输入他们的姓的人身上。看到这一点,下一个好的步骤似乎是清除那些案例中的原始数据集。目前,结果看起来很有希望。以我们所能达到的精确度,这个模型已经可以用于许多真实世界的情况。此外,为更多时期训练模型可能会提高其性能,这里重要的是注意验证集的性能,以防止可能的过度拟合
最后的想法
在这篇文章中,我们成功地构建了一个小模型,以超过 98%的准确率从一个给定的(德国)名字预测性别。虽然 Keras 让我们从编写复杂的深度学习算法中解放出来,但我们仍然必须在这个过程中就一些超参数做出选择。在某些情况下,例如选择正确的激活函数,我们可以依靠经验法则,或者可以根据我们的问题确定正确的参数。然而,在其他一些情况下,最好的结果来自于测试各种配置,然后评估结果。
度量标准有什么问题?
或者任何类型的机器学习问题,你必须知道你将如何评估你的结果,或者评估标准是什么。
在本帖中,我们将查看最常见的指标,并根据目标和我们试图解决的问题讨论每个指标的有用性。
分类指标
准确(性)
可能是分类器性能的最直接和直观的度量。它只是简单地计算我们在预测总数中预测正确类别的次数。
当面对阶级不平衡的问题时,准确性显然是一个错误的衡量标准。假设你有两个类:A 类是你的数据集的 99%,B 类是剩下的 1%。通过预测每个时间案例的 A 类,您可以达到 99%的准确率。这看起来是个好成绩,但事实并非如此。
精确度和召回率
一般来说,在召回(被如此分类的真正肯定的实例的百分比)和精度(真正肯定的肯定分类的百分比)之间存在权衡。
在您想要检测少数类的实例的情况下,您通常更关心召回率而不是精确度。正如在欺诈检测的情况下,错过正面实例通常比错误地标记负面实例代价更高。
f-测度
我们都希望的理想场景是拥有高精度和高召回率!
但要选择你的最佳模式,你需要一个单一的数字性能总结。F1 得分是精确度和召回率的调和平均值:
F1 分数没有一个很好的直观解释,它是一个被称为 F-Beta 分数的指标的特例,F-Beta 分数衡量的是用户对回忆的重视程度是对精确度的重视程度的β倍。
卡帕
Kappa 或 Cohen 的 Kappa 类似于分类准确性,只是它是在数据集的随机机会基线上进行标准化的:
其中 po 是观察到的一致,pe 是预期的一致。
它基本上告诉你你的分类器(po)的性能比一个简单地根据每个类(pe)的频率随机猜测的分类器的性能好多少。
没有标准化的方法来解释它的值。兰迪斯和科赫(1977) 提供了一种表征价值观的方法。根据他们的方案,a 值 0 表示不同意,0-0.20 表示轻微,0.21-0.40 表示一般,0.41-0.60 表示一般,0.61-0.80 表示基本同意,0.81-1 表示几乎完全同意。
罗马纪元
这是业内使用的流行指标之一。
AUC 代表曲线下面积。该曲线可以代表 ROC 曲线或 PR 曲线。
PR 曲线说明了在不同阈值设置下精度和召回之间的权衡。
ROC 曲线是通过在不同的阈值设置下绘制 TPR (真阳性率),也称为灵敏度,相对于 FPR (假阳性率),也称为特异性而创建的。
以下是 ROC 曲线绘制的可视化效果:
Each point on the ROC curve (left)represents a different cutoff value — The curves on the right represent the Class-Conditional Probabilities
让我们看看当重叠部分的百分比增加/减少时会发生什么:
ROC curve (left) and Class-Conditional Probabilities (right) — varying the the percentage of overlapping for a fixed threshold
重叠越少,误差越小,ROC 曲线向上和向左移动得越远。所以,分班越好,AUC 就越高。
换句话说,AUC 不在乎绝对值,只在乎排名。你只需要很好地分开你的类,以获得高 AUC。
ROC 和 PR 有什么区别?
召回率=真阳性率(TPR)。所以区别在于精度和假阳性率。
这两种度量的主要区别在于,精度分母包含假阳性,而假阳性率分母包含真阴性。
精度衡量的是被分类为阳性的样本实际上是阳性的概率,而假阳性率衡量的是阴性样本中假阳性的比率。
应该用哪个?
对于任何度量标准来说,这完全取决于您打算如何处理数据。如果你的模型需要在正类和负类上表现的一样好。例如,为了对猫和狗之间的图像进行分类,您希望模型在猫和狗身上都表现良好。为此,您可以使用 ROC-AUC。另一方面,如果您对模型在负类上的表现并不真正感兴趣,而只是希望确保每个正预测都是正确的(精度),并且您得到尽可能多的正预测(回忆),那么您应该选择 PR-AUC。
简而言之:
使用 PR-AUC 关注小阳性类别
当两类检测同等重要时,使用 ROC-AUC
当阳性结果占多数时,使用 ROC-AUC,或者切换标签,使用 precision 和 recall
注意:许多人倾向于坚持使用 ROC,因为在大多数情况下这是一个更容易解释的指标。除此之外,计算精确的 PR 曲线就不那么直接了。(查看此链接了解更多详情)。
也就是说,AUC 也有其缺点:它可能会给出潜在的误导性结果…见下图!!
Both models A and B have an equal area under the ROC cure. However, in the high FPR range, model B is better than A, whereas in the low FPR range model A is better than B.
有些人不建议使用 AUC,原因如下:
(1)它忽略了预测的概率值和模型的拟合优度
(2)它总结了在人们很少操作的曲线空间区域上的测试性能
(3)它同等重视遗漏和犯错误
(4)它没有给出关于模型误差的空间分布的信息
(5)模型执行的总程度高度影响良好预测的缺席率和 AUC 分数
豪尔赫·洛沃、阿尔韦托·希门尼斯·瓦尔夫德和雷蒙多·雷亚尔
部分 AUC (pAUC)
部分 AUC 已被提议作为标准 AUC 的替代措施。当使用部分 AUC 时,只考虑 ROC 空间的特定区域。
pAUC denotes the area of shaded region
双向 pAUC
双向 pAUC 不是只限制假阳性率(FPR),而是关注曲线下的部分区域,同时具有水平和垂直限制。已经表明,pAUC 对真阳性率(TPR)的间接控制在概念上和实践上都是误导的。
Two-way pAUC denotes the area of shaded region A. This shaded region is directly determined by explicit FPR upper bound p0 (= 0.5) and TPR lower bound q0 (= 0.65). In contrast, pAUC denotes the area of both region A and B. Its indirect FPR lower bound (green dotted line) is determined by the TPR lower bound q0
对数损失
对数损失是基于概率的最重要的分类度量之一。
其中 yi 是真实标签,pi 是 yi = 1 的概率。
这完全是关于信心:如果对于一个特定的观察,分类器分配一个非常小的概率给正确的类,那么相应的对日志损失的贡献将会非常大。对数损失度量可以被视为精确度的“软”度量。
2 different models — same AUC but different LogLoss
这两个模型输出有相同的排名,因此相同的 ROC-AUC,PR-AUC !
但是,根据 LogLoss 值,右边的模型比左边的要好。
这是显而易见的,因为 Logloss 包含了概率置信度的概念。
这个指标的一个缺点是多数阶级可以支配损失!!
学习对指标进行排序
现在让我们来看看如何评估一个搜索引擎、一个推荐系统或者任何输出商品列表的系统。
在研究文献中,排序“项目”被称为学习排序。
Example of ranked urls for a given query
两个最流行的排名指标是地图@k 和 NDCG@k。让我们看看他们是如何工作的…
符号:
rel(i) 是指示函数,如果等级 I 处的项目是相关的,则等于 1,否则等于 0。
P(i) 是 top-i 集合中相关的返回项目的比例。
n 是系统做出的预测次数。
m 是项目全空间中相关项目的个数。
Q 是查询总数。
为了解释 MAP@k 做什么,我们需要从 AP@k 开始……
美联社@k
这个度量关心第 k 项的平均精度
当推荐的数量不可能捕获所有正确的推荐时,所使用的标准化因子防止 AP@k 分数被不公平地抑制。
……不要担心,这里有一个简单的例子可以更好地理解公式:
考虑一下,对于一个给定的查询,您必须预测一个包含多达 10 个项目的有序列表。并且只有 4 个可能的正确预测(地面真相)。
对于每一个预测,你都需要检查它是否正确。如果不是,你的预测就没有分数。如果它是正确的,你得到的点数等于正确预测的点数,包括这一个。
你除以的数就是可能的点数。换句话说,这是 10 个(你最多能预测的)和 4 个实际正确答案中的较小者。
因此:AP@10 = (1/2 + 2/3 + 3/5 + 4/9 ) / 4 = 0.55
地图@k
MAP@k 计算所有查询的平均精度(AP@k) 的平均值。对,一个平均一个平均!!
AP@k 是一个度量,它接受前 k 个项目的排序列表,并将其与给定查询的真实“相关”项目集的列表进行比较。AP@k 奖励你在你的列表中有很多相关的条目,并且把最可能正确的条目放在最上面。因此,顺序 对于计算 AP@k 分数很重要。MAP@k 只是计算 AP@k 在所有查询中的平均值。
现在,让我们解释另一个流行的排名质量指标…
NDCG@k
该指标声明了以下内容:
- 非常相关的结果>稍微相关的结果>不相关的结果(Cu 累计 G ain)。
- 当相关结果出现在结果集的前面时,它们会更有用( D iscounting)。
- 排序的结果应该与所执行的查询无关( N 规范化)。
***【CG】***是检索到的候选项的相关性得分的总和。它被计算为前 k 个相关性分数的总和:
贴现 CG (DCG) ,基本上根据项目的位置来惩罚相关性分数。使用对数衰减:
提出了一个替代方案以更加强调检索相关项目:
名词(noun 的缩写)b:当相关值为二进制时, DCG@k 的这两个公式是相同的。
然而,这个分数没有固定的上限,因为它取决于查询返回的结果的数量,因此为了比较不同查询的 DCG,我们必须 将它们 归一化。为了实现这一点,我们将 DCG 值除以最佳可能( 【理想】 )排名,得到*,一个介于 0 和 1 之间的值。*
地图@k vs NDCG@k:主要区别?
顺序对 MAP@k 和 NDCG@k 都很重要。但主要区别是 MAP@k 假设二元相关性(一个项目是感兴趣的还是不感兴趣的),而 NDCG@k 允许实数形式的相关性分数。
连续变量的度量呢?
回归度量
当谈到回归性能指标时,MAE 和 RMSE 是两个最流行的指标。
绝对平均误差
均方根误差
梅与 RMSE:应该使用哪一个?
以下几点可能有助于你做出决定:
当误差分布预期为高斯分布时,RMSE 比 MAE 更适合表示模型性能。
MAE 适用于描述均匀分布的误差。
MAE 对异常值更稳健:最小化平方误差导致找到它的平均值,最小化绝对误差导致找到它的中值。我们都知道中位数比简单平均数对异常值更稳健。
RMSE 避免使用绝对值,这在许多数学计算中是非常不可取的。例如,可能很难计算 MAEs 相对于某些模型参数的梯度。
….那 R 呢?
r 平方
R 平方的定义相当直接:它是用线性模型解释的响应变量变化的百分比。
误解: R 不在 0 和 1 之间。R 的最大值是 1,但也可能是负值。
R 有什么问题吗?
是啊!!!当增加新的预测值时,r 总是增加,不管它们是否有用:
每当您向模型中添加一个变量时,其估计系数的值可以为零,在这种情况下,解释方差的比例保持不变,也可以采用非零值 ,因为它提高了拟合的质量 。通过构造,你的 R 不能在增加一个变量后变小- Maxime Phillot 在 Quora 上的响应
我们如何克服这个问题?
调整后的 R
其中 n 是观察值的总数,k 是预测值的数量。
如果添加有用的术语,该指标将会增加,如果添加不太有用的预测值,该指标将会减少。
更多指标!!!!
NLP/NLG 指标:BLEU 和 ROUGE
这两个指标是互补的,主要用于评估文本的自动摘要和机器翻译。
双语评估替补演员
胭脂(面向回忆的吉斯丁评价替角)
胭脂只基于回忆。
基于用于计算召回的特征,胭脂可以有许多类型:
- ROUGE-N 基于一元、二元、三元或更高阶的 N -gram 重叠。
- ROUGE-L/W/S 分别基于 L ongest 公共子序列(LCS)、 W eighted LCS 和 S kip-bigram 共现统计。
有关这些指标的更多信息,您可以参考林的论文。
语音识别指标:WER(单词错误率)
WER 是用于评估 ASR(自动语音识别)系统的常用指标。这里有一个简单的方法来理解 WER 是如何计算的:
删除:
***语音输入:**我昨天连接了
**ASR 结果:*我昨天连接了插入:
***语音输入:**昨天连接了
**ASR 结果:*昨天连接了替代:
***语音输入:**昨天连接了
**ASR 结果:*连接了是
奖金!
走到最后是你应得的。
以下是您可以在网上找到的挑战列表,这些挑战使用我们提供的一个指标来评估参与者模型的性能。
结论
没有硬性规定可以找到一个理想的指标来说明在所有情况下应该最小化/最大化什么!这完全取决于业务需求和您试图解决的问题的背景。主要的信息很简单,当定义一个问题时,度量应该被接受并扮演一个关键的角色。
请继续关注,如果你喜欢这篇文章,请留下👏!
参考文献
[1] Jorge M. Lobo,A. Jiménez 和 R.Raimundo,AUC:对预测分布模型性能的误导性衡量,2007 年
[2] 斯坦福大学信息检索导论课程
棋盘游戏:骰子有多随机?
用 openCV 和假设检验分析骰子的随机性
Image via photodune.net under license to mtstrauss
虽然节日应该是快乐和幸福的源泉,但玩桌游可能是一种微妙的消遣。总有一些人似乎比预期的更有运气。一个典型的问题是骰子是公平的还是被操纵的。这里我们就通过反复掷骰子来分析骰子随机性。对于评估,我们将使用两种关键方法:圆检测来计算骰子图像上的点数,以及假设检验来对骰子的随机性进行定量说明。
由于 n 越大统计越好,一些爱好者甚至掷骰子 10.000 次来测试他们骰子的公平性。由于我不想手动掷骰子,我决定用一些乐高、Arduino 微控制器和网络摄像头来制作一个小型自动掷骰子器。基本上,骰子位于一个轮子上的一个小室中,轮子旋转,使骰子旋转。Arduino 转动滚轮 1.5 秒,再停 1.5 秒,然后网络摄像头拍摄结果,并重复该过程。在下面的 gif 图中可以看到机器运行和该机制的延时。
Dice Rolling Mechanism: An Arduino controls a LEGO® motor, which rotates wheels to rotate the die. A webcam captures the outcome.
Dice Rolling Mechanism Close Up Timelapse: The two rounded parts allow the die to flip around randomly.
由于轮子只在一个方向旋转,我在两个圆形部分的形式上增加了一点不对称,这样骰子也可以在垂直轴上旋转。我让机器运行了大约 2.5 小时,以创建一个大约 3000 次投掷的数据集。如果对 Arduino 代码或布线感兴趣,请随时联系我。
现在让我们进入分析部分。有几种方法可以计算点数,例如,我们可以使用形态学操作,通过应用二进制阈值并选择其凸包来掩盖骰子的朝上面(它明显比背景亮)。然后,可以通过对区域进行计数或者仅仅通过确定黑色像素与白色像素的比率来确定 pip 的数量。我尝试了几种方法,但最终决定使用 OpenCV 的 HoughCircles 函数,因为它需要最少的代码来实现。一般介绍可以在这里找到。在试验了这些参数之后,人们能够很快在圆检测中获得不错的结果:
Webcam image of the die and the detected pips using OpenCV ‘s HoughCircles function
接下来,我们计算每个图像的点数。当检测不到圆时,将指定 0 值:
为了检查算法的结果,我们绘制了每个类别的图像:
由于人类的大脑在识别错误分类方面速度超快,我决定检查这些类并手动纠正它们。检查还让我意识到,实际上有许多投掷是不明确的,因为骰子是站在边缘上的(它们被分配到零类)。
注意,HoughCircles 函数在大约 90%的情况下做了正确的分类。由于手动校正,现在人们也有了训练集,并且可以花费更多的时间来构建更好的分类器(即,当增加 n 时)。让我知道,如果你想得到数据集,有兴趣玩一玩,并建立一个基于此数据的骰子分类器。
现在,我们可以珍惜一个正确分类的骰子汇编。在所有六个数据集的下面(如果你发现一个不属于那里的,请告诉我):
All sixes of the dataset.
现在我们已经对所有的图像进行了正确的分类,我们现在可以测试我们的骰子是否是公平的了。首先,我们将绘制每个数字的出现次数:
正如我们所观察到的,第一种情况发生得更频繁。现在我们如何发现这个偏差是否显著?我们可以使用的一个统计检验是卡方检验。为了执行这个测试,我们计算预期结果的数量(E),计算与预期发生的差异(O-E),平方这个值((O-E)),然后通过预期值的数量将其归一化((O-E) /E)。卡方检验统计量是所有标准化值的总和。为了计算显著性水平,我们将检验统计量与 5 度的卡方分布(6–1)进行比较。
The results data frame
要使用卡方检验,我们不需要总是计算表(虽然这样便于理解检验),但是也可以使用 stats 库直接计算值。
from scipy.stats import chisquare1 - chisquare(counts).pvalue
最终,测试显示骰子在 97%的显著性水平上有偏差,因此这是不公平的。从上表判断,这种情况比正常情况多出现了 12%。毕竟,我现在找到了一个合理的解释,来解释为什么我用这个骰子输掉了过去的游戏。
讨论
这里,我们使用 OpenCV 的 HoughCircles 函数来计算骰子图像上的点数。使用卡方检验,我们能够在 97%的显著性水平上检验我们的假设,即骰子是不公平的。
然而,另一个问题是为什么死得不公平。我会假设它源于制造问题,所以质心错位,一些边缘比其他边缘更圆。在浏览专业骰子时,我注意到很多骰子都有锋利的边缘。
可能的后续行动是调查其他几款骰子,并寻找最公平骰子的最佳制造商。此外,骰子投掷机可以通过嵌入平面来模拟更真实的投掷来改进。
当然,另一个主要的限制是掷骰子是否是随机的。给定有限数量的相互作用,人们可以认为最终位置是由起始条件决定的。
至于这个特定的骰子,请放心,它将被排除在下一个棋盘游戏会话之外,以拯救家庭和平。
基于机器学习的客户流失预测
客户流失是一个用来量化离开公司的客户数量的指标。对于 SaaS 企业来说,它可以由那些取消订阅或取消之前签订的服务的人来定义。但对于销售不需要订阅的产品的电子商务公司来说,判断顾客何时购买是相当棘手的。
与其他指标一起,客户流失对于评估一段时间内的客户满意度至关重要,尤其是在衡量网站、产品供应商和其他方面最近的变化可能导致客户离开的负面影响时。
例句:你在你的电子商务平台上推出了一个新的布局,随后客户数量增加了。
客户流失也可以成为你做出更好营销决策的最好朋友。尽早发现有流失风险的客户是细分营销活动的最佳方式,以便及时有效地重新吸引这些用户,因为获得新客户比留住老客户更昂贵、更耗时。对于电子商务公司来说,这种说法非常正确。获得新客户总是需要大量的营销努力,公司必须在潜在消费者想到点击“购买”按钮之前向他们展示值得信赖。这通常需要时间。老顾客对商店很熟悉,他们不需要在网站上注册就可以方便地回到那里,因为他们已经在第一次购买时浏览过了。
总之,客户流失或流失率是一个温度计,显示客户对所提供的产品和服务是否有良好的体验。因为否则,他们显然会离开。
但是公司如何预测客户流失呢?这个问题没有正确答案。人们认为,当顾客不满意并准备离开时,他们会以某种方式做出类似的行为。这些信号可能很多,比如不回复营销邮件、不登录、不搜索产品、在网站上投诉、住在竞争对手突然变强的地区等等。
这就是为什么机器学习在检测客户流失方面变得非常受欢迎。通过向机器显示积极的流失案例,该模型计算出某人即将离开的概率。识别出那些处于风险中的顾客,公司可以发送一个特别的报价来吸引他们回到商店。它可以以折扣券或热身信息的形式出现,以提醒客户他们对公司的重要性。
机器学习在这种背景下如何运行?粗略地说,它是一个经过训练的模型,可以学习如何根据以前的数据,通过真实的案例来预测流失。记录所有客户在网站上随时间执行的交互的日志很容易成为无法操纵的无尽数据集,在这种情况下,机器学习是一个不断输入新信息的自动化程序,根据不同的场景调整预测。因此能够做出更好的预测。
尽管客户流失和机器学习是一个高度复杂的领域,缺乏改进,但幸运的是,涉及流失率和机器学习的测试越来越受欢迎,每天都有新的结果出现,以澄清所有这些混乱。
建议?想法?欢迎在下方评论或联系我LinkedIn😃
张量流中的 CIFAR-10 影像分类
在这个故事中,我将对来自 CIFAR-10 数据集的图像进行分类。这个故事包括预处理图像和训练/预测卷积神经网络模型。
这个笔记本的一些代码和描述是借用了这个回购由 Udacity 提供,但是这个故事提供了更丰富的描述。代码和 jupyter 笔记本可以在我的 github repo 里找到,https://github . com/deep-diver/cifar 10-img-classification-tensor flow。
我的深度学习背景是uda city { Deep Learning ND&AI-ndwith contentrations(CV, NLP ,VUI)},Coursera Deep Learning . AI Specialization(AI-ND 被拆分成 4 个不同的部分,我是和之前版本的 ND 一起完成的)。还有,我目前正在服用 Udacity 数据分析师 ND ,已经 80%完成。
在跳进去之前…
- 理解原始数据和原始标签
实施预处理功能
- 规格化,一个热编码
- 培训/开发/测试集中的数据分割
建立网络
- CNN 模型及其代价函数和优化器
训练神经网络
- 超参数
- 训练模型
测试模型(预测)
在跳进去之前…
文件列表
Fig 1. list of files of batch
如图 1 所示,数据集被分成几批以防止你的机器运行出内存。CIFAR-10 数据集由 5 个批次组成,命名为data_batch_1
、data_batch_2
等。如官方网站所述,每个文件使用 python 中的 pickle 模块打包数据。
了解原始影像数据集
原来的一个批量数据是用 numpy 数组表示的 (10000 x 3072)矩阵。列数,(10000),表示样本数据的数量。如 CIFAR-10/CIFAR-100 数据集中所述,行向量,(3072)代表一幅 32×32 像素的彩色图像。因为这个项目将使用 CNN 进行分类任务,所以原始的行向量是不合适的。为了将图像数据馈入 CNN 模型,输入张量的维数应该是**(宽度 x 高度 x 数量 _ 通道)或(数量 _ 通道 x 宽度 x 高度)**。这取决于你的选择(查看 tensorflow conv2d )。我要用第一种选择,因为 tensorflow 的 CNN 操作中默认选择是这样的。
如何重塑成这样的形态?
如果您计算 32323 == 3072,则图像的行向量具有完全相同的元素数量。为了将行向量重新整形为(宽度 x 高度 x 数量 _ 通道)形式,需要两个步骤。第一步是使用[**reshape**](https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html)
功能,第二步是使用 numpy 中的[**transpose**](https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html)
功能。
根据 numpy 官方网站的定义,[**reshape**](https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html)
将数组转换成新的形状,而不改变其数据。在这里,短语不改变其数据是一个重要的部分,因为你不想伤害数据。[**reshape**](https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html)
运营应分三个更详细的步骤进行。下面的方向是用逻辑概念描述的。
- 将行向量分成 3 块,每块代表一个颜色通道。
-得到的数组有(3×1024)个矩阵,总共就有**(10000×3×1024)**个张量。 - 用 32 将中的每 3 块进一步分割**。32 是图像的宽度和高度。
-这导致(3×32×32),这使得**(10000×3×32×32)张量总计
为了实现 numpy 中的逻辑概念,[**reshape**](https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html)
应该用下面的自变量来调用,(10000,3,32,32)。正如您所注意到的,当提供第三个值(32,width)时,reshape 函数不会自动进一步分割。您需要明确指定最后一个值(32,height)
Fig 2. reshape and transpose
故事还没有结束。现在,一个图像数据被表示为(num_channel,width,height)形式。然而,这并不是 tensorflow 和 matplotlib 期待的形状。他们期待不同的形状(宽度,高度,通道数)。你需要交换每个轴的顺序,这就是[**transpose**](https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html)
的作用。
[**transpose**](https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html)
可以接受一个轴列表,每个值指定它想要移动的维度的索引。例如,在(num_channel,width,height)的 numpy 数组中调用 transpose with argument (1,2,0)将返回(width,height,num_channel)的新 numpy 数组。
Code 1. reshape and transpose after loading
了解原始标签
标签数据只是一个包含从 0 到 9 的 10000 个数字的列表,对应 CIFAR-10 中的 10 个类中的每一个。
- 飞机:0
- 汽车:1
- 小鸟:2
- 猫:3
- 鹿:4
- 狗:5
- 青蛙:6
- 马:7
- 船舶:8 艘
- 卡车:9 辆
代码 1 定义一个函数,返回一个方便的图像类别列表。该功能将用于预测阶段。因为预测的输出是一个数字,所以它应该被转换成字符串,以便人们能够阅读。
Code 2. label names
探索数据
你可以在 my github 通过改变batch_id
和sample_id
来玩笔记本中的代码单元。batch_id
是一个批次(1-5)的 id。sample_id
是批次中图像和标签对的 id。
下面定义的 display_stats 回答了一些问题,比如在给定的一批数据中…
- “所有可能的标签是什么?”
- “图像数据的取值范围是什么?”
- “标签是有序的还是随机的?”
Code 3. showing sample image in batch #3
我已经尝试了第三批和第 7000 张图片。如图 3 中的结果所示,每个类别的图像数据的数量大致相同。
Fig 3. showing sample image in batch #3
实现预处理功能
您可能会注意到,一些框架/库,如 TensorFlow、Numpy 或 Scikit-learn,提供了与我将要构建的类似的功能。这反映了我不太依赖框架或库的目的。我相信我可以把自己的模型做得更好,或者复制/试验论文中介绍的最先进的模型。对于这个故事,我将实现**normalize**
和**one-hot-encode**
函数。
使标准化
**normalize**
函数获取数据x
,并将其作为规范化的 Numpy 数组返回。x
可以是任何东西,也可以是 N 维数组。在这个故事中,它将是一个图像的三维数组。 最小-最大归一化 ( **y = (x-min) / (max-min)**
) 技术被使用,但是也有其他选项。通过应用最小-最大归一化,原始图像数据将在 0 到 1 的范围内进行变换。为什么应该执行规范化的一个简单答案与激活函数有些关系。
Code 4. min-max normalize function
例如, sigmoid 激活函数接受一个输入值,输出一个新值,范围为从 0 到 1 。当输入值较大时,输出值很容易达到最大值 1。同样,当输入值稍小时,输出值很容易达到最大值 0。
Fig 4. sigmoid function
再比如, ReLU 激活函数取一个输入值,输出一个范围从 0 到无穷大的新值。当输入值稍大时,输出值线性增加。但是,当输入值稍小时,输出值很容易达到最大值 0。
Fig 5. ReLU function
现在,当您考虑图像数据时,所有值最初的范围是从 0 到 255。这听起来像是当它被传递给 sigmoid 函数时,输出几乎总是 1,而当它被传递给 ReLU 函数时,输出可能非常巨大。当执行反向传播过程以优化网络时,这可能导致爆炸/消失梯度问题。为了避免这个问题,最好让所有的值都在 0 和 1 之间。
独热编码
稍后,我将解释模型。目前,你需要知道的是模型的输出。它是基于模型预测结果的每类图像的一组概率。为了在代码中表示这些概率,需要一个具有与图像类别数量相同的元素数量的向量。例如,CIFAR-10 提供了 10 种不同的图像类别,因此您还需要一个大小为 10 的矢量。
Fig 6. one-hot-encoding process
此外,我们的模型应该能够比较预测与地面真相标签。这意味着标签数据的形状也应该转换成大小为 10 的向量。相反,因为 label 是基本事实,所以将值 1 设置为相应的元素。
**one_hot_encode**
函数接受输入**x**
,这是一个标签列表(基本事实)。列表中元素的总数是一个批次中样本的总数。**one_hot_encode**
函数返回一个二维张量,其中行数是批量的大小,列数是图像类的数量。
Code 5. one hot encoding function
预处理所有数据并保存
Fig 7. train/valid/test set
下面的代码 6 使用之前实现的函数**normalize**
和**one-hot-encode**
来预处理给定的数据集。如图 7 所示,来自每个批次的 10%的数据将被合并以形成验证数据集。其余 90%的数据用作训练数据集。最后,有测试数据集已经提供。下面的代码单元将预处理所有的 CIFAR-10 数据,并将其保存到外部文件中。
Code 6. preprocessing
张量流基础
在开始构建网络和训练过程之前,提醒自己 TensorFlow 是如何工作的以及有哪些包是很好的。
TensorFlow 软件包
TensorFlow 附带一堆包。您甚至可以找到具有类似功能的模块。例如,tf.nn.conv2d 和 tf.layers.conv2d 都是二维卷积运算。以下是每个包的类别的用途。
**tf.nn**
:神经网络的低层 APIs】
- 这个包中的每个 API 都有其唯一的用途
- 例如,为了在 conv2d 之后应用激活函数,您需要两个单独的 API 调用
- 你可能需要自己手动设置很多设置
**tf.layers**
:神经网络的高级 API
- 这个包下的每个 API 可能都有简化的过程
- 例如,为了在 conv2d 之后应用激活函数,您不需要两次单独的 API 调用。此程序包下的 Intead,conv2d API 具有激活参数
- 这个包中的每个 API 在参数中都有很多默认设置
**tf.contrib**
:包含易变的或者实验性的 API
- 就像文档解释的那样,这个包提供了实验代码
- 您可能会找到更方便的 API
- 当你在主包下找不到功能的时候,你可以去看看这个包
- 它意味着包含最终应该合并到核心 TensorFlow 中的特性和贡献,但是您可以将它们想象为正在构建中
我将在每个不同的包下使用 API,这样我可以熟悉不同的 API 用法。
张量流工作流
根据官方文档, TensorFlow 使用一个数据流图来根据各个操作之间的依赖关系来表示您的计算。这导致了一个低级编程模型,其中您首先定义数据流图,然后创建一个 TensorFlow 会话来跨一组本地和远程设备运行图的一部分。
数据流是并行计算的通用编程模型。在数据流图中,节点代表计算单元,边代表计算消耗或产生的数据。例如,在 TensorFlow 图中,tf.matmul 操作将对应于具有两条传入边(要相乘的矩阵)和一条传出边(相乘的结果)的单个节点。
大多数 TensorFlow 程序从数据流图构建阶段开始。在这个阶段,您调用 TensorFlow API 函数来构造新的 tf。操作(节点)和 tf。张量(边缘)对象,并将它们添加到一个**tf.Graph**
实例中。 TensorFlow 提供了一个默认图,它是同一上下文中所有 API 函数的一个隐式参数。
**tf.Session.run**
方法是运行 **tf.Operation**
或评估 **tf.Tensor**
的主要机制。您可以将一个或多个**tf.Operation**
或**tf.Tensor**
对象传递给**tf.Session.run**
,TensorFlow 将执行计算结果所需的操作。
Fig 9. TensorFlow dataflow graph
建立网络
下面的图 8 简单地显示了模型将会是什么样子。
Fig 8. classification model
为模型准备输入
为了训练模型,至少应该提供两种数据。应该将图像数据输入到模型中,以便模型可以学习并输出其预测。应该在模型的末尾提供标签数据,以便与预测输出进行比较。要提供的值有很多,但我只打算再包括一个。**keep_prob**
是单个数字在什么概率下每层应该保留多少个单元。这就是所谓的辍学技术。
无论进给数据应该放在模式的前面、中间还是最后,这些进给数据都称为输入。
Code 7. input tensors
TensorFlow 中的[**tf.placeholer**](https://www.tensorflow.org/api_docs/python/tf/placeholder)
创建一个输入。每个输入需要指定期望的数据类型及其维度形状。形状中无表示长度未定义,可以是任何长度。
创建模型
整个模型总共由 14 层组成。除了下面列出的层什么技术适用于建立模型。
- 与 64 个大小为(3x3)的不同滤波器卷积
- 最大 2 池
- ReLU 激活功能
-批量正常化
- ReLU 激活功能
- 与 128 个大小为(3×3)的不同滤波器卷积
- 最大池乘 2
- ReLU 激活功能
-批量正常化
- ReLU 激活功能
- 与 256 个大小为(3×3)的不同滤波器卷积
- 最大 2 池
- ReLU 激活功能
-批量正常化
- ReLU 激活功能
- 与大小为(3x3)的 512 个不同滤波器卷积
- 最大 2 池
- ReLU 激活功能
-批量正常化
- ReLU 激活功能
- 展平最后一次卷积操作的三维输出。
- 全连通 128 层
-脱扣
-批量正常化 - 256 单元全连接层
-脱扣
-批量正常化 - 全连接 512 层
-漏接
-批量归一化 - 1024 单元全连通层
-漏接
-批量归一化 - 具有 10 个单元(图像类别数)的全连接层
下图 9 描述了当您使用**【通道 x 宽度 x 高度】**张量格式时,概念卷积操作与 TensorFlow 实现的不同之处。
Fig 9. convolving operation in tensorflow with [NCWH] form of input
下面的代码 8 展示了如何在 TensorFlow 中构建模型。我们先来看看卷积层。可以使用[**tf.nn.conv2d**](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d)
或[**tf.layers.conv2d**](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d)
创建卷积层。后一种更方便,因为它有更多可选参数。前一种选择创建了最基本的卷积层,您可能需要在**tf.nn.conv2d**
之前或之后添加更多卷积层。比如激活函数可以在**tf.layers.conv2d**
中直接指定为参数,但是在使用**tf.nn.conv2d**
的时候要手动添加。
构建卷积层时,有三点需要考虑。这就是步幅、填充和过滤器。步长决定了滤波器的窗口在每个卷积步骤中应该移动多少,它是一个长度为 4 的一维张量。但是,从技术上来说,官方文件说*‘必须有步幅[0] =步幅[3] = 1’* 。所以你只能控制步幅[1]和步幅[2]的值,但是把它们设置成相等的值是不是很常见。[1,1,1,1]和[1,2,2,1]是最常见的用例。我将使用[1,1,1,1],因为我想逐个像素地进行卷积。
当一个完整的卷积操作完成后,图像的输出尺寸变得小于输入尺寸。但是,您可以通过在图像周围应用额外的 0 值像素来强制保持不变。当填充设置为“相同”时,图像的输出大小将保持与输入图像相同。另一方面,当填充被设置为“有效”时,它会更小。我将使用“相同的”填充样式,因为它更容易管理每个卷积层中图像的大小。
可以用[**tf.Variable**](https://www.tensorflow.org/api_docs/python/tf/Variable)
定义过滤器,因为它只是一堆权重值,并且随着时间的推移在训练网络时会发生变化。过滤器应该是形状为[过滤器 _ 高度,过滤器 _ 宽度,入口 _ 通道,出口 _ 通道]的 4-D 张量。in_channels 表示当前卷积运算所应用的通道数,out_channels 表示当前卷积运算将要产生的通道数。
Code 8. CNN model
如前所述,[**tf.nn.conv2d**](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d)
没有将激活函数作为参数的选项(而[**tf.layers.conv2d**](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d)
有),[**tf.nn.relu**](https://www.tensorflow.org/api_docs/python/tf/nn/relu)
被明确地添加在**tf.nn.conv2d**
操作之后。然后通过使用[**tf.nn.max_pool**](https://www.tensorflow.org/api_docs/python/tf/nn/max_pool)
功能应用最大池化。max pooling 操作可以被视为一种特殊的 conv2d 操作,只是它没有权重。目的是通过保留最强的值来缩小图像。ksize=[1,2,2,1]和 stamps =[1,2,2,1]表示将图像缩小一半。
[**tf.contrib.layers.flatten**](https://www.tensorflow.org/api_docs/python/tf/contrib/layers/flatten)
、[**tf.contrib.layers.fully_connected**](https://www.tensorflow.org/api_docs/python/tf/contrib/layers/fully_connected)
、[**tf.nn.dropout**](https://www.tensorflow.org/api_docs/python/tf/nn/dropout)
功能直观易懂,使用非常方便。只有一件重要的事情要记住,你不要在完全连接的层列表的末尾指定激活函数。这将在稍后定义成本函数时指定。
超参数
超参数是通过十几次实验选择的。需要注意的一点是,必须在定义优化器之前定义 learning_rate,因为这是您需要将 learning rate 作为构造函数参数的地方。
Code 9. hyper parameters
成本函数和优化器
最后,您将定义成本、优化器和准确性。[**tf.reduce_mean**](https://www.tensorflow.org/api_docs/python/tf/reduce_mean)
取一个输入张量进行约简,输入张量是预测结果和地面事实之间某些损失函数的结果。因为 CIFAR-10 必须测量 10 个等级的损耗,所以使用了[**tf.nn.softmax_cross_entropy_with_logis**](https://www.tensorflow.org/api_docs/python/tf/nn/softmax_cross_entropy_with_logits)
函数。在训练网络时,您想要的是通过应用您选择的算法来最小化成本。可能是 SGD , AdamOptimizer ,adagradmoptimizer之类的。你必须研究每种算法是如何工作的,以选择使用什么,但是 AdamOptimizer 通常适用于大多数情况。
Code 10. cost function & optimizer & accuracy
训练神经网络
您已经定义了成本、优化器和准确性,它们实际上是什么…
- 成本
- reduce_mean = >约化后的张量 - 优化器
- AdamOptimizer = >应用指定渐变的操作。 - 精度
- 化简 _ 均值= >化简张量
tf。官方文档中的 Session.run 方法解释了它运行 TensorFlow 计算的一个“步骤”,通过运行必要的图形片段来执行每个操作,并在获取中评估每个张量,用**feed_dict**
中的值替换相应的输入值。获取参数可以是单个图形元素,或者任意嵌套的列表、元组等。
这里真正的图元是**tf.Tensor**
或**tf.Operation**
。成本、优化和准确性就是其中之一。这意味着它们可以被指定为提取参数的一部分。然后,你可以在这个过程中加入一些变量。这是张量流的一个便利特性。一旦构建了图表,您需要做的就是将数据输入图表并指定要检索的结果。
单一优化
**train_neural_network**
函数对给定的一批数据运行优化任务。它将在一个循环中使用,并在以后的多个时期和批次中使用。简单来说,**session.run**
照顾工作。它将第一个参数作为要运行的内容,将第二个参数作为数据列表提供给网络,以便从第一个参数中检索结果。如前所述,您希望通过运行 optimizer 来最小化成本,因此这必须是第一个参数。
Code 11. single optimization task
显示统计数据
**print_stats**
显示当前训练步骤的成本和准确性。与**train_neural_network**
功能类似的过程也适用于此。不是将优化器交付给**session.run**
函数,而是给出成本和精度。请注意**keep_prob**
被设置为 1。辍学率必须适用于培训阶段,否则必须根据论文设置为 1。
Code 12. showing stats
分批训练模型
**train_neural_network**
函数在给定批次上运行优化任务。因为 CIFAR-10 数据集有 5 个单独的批次,并且每个批次包含不同的图像数据,所以应该对每个批次运行 train_neural_network。这可以用简单的代码来完成,如代码 13 所示。代码 13 为每个批次运行 10 个时期的训练,图 10 显示了训练结果。
Code 13. train over batches
Fig 10. loss and accuracy
测试模型
Fig 11. prediction result
参考
- CIFAR-10/CIFAR-100 数据
- 蟒蛇泡菜
- 数字整形
- numpy 转置
- numpy 转置轴说明列表
- 张量流 conv2d
- 行主要订单解释
- 最小-最大归一化
- 观看“为什么要标准化输入”/ deeplearning.ai —吴恩达。
- 爆炸,虚化梯度下降/深度学习. ai——吴恩达。
- 一个热编码
- 张量流架构
- 张量流图和时段
- 张量流数据类型
- Tensorflow 占位符
- 张量流变量
- 【tf.nn 下的 Tensorflow Conv2D】
- 【tf.nn 下的 tensor flow ReLU
- 【tf.nn 下的 tensor flow Max Pooling
- 【tf.nn 下的张量流丢失
- 【tf.layers 下的张量流批量归一化
- 张量流在 tf.contrib 下展平
- 张量流在 tf.contrib 下全连接
- 批量归一化(原纸)
- 批量定额为什么行得通?/ deeplearning.ai —吴恩达。
- 退学(原论文)
- 了解辍学/deep learning . ai——吴恩达。
- (深度)机器学习中的辍学
- 卷积神经网络中的展平步骤是什么意思?
- 卷积神经网络(CNN/conv nets)—cs 231n
- 可视化和理解卷积网络
- 评估 CNN design choices 在 ImageNet-2012 上的表现
- Tensorflow Softmax 与 Logits 的交叉熵
- 张量流减少平均
- 张量流优化器
- 张量流等于
- 张量流投射
- 梯度下降优化算法概述
- 深度模型训练优化
- Tensorflow 会话运行功能
- 张量流 tf.reduce_mean
- tensor flow TF . train . adamotimizer
- 分类数据集结果—远高于 70%
花旗自行车 2017 年分析
此分析的目标是创建 2017 年花旗自行车的运营报告。以下工作在不到五个工作日内完成。在每张图片下,我都加入了自己的想法,如果没有时间限制,我会考虑哪些内容。花旗自行车的分析是基于如下所示的模拟案例:
**概述:**您的客户,纽约市市长,需要更好地了解花旗自行车骑行的情况。他想要一份 2017 年的运营报告,在周末之前放在他的办公桌上。根据之前的约定,我们知道市长非常喜欢在图表中可视化数据。具体来说,市长希望看到各种数据可视化,以了解
- 开始次数最多的前 5 个电台(显示开始次数)
- 按用户类型划分的行程持续时间
- 基于始发站和停靠站的最受欢迎的行程)
- 基于平均行程距离(站到站)、中间速度(行程持续时间/行驶距离)的按性别和年龄划分的骑手表现
- 2017 年纽约最忙的自行车是什么?用了多少次?使用了多少分钟?
此外,市长有一个想法,他想推销给花旗自行车,并需要您的帮助来证明其可行性。他希望花旗自行车能给他们的自助服务终端增加一项新功能:“输入一个目的地,我们会告诉你行程需要多长时间”。我们需要你建立一个模型,在给定起点和目的地的情况下,预测一次旅行需要多长时间。
**客户:**比尔·白思豪纽约市市长
**目标:**通过创建 2017 年运营报告,帮助市长更好地了解花旗自行车骑行情况(仅限纽约市)。
提问:
- 开始次数最多的前 5 个电台(显示开始次数)
- 按用户类型划分的行程持续时间
- 最受欢迎的行程(基于始发站和停靠站)
- 基于平均值按性别和年龄划分的骑手表现。行程距离(站与站之间)、中间速度(行程持续时间/行驶距离)
- 2017 年纽约最忙的自行车是什么?用了多少次?使用了多少分钟?
- 一个模型,可以预测一次旅行需要多长时间,给定一个起点和目的地(不要使用谷歌地图 API)。
数据来源于花旗自行车的亚马逊服务器,可以在这里访问。本文使用的代码可以在这里找到。*
首先,让我们最小化来自服务器的数据集中的工作和负载。很明显,这些文件非常大,每个都有几百兆字节。
!curl -O "[https://s3.amazonaws.com/tripdata/2017[01-12]-citibike-tripdata.csv.zip](https://s3.amazonaws.com/tripdata/2017[01-12]-citibike-tripdata.csv.zip)"
!unzip '*.zip'
!rm *.zip
files = !ls *.csv #For Ipython only
df = concat([read_csv(f, header=None,low_memory=False) for f in files], keys=files)
列名中有空格,出于工作目的,最好将其删除。如果我在一个团队或者一个长期项目中工作,我会稍微不同地配置列名,使它们更容易使用。然而,为了本文的目的,我保持了简单易懂的名称。
数据集非常庞大,大约有 1600 万行。大数据工具会有所帮助,但是,大多数需要您付费或拥有企业许可证或有限试用。此外,数据非常脏。不同的文件有不同的列名,需要考虑这一点。白思豪市长没有技术背景。这里的图表尽可能简单但信息丰富。我本可以做出更复杂的情节,但是,对市长来说,这些情节不会提供太多信息。这些图表是为用户设计的。
最后,我的分析尽量遵循下面概述的 crisp-dm 方法。
Taken from SafariBooksOnline.com
让我们来理解我们正在处理的数据,并简要概述每个特性代表或应该代表什么。
1\. Trip Duration (seconds) — How long a trip lasted
2\. Start Time and Date - Self explanatory
3\. Stop Time and Date - Self explanatory
4\. Start Station Name - Self explanatory
5\. End Station Name - Self explanatory
6\. Station ID - Unique identifier for each station
7\. Station Lat/Long - Coordinates
8\. Bike ID - unique identifier for each bike
9\. User Type (Customer = 24-hour pass or 3-day pass user; Subscriber = Annual Member) - Customers are usually tourists, subscribers are usually NYC residents
10\. Gender (Zero=unknown; 1=male; 2=female) - Usually unknown for customers since they often sign up at a kiosk
11\. Year of Birth - Self entered, not validated by an ID.
第 1 部分:排名前五的电台
让我们检查一下在创建图表之前是否有任何干扰或需要清理的地方。
- 有缺少的值吗?
- 大多是出生年份
- 用户类型很少。
- 花旗自行车客户(一日通票或三日通票)通常是游客,可能不会匆忙或因其他原因填写出生年份
- 花旗自行车的用户往往是纽约市的居民,通过盲目删除缺少值的行,我们将丢失关键信息,并可能引入偏见。
2.让我们了解一下我们正在处理的数据:
3.花旗自行车骑手经常会碰到坏掉的自行车。作为用户,我对这种困境相当熟悉。让我们删除任何行程持续时间少于 90 秒的行程和起点站==终点站。90 秒是一个任意的选择,基于骑车人意识到自行车工作不正常并回到车站归还自行车并换上新自行车所需的时间。另一个可以使用的度量是 372 秒(25%四分位数)。这是基于这样一个假设,如果某人正在进行一次往返旅行,它最有可能是执行一些快速的任务,这些任务离得不够近,不能步行到达,因此这次旅行应该至少比最短的旅行稍微长一点。如果是短途旅行,让我们添加额外的和条件,以确保起点和终点站名相同。
4.诸如盗窃和破损码头之类的异常情况对这个指标来说不重要,可以在以后处理。
Considered a pie chart for this, however, these stations make up less than 5% of the total starts in this dataset
**下一步和业务用例:**在地图上可视化这些车站,看看它们彼此之间有多近,会很有趣。这可用于确定哪些区域需要额外的加油站或自行车。
第 2 部分:按用户类型划分的行程持续时间
就如何处理异常而言,这个问题有点不清楚,所以我将制作两个图表。一个有异常,一个没有。
用户类型的数据集中有 NA 值,如上面缺失的表格图所示。因为它只占数据的 0.09%,所以可以安全地删除它。
**根据花旗自行车的网站:**年度会员每次骑行的前 45 分钟包括在内,日卡用户每次骑行的前 30 分钟包括在内。如果你想把自行车放在外面更久,每多 15 分钟只需额外支付 4 美元。
可以肯定的是,没有人(或很少人)愿意租一辆超过 2 小时的自行车,尤其是一辆笨重的 citibike。如果他们这样做了,假设他们是年度用户,他们将额外花费 20 美元。对于他们来说,如果他们想锻炼身体,买辆自行车会更经济;如果他们想骑自行车游览和探索这座城市,他们可以在中央公园骑辆自行车。可能有一个更好的方法来选择一个最佳的截止日期,但是,时间是客户项目的关键。或者只是接受治疗,再买一辆自行车。自行车的实际成本是 24 小时累计的。
异常:任何超过 2 小时(7200 秒)的行程都可能表明自行车被盗、异常或自行车停靠不正确。作为一名狂热的花旗自行车用户,我亲身体会到一个人骑自行车超过一个小时是没有任何意义的!不过,我加了一个小时的缓冲以防万一。没有骑手会计划超过允许的最长 45 分钟。然而,为了建模的目的,我计划在将来把这个时间减少到一个小时。
- 前半段——数据集中出现异常
- 每种用户类型的平均行程持续时间条形图。这是有帮助的,但最好是看到一个盒子情节或小提琴情节。在几分钟内会更容易解释。
- 第二张图是一个基本的小提琴图,包括了一些异常现象。正如我们所见,噪声太大,这是没有用的。最好不要出现异常情况。
2。后半部分—数据集中无异常
- 基于用户类型的行程持续时间的信息量更大的图表,异常情况如上所述。“传单”已从下图中移除。
Note: User Type will most likely be a strong predictor of trip duration
- 基于用户类型突出显示每次旅行平均持续时间的条形图
可以肯定地说,用户类型将是旅行持续时间的一个强有力的预测因素。这是目前需要注意的一点,我们可以稍后再回到这一点。
**后续步骤&业务用例:**客户每辆自行车允许 30 分钟,而用户每辆自行车允许 45 分钟。数据清楚地表明,消费者倾向于使用自行车的时间更长。如果主要关注的是在码头有自行车可用,那么目前的时间限制是有意义的。然而,如果花旗自行车希望以用户为中心,让客户每辆自行车有更多的时间是值得探索的。
第三部分:最受欢迎的旅行
要获得最受欢迎的旅行,最方便的方法是使用 pandas 中的 groupby 功能。它类似于数据透视表。
trips_df = df.groupby([‘Start Station Name’,’End Station Name’]).size().reset_index(name = ‘Number of Trips’)
groupby 功能使识别最受欢迎的旅行变得极其容易和方便。
**下一步&业务用例:**在地图上看到这一点会很有意思,看看骑手是从北到南、从东到西等等。此外,根据一天中的时间来查看最受欢迎的旅行也不错。这可以帮助 Citi Bike 根据一天中的时间来确定在哪里存放自行车以及在哪里有码头。假设骑车人早上朝一个方向去上班,晚上朝相反的方向回家。
第 4 部分:按性别和年龄划分的骑手表现
**提问:**根据平均行程距离(站与站之间)、中间速度(行程持续时间/行驶距离)按性别和年龄划分的骑手表现
让我们确保我们在这里处理的数据是干净的。
- 缺少性别和出生年份值?—检查上面的缺失表
- 性别不行。出生年份是
- 约 10%的人缺少出生年份。不是一大块数据。可以估算缺失值或删除它。由于它不到数据的 10%,可以安全地假设其余的 90%是数据的代表性样本,我们可以根据性别和起始站 ID 用中值替换出生年份。我选择这种方法是因为大多数同龄的人住在相似的社区(例如:年轻人住在东村,老年人住在上东区,等等。).这将在异常被消除和速度被计算之后进行。可能有更好的方法来估算这些数据,请在下面的评论部分分享你的想法。
df['Birth Year'] = df.groupby(['Gender','Start Station ID'])['Birth Year'].transform(lambda x: x.fillna(x.median()))
2.有异常吗?
- 至于出生年份,有些人出生在 1960 年之前。我可以相信一些 60 岁的老人可以骑自行车,这是一个延伸,然而,任何人“出生”之前骑花旗自行车是一个异常和虚假的数据。可能会有一些老年人骑自行车,但可能性不大。
- 我的方法是找出低于平均值的 2 岁标准差。计算出这个数字后,mean - 2stdev,我去掉了数据的尾端,1956 年之前的出生年份。
df = df.drop(df.index[(df['Birth Year'] < df['Birth Year'].mean()-(2*df['Birth Year'].std()))])
3.计算年龄栏,使视觉效果更容易理解:
df['Age'] = 2018 - df['Birth Year'];
df['Age'] = df['Age'].astype(int);
4.计算行程距离(英里)
- 没有可靠的方法来计算自行车路线,因为没有每辆自行车的 GPS 数据,我们无法知道骑车人走了什么路线。
- 可以使用谷歌地图,并使用纬度,长坐标找到自行车路线的距离。然而,这将需要超过 API 调用的每日限制。使用 geopy.distance 包,该包使用 Vincenty 距离,使用更精确的椭球体模型。这比哈弗辛公式更准确,但对我们的目的来说并不重要,因为地球的曲率对纽约市自行车出行的距离影响可以忽略不计。
- 将来,对于这种规模的数据集,如果速度更快,我会考虑使用哈弗辛公式来计算距离。下面的代码在这样大小的数据集上运行时间太长。
dist = []
for i in range(len(df)):
dist.append(geopy.distance.vincenty(df.iloc[i]['Start Coordinates'],df.iloc[i]['End Coordinates']).miles)
if (i%1000000==0):
print(i)
5.计算速度(分钟/英里)和(英里/小时)
- (分钟/英里):可以像短跑时间(这个人跑多快)一样使用
df['min_mile'] = round(df['Minutes']/df['Distance'], 2)
- (英里/小时):常规方法。英里/小时是一个容易理解的度量单位,也是大多数人习惯看到的单位。因此视觉将基于这种理解而产生。
df['mile_hour'] = round(df['Distance']/(df['Minutes']/60),2)
6.处理“循环”旅行
- 循环旅行是在同一个车站开始和结束的旅行。这些行程的距离将为 0,然而,事实并非如此。这些点会扭曲数据和视觉效果。将删除它们以解决此问题。
- 对于模型来说,这个数据也是无关紧要的。因为如果有人要进行一次循环旅行,唯一知道旅行要花多长时间的人是骑手,假设她/他知道。因此,为模型删除这些数据是安全的。
df = df.drop(df.index[(df['Distance'] == 0)])
7.我们有一些起始坐标为(0.0,0.0)。这些旅行是为了修理或其他目的而被带走的。这些应该被放弃。如果保持的话,这些行程的距离是 5389 英里。由于这个原因,我放弃了任何距离大得惊人的点。此外,我们还缺少一些值。因为它是很小的一部分,所以让我们根据性别和起始位置来替换丢失的值。
Apologies for separate images
- 在一些行程中,骑车人的速度超过每小时 200 英里。这可能是由于用于距离计算的公式或一些其他错误。有记录以来,世界上在平坦路面上骑自行车最快的人达到了每小时 82 英里。可以肯定的是,花旗的自行车手没有一个能达到这个速度。由于这一点以及骑自行车者平均速度为 10 英里/小时的事实,我决定删除所有以英里/小时为单位的速度大于 20 英里/小时且小于平均值 2 标准偏差的数据,因为这可能是骑自行车者发现码头已满并使用另一个码头代替的往返。
8.数据清理后按年龄和性别划分的骑手表现(英里/小时)
There’s a bit of a difference in speed, however, it doesn’t seem drastic enough to have a major impact. Surprising thing is that age doesn’t have a strong impact on speed either.
9.按年龄和性别划分的骑手平均里程表现
Barely a difference in distance travelled, age doesn’t seem to have an impact either except for folks aged 16–25
**下一步&业务用例:**值得探究基于性别和年龄的旅行次数。这有助于根据自行车使用情况创建不同的顾客购物篮。如果工作人员更频繁地使用花旗自行车,他们可能会被收取更高的费用。如果老年人使用花旗自行车,他们应该因为保持健康和活跃而受到奖励。这些信息可以传达给他们的保险公司,以奖励他们对健康的关注。
第 5 部分:按使用时间和分钟划分的最繁忙自行车
提问:
- 2017 年纽约最忙的自行车是什么?
- 用了多少次?
- 使用了多少分钟?
- 最繁忙的自行车和计数可以通过 groupby 函数来识别。下面的功能还将识别自行车被使用的次数
bike_use_df = df.groupby(['Bike ID']).size().reset_index(name = 'Number of Times Used');
bike_use_df = bike_use_df.sort_values('Number of Times Used', ascending = False);
Most popular bike by number of times used: Bike 25738 (2355 times)
- 一个类似的 groupby 函数调用 sum on minutes,它可以识别自行车被使用的分钟数。
bike_min_df['Minutes Used'] = df.groupby('Bike ID')['Minutes'].sum()
bike_min_df = bike_min_df.sort_values('Minutes Used', ascending = False)
Most popular bike by number of minutes used: Bike 25738 (31,340 minutes)
**后续步骤&业务使用案例:**如果结合花旗自行车维护数据,这些信息可用于确定自行车何时需要维护和修理。这有助于减少坏自行车占用车站码头的问题,这是许多骑车人面临的问题。这些信息也可用于建立品牌和营销目的。拥有一辆“花旗年度自行车”会很不错,这是公开宣传的最常用的自行车,作为增加纽约市自行车使用的象征。
第 6.1 部分:预测模型—基线模型
提问:建立一个模型,在给定起点和目的地的情况下,该模型可以预测旅行需要多长时间。
关于信息亭如何工作的假设: 让我们假设当用户输入起点和终点车站时,他们在输入起点和终点车站之前刷他们的密钥卡(如果他们是订户)并在信息亭上输入他们的信息(如果他们是“顾客”)。这意味着我们将知道他们的性别和年龄。因此,这些变量可用于建立模型。
第一步。
- 这个数据集非常庞大。差不多一千四百万行。在我们构建和评估模型时,让我们研究一个随机子样本。如果我试图在整个数据集上构建和评估一个模型,每次运行将花费我大约 10 多分钟,具体取决于模型。决定使用哪部分数据的一个好方法是使用学习曲线。然而,我的内核在试图创建学习曲线时不断崩溃。如果我们要处理多年的数据,我们需要重新考虑这种方法。然而,鉴于上述原因,让我们抽取 10%的数据。它仍然有大约 130 万行,应该是一个有代表性的样本,因为它是随机选择的。为了确保它是一个有代表性的样本,我们应该查看原始数据集和样本数据集的描述。最后,我们可以通过使上面的图像与随机样本相似来确保数据具有代表性。10%的数据通过了上述测试。
- 此外,花旗自行车旅行对订户的限制为 45 分钟,对客户的限制为 30 分钟(参见上文“根据花旗自行车网站”)。在这些各自的时间限制之后,骑手要付费。为了对我们的数据建模,包含持续时间超过规定的 45 分钟的行程是没有意义的。骑手不经常计划超过分配的时间,也没有明确的方法知道谁计划超过分配的时间。这是一个值得探讨的问题,然而,这些数据对于我们的模型来说是噪音。
df = df.drop(df.index[(df['Trip Duration'] > 2700)])
df_sample = df.sample(frac = 0.1, random_state = 0)
第二步。
- 让我们得到一个基线。如果我只是运行一个简单的多元线性回归,我的模型会是什么样的,它会有多精确?需要为多元回归准备数据
- 删除不相关的列
- 旅行持续时间:我们有分钟列,这是目标变量
- 停止时间:在现实世界中,我们在预测行程持续时间时不会有这些信息。
- 起点桩号 ID:起点桩号名称捕获此信息
- 起点桩号纬度:起点桩号名称捕获此信息
- 起点桩号经度:起点桩号名称捕获此信息
- 起点坐标:起点桩号名称获取此信息
- 终点桩号 ID:终点桩号名称捕获此信息
- 终点桩号纬度:终点桩号名称捕获此信息
- 终点桩号经度:终点桩号名称捕获此信息
- 终点坐标:终点桩号名称获取此信息
- 自行车 Id:我们不知道用户最终会使用哪辆自行车
- 出生年份:年龄记录了这些信息
- min_mile:当与距离结合时,实际上是与结束时间相同的信息。我们在现实世界中不会有这些信息。
- mile_hour:当与距离结合时,实际上是与结束时间相同的信息。我们在现实世界中不会有这些信息。
(Speed * Distance = Trip Duration): Which is why speed is dropped
- 起点桩号名称和终点桩号名称:距离变量捕获相同的信息。对于该模型,如果用户输入起点和终点,我们可以构建一个简单的函数来计算距离,这将捕获相同的信息。有人可能会认为应该保留这些信息,因为这是将在信息亭提供的信息。然而,假设有超过 800 个站,如果我们保留这些信息,我们需要为任何回归算法对其进行编码。这将创建 800 个要素(约 1500 万行),产生大量数据,但没有多少信息增益。
- 在上述清理之后,用于基线模型的最终预测因子是距离、用户类型和性别。从第四部分的图片中可以看出,年龄似乎没有影响。为了证实这一点,我运行了有年龄和无年龄的模型。年龄对模型几乎没有影响。
- 我选择进行线性回归。数据的规模和资源的限制使得运行更复杂的模型变得不那么有吸引力。集成算法已经过测试,但是运行时间太长。
- 这个模型对于一个 R 值为 0.774 的基线模型来说是相当好的。距离似乎对旅行持续时间有很大的影响,这是有道理的。
第 6.2 部分:预测模型—包括日期
- 进行改进的步骤:
1.按以下格式添加回溯时间
- 是在工作日还是周末乘车。工作日,大部分时间是上下班高峰期,可能是从家到单位。周末可能是一个更长,更休闲的旅程,并且有更高的可变性。
- *中的乘车时间是上午、下午、晚上还是晚上。*准确的时间将基于基于一天中不同时间的旅行持续时间的差异。会在下面有图片。
2.现在是什么季节?
- 十二月—二月=冬天
- 三月—五月=春天
- 六月—八月=夏天
- 9 月—11 月=秋季
def get_date_info(df):
df['d_week'] = df['Start Time'].dt.dayofweek
df['m_yr'] = df['Start Time'].dt.month
df['ToD'] = df['Start Time'].dt.hour df['d_week'] = (df['d_week']<5).astype(int) df['m_yr'] = df['m_yr'].replace(to_replace=[12,1,2], value = 0)
df['m_yr'] = df['m_yr'].replace(to_replace=[3,4,5], value = 1)
df['m_yr'] = df['m_yr'].replace(to_replace=[6,7,8], value = 2)
df['m_yr'] = df['m_yr'].replace(to_replace=[9,10,11], value = 3)
df['ToD'] = pd.cut(df['ToD'], bins=[-1, 5, 9, 14, 20, 25], labels=['Night','Morning','Afternoon','Evening','Night1'])
df['ToD'] = df['ToD'].replace(to_replace='Night1', value = 'Night')
df['ToD'] = df['ToD'].cat.remove_unused_categories()
df['m_yr'] = df['m_yr'].astype('category')
df['d_week'] = df['d_week'].astype('category')return(df)
- 模型 1:R 中可忽略的改进:77.7%(取决于所使用的 random_state)
- 安全地假设我们可以放弃这些变量,因为它们没有重大影响。
- 有点令人惊讶的是,工作日变量几乎没有影响,因为人们最有可能在周末骑自行车休闲,而不是工作。这可以通过获得骑手的分类来解释。可能很多花旗单车用户都是大学生。
- 另一种可能性是,该特征的效果被这样的事实所扭曲,即在该数据集中既有客户又有订户,并且该特征对两个变量的效果是不同的。然而,现在还没有明确的解释。值得考虑为订阅者和客户建立一个单独的模型,因为他们的行为如第 2 部分所示有很大的不同。
第 6.3 部分:预测模型—改进模型 1
- 下一步将根据性别和行程考虑速度和距离。由于无法对始发站和终点站进行编码(由于点的数量太多),我们正在丢失旅程本身的关键信息。我们需要另一种方法来替代这些措施。
- 我可以做的另一个改变是将 age 放入桶中。然而,数据表明年龄对旅行持续时间没有相关性或影响。这是反直觉的,然而,我没有很好的理由来反驳这些数据。
- 包括基于行程(起点站+终点站)和用户类型的平均速度。
- 旅行原因:有些旅行是上山,有些是下山。根据直觉,有些路线,比如穿过时代广场的路线,交通会很拥挤。
- 用户类型的原因:根据数据,游客(客户)通常会比订户骑得更慢,并经常停车。
2.包括每次旅行的平均持续时间,基于:上述原因的旅行和用户类型
def get_speed_distance(df): df['Start Station Name'] = df['Start Station Name'].astype(str)
df['End Station Name'] = df['End Station Name'].astype(str)
df['Trip'] = df['Start Station Name'] + ' to ' + df['End Station Name']
df['Trip'] = df['Trip'].astype('category')
df['avg_speed'] = df.groupby(['Trip','User Type'])['mile_hour'].transform('mean')
df['avg_duration'] = df.groupby(['Trip','User Type'])['Trip Duration'].transform('median')
return df
- 这个模型要好得多。但是还能更好吗?
- 对出行持续时间有重大影响的一个因素是交通。然而,由于我们不知道骑手走的是哪条路线,所以很难整合这些信息。最后,谷歌地图 API 有使用上限,所以我们不能用它来轻松识别交通模式。
第 6.4 部分:预测模型—改进模型 2
- 很多人认为天气是旅行持续时间的一个很好的预测因素。我个人不同意。天气影响用户是否会骑车,而不是他们会骑多长时间。如果下雪,我不会骑自行车去上班。如果天气好,我将骑自行车去上班。不管我的观点如何,我都要检验这个假设。如果天气不是一个强有力的指标,我将在下一个模型中删除它。
- 气象数据是从国家环境信息中心获得的。来自网站的数据是每日总结。属性包括:高温(华氏度)、低温(华氏度)和降水量(英寸)。
def get_weather(df):
df['DATE'] = to_datetime(df['Start Time'].dt.date)
df = df.merge(df_weather, on = 'DATE', how = 'left')
return df
- 模型几乎没有改进。天气几乎没有影响。
- avg_duration 的系数急剧上升。不知道为什么,但较高的系数是有意义的,因为持续时间是我们的目标变量,avg_duration 是一次旅行最可能花费多长时间的可靠代理(锚)。
- 让我们通过交叉验证来确认模型的有效性:
CV accuracy: 0.874 +/- 0.001
- 基于上面的一些观察,我在没有天气和日期信息作为预测的情况下运行了上面的相同模型。
- 正如我们所看到的,R 有非常小的下降。另一个有趣的观察是该数据对用户类型系数的影响,它几乎减半。
- 对随机样本的影响很小,但是,对于 10 倍的数据量,影响可能会稍大一些,因此对于最终模型,我们保留日期信息。
- 最后,我选择测试其他回归算法,比如随机森林,看看另一个回归变量是否表现得更好。出于运行时的考虑,我选择保持 n_estimators 较低。当此参数设置为 80 时,模型需要 10 分钟运行,R 与线性回归的 R 相同。通过优化其他参数(如 min_samples_leaf)来追踪随机森林可能是值得的。一种方法可能是查看行程持续时间的分布,以确定花费 5-6 分钟、6-7 分钟等的行程数量。这可以帮助识别 min_samples_leaf 参数。在现实世界中,我们不需要精确到精确到秒。只要我们能在一分钟内预测旅程需要多长时间,在我看来这就是一个可靠的结果。谷歌地图不会告诉你你的旅程需要多长时间,精确到秒,它会给你以分钟为单位的整数预测。
第 6.5 部分:预测模型—最终模型
- 我本来可以使用 XGboost 和其他高级算法,但是,对于这种规模的数据集,运行时间太长,而且即使有收益也不值得。
- 最终模型:线性回归(值得探索套索)
- 预测因素:基于行程和性别、用户类型和日期信息的距离、性别、平均持续时间和平均速度
CV accuracy: 0.852 +/- 0.000
*代码是一项正在进行的工作,并且会根据您的反馈不断进行更改和改进。请在下面的评论区留下你的想法。
花旗自行车:泽西城加入了吗?
乘客使用情况、模式和城市最受欢迎的自行车站点
当我第一次听说花旗自行车将在泽西城推出时,我欣喜若狂。夏天的许多周末早晨,我会去林肯公园散步,感受微风,迈着轻快的步伐。我把花旗自行车看作是对我无忧无虑的童年时代的回归,在公园里骑自行车,外加有氧运动。赢赢!如果我喜欢它,我会在纽约的日常通勤中尝试一下,因为 JC 会员资格也允许在那里使用。
Citi Bike NYC 于 2013 年 5 月 23 日推出,拥有 332 个自行车站点和 6,000 辆自行车。**两年多后,花旗自行车新泽西城于 2015 年 9 月 21 日开业,共有 35 个站点和 350 辆自行车。**进展如何?其他人会像我一样兴奋地加入并把它用于娱乐或日常通勤吗?在泽西城骑花旗自行车的到底是谁?
我把我的探索集中在两个最重要的问题上:
- 花旗自行车泽西城用户的骑行模式有哪些?
- 花旗自行车泽西城用户的人口构成是怎样的?
背线用法
首先,全面概述一下花旗自行车 JC 的用法。
Figure A: Citi Bike Jersey City Cumulative Trips — September 21, 2015 (Launch) to July 26, 2016
在 10 个月内进行了超过 161,000 次旅行(图 A),平均每天 520 次旅行。相比之下,纽约在 2015 年有 1000 万次旅行,大约每天 2.7 万次。
Figure B: Citi Bike Jersey City Trips per Month
Trips taken September 21, 2015 to July 26, 2016
每月乘客量如何?
月度细分(图 B)显示,随着 2016 年 5 月和 6 月这几个温暖的月份的到来,使用量有所增加。7 月份的数据不完整,但与 6 月份的趋势一致。
乘客量模式
我们对整个泽西城的乘客量进行了概述,但是所有泽西城的乘客量是否相等?我们先来看看泽西城所有的花旗自行车站。
截至 2016 年 7 月,泽西城共有 47 个车站。更多车站(Astor Place、Communipaw & Berry Lane、Brunswick & 6th 等。)已被添加。
下面的地图显示了 JC Citi 自行车站的使用情况,其中包括从一个 Citi 自行车 JC 站开始的所有行程。前 10 个最活跃的车站中有 9 个位于 JC 市中心(从该车站出发的乘车总次数),唯一一个异常的 Sip 大道位于 Journal Square。
** Citi Bike Jersey City trips taken September 21, 2015 to July 26, 2016
你还会注意到使用范围已经扩展到了泽西城以外,进入了曼哈顿,甚至布鲁克林。这是非常小的一部分,在 161,000 次旅行中只有 84 次,但仍然很有趣。2 个可能的解释:1)泽西城的骑车人把自行车带上轨道列车,或者骑着自行车穿过桥梁和隧道进入纽约市,或者 2)花旗自行车的员工发现废弃的自行车,并在纽约市的车站重新装上。我没有亲眼见过这两种情况,但我更倾向于相信第二种情况
大多数最活跃的电视台都位于市中心,你对此感到惊讶吗?花旗自行车可能只是吸引了一部分客户。事实上,引用了 60%的花旗自行车用户居住在 07302 邮政编码,包括大部分市区。
Figure C: Citi Bike Jersey City Trips by Neighborhood, Start Station
Trips taken September 21, 2015 to July 26, 2016
如果我们直接观察邻近地区的出行(图 C),70%的出行始于市中心的一个车站,Journal Square 位居第二,但在所有出行中占 16%。
市中心有什么吸引了这么多用户?它真的对普通市区居民有吸引力吗?也可能不是骑手的问题,更多的是车站的位置问题。这些车站是否位于交通便利的地点,靠近步行交通便利的泽西城商业区或其他公共交通枢纽?
Figure D: Citi Bike Jersey City Most Popular Start Stations
Trips taken September 21, 2015 to July 26, 2016
让我们来了解一下!以下是最受欢迎/最活跃的起点站(图 D)。
****前 10 个车站中,有 5 个(Grove St PATH、Exchange Place、Sip Ave、Newport PATH、Essex Light Rail)距离其他形式的公共交通、PATH 站或轻轨非常近。在前 10 名中,Sip 大道甚至不在市中心。Sip Avenue 站就在 Journal Square 交通枢纽的外面,乘客可以乘坐轨道列车进入泽西城、霍博肯、曼哈顿市中心区的其他地区,或者选择乘坐巴士环游泽西城或前往霍博肯、巴约纳或曼哈顿。
****但是靠近交通枢纽并不是成功的立竿见影的方法。Garfield Ave、West Side 和 MLK 轻轨 Citi 自行车站的使用率都在三分之一以下。然而,市中心可能是一个神奇的社区——前 20 个车站中有 13 个在市中心。注意:莫里斯运河、泽西第六街&和泽西第三街&的使用率确实很低,但这些站点是 2016 年 7 月才增加的,所以你最多只能看到 3 周的使用率。此外,这里没有列出的几个市区车站没有任何乘客,但几个月后我们就可以看到采用率是否上升。
Figure E: Citi Bike Jersey City Most Popular Routes
Trips taken September 21, 2015 to July 26, 2016
最后,让我们从另一个角度来看乘客量:最受欢迎的路线(图 E)。
到目前为止,我们并不惊讶地得知 10 条最受欢迎的路线中有 8 条的起点或终点都在市中心。但是看看 4 号,麦金莱广场- > Sip Ave。麦金莱广场甚至没有打破我们的十大起点站,但是作为骑手常规路线的一部分,它就在那里。因为我是泽西城的居民,所以我能猜到原因。麦金莱广场自行车站就在哈德逊天主教地区高中外面,是一个相当活跃的公交车站。学生们可以离开教室,跳上一辆花旗自行车去 Sip Ave(就在期刊广场),然后换乘只有在 JSQ 站才有的 PATH 火车或公共汽车。
你有没有注意到最受欢迎路线的下半部分正好是上半部分路线的反方向?我乐在其中!这可能是一个迹象,表明这些骑车人正在遵循一个日常或至少是规律的模式**:早上跳上一辆花旗自行车去上班,把它停靠在终点站(靠近另一个交通枢纽),在一天结束时,如果他们选择,就把花旗自行车直接开回家。然而,因为反向旅行的数字并不完全反映对应的,有可能他们正在寻找另一条回家的路。当然也可以反过来,前 5 条路线实际上可以从骑手的工作场所开始。我需要将路线数据按时间分段来找出答案。我们将把这个分析留到下一天。**
在我的 的下一篇文章 中,我们将看看工作日与周末的使用情况,以及花旗自行车新泽西城骑行者的人口构成。
— —
花旗自行车出行信息数据来自泽西城开放数据门户 此处
花旗自行车站位置 此处
城市级项目#2
结论和进一步措施
urban pattern convolution layer
城市级—第一部分
令我高兴的是, 城市级 项目受到了城市规划专家、城市规划专家和 IT 专家的广泛关注。幸运的是,我赶上了机器学习的潮流,它在不同的领域传播。特别是可以在莫斯科研究所 Strelka “机器能看见”的文章中读到。
我从双方那里得到了很多有意义的反馈。这表明所选择的活动方向比以往任何时候都更重要,而且有必要继续这项工作。最重要的事件是受邀参加 Yandex Data &科学大会:城市,在那里我做了详细的报告(Yandex——俄罗斯最大的搜索引擎和 IT 公司。视频记录,俄语,见页面底部)。为这次活动准备了额外的材料,我将在下面概述这些材料。
城市+数据科学=:)
结论和补充
也许最重要的结论是,对于那些人们已经学习了多年的特定知识,机器学习的可能性非常大,并且委托给神经网络来做专家在大多数时间里做的事情。机器学习的这种结果可以完全改变既定的方法和实践。本研究项目是对本论文的实践验证。
人们特别感兴趣的是观察深层神经网络内层的图像。我的神经网络包括如下 3 个卷积层(LeNet-like):
#Keras CNN-model
model = Sequential()model.add(Convolution2D(32, 3, 3, input_shape=(3, 300, 300)))#1 conv
model.add(Activation('relu')) #2 activation
model.add(MaxPooling2D(pool_size=(2, 2)))#3 MaxPoolingmodel.add(Convolution2D(64, 3, 3)) #4 conv
model.add(Activation('relu')) #5 activation
model.add(MaxPooling2D(pool_size=(2, 2))) #6 MaxPoolingmodel.add(Convolution2D(64, 3, 3)) #7 conv
model.add(Activation('relu')) #8 activation
model.add(MaxPooling2D(pool_size=(2, 2))) #9 MaxPoolingmodel.add(Flatten())
model.add(Dense(128)) #all connected layers
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes)) #7 classes
model.add(Activation('softmax'))
由于下面的过程,使用 theano 函数,我们可以从所需的层中获得图像数组,然后将它们可视化。
LayerID = 0 # layer to viz (0..8)output_layer = model.layers[LayerID].output
output_fn = theano.function([model.layers[0].input], output_layer) output_image = output_fn(input_image)
在直觉层面上,神经网络的图像处理可以描述如下:
- 在第一卷积层(1.conv ),网络感知输入图像,揭示其中的特征轮廓;
- 在随后的层(2-6)上,识别出单独的结构,在这种情况下是道路和房屋;
- 在最后一个卷积层(7.conv)上,将分离的结构组装成一些复合体,这些复合体是该类的特征,在此基础上图像被进一步分类。
分析中间图像,人们可以注意到隐藏的模式和启发,当考虑原始图像时并不总是清楚的。
俄罗斯城市的一些城市模式和内层可视化:
Private housing; Historic district
Urban blocks mid 20th; Microrayon
城市群分析和预测的新工具
基于在第一部分中获得的数据,可以获得所考虑城市的城市规划情况的概化方案。
需要强调的是,城市的一个区域超出了的行政边界。因此,机器学习是一种具有巨大潜力的工具,用于分析和修复发生在最大城市的聚集过程。今后,这些方案可用于制定总体规划和其他相关文件的方案。
根据我的经验,我认为在项目设计和城镇规划中使用机器学习的可能场景如下:
- 总体规划方案
- 帮助决策
- 信息图表和商业分析
- 与 CAD 和 BIM 设计系统集成
- 描述和预测城市发展的新方法
- 见解!
未来计划
CityClass 项目显示了使用机器学习作为与城市和集聚区合作的新工具的巨大潜力。因此,我将沿着以下方向发展我的工作室 建筑 :
- 对世界其他城市的报道和分析
- 从细胞网格撤退,基于街道网络的分裂和区分
- 基于其他标准、类别的培训模型
- 对象检测和生成
- 过渡到张量流
кучуков/罗曼·库丘科夫—
建筑师、城市规划者和城市研究者;
工作室的创始人 建筑
市级项目
基于神经网络的城市模式识别
这是我长期项目*【aitecture.com】*的一部分
城市级—第二部分
人工智能技术现在已经渗透到经济的许多领域,建筑、设计和城市化也不例外。它们有巨大的潜力,直到完全修改已建立的方法和实践。我的研究是我们如何利用人工智能完成特定的任务——以俄罗斯城市为例识别城市模式。
和一个城市打交道,无论是城市规划、概念还是研究,都要把握它的结构。地图服务的可用性并不能给出城市的总体概念。
这种方法采用了神经网络,它可以学习如何识别不同的城市模式,最终得到一个整体的画面。所以我们可以对这个城市和它的景观有一个新的认识。
如果一个人在看卫星地图时能够区分工业区和住宅区,那么计算机就能为我们做到这一点。任务是训练它,从而将知识从人转移到神经网络。
在我的研究中,我分析了五个人口超过 100 万的俄罗斯大城市:
莫斯科,下诺夫哥罗德,喀山,萨马拉,叶卡捷琳堡。
许多俄罗斯城市的特点是它们有共同的城市发展模式(形态类型)。例如,住宅区由典型的系列建筑组成,根据一个原理——这种类型或住宅区称为‘微住宅区’。因此,俄罗斯城市的地貌类型可以在单一模式集合的基础上进行分析。
该方法包括两个阶段:
1)学习:培训模式
在这一阶段,获得足够数量的高质量训练数据集非常重要。为此,一个专家——一个可以对物体进行分类的人(在这种情况下——我自己),以随机的顺序,对数据库中的单个物体进行分类,例如总数的 10%。越大越好。然后,当训练数据集被收集时,就可以训练神经网络模型——分类器。
2)预测:样本分类
当模型被训练时,无限数量的样本可以通过它。输出是样本的预测类别。
我们训练了一台计算机,现在它为我们产生新的知识!
Preliminary (expert) classification
我用了一个工作流带:
- GIS 包 Qgis,带模块 Open Layers for Google maps,还有我自己的脚本用于样本的初步分类和导出;
-带有机器学习库的 Python 环境:Keras,Theano。
作为机器学习的模型,我使用了卷积神经网络(CNN),它用于 LeNet 项目。
LeNet project —handwriting recognition
对于 CityClass 项目,选择并分类了 1686 个样本( 1267 训练/ 419 验证)。有可能通过 70–75%的验证集实现分类的准确性,这对于小型数据库来说仅仅是一个很好的指标,并且考虑到不是所有的样本都可以明确确定。
模式的类别
所有城市被划分为一个网格,网格大小为 600 x 600 m,从中选择了 7 个典型的城市模式类别。根据样品中的主要成分,对整个样品进行了分类。
Classes: 1, 2, 3
- 1 —私人住宅区;
- 2 —历史街区,20 世纪初以前。;
- 3 —拥有独立住宅建筑的城市街区,也就是所谓的“斯大林风格”,小写——20 世纪上半叶,1930-1960;
классы 4, 5, 6, 7
- 4——大众住宅公寓建筑— 微型住宅,1960 年至 1990 年;
- 5 —现代住宅开发,从 2000 年代开始;
- 6—工业和公共区域:工业区、火车站、购物中心、体育场、基础设施;
- 7 —自然和混合区域。
结果
莫斯科
7636 个样本
Moscow
公认的大区域,由许多瓦片组成:莫斯科的历史中心,公园,莫斯科的河床,工业区,城市主要部分以外的低层居住区网络。
城市的放大片段:
在放大的片段上,单个物体清晰可见,例如:列宁斯基前景(街道)、铁路基础设施、前 ZIL 工厂等。
其他城市也有类似的描述。
喀山
1389 个样本
Kazan
下诺夫哥罗德
1188 个样本
Nizhny Novgorod
翅果
691 个样本
Samara
叶卡捷琳堡
1254 个样本
Yekaterinburg
结论
我很高兴我设法以我构想的形式实现了这项研究的想法,同时达到了 70%以上的分类准确率的计划水平。
这只是如何在城市/城市发展实践中使用深度机器学习技术的一个例子。例如,你可以训练一个神经网络来区分区域和公共空间,提取它们的具体特征以便以后使用。
通过同样的技术,我们可以分类其他城市,例如在欧洲或美国。
从神经网络的内层获取图像也是一个好主意。这将是下列职位之一。
结果,我们用电脑看待城市的方式来看待城市。
基于 R 的大规模噪声数据集的分类
几天前,我写了一篇文章,描述了一个全面的监督学习工作流程,使用 caret 和 caretEnsemble 包进行多种建模。当时我提到我使用的是一种简单的T4,在某种意义上,它是全数字的,完全填充的(没有一个缺失值),没有分类特征,没有类别不平衡(当然,因为这是一个回归问题),并且它是一个相当小的数据集,只有 8 个预测值。
这感觉就像是作弊,但它确实帮助了我写的第一篇文章,也帮助我顺利地完成了整个工作流程,并最终使用caretEnsemble.
做了一些多重建模
所以现在我决定把这个从简单难度提升到普通难度。
在这种意义上,我在我打算使用的 UCI 机器学习库中遇到了这个数据集。
我们在这个数据集上遇到的新困难是什么?我来总结一下:
- 目标变量是分类二项式的,具有非常高的类别不平衡
- 数据集的大小相当大。训练集是 60,000 x 171,测试集是 16,000 x 171
- 巨大的价值缺失问题
- 异常值和多重共线性的潜在存在
- 第一类错误和第二类错误都有特定的成本,这就要求我们尽量减少第二类错误。
这是存储库所有者对数据集和任务的描述:
“数据集包含从日常使用的重型斯堪尼亚卡车上收集的数据。重点介绍的系统是空气压力系统(APS ),它产生压缩空气,用于卡车的各种功能,如制动和换档。数据集的正类包括 APS 系统特定组件的组件故障。负类包括与 APS 无关的部件出现故障的卡车。这些数据由专家选择的所有可用数据的子集组成。
出于专有原因,数据的属性名称已被匿名化。它由单个数字计数器和直方图组成,直方图由不同条件的仓组成。(…)总共有 171 个属性,其中 7 个是直方图变量。缺失值用“na”表示。
—挑战指标
失误分类的成本度量:
在这种情况下,成本 _1 指的是需要由一名机械师在车间进行不必要检查的成本,而成本 _2 指的是遗漏一辆故障卡车的成本,这可能会导致故障。
*Total_cost = Cost_1 * No_Instances + Cost_2 * No_Instances*
我们会试试看!
环境
1.1)我们试图预测什么?
我们需要预测系统故障的类型。它可以是 APS 的故障组件,也可以是与 APS 无关的故障组件。这一点非常重要,因为我们的预测误差会导致公司不必要的支出。具体来说,我们希望避免类型 2 错误(错过故障卡车的成本,这可能会导致故障)。
2.2)这是什么类型的问题?监督学习还是非监督学习?分类还是回归?二元还是多类?单变量还是多变量?
这是一个具有多个特征的二元分类问题。
2.3)我们有什么类型的数据?
我们有两个 csv 文件,一个用于培训,一个用于测试。在实际数据开始之前,两者都显示了 20 个不重要的文本行,我们必须在导入数据框时跳过这些行。列名有一行,缺少的值用“na”表示,因此我们将确保在读取CSV 时包含这些值。
2.4)导入数据集
training_data <- read.csv("aps_failure_traning_set.csv",
skip = 20,
na.strings = "na")test_data <- read.csv("aps_failure_test_set.csv",
skip = 20,
na.strings = "na")
我们检查两个数据集的维度:
dim(training_data)
dim(test_data)[1] 60000 171
[1] 16000 171
2.5)激活项目期间要使用的包
library(dplyr)
library(caret)
library(caretEnsemble)
library(mice)
library(doParallel)
library(car)
探索性数据分析
2.1)查看数据(str 或 dplyr 的一瞥)。第一眼。有什么奇怪的吗?
导入集合时指定na.strings=”na"
允许 R 将每个特性识别为数字。如果我们不这样做,每列中出现的 na 会自动导致它们被归类为字符类型。
使用下面的代码,我们可以看到除了我们的响应变量class
,所有其他的特性都是数字的。
glimpse(training_data)glimpse(test_data)
2.2)它是一个“整洁”的数据集吗?需要“聚集”还是“分散”呢?它是以一种我们可以合作的方式呈现的吗?
很整洁。每行是一个观察值,每列是一个特征。
2.3)行名和列名可以吗?我们应该改变他们吗?
我看不出有什么理由要改变它们。
2.4)检查数据类型。他们还好吗?如果没有,转换
我们已经评估过数据类型是可以的。在这里,您还需要检查响应变量是否属于 factor 类型,以及预期的两个级别。
2.5)我们的响应/目标变量是什么?阶层失衡?研究一下
我们的目标变量是class
,有两个级别: neg 和 pos 。积极类包括 APS 系统特定组件的组件故障。负类包括与 APS 无关的部件出现故障的卡车。
每组有多少个阴性和阳性?
summary(training_data$class)
summary(test_data$class) **neg pos
59000 1000
neg pos
15625 375**
让我们检查一下比例:
options(digits = 2)prop.table(table(training_data$class))
prop.table(table(test_data$class))**neg pos
0.983 0.017****neg pos
0.977 0.023**
好吧,看起来这里有个问题。阶级完全不平衡。
我们可能会想出一个无用的模型,将每个观察结果分类为阴性并获得 97.7%的准确性,所以让我们小心我们的准确性分数解释。
稍后我们会看到我们如何处理阶级不平衡。
2.6)其余功能。汇总统计数据。了解您的数据
我们正在处理 171 个特征,所以在整个数据集上调用summary()
在视觉解释方面不会有太大帮助。相反,我们将使用summary()
函数创建一个数据框。这将使我们能够计算一些新的统计数据,特别是与缺失值相关的统计数据,正如您将看到的,这是该数据的另一个大问题。
利用这个汇总数据框架,我们还将计算所有数据的平均四分位数。这也将允许我们了解更多关于特征的分布和丢失值的平均数。
options(scipen = 999)**summary_df** <- do.call(cbind, lapply(training_data[,
2:ncol(training_data)], summary))
**summary_df_t** <- as.data.frame(round(t(summary_df),0))**names**(summary_df_t)[7] <- paste("Missing_values")summary_df_t_2 <- summary_df_t %>%
mutate(obs = nrow(training_data),
Missing_prop = Missing_values / obs)print(summary_df_t_2)
Each row is a feature. In this case we are just looking at the first 10 features
summary_df_t_2 %>% summarise(Min = mean(Min.),
first_Q = mean(`1st Qu.`),
Median = median(Median),
Mean = mean(Mean),
third_Q = mean(`3rd Qu.`),
Max = max(Max.),
mean_MV = mean(Missing_values),
obs = mean(obs),
mean_MV_perc = mean_MV / obs)
Summary of all features using the mean of each column
我们可以看到,在 60,000 个样本中,每个特征的平均缺失值数为 5,000。这意味着每列平均有 8.3%的缺失值。太多了!
让我们对我们的测试集进行同样的检查:
同样,我们还有 8.4%的缺失值。我们将不得不处理他们,之后会有一个特别的部分。
2.7)分类数据/因素:创建计数表以了解不同的类别。全部检查一下。
除了我们的响应变量,我们不使用任何其他分类特征。
2.8)不必要的列?我们可以很快理解我们不需要的列。放下它们
到目前为止,我们还没有检测到任何要删除的列。这个我们以后再说。
2.9)检查是否有缺失值。多少?在哪里?删除它们?归咎于他们?
我们的特征平均存在超过 8%的缺失值。
因为我们不想失去很多信息,所以我们的方法是估算它们。但是首先,我们不想使用一种技术来分别估算我们的两个集合(训练和测试)。它必须是使用全部信息的一次性估算。为了做到这一点,我们将结合这两个集合,对它们进行处理,然后再次分离。
#replicate our sets
training_data_bind <- training_data
test_data_bind <- test_data#create a new column "set" to label the observations
training_data_bind$set <- "TRAIN"
test_data_bind$set <- "TEST"#merge them into 1 single set
full_dataset <- rbind(training_data_bind, test_data_bind)
dim(full_dataset)[1] 76000 172
我们最终得到包含 76,000 个样本的单个集合(16,000 个来自测试集,60,000 个来自训练集)。列数为 172 (171 个功能+ 1 个“设置”列)
缺失值插补
我们将使用包鼠标来估算缺失值。这里有一个关于鼠标如何工作的很好的解释
下面的公式允许我们使用均值插补来插补整个数据集:
set.seed(123)
imputed_full <- mice(full_dataset,
m=1,
maxit = 5,
method = "mean",
seed = 500)
现在我们存储估算值:
full_imputed <- complete(imputed_full, 1)
然后,我们检查是否仍然保持相同的尺寸:
dim(full_imputed)[1] 76000 172
现在让我们检查我们没有丢失值:
(na_count_full_imputed <-data.frame(sapply(full_imputed, function(y) sum(length(which(is.na(y)))))))
等等。如果您运行该代码并查看每一行,您会注意到有些特性仍然缺少值。具体来说有 9 行。
让我们来看看是什么导致了它们:
issue_columns <- subset(imputed_full$loggedEvents,
meth == "constant" | meth == "collinear")
print(issue_columns)
我过滤了估算数据框的$loggedEvents
属性。这里我们看到一些特征被标记为常数或共线。其中一个是我们的集合列(我们用来把两个集合合二为一的那个),所以我们不担心那个。其余的主要是共线变量和一个常量变量。鼠标会自动跳过这些栏,让我们知道问题。我们希望删除这些要素,这样我们就有了一个完整的数据集,不会丢失任何值。
为此,我们首先存储列名,注意不要存储集合的列名(我们需要它)
#create vector of column names
issue_columns_names <- as.character(issue_columns[, "out"])
issue_columns_names <- issue_columns_names[-2]
print(issue_columns_names)[1] "cd_000" "bt_000" "ah_000" "bu_000" "bv_000" "cq_000" "cf_000" "co_000"
然后,我们使用存储的向量从数据框中移除这些列,并将其存储为最终的估算数据框:
full_imputed_filtered <- full_imputed[ , !(names(full_imputed) %in%
issue_columns_names)]
dim(full_imputed_filtered)[1] 76000 164
请注意,列数从 172 减少到了 164。
现在我们不再有缺失值了!(查一下!)
最后,是时候将我们的完整估算数据集再次分成训练集和测试集,我们需要将其分成与之前完全相同的样本。为此,我们只需使用我们的 set 列过滤数据帧。
#subset the full_imputed_filtered dataset
training_data_imp <- subset(full_imputed_filtered, set == "TRAIN")
test_data_imp <- subset(full_imputed_filtered, set == "TEST")#drop the "set" column, we don't need it anymore
training_data_imp$set <- NULL
test_data_imp$set <- NULL#check dimensions
dim(training_data_imp)
dim(test_data_imp)[1] 60000 163
[1] 16000 163
太好了!,我们有我们的训练和测试集分裂,没有丢失值!
2.10)检查异常值和其他不一致的数据点。箱线图。厨师的距离。DBSCAN?
对于该数据集,我们将使用库克距离:
cooksd <- cooks.distance(glm(class ~ .,
family = "binomial",
data = training_data_imp))
让我们画出结果:
plot(cooksd,
pch="*",
cex=2,
main="Influential Obs by Cooks distance") abline(h = 4*mean(cooksd, na.rm=T), col="red")
在这个图中,看似一条又黑又粗的黑线,实际上是我们所有的数据点。在右上角,我们还可以看到似乎有 1 个异常值,或者一堆异常值组合在一起。
让我们看看有多少:
outliers <- rownames(training_data_imp[cooksd > 4*mean(cooksd, na.rm=T), ])
print(outliers)[1] "617" "3993" "5349" "10383" "10829" "18764" "19301" "21138" "22787" "24360" "24975" "29146" "30633" "33684"
[15] "38785" "45978" "50283" "51003" "52573" "53283" "54957" "57186"
根据 cook 的距离测试,总共有 22 个点被认为是异常值。
因为与我们的总数 60,000 相比,这是一个非常低的观察值,所以我决定不删除它们。这似乎只是测量中的可变性,而不是实验误差。
2.11)检查数字数据中的多重共线性
EDA 阶段的最后一步是检查多重共线性。我们已经删除了一些被小鼠检测为共线的列。这里,我们将分析有多少双变量关系具有高相关性,如果比例非常高:
sum((correlation > 0.5 | correlation < -0.5) & correlation < 1) / (162*162)
[1] 0.12sum((correlation > 0.7 | correlation < -0.7) & correlation < 1) / (162*162)
[1] 0.047sum((correlation > 0.9 | correlation < -0.9) & correlation < 1) / (162*162)
[1] 0.0055
这意味着在 26,244 个可能的变量相关性中:
- 12%的人得分高于 0.5
- 比 0.7 高 4.7%
- 比 0.9 高 0.55%
我不会做更多的讨论,并且认为多重共线性在这一点上不是一个大问题。
特征工程
我们也不会花时间在这个已经加载了大量功能的数据集中设计功能。没有我们可以使用的额外信息。
系统模型化
我们现在已经为建模准备好了训练和测试数据集。我们估算了缺失值,移除了共线要素,并验证了异常值和多重共线性不是我们应该关注的大问题。
由于数据的大小,我们将训练一个逻辑回归模型和一个朴素贝叶斯模型。与 r andom forests 、 SVMs 或梯度推进模型等更先进的算法相比,两者都非常快。
我在这里不是为了赢得比赛,而是为了证明自己有一个可以接受的分数。
我将使用caretEnsemble
的caretList()
在同一时间用相同的重采样来训练两者。
请注意,我在trainControl()
中指定了*“上升”——采样*。这将解决等级不平衡。关于上采样的更多信息。
registerDoParallel(3)
getDoParWorkers()set.seed(123)my_ctrl <- trainControl(method = "cv",
number = 5,
classProbs = TRUE,
savePredictions = "final",
index =
createResample(training_data_imp$class, 3),
sampling = "up",
allowParallel = TRUE) model_list <- caretList(class ~ .,
data = training_data_imp,
methodList = c("glm", "nb"),
metric = "Kappa",
tuneList = NULL,
continue_on_fail = FALSE,
preProcess = c("center", "scale"),
trControl = my_ctrl)
我们的结果:
Logistic Regression model
Naive Bayes model
请注意,我们的准确性得分低于我们的无用户 预测全否定 模型的 97.7%。我们没有获得更高分数的原因是因为我们对数据进行了上采样,从而生成了新的数据点来修复类别不平衡。我们在 caret 的 trainControl 中将其作为一个参数集,所以我不会显示任何细节,但通过这样做,我们提高了预测正类(在这种情况下为“neg”)的能力,而不仅仅是为了最大限度地提高准确性。
对看不见的(测试)数据的性能
让我们快速检查一下混淆矩阵:
#Logistic Regression model
confusionMatrix(predict(model_list$glm,test_data_imp, type = "raw"), test_data_imp$class)#Naive Bayes model
confusionMatrix(predict(model_list$nb,test_data_imp, type = "raw"), test_data_imp$class)
Logistic Regression performance on test set
Naive Bayes performance on test set
根据每种错误的成本矩阵,我们的得分为:
逻辑回归模型:52 x 500 + 834 x 10 = 34,340
朴素贝叶斯模型:42 x 500 + 498 x 10 = 25,980
对于这种快速的建模来说,这已经是不错的表现了。我敢打赌,通过更多的努力,我们可以非常接近最佳的 3 名选手: