原文:
annas-archive.org/md5/cee4ba49129fb804cd87ad198b9c8127
译者:飞龙
前言
神经网络是解决复杂计算问题的最具吸引力的机器学习模型之一,具有高效性。神经网络被广泛应用于人工智能和机器学习的不同领域,以解决各种问题。
本书解释了神经网络的细分领域,并为你提供了开始深入学习高级主题的基础。书中首先介绍了使用neuralnet
包进行神经网络设计;然后,你将构建扎实的知识,了解神经网络如何从数据中学习及其背后的原理。本书涵盖了多种类型的神经网络,包括递归神经网络和卷积神经网络。你不仅将学习如何训练神经网络,还将探索这些网络的泛化。随后,我们将深入探讨如何结合不同的神经网络模型,并结合实际案例进行工作。
到本书结束时,你将学习如何在应用中实现神经网络模型,并通过书中的实践示例来帮助你。
本书涵盖的内容
第一章,神经网络与人工智能概念,介绍了人工神经网络(ANN)和人工智能(AI)的基本理论概念。它展示了 ANN 和 AI 的简单应用,并利用数学概念进行阐释。同时也涉及了一些 R 中 ANN 函数的介绍。
第二章,神经网络中的学习过程,展示了如何在图形模型中进行精确推理,并将应用展示为专家系统。推理算法是学习和使用这些类型模型的基础组件。读者必须至少理解它们的使用方式,并了解它们的工作原理。
第三章,使用多层神经网络进行深度学习,是关于理解深度学习和神经网络在深度学习中的应用。本章详细介绍了使用 R 包的实现过程,涵盖了深度学习中设置的多个隐藏层,并使用实际数据集帮助理解该实现。
第四章,感知器神经网络——基本模型,帮助理解什么是感知器以及可以用它构建的应用程序。本章介绍了使用 R 实现感知器的过程。
第五章,在 R 中训练和可视化神经网络,展示了使用数据集训练神经网络的另一个示例。它还通过使用 R 中的plot()
函数,提供了输入层、隐藏层和输出层的图形表示,帮助更好地理解神经网络。
第六章,递归神经网络和卷积神经网络,介绍了递归神经网络(RNN)和卷积神经网络(CNN)以及它们在 R 中的实现。提出了多个示例以帮助理解基本概念。
第七章,神经网络的应用案例—高级话题,展示了来自不同领域的神经网络应用,以及神经网络如何在人工智能领域中使用。这将帮助读者理解神经网络算法的实际应用。读者还可以通过使用不同的数据集并运行 R 代码进一步提升自己的技能。
本书所需内容
本书专注于 R 环境中的神经网络。我们使用了 R 版本 3.4.1 来构建各种应用,并使用了 R 的开源及企业级专业软件 RStudio 版本 1.0.153。我们重点介绍如何以最佳方式利用各种 R 库来构建实际应用。为此,我们尽力保持所有代码简洁易读。我们认为,这将使读者能够轻松理解代码,并在不同场景中方便地使用它。
本书的目标读者
本书适用于具有统计学背景、熟悉 R 语言并希望通过神经网络从复杂数据中获得更好结果的读者。如果您对人工智能和深度学习感兴趣并希望提升技能,那么这本书正是您需要的!
约定
本书中,您将看到多种文本样式,用于区分不同类型的信息。以下是这些样式的一些示例及其含义的解释。
文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 账户名均如下所示:“R 中的这一行包含了neuralnet()
库。”
任何命令行输入或输出均按如下方式编写:
mydata=read.csv('Squares.csv',sep=",",header=TRUE)
mydata
attach(mydata)
names(mydata)
新术语和重要单词以粗体显示。您在屏幕上看到的词语,例如在菜单或对话框中出现的词语,会以以下方式出现在文本中:“帮助浏览器中的参考页面”。
警告或重要提示会显示在类似这样的框中。
提示和技巧会以这种方式出现。
读者反馈
我们始终欢迎读者反馈。请告诉我们您对本书的看法——您喜欢或不喜欢的部分。读者的反馈对我们非常重要,因为它帮助我们开发出您能真正从中受益的书籍。
要向我们提供一般反馈,只需发送电子邮件至feedback@packtpub.com
,并在邮件主题中提及书名。
如果您在某个主题上有专长,并且有兴趣编写或参与编写书籍,请查看我们的作者指南,网址为www.packtpub.com/authors。
客户支持
现在,您是一本 Packt 书籍的骄傲拥有者,我们为您准备了一些资源,帮助您最大化地利用您的购买。
下载示例代码
您可以从您的账户中下载此书的示例代码文件,网址是www.packtpub.com
。如果您从其他地方购买了此书,可以访问www.packtpub.com/support
并注册,以便将文件直接通过电子邮件发送给您。您可以按照以下步骤下载代码文件:
-
使用您的电子邮件地址和密码登录或注册我们的网站。
-
将鼠标指针悬停在顶部的“SUPPORT”标签上。
-
点击“代码下载与勘误”。
-
在搜索框中输入书名。
-
选择您要下载代码文件的书籍。
-
从下拉菜单中选择您购买此书的来源。
-
点击“代码下载”。
文件下载完成后,请确保使用以下最新版本的工具解压文件夹:
-
WinRAR / 7-Zip for Windows
-
Zipeg / iZip / UnRarX for Mac
-
7-Zip / PeaZip for Linux
本书的代码包也托管在 GitHub 上,网址是github.com/PacktPublishing/Neural-Networks-with-R
。我们还提供其他书籍和视频的代码包,您可以在github.com/PacktPublishing/
查看。快去看看吧!
勘误
尽管我们已尽力确保内容的准确性,但难免会出现错误。如果您在我们的书籍中发现错误——可能是文本或代码中的错误——我们将不胜感激,如果您能将其报告给我们。这样,您可以帮助其他读者避免困扰,并帮助我们改进此书的后续版本。如果您发现任何勘误,请访问www.packtpub.com/submit-errata
报告,选择您的书籍,点击“勘误提交表单”链接,并输入勘误的详细信息。一旦您的勘误得到验证,您的提交将被接受,勘误将被上传到我们的网站,或添加到该书籍勘误列表的勘误部分。要查看已提交的勘误,请访问www.packtpub.com/books/content/support
,并在搜索框中输入书名。所需信息将显示在勘误部分。
盗版
网络上的版权材料盗版问题在所有媒体中都是一个持续存在的问题。在 Packt,我们非常重视版权和许可的保护。如果你在互联网上遇到任何形式的我们作品的非法复制,请立即提供其网址或网站名称,以便我们采取措施。请通过copyright@packtpub.com
与我们联系,并附上涉嫌盗版材料的链接。感谢你帮助我们保护作者的权益,以及我们为你带来有价值内容的能力。
问题
如果你在本书的任何方面遇到问题,可以通过questions@packtpub.com
联系我们,我们将尽力解决问题。
第一章:神经网络与人工智能概念
通过几百年来的科学与哲学研究,已经识别出一些特殊的机制,它们构成人类智能的基础。受其运作的启发,人类成功创造出了部分模仿这些机制的机器。问题在于它们尚未能成功地模仿并整合所有这些机制,因此我们现有的人工智能(AI)系统在很大程度上是不完整的。
这种机器改进的决定性一步来自所谓的人工神经网络(ANNs)的使用,这些网络从调节自然神经网络的机制出发,计划模拟人类思维。现在,软件可以模仿赢得国际象棋比赛或将文本翻译成另一种语言的机制,并遵循其语法规则。
本章介绍了 ANN 和 AI 的基本理论概念。预期您对以下内容有基础理解:
-
基础的高中数学;微分学和如 sigmoid 等函数
-
R 编程及 R 库的使用
我们将介绍神经网络的基础,并使用 R 尝试一个模型。本章是神经网络的基础,所有后续章节都将基于此。
本章将涵盖以下主题:
-
ANN 概念
-
神经元、感知器和多层神经网络
-
偏差、权重、激活函数和隐藏层
-
前向传播和反向传播方法
-
图形处理单元(GPU)的简要概述
在本章结束时,您将能够识别 R 提供的不同神经网络算法和工具,以便处理它们。
介绍
大脑是人体最重要的器官,是我们进行所有功能处理的中央处理单元。它仅重 1.5 公斤,却有约 860 亿个神经元。神经元被定义为传递神经冲动或电化学信号的细胞。大脑是一个复杂的神经网络,通过一系列相互连接的神经元处理信息。理解大脑功能一直是一个挑战;然而,随着计算技术的进步,我们现在可以人工编程神经网络。
人工神经网络(ANN)的学科源自模仿人类大脑功能的思想,这正是试图解决问题的地方。传统方法及其随后的应用在明确的技术环境中得到了克服。
人工智能或机器智能是一个研究领域,旨在赋予计算机认知能力,使其能够进行学习和解决问题的编程。其目标是模拟具有类似人类智能的计算机。人工智能无法完全模仿人类智能;计算机只能被编程去执行人类大脑的某些方面。
机器学习是人工智能(AI)的一个分支,帮助计算机根据输入数据自我编程。机器学习赋予人工智能基于数据进行问题解决的能力。人工神经网络(ANNs)是机器学习算法的一个例子。
深度学习(DL)是一种复杂的神经网络集合,具有更多的处理层,能够发展出更高水平的抽象。它们通常用于复杂的任务,如图像识别、图像分类和手写识别。
大多数观众认为神经网络难以学习,并把它当作一个“黑箱”来使用。本书的目的是打开这个“黑箱”,帮助读者通过 R 语言的实现来学习神经网络的内部工作原理。通过工作知识,我们可以看到神经网络在以下图示中展示的许多应用场景,能够大大提升其价值:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00005.jpeg
神经网络的灵感来源
神经网络的灵感来自于人类大脑的工作方式。人类大脑通过人类感官(特别是视觉)传递的数据来处理大量信息。神经元在处理过程中,通过电信号在它们之间传递,并应用翻转逻辑,就像信号传输时门的开闭。下图展示了神经元的结构:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00006.jpeg
每个神经元的主要组成部分是:
-
树突:每个神经元的输入点,接收来自网络中其他神经元的电信号输入。
-
细胞体:它根据树突输入生成推论,并决定采取什么行动。
-
轴突末端:它们以电信号的形式将输出传输到下一个神经元。
每个神经元只有在信号超过某一特定阈值时才会处理信号。神经元要么触发,要么不触发;要么是0,要么是1。
人工智能曾是科幻电影和小说书籍中的一个领域。人工神经网络(ANNs)自 20 世纪 50 年代以来就已经存在,但由于计算架构和性能的进步,过去 10 年它们变得更加主流。计算机处理能力的重大进展导致了:
-
大规模并行处理
-
分布式表示与计算
-
学习和泛化能力
-
容错性
-
低能耗
在数值计算和符号操作领域,在集中的架构上解决问题时,现代计算机已经在很大程度上超越了人类。它们在模式识别、噪声降低和优化领域仍有所滞后。例如,一个幼儿能够在人群中认出自己的妈妈,但使用集中式架构的计算机却做不到这一点。
这就是大脑的生物神经网络超越机器的地方,因此激发了开发一种松散的、去中心化的结构,模拟大脑的灵感。
人工神经网络(ANN)是一个大规模并行计算系统,由大量简单的处理器和许多互连组成。
全球领先的新闻机构之一《卫报》利用大数据对档案进行数字化,通过上传他们所有档案的快照。然而,用户复制内容并在其他地方使用是这里的限制。为了解决这个问题,可以使用人工神经网络(ANN)进行文本模式识别,将图像转换为文本文件,再根据最终用户的需求转换成任何格式。
神经网络是如何工作的?
类似于生物神经元结构,人工神经网络将神经元定义为一个中央处理单元,它执行数学运算,将一组输入生成一个输出。神经元的输出是输入的加权和加上偏置的函数。每个神经元执行一个非常简单的操作,当接收到的总信号超过激活阈值时就会被激活,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00007.gif
整个神经网络的功能就是计算所有神经元的输出,这完全是一个确定性的计算过程。从本质上讲,ANN 是一组数学函数的逼近。我们现在将介绍与 ANN 相关的新术语:
-
输入层
-
隐藏层
-
输出层
-
权重
-
偏置
-
激活函数
分层方法
任何神经网络处理框架都有以下结构:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00008.gif
这里有一组输入,一个处理器和一组输出。这种分层方法也被神经网络所采用。输入层由输入组成,执行处理的 中间层 被称为 隐藏层,而 输出层 形成输出层。
我们的神经网络架构也基于相同的原理。隐藏层有魔力,它将输入转换为所需的输出。理解隐藏层需要了解权重、偏置和激活函数,这是我们接下来讨论的话题。
权重和偏置
在人工神经网络(ANN)中,权重是将输入转化为影响输出的最重要因素。这类似于线性回归中的斜率,其中权重被乘以输入,以加和形成输出。权重是数值参数,决定了每个神经元对其他神经元的影响强度。
对于一个典型的神经元,如果输入为 x[1]、x[2] 和 x[3],那么应用于它们的突触权重分别表示为 w[1]、w[2] 和 w[3]。
输出为
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00009.jpeg
其中 i 是从 1 到输入数量的编号。
简单来说,这是一个矩阵乘法过程,用来得到加权和。
偏置就像线性方程中加上的截距。它是一个额外的参数,用于调整输出,同时与神经元输入的加权和一起作用。
神经元所执行的处理可以表示为:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00010.jpeg
对此输出应用一个函数,称为激活函数。下一层的输入是前一层神经元的输出,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00011.gif
神经网络训练
训练是通过向网络提供一些样本数据,并修改权重以更好地逼近期望的功能。
训练主要有两种类型:监督学习和无监督学习。
监督学习
我们向神经网络提供输入和期望的输出。网络对输入的响应被测量,权重被修改,以减少实际输出和期望输出之间的差异。
无监督学习
我们只提供输入。神经网络调整自身的权重,使得相似的输入产生相似的输出。网络识别输入中的模式和差异,而不依赖外部帮助。
训练轮次(Epoch)
一次迭代或遍历网络过程,即给网络提供输入并更新网络权重的过程,称为训练轮次(epoch)。它是前馈和反向传播更新权重的完整过程,也是对整个数据集的完整读取。
通常,需要进行多次训练轮次,有时达到数万次,才能高效地训练神经网络。我们将在后续章节中了解更多关于训练轮次的内容。
激活函数
神经网络处理的抽象主要通过激活函数来实现。激活函数是一个数学函数,它将输入转化为输出,并增加神经网络处理的魔力。没有激活函数,神经网络的工作就像线性函数。线性函数的输出与输入成正比,例如:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00012.jpeghttps://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00013.jpeg
线性函数是一次多项式。简单来说,它是一条没有任何曲线的直线。
然而,大多数神经网络试图解决的问题本质上是非线性和复杂的。为了实现非线性,使用了激活函数。非线性函数是高次多项式函数,例如:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00014.jpeghttps://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00015.jpeg
非线性函数的图形是曲线的,增加了复杂性因素。
激活函数赋予神经网络非线性特性,使其成为真正的通用函数逼近器。
不同的激活函数
神经网络有许多可用的激活函数。我们将在这里介绍其中一些。
线性函数
最简单的激活函数,是在神经网络问题中常用于输出层的激活函数,它由以下公式表示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00016.jpeg
输出与输入相同,函数定义在范围(-infinity, +infinity)内。下图展示了一个线性激活函数:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00017.gif
单位阶跃激活函数
单位阶跃激活函数是神经网络中使用频繁的特性。对于负数参数,输出值为0,对于正数参数,输出值为1。该函数如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00018.jpeg
范围在*(0,1)*之间,输出是二元的。这些类型的激活函数在二进制方案中非常有用。当我们想要将输入模型分类到两个组中的一个时,可以使用带有单位阶跃激活函数的二进制编译器。单位阶跃激活函数如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00019.gif
Sigmoid
sigmoid函数是一个数学函数,产生一个 sigmoidal 曲线;其特征曲线呈S形状。这是最早且常用的激活函数。它将输入压缩到0和1之间的任何值,使模型在本质上具有逻辑性。该函数是由以下公式定义的逻辑函数的特例:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00020.jpeg
下图显示了一个具有S形状的 sigmoid 曲线:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00021.gif
双曲正切函数
另一个非常流行并广泛使用的激活特性是tanh函数。如果你看接下来的图形,你会发现它看起来与sigmoid非常相似;事实上,它是一个缩放过的sigmoid函数。这是一个非线性函数,定义在*(-1, 1)的范围内,因此你不必担心激活值爆炸的问题。需要澄清的一点是,tanh的梯度比sigmoid更强(其导数更陡峭)。在sigmoid和tanh之间做决定将取决于你的梯度强度需求。像sigmoid*一样,tanh也有缺失斜率的问题。该函数由以下公式定义:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00022.jpeg
下图显示了一个双曲正切激活函数:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00023.gif
这看起来与sigmoid非常相似;事实上,它是一个缩放过的sigmoid函数。
修正线性单元(ReLU)
修正线性单元(ReLU)是自 2015 年以来使用最广泛的激活函数。它是一个简单的条件,并且相较于其他函数有优势。该函数由以下公式定义:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00024.jpeg
下图显示了一个 ReLU 激活函数:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00025.gif
输出的范围在0到无穷大之间。ReLU 在计算机视觉和语音识别中使用深度神经网络时找到了应用。还有许多其他的激活函数,但我们在这里涵盖了最重要的几个。
应该使用哪些激活函数?
由于神经网络需要支持非线性和更复杂的特性,所使用的激活函数必须足够强大,满足以下要求:
-
它应该是可微分的;我们将在反向传播中看到为什么需要微分。它不应导致梯度消失。
-
它应该是简单且快速的处理。
-
它不应是零中心的。
sigmoid是最常用的激活函数,但它有以下几个问题:
-
由于使用的是逻辑模型,计算过程非常耗时且复杂。
-
它会导致梯度消失,某个时刻神经元之间没有信号传递。
-
它收敛较慢。
-
它不是零中心的。
这些缺点通过 ReLU 得到了改善。ReLU 简单且处理速度更快。它没有消失梯度问题,并且相比于sigmoid和tanh函数,取得了显著的改进。ReLU 是神经网络和深度学习问题中最常用的激活函数。
ReLU 用于隐藏层,而输出层可以使用softmax
函数来解决逻辑回归问题,线性函数用于回归问题。
感知器和多层架构
感知器是一个单一神经元,用于将一组输入分类为两类之一(通常是1或*-1*)。如果输入是以网格形式出现,感知器可以用来识别形状的视觉图像。感知器通常使用阶跃函数,如果输入的加权和超过某个阈值,返回1,否则返回0。
当多个感知器层组合在一起时,它们形成一个多层架构,这提供了神经网络处理所需的复杂性。多层感知器(MLPs)是最广泛使用的神经网络架构。
前向传播和反向传播
从输入层到隐藏层(或多个隐藏层)再到输出层的处理过程称为前向传播。每一层都应用sum(inputweights)+bias*,然后激活函数的值被传递到下一层。下一层可以是另一个隐藏层,也可以是输出层。神经网络的构建使用大量的隐藏层,从而形成深度神经网络(DNN)。
一旦在最后一层(输出层)得到了输出,我们计算误差(预测输出减去原始输出)。这个误差用于修正前向传播中使用的权重和偏差。这里需要使用导数函数。需要改变的权重量由梯度下降决定。
反向传播过程使用每个神经元激活函数的偏导数来识别每个输入权重的梯度(或坡度)。梯度指示权重变化时,误差将如何剧烈地增加或减少。反向传播会不断地调整权重,直到误差减少到最大程度,减小量由学习率决定。
学习率是一个标量参数,类似于数值积分中的步长,用于设置调整速率以加快误差的减少。学习率在反向传播过程中用于调整权重和偏差。
学习率越高,算法减少误差的速度越快,训练过程也越快:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00026.jpeg
神经网络和激活函数的逐步说明
我们将通过逐步的方式,理解带有单隐藏层的前向和反向传播。输入层有一个神经元,输出将解决一个二元分类问题(预测 0 或 1)。下图展示了带有单隐藏层的前向和反向传播:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00027.jpeg
接下来,让我们详细逐步分析网络训练过程中需要执行的所有操作:
-
将输入作为矩阵处理。
-
初始化权重和偏差为随机值。这是一次性操作,我们将通过误差传播过程不断更新这些值。
-
对每个训练模式重复步骤 4 到 9(以随机顺序呈现),直到误差最小化。
-
将输入应用到网络中。
-
计算从输入层到输出层,每个神经元的输出,包括隐藏层(如果有)。
-
计算输出的误差:实际值减去预测值。
-
使用输出误差计算前面层的误差信号。激活函数的偏导数用于计算误差信号。
-
使用误差信号计算权重调整。
-
应用权重调整。
步骤 4 和 5 是前向传播,步骤 6 到 9 是反向传播。
学习率是控制权重更新量的配置参数。
完整的来回传递过程称为训练周期或时代。更新后的权重和偏差将在下一个周期中使用。我们会不断进行递归训练,直到误差极小。
本书将进一步详细讲解前向传播和反向传播。
前馈网络与反馈网络
神经网络中信号的流动可以是单向的,也可以是循环的。在第一种情况下,我们称神经网络架构为前馈网络,因为输入信号被输入到输入层后,经过处理后会传递到下一层,就像下图所示。MLP(多层感知机)和径向基函数也是前馈网络的典型例子。下图展示了一个 MLP 架构:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00028.gif
当神经网络存在某种内部反馈时,意味着信号被反馈到已经接收和处理过该信号的神经元或层中,那么网络就是反馈型网络,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00029.jpeg
在网络中添加循环的特别原因是产生动态行为,尤其是在网络处理涉及时间序列或模式识别的任务时,这些任务需要一个内部记忆来加强学习过程。然而,这类网络尤其难以训练,最终可能会无法学习。大多数反馈型网络是单层的,如Elman网络和Hopfield网络,但也可以构建递归的多层网络,如回声网络和递归 MLP 网络。
梯度下降
梯度下降是任何学习模型中用于错误校正的迭代方法。对于神经网络在反向传播期间,通过误差乘以激活函数的导数来迭代更新权重和偏置的过程是梯度下降的方法。最陡下降步长被上一步的相似大小替换。梯度基本上定义为曲线的斜率,是激活函数的导数:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00030.jpeg
在每一步推导梯度下降的目标是找到全局成本最低点,其中误差最小。这是模型对数据拟合良好且预测更准确的地方。
梯度下降可以在完整批次或随机中执行。在完整批次梯度下降中,为整个训练数据集计算梯度,而随机梯度下降 (SGD) 则使用单个样本进行梯度计算。它还可以采用小批量并执行计算。SGD 的一个优点是更快地计算梯度。
神经网络的分类
人工神经网络的基本基础是相同的,但在其演变过程中设计了各种神经网络模型。以下是一些人工神经网络模型:
-
自适应线性元素 (ADALINE),是一个简单的感知器,只能解决线性问题。每个神经元都接收输入的加权线性和,并将其传递给双极函数,该函数根据总和产生*+1或-1*。该函数检查传递的输入总和,如果净值*>= 0*,则为*+1*,否则为*-1*。
-
多个 ADALINE (MADALINE),是 ADALINE 单元的多层网络。
-
感知器是单层神经网络(单个神经元或单元),其中输入是多维的(向量),输出是输入权重和的函数。
-
径向基函数网络是一种人工神经网络,其中径向基函数用作激活函数。网络输出是输入和一些神经元参数的径向基函数的线性组合。
-
前馈是神经网络中最简单的形式。数据在各层之间处理,没有任何循环或循环。我们将在本书中研究以下前馈网络:
-
自编码器
-
概率的
-
时间延迟
-
卷积的
-
-
递归神经网络 (RNNs),与前馈网络不同,将数据前向和后向传播,从后续处理阶段向早期阶段传播。以下是 RNN 的类型;我们将在后续章节中学习它们:
-
霍普菲尔德网络
-
波尔兹曼机器
-
自组织映射 (SOMs)
-
双向联想记忆 (BAM)
-
长短期记忆 (LSTM)
-
以下图片描述了**(a) 循环神经网络和(b) 前向神经网络**:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00031.gif
使用 R 神经网络库进行简单示例 - neuralnet()
考虑一个简单的数据集,包含数字的平方,我们将使用它来训练 R 中的 neuralnet
函数,然后测试构建的神经网络的准确性:
输入 | 输出 |
---|---|
0 | 0 |
1 | 1 |
2 | 4 |
3 | 9 |
4 | 16 |
5 | 25 |
6 | 36 |
7 | 49 |
8 | 64 |
9 | 81 |
10 | 100 |
我们的目标是设置权重和偏置,以便模型能够完成这里所做的工作。输出需要基于输入的函数进行建模,这个函数未来可以用于根据输入确定输出:
#########################################################################
###Chapter 1 - Introduction to Neural Networks - using R ################
###Simple R program to build, train and test neural Networks#############
#########################################################################
#Choose the libraries to use
library("neuralnet")
#Set working directory for the training data
setwd("C:/R")
getwd()
#Read the input file
mydata=read.csv('Squares.csv',sep=",",header=TRUE)
mydata
attach(mydata)
names(mydata)
#Train the model based on output from input
model=neuralnet(formula = Output~Input,
data = mydata,
hidden=10,
threshold=0.01 )
print(model)
#Lets plot and see the layers
plot(model)
#Check the data - actual and predicted
final_output=cbind (Input, Output,
as.data.frame(model$net.result) )
colnames(final_output) = c("Input", "Expected Output",
"Neural Net Output" )
print(final_output)
#########################################################################
让我们逐行查看代码
为了理解上面所提到的所有代码步骤,我们将逐一详细讲解。如果某些步骤目前看起来不清楚,不用担心,您可以在接下来的示例中深入了解。首先将显示代码片段,然后给出相应的解释:
library("neuralnet")
该行代码在我们的程序中包含了 neuralnet()
库。neuralnet()
是 综合 R 档案网络(CRAN)的一部分,CRAN 包含了许多用于各种应用的 R 库。
mydata=read.csv('Squares.csv',sep=",",header=TRUE)
mydata
attach(mydata)
names(mydata)
| 该代码读取以 ,
(逗号)为分隔符的 CSV 文件,文件的第一行为表头。使用 names()
可以显示文件的表头。|
model=neuralnet(formula = Output~Input,
data = mydata,
hidden=10,
threshold=0.01 )
| 输出与输入的训练过程发生在此。neuralnet()
函数接收输出和输入的列名(output~input
),数据集,隐藏层中的神经元数目,以及停止标准(threshold
)。 |
neuralnet
包的简要描述,摘自官方文档,见下表:
neuralnet 包: |
---|
描述: |
使用反向传播训练神经网络,带有(Riedmiller,1994)或不带权重回溯的弹性反向传播(Riedmiller,1993),或由 Anastasiadis 等人(2005)修改的全局收敛版本。该包允许通过自定义选择误差和激活函数来进行灵活设置。此外,还实现了广义权重的计算(Intrator O 和 Intrator N,1993)。 |
详情: |
包:neuralnet 类型:包 版本:1.33 日期:2016-08-05 许可:GPL (>=2) |
作者: |
Stefan Fritsch, Frauke Guenther (电子邮件:guenther@leibniz-bips.de ) 维护者:Frauke Guenther (电子邮件:guenther@leibniz-bips.de ) |
用法: |
neuralnet(formula, data, hidden = 1, threshold = 0.01, stepmax = 1e+05, rep = 1, startweights = NULL, learningrate.limit = NULL, learningrate.factor = list(minus = 0.5, plus = 1.2), learningrate=NULL, lifesign = "none", lifesign.step = 1000, algorithm = "rprop+", err.fct = "sse", act.fct = "logistic", linear.output = TRUE, exclude = NULL, constant.weights = NULL, likelihood = FALSE) |
参数的含义: |
formula : 模型的符号描述。data : 一个包含公式中指定变量的数据框。hidden : 一个整数向量,指定每一层中的隐藏神经元(节点)数量。threshold : 一个数值,指定误差函数的偏导数的阈值作为停止标准。stepmax : 神经网络训练的最大步数。达到此最大值会导致神经网络训练过程停止。rep : 神经网络训练的重复次数。startweights : 一个包含初始权重值的向量。权重将不会随机初始化。learningrate.limit : 一个向量或列表,包含学习率的最低和最高限制。仅用于RPROP 和GRPROP 。learningrate.factor : 一个向量或列表,包含学习率上限和下限的乘法因子,仅用于RPROP 和GRPROP 。learningrate : 一个数值,指定传统反向传播算法使用的学习率。仅用于传统反向传播。lifesign : 一个字符串,指定神经网络计算过程中输出的详细程度- 'none' 、'minimal' 或 'full' 。lifesign.step : 一个整数,指定在完整的生命周期模式下,打印最小阈值的步长。algorithm : 一个字符串,包含用于计算神经网络的算法类型。err.fct : 一个可微函数,用于计算误差。act.fct : 一个可微函数,用于平滑协变量或神经元与权重的叉积结果。linear.output : 逻辑值。如果输出神经元不应用 act.fct ,则将线性输出设置为 TRUE ,否则设置为 FALSE 。exclude : 一个向量或矩阵,指定从计算中排除的权重。constant.weights : 一个向量,指定在训练过程中被排除并视为固定的权重值。likelihood : 逻辑值。如果误差函数等于负对数似然函数,则会计算信息标准 AIC 和 BIC。此外,置信区间的使用也是有意义的。 |
在简要浏览了包的文档后,我们来看一下剩余的代码示例:
print(model)
该命令输出刚生成的模型,如下所示:
$result.matrix
1
error 0.001094100442
reached.threshold 0.009942937680
steps 34563.000000000000
Intercept.to.1layhid1 12.859227998180
Input.to.1layhid1 -1.267870997079
Intercept.to.1layhid2 11.352189417430
Input.to.1layhid2 -2.185293148851
Intercept.to.1layhid3 9.108325110066
Input.to.1layhid3 -2.242001064132
Intercept.to.1layhid4 -12.895335140784
Input.to.1layhid4 1.334791491801
Intercept.to.1layhid5 -2.764125889399
Input.to.1layhid5 1.037696638808
Intercept.to.1layhid6 -7.891447011323
Input.to.1layhid6 1.168603081208
Intercept.to.1layhid7 -9.305272978434
Input.to.1layhid7 1.183154841948
Intercept.to.1layhid8 -5.056059256828
Input.to.1layhid8 0.939818815422
Intercept.to.1layhid9 -0.716095585596
Input.to.1layhid9 -0.199246231047
Intercept.to.1layhid10 10.041789457410
Input.to.1layhid10 -0.971900813630
Intercept.to.Output 15.279512257145
1layhid.1.to.Output -10.701406269616
1layhid.2.to.Output -3.225793088326
1layhid.3.to.Output -2.935972228783
1layhid.4.to.Output 35.957437333162
1layhid.5.to.Output 16.897986621510
1layhid.6.to.Output 19.159646982676
1layhid.7.to.Output 20.437748965610
1layhid.8.to.Output 16.049490298968
1layhid.9.to.Output 16.328504039013
1layhid.10.to.Output -4.900353775268
让我们回到代码分析:
plot(model)
之前的命令为我们绘制了神经网络,如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00032.gif
final_output=cbind (Input, Output,
as.data.frame(model$net.result) )
colnames(final_output) = c("Input", "Expected Output",
"Neural Net Output" )
print(final_output)
之前的代码输出最终结果,将预测输出与实际输出进行比较,如下所示:
> print(final_output)
Input Expected Output Neural Net Output
1 0 0 -0.0108685813
2 1 1 1.0277796553
3 2 4 3.9699671691
4 3 9 9.0173879001
5 4 16 15.9950295615
6 5 25 25.0033272826
7 6 36 35.9947137155
8 7 49 49.0046689369
9 8 64 63.9972090104
10 9 81 81.0008391011
11 10 100 99.9997950184
使用 nnet() 库的实现
为了提高我们对nnet
库的使用,我们来看另一个例子。这一次,我们将使用通过顾客访谈收集的数据。顾客被要求对以下方面进行评分:服务、环境和食物。顾客还被问到是否会根据这些评分给小费。在这个案例中,输入的数量是2
,输出是一个分类值(Tip=1
和No-tip=0
)。
将使用的输入文件如下面的表格所示:
编号 | 顾客是否给小费 | 服务 | 环境 | 食物 | 是否给小费 |
---|---|---|---|---|---|
1 | 1 | 4 | 4 | 5 | Tip |
2 | 1 | 6 | 4 | 4 | Tip |
3 | 1 | 5 | 2 | 4 | Tip |
4 | 1 | 6 | 5 | 5 | Tip |
5 | 1 | 6 | 3 | 4 | Tip |
6 | 1 | 3 | 4 | 5 | Tip |
7 | 1 | 5 | 5 | 5 | Tip |
8 | 1 | 5 | 4 | 4 | Tip |
9 | 1 | 7 | 6 | 4 | Tip |
10 | 1 | 7 | 6 | 4 | Tip |
11 | 1 | 6 | 7 | 2 | Tip |
12 | 1 | 5 | 6 | 4 | Tip |
13 | 1 | 7 | 3 | 3 | Tip |
14 | 1 | 5 | 1 | 4 | Tip |
15 | 1 | 7 | 5 | 5 | Tip |
16 | 0 | 3 | 1 | 3 | No-tip |
17 | 0 | 4 | 6 | 2 | No-tip |
18 | 0 | 2 | 5 | 2 | No-tip |
19 | 0 | 5 | 2 | 4 | No-tip |
20 | 0 | 4 | 1 | 3 | No-tip |
21 | 0 | 3 | 3 | 4 | No-tip |
22 | 0 | 3 | 4 | 5 | No-tip |
23 | 0 | 3 | 6 | 3 | No-tip |
24 | 0 | 4 | 4 | 2 | No-tip |
25 | 0 | 6 | 3 | 6 | No-tip |
26 | 0 | 3 | 6 | 3 | No-tip |
27 | 0 | 4 | 3 | 2 | No-tip |
28 | 0 | 3 | 5 | 2 | No-tip |
29 | 0 | 5 | 5 | 3 | No-tip |
30 | 0 | 1 | 3 | 2 | No-tip |
这是一个分类问题,包含三个输入和一个分类输出。我们将通过以下代码来解决这个问题:
########################################################################
##Chapter 1 - Introduction to Neural Networks - using R ################
###Simple R program to build, train and test neural networks ###########
### Classification based on 3 inputs and 1 categorical output ##########
########################################################################
###Choose the libraries to use
library(NeuralNetTools)
library(nnet)
###Set working directory for the training data
setwd("C:/R")
getwd()
###Read the input file
mydata=read.csv('RestaurantTips.csv',sep=",",header=TRUE)
mydata
attach(mydata)
names(mydata)
##Train the model based on output from input
model=nnet(CustomerWillTip~Service+Ambience+Food,
data=mydata,
size =5,
rang=0.1,
decay=5e-2,
maxit=5000)
print(model)
plotnet(model)
garson(model)
########################################################################
让我们逐行分析代码。
为了理解刚才提出的代码中的所有步骤,我们将详细分析它们。首先会展示代码片段,然后进行解释。
library(NeuralNetTools)
library(nnet)
这包括我们的程序所需的库NeuralNetTools
和nnet()
。
###Set working directory for the training data
setwd("C:/R")
getwd()
###Read the input file
mydata=read.csv('RestaurantTips.csv',sep=",",header=TRUE)
mydata
attach(mydata)
names(mydata)
这将设置工作目录并读取输入的 CSV 文件。
##Train the model based on output from input
model=nnet(CustomerWillTip~Service+Ambience+Food,
data=mydata,
size =5,
rang=0.1,
decay=5e-2,
maxit=5000)
print(model)
这调用了nnet()
函数,并传入了参数。输出如下。nnet()
会处理前向传播和反向传播直到收敛:
> model=nnet(CustomerWillTip~Service+Ambience+Food,data=mydata, size =5, rang=0.1, decay=5e-2, maxit=5000)
# weights: 26
initial value 7.571002
iter 10 value 5.927044
iter 20 value 5.267425
iter 30 value 5.238099
iter 40 value 5.217199
iter 50 value 5.216688
final value 5.216665
converged
nnet
包的简要描述,摘自官方文档,如下表所示:
nnet-package:前馈神经网络和多项式对数线性模型 |
---|
描述: |
用于前馈神经网络(单隐层)和多项式对数线性模型的软件。 |
详情: |
| 包名:nnet
类型:包
版本:7.3-12
日期:2016-02-02
许可证:GPL-2 | GPL-3
作者: |
---|
Brian Ripley William Venables |
使用方法: |
nnet(formula, data, weights, subset, na.action, contrasts = NULL) |
参数含义: |
| Formula
: 形如 class ~ x1 + x2 + … 的公式 data
: 从数据框中提取优先使用公式中指定的变量
weights
: (案例)每个示例的权重;如果缺失,则默认为 1
subset
: 一个索引向量,指定训练样本中要使用的案例
na.action
: 一个函数,用于指定在发现缺失值(NA)时要采取的措施
contrasts:
用于某些或所有出现在模型公式中的变量的对比列表 |
在简要介绍包文档后,接下来让我们查看以下代码示例中剩余的行:
print(model)
此命令打印出net()
的详细信息,如下所示:
> print(model)
a 3-5-1 network with 26 weights
inputs: Service Ambience Food
output(s): CustomerWillTip
options were - decay=0.05
要绘制model
,使用以下命令:
plotnet(model)
model
的绘图如下;单隐藏层中有五个节点:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00033.jpeg
使用NeuralNetTools
,可以通过garson
算法获取神经网络中输入变量的相对重要性:
garson(model)
此命令打印出各种输入参数及其对输出预测的重要性,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00034.jpeg
从应用 Garson 算法获得的图表中,可以注意到,在决定给小费时,顾客所获得的服务对这一决定的影响最大。
我们已经看到过 R 中的两个神经网络库,并在简单示例中使用了它们。接下来,我们将深入探讨本书中的几个实际用例。
深度学习
深度学习(DL)形成了一个具有众多隐藏层的高级神经网络。深度学习是一个庞大的学科,是构建人工智能的重要概念。它被广泛应用于各种领域,例如:
-
图像识别
-
计算机视觉
-
手写识别
-
文本分类
-
多类分类
-
回归问题等
我们将在未来的章节中详细了解使用 R 进行深度学习。
神经网络的优缺点
神经网络是深度学习的基础,深度学习的应用非常广泛,从语音识别到癌症检测。神经网络的优缺点在本节中进行了描述。优点超过缺点,因此神经网络被视为数据科学、机器学习和预测建模的首选技术。
优势
以下是神经网络的一些优势:
-
神经网络具有灵活性,可以用于回归和分类问题。任何可以转化为数值的数据都可以用于模型,因为神经网络是一个具有近似函数的数学模型。
-
神经网络适合建模具有大量输入的非线性数据,例如图像。它在处理涉及大量特征的任务时非常可靠。它通过将分类问题拆分成简单元素的层次网络来工作。
-
一旦训练完成,预测速度相当快。
-
神经网络可以用任意数量的输入和层进行训练。
-
神经网络在有更多数据点时效果最佳。
缺点
让我们来看看神经网络的一些缺点:
-
神经网络是黑箱模型,意味着我们无法知道每个独立变量对因变量的影响程度。
-
使用传统的 CPU 进行训练在计算上非常昂贵且耗时。
-
神经网络在很大程度上依赖于训练数据。这会导致过拟合和泛化问题。模型过于依赖训练数据,可能会被调整得过于符合数据。
神经网络实现中的最佳实践
以下是一些最佳实践,有助于神经网络的实现:
-
神经网络在有良好训练数据的情况下实现最佳。
-
在多层感知机(MLP)中,隐藏层越多,模型的预测准确度越高。
-
隐藏层最好有五个节点。
-
ReLU 和 误差平方和 (SSE) 分别是最佳的激活函数和误差调整技术。
快速说明 GPU 处理
处理能力的提升为神经网络在日常问题中的应用提供了强大支持。GPU 是专门设计来执行图形操作的处理器(例如,游戏、3D 动画等)。它们执行数学密集型任务,且与 CPU 配合使用。CPU 负责计算机的操作任务,而 GPU 则用于处理繁重的工作负载。
神经网络架构需要强大的数学计算能力,GPU 是首选的硬件。在每个神经元的权重和输入之间的向量化点积可以通过 GPU 并行计算。GPU 的进步正在推动神经网络的普及。深度学习在图像处理、计算机视觉、生物信息学和天气建模等领域的应用都受益于 GPU。
总结
在本章中,我们回顾了人工神经网络(ANN)的概述。神经网络的实现相对简单,但其内部机制非常复杂。我们可以将神经网络总结为一种通用的数学函数逼近方法。任何一组输入输出的映射都可以通过神经网络转化为一个黑箱数学函数,近年来,神经网络的应用也变得非常广泛。
本章我们讨论了以下内容:
-
神经网络是一种机器学习技术,并且是数据驱动的。
-
人工智能、机器学习和神经网络是让机器像人类一样工作的不同范式。
-
神经网络可以用于监督学习和无监督学习。
-
权重、偏置和激活函数是神经网络中的重要概念。
-
神经网络是非线性和非参数化的。
-
神经网络在预测时非常快速,并且相较于其他机器学习模型最为准确。
-
任何神经网络架构中都包含输入层、隐藏层和输出层。
-
神经网络基于构建多层感知机(MLP),我们理解了神经网络的基础:权重、偏差、激活函数、前向传播和反向传播处理
-
前向传播和反向传播是推导神经网络模型的技术
神经网络可以通过多种编程语言实现,例如 Python、R、MATLAB、C 和 Java 等。本书的重点将是使用 R 构建应用程序。深度神经网络(DNN)和人工智能(AI)系统正基于神经网络不断发展。在接下来的章节中,我们将深入探讨不同类型的神经网络及其各种应用。
第二章:神经网络中的学习过程
正如人类学习有许多不同的类型和方法一样,机器学习也可以有不同的方式。为了确保机器能够从经验中学习,定义最适合的学习方法非常重要,这取决于具体的工作要求。这通常意味着选择当前情况下有效的技术,并不时进行评估,以决定是否需要尝试新的方法。
我们已经在第一章中学习了神经网络的基础知识,神经网络与人工智能概念,并通过 R 语言进行了两个简单的实现。在本章中,我们将探讨学习过程,也就是如何训练、测试和部署神经网络机器学习模型。训练阶段用于学习,以调整神经网络的参数。测试阶段用于评估完全训练好的神经网络的性能。最后,在部署阶段,实际数据会通过模型进行预测。
以下是本章涵盖的概念列表:
-
学习过程
-
有监督学习
-
无监督学习
-
训练、测试和部署模型
-
评估指标——误差测量与微调;衡量模型的准确性
-
使用神经网络的有监督学习模型
-
使用神经网络的无监督学习模型
-
反向传播
到本章结束时,我们将理解学习过程的基本概念,并学习如何在 R 环境中实现它。我们将发现实现神经网络的不同类型的算法。我们将学习如何训练、测试和部署模型。我们将知道如何执行正确的评估程序。
机器学习是什么?
机器学习是什么意思?这个定义相当复杂,因此我们需要请广大科学家们帮助解答。我们可以提到一位人工智能先驱的名言:
“一个研究领域,赋予计算机无需明确编程即可学习的能力。”
– 阿瑟·塞缪尔
机器学习是指通过数据训练模型或算法,然后使用该模型预测新的数据。例如,一个幼儿从爬行阶段被教会如何走路。最初,幼儿的父母扶着孩子的手帮助他站起来,并通过给定的数据进行教学。基于这些过程,如果在幼儿的路上出现障碍,或者某个地方需要转弯,在训练之后,幼儿能够自己导航。用于训练的数据称为训练数据,接受者在正式训练后仍然继续学习。
机器也可以像教小孩子一样,基于训练来完成任务。首先,我们输入足够的数据来告诉机器在什么情况下需要做什么。经过训练后,机器可以自动执行任务,还能学会自我调整。这种训练机器的方式叫做机器学习。
机器学习与编程的主要区别在于,机器学习不涉及编码/编程,而编程是给机器一组执行指令的过程。在机器学习中,数据是唯一的输入,而模型是基于我们决定使用的算法。
要使用的算法是基于数据的各种因素:特征(或自变量)、因变量的类型、模型的准确性以及模型训练和预测的速度。
基于机器学习数据的自变量,有三种不同的方式来训练模型:
-
监督学习
-
无监督学习
-
强化学习
下图展示了用于训练机器学习模型的不同算法:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00035.gif
在接下来的章节中,我们将逐一讲解这些内容。
监督学习
监督学习是一种学习方法,其中一部分训练数据作为算法的“老师”,帮助确定模型。机器被教会如何从目标数据中学习。目标数据或因变量是自变量的集体作用结果。网络训练是通过目标数据及其与输入数据模式的关系进行的。目标标签是事先已知的,数据被输入算法以推导模型。
大多数神经网络的使用是基于监督学习的。权重和偏差根据输出值进行调整。输出可以是分类的(如真/假或 0/1/2)或连续的(如 1、2、3,依此类推)。模型依赖于输出变量的类型,而在神经网络中,输出层是根据目标变量的类型来构建的。
对于神经网络,所有的自变量和因变量需要是数值型的,因为神经网络是基于数学模型的。数据科学家需要将数据转换为数值形式,以便输入模型。
监督学习通过下图来表示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00036.gif
无监督学习
在无监督学习(或自组织)中,输出层被训练以将输入数据组织成另一组数据,而无需目标变量。输入数据会被分析,并从中找到模式以推导输出,如下图所示。由于没有教师(或目标变量),这种学习方式称为无监督学习。
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00037.gif
无监督学习中可用的不同技术如下:
-
聚类(K 均值,层次聚类)
-
关联技术
-
降维
-
自组织映射(SOM)/ Kohonen 网络
总结一下,以下图示了机器学习的两种主要类型:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00038.jpeg
对于神经网络,我们有两种类型可用,使用 R 中不同的方式。
强化学习
强化学习是一种机器学习类型,在这种类型中,模型会不断收到反馈,以适应环境。在每个步骤中都会进行性能评估,以改进模型。对于神经网络,有一种特殊类型叫做Q-learning,它结合神经元来实现反向传播反馈机制中的强化学习。本书不涉及详细内容。
以下是我们目前已经涵盖的三种学习类型:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00039.gif
训练和测试模型
训练和测试模型是将该模型用于预测分析的基础。给定一个包含100行数据的数据集,其中包括预测变量和响应变量,我们将数据集分成一个合适的比例(例如70:30),并分配70行用于训练,30行用于测试。数据行是随机选择的,以减少偏差。
一旦训练数据可用,数据将被传入神经网络,以建立巨大的通用函数。训练数据决定了权重、偏置和激活函数的使用,以便从输入得到输出。直到最近,我们才不能说一个权重对目标变量有正向或负向影响。但现在我们已经能够揭示这个黑盒中的一些信息。例如,通过绘制一个训练过的神经网络,我们可以发现训练过的突触权重和有关训练过程的基本信息。
一旦足够的收敛性达到,模型将存储在内存中,下一步是测试模型。我们将30行数据传入模型,检查实际输出是否与模型的预测输出相符。评估用于获取各种指标,以验证模型。如果准确度差异过大,则需要通过更改训练数据和传递给神经网络函数的其他参数重新构建模型。我们将在本章稍后讨论更多关于评估指标的内容。
在训练和测试之后,模型被认为已部署,其中实际数据通过模型传递以获得预测。例如,使用案例可能是基于各种输入参数确定欺诈交易或房贷资格检查。
训练、测试和部署在下图中表示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00040.gif
到目前为止,我们关注的是各种可用的算法;现在是时候将注意力集中在代表每个分析基本元素的数据上。
数据周期
数据是模型构建和学习过程中的关键组成部分。数据需要被收集、清洗、转换,然后输入模型进行学习。整体数据生命周期如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00041.gif
建模的一个关键要求是拥有良好且平衡的数据。这有助于提高模型的准确度,并更好地利用现有的算法。数据科学家的大部分时间都花费在数据清洗上,然后才能开始建模。
我们已经看到模型部署前的训练和测试过程。在测试时,结果作为评估指标进行记录,帮助我们决定是否使用某个模型,或是否需要改变模型。
接下来我们将看到评估指标。
评估指标
评估一个模型涉及在测试阶段检查预测值是否等于实际值。有多种评估指标可用,它们取决于目标变量的状态。
对于二分类问题,预测目标变量和实际目标变量可以处于以下四种状态之一:
预测 | 实际 |
---|---|
预测 = 真 | 实际 = 真 |
预测 = 真 | 实际 = 假 |
预测 = 假 | 实际 = 真 |
预测 = 假 | 实际 = 假 |
当预测值与实际值相同,我们认为模型是准确的。如果所有预测值和实际值都相同(无论是全为真还是全为假),则模型准确度为100%。但实际情况中永远不会如此。
由于神经网络是近似模型,总会有一些误差的可能性。前述表格中的四种状态都是可能的。
我们为模型定义以下术语和指标:
-
真阳性 (TP):所有预测值与实际值均为真的情况(准确度良好)。
-
真负例 (TN):所有预测为假且实际也是假的情况(准确度良好)。
-
假阳性 (FP):这是当我们预测某个值为阳性(真),但实际为阴性时的情况。就像是误报或 FP 错误。例如,当预测男性为孕妇时。所有预测为真,而实际为假的情况。这也叫做第一类错误。
-
假负例 (FN):当我们预测某个值为假,但实际却为真时,该情况称为 FN。例如,当孕妇被孕检试剂预测为未怀孕时,就是一个 FN 案例。所有预测为假且实际为真的情况。这也叫做第二类错误。
混淆矩阵
当分类值被绘制成一个nxn矩阵(在二分类情况下为2x2矩阵)时,该矩阵称为混淆矩阵。所有评估指标都可以从混淆矩阵本身得出:
预测值 | 预测值 | |
---|---|---|
实际值 | 真 | 假 |
真 | TP | FN |
假 | FP | TN |
现在,让我们详细看看一些评估指标。
真阳性率
真阳性率 (TPR) 或敏感性或召回率或命中率,是指从所有识别出的正样本中,正确识别的真阳性比例:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00042.jpeg
理想情况下,如果模型的值接近 1,那么模型的表现会更好。
真负率
真负率 (TNR) 或特异度是正确预测的负样本与我们预测的所有负样本总数之比:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00043.jpeg
如果这个比率接近零,模型就更准确。
准确率
准确率是衡量我们模型好坏的标准。如果模型表现良好,它应该接近 1。
准确率是正确预测与所有总预测的比率:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00044.jpeg
精确度和召回率
精确度和召回率分别是 TP 与 (TP+FP) 以及 TP 与 (TP+FN) 的比率。这些比率决定了我们的预测与实际的相关程度。
精确度定义为选定项目中相关项目的比例。也就是说,预测的结果中有多少是实际正确的。
方程式是:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00045.gif
如果精确度接近 1,我们的预测就会更准确。
召回率则告诉我们选择了多少相关项目。从数学上讲,它是:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00046.gif
以下图表清晰地展示了我们迄今为止的讨论:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00047.jpeg
F 分数
F 分数,或 F1 分数,是衡量准确度的另一种方式。从技术上讲,它是精确度和召回率的调和均值:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00048.jpeg
接收者操作特征曲线
接收者操作特征 (ROC) 曲线是一种图形展示,说明二分类系统的预测能力。ROC 曲线通过在各种阈值设置下绘制真阳性率(TPR)与假阳性率(FPR)的图表来创建。这给我们提供了敏感性与(1 - 特异度)的关系。ROC 曲线通常看起来是这样的:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00049.gif
获得必要技能后,我们已经准备好详细分析用于构建神经网络的算法。
神经网络中的学习
正如我们在第一章《神经网络与人工智能概念》中看到的,神经网络是一种机器学习算法,具有从数据中学习并使用构建的模型进行预测的能力。它是一种通用的函数近似方法,也就是说,任何输入输出数据都可以逼近为数学函数。
正向传播通过选择随机权重为我们提供了一个初始的数学函数,用于根据输入得到输出。实际输出与预测输出之间的差异称为误差项。神经网络的学习过程实际上发生在反向传播阶段。通过减少每次迭代中的误差项,模型会对权重进行微调。在反向传播过程中使用梯度下降法。
让我们在本章详细讲解反向传播,因为它是神经网络中重要的机器学习方面。
返回到反向传播
我们已经在第一章中详细讨论了正向传播,神经网络与人工智能概念,以及使用梯度下降法的反向传播的一些内容。反向传播是理解神经网络的重要概念之一,它依赖于微积分来更新每一层的权重和偏置。误差的反向传播类似于从错误中学习。我们在每次迭代中纠正我们的错误(误差),直到达到一个称为收敛的点。*反向传播的目标是纠正每一层的权重,并最小化输出层的整体误差。
神经网络的学习在前馈网络中极度依赖反向传播。正向传播和误差修正的常见步骤如下所示:
-
通过为隐藏层中每个神经元分配随机的权重和偏置,开始神经网络的正向传播。
-
在每个神经元上获取 sum(weightinput) + bias* 的总和。
-
在每个神经元上应用激活函数(sigmoid)。
-
将此输出传递给下一个层的神经元。
-
如果该层是输出层,应用权重并获取每个输出层神经元的 sum(weightinput) + bias* 的总和。
-
再次,在输出层神经元应用激活函数。
-
这就形成了神经网络在一次正向传播中的输出层输出。
-
现在,使用训练数据,我们可以通过减去实际输出和激活函数输出值来识别每个输出神经元的误差项。
-
误差的总和通过以下公式计算得出:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00050.jpeg
当误差函数 E 随后进行微分时,使用一个 1/2 的因子来消除指数。
- 梯度下降技术要求计算误差项(E)相对于网络权重的偏导数。使用链式法则来计算误差项相对于权重 w[ij] 的全误差的偏导数:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00051.jpeg
导数定义为值变化的速率,梯度下降使用导数(或斜率)来最小化误差项并得到一组正确的权重。
- 第一个因子是该特定神经元 j 对输出的误差项的偏导数,并且 o[j] 等于 y:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00052.jpeg
- 链式法则中的第二个因子是神经元 o[j] 对其输入的输出的偏导数,并且是激活函数(sigmoid 函数)的偏导数:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00053.jpeg
这里 net[j] 是输入到神经元的值。
- 链式法则中的第三项只是 o[i]。
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00054.jpeg
- 将第 11 步、第 12 步和第 13 步结合,我们得到:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00055.jpeg
- 每个神经元(任何层级)上的权重 w[ij] 会通过此偏导数与学习率结合进行更新。
这些步骤会重复进行,直到我们获得非常低的误差项的收敛或达到指定的次数。
所有步骤都在可用的 R 包中内部处理。我们可以提供学习率以及其他各种参数。
反向传播过程如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00056.jpeg
就像生活中的一切事物一样,即便是算法也有进一步改进的空间。在接下来的章节中,我们将看到如何实现这一点。
神经网络学习算法优化
在神经网络中执行学习过程的程序称为训练算法。学习算法是机器学习算法选择的最佳优化模型。其目标是最小化损失函数并提高准确性。这里我们展示一些优化技术,除了梯度下降法。
粒子群优化(PSO)方法受到鸟群在寻找食物或生存过程中的集体行为观察的启发。它类似于鱼群试图一起移动。我们知道粒子的位置和速度,PSO 的目标是在由位置和速度控制的数学方程的指导下,在大空间中搜索解决方案集。它从生物体行为中汲取灵感,用于集体智能。
模拟退火是一种基于概率方法的技术,用来逼近代价函数的全局最优解。该方法在大空间中通过模拟搜索解决方案。
进化方法源自生物学中的进化过程,且
进化可以通过繁殖、变异、选择和重组来进行。
适应度函数用于确定模型的性能,并基于此进行调整。
函数,我们选择最终模型。
期望最大化(EM)方法是一种统计学习方法,采用迭代方法找到最大似然或最大后验估计,从而最小化误差。
神经网络中的监督学习
如前所述,监督学习是一种学习方法,其中一部分训练数据作为算法的“老师”,帮助确定模型。在接下来的部分中,将提出一个回归预测建模问题示例,以便了解如何使用神经网络解决该问题。
波士顿数据集
该数据集描述了波士顿郊区住宅的 13 个数值属性,并涉及在这些郊区以千美元为单位建模住宅价格。因此,这是一个回归预测建模问题。输入属性包括犯罪率、非零售商业用地比例、化学浓度等。以下列表显示了所有变量及其简要描述:
-
实例数量:506
-
属性数量:13 个连续属性(包括
class
)属性
MEDV
,以及一个二进制值属性
每个属性的详细描述如下:
-
crim
按城镇划分的每人犯罪率。 -
zn
划为住宅用地的、超过25,000平方英尺的地块比例。 -
indus
每个城镇的非零售商业用地比例。 -
chas
查尔斯河虚拟变量(如果区域边界是河流,= 1;否则为0)。 -
nox
氮氧化物浓度(单位:每10百万)。 -
rm
每个住宅的平均房间数。 -
age
1940 年前建成的自有住房比例。 -
dis
到波士顿五个就业中心的加权距离 -
rad
通往放射性高速公路的可达性指数。 -
tax
每10,000美元的全额财产税率。 -
ptratio
按城镇划分的师生比。 -
black
1000(Bk - 0.63)² 其中 Bk 是按城镇划分的黑人比例。 -
lstat
低收入人群的百分比。 -
medv
自有住房的中位数价值(单位:1000 美元)。
在这些变量中,medv
是响应变量,而其他十三个变量是可能的预测变量。本分析的目标是拟合一个回归模型,最有效地解释 medv
的变化。
前十三列与 medv
响应变量之间存在关系。我们可以根据输入的十三列预测 medv
的值。
该数据集已通过 R 库(MASS
)提供,正如我们稍后将看到的那样,因此我们不必担心如何获取数据。
使用波士顿数据集进行神经网络回归
在本节中,我们将为 Boston
数据集运行回归神经网络。预测测试数据的 medv
值。训练和测试的划分比例为70:30。neuralnet
函数用于通过神经网络建模数据:
#####################################################################
###Chapter 2 - Introduction to Neural Networks - using R ############
###Simple R program to build, train, test regression neural networks#
#########################flename: Boston.r###########################
#####################################################################
library("neuralnet")
library(MASS)
set.seed(1)
data = Boston
max_data <- apply(data, 2, max)
min_data <- apply(data, 2, min)
data_scaled <- scale(data,center = min_data, scale = max_data - min_data)
index = sample(1:nrow(data),round(0.70*nrow(data)))
train_data <- as.data.frame(data_scaled[index,])
test_data <- as.data.frame(data_scaled[-index,])
n = names(data)
f = as.formula(paste("medv ~", paste(n[!n %in% "medv"], collapse = " + ")))
net_data = neuralnet(f,data=train_data,hidden=10,linear.output=T)
plot(net_data)
predict_net_test <- compute(net_data,test_data[,1:13])
predict_net_test_start <- predict_net_test$net.result*(max(data$medv)-min(data$medv))+min(data$medv)
test_start <- as.data.frame((test_data$medv)*(max(data$medv)-min(data$medv))+min(data$medv))
MSE.net_data <- sum((test_start - predict_net_test_start)²)/nrow(test_start)
Regression_Model <- lm(medv~., data=data)
summary(Regression_Model)
test <- data[-index,]
predict_lm <- predict(Regression_Model,test)
MSE.lm <- sum((predict_lm - test$medv)²)/nrow(test)
MSE.net_data
MSE.lm
###########################################################################
别担心,我们将逐行详细解释整个代码。
library("neuralnet")
library(MASS)
代码的前两行很简单,因为它们加载了我们将用于后续计算的库。具体来说,neuralnet
库将帮助我们构建和训练神经网络,而 MASS
库将帮助我们加载之前已详细介绍过的 Boston
数据集。
请记住,要安装 R 初始发行版中没有的库,必须使用 install.package
函数。这是安装软件包的主要函数。它接受一个包含名称的向量和一个目标库,从仓库下载软件包并进行安装。
例如,在我们的例子中,要安装 neuralnet
包,我们应该写:
install.neuralnet
最后需要强调的是,这个函数只应该使用一次,而不是每次运行代码时都使用。相反,通过以下命令加载库,并且每次运行代码时必须重复这一过程:
library (neuralnet)
set.seed
函数设置 R 随机数生成器的种子,这对创建可以复现的模拟或随机对象很有用:
set.seed(1)
每次你想获得可复现的随机结果时,都必须使用这个函数。在这种情况下,随机数是相同的,无论我们在序列中走多远,它们都会保持不变。
以下命令加载 Boston
数据集,该数据集如我们预期,包含在 MASS
库中,并将其保存到给定的框架中:
data = Boston
使用 str
函数查看任意 R 对象的紧凑结构。在我们的例子中,使用 str(data)
,我们将获得如下结果:
> str(data)
'data.frame': 506 obs. of 14 variables:
$ crim : num 0.00632 0.02731 0.02729 0.03237 0.06905 ...
$ zn : num 18 0 0 0 0 0 12.5 12.5 12.5 12.5 ...
$ indus : num 2.31 7.07 7.07 2.18 2.18 2.18 7.87 7.87 7.87 7.87 ...
$ chas : int 0 0 0 0 0 0 0 0 0 0 ...
$ nox : num 0.538 0.469 0.469 0.458 0.458 0.458 0.524 0.524 0.524 0.524 ...
$ rm : num 6.58 6.42 7.18 7 7.15 ...
$ age : num 65.2 78.9 61.1 45.8 54.2 58.7 66.6 96.1 100 85.9 ...
$ dis : num 4.09 4.97 4.97 6.06 6.06 ...
$ rad : int 1 2 2 3 3 3 5 5 5 5 ...
$ tax : num 296 242 242 222 222 222 311 311 311 311 ...
$ ptratio: num 15.3 17.8 17.8 18.7 18.7 18.7 15.2 15.2 15.2 15.2 ...
$ black : num 397 397 393 395 397 ...
$ lstat : num 4.98 9.14 4.03 2.94 5.33 ...
$ medv : num 24 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 ...
对给定对象获得的结果如下面的图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00057.jpeg
让我们回过头来解析代码:
max_data <- apply(data, 2, max)
min_data <- apply(data, 2, min)
data_scaled <- scale(data,center = min_data, scale = max_data - min_data)
我们需要这段代码来规范化数据。
请记住,在训练神经网络之前,规范化数据是一个好习惯。通过规范化,数据单位被消除,从而可以轻松地比较来自不同地点的数据。
这是构建神经网络中一个极其重要的步骤,因为它可以避免不必要的结果或非常复杂的训练过程,从而导致算法收敛问题。你可以选择不同的数据缩放方法(z-标准化、最小-最大缩放等)。在这个示例中,我们将使用最小-最大方法(通常称为特征缩放)将所有数据缩放到 [0,1] 范围内。实现这一点的公式如下:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00058.gif
在应用所选的规范化方法之前,必须先计算每个数据库列的最小值和最大值。为此,我们使用 apply
函数。该函数返回一个通过将函数应用于数组或矩阵的边缘而获得的向量、数组或列表。让我们理解所使用参数的含义。
max_data <- apply(data, 2, max)
apply
函数的第一个参数指定应用该函数的数据集,在我们的例子中是名为 data
的数据集。第二个参数必须包含一个向量,给出函数将应用于的下标。在我们的例子中,1
表示行,2
表示列。第三个参数必须包含要应用的函数;在我们的例子中是 max
函数。
为了对数据进行标准化,我们使用了scale
函数,这是一个通用函数,其默认方法是对数值矩阵的列进行居中和/或缩放。
index = sample(1:nrow(data),round(0.70*nrow(data)))
train_data <- as.data.frame(data_scaled[index,])
test_data <- as.data.frame(data_scaled[-index,])
在刚才建议的代码的第一行中,数据集被分割为70:30,目的是使用70百分比的数据来训练网络,剩余的30百分比用于测试网络。在第二行和第三行中,名为data
的数据框的内容被划分为两个新的数据框,分别称为train_data
和test_data
。
n = names(data)
f = as.formula(paste("medv ~", paste(n[!n %in% "medv"], collapse = " + ")))
net_data = neuralnet(f,data=train_data,hidden=10,linear.output=T)
plot(net_data)
到目前为止,所有工作仅用于准备数据。现在是时候构建网络了。为此,我们首先通过names
函数恢复所有变量名称。该函数可以获取或设置对象的名称。
接下来,我们构建了用于构建网络的formula
,因此我们使用neuralnet
函数来构建和训练网络。在这种情况下,我们将创建一个只有一个隐藏层,且有10
个节点的网络。最后,我们绘制了神经网络,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00059.jpeg
既然我们有了网络,接下来该做什么呢?当然,我们用它来进行预测。我们已经预留了30百分比的可用数据来进行预测:
predict_net_test <- compute(net_data,test_data[,1:13])
在我们的案例中,我们将该函数应用于test_data
数据集,仅使用前13
列,代表网络的输入变量:
predict_net_test_start <- predict_net_test$net.result*(max(data$medv)- min(data$medv))+min(data$medv)
test_start <- as.data.frame((test_data$medv)*(max(data$medv)-min(data$medv))+min(data$medv))
MSE.net_data <- sum((predict_net_test_start - test_start)²)/nrow(test_start)
那么,如何判断网络能够进行的预测是否准确呢?我们可以使用均方误差(MSE)作为衡量我们预测值与真实数据之间差距的标准。
在这方面,值得记住的是,在构建网络之前,我们已经对数据进行了标准化。现在,为了能够进行比较,我们需要退回一步,回到起始位置。一旦数据集的值恢复后,我们就可以通过以下公式计算MSE:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00060.jpeg
好的,我们现在已经计算了MSE,那么该用什么来进行比较呢?为了了解网络预测的准确性,我们可以构建一个线性回归模型:
Regression_Model <- lm(medv~., data=data)
summary(Regression_Model)
test <- data[-index,]
predict_lm <- predict(Regression_Model,test)
MSE.lm <- sum((predict_lm - test$medv)²)/nrow(test)
我们使用lm
函数构建了一个线性回归模型。该函数用于拟合线性模型,可以用于回归分析、单层方差分析和协方差分析。为了生成模型拟合结果的摘要,我们使用了summary
函数,返回了以下结果:
> summary(Regression_Model)
Call:
lm(formula = medv ~ ., data = data)
Residuals:
Min 1Q Median 3Q Max
-15.5944739 -2.7297159 -0.5180489 1.7770506 26.1992710
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 36.4594883851 5.1034588106 7.14407 0.00000000000328344 ***
crim -0.1080113578 0.0328649942 -3.28652 0.00108681 **
zn 0.0464204584 0.0137274615 3.38158 0.00077811 ***
indus 0.0205586264 0.0614956890 0.33431 0.73828807
chas 2.6867338193 0.8615797562 3.11838 0.00192503 **
nox -17.7666112283 3.8197437074 -4.65126 0.00000424564380765 ***
rm 3.8098652068 0.4179252538 9.11614 < 0.000000000000000222 ***
age 0.0006922246 0.0132097820 0.05240 0.95822931
dis -1.4755668456 0.1994547347 -7.39800 0.00000000000060135 ***
rad 0.3060494790 0.0663464403 4.61290 0.00000507052902269 ***
tax -0.0123345939 0.0037605364 -3.28001 0.00111164 **
ptratio -0.9527472317 0.1308267559 -7.28251 0.00000000000130884 ***
black 0.0093116833 0.0026859649 3.46679 0.00057286 ***
lstat -0.5247583779 0.0507152782 -10.34715 < 0.000000000000000222 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 4.745298 on 492 degrees of freedom
Multiple R-squared: 0.7406427, Adjusted R-squared: 0.7337897
F-statistic: 108.0767 on 13 and 492 DF, p-value: < 0.00000000000000022204
此外,对于回归模型,我们计算了平均均方误差(MSE)。最后,为了评估网络的性能,我们将其与使用相同数据库计算的多元线性回归模型进行比较,具体如下:
MSE.net_data
MSE.lm
结果如下:
> MSE.net_data
[1] 12.0692812
> MSE.lm
[1] 26.99265692
从结果分析中可以看出,神经网络的MSE
低于线性回归模型。
神经网络中的无监督学习
本节中,我们介绍了神经网络中的无监督学习模型,分别是竞争学习和 Kohonen 自组织映射(SOM)。Kohonen SOM 是由名为 Teuvo Kohonen 的教授发明的,它是一种将多维数据表示为更低维度的方法:1D或2D。它可以在没有监督的情况下对数据进行分类。无监督学习旨在发掘数据集中的隐藏模式,并将它们聚类成不同的数据类别。
有许多无监督学习技术,如 K 均值聚类、降维、EM 等。它们的共同特征是没有输入输出映射,我们仅根据输入值来创建一个输出的组或集合。
对于神经网络,它们可以用于无监督学习。它们可以将数据分组到不同的桶中(聚类),或者将原始数据抽象成不同的一组输出数据点(特征抽象或降维)。无监督技术比有监督技术需要更少的处理能力和内存。
在无监督神经网络中,没有目标变量,因此我们无法进行反向传播。相反,我们在没有误差度量的情况下持续调整权重,并尝试将相似的数据分组。我们将看到两种无监督神经网络方法:
-
竞争学习
-
Kohonen 自组织映射(SOM)
竞争学习
在这里,神经网络节点之间相互竞争,以争夺对输入数据子集的响应权。隐藏层被称为竞争层。每个竞争神经元都有自己的权重,我们计算每个输入向量与神经元权重之间的相似度。对于每个输入向量,隐藏神经元之间相互竞争,看哪个最类似于该输入向量:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00061.gif
输出神经元被认为是在为输入模式进行竞争。
-
在训练过程中,提供给定输入模式最高激活的输出神经元被声明为胜者,并且其权重被移向该输入模式,而其余神经元保持不变。
-
这种策略也叫做胜者全得,因为只有获胜的神经元会被更新:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00062.gif
让我们看一个简单的竞争学习算法示例,以在给定的输入数据中找到三个神经元:
-
我们将在输入层中设置三个输入神经元。每个神经元的输入是一个连续变量,假设每个输入神经元的权重是一个介于0.0和1.0之间的随机数。每个节点的输出是三个权重与其输入的乘积。
-
每个竞争层神经元接收权重和输入的乘积之和。
-
输出最大值的竞争层节点被视为胜者。然后,输入被分类为属于该节点对应的聚类。
-
胜者更新其每个权重,将权重从那些提供较弱信号的连接转移到那些提供较强信号的连接上。
因此,随着我们接收更多数据,每个节点都会收敛到它所代表的聚类中心。它对属于该聚类的输入激活得更强烈,而对属于其他聚类的输入激活得较弱。
竞争学习基本上有两个停止条件:
-
预定义的周期数:仅运行N个周期,这防止了算法在没有收敛的情况下运行过长时间。
-
最小权重更新值:算法会一直运行,直到我们得到最小的权重更新值。
Kohonen SOM
竞争学习的概念与邻域神经元相结合,得到了 Kohonen SOM。输出层中的每个神经元都有两个邻居。在竞争学习中,发出最大值的神经元会更新其权重,但在 SOM 中,邻域神经元也会以相对较慢的速度更新其权重。网络更新权重的邻域神经元数量取决于问题的维度。
对于一个2D问题,SOM 的表示方式如下:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00063.jpeg
从图示来看,SOM 是如何将不同的颜色映射到不同的聚类中的:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00064.jpeg
让我们一步一步地理解 Kohonen SOM 的工作原理:
-
初始化定义 SOM 结构的输入数量、聚类数量以及每个节点的权重。
-
从训练数据集中随机选择一个向量并将其呈现给网络。
-
检查网络中的每个节点,计算哪个节点的权重与输入向量最相似。获胜节点通常被称为最佳匹配单元(BMU)。
-
计算 BMU 的邻域半径。这个值开始时较大,通常设置为网络的半径,并随着每个时间步逐渐减小。
-
任何位于步骤 4 中计算的 BMU 半径范围内的神经元,都将进行调整,使其更加接近输入向量。神经元离 BMU 越近,其权重的改变越大。
-
对N次迭代重复执行步骤 2。
步骤会重复执行N次周期,或者直到获得最小的权重更新。
SOM 被应用于聚类(将数据分组到不同的桶中)、数据抽象(从输入中派生输出数据)和降维(减少输入特征的数量)等领域。SOM 以类似于多维尺度法(MDS)的方式处理问题,但不是最小化距离,而是尝试重新分组拓扑,换句话说,它们尽量保持相同的邻居。
让我们看看 R 中 SOM 实现的一个示例。kohonen
包是一个需要安装的包,用于在 R 中使用 SOM 相关的函数。
以下 R 程序说明了kohonen
包中的一些函数:
######################################################################
###Chapter 2 - Introduction to Neural Networks - using R ##########
###Usuervised ML technique using Kohonen package ####################
######################filename: kohonen.r#############################
######################################################################
library("kohonen")
data("wines")
str(wines)
head(wines)
View (wines)
set.seed(1)
som.wines = som(scale(wines), grid = somgrid(5, 5, "hexagonal"))
som.wines
dim(getCodes(som.wines))
plot(som.wines, main = "Wine data Kohonen SOM")
par(mfrow = c(1, 1))
plot(som.wines, type = "changes", main = "Wine data: SOM")
training = sample(nrow(wines), 150)
Xtraining = scale(wines[training, ])
Xtest = scale(wines[-training, ],
center = attr(Xtraining, "scaled:center"),
scale = attr(Xtraining, "scaled:scale"))
trainingdata = list(measurements = Xtraining,
vintages = vintages[training])
testdata = list(measurements = Xtest, vintages = vintages[-training])
mygrid = somgrid(5, 5, "hexagonal")
som.wines = supersom(trainingdata, grid = mygrid)
som.prediction = predict(som.wines, newdata = testdata)
table(vintages[-training], som.prediction$predictions[["vintages"]])
######################################################################
代码使用了一个葡萄酒数据集,该数据集包含一个有177
行和13
列的数据框;vintages
对象包含类标签。这些数据来自于意大利(皮埃蒙特)同一地区葡萄酒的化学分析,这些葡萄酒源自三种不同的葡萄品种,即Nebbiolo
、Barberas
和Grignolino
葡萄。Nebbiolo
葡萄酿成的葡萄酒叫做巴罗洛。数据包括每种葡萄酒中多种成分的含量,以及一些光谱变量。
现在,让我们查看每个代码部分的输出。
library("kohonen")
代码的第一行很简单,它加载了我们将用于后续计算的库。具体来说,kohonen
库将帮助我们训练 SOM。此外,支持对映射的查询和使用训练好的映射进行预测。
请记住,要安装 R 中初始分发版中没有的库,您必须使用install.package
函数。这是安装包的主要函数。它接受一个名称向量和目标库,从仓库中下载包并安装它们。
data("wines")
str(wines)
head(wines)
view (wines)
这些代码行加载了wines
数据集,正如我们所预期的,它包含在 R 的分发版中,并将其保存到一个名为data
的数据框中。然后,我们使用str
函数来紧凑显示数据集的结构。head
函数用于返回数据框的前部分或后部分。最后,view
函数用于调用数据框对象的电子表格样式数据查看器,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00065.jpeg
接下来,我们将继续分析代码:
set.seed(1)
som.wines = som(scale(wines), grid = somgrid(5, 5, "hexagonal"))
dim(getCodes(som.wines))
plot(som.wines, main = "Wine data Kohonen SOM")
加载葡萄酒数据并设置seed
以确保结果可重复后,我们调用som
函数来创建一个5x5的矩阵,其中需要对特征进行聚类。该函数内部执行kohonen
处理,结果可以通过特征聚类来看。共有25个聚类,每个聚类都有一组具有相似模式的特征,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00066.jpeg
代码的下一部分绘制了与som
迭代次数相关的最近单元的平均距离:
graphics.off()
par(mfrow = c(1, 1))
plot(som.wines, type = "changes", main = "Wine data: SOM")
下图展示了与迭代次数相关的最近单元的平均距离:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00067.jpeg
接下来,我们创建了一个training
数据集,包含150
行,和一个test
数据集,包含27
行。我们运行 SOM 并使用测试数据进行预测。这里使用了supersom
函数。此处的模型是监督式 SOM:
training = sample(nrow(wines), 150)
Xtraining = scale(wines[training, ])
Xtest = scale(wines[-training, ],
center = attr(Xtraining, "scaled:center"),
scale = attr(Xtraining, "scaled:scale"))
trainingdata = list(measurements = Xtraining,
vintages = vintages[training])
testdata = list(measurements = Xtest, vintages = vintages[-training])
mygrid = somgrid(5, 5, "hexagonal")
som.wines = supersom(trainingdata, grid = mygrid)
som.prediction = predict(som.wines, newdata = testdata)
table(vintages[-training], som.prediction$predictions[["vintages"]])
最后,我们调用table
函数,它使用交叉分类因素构建一个列出每个因素水平组合计数的列联表,如下所示:
> table(vintages[-training], som.prediction$predictions[["vintages"]])
Barbera Barolo Grignolino
Barbera 5 0 0
Barolo 0 11 0
Grignolino 0 0 11
kohonen
包具有标准的 SOM(自组织映射)功能,并提供了两个扩展功能:用于分类和回归的扩展,以及用于数据挖掘的扩展。同时,它还具有广泛的图形功能用于可视化。
下表列出了kohonen
包中可用的函数:
函数名称 | 描述 |
---|---|
som | 标准 SOM |
xyf , bdk | 监督式 SOM;两个并行映射 |
supersom | 带有多个并行映射的 SOM |
plot.kohonen | 通用绘图函数 |
summary.kohonen | 通用总结函数 |
map.kohonen | 将数据映射到最相似的神经元 |
predict.kohonen | 通用预测属性函数 |
总结
在本章中,我们探讨了机器学习领域,并观察了神经网络中的学习过程。我们学会了区分监督学习、无监督学习和强化学习。为了详细了解必要的流程,我们还学习了如何训练和测试模型。
随后,我们发现了数据周期的意义,以及数据必须如何收集、清理、转换,再输入模型进行学习。因此,我们深入研究了评估模型,查看测试阶段的预期值是否等于实际值。我们分析了可用于控制模型的不同度量标准,这些度量标准依赖于目标变量的状态。
然后我们发现了理解神经网络时一个重要的概念——反向传播算法,它基于计算来更新每个层级的权重和偏置。
最后,我们介绍了两个 R 中的实际程序,应用了neuralnet
和kohonen
库来实现学习过程。我们可以系统地使用这些基础知识进一步构建复杂的网络。
在下一章中,我们将探索深度神经网络(DNN)。我们将了解H2O
包的一些基础知识。总体而言,H2O
是一个高度用户友好的包,可以用于训练前馈网络或深度自编码器。它支持分布式计算,并提供 Web 界面。通过引入H2O
包,像使用任何其他 R 包一样,我们可以进行各种 DNN 建模和处理。
第三章:使用多层神经网络进行深度学习
深度学习是机器学习/人工智能领域的最新热门趋势。它的核心在于构建先进的神经网络。通过使多个隐藏层在神经网络模型中工作,我们可以处理复杂的非线性数据表示。我们通过基础神经网络创建深度学习。深度学习在现实生活中有许多应用案例,例如无人驾驶汽车、医学诊断、计算机视觉、语音识别、自然语言处理(NLP)、手写识别、语言翻译等多个领域。
在本章中,我们将讨论深度学习过程:如何训练、测试和部署深度神经网络(DNN)。我们将探讨 R 中可用于处理 DNN 的不同包。我们将了解如何使用neuralnet
包构建和训练 DNN。最后,我们将分析一个使用 h2o 平台训练和建模 DNN 的例子,h2o 是一个可扩展的开源内存学习平台,用于在大数据集上创建模型并实施高精度的预测方法。
本章涵盖的主题如下:
-
DNN 的类型
-
深度学习的 R 包
-
使用
neuralnet
训练和建模 DNN -
h2o
库
在本章结束时,我们将理解深度学习的基本概念,以及如何在 R 环境中实现它。我们将了解不同类型的 DNN。我们将学习如何训练、测试和部署模型。我们将知道如何使用h2o
训练和建模 DNN。
深度神经网络(DNN)介绍
随着大数据处理基础设施、GPU 和 GP-GPU 的出现,我们现在能够克服浅层神经网络的挑战,即过拟合和梯度消失问题,使用各种激活函数和 L1/L2 正则化技术。深度学习可以轻松高效地处理大量标注和未标注的数据。
如前所述,深度学习是机器学习中的一类,其中学习发生在多个神经网络层次上。标准的 DNN 图示如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00068.jpeg
从前面的图分析中,我们可以注意到与我们迄今为止研究的神经网络之间的显著相似性。然后,我们可以放心,尽管它看起来可能不一样,深度学习实际上只是神经网络的扩展。在这方面,我们在前几章中看到的大部分内容仍然适用。简而言之,DNN 是一个包含两个或更多隐藏层的多层神经网络。这里没有什么特别复杂的内容。通过添加更多层和每层更多神经元,我们增加了模型对训练数据的专门化,但却降低了其在测试数据上的性能。
正如我们所预期的,DNN 是 ANN 的衍生物。通过增加隐藏层的数量,我们构建了 DNN。DNN 有很多变种,以下列举了几个不同的术语:
-
深度信念网络(DBN):它通常是一个前馈网络,数据从一层流向另一层,而没有回流。它至少有一层隐藏层,并且可以有多个隐藏层,从而增加复杂性。
-
限制玻尔兹曼机(RBM):它只有一个隐藏层,且同一组内的节点之间没有连接。它是一个简单的多层感知器(MLP)神经网络模型。
-
循环神经网络(RNN)和长短期记忆网络(LSTM):这些网络在组内和组间的数据流动是双向的。
与任何机器学习算法一样,DNN(深度神经网络)也需要构建、训练和评估的过程。以下图展示了深度学习的基本工作流程:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00069.jpeg
我们在前一图中看到的工作流程与典型的监督学习算法非常相似。但它与其他机器学习算法有何不同呢?
几乎所有的机器学习算法在识别原始输入数据的特征时都会显示出它们的局限性,尤其是在数据复杂且缺乏明显顺序的情况下,比如图像。通常,这种局限性是通过人类的帮助来突破的,人类负责识别机器无法做到的部分。深度学习则去除了这一环节,依赖于训练过程通过输入示例找到最有用的模型。在这种情况下,人类干预仍然是必要的,以便在开始训练之前做出选择,但自动发现特征大大简化了过程。与机器学习提供的其他解决方案相比,神经网络特别具有优势的地方在于其模型的强大泛化能力。
这些特性使得深度学习在几乎所有需要自动学习的任务中都非常有效,尤其是在复杂的层级数据情境下表现尤为突出。它的基础人工神经网络(ANN)形式表现为高度非线性的表示;这些表示通常由多个层以及非线性变换和定制的架构组成。
从本质上讲,深度学习在处理来自现实世界的杂乱数据时表现得非常出色,使其成为未来几年多个技术领域的关键工具。直到最近,它仍然是一个让人感到陌生且令人生畏的领域,但它的成功带来了许多极好的资源和项目,使得开始学习它比以往任何时候都更加容易。
现在我们了解了什么是 DNN,让我们看看 R 开发环境为我们处理这一特定主题提供了哪些工具。
R for DNNs
在前一部分中,我们澄清了一些深度学习基础的关键概念。我们还了解了深度学习在应用时特别方便的特点。此外,它的快速普及也得益于各种编程语言中框架和库的广泛可用性。
R 编程语言因其极易使用而被科学家和程序员广泛采用。此外,R 还有丰富的库集合,能够进行专业的数据可视化和分析,使用最流行的算法。深度学习算法的快速扩散促使了越来越多的深度学习包的创建,甚至在 R 中也不例外。
以下表格展示了使用 R 进行深度学习的各种包/接口:
CRAN 包 | 支持的神经网络分类 | 基础语言/供应商 |
---|---|---|
MXNet | 前馈神经网络,卷积神经网络(CNN) | C/C++/CUDA |
darch | RBM,DBN | C/C++ |
deepnet | 前馈神经网络,RBM,DBN,自编码器 | R |
h2o | 前馈神经网络,自编码器 | Java |
nnet 和 neuralnet | 前馈神经网络 | R |
Keras | 多种深度神经网络(DNN) | Python/keras.io |
TensorFlow | 多种深度神经网络(DNN) | C++、Python/Google |
MXNet
是一个现代的、可移植的深度学习库,支持多台机器。世界上最大的公司和大学都已将 MXNet
作为机器学习框架。这些公司包括亚马逊、英特尔、Data、百度、微软、Wolfram Research、卡内基梅隆大学、麻省理工学院、华盛顿大学和香港科技大学。
MXNet
是一个开源框架,支持快速建模,并在多种编程语言中支持灵活的编程模型(C++、Python、Julia、MATLAB、JavaScript、Go、R、Scala、Perl 和 Wolfram Language)。
MXNet
框架支持 R 编程语言。MXNet
R 包提供灵活高效的 GPU 计算和最先进的 R 深度学习。它允许我们在 R 中使用多个 GPU 进行无缝的张量/矩阵计算。它还允许我们在 R 中构建和定制最先进的深度学习模型,并将其应用于图像分类、数据科学挑战等活动。
darch
框架基于 G. E. Hinton 和 R. R. Salakhutdinov 编写的代码,并在 MATLAB 环境中实现 DBN。该包能够生成多层神经网络(深度架构),并通过作者开发的创新方法对其进行构建。该方法提供了一种与 G. Hinton(2002)发布的对比发散法相结合的预形成方法,并通过常见的训练算法如反向传播或共轭梯度法进行微调。此外,微调监督可以通过 maxout 和 dropout 进行改善,这两种是近年来为提高深度学习微调效果而开发的技术。
deepnet
库是一个相对较小但功能强大的包,提供多种架构供选择。该库实现了一些深度学习架构和神经网络算法,包括反向传播、RBM、DBN、深度自编码器等。与我们分析的其他库不同,它是专为 R 编写的。它有几个功能,包括:
-
nn.train
:用于通过 BP 训练单个或多个隐藏层的神经网络 -
nn.predict
:用于通过训练好的神经网络预测新的样本 -
dbn.dnn.train
:用于训练一个由 DBN 初始化权重的 DNN -
rbm.train
:用于训练一个 RBM
h2o
R 包具有构建普通线性回归、K-means、朴素贝叶斯、主成分分析 (PCA)、森林和深度学习(多层 neuralnet
模型)等功能。h2o
是一个外部包,不属于 CRAN,使用 Java 构建,支持多种平台。它是一个开源的大数据数学引擎,能够并行分布式计算机器学习算法。
在前几章中我们广泛讨论了 nnet
和 neuralnet
包。这是两个用于管理 R 中神经网络的包。它们还能够构建和训练多核神经网络,因此依赖于深度学习。
Keras
是一个用 Python 编写的开源神经网络库。它旨在支持快速实验,专注于最小化、模块化和可扩展性。该库包含许多常用神经网络构建块的实现,如层、目标、激活函数、优化器,以及一系列使得处理图像和文本数据更简单的工具。代码托管在 GitHub 上,社区支持论坛包括 GitHub 问题页面、Gitter 频道和 Slack 频道。
TensorFlow
是一个开源的机器学习软件库。它包含一个用于构建和训练神经网络的系统,用来检测和解码模式与关联,方法类似于人类学习采用的方式。它被用于搜索以及 Google 的生产环境中。
使用 neuralnet 训练多层神经网络
在理解了深度学习的基本原理后,是时候将所学技能应用到实际案例中了。我们在上一节中看到,两个我们熟悉的库已经列出在 R for DNNs 部分的可用包中。我指的是我们在前几章中通过实际示例学习使用的 nnet
和 neuralnet
包。由于我们已经对 neuralnet
库有了一些实践经验,我认为我们应该从这里开始,实际探索深度学习的精彩世界。
首先,我们介绍将用于构建和训练网络的数据集。它名为 College
数据集,包含大量美国大学的统计数据,数据来自 1995 年 US News and World Report 的刊物。该数据集来自由卡内基梅隆大学维护的 StatLib
库,并曾在 ASA Section on Statistical Graphics 中使用。
对我们来说,情况更加简化,因为我们不需要获取数据然后导入到 R 中,因为这些数据已包含在 R 包中。我指的是 ISLR
包。我们只需要安装包并加载相应的库。但我们稍后会看到,在详细解释代码时会提到这一点。现在,让我们仅仅查看数据集 College
的内容。它是一个包含 777
个观测值的 dataframe,包含以下 18
个变量:
-
Private
:一个包含No
和Yes
两个级别的因子,表示私立或公立大学 -
Apps
:收到的申请数量 -
Accept
:被录取的申请数量 -
Enroll
:新入学学生人数 -
Top10perc
:来自高年级前 10%学生的新生比例 -
Top25perc
:来自高年级前 25%学生的新生比例 -
F.Undergrad
:全日制本科生人数 -
P.Undergrad
:兼职本科生人数 -
Outstate
:州外学费 -
Room.Board
:住宿和餐饮费用 -
Books
:预计书籍费用 -
Personal
:预计个人开销 -
PhD
:拥有博士学位的教师比例 -
Terminal
:拥有终极学位的教师比例 -
S.F.Ratio
:师生比 -
perc.alumni
:捐赠校友的比例 -
Expend
:每个学生的教学支出 -
Grad.Rate
:毕业率
我们的目标是建立一个多层神经网络,能够根据其他 17
个变量的值预测学校是公立还是私立:
###########################################################################
#############Chapter 3 - Deep Learning with neuralnet###################### ###########################################################################
library("neuralnet")
library(ISLR)
data = College
View(data)
max_data <- apply(data[,2:18], 2, max)
min_data <- apply(data[,2:18], 2, min)
data_scaled <- scale(data[,2:18],center = min_data, scale = max_data - min_data)
Private = as.numeric(College$Private)-1
data_scaled = cbind(Private,data_scaled)
index = sample(1:nrow(data),round(0.70*nrow(data)))
train_data <- as.data.frame(data_scaled[index,])
test_data <- as.data.frame(data_scaled[-index,])
n = names(train_data)
f <- as.formula(paste("Private ~", paste(n[!n %in% "Private"], collapse = " + ")))
deep_net = neuralnet(f,data=train_data,hidden=c(5,3),linear.output=F)
plot(deep_net)
predicted_data <- compute(deep_net,test_data[,2:18])
print(head(predicted_data$net.result))
predicted_data$net.result <- sapply(predicted_data$net.result,round,digits=0)
table(test_data$Private,predicted_data$net.result)
和往常一样,我们将逐行分析代码,详细解释所有用于捕获结果的功能。
library("neuralnet")
library(ISLR)
和往常一样,初始代码的前两行用于加载运行分析所需的库。
请记住,要安装 R 初始分发版中没有的库,必须使用install.package
函数。这是安装包的主要函数。它接收一个名称向量和一个目标库,从仓库下载包并进行安装。此函数应该仅使用一次,而不是每次运行代码时都使用。
data = College
View(data)
该命令加载了 College
数据集,正如我们所预期,它包含在 ISLR
库中,并将其保存到一个给定的数据框中。使用 View
函数查看任意 R 对象的结构的简洁显示。以下图显示了 College
数据集中的部分数据:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00070.jpeg
每个大学都有一系列统计数据,如何表示;行表示观察,列则呈现所检测的特征:
max_data <- apply(data[,2:18], 2, max)
min_data <- apply(data[,2:18], 2, min)
data_scaled <- scale(data[,2:18],center = min_data, scale = max_data - min_data)
在这段代码中,我们需要对数据进行归一化。
请记住,在训练神经网络之前进行数据归一化是良好的实践。通过归一化,数据单位被消除,允许你轻松比较来自不同地点的数据。
对于这个例子,我们将使用最小-最大方法(通常称为特征缩放)来将所有数据缩放到*【0,1】*的范围内。在应用所选择的归一化方法之前,必须计算每个数据库列的最小值和最大值。这个过程在我们分析的第二章《神经网络中的学习过程》示例中已经采用。
最后一行通过采用预期的归一化规则来缩放数据。请注意,我们仅对最后17行(从2到18)进行了归一化,排除了第一列Private
,该列包含有No
和Yes
两个层次的因子,表示私立或公立大学。这个变量将是我们即将构建的网络中的目标。为了验证我们所说的内容,可以检查数据集中变量的类型。为此,我们将使用str
函数,以紧凑的方式显示一个任意 R 对象的结构:
> str(data)
'data.frame': 777 obs. of 18 variables:
$ Private : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 2 2 2 2 2 ...
$ Apps : num 1660 2186 1428 417 193 ...
$ Accept : num 1232 1924 1097 349 146 ...
$ Enroll : num 721 512 336 137 55 158 103 489 227 172 ...
$ Top10perc : num 23 16 22 60 16 38 17 37 30 21 ...
$ Top25perc : num 52 29 50 89 44 62 45 68 63 44 ...
$ F.Undergrad: num 2885 2683 1036 510 249 ...
$ P.Undergrad: num 537 1227 99 63 869 ...
$ Outstate : num 7440 12280 11250 12960 7560 ...
$ Room.Board : num 3300 6450 3750 5450 4120 ...
$ Books : num 450 750 400 450 800 500 500 450 300 660 ...
$ Personal : num 2200 1500 1165 875 1500 ...
$ PhD : num 70 29 53 92 76 67 90 89 79 40 ...
$ Terminal : num 78 30 66 97 72 73 93 100 84 41 ...
$ S.F.Ratio : num 18.1 12.2 12.9 7.7 11.9 9.4 11.5 13.7 11.3 11.5 ...
$ perc.alumni: num 12 16 30 37 2 11 26 37 23 15 ...
$ Expend : num 7041 10527 8735 19016 10922 ...
$ Grad.Rate : num 60 56 54 59 15 55 63 73 80 52 ...
如预期的那样,第一个变量是Factor
类型,具有两个levels
:No
和Yes
。对于剩余的17个变量,它们是数值型的。正如在第一章《神经网络与人工智能概念》中预期的那样,只有数值数据可以用于模型,因为神经网络是一个具有逼近函数的数学模型。所以我们遇到了第一个变量Private
的问题。别担心,这个问题可以很容易地解决;只需将其转换为数值变量即可:
Private = as.numeric(College$Private)-1
data_scaled = cbind(Private,data_scaled)
在这方面,第一行将Private
变量转换为数值型,而第二行代码则用于用该变量和剩余的17个适当归一化的变量重新构建数据集。为此,我们使用cbind
函数,它接受一系列向量、矩阵或数据框作为参数,并按列或行分别组合:
index = sample(1:nrow(data),round(0.70*nrow(data)))
train_data <- as.data.frame(data_scaled[index,])
test_data <- as.data.frame(data_scaled[-index,])
现在是时候将数据拆分用于网络的训练和测试了。在刚才建议的代码的第一行中,数据集被拆分为70:30,目的是将70%的数据用于训练网络,剩余的30%用于测试网络。在第三行中,名为 data 的数据框被细分为两个新的数据框,分别称为train_data
和test_data
:
n = names(train_data)
f <- as.formula(paste("Private ~", paste(n[!n %in% "Private"], collapse = " + ")))
在这段代码中,我们首先使用names
函数恢复所有变量名。该函数用于获取或设置对象的名称。接下来,我们构建将用于构建网络的公式,因此我们使用neuralnet
函数来构建和训练网络。到目前为止,一切只是用于准备数据。现在是时候构建网络了:
deep_net = neuralnet(f,data=train_data,hidden=c(5,3),linear.output=F)
这是代码中的关键行。这里,网络被构建并训练完成;让我们详细分析一下。我们曾预期使用neuralnet
库来构建我们的 DNN。但与我们之前构建单隐层网络的情况相比,发生了什么变化呢?一切都发生在hidden
参数的设置上。
记住,hidden
参数必须包含一个整数向量,指定每一层中隐藏神经元(顶点)的数量。
在我们的案例中,我们将隐藏层设置为包含向量*(5,3)*,这对应于两个隐藏层,第一个隐藏层有五个神经元,第二个隐藏层有三个神经元。
plot(deep_net)
前一行简单地绘制了网络图,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00071.jpeg
如我们所见,网络已经构建并训练完成,我们只需要验证其预测能力:
predicted_data <- compute(deep_net,test_data[,2:18])
print(head(predicted_data$net.result))
为了预测保留用于测试的数据,我们可以使用compute
方法。这是nn
类对象的方法,通常由neuralnet
函数生成。给定一个经过训练的神经网络,它计算所有神经元在特定自变量向量上的输出。确保新矩阵或数据框中的自变量顺序与原始神经网络中的一致是至关重要的。然后,为了可视化,使用print
函数展示预测结果的前几行,如下所示:
> print(head(predicted_data$net.result))
[,1]
Abilene Christian University 0.1917109322
Adelphi University 1.0000000000
Adrian College 1.0000000000
Agnes Scott College 1.0000000000
Albertus Magnus College 1.0000000000
Albion College 1.0000000000
如所见,预测结果以小数形式提供,接近预期的两个类别的值(一和零),但并不完全等于这些值。我们需要精确假设这些值,以便与当前值进行比较。为此,我们将使用sapply()
函数将这些结果四舍五入到零或一类别,从而与测试标签进行评估:
predicted_data$net.result <- sapply(predicted_data$net.result,round,digits=0)
正如预期的那样,sapply()
函数将两个可用类别的预测结果进行了四舍五入。现在我们拥有了进行比较所需的一切,以评估 DNN 作为预测工具的效果:
table(test_data$Private,predicted_data$net.result)
为了进行比较,我们依赖于混淆矩阵。构建它时,只需使用table
函数。实际上,table
函数利用交叉分类因子来构建每个因子水平组合的计数列联表。
混淆矩阵是一种特定的表格布局,用于可视化算法的表现。每一行代表实际类别中的实例,而每一列代表预测类别中的实例。术语“混淆矩阵”源于它能清楚地显示系统是否将两个类别混淆。
那么,让我们看看得到的结果:
> table(test_data$Private,predicted_data$net.result)
0 1
0 49 8
1 9 167
让我们理解一下这些结果。首先,让我们记住,在混淆矩阵中,主对角线上的术语表示正确预测的数量,即预测类别与实际类别的实例相符的数量。看来在我们的模拟中,一切顺利。事实上,我们得到了49
个类别0
(No
)的结果,和167
个类别1
(Yes
)的结果。但现在让我们分析另外两个术语,它们表示模型犯的错误。
如第二章中定义的,神经网络中的学习过程,8
是 FN,9
是 FP。在这方面,我们回顾一下,FN 表示实际数据中为负的预测为正,而 FP 表示实际数据中为正的预测为负。我们可以通过再次使用table
函数来检查这一点:
> table(test_data$Private)
0 1
57 176
这些表示实际结果,特别是,57
个结果属于类别0
,176
个结果属于类别1
。通过求和混淆矩阵中行的数据,我们实际上得到了这些值的实际结果:
> 49 + 8
[1] 57
> 9 + 167
[1] 176
现在我们再次使用table
函数来获取预测数据中的出现次数:
> table(predicted_data$net.result)
0 1
58 175
这些表示预测结果,特别是,58
个结果属于类别0
,175
个结果属于类别1
。通过求和混淆矩阵中列的数据,我们实际上得到了这些值的结果:
> 49 + 9
[1] 58
> 8 + 167
[1] 175
在这一点上,我们通过使用混淆矩阵中的数据来计算模拟的准确率。让我们记住,准确率由以下公式定义:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00072.gif
这里:
TP = 真阳性
TN = 真负性
FP = 假阳性
FN = 真负性
让我们通过以下代码示例来看一下:
> Acc = (49 + 167) / (49 + 167 + 9 + 8)
> Acc
[1] 0.9270386266
我们得到了大约 93%的准确率,确认我们的模型能够很好地预测数据并取得良好结果。
使用 H2O 训练和建模 DNN
在本节中,我们将介绍使用h2o
训练和建模 DNN 的示例。h2o
是一个开源的内存中可扩展的机器学习和 AI 平台,用于构建大数据集的模型并实现高准确率的预测方法。h2o
库在许多组织中被大规模应用,用于实现数据科学并提供构建数据产品的平台。h2o
可以运行在单个笔记本电脑上,也可以在高性能可扩展服务器的集群上运行。它运行非常快,充分利用了机器架构的进展和 GPU 处理。它具有高准确度的深度学习、神经网络和其他机器学习算法的实现。
如前所述,h2o
R 包包含用于构建一般线性回归、K 均值、朴素贝叶斯、PCA、森林和深度学习(多层neuralnet
模型)等功能。h2o
包是一个外部包,不属于 CRAN,使用 Java 构建。它适用于多种平台。
我们将通过以下代码在 R 中安装h2o
:
install.packages("h2o")
我们得到了以下结果:
> install.packages("h2o")
Installing package into ‘C:/Users/Giuseppe/Documents/R/win-library/3.4’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/3.4/h2o_3.10.5.3.zip'
Content type 'application/zip' length 73400625 bytes (70.0 MB)
downloaded 70.0 MB
package ‘h2o’ successfully unpacked and MD5 sums checked
The downloaded binary packages are in
C:\Users\Giuseppe\AppData\Local\Temp\RtmpGEc5iI\downloaded_packages
为了测试这个包,让我们通过以下示例来使用流行的数据集 Irisdataset
。我所指的是鸢尾花数据集,这是英国统计学家和生物学家 Ronald Fisher 在其 1936 年的论文《多重测量在分类问题中的应用》中引入的一个多变量数据集,用作线性判别分析的例子。
数据集包含来自三种鸢尾花(鸢尾花 setosa
,鸢尾花 virginica
和鸢尾花 versicolor
)的 50 个样本。每个样本测量了四个特征:花萼和花瓣的长度和宽度,单位是厘米。
包含以下变量:
-
Sepal.Length
单位:厘米 -
Sepal.Width
单位:厘米 -
Petal.Length
单位:厘米 -
Petal.Width
单位:厘米 -
类别:
setosa
,versicolour
,virginica
下图紧凑地显示了 iris
数据集的结构:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00073.jpeg
我们希望构建一个分类器,能够根据花萼和花瓣的大小来对花的种类进行分类:
##########################################################################
#################Chapter 3 - Deep Learning with H2O and R################# ##########################################################################
library(h2o)
c1=h2o.init(max_mem_size = "2G",
nthreads = 2,
ip = "localhost",
port = 54321)
data(iris)
summary(iris)
iris_d1 <- h2o.deeplearning(1:4,5,
as.h2o(iris),hidden=c(5,5),
export_weights_and_biases=T)
iris_d1
plot(iris_d1)
h2o.weights(iris_d1, matrix_id=1)
h2o.weights(iris_d1, matrix_id=2)
h2o.weights(iris_d1, matrix_id=3)
h2o.biases(iris_d1, vector_id=1)
h2o.biases(iris_d1, vector_id=2)
h2o.biases(iris_d1, vector_id=3)
#plot weights connecting `Sepal.Length` to first hidden neurons
plot(as.data.frame(h2o.weights(iris_d1, matrix_id=1))[,1])
##########################################################################
现在,让我们通过代码来了解如何应用 h2o
包解决模式识别问题。
在继续之前,必须说明的是,在 R 中运行 h2o
需要 Java 8 运行时。请提前验证您计算机上安装的 Java 版本,并最终从 www.java.com/en/download/win10.jsp
下载 Java 8 版本。
下图展示了来自 Oracle 网站的 Java 下载页面:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00074.jpeg
此外,h2o
包是由一些必需的包构建的;因此,为了正确安装 h2o
包,请记得安装以下依赖项,所有这些都可以在 CRAN 中找到:
-
RCurl
-
bitops
-
rjson
-
jsonlite
-
statmod
-
tools
在成功安装 h2o
包后,我们可以继续加载库:
library(h2o)
此命令将在 R 环境中加载该库。返回以下信息:
Your next step is to start H2O:
> h2o.init()
For H2O package documentation, ask for help:
> ??h2o
After starting H2O, you can use the Web UI at http://localhost:54321
For more information visit http://docs.h2o.ai
c1=h2o.init(max_mem_size = "2G",
nthreads = 2,
ip = "localhost",
port = 54321)
我们按照 R 提示中的说明进行操作:
c1=h2o.init(max_mem_size = "2G",
nthreads = 2,
ip = "localhost",
port = 54321)
h20.init
函数初始化 h2o
引擎,最大内存大小为 2 GB,并使用两个并行核心。初始化 h2o
控制台后,我们运行此脚本时会收到以下信息:
> c1=h2o.init(max_mem_size = "2G", nthreads = 2)
H2O is not running yet, starting it now...
Note: In case of errors look at the following log files:
C:\Users\Giuseppe\AppData\Local\Temp\RtmpU3xPvT/h2o_Giuseppe_started_from_r.out
C:\Users\Giuseppe\AppData\Local\Temp\RtmpU3xPvT/h2o_Giuseppe_started_from_r.err
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
Starting H2O JVM and connecting: . Connection successful!
R is connected to the H2O cluster:
H2O cluster uptime: 6 seconds 912 milliseconds
H2O cluster version: 3.10.5.3
H2O cluster version age: 2 months and 9 days
H2O cluster name: H2O_started_from_R_Giuseppe_woc815
H2O cluster total nodes: 1
H2O cluster total memory: 1.78 GB
H2O cluster total cores: 4
H2O cluster allowed cores: 2
H2O cluster healthy: TRUE
H2O Connection ip: localhost
H2O Connection port: 54321
H2O Connection proxy: NA
H2O Internal Security: FALSE
R Version: R version 3.4.1 (2017-06-30)
一旦 h2o
被初始化,控制台可以通过任何浏览器访问,只需指向 localhost:54321
。h2o
库运行在 JVM 上,控制台允许:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00075.jpeg
控制台直观易用,并提供与 h[2]o 引擎交互的界面。我们可以训练和测试模型,并基于这些模型进行预测。第一个文本框标记为 CS,允许我们输入要执行的例程。assist
命令会列出可用的例程。让我们继续分析以下示例代码。
data(iris)
summary(iris)
第一个命令加载了 iris
数据集,该数据集包含在数据集库中,并将其保存在指定的数据框中。然后,我们使用 summary
函数来生成数据集结果的摘要。该函数调用依赖于第一个参数的类的特定方法。结果如下所示:
> summary(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width
Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
Median :5.800 Median :3.000 Median :4.350 Median :1.300
Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500 Species
setosa :50
versicolor:50
virginica :50
让我们分析接下来的代码:
iris_d1 <- h2o.deeplearning(1:4,5,
as.h2o(iris),hidden=c(5,5),
export_weights_and_biases=T)
h2o.deeplearning
函数是 h2o
中的一个重要函数,可用于多种操作。此函数使用 CPU 构建 DNN 模型,并在 H2OFrame
上构建一个前馈多层人工神经网络(ANN)。hidden
参数用于设置隐藏层的数量和每个隐藏层的神经元数量。在我们的例子中,我们设置了一个具有两个隐藏层的 DNN,每个隐藏层有 5
个神经元。最后,参数 export_weights_and_biases
告诉我们,权重和偏置可以存储在 H2OFrame
中,并可以像其他数据框一样访问以进行进一步处理。
在继续代码分析之前,需要做一个澄清。细心的读者可能会问,基于什么评估我们选择了每个隐藏层的隐藏层数量和神经元数量。不幸的是,没有一个精确的规则,甚至没有一个数学公式可以帮助我们确定哪些数字适合特定问题。这是因为每个问题都不同,每个网络对系统的近似方式也不同。那么,是什么使得一个模型和另一个模型之间有所不同呢?答案显而易见,而且非常清楚:那就是研究者的经验。
我能给出的建议,来源于我在数据分析方面的丰富经验,就是尝试,尝试,再尝试。实验活动的秘密就在于此。在神经网络的情况下,这意味着要尝试搭建不同的网络,然后验证它们的性能。例如,在我们的例子中,我们可以从一个包含两个隐藏层且每个隐藏层有 100 个神经元的网络开始,然后逐渐减少这些值,最终达到我在示例中提出的值。这个过程可以通过 R 所拥有的迭代结构来自动化。
然而,有些事情可以说,例如,对于神经元数量的最佳选择,我们需要知道:
-
神经元数量过少会导致系统误差较大,因为预测因子可能过于复杂,难以为少量神经元所捕捉。
-
神经元数量过多会导致训练数据过拟合,且泛化效果差。
-
每个隐藏层的神经元数量应介于输入层和输出层的大小之间,可能是其均值。
-
每个隐藏层的神经元数量不应超过输入神经元数量的两倍,否则你可能会严重过拟合。
话虽如此,我们回到代码:
iris_d1
在 R 提示符下,此命令打印出我们刚创建的模型的简要描述,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00076.jpeg
通过仔细分析前面的图,我们可以清晰地区分模型的细节以及混淆矩阵。现在让我们看看训练过程是如何进行的:
plot(iris_d1)
plot
方法会根据 h2o 模型的类型来选择正确的评分历史记录。参数仅限于特定模型类型的评分历史记录中可用的内容,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00077.gif
在此图中,展示了训练分类误差与迭代次数(epochs)的关系,我们可以看到梯度下降过程以及误差随着迭代次数的增加而减少。数据集的迭代次数(流式处理)可以是小数,默认值为10
:
h2o.weights(iris_d1, matrix_id=1)
h2o.weights(iris_d1, matrix_id=2)
h2o.weights(iris_d1, matrix_id=3)
h2o.biases(iris_d1, vector_id=1)
h2o.biases(iris_d1, vector_id=2)
h2o.biases(iris_d1, vector_id=3)
代码的最后六行简单地打印出三种鸢尾花物种的权重和偏差的简要总结,如下所示:
> h2o.weights(iris_d1, matrix_id=1)
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 -0.013207575 -0.06818321 -0.02756812 0.092810206
2 0.036195096 0.02568028 0.05634377 0.035429616
3 -0.002411760 -0.11541270 0.08219513 0.001957144
4 0.091338813 -0.03271343 -0.25603485 -0.205898494
6 -0.151234403 0.01785624 -0.11815275 -0.110585481
[200 rows x 4 columns]
> h2o.biases(iris_d1, vector_id=1)
C11 0.48224932 0.47699773 0.48994124 0.49552965 0.48991496 0.4739439
[200 rows x 1 column]
出于空间原因,我们将自己限制只查看setosa
物种的权重和偏差。在以下代码中,我们再次使用了绘图函数:
plot(as.data.frame(h2o.weights(iris_d1, matrix_id=1))[,1])
此命令绘制了第一隐藏层神经元的权重与花萼长度的关系,如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00078.gif
现在,让我们花点时间分析结果;特别是,我们恢复了刚才在模型摘要屏幕上看到的混淆矩阵。要调用混淆矩阵,我们可以使用h2o.confusionMatrix
函数,如下代码示例所示,它从h2o
对象中获取单个或多个混淆矩阵。
> h2o.confusionMatrix(iris_d1)
Confusion Matrix: Row labels: Actual class; Column labels: Predicted class
setosa versicolor virginica Error Rate
setosa 50 0 0 0.0000 = 0 / 50
versicolor 0 48 2 0.0400 = 2 / 50
virginica 0 2 48 0.0400 = 2 / 50
Totals 50 50 50 0.0267 = 4 / 150
从混淆矩阵的分析中可以看出,模型能够正确地分类三种花卉物种,只犯了四个错误。这些错误相当分布在两个物种中:versicolor
和virginica
。然而,setosa
物种在所有50
次出现中都被正确分类。那么,为什么会这样呢?为了理解这一点,我们来看一下原始数据。在多维数据的情况下,最好的方法是绘制数据集中选定变量的散点图矩阵:
> pairs(iris[1:4], main = "Scatterplot matrices of Iris Data", pch = 21, bg = c("red", "green3", "blue")[unclass(iris$Species)])
结果如下图所示:
https://github.com/OpenDocCN/freelearn-dl-pt6-zh/raw/master/docs/nn-r/img/00079.gif
让我们详细分析一下刚才提出的图表。变量沿着从左上到右下的对角线排列。然后,每个变量都会与其他变量进行绘制。例如,第一列第二个框是Sepal.Length
与Sepal.Width
的单独散点图,Sepal.Length
作为X轴,Sepal.Width
作为Y轴。这个图在第二列的第一个图中得到了复制。从本质上讲,整个散点图右上角的框是左下角图的镜像。
从刚刚看到的图表分析中,可以看出versicolor
和virginica
物种的边界重叠。这使我们明白,当模型在这些区域进行分类时,可能会出现错误。我们可以看到setosa
物种的情况,它的边界与其他花卉物种相距甚远,且没有任何分类错误。
也就是说,我们根据花瓣和萼片的大小来评估模型在分类花卉物种方面的准确性:
> h2o.hit_ratio_table(iris_d1)
Top-3 Hit Ratios:
k hit_ratio
1 1 0.973333
2 2 1.000000
3 3 1.000000
结果表明,基于第一个假设的模拟将物种的分类准确率排到了97百分比。我认为这是一个不错的结果;模型拟合数据非常好。但我们如何衡量这个特性呢?找到更好拟合的方法之一是计算决定系数(R-squared)。在h2o
中计算 R-squared 的方法是使用h2o.r2
方法:
> h2o.r2(iris_d1)
[1] 0.9596034
现在让我们理解一下我们所计算的内容以及如何解读结果。决定系数(R-squared)衡量模型预测数据的能力,其值介于零和一之间。决定系数的值越高,模型预测数据的能力越强。
我们得到了0.96的值,所以根据我们之前所说的,这是一个很棒的结果。为了确认这一点,我们需要将其与另一个模拟模型的结果进行比较。因此,我们基于相同的数据构建了一个线性回归模型,即iris
数据集。
要构建线性回归模型,我们可以使用glm
函数。该函数用于拟合广义线性模型,通过给出线性预测符号描述和误差分布描述来指定:
m=iris.lm <- h2o.glm(x=2:5,y=1,training_frame=as.h2o(iris))
现在我们计算模型的决定系数:
> h2o.r2(m)
[1] 0.8667852
现在我们可以比较基于 DNN 的模型和线性回归模型。DNN 提供的 R-squared 值为0.96,而回归模型的 R-squared 值为0.87。显然,DNN 提供了更好的性能。
最后,分析神经网络专家认为重要的参数可能会很有用,如下表所示:
Argument | Description |
---|---|
x | 包含用于构建模型的预测变量名称或索引的向量。如果x 缺失,则使用除y 外的所有列。 |
y | 模型中响应变量的名称。如果数据没有包含表头,则这是第一列的索引,从左到右递增(响应变量必须是整数或类别变量)。 |
model_id | 这是模型的目标id ;如果没有指定,则会自动生成。 |
standardize | 这是一个逻辑函数。如果启用,它会自动标准化数据。如果禁用,用户必须提供适当缩放的输入数据。默认值为TRUE 。 |
activation | 这是一个激活函数。它必须是Tanh 、TanhWithDropout 、Rectifier 、RectifierWithDropout 、Maxout 或MaxoutWithDropout 之一。默认值为Rectifier 。 |
hidden | 该参数指定隐藏层的大小(例如,[100, 100] )。默认值为[200, 200] 。 |
epochs | 数据集应被迭代(流式处理)的次数,可以是小数。默认值为10 。 |
adaptive_rate | 这是一个逻辑参数,用于指定自适应学习率。默认值为TRUE 。 |
rho | 这是描述自适应学习率时间衰减因子的参数(类似于先前的更新)。默认值为0.99 。 |
rate_annealing | 学习率退火由rate/(1 + rate_annealing * samples) 给出。默认值为1e-06 。 |
rate_decay | 这是层之间的学习率衰减因子(*N^(th)*层: rate * rate_decay ^ (n - 1) )。默认值为1 。 |
input_dropout_ratio | 输入层的 dropout 比率(可以提高泛化能力,尝试0.1 或0.2 )。默认值为0 。 |
hidden_dropout_ratios | 隐藏层的 dropout 比率可以提高泛化能力。每个隐藏层指定一个值。默认值为0.5 。 |
l1 | L1 正则化可以增加稳定性并提高泛化能力,它使得许多权重变为0 。默认值为0 。 |
l2 | L2 正则化可以增加稳定性并提高泛化能力,它使得许多权重变得很小。默认值为0 。 |
initial_weights | 这是一个H2OFrame ID 的列表,用于初始化模型的权重矩阵。 |
initial_biases | 这是一个H2OFrame ID 的列表,用于初始化模型的偏置向量。 |
loss | 损失函数必须是Automatic 、CrossEntropy 、Quadratic 、Huber 、Absolute 或Quantile 之一。默认值为Automatic 。 |
distribution | 分布函数必须是AUTO 、bernoulli 、multinomial 、gaussian 、poisson 、gamma 、tweedie 、laplace 、quantile 或huber 之一。默认值为AUTO 。 |
score_training_samples | 它是用于评分的训练集样本数量(0 表示所有样本)。默认值为10000 。 |
score_validation_samples | 它是用于评分的验证集样本数量(0 表示所有样本)。默认值为0 。 |
classification_stop | 分类误差比例的停止准则,针对训练数据(-1 表示禁用)。默认值为0 。 |
regression_stop | 这是回归误差(均方误差)在训练数据上的停止准则(-1 表示禁用)。默认值为1e-06 。 |
stopping_rounds | 基于stopping_metric 收敛情况的早期停止。如果stopping_metric 的长度为k 的简单移动平均值在k:=stopping_rounds 次评分事件中没有改善,则停止训练(0 表示禁用)。默认值为5 。 |
max_runtime_secs | 这是模型训练的最大允许运行时间,单位为秒。使用0 可以禁用该设置。默认值为0 。 |
diagnostics | 启用隐藏层的诊断。默认值为TRUE 。 |
fast_mode | 启用快速模式(反向传播时的微小近似)。默认值为TRUE 。 |
replicate_training_data | 在每个节点上复制整个训练数据集,以加快小数据集上的训练。默认值为TRUE 。 |
single_node_mode | 在单个节点上运行,用于微调模型参数。默认值为FALSE 。 |
shuffle_training_data | 启用训练数据的随机打乱(如果训练数据被复制且train_samples_per_iteration 接近#nodes x #rows ,或者如果使用balance_classes ,建议启用)。默认值为FALSE 。 |
missing_values_handling | 处理缺失值时,必须选择MeanImputation 或Skip 。默认值为MeanImputation 。 |
quiet_mode | 启用安静模式,减少标准输出的内容。默认值为FALSE 。 |
verbose | 将评分历史打印到控制台(对于 GBM、DRF 和 XGBoost,每棵树的指标;对于深度学习,每个 epoch 的指标)。默认值为False |
autoencoder | 逻辑自编码器,默认值为FALSE |
export_weights_and_biases | 是否将神经网络的权重和偏差导出到H2OFrame 。默认值为FALSE 。 |
mini_batch_size | 小批量大小(较小的值有助于更好地拟合,而较大的值可以加速并更好地泛化)。默认值为1 。 |
有一些与 R 和h2o
相关的深度学习函数。以下列出了一些有用的函数:
函数 | 描述 |
---|---|
predict.H2Omodel | 返回一个包含概率和默认预测的H2OFrame 对象。 |
h2o.deepwater | 使用多个本地 GPU 后端构建深度学习模型。在包含各种数据源的H2OFrame 上构建 DNN。 |
as.data.frame.H2OFrame | 将H2OFrame 转换为数据框。 |
h2o.confusionMatrix | 显示分类模型的混淆矩阵。 |
print.H2OFrame | 打印H2OFrame 。 |
h2o.saveModel | 将一个h2o 模型对象保存到磁盘。 |
h2o.importFile | 将文件导入到 h2o 中。 |
使用 H2O 的深度自编码器
自编码器是神经网络中的无监督学习方法。在第七章,神经网络的应用案例 – 高级主题中,我们将进一步了解这些内容。h2o
可以通过使用深度自编码器来检测异常。要训练这样的模型,使用相同的函数h2o.deeplearning()
,只需要对参数进行一些更改:
anomaly_model <- h2o.deeplearning(1:4,
training_frame = as.h2o(iris),
activation = "Tanh",
autoencoder = TRUE,
hidden = c(50,20,50),
sparse = TRUE,
l1 = 1e-4,
epochs = 100)
autoencoder=TRUE
将deeplearning
方法设置为使用自编码器技术的无监督学习方法。我们仅使用训练数据,而没有测试集和标签。需要使用深度autoencoder
而不是前馈网络的事实是由autoencoder
参数指定的。
我们可以选择不同层中要包含的隐藏单元的数量。如果选择一个整数值,得到的模型被称为朴素自编码器。
总结
深度学习是一个非常重要的学科,涉及从图像识别到语音识别及 AI 相关活动。市场上有许多深度学习的产品和包,其中包括Keras
、TensorFlow
、h2o
以及其他许多。
在这一章,我们学习了深度学习的基础知识、DNN 的许多变种、最重要的深度学习算法以及深度学习的基本工作流程。我们探索了 R 中处理 DNN 的不同包。
为了了解如何构建和训练 DNN,我们分析了一个使用neuralnet
包实现的 DNN 实践示例。我们学习了如何通过各种现有的技术对数据进行归一化,以去除数据单位,从而便于比较来自不同位置的数据。我们还了解了如何将数据拆分用于网络的训练和测试。我们学会了使用neuralnet
函数来构建和训练多层神经网络。因此,我们理解了如何使用训练好的网络进行预测,并学会了使用混淆矩阵来评估模型性能。
我们了解了h2o
包的一些基础知识。总体而言,h2o
包是一个非常用户友好的包,可以用来训练前馈网络或深度自编码器。它支持分布式计算,并提供了一个 web 界面。通过像使用其他包一样引入h2o
包,我们可以进行各种类型的 DNN 模型构建和处理。h2o
的强大功能可以通过包中提供的多种特性来充分利用。
在下一章,我们将了解什么是感知机,以及可以使用基本感知机构建的应用程序。我们将学习在 R 环境中实现简单感知机的函数。我们还将学习如何训练和建模一个 MLP。我们将探索线性可分的分类器。