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

  • Post author:
  • Post category:其他


一般说“感知机”指的是“朴素感知机”,即使用阶跃函数为激活函数的单层感知机;

而“多层感知机”就是指神经网络,即使用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




>




0








0


,




x









0

























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




+




e


x


p


(





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




>




0








0


,




x









0

























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







y










k



























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)}







y










k




















=
































i


=


1









n




















e


x


p


(



a










i


















)














e


x


p


(



a










k


















)

























分母是所有输入信号的指数函数的和,所以输出层的每个神经元都要受到所有输入信号的影响。

重要性质:



k

=

1

n

y

k

=

1

\sum_{k=1}^ny_k=1



















k


=


1









n





















y










k




















=








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)}







y










k




















=
































i


=


1









n




















e


x


p


(



a










i


















)














e


x


p


(



a










k


















)






















=



















C

















i


=


1









n




















e


x


p


(



a










i


















)














C


e


x


p


(



a










k


















)





























=

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


=


1









n




















e


x


p


(



a










i




















+




l


o


g


C


)














e


x


p


(



a










k




















+




l


o


g


C


)






















=
































i


=


1









n




















e


x


p


(



a










i




















+





C






















)














e


x


p


(



a










k




















+





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



版权声明:本文为qq_36607894原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。