Java 机器学习(一)

零、前言

Java 中的机器学习,第二版,将为您提供从复杂数据中快速获得洞察力所需的技术和工具。您将从学习如何将机器学习方法应用于各种常见任务开始,包括分类、预测、预报、购物篮分析和聚类。

这是一个实用的教程,使用实际操作的例子来逐步完成机器学习的一些现实应用。在不回避技术细节的情况下,您将使用清晰实用的例子来探索 Java 库的机器学习。您将探索如何为分析准备数据,选择机器学习方法,并衡量该过程的成功。

这本书是给谁的

如果你想学习如何使用 Java 的机器学习库从你的数据中获得洞察力,这本书是给你的。它将帮助您快速启动和运行,并为您提供轻松成功地创建、定制和部署机器学习应用程序所需的技能。为了充分利用这本书,你应该熟悉 Java 编程和一些基本的数据挖掘概念,但是不需要有机器学习的经验。

从这本书中获得最大收益

本书假设用户具备 Java 语言的工作知识和机器学习的基本概念。这本书大量使用了 JAR 格式的外部库。假设用户知道在终端或命令提示符下使用 JAR 文件,尽管这本书也解释了如何做。用户可以很容易地在任何通用的 Windows 或 Linux 系统上使用本书。

下载示例代码文件

你可以从你在www.packt.com的账户下载本书的示例代码文件。如果你在其他地方购买了这本书,你可以访问 www.packt.com/support 的并注册,让文件直接通过电子邮件发送给你。

您可以按照以下步骤下载代码文件:

  1. www.packt.com登录或注册。
  2. 选择支持选项卡。
  3. 点击代码下载和勘误表。
  4. 在搜索框中输入图书名称,然后按照屏幕指示进行操作。

下载文件后,请确保使用最新版本的解压缩或解压文件夹:

  • WinRAR/7-Zip for Windows
  • 适用于 Mac 的 Zipeg/iZip/UnRarX
  • 用于 Linux 的 7-Zip/PeaZip

该书的代码包也托管在 GitHub 的 https://GitHub . com/packt publishing/Machine-Learning-in-Java-Second-Edition 上。如果代码有更新,它将在现有的 GitHub 库中更新。

我们在也有丰富的书籍和视频目录中的其他代码包。看看他们!

下载彩色图像

我们还提供了一个 PDF 文件,其中有本书中使用的截图/图表的彩色图像。可以在这里下载:www . packtpub . com/sites/default/files/downloads/9781788474399 _ color images . pdf

使用的惯例

本书通篇使用了许多文本约定。

CodeInText:表示文本中的码字、数据库表名、文件夹名、文件名、文件扩展名、路径名、伪 URL、用户输入和 Twitter 句柄。下面是一个例子:“解压存档文件并在解压的存档文件中找到weka.jar

代码块设置如下:

data.defineSingleOutputOthersInput(outputColumn); 

EncogModel model = new EncogModel(data); 
model.selectMethod(data, MLMethodFactory.TYPE_FEEDFORWARD);
model.setReport(new ConsoleStatusReportable()); 
data.normalize(); 

任何命令行输入或输出都按如下方式编写:

$ java -cp moa.jar -javaagent:sizeofag.jar moa.gui.GUI

粗体:表示一个新术语、一个重要单词或您在屏幕上看到的单词。例如,菜单或对话框中的单词在文本中以粗体显示。下面是一个例子:“我们可以通过点击文件|另存为,并在保存对话框中选择 CSV,将其转换为逗号分隔值 ( CSV )格式。”

警告或重要提示如下所示。

提示和技巧是这样出现的。

取得联系

我们随时欢迎读者的反馈。

总体反馈:如果您对这本书的任何方面有疑问,请在邮件主题中提及书名,并在customercare@packtpub.com发送电子邮件给我们。

勘误表:虽然我们已经尽力确保内容的准确性,但错误还是会发生。如果你在这本书里发现了一个错误,请告诉我们,我们将不胜感激。请访问 www.packt.com/submit-errata,选择您的图书,点击勘误表提交表格链接,并输入详细信息。

盗版:如果您在互联网上遇到我们作品的任何形式的非法拷贝,如果您能提供我们的地址或网站名称,我们将不胜感激。请通过copyright@packt.com联系我们,并提供材料链接。

如果你有兴趣成为一名作者:如果有一个你擅长的主题,并且你有兴趣写作或投稿,请访问 authors.packtpub.com。

复习

请留下评论。一旦你阅读并使用了这本书,为什么不在你购买它的网站上留下评论呢?潜在的读者可以看到并使用您不带偏见的意见来做出购买决定,我们 Packt 可以了解您对我们产品的看法,我们的作者可以看到您对他们的书的反馈。谢谢大家!

更多关于 Packt 的信息,请访问packt.com

一、应用机器学习快速入门

本章介绍了机器学习的基础知识,列出了常见的主题和概念,并使其易于遵循逻辑和熟悉主题。目标是快速学习应用机器学习的分步过程,掌握主要的机器学习原理。在本章中,我们将讨论以下主题:

  • 机器学习和数据科学
  • 数据和问题定义
  • 数据收集
  • 数据预处理
  • 无监督学习
  • 监督学习
  • 概括和评价

如果你已经熟悉机器学习,并渴望开始编码,那么请快速跳转到这一章之后的章节。但是,如果您需要刷新您的记忆或澄清一些概念,那么强烈建议您重温本章中介绍的主题。

机器学习和数据科学

现在大家都在说机器学习和数据科学。那么,到底什么是机器学习呢?它与数据科学有什么关系?这两个术语经常被混淆,因为它们经常使用相同的方法并且有很大的重叠。所以,我们先明确一下它们是什么。乔希·威尔斯在推特上写道:

“数据科学家是比任何软件工程师都更擅长统计,比任何统计学家都更擅长软件工程的人。”

-乔希·威尔斯

更具体地说,数据科学包括通过整合统计学、计算机科学和其他领域的方法从数据中获得洞察力来获取知识的整个过程。在实践中,数据科学包含数据采集、清理、分析、可视化和部署的迭代过程。

另一方面,机器学习主要关注在数据科学过程的分析和建模阶段使用的通用算法和技术。

用机器学习解决问题

在不同的机器学习方法中,有三种主要的学习方法,如下表所示:

  • 监督学习
  • 无监督学习
  • 强化学习

给定一组示例输入 X 及其输出 Y,监督学习旨在学习通用映射函数 f,该函数将输入转换为输出,如 f: (X,Y)。

监督学习的一个例子是信用卡欺诈检测,其中学习算法用标记为正常或可疑(向量 Y)的信用卡交易(矩阵 X)来表示。学习算法产生一个决策模型,将看不见的交易标记为正常或可疑(这是 f 函数)。

相比之下,无监督学习算法不假设给定的结果标签,因为它们专注于学习数据的结构,例如将相似的输入分组到聚类中。因此,无监督学习可以发现数据中隐藏的模式。无监督学习的一个例子是基于物品的推荐系统,其中学习算法发现一起购买的相似物品;比如买了书 A 的人也买了书 b。

强化学习从一个完全不同的角度处理学习过程。它假设一个智能体,可以是机器人、机器人或计算机程序,与动态环境交互以实现特定目标。环境用一组状态来描述,代理可以采取不同的动作从一个状态移动到另一个状态。一些状态被标记为目标状态,如果代理实现了这个状态,它将获得一大笔奖励。在其他州,奖励更少,不存在,甚至是负的。强化学习的目标是找到一个最佳策略或映射函数,指定在每个状态下采取的行动,而无需教师明确告知这是否会导致目标状态。强化学习的一个例子是用于驾驶车辆的程序,其中状态对应于驾驶条件,例如当前速度、路段信息、周围交通、速度限制和道路上的障碍物;这些动作可以是驾驶操作,例如左转或右转、停止、加速和继续。该学习算法产生一个策略,该策略规定了在特定的驾驶条件配置中要采取的行动。

在本书中,我们将只关注监督学习和非监督学习,因为它们有许多相同的概念。如果强化学习激发了你的兴趣,那么一本好书是《强化学习:导论》,作者理查德·萨顿和安德鲁·巴尔托,麻省理工出版社(2018)。

应用机器学习工作流

这本书的重点是应用机器学习。我们希望为您提供让学习算法在不同环境中工作所需的实用技能。代替机器学习中的数学和理论,我们将花更多的时间在实践、动手技能(和肮脏的把戏)上,以使这些东西在应用程序中很好地工作。我们将关注监督和非监督机器学习,并学习数据科学中的基本步骤,以建立应用机器学习工作流程。

应用机器学习应用中的典型工作流由回答一系列问题组成,这些问题可以概括为以下步骤:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 数据和问题定义:第一步,提出有趣的问题,比如:你正在尝试解决的问题是什么为什么重要哪种格式的结果回答了你的问题这是一个简单的是/否答案是否需要从可用问题中选择一个
  2. 数据收集:一旦你有问题要解决,你将需要数据。问问你自己什么样的数据会帮助你回答这个问题。你能从现有的来源得到数据吗你必须结合多种来源吗一定要生成数据吗?有没有抽样偏倚需要多少数据
  3. 数据预处理:第一个数据预处理任务是数据清理。一些示例包括填充缺失值、平滑噪声数据、移除异常值和解决一致性问题。随后通常会集成多个数据源,并将数据转换到特定范围(标准化)、值箱(离散化区间),并减少维数。
  4. 数据分析和建模:数据分析和建模包括无监督和有监督的机器学习、统计推断和预测。有各种各样的机器学习算法可用,包括 k-最近邻、朴素贝叶斯分类器、决策树、支持向量机 ( 支持向量机)、逻辑回归、k-means 等等。要部署的方法取决于第一步中讨论的问题定义和收集的数据类型。这一步的最终产品是从数据中推断出的模型。
  5. 评估:最后一步是模型评估。用机器学习建立的模型面临的主要问题是它们对底层数据的建模有多好;例如,如果一个模型过于具体或者过于适合用于训练的数据,那么它很可能在新数据上表现不佳。该模型可能过于一般化,这意味着它对训练数据的拟合不足。比如,当被问及加州的天气如何时,它总是回答晴朗,这在大多数时候确实是正确的。然而,这样的模型对于做出有效的预测并不真正有用。这一步的目标是正确评估模型,并确保它也适用于新数据。评估方法包括单独的测试和训练集、交叉验证和留一交叉验证。

我们将在接下来的几节中仔细研究每个步骤。我们将尝试理解在应用机器学习工作流程中我们必须回答的问题类型,并查看数据分析和评估的相关概念。

数据和问题定义

当提出问题定义时,我们需要问一些问题,这些问题将有助于从数据中理解目标和目标信息。我们可以问一些非常常见的问题,例如:一旦研究了数据,预期的发现是什么? *数据探索后能提取出什么样的信息?*或者,*需要什么样的格式才能回答问题?*提出正确的问题会让你更清楚地了解下一步该怎么做。数据只是数字、文字、观察、事物描述、图像等形式的测量值的集合。

测量标度

表示数据最常见的方式是使用一组属性-值对。考虑下面的例子:

Bob = { 
height: 185cm, 
eye color: blue, 
hobbies: climbing, sky diving 
} 

例如,Bob具有名为heighteye colorhobbies的属性,其值分别为185cmblueclimbingsky diving

一组数据可以简单地表示为表格,其中列对应于属性或特征,行对应于特定的数据示例或实例。在监督机器学习中,我们希望根据其他属性 X 的值来预测结果 Y 的值的属性被表示为类或目标变量,如下表所示:

| 名称 | 身高【厘米】 | 眼睛颜色 | 兴趣爱好 |
| 上下移动 | One hundred and eighty-five | 蓝色 | 爬山,跳伞 |
| 安娜;安那(anna 旧时印度货币名) | One hundred and sixty-three | 褐色的 | 阅读 |
| … | … | … | … |

我们注意到的第一件事是属性值变化有多大。例如,身高是一个数字,眼睛的颜色是文本,爱好是一个列表。为了更好地理解值类型,让我们仔细看看不同类型的数据或度量尺度。斯坦利·史密斯·史蒂文斯(1946 年)定义了以下四种具有越来越多表达性质的衡量尺度:

  • 名义数据由互斥但不有序的数据组成。例子包括眼睛的颜色、婚姻状况、拥有的汽车类型等等。
  • 顺序数据对应于顺序重要的类别,而不是值之间的差异,例如疼痛程度、学生信等级、服务质量评级、IMDb 电影评级等等。
  • 区间数据由两个值之间的差异有意义的数据组成,但没有零的概念,例如标准化考试分数、华氏温度等。
  • 比率数据具有区间变量的所有性质,也有零的明确定义;当变量等于零时,这个变量将会丢失。身高、年龄、股票价格和每周食物支出等变量是比率变量。

我们为什么要关心测量尺度?嗯,机器学习很大程度上依赖于数据的统计属性;因此,我们应该意识到每种数据类型的局限性。一些机器学习算法只能应用于测量尺度的子集。

下表总结了每种测量类型的主要操作和统计属性:

| 属性 | 标称值 | 序数 | 间隔 | 比率 |
| one | 分布频率 | 真实的 | 真实的 | 真实的 | 真实的 |
| Two | 众数和中位数 | | 真实的 | 真实的 | 真实的 |
| three | 值的顺序是已知的 | | 真实的 | 真实的 | 真实的 |
| four | 可以量化每个值之间的差异 | | | 真实的 | 真实的 |
| five | 可以增加或减少数值 | | | 真实的 | 真实的 |
| six | 可以乘除数值 | | | | 真实的 |
| seven | 具有真零点 | | | | 真实的 |

此外,标称和序数数据对应于离散值,而间隔和比率数据也可以对应于连续值。在监督学习中,我们想要预测的属性值的度量尺度决定了可以使用的机器算法的种类。例如,从有限的列表中预测离散值称为分类,可以使用决策树来实现,而预测连续值称为回归,可以使用模型树来实现。

数据收集

一旦问题问对了方向,数据探索的目标就很明确了。所以,下一步就是看数据从哪里来。收集的数据可能非常杂乱,格式也非常多样,这可能涉及到从数据库、互联网、文件系统或其他文档中读取数据。大多数机器学习工具要求数据以特定的格式呈现,以便生成正确的结果。我们有两种选择:观察现有来源的数据,或者通过调查、模拟和实验生成数据。让我们仔细看看这两种方法。

查找或观察数据

数据可以在很多地方找到或观察到。一个明显的数据来源是互联网。随着社交媒体使用的增加,以及随着移动数据计划变得更便宜甚至提供无限数据,移动电话渗透得更深,用户消费的数据呈指数级增长。

现在,在线流媒体平台已经出现——下图显示,花费在视频数据上的时间也在快速增长:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

要从 internet 获取数据,有多个选项,如下表所示:

  • 从维基百科、https://labrosa.ee.columbia.edu/millionsong/、百万歌曲数据集(可以在这里找到:)等网站批量下载。
  • 通过 API(如谷歌、推特、脸书和 YouTube)访问数据。
  • 搜集公开的、非敏感的、匿名的数据是可以的。请务必检查条款和条件,并充分参考信息。

收集数据的主要缺点是,积累数据需要时间和空间,而且它只涵盖发生的事情;例如,没有收集意图以及内部和外部动机。最后,这样的数据可能是嘈杂的、不完整的、不一致的,甚至可能随时间而改变。

另一种选择是从传感器收集测量值,例如移动设备中的惯性和位置传感器、环境传感器以及监控关键性能指标的软件代理。

生成数据

另一种方法是由您生成数据,例如,通过调查。在调查设计中,我们必须注意数据抽样;也就是回答调查的回答者是谁。我们只从容易接近并愿意回答的受访者那里获得数据。此外,受访者可以提供符合其自我形象和研究者预期的答案。

或者,可以通过模拟来收集数据,其中领域专家在微观层面上指定用户的行为模型。例如,人群模拟需要指定不同类型的用户在人群中的行为方式。一些例子可以是跟随人群,寻找一个逃避的方法,等等。然后可以在不同的条件下运行模拟,看看会发生什么(Tsai 等人,2011)。模拟适用于研究宏观现象和突发行为;然而,它们通常很难用经验来验证。

此外,您可以设计实验来彻底涵盖所有可能的结果,其中您保持所有变量不变,并且一次只操纵一个变量。这是最昂贵的方法,但通常提供最好的质量。

取样陷阱

数据收集可能涉及许多陷阱。为了演示一个,我来分享一个故事。学生之间免费发送普通邮件应该有一个全球性的不成文的规则。如果你在应该贴邮票的地方写上"学生对学生",邮件就会免费送到收件人手中。现在,假设 Jacob 给 Emma 发送了一套明信片,并且 Emma 确实收到了一些明信片,她得出结论所有的明信片都已送达,并且该规则确实成立。艾玛的理由是,当她收到明信片时,所有的明信片都被投递了。然而,她不知道 Jacob 寄出的明信片没有被投递;因此,她无法在她的推论中解释这一点。艾玛经历的是生存偏见;也就是她根据留存下来的数据得出的结论。供您参考,附有学生对学生邮票的明信片上有一个圈起来的黑色字母 T 邮票,这意味着邮资是到期的,收件人应该支付它,包括一笔小额罚款。然而,邮件服务在收取这些费用时通常会有更高的成本,因此不会这样做。(magal hes,2010 年)。

另一个例子是一项研究发现,平均死亡年龄最低的职业是学生。当学生并不会导致你早夭;相反,作为一名学生意味着你年轻。这就是平均水平如此之低的原因。(盖尔曼和诺兰,2002 年)。

此外,一项研究发现,在事故中只有 1.5%的司机报告说他们在使用手机,而 10.9%的人报告说车里的另一个乘客分散了他们的注意力。我们能得出使用手机比与另一个居住者交谈更安全的结论吗?(悉尼科技大学,2003 年)要回答这个问题,我们需要知道手机使用的普遍性。在收集数据期间,很可能有更多的人在开车时与车内的另一位乘客交谈,而不是打手机。

数据预处理

数据预处理任务的目标是以尽可能好的方式为机器学习算法准备数据,因为并非所有算法都能够解决丢失数据、额外属性或反规格化值的问题。

数据清理

数据清理,也称为数据清理或数据清理,是一个由以下步骤组成的过程:

  1. 识别不准确、不完整、不相关或损坏的数据,以将其从进一步处理中移除
  2. 解析数据,提取感兴趣的信息,或者验证数据字符串的格式是否可以接受
  3. 将数据转换为通用编码格式,例如 UTF-8 或 int32、时间刻度或标准化范围
  4. 将数据转换成公共数据模式;例如,如果我们从不同类型的传感器收集温度测量值,我们可能希望它们具有相同的结构

填充缺失值

机器学习算法通常不能很好地处理缺失值。罕见的例外包括决策树、朴素贝叶斯分类器和一些基于规则的学习器。理解一个值缺失的原因是非常重要的。它可能由于多种原因而丢失,例如随机误差、系统误差和传感器噪声。一旦我们确定了原因,就有多种方法来处理丢失的值,如下表所示:

  • 删除实例:如果有足够的数据,并且只有几个不相关的实例有一些丢失的值,那么删除这些实例是安全的。
  • 删除属性:当大部分值缺失、值不变或者一个属性与另一个属性强相关时,删除一个属性是有意义的。
  • 指定一个特殊值 ( N/A ):有时由于有效的原因,某个值会丢失,例如该值超出范围,离散属性值未定义,或者无法获取或测量该值。例如,如果一个人从不评价一部电影,那么他对这部电影的评价就是不存在的。
  • 以平均属性值为例:如果我们的实例数量有限,我们可能无法承担删除实例或属性的费用。在这种情况下,我们可以通过分配平均属性值来估计缺失值。
  • 预测其他属性的值:如果属性具有时间相关性,则预测之前条目的值。

正如我们所看到的,值的丢失可能有多种原因,因此,理解值丢失、缺失或损坏的原因是很重要的。

移除异常值

数据中的异常值是不同于序列中任何其他值的值,并在不同程度上影响所有学习方法。这些可能是极端值,可以用置信区间来检测,并通过使用阈值来消除。最好的方法是将数据可视化,并检查可视化以检测不规则性。下图显示了一个示例。可视化仅适用于低维数据:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据转换

数据转换技术将数据集驯服为机器学习算法期望作为输入的格式,甚至可以帮助算法更快地学习并实现更好的性能。它也被称为数据管理或数据争论。例如,标准化假设数据遵循高斯分布,并以平均值为 0、偏差为 1 的方式转换值,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

另一方面,规范化将属性值调整到一个较小的指定范围,通常在 0 和 1 之间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

很多机器学习工具箱会自动为你将数据规格化、标准化。

最后一种转换技术是离散化,它将连续属性的范围划分为多个区间。我们为什么要关心?一些算法,如决策树和朴素贝叶斯更喜欢离散属性。选择间隔的最常见方法如下:

  • 等宽:连续变量的区间分为 k 等宽区间
  • 等频:假设有 N 个实例,每个 k 个区间包含大约 Nk 个实例
  • 最小熵(Min entropy):这种方法递归地分割区间,直到度量无序度的熵减少超过区间分割引入的熵增加(法耶兹和伊拉尼,1993)

前两种方法需要我们指定区间数,后一种方法自动设置区间数;然而,它需要 class 变量,这意味着它不适用于无监督的机器学习任务。

数据整理

数据约简处理丰富的属性和实例。属性的数量对应于数据集中的维数。预测能力低的维度对整体模型的贡献很小,造成的危害很大。例如,具有随机值的属性可以引入一些随机模式,这些模式将被机器学习算法拾取。可能会出现数据包含大量缺失值的情况,我们必须找到大量缺失值的原因,并在此基础上用一些替代值填充,或者估算或完全删除属性。如果缺少 40%或更多的值,那么建议删除这些属性,因为这会影响模型性能。

另一个因素是方差,其中常数变量可能具有较低的方差,这意味着数据彼此非常接近,或者数据中没有太大的变化。

为了处理这个问题,第一组技术去除这样的属性并选择最有希望的属性。这一过程被称为特征选择或属性选择,包括诸如 ReliefF、信息增益和基尼指数等方法。这些方法主要关注离散属性。

另一组工具侧重于连续属性,将数据集从原始维度转换到低维空间。例如,如果我们在三维空间中有一组点,我们可以将其投影到二维空间中。一些信息丢失了,但是在第三维度不相关的情况下,我们不会丢失太多,因为数据结构和关系几乎被完美地保留了下来。这可以通过以下方法实现:

  • 奇异值分解 ( SVD )
  • 主成分分析 ( PCA )
  • 向后/向前特征消除
  • 要素分析
  • 线性判别分析 ( LDA )
  • 神经网络自动编码器

数据简化的第二个问题与过多的实例有关;例如,它们可能是重复的或者来自非常频繁的数据流。主要思想是选择实例的子集,使得所选数据的分布仍然类似于原始数据分布,更重要的是,类似于观察到的过程。减少实例数量的技术包括随机数据采样、分层等。一旦准备好数据,我们就可以开始数据分析和建模了。

无监督学习

无监督学习是关于分析数据和发现未标记数据中的隐藏结构。因为没有给出正确标签的概念,所以也没有错误度量来评估学习模型;然而,无监督学习是一个极其强大的工具。你有没有想过亚马逊如何预测你会喜欢什么书?或者网飞如何在你之前知道你想看什么?答案可以在无监督学习中找到。我们将在下一节看一个类似的无监督学习的例子。

查找相似的项目

许多问题可以表述为寻找相似的元素集合,例如,购买相似产品的客户、具有相似内容的网页、具有相似对象的图像、访问相似网站的用户等等。

如果两个项目相距很小,则认为它们是相似的。主要问题是如何表示每个项目,以及如何定义项目之间的距离。距离测量主要有两类:

  • 欧几里德距离
  • 非欧几里德距离

欧几里德距离

在欧几里得空间中,在维度为 n 的情况下,两个元素之间的距离是基于元素在这样一个空间中的位置,表示为p-范数距离。两种常用的距离度量是 L2 范数距离和 L1 范数距离。

L2 范数,也称为欧几里德距离,是最常用的距离度量,用于测量二维空间中两个项目之间的距离。其计算方法如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

L1 定额,也称为曼哈顿距离、城市街区距离和出租车定额,简单地对每个维度的绝对差异求和,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

非欧几里德距离

非欧几里得距离是基于元素的属性,而不是基于它们在空间中的位置。一些众所周知的距离是雅克卡距离、余弦距离、编辑距离和汉明距离。

Jaccard distance 用于计算两组之间的距离。首先,我们将两个集合的 Jaccard 相似性计算为它们的交集大小除以它们的并集大小,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后根据以下公式定义 Jaccard 距离:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

两个向量之间的余弦距离关注的是方向而不是大小,因此,两个方向相同的向量的余弦相似度为 1,而两个垂直的向量的余弦相似度为 0。假设我们有两个多维点,把一个点想象成一个从原点出发的向量( 0,0,…,0 到它的位置。两个向量构成一个角度,其余弦距离是向量的归一化点积,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

余弦距离常用于高维特征空间;例如,在文本挖掘中,文本文档代表一个实例,对应于不同单词的特征,它们的值对应于单词在文档中出现的次数。通过计算余弦相似度,我们可以测量两个文档在描述相似内容时匹配的可能性。

编辑距离在我们比较两个字符串的时候是有意义的。a=a1,a2,a3 之间的距离,…an 和 b=b1,b2,b3,…bn strings 是将字符串从 a 转换为 b 所需的单个字符的插入/删除操作的最小次数,例如,a = abcd,b = abbd。要将 a 转换成 b,我们必须删除第二个 b,并在它的位置插入 c。没有任何最小数量的运算会将 a 转换成 b,因此距离为 d(a,b) =2。

汉明距离比较两个大小相同的向量,并计算它们不同的维数。换句话说,它测量将一个载体转换成另一个载体所需的替换次数。

有许多侧重于各种属性的距离度量,例如,相关性度量两个元素之间的线性关系; Mahalanobis distance 度量一个点与其他点的分布之间的距离 SimRank 基于图论,度量元素出现的结构的相似性,等等。正如您所想象的,为您的问题选择和设计正确的相似性度量是成功的一半以上。A. A. Goshtasby,Springer Science and Business Media(2012)所著的《图像配准:原理、工具和方法》一书的第二章相似性和不相似性度量 *、*中收集了对相似性度量的令人印象深刻的概述和评估。

维度的诅咒

维数灾难指的是这样一种情况,我们有大量的特征,通常有数百个或数千个,这导致数据稀疏的空间非常大,从而导致距离异常。例如,在高维空间中,几乎所有的点对彼此之间的距离都是相等的;事实上,几乎所有配对的距离都接近平均距离。诅咒的另一个表现是任何两个向量几乎是正交的,这意味着所有的角度都接近 90 度。这实际上使任何距离测量变得无用。

一种解决维数灾难的方法可能会在一种数据简化技术中找到,在这种技术中,我们希望减少特征的数量;例如,我们可以运行一个特征选择算法,比如 ReliefF,或者一个特征提取或简化算法,比如 PCA。

使聚集

聚类是一种根据一些距离度量将相似的实例分组到簇中的技术。主要思想是将相似(即彼此靠近)的实例放入同一个群集中,同时将不相似的点(即彼此远离的点)放在不同的群集中。下图显示了群集的一个示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

聚类算法遵循两种根本不同的方法。第一种是分层或凝聚方法,首先将每个点视为其自己的聚类,然后迭代地将最相似的聚类合并在一起。当进一步的合并达到预定义的聚类数量时,或者如果要合并的聚类分布在很大的区域上时,它停止。

另一种方法是基于点分配。首先,例如随机地估计初始聚类中心(即质心),然后,将每个点分配给最近的聚类,直到所有的点都被分配。这一组中最著名的算法是 k 均值聚类。

k-均值聚类或者选取初始聚类中心作为彼此尽可能远的点,或者(分层地)对数据样本进行聚类,并选取最接近每个 k-聚类中心的点。

监督学习

监督学习是语音识别、垃圾邮件过滤、照片中的人脸识别以及检测信用卡欺诈等惊人事情背后的关键概念。更正式地说,给定一组用特征 X 描述的学习示例 D,监督学习的目标是找到预测目标变量 Y 的函数。描述特征 X 和类 Y 之间关系的函数 f 称为模型:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

监督学习算法的一般结构由以下决定定义(Hand 等人,2001 年):

  1. 定义任务
  2. 决定引入特定归纳偏差的机器学习算法;也就是说,它对目标概念的先验假设
  3. 决定分数或成本函数,例如,信息增益、均方根误差等等
  4. 决定优化/搜索方法以优化得分函数
  5. 找出一个描述 X 和 Y 之间关系的函数

许多决定已经由我们所拥有的任务和数据集的类型为我们做出了。在接下来的几节中,我们将进一步了解分类和回归方法以及相应的得分函数。

分类

当我们处理一个离散类时,可以应用分类,其中的目标是预测目标变量中的一个互斥值。信用评分就是一个例子,它的最终预测是这个人是否有信用责任。最流行的算法包括决策树、朴素贝叶斯分类器、支持向量机、神经网络和集成方法。

决策树学习

决策树学习构建分类树,每个节点对应其中一个属性;边对应于节点源自的属性的可能值(或区间);每片叶子对应一个类别标签。决策树可用于直观和明确地表示预测模型,这使其成为非常透明的(白盒)分类器。值得注意的算法是 ID3 和 C4.5,尽管存在许多替代实现和改进(例如,Weka 中的 J48)。

概率分类器

给定一组属性值,概率分类器能够预测一组类的分布,而不是准确的类。这可以作为一定程度的确定性;也就是说,分类器对其预测有多大把握。最基本的分类器是朴素贝叶斯,当且仅当属性条件独立时,它才是最佳分类器。不幸的是,这在实践中极为罕见。

有一个被称为概率图形模型的巨大子领域,包括数百种算法,例如贝叶斯网络、动态贝叶斯网络、隐马尔可夫模型和条件随机场,它们不仅可以处理属性之间的特定关系,还可以处理时间依赖性。Kiran R Karkera 写了一本关于这个主题的优秀入门书籍,用 Python 构建概率图形模型,Packt 出版社(2014),而柯勒和弗里德曼则出版了一本全面的理论圣经,*概率图形模型,*麻省理工出版社(2009)。

核心方法

任何线性模型都可以通过对模型应用核技巧(用核函数替换其特征(预测值))而变成非线性模型。换句话说,内核隐式地将我们的数据集转换到更高维度。内核技巧利用了这样一个事实,即在更多维度上分离实例通常更容易。能够对内核进行操作的算法包括内核感知器、支持向量机、高斯过程、PCA、典型相关分析、岭回归、谱聚类、线性自适应滤波器等等。

人工神经网络

人工神经网络受生物神经网络结构的启发,能够进行机器学习和模式识别。它们通常用于回归和分类问题,包括各种算法和各种问题类型的变体。一些流行的分类方法有感知器受限玻尔兹曼机 ( RBM )、深度信念网络

集成学习

集成方法由一组不同的较弱模型组成,以获得更好的预测性能。单独训练各个模型,然后以某种方式将它们的预测组合起来,以进行整体预测。因此,集成包含多种建模数据的方式,这有望带来更好的结果。这是一类非常强大的技术,因此非常受欢迎。这个类包括 boosting、bagging、AdaBoost 和 random forest。他们之间的主要区别是要结合的弱学习者的类型和结合他们的方式。

评估分类

我们的分类器做得好吗?这个比另一个好吗?在分类中,我们会计算我们对某件事进行正确和错误分类的次数。假设有“是”和“否”两种可能的分类标签,则有四种可能的结果,如下表所示:

| | 预测为阳性? |
| | |
| 真的阳性? | | TP-真阳性 | FN-假阴性 |
| | FP-假阳性 | TN-真阴性 |

四个变量:

  • 真肯定 ( 击中):这表示一个 yes 实例被正确预测为 yes
  • 真否定 ( 正确拒绝):这表示没有实例被正确预测为否
  • 误报 ( 误报):表示没有实例预测为是
  • 假阴性 ( 错过):这表示一个是实例被预测为否

分类器的两个基本性能指标是,首先,分类误差:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其次,分类准确性是另一个性能衡量指标,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这两种方法的主要问题是它们不能处理不平衡的类。对信用卡交易是否滥用进行分类是不平衡分类问题的一个例子:有 99.99%的正常交易,只有极小比例的滥用。说每笔交易都是正常交易的分类器有 99.99%的准确率,但我们主要对那些很少出现的少数分类感兴趣。

精确度和召回率

解决办法是使用不涉及真正负面的方法。两项此类措施如下:

  • Precision :正确预测为正( TP )的正例占所有预测为正( TP + FP )的正例的比例;

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 回忆:这是所有正例( TP + FN )中被正确预测为正例( TP )的正例的比例;

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通常将两者结合起来并报告 F-measure ,它同时考虑了精确度和召回率,以加权平均值的形式计算得分,其中得分在 1 时达到最佳值,在 0 时达到最差值,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Roc 曲线

大多数分类算法返回表示为 f(X) 的分类置信度,该置信度又用于计算预测。以信用卡滥用为例,规则可能如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

阈值决定了错误率和真阳性率。所有可能阈值的结果可以绘制成接收器工作特性 ( ROC ),如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

随机预测值用红色虚线绘制,理想预测值用绿色虚线绘制。为了比较 A 分类器是否优于 C ,我们比较曲线下的面积。

大多数工具箱都提供了所有现成的先前测量。

回归

回归处理的是连续的目标变量,而分类处理的是离散的目标变量。例如,为了预测未来几天的室外温度,我们将使用回归,而分类将用于预测是否会下雨。一般来说,回归是一个估计特征之间关系的过程,即改变一个特征如何改变目标变量。

线性回归

最基本的回归模型假设特征和目标变量之间的线性相关性。该模型通常使用最小二乘法拟合,即最佳模型使误差的平方最小化。在许多情况下,线性回归不能模拟复杂的关系;例如,下图显示了具有相同线性回归线的四组不同的点。左上角的模型捕捉到了总体趋势,可被视为合适的模型,而左下角的模型拟合点更好(除了一个异常值,应仔细检查),右上角和右下角的线性模型完全错过了数据的基本结构,不能被视为合适的模型:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

逻辑回归

当因变量连续时,线性回归有效。然而,如果因变量本质上是二元的,即 0 或 1、成功或失败、是或否、真或假、存活或死亡等等,那么就用逻辑回归来代替。一个这样的例子是药物的临床试验,其中被研究的对象或者对药物有反应或者没有反应。它还用于欺诈检测,即交易是欺诈还是非欺诈。通常,逻辑函数用于衡量因变量和自变量之间的关系。它被视为伯努利分布,当绘制时,看起来类似于字符形状的曲线。

评估回归

在回归中,我们从输入 X 预测数字 Y,而预测通常是错误的或不准确的。我们必须问的主要问题是:增加多少?换句话说,我们想要测量预测值和真实值之间的距离。

均方误差

均方误差 ( MSE )是预测值和真实值之间的平方差的平均值,如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

该度量对异常值非常敏感,例如,99 个精确预测和 1 个相差 10 的预测与所有相差 1 的预测得分相同。此外,该度量对均值敏感。因此,通常使用相对平方误差来比较我们的预测值的 MSE 和平均预测值(总是预测平均值)的 MSE。

绝对平均误差

平均绝对误差 ( MAS )是预测值和真实值之间绝对差值的平均值,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

MAS 对异常值不太敏感,但对平均值和标度也很敏感。

相关系数

相关系数 ( CC )比较相对于平均值的预测平均值,乘以相对于平均值的训练值。如果数字为负,说明弱相关;正数表示相关性强;零表示没有相关性。真实值 X 和预测值 Y 之间的相关性定义如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

CC 测量对平均值和标度完全不敏感,对异常值不太敏感。它能够捕捉相对排序,这使得它对于排序任务非常有用,例如文档相关性和基因表达。

概括和评价

一旦建立了模型,我们如何知道它将在新数据上执行?这个模型好吗?为了回答这些问题,我们将首先研究模型的泛化,然后看看如何获得对新数据的模型性能的估计。

欠拟合和过拟合

预测器训练可能导致模型过于复杂或过于简单。低复杂度的模型(下图中最左边的模型)可以简单到预测最频繁或平均的类值,而高复杂度的模型(最右边的模型)可以表示定型实例。过于僵硬的模式,显示在左手边,不能捕捉复杂的模式;而右侧所示的过于灵活的模型适合训练数据中的噪声。主要的挑战是选择适当的学习算法及其参数,以便学习的模型将在新数据上表现良好(例如,中间的列):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下图显示了定型集中的错误如何随着模型复杂性的增加而减少。简单的刚性模型对数据拟合不足,误差较大。随着模型复杂性的增加,它可以更好地描述训练数据的基础结构,因此,误差会减小。如果模型太复杂,它会过度拟合训练数据,并且其预测误差会再次增加:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

根据任务的复杂性和数据的可用性,我们希望将我们的分类器调整到更复杂或更简单的结构。大多数学习算法都允许这样的调整,如下所示:

  • 回归:这是多项式的阶
  • 朴素贝叶斯:这是属性的数量
  • 决策树:这是树中节点的数量——修剪置信度
  • K-最近邻居:这是邻居的数量——基于距离的邻居权重
  • SVM :这是内核类型;成本参数
  • 神经网络:这是神经元和隐含层的数量

通过调整,我们希望最小化泛化误差;也就是说,分类器对未来数据的表现如何。不幸的是,我们永远无法计算真实的泛化误差;但是,我们可以估算一下。然而,如果模型在训练数据上表现良好,但在测试数据上表现差得多,则模型很可能过拟合。

训练和测试集

为了估计泛化误差,我们将数据分成两部分:训练数据和测试数据。一个通用的经验法则是按照培训:测试的比例(即 70:30)将它们分开。我们首先根据训练数据训练预测器,然后预测测试数据的值,最后计算误差,即预测值和真实值之间的差异。这给了我们一个真实的泛化误差的估计。

该估计基于以下两个假设:首先,我们假设测试集是来自数据集的无偏样本;第二,我们假设实际的新数据将重组分布作为我们的训练和测试示例。第一个假设可以通过交叉验证和分层来缓解。此外,如果它是稀缺的,人们不能为一个单独的测试集遗漏大量的数据,因为如果学习算法没有接收到足够的数据,它们就不会执行得很好。在这种情况下,使用交叉验证来代替。

交叉验证

交叉验证将数据集分成大小大致相同的 k 个集合,例如,在下图中,分成五个集合。首先,我们使用集合 2 到 5 进行学习,集合 1 进行训练。然后,我们重复该过程五次,每次留出一组进行测试,并平均五次重复的误差:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这样,我们也可以使用所有的数据进行学习和测试,同时避免使用相同的数据来训练和测试模型。

留一验证

交叉验证的一个极端例子是留一验证。在这种情况下,折叠的数量等于实例的数量;我们在除了一个实例之外的所有实例上学习,然后在省略的实例上测试模型。我们对所有实例重复这一过程,以便每个实例只被用于一次验证。当我们只有有限的一组学习示例时,例如少于 50 个,推荐使用这种方法。

分层

分层是一个选择实例子集的过程,其方式是每个文件夹大致包含相同比例的类值。当一个类是连续的时,选择的折叠使得平均响应值在所有的折叠中近似相等。分层可以与交叉验证或单独的训练和测试集一起应用。

摘要

在这一章中,我们更新了机器学习基础知识。我们回顾了应用机器学习的工作流程,并阐明了主要任务、方法和算法。我们学习了不同类型的回归以及如何评估它们。我们还探索了交叉验证及其应用。

在下一章,我们将学习 Java 库,它们可以执行的任务,以及不同的机器学习平台。

二、用于机器学习的 Java 库和平台

自己实现机器学习算法可能是学习机器学习的最佳方式,但如果你站在巨人的肩膀上,利用现有的开源库之一,你可以进步得更快。

本章回顾了 Java 中用于机器学习的各种库和平台。目标是了解每个库带来了什么,以及它能够解决什么样的问题。

在本章中,我们将讨论以下主题:

  • 实现机器学习应用程序对 Java 的要求
  • Weka,一个通用机器学习平台
  • Java 机器学习库,机器学习算法的集合
  • Apache Mahout,一个可扩展的机器学习平台
  • Apache Spark,一个分布式机器学习库
  • Deeplearning4j,深度学习库
  • MALLET,一个文本挖掘库

我们还将讨论如何通过将这些库与其他组件一起使用,为单机和大数据应用设计完整的机器学习应用堆栈。

对 Java 的需求

新的机器学习算法通常首先在大学实验室编写脚本,将 shell 脚本、Python、R、MATLAB、Scala 或 C++等几种语言粘合在一起,以提供一个新概念,并从理论上分析其属性。一个算法在进入一个具有标准化输入或输出和接口的程序库之前,可能要经历一个漫长的重构过程。虽然 Python、R 和 MATLAB 相当流行,但它们主要用于编写脚本、研究和实验。另一方面,Java 是事实上的企业语言,这可以归功于静态类型、健壮的 IDE 支持、良好的可维护性以及体面的线程模型和高性能并发数据结构库。此外,已经有许多 Java 库可用于机器学习,这使得在现有的 Java 应用程序中应用它们并利用强大的机器学习功能非常方便。

机器学习库

MLOSS.org 网站上列出了超过 70 个基于 Java 的开源机器学习项目,可能还有更多未列出的项目位于大学服务器、GitHub 或 Bitbucket 上。在这一节中,我们将回顾主要的库和平台,它们可以解决的问题类型,它们支持的算法,以及它们可以处理的数据类型。

新西兰黑秧鸡

怀卡托知识分析环境 ( WEKA )是新西兰怀卡托大学开发的机器学习库,可能是最知名的 Java 库。这是一个通用库,能够解决各种各样的机器学习任务,如分类、回归和聚类。它具有丰富的图形用户界面、命令行界面和 Java API。你可以在 http://www.cs.waikato.ac.nz/ml/weka/的查看 Weka。

在写这本书的时候,Weka 总共包含了 267 种算法:数据预处理(82),属性选择(33),分类回归(133),聚类(12),关联规则挖掘(7)。图形界面非常适合探索您的数据,而 Java API 允许您开发新的机器学习方案,并在应用程序中使用这些算法。

Weka 是在 GNU 通用公共许可证 ( GNU GPL )下发布的,这意味着只要你跟踪源文件中的变化并保持在 GNU GPL 下,你就可以复制、发布和修改它。你甚至可以在商业上发布它,但是你必须公开源代码或者获得商业许可。

除了几种受支持的文件格式之外,Weka 还有自己的默认数据格式,即 ARFF,通过属性-数据对来描述数据。它由两部分组成。第一部分包含一个头,它指定了所有属性及其类型,例如,名义、数字、日期和字符串。第二部分包含数据,其中每一行对应一个实例。头中的最后一个属性被隐式地认为是目标变量,缺少的数据用问号标记。例如,回到来自第一章、应用机器学习快速入门的示例,以 ARFF 文件格式编写的Bob实例如下:

@RELATION person_dataset @ATTRIBUTE `Name` STRING @ATTRIBUTE `Height` NUMERIC @ATTRIBUTE `Eye color`{blue, brown, green} @ATTRIBUTE `Hobbies` STRING @DATA 'Bob', 185.0, blue, 'climbing, sky diving' 'Anna', 163.0, brown, 'reading' 'Jane', 168.0, ?, ? 

该文件由三部分组成。第一部分以@RELATION <String>关键字开始,指定数据集名称。下一部分以关键字@ATTRIBUTE开始,后面是属性名和类型。可用的类型有STRINGNUMERICDATE和一组分类值。最后一个属性被隐含地假定为我们想要预测的目标变量。最后一部分以关键字@DATA开始,每行一个实例。实例值由逗号分隔,并且必须遵循与第二部分中的属性相同的顺序。

更多 Weka 示例将在第三章、基本算法——分类、回归和聚类以及第四章、用系综进行客户关系预测中演示。

要了解关于 Weka 的更多信息,请阅读一本快速入门书籍,由卡鲁扎出版社出版的 Weka How-to、开始编写代码,或者查阅由 Witten 和 Frank摩根考夫曼出版社出版的数据挖掘:实用的机器学习工具和 Java 实现技术,了解理论背景和深入的解释。

Weka 的 Java API 被组织成以下顶级包:

  • weka.associations:这些是关联规则学习的数据结构和算法,包括先验预测先验过滤关联器FP-Growth广义序列模式 ( GSP )、热点Tertius
  • 这些是监督学习算法、评估器和数据结构。该包进一步分为以下几个部分:
    • weka.classifiers.bayes:实现了贝叶斯方法,包括朴素贝叶斯、贝叶斯网、贝叶斯逻辑回归等等。
    • weka.classifiers.evaluation:这些是针对名义和数值预测的监督评估算法,比如评估统计、混淆矩阵、ROC 曲线等等。
    • weka.classifiers.functions:这些是回归算法,包括线性回归、保序回归、高斯过程、支持向量机(SVM)、多层感知器、投票感知器等。
    • weka.classifiers.lazy:这些是基于实例的算法,比如 K-最近邻、K*和懒惰贝叶斯规则。
    • weka.classifiers.meta:这些是监督学习元算法,包括 AdaBoost、bagging、加法回归、随机委员会等等。
    • weka.classifiers.mi:这些都是多实例学习算法,比如引文 k 近邻、多样性密度、AdaBoost 等等。
    • 这些是基于分而治之方法、RIPPER、PART、PRISM 等的决策表和决策规则。
    • weka.classifiers.trees:这些是各种决策树算法,包括 ID3,C4.5,M5,功能树,逻辑树,随机森林等等。
    • weka.clusterers:这些是聚类算法,包括 k-means,CLOPE,Cobweb,DBSCAN 层次聚类,FarthestFirst。
    • 这些是各种实用程序类,例如属性类、统计类和实例类。
    • 这些是用于分类、回归和聚类算法的数据生成器。
    • weka.estimators:这些是离散/名义域的各种数据分布估计器,条件概率估计等等。
    • 这些是一组类,支持运行实验所必需的配置、数据集、模型设置和统计。
    • weka.filters:这些是基于属性和基于实例的选择算法,用于监督和非监督数据预处理。
    • 这些是实现资源管理器、实验器和知识流应用程序的图形界面。Weka Explorer 允许您研究数据集、算法及其参数,并使用散点图和其他可视化方式可视化数据集。Weka 实验器用于设计批量实验,但只能用于分类和回归问题。Weka KnowledgeFlow 实现了一个可视化的拖放用户界面来构建数据流,例如,加载数据、应用过滤器、构建分类器以及评估它。

Java 机器学习

Java 机器学习库 ( Java-ML )是一个机器学习算法的集合,具有同类型算法的通用接口。它只以 Java API 为特色,因此主要面向软件工程师和程序员。Java-ML 包含数据预处理、特征选择、分类和聚类的算法。此外,它还具有几个 Weka 桥,可以通过 Java-ML API 直接访问 Weka 的算法。可以从 http://java-ml.sourceforge.net 的下载。

Java-ML 也是一个通用的机器学习库。与 Weka 相比,它提供了更一致的接口和其他软件包中不存在的最新算法的实现,例如一组广泛的最先进的相似性度量和特征选择技术,例如,动态时间扭曲()、随机森林属性评估等等。Java-ML 在 GNU GPL 许可下也是可用的。

**Java-ML 支持所有类型的文件,只要它们每行包含一个数据样本,并且用逗号、分号或制表符等符号分隔。

该库是围绕以下顶级包组织的:

  • net.sf.javaml.classification:这些是分类算法,包括朴素贝叶斯、随机森林、bagging、自组织地图、k 近邻等等
  • 这些是聚类算法,如 k-means、自组织映射、空间聚类、蛛网、ABC 等
  • 这些是代表实例和数据集的类
  • 这些是测量实例距离和相似性的算法,例如,切比雪夫距离、余弦距离/相似性、欧几里德距离、雅克卡距离/相似性、马哈拉诺比斯距离、曼哈顿距离、闵可夫斯基距离、皮尔逊相关系数、斯皮尔曼尺距、DTW 等等
  • net.sf.javaml.featureselection:这些是用于特征评估、评分、选择和排序的算法,例如,增益率、ReliefF、Kullback-Leibler 散度、对称不确定性等等
  • 这些是通过过滤、删除属性、设置类或属性值等操作实例的方法
  • net.sf.javaml.matrix:这实现了内存或基于文件的数组
  • net.sf.javaml.sampling:这实现了采样算法来选择数据集的子集
  • 这些是关于数据集、实例操作、序列化、Weka API 接口等等的实用方法
  • 这些是算法的实用方法,例如,统计、数学方法、列联表等等** **

阿帕奇看象人

Apache Mahout 项目旨在建立一个可扩展的机器学习库。它使用 MapReduce 范式构建在可扩展的分布式架构(如 Hadoop)之上,MapReduce 范式是一种使用服务器集群通过并行分布式算法处理和生成大型数据集的方法。

Mahout 具有一个控制台界面和 Java API,作为集群、分类和协作过滤的可伸缩算法。它能够解决三个业务问题:

  • 物品推荐:推荐 等物品喜欢这部电影的人也喜欢
  • 聚类:将文本文档分类成与主题相关的文档组
  • 分类:学习将哪个主题分配给未标记的文档

Mahout 是在商业友好的 Apache 许可下发布的,这意味着只要您保留 Apache 许可并在程序的版权声明中显示它,您就可以使用它。

Mahout 具有以下库:

  • org.apache.mahout.cf.taste:这些是基于基于用户和基于项目的协同过滤和基于 ALS 的矩阵分解的协同过滤算法
  • org.apache.mahout.classifier:这些是内存和分布式实现,包括逻辑回归、朴素贝叶斯、随机森林、隐马尔可夫模型 ( HMM )和多层感知器
  • org.apache.mahout.clustering:这些是聚类算法,例如树冠聚类、k-均值、模糊 k-均值、流式 k-均值和谱聚类
  • 这些是算法的实用方法,包括距离、MapReduce 操作、迭代器等等
  • org.apache.mahout.driver:实现了一个通用的驱动程序来运行其他类的 main 方法
  • org.apache.mahout.ep:这是使用记录步骤变异的进化优化
  • 这些是 Hadoop 中的各种数学工具方法和实现
  • 这些是用于数据表示、操作和 MapReduce 作业的类

阿帕奇火花

Apache Spark,或简称 Spark,是一个基于 Hadoop 构建的大规模数据处理平台,但是与 Mahout 不同,它不依赖于 MapReduce 范式。相反,它使用内存缓存来提取一组工作数据,对其进行处理,并重复查询。据报道,这比直接处理存储在磁盘中的数据的 Mahout 实现快 10 倍。可以从spark.apache.org抢。

Spark 上构建了许多模块,例如,GraphX 用于图形处理,Spark Streaming 用于处理实时数据流,MLlib 用于机器学习库,具有分类、回归、协同过滤、聚类、降维和优化功能。

Spark 的 MLlib 可以使用基于 Hadoop 的数据源,例如, Hadoop 分布式文件系统()或 HBase,以及本地文件。支持的数据类型包括:

*** 本地向量存储在一台机器上。密集向量表示为双类型值的数组,例如(2.0,0.0,1.0,0.0),而稀疏向量表示为向量的大小、索引数组和值数组,例如[4,(0,2),(2.0,1.0)]。

  • 标记点用于监督学习算法,由标记有双类型类值的局部向量组成。标签可以是类别索引、二进制结果或多个类别索引的列表(多类别分类)。例如,标记的密集向量表示为[1.0,(2.0,0.0,1.0,0.0)]。
  • 局部矩阵在单台机器上存储一个密集矩阵。它由矩阵维数和以列主顺序排列的单个双数组定义。
  • 分布式矩阵对存储在 Spark 的弹性分布式数据集 ( RDD )中的数据进行操作,该数据集代表了可以并行操作的元素集合。有三种表示法:行矩阵,其中每一行都是可以存储在单台机器上的局部向量,行索引没有意义;索引行矩阵,类似于行矩阵,但行索引是有意义的,即行可以被标识,连接可以被执行;和坐标矩阵,当一行不能存储在单台机器上并且矩阵非常稀疏时使用。

Spark 的 MLlib API 库为各种学习算法和实用程序提供了接口,如下表所示:

  • 这些是二元和多类分类算法,包括线性支持向量机、逻辑回归、决策树和朴素贝叶斯
  • 这些是 k 均值聚类算法
  • 这些是数据表示,包括密集向量、稀疏向量和矩阵
  • org.apache.spark.mllib.optimization:这些是在 MLlib 中用作底层原语的各种优化算法,包括梯度下降、随机梯度下降 ( SGD )、分布式 SGD 的更新方案以及有限内存Broyden–Fletcher–Goldfarb–Shanno(BFGS算法
  • 这些是基于模型的协同过滤技术,通过交替最小二乘矩阵分解来实现
  • 这些是回归学习算法,比如线性最小二乘法、决策树、Lasso 和岭回归
  • org.apache.spark.mllib.stat:这些是稀疏或密集向量格式的样本的统计函数,用于计算平均值、方差、最小值、最大值、计数和非零计数
  • org.apache.spark.mllib.tree:这实现了分类和回归决策树学习算法
  • 这些是用于加载、保存、预处理、生成和验证数据的方法的集合** **

深度学习 4j

Deeplearning4j,或 DL4J,是一个用 Java 编写的深度学习库。它具有分布式以及单机深度学习框架,包括并支持各种神经网络结构,如前馈神经网络、RBM、卷积神经网络、深度信念网络、自动编码器等。DL4J 可以解决不同的问题,例如识别面孔、声音、垃圾邮件或电子商务欺诈。

Deeplearning4j 也在 Apache 2.0 许可下发布,可以从deeplearning4j.org下载。该库的组织结构如下:

  • 这些是加载类
  • 这些是数学实用方法
  • org.deeplearning4j.clustering:这是 k-means 聚类的实现
  • org.deeplearning4j.datasets:这是数据集操作,包括导入、创建、迭代等
  • 这些是分配的实用方法
  • 这些是评估类,包括混淆矩阵
  • org.deeplearning4j.exceptions:实现异常处理程序
  • 这些是监督学习算法,包括深度信念网络、堆叠自动编码器、堆叠去噪自动编码器和 RBM
  • org.deeplearning4j.nn:这些是基于神经网络的组件和算法的实现,比如神经网络、多层网络、卷积多层网络等等
  • org.deeplearning4j.optimize:这些是神经网络优化算法,包括反向传播、多层优化、输出层优化等等
  • 这些是渲染数据的各种方法
  • 这是一个随机数据发生器
  • 这些是助手和实用程序方法

木槌

语言工具包 ( 木槌)是一个大型的自然语言处理算法和实用程序库。它可用于多种任务,如文档分类、文档聚类、信息提取和主题建模。它有一个命令行界面和一个 Java API,用于一些算法,如朴素贝叶斯、HMM、潜在狄利克雷主题模型、逻辑回归和条件随机字段。

MALLET 在通用公共许可证 1.0 下可用,这意味着您甚至可以在商业应用程序中使用它。可以从mallet.cs.umass.edu下载。MALLET 实例由名称、标签、数据和源表示。但是,有两种方法可以将数据导入 MALLET 格式,如下表所示:

  • 每个文件的实例:每个文件或文档对应一个实例,MALLET 接受输入的目录名。
  • 每行一个实例:每行对应一个实例,假设格式如下——instance_name标签令牌。数据将是一个特征向量,由作为标记出现的不同单词及其出现次数组成。

该库由以下软件包组成:

  • cc.mallet.classify:这些是用于训练和分类实例的算法,包括 AdaBoost、bagging、C4.5,以及其他决策树模型、多元逻辑回归、朴素贝叶斯和 Winnow2。
  • cc.mallet.cluster:这些是无监督聚类算法,包括贪婪凝聚、爬山、k-best、k-means 聚类。
  • 这个实现了记号赋予器、文档提取器、文档查看器、清理器等等。
  • cc.mallet.fst:这个实现了序列模型,包括条件随机场,HMM,最大熵马尔可夫模型,以及相应的算法和评估器。
  • cc.mallet.grmm:这实现了图形模型和因子图,比如推理算法、学习和测试,例如,loopy 信念传播、Gibbs 抽样等等。
  • cc.mallet.optimize:这些是寻找函数最大值的优化算法,比如梯度上升、有限记忆 BFGS、随机元上升等等。
  • 这些方法是将数据处理成 MALLET 实例的管道。
  • 这些是主题建模算法,比如潜在狄利克雷分配,四级弹球分配,分级 PAM,DMRT 等等。
  • cc.mallet.types:实现数据集、特征向量、实例、标签等基本数据类型。
  • 这些是各种各样的实用函数,比如命令行处理、搜索、数学、测试等等。

Encog 机器学习框架

Encog 是由数据科学家杰夫·希顿开发的 Java/C#机器学习框架。它支持标准化和处理数据以及各种高级算法,如 SVM、神经网络、贝叶斯网络、隐马尔可夫模型、遗传编程和遗传算法。从 2008 年开始积极开发。它支持多线程,可提升多核系统的性能。

可以在www.heatonresearch.com/encog/找到。MLMethod 是基本接口,它包括模型的所有方法。以下是它包含的一些接口和类:

  • MLRegression:该接口定义回归算法
  • MLClassification:该接口定义了分类算法
  • MLClustering:该接口定义了聚类算法
  • 这个类代表了一个模型中使用的向量,用于输入或输出
  • MLDataPair:该类的功能与MLData类似,但可用于输入和输出
  • MLDataSet:表示培训师的MLDataPair实例列表
  • 这个类被用作一个神经元
  • FreeformConnection:显示神经元之间的加权连接
  • FreeformContextNeuron:这代表一个上下文神经元
  • InputSummation:该值指定如何对输入求和以形成单个神经元
  • 这是所有输入神经元的简单总和
  • BasicFreeConnection:这是神经元之间的基本加权连接
  • BasicFreeformLayer:该界面提供了一个图层

埃尔基

ELKI 为开发由索引结构支持的 KDD 应用程序创建了一个环境,重点是无监督学习。它为聚类分析和离群点检测提供了各种实现。它提供了诸如 R*树的索引结构来提高性能和可伸缩性。到目前为止,它已被学生和教师广泛应用于研究领域,最近也引起了其他方面的关注。

ELKI 使用 AGPLv3 许可证,可以在elki-project.github.io/找到。它由以下软件包组成:

  • de.lmu.ifi.dbs.elki.algorithm:包含聚类、分类、项目集挖掘等各种算法
  • de.lmu.ifi.dbs.elki.outlier:定义基于异常值的算法
  • de.lmu.ifi.dbs.elki.statistics:定义统计分析算法
  • 这是 ELKI 数据库层
  • de.lmu.ifi.dbs.elki.index:这是为了实现索引结构
  • de.lmu.ifi.dbs.elki.data:定义各种数据类型和数据库对象类型

恐鸟

大规模在线分析 ( MOA )包含大量各种机器学习算法,包括分类、回归、聚类、离群点检测、概念漂移检测和推荐系统的算法,以及评估工具。所有算法都是为大规模机器学习而设计的,有漂移的概念,处理实时数据流。它还可以很好地与 Weka 一起工作和集成。

它以 GNU 许可证的形式提供,可以从 https://moa.cms.waikato.ac.nz/下载。以下是它的主要软件包:

  • moa.classifiers:包含分类的算法
  • moa.clusters:包含聚类的算法
  • moa.streams:包含与流相关的类
  • moa.evaluation:用于评估

比较库

下表总结了所有提供的库。该表绝不是详尽的,还有更多涵盖特定问题领域的库。这篇综述应该作为 Java 机器学习世界中的大人物的概述:

| 图书馆 | 问题域 | 执照 | 架构 | 算法 |
| 新西兰黑秧鸡 | 通用 | GNU GPL | 单机 | 决策树、朴素贝叶斯、神经网络、随机森林、AdaBoost、层次聚类等等 |
| Java-ML | 通用 | GNU GPL | 单机 | K-means 聚类、自组织映射、马尔可夫链聚类、蛛网、随机森林、决策树、bagging、距离度量等等 |
| 象夫 | 分类、推荐和聚类 | Apache 2.0 许可证 | 分布式单机 | 逻辑回归、朴素贝叶斯、随机森林、HMM、多层感知器、k 均值聚类等等 |
| 火花 | 通用 | Apache 2.0 许可证 | 分布的 | SVM、逻辑回归、决策树、朴素贝叶斯、k 均值聚类、线性最小二乘法、Lasso、岭回归等等 |
| DL4J | 深度学习 | Apache 2.0 许可证 | 分布式单机 | RBM、深度信念网络、深度自动编码器、递归神经张量网络、卷积神经网络和堆叠去噪自动编码器 |
| 木槌 | 文本挖掘 | 通用公共许可证 1.0 | 单机 | 朴素贝叶斯、决策树、最大熵、HMM 和条件随机场 |
| Encog | 机器学习框架 | Apache 2.0 许可证 | 跨平台 | SVM、神经网络、贝叶斯网络、hmm、遗传编程和遗传算法 |
| 埃尔基 | 数据挖掘 | AGPL | 分布式单机 | 聚类检测、异常检测、评估、索引 |
| 恐鸟 | 机器学习 | GNU GPL | 分布式单机 | 分类、回归、聚类、离群点检测、推荐系统、频繁模式挖掘 |

构建机器学习应用程序

机器学习应用程序,尤其是那些专注于分类的应用程序,通常遵循下图所示的相同高级工作流程。工作流由两个阶段组成—训练分类器和新实例的分类。这两个阶段有共同的步骤,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

首先,我们使用一组训练数据,选择一个有代表性的子集作为训练集,对缺失数据进行预处理,并提取其特征。使用选定的监督学习算法来训练模型,在第二阶段部署该模型。第二阶段使新的数据实例通过相同的预处理和特征提取过程,并应用所学习的模型来获得实例标签。如果您能够收集新的标记数据,请定期重新运行学习阶段来重新训练模型,并在分类阶段用重新训练的模型替换旧的模型。

传统机器学习架构

结构化数据,如交易、客户、分析和市场数据,通常驻留在本地关系数据库中。给定一种查询语言,如 SQL,我们可以查询用于处理的数据,如上图中的工作流所示。通常,所有的数据都可以存储在内存中,并用机器学习库如 Weka、Java-ML 或 MALLET 进行进一步处理。

架构设计中的一个常见做法是创建数据管道,其中工作流中的不同步骤被拆分。例如,为了创建一个客户数据记录,我们可能必须从不同的数据源中删除数据。然后,可以将记录保存在中间数据库中,以供进一步处理。

为了了解大数据架构的高级别方面有何不同,我们先来澄清一下数据何时被视为大数据。

处理大数据

大数据早在这个词被发明之前就存在了。例如,多年来,银行和证券交易所每天处理数十亿笔交易,航空公司拥有全球实时基础设施,用于乘客预订的运营管理,等等。那么,大数据到底是什么?Doug Laney (2001)提出,大数据由三个 v 定义:数量、速度和多样性。因此,要回答你的数据是否庞大的问题,我们可以将此转化为以下三个子问题:

  • :你能把你的数据存在内存里吗?
  • 速度:你能用一台机器处理新的输入数据吗?
  • 多样性:你的数据来源单一吗?

如果您对所有这些问题的回答都是肯定的,那么您的数据可能并不大,您只是简化了您的应用程序架构。

如果你对所有这些问题的答案都是否定的,那么你的数据是巨大的!然而,如果你有混合的答案,那就复杂了。有人可能会说一个 V 很重要;其他人可能会说其他 v 更重要。从机器学习的角度来看,为了处理内存中的数据或来自分布式存储的数据,在算法实现上有根本的区别。因此,一个经验法则是:如果您无法将数据存储在内存中,那么您应该查看大数据机器学习库。

确切的答案取决于你试图解决的问题。如果你正在开始一个新的项目,我建议你从一个单机库和你的算法原型开始,如果整个数据不适合内存,可能用你的数据的一个子集。一旦你建立了良好的初步结果,考虑转移到一些更重的任务,如驯象或火花。

大数据应用架构

文档、博客、社交网络、传感器数据等大数据存储在 NoSQL 数据库(如 MongoDB)或分布式文件系统(如 HDFS)中。如果我们处理结构化数据,我们可以使用构建在 Hadoop 之上的 Cassandra 或 HBase 等系统来部署数据库功能。数据处理遵循 MapReduce 范式,该范式将数据处理问题分解为更小的子问题,并将任务分布在处理节点上。机器学习模型最后用 Mahout、Spark 等机器学习库进行训练。

MongoDB is a NoSQL database, which stores documents in a JSON-like format. You can read more about it at www.mongodb.org. Hadoop is a framework for the distributed processing of large datasets across a cluster of computers. It includes its own filesystem format, HDFS, job scheduling framework, YARD, and implements the MapReduce approach for parallel data processing. We can learn more about Hadoop at hadoop.apache.org/. Cassandra is a distributed database management system that was built to provide fault-tolerant, scalable, and decentralized storage. More information is available at cassandra.apache.org/. HBase is another database that focuses on random read/write access for distributed storage. More information is available at hbase.apache.org/.

摘要

选择机器学习库对你的应用架构有重要影响。关键是要考虑你的项目需求。你有什么样的数据?你想解决什么样的问题?你的数据大吗?您需要分布式存储吗?你打算用什么样的算法?一旦你发现你需要什么来解决你的问题,选择一个最适合你需要的库。

在下一章,我们将介绍如何通过使用一些提供的库来完成基本的机器学习任务,如分类、回归和聚类。****

三、基本算法——分类、回归和聚类

在前一章中,我们回顾了用于机器学习的关键 Java 库以及它们带来了什么。在这一章中,我们将最终弄脏我们的手。我们将进一步了解基本的机器学习任务,如分类、回归和聚类。每个主题将介绍分类、回归和聚类的基本算法。示例数据集将会很小、简单且易于理解。

本章将涵盖以下主题:

  • 加载数据
  • 过滤属性
  • 构建分类、回归和聚类模型
  • 评估模型

开始之前

在开始之前,从www.cs.waikato.ac.nz/ml/weka/downloading.html下载 Weka 的最新稳定版本(在撰写本文时为 Weka 3.8)。

有多种下载选项可供选择。您将希望在源代码中使用 Weka 作为库,因此请确保跳过自解压可执行文件并下载 ZIP 存档,如下面的屏幕截图所示。解压缩归档文件,并在解压缩的归档文件中找到weka.jar:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们将使用 Eclipse IDE 来展示例子;请遵循以下步骤:

  1. 开始一个新的 Java 项目。
  2. 右键单击项目属性,选择 Java 构建路径,单击库选项卡,然后选择添加外部 jar。
  3. 导航至提取 Weka 档案并选择weka.jar文件。

就是这样;我们已经准备好实现基本的机器学习技术了!

分类

我们将从最常用的机器学习技术开始:分类。正如我们在第一章中回顾的,主要思想是自动建立输入变量和结果之间的映射。在接下来的小节中,我们将看看如何加载数据、选择特性、在 Weka 中实现一个基本的分类器,并评估它的性能。

数据

对于这个任务,我们将看一下ZOO数据库。该数据库包含用 18 个属性描述的 101 个动物数据条目,如下表所示:

| 动物 | 水生的 | 散热片 |
| 头发 | 食肉动物 | 腿 |
| 羽毛 | 锯齿状的 | 尾巴 |
| 蛋 | 毅力 | 国内的 |
| 牛奶 | 呼吸 | 猫的大小 |
| 空运的 | 有毒的 | 类型 |

数据集中的一个示例条目是一只狮子,具有以下属性:

  • animal:狮子
  • hair:真
  • feathers:假
  • eggs:假
  • milk:真
  • airborne:假
  • aquatic:假
  • predator:真
  • toothed:真
  • backbone:真
  • breathes:真
  • venomous:假
  • fins:假
  • legs : 4
  • tail:真
  • domestic:假
  • catsize:真
  • type:哺乳动物

我们的任务是建立一个模型来预测结果变量animal,给定所有其他属性作为输入。

加载数据

在开始分析之前,我们将加载 Weka 的属性关系文件格式 ( ARFF )的数据,并打印加载实例的总数。每个数据样本保存在一个DataSource对象中,而完整的数据集,伴随着元信息,由Instances对象处理。

为了加载输入数据,我们将使用接受各种文件格式的DataSource对象,并将它们转换成Instances:

DataSource source = new DataSource("data/zoo.arff"); 
Instances data = source.getDataSet(); 
System.out.println(data.numInstances() + " instances loaded."); 
System.out.println(data.toString()); 

这将提供已加载实例的数量作为输出,如下所示:

101 instances loaded.

我们还可以通过调用data.toString()方法来打印完整的数据集。

我们的任务是学习一个模型,它能够在我们知道其他属性,但不知道animal标签的未来示例中预测animal属性。因此,我们将从训练集中删除animal属性。我们将通过使用Remove()过滤器过滤出动物属性来实现这一点。

首先,我们设置一个参数字符串表,指定必须删除第一个属性。剩余的属性用作训练分类器的数据集:

Remove remove = new Remove(); 
String[] opts = new String[]{ "-R", "1"}; 

最后,我们调用Filter.useFilter(Instances, Filter)静态方法对所选数据集应用过滤器:

remove.setOptions(opts); 
remove.setInputFormat(data); 
data = Filter.useFilter(data, remove); 
System.out.println(data.toString()); 

特征选择

如第一章、应用机器学习快速入门中介绍的,预处理步骤之一集中在特征选择,也称为属性选择。目标是选择将在学习模型中使用的相关属性子集。为什么特征选择很重要?一组较小的属性简化了模型,使用户更容易理解。这通常需要较短的训练,并减少过度拟合。

属性选择可以考虑类值,也可以不考虑。在第一种情况下,属性选择算法评估不同的特征子集,并计算表示所选属性质量的分数。我们可以使用不同的搜索算法,如穷举搜索和最佳优先搜索,以及不同的质量分数,如信息增益、基尼指数等。

Weka 用一个AttributeSelection对象支持这个过程,它需要两个额外的参数:一个计算属性信息量的赋值器,和一个根据赋值器分配的分数对属性进行排序的排序器。

我们将使用以下步骤来执行选择:

  1. 在本例中,我们将使用信息增益作为评估器,并根据信息增益得分对要素进行排名:
InfoGainAttributeEval eval = new InfoGainAttributeEval(); 
Ranker search = new Ranker(); 
  1. 我们将初始化一个AttributeSelection对象,并设置赋值器、排序器和数据:
AttributeSelection attSelect = new AttributeSelection(); 
attSelect.setEvaluator(eval); 
attSelect.setSearch(search); 
attSelect.SelectAttributes(data); 
  1. 我们将打印属性indices的订单列表,如下所示:
int[] indices = attSelect.selectedAttributes(); 
System.out.println(Utils.arrayToString(indices)); 

该过程将提供以下结果作为输出:

12,3,7,2,0,1,8,9,13,4,11,5,15,10,6,14,16 

最能提供信息的属性是12(鳍)3(蛋)7(水生)2(毛发),等等。基于该列表,我们可以移除额外的、非信息性的特征,以便帮助学习算法实现更准确和更快速的学习模型。

什么会最终决定要保留多少属性?没有与确切数字相关的经验法则;属性的数量取决于数据和问题。属性选择的目的是选择更好地服务于你的模型的属性,所以最好把重点放在属性是否在改善模型上。

学习算法

我们已经加载了数据并选择了最佳特征,我们准备学习一些分类模型。让我们从基本的决策树开始。

在 Weka 中,决策树是在J48类中实现的,这是 Quinlan 著名的 C4.5 决策树学习器(Quinlan,1993)的重新实现。

我们将通过以下步骤制作一个决策树:

  1. 我们初始化一个新的J48决策树学习器。我们可以用字符串表传递额外的参数——例如,控制模型复杂性的树修剪(参见第一章、应用机器学习快速入门)。在我们的例子中,我们将构建一棵未修剪的树;因此,我们将传递单个-U参数,如下所示:
J48 tree = new J48(); 
String[] options = new String[1]; 
options[0] = "-U"; 

tree.setOptions(options); 
  1. 我们将调用buildClassifier(Instances)方法来初始化学习过程:
tree.buildClassifier(data); 
  1. 构建的模型现在存储在一个tree对象中。我们可以通过调用toString()方法来提供整个J48未修剪的树:
System.out.println(tree); 

输出如下所示:

    J48 unpruned tree
    ------------------

    feathers = false
    |   milk = false
    |   |   backbone = false
    |   |   |   airborne = false
    |   |   |   |   predator = false
    |   |   |   |   |   legs <= 2: invertebrate (2.0)
    |   |   |   |   |   legs > 2: insect (2.0)
    |   |   |   |   predator = true: invertebrate (8.0)
    |   |   |   airborne = true: insect (6.0)
    |   |   backbone = true
    |   |   |   fins = false
    |   |   |   |   tail = false: amphibian (3.0)
    |   |   |   |   tail = true: reptile (6.0/1.0)
    |   |   |   fins = true: fish (13.0)
    |   milk = true: mammal (41.0)
    feathers = true: bird (20.0)

    Number of Leaves  : 9

    Size of the tree : 17

输出中的树总共有17个节点,其中9个是终端(Leaves)。

展示树的另一种方式是利用内置的TreeVisualizer树查看器,如下所示:

TreeVisualizer tv = new TreeVisualizer(null, tree.graph(), new PlaceNode2()); 
JFrame frame = new javax.swing.JFrame("Tree Visualizer"); 
frame.setSize(800, 500); 
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
frame.getContentPane().add(tv); 
frame.setVisible(true); 
tv.fitToScreen(); 

上述代码会产生以下输出帧:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

决策过程从顶层节点开始,也称为根节点。节点标签指定将被检查的属性值。在我们的例子中,首先,我们检查feathers属性的值。如果羽毛存在,我们跟随右边的分支,这将我们带到标有bird的叶子,表明有20的例子支持这个结果。如果羽毛不存在,我们沿着左边的分支,这将我们带到milk属性。我们再次检查属性值,然后沿着与属性值匹配的分支前进。我们重复这个过程,直到到达一个叶节点。

我们可以按照相同的步骤构建其他分类器:初始化一个分类器,传递控制模型复杂性的参数,并调用buildClassifier(Instances)方法。

在下一节中,您将学习如何使用训练好的模型为标签未知的新示例分配一个类标签。

分类新数据

假设我们记录一种动物的属性,但我们不知道它的标签;我们可以从学习到的分类模型中预测它的标签。我们将在此过程中使用以下动物:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

首先,我们构建描述新样本的特征向量,如下所示:

double[] vals = new double[data.numAttributes()]; 
vals[0] = 1.0; //hair {false, true} 
vals[1] = 0.0;  //feathers {false, true} 
vals[2] = 0.0;  //eggs {false, true} 
vals[3] = 1.0;  //milk {false, true} 
vals[4] = 0.0;  //airborne {false, true} 
vals[5] = 0.0;  //aquatic {false, true} 
vals[6] = 0.0;  //predator {false, true} 
vals[7] = 1.0;  //toothed {false, true} 
vals[8] = 1.0;  //backbone {false, true} 
vals[9] = 1.0;  //breathes {false, true} 
vals[10] = 1.0;  //venomous {false, true} 
vals[11] = 0.0;  //fins {false, true} 
vals[12] = 4.0;  //legs INTEGER [0,9] 
vals[13] = 1.0;  //tail {false, true} 
vals[14] = 1.0;  //domestic {false, true} 
vals[15] = 0.0;  //catsize {false, true} 
DenseInstance myUnicorn = new DenseInstance(1.0, vals);
myUnicorn.setDataset(data); 

然后,我们在模型上调用classify(Instance)方法,以获取类值。方法返回标签索引,如下所示:

double result = tree.classifyInstance(myUnicorn); 
System.out.println(data.classAttribute().value((int) result)); 

这将提供mammal类标签作为输出。

评估和预测误差度量

我们建立了一个模型,但我们不知道它是否可信。为了评估它的性能,我们可以应用一种交叉验证技术,这在第一章、应用机器学习快速入门中有所解释。

Weka 提供了一个Evaluation类来实现交叉验证。我们传递模型、数据、折叠数和初始随机种子,如下所示:

Classifier cl = new J48(); 
Evaluation eval_roc = new Evaluation(data); 
eval_roc.crossValidateModel(cl, data, 10, new Random(1), new Object[] {}); 
System.out.println(eval_roc.toSummaryString()); 

评估结果存储在Evaluation对象中。

通过调用toString()方法,可以调用最常见指标的组合。请注意,输出不会区分回归和分类,因此请务必注意有意义的指标,如下所示:

    Correctly Classified Instances          93               92.0792 %
    Incorrectly Classified Instances         8                7.9208 %
    Kappa statistic                          0.8955
    Mean absolute error                      0.0225
    Root mean squared error                  0.14  
    Relative absolute error                 10.2478 %
    Root relative squared error             42.4398 %
    Coverage of cases (0.95 level)          96.0396 %
    Mean rel. region size (0.95 level)      15.4173 %
    Total Number of Instances              101  

在分类中,我们感兴趣的是正确/错误分类的实例的数量。

混乱矩阵

此外,我们可以通过检查混淆矩阵来检查特定的错误分类发生在哪里。混淆矩阵显示了特定类别值是如何预测的:

double[][] confusionMatrix = eval_roc.confusionMatrix(); 
System.out.println(eval_roc.toMatrixString()); 

由此产生的混淆矩阵如下:

    === Confusion Matrix ===

      a  b  c  d  e  f  g   <-- classified as
     41  0  0  0  0  0  0 |  a = mammal
      0 20  0  0  0  0  0 |  b = bird
      0  0  3  1  0  1  0 |  c = reptile
      0  0  0 13  0  0  0 |  d = fish
      0  0  1  0  3  0  0 |  e = amphibian
      0  0  0  0  0  5  3 |  f = insect
      0  0  0  0  0  2  8 |  g = invertebrate

第一行中的列名对应于由分类节点分配的标签。然后,每个额外的行对应于一个实际的真实类值。例如,第二行对应于带有mammal真实类标签的实例。在栏行中,我们读到所有的哺乳动物都被正确地归类为哺乳动物。在第四行reptiles中,我们注意到三个被正确分类为reptiles,而一个被分类为fish,一个被分类为insect。混淆矩阵让我们深入了解我们的分类模型可能产生的各种错误。

选择分类算法

朴素贝叶斯是机器学习中最简单、高效和有效的归纳算法之一。当特征是独立的时,这在现实世界中很少是真实的,它在理论上是最优的,即使具有依赖的特征,它的性能也是惊人地有竞争力的(张,2004)。主要的缺点是它不能学习特性之间是如何相互作用的;例如,尽管你喜欢加柠檬或牛奶的茶,但你讨厌同时加柠檬或牛奶的茶。

决策树的主要优势在于它是一个易于解释和说明的模型,正如我们在示例中所研究的那样。它既可以处理名义特征,也可以处理数值特征,你不用担心数据是否是线性可分的。

分类算法的一些其他示例如下:

  • weka.classifiers.rules.ZeroR:这预测了多数类,并被视为基线;也就是说,如果您的分类器的性能比平均值预测器差,就不值得考虑它。
  • weka.classifiers.trees.RandomTree:这构建了一个树,考虑了在每个节点随机选择的 K 属性。
  • 这构建了一个随机树的集合(森林),并使用多数投票来分类一个新的实例。
  • weka.classifiers.lazy.IBk:这是 k-最近邻分类器,能够基于交叉验证选择适当的邻居值。
  • 这是一个基于神经网络的分类器,使用反向传播对实例进行分类。网络可以手工构建,或通过算法创建,或两者兼而有之。
  • weka.classifiers.bayes.NaiveBayes:这是一个朴素贝叶斯分类器,它使用估计器类,其中基于对训练数据的分析来选择数字估计器精度值。
  • weka.classifiers.meta.AdaBoostM1:这是使用AdaBoost M1方法提升一个名义类分类器的类。只能解决名义上的阶级问题。这通常会极大地提高性能,但有时会适得其反。
  • weka.classifiers.meta.Bagging:该类用于打包分类器以减少方差。这可以根据基础学习者执行分类和回归。

使用 Encog 分类

在上一节中,您看到了如何使用 Weka 库进行分类。在这一节中,我们将快速了解如何通过使用 Encog 库实现同样的功能。Encog 要求我们建立一个模型来做分类。从 https://github.com/encog/encog-java-core/releases 下载 Encog 库。下载完成后,在 Eclipse 项目中添加.jar文件,如本章开头所述。

对于这个例子,我们将使用iris数据集,它以.csv格式提供;可以从archive.ics.uci.edu/ml/datasets/Iris下载。从下载路径,复制iris.data.csv文件到你的数据目录。这个文件包含了 150 种不同花的数据。它包含了花的四个不同的尺寸,最后一列是标签。

我们现在将使用以下步骤执行分类:

  1. 我们将使用VersatileMLDataSet方法加载文件并定义所有四列。下一步是调用analyze方法,该方法将读取整个文件并找到统计参数,比如平均值、标准偏差等等:
File irisFile = new File("data/iris.data.csv");
VersatileDataSource source = new CSVDataSource(irisFile, false, CSVFormat.DECIMAL_POINT);

VersatileMLDataSet data = new VersatileMLDataSet(source); 
data.defineSourceColumn("sepal-length", 0, ColumnType.continuous); 
data.defineSourceColumn("sepal-width", 1, ColumnType.continuous); 
data.defineSourceColumn("petal-length", 2, ColumnType.continuous); 
data.defineSourceColumn("petal-width", 3, ColumnType.continuous); 

ColumnDefinition outputColumn = data.defineSourceColumn("species", 4, ColumnType.nominal);
data.analyze(); 
  1. 下一步是定义输出列。然后,是时候对数据进行归一化处理了;但在此之前,我们需要决定数据将被规范化的模型类型,如下所示:
data.defineSingleOutputOthersInput(outputColumn); 

EncogModel model = new EncogModel(data); 
model.selectMethod(data, MLMethodFactory.TYPE_FEEDFORWARD);

model.setReport(new ConsoleStatusReportable()); 
data.normalize(); 
  1. 下一步是在训练集上拟合模型,留出测试集。我们将持有 30%的数据,如第一个参数0.3所指定的;下一个参数指定我们想要随机地将数据放入。1001表示有一个种子值 1001,所以我们使用一个holdBackValidation模型:
model.holdBackValidation(0.3, true, 1001);
  1. 现在,是时候根据测量值和标签来训练模型并对数据进行分类了。交叉验证将训练数据集分成五种不同的组合:
model.selectTrainingType(data); 
MLRegression bestMethod = (MLRegression)model.crossvalidate(5, true); 
  1. 下一步是显示每次折叠的结果和错误:
System.out.println( "Training error: " + EncogUtility.calculateRegressionError(bestMethod, model.getTrainingDataset())); 
System.out.println( "Validation error: " + EncogUtility.calculateRegressionError(bestMethod, model.getValidationDataset())); 
  1. 现在,我们将开始使用模型来预测值,使用以下代码块:
while(csv.next()) { 
            StringBuilder result = new StringBuilder(); 
            line[0] = csv.get(0); 
            line[1] = csv.get(1); 
            line[2] = csv.get(2); 
            line[3] = csv.get(3); 
            String correct = csv.get(4); 
            helper.normalizeInputVector(line,input.getData(),false); 
            MLData output = bestMethod.compute(input); 
            String irisChosen = helper.denormalizeOutputVectorToString(output)[0]; 

            result.append(Arrays.toString(line)); 
            result.append(" -> predicted: "); 
            result.append(irisChosen); 
            result.append("(correct: "); 
            result.append(correct); 
            result.append(")"); 

            System.out.println(result.toString()); 
        } 

这将产生类似如下的输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Encog 在MLMethodFactory中支持许多其他选项,比如 SVM、PNN 等等。

使用大量在线分析进行分类

海量在线分析 ( MOA ),如第二章、*用于机器学习的 Java 库和平台所讨论的,*是另一个可以用来实现分类的库。它主要被设计成与流一起工作。如果它与流一起工作,大量的数据将会在那里;那么,我们如何评价这个模型呢?在传统的批量学习模式中,我们通常将数据分为训练集和测试集,如果数据有限,则首选交叉验证。在流处理中,数据似乎是无限的,交叉验证被证明是昂贵的。我们可以使用的两种方法如下:

  • Holdout :当数据已经被分为两部分时,这是很有用的,这是预先定义的。它给出当前分类器的估计,如果它与当前数据相似的话。很难保证维持集和当前数据之间的相似性。
  • 先测试后训练,或先训练后训练:在这种方法中,模型在用于训练之前,先在示例上进行测试。因此,模型总是被测试它从未见过的数据。在这种情况下,不需要维持方案。它使用可用的数据。随着时间的推移,这种方法将提高分类的准确性。

MOA 提供了多种生成数据流的方法。首先,从 https://moa.cms.waikato.ac.nz/downloads/的下载恐鸟库。将下载的.jar文件添加到 Eclipse,就像我们在本章开始时为 Weka 所做的那样。我们将使用 MOA 提供的 GUI 工具来了解如何使用 MOA 处理流。要启动 GUI,确保moa.jarsizeofag.jar在当前路径中;然后,在命令提示符下运行以下命令:

$ java -cp moa.jar -javaagent:sizeofag.jar moa.gui.GUI

它将显示以下输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到它有分类、回归、聚类、异常值等选项。单击配置按钮将显示用于制作分类器的屏幕。它提供了各种学习者和流,如下面的屏幕截图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面是用NaiveBayesHoeffdingTree运行RandomTreeGenerator的例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

估价

在开发出模型之后,评估是下一个重要的任务。它让您决定模型是否在给定的数据集上运行良好,并确保它能够处理它从未见过的数据。评估框架主要使用以下功能:

  • 误差估计:使用维持或交错测试训练方法来估计误差。还使用了 k 倍交叉验证。
  • 性能测量:使用 Kappa 统计量,它对流式分类器更敏感。
  • 统计验证:在比较评估分类器时,一定要看随机和非随机实验的差异。McNemar 检验是流中最流行的检验,用于评估两个分类器之间差异的统计显著性。如果我们使用一个分类器,参数估计的置信区间表示可靠性。
  • 流程的成本衡量:由于我们正在处理流数据,这可能需要访问第三方或基于云的解决方案来获取和处理数据,因此每小时的使用和内存成本将被视为评估目的。

基线分类

批量学习已经导致了许多不同范式的分类器的发展,例如分而治之、懒惰学习器、内核方法、图形模型等等。现在,如果我们转移到流中,我们需要了解如何使它们对于流中的大型数据集是增量的和快速的。我们必须考虑模型的复杂性和模型更新的速度,这是需要考虑的主要权衡因素。

多数类算法是最简单的分类器之一,它被用作基线。它也用作决策树叶子的默认分类器。另一个是 - 变化分类器,它预测新实例的标签。朴素贝叶斯算法以其在计算能力和简单性方面的低成本而闻名。这是一个增量算法,最适合流。

决策图表

决策树是一种非常流行的分类器技术,使得解释和可视化模型变得容易。它以树木为基础。它基于属性值划分或分割节点,并且树的叶子通常落在多数类分类器上。在流数据中,Hoeffding 树是一种非常快速的决策树算法;它等待新的实例,而不是重用实例。它为大数据建立了一棵树。概念-适应非常快的决策树 ( CVFDT )处理漂移的概念,在滑动窗口中保持模型与实例的一致性。其他的树是超快速森林树 ( UFFT )、Hoeffding 自适应树、穷举二叉树等等。

懒惰的学习

在流式上下文中, k 近邻()是最方便的批处理方法。滑动窗口用于确定尚未分类的新实例的 KNN。它通常使用滑动窗口的 1000 个最新实例。当滑动窗口滑动时,它也处理概念漂移。

**

主动学习

我们都知道分类器对带标签的数据工作得很好,但是对于流数据并不总是这样。例如,来自流的数据可能是未标记的。标记数据的成本很高,因为它需要人工干预来标记未标记的数据。我们知道数据流会产生大量数据。主动学习算法只对选择性数据进行标记。要标记的数据由适合基于池的设置的历史数据决定。需要定期进行再培训,以决定传入实例是否需要标签。标记数据的一个简单策略是使用随机策略。它也被称为基线策略,它要求为每个传入的实例添加一个标签,并给出标签预算的概率。另一个策略是为当前分类器最不确定的实例请求一个标签。这可能工作得很好,但很快,分类器将耗尽其预算或达到其阈值。

回归

我们将通过对能效数据集的分析来探索基本的回归算法(Tsanas 和 Xifara,2012)。我们将根据建筑的构造特征(如表面、墙壁和屋顶面积)调查建筑的热负荷和冷负荷要求;身高;玻璃区域;和紧凑性。研究人员使用模拟器设计了 12 种不同的房屋结构,同时改变了 18 种建筑特征。总共模拟了 768 座不同的建筑。

我们的第一个目标是系统地分析每个建筑特征对目标变量(即热负荷或冷负荷)的影响。第二个目标是比较经典线性回归模型与其他方法(如 SVM 回归、随机森林和神经网络)的性能。对于这个任务,我们将使用 Weka 库。

加载数据

archive.ics.uci.edu/ml/datasets/Energy+efficiency下载能效数据集。

数据集是 Excel 的 XLSX 格式,Weka 无法读取。我们可以通过点击文件|另存为,在保存对话框中勾选.csv,将其转换为逗号分隔值 ( CSV )格式,如下图截图所示。确认仅保存活动工作表(因为所有其他工作表都是空的),确认继续,将丢失一些格式设置功能。现在,该文件已准备好由 Weka 加载:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在文本编辑器中打开文件,检查文件是否被正确转换。可能有些小问题会引起问题。例如,在我的导出中,每一行都以双分号结束,如下所示:

X1;X2;X3;X4;X5;X6;X7;X8;Y1;Y2;; 
0,98;514,50;294,00;110,25;7,00;2;0,00;0;15,55;21,33;; 
0,98;514,50;294,00;110,25;7,00;3;0,00;0;15,55;21,33;; 

要删除重复的分号,可以使用查找和替换功能:查找;;并用;替换它。

第二个问题是我的文件在文档末尾有一长串空行,可以删除,如下所示:

0,62;808,50;367,50;220,50;3,50;5;0,40;5;16,64;16,03;; 
;;;;;;;;;;; 
;;;;;;;;;;; 

现在,我们准备加载数据。让我们打开一个新文件,并使用 Weka 的转换器编写一个简单的数据导入函数来读取 CSV 格式的文件,如下所示:

import weka.core.Instances; 
import weka.core.converters.CSVLoader; 
import java.io.File; 
import java.io.IOException; 

public class EnergyLoad { 

  public static void main(String[] args) throws IOException { 

    // load CSV 
    CSVLoader loader = new CSVLoader();
    loader.setFieldSeparator(","); 
    loader.setSource(new File("data/ENB2012_data.csv")); 
    Instances data = loader.getDataSet(); 

    System.out.println(data); 
  } 
} 

数据加载完毕!我们继续吧。

分析属性

在我们分析属性之前,让我们试着理解我们在处理什么。总共有八个描述建筑特征的属性,还有两个目标变量,即热负荷和冷负荷,如下表所示:

| 属性 | 属性名 |
| X1 | 相对紧性 |
| X2 | 表面面积 |
| X3 | 墙壁面积 |
| X4 | 屋顶面积 |
| X5 | 总高 |
| X6 | 方向 |
| X7 | 玻璃区域 |
| X8 | 玻璃面积分布 |
| Y1 | 供热量 |
| Y2 | 冷负荷 |

构建和评估回归模型

我们将通过在要素位置设置类属性来开始学习热负荷模型:

data.setClassIndex(data.numAttributes() - 2); 

现在可以删除第二个目标变量,即冷负荷:

//remove last attribute Y2 
Remove remove = new Remove(); 
remove.setOptions(new String[]{"-R", data.numAttributes()+""}); 
remove.setInputFormat(data);
data = Filter.useFilter(data, remove); 

线性回归

我们将从一个基本的线性回归模型开始,用LinearRegression类实现。与分类示例类似,我们将初始化一个新的模型实例,传递参数和数据,并调用buildClassifier(Instances)方法,如下所示:

import weka.classifiers.functions.LinearRegression; 
... 
data.setClassIndex(data.numAttributes() - 2);
LinearRegression model = new LinearRegression(); 
model.buildClassifier(data); 
System.out.println(model);

存储在对象中的学习模型可以通过调用toString()方法来提供,如下所示:

    Y1 =

        -64.774  * X1 +
         -0.0428 * X2 +
          0.0163 * X3 +
         -0.089  * X4 +
          4.1699 * X5 +
         19.9327 * X7 +
          0.2038 * X8 +
         83.9329

线性回归模型构建了一个函数,该函数线性组合输入变量来估计热负荷。特征前面的数字说明了该特征对目标变量的影响:符号对应的是正面/负面影响,幅度对应的是其显著性。例如,特征X1的相对紧密度与热负荷呈负相关,而玻璃面积呈正相关。这两个特征也显著影响最终的热负荷估计。该模型的性能同样可以用交叉验证技术进行评估。

十重交叉验证如下:

Evaluation eval = new Evaluation(data); 
eval.crossValidateModel(model, data, 10, new Random(1), new String[]{}); 
System.out.println(eval.toSummaryString()); 

我们可以提供常用的评估指标,包括相关性、平均绝对误差、相对绝对误差等,作为输出,如下所示:

Correlation coefficient                  0.956  
Mean absolute error                      2.0923 
Root mean squared error                  2.9569 
Relative absolute error                 22.8555 % 
Root relative squared error             29.282  % 
Total Number of Instances              768      

使用 Encog 进行线性回归

现在,我们将快速查看如何使用 Encog 来制作回归模型。我们将使用我们在上一节中使用的数据集,加载数据。以下步骤显示了如何制作模型:

  1. 为了加载数据,我们将使用VersatileMLDataSet函数,如下所示:
File datafile = new File("data/ENB2012_data.csv");
VersatileDataSource source = new CSVDataSource(datafile, true, CSVFormat.DECIMAL_POINT);
VersatileMLDataSet data = new VersatileMLDataSet(source); 
data.defineSourceColumn("X1", 0, ColumnType.continuous); 
data.defineSourceColumn("X2", 1, ColumnType.continuous); 
data.defineSourceColumn("X3", 2, ColumnType.continuous); 
data.defineSourceColumn("X4", 3, ColumnType.continuous);
data.defineSourceColumn("X5", 4, ColumnType.continuous);
data.defineSourceColumn("X6", 5, ColumnType.continuous);
data.defineSourceColumn("X7", 6, ColumnType.continuous);
data.defineSourceColumn("X8", 7, ColumnType.continuous);
  1. 由于我们有两个输出,Y1Y2,它们可以通过使用defineMultipleOutputsOthersInput函数相加,如下所示:
ColumnDefinition outputColumn1 = data.defineSourceColumn("Y1", 8,    ColumnType.continuous);
ColumnDefinition outputColumn2 = data.defineSourceColumn("Y2", 9,  ColumnType.continuous);
ColumnDefinition outputscol [] = {outputColumn1, outputColumn2};
data.analyze();

data.defineMultipleOutputsOthersInput(outputscol);
  1. 下一步是通过使用FEEDFORWARD实例开发一个简单的回归模型:
EncogModel model = new EncogModel(data); 
model.selectMethod(data, MLMethodFactory.TYPE_FEEDFORWARD);
model.setReport(new ConsoleStatusReportable());

data.normalize();
model.holdBackValidation(0.3, true, 1001);
model.selectTrainingType(data);
MLRegression bestMethod = (MLRegression)model.crossvalidate(5, true);            
NormalizationHelper helper = data.getNormHelper(); 

System.out.println(helper.toString()); 
System.out.println("Final model: " + bestMethod); 

现在,我们的回归模型准备好了。下面的屏幕截图给出了输出的最后几行:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 MOA 进行回归

使用 MOA 进行回归需要我们使用 GUI。可以从www . cs . waikato . AC . NZ/~ Bernhard/Halifax 17/census . ARFF . gz下载数据集。

以下步骤显示了如何执行回归:

  1. 使用以下命令启动 MOA GUI:
$ java -cp moa.jar -javaagent:sizeofag-1.0.4.jar moa.gui.GUI
  1. 选择回归选项卡并单击配置,如下面的屏幕截图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 我们将使用下载的.arff文件进行回归。当我们在前面的步骤中单击“配置”时,将显示“配置任务”窗口,如下面的屏幕截图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 在流选项中,单击编辑并选择 ArffFileStream 选择我们下载的.arff文件,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 在 classIndex 中,指定-1,它将第一个属性设置为目标。在所有弹出窗口中单击确定,然后单击运行。这需要一些时间,因为人口普查文件有大量数据要处理,如下面的屏幕截图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

回归树

另一种方法是构建一组回归模型,每个模型都有自己的数据部分。下图显示了回归模型和回归树之间的主要区别。回归模型构建了最适合所有数据的单一模型。另一方面,回归树构建了一组回归模型,每个模型对数据的一部分进行建模,如右侧所示。与回归模型相比,回归树可以更好地拟合数据,但该函数是一个分段线性图,在建模区域之间有跳跃,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Weka 中的回归树是在M5类中实现的。模型构建遵循相同的范例:初始化模型,传递参数和数据,并调用buildClassifier(Instances)方法,如下所示:

import weka.classifiers.trees.M5P; 
... 
M5P md5 = new M5P(); 
md5.setOptions(new String[]{""}); 
md5.buildClassifier(data);  
System.out.println(md5); 

归纳模型是在叶节点中具有等式的树,如下所示:

    M5 pruned model tree:
    (using smoothed linear models)

    X1 <= 0.75 : 
    |   X7 <= 0.175 : 
    |   |   X1 <= 0.65 : LM1 (48/12.841%)
    |   |   X1 >  0.65 : LM2 (96/3.201%)
    |   X7 >  0.175 : 
    |   |   X1 <= 0.65 : LM3 (80/3.652%)
    |   |   X1 >  0.65 : LM4 (160/3.502%)
    X1 >  0.75 : 
    |   X1 <= 0.805 : LM5 (128/13.302%)
    |   X1 >  0.805 : 
    |   |   X7 <= 0.175 : 
    |   |   |   X8 <= 1.5 : LM6 (32/20.992%)
    |   |   |   X8 >  1.5 : 
    |   |   |   |   X1 <= 0.94 : LM7 (48/5.693%)
    |   |   |   |   X1 >  0.94 : LM8 (16/1.119%)
    |   |   X7 >  0.175 : 
    |   |   |   X1 <= 0.84 : 
    |   |   |   |   X7 <= 0.325 : LM9 (20/5.451%)
    |   |   |   |   X7 >  0.325 : LM10 (20/5.632%)
    |   |   |   X1 >  0.84 : 
    |   |   |   |   X7 <= 0.325 : LM11 (60/4.548%)
    |   |   |   |   X7 >  0.325 : 
    |   |   |   |   |   X3 <= 306.25 : LM12 (40/4.504%)
    |   |   |   |   |   X3 >  306.25 : LM13 (20/6.934%)

    LM num: 1
    Y1 = 
      72.2602 * X1 
      + 0.0053 * X3 
      + 11.1924 * X7 
      + 0.429 * X8 
      - 36.2224

    ...

    LM num: 13
    Y1 = 
      5.8829 * X1 
      + 0.0761 * X3 
      + 9.5464 * X7 
      - 0.0805 * X8 
      + 2.1492

    Number of Rules : 13

树有13片叶子,每片叶子对应一个线性方程。下图显示了上述输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

该树可以类似于分类树来阅读。最重要的特性在树的顶部。终端节点(叶节点)包含一个线性回归模型,解释到达树的这一部分的数据。

评估将提供以下结果作为输出:

    Correlation coefficient                  0.9943
    Mean absolute error                      0.7446
    Root mean squared error                  1.0804
    Relative absolute error                  8.1342 %
    Root relative squared error             10.6995 %
    Total Number of Instances              768     

避免常见回归问题的技巧

首先,我们必须使用先前的研究和领域知识来确定哪些特性要包含在回归中。查阅文献、报告和以前的研究,了解什么样的功能起作用,以及为您的问题建模的一些合理变量。假设您有一个包含随机数据的大型要素集;很有可能几个特征将与目标变量相关联(即使数据是随机的)。

为了避免过度拟合,我们必须保持模型简单。奥卡姆剃刀原则指出,你应该选择一个模型,最好地解释你的数据,用最少的假设。实际上,该模型可以简单到只有两到四个预测特征。

使聚集

与监督分类器相比,聚类的目标是识别一组未标记数据中的内在组。它可以用于识别同类组的代表性示例,找到有用和合适的分组,或者找到异常的示例,如异常值。

我们将通过分析一个银行数据集来演示如何实现聚类。该数据集由 11 个属性组成,描述了 600 个实例,包括年龄、性别、地区、收入、婚姻状况、子女、汽车拥有状况、储蓄活动、当前活动、抵押贷款状况和 PEP。在我们的分析中,我们将尝试通过应用期望最大化 ( EM )聚类来识别常见的客户群。

EM 的工作方式如下:给定一组聚类,EM 首先为每个实例分配属于特定聚类的概率分布。例如,如果我们从三个集群(即 A、B 和 C)开始,一个实例可能得到概率分布 0.70、0.10 和 0.20,分别属于 A、B 和 C 集群。第二步,EM 重新估计每类概率分布的参数向量。该算法迭代这两个步骤,直到参数收敛或达到最大迭代次数。

EM 中使用的聚类数可以手动设置,也可以通过交叉验证自动设置。确定数据集中聚类数量的另一种方法包括肘方法。这种方法着眼于用特定数量的分类解释的方差百分比。该方法建议增加聚类的数量,直到附加的聚类不会添加太多信息,也就是说,它解释了很少的附加变化。

聚类算法

构建聚类模型的过程与构建分类模型的过程非常相似,即加载数据并构建模型。聚类算法在weka.clusterers包中实现,如下所示:

import java.io.BufferedReader; 
import java.io.FileReader; 

import weka.core.Instances; 
import weka.clusterers.EM; 

public class Clustering { 

  public static void main(String args[]) throws Exception{ 

    //load data 
    Instances data = new Instances(new BufferedReader
       (new FileReader("data/bank-data.arff"))); 

    // new instance of clusterer 
    EM model = new EM(); 
    // build the clusterer 
    model.buildClusterer(data); 
    System.out.println(model); 

  } 
} 

该模型确定了以下六个集群:

    EM
    ==

    Number of clusters selected by cross validation: 6

                     Cluster
    Attribute              0        1        2        3        4        5
                       (0.1)   (0.13)   (0.26)   (0.25)   (0.12)   (0.14)
    ======================================================================
    age
      0_34            10.0535  51.8472 122.2815  12.6207   3.1023   1.0948
      35_51           38.6282  24.4056  29.6252  89.4447  34.5208   3.3755
      52_max          13.4293    6.693   6.3459  50.8984   37.861  81.7724
      [total]         62.1111  82.9457 158.2526 152.9638  75.4841  86.2428
    sex
      FEMALE          27.1812  32.2338  77.9304  83.5129  40.3199  44.8218
      MALE            33.9299  49.7119  79.3222  68.4509  34.1642   40.421
      [total]         61.1111  81.9457 157.2526 151.9638  74.4841  85.2428
    region
      INNER_CITY      26.1651  46.7431   73.874  60.1973  33.3759  34.6445
      TOWN            24.6991  13.0716  48.4446  53.1731   21.617  17.9946
    ...

该表如下所示:第一行表示六个分类,而第一列显示属性及其范围。例如,属性age被分成三个范围:0-3435-5152-max。左侧的列指示每个群集中有多少实例属于特定范围;例如,0-34年龄组中的客户主要在聚类 2 中(122 个实例)。

估价

聚类算法的质量可以通过使用logLikelihood度量来估计,该度量测量所识别的聚类的一致性。数据集被拆分成多个文件夹,并对每个文件夹运行聚类。这样做的动机是,如果聚类算法为没有用于拟合参数的相似数据分配了很高的概率,那么它可能在捕获数据结构方面做得很好。Weka 提供了CluterEvaluation类来估计它,如下所示:

double logLikelihood = ClusterEvaluation.crossValidateModel(model, data, 10, new Random(1));
System.out.println(logLikelihood);  

它提供以下输出:

-8.773410259774291 

使用 Encog 进行聚类

Encog 支持 k 均值聚类。让我们考虑一个非常简单的例子,数据显示在下面的代码块中:

DATA = { { 28, 15, 22 }, { 16, 15, 32 }, { 32, 20, 44 }, { 1, 2, 3 }, { 3, 2, 1 } };

为了从该数据生成BasicMLDataSet,使用了一个简单的for循环,它将数据添加到数据集:

BasicMLDataSet set = new BasicMLDataSet();

for (final double[] element : DATA) {
    set.add(new BasicMLData(element));
}

使用KMeansClustering函数,让我们将数据集分成两个集群,如下所示:

KMeansClustering kmeans = new KMeansClustering(2, set);

kmeans.iteration(100);

// Display the cluster
int i = 1;
for (MLCluster cluster : kmeans.getClusters()) {
    System.out.println("*** Cluster " + (i++) + " ***");
    final MLDataSet ds = cluster.createDataSet();
    final MLDataPair pair = BasicMLDataPair.createPair(ds.getInputSize(), ds.getIdealSize());
    for (int j = 0; j < ds.getRecordCount(); j++) {
        ds.getRecord(j, pair);
        System.out.println(Arrays.toString(pair.getInputArray()));
        }
    }

这将生成以下输出:

*** Cluster 1 ***
[16.0, 15.0, 32.0]
[1.0, 2.0, 3.0]
[3.0, 2.0, 1.0]
*** Cluster 2 ***
[28.0, 15.0, 22.0]
*** Cluster 3 ***
[32.0, 20.0, 44.0]

使用 ELKI 进行聚类

ELKI 支持许多聚类算法。下面列出了一些例子:

  • 仿射传播聚类算法:这是一个使用仿射传播的聚类分析。
  • DBSCAN :这是一种基于密度的聚类,尤其适用于有噪声的应用;它根据密度在数据库中查找集合。
  • EM :该算法基于期望最大化算法创建聚类。
  • AGNES : **层次凝聚聚类(HAC),凝聚嵌套(AGNES),**是一种经典的层次聚类算法。
  • SLINK :这是单链路算法。
  • 叮当:用于完全联动。
  • HDBSCAN :这是一个抽取集群层次。

此外,KMeansSort、KMeansCompare、KMedianLloyd、KMediodsEM、KMeansBisecting 等等都是 KMean 家族中的一些例子。

elki-project.github.io/algorithms/可以找到聚类算法的详细列表,包括 ELKI 支持的所有算法。

我们需要从elki-project.github.io/releases/那里得到所需的.jar文件。下载可执行文件,从elki-project.github.io/datasets/下载鼠标数据集。

在终端或命令提示符下,运行以下命令:

$ java -jar elki-bundle-0.7.1.jar 

上述命令会生成以下输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到橙色的两个选项:dbc.inalgorithm。我们需要指定值。在dbc.in中,点击圆点(...,选择我们下载的mouse.csv文件。在algorithm中,点击加号(+)选择k-Mean Clustering algorithm,找到kmean.k,填入数值3。单击“运行任务”按钮,该按钮现已启用。它将生成以下输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

摘要

在本章中,您学习了如何使用 Weka 实现基本的机器学习任务:分类、回归和聚类。我们简要讨论了属性选择过程和训练模型,并评估了它们的性能。

下一章将关注如何应用这些技术来解决现实生活中的问题,比如客户保持。**

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值