《动手学深度学习(PyTorch版)》3、多层感知机
本帖最后由 xinmeng_wit 于 2024-10-14 22:11 编辑<p>本章来学习多层感知机。</p>
<p><span style="font-size:18px;"><strong>一、多层感知机</strong></span></p>
<p><span style="font-size:16px;"><strong>1、概念</strong></span></p>
<p>多层感知机(multilayer perceptron,MLP)是包含输入层、输出层和隐藏层的一种网络结构,节点连接采用全连接方式,如下:</p>
<div style="text-align: left;"></div>
<p>这个多层感知机有4个输入,3个输出,其隐藏层包含5个隐藏单元。 输入层不涉及任何计算,因此使用此网络产生输出只需要实现隐藏层和输出层的计算。 因此,这个多层感知机中的层数为2。 注意,这两个层都是全连接的。 每个输入都会影响隐藏层中的每个神经元, 而隐藏层中的每个神经元又会影响输出层中的每个神经元。</p>
<p>另外,为了让多层感知机能够表达非线性特性,在隐藏层的输出需要增加非线性激活函数(activation function)σ。激活函数的输出(例如,σ(⋅))被称为<em>活性值</em>(activations)。</p>
<p> 一般来说,有了激活函数,就不可能再将我们的多层感知机退化成线性模型了。</p>
<p> </p>
<p><span style="font-size:16px;"><strong>2、激活函数</strong></span></p>
<p><em>激活函数</em>(activation function)通过计算加权和并加上偏置来确定神经元是否应该被激活, 它们将输入信号转换为输出的可微运算。 大多数激活函数都是非线性的。 由于激活函数是深度学习的基础,下面简要介绍一些常见的激活函数。</p>
<p>1)ReLU函数</p>
<p>最受欢迎的激活函数是<em>修正线性单元</em>(Rectified linear unit,<em>ReLU</em>), 因为它实现简单,同时在各种预测任务中表现良好。 ReLU提供了一种非常简单的非线性变换。 给定元素x,ReLU函数被定义为该元素与0的最大值:</p>
<pre>
<code>ReLU(x) = max(x, 0)</code></pre>
<p>ReLU函数通过将相应的活性值设为0,仅保留正元素并丢弃所有负元素。</p>
<p>ReLU曲线如下:</p>
<div style="text-align: left;"></div>
<p>当输入为负时,ReLU函数的导数为0,而当输入为正时,ReLU函数的导数为1。 注意,当输入值精确等于0时,ReLU函数不可导。 在此时,我们默认使用左侧的导数,即当输入为0时导数为0。</p>
<p>使用ReLU的原因是,它求导表现得特别好:要么让参数消失,要么让参数通过。 这使得优化表现得更好,并且ReLU减轻了困扰以往神经网络的梯度消失问题.</p>
<p>注意,ReLU函数有许多变体,包括<em>参数化ReLU</em>(Parameterized ReLU,<em>pReLU</em>) 函数 。 该变体为ReLU添加了一个线性项,因此即使参数是负的,某些信息仍然可以通过:</p>
<pre>
<code>pReLU(x) = max( 0, x ) + a * min(0, x)</code></pre>
<p>2) sigmoid函数</p>
<p><em>sigmoid函数</em>将输入变换为区间(0, 1)上的输出。 因此,sigmoid通常称为<em>挤压函数</em>(squashing function): 它将范围(-inf, inf)中的任意输入压缩到区间(0, 1)中的某个值:</p>
<div style="text-align: left;"></div>
<div style="text-align: left;"></div>
<p>3)tanh函数</p>
<p>与sigmoid函数类似, tanh(双曲正切)函数也能将其输入压缩转换到区间(-1, 1)上。 tanh函数的公式如下:</p>
<div style="text-align: left;"></div>
<p>下面我们绘制tanh函数。 注意,当输入在0附近时,tanh函数接近线性变换。 函数的形状类似于sigmoid函数, 不同的是tanh函数关于坐标系原点中心对称。</p>
<div style="text-align: left;"></div>
<p> </p>
<p><span style="font-size:18px;"><strong>二、模型选择、欠拟合和过拟合</strong></span></p>
<p>将模型在训练数据上拟合的比在潜在分布中更接近的现象称为<em>过拟合</em>(overfitting), 用于对抗过拟合的技术称为<em>正则化</em>(regularization)。</p>
<p>为了进一步讨论这一现象,我们需要了解训练误差和泛化误差。 <em>训练误差</em>(training error)是指, 模型在训练数据集上计算得到的误差。 <em>泛化误差</em>(generalization error)是指, 模型应用在同样从原始样本的分布中抽取的无限多数据样本时,模型误差的期望。</p>
<p>问题是,我们永远不能准确地计算出泛化误差。 这是因为无限多的数据样本是一个虚构的对象。 在实际中,我们只能通过将模型应用于一个独立的测试集来估计泛化误差, 该测试集由随机选取的、未曾在训练集中出现的数据样本构成。</p>
<p><span style="font-size:16px;"><strong>1、模型选择</strong></span></p>
<p>在机器学习中,我们通常在评估几个候选模型后选择最终的模型。 这个过程叫做<em>模型选择</em>。 有时,需要进行比较的模型在本质上是完全不同的(比如,决策树与线性模型)。 又有时,我们需要比较不同的超参数设置下的同一类模型。</p>
<p><span style="font-size:16px;"><strong>2、K折交叉验证</strong></span></p>
<p>当训练数据稀缺时,我们甚至可能无法提供足够的数据来构成一个合适的验证集。 这个问题的一个流行的解决方案是采用K<em>折交叉验证</em>。 这里,原始训练数据被分成K个不重叠的子集。 然后执行K次模型训练和验证,每次在K−1个子集上进行训练, 并在剩余的一个子集(在该轮中没有用于训练的子集)上进行验证。 最后,通过对K次实验的结果取平均来估计训练和验证误差。</p>
<p><span style="font-size:16px;"><strong>3、欠拟合和过拟合</strong></span></p>
<p>当我们比较训练和验证误差时,我们要注意两种常见的情况。 首先,我们要注意这样的情况:训练误差和验证误差都很严重, 但它们之间仅有一点差距。 如果模型不能降低训练误差,这可能意味着模型过于简单(即表达能力不足), 无法捕获试图学习的模式。 此外,由于我们的训练和验证误差之间的<em>泛化误差</em>很小, 我们有理由相信可以用一个更复杂的模型降低训练误差。 这种现象被称为<em>欠拟合</em>(underfitting)。</p>
<p>另一方面,当我们的训练误差明显低于验证误差时要小心, 这表明严重的<em>过拟合</em>(overfitting)。 注意,<em>过拟合</em>并不总是一件坏事。 特别是在深度学习领域,众所周知, 最好的预测模型在训练数据上的表现往往比在保留(验证)数据上好得多。 最终,我们通常更关心验证误差,而不是训练误差和验证误差之间的差距。</p>
<div style="text-align: left;"></div>
<p> </p>
<p><span style="font-size:18px;"><strong>三、权重衰减</strong></span></p>
<p>前面我们描述了过拟合的问题,现在我们将介绍一些正则化模型的技术。 我们总是可以通过去收集更多的训练数据来缓解过拟合。 但这可能成本很高,耗时颇多,或者完全超出我们的控制,因而在短期内不可能做到。 假设我们已经拥有尽可能多的高质量数据,我们便可以将重点放在正则化技术上。</p>
<p>在训练参数化机器学习模型时, <em>权重衰减</em>(weight decay)是最广泛使用的正则化的技术之一, 它通常也被称为L2<em>正则化</em>。 这项技术通过函数与零的距离来衡量函数的复杂度, 因为在所有函数f中,函数f=0(所有输入都得到值0) 在某种意义上是最简单的。</p>
<p> </p>
<p><span style="font-size:18px;"><strong>四、暂退法(Dropout)</strong></span></p>
<p>在2014年,斯里瓦斯塔瓦等人 (<a href="https://zh-v2.d2l.ai/chapter_references/zreferences.html#id155" title="Srivastava, N., Hinton, G., Krizhevsky, A., Sutskever, I., & Salakhutdinov, R. (2014). Dropout: a simple way to prevent neural networks from overfitting. The Journal of Machine Learning Research, 15(1), 1929–1958.">Srivastava <em>et al.</em>, 2014</a>) 就如何将毕晓普的想法应用于网络的内部层提出了一个想法: 在训练过程中,他们建议在计算后续层之前向网络的每一层注入噪声。 因为当训练一个有多层的深层网络时,注入噪声只会在输入-输出映射上增强平滑性。</p>
<p>这个想法被称为<em>暂退法</em>(dropout)。 暂退法在前向传播过程中,计算每一内部层的同时注入噪声,这已经成为训练神经网络的常用技术。 这种方法之所以被称为<em>暂退法</em>,因为我们从表面上看是在训练过程中丢弃(drop out)一些神经元。 在整个训练过程的每一次迭代中,标准暂退法包括在计算下一层之前将当前层中的一些节点置零。</p>
<p> </p>
<p><span style="font-size:18px;"><strong>五、前向传播和反向传播</strong></span></p>
<p><em>前向传播</em>(forward propagation或forward pass) 指的是:按顺序(从输入层到输出层)计算和存储神经网络中每层的结果。</p>
<div style="text-align: left;"></div>
<p><em>反向传播</em>(backward propagation或backpropagation)指的是计算神经网络参数梯度的方法。 简言之,该方法根据微积分中的<em>链式规则</em>,按相反的顺序从输出层到输入层遍历网络。 该算法存储了计算某些参数梯度时所需的任何中间变量(偏导数)。 假设我们有函数Y=f(X)和Z=g(Y), 其中输入和输出X,Y,Z是任意形状的张量。 利用链式法则,我们可以计算Z关于X的导数:</p>
<div style="text-align: left;"></div>
<p>在这里,我们使用prod运算符在执行必要的操作(如换位和交换输入位置)后将其参数相乘。 对于向量,这很简单,它只是矩阵-矩阵乘法。 对于高维张量,我们使用适当的对应项。 运算符prod指代了所有的这些符号。</p>
<p>反向传播的过程如下:</p>
<p>第一步是计算目标函数J=L+s相对于损失项L和正则项s的梯度。</p>
<div style="text-align: left;"></div>
<p> </p>
<p>在训练神经网络时,前向传播和反向传播相互依赖。 对于前向传播,我们沿着依赖的方向遍历计算图并计算其路径上的所有变量。 然后将这些用于反向传播,其中计算顺序与计算图的相反。</p>
<p>因此,在训练神经网络时,在初始化模型参数后, 我们交替使用前向传播和反向传播,利用反向传播给出的梯度来更新模型参数。 注意,反向传播重复利用前向传播中存储的中间值,以避免重复计算。 带来的影响之一是我们需要保留中间值,直到反向传播完成。 这也是训练比单纯的预测需要更多的内存(显存)的原因之一。 此外,这些中间值的大小与网络层的数量和批量的大小大致成正比。 因此,使用更大的批量来训练更深层次的网络更容易导致<em>内存不足</em>(out of memory)错误。</p>
<p> </p>
<p>加油wit。。。。。。。。。。。不要停更哟。。。。。。。。。。。<img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/loveliness.gif" width="48" /><img height="63" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/victory.gif" width="61" /></p>
<p>谢谢分享,期待后续深度评测</p>
hellokitty_bean 发表于 2024-10-17 10:54
加油wit。。。。。。。。。。。不要停更哟。。。。。。。。。。。
<p>感谢,不会停更的</p>
页:
[1]