激活函数(ReLU、Leaky ReLU、PReLU、tanh)

介绍

神经网络中的每个 神经元节点 接受上一层 神经元的输出值 作为本神经元的 输入值,计算后并将输出值 传递给下一层,输入层神经元节点会将输入属性值直接传递给下一层(隐层或输出层)。

在多层神经网络中,上层节点的输出 和 下层节点的输入 之间具有一个函数关系,这个函数称为 激活函数 (又称 激励函数)

作用

如果 没有 激活函数,每一层节点的输入 都是 上层输出的线性函数结果,无论你神经网络有多少层,输出都是输入的 线性组合,相当于没有隐藏层,这种情况就是最原始的感知机(Perceptron)了,那么网络的逼近能力就相当有限。

所以要引入 非线性函数 作为 激活函数,这样深层神经网络表达能力就更加强大(不再是输入的线性组合,而是几乎可以逼近任意函数)。

一句话解释

  • 将 线性函数结果 做 非线性 映射
  • 让直线弯曲,有更强的拟合能力
  • 将 线性问题 ,转变为 分类问题

问题

使用某个激活函数后,可能效果不好(如偏差比较大),那么就要换一个激活函数

有哪些激活函数

早期研究神经网络主要采用 sigmoid函数 或者 tanh函数,输出有边界,很容易充当下一层的输入。

近些年 Relu函数 及其改进型(如 Leaky-ReLU、P-ReLU、R-ReLU 等)在多层神经网络中应用比较多。

  1. sigmoid
  2. tanh
  3. relu
  4. leaky relu
  5. PReLU
  6. softmax

ReLU (推荐)

ReLU,Rectified Linear Unit,修正线性单元函数

激活函数的默认选择,如果不知道在隐层中该使用什么激活函数,那么就是用ReLU

图像

公式

f(x)=max(0,x)
  1. 当x>0时,输出等于输入
  2. 当x<=0时,输出为0

导数

当x < 0时,导数为0
当x > 0时,导数为1
当x = 0时,没有定义 (在编程中可以将导数设置成0或1)

优点

学习速度快,因为斜率不为0,不会减慢学习速度
(sigmoid、tanh都有斜率接近0)

Leaky ReLU

Leaky ReLU,Leaky Rectified Linear Unit ,带泄露整流函数

比ReLU要好,但很少使用

图像

特点:

  1. 当x>0时,原样输出
  2. 当x<=0时,输出较小的值。ai是固定值

优点

学习速度快,因为斜率不为0,不会减慢学习速度
(sigmoid、tanh都有斜率接近0)

导数

当x < 0时,导数为0.01
当x > 0时,导数为1
当x = 0时,没有定义(在编程中可以将导数设置成0.01 或 1)

keras api

https://www.malaoshi.top/show_1EF5CzrzJfSB.html

PReLU

PReLU,Parametric Rectified Linear Unit,带参数的ReLU

图像

特点:

  1. 当x>0时,原样输出
  2. 当x<=0时,输出较小的值。
    ai 是可以学习的的:
    • 如果ai=0,那么PReLU退化为ReLU;
    • 如果ai是一个很小的固定值(如ai=0.01),则PReLU退化为Leaky ReLU(LReLU)。

优点

学习速度快,因为斜率不为0,不会减慢学习速度
(sigmoid、tanh都有斜率接近0)

tanh

tanh,hyperbolic tangent,双曲正切函数

除了 二分类 输出层,一般情况下,可以替代sigmoid函数

公式

图像

特点:

从函数图像上看,与sigmoid有些类似

  1. 接近0时,非常陡峭,输出值变化非常大
  2. 远离0时,越平缓,输出值变化不大
  3. 输出值在 -1 ~ 1 之间,平均值接近0,让下一层学习更方便一点

导数

  • 当 x 越大 时,tanh(x) 越接近1,那么 导数结果为 0
  • 当 x 越小 时,tanh(x) 越接近-1,那么 导数结果为 0

缺点

  1. 计算量大
  2. 当x过大、过小时,函数值变化小,梯度容易消失,不利于 后向传播

作用

由于输出值在 -1 ~ 1 之间,平均值接近0,让下一层学习更方便一点,所以一般用在 隐层

应用场景

常被用在:

  • 循环神经网络(RNN/LSTM)的隐藏层(相比 sigmoid 更适合,因为输出中心化);
  • 一些传统的全连接网络中(但现在更多被 ReLU 及其变体替代);
  • 生成对抗网络(GAN)的判别器输出层(需要输出 [-1,1] 区间)。

图像代码

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.axisartist as axisartist

def a(x):
    return (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))

x=np.linspace(-5,5,100)
y=a(x)

# fig = plt.figure(figsize=(10, 10),dpi=70)
fig = plt.figure(figsize=(8, 8))
ax = axisartist.Subplot(fig, 111)  
#将绘图区对象添加到画布中
fig.add_axes(ax)

#设置x、y坐标轴的范围
# plt.xlim(-12,12)
# plt.ylim(-1.5, 1.5)

#设置绘图区所有坐标轴隐藏
ax.axis[:].set_visible(False)
#添加新的坐标轴
ax.axis["x"] = ax.new_floating_axis(0,0)
#设置箭头,-|>表示实心箭头,->空心箭头
# ax.axis["x"].set_axisline_style("-|>", size = 2.0)

#添加新的坐标轴
ax.axis["y"] = ax.new_floating_axis(1,0)
#设置箭头,-|>表示实心箭头,->空心箭头
# ax.axis["y"].set_axisline_style("-|>", size = 0.80)
#设置x、y轴上刻度显示方向
ax.axis["x"].set_axis_direction("bottom")
ax.axis["y"].set_axis_direction("left")

plt.plot(x,y)

感谢:
https://blog.csdn.net/tyhj_sf/article/details/79932893