激活函数(阶跃,sigmoid,relu,恒等,softmax)

一般说“感知机”指的是“朴素感知机”,即使用阶跃函数为激活函数的单层感知机;
而“多层感知机”就是指神经网络,即使用sigmoid函数等平滑的激活函数的多层网络。

激活函数activation function:把输入信号的总和转换为输出信号的转换器。
它的关键在于如何去激活输入信号的总和。

(1)阶跃函数

h ( x ) = { 1 , x > 0 0 , x ≤ 0 h(x)=\left\{ \begin{aligned} 1,x>0\\ 0,x\leq0 \end{aligned} \right. h(x)={1,x>00,x0

def step_function(x): # 参数x只能接收实数
    if x>0:
        return 1
    else:
        return 0
import numpy as np
import matplotlib.pylab as plt

def step_func(x): # 参数x可以接受numpy数组
    y = x > 0 # y是布尔型数组
    return y.astype(np.int)

x = np.arange(-5., 5., .1)
y = step_func(x)
plt.plot(x,y)
plt.ylim(-0.1, 1.1) # y轴范围
plt.title('step function')
plt.show()

在这里插入图片描述
显然,阶跃函数的导数在绝大多数地方(除了0之外)的导数都是0。所以用它做激活函数的话,参数们的微小变化所引起的输出的变化就会直接被阶跃函数抹杀掉,在输出端完全体现不出来,训练时使用的损失函数的值就不会有任何变化,这是不利于训练过程的参数更新的。

(2)sigmoid

h ( x ) = 1 1 + e x p ( − x ) h(x)=\frac{1}{1+exp(-x)} h(x)=1+exp(x)1

import numpy as np
import matplotlib.pylab as plt

def step_func(x): # 参数x可以接受numpy数组
    y = x > 0 # y是布尔型数组
    return y.astype(np.int)

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

x = np.arange(-5., 5., .1)
y1 = step_func(x)
y2 = sigmoid(x)
plt.plot(x,y1,linestyle='--',color='black')
plt.plot(x,y2,color='black')
plt.ylim(-0.1, 1.1) # y轴范围
plt.title('step function & sigmoid function')
plt.show()

在这里插入图片描述


step function 和sigmoid的相同点:

  • 都是非线性函数
  • 虽然平滑性不同,但宏观上看的形状是相似的,均为“输入小则输出接近0,输入大则输出接近1”
  • 输出均在0和1之间

step function 和sigmoid的不同点:

  • 导数

sigmoid函数的导数在任何地方都不为0。

而阶跃函数的导数在绝大多数地方(除了0之外)的导数都是0。

sigmoid函数的导数在任何地方都不为0。这对NN的学习非常重要。参数们的一点微小的变化也会引起输出的微小的连续的变化,从而使得损失函数可以连续地变化,从而使得参数的更新正常进行,使得NN的学习正确进行。

所以用它做激活函数的话,参数们的微小变化所引起的输出的变化就会直接被阶跃函数抹杀掉,在输出端完全体现不出来,训练时使用的损失函数的值就不会有任何变化,这是不利于训练过程的参数更新的。

  • 平滑性不同。sigmoid是平滑曲线,输出随输入连续变化。而阶跃函数的输出随着输入急剧性变化。sigmoid的这种平滑性对于NN的学习具有重要意义。
  • 阶跃函数只能返回0或1,而sigmoid可以返回0,1之间的实值。所以感知机中流动的是0,1二元信号,而NN中流动的是连续的实值信号。

(3)RELU(Rectified Linear Unit)

NN的历史上,sigmoid最早被使用。但relu最近用的更多。
h ( x ) = { x , x > 0 0 , x ≤ 0 h(x)=\left\{ \begin{aligned} x,x>0\\ 0,x\leq0 \end{aligned} \right. h(x)={x,x>00,x0

def relu(x):
    return np.maximum(0,x)
    
x = np.arange(-5., 5., .1)
y3 = relu(x)
plt.plot(x,y3,color='black')
plt.ylim(-0.1, 5) # y轴范围
plt.title('relu')
plt.show()

在这里插入图片描述

输出层的激活函数

(4)恒等函数(用于回归任务)

机器学习任务通常分为回归和分类两种任务。回归任务是要求出具体的预测值,所以输出层不再使用激活函数进行非线性转换,或者说使用恒等函数作为激活函数,它什么都没做。

def identity_function(x): # 恒等函数,用作回归任务的输出层的激活函数
    return x

(5)softmax(用于分类任务)

分类的类别数目等于输出层神经元的数目。

假设输出层有n个神经元,第k个的输出 y k y_k yk
y k = e x p ( a k ) ∑ i = 1 n e x p ( a i ) y_k=\frac{exp(a_k)}{\sum_{i=1}^nexp(a_i)} yk=i=1nexp(ai)exp(ak)
分母是所有输入信号的指数函数的和,所以输出层的每个神经元都要受到所有输入信号的影响。

重要性质: ∑ k = 1 n y k = 1 \sum_{k=1}^ny_k=1 k=1nyk=1. 这使得我们可以把softmax的输出解释为概率。

e: 纳皮尔常数 2.7182···

'''
# 这个实现虽然功能正确,但容易导致溢出
# 指数函数的运算容易出现很大的超出数值范围(4或8字节)的数字,如exp(1000)导致溢出overflow
# 推导发现,可以通过减去输入信号的最大值避免溢出,且结果不变
def softmax(a): # a是数组,包含所有的输入信号
   exp_a = np.exp(a)
   sum_exp_a = np.sum(exp_a)
   y = exp_a / sum_exp_a
 
   return y
   '''

在这里插入图片描述
y k = e x p ( a k ) ∑ i = 1 n e x p ( a i ) = C e x p ( a k ) C ∑ i = 1 n e x p ( a i ) y_k=\frac{exp(a_k)}{\sum_{i=1}^nexp(a_i)}=\frac{Cexp(a_k)}{C\sum_{i=1}^nexp(a_i)} yk=i=1nexp(ai)exp(ak)=Ci=1nexp(ai)Cexp(ak)
= e x p ( a k + l o g C ) ∑ i = 1 n e x p ( a i + l o g C ) = e x p ( a k + C ′ ) ∑ i = 1 n e x p ( a i + C ′ ) =\frac{exp(a_k+logC)}{\sum_{i=1}^nexp(a_i+logC)}=\frac{exp(a_k+C')}{\sum_{i=1}^nexp(a_i+C')} =i=1nexp(ai+logC)exp(ak+logC)=i=1nexp(ai+C)exp(ak+C)
C ′ C' C为输入信号的最大值,即可解决溢出问题

def softmax(a):
    c = np.max(a)
    exp_a = np.exp(a-c) # 防溢出
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a

    return y
  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值