Page37页继续往下: 第三章:神经网络 上一章节里面,设定权重的工作、即确定合适的、能符合预期的输入与输出的权重,是由人工来设定的。神经网络就是为了解决这个人工设定的问题,具体地讲,神经网络的一个重要性质就是它可以自动地从数据中学习到合适的权重参数。 本章节先介绍神经网络的概要,再重点关注神经网络进行识别时的处理。第4章再介绍如何从数据中学习权重参数。从感知机到神经网络 1。1神经网络的例子: 用图来表示神经网络的话,最左边的一列是输入层、最右边的一列为输出层,中间一列为中间层,中间层有时候也称为隐藏层。隐藏层的神经元肉眼看不见。另外本书把输入层到输出层依次称为0层1层2层。(层号的目的是和python的序列对应)如下图,0对应输入层,1对应中间层,2对应输出层。 神经网络的例子 实际上就神经元的连接方式,和感知机没有任何差异。那么神经网络是怎么传递的呢? 3。1。2复习感知机 感知机接受x1和x2两个输入信号,输出y。如果用数据式来表示上图的感知机,则如下所示: 式3。1 b是被称为偏置函数的参数,用于控制神经元被激活的容易程度;而w1和w2是表示各个信号的权重的参数,用于控制各个信号的重要性。 如果要明确的在图中表示偏置b,可以像下图一样。由于偏置的输入信号一直是固定值,所以为了区别其它神经元,在图中把这个神经元涂成灰色。 现在将公式3。1改为更简洁的形式,用一个函数来表示分情况动作(超过0则输出1,否则输出0)。引入新函数h(x),将公式改为下面的公式3。2,和公式3。3 3。2 3。3 图33明确表示出偏置 3。1。3激活函数登场 刚才登场的h(x)函数会将输入信号的综合转换为输出信号,这种函数一般称为激活函数(activationfunction)。如激活一词所示,激活函数的作用在于决定如何来激活输入信号的总和。 明确显示激活函数的计算过程 如上图所示,表示神经元的0中明确显示了激活函数的计算过程,即加权总和为节点a,然后节点a被激活函数h()转换成节点y。这里我们称a和y为节点,其实它和之前所说的神经元含义相同。 激活函数是连接感知机和神经网络的桥梁。一般而言,朴素感知机是指单层网络,指的是激活函数使用了阶跃函数的模型,多层感知机是指神经网络,即使用sigmoid函数(后述)等平滑的激活函数的多层网络。 3。2激活函数 激活函数以阈值为界,一旦超过阈值,就切换输出,这样的函数称为阶跃函数,也就是说,在激活函数的众多候选函数中,感知机使用了阶跃函数。如果感知机使用了其它函数作为激活函数的话会怎么样呢?实际上,如果将激活函数从阶跃函数换成其他函数,就可以进入神经网络的世界了。 3。2。1sigmoid函数 神经网络中经常使用的一个激活函数就是式(3。6)表示的sigmoid函数。(sigmoidfunction) 3。6 神经网络中使用sigmoid函数作为激活函数、进行信号的转换,转换后的信号被传递给下一个神经元。 3。2。2阶跃函数的实现 我们试着用Python画出阶跃函数的图,如下所示,当超过0时,输出1,否则输出0 这个是实现简单,但是参数x只能接受实数(浮点数)。也就是说,允许stepfunction(3。0)的调用,单不允许参数取NumPy数组,例如stepfuntion(np。array(〔1。0,2。0〕)。为了便于后面的操作,我们把它修改为支持NumPy数组的实现: y。astype()方法转换NumPy数组的类型。Python将布尔函数转换为Int型后,True会转换为1,False会转换为0。 3。2。3阶跃函数的图形 使用matplotlib库来定义阶跃函数图形 阶跃函数的图形如下 36 阶跃函数以0为界,输出从0转化为1。它的数值呈阶梯式变化,所以称为阶跃函数。 3。2。4sigmoid函数的实现importnumpyasnpimportmatplotlib。pyplotaspltdefsigmoid(x):return1(1np。exp(x))xnp。arange(2,2,0。1)ysigmoid(x)plt。plot(x,y)plt。show() 上图实现 书中解释了,sigmoid()函数其实和np。array可以配合进行运算,因为NumPy数组支持广播功能,如果标量和Numpy数组之间进行运算,则标量会和NumPy数组的各个元素进行运算。 3。2。5sigmoid函数和阶跃函数的比较importnumpyasnpimportmatplotlib。pyplotaspltdefsigmoid(x):return1(1np。exp(x))defstepfunction(x):returnnp。array(x0,dtypenp。int)xnp。arange(5。0,5。0,0。1)ysigmoid(x)zstepfunction(x)plt。plot(x,y,labelsigmoid)plt。plot(x,z,linestyle,labelstep)plt。ylim(0。1,1。1)plt。lengend()plt。show() 这里stepfunction()以阶跃函数为参数,对数组的各个元素执行阶跃函数运算,并以数组形式返回运算结果,对数组y和z进行绘图,如上图所示。 观察上图,首先注意到平滑性不同,也就是说,感知机中神经元之间流动的是0或1的二元信号,而神经网络中流动的是连续的实数值信号。 阶跃函数就像竹筒敲石头一样,制作是否传输的两个动作,而sigmoid函数就像水车一样,根据流过来的数量相应调整传送出去的水量。 两个函数的共同性质是:不管输入信号有多小,或者多大,输出信号的值都在0和1之间。另外,输入小时,输出接近0,输入增大,输出向1靠近。 3。2。6非线性函数: 阶跃函数和sigmoid函数还有其它共同点,两者均为非线性函数,sigmoid函数是一条曲线,阶跃函数是一条像阶梯一样的折线,两者都算非线性的函数。 输出值时输入值的常数倍的函数称为线性函数(用数学式表示为h(x)cx,c为常数),线性函数是一条笔直的直线,而非线性函数,顾名思义,指的是不像线性函数那样呈现出一条直线的函数。 线性函数的问题是,不管如何加深层数,总是存在与之等效的无隐藏层的神经网络。为了具体的(稍微直观地)理解这一点,我们来思考下面这个简单的例子。 把y(x)h(h(h(x)))运算对应3层神经网络,这个运算会进行y(x)cccX的乘法运算,如这个例子所示,使用线性函数时,无法发挥多层网络带来的优势。为了发挥叠加层所带来的优势,激活函数必须使用非线性函数。 3。2。7ReLU函数 到目前为止,我们介绍了作为激活函数的阶跃函数和sigmoid函数。在神经网络发展的历史上,sigmoid函数很早就开始被使用了,而最近则主要使用ReLU(RectifiedLinearUnit)函数。 ReLU函数在输入大于0时,直接输出该数值;在输入小于等于0时,输出0。ReLU函数可以表示为下面的公式: 3。7 如下图所示,ReLU函数是一个非常简单的函数,因此,ReLU函数的实现也很简单,可以写成如下形式: 本章剩余部分使用sigmoid函数作为激活函数,但在本书的后半部分,主要使用ReLU函数。 ReLU函数 这里使用了NumPy的maximum函数,maximum函数会从输入的数值中选择较大的那个值进行输出。 看到page50,待继续。