目录
一、什么是激活函数
如图所示,表示神经元的O中明确显示了激活函数的计算过程,即信号的加权总和为节点a,然后节点a被激活函数h()转换成节点y。简单的说,我们可以将上图用以下两个函数表示:
表示先计算输入信号的加权总和,然后用激活函数转换这一总和。因此,登场的函数会将输入信号的总和转换为输出信号,这种函数一般称为激活函数(activation function)。
二、神经网络的激活函数为什么必须使用非线性函数
换句话说,激活函数不能使用线性函数。为什么不能使用线性函数呢?
因为使用线性函数的话,加深神经网络的层数就没有意义了。 线性函数的问题在于,不管如何加深层数,总是存在与之等效的“无隐藏层的神经网络”。为了具体地(稍微直观地)理解这一点,我们来思考下面这个简单的例子。
这里我们考虑把线性函数作为激活函数,把的运算对应3层神经网络A。这个运算会进行 的乘法运算,但是同样的处理可以由(注意,)这一次乘法运算(即没有隐藏层的神经网络)来表示。如本例所示, 使用线性函数时,无法发挥多层网络带来的优势。因此,为了发挥叠加层所带来的优势,激活函数必须使用非线性函数。
如果使用非线性函数的话,激活函数给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中。
三、几种激活函数
3.1 阶跃函数
公式:
1. 阶跃函数的实现
当输入超过0时,输出1, 否则输出0。可以像下面这样简单地实现阶跃函数。
def step_function(x):
if x > 0:
return 1
else:
return 0
这个实现简单、易于理解,但是参数x只能接受实数(浮点数)。也就是说,允许形如step_function(3.0)的调用,但不允许参数取NumPy数组,例如step_function(np.array([1.0, 2.0]))。为了便于后面的操作,因此我们把它修改为支持NumPy数组的实现。
def step_function(x):
y = x > 0
return y.astype(np.int)
上述函数的内容只有两行。由于使用了NumPy中的“技巧”,可能会有点难理解。因此将用几行代码让你更好地理解这种“技巧”。
import numpy as np
x = np.array([-1.0, 1.0, 2.0])
print(x) # [-1., 1., 2.]
y = x > 0
print(y) # [False, True, True]
Y = y.astype(np.int)
print(Y) # [0, 1, 1]
[-1. 1. 2.] [False True True] [0 1 1]
其中astype()方法通过参数指定期望的类型,这个例子中是np.int型。Python中将布尔型转换为int型后,True会转换为1,False会转换为0。以上就是阶跃函数的实现中所用到的NumPy的“技巧”。
2. 阶跃函数的图形
# 导包
import numpy as np
import matplotlib.pylab as plt
# 定义阶跃函数
def step_function(x):
return np.array(x > 0, dtype=np.int)
# 模拟数据
x = np.arange(-5.0, 5.0, 0.1)
y = step_function(x)
# 绘图
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # 指定y轴的范围
plt.show()
阶跃函数以0为界,输出从0切换为1(或者从1切换为0)。它的值呈阶梯式变化,所以称为阶跃函数。
3.2 sigmoid函数
公式:
1. sigmoid函数的实现
下面,用Python可以像下面代码表示的sigmoid函数。
def sigmoid(x):
return 1 / (1 + np.exp(-x))
如果在这个sigmoid函数中输入一个NumPy数组,结果会如何呢?
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
x = np.array([-1.0, 1.0, 2.0])
print(sigmoid(x))
[0.26894142 0.73105858 0.88079708]
之所以sigmoid函数的实现能支持NumPy数组,秘密就在于NumPy的广播功能。根据NumPy 的广播功能,如果在标量和NumPy数组 之间进行运算,则标量会和NumPy数组的各个元素进行运算。
2. sigmoid函数的图形
# 导包
import numpy as np
import matplotlib.pylab as plt
# 定义sigmoid函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 模拟数据
x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
# 绘图
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # 指定y轴的范围
plt.show()
纵轴的取值范围(0, 1)。
3.3 ReLU函数
公式:
1. ReLu函数的实现
ReLU(Rectified Linear Unit)函数在输入大于0时,直接输出该值;在输入小于等于0时,输出0。因此,ReLU函数的实现也很简单,可以写成如下形式。
def relu(x):
return np.maximum(0, x)
这里使用了NumPy的maximum函数。maximum函数会从输入的数值中选择较大的那个值进行输出。
2. ReLu函数的图形
# 导包
import numpy as np
import matplotlib.pylab as plt
# 定义relu函数
def relu(x):
return np.maximum(0, x)
# 模拟数据
x = np.arange(-5.0, 5.0, 0.1)
y = relu(x)
# 绘图
plt.plot(x, y)
plt.ylim(-1, 5) # 指定y轴的范围
plt.show()
3.4 softmax函数
公式:
softmax函数的分子是输入信号的指数函数,分母是所有输入信号的指数函数的和。
1. softmax函数的实现
用图表示softmax函数的话,如图所示,softmax函数的输出通过箭头与所有的输入信号相连。输出层的各个神经元都受到所有输入信号的影响。
下面,用Python可以像下面代码表示的softmax函数。
def softmax(a):
exp_a = np.exp(a)
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a
return y
2. 实现softmax函数时的注意事项
上面的softmax函数的实现虽然正确描述了公式,但在计算机的运算上有一定的缺陷。这个缺陷就是溢出问题。softmax函数的实现中要进行指数函数的运算,但是此时指数函数的值很容易变得非常大。比如,的值 会超过20000,会变成一个后面有40多个0的超大值,的结果会返回一个表示无穷大的inf。如果在这些超大值之间进行除法运算,结果会出现“不确定”的情况。
softmax函数的实现可以像下式这样进行改进。
这里的可以使用任何值,但是为了防止溢出,一般会使用输入信号中的最大值。我们来看一个具体的例子。
a = np.array([1010, 1000, 990])
print(np.exp(a) / np.sum(np.exp(a))) # softmax函数的运算
c = np.max(a) # 1010
print(a - c)
print(np.exp(a - c) / np.sum(np.exp(a - c)))
[nan nan nan] [ 0 -10 -20] [9.99954600e-01 4.53978686e-05 2.06106005e-09]
我们发现原本为nan(not a number,不确定)的地方,现在被正确计算了。综上,我们可以像下面这样实现softmax函数。
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
3. softmax函数的特征
使用softmax()函数,可以按如下方式计算神经网络的输出。
import numpy as np
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
a = np.array([0.3, 2.9, 4.0])
y = softmax(a)
print(y)
print(np.sum(y))
[0.01821127 0.24519181 0.73659691] 1.0
如上所示,softmax函数的输出是0.0到1.0之间的实数。并且softmax函数的输出值的总和是1。输出总和为1是softmax函数的一个重要性质。
正因为有了这个性质,我们才可以把softmax函数的输出解释为“概率”。 比如,上面的例子可以解释成y[0]的概率是0.018(1.8%),y[1]的概率是0.245(24.5%),y[2]的概率是0.737(73.7%)。从概率的结果来看,可以说“因为第2个元素的概率最高,所以答案是第2个类别”。而且,还可以回答“有74%的概率是第2个类别,有25%的概率是第1个类别,有1%的概率是第0个类别”。也就是说,通过使用softmax函数,我们可以用概率的(统计的)方法处理问题。