神经网络的梯度消失和梯度爆炸问题(一):反向传播——公式推导+示例说明

本文主要为大家解释一下神经网络的反向传播,为神经网络的梯度消失和梯度爆炸问题做一个铺垫。

目录

 

一、Sigmoid函数

二、反向传播

2.1前向传播

2.2误差计算

2.3反向传播

2.4权重更新

2.5误差再次计算

2.6权重更新的标量计算方法

三、总结


一、Sigmoid函数

本文后面所用的神经网络激活函数全部将会是sigmoid函数,它可以将变量映射到0,1之间。它的表达式为:

以及sigmoid的导函数为:

曲线为

二、反向传播

首先声明一下,为了简化公式的推导,所有的神经元会省略掉截距b。

已知:输入X=\begin{bmatrix} 0.05\\ 0.15\end{bmatrix}    输出 Y=\begin{bmatrix} 0.1\\ 0.9\end{bmatrix}  第一层的权重 W_{1}=\begin{bmatrix} \omega_{1} & \omega_{3}\\ \omega_{2} & \omega_{4} \end{bmatrix}=\begin{bmatrix} 0.13 & 0.15\\ 0.12& 0.20\end{bmatrix} 

           第二层的权重为W_{2}=\begin{bmatrix} \omega_{5} & \omega_{7}\\ \omega_{6} & \omega_{8} \end{bmatrix}=\begin{bmatrix} 0.40 & 0.25\\ 0.30& 0.20\end{bmatrix},损失函数为L=\frac{1}{2}\begin{Vmatrix} Y-S(W_{2}*S(W_{1}*X)) \end{Vmatrix}^{2}

注:损失函数的中后面减的一部分是神经网络的输出(省略了常数项b),S(.)表示激活函数sigmoid

2.1前向传播

S(W_{2}*S(W_{1}*X))=S(W_{2}*S(\begin{bmatrix} 0.13 &0.15 \\ 0.12&0.20 \end{bmatrix}\begin{bmatrix} 0.05 \\ 0.15 \end{bmatrix}))=S(W_{2}*S(\begin{bmatrix} 0.029 \\ 0.036 \end{bmatrix}))=S(W_{2}*\begin{bmatrix} 0.50725 \\ 0.50900 \end{bmatrix})=S(\begin{bmatrix} 0.33015 \\ 0.25397 \end{bmatrix})=\begin{bmatrix} 0.581796 \\ 0.563155 \end{bmatrix}

上面的结果就是前向传播输出的结果,可能有人会问向量是怎么激活的,其实很简单,比如最后一步:S(0.33015)=0.581796

S(0.25397)=0.563155,就是这样个算个的就可以了。

2.2误差计算

本例中损失函数采用均方误差。

L=\frac{1}{2}\begin{Vmatrix} Y-S(W_{2}*S(W_{1}*X)) \end{Vmatrix}^{2}=\frac{1}{2}\begin{Vmatrix} \begin{bmatrix} 0.1\\ 0.9 \end{bmatrix}- \begin{bmatrix} 0.581796\\ 0.563155 \end{bmatrix} \end{Vmatrix}^{2}=0.274635

2.3反向传播

W_{2}更新权重:

\frac{\partial L}{\partial W_{2}}

 

\tiny =\frac{\partial \frac{1}{2}\begin{Vmatrix} Y-S(W_{2}*S(W_{1}*X)) \end{Vmatrix}^{2}}{\partial W_{2}}

 

\tiny = 2*\frac{1}{2}*(Y-S(W_{2}*S(W_{1}*X)))*(-1)*\frac{\partial S(W_{2}*S(W_{1}*X))}{\partial W_{2}}

 

\tiny = 2*\frac{1}{2}*(Y-S(W_{2}*S(W_{1}*X)))*(-1)*\frac{\partial S(W_{2}*S(W_{1}*X))}{\partial W_{2}*S(W_{1}*X)}*\frac{\partial W_{2}*S(W_{1}*X)}{\partial W_{2}}

 

\tiny = 2*\frac{1}{2}*(Y-S(W_{2}*S(W_{1}*X)))*(-1)*\frac{\partial S(W_{2}*S(W_{1}*X))}{\partial W_{2}*S(W_{1}*X)}*(S(W_{1}*X))T

 

\tiny = 2*\frac{1}{2}*(Y-S(W_{2}*S(W_{1}*X)))*(-1)*(S(W_{2}*S(W_{1}*X)))^T*(I-S(W_{2}*S(W_{1}*X)))*(S(W_{1}*X))^T

 

\tiny = -(Y-S(W_{2}*S(W_{1}*X)))*S(W_{2}*(S(W_{1}*X)))^T*(I-S(W_{2}*S(W_{1}*X)))*(S(W_{1}*X))^T

上面的公式推导看上去十分的庞大,但是千万别被它给吓倒,其实就是很简单的链式求导,另外在最后一步直接使用了前面sigmoid的导函数,可以参见第一部分,I是一个元素全为‘1’的向量。

同理可以得到:

\frac{\partial L}{\partial W_{1}}

 

\tiny =\frac{\partial \frac{1}{2}\begin{Vmatrix} Y-S(W_{2}*S(W_{1}*X)) \end{Vmatrix}^{2}}{\partial W_{1}}

 

\tiny =-W_{2}*(Y-S(W_{2}*S(W_{1}*X)))*(S(W_{2}*S(W_{1}*X)))^T*(I-S(W_{2}*S(W_{1}*X)))*(S(W_{1}*X))^T*(I-S(W_{1}*X))*X^T

 

\tiny =W_{2}*\frac{\partial L}{\partial W_{2}}*(I-S(W_{1}*X))*X^T

我们将我们的所有数值代进去可得

\frac{\partial L}{\partial W_{2}}=\begin{bmatrix} 0.11958562 &0.11999819 \\ -0.08360763&-0.08389607 \end{bmatrix}

\frac{\partial L}{\partial W_{1}}=\begin{bmatrix} 0.00132702 &0.00398105 \\ 0.00094377&0.0028313 \end{bmatrix}

注:所有的运算中间过程省略,由于本人在运算时存在位数保留问题,所以结果可能会存在偏差。

2.4权重更新

本例中学习率采用\eta=0.5,梯度下降法。更新公式为:

W=W-\eta \frac{\partial L}{\partial W}

那么有:

W_{2}=W_{2}-\eta \frac{\partial L}{\partial W_{2}}=\begin{bmatrix} 0.34020719 &0.190009 \\ 0.34180382 &0.24194804 \end{bmatrix}

 

W_{1}=W_{1}-\eta \frac{\partial L}{\partial W_{1}}=\begin{bmatrix} 0.12933649 &0.14800948 \\ 0.11952812&0.19858435 \end{bmatrix}

2.5误差再次计算

L=\frac{1}{2}\begin{Vmatrix} Y-S(W_{2}*S(W_{1}*X)) \end{Vmatrix}^{2}=0.16227459<0.274635

通过一次反向传播之后,误差顺利减小。

2.6权重更新的标量计算方法

在这里就不再一步一步推导公式,推公式确实比较麻烦,给大家一个用标量计算的链接:https://www.cnblogs.com/charlotte77/p/5629865.html

三、总结

反向传播其实就是一个以减小误差为目的,以各种梯度优化方法为手段的不断迭代的一个过程。本文只是一个非常简单的例子,希望可以帮助大家理解它,有了这个基础,接下来,我会为大家介绍梯度消失和梯度爆炸,下篇见。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
反向传播算法(Backpropagation)是一种用于训练神经网络的常见优化算法。它通过计算损失函数相对于每个参数的梯度,并使用梯度下降来更新参数。下面我将给出反向传播算法的公式推导示例代码。 1. 反向传播算法公式推导: 首先,定义神经网络的损失函数为L,该函数是由网络输出和真实标签之间的差异计算得出。假设神经网络有多个隐藏层,每个隐藏层的参数为W和b。 1.1 前向传播: 首先,我们通过前向传播计算每一层的输出值。假设输入为x,第l层的输出为a[l],则有: a = x z[l] = W[l] * a[l-1] + b[l] a[l] = g(z[l]) 其中,g()是激活函数。 1.2 反向传播: 接下来,我们需要计算损失函数相对于每个参数的梯度,然后使用梯度下降更新参数。假设我们有L层神经网络,则有以下公式: 输出层的梯度: dz[L] = dL / da[L] * g'(z[L]) 隐藏层的梯度: dz[l] = (W[l+1]的转置 * dz[l+1]) * g'(z[l]) 参数梯度: dW[l] = dz[l] * a[l-1的转置] db[l] = dz[l] 更新参数: W[l] = W[l] - learning_rate * dW[l] b[l] = b[l] - learning_rate * db[l] 其中,dL / da[L]是损失函数对输出层输出的导数,g'()是激活函数的导数。 2. 反向传播算法示例代码: 下面是一个使用反向传播算法进行训练的示例代码: ```python # 假设网络有三个隐藏层 hidden_layers = [10, 20, 30] output_size = 2 # 初始化参数 parameters = {} layers_dims = [input_size] + hidden_layers + [output_size] L = len(layers_dims) - 1 for l in range(1, L + 1): parameters['W' + str(l)] = np.random.randn(layers_dims[l], layers_dims[l-1]) * 0.01 parameters['b' + str(l)] = np.zeros((layers_dims[l], 1)) # 前向传播 def forward_propagation(X, parameters): caches = [] A = X for l in range(1, L): Z = np.dot(parameters['W' + str(l)], A) + parameters['b' + str(l)] A = sigmoid(Z) cache = (Z, A) caches.append(cache) Z = np.dot(parameters['W' + str(L)], A) + parameters['b' + str(L)] AL = softmax(Z) cache = (Z, AL) caches.append(cache) return AL, caches # 反向传播 def backward_propagation(AL, Y, caches): grads = {} dZ = AL - Y m = AL.shape[1] grads['dW' + str(L)] = 1/m * np.dot(dZ, caches[-1][1].T) grads['db' + str(L)] = 1/m * np.sum(dZ, axis=1, keepdims=True) for l in reversed(range(1, L)): dA_prev = np.dot(parameters['W' + str(l+1)].T, dZ) dZ = dA_prev * sigmoid_derivative(caches[l-1][0]) grads['dW' + str(l)] = 1/m * np.dot(dZ, caches[l-1][1].T) grads['db' + str(l)] = 1/m * np.sum(dZ, axis=1, keepdims=True) return grads # 参数更新 def update_parameters(parameters, grads, learning_rate): for l in range(1, L+1): parameters['W' + str(l)] -= learning_rate * grads['dW' + str(l)] parameters['b' + str(l)] -= learning_rate * grads['db' + str(l)] return parameters # 训练模型 def train_model(X, Y, learning_rate, num_iterations): for i in range(num_iterations): AL, caches = forward_propagation(X, parameters) cost = compute_cost(AL, Y) grads = backward_propagation(AL, Y, caches) parameters = update_parameters(parameters, grads, learning_rate) if i % 100 == 0: print("Cost after iteration {}: {}".format(i, cost)) return parameters # 使用示例 parameters = train_model(X_train, Y_train, learning_rate=0.01, num_iterations=1000) ``` 这是一个简单的反向传播算法示例代码,其中的sigmoid()、softmax()、sigmoid_derivative()和compute_cost()函数需要根据具体情况自行实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值