【卷积神经网络】12、激活函数 | Tanh / Sigmoid / ReLU / Leaky ReLU / ELU / SiLU / Mish

本文主要介绍卷积神经网络中常用的激活函数及其各自的优缺点

在这里插入图片描述

最简单的激活函数被称为线性激活,其中没有应用任何转换。 一个仅由线性激活函数组成的网络很容易训练,但不能学习复杂的映射函数。线性激活函数仍然用于预测一个数量的网络的输出层(例如回归问题)。

非线性激活函数是更好的,因为它们允许节点在数据中学习更复杂的结构 。两个广泛使用的非线性激活函数是 sigmoid 函数和 双曲正切 激活函数。

在这里插入图片描述

一、Tanh

在这里插入图片描述

Tanh 函数公式如下,数值范围在 (-1, 1),导数范围为 (0, 1]

Tanh 函数的优点:

  • 以 0 为中心,能够达到正负平衡,避免出现梯度的不稳定性

Tanh 函数的缺点:

  • 会导致梯度消失问题!

二、Sigmoid

在这里插入图片描述

Sigmoid 函数公式如下,数值范围为 (0, 1),导数范围为 (0, 0.25]:

  • f ( x ) = 1 1 + e − z f(x) = \frac{1}{1+e^{-z}} f(x)=1+ez1

sigmoid 函数优点:

  • 可以把输入映射到 (0, 1)区间,可以用来表示概率,在物理意义上最为接近生物神经元

sigmoid 函数缺点:

  • 梯度消失问题 :由于 sigmoid 的导数 f′(zl) 区间为 (0, 0.25],所以其极易落入饱和区,导致梯度非常小,权重接近不变,无法正常更新
  • sigmoid 的输出并不是均值为 0 的,所有输出数据的大于0,会增加梯度的不稳定性
  • 当输出接近饱和或剧烈变化时,对输出范围的这种缩减往往会带来一些不利影响

三、ReLU

在这里插入图片描述

f ( x ) = max ( 0 , x ) f(x) = \text{max}(0, x) f(x)=max(0,x)

ReLU 函数的优点:

  • 摒弃了复杂的计算, 比 sigmoid/tanh 收敛的更快 (大概快 6x)
  • 其导数在其权重和(z) 大于 0 的时候为 1,不存在梯度消失现象权重可以正常更新,但也要防止 ReLU 的梯度爆炸

ReLU 函数的缺点:

  • 小于 0 的输出经过 ReLU 之后会全都变成 0,梯度值为0,从而权重无法正常更新
  • 输出具有偏移现象,即输出均值恒大于零
  • 当使用了较大的学习速率时,易受到饱和的神经元的影响。

四、Leaky ReLU

在这里插入图片描述

公式如下:

  • f ( x ) = α x ,   x < 0 f(x) = \alpha x, \ x<0 f(x)=αx, x<0
  • f ( x ) = x ,   x > = 0 f(x) = x, \ x>=0 f(x)=x, x>=0

为了防止模型 dead 的情况,出现了很多 ReLU 的改进版本,如 Leaky ReLU,在 0 右侧和 ReLU 一样,左侧从全零变成了一个斜率很小的直线

优点:

  • 避免了小于零的特征被处理为 0 导致特征丢失的情况,同时左右两侧梯度都是恒定的,不会出现梯度消失现象

缺点:

  • Leaky ReLU中的 α \alpha α 为常数,一般设置 0.01。这个函数通常比 ReLU 激活函数效果要好,但是效果不是很稳定,所以在实际中 Leaky ReLU 使用的并不多。

五、ELU

在这里插入图片描述

在这里插入图片描述

ELU(Exponential Linear Unit,指数线性单元)尝试加快学习速度。基于ELU,有可能得到比ReLU更高的分类精确度。

优点:

  • 解决了 ReLU 可能导致的网络 dead 的问题

缺点:

  • 计算量较大

六、SiLU

在这里插入图片描述

f ( x ) = x ∗ sigmoid ( β x ) f(x) = x *\text{sigmoid}(\beta x) f(x)=xsigmoid(βx) β = 1 \beta=1 β=1 时就是 SiLU

优点:

  • 相比 ReLU 增加了平滑性的特点

缺点:

  • 引入了指数计算,增加了计算量

七、Mish

在这里插入图片描述

f ( x ) = x ∗ tanh ( ln ( 1 + e x ) ) f(x) = x * \text{tanh}(\text{ln}(1+e^x)) f(x)=xtanh(ln(1+ex))

优点:

  • 平滑、非单调、无上界、有下界

缺点:

  • 引入了指数函数,增加了计算量

绘图代码:

import matplotlib.pyplot as plt
import numpy as np
import math
#
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False


## sigmoid
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
x1 = np.arange(-10.0, 10.0, 0.1)
y1 = sigmoid(x1)
plt.plot(x1, y1, color='purple', label='sigmoid')
plt.legend()

## ReLU
def ReLU(x):
    return np.maximum(0, x)  # ReLU函数的定义
x2 = np.arange(-10.0, 10.0, 0.1)
y2 = ReLU(x2)
plt.plot(x2, y2, color='orange', label='ReLU')
plt.legend()


## tanh
def tanh(x):
    return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))
x3 = np.arange(-10.0, 10.0, 0.1)
y3 = tanh(x3)
plt.plot(x3, y3, color='yellow', label='Taanh')
plt.legend()


## Leaky ReLU
def Leaky_ReLU(xx):
    return [x if x > 0 else 0.1 * x for x in xx]
x4 = np.arange(-10, 10.0, 0.1)
y4 = Leaky_ReLU(x4)
plt.plot(x4, y4, color='black', label='Leaky ReLU(alpha=0.1)')
plt.legend()

## ELU
def ELU(xx):
    return [x if x > 0 else 1 * (np.exp(x) - 1) for x in xx]
x5 = np.arange(-10.0, 10.0, 0.1)
y5 = ELU(x5)
plt.plot(x5, y5, color='green', label='ELU(alpha=1)')
plt.legend()

# silu
def SiLU(xx):
    return [x * (1 / (1 + np.exp(-x))) for x in xx]
x6 = np.arange(-10.0, 10.0, 0.1)
y6 = SiLU(x6)
plt.plot(x6, y6, color='red', label='SiLU')
plt.legend()

## Mish
def Mish(xx):
    return [x * tanh(np.log(1 + np.exp(x))) for x in xx]
def tanh(x):
    return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))
x7 = np.arange(-10.0, 10.0, 0.1)
y7 = Mish(x7)
plt.plot(x7, y7, color='pink', label='Mish')
plt.legend()

# 获得当前的axis
ax = plt.gca()
# 设置图像的上边、右边axis为无色
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

# 设置x轴坐标在下部
ax.xaxis.set_ticks_position('bottom')
# 设置x轴位于图像y=0处
ax.spines['bottom'].set_position(('data', 0))
# 设置x轴坐标在左部
ax.yaxis.set_ticks_position('left')
# 设置y轴位于图像x=0处
ax.spines['left'].set_position(('data', 0))
plt.show()
  • 10
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个使用8086汇编语言的程序,可以输入一组不超过30个的字符串,并在屏幕上输出: ``` .model small .stack 100h .data str_arr db 30, 0 ; 字符串数组,最大长度为30 str_len db ? ; 字符串长度 str db 80, 0 ; 缓冲区,用于读入字符串 prompt db 'Enter a string: $' output db 'You entered: $' .code main proc mov ax, @data ; 初始化数据段寄存器 mov ds, ax ; 循环输入字符串 mov cx, 30 ; 最多输入30个字符串 input_loop: ; 输出提示信息 mov ah, 9 lea dx, prompt int 21h ; 读入字符串 mov ah, 0ah lea dx, str int 21h ; 将字符串复制到数组中 mov si, offset str+1 ; 跳过字符个数的字节 mov di, offset str_arr mov al, [si] mov [di], al mov str_len, al inc di inc si mov cx, str_len rep movsb ; 判断是否已经输入30个字符串 dec cx jz input_done ; 继续输入 jmp input_loop input_done: ; 输出已输入的字符串 mov ah, 9 lea dx, output int 21h mov si, offset str_arr mov cx, 30 output_loop: mov dl, [si] cmp dl, 0 jz output_done mov ah, 2 int 21h inc si loop output_loop output_done: ; 程序结束 mov ah, 4ch int 21h main endp end main ``` 这个程序使用了`INT 21h`来输出字符串和读入字符串。具体来说,使用了`AH=0ah`来读入字符串,使用了`AH=9`来输出字符串。在输入字符串时,程序将字符个数和字符串一起读入缓冲区,并将字符串复制到字符串数组中。在输出字符串时,程序遍历字符串数组,并输出每个字符串。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呆呆的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值