上文我们已经认识了激活函数家族的第一个成员。以阈值为界,一旦输入超过阈值,就切换输出。这样的函数称为“阶跃函数”。但高大上的神经网络世界是不会使用这么低端的激活函数的,只有低级的感知机世界才会用'阶跃函数'。下面登场的是神经网络世界的激活函数----sigmoid函数!!(之所以加双叹号,是因为我们即将进入神经网络的世界。之后就可以制作机器人,然后机器人反叛,一统天下,走向人生巅峰了。)
看起来很简单有木有?exp(−x)表示e 的−x次方 。e是纳皮尔常数2.7182 . . .
为了更加直观的表现sigmoid和阶跃函数的不同,我会用代码实现它们,并显示在图表上。
下面是阶跃函数的实现:
# 阶跃函数
def step_function(x):
y = x > 0
return y.astype(np.int)
x参数是一个np数组。还记得吗?x>0会返回一串bool值。
.astype(np.int)则是把bool值转化为np.int类型。
True--->1
False-->0
下面是sigmoid函数的实现:
#sigmoid函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
x参数是一个np数组。还记得吗?之前我们提到了广播,所以np数组可以与单数运算。
接下来,把它们画在图表上。先设置阶跃函数:
#把阶跃函数画出来
def drow_step_function():
x=np.arange(-6,6,0.1)
y=step_function(x)
pyplot.plot(x,y,linestyle='--',label='step_function')
np.arange()与我们用的range功能差不多。它把-6到6区间以0.1为步长,等分了120份,生成了np数组。
y就是阶跃函数的返回值
最后把xy的值加入图表属性。并设置了线条和标签。
继续设置sidmoid函数的图表:
#把sigmoid函数画出来
def drow_sigmoid():
x=np.arange(-6,6,0.1)
y=sigmoid(x)
pyplot.plot(x,y,label='sigmoid')
嗯,两个函数相关的图表设置完毕了。现在把它们显示出来:
def main():
pyplot.title('step&sigmoid_function')
pyplot.ylabel('y')
pyplot.xlabel('x')
#设置y轴方向的上限和下限
pyplot.ylim(-0.1, 1.1)
drow_step_function()
drow_sigmoid()
pyplot.legend()
pyplot.show()
if __name__ == '__main__':
main()
我启动了这个代码。。。
阶跃函数和sigmoid函数挤在同一个图表里,看起来是这个样子的。
这两个函数的异同点也非常明显:
阶跃函数:信号不平滑两极分化
sigmoid:信号连续平滑
相同点:信号都在01之间,都是非线性的
后面你会知道,信号平滑对神经网络而言意义非凡。也是高大上的神经网络世界不接受阶跃函数的原因。
神经网络必须使用非线性函数作为激活函数。下面会给出让你折服的理由。
我们假设使用h(x) = cx这个线性函数作为激活函数。并且我们意淫有一个3层网络的神经网络使用了它。
y(x) = h(h(h(x)))的运算对应3层神经网络,这个运算会进行y(x) = c × c × c × x的乘法运算,既然一步就能算出来的东西,我们何必
用好几层神经网络呢?换句话说,多层网络本应该发挥的巨大作用,在线性激活函数面前失效了。所以,神经网络必须使用非线
性函数。
----ReLU函数----
def relu(x):
return np.maximum(0, x)
maximum 方法会从输入的数值中选择较大的那个值进行输出。下面是ReLU函数的图像化表示:
是不是很呆萌的小函数呢?嗯,你知道这个激活函数的存在就好。后面会经常用到它!
--------结语--------
我们现在了解了3个激活函数。想必,看到这里,知识已经开始与前面的知识混做一团。大脑即将开启混乱模式了。