美文网首页
浅层神经网络

浅层神经网络

作者: 小王子特洛伊 | 来源:发表于2020-01-26 13:34 被阅读0次

    神经网络的表示

    上图是只有一个隐藏层的神经网络,其中左侧为输入层,x_1,x_2,x_3 表示一个样本的 3 个特征,中间为隐藏层,表示 4 个隐藏单元,右侧为输出层,表示一个单元。在训练集中,输入层和输出层的数值是可以观察到的,而这些中间层的真实数值是看不到的,所以叫做隐藏层。

    输入样本 x 可以用 a^{[0]} 表示,这里的 a 也表示激活的意思,它意味着网络中不同层的值会传递给后面的层。输入层将 x 的值传递给隐藏层,我们将输入层的激活值,记为 a^{[0]}。隐藏层也会产生激活值,记为 a^{[1]}。第 l 层的第 i 个隐藏单元记为 a^{[l]}_i,图中隐藏层包括 4 个隐藏单元,所以 a^{[1]} 是一个 4 x 1 维的列向量,如下所示:
    a^{[1]}=\begin{bmatrix}a^{[1]}_1\\a^{[1]}_2\\ \vdots\\ a^{[1]}_4 \end{bmatrix}

    最后的输出层会产生一个实数 a^{[2]},这就是预测值 \hat y。当我们计算神经网络的层数时,不将输入层算作在内,通常将输入层称为第 0 层,所以上图是拥有一个隐藏层和一个输出层的双层神经网络。隐藏层和输出层都是带有参数的,这里的隐藏层有两个相关参数 w 和 b,记作w^{[1]},b^{[1]}。其中 w^{[1]}是一个 4 x 3 的矩阵,b^{[1]} 是一个 4 x 1 的向量,这里 4 代表隐藏层有 4 个隐藏单元,3 代表输入层有 3 个输入特征,1 代表输出层有 1 个隐藏单元。输出层的参数是 w^{[2]},b^{[2]},其中 w^{[2]} 是一个 1 x 4 的矩阵,b^{[2]} 是一个 1 x 1 的向量,即一个实数,4 代表隐藏层有 4 个隐藏单元,1 代表输出层有 1 个单元。

    神经网络输出的计算

    上图显示,一个隐藏单元代表了逻辑回归计算的两个步骤:首先计算出 z,然后再计算激活函数值 a。通常一个隐藏层包含多个隐藏单元,需要将特征分别输入到多个不同的隐藏单元进行计算:

    首先,第一个隐藏单元的计算过程,如下所示:

    第 1 步,计算:z^{[1]}_1=w^{[1]T}_1x+b^{[1]}_1,其中 x 包含 3 个特征,分别为 x_1, x_2, x_3。第 2 步计算:a^{[1]}_1=\sigma(z^{[1]}_1)。这和逻辑回归计算类似,接下来,第 2 个隐藏单元也执行相似计算:

    直到隐藏层所有单元计算完成,计算过程如下图所示:

    其中 w^{[1]}_i 是 3 x 1 维的向量,转置后为 1 x 3 维的向量,x 为 3 x 1 的向量,b^{[1]}_i 为一个实数,所以 w^{[1]T}_i x+b^{[1]}_i 的结果 z^{[1]}_i 是一个实数。如果利用循环,遍历所有隐藏单元进行计算,计算效率非常低下,所以我们应该将 4 个等式向量化。

    向量化计算

    可以把一个隐藏层的多个单元纵向堆叠起来构成列矩阵,直接计算隐藏层的所有隐藏单元。将第一个隐藏层的 4 个隐藏单元的 w 参数提取出来并转置,构成一个 4 x 3 维的矩阵 W^{[1]},将第一个隐藏层的 4 个隐藏单元的 b 参数提取出来构成一个 4 x 1 维的向量 b^{[1]},如下所示:
    W=\begin{bmatrix}w^{[1]T}_1\\w^{[1]T}_2\\w^{[1]T}_3\\w^{[1]T}_4 \end{bmatrix},x=\begin{bmatrix}x_1\\x_2\\x_3\end{bmatrix},b= \begin{bmatrix}b^{[1]}_1\\b^{[1]}_2\\b^{[1]}_3\\b^{[1]}_4\end{bmatrix}

    然后,直接计算得出隐藏层所有隐藏单元的预测值 z^{[1]},这是一个 4 x 1 的向量,其中第 i 个元素即第 i 个隐藏单元的计算结果 z^{[1]}_i,而z^{[1]}_i=w^{[1]T}_i x+b^{[1]}_i,这和非向量化计算的等式完全一致。计算过程如下所示:

    W^{[1]}\times x + b^{[1]}=\begin{bmatrix}w^{[1]T}_1\\w^{[1]T}_2\\w^{[1]T}_3\\w^{[1]T}_4 \end{bmatrix} \times \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}w^{[1]T}_1x+b^{[1]}_1\\w^{[1]T}_2x+b^{[1]}_2\\w^{[1]T}_3x+b^{[1]}_3\\w^{[1]T}_4x+b^{[1]}_4\end{bmatrix}= \begin{bmatrix}z^{[1]}_1\\z^{[1]}_2\\z^{[1]}_3\\z^{[1]}_4\end{bmatrix}=z^{[1]}

    接下来,需要将 sigmoid 函数作用到向量 z 的每个元素,得出每个隐藏单元的激活值,构成了 4 x 1 维的向量 a^{[1]}

    \sigma(z^{[1]})=\begin{bmatrix}\sigma(z^{[1]}_1)\\\sigma(z^{[1]}_2)\\\sigma(z^{[1]}_3)\\\sigma(z^{[1]}_4)\end{bmatrix}= \begin{bmatrix}a^{[1]}_1\\a^{[1]}_2\\a^{[1]}_3\\a^{[1]}_4\end{bmatrix}=a^{[1]}

    概况起来,一个样本在双层神经网络的向量化计算过程为:
    \begin{align}z^{[1]}=&W^{[1]}x+b^{[1]}\\ a^{[1]}=&\sigma(z^{[1]})\\ z^{[2]}=&W^{[2]}a^{[1]}+b^{[2]}\\ a^{[2]}=&\sigma(z^{[2]})\end{align}

    其中,隐藏层参数 W^{[1]} 是一个 4 x 3 维的矩阵,输入样本 x(即 a^{[0]})是一个 3 x 1 维的向量,隐藏层参数 b^{[1]} 是一个 4 x 1 维的向量,z^{[1]} 也是一个 4 x 1 维的向量,进行 sigmoid 激活后的隐藏层结果 a^{[1]} 也是一个 4 x 1 维的向量。输出层参数 W^{[2]} 是一个 1 x 4 维的矩阵,参数 b^{[2]} 是一个实数,z^{[2]} 也是一个实数,最后输出结果 a^{[2]} 也是一个实数。

    逻辑回归模型的假设函数为:\hat y=\sigma(w^Tx+b),可以将输出层参数 W^{[2]} 看作是逻辑回归模型中的参数 w^T,将输出层参数 b^{[2]} 看作逻辑回归模型中的参数 b,将隐藏层的激活值 a^{[1]} 看作逻辑回归中的输入 x,那么输出层的激活值 a^{[2]} 即为预测结果 \hat y

    以上通过向量化的四个等式,即完成了一个样本在双层神经网络的计算,前两个等式为隐藏层计算,后两个等式为输出层计算。

    多个样本的向量化计算

    我们知道了单个样本 x 计算预测值 \hat y 的过程,很容易想到可以利用循环来计算多个样本的预测值。可以用 a^{[2](i)} 来表示第 i 个样本在输出层的计算结果,那么 m 个样本的非向量化计算过程如下:

    为了提高计算效率,我们需要使用向量化计算。首先需要重新设计输入和参数结构,用 x^{(i)} 表示第 i 个样本,将输入层的 m 个样本 x^{(i)} 横向堆叠起来构成 n x m 维的输入矩阵 X,其中 n 为特征数。将隐藏层的 m 个计算结果 z^{[1](i)} 横向堆叠起来构成 4 x m 维的矩阵 Z^{[1]},将隐藏层 m 个激活函数计算结果 a^{[1](i)} 横向堆叠起来构成 4 x m 维的矩阵 A^{[1]},这里的 4 代表第一个隐藏层的单元数。Z^{[2]},A^{[2]}同理,矩阵 Z 和矩阵 A 的横向长度对应训练集样本数,纵向长度对应神经网络的中隐藏层的单元数。

    X=A^{[0]}=\begin{bmatrix}x^{(1)}&x^{(2)}&\cdots&x^{(m)}\end{bmatrix}\\ Z^{[1]}=\begin{bmatrix}z^{[1](1)}&z^{[1](2)}&\cdots&z^{[1](m)}\end{bmatrix}\\ A^{[1]}=\begin{bmatrix}a^{[1](1)}&a^{[1](2)}&\cdots&a^{[1](m)}\end{bmatrix}\\ Z^{[2]}=\begin{bmatrix}z^{[2](1)}&z^{[2](2)}&\cdots&z^{[2](m)}\end{bmatrix}\\ A^{[2]}=\begin{bmatrix}a^{[2](1)}&a^{[2](2)}&\cdots&a^{[2](m)}\end{bmatrix}

    多个样本的向量化计算公式为:
    \begin{align}Z^{[1]}=&W^{[1]}X+b^{[1]}\\ A^{[1]}=&\sigma(Z^{[1]})\\ Z^{[2]}=&W^{[2]}A^{[1]}+b^{[2]}\\ A^{[2]}=&\sigma(Z^{[2]})\end{align}

    Z^{[1]} 计算过程如下:
    \begin{align}W^{[1]}\times X+ b^{[1]}=&\begin{bmatrix}w^{[1](1)T}_1&\cdots&w^{[1](n_x)T}_1\\w^{[1](1)T}_2&\cdots&w^{[1](n_x)T}_2\\w^{[1](1)T}_3&\cdots&w^{[1](n_x)T}_3\\w^{[1](1)T}_4&\cdots&w^{[1](n_x)T}_4 \end{bmatrix} \times \begin{bmatrix}x^{(1)}&\cdots&x^{(m)}\end{bmatrix}+ \begin{bmatrix}b^{[1]}_1\\b^{[1]}_2\\b^{[1]}_3\\b^{[1]}_4\end{bmatrix}\\ =&\begin{bmatrix}w^{[1]T}_1x^{(1)}+b^{[1]}_1&\cdots&w^{[1]T}_1x^{(m)}+b^{[1]}_1\\w^{[1]T}_2x^{(1)}+b^{[1]}_2&\cdots&w^{[1]T}_2x^{(m)}+b^{[1]}_2\\w^{[1]T}_3x^{(1)}+b^{[1]}_3&\cdots&w^{[1]T}_3x^{(m)}+b^{[1]}_3\\w^{[1]T}_4x^{(1)}+b^{[1]}_4&\cdots&w^{[1]T}_4x^{(m)}+b^{[1]}_4\end{bmatrix}\\=&\begin{bmatrix}z^{[1](1)}_1&\cdots&z^{[1](m)}_1\\z^{[1](1)}_2&\cdots&z^{[1](m)}_2\\z^{[1](1)}_3&\cdots&z^{[1](m)}_3\\z^{[1](1)}_4&\cdots&z^{[1](m)}_4\end{bmatrix}=Z^{[1]}\end{align}

    将第 i 层的单元数记为 n_{li},将训练样本 x 的特征数记为 n_x。第一个隐藏层参数 W^{[1]}n_{l1}\times n_x 的矩阵,X 是 m 个样本横向堆叠构成的 n_x\times m 的矩阵,x^{(i)}n_x\times 1 的向量,b^{[1]}n_{l1}\times 1 的向量。所以在第 1 个隐藏层中,第 i 个样本的计算结果为 z^{[1](i)}=W^{[1]}x^{(i)}+b^{[1]},是一个n_l1\times 1的向量。第 1 个隐藏层 m 个样本的计算结果 Z^{[1]}n_{l1}\times m 的矩阵,后面 A^{[1]},Z^{[2]},A^{[2]} 同理。

    激活函数

    在神经网络中,我们可以选择隐藏层和输出层采用哪种激活函数,通常用 g^{[i]} 表示第 i 层的激活函数。

    sigmoid 激活函数,可以将预测值限制在 0-1 之间,作为预测分类概率,适合用于二元分类的输出层。

    tanh:a=\frac{e^z-e^{-z}}{e^z+e^{-z}}

    tanh 函数也叫双曲正切函数,在数学中实际上是 sigmoid 函数平移后的版本。激活函数使用 tanh 几乎总比 sigmoid 表现好。因为 tanh 函数输出值介于 -1 到 1 之间,输出的平均值更接近 0,有数据中心化的效果,而 sigmoid 函数输出值则更接近 0.5。除了在输出层,tanh 激活函数是比 sigmoid 激活函数更好的选择。

    tanh 函数和 sigmoid 函数都有一个缺点,当 z 非常大或非常小时,导数的梯度(斜率)会非常小,甚至接近 0,这将使梯度下降变得非常缓慢。

    ReLU:a=max(0,z)

    ReLU 是最常用的激活函数,叫做修正线性单元。根据公式,当 z > 0,导数为 1;当 z < 0,导数为 0;当 z = 0 时,导数未定义,但 z = 0 的概率很低,实际开发中,可以在 z = 0 时给导数设为 0 或 1。ReLU 激活函数的优点是,当 z > 0,一般来说激活函数的导数和 0 差很远,所以不会出现由于导数接近 0 而减慢学习速度的效应,这会使得梯度下降的速度快很多。ReLU 激活函数的缺点是,当 z 为负数,导数为 0,不过这也没什么太大问题。

    ReLU:a=max(0.01,z)

    ReLU还有一个版本叫做带泄漏的 ReLU,当 z < 0,导数不再为 0,而是有一个很平缓的斜率,这通常比 ReLU 激活函数更好,不过实际中使用的频率没有那么高,还是使用 ReLU 激活函数的更多。

    可以通过交叉验证集分别进行测试,从而选择效果最好的激活函数。

    为什么需要非线性激活函数

    如上图所示,我们尝试在神经网络中将激活函数去掉,在计算过程中,令 a^{[1]}=z^{[1]},a^{[2]}=z^{[2]},那么:
    \begin{align}a^{[1]}=&z^{[1]}=W^{[1]}x+b^{[1]}\\ a^{[2]}=&z^{[2]}=W^{[2]}a^{[1]}+b^{[2]}\end{align}

    a^{[1]} 带入到 a^{[2]} 中:
    \begin{align} a^{[2]}=&W^{[2]}(W^{[1]}x+b^{[1]})+b^{[2]}\\ =&(W^{[2]}W^{[1]})x+(W^{[2]}b^{[1]})+b^{[2]}\\ =&(W^{[2]}W^{[1]})x+(W^{[2]}b^{[1]}+b^{[2]})\\ =&W'x+b'\end{align}

    可以发现,x 的权重参数由 W^{[1]} 变为 W^{[2]}W^{[1]},记作 W',偏置参数由 b^{[1]} 变为 W^{[2]}b^{[1]}+b^{[2]},记作 b'。事实证明,如果使用线性激活函数或者不用激活函数,模型的输出 \hat y 不过是把输入线性组合后再输出。所以不论神经网络包括多少层,线性激活函数都不会起到作用,因为两个线性函数组合还是一个线性函数,和去掉所有隐藏层没有本质区别。

    如图所示,如果中间隐藏层为线性激活函数,这和没有任何隐藏层的标准逻辑回归是一样的,因为线性隐藏层没有任何作用。当然,如果要学习的是回归问题,可以在输出层使用线性激活函数,因为输出的预测值的取值范围是负无穷到正无穷,如果预测值一定大于 0 ,也可以在输出层使用 ReLU 激活函数,但解决分类问题时,隐藏单元还是不能用线性激活函数。

    激活函数的导数

    激活函数的导数可以表示为 \frac{dg(z)}{dz},也可以表示为 g'(z),在微积分中这个符号 ' 叫做 prime,表示函数 g 对输入变量 z 的导数。

    sigmoid 激活函数的导数:
    \frac{d}{dz}g(z)=\frac{1}{1+e^{-z}}(1-\frac{1}{1+e^{-z}})\\ =g(z)\cdot (1-g(z))

    z 越大,g(z) 越接近 1,所以 \frac{dg(z)}{dz}\approx 1\times(1-1)\approx 0 越接近0;
    z 越小,g(z) 越接近 0,所以\frac{dg(z)}{dz}\approx 0\times(1-0)\approx 0 越接近0;
    z = 0,g(z) = 0.5,所以 \frac{d}{dz}g(z)=0.5\times(1-0.5)=0.25

    g'(z) = a(1 - a),计算出 a 值后,可以快速计算出 g’(z)。

    tanh(z)=\frac{e^z-e^{-z}}{e^z+e^{-z}}

    tanh 激活函数的导数:
    g'(z)=\frac{dg(z)}{dz}=1-tanh(z)^2

    z 越大,g(z) 越接近 1,所以 \frac{d}{dz}g(z) \approx 1-1^2\approx 0 越接近 0;
    z 越小,g(z) 越接近 -1,所以 \frac{d}{dz}g(z) \approx 1-(-1)^2\approx 0 越接近 0;
    z = 0,g(z) = 0,所以 \frac{dg(z)}{dz}=1-0^2=1

    如果 a = g(z), g(z) = tanh(z),那么 g'(z)=1-a^2,计算出 a 值后,即可快速计算出 g'(z)。

    g(z)=max(0,z)

    ReLU 激活函数的导数:
    g'(z)=\begin{cases}0&z<0\\ 1&z>0\\ undefine&z=0 \end{cases}

    实际情况中,我们可以令 g'(0) = 1 或 g'(0) = 0,g'(0) 就是激活函数 g(z) 的次梯度,梯度下降仍然有效,但 z = 0 的概率非常小,所以 g'(0) 的值实际上并不重要。

    g(z)=max(0.01z,z)

    带泄漏的 ReLU 激活函数的导数:
    g'(z)=\begin{cases}0.01&z<0\\ 1&z>0\\ undefine&z=0 \end{cases}

    同样,可以令 g'(0) = 1 或 g'(0) = 0。

    神经网络的梯度下降

    图中双层神经网络中的参数为:W^{[1]},b^{[1]},W^{[2]},b^{[2]},通常 n_x(即 n^{[0]}) 表示输入层样本的特征数,n^{[1]} 表示隐藏层的单元数,n^{[2]} 表示输出层单元数。

    神经网络的代价函数为:
    J(W^{[1]},b^{[1]},W^{[2]},b^{[2]})=\frac{1}{m}\sum_{i=1}^mL(\hat y,y)

    L(\hat y,y) 表示损失函数,这里和标准逻辑回归的损失函数一样,即 \hat y=a^{[2]}

    通常梯度下降分为三个步骤:前向传播、反向传播以及迭代更新参数。首先通过前向传播计算每个样本的预测值 a^{[2]},向量化计算公式为:
    \begin{align}Z^{[1]}=&W^{[1]}X+b^{[1]}\\ A^{[1]}=&g^{[1]}(Z^{[1]})\\ Z^{[2]}=&W^{[2]}A^{[1]}+b^{[2]}\\ A^{[2]}=&g^{[2]}(Z^{[2]})\end{align}

    其中激活函数 g(z) 为 sigmoid 激活函数,W^{[1]}n^{[1]}\times n^{[0]} 维的矩阵,X 是 m 个样本横向堆叠构成的 n^{[0]}\times m 维的矩阵(n^{[0]}=n_x),b^{[1]} 是一个 n^{[1]}\times 1 维的向量,所以 Z^{[1]}n^{[1]}\times m 维的矩阵。W^{[2]}n^{[2]}\times n^{[1]} 维的矩阵,A^{[1]}n^{[1]}\times m 维的矩阵,b^{[2]}n^{[2]}\times 1 维的向量,因为这里 n^{[2]} = 1,所以 Z^{[2]} 是 1 x m 维的向量,A^{[2]} 就是 m 个样本预测值横向堆叠起来形成的 1 x m 维的向量,即 A^{[2]}=[\begin{smallmatrix}\hat y^{(1)}&\hat y^{(2)}&\cdots&\hat y^{(m)}\end{smallmatrix}]

    接下来,再通过反向传播计算各个参数的导数:dW^{[1]}=\frac{dJ}{dW^{[1]}},db^{[1]}=\frac{dJ}{db^{[1]}},W^{[2]}=\frac{dJ}{dW^{[2]}},db^{[2]}=\frac{dJ}{db^{[2]}},向量化计算公式为:
    \begin{align}dZ^{[2]}=&A^{[2]}-Y\\ dW^{[2]}=&\frac{1}{m}dZ^{[2]}A^{[1]T}\\ db^{[2]}=&\frac{1}{m}\text{np.sum($dZ^{[2]}$,axis=1,keepdim=True)}\\ dZ^{[1]}=&W^{[2]T}dZ^{[2]}*g^{[1]}{'}(Z^{[1]})\\ dW^{[1]}=&\frac{1}{m}dZ^{[1]}X^T\\ db^{[1]}=&\frac{1}{m}\text{np.sum($dZ^{[1]}$,axis=1,keepdim=True)}\end{align}

    其中,Y 是 m 个样本真实值横向堆叠起来形成的 1 x m 维的向量,Y=[\begin{smallmatrix}y^{(1)}&y^{(2)}&\cdots&y^{(m)}\end{smallmatrix}]dZ^{[2]} 是 1 x m 维的向量,A^{[1]T}m\times n^{[1]} 维的矩阵,所以 dW^{[2]}1\times n^{[1]} 维的矩阵,db^{[2]} 是 1 x 1 维的矩阵,即一个实数,W^{[2]T}n^{[1]}\times 1 维的矩阵,所以 W^{[2]T}dZ^{[2]}n^{[1]}\times m 维的矩阵,所以 dZ^{[1]}n^{[1]}\times m 维的矩阵,又 X^Tm\times n^{[0]} 维的矩阵,所以 dW^{[1]}n^{[1]}\times n^{[0]} 维的矩阵,db^{[1]}n^{[1]}\times 1 维的矩阵。这里利用 np.sum() 函数 axis = 1 进行水平相加求和,keepdims = True 是为防止 Python 输出秩为 1 的数组,确保输出的是矩阵。

    最后根据梯度下降公式,更新参数:
    W^{[1]}=W^{[1]}-\alpha\cdot dW^{[1]}\\ b^{[1]}=b^{[1]}-\alpha\cdot db^{[1]}\\ W^{[2]}=W^{[2]}-\alpha\cdot dW^{[2]}\\ b^{[2]}=b^{[2]}-\alpha\cdot db^{[2]}\\

    至此,已经完成了一次梯度下降迭代,需要不断重复迭代,更新参数,才能将代价函数收敛到最小值。

    反向传播的计算

    逻辑回归模型中,通常根据前向传播计算流程,利用反向传播来分步计算导数,先计算 da,接着计算 dz,最后计算 dw 和 db。

    损失函数为:L(a,y)=-y \cdot \log a-(1-y)\log(1-a)

    首先计算 da:da=\frac{dL}{da}=-\frac{y}{a}+\frac{1-y}{1-a}

    接着计算 dz:dz=\frac{dL}{da}\frac{da}{dz},又 a=\sigma(z)g(z)=\sigma(z)\frac{da}{dz}=\frac{dg(z)}{dz}=g'(z),所以 dz=da\cdot g'(z)=a-y

    最后计算 dw 和 db:dw=dz\cdot x,db=dz

    以上就是逻辑回归模型中单个样本的反向传播计算过程,这和双层神经网络很像,如下所示:

    前向传播的计算过程是:首先计算 z^{[1]},然后计算 a^{[1]},然后计算 z^{[2]}z^{[2]} 也取决于参数 W^{[2]}b^{[2]},然后从z^{[2]}出发,计算a^{[2]},最后得到损失函数。

    反向传播的计算过程是:向后推算出 da^{[2]},然后是 dz^{[2]},然后计算 dW^{[2]}db^{[2]},然后反向计算 da^{[1]}dz^{[1]},最后求出 dW^{[1]}db^{[1]}

    我们可以跳过显式计算 da^{[2]},直接计算 dz^{[2]},将两步计算合并成一步,直接得到 dz^{[2]}=a^{[2]}-ydW^{[2]}=dz^{[2]}a^{[1]T},和逻辑回归导数计算中 dw=dz\cdot x 类似,只不过这里的 x 变为 a^{[1]},还有一个额外的转置运算,因为逻辑回归中 w 是行向量,而神经网络中 W 是列向量。db^{[2]}=dz^{[2]}

    接下来需要计算 da^{[1]},然后计算dz^{[1]}。这里也可以将两步计算合并成一步,直接得到 dz^{[1]}=W^{[2]T}dz^{[2]}*g^{[1]'} (z^{[1]})

    最后 dW^{[1]}=dz^{[1]}\cdot x^Tdb^{[1]}=dz^{[1]}x^T 相当于 a^{[0]T}

    我们用 n^{[0]} 表示输入特征数,n^{[1]} 表示隐藏层单元数,n^{[2]} 表示输出层单元数。那么,W^{[2]}n^{[2]}\times n^{[1]} 维的矩阵,z^{[2]},dz^{[2]}n^{[2]}\times 1 维的向量,当做二元分类时,n^{[2]} = 1,就是 1 x 1 维,即一个实数。z^{[1]}dz^{[1]}n^{[1]}\times 1 维的向量,可以发现变量和变量导数的维度是一样的。整个计算过程,如下所示:

    反向传播的向量化计算

    在前向传播的向量化计算中,需要计算:z^{[1]}=w^{[1]}x+b^{[1]}a^{[1]}=g^{[1]}(z^{[1]}),我们把 z 横向堆叠起来形成行向量:Z^{[1]}=[\begin{smallmatrix}z^{[1](1)}&\cdots&z^{[1](m)}\end{smallmatrix}],从而得出如下向量化计算公式:
    \begin{align}Z^{[1]}=&W^{[1]}X+b^{[1]}\\ A^{[1]}=&g^{[1]}(Z^{[1]})\\ Z^{[2]}=&W^{[2]}A^{[1]}+b^{[2]}\\ A^{[2]}=&g^{[2]}(Z^{[2]})\end{align}

    反向传播也是如此,下图中,左侧为单个样本反向传播的计算过程,右侧为多个样本反向传播的向量化计算过程。

    首先计算 dZ^{[2]}=A^{[2]}-YdW^{[2]}=\frac{1}{m}dZ^{[2]}-A^{[1]T},这里 \frac{1}{m} 是由于代价函数是 m 个样本的平均损失,即 J=\frac{1}{m}\sum_{i=1}^mL(\hat y,y),接下来计算:
    \begin{align}db^{[2]}=&\frac{1}{m}\text{np.sum($dZ^{[2]}$,axis=1,keepdims=True)}\\ dZ^{[1]}=&W^{[2]T}dZ^{[2]}* g^{[1]}{'}(Z^{[1]})\end{align}

    其中 dZ^{[1]}n^{[1]}\times m 维矩阵,后面两项也是,两项逐个元素乘积。

    最后计算:
    \begin{align}dW^{[1]}=&\frac{1}{m}dZ^{[1]}X^T\\ db^{[1]}=&\frac{1}{m}\text{np.sum($dZ^{[1]}$,axis=1,keepdims=True)}\end{align}

    随机初始化权重

    逻辑回归中,我们可以将参数全部初始化为 0,但在神经网络中将参数全部初始化为 0 会导致梯度下降失效。

    假设输入层有两个输入特征,即 n^{[0]}=2,隐藏层有两个单元,即 n^{[1]}=2。那么和隐层相关的参数 W^{[1]} 就是一个 2 x 2 的矩阵,假设将其全部初始化为 0,将 b^{[1]} 也初始化为 0(实际上将偏置项 b 初始化为 0 是可行的,但将 w 初始化为 0 就有问题了),因为对于输入的任何样本,a^{[1]}_1a^{[1]}_2 是一样的。也就是说这两个激活函数完全一样,因为两个隐藏单元都在做完全一样的计算,当计算反向传播时,事实证明,出于对称性,dz^{[1]}_1dz^{[1]}_2 也是相同的,那么两个隐藏单元完全相同,这就是所谓的完全对称,我们通过归纳法证明,每次训练迭代之后,两个隐藏单元仍然在计算完全相同的函数,两个隐藏单元对输出单元的影响也是一样的,在一次迭代之后同样的对称性依然存在,两个隐藏单元仍然是对称的。无论尝试迭代多少次,都还是对称的。所以在这种情况下多个隐藏单元没有意义。当然对于更大的神经网络或者输入有 3 个特征,或者隐藏单元的数目非常多,如果把所有权重的初始化为 0,那所有隐藏单元都是对称的,不管运行多久梯度下降,它们的计算完全一样,所以没有任何意义。因为我们需要不同的隐藏单元去计算不同的函数。解决方案是随机初始化所有参数。
    \begin{align}W^{[1]}=&\text{np.random.rand((2,2))*0.01}\\ b^{[1]}=&\text{np.zero((2,1))}\\ W^{[2]}=&\text{np.random.rand((1,2))*0.01}\\ b^{[2]}=&\text{np.zeros((2,1))}\end{align}

    我们通常把权重初始化为非常小的随机值。因为如果使用 tanh 或者 sigmoid 激活函数,权重太大的话,当计算激活函数值时,很容易得出非常大或非常小的值,那么函数曲线会非常平缓,梯度的斜率非常小,梯度下降会变得非常慢。如果是深度神经网络,应该用0.001甚至更小。但参数 b 是没有对称性问题的。

    参考

    https://mooc.study.163.com/smartSpec/detail/1001319001.htm

    相关文章

      网友评论

          本文标题:浅层神经网络

          本文链接:https://www.haomeiwen.com/subject/bffkyctx.html