深度学习:浅层神经网络与深度神经网络运算推导

之前学习机器学习的时候已经写了几篇有关神经网络的博客,最近看吴恩达深度学习的视频,其中的神经网络跟之前又有所不同,所以记个笔记。

基本结构与符号约定

在这里插入图片描述
基本结构还是输入层、隐藏层,中间层,激励用字母 a a a表示,单元的层标号放在方括号中,圆括号中为样本标号,所以有输入层 x x x a [ 0 ] a^{[0]} a[0])、隐藏层 a [ 1 ] a^{[1]} a[1]和输出层 a [ 2 ] a^{[2]} a[2]。运算过程中需要用到权重 w w w和偏置 b b b,单元内的函数仍然是逻辑函数 σ ( z ) = 1 1 + e − z \sigma(z)=\frac{1}{1+e^{-z}} σ(z)=1+ez1

声明数据矩阵 X ( n × m ) X(n\times m) X(n×m),权重矩阵 W [ l ] ( s l × s l − 1 ) W^{[l]}(s_l\times s_{l-1}) W[l](sl×sl1)和偏置矩阵 b [ l ] ( s l × 1 ) b^{[l]}(s_l\times 1) b[l](sl×1),激励矩阵 A [ l ] ( s l × m ) A^{[l]}(s_l\times m) A[l](sl×m) n [ l ] n^{[l]} n[l]表示第 l l l层的单元个数,令
A [ 0 ] = X = [ ∣ ∣ ∣ x ( 1 ) x ( 2 ) ⋯ x ( m ) ∣ ∣ ∣ ] , W [ l ] = [ − w 1 [ l ] T − − w 2 [ l ] T − ⋯ − w n [ l ] [ l ] T − ] , b [ l ] = [ b 1 [ l ] b 2 [ l ] ⋮ b n [ l ] [ l ] ] A^{[0]}=X=\left[\begin{matrix} |&|& &|\\ x^{(1)}&x^{(2)}&\cdots&x^{(m)}\\ |&|& &|\\ \end{matrix}\right], W^{[l]}=\left[\begin{matrix} -&w_1^{[l]T}&-\\ -&w_2^{[l]T}&-\\ &\cdots&\\ -&w_{n^{[l]}}^{[l]T}&-\\ \end{matrix}\right], b^{[l]}=\left[\begin{matrix} b^{[l]}_1\\ b^{[l]}_2\\ \vdots\\ b^{[l]}_{n^{[l]}}\\ \end{matrix}\right] A[0]=X=x(1)x(2)x(m),W[l]=w1[l]Tw2[l]Twn[l][l]T,b[l]=b1[l]b2[l]bn[l][l]

还有一些补充可见机器学习中的神经网络

向前传播

机器学习中的神经网络向量化推导打底,再加上向前传播比较简单,我们就直接上多组数据+多隐藏层的情况吧。

中间向量 z [ l ] z^{[l]} z[l]
z [ l ] = [ z 1 [ l ] z 2 [ l ] ⋮ z n [ l ] [ l ] ] = [ w 1 [ l ] T a [ l − 1 ] + b 1 [ l ] w 2 [ l ] T a [ l − 1 ] + b 2 [ l ] ⋮ w n [ l ] [ l ] T a [ l − 1 ] + b n [ l ] [ l ] ] = W [ l ] a [ l − 1 ] + b [ l ] z^{[l]}=\left[\begin{matrix} z^{[l]}_1\\ z^{[l]}_2\\ \vdots\\ z^{[l]}_{n^{[l]}}\\ \end{matrix}\right]= \left[\begin{matrix} w^{[l]T}_1a^{[l-1]}+b_1^{[l]}\\ w^{[l]T}_2a^{[l-1]}+b_2^{[l]}\\ \vdots\\ w^{[l]T}_{n^{[l]}}a^{[l-1]}+b_{n^{[l]}}^{[l]}\\ \end{matrix}\right]= W^{[l]}a^{[l-1]}+b^{[l]} z[l]=z1[l]z2[l]zn[l][l]=w1[l]Ta[l1]+b1[l]w2[l]Ta[l1]+b2[l]wn[l][l]Ta[l1]+bn[l][l]=W[l]a[l1]+b[l]
所以由 z [ l ] ( i ) z^{[l](i)} z[l](i)构成的矩阵 Z [ l ] Z^{[l]} Z[l]
Z [ l ] = [ ∣ ∣ ∣ z [ l ] ( 1 ) z [ l ] ( 2 ) ⋯ z [ l ] ( m ) ∣ ∣ ∣ ] = W [ l ] A [ l − 1 ] + b [ l ] Z^{[l]}=\left[\begin{matrix} |&|& &|\\ z^{[l](1)}&z^{[l](2)}&\cdots&z^{[l](m)}\\ |&|& &|\\ \end{matrix}\right]= W^{[l]}A^{[l-1]}+b^{[l]} Z[l]=z[l](1)z[l](2)z[l](m)=W[l]A[l1]+b[l]
而隐藏层的激励矩阵 A [ l ] A^{[l]} A[l]就是
A [ l ] = [ ∣ ∣ ∣ a [ l ] ( 1 ) a [ l ] ( 2 ) ⋯ a [ l ] ( m ) ∣ ∣ ∣ ] = σ ( Z [ l ] ) = σ ( W [ l ] A [ l − 1 ] + b [ l ] ) A^{[l]}=\left[\begin{matrix} |&|& &|\\ a^{[l](1)}&a^{[l](2)}&\cdots&a^{[l](m)}\\ |&|& &|\\ \end{matrix}\right]=\sigma(Z^{[l]}) =\sigma(W^{[l]}A^{[l-1]}+b^{[l]}) A[l]=a[l](1)a[l](2)a[l](m)=σ(Z[l])=σ(W[l]A[l1]+b[l])

其他激活函数

之前我们的神经网络都是沿用的逻辑回归使用的逻辑函数,但事实上在神经网络中有许多更好的选择。

tanh函数

tanh ⁡ ( z ) = e z − e − z e z + e − z \tanh(z)=\frac{e^z-e^{-z}}{e^z+e^{-z}} tanh(z)=ez+ezezez
图像如下:
在这里插入图片描述
tanh ⁡ \tanh tanh函数几乎是严格优越于逻辑函数,因为 tanh ⁡ \tanh tanh函数使得激励的平均值在0左右,这能让下一层的计算更轻松。除了在输出层,我们期望的是 0 ∼ 1 0\sim 1 01之间的输出,这时我们可以在输出层使用逻辑函数。

该函数的导数为
tanh ⁡ ′ ( z ) = 1 − ( tanh ⁡ ( z ) ) 2 \tanh'(z)=1-(\tanh(z))^2 tanh(z)=1(tanh(z))2

ReLU函数

不过逻辑函数和 tanh ⁡ \tanh tanh函数都有一个毛病,那就是在坐标的绝对值很大的时候,函数的梯度会变得非常小,这样我们在运行类似梯度下降的算法时收敛的速度就会变得很慢。而ReLU函数就可以解决这个问题,其表达式为
ReLU ( z ) = max ⁡ ( 0 , z ) \text{ReLU}(z)=\max(0,z) ReLU(z)=max(0,z)
图像为:
在这里插入图片描述
这样,只要 z > 0 z>0 z>0,导数就是1,而 z < 0 z<0 z<0时导数则是0。虽然从数学上 z = 0 z=0 z=0处并没有导数,但是 z z z值刚好为0的概率非常小,而且我们可以人为定义其为1或0,这在实际应用中无伤大雅。

一般来讲,如果要做一个二元分类问题,我们可能会使用 tanh ⁡ \tanh tanh函数,输出层再加一个逻辑函数,而在其他时候一般默认ReLU函数。

Leaky ReLU

在实际运用中,ReLU函数的表现通常很不错,但是因为它负数部分的导数为0,所以对于这部分它的梯度下降速率会很慢,尽管在一个网络中,我们会有很多正的部分,使参数整体仍以一个较快的速度学习。如果不放心,可以给负的部分也设置一个较小的斜率,比如 0.01 0.01 0.01,这样激活函数就表示为
Leaky ReLU ( z ) = max ⁡ ( 0.01 z , z ) \text{Leaky ReLU}(z)=\max(0.01z,z) Leaky ReLU(z)=max(0.01z,z)
在这里插入图片描述

向后传播

浅层神经网络

向后传播较复杂,我们先推一个浅层神经网络:
在这里插入图片描述
首先,对于最后一步代价函数,其值为
L ( a [ 2 ] , y ) = − y log ⁡ a [ 2 ] − ( 1 − y ) log ⁡ ( 1 − a [ 2 ] ) \mathcal{L}(a^{[2]},y)=-y\log a^{[2]}-(1-y)\log(1-a^{[2]}) L(a[2],y)=yloga[2](1y)log(1a[2])
a [ 2 ] a^{[2]} a[2]求微分,可得
d L d a [ 2 ] = − y a [ 2 ] + 1 − y 1 − a [ 2 ] \frac{d\mathcal{L}}{da^{[2]}}=-\frac{y}{a^{[2]}}+\frac{1-y}{1-a^{[2]}} da[2]dL=a[2]y+1a[2]1y
z [ 2 ] z^{[2]} z[2]对代价函数的微分为
d L d z [ 2 ] = d L d a [ 2 ] d a [ 2 ] d z [ 2 ] = ( − y a [ 2 ] + 1 − y 1 − a [ 2 ] ) a [ 2 ] ( 1 − a [ 2 ] ) = a [ 2 ] − y \frac{d\mathcal{L}}{dz^{[2]}}=\frac{d\mathcal{L}}{da^{[2]}}\frac{d a^{[2]}}{dz^{[2]}}=(-\frac{y}{a^{[2]}}+\frac{1-y}{1-a^{[2]}})a^{[2]}(1-a^{[2]})=a^{[2]}-y dz[2]dL=da[2]dLdz[2]da[2]=(a[2]y+1a[2]1y)a[2](1a[2])=a[2]y
之后计算 d L d W [ 2 ] \frac{d\mathcal{L}}{dW^{[2]}} dW[2]dL d L d b [ 2 ] \frac{d\mathcal{L}}{db^{[2]}} db[2]dL
d L d W [ 2 ] = d L d z [ 2 ] a [ 1 ] T d L d b [ 2 ] = d L d z [ 2 ] \frac{d\mathcal{L}}{dW^{[2]}}=\frac{d\mathcal{L}}{dz^{[2]}}a^{[1]T}\\ \frac{d\mathcal{L}}{db^{[2]}}=\frac{d\mathcal{L}}{dz^{[2]}} dW[2]dL=dz[2]dLa[1]Tdb[2]dL=dz[2]dL
现在推导已经完成了一半了,我们再计算 a [ 1 ] a^{[1]} a[1]的导数为
d L d a [ 1 ] = W [ 2 ] T d L d z [ 2 ] \frac{d\mathcal{L}}{da^{[1]}}=W^{[2]T}\frac{d\mathcal{L}}{dz^{[2]}} da[1]dL=W[2]Tdz[2]dL
因为 z [ 2 ] z^{[2]} z[2] n [ 2 ] × 1 n^{[2]}\times 1 n[2]×1的, W [ 2 ] W^{[2]} W[2] n [ 2 ] × n [ 1 ] n^{[2]}\times n^{[1]} n[2]×n[1]的,所以这里需要转置一下。之后,再求对于 z [ 1 ] z^{[1]} z[1]的导数,只需要在此基础之上乘上 d a [ 1 ] d z [ 1 ] \frac{d a^{[1]}}{dz^{[1]}} dz[1]da[1] ∗ * 表示按位相乘):
d L d z [ 1 ] = W [ 2 ] T d L d z [ 2 ] ∗ g [ 1 ] ′ ( z [ 1 ] ) \frac{d\mathcal{L}}{dz^{[1]}}=W^{[2]T}\frac{d\mathcal{L}}{dz^{[2]}}*g^{[1]'}(z^{[1]}) dz[1]dL=W[2]Tdz[2]dLg[1](z[1])
而计算 d L d W [ 1 ] \frac{d\mathcal{L}}{dW^{[1]}} dW[1]dL d L d b [ 1 ] \frac{d\mathcal{L}}{db^{[1]}} db[1]dL的过程与第2层几乎一模一样:
d L d W [ 1 ] = d L d z [ 1 ] a [ 0 ] T d L d b [ 1 ] = d L d z [ 1 ] \frac{d\mathcal{L}}{dW^{[1]}}=\frac{d\mathcal{L}}{dz^{[1]}}a^{[0]T}\\ \frac{d\mathcal{L}}{db^{[1]}}=\frac{d\mathcal{L}}{dz^{[1]}} dW[1]dL=dz[1]dLa[0]Tdb[1]dL=dz[1]dL
以上推导都是针对单个样本的,要对多个样本进行向后传播,将样本列向量按列堆叠在一起,就可以套用上面推导的结果,其实就是所有 n [ l ] × 1 n^{[l]}\times1 n[l]×1的矩阵变成了 n [ l ] × m n^{[l]}\times m n[l]×m,然后 b b b向量需要在水平方向求和一次(为了简化表达,我们用 d Z [ 2 ] dZ^{[2]} dZ[2]表示矩阵 Z [ 2 ] Z^{[2]} Z[2]对代价函数求导的结果,其他矩阵同理):
d Z [ 2 ] = ( A [ 2 ] − Y ) d W [ 2 ] = 1 m d Z [ 2 ] A [ 1 ] T d b [ 2 ] = 1 m n p . s u m ( d Z [ 2 ] , a x i s = 1 , k e e p d i m s = T r u e ) d Z [ 1 ] = W [ 2 ] T d Z [ 2 ] ∗ g [ 1 ] ′ ( Z [ 1 ] ) d W [ 1 ] = 1 m d Z [ 1 ] X T d b [ 1 ] = 1 m n p . s u m ( d Z [ 1 ] , a x i s = 1 , k e e p d i m s = T r u e ) \begin{aligned} &dZ^{[2]}=(A^{[2]}-Y)\\ &dW^{[2]}=\frac{1}{m}dZ^{[2]}A^{[1]T}\\ &db^{[2]}=\frac{1}{m}np.sum(dZ^{[2]},axis=1,keepdims=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}np.sum(dZ^{[1]},axis=1,keepdims=True)\\ \end{aligned} dZ[2]=(A[2]Y)dW[2]=m1dZ[2]A[1]Tdb[2]=m1np.sum(dZ[2],axis=1,keepdims=True)dZ[1]=W[2]TdZ[2]g[1](Z[1])dW[1]=m1dZ[1]XTdb[1]=m1np.sum(dZ[1],axis=1,keepdims=True)keepdims的作用是让Python不要将我们的列向量(n,1)变成秩为1的矩阵(n,),那可能导致难以发现的bug。

深度神经网络

上面的浅层网络只有两层,而对于复杂的问题,增加网络的层数(深度)比强制在一个隐藏层中添加节点要有效得多,所以就需要将上面的推导化为更一般的形式,即下面这四个公式:
d Z [ l ] = d A [ l ] ∗ g [ l ] ′ ( Z [ l ] ) d W [ l ] = 1 m d Z [ l ] A [ l − 1 ] T d b [ l ] = 1 m n p . s u m ( d Z [ l ] , a x i s = 1 , k e e p d i m s = T r u e ) d A [ l − 1 ] = W [ l ] T d Z [ l ] \begin{aligned} &dZ^{[l]}=dA^{[l]}*g^{[l]'}(Z^{[l]})\\ &dW^{[l]}=\frac{1}{m}dZ^{[l]}A^{[l-1]T}\\ &db^{[l]}=\frac{1}{m}np.sum(dZ^{[l]},axis=1,keepdims=True)\\ &dA^{[l-1]}=W^{[l]T}dZ^{[l]} \end{aligned} dZ[l]=dA[l]g[l](Z[l])dW[l]=m1dZ[l]A[l1]Tdb[l]=m1np.sum(dZ[l],axis=1,keepdims=True)dA[l1]=W[l]TdZ[l]
初始的输入 d A [ L ] dA^{[L]} dA[L]由输出节点的激励函数决定,对于 m m m组样本,其值为
d A [ L ] = [ d L d a [ L ] ( 1 ) d L d a [ L ] ( 2 ) ⋯ d L d a [ L ] ( m ) ] dA^{[L]}=\left[\begin{matrix} \frac{d\mathcal{L}}{da^{[L](1)}}&\frac{d\mathcal{L}}{da^{[L](2)}}&\cdots&\frac{d\mathcal{L}}{da^{[L](m)}} \end{matrix}\right] dA[L]=[da[L](1)dLda[L](2)dLda[L](m)dL]

由上面的公式,我们就可以做到输入 d A [ l ] dA^{[l]} dA[l],输出 d A [ l − 1 ] dA^{[l-1]} dA[l1],同时计算每一层的权值和偏置的梯度。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值