数据科学的统计学-全-
数据科学的统计学(全)
原文:
annas-archive.org/md5/c1775cf5add79c3a9b0f4e83a2b2229d
译者:飞龙
前言
统计学是数据科学领域任何任务的绝对必要先决条件,但对于进入数据科学领域的开发人员来说,可能也是最令人生畏的障碍。本书将带你踏上从几乎一无所知到能够熟练使用各种统计方法处理典型数据科学任务的统计之旅。
本书所需的内容
本书适合那些有数据开发背景的人员,他们有兴趣可能进入数据科学领域,并希望通过富有洞察力的程序和简单的解释获得关于统计学的简明信息。只需带上你的数据开发经验和开放的心态!
本书适用对象
本书适合那些有兴趣进入数据科学领域,并希望通过富有洞察力的程序和简单的解释获得关于统计学的简明信息的开发人员。
约定
在本书中,你会发现一些文本样式,用来区分不同类型的信息。以下是一些样式示例及其含义说明。
文本中的代码词、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟网址、用户输入以及 Twitter 用户名等如下所示:在统计学中,boxplot
是一种简单的方法,用于获取关于统计数据集的形状、变异性和中心(或中位数)信息,因此我们将使用 boxplot
来分析数据,以查看我们是否能识别出中位数 Coin-in
以及是否有任何离群值。
代码块设置如下:
MyFile <-"C:/GammingData/SlotsResults.csv"
MyData <- read.csv(file=MyFile, header=TRUE, sep=",")
新术语和重要词汇以粗体显示。
警告或重要提示如下所示。
提示和技巧如下所示。
读者反馈
我们始终欢迎读者的反馈。告诉我们你对这本书的看法——喜欢或不喜欢的部分。读者的反馈对我们非常重要,因为它帮助我们开发出你能够真正受益的书籍。如果你想给我们提供一般性反馈,只需发送电子邮件到feedback@packtpub.com
,并在邮件主题中提及书名。如果你在某个领域拥有专业知识,且有兴趣撰写或为书籍提供贡献,请查看我们的作者指南:www.packtpub.com/authors。
客户支持
现在你已经成为一本 Packt 书籍的骄傲拥有者,我们为你提供了一些帮助,以便你最大限度地利用你的购买。
下载示例代码
你可以从你的账户下载本书的示例代码文件:www.packtpub.com
。如果你是从其他地方购买了这本书,可以访问www.packtpub.com/support
,并注册以便将文件直接通过电子邮件发送给你。你可以按照以下步骤下载代码文件:
-
使用你的电子邮件地址和密码登录或注册我们的网站。
-
将鼠标指针悬停在顶部的 SUPPORT 标签上。
-
点击代码下载与勘误。
-
在搜索框中输入书名。
-
选择你要下载代码文件的书籍。
-
从下拉菜单中选择你购买这本书的地点。
-
点击代码下载。
下载文件后,请确保使用最新版本的工具解压或提取文件夹:
-
Windows 版 WinRAR / 7-Zip
-
Mac 版 Zipeg / iZip / UnRarX
-
Linux 版 7-Zip / PeaZip
本书的代码包也托管在 GitHub 上,网址为github.com/PacktPublishing/Statistics-for-Data-Science
。我们还提供了其他来自我们丰富书籍和视频目录的代码包,网址为github.com/PacktPublishing/
。赶紧去看看吧!
下载本书的彩色图片
我们还为你提供了一份 PDF 文件,其中包含本书中使用的屏幕截图/图表的彩色图片。这些彩色图片将帮助你更好地理解输出的变化。你可以从www.packtpub.com/sites/default/files/downloads/StatisticsforDataScience_ColorImages.pdf
下载该文件。
勘误
尽管我们已尽最大努力确保内容的准确性,但错误仍然可能发生。如果你在我们的书籍中发现错误——可能是文本或代码中的错误——我们非常感谢你向我们报告。通过这样做,你不仅能帮助其他读者避免困扰,还能帮助我们改进后续版本的书籍。如果你发现了勘误,请访问www.packtpub.com/submit-errata
报告,选择你的书籍,点击“勘误提交表单”链接,填写勘误详情。一旦勘误得到验证,你的提交将被接受,并且该勘误将被上传到我们的网站或加入该书名的现有勘误列表中。要查看之前提交的勘误,请访问www.packtpub.com/books/content/support
,并在搜索框中输入书名。所需的信息将显示在勘误部分。
盗版
互联网盗版一直是各类媒体中的一个持续性问题。我们在 Packt 非常重视保护我们的版权和许可证。如果你在互联网上发现任何形式的非法复制品,请立即提供相关网址或网站名称,以便我们采取相应措施。请通过copyright@packtpub.com
与我们联系,并附上涉嫌盗版材料的链接。感谢你在保护我们的作者以及我们为你提供有价值内容的能力方面的帮助。
问题
如果你在使用本书的过程中遇到任何问题,可以通过questions@packtpub.com
与我们联系,我们将尽力解决问题。
第一章:从数据开发者到数据科学家的过渡
在本章中(以及本书的所有章节中),我们将为你规划从像数据开发者一样思考到像数据科学家一样思考的过程。
我们将使用开发者术语和类比,讨论开发者的目标,典型的开发者思维方式,如何与数据科学家的思维方式有所不同,为什么两者之间会有重要的差异(以及相似之处),并建议如何过渡到像数据科学家一样思考。最后,我们将提出理解统计学和数据科学的某些优势,从数据的角度思考,以及简单地像数据科学家一样思考。
在本章中,我们将内容分为以下几个主题:
-
数据开发者角色的目标
-
数据开发者的思维方式
-
数据开发者与数据科学家的区别
-
像数据科学家一样思考的优势
-
向数据科学家思维方式过渡的步骤
那么,让我们开始吧!
数据开发者的思维方式
在担任数据开发者角色多年之后,首先从一些关于数据开发者的简短评论开始是很有道理的。
在一些领域,数据库开发者等同于数据开发者。但无论是数据还是数据库,两者通常都会被标记为信息技术(IT)专业人员。两者都花时间从事或与数据和数据库技术打交道。
我们可能会看到一些数据库(数据)开发者之间的分歧,那些更多关注支持和常规维护(如管理员)的与那些更关注改善、扩展以及开发数据访问的(如开发者)之间的差异。
典型的数据开发者主要参与的是创建和维护对数据的访问,而不是消费这些数据。他或她会参与或做出关于选择编程语言以访问或操作数据的决策。我们会确保新的数据项目符合关于数据库如何存储和处理数据的规则,并且我们将创建数据源之间的接口。
此外,一些数据开发者还会参与审查和调优他人编写的查询,因此,他们必须精通最新的调优技术、各种查询语言,如结构化查询语言(SQL),以及如何存储和结构化所访问的数据。
总结来说,至少从数据开发者的角度来看,重点在于获取有价值的数据资源,而非消费这些有价值的数据资源。
数据开发者的目标
每个角色、职位或工作岗位都有自己的一份目标、责任或计划。
因此,作为数据开发者,可能会承担以下一些责任:
-
维护数据库和基础设施的完整性
-
监控和优化以保持响应水平
-
确保数据资源的质量和完整性
-
为用户群体提供适当的支持
-
强制执行数据资源的安全策略
作为数据科学家,你会注意到一些略有不同的目标。这个角色通常会包括这里列出的一些目标:
-
从不同来源挖掘数据
-
识别模式或趋势
-
创建统计模型——建模
-
学习和评估
-
识别洞察并进行预测
你是否注意到这里开始有一个主题了?
注意以下关键词:
-
维护
-
监控
-
确保
-
提供
-
强制执行
这些术语表达的概念与那些更与数据科学家角色相关的术语有所不同,例如以下这些:
-
挖掘
-
趋势
-
建模
-
学习
-
预测
当然,也有一些活动看起来似乎同时与数据开发人员和数据科学家相关,并将在这里进行探讨。
查询或挖掘
作为数据开发人员,你几乎总是习惯于查询数据。实际上,数据科学家也会查询数据。那么,什么是数据挖掘呢?当人们查询数据时,通常会问一个具体的问题。例如,你可能会问,四月销售了多少水仙花?并期望得到一个已知的、相关的答案,例如四月水仙花总销量为 269 株。
在数据挖掘中,人们通常更专注于数据关系(或者数据点之间的潜在关系,有时称为变量)和认知分析。一个简单的例子可能是:在四月,月平均气温如何影响水仙花的总销量?
数据查询和数据挖掘之间的另一个重要区别在于,查询通常是历史性的,因为它们用于报告过去的结果(例如四月的总销售额),而数据挖掘技术则可以是前瞻性的,通过使用适当的统计方法,它们可以推测未来的结果或提供某个结果或事件发生的概率。例如,使用我们之前的例子,我们可能会预测,当销售区域的平均气温上升时,水仙花的销量会增加。
数据质量或数据清洗
你认为数据开发人员关心数据库中数据的质量吗?当然,数据开发人员需要关心他们支持或提供访问的数据的质量水平。对于数据开发人员而言,组织内的数据质量保证(DQA)过程更具机械性,例如确保数据是最新的、完整的,并且存储在正确的格式中。
通过数据清洗,你可以看到数据科学家更加注重统计数据质量的概念。这包括利用数据中发现的关系来提高数据质量水平。例如,一个九岁的个人不应被错误地标记为美国合法驾驶员群体的一部分。
你可能听说过数据清洗(munging)这个术语。数据清洗有时被定义为将未专门设计为互操作的系统和接口连接在一起的过程。数据清洗还可以定义为将原始数据处理或过滤为另一种形式,以便用于特定的需求或用途。
数据建模
数据开发人员通过与关键利益相关者密切合作,根据给定的需求(如能够快速输入销售交易到组织的在线订单输入系统)来为数据创建设计(或模型)。在模型设计过程中,数据开发人员必须熟悉三种数据模型——概念模型、逻辑模型和物理模型——它们彼此相对独立。
数据科学家创建模型的目的是通过训练数据样本或群体,识别先前未知的洞察或验证当前假设。
数据建模可能变得复杂,因此,通常会看到数据开发与数据建模角色之间的区别。在这些情况下,数据开发人员专注于评估数据本身,创建有意义的报告,而数据模型师则评估如何收集、维护和使用数据。
问题或洞察
数据开发人员可能会花费大量时间监控数据、用户和环境,寻找任何可能导致性能瓶颈或停机的潜在问题的迹象,如意外的使用量水平。其他常见的职责包括审计、应用程序集成、灾难规划与恢复、容量规划、变更管理、数据库软件版本更新、负载均衡等。
数据科学家将他们的时间用于评估和分析数据以及信息,以发现有价值的新洞察。希望一旦建立了洞察,它们可以用来做出更好的商业决策。
有一个相关的概念需要理解;通过使用分析工具,人们可以在数据中识别出模式和趋势,而洞察则是通过使用分析结果获得的价值。
思维过程
某人的心理过程或认知活动,基于解释、过去的经验、推理、问题解决、想象和决策等,构成了他们的思维方式或思维过程。
我们只能猜测某些人实际会怎么想,或者他们在某一特定时刻或活动中会有什么具体想法,或者他们会采用什么样的思维过程来完成目标,但一般来说,数据开发者可能更多地关注数据的便捷性(根据需求使数据可用),而数据科学家则更注重数据的消费(寻找新的方法利用数据以发现现有问题的洞察或新机会)。
为了更清晰地描绘这一点,你可以用汽车修理工和学校辅导员的类比来说明。
一位汽车修理工将利用他的技能和适当的工具,确保汽车能为车主提供使用并保持良好的运行状态,或者如果车辆出现问题,修理工会根据症状进行诊断并修复问题。这与数据开发者的工作非常相似。
对于辅导员来说,他或她可能会审查大量关于学生过去表现、个性特征以及经济统计数据的信息,以确定该学生未来可能存在的机会。此外,辅导员还可能研究多种情境,以预测基于该学生的资源,最佳的结果可能是什么。
显然,上述两类人都提供有价值的服务,但他们使用(可能是非常不同的)不同方法和个人思维过程来产生期望的结果。
尽管存在一定的重叠,当你是数据开发者时,你的思维通常围绕着如何保持对适当数据资源的便捷访问,而不是特别关注数据的本质。也就是说,你可能关心数据类型、数据量和访问路径,但不关心是否存在或存在何种认知关系,或者数据的潜在强大用途。
在下一节中,我们将通过一些简单的情况来展示数据开发者和数据科学家之间的各种对比。
开发者与科学家
为了更好地理解数据开发者和数据科学家之间的差异,让我们花一点时间来考虑一些假设性的(但仍然现实的)情况,这些情况可能会在你的一天中发生。
新数据,新来源
当新的数据或新的数据源可用或被呈现时,会发生什么?
在这里,新的数据通常意味着更多当前的或最新的数据已经可用。一个例子是,每天早上接收到最新的本月销售交易数据文件,这通常被称为实际更新。
在商业世界中,数据可以是真实的(实际的),例如经过认证的销售数据,或在订单处理系统中输入的销售交易数据;也可以是假设的,例如组织预测未来(尚未实际发生的)销售或交易。
你可能会定期收到来自在线交易处理系统的文件,这些文件提供从本月初到当前日期的日销售额或销售数据。你希望你的业务报告能够显示包括最新销售交易在内的总销售数字。
新数据源的概念有所不同。如果我们使用之前提到的类比,其中一个例子可能是来自一个母公司新收购的公司的销售交易文件。另一个例子可能是接收报告近期在线调查结果的数据。这些信息是为了特定目的而收集的,通常并非(但可能是)例行事件。
机器数据(以及其他数据)正在不断积累,即使在你阅读本文时,也在提供新的、有趣的数据源,创造了一个数据消费市场。一个有趣的例子可能是亚马逊网络服务(aws.amazon.com/datasets/
)。在这里,你可以找到大量的公共数据资源,包括1000 基因组计划(旨在建立最全面的人类基因信息数据库)以及 NASA 的地球卫星影像数据库。
在前面的情境中,数据开发人员最有可能(应该)预期更新文件,并且已经实现了提取、转换和加载(ETL)过程来自动处理数据,处理任何异常,并确保所有相关报告反映最新的、正确的信息。数据开发人员还将处理从新收购公司过渡过来的销售文件,但可能不会成为处理调查结果(或1000 基因组计划)的主要资源。
数据科学家并不参与日常数据处理(例如销售数据),但会直接负责调查结果项目。也就是说,数据科学家几乎总是亲自参与诸如研究和获取新信息源等与调查相关的项目。数据科学家很可能会在调查设计阶段提供意见,因为他们是那些将在分析中使用数据的人。
质量问题
假设有关于组织正在消费或即将消费的数据质量的担忧。正如我们在本章前面提到的那样,数据质量问题有多种类型,例如我们所称的机械问题以及统计问题(还有其他问题)。
当前最常见的统计质量问题的趋势例子包括重复条目和拼写错误、误分类和汇总,以及含义的变化。
如果管理层对日常报告中列出的总销售额的有效性产生质疑,或者因为大部分客户在美国法律上不能开车而不信任该数据,或者组织的回头客数量正在下降,那么你就面临了质量问题:
质量对数据开发人员和数据科学家来说都是一个关注点。数据开发人员更关注时间和格式(数据的机制),而数据科学家更关注数据的统计质量(优先考虑可能影响特定研究可靠性的数据问题)。
查询和数据挖掘
历史上,信息技术组或部门经常被各种业务用户请求生成并提供报告,展示数据库和系统中存储的感兴趣的信息。
这些临时报告请求已经发展成了对按需原始数据提取的请求(而不是格式化或漂亮的打印报告),以便业务用户可以将提取的数据导入如 MS Excel(或其他工具)中,在那里他们可以进行自己的格式化和报告,或进行进一步的分析和建模。在今天的世界中,业务用户要求更多的自助服务(甚至是移动端)功能,以满足组织(或个人)的分析和报告需求,期望能够直接或通过更小、更专注的数据池访问更新的原始数据存储。
如果业务应用程序无法提供必要的报告,业务用户通常会继续他们的自助服务之旅。
-Christina Wong (www.datainformed.com)
创建临时报告和根据特定的按需需求进行提取,或者提供自助数据访问,完全由组织的数据开发人员负责。然而,请注意,数据科学家通常会定期执行自己的查询和提取——通常是他们正在进行的项目的一部分。他们可能会使用这些查询结果来确定他们需要的数据的可行性和可用性,或者作为创建特定统计项目的样本或总体过程的一部分。这种查询形式可能被认为是一种数据挖掘方式,比普通查询更深入地探讨数据。这项工作通常由数据科学家而非数据开发人员来完成。
性能
你可以打赌,几乎每个人都在关心,或将来会关心,绩效的话题。某些形式(的绩效)可能更容易量化,例如一个临时查询或数据提取完成的可接受响应时间是多少?或者,输入一个销售订单需要的总鼠标点击或键盘操作数是多少?而其他问题可能会更难回答或解决,例如为什么似乎回头客数量呈下降趋势?
数据开发人员的责任是创建并支持数据设计(甚至参与基础设施配置选项),以确保持续产生快速的响应时间,并且易于理解和使用。
一个可能令人困惑的绩效责任领域是网站性能。例如,如果一个组织的网站表现不佳,是因为某些页面加载缓慢,或内容不吸引人,或与目标受众或客户无关吗?在这个例子中,数据开发人员和数据科学家可能都被指派解决问题。
这些人——数据开发人员——不会参与调查项目。另一方面,数据科学家将不参与日常的交易性(或类似)绩效问题,而是负责与组织的利益相关者合作,定义并领导一个统计项目,旨在回答类似于关于回头客数量的问题。
财务报告
在每个组织中,都需要定期生成财务报表(如损益表、资产负债表或现金流量表)。财务报告(或财务报表)旨在回答关于业务的关键问题,诸如以下问题:
-
我们是在盈利还是亏损?
-
资产与负债相比如何?
-
我们有多少自由现金或需要多少自由现金?
创建、更新和验证定期财务报表的过程是任何规模的企业——无论是营利性还是非营利性——无论是公立还是私营企业,的强制性任务。即使今天,许多组织仍未完全使用自动化报告解决方案。这意味着,即使是更新一份报表并添加最新数据,也可能是一项艰巨的任务。
财务报告是行业内职责相对明确的一个领域。数据开发人员负责创建和支持使数据可用的处理系统,确保数据的正确性,甚至在某些情况下,创建和分发报告。
全球超过 83%的企业使用 MS Excel 进行月末结账和报告 * -venasolutions.com/
*
通常,数据开发人员会提供并维护数据,以支持这些工作。
数据科学家通常不会支持一个组织的常规处理和(财务)报告工作。然而,数据科学家会对所产生的财务信息(及其支持数据)进行分析,制作报告和可视化,展示管理层在盈利能力、效率和风险等方面的洞察(仅举几例)。
统计学和数据科学中一个特别有趣的领域是,当数据科学家执行纵向分析以识别变量与组织财务报表中基本数额之间的关系时。
可视化
今天,生产仪表板格式的可视化已成为常见做法,它可以展示更新后的个别关键绩效指标(KPI)。此外,传达特定的观点或简化大量数据的复杂性并不一定需要使用数据可视化技术,但在某些情况下,今天的世界可能要求这样做。
大多数人可能会同意,扫描大量的工作表、电子表格或报告充其量是单调乏味的,而查看图表和图形(如可视化)通常更容易让眼睛感到舒适。基于这一点,数据开发人员和数据科学家都会参与设计、创建和使用数据可视化。不同之处在于所创建的可视化类型。数据开发人员通常专注于重复数据点的可视化(例如,预测与实际数据的对比),而数据科学家则将可视化用作统计项目中的一个重要环节来表达某个观点。
再次强调,数据开发人员很可能会利用可视化来展示或突出例如销售量的变化,例如按月展示全年数据,而数据科学家则可能会使用可视化来预测明年每月的潜在销售量,考虑到季节性(及其他)统计数据。
行业工具
个人访问和消费数据所使用的工具和技术会因多种因素而有所不同,以下是一些因素:
-
业务类型
-
业务问题(或机会)类型
-
安全性或法律要求
-
硬件和软件兼容性及/或前提条件
-
数据类型和用途
-
用户群体的具体情况
-
企业政策
-
价格
在不断变化的技术环境中,数据开发人员和数据科学家面临着越来越多的选择,甚至可能是压倒性的选择,其中包括非常可行的开源选项。
开源软件是由用户社区为用户开发的。好消息是,开源软件目前在全球大多数(即 78%)企业中得到应用——Vaughan-Nichols,www.zdnet.com/
。开源在数据科学中发挥着日益重要的作用。
当我们谈论工具和技术时,数据开发人员和数据科学家都将同等参与选择最符合他们个人喜好并满足项目或目标需求的正确工具或技术。
像数据科学家一样思考的优势
那么,为什么你作为一个数据开发人员,应该努力像(或更像)数据科学家一样思考呢?理解统计学的方式及其原理有什么意义?具体来说,像数据科学家一样思考可能会带来哪些优势?
以下是支持迈向数据科学努力的几个理念:
-
培养更好的数据理解方法
-
在程序或数据库设计过程中运用统计思维
-
增加个人工具箱
-
增强市场竞争力
-
持续学习
-
看见未来
培养更好的数据理解方法
无论你是数据开发人员、系统分析师、程序员/开发人员、数据科学家,还是其他商业或技术专业人员,你都需要能够与自己所使用或设计应用程序或数据库架构的数据建立全面的关系。
有些人可能依赖于作为整体项目计划或需求一部分提供给你的数据规范,仍然有些人(通常是那些更有经验的人)可能会通过在数据上执行一些常规查询来补充他们的理解,无论哪种方式,这通常都不足够。
事实上,在行业案例研究中,不清晰、误解或不完整的需求或规范经常位列导致项目失败或增加风险的前五名原因。
数据剖析是一个过程,数据科学的特点之一,旨在建立数据亲密关系(或更清晰、简洁地掌握数据及其内部关系)。数据剖析还建立了背景,其中有多个通用的上下文类别,可以用来增加或提升数据的价值和理解,以支持任何目的或项目。
这些类别包括以下内容:
-
定义和解释:这些有助于获得数据点的附加信息或属性
-
比较:这有助于为数据中的某个数据点增加可比性
-
对比:这有助于为数据点增加一个对立面,从而查看它是否可能提供不同的视角
-
趋势:这些是典型的数学计算、汇总或聚合
-
离散度:这包括描述数据集(或数据组)平均值的数学计算(或总结),如范围、方差和标准差。
将数据分析看作是你用来检查数据文件中数据的过程,并收集关于该数据的统计信息和信息。这些统计数据很可能驱动了程序中实现的逻辑,或你如何在数据库的表中关联数据。
在程序或数据库设计过程中使用统计思维
创建数据库设计的过程通常包括多个任务,这些任务将由数据库设计师(或数据开发人员)执行。通常,设计师会执行以下任务:
-
确定哪些数据将保存在数据库中。
-
确立不同数据点之间的关系。
-
创建基于第 1 步和第 2 步的逻辑数据结构。
即使在应用程序设计过程中,彻底了解数据的工作原理也是至关重要的。如果不了解平均值或默认值、数据点之间的关系和分组等,所创建的应用程序很可能会失败。
将统计思维应用于数据设计的一个思路是在数据有限的情况下。如果无法收集足够的数据,可以通过多种抽样方法,如概率抽样,来创建样本(测试)数据。
基于概率的样本是通过构建目标人群值的列表,称为样本框架,然后通过随机化过程从样本框架中选择记录,这一过程称为选择程序。可以把它看作是基于你对实际数据的知识以及一些统计逻辑生成样本数据记录的脚本,用于测试你的设计。
最后,采用科学或统计方法来处理任何问题,成功的概率会更高。
添加到你的个人工具箱中
根据我的经验,大多数数据开发人员倾向于基于多种因素(其中一些在本章前面提到过)固定在某项技术或工具上,逐渐熟悉并(希望)更精通该产品、工具或技术——甚至是不断发布的新版本。人们可能会猜测(而且很可能是对的)开发人员使用工具的时间越长,他们建立的技能水平就会越高。然而,数据科学家似乎更多地专注于方法论、实践或概念,而不是他们用来实现这些方法的实际工具和技术。
这种焦点转移(从工具到技术)改变了一个人的思维方式,使其从“这个工具如何服务我的目标”转变为“哪个工具最能服务我的目标”。
你接触的工具越多,你作为开发者或数据科学家的思维就会变得更加广阔。开源社区提供了出色的工具,供你下载、学习并自由使用。我们应该培养一种“下一个或新事物”的思维方式,即使这种思维只是为了将新工具的特性与功能与自己偏好的工具进行对比。我们将在本章的终身学习部分进一步讨论这一点。
一个目前流行的数据开发者或数据启用工具的激动人心的例子是MarkLogic(www.marklogic.com/
)。这是一款面向企业的操作性和事务性 NoSQL 数据库,旨在整合、存储、管理和搜索比以往更多的数据。MarkLogic 获得了 2017 年 DAVIES 最佳数据开发工具奖。R 和 Python 似乎是数据科学家的首选工具。
如果不提到 IBM Watson Analytics(www.ibm.com/watson/
),这部分就不完整,因为它正在改变行业对统计或认知思维的看法。
增强市场竞争力
数据科学显然是一个不断发展的领域,且受欢迎程度呈指数级增长。事实上,如果你问一打专业人士,你很可能会得到一打关于数据科学家定义的不同回答(以及他们在项目或组织中的角色),但大多数人可能会同意数据科学家的重要性,并且一致认为如今行业内外存在着大量的机会。
数据科学家面临前所未有的需求,需要更多的模型和更多的洞察……只有一个办法可以做到:他们必须大幅加快从洞察到行动的速度。在未来,数据科学家必须变得更加高效。这是他们从数据中获取更多价值的唯一方式。
-Gualtieri www.datanami.com/2015/09/18/the-future-of-data-science/
今天,数据科学家是相对难以找到的。如果你做一些研究,你会发现今天的数据科学家通常具有数学、编程、软件设计、实验设计、工程、沟通以及管理技能等多元化的背景。实际上,你会发现大多数数据科学家并不专注于某一方面,而是具有多个领域或背景的不同程度的熟练度。
数据科学家的角色自 1200 多年前统计学领域诞生以来,已经明确发生了变化。尽管这个术语自本世纪初才出现,但它已经被贴上了“21 世纪最性感的职业”的标签,这也让这一职位的求职者排成了长队。
-Pearson
https://www.linkedin.com/pulse/evolution-data-scientist-chris-pearson
目前,还没有正式的数据科学家职位描述(或者说,没有前提条件列表)。这给了你一个机会,去创造你自己的数据科学家类型,以新的方式为你的组织提供价值。
持续学习
持续评估或持续学习的理念是一个重要的统计学概念。可以将其理解为提升感知技能的常见定义。例如,在统计学中,我们可以提到交叉验证的概念。这是一种统计方法,用于衡量(评估)统计模型的表现。该方法包括确定一组验证值,并通过运行模型若干轮(持续地),使用样本数据集,并平均每轮的结果,最终查看模型(或方法)在解决特定问题或达成目标方面的表现如何。
这里的期望是,基于性能结果,可以做出调整来微调模型,以便在使用实际数据或完整数据集时提供识别洞察的能力。这个概念不仅是数据开发者在优化或微调数据设计或数据驱动的应用流程时应当采用的做法,而且这也是一种很好的生活建议,形式是:尝试、学习、调整并重复。
模型评估的概念并不是统计学独有的。数据开发者可能会认为这类似于预测 SQL 性能的行为,或者类似于应用程序演练的做法,在这种做法中,应用程序会根据其文档化需求中的意图和目的进行验证。
看见未来
预测建模利用数据科学的统计学来预测或预见结果(实际上是一个可能的结果)。这听起来像是在算命,但更重要的是运用认知推理来解读信息(从数据中提取的)并得出结论。就像科学家通常被描述为以系统的方法获取知识或学习一样,数据科学家也可以被视为尝试利用统计学和(机器)学习来做出预测。
当我们谈论预测结果时,实际上是在谈论看到某一结果的概率。概率是用来预测未来事件发生的可能性,而统计学则涉及分析过去事件发生的频率。
如果你是一名数据开发者,可能曾参与过为财务部门提供服务的项目,那么你可能理解为什么企业领导者会认为不仅仅是报告财务结果(即使最准确的结果也仍然是历史事件)是有价值的,还应当能够对未来的表现做出有根据的假设。
也许你可以理解,如果你有金融报告方面的背景并且负责此类工作,那么你现在可以迈出一步,开始为这些报告提供统计预测!
统计建模技术也可以应用于任何类型的未知事件,不论它发生在何时,例如在犯罪侦查和嫌疑人识别的情况下。
转型为数据科学家
让我们从这一部分开始,先花点时间阐明我认为的几条关于转型为数据科学家的普遍接受的事实。我们会在本书接下来的内容中不断重申这些观点:
-
学术背景:数据科学家并不全来自某一特定学术背景。他们并非全是计算机科学或统计学/数学专业毕业的,也并非所有人都拥有高级学位(事实上,你可以通过本科学位甚至更少的学历来使用统计学和数据科学)。
-
这不是基于魔法的:数据科学家可以使用机器学习和其他公认的统计方法从数据中识别洞察,而不是依赖魔法。
-
他们并不全是技术或计算机迷:你不需要多年编程经验或昂贵的统计软件就能有效工作。
-
你不需要有经验就能开始。你可以从今天、从现在就开始。(好吧,当你买了这本书的时候,其实你已经开始了!)
好的,在做了前述声明之后,让我们也保持现实。像往常一样,生活中的一切都有一个切入点,值得称赞的是,你能够开始时获取更多的证书通常会让你更有优势。不过,正如我们在本章后面看到的那样,完全没有合理的理由阻止你立即开始理解、使用并高效地应用数据科学和统计学。
像任何职业一样,证书和学位可能为你打开大门,而经验,像往常一样,可能被认为是最好的老师。然而,世界上没有伪数据科学家,只有那些当前比实际经验更渴望的人。
如果你不仅对理解统计学和数据科学感兴趣,而且最终希望成为一名全职数据科学家,你应该考虑以下常见主题(你很可能会在数据科学家的招聘信息中看到)作为关注的重点:
-
教育:常见的学习领域包括数学和统计学,其次是计算机科学和工程学(也包括经济学和运筹学)。再次强调,这里并没有严格要求必须拥有高级或相关学位。此外,通常,学位或等效经验的概念也适用于此。
-
技术:你会听到提到 SAS 和 R(实际上,你会听到很多关于 R 的内容),以及 Python、Hadoop 和 SQL,它们被认为是数据科学家应该熟悉的关键或首选工具,但工具和技术总是在不断变化,因此,正如本章中多次提到的那样,只要数据开发人员理解数据科学的目标和各种统计方法论,就可以立即开始高效工作,而无需学习新的工具或语言。
基本的商业技能,如 Omniture、Google Analytics、SPSS、Excel 或任何其他 Microsoft Office 工具,在各个地方几乎都是默认要求,并不算优势,但如果你有编程语言(如 Java、PERL 或 C++)或数据库(如 MySQL、NoSQL、Oracle 等)的经验,确实会有帮助!
- 数据:理解数据的能力,以及处理各种类型数据特有的挑战,如非结构化数据、机器生成数据和大数据(包括组织和结构化大型数据集)。
非结构化数据是统计学和数据科学家关注的一个关键领域。它通常被描述为没有为其定义重新定义的模型,或者没有以预定的方式进行组织。非结构化信息通常以文本为主,但也可能包含日期、数字和其他各种事实。
-
求知欲:我很喜欢这个。这或许可以定义为一种性格特征,对于想成为数据科学家的人来说,这是一项有用的(如果不是必要的话)品质。这意味着你持续有想要了解更多信息的需求,而不仅仅停留在基础知识上,或者想要超越某个主题的常识(你不需要在墙上挂一张学位证书!)。
-
商业敏锐度:要成为数据开发者或数据科学家,你需要对你所在行业有深入的理解,还需要知道你的组织需要解决哪些商业问题。在数据科学领域,除了识别新方式让企业利用数据外,能够分辨哪些问题是最重要的也至关重要。
-
沟通技巧:所有公司都在寻找能够清晰流利地将自己的发现传达给非技术团队(如市场或销售部门)的人。作为数据科学家,必须能够通过为企业提供量化的洞察,帮助他们做出决策,并且理解非技术同事的需求,从而增加价值并取得成功。
我们继续前进
那么,让我们以一些轻松的(即便不是常识性的)建议来结束本章,面向那些想学习统计学并过渡到数据科学领域的数据开发者。
以下是一些建议,你应该考虑作为熟悉统计学和数据科学主题的资源:
-
书籍:仍然是学习的最佳方式!你可以从书籍中获得非常实用和详细的信息(包括例子)以及建议。很高兴你从这本书开始,但实际上有大量(而且还在不断增加)等待你去阅读的资源。
-
Google:我非常喜欢做互联网研究。你会惊讶于可以找到的开源软件库、工具、模型、样本数据、白皮书、博客等的数量和质量。很多东西可以直接下载并用来教育自己,甚至作为实际项目或交付物的一部分。
-
LinkedIn:很大比例的企业和独立招聘人员使用社交媒体,其中大多数使用 LinkedIn。这是一个了解哪些职位需求较大,以及他们需要什么样的技能和经验的机会。当你看到一些你不熟悉的职位时,做一些研究来了解该主题。此外,LinkedIn 上有大量专注于统计学和数据科学的群组。加入所有群组!与成员们建立联系——甚至可以直接向他们提问。大多数情况下,社区成员都很乐意帮助你(即使只是展示他们知道多少)。
-
志愿者工作:一个很好的方式来提升技能,继续学习,并扩展你的统计学网络,就是做志愿者。查看 http://www.datakind.org/get-involved。如果你报名成为志愿者,他们会审查你的技能,并保持联系,介绍符合你背景或你感兴趣的项目。
-
实习:有经验的专业人士可以重新报名作为实习生,测试一个新职业或进入一个新行业(www.Wetfeet.com)。虽然这对除了刚毕业的大学生之外的人来说可能不太现实,但如果你能承担减少收入(甚至无薪)一段时间以获得统计学和数据科学的实际经验,实习是可以考虑的。更实际的做法是,在自己的公司内部做数据科学学徒角色的实习,时间可以短一些或针对某个特定项目。
-
副项目:这是我最喜欢的之一。在你的组织内寻找统计学可能正在使用的机会,并要求在空闲时间参加会议或电话。如果这不可能,寻找统计学和数据科学可能解决问题或应对挑战的场景,并将其作为一个业余项目在空闲时间进行。这类项目风险较低,因为没有截止日期,而且如果一开始没有成功,也不算世界末日。
-
数据:帮助你顺利过渡到统计学和数据科学的最简单方法之一,可能就是接触更多种类的数据,尤其是非结构化数据和大数据。此外,探索其他行业或应用的数据也是很有帮助的。
-
Coursera 和 Kaggle:Coursera 是一个在线网站,您可以在该网站上支付费用参加 大规模在线开放课程(MOOCs)并获得证书,而 Kaggle 举办数据科学竞赛,您不仅可以在与其他成员的竞争中评估自己的能力,还可以访问大量的、非结构化的大数据文件,这些文件可能更像您在实际统计项目中使用的文件。
-
多元化:为了增加您分析技能的可信度(因为许多公司每天都在采用各种新工具),例如 R、Python、SAS、Scala(当然还有)SQL 等,如果您花时间学习尽可能多的工具和技术,您将具有显著的优势。除了这些主流的数据科学工具外,您还可以研究一些新兴工具,如 Paxada、MatLab、Trifacta、Google Cloud Prediction API 或 Logical Glue。
-
询问招聘人员:在转型初期花时间与招聘人员建立关系将带来许多好处,信任的招聘人员可以传递目前需求技能的列表以及哪些统计实践最受欢迎。此外,随着您积累经验和信心,招聘人员可以帮助您专注或微调您的经验,向那些可能在远期出现的具体机会发展,这可能会使您在其他候选人中占据优势。
-
在线视频:查看 YouTube 上的网络研讨会和教程视频。无论何时您的时间允许,您都可以观看来自业余爱好者和专业人士的无数资源。
总结
在本章中,我们勾画了数据库(或数据)开发人员如何在日常工作中以解决问题为基础进行思考,比较了数据开发人员和数据科学家的思维方式,并通过各种实际例子进行了说明。
我们还列出了作为数据科学家的思维方式的一些优势,并最终讨论了您在理解统计学并进入数据科学领域时需要关注的常见主题。
在下一章中,我们将介绍并解释(再次从开发者的角度)数据科学统计学背后的基本目标,并向您介绍本书中使用的、带有易于理解的解释和示例的重要术语和关键概念。
第二章:声明目标
本章介绍并解释了(再次从开发者的角度)数据科学统计学的基本目标,并向读者介绍了书中使用的关键术语和概念(带有解释和示例)。
在本章中,我们将内容拆解为以下几个主题:
-
数据科学的关键目标入门
-
将统计学引入数据科学
-
统计学和数据科学中常用的术语
数据科学的关键目标
如第一章中所提到的,从数据开发者到数据科学家的过渡,数据科学如何定义是一个主观问题。
我个人喜欢的解释是,数据科学是思想或步骤的进程,甚至更好的是,它是一个演变过程,如下图所示:
这种数据科学的演变(如前图所示)由一系列步骤或阶段组成,数据科学家在其中跟踪进展,包括以下内容:
-
数据收集
-
数据处理
-
探索和可视化数据
-
数据分析和/或应用机器学习(于数据)
-
基于获得的见解做决策(或规划)
尽管“进展”或“演变”暗示了一个顺序性的旅程,但在实践中,这是一个非常流动的过程;每个阶段都可能激发数据科学家反向并重复一个或多个阶段,直到他们感到满意。换句话说,过程中的所有或部分阶段可能会被重复,直到数据科学家认为已达成期望的结果。
例如,在仔细审查生成的可视化图表后(在探索和可视化数据阶段),可能会发现需要对数据进行额外处理,或者在进行任何合理的分析或学习之前,需要收集更多的数据。
你可以大致将数据科学过程与敏捷软件开发方法论进行比较,在这种方法中,开发者执行各种任务,分析结果,继续工作,重新审视工作,直到获得期望的结果或成果。
让我们解释数据科学演变的每一个阶段。
数据收集
这一点应该是显而易见的——没有(至少一些)数据,我们无法执行任何后续步骤(尽管有人可能会争论推断问题,但那是不合适的。数据科学中没有魔法。我们,作为数据科学家,不是从任何东西中创造出东西。推断(我们将在本章稍后定义)至少需要一些数据作为起点。
收集数据的一些新概念包括数据可以来自各种来源,数据源的数量和类型每天都在增长。此外,数据的收集方式可能需要数据开发者一种全新的视角;数据科学中的数据并不总是来自关系型数据库,而是来自机器生成的日志文件、在线调查、性能统计等;再次强调,这个列表仍在不断发展。
另一个值得思考的点是,收集数据也涉及补充。例如,数据科学家可能会发现需要为先前收集、处理和审核过的特定应用数据池添加额外的群体统计数据。
处理数据
数据的处理(或转换)是数据科学家编程技能发挥作用的地方(尽管你通常可以看到数据科学家在其他步骤中执行某种形式的处理,例如收集、可视化或学习)。
请记住,数据科学中涉及的处理方面有很多。最常见的包括格式化(和重新格式化),其涉及的活动如机械地设置数据类型、汇总值、重新排序或删除列等;数据清理(或处理数据质量),解决诸如默认值或缺失值、不完整或不合适的值等问题;以及数据分析,生成统计性的数据理解,为数据提供背景信息。
对数据进行的处理可以是简单的(例如,可能是一个非常简单且手动的事件,需要对 MS Excel 工作表中的数据进行重复更新),也可以是复杂的(如使用 R 或 Python 等编程语言),甚至更复杂(例如,当处理逻辑被编写到程序中时,这些程序可以被调度,并在新的数据群体上自动重新运行)。
探索与可视化数据
在整体数据科学流程的这一阶段或步骤中,数据科学家将使用各种方法深入挖掘数据。通常,会创建几个图形化的表示(再次强调,这些可能是手动完成的,也可能是通过编程脚本或工具生成的),以强调或验证数据科学家的观察、某个特定的观点或信念。这是数据科学流程中的一个重要步骤,因为数据科学家可能会意识到数据需要进一步处理,或者需要收集更多的数据,亦或是原始理论似乎得到了验证。这些发现将促使数据科学家停下来,反思接下来的步骤。数据科学家是否应该继续正式的分析过程,或许是创建一个自动化学习的预测模型?还是应该回到之前的步骤,收集更多(或不同的)数据进行处理?
数据可视化是一项关键技术,它使数据科学家能够快速执行分析,识别关键趋势或事件,并做出更有信心的决策。
分析数据和/或将机器学习应用于数据
在这一阶段,数据科学家(受到强烈的科学好奇心和经验驱动)会进行大量分析,试图基于观察或对数据理解的解释,构建一个故事。数据科学家继续切分和分析数据,使用分析或商业智能工具(如 Tableau、Pentaho,或者使用开源解决方案如 R 或 Python),创建具体的数据故事线。再次根据这些分析结果,数据科学家可能会选择返回到先前的阶段,提取新数据,进行处理和再处理,并创建额外的可视化效果。到了某个阶段,当进展适当时,数据科学家可能会决定开始数据分析。机器学习(将在本章后续详细定义)随着时间的推移,已从最初的模式识别演变为现在使用选定的统计方法深入挖掘,利用数据及本阶段分析的结果进行学习并做出预测。
数据科学家通过机器学习从数据中提取定量结果,并将其以每个人(不仅仅是其他数据科学家)能够立即理解的方式表达出来,这是一个宝贵的技能,我们将在本书中进一步探讨这一点。
基于获得的洞察做决策(或规划)
在此步骤中,数据科学家希望通过努力获得价值,并以洞察的形式呈现出来。通过执行之前描述的阶段,获得对特定情况或现象的理解,从而得到这个洞察。这个洞察随后可以作为输入,用于做出更好的决策。
一个有趣的例子,展示了从数据中挖掘洞察并创造性使用的过程,就是由 IBM Watson 支持的(截至本文撰写时,仍为实验性)Roztayger 人格匹配过程。使用你的 Facebook 或 Twitter 动态(或者你也可以输入简短的个人简介),Watson 会即时对你的个性进行分析。结果既有趣又非常精准,这些洞察随后被用来推荐最适合你及你个人风格的设计师品牌。
你可以在roztayger.com/match
找到这个功能。个性洞察服务根据一个人的写作方式提取个性特征。你可以使用该服务将个体与其他个体、机会和产品进行匹配,或通过个性化信息和推荐来定制他们的体验。特征包括大五人格特质、价值观和需求。建议使用至少 1,200 个字的输入文本。
一旦(实时)数据科学分析完成,前述网站不仅提供建议,还分享其洞察背后的数据,以易于理解、条理清晰的表格视图展示结果,同时也提供引人注目的可视化效果,如下图所示:
这展示了数据科学进展阶段的另一个关键方面,也就是,一旦数据科学家识别出某个洞察,他们必须清晰地展示和传达这些数据洞察/发现。
像数据科学家一样思考
正如我们之前强调的,数据科学家的定义和职责的共识仍在逐步形成。数据科学领域的整体定义至多是粗略的。转型为数据科学家的过程,也许更像是寻找一个与自己技能匹配的组织或团队,而不仅仅是理解数据科学所涉及的技能和概念,并朝着这些技能努力。
就像数据开发人员保持对数据操作和访问趋势及工具的了解一样,未来的数据科学家也应该如此。
将统计学引入数据科学
根据你的来源和个人信念,你可能会说以下内容:
统计学就是数据科学,数据科学就是统计学。
为了澄清这一点,请注意有一种流行的观点认为,统计学可以被视为一个涵盖数据收集、分析、解释、展示和组织的研究或过程。正如你所看到的,这一定义与我们在本章上一节中描述的数据科学过程非常相似。
深入探讨这个话题,我们会发现统计学总是涉及(或包含)一些技术或方法,用于帮助分析和展示数据(同样,这种理解也可以用来描述数据科学)。
在一些圈子里,人们普遍认为数据科学和统计学是同义词。当然,数据科学家之间对术语和概念的统一仍在不断演进。
常见术语
根据个人经验、研究以及各行各业专家的建议,深入学习数据科学的人应该抓住每一个机会,理解并积累以下常见数据科学术语的经验和熟练度:
-
统计学总体
-
概率
-
假阳性
-
统计推断
-
回归
-
拟合
-
分类数据
-
分类
-
聚类
-
统计比较
-
编码
-
分布
-
数据挖掘
-
决策树
-
机器学习
-
数据清洗和整理
-
可视化
-
D3
-
正则化
-
评估
-
交叉验证
-
神经网络
-
提升
-
提升率
-
众数
-
异常值
-
预测建模
-
大数据
-
置信区间
-
写作
统计总体
你或许可以将统计总体看作一个记录集(或一组记录)。这组记录将包含一些类似的项目或事件,数据科学家对此感兴趣,用于某些实验。
对于数据开发人员来说,数据总体可能是某个月份的所有销售交易记录,而关注点可能是向公司高层报告哪些产品是最快的畅销产品,以及在一年中的哪个时间段。
对于数据科学家来说,总体可能是某个月所有急诊室入院的记录,而关注点可能是确定急诊室使用的统计人口特征。
通常,统计总体和统计模型这两个术语可以互换使用。再次强调,数据科学家们在使用这些常用术语时不断发展和统一。
另一个关于统计总体的关键点是,记录集可能是一个(实际上)存在的对象组,或者是一个假设的对象组。以之前的例子为例,实际对象可以是该月记录的实际销售交易,而假设对象则是预计、预测或假定(基于观察或经验假设或其他逻辑)将在一个月内发生的销售交易。
最后,通过使用统计推断(将在本章后面解释),数据科学家可以选择记录集(或总体)的一部分或子集,目的是使其代表某一特定领域的总总体。这个子集被称为统计样本。
如果准确地选择了一个总体样本,可以根据样本的相应特征估算整个总体(该样本所来自的总体)的特征。
概率
概率关注的是支配随机事件的法则。
-www.britannica.com
在思考概率时,你会想到可能发生的事件以及它们实际上发生的可能性。这与统计思维过程相比较,后者涉及分析过去事件的频率,以试图解释或理解观察到的现象。此外,数据科学家还会关联各种个体事件,研究这些事件之间的关系。这些不同事件之间的关系决定了我们在研究它们的概率时需要遵循的方法和规则。
概率分布是一个表格,用于显示样本总体或记录集中的各种结果的概率。
假阳性
假阳性的概念是一个非常重要的统计学(数据科学)概念。假阳性是一个错误或失误的结果。也就是说,这是一个场景,其中过程或实验的结果表明条件已满足或为真,但实际上该条件并不成立(未满足)。这种情况也被一些数据科学家称为假警报,最容易理解的是考虑记录集或统计总体的概念(我们在本节前面讨论过),它不仅由处理的准确性决定,还由所抽取样本总体的特征决定。换句话说,数据科学家在统计过程中犯了错误,或者记录集是一个没有适当样本(或特征)的总体,无法满足正在研究的条件。
统计推断
哪个开发者在职业生涯中某个时刻没有创建过样本或测试数据?例如,我常常会创建一个简单的脚本来生成一个随机数(基于可能的选项或选择的数量),然后将这个数字作为选中的选项(在我的测试记录集中)。这在数据开发中可能运作得很好,但在统计学和数据科学中,这是不够的。
为了创建样本数据(或样本总体),数据科学家将使用一个叫做统计推断的过程,这个过程通过分析你拥有或尝试生成的数据来推断潜在分布的选项。这个过程有时也称为推断统计分析,包括测试各种假设并得出估计值。
当数据科学家确定记录集(或总体)应比实际更大时,假设该记录集是来自更大总体的样本,数据科学家会利用统计推断来弥补差距。
正在使用的数据或记录集被数据科学家称为观测数据。推断统计学可以与描述性统计学进行对比,后者仅关注观测数据的属性,并不假设记录集来自更大的总体。
回归
回归是一个过程或方法(由数据科学家根据当前实验的需要选定为最佳拟合技术),用于确定变量之间的关系。如果你是程序员,你对变量有一定的理解,但在统计学中,我们对这个术语的使用有所不同。变量被判定为依赖变量或独立变量。
独立变量(也称为预测变量)是数据科学家操控的变量,目的是确定它与依赖变量的关系。依赖变量是数据科学家正在测量的变量。
在数据科学的进程或实验中,出现多个自变量并不罕见。
更准确地说,回归是一个帮助数据科学家理解当一个或多个自变量变化时,而其他自变量保持固定时,因变量(或标准变量)的典型值如何变化的过程。
拟合
拟合是衡量统计模型或过程如何描述数据科学家关于记录集或实验的观察结果的过程。这些度量将试图指出观察值和可能值之间的差异。模型或过程的可能值称为分布或概率分布。
因此,概率分布拟合(或分布拟合)是指数据科学家将概率分布拟合到关于变量现象重复测量的一系列数据上。
数据科学家进行分布拟合的目标是预测某一现象在特定时间间隔内发生的概率或预测其发生频率。
拟合的一个常见用途是测试两个样本是否来自相同的分布。
数据科学家可以选择的概率分布有很多种。一些分布比其他分布更适合观察到的数据频率。拟合得较好的分布应该能做出好的预测;因此,数据科学家需要选择适合数据的分布。
分类数据
之前,我们解释了数据中的变量可以是自变量或因变量。另一种变量定义是分类变量。这种变量是指可以取有限且通常固定的可能值之一,从而将每个个体分配到特定类别。
经常情况下,收集到的数据含义不明确。分类数据是数据科学家可以用来为数据赋予含义的一种方法。
例如,如果收集了一个数值变量(假设发现的值为 4、10 和 12),如果这些值被分类,变量的含义就会变得清晰。假设根据对数据收集方式的分析,我们可以通过指明这些数据描述的是大学生,并且以下是运动员的数量:
-
4 名网球运动员
-
10 名足球运动员
-
12 名足球运动员
现在,因为我们将数据分组为类别,含义变得清晰。
其他一些分类数据的例子可能是个人宠物偏好(按宠物类型分组),或汽车拥有情况(按所拥有的汽车类型分组)等等。
因此,分类数据,顾名思义,是将数据分组到某种类别或多个类别中。一些数据科学家将类别称为数据的子人群。
分类数据也可以是收集的是“是”或“否”的答案。例如,医院接纳数据可能表明患者是否吸烟。
分类
数据的统计分类是识别数据点、观测值或变量应归入哪个类别(在前一部分讨论过)的过程。执行分类过程的数据科学过程被称为分类器。
判断一本书是小说还是非小说是一个简单的分类例子。对餐馆数据的分析可能会将它们分类为多个类型。
聚类
聚类是将数据出现的实例划分为组或同质子集的过程,不同于分类(如前一部分所述)中预设的组,而是通过执行数据科学过程,基于它在实例中发现的相似性来识别的组。
位于同一组中的对象(该组也称为簇)被发现比与其他组中的对象(或其他簇中的对象)相比更为相似(在某种程度上)。聚类过程在探索性数据挖掘中非常常见,也是统计数据分析中的常用技术。
统计比较
简而言之,当你听到统计比较这个术语时,通常指的是数据科学家执行分析过程,以查看两个或多个组或种群(或记录集)之间的相似性或差异。
作为数据开发人员,可能熟悉各种工具,如 FC Compare、UltraCompare 或 WinDiff,它们旨在为开发人员提供两个或更多文件(甚至二进制文件)内容的逐行比较。
在统计学(数据科学)中,这一比较过程是一种统计技术,用于比较种群或记录集。在这种方法中,数据科学家将执行所谓的方差分析(ANOVA),比较分类变量(在记录集内)等。
ANOVA 是一种统计方法,用于分析组均值之间的差异及其相关过程(例如组间、组内或记录集之间的变异)。该方法最终演变为六西格玛数据集比较。
编码
编码或统计编码是数据科学家在准备数据进行分析时使用的过程。在这个过程中,定量数据值(如收入或教育年限)和定性数据(如种族或性别)都以一致的方式进行分类或编码。
数据科学家进行编码的原因有多种,具体如下:
-
更有效地运行统计模型
-
计算机理解变量
-
责任制——使数据科学家能够盲目地运行模型,或者在不知晓变量代表什么的情况下运行,以减少编程/作者偏见。
你可以将编码过程视为将数据转化为系统或应用所需形式的手段。
分布
统计记录集(或人口)的分布是一个可视化,展示数据的所有可能值(或有时称为区间)及其发生频率。当数据科学家创建分类数据的分布(我们在本章前面定义过的分类数据)时,试图展示每个组或类别中的个体数量或百分比。
将之前定义的术语与此术语“概率分布”联系起来,简单来说,概率分布可以被看作是一个可视化图,展示在实验中不同可能结果发生的概率。
数据挖掘
在第一章《从数据开发者到数据科学家》中,我们提到,数据挖掘通常更专注于数据关系(或数据点之间的潜在关系,有时称为变量)和认知分析。
为了进一步定义这一术语,我们可以提到,数据挖掘有时更简单地被称为知识发现,甚至仅称为发现,基于从新的或不同的视角处理或分析数据,并将其总结为可用于增加收入、削减成本或两者兼得的有价值的见解。
使用专门的用于数据挖掘的软件只是数据挖掘几种分析方法之一。尽管有专门的工具(如 IBM Cognos BI 和 Planning Analytics、Tableau、SAS 等),数据挖掘的核心是通过分析过程发现数据中的字段之间的相关性或模式,这可以通过 MS Excel 或其他许多开源技术有效完成。
数据挖掘的一种常见技术是通过使用如 R 或 Python 之类的工具创建自定义脚本。通过这种方式,数据科学家能够根据项目的具体需求定制逻辑和处理过程。
决策树
统计决策树使用一种看起来像树的图示结构。这种结构试图表示可选的决策路径以及每个选定路径的预测结果。数据科学家将使用决策树来支持、跟踪和建模决策制定及其可能的后果,包括偶然事件结果、资源成本和效用。这是一种常见的数据科学过程逻辑展示方式。
机器学习
机器学习是数据科学中最具吸引力和令人兴奋的领域之一。它唤起了与人工智能相关的各种形象,包括神经网络、支持向量机(SVM)等。
从根本上说,我们可以将机器学习这一术语描述为一种训练计算机的方法,通过数据或更具体地说,数据中的关系来做出或改善预测或行为。继续来说,机器学习是一个基于在数据中识别到的模式进行预测的过程,并且它具有从数据模式中持续学习的能力,因此能够不断做出更好的预测。
有人将机器学习的过程误认为数据挖掘并不罕见,但数据挖掘更多地侧重于探索性数据分析,并被称为无监督学习。
机器学习可以用来学习并建立各种实体的基线行为特征,然后寻找有意义的异常情况。
这里是激动人心的部分:机器学习的过程(使用数据关系做出预测)被称为预测分析。
预测分析使数据科学家能够通过从历史关系和数据中的趋势中学习,做出可靠的、可重复的决策和结果,并揭示隐藏的见解。
数据清洗和整理
数据清洗和数据整理这两个术语是时髦词或行话,旨在描述某人在某种程度上对数据、记录集或文件格式进行调整的努力,以便为后续的处理和/或评估做准备。
在数据开发中,您很可能已经熟悉了提取、转换和加载(ETL)的概念。在某种程度上,数据开发人员可能会在 ETL 过程中的转换步骤中对数据进行清洗或整理。
常见的数据清洗和整理可能包括去除标点符号或 HTML 标签、数据解析、过滤、各种转换、映射,以及将不专门设计为互操作的系统和接口结合起来。数据清洗还可以描述将原始数据处理或过滤成另一种形式,以便在其他地方更方便地使用。
数据清洗和整理可能在数据科学过程中多次执行,或者在不断发展的过程中不同的步骤中进行。有时,数据科学家使用数据清洗来包括各种数据可视化、数据聚合、训练统计模型以及其他许多潜在的工作。至此,数据清洗和整理可能遵循一个流程,从提取原始数据开始,使用各种逻辑进行数据清洗,最后将结果内容放入结构中以供使用。
虽然有许多有效的选项可以进行数据清洗和整理、预处理和操作,但目前许多数据科学家喜爱的工具是名为Trifecta的产品,它声称是许多行业中排名第一的数据整理解决方案。
Trifecta可以从www.trifacta.com/
下载进行个人评估。去看看吧!
可视化
使用数据可视化技术的主要目的是让复杂的内容看起来简单(尽管还有其他目标)。你可以把可视化看作是任何一种创建图形(或类似的方式)以传达信息的技术。
使用数据可视化的其他动机包括以下几点:
-
解释数据或将数据置于上下文中(即突出显示人口统计统计信息)
-
解决特定问题(例如,识别特定商业模型中的问题领域)
-
探索数据以更好地理解或增加清晰度(例如,这些数据跨越了哪些时间段?)
-
突出或说明那些无法直接看见的数据(例如,隔离数据中的异常值)
-
进行预测,例如潜在的销售量(可能基于季节性销售统计数据)
-
以及其他
统计可视化几乎应用于数据科学过程中的每一个步骤,包括显而易见的步骤如探索和可视化、分析和学习,但也可以在收集、处理以及使用识别出的洞察力的最终阶段发挥作用。
D3
D3 或D3.js
本质上是一个开源的 JavaScript 库,旨在使用现代网络标准可视化数据。D3 通过使用可缩放矢量图形(SVG)、Canvas 和标准 HTML 来帮助赋予数据生命。
D3 结合了强大的可视化和交互技术,并采用基于数据的 DOM 操作方法,为数据科学家提供了现代浏览器的全部功能,并且有自由设计出最佳视觉界面的能力,以最准确地展现目标或假设。
与许多其他库不同,D3.js
允许对数据可视化进行极高的控制。D3 嵌入在 HTML 网页中,并使用预构建的 JavaScript 函数选择元素、创建 SVG 对象、设置样式、或添加过渡、动态效果等。
正则化
正则化是数据科学家用来改善统计模型或数据科学过程生成的结果的一种可能方法,尤其是在处理统计学和数据科学中的过拟合问题时。
我们在本章之前定义了拟合(拟合描述了统计模型或过程如何很好地描述数据科学家对观察结果的解释)。过拟合是一种情况,在这种情况下,统计模型或过程似乎拟合得过于完美,或者看起来与实际数据过于接近。
过拟合通常发生在一个过于简单的模型中。这意味着你可能只有两个变量,并且根据这两个变量得出结论。例如,使用我们之前提到的水仙花销售的例子,可能会生成一个以温度为自变量,以销售为因变量的模型。你可能会看到该模型失败,因为简单地得出温暖的天气总是带来更多的销售并不成立。
在这个例子中,通常会通过向过程或模型中添加更多数据来希望获得更好的结果。这个想法听起来是合理的。例如,你有一些信息,如平均降水量、花粉计数、化肥销售量等;这些数据点可以作为解释变量添加进来吗?
解释变量是一种独立变量,但有着微妙的区别。当一个变量是独立的时,它完全不受任何其他变量的影响。当一个变量不完全独立时,它就是一个解释变量。
继续向模型中添加更多数据会产生一定效果,但可能会导致过拟合,导致预测结果不准确,因为它会与数据高度相似,而这些数据大多只是背景噪声。
为了克服这种情况,数据科学家可以使用正则化,引入一个调节参数(附加因素,如数据点的均值或最小/最大限制,使你能够改变模型的复杂度或平滑度),以解决不适定问题或防止过拟合。
评估
当数据科学家评估一个模型或数据科学过程的性能时,这被称为评估。性能可以通过多种方式定义,包括模型学习的增长,或模型通过额外经验(例如更多轮训练以及更多数据样本)来改进学习的能力(以获得更好的分数),或结果的准确性。
评估模型或过程性能的一个流行方法被称为自助法抽样。这种方法通过反复生成结果,来检查在特定数据子集上的表现,这些结果可以用来计算准确度(性能)的估算值。
自助法抽样方法(bootstrap sampling)从数据中随机抽取样本,将其分成三个文件——训练文件、测试文件和验证文件。模型或过程逻辑是基于训练文件中的数据开发的,然后使用测试文件进行评估(或测试)。这个“调优然后测试”的过程会重复进行,直到数据科学家对测试结果感到满意。到那时,模型或过程会再次进行测试,这次使用的是验证文件,结果应该能真实反映其表现如何。
你可以想象使用自助法抽样
方法通过分析测试数据来开发程序逻辑,确定逻辑流程,然后将你的逻辑与测试数据文件进行对比测试。一旦你确信你的逻辑处理了测试数据中的所有条件和异常,你可以对一个新的、未曾见过的数据文件进行最终验证测试。
交叉验证
交叉验证是一种评估数据科学过程性能的方法。主要用于预测建模,以估计模型在实际中的表现准确性,交叉验证通常用于检查模型如何潜在地进行泛化,换句话说,就是模型如何将从样本中推断出的信息应用到整个群体(或记录集)上。
在交叉验证中,你需要确定一个(已知的)数据集作为验证数据集,在这个数据集上进行训练,并使用一个未知数据集(或首次出现的数据)对模型进行测试(这就是你的测试数据集)。其目的是确保诸如过拟合(允许不完全的信息影响结果)等问题得到控制,同时提供有关模型如何在实际问题或实际数据文件上进行泛化的洞察。
交叉验证过程将包括将数据划分为相似子集的样本,对一个子集(称为训练集)进行分析,并在另一个子集(称为验证集或测试集)上验证分析结果。为了减少变异性,交叉验证会进行多次迭代(也称为折叠或轮次),使用不同的划分方式,验证结果会在多个轮次中求平均。通常,数据科学家会利用模型的稳定性来确定应执行多少轮交叉验证。
神经网络
神经网络也被称为人工神经网络(ANNs),其目标是以与人类大脑相同的方式解决问题。
Google 将在《神经网络入门:第一部分,Maureen Caudill,AI 专家,1989 年 2 月》中提供以下关于 ANN 的解释:
一个计算系统由多个简单且高度互联的处理元素组成,这些处理元素通过对外部输入的动态状态响应来处理信息。
为了简化神经网络的概念,可以回想一下软件封装的概念,考虑一个包含输入层、处理层和输出层的计算机程序。理解这一点后,你会明白,神经网络也组织成这些层的网络,通常不止一个处理层。
模式通过输入层呈现给网络,随后传递给一个或多个处理层(实际处理发生的地方)。处理层再与输出层相连接,结果在此呈现。
大多数神经网络还会包含某种形式的学习规则,通过该规则根据所呈现的输入模式修改连接的权重(换句话说,网络会学习哪些处理节点表现更好,并给予其更大的权重)。通过这种方式(从某种意义上说),神经网络像孩子通过接触猫的例子来学习识别猫一样,通过示例进行学习。
提升法
可以说,提升是数据科学中普遍接受的一种过程,用于提高弱学习数据科学过程的准确性。
被定义为弱学习者的数据科学过程是指那些产生的结果仅比随机猜测的结果略好。弱学习者基本上是阈值或单层决策树。
具体来说,提升的目标是在监督学习中减少偏差和方差。
我们所说的偏差和方差是什么意思?在进一步讨论提升之前,让我们先了解一下偏差和方差的含义。
数据科学家将偏差描述为在数据收集过程中存在的一种偏爱程度,导致结果不均衡、不真实,并且可能以多种不同的方式发生。如果一个采样
方法系统地偏向某些结果而非其他结果,则称该方法为有偏的。
方差可以简单地定义为一个变量均值的距离(或者结果距离平均值的远近)。
提升方法可以描述为数据科学家反复执行数据科学过程(该过程已被确定为弱学习过程),每次迭代都使用从原始总体记录集随机抽取的不同数据样本。每次运行产生的所有结果(或分类器或残差)随后会被合并为一个单一的合并结果(即梯度)。
每次迭代使用原始记录集的随机子集这一概念,源自于袋装法中的自助采样,并对合并模型具有类似的方差降低效果。
此外,一些数据科学家认为提升是将弱学习者转化为强学习者的一种方式;事实上,对于某些人来说,提升过程仅仅意味着将弱学习者转化为强学习者。
提升
在数据科学中,"提升"(lift)一词用于比较记录集或总体中观察到的模式的频率与通过随机或偶然方式在数据中出现该模式的预期频率。
如果提升值非常低,那么通常,数据科学家会认为识别出的模式很可能只是偶然发生的。提升值越大,模式越有可能是真实的。
众数
在统计学和数据科学中,当数据科学家使用“众数”一词时,他或她指的是在数据样本中出现频率最高的值。众数不是通过计算得到的,而是通过手动确定或通过处理数据来确定的。
异常值
异常值可以定义如下:
-
与其他数据点差异极大的数据点
-
那些不符合其他数据点的异常数据
-
一个非常高的值或非常低的值
-
数据中的异常观察
-
与其他所有数据点相距较远的观察点
预测建模
统计模型和/或数据科学过程的发展,旨在预测未来事件,称为预测建模。
大数据
再次提到,我们对于大数据的定义有所不同。大数据通常被定义为数据量庞大或复杂,以至于传统的数据处理应用无法胜任,并且涉及我们生活的各个方面。2001 年,时任 Gartner 分析师的 Doug Laney 提出了 3V 概念。
根据 Laney 的定义,3V 是体积、种类和速度。3V 构成了大数据的维度:体积(或数据的可衡量数量)、种类(即数据的类型数量)和速度(指处理或处理数据的速度)。
置信区间
置信区间是数据科学家在估算值周围指定的一系列值,用于表示他们的误差范围,并结合一个概率,表示某个值落入该范围的可能性。换句话说,置信区间是对未知总体参数的良好估计。
写作
尽管在展示数据科学过程或预测模型的输出或结果时,可视化通常更为引人注目,但写作技巧仍然是数据科学家交流的重要部分,而且仍然被认为是所有数据科学家成功的关键技能。
总结
在这一章中,我们提到,当前数据科学的定义是一个意见问题。一个实际的解释是,数据科学是思想的一种进展,甚至更好地说,是一种演变,包括收集、处理、探索和可视化数据,分析(数据)和/或应用机器学习(到数据中),然后基于获得的洞察做出决策(或规划)。
接着,为了让你像数据科学家一样思考,我们介绍并定义了一些数据科学家应该熟悉的常见术语和概念。
在下一章中,我们将介绍并解释数据开发人员如何使用几种常见的统计方法理解和处理数据清洗的主题。
第三章:开发人员如何处理数据清理
本章讨论了开发人员如何运用几种常见的统计方法理解并处理数据清理这一话题。
本章我们将内容分为以下几个话题:
-
理解基础数据清理
-
使用 R 检测和诊断常见的数据问题,例如缺失值、特殊值、离群值、不一致性和本地化问题
-
使用 R 解决高级统计问题,例如数据转换、推导修正和确定性填补
理解基础数据清理
在任何统计项目中,拥有干净(因此可靠)的数据至关重要。脏数据,即使在正确的统计实践下,也可能是不可靠的,可能导致得出错误的行动建议,甚至可能造成伤害或经济损失。曾有人指出,数据科学家几乎 90%的时间都花在清理数据上,只有 10%的时间用于实际建模和从数据中得出结果。
那么,数据清理到底是什么呢?
数据清理也称为数据清洗或数据去污,涉及到检测和解决数据集中的错误、遗漏和不一致性问题。
这可以通过数据整理工具进行交互式处理,或者通过脚本批量处理。本书将使用 R 语言,因为它非常适合数据科学,能够处理非常复杂的数据集,支持通过各种建模功能对数据进行处理,甚至可以通过几行代码生成可视化数据,来证明理论和假设。
在清理过程中,首先使用逻辑来检查和评估数据池,以建立数据的质量水平。数据质量的高低可以受到数据录入、存储和管理方式的影响。清理过程可能涉及纠正、替换或直接删除数据点或整个实际记录。
清理过程不应与验证过程混淆,它们是不同的。验证过程通常在数据捕获时(即录入时)进行,是一个通过或不通过的过程,而不是在数据处理后,为某个特定目的进行的操作。
作为数据开发人员,不应对数据清理的概念或提升数据质量的重要性感到陌生。数据开发人员还会同意,数据质量的处理过程需要定期的常规评审和评估,实际上,大多数组织都有企业级工具和/或流程(或者至少有相关政策)来定期预处理和清理企业数据。
如果你感兴趣的话,市面上有许多免费的和付费的工具可以尝试,包括 iManageData、Data Manager、DataPreparator(Trifecta)Wrangler 等。从统计学的角度来看,最受欢迎的选择包括 R、Python 和 Julia。
在你处理数据中的具体问题之前,你需要先检测到它们。检测这些问题要求你根据目标的背景,确定什么可以被视为问题或错误(后面这一节会有更多的内容)。
常见的数据问题
我们可以将数据难题分为几个组。最普遍接受的(数据问题)分类包括:
-
准确性:数据不准确有很多种类型,最常见的例子包括数学错误、超出范围的值、无效值、重复等。
-
完整性:数据源可能会缺少某些列的值,缺少整列数据,甚至缺少完整的交易。
-
更新状态:作为质量保证的一部分,你需要建立数据刷新或更新的节奏,并且能够判断数据最后一次保存或更新的时间。这也被称为延迟。
-
相关性:这涉及识别并消除在特定目标下不需要或不相关的信息。例如,如果你的研究目标是个人护理产品,那么去除关于腌黄瓜的销售交易就是一个例子。
-
一致性:通常需要交叉参考或转换数据源中的信息。例如,记录的病人调查反馈可能需要转换为一个一致的指标,以便以后简化处理或可视化。
-
可靠性:这主要关注确保数据收集方法能产生一致的结果。常见的数据保障流程包括建立基准线和范围,然后定期验证数据结果是否符合预期。例如,通常有混合的注册民主党和共和党选民的地区,如果数据突然变为 100%的单一党派,就需要进行调查。
-
适用性:当数据适合预定的用途时,就被认为是合适的;这可能是主观的。例如,假设假期交通影响了购买习惯(美国国旗在阵亡将士纪念日一周的销售量增加并不表示这是一个平均或预期的每周行为)。
-
可访问性:有趣的数据可能会被大量无关数据所淹没,从而降低了有趣数据的质量,因为它变得难以访问。这在大数据项目中尤其常见。此外,安全性也可能影响数据的质量。例如,某些计算机可能会被排除在捕获的日志文件之外,或某些与健康相关的信息可能被隐藏,未包含在共享的病人数据中。
上下文数据问题
很多前面提到的数据问题可以被自动检测到,甚至可以被修正。这些问题最初可能是由用户输入错误、传输或存储过程中的损坏,或者由不同数据源中相似实体的不同定义或理解所引起的。在数据科学中,还有更多需要考虑的事项。
在数据清洗过程中,数据科学家会尝试根据对数据背景及其预期用途的假设或假定,识别数据中的模式。换句话说,任何数据科学家认为明显与数据假设或目标无关,或明显不准确的数据都会被处理。这个过程依赖于数据科学家的判断力以及他或她确定哪些数据点有效,哪些无效的能力。
依赖人类判断时,总有可能忽视或错误处理那些没有充分考虑在数据科学家假设/假定中的有效数据点。因此,保持适当标签的清洗数据版本是一种常见的做法。
清洗技术
通常,数据清洗过程围绕识别那些异常数据点展开,或者识别那些由于不符合数据科学家所看到或感兴趣的数据模式而显得突出的数据点。
数据科学家使用各种方法或技术来识别数据中的异常值。一种方法是绘制数据点图,然后通过视觉检查结果图,找出那些远离整体分布的数据点。另一种技术是通过编程方式删除所有不符合数据科学家数学控制限制的数据点(这些限制基于统计项目的目标或意图)。
其他数据清洗技术包括:
-
有效性检查:有效性检查涉及应用规则来判断数据是否有效。这些规则可以是全局性的;例如,如果数据池中包含特定唯一键(例如社会安全号码不能重复),数据科学家可以进行唯一性检查;也可以是案例级的,例如当某些字段值的组合必须是特定值时。验证可以是严格的(例如删除缺失值的记录),也可以是模糊的(例如修正与现有已知值部分匹配的值)。
-
增强:这是一种通过添加相关信息使数据完整的技术。额外的信息可以通过使用数据文件中的现有值计算得出,也可以从其他来源添加。这些信息可以用于参考、比较、对比或展示趋势。
-
标准化:在数据标准化过程中,数据值会被转换或映射到其他更为理想的值。
-
标准化:这涉及将参考数据集转换为新的标准。例如,使用标准代码。
-
领域专业知识:这涉及根据数据科学家的经验或最佳判断,删除或修改数据文件中的数据值。
我们将在本章的接下来的部分中逐一讲解这些技术的例子。
R 与常见数据问题
让我们从一些关于 R 的背景知识开始。R 是一种易学的语言和环境,天生非常灵活,专注于统计计算,因而成为处理、清洗、汇总、生成概率统计等的绝佳选择。
此外,还有一些使用 R 进行数据清洗的其他原因:
-
它被大量数据科学家使用,所以它不会很快消失
-
R 是平台独立的,因此你所创建的内容几乎可以在任何地方运行
-
R 有非常棒的帮助资源——只需谷歌一下,你就能找到!
异常值
对异常值最简单的解释是,异常值就是那些与其他数据点不相符的数据点。观察时,任何特别高、特别低,或在你项目的上下文中显得特别不寻常的数据,都可以视为异常值。作为数据清洗的一部分,数据科学家通常会识别异常值,然后采用公认的方法来处理这些异常值:
-
删除异常值,甚至删除包含异常值的实际变量
-
转换值或变量本身
让我们来看一个使用 R 识别并解决数据异常值的真实世界例子。
在游戏世界中,老丨虎丨机(是一种通过将硬币插入插槽并拉动手柄来操作的赌博机器,手柄决定了支付的结果)非常受欢迎。如今大多数老丨虎丨机是电子的,因此它们被编程成可以持续追踪所有活动的方式。在我们的例子中,赌场的投资者希望利用这些数据(以及各种补充数据)来推动他们的盈利策略调整。换句话说,什么样的老丨虎丨机更能带来盈利?是机器的主题还是类型?新型机器比旧型或复古机器更有利可图吗?机器的物理位置如何?低面额的机器更有利可图吗?我们尝试通过异常值来寻找答案。
我们得到一组游戏数据(格式为逗号分隔或 CSV 文本文件),其中包括老丨虎丨机的位置、面额、月份、日期、年份、机器类型、机器年龄、促销活动、优惠券、天气和投币金额(即插入机器的总金额减去支付出的金额)。作为数据科学家的第一步,我们需要审查(有时称为分析)数据,查看是否存在异常值。第二步是处理这些异常值。
步骤 1 – 数据分析
R 使这一步变得非常简单。虽然有很多种方式可以编写解决方案,但我们尽量保持实际程序代码或脚本的行数最小。我们可以从在 R 会话中定义 CSV 文件作为一个变量(命名为 MyFile
)开始,然后将文件读取到 R 的 data.frame
(命名为 MyData
)中:
MyFile <-"C:/GammingData/SlotsResults.csv"
MyData <- read.csv(file=MyFile, header=TRUE, sep=",")
在统计学中,boxplot
是一种简单的方式,可以了解统计数据集的形状、变异性和中心(或中位数),因此我们将使用 boxplot
来查看我们的数据,看看能否识别出 Coin-in
的中位数,并确定是否存在离群值。为此,我们可以请求 R 绘制文件中每台老丨虎丨机的 Coin-in
值,使用 boxplot
函数:
boxplot(MyData[11],main='Gamming Data Review', ylab = "Coin-in")
Coin-in
是文件中的第 11 列,因此我在函数 boxplot
中明确将其作为参数。为了保持简洁,我还添加了可选的参数(继续简化代码),这些参数为可视化图形添加了标题。
执行之前的脚本后,我们得到了以下图形。注意中位数(通过 boxplot
中穿过盒子的线表示)以及四个离群值:
步骤 2 – 处理离群值
现在我们看到数据中确实存在离群值,我们可以处理它们,避免它们对我们的研究产生不利影响。首先,我们知道负的 Coin-in
值是不合逻辑的,因为机器不能发放超过已经投入的硬币。根据这一规则,我们可以简单地删除文件中所有 Coin-in
值为负的记录。再次地,R 使这变得很简单,我们将使用 subset
函数来创建一个新的 data.frame
,该数据框只包含那些 Coin-in
值非负的记录(或案例)。
我们将把这个 subset
数据框命名为 noNegs
:
noNegs <- subset(MyData, MyData[11]>0)
然后,我们将重新绘制图形,确保已经删除了负的离群值:
boxplot(noNegs[11],main='Gamming Data Review', ylab = "Coin-in")
这生成了一个新的 boxplot
,如下面的截图所示:
我们可以使用相同的方法来删除极端的正 Coin-in
值(大于 $1,500 的值),通过创建另一个 subset
,然后重新绘制:
noOutliers <-subset(noNegs, noNegs[11]<1500)
boxplot(noOutliers[11],main='Gamming Data Review', ylab = "Coin-in")
在处理数据的不同迭代过程中,建议你保存大部分(如果不是所有的话)版本的数据显示,特别是保存最重要的版本。你可以使用 R 的 write.csv
函数:
write.csv(noOutliers, file = "C:/GammingData/MyData_lessOutliers.csv")
大多数数据科学家采用统一的命名约定,贯穿整个项目(如果不是所有项目的话)。你的文件名应该尽可能明确,以便以后节省时间。此外,尤其是在处理大数据时,你还需要注意磁盘空间。
前面代码的输出结果如下:
领域专业知识
接下来,另一种数据清理技巧是基于领域知识进行数据清理。这并不复杂。这种技巧的关键是利用数据中没有的额外信息。例如,之前我们排除了具有负值的 Coin-in
数据,因为我们知道负的 Coin-in
数值是不可能的。另一个例子可能是当飓风桑迪袭击美国东北部时。在那段时间里,大多数机器的 Coin-in
数值非常低(如果不是零的话)。数据科学家可能会基于这些信息,移除特定时间段的数据。
有效性检查
正如我在本章之前提到的,交叉验证是指数据科学家对数据池中的数据应用规则。
有效性检查是最常见的统计数据清理形式,是数据开发人员和数据科学家最有可能(至少有些)熟悉的过程。
清理数据时可以使用任何数量的有效性规则,这些规则将依赖于数据科学家的预期目的或目标。这些规则的示例包括:数据类型(例如,一个字段必须是数值类型)、范围限制(数字或日期必须落在某个范围内)、必填(值不能为空或缺失)、唯一性(字段或字段组合必须在数据池内唯一)、集合成员(即值必须是某个离散列表的成员)、外键(某些值在某个案例中必须定义为某个规则的成员或符合该规则)、正则表达式匹配(即验证值是否符合预定的格式)、以及跨字段验证(即一个案例中的多个字段组合必须符合某个特定条件)。
让我们看一些前述的示例,首先从数据类型转换(也叫 强制转换)开始。R 提供了六个强制转换函数,方便使用:
-
as.numeric
-
as.integer
-
as.character
-
as.logical
-
as.factor
-
as.ordered
-
as.Date
这些函数,加上一点 R 知识,可以使得将数据池中的一个值转换变得相当简单。例如,使用之前的 GammingData 为例,我们可能会发现生成了一个新的游戏结果文件,且年龄值被保存为字符串(或文本值)。为了清理这些数据,我们需要将值转换为数值类型。我们可以使用以下一行 R 代码快速转换文件中的值:
noOutliers["Age"]<-as.numeric(noOutliers["Age"])
一点提示:使用这种简单的方法,如果任何值无法转换,它将被设置为 NA 值。在类型转换中,真正的工作是理解一个值需要转换成什么类型,当然,还有哪些数据类型是有效的;R 语言有多种数据类型,包括标量、向量(数值型、字符型、逻辑型)、矩阵、数据框和列表。
我们在这里查看的另一个数据清理领域是正则表达式模式的处理。在实际操作中,特别是当处理来自多个来源的数据时,数据科学家无疑会遇到一些字段,它们的格式不符合要求(例如目标任务的格式),或者字段值格式不一致(这可能会导致错误的结果)。一些例子包括日期、社会保障号码和电话号码。对于日期,视来源而定,你可能需要重新输入(如前所述),但通常情况下,你还需要将这些值重新格式化成一个可用的格式,符合你的目标。
重新输入日期是很重要的,这样 R 才知道使用该值作为实际日期,并且你可以正确地使用各种 R 数据函数。
一个常见的例子是,当数据包含日期字段,格式可能是YYYY/MM/DD
,你想进行时间序列分析,展示每周的总和,或者进行其他操作,这些操作需要使用日期值,但可能需要重新格式化日期,或者你仅仅需要它作为一个真正的 R 日期对象类型。假设我们有一个新的 Gamming 文件——这个文件只有两列数据:Date
和 Coinin
。这个文件是一个收集的 Coinin
值的转储,针对一个老丨虎丨机的每一天数据。
我们新文件中的记录(或案例)看起来像以下截图:
数据科学家可以使用多种清理方法。首先,验证这些数据点的每种数据类型。我们可以使用 R 函数 class
来验证文件的数据类型。首先(正如我们在前面的例子中做的),我们将 CSV 文件读入一个 R 数据框对象中:
MyFile <-"C:/GammingData/SlotsByMachine.csv"
MyData <- read.csv(file=MyFile, header=TRUE, sep=",")
接下来,我们可以使用 class
函数, 如下截图所示:
在前面的截图中,你可以看到我们使用了 class
来显示我们的数据类型。
MyData
是我们的数据框,包含我们的游戏数据,Date
是 factor
类型,Coinin
是 integer
类型。所以,数据框和整数类型对你来说应该是清晰的,但请注意,R 会将日期设置为所谓的 factor
类型。因子(factor)是分类变量,在总结统计、绘图和回归分析中非常有用,但作为日期值并不适合。为了修正这个问题,我们可以使用 R 函数 substr
和 paste
,如下面所示:
MyData$Date<-paste(substr(MyData$Date,6,7), substr(MyData$Date,9,10), substr(MyData$Date,1,4),sep="/")
通过这行简单的脚本,我们可以将所有记录中 Data
字段的值重新格式化。它将字段拆分成三个部分(即月、日和年),然后按照我们想要的顺序将这些部分重新拼接起来(使用 /
作为分隔符 (sep
)),如下所示的截图:
我们发现,这行脚本将我们的 Data
字段转换为 character
类型,最后我们可以使用 as.Date
函数将我们的值重新转为 R 中的 Date
类型:
通过一些反复试验,你可以将字符串或字符数据点格式化成你想要的样子。
增强数据
通过增强进行数据清洗是另一种常见的技术,它通过添加相关的信息、事实和/或数据,使数据变得完整(也许更有价值)。这些附加数据的来源可以是使用数据中已有信息的计算,或者是从另一个来源添加的数据。数据科学家可能会花时间增强数据的原因有很多种。
根据手头的目的或目标,数据科学家添加的信息可能用于参考、比较、对比或展示趋势。典型的使用场景包括:
-
派生事实计算
-
指明使用日历年与财政年度
-
转换时区
-
货币转换
-
添加当前与上一时期的指标
-
计算每天运送的总单位数
-
维护缓慢变化的维度
作为数据科学家,你应始终使用脚本来增强数据,因为这种方法比直接编辑数据文件要好得多,因为它更不容易出错,并且能保持原始文件的完整性。此外,创建脚本还允许你将增强功能应用于多个文件和/或新版本的文件,而无需重新做同样的工作。
作为一个工作示例,让我们再次回到我们的GammingData
。假设我们正在接收每台老丨虎丨机的Coinin
金额文件,并且我们的博彩公司现在在美国本土以外的地方运营赌场。这些地点向我们发送文件,以便将其纳入我们的统计分析,并且我们现在发现这些国际文件提供的Coinin
金额是以当地货币表示的。为了能够正确地建模数据,我们需要将这些金额转换为美元。以下是这个场景:
文件来源:英国
使用的货币:GBP 或英镑
将我们的 GBP 值转换为美元的公式很简单,就是将金额乘以汇率。因此,在 R 语言中:
MyData$Coinin<-MyData$Coinin * 1.4
上一行代码将完成我们想要的操作;然而,数据科学家需要决定需要转换哪种货币(GBP)以及使用的汇率是多少。虽然这不是一个大问题,但可能有人想尝试创建一个用户定义的函数来确定要使用的汇率,如下所示:
getRate <- function(arg){
if(arg=="GPB") {
myRate <- 1.4
}
if(arg=="CAD") {
myRate <- 1.34
}
return(myRate)
}
尽管前面的代码片段相当简单,但它说明了创建我们可以稍后重复使用的逻辑这一点:
最后,为了进一步改善,保存你的函数(在 R 文件中),这样它可以随时使用:
source("C:/GammingData/CurerncyLogic.R")
然后:
MyFile <-"C:/GammingData/SlotsByMachine.csv"
MyData <- read.csv(file=MyFile, header=TRUE, sep=",")
MyData$Coin <- MyData$Coinin * getRate("CAD")
当然,在最理想的情况下,我们可能会修改该函数,通过查找表格或文件中的汇率来获取汇率,基于国家代码,这样汇率就可以反映最新的值,并将数据与程序代码解耦。
协同化
在数据统一化过程中,数据科学家会根据分析目标或目的,将数据值转换、翻译或映射到其他更理想的值。最常见的例子是性别或国家代码。例如,如果你的文件中性别编码为1
和0
,或者M
和F
,你可能想将数据点统一编码为MALE
或FEMALE
。
使用国家代码时,数据科学家可能希望按区域绘制汇总数据:北美、南美和欧洲,而不是单独显示 USA、CA、MX、BR、CH、GB、FR 和 DE。在这种情况下,他或她会创建汇总值:
北美 = 美国 + 加拿大 + 墨西哥
南美 = 巴西 + 瑞士
欧洲 = 英国 + 法国 + 德国
举个例子,也许数据科学家将多个调查文件拼接在一起,这些文件都包含性别信息,文件名为gender.txt
,但性别使用了不同的编码(1
、0
、M
、F
、Male
和Female
)。如果我们尝试使用 R 函数table
,我们会看到以下不希望出现的结果:
如果我们带着最好的期待来可视化这个过程:
lbs = c("Male", "Female")
pie(table(MyData), main="Gambling by Gender")
我们看到以下截图:
再次,为了解决数据点性别编码不一致的问题,我借用了上一节中的示例概念,并创建了一个简单的函数来帮助我们重新编码:
setGender <- function(arg){
if(substr(arg,1,1)=="0" | toupper(substr(arg,1,1))=="M") { Gender <- "MALE" }
if(substr(arg,1,1)=="1" | toupper(substr(arg,1,1))=="F") { Gender <- "FEMALE" }
return(Gender)
}
这次,我添加了toupper
函数,以便我们不必担心字母大小写,同时使用substr
处理长度超过一个字符的值。
我假设参数值将是0
、1
、m
、M
、f
、F
、Male
或Female
,否则将会出现错误。
由于 R 将Gender
值归类为数据类型factor
,我发现很难轻松使用简单的函数,因此我决定创建一个新的 R 数据框对象来存储我们的统一数据。我还决定使用循环过程,逐一读取文件中的每个记录,并将其转换为Male
或Female
:
MyFile <-"C:/GammingData/Gender.txt"
MyData <- read.csv(file=MyFile, header=TRUE, sep=",")
GenderData <-data.frame(nrow(MyData))
for(i in 2:nrow(MyData))
{
x<-as.character(MyData[i,1])
GenderData[i,1] <-setGender(x)
}
现在我们可以通过编写代码来享受更合适的可视化效果:
lbls = c("Male", "Female")
pie(table(GenderData), labels=lbls, main="Gambling by Gender")
上述代码的输出如下:
标准化
大多数主流数据科学家已注意到,在开始统计研究或分析项目之前,标准化数据变量(将参考数据更改为标准数据)是数据清理过程中的一个重要步骤。这很重要,因为如果没有标准化,使用不同尺度测量的数据点很可能不会对分析贡献相同。
如果你考虑到一个在 0 到 100 范围内的数据点会比一个在 0 到 1 范围内的变量具有更大的权重,那么你可以理解数据标准化的重要性。没有标准化地使用这些变量,实际上会让范围更大的变量在分析中占据更大的权重。为了解决这个问题并使变量平衡,数据科学家会尝试将数据转换成一个可比的尺度。
居中(数据点)是数据标准化最常见的示例(当然,还有其他很多例子)。为了居中一个数据点,数据科学家会将所有数据点的均值从文件中的每个数据点中减去。
R 语言提供了scale
函数,省去了手动计算的麻烦。这是一个默认方法可以在一行代码中完成列的居中和/或缩放的函数。让我们看一个简单的例子。
回到我们的老丨虎丨机!在我们的游戏文件中,你可能记得有一个名为Coinin
的字段,其中包含一个数值,表示投放到机器中的总金额。这被视为机器盈利能力的衡量标准。这个数据点看起来是我们盈利分析中一个显而易见的选项。然而,这些金额可能具有误导性,因为存在不同面额的机器(换句话说,有些机器接受五分镍币,而有些则接受十分硬币或美元)。或许机器面额的不同造成了不平等的尺度。我们可以使用scale
函数来解决这个问题。首先,我们可以在下图中看到Coin.in
的值:
我们可以写出以下代码来居中我们的Coin.in
数据点:
scale(MyData[11], center = TRUE, scale = TRUE)
center
的值决定了如何执行列的居中。使用TRUE
值时,居中是通过从相应列中减去Coin.in
的列均值(忽略 NA 值)来完成的。scale
的值决定了如何执行列的缩放(在居中之后)。如果scale
为TRUE
,则通过将(已居中的)Coin.in
列除以它们的标准差来进行缩放,如果center
为TRUE
,否则除以均方根。
我们可以在下图中看到差异:
转换
一种引人深思的数据清理类型,可能对数据开发者来说是一个新概念,那就是数据转换。数据转换是一个过程,其中数据科学家通过一些数学操作实际改变你可能认为是有效数据值的内容。
数据转换的执行是将数据从原始格式映射到适当应用所期望的格式,或更适合特定假设或目的的格式。这包括值转换或翻译函数,以及将数值标准化以符合最小和最大值。
正如我们在本章前面使用 R 的示例一样,我们可以看到这个过程的一个非常简单的例子,语法也非常简单。例如,数据科学家可能决定将一个给定值转换为该值的平方根:
data.dat$trans_Y <-sqrt(data.dat$Y)
上面的代码示例告诉 R 创建一个新的变量(或 data.dat
数据集中的一列)trans_Y
,该变量等于原始响应变量 Y
的平方根。
虽然 R 可以支持几乎所有你能想到或需要的数学运算,但其语法并不总是直观的。R 甚至提供了通用函数 transform
,但截至本文写作时,它仅适用于数据框。transform.default
将其第一个参数转换为数据框,然后调用 transform.data.frame
。
那么,为什么要这么做呢?一个原因是像这样的关系可能不太奏效。例如,如果你正在处理数量级差异很大的值,那么处理这些值会变得困难。在实际应用中,比如比较不同物种的体重或各种声音频率及其对大气的影响。这些例子中,使用对数变换使得数据科学家能够以一种方式绘制值的图表,从而能看到在较小值之间的数据点差异。
另一个例子是对测试成绩的变换(将成绩转换为距离均值的差值)。
最后,许多广泛使用的统计方法假设数据服从正态分布或呈正态分布形态。在数据科学家观察到的数据与正常分布不符的情况下,可以使用数据变换。数据变换如对数、指数或幂变换通常用于尝试使非正态形态的分布数据变得更接近正态分布。这些数据变换也有助于数据科学家将极端离群值拉近与其他数据值的距离,从而减少离群值对总结统计量(如样本均值或相关性)的影响。
演绎推理
在演绎推理中,人们使用已知的信息、假设或普遍接受的规则来得出结论。在统计学中,数据科学家使用这一概念(尝试)修复数据集中存在的不一致性和/或缺失值。
对于数据开发人员,推理修正的例子包括将字符串或文本值转换为数值数据类型,或将符号从负数翻转为正数(或反之)。这些情况的实际例子包括克服存储限制,例如,当调查信息总是以文本形式捕获并存储,或会计需要将数值的美元金额表示为支出。在这些情况下,可能会进行数据审查(以推断需要执行哪些修正——也称为统计数据编辑——),或者该过程可以自动化,以影响来自特定数据源的所有传入数据。
数据科学家常规执行的其他推理修正包括输入打字错误、四舍五入误差、符号错误和数值交换错误的修正。
有一些 R 语言包和库可用,例如deducorrect
包,专注于修正四舍五入、打字和符号错误,并包括三种数据清洗算法(correctRounding
、correctTypos
和correctSigns
)。然而,数据科学家通常希望为当前项目特别定制编写解决方案。
确定性填充
我们一直在讨论数据科学家推导或确定如何处理或修正脏数据问题的主题,例如数据池中的缺失、错误、不完整或不一致的值。
当数据池中的数据缺失(或错误、不完整、不一致)时,会使处理和分析变得困难,并且可能引入偏差,影响对数据进行的分析结果。这就引出了填充方法。
在数据统计中,填充是指通过数据清洗过程,数据科学家用其他值替换缺失(或以其他方式指定的)数据。
由于缺失数据可能在分析数据时产生问题,填充被视为避免仅仅丢弃或完全删除缺失值案例所带来的风险的方式。实际上,一些统计软件包默认丢弃任何具有缺失值的案例,这可能引入偏差或影响结果的代表性。填充通过基于其他可用信息估算的值来替换缺失数据,从而保留数据池中的所有案例。
确定性填充是数据科学家在为缺失、无效或不一致的数据分配替换值时使用的过程,这些数据在编辑过程中未通过。换句话说,在特定情况下,当所有其他字段的具体值已知且有效时,如果只有一个(缺失)值会使记录或案例满足或通过所有数据科学家的编辑,那么该值将被填充。确定性填充是一种保守的填充理论,它针对的是那些简单可识别的情况(如前所述),并且可能是自动化编辑和填充数据时考虑的首要情况。
目前,在数据科学领域,填补理论正在获得越来越多的关注,并且持续发展,因此需要持续关注该领域的新信息。
其他一些著名的缺失数据填补理论包括热补法和冷补法;完全删除和配对删除;均值填补;回归填补;最后观察值前移法;随机填补;以及多重填补。
总结
在本章中,我们概述了不同类型或种类的统计数据清洗的基本原理。然后,使用 R 编程语言,我们展示了各种实际示例,说明了每种最佳或常用的数据清洗技术。
我们还介绍了数据转换、推理修正和确定性填补的概念。
在下一章,我们将深入探讨数据挖掘是什么以及为什么它很重要,并使用 R 进行最常见的统计数据挖掘方法:降维、频繁模式和序列。
第四章:数据挖掘与数据库开发者
本章向数据开发者介绍数据挖掘(与查询不同),并帮助理解什么是数据挖掘以及它为何是数据科学的核心组成部分。
我们将提供工作示例,帮助读者熟悉使用 R 进行最常见的统计数据挖掘方法:维度约简、频繁模式和序列挖掘。
在本章中,我们将内容分为以下主题:
-
数据挖掘的定义与目的
-
为数据挖掘而非数据查询准备开发者
-
使用 R 进行维度约简、频繁模式和序列挖掘
数据挖掘
通常,在解释事物时,从高层次的定义开始是明智的。
数据挖掘可以简单地解释为将有关特定主题或信念的信息整理成一种可理解(且可进一步使用)的格式。然而,需要记住的是,整理的信息并非数据本身(如数据查询),而是来自数据的信息(本章后面会详细讨论)。
数据挖掘也不应与分析、信息提取或数据分析混淆。此外,它可以是手动的、半自动的或自动化的过程。在处理新数据时,通常是由数据科学家手动进行的过程。后来,在处理相同数据(来源)的新版本时,可能会在某种程度上实现自动化。
数据挖掘是数据科学家进行的一种探测,目的是在数据中发现以前未知的信息,例如:
-
模式,如一组数据记录,被称为簇
-
不寻常的记录,被称为异常值
-
依赖关系,如关联规则或序列模式
这些新信息(或洞察)可以看作是一种数据总结,并可用于进一步分析,或例如在机器学习和预测分析中使用。例如,通过数据挖掘,数据科学家可能会识别出不同的组群,这些组群可以在决策支持系统中用于获得更准确的预测结果。
数据开发者可以将从数据挖掘中得到的洞察类比为描述性或结构性元数据,这在行业中被理解为定义数据的数据。
一旦探测完成,数据科学家已经挖掘出信息,这些信息必须根据工作目标转化为可理解且可用的结构。
数据收集、数据准备、解释和可视化的结果以及报告不属于数据挖掘的范畴。
常见技术
以下小节解释了一些最常见且被广泛接受和使用的数据挖掘(统计)分析方法。
可视化
平均值、变异度量、计数、百分比、交叉表格和简单相关性可帮助数据科学家理解数据结构。这也被称为数据概况分析。
区域、时间、 多维和层次化是常见且易于理解的数据可视化格式。
聚类分析
聚类分析被数据科学家用来将数据变量归入定义好的集合(即聚类),作为数据总结的一种方式。聚类应该在内部是同质的(变量之间相似),而在外部是异质的(变量与其他聚类中的成员不同)。
层次聚合法、划分法和基于模型的方法是常见的聚类分析方法。
相关分析
相关分析是一种方法,数据科学家通过该方法衡量两个数据变量之间的关系。由此得出的结果被称为相关系数,它展示了一个变量(自变量)的变化是否会导致另一个变量(因变量)的变化。
常见的相关性分析方法包括正相关/负相关、线性相关和非线性相关。
判别分析
判别分析用于在没有明显自然排序的群体情况下,判断数据变量是否属于某一类。使用这种方法时,预先设定好一些带有特定评分或度量的群体,并将其用于数据变量分类或分组过程中。
线性判别分析(LDA)是最常见的判别分析方法之一,数据科学家尝试找到特征的线性组合,用于表征或区分数据变量(分成不同组)。
因子分析
因子分析有助于理解数据变量之间关联的原因。其主要目标是减少变量的数量,并在它们之间的关系中检测结构(该方法也有助于整体数据的降维)。
数据科学家使用的因子分析类型包括主成分分析、公共因子分析、图像因子分析、阿尔法因子分析和因子回归分析。
回归分析
回归分析通过研究两个或多个定量变量之间的关系,使得可以根据其他变量(自变量)预测某个变量(因变量)的值。
回归分析有很多种类型,包括简单线性回归、多元线性回归、曲线回归和多重曲线回归,以及逻辑回归模型。
逻辑回归分析
逻辑回归分析是一种用于响应变量是二元或定性的情况,旨在通过最大似然法找到一个最佳拟合方程,以最大化在已拟合回归系数的条件下得到观测结果的概率。
逻辑回归的常见类型包括简单逻辑回归、多重逻辑回归、多类别逻辑回归和泊松逻辑回归模型。
目的
通过数据挖掘的实践,数据科学家可以实现(前述)从大量信息或数据中提取可操作信息的目标。
有人曾说数据挖掘的目标是发现无结构数据中的结构。例如,你可以使用数据挖掘来识别客户群体,以设计针对高价值客户的促销活动,或设计一个库存控制计划,以确保短期产品保质期。
有人可能会混淆数据查询与数据挖掘。但如果我们考虑为新开设的家居改善商店生成库存控制计划的例子,仅通过查询销售交易记录来确定过去几个月(来自其他商店)的最畅销产品,可能不会成功。而挖掘人口统计信息可能会得出更好的结果,因为我们可能会识别出有效的新颖、潜在有用的可理解的关联和模式,这些模式可以用于预测当地消费者的购买行为。换句话说,数据挖掘的目标或目的不是报告,而是发现。
在接下来的章节中,我们将更深入地探讨数据挖掘与数据查询之间的区别。
挖掘与查询
数据查询是提出具体、结构化问题来寻找特定答案的过程,而数据挖掘则是通过统计算法筛选数据,以识别模式和关系的过程。
以下矩阵可以帮助数据开发人员理解数据查询与数据挖掘之间的区别:
示例 | 数据查询或挖掘 |
---|---|
上个月全球销售的技术书籍总数是多少? | 数据查询 |
上个月影响全球销售的技术书籍类型的因素有哪些? | 数据挖掘 |
上个季度售出了多少种不同技术的技术书籍? | 数据查询 |
哪些技术是作为一套书籍购买的? | 数据挖掘 |
一项技术是倾向于购买纸质版还是电子版? | 数据挖掘 |
哪些技术书籍有重复购买的客户? | 数据挖掘 |
哪本技术书籍是总体销售量最高的? | 数据查询 |
再次强调,数据查询是报告事件结果,而数据挖掘则是识别可能有助于理解哪些因素影响了这些事件结果的关系的过程,或者这些关系可以用于预测类似事件的未来结果。
选择 R 进行数据挖掘
虽然有很多不错的选择,R 是一种学习曲线较短、非常灵活、且专注于统计计算的语言和环境,非常适合用于数据操作、清洗、总结、生成概率统计等(以及使用数据实际创建可视化);因此,它是进行数据挖掘练习的极佳选择。
此外,这里还有一些学习和使用 R 进行数据挖掘项目的更多理由:
-
R 被大量学术统计学家使用,所以它是一个不会消失的工具。
-
R 几乎是平台独立的;你开发的内容几乎可以在任何地方运行。
-
R 有很棒的帮助资源,只需谷歌一下,你就能看到!
为了说明,我们将在本章的其余部分探索几个使用 R 编程语言的实际数据挖掘例子。
可视化
首先,让我们来看一下如何使用 R 创建一个简单的数据可视化。在这个使用场景中,我们有来自理论医院的数据,患者在入院时通过在线调查收集病史信息,并在治疗过程中将信息添加到患者档案中。文件包括许多字段,其中包括:
-
患者的基本描述数据,例如性别、出生日期、身高、体重、血型等。
-
生命体征,例如血压、心率等。
-
病史,如住院次数、手术、重大疾病或病情、是否在医生治疗下等。
-
人口统计学统计数据,例如职业、家乡、教育背景等。
-
文件中还收集了一些额外的信息,用于开发患者的特点和习惯,例如患者每周饮食中牛肉、猪肉和家禽的摄入次数,是否通常使用黄油替代品等。
假设我们没有得到关于数据的更多信息(除了简要的字段名称列表以及数据是由医院人员在患者入院时采集的),接下来的步骤是进行一些数据挖掘,即识别或分组数据,并可能查找变量之间的关系。
要开始,我们可以将医院调查数据读入 R 数据框架,然后使用两个可用的 R 函数来揭示文件中的信息:
这里显示的代码将我们的文本文件(名为Chapter4.txt
)读取到 R 数据框架中(也名为chapter4
),然后使用dim
和names
函数。dim
函数展示了文件的数据结构(此文件中有5994
条记录或案例,以及107
个数据点或变量,如我们刚才看到的截图所示)。names
函数则列出了文件中所有字段或变量的名称(部分名称在我们刚才看到的截图中显示)。
R 函数属性和str
也是一些非常有用的 R 数据挖掘函数,值得读者花时间深入研究并进行实验。
最初,数据科学家可能会通过查看字段名称来寻找一些初步的思路;例如,常见的分组项,如性别、年龄和州(如今“是否投保”也是一个非常有趣的属性!)。
当前吸烟者
通常,数据科学家在进行数据挖掘时会有一个目标。在这个例子中,假设我们有兴趣将吸烟患者分成不同的年龄组。使用current_smoker
变量,我们可以使用 R 的 table 函数并运行以下代码:
table(chapter4["current_smoker"])
这将生成以下信息:
从这里显示的结果来看,似乎我们有更多的非吸烟者(5466
)而不是吸烟者(528
),至少在这个文件或人群中是这样。
接下来,我们想看到的(即可视化)是将我们人群中的吸烟患者按年龄组进行组织。为此,数据科学家的下一步逻辑应该是了解age
变量中的range
值。换句话说,我们的数据挖掘工作的一部分将是查看我们人群中最年轻患者的年龄以及最年长患者的年龄。我们不需要通过切片和筛选数据来查找这些信息,可以使用 R 的 range 函数,如下所示:
从这些结果中,数据科学家现在可以看到我们有患者年龄从 1 岁到 99 岁的病例!另一个好主意是可视化我们患者年龄的频率。数据科学家可能希望再次使用 R 的 table 函数来创建一个直方图:
hist(table(Chapter4["age"]))
上述代码的输出结果是:
这段 R 代码将生成以下可视化图表,进一步展示我们患者的年龄分布:
另一个有趣的信息是密度估计。通过不太复杂的操作,我们可以将三个 R 函数plot
、density
和table
嵌套在一起,创建另一个患者年龄的可视化图表。
我们可以运行以下代码:
这将生成以下可视化图表:
鉴于所有这些新获得的知识,也许数据科学家会想继续将我们的病例分成六个不同的年龄组:
-
22 岁以下
-
22 到 34 岁
-
35 到 44 岁
-
45 到 54 岁
-
55 到 64 岁
-
65 岁及以上
为了开始使用数据科学家的术语,数据开发者应该开始使用“病例”而不是“记录”(在文件中),使用“人群”而不是“文件”。
以下 R 程序代码根据记录的年龄将我们的病例按当前吸烟者进行分组,并创建一个简单的饼图来可视化结果:
# -- read our data into a data frame object
Chapter4<-read.csv('c:/chapter4/Chapter4.txt')
# -- initialize holders for counting cases
a1 <-0;a2 <-0;a3 <-0;a4 <-0;a5 <-0;a6 <-0
# -- read through the cases and count smokers by age group
for(i in 2:nrow(Chapter4))
{
if (as.numeric(Chapter4[i,"age"]) < 22 & Chapter4[i,"current_smoker"]=="Yes") {a1 <- a1 + 1}
if (as.numeric(Chapter4[i,"age"]) > 21 & as.numeric(Chapter4[i,"age"]) < 35 & Chapter4[i,"current_smoker"]=="Yes") {a2 <- a2 + 1}
if (as.numeric(Chapter4[i,"age"]) > 34 & as.numeric(Chapter4[i,"age"]) < 45 & Chapter4[i,"current_smoker"]=="Yes") {a3 <- a3 + 1}
if (as.numeric(Chapter4[i,"age"]) > 44 & as.numeric(Chapter4[i,"age"]) < 55 & Chapter4[i,"current_smoker"]=="Yes") {a4 <- a4 + 1}
if (as.numeric(Chapter4[i,"age"]) > 54 & as.numeric(Chapter4[i,"age"]) < 65 & Chapter4[i,"current_smoker"]=="Yes") {a5 <- a5 + 1}
if (as.numeric(Chapter4[i,"age"]) > 64) {a6 <- a6 + 1}
}
# -- build a pie chart
slices <- c(a1, a2, a3, a4, a5, a6)
lbls <- c("under 21", "22-34","35-44","45-54","55-64", "65 & over")
# -- create the actual visualization
pie(slices, labels = lbls, main="Smokers by Age Range")
以下是我们使用 R pie
函数生成的简单饼图:
缺失值
任何分析结果的关键是数据的可用性。
假设在我们的数据集中有一些案例缺少值。你可能希望在分析中忽略(或省略)这些案例。与其花时间编写代码来处理这些案例,不如使用 R 的通用函数na
。na.omit
函数会评估文件中的每个案例,如果某个案例在任何变量上都有缺失值,它会自动删除该案例。
以下示例展示了 R 函数na.omit
和nrow
在一个包含缺失值的文件上的使用:
请注意使用na.omit
前后行(案例)数量的变化(删除了五条记录)。
我已经用更新的文件覆盖了对象Chapter4
;实际上,养成创建新对象的好习惯是很有益的,这样在任何处理前后都能保留数据的审计记录。
聚类分析
在下一个示例中,数据科学家希望更仔细地查看我们的案例,但只关注那些吸烟者。所以,我们在 R 中首先创建一个原始案例的子集,只包含那些当前吸烟的案例。和之前的例子一样,在创建子集(命名为mysub
)后,我们将使用 R 的nrow
函数验证我们新数据集中的记录数,以便了解新数据集中的案例数量:
# --- create a subset of smokers only cases
mysub <- subset(Chapter4,Chapter4["current_smoker"]=="Yes")
# --- confirm the row count
nrow(mysub)
上述代码的输出是:
根据我们刚刚看到的输出,我们的新数据集仍然有超过 500 个案例。因此,作为数据科学家,我们决定从我们的案例中随机抽取一部分样本(我们将对其进行聚类分析),然后再次验证我们最新数据集中的记录数。
我们可以使用 R 的sample
命令来创建仅包含 30 个案例的样本:
# --- create a random sample of 30 smokers
mysample <- mysub[sample(1:nrow(mysub), 30,
replace=FALSE),]
# --- confirm the row count in our random case sample
nrow(mysample)
上述代码的输出是:
最后,我们的数据科学家觉得现在他已经有了足够小的样本,足以进行处理,所以我们继续用这个样本进行聚类分析。如本章前面提到的,层次聚合聚类是最流行的聚类分析技术之一,因此我们将使用它来处理我们随机抽样的案例。
我们可以使用 R 的dist
和hclust
函数组合对我们随机抽样的案例进行层次聚合聚类分析。dist
函数计算数据集的距离矩阵,给出任意两条观察值之间的欧几里得距离。hclust
函数则在该距离矩阵上执行层次聚类。
总结来说,回顾和理解层次聚类分析结果的最简单方式是通过结果的可视化。这个可视化通常被称为树状图(一种常用于说明聚类安排的树形图),所以我们也会添加这段代码:
# -- perform the hierarchical cluster analysis
smokerclust<-hclust(dist(mysample))
# -- create results in a dendrogram
plot(smokerclust)
上述代码的输出是:
这段代码示例创建了以下可视化:
R 提供了一个长长的选项列表,可以根据数据和统计信息创建丰富的可视化图表。对数据科学家来说,熟悉这些选项非常重要,也许更重要的是理解哪种可视化图表最适合分析的目标。
降维
聚类是旨在基于对属性值的观察,将相关的数据变量分组。然而,考虑到有大量属性的场景,数据科学家会发现,一些属性通常对某个特定的聚类来说没有意义。在我们之前本章中使用的示例(处理病人病例)中,可能会遇到这种情况。回想一下,我们对吸烟者进行了层次聚类分析。那些案例包括许多属性,如性别、年龄、体重、身高、就诊次数、心率、州、关系、保险、血型、血压、教育、出生日期、是否为当前饮酒者、是否正在服药、已知过敏症、是否正在接受医生照护、是否曾做过手术、职业、心脏病发作、风湿热、心脏杂音、动脉疾病等。
作为数据科学家,你可以使用 R 函数names
,就像我们在本章前面所做的那样,查看所有属性的完整列表。
降维是一个过程,数据科学家尝试减少或限制一个案例中的属性(或维度)数量。这被称为减少考虑中的随机变量数量,但实际上就是根据科学理论,从数据文件中移除某些列。
当前接受和常用的去除维度的方法包括:
-
缺失数据:如果某个变量(列)有很多没有值的案例(记录),它不会增加太多的价值;因此,该列可以被删除。
-
记住,在本章前面,我们使用了 R 函数
na.omit
。这个函数在删除整个案例时非常有用;然而,使用降维时,我们想要为所有案例删除整个变量。 -
小方差:像变量有大量缺失值一样,方差小的变量没有增加价值,也可以被删除。
-
高度相关性:具有相似趋势的数据列也可能携带非常相似的信息。在这种情况下,只需要其中一个。
-
决策树:这是一种可能需要更多工作的方法。它是一种降维技术,数据科学家通过针对目标属性生成一组决策树,然后利用每个属性的使用统计数据,找出最有信息量的特征(或列)。使用统计数据最少的列可以被删除。
-
主成分分析(PCA):它是一个过程,将数据集中的变量转换为一组新的变量,称为主成分。这些成分按变量的可能方差排序,只有那些方差最高的成分才会被保留。
-
后向消除法和前向构造法:这些技术涉及集中关注一个或多个变量,并按顺序一个一个地去除或添加额外的变量并观察其效果。后向消除法通过可接受的误差率来衡量效果,而前向构造法则通过对性能的影响来衡量效果。
计算统计显著性
现在让我们来看一个简单的例子,使用数据变量计算出的方差来决定它是否应该从分析中移除。
再次使用我们在本章中一直使用的患者案例例子,我们可以使用 R 函数var
来确定我们人群中变量的统计显著性。
R 函数var
仅适用于数值型数据。
在下面的代码中,我们使用 R 函数var
来计算名为的变量的方差:
"no_servings_per_week_skim_milk".
我们可以看到,它有一个较低的方差百分比(它变化不频繁,或者在不同的案例中没有很多不同的值):
如果我们看另一个变量的计算方差百分比,名为:No_servings_per_week_regular_or_diet_soda
,我们会发现它的计算方差(比前一个变量)更高:
最后,如果我们看一个第三个变量,名为No_servings_per_week_water
,我们得到第三个计算出的方差:
从这些单独的方差计算中,我们可以看到每个变量在我们案例分析中的统计显著性:
数据变量 | 计算出的方差 |
---|---|
No_servings_per_week_skim_milk |
.003160316 |
No_servings_per_week_regular_or_diet_soda |
8.505655 |
No_servings_per_week_water |
24.10477 |
名为No_servings_per_week_skim_milk
的数据变量可以肯定地从分析中剔除,并且根据我们的数据科学家容忍度,名为No_servings_per_week_regular_or_diet_soda
的数据变量也可能会被从分析中剔除。
使用简单的 R 函数,我们可以可视化我们计算出的方差数据,以便更好地理解:
因此,我们生成以下可视化:
当我们去除一个变量时,它会从我们所有的案例中被移除。
高频模式
为了理解统计模式,让我们首先思考一下当城市地区受到严重天气和潜在危险的旅行威胁时会发生什么——所有本地商店都抢购面包、牛奶和鸡蛋!
模式挖掘(数据挖掘的一个子领域)是通过查看数据来识别以前未知但可能有用的模式的过程,这些模式通常由频繁同时发生的事件(例如暴风雨天气触发面包、牛奶和鸡蛋的销售)或对象(例如面包、牛奶和鸡蛋通常一起购买或在同一个购物车中捆绑在一起)组成。
模式挖掘是指使用或开发自定义模式挖掘逻辑的过程。该逻辑可能应用于各种类型的数据源(如交易和序列数据库、流数据、字符串、空间数据、图形等),以便查找各种类型的模式。
在更高层次上,数据科学家寻找:
-
有趣的模式
-
频繁模式
-
稀有模式
-
高置信度模式
-
顶级模式,以及其他模式
一些可能存在于数据中的更具体的模式类型包括:
-
子图:在图或一组图中发现一个有趣的图形
-
直接和间接关联:识别对象或事件之间的耦合或依赖关系;可以是隐式或显式定义的
-
趋势:这也有时称为趋势分析,是收集看似无关的信息并尝试找出模式的实践
-
周期性模式:定义为元素在一个周期或组中,特征的变化或趋势
-
序列规则:这是对序列模式挖掘的扩展,考虑了一个已识别模式被跟随的概率
-
格:一个部分有序的集合,其中每两个元素都有一个唯一的最小上界和唯一的最大下界
-
序列模式:出现在多个数据序列中的子序列
-
高效模式:高效模式是指那些已被确定为具有较高、较大或等于阈值的模式
频繁项集
在前一节(寻找频繁模式)的基础上,频繁项集是一个扩展概念。对于数据开发者来说,最适用的模式概念是频繁项集或查找经常作为一组或集合成员出现的项。
以我们前面章节中的暴风雨天气为例,可以设想通过查找销售交易文件或数据库中的过程,寻找那些在一次销售中(或一组产品中)一起购买牛奶、面包和鸡蛋的情形(即事件)。
频繁项集还涉及确定在分析中使用的最小支持度(minsup)阈值。这意味着数据科学家将确定构成一个集的项的最小出现次数。
再次回到我们暴风雨天气的例子,如果数据科学家设置最小支持度为 2,那么仅有两个成员商品的销售将被视为一个集合或模式。
让我们考虑以下销售交易:
销售 ID | 购买商品 | 是否符合(作为频繁项集) |
---|---|---|
销售 1 | 牛奶,面包,鸡蛋 | 是 |
销售 2 | 牛奶,土豆 | 否 |
销售 3 | 面包,鸡蛋,茶 | 是 |
销售 4 | 鸡蛋,橙汁 | 否 |
最著名的模式挖掘算法无疑是 Apriori,它旨在应用于事务数据库,用于发现客户在商店中进行交易时的模式。该算法以用户设置的最小支持度(minsup)阈值和包含一组事务的事务数据库作为输入,并输出所有频繁项集。
序列挖掘
序列挖掘进一步发展了前述概念。这是一个过程,数据科学家用它来发现一组在对象之间共享的模式,并且这些模式之间有特定的顺序。
在序列挖掘中,我们认识到有与已识别序列相关的序列规则。这些规则定义了模式的对象和顺序。一个序列可以有多个规则。序列规则的支持度可以通过数据科学家计算,方法是将包含该规则的序列数量除以总序列数。序列规则的置信度则是将包含该规则的序列数除以包含其前提的序列数。
总体而言,序列规则挖掘的目标是发现所有支持度和置信度都不低于用户指定的最小支持度(minsup)和最小置信度(minconf)阈值的序列规则。
总结
在本章中,我们提供了数据挖掘的通用定义,列出了数据科学家最常用的技术,并说明了这些工作的整体目标。数据挖掘还与数据查询进行了比较,并通过 R 语言提供了各种工作示例,以说明某些关键技术。最后,探讨了降维、频繁模式挖掘和序列挖掘的概念。
下一章将通过数据开发者的视角,手把手介绍数据的统计分析,提供描述数据特征、探索数据中呈现的关系、从数据中创建总结模型、验证数据模型有效性以及在数据开发模型上进行预测分析的指导。
第五章:数据库开发者的统计分析
本章将数据开发者引入统计分析的实践。
作为数据开发者,数据分析的概念或过程可能在你脑海中已经很清晰。然而,尽管数据分析和统计分析之间存在相似之处,但也有一些重要的差异需要理解。
本章旨在指出分析类型之间的相似性和差异,帮助读者理解数据、总结和统计分析过程中的基本原则,这些过程描述了成功的统计分析工作中所涉及的关键因素或特征,并提供每个步骤的工作示例,帮助读者掌握如何成功地进行数据统计分析。
在本章中,我们将内容分为以下主题:
-
什么是数据分析、统计分析和总结?
-
成功的统计分析步骤
-
使用 R 进行数据的统计分析
-
示例--总结模型
数据分析
我们首先来看看所谓的数据分析。这被定义为通过分析和逻辑推理对数据进行评估的结构化过程。进行数据分析时,需要花时间收集所有要分析的数据,将数据(现在视为数据源)分解为可以审查的块或组件,然后根据数据中看到或发现的内容得出结论。通常,这样做的目的是确定某个数据源是否适用于完成声明的项目交付目标。
数据分析方法有很多种,其中包括数据挖掘(在第四章中讨论过,数据挖掘与数据库开发者)、文本分析、商业智能和数据可视化(仅举几个例子)。
对于数据开发者而言,数据分析涉及以某个目的为导向,检查数据源的各个部分。
例如,假设我们有一些来自自行车制造组织的交易数据,想要用它来生成销售绩效报告。通常这类项目,我们可以假设我们获得了从数据库中提取的 CSV 格式数据。
现在,使用 R 命令,我们可以识别数据中的字段或列,并查看数据的总结。以下 R 代码使用read.csv
将我们的数据文件加载到 R 数据框对象中,然后使用命令colnames
列出文件中的字段或列名;最后,我们使用 R 命令 summary 来指示 R 为我们提供一些关于数据的统计信息。
以下截图展示了运行 R 命令(colnames
和summary
)的输出结果:
更进一步的观察
一旦我们确认数据中包含了产品标识符(编号和名称)、交易数量、销售日期、退货日期、销售区域信息等内容,我们将希望对数据中的各个组成部分进行一些探索(分析)。也许我们可以通过使用 R 命令nrow
来计算文件中的总记录数,然后使用 R 命令list
和unique
列出数据中出现的唯一零件或产品编号,如下所示的代码和部分输出所示:
进一步的数据分析任务包括检查数据中每个组成部分的内容,例如:
-
sales_date
和return_date
(字段)的日期值格式是什么? -
这些字段中的日期范围是什么?
-
我们的数据文件中包含多少个唯一的产品和销售区域?
请记住,日期总是一个难点,因此确定日期格式和范围始终是进行包含日期或时间值的数据分析时的一个有价值的分析任务。
为了说明这一点,我们可以使用几个简单的 R 命令,创建一个包含我们数据中年份和月份的列表。
以下是用于完成此统计分析任务的 R 代码:
# --- read our data file into "x"
x <-read.table("c:/Worker/23SamplesSalesTrans.csv", sep=",", header = FALSE, skip = 1)
# --- convert "x" into a data frame object, then set the data frame to
# --- hold only the sales_date
data.df <- data.frame(x)
data.df <- data.df[,4]
# --- use the R commands substr and regexpr to strip out just the year and # --- month from the sales date field
YearsInData = substr(substr(data.df[],(regexpr('/',data.df[])+1),11),( regexpr('/',substr(data.df[],(regexpr('/',data.df[])+1),11))+1),11)
MonthsInData = substr(data.df[],(regexpr('/',data.df[])-1),1)
# --- use sort and unique functions to list our year(s) and month(s)
sort(unique(YearsInData))
sort(unique(MonthsInData))
以下截图显示了运行前述命令后的输出:
我们可以看到,数据中只包含了 2013 年日历年第一季度的数据,即月份1
、2
和3
。现在我们已经确定了数据的时间序列。虽然还有许多数据分析工作可以继续进行,但关键在于我们正在进行旨在建立结构的分析练习,以便实现最初的销售业绩报告目标,而不是进行机器学习。
有了这个前提,假设我们希望检查按月的交易量。为此,我们可以使用 R 计算这些每月的总额,代码如下:
# --- read data
data.df<-data.frame(x)
# --- initialize counters
JanuarySales <-0
FebruarySales <-0
MarchSales <-0
# --- loop and count
for(i in 1:nrow(data.df))
{
MonthInData = substr(data.df[i,4],(regexpr('/',data.df[i,4])-1),1)
if (MonthInData == '1') {JanuarySales <- JanuarySales + data.df[i,3]}
if (MonthInData == '2') {FebruarySales <- FebruarySales + + data.df[i,3]}
if (MonthInData == '3') {MarchSales <- MarchSales + + data.df[i,3]}
}
一旦我们计算出每月的交易总额(使用前面的命令),我们就可以报告这些结果。这可以通过创建一个简单的条形图可视化来完成。
我们可以在以下代码中使用 R 的barplot
函数:
barplot(c(JanuarySales, FebruarySales, MarchSales), main="Sales Qty by Month", border = "dark blue", legend.text = c("Jan", "Feb", "Mar"), col = c("lightblue", "mistyrose","lightcyan"), sub = "Sales Transactions from File")
上述命令生成了以下可视化结果:
这些描述的数据分析任务示例只是进行特定目标数据分析时通常完成的众多步骤中的一部分,例如生成业绩报告。
总结来说,数据分析就是回顾数据,确定其是否可以作为创建特定结果的有效来源,并且如果可以,如何使用它。
接下来,让我们继续进行下一节的统计分析。
统计分析
一些统计学研究者有时将统计分析描述为统计项目的一部分,涉及收集和审查数据源,以努力识别数据中的趋势。
在数据分析中,目标是验证数据是否适合某种需求,而在统计分析中,目标是理解数据并从中得出一些推论。
有许多可能的统计分析技术或方法可以考虑。
总结
让我们回到我们的自行车零部件制造组织示例。假设我们有一个新的交易文件,这次我们有更多的数据,我们的工作重点将是进行统计分析,目的是识别可能影响销售表现的具体因素,作为前面活动的一部分。
第一步是对数据进行总结。前一部分已经展示了一些分组:产品和时间段。利用这些组件,我们能够讲述组织销售表现的故事。
数据中可能还包含哪些其他分组或类别?
例如,如果我们假设销售表现依赖于时间段,那么首先要做的可能是将数据按时间段分组。标准的时间段当然是月份、季度和年份(我们在之前的部分已经做了这个),但从统计学角度来看,数据越多越好,因此一个更好的时间分组方式可能是十年或五年的区间。
总结过程中常用的做法是可视化,通常使用条形图,这些图表按顺序显示每个数据点,或使用直方图,它是按更广泛的类别分组的条形图。在这一部分中,我们将牢记这一点,并使用 R 创建各种可视化,以展示我们数据总结的结果。
比较分组
让我们继续进行(像本章前面一样)使用 R 命令colnames
和summary
;这次应用于我们的新数据文件:
如图所示,我们的文件中有一个额外的字段(或组件)sale_type
,执行总结命令后,得到了以下统计数据,其中包括销售类型的细分:
下一步将取决于你的假设。例如,如果你认为销售类型(sale_type
)对整体销售表现有影响,那么你需要为每个(销售类型)组生成summary
数据,通常包括均值、中位数和/或标准差(之前的summary
命令是一个很好的开始)。让我们来看一些使用 R 来创建这些summary
信息的例子。
和往常一样,我们可以首先将数据读取到 R 中,然后明确地将其移动到 R 数据框对象中。以下代码适用于此步骤:
# --- read in the data in
sales <- read.csv("c:/Worker/SamplesSalesTrans_2.csv")
# --- just moving our original data to a data frame object
# --- preserving the original
data.df<-data.frame(sales.new)
使用 R 语言时,有许多不同的方法或方法可以完成相同的任务,但在这个示例中,我们将使用最直接、最简单的方法——通过循环遍历数据,创建每种销售类型的汇总总量。
以下是我们使用的循环代码:
# --- looping through the data and counting quantities
# --- type
for(i in 1:nrow(data.df))
{
if (data.df[i,2] == 'Online')
{Online <- Online + data.df[i,1]
OnlineC <- OnlineC +1}
if (data.df[i,2] == 'Television')
{Television <- Television + data.df[i,1]
TelevisionC <- TelevisionC +1}
if (data.df[i,2] == 'New Customer')
{NewCustomer <- NewCustomer + data.df[i,1]
NewCustomerC <- NewCustomerC +1}
if (data.df[i,2] == 'Retailer')
{Retailer <- Retailer + data.df[i,1]
RetailerC <- RetailerC +1}
if (data.df[i,2] == 'Club')
{Club <- Club + data.df[i,1]
ClubC <- ClubC +1}
if (data.df[i,2] == 'Discounted')
{Discounted <- Discounted + data.df[i,1]
DiscountedC <- DiscountedC +1}
if (data.df[i,2] == 'Repeat')
{Repeat <- Repeat + data.df[i,1]
RepeatC <- RepeatC +1}
if (data.df[i,2] == 'Vendor')
{Vendor <- Vendor + data.df[i,1]
VendorC <- VendorC +1}
}
也许,更高效的方法是根据 sale_type
来创建数据子集。这可以通过使用以下 R 命令来实现:
# --- create average or mean for all Online sales quantities
# --- by first creating a subset of only quanities of that sale
# --- type
OnlineSales.new <-data.df[data.df$sale_type == "Online",]
OnlineSalesMean <-mean(OnlineSales.new$quantity)
# --- using the summary totals, you could do the math to calculate # --- the average or mean:
OnlineMean <- Online/OnlineC
此外,我们还可以使用 R 函数 mean、median 和标准分布来计算数据的统计summary
信息,具体如下所示的 R 命令:
# --- calculate the mean for all sale types:
MeanAll <-mean(data.df [["quantity"]])
# --- calculate the standard deviation for all sales types:
StdDAll<-sd(data.df[["quantity"]])
# --- calculate the median for all sales types:
MeanAll <-mean(data.df [["quantity"]])
下图展示了运行前述命令的结果:
一旦我们计算出一些summary
信息,下一步就是利用这些信息创建一个或多个可视化图表,便于我们更轻松地观察和研究。
直方图是实现此目标的一个不错的可视化选项。在执行几个数据操作后,我们可以使用 R 函数hist
,如下所示的 R 代码:
# --- using the calculated average/mean for each sale type
temp<-c(Online, Television, NewCustomer, Retailer, Club, Discounted, Repeat, Vendor)
# --- create the histogram
hist(temp, breaks=8, freq=TRUE, main="Quantity by Sales Type", border="black", col = "gray", xlab="Types: Online, Televsion, New Customer, Retailer, Club, Discounted, Repeat, Vendor")
abline(v=ref,col="red")
以下图示展示了由前述 R 命令创建的直方图可视化图:
为了决定是否存在任何观察组之间的实际差异,大多数情况下,你会首先建立一个参考值或参考分布,用于衡量每个组的值(在本例中是每个sales type
组)。
最常见的参考标准是标准分布。标准分布衡量的是数据的变异性,或者说一组数值有多么不同和/或分散;在这个示例中,我们讨论的是sales quantities
。就像我们在本节前面所做的,我们可以使用 R 命令sd
来建立数据源中所有产品的标准分布,使用以下 R 命令:
# -- calculate standard distribution of all product quantities
sd(data.df[["quantity"]])
接下来,我们可以快速地通过可视化,比较每个sales type
组的summary
数据与我们的标准分布。
以下 R 命令可用于计算每个组的标准分布总量:
# --- create a subset of only online sale type quantities
quantity.new <- data.df[data.df$sale_type == "Online",]
# --- calculate this subsets standard distribution
StdDOnline<-sd(quantity.new$quantity)
# --- repeated for each sales type group!
然后,我们可以使用以下 R 命令绘制标准分布总量,进行可视化比较:
# --- after computing each type, calculate the standard
# --- distribution for all sales quantities:
StdDVendor<-sd(quantity.new$quantity)
# --- combine the totals into "Temp"
Temp<-c(StdDOnline, StdDTelevision, StdDNewCustomer, StdDRetailer, StdDClub, StdDDiscounted, StdDRepeat, StdDVendor)
# --- create a simple Line Chart
plot(Temp, type="o", col="blue", axes=FALSE, ann=FALSE)
axis(1, at=1:8, lab=c("Online", "TV","New", "Retail","Club","Disc","Rep","Ven"))
title(ylab="STD DIST", col.lab=rgb(0,0.5,0))
box()
随后,使用前述命令生成的线形图可视化图,显示了每种sales type
的标准分布:
在这个可视化图中,我们忘记绘制的是所有sales types
的标准分布。通过之前的计算和 R 的abline
函数,我们可以使用以下 R 命令更新我们的可视化图:
abline(h=sd(data.df[["quantity"]]), col="green")
以下是我们更新的可视化图,增加了水平线(绿色水平线)或水印,显示了所有sales types
的标准分布:
上图现在让我们了解了每种销售类型与标准分布总量的对比情况。
样本
通常,你会希望将分布与样本进行比较(而不是所有量的总和),因此我们可以使用 R 语言的样本函数从我们的数据中创建一个样本:
# --- use sample to create a random sampling of data
mysample.df <- data.df[sample(1:nrow(data.df), 100, replace=FALSE),]
然后,我们可以重新创建之前的可视化图(使用plot
,axis
,title
和box
),其中横线或水印表示(随机)样本的标准分布:
# --- original visualization
plot(Temp, type="o", col="blue", axes=FALSE, ann=FALSE)
axis(1, at=1:8, lab=c("Online", "TV", "New", "Retail","Club","Disc","Rep","Ven"))
title(ylab="STD DIST", col.lab=rgb(0,0.5,0))
box()
# --- create a sample population
mysample.df <- data.df[sample(1:nrow(data.df), 100, replace=FALSE),]
# --- draw a water mark from the
$ --- samples standard distribution
abline(h=sd(mysample.df[["quantity"]]), col="green")
运行前面的 R 代码会生成以下可视化图:
其他比较群体的方法包括平均值,特别是均值、中位数和众数。
另一个关键比较是衡量数据的分散程度,即数据在整个可能测量范围内的分布广度。通常,我们通过计算方差来执行此分析。同样,R 使这一任务变得简单,只需使用var
函数。
以下命令计算我们样本的方差,以及整个群体的方差:
# --- calculate our samples variance
var(mysample.df[["quantity"]])
# --- calculate total variance
var(data.df[["quantity"]])
群体比较结论
在继续之前,我们需要指出的是,你在进行群体的统计分析时,需要小心得出结论。在前面的例子中,我们集中于比较分布。使用单一的比较点可能导致你做出不准确的假设,例如:
-
群体是不同的,但你得出结论它们并不不同
-
群体是相同的或非常相似,但你得出结论它们是不同的
为了避免这些错误,明智的做法是计算并观察数据中的多个总结点。为此,你可以创建一个总结模型,这也是我们下一节的主题。
总结建模
常见的做法是通过开发总结模型来建立多个总结点。简而言之,从数据中创建总结模型,就是创建一个表格或数据框,表格的行包含均值、标准分布、中位数、最小值、最大值,以及每个数据组件的总和(或者至少是你感兴趣的每个数据组件)。
让我们使用之前的数据示例,在其中我们根据各个销售类型
组别检查了销售数量。幸运的是,R 提供了简单的函数来计算我们的比较点:最大值、均值、标准分布、中位数、最小值和总和。
我们可以利用它们单独计算每个群体的比较点,如下所示:
# --- create subset of Online quantities
quantity.new <- data.df[data.df$sale_type == "Online",]
# --- calculate each comparison point
max(quantity.new[["quantity"]])
mean(quantity.new[["quantity"]])
sd(quantity.new[["quantity"]])
median(quantity.new[["quantity"]])
min(quantity.new[["quantity"]])
sum(quantity.new[["quantity"]])
接下来,我们创建一个 R 的data frame
(df
)对象来保存我们的总结数据,然后将所有的比较点加载到数据框中。以下是相应的 R 代码:
# --- create a data frame object for summarization
df<-data.frame(8,7)
# --- create our subset of data - this is online sales
quantity.new <- data.df[data.df$sale_type == "Online",]
# --- calculate comparison points based upon
# --- our current subset dropping each in a temp
# --- variable for now (a, b, c, d, e and f)
a<-max(quantity.new[["quantity"]])
b<-mean(quantity.new[["quantity"]])
c<-sd(quantity.new[["quantity"]])
d<-median(quantity.new[["quantity"]])
e<-min(quantity.new[["quantity"]])
f<-sum(quantity.new[["quantity"]])
# --- load our calculations into the data frame object
# --- just using "i" as an index to the data frame
i<-1
df[i,1]<-"Online"
df[i,2]<-a
df[i,3]<-b
df[i,4]<-c
df[i,5]<-d
df[i,6]<-e
df[i,7]<-f
# --- add headings/column names to our data frame object
names(df)<-c("group", "max", "mean", "sd", "median", "min", "sum")
# --- note: repeat the section of code here that creates a
# --- subset and calculates its points for all sale types
# --- display out finished summation model
df
以下是我们的总结模型数据框对象示例:
一个总结表格,例如我们之前创建的那种,通常无法回答你所有关于数据的问题,但实际上,它会提出更多的问题和假设供你进一步探究。统计分析的核心是提出下一个要问的问题。
汇总表帮助我们确定:
-
这数据中真的有任何重要的信息吗?
-
这个数据源可靠吗?
-
如果这些数据似乎支持我的假设,那么整体证据有多强?
-
这些信息(如总结的)真的对我的当前假设有意义吗?
-
这些数字意味着什么(暗示可能需要更多的分析和汇总)?
-
接下来可以采取什么行动?
-
数据的性质是什么?(将在下一节讨论。)
有多种 R 包(例如gridExtra
包)可供下载并安装,用于将格式化良好的数据框打印到纸上。读者值得花时间探索这些选项。
确定数据的性质
当谈到统计分析的目标时,人们通常会提到描述或确定数据源性质的过程。
确定某事的性质意味着对其进行理解。这个理解可以是简单的,也可以是复杂的。例如,我们能否确定数据源中每个变量或组件的类型?它们是定量的、比较性的,还是定性的?
使用本章前面提到的交易数据源,我们可以按类型识别一些变量,如下所示:
-
定量:数量
-
比较性:
sale_type
-
定性:
sales_region
-
分类:
product_name
更高级的统计分析旨在识别数据中的模式;例如,是否存在变量之间的关系,或者某些群体是否比其他群体更可能表现出某些特征。
探索数据中呈现的关系可能类似于在关系数据库中识别外键的想法,但在统计学中,组件或变量之间的关系基于相关性和因果关系。
此外,确定数据源的性质实际上也是对该数据源进行建模的过程。在建模过程中,通常会涉及提问,如下所示(旨在确立数据的性质):
-
什么?一些常见的示例(什么)包括收入、支出、运输、医院就诊、网站点击等。在本章使用的示例中,我们正在测量数量,即被移动的产品数量(销售)。
-
为什么?(为什么)通常取决于你项目的具体目标,这些目标可能会有很大差异。例如,我们可能想要追踪一个业务的增长、网站上的活动,或是某个选定产品或市场兴趣的演变。同样,在我们当前的交易数据示例中,我们可能希望识别表现过高或过低的
销售类型
,并确定新客户或回头客是否贡献更多或更少的销售? -
怎么做?通常会在一段时间内(也许是一年、一个月、一周等)并且通过其他相关测量,如产品、州、地区、经销商等,来进行。在我们的交易数据示例中,我们专注于按销售类型观察数量。
在本章关于数据分析的讨论开始时,我们创建了一个可视化,显示了前面提到的模型,即按月份的数量。接下来是该可视化:
通常,建模过程将包括多次迭代:观察、提出新问题、操作数据、创建新的可视化,并观察这些可视化结果,每次迭代都由前一次迭代的结果驱动。
例如,在查看之前的可视化(按月销售数量)之后,可能会出现新的问题,比如销售区域的总销售数量是多少。
可以使用类似 R 命令逻辑(如barplot
函数)来操作我们的数据并展示这些信息,如下所示:
# --- load our data into a data frame object
data.df<-data.frame(x)
# --- initialize some counters one for each sales region ID
R1<-0
R2<-0
R3<-0
R4<-0
R5<-0
# --- loop through the data and accumulate sale quantities
# --- for each sales region
for(i in 1:nrow(data.df))
{
MonthInData <-data.df[i,6]
if (MonthInData == '1') {R1 <- R1 + data.df[i,3]}
if (MonthInData == '2') {R2 <- R2 + data.df[i,3]}
if (MonthInData == '3') {R3 <- R3 + data.df[i,3]}
if (MonthInData == '4') {R4 <- R4 + data.df[i,3]}
if (MonthInData == '5') {R5 <- R5 + data.df[i,3]}
}
# --- generate our barplot from accumulated data
# --- in R1 through R5
barplot(c(R1, R2, R3, R4, R5), main="Sales Qty by Region", border = "dark blue", legend.text = c("1","2","3", "4", "5"), col = c("lightblue", "mistyrose","lightcyan", "Green", "grey"))
生成的可视化如下所示:
根据以前的可视化,当然可以提出更多问题并进行可视化:
-
按销售区域按月份或季度的数量分布如何?
-
按产品的总数量是多少?
-
按月、季度、产品等总返回量是多少?
-
等等!
描述数据性质的另一种方式是为其添加上下文或进行概述。无论如何,目标是通过可视化使数据使用者更好地理解数据。
另一个添加上下文或者建立数据性质的动机可能是为了从数据中获得新的视角。例如,我们可以添加比较,比如我们之前的销售类型
示例。
成功的统计分析
值得一提的是,在这一部分处理确保成功(或至少是有成效的)统计分析工作的关键点。
你可能会发现这些大多数都是常识性的概念,但也许有些不是。
-
尽快确定您的目标或目的。您需要知道胜利是什么,即驱动分析工作的问题或想法是什么。此外,您需要确保无论分析的驱动力是什么,都必须以某种方式可测量。必须早期确定这个度量或绩效指标。
-
确定关键的杠杆。这意味着一旦确定了您的目标及衡量达到这些目标的绩效方式,您还需要找出影响每个目标达成绩效的因素。
-
进行彻底的数据收集。通常情况下,数据越多越好,但在数量不足的情况下,始终要追求质量。
-
清理你的数据。确保你的数据以一致的方式进行清理,这样数据问题不会影响你的结论。
-
建模,建模和再建模你的数据。正如我们在前一节中提到的,建模推动建模。你对数据进行的建模越多,你就会提出和回答更多问题,并获得更好的结果。
-
花时间提升你的统计分析技能。持续演进你的经验和统计分析风格总是个好主意。改进的方式就是去做。另一种方法是重新调整手头可能有的数据,以磨练你的技能。
-
优化并重复。一如既往,你需要花时间进行标准化,遵循成熟的实践,使用模板,并测试和记录你的脚本和模型,这样你就可以一遍又一遍地重复使用你最好的努力。你会发现这段时间花得很值,即使是你更好的努力也会因使用而改善。最后,与他人分享你的工作!眼界越广,产品就会越好。
关于确保统计项目成功的一些有趣建议包括以下引用:
建议建立一个团队,使得那些拥有统计学高级学位的人专注于数据建模和预测,而团队中的其他成员-合格的基础设施工程师、软件开发人员和 ETL 专家-构建必要的数据收集基础设施、数据管道和数据产品,使得数据通过模型流动,并以报告和仪表板的形式向业务展示结果。 - G Shapira, 2017*
R 与统计分析
关于使用 R 进行统计分析、数据概要和为数据添加视角(建立上下文)的一点说明。
R 是一种易学、非常灵活,并且非常专注于统计计算的语言和环境,使其非常适合操纵、清洗、总结和生成概率统计(以及实际上使用数据创建可视化),因此它是进行概要、建立上下文和识别额外视角所需的练习的绝佳选择。
此外,以下是使用 R 进行任何类型数据或统计分析时的几个更多原因:
-
R 被大量学术统计学家使用,因此它不会被淘汰。
-
R 几乎是平台无关的;你开发的内容几乎可以在任何地方运行。
-
R 拥有出色的帮助资源。只需 Google 一下,你就会看到!
总结
在本章中,我们详细探讨了统计分析的目的和过程(数据分析的差异),创建了一个总结模型,并列出了成功进行统计分析的步骤。最后,我们强调了选择 R 作为首选统计分析工具的原因。
下一章将重点解释统计回归及其在数据科学中的重要性。我们将介绍在日常数据项目中使用各种统计回归方法,并概述开发人员如何在典型的数据开发项目中使用回归进行简单的预测和预报。
第六章:数据库的回归进展
在这一章中,我们将通过提供(数据)统计回归的定义来开始,然后继续讨论回归概念,并概述开发人员如何在典型的数据开发项目中使用最常见的回归技术进行预测和预报。
在本章中,我们将信息组织成以下几个领域:
-
统计回归简介
-
识别回归使用机会的方法(在数据项目中)
-
R 与统计回归
-
一个工作示例
引入统计回归
如承诺所说,让我们从这一章开始,提供一个关于统计回归的清晰解释。
初步了解,统计回归也常常被称为回归分析,它是估计变量之间关系的一个过程。 这个过程包含了多种用于建模和分析变量的技术,重点是因变量与一个(或多个)自变量(或预测变量)之间的关系。
具体来说,回归分析是指通过识别和理解一个因变量(依赖于其他因素的变量)如何随着任何一个自变量(独立于其他变量且不受其影响的变量)的变化而变化的工作,前提是其他自变量保持不变。
一个简单的例子可能是,营销总支出(一个自变量示例)如何影响一段时间内的总销售额(一个因变量示例)(真的是越多的营销就等于更高的销售额吗?),或者也许存在一个关联,即总的营销支出(自变量),产品价格的折扣(另一个自变量),以及销售额(因变量)之间?
记住这个关键点,回归分析用于理解在所有自变量中,哪些与因变量有关,而不仅仅是这些变量之间的关系。此外,推断因果关系(自变量与因变量之间)是一个重要目标。然而,这可能导致错觉或虚假的关系,因此建议小心!
总的来说,回归分析可以被视为在观察自变量的条件下,估计因变量的期望值,也就是说,尝试预测当自变量设置为某些特定值时,因变量的平均值。我称之为杠杆效应——这意味着当一个组件的值增加或减少时,它会直接影响至少一个其他(变量)的值。
回归分析的另一个目标是建立位置参数或分布的分位数。换句话说,这个思想是确定可能作为临界值的值,用于划分概率分布值的范围。
你会发现回归分析是一个非常有用的预测和预测工具(不仅仅是复杂的机器学习应用)。稍后我们会探索一些现实世界的例子,但现在让我们先看一下这个过程的一些技术。
回归的技术与方法
你会发现,已经开发并接受了多种进行回归分析的技术。
一些研究可能会展示以下几种顶级技术:
-
线性
-
逻辑回归
-
多项式
-
步骤法
-
岭
-
套索回归
以下是每种方法的简短介绍:
-
线性回归:线性回归是最基本的回归类型,通常用于预测分析项目。事实上,当你使用单一预测变量时,我们称之为简单线性回归;如果有多个预测变量,我们称之为多重线性回归。简而言之,线性回归使用线性预测函数,其值是从模型中的数据估算出来的。
-
逻辑回归:逻辑回归是一种回归模型,其中因变量是分类变量。这意味着该变量只有两个可能的值,例如通过/不通过、胜/败、生死、健康/生病。如果因变量有两个以上的可能值,可以使用各种修改版的逻辑回归技术,例如多项式逻辑回归、有序逻辑回归等。
-
多项式回归:当我们谈到多项式回归时,这项技术的重点是将自变量与因变量之间的关系建模为 n^(次)方多项式。
- 多项式回归被认为是多重线性回归的一个特例。通过对基线预测变量进行多项式展开得到的预测变量被称为交互特征。
-
逐步回归:逐步回归是一种技术,它使用某种自动化程序不断执行一步逻辑,即在每一步中,根据预先指定的标准,考虑将某个变量添加到或从自变量集中去除。
-
岭回归:通常,预测变量被认为是相互关联的。当这种情况发生时,某个变量的回归系数取决于其他哪些预测变量被包括在模型中,哪些被排除在外。岭回归是一种技术,通过向所选变量添加一个小的偏差因子来改善这种情况。因此,岭回归实际上被认为是一种缓解预测变量之间多重共线性的补救措施。
-
Lasso 回归:Lasso(最小绝对收缩和选择算子)回归是一种既进行预测变量选择,又进行正则化的技术,目的是提高预测准确性和结果的可解释性。
选择你的技术
除了上述回归技术外,还有许多其他方法需要考虑,未来可能还会有更多新的方法。面对这么多选项,选择适合你数据和项目的技术非常重要。
选择回归方法不仅仅是选择正确的回归方法,更重要的是选择最有效的回归方法。
通常,你会使用数据来确定将使用的回归方法。首先,你需要为你的数据建立统计资料或特征。在这个过程中,你需要识别并理解不同变量的重要性,它们之间的关系、系数符号,以及它们的影响。
总的来说,以下是一些关于选择合适回归方法的一般性建议:
-
模仿他人已经成功使用的方法。做足研究。将其他项目的成果融入到你的项目中。不要重新发明轮子。而且,即使观察到的方法并不完全适用,也许通过一些简单的调整,它会成为一个不错的选择。
-
尽量保持方法简单。许多研究表明,简单的模型通常会产生更好的预测结果。从简单开始,只有在必要时才让模型变得更加复杂。你使模型更复杂的可能性越大,就越有可能是将模型专门调整为适应你的数据集,这会导致模型的泛化能力下降。
-
检查你的工作。当你评估方法时,检查残差图(本章接下来的部分会讲到更多内容),因为它们可以帮助你避免不充分的模型,并调整模型以获得更好的结果。
-
利用你的领域专业知识。没有任何统计方法能像你一样理解底层过程或领域知识。你的知识是关键部分,也是最可靠的确定最佳回归方法的方式。
它是否拟合?
在选择了一个你认为适合你数据的模型(也就是确定该方法最适合)之后,你需要验证你的选择,也就是确定其拟合效果。
拟合良好的回归模型会使预测值接近观察到的数据值。
如果没有信息丰富的预测变量,通常会使用均值模型(该模型对每个预测值使用均值)。因此,拟合的回归模型应该比均值模型的拟合效果更好。
作为数据科学家,你需要仔细审视决定系数,测量估计的标准误差,分析回归参数的显著性和置信区间(稍后在本章中会详细讨论这些内容)。
记住,回归模型拟合得越好,结果的精度通常就越高,或者说结果就越好。
已经证明,简单模型能够产生更精确的结果!在选择方法或技术时,始终记住这一点,甚至在问题可能很复杂时,也不一定非得采用复杂的回归方法。
确定统计回归的机会
典型的统计分析工作,通常会成为正式的统计项目,首先从确定一个目标开始,最终确定达到目标的正确方法。
流行的数据科学观点认为,确定一个目标即是确立统计分析的目的,然后将目的分为三个领域:
-
总结数据(也叫构建数据概况)
-
揭示并探索数据中变量之间的关系
-
测试差异的显著性(在数据中的变量或组之间)
总结数据
如果你的统计目标是总结数据,你将生成描述性统计量,如均值、标准差、方差等。
探索关系
如果你的统计目标是寻找并了解数据中的关系,首先要检查数据是否具有某种形式,换句话说,问问自己:你的数据是围绕频率还是测量展开的?从那里开始,预测变量的数量将告诉你应该使用哪种回归(或其他)方法来进行项目分析。
测试差异的显著性
如果你的统计目标涉及测试数据中发现的差异(组之间),你首先需要确定这些组以及组的数量。数据分析涉及单一组(感兴趣的)的数据,通过与均值比较来加以利用,而多组数据则可以使用组的数量来确定应考虑哪种预测方法。
项目盈利能力
作为一个实际例子,假设有一个咨询服务组织,它收集了关于其项目工作的时间数据。该组织可能被雇佣来领导各种规模和努力水平的技术或商业相关项目。每个项目都有费用和收入。有些项目是盈利的,有些则不是。公司希望识别哪些变量(如果有的话)可以预测项目的盈利能力,换句话说,哪些变量(特别是哪些)是因变量(在此案例中为盈利能力)的显著预测因子?
检查数据时,我们会看到一份良好的变量和测量的列表,其中一些如下所示:
-
分配给项目的顾问人数 全职 (FT)
-
分配给项目的顾问人数 兼职 (PT)
-
分配给项目的分包商人数(全职或兼职)
-
分配给项目全职的客户资源人数
-
分配给项目的客户资源数量(兼职)
-
与项目核心技术的经验年数
-
总项目管理小时数
-
总开发小时数
-
每小时计费率
-
总计费小时数
-
项目中使用的技术数量
-
项目类型(时间与材料,限制不超过或人员增补)等等
一般而言,当数据科学家使用回归分析时,他或她希望回答以下三个问题:
-
一组预测变量能否很好地预测结果变量?在我们项目盈利性的例子中,分配给项目的全职顾问人数是否能够很好地预测盈利能力?
-
哪些变量(特别是)是因变量的重要预测因子?再以我们项目盈利性的例子来看,我们能否通过全职顾问分配到项目中的人数,或许是总项目管理小时数,来确定一个显著的预测因子?
-
回归方程是什么(即某些变量对其他变量的估计关系或影响),它展示了如何使用一组预测变量来预测结果?在我们项目盈利性的例子中,回归方程是这样的么?
我们的项目盈利性示例看起来可以成为回归分析的合理候选者。
在本章的下一个部分,我们将尝试为项目数据建立一个概况,并使用合适的回归技术来建立它。然后,检查变量之间的关系,并希望基于选定的预测变量预测项目的盈利能力。
R 和统计回归
在我们直接进入建模之前,让我们先花点时间验证 R 作为我们的统计建模工具的使用。
R 是一个开源的统计环境和强大的编程语言,继续成为统计建模最受欢迎的选择之一。R 是在 S 和 S-Plus 的基础上开发的,它有着不断增长的广泛受众,并由 R 核心开发团队(一个由志愿开发者组成的国际团队)良好维护。
R 和许多相关资源可以很容易地在线找到,并且有详细的说明,指导如何下载软件、附带的包以及其他文档来源。此外,世界各地的人们为 R 编写了大量专门的例程,并作为 R 包免费提供。
由于 R 是一种编程语言,它为你的项目带来了编程的强大功能,但它确实需要一定的工具使用经验。幸运的是,它提供了一个图形用户界面(GUI),使操作更加简便,并允许你从其他来源和项目中复制粘贴。
一个实际的例子
现在让我们回到项目盈利性的现实例子!
我们知道,我们的咨询服务组织的项目结果数据描述了所有项目工作的结果。这些数据中有 100 个项目(或观察值),包含了两个变量:账单小时数和利润。第一个变量不言自明:它是该项目向客户收取的总小时数。第二个是一个美元金额,表示从客户收取的收入,扣除所有费用(与项目相关的费用)后的净收入。
我们知道,每个项目都有费用和收入,而一些项目是盈利的,另一些则不是。此外,即使是盈利的项目,其盈利水平也差异巨大。再次强调,公司希望识别哪些变量(如果有的话)可能用于预测项目的盈利能力。
让我们开始我们的统计分析吧!
确定数据特征
在尝试使用我们的项目结果数据建立回归模型之前,通常会先分析数据,识别关键变量。通常,你会通过创建各种数据可视化图表(我们将在本节后续部分逐步演示)来理解数据中变量或群体之间的因果关系。
在统计学中,这些任务通常被称为执行图形分析和相关性研究。
图形分析
在我们的统计分析示例中,我们希望构建一个简单的回归模型,通过建立与账单小时(向客户收取的小时数)(hours billed)之间的统计显著线性关系,来预测项目的盈利能力(利润)。因此,我们可以通过多种方式绘制数据,开始我们的图形分析。
通常,对于每个自变量(预测变量),应绘制以下图表以可视化以下行为:
-
散点图:用于可视化预测变量与响应变量之间的线性关系。
-
箱线图:用于识别变量中的任何异常值。预测变量中的异常值可能会极大地影响预测,因为它们可以轻易地改变最佳拟合线的方向/斜率。
-
密度图:用于查看预测变量的分布。理想情况下,最好接近正态分布(钟形曲线),而不是向左或向右偏斜。
散点图可以帮助可视化因变量(响应变量)与自变量(预测变量)之间的任何线性关系。
理想情况下,如果你观察多个预测变量,则应为每个预测变量与响应变量之间绘制散点图。
以下是使用我们项目结果数据中的HoursBilled
和Profit
变量,创建散点图可视化的简单 R 命令:
# --- load our project results data
MyData <- read.csv(file="c:/Worker/HoursBilledProfit.csv", header=TRUE, sep=",")
# --- build our scatter plot on the relationship between our
# --- variables
scatter.smooth(x=MyData$HoursBilled, y=MyData$Profit, main="Hours Billed vs. Profit") # scatterplot
以下是我们生成的散点图:
小时计费与利润的散点图以及前述图表中的平滑线表明,项目的总小时计费与利润变量之间最初是线性增加后再减少的关系。
请注意,线性回归的一个基本假设是响应变量与预测变量之间的关系是线性和加性的,因此这些数据最初看起来符合这一假设。
我们的下一步是查看数据中是否存在任何离群值。位于 1.5 * 四分位距(1.5 * IQR)之外的数据点被视为离群值,其中 IQR 是计算为该变量第 25 百分位和第 75 百分位值之间的距离。
在数据的统计分析中,箱线图通常用于通过四分位数图形化地表示一组数值数据。这些可视化图形可能还会有从箱体延伸出的垂直线(一些数据科学家称这些线为“胡须”),表示上下四分位数之外的变异性。箱线图非常适合用于识别离群值。
以下 R 命令用于生成箱线图:
# --- load our project results data
MyData <- read.csv(file="c:/Worker/HoursBilledProfit.csv", header=TRUE, sep=",")
par(mfrow=c(1, 2)) # divide graph area in 2 columns
# --- box plot for hours billed
boxplot(MyData$HoursBilled, main="Hours Billed", sub=paste("Outlier rows: ", boxplot.stats(MyData$HoursBilled)$out))
# --- box plot for Profit
boxplot(MyData$Profit, main="Profit", sub=paste("Outlier rows: ", boxplot.stats(MyData$Profit)$out))
以下是从我们项目结果数据生成的离群值箱线图:
你可以注意到在利润变量中识别出的离群值(位于前述图形的右侧)。离群值行:3648270对应于我们文件中的一个数据点:
最后,可以创建一个密度图来查看我们的响应变量(ProjectID
,HoursBilled
和Profit
)与正态分布的接近程度。为此,我们可以使用以下 R 命令:
# --- load our project results data
MyData <- read.csv(file="c:/Worker/HoursBilledProfit.csv", header=TRUE, sep=",")
library(e1071)
# --- divide graph area in 2 columns
par(mfrow=c(1, 2))
# --- density plot for profit
plot(density(MyData$Profit), main="Density Plot: Profit", ylab="Frequency", sub=paste("Skewness:", round(e1071::skewness(MyData$Profit), 2)))
polygon(density(MyData$Profit), col="red")
# --- density plot for hours billed
plot(density(MyData$HoursBilled), main="Density Plot: Hours Billed", ylab="Frequency", sub=paste("Skewness:", round(e1071::skewness(MyData$HoursBilled), 2)))
polygon(density(MyData$HoursBilled), col="red")
以下是密度图:
那么,我们是否能看到项目的小时计费和项目利润之间的相关关系呢?
我们确认这一点的一种方法是建立变量之间的相关性。相关性表示成对出现的两个变量之间的线性依赖程度,就像我们认为小时计费和(项目)利润之间的关系一样。
如果数据科学家发现利润随着每个项目小时计费的增加而增加,那么这两个变量之间会有很高的正相关性,因此,它们之间的相关性会接近 1。相反,对于反向关系,相关性将接近-1。
值越接近 0,表示变量之间的关系越弱。低相关性(-0.2 < x < 0.2)可能表明响应变量(Y)的变化大部分无法通过预测变量(X)来解释,在这种情况下,我们可能需要寻找更好的解释变量。
R 编程语言再次为我们提供了一种简便的方法来实现这一点:cor
函数,它可以确定我们两个变量之间的相关性:
根据前面的输出,我们可以确定实际上没有理由相信,随着项目的账单小时数的增加,盈利能力也会增加。鉴于此,我们应当考虑其他可能的预测变量。
为了节省时间(我们想继续进行回归模型的构建),我们不打算重新开始,而是根据经验猜测,或许总项目管理小时数是一个良好的项目盈利预测变量。让我们尝试使用这个变量运行相同的cor
函数:
正如前面计算出的相关性所示(通过使用 R 函数cor
生成),变量ProjectManagement
似乎与项目盈利能力具有更高的正相关性(相比账单小时数)。
通常,我们会花时间重新构建我们在本节中使用此数据所创建的可视化图形(例如以下的散点图),但为了节省时间,我们将继续前进:
从我们的散点图中可以看出:利润管理与利润之间存在平滑的线性回归关系。随着项目管理时间的增加,项目的整体盈利能力也随之提高!
继续吧!
现在,我们已经通过散点图(以及前一节中的其他示例)等可视化图表建立了(看似)良好的线性关系,并通过计算出正相关性(使用 R 函数cor
),我们可以尝试构建实际的线性回归模型。
再次,R 为我们提供了一个相关函数——lm()
。lm()
函数有两个主要参数:
-
公式(一个公式类的对象)
-
数据(通常是一个
data.frame
)
以下是我们可以用来生成 R 回归模型的 R 命令:
# --- build linear regression model on all of our
# --- project results data
alinearMod <- lm(ProjectManagement ~ Profit, data=MyData)
print(alinearMod)
以下是构建我们模型的结果:
使用之前的 R 命令构建线性模型后,我们已经建立了预测变量(项目管理小时数)与响应变量(项目的盈利能力)之间的数学公式关系,其中项目管理(ProjectManagement)是Profit
的函数。
我们可以使用前面输出中的系数(Intercept: 6.180
和 Profit: 1.629
)来创建公式:
projectmanagement = −6.180 + 1.629 * profit
利用我们的线性模型和公式,如果知道对应的项目管理总小时数,我们就可以预测项目的盈利值。令人兴奋!
尽管我们已经建立了预测(项目盈利性)的手段,但请记住,在使用任何回归模型之前,必须确保其具有统计学显著性。
使用我们的线性模型进行预测
我们刚刚使用 R 命令创建了一个线性回归模型,并使用了所有的项目结果数据。在实际应用中,人们通常会使用所谓的80:20 样本法则来分割数据。这意味着 80%的数据将用于训练模型,而剩下的 20%可以用于测试和验证。
现在让我们来经历这个过程。
第 1 步:分割数据
我们可以读取项目结果数据,然后使用 R 的 sample 函数将数据分割成两个部分(分别为trainingData
和testData
),如下所示的 R 命令:
# --- first load our project results data
# --- from our CSV file into the object MyData
MyData <- read.csv(file="c:/Worker/ProjectManagementProfit.csv", header=TRUE, sep=",")
# --- next we are setting the ""sample seed""
# --- to reproduce results of random sampling
set.seed(100)
trainingRowIndex <- sample(1:nrow(MyData), 0.8*nrow(MyData))
# --- create our ""chunk"" of
# --- model training data
trainingData <- MyData [trainingRowIndex,]
# --- create our ""chunk of
# --- test data
testData <- MyData [-trainingRowIndex,]
第 2 步:在训练数据上创建模型
就像我们在本章前面所做的那样,我们可以使用 R 函数 lm 来使用trainingData
数据块创建回归模型:
# --- Build the model on training data
lmMod <- lm(ProjectManagement ~ Profit, data=trainingData)
第 3 步:预测测试数据的预期利润
然后,我们使用 R 函数 predict 来生成项目预测,如下所示的 R 命令:
# --- predict project profitability
ProfitPred <- predict(lmMod, testData)
以下是前面 R 命令生成的输出:
第 4 步:回顾模型
也许我们过程中的最后一步是对模型进行总结并审查其统计显著性。
我们可以使用 R 函数 summary:
# --- generate the summary of the model
summary (lmMod)
这将生成以下输出:
从之前生成的输出中,我们可以看到我们的模型预测器的p
值在视觉上被解读为显著,通过行末的显著性星号(已标出)可以看到,因此我们知道我们的模型是统计显著的。
第 4 步:准确性与误差
我们可以通过实际值(实际项目利润总额)与模型预测值(利润值)之间的简单关联来测试我们项目利润预测的准确性。
如下所示,以下 R 命令再次使用了 R 函数cor
:
高度的相关性精度意味着实际值和预测值具有相似的方向性变化,即当实际值增加时,预测值也会增加,反之亦然;或者可以假设当一个项目的总项目管理时间增加或减少时,项目的盈利性也会以相同的方式增加或减少!
摘要
在本章中,我们介绍了统计回归,概述了最常见的回归方法,并提供了在特定统计项目中选择校正方法的一些建议。此外,我们还提到了如何识别使用统计回归的机会,并讨论了数据总结、探索关系以及检验差异的显著性。
最后,我们通过一个实际的线性回归模型示例,展示了如何预测项目盈利能力。
下一章将向开发者介绍统计正则化的概念,帮助理解统计正则化是什么以及它的重要性,并使开发者对各种统计正则化方法感到熟悉。
第七章:数据库改进的正则化
在本章中,我们将介绍统计正则化的概念,以改善数据模型,并帮助理解统计正则化是什么、为什么它很重要,并且让您对各种统计正则化方法感到熟悉。
本章中,我们将信息组织成以下几个方面:
-
统计正则化
-
使用数据理解统计正则化
-
改进数据或数据模型
-
使用 R 进行统计正则化
统计正则化
那么,什么是统计正则化呢?
在正则化中,无论我们讨论的是数学、统计学还是机器学习,本质上是在讨论通过添加额外信息来解决问题的过程。
正则化一词被描述为管理复杂系统的抽象概念(根据一套规则或公认的概念)。这些规则定义了如何添加或修改值,以满足要求或解决问题。
添加或修改值是否意味着改变数据?(本章稍后将深入研究这一问题。)
各种统计正则化方法
在统计学界,最流行的统计正则化方法可能包括以下几种:
-
脊
-
套索
-
最小角度
脊
脊回归是一种统计技术,通常用于分析回归数据或模型,这些数据或模型存在一个被称为多重共线性的问题。当出现多重共线性时,估计值可能是无偏的,但其方差通常很大,且远离真实值。此技术通过向回归估计添加一定的偏差来减少标准误差(以产生更可靠的估计值)。
多重共线性是统计学中的一种现象,在这种情况下,多元回归模型中的一个预测因子可以通过其他预测因子线性地预测,并且预测准确度较高。
套索
最小绝对收缩和选择算子(Lasso)是一种统计技术,既执行变量选择,又进行正则化,以提高模型中的预测准确性。
在统计模型中选择或挑选变量的过程显然会导致变量数量的减少,这也被称为变量收缩。
最小角度
最小角度回归(LARS)是一种统计技术,数据科学家在处理高维数据时会使用此技术。如果怀疑某响应变量是由特定的预测因子子集决定的,那么 LARS 技术可以帮助确定应将哪些变量纳入回归过程。
正则化机会
那么,作为数据科学家,您何时会考虑使用任何类型的正则化方法?
事实上,没有绝对的规则规定何时使用正则化;然而,有一些指标可以观察,当这些指标出现时,你应该考虑使用正则化。例如:
-
如果数据中包含较高的变量计数
-
如果数据中观测值的数量与变量数量的比率很低
在第六章,从数据库发展到数据库回归(统计回归),我们回顾了一些包含咨询项目结果的示例数据。在该示例中,我们探讨了项目的总开票小时数、项目管理的总小时数和项目假定的盈利能力之间的关系。
仔细观察相同的数据,也许我们现在会看到更多的变量,例如:
-
分配到项目的全职顾问数量
-
分配到项目的兼职顾问数量
-
分配到项目的分包商数量(全职或兼职)
-
分配到项目的全职客户资源数量
-
分配到项目的兼职客户资源数量
-
分配到项目的本地资源数量
-
在项目核心技术方面的经验年数
-
总项目管理小时数
-
总开发小时数
-
每小时账单费率
-
总开票小时数
-
项目中使用的技术数量
-
项目风格(时间和材料、不可超出预算或人员增补)
在这里,我们可以看到超过十二个可能的自变量或预测变量——这显然是一个可管理的数量——特别是考虑到文件中的观测值(记录)数量超过 100 个(变量与观测值的比例约为 12%)。
自变量(或实验变量或预测变量)是在模型中被操控的变量,目的是观察它对因变量或结果变量的影响。
当数据科学家谈到高变量计数时,实际上他们指的是过多的变量数,或者当变量数接近观测数时(在这个例子中不是如此),假设我们在只有 100 个观测值的数据中有超过 50 个可能的预测变量?这就是所谓的过于复杂的模型,并需要考虑使用常见的正则化方法。
什么构成过于复杂的模型通常是一个争议话题,且往往根据数据和统计模型的目标不同而有所不同。
经验证明,当模型过于复杂时,模型可能会拟合数据,但预测性能较差(最终目标是预测)。当这种情况发生时,数据科学家会认识到过拟合。
正则化是数据科学家用来避免或解决过拟合问题的统计技术。正则化的基本思想是,过拟合数据的模型是复杂的统计模型,这些模型例如具有过多的参数。
正则化的其他已知应用包括以下内容:
-
涉及高共线性的实例
-
当项目目标是稀疏解时
-
考虑高维数据中的变量分组
-
分类
共线性
共线性一词描述了统计学中的一种情况,即选定的预测变量可以通过其他变量线性预测,且具有相当高的准确度。
线性预测是一种程序,其中根据先前样本的线性函数估算变量的未来值。
这通常会导致数据的微小变化产生关于个别预测变量的不可靠结果。也就是说,具有共线性预测变量的多元回归模型可以指示整个预测变量组如何预测结果变量,但可能无法提供关于任何单个预测变量的有效结果,也无法指示哪些预测变量在与其他变量的关系中是冗余的。
稀疏解
稀疏解或近似解是一个稀疏向量,它大致解决了一组方程。寻找稀疏近似解的技术在图像处理和文档分析等应用中得到广泛应用。
你应该记得,向量是由相同基本类型的数据点组成的序列。向量的成员正式称为分量。
高维数据
高维统计学是研究数据维度大于经典多元分析(MVA)中考虑的维度的数据的学科。
在统计研究中,多元随机变量(或随机向量)是一个由变量组成的列表,每个变量的值都未知。多元分析(MVA)被定义为研究这一情况的学科。
高维统计学依赖于随机向量理论。在许多应用中,数据向量的维度可能大于样本大小。
分类
分类是根据已知类别成员的数据训练集,识别新观察值属于哪些类别或组的过程。
正则化是一种常见的统计技术,用于解决上述(以及其他)情境。在下一节中,我们将介绍每种情境的一些简单示例。
使用数据理解统计学正则化
变量选择是统计学领域中的一个重要过程,因为它旨在通过消除与输出无关的变量,使模型更易理解、更易训练,并避免误关联。
这(变量选择)是解决过拟合问题的一个可能方法。通常,我们不期望模型完全拟合我们的数据;实际上,过拟合问题通常意味着如果我们过度拟合训练或测试数据,它可能会对我们预测模型在未见数据上的准确性造成不利影响。
与其使用变量选择,不如说正则化过程是一种减少数据中变量数量的替代方法,用来解决过拟合问题,本质上是通过在模型训练过程中引入有意的偏差或约束(希望)防止我们的系数出现非常高的方差。
当参数的数量(在总体中)被认为非常大——尤其是与可用观察值的数量相比——线性回归往往允许少数观察值的微小变化导致系数发生剧烈变化(或者,如我们所说,表现出非常高的方差)。
岭回归是一种统计方法,通过对模型的回归估计引入受控偏差(通过或使用约束),但它在减少模型方差方面非常有效。
岭回归有时在数据科学社区中被称为一种惩罚回归技术。
有许多不同的 R 函数和包实现了岭回归,例如来自MASS
包的lm.ridge()
函数和来自genridge
包的ridge()
函数。
你可能熟悉MASS
R 包,但可能不太了解genridge
。genridge
包引入了岭回归和相关方法中使用的标准单变量岭迹图的推广,并值得进一步研究。
在第六章《从数据库进阶到数据库回归》中,我们提出了一个例子,使用一个咨询公司项目结果的数据创建了一个线性回归模型,旨在预测项目的盈利能力。我们使用了 R 函数:lm()
,该函数接受两个主要参数:formula
(一个公式类的对象)和data
(通常是一个data.frame
),如下所示的 R 代码:
# --- build linear regression model using all the
# --- project results data
alinearMod <- lm(ProjectManagement ~ Profit, data=MyData)
在本章中,我们将使用lm.ridge()
函数,尝试通过岭回归来合理地拟合前述线性模型。前面的代码使用我们的 R 对象MyData
,并通过ProjectManagment
变量来预测Profit
,从而生成了一个线性模型。
lm.ridge
函数使用以下语法:
lm.ridge(formula, data, subset, na.action, lambda = 0, model = FALSE,
x = FALSE, y = FALSE, contrasts = NULL, ...)
参数在此列出,供后续参考:
-
formula
:这是一个回归模型的公式表达式,形式为response ~ predictors
-
data
:这是一个可选的数据框,用来解释公式中出现的变量 -
subset
:这是一个表达式,用于指定在拟合过程中应使用数据的哪些行子集。默认情况下,所有观察值都会被包含在内。 -
na.action
:这是一个函数,用于过滤缺失数据 -
lambda
:这是一个标量或向量,表示岭常数 -
model
:是否返回模型框架? -
x
:是否返回设计矩阵? -
y
:是否返回响应值? -
contrasts
:一组对比列表,用于公式中的某些或所有因子项
lambda
这个术语(在此,指的是 lm.ridge
函数中的一个参数)通常定义为在一组依赖变量的组合上对组均值的比较。
为了设定我们下一个示例,让我们回顾一下,我们的项目数据的变量与观测值的比例为 12%。假设我们已经获得了一个新的数据文件,这个文件只有 50 个观测值。现在,我们的变量与观测值的比例上升到 24%。
那么,只有 12 个观测值的文件呢?再假设我们被告知,管理层认为这 12 个观测值基于关键的高可见性项目,因此不愿意提供更多的数据样本给数据科学家(至少目前是这样)?对这些数据建模是否还有意义?结果会有任何价值吗?
通常来说,人们会说回归模型中变量越多,模型就越灵活,或者说它会变得更加灵活。很可能,这种类型的模型会通过拟合训练数据中的随机波动来获得较低的误差,但结果或结论并不能代表数据中变量的真实潜在分布,换句话说,当该模型在从相同分布中提取的未来数据上运行时,性能会较差。(如果我们关于项目盈利能力的预测是基于错误的逻辑,管理层可不会高兴!)
在上述情境下,数据科学家应该如何处理?好吧,尽管数据点少于变量时,确实有可能拟合出好的模型,但这必须非常小心地进行。
通常情况下,当数据中的变量数量超过观测值时,结果可能看起来会表现良好,但正如我们之前提到的,解决方案可能在训练数据上取得有利结果,甚至是零误差。这样的模型肯定会在实际数据上发生过拟合,因为它对于训练数据的数量来说过于灵活。(这种情况称为病态或欠定。)
这个问题通常通过仔细设定限制或施加约束来解决,可以通过显式的方式或逻辑过程来实现。模型成为了在很好地拟合数据和满足这些设定的限制或约束之间的权衡。岭回归约束或惩罚数据参数,并通过限制模型的灵活性来提高预测性能,从而减少过拟合的倾向。
然而,简单地设定限制或施加约束并不意味着得到的解决方案会是好的或可接受的。只有当这些约束真正适合当前问题或目标时,它们才会产生好的解决方案。
回到我们在本节前面提到的 lm.ridge
函数。与 lm
函数的使用稍有不同,我们可以通过以下的使用示例看到其中的差异。
和大多数示例一样,我们可以利用runif
和rnom
这两个 R 函数来生成一些随机数数据集(用于插图),我们可以看到执行lm
和lm.ridge
之间的区别:
# -- create a uniform random number series as X1, X2 and X3
# --- using runif
x1 <- runif(n=20)
x2 <- runif(n=20)
x3 <- runif(n=20)
# --- Create a new variable from x1 and x2
x3c <- 10*x1 + x3
# --- create a random number
ep <- rnorm(n=20)
y <- x1 + x2 + ep
既然我们知道了我们要探索的内容(例如,估计线性回归模型中的参数),我们就可以在创建测试数据时进行一些自由发挥。以下是一个使用我们三个人造变量生成线性回归模型的 R 代码示例:
# --- using the R lm function to create an ordinary least squares (OLS) # -- fit of 3-variable model using x3 as an independent x3 variable
ols <- lm(y~ x1 + x2 + x3)
summary(ols)
以下是从前面的代码生成的输出:
现在,让我们继续。
使用我们相同的虚拟示例数据和类似的思路,我们可以使用 R 函数lm.ridge
来尝试通过岭回归拟合线性模型:
# --- Fit model using ridge regression using independent variables
ridge <- lm.ridge (y ~ x1 + x2 + x3, lambda = seq(0, .1, .001))
summary(ridge)
以下是生成的输出(请注意summary
函数生成的输出差异):
你会发现,summary
函数在使用线性回归模型时与在使用岭回归方法的模型中生成的输出不同。然而,有多种包可以生成岭回归模型的充分输出。
改善数据或数据模型
有多种参数可用于改善数据或数据模型。在本节中,我们将研究其中的一些。
数据科学家可以采用许多其他可接受的或至少是广为人知的方法或策略,以期改进统计模型(除了正则化之外),值得花些时间提到其中一些最流行的方法:
-
简化
-
相关性
-
速度
-
转换
-
系数的变化
-
因果推断
-
回到正则化
-
可靠性
简化
第一个可能只是常识。一个简单的模型更容易解释和理解。算法在简单模型上运行得更高效,允许数据科学家有更多的迭代次数以及更多的时间来评估结果。
然而,请记住,更复杂的模型在某种程度上更具可信性,因此要小心过度简化。寻找复杂与简单之间正确平衡的方法可以双向进行;可以从简单开始并逐步增加复杂性,或者更常见的是,从复杂开始,然后逐步剔除模型中的内容,进行测试、评估并重复,直到成功理解(拟合)过程。
相关性
这一点也似乎显而易见。换句话说,不要浪费时间在统计噪声上。使用常见的统计回归包,你将有可视化图(如分位数-分位数图、影响图、箱形图等)来研究并理解。花时间从模型或数据中剔除无关项将带来回报。关键是能够识别什么是相关的。
速度
数据科学家能够更快地拟合模型,就能评估和理解更多的模型(和数据)(这就是最终目标!)。模型优化的方式和手段可能是昂贵的——无论是在时间上还是在专业技能上——并且可以集中在模型、数据或两者上。
变量变换
这是一种可能对模型产生重大影响的方法,但并非没有风险。变量的转换可以创建看似合理的模型(然后可以拟合并与数据进行比较),并且包括所有相关信息,但如果做得不理性,可能会引入偏差并导致错误的结果。
系数的变异
测试系数,以确定某个系数是否应该随组别变化,以及变化的估计规模,是改善模型的可行方法。非常小的变动系数(在不同类别之间)有可能被排除在考虑之外。
因果推断
你可能会想设置一个大的回归模型来回答模型或数据中存在的多个因果问题;然而,在观察性设置中(包括在某些感兴趣的条件下的实验),这种方法可能存在偏差的风险。关键是,不要对任何感知到的关系(或系数)做出假设,尤其是不要假设一个系数可以因果解释。然而,因果推断可以在适当的情况下作为一种方法,用来改善统计模型。
回到正则化
直接切入主题——正则化的核心主题是试图改善统计模型或方法的结果或性能。换句话说,就是通过直接和间接的观察来改进学习过程(当然是通过数据)。
试图从有限的数据集获取知识或学习(也称为经验学习)被认为是一个欠定问题,因为通常情况下,它是试图推断一个函数x {\displaystyle x}
,仅给定一些数据观察的例子。
改进统计模型的另一种可能方法是,在模型训练过程中使用加法平滑(也称为拉普拉斯平滑)。这是一种正则化形式,通过在模型训练过程中将一个固定的数字添加到所有特征和类别组合的计数中来工作。
有一种普遍的观点认为,加法平滑在一些检索任务中(如基于语言模型的应用)比其他概率平滑方法更有效。
正则化从根本上来说是通过引入额外的信息、故意的偏差或约束来解决一个不适定的问题——防止系数取大值——这是一种试图收缩系数的方法,也称为收缩方法。引入的信息通常表现为对复杂度的惩罚,例如平滑性限制或向量空间范数的约束。换句话说,正则化 A 的作用正如其名称所示,它调节你可以在统计模型或其数据中如何以及多大程度上改变一个参数。没错,实际上,你可以改变数据本身!
什么时候改变数据的值是合理的?
统计学界认为,正则化的理论依据可能是它试图施加一种信念:在多个竞争假设中,假设最少的那一个将是最有效的(因此应当是被选中并使用的)。这种信念被严格称为奥卡姆剃刀(或称“简约法则”)。
可靠性
是否应该总是在统计模型中尝试实施正则化方法呢?(当然,我们指的是本章“正则化机会”部分中所讨论的那些情况。)它是否总能改善模型或数据集?
在考虑如何回答这个问题之前,记住正则化不会改善算法最初用来学习模型参数(特征权重)的数据集上的表现。然而,它可以改善模型的泛化性能(即在新的、未见过的数据上的表现,这正是你所追求的)。
可以把在统计模型中使用正则化看作是对过拟合的反制措施,类似于加入偏差;但另一方面,加入过多的偏差几乎总是导致欠拟合,模型表现会很差。
答:正则化并不总是有效,可能导致模型表现不佳(甚至比之前更差!)。《Python 机器学习》一书的作者 S. Raschka 提出了一个有趣的评论:
从直观角度来看,可以将正则化理解为对模型复杂度的惩罚。增加正则化强度会惩罚大权重系数。因此,你的目标是防止模型捕捉到异常或噪声,并确保模型能很好地泛化到新的、未见过的数据。
使用 R 进行统计正则化
有许多不同的函数和包实现了岭回归,例如来自MASS
包的lm.ridge()
和来自genridge
包的ridge()
。对于套索回归,还有lars
包。在本章中,我们将使用 R 的glmnet()
函数(来自glmnet
包),因为它文档完善,接口一致且友好。
使用正则化的关键是确定一个合适的lambda
值。glmnet()
函数使用的方法是使用不同的lambda
值组成的网格,为每个值训练一个回归模型。然后,可以手动选择一个值,或者使用某种技术估计出最佳的lambda
。
你可以指定尝试的值的序列(通过lambda
参数);否则,将使用包含 100 个值的默认序列。
参数设置
glmnet()
函数的第一个参数必须是特征矩阵(我们可以使用 R 函数model.matrix()
创建该矩阵)。第二个参数是包含输出变量的向量。最后,alpha
参数是用来在岭回归(0)和 lasso(1)之间切换的。以下代码为我们的示例设置了环境:
# --- load the package
library(glmnet)
# --- create our parameter data
cars_train_mat <- model.matrix(Price ~ .-Saturn, cars_train)[,-1]
lambdas <- 10 ^ seq(8, -4, length = 250)
model.matrix
是一个 R 函数,通过扩展因子为一组汇总变量(取决于对比)并类似地扩展交互作用来创建矩阵。
# --- create regression model
cars_models_ridge <-
glmnet(cars_train_mat, cars_train$Price, alpha = 0, lambda = lambdas)
# --- create a lasso model
cars_models_lasso <-
glmnet(cars_train_mat, cars_train$Price, alpha = 1, lambda = lambdas)
我们在此示例中用于设置数据的前述代码(具体为length = 250
)提供了一个包含 250 个值的序列。这意味着(在前述代码中)实际上训练了 250 个岭回归模型和另外 250 个 lasso 模型!
我们可以查看glmnet()
生成的cars_models_ridge
对象的lambda
属性值,然后应用coef()
函数来提取第 100^(th)模型的相应系数,方法如下:
# --- print the value of the lambda object of the 100th model
# --- generated by glmnet
cars_models_ridge$lambda[100]
[1] 1694.009
# --- use coef to see 100th model's coefficient values
coef(cars_models_ridge)[,100]
(Intercept) Mileage Cylinder Doors
6217.5498831 -0.1574441 2757.9937160 371.2268405
Cruise Sound Leather Buick
1694.6023651 100.2323812 1326.7744321 -358.8397493
Cadillac Chevy Pontiac Saab
11160.4861489 -2370.3268837 -2256.7482905 8416.9209564
convertible hatchback sedan
10576.9050477 -3263.4869674 -2058.0627013
最后,我们可以使用 R 的plot()
函数生成一张图,显示随着对数值变化,系数值如何变化。
如以下代码所示,将岭回归和 lasso 的图表并排显示是非常有用的:
# --- visualize our model data
# --- set matrix column-widths and the row-heights
layout(matrix(c(1, 2), 1, 2))
# --- create ridge regression plot
plot(cars_models_ridge, xvar = "lambda", main = "Ridge
Regression\n")
以下是前述 R 代码生成的图形:
这是生成lasso
图的 R 代码:
# --- create lasso plot
plot(cars_models_lasso, xvar = "lambda", main = "Lasso\n")
这是相应的输出:
上述两个图的显著区别在于,lasso
会强制许多系数精确地降到零,而在岭回归中,系数通常会平滑地下降,只有在极端值时才会完全降到零。请注意,两个图的上方水平轴上的数值,显示了随着值的变化,非零系数的数量。
除了应用正则化以最小化过拟合问题外,lasso
函数通常用于执行特征选择,因为具有零系数的特征将不会被包含在模型中。
作为glmnet
包的一部分,predict()
函数可以在多种情境中使用。例如,我们可以确定模型在一个原始列表中未包含的lambda
值下的系数方差(CV)百分比(两个变量之间线性关系的强度和方向)。
Predict
是一个通用函数,用于从各种模型拟合函数的结果中进行预测。
让我们尝试在之前创建的lasso
模型上使用predict
。
我们可以在之前创建的lasso
模型cars_models_lasso
上编写以下 R 代码:
# --- use predict function on the lasso model
predict(cars_models_lasso, type = "coefficients", s = lambda_lasso)
Below is the generated output, a list of the coefficient values:
(Intercept) -521.3516739
Mileage -0.1861493
Cylinder 3619.3006985
Doors 1400.7484461
Cruise 310.9153455
Sound 340.7585158
Leather 830.7770461
Buick 1139.9522370
Cadillac 13377.3244020
Chevy -501.7213442
Pontiac -1327.8094954
Saab 12306.0915679
convertible 11160.6987522
hatchback -6072.0031626
sedan -4179.9112364
从前面的输出可以看出,lasso
没有将任何系数强制为零,这表明在这种情况下,应该保留所有特征(即不应从数据中删除任何特征)。
总结
在本章中,我们提供了统计正则化的解释,并使用示例数据进行了演示,以便更好地理解统计正则化。之后,我们讨论了如何通过正则化来改进数据或数据模型的多种方法。最后,我们看到了 R 语言如何很好地支持正则化的概念和方法。
在下一章,我们将介绍数据模型评估的概念,并使用统计学进行评估。我们将比较数据评估和数据质量保证的概念,最后,应用统计评估的思想,并通过 R 语言对数据进行评估。
第八章:数据库开发与评估
本章将介绍数据(数据库)评估的实践。我们将解释什么是统计评估,为什么它对数据科学家非常重要,并通过使用 R 提供一些示范性的例子,展示如何执行各种统计评估方法。
正如我们在本书中一直努力做的那样,我们将对某些数据开发人员和数据科学家的概念进行类比,比较数据或数据库开发与数据(数据库)评估之间的区别,并对数据评估和数据(质量)保证的实践进行比较。
我们已将本章信息组织成以下几个部分:
-
评估与统计评估的比较
-
开发与评估的对比
-
数据评估是否能保证数据质量?
-
使用 R 应用统计评估方法对数据进行评估
让我们开始吧!
评估与统计评估
Merriam-Webster 将评估定义为:
做出判断的行为或实例。
下图展示了评估统计数据的流程:
我们需要记住一些统计评估的要点。它们如下所列。
目标
牢记这一点,要能够做出合理的评估——也就是说,做出判断——首先必须设定目标。评估目标帮助数据科学家确定如何评估数据、数据库或统计数据模型。没有明确的目标,你会浪费宝贵的时间,并且可能对一个不符合业务需求的模型产生信任,甚至可能导致错误的假设(预测)。
基准线
接下来,(根据你设定的目标)需要建立标准、最低可接受的性能或基准,以便对所评估的内容形成意见。换句话说,你评估的内容与所认可的可接受标准相比,表现如何?
尽管我们在这里不会花太多时间讨论数据库评估的过程(而是着重于统计数据或统计数据模型评估),但我们会提到使用特定的性能度量(性能指标或度量标准)。
数据科学家在评估统计模型的预测准确性时,通常会使用非常具体的(性能)度量标准。这些度量标准取决于所评估问题的类别或类型,并要求采用略有不同的方式来评估(模型的)性能。这一方法也同样适用于评估标准的非统计数据和数据库。例如,用于评估在线事务处理(OLTP)数据模型的性能度量标准与用于评估企业数据仓库(EDW)模型的标准将会非常不同。
更深入地看,在评估、性能测试或评估(非统计性)数据库时,需要关注不同基准的识别(即基准测试)、容量的确定与规划、执行浸泡测试或测试、峰值-休息间隔(仅举几个例子)作为努力的一部分。
评估规划
正如非统计性数据库(例如 OLTP、EDW 等)的类型决定了用于评估的测试类型,统计模型的类型(例如回归、分类、二分类等)也会决定数据科学家用来评估统计模型的适当评估技术或方法(稍后将在本章中详细讲解)。
一旦你设定了评估目标并建立了基准,就会制定执行计划。该计划通常概述了整个执行过程。计划中会列出要执行的测试以及测试目标、需要比较的基准,甚至包括预期结果。
评估
在统计学中,性能通常与模型的准确性互换使用。当谈到非统计性数据库或模型时,性能可能更多与速度有关——查询返回值所需时间、提交事务所需时间等——以及准确性,通常围绕质量保证的概念,而不是预测值的能力!
在评估统计模型时,数据科学家会查看模型的错误率、模型所做的错误分类数量、正确预测的数量与总预测数量的比例(由模型预测)等。此外,所有这些都取决于统计模型的类型和目标。
最后,一旦完成,数据库和统计数据模型评估的结果通常会以多种方式进行可视化,以便于评估,采用常见的方法(同样,如何呈现或可视化过程结果将取决于准备可视化的人或模型的目标)。应当理解,一旦评估结果被评估后,评估过程的各个部分(甚至整个评估过程)进行重复是很常见的。这可能是为了进一步澄清在呈现结果中识别的某些内容,或重新验证某些结果。在某些情况下,可能会制定并执行新的项目目标、基准,甚至新的计划。
总结来说,执行数据库或(统计)数据模型评估的过程,在广义上是相似的,都需要以下内容:
-
设定目标(数据库或数据模型的目标)
-
建立基准(用于比较性能)
-
确定评估计划
-
评估结果
开发与评估
尽管评估过程会产生输出,最终可能只是一个决策(也就是说,观察的数据、数据库或统计数据模型是否达到了基于目标的可接受性能限度?),但开发意味着构建。
开发也可以意味着通过扩展、扩大或精细化来改进。这意味着(或至少暗示)任何人所开发的东西可能永远不会完全完成。事实上,开发和评估是并行进行的。
开发任何事物的行业公认实践建议如下:
-
构建(或开发)
-
测试
-
评估
-
重复
在开发关系型数据模型时,可能会使用create
SQL 语句,如以下代码所示:
mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
-> PRIMARY KEY (a), KEY(b))
-> ENGINE=MyISAM SELECT b,c FROM test2;
分析前面的代码,我们可以看到,结果是生成了一个表对象test
。也许,保持相同的思路,评估一个(关系型)数据库或数据模型可能会使用以下代码示例的某种形式:
USE AdventureWorks;
GO
SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT p.Name, pr.ProductReviewID
FROM Production.Product p
JOIN Production.ProductReview pr
ON p.ProductID = pr.ProductID
SET STATISTICS IO OFF
SET STATISTICS TIME OFF
像前面那样的语句执行性能工具,返回相关的统计数据,可以进行可视化和分析。
一个类似的(尽管简单的)统计开发(或创建)示例可能看起来像以下 R 代码(摘自第七章,数据库改进的正则化):
# --- using the R lm function to create an ordinary least squares (OLS) # -- fit of 3-variable model using x3 as an independent x3 variable
ols <- lm(y~ x1 + x2 + x3)
summary(ols)
同样来自第七章,数据库改进的正则化,我们使用 R 函数 summary 开始对生成的线性回归模型的性能进行评估:
如前所述,根据统计问题的类别,数据科学家将使用不同的方法或手段来评估(模型的)性能(包括 R 函数 summary)。
规划
在本章的上一节中,我们比较并找出了评估与统计评估之间的相似之处,并指出,作为任何评估项目的一部分(或者至少是你希望其成功的项目),你需要制定一个计划。
进入这一部分,我们将开发与评估联系起来,我们再次看到,开发过程中的第一步可能是制定一个计划。
作者认为,制定计划是生活中任何事业的基本要求,甚至是早晨起床!
当你在考虑数据库开发时所制定的计划可以在实施时作为指南(在此情况下为数据库或统计数据模型),并且在实施后作为功能规范(对于数据库)。
那么,评估一个数据库(或在统计学中,评估一个数据模型)的任务呢?嗯,同样的道理。第一步是制定一个详细的评估计划,这个计划不仅可以指导整个评估过程,评估完成后,还可以作为一个功能规范参考。
计划总是会自我付出回报。一个好的开发或评估计划可以成为详细的项目计划、验收测试计划、部署文档,并且如前所述,还可以作为功能规范的参考。
数据库设计是数据或数据库开发过程的一部分。设计一个数据库可能是一个复杂的任务。设计过程的一部分是数据建模师(或经验丰富的数据开发者)研究数据、其来源、需求等,然后生成详细的数据模型。该数据模型将包含所有必要的逻辑设计和物理设计选择,以及生成数据定义语言(DDL)所需的物理存储参数,这样就可以实际创建数据库。
一个全面的数据库开发计划应包括数据库设计阶段(从建模到创建),并在过程中指明多个测试和评估步骤。
统计建模(实际上被认为是数学建模的一种形式)涉及整合或汇集一组假设,这些假设涉及或关于生成某些样本数据和来自(希望是)更大数据集的类似数据。
生成统计模型的计划(类似于生成数据库模型的计划)应包括对(样本)数据、其来源、所有需求等的检查。同样,和前述计划一样,统计建模计划应包括提及数据科学家计划在统计模型上使用的每次评估和评估。
通常,统计模型评估计划还会包括数据科学家在每次评估测试后,计划用来阐明观点或总结结果的可视化参考。
统计建模被描述为研究一个系统或过程,以预测其未来的行为,正如 Madhuri Kulkarni 所说:
在拥有系统的观察数据的情况下,模型可以帮助推断系统的各种替代方案。
所有可用于统计建模(以及理解和操作数据)的通用工具中,R 似乎是最强大且最流行的。
从非统计建模的角度看,数据建模定义并分析支持业务流程的需求(在组织中某些信息系统的范围内)。在这里,像 Erwin Data Modeler 和 MySQL Workbench 这样的工具似乎是最常成功使用的工具。
最后,尽管开发和评估是两个独立的工作,但它们是紧密相关的,无论是统计还是非统计,一个都离不开另一个的存在。
数据评估和数据质量保证
为了系统地讨论,我们来看一下数据评估如何与数据质量(保证)进行比较或对比。
数据质量保证,或者通常由数据科学家称为整理数据,是解决(可能是感知的)数据问题或担忧的过程。这些问题会影响数据库或数据模型的使用、质量和结果(性能)——当然,数据质量相对于预期使用目的(数据、数据库或数据模型的使用)来说是相对的。
质量分类
通常,数据质量问题可以归类为以下几个领域之一:
-
准确性
-
完整性
-
更新状态
-
相关性
-
一致性(跨来源)
-
可靠性
-
适当性
-
可访问性
你会发现统计数据和非统计数据之间有很多数据质量分类的重叠。有时,数据质量问题可能看起来仅适用于某一特定类别——统计数据与非统计数据——但经过进一步调查或至少对数据或领域的更多经验,你可能会发现质量是质量。
数据的质量会影响结果,且数据的质量可能受到数据输入、存储和管理方式的影响,解决数据质量问题的过程(通常被称为质量保证,数据质量保证(DQA))需要定期的例行审查和评估数据,并进行名为“分析”和“清洗”的持续过程。(即使数据存储在多个不同的系统中,这些过程也至关重要,这使得这些过程变得更加困难。)
尽管数据质量保证(DQA)和整理数据的概念在许多方面相似,但 DQA 通常更侧重于可重复的过程,而整理数据通常是根据需要进行的,并且由数据科学家根据统计模型的目标自由决定(尽管有经验的数据科学家很可能会努力创建可重用的例程或脚本,以便以后在当前或其他项目中使用这些脚本来操作或整理数据)。
相关性
很多值得注意的重点都放在统计相关性上。统计信息的相关性反映了它满足特定项目实际需求的程度。它关心的是现有信息是否能解决项目中重要问题的相关性。评估相关性是主观的,并依赖于用户不断变化的需求。
确定和衡量数据相关性的一个关键方法是通过一个叫做添加上下文或分析的过程。
我们来看一下,这个概念是什么?
一般来说,看似相似的数据实际上可能意味着截然不同的事情。例如,平均每分钟转速(RPM)的含义,如果数据代表的是跑车与经济型汽车,甚至卡车,便会有不同的涵义。
对于数据,应该通过我们提到的分析过程来发展背景线索,这个过程被称为数据分析,以便数据使用者在使用数据时能更好地理解它。此外,了解你正在处理的数据的背景和视角,是确定应进行何种评估的关键步骤,或者对于非统计模型而言,可能需要进行哪种性能评估。
添加背景到数据的另一个动机可能是为了从数据中获得新的视角。例如,认识到并检查数据中存在的比较。例如,住宅或房价可以根据邮政编码或其他标准进行比较。
将背景添加到数据中(无论是统计的还是其他形式的),作为开发和评估过程的一部分(回想一下,我们提到过这两者是紧密结合的),确实可以使数据更加相关,但背景仍然无法替代数据的价值。
在考虑数据中的任何变量之前,例如平均转速、扭矩、最高速度、轴距、重量(或其他),最重要的是,评估测试需要使那些将要使用数据的人受益,或者换句话说,无论数据科学家希望预测什么。举例来说,如果我们扩展这个车辆数据的例子,期望的每加仑英里数(MPG)就是其中之一,因此建立适当的背景要求至关重要。
对于数据分析(或为项目中使用的数据添加背景),规则如下:
在考虑背景之前,思考−> 价值
类似于我们如何分类数据质量问题的类型一样,也有几个背景类别,可以用来论证或提升数据的价值与理解,以便进行可视化:
-
定义与解释
-
比较
-
对比
-
趋势
-
离散度
评估值和数据质量,甚至数据或数据模型的价值,虽然可能有重叠的部分,但其目标是不同的。
交叉验证
如果一本书的章节集中在统计学(以及评估统计模型)上,而没有至少一节关于交叉验证的内容,那是不可行的。你可能听到一些数据科学家将交叉验证称为旋转估计,或者仅仅视为一种评估模型的通用技术。
交叉验证是数据科学家常用的一种方法,用来评估统计模型的准确性。交叉验证的关键概念是测试一个模型的泛化能力,或者更具体地说,测试该模型如何将从训练数据样本中推断的结果应用于整个数据集或人群。
交叉验证有两个目标——使用一个算法从可用数据中估算模型的性能,以及比较两种或更多不同算法的性能,并找出最适合可用数据的算法。
从高层次来看,交叉验证的过程是识别一个已知数据集,称为验证数据集,然后在该数据集上进行训练,接着使用第二个数据集(未知数据或首次出现的数据)进行测试(这被称为测试数据集)。这里的目标是尽量确保控制过拟合等问题(避免不包括信息影响结果),并且提供一些对模型如何概括实际问题或真实数据文件的理解。
准备数据
要执行交叉验证,数据科学家必须准备数据。这项工作将包括通过概况分析(我们在本章的前面部分提到过)来了解数据,以便将数据分为几个可比的子集。然后,确定其中一个子集为训练集并对其进行分析。接下来,一旦分析(或训练)完成,就会使用另一个子集(称为验证集或测试集)来验证结果(或性能)。
为了减少变异性,使用不同的数据分区执行多轮交叉验证(也称为折叠或回合),并在回合之间对验证结果进行平均。
通常,数据科学家会使用模型的稳定性来确定应该执行的交叉验证轮次:
如前图所示,交叉验证方法可以通过将数据科学家将数据群体组织成两个子集来更好地理解:已知数据和未知数据(你将在本章下一节看到如何实现这一点)。然后,数据科学家对数据进行分析并手动计算结果。一旦确定了预期的或正确的结果,就可以将其与统计模型生成的结果进行比较(使用那个独立的未知数据子集)。
上述是一次循环。将进行多次循环,比较结果后进行平均并复审,最终提供一个公平的模型预测性能估计。
让我们考虑一个实际应用场景。
在第六章《数据库改进的正则化》中,我们再次回顾了一些由咨询项目结果组成的示例数据。在这个例子中,我们探讨了项目总计费用、项目管理总小时数与项目预期盈利之间的关系。
回顾那份数据以说明一个观点,我们可以考虑不同的项目特征(而非变量):
-
该项目是否在组织的核心技术强项范围内?
-
是否有全职项目经理被分配到该项目?
-
项目是否有全职客户资源分配?
-
项目工作是否外包了?
-
这个项目是时间和材料型的项目吗?
-
项目是否属于不超支类型的项目?
-
项目是否有正式的质量保证 (QA) 部分?
-
工作是否主要在现场进行?
-
工作是否主要是远程进行(来自客户现场)?
再次,我们的预测模型旨在预测一个有利可图的咨询项目具有什么特征。
以下是使用五轮交叉验证过程预测我们模型预期准确度的结果表示:
根据前面的图示,我认为我们的预测模型预计将非常准确!
总结来说,交叉验证结合了(平均)拟合度(预测误差)度量,以得出更准确的模型预测性能估计。这个方法通常在数据不足以进行测试而不损失显著建模或测试质量的情况下使用。
现在让我们进入本章的最后一节,来看一些使用 R 编程语言进行评估的示例。
R 和统计评估
那么,让我们开始一些统计评估工作吧!
正如我们在上一节中讨论的那样,交叉验证不是使用所有数据(整个观察集)来训练统计模型(然后使用其中一些数据进行测试),而是将数据分为训练集和测试集。
数据科学家在使用交叉验证评估统计模型性能时,首先需要做的步骤是将数据组织(或拆分)成两个独立的子集。
实际上,交叉验证有几种方法:
-
留一法交叉验证 (LOOCV)
-
保留法
-
k 折交叉验证和重复 k 折交叉验证
-
重新代入(大多数人认为这是最简单的方法)
这些交叉验证方法都集中在如何拆分数据以进行训练、测试和验证。每种方法都有其优点(优缺点)。
编程问题总是有许多解决方法。以下是其中一种简单的方法。这个例子通过 70 对 30 的比例随机拆分总文件:
# --- setting seed so we get same data split each time
# --- we'll use 100 for seed
set.seed(100)
# --- determine the total number of rows in the data
# --- using nrow function
nall = nrow(MyData)
# --- number of rows for train subset is 70%
# --- of the total rowsntrain = floor(0.7 * nall)
# --- number of rows for test subset is 30%
# --- of the total rows
ntest = floor(0.3* nall)
index = seq(1:nall)
# --- create the train data subsettrainIndex = sample(index, ntrain)
testIndex = index[-train]
train = mydata[trainIndex,]
test = mydata[test,]
一旦我们创建了所需的文件,我们就可以继续训练并验证我们的统计模型。
正如我们在本书中时不时提到的,经过验证的做法是保存前面的代码,以便在新的数据集上反复使用。
需要问的问题
在本章的前几节中,我们讨论了交叉验证的各种方法或途径、交叉验证的轮次(实际上,我们展示了五轮交叉验证的结果),以及如何组织和拆分数据以便对统计模型进行交叉验证。
在继续进行交叉验证过程之前,需要考虑一些要点。(一个计划已被制定!)这带出了以下问题:
-
我应该使用哪种交叉验证方法?答案是最好的方法。然后又有一个新问题——“最好”是什么意思?每种方法都有其优缺点。最佳的交叉验证方法是最适合你的数据和目标的方法。通常,直到尝试了其他方法之后,你才会发现应该使用哪种方法。
-
应该执行多少轮或折叠?通常,越多越好!然而,这将由你选择使用的交叉验证方法、可用数据和时间的多少等因素决定。
-
创建每轮数据的方法是什么?这将由你选择使用的交叉验证方法、可用数据和时间的多少以及数据科学家的能力等因素决定!
学习曲线
评估统计模型性能的另一种方法是通过评估模型的学习增长或模型在更多经验(例如更多轮交叉验证)下改善学习的能力(获得更好的分数)。
术语随着额外经验在统计学中至关重要,因为我们不仅仅希望统计模型在给定数据集上表现良好,我们还希望随着模型在更多数据上进行训练和测试,其性能能不断改善。
表示模型性能、结果或分数的信息通常会与其他分数结合,显示为一条线或曲线——这就是统计模型的学习曲线。
这意味着学习曲线是学习增长(在纵轴上显示的分数)与实践(在横轴上显示的各个数据文件或轮次)之间的图形表示。
这也可以用以下方式来概念化:
-
在一系列中重复相同的任务
-
随时间积累的知识
学习曲线示例
举个例子,假设我们想要可视化一个统计模型在多轮表现结果中的学习增长速度,比较测试数据与训练数据在某一特征上的表现。
这在本章的前面部分已有展示:
以下是一个可视化,显示了使用前述交叉验证轮次的结果分数所表示的预测模型学习速度:
核心技术
以下是生成前述可视化的示例 R 代码:
# --- load scores from 5 rounds of testing
v <-c(90,80, 89,72, 90)
# -- plot the model scores round by round
plot(v, type = "o", col = "red", xlab = "Round", ylab = "Score", main = "Core Technology")
再次提到,学习曲线将统计模型的表现与经验联系起来,通常在进行模型评估时使用,尤其是在进行多轮测试(或分析工作,以确定用于统计模型的正确交叉验证方法)时。
到目前为止,仅仅进行测试轮次然后查看结果还不够。一个经验丰富的数据科学家会确保正确地记录每一次测试的迭代过程,以及相应的结果和结论。
再次查看前面的示例,我们可以添加对 R 函数png
的使用,它可以用来自动创建并保存你在评估过程中创建的任何可视化的图像文件。如果你预先定义了一个文件结构来保存你的评估结果,并使用这种或类似的方法,它将为你节省大量的时间。
R 函数png
可以轻松地转换为许多其他位图格式,并且它们都可以在现代的网页浏览器中显示!
以下是我们的示例 R 代码语句,展示了数据的设置、图像文件的创建以及绘图可视化的生成:
# --- load scores from 5 rounds of testing
v <-c(90,80, 89,72, 90)
# -- create an image file for the visualization for later use
png(file = "c:/provenpratice/learning curve.png", type = c("windows", "cairo", "cairo-png"))
# -- plot the model scores round by round
plot(v, type = "o", col = "red", xlab = "Round", ylab = "Score", main = "Learning Curve")
# -- close output
dev.off()
你需要注意的是,如果你期望得到交互式结果,你将不会收到!前面的代码使用了png
,这只是将输出(来自plot
函数的结果)写入那个文件。
好的实践建议:使用dev.off()
确保文件已关闭。
这将创建以下图形文件:
总结
在本章中,我们定义了评估,并且考察了评估与统计评估之间的相似性和差异。接着,我们讨论了开发与评估之间的关系,并解释了数据评估与数据质量保证之间的部分重叠,二者是并行的,但目标不同。最后,我们应用了使用编程工具 R 进行统计评估的概念。
在下一章中,我们将定义神经网络模型,并借助开发人员对数据模型的理解来帮助理解神经网络在数据科学中的目的和应用。
第九章:数据库与神经网络
在本章中,我们将定义人工神经网络(ANN),并结合数据开发人员对数据、数据库和数据模型的知识,帮助他们理解神经网络的目的和用途,以及为什么神经网络对数据科学和统计学如此重要。
我们已将本章内容整理为以下几个关键领域:
-
神经网络的定义
-
将神经网络模型与数据库模型联系起来
-
查看基于 R 的神经网络
-
用例
问问任何数据科学家
今天,如果你问任何数据科学家关于统计方法的问题(即便是几个问题),你很可能会发现如今在数据科学和统计行业中,最著名的两种统计方法就是用于预测建模的这两种方法。我们在第六章数据库发展到数据库回归中介绍了这两种方法。
这两种方法如下:
-
线性回归
-
逻辑回归
线性回归方法可能被认为是预测数值量时问题的经典或最常见的起点。线性回归(或LR)模型基于输入特征的线性组合。
逻辑回归方法使用对这种线性特征组合的非线性变换,以将输出的范围限制在区间[0, 1]内。这样,它预测输出属于两个类别之一的概率。因此,它是一个非常著名的分类技术。
记住,分类是根据训练数据集,识别新的或不同的观察结果属于哪一类别(或子人群)的过程。
这两种方法各有其独特的优势,但它们也有相同的缺点,即在面对大量输入特征的情况时,它们的预测效果并不好。
在本章中(作为线性回归和逻辑回归的替代方法),我们希望介绍人工神经网络(ANN)的概念,这实际上是一种非线性的方法,用于解决回归和分类问题。
当处理更高维的输入特征空间时(ANNs)具有显著更强的鲁棒性,并且在分类问题中,它们具有一种自然的方式来处理多于两个输出类别的问题。我们将在本章后面详细讨论 ANN 的优势。
人工神经网络是一种生物启发式统计方法或模型(基于生物神经网络的结构和功能),其根源可以追溯到 20 世纪 40 年代。
另一个有趣的观点:
神经网络是一种机器学习框架,试图模仿自然生物神经网络的学习模式。
- Jose Portilla,Udemy 数据科学讲师。
自那时以来,人工神经网络的兴趣变化很大——主要是因为最早的人工神经网络模型非常初步,因此与当时的预期相比,实践中发现其局限性。
神经网络并不总是受欢迎,部分原因是它们计算上昂贵,且在某些情况下仍然如此;另外,部分原因是与更简单的方法如支持向量机(SVMs)相比,它们似乎并没有带来更好的结果。然而,神经网络再次引起了关注并变得流行。
-Michy Alice, 2015 年 9 月。
此外,训练一个大型人工神经网络确实需要大量的计算资源。最近,由于分布式按需计算资源的普及,人工神经网络的兴趣重新激增,并且被称为深度学习的机器学习领域已经非常流行,且展现出巨大潜力。
时机恰到好处!
因此,现在是数据开发者开始学习 ANNs 模型的好时机。
深度学习(也称为深度结构学习、层次学习或深度机器学习)是一类使用多个非线性处理单元层级来进行特征提取和转换的机器学习算法 (en.wikipedia.org/wiki/Deep_learning)。
开始吧!
定义神经网络
我们的方法是始终从一个明确的定义开始。那么——什么是人工神经网络呢?或许是:
一个模拟人脑和神经系统的计算机系统。
一个常见的理解,或者如果我们在线查找定义的话:
在机器学习和认知科学中,人工神经网络(ANNs)是一类受生物神经网络启发的模型(尤其是动物的中央神经系统,特别是大脑),用于估计或近似那些可能依赖大量输入并且通常是未知的函数。
所以有许多不同的定义,但总体来说,你会发现所有关于 ANNs 的定义都围绕着一个共同的主题:它被定义为基于人脑工作原理的计算机数据模型。
ANN 模型表示
正如前面的截图所示,典型的人工神经网络的构建基于以下几个要素:
-
节点
-
层
-
连接
节点
每一层由若干互相连接的节点组成——每个节点包含所谓的激活函数。
输入层中将至少有一个节点用于每个数据中的预测变量。输入节点将输入值(待解决的问题)传递给(下一个)隐藏层中的每个节点。
每个节点的输入会被求和,得到一个单一的值,x。然后,这个值会被输入到节点的激活函数中,节点的输出就是其激活函数的输出,f(x)。
人工神经网络节点中可以使用多种函数,包括径向基函数或简单的线性函数,但最常见的是 Sigmoid 函数或逻辑函数。
Sigmoid 函数通常是最常见且也许最容易理解的。Sigmoid 函数是一个数学函数,具有特征的 S 形曲线或 Sigmoid 曲线。Sigmoid 函数的定义域为所有实数,返回值通常单调递增,从 0 到 1,或者根据约定,从-1 到 1。(en.wikipedia.org/wiki/Sigmoid_function
)
人工神经网络中的节点总是会产生或计算一个介于 0 和 1 之间的值,因此一个节点的输出只能在 0 到 1 之间。
层
层是一个通用术语,用来定义在人工神经网络中按特定深度协同工作的节点集合。
隐含层将有一个可变数量的节点(由使用的训练算法决定)。每个节点将包含多个逻辑函数,用来处理输入并计算结果。最终结果将被传递到下一层。
层的总结如下:
-
输入层:该层包含你的数据,每个变量对应一个节点。
-
隐含层:每一层通过最小化误差/成本函数,尝试学习关于数据的不同方面。
-
输出层:这是最简单的一层,通常由一个用于分类问题的输出组成。
训练
回忆上一节描述的人工神经网络节点,如果所有节点的工作方式相同,或者至少产生相同的结果(0 或 1),那么网络如何区分不同的类别呢?
它将权重分配给每个节点的输入。这是一个特征(或数据中的变量),其权重可以大也可以小,进而导致变量或特征对任何节点的和的贡献有所不同。
实际上,一个变量可以被赋予一个较大的权重,传递到一个节点,而传递到另一个节点的权重几乎为零,这意味着该变量对第一个节点的影响很大,对第二个节点几乎没有影响。
Sigmoid 函数(我们在上一节也提到了)表明,当节点的x值跨越一个阈值时,节点的输出会从 0 变为 1。这可以通过多种方式发生,例如当一个高权重的输入具有较高的值,或者一组中等权重的输入具有较高的值时。
训练人工神经网络的过程是系统地发现最优权重值,以最大化分类的准确性。
解决方案
隐藏层中某个节点的输出值会与进行计算的节点的权重相乘,并加到其他节点的加权值中。这一求和结果成为人工神经网络模型的输出或解决方案。(需要注意的是,这个术语在数据科学家之间有所不同,有些人称之为输出,有些人称之为解决方案、结果,甚至是结果值)。
再次强调,问题被呈现给人工神经网络(通过模型的输入层),该网络会传递到一个或(更可能)多个隐藏层,实际的处理通过加权连接的系统完成。然后,隐藏层与输出层相连接,给出解决方案。
大多数人工神经网络模型包含某种形式的算法,决定模型如何学习。这个算法就是我们之前讨论的,通过它根据提交给模型的(输入)问题来调整节点连接的权重。
这种调整节点权重(有些人称之为右调节)类似于基于经验(在这种情况下,经验可能是反复查看示例)来识别图像(或确定解决方案)的想法。
理解这些概念
要理解一个新概念,通常有助于将熟悉的内容与新知识进行对比。
为了更好地理解人工神经网络的概念,比较 ANNs 与传统数据库算法如何处理数据和信息(或它是如何工作的)将会是有帮助的。
在下一节中,我们将比较人工神经网络模型的概念与常见的数据或数据库模型。
神经网络模型和数据库模型
正如我们在本章前面部分所指出的那样,神经网络模型是一个处理节点系统,跨越不同层级互联,这些层级不会以顺序的方式处理数据。那么,这种结构与传统的数据库模型或程序有什么不同呢?
传统数据库模型表示
正如我们在本章前面部分所指出的那样,神经网络模型是一个处理节点系统,跨越不同层级互联,这些层级不会以顺序的方式处理数据。那么,这种结构与传统的数据库模型或程序有什么不同呢?
在技术行业中,传统的(数据库)模型有时被称为串行处理组件,这意味着这种类型的模型拥有一个中央处理单元或 CPU(或许你可以将其理解为一个大型的中央处理节点),用于访问存储在内存中的原始数据和指令。
在传统的数据库模型中,中央处理器对输入或选定的数据进行计算或逻辑处理(算法),存储计算结果(在指定的内存位置),然后继续执行下一个指令(和数据),依此类推——直到达到解决方案或结果。
这个概念有点类似于神经网络中单独处理流的概念:
-
一个节点接受或消耗数据
-
一个节点应用逻辑
-
一个节点输出它的结果
虽然相似,但请记住,传统数据库模型是串行的,因为它们按线性或一个接一个的方式执行每个任务(或指令),而人工神经网络模型中的多个节点流则并行执行任务。
因此,在一个串行系统中,计算步骤是确定性的、顺序的和逻辑的,并且可以从一个操作到另一个操作追踪给定变量的状态。相比之下,人工神经网络(ANNs)既不是顺序的,也不一定是确定性的。
还有其他一些关键的不同之处,包括以下在接下来的子部分中解释的概念。
没有单一或主要节点
不是一个复杂的中央处理器(或节点),而是许多简单的节点——它们通常只做一件事,即将它们从其他节点接收到的加权和进行计算。
不是串行的
人工神经网络并不按顺序或串行执行编程指令;它们并行响应(无论是模拟的还是实际的)提供给它们的输入。
没有内存地址来存储结果
在人工神经网络模型中,也没有单独的内存地址来存储数据。
相反,信息包含在模型的整体激活状态中。因此,知识由人工神经网络模型本身表示,它字面上是其各个组成部分的总和之外。
最后,对于数据开发者来说,人工神经网络的概念可以想象为启动并异步运行多个 SQL 查询。试想创建一个简单分支任务流的 SQL DTS(数据转换服务)或SQL Server 集成服务(SSIS)包,这样 DTS 将会在单独的spids(服务器进程 ID)中启动任务。每个 spid 随后将与神经网络节点流的概念相对齐,所有节点并行工作以创建结果或解决方案。
一个非常好的神经网络工作原理的解释——通过一个数据开发者类型的实际例子——可以在线找到,作者是 Sunil Ray。
理解和从头编写神经网络的 Python 和 R 代码,在撰写本文时,可以在www.analyticsvidhya.com上找到,链接为:/blog/2017/05/neural-network-from-scratch-in-python-and-r。
他提到以下引述:
“如果你曾经是开发人员,或者看过开发人员的工作,你会知道在代码中搜索 bug 是什么感觉。你会通过改变输入或环境来运行不同的测试用例,查看输出。输出的变化会给你一些提示,告诉你应该查找哪个模块,阅读哪些行。找到问题后,你会进行修改,然后继续这个过程,直到你有了正确的代码/应用。”
神经网络的工作方式非常相似。它接受多个输入,通过多个隐藏层的多个神经元处理数据,然后通过输出层返回结果。这个结果估算过程在技术上被称为前向传播。
接下来,我们将结果与实际输出进行比较。任务是将神经网络的输出尽可能接近实际(期望的)输出。每个神经元都会对最终输出贡献一定的误差。如何减少这些误差?
我们试图最小化那些对误差贡献较大的神经元的值/权重,而这发生在神经网络反向传播过程中,找出误差所在的地方。这个过程被称为反向传播。
好的,这确实有点多——但现在,幸运的话,我们已经对人工神经网络是什么以及它如何工作有了一个相对清晰的理解。接下来,让我们看看 ANN 和 R 编程语言的结合。
基于 R 的神经网络
现在我们已经了解了一些人工神经网络的工作原理,让我们回顾一些实现 ANN 的基本信息,特别是使用 R 编程语言时。
基于 R 的 ANN 包
这里的目的是不是提供一个详细的步骤指南,告诉你如何创建一个复杂且强大的 ANN,而是展示如何通过 R 语言轻松创建一个 ANN 模型——实际上只需要基本的 R 技能或经验。
参考文献
是的,你会发现,互联网上有大量尊重且易于理解的、关于人工神经网络的有价值信息和示例,值得一读。
一个这样的资源由 Gekko Quant 提供,(gekkoquant.com/author/gekkoquant/
),值得花时间查找并阅读。
这段信息提供了一个非常好的教程,展示了如何创建一个人工神经网络,该网络接受一个输入(你想计算平方根的数字)并输出一个结果(该数字的平方根)。
这个人工神经网络示例模型的输出以易于理解的格式展示,我将在这里展示它作为一个很好的示例,说明 ANN 模型的输出应如何呈现:
人工神经网络的结果
从这里显示的输出信息可以看出(正如作者所声明的),神经网络在求平方根(每个输入数值)的任务中表现得相当不错。
在数据科学家开始拟合人工神经网络之前,必须完成一些节省时间的重要准备工作,我们将在接下来的几节中讨论这些内容。
需要明确的是,人工神经网络并不容易理解、训练和调优;因此,强烈建议先进行一些预处理。
数据准备和预处理
让我们从显而易见的开始——我们的数据!
数据科学家在使用 ANN 模型时经验越丰富,就越能理解正式审查和准备数据的重要性,在开始尝试训练或拟合模型之前,提前做好数据准备是至关重要的。
我们在第三章,开发者的数据清理方法中讨论了数据清理,因此到此为止,你应该对数据清理和净化的过程有一个较好的理解,在这里我们将重点关注一些更具体的与人工神经网络模型相关的数据准备工作。
数据科学家普遍认为,在训练人工神经网络之前,对数据进行归一化可能是一个好的做法。根据你的数据,如果不进行任何数据归一化,可能会导致不可用的结果,或者至少是非常困难的训练过程;大多数情况下,算法在达到最大迭代次数之前不会收敛——换句话说,它会用尽所有尝试!
根据行业经验,如果数据没有经过归一化,人工神经网络可能会在达到最大迭代次数之前难以收敛。
尽管有许多方法可以实现数据归一化,但最常用的一种是 R 语言内置的scale()
函数,它可以轻松完成这一任务。
scale()
函数是一个通用的 R 语言函数,其默认方法会为你居中和/或缩放(归一化)数值矩阵的列。
我喜欢使用简单的 R 代码语句来演示以下缩放示例,因为这可以明显看出scale()
函数正确工作(是否如预期?),而且比手动缩放(即编写 R 代码语句来缩放值)要有效得多。
快速看一下:
Setting up the sample data, in the object named "x":
# --- set up the data
Set.seed(1)
X <- runif(7)
Next, here is the manual scaling approach, using mean and sd:
#---manual scale method
(x - mean(x)) /sd(x)
And then the use of the R scale function:
# --- scale using the function
Scale(x)
最后,这是输出,显示了手动缩放方法和缩放函数所产生的相同结果:
太棒了!
数据拆分
我们预处理的下一步是拆分数据。我们在第八章,数据库开发与评估中详细讨论了数据拆分,所以在这里我们不会再重提这个话题。
然而,请记住,数据拆分的过程旨在从原始数据集或来源中创建训练子集和测试子集(基于适当的逻辑)。
例如,我们可以通过随机将数据拆分为训练集和测试集,接着拟合线性回归模型,并在测试数据集上进行测试(或者使用我们在上一章中使用的拆分方法,创建一个 70/30 的拆分)。
模型参数
没有最佳实践或推荐规则能够告诉数据科学家在人工神经网络模型中应该使用多少层和/或节点(尽管有几条或多或少被业界接受的规则)。
通常,如果需要的话,一个隐藏层对于大多数或大量的人工神经网络统计应用已经足够(尽管你可能注意到,我们在本章开始时的图形图像中展示了三个隐藏层)。
就节点数而言,节点数通常应介于输入层大小和输出层大小之间,通常是输入大小的 2/3。
归根结底——当数据科学家确定在其人工神经网络模型中应该有多少层和节点时,他们将不断测试、测试、再测试(一次又一次),以找到最佳或最优化的解决方案,以满足当前的需求,因为无法保证任何过去的经验或规则能最适合你的统计模型。
交叉验证
交叉验证是我们在第二章中介绍的一个重要话题,目标声明,我们再次提醒它是构建任何预测模型时的一个非常重要的步骤。
虽然有很多不同种类的交叉验证方法,但基本的思路是数据科学家重复以下过程若干次:
训练我,测试我,拆分我:
-
进行训练-测试拆分。
-
将模型拟合到训练集。
-
在测试集上测试模型。
-
计算并回顾预测误差。
-
重复(n次)。
通过多次执行上述过程,数据科学家将能够计算出平均误差,并用其来评估统计模型的表现(性能是另一个重要话题,我们在第八章,数据库开发与评估中进行了讨论)。
用于 ANN 开发的 R 包
那么,数据科学家如何创建自己的人工神经网络(ANN)呢?
R 编程语言(截至本文编写时)提供了多种创建不同类型人工神经网络的包。这些包目前包括以下内容。
ANN
本包提供了一个由遗传算法(GA)优化的前馈人工神经网络。
ANN2
这提供了使用梯度下降训练一般的分类和回归神经网络。
NNET
Ripley 创建的 NNET 包提供了用于单层隐藏层前馈神经网络和多项式对数线性模型的方法。具体来说,本书的这一章节将介绍 NNET 方法。在这里,我们简要描述了所使用的方法和参数。
请注意,我是这样拆分数据的:以随机方式将 90%的数据作为训练集,10%作为测试集,重复 10 次。
我还使用plyr
库初始化了一个进度条,因为我希望在神经网络的拟合过程中保持对状态的关注,毕竟这一过程可能会花费一些时间。
黑箱
人工神经网络(ANNs)非常难以理解(即使是对于最先进或经验丰富的数据科学家)。解释它们的结果(或输出)比解释简单模型(如线性模型)的结果要复杂得多。
有时,数据科学家对人工神经网络模型的理解仅停留在非常高层次。虽然仅有这样的理解水平也能保持生产力,但如果无法完全理解人工神经网络模型的内部工作原理,可能会导致一种情况,即所谓的BBU模型或黑箱理解模型或方法。
黑箱模型、方法或系统是指仅能从其输入和输出角度来看待,而无法了解其内部工作原理的模型、方法或系统。
因此,根据你需要的应用类型,你可能需要记住,在模型结果能够有用之前,你必须能够恰当地解释模型的结果(而不仅仅是运行模型并产生结果),因此需要投入时间去深入理解所使用的模型和方法。
一个使用案例
有人说过(很可能不是数据科学家!):
神经网络模型无法学习任何一个合理聪明的人,在相同数据上经过足够时间学习后无法学到的东西。
这一声明中的关键术语是“足够的时间”。数据科学家(以及人类通常)几乎从未拥有足够的时间——时间可能就是决定你所在组织能否超越竞争对手的关键。
支持使用人工神经网络(而非合理聪明的人类)的理由之一是,人工神经网络模型的一些额外优势如下:
-
发现别人甚至从未想象过的东西
-
在比一团队还短的时间内找到解决方案
-
以更低的成本产生结果
-
在经过训练的输入下,产生一致的结果,并且如果适当调整,应该能够很好地泛化
-
神经网络永远不会感到厌倦或分心。
有了这些优势后,我们来看看人工神经网络模型的一些实际应用场景。
流行的应用案例
人工神经网络有许多应用。通过调查行业,最成熟的人工神经网络应用案例包括以下几种。
字符识别
神经网络可以用于识别手写字符,将手写内容实时转换为控制计算机,或用于自动车牌识别(ANPR),自动读取车辆注册号牌。
图像压缩
神经网络能够一次性接收并处理巨量信息,这使它们在图像压缩中具有重要作用。随着大数据的爆炸式增长,应用人工神经网络(ANN)于数字图像,以降低存储或传输的成本,已成为一个日益增长的机会。
股票市场预测
股票市场的实时波动极为复杂,受到众多因素的影响。许多因素如最高价、最低价、开盘价、收盘价、交易量、其他证券的价格以及经济指标都会对其产生影响。由于神经网络能够快速分析大量信息,它们可以用于预测股价。
欺诈检测
近年来,新技术的发展也为犯罪分子实施欺诈提供了更多方式。神经网络可以通过从样本中学习可疑模式,识别近似的类别、聚类或可疑行为模式,并利用这些模式来进行欺诈检测。
神经科学
理论与计算神经科学是生物神经系统的理论分析与计算建模的研究领域。由于神经系统试图复制认知过程和行为,因此该领域与认知与行为建模密切相关。
总结
本章中,我们定义了神经网络,并从数据开发者对数据库和数据模型的知识出发,逐步理解了神经网络的目的和用途,以及神经网络为何对数据科学如此重要。我们还介绍了基于 R 的 ANN,并列出了几个流行的应用案例。
在下一章中,我们将介绍使用统计提升方法,更好地理解数据库中的数据。
第十章:提升你的数据库
本章中,我们将解释什么是统计提升,它如何运作,并介绍如何利用统计提升更好地理解数据库中的数据。
我们已经将本章的主题分解为以下重要领域以便更清晰:
-
统计提升的定义与目的
-
你可以从提升(帮助)你的数据库中学到什么
-
使用 R 来说明提升方法
定义与目的
首先,我们可以考虑一个你可能在网上找到的常见定义:
提升是一种机器学习集成元算法,主要用于减少偏差,同时也减少监督学习中的方差,是一类将弱学习器转化为强学习器的机器学习算法。
-维基百科
en.wikipedia.org/wiki/Boosting_(machine_learning)
提醒:在统计学中,集成方法使用多个学习算法,目的是获得比任何基础学习算法更好的预测性能(尽管结果因数据和数据模型而异)。
在我们深入了解统计学提升的细节之前,首先必须花些时间理解偏差、方差、噪声,以及什么是弱学习器和强学习器。
接下来的章节将涵盖这些术语和相关概念。
偏差
让我们从讨论统计偏差开始。
如果统计量的计算方式使其在分析上与被估计的总体参数不相似,那么该统计量就存在偏差。
我遇到过的关于偏差的最佳解释是一个偏离零的小刻度的概念。在这种情况下,刻度会给出略微高估的结果。换句话说,当某人站上秤时,总体体重可能被高估或低估(这可能让那个人觉得他们的饮食比实际效果更好)。
在统计学中,数据科学家需要认识到,实际上有多个常用的类别来定义统计偏差。下一节将列出这些偏差类别并提供示例。
偏差的分类有些主观,因为某些类别可能会有重叠的情况。
偏差的分类
偏差有许多类别,包括以下具体示例:
-
选择偏差:指的是某些个体观察值比其他观察值更可能被选中进行研究。
-
谱偏差:当数据科学家在偏倚的样本上评估结果时,导致对测试的敏感性和特异性估计过高。
-
估计器偏差:指的是估计器的期望值与被估计参数的真实值之间的差异。
-
遗漏变量偏差:在回归分析中估计参数时,如果假设的模型忽略了某个自变量,就会出现这种偏差。
-
检测偏差:当某个特征或事件在特定研究对象组中更容易被观察到时,就会发生这种偏差。
-
抽样偏差:当由于抽样数据的错误而导致统计误差时,就会发生这种偏差。
-
测量偏差:当测试内容、测试管理和/或评分程序存在系统性问题时,就会发生这种偏差。
-
资金偏差:这种类型的偏差可能导致选择特定的结果、观察、测试样本或测试程序,这些都偏向于研究的资金赞助者。
-
报告偏差:这种类型的偏差涉及数据可用性的偏差,这导致某种类型或集合的观察结果更有可能被报告为结果,或影响表现。
-
分析偏差:这种偏差发生在用于评估某些观察结果或统计模型整体表现的方法或过程上。
-
排除偏差:这种偏差类别可能由于某个过程或程序而产生,该过程或程序有可能系统性地排除某些样本或观察结果,导致统计研究中的样本或观察缺失。
-
脱落偏差:当研究或统计项目中的参与者离开程序或过程时。换句话说,一个项目的某个组或类别可能会离开或被移除,并且不再被数据科学家考虑。
-
回忆偏差:当研究参与者的准确性或完整性由于对过去事件或研究对象特征的错误记忆而不一致时。这会导致结果的高估或低估。
-
观察者偏差:这种偏差发生在研究人员由于认知偏差无意识地影响数据时,判断可能会改变观察或研究的进行方式/结果的记录方式。
-
混杂偏差:当影响研究中相同信息的因素使研究者或数据科学家感到误导或困惑时,就会发生这种偏差。
-
负面偏差:当数据科学家倾向于对负面的特征、事件或结果赋予更多的权重或价值,仅仅因为它们是负面的时,就会发生这种情况。
-
代表性偏差:当数据科学家根据群体中识别出的某些观察特征将某些事情视为理所当然时,就会发生这种偏差。
-
近期偏差:这种偏差类别发生在数据科学家使用最近的经验和观察(或赋予更多的价值)来预测未来结果时。
而我最喜欢的其中一种类型是:
- 数据窥探偏差:当数据科学家形成错误的意见或提出假设,并随后挖掘数据以特别支持该观点时,就会发生这种情况。
偏差的原因
偏差 是一个你会在统计学领域常常听到的术语,几乎总是与负面或不良事件相关。事实上,甚至在统计学的领域之外,偏差几乎总是导致麻烦或某种形式的困扰。
将偏差视为偏袒。举例来说,在数据收集过程中存在的偏袒通常会导致误导性结果或错误的假设。
偏差可以以各种方式出现,作为数据科学家,必须熟悉这些情况。事实上,偏差可以在任何时间或阶段进入统计项目。
引入偏差最常见的时机之一就是项目一开始的数据收集或选择时。这个时候是最糟糕的,因为几乎所有后续的工作和努力都会受到怀疑,或者很可能是错误的。
偏差数据收集
偏差的一个主要来源是数据的收集方式。坦率地说,经验不足的研究人员,或者有某种特定结果期望的研究人员,可能会使用低劣的数据收集方法或实践,甚至以一种强调某种特定倾向或导致预期结果的方式收集数据。
数据收集方法中需要注意的事项:
-
带有特定倾向或强调的调查
-
选择一个已知的、具有特定背景的群体来回答调查
-
以误导性分类方式报告数据
-
非随机的样本选择
-
系统性测量误差
偏差样本选择
样本选择或抽样过程同样容易引入偏差。当样本不能准确代表总体时,就会出现样本偏差。由不具代表性的样本引发的偏差被称为选择偏差。
可能导致在统计样本中引入偏差的问题包括:
-
采样的时机
-
样本的长度或大小
-
问题的难度级别
-
低覆盖率(对于总体)
-
非回应错误地用于样本中
-
自愿回应错误地用于样本中
-
样本中被联系的方式(电话、邮件、上门等),或观察数据的划分方式
偏差说得够多了。让我们进入下一部分,讨论统计方差。
方差
在统计学理论中(en.wikipedia.org/wiki/Statistics
),方差的概念定义如下:
随机变量与其均值的平方偏差的期望值(en.wikipedia.org/wiki/Expected_value
),换句话说,它是衡量一组随机数相对于其平均值的分散程度。
方差分析的实践(或简称方差分析)涉及数据科学家评估两个数值之间的差异。通常,这一过程应用于财务或运营数据,试图识别并确定方差的原因。在应用统计学中,方差分析有不同的形式。
方差和方差分析是统计学领域中的一个重要话题,它在以下统计实践中发挥着关键作用:
你会发现方差分析有以下规律:
-
每当需要进行数据的统计分析时,数据科学家很可能会首先进行方差分析。
-
统计方差为数据科学家提供了一个衡量数据如何分布(围绕均值或预期值)的标准。
-
与范围(仅看极端值)不同,方差会考虑所有数据点,并得出它们的分布结论。
方差分析(ANOVA)
作为数据科学家,当你谈论方差分析的过程或实践时,你实际上是在谈论ANOVA。ANOVA 可以理解为一系列方法,用于研究群体均值之间发现或潜在的差异(方差)及其相关过程。
方差分析(ANOVA)在统计学领域有三种不同的研究和应用方式。这些方式由数据科学家处理或感兴趣的独立变量的数量来决定和定义:
-
单因素方差分析(只处理一个独立变量)
-
双因素方差分析(使用或关注两个独立变量)
-
多因素方差分析(当数据科学家感兴趣的不止两个独立变量时)
当数据科学家或研究人员进行 ANOVA 时,他们的目的是判断其群体内部是否存在统计学上显著的差异。如果他们发现存在差异,他们将继续确定这些群体差异的具体位置。
噪声
噪声,或者对数据科学家来说,统计噪声,是指在样本、群体或数据源中公认的无法解释的变化量或变异性。
噪声一词的实际应用可以追溯到早期的信号处理,当时它被用来指代那些被发现会降低信号和数据质量的、不希望出现的(电磁)能量。
对于数据或数据库开发人员来说,考虑这样一个例子:运行一个简单的数据库查询,来确定某个特定销售区域的业绩。如果你的 SQL 查询返回所有销售区域的销售数据,那么在这个练习的背景下,你可能会把其他的销售区域看作噪声,这些噪声使得销售信息变得无用(再说一次,是在试图关注某个特定销售区域的背景下)。当然,为了解决这个问题,你可以重新构造查询,以过滤掉不需要的区域,或者修改查询结果,以去除不需要区域的噪声。请记住,在统计学中,重建数据源可能不现实。
噪声数据
在统计学之外,人们常常使用“统计噪声”这一术语来抛开他们不感兴趣的数据。一个例子是职业足球队的体育场,球迷的欢呼声干扰了客队的沟通能力。噪声成了不便。
然而,在统计学中,当数据科学家意识到样本中存在噪声时,意味着任何来自统计抽样的结果,如果重复这个过程,可能无法再现。在这种情况下,样本可能变成噪声数据,并因为过多的变异而变得毫无意义。
揭示噪声与真实信号之间的关系,几乎一直是统计学中的一个重要议题(以便研究人员能够使用有意义的数据),然而,噪声数据中有意义的数据比例通常太小,以至于难以派上用场。
随着时间的推移,噪声数据这个术语也被用来指代任何机器无法读取的数据,例如非结构化文本,甚至是任何在某种程度上被修改,导致不再与创建它的程序兼容的数据。幸运的是,分析工具的进步正在稳步克服这些统计障碍(比如 IBM Watson 分析工具,当然还有许多其他工具)。
一些最常见的统计噪声示例包括高斯噪声、散射噪声和白噪声。好了,够了,我们不再谈论(统计)噪声了!
让我们继续讨论学习者。
弱学习者和强学习者
一个很好的过渡(回到)提升方法的主题,是统计算法或模型在时间推移中的预测能力的提升,也就是其性能的提高。
如果你正在阅读这本书,并且已经到达了这一章节的这一部分,那么假设你已经理解了与统计预测相关的机器学习概念。学习是指计算机或模型能够学习(如何根据数据做出预测),而不需要明确的编程指令。
我们使用术语显式地来表示基于数据值的硬编码选择。
如果你基于这一概念进一步思考,你可以理解,计算机或模型的目标是基于数据做出良好预测(正确猜测结果),其表现或结果会介于不正确(差)和正确(好)之间。
也可以说,计算机或模型或许能通过更多经验(更多数据)来提高其表现,并且能以某个速率改善学习。
因此,数据科学家会根据计算机或模型的表现(或其预测或猜测结果的能力)将其标记为弱学习器或强学习器。
在统计学和数据科学领域,人们也可以将学习器称为分类器或预测器。
那么,如何界定一个学习器是弱还是强呢?
弱学习器是指无论数据呈现何种形式(意味着模型训练数据中的值分布),在尝试标记数据时,总能比随机猜测表现得更好。
我们将做得比随机猜测好定义为始终具有小于一半的错误率。
从弱到强
比随机 猜测 好,基本上是弱学习器的唯一先决条件。因此,只要算法或模型能始终优于随机猜测,应用提升算法将能提高模型预测的准确性(其表现),从而将模型从弱学习器转变为强学习器。
请注意,数据科学家一致认为,将模型的预测能力或表现提高,即使只是略微优于随机猜测,也意味着成功。
当数据科学家考虑提升模型表现(或将弱学习器转变为强学习器)时,需要考虑许多因素。
这些因素包括模型偏差、处理时间和复杂性。让我们稍微解释一下每一个。
模型偏差
我们在本章的早期部分讨论了统计偏差。在统计模型中识别的偏差水平需要被考虑。通常,偏差越小越好,因为一些改善弱学习器的方法——例如提升(boosting)——可能会导致过拟合,从而产生误导性的结果。
训练和预测时间
无论如何,提升弱学习器表现的方法是否显著增加了模型学习、训练或在数据子集上预测的时间。通常,训练得越多,结果越好,因此如果你预期需要进行数百次训练迭代,你需要考虑如果改进使训练迭代增加 100%,这一过程或努力将需要多长时间。
复杂性
通常会假设弱学习者在设计上计算上比较简单(它是一个弱学习者,对吧?),但情况并不总是如此。在选择提升性能的方法之前,理解算法或模型的复杂程度对决策过程至关重要。
哪种方式?
数据科学家为了提升模型性能,将其从弱学习者转变为强学习者,最终选择哪种方式(方法)将取决于许多因素,但归根结底,所采取的方法依赖于具体问题。
AdaBoost(也称为自适应提升)是一个迭代算法,使用指定次数的迭代或回合来提升一个弱学习者。该算法从在数据上训练/测试一个弱学习者开始,为每个示例赋予相等的权重。那些被错误分类的示例,其权重将在下一轮(回合)中增加,而正确分类的示例则会减小其权重。
我们将在本章稍后了解 AdaBoost。
回到提升
到此为止,我们已经涵盖了与提升(boosting)最相关的所有话题,现在让我们回到重点,统计提升。
我们已经描述了统计提升是什么以及它的用途(即旨在减少偏差和方差,并将弱学习者转变为强学习者的学习算法)。
这个概念的关键在于学习者的行为方式,其中弱学习者被定义为与真实分类仅有轻微相关性的学习者(它比随机猜测更能正确标记示例)。相对地,强学习者则是与真实分类有良好相关性的学习者。
它是如何开始的
尝试通过提升算法来提高性能,实际上是一个假设问题。也就是说,这是每个数据科学家都应该问自己在其统计算法或模型中的问题。
这在统计学中被称为假设提升问题,核心是数据科学家寻找一种方法,即使是稍微改进学习过程(将弱学习者转变为更强的学习者)。
强学习者的概念仅仅意味着稍微改进的学习者——实际上,它仅比随机猜测略好。
在数据科学或统计学领域,假设提升问题也暗示着存在一个高效的算法,它能输出一个针对所解决问题的任意准确度的假设。这些(能够改善学习者的)算法迅速被称为提升。
一如既往,数据科学家交替使用不同术语来表示相同的概念,提升也不例外,一些数据科学家会将提升称为重采样或组合。
AdaBoost
回到我们之前提到的一个名为AdaBoost的包,它是自适应增强(adaptive boosting)的缩写。AdaBoost 是一种增强方法,通常被称为集成学习算法。集成学习是指通过结合多个学习器来构建一个更强大的学习算法。
AdaBoost 的工作原理是选择一个基础算法,然后通过考虑训练数据集中的错误分类样本,迭代地改进它。
在线可以找到对增强和 AdaBoost 的精彩解释:通过 AdaBoost 实现更好的生活 bbacon.org/Better-Living-Through-AdaBoost
。
上述文章描述了 AdaBoost 的工作原理:
-
AdaBoost 在数据子集上训练一个模型
-
弱学习器(基于性能)被加权
-
这个过程会重复进行
从叙述的角度来看,AdaBoost 增强逻辑可以通过以下方式来解释:
-
该过程通过在训练数据上构建模型,然后衡量结果在训练数据上的准确性,接着:
- 在模型中那些错误的个体结果会被赋予更大的权重(或赋予更多的权重),而正确的结果则不会,然后模型会使用这些新的权重进行再训练。这个逻辑会重复多次,每次根据上一次迭代中是否正确分类来调整个体观察的权重!
AdaBoost 算法最初由Freund和Schapire在 1997 年发表于《计算机与系统科学杂志》上的一篇论文中提出,论文标题为在线学习的决策理论推广及其在增强中的应用。
你可以从增强(以帮助)你的数据库中学到什么
从数据库开发者的角度思考,你可能正在尝试构思增强的过程。正如我们在本书中所做的那样,在这里,我们将尝试使用一个面向数据库的示例来帮助我们理解增强:
我们的示例从一个关系数据库开始。在那里,有效的索引是提高数据库应用程序性能的最佳方式之一。如果没有有效的(强大的)索引,数据库引擎就像是一个读者,试图通过检查每一页来找到参考书中的某个短语。但如果读者使用参考书的索引,那么读者就能在更短的时间内完成任务(更好的性能 = 更好的结果)。
在数据库术语中,当没有可用的索引来提升数据库查询性能时,就会发生表扫描。在表扫描中,数据库引擎检查表中的每一行,以满足查询结果。
数据库开发者最重要的工作之一是找到生成执行计划时使用的最佳索引(针对查询)。大多数主要数据库都提供工具来显示查询的执行计划,并帮助优化和调优查询索引。
前述情况可以与在数据库中反复测试查询、评分每个查询结果的表现(即返回查询结果)直到确定一个高效(或强大的)索引进行比较。
这会改善数据库查询的性能,使其成为强大的响应者(或者,如果你愿意,可以说是强大的学习者)。
使用 R 语言展示提升方法
为了进一步说明提升方法的使用,我们应该有一个示例。
在本节中,我们将从Mastering Predictive Analytics with R, Second Edition, James D. Miller 和 Rui Miguel Forte,2017 年 8 月(www.packtpub.com/big-data-and-business-intelligence/mastering-predictive-analytics-r-second-edition
)中引入一个发人深思的预测问题,做一个高层次的回顾。
在这个原始示例中,分析了望远镜相机上辐射形成的图案,试图预测某一特定图案是来自大气中泄漏的γ射线还是来自常规的背景辐射。
γ射线会留下具有独特椭圆形状的图案,因此我们可以创建一组特征来描述这些图案。使用的数据集是MAGIC Gamma Telescope Data Set,由UCI Machine Learning Repository 提供,网址为archive.ics.uci.edu/ml/datasets/MAGIC+Gamma+Telescope
。
该数据集包含 19,020 个观测值,具有以下属性列表:
列名 | 类型 | 定义 |
---|---|---|
FLENGTH |
数值型 | 椭圆的主轴(毫米) |
FWIDTH |
数值型 | 椭圆的次轴(毫米) |
FSIZE |
数值型 | 所有像素内容总和的十进对数 |
FCONC |
数值型 | 两个最高像素之和与FSIZE 的比率 |
FCONC1 |
数值型 | 最高像素与FSIZE 的比率 |
FASYM |
数值型 | 从最高像素到中心的距离,投影到主轴上(毫米) |
FM3LONG |
数值型 | 沿主轴的三次矩的三次根(毫米) |
FM3TRANS |
数值型 | 沿次轴的三次矩的三次根(毫米) |
FALPHA |
数值型 | 主轴与指向原点的向量之间的角度(度) |
FDIST |
数值型 | 从原点到椭圆中心的距离(毫米) |
CLASS |
二元 | γ射线(g)或背景哈德龙辐射(b) |
数据准备
首先,需要对我们的示例数据执行多个步骤。
数据首先加载到一个名为magic
的 R 数据框对象中,并将CLASS
输出变量重新编码,分别使用1
和-1
表示伽马射线和背景辐射:
> magic <- read.csv("magic04.data", header = FALSE)
> names(magic) <- c("FLENGTH", "FWIDTH", "FSIZE", "FCONC", "FCONC1",
"FASYM", "FM3LONG", "FM3TRANS", "FALPHA", "FDIST", "CLASS")
> magic$CLASS <- as.factor(ifelse(magic$CLASS =='g', 1, -1))
接下来,将数据分成两个文件:训练数据和测试数据框,采用 80-20 的拆分方式:
> library(caret)
> set.seed(33711209)
> magic_sampling_vector <- createDataPartition(magic$CLASS,
p = 0.80, list = FALSE)
> magic_train <- magic[magic_sampling_vector, 1:10]
> magic_train_output <- magic[magic_sampling_vector, 11]
> magic_test <- magic[-magic_sampling_vector, 1:10]
> magic_test_output <- magic[-magic_sampling_vector, 11]
用于提升的模型是一个简单的多层感知机,具有一个单隐藏层,利用 R 的nnet
包。
神经网络(在第九章,数据库与神经网络中讨论)通常在输入数据标准化时能产生更高的准确性,因此在本例中,在训练任何模型之前,首先执行此预处理:
> magic_pp <- preProcess(magic_train, method = c("center",
"scale"))
> magic_train_pp <- predict(magic_pp, magic_train)
> magic_train_df_pp <- cbind(magic_train_pp,
CLASS = magic_train_output)
> magic_test_pp <- predict(magic_pp, magic_test)
训练
提升(Boosting)旨在与弱学习者一起最佳工作,因此在模型的隐藏层中使用非常少量的隐藏神经元。
具体来说,我们将从最简单的多层感知机开始,使用一个隐藏神经元。为了理解提升的效果,通过训练一个单一的神经网络并测量其性能来建立基准性能。
这将完成以下任务:
> library(nnet)
> n_model <- nnet(CLASS ~ ., data = magic_train_df_pp, size = 1)
> n_test_predictions <- predict(n_model, magic_test_pp,
type = "class")
> (n_test_accuracy <- mean(n_test_predictions ==
magic_test_output))
[1] 0.7948988
这表明我们有一个大约 79.5%的基准准确率。还不错,但是否可以通过提升来改善这个得分呢?
为此,使用如下的AdaBoostNN()
函数。该函数将接受数据框输入、输出变量的名称、要构建的单层隐藏神经网络模型数量,最后是这些神经网络将包含的隐藏单元数量。
然后,该函数将实现 AdaBoost 算法,并返回一个包含相应权重的模型列表。
这是该函数:
AdaBoostNN <- function(training_data, output_column, M,
hidden_units) {
require("nnet")
models <- list()
alphas <- list()
n <- nrow(training_data)
model_formula <- as.formula(paste(output_column, '~ .', sep = ''))
w <- rep((1/n), n)
for (m in 1:M) {
model <- nnet(model_formula, data = training_data,
size = hidden_units, weights = w)
models[[m]] <- model
predictions <- as.numeric(predict(model,
training_data[, -which(names(training_data) ==
output_column)], type = "class"))
errors <- predictions != training_data[, output_column]
error_rate <- sum(w * as.numeric(errors)) / sum(w)
alpha <- 0.5 * log((1 - error_rate) / error_rate)
alphas[[m]] <- alpha
temp_w <- mapply(function(x, y) if (y) { x * exp(alpha) }
else { x * exp(-alpha)}, w, errors)
w <- temp_w / sum(temp_w)
}
return(list(models = models, alphas = unlist(alphas)))
}
上述函数使用以下逻辑:
-
首先,初始化空的模型和模型权重(
alphas
)列表。计算训练数据中的观测值数量,并将其存储在变量n
中。然后,使用提供的输出列名称创建一个公式,描述将构建的神经网络。 -
在所使用的数据集中,该公式将是
CLASS ~ .
,意味着神经网络将计算CLASS
作为所有其他列(输入特征)的函数。 -
接下来,初始化权重向量并定义一个循环,该循环将运行
M
次迭代,以构建M
个模型。 -
在每次迭代中,第一步是使用当前的权重向量设置来训练神经网络,使用输入中指定的隐藏单元数量
hidden_units
。 -
然后,使用
predict()
函数计算模型在训练数据上生成的预测向量。通过将这些预测与训练数据的输出列进行比较,计算当前模型在训练数据上的误差。这将允许计算误差率。 -
该错误率被设置为当前模型的权重,最后,观察权重将根据每个观察是否被正确分类,更新以便在下一次迭代中使用。
-
然后,权重向量将被归一化,接下来我们就可以开始下一次迭代了!
-
完成
M
次迭代后,输出模型列表及其对应的模型权重。
准备进行提升
现在有一个函数可以使用 AdaBoost 训练我们的集成分类器,但我们还需要一个函数来进行实际的预测。该函数将接受由我们训练函数AdaBoostNN()
产生的输出列表,以及一个测试数据集。
该函数是AdaBoostNN.predict()
,其表现如下所示:
AdaBoostNN.predict <- function(ada_model, test_data) {
models <- ada_model$models
alphas <- ada_model$alphas
prediction_matrix <- sapply(models, function (x)
as.numeric(predict(x, test_data, type = "class")))
weighted_predictions <- t(apply(prediction_matrix, 1,
function(x) mapply(function(y, z) y * z, x, alphas)))
final_predictions <- apply(weighted_predictions, 1,
function(x) sign(sum(x)))
return(final_predictions)
}
该函数首先提取模型和模型权重(来自前一个函数产生的列表)。然后创建一个预测矩阵,其中每列对应于某个特定模型所做的预测向量。因此,这个矩阵的列数将等于我们用于提升的模型数量。
然后,我们将每个模型产生的预测与其对应的模型权重相乘。例如,第一个模型的每个预测值都位于预测矩阵的第一列,并将其值乘以第一个模型的权重α[1]。
最后,通过对每个观察的加权预测求和,并取结果的符号,将加权观察矩阵减少为一个单一的观察向量。这个预测向量将由函数返回。
作为实验,我们将训练十个带有单个隐藏单元的神经网络模型,并观察提升是否提高了准确率:
> ada_model <- AdaBoostNN(magic_train_df_pp, 'CLASS', 10, 1)
> predictions <- AdaBoostNN.predict(ada_model, magic_test_pp,
'CLASS')
> mean(predictions == magic_test_output)
[1] 0.804365
在这个例子中,提升十个模型仅显示了微小的准确率提高,但或许训练更多的模型可能会带来更大的变化。
正如我们在本章中多次提到的,即使是性能上的微小提升,也足以将一个弱学习器转化为强学习器!
示例结果
从上面的例子中,你可能得出结论,对于具有一个隐藏单元的神经网络,随着提升模型数量的增加,我们看到准确度有所提高,但在达到 100 个模型后,这种提升开始减缓,甚至在 200 个模型时稍微下降。与单一模型的基准相比,这些网络的提升是显著的。当我们通过添加一个包含三个隐藏神经元的隐藏层来增加学习器的复杂度时,性能的提升就变得非常小。在 200 个模型时,两个集成模型表现相似,这表明此时我们的准确度受限于训练的模型类型。
总结
在本章中,我们发现了统计提升,首先提供了与提升主题相关的统计学关键概念的解释,从而有助于定义提升算法本身。
我们还考虑了使用统计提升来更好地理解几乎每个数据库中的数据的概念。
在下一章中,我们将再次努力使用开发者术语,这次旨在定义支持向量机,识别其各种应用,并通过一个简单的 SVM 示例,演示如何使用支持向量机对数据库中的数据进行分类。
第十一章:使用支持向量机进行数据库分类
本章我们将探讨支持向量机(SVMs),识别它们的各种应用,并通过一个使用简单 SVM 对数据库中的数据进行分类的示例来说明。
本章中,我们将再次将主题组织成以下几个主要领域:
-
数据库分类
-
SVM 的定义和用途
-
常见的支持向量机(SVM)应用
-
使用 R 语言和支持向量机对数据库中的数据进行分类
让我们从一些关于通用数据分类的对话开始本章内容。
数据库分类
正如我们在本书中所提到的,如果读者是数据或数据库开发人员,或者有类似的背景,那么读者很可能听说过并且熟悉数据建模的过程。可以简单地将其描述为分析和理解某些数据的构成和细节的努力。然后,这些数据被组织或分类,目标是使其能够被用户社区轻松理解和使用,无论是已命名的(如组织中的财务分析师)还是匿名的(如互联网用户)。下图展示了根据需求进行的数据分类:
匿名访问是最常见的系统访问控制方法,至少在网站方面是如此。
作为几乎任何数据建模开发项目的一部分,可能会要求创建类图。这个(类)图详细说明了如何将数据(或数据库)拆分为离散的对象,这些对象之间的关系,以及它们可能拥有的任何已知接口或连接。类图中的每个类既可以包含数据,也可以包含其用途。
因此,数据分类是将数据按照不同的类型、形式或任何其他不同类别进行排序和分类的过程。
数据分类使得根据数据的既定要求,将数据进行分离和归类,以满足多个业务或其他目标,从而可以制定数据计划或数据模型:
也许一个现实世界的例子,一个数据库或数据开发人员可能会认同或有一定了解的例子,是对财务账户进行分类或重新分类的工作,以便进行报告。
例如,在财务报告项目中(或者可能是在典型的会计期间结算时),你可能会发现一个典型的、反复进行的操作是对每个账户进行详细审查,并对正在使用的账户进行合并,以报告一个组织的财务结果或表现。
对会计部门而言,术语分类(或重新分类)通常用于定义将金额从一个总账(GL)账户转移到另一个账户。例如,如果某项费用(例如税务准备)被错误地记入了市场营销用品账户而不是行政用品账户,那么更正分录可能是:
从市场营销用品账户重新分类到行政用品账户。
在这里,从会计部门的角度来看,我们讨论的是一笔实际交易,即从一个 GL 账户中扣除金额并将该金额加到另一个账户。对于数据开发者而言,虽然没有进行账户交易,但可能会运行一个编程变更或流程,移除某个账户(或将多个账户合并)并转移到另一个账户。这通常被称为更新账务科目报告层级,或科目表(COA)维护。
我们会发现这些相同的概念在统计学领域也适用吗?
在本章的以下部分,我们将回答这个问题。
统计学中的数据分类
一些数据科学家或统计学家将统计数据分类定义为:
将数据划分为有意义的类别以进行分析。
阅读此内容的数据库开发人员应该能够理解这一点:
在数据科学和统计学中,分类被定义为根据包含已验证类别成员的训练数据集,确定一个新的观察值应归入哪个类别(有时称为子群体)。
数据科学家通常会自动将统计公式应用于数据,允许在进行统计分析准备时处理大数据。
通常情况下,未组织或未分类的人群数据(通常称为原始数据),这些数据是在实际情况下收集并且无序排列的,并不会为数据科学家提供任何清晰的理解,只能得到基于不充分意见的直觉。
数据分类的过程试图在数据中找到相似性,并通过去除不必要的细节或噪音(我们在第十章中讨论过,提升你的数据库)来简化数据。分类有助于对不同数据集之间进行比较,清晰地显示一致与不一致的点。
数据分类还可以帮助确定数据使用的基准线。
分类使数据科学家能够研究多个特征之间的关系,并进行进一步的统计处理,如制表等。
一个非常好的统计数据分类受益的例子是年度人口普查,其中人口根据性别、年龄、婚姻状况等进行分类。
数据分类指南
指南(或政策)的目的是为执行某个任务建立框架。对于统计分类,存在许多不同的思维流派,关于最佳方法或最有效的方法。
在统计数据分类中,数据科学家将通过分配限制或边界来对数据进行分类。这些通常被称为类别限制。任何两个类别限制之间的组被称为类别或类别区间。
在你的统计学旅程中,你可能也遇到过术语决策边界。数据科学家经常使用不同或相似的术语来指代某个概念。在涉及两个类别的统计分类问题中,他们可能会使用决策 边界或决策 面来定义一个超平面(超平面是超平面概念的广义化),它将基础向量空间划分为两个集合,每个集合对应一个类别。分类器会将决策边界一侧的所有点归为一个类别,另一侧的所有点归为另一个类别。
常见指南
分类的指南通常会遵循以下内容:
-
对类别的定义应该毫无疑问
-
所有类别最好具有相同的宽度或长度
-
类别的限制应当选择使得原始数据中的任何项都不与限制值重合
-
类别的数量最好在 10 到 20 之间,即既不太大也不太小
-
类别应该是详尽无遗的,也就是说,每个原始数据的值都应该包含在其中。
-
类别应当是互斥且不重叠的,也就是说,原始数据中的每一项应该只适合一个类别
-
分类必须适用于研究对象
-
分类应该是灵活的,每个类别中包含的项目必须保持一致
-
类别区间的宽度由首先固定类别区间的数量,然后将总范围除以该数量来决定
指南适用于数据科学家用于分类的任何指导方针或政策。这些指导方针或政策必须适用于统计项目开始到完成期间所有被观察到的数据。
定义
数据科学家必须了解的几个关键术语,因为这些术语可能会影响分类方法的选择,分别是:
-
机密数据通常指的是任何被分类为受限的数据,且常与敏感数据互换使用
-
数据管理员通常是一个高级资源,负责监督一个或多个数据集的生命周期,以便进行分类
-
超平面子空间;一个 n 维欧几里得空间是平坦的,n 到该空间的一维子集将空间分为两个不相连的部分
-
特征选择是选择用于构建统计模型的相关特征(变量、预测因子)子集的行为。
-
特征空间简单来说是指用于描述数据的特征集合。
-
统计分类是识别新观察值应属于哪一类类别(子群体)的问题。
-
软边界分类是一种分类方法,其中数据科学家允许在定义或创建分类器时出现一些错误。
-
机构数据被定义为由大学维护或许可的所有数据。
-
边界分类器是一种能够为数据中的每个示例提供决策边界的伴随距离的分类器。
-
非公开信息是根据指南、政策或法律规定的私密或受限信息。
-
敏感数据通常指被归类为受限的数据,并且常常与机密数据交替使用。
-
属性描述符;有时分类系统会使用描述符来传达给定分类的原因;例如,中年或城市化是常见的描述符。
-
互操作性;当不同的应用程序使用不同的描述符,并且对哪些属性是必需的,哪些是可选的有不同的规则时(对于特定分类),这如何支持互操作性?
读者应该花时间研究与统计数据分类相关的许多术语——在统计学领域中,还有许多其他数据定义的术语。
SVM 的定义和目的
我支持支持向量机,你呢?
在机器学习领域,SVM 也被称为支持向量网络,并被定义为有监督学习模型,伴随的学习算法分析用于分类的数据。
关于 SVM 的一个重要说明是,它们完全是关于成功执行模式识别的能力。换句话说,SVM 促进了在数据中扩展找到的模式的能力,这些模式是:
通过对原始数据进行变换来映射到新空间时,不能线性分离。
再次强调,你所了解的所有关于 SVM 的内容都会与 SVM 是一个有监督的机器学习算法这一观念相符合,这种算法最常用于统计学中的分类或回归问题。
这个技巧
你今天会听到大多数数据科学家提到技巧或 SVM 技巧;他们指的就是支持向量机算法使用一种称为核心技巧的方法。
核心技巧通过对数据进行变换,然后基于这些变换来发现可能输出或数据点之间的最优边界(记住,我们在本章前面定义了分类边界)。
在统计学中,核方法是一种用于模式分析的算法。执行模式分析的总体任务是找到并研究数据中普遍的关系类型。
基本上,SVM 执行的变换是一些极其复杂的数据变换(对你的数据进行处理),然后通过这些变换有效地找出如何根据数据科学家事先定义的标签或输出(有时被认为是数据科学家定义的特征)来分离数据。
另一个需要注意的重要(并且引人深思)点是,数据科学家在 SVM 执行变换时,并不需要担心保持数据的原始维度。
因此,核技巧将原始数据和一些事先定义的特征进行处理,执行其变换,并生成你可能无法识别的输出——有点像揭开一个巨大的迷宫!
以下内容摘自 www.yaksis.com/posts/why-use-svm.html,为什么使用 SVM?:
“你从这一个看似无害的数据向量开始,经过核技巧处理后,它被展开并且自我组合,直到它变成一个更大的数据集,单纯从电子表格中是无法理解的。”
“但魔法在这里,随着数据集的扩展,你的类别之间现在有了更明显的边界,SVM 算法能够计算出一个更加优化的超平面。”
特征空间和低成本计算
理解 SVM 如何工作的一个重要部分,就是理解我们刚才提到的技巧。这个技巧,正如我们所说,使用核方法(即使用核函数),并且能够在高维特征空间中表现良好。
特征空间是一个 n 维空间,其中包含你的数据变量。核函数能够在这个高维空间内操作,而无需计算数据在该空间中的坐标,而只需计算特征空间中所有数据对的图像之间的内积。
这个核技巧可以比显式计算坐标更快、更高效地处理数据。这被称为计算开销小。
对于数据或数据库开发者来说,由于数据库视图可以隐藏复杂性;可以想象将数据库中的数据划分为多个编译视图(而不是对所有数据作为单一源运行查询)这一概念,类似于支持向量机(SVM)如何定义和使用向量。
画出分割线
描述支持向量机在分类数据时所执行的功能性(或实际)步骤的一种好方法是,想象 SVM 不断努力寻找 最佳分割线 ,以最优地分离两类数据点:
在这里,最佳的线是指通过最大化两个分类之间的边界来定义的直线。位于此边界上的点即为支持向量。
认识到这些(支持)向量的好处在于,我们可以将寻找最大边界超平面(即最能分离两个类别的直线)的问题,表述为一个优化问题,该问题仅考虑 SVM 所确定的支持向量。
这意味着 SVM 处理可以忽略绝大多数数据,从而使得分类过程更加高效。
更重要的是,通过将问题呈现为支持向量(即所谓的对偶形式),我们可以利用本章之前定义的核技巧,将支持向量机有效地转化为一个非线性分类器。
线性方法只能解决线性可分的问题(通常通过超平面)。非线性方法的特点是对输入数据集进行某种类型的转换。
不仅仅是分类
另一个关键点是,除了分类,SVM 还可以进行回归。
使用非线性核算法的 SVM 意味着算法计算出的边界不必是直线;这意味着 SVM 可以捕捉到数据点之间更为复杂的关系,而无需数据科学家手动进行那些复杂的转换。
缺点
那么,我们能否找到使用支持向量机的缺点或不足之处?
是的,有时候 SVM 所需的训练时间要长得多,而且计算开销也要大得多(我们在本章之前提到过计算成本的问题)。
参考资源
一本非常易懂的关于 SVM 的书籍是 NelloChristiani 和 John Shawe-Taylor 的An Introduction to Support Vector Machines and Other Kernel-based Learning Methods。
另一个值得参考的资料是《Neural Networks and Learning Machines》一书,作者为 Simon Haykin,书中提供了对支持向量机(SVM)与一种称为径向基函数网络的神经网络类型之间的深入关联的解析,我们也在第五章《神经网络》中引用了这本书。
预测信用评分
在本章的剩余部分,我们将尝试像数据开发者一样,通过 R 语言回顾一个 SVM 示例。
这个示例可以在线访问,并在《Mastering Predictive Analytics with R, Second Edition》一书的第六章中详细引用。
www.packtpub.com/big-data-and-business-intelligence/mastering-predictive-analytics-r-second-edition
如果你是数据开发者,可能不知道以下网站提供了非常好的测试数据集资源:archive.ics.uci.edu/ml/index.php
本示例使用的特定数据集是Statlog(德国信用数据)数据集,可以在以下网址找到:archive.ics.uci.edu/ml/datasets/statlog+(german+credit+data)
网站如下所示:
该数据集来自银行和金融领域。数据集中的观察是个人在银行申请的贷款。
该数据的目标是确定贷款申请是否构成高信用风险。
数据或数据库开发人员很可能会注意到,与其下载一个数据集,不如创建查询来提取数据作为记录或交易,而不是实例(或观察)。
如果从数据库中提取这些数据,最有可能的情况是,提取不会像仅查询一个表那样简单,因为贷款申请可能以交易的形式存在,需要从多个数据库表中提取数据点。
数据开发人员应考虑的其他事项包括:
-
数据集特征——字段名称
-
属性特征——数据类型
-
捐赠日期——最后更新或添加日期
网站 https://archive.ics.uci.edu/ml/machine-learning-databases/statlog/german/提供了两个关键文件:一个是实际数据,另一个是数据模式:
数据模式是 MS Word 文档格式(german.doc
),用于创建以下矩阵:
列名 | 类型 | 定义 |
---|---|---|
支票账户 | 分类 | 现有支票账户的状态 |
持续时间 | 数值型 | 以月为单位的贷款期限 |
信用历史 | 分类 | 申请人的信用历史 |
目的 | 分类 | 贷款的目的 |
信用 | 数值型 | 信用金额 |
储蓄 | 分类 | 储蓄账户/债券 |
就业 | 分类 | 目前就业自 |
分期利率 | 数值型 | 分期利率(占可支配收入的百分比) |
个人 | 分类 | 个人状况和性别 |
债务人 | 分类 | 其他债务人/担保人 |
现居住地 | 数值型 | 目前居住地自 |
财产 | 分类 | 财产类型 |
年龄 | 数值型 | 申请人年龄(以年为单位) |
其他计划 | 分类 | 其他分期付款计划 |
住房 | 分类 | 申请人的住房状况 |
现有银行信贷 | 数值型 | 在此银行的现有信贷数量 |
职业 | 分类 | 申请人的工作状况 |
赡养人 | 数值型 | 赡养人数量 |
电话 | 分类 | 申请人电话状态 |
外国人 | 分类 | 外籍工人 |
风险 | 二进制 | 信用风险(1 = 良好,2 = 差) |
原始数据如下所示:
使用 R 和 SVM 在数据库中分类数据
现在我们已经理解了数据,接下来可以继续进行这个特定的统计学示例。
首先,数据科学家需要将数据加载到 R 的数据框对象中。这个示例中将其命名为 german_raw.
# --- load the data
german_raw<- read.table("german.data", quote = "\"")
下一步是提供与我们数据模式表格匹配的列名,如前所示:
names(german_raw) <- c("checking", "duration", "creditHistory",
"purpose", "credit", "savings", "employment", "installmentRate",
"personal", "debtors", "presentResidence", "property", "age",
"otherPlans", "housing", "existingBankCredits", "job",
"dependents", "telephone", "foreign", "risk")
从数据模式(描述数据特征的表格)中可以注意到,我们有许多分类特征需要处理。因此,数据科学家可以使用 R 的 dummyVars()
函数(用于创建一整套虚拟变量)来创建用于分析的虚拟二元变量。此外,他或她还会将输出变量 risk
记录为一个因子变量,使用以下方式:
-
level 0 = 良好信用
-
level 1 = 不良信用
library(caret)
dummies <- dummyVars(risk ~ ., data = german_raw)
german<- data.frame(predict(dummies, newdata = german_raw),
risk = factor((german_raw$risk - 1)))
dim(german)
[1] 1000 62
经过之前的工作后,结果将得到一个包含 61 个特征的 R 数据框对象(因为一些分类输入特征具有多个级别)。
接下来,数据科学家会将数据分成两个子集:
-
训练数据集
-
测试数据集
这种数据划分可以通过以下 R 语句实现:
set.seed(977)
german_sampling_vector<- createDataPartition(german$risk,
p = 0.80, list = FALSE)
german_train<- german[german_sampling_vector,]
german_test<- german[-german_sampling_vector,]
对于数据开发人员,采取类似的方法,如可能使用 from
子句中的 TABLESAMPLE 选项。使用 TAMPLESAMPLE 选项,你可以从表中获取数据的样本集,而无需读取整个表或为每一行数据分配临时随机值。
继续
在(之前提到的)网站上提到,这个数据集的一个特殊性是,数据来自于一个场景,在这个场景中,定义的两种错误类型具有不同的相关成本。
具体而言,将高风险客户误判为低风险客户的成本是银行将低风险客户误判为高风险客户的五倍。这是可以理解的,因为在第一种情况下,银行可能会因无法偿还的贷款而损失大量资金,而在第二种情况下,银行错失了一个可以带来利息收入的贷款机会。
这是一个实际的例子,其中预测分析直接影响了组织的盈利。
svm()
R 函数具有一个 class.weights
参数,之后该参数用于指定误分类(每个类别的观察值)成本。这就是数据科学家如何将不对称的错误成本信息纳入模型。
首先,创建一个类别权重向量,并注意需要指定与输出因子水平对应的名称。
然后,数据科学家使用 R 的 tune()
函数训练多个具有径向核函数的 SVM 模型:
class_weights<- c(1, 5)
names(class_weights) <- c("0", "1")
class_weights
0 1
1 5
set.seed(2423)
german_radial_tune<- tune(svm,risk ~ ., data = german_train,
kernel = "radial", ranges = list(cost = c(0.01, 0.1, 1, 10, 100),
gamma = c(0.01, 0.05, 0.1, 0.5, 1)), class.weights = class_weights)
german_radial_tune$best.parameters
cost gamma
9 10 0.05
german_radial_tune$best.performance
[1] 0.26
这里推荐的最佳模型成本为 10,gamma 为 0.05,并且训练准确率达到 74%。
接下来,我们查看模型在测试数据集上的表现:
german_model<- german_radial_tune$best.model
test_predictions<- predict(german_model, german_test[,1:61])
mean(test_predictions == german_test[,62])
[1] 0.735
table(predicted = test_predictions, actual = german_test[,62])
actual
predicted 0 1
0 134 47
1 6 13
测试集上的表现为 73.5%,与模型训练时的结果非常接近。如预期所示,该模型倾向于产生更多错误,将低风险客户误分类为高风险客户。
不出所料,这对整体分类准确度造成了影响,准确度仅仅计算正确分类的观察结果与总观察结果的比例。事实上,如果我们去除这种成本不平衡,我们实际上会为模型选择一组不同的参数,从无偏分类准确度的角度来看,性能会更好:
set.seed(2423)
german_radial_tune_unbiased<- tune(svm,risk ~ .,
data = german_train, kernel = "radial", ranges = list(
cost = c(0.01, 0.1, 1, 10, 100), gamma = c(0.01, 0.05, 0.1, 0.5, 1)))
german_radial_tune_unbiased$best.parameters
cost gamma
3 1 0.01
german_radial_tune_unbiased$best.performance
[1] 0.23875
当然,最后这个模型会倾向于将更多高风险客户误分类为低风险客户,而这种错误分类是非常不希望发生的。我们将在本节结束时提出两个最后的想法。首先,我们为gamma
和cost
参数使用了相对较小的范围。
最初,当这个示例呈现时,它被作为“留给读者的练习”,让读者使用更广泛的数值范围重新运行分析,以查看我们是否能获得更好的性能,这很可能会导致更长的训练时间。
其次,那个特定数据集相当具有挑战性,因为它的基准准确度实际上是 70%。这是因为数据中有 70%的客户是低风险客户(两个输出类别是不平衡的)。
呼!
总结
在本章中,我们通过一些数据开发者可能熟悉的示例定义了数据库和数据分类的概念。接下来,我们介绍了统计数据分类,并将这一概念与前者进行了比较。
提供了分类指南以及几个重要的相关术语。
最后,我们讨论了支持向量机、它们的工作原理以及它们为数据科学家提供的优势。
在下一章中,我们旨在解释机器学习的类型,并向开发者展示如何利用机器学习过程来理解数据库映射并识别数据中的模式。
第十二章:数据库结构与机器学习
在本章的最后,我们将专注于机器学习的概念和类型。
根据本书的总体主题,我们将首先解释统计机器学习及相关概念,然后将继续分析统计机器学习与具有数据或数据库开发背景的读者可能相关的基本概念之间的一些相似之处。
本章分为以下几个部分:
-
数据结构就是数据模型吗?
-
机器学习概念概述
-
机器学习的类型
-
数据开发人员与机器学习
-
使用 R 将机器学习技术应用于数据库
数据结构与数据模型
当你拥有大量数据,却不知道该如何处理时,结构化数据、分析数据并将其有效利用是非常重要的(无论在何处需要)。在这一部分,我们将重点讲解数据结构和数据模型,并理解它们之间的差异。
数据结构
数据开发人员会同意,每当处理大量数据时,数据的组织结构至关重要。如果数据没有有效地组织,将很难对其进行任何操作,或者至少无法高效地完成任务。如果数据得到有效组织,那么几乎任何操作都可以轻松地在数据上执行。
数据或数据库开发人员会将数据组织成所谓的数据结构。下面的图像展示了一个简单的二叉树,在这种结构中数据得到了高效的组织:
数据结构可以定义为一种更高效地组织大量数据的方法,以便对数据执行的任何操作变得容易。
数据结构的创建方式是为了实现一个或多个特定的抽象数据类型(ADT),而这些抽象数据类型将规定可以对数据结构执行哪些操作,以及这些操作的计算复杂度。
在统计学领域,ADT 是数据类型的模型,其中数据类型是通过用户视角(POV)定义的,明确显示该数据类型的可能值、对这种类型数据可以进行的操作以及所有操作的行为。
数据库设计是使用已定义的数据结构来生成详细数据模型的过程,最终形成数据库。这个数据模型必须包含所有所需的逻辑和物理设计选择,以及生成数据定义语言(DDL)设计所需的物理存储参数,从而可以用来创建实际的数据库。
数据模型有不同的层次,例如,一个完全属性化的数据模型还会包含模型中每个实体的详细属性。
那么,数据结构就是数据模型吗?
不,数据结构是用来创建数据模型的。那么,这个数据模型是否与统计学中使用的数据模型相同呢?让我们在接下来的部分看看。
数据模型
你会发现统计数据模型是统计分析的核心。
简单来说,统计数据模型定义如下:
我们希望理解并推理的状态、过程或系统的表示
在前述定义的范围内,数据或数据库开发人员可能会同意,在理论上或概念上,可以使用相同的术语来定义财务报表数据库,因为它被设计用来包含商业交易,并且以数据结构的形式组织,使得商业分析师能够高效地审查数据,从而理解或推理他们可能对商业有特定兴趣的方面。
数据科学家开发统计数据模型,以便从中得出推论,更重要的是,做出关于关注话题的预测。数据开发人员开发数据库,以便同样从中得出推论,更重要的是,做出关于关注话题的预测(尽管在某些组织中,数据库可能更关注过去和当前的事件(交易),而非前瞻性的预测)。
统计数据模型有多种不同的格式和类型(数据库也是如此)。这些模型可以是将我们可以观察或测量的数量联系起来的方程式;它们也可以是简单的规则集合。
数据库可以设计或格式化,以简化在线交易的输入——例如,在订单输入系统中,或用于财务报表,当会计部门必须为股东生成资产负债表、利润表或损益表时。
我找到了一个简单的统计数据模型的例子:牛顿第二定律,它指出,作用在物体上的合力会使物体朝着力的方向加速,且加速的速率与合力的大小成正比,与物体的质量成反比。
有什么区别?
读者在哪里或如何能找到数据结构或数据库与统计模型之间的区别呢?从高层次来看,正如我们在前述部分推测的那样,可以得出结论:数据结构/数据库实际上与统计数据模型是相同的,如下图所示:
从高层次来看,正如我们在前述部分推测的那样,可以得出结论:数据结构/数据库实际上与统计数据模型是相同的。
当我们深入探讨这个话题时,应该考虑以下关键点:
-
尽管数据结构/数据库和统计模型都可以被认为代表一组假设,但统计模型通常会更加聚焦于一组关于生成某些样本数据的假设,及类似数据从更大群体中产生的假设,而数据结构/数据库通常会更加广泛。
-
统计模型通常处于一种理想化的形式,而数据结构/数据库则可能在追求特定假设的过程中显得不那么完美
-
数据结构/数据库和统计模型都是围绕变量之间的关系构建的
-
数据结构/数据库的关系可能专注于回答某些问题,例如:
-
特定客户的总订单量是多少?
-
某个客户从某个销售员那里购买的总订单量是多少?
-
哪个客户下单最多?
-
-
统计模型的关系通常非常简单,且专注于证明特定问题:
-
女性比男性矮一个固定的高度
-
体重与身高成正比
-
-
任何给定的人参与某项运动的概率是年龄、性别和社会经济地位的函数
-
数据结构/数据库完全是基于变量之间关系对数据进行总结的过程
关系
统计模型中变量之间的关系可能比简单的直观认识和理解要复杂得多。一个例子是效应统计的概念。效应统计是显示或展示某个值的差异,而这个差异与一个或多个其他变量的差异相关联。
你能想象出你会使用什么 SQL 查询语句来基于一个或多个效应统计量建立两个数据库变量之间的关系吗?
在这一点上,你可能会发现,数据结构/数据库通常旨在表征变量之间的关系,而在统计模型中,数据科学家则试图通过拟合模型来证明某个观点或对模型中的群体做出陈述。也就是说,数据科学家努力对描述模型的效应统计量的估计准确性做出声明!
另一个值得注意的点是,数据结构/数据库和统计模型都可以看作是旨在对一个群体进行概括的工具或载体;数据库使用 SQL 来聚合或总结数据,而统计模型则使用效应统计来总结其数据。
好的,希望我们已经成功地表达了这样一个观点:数据结构/数据库和统计数据模型在许多方面是非常相似的。
现在,让我们继续讨论机器学习。
机器学习
统计机器学习有很多深奥的定义,但让我们从最简单或最基本的版本开始:
机器学习是旨在教计算机根据某些数据流或数据源做出现实预测(或改进预测)的过程。
读者应该注意到,数据源明确依赖于数据科学家正在解决(或尝试解决)的具体问题。例如,Netflix 这一订阅娱乐服务不会使用患者的牙科记录数据作为输入来预测订阅者的观看行为!
可以提供一个稍微深入的解释:
机器学习是计算机科学的一个子领域,起源于人工智能中的模式识别和计算学习理论的研究。1959 年,Arthur Samuel 将机器学习定义为“让计算机在没有明确编程的情况下学习的研究领域。”
; -scratch.mit.edu/studios/3475398/activity
在机器学习中,数据科学家将花费时间探索、研究并构建他们可以从中学习并对数据源做出预测的过程。
这些机器学习过程或算法实际工作的方式是通过使用示例数据源输入构建统计模型。这不同于典型的计算机算法(即传统的计算机编程),后者通过遵循一组由开发团队编写的静态程序指令来工作。
你会发现在设计和编程明确程序指令不可行的地方,机器学习被广泛应用,例如图像识别和计算机视觉等应用。
在本章的后续部分,我们将花些时间列举更多今天机器学习应用的例子。
机器学习概念概述
在本章的前一部分,我们提到了传统编程的概念。使用传统编程时,数据和程序在计算机上运行以产生所需的输出。而在机器学习中,数据和输出在计算机上运行以创建一个程序。然后,这个程序可以在传统编程中使用。
一个稍为流行的、可能有趣的类比来描述机器学习是农业。
在这里,人们可能会把机器学习算法看作是种子,数据源看作是肥料,数据科学家则是农民,他们种植和滋养这些种子,最终收获成果!
机器学习的关键元素
当前数据科学家使用了大量的机器学习算法。实际上,一些研究表明,可能有成千上万种。此外,每年都有数百种新的算法被提出用于实践。
根据大众观点,今天所有的机器学习算法都由三个组成部分构成。它们如下:
-
表征
-
评估
-
优化
表示
这就是信息的表示方式。示例包括决策树、规则集合、实例、图形模型、神经网络、支持向量机、模型集成等。
评估
这就是候选程序(假设)将如何评估。示例包括准确率、预测和召回率、平方误差、似然性、后验概率、成本、边际、熵、Kullback-Leibler(KL 散度)等。
优化
这就是候选程序生成的方式,也叫做搜索过程,例如组合优化、凸优化和约束优化。
机器学习的类型
今天,机器学习有四种类型或类别。
这些类型如下:
-
监督学习
-
无监督学习
-
半监督学习
-
强化学习
理解每种学习类型非常重要。
监督学习
这种类型的学习也被称为归纳学习。此时,训练数据将包括期望的输出;算法从标记或分类的训练数据中推断。训练数据是一组训练示例。
无监督学习
与监督学习不同,在这里,训练数据不包括期望的输出。这是机器学习任务的一个范畴,即从未标记或未分类的数据中推断出一个描述隐藏结构的函数。由于提供给学习者的示例是未标记的,因此没有错误或奖励信号来评估潜在的解决方案。
半监督学习
在这种机器学习类型中,训练数据包含一些期望的输出样本。半监督学习实际上被认为是一种监督式机器学习,它利用未标记或未分类的数据进行训练,通常是少量标记数据与大量未标记数据结合。
强化学习
来自一系列动作的奖励,人工智能(AI)类型喜欢这种方式,因为它是最雄心勃勃的学习类型。强化学习(RL)是一种机器学习,允许机器和软件代理在特定环境中自动确定理想的行为,以最大化其性能。
最受欢迎的
监督学习是最成熟的,因为它存在的时间最长。它是研究最多的,也是大多数机器学习算法所使用的学习类型。
有监督的学习比没有监督的学习要容易得多。
在我们继续进行一个机器学习示例之前,先来回顾一下几个机器学习应用。
机器学习的应用
如果你还不清楚机器学习这一主题为何如此重要,或许回顾一下真实世界中的机器学习使用案例会有所帮助。
在本节中,我们将占用您一些时间列举一些真实世界的机器学习应用。
当前机器学习的示例应用程序包括以下内容(实际上几乎每天都在使用):
搜索 | 你可能每天在多个设备上使用此功能。机器学习结果被用于开发网页搜索排名页面。排名页面是个人最可能感兴趣并点击的内容列表。 |
---|---|
数字识别 | 给定手写在信封上的邮政编码,识别每个手写字符对应的数字。该问题的模型将允许计算机程序读取和理解手写的邮政编码,并按地理区域对信封进行排序。 |
生物学 | 基于过去的实验,理性设计计算机上的药物。 |
银行与金融 | 用于确定向谁发送哪些信用卡优惠。评估信用优惠的风险。如何决定将钱投资于哪里。 |
电子商务 | 预测客户流失、欺诈检测和机器人检测。 |
理解语音 | 给定用户的发声,识别用户所做的具体请求。这个问题的模型将允许程序理解并尝试满足该请求。iPhone 配有 Siri,具备此功能。 |
人脸识别 | 给定一个包含数百张数字照片的数字相册,识别其中包含某个特定人物的照片。该决策过程的模型允许程序按人物组织照片。一些相机和软件,如 iPhoto,具备此功能。 |
太空探索 | 太空探测器和射电天文学。 |
形状识别 | 给定用户在触摸屏上绘制形状,以及已知形状的数据库,确定用户试图绘制的形状。该决策模型将允许程序显示用户绘制的形状的柏拉图版本,从而制作清晰的图表。 |
机器人技术 | 如何处理新环境中的不确定性;自动驾驶汽车。 |
信息提取 | 能够在互联网上的数据库上提问。 |
社交网络 | 关于关系和偏好的数据。机器学习从数据中提取价值。 |
产品推荐 | 给定客户的购买历史和大量产品库存,识别客户可能感兴趣并可能购买的产品。该决策过程的模型将允许程序向客户推荐产品并激励购买。Amazon 具备此功能。还可以考虑 Facebook 和 GooglePlus,它们在用户注册后推荐与其连接的用户。 |
调试 | 用于计算机科学问题,例如调试。劳动密集型过程。可以提示错误可能的位置。 |
机器学习的实际应用
如果我们继续比较数据/数据库开发与机器学习,专注于一个典型项目,我们将看到相似之处。
在这一点上,Jason Brownlee 提供的一个相当不错的示例很好地说明了这一点。在 Jason 的文章中,他提醒我们,机器学习项目不仅仅是运行算法:
机器学习算法只是数据分析师或数据科学家在实践中使用机器学习的一小部分。
你可以在线查阅 Jason 的文章,网址是 machinelearningmastery.com/basic-concepts-in-machine-learning
。
实际上,Jason 指出,典型的涉及机器学习的统计项目中遵循的各个阶段很可能是迭代的,并且大致如下所示:
理解
项目的初始阶段将涉及建立对所需领域知识和项目目标的良好理解。数据科学家将与领域专家(或主题专家)交流,以明确项目目标。在项目开始时,目标模糊或不清晰是很常见的。你往往有更多的事情要测试,但无法全部实现。
项目的这一阶段与数据/数据库开发项目的第一阶段直接相关,因为数据开发人员总是需要从领域专家那里收集信息,以便在设计数据结构或数据库模型之前,详细了解项目目标。
准备
在此阶段,进行数据集成、选择、清洗和预处理。这通常是最耗时的部分,但也许是最重要的步骤,因为高质量的数据至关重要。数据量越大,数据就越脏。
再次强调,这一阶段与数据库开发项目非常相似。系统集成、查询与选择、清洗和其他数据预处理步骤(以便能够在新的数据库模型中使用)是预期的内容。这通常涉及到数据聚合、建立主外键关系、清洗等操作。
学习
这一阶段是最有趣的部分,机器学习算法被应用到数据中。
项目的这一阶段与数据库开发项目中的数据建模或数据模型设计阶段最为相关。请记住,在机器学习统计项目中,学习更多偏向机器方向,而在数据库开发项目中,建模则更多偏向人类方向。
解释
在此阶段,数据科学家和统计团队会回顾并解释之前阶段的结果。有时候,模型的工作原理并不重要,只要它能够提供好的结果。在某些项目中,要求结果易于理解。专家们会对结果提出挑战。
这一阶段与数据库开发项目的验收测试阶段相似,在数据库构建完成后,领域专家将审查和测试模型,并解释结果,以确定数据库是否提供了符合项目要求的可接受结果。
部署
在最后阶段,前几个阶段的结果(发现的知识)将被整合并部署。
在实验室中成功的机器学习项目,往往并未完全投入实践。通常情况下,项目会进入“另一个阶段”,通常会使用更多或更新的数据。
在这个阶段,我们看到数据库正式上线,或者被部署到生产环境中,由数据拥有者使用。
迭代
最后,Jason 还指出:
这不是一次性的过程,而是一个循环。数据科学家可能需要重复执行这个循环(可能重新执行第 1 至第 5 阶段),直到得到一个可以实际应用的结果。此外,数据可能会发生变化,需要进行新的循环,等等。
这可能是数据库开发项目与机器学习统计项目的区别所在。虽然数据库项目可能会经历多个迭代阶段(例如为了应对在验收测试中发现的某些问题),但大多数数据库项目通常会以一个实际被数据拥有者使用的数据库作为结束。
使用 R 将机器学习技术应用于数据库
从本书的始至终,我们几乎都使用了 R 编程语言,因为它被大多数数据科学家使用,而且对于刚刚接触统计学的人来说,非常易于理解。在本章中,我们将再次使用 R,这次是为了探讨机器学习技术如何应用于数据或数据库开发者。
我们将使用数据科学家 Will Stanton 提供的一篇文章作为起点。在他的文章中,他展示了如何使用 caret
包在 R 中创建一个简单的分类模型的巧妙示例。
R caret
包是 Will 在他的示例中使用的,非常易于使用,包含包装函数,允许你使用相同的函数进行训练和预测,适用于数十种不同的算法。除此之外,它还包括用于评估从模型中获得的预测效果的复杂内建方法。
在这个示例中(尽管有点令人不适),任务是建立一个统计模型,能够分析在泰坦尼克号上乘坐的个体的特征,然后预测他们生还的可能性。
理解数据
提供的数据包含关于谁幸存和谁遇难的信息:
这些数据以可下载的文本 CSV 文件形式提供,其中包含每个人的几个有用变量:
-
Pclass: 乘客等级(头等舱、二等舱或三等舱)
-
性别
-
年龄
-
SibSp: 登船的兄弟姐妹/配偶的数量
-
Parch: 登船的父母/子女的数量
-
票价: 乘客支付的金额
-
登船地点: 他们登船的地点(C = 瑟堡;Q = 皇后镇;S = 南安普敦)
所需的逐步 R 代码,用于安装和加载 R 包,以及加载前述数据集,可以在线找到,链接为will-stanton.com/machine-learning-with-r-an-irresponsibly-fast-tutorial
。
给出的示例在概述所需的创建简单分类模型的每个步骤时做得非常出色,旨在说明一种机器学习的形式。
所使用的方法与我们在本章的机器学习实战部分之前提到的内容一致。
第一步是理解问题或挑战,并做好准备,以便能够进行实际的机器学习。
准备工作
在 R 示例中,我们了解到挑战是预测乘客幸存的可能性;然后我们进行准备,加载数据以便进行审查,识别出合适或最佳的变量(以供学习算法使用):
这篇文章提供了读取train.csv
文件的 R 命令,使用,
分隔符,包括将标题行作为列名,并将其分配给 R 对象。它还读取了testSet.csv
文件,最后使用 R 的Head
函数显示数据集的前几行,读者可以看到每行都有一个Survived
列,该列值为 1 表示该人幸存,为 0 表示未幸存(你可以在本节之前提供的数据文件图片中看到这部分信息)。
接下来,示例解释了比较训练集和测试集,展示了训练集和测试集之间的显著差异;训练集是带标签的,而测试集是无标签的。当前的任务是对无标签的测试集进行预测,并根据正确标记的乘客百分比进行评分。
文章还告知读者,大部分机器学习实际上是关于选择模型中最合适的特征。在机器学习中,特征实际上就是一个变量或某些变量的组合(例如两个变量的和或积)。
在统计分类模型示例中,泰坦尼克号挑战,通过使用交叉表和条件箱型图,选择最有用的变量来进行建模。
交叉表以一种非常易于理解的方式展示了两个变量之间的相互作用。在此示例中,为了确定哪些变量是生存的最佳预测因子,使用了 R 的 table 函数来查看生存与其他每个变量之间的交叉表。
箱形图对于识别有用的连续变量非常有用。给出的 R 示例使用条件箱形图比较数据中每个连续变量的分布,条件是乘客是否幸存。
在进行的分析中,可以看到 Pclass 对于根据指示的生存率预测某人是否生存具有强大的预测价值:
乘客等级 | 结果 | 生存率 |
---|---|---|
1 班 | 136 幸存,80 死亡 | 63% |
2 班 | 87 幸存,97 死亡 | 47% |
3 班 | 119 幸存,372 死亡 | 24% |
数据开发者
前述示例与数据或数据库开发者有何异同?可能有何相关示例?
从顶部开始,假设您负责一家游戏公司拥有的数据库。该公司购买并在其赌场和俱乐部的地板上放置各种类型的老丨虎丨机。
老丨虎丨机是一种赌场博彩机,具有三个或更多个卷轴,在按下按钮时旋转。机器由插入硬币操作。
数据库包含每种类型的游戏机的许多有用变量:
-
主题:传统的老丨虎丨机以水果和条形符号为特色,但主题正在成为老丨虎丨机游戏的主要特征
-
面额:五分、十分、二十五分、五十分等等
-
支付频率:松散、中等或紧密
-
玩家位置:低级或直立
-
卷轴类型:机械或虚拟
-
玩家数量:独立或社区
在这里,我们的挑战是根据机器的特征或已知变量来预测特定机器是否会成为游戏公司的热门机器。
在 R 示例中,数据科学家很幸运有提供的数据文件。但是,作为数据或数据库开发者,我们通常不会那么幸运,尽管这并不是什么大问题。
熟悉数据结构/数据库模型(正如我们在本章开始时讨论的),数据开发者可以构建适当的 SQL 查询来定位我们项目中感兴趣的数据(有些人称这一过程为挖掘数据)。
数据挖掘是发现数据模式的过程,涉及人工智能、机器学习、统计学和数据库系统的交集方法。
此外,一旦数据已经在数据库中定位,将信息写入 CSV 文本文件以供我们的统计项目消耗是常规工作:
select * into outfile 'd:/report.csv' fields terminated by ',' from tableName;
但事实上,数据开发者可能会进行数据分析、变量审查和特征选择,而数据仍在数据库中;这样一旦确定了最强大的预测因子,其他(在我们的挑战环境中可能被视为噪声的因素)就不必提取到我们的文件中。这样可以节省时间,使数据可能更易管理。
噪声 在第十章中进行了讨论,提升和你的数据库。
理解挑战
在完全理解当前的挑战后,也许我们已经得知,如果一台游戏机的平均硬币投入(即老丨虎丨机上投币的总美元金额)每天超过一万美元,它就会被组织认为是受欢迎的游戏机。
有了这些信息,我们可以构建一个查询(或很可能是几个查询),用来计算并提取每个机器观察值的该变量数值。
到那时,我们将拥有每台公司运营的机器的观察数据(记录),以及每台机器的特征列表(我们想要检查的变量),以及已确定的结果(是否受欢迎)。
听起来熟悉吗?应该是的!
假设在我们的数据库示例中,我们发现面额是判断一台游戏机是否受欢迎的最强预测因子:
面额 | 结果/平均硬币投入值 | 流行度 |
---|---|---|
10 美分 | $7,500 | 否 |
25 美分 | $18,000 | 是 |
50 美分 | $9,000 | 否 |
从这些例子的比较中,我们可以看到数据开发人员有很多机会定位并利用存储在数据库中的信息,作为统计模型的输入。
交叉表和图表绘制
我们之前提到过,交叉表用于以非常易读的格式展示两个变量之间的交互关系。为了查看Survived
与其他每个变量之间的交叉表,使用了 R 函数 table。
数据开发人员有类似的工具,PIVOT。PIVOT 是 SQL Server 2005 中引入的一种新的关系操作符。它为 SQL Server 提供了一个简单的机制,可以将行转换为列。
我们这里关注的 R 示例也使用了箱线图可视化来识别数据中的连续变量。虽然原生 SQL 并没有直接提供绘图功能,但数据开发人员可以考虑利用像SQL Server 报告服务(SSRS)之类的工具来绘制从数据库中提取的数据;不过,由于下一阶段将需要我们创建一个分类模型,我建议利用 R 的可视化功能来创建我们的图表和图形。
网上有一个非常好的资源,值得读者花时间阅读,内容涉及主题使用 SQL 和 R 创建图表和绘图(操作指南):
此时,你可以继续进行之前讨论过的学习、评估和部署阶段。
总结
在本章中,我们首先回顾了数据结构、数据模型和数据库的概念,并找到了它们之间的相似性和差异。
接下来,我们概述了机器学习及相关概念,并将机器学习统计项目的实践与数据库开发项目进行了比较。
最后,我们介绍了 R 语言的概念性应用,并将机器学习技术应用于来自数据库的数据。
本书旨在帮助典型的数据或数据库开发人员过渡到统计学领域,因此我们希望读者已经对统计学和数据科学中的相关主题有了扎实的理解。
祝你好运!