神经网络第一篇:激活函数是连接感知机和神经网络的桥梁

前面发布的文章介绍了感知机,了解了感知机可以通过叠加层表示复杂的函数。遗憾的是,设定合适的、能符合预期的输入与输出的权重,是由人工进行的。从本章开始,将进入神经网络的学习,首先介绍激活函数,因为它是连接感知机和神经网络的桥梁。如果读者认知阅读了本专题知识,相信你必有收获。

感知机数学表达式的简化

前面我们介绍了用感知机接收两个输入信号的数学表示如下:

                                         

现在将上式改成更加简洁的形式,我们不妨想一下,上面的表达式(或者说是函数)输出y只有两种值0和1。因此,我们引入一个新函数将上式改写成下式:

                                        

式(2)中,输入信号的总和会被函数h(x)转换,转换后的值就是输出y。而式(3)所表示的h(x)在输入超过0时返回1,否则返回0。不难理解,式(1)和式(2)、(3)做的是一件事情。其实这和数学中的复合函数的意思一样(将b+w1x1+w2x2整体作为变量x,变量名可随便取)。

激活函数登场

 我们刚引入的h(x)函数能将输入信号的总和转换为输出信号(只有0和1),这种函数就是激活函数。正如“激活”二字,激活函数就是决定如何来激活输入信号的总和。读者意识可能有点模糊,我们对上面的式子再分析一下,将式(2)分为两个阶段,如下式,第一阶段是计算输入信号的加权和,第二阶段则用激活函数来转换这一加权和。

                                      

式(4)计算输入信号和偏置b的总和,记为a,接着用h()函数将a转换为输出y。这里我们用下图来形象地表示式(4)和式(5)。

                                     

    0表示神经元,这里我们新增了一个输入信号为常数1的神经元(灰色),其权重为b,主要是把偏置b(控制神经元被激活的容易程度)添加至感知机中。把上图和上面的公式结合起来分析,节点a接收了输入信号的加权和,接着节点a被激活函数h()转换为节点y输出。注意节点和神经元是一样的意思。

试想什么样的函数的输出只有0和1两种值,毫无疑问,阶跃函数(0处突变为1)的输出就是这样的。这里科普一下,一般而言,单层感知机也称为朴素感知机,即使用了阶跃函数作为激活函数的单层网络。多层感知机指神经网络,即使用了sigmoid函数等平滑函数作为激活函数的多层网络。

式(3)表明,输入一旦超过阀值,激活函数就切换输出,因此在感知机中的激活函数是“阶跃函数”。我们不难发问,如果感知机使用其他函数作为激活函数,结果会怎么样呢?答案是使用其他激活函数,那我们就进入了神经网络的世界了。下面我们详细介绍在神经网络中常用的几种激活函数。

阶跃函数

    如式(3),输入大于0,输出为1,否则输出为0。Python实现如下:

import numpy as np

import matplotlib.pylab as plt

"""numpy轻易实现"""

def step_function(x):

    return np.array(x>0,dtype=np.int) #true为1,false为0

"""绘图"""

x=np.arange(-3.0,3.0,0.1)

y=step_function(x)

plt.plot(x,y)

plt.ylim(-0.1,1.1)

plt.show()


 

sigmoid函数

在神经网络中,sigmoid函数常作为激活函数,其表达式如下:

                                      

式(6)中exp(-x)表示e-x次方的意思。实际上,感知机和神经网络的主要区别就在于激活函数的不同。Sigmoid函数作为激活函数,对信号进行转换,转换后的信号被传送给下一个神经元。Python实现如下:

"""sigmoid函数,除了函数不一样,绘图代码同上"""

def sigmoid(x):

    return 1/(1+np.exp(-x))  #numpy的广播功能

                                     

比较

绘图代码如下:

# coding: utf-8
#阶跃函数和sigmoid函数比较
import numpy as np
import matplotlib.pylab as plt


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


def step_function(x):
    return np.array(x > 0, dtype=np.int)

x = np.arange(-5.0, 5.0, 0.1)
y1 = sigmoid(x)
y2 = step_function(x)

plt.plot(x, y1)
plt.plot(x, y2, 'k--')
plt.ylim(-0.1, 1.1) #指定图中绘制的y轴的范围
plt.show()

                                              

不同点:

    (1)sigmoid函数是一条平滑的曲线,即输出随输入发生连续的变化,阶跃函数以0为界,发生急剧性的变化。sigmoid函数的平滑性对神经网络的学习极有帮助。

    (2)阶跃函数只能输出0或1(二元信号),而sigmoid函数可输出连续的实数信号。

相同点:

    (1)形状相似,输入小时,输出接近0;输入增大时,输出向1靠近。也就是说,当输入信号为重要信息时,阶跃函数和sigmoid函数都会输出较大的值;当输入信号为不重要的信息时,两者都输出较小的值。

    (2)输出信号值均在0~1之间。

    (3)两者都是非线性函数。阶跃函数是一条折线,sigmoid函数是一条曲线。实际上,神经网络的激活函数必须使用非线性函数,否则加深层的意义就没有了。对于线性函数而言,不管如何加深层,总存在与之等效的无隐藏层的神经网络。举个例子,激活函数h(x)=cx,把y(x)=h(h(x))的运算对应2层神经网络,显然y(x)=c·c·x=c2·x=ax(a= c2)。所以为了利用多层神经网络的优势,激活函数必须使用非线性函数。

Relu函数

    Sigmoid函数的使用历史比较久,现在主要流行ReLU(Rectified Linear Unit)函数,如下:

                                      

    式(7)表明,输入大于0,则直接输出该值;输入小于等于0时,输出0。Python实现也很简单,代码如下:

# 只给出函数,绘图代码同上

def relu(x):

    return np.maximum(0, x) #小于0的为0,大于0的为其本身

                              

本章剩余部分的内容一直采用sigmoid函数作为激活函数,在靠后的知识点中,才使用ReLU函数。

今天的内容就讲到这里了,希望读者好好回顾一下激活函数的产生及特点。下一篇知识点,将介绍使用numpy数组实现神经网络。欢迎读者订阅我的微信公众号“Python生态智联”,充分利用好零碎时间学AI

猜你喜欢

转载自blog.csdn.net/u012132349/article/details/86500526