Python迁移学习实用指南:1~5绝不原创的飞龙

不要担心自己的形象,只关心如何实现目标。——《原则》,生活原则2.3.c

有一天,人工智能将像看非洲平原上的化石骨架一样回望我们。一只生活在尘土中的直立猿,用粗俗的语言和工具灭绝。

——内森·贝特曼(NathanBateman),前Machina(电影节2014)

本章为读者提供了有关ML基本概念的快速入门,然后在后续各章中开始进行深度学习。本章涵盖以下方面:

传统编程范例

尽管当前的范例已经在帮助我们开发出惊人的复杂软件/系统,以一种非常有效的方式来解决来自不同领域和方面的任务,但它们仍需要有人为此类程序定义并编写明确的规则才能工作。这些任务对于计算机来说很容易解决,但对人类来说却是困难或费时的。例如,执行复杂的计算,存储大量数据,通过庞大的数据库进行搜索等等都是可以在定义规则后由计算机有效执行的任务。

这种体现了通用计算思想的新范式在更广泛的意义上促成了AI的产生。这种新的范式,更好地称为ML范式,是计算机或机器从经验(类似于人类学习)中学习来解决任务的方法,而不是经过明确编程才能做到的。

人工学习的范围,以机器学习和深度学习为子领域

由汤姆·米切尔(TomMitchell)提出的ML的正式定义解释如下。

如果P所衡量的计算机程序在T上的表现,会随着经验E而提高,该计算机程序据称可以从E的经验中以表现指标P学习某些任务T。

该定义以非常简洁的方式很好地捕捉了ML的本质。让我们以现实世界为例,以更好地理解它。让我们考虑一个任务(T)是识别垃圾邮件。现在,我们可能会向有关垃圾邮件和非垃圾邮件的系统提供许多示例(或经验),从中可以学习而不是对其进行明确编程。然后可以在学习到的识别垃圾邮件的任务上对程序或系统的表现进行测量(P)。有趣,不是吗?

因此,ML的任务是从训练示例中识别模式,并将这些学习到的模式(或表示形式)应用于新的看不见的数据。ML有时也称为浅层学习,因为它学习单层表示形式的性质(在大多数情况下)。这使我们想到“表示层是什么”和“什么是深度学习”,我们将在后续章节中回答这些问题。让我们快速了解一下深度学习。

如前所述,不要担心是否难以理解和理解,我们将在后续章节中更深入地介绍。

由于我们正在生成和收集的数据量以及更快的计算能力,ML已成为流行语。在以下各节中,让我们更深入地研究ML。

ML是AI的一个流行子领域,涵盖了非常广泛的领域。如此受欢迎的原因之一是在其能力范围内的复杂算法,技术和方法的综合工具箱。多年来,该工具箱已经得到开发和改进,并且正在不断研究新的工具箱。为了明智地理解和使用ML工具箱,请考虑以下几种分类方法。

基于人工监督量的分类:

根据数据可用性进行分类:

前面讨论的分类为我们提供了如何组织,理解和利用ML算法的抽象视图。将它们分类的最常见方法是有监督和无监督学习算法。让我们更详细地介绍这两个类别,因为这将有助于我们开始进一步的高级主题,稍后再进行介绍。

监督学习算法是一类利用数据样本(也称为训练样本)和相应的输出(或标签)推断两者之间映射函数的算法。推断的映射函数或习得函数是此训练过程的输出。然后,将习得函数用于正确映射新的和看不见的数据点(输入元素)以测试习得函数的表现。

监督学习算法的一些关键概念如下:

有多种可用的监督学习算法。根据用例需求,可以将它们主要分类为分类和回归模型。

简而言之,这些算法可帮助我们回答客观问题或是/否预测。例如,“这些算法在这样的场景下有用吗”或“该肿瘤会癌变吗”等。

形式上,分类算法的主要目标是根据输入数据点预测本质上属于分类的输出标签。输出标签本质上是分类的;也就是说,它们每个都属于离散的类或类别。

Logistic回归,支持向量机(SVM),神经网络,随机森林,K最近邻(KNN),决策树等是一些流行的分类算法。

假设我们有一个真实的用例来评估不同的汽车模型。为简单起见,让我们假设该模型可以根据多个输入训练样本预测每种汽车模型的输出是可接受的还是不可接受的。输入的训练样本具有诸如购买价格,门数,容量(以人数计)和安全性的属性。

除类标签之外的级别将每个数据点表示为可接受或不可接受。下图描述了即将出现的二分类问题。分类算法将训练样本作为输入以准备监督模型。然后,利用该模型来预测新数据点的评估标签:

监督学习:用于汽车模型评估的二分类

由于在分类问题中输出标签是离散类,因此如果只有两个可能的输出类,则该任务称为二分类问题,否则称为多类分类。预测明天是否下雨将是一个二分类问题(输出是“是”或“否”),而从扫描的手写图像中预测数字将是具有10个标签(零到九个可能的输出标签)的多类分类。。

此类监督学习算法有助于我们回答数量或定量类型的问题。正式而言,回归模型的关键目标是值的估计。在这种情况下,输出标签本质上是连续的(相对于分类而言是离散的)。

可以基于建模模型如何对因变量和自变量之间的关系建模来进一步分类。

简单线性回归模型适用于单个自变量和单个因变量。普通最小二乘(OLS)回归是一种流行的线性回归模型。多元回归或多元回归是只有一个因变量的地方,而每个观察值都是由多个解释变量组成的向量。

多项式回归模型是多元回归的一种特殊情况。在此,因变量被建模为自变量的第n次幂。由于多项式回归模型拟合或映射因变量和自变量之间的非线性关系,因此这些也称为非线性回归模型。

以下是线性回归的示例:

监督学习:线性回归

为了理解不同的回归类型,让我们考虑一个真实的用例,它基于汽车的速度来估计汽车的停止距离。在这里,根据我们拥有的训练数据,我们可以将停车距离建模为速度的线性函数或汽车速度的多项式函数。请记住,主要目的是在不过拟合训练数据本身的情况下最大程度地减少误差。

上图描述了线性拟合,而下图描述了同一数据集的多项式拟合:

监督学习:多项式回归

顾名思义,此类算法无需监督即可学习/推断概念。与监督学习算法基于包含输入数据点和输出信号的训练数据集推断映射函数不同,无监督算法的任务是在训练数据中查找模式和关系,而训练数据集中没有可用的输出信号。这类算法利用输入数据集来检测模式,并挖掘规则或组/集群数据点,以便从原始输入数据集中提取有意义的见解。

当我们没有包含相应输出信号或标签的训练集的自由时,无监督算法会派上用场。在许多实际场景中,可以使用没有输出信号的数据集,很难手动标记它们。因此,无监督算法有助于弥补这种差距。

与监督学习算法类似,也可以对非监督算法进行分类,以易于理解和学习。以下是无监督学习算法的不同类别。

分类的无监督等效项称为聚类。这些算法可以帮助我们将数据点聚类或分组为不同的组或类别,而无需在输入/训练数据集中使用任何输出标签。这些算法尝试使用固有特征基于某种相似性度量将输入数据集中的模式和关系查找到不同的组中,如下图所示:

有多种执行聚类过程的方法。最受欢迎的是:

数据和ML是最好的朋友,但是越来越多的数据带来了很多问题。大量的属性或膨胀的特征空间是一个常见问题。较大的特征空间在分析和可视化数据时会带来问题,以及与训练,内存和空间限制有关的问题。这也被称为维度诅咒。由于无监督方法可以帮助我们从未标记的训练数据集中提取见解和模式,因此它们也有助于我们减少维度。

换句话说,无监督方法通过帮助我们从完整的可用列表中选择一组代表性的特征来帮助我们减少特征空间:

无监督学习:使用PCA减少维度

主成分分析(PCA),最近邻和判别分析是一些流行的降维技术。

上图是对基于PCA的降维技术工作的著名描述。它显示了瑞士卷形状,其中数据以三维空间表示。PCA的应用导致将数据转换为二维空间,如图的右侧所示。

这类无监督的ML算法有助于我们理解事务数据集并从中提取模式。这些算法也称为市场篮子分析(MBA),可帮助我们识别跨交易的项目之间有趣的关系和关联。

使用关联规则挖掘,我们可以回答诸如“人们在给定商店中一起购买了哪些物品或购买葡萄酒的人也倾向于购买奶酪吗”之类的问题等等。FP-growth,ECLAT和Apriori是用于关联规则挖掘任务的最广泛使用的算法。

对于此类任务,我们为算法提供了历史数据集,因此它可以以无监督的方式识别和了解数据的正常行为。学习后,该算法将帮助我们识别与该学习行为不同的模式。

跨行业数据挖掘标准流程(CRISP-DM)是数据挖掘和分析项目中最流行且使用最广泛的流程之一。CRISP-DM提供了所需的框架,该框架清楚地概述了执行数据挖掘和分析项目所需的步骤和工作流程,从业务需求到最终部署阶段以及介于两者之间的所有内容。

CRISP-DM以首字母缩略词本身更广为人知,是一种经过尝试,测试且可靠的行业标准过程模型,适用于数据挖掘和分析项目。CRISP-DM清楚地描述了执行任何项目所必需的步骤,过程和工作流,从正式的业务需求到测试和部署解决方案以将数据转化为见解。数据科学,数据挖掘和ML都是要尝试运行多个迭代过程以从数据中提取见解和信息。因此,我们可以说,分析数据的确是一门艺术,也是一门科学,因为它并非总是无缘无故地运行算法。许多主要工作涉及了解业务,所投入工作的实际价值以及表达最终结果和见解的正确方法。

与具有不同生命周期模型的软件工程项目相似,CRISP-DM可帮助我们从头到尾跟踪数据挖掘和分析项目。该模型分为六个主要步骤,涵盖从业务和数据理解到评估和最终部署的各个方面,所有这些本质上都是迭代的。请参见下图:

描述ML项目工作流程的CRISP-DM模型

现在让我们更深入地研究六个阶段中的每个阶段,以更好地了解CRISP-DM模型。

第一步也是最重要的一步是了解业务。这一关键步骤始于设置业务环境和问题要求。正式定义业务需求对于将其转换为数据科学和分析问题陈述至关重要。此步骤还用于为业务和数据科学团队设置期望和成功标准,使其位于同一页面上并跟踪项目进度。

数据收集和理解是CRISP-DM框架的第二步。在这一步中,我们将进行更深入的了解,以了解和分析上一步中形式化的问题陈述的数据。此步骤开始于调查先前详细项目计划中概述的各种数据源。然后将这些数据源用于收集数据,分析不同的属性并记录数据质量。此步骤还涉及通常称为探索性数据分析的内容。

探索性数据分析(EDA)是非常重要的子步骤。在EDA期间,我们分析了数据的不同属性,属性和特征。我们还将EDA期间的数据可视化,以更好地理解和发现以前可能看不见或忽略的模式。此步骤为后续步骤奠定了基础,因此,这一步骤根本不能忽略。

数据清理和整理是非常重要的步骤。这涉及处理缺失值,数据不一致,修复不正确的值以及将数据转换为可摄取格式,以便ML算法可以使用它们。

第四步或建模步骤是进行实际分析和机器学习的地方。此步骤将在上一步中准备的干净和格式化的数据用于建模目的。这是一个迭代过程,与数据准备步骤同步工作,因为模型/算法需要具有不同属性集的不同设置/格式的数据。

一旦建模步骤生成满足成功标准,表现基准和模型评估指标的模型,就需要进行彻底的评估。在此步骤中,我们将在进行部署阶段之前考虑以下活动:

CRISP-DM模型的最后一步是部署到生产。在多次迭代过程中开发,微调,验证和测试的模型将保存起来并准备用于生产环境。构建了适当的部署计划,其中包括有关硬件和软件要求的详细信息。部署阶段还包括进行检查和监视方面,以评估生产中的模型的结果,表现和其他指标。

典型的ML流水线

标准ML流水线大致包括以下阶段。

数据收集和提取通常是故事的起点。数据集有各种形式,包括结构化和非结构化数据,这些数据通常包括丢失或嘈杂的数据。每种数据类型和格式都需要特殊的机制来进行数据处理和管理。例如,如果一个项目涉及对推文的分析,我们需要使用TwitterAPI并开发机制以提取所需的推文,这些推文通常为JSON格式。

其他场景可能涉及已经存在的结构化或非结构化公共数据集或私有数据集,除了仅开发提取机制外,这两种情况都可能需要其他权限。Sarkar和他们的合著者在《Python机器学习》的第3章中讨论了与使用各种数据格式有关的相当详细的内容,如果您有兴趣进一步研究,请参阅它。

到目前为止,项目的所有初始步骤都围绕业务环境,需求,风险等。这是我们实际深入研究收集/可用数据的第一个接触点。EDA帮助我们了解数据的各个方面。在此步骤中,我们将分析数据的不同属性,发现有趣的见解,甚至可视化不同维度上的数据以获得更好的理解。

此步骤可帮助我们收集手头的数据集的重要特征,这不仅在项目的后期阶段很有用,而且还有助于我们在流水线早期识别和/或缓解潜在问题。我们将在本章后面介绍一个有趣的示例,以使读者了解EDA的过程和重要性。

此步骤与将数据转换为可用形式有关。在大多数情况下,ML算法无法使用第一步中检索到的原始数据。形式上,数据整理是将数据从一种形式清除,转换和映射为另一种形式,以便在项目生命周期的后期阶段使用的过程。此步骤包括缺少数据插补,类型转换,处理重复项和异常值,等等。为了更好的理解,我们将在用例驱动的章节中介绍这些步骤。

经过预处理和处理后的数据达到了可以被特征工程和提取步骤利用的状态。在此步骤中,我们利用现有属性来导出和提取上下文/用例特定的属性或特征,这些属性或特征可以在接下来的阶段中被ML算法利用。我们根据数据类型采用不同的技术。

特征工程和提取是一个相当复杂的步骤,因此在本章的后面部分将进行更详细的讨论。

在某些情况下,可用特征的数量过大,会对整个解决方案产生不利影响。具有大量属性的数据集的处理和处理不仅成为问题,而且还导致解释,可视化等方面的困难。这些问题被正式称为维度的诅咒。

因此,特征选择可以帮助我们确定可以在建模步骤中使用的代表性特征集,而不会造成太多信息损失。有多种技术可以执行特征选择。本章后面的部分将讨论其中的一些。

在建模过程中,我们通常将数据特征提供给ML方法或算法并训练模型,通常是为了优化特定的成本函数,在大多数情况下,目的是减少误差并归纳从数据中学到的表示形式。

根据数据集和项目要求,我们应用一种或多种不同的机器学习技术的组合。这些可以包括有监督的技术(例如分类或回归),无监督的技术(例如聚类),甚至是结合了不同技术的混合方法(如先前在“ML技术”部分中所讨论的)。

建模通常是一个迭代过程,我们经常利用多种算法或方法,并根据模型评估表现指标来选择最佳模型。由于这是一本有关迁移学习的书,因此我们将在后续章节中主要基于深度学习构建模型,但是建模的基本原理与ML模型非常相似。

开发模型只是从数据中学习的一部分。建模,评估和调整是迭代步骤,可帮助我们微调和选择表现最佳的模型。

模型基本上是数据的通用表示形式,并且是用于学习该表示形式的基础算法。因此,模型评估是针对某些标准评估构建模型以评估其表现的过程。模型表现通常是定义为提供数值以帮助我们确定任何模型的有效性的函数。通常,会根据这些评估指标对成本或损失函数进行优化以构建准确的模型。

评估无监督方法(例如聚类)的流行指标包括:

请注意,此列表描述了广泛使用的最受欢迎的度量标准,但绝不是模型评估度量标准的详尽列表。

交叉验证也是模型评估过程的重要方面,在该过程中,我们利用基于交叉验证策略的验证集通过调整模型的各种超参数来评估模型表现。您可以将超参数视为可以用来调整模型以构建有效且表现更好的模型的旋钮。当我们在随后的章节中使用大量的实际操作示例来评估模型时,这些评估技术的用法和细节将更加清晰。

监督学习算法可帮助我们推断或学习从输入数据点到输出信号的映射。该学习导致目标或习得函数。现在,在理想情况下,目标函数将学习输入变量和输出变量之间的精确映射。不幸的是,没有理想。

正如在介绍监督学习算法时所讨论的那样,我们利用称为训练数据集的数据子集来学习目标函数,然后在称为测试数据集的另一个子集上测试表现。由于该算法仅看到所有可能数据组合的子集,因此在预测输出和观察到的输出之间会出现误差。这称为总误差或预测误差:

总误差=偏差误差+方差误差+不可约误差

不可减少的误差是由于噪声,我们对问题的框架,收集数据的方式等导致的固有误差。顾名思义,这种误差是无法避免的,从算法的角度来看,我们几乎无能为力。

术语偏差是指由学习算法推断目标函数的基础假设。高偏差表明该算法对目标函数有更多假设,而低偏差表明该假设较少。

由偏差引起的误差只是预期(或平均)预测值与实际观察值之间的差。为了获得预测的平均值,我们多次重复学习步骤,然后取平均结果。偏差误差有助于我们了解模型的概括性。低偏差算法通常是非参数算法,例如决策树,SVM等,而参数函数(例如线性和逻辑回归)的偏差很高。

方差标志着模型对训练数据集的敏感性。众所周知,学习阶段依赖于称为训练集的所有可能数据组合的一小部分。因此,随着训练数据集的变化,方差误差捕获了模型估计值的变化。

低方差表明预测值的变化要少得多,因为基础训练数据集会发生变化,而高方差则指向另一个方向。非参数算法(例如决策树)具有较高的方差,而参数算法(例如线性回归)的灵活性较差,因此方差较低。

偏差方差权衡是同时减少监督学习算法的偏差和方差误差的问题,这阻止了目标函数泛化到训练数据点之外。让我们看一下以下插图:

偏差方差权衡

考虑给我们给出一个问题陈述:“给定一个人的身高,确定他/她的体重”。我们还为训练数据集提供了相应的身高和体重值。数据如下图所示:

描绘身高体重数据集的图

请注意,这是一个说明重要概念的示例,在解决实际问题的后续章节中,我们将使用实际案例。

这是监督学习问题的一个实例,更多是回归问题的实例(请参阅为什么?)。利用该训练数据集,我们的算法将必须学习目标函数,以找到不同个体的身高和体重之间的映射。

根据我们的算法,训练阶段可能会有不同的输出。假设学习的目标函数如下图所示:

欠拟合模型

该惰性函数始终预测恒定的输出值。由于目标函数无法学习数据的基础结构,因此导致欠拟合的情况。欠拟合模型的预测表现较差。

训练阶段的另一个极端称为过拟合。过拟合图可以表示如下:

过拟合模型

这显示了一个目标函数,可以完美地映射训练数据集中的每个数据点。这就是众所周知的模型过拟合。在这种情况下,该算法试图了解包括噪声在内的确切数据特征,因此无法可靠地预测看不见的新数据点。

欠拟合和过拟合之间的最佳结合点是我们所说的良好拟合。可以很好地概括给定问题的模型图如下:

很好的概括

可以在看不见的数据点以及训练数据上表现良好的学习能力被称为泛化能力。因此,泛化指的是基于在训练阶段学到的概念,目标函数在看不见的数据上执行得如何。上图描绘了很好的概括拟合。

准备和评估模型与调整模型一样重要。与为我们提供标准算法集的不同ML框架/库一起工作,我们几乎从来没有立即使用它们。

ML算法具有不同的参数或旋钮,可以根据项目要求和不同的评估结果进行调整。通过遍历超参数或元参数的不同设置来获得更好的结果,模型调整可以起作用。超参数是高级抽象上的旋钮,它是在学习过程开始之前设置的。

这与模型级别参数不同,模型级别参数在训练阶段期间学习。因此,模型调整也称为超参数优化。

网格搜索,随机超参数搜索,贝叶斯优化等是执行模型调整的流行方法。尽管模型调整非常重要,但过度调整可能会对学习过程产生不利影响。在“偏差方差权衡”部分中讨论了与过度调整过程有关的一些问题。

一旦完成了模型开发,评估和调整,并进行了多次迭代以改善结果,那么模型部署的最后阶段就到了。模型部署负责各个方面,例如模型持久性,通过不同的机制(例如API端点)将模型公开给其他应用,以及制定监视策略。

机器学习流水线与软件工程以及数据科学和机器学习一样重要。我们简要概述并讨论了典型流水线的不同组成部分。根据特定的用例,我们修改了标准流水线以适应需要,同时确保我们不会忽略已知的陷阱。在接下来的部分中,我们将通过实际示例和代码片段更详细地了解典型ML流水线的几个组件。

当我们开始任何ML项目时,EDA就是我们执行的前几个任务之一。正如在“CRISP-DM”一节中所讨论的那样,数据理解是发现有关数据的各种见解并更好地理解业务需求和上下文的重要步骤。

在本节中,我们将使用一个实际的数据集,并使用pandas作为我们的数据处理库以及seaborn进行可视化来执行EDA。Python笔记本game_of_thrones_eda.ipynb中提供了完整的代码段和此分析的详细信息。

首先,我们导入所需的库并按照以下代码片段所示设置配置:

以下代码段使用pandas加载battles.csv文件:

In[2]:battles_df=pd.read_csv('battles.csv')数据集如以下屏幕快照所示:

权力的游戏的Battles.csv中的示例行

我们可以分别使用pandas工具shape,dtypes和describe()查看行的总数,每个属性的数据类型以及数字属性的常规统计信息。我们有38场战斗的数据,其中25项属性描述了每一场。

让我们了解幻想世界多年来战斗的分布情况。以下代码段绘制了此分布的条形图:

In[3]:sns.countplot(y='year',data=battles_df)...:plt.title('BattleDistributionoverYears')...:plt.show()下图显示,在299年中,战斗次数最多,其次分别是300和298:

多年来的战斗分配

在这个幻想的土地上有不同的地区,在可以想象的每个地方都发生着战斗。但是,有趣的是看看是否有任何首选区域。以下代码段有助于我们准确地回答此问题:

In[4]:sns.countplot(x='region',data=battles_df)...:plt.title('BattlesbyRegions')...:plt.show()以下图表可帮助我们确定里弗兰兹战斗最多,其次是北部和西部:

地区战

我们可以使用不同的分组依据进行类似的分析,以了解例如主要死亡人数或每个地区的捕获数,等等。

我们继续前进,看看哪个国王攻击最多。我们使用饼图将其可视化,以了解每个参与的国王所进行的战斗所占的百分比。请注意,我们基于攻击国王进行此分析。防御王也可以执行类似的分析。以下代码段准备了一个饼图,以显示每个进攻国王的战斗份额:

In[5]:attacker_king=battles_df.attacker_king.value_counts()...:attacker_king.name=''#turnoffannoyingy-axis-label...:attacker_king.plot.pie(figsize=(6,6),autopct='%.2f')以下饼形图显示了每个进攻国王的战斗份额:

每个进攻国王的战斗份额

韦斯特罗斯和埃索斯的土地充满危险,遍布敌人和威胁。让我们稍微分析一下数据,以了解每位国王在多少次获胜者。由于国王既可以保卫自己的土地,也可以争取权力,因此看到保卫和进攻的胜利也很有趣。以下代码段有助于我们准备堆积的条形图,以分析每位国王的进攻和防守胜利:

In[6]:attack_winners=battles_df[battles_df....:attacker_outcome=='win']...:['attacker_king']....:value_counts()....:reset_index()...:...:attack_winners.rename(...:columns={'index':'king',...:'attacker_king':'wins'},...:inplace=True)...:...:attack_winners.loc[:,'win_type']='attack'...:...:defend_winners=battles_df[battles_df....:attacker_outcome=='loss']...:['defender_king']....:value_counts()....:reset_index()...:defend_winners.rename(...:columns={'index':'king',...:'defender_king':'wins'},...:inplace=True)...:...:defend_winners.loc[:,'win_type']='defend'...:...:...:sns.barplot(x="king",...:y="wins",...:hue="win_type",...:data=pd.concat([attack_winners,...:defend_winners]))...:plt.title('KingsandTheirWins')...:plt.ylabel('wins')...:plt.xlabel('king')...:plt.show()前面的代码段计算出攻击时每位国王的获胜次数,然后计算出防守时每位国王的获胜次数。然后,我们将两个结果合并,并使用堆叠的条形图绘制相同的结果。结果显示在下图中:

每位国王获胜的次数

上图清楚地表明,马拉松男孩在进攻和防守中获胜的次数最多。到目前为止,他们似乎很幸运。RobbStark是第二成功的国王,当然红色婚礼发生了。

数据集还包含描述所涉及房屋的数量,战斗指挥官和军队规模的属性。我们可以进行类似且更深入的分析,以更好地理解战斗。我们鼓励读者尝试其中一些作为练习,并检查Python笔记本中的更多指针。

权力的游戏中的大敌

我们看到数据集证实了直觉。RobbStark和JoffreyBaratheon已经进行了19场战斗,其他两对则进行了五场或更少的战斗。

本节中共享的分析和可视化效果是对数据集可以完成的工作的一瞥。仅从该数据集中可以提取出更多的模式和见解。

EDA是一种非常强大的机制,可用于在进入ML的其他阶段之前详细了解数据集。在接下来的章节中,在进入建模,调整,评估和部署阶段之前,我们将定期执行EDA,以帮助我们理解业务问题以及数据集。

对原始数据集进行预处理和处理后,下一步就是使其可用于ML算法。特征提取是从原始属性派生特征的过程。例如,在处理图像数据时进行特征提取是指从原始像素级数据中提取红色,蓝色和绿色通道信息作为特征。

同样,特征工程指的是使用数学变换从现有特征中推导其他特征的过程。例如,特征工程将帮助我们从一个人的月收入中得出一个特征,例如年收入(基于用例要求)。由于特征提取和工程设计都可以帮助我们将原始数据集转换为可用形式,因此ML实践者可以互换使用这些术语。

将原始数据集(后期清理和整理)转换为可以由ML算法使用的特征的过程是领域知识,用例需求和特定技术的组合。因此,特征描述了基础数据的各种表示形式,并且是特征工程过程的结果。

由于特征工程将原始数据转换为自身的有用表示形式,因此根据手头的数据类型,可以使用各种标准技术和策略。在本节中,我们将讨论其中一些策略,简要介绍结构化和非结构化数据。

数值数据通常以整数或浮点数的形式在数据集中可用,并且通常称为连续数值数据,通常是ML友好数据类型。友好地说,我们指的是可以直接在大多数ML算法中摄取数字数据的事实。但是,这并不意味着数字数据不需要其他处理和特征工程步骤。

有多种技术可以从数值数据中提取和工程化特征。让我们看一下本节中的一些技术:

笔记本feature_engineering_numerical_and_categorical_data.ipynb中提供了代码片段,以更好地理解数字数据的特征工程。

常见的另一类重要数据是类别数据。类别特征具有离散值,这些离散值属于一组有限的类。这些类可以表示为文本或数字。根据类别的顺序,类别特征分别称为标称和序数。

标称特征是具有有限值集合但没有任何自然顺序的那些类别特征。例如,天气季节,电影类型等都是标称特征。具有有限类集并具有自然顺序的类别特征称为序数特征。例如,星期几,着装大小等都是常规的。

通常,特征工程中的任何标准工作流程都涉及将这些类别值转换为数字标签的某种形式,然后在这些值上应用某种编码方案。流行的编码方案简要介绍如下:

笔记本feature_engineering_numerical_and_categorical_data.ipynb中提供了代码片段,以更好地理解类别数据的特征工程。

图像或视觉数据是丰富的数据源,可以使用ML算法和深度学习解决几个用例。图像数据提出了很多挑战,需要经过仔细的预处理和转换,然后才能被任何算法使用。对图像数据执行特征工程的一些最常见方法如下:

最近,人们已经研究了深度学习,特别是卷积神经网络(CNN),并将其用作自动特征提取器。CNN是针对图像数据进行优化的深度神经网络的特例。卷积层是任何CNN的核心,它们基本上会在图像的高度和宽度上应用滑动滤镜。像素值与这些滤镜的点积会生成跨多个周期学习的激活图。在每个层次上,这些卷积层都有助于提取特定特征,例如边缘,纹理,角等。

深度学习和CNN还有很多,但是为了简单起见,让我们假设CNN在每一层都可以帮助我们自动提取不同的低级和高级特征。反过来,这使我们免于手动执行特征提取。我们将在接下来的章节中更详细地研究CNN,并了解它们如何帮助我们自动提取特征。

在进行任何特征提取/工程设计之前,文本数据需要仔细而勤奋的预处理。预处理文本数据涉及多个步骤。以下是一些最广泛使用的文本数据预处理步骤的列表:

在与用例有关的章节中,我们将详细介绍大多数技术。为了更好地理解,读者可以参考《Python实用机器学习》的第4章和第7章(Sarkar及其合著者,Springer,2017年)。

通过上一节中提到的方法对文本数据进行正确处理后,我们就可以利用以下一些技术来进行特征提取和转换为数值形式。Jupyter笔记本feature_engineering_text_data.ipynb中提供了可更好地理解文本数据特征的代码片段:

除了词袋和TF-IDF外,还有其他转换,例如N-gram袋,以及单词嵌入,例如Word2vec,GloVe等。我们将在后续章节中详细介绍其中的几个。

特征提取和工程设计的过程可帮助我们从基础数据集中提取特征并生成特征。在某些情况下,这会导致大量输入要处理的算法。在这种情况下,怀疑输入中的许多特征可能是多余的,并可能导致复杂的模型甚至过拟合。特征选择是从可用/生成的完整特征集中识别代表性特征的过程。预期所选特征集将包含所需信息,以使算法能够解决给定任务而不会遇到处理,复杂性和过拟合的问题。特征选择还有助于更好地理解建模过程中使用的数据,并加快处理速度。

特征选择方法大致可分为以下三类:

最受欢迎的库提供了多种特征选择技术。诸如scikit-learn之类的库提供了开箱即用的这些方法。在后面的章节中,我们将看到并利用其中的许多内容。

在任何旅程中,了解概念和技术的牢固基础和共同基础都非常重要。通过本章有关机器学习基础知识的章节,我们试图实现这一目标。在开始学习深度学习,迁移学习和更高级的概念之前,必须为ML概念奠定坚实的基础。在本章中,我们涵盖了相当多的基础,并提供了更详细地研究概念的重要指示。

我们通过理解机器学习为何如此重要以及它是一个完全不同的范例来开始本章。我们简要讨论了AI,机器学习和深度学习之间的关系。然后,本章继续介绍了不同的机器学习技术,例如有监督,无监督和强化学习。我们详细讨论了通常使用哪些不同的监督和非监督方法。

本章还简要介绍了用于ML项目工作流程的CRISP-DM模型以及ML流水线。我们还讨论了《权力的游戏》幻想世界中战斗数据集的EDA,以应用不同的概念并了解EDA的重要性。在本章的最后,介绍了特征提取和工程以及特征选择。

在接下来的章节中,我们将以这些概念为基础,并最终在涉及不同实际使用案例的章节中应用所学知识。欢迎登机!

深度学习是ML的一个子字段,在其中创建数据的分层表示。层次结构的较高级别由较低级别的表示形式组成。更重要的是,通过完全自动化ML中最关键的步骤(称为特征工程),可以从数据中自动学习这种表示层次。在多个抽象级别上自动学习特征允许系统直接从数据中学习输入到输出的复杂表示形式,而无需完全依赖于人工制作的特征。

深度学习模型实际上是具有多个隐藏层的神经网络,它可以帮助创建输入数据的分层层次表示。之所以称为深度,是因为我们最终使用了多个隐藏层来获取表示。用最简单的术语来说,深度学习也可以称为分层特征工程(当然,我们可以做更多的事情,但这是核心原理)。深度神经网络的一个简单示例可以是具有多个隐藏层的多层感知器(MLP)。下图中考虑基于MLP的人脸识别系统。它学习到的最低级别的特征是对比度的一些边缘和图案。然后,下一层能够使用那些局部对比的图案来模仿眼睛,鼻子和嘴唇。最后,顶层使用这些面部特征创建面部模板。深度网络正在组成简单的特征,以创建越来越复杂的特征,如下图所示:

为了理解深度学习,我们需要对神经网络的构建模块,如何训练这些网络以及如何将这样的训练算法扩展到非常大的深度网络有一个清晰的了解。在深入探讨有关神经网络的更多细节之前,让我们尝试回答一个问题:为什么现在要进行深度学习?神经网络的理论,甚至是卷积神经网络(CNN)都可以追溯到1990年代。他们之所以变得越来越受欢迎的原因归结于以下三个原因:

上面的框架列表绝对不是深度学习框架的详尽列表,但是应该使您对深度学习领域中的内容有个很好的了解。随意探索这些框架,并根据最适合您的情况选择任何一个。

涉及的主要组件如下:

让我们更详细地研究这些组件中的每个组件,并逐步执行过程,以帮助您建立自己的深度学习环境。

如今,有多家云提供商的价格可承受且具有竞争力。我们希望利用平台即服务(PaaS)功能来管理数据,应用和基本配置。

下图显示了一些流行的云提供商:

受欢迎的提供商包括亚马逊的AWS,微软的Azure和Google的Google云平台(GCP)。就本教程和本书而言,我们将利用AWS。

单击启动实例按钮应带您到该页面,以选择您自己的AmazonMachineImage(AMI)。通常,AMI由构建虚拟服务器所需的各种软件配置组成。它包括以下内容:

选择AMI之后,您需要选择实例类型。对于支持GPU的深度学习,我们建议使用p2.xlarge实例,该实例功能强大且经济实惠,每小时使用成本约为0.90美元(截至2018年)。

P2实例最多可提供16个NVIDIAK80GPU,64个vCPU和732GiB主机内存,以及总共192GB的GPU内存,如以下屏幕快照所示:

接下来是配置实例详细信息。除非希望启动多个实例,指定子网首选项以及指定关闭行为,否则可以保留默认设置。

下一步涉及添加存储详细信息。通常,您具有根卷,可以在根卷中根据需要增加其大小,并添加额外的弹性块存储(EBS)卷以增加磁盘空间。

然后,我们看一下是否需要添加标签(区分大小写和键值对)。目前我们不需要这个,所以我们跳过它。

我们将重点放在配置安全组的下一步上,特别是如果您想通过利用功能强大的Jupyter笔记本从外部访问深度学习设置。为此,我们创建一个新的安全组并创建一个CustomTCP规则以打开并启用对端口8888的访问,如下所示:

请注意,此规则通常允许任何IP监听您实例(我们将在其中运行Jupyter笔记本的实例)上的端口(8888)。如果需要,可以更改此设置,仅添加特定PC或笔记本电脑的IP地址,以提高安全性。除此之外,我们稍后还将为Jupyter笔记本添加一个额外的密码保护功能,以提高安全性。

最后,您将需要通过创建密钥对(公钥和私钥)来启动实例,以安全地连接到实例。如果您没有现有的密钥对,则可以创建一个新的密钥对,将私钥文件安全地存储到磁盘上,然后启动实例,如以下屏幕快照所示:

请注意,虚拟服务器启动和启动可能需要几分钟,因此您可能需要稍等片刻。通常,您可能会发现由于帐户的限制或容量不足而导致实例启动失败。

如果遇到此问题,您可以请求增加使用的特定实例类型的限制(在我们的例子中为p2.xlarge):

通常,AWS会在不到24小时内响应并批准您的请求,因此您可能需要稍等片刻才能获得批准,然后才可以启动实例。启动实例后,您可以签出“实例”部分并尝试连接到该实例:

您可以使用本地系统中的命令提示符或终端(之前已存储了先前的私有AWS密钥)来立即连接到实例:

让我们设置一些基本配置,以利用Jupyter笔记本的功能在虚拟服务器上进行分析和深度学习建模,而无需始终在终端上进行编码。首先,我们需要设置SSL证书。让我们创建一个新目录:

ubuntu@ip:~$mkdirsslubuntu@ip:~$cdsslubuntu@ip:~/ssl$进入目录后,我们将利用OpenSSL创建新的SSL证书:

ubuntu@ip:~/ssl$sudoopensslreq-x509-nodes-days365-newkeyrsa:1024-keyout"cert.key"-out"cert.pem"-batchGeneratinga1024bitRSAprivatekey......++++++...++++++writingnewprivatekeyto'cert.key'-----ubuntu@ip:~/ssl2$lscert.keycert.pem现在,我们需要在前面提到的Jupyter笔记本中添加基于密码的安全性的附加层。为此,我们需要修改Jupyter的默认配置设置。如果您没有Jupyter的config文件,则可以使用以下命令生成它:

$jupyternotebook--generate-config要为笔记本计算机启用基于密码的安全性,我们需要首先生成一个密码及其哈希。我们可以如下利用Ipython.lib中的passwd()函数:

ubuntu@ip:~$ipythonPython3.4.3(default,Nov172016,01:08:31)Type'copyright','credits'or'license'formoreinformationIPython6.1.0--AnenhancedInteractivePython.Type''forhelp.In[1]:fromIPython.libimportpasswdIn[2]:passwd()Enterpassword:Verifypassword:Out[2]:'sha1:e9ed12b73a30:142dff0cdcaf375e4380999a6ca17b47ce187eb6'In[3]:exitubuntu@:~$输入密码并进行验证后,该函数将向您返回一个哈希值,即您的密码哈希值(在这种情况下,我键入的密码密钥实际上是单词password,因此您绝对不应使用!)。复制并保存该哈希值,因为我们很快将需要它。

接下来,启动您喜欢的文本编辑器以编辑Jupyterconfig文件,如下所示:

ubuntu@ip:~$vim~/.jupyter/jupyter_notebook_config.py#Configurationfileforjupyter-notebook.c=get_config()#thisistheconfigobjectc.NotebookApp.certfile=u'/home/ubuntu/ssl/cert.pem'c.NotebookApp.keyfile=u'/home/ubuntu/ssl/cert.key'c.IPKernelApp.pylab='inline'c.NotebookApp.ip='*'c.NotebookApp.open_browser=Falsec.NotebookApp.password='sha1:e9ed12b73a30:142dff0cdcaf375e4380999a6ca17b47ce187eb6'#replacethis#pressitoinsertnewtextandthenpress'esc'and:wqtosaveandexitubuntu@ip:~$现在,在开始构建模型之前,我们将研究实现深度学习的一些基本依赖项。

深度学习有几个主要方面,并且针对Python利用GPU支持的深度学习。我们将尽力介绍基本知识,但可以根据需要随时参考其他在线文档和资源。您也可以跳过这些步骤,转到下一部分,以测试服务器上是否已启用启用GPU的深度学习。较新的AWS深度学习AMI设置了支持GPU的深度学习。

但是,通常设置不是最好的,或者某些配置可能是错误的,因此(如果您看到深度学习没有利用您的GPU,(从下一部分的测试中),您可能需要遍历这些知识。您可以转到“访问深度学习云环境”和“验证深度学习环境上的GPU启用”部分,以检查Amazon提供的默认设置是否有效。然后,您无需麻烦执行其余步骤!

首先,您需要检查是否已启用NvidiaGPU,以及GPU的驱动程序是否已正确安装。您可以利用以下命令进行检查。请记住,p2.x通常配备有TeslaGPU:

ubuntu@ip:~$sudolshw-businfo|grep-idisplaypci@0000:00:02.0displayGD5446pci@0000:00:1e.0displayGK210GL[TeslaK80]ubuntu@ip-172-31-90-228:~$nvidia-smi如果正确安装了驱动程序,则应该看到类似于以下快照的输出:

如果出现错误,请按照以下步骤安装NvidiaGPU驱动程序。切记根据您使用的OS使用其他驱动程序链接。我有一个较旧的Ubuntu14.04AMI,为此,我使用了以下命令:

请记住,CUDA非常特定于版本,并且我们的Python深度学习框架的不同版本仅与特定CUDA版本兼容。我将在本章中使用CUDA8。如果已经为您安装了CUDA,并且与服务器上的深度学习生态系统一起正常工作,请跳过此步骤。

要安装CUDA,请运行以下命令:

ubuntu@ip:~$sudopipinstallkeras--upgradeubuntu@ip:~$sudopip3installkeras--upgradeubuntu@ip:~$rm~/.keras/keras.json现在,我们几乎准备开始利用云上的深度学习设置。紧紧抓住!

我们真的不想一直坐在服务器上的终端并在其中进行编码。由于我们要利用Jupyter笔记本进行交互式开发,因此我们将从本地系统访问云服务器上的笔记本。为此,我们首先需要在远程实例上启动Jupyter笔记本服务器。

sudossh-imy-dl-box.pem-N-f-Llocal_machine:local_port:remote_machine:remote_portubuntu@ec2-xxxxx.compute-1.amazonaws.com这将开始将本地计算机的端口(在我的情况下为8890)转发到远程虚拟服务器的端口8888。以下是我用于设置的内容:

如果到目前为止您已正确完成所有操作,则应在浏览器中看到一个警告屏幕,并且按照以下屏幕截图中的步骤进行操作,则在任何笔记本上工作时,都应该会看到熟悉的Jupyter用户界面:

您可以放心地忽略“您的连接不是私人警告”;之所以显示它,是因为我们自己生成了SSL证书,并且尚未得到任何可信机构的验证。

最后一步是确保一切正常,并且我们的深度学习框架正在利用我们的GPU(我们需要按小时支付!)。您可以参考TestGPUenabling.ipynbJupyter笔记本来测试所有代码。我们将在这里详细介绍。我们首先要验证的是keras和tensorflow是否已正确加载到我们的服务器中。可以通过如下导入它们来验证:

importkerasimporttensorflowUsingTensorFlowbackend.如果您看到前面的代码加载没有错误,那就太好了!否则,您可能需要追溯以前执行的步骤,并在线搜索要获取的特定错误;查看每个框架的GitHub存储库。

最后一步是检查tensorflow是否已启用以使用我们服务器的NvidiaGPU。您可以使用以下测试对此进行验证:

In[1]:fromtensorflow.python.clientimportdevice_lib...:device_lib.list_local_devices()Out[1]:[name:"/cpu:0"device_type:"CPU"memory_limit:268435456locality{}incarnation:9997170954542835749,name:"/gpu:0"device_type:"GPU"memory_limit:11324823962locality{bus_id:1}incarnation:10223482989865452371physical_device_desc:"device:0,name:TeslaK80,pcibusid:0000:00:1e.0"]如果您观察到上述输出,则可以看到我们的GPU列在设备列表中,因此在训练我们的深度学习模型时它将利用相同的GPU。您已经在云上成功建立了强大的深度学习环境,您现在可以使用它使用GPU来更快地训练深度学习模型!

永远记住,AWS按小时收费实例,并且您不希望在完成分析和构建模型后保持实例运行。您始终可以根据需要从EC2控制台重新启动实例。

通常,用户或组织可能不希望利用云服务,尤其是在其数据敏感的情况下,因此要专注于构建本地深度学习环境。这里的主要重点应该是投资于正确的硬件类型,以实现最佳表现并利用正确的GPU来构建深度学习模型。关于硬件,特别强调以下方面:

您不应该忽略的其他事项包括主板,电源,坚固的外壳和散热器。

设置完钻机之后,对于软件配置,您可以重复上一部分中的所有步骤,但不包括云设置,您应该一切顺利!

让我们尝试熟悉一下神经网络背后的一些基本概念,这些基本概念使所有深度学习模型都获得成功!

线性神经元是深度神经网络的最基本组成部分。可以如下图所示。在这里,X={x1,...,xn}代表输入向量,w[i]是神经元的权重。给定一个包含一组输入目标值对的训练集,线性神经元尝试学习一种线性变换,该变换可以将输入向量映射到相应的目标值。基本上,线性神经元通过线性函数W^Tx=y近似输入输出关系:

简单线性神经元和简单非线性神经元的示意图

让我们尝试用这个简单的神经元为玩具问题建模。员工A从自助餐厅购买午餐。他们的饮食包括鱼,薯条和番茄酱。他们每个人得到几个部分。收银员只告诉他们一顿饭的总价。几天后,他们能算出每份的价格吗?

好吧,这听起来像一个简单的线性编程问题,可以很容易地通过解析来解决。让我们使用前面的线性神经单元来表示这个问题。在这里,X={x[fish],x[ketchup],x[chips]}和我们有相应的权重(w[fish],w[ketchup],w[chips])。

每个进餐价格对各部分的价格给出线性约束:

假设t[n]为真实价格,y[n]由我们的模型估计的价格,由前面的线性方程式给出。目标与我们的估计之间的剩余价格差为t[n]-y[n]。现在,不同餐点的这些残差可以为正或负,并且可以抵消,从而使总体误差为零。处理此问题的一种方法是使用平方和残差:

如果我们能够最大程度地减少此误差,则可以对每件商品的一组权重/价格进行很好的估计。因此,我们得出了一个优化问题。让我们首先讨论一些解决优化问题的方法。

优化基本上涉及最小化或最大化某些函数f(x),其中x是数值向量或标量。在此,f(x)被称为目标函数或准则。在神经网络中,我们称其为成本函数,损失函数或误差函数。在前面的示例中,我们要最小化的损失函数为E。

假设我们有一个函数y=f(x),其中x和y是实数。此函数的导数告诉我们此函数如何随x的微小变化而变化。因此,可以通过无穷大地更改x来使用导数来减小函数的值。假设对于x,f'(x)>0。这意味着,如果我们沿着x的正数增加x,则f(x)将会增加,因此对于足够小的ε,f(x-ε)

函数值沿导数的相反方向或相反方向的变化方式

如果导数f'(x)<0,则导数不提供信息,我们需要朝哪个方向移动以达到函数最小值。在局部最优(最小/最大)时,导数可以为零。如果x处的函数f(x)的值小于所有相邻点,则将点称为局部最小值。同样,我们可以定义一个局部最大值。某些点既不能是最大值,也不能是最小值,但是导数f'(x)在这些点上为零。这些称为鞍点。下图说明了f'(x)=0的三种情况:

单个变量函数的最小,最大和鞍点。在所有三个突出显示的点上导数f'(x)=0

在x的所有可能值中达到f的最小值的点称为全局最小值。一个函数可以具有一个或多个全局最小值。可能存在局部最小值,而不是全局最小值。但是,如果函数是凸函数,则可以保证它只有一个全局最小值,而没有局部最小值。

通常,在ML中,我们希望最小化几个变量f的实值函数:R^n->R。几个变量的实值函数的一个简单示例是热板温度函数f(x1,x2)=50-x1^2-2x2^2,其在板上的坐标为x=(x1,x2)。在深度学习中,我们通常最小化损失函数,该函数是多个变量(例如神经网络中的权重)的函数。这些函数具有许多局部最小值,许多鞍点被非常平坦的区域包围,并且它们可能具有也可能没有任何全局最小值。所有这些使得优化此类函数非常困难。

几个变量的函数的导数表示为偏导数,当我们更改其中一个输入变量x[i],并保持其他不变时,它将衡量函数的变化率。关于所有变量的偏导数向量称为f的梯度向量,用f表示。我们还可以找出函数相对于任意方向v(单位向量)的变化速度。这是通过在单位向量v,即点积f·v的方向上投影梯度向量f来计算的。这在v方向上被称为f的定向导数,通常用[v]表示。为了使f最小化,我们需要找到一个方向u,在其中要更改x,以使f的值最大程度地减小。

令x[a]为非常接近x的点,即||x-x[a]||非常小。首先,泰勒级数围绕x的阶展开式为:

上式中的最后一项对于x[a]足够接近x可以忽略。第二项表示f沿x[a]-x的方向导数。这里有:

因此,如果cos(θ)最小,则f(x)最大减小,即-1,如果θ=π,即x[a]-x应该指向与梯度向量,f相反的方向,则f(x)会最大程度地减小。这是最陡下降方向:-f或最陡梯度下降的方向。我们在下图中对此进行说明:

热板

让我们使用tensorflow实现热板温度函数的梯度下降优化。我们需要初始化梯度下降,所以让我们从x=y=2开始:

Startingatcoordinatex=2.0,y=2.0andtemperaturethereis38.0step(0)x=2.79,y=2.40000,T=28.55,Gradient=[-11.2,-4.8000002]step(1)x=3.92,y=2.88000,T=10.97,Gradient=[-15.68,-5.7600002]..........step(9)x=57.85,y=12.38347,T=-6796.81,Gradient=[-231.40375,-24.766947]Jacobian矩阵和Hessian矩阵有时,我们需要优化其输入和输出为向量的函数。因此,对于输出向量的每个分量,我们需要计算梯度向量。对于f:R^n->R^m,我们将有m个梯度向量。通过将它们排列成矩阵形式,我们得到nxm个偏导数J[ij]=f(x)[i]/x[j]的矩阵,称为Jacobian矩阵。

对于单个变量的实值函数,如果要在某个点测量函数曲线的曲率,则需要计算在更改输入时导数将如何变化。这称为二阶导数。二阶导数为零的函数没有曲率,并且是一条平线。现在,对于几个变量的函数,有许多二阶导数。这些导数可以布置在称为Hessian矩阵的矩阵中。由于二阶偏导数是对称的,即:

对于我们的温度示例,Hessian为:

最大曲率的方向是最小曲率的方向的两倍。因此,沿着y遍历,我们将更快地到达最小点。从前面的热板图中所示的温度轮廓中也可以看出这一点。

我们可以使用二阶导数曲率信息来检查最佳点是最小还是最大。对于单个变量,f'(x)=0,f''(x)>0表示x是f的局部最小值,并且f'(x)=0,f''(x)<0表示x是局部最大值。这称为二阶导数测试(请参见下图解释曲率)。类似地,对于几个变量的函数,如果Hessian在x为正定(即所有本征值均为正),则f会在x达到局部最小值。如果Hessian在x处为负定值,则f在x处达到局部最大值。如果Hessian同时具有正和负特征值,则x是f的鞍点。否则,测试没有定论:

解释曲率

存在基于使用曲率信息的二阶导数的优化算法。牛顿法就是这样一种方法,对于凸函数,它只需一步就可以达到最佳点。

令f和g均为单个变量的实值函数。假设y=g(x)和z=f(g(x))=f(y)。

然后,导数的链式规则指出:

同样,对于几个变量的函数,令x∈R^m,y∈R^n,g:R^m->R^n,f:R^n->R,y=g(x),z=f(y),然后:

因此,z相对于x的梯度z/x表示为Jacobiany/x与z/y梯度向量的乘积。因此,对于多个变量的函数,我们具有导数的链式规则,如下所示:

神经网络学习算法由几个这样的雅可比梯度乘法组成。

几乎所有的神经网络学习都由一种非常重要的算法提供支持:SGD。这是常规梯度下降算法的扩展。在ML中,损失函数通常写为样本损失函数之和,作为自助餐厅示例中的平方误差E。因此,如果我们有m个训练示例,则梯度函数也将具有m个可加项。

SGD取决于对梯度实际上是期望值的简单理解。我们可以通过在小样本集上计算期望值来近似。可以从训练集中随机抽取m'(比m小得多的小批量)样本大小,并且梯度可以近似为计算单个梯度下降步骤。让我们再次考虑自助餐厅示例。应用链式规则,误差函数(三个变量的函数)的梯度由下式给出:

现在,代替使用所有n训练示例来计算导数,如果我们从训练示例中抽取少量随机样本,我们仍然可以合理地近似导数。

E的梯度给出了权重更新的估计值。我们可以通过将其乘以一个常数ε(称为学习率)来进一步控制它。取得非常高的学习率可能会增加而不是使优化目标函数值最小化。

在SGD中,在将每个小批量展示给算法后,将更新权重。将整个训练数据一次呈现给训练算法需要很多数据点/批量大小的步骤。一个周期描述了算法看到整个数据集的次数。

以下是自助餐厅问题的keras代码。假设鱼类的实际价格为150美分,薯条为50美分,番茄酱为100美分。我们已随机生成餐中物品的样本部分。假设初始的价格为每份50美分。30个周期后,我们得到的估计值与商品的真实价格非常接近:

学习率对自助餐厅问题SGD收敛速度的影响

下表显示了SGD在LR=0.01的连续周期如何更新价格猜测:

线性神经元很简单,但是在计算上受到限制。即使我们使用多层线性单元的深层栈,我们仍然具有仅学习线性变换的线性网络。为了设计可以学习更丰富的转换集(非线性)的网络,我们需要一种在神经网络的设计中引入非线性的方法。通过使输入的线性加权总和通过非线性函数,我们可以在神经单元中引起非线性。

尽管非线性函数是固定的,但是它可以通过线性单元的权重来适应数据,权重是该函数的参数。此非线性函数称为非线性神经元的激活函数。一个简单的激活函数示例是二元阈值激活,相应的非线性单元称为McCulloch-Pitts单元。这是一个阶跃函数,不可微分为零。同样,在非零点,其导数为零。其他常用的激活函数是Sigmoid,tanh和ReLu。下图提供了这些函数的定义和图解:

激活函数图

这是激活函数定义:

如果我们有一个K类(K>2)分类问题,那么我们基本上想学习条件概率分布P(y|x)。因此,输出层应具有K个神经元,其值应为1。为了使网络了解所有K单元的输出应为1,使用softmax激活函数。这是Sigmoid激活的概括。像Sigmoid函数一样,softmax函数将每个单元的输出压缩为0到1之间。

而且,它会将每个输出相除,以使输出的总和等于1:

数学上,softmax函数如下所示,其中z是输出层输入的向量(如果有10个输出单元,则z中有10个元素)。同样,j索引输出单元,因此j=1,2,...,K:

假设我们有两个类分类问题;也就是说,我们需要预测二元结果变量y的值。就概率而言,结果y取决于特征x的伯努利分布。神经网络需要预测概率P(y=1|x)。为了使神经网络的输出成为有效概率,它应该位于[0,1]中。为此,我们使用Sigmoid激活函数并获得非线性逻辑单元。

要学习逻辑单元的权重,首先我们需要一个成本函数并找到成本函数的导数。从概率的角度来看,如果我们想最大化输入数据的可能性,则交叉熵损失会作为自然成本函数出现。假设我们有一个训练数据集X={x[n],t[n]},n=1,…,N,似然函数可以写成:

其中y[n]是在将x[n]作为输入数据传递到逻辑单元之后,Sigmoid单元的输出。注意t和w分别表示Sigmoid单元的目标向量(训练集中的所有N个目标值)和权重向量(所有权重的集合)。可以通过采用似然性的负算法来定义误差函数,这给出了交叉熵代价函数:

要学习逻辑神经单元的权重,我们需要关于每个权重的输出导数。我们将使用导数的链式规则来导出逻辑单元的误差导数:

让:

因此:

就线性单元的平方误差损失而言,我们发现的导数看起来与导数非常相似,但它们并不相同。让我们仔细看一下交叉熵损失,看看它与平方误差有何不同。我们可以如下重写交叉熵损失:

现在,让我们尝试将平方误差损失与逻辑输出一起使用。因此,我们的成本函数为:

该误差导数直接取决于Sigmoid函数σ'(y[n])的导数。现在,当y[n]高度负值时,Sigmoid函数趋于0;当y[n]高度正值时,Sigmoid函数趋于1。从Sigmoid曲线的平坦水平区域可以明显看出,对于y[n]的这种值,梯度可以缩小得太小。因此,即使t[n]和y[n]不一致,对于这些数据点,平方误差导数也将具有很小的更新。也就是说,它们被网络严重错误分类。这称为消失梯度问题。因此,基于最大似然的交叉熵损失几乎始终是训练逻辑单元的首选损失函数。

损失函数将神经网络的输出与训练中的目标值进行比较,产生一个损失值/分数,以测量网络的预测与期望值的匹配程度。在上一节中,我们看到了针对不同任务(例如回归和二分类)的不同类型损失函数的需求。以下是一些其他流行的损失函数:

神经网络训练的训练集中的所有输入和目标都必须表示为张量(或多维数组)。张量实际上是将二维矩阵推广到任意数量的维。通常,这些是浮点张量或整数张量。无论原始输入数据类型是什么(图像,声音,文本),都应首先将其转换为合适的张量表示形式。此步骤称为数据向量化。以下是本书中经常使用的不同维度的张量:

通过将三维张量放置在一个数组中,可以创建三维张量。等等。在深度学习中,通常我们使用零维到四维张量。

张量具有三个关键属性:

以下是在讨论迁移学习用例时将经常使用的一些示例张量。

可以通过一组张量运算来表述用于训练/测试深度神经网络的所有计算。例如,张量的相加,相乘和相减。以下是本书中一些常用的张量运算:

我们可以将其视为输入模式为X={(0,0),(0,1),(1,0),(1,1)}的模式分类问题。第一个和第四个在类0中,其他在第1类中。让我们将此问题视为回归问题,损失为均方误差(MSE),并尝试使用线性单元。通过分析求解,得出所需权重:w=(0,0)和偏差:b=1/2。该模型为所有输入值输出0.5。因此,简单的线性神经元无法学习XOR函数。

解决XOR问题的一种方法是使用输入的不同表示形式,以便线性模型能够找到解决方案。这可以通过向网络添加非线性隐藏层来实现。我们将使用带有两个隐藏单元的ReLU层。输出是布尔值,因此最适合的输出神经元是逻辑单元。我们可以使用二元交叉熵损失来学习权重:

让我们使用SGD学习此网络的权重。以下是XOR函数学习问题的keras代码:

model_input=Input(shape=(2,),dtype='float32')z=Dense(2,name='HiddenLayer',kernel_initializer='ones')(model_input)z=Activation('relu')(z)#hiddenactivationReLuz=Dense(1,name='OutputLayer')(z)model_output=Activation('sigmoid')(z)#Outputactivationmodel=Model(model_input,model_output)model.summary()#CompilemodelwithSGDoptimization,withlearningrate=0.5sgd=SGD(lr=0.5)model.compile(loss="binary_crossentropy",optimizer=sgd)#Thedatasetisverysmall-willusefullbatch-settingbatchsize=4model.fit(X,y,batch_size=4,epochs=300,verbose=0)#Outputofmodelpreds=np.round(model.predict(X),decimals=3)pd.DataFrame({'Y_actual':list(y),'Predictions':list(preds)})前面代码的输出如下:

(左)显示4点的原始空间-显然没有行可以将0类{(0,0),(1,1)}与其他类分开。(中心)显示隐藏的ReLU层学习到的变换空间。(右)该表显示了通过该函数获得的预测值

具有一层隐藏层的神经网络能够学习XOR函数。这个例子说明了神经网络需要非线性隐藏层来做有意义的事情。让我们仔细看一下隐藏层学习了哪些输入转换,从而使输出逻辑神经元学习该函数。在Keras中,我们可以从学习的模型中提取中间隐藏层,并使用它来提取传递给输出层之前输入的转换。上图显示了如何转换四个点的输入空间。转换后,可以用一条线轻松地分隔1类和0类点。这是为原始空间和变换后的空间生成图的代码:

importmatplotlib.pyplotasplt#ExtractintermediateLayerfunctionfromModelhidden_layer_output=Model(inputs=model.input,outputs=model.get_layer('HiddenLayer').output)projection=hidden_layer_output.predict(X)#usepredictfunctiontoextractthetransformations#Plottingthetransformedinputfig=plt.figure(figsize=(5,10))ax=fig.add_subplot(211)plt.scatter(x=projection[:,0],y=projection[:,1],c=('g'))通过堆叠多个非线性隐藏层,我们可以构建能够学习非常复杂的非线性输入输出转换的网络。

为了训练深层的神经网络,我们仍然可以使用梯度下降SGD。但是,SGD将需要针对网络的所有权重计算损失函数的导数。我们已经看到了如何应用导数链式规则来计算逻辑单元的导数。

现在,对于更深的网络,我们可以逐层递归地应用相同的链式规则,以获得与网络中不同深度处的层对应的权重有关的损失函数的导数。这称为反向传播算法。

反向传播算法是在单个训练示例上针对每个权重计算误差导数dE/dθ的有效方法。为了理解反向传播算法,让我们首先代表一个带有计算图符号的神经网络。神经网络的计算图将具有节点和有向边,其中节点代表变量(张量),边代表连接到下一个变量的变量的运算。如果y=f(x),则变量x通过有向边连接到y,对于某些函数f。

例如,逻辑单元的图形可以表示如下:

(左)逻辑回归作为计算图。(右)三层网络计算图的BP算法信息流

我们用u[1],u[2],...,u[n]表示计算节点。另外,我们按顺序排列节点,以便可以一个接一个地计算它们。u[n]是一个标量-损失函数。让我们用节点θ[k]表示网络的参数或权重。要应用梯度下降,我们需要计算所有导数u^n/θ[k]。可以通过遵循从输入节点到最终节点u^n的计算图中的有向路径来计算该图的正向计算。这称为前向传播。

由于图中的节点为张量,因此要计算偏导数u^n/θ[k],将使用多个变量函数的导数链式规则,该规则由雅可比矩阵与梯度的乘积表示。反向传播算法涉及一系列这样的雅可比梯度积。

反向传播算法表示如下:

我们将使用完全连接的三层神经网络解释反向传播。上图显示了为此的计算图。令z(i)表示图中的计算节点。为了执行反向传播,导数C/z(i)的计算将与正向传递的反向顺序完全相同。这些由向下箭头指示。让我们表示关于层l的输入z(l)的成本函数的导数δ(l)。对于最顶层,让δ(4)=1。为了递归计算,让我们考虑一个单层。一层具有输入z(l)和输出z(l+1)。同样,该层将接受输入δ(l+1)并产生δ(l)和C/θ[l]。

对于层l:

i代表梯度δ(l)[i]的第i个分量。

因此,我们得出了用于计算反向消息的递归公式。使用这些,我们还可以计算关于模型参数的成本导数,如下所示:

反向传播算法在计算图中相对于其祖先x,计算标量成本函数z的梯度。该算法开始于计算关于其本身的成本z的导数z/z=1。可以通过将当前梯度乘以产生z的运算的雅可比行列式来计算关于z父级的梯度。我们一直向后遍历计算图并乘以雅可比行列式,直到达到输入x为止。

通常,优化是一项非常困难的任务。在本节中,我们讨论了用于训练深度模型的优化方法所涉及的一些常见挑战。了解这些挑战对于评估神经网络模型的训练表现并采取纠正措施以缓解问题至关重要。

让我们考虑我们要优化的f(x)函数的二阶泰勒级数逼近。z[0]点的泰勒级数由下式给出:

其中g是梯度向量,H是f(x)在x[0]时的Hessian。如果ε是我们使用的学习率,则根据梯度下降的新点为x[0]-ε[g]。将其替换为Taylor系列展开式,我们得到:

注意,如果-εg^tg+ε^2g^TH[g]>0,则与x[0]相比,新点的函数值会增加。同样,在存在强梯度的情况下,我们将具有较高的平方梯度范数||g||^2=g^Tg,但同时,如果其他数量为g^TH[g]增长一个数量级,那么我们将看到f(x)的下降速度非常缓慢。但是,如果此时可以缩小学习率ε,则可能会在某种程度上使这种影响无效,因为g^TH[g]数量乘以ε^2。可以通过在训练周期绘制平方梯度范数和g^TH[g]来监测疾病的影响。我们在热板中看到了如何计算梯度范数的示例。

DNN模型实质上可以保证具有极大数量的局部最小值。如果局部最小值与全局最小值相比成本较高,则可能会出现问题。长期以来,人们一直认为,由于存在这样的局部极小值,神经网络训练受到了困扰。这仍然是一个活跃的研究领域,但是现在怀疑对于DNN,大多数局部最小值具有较低的成本值,没有必要找到全局最小值,而是在权重空间中具有足够低的成本函数值。可以通过监视梯度范数来检测强局部极小值的存在。如果梯度范数减小到很小的数量级,则表明存在局部极小值。

鞍点是既不是最大值也不是最小值的点,而是被平坦区域围绕,该平坦区域的一侧目标函数值增大,而另一侧目标函数减小。由于该平坦区域,梯度变得非常小。然而,已经观察到,凭经验梯度下降迅速逃离了这些区域。

高度非线性DNN的目标函数具有非常陡峭的区域,类似于悬崖,如下图所示。在极陡峭的悬崖结构的负梯度方向上移动会使权重移得太远,以致我们完全跳下悬崖结构。因此,在我们非常接近的时候错过了极小值。

因此,取消了为达到当前解决方案所做的许多工作:

解释何时需要裁剪梯度范数

在Keras中,可以如下实现:

解释初始化误差的情况以及对基于梯度的优化的影响

大多数优化算法都是基于这样的假设,即我们在给定点具有已知的精确梯度。但是,实际上我们只对梯度有一个估计。这个估计有多好?在SGD中,批次大小会极大地影响随机优化算法的行为,因为它确定了梯度估计的方差。

总之,可以通过以下四个技巧来解决神经网络训练中面临的不同问题:

现在,让我们简要讨论一下各种启发式方法/策略,这些方法使学习DNN切实可行并继续使深度学习取得巨大成功。

以下是初始点的选择如何影响深度神经网络的迭代学习算法的表现:

初始化算法主要是启发式的。良好初始化的全部要点是可以以某种方式使学习更快。初始化的重要方面之一是破坏初始权重集对隐藏层单元的对称性。如果以相同的权重对其进行初始化,则在网络相同级别上具有相同激活函数的两个单元将被同等更新。多个单元保留在隐藏层中的原因是它们应该学习不同的特征。因此,获得同等更新不会影响其他特征的学习。

打破对称性的一种简单方法是使用随机初始化-从高斯或均匀分布中采样。模型中的偏差参数可以通过启发式选择常量。选择权重的大小取决于优化和正则化之间的权衡。正则化要求权重不应太大-这可能导致不良的泛化表现。优化需要权重足够大,才能成功地通过网络传播信息。

让我们考虑具有m输入和n输出单元的密集层:

初始化方案也可以视为神经网络训练中的超参数。如果我们有足够的计算资源,则可以评估不同的初始化方案,我们可以选择具有最佳泛化表现和更快的收敛速度的方案。

近年来,已提出了不同的优化算法,这些算法使用不同的方程式更新模型的参数。

成本函数可能具有高曲率和较小但一致的梯度的区域。这是由于Hessian矩阵的条件不佳以及随机梯度的方差。SGD在这些地区可能会放慢很多速度。动量算法会累积先前梯度的指数加权移动平均值(EWMA),并朝该方向移动,而不是SGD建议的局部梯度方向。指数加权由超参数α∈[0,1)控制,该超参数确定先前梯度的影响衰减的速度。动量法通过组合相反符号的梯度来阻尼高曲率方向上的振荡。

Nesterov动量是动量算法的一种变体,仅在计算梯度时与动量方法不同。标准动量法首先在当前位置计算梯度,然后在累积梯度的方向上发生较大的跳跃。涅斯特罗夫动量首先沿先前累积的梯度的方向跃升,然后计算新点的梯度。通过再次采用所有先前梯度的EWMA来校正新梯度:

在前面的方法中,将相同的学习率应用于所有参数更新。由于数据稀疏,我们可能想在不同程度上更新参数。诸如AdaGrad,AdaDelta,RMSprop和Adam之类的自适应梯度下降算法通过保持每个参数的学习率,提供了经典SGD的替代方法。

AdaGrad算法通过按与先前所有梯度的平方和值的平方根成比例的方式将它们成反比例缩放来调整每个连接的学习率。因此,在误差表面的平缓倾斜方向上进行了较大的移动。但是,从一开始就采用这种技巧可能会导致某些学习率急剧下降。但是,AdaGrad在一些深度学习任务上仍然表现出色。

RMSprop通过采用先前平方梯度的EWMA来修改AdaGrad算法。它具有移动平均参数ρ,它控制移动平均的长度和比例。这是深度神经网络训练最成功的算法之一。

自适应力矩(Adam)。它充分利用了基于动量的算法和自适应学习率算法,并将它们组合在一起。在此,动量算法应用于由RMSprop计算的重新缩放的梯度。

与其他任何ML训练一样,用于训练深度学习模型的数据集也分为训练,测试和验证。在模型的迭代训练期间,通常,验证误差比训练误差略大。如果测试误差和验证误差之间的差距随着迭代的增加而增加,则是过拟合的情况。如果训练误差不再减小到足够低的值,我们可以得出结论,该模型是欠拟合的。

模型的能力描述了模型可以建模的输入输出关系的复杂性。也就是说,在模型的假设空间中允许有多大的函数集。例如,可以将线性回归模型推广为包括多项式,而不只是线性函数。这可以通过在构建模型时将x的n积分乘以x作为积分来完成。还可以通过向网络添加多个隐藏的非线性层来控制模型的容量。因此,我们可以使神经网络模型更宽或更深,或两者同时进行,以增加模型的容量。

但是,在模型容量和模型的泛化误差之间需要权衡:

(左):线性函数根据数据拟合而拟合。(中):适合数据的二次函数可以很好地推广到看不见的点(右)适合数据的次数为9的多项式存在过拟合的问题

具有极高容量的模型可能通过训练集中的学习模式而过拟合训练集,而训练模式可能无法很好地推广到看不见的测试集。而且,它非常适合少量的训练数据。另一方面,低容量的模型可能难以适应训练集:

在训练和验证损失方面过拟合/欠拟合

过拟合是ML中的核心问题。对于神经网络,开发了许多策略来避免过拟合并减少泛化误差。这些策略统称为正则化。

权重共享意味着同一组权重在网络的不同层中使用,因此我们需要优化的参数更少。在一些流行的深度学习架构中可以看到这一点,例如暹罗网络和RNN。在几层中使用共享权重可以通过控制模型容量来更好地推广模型。反向传播可以轻松合并线性权重约束,例如权重共享。CNN中使用了另一种权重分配方式,其中与完全连接的隐藏层不同,卷积层在局部区域之间具有连接。在CNN中,假设可以将要由网络处理的输入(例如图像或文本)分解为具有相同性质的一组局部区域,因此可以使用相同的一组转换来处理它们。是,共享权重。RNN可以被视为前馈网络,其中每个连续的层共享相同的权重集。

可以看到,像前面示例中的多项式一样,过拟合模型的权重非常大。为了避免这种情况,可以将罚分项Ω添加到目标函数中,这将使权重更接近原点。因此,惩罚项应该是权重范数的函数。同样,可以通过乘以超参数α来控制惩罚项的效果。因此我们的目标函数变为:E(w)+αΩ(w)。常用的惩罚条款是:

L1正则化导致稀疏解;也就是说,它会将许多权重设置为零,因此可以作为回归问题的良好特征选择方法。

提前停止:训练与验证误差

如果在验证误差开始增加的时候停止训练,我们可以建立一个具有更好泛化表现的模型。这称为提前停止。它由耐心超参数控制,该参数设置了中止训练之前观察增加的验证集误差的次数。提前停止可以单独使用,也可以与其他正则化策略结合使用。

丢弃法是一种在深度神经网络中进行正则化的计算廉价但功能强大的方法。它可以分别应用于输入层和隐藏层。通过在正向传递过程中将节点的输出设置为零,丢弃法随机掩盖了一部分节点的输出。这等效于从层中删除一部分节点,并创建一个具有更少节点的新神经网络。通常,在输入层上会删除0.2个节点,而在隐藏层中最多会删除0.5个节点。

模型平均(集成方法)在ML中被大量使用,通过组合各种模型的输出来减少泛化误差。套袋是一种整体方法,其中通过从训练集中替换并随机抽样来构建k不同的数据集,并在每个模型上训练单独的k模型。特别地,对于回归问题,模型的最终输出是k模型的输出的平均值。还有其他组合策略。

还可以将丢弃视为一种模型平均方法,其中通过更改应用了丢弃的基本模型的各个层上的活动节点数来创建许多模型。

在ML中,通常的做法是先缩放并标准化输入的训练数据,然后再将其输入模型进行训练。对于神经网络而言,缩放也是预处理步骤之一,并且已显示出模型表现的一些改进。在将数据馈送到隐藏层之前,我们可以应用相同的技巧吗?批量规范化基于此思想。它通过减去激活的最小批量平均值μ并除以最小批量标准差σ来归一化前一层的激活。在进行预测时,我们一次可能只有一个示例。因此,不可能计算批次均值μ和批次σ。将这些值替换为训练时收集的所有值的平均值。

使神经模型具有更好的概括性或测试表现的最佳方法是通过训练它获得更多数据。实际上,我们的训练数据非常有限。以下是一些用于获取更多训练数据的流行策略:

开发了多种用于超参数调整的方法。但是,对于大多数参数,需要为每个超参数指定一个特定范围的值。可以通过了解它们对模型容量的影响来设置大多数超参数。

网格搜索是对超参数空间的手动指定子集的详尽搜索。网格搜索算法需要表现指标,例如交叉验证误差或验证集误差,以评估最佳可能参数。通常,网格搜索涉及选择对数刻度的参数。例如,可以从集合{50,100,200,500,1000,...}中选择在集合{0.1,0.01,0.001,0.0001}内获得的学习率或多个隐藏单元。网格搜索的计算成本随着超参数的数量呈指数增长。因此,另一种流行的技术是随机网格搜索。随机搜索从所有指定的参数范围中对参数采样固定次数。当我们具有高维超参数空间时,发现这比穷举搜索更有效。更好,因为可能存在一些不会显着影响损耗的超参数。

在本章中,我们涉及了深度学习的基础知识。我们真的赞扬您为实现这一目标所做的努力!本章的目的是向您介绍与深度学习领域有关的核心概念和术语。我们首先简要介绍了深度学习,然后介绍了当今深度学习领域中流行的框架。还包括详细的分步指南,用于设置您自己的深度学习环境,以在GPU上开发和训练大规模深度学习模型。

最后,我们涵盖了围绕神经网络的基本概念,包括线性和非线性神经元,数据表示,链式规则,损失函数,多层网络和SGD。还讨论了神经网络中的学习挑战,包括围绕局部极小值和梯度爆炸的常见警告。我们研究了神经网络中过拟合和欠拟合的问题,以及处理这些问题的策略。然后,我们介绍了神经网络单元的流行初始化启发法。除此之外,我们还探索了一些更新的优化技术,它们是对香草SGD的改进,其中包括RMSprop和Adam之类的流行方法。

在下一章中,我们将探讨深度学习模型周围的各种架构,这些架构可用于解决不同类型的问题。

本章将着重于理解当今深度学习中存在的各种架构。神经网络的许多成功都在于对神经网络架构的精心设计。自1960年代的传统人工神经网络(ANNs)以来,我们已经走了很长一段路。在本书中,我们介绍了基本模型架构,例如完全连接的深度神经网络,卷积神经网络(CNN),循环神经网络(RNN),长短期记忆(LSTM)网络,以及最新的胶囊网络。

在本章中,我们将介绍以下主题:

架构一词是指神经网络的整体结构,包括其可以具有多少层以及各层中的单元应如何相互连接(例如,连续层中的单元可以完全连接),部分连接,或者甚至可以完全跳过下一层,然后再连接到网络中更高级别的一层。随着模块化深度学习框架(例如Caffe,Torch和TensorFlow)的出现,复杂的神经网络设计发生了革命性的变化。现在,我们可以将神经网络设计与Lego块进行比较,在这里您可以构建几乎可以想象的任何结构。但是,这些设计不仅仅是随机的猜测。这些设计背后的直觉通常是由设计人员对问题的领域知识以及一些反复试验来精调最终设计的结果所驱动。

前馈多层神经网络具有学习巨大的假设空间并提取每个非线性隐藏层中复杂特征的能力。那么,为什么我们需要不同的架构?让我们尝试理解这一点。

深度学习带有一个希望,即给定足够的数据,深度学习模型能够自动确定正确的特征集,即复杂性不断增加的特征层次。好吧,深度学习的希望是真实的,并且会产生误导。深度学习确实在许多情况下简化了特征工程,但是它并没有完全消除对它的需求。随着手动特征工程的减少,神经网络模型本身的架构变得越来越复杂。特定架构旨在解决特定问题。与手工特征工程相比,架构工程是一种更为通用的方法。在架构工程中,与特征工程不同,领域知识不会硬编码为特定特征,而只会在抽象级别使用。例如,如果我们要处理图像数据,则有关该数据的一个非常高级的信息是对象像素的二维局部性,而另一个是平移不变性。换句话说,将猫的图像平移几个像素仍然可以保持猫的状态。

其他高级ML问题(例如语音翻译,问题解答系统和关系建模)要求开发各种深度学习架构。

现在让我们看一些流行的神经网络架构及其应用。我们将从多层感知器(MLP)网络开始。我们已经介绍了单层感知器网络,这是最基本的神经网络架构。

MLP或简单的深层神经网络(DNNs)是神经网络架构的最基本形式。神经单元一层又一层地排列,相邻的网络层彼此完全连接。我们已经在上一章中对此进行了详细讨论:

自编码器通常用于减少神经网络中数据的维数。自编码器也已成功用于异常检测和新颖性检测问题。自编码器神经网络属于无监督学习类别。在此,目标值设置为等于输入值。换句话说,我们想学习单位特征。通过这样做,我们可以获得数据的紧凑表示。

通过最小化输入和输出之间的差异来训练网络。典型的自编码器架构是DNN架构的略微变体,其中,每个隐藏层的单元数量逐渐减少,直到某个点,然后逐渐增加,最终层尺寸等于输入尺寸。其背后的关键思想是在网络中引入瓶颈,并迫使其学习有意义的紧凑表示形式。隐藏单元的中间层(瓶颈)基本上是输入的降维编码。隐藏层的前半部分称为编码器,后半部分称为解码器。下面描述了一个简单的自编码器架构。名为z的层是此处的表示层:

深度很深的自编码器很难训练,并且容易过度安装。有许多改进了自编码器训练方式的开发,例如使用受限玻尔兹曼机(RBM)进行生成式预训练。变分自编码器(VAE)也是生成模型,与其他深层生成模型相比,VAE在计算上易于处理且稳定,可以通过有效的反向传播算法进行估计。它们受到贝叶斯分析中变分推理的启发。

变分推理的概念如下:给定输入分布x时,输出y上的后验概率分布太复杂而无法使用。因此,让我们用一个更简单的分布q(y)来近似复杂的后验p(y|x)。在这里,q是从最接近后验的分布族Q中选择的。例如,此技术用于训练潜在Dirichlet分配(LDA)(它们对文本进行主题建模,并且是贝叶斯生成模型)。但是,经典变分推论的一个关键局限性是需要对似然性和先验共轭才能进行优化。VAE引入了使用神经网络来输出条件后验的方法(Kingma和Welling,2013年),从而允许使用随机梯度下降(SGD)和反向传播来优化变分推断目标。。该方法称为重新参数化技巧。

给定数据集X,VAE可以生成与样本X类似但不一定相等的新样本。数据集X具有连续或离散随机变量x的N个独立且完全相同的样本。假设数据是通过某种随机过程生成的,涉及一个未观察到的连续随机变量z。在简单自编码器的此示例中,变量z是确定性的,并且是随机变量。数据生成是一个两步过程:

因此,p(x)基本上是边缘概率,计算公式为:

分布的参数θ和潜变量z都是未知的。在此,x可以通过从边际p(x)取样来生成。反向传播无法处理网络中的随机变量z或随机层z。假设先验分布p(z)为高斯分布,我们可以利用高斯分布的位置尺度属性,并将随机层重写为z=μ+σε,其中μ是位置参数,σ是刻度,ε是白噪声。现在,我们可以获得噪声ε的多个样本,并将它们作为确定性输入提供给神经网络。

然后,该模型成为端到端确定性深度神经网络,如下所示:

顾名思义,这是使用神经网络的另一种生成模型。GAN具有两个主要组成部分:生成器神经网络和判别器神经网络。生成器网络采用随机噪声输入,并尝试生成数据样本。判别器网络将生成的数据与真实数据进行比较,并使用S型输出激活来解决生成的数据是否为伪造的二分类问题。生成器和判别器都在不断竞争,并试图互相愚弄-这就是GAN也被称为对抗网络的原因。这种竞争驱使两个网络都提高其权重,直到判别器开始输出0.5的概率为止。也就是说,直到生成器开始生成真实图像为止。通过反向传播同时训练两个网络。这是GAN的高级结构图:

训练这些网络的损失函数可以定义如下。令p(data)为数据的概率分布,p(g)为生成器分布。D(x)表示x来自p(data)而非来自p(g)的概率。对D进行了训练,以使将正确标签分配给G的训练示例和样本的概率最大化。同时,训练G以最小化log(1-D(G(z)))*。因此,D和G玩一个具有值函数V(D,G)的两人minimax游戏:

可以证明,对于p(g)=p(data)来说,这种极小极大游戏具有全局最优性。

以下是通过反向传播训练GAN以获得所需结果的算法:

forNepochsdo:#updatediscriminatornetfirstforkstepsdo:Sampleminibatchofmnoisesamples{z(1),,...,z(m)}fromnoisepriorpg(z).Sampleminibatchofmexamples{x(1),...,x(m)}fromdatageneratingdistributionpdata(x).Updatethediscriminatorby:endforSampleminibatchofmnoisesamples{z(1),...,z(m)}fromnoisepriorpg(z).Updatethegeneratorbydescendingitsstochasticgradient:endfor使用GAN架构的文本到图像合成让我们看看使用GAN从文本描述生成图像。下图显示了这种GAN的完整架构:

这是条件GAN的一种。生成器网络获取带有噪声向量的输入文本以生成图像。生成的图像以输入文本为条件。使用嵌入层φ(t)将图像描述转换为密集向量。使用完全连接的层对其进行压缩,然后将其与噪声向量连接。检测器网络是CNN,并且生成器网络的架构使用具有与CNN网络中使用的过滤器相同的过滤器的反卷积层。反卷积基本上是转置的卷积,我们将在后面讨论。

CNN是专门设计用于识别形状图案的多层神经网络,这些形状图案对于二维图像数据的平移,缩放和旋转具有高度不变性。这些网络需要以监督的方式进行训练。通常,提供一组标记的对象类(例如MNIST或ImageNet)作为训练集。任何CNN模型的关键都在于卷积层和子采样/合并层。因此,让我们详细了解在这些层中执行的操作。

该职位的估计可以写成:

这里,权重函数w(t)被称为卷积的内核。我们可以使用卷积计算位置传感器数据的简单移动平均值(SMA)。令m为SMA的窗口大小。

内核定义为:

这是使用卷积的SMA的NumPy实现:

x=[1,2,3,4,5,6,7]m=3#movingaveragewindowsizesma=np.convolve(x,np.ones((m,))/m,mode='valid')#Outputs#array([2.,3.,4.,5.,6.])在深度学习中,输入通常是多维数据数组,而内核通常是由训练算法学习的参数多维数组。尽管我们在卷积公式中具有无限求和,但对于实际实现而言,权重函数的值仅在值的有限子集时才为非零(如SMA的情况)。因此,公式中的求和变为有限求和。卷积可应用于多个轴。如果我们有一个二维图像I和一个二维平滑核K,则卷积图像的计算方式如下:

或者,也可以如下计算:

下图说明了如何使用大小为2且步幅为1的内核来计算卷积层输出:

卷积内核通过一次移动一列/行来围绕输入体积进行卷积。滤波器移位的量称为跨度。在前面的场景中,将跨度隐式设置为1。如果将内核跨度移动2(两列或两行),则输出单元的数量将减少:

卷积运算符减小了输入的大小。如果要保留输入的大小,则需要在输入周围均匀填充零。对于二维图像,这意味着在图像的四个侧面周围添加零像素的边框。边框的粗细(即添加的像素行数)取决于所应用的内核大小。任何卷积运算符实现通常都采用指定填充类型的模式参数。有两个这样的参数:

在前面的一维卷积码中,我们将模式设置为VALID,因此没有填充发生。您可以尝试使用相同的填充。

卷积层包括三个主要阶段,每个阶段在多层网络上都构成一些结构约束:

将这三个阶段结合在一起,就可以为我们提供CNN中的一个复杂层,这三个阶段中的每个本身就是简单层:

可以通过将并排堆叠在一起的方式,将合并后的特征图按一个体积进行排列,如下所示。然后,我们可以再次对此应用下一个卷积级别。现在,单个特征图中隐藏单元的接受场将是神经单元的体积,如下图所示。但是,将在整个深度上使用同一组二维权重。深度尺寸通常由通道组成。如果我们有RGB输入图像,那么我们的输入本身将具有三个通道。但是,卷积是二维应用的,并且所有通道之间的权重相同:

这是LeCun及其合作者于1998年设计的具有开创性的七级卷积网络,用于数字分类。后来,它被几家银行用来识别支票上的手写数字。网络的较低层由交替的卷积和最大池化层组成。

上层是完全连接的密集MLP(由隐藏层和逻辑回归组成)。第一个完全连接的层的输入是上一层的所有特征图的集合:

最高得分的计算方法与此类似。

在2012年,AlexNet的表现明显优于所有先前的竞争对手,并通过将前5名的错误率降低到15.3%赢得了ILSVRC,而亚军则只有26%。这项工作推广了CNN在计算机视觉中的应用。AlexNet与LeNet的架构非常相似,但是每层具有更多的过滤器,并且更深入。而且,AlexNet引入了使用栈式卷积的方法,而不是始终使用替代性卷积池。小卷积的栈优于大卷积层的接收场,因为这会引入更多的非线性和更少的参数。

假设我们彼此之间具有三个3x3卷积层(在它们之间具有非线性或池化层)。在此,第一卷积层上的每个神经元都具有输入体积的3x3视图。第二卷积层上的神经元具有第一卷积层的3x3视图,因此具有输入体积的5x5视图。类似地,第三卷积层上的神经元具有第二卷积层的3x3视图,因此具有输入体积的7x7视图。显然,与3个3x3卷积的3x(3x3)=27个参数相比,7x7接收场的参数数量是49倍。

2013年ILSVRC冠军是MatthewZeiler和RobFergus的CNN。它被称为ZFNet。通过调整架构的超参数,特别是通过扩展中间卷积层的大小并减小第一层的步幅和过滤器大小,它在AlexNet上得到了改进,从AlexNet的11x11步幅4变为7x7步幅。ZFNet。这背后的直觉是,在第一卷积层中使用较小的滤镜尺寸有助于保留大量原始像素信息。此外,AlexNet接受了1500万张图像的训练,而ZFNet接受了130万张图像的训练:

2014年ILSVRC获奖者是来自Google的名为GoogLeNet的卷积网络。它的前5个错误率达到6.67%!这非常接近人类水平的表现。排在第二位的是来自KarenSimonyan和AndrewZisserman的网络,称为VGGNet。GoogLeNet使用CNN引入了一个称为初始层的新架构组件。初始层背后的直觉是使用较大的卷积,但对于图像上的较小信息也要保持较高的分辨率。

因此,我们可以并行处理不同大小的内核,从1x1到更大的内核,例如5x5,然后将输出级联以产生下一层:

显然,增加更多的层会爆炸参数空间。为了控制这一点,使用了降维技巧。请注意,1x1卷积基本上不会减小图像的空间尺寸。但是,我们可以使用1x1滤镜减少特征图的数量,并减少卷积层的深度,如下图所示:

下图描述了完整的GoogLeNet架构:

牛津视觉几何学组或简称为VGG的研究人员开发了VGG网络,该网络的特点是简单,仅使用3x3卷积层并排叠加,且深度不断增加。减小卷大小由最大池化处理。最后,两个完全连接的层(每个层有4,096个节点)之后是softmax层。对输入进行的唯一预处理是从每个像素减去在训练集上计算出的RGB平均值。

通过最大池化层执行池化,最大池化层跟随一些卷积层。并非所有卷积层都跟随最大池化。最大合并在2x2像素的窗口上执行,步幅为2。每个隐藏层都使用ReLU激活。在大多数VGG变体中,过滤器的数量随深度的增加而增加。下图显示了16层架构VGG-16。下一节显示了具有均匀3x3x卷积(VGG-19)的19层架构。VGG模型的成功证实了深度在图像表示中的重要性:

VGG-16:输入大小为224x224x3的RGB图像,每层中的滤镜数量都被圈起来

在ILSVRC2015中,由KaimingHe及其来自MicrosoftResearchAsia的合著者介绍了一种具有跳跃连接和批量归一化的新颖CNN架构,称为残差神经网络(ResNet)。这样,他们就可以训练一个具有152层(比VGG网络深八倍)的神经网络,同时仍比VGG网络具有更低的复杂度。它的前5个错误率达到3.57%,在此数据集上超过了人类水平的表现。

该架构的主要思想如下。他们没有希望一组堆叠的层将直接适合所需的基础映射H(x),而是尝试适应残差映射。更正式地讲,他们让堆叠的层集学习残差R(x)=H(x)-x,随后通过跳过连接获得真实映射。然后将输入添加到学习的残差R(x)+x。

同样,在每次卷积之后和激活之前立即应用批量归一化:

剩余网络的一个组成部分

与VGG-19相比,这是完整的ResNet架构。点缀的跳过连接显示尺寸增加;因此,为了使添加有效,不执行填充。同样,尺寸的增加由颜色的变化表示:

fromkeras.applications.vgg16importVGG16model=VGG16()print(model.summary())胶囊网络我们已经讨论了各种CNN架构是如何演变的,并且已经研究了它们的连续改进。现在我们可以将CNN用于更高级的应用,例如高级驾驶员辅助系统(ADAS)和自动驾驶汽车吗?我们能否在现实世界中实时地检测道路上的障碍物,行人和其他重叠物体?也许不会!我们还不在那里。尽管CNN在ImageNet竞赛中取得了巨大成功,但CNN仍然存在一些严重的局限性,将它们的适用性限制在更高级的现实问题中。CNN的翻译不变性差,并且缺乏有关方向的信息(或姿势)。

姿势信息是指相对于观看者的三维方向,还指照明和颜色。旋转物体或改变照明条件时,CNN确实会带来麻烦。根据Hinton的说法,CNN根本无法进行顺手性检测;例如,即使他们都接受过这两种训练,他们也无法从右鞋中分辨出左鞋。CNN受到这些限制的原因之一是使用最大池化,这是引入不变性的粗略方法。通过粗略不变性,我们的意思是,如果图像稍有移位/旋转,则最大合并的输出不会发生太大变化。实际上,我们不仅需要不变性,还需要等价性;即,在图像的对称变换下的不变性。

边缘检测器是CNN中的第一层,其功能与人脑中的视觉皮层系统相同。大脑和CNN之间的差异出现在较高水平。有效地将低层视觉信息路由到高层信息,例如各种姿势和颜色或各种比例和速度的对象,这是由皮质微柱完成的,Hinton将其命名为胶囊。这种路由机制使人的视觉系统比CNN更强大。

胶囊网络(CapsNets)对CNN架构进行了两个基本更改:首先,它们用向量输出胶囊代替CNN的标量输出特征检测器;其次,他们将最大池与按协议路由一起使用。这是一个简单的CapsNet架构:

这是一种浅薄的架构,需要根据MNIST数据(28x28个手写数字图像)进行训练。这具有两个卷积层。第一卷积层具有256个特征图,具有9x9内核(步幅为1)和ReLu激活。因此,每个特征图是(28-9+1)x(28-9+1)或20x20。第二个卷积层又具有256个特征图,具有9x9个内核(步幅为2)和ReLu激活。这里每个特征图是6x6,6=((20-9)/2+1)。对该层进行了重塑,或者将特征图重新分组为32组,每组具有8个特征图(256=8x32)。分组过程旨在创建每个大小为8的特征向量。为了表示姿势,向量表示是一种更自然的表示。来自第二层的分组特征图称为主胶囊层。我们有(32x6x6)八维胶囊向量,其中每个胶囊包含8个卷积单元,内核为9x9,步幅为2。最后一个胶囊层(DigitCaps)对于每十个类别有一个十六维的胶囊,这些胶囊中的每一个都从主胶囊层中的所有胶囊接收输入。

胶囊的输出向量的长度表示由胶囊表示的实体存在于当前输入中的概率。胶囊向量的长度被归一化,并保持在0到1之间。此外,在向量的范数上使用了压缩函数,以使短向量缩小到几乎零长度,而长向量缩小到略小于1的长度。

压缩函数为:

其中x是向量的范数,因此x>0(请参见下图):

W[ij]是每个初级胶囊中u[i],i∈(1,32x6x6)和v[j],在DigitCaps中j∈(1,10)。在此,u_hat[j|i]=w[ij]u[i]被称为预测向量,并且像一个已转换(旋转/翻译)的输入胶囊向量u[i]。胶囊的总输入s[j]是来自下一层胶囊的所有预测向量的加权总和。这些权重c[ij]的总和为1,在Hinton中称为耦合系数。一开始,它假设胶囊i应该与母体胶囊j结合的对数先验概率对于所有i和j都是相同的,用b[ij]表示。因此,可以通过此众所周知的softmax转换来计算耦合系数:

通过称为协议路由的算法,这些耦合系数与网络的权重一起迭代更新。简而言之,它执行以下操作:如果主胶囊i的预测向量与可能的父级j的输出具有大的标量积,则耦合系数b[ij]对于该父对象增加而对于其他父对象减少。

完整的路由算法在这里给出:

左侧显示了如何通过权重矩阵W[ij]将所有主胶囊连接到数字胶囊。此外,它还描述了如何通过非线性压缩函数计算耦合系数以及如何计算DigitCaps的十六维输出。在右侧,假设主胶囊捕获了两个基本形状:输入图像中的三角形和矩形。旋转后将它们对齐会根据旋转量给出房屋或帆船。很明显,这两个物体在极少或几乎没有旋转的情况下结合在一起,形成了帆船。即,两个主胶囊比房屋更对准以形成船。因此,路由算法应更新b[i,船]的耦合系数:

procedurerouting(,r,l):forallcapsuleiinlayerlandcapsulejinlayer(l+1):bij<-0forriterationsdo:forallcapsuleiinlayerl:ci<-softmax(bi)forallcapsulejinlayer(l+1):forallcapsulejinlayer(l+1):vj<-squash(sj)forallcapsuleiinlayerlandcapsulejinlayer(l+1):returnvj最后,我们需要适当的损失函数来训练该网络。在此,将数字存在的余量损失用作损失函数。它还考虑了数字重叠的情况。对于每个胶囊k,单独的裕量损失L[k]用于允许检测多个重叠的数字。L[k]观察胶囊向量的长度,对于k类的数字,第k个胶囊向量的长度应最大:

如果存在第k位,则T[k]=1。m+=0.9,m-=0.1。λ用于降低缺少数字类别的损失的权重。与L[k]一起,图像重建误差损失被用作网络的正则化。如CapsNet架构所示,数字胶囊的输出被馈送到由三个完全连接的层组成的解码器中。逻辑单元的输出与原始图像像素强度之间的平方差之和最小。重建损失缩小了0.0005倍,因此在训练过程中它不控制边际损失。

循环神经网络(RNN)专用于处理一系列值,如x(1)...x(t)。例如,如果要在给定序列的最新历史的情况下预测序列中的下一项,或者将一种语言的单词序列翻译为另一种语言,则需要进行序列建模。RNN与前馈网络的区别在于其架构中存在反馈环路。人们常说RNN有记忆。顺序信息保留在RNN的隐藏状态中。因此,RNN中的隐藏层是网络的内存。从理论上讲,RNN可以任意长的顺序使用信息,但实际上,它们仅限于回顾一些步骤。

我们将在后面解释:

让我们看一下使用基于梯度的优化算法学习权重所需的总误差导数。我们有h[t]=Uφh[t-1]+Wx[t],Φ是非线性激活,而y[t]=Vφh[t]。

现在是:

根据链式规则,我们有:

在此,雅可比行列式h[t]/h[k],即层t相对于前一层k本身是雅可比行列式

的乘积。

使用前面的h[t]方程,我们有:

因此,雅可比式h[t]/h[k]的范数由乘积

给出。如果数量||h[s]/h[s-1]||小于1,则在较长的序列(例如100步)中,这些规范的乘积将趋于零。同样,如果范数大于1,则长序列的乘积将成倍增长。这些问题在RNN中称为消失梯度和梯度爆炸。因此,在实践中,RNN不能具有很长的记忆。

下图显示了单个LSTM单元的高级表示:

输入门通常可以允许或拒绝进入的信号或输入以更改存储单元状态。输出门通常会根据需要将该值传播到其他神经元。遗忘门控制存储单元的自循环连接以根据需要记住或忘记以前的状态。通常,将多个LSTM单元堆叠在任何深度学习网络中,以解决现实世界中的问题,例如序列预测。在下图中,我们比较了RNN和LSTM的基本结构:

通过LSTM的信息流包括四个步骤:

LSTM可以用于序列预测以及序列分类。例如,我们可以预测未来的股价。另外,我们可以使用LSTM构建分类器,以预测来自某些健康监控系统的输入信号是致命还是非致命信号(二分类器)。我们甚至可以使用LSTM构建文本文档分类器。单词序列将作为LSTM层的输入,LSTM的隐藏状态将连接到密集的softmax层作为分类器。

机器翻译是计算语言学的一个子领域,涉及将文本或语音从一种语言翻译成另一种语言。传统的机器翻译系统通常依赖于基于文本统计属性的复杂特征工程。最近,深度学习已被用于解决此问题,其方法称为神经机器翻译(NMT)。NMT系统通常由两个模块组成:编码器和解码器。

它首先使用编码器读取源句子,以构建思想向量:代表该句子含义的数字序列。解码器处理句子向量以发出对其他目标语言的翻译。这称为编码器-解码器架构。编码器和解码器通常是RNN的形式。下图显示了使用堆叠LSTM的编码器-解码器架构。在这里,第一层是一个嵌入层,用于通过密集的实向量来表示源语言中的单词。为源语言和目标语言都预定义了词汇表。不在词汇表中的单词由固定单词<未知>表示,并由固定嵌入向量表示。该网络的输入首先是源句子,然后是句子标记的结尾,指示从编码模式到解码模式的转换,然后馈入目标句子:

输入嵌入层后面是两个堆叠的LSTM层。然后,投影层将最上面的隐藏状态转换为尺寸为V(目标语言的词汇量)的对率向量。这里,交叉熵损失用于通过反向传播训练网络。我们看到在训练模式下,源句子和目标句子都被输入到网络中。在推理模式下,我们只有源句。在那种情况下,可以通过几种方法来完成解码,例如贪婪解码,与贪婪解码结合的注意力机制以及集束搜索解码。我们将在这里介绍前两种方法:

在贪婪的解码方案中(请参见前面两个图的左手图),我们选择最有可能的单词(以最大对率值描述为发射的单词),然后将其反馈给解码器作为输入。继续该解码过程,直到产生句子结束标记作为输出符号。

由源句子的句子结尾标记生成的上下文向量必须对我们需要了解的有关源句子的所有内容进行编码。它必须充分体现其含义。对于长句子,这意味着我们需要存储非常长的记忆。研究人员发现,反转源序列或两次馈入源序列有助于网络更好地记忆事物。对于与英语非常相似的法语和德语这样的语言,反转输入是有意义的。对于日语,句子的最后一个单词可能会高度预测英语翻译中的第一个单词。因此,这里的反转会降低翻译质量。因此,一种替代解决方案是使用注意机制(如前两个图的右图所示)。

现在,无需尝试将完整的源句子编码为固定长度的向量,而是允许解码器在输出生成的每个步骤中使参与到源句子的不同部分。因此,我们将第t个目标语言单词的基于注意力的上下文向量c[t]表示为所有先前源隐藏状态的加权和:

注意权重为:

得分的计算如下:sc(h[t],h[s])=h[t]Wh[s]。

W是权重矩阵,将与RNN权重一起学习。该得分函数称为Luong的乘法样式得分。此分数还有其他一些变体。最后,通过将上下文向量与当前目标隐藏状态组合如下来计算注意向量,a[t]:

GRU相对较新,其表现与LSTM相当,但由于结构更简单,参数更少,因此它们在计算上更加高效。这是LSTM和GRU之间的一些结构差异:

如果有足够的数据,建议使用LSTM,因为LSTM的更高表达能力可能会导致更好的结果。

大多数机器学习模型无法读取和写入长期内存组件,也无法将旧内存与推理无缝结合。RNN及其变体(例如LSTM)确实具有存储组件。但是,它们的内存(由隐藏状态和权重编码)通常太小,不像我们在现代计算机中发现的大块数组(以RAM的形式)。他们试图将所有过去的知识压缩为一个密集的向量-记忆状态。对于诸如虚拟协助或问题解答(QA)系统之类的复杂应用,该应用可能会受到很大限制,在这种系统中,长期记忆有效地充当了(动态)知识库,输出是文本响应。为了解决这个问题,FacebookAI研究小组开发了记忆神经网络(MemNNs)。MemNN的中心思想是将深度学习文献中为推理而开发的成功学习策略与可以像RAM一样读写的内存组件相结合。同样,模型被训练以学习如何与存储组件一起有效地操作。存储网络由存储器m,对象的索引数组(例如,向量或字符串数组)和要学习的四个组件I,G,O,R组成:

当分量I,G,O和R是神经网络时,则所得系统称为MemNN。让我们尝试通过示例质量检查系统来理解这一点。系统将获得一系列事实和问题。它将输出该问题的答案。我们有以下六个文本事实和一个问题,问:“牛奶现在在哪里?”:

请注意,语句的某些子集包含答案所需的信息,而其他子集本质上是无关紧要的。我们将用MemNN模块I,G,O和R来表示这一点。模块I是一个简单的嵌入模块,它将文本转换为二元词袋向量。文本以其原始形式存储在下一个可用的存储插槽中,因此G模块非常简单。一旦去除了停用词,给定事实中使用的单词词汇为V={乔,弗雷德,旅行,捡起,离开,离开,去办公室,洗手间,厨房,牛奶}。现在,这是所有文本存储后的内存状态:

O模块通过在给定问题q的情况下找到k个支持存储器来产生输出特征。对于k=2,使用以下方法检索最高得分的支持内存:

其中s[0]是输入q和m[i]之间的评分函数,o1是具有最佳匹配的内存m的索引。现在,使用查询和第一个检索到的内存,我们可以检索下一个内存m[o2],这两个内存都很接近:

合并的查询和内存结果为o=[q,m[o1],m[o2]]=[现在牛奶在哪里,乔离开了牛奶,乔去了办公室]。最后,模块R需要产生文本响应r。R模块可以输出一个单词的答案,或者可以输出一个完整句子的RNN模块。对于单字响应,令r是对[q,m[o1],m[o2]]和单词w的回应。因此,最后的回应r是办公室一词:

这种模型很难使用反向传播来进行端到端训练,并且需要在网络的每个模块上进行监督。对此有一点修改,实际上是称为端到端存储网络(MemN2N)的连续版本的存储网络。该网络可以通过反向传播进行训练。

我们从一个查询开始:牛奶现在在哪里?使用大小为V的向量,用成袋的单词进行编码。在最简单的情况下,我们使用嵌入B(dxV)将向量转换为大小为d的词嵌入。我们有u=embeddingB(q):

输入句子x1,x2,...,xi通过使用另一个嵌入矩阵A(dxV)存储在内存中,其大小与B[mi]=embeddingA(x[i])。每个嵌入式查询u与每个内存m[i]之间的相似度是通过取内积和softmax来计算的:p[i]=softmax(u^Tm[i])。

输出存储器表示如下:每个x[i]具有对应的输出向量c[i],可以用另一个嵌入矩阵C表示。然后,来自存储器的响应向量o是c[i]上的总和,并由来自以下输入的概率向量加权:

最后,将o和u之和与权重矩阵W(Vxd)相乘。结果传递到softmax函数以预测最终答案:

神经图灵机(NTM)受到图灵机(TM)的启发:定义了一个抽象机。TM可以根据规则表来操作一条胶带上的符号。对于任何计算机算法,TM都可以模拟该算法的逻辑。机器将其头放在单元格上方并在其中读取或写入符号。此后,根据定义的规则,它可以向左或向右移动甚至停止程序。

NTM架构包含两个基本组件:神经网络控制器和内存。下图显示了NTM架构的高层表示:

控制器使用输入和输出向量与外部世界进行交互。与标准神经网络不同,此处的控制器还使用选择性读取和写入操作与存储矩阵进行交互。内存是一个实值矩阵。内存交互是端到端可区分的,因此可以使用梯度下降对其进行优化。NTM可以从输入和输出示例中学习简单的算法,例如复制,排序和关联召回。而且,与TM不同,NTM是可通过梯度下降训练的可微分计算机,为学习程序提供了一种实用的机制。

控制器可以由LSTM建模,LSTM具有自己的内部存储器,可以补充矩阵中更大的存储器。可以将控制器与计算机中的CPU相比较,并且可以将存储矩阵与计算机的RAM相比较。

读写头选择要读取或写入的内存部分。可以通过神经网络中的隐藏层(可能是softmax层)对它们进行建模,以便可以将它们视为外部存储单元上的权重之和,这些权重之和为1。此外,请注意,模型参数的数量是受控的,不会随存储容量的增长而增加。

控制器输出用于确定要读取或写入的存储器位置。这由一组分布在所有内存位置上的权重定义,这些权重之和为1。权重由以下两种机制定义。想法是为控制器提供几种不同的读取或写入内存的模式,分别对应于不同的数据结构:

在这种情况下,β≥1称为清晰度参数,并控制对特定位置的聚焦。它还为网络提供了一种方法来决定其希望内存位置访问的精确度。就像模糊均值聚类中的模糊系数。

在应用旋转移位之前,将内容寻址所给定的权重向量与先前的权重向量w[t-1]相结合,如下所示:

在此,g[t]是由控制器头发出的标量内插门,范围为(0,1)。如果g[t]=1,则忽略先前迭代的加权。

M读取向量r[t]的长度定义为行向量M[t](i)的凸组合,在内存中:

每个写头接收一个擦除向量,e[t]和一个加性向量,a[t],以像LSTM单元一样重置和写入存储器,如下所示:M[t](i)←M[t](i)[1-e[t](i)w[t](i)]+w[t](i)a[t](i)。

这是上述操作的伪代码:

类似地,给定一组随机序列和相应的排序序列,NTM可以从数据中高效地学习排序算法。

我们已经讨论了基于注意力的机器翻译模型。基于注意力的模型的优点在于,它们提供了一种解释模型并理解其工作方式的方式。注意机制是记忆以前的内部状态的一种形式。这就像内部存储器。与典型的存储器不同,这里的存储器访问机制是软的,这意味着网络将检索所有存储器位置的加权组合,而不是单个离散位置的值。软存储器访问使通过反向传播训练网络变得可行。基于注意的架构不仅用于机器翻译,还可以用于自动生成图像标题。

本章介绍了神经网络架构的各种进展及其在各种实际问题中的应用。我们讨论了对这些架构的需求,以及为什么简单的深度多层神经网络不能充分解决各种问题,因为它具有强大的表达能力和丰富的假设空间。讨论迁移学习用例时,将在后面的章节中使用其中讨论的许多架构。提供了几乎所有架构的Python代码参考。我们还试图清楚地解释一些最近的架构,例如CapsNet,MemNN和NTM。当您逐步学习迁移学习用例时,我们将经常参考本章。

下一章将介绍转学的概念。

我还在学习。

——米开朗基罗

传统上,学习算法设计为单独解决任务或问题。根据用例和手头数据的要求,应用算法来训练给定特定任务的模型。传统的机器学习(ML)根据特定的域,数据和任务单独地训练每个模型,如下图所示:

传统机器学习

从那时起,诸如元学习,知识整合和归纳迁移等术语已与迁移学习互换使用。总是有不同的研究人员和学术著作提供不同背景下的定义。在他们的书深度学习中,Goodfellow等人。在泛化的背景下指迁移学习。它们的定义如下:

利用一种情况下所学的知识来改善另一种情况下的泛化的情况。

如上图所示,在学习目标任务时,来自现有任务的知识将作为附加输入。

我们利用源模型中的知识来改进目标任务中的学习。除了提供重用已经构建的模型的功能之外,迁移学习还可以通过以下方式帮助学习目标任务:

读者应注意,有可能获得这些收益中的一项或多项,我们将在接下来的章节中详细讨论。如下图所示,它显示出更好的基线表现(更高的起始),效率增益(更高的斜率)和更好的最终表现(渐近线更高):

迁移学习已在归纳学习器(例如神经网络和贝叶斯网络)的上下文中得到应用和研究。强化学习是另一个探索迁移学习可能性的领域。因此,迁移学习的概念不限于深度学习。

在本章及后续章节中,我们将限制使用迁移学习的范围仅限于深度学习的上下文。

域D定义为由特征空间χ和边缘概率P(X)组成的二元元组,其中X是样本数据点。

在此,x={x[1],x[2],....x[n]},其中x[i]作为X的特定向量εχ。从而:

另一方面,可以将任务T定义为标签空间γ和目标函数f的二元组。从概率的观点来看,目标函数也可以表示为P(γ|Χ)。从而:

使用此框架,我们可以将迁移学习定义为旨在改善目标目标函数f(T)(或目标任务T(T))的过程。使用来自T(S)源的知识,在目标域中将D[T]D[S]域中的任务。这导致以下四种情况:

到目前为止,我们已经看到迁移学习具有在目标任务中利用来自源学习器的现有知识的能力。在迁移学习过程中,必须回答以下三个重要问题:

分组技术可帮助我们了解整体特征并提供更好的框架来利用它们。可以根据所涉及的传统ML算法的类型对迁移学习方法进行分类,例如:

上一节中讨论的三种迁移类别概述了可以应用和详细研究迁移学习的不同设置。为了回答在这些类别中迁移什么的问题,可以采用以下一些方法:

在本节中,我们以非常通用的方式研究了在不同背景和环境下进行迁移学习的不同策略。现在让我们利用这种理解,学习如何在深度学习的上下文中应用迁移学习。

深度学习模型代表了归纳学习。归纳学习算法的目的是从一组训练示例中得出映射。例如,在分类的情况下,模型学习输入特征和类标签之间的映射。为了使这样的学习器能够很好地对看不见的数据进行概括,其算法采用了与训练数据的分布有关的一组假设。这些假设集合称为感应偏置。

归纳偏差或假设可以由多个因素来表征,例如它所限制的假设空间以及通过假设空间进行的搜索过程。因此,这些偏差会影响模型在给定任务和领域上的学习方式和知识。

归纳迁移技术利用源任务的归纳偏差来辅助目标任务。这可以通过不同的方式来完成,例如通过限制模型空间,缩小假设空间来调整目标任务的归纳偏差,或者借助源任务的知识来对搜索过程本身进行调整。下图直观地描述了此过程:

除了归纳迁移,归纳学习算法还利用贝叶斯和层次迁移技术来帮助改进目标任务的学习和表现。

跨计算机视觉和自然语言处理(NLP)。在大多数情况下,团队/人员共享这些网络的详细信息以供其他人使用(第3章“了解深度学习架构”中共享了一些受欢迎的网络)。这些预训练的网络/模型在深度学习的背景下构成了迁移学习的基础。

如第3章“了解深度学习架构”中所述,深度学习系统是分层的架构,可在不同的层学习不同的特征。然后将这些层最终连接到最后一层(在分类的情况下,通常是完全连接的层)以获得最终输出。这种分层的架构使我们可以利用预先训练的网络(例如InceptionV3或VGG),而无需将其最终层用作其他任务的固定特征提取器。下图表示基于特征提取的深度迁移:

例如,如果我们使用没有最终分类层的AlexNet,它将帮助我们将新领域任务的图像基于其隐藏状态转换为4,096维向量,从而使我们能够利用来自源域任务的知识,从新领域任务中提取特征。这是使用深度神经网络执行迁移学习的最广泛使用的方法之一。

深度学习是一类算法,已被用来非常成功地获得迁移学习的好处。以下是一些示例:

我们学习了不同的迁移学习策略,甚至讨论了如何将知识从源迁移到目标的三个问题。特别是,我们讨论了特征表示传递如何有用。值得重申的是,深度学习网络中的不同层捕获了不同的特征集。我们可以利用这一事实来学习领域不变的特征,并提高其跨领域的可移植性。代替让模型学习任何表示,我们将两个域的表示微调为尽可能相似。

多任务学习与迁移学习世界略有不同。在多任务学习的情况下,可以同时学习多个任务,而无需区分源和目标。在这种情况下,与迁移学习相比,学习器一次就接收到有关多个任务的信息,在迁移学习中,学习器最初对目标任务一无所知。

如下图所示:

多任务学习:学习器同时从所有任务接收信息

深度学习系统天生就渴望数据,因此它们需要许多训练示例来学习权重。这是深度神经网络的局限性之一,尽管人类学习并非如此。例如,一旦向孩子展示了苹果的外观,他们就可以轻松识别出不同种类的苹果(带有一个或几个训练示例);机器学习和深度学习算法并非如此。单样本学习是迁移学习的一种变体,在这种学习中,我们尝试仅根据一个或几个训练示例来推断所需的输出。这在无法为每个可能的类提供标签数据的现实世界场景中(如果是分类任务)和在经常可以添加新类的场景中非常有用。

零镜头学习是迁移学习的另一个极端变体,它不依赖任何标记的示例来学习任务。这听起来令人难以置信,尤其是当使用示例学习是大多数监督学习算法所要解决的问题时。零数据学习或零短学习方法在训练阶段本身进行了巧妙的调整,以利用附加信息来理解看不见的数据。在他们的《学会学习》一书中,Goodfellow及其合作者提出了零样本学习作为学习三个变量的场景,例如传统输入变量x,传统输出变量y以及描述任务的其他随机变量T&。因此,训练模型以学习P(y|x,T)的条件概率分布。零镜头学习在机器翻译等场景中非常有用,在这种情况下,我们甚至可能没有目标语言的标签。

在上一章中,我们介绍了围绕迁移学习的主要概念。关键思想是,与从头开始构建自己的深度学习模型和架构相比,在各种任务中利用先进的,经过预训练的深度学习模型可产生更好的结果。在本章中,我们将获得一个更动手的观点,即使用迁移学习实际构建深度学习模型并将其应用于实际问题。有无迁移学习,我们将构建各种深度学习模型。我们将分析它们的架构,并比较和对比它们的表现。本章将涵盖以下主要方面:

现在让我们考虑一个现实世界的问题,在本章中,我们还将继续使用它来说明我们不同的深度学习模型,并在同一模型上利用迁移学习。您必须一次又一次听到深度学习的关键要求之一是,我们需要大量数据和样本来构建可靠的深度学习模型。其背后的想法是模型可以从大量样本中自动学习特征。但是,如果我们没有足够的训练样本并且要解决的问题仍然是一个相对复杂的问题,我们该怎么办?例如,计算机视觉问题,例如图像分类,可能难以使用传统的统计技术或机器学习(ML)技术解决。我们会放弃深度学习吗?

考虑到图像分类问题,由于我们要处理的图像本质上是高维张量,因此拥有更多数据可使深度学习模型学习更好的图像基本特征表示。但是,即使我们每个类别的图像样本的范围从几百到数千,基本的CNN模型在正确的架构和规范化条件下仍能正常运行。这里要记住的关键点是,CNN会学习与缩放,平移和旋转不变的模式和特征,因此我们在这里不需要自定义特征工程技术。但是,我们可能仍然会遇到模型过拟合之类的问题,我们将在本章稍后部分尝试解决这些问题。

首先,从数据集页面下载train.zip文件并将其存储在本地系统中。下载后,将其解压缩到文件夹中。该文件夹将包含25,000张猫和狗的图像;即每个类别12500张图像。

虽然我们可以使用所有25,000张图像并在它们上建立一些不错的模型,但是,如果您还记得的话,我们的问题目标包括增加的约束,即每类图像的数量很少。为此,我们构建自己的数据集。如果您想自己运行示例,可以参考DatasetsBuilder.ipynbJupyter笔记本。

首先,我们加载以下依赖项,包括一个名为utils的工具模块,该模块在本章代码文件中的utils.py文件中可用。当我们将图像复制到新文件夹时,这主要用于获得视觉进度条:

importglobimportnumpyasnpimportosimportshutilfromutilsimportlog_progressnp.random.seed(42)现在,如下所示将所有图像加载到原始训练数据文件夹中:

files=glob.glob('train/*')cat_files=[fnforfninfilesif'cat'infn]dog_files=[fnforfninfilesif'dog'infn]len(cat_files),len(dog_files)Out[3]:(12500,12500)我们可以使用前面的输出来验证每个类别有12,500张图像。现在,我们构建较小的数据集,以使我们有3,000张图像用于训练,1,000张图像用于验证和1,000张图像用于我们的测试数据集(两个动物类别的表示均相同):

cat_train=np.random.choice(cat_files,size=1500,replace=False)dog_train=np.random.choice(dog_files,size=1500,replace=False)cat_files=list(set(cat_files)-set(cat_train))dog_files=list(set(dog_files)-set(dog_train))cat_val=np.random.choice(cat_files,size=500,replace=False)dog_val=np.random.choice(dog_files,size=500,replace=False)cat_files=list(set(cat_files)-set(cat_val))dog_files=list(set(dog_files)-set(dog_val))cat_test=np.random.choice(cat_files,size=500,replace=False)dog_test=np.random.choice(dog_files,size=500,replace=False)print('Catdatasets:',cat_train.shape,cat_val.shape,cat_test.shape)print('Dogdatasets:',dog_train.shape,dog_val.shape,dog_test.shape)Catdatasets:(1500,)(500,)(500,)Dogdatasets:(1500,)(500,)(500,)现在我们已经创建了数据集,让我们将它们写到单独文件夹中的磁盘中,以便我们将来可以在任何时候返回它们,而不必担心它们是否存在于主内存中:

train_dir='training_data'val_dir='validation_data'test_dir='test_data'train_files=np.concatenate([cat_train,dog_train])validate_files=np.concatenate([cat_val,dog_val])test_files=np.concatenate([cat_test,dog_test])os.mkdir(train_dir)ifnotos.path.isdir(train_dir)elseNoneos.mkdir(val_dir)ifnotos.path.isdir(val_dir)elseNoneos.mkdir(test_dir)ifnotos.path.isdir(test_dir)elseNoneforfninlog_progress(train_files,name='TrainingImages'):shutil.copy(fn,train_dir)forfninlog_progress(validate_files,name='ValidationImages'):shutil.copy(fn,val_dir)forfninlog_progress(test_files,name='TestImages'):shutil.copy(fn,test_dir)一旦所有图像都复制到各自的目录中,以下屏幕快照中描述的进度条将变为绿色:

由于这是图像分类问题,因此我们将利用CNN模型或convNets尝试解决此问题。在本章开始时,我们简要讨论了我们的方法。我们将从头开始构建简单的CNN模型,然后尝试使用正则化和图像增强等技术进行改进。然后,我们将尝试利用预训练的模型来释放转学的真正力量!

让我们开始构建图像分类分类器。我们的方法是在训练数据集上建立模型,并在验证数据集上进行验证。最后,我们将在测试数据集上测试所有模型的表现。在进入建模之前,让我们加载并准备数据集。首先,我们加载一些基本的依赖项:

importglobimportnumpyasnpimportmatplotlib.pyplotaspltfromkeras.preprocessing.imageimportImageDataGenerator,load_img,img_to_array,array_to_img%matplotlibinline现在,使用以下代码片段加载数据集:

IMG_DIM=(150,150)train_files=glob.glob('training_data/*')train_imgs=[img_to_array(load_img(img,target_size=IMG_DIM))forimgintrain_files]train_imgs=np.array(train_imgs)train_labels=[fn.split('/')[1].split('.')[0].strip()forfnintrain_files]validation_files=glob.glob('validation_data/*')validation_imgs=[img_to_array(load_img(img,target_size=IMG_DIM))forimginvalidation_files]validation_imgs=np.array(validation_imgs)validation_labels=[fn.split('/')[1].split('.')[0].strip()forfninvalidation_files]print('Traindatasetshape:',train_imgs.shape,'tValidationdatasetshape:',validation_imgs.shape)Traindatasetshape:(3000,150,150,3)Validationdatasetshape:(1000,150,150,3)我们可以清楚地看到我们有3000训练图像和1000验证图像。每个图像的尺寸为150x150,并具有用于红色,绿色和蓝色(RGB)的三个通道,因此为每个图像提供(150,150,3)尺寸。现在,我们将像素值在(0,255)之间的每个图像缩放到(0,1)之间的值,因为深度学习模型在较小的输入值下确实可以很好地工作:

train_imgs_scaled=train_imgs.astype('float32')validation_imgs_scaled=validation_imgs.astype('float32')train_imgs_scaled/=255validation_imgs_scaled/=255#visualizeasampleimageprint(train_imgs[0].shape)array_to_img(train_imgs[0])(150,150,3)前面的代码生成以下输出:

前面的输出显示了我们训练数据集中的示例图像之一。现在,让我们设置一些基本的配置参数,并将文本类标签编码为数值(否则,Keras将抛出错误):

batch_size=30num_classes=2epochs=30input_shape=(150,150,3)#encodetextcategorylabelsfromsklearn.preprocessingimportLabelEncoderle=LabelEncoder()le.fit(train_labels)train_labels_enc=le.transform(train_labels)validation_labels_enc=le.transform(validation_labels)print(train_labels[1495:1505],train_labels_enc[1495:1505])['cat','cat','cat','cat','cat','dog','dog','dog','dog','dog'][0000011111]我们可以看到,我们的编码方案将0分配给cat标签,将1分配给dog标签。现在,我们准备构建我们的第一个基于CNN的深度学习模型。

我们将从建立具有三个卷积层的基本CNN模型开始,再加上用于从图像中自动提取特征的最大池化,以及对输出卷积特征图进行下采样。要刷新有关卷积和池化层如何工作的记忆,请查看第3章“了解深度学习架构”中的CNN部分。

提取这些特征图后,我们将使用一个密集层以及一个具有S型函数的输出层进行分类。由于我们正在执行二分类,因此binary_crossentropy损失函数就足够了。我们将使用流行的RMSprop优化器,该优化器可帮助我们使用反向传播来优化网络中单元的权重,从而使网络中的损失降到最低,从而得到一个不错的分类器。请参阅第2章,“深度学习要点”中的“随机梯度下降”和“SGD改进”部分,以获取有关优化器如何工作的深入见解。简而言之,优化器(如RMSprop)指定有关损耗梯度如何用于更新传递到我们网络的每批数据中的参数的规则。

让我们利用Keras并立即构建我们的CNN模型架构:

我们使用30的batch_size,我们的训练数据总共有3,000个样本,这表示每个周期总共有100次迭代。我们对模型进行了总共30个周期的训练,并因此在我们的1,000张图像的验证集上进行了验证:

history=model.fit(x=train_imgs_scaled,y=train_labels_enc,validation_data=(validation_imgs_scaled,validation_labels_enc),batch_size=batch_size,epochs=epochs,verbose=1)Trainon3000samples,validateon1000samplesEpoch1/303000/3000-10s-loss:0.7583-acc:0.5627-val_loss:0.7182-val_acc:0.5520Epoch2/303000/3000-8s-loss:0.6343-acc:0.6533-val_loss:0.5891-val_acc:0.7190......Epoch29/303000/3000-8s-loss:0.0314-acc:0.9950-val_loss:2.7014-val_acc:0.7140Epoch30/303000/3000-8s-loss:0.0147-acc:0.9967-val_loss:2.4963-val_acc:0.7220根据训练和验证的准确率值,我们的模型似乎有点过拟合。我们可以使用以下代码段绘制模型的准确率和误差,以获得更好的视角:

f,(ax1,ax2)=plt.subplots(1,2,figsize=(12,4))t=f.suptitle('BasicCNNPerformance',fontsize=12)f.subplots_adjust(top=0.85,wspace=0.3)epoch_list=list(range(1,31))ax1.plot(epoch_list,history.history['acc'],label='TrainAccuracy')ax1.plot(epoch_list,history.history['val_acc'],label='ValidationAccuracy')ax1.set_xticks(np.arange(0,31,5))ax1.set_ylabel('AccuracyValue')ax1.set_xlabel('Epoch')ax1.set_title('Accuracy')l1=ax1.legend(loc="best")ax2.plot(epoch_list,history.history['loss'],label='TrainLoss')ax2.plot(epoch_list,history.history['val_loss'],label='ValidationLoss')ax2.set_xticks(np.arange(0,31,5))ax2.set_ylabel('LossValue')ax2.set_xlabel('Epoch')ax2.set_title('Loss')l2=ax2.legend(loc="best")以下图表利用了历史对象,其中包含每个周期的精度和损耗值:

您可以清楚地看到,在2-3个周期之后,模型开始对训练数据进行过拟合。我们在验证集中获得的平均准确率约为72%,这不是一个不好的开始!我们可以改进此模型吗?

让我们通过增加一个卷积层,另一个密集的隐藏层来改进我们的基本CNN模型。除此之外,我们将在每个隐藏的密集层之后添加0.3的差值以启用正则化。我们在第2章“深度学习基础知识”中简要介绍了丢弃法问题,因此随时可以快速浏览一下它,以备不时之需。基本上,丢弃法是在深度神经网络中进行正则化的有效方法。它可以分别应用于输入层和隐藏层。

通过将输出的输出设置为零,丢弃法随机掩盖了一部分设备的输出(在我们的示例中,它是密集层中30%的设备的输出):

model=Sequential()#convolutionalandpoolinglayersmodel.add(Conv2D(16,kernel_size=(3,3),activation='relu',input_shape=input_shape))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Conv2D(64,kernel_size=(3,3),activation='relu'))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Conv2D(128,kernel_size=(3,3),activation='relu'))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Conv2D(128,kernel_size=(3,3),activation='relu'))model.add(MaxPooling2D(pool_size=(2,2)))model.add(Flatten())model.add(Dense(512,activation='relu'))model.add(Dropout(0.3))model.add(Dense(512,activation='relu'))model.add(Dropout(0.3))model.add(Dense(1,activation='sigmoid'))model.compile(loss='binary_crossentropy',optimizer=optimizers.RMSprop(),metrics=['accuracy'])现在,让我们在训练数据上训练新模型,并在验证数据集上验证其表现:

history=model.fit(x=train_imgs_scaled,y=train_labels_enc,validation_data=(validation_imgs_scaled,validation_labels_enc),batch_size=batch_size,epochs=epochs,verbose=1)Trainon3000samples,validateon1000samplesEpoch1/303000/3000-7s-loss:0.6945-acc:0.5487-val_loss:0.7341-val_acc:0.5210Epoch2/303000/3000-7s-loss:0.6601-acc:0.6047-val_loss:0.6308-val_acc:0.6480......Epoch29/303000/3000-7s-loss:0.0927-acc:0.9797-val_loss:1.1696-val_acc:0.7380Epoch30/303000/3000-7s-loss:0.0975-acc:0.9803-val_loss:1.6790-val_acc:0.7840我们还要看看模型训练期间所有周期的准确率和损失值:

model.save('cats_dogs_basic_cnn.h5')具有图像增强的CNN模型让我们通过使用适当的图像增强策略添加更多数据来改进我们的常规CNN模型。由于我们先前的模型每次都在相同的小数据点样本上进行训练,因此无法很好地推广,并在经过几个周期后最终过拟合。

图像增强背后的想法是,我们遵循一个既定过程,从训练数据集中获取现有图像,并对它们应用一些图像变换操作,例如旋转,剪切,平移,缩放等,以生成现有图像的新的,经过修改的版本。由于这些随机转换,我们每次都不会获得相同的图像,我们将利用Python生成器在训练过程中将这些新图像提供给我们的模型。

Keras框架具有一个称为ImageDataGenerator的出色工具,可以帮助我们完成所有前面的操作。让我们为训练和验证数据集初始化两个数据生成器:

让我们看看其中一些生成的图像可能看起来如何,以便您可以更好地理解它们。我们将从训练数据集中获取两个样本图像进行说明。第一张图片是猫的图片:

让我们看一下现在是狗的图像:

img_id=1991dog_generator=train_datagen.flow(train_imgs[img_id:img_id+1],train_labels[img_id:img_id+1],batch_size=1)dog=[next(dog_generator)foriinrange(0,5)]fig,ax=plt.subplots(1,5,figsize=(15,6))print('Labels:',[item[1][0]foritemindog])l=[ax[i].imshow(dog[i][0][0])foriinrange(0,5)]这向我们展示了图像增强如何帮助创建新图像,以及在其上训练模型应如何帮助对抗过拟合:

请记住,对于我们的验证生成器,我们只需要将验证图像(原始图像)发送到模型以进行评估;因此,我们仅缩放图像像素(介于0-1之间),并且不应用任何变换。我们仅将图像增强转换应用于我们的训练图像:

train_generator=train_datagen.flow(train_imgs,train_labels_enc,batch_size=30)val_generator=val_datagen.flow(validation_imgs,validation_labels_enc,batch_size=20)input_shape=(150,150,3)现在,使用我们创建的图像增强数据生成器来训练带有正则化的CNN模型。我们将使用之前的相同模型架构:

history=model.fit_generator(train_generator,steps_per_epoch=100,epochs=100,validation_data=val_generator,validation_steps=50,verbose=1)Epoch1/100100/100-12s-loss:0.6924-acc:0.5113-val_loss:0.6943-val_acc:0.5000Epoch2/100100/100-11s-loss:0.6855-acc:0.5490-val_loss:0.6711-val_acc:0.5780......Epoch99/100100/100-11s-loss:0.3735-acc:0.8367-val_loss:0.4425-val_acc:0.8340Epoch100/100100/100-11s-loss:0.3733-acc:0.8257-val_loss:0.4046-val_acc:0.8200我们的验证准确率跃升至82%左右,几乎比我们先前的模型好4-5%。此外,我们的训练准确率与验证准确率非常相似,这表明我们的模型不再适合。下图描述了模型的准确率和每个周期的损失:

总体上,虽然验证准确率和损失存在一些峰值,但我们发现它与训练准确率非常接近,损失表明我们获得的模型与以前的模型相比,泛化效果更好。现在保存此模型,以便稍后可以在测试数据集中对其进行评估:

model.save('cats_dogs_cnn_img_aug.h5')现在,我们将尝试并利用迁移学习的功能,看看是否可以构建更好的模型。

到目前为止,我们已经通过指定自己的架构从头开始构建了CNN深度学习模型。在本节中,我们将利用预训练的模型,该模型基本上是计算机视觉领域的专家,并且在图像分类和归类中享有盛誉。我们建议您阅读第4章“迁移学习基础知识”,以简要地了解预训练模型及其在该领域中的应用。

在构建新模型或重用它们时,可以通过以下两种流行的方式来使用预训练的模型:

这为我们提供了一个优势,即可以使用预先训练的模型作为新图像的有效特征提取器,以解决各种复杂的计算机视觉任务,例如用较少的图像解决我们的猫对狗分类器,甚至构建狗的品种分类器,面部表情分类器,以及更多!在释放迁移学习的力量解决我们的问题之前,让我们简要讨论一下VGG-16模型架构。

我建议所有感兴趣的读者继续阅读本文中的优秀文献。在第3章“了解深度学习架构”中简要提到了VGG-16模型,但我们将对其进行更详细的讨论,并在我们的示例中也使用它。下图描述了VGG-16模型的架构:

您可以清楚地看到,我们总共有13个卷积层,其中使用了3x3卷积滤波器,以及用于下采样的最大池化层,每层中总共有两个完全连接的隐藏层,共4,096个单元,然后是1,000个单元的密集层,其中每个单元代表ImageNet数据库中的图像类别之一。

在下面的框图中,我们代表了先前的架构以及将要使用的两个变体(基本特征提取器和微调),因此您可以获得更好的视觉视角:

因此,我们最关心的是利用VGG-16模型的卷积块,然后展平最终输出(来自特征图),以便我们可以将其输入到我们自己的密集层中进行分类。本章本节中使用的所有代码都可以通过TransferLearning.ipynbJupyter笔记本在CNN中找到。

让我们利用Keras,加载VGG-16模型并冻结卷积块,以便将其用作图像特征提取器:

要验证VGG-16模型的各层是否冻结,我们可以使用以下代码:

importpandasaspdpd.set_option('max_colwidth',-1)layers=[(layer,layer.name,layer.trainable)forlayerinvgg_model.layers]pd.DataFrame(layers,columns=['LayerType','LayerName','LayerTrainable'])前面的代码生成以下输出:

print("Trainablelayers:",vgg_model.trainable_weights)Trainablelayers:[]从前面的输出中很明显,VGG-16模型的所有层都是冻结的,这很好,因为我们不希望在模型训练期间改变它们的权重。VGG-16模型中的最后一个激活特征图(block5_pool的输出)为我们提供了瓶颈特征,这些特征可以被展平并馈送到完全连接的深度神经网络分类器中。以下代码片段显示了来自我们的训练数据的样本图像的瓶颈特征:

bottleneck_feature_example=vgg.predict(train_imgs_scaled[0:1])print(bottleneck_feature_example.shape)plt.imshow(bottleneck_feature_example[0][:,:,0])(1,4,4,512)前面的代码生成以下输出:

defget_bottleneck_features(model,input_imgs):features=model.predict(input_imgs,verbose=0)returnfeaturestrain_features_vgg=get_bottleneck_features(vgg_model,train_imgs_scaled)validation_features_vgg=get_bottleneck_features(vgg_model,validation_imgs_scaled)print('TrainBottleneckFeatures:',train_features_vgg.shape,'\tValidationBottleneckFeatures:',validation_features_vgg.shape)TrainBottleneckFeatures:(3000,8192)ValidationBottleneckFeatures:(1000,8192)前面的输出告诉我们,我们已经成功提取了3,000个训练图像和1,000个验证图像的尺寸为1x8,192的扁平瓶颈特征。现在让我们构建深度神经网络分类器的架构,它将这些特征作为输入:

history=model.fit(x=train_features_vgg,y=train_labels_enc,validation_data=(validation_features_vgg,validation_labels_enc),batch_size=batch_size,epochs=epochs,verbose=1)Trainon3000samples,validateon1000samplesEpoch1/303000/3000-1s373us/step-loss:0.4325-acc:0.7897-val_loss:0.2958-val_acc:0.8730Epoch2/303000/3000-1s286us/step-loss:0.2857-acc:0.8783-val_loss:0.3294-val_acc:0.8530......Epoch29/303000/3000-1s287us/step-loss:0.0121-acc:0.9943-val_loss:0.7760-val_acc:0.8930Epoch30/303000/3000-1s287us/step-loss:0.0102-acc:0.9987-val_loss:0.8344-val_acc:0.8720我们得到的模型的验证精度接近88%,几乎比具有图像增强的基本CNN模型提高了5-6%,这非常好。不过,该模型似乎确实过拟合,我们可以使用下图中所示的精度和损耗图进行检查:

在第五个周期之后,模型训练与验证准确率之间存在相当大的差距,这清楚表明模型在此之后对训练数据过拟合。但是总的来说,这似乎是迄今为止最好的模型,通过利用VGG-16模型作为特征提取器,我们甚至不需要使用图像增强策略就可以接近90%验证精度。但是我们还没有充分利用迁移学习的全部潜力。让我们尝试在此模型上使用我们的图像增强策略。在此之前,我们使用以下代码将此模型保存到磁盘:

model.save('cats_dogs_tlearn_basic_cnn.h5')作为图像增强的特征提取器预训练的CNN模型我们将为之前使用的训练和验证数据集使用相同的数据生成器。为了便于理解,构建它们的代码如下所示:

train_datagen=ImageDataGenerator(rescale=1./255,zoom_range=0.3,rotation_range=50,width_shift_range=0.2,height_shift_range=0.2,shear_range=0.2,horizontal_flip=True,fill_mode='nearest')val_datagen=ImageDataGenerator(rescale=1./255)train_generator=train_datagen.flow(train_imgs,train_labels_enc,batch_size=30)val_generator=val_datagen.flow(validation_imgs,validation_labels_enc,batch_size=20)现在让我们构建深度学习模型架构。因为我们将在数据生成器上进行训练,所以我们不会像上次那样提取瓶颈特征。因此,我们将vgg_model对象作为输入传递给我们自己的模型:

model=Sequential()model.add(vgg_model)model.add(Dense(512,activation='relu',input_dim=input_shape))model.add(Dropout(0.3))model.add(Dense(512,activation='relu'))model.add(Dropout(0.3))model.add(Dense(1,activation='sigmoid'))model.compile(loss='binary_crossentropy',optimizer=optimizers.RMSprop(lr=2e-5),metrics=['accuracy'])您可以清楚地看到一切都一样。由于我们将训练100个周期,因此我们将学习率稍微降低了,并且不想对我们的模型层进行突然的权重调整。请记住,VGG-16模型的层仍在此处冻结,我们仍将其仅用作基本特征提取器:

history=model.fit_generator(train_generator,steps_per_epoch=100,epochs=100,validation_data=val_generator,validation_steps=50,verbose=1)Epoch1/100100/100-45s449ms/step-loss:0.6511-acc:0.6153-val_loss:0.5147-val_acc:0.7840Epoch2/100100/100-41s414ms/step-loss:0.5651-acc:0.7110-val_loss:0.4249-val_acc:0.8180......Epoch99/100100/100-42s417ms/step-loss:0.2656-acc:0.8907-val_loss:0.2757-val_acc:0.9050Epoch100/100100/100-42s418ms/step-loss:0.2876-acc:0.8833-val_loss:0.2665-val_acc:0.9000我们可以看到我们的模型的整体验证精度为90%,这比我们先前的模型略有改进,并且训练和验证精度彼此非常接近,表明该模型是欠拟合。可以通过查看以下有关模型准确率和损失的图来加强这一点:

我们可以清楚地看到,训练值和验证准确率的值非常接近,并且模型也不会过拟合。此外,我们达到90%的准确率,这很干净!让我们现在将此模型保存在磁盘上,以便将来对测试数据进行评估:

model.save('cats_dogs_tlearn_img_aug_cnn.h5')现在,我们将微调VGG-16模型以构建我们的最后一个分类器,我们将在此取消冻结第4块和第5块,如本节开头所述。

现在,我们将利用存储在vgg_model变量中的VGG-16模型对象,解冻卷积块4和5,同时保持前三个块处于冻结状态。以下代码可帮助我们实现这一目标:

layers=[(layer,layer.name,layer.trainable)forlayerinvgg_model.layers]pd.DataFrame(layers,columns=['LayerType','LayerName','LayerTrainable'])前面的代码生成以下输出:

我们可以清楚地看到最后两个块现在是可训练的,这意味着当我们传递每批数据时,这些层的权重也将在每个周期中通过反向传播进行更新。我们将使用与之前的模型相同的数据生成器和模型架构,并对模型进行训练。因为我们不想卡在任何局部最小值上,所以我们会稍微降低学习率,并且我们也不想突然将可训练的VGG-16模型层的权重突然增加可能会对模型产生不利影响的大因素:

让我们观察模型的准确率和损失图:

我们可以看到,这里的准确率值确实非常好,尽管模型看起来可能对训练数据有些过拟合,但我们仍然获得了很高的验证准确率。现在,使用以下代码将此模型保存到磁盘:

model.save('cats_dogs_tlearn_finetune_img_aug_cnn.h5')现在,通过在测试数据集上实际评估模型的表现,将所有模型进行测试。

现在,我们将评估到目前为止构建的五个不同模型,方法是首先在样本测试图像上对其进行测试,然后可视化CNN模型实际上是如何尝试从图像中分析和提取特征,最后通过在测试数据集上测试每个模型的表现来进行评估。如果要执行代码并遵循本章的内容,ModelPerformanceEvaluations.ipynbJupyter笔记本中提供了此部分的代码。我们还构建了一个名为model_evaluation_utils的实用工具模块,我们将使用该模块来评估深度学习模型的表现。让我们在开始之前加载以下依赖项:

importglobimportnumpyasnpimportmatplotlib.pyplotaspltfromkeras.preprocessing.imageimportload_img,img_to_array,array_to_imgfromkeras.modelsimportload_modelimportmodel_evaluation_utilsasmeu%matplotlibinline加载这些依赖关系后,让我们加载到目前为止已保存的模型:

basic_cnn=load_model('cats_dogs_basic_cnn.h5')img_aug_cnn=load_model('cats_dogs_cnn_img_aug.h5')tl_cnn=load_model('cats_dogs_tlearn_basic_cnn.h5')tl_img_aug_cnn=load_model('cats_dogs_tlearn_img_aug_cnn.h5')tl_img_aug_finetune_cnn=load_model('cats_dogs_tlearn_finetune_img_aug_cnn.h5')这有助于我们检索使用各种技术和架构在本章中创建的所有五个模型。

现在,我们将加载不属于任何数据集的样本图像,并尝试查看不同模型的预测。我将在此处使用我的宠物猫的图像,因此这将很有趣!让我们加载示例图像和一些基本配置:

#basicconfigurationsIMG_DIM=(150,150)input_shape=(150,150,3)num2class_label_transformer=lambdal:['cat'ifx==0else'dog'forxinl]class2num_label_transformer=lambdal:[0ifx=='cat'else1forxinl]#loadsampleimagesample_img_path='my_cat.jpg'sample_img=load_img(sample_img_path,target_size=IMG_DIM)sample_img_tensor=img_to_array(sample_img)sample_img_tensor=np.expand_dims(sample_img_tensor,axis=0)sample_img_tensor/=255\.print(sample_img_tensor.shape)plt.imshow(sample_img_tensor[0])(1,150,150,3)前面的代码生成以下输出:

现在,我们已经加载了示例图像,让我们看看我们的模型将其作为该图像类别的预测(我的猫):

深度学习模型通常被称为黑盒模型,因为与诸如决策树之类的简单ML模型相比,很难真正解释该模型在内部的工作方式。我们知道,基于CNN的深度学习模型使用卷积层,该卷积层使用过滤器提取代表特征空间层次的激活特征图。从概念上讲,顶级卷积层学习小的局部模式,而网络中较低的层则学习更复杂和更大的模式,这些模式是从顶级卷积层获得的。让我们尝试通过一个示例来形象化。

我们将采用最佳模型(通过微调和图像增强进行迁移学习),并尝试从前八层中提取输出激活特征图。本质上,这将最终为我们提供VGG-16模型前三个模块的卷积和池化层,因为我们在模型中使用了相同的特征提取。

要查看这些层,可以使用以下代码:

tl_img_aug_finetune_cnn.layers[0].layers[1:9][,,,,,,,]现在,基于它试图从我的猫的样本测试图像中提取的内容,从我们的模型中提取特征图。为了简单说明,我们从块1中提取第一个卷积层之后的输出,并在以下代码段中从中查看一些激活特征图:

fromkerasimportmodels#Extractstheoutputsofthetop8layers:layer_outputs=[layer.outputforlayerintl_img_aug_finetune_cnn.layers[0].layers[1:9]]#Createsamodelthatwillreturntheseoutputs,giventhemodelinput:activation_model=models.Model(inputs=tl_img_aug_finetune_cnn.layers[0].layers[1].input,outputs=layer_outputs)#Thiswillreturnalistof8Numpyarrays#onearrayperlayeractivationactivations=activation_model.predict(sample_img_tensor)print('Samplelayershape:',activations[0].shape)print('Sampleconvolution(activationmap)shape:',activations[0][0,:,:,1].shape)fig,ax=plt.subplots(1,5,figsize=(16,6))ax[0].imshow(activations[0][0,:,:,10],cmap='bone')ax[1].imshow(activations[0][0,:,:,25],cmap='bone')ax[2].imshow(activations[0][0,:,:,40],cmap='bone')ax[3].imshow(activations[0][0,:,:,55],cmap='bone')ax[4].imshow(activations[0][0,:,:,63],cmap='bone')Samplelayershape:(1,150,150,64)Sampleconvolution(activationmap)shape:(150,150)前面的代码生成以下输出:

为了获得上述激活函数图,我们利用了ModelPerformanceEvaluations.ipynbJupyter笔记本中可用的代码段,这要感谢FrancoisChollet和他的书《Python深度学习》,它可以帮助可视化我们的CNN模型中所有选定的层。我们已经可视化了模型的前八层,这是我们在笔记本中较早选择的,但是在这里显示了前两个块的激活图。随意检出笔记本并为自己的模型重复使用相同的代码。从前面的屏幕截图中,您可能会看到顶层特征图通常保留了很多原始图像,但是当您深入模型时,特征图变得更加抽象,复杂且难以解释。

现在是时候进行最终测试了,在该测试中,我们通过对测试数据集进行预测来从字面上测试模型的表现。在进行预测之前,让我们先加载并准备测试数据集:

IMG_DIM=(150,150)test_files=glob.glob('test_data/*')test_imgs=[img_to_array(load_img(img,target_size=IMG_DIM))forimgintest_files]test_imgs=np.array(test_imgs)test_labels=[fn.split('/')[1].split('.')[0].strip()forfnintest_files]test_labels_enc=class2num_label_transformer(test_labels)test_imgs_scaled=test_imgs.astype('float32')test_imgs_scaled/=255print('Testdatasetshape:',test_imgs.shape)Testdatasetshape:(1000,150,150,3)现在我们已经准备好按比例缩放的数据集,让我们通过对所有测试图像进行预测来评估每个模型,然后通过检查预测的准确率来评估模型的表现:

#Model1-BasicCNNpredictions=basic_cnn.predict_classes(test_imgs_scaled,verbose=0)predictions=num2class_label_transformer(predictions)meu.display_model_performance_metrics(true_labels=test_labels,predicted_labels=predictions,classes=list(set(test_labels)))前面的代码生成以下输出:

#Model2-BasicCNNwithImageAugmentationpredictions=img_aug_cnn.predict_classes(test_imgs_scaled,verbose=0)predictions=num2class_label_transformer(predictions)meu.display_model_performance_metrics(true_labels=test_labels,predicted_labels=predictions,classes=list(set(test_labels)))前面的代码生成以下输出:

#Model3-TransferLearning(basicfeatureextraction)test_bottleneck_features=get_bottleneck_features(vgg_model,test_imgs_scaled)predictions=tl_cnn.predict_classes(test_bottleneck_features,verbose=0)predictions=num2class_label_transformer(predictions)meu.display_model_performance_metrics(true_labels=test_labels,predicted_labels=predictions,classes=list(set(test_labels)))前面的代码生成以下输出:

#Model4-TransferLearningwithImageAugmentationpredictions=tl_img_aug_cnn.predict_classes(test_imgs_scaled,verbose=0)predictions=num2class_label_transformer(predictions)meu.display_model_performance_metrics(true_labels=test_labels,predicted_labels=predictions,classes=list(set(test_labels)))前面的代码生成以下输出:

我们可以看到我们肯定有一些有趣的结果。每个后续模型的表现均优于先前模型,这是预期的,因为我们对每个新模型都尝试了更高级的技术。我们最差的模型是基本的CNN模型,其模型准确率和F1分数约为78%,而我们最好的模型是经过微调的模型,其中包含迁移学习和图像增强,从而为我们提供了一个模型准确率和96%的F1得分,考虑到我们从3,000个图像训练数据集中训练了模型,这真是太了不起了。现在,让我们绘制最差模型和最佳模型的ROC曲线:

#worstmodel-basicCNNmeu.plot_model_roc_curve(basic_cnn,test_imgs_scaled,true_labels=test_labels_enc,class_names=[0,1])#bestmodel-transferlearningwithfine-tuning&imageaugmentationmeu.plot_model_roc_curve(tl_img_aug_finetune_cnn,test_imgs_scaled,true_labels=test_labels_enc,class_names=[0,1])我们得到的图如下:

这应该给您一个很好的主意,即预训练模型和迁移学习可以带来多大的差异,尤其是当我们面临诸如数据较少等约束时,在解决复杂问题上。我们鼓励您使用自己的数据尝试类似的策略。

本章的目的是让您更深入地了解构建深度学习模型以解决实际问题,并了解迁移学习的有效性。我们涵盖了迁移学习需求的各个方面,尤其是在解决数据受限的问题时。我们从头开始构建了多个CNN模型,还看到了适当的图像增强策略的好处。我们还研究了如何利用预训练的模型进行迁移学习,并介绍了使用它们的各种方法,包括用作特征提取器和微调。我们看到了VGG-16模型的详细架构,以及如何利用该模型作为有效的图像特征提取器。与迁移学习有关的策略(包括特征提取和微调以及图像增强)被用来构建有效的深度学习图像分类器。

THE END
1.AI教育在线,重塑教育模式的未来之路蔬菜花卉AI教育在线致力于重塑教育模式,探索未来教育的新路径。借助人工智能技术的力量,AI教育在线提供个性化的学习体验,深化学习内容的理解与应用,提高教育质量。通过智能教学工具和数据分析,AI教育在线帮助学生发掘潜力,提升学https://hnjwwzy.cn/post/2885.html
2.易学习在线,数字化高效学习路径的探索技术服务易学习在线致力于探索高效学习的数字化路径。通过结合现代科技,提供丰富的学习资源和工具,帮助学习者随时随地获取知识,提升学习效率。致力于创新教学方式,让学习变得更加便捷、高效。 易学习在线的核心特点 易学习在线以其丰富的教育资源、个性化的学习体验、强大的互动功能以及高度的灵活性,成为数字化教育的新宠。 https://m.ahsanfangjs.com/post/22849.html
3.AI自习室:莫让网课李代桃僵新闻频道近来,厦门一些学校、社区周边,悄然出现了一种利用人工智能技术提供个性化学习体验的AI自习室。这种自习室结合?智能技术和传统自习室概念的创新学习场所,不仅具备传统自习室的自学功能,还能通过?智能硬件和?大模型技术的应用,为使用者提供更加高效和个性化的学习体验,这对于不少想要获得更好学习体验的人来说是一个https://news.xmnn.cn/ldrp/zgsb/202412/t20241216_287856.html
4.线上教育系统开发:打造高效互动的学习平台线上教育系统的互动性是其区别于传统教育模式的重要特征之一。系统应提供师生互动、付费问答、移动社群等功能,鼓励学生积极参与讨论,提高学习效果。同时,通过在线打卡、督导管理等功能,系统可以帮助学生养成良好的学习习惯。 数据分析 线上教育系统应具备强大的数据分析能力,能够实时跟踪学生的学习进度、成绩变化等关键指标https://pbids.com/aboutUs/pbidsNews/1861300381964931072
5.AI自习室是风口还是噱头?在教育领域,AI自习室正逐渐兴起。这不仅为学生提供了个性化的学习体验,也引发了关于教育未来发展路径的广泛讨论。(12月19日《科技日报》) 加上“AI”前缀的自习室成了一门“火热”的生意。AI自习室在学校附近底商、培训机构教室以及小区内部悄然活跃起来。在资本市场的表现同样火热——这类软硬一体式的教育经营模式http://www.xinhuanet.com/comments/20241220/32fe7fbc94e0494db8428538d41cb591/c.html
6.连续工龄的认定职工自动离职的工龄计算按除名情况处理。根据有关规定,受到除名处理的职工,除名前的连续工龄与重新就业后的工作时间可以合并计算为连续工龄。 职工曾被开除、刑事处分后再次参加工作的,其连续工龄只能从最后一次参加工作之日算起。 6、在高等院校脱产、半脱产学习的职工工龄能否计算? 在高等院校脱产、半脱产学习的职工,https://www.66law.cn/laws/38886.aspx
7.视频课程干部培训点击学习选项卡里的课程列表下面红色的自动连续学习上面的课程按钮,视频将自动连续放。 广东省干部培训网络学院是由中共广东省委组织部主办,网站涵盖了政治、经济、教育、时事分析等各个板块的视频课程。 中国教育干部培训网视频如何下载 登陆中国教育干部培训网,找到您想要的课程点击打开,最下方会有课程位置。将其复制、https://www.govjiaoyu.cn/peixun/1842.html
8.驾照满分学习要连续学习七天,中间不能断吗1、驾驶证实习期内如果扣满12分,驾驶证自动注销。需连续7天学习并考试科目一,考试合格后,可以领取https://www.64365.com/ask/11004443.aspx
9.分析股市预测的深度学习技术结合在线学习和深度学习方法 在线学习是一种训练方法,它使用模型的在线训练结果作为反馈以实现模型调整。对于缓解股市波动性、不确定性、高噪声因素的影响大有裨益。投资者需要根据股价走势及时调整投资计划,将此方法应用于股票市场投资策略是明智的。它将同时更新模型,从而自动控制预测结果和期望值之间的差异。已经有一些https://maimai.cn/article/detail?fid=1810610871&efid=k8hnL1-NvJ2kAfW8I85mSg
10.中控技术2022年年度董事会经营评述股市直击股票基于迁移学习的控制回路自整定技术,利用了回路整定的大数据和专家经验,实现了缺乏历史数据情况下的参数预整定;实现了历史及在线数据自动分析,数据和回路特征提取,智能匹配整定策略,回路批量自整定;基于自学习策略不断迭代优化过程对象模型,实现了回路参数的渐进优化,降低了整定过程的门槛,提高了整定的效率和不同工况http://4g.stockstar.com/detail/IG2023042600034846
11.批量梯度下降和随机梯度下降(SGD)和小批量梯度下降在线学习机制今天 许多大型网站 或者许多大型网络公司 使用不同版本的 在线学习机制算法 从大批的涌入 又离开网站的用户身上 进行学习 特别要提及的是 如果你有 一个由连续的用户流引发的 连续的数据流 用户流进入 你的网站 你能做的是使用一个 在线学习机制 从数据流中学习 用户的偏好 然后使用这些信息 来优化一些 关于网站https://blog.51cto.com/u_15127568/3859318
12.深度强化学习为智能航空发动机控制赋能因此他提出了一种基于连续动作空间的强化学习自动机,用以在线自动调整发动机怠速转速控制的PID参数,如图3所示。此方法相较于传统的人工调参而言大幅降低了人力成本,同时显著提高了调参效率及发动机的动态性能。这不仅为深度强化学习在实际控制系统中的应用奠定了实证基础,而且对发动机控制技术的发展做出了实质性贡献。https://www.aerospacepower.cn/article/2314
13.计算机应用研究杂志四川省计算机研究院主办2016年第01期一种基于学习自动机的推荐算法改进 关键词:学习自动机 奇异值分解 推荐算法 隐语义模型 梯度下降算法 针对原有的基于隐语义模型(LFM)的推荐算法中,当训练样本数减少时,训练误差和测试误差都明显增大的问题进行改进研究,提出了一种全新的基于学习自动机的矩阵训练算法。该算法充分利用连续型学习自动机在随机和高噪声https://www.youfabiao.com/jsjyyyj/201601/
14.学习啦在线学习网免费的技能特长知识学习网站学习啦在线学习网是免费的技能、特长、知识综合学习网站,提供各行各业学习资讯供大家学习参考,如学习方法交流、智力测试、记忆力训练、电脑教程、英语学习教程、职场攻略、励志故事、各种实用生活百科知识等等!https://www.xuexila.com/
15.自动驾驶的社会交互:一个综述和思考汽车技术SVO模型衡量了一个驾驶员如何将其奖励相对其他智体的奖励的加权,这可以从逆强化学习(IRL)结构下的观测轨迹中学习。然后,SVO模型的在线学习驾驶偏好,集成到两辆或多辆的车辆协同交互的游戏场景中。SVO概念已被广泛研究并应用于社会兼容的自主驾驶中。 2 社交驱动模仿的社会凝聚力https://www.auto-testing.net/news/show-116481.html
16.个人工作技术总结范文3000字(通用13篇)20xx年7月毕业后来到公司,正值动力厂筹建25MW煤气发电项目,由于刚刚毕业,现场经验不足,于是自己一直扎根现场,将书本上的知识与现场相结合,理论联系实际,同时虚心请教学习,对于每个设备从认识到了解,是一个很充实的过程,从锅炉部件安装开始,从汽机每个独立的设备安装开始,每个设备最后都能熟悉其结构及原理,一直在整个筹https://www.fwsir.com/Article/html/Article_20220922085447_1988195.html
17.电力营销安全生产工作总结(通用19篇)1、强化安全培训,提高职工安全素质:实践证明提高职工安全素质是预防事故的跟本措施,必须加大力度,不会什么学什么,不懂什么学什么,在今年我所依据年初制定的职工培训计划,有目标,有针对性开展了各项安全培训活动,组织职工学习电力局编印成册的《现场应重点防止的习惯性违章行为》,并针对工作中的违章易发环节,开展讨论活动https://www.oh100.com/a/202204/4563649.html