神经网路反向传播算法

神经网路反向传播算法

以下是一个简单的反向传播算法的神经网络的实现:

假设我们有一个三层的神经网络,输入层有3个神经元,隐层有4个神经元,输出层有2个神经元。我们使用sigmoid函数作为激活函数。

  1. 初始化权重和偏置

我们需要随机初始化权重和偏置。假设输入层到隐层的权重矩阵为W1,大小为4x3,隐层到输出层的权重矩阵为W2,大小为2x4。偏置向量b1和b2都是大小为4x1和2x1的列向量。

import numpy as np

# 随机初始化权重和偏置
W1 = np.random.randn(4, 3)
W2 = np.random.randn(2, 4)
b1 = np.zeros((4, 1))
b2 = np.zeros((2, 1))
  1. 前向传播

对于一个输入样本x,我们需要执行前向传播来计算输出层的预测值。假设输入样本为大小为3x1的列向量。我们将它传递给隐藏层和输出层,并使用sigmoid函数作为激活函数。

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

def forward_propagation(x, W1, W2, b1, b2):
    # 隐藏层输入
    z1 = np.dot(W1, x) + b1
    # 隐藏层输出
    a1 = sigmoid(z1)
    # 输出层输入
    z2 = np.dot(W2, a1) + b2
    # 输出层输出
    a2 = sigmoid(z2)
    return a1, a2

x = np.random.randn(3, 1)
a1, a2 = forward_propagation(x, W1, W2, b1, b2)
  1. 计算误差

我们需要计算预测值和实际值之间的误差。假设我们有一个大小为2x1的目标向量y。

y = np.array([[0.5], [0.8]])

我们可以使用平方误差函数来计算误差。

def compute_cost(a2, y):
    m = y.shape[1]
    cost = np.sum(np.square(a2 - y)) / (2 * m)
    return cost

cost = compute_cost(a2, y)
  1. 反向传播

现在我们可以执行反向传播来计算梯度,并更新权重和偏置。我们需要计算输出层的误差项d2和隐藏层的误差项d1。对于输出层的误差项d2,我们可以使用下面的公式:

d2 = (a2 - y) * sigmoid(z2) * (1 - sigmoid(z2))

对于隐藏层的误差项d1,我们可以使用下面的公式:

d1 = np.dot(W2.T, d2) * sigmoid(z1) * (1 - sigmoid(z1))

现在我们可以计算权重和偏置的梯度了。

def backward_propagation(x, y, a1, a2, W1, W2, b1, b2):
    m = y.shape[1]
    # 计算输出层误差项
    d2 = (a2 - y) * sigmoid(z2) * (1 - sigmoid(z2))
    # 计算隐藏层误差项
    d1 = np.dot(W2.T, d2) * sigmoid(z1) * (1 - sigmoid(z1))
    # 计算权重和偏置的梯度
    dW2 = np.dot(d2, a1.T) / m
    db2 = np.sum(d2, axis=1, keepdims=True) / m
    dW1 = np.dot(d1, x.T) / m
    db1 = np.sum(d1, axis=1, keepdims=True) / m
    return dW1, db1, dW2, db2

dW1, db1, dW2, db2 = backward_propagation(x, y, a1, a2, W1, W2, b1, b2)
  1. 更新权重和偏置

现在我们可以使用梯度下降来更新权重和偏置。

def update_parameters(W1, b1, W2, b2, dW1, db1, dW2, db2, learning_rate):
    # 更新权重和偏置
    W1 = W1 - learning_rate * dW1
    b1 = b1 - learning_rate * db1
    W2 = W2 - learning_rate * dW2
    b2 = b2 - learning_rate * db2
    return W1, b1, W2, b2

learning_rate = 0.01
W1, b1, W2, b2 = update_parameters(W1, b1, W2, b2, dW1, db1, dW2, db2, learning_rate)

以上就是一个简单的反向传播算法的神经网络的实现。

m = y.shape[1]是干嘛的

m是代表样本数的参数,y的shape是(2, 1),其中2表示有2个输出,1表示只有1个样本。因此,m=y.shape[1]就是将样本数赋值给m。在计算代价函数和梯度时,需要对每个样本的误差进行平均,所以需要知道样本数m。

为什么对于输出层的误差项d2= (a2 - y) * sigmoid(z2) * (1 - sigmoid(z2))

对于输出层的误差项 d 2 d_2 d2,我们可以根据链式法则写出:
d 2 = ∂ J ∂ z 2 = ∂ J ∂ a 2 ⋅ ∂ a 2 ∂ z 2 d_2 = \frac{\partial J}{\partial z_2} = \frac{\partial J}{\partial a_2} \cdot \frac{\partial a_2}{\partial z_2} d2=z2J=a2Jz2a2
其中, J J J是代价函数, a 2 a_2 a2是输出层的输出结果, z 2 z_2 z2是经过输出层的加权输入。根据神经网络的定义,我们知道:
a 2 = σ ( z 2 ) a_2 = \sigma(z_2) a2=σ(z2)
其中, σ \sigma σ是sigmoid函数,其表达式为:
σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1+e^{-x}} σ(x)=1+ex1
对sigmoid函数求导可得:
∂ σ ( x ) ∂ x = σ ( x ) ⋅ ( 1 − σ ( x ) ) \frac{\partial \sigma(x)}{\partial x} = \sigma(x) \cdot (1-\sigma(x)) xσ(x)=σ(x)(1σ(x))
将上述式子代入 d 2 d_2 d2的计算式中,可得:
d 2 = ∂ J ∂ a 2 ⋅ σ ( z 2 ) ⋅ ( 1 − σ ( z 2 ) ) = ( a 2 − y ) ⋅ σ ( z 2 ) ⋅ ( 1 − σ ( z 2 ) ) d_2 = \frac{\partial J}{\partial a_2} \cdot \sigma(z_2) \cdot (1-\sigma(z_2)) = (a_2 - y) \cdot \sigma(z_2) \cdot (1-\sigma(z_2)) d2=a2Jσ(z2)(1σ(z2))=(a2y)σ(z2)(1σ(z2))
其中, y y y是样本的真实输出,即目标值。所以,对于输出层的误差项 d 2 d_2 d2,我们可以通过求解代价函数关于输出层输出结果 a 2 a_2 a2的偏导数,再乘以sigmoid函数的导数得到。

为什么隐藏层的误差项d1 = np.dot(W2.T, d2) * sigmoid(z1) * (1 - sigmoid(z1))

对于隐藏层的误差项 d 1 d_1 d1,我们同样可以根据链式法则写出:
d 1 = ∂ J ∂ z 1 = ∂ J ∂ a 1 ⋅ ∂ a 1 ∂ z 1 d_1 = \frac{\partial J}{\partial z_1} = \frac{\partial J}{\partial a_1} \cdot \frac{\partial a_1}{\partial z_1} d1=z1J=a1Jz1a1
其中, a 1 a_1 a1是隐藏层的输出结果, z 1 z_1 z1是经过隐藏层的加权输入, J J J是代价函数。根据神经网络的定义,我们知道:
a 1 = σ ( z 1 ) a_1 = \sigma(z_1) a1=σ(z1)
对sigmoid函数求导可得:
∂ σ ( x ) ∂ x = σ ( x ) ⋅ ( 1 − σ ( x ) ) \frac{\partial \sigma(x)}{\partial x} = \sigma(x) \cdot (1-\sigma(x)) xσ(x)=σ(x)(1σ(x))
将上述式子代入 d 1 d_1 d1的计算式中,可得:
d 1 = ∂ J ∂ a 1 ⋅ σ ( z 1 ) ⋅ ( 1 − σ ( z 1 ) ) = ( ∑ i = 1 m W 2 , i ⋅ d 2 , i ) ⋅ σ ( z 1 ) ⋅ ( 1 − σ ( z 1 ) ) d_1 = \frac{\partial J}{\partial a_1} \cdot \sigma(z_1) \cdot (1-\sigma(z_1)) = \left(\sum_{i=1}^{m} W_{2,i} \cdot d_{2,i}\right) \cdot \sigma(z_1) \cdot (1-\sigma(z_1)) d1=a1Jσ(z1)(1σ(z1))=(i=1mW2,id2,i)σ(z1)(1σ(z1))
其中, W 2 , i W_{2,i} W2,i表示第二层权重矩阵的第 i i i列, d 2 , i d_{2,i} d2,i表示第 i i i个样本在第二层的误差项。因此,我们可以用矩阵乘法 np.dot ( W 2 . T , d 2 ) \text{np.dot}(W_2.T, d_2) np.dot(W2.T,d2)来计算 ∑ i = 1 m W 2 , i ⋅ d 2 , i \sum_{i=1}^{m} W_{2,i} \cdot d_{2,i} i=1mW2,id2,i。所以,对于隐藏层的误差项 d 1 d_1 d1,我们可以通过求解代价函数关于隐藏层输出结果 a 1 a_1 a1的偏导数,再乘以sigmoid函数的导数得到。

如何计算权重和偏置的梯度

权重和偏置的梯度可以通过反向传播算法计算得到。具体计算方法如下:

  1. 首先,根据输入样本和当前的权重和偏置,前向计算出每一层的加权输入 z z z和输出 a a a

  2. 然后,计算输出层的误差项 d 2 d_2 d2,即 d 2 = ( a 2 − y ) ⋅ σ ( z 2 ) ⋅ ( 1 − σ ( z 2 ) ) d_2 = (a_2 - y) \cdot \sigma(z_2) \cdot (1-\sigma(z_2)) d2=(a2y)σ(z2)(1σ(z2)),其中, y y y是样本的真实输出。

  3. 接着,计算隐藏层的误差项 d 1 d_1 d1,即 d 1 = np.dot ( W 2 . T , d 2 ) ⋅ σ ( z 1 ) ⋅ ( 1 − σ ( z 1 ) ) d_1 = \text{np.dot}(W_2.T, d_2) \cdot \sigma(z_1) \cdot (1-\sigma(z_1)) d1=np.dot(W2.T,d2)σ(z1)(1σ(z1)),其中, W 2 W_2 W2是第二层权重矩阵。

  4. 然后,根据误差项 d d d和输出 a a a,计算每一层的偏置梯度 ∂ J ∂ b \frac{\partial J}{\partial b} bJ,其中, J J J是代价函数, ∂ J ∂ b \frac{\partial J}{\partial b} bJ表示代价函数关于偏置 b b b的偏导数。具体计算公式为: ∂ J ∂ b = d \frac{\partial J}{\partial b} = d bJ=d

  5. 最后,根据误差项 d d d和输入 x x x,计算每一层的权重梯度 ∂ J ∂ W \frac{\partial J}{\partial W} WJ,其中, ∂ J ∂ W \frac{\partial J}{\partial W} WJ表示代价函数关于权重 W W W的偏导数。具体计算公式为: ∂ J ∂ W = x T ⋅ d \frac{\partial J}{\partial W} = x^T \cdot d WJ=xTd

以上计算步骤可以通过循环实现,从输出层到输入层依次计算每一层的梯度。最终得到的权重和偏置梯度可以用来更新模型的参数,从而使代价函数最小化。

为什么权重和偏置的梯度

dW2 = np.dot(d2, a1.T) / m
db2 = np.sum(d2, axis=1, keepdims=True) / m
dW1 = np.dot(d1, x.T) / m
db1 = np.sum(d1, axis=1, keepdims=True) / m

这里的权重和偏置的梯度是通过反向传播算法计算得到的。在训练神经网络时,我们需要通过不断调整权重和偏置的值来最小化代价函数。而梯度是代价函数对参数的偏导数,它表示了在当前点上函数增加最快的方向。因此,我们可以利用梯度信息来调整参数,使它们朝着更小的代价函数方向移动。

具体地,在反向传播算法中,我们首先计算了每一层的误差项 d d d,然后根据误差项和输入 x x x或输出 a a a计算了每一层的权重和偏置梯度。这些梯度告诉我们,如果我们想要减小代价函数,应该如何调整权重和偏置的值。例如,如果 d W 2 dW2 dW2是正的,那么我们需要减小 W 2 W2 W2的值,从而使代价函数减小。同样,如果 d b 2 db2 db2是正的,我们需要减小 b 2 b2 b2的值。通过这种方式,我们可以利用反向传播算法计算出梯度,并使用梯度下降等优化算法更新模型的参数,从而训练出更好的神经网络模型。

dW2 = np.dot(d2, a1.T) / m中,a1.T什么意思

在神经网络中, a ( l ) a^{(l)} a(l)表示第 l l l层的输出, z ( l ) z^{(l)} z(l)表示第 l l l层的加权输入。在反向传播算法中,我们需要计算每一层的误差项 d ( l ) d^{(l)} d(l),其中 d ( l ) d^{(l)} d(l)表示第 l l l层的误差项。

在计算第二层的权重梯度 d W 2 dW2 dW2时,我们需要用到第一层的输出 a ( 1 ) a^{(1)} a(1)。而 a ( 1 ) a^{(1)} a(1)是一个行向量,需要转置成列向量才能与误差项 d ( 2 ) d^{(2)} d(2)相乘。因此, a ( 1 ) T a^{(1)T} a(1)T表示将 a ( 1 ) a^{(1)} a(1)转置成列向量的结果,即第一层输出的转置。

具体地, a ( 1 ) T a^{(1)T} a(1)T的形状是 ( n ( 1 ) , 1 ) (n^{(1)}, 1) (n(1),1),其中 n ( 1 ) n^{(1)} n(1)表示第一层的神经元数量。 d ( 2 ) d^{(2)} d(2)的形状是 ( n ( 2 ) , m ) (n^{(2)}, m) (n(2),m),其中 n ( 2 ) n^{(2)} n(2)表示第二层的神经元数量, m m m表示训练样本数量。因此, d ( 2 ) , a ( 1 ) T ˙ \dot{d^{(2)}, a^{(1)T}} d(2),a(1)T˙的形状是 ( n ( 2 ) , n ( 1 ) ) (n^{(2)}, n^{(1)}) (n(2),n(1)),即第二层权重矩阵的形状,表示每个神经元与前一层的所有神经元之间的权重。

通过上述计算,我们得到了第二层权重的梯度 d W 2 dW2 dW2,它的形状与权重矩阵 W 2 W2 W2相同。

db2 = np.sum(d2, axis=1, keepdims=True) / m中,axis=1、keepdims=True什么意思

在神经网络反向传播算法中,计算偏置 b b b的梯度时,需要将误差项 d d d沿着样本维度求和,然后再除以样本数量 m m m,即 d B = 1 m ∑ i = 1 m d ( i ) dB = \frac{1}{m}\sum_{i=1}^{m}d^{(i)} dB=m1i=1md(i),其中 d ( i ) d^{(i)} d(i)是第 i i i个样本的误差项。

在使用Numpy进行计算时,可以使用np.sum函数对误差项沿着样本维度进行求和。axis=1表示沿着第二个维度(即列维度)进行求和,从而得到每个神经元的误差项和。keepdims=True表示保持结果的维度不变,即保持二维数组的形状。这样得到的结果的形状是 ( n ( l ) , 1 ) (n^{(l)}, 1) (n(l),1),即每个神经元的误差项和。

然后再将这个结果除以样本数量 m m m,即可得到偏置 b b b的梯度。最终得到的 d B dB dB的形状与偏置 b b b的形状相同,即 ( n ( l ) , 1 ) (n^{(l)}, 1) (n(l),1),其中 n ( l ) n^{(l)} n(l)表示第 l l l层的神经元数量。

db2 = np.sum(d2, axis=1, keepdims=True) / m中,为什么沿着第二个维度(即列维度)进行求和

在神经网络中,每个神经元都对应一个偏置 b b b。对于第 l l l层的第 j j j个神经元,它的偏置 b j ( l ) b_j^{(l)} bj(l)对应的是第 l l l层的所有神经元与第 l + 1 l+1 l+1层的第 j j j个神经元之间的连接,即权重 W j , : ( l ) W_{j,:}^{(l)} Wj,:(l)

在计算偏置 b j ( l ) b_j^{(l)} bj(l)的梯度时,需要将所有样本中第 l + 1 l+1 l+1层的第 j j j个神经元的误差项 d j ( l + 1 ) d_j^{(l+1)} dj(l+1)相加,从而得到 d B j ( l ) dB_j^{(l)} dBj(l)。因此,需要沿着样本维度(即第二个维度)对误差项 d d d进行求和,从而得到每个神经元的误差项和。

具体地,假设误差项 d ( l + 1 ) d^{(l+1)} d(l+1)的形状是 ( n ( l + 1 ) , m ) (n^{(l+1)}, m) (n(l+1),m),其中 n ( l + 1 ) n^{(l+1)} n(l+1)表示第 l + 1 l+1 l+1层的神经元数量, m m m表示样本数量。那么,沿着第二个维度求和后得到的结果的形状是 ( n ( l + 1 ) , 1 ) (n^{(l+1)}, 1) (n(l+1),1),即每个神经元的误差项和。最终再将这个结果除以样本数量 m m m,即可得到每个神经元的平均误差项,即偏置 b j ( l ) b_j^{(l)} bj(l)的梯度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值