深度学习和神经网络导论(深度学习笔记-1)

Vivian
2周前 阅读 235 点赞 2

从分类图像和翻译语言到建造自动驾驶汽车,所有这些任务都是由计算机驱动而非人工。深度学习已经渗透到各行各业中,并持续开疆拓土。

越来越多的人对深度学习感兴趣。但是你应该从哪里开始呢?该学习什么?究竟是什么构成了这个复杂而又有趣的领域的核心概念?

我很高兴能写下一系列文章,我将详细介绍每个爱好者都应该彻底了解的深度学习的基本组成部分。我的灵感来自于deeplearning.ai,它发布了一门很棒的对我的学习之旅非常有帮助的深度学习专业课程。

在这篇文章中,我将介绍的是Andrew Ng教授解释的神经网络的基础知识以及如何实现它们。

注意:我们将在本系列中遵循自下而上的方法——我们将首先从基础开始理解概念,然后才遵循其实现。这种方法已经证明对我很有帮助。

目录表

1. 理解课程结构

2.课程1:神经网络与深度学习

2.1 深度学习导论

2.2 神经网络基础

2.2.1 神经网络的Logistic回归

2.2.2 Python与矢量化

2.3 浅层神经网络

2.4 深度神经网络

1.理解课程结构

本系列文章一共有5节课程,今天是第一节,本节重点分为4个子模块:

  1. 第一部分简要介绍了深度学习和神经网络。
  2. 第二部分,我们深入研究了神经网络的基本原理。Andrew Ng解释了如何利用神经网络求解逻辑回归问题。
  3. 第三部分讨论浅层神经网络,简要介绍激活函数、梯度下降和前后向传播。
  4. 最后,Andrew Ng教授了最令人期待的主题——深度神经网络。


2. 神经网络与深度学习

既然我们有了这篇文章的结构,是时候从零开始学习了。

2.1 深度学习导论

这部分的目标如下:

  1. 理解推动深度学习兴起的主要趋势
  2. 能够解释如何深度学习如何被应用于有监督的学习
  3. 了解神经网络的主要类别(如CNNs和RNNs),以及何时应用它们
  4. 能够认识到什么时候深度学习(或将不会)有效

2.1.1 什么是神经网络?

举个例子,我们必须预测房子的价格。我们给出的变量是房子的面积平方英尺(或平方米)和房子的价格。现在假设我们有6栋房子。所以首先用图形可视化我们所看到的:

在X轴上,我们有房子的大小,在Y轴上有相应的价格。线性回归模型将尝试绘制直线拟合数据:

因此,这里的输入(x)是房子的大小,输出(y)是价格。现在让我们来看看我们如何用简单的神经网络来解决这个问题:

这里,神经元将输入一个输入,应用一些激活函数,并产生一个输出。最常用的激活函数之一是ReLU(Rectified Linear Unit,整流线性单元):

ReLU取实数作为输入,并返回最大值0或该数。比如,如果我们输入的是10,输出将是10;如果输入是-10,输出将是0。稍后我们将详细讨论激活函数。

如果我们根据房子大小并使用ReLU激活函数来预测一个房子的价格,这就是我们可能看到的预测结果。

到目前为止,我们已经看到了一个具有单个神经元的神经网络,即,我们只有一个特征(房子的大小)来预测房价。但在现实中,我们必须考虑多个特征,如卧室数量,邮政编码等。房价也可以取决于家庭人口数量、周边地区或学校的质量。在这种情况下,我们如何定义神经网络?

我们输入4个特征作xx ,它自动地从输入中识别出一些隐藏的特征,并最终生成输出yy 。以下是一个“具有4个输入并输出具有单个隐藏层的神经网络”的样子:

现在我们已经了解了神经网络,下面看看如何将它们用于有监督的学习问题。

基于神经网络的监督学习

监督学习指的是我们需要找到能够将输入映射到相应输出(给定一组输入-输出)的函数的任务。对于每个给定的输入都有一个明确的输出,我们用这些例子训练模型。下面是一个相当方便的表格,它介绍了监督学习的不同应用以及可用于解决这些问题的不同类型的神经网络:

下面是最常见的神经网络类型的可视化表示:

在这篇文章中,我们将重点放在标准神经网络(Standard NN)上。

监督学习可用于结构化数据和非结构化数据。

在我们的房价预测案例中,给定的数据为卧室的大小和数量。这是结构化数据,意味着每个特征,如房子的大小,卧室的数量等,都有非常明确的含义。

相比之下,非结构化数据指的是诸如音频、原始音频或图像之类的东西,您可能想要从中识别图像或文本中的内容(比如对象检测)。这里,特征可能是图像中的像素值,或者是文本中的单个单词。目前还不清楚图像的每个像素代表什么,因此这属于非结构化数据。

简单的机器学习算法可以很好地处理结构化数据。但当涉及到非结构化数据时,它们的性能往往会下降很多。这就是神经网络被证明是如此有效和有用的地方。它们在非结构化数据上执行得非常出色。目前大多数突破性研究都以神经网络为核心。

为什么深度学习会流行?

随着数据量的增加,传统的学习算法如支持向量机和logistic回归,其性能并没有得到很大的提高。事实上,它在某一点之后趋于稳定。对神经网络而言,模型的性能随着数据的增加而增加。

基本上有三个尺度驱动一个典型的深度学习过程:

  1. 数据
  2. 计算时间
  3. 算法

为了提高模型的计算时间,激活函数起着重要的作用。如果我们使用Sigmoid激活函数,结果如下图:

这个函数的斜率或极值的梯度在极值处接近于零。因此,参数非常缓慢地更新,导致学习非常缓慢。因此,从sigmoid激活函数转换到ReLU(整流线性单元)是我们在神经网络中看到的最大突破之一。,当x>0时斜率为1,此时Relu更新参数快得多。这是模型快速计算的主要原因。

2.2 深度学习导论

本小结目标如下:

  1. 构造一个基于浅层神经网络的Logistic回归模型
  2. 实现ML算法的主要步骤,包括预测、导数计算和梯度下降。
  3. 实现计算效率和高度矢量化的模型版本
  4. 了解如何使用反向传播思想计算Logistic回归的导数
  5. 熟悉Python和Numpy

该小结进一步分为两部分:

  1. 逻辑回归作为神经网络
  2. Python和矢量化

2.2.1 神经网络中的Logistic回归

二进制分类

在二元分类问题中,我们有一个输入xx ,比如说一个图像,我们必须把它分类为有猫或没有猫。如果它是一只猫,我们会给它分配一个1,不是就分配0。在这里,我们只有两个输出——要么图像包含猫,要么不包含猫。这是二进制分类问题的一个例子。

在这种情况下,我们当然可以使用最流行的分类技术,Logistic回归。

逻辑回归(Logistic Regression)

我们有一个输入X(图像),我们想知道图像属于第1类(即猫)的概率。对于给定的X向量,输出将是:

y = w(transpose)X + b

这里w和b是参数。输出y是概率,它应该在0到1之间。但是在上面的等式中,它可以取任何实际的值,这对于获得概率是没有意义的。因此Logistic回归也使用Sigmoid函数来输出概率:

对于任何值作为输入,它只返回0到1范围内的值。Sigmoid函数的公式是:

因此,如果z非常大,exp(-z)将接近0,因此Sigmoid的输出将是1。同样,如果z很小,exp(-z)将是无穷大的,因此S形的输出将是0。

注意,参数w是nx维向量,b是实数。现在让我们看看Logistic回归的成本函数。

Logistic回归损失函数

为了训练Logistic回归的参数w和b,我们需要一个损失函数。我们希望找到参数w和b,这样至少在训练集中,您所具有的输出(y-hat)接近实际值(y)。

我们可以使用下面定义的损失函数:

这个问题的问题是,优化问题变得非凸,导致多个局部最优。因此,梯度下降将不能很好地作用于此损失函数。因此,对于logistic回归,我们定义了与上述损失函数具有相似作用的不同的损失函数,并且还通过给出凸函数来解决优化问题:

损失函数是针对单个训练实例定义的,它告诉我们在特定示例中我们做得有多好。另一方面,成本函数是针对整个训练集的。Logistic回归的损失函数为:

我们希望损失函数尽可能小。为此,我们希参数w和b被优化。

梯度下降

梯度下降能找到参数w和b使得损失函数最小化。Logistic回归的损失函数本质上是凸的(即只有一个全局最小值),这也是选择该函数而不是平方误差(可以有多个局部最小值)的原因。

以下是梯度下降的步骤:

  1. 初始化w和b(通常Logistic回归初始化为0)
  2. 在最陡峭的下坡方向上迈出一步
  3. 重复步骤2直到达到全局最优

梯度下降的更新方程变为:

这里,学习速率α\alpha 控制每一次迭代后我们应该采取多大的步骤。

如果我们在图的右边,斜率将是正的。使用更新的方程后我们将移动到左侧(即向下方向),直到达到全局最小值。然而,如果我们在左侧,斜率将是负的,因此我们将向右(向下方向)迈出一步,直到达到全局最小值。

Logistic回归参数的更新方程为:

导数

考虑函数,f(a)=3a,如下所示:

该函数在任何点的导数将给出该点的斜率。所以,

f(a=2)=3*2=6

f(a=2.001)=3*2.001=6.003

在a=2的函数的斜率/导数是:

斜率=0.003/0.001=3

这就是我们如何计算函数的导数/斜率。让我们再来看看几个衍生工具的例子。

更多衍生实例

考虑下面的3个函数及其对应的导数:

在上述所有例子中,导数是a的函数,这意味着函数的斜率在不同点不同。

计算图(Computation Graph)

这些图组织了特定函数的计算。考虑下面的例子:

J(a,b,c)=3(a+bC)

我们必须用给定a、b和c计算出J,我们可以把它分成三个步骤:

让我们将这些步骤可视化为a=5,b=3,c=2:

这是我们计算输出的前向传播步骤,即J。我们还可以使用计算图进行反向传播,在上面的例子中我们更新了参数a、b和c。

具有计算图的导数

现在让我们看看如何借助计算图来计算导数。假设我们必须计算dJ/da。步骤如下:

1.因为J是v的函数,所以计算dJ/dv: dJ/dv= d(3v)/dv=3

2.由于v是a和u的函数,所以计算dv/da: dv/da= d(a+u)/da=1

3.计算dJ/da: dJ/da=(dJ/dv)*(dv/da)=3*1=3

类似地,我们可以计算dJ/db和dJ/dc:

现在我们将结合计算图和梯度下降的概念,来看看如何更新逻辑回归的参数。

Logistic回归梯度下降

Logistic回归方程为:

其中L是损失函数。现在,对于两个特征(x1和x2),计算损失的计算图将是:

这里,w1、w2和b是需要更新的参数。步骤如下(对于w1):

1.计算da:da= dL/da=(-y/a)+(1-y)/(1-a)

2.计算dz:dz=(dL/da)*(da/dz)=[(-y/a)+(1-y)/(1-a)] *[a(1-a)]=a- y

3.计算dw1:dw1= [(dL/da)*(da/dz)] *dz/dw1=(a-y)*da/dw1

同样,我们可以计算dw2和db。最后,使用下面的公式更新权重:

请记住,这是一个单一的训练例子。我们将在真实场景中有多个示例。因此,让我们来看看如何为"m"训练实例计算梯度下降。

“m”实例的梯度下降

我们可以定义"m”训练示例的预测和损失函数:

损失函数w.r.t的导数可以写成:

现在让我们看看我们如何应用“m”实例的逻辑回归:

J = 0; dw1 = 0; dw2 =0; db = 0;                
w1 = 0; w2 = 0; b=0;                            
for i = 1 to m
    # Forward pass
    z(i) = W1*x1(i) + W2*x2(i) + b
    a(i) = Sigmoid(z(i))
    J += (Y(i)*log(a(i)) + (1-Y(i))*log(1-a(i)))
    
    # Backward pass
    dz(i) = a(i) - Y(i)
    dw1 += dz(i) * x1(i)
    dw2 += dz(i) * x2(i)
    db  += dz(i)
J /= m
dw1/= m
dw2/= m
db/= m

# Gradient descent
w1 = w1 - alpa * dw1
w2 = w2 - alpa * dw2
b = b - alpa * db

这些for循环最终使得计算非常缓慢。为了使代码更高效,有一种方法可以替换这些循环。我们将在接下来的章节中看这些技巧。

2.2.2 Python和矢量化

到目前为止,我们已经看到了如何使用梯度下降来更新Logistic回归的参数。在上面的例子中,我们看到,如果我们有“m”训练示例,我们必须运行循环“m”多次以获得输出,这使得计算非常慢。

我们可以使用矢量化代替这些循环,这是一种有效的和时间有效的方法。

矢量化

在我们的代码中,矢量化基本上是一种去循环的方法。它执行所有的操作一起用于“m”训练实例,而不是单独计算它们。让我们看看逻辑回归的非矢量化和向量化表示:

非矢量化形式:

z = 0
for i in range(nx):
   z += w[i] * x[i]
z +=b

现在,让我们来看看向量化的形式。我们可以用向量形式表示w和x:

现在我们可以使用所有的训练例子计算Z:

Numpy库的dot 函数默认采用矢量化。这就是我们如何矢量化乘法。现在来看看如何矢量化整个逻辑回归算法。

矢量化Logistic回归

与“m”训练示例保持一致,第一步是计算所有这些示例的Z:

这里,X包含所有训练实例的特征,而W是这些示例的系数矩阵。下一步是计算输出(A),它是Z的Sigmoid函数:

现在,计算损失,然后使用反向传播来最小化损失:

dz=A-y

最后,我们将计算参数的导数并更新它们:

Python中的广播机制(Broadcating)

广播机制使代码的某些部分效率更高。来看一些例子:

  1. obj.sum(轴=0)对列求和,而obj.sum(轴=1)与行相加。
  2. obj.reshape(1,4)通过广播值来改变矩阵的形状

如果我们将100增加到(4×1)矩阵,它将复制100到(4×1)矩阵。类似地,在下面的例子中,(1×3)矩阵将被复制以形成(2×3)矩阵:

一般原则是:

如果我们将(m,n)矩阵加、减、乘或除以(1,n)矩阵,这将复制m次到(m,n)矩阵中。这叫做广播机制,它使计算速度更快。

关于Python/Numpy向量的一个注记

如果使用以下格式形成数组:

a = np.random.randn(5)

它将创建一个形状数组(5),这是一个秩1数组。使用这个数组会导致数组转置时出现问题。相反,我们可以使用下面的代码来形成向量,而不是秩1数组:

为了将(1,5)行向量转换为(5,1)列向量,可以使用:

2.3 浅层神经网络

目标:

  1. 了解隐藏单元和隐藏层
  2. 能够在神经网络中应用多种激活函数。
  3. 用隐层构建第一个前向/反向传播
  4. 将随机初始化应用于神经网络
  5. 熟悉深度学习符号和神经网络表示
  6. 一层隐层神经网络的构建与训练

2.3.1 神经网络综述

在Logistic回归中,为了计算输出(y= a),我们使用下面的计算图:

在具有单个隐藏层的神经网络的情况下,该结构将看起来像:

计算输出的计算图为:

X1  \ 
X2   => z1 = XW1 + B1 => a1 = Sigmoid(z1) => z2 = a1W2 + B2 => a2 = Sigmoid(z2) => l(a2,Y)
X3  /

神经网络表示

考虑下面的神经网络表示:

你能识别上述神经网络中的层数吗?记住,在计算神经网络中的层数时,我们不计算输入层。因此,在上述神经网络中有2个层,即一个隐含层和一个输出层。

第一层被称为,第二层为,最后层为。这里的a代表激活(神经网络的不同层传递到下一层的值)。相应的参数是

这就是神经网络的表示方式。接下来,我们将讨论如何计算神经网络的输出。

计算神经网络的输出

让我们详细地看看神经网络的每个神经元是如何工作的。每个神经元取一个输入,对它们执行一些运算(计算),然后应用Sigmoid函数:

这个步骤是由每个神经元执行的。具有四个神经元的第一隐层的方程将是:

因此,对于给定的输入X,每个神经元的输出将是:

为了计算这些输出,我们需要运行一个for循环,它将为每个神经元单独计算这些值。但是请记住,使用for循环会使计算非常慢,因此我们应该优化代码来消除这个for循环并更快地运行它。

多个实例的矢量化

计算神经网络输出的非矢量化形式是:

使用这个for循环,我们分别计算z和每个训练示例的值。现在我们来看看它是如何被矢量化的。所有的训练实例将合并在一个矩阵X中:

这里,nx是特征的数目,m是训练实例的数目。计算输出的向量化形式将是:

这将减少计算时间(在大多数情况下显著)。

激活函数

在计算输出时,可以应用激活函数。激活函数的选择高度影响模型的性能。到目前为止,我们已经使用了Sigmoid激活函数:

然而,在某些情况下,这可能不是最好的选择。为什么?因为在图的极端,导数将接近于零,因此梯度下降将非常缓慢地更新参数。

还有其他功能可以代替这种激活功能:

tanh:

ReLU:


激活函数

根据我们试图解决的问题,我们可以选择不同的激活函数。

为什么我们需要非线性激活函数?

如果我们对层的输出使用线性激活函数,它将计算输出作为输入特征的线性函数。我们首先计算Z值为:

Z= WX+b

在线性激活函数的情况下,输出将等于Z(而不是计算任何非线性激活):

A=Z

使用线性激活本质上是毫无意义的。两个线性函数的组合本身就是一个线性函数,除非我们使用一些非线性激活,否则我们就不能计算更有趣的函数。这就是为什么大多数专家坚持使用非线性激活函数。

只有一种情况下,我们倾向于使用线性激活函数。假设我们想要预测一所房子的价格(它可以是任何正数)。如果我们使用Sigmoid或Tanh函数,输出将分别为(0,1)和(-1,1)。但价格也会超过1。在这种情况下,我们将在输出层使用线性激活函数。

一旦我们有了输出,下一步是什么?我们想要执行反向传播,以便使用梯度下降来更新参数。

神经网络的梯度下降法

我们必须在二层神经网络中更新的参数是:w[1]、b[1]、w[2]和b[2],并且我们将要最小化的损失函数是:

梯度下降步骤可以概括为:

让我们快速地研究两层神经网络的前向和反向传播步骤。

前向传播:

反向传播:

这些是神经网络完成输出的完整步骤。注意,我们必须初始化权重(W)在开始,然后在反向传播步骤中更新。让我们看看这些权值应该如何初始化。

随机初始化

我们以前已经看到,在Logistic回归算法的情况下,权重被初始化为0。但是我们应该将神经网络的权值初始化为0吗?这是一个很好的问题。让我们考虑下面的例子:

如果权值被初始化为0,则W矩阵将是:

使用这些权重:

最后在反向传播步骤:

不管我们在一层中使用多少单位,我们总是得到相同的输出,这与使用单个单位的输出类似。因此,不是将权重初始化为0,而是使用以下代码随机初始化它们:

我们将权重乘以0.01以初始化小的权重。如果我们初始化较大的权重,激活将会很大,导致零斜率(在sigmoid和tanh激活函数的情况下)。因此,学习将是缓慢的。因此,我们通常随机初始化小权值。

2.4 深度神经网络

终于到了学习深度神经网络的时候了!这些已经成为当今行业和研究领域的热门话题。无论我最近选了哪篇研究论文,都不可避免地提到如何使用深度神经网络来推动研究背后的思维过程。

我们最终目标是:

  1. 将深度神经网络视为相继的块
  2. 构建和训练深度L层神经网络
  3. 分析矩阵和向量维数以检查神经网络实现
  4. 了解如何使用缓存将信息从前向传播传递到反向传播
  5. 理解超参数在深度学习中的作用

深L层神经网络

在这一节中,我们将研究如何将正向和反向传播的概念应用于深度神经网络。但你可能想知道,在这一点上,深度神经网络究竟是什么?

浅与深是程度的问题。Logistic回归是一个非常浅的模型,因为它只有一层(记住我们不把输入作为一个层来计算):

更深层次的神经网络有更多的隐藏层:

让我们来看看一些与深度神经网络相关的符号:

  • L是神经网络中的层数
  • 是L层中的单位数
  • 是L层中的激活
  • 的权重

这些是我们将在即将到来的章节中使用的一些符号。当我们继续的时候,记住它们,或者快速地跳回来,以防你错过什么。

深度神经网络中的前向传播

对于单个训练示例,前向传播步骤可以写成:

我们可以将这些步骤向量化为m’训练示例,如下所示:

上一层输出作为下一层的输入。在没有for循环的情况下,我们不能计算神经网络的所有层的前向传播,所以这里最好有一个for循环。在继续之前,让我们看一下各种矩阵的维度,它们将帮助我们以更好的方式理解这些步骤。

获得正确矩阵尺寸

分析矩阵的维数是检查我们的代码有多正确的最佳调试工具之一。我们将讨论在这一节中每个矩阵应该是什么尺寸。参照下面的例子:

你能算出这个神经网络中的层数(L)吗?如果你猜5,你是正确的。有4个隐藏层和1个输出层。每一层的单位是:

W,b及其导数的维数的广义形式是:

其中m是训练实例的数量。这些是一些广义矩阵维数,它们将帮助您顺利地运行代码。

到目前为止,我们已经看到了一些深层神经网络的基础知识。但是为什么我们首先需要深切的表达呢?为什么当容易解决的时候事情变得复杂?让我们找出答案!

为什么要Deep Representation?

在深度神经网络中,我们有大量的隐含层。这些隐藏的层实际上在做什么?要理解这一点,请考虑下面的图像:

深度神经网络发现与数据的关系(简单到复杂的关系)。第一个隐藏层可能正在做的是试图找到简单的函数,如识别上面图像中的边缘。随着我们深入网络,这些简单的功能结合在一起,形成更复杂的功能,如识别人脸。利用深度神经网络的一些常见例子是:


  • 人脸识别

图像==>边==面部分==面==>期望面

  • 音频识别

音频= =低电平声音特征(sss,bb)=>音素==单词==>句子

深层神经网络的构造

考虑深度神经网络中的任何层。该层的输入将是来自前一层(l-1)的激活,该层的输出将是其自身的激活。

该层首先计算应用激活的z[l]。这个被保存为缓存。对于反向传播步骤,它将首先计算,即层l处激活的导数、权重的导数,最后计算。让我们将这些步骤可视化,以减少复杂性:

这就是深度神经网络的每个块(层)是如何工作的。接下来,我们将了解如何实现所有这些块。

前向传播和反向传播

前向传播步骤中的输入是,输出是和缓存,它是的函数。因此,计算的向量化形式是:

我们将计算Z和A的每一层的网络。在计算激活之后,下一步是反向传播,在这里我们使用导数来更新权重。反向传播的输入是,输出是。让我们来看看反向传播的矢量化方程:

这就是我们如何实现深度神经网络。

深度神经网络表现出奇的好(如果你以前使用过的话,也许不那么令人惊讶!),只运行几行代码给我们带来满意的结果。这是因为我们正在向网络馈送大量数据,并且它正在使用隐藏层从该数据中学习。

选择正确的超参数有助于我们的模型更有效。我们将在本系列的下一篇文章中详细介绍超参数调谐的细节。

参数与超参数

这是一个经常被问到的问题。参数与超参数之间的主要区别在于参数是在训练过程中通过模型学习的,而超参数可以在训练模型之前改变。

深度神经网络的参数是W和b,模型在反向传播步骤中更新。另一方面,深度神经网络有很多超参数,包括:

  • 学习速率α\alpha
  • 迭代次数
  • 隐含层数
  • 每个隐藏层中的单元
  • 激活函数的选择

这是对这两个方面的差异的简要概述。我很乐意回答你的任何问题,在下面的评论部分。

小结

恭喜完成第一门课!我们现在知道如何实现前向和反向传播和梯度下降的深度神经网络。我们还看到向量化如何帮助我们摆脱显式的循环,使我们的代码在这个过程中高效。

在下一篇文章(课程2)中,我们将看到如何通过超参数调整、正则化和优化来改进深度神经网络。这是深度学习中更为棘手和引人入胜的方面之一。

原文链接:An Introductory Guide to Deep Learning and Neural Networks (Notes from deeplearning.ai Course #1)

翻译:Vivian


| 2
登录后可评论,马上登录吧~
评论 ( 0 )

还没有人评论...