• 【深度学习】单隐层神经网络


    logistic回归中只包含了简单的输入层和输出层,而神经网络往往更复杂会由很多的隐藏层来组成,下面先来看看单隐藏层神经网络。

    目录

    神经网络:

    神经网络的计算:

    激活函数:

     梯度下降与求导运算:

    参数随机初始化:


    神经网络:

    与之前的单层模型不同,神经网络可以有多个隐藏层。输入层的样品会向隐藏层中的每一个单元(下图四个)传递数据,也就是单个样品的特征值。然后四个单元又会接收并且处理来自输入层的数据后将数据传递给输出层。其中每一层会有对应的激活函数,我们将每一层输出给下一层的数据记为a_{n},对应下图我们将输入层输出给下一层的数据记为a0,隐藏层输出给输出层的数据记为a_{1},而输出层输出的数据就是a_{2}。值得注意的是,我们记神经网络的层数通常是计算隐藏层和输出层的和,而不计算输入层的层数。所以下图的神经网络层数是2。

    神经网络的计算:

    节点运算:

    对于类似上图的神经网络,它的计算方式和之前的logistic模型的计算方式类似:如果我们将隐藏层的每一个结点都看作是计算一次logistic模型,那么这个神经网络就可以看作是这些模型的组合。

     此时隐藏层的各个节点单元的计算都可以类比成多个相异的logistic模型重复计算4次并且进行叠加:

    看到这里4组函数,我们很自然考虑到不使用for循环遍历n个结点计算,而是选择矩阵运算,将隐藏层这4个结点的数据向量化运算。这就需要从输入层输出的a_{0}进行考虑了。我们可以将a_{0}定义为一个列为特征值大小的向量,然后再定义一个W矩阵,矩阵的行数为结点的个数,矩阵的列数为特征值的大小。即\begin{bmatrix} - &w^{[1]T}_{1} &- \\ -& w^{[1]T}_{2}& -\\ -& w^{[1]T}_{3}&- \\ -& w^{[1]T}_{4}&- \end{bmatrix} \begin{bmatrix} x_{1}\\ x_{2}\\ x_{3} \end{bmatrix}+\begin{bmatrix} b^{[1]}_{1}\\ b^{[1]}_{2}\\ b^{[1]}_{3} \\ b^{[1]}_{4}\end{bmatrix} = \begin{bmatrix} z^{[1]}_{1}\\ z^{[1]}_{2}\\ z^{[1]}_{3} \\ z^{[1]}_{4}\end{bmatrix},这样我们就可以得到一个用向量化运算并且将隐藏层的z都综合到一起的矩阵了。我们可以将其简写为:Z^{[1]} = W^{[1]}x+b^{[1]}

    多样本运算:

    刚刚我们说的还只是针对单个样本的情况,对应于多个样本的输出,我们只需要针对输入方式进行一定程度上的改变即可。具体来说是对每一个层的输出都进行横向的矩阵构建,例如在输入层,我们得到的是m个样本,每个样本有n个特征值,那么我们就构建一个n行m列的矩阵输出给隐藏层。当我们在隐藏层参与运算完后,现针对每一个样本我们都会得到一个n x 1的向量z,这时候针对每一个样本的向量,我们可以将其类似于之前的X一样横向叠加在一起形成一个n x m的矩阵。具体来说多样本就是将\begin{bmatrix} - &w^{[1]T}_{1} &- \\ -& w^{[1]T}_{2}& -\\ -& w^{[1]T}_{3}&- \\ -& w^{[1]T}_{4}&- \end{bmatrix} \begin{bmatrix} x_{1}\\ x_{2}\\ x_{3} \end{bmatrix}+\begin{bmatrix} b^{[1]}_{1}\\ b^{[1]}_{2}\\ b^{[1]}_{3} \\ b^{[1]}_{4}\end{bmatrix} = \begin{bmatrix} z^{[1]}_{1}\\ z^{[1]}_{2}\\ z^{[1]}_{3} \\ z^{[1]}_{4}\end{bmatrix}变成:\begin{bmatrix} - &w^{[1]T}_{1} &- \\ -& w^{[1]T}_{2}& -\\ -& w^{[1]T}_{3}&- \\ -& w^{[1]T}_{4}&- \end{bmatrix}\begin{bmatrix} x^{(1)}_{1} &x^{(2)}_{1} &x^{(3)}_{1} \\ x^{(1)}_{2} &x^{(2)}_{2} &x^{(3)}_{2} \\ x^{(1)}_{3} &x^{(2)}_{3} &x^{(3)}_{3} \end{bmatrix}+\begin{bmatrix} b^{[1]}_{1}\\ b^{[1]}_{2}\\ b^{[1]}_{3} \\ b^{[1]}_{4}\end{bmatrix} = \begin{bmatrix} z^{[1](1)}_{1}&z^{[1](2)}_{1}&z^{[1](3)}_{1}\\ z^{[1](1)}_{2}&z^{[1](2)}_{2}&z^{[1](3)}_{2}\\ z^{[1](1)}_{3}&z^{[1](2)}_{3}&z^{[1](3)}_{3} \\ z^{[1](1)}_{4}&z^{[1](2)}_{4}&z^{[1](4)}_{4}\end{bmatrix}

    这样我们的每一个层输出是一个列为样本数的矩阵。这样我们对于m个样本的数据集,就不需要进行for'循环遍历,可以直接利用矩阵运算来快速获取数据。

    激活函数:

    在深度学习中,我们常见的激活函数有很多,但是这些激活函数一般都是非线性的激活函数,要是我们使用线性的激活函数,那么我们的隐藏层就没有意义了,因为这样无论怎么算都是线性函数的组合而已,不能达到表示更多函数的作用。下面列举几个常见的非线性激活函数:

    1、sigmoid函数:

    这个函数常用于二分类的输出层,因为它的因变量范围是从0-1,所以它可以很好的去代表我们常见的二分类问题。它的解析式是y=\frac{1}{1+e^{-x}},它的导数是:\frac{1}{1+e^{-x}}(1-\frac{1}{1+e^{-x}})

    2、ReLU函数:

    这个函数是最常用于隐藏层的函数,它有一个很大的优点,那就是当它自变量大于0的时候,它的斜率是1,这就代表着当我们使用梯度下降时,它的下降速度可以很快。它的解析式是:y=max(0,z) ,它的导数是:\left\{\begin{matrix} 0 (x<0)\\ 1(x>0)\\ undef(x=0) \end{matrix}\right.,事实上,因为ReLU函数很难取到x为0,所以我们可以将0处的导数设为任意值,为了让这个函数可以一直可导。

    3、tanh函数:

    这个函数是用于拓展sigmoid函数的,弥补了sigmoid函数输出范围是0-1的缺点,它的因变量的范围是-1到1,这样它均值就靠近0,对于下一个隐藏层处理数据很有好处。它的解析式是:y=exexex+exy=exexex+ex,它的导数是:1(exexex+ex)21(exexex+ex)2

     梯度下降与求导运算:

    单隐藏层神经网络

     首先我们来看一下dz[2]dW[2]da[2]db[2]。这里因为da[2]dz[2]的导数维度相似,所以这里我们只计算dz[2]。这里dz[2]类似于logistic回归里的dz,它的导数相似地是a[2]y;而dW[2]的导数为:dz[2]a[1]T。这里的形式与logistic里的dW不同,因为之前的W是一个行向量,而当这里只有一个样本是,我们可以将dW[2]看成是一个列向量,所以对比于之前会将整个式子两边会有一个转置,而db[2]也类似可以求得dz[2]。类似地我们可以求得其它参数的导数:

    单样本多样本(z横向堆叠)
    dz[2]=a[2]ydZ[2]=A[2]Y
    dW[2]=dz[2]a[1]TdW[2]=1mdZ[2]A[1]T
    db[2]=dz[2]db[2]=1mnp.sum(dZ[2],axis=1,keepdims=True)
    dz[1]=W[2]Tdz[2]g[1](z[1])dZ[1]=W[2]TdZ[2]g[1](Z[1])
    dW[1]=dz[1]xTdW[1]=dZ[1]XT
    db[1]=dz[1]db[1]=1mnp.sum(dZ[1],axis=1,keepdims=True)

    参数随机初始化:

    我们在logistic回归里将w和b都初始化为0,但是到了这里就不能将w都初始化为0了,因为当我们在计算隐藏层时,如果每一个节点单元的w都同样为0,那么这就代表着每一个结点的参数都是对称,这样无论你设置多少个结点,最终的工作效果是每个结点输出都是一样的,并且反向传播时,每一个节点的z求导的结果都是一样的,所有的节点都在进行同样的运算,所有节点等分影响下一层。所以我们应该将w随机初始化,一般来说是利用随机矩阵生成的函数来生产随机矩阵,并且在末尾乘上0.01,这样就能保证一开始w的位置是位于比较接近0的位置,这样的话便于梯度下降。因为如果我们一开始取得w过大,势必会导致z过大,从而导致a过大。如果我们使用sigmoid函数,那么会导致a位于比较靠后的地方,如果是这样,那么我们求导时势必会获得较小的斜率,从而梯度下降会花很多的时间,造成反向优化时间过长。

    因为如sigmoid函数,当它的W很大或者很小时,它的导数几乎为0。但是这也不是绝对就乘0.01的,需要看具体情况而定。


    参考资料:

    3.1 神经网络概览_哔哩哔哩_bilibili

  • 相关阅读:
    redis
    计算机网络五层协议的体系结构
    python+opencv+深度学习实现二维码识别 计算机竞赛
    【go微服务】protobuf中oneof、WrapValue和FieldMask的使用
    什么是PDF转换器?很少有人知道的方法
    spring boot + vue 前后端下载文件文件
    Impala优化,并发性能问题,压测
    docker mysql 容器中执行mysql脚本文件并解决乱码
    Android BitmapUtil图片工具类
    电脑病毒感染C卷(Java&&Python&&C++&&Node.js&&C语言)
  • 原文地址:https://blog.csdn.net/m0_61151031/article/details/126375724