【深度学习】2、Pytorch自行实现常见的11个激活函数的Fashion Minist项目实践对比(你需要的这里都有了!)(一)

简介: 【深度学习】2、Pytorch自行实现常见的11个激活函数的Fashion Minist项目实践对比(你需要的这里都有了!)(一)

简介


神经网络为什么需要激活函数:首先数据的分布绝大多数是非线性的,而一般神经网络的计算是线性的,引入激活函数,是在神经网络中引入非线性,强化网络的学习能力。所以激活函数的最大特点就是非线性。


   激活函数对神经网络的重要性自不必多言,来自丹麦技术大学的 Casper Hansen 通过公式、图表和代码实验介绍了 Sigmoid、Tanh、ReLU、Softplus、Softmax、ELU 以及更新的 Leaky ReLU、SELU、GELU、Maxout 以及Swish这些激活函数,并比较了它们的优势和短板。


   在计算每一层的激活值时,我们要用到激活函数,之后才能确定这些激活值究竟是多少。根据每一层前面的激活、权重和偏置,我们要为下一层的每个激活计算一个值。但在将该值发送给下一层之前,我们要使用一个激活函数对这个输出进行缩放。本文将介绍不同的激活函数。


1、概述


   激活函数是神经网络中一个至关重要的部分。在这篇长文中,我将全面介绍11种不同的激活函数,并阐述它们各自的优缺点。我会给出激活函数的方程和微分方程,还会给出它们的图示。本文的目标是以简单的术语解释这些方程以及图。


2、Sigmoid 函数


   Sigmoid 函数是一个Logistic函数,意思就是说:不管输入是什么,得到的输出都在0到1之间。也就是说,你输入的每个神经元、节点或激活都会被缩放为一个介于 0到1之间的值。

   sigmoid 这样的函数常被称为非线性函数,因为我们不能用线性的项来描述它。很多激活函数都是非线性或者线性和非线性的组合(有可能函数的一部分是线性的,但这种情况很少见)。


   这基本上没什么问题,但值恰好为 0 或 1 的时候除外(有时候确实会发生这种情况)。为什么这会有问题?


   这个问题与反向传播有关(有关反向传播的介绍请参阅我的前一篇文章)。在反向传播中,我们要计算每个权重的梯度,即针对每个权重的小更新。这样做的目的是优化整个网络中激活值的输出,使其能在输出层得到更好的结果,进而实现对成本函数的优化。


   在反向传播过程中,我们必须计算每个权重影响成本函数(cost function)的比例,具体做法是计算成本函数相对于每个权重的偏导数。假设我们不定义单个的权重,而是将最后一层 L 中的所有权重 w 定义为 w^L,则它们的导数为:

83b586af8f35c4f0ed67b587d66591c3.png

   注意,当求偏导数时,我们要找到 ∂a^L 的方程,然后仅微分 ∂z^L,其余部分保持不变。我们用撇号「'」来表示任意函数的导数。当计算中间项 ∂a^L/∂z^L 的偏导数时,我们有:

08d6998f52f4632710aa78bc8fe42547.png

   则sigmoid 函数的导数就为:

2699db00b728660c01151b39f3f1f907.png

   当我们向这个 sigmoid 函数输入一个很大的x值(正或负)时,我们得到几乎为 0 的y值——也就是说,当我们输入 w×a+b 时,我们可能得到一个接近于 0 的值。


   当 x 是一个很大的值(正或负)时,我们本质上就是用一个几乎为0的值来乘这个偏导数的其余部分。

13666f328a4a0792c511563c7102b5de.png

   如果有太多的权重都有这样很大的值,那么我们根本就没法得到可以调整权重的网络,这可是个大问题。如果我们不调整这些权重,那么网络就只有细微的更新,这样算法就不能随时间给网络带来多少改善。对于针对一个权重的偏导数的每个计算,我们都将其放入一个梯度向量中,而且我们将使用这个梯度向量来更新神经网络。可以想象,如果该梯度向量的所有值都接近 0,那么我们根本就无法真正更新任何东西。

a1648e315ca0df47a3e6ba712b7beb0a.png

   这里描述的就是梯度消失问题。这个问题使得 sigmoid 函数在神经网络中并不实用,我们应该使用后面介绍的其它激活函数。


Sigmoid函数的自定义实现

b90f1c4e90221048a11b74d8ccad563a.png


3、Tanh函数


   tanh为双曲正切函数,其英文读作Hyperbolic Tangent。tanh和 sigmoid 相似,都属于饱和激活函数,区别在于输出值范围由 (0,1) 变为了 (-1,1),可以把 tanh 函数看做是 sigmoid 向下平移和拉伸后的结果。

tanh公式:

c9ca2666053525d0be994c2f69a13c26.png

   从公式中,可以更加清晰看出tanh与sigmoid函数的关系(平移+拉伸)。tanh及其导数曲线:

a18f202cb4fadfc86e29bd14c3593f48.jpg

tanh作为激活函数的特点:

相比Sigmoid函数,

   1、tanh的输出范围时(-1, 1),解决了Sigmoid函数的不是zero-centered输出问题;

   2、幂运算的问题仍然存在;

   3、tanh导数范围在(0, 1)之间,相比sigmoid的(0, 0.25),梯度消失(gradient vanishing)问题会得到缓解,但仍然还会存在。

自定义实现:

b25e6534ce43ed17397424671a907ab7.png


4、梯度问题


4.1、梯度消失问题

更新特定的权重,则更新规则为:

298ad8347485a500e15ae7d2701a441f.png

   但如果偏导数 ∂C/∂w^(L) 很小,如同消失了一般,又该如何呢?这时我们就遇到了梯度消失问题,其中许多权重和偏置只能收到非常小的更新。

   可以看到,如果权重的值为 0.2,则当出现梯度消失问题时,这个值基本不会变化。因为这个权重分别连接了第一层和第二层的首个神经元:

   假设这个权重的值为 0.2,给定一个学习率(具体多少不重要,这里使用了 0.5),则新的权重为:

   这个权重原来的值为 0.2,现在更新为了 0.199999978。很明显,这是有问题的:梯度很小,如同消失了一样,使得神经网络中的权重几乎没有更新。这会导致网络中的节点离其最优值相去甚远。这个问题会严重妨碍神经网络的学习。


人们已经观察到,如果不同层的学习速度不同,那么这个问题还会变得更加严重。层以不同的速度学习,前面几层总是会根据学习率而变得更差。

   在这个示例中,隐藏层 4 的学习速度最快,因为其成本函数仅取决于连接到隐藏层 4 的权重变化。我们看看隐藏层 1;这里的成本函数取决于连接隐藏层 1 与隐藏层 2、3、4 的权重变化。如果你看过了我前一篇文章中关于反向传播的内容,那么你可能知道网络中更前面的层会复用后面层的计算。

同时,如前面介绍的那样,最后一层仅取决于计算偏导时出现的一组变化:

350d227b20222d3730af81546ec857c8.png

   最终,这就是个大问题了,因为现在权重层的学习速度不同。这意味着网络中更后面的层几乎肯定会被网络中更前面的层受到更多优化。而且问题还在于反向传播算法不知道应该向哪个方向传递权重来优化成本函数。


4.2、梯度爆炸问题

   梯度爆炸问题本质上就是梯度消失问题的反面。研究表明,这样的问题是可能出现的,这时权重处于「爆炸」状态,即它们的值快速增长。


我们将遵照以下示例来进行说明:http://neuralnetworksanddeeplearning.com/chap5.html#what's_causing_the_vanishing_gradient_problem_unstable_gradients_in_deep_neural_nets


   注意,这个示例也可用于展示梯度消失问题,而我是从更概念的角度选择了它,以便更轻松地解释。


   本质上讲,当 01 时,我们可能遇到梯度爆炸问题。但是,当一个层遇到这个问题时,必然有更多权重满足梯度消失或爆炸的条件。


   我们从一个简单网络开始。这个网络有少量权重、偏置和激活,而且每一层也只有一个节点。

5a370ee769400b2d51e96468288c13d9.png

   这个网络很简单。权重表示为 w_j,偏置为 b_j,成本函数为 C。节点、神经元或激活表示为圆圈。


   Nielsen 使用了物理学上的常用表示方式 Δ 来描述某个值中的变化(这不同于梯度符号 ∇)。举个例子,Δb_j 描述的是第 j 个偏置的值变化。

4b155ea55e890c678e47cd6ba57daea6.png

通过下式衡量变化率:

2565b6e214ecf884377f6c98ff95f574.png

   下面式子的论据和上面的偏导一样。即我们如何通过偏置的变化率来衡量成本函数的变化率?正如刚才介绍的那样,Nielsen 使用Δ来描述变化,因此我们可以说这个偏导能大致通过Δ来替代:

95a5dbad011b3641623dba2cf161a8db.png

   先从网络的起点开始,计算第一个偏置 b_1 中的变化将如何影响网络。因为我们知道,在上一篇文章中,第一个偏置 b_1 会馈入第一个激活 a_1,我们就从这里开始。我们先回顾一下这个等式:

bfdff85af5a7be2e65f0f18492fbe394.png

   如果 b_1 改变,我们将这个改变量表示为 Δb_1。因此,我们注意到当 b_1改变时,激活a_1也会改变——我们通常将其表示为 ∂a_1/∂b_1。


   因此,我们左边有偏导的表达式,这是 b_1中与 a_1 相关的变化。但我们开始替换左边的项,先用 z_1 的 sigmoid 替换a_1:

   上式表示当 b_1 变化时,激活值 a_1 中存在某个变化。我们将这个变化描述为 Δa_1。

   我们将变化 Δa_1 看作是与激活值 a_1 中的变化加上变化 Δb_1 近似一样。

8572ed4982dcbfa165158b750dbe9569.png

   这里我们跳过了一步,但本质上讲,我们只是计算了偏导数,并用偏导的结果替代了分数部分。a_1 的变化导致 z_2 的变化所描述的变化 Δa_1 现在会导致下一层的输入 z_2 出现变化。

06a577d7cd74a2bca26b8e2877398feb.png

表示方式和前面一样,我们将下一个变化记为 Δz_2。我们又要再次经历前面的过程,只是这次要得到的是 z_2 中的变化:

cfea8302cf5ae6c2ddf01d9c71ecd023.png

可以使用下式替代 Δa_1:

e05e4f778caf7e9f226c72bd1bf854ef.png

   计算这个式子。希望你清楚地明白到这一步的过程——这与计算 Δa_1 的过程一样。


   这个过程会不断重复,直到我们计算完整个网络。通过替换 Δa_j 值,我们得到一个最终函数,其计算的是成本函数中与整个网络(即所有权重、偏置和激活)相关的变化。

7fe6ee9d8cfac6d9571dee05fbf91402.png

基于此,我们再计算 ∂C/∂b_1,得到我们需要的最终式:

79fbdb46a6479a93c5495ca8b23e8382.png


4.3、梯度爆炸的极端案例

   据此,如果所有权重 w_j 都很大,即如果很多权重的值大于 1,我们就会开始乘以较大的值。举个例子,所有权重都有一些非常高的值,比如 100,而我们得到一些在 0 到 0.25 之间、sigmoid 函数导数的随机输出:

5120847c58f56df2b9fc26042ec3d914.png

可以合理地相信这会远大于1,但为了方便示例展示,我们将其设为 1。

f0c29844f19c18ee5b26a051c03ed08f.png

使用这个更新规则,如果我们假设 b_1 之前等于 1.56,而学习率等于 0.5。

5a2dbbf375267e3226142098182a526f.png

尽管这是一个极端案例,但你懂我的意思。权重和偏置的值可能会爆发式地增大,进而导致整个网络爆炸。

c0eb50838f0907ee5558ca7388822425.png

   现在花点时间想想网络的权重和偏置以及激活的其它部分,爆炸式地更新它们的值。这就是我们所说的梯度爆炸问题。很显然,这样的网络学不到什么东西,因此这会完全毁掉你想要解决的任务。


4.4、避免梯度爆炸:梯度裁剪/规范

   解决梯度爆炸问题的基本思路就是为其设定一个规则。这部分我不会深入进行数学解释,但我会给出这个过程的步骤:

   选取一个阈值——如果梯度超过这个值,则使用梯度裁剪或梯度规范;


   定义是否使用梯度裁剪或规范。如果使用梯度裁剪,你就指定一个阈值,比如 0.5。如果这个梯度值超过 0.5 或 -0.5,则要么通过梯度规范化将其缩放到阈值范围内,要么就将其裁剪到阈值范围内。


    但是要注意,这些梯度方法都不能避免梯度消失问题。所以我们还将进一步探索解决这个问题的更多方法。通常而言,如果你在使用循环神经网络架构(比如 LSTM 或 GRU),那么你就需要这些方法,因为这种架构常出现梯度爆炸的情况

相关文章
|
3天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
7天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的卷积神经网络:从理论到实践
【10月更文挑战第35天】在人工智能的浪潮中,深度学习技术以其强大的数据处理能力成为科技界的宠儿。其中,卷积神经网络(CNN)作为深度学习的一个重要分支,在图像识别和视频分析等领域展现出了惊人的潜力。本文将深入浅出地介绍CNN的工作原理,并结合实际代码示例,带领读者从零开始构建一个简单的CNN模型,探索其在图像分类任务中的应用。通过本文,读者不仅能够理解CNN背后的数学原理,还能学会如何利用现代深度学习框架实现自己的CNN模型。
|
4天前
|
机器学习/深度学习 数据采集 自然语言处理
深入浅出深度学习:从理论到实践
【10月更文挑战第38天】本文旨在通过浅显易懂的语言和直观的代码示例,带领读者探索深度学习的奥秘。我们将从深度学习的基本概念出发,逐步深入到模型构建、训练以及应用实例,让初学者也能轻松入门。文章不仅介绍了深度学习的原理,还提供了实战操作指南,帮助读者在实践中加深理解。无论你是编程新手还是有一定基础的学习者,都能在这篇文章中找到有价值的内容。让我们一起开启深度学习之旅吧!
|
24天前
|
机器学习/深度学习 调度 计算机视觉
深度学习中的学习率调度:循环学习率、SGDR、1cycle 等方法介绍及实践策略研究
本文探讨了多种学习率调度策略在神经网络训练中的应用,强调了选择合适学习率的重要性。文章介绍了阶梯式衰减、余弦退火、循环学习率等策略,并分析了它们在不同实验设置下的表现。研究表明,循环学习率和SGDR等策略在提高模型性能和加快训练速度方面表现出色,而REX调度则在不同预算条件下表现稳定。这些策略为深度学习实践者提供了实用的指导。
33 2
深度学习中的学习率调度:循环学习率、SGDR、1cycle 等方法介绍及实践策略研究
|
6天前
|
机器学习/深度学习 自然语言处理 语音技术
深度学习的奇妙之旅:从理论到实践
【10月更文挑战第36天】在本文中,我们将一起探索深度学习的神秘世界。我们将首先了解深度学习的基本概念和原理,然后通过一个简单的Python代码示例,学习如何使用深度学习库Keras进行图像分类。无论你是深度学习的初学者,还是有一定基础的学习者,都可以从这篇文章中获得新的知识和启示。
|
11天前
|
机器学习/深度学习 监控 PyTorch
深度学习工程实践:PyTorch Lightning与Ignite框架的技术特性对比分析
在深度学习框架的选择上,PyTorch Lightning和Ignite代表了两种不同的技术路线。本文将从技术实现的角度,深入分析这两个框架在实际应用中的差异,为开发者提供客观的技术参考。
32 7
|
19天前
|
机器学习/深度学习 数据采集 人工智能
深度学习的魔法:从理论到实践的探索####
【10月更文挑战第22天】 本文深入探讨了深度学习这一现代人工智能领域的璀璨明珠,通过生动实例与通俗语言,揭示了其背后的原理、发展历程及在多个行业的应用潜力。文章首先概述了深度学习的基本概念,随后详细解析了神经网络的核心构成,并探讨了当前面临的挑战与未来趋势。最终,通过实际案例展示了深度学习如何改变世界,为读者呈现一幅技术革新引领未来的画卷。 ####
24 3
|
28天前
|
机器学习/深度学习 人工智能 监控
深入理解深度学习中的卷积神经网络(CNN):从原理到实践
【10月更文挑战第14天】深入理解深度学习中的卷积神经网络(CNN):从原理到实践
82 1
|
13天前
|
机器学习/深度学习 自动驾驶 大数据
深入探索深度学习:理论与实践
【10月更文挑战第29天】本文将深入探讨深度学习的理论与实践,包括其基本概念、发展历程、关键技术以及应用场景。我们将从浅入深,逐步解析深度学习的内在机制,并通过实例展示其在实际应用中的强大能力。无论你是深度学习的初学者,还是已经在该领域有所建树的研究者,都能在本文中找到有价值的信息。让我们一起踏上深度学习的探索之旅吧!
|
7天前
|
机器学习/深度学习 人工智能 测试技术
深度学习在图像识别中的应用与挑战
本文探讨了深度学习技术,尤其是卷积神经网络(CNN)在图像识别任务中的最新进展和面临的主要挑战。通过分析不同的网络架构、训练技巧以及优化策略,文章旨在提供一个全面的概览,帮助研究人员和实践者更好地理解和应用这些技术。
36 9

热门文章

最新文章

相关实验场景

更多