每个程序员都应该知道的 40 个算法(三)(1)

简介: 每个程序员都应该知道的 40 个算法(三)


原文:zh.annas-archive.org/md5/8ddea683d78e7bd756401ec665273969

译者:飞龙

协议:CC BY-NC-SA 4.0

第八章:神经网络算法

各种因素的结合使得人工神经网络(ANNs)成为当今最重要的机器学习技术之一。这些因素包括解决日益复杂的问题的需求,数据的爆炸以及诸如可用的廉价集群等技术的出现,这些技术提供了设计非常复杂算法所需的计算能力。

事实上,这是一个迅速发展的研究领域,负责实现机器人技术、自然语言处理和自动驾驶汽车等领先技术领域所宣称的大部分重大进展。

观察 ANN 的结构,其基本单元是神经元。ANN 的真正优势在于其能够通过将它们组织成分层架构来利用多个神经元的力量。ANN 通过在不同层中将神经元链接在一起来创建分层架构。信号通过这些层传递,并在每个层中以不同的方式进行处理,直到生成最终所需的输出。正如我们将在本章中看到的,ANN 使用的隐藏层充当抽象层,实现了深度学习,这在实现强大的应用程序中被广泛使用,如亚马逊的 Alexa,谷歌的图像搜索和谷歌相册。

本章首先介绍了典型神经网络的主要概念和组件。然后,它介绍了各种类型的神经网络,并解释了这些神经网络中使用的不同类型的激活函数。接下来,详细讨论了反向传播算法,这是训练神经网络最广泛使用的算法。然后,解释了迁移学习技术,可以用来大大简化和部分自动化模型的训练。最后,通过一个真实世界的应用程序案例,探讨了如何使用深度学习来标记欺诈文件。

本章讨论的主要概念如下:

  • 理解人工神经网络
  • ANN 的演变
  • 训练神经网络
  • 工具和框架
  • 迁移学习
  • 案例研究:使用深度学习进行欺诈检测

让我们从人工神经网络的基础知识开始。

理解人工神经网络

受人脑神经元工作的启发,神经网络的概念是由 Frank Rosenblatt 在 1957 年提出的。要充分理解其架构,有助于简要了解人脑中神经元的分层结构。(参考以下图表,了解人脑中的神经元是如何连接在一起的。)

在人脑中,树突充当检测信号的传感器。然后,信号传递给轴突,轴突是神经细胞的一种长而细的突出部分。轴突的功能是将这个信号传递给肌肉、腺体和其他神经元。如下图所示,信号通过称为突触的相互连接的组织传递,然后传递给其他神经元。请注意,通过这种有机管道,信号一直传递,直到它到达目标肌肉或腺体,引起所需的动作。信号通常需要七到八毫秒才能通过神经元链传递并到达目标位置:


受到这种自然的信号处理的建筑杰作的启发,Frank Rosenblatt 设计了一种意味着数字信息可以在层中处理以解决复杂数学问题的技术。他最初设计的神经网络非常简单,看起来类似于线性回归模型。这种简单的神经网络没有任何隐藏层,被命名为感知器。以下图表对其进行了说明:


让我们尝试开发这个感知器的数学表示。在前面的图表中,输入信号显示在左侧。这是输入的加权和,因为每个输入*(x[1],x[2]…x[n])都会乘以相应的权重(w[1],w[2]… w[n])*,然后求和:


请注意,这是一个二元分类器,因为这个感知器的最终输出取决于聚合器的输出是真还是假(在图表中显示为)。如果聚合器能够从至少一个输入中检测到有效信号,它将产生一个真实的信号。

现在让我们来看看神经网络是如何随着时间的推移而发展的。

人工神经网络的演变

在前面的部分中,我们研究了一个没有任何层的简单神经网络,称为感知器。发现感知器有严重的局限性,并且在 1969 年,马文·明斯基和西摩·帕帕特进行了研究,得出结论感知器无法学习任何复杂的逻辑。

事实上,他们表明即使学习像异或这样简单的逻辑函数也是一种挑战。这导致了对机器学习和神经网络的兴趣下降,开始了一个现在被称为AI 寒冬的时代。世界各地的研究人员不会认真对待人工智能,认为它无法解决任何复杂的问题。

所谓的 AI 寒冬的主要原因之一是当时可用的硬件能力的限制。要么是必要的计算能力不可用,要么是价格昂贵。到了 20 世纪 90 年代末,分布式计算的进步提供了易于获得和负担得起的基础设施,这导致了 AI 寒冬的融化。这种融化重新激发了对人工智能的研究。最终导致了将当前时代变成一个可以称为AI 春天的时代,人们对人工智能和神经网络特别感兴趣。

对于更复杂的问题,研究人员开发了一个称为多层感知器的多层神经网络。多层神经网络有几个不同的层,如下图所示。这些层包括:

  • 输入层
  • 隐藏层
  • 输出层:

深度神经网络是一个具有一个或多个隐藏层的神经网络。深度学习是训练人工神经网络的过程。

一个重要的事情要注意的是神经元是这个网络的基本单元,每个层的神经元都连接到下一层的所有神经元。对于复杂的网络,这些互连的数量激增,我们将探索不牺牲太多质量的不同减少这些互连的方法。

首先,让我们尝试阐明我们要解决的问题。

输入是一个特征向量x,维度为n

我们希望神经网络能够预测值。预测值由ý表示。

从数学上讲,我们想要确定在给定特定输入的情况下,交易是欺诈的概率。换句话说,给定特定的x值,y=1 的概率是多少?从数学上讲,我们可以表示如下:


注意,x是一个*n[x]维向量,其中n[x]*是输入变量的数量。

这个神经网络有四层。输入和输出之间的层是隐藏层。第一个隐藏层中的神经元数量用表示。各个节点之间的连接由称为权重的参数相乘。训练神经网络就是找到权重的正确值。

让我们看看如何训练神经网络。

训练神经网络

使用给定数据集构建神经网络的过程称为训练神经网络。让我们来看一下典型神经网络的解剖结构。当我们谈论训练神经网络时,我们谈论计算权重的最佳值。训练是通过使用一组示例(训练数据的形式)进行迭代完成的。训练数据中的示例具有不同输入值组合的输出的预期值。神经网络的训练过程与传统模型的训练方式不同(这些在第七章中讨论过,传统监督学习算法)。

理解神经网络的解剖结构

让我们看看神经网络包括什么:

  • 层: 层是神经网络的核心构建模块。每一层都是一个数据处理模块,充当过滤器。它接受一个或多个输入,以某种方式处理它,然后产生一个或多个输出。每当数据通过一层时,它都会经过一个处理阶段,并显示与我们试图回答的业务问题相关的模式。
  • 损失函数: 损失函数提供了在学习过程的各个迭代中使用的反馈信号。损失函数提供了单个示例的偏差。
  • 成本函数: 成本函数是完整示例集上的损失函数。
  • 优化器: 优化器确定损失函数提供的反馈信号将如何被解释。
  • 输入数据: 输入数据是用于训练神经网络的数据。它指定目标变量。
  • 权重: 权重是通过训练网络计算的。权重大致对应于每个输入的重要性。例如,如果特定输入比其他输入更重要,在训练后,它将被赋予更大的权重值,充当乘数。即使对于该重要输入的弱信号也将从大的权重值(充当乘数)中获得力量。因此,权重最终会根据它们的重要性转换每个输入。
  • 激活函数: 值将由不同的权重相乘然后聚合。它们将如何被聚合以及它们的值将如何被解释将由所选择的激活函数的类型确定。

现在让我们来看看神经网络训练的一个非常重要的方面。

在训练神经网络时,我们逐个示例地进行。对于每个示例,我们使用正在训练的模型生成输出。我们计算期望输出和预测输出之间的差异。对于每个单独的示例,这种差异称为损失。在整个训练数据集中,损失被称为成本。随着我们不断训练模型,我们的目标是找到导致最小损失值的权重值。在整个训练过程中,我们不断调整权重的值,直到找到导致最小可能总成本的权重值集。一旦达到最小成本,我们标记模型已经训练完成。

定义梯度下降

训练神经网络模型的目的是找到权重的正确值。我们开始训练神经网络时,权重使用随机或默认值。然后,我们迭代使用优化算法,例如梯度下降,以改变权重,使我们的预测改善。

梯度下降算法的起点是需要通过算法迭代优化的随机权重值。在随后的每次迭代中,算法通过以最小化成本的方式改变权重值来进行。

以下图解释了梯度下降算法的逻辑:


在前面的图中,输入是特征向量X。目标变量的实际值是Y,目标变量的预测值是Y’。我们确定实际值与预测值的偏差。我们更新权重并重复这些步骤,直到成本最小化。

在算法的每次迭代中如何改变权重将取决于以下两个因素:

  • 方向: 要走的方向以获得损失函数的最小值
  • 学习率: 我们选择的方向中变化应该有多大

下面的图表显示了一个简单的迭代过程:


该图显示了通过改变权重,梯度下降试图找到最小成本。学习率和选择的方向将决定要探索的图表上的下一个点。

选择正确的学习率很重要。如果学习率太小,问题可能需要很长时间才能收敛。如果学习率太高,问题将无法收敛。在前面的图中,代表当前解决方案的点将在图表的两条相反线之间不断振荡。

现在,让我们看看如何最小化梯度。只考虑两个变量,xyxy的梯度计算如下:

为了最小化梯度,可以使用以下方法:

while(gradient!=0):
 if (gradient < 0); move right
 if (gradient > 0); move left
• 1
• 2
• 3

该算法也可以用于找到神经网络的最优或接近最优的权重值。

请注意,梯度下降的计算是在整个网络中向后进行的。我们首先计算最后一层的梯度,然后是倒数第二层,然后是倒数第二层之前的层,直到达到第一层。这被称为反向传播,由 Hinton、Williams 和 Rumelhart 于 1985 年引入。

接下来,让我们看看激活函数。

激活函数

激活函数规定了特定神经元的输入如何被处理以生成输出。

如下图所示,神经网络中的每个神经元都有一个激活函数,确定输入将如何被处理:


在前面的图中,我们可以看到激活函数生成的结果传递到输出。激活函数设置了如何解释输入值以生成输出的标准。

对于完全相同的输入值,不同的激活函数将产生不同的输出。在使用神经网络解决问题时,了解如何选择正确的激活函数是很重要的。

现在让我们逐个查看这些激活函数。

阈值函数

最简单的激活函数是阈值函数。阈值函数的输出是二进制的:0 或 1。如果任何输入大于 1,它将生成 1 作为输出。这可以在下图中解释:


请注意,一旦检测到输入加权和中有任何生命迹象,输出(y)就变为 1。这使得阈值激活函数非常敏感。它很容易被输入中的最轻微的信号或噪音错误触发。

Sigmoid

Sigmoid 函数可以被认为是阈值函数的改进。在这里,我们可以控制激活函数的灵敏度。


Sigmoid 函数y定义如下:


可以在 Python 中实现如下:

def sigmoidFunction(z): 
      return 1/ (1+np.exp(-z))

请注意,通过降低激活函数的灵敏度,我们可以减少输入中的故障的影响。请注意,Sigmoid 激活函数的输出仍然是二进制的,即 0 或 1。

修正线性单元(ReLU)

本章介绍的前两个激活函数的输出是二进制的。这意味着它们将取一组输入变量并将它们转换为二进制输出。ReLU 是一个激活函数,它将一组输入变量作为输入,并将它们转换为单一的连续输出。在神经网络中,ReLU 是最流行的激活函数,通常用于隐藏层,我们不希望将连续变量转换为类别变量。

下面的图表总结了 ReLU 激活函数:

请注意,当x≤ 0时,y = 0。这意味着输入中的任何信号为零或小于零都被转换为零输出:

for for

一旦x大于零,它就是x

ReLU 函数是神经网络中最常用的激活函数之一。它可以在 Python 中实现如下:

def ReLU(x): 
if x<0: 
    return 0 
else: 
    return x

现在让我们来看看 Leaky ReLU,它是基于 ReLU 的。

Leaky ReLU

在 ReLU 中,x的负值导致y的值为零。这意味着在这个过程中丢失了一些信息,这使得训练周期变得更长,特别是在训练开始时。Leaky ReLU 激活函数解决了这个问题。对于 Leaky ReLu,以下内容适用:

; for  for

下面的图表显示了这一点:

这里,ß是一个小于一的参数。

它可以在 Python 中实现如下:

def leakyReLU(x,beta=0.01):
    if x<0:
        return (beta*x)    
    else:        
        return x

有三种指定ß值的方法:

  • 我们可以指定一个默认值为ß。
  • 我们可以在我们的神经网络中将ß设为一个参数,并让神经网络决定该值(这称为参数化 ReLU)。
  • 我们可以将ß设为一个随机值(这称为随机化 ReLU)。

双曲正切(tanh)

tanh 函数类似于 Sigmoid 函数,但它也能给出负信号。下图说明了这一点:


y函数如下:


可以通过以下 Python 代码实现:

def tanh(x): 
    numerator = 1-np.exp(-2*x) 
    denominator = 1+np.exp(-2*x) 
    return numerator/denominator

现在让我们来看看 softmax 函数。

Softmax

有时,我们需要激活函数的输出不止两个级别。Softmax 是一个可以为输出提供不止两个级别的激活函数。它最适用于多类分类问题。假设我们有n个类。我们有输入值。输入值将类映射如下:

x = {x((1)),x((2)),…x^((n))}

Softmax 是基于概率理论的。Softmax 的第e类的输出概率计算如下:

对于二元分类器,最终层的激活函数将是 Sigmoid,对于多类分类器,它将是 Softmax。

工具和框架

在本节中,我们将详细了解用于实现神经网络的框架和工具。

随着时间的推移,许多不同的框架已经被开发出来来实现神经网络。不同的框架有各自的优势和劣势。在本节中,我们将重点关注具有 TensorFlow 后端的 Keras。

Keras

Keras 是最受欢迎和易于使用的神经网络库之一,用 Python 编写。它考虑到易用性,并提供了实现深度学习的最快方式。Keras 只提供高级模块,并被认为是在模型级别上。

Keras 的后端引擎

Keras 需要一个低级别的深度学习库来执行张量级别的操作。这个低级别的深度学习库称为后端引擎。Keras 的可能后端引擎包括以下内容:

  • TensorFlow (www.tensorflow.org):这是同类框架中最受欢迎的框架,由谷歌开源。
  • Theona (deeplearning.net/software/theano):这是在蒙特利尔大学 MILA 实验室开发的。
  • Microsoft Cognitive ToolkitCNTK):这是由微软开发的。

这种模块化深度学习技术堆栈的格式如下图所示:


这种模块化的深度学习架构的优势在于,Keras 的后端可以在不重写任何代码的情况下进行更改。例如,如果我们发现对于特定任务,TensorFlow 比 Theona 更好,我们可以简单地将后端更改为 TensorFlow,而无需重写任何代码。

深度学习堆栈的低级层

我们刚刚提到的三种后端引擎都可以在 CPU 和 GPU 上运行,使用堆栈的低级层。对于 CPU,使用了一个名为Eigen的张量操作低级库。对于 GPU,TensorFlow 使用了 NVIDIA 的CUDA 深度神经网络cuDNN)库。

定义超参数

如第六章中所讨论的无监督机器学习算法,超参数是在学习过程开始之前选择其值的参数。我们从常识值开始,然后尝试稍后优化它们。对于神经网络,重要的超参数包括:

  • 激活函数
  • 学习率
  • 隐藏层的数量
  • 每个隐藏层中的神经元数量

让我们看看如何使用 Keras 定义模型。

定义 Keras 模型

定义完整的 Keras 模型涉及三个步骤:

  1. 定义层

我们可以用两种可能的方式使用 Keras 构建模型:

  • **Sequential API:**这允许我们为一系列层构建模型。它用于相对简单的模型,并且通常是构建模型的常规选择:


请注意,在这里,我们创建了三层 - 前两层具有 ReLU 激活函数,第三层具有 softmax 作为激活函数。

  • **Functional API:**这允许我们为层的非循环图形构建模型。使用 Functional API 可以创建更复杂的模型。


请注意,我们可以使用顺序和功能 API 来定义相同的神经网络。从性能的角度来看,使用哪种方法来定义模型并没有任何区别。

  1. 定义学习过程

在这一步中,我们定义了三件事:

  • 优化器
  • 损失函数
  • 将量化模型质量的指标:

请注意,我们使用model.compile函数来定义优化器、损失函数和指标。

  1. 训练模型

一旦定义了架构,就是训练模型的时候了:


请注意,batch_sizeepochs等参数是可配置的参数,使它们成为超参数。

选择顺序或功能模型

顺序模型将 ANN 创建为简单的层堆叠。顺序模型易于理解和实现,但其简单的架构也有一个主要限制。每一层只连接到一个输入和输出张量。这意味着如果我们的模型在任何隐藏层的输入或输出处有多个输入或多个输出,那么我们不能使用顺序模型。在这种情况下,我们将不得不使用功能模型。

理解 TensorFlow

TensorFlow 是处理神经网络的最流行的库之一。在前面的部分中,我们看到了如何将其用作 Keras 的后端引擎。它是一个开源的高性能库,实际上可以用于任何数值计算。如果我们看一下堆栈,我们可以看到我们可以用高级语言(如 Python 或 C++)编写 TensorFlow 代码,然后由 TensorFlow 分布式执行引擎解释。这使得它对开发人员非常有用和受欢迎。

TensorFlow 的工作方式是创建一个有向图DG)来表示您的计算。连接节点的是边,数学运算的输入和输出。它们也代表数据的数组。


每个程序员都应该知道的 40 个算法(三)(2)https://developer.aliyun.com/article/1506356

相关文章
|
2月前
|
负载均衡 监控 算法
每个程序员都应该知道的 6 种负载均衡算法
每个程序员都应该知道的 6 种负载均衡算法
230 2
|
3月前
|
算法 程序员 Python
程序员必看!Python复杂度分析全攻略,让你的算法设计既快又省内存!
在编程领域,Python以简洁的语法和强大的库支持成为众多程序员的首选语言。然而,性能优化仍是挑战。本文将带你深入了解Python算法的复杂度分析,从时间与空间复杂度入手,分享四大最佳实践:选择合适算法、优化实现、利用Python特性减少空间消耗及定期评估调整,助你写出高效且节省内存的代码,轻松应对各种编程挑战。
61 1
|
4月前
|
算法 搜索推荐 程序员
程序员常用算法详细讲解
每一种算法都有其适用场景,了解并熟悉这些常用算法的策略和实现,对于解决实际编程问题具有重要的意义。需要注意的是,理论知识的重要性虽然不言而喻,但真正的理解和掌握,还需要在实践中不断地尝试和错误,以达到深入理解的目的。
41 1
|
4月前
|
机器学习/深度学习 算法 搜索推荐
程序员必须掌握的算法
作为一名程序员,掌握一些重要的算法是必不可少的。算法是解决问题的方法和步骤,对于程序员来说,熟悉和掌握一些常见的算法可以提高编程能力,解决复杂的计算问题。与此同时,算法是计算机科学中的核心概念,对于程序员来说,掌握一些基本的算法是非常重要的。
53 1
|
6月前
|
算法 程序员
程序员必知:XGB算法梳理
程序员必知:XGB算法梳理
34 0
|
6月前
|
算法 JavaScript 程序员
程序员必知:《程序设计与算法(二)算法基础》《第一周枚举》熄灯问题POJ
程序员必知:《程序设计与算法(二)算法基础》《第一周枚举》熄灯问题POJ
36 0
|
7月前
|
机器学习/深度学习 人工智能 算法
每个程序员都应该知道的 40 个算法(四)(3)
每个程序员都应该知道的 40 个算法(四)
50 2
|
7月前
|
机器学习/深度学习 算法 数据挖掘
每个程序员都应该知道的 40 个算法(四)(4)
每个程序员都应该知道的 40 个算法(四)
51 1
|
7月前
|
NoSQL 算法 Java
【redis源码学习】持久化机制,java程序员面试算法宝典pdf
【redis源码学习】持久化机制,java程序员面试算法宝典pdf