介绍
神经网络中的每个 神经元节点 接受上一层 神经元的输出值 作为本神经元的 输入值,计算后并将输出值 传递给下一层,输入层神经元节点会将输入属性值直接传递给下一层(隐层或输出层)。
在多层神经网络中,上层节点的输出 和 下层节点的输入 之间具有一个函数关系,这个函数称为 激活函数 (又称 激励函数)
作用
如果 没有 激活函数,每一层节点的输入 都是 上层输出的线性函数结果,无论你神经网络有多少层,输出都是输入的 线性组合,相当于没有隐藏层,这种情况就是最原始的感知机(Perceptron)了,那么网络的逼近能力就相当有限。
所以要引入 非线性函数 作为 激活函数,这样深层神经网络表达能力就更加强大(不再是输入的线性组合,而是几乎可以逼近任意函数)。
一句话解释
- 将 线性函数结果 做 非线性 映射
- 让直线弯曲,有更强的拟合能力
- 将 线性问题 ,转变为 分类问题
问题
使用某个激活函数后,可能效果不好(如偏差比较大),那么就要换一个激活函数
有哪些激活函数
早期研究神经网络主要采用 sigmoid函数 或者 tanh函数,输出有边界,很容易充当下一层的输入。
近些年 Relu函数 及其改进型(如 Leaky-ReLU、P-ReLU、R-ReLU 等)在多层神经网络中应用比较多。
ReLU (推荐)
ReLU,Rectified Linear Unit,修正线性单元函数
激活函数的默认选择,如果不知道在隐层中该使用什么激活函数,那么就是用ReLU
图像
公式
f(x)=max(0,x)
- 当x>0时,输出等于输入
- 当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要好,但很少使用
图像
特点:
- 当x>0时,原样输出
- 当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
图像
特点:
- 当x>0时,原样输出
- 当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有些类似
- 接近0时,非常陡峭,输出值变化非常大
- 远离0时,越平缓,输出值变化不大
- 输出值在 -1 ~ 1 之间,平均值接近0,让下一层学习更方便一点
导数
- 当
x越大 时,tanh(x)越接近1,那么 导数结果为0 - 当
x越小 时,tanh(x)越接近-1,那么 导数结果为0
缺点
- 计算量大
- 当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)





