文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

YOLO v4常见的非线性激活函数详解

2024-04-02 19:55

关注

YOLO v4中用到的激活函数是Mish激活函数
在YOLO v4中被提及的激活函数有: ReLU, Leaky ReLU, PReLU, ReLU6, SELU, Swish, Mish
其中Leaky ReLU, PReLU难以训练,ReLU6转为量化网络设计

激活函数使用过程图:

在这里插入图片描述

一、饱和激活函数

 1.1、Sigmoid

函数表达式:

Sigmoid函数图像及其导数图像:

在这里插入图片描述

优点:

缺点:

1.2、hard-Sigmoid函数

hard-Sigmoid函数时Sigmoid激活函数的分段线性近似。

函数公式:

hard-Sigmoid函数图像和Sigmoid函数图像对比:

在这里插入图片描述

hard-Sigmoid函数图像及其导数图像:

在这里插入图片描述

优点:

  1. 从公示和曲线上来看,其更易计算,没有指数运算,因此会提高训练的效率。

缺点:

  1. 首次派生值为零可能会导致神经元died或者过慢的学习率。

1.3、Tanh双曲正切

函数表达式:

Tanh函数图像及其导函数图像:

在这里插入图片描述

优点:

  1. 解决了Sigmoid函数的非zero-centered问题
  2. 能压缩数据,使输出保证在 [ 0 , 1 ] [0,1] [0,1]之间(相当于对输出做了归一化),保证数据幅度不会有问题;(有上下界)

缺点:

二、非饱和激活函数

 2.1、ReLU(修正线性单元)

函数表达式:

f ( z ) = m a x ( 0 , x ) f(z)=max(0,x) f(z)=max(0,x)

ReLU函数图像及其导数图像:

在这里插入图片描述

优点:

  1. ReLu的收敛速度比 sigmoid 和 tanh 快;
  2. 输入为正时,解决了梯度消失的问题,适合用于反向传播。;
  3. 计算复杂度低,不需要进行指数运算;

缺点:

 2.2、ReLU6(抑制其最大值)

函数表达式:

ReLU函数图像和ReLU6函数图像对比:

在这里插入图片描述

ReLU6函数图像及其导数图像:

在这里插入图片描述

2.3、Leakly ReLU

函数表达式:

ReLU函数图像和Leakly ReLU函数图像对比:

在这里插入图片描述

Leakly ReLU函数图像及其导数图像:

在这里插入图片描述

优点:

  1. 解决上述的dead ReLU现象, 让负数区域也会梯度消失;

理论上Leaky ReLU 是优于ReLU的,但是实际操作中,并不一定。

2.4、PReLU(parametric ReLU)

函数公式:

注意:

函数图像:

在这里插入图片描述

优点:

2.5、ELU(指数线性函数)

函数表达式:

ELU函数图像及其导数图像( α = 1.5 \alpha=1.5 α=1.5):

在这里插入图片描述

优点:

缺点:

理论上ELU优于ReLU, 但是真实数据下,并不一定。

2.6、SELU

SELU就是在ELU的基础上添加了一个 λ \lambda λ参数,且 λ > 1 \lambda>1 λ>1

函数表达式:

ELU函数图像和SELU函数图像对比( α = 1.5 , λ = 2 \alpha=1.5, \lambda=2 α=1.5,λ=2):

在这里插入图片描述

SELU函数图像及其导数图像( α = 1.5 , λ = 2 \alpha=1.5, \lambda=2 α=1.5,λ=2):

在这里插入图片描述

优点:

  1. 以前的ReLU、P-ReLU、ELU等激活函数都是在负半轴坡度平缓,这样在激活的方差过大时可以让梯度减小,防止了梯度爆炸,但是在正半轴其梯度简答的设置为了1。而SELU的正半轴大于1,在方差过小的时候可以让它增大,但是同时防止了梯度消失。这样激活函数就有了一个不动点,网络深了之后每一层的输出都是均值为0,方差为1. 2.7、Swish

函数表达式:

Swish函数图像( β = 0.1 , β = 1 , β = 10 \beta=0.1, \beta=1,\beta=10 β=0.1,β=1,β=10):

在这里插入图片描述

Swish函数梯度图像( β = 0.1 , β = 1 , β = 10 \beta=0.1, \beta=1,\beta=10 β=0.1,β=1,β=10):

在这里插入图片描述

优点:

缺点:

hard = 硬,就是让图像在整体上没那么光滑(从下面两个图都可以看出来)

函数表达式:

hard-Swish函数图像和Swish( β = 1 \beta=1 β=1)函数图像对比:

在这里插入图片描述

hard-Swish函数图像和Swish( β = 1 \beta=1 β=1)函数梯度图像对比:

在这里插入图片描述

优点:

  1. hard-Swish近似达到了Swish的效果;
  2. 且改善了Swish的计算量过大的问题,在量化模式下,ReLU函数相比Sigmoid好算太多了;

 2.9、Mish

论文地址:

https://arxiv.org/pdf/1908.08681.pdf

关于激活函数改进的最新一篇文章,且被广泛用于YOLO4中,相比Swish有0.494%的提升,相比ReLU有1.671%的提升。

Mish函数公式:

Mish函数图像和Swish( β = 1 \beta=1 β=1)函数图像对比:

在这里插入图片描述

Mish函数图像和Swish( β = 1 \beta=1 β=1)函数导数图像对比:

在这里插入图片描述

为什么Mish表现的更好:

上面无边界(即正值可以达到任何高度)避免了由于封顶而导致的饱和。理论上对负值的轻微允许更好的梯度流,而不是像ReLU中那样的硬零边界。
最后,可能也是最重要的,目前的想法是,平滑的激活函数允许更好的信息深入神经网络,从而得到更好的准确性和泛化。Mish函数在曲线上几乎所有点上都极其平滑。

三、PyTorch 实现


import matplotlib.pyplot as plt
import numpy as np

class ActivateFunc():
    def __init__(self, x, b=None, lamb=None, alpha=None, a=None):
        super(ActivateFunc, self).__init__()
        self.x = x
        self.b = b
        self.lamb = lamb
        self.alpha = alpha
        self.a = a

    def Sigmoid(self):
        y = np.exp(self.x) / (np.exp(self.x) + 1)
        y_grad = y*(1-y)
        return [y, y_grad]

    def Hard_Sigmoid(self):
        f = (2 * self.x + 5) / 10
        y = np.where(np.where(f > 1, 1, f) < 0, 0, np.where(f > 1, 1, f))
        y_grad = np.where(f > 0, np.where(f >= 1, 0, 1 / 5), 0)
        return [y, y_grad]

    def Tanh(self):
        y = np.tanh(self.x)
        y_grad = 1 - y * y
        return [y, y_grad]

    def ReLU(self):
        y = np.where(self.x < 0, 0, self.x)
        y_grad = np.where(self.x < 0, 0, 1)
        return [y, y_grad]

    def ReLU6(self):
        y = np.where(np.where(self.x < 0, 0, self.x) > 6, 6, np.where(self.x < 0, 0, self.x))
        y_grad = np.where(self.x > 6, 0, np.where(self.x < 0, 0, 1))
        return [y, y_grad]

    def LeakyReLU(self):   # a大于1,指定a
        y = np.where(self.x < 0, self.x / self.a, self.x)
        y_grad = np.where(self.x < 0, 1 / self.a, 1)
        return [y, y_grad]

    def PReLU(self):    # a大于1,指定a
        y = np.where(self.x < 0, self.x / self.a, self.x)
        y_grad = np.where(self.x < 0, 1 / self.a, 1)
        return [y, y_grad]

    def ELU(self): # alpha是个常数,指定alpha
        y = np.where(self.x > 0, self.x, self.alpha * (np.exp(self.x) - 1))
        y_grad = np.where(self.x > 0, 1, self.alpha * np.exp(self.x))
        return [y, y_grad]

    def SELU(self):  # lamb大于1,指定lamb和alpha
        y = np.where(self.x > 0, self.lamb * self.x, self.lamb * self.alpha * (np.exp(self.x) - 1))
        y_grad = np.where(self.x > 0, self.lamb * 1, self.lamb * self.alpha * np.exp(self.x))
        return [y, y_grad]

    def Swish(self): # b是一个常数,指定b
        y = self.x * (np.exp(self.b*self.x) / (np.exp(self.b*self.x) + 1))
        y_grad = np.exp(self.b*self.x)/(1+np.exp(self.b*self.x)) + self.x * (self.b*np.exp(self.b*self.x) / ((1+np.exp(self.b*self.x))*(1+np.exp(self.b*self.x))))
        return [y, y_grad]

    def Hard_Swish(self):
        f = self.x + 3
        relu6 = np.where(np.where(f < 0, 0, f) > 6, 6, np.where(f < 0, 0, f))
        relu6_grad = np.where(f > 6, 0, np.where(f < 0, 0, 1))
        y = self.x * relu6 / 6
        y_grad = relu6 / 6 + self.x * relu6_grad / 6
        return [y, y_grad]

    def Mish(self):
        f = 1 + np.exp(x)
        y = self.x * ((f*f-1) / (f*f+1))
        y_grad = (f*f-1) / (f*f+1) + self.x*(4*f*(f-1)) / ((f*f+1)*(f*f+1))
        return [y, y_grad]

def PlotActiFunc(x, y, title):
    plt.grid(which='minor', alpha=0.2)
    plt.grid(which='major', alpha=0.5)
    plt.plot(x, y)
    plt.title(title)
    plt.show()

def PlotMultiFunc(x, y):
    plt.grid(which='minor', alpha=0.2)
    plt.grid(which='major', alpha=0.5)
    plt.plot(x, y)

if __name__ == '__main__':
    x = np.arange(-10, 10, 0.01)
    activateFunc = ActivateFunc(x)
    activateFunc.a = 100
    activateFunc.b= 1
    activateFunc.alpha = 1.5
    activateFunc.lamb = 2

    plt.figure(1)
    PlotMultiFunc(x, activateFunc.Sigmoid()[0])
    PlotMultiFunc(x, activateFunc.Hard_Sigmoid()[0])
    PlotMultiFunc(x, activateFunc.Tanh()[0])
    PlotMultiFunc(x, activateFunc.ReLU()[0])
    PlotMultiFunc(x, activateFunc.ReLU6()[0])
    PlotMultiFunc(x, activateFunc.LeakyReLU()[0])
    PlotMultiFunc(x, activateFunc.ELU()[0])
    PlotMultiFunc(x, activateFunc.SELU()[0])
    PlotMultiFunc(x, activateFunc.Swish()[0])
    PlotMultiFunc(x, activateFunc.Hard_Swish()[0])
    PlotMultiFunc(x, activateFunc.Mish()[0])

    plt.legend(['Sigmoid', 'Hard_Sigmoid', 'Tanh', 'ReLU', 'ReLU6', 'LeakyReLU',
                'ELU', 'SELU', 'Swish', 'Hard_Swish', 'Mish'])
    plt.show()

四、结果显示

在这里插入图片描述

Reference

链接1: link.

链接2: link.

https://arxiv.org/pdf/1908.08681.pdf

到此这篇关于YOLO v4常见的非线性激活函数详解的文章就介绍到这了,更多相关YOLO v4激活函数内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯